static int openssl_ec_group_parse(lua_State*L) { const EC_GROUP* group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group"); const EC_POINT *generator = EC_GROUP_get0_generator(group); BN_CTX* ctx = BN_CTX_new(); BIGNUM *a, *b, *p, *order, *cofactor; lua_newtable(L); if (generator) { generator = EC_POINT_dup(generator, group); AUXILIAR_SETOBJECT(L, generator, "openssl.ec_point", -1, "generator"); } order = BN_new(); EC_GROUP_get_order(group, order, ctx); AUXILIAR_SETOBJECT(L, order, "openssl.bn", -1, "order"); cofactor = BN_new(); EC_GROUP_get_cofactor(group, cofactor, ctx); AUXILIAR_SETOBJECT(L, cofactor, "openssl.bn", -1, "cofactor"); AUXILIAR_SET(L, -1, "asn1_flag", EC_GROUP_get_asn1_flag(group), integer); AUXILIAR_SET(L, -1, "degree", EC_GROUP_get_degree(group), integer); AUXILIAR_SET(L, -1, "curve_name", EC_GROUP_get_curve_name(group), integer); AUXILIAR_SET(L, -1, "conversion_form", EC_GROUP_get_point_conversion_form(group), integer); AUXILIAR_SETLSTR(L, -1, "seed", EC_GROUP_get0_seed(group), EC_GROUP_get_seed_len(group)); a = BN_new(); b = BN_new(); p = BN_new(); EC_GROUP_get_curve_GFp(group, p, a, b, ctx); lua_newtable(L); { AUXILIAR_SETOBJECT(L, p, "openssl.bn", -1, "p"); AUXILIAR_SETOBJECT(L, a, "openssl.bn", -1, "a"); AUXILIAR_SETOBJECT(L, b, "openssl.bn", -1, "b"); } lua_setfield(L, -2, "curve"); BN_CTX_free(ctx); 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 compute_password_element (pwd_session_t *sess, uint16_t grp_num, char *password, int password_len, char *id_server, int id_server_len, char *id_peer, int id_peer_len, uint32_t *token) { BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL; HMAC_CTX ctx; uint8_t pwe_digest[SHA256_DIGEST_LENGTH], *prfbuf = NULL, ctr; int nid, is_odd, primebitlen, primebytelen, ret = 0; switch (grp_num) { /* from IANA registry for IKE D-H groups */ case 19: nid = NID_X9_62_prime256v1; break; case 20: nid = NID_secp384r1; break; case 21: nid = NID_secp521r1; break; case 25: nid = NID_X9_62_prime192v1; break; case 26: nid = NID_secp224r1; break; default: DEBUG("unknown group %d", grp_num); goto fail; } sess->pwe = NULL; sess->order = NULL; sess->prime = NULL; if ((sess->group = EC_GROUP_new_by_curve_name(nid)) == NULL) { DEBUG("unable to create EC_GROUP"); goto fail; } if (((rnd = BN_new()) == NULL) || ((cofactor = BN_new()) == NULL) || ((sess->pwe = EC_POINT_new(sess->group)) == NULL) || ((sess->order = BN_new()) == NULL) || ((sess->prime = BN_new()) == NULL) || ((x_candidate = BN_new()) == NULL)) { DEBUG("unable to create bignums"); goto fail; } if (!EC_GROUP_get_curve_GFp(sess->group, sess->prime, NULL, NULL, NULL)) { DEBUG("unable to get prime for GFp curve"); goto fail; } if (!EC_GROUP_get_order(sess->group, sess->order, NULL)) { DEBUG("unable to get order for curve"); goto fail; } if (!EC_GROUP_get_cofactor(sess->group, cofactor, NULL)) { DEBUG("unable to get cofactor for curve"); goto fail; } primebitlen = BN_num_bits(sess->prime); primebytelen = BN_num_bytes(sess->prime); if ((prfbuf = talloc_zero_array(sess, uint8_t, primebytelen)) == NULL) { DEBUG("unable to alloc space for prf buffer"); goto fail; } ctr = 0; while (1) { if (ctr > 10) { DEBUG("unable to find random point on curve for group %d, something's fishy", grp_num); goto fail; } ctr++; /* * compute counter-mode password value and stretch to prime * pwd-seed = H(token | peer-id | server-id | password | * counter) */ H_Init(&ctx); H_Update(&ctx, (uint8_t *)token, sizeof(*token)); H_Update(&ctx, (uint8_t *)id_peer, id_peer_len); H_Update(&ctx, (uint8_t *)id_server, id_server_len); H_Update(&ctx, (uint8_t *)password, password_len); H_Update(&ctx, (uint8_t *)&ctr, sizeof(ctr)); H_Final(&ctx, pwe_digest); BN_bin2bn(pwe_digest, SHA256_DIGEST_LENGTH, rnd); eap_pwd_kdf(pwe_digest, SHA256_DIGEST_LENGTH, "EAP-pwd Hunting And Pecking", strlen("EAP-pwd Hunting And Pecking"), prfbuf, primebitlen); 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, sess->prime) >= 0) { continue; } /* * 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(sess->group, sess->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(sess->group, sess->pwe, NULL)) { DEBUG("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(sess->group, sess->pwe, NULL, sess->pwe, cofactor, NULL)) { DEBUG("EAP-pwd: cannot multiply generator by order"); continue; } if (EC_POINT_is_at_infinity(sess->group, sess->pwe)) { DEBUG("EAP-pwd: point is at infinity"); continue; } } /* if we got here then we have a new generator. */ break; } sess->group_num = grp_num; if (0) { fail: /* DON'T free sess, it's in handler->opaque */ ret = -1; } /* cleanliness and order.... */ BN_free(cofactor); BN_free(x_candidate); BN_free(rnd); talloc_free(prfbuf); 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); }
int BFIBE_setup(const EC_GROUP *group, const EVP_MD *md, BFPublicParameters **pmpk, BFMasterSecret **pmsk) { int ret = 0; BFPublicParameters *mpk = NULL; BFMasterSecret *msk = NULL; BN_CTX *bn_ctx = NULL; EC_POINT *point = NULL; BIGNUM *a; BIGNUM *b; if (!group || !pmpk || !pmsk) { BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (!(bn_ctx = BN_CTX_new())) { BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_MALLOC_FAILURE); goto end; } BN_CTX_start(bn_ctx); a = BN_CTX_get(bn_ctx); b = BN_CTX_get(bn_ctx); if (!b) { BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_MALLOC_FAILURE); goto end; } mpk = BFPublicParameters_new(); msk = BFMasterSecret_new(); point = EC_POINT_new(group); if (!mpk || !msk || !point) { BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_MALLOC_FAILURE); goto end; } /* * set mpk->version * set mpk->curve */ mpk->version = BFIBE_VERSION; OPENSSL_assert(mpk->curve); ASN1_OBJECT_free(mpk->curve); if (!(mpk->curve = OBJ_nid2obj(NID_type1curve))) { BFIBEerr(BFIBE_F_BFIBE_SETUP, BFIBE_R_NOT_NAMED_CURVE); goto end; } /* mpk->p = group->p */ if (!EC_GROUP_get_curve_GFp(group, mpk->p, a, b, bn_ctx)) { BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_EC_LIB); goto end; } if (!BN_is_zero(a) || !BN_is_one(b)) { BFIBEerr(BFIBE_F_BFIBE_SETUP, BFIBE_R_INVALID_TYPE1CURVE); goto end; } /* mpk->q = group->order */ if (!EC_GROUP_get_order(group, mpk->q, bn_ctx)) { BFIBEerr(BFIBE_F_BFIBE_SETUP, BFIBE_R_INVALID_TYPE1CURVE); goto end; } /* mpk->pointP = group->generator */ if (!EC_POINT_get_affine_coordinates_GFp(group, EC_GROUP_get0_generator(group), mpk->pointP->x, mpk->pointP->y, bn_ctx)) { BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_EC_LIB); goto end; } /* set mpk->hashfcn from F_p^2 element bits */ OPENSSL_assert(mpk->hashfcn); ASN1_OBJECT_free(mpk->hashfcn); if (!(mpk->hashfcn = OBJ_nid2obj(EVP_MD_type(md)))) { BFIBEerr(BFIBE_F_BFIBE_SETUP, BFIBE_R_PARSE_PAIRING); goto end; } /* * set msk->version * random msk->masterSecret in [2, q - 1] */ msk->version = BFIBE_VERSION; do { if (!BN_rand_range(msk->masterSecret, mpk->q)) { BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_BN_LIB); goto end; } } while (BN_is_zero(msk->masterSecret) || BN_is_one(msk->masterSecret)); /* mpk->pointPpub = msk->masterSecret * mpk->pointP */ if (!EC_POINT_mul(group, point, msk->masterSecret, NULL, NULL, bn_ctx)) { BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_EC_LIB); goto end; } if (!EC_POINT_get_affine_coordinates_GFp(group, point, mpk->pointPpub->x, mpk->pointPpub->y, bn_ctx)) { BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_EC_LIB); goto end; } /* set return value */ *pmpk = mpk; *pmsk = msk; ret = 1; end: if (!ret) { BFPublicParameters_free(mpk); BFMasterSecret_free(msk); *pmpk = NULL; *pmsk = NULL; } if (bn_ctx) { BN_CTX_end(bn_ctx); } BN_CTX_free(bn_ctx); EC_POINT_free(point); 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; }
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); }
void prime_field_tests() { BN_CTX *ctx = NULL; BIGNUM *p, *a, *b; EC_GROUP *group; EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL, *P_256 = NULL, *P_384 = NULL, *P_521 = NULL; EC_POINT *P, *Q, *R; BIGNUM *x, *y, *z; unsigned char buf[100]; size_t i, len; int k; #if 1 /* optional */ ctx = BN_CTX_new(); if (!ctx) ABORT; #endif p = BN_new(); a = BN_new(); b = BN_new(); if (!p || !a || !b) ABORT; if (!BN_hex2bn(&p, "17")) ABORT; if (!BN_hex2bn(&a, "1")) ABORT; if (!BN_hex2bn(&b, "1")) ABORT; group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use EC_GROUP_new_curve_GFp * so that the library gets to choose the EC_METHOD */ if (!group) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; { EC_GROUP *tmp; tmp = EC_GROUP_new(EC_GROUP_method_of(group)); if (!tmp) ABORT; if (!EC_GROUP_copy(tmp, group)) ABORT; EC_GROUP_free(group); group = tmp; } if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) ABORT; fprintf(stdout, "Curve defined by Weierstrass equation\n y^2 = x^3 + a*x + b (mod 0x"); BN_print_fp(stdout, p); fprintf(stdout, ")\n a = 0x"); BN_print_fp(stdout, a); fprintf(stdout, "\n b = 0x"); BN_print_fp(stdout, b); fprintf(stdout, "\n"); P = EC_POINT_new(group); Q = EC_POINT_new(group); R = EC_POINT_new(group); if (!P || !Q || !R) ABORT; if (!EC_POINT_set_to_infinity(group, P)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; buf[0] = 0; if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT; if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; x = BN_new(); y = BN_new(); z = BN_new(); if (!x || !y || !z) ABORT; if (!BN_hex2bn(&x, "D")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, Q, ctx)) { if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx)) ABORT; fprintf(stderr, "Point is not on curve: x = 0x"); BN_print_fp(stderr, x); fprintf(stderr, ", y = 0x"); BN_print_fp(stderr, y); fprintf(stderr, "\n"); ABORT; } fprintf(stdout, "A cyclic subgroup:\n"); k = 100; do { if (k-- == 0) ABORT; if (EC_POINT_is_at_infinity(group, P)) fprintf(stdout, " point at infinity\n"); else { if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, " x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, ", y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); } if (!EC_POINT_copy(R, P)) ABORT; if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; #if 0 /* optional */ { EC_POINT *points[3]; points[0] = R; points[1] = Q; points[2] = P; if (!EC_POINTs_make_affine(group, 2, points, ctx)) ABORT; } #endif } while (!EC_POINT_is_at_infinity(group, P)); if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "Generator as octect string, compressed form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "\nGenerator as octect string, uncompressed form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "\nGenerator as octect string, hybrid form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT; fprintf(stdout, "\nA representation of the inverse of that generator in\nJacobian projective coordinates:\n X = 0x"); BN_print_fp(stdout, x); fprintf(stdout, ", Y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, ", Z = 0x"); BN_print_fp(stdout, z); fprintf(stdout, "\n"); if (!EC_POINT_invert(group, P, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; /* Curve secp160r1 (Certicom Research SEC 2 Version 1.0, section 2.4.2, 2000) * -- not a NIST curve, but commonly used */ if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC")) ABORT; if (!BN_hex2bn(&b, "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) ABORT; if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) ABORT; if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nSEC2 curve secp160r1 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "23a628553168947d59dcc912042351377ac5fb32")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 160) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_160, group)) ABORT; /* Curve P-192 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")) ABORT; if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-192 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 192) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_192, group)) ABORT; /* Curve P-224 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")) ABORT; if (!BN_hex2bn(&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-224 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 224) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_224, group)) ABORT; /* Curve P-256 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")) ABORT; if (!BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E" "84F3B9CAC2FC632551")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-256 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 256) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_256, group)) ABORT; /* Curve P-384 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")) ABORT; if (!BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141" "120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B" "9859F741E082542A385502F25DBF55296C3A545E3872760AB7")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-384 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A14" "7CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 384) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_384, group)) ABORT; /* Curve P-521 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFFFFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFFFFFFFFC")) ABORT; if (!BN_hex2bn(&b, "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B" "315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573" "DF883D2C34F1EF451FD46B503F00")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "C6858E06B70404E9CD9E3ECB662395B4429C648139053F" "B521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B" "3C1856A429BF97E7E31C2E5BD66")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5" "C9B8899C47AEBB6FB71E91386409")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-521 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579" "B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C" "7086A272C24088BE94769FD16650")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 521) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_521, group)) ABORT; /* more tests using the last curve */ if (!EC_POINT_copy(Q, P)) ABORT; if (EC_POINT_is_at_infinity(group, Q)) ABORT; if (!EC_POINT_dbl(group, P, P, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */ if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT; if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */ { const EC_POINT *points[3]; const BIGNUM *scalars[3]; if (EC_POINT_is_at_infinity(group, Q)) ABORT; points[0] = Q; points[1] = Q; points[2] = Q; if (!BN_add(y, z, BN_value_one())) ABORT; if (BN_is_odd(y)) ABORT; if (!BN_rshift1(y, y)) ABORT; scalars[0] = y; /* (group order + 1)/2, so y*Q + y*Q = Q */ scalars[1] = y; fprintf(stdout, "combined multiplication ..."); fflush(stdout); /* z is still the group order */ if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT; if (!BN_add(z, z, y)) ABORT; BN_set_negative(z, 1); scalars[0] = y; scalars[1] = z; /* z = -(order + y) */ if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT; if (!BN_add(z, x, y)) ABORT; BN_set_negative(z, 1); scalars[0] = x; scalars[1] = y; scalars[2] = z; /* z = -(x+y) */ if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; fprintf(stdout, " ok\n\n"); } #if 0 timings(P_160, TIMING_BASE_PT, ctx); timings(P_160, TIMING_RAND_PT, ctx); timings(P_160, TIMING_SIMUL, ctx); timings(P_192, TIMING_BASE_PT, ctx); timings(P_192, TIMING_RAND_PT, ctx); timings(P_192, TIMING_SIMUL, ctx); timings(P_224, TIMING_BASE_PT, ctx); timings(P_224, TIMING_RAND_PT, ctx); timings(P_224, TIMING_SIMUL, ctx); timings(P_256, TIMING_BASE_PT, ctx); timings(P_256, TIMING_RAND_PT, ctx); timings(P_256, TIMING_SIMUL, ctx); timings(P_384, TIMING_BASE_PT, ctx); timings(P_384, TIMING_RAND_PT, ctx); timings(P_384, TIMING_SIMUL, ctx); timings(P_521, TIMING_BASE_PT, ctx); timings(P_521, TIMING_RAND_PT, ctx); timings(P_521, TIMING_SIMUL, ctx); #endif if (ctx) BN_CTX_free(ctx); BN_free(p); BN_free(a); BN_free(b); EC_GROUP_free(group); EC_POINT_free(P); EC_POINT_free(Q); EC_POINT_free(R); BN_free(x); BN_free(y); BN_free(z); if (P_160) EC_GROUP_free(P_160); if (P_192) EC_GROUP_free(P_192); if (P_224) EC_GROUP_free(P_224); if (P_256) EC_GROUP_free(P_256); if (P_384) EC_GROUP_free(P_384); if (P_521) EC_GROUP_free(P_521); }
int ecdh_im_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in, BN_CTX *bn_ctx) { int ret = 0; BUF_MEM * x_mem = NULL; BIGNUM * a = NULL, *b = NULL, *p = NULL; BIGNUM * x = NULL, *y = NULL, *v = NULL, *u = NULL; BIGNUM * tmp = NULL, *tmp2 = NULL, *bn_inv = NULL; BIGNUM * two = NULL, *three = NULL, *four = NULL, *six = NULL; BIGNUM * twentyseven = NULL; EC_KEY *static_key = NULL, *ephemeral_key = NULL; EC_POINT *g = NULL; BN_CTX_start(bn_ctx); check((ctx && ctx->static_key && s && ctx->ka_ctx), "Invalid arguments"); static_key = EVP_PKEY_get1_EC_KEY(ctx->static_key); if (!static_key) goto err; /* Setup all the variables*/ a = BN_CTX_get(bn_ctx); b = BN_CTX_get(bn_ctx); p = BN_CTX_get(bn_ctx); x = BN_CTX_get(bn_ctx); y = BN_CTX_get(bn_ctx); v = BN_CTX_get(bn_ctx); two = BN_CTX_get(bn_ctx); three = BN_CTX_get(bn_ctx); four = BN_CTX_get(bn_ctx); six = BN_CTX_get(bn_ctx); twentyseven = BN_CTX_get(bn_ctx); tmp = BN_CTX_get(bn_ctx); tmp2 = BN_CTX_get(bn_ctx); bn_inv = BN_CTX_get(bn_ctx); if (!bn_inv) goto err; /* Encrypt the Nonce using the symmetric key in */ x_mem = cipher_no_pad(ctx->ka_ctx, NULL, in, s, 1); if (!x_mem) goto err; /* Fetch the curve parameters */ if (!EC_GROUP_get_curve_GFp(EC_KEY_get0_group(static_key), p, a, b, bn_ctx)) goto err; /* Assign constants */ if ( !BN_set_word(two,2)|| !BN_set_word(three,3)|| !BN_set_word(four,4)|| !BN_set_word(six,6)|| !BN_set_word(twentyseven,27) ) goto err; /* Check prerequisites for curve parameters */ check( /* p > 3;*/ (BN_cmp(p, three) == 1) && /* p mod 3 = 2; (p has the form p=q^n, q prime) */ BN_nnmod(tmp, p, three, bn_ctx) && (BN_cmp(tmp, two) == 0), "Unsuited curve"); /* Convert encrypted nonce to BIGNUM */ u = BN_bin2bn((unsigned char *) x_mem->data, x_mem->length, u); if (!u) goto err; if ( /* v = (3a - u^4) / 6u mod p */ !BN_mod_mul(tmp, three, a, p, bn_ctx) || !BN_mod_exp(tmp2, u, four, p, bn_ctx) || !BN_mod_sub(v, tmp, tmp2, p, bn_ctx) || !BN_mod_mul(tmp, u, six, p, bn_ctx) || /* For division within a galois field we need to compute * the multiplicative inverse of a number */ !BN_mod_inverse(bn_inv, tmp, p, bn_ctx) || !BN_mod_mul(v, v, bn_inv, p, bn_ctx) || /* x = (v^2 - b - ((u^6)/27)) */ !BN_mod_sqr(tmp, v, p, bn_ctx) || !BN_mod_sub(tmp2, tmp, b, p, bn_ctx) || !BN_mod_exp(tmp, u, six, p, bn_ctx) || !BN_mod_inverse(bn_inv, twentyseven, p, bn_ctx) || !BN_mod_mul(tmp, tmp, bn_inv, p, bn_ctx) || !BN_mod_sub(x, tmp2, tmp, p, bn_ctx) || /* x -> x^(1/3) = x^((2p^n -1)/3) */ !BN_mul(tmp, two, p, bn_ctx) || !BN_sub(tmp, tmp, BN_value_one()) || /* Division is defined, because p^n = 2 mod 3 */ !BN_div(tmp, y, tmp, three, bn_ctx) || !BN_mod_exp(tmp2, x, tmp, p, bn_ctx) || !BN_copy(x, tmp2) || /* x += (u^2)/3 */ !BN_mod_sqr(tmp, u, p, bn_ctx) || !BN_mod_inverse(bn_inv, three, p, bn_ctx) || !BN_mod_mul(tmp2, tmp, bn_inv, p, bn_ctx) || !BN_mod_add(tmp, x, tmp2, p, bn_ctx) || !BN_copy(x, tmp) || /* y = ux + v */ !BN_mod_mul(y, u, x, p, bn_ctx) || !BN_mod_add(tmp, y, v, p, bn_ctx) || !BN_copy(y, tmp) ) goto err; /* Initialize ephemeral parameters with parameters from the static key */ ephemeral_key = EC_KEY_dup(static_key); if (!ephemeral_key) goto err; EVP_PKEY_set1_EC_KEY(ctx->ka_ctx->key, ephemeral_key); /* configure the new EC_KEY */ g = EC_POINT_new(EC_KEY_get0_group(ephemeral_key)); if (!g) goto err; if (!EC_POINT_set_affine_coordinates_GFp(EC_KEY_get0_group(ephemeral_key), g, x, y, bn_ctx)) goto err; ret = 1; err: if (x_mem) BUF_MEM_free(x_mem); if (u) BN_free(u); BN_CTX_end(bn_ctx); if (g) EC_POINT_clear_free(g); /* Decrement reference count, keys are still available via PACE_CTX */ if (static_key) EC_KEY_free(static_key); if (ephemeral_key) EC_KEY_free(ephemeral_key); return ret; }
int main(int argc, const char *argv[]) { int r; int ok = 0; char *prog = "ecc"; // libpopt var poptContext popt_ctx; const char **rest; int command = 0; char *curve_name = "secp192k1"; int point_compressed = 0; point_conversion_form_t point_form; struct poptOption options[] = { {"curve-name", 'c', POPT_ARG_STRING, &curve_name, 0, "elliptic curve name", "NAME"}, {"point-compressed", 'z', POPT_ARG_NONE, &point_compressed, 0, "point format, compress or uncompress", NULL}, {"print-curve", 'p', POPT_ARG_VAL, &command, ECC_PRINT, "print elliptic curve parameters", NULL}, {"random-private-key", 0, POPT_ARG_VAL, &command, ECC_RAND_SKEY, "random generate a private key\n", NULL}, {"random-keypair", 0, POPT_ARG_VAL, &command, ECC_RAND_KEYPAIR, "generate a random key pair\n", NULL}, {"check-point", 'e', POPT_ARG_VAL, &command, ECC_CHECK_POINT, "check if point is valid\n", NULL}, {"point-add", 'a', POPT_ARG_VAL, &command, ECC_ADD, "elliptic curve point addition", NULL}, {"point-double", 'b', POPT_ARG_VAL, &command, ECC_DOUBLE, "elliptic curve point double", NULL}, {"point-mul", 'x', POPT_ARG_VAL, &command, ECC_MUL, "k*G", NULL}, {"point-mul-generator", 'X', POPT_ARG_VAL, &command, ECC_MUL_G, "elliptic curve point scalar multiply", NULL}, {"point-invert", 'i', POPT_ARG_VAL, &command, ECC_INVERT, "elliptic curve point inverse", NULL}, {"ecdsa-sign", 's', POPT_ARG_VAL, &command, ECC_SIGN, "ecdsa sign", NULL}, {"ecdsa-verify", 'v', POPT_ARG_VAL, &command, ECC_VERIFY, "ecdsa verify", NULL}, POPT_AUTOHELP POPT_TABLEEND }; // openssl var EC_GROUP *ec_group = NULL; EC_POINT *P = NULL; EC_POINT *Q = NULL; EC_POINT *R = NULL; BIGNUM *k = BN_new(); BN_CTX *bn_ctx = BN_CTX_new(); // argument parsing popt_ctx = poptGetContext(argv[0], argc, argv, options, 0); if ((r = poptGetNextOpt(popt_ctx)) < -1) { fprintf(stderr, "%s: bad argument %s: %s\n", argv[0], poptBadOption(popt_ctx, POPT_BADOPTION_NOALIAS), poptStrerror(r)); goto exit; } rest = poptGetArgs(popt_ctx); // check arguments ec_group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve_name)); if (ec_group == NULL) { fprintf(stderr, "%s: unknown curve name\n", prog); goto exit; } P = EC_POINT_new(ec_group); Q = EC_POINT_new(ec_group); R = EC_POINT_new(ec_group); point_form = point_compressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED; switch (command) { case ECC_PRINT: { BIGNUM *p = BN_new(); BIGNUM *a = BN_new(); BIGNUM *b = BN_new(); char *generator; BIGNUM *order = BN_new(); BIGNUM *cofactor = BN_new(); EC_GROUP_get_curve_GFp(ec_group, p, a, b, bn_ctx); generator = EC_POINT_point2hex(ec_group, EC_GROUP_get0_generator(ec_group), point_form, bn_ctx); EC_GROUP_get_order(ec_group, order, bn_ctx); EC_GROUP_get_cofactor(ec_group, cofactor, bn_ctx); fprintf(stdout, "Name : %s\n", OBJ_nid2sn(EC_GROUP_get_curve_name(ec_group))); fprintf(stdout, "FieldType : %s\n", "PrimeField"); fprintf(stdout, "Prime : %s\n", BN_bn2hex(p)); fprintf(stdout, "A : %s\n", BN_bn2hex(a)); fprintf(stdout, "B : %s\n", BN_bn2hex(b)); fprintf(stdout, "Generator : %s\n", generator); fprintf(stdout, "Order : %s\n", BN_bn2hex(order)); fprintf(stdout, "Cofactor : %s\n", BN_bn2hex(cofactor)); BN_free(p); BN_free(a); BN_free(b); BN_free(order); BN_free(cofactor); break; } case ECC_CHECK_POINT: { if (!rest) { fprintf(stderr, "%s: short of point\n", prog); goto exit; } if (!rest[0]) { fprintf(stderr, "%s: short of point\n", prog); goto exit; } if (EC_POINT_hex2point(ec_group, rest[0], P, bn_ctx)) fprintf(stdout, "ture\n"); else fprintf(stdout, "false\n"); break; } case ECC_RAND_SKEY: { EC_KEY *ec_key = EC_KEY_new(); EC_KEY_set_group(ec_key, ec_group); EC_KEY_generate_key(ec_key); fprintf(stdout, "%s\n", BN_bn2hex(EC_KEY_get0_private_key(ec_key))); EC_KEY_free(ec_key); break; } case ECC_RAND_KEYPAIR: { EC_KEY *ec_key = EC_KEY_new(); EC_KEY_set_group(ec_key, ec_group); EC_KEY_generate_key(ec_key); fprintf(stdout, "%s\n", BN_bn2hex(EC_KEY_get0_private_key(ec_key))); fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, EC_KEY_get0_public_key(ec_key), point_form, bn_ctx)); EC_KEY_free(ec_key); break; } case ECC_ADD: { if (!rest) { fprintf(stderr, "%s: short of point\n", prog); goto exit; } if (!rest[0] || !rest[1]) { fprintf(stderr, "%s: short of point\n", prog); goto exit; } if (!EC_POINT_hex2point(ec_group, rest[1], P, bn_ctx)) { fprintf(stderr, "%s: first point invalid\n", prog); goto exit; } if (!EC_POINT_hex2point(ec_group, rest[1], Q, bn_ctx)) { fprintf(stderr, "%s: second point invalid\n", prog); goto exit; } EC_POINT_add(ec_group, R, P, Q, bn_ctx); fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, R, point_form, bn_ctx)); break; } case ECC_DOUBLE: { EC_POINT_dbl(ec_group, R, P, bn_ctx); fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, R, point_form, bn_ctx)); break; } case ECC_MUL: { BIGNUM *order = NULL; if (!BN_hex2bn(&k, rest[0])) { fprintf(stderr, "%s: integer invalid\n", prog); goto exit; } order = BN_new(); EC_GROUP_get_order(ec_group, order, bn_ctx); if (BN_cmp(k, order) >= 0) { fprintf(stderr, "%s: integer value invalid\n", prog); BN_free(order); goto exit; } BN_free(order); if (!EC_POINT_hex2point(ec_group, rest[1], P, bn_ctx)) { fprintf(stderr, "%s: point invalid\n", prog); goto exit; } EC_POINT_mul(ec_group, R, k, P, NULL, bn_ctx); fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, R, point_form, bn_ctx)); break; } case ECC_MUL_G: { BIGNUM *order = NULL; if (!BN_hex2bn(&k, rest[0])) { fprintf(stderr, "%s: integer format invalid\n", prog); goto exit; } order = BN_new(); EC_GROUP_get_order(ec_group, order, bn_ctx); if (BN_cmp(k, order) >= 0) { fprintf(stderr, "%s: integer value invalid\n", prog); BN_free(order); goto exit; } BN_free(order); EC_POINT_mul(ec_group, R, k, EC_GROUP_get0_generator(ec_group), NULL, bn_ctx); fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, R, point_form, bn_ctx)); break; } default: fprintf(stderr, "%s: command is required\n", prog); break; } ok = 1; exit: if (ec_group) EC_GROUP_free(ec_group); if (P) EC_POINT_free(P); if (k) BN_free(k); if (bn_ctx) BN_CTX_free(bn_ctx); return ok ? 0 : -1; }
static void timings(EC_GROUP *group, int multi, BN_CTX *ctx) { clock_t clck; int i, j; BIGNUM *s, *s0; EC_POINT *P; s = BN_new(); s0 = BN_new(); if (s == NULL || s0 == NULL) ABORT; if (!EC_GROUP_get_curve_GFp(group, s, NULL, NULL, ctx)) ABORT; fprintf(stdout, "Timings for %d bit prime, ", (int)BN_num_bits(s)); if (!EC_GROUP_get_order(group, s, ctx)) ABORT; fprintf(stdout, "%d bit scalars ", (int)BN_num_bits(s)); fflush(stdout); P = EC_POINT_new(group); if (P == NULL) ABORT; EC_POINT_copy(P, EC_GROUP_get0_generator(group)); clck = clock(); for (i = 0; i < 10; i++) { if (!BN_pseudo_rand(s, BN_num_bits(s), 0, 0)) ABORT; if (multi) { if (!BN_pseudo_rand(s0, BN_num_bits(s), 0, 0)) ABORT; } for (j = 0; j < 10; j++) { if (!EC_POINT_mul(group, P, s, multi ? P : NULL, multi ? s0 : NULL, ctx)) ABORT; } fprintf(stdout, "."); fflush(stdout); } fprintf(stdout, "\n"); clck = clock() - clck; #ifdef CLOCKS_PER_SEC /* "To determine the time in seconds, the value returned * by the clock function should be divided by the value * of the macro CLOCKS_PER_SEC." * -- ISO/IEC 9899 */ # define UNIT "s" #else /* "`CLOCKS_PER_SEC' undeclared (first use this function)" * -- cc on NeXTstep/OpenStep */ # define UNIT "units" # define CLOCKS_PER_SEC 1 #endif fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j, multi ? "s*P+t*Q operations" : "point multiplications", (double)clck/CLOCKS_PER_SEC); fprintf(stdout, "average: %.4f " UNIT "\n", (double)clck/(CLOCKS_PER_SEC*i*j)); EC_POINT_free(P); BN_free(s); BN_free(s0); }
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; }