pseudonym *polypseud_specialize(const polypseud_ctx *ctx, pseudonym *pseud, char *spid, unsigned char *Dp, int Dp_len, unsigned char *Dk, int Dk_len) { unsigned int kdf_dp_len; unsigned char *kdf_dp_arr = KDF(Dp, Dp_len, (unsigned char *)spid, strlen(spid), &kdf_dp_len); if(kdf_dp_arr == NULL) return NULL; BIGNUM *kdf_dp = BN_bin2bn(kdf_dp_arr, kdf_dp_len, NULL); unsigned int kdf_dk_len; unsigned char *kdf_dk_arr = KDF(Dk, Dk_len, (unsigned char *)spid, strlen(spid), &kdf_dk_len); if(kdf_dk_arr == NULL) return NULL; BIGNUM *kdf_dk = BN_bin2bn(kdf_dk_arr, kdf_dk_len, NULL); BIGNUM *kdf_dk_inv = BN_mod_inverse(NULL, kdf_dk, ctx->q, ctx->bn_ctx); EC_POINT_mul(ctx->ec_group, pseud->a, NULL, pseud->a, kdf_dp, ctx->bn_ctx); EC_POINT_mul(ctx->ec_group, pseud->b, NULL, pseud->b, kdf_dp, ctx->bn_ctx); EC_POINT_mul(ctx->ec_group, pseud->a, NULL, pseud->a, kdf_dk, ctx->bn_ctx); EC_POINT_mul(ctx->ec_group, pseud->c, NULL, pseud->c, kdf_dk_inv, ctx->bn_ctx); if(polypseud_randomize(ctx, pseud) == NULL) return NULL; BN_free(kdf_dk_inv); BN_free(kdf_dk); free(kdf_dk_arr); BN_free(kdf_dp); free(kdf_dp_arr); return pseud; }
int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, const EC_KEY *eckey, void *(*KDF) (const void *in, size_t inlen, void *out, size_t *outlen)) { unsigned char *sec = NULL; size_t seclen; if (eckey->meth->compute_key == NULL) { ECerr(EC_F_ECDH_COMPUTE_KEY, EC_R_OPERATION_NOT_SUPPORTED); return 0; } if (outlen > INT_MAX) { ECerr(EC_F_ECDH_COMPUTE_KEY, EC_R_INVALID_OUTPUT_LENGTH); return 0; } if (!eckey->meth->compute_key(&sec, &seclen, pub_key, eckey)) return 0; if (KDF != NULL) { KDF(sec, seclen, out, &outlen); } else { if (outlen > seclen) outlen = seclen; memcpy(out, sec, outlen); } OPENSSL_clear_free(sec, seclen); return outlen; }
int ecdh_compute_key_point(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen)) { BN_CTX *ctx = NULL; EC_POINT *tmp=NULL; const BIGNUM *priv_key; const EC_GROUP* group; int ret= -1; size_t buflen; unsigned char *buf=NULL; check((outlen < INT_MAX), "out of memory"); /* sort of, anyway */ if ((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); priv_key = EC_KEY_get0_private_key(ecdh); check(priv_key, "No pivate key"); group = EC_KEY_get0_group(ecdh); tmp = EC_POINT_new(group); check(tmp, "Out of memory"); check((EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)), "Arithmetic error"); buflen = EC_POINT_point2oct(group, tmp, EC_KEY_get_conv_form(ecdh), NULL, 0, ctx); check((buflen != 0), "Failed to convert point to hex"); buf = OPENSSL_malloc(buflen); check(buf, "Out of memory"); check((buflen == EC_POINT_point2oct(group, tmp, EC_KEY_get_conv_form(ecdh), buf, buflen, ctx)), "Failed to convert point to hex"); if (KDF != 0) { check((KDF(buf, buflen, out, &outlen) != NULL), "Key derivation function failed"); ret = outlen; } else { /* no KDF, just copy as much as we can */ if (outlen > buflen) outlen = buflen; memcpy(out, buf, outlen); ret = outlen; } err: if (tmp) EC_POINT_free(tmp); if (ctx) BN_CTX_end(ctx); if (ctx) BN_CTX_free(ctx); if (buf) OPENSSL_free(buf); return(ret); }
/** * ECDH key derivation method (replaces ossl_ecdh_compute_key) * Implementation for OpenSSL 1.1.0-pre3 and earlier * * @param out derived key * @param outlen derived key length * @param peer_point public key point * @param ecdh private key * @param KCF key derivation function * @return the length of the derived key or -1 if an error occurred */ static int pkcs11_ec_ckey(void *out, size_t outlen, const EC_POINT *peer_point, const EC_KEY *ecdh, void *(*KDF)(const void *, size_t, void *, size_t *)) { PKCS11_KEY *key; CK_ECDH1_DERIVE_PARAMS *parms; unsigned char *buf = NULL; size_t buflen; int rv; #if OPENSSL_VERSION_NUMBER >= 0x10100000L key = (PKCS11_KEY *)EC_KEY_get_ex_data(ecdh, ec_ex_index); #else key = (PKCS11_KEY *)ECDSA_get_ex_data((EC_KEY *)ecdh, ec_ex_index); #endif if (key == NULL) /* The private key is not handled by PKCS#11 */ return ossl_ecdh_compute_key(out, outlen, peer_point, ecdh, KDF); /* TODO: Add an atfork check */ /* both peer and ecdh use same group parameters */ parms = pkcs11_ecdh_params_alloc(EC_KEY_get0_group(ecdh), peer_point); if (parms == NULL) return -1; rv = pkcs11_ecdh_derive(&buf, &buflen, CKM_ECDH1_DERIVE, parms, NULL, key); pkcs11_ecdh_params_free(parms); if (rv < 0) return -1; if (KDF) { if (KDF(buf, buflen, out, &outlen) == NULL) { OPENSSL_free(buf); return -1; } } else { if (outlen > buflen) outlen = buflen; memcpy(out, buf, outlen); } OPENSSL_free(buf); return outlen; }
void kdf_calc_ptk(struct ether_addr *auth_ea, struct ether_addr *sta_ea, uint8 *anonce, uint8* snonce, uint8 *pmk, uint pmk_len, uint8 *ptk, uint ptk_len) { uchar data[128], prf_buff[PRF_OUTBUF_LEN]; char prefix[] = "Pairwise key expansion"; uint data_len = 0; /* Create the the data portion: * the lesser of the EAs, followed by the greater of the EAs, * followed by the lesser of the the nonces, followed by the * greater of the nonces. */ bcopy(wpa_array_cmp(MIN_ARRAY, (uint8 *)auth_ea, (uint8 *)sta_ea, ETHER_ADDR_LEN), (char *)&data[data_len], ETHER_ADDR_LEN); data_len += ETHER_ADDR_LEN; bcopy(wpa_array_cmp(MAX_ARRAY, (uint8 *)auth_ea, (uint8 *)sta_ea, ETHER_ADDR_LEN), (char *)&data[data_len], ETHER_ADDR_LEN); data_len += ETHER_ADDR_LEN; bcopy(wpa_array_cmp(MIN_ARRAY, snonce, anonce, EAPOL_WPA_KEY_NONCE_LEN), (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN); data_len += EAPOL_WPA_KEY_NONCE_LEN; bcopy(wpa_array_cmp(MAX_ARRAY, snonce, anonce, EAPOL_WPA_KEY_NONCE_LEN), (char *)&data[data_len], EAPOL_WPA_KEY_NONCE_LEN); data_len += EAPOL_WPA_KEY_NONCE_LEN; /* generate the PTK */ ASSERT(strlen(prefix) + data_len + 1 <= PRF_MAX_I_D_LEN); KDF(pmk, (int)pmk_len, (uchar *)prefix, strlen(prefix), data, data_len, prf_buff, (int)ptk_len); bcopy(prf_buff, (char*)ptk, ptk_len); }
/** * ECDH key derivation method (replaces ossl_ecdh_compute_key) * Implementation for OpenSSL 1.1.0-pre3 and earlier * * @param out derived key * @param outlen derived key length * @param peer_point public key point * @param ecdh private key * @param KCF key derivation function * @return the length of the derived key or -1 if an error occurred */ static int pkcs11_ec_ckey(void *out, size_t outlen, const EC_POINT *peer_point, const EC_KEY *ecdh, void *(*KDF)(const void *, size_t, void *, size_t *)) { PKCS11_KEY *key; CK_ECDH1_DERIVE_PARAMS *parms; unsigned char *buf = NULL; size_t buflen; int rv; key = pkcs11_get_ex_data_ec(ecdh); if (check_key_fork(key) < 0) return ossl_ecdh_compute_key(out, outlen, peer_point, ecdh, KDF); /* both peer and ecdh use same group parameters */ parms = pkcs11_ecdh_params_alloc(EC_KEY_get0_group(ecdh), peer_point); if (parms == NULL) return -1; rv = pkcs11_ecdh_derive(&buf, &buflen, CKM_ECDH1_DERIVE, parms, NULL, key); pkcs11_ecdh_params_free(parms); if (rv < 0) return -1; if (KDF) { if (KDF(buf, buflen, out, &outlen) == NULL) { OPENSSL_free(buf); return -1; } } else { if (outlen > buflen) outlen = buflen; memcpy(out, buf, outlen); } OPENSSL_free(buf); return outlen; }
/* This implementation is based on the following primitives in the IEEE 1363 standard: * - ECKAS-DH1 * - ECSVDP-DH * Finally an optional KDF is applied. */ static int ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen)) { BN_CTX *ctx; EC_POINT *tmp=NULL; BIGNUM *x=NULL, *y=NULL; const BIGNUM *priv_key; const EC_GROUP* group; int ret= -1; size_t buflen, len; unsigned char *buf=NULL; if (outlen > INT_MAX) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); /* sort of, anyway */ return -1; } if ((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); priv_key = EC_KEY_get0_private_key(ecdh); if (priv_key == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_NO_PRIVATE_VALUE); goto err; } group = EC_KEY_get0_group(ecdh); if ((tmp=EC_POINT_new(group)) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, y, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } #ifndef OPENSSL_NO_EC2M else { if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } #endif buflen = (EC_GROUP_get_degree(group) + 7)/8; len = BN_num_bytes(x); if (len > buflen) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_INTERNAL_ERROR); goto err; } if ((buf = malloc(buflen)) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); goto err; } memset(buf, 0, buflen - len); if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_BN_LIB); goto err; } if (KDF != 0) { if (KDF(buf, buflen, out, &outlen) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_KDF_FAILED); goto err; } ret = outlen; } else { /* no KDF, just copy as much as we can */ if (outlen > buflen) outlen = buflen; memcpy(out, buf, outlen); ret = outlen; } err: EC_POINT_free(tmp); if (ctx) BN_CTX_end(ctx); BN_CTX_free(ctx); free(buf); return(ret); }
static int compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen)) { const EC_GROUP* group; int ret; group = EC_KEY_get0_group(ecdh); // only use our solution if the curve name is SECT163K1 if (EC_GROUP_get_curve_name(group) == NID_sect163k1) { const BIGNUM* rkey; BN_CTX *ctx; BIGNUM* x, *y; mm256_point_t p, q; mm_256 mkey; int r; ctx = BN_CTX_new(); BN_CTX_start(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); rkey = EC_KEY_get0_private_key(ecdh); memset(&mkey, 0, sizeof(mkey)); memcpy(&mkey, rkey->d, sizeof(rkey->d[0]) * rkey->top); ec2m_import_key(&mkey); r = EC_POINT_get_affine_coordinates_GF2m(group, pub_key, x, y, ctx); memset(&p, 0, sizeof(p)); memcpy(&p.x, x->d, sizeof(x->d[0]) * x->top); memcpy(&p.y, y->d, sizeof(y->d[0]) * y->top); p.z.iv[0] = 1; r = ec2m_private_operation(&p, &q); if (r < 0) { fprintf(stderr, "invalid result: %d\n", r); } int xlen = (163 + 7) / 8; if (KDF != 0) { if (KDF(&q.x, xlen, out, &outlen) == NULL) { return -1; } ret = outlen; } else { /* no KDF, just copy as much as we can */ if (outlen > xlen) outlen = xlen; memcpy(out, &q.x, outlen); ret = outlen; } BN_CTX_end(ctx); BN_CTX_free(ctx); } else { // use the default method const ECDH_METHOD* meth = ECDH_OpenSSL(); return meth->compute_key(out, outlen, pub_key, ecdh, KDF); } return ret; }
/* Our version of the ossl_ecdh_compute_key replaced in the EC_KEY_METHOD */ static int pkcs11_ec_ckey(void *out, size_t outlen, const EC_POINT *ecpointpeer, const EC_KEY *ecdh, void *(*KDF) (const void *in, size_t inlen, void *out, size_t *outlen)) { int ret = -1; size_t buflen; unsigned char *buf = NULL; size_t peerbuflen; unsigned char *peerbuf = NULL; const EC_GROUP *ecgroup = NULL; const EC_POINT *ecpoint = NULL; CK_ECDH1_DERIVE_PARAMS ecdh_parms; PKCS11_KEY * key = NULL; key = (PKCS11_KEY *) EC_KEY_get_ex_data(ecdh, ec_key_ex_index); if (key == NULL) { ret -1; goto err; } /* both peer and ecdh use same group parameters */ ecgroup = EC_KEY_get0_group(ecdh); buflen = (EC_GROUP_get_degree(ecgroup) + 7) / 8; peerbuflen = 2*buflen + 1; peerbuf = OPENSSL_malloc(peerbuflen); if (peerbuf == NULL) { ret = -1; goto err; } ecdh_parms.kdf = CKD_NULL; ecdh_parms.ulSharedDataLen = 0; ecdh_parms.pSharedData = NULL; ecdh_parms.ulPublicDataLen = peerbuflen; ret = EC_POINT_point2oct(ecgroup, ecpointpeer, POINT_CONVERSION_UNCOMPRESSED, peerbuf, peerbuflen,NULL); ecdh_parms.ulPublicDataLen = peerbuflen; ecdh_parms.pPublicData = peerbuf; ret = pkcs11_ecdh_derive_internal(&buf, &buflen, CKM_ECDH1_DERIVE, (const void *)&ecdh_parms, NULL, key); if (KDF != 0) { if (KDF(buf, buflen, out, &outlen) == NULL) { ret -1; goto err; } ret = outlen; } else { if (outlen > buflen) outlen = buflen; memcpy(out, buf, outlen); ret = outlen; } err: OPENSSL_free(buf); return (ret); }
VOID PMF_DerivePTK( IN PRTMP_ADAPTER pAd, IN UCHAR *PMK, IN UCHAR *ANonce, IN UCHAR *AA, IN UCHAR *SNonce, IN UCHAR *SA, OUT UCHAR *output, IN UINT len) { UCHAR concatenation[76]; UINT CurrPos = 0; UCHAR temp[32]; UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ', 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'}; /* initiate the concatenation input */ NdisZeroMemory(temp, sizeof(temp)); NdisZeroMemory(concatenation, 76); /* Get smaller address */ if (RTMPCompareMemory(SA, AA, 6) == 1) NdisMoveMemory(concatenation, AA, 6); else NdisMoveMemory(concatenation, SA, 6); CurrPos += 6; /* Get larger address */ if (RTMPCompareMemory(SA, AA, 6) == 1) NdisMoveMemory(&concatenation[CurrPos], SA, 6); else NdisMoveMemory(&concatenation[CurrPos], AA, 6); /* store the larger mac address for backward compatible of ralink proprietary STA-key issue */ NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN); CurrPos += 6; /* Get smaller Nonce */ if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) NdisMoveMemory(&concatenation[CurrPos], temp, 32); else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); else NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); CurrPos += 32; /* Get larger Nonce */ if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) NdisMoveMemory(&concatenation[CurrPos], temp, 32); else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); else NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); CurrPos += 32; hex_dump("[PMF]PMK", PMK, LEN_PMK); hex_dump("[PMF]concatenation=", concatenation, 76); /* Calculate a key material through FT-KDF */ KDF(PMK, LEN_PMK, Prefix, 22, concatenation, 76, output, len); }