static EC_KEY *extract_ec_pub_key(CPK_PUBLIC_PARAMS *param, const char *id) { int e = 1; EC_KEY *ec_key = NULL; const EC_GROUP *ec_group; EC_POINT *pub_key = NULL; EC_POINT *pt = NULL; BIGNUM *order = BN_new(); BIGNUM *bn = BN_new(); BN_CTX *ctx = BN_CTX_new(); int *index = NULL; int i, bn_size, pt_size, num_indexes, num_factors; if (!(ec_key = X509_ALGOR_get1_EC_KEY(param->pkey_algor))) { goto err; } ec_group = EC_KEY_get0_group(ec_key); if (!(pub_key = EC_POINT_new(ec_group))) { goto err; } if (!(pt = EC_POINT_new(ec_group))) { goto err; } if (!EC_GROUP_get_order(ec_group, order, ctx)) { goto err; } bn_size = BN_num_bytes(order); pt_size = bn_size + 1; if ((num_factors = CPK_MAP_num_factors(param->map_algor)) <= 0) { goto err; } if (M_ASN1_STRING_length(param->public_factors) != pt_size * num_factors) { goto err; } if ((num_indexes = CPK_MAP_num_indexes(param->map_algor)) <= 0) { goto err; } if (!(index = OPENSSL_malloc(sizeof(int) * num_indexes))) { goto err; } if (!CPK_MAP_str2index(param->map_algor, id, index)) { goto err; } if (!EC_POINT_set_to_infinity(ec_group, pub_key)) { goto err; } for (i = 0; i < num_indexes; i++) { const unsigned char *p = M_ASN1_STRING_data(param->public_factors) + pt_size * index[i]; if (!EC_POINT_oct2point(ec_group, pt, p, pt_size, ctx)) { goto err; } if (!EC_POINT_add(ec_group, pub_key, pub_key, pt, ctx)) { goto err; } } if (!EC_KEY_set_public_key(ec_key, pub_key)) { goto err; } e = 0; err: if (e && ec_key) { EC_KEY_free(ec_key); ec_key = NULL; } if (pub_key) EC_POINT_free(pub_key); if (order) BN_free(order); if (bn) BN_free(bn); if (ctx) BN_CTX_free(ctx); if (index) OPENSSL_free(index); return ec_key; }
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 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); EC_POINT_free(point); 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; 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(); BN_CTX_start(ctx); OPENSSL_assert(dlen==32); newsig=DSA_SIG_new(); if (!newsig) { GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_NO_MEMORY); goto err; } group = EC_KEY_get0_group(eckey); order=BN_CTX_get(ctx); EC_GROUP_get_order(group,order,ctx); priv_key = EC_KEY_get0_private_key(eckey); e = BN_CTX_get(ctx); BN_mod(e,md,order,ctx); #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); do { do { if (!BN_rand_range(k,order)) { GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); DSA_SIG_free(newsig); newsig = NULL; goto err; } if (!EC_POINT_mul(group,C,k,NULL,NULL,ctx)) { GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB); DSA_SIG_free(newsig); newsig = NULL; goto err; } if (!X) X=BN_CTX_get(ctx); if (!EC_POINT_get_affine_coordinates_GFp(group,C,X,NULL,ctx)) { GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB); DSA_SIG_free(newsig); newsig = NULL; goto err; } if (!r) r=BN_CTX_get(ctx); BN_nnmod(r,X,order,ctx); } while (BN_is_zero(r)); /* s = (r*priv_key+k*e) mod order */ if (!tmp) tmp = BN_CTX_get(ctx); BN_mod_mul(tmp,priv_key,r,order,ctx); if (!tmp2) tmp2 = BN_CTX_get(ctx); BN_mod_mul(tmp2,k,e,order,ctx); if (!s) s=BN_CTX_get(ctx); BN_mod_add(s,tmp,tmp2,order,ctx); } while (BN_is_zero(s)); newsig->s=BN_dup(s); newsig->r=BN_dup(r); err: BN_CTX_end(ctx); BN_CTX_free(ctx); EC_POINT_free(C); BN_free(md); return newsig; }
static CK_RV gostr3410_verify_data(const unsigned char *pubkey, int pubkey_len, const unsigned char *params, int params_len, unsigned char *data, int data_len, unsigned char *signat, int signat_len) { EVP_PKEY *pkey; EVP_PKEY_CTX *pkey_ctx = NULL; EC_POINT *P; BIGNUM *X, *Y; ASN1_OCTET_STRING *octet; const EC_GROUP *group = NULL; char paramset[2] = "A"; int r = -1, ret_vrf = 0; pkey = EVP_PKEY_new(); if (!pkey) return CKR_HOST_MEMORY; r = EVP_PKEY_set_type(pkey, NID_id_GostR3410_2001); if (r == 1) { pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL); if (!pkey_ctx) { EVP_PKEY_free(pkey); return CKR_HOST_MEMORY; } /* FIXME: fully check params[] */ if (params_len > 0 && params[params_len - 1] >= 1 && params[params_len - 1] <= 3) { paramset[0] += params[params_len - 1] - 1; r = EVP_PKEY_CTX_ctrl_str(pkey_ctx, "paramset", paramset); } else r = -1; if (r == 1) r = EVP_PKEY_paramgen_init(pkey_ctx); if (r == 1) r = EVP_PKEY_paramgen(pkey_ctx, &pkey); if (r == 1 && EVP_PKEY_get0(pkey) != NULL) group = EC_KEY_get0_group(EVP_PKEY_get0(pkey)); r = -1; if (group) octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey, (long)pubkey_len); if (group && octet) { reverse(octet->data, octet->length); Y = BN_bin2bn(octet->data, octet->length / 2, NULL); X = BN_bin2bn((const unsigned char*)octet->data + octet->length / 2, octet->length / 2, NULL); ASN1_OCTET_STRING_free(octet); P = EC_POINT_new(group); if (P && X && Y) r = EC_POINT_set_affine_coordinates_GFp(group, P, X, Y, NULL); BN_free(X); BN_free(Y); if (r == 1 && EVP_PKEY_get0(pkey) && P) r = EC_KEY_set_public_key(EVP_PKEY_get0(pkey), P); EC_POINT_free(P); } if (r == 1) { r = EVP_PKEY_verify_init(pkey_ctx); reverse(data, data_len); if (r == 1) ret_vrf = EVP_PKEY_verify(pkey_ctx, signat, signat_len, data, data_len); } } EVP_PKEY_CTX_free(pkey_ctx); EVP_PKEY_free(pkey); if (r != 1) return CKR_GENERAL_ERROR; return ret_vrf == 1 ? CKR_OK : CKR_SIGNATURE_INVALID; }
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, const uint8_t *digest, size_t digest_len) { 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) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { OPENSSL_PUT_ERROR(ECDSA, 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) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); goto err; } tmp_point = EC_POINT_new(group); if (tmp_point == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } do { /* If possible, we'll include the private key and message digest in the k * generation. The |digest| argument is only empty if |ECDSA_sign_setup| is * being used. */ do { int ok; if (digest_len > 0) { ok = BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey), digest, digest_len, ctx); } else { ok = BN_rand_range(k, order); } if (!ok) { OPENSSL_PUT_ERROR(ECDSA, 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)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, X, NULL, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!BN_nnmod(r, X, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(r)); /* compute the inverse of k */ if (!BN_mod_inverse(k, k, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } /* clear old values if necessary */ BN_clear_free(*rp); BN_clear_free(*kinvp); /* save the pre-computed values */ *rp = r; *kinvp = k; ret = 1; err: if (!ret) { BN_clear_free(k); BN_clear_free(r); } if (ctx_in == NULL) { BN_CTX_free(ctx); } BN_free(order); EC_POINT_free(tmp_point); BN_clear_free(X); return ret; }
EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) { EVP_PKEY *pkey = NULL; #ifndef OPENSSL_NO_RSA RSA *rsa = NULL; #endif #ifndef OPENSSL_NO_DSA DSA *dsa = NULL; ASN1_TYPE *t1, *t2; ASN1_INTEGER *privkey; STACK_OF(ASN1_TYPE) *ndsa = NULL; #endif #ifndef OPENSSL_NO_EC EC_KEY *eckey = NULL; const unsigned char *p_tmp; #endif #if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC) ASN1_TYPE *param = NULL; BN_CTX *ctx = NULL; int plen; #endif X509_ALGOR *a; const unsigned char *p; const unsigned char *cp; int pkeylen; int nid; char obj_tmp[80]; if(p8->pkey->type == V_ASN1_OCTET_STRING) { p8->broken = PKCS8_OK; p = p8->pkey->value.octet_string->data; pkeylen = p8->pkey->value.octet_string->length; } else { p8->broken = PKCS8_NO_OCTET; p = p8->pkey->value.sequence->data; pkeylen = p8->pkey->value.sequence->length; } if (!(pkey = EVP_PKEY_new())) { EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); return NULL; } a = p8->pkeyalg; nid = OBJ_obj2nid(a->algorithm); switch(nid) { #ifndef OPENSSL_NO_RSA case NID_rsaEncryption: cp = p; if (!(rsa = d2i_RSAPrivateKey (NULL,&cp, pkeylen))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); return NULL; } EVP_PKEY_assign_RSA (pkey, rsa); break; #endif #ifndef OPENSSL_NO_DSA case NID_dsa: /* PKCS#8 DSA is weird: you just get a private key integer * and parameters in the AlgorithmIdentifier the pubkey must * be recalculated. */ /* Check for broken DSA PKCS#8, UGH! */ if(*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) { if(!(ndsa = ASN1_seq_unpack_ASN1_TYPE(p, pkeylen, d2i_ASN1_TYPE, ASN1_TYPE_free))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } if(sk_ASN1_TYPE_num(ndsa) != 2 ) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } /* Handle Two broken types: * SEQUENCE {parameters, priv_key} * SEQUENCE {pub_key, priv_key} */ t1 = sk_ASN1_TYPE_value(ndsa, 0); t2 = sk_ASN1_TYPE_value(ndsa, 1); if(t1->type == V_ASN1_SEQUENCE) { p8->broken = PKCS8_EMBEDDED_PARAM; param = t1; } else if(a->parameter->type == V_ASN1_SEQUENCE) { p8->broken = PKCS8_NS_DB; param = a->parameter; } else { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } if(t2->type != V_ASN1_INTEGER) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } privkey = t2->value.integer; } else { if (!(privkey=d2i_ASN1_INTEGER (NULL, &p, pkeylen))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } param = p8->pkeyalg->parameter; } if (!param || (param->type != V_ASN1_SEQUENCE)) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } cp = p = param->value.sequence->data; plen = param->value.sequence->length; if (!(dsa = d2i_DSAparams (NULL, &cp, plen))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } /* We have parameters now set private key */ if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) { EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_DECODE_ERROR); goto dsaerr; } /* Calculate public key (ouch!) */ if (!(dsa->pub_key = BN_new())) { EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); goto dsaerr; } if (!(ctx = BN_CTX_new())) { EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); goto dsaerr; } if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) { EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_PUBKEY_ERROR); goto dsaerr; } EVP_PKEY_assign_DSA(pkey, dsa); BN_CTX_free (ctx); if(ndsa) sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); else ASN1_INTEGER_free(privkey); break; dsaerr: BN_CTX_free (ctx); sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); DSA_free(dsa); EVP_PKEY_free(pkey); return NULL; break; #endif #ifndef OPENSSL_NO_EC case NID_X9_62_id_ecPublicKey: p_tmp = p; /* extract the ec parameters */ param = p8->pkeyalg->parameter; if (!param || ((param->type != V_ASN1_SEQUENCE) && (param->type != V_ASN1_OBJECT))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto ecerr; } if (param->type == V_ASN1_SEQUENCE) { cp = p = param->value.sequence->data; plen = param->value.sequence->length; if (!(eckey = d2i_ECParameters(NULL, &cp, plen))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto ecerr; } } else { EC_GROUP *group; cp = p = param->value.object->data; plen = param->value.object->length; /* type == V_ASN1_OBJECT => the parameters are given * by an asn1 OID */ if ((eckey = EC_KEY_new()) == NULL) { EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_MALLOC_FAILURE); goto ecerr; } group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(a->parameter->value.object)); if (group == NULL) goto ecerr; EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); if (EC_KEY_set_group(eckey, group) == 0) goto ecerr; EC_GROUP_free(group); } /* We have parameters now set private key */ if (!d2i_ECPrivateKey(&eckey, &p_tmp, pkeylen)) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_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) { EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); goto ecerr; } if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) { EC_POINT_free(pub_key); EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); goto ecerr; } priv_key = EC_KEY_get0_private_key(eckey); if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) { EC_POINT_free(pub_key); EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); goto ecerr; } if (EC_KEY_set_public_key(eckey, pub_key) == 0) { EC_POINT_free(pub_key); EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); goto ecerr; } EC_POINT_free(pub_key); } EVP_PKEY_assign_EC_KEY(pkey, eckey); if (ctx) BN_CTX_free(ctx); break; ecerr: if (ctx) BN_CTX_free(ctx); if (eckey) EC_KEY_free(eckey); if (pkey) EVP_PKEY_free(pkey); return NULL; #endif default: EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); if (!a->algorithm) BUF_strlcpy (obj_tmp, "NULL", sizeof obj_tmp); else i2t_ASN1_OBJECT(obj_tmp, 80, a->algorithm); ERR_add_error_data(2, "TYPE=", obj_tmp); EVP_PKEY_free (pkey); return NULL; } return pkey; }
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->conv_form = src->conv_form; dest->version = src->version; return dest; }
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; 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 GOST_KEY_check_key(const GOST_KEY *key) { int ok = 0; BN_CTX *ctx = NULL; BIGNUM *order = NULL; EC_POINT *point = NULL; if (!key || !key->group || !key->pub_key) { GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (EC_POINT_is_at_infinity(key->group, key->pub_key)) { GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY); goto err; } if ((ctx = BN_CTX_new()) == NULL) goto err; if ((point = EC_POINT_new(key->group)) == NULL) goto err; /* testing whether the pub_key is on the elliptic curve */ if (EC_POINT_is_on_curve(key->group, key->pub_key, ctx) <= 0) { GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); goto err; } /* testing whether pub_key * order is the point at infinity */ if ((order = BN_new()) == NULL) goto err; if (!EC_GROUP_get_order(key->group, order, ctx)) { GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER); goto err; } if (!EC_POINT_mul(key->group, point, NULL, key->pub_key, order, ctx)) { GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, ERR_R_EC_LIB); goto err; } if (!EC_POINT_is_at_infinity(key->group, point)) { GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_WRONG_ORDER); goto err; } /* * in case the priv_key is present : check if generator * priv_key == * pub_key */ if (key->priv_key) { if (BN_cmp(key->priv_key, order) >= 0) { GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_WRONG_ORDER); goto err; } if (!EC_POINT_mul(key->group, point, key->priv_key, NULL, NULL, ctx)) { GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, ERR_R_EC_LIB); goto err; } if (EC_POINT_cmp(key->group, point, key->pub_key, ctx) != 0) { GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); goto err; } } ok = 1; err: BN_free(order); BN_CTX_free(ctx); EC_POINT_free(point); return (ok); }
static int ssl_ec_point_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret, size_t *out_secret_len, uint8_t *out_alert, const uint8_t *peer_key, size_t peer_key_len) { BIGNUM *private_key = (BIGNUM *)ctx->data; assert(private_key != NULL); *out_alert = SSL_AD_INTERNAL_ERROR; /* Set up a shared |BN_CTX| for all operations. */ BN_CTX *bn_ctx = BN_CTX_new(); if (bn_ctx == NULL) { return 0; } BN_CTX_start(bn_ctx); int ret = 0; EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid); EC_POINT *peer_point = NULL, *result = NULL; uint8_t *secret = NULL; if (group == NULL) { goto err; } /* Compute the x-coordinate of |peer_key| * |private_key|. */ peer_point = EC_POINT_new(group); result = EC_POINT_new(group); if (peer_point == NULL || result == NULL) { goto err; } BIGNUM *x = BN_CTX_get(bn_ctx); if (x == NULL) { goto err; } if (!EC_POINT_oct2point(group, peer_point, peer_key, peer_key_len, bn_ctx)) { *out_alert = SSL_AD_DECODE_ERROR; goto err; } if (!EC_POINT_mul(group, result, NULL, peer_point, private_key, bn_ctx) || !EC_POINT_get_affine_coordinates_GFp(group, result, x, NULL, bn_ctx)) { goto err; } /* Encode the x-coordinate left-padded with zeros. */ size_t secret_len = (EC_GROUP_get_degree(group) + 7) / 8; secret = OPENSSL_malloc(secret_len); if (secret == NULL || !BN_bn2bin_padded(secret, secret_len, x)) { goto err; } *out_secret = secret; *out_secret_len = secret_len; secret = NULL; ret = 1; err: EC_GROUP_free(group); EC_POINT_free(peer_point); EC_POINT_free(result); BN_CTX_end(bn_ctx); BN_CTX_free(bn_ctx); OPENSSL_free(secret); return ret; }
int GOST_KEY_set_public_key(GOST_KEY *key, const EC_POINT *pub_key) { EC_POINT_free(key->pub_key); key->pub_key = EC_POINT_dup(pub_key, key->group); return (key->pub_key == NULL) ? 0 : 1; }
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, const unsigned char *dgst, int dlen) { BN_CTX *ctx = NULL; BIGNUM *k = NULL, *r = NULL, *X = NULL; const BIGNUM *order; EC_POINT *tmp_point = NULL; const EC_GROUP *group; int ret = 0; int order_bits; if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (!EC_KEY_can_sign(eckey)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); return 0; } if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { ECerr(EC_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 */ X = BN_new(); if (k == NULL || r == NULL || X == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } if ((tmp_point = EC_POINT_new(group)) == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } order = EC_GROUP_get0_order(group); if (order == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } /* Preallocate space */ order_bits = BN_num_bits(order); if (!BN_set_bit(k, order_bits) || !BN_set_bit(r, order_bits) || !BN_set_bit(X, order_bits)) goto err; do { /* get random k */ do if (dgst != NULL) { if (!BN_generate_dsa_nonce (k, order, EC_KEY_get0_private_key(eckey), dgst, dlen, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } else { if (!BN_priv_rand_range(k, order)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } while (BN_is_zero(k)); /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { ECerr(EC_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)) { ECerr(EC_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)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } } #endif if (!BN_nnmod(r, X, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(r)); /* Check if optimized inverse is implemented */ if (EC_GROUP_do_inverse_ord(group, k, k, ctx) == 0) { /* compute the inverse of k */ if (group->mont_data != NULL) { /* * We want inverse in constant time, therefore we utilize the fact * order must be prime and use Fermats Little Theorem instead. */ if (!BN_set_word(X, 2)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } if (!BN_mod_sub(X, order, X, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } BN_set_flags(X, BN_FLG_CONSTTIME); if (!BN_mod_exp_mont_consttime(k, k, X, order, ctx, group->mont_data)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } else { if (!BN_mod_inverse(k, k, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } } /* clear old values if necessary */ BN_clear_free(*rp); BN_clear_free(*kinvp); /* save the pre-computed values */ *rp = r; *kinvp = k; ret = 1; err: if (!ret) { BN_clear_free(k); BN_clear_free(r); } if (ctx != ctx_in) BN_CTX_free(ctx); EC_POINT_free(tmp_point); BN_clear_free(X); 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; }
int StealthSecretSpend(ec_secret& scanSecret, ec_point& ephemPubkey, ec_secret& spendSecret, ec_secret& secretOut) { /* c = H(dP) R' = R + cG [without decrypting wallet] = (f + c)G [after decryption of wallet] Remember: mod curve.order, pad with 0x00s where necessary? */ int rv = 0; std::vector<uint8_t> vchOutP; BN_CTX* bnCtx = NULL; BIGNUM* bnScanSecret = NULL; BIGNUM* bnP = NULL; EC_POINT* P = NULL; BIGNUM* bnOutP = NULL; BIGNUM* bnc = NULL; BIGNUM* bnOrder = NULL; BIGNUM* bnSpend = NULL; EC_GROUP* ecgrp = EC_GROUP_new_by_curve_name(NID_secp256k1); if (!ecgrp) { printf("StealthSecretSpend(): EC_GROUP_new_by_curve_name failed.\n"); return 1; }; if (!(bnCtx = BN_CTX_new())) { printf("StealthSecretSpend(): BN_CTX_new failed.\n"); rv = 1; goto End; }; if (!(bnScanSecret = BN_bin2bn(&scanSecret.e[0], ec_secret_size, BN_new()))) { printf("StealthSecretSpend(): bnScanSecret BN_bin2bn failed.\n"); rv = 1; goto End; }; if (!(bnP = BN_bin2bn(&ephemPubkey[0], ephemPubkey.size(), BN_new()))) { printf("StealthSecretSpend(): bnP BN_bin2bn failed\n"); rv = 1; goto End; }; if (!(P = EC_POINT_bn2point(ecgrp, bnP, NULL, bnCtx))) { printf("StealthSecretSpend(): P EC_POINT_bn2point failed\n"); rv = 1; goto End; }; // -- dP if (!EC_POINT_mul(ecgrp, P, NULL, P, bnScanSecret, bnCtx)) { printf("StealthSecretSpend(): dP EC_POINT_mul failed\n"); rv = 1; goto End; }; if (!(bnOutP = EC_POINT_point2bn(ecgrp, P, POINT_CONVERSION_COMPRESSED, BN_new(), bnCtx))) { printf("StealthSecretSpend(): P EC_POINT_bn2point failed\n"); rv = 1; goto End; }; vchOutP.resize(ec_compressed_size); if (BN_num_bytes(bnOutP) != (int) ec_compressed_size || BN_bn2bin(bnOutP, &vchOutP[0]) != (int) ec_compressed_size) { printf("StealthSecretSpend(): bnOutP incorrect length.\n"); rv = 1; goto End; }; uint8_t hash1[32]; SHA256(&vchOutP[0], vchOutP.size(), (uint8_t*)hash1); if (!(bnc = BN_bin2bn(&hash1[0], 32, BN_new()))) { printf("StealthSecretSpend(): BN_bin2bn failed\n"); rv = 1; goto End; }; if (!(bnOrder = BN_new()) || !EC_GROUP_get_order(ecgrp, bnOrder, bnCtx)) { printf("StealthSecretSpend(): EC_GROUP_get_order failed\n"); rv = 1; goto End; }; if (!(bnSpend = BN_bin2bn(&spendSecret.e[0], ec_secret_size, BN_new()))) { printf("StealthSecretSpend(): bnSpend BN_bin2bn failed.\n"); rv = 1; goto End; }; //if (!BN_add(r, a, b)) return 0; //return BN_nnmod(r, r, m, ctx); if (!BN_mod_add(bnSpend, bnSpend, bnc, bnOrder, bnCtx)) { printf("StealthSecretSpend(): bnSpend BN_mod_add failed.\n"); rv = 1; goto End; }; if (BN_is_zero(bnSpend)) // possible? { printf("StealthSecretSpend(): bnSpend is zero.\n"); rv = 1; goto End; }; if (BN_num_bytes(bnSpend) != (int) ec_secret_size || BN_bn2bin(bnSpend, &secretOut.e[0]) != (int) ec_secret_size) { printf("StealthSecretSpend(): bnSpend incorrect length.\n"); rv = 1; goto End; }; End: if (bnSpend) BN_free(bnSpend); if (bnOrder) BN_free(bnOrder); if (bnc) BN_free(bnc); if (bnOutP) BN_free(bnOutP); if (P) EC_POINT_free(P); if (bnP) BN_free(bnP); if (bnScanSecret) BN_free(bnScanSecret); if (bnCtx) BN_CTX_free(bnCtx); EC_GROUP_free(ecgrp); return rv; };
int EC_KEY_check_key(const EC_KEY *eckey) { int ok = 0; BN_CTX *ctx = NULL; const BIGNUM *order = NULL; EC_POINT *point = NULL; if (!eckey || !eckey->group || !eckey->pub_key) { ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); return 0; } 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)) { ECerr(EC_F_EC_KEY_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_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_CHECK_KEY, ERR_R_EC_LIB); goto err; } if (!EC_POINT_is_at_infinity(eckey->group, point)) { ECerr(EC_F_EC_KEY_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) { if (BN_cmp(eckey->priv_key, order) >= 0) { ECerr(EC_F_EC_KEY_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_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_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); goto err; } } ok = 1; err: if (ctx != NULL) BN_CTX_free(ctx); if (point != NULL) EC_POINT_free(point); return(ok); }
int ECDSA_do_verify_point(const uint8_t *digest, size_t digest_len, const ECDSA_SIG *sig, const EC_GROUP *group, const EC_POINT *pub_key) { int ret = 0; BN_CTX *ctx; BIGNUM *order, *u1, *u2, *m, *X; EC_POINT *point = NULL; /* check input values */ ctx = BN_CTX_new(); if (!ctx) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); return 0; } 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 (order == NULL || u1 == NULL || u2 == NULL || m == NULL || X == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, 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) { OPENSSL_PUT_ERROR(ECDSA, 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)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } if (!digest_to_bn(m, digest, digest_len, order)) { goto err; } /* u1 = m * tmp mod order */ if (!BN_mod_mul(u1, m, u2, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } /* u2 = r * w mod q */ if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } point = EC_POINT_new(group); if (point == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!BN_nnmod(u1, X, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, 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); EC_POINT_free(point); return ret; }
/*- * This implementation is based on the following primitives in the IEEE 1363 standard: * - ECKAS-DH1 * - ECSVDP-DH * Finally an optional KDF is applied. */ int ossl_ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, const 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) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); /* sort of, * anyway */ return -1; } if (ecdh->group->meth->ecdh_compute_key != 0) return ecdh->group->meth->ecdh_compute_key(out, outlen, pub_key, ecdh, KDF); 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) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_NO_PRIVATE_VALUE); goto err; } group = EC_KEY_get0_group(ecdh); if (EC_KEY_get_flags(ecdh) & EC_FLAG_COFACTOR_ECDH) { if (!EC_GROUP_get_cofactor(group, x, NULL) || !BN_mul(x, x, priv_key, ctx)) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); goto err; } priv_key = x; } if ((tmp = EC_POINT_new(group)) == NULL) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_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)) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE); goto err; } } #ifndef OPENSSL_NO_EC2M else { if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx)) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE); goto err; } } #endif buflen = (EC_GROUP_get_degree(group) + 7) / 8; len = BN_num_bytes(x); if (len > buflen) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_INTERNAL_ERROR); goto err; } if ((buf = OPENSSL_malloc(buflen)) == NULL) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); goto err; } memset(buf, 0, buflen - len); if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_BN_LIB); goto err; } if (KDF != 0) { if (KDF(buf, buflen, out, &outlen) == NULL) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_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); OPENSSL_free(buf); return (ret); }
void vg_output_match_console(vg_context_t *vcp, EC_KEY *pkey, const char *pattern) { unsigned char key_buf[512], *pend; char addr_buf[64], addr2_buf[64]; char privkey_buf[VG_PROTKEY_MAX_B58]; const char *keytype = "Privkey"; int len; int isscript = (vcp->vc_format == VCF_SCRIPT); EC_POINT *ppnt; int free_ppnt = 0; if (vcp->vc_pubkey_base) { ppnt = EC_POINT_new(EC_KEY_get0_group(pkey)); EC_POINT_copy(ppnt, EC_KEY_get0_public_key(pkey)); EC_POINT_add(EC_KEY_get0_group(pkey), ppnt, ppnt, vcp->vc_pubkey_base, NULL); free_ppnt = 1; keytype = "PrivkeyPart"; } else { ppnt = (EC_POINT *) EC_KEY_get0_public_key(pkey); } assert(EC_KEY_check_key(pkey)); vg_encode_address(ppnt, EC_KEY_get0_group(pkey), vcp->vc_pubkeytype, addr_buf); if (isscript) vg_encode_script_address(ppnt, EC_KEY_get0_group(pkey), vcp->vc_addrtype, addr2_buf); if (vcp->vc_key_protect_pass) { len = vg_protect_encode_privkey(privkey_buf, pkey, vcp->vc_privtype, VG_PROTKEY_DEFAULT, vcp->vc_key_protect_pass); if (len) { keytype = "Protkey"; } else { fprintf(stderr, "ERROR: could not password-protect key\n"); vcp->vc_key_protect_pass = NULL; } } if (!vcp->vc_key_protect_pass) { vg_encode_privkey(pkey, vcp->vc_privtype, privkey_buf); } if (!vcp->vc_result_file || (vcp->vc_verbose > 0)) { printf("\r%79s\rPattern: %s\n", "", pattern); } if (vcp->vc_verbose > 0) { if (vcp->vc_verbose > 1) { pend = key_buf; len = i2o_ECPublicKey(pkey, &pend); printf("Pubkey (hex): "); dumphex(key_buf, len); printf("Privkey (hex): "); dumpbn(EC_KEY_get0_private_key(pkey)); pend = key_buf; len = i2d_ECPrivateKey(pkey, &pend); printf("Privkey (ASN1): "); dumphex(key_buf, len); } } if (!vcp->vc_result_file || (vcp->vc_verbose > 0)) { if (isscript) printf("P2SHAddress: %s\n", addr2_buf); printf("Address: %s\n" "%s: %s\n", addr_buf, keytype, privkey_buf); } if (vcp->vc_result_file) { FILE *fp = fopen(vcp->vc_result_file, "a"); if (!fp) { fprintf(stderr, "ERROR: could not open result file: %s\n", strerror(errno)); } else { fprintf(fp, "Pattern: %s\n" , pattern); if (isscript) fprintf(fp, "P2SHAddress: %s\n", addr2_buf); fprintf(fp, "Address: %s\n" "%s: %s\n", addr_buf, keytype, privkey_buf); fclose(fp); } } if (free_ppnt) EC_POINT_free(ppnt); }
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, const unsigned char *dgst, int dlen) { 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 (dgst != NULL) { if (!BN_generate_dsa_nonce (k, order, EC_KEY_get0_private_key(eckey), dgst, dlen, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } else { 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 (EC_GROUP_get_mont_data(group) != NULL) { /* * We want inverse in constant time, therefore we utilize the fact * order must be prime and use Fermats Little Theorem instead. */ if (!BN_set_word(X, 2)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } if (!BN_mod_sub(X, order, X, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } BN_set_flags(X, BN_FLG_CONSTTIME); if (!BN_mod_exp_mont_consttime (k, k, X, order, ctx, EC_GROUP_get_mont_data(group))) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } else { 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); EC_POINT_free(tmp_point); if (X) BN_clear_free(X); 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; 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); EC_GROUP_get_order(group,order,ctx); pub_key = EC_KEY_get0_public_key(ec); 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); BN_mod(e,md,order,ctx); #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); v=BN_mod_inverse(v,e,order,ctx); BN_mod_mul(z1,sig->s,v,order,ctx); BN_sub(tmp,order,sig->r); BN_mod_mul(z2,tmp,v,order,ctx); #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 (!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; } BN_mod(R,X,order,ctx); #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); BN_CTX_end(ctx); BN_CTX_free(ctx); BN_free(md); return ok; }
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 ((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)) || !(a = BN_bin2bn(params+1*param_len, param_len, NULL)) || !(b = BN_bin2bn(params+2*param_len, param_len, 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)) || !(y = BN_bin2bn(params+4*param_len, param_len, 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)) || !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; } if (P) EC_POINT_free(P); if (ctx) BN_CTX_free(ctx); if (p) BN_free(p); if (a) BN_free(a); if (b) BN_free(b); if (order) BN_free(order); if (x) BN_free(x); if (y) BN_free(y); return group; }
/*- * Computes the sum * scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*points[num-1] * gracefully ignoring NULL scalar values. */ int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx) { BN_CTX *new_ctx = NULL; int ret = 0; size_t i; EC_POINT *p = NULL; EC_POINT *acc = NULL; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } /* * This implementation is more efficient than the wNAF implementation for * 2 or fewer points. Use the ec_wNAF_mul implementation for 3 or more * points, or if we can perform a fast multiplication based on * precomputation. */ if ((scalar && (num > 1)) || (num > 2) || (num == 0 && EC_GROUP_have_precompute_mult(group))) { ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); goto err; } if ((p = EC_POINT_new(group)) == NULL) goto err; if ((acc = EC_POINT_new(group)) == NULL) goto err; if (!EC_POINT_set_to_infinity(group, acc)) goto err; if (scalar) { if (!ec_GF2m_montgomery_point_multiply (group, p, scalar, group->generator, ctx)) goto err; if (BN_is_negative(scalar)) if (!group->meth->invert(group, p, ctx)) goto err; if (!group->meth->add(group, acc, acc, p, ctx)) goto err; } for (i = 0; i < num; i++) { if (!ec_GF2m_montgomery_point_multiply (group, p, scalars[i], points[i], ctx)) goto err; if (BN_is_negative(scalars[i])) if (!group->meth->invert(group, p, ctx)) goto err; if (!group->meth->add(group, acc, acc, p, ctx)) goto err; } if (!EC_POINT_copy(r, acc)) goto err; ret = 1; err: if (p) EC_POINT_free(p); if (acc) EC_POINT_free(acc); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; }
int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, const EC_KEY *priv_key, void *(*kdf)(const void *in, size_t inlen, void *out, size_t *outlen)) { if (priv_key->priv_key == NULL) { OPENSSL_PUT_ERROR(ECDH, ECDH_R_NO_PRIVATE_VALUE); return -1; } const EC_SCALAR *const priv = &priv_key->priv_key->scalar; BN_CTX *ctx = BN_CTX_new(); if (ctx == NULL) { return -1; } BN_CTX_start(ctx); int ret = -1; size_t buflen = 0; uint8_t *buf = NULL; const EC_GROUP *const group = EC_KEY_get0_group(priv_key); EC_POINT *tmp = EC_POINT_new(group); if (tmp == NULL) { OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE); goto err; } if (!ec_point_mul_scalar(group, tmp, NULL, pub_key, priv, ctx)) { OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } BIGNUM *x = BN_CTX_get(ctx); if (!x) { OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, NULL, ctx)) { OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } buflen = (EC_GROUP_get_degree(group) + 7) / 8; buf = OPENSSL_malloc(buflen); if (buf == NULL) { OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE); goto err; } if (!BN_bn2bin_padded(buf, buflen, x)) { OPENSSL_PUT_ERROR(ECDH, ERR_R_INTERNAL_ERROR); goto err; } if (kdf != NULL) { if (kdf(buf, buflen, out, &outlen) == NULL) { OPENSSL_PUT_ERROR(ECDH, ECDH_R_KDF_FAILED); goto err; } } else { // no KDF, just copy as much as we can if (buflen < outlen) { outlen = buflen; } OPENSSL_memcpy(out, buf, outlen); } if (outlen > INT_MAX) { OPENSSL_PUT_ERROR(ECDH, ERR_R_OVERFLOW); goto err; } ret = (int)outlen; err: OPENSSL_free(buf); EC_POINT_free(tmp); BN_CTX_end(ctx); BN_CTX_free(ctx); return ret; }
/* * 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; }
/* creates a bitcoin address+private key from the SHA256 * hash of string. converts to base58 if base58 is 'true' * returns 1 if successful, 0 if not*/ int create_address_from_string(const unsigned char *string, unsigned char *address, unsigned char *priv_key, EC_GROUP *precompgroup, bool base58, bool debug) { u_int8_t * hash = malloc(SHA256_DIGEST_LENGTH); BIGNUM * n = BN_new(); //first we hash the string SHA256 (string, strlen(string), hash); //then we convert the hash to the BIGNUM n n = BN_bin2bn(hash, SHA256_DIGEST_LENGTH, n); BIGNUM * order = BN_new(); BIGNUM * nmodorder = BN_new(); BN_CTX *bnctx; bnctx = BN_CTX_new(); //then we create a new EC group with the curve secp256k1 EC_GROUP * pgroup; pgroup = EC_GROUP_new_by_curve_name(NID_secp256k1); if (!pgroup) { printf("ERROR: Couldn't get new group\n"); return 0; } //now we need to get the order of the group, and make sure that //the number we use for the private key is less than or equal to //the group order by using "nmodorder = n % order" EC_GROUP_get_order(pgroup, order, NULL); BN_mod(nmodorder, n, order, bnctx); if (BN_is_zero(nmodorder)) { printf("ERROR: SHA256(string) % order == 0. Pick another string.\n"); return 0; } if (debug) printf ("Secret number: %s\n", BN_bn2dec(nmodorder)); //now we create a new EC point, ecpoint, and place in it the secp256k1 //generator point multiplied by nmodorder. this newly created //point is the public key EC_POINT * ecpoint = EC_POINT_new(pgroup); if (!EC_POINT_mul(pgroup, ecpoint, nmodorder, NULL, NULL, NULL)) { printf("ERROR: Couldn't multiply the generator point with n\n"); return 0; } if (debug) { BIGNUM *x=NULL, *y=NULL; x=BN_new(); y=BN_new(); if (!EC_POINT_get_affine_coordinates_GFp(pgroup, ecpoint, x, y, NULL)) { printf("ERROR: Failed getting coordinates."); //don't fail on debug fail //return 0; } printf ("Public key coordinates. x: %s, y: %s\n", BN_bn2dec(x), BN_bn2dec(y)); BN_free(x); BN_free(y); } //then we need to convert the public key point to data //first we get the required size of the buffer in which the data is placed //by passing NULL as the buffer argument to EC_POINT_point2oct unsigned int bufsize = EC_POINT_point2oct (pgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); u_int8_t * buffer = malloc(bufsize); //then we place the data in the buffer int len = EC_POINT_point2oct (pgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, buffer, bufsize, NULL); if (len == 0) { printf("ERROR: Couldn't convert point to octet string."); return 0; } if (debug) { printf("DER encoded public key: "); print_hex(buffer, len); } //next we need to hash the public key data. first with SHA256, then with RIPEMD160 SHA256(buffer, len, hash); if (debug) { printf("SHA256 hash of public key: "); print_hex(hash, SHA256_DIGEST_LENGTH); } u_int8_t * ripemd = malloc(RIPEMD160_DIGEST_LENGTH+1+4); RIPEMD160(hash, SHA256_DIGEST_LENGTH, ripemd); if (debug) { printf("RIPEMD160 hash of SHA256 hash: "); print_hex(ripemd, RIPEMD160_DIGEST_LENGTH); } if (base58 == true) { //here we add the version byte to the beginning of the public key and four checksum //bytes at the end prepare_for_address(ripemd, RIPEMD160_DIGEST_LENGTH, 0); if (debug) { printf("Address in hex with version byte and checksum: "); print_hex(ripemd, RIPEMD160_DIGEST_LENGTH+1+4); } //and we convert the resulting data to base58 base58_encode(ripemd, RIPEMD160_DIGEST_LENGTH+1+4, address); } else { memcpy(address, ripemd, RIPEMD160_DIGEST_LENGTH); } //now we need to convert the big number nmodorder (private key) to data int buflen = BN_num_bytes(nmodorder); u_int8_t * buf = malloc(buflen+1+4); int datalen; //nmodorder is converted to binary representation datalen = BN_bn2bin(nmodorder, buf); if (debug) { printf("Private key: "); print_hex(buf, datalen); } if (base58 == true) { //and we add version byte and four byte checksum to the data prepare_for_address(buf, datalen, 0x80); //and convert this to base58 base58_encode(buf, datalen+5, priv_key); } else { memcpy(priv_key, buf, datalen+5); } free(hash); free(buffer); free(ripemd); free(buf); BN_free(n); BN_free(order); BN_free(nmodorder); if (precompgroup == NULL) EC_GROUP_free(pgroup); EC_POINT_free(ecpoint); BN_CTX_free(bnctx); return 1; }
// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields // recid selects which key is recovered // if check is nonzero, 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; }
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 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 */ BN_clear_free(*rp); BN_clear_free(*kinvp); /* save the pre-computed values */ *rp = r; *kinvp = k; ret = 1; err: if (!ret) { BN_clear_free(k); BN_clear_free(r); } if (ctx_in == NULL) BN_CTX_free(ctx); BN_free(order); EC_POINT_free(tmp_point); BN_clear_free(X); return(ret); }
static EC_KEY *extract_ec_priv_key(CPK_MASTER_SECRET *master, const char *id) { int e = 1; EC_KEY *ec_key = NULL; const EC_GROUP *ec_group; EC_POINT *pub_key = NULL; BIGNUM *priv_key = BN_new(); BIGNUM *order = BN_new(); BIGNUM *bn = BN_new(); BN_CTX *ctx = BN_CTX_new(); int *index = NULL; int i, num_indexes, bn_size; if (!priv_key || !bn || !order || !ctx) { goto err; } if (!(ec_key = X509_ALGOR_get1_EC_KEY(master->pkey_algor))) { goto err; } ec_group = EC_KEY_get0_group(ec_key); if (!(pub_key = EC_POINT_new(ec_group))) { goto err; } if ((num_indexes = CPK_MAP_num_indexes(master->map_algor)) <= 0) { goto err; } if (!(index = OPENSSL_malloc(sizeof(int) * num_indexes))) { goto err; } if (!CPK_MAP_str2index(master->map_algor, id, index)) { goto err; } BN_zero(priv_key); if (!(EC_GROUP_get_order(EC_KEY_get0_group(ec_key), order, ctx))) { goto err; } bn_size = BN_num_bytes(order); for (i = 0; i < num_indexes; i++) { const unsigned char *p = M_ASN1_STRING_data(master->secret_factors) + bn_size * index[i]; if (!BN_bin2bn(p, bn_size, bn)) { goto err; } if (BN_is_zero(bn) || BN_cmp(bn, order) >= 0) { goto err; } if (!BN_mod_add(priv_key, priv_key, bn, order, ctx)) { goto err; } } if (!EC_KEY_set_private_key(ec_key, priv_key)) { goto err; } if (!EC_POINT_mul(ec_group, pub_key, priv_key, NULL, NULL, ctx)) { goto err; } if (!EC_KEY_set_public_key(ec_key, pub_key)) { goto err; } e = 0; err: if (e && ec_key) { EC_KEY_free(ec_key); ec_key = NULL; } if (priv_key) BN_free(priv_key); if (pub_key) EC_POINT_free(pub_key); if (order) BN_free(order); if (bn) BN_free(bn); if (ctx) BN_CTX_free(ctx); if (index) OPENSSL_free(index); return ec_key; }