static int ec_get_pubkey(EC_KEY *key, BIGNUM *x, BIGNUM *y) { const EC_POINT *pt; const EC_GROUP *grp; const EC_METHOD *meth; int rv; BN_CTX *ctx; ctx = BN_CTX_new(); if (!ctx) return 0; grp = EC_KEY_get0_group(key); pt = EC_KEY_get0_public_key(key); meth = EC_GROUP_method_of(grp); if (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field) rv = EC_POINT_get_affine_coordinates_GFp(grp, pt, x, y, ctx); else # ifdef OPENSSL_NO_EC2M { fprintf(stderr, "ERROR: GF2m not supported\n"); exit(1); } # else rv = EC_POINT_get_affine_coordinates_GF2m(grp, pt, x, y, ctx); # endif BN_CTX_free(ctx); return rv; }
int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1, unsigned int *k2, unsigned int *k3) { if (group == NULL) return 0; if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != NID_X9_62_characteristic_two_field || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] != 0) && (group->poly[3] != 0) && (group->poly[4] == 0))) { ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (k1) *k1 = group->poly[3]; if (k2) *k2 = group->poly[2]; if (k3) *k3 = group->poly[1]; return 1; }
int EC_GROUP_get_trinomial_basis(const EC_GROUP * group, unsigned int *k) { if (group == NULL) return 0; if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != NID_X9_62_characteristic_two_field || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] == 0))) { ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (k) *k = group->poly[1]; return 1; }
/* For an EC key set TLS ID and required compression based on parameters. */ static int tls1_set_ec_id(uint16_t *curve_id, uint8_t *comp_id, EC_KEY *ec) { const EC_GROUP *grp; const EC_METHOD *meth; int is_prime = 0; int nid, id; if (ec == NULL) return (0); /* Determine if it is a prime field. */ if ((grp = EC_KEY_get0_group(ec)) == NULL) return (0); if ((meth = EC_GROUP_method_of(grp)) == NULL) return (0); if (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field) is_prime = 1; /* Determine curve ID. */ nid = EC_GROUP_get_curve_name(grp); id = tls1_ec_nid2curve_id(nid); /* If we have an ID set it, otherwise set arbitrary explicit curve. */ if (id != 0) *curve_id = id; else *curve_id = is_prime ? 0xff01 : 0xff02; /* Specify the compression identifier. */ if (comp_id != NULL) { if (EC_KEY_get0_public_key(ec) == NULL) return (0); if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_COMPRESSED) { *comp_id = is_prime ? TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime : TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; } else { *comp_id = TLSEXT_ECPOINTFORMAT_uncompressed; } } return (1); }
int EC_GROUP_get_basis_type(const EC_GROUP *group) { int i = 0; if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != NID_X9_62_characteristic_two_field) /* everything else is currently not supported */ return 0; while (group->poly[i] != 0) i++; if (i == 4) return NID_X9_62_ppBasis; else if (i == 2) return NID_X9_62_tpBasis; else /* everything else is currently not supported */ return 0; }
void Z_Gen(unsigned char *z, unsigned int klen, unsigned char *ID, unsigned char *x, unsigned char *y) { // Tsp 需要 // ZA=H256(ENTLA || IDA || a || b || xG || yG || xA || yA)。 BN_CTX *ctx = NULL; ctx = BN_CTX_new(); EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1); const EC_GROUP *ec_group = EC_KEY_get0_group(ec_key); BIGNUM *p = NULL, *a = NULL, *b = NULL, *gen = NULL, *order = NULL, *cofactor = NULL; if ((p = BN_new()) == NULL || (a = BN_new()) == NULL || (b = BN_new()) == NULL || (order = BN_new()) == NULL || (cofactor = BN_new()) == NULL) { goto err; } int is_char_two = 0; int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(ec_group)); if (tmp_nid == NID_X9_62_characteristic_two_field) is_char_two = 1; #ifndef OPENSSL_NO_EC2M if (is_char_two) { if (!EC_GROUP_get_curve_GF2m(ec_group, p, a, b, ctx)) { goto err; } } else /* prime field */ #endif { if (!EC_GROUP_get_curve_GFp(ec_group, p, a, b, ctx)) { goto err; } } const EC_POINT *generator = EC_GROUP_get0_generator(ec_group); unsigned char g[65]; EC_POINT_point2oct(ec_group, generator, POINT_CONVERSION_UNCOMPRESSED, g, ECDH_SIZE, NULL); sm3_ctx_t ctx2; sm3_init(&ctx2); unsigned char entla[2]; entla[0] = (klen / 32); entla[1] = (klen * 8); sm3_update(&ctx2, entla, sizeof(entla)); sm3_update(&ctx2, ID, klen); unsigned char buffer[32]; BN_bn2bin(a, buffer); sm3_update(&ctx2, buffer, 32); BN_bn2bin(b, buffer); sm3_update(&ctx2, buffer, 32); sm3_update(&ctx2, g + 1, 64); sm3_update(&ctx2, x, 32); sm3_update(&ctx2, y, 32); sm3_final(&ctx2, z); err: return; }
int main(int argc, char *argv[]) { void *bb; BN_CTX *ctx = NULL; int nid; BIO *out; CRYPTO_malloc_debug_init(); CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); const char *text = "NIST Prime-Curve P-192"; #ifdef OPENSSL_SYS_WIN32 CRYPTO_malloc_init(); #endif RAND_seed(rnd_seed, sizeof rnd_seed); out = BIO_new(BIO_s_file()); if (out == NULL) EXIT(1); BIO_set_fp(out, stdout, BIO_NOCLOSE); if ((ctx = BN_CTX_new()) == NULL) goto err; nid = NID_X9_62_prime192v1; //EC_POINT *bb; EC_KEY *a = NULL; //EC_KEY is a structure BIGNUM *x_a = NULL, *y_a = NULL; char buf[12]; //unsigned char *abuf=NULL,*bbuf=NULL; int i, alen, blen, aout, bout; const EC_GROUP *group; a = EC_KEY_new_by_curve_name(nid); if (a == NULL) goto err; group = EC_KEY_get0_group(a); if ((x_a = BN_new()) == NULL) goto err; //BN_new returns a pointer to the bignum if ((y_a = BN_new()) == NULL) goto err; BIO_puts(out, "Testing key generation with "); BIO_puts(out, text); if (!EC_KEY_generate_key(a)) goto err; printf("\n1 ) generating keys\n"); if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } //returns the public key else { if (!EC_POINT_get_affine_coordinates_GF2m(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } BIO_puts(out, " pri 1="); BN_print(out, EC_KEY_get0_private_key(a)); BIO_puts(out, "\n pub 1="); BN_print(out, x_a); BIO_puts(out, ","); BN_print(out, y_a); BIO_puts(out, "\n"); func(EC_KEY_get0_public_key(a)); err: ERR_print_errors_fp(stderr); if (x_a) BN_free(x_a); if (y_a) BN_free(y_a); if (a) EC_KEY_free(a); if (ctx) BN_CTX_free(ctx); BIO_free(out); CRYPTO_cleanup_all_ex_data(); ERR_remove_state(0); CRYPTO_mem_leaks_fp(stderr); return 0; }
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) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); 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 */ order = BN_new(); X = BN_new(); if (k == NULL || r == NULL || order == 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; } if (!EC_GROUP_get_order(group, order, ctx)) { ECerr(EC_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)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } else { if (!BN_rand_range(k, order)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_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)) { 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)); /* 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)) { 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, EC_GROUP_get_mont_data(group))) { 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); BN_free(order); EC_POINT_free(tmp_point); BN_clear_free(X); 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. */ static int ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen)) { BN_CTX *ctx; EC_POINT *tmp=NULL; BIGNUM *x=NULL, *y=NULL; const BIGNUM *priv_key; const EC_GROUP* group; int ret= -1; size_t buflen, len; unsigned char *buf=NULL; if (outlen > INT_MAX) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); /* sort of, anyway */ return -1; } if ((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); priv_key = EC_KEY_get0_private_key(ecdh); if (priv_key == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_NO_PRIVATE_VALUE); goto err; } group = EC_KEY_get0_group(ecdh); if ((tmp=EC_POINT_new(group)) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, y, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } #ifndef OPENSSL_NO_EC2M else { if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } #endif buflen = (EC_GROUP_get_degree(group) + 7)/8; len = BN_num_bytes(x); if (len > buflen) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_INTERNAL_ERROR); goto err; } if ((buf = malloc(buflen)) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); goto err; } memset(buf, 0, buflen - len); if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_BN_LIB); goto err; } if (KDF != 0) { if (KDF(buf, buflen, out, &outlen) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_KDF_FAILED); goto err; } ret = outlen; } else { /* no KDF, just copy as much as we can */ if (outlen > buflen) outlen = buflen; memcpy(out, buf, outlen); ret = outlen; } err: EC_POINT_free(tmp); if (ctx) BN_CTX_end(ctx); BN_CTX_free(ctx); free(buf); return(ret); }
static int 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; } #ifdef OPENSSL_FIPS if (!fips_check_ec_prng(eckey)) goto err; #endif 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)); #ifdef ECDSA_POINT_MUL_NO_CONSTTIME /* 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; #endif /* def(ECDSA_POINT_MUL_NO_CONSTTIME) */ /* 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); }
// unsigned char *rgbHashData, 哈希数值 // unsigned char *rgbKeyPb, SM2公钥数据,Px Py 不含标志位 point_conversion_form_t // unsigned char *rs 待验证的签名数据 unsigned char eccVerifySignature(unsigned char *rgbHashData, unsigned char *rgbKeyPb, unsigned char *rs) { int ret = SM2_VERIFY_INNER_ERROR; EC_POINT *point = NULL; BN_CTX *ctx = NULL; BIGNUM *order = NULL; BIGNUM *e = NULL; BIGNUM *t = NULL; int i; EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1); BIGNUM *x = BN_new();; BIGNUM *y = BN_new();; if (!BN_bin2bn(rgbKeyPb, 32, x)) { goto err; } if (!BN_bin2bn(rgbKeyPb + 32, 32, y)) { goto err; } if (!EC_KEY_set_public_key_affine_coordinates(ec_key, x, y)) { goto err; } const EC_POINT *pub_key = EC_KEY_get0_public_key(ec_key); BIGNUM *r= BN_new(), *s = BN_new(); BN_bin2bn(rs, 32, r); BN_bin2bn(rs + 32, 32, s); //// 相当于 //EC_KEY *ret = EC_KEY_new(); EC_GROUP *ec_group = EC_GROUP_new_by_curve_name(NID_sm2p256v1); ctx = BN_CTX_new(); order = BN_new(); e = BN_new(); t = BN_new(); if (!ctx || !order || !e || !t) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_GROUP_get_order(ec_group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } /* check r, s in [1, n-1] and r + s != 0 (mod n) */ if (BN_is_zero(r) || BN_is_negative(r) || BN_ucmp(r, order) >= 0 || BN_is_zero(s) || BN_is_negative(s) || BN_ucmp(s, order) >= 0) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE); ret = 0; goto err; } /* check t = r + s != 0 */ if (!BN_mod_add(t, r, s, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if (BN_is_zero(t)) { ret = 0; goto err; } /* convert digest to e */ i = BN_num_bits(order); #if 0 if (8 * dgstlen > i) { dgstlen = (i + 7)/8; } #endif if (!BN_bin2bn(rgbHashData, 32, e)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } #if 0 if ((8 * dgstlen > i) && !BN_rshift(e, e, 8 - (i & 0x7))) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } #endif /* compute (x, y) = sG + tP, P is pub_key */ if (!(point = EC_POINT_new(ec_group))) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(ec_group, point, s, pub_key, t, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(ec_group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(ec_group, point, t, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(ec_group, point, t, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } if (!BN_nnmod(t, t, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* check (sG + tP).x + e == sig.r */ if (!BN_mod_add(t, t, e, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if (BN_ucmp(t, r) == 0) { ret = SM2_VERIFY_SUCCESS; } else { ret = SM2_VERIFY_FAILED; } err: if (point) EC_POINT_free(point); if (order) BN_free(order); if (e) BN_free(e); if (t) BN_free(t); if (ctx) BN_CTX_free(ctx); return 0; }
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; }
int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) { int r = 0; BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; BN_CTX *ctx_new = NULL; /* compare the field types*/ if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != EC_METHOD_get_field_type(EC_GROUP_method_of(b))) return 1; /* compare the curve name (if present) */ if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && EC_GROUP_get_curve_name(a) == EC_GROUP_get_curve_name(b)) return 0; if (!ctx) ctx_new = ctx = BN_CTX_new(); if (!ctx) return -1; BN_CTX_start(ctx); a1 = BN_CTX_get(ctx); a2 = BN_CTX_get(ctx); a3 = BN_CTX_get(ctx); b1 = BN_CTX_get(ctx); b2 = BN_CTX_get(ctx); b3 = BN_CTX_get(ctx); if (!b3) { BN_CTX_end(ctx); if (ctx_new) BN_CTX_free(ctx); return -1; } /* XXX This approach assumes that the external representation * of curves over the same field type is the same. */ if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || !b->meth->group_get_curve(b, b1, b2, b3, ctx)) r = 1; if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) r = 1; /* XXX EC_POINT_cmp() assumes that the methods are equal */ if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), EC_GROUP_get0_generator(b), ctx)) r = 1; if (!r) { /* compare the order and cofactor */ if (!EC_GROUP_get_order(a, a1, ctx) || !EC_GROUP_get_order(b, b1, ctx) || !EC_GROUP_get_cofactor(a, a2, ctx) || !EC_GROUP_get_cofactor(b, b2, ctx)) { BN_CTX_end(ctx); if (ctx_new) BN_CTX_free(ctx); return -1; } if (BN_cmp(a1, b1) || BN_cmp(a2, b2)) r = 1; } BN_CTX_end(ctx); if (ctx_new) BN_CTX_free(ctx); return r; }
int SM2_do_decrypt(const EVP_MD *md, const SM2CiphertextValue *cv, unsigned char *out, size_t *outlen, EC_KEY *ec_key) { int ret = 0; const EC_GROUP *group; const BIGNUM *pri_key; KDF_FUNC kdf; EC_POINT *point = NULL; EC_POINT *tmp_point = NULL; BIGNUM *n = NULL; BIGNUM *h = NULL; BN_CTX *bn_ctx = NULL; EVP_MD_CTX *md_ctx = NULL; unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1]; unsigned char mac[EVP_MAX_MD_SIZE]; unsigned int maclen = sizeof(mac); int nbytes, len, i; /* check arguments */ if (!md || !cv || !outlen || !ec_key) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (!(kdf = KDF_get_x9_63(md))) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_DIGEST_ALGOR); return 0; } if (!cv->xCoordinate || !cv->yCoordinate || !cv->hash || !cv->ciphertext) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT); return 0; } if (cv->hash->length != EVP_MD_size(md)) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT); return 0; } if (cv->ciphertext->length < SM2_MIN_PLAINTEXT_LENGTH || cv->ciphertext->length > SM2_MAX_PLAINTEXT_LENGTH) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT); return 0; } if (!(group = EC_KEY_get0_group(ec_key)) || !(pri_key = EC_KEY_get0_private_key(ec_key))) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_EC_KEY); return 0; } if (!out) { *outlen = cv->ciphertext->length; return 1; } if (*outlen < cv->ciphertext->length) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_BUFFER_TOO_SMALL); return 0; } /* malloc */ point = EC_POINT_new(group); tmp_point = EC_POINT_new(group); n = BN_new(); h = BN_new(); bn_ctx = BN_CTX_new(); md_ctx = EVP_MD_CTX_new(); if (!point || !n || !h || !bn_ctx || !md_ctx) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_MALLOC_FAILURE); goto end; } /* init ec domain parameters */ if (!EC_GROUP_get_order(group, n, bn_ctx)) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB); goto end; } if (!EC_GROUP_get_cofactor(group, h, bn_ctx)) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB); goto end; } nbytes = (EC_GROUP_get_degree(group) + 7) / 8; /* get x/yCoordinates as C1 = (x1, y1) */ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_set_affine_coordinates_GFp(group, point, cv->xCoordinate, cv->yCoordinate, bn_ctx)) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT); goto end; } } else { if (!EC_POINT_set_affine_coordinates_GF2m(group, point, cv->xCoordinate, cv->yCoordinate, bn_ctx)) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT); goto end; } } /* check [h]C1 != O */ if (!EC_POINT_mul(group, tmp_point, NULL, point, h, bn_ctx)) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB); goto end; } if (EC_POINT_is_at_infinity(group, tmp_point)) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT); goto end; } /* compute ECDH [d]C1 = (x2, y2) */ if (!EC_POINT_mul(group, point, NULL, point, pri_key, bn_ctx)) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB); goto end; } if (!(len = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB); goto end; } /* compute t = KDF(x2 || y2, clen) */ *outlen = cv->ciphertext->length; kdf(buf + 1, len - 1, out, outlen); /* compute M = C2 xor t */ for (i = 0; i < cv->ciphertext->length; i++) { out[i] ^= cv->ciphertext->data[i]; } /* check hash == Hash(x2 || M || y2) */ if (!EVP_DigestInit_ex(md_ctx, md, NULL) || !EVP_DigestUpdate(md_ctx, buf + 1, nbytes) || !EVP_DigestUpdate(md_ctx, out, *outlen) || !EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes) || !EVP_DigestFinal_ex(md_ctx, mac, &maclen)) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EVP_LIB); goto end; } if (OPENSSL_memcmp(cv->hash->data, mac, maclen) != 0) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT); goto end; } ret = 1; end: EC_POINT_free(point); EC_POINT_free(tmp_point); BN_free(n); BN_free(h); BN_CTX_free(bn_ctx); EVP_MD_CTX_free(md_ctx); return ret; }
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)); /* 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; } } 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; } } 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); }
int ecparam_main(int argc, char **argv) { BIGNUM *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL; BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL; BIO *in = NULL, *out = NULL; EC_GROUP *group = NULL; point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; char *curve_name = NULL, *inrand = NULL; char *infile = NULL, *outfile = NULL, *prog; unsigned char *buffer = NULL; OPTION_CHOICE o; int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_asn1_flag = 0; int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0, ret = 1; int list_curves = 0, no_seed = 0, check = 0, new_form = 0; int text = 0, i, need_rand = 0, genkey = 0; prog = opt_init(argc, argv, ecparam_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(ecparam_options); ret = 0; goto end; case OPT_INFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) goto opthelp; break; case OPT_IN: infile = opt_arg(); break; case OPT_OUTFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) goto opthelp; break; case OPT_OUT: outfile = opt_arg(); break; case OPT_TEXT: text = 1; break; case OPT_C: C = 1; break; case OPT_CHECK: check = 1; break; case OPT_LIST_CURVES: list_curves = 1; break; case OPT_NO_SEED: no_seed = 1; break; case OPT_NOOUT: noout = 1; break; case OPT_NAME: curve_name = opt_arg(); break; case OPT_CONV_FORM: if (!opt_pair(opt_arg(), forms, &new_form)) goto opthelp; form = new_form; new_form = 1; break; case OPT_PARAM_ENC: if (!opt_pair(opt_arg(), encodings, &asn1_flag)) goto opthelp; new_asn1_flag = 1; break; case OPT_GENKEY: genkey = need_rand = 1; break; case OPT_RAND: inrand = opt_arg(); need_rand = 1; break; case OPT_ENGINE: (void)setup_engine(opt_arg(), 0); break; } } argc = opt_num_rest(); argv = opt_rest(); in = bio_open_default(infile, RB(informat)); if (in == NULL) goto end; out = bio_open_default(outfile, WB(outformat)); if (out == NULL) goto end; if (list_curves) { EC_builtin_curve *curves = NULL; size_t crv_len = EC_get_builtin_curves(NULL, 0); size_t n; curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves"); if (!EC_get_builtin_curves(curves, crv_len)) { OPENSSL_free(curves); goto end; } for (n = 0; n < crv_len; n++) { const char *comment; const char *sname; comment = curves[n].comment; sname = OBJ_nid2sn(curves[n].nid); if (comment == NULL) comment = "CURVE DESCRIPTION NOT AVAILABLE"; if (sname == NULL) sname = ""; BIO_printf(out, " %-10s: ", sname); BIO_printf(out, "%s\n", comment); } OPENSSL_free(curves); ret = 0; goto end; } if (curve_name != NULL) { int nid; /* * workaround for the SECG curve names secp192r1 and secp256r1 (which * are the same as the curves prime192v1 and prime256v1 defined in * X9.62) */ if (strcmp(curve_name, "secp192r1") == 0) { BIO_printf(bio_err, "using curve name prime192v1 " "instead of secp192r1\n"); nid = NID_X9_62_prime192v1; } else if (strcmp(curve_name, "secp256r1") == 0) { BIO_printf(bio_err, "using curve name prime256v1 " "instead of secp256r1\n"); nid = NID_X9_62_prime256v1; } else nid = OBJ_sn2nid(curve_name); if (nid == 0) nid = EC_curve_nist2nid(curve_name); if (nid == 0) { BIO_printf(bio_err, "unknown curve name (%s)\n", curve_name); goto end; } group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) { BIO_printf(bio_err, "unable to create curve (%s)\n", curve_name); goto end; } EC_GROUP_set_asn1_flag(group, asn1_flag); EC_GROUP_set_point_conversion_form(group, form); } else if (informat == FORMAT_ASN1) group = d2i_ECPKParameters_bio(in, NULL); else group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); if (group == NULL) { BIO_printf(bio_err, "unable to load elliptic curve parameters\n"); ERR_print_errors(bio_err); goto end; } if (new_form) EC_GROUP_set_point_conversion_form(group, form); if (new_asn1_flag) EC_GROUP_set_asn1_flag(group, asn1_flag); if (no_seed) { EC_GROUP_set_seed(group, NULL, 0); } if (text) { if (!ECPKParameters_print(out, group, 0)) goto end; } if (check) { if (group == NULL) BIO_printf(bio_err, "no elliptic curve parameters\n"); BIO_printf(bio_err, "checking elliptic curve parameters: "); if (!EC_GROUP_check(group, NULL)) { BIO_printf(bio_err, "failed\n"); ERR_print_errors(bio_err); } else BIO_printf(bio_err, "ok\n"); } if (C) { size_t buf_len = 0, tmp_len = 0; const EC_POINT *point; int is_prime, len = 0; const EC_METHOD *meth = EC_GROUP_method_of(group); if ((ec_p = BN_new()) == NULL || (ec_a = BN_new()) == NULL || (ec_b = BN_new()) == NULL || (ec_gen = BN_new()) == NULL || (ec_order = BN_new()) == NULL || (ec_cofactor = BN_new()) == NULL) { perror("Can't allocate BN"); goto end; } is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field); if (!is_prime) { BIO_printf(bio_err, "Can only handle X9.62 prime fields\n"); goto end; } if (!EC_GROUP_get_curve_GFp(group, ec_p, ec_a, ec_b, NULL)) goto end; if ((point = EC_GROUP_get0_generator(group)) == NULL) goto end; if (!EC_POINT_point2bn(group, point, EC_GROUP_get_point_conversion_form(group), ec_gen, NULL)) goto end; if (!EC_GROUP_get_order(group, ec_order, NULL)) goto end; if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL)) goto end; if (!ec_p || !ec_a || !ec_b || !ec_gen || !ec_order || !ec_cofactor) goto end; len = BN_num_bits(ec_order); if ((tmp_len = (size_t)BN_num_bytes(ec_p)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t)BN_num_bytes(ec_a)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t)BN_num_bytes(ec_b)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t)BN_num_bytes(ec_gen)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t)BN_num_bytes(ec_order)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t)BN_num_bytes(ec_cofactor)) > buf_len) buf_len = tmp_len; buffer = app_malloc(buf_len, "BN buffer"); BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n{\n", len); print_bignum_var(out, ec_p, "ec_p", len, buffer); print_bignum_var(out, ec_a, "ec_a", len, buffer); print_bignum_var(out, ec_b, "ec_b", len, buffer); print_bignum_var(out, ec_gen, "ec_gen", len, buffer); print_bignum_var(out, ec_order, "ec_order", len, buffer); print_bignum_var(out, ec_cofactor, "ec_cofactor", len, buffer); BIO_printf(out, " int ok = 0;\n" " EC_GROUP *group = NULL;\n" " EC_POINT *point = NULL;\n" " BIGNUM *tmp_1 = NULL;\n" " BIGNUM *tmp_2 = NULL;\n" " BIGNUM *tmp_3 = NULL;\n" "\n"); BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_p_%d, sizeof (ec_p_%d), NULL)) == NULL)\n" " goto err;\n", len, len); BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_a_%d, sizeof (ec_a_%d), NULL)) == NULL)\n" " goto err;\n", len, len); BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_b_%d, sizeof (ec_b_%d), NULL)) == NULL)\n" " goto err;\n", len, len); BIO_printf(out, " if ((group = EC_GROUP_new_curve_GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)\n" " goto err;\n" "\n"); BIO_printf(out, " /* build generator */\n"); BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_gen_%d, sizeof (ec_gen_%d), tmp_1)) == NULL)\n" " goto err;\n", len, len); BIO_printf(out, " point = EC_POINT_bn2point(group, tmp_1, NULL, NULL);\n"); BIO_printf(out, " if (point == NULL)\n" " goto err;\n"); BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_order_%d, sizeof (ec_order_%d), tmp_2)) == NULL)\n" " goto err;\n", len, len); BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_cofactor_%d, sizeof (ec_cofactor_%d), tmp_3)) == NULL)\n" " goto err;\n", len, len); BIO_printf(out, " if (!EC_GROUP_set_generator(group, point, tmp_2, tmp_3))\n" " goto err;\n" "ok = 1;" "\n"); BIO_printf(out, "err:\n" " BN_free(tmp_1);\n" " BN_free(tmp_2);\n" " BN_free(tmp_3);\n" " EC_POINT_free(point);\n" " if (!ok) {\n" " EC_GROUP_free(group);\n" " return NULL;\n" " }\n" " return (group);\n" "}\n"); } if (!noout) { if (outformat == FORMAT_ASN1) i = i2d_ECPKParameters_bio(out, group); else i = PEM_write_bio_ECPKParameters(out, group); if (!i) { BIO_printf(bio_err, "unable to write elliptic " "curve parameters\n"); ERR_print_errors(bio_err); goto end; } } if (need_rand) { app_RAND_load_file(NULL, (inrand != NULL)); if (inrand != NULL) BIO_printf(bio_err, "%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); } if (genkey) { EC_KEY *eckey = EC_KEY_new(); if (eckey == NULL) goto end; assert(need_rand); if (EC_KEY_set_group(eckey, group) == 0) goto end; if (!EC_KEY_generate_key(eckey)) { EC_KEY_free(eckey); goto end; } if (outformat == FORMAT_ASN1) i = i2d_ECPrivateKey_bio(out, eckey); else i = PEM_write_bio_ECPrivateKey(out, eckey, NULL, NULL, 0, NULL, NULL); EC_KEY_free(eckey); } if (need_rand) app_RAND_write_file(NULL); ret = 0; end: BN_free(ec_p); BN_free(ec_a); BN_free(ec_b); BN_free(ec_gen); BN_free(ec_order); BN_free(ec_cofactor); OPENSSL_free(buffer); BIO_free(in); BIO_free_all(out); EC_GROUP_free(group); return (ret); }
/* * 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; }
return NULL; #endif } int main(void) { unsigned char *abuf = NULL; //const EC_POINT *public_key; int i, alen, aout, jj = 0; int sockfd, new_fd; // listen on sock_fd, new connection on new_fd struct sockaddr_in my_addr; // my address information struct sockaddr_in their_addr; // connector's address information socklen_t sin_size; int yes = 1, numbytes; char buf[MAXDATASIZE]; /*//////////////////////////////////////////////////////////////Generating Keys/////////////////////////////////////*/ BN_CTX *ctx = NULL; int nid; BIO *out; CRYPTO_malloc_debug_init(); CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); const char *text = "NIST Prime-Curve P-192"; #ifdef OPENSSL_SYS_WIN32 CRYPTO_malloc_init(); #endif RAND_seed(rnd_seed, sizeof rnd_seed); out = BIO_new(BIO_s_file()); if (out == NULL) EXIT(1); BIO_set_fp(out, stdout, BIO_NOCLOSE); if ((ctx = BN_CTX_new()) == NULL) goto err; nid = NID_X9_62_prime192v1; EC_KEY *a = NULL; //EC_KEY is a structure BIGNUM *x_a = NULL, *y_a = NULL; const BIGNUM *BIG = NULL; char *buff; //unsigned char *abuf=NULL,*bbuf=NULL; const EC_GROUP *group; a = EC_KEY_new_by_curve_name(nid); if (a == NULL) goto err; group = EC_KEY_get0_group(a); // aa=EC_POINT_new(group); if ((x_a = BN_new()) == NULL) goto err; //BN_new returns a pointer to the bignum if ((y_a = BN_new()) == NULL) goto err; // if ((BIG=BN_new()) == NULL) goto err; BIO_puts(out, "Testing key generation with "); BIO_puts(out, text); if (!EC_KEY_generate_key(a)) goto err; printf("\n1 ) generating keys\n"); if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } //returns the public key else { if (!EC_POINT_get_affine_coordinates_GF2m(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } BIO_puts(out, " pri 1="); BN_print(out, EC_KEY_get0_private_key(a)); BIO_puts(out, "\n pub 1="); BN_print(out, x_a); BIO_puts(out, ","); BN_print(out, y_a); BIO_puts(out, "\n"); /* printf("importnt work\n"); //BN_print(out,x_a); buff=BN_bn2dec(x_a); printf("%s\n",buff); BN_dec2bn(&(x_a),buff); printf("%s\n",buff); BN_print(out,x_a); */ /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(1); } my_addr.sin_family = AF_INET; // host byte order my_addr.sin_port = htons(MYPORT); // short, network byte order my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero); if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof my_addr) == -1) { perror("bind"); exit(1); } if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } while (1) { // main accept() loop sin_size = sizeof their_addr; if ((new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &sin_size)) == -1) { perror("accept"); continue; } printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr)); if (send(new_fd, "Hello, world!\n", 14, 0) == -1) perror("send"); // BN_print(out,x_a); // if ((jj=send(new_fd, &aa, sizeof(BIGNUM), 0)) == -1) // perror("send"); ////////////////////////////////////////////////////////////////////////////// //printf("side %d\n",sizeof(EC_POINT*)); //aa= EC_KEY_get0_public_key(a); //printf("side %d\n",sizeof(aa)); // if ((jj=send(new_fd, &aa, sizeof(EC_POINT*), 0)) == -1) //perror("send"); //printf("\nbytes send %d\n",jj); //////////////////////////////////////////////////////////////////////////////// //x_a=(BIGNUM*)&buff; //BN_print(out,x_a); //printf("%d",sizeof(EC_POINT)); //buff=(char*)&x_a; //if (send(new_fd, &x_a, sizeof(x_a), 0) == -1) //perror("send"); //buff[10]='\0'; //BIG =EC_KEY_get0_private_key(a); //BN_print(out,BIG); /* buff=BN_bn2dec(x_a); // BN_print(out,BIG); buff=(char*)&x_a; //buff[10]='\0'; printf("%s\n",buff); x_a=(BIGNUM*)&buff; BN_dec2bn(&(y_a),buff); printf("%s",buff); */ //sprintf(buff,"%u",EC_KEY_get0_private_key(a)); //printf("send: %d\n",BIG); //printf("%s",buff); //printf("%d",strlen(buff)); // float data1; //char data2[64]; //BIG=(BIGNUM*)(buff); //BIO_puts(out,BIG); //memcpy((void*)buff, (void*)EC_KEY_get0_private_key(a), 20); //printf("%s",buff); //for (i=0; i<10; i++) //{ //printf("%c",buff[i]); //BIO_puts(out,buff); //} //if (send(new_fd,buff,strlen(buff), 0) == -1) // { // perror("send"); // } //printf("\npublic key send\n"); /* //EC_POINT *bb; if ((numbytes=recv(new_fd,(char*)&bb,500, 0)) == -1) { perror("recv"); exit(1); } printf("\npublic key received\n"); */ /* if ((numbytes=recv(new_fd, buf, MAXDATASIZE-1, 0)) == -1) { perror("recv"); exit(1); } */ // buf[numbytes] = '\0'; /* printf("Received: %d",numbytes); printf("working\n"); alen=KDF1_SHA1_len; ///it is a static constant integer. printf("working\n"); abuf=(unsigned char *)OPENSSL_malloc(alen); printf("working\n"); if(abuf==NULL || bb==NULL || a==NULL) printf("i hate you error\n"); aout=ECDH_compute_key(abuf,alen,bb,a,KDF1_SHA1); //generating session key printf("working\n"); // BN_print(out, abuf); //BIO_puts(out,"\n"); BIO_puts(out," key1 ="); for (i=0; i<aout; i++) { sprintf(buf,"%02X",abuf[i]); BIO_puts(out,buf); } BIO_puts(out,"\n"); */ close(new_fd); exit(0); close(new_fd); // parent doesn't need this } err: ERR_print_errors_fp(stderr); if (x_a) BN_free(x_a); if (y_a) BN_free(y_a); if (a) EC_KEY_free(a); if (ctx) BN_CTX_free(ctx); BIO_free(out); CRYPTO_cleanup_all_ex_data(); ERR_remove_state(0);
static int test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out) { printf("in ecdh test\n"); EC_KEY *a = NULL; //EC_KEY is a structure EC_KEY *b = NULL; BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL; char buf[12]; unsigned char *abuf = NULL, *bbuf = NULL; int i, alen, blen, aout, bout, ret = 0; const EC_GROUP *group; a = EC_KEY_new_by_curve_name(nid); // creates a new key according to the curve specified //it fills in the EC_KEY structure // use function called EC_KEY *EC_KEY_new(void) //also use a function called EC_GROUP_new_by_curve_name() creates a EC_GROUP structure specified by a curve name (in form of a NID) */ // the group returned is set in the EC_KEY structure. b = EC_KEY_new_by_curve_name(nid); if (a == NULL || b == NULL) goto err; group = EC_KEY_get0_group(a); //returns the EC_GROUP structure created by the EC_KEY structure //EC_GROUP structure is present in the EC_KEY structure. if ((x_a = BN_new()) == NULL) goto err; //BN_new returns a pointer to the bignum if ((y_a = BN_new()) == NULL) goto err; if ((x_b = BN_new()) == NULL) goto err; if ((y_b = BN_new()) == NULL) goto err; BIO_puts(out, "Testing key generation with "); BIO_puts(out, text); #ifdef NOISY printf ("noisy"); BIO_puts(out,"\n"); BIO_puts(out,"\n"); BIO_puts(out,"\n"); #else BIO_flush(out); #endif //public key number one is created here if (!EC_KEY_generate_key(a)) goto err; //pass the filled EC_KEY structure and it will create a public or private ec key. //it places the key in a->priv_key a->pub_key /// PUBLIC AND PVT KEYS ARE GENERATED BY THE SCALAR MULTIPLICATION printf("\n1 ) generating keys\n"); if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } //returns the public key else { if (!EC_POINT_get_affine_coordinates_GF2m(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } //BN_print_fp(stdout, a->pub_key); printf("private key is : "); BN_print_fp(stdout, EC_KEY_get0_private_key(a)); printf("\nAffine cordinates x:"); BN_print_fp(stdout, x_a); printf("\nAffine cordinates y:"); BN_print_fp(stdout, y_a); printf( "\n2 ) generated keys , generated affine points x and y , and also determided the primse brinary case\n"); #ifdef NOISY printf("no generation"); BIO_puts(out," pri 1="); BN_print(out,a->priv_key); BIO_puts(out,"\n pub 1="); BN_print(out,x_a); BIO_puts(out,","); BN_print(out,y_a); BIO_puts(out,"\n"); #else BIO_printf(out, " ."); BIO_flush(out); #endif //public key number two is created here if (!EC_KEY_generate_key(b)) 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, EC_KEY_get0_public_key(b), x_b, y_b, ctx)) goto err; // not well } else { if (!EC_POINT_get_affine_coordinates_GF2m(group, EC_KEY_get0_public_key(b), x_b, y_b, ctx)) goto err; } // printf("public key is : "); // BN_print_fp(stdout, EC_KEY_get0_private_key(b)); // for public key they will exchange the whole EC_POINT structure printf("private key is : "); BN_print_fp(stdout, EC_KEY_get0_private_key(b)); printf("\nAffine cordinates x"); BN_print_fp(stdout, x_b); printf("\nAffine cordinates y"); BN_print_fp(stdout, y_b); #ifdef NOISY BIO_puts(out," pri 2="); BN_print(out,b->priv_key); BIO_puts(out,"\n pub 2="); BN_print(out,x_b); BIO_puts(out,","); BN_print(out,y_b); BIO_puts(out,"\n"); #else BIO_printf(out, "."); BIO_flush(out); #endif alen = KDF1_SHA1_len; ///it is a static constant integer. abuf = (unsigned char *) OPENSSL_malloc(alen); aout = ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1); //generating session key // BN_print(out, abuf); //BIO_puts(out,"\n"); #ifdef NOISY BIO_puts(out," key1 ="); for (i=0; i<aout; i++) { sprintf(buf,"%02X",abuf[i]); BIO_puts(out,buf); } BIO_puts(out,"\n"); #else BIO_printf(out, "."); BIO_flush(out); #endif blen = KDF1_SHA1_len; bbuf = (unsigned char *) OPENSSL_malloc(blen); bout = ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1); // BN_print(out, bbuf); // BIO_puts(out,"\n"); #ifdef NOISY BIO_puts(out," key2 ="); for (i=0; i<bout; i++) { sprintf(buf,"%02X",bbuf[i]); BIO_puts(out,buf); } BIO_puts(out,"\n"); #else BIO_printf(out, "."); BIO_flush(out); #endif if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) { #ifndef NOISY BIO_printf(out, " failed\n\n"); BIO_printf(out, "key a:\n"); BIO_printf(out, "private key: "); BN_print(out, EC_KEY_get0_private_key(a)); BIO_printf(out, "\n"); BIO_printf(out, "public key (x,y): "); BN_print(out, x_a); BIO_printf(out, ","); BN_print(out, y_a); BIO_printf(out, "\nkey b:\n"); BIO_printf(out, "private key: "); BN_print(out, EC_KEY_get0_private_key(b)); BIO_printf(out, "\n"); BIO_printf(out, "public key (x,y): "); BN_print(out, x_b); BIO_printf(out, ","); BN_print(out, y_b); BIO_printf(out, "\n"); BIO_printf(out, "generated key a: "); for (i = 0; i < bout; i++) { sprintf(buf, "%02X", bbuf[i]); BIO_puts(out, buf); } BIO_printf(out, "\n"); BIO_printf(out, "generated key b: "); for (i = 0; i < aout; i++) { sprintf(buf, "%02X", abuf[i]); BIO_puts(out, buf); } BIO_printf(out, "\n"); #endif fprintf(stderr, "Error in ECDH routines\n"); ret = 0; } else { #ifndef NOISY BIO_printf(out, " ok\n"); #endif ret = 1; } err: ERR_print_errors_fp(stderr); if (abuf != NULL) OPENSSL_free(abuf); if (bbuf != NULL) OPENSSL_free(bbuf); if (x_a) BN_free(x_a); if (y_a) BN_free(y_a); if (x_b) BN_free(x_b); if (y_b) BN_free(y_b); if (b) EC_KEY_free(b); if (a) EC_KEY_free(a); return (ret); }
SM2CiphertextValue *SM2_do_encrypt(const EVP_MD *md, const unsigned char *in, size_t inlen, EC_KEY *ec_key) { SM2CiphertextValue *ret = NULL; SM2CiphertextValue *cv = NULL; const EC_GROUP *group; const EC_POINT *pub_key; KDF_FUNC kdf; EC_POINT *ephem_point = NULL; EC_POINT *share_point = NULL; BIGNUM *n = NULL; BIGNUM *h = NULL; BIGNUM *k = NULL; BN_CTX *bn_ctx = NULL; EVP_MD_CTX *md_ctx = NULL; unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1]; int nbytes; size_t len; size_t i; unsigned int hashlen; /* check arguments */ if (!md || !in || !ec_key) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (inlen < SM2_MIN_PLAINTEXT_LENGTH || inlen > SM2_MAX_PLAINTEXT_LENGTH) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_PLAINTEXT_LENGTH); return 0; } if (!(kdf = KDF_get_x9_63(md))) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_DIGEST_ALGOR); return 0; } if (!(group = EC_KEY_get0_group(ec_key)) || !(pub_key = EC_KEY_get0_public_key(ec_key))) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_EC_KEY); return 0; } /* malloc */ if (!(cv = SM2CiphertextValue_new()) || !(ephem_point = EC_POINT_new(group)) || !(share_point = EC_POINT_new(group)) || !(n = BN_new()) || !(h = BN_new()) || !(k = BN_new()) || !(bn_ctx = BN_CTX_new()) || !(md_ctx = EVP_MD_CTX_new())) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); goto end; } if (!ASN1_OCTET_STRING_set(cv->ciphertext, NULL, (int)inlen) || !ASN1_OCTET_STRING_set(cv->hash, NULL, EVP_MD_size(md))) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_ASN1_LIB); goto end; } /* init ec domain parameters */ if (!EC_GROUP_get_order(group, n, bn_ctx)) { ECerr(EC_F_SM2_DO_ENCRYPT, EC_R_ERROR); goto end; } if (!EC_GROUP_get_cofactor(group, h, bn_ctx)) { ECerr(EC_F_SM2_DO_ENCRYPT, EC_R_ERROR); goto end; } nbytes = (EC_GROUP_get_degree(group) + 7) / 8; /* check [h]P_B != O */ if (!EC_POINT_mul(group, share_point, NULL, pub_key, h, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } if (EC_POINT_is_at_infinity(group, share_point)) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_PUBLIC_KEY); goto end; } do { size_t size; /* rand k in [1, n-1] */ do { BN_rand_range(k, n); } while (BN_is_zero(k)); /* compute ephem_point [k]G = (x1, y1) */ if (!EC_POINT_mul(group, ephem_point, k, NULL, NULL, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } /* compute ECDH share_point [k]P_B = (x2, y2) */ if (!EC_POINT_mul(group, share_point, NULL, pub_key, k, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } /* compute t = KDF(x2 || y2, klen) */ if (!(len = EC_POINT_point2oct(group, share_point, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } size = cv->ciphertext->length; kdf(buf + 1, len - 1, cv->ciphertext->data, &size); if (size != inlen) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_KDF_FAILURE); goto end; } /* ASN1_OCTET_STRING_is_zero in asn1.h and a_octet.c */ } while (ASN1_OCTET_STRING_is_zero(cv->ciphertext)); /* set x/yCoordinates as (x1, y1) */ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, ephem_point, cv->xCoordinate, cv->yCoordinate, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } } else { if (!EC_POINT_get_affine_coordinates_GF2m(group, ephem_point, cv->xCoordinate, cv->yCoordinate, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } } /* ciphertext = t xor in */ for (i = 0; i < inlen; i++) { cv->ciphertext->data[i] ^= in[i]; } /* generate hash = Hash(x2 || M || y2) */ hashlen = cv->hash->length; if (!EVP_DigestInit_ex(md_ctx, md, NULL) || !EVP_DigestUpdate(md_ctx, buf + 1, nbytes) || !EVP_DigestUpdate(md_ctx, in, inlen) || !EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes) || !EVP_DigestFinal_ex(md_ctx, cv->hash->data, &hashlen)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EVP_LIB); goto end; } ret = cv; cv = NULL; end: SM2CiphertextValue_free(cv); EC_POINT_free(share_point); EC_POINT_free(ephem_point); BN_free(n); BN_free(h); BN_clear_free(k); BN_CTX_free(bn_ctx); EVP_MD_CTX_free(md_ctx); return ret; }
static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey) { int ret = -1; 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 (8 * dgst_len > BN_num_bits(order)) { /* XXX * * Should provide for optional hash truncation: * Keep the BN_num_bits(order) leftmost bits of dgst * (see March 2006 FIPS 186-3 draft, which has a few * confusing errors in this part though) */ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); ret = 0; 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 */ if (!BN_bin2bn(dgst, dgst_len, m)) { 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; } } 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; } } 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; }
/*- * This implementation is based on the following primitives in the IEEE 1363 standard: * - ECKAS-DH1 * - ECSVDP-DH */ int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, const EC_POINT *pub_key, const EC_KEY *ecdh) { BN_CTX *ctx; EC_POINT *tmp = NULL; BIGNUM *x = NULL, *y = NULL; const BIGNUM *priv_key; const EC_GROUP *group; int ret = 0; size_t buflen, len; unsigned char *buf = NULL; 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_ECDH_SIMPLE_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_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); goto err; } priv_key = x; } if ((tmp = EC_POINT_new(group)) == NULL) { ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { ECerr(EC_F_ECDH_SIMPLE_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_ECDH_SIMPLE_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_ECDH_SIMPLE_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_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_INTERNAL_ERROR); goto err; } if ((buf = OPENSSL_malloc(buflen)) == NULL) { ECerr(EC_F_ECDH_SIMPLE_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_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_BN_LIB); goto err; } *pout = buf; *poutlen = buflen; buf = NULL; ret = 1; err: EC_POINT_free(tmp); if (ctx) BN_CTX_end(ctx); BN_CTX_free(ctx); OPENSSL_free(buf); return ret; }
static int test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out) { EC_KEY *a = NULL; EC_KEY *b = NULL; BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL; char buf[12]; unsigned char *abuf = NULL, *bbuf = NULL; int i, alen, blen, aout, bout, ret = 0; const EC_GROUP *group; a = EC_KEY_new_by_curve_name(nid); b = EC_KEY_new_by_curve_name(nid); if (a == NULL || b == NULL) goto err; group = EC_KEY_get0_group(a); if ((x_a = BN_new()) == NULL) goto err; if ((y_a = BN_new()) == NULL) goto err; if ((x_b = BN_new()) == NULL) goto err; if ((y_b = BN_new()) == NULL) goto err; BIO_puts(out, "Testing key generation with "); BIO_puts(out, text); # ifdef NOISY BIO_puts(out, "\n"); # else (void)BIO_flush(out); # endif if (!EC_KEY_generate_key(a)) 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, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } # ifndef OPENSSL_NO_EC2M else { if (!EC_POINT_get_affine_coordinates_GF2m(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } # endif # ifdef NOISY BIO_puts(out, " pri 1="); BN_print(out, a->priv_key); BIO_puts(out, "\n pub 1="); BN_print(out, x_a); BIO_puts(out, ","); BN_print(out, y_a); BIO_puts(out, "\n"); # else BIO_printf(out, " ."); (void)BIO_flush(out); # endif if (!EC_KEY_generate_key(b)) 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, EC_KEY_get0_public_key(b), x_b, y_b, ctx)) goto err; } # ifndef OPENSSL_NO_EC2M else { if (!EC_POINT_get_affine_coordinates_GF2m(group, EC_KEY_get0_public_key(b), x_b, y_b, ctx)) goto err; } # endif # ifdef NOISY BIO_puts(out, " pri 2="); BN_print(out, b->priv_key); BIO_puts(out, "\n pub 2="); BN_print(out, x_b); BIO_puts(out, ","); BN_print(out, y_b); BIO_puts(out, "\n"); # else BIO_printf(out, "."); (void)BIO_flush(out); # endif alen = KDF1_SHA1_len; abuf = (unsigned char *)OPENSSL_malloc(alen); aout = ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1); # ifdef NOISY BIO_puts(out, " key1 ="); for (i = 0; i < aout; i++) { sprintf(buf, "%02X", abuf[i]); BIO_puts(out, buf); } BIO_puts(out, "\n"); # else BIO_printf(out, "."); (void)BIO_flush(out); # endif blen = KDF1_SHA1_len; bbuf = (unsigned char *)OPENSSL_malloc(blen); bout = ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1); # ifdef NOISY BIO_puts(out, " key2 ="); for (i = 0; i < bout; i++) { sprintf(buf, "%02X", bbuf[i]); BIO_puts(out, buf); } BIO_puts(out, "\n"); # else BIO_printf(out, "."); (void)BIO_flush(out); # endif if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) { # ifndef NOISY BIO_printf(out, " failed\n\n"); BIO_printf(out, "key a:\n"); BIO_printf(out, "private key: "); BN_print(out, EC_KEY_get0_private_key(a)); BIO_printf(out, "\n"); BIO_printf(out, "public key (x,y): "); BN_print(out, x_a); BIO_printf(out, ","); BN_print(out, y_a); BIO_printf(out, "\nkey b:\n"); BIO_printf(out, "private key: "); BN_print(out, EC_KEY_get0_private_key(b)); BIO_printf(out, "\n"); BIO_printf(out, "public key (x,y): "); BN_print(out, x_b); BIO_printf(out, ","); BN_print(out, y_b); BIO_printf(out, "\n"); BIO_printf(out, "generated key a: "); for (i = 0; i < bout; i++) { sprintf(buf, "%02X", bbuf[i]); BIO_puts(out, buf); } BIO_printf(out, "\n"); BIO_printf(out, "generated key b: "); for (i = 0; i < aout; i++) { sprintf(buf, "%02X", abuf[i]); BIO_puts(out, buf); } BIO_printf(out, "\n"); # endif fprintf(stderr, "Error in ECDH routines\n"); ret = 0; } else { # ifndef NOISY BIO_printf(out, " ok\n"); # endif ret = 1; } err: ERR_print_errors_fp(stderr); if (abuf != NULL) OPENSSL_free(abuf); if (bbuf != NULL) OPENSSL_free(bbuf); if (x_a) BN_free(x_a); if (y_a) BN_free(y_a); if (x_b) BN_free(x_b); if (y_b) BN_free(y_b); if (b) EC_KEY_free(b); if (a) EC_KEY_free(a); return (ret); }
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; int order_bits; 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; } /* 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 (!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. * * We unconditionally perform both of these additions to prevent a * small timing information leakage. We then choose the sum that is * one bit longer than the order. This guarantees the code * path used in the constant time implementations elsewhere. * * TODO: revisit the BN_copy aiming for a memory access agnostic * conditional copy. */ if (!BN_add(r, k, order) || !BN_add(X, r, order) || !BN_copy(k, BN_num_bits(r) > order_bits ? r : X)) 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); if (tmp_point != NULL) EC_POINT_free(tmp_point); if (X) BN_clear_free(X); return (ret); }
int ecparam_main(int argc, char **argv) { EC_GROUP *group = NULL; point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; int new_form = 0; int asn1_flag = OPENSSL_EC_NAMED_CURVE; int new_asn1_flag = 0; char *curve_name = NULL, *inrand = NULL; int list_curves = 0, no_seed = 0, check = 0, badops = 0, text = 0, i, genkey = 0; char *infile = NULL, *outfile = NULL, *prog; BIO *in = NULL, *out = NULL; int informat, outformat, noout = 0, C = 0, ret = 1; char *engine = NULL; BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL, *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL; unsigned char *buffer = NULL; if (!load_config(bio_err, NULL)) goto end; informat = FORMAT_PEM; outformat = FORMAT_PEM; prog = argv[0]; argc--; argv++; while (argc >= 1) { if (strcmp(*argv, "-inform") == 0) { if (--argc < 1) goto bad; informat = str2fmt(*(++argv)); } else if (strcmp(*argv, "-outform") == 0) { if (--argc < 1) goto bad; outformat = str2fmt(*(++argv)); } else if (strcmp(*argv, "-in") == 0) { if (--argc < 1) goto bad; infile = *(++argv); } else if (strcmp(*argv, "-out") == 0) { if (--argc < 1) goto bad; outfile = *(++argv); } else if (strcmp(*argv, "-text") == 0) text = 1; else if (strcmp(*argv, "-C") == 0) C = 1; else if (strcmp(*argv, "-check") == 0) check = 1; else if (strcmp(*argv, "-name") == 0) { if (--argc < 1) goto bad; curve_name = *(++argv); } else if (strcmp(*argv, "-list_curves") == 0) list_curves = 1; else if (strcmp(*argv, "-conv_form") == 0) { if (--argc < 1) goto bad; ++argv; new_form = 1; if (strcmp(*argv, "compressed") == 0) form = POINT_CONVERSION_COMPRESSED; else if (strcmp(*argv, "uncompressed") == 0) form = POINT_CONVERSION_UNCOMPRESSED; else if (strcmp(*argv, "hybrid") == 0) form = POINT_CONVERSION_HYBRID; else goto bad; } else if (strcmp(*argv, "-param_enc") == 0) { if (--argc < 1) goto bad; ++argv; new_asn1_flag = 1; if (strcmp(*argv, "named_curve") == 0) asn1_flag = OPENSSL_EC_NAMED_CURVE; else if (strcmp(*argv, "explicit") == 0) asn1_flag = 0; else goto bad; } else if (strcmp(*argv, "-no_seed") == 0) no_seed = 1; else if (strcmp(*argv, "-noout") == 0) noout = 1; else if (strcmp(*argv, "-genkey") == 0) { genkey = 1; } else if (strcmp(*argv, "-rand") == 0) { if (--argc < 1) goto bad; inrand = *(++argv); } else if (strcmp(*argv, "-engine") == 0) { if (--argc < 1) goto bad; engine = *(++argv); } else { BIO_printf(bio_err, "unknown option %s\n", *argv); badops = 1; break; } argc--; argv++; } if (badops) { bad: BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog); BIO_printf(bio_err, "where options are\n"); BIO_printf(bio_err, " -inform arg input format - " "default PEM (DER or PEM)\n"); BIO_printf(bio_err, " -outform arg output format - " "default PEM\n"); BIO_printf(bio_err, " -in arg input file - " "default stdin\n"); BIO_printf(bio_err, " -out arg output file - " "default stdout\n"); BIO_printf(bio_err, " -noout do not print the " "ec parameter\n"); BIO_printf(bio_err, " -text print the ec " "parameters in text form\n"); BIO_printf(bio_err, " -check validate the ec " "parameters\n"); BIO_printf(bio_err, " -C print a 'C' " "function creating the parameters\n"); BIO_printf(bio_err, " -name arg use the " "ec parameters with 'short name' name\n"); BIO_printf(bio_err, " -list_curves prints a list of " "all currently available curve 'short names'\n"); BIO_printf(bio_err, " -conv_form arg specifies the " "point conversion form \n"); BIO_printf(bio_err, " possible values:" " compressed\n"); BIO_printf(bio_err, " " " uncompressed (default)\n"); BIO_printf(bio_err, " " " hybrid\n"); BIO_printf(bio_err, " -param_enc arg specifies the way" " the ec parameters are encoded\n"); BIO_printf(bio_err, " in the asn1 der " "encoding\n"); BIO_printf(bio_err, " possible values:" " named_curve (default)\n"); BIO_printf(bio_err, " " " explicit\n"); BIO_printf(bio_err, " -no_seed if 'explicit'" " parameters are chosen do not" " use the seed\n"); BIO_printf(bio_err, " -genkey generate ec" " key\n"); BIO_printf(bio_err, " -rand file files to use for" " random number input\n"); BIO_printf(bio_err, " -engine e use engine e, " "possibly a hardware device\n"); goto end; } ERR_load_crypto_strings(); in = BIO_new(BIO_s_file()); out = BIO_new(BIO_s_file()); if ((in == NULL) || (out == NULL)) { ERR_print_errors(bio_err); goto end; } if (infile == NULL) BIO_set_fp(in, stdin, BIO_NOCLOSE); else { if (BIO_read_filename(in, infile) <= 0) { perror(infile); goto end; } } if (outfile == NULL) { BIO_set_fp(out, stdout, BIO_NOCLOSE); } else { if (BIO_write_filename(out, outfile) <= 0) { perror(outfile); goto end; } } #ifndef OPENSSL_NO_ENGINE setup_engine(bio_err, engine, 0); #endif if (list_curves) { EC_builtin_curve *curves = NULL; size_t crv_len = 0; size_t n = 0; crv_len = EC_get_builtin_curves(NULL, 0); curves = reallocarray(NULL, crv_len, sizeof(EC_builtin_curve)); if (curves == NULL) goto end; if (!EC_get_builtin_curves(curves, crv_len)) { free(curves); goto end; } for (n = 0; n < crv_len; n++) { const char *comment; const char *sname; comment = curves[n].comment; sname = OBJ_nid2sn(curves[n].nid); if (comment == NULL) comment = "CURVE DESCRIPTION NOT AVAILABLE"; if (sname == NULL) sname = ""; BIO_printf(out, " %-10s: ", sname); BIO_printf(out, "%s\n", comment); } free(curves); ret = 0; goto end; } if (curve_name != NULL) { int nid; /* * workaround for the SECG curve names secp192r1 and * secp256r1 (which are the same as the curves prime192v1 and * prime256v1 defined in X9.62) */ if (!strcmp(curve_name, "secp192r1")) { BIO_printf(bio_err, "using curve name prime192v1 " "instead of secp192r1\n"); nid = NID_X9_62_prime192v1; } else if (!strcmp(curve_name, "secp256r1")) { BIO_printf(bio_err, "using curve name prime256v1 " "instead of secp256r1\n"); nid = NID_X9_62_prime256v1; } else nid = OBJ_sn2nid(curve_name); if (nid == 0) { BIO_printf(bio_err, "unknown curve name (%s)\n", curve_name); goto end; } group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) { BIO_printf(bio_err, "unable to create curve (%s)\n", curve_name); goto end; } EC_GROUP_set_asn1_flag(group, asn1_flag); EC_GROUP_set_point_conversion_form(group, form); } else if (informat == FORMAT_ASN1) { group = d2i_ECPKParameters_bio(in, NULL); } else if (informat == FORMAT_PEM) { group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); } else { BIO_printf(bio_err, "bad input format specified\n"); goto end; } if (group == NULL) { BIO_printf(bio_err, "unable to load elliptic curve parameters\n"); ERR_print_errors(bio_err); goto end; } if (new_form) EC_GROUP_set_point_conversion_form(group, form); if (new_asn1_flag) EC_GROUP_set_asn1_flag(group, asn1_flag); if (no_seed) { EC_GROUP_set_seed(group, NULL, 0); } if (text) { if (!ECPKParameters_print(out, group, 0)) goto end; } if (check) { if (group == NULL) BIO_printf(bio_err, "no elliptic curve parameters\n"); BIO_printf(bio_err, "checking elliptic curve parameters: "); if (!EC_GROUP_check(group, NULL)) { BIO_printf(bio_err, "failed\n"); ERR_print_errors(bio_err); } else BIO_printf(bio_err, "ok\n"); } if (C) { size_t buf_len = 0, tmp_len = 0; const EC_POINT *point; int is_prime, len = 0; const EC_METHOD *meth = EC_GROUP_method_of(group); if ((ec_p = BN_new()) == NULL || (ec_a = BN_new()) == NULL || (ec_b = BN_new()) == NULL || (ec_gen = BN_new()) == NULL || (ec_order = BN_new()) == NULL || (ec_cofactor = BN_new()) == NULL) { perror("malloc"); goto end; } is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field); if (is_prime) { if (!EC_GROUP_get_curve_GFp(group, ec_p, ec_a, ec_b, NULL)) goto end; } else { /* TODO */ goto end; } if ((point = EC_GROUP_get0_generator(group)) == NULL) goto end; if (!EC_POINT_point2bn(group, point, EC_GROUP_get_point_conversion_form(group), ec_gen, NULL)) goto end; if (!EC_GROUP_get_order(group, ec_order, NULL)) goto end; if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL)) goto end; if (!ec_p || !ec_a || !ec_b || !ec_gen || !ec_order || !ec_cofactor) goto end; len = BN_num_bits(ec_order); if ((tmp_len = (size_t) BN_num_bytes(ec_p)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t) BN_num_bytes(ec_a)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t) BN_num_bytes(ec_b)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t) BN_num_bytes(ec_gen)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t) BN_num_bytes(ec_order)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t) BN_num_bytes(ec_cofactor)) > buf_len) buf_len = tmp_len; buffer = (unsigned char *) malloc(buf_len); if (buffer == NULL) { perror("malloc"); goto end; } ecparam_print_var(out, ec_p, "ec_p", len, buffer); ecparam_print_var(out, ec_a, "ec_a", len, buffer); ecparam_print_var(out, ec_b, "ec_b", len, buffer); ecparam_print_var(out, ec_gen, "ec_gen", len, buffer); ecparam_print_var(out, ec_order, "ec_order", len, buffer); ecparam_print_var(out, ec_cofactor, "ec_cofactor", len, buffer); BIO_printf(out, "\n\n"); BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n\t{\n", len); BIO_printf(out, "\tint ok=0;\n"); BIO_printf(out, "\tEC_GROUP *group = NULL;\n"); BIO_printf(out, "\tEC_POINT *point = NULL;\n"); BIO_printf(out, "\tBIGNUM *tmp_1 = NULL, *tmp_2 = NULL, " "*tmp_3 = NULL;\n\n"); BIO_printf(out, "\tif ((tmp_1 = BN_bin2bn(ec_p_%d, " "sizeof(ec_p_%d), NULL)) == NULL)\n\t\t" "goto err;\n", len, len); BIO_printf(out, "\tif ((tmp_2 = BN_bin2bn(ec_a_%d, " "sizeof(ec_a_%d), NULL)) == NULL)\n\t\t" "goto err;\n", len, len); BIO_printf(out, "\tif ((tmp_3 = BN_bin2bn(ec_b_%d, " "sizeof(ec_b_%d), NULL)) == NULL)\n\t\t" "goto err;\n", len, len); if (is_prime) { BIO_printf(out, "\tif ((group = EC_GROUP_new_curve_" "GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)" "\n\t\tgoto err;\n\n"); } else { /* TODO */ goto end; } BIO_printf(out, "\t/* build generator */\n"); BIO_printf(out, "\tif ((tmp_1 = BN_bin2bn(ec_gen_%d, " "sizeof(ec_gen_%d), tmp_1)) == NULL)" "\n\t\tgoto err;\n", len, len); BIO_printf(out, "\tpoint = EC_POINT_bn2point(group, tmp_1, " "NULL, NULL);\n"); BIO_printf(out, "\tif (point == NULL)\n\t\tgoto err;\n"); BIO_printf(out, "\tif ((tmp_2 = BN_bin2bn(ec_order_%d, " "sizeof(ec_order_%d), tmp_2)) == NULL)" "\n\t\tgoto err;\n", len, len); BIO_printf(out, "\tif ((tmp_3 = BN_bin2bn(ec_cofactor_%d, " "sizeof(ec_cofactor_%d), tmp_3)) == NULL)" "\n\t\tgoto err;\n", len, len); BIO_printf(out, "\tif (!EC_GROUP_set_generator(group, point," " tmp_2, tmp_3))\n\t\tgoto err;\n"); BIO_printf(out, "\n\tok=1;\n"); BIO_printf(out, "err:\n"); BIO_printf(out, "\tif (tmp_1)\n\t\tBN_free(tmp_1);\n"); BIO_printf(out, "\tif (tmp_2)\n\t\tBN_free(tmp_2);\n"); BIO_printf(out, "\tif (tmp_3)\n\t\tBN_free(tmp_3);\n"); BIO_printf(out, "\tif (point)\n\t\tEC_POINT_free(point);\n"); BIO_printf(out, "\tif (!ok)\n"); BIO_printf(out, "\t\t{\n"); BIO_printf(out, "\t\tEC_GROUP_free(group);\n"); BIO_printf(out, "\t\tgroup = NULL;\n"); BIO_printf(out, "\t\t}\n"); BIO_printf(out, "\treturn(group);\n\t}\n"); } if (!noout) { if (outformat == FORMAT_ASN1) i = i2d_ECPKParameters_bio(out, group); else if (outformat == FORMAT_PEM) i = PEM_write_bio_ECPKParameters(out, group); else { BIO_printf(bio_err, "bad output format specified for" " outfile\n"); goto end; } if (!i) { BIO_printf(bio_err, "unable to write elliptic " "curve parameters\n"); ERR_print_errors(bio_err); goto end; } } if (genkey) { EC_KEY *eckey = EC_KEY_new(); if (eckey == NULL) goto end; if (EC_KEY_set_group(eckey, group) == 0) goto end; if (!EC_KEY_generate_key(eckey)) { EC_KEY_free(eckey); goto end; } if (outformat == FORMAT_ASN1) i = i2d_ECPrivateKey_bio(out, eckey); else if (outformat == FORMAT_PEM) i = PEM_write_bio_ECPrivateKey(out, eckey, NULL, NULL, 0, NULL, NULL); else { BIO_printf(bio_err, "bad output format specified " "for outfile\n"); EC_KEY_free(eckey); goto end; } EC_KEY_free(eckey); } ret = 0; end: if (ec_p) BN_free(ec_p); if (ec_a) BN_free(ec_a); if (ec_b) BN_free(ec_b); if (ec_gen) BN_free(ec_gen); if (ec_order) BN_free(ec_order); if (ec_cofactor) BN_free(ec_cofactor); free(buffer); if (in != NULL) BIO_free(in); if (out != NULL) BIO_free_all(out); if (group != NULL) EC_GROUP_free(group); return (ret); }
int ECPKParameters_print(BIO * bp, const EC_GROUP * x, int off) { unsigned char *buffer = NULL; size_t buf_len = 0, i; int ret = 0, reason = ERR_R_BIO_LIB; BN_CTX *ctx = NULL; const EC_POINT *point = NULL; BIGNUM *p = NULL, *a = NULL, *b = NULL, *gen = NULL, *order = NULL, *cofactor = NULL; const unsigned char *seed; size_t seed_len = 0; const char *nname; static const char *gen_compressed = "Generator (compressed):"; static const char *gen_uncompressed = "Generator (uncompressed):"; static const char *gen_hybrid = "Generator (hybrid):"; if (!x) { reason = ERR_R_PASSED_NULL_PARAMETER; goto err; } ctx = BN_CTX_new(); if (ctx == NULL) { reason = ERR_R_MALLOC_FAILURE; goto err; } if (EC_GROUP_get_asn1_flag(x)) { /* the curve parameter are given by an asn1 OID */ int nid; if (!BIO_indent(bp, off, 128)) goto err; nid = EC_GROUP_get_curve_name(x); if (nid == 0) goto err; if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0) goto err; if (BIO_printf(bp, "\n") <= 0) goto err; nname = EC_curve_nid2nist(nid); if (nname) { if (!BIO_indent(bp, off, 128)) goto err; if (BIO_printf(bp, "NIST CURVE: %s\n", nname) <= 0) goto err; } } else { /* explicit parameters */ int is_char_two = 0; point_conversion_form_t form; int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x)); if (tmp_nid == NID_X9_62_characteristic_two_field) is_char_two = 1; if ((p = BN_new()) == NULL || (a = BN_new()) == NULL || (b = BN_new()) == NULL || (order = BN_new()) == NULL || (cofactor = BN_new()) == NULL) { reason = ERR_R_MALLOC_FAILURE; goto err; } #ifndef OPENSSL_NO_EC2M if (is_char_two) { if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx)) { reason = ERR_R_EC_LIB; goto err; } } else /* prime field */ #endif { if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx)) { reason = ERR_R_EC_LIB; goto err; } } if ((point = EC_GROUP_get0_generator(x)) == NULL) { reason = ERR_R_EC_LIB; goto err; } if (!EC_GROUP_get_order(x, order, NULL) || !EC_GROUP_get_cofactor(x, cofactor, NULL)) { reason = ERR_R_EC_LIB; goto err; } form = EC_GROUP_get_point_conversion_form(x); if ((gen = EC_POINT_point2bn(x, point, form, NULL, ctx)) == NULL) { reason = ERR_R_EC_LIB; goto err; } buf_len = (size_t) BN_num_bytes(p); if (buf_len < (i = (size_t) BN_num_bytes(a))) buf_len = i; if (buf_len < (i = (size_t) BN_num_bytes(b))) buf_len = i; if (buf_len < (i = (size_t) BN_num_bytes(gen))) buf_len = i; if (buf_len < (i = (size_t) BN_num_bytes(order))) buf_len = i; if (buf_len < (i = (size_t) BN_num_bytes(cofactor))) buf_len = i; if ((seed = EC_GROUP_get0_seed(x)) != NULL) seed_len = EC_GROUP_get_seed_len(x); buf_len += 10; if ((buffer = malloc(buf_len)) == NULL) { reason = ERR_R_MALLOC_FAILURE; goto err; } if (!BIO_indent(bp, off, 128)) goto err; /* print the 'short name' of the field type */ if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid)) <= 0) goto err; if (is_char_two) { /* print the 'short name' of the base type OID */ int basis_type = EC_GROUP_get_basis_type(x); if (basis_type == 0) goto err; if (!BIO_indent(bp, off, 128)) goto err; if (BIO_printf(bp, "Basis Type: %s\n", OBJ_nid2sn(basis_type)) <= 0) goto err; /* print the polynomial */ if ((p != NULL) && !ASN1_bn_print(bp, "Polynomial:", p, buffer, off)) goto err; } else { if ((p != NULL) && !ASN1_bn_print(bp, "Prime:", p, buffer, off)) goto err; } if ((a != NULL) && !ASN1_bn_print(bp, "A: ", a, buffer, off)) goto err; if ((b != NULL) && !ASN1_bn_print(bp, "B: ", b, buffer, off)) goto err; if (form == POINT_CONVERSION_COMPRESSED) { if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen, buffer, off)) goto err; } else if (form == POINT_CONVERSION_UNCOMPRESSED) { if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen, buffer, off)) goto err; } else { /* form == POINT_CONVERSION_HYBRID */ if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen, buffer, off)) goto err; } if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order, buffer, off)) goto err; if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor, buffer, off)) goto err; if (seed && !print_bin(bp, "Seed:", seed, seed_len, off)) goto err; } ret = 1; err: if (!ret) ECerror(reason); BN_free(p); BN_free(a); BN_free(b); BN_free(gen); BN_free(order); BN_free(cofactor); BN_CTX_free(ctx); free(buffer); return (ret); }
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; }
builtin_curves::builtin_curves() { int i, num_curves = EC_get_builtin_curves(NULL, 0); EC_builtin_curve *curves = (EC_builtin_curve*)OPENSSL_malloc( (int)(sizeof(EC_builtin_curve) *num_curves)); check_oom(curves); BIGNUM *order = BN_new(); check_oom(order); EC_get_builtin_curves(curves, num_curves); for (i=0; i< num_curves; i++) { size_t j; int flag = 0, nid = curves[i].nid; unsigned long type = 0; for (j=0; j<ARRAY_SIZE(x962_curve_nids); j++) { if (x962_curve_nids[j] == nid) { flag = CURVE_X962; break; } } if (!flag) { for (j=0; j<ARRAY_SIZE(other_curve_nids); j++) { if (other_curve_nids[j] == nid) { flag = CURVE_OTHER; break; } } } if (!flag) continue; EC_GROUP *group = EC_GROUP_new_by_curve_name(nid); EC_GROUP_get_order(group, order, NULL); switch (EC_METHOD_get_field_type(EC_GROUP_method_of(group))) { case NID_X9_62_prime_field: type = CKF_EC_F_P; break; case NID_X9_62_characteristic_two_field: type = CKF_EC_F_2M; break; default: continue; } #undef PRINT_KNOWN_CURVES #ifdef PRINT_KNOWN_CURVES fprintf(stderr, "%50s %27s %20s %s\n", curves[i].comment, OBJ_nid2sn(nid), CCHAR(OBJ_obj2QString(OBJ_nid2obj(nid), 1)), type == CKF_EC_F_P ? "Fp" : "F2m"); #endif append(builtin_curve(nid, QString(curves[i].comment), BN_num_bits(order), flag, type)); EC_GROUP_free(group); } BN_free(order); }
int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) { int r = 0; BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; BN_CTX *ctx_new = NULL; /* compare the field types */ if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != EC_METHOD_get_field_type(EC_GROUP_method_of(b))) return 1; /* compare the curve name (if present in both) */ if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) return 1; if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE) return 0; if (ctx == NULL) ctx_new = ctx = BN_CTX_new(); if (ctx == NULL) return -1; BN_CTX_start(ctx); a1 = BN_CTX_get(ctx); a2 = BN_CTX_get(ctx); a3 = BN_CTX_get(ctx); b1 = BN_CTX_get(ctx); b2 = BN_CTX_get(ctx); b3 = BN_CTX_get(ctx); if (b3 == NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx_new); return -1; } /* * XXX This approach assumes that the external representation of curves * over the same field type is the same. */ if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || !b->meth->group_get_curve(b, b1, b2, b3, ctx)) r = 1; if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) r = 1; /* XXX EC_POINT_cmp() assumes that the methods are equal */ if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), EC_GROUP_get0_generator(b), ctx)) r = 1; if (!r) { const BIGNUM *ao, *bo, *ac, *bc; /* compare the order and cofactor */ ao = EC_GROUP_get0_order(a); bo = EC_GROUP_get0_order(b); ac = EC_GROUP_get0_cofactor(a); bc = EC_GROUP_get0_cofactor(b); if (ao == NULL || bo == NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx_new); return -1; } if (BN_cmp(ao, bo) || BN_cmp(ac, bc)) r = 1; } BN_CTX_end(ctx); BN_CTX_free(ctx_new); return r; }
/* k in [1, n-1], (x, y) = kG */ static int sm2_sign_setup(EC_KEY *ec_key, BN_CTX *ctx_in, BIGNUM **kp, BIGNUM **xp) { int ret = 0; const EC_GROUP *ec_group; BN_CTX *ctx = NULL; BIGNUM *k = NULL; BIGNUM *x = NULL; BIGNUM *order = NULL; EC_POINT *point = NULL; if (ec_key == NULL || (ec_group = EC_KEY_get0_group(ec_key)) == 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(); x = BN_new(); order = BN_new(); if (!k || !x || !order) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_GROUP_get_order(ec_group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if ((point = EC_POINT_new(ec_group)) == NULL) { 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)); /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(ec_group, 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(ec_group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(ec_group, point, x, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB); goto err; } } else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(ec_group, point, x, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB); goto err; } } //FIXME: do we need this? if (!BN_nnmod(x, x, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(x)); /* clear old values if necessary */ if (*kp != NULL) BN_clear_free(*kp); if (*xp != NULL) BN_clear_free(*xp); /* save the pre-computed values */ *kp = k; *xp = x; ret = 1; err: if (!ret) { if (k) BN_clear_free(k); if (x) BN_clear_free(x); } if (ctx_in == NULL) BN_CTX_free(ctx); if (order) BN_free(order); if (point) EC_POINT_free(point); return(ret); }