1 module msgtrans.ee2e.crypto;
2 
3 import hunt.logging;
4 import deimos.openssl.ssl;
5 import deimos.openssl.rand;
6 import deimos.openssl.aes;
7 import deimos.openssl.evp;
8 import core.stdc..string;
9 
10 enum CRYPTO_CURVE_NID = NID_X9_62_prime256v1;
11 
12 enum  CRYPTO_EC_PUB_KEY_LEN = 65;
13 
14 enum  CRYPTO_EC_PRIV_KEY_LEN = 32;
15 
16 enum  CRYPTO_SALT_LEN = 32;
17 
18 enum  CRYPTO_ECDH_SHARED_KEY_LEN = 32;
19 
20 enum  CRYPTO_HMAC_SHA256 = 32;
21 
22 enum  CRYPTO_AES_KEY_LEN = 32;
23 
24 enum  CRYPTO_AES_IV_LEN = 12;
25 
26 enum  CRYPTO_AES_TAG_LEN = 16;
27 
28 enum  CRYPTO_ECDSA_SIG_s_LEN = 32;
29 
30 enum  CRYPTO_ECDSA_SIG_r_LEN = 32;
31 
32 enum  CRYPTO_ECDSA_SIG_LEN = CRYPTO_ECDSA_SIG_s_LEN + CRYPTO_ECDSA_SIG_r_LEN;
33 
34 enum  CRYPTO_VERSION = 1;
35 
36 enum  CRYPTO_KEY_INFO = "ENCRYPTION";
37 
38 
39 class ownkey_s
40 {
41     ubyte[CRYPTO_EC_PUB_KEY_LEN] ec_pub_key;
42     ubyte[CRYPTO_EC_PRIV_KEY_LEN] ec_priv_key;
43     ubyte[CRYPTO_SALT_LEN] salt;
44 }
45 
46 class peerkey_s
47 {
48     ubyte[CRYPTO_EC_PUB_KEY_LEN] ec_pub_key;
49     ubyte[CRYPTO_AES_KEY_LEN] aes_key;
50     ubyte[CRYPTO_SALT_LEN] salt;
51 }
52 
53 bool rand_salt(ubyte[] salt, int bytes)
54 {
55   return (RAND_bytes(salt.ptr, bytes)==1);
56 }
57 
58 bool generate_ecdh_keys(out ubyte[CRYPTO_EC_PUB_KEY_LEN] ecdh_public_key, out ubyte[CRYPTO_EC_PRIV_KEY_LEN] ecdh_private_key)
59 {
60     size_t len = 0;
61     bool ret = false;
62 
63     const(EC_KEY) *ecdh = EC_KEY_new();
64     const(EC_POINT) *point = null;
65     const(EC_GROUP) *group = null;
66 
67   //Generate Public
68     ecdh = EC_KEY_new_by_curve_name(CRYPTO_CURVE_NID);
69 
70     group = EC_KEY_get0_group(ecdh);
71 
72   /* get x y */
73     if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field)
74     {
75       if (!EC_KEY_generate_key(cast(EC_KEY*)ecdh))
76       {
77         logError("Ecdh NIST P-256 generate error.");
78         goto err;
79       }
80 
81       point = EC_KEY_get0_public_key(ecdh);
82 
83       len = EC_POINT_point2oct(group, point, point_conversion_form_t.POINT_CONVERSION_UNCOMPRESSED, ecdh_public_key.ptr, cast(size_t)CRYPTO_EC_PUB_KEY_LEN , null);
84       if (len != CRYPTO_EC_PUB_KEY_LEN)
85       {
86         logError("Ecdh NIST P-256 public key get error.");
87         goto err;
88       }
89 
90       len = BN_bn2bin(EC_KEY_get0_private_key(ecdh), ecdh_private_key.ptr);
91       if (len != CRYPTO_EC_PRIV_KEY_LEN)
92       {
93         logError("Ecdh NIST P-256 private key get error.");
94         goto err;
95       }
96 
97       ret = true;
98     }
99 
100     err:
101     EC_KEY_free(cast(EC_KEY*)ecdh);
102     return ret;
103 }
104 
105 bool calc_ecdh_shared_key(const ubyte[CRYPTO_EC_PUB_KEY_LEN] ecdh1_public_key,
106                           const ubyte[CRYPTO_EC_PRIV_KEY_LEN] ecdh1_private_key,
107                           const ubyte[CRYPTO_EC_PUB_KEY_LEN] ecdh2_public_key,
108                           out ubyte[CRYPTO_ECDH_SHARED_KEY_LEN] ecdh_shared_key)
109 {
110     int len = 0;
111     int ret = false;
112     EC_KEY *ecdh = EC_KEY_new();
113     const(EC_GROUP) *group = null;
114     BIGNUM   *priv = null;
115     EC_POINT *p_ecdh1_public = null;
116     EC_POINT *p_ecdh2_public = null;
117 
118     ecdh = EC_KEY_new_by_curve_name(CRYPTO_CURVE_NID);
119     if (ecdh is null)
120     {
121       logError("Ecdh key by curve name error.");
122       goto err;
123     }
124 
125     group = EC_KEY_get0_group(ecdh);
126 
127     if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field)
128     {
129       /* 1==> Set ecdh1's public and privat key. */
130       p_ecdh1_public = EC_POINT_new(group);
131       if (p_ecdh1_public is null)
132       {
133         logError("EC_POINT new error.");
134         goto err;
135       }
136 
137       ret = EC_POINT_oct2point(group, p_ecdh1_public, ecdh1_public_key.ptr, CRYPTO_EC_PUB_KEY_LEN, null);
138       if (!ret)
139       {
140         logError("EC_POINT oct2point error.");
141         goto err;
142       }
143 
144       if (!EC_KEY_set_public_key(ecdh, p_ecdh1_public))
145       {
146         logError("Ecdh set public key error.");
147       }
148 
149       priv = BN_bin2bn(ecdh1_private_key.ptr, CRYPTO_EC_PRIV_KEY_LEN, null);
150       if (!EC_KEY_set_private_key(ecdh, priv))
151       {
152         logError("set private error \n");
153       }
154       /*-------------*/
155 
156       /* 2==> Set ecdh2's public key */
157       p_ecdh2_public = EC_POINT_new(group);
158       if (p_ecdh2_public is null)
159       {
160         logError("EC_POINT new error.");
161         goto err;
162       }
163 
164       ret = EC_POINT_oct2point(group, p_ecdh2_public, ecdh2_public_key.ptr, CRYPTO_EC_PUB_KEY_LEN, null);
165       if (!ret)
166       {
167         logError("EC_POINT oct2point error.");
168         goto err;
169       }
170 
171       if (!EC_KEY_set_public_key(ecdh, p_ecdh2_public))
172       {
173         logError("Ecdh set public key error.");
174         goto err;
175       }
176       /*------------*/
177 
178       /* 3==> Calculate the shared key of ecdh1 and ecdh2 */
179       len = ECDH_compute_key(ecdh_shared_key.ptr, CRYPTO_ECDH_SHARED_KEY_LEN, p_ecdh2_public, ecdh, null);
180       if (len != CRYPTO_ECDH_SHARED_KEY_LEN)
181       {
182         logError("Ecdh compute key error.");
183         goto err;
184       }
185 
186       ret = 0;
187     }
188 
189     err:
190     if (priv)
191       BN_free(priv);
192     if (ecdh)
193       EC_KEY_free(ecdh);
194     if (p_ecdh1_public)
195       EC_POINT_free(p_ecdh1_public);
196     if (p_ecdh2_public)
197       EC_POINT_free(p_ecdh2_public);
198 
199     return (ret==0);
200 }
201 
202 bool ecdsa_sign(const ubyte[CRYPTO_EC_PRIV_KEY_LEN] ec_private_key, ubyte *hash, ubyte hash_len, ubyte[CRYPTO_ECDSA_SIG_LEN] sign)
203 {
204     int len = 0;
205     int ret = false;
206     EC_KEY *eckey = EC_KEY_new();
207     BIGNUM   *priv = null;
208     const (EC_GROUP) *group = null;
209     EC_POINT *p_ec_point = null;
210 
211     eckey = EC_KEY_new_by_curve_name(CRYPTO_CURVE_NID);
212     if (eckey is null)
213     {
214       logError("Ecdh key by curve name error.");
215       goto err;
216     }
217 
218     group = EC_KEY_get0_group(eckey);
219 
220     if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field)
221     {
222         priv = BN_bin2bn(ec_private_key.ptr,CRYPTO_EC_PRIV_KEY_LEN, null);
223         if (!EC_KEY_set_private_key(eckey, priv))
224         {
225           logError("set private error \n");
226         }
227 
228         ECDSA_SIG *signature = ECDSA_do_sign(hash, hash_len, eckey);
229         if (signature is null)
230         {
231           logError("ECDSA_do_sign error.");
232           goto err;
233         }
234 
235         ret = 0;
236 
237         BN_bn2bin(signature.s, sign.ptr);
238         BN_bn2bin(signature.r, sign.ptr + CRYPTO_ECDSA_SIG_s_LEN);
239 
240         ECDSA_SIG_free(signature);
241     }
242 err:
243 if (priv)
244   BN_free(priv);
245     if (eckey)
246       EC_KEY_free(eckey);
247 
248     return (ret == 0);
249 }
250 
251 
252 bool hmac_sha256(ubyte[] hmac, const ubyte[] key, uint key_len, const ubyte[] data, uint data_len)
253 {
254     uint resultlen = 0;
255     HMAC(EVP_sha256(), key.ptr, key_len, data.ptr, data_len, hmac.ptr, &resultlen);
256     logInfo("hmac_sha256 .............................. %s",hmac);
257     if (resultlen != CRYPTO_HMAC_SHA256)
258     {
259       logError("HMAC SHA-256 error.");
260       return false;
261     }
262 
263     return true;
264 }
265 
266 bool bytes_xor(const ubyte[] data1, int data1_len, const ubyte[] data2, int data2_len, ubyte[] m_out)
267 {
268     int i = 0;
269 
270     if ((data1_len != data2_len) || (m_out is null))
271         return false;
272 
273     for (i = 0; i < data1_len; i ++)
274     {
275        m_out[i] = data1[i] ^ data2[i];
276     }
277 
278     return true;
279 }
280 
281 bool generate_hkdf_bytes(const ubyte[CRYPTO_ECDH_SHARED_KEY_LEN] ecdh_shared_key,const ubyte[CRYPTO_SALT_LEN] salt, const ubyte[] info, int info_len, ubyte[] m_out)
282 {
283     const EVP_MD *md = EVP_sha256();
284     ubyte[CRYPTO_ECDH_SHARED_KEY_LEN] prk ;
285     ubyte[CRYPTO_ECDH_SHARED_KEY_LEN] T ;
286     ubyte[CRYPTO_AES_KEY_LEN] tmp;
287     uint outlen = CRYPTO_ECDH_SHARED_KEY_LEN;
288     int i, ret, tmplen;
289     ubyte *p;
290     /*extract is a simple HMAC...
291       Note:salt should be treated as hmac key and ikm should be treated as data
292      */
293     if (!HMAC(md, salt.ptr, CRYPTO_SALT_LEN, ecdh_shared_key.ptr, CRYPTO_ECDH_SHARED_KEY_LEN, prk.ptr, &outlen))
294       return false;
295     ret = CRYPTO_AES_KEY_LEN/CRYPTO_ECDH_SHARED_KEY_LEN + !!(CRYPTO_AES_KEY_LEN%CRYPTO_ECDH_SHARED_KEY_LEN);
296 
297     tmplen = outlen;
298     for (i = 0; i < ret; i++)
299     {
300         p = tmp.ptr;
301 
302         /*T(0) = empty string (zero length)*/
303         if (i != 0)
304         {
305           memcpy(p, T.ptr, CRYPTO_ECDH_SHARED_KEY_LEN);
306           p += CRYPTO_ECDH_SHARED_KEY_LEN;
307         }
308 
309         memcpy(p, info.ptr, info_len);
310         p += info_len;
311         *p++ = cast(ubyte)(i + 1);
312 
313         HMAC(md, prk.ptr, CRYPTO_ECDH_SHARED_KEY_LEN, tmp.ptr, cast(int)(p - tmp.ptr), T.ptr, &outlen);
314         memcpy(m_out.ptr + i*CRYPTO_ECDH_SHARED_KEY_LEN, T.ptr, tmplen < CRYPTO_ECDH_SHARED_KEY_LEN ? tmplen:CRYPTO_ECDH_SHARED_KEY_LEN);
315         tmplen -= CRYPTO_ECDH_SHARED_KEY_LEN;
316     }
317 
318     return true;
319 }
320 
321 
322 bool aes_encrypt(const ubyte *plaintext, int plaintext_len, const ubyte *key, const ubyte *iv, ubyte *ciphertext, ubyte *tag)
323 {
324     EVP_CIPHER_CTX *ctx;
325 
326     int len;
327 
328     int ciphertext_len;
329 
330     int ret = -1;
331 
332 
333     /* Create and initialise the context */
334     ctx = EVP_CIPHER_CTX_new();
335     if (ctx is null)
336     {
337       goto err;
338     }
339 
340 
341     /* Initialise the encryption operation. */
342     if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), null, null, null))
343       goto err;
344 
345     /* Set IV length if default 12 bytes (96 bits) is not appropriate */
346     //if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, null))
347     //   goto err;
348 
349     /* Initialise key and IV */
350     if(1 != EVP_EncryptInit_ex(ctx, null, null, key, iv))  goto err;
351 
352     /* Provide any AAD data. This can be called zero or more times as
353        * required
354        */
355     //if(1 != EVP_EncryptUpdate(ctx, null, &len, aad, aad_len))
356     //   handleErrors();
357 
358     /* Provide the message to be encrypted, and obtain the encrypted output.
359        * EVP_EncryptUpdate can be called multiple times if necessary
360        */
361     if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
362     {
363       goto err;
364     }
365     ciphertext_len = len;
366 
367     /* Finalise the encryption. Normally ciphertext bytes may be written at
368        * this stage, but this does not occur in GCM mode
369        */
370     if(1 != EVP_EncryptFinal_ex(ctx, ciphertext, &len))  goto err;
371     //ciphertext_len += len;
372 
373     /* Get the tag */
374     if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
375       goto err;
376 
377     err:
378     /* Clean up */
379     EVP_CIPHER_CTX_free(ctx);
380 
381     return (ciphertext_len == plaintext_len);
382 }
383 
384 bool aes_decrypt(const ubyte *ciphertext, int ciphertext_len, const ubyte *tag, const ubyte *key, const ubyte *iv, ubyte *plaintext)
385 {
386     EVP_CIPHER_CTX *ctx;
387     int len;
388     int plaintext_len;
389     int ret = -1;
390 
391     /* Create and initialise the context */
392     ctx = EVP_CIPHER_CTX_new();
393     if(ctx is null)
394     {
395       goto err;
396     }
397 
398     /* Initialise the decryption operation. */
399     if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), null, null, null))
400         goto err;
401 
402     /* Set IV length. Not necessary if this is 12 bytes (96 bits) */
403     //if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, null))
404     //    goto err;
405 
406     /* Initialise key and IV */
407     if(!EVP_DecryptInit_ex(ctx, null, null, key, iv)) goto err;
408 
409     /* Provide any AAD data. This can be called zero or more times as
410      * required
411      */
412     //if(!EVP_DecryptUpdate(ctx, null, &len, aad, aad_len))
413     //    handleErrors();
414 
415     /* Provide the message to be decrypted, and obtain the plaintext output.
416      * EVP_DecryptUpdate can be called multiple times if necessary
417      */
418     if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
419         goto err;
420     plaintext_len = len;
421 
422     /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
423     if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, cast(void*)tag))
424         goto err;
425 
426     /* Finalise the decryption. A positive return value indicates success,
427      * anything else is a failure - the plaintext is not trustworthy.
428      */
429     ret = EVP_DecryptFinal_ex(ctx, plaintext, &len);
430     //plaintext_len = len;
431 
432     //CRYPTO_DBG("ret:%d", ret);
433 err:
434     /* Clean up */
435     EVP_CIPHER_CTX_free(ctx);
436 
437     if(ret > 0)
438     {
439         /* Success */
440         return (plaintext_len == ciphertext_len);
441     }
442     else
443     {
444         /* Verify failed */
445         return false;
446     }
447 }