int compute_password_element(REQUEST *request, pwd_session_t *session, uint16_t grp_num, char const *password, int password_len, char const *id_server, int id_server_len, char const *id_peer, int id_peer_len, uint32_t *token) { BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL; HMAC_CTX *hmac_ctx = NULL; uint8_t pwe_digest[SHA256_DIGEST_LENGTH], *prf_buf = NULL, ctr; int nid, is_odd, prime_bit_len, prime_byte_len, ret = 0; switch (grp_num) { /* from IANA registry for IKE D-H groups */ case 19: nid = NID_X9_62_prime256v1; break; case 20: nid = NID_secp384r1; break; case 21: nid = NID_secp521r1; break; case 25: nid = NID_X9_62_prime192v1; break; case 26: nid = NID_secp224r1; break; default: REDEBUG("Unknown group %d", grp_num); error: ret = -1; goto finish; } session->pwe = NULL; session->order = NULL; session->prime = NULL; session->group = EC_GROUP_new_by_curve_name(nid); if (!session->group) { REDEBUG("Unable to create EC_GROUP"); goto error; } MEM(session->pwe = EC_POINT_new(session->group)); MEM(session->order = BN_new()); MEM(session->prime = BN_new()); MEM(rnd = BN_new()); MEM(cofactor = BN_new()); MEM(x_candidate = BN_new()); if (!EC_GROUP_get_curve_GFp(session->group, session->prime, NULL, NULL, NULL)) { REDEBUG("Unable to get prime for GFp curve"); goto error; } if (!EC_GROUP_get_order(session->group, session->order, NULL)) { REDEBUG("Unable to get order for curve"); goto error; } if (!EC_GROUP_get_cofactor(session->group, cofactor, NULL)) { REDEBUG("unable to get cofactor for curve"); goto error; } prime_bit_len = BN_num_bits(session->prime); prime_byte_len = BN_num_bytes(session->prime); MEM(prf_buf = talloc_zero_array(session, uint8_t, prime_byte_len)); MEM(hmac_ctx = HMAC_CTX_new()); ctr = 0; for (;;) { if (ctr > 10) { REDEBUG("Unable to find random point on curve for group %d, something's fishy", grp_num); goto error; } ctr++; /* * compute counter-mode password value and stretch to prime * pwd-seed = H(token | peer-id | server-id | password | * counter) */ HMAC_Init_ex(hmac_ctx, allzero, SHA256_DIGEST_LENGTH, EVP_sha256(), NULL); HMAC_Update(hmac_ctx, (uint8_t *)token, sizeof(*token)); HMAC_Update(hmac_ctx, (uint8_t const *)id_peer, id_peer_len); HMAC_Update(hmac_ctx, (uint8_t const *)id_server, id_server_len); HMAC_Update(hmac_ctx, (uint8_t const *)password, password_len); HMAC_Update(hmac_ctx, (uint8_t *)&ctr, sizeof(ctr)); pwd_hmac_final(hmac_ctx, pwe_digest); BN_bin2bn(pwe_digest, SHA256_DIGEST_LENGTH, rnd); eap_pwd_kdf(pwe_digest, SHA256_DIGEST_LENGTH, "EAP-pwd Hunting And Pecking", strlen("EAP-pwd Hunting And Pecking"), prf_buf, prime_bit_len); BN_bin2bn(prf_buf, prime_byte_len, x_candidate); /* * eap_pwd_kdf() returns a string of bits 0..prime_bit_len but * BN_bin2bn will treat that string of bits as a big endian * number. If the prime_bit_len is not an even multiple of 8 * then excessive bits-- those _after_ prime_bit_len-- so now * we have to shift right the amount we masked off. */ if (prime_bit_len % 8) BN_rshift(x_candidate, x_candidate, (8 - (prime_bit_len % 8))); if (BN_ucmp(x_candidate, session->prime) >= 0) continue; /* * need to unambiguously identify the solution, if there is * one... */ is_odd = BN_is_odd(rnd) ? 1 : 0; /* * solve the quadratic equation, if it's not solvable then we * don't have a point */ if (!EC_POINT_set_compressed_coordinates_GFp(session->group, session->pwe, x_candidate, is_odd, NULL)) { continue; } /* * If there's a solution to the equation then the point must be * on the curve so why check again explicitly? OpenSSL code * says this is required by X9.62. We're not X9.62 but it can't * hurt just to be sure. */ if (!EC_POINT_is_on_curve(session->group, session->pwe, NULL)) { REDEBUG("Point is not on curve"); continue; } if (BN_cmp(cofactor, BN_value_one())) { /* make sure the point is not in a small sub-group */ if (!EC_POINT_mul(session->group, session->pwe, NULL, session->pwe, cofactor, NULL)) { RDEBUG("Cannot multiply generator by order"); continue; } if (EC_POINT_is_at_infinity(session->group, session->pwe)) { REDEBUG("Point is at infinity"); continue; } } /* if we got here then we have a new generator. */ break; } session->group_num = grp_num; finish: /* cleanliness and order.... */ HMAC_CTX_free(hmac_ctx); BN_clear_free(cofactor); BN_clear_free(x_candidate); BN_clear_free(rnd); talloc_free(prf_buf); return ret; }
static int eckey_priv_decode(EVP_PKEY * pkey, PKCS8_PRIV_KEY_INFO * p8) { const unsigned char *p = NULL; void *pval; int ptype, pklen; EC_KEY *eckey = NULL; X509_ALGOR *palg; if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) return 0; X509_ALGOR_get0(NULL, &ptype, &pval, palg); eckey = eckey_type2param(ptype, pval); if (!eckey) goto ecliberr; /* We have parameters now set private key */ if (!d2i_ECPrivateKey(&eckey, &p, pklen)) { ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR); goto ecerr; } /* calculate public key (if necessary) */ if (EC_KEY_get0_public_key(eckey) == NULL) { const BIGNUM *priv_key; const EC_GROUP *group; EC_POINT *pub_key; /* * the public key was not included in the SEC1 private key => * calculate the public key */ group = EC_KEY_get0_group(eckey); pub_key = EC_POINT_new(group); if (pub_key == NULL) { ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); goto ecliberr; } if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) { EC_POINT_free(pub_key); ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); goto ecliberr; } priv_key = EC_KEY_get0_private_key(eckey); if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) { EC_POINT_free(pub_key); ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); goto ecliberr; } if (EC_KEY_set_public_key(eckey, pub_key) == 0) { EC_POINT_free(pub_key); ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); goto ecliberr; } EC_POINT_free(pub_key); } EVP_PKEY_assign_EC_KEY(pkey, eckey); return 1; ecliberr: ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); ecerr: if (eckey) EC_KEY_free(eckey); return 0; }
EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) { EC_EXTRA_DATA *d; if (dest == NULL || src == NULL) { ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER); return NULL; } /* copy the parameters */ if (src->group) { const EC_METHOD *meth = EC_GROUP_method_of(src->group); /* clear the old group */ if (dest->group) EC_GROUP_free(dest->group); dest->group = EC_GROUP_new(meth); if (dest->group == NULL) return NULL; if (!EC_GROUP_copy(dest->group, src->group)) return NULL; } /* copy the public key */ if (src->pub_key && src->group) { if (dest->pub_key) EC_POINT_free(dest->pub_key); dest->pub_key = EC_POINT_new(src->group); if (dest->pub_key == NULL) return NULL; if (!EC_POINT_copy(dest->pub_key, src->pub_key)) return NULL; } /* copy the private key */ if (src->priv_key) { if (dest->priv_key == NULL) { dest->priv_key = BN_new(); if (dest->priv_key == NULL) return NULL; } if (!BN_copy(dest->priv_key, src->priv_key)) return NULL; } /* copy method/extra data */ EC_EX_DATA_free_all_data(&dest->method_data); for (d = src->method_data; d != NULL; d = d->next) { void *t = d->dup_func(d->data); if (t == NULL) return 0; if (!EC_EX_DATA_set_data(&dest->method_data, t, d->dup_func, d->free_func, d->clear_free_func)) return 0; } /* copy the rest */ dest->enc_flag = src->enc_flag; dest->nonce_from_hash_flag = src->nonce_from_hash_flag; dest->conv_form = src->conv_form; dest->version = src->version; dest->flags = src->flags; return dest; }
static int input_kex_ecdh_init(int type, u_int32_t seq, void *ctxt) { struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; EC_POINT *client_public; EC_KEY *server_key = NULL; const EC_GROUP *group; const EC_POINT *public_key; BIGNUM *shared_secret = NULL; struct sshkey *server_host_private, *server_host_public; u_char *server_host_key_blob = NULL, *signature = NULL; u_char *kbuf = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; size_t slen, sbloblen; size_t klen = 0, hashlen; int r; if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (EC_KEY_generate_key(server_key) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } group = EC_KEY_get0_group(server_key); #ifdef DEBUG_KEXECDH fputs("server private key:\n", stderr); sshkey_dump_ec_key(server_key); #endif if (kex->load_host_public_key == NULL || kex->load_host_private_key == NULL) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } server_host_public = kex->load_host_public_key(kex->hostkey_type, kex->hostkey_nid, ssh); server_host_private = kex->load_host_private_key(kex->hostkey_type, kex->hostkey_nid, ssh); if (server_host_public == NULL) { r = SSH_ERR_NO_HOSTKEY_LOADED; goto out; } if ((client_public = EC_POINT_new(group)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshpkt_get_ec(ssh, client_public, group)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; #ifdef DEBUG_KEXECDH fputs("client public key:\n", stderr); sshkey_dump_ec_point(group, client_public); #endif if (sshkey_ec_validate_public(group, client_public) != 0) { sshpkt_disconnect(ssh, "invalid client public key"); r = SSH_ERR_MESSAGE_INCOMPLETE; goto out; } /* Calculate shared_secret */ klen = (EC_GROUP_get_degree(group) + 7) / 8; if ((kbuf = malloc(klen)) == NULL || (shared_secret = BN_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (ECDH_compute_key(kbuf, klen, client_public, server_key, NULL) != (int)klen || BN_bin2bn(kbuf, klen, shared_secret) == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } #ifdef DEBUG_KEXECDH dump_digest("shared secret", kbuf, klen); #endif /* calc H */ if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, &sbloblen)) != 0) goto out; hashlen = sizeof(hash); if ((r = kex_ecdh_hash( kex->hash_alg, group, kex->client_version_string, kex->server_version_string, sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, client_public, EC_KEY_get0_public_key(server_key), shared_secret, hash, &hashlen)) != 0) goto out; /* save session id := H */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; kex->session_id = malloc(kex->session_id_len); if (kex->session_id == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(kex->session_id, hash, kex->session_id_len); } /* sign H */ if ((r = kex->sign(server_host_private, server_host_public, &signature, &slen, hash, hashlen, ssh->compat)) < 0) goto out; /* destroy_sensitive_data(); */ public_key = EC_KEY_get0_public_key(server_key); /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 || (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || (r = sshpkt_put_ec(ssh, public_key, group)) != 0 || (r = sshpkt_put_string(ssh, signature, slen)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) r = kex_send_newkeys(ssh); out: explicit_bzero(hash, sizeof(hash)); if (kex->ec_client_key) { EC_KEY_free(kex->ec_client_key); kex->ec_client_key = NULL; } if (server_key) EC_KEY_free(server_key); if (kbuf) { explicit_bzero(kbuf, klen); free(kbuf); } if (shared_secret) BN_clear_free(shared_secret); free(server_host_key_blob); free(signature); return r; }
int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) { EC_EXTRA_DATA *d; if (dest->meth->group_copy == 0) { ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (dest->meth != src->meth) { ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS); return 0; } if (dest == src) return 1; EC_EX_DATA_free_all_data(&dest->extra_data); for (d = src->extra_data; d != NULL; d = d->next) { void *t = d->dup_func(d->data); if (t == NULL) return 0; if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, d->free_func, d->clear_free_func)) return 0; } if (src->generator != NULL) { if (dest->generator == NULL) { dest->generator = EC_POINT_new(dest); if (dest->generator == NULL) return 0; } if (!EC_POINT_copy(dest->generator, src->generator)) return 0; } else { /* src->generator == NULL */ if (dest->generator != NULL) { EC_POINT_clear_free(dest->generator); dest->generator = NULL; } } if (!BN_copy(&dest->order, &src->order)) return 0; if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0; dest->curve_name = src->curve_name; dest->asn1_flag = src->asn1_flag; dest->asn1_form = src->asn1_form; if (src->seed) { if (dest->seed) OPENSSL_free(dest->seed); dest->seed = OPENSSL_malloc(src->seed_len); if (dest->seed == NULL) return 0; if (!memcpy(dest->seed, src->seed, src->seed_len)) return 0; dest->seed_len = src->seed_len; } else { if (dest->seed) OPENSSL_free(dest->seed); dest->seed = NULL; dest->seed_len = 0; } return dest->meth->group_copy(dest, src); }
/* * NIST SP800-56A co-factor ECDH tests. * KATs taken from NIST documents with parameters: * * - (QCAVSx,QCAVSy) is the public key for CAVS. * - dIUT is the private key for IUT. * - (QIUTx,QIUTy) is the public key for IUT. * - ZIUT is the shared secret KAT. * * CAVS: Cryptographic Algorithm Validation System * IUT: Implementation Under Test * * This function tests two things: * * 1. dIUT * G = (QIUTx,QIUTy) * i.e. public key for IUT computes correctly. * 2. x-coord of cofactor * dIUT * (QCAVSx,QCAVSy) = ZIUT * i.e. co-factor ECDH key computes correctly. * * returns zero on failure or unsupported curve. One otherwise. */ static int ecdh_cavs_kat(BIO *out, const ecdh_cavs_kat_t *kat) { int rv = 0, is_char_two = 0; EC_KEY *key1 = NULL; EC_POINT *pub = NULL; const EC_GROUP *group = NULL; BIGNUM *bnz = NULL, *x = NULL, *y = NULL; unsigned char *Ztmp = NULL, *Z = NULL; size_t Ztmplen, Zlen; BIO_puts(out, "Testing ECC CDH Primitive SP800-56A with "); BIO_puts(out, OBJ_nid2sn(kat->nid)); /* dIUT is IUT's private key */ if ((key1 = mk_eckey(kat->nid, kat->dIUT)) == NULL) goto err; /* these are cofactor ECDH KATs */ EC_KEY_set_flags(key1, EC_FLAG_COFACTOR_ECDH); if ((group = EC_KEY_get0_group(key1)) == NULL) goto err; if ((pub = EC_POINT_new(group)) == NULL) goto err; if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_characteristic_two_field) is_char_two = 1; /* (QIUTx, QIUTy) is IUT's public key */ if(!BN_hex2bn(&x, kat->QIUTx)) goto err; if(!BN_hex2bn(&y, kat->QIUTy)) goto err; if (is_char_two) { #ifdef OPENSSL_NO_EC2M goto err; #else if (!EC_POINT_set_affine_coordinates_GF2m(group, pub, x, y, NULL)) goto err; #endif } else { if (!EC_POINT_set_affine_coordinates_GFp(group, pub, x, y, NULL)) goto err; } /* dIUT * G = (QIUTx, QIUTy) should hold */ if (EC_POINT_cmp(group, EC_KEY_get0_public_key(key1), pub, NULL)) goto err; /* (QCAVSx, QCAVSy) is CAVS's public key */ if(!BN_hex2bn(&x, kat->QCAVSx)) goto err; if(!BN_hex2bn(&y, kat->QCAVSy)) goto err; if (is_char_two) { #ifdef OPENSSL_NO_EC2M goto err; #else if (!EC_POINT_set_affine_coordinates_GF2m(group, pub, x, y, NULL)) goto err; #endif } else { if (!EC_POINT_set_affine_coordinates_GFp(group, pub, x, y, NULL)) goto err; } /* ZIUT is the shared secret */ if(!BN_hex2bn(&bnz, kat->ZIUT)) goto err; Ztmplen = (EC_GROUP_get_degree(EC_KEY_get0_group(key1)) + 7) / 8; Zlen = BN_num_bytes(bnz); if (Zlen > Ztmplen) goto err; if((Ztmp = OPENSSL_zalloc(Ztmplen)) == NULL) goto err; if((Z = OPENSSL_zalloc(Ztmplen)) == NULL) goto err; if(!BN_bn2binpad(bnz, Z, Ztmplen)) goto err; if (!ECDH_compute_key(Ztmp, Ztmplen, pub, key1, 0)) goto err; /* shared secrets should be identical */ if (memcmp(Ztmp, Z, Ztmplen)) goto err; rv = 1; err: EC_KEY_free(key1); EC_POINT_free(pub); BN_free(bnz); BN_free(x); BN_free(y); OPENSSL_free(Ztmp); OPENSSL_free(Z); if (rv) { BIO_puts(out, " ok\n"); } else { fprintf(stderr, "Error in ECC CDH routines\n"); ERR_print_errors_fp(stderr); } return rv; }
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) { BN_CTX *ctx = NULL; BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL; EC_POINT *tmp_point=NULL; const EC_GROUP *group; int ret = 0; if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_MALLOC_FAILURE); return 0; } } else ctx = ctx_in; k = BN_new(); /* this value is later returned in *kinvp */ r = BN_new(); /* this value is later returned in *rp */ order = BN_new(); X = BN_new(); if (!k || !r || !order || !X) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } if ((tmp_point = EC_POINT_new(group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } do { /* get random k */ do if (!BN_rand_range(k, order)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } while (BN_is_zero(k)); /* We do not want timing information to leak the length of k, * so we compute G*k using an equivalent scalar of fixed * bit-length. */ if (!BN_add(k, k, order)) goto err; if (BN_num_bits(k) <= BN_num_bits(order)) if (!BN_add(k, k, order)) goto err; /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); 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_point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB); goto err; } } #ifndef OPENSSL_NO_EC2M else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp_point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB); goto err; } } #endif if (!BN_nnmod(r, X, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(r)); /* compute the inverse of k */ if (!BN_mod_inverse(k, k, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } /* clear old values if necessary */ if (*rp != NULL) BN_clear_free(*rp); if (*kinvp != NULL) BN_clear_free(*kinvp); /* save the pre-computed values */ *rp = r; *kinvp = k; ret = 1; err: if (!ret) { if (k != NULL) BN_clear_free(k); if (r != NULL) BN_clear_free(r); } if (ctx_in == NULL) BN_CTX_free(ctx); if (order != NULL) BN_free(order); if (tmp_point != NULL) EC_POINT_free(tmp_point); if (X) BN_clear_free(X); return(ret); }
static LUA_FUNCTION(openssl_pkey_new) { EVP_PKEY *pkey = NULL; const char* alg = "rsa"; if (lua_isnoneornil(L, 1) || lua_isstring(L, 1)) { alg = luaL_optstring(L, 1, alg); if (strcasecmp(alg, "rsa") == 0) { int bits = luaL_optint(L, 2, 1024); int e = luaL_optint(L, 3, 65537); RSA* rsa = RSA_new(); BIGNUM *E = BN_new(); BN_set_word(E, e); if (RSA_generate_key_ex(rsa, bits, E, NULL)) { pkey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(pkey, rsa); } else RSA_free(rsa); BN_free(E); } else if (strcasecmp(alg, "dsa") == 0) { int bits = luaL_optint(L, 2, 1024); size_t seed_len = 0; const char* seed = luaL_optlstring(L, 3, NULL, &seed_len); DSA *dsa = DSA_new(); if (DSA_generate_parameters_ex(dsa, bits, (byte*)seed, seed_len, NULL, NULL, NULL) && DSA_generate_key(dsa)) { pkey = EVP_PKEY_new(); EVP_PKEY_assign_DSA(pkey, dsa); } else DSA_free(dsa); } else if (strcasecmp(alg, "dh") == 0) { int bits = luaL_optint(L, 2, 512); int generator = luaL_optint(L, 3, 2); DH* dh = DH_new(); if (DH_generate_parameters_ex(dh, bits, generator, NULL)) { if (DH_generate_key(dh)) { pkey = EVP_PKEY_new(); EVP_PKEY_assign_DH(pkey, dh); } else DH_free(dh); } else DH_free(dh); } #ifndef OPENSSL_NO_EC else if (strcasecmp(alg, "ec") == 0) { int ec_name = NID_undef; EC_KEY *ec = NULL; EC_GROUP *group = openssl_get_ec_group(L, 2, 3, 4); if (!group) luaL_error(L, "failed to get ec_group object"); ec = EC_KEY_new(); if (ec) { EC_KEY_set_group(ec, group); EC_GROUP_free(group); if (EC_KEY_generate_key(ec)) { pkey = EVP_PKEY_new(); EVP_PKEY_assign_EC_KEY(pkey, ec); } else EC_KEY_free(ec); } else EC_GROUP_free(group); } #endif else { luaL_error(L, "not support %s!!!!", alg); } } else if (lua_istable(L, 1)) { lua_getfield(L, 1, "alg"); alg = luaL_optstring(L, -1, alg); lua_pop(L, 1); if (strcasecmp(alg, "rsa") == 0) { pkey = EVP_PKEY_new(); if (pkey) { RSA *rsa = RSA_new(); if (rsa) { OPENSSL_PKEY_SET_BN(1, rsa, n); OPENSSL_PKEY_SET_BN(1, rsa, e); OPENSSL_PKEY_SET_BN(1, rsa, d); OPENSSL_PKEY_SET_BN(1, rsa, p); OPENSSL_PKEY_SET_BN(1, rsa, q); OPENSSL_PKEY_SET_BN(1, rsa, dmp1); OPENSSL_PKEY_SET_BN(1, rsa, dmq1); OPENSSL_PKEY_SET_BN(1, rsa, iqmp); if (rsa->n) { if (!EVP_PKEY_assign_RSA(pkey, rsa)) { EVP_PKEY_free(pkey); pkey = NULL; } } } } } else if (strcasecmp(alg, "dsa") == 0) { pkey = EVP_PKEY_new(); if (pkey) { DSA *dsa = DSA_new(); if (dsa) { OPENSSL_PKEY_SET_BN(-1, dsa, p); OPENSSL_PKEY_SET_BN(-1, dsa, q); OPENSSL_PKEY_SET_BN(-1, dsa, g); OPENSSL_PKEY_SET_BN(-1, dsa, priv_key); OPENSSL_PKEY_SET_BN(-1, dsa, pub_key); if (dsa->p && dsa->q && dsa->g) { if (!dsa->priv_key && !dsa->pub_key) { DSA_generate_key(dsa); } if (!EVP_PKEY_assign_DSA(pkey, dsa)) { EVP_PKEY_free(pkey); pkey = NULL; } } } } } else if (strcasecmp(alg, "dh") == 0) { pkey = EVP_PKEY_new(); if (pkey) { DH *dh = DH_new(); if (dh) { OPENSSL_PKEY_SET_BN(-1, dh, p); OPENSSL_PKEY_SET_BN(-1, dh, g); OPENSSL_PKEY_SET_BN(-1, dh, priv_key); OPENSSL_PKEY_SET_BN(-1, dh, pub_key); if (dh->p && dh->g) { if (!dh->pub_key) { DH_generate_key(dh); } if (!EVP_PKEY_assign_DH(pkey, dh)) { EVP_PKEY_free(pkey); pkey = NULL; } } } } } else if (strcasecmp(alg, "ec") == 0) { BIGNUM *d = NULL; BIGNUM *x = NULL; BIGNUM *y = NULL; BIGNUM *z = NULL; EC_GROUP *group = NULL; lua_getfield(L, -1, "ec_name"); lua_getfield(L, -2, "param_enc"); lua_getfield(L, -3, "conv_form"); group = openssl_get_ec_group(L, -3, -2, -1); lua_pop(L, 3); if (!group) { luaL_error(L, "get openssl.ec_group fail"); } EC_GET_FIELD(d); EC_GET_FIELD(x); EC_GET_FIELD(y); EC_GET_FIELD(z); pkey = EVP_PKEY_new(); if (pkey) { EC_KEY *ec = EC_KEY_new(); if (ec) { EC_KEY_set_group(ec, group); if (d) EC_KEY_set_private_key(ec, d); if (x != NULL && y != NULL) { EC_POINT *pnt = EC_POINT_new(group); if (z == NULL) EC_POINT_set_affine_coordinates_GFp(group, pnt, x, y, NULL); else EC_POINT_set_Jprojective_coordinates_GFp(group, pnt, x, y, z, NULL); EC_KEY_set_public_key(ec, pnt); } if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) { EC_KEY_free(ec); EVP_PKEY_free(pkey); pkey = NULL; } if (d && !EC_KEY_check_key(ec)) { EC_KEY_generate_key_part(ec); } } } } } if (pkey) { PUSH_OBJECT(pkey, "openssl.evp_pkey"); return 1; } return 0; }
/***************************************************************************//** * Initialise the Mikey Sakke Parameter set storage. Presently there is only * one set (1), defined in RFC 6509, Appendix A. * * @return A boolean indicating success or failure. ******************************************************************************/ short ms_initParameterSets() { short ret_val = 1; uint8_t c = 0; BIGNUM *a = NULL; BIGNUM *b = NULL; BN_CTX *bn_ctx = NULL; if (!ms_parameter_sets_initialised) { /* Clear out the storage structure */ memset(ms_parameter_sets, 0, sizeof(ms_parameter_sets)); /**********************************************************************/ /* Add Parameter Set 1 (the default) */ /* - these values are immutable and defined in RFC 6509, Appendix A.*/ /**********************************************************************/ ms_parameter_sets[c].iana_sakke_params = 1; ms_parameter_sets[c].n = 128; ms_parameter_sets[c].p = BN_new(); BN_hex2bn(&ms_parameter_sets[c].p, MIKEY_SAKKE_p); ms_parameter_sets[c].q = BN_new(); BN_hex2bn(&ms_parameter_sets[c].q, MIKEY_SAKKE_q); ms_parameter_sets[c].Px = BN_new(); BN_hex2bn(&ms_parameter_sets[c].Px, MIKEY_SAKKE_Px); ms_parameter_sets[c].Py = BN_new(); BN_hex2bn(&ms_parameter_sets[c].Py, MIKEY_SAKKE_Py); ms_parameter_sets[c].g = BN_new(); BN_hex2bn(&ms_parameter_sets[c].g, MIKEY_SAKKE_g); ms_parameter_sets[c].data_set = ES_TRUE; if ((NULL != ms_parameter_sets[c].Px) && (NULL != ms_parameter_sets[c].Py) && (NULL != ms_parameter_sets[c].p)) { bn_ctx = BN_CTX_new(); a = BN_new(); b = BN_new(); /* Create a curve E */ BN_dec2bn(&a, "-3l"); /* Coefficient of 'x', see RFC 6508 Section * 2.1 description of 'E'. */ BN_dec2bn(&b, "0"); ms_parameter_sets[c].E = EC_GROUP_new_curve_GFp(ms_parameter_sets[c].p, a, b, bn_ctx); if (NULL != ms_parameter_sets[c].E) { ms_parameter_sets[c].P = EC_POINT_new(ms_parameter_sets[c].E); if (EC_POINT_set_affine_coordinates_GFp( ms_parameter_sets[c].E, ms_parameter_sets[c].P, ms_parameter_sets[c].Px, ms_parameter_sets[c].Py, bn_ctx)) { /* Indicate the MS parameter set(s) storage is initialised. */ ret_val = 0; ms_parameter_sets_initialised = ES_TRUE; ret_val = 0; } else { ES_ERROR("%s:%s:%d - MS parameter initialisation, unable to create Point 'P'!", __FILE__, __FUNCTION__, __LINE__); } } else { ES_ERROR("%s:%s:%d - MS parameter initialisation, unable to create curve 'E'!", __FILE__, __FUNCTION__, __LINE__); } BN_CTX_free(bn_ctx); BN_clear_free(a); BN_clear_free(b); bn_ctx = NULL; a = NULL; b = NULL; } /* Else just fall through and fail. */ /**********************************************************************/ /* !!!!! Add new Mikey Sakke parameter sets here. !!!!! */ /**********************************************************************/ /* increment c to add new set. */ } else { ES_ERROR("%s:%s:%d - MS parameter set already initialiased. Delete and reinitialise.", __FILE__, __FUNCTION__, __LINE__); /* Already initialised so return success. */ ret_val = 0; } return ret_val; } /* ms_initParameterSets */
void kexecdh_server(Kex *kex) { EC_POINT *client_public; EC_KEY *server_key; const EC_GROUP *group; BIGNUM *shared_secret; Key *server_host_private, *server_host_public; u_char *server_host_key_blob = NULL, *signature = NULL; u_char *kbuf, *hash; u_int klen, slen, sbloblen, hashlen; int curve_nid; if ((curve_nid = kex_ecdh_name_to_nid(kex->name)) == -1) fatal("%s: unsupported ECDH curve \"%s\"", __func__, kex->name); if ((server_key = EC_KEY_new_by_curve_name(curve_nid)) == NULL) fatal("%s: EC_KEY_new_by_curve_name failed", __func__); if (EC_KEY_generate_key(server_key) != 1) fatal("%s: EC_KEY_generate_key failed", __func__); group = EC_KEY_get0_group(server_key); #ifdef DEBUG_KEXECDH fputs("server private key:\n", stderr); key_dump_ec_key(server_key); #endif if (kex->load_host_public_key == NULL || kex->load_host_private_key == NULL) fatal("Cannot load hostkey"); server_host_public = kex->load_host_public_key(kex->hostkey_type); if (server_host_public == NULL) fatal("Unsupported hostkey type %d", kex->hostkey_type); server_host_private = kex->load_host_private_key(kex->hostkey_type); if (server_host_private == NULL) fatal("Missing private key for hostkey type %d", kex->hostkey_type); debug("expecting SSH2_MSG_KEX_ECDH_INIT"); packet_read_expect(SSH2_MSG_KEX_ECDH_INIT); if ((client_public = EC_POINT_new(group)) == NULL) fatal("%s: EC_POINT_new failed", __func__); packet_get_ecpoint(group, client_public); packet_check_eom(); if (key_ec_validate_public(group, client_public) != 0) fatal("%s: invalid client public key", __func__); #ifdef DEBUG_KEXECDH fputs("client public key:\n", stderr); key_dump_ec_point(group, client_public); #endif /* Calculate shared_secret */ klen = (EC_GROUP_get_degree(group) + 7) / 8; kbuf = xmalloc(klen); if (ECDH_compute_key(kbuf, klen, client_public, server_key, NULL) != (int)klen) fatal("%s: ECDH_compute_key failed", __func__); #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, klen); #endif if ((shared_secret = BN_new()) == NULL) fatal("%s: BN_new failed", __func__); if (BN_bin2bn(kbuf, klen, shared_secret) == NULL) fatal("%s: BN_bin2bn failed", __func__); memset(kbuf, 0, klen); xfree(kbuf); /* calc H */ key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); kex_ecdh_hash( kex->evp_md, group, kex->client_version_string, kex->server_version_string, buffer_ptr(&kex->peer), buffer_len(&kex->peer), buffer_ptr(&kex->my), buffer_len(&kex->my), server_host_key_blob, sbloblen, client_public, EC_KEY_get0_public_key(server_key), shared_secret, &hash, &hashlen ); EC_POINT_clear_free(client_public); /* save session id := H */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; kex->session_id = xmalloc(kex->session_id_len); memcpy(kex->session_id, hash, kex->session_id_len); } /* sign H */ if (PRIVSEP(key_sign(server_host_private, &signature, &slen, hash, hashlen)) < 0) fatal("kexdh_server: key_sign failed"); /* destroy_sensitive_data(); */ /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ packet_start(SSH2_MSG_KEX_ECDH_REPLY); packet_put_string(server_host_key_blob, sbloblen); packet_put_ecpoint(group, EC_KEY_get0_public_key(server_key)); packet_put_string(signature, slen); packet_send(); xfree(signature); xfree(server_host_key_blob); /* have keys, free server key */ EC_KEY_free(server_key); kex_derive_keys(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); }
int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) { if (dest->meth->group_copy == 0) { ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (dest->meth != src->meth) { ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS); return 0; } if (dest == src) return 1; /* Copy precomputed */ dest->pre_comp_type = src->pre_comp_type; switch (src->pre_comp_type) { case PCT_none: dest->pre_comp.ec = NULL; break; case PCT_nistz256: #ifdef ECP_NISTZ256_ASM dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256); #endif break; #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 case PCT_nistp224: dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224); break; case PCT_nistp256: dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256); break; case PCT_nistp521: dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521); break; #else case PCT_nistp224: case PCT_nistp256: case PCT_nistp521: break; #endif case PCT_ec: dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec); break; } if (src->mont_data != NULL) { if (dest->mont_data == NULL) { dest->mont_data = BN_MONT_CTX_new(); if (dest->mont_data == NULL) return 0; } if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data)) return 0; } else { /* src->generator == NULL */ BN_MONT_CTX_free(dest->mont_data); dest->mont_data = NULL; } if (src->generator != NULL) { if (dest->generator == NULL) { dest->generator = EC_POINT_new(dest); if (dest->generator == NULL) return 0; } if (!EC_POINT_copy(dest->generator, src->generator)) return 0; } else { /* src->generator == NULL */ EC_POINT_clear_free(dest->generator); dest->generator = NULL; } if ((src->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) { if (!BN_copy(dest->order, src->order)) return 0; if (!BN_copy(dest->cofactor, src->cofactor)) return 0; } dest->curve_name = src->curve_name; dest->asn1_flag = src->asn1_flag; dest->asn1_form = src->asn1_form; if (src->seed) { OPENSSL_free(dest->seed); dest->seed = OPENSSL_malloc(src->seed_len); if (dest->seed == NULL) return 0; if (!memcpy(dest->seed, src->seed, src->seed_len)) return 0; dest->seed_len = src->seed_len; } else { OPENSSL_free(dest->seed); dest->seed = NULL; dest->seed_len = 0; } return dest->meth->group_copy(dest, src); }
int main() { BIGNUM *x, *y, *exp, *m, *order, *cof; BIGNUM t, store[30]; COMPLEX *a, *b, *r; EC_POINT *point, *Q; int i; x = BN_new(); y = BN_new(); order = BN_new(); exp = BN_new(); m = BN_new(); a = COMP_new(); b = COMP_new(); r = COMP_new(); for( i = 0; i < 30; i++ ) BN_init( &(store[i]) ); if ( Context == NULL ) Context = BN_CTX_new(); bi_init( &malloc ); group = EC_GROUP_new( EC_GFp_simple_method() ); if ( group == NULL ) goto err; if(!BN_set_word(m, 43l)) goto err; BN_set_word(x, 1l); BN_set_word(y, 0l); if ( !EC_GROUP_set_curve_GFp( group, m, x, y, Context) ) goto err; BN_set_word(x, 23l); BN_set_word(y, 8l); BN_set_word(order, 11l); point = EC_POINT_new( group ); EC_POINT_set_affine_coordinates_GFp( group, point, x, y, Context ); cof = BN_new(); BN_set_word( cof, 4 ); EC_GROUP_set_generator( group, point, order, cof ); if ( EC_GROUP_check( group, Context ) ) printf(" group set is ok \n"); TSS_DAA_ISSUER_KEY issuer_key; TSS_DAA_ISSUER_PROOF issuer_proof; TSS_DAA_JOIN_issuer_setup(&issuer_key, &issuer_proof); // printf("\n"); // BN_set_word(x, 41l); // BN_mod_inverse(x, x, m, Context); // BN_print_fp(stdout, x); // // printf("\n"); // BN_set_word(x, 11l); // BN_mod_inverse(x, x, m, Context); // BN_print_fp(stdout, x); char *str = "abcdefghijklmnop"; Q = map_to_point( str ); BN_set_word(x, 23l); BN_set_word(y, 8l); BN_set_word(order, 11l); Q = EC_POINT_new( group ); EC_POINT_set_affine_coordinates_GFp( group, Q, x, y, Context ); Tate( point, Q, order, 0, store, a ); printf("tate pair t(p, Q) =:\n a.x: "); BN_print_fp(stdout, &a->x); printf("\na.y: "); BN_print_fp(stdout, &a->y); EC_POINT_dbl( group, point, point, Context); EC_POINT_get_affine_coordinates_GFp( group, point, x, y, Context); printf("2A.x =:\n"); BN_print_fp(stdout, x); printf("2P.y= :\n"); BN_print_fp(stdout, y); Tate( point, Q, order, 0, store, a ); printf("tate pair t(2p, Q) =:\n a.x: "); BN_print_fp(stdout, &a->x); printf("\na.y: "); BN_print_fp(stdout, &a->y); BN_free( x ); BN_free( y ); BN_free( exp ); BN_free( m ); BN_free( order ); BN_free( cof ); COMP_free( a ); COMP_free( b ); COMP_free( r ); return 0; err: BN_free( &t ); BN_free( x ); BN_free( y ); BN_free( exp ); BN_free( m ); BN_free( order ); BN_free( cof ); COMP_free( a ); COMP_free( b ); COMP_free( r ); return 0; }
void * vg_thread_loop(void *arg) { unsigned char hash_buf[128]; unsigned char *eckey_buf; unsigned char hash1[32]; int i, c, len, output_interval; int hash_len; const BN_ULONG rekey_max = 10000000; BN_ULONG npoints, rekey_at, nbatch; vg_context_t *vcp = (vg_context_t *) arg; EC_KEY *pkey = NULL; const EC_GROUP *pgroup; const EC_POINT *pgen; const int ptarraysize = 256; EC_POINT *ppnt[ptarraysize]; EC_POINT *pbatchinc; vg_test_func_t test_func = vcp->vc_test; vg_exec_context_t ctx; vg_exec_context_t *vxcp; struct timeval tvstart; memset(&ctx, 0, sizeof(ctx)); vxcp = &ctx; vg_exec_context_init(vcp, &ctx); pkey = vxcp->vxc_key; pgroup = EC_KEY_get0_group(pkey); pgen = EC_GROUP_get0_generator(pgroup); for (i = 0; i < ptarraysize; i++) { ppnt[i] = EC_POINT_new(pgroup); if (!ppnt[i]) { fprintf(stderr, "ERROR: out of memory?\n"); exit(1); } } pbatchinc = EC_POINT_new(pgroup); if (!pbatchinc) { fprintf(stderr, "ERROR: out of memory?\n"); exit(1); } BN_set_word(&vxcp->vxc_bntmp, ptarraysize); EC_POINT_mul(pgroup, pbatchinc, &vxcp->vxc_bntmp, NULL, NULL, vxcp->vxc_bnctx); EC_POINT_make_affine(pgroup, pbatchinc, vxcp->vxc_bnctx); npoints = 0; rekey_at = 0; nbatch = 0; vxcp->vxc_key = pkey; vxcp->vxc_binres[0] = vcp->vc_addrtype; c = 0; output_interval = 1000; gettimeofday(&tvstart, NULL); if (vcp->vc_format == VCF_SCRIPT) { hash_buf[ 0] = 0x51; // OP_1 hash_buf[ 1] = 0x41; // pubkey length // gap for pubkey hash_buf[67] = 0x51; // OP_1 hash_buf[68] = 0xae; // OP_CHECKMULTISIG eckey_buf = hash_buf + 2; hash_len = 69; } else { eckey_buf = hash_buf; hash_len = 65; } while (!vcp->vc_halt) { if (++npoints >= rekey_at) { vg_exec_context_upgrade_lock(vxcp); /* Generate a new random private key */ EC_KEY_generate_key(pkey); npoints = 0; /* Determine rekey interval */ EC_GROUP_get_order(pgroup, &vxcp->vxc_bntmp, vxcp->vxc_bnctx); BN_sub(&vxcp->vxc_bntmp2, &vxcp->vxc_bntmp, EC_KEY_get0_private_key(pkey)); rekey_at = BN_get_word(&vxcp->vxc_bntmp2); if ((rekey_at == BN_MASK2) || (rekey_at > rekey_max)) rekey_at = rekey_max; assert(rekey_at > 0); EC_POINT_copy(ppnt[0], EC_KEY_get0_public_key(pkey)); vg_exec_context_downgrade_lock(vxcp); npoints++; vxcp->vxc_delta = 0; if (vcp->vc_pubkey_base) EC_POINT_add(pgroup, ppnt[0], ppnt[0], vcp->vc_pubkey_base, vxcp->vxc_bnctx); for (nbatch = 1; (nbatch < ptarraysize) && (npoints < rekey_at); nbatch++, npoints++) { EC_POINT_add(pgroup, ppnt[nbatch], ppnt[nbatch-1], pgen, vxcp->vxc_bnctx); } } else { /* * Common case * * EC_POINT_add() can skip a few multiplies if * one or both inputs are affine (Z_is_one). * This is the case for every point in ppnt, as * well as pbatchinc. */ assert(nbatch == ptarraysize); for (nbatch = 0; (nbatch < ptarraysize) && (npoints < rekey_at); nbatch++, npoints++) { EC_POINT_add(pgroup, ppnt[nbatch], ppnt[nbatch], pbatchinc, vxcp->vxc_bnctx); } } /* * The single most expensive operation performed in this * loop is modular inversion of ppnt->Z. There is an * algorithm implemented in OpenSSL to do batched inversion * that only does one actual BN_mod_inverse(), and saves * a _lot_ of time. * * To take advantage of this, we batch up a few points, * and feed them to EC_POINTs_make_affine() below. */ EC_POINTs_make_affine(pgroup, nbatch, ppnt, vxcp->vxc_bnctx); for (i = 0; i < nbatch; i++, vxcp->vxc_delta++) { /* Hash the public key */ len = EC_POINT_point2oct(pgroup, ppnt[i], POINT_CONVERSION_UNCOMPRESSED, eckey_buf, 65, vxcp->vxc_bnctx); assert(len == 65); SHA256(hash_buf, hash_len, hash1); RIPEMD160(hash1, sizeof(hash1), &vxcp->vxc_binres[1]); switch (test_func(vxcp)) { case 1: npoints = 0; rekey_at = 0; i = nbatch; break; case 2: goto out; default: break; } } c += i; if (c >= output_interval) { output_interval = vg_output_timing(vcp, c, &tvstart); if (output_interval > 250000) output_interval = 250000; c = 0; } vg_exec_context_yield(vxcp); } out: vg_exec_context_del(&ctx); vg_context_thread_exit(vcp); for (i = 0; i < ptarraysize; i++) if (ppnt[i]) EC_POINT_free(ppnt[i]); if (pbatchinc) EC_POINT_free(pbatchinc); return NULL; }
static struct wpabuf * eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data, struct eap_method_ret *ret, const struct wpabuf *reqData, const u8 *payload, size_t payload_len) { struct wpabuf *resp = NULL; EC_POINT *K = NULL, *point = NULL; BIGNUM *mask = NULL, *x = NULL, *y = NULL, *cofactor = NULL; u16 offset; u8 *ptr, *scalar = NULL, *element = NULL; if (((data->private_value = BN_new()) == NULL) || ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) || ((cofactor = BN_new()) == NULL) || ((data->my_scalar = BN_new()) == NULL) || ((mask = BN_new()) == NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): scalar allocation fail"); goto fin; } if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) { wpa_printf(MSG_INFO, "EAP-pwd (peer): unable to get cofactor " "for curve"); goto fin; } BN_rand_range(data->private_value, data->grp->order); BN_rand_range(mask, data->grp->order); BN_add(data->my_scalar, data->private_value, mask); BN_mod(data->my_scalar, data->my_scalar, data->grp->order, data->bnctx); if (!EC_POINT_mul(data->grp->group, data->my_element, NULL, data->grp->pwe, mask, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): element allocation " "fail"); eap_pwd_state(data, FAILURE); goto fin; } if (!EC_POINT_invert(data->grp->group, data->my_element, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail"); goto fin; } BN_free(mask); if (((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): point allocation fail"); goto fin; } /* process the request */ if (((data->server_scalar = BN_new()) == NULL) || ((data->k = BN_new()) == NULL) || ((K = EC_POINT_new(data->grp->group)) == NULL) || ((point = EC_POINT_new(data->grp->group)) == NULL) || ((data->server_element = EC_POINT_new(data->grp->group)) == NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): peer data allocation " "fail"); goto fin; } /* element, x then y, followed by scalar */ ptr = (u8 *) payload; BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x); ptr += BN_num_bytes(data->grp->prime); BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y); ptr += BN_num_bytes(data->grp->prime); BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->server_scalar); if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group, data->server_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): setting peer element " "fail"); goto fin; } /* check to ensure server's element is not in a small sub-group */ if (BN_cmp(cofactor, BN_value_one())) { if (!EC_POINT_mul(data->grp->group, point, NULL, data->server_element, cofactor, NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply " "server element by order!\n"); goto fin; } if (EC_POINT_is_at_infinity(data->grp->group, point)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): server element " "is at infinity!\n"); goto fin; } } /* compute the shared key, k */ if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe, data->server_scalar, data->bnctx)) || (!EC_POINT_add(data->grp->group, K, K, data->server_element, data->bnctx)) || (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value, data->bnctx))) { wpa_printf(MSG_INFO, "EAP-PWD (peer): computing shared key " "fail"); goto fin; } /* ensure that the shared key isn't in a small sub-group */ if (BN_cmp(cofactor, BN_value_one())) { if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor, NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply " "shared key point by order"); goto fin; } } /* * This check is strictly speaking just for the case above where * co-factor > 1 but it was suggested that even though this is probably * never going to happen it is a simple and safe check "just to be * sure" so let's be safe. */ if (EC_POINT_is_at_infinity(data->grp->group, K)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): shared key point is at " "infinity!\n"); goto fin; } if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k, NULL, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to extract " "shared secret from point"); goto fin; } /* now do the response */ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, data->my_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): point assignment fail"); goto fin; } if (((scalar = os_malloc(BN_num_bytes(data->grp->order))) == NULL) || ((element = os_malloc(BN_num_bytes(data->grp->prime) * 2)) == NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): data allocation fail"); goto fin; } /* * bignums occupy as little memory as possible so one that is * sufficiently smaller than the prime or order might need pre-pending * with zeros. */ os_memset(scalar, 0, BN_num_bytes(data->grp->order)); os_memset(element, 0, BN_num_bytes(data->grp->prime) * 2); offset = BN_num_bytes(data->grp->order) - BN_num_bytes(data->my_scalar); BN_bn2bin(data->my_scalar, scalar + offset); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); BN_bn2bin(x, element + offset); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset); resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, sizeof(struct eap_pwd_hdr) + BN_num_bytes(data->grp->order) + (2 * BN_num_bytes(data->grp->prime)), EAP_CODE_RESPONSE, eap_get_id(reqData)); if (resp == NULL) goto fin; wpabuf_put_u8(resp, EAP_PWD_OPCODE_COMMIT_EXCH); /* we send the element as (x,y) follwed by the scalar */ wpabuf_put_data(resp, element, (2 * BN_num_bytes(data->grp->prime))); wpabuf_put_data(resp, scalar, BN_num_bytes(data->grp->order)); fin: os_free(scalar); os_free(element); BN_free(x); BN_free(y); BN_free(cofactor); EC_POINT_free(K); EC_POINT_free(point); if (resp == NULL) eap_pwd_state(data, FAILURE); else eap_pwd_state(data, PWD_Confirm_Req); return resp; }
/* * Fills EC_KEY structure hidden in the app_data field of DSA structure * with parameter information, extracted from parameter array in * params.c file. * * Also fils DSA->q field with copy of EC_GROUP order field to make * DSA_size function work */ int fill_GOST2001_params(EC_KEY *eckey, int nid) { R3410_2001_params *params = R3410_2001_paramset; EC_GROUP *grp = NULL; BIGNUM *p = NULL, *q = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL; EC_POINT *P = NULL; BN_CTX *ctx = BN_CTX_new(); int ok = 0; if (!ctx) { GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); goto err; } BN_CTX_start(ctx); p = BN_CTX_get(ctx); a = BN_CTX_get(ctx); b = BN_CTX_get(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); q = BN_CTX_get(ctx); if (!p || !a || !b || !x || !y || !q) { GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); goto err; } while (params->nid != NID_undef && params->nid != nid) params++; if (params->nid == NID_undef) { GOSTerr(GOST_F_FILL_GOST2001_PARAMS, GOST_R_UNSUPPORTED_PARAMETER_SET); goto err; } if (!BN_hex2bn(&p, params->p) || !BN_hex2bn(&a, params->a) || !BN_hex2bn(&b, params->b)) { GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); goto err; } grp = EC_GROUP_new_curve_GFp(p, a, b, ctx); if (!grp) { GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); goto err; } P = EC_POINT_new(grp); if (!P) { GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); goto err; } if (!BN_hex2bn(&x, params->x) || !BN_hex2bn(&y, params->y) || !EC_POINT_set_affine_coordinates_GFp(grp, P, x, y, ctx) || !BN_hex2bn(&q, params->q)) { GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); goto err; } #ifdef DEBUG_KEYS fprintf(stderr, "Set params index %d oid %s\nq=", (params - R3410_2001_paramset), OBJ_nid2sn(params->nid)); BN_print_fp(stderr, q); fprintf(stderr, "\n"); #endif if (!EC_GROUP_set_generator(grp, P, q, NULL)) { GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); goto err; } EC_GROUP_set_curve_name(grp, params->nid); if (!EC_KEY_set_group(eckey, grp)) { GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); goto err; } ok = 1; err: EC_POINT_free(P); EC_GROUP_free(grp); if (ctx) BN_CTX_end(ctx); BN_CTX_free(ctx); return ok; }
int StealthSecret(ec_secret& secret, ec_point& pubkey, const ec_point& pkSpend, ec_secret& sharedSOut, ec_point& pkOut) { /* send: secret = ephem_secret, pubkey = scan_pubkey receive: secret = scan_secret, pubkey = ephem_pubkey c = H(dP) Q = public scan key (EC point, 33 bytes) d = private scan key (integer, 32 bytes) R = public spend key f = private spend key Q = dG R = fG Sender (has Q and R, not d or f): P = eG c = H(eQ) = H(dP) R' = R + cG Recipient gets R' and P test 0 and infinity? */ int rv = 0; std::vector<uint8_t> vchOutQ; BN_CTX* bnCtx = NULL; BIGNUM* bnEphem = NULL; BIGNUM* bnQ = NULL; EC_POINT* Q = NULL; BIGNUM* bnOutQ = NULL; BIGNUM* bnc = NULL; EC_POINT* C = NULL; BIGNUM* bnR = NULL; EC_POINT* R = NULL; EC_POINT* Rout = NULL; BIGNUM* bnOutR = NULL; EC_GROUP* ecgrp = EC_GROUP_new_by_curve_name(NID_secp256k1); if (!ecgrp) { printf("StealthSecret(): EC_GROUP_new_by_curve_name failed.\n"); return 1; }; if (!(bnCtx = BN_CTX_new())) { printf("StealthSecret(): BN_CTX_new failed.\n"); rv = 1; goto End; }; if (!(bnEphem = BN_bin2bn(&secret.e[0], ec_secret_size, BN_new()))) { printf("StealthSecret(): bnEphem BN_bin2bn failed.\n"); rv = 1; goto End; }; if (!(bnQ = BN_bin2bn(&pubkey[0], pubkey.size(), BN_new()))) { printf("StealthSecret(): bnQ BN_bin2bn failed\n"); rv = 1; goto End; }; if (!(Q = EC_POINT_bn2point(ecgrp, bnQ, NULL, bnCtx))) { printf("StealthSecret(): Q EC_POINT_bn2point failed\n"); rv = 1; goto End; }; // -- eQ // EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx); // EC_POINT_mul calculates the value generator * n + q * m and stores the result in r. The value n may be NULL in which case the result is just q * m. if (!EC_POINT_mul(ecgrp, Q, NULL, Q, bnEphem, bnCtx)) { printf("StealthSecret(): eQ EC_POINT_mul failed\n"); rv = 1; goto End; }; if (!(bnOutQ = EC_POINT_point2bn(ecgrp, Q, POINT_CONVERSION_COMPRESSED, BN_new(), bnCtx))) { printf("StealthSecret(): Q EC_POINT_bn2point failed\n"); rv = 1; goto End; }; vchOutQ.resize(ec_compressed_size); if (BN_num_bytes(bnOutQ) != (int) ec_compressed_size || BN_bn2bin(bnOutQ, &vchOutQ[0]) != (int) ec_compressed_size) { printf("StealthSecret(): bnOutQ incorrect length.\n"); rv = 1; goto End; }; SHA256(&vchOutQ[0], vchOutQ.size(), &sharedSOut.e[0]); if (!(bnc = BN_bin2bn(&sharedSOut.e[0], ec_secret_size, BN_new()))) { printf("StealthSecret(): BN_bin2bn failed\n"); rv = 1; goto End; }; // -- cG if (!(C = EC_POINT_new(ecgrp))) { printf("StealthSecret(): C EC_POINT_new failed\n"); rv = 1; goto End; }; if (!EC_POINT_mul(ecgrp, C, bnc, NULL, NULL, bnCtx)) { printf("StealthSecret(): C EC_POINT_mul failed\n"); rv = 1; goto End; }; if (!(bnR = BN_bin2bn(&pkSpend[0], pkSpend.size(), BN_new()))) { printf("StealthSecret(): bnR BN_bin2bn failed\n"); rv = 1; goto End; }; if (!(R = EC_POINT_bn2point(ecgrp, bnR, NULL, bnCtx))) { printf("StealthSecret(): R EC_POINT_bn2point failed\n"); rv = 1; goto End; }; if (!EC_POINT_mul(ecgrp, C, bnc, NULL, NULL, bnCtx)) { printf("StealthSecret(): C EC_POINT_mul failed\n"); rv = 1; goto End; }; if (!(Rout = EC_POINT_new(ecgrp))) { printf("StealthSecret(): Rout EC_POINT_new failed\n"); rv = 1; goto End; }; if (!EC_POINT_add(ecgrp, Rout, R, C, bnCtx)) { printf("StealthSecret(): Rout EC_POINT_add failed\n"); rv = 1; goto End; }; if (!(bnOutR = EC_POINT_point2bn(ecgrp, Rout, POINT_CONVERSION_COMPRESSED, BN_new(), bnCtx))) { printf("StealthSecret(): Rout EC_POINT_bn2point failed\n"); rv = 1; goto End; }; pkOut.resize(ec_compressed_size); if (BN_num_bytes(bnOutR) != (int) ec_compressed_size || BN_bn2bin(bnOutR, &pkOut[0]) != (int) ec_compressed_size) { printf("StealthSecret(): pkOut incorrect length.\n"); rv = 1; goto End; }; End: if (bnOutR) BN_free(bnOutR); if (Rout) EC_POINT_free(Rout); if (R) EC_POINT_free(R); if (bnR) BN_free(bnR); if (C) EC_POINT_free(C); if (bnc) BN_free(bnc); if (bnOutQ) BN_free(bnOutQ); if (Q) EC_POINT_free(Q); if (bnQ) BN_free(bnQ); if (bnEphem) BN_free(bnEphem); if (bnCtx) BN_CTX_free(bnCtx); EC_GROUP_free(ecgrp); return rv; };
static int input_kex_ecdh_reply(int type, u_int32_t seq, void *ctxt) { struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; const EC_GROUP *group; EC_POINT *server_public = NULL; EC_KEY *client_key; BIGNUM *shared_secret = NULL; struct sshkey *server_host_key = NULL; u_char *server_host_key_blob = NULL, *signature = NULL; u_char *kbuf = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; size_t slen, sbloblen; size_t klen = 0, hashlen; int r; if (kex->verify_host_key == NULL) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } group = kex->ec_group; client_key = kex->ec_client_key; /* hostkey */ if ((r = sshpkt_get_string(ssh, &server_host_key_blob, &sbloblen)) != 0 || (r = sshkey_from_blob(server_host_key_blob, sbloblen, &server_host_key)) != 0) goto out; if (server_host_key->type != kex->hostkey_type || (kex->hostkey_type == KEY_ECDSA && server_host_key->ecdsa_nid != kex->hostkey_nid)) { r = SSH_ERR_KEY_TYPE_MISMATCH; goto out; } if (kex->verify_host_key(server_host_key, ssh) == -1) { r = SSH_ERR_SIGNATURE_INVALID; goto out; } /* Q_S, server public key */ /* signed H */ if ((server_public = EC_POINT_new(group)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshpkt_get_ec(ssh, server_public, group)) != 0 || (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; #ifdef DEBUG_KEXECDH fputs("server public key:\n", stderr); sshkey_dump_ec_point(group, server_public); #endif if (sshkey_ec_validate_public(group, server_public) != 0) { sshpkt_disconnect(ssh, "invalid server public key"); r = SSH_ERR_MESSAGE_INCOMPLETE; goto out; } klen = (EC_GROUP_get_degree(group) + 7) / 8; if ((kbuf = malloc(klen)) == NULL || (shared_secret = BN_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (ECDH_compute_key(kbuf, klen, server_public, client_key, NULL) != (int)klen || BN_bin2bn(kbuf, klen, shared_secret) == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } #ifdef DEBUG_KEXECDH dump_digest("shared secret", kbuf, klen); #endif /* calc and verify H */ hashlen = sizeof(hash); if ((r = kex_ecdh_hash( kex->hash_alg, group, kex->client_version_string, kex->server_version_string, sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, EC_KEY_get0_public_key(client_key), server_public, shared_secret, hash, &hashlen)) != 0) goto out; if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen, ssh->compat)) != 0) goto out; /* save session id */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; kex->session_id = malloc(kex->session_id_len); if (kex->session_id == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(kex->session_id, hash, kex->session_id_len); } if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) r = kex_send_newkeys(ssh); out: explicit_bzero(hash, sizeof(hash)); if (kex->ec_client_key) { EC_KEY_free(kex->ec_client_key); kex->ec_client_key = NULL; } if (server_public) EC_POINT_clear_free(server_public); if (kbuf) { explicit_bzero(kbuf, klen); free(kbuf); } if (shared_secret) BN_clear_free(shared_secret); sshkey_free(server_host_key); free(server_host_key_blob); free(signature); return r; }
static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) { EC_GROUP *group = NULL; EC_POINT *P = NULL; BN_CTX *ctx = NULL; BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order = NULL; int ok = 0; int seed_len, param_len; const EC_METHOD *meth; const EC_CURVE_DATA *data; const unsigned char *params; /* If no curve data curve method must handle everything */ if (curve.data == NULL) return EC_GROUP_new(curve.meth != NULL ? curve.meth() : NULL); if ((ctx = BN_CTX_new()) == NULL) { ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE); goto err; } data = curve.data; seed_len = data->seed_len; param_len = data->param_len; params = (const unsigned char *)(data + 1); /* skip header */ params += seed_len; /* skip seed */ if ((p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) == NULL || (a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) == NULL || (b = BN_bin2bn(params + 2 * param_len, param_len, NULL)) == NULL) { ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); goto err; } if (curve.meth != 0) { meth = curve.meth(); if (((group = EC_GROUP_new(meth)) == NULL) || (!(group->meth->group_set_curve(group, p, a, b, ctx)))) { ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); goto err; } } else if (data->field_type == NID_X9_62_prime_field) { if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) { ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); goto err; } } #ifndef OPENSSL_NO_EC2M else { /* field_type == * NID_X9_62_characteristic_two_field */ if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL) { ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); goto err; } } #endif if ((P = EC_POINT_new(group)) == NULL) { ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); goto err; } if ((x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) == NULL || (y = BN_bin2bn(params + 4 * param_len, param_len, NULL)) == NULL) { ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); goto err; } if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) { ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); goto err; } if ((order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) == NULL || !BN_set_word(x, (BN_ULONG)data->cofactor)) { ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); goto err; } if (!EC_GROUP_set_generator(group, P, order, x)) { ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); goto err; } if (seed_len) { if (!EC_GROUP_set_seed(group, params - seed_len, seed_len)) { ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); goto err; } } ok = 1; err: if (!ok) { EC_GROUP_free(group); group = NULL; } EC_POINT_free(P); BN_CTX_free(ctx); BN_free(p); BN_free(a); BN_free(b); BN_free(order); BN_free(x); BN_free(y); return group; }
static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey) { int ret = -1, i; BN_CTX *ctx; BIGNUM *order, *u1, *u2, *m, *X; EC_POINT *point = NULL; const EC_GROUP *group; const EC_POINT *pub_key; /* check input values */ if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS); return -1; } ctx = BN_CTX_new(); if (!ctx) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); return -1; } BN_CTX_start(ctx); order = BN_CTX_get(ctx); u1 = BN_CTX_get(ctx); u2 = BN_CTX_get(ctx); m = BN_CTX_get(ctx); X = BN_CTX_get(ctx); if (!X) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE); ret = 0; /* signature is invalid */ goto err; } /* calculate tmp1 = inv(S) mod order */ if (!BN_mod_inverse(u2, sig->s, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* digest -> m */ i = BN_num_bits(order); /* Need to truncate digest if it is too long: first truncate whole * bytes. */ if (8 * dgst_len > i) dgst_len = (i + 7)/8; if (!BN_bin2bn(dgst, dgst_len, m)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* If still too long truncate remaining bits with a shift */ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* u1 = m * tmp mod order */ if (!BN_mod_mul(u1, m, u2, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* u2 = r * w mod q */ if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if ((point = EC_POINT_new(group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); 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, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } #ifndef OPENSSL_NO_EC2M else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(group, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } #endif if (!BN_nnmod(u1, X, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* if the signature is correct u1 is equal to sig->r */ ret = (BN_ucmp(u1, sig->r) == 0); err: BN_CTX_end(ctx); BN_CTX_free(ctx); if (point) EC_POINT_free(point); return ret; }
int ec_key_simple_check_key(const EC_KEY *eckey) { int ok = 0; BN_CTX *ctx = NULL; const BIGNUM *order = NULL; EC_POINT *point = NULL; if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_AT_INFINITY); goto err; } if ((ctx = BN_CTX_new()) == NULL) goto err; if ((point = EC_POINT_new(eckey->group)) == NULL) goto err; /* testing whether the pub_key is on the elliptic curve */ if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); goto err; } /* testing whether pub_key * order is the point at infinity */ order = eckey->group->order; if (BN_is_zero(order)) { ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_GROUP_ORDER); goto err; } if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB); goto err; } if (!EC_POINT_is_at_infinity(eckey->group, point)) { ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER); goto err; } /* * in case the priv_key is present : check if generator * priv_key == * pub_key */ if (eckey->priv_key != NULL) { if (BN_cmp(eckey->priv_key, order) >= 0) { ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER); goto err; } if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) { ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB); goto err; } if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); goto err; } } ok = 1; err: BN_CTX_free(ctx); EC_POINT_free(point); return ok; }
/* 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 = OPENSSL_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: 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); }
int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y) { BN_CTX *ctx = NULL; BIGNUM *tx, *ty; EC_POINT *point = NULL; int ok = 0; #ifndef OPENSSL_NO_EC2M int tmp_nid, is_char_two = 0; #endif if (key == NULL || key->group == NULL || x == NULL || y == NULL) { ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER); return 0; } ctx = BN_CTX_new(); if (ctx == NULL) return 0; BN_CTX_start(ctx); point = EC_POINT_new(key->group); if (point == NULL) goto err; tx = BN_CTX_get(ctx); ty = BN_CTX_get(ctx); if (ty == NULL) goto err; #ifndef OPENSSL_NO_EC2M tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group)); if (tmp_nid == NID_X9_62_characteristic_two_field) is_char_two = 1; if (is_char_two) { if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point, x, y, ctx)) goto err; if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point, tx, ty, ctx)) goto err; } else #endif { if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, ctx)) goto err; if (!EC_POINT_get_affine_coordinates_GFp(key->group, point, tx, ty, ctx)) goto err; } /* * Check if retrieved coordinates match originals and are less than field * order: if not values are out of range. */ if (BN_cmp(x, tx) || BN_cmp(y, ty) || (BN_cmp(x, key->group->field) >= 0) || (BN_cmp(y, key->group->field) >= 0)) { ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, EC_R_COORDINATES_OUT_OF_RANGE); goto err; } if (!EC_KEY_set_public_key(key, point)) goto err; if (EC_KEY_check_key(key) == 0) goto err; ok = 1; err: BN_CTX_end(ctx); BN_CTX_free(ctx); EC_POINT_free(point); return ok; }
static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) { EC_GROUP *group = NULL; EC_POINT *P = NULL; BN_CTX *ctx = NULL; BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL; int ok = 0; unsigned param_len; const EC_METHOD *meth; const struct curve_data *data; const uint8_t *params; if ((ctx = BN_CTX_new()) == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); goto err; } data = curve->data; param_len = data->param_len; params = data->data; if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) || !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) || !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } if (curve->method != 0) { meth = curve->method(); if (((group = ec_group_new(meth)) == NULL) || (!(group->meth->group_set_curve(group, p, a, b, ctx)))) { OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); goto err; } } else { if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); goto err; } } if ((P = EC_POINT_new(group)) == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); goto err; } if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) || !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) { OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); goto err; } if (!BN_bin2bn(params + 5 * param_len, param_len, &group->order) || !BN_set_word(&group->cofactor, (BN_ULONG)data->cofactor)) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } group->generator = P; P = NULL; ok = 1; err: if (!ok) { EC_GROUP_free(group); group = NULL; } EC_POINT_free(P); BN_CTX_free(ctx); BN_free(p); BN_free(a); BN_free(b); BN_free(x); BN_free(y); return group; }
EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) { if (dest == NULL || src == NULL) { ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER); return NULL; } if (src->meth != dest->meth) { if (dest->meth->finish != NULL) dest->meth->finish(dest); if (dest->group && dest->group->meth->keyfinish) dest->group->meth->keyfinish(dest); #ifndef OPENSSL_NO_ENGINE if (ENGINE_finish(dest->engine) == 0) return 0; dest->engine = NULL; #endif } /* copy the parameters */ if (src->group != NULL) { const EC_METHOD *meth = EC_GROUP_method_of(src->group); /* clear the old group */ EC_GROUP_free(dest->group); dest->group = EC_GROUP_new(meth); if (dest->group == NULL) return NULL; if (!EC_GROUP_copy(dest->group, src->group)) return NULL; /* copy the public key */ if (src->pub_key != NULL) { EC_POINT_free(dest->pub_key); dest->pub_key = EC_POINT_new(src->group); if (dest->pub_key == NULL) return NULL; if (!EC_POINT_copy(dest->pub_key, src->pub_key)) return NULL; } /* copy the private key */ if (src->priv_key != NULL) { if (dest->priv_key == NULL) { dest->priv_key = BN_new(); if (dest->priv_key == NULL) return NULL; } if (!BN_copy(dest->priv_key, src->priv_key)) return NULL; if (src->group->meth->keycopy && src->group->meth->keycopy(dest, src) == 0) return NULL; } } /* copy the rest */ dest->enc_flag = src->enc_flag; dest->conv_form = src->conv_form; dest->version = src->version; dest->flags = src->flags; if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, &dest->ex_data, &src->ex_data)) return NULL; if (src->meth != dest->meth) { #ifndef OPENSSL_NO_ENGINE if (src->engine != NULL && ENGINE_init(src->engine) == 0) return NULL; dest->engine = src->engine; #endif dest->meth = src->meth; } if (src->meth->copy != NULL && src->meth->copy(dest, src) == 0) return NULL; return dest; }
/* * compute a "random" secret point on an elliptic curve based * on the password and identities. */ int compute_password_element(EAP_PWD_group *grp, u16 num, u8 *password, int password_len, u8 *id_server, int id_server_len, u8 *id_peer, int id_peer_len, u8 *token) { BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL; struct crypto_hash *hash; unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr; int nid, is_odd, ret = 0; size_t primebytelen, primebitlen; switch (num) { /* from IANA registry for IKE D-H groups */ case 19: nid = NID_X9_62_prime256v1; break; case 20: nid = NID_secp384r1; break; case 21: nid = NID_secp521r1; break; case 25: nid = NID_X9_62_prime192v1; break; case 26: nid = NID_secp224r1; break; default: wpa_printf(MSG_INFO, "EAP-pwd: unsupported group %d", num); return -1; } grp->pwe = NULL; grp->order = NULL; grp->prime = NULL; if ((grp->group = EC_GROUP_new_by_curve_name(nid)) == NULL) { wpa_printf(MSG_INFO, "EAP-pwd: unable to create EC_GROUP"); goto fail; } if (((rnd = BN_new()) == NULL) || ((cofactor = BN_new()) == NULL) || ((grp->pwe = EC_POINT_new(grp->group)) == NULL) || ((grp->order = BN_new()) == NULL) || ((grp->prime = BN_new()) == NULL) || ((x_candidate = BN_new()) == NULL)) { wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums"); goto fail; } if (!EC_GROUP_get_curve_GFp(grp->group, grp->prime, NULL, NULL, NULL)) { wpa_printf(MSG_INFO, "EAP-pwd: unable to get prime for GFp " "curve"); goto fail; } if (!EC_GROUP_get_order(grp->group, grp->order, NULL)) { wpa_printf(MSG_INFO, "EAP-pwd: unable to get order for curve"); goto fail; } if (!EC_GROUP_get_cofactor(grp->group, cofactor, NULL)) { wpa_printf(MSG_INFO, "EAP-pwd: unable to get cofactor for " "curve"); goto fail; } primebitlen = BN_num_bits(grp->prime); primebytelen = BN_num_bytes(grp->prime); if ((prfbuf = os_malloc(primebytelen)) == NULL) { wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf " "buffer"); goto fail; } os_memset(prfbuf, 0, primebytelen); ctr = 0; while (1) { if (ctr > 30) { wpa_printf(MSG_INFO, "EAP-pwd: unable to find random " "point on curve for group %d, something's " "fishy", num); goto fail; } ctr++; /* * compute counter-mode password value and stretch to prime * pwd-seed = H(token | peer-id | server-id | password | * counter) */ hash = eap_pwd_h_init(); if (hash == NULL) goto fail; eap_pwd_h_update(hash, token, sizeof(u32)); eap_pwd_h_update(hash, id_peer, id_peer_len); eap_pwd_h_update(hash, id_server, id_server_len); eap_pwd_h_update(hash, password, password_len); eap_pwd_h_update(hash, &ctr, sizeof(ctr)); eap_pwd_h_final(hash, pwe_digest); BN_bin2bn(pwe_digest, SHA256_MAC_LEN, rnd); if (eap_pwd_kdf(pwe_digest, SHA256_MAC_LEN, (u8 *) "EAP-pwd Hunting And Pecking", os_strlen("EAP-pwd Hunting And Pecking"), prfbuf, primebitlen) < 0) goto fail; BN_bin2bn(prfbuf, primebytelen, x_candidate); /* * eap_pwd_kdf() returns a string of bits 0..primebitlen but * BN_bin2bn will treat that string of bits as a big endian * number. If the primebitlen is not an even multiple of 8 * then excessive bits-- those _after_ primebitlen-- so now * we have to shift right the amount we masked off. */ if (primebitlen % 8) BN_rshift(x_candidate, x_candidate, (8 - (primebitlen % 8))); if (BN_ucmp(x_candidate, grp->prime) >= 0) continue; wpa_hexdump(MSG_DEBUG, "EAP-pwd: x_candidate", prfbuf, primebytelen); /* * need to unambiguously identify the solution, if there is * one... */ if (BN_is_odd(rnd)) is_odd = 1; else is_odd = 0; /* * solve the quadratic equation, if it's not solvable then we * don't have a point */ if (!EC_POINT_set_compressed_coordinates_GFp(grp->group, grp->pwe, x_candidate, is_odd, NULL)) continue; /* * If there's a solution to the equation then the point must be * on the curve so why check again explicitly? OpenSSL code * says this is required by X9.62. We're not X9.62 but it can't * hurt just to be sure. */ if (!EC_POINT_is_on_curve(grp->group, grp->pwe, NULL)) { wpa_printf(MSG_INFO, "EAP-pwd: point is not on curve"); continue; } if (BN_cmp(cofactor, BN_value_one())) { /* make sure the point is not in a small sub-group */ if (!EC_POINT_mul(grp->group, grp->pwe, NULL, grp->pwe, cofactor, NULL)) { wpa_printf(MSG_INFO, "EAP-pwd: cannot " "multiply generator by order"); continue; } if (EC_POINT_is_at_infinity(grp->group, grp->pwe)) { wpa_printf(MSG_INFO, "EAP-pwd: point is at " "infinity"); continue; } } /* if we got here then we have a new generator. */ break; } wpa_printf(MSG_DEBUG, "EAP-pwd: found a PWE in %d tries", ctr); grp->group_num = num; if (0) { fail: EC_GROUP_free(grp->group); grp->group = NULL; EC_POINT_free(grp->pwe); grp->pwe = NULL; BN_free(grp->order); grp->order = NULL; BN_free(grp->prime); grp->prime = NULL; ret = 1; } /* cleanliness and order.... */ BN_free(cofactor); BN_free(x_candidate); BN_free(rnd); os_free(prfbuf); return ret; }
/* * Computes gost2001 signature as DSA_SIG structure * * */ DSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey) { DSA_SIG *newsig = NULL, *ret = NULL; BIGNUM *md = hashsum2bn(dgst); BIGNUM *order = NULL; const EC_GROUP *group; const BIGNUM *priv_key; BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL, *k = NULL, *e = NULL; EC_POINT *C = NULL; BN_CTX *ctx = BN_CTX_new(); if (!ctx || !md) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } BN_CTX_start(ctx); OPENSSL_assert(dlen == 32); newsig = DSA_SIG_new(); if (!newsig) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } group = EC_KEY_get0_group(eckey); if (!group) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); goto err; } order = BN_CTX_get(ctx); if (!order || !EC_GROUP_get_order(group, order, ctx)) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); goto err; } priv_key = EC_KEY_get0_private_key(eckey); if (!priv_key) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); goto err; } e = BN_CTX_get(ctx); if (!e || !BN_mod(e, md, order, ctx)) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); goto err; } #ifdef DEBUG_SIGN fprintf(stderr, "digest as bignum="); BN_print_fp(stderr, md); fprintf(stderr, "\ndigest mod q="); BN_print_fp(stderr, e); fprintf(stderr, "\n"); #endif if (BN_is_zero(e)) { BN_one(e); } k = BN_CTX_get(ctx); C = EC_POINT_new(group); if (!k || !C) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } do { do { if (!BN_rand_range(k, order)) { GOSTerr(GOST_F_GOST2001_DO_SIGN, GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); goto err; } if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); goto err; } if (!X) X = BN_CTX_get(ctx); if (!r) r = BN_CTX_get(ctx); if (!X || !r) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); goto err; } if (!BN_nnmod(r, X, order, ctx)) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); goto err; } } while (BN_is_zero(r)); /* s = (r*priv_key+k*e) mod order */ if (!tmp) tmp = BN_CTX_get(ctx); if (!tmp2) tmp2 = BN_CTX_get(ctx); if (!s) s = BN_CTX_get(ctx); if (!tmp || !tmp2 || !s) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } if (!BN_mod_mul(tmp, priv_key, r, order, ctx) || !BN_mod_mul(tmp2, k, e, order, ctx) || !BN_mod_add(s, tmp, tmp2, order, ctx)) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); goto err; } } while (BN_is_zero(s)); newsig->s = BN_dup(s); newsig->r = BN_dup(r); if (!newsig->s || !newsig->r) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } ret = newsig; err: if (ctx) BN_CTX_end(ctx); BN_CTX_free(ctx); EC_POINT_free(C); BN_free(md); if (!ret) DSA_SIG_free(newsig); return ret; }
// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields // recid selects which key is recovered // if check is non-zero, additional checks are performed int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check) { if (!eckey) return 0; int ret = 0; BN_CTX *ctx = NULL; BIGNUM *x = NULL; BIGNUM *e = NULL; BIGNUM *order = NULL; BIGNUM *sor = NULL; BIGNUM *eor = NULL; BIGNUM *field = NULL; EC_POINT *R = NULL; EC_POINT *O = NULL; EC_POINT *Q = NULL; BIGNUM *rr = NULL; BIGNUM *zero = NULL; int n = 0; int i = recid / 2; const EC_GROUP *group = EC_KEY_get0_group(eckey); if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; } BN_CTX_start(ctx); order = BN_CTX_get(ctx); if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; } x = BN_CTX_get(ctx); if (!BN_copy(x, order)) { ret=-1; goto err; } if (!BN_mul_word(x, i)) { ret=-1; goto err; } if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; } field = BN_CTX_get(ctx); if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; } if (BN_cmp(x, field) >= 0) { ret=0; goto err; } if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; } if (check) { if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; } if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; } } if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } n = EC_GROUP_get_degree(group); e = BN_CTX_get(ctx); if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; } if (8*msglen > n) BN_rshift(e, e, 8-(n & 7)); zero = BN_CTX_get(ctx); if (!BN_zero(zero)) { ret=-1; goto err; } if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; } rr = BN_CTX_get(ctx); if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; } sor = BN_CTX_get(ctx); if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; } eor = BN_CTX_get(ctx); if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; } if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; } if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; } ret = 1; err: if (ctx) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (R != NULL) EC_POINT_free(R); if (O != NULL) EC_POINT_free(O); if (Q != NULL) EC_POINT_free(Q); return ret; }
/* * Verifies gost 2001 signature * */ int gost2001_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, EC_KEY *ec) { BN_CTX *ctx = BN_CTX_new(); const EC_GROUP *group = EC_KEY_get0_group(ec); BIGNUM *order; BIGNUM *md = NULL, *e = NULL, *R = NULL, *v = NULL, *z1 = NULL, *z2 = NULL; BIGNUM *X = NULL, *tmp = NULL; EC_POINT *C = NULL; const EC_POINT *pub_key = NULL; int ok = 0; if (!ctx || !group) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); goto err; } BN_CTX_start(ctx); order = BN_CTX_get(ctx); e = BN_CTX_get(ctx); z1 = BN_CTX_get(ctx); z2 = BN_CTX_get(ctx); tmp = BN_CTX_get(ctx); X = BN_CTX_get(ctx); R = BN_CTX_get(ctx); v = BN_CTX_get(ctx); if (!order || !e || !z1 || !z2 || !tmp || !X || !R || !v) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } pub_key = EC_KEY_get0_public_key(ec); if (!pub_key || !EC_GROUP_get_order(group, order, ctx)) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); goto err; } if (BN_is_zero(sig->s) || BN_is_zero(sig->r) || (BN_cmp(sig->s, order) >= 1) || (BN_cmp(sig->r, order) >= 1)) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); goto err; } md = hashsum2bn(dgst); if (!md || !BN_mod(e, md, order, ctx)) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); goto err; } #ifdef DEBUG_SIGN fprintf(stderr, "digest as bignum: "); BN_print_fp(stderr, md); fprintf(stderr, "\ndigest mod q: "); BN_print_fp(stderr, e); #endif if (BN_is_zero(e) && !BN_one(e)) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); goto err; } v = BN_mod_inverse(v, e, order, ctx); if (!v || !BN_mod_mul(z1, sig->s, v, order, ctx) || !BN_sub(tmp, order, sig->r) || !BN_mod_mul(z2, tmp, v, order, ctx)) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); goto err; } #ifdef DEBUG_SIGN fprintf(stderr, "\nInverted digest value: "); BN_print_fp(stderr, v); fprintf(stderr, "\nz1: "); BN_print_fp(stderr, z1); fprintf(stderr, "\nz2: "); BN_print_fp(stderr, z2); #endif C = EC_POINT_new(group); if (!C) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (!BN_mod(R, X, order, ctx)) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); goto err; } #ifdef DEBUG_SIGN fprintf(stderr, "\nX="); BN_print_fp(stderr, X); fprintf(stderr, "\nX mod q="); BN_print_fp(stderr, R); fprintf(stderr, "\n"); #endif if (BN_cmp(R, sig->r) != 0) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); } else { ok = 1; } err: EC_POINT_free(C); if (ctx) BN_CTX_end(ctx); BN_CTX_free(ctx); BN_free(md); return ok; }
int EC_KEY_generate_key(EC_KEY *eckey) { int ok = 0; BN_CTX *ctx = NULL; BIGNUM *priv_key = NULL, *order = NULL; EC_POINT *pub_key = NULL; #ifdef OPENSSL_FIPS if (FIPS_mode()) return FIPS_ec_key_generate_key(eckey); #endif if (!eckey || !eckey->group) { ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); return 0; } if ((order = BN_new()) == NULL) goto err; if ((ctx = BN_CTX_new()) == NULL) goto err; if (eckey->priv_key == NULL) { priv_key = BN_new(); if (priv_key == NULL) goto err; } else priv_key = eckey->priv_key; if (!EC_GROUP_get_order(eckey->group, order, ctx)) goto err; do if (!BN_rand_range(priv_key, order)) goto err; while (BN_is_zero(priv_key)); if (eckey->pub_key == NULL) { pub_key = EC_POINT_new(eckey->group); if (pub_key == NULL) goto err; } else pub_key = eckey->pub_key; if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) goto err; eckey->priv_key = priv_key; eckey->pub_key = pub_key; ok=1; err: if (order) BN_free(order); if (pub_key != NULL && eckey->pub_key == NULL) EC_POINT_free(pub_key); if (priv_key != NULL && eckey->priv_key == NULL) BN_free(priv_key); if (ctx != NULL) BN_CTX_free(ctx); return(ok); }
int process_peer_commit(REQUEST *request, pwd_session_t *session, uint8_t *in, size_t in_len, BN_CTX *bn_ctx) { uint8_t *ptr; size_t data_len; BIGNUM *x = NULL, *y = NULL, *cofactor = NULL; EC_POINT *K = NULL, *point = NULL; int ret = 1; MEM(session->peer_scalar = BN_new()); MEM(session->k = BN_new()); MEM(session->peer_element = EC_POINT_new(session->group)); MEM(point = EC_POINT_new(session->group)); MEM(K = EC_POINT_new(session->group)); MEM(cofactor = BN_new()); MEM(x = BN_new()); MEM(y = BN_new()); if (!EC_GROUP_get_cofactor(session->group, cofactor, NULL)) { REDEBUG("Unable to get group co-factor"); goto finish; } /* element, x then y, followed by scalar */ ptr = (uint8_t *)in; data_len = BN_num_bytes(session->prime); /* * Did the peer send enough data? */ if (in_len < (2 * data_len + BN_num_bytes(session->order))) { REDEBUG("Invalid commit packet"); goto finish; } BN_bin2bn(ptr, data_len, x); ptr += data_len; BN_bin2bn(ptr, data_len, y); ptr += data_len; data_len = BN_num_bytes(session->order); BN_bin2bn(ptr, data_len, session->peer_scalar); /* validate received scalar */ if (BN_is_zero(session->peer_scalar) || BN_is_one(session->peer_scalar) || BN_cmp(session->peer_scalar, session->order) >= 0) { REDEBUG("Peer's scalar is not within the allowed range"); goto finish; } if (!EC_POINT_set_affine_coordinates_GFp(session->group, session->peer_element, x, y, bn_ctx)) { REDEBUG("Unable to get coordinates of peer's element"); goto finish; } /* validate received element */ if (!EC_POINT_is_on_curve(session->group, session->peer_element, bn_ctx) || EC_POINT_is_at_infinity(session->group, session->peer_element)) { REDEBUG("Peer's element is not a point on the elliptic curve"); goto finish; } /* check to ensure peer's element is not in a small sub-group */ if (BN_cmp(cofactor, BN_value_one())) { if (!EC_POINT_mul(session->group, point, NULL, session->peer_element, cofactor, NULL)) { REDEBUG("Unable to multiply element by co-factor"); goto finish; } if (EC_POINT_is_at_infinity(session->group, point)) { REDEBUG("Peer's element is in small sub-group"); goto finish; } } /* detect reflection attacks */ if (BN_cmp(session->peer_scalar, session->my_scalar) == 0 || EC_POINT_cmp(session->group, session->peer_element, session->my_element, bn_ctx) == 0) { REDEBUG("Reflection attack detected"); goto finish; } /* compute the shared key, k */ if ((!EC_POINT_mul(session->group, K, NULL, session->pwe, session->peer_scalar, bn_ctx)) || (!EC_POINT_add(session->group, K, K, session->peer_element, bn_ctx)) || (!EC_POINT_mul(session->group, K, NULL, K, session->private_value, bn_ctx))) { REDEBUG("Unable to compute shared key, k"); goto finish; } /* ensure that the shared key isn't in a small sub-group */ if (BN_cmp(cofactor, BN_value_one())) { if (!EC_POINT_mul(session->group, K, NULL, K, cofactor, NULL)) { REDEBUG("Unable to multiply k by co-factor"); goto finish; } } /* * This check is strictly speaking just for the case above where * co-factor > 1 but it was suggested that even though this is probably * never going to happen it is a simple and safe check "just to be * sure" so let's be safe. */ if (EC_POINT_is_at_infinity(session->group, K)) { REDEBUG("K is point-at-infinity"); goto finish; } if (!EC_POINT_get_affine_coordinates_GFp(session->group, K, session->k, NULL, bn_ctx)) { REDEBUG("Unable to get shared secret from K"); goto finish; } ret = 0; finish: EC_POINT_clear_free(K); EC_POINT_clear_free(point); BN_clear_free(cofactor); BN_clear_free(x); BN_clear_free(y); return ret; }