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 }