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; }
static void eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data, struct eap_method_ret *ret, const struct wpabuf *reqData, const u8 *payload, size_t payload_len) { EC_POINT *K = NULL, *point = NULL; BIGNUM *mask = NULL, *x = NULL, *y = NULL, *cofactor = NULL; u16 offset; u8 *ptr, *scalar = NULL, *element = NULL; if (((data->private_value = BN_new()) == NULL) || ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) || ((cofactor = BN_new()) == NULL) || ((data->my_scalar = BN_new()) == NULL) || ((mask = BN_new()) == NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): scalar allocation fail"); goto fin; } if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) { wpa_printf(MSG_INFO, "EAP-pwd (peer): unable to get cofactor " "for curve"); goto fin; } BN_rand_range(data->private_value, data->grp->order); BN_rand_range(mask, data->grp->order); BN_add(data->my_scalar, data->private_value, mask); BN_mod(data->my_scalar, data->my_scalar, data->grp->order, data->bnctx); if (!EC_POINT_mul(data->grp->group, data->my_element, NULL, data->grp->pwe, mask, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): element allocation " "fail"); eap_pwd_state(data, FAILURE); goto fin; } if (!EC_POINT_invert(data->grp->group, data->my_element, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail"); goto fin; } BN_free(mask); if (((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): point allocation fail"); goto fin; } /* process the request */ if (((data->server_scalar = BN_new()) == NULL) || ((data->k = BN_new()) == NULL) || ((K = EC_POINT_new(data->grp->group)) == NULL) || ((point = EC_POINT_new(data->grp->group)) == NULL) || ((data->server_element = EC_POINT_new(data->grp->group)) == NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): peer data allocation " "fail"); goto fin; } /* element, x then y, followed by scalar */ ptr = (u8 *) payload; BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x); ptr += BN_num_bytes(data->grp->prime); BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y); ptr += BN_num_bytes(data->grp->prime); BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->server_scalar); if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group, data->server_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): setting peer element " "fail"); goto fin; } /* check to ensure server's element is not in a small sub-group */ if (BN_cmp(cofactor, BN_value_one())) { if (!EC_POINT_mul(data->grp->group, point, NULL, data->server_element, cofactor, NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply " "server element by order!\n"); goto fin; } if (EC_POINT_is_at_infinity(data->grp->group, point)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): server element " "is at infinity!\n"); goto fin; } } /* compute the shared key, k */ if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe, data->server_scalar, data->bnctx)) || (!EC_POINT_add(data->grp->group, K, K, data->server_element, data->bnctx)) || (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value, data->bnctx))) { wpa_printf(MSG_INFO, "EAP-PWD (peer): computing shared key " "fail"); goto fin; } /* ensure that the shared key isn't in a small sub-group */ if (BN_cmp(cofactor, BN_value_one())) { if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor, NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply " "shared key point by order"); goto fin; } } /* * This check is strictly speaking just for the case above where * co-factor > 1 but it was suggested that even though this is probably * never going to happen it is a simple and safe check "just to be * sure" so let's be safe. */ if (EC_POINT_is_at_infinity(data->grp->group, K)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): shared key point is at " "infinity!\n"); goto fin; } if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k, NULL, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to extract " "shared secret from point"); goto fin; } /* now do the response */ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, data->my_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): point assignment fail"); goto fin; } if (((scalar = os_malloc(BN_num_bytes(data->grp->order))) == NULL) || ((element = os_malloc(BN_num_bytes(data->grp->prime) * 2)) == NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): data allocation fail"); goto fin; } /* * bignums occupy as little memory as possible so one that is * sufficiently smaller than the prime or order might need pre-pending * with zeros. */ os_memset(scalar, 0, BN_num_bytes(data->grp->order)); os_memset(element, 0, BN_num_bytes(data->grp->prime) * 2); offset = BN_num_bytes(data->grp->order) - BN_num_bytes(data->my_scalar); BN_bn2bin(data->my_scalar, scalar + offset); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); BN_bn2bin(x, element + offset); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset); data->outbuf = wpabuf_alloc(BN_num_bytes(data->grp->order) + 2 * BN_num_bytes(data->grp->prime)); if (data->outbuf == NULL) goto fin; /* we send the element as (x,y) follwed by the scalar */ wpabuf_put_data(data->outbuf, element, 2 * BN_num_bytes(data->grp->prime)); wpabuf_put_data(data->outbuf, scalar, BN_num_bytes(data->grp->order)); fin: os_free(scalar); os_free(element); BN_free(x); BN_free(y); BN_free(cofactor); EC_POINT_free(K); EC_POINT_free(point); if (data->outbuf == NULL) eap_pwd_state(data, FAILURE); else eap_pwd_state(data, PWD_Confirm_Req); }
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); }
/*- * 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 (EC_KEY_get_flags(ecdh) & EC_FLAG_COFACTOR_ECDH) { if (!EC_GROUP_get_cofactor(group, x, ctx) || !BN_mul(x, x, priv_key, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); goto err; } priv_key = x; } if ((tmp = EC_POINT_new(group)) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, y, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } #ifndef OPENSSL_NO_EC2M else { if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } #endif buflen = (EC_GROUP_get_degree(group) + 7) / 8; len = BN_num_bytes(x); if (len > buflen) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_INTERNAL_ERROR); goto err; } if ((buf = OPENSSL_malloc(buflen)) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); goto err; } memset(buf, 0, buflen - len); if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_BN_LIB); goto err; } if (KDF != 0) { if (KDF(buf, buflen, out, &outlen) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_KDF_FAILED); goto err; } ret = outlen; } else { /* no KDF, just copy as much as we can */ if (outlen > buflen) outlen = buflen; memcpy(out, buf, outlen); ret = outlen; } err: EC_POINT_free(tmp); if (ctx) BN_CTX_end(ctx); BN_CTX_free(ctx); OPENSSL_free(buf); 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); }
// unsigned char *pM 输出,明文 // unsigned char *pPDKey 私钥 // unsigned char *pC 密文 // unsigned long Clen 密文长度 unsigned char eccDecrypt(unsigned char *pM, unsigned char *pPDKey, unsigned char *pC, unsigned long Clen) { EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1); EC_GROUP *ec_group = EC_GROUP_new_by_curve_name(NID_sm2p256v1); KDF_FUNC kdf = KDF_get_x9_63(EVP_sm3()); // 设置私钥 BIGNUM *pri_key = BN_new(); BN_bin2bn(pPDKey, 32, pri_key); EC_KEY_set_private_key(ec_key, pri_key); int ret = 1; EC_POINT *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; int nbytes; size_t size; size_t i; if (!ec_group || !pri_key) { goto end; } if (!kdf) { goto end; } EC_POINT *ephem_point = EC_POINT_new(ec_group); EC_POINT_oct2point(ec_group, ephem_point, pC, 65, NULL); /* init vars */ point = EC_POINT_new(ec_group); n = BN_new(); h = BN_new(); bn_ctx = BN_CTX_new(); md_ctx = EVP_MD_CTX_create(); if (!point || !n || !h || !bn_ctx || !md_ctx) { goto end; } /* init ec domain parameters */ if (!EC_GROUP_get_order(ec_group, n, bn_ctx)) { goto end; } if (!EC_GROUP_get_cofactor(ec_group, h, bn_ctx)) { goto end; } nbytes = (EC_GROUP_get_degree(ec_group) + 7) / 8; /* B2: check [h]C1 != O */ if (!EC_POINT_mul(ec_group, point, NULL, ephem_point, h, bn_ctx)) { goto end; } if (EC_POINT_is_at_infinity(ec_group, point)) { goto end; } /* B3: compute ECDH [d]C1 = (x2, y2) */ if (!EC_POINT_mul(ec_group, point, NULL, ephem_point, pri_key, bn_ctx)) { goto end; } if (!(size = EC_POINT_point2oct(ec_group, point, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) { goto end; } OPENSSL_assert(size == 1 + nbytes * 2); /* B4: compute t = KDF(x2 || y2, clen) */ size_t len = 0; size_t *outlen = &len; *outlen = Clen - 97; //FIXME: duplicated code unsigned char *out = (unsigned char *)OPENSSL_malloc(*outlen); kdf(buf + 1, size - 1, out, outlen); unsigned char *ciphertext = pC + 65; /* B5: compute M = C2 xor t */ for (i = 0; i < len; i++) { out[i] ^= ciphertext[i]; } *outlen = len; if (1) { /* B6: check Hash(x2 || M || y2) == C3 */ if (!EVP_DigestInit_ex(md_ctx, EVP_sm3(), NULL)) { goto end; } if (!EVP_DigestUpdate(md_ctx, buf + 1, nbytes)) { goto end; } if (!EVP_DigestUpdate(md_ctx, out, *outlen)) { goto end; } if (!EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes)) { goto end; } if (!EVP_DigestFinal_ex(md_ctx, mac, &maclen)) { goto end; } /* GmSSL specific */ if (memcmp(mac, pC + 129, 32)) { goto end; } } for (i = 0; i < len; i++) { pM[i] = out[i] ; } ret = 0; end: if (point) EC_POINT_free(point); if (n) BN_free(n); if (h) BN_free(h); if (bn_ctx) BN_CTX_free(bn_ctx); if (md_ctx) EVP_MD_CTX_destroy(md_ctx); 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; }
SM2_CIPHERTEXT_VALUE *SM2_do_encrypt(const EVP_MD *kdf_md, const EVP_MD *mac_md, const unsigned char *in, size_t inlen, EC_KEY *ec_key) { int ok = 0; SM2_CIPHERTEXT_VALUE *cv = NULL; const EC_GROUP *ec_group = EC_KEY_get0_group(ec_key); const EC_POINT *pub_key = EC_KEY_get0_public_key(ec_key); KDF_FUNC kdf = KDF_get_x9_63(kdf_md); EC_POINT *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; int i; if (!ec_group || !pub_key) { goto end; } if (!kdf) { goto end; } /* init ciphertext_value */ if (!(cv = OPENSSL_malloc(sizeof(SM2_CIPHERTEXT_VALUE)))) { goto end; } bzero(cv, sizeof(SM2_CIPHERTEXT_VALUE)); cv->ephem_point = EC_POINT_new(ec_group); cv->ciphertext = OPENSSL_malloc(inlen); cv->ciphertext_size = inlen; if (!cv->ephem_point || !cv->ciphertext) { goto end; } point = EC_POINT_new(ec_group); n = BN_new(); h = BN_new(); k = BN_new(); bn_ctx = BN_CTX_new(); md_ctx = EVP_MD_CTX_create(); if (!point || !n || !h || !k || !bn_ctx || !md_ctx) { goto end; } /* init ec domain parameters */ if (!EC_GROUP_get_order(ec_group, n, bn_ctx)) { goto end; } if (!EC_GROUP_get_cofactor(ec_group, h, bn_ctx)) { goto end; } nbytes = (EC_GROUP_get_degree(ec_group) + 7) / 8; OPENSSL_assert(nbytes == BN_num_bytes(n)); #if 0 /* check sm2 curve and md is 256 bits */ OPENSSL_assert(nbytes == 32); OPENSSL_assert(EVP_MD_size(kdf_md) == 32); OPENSSL_assert(EVP_MD_size(mac_md) == 32); #endif do { /* A1: rand k in [1, n-1] */ do { BN_rand_range(k, n); } while (BN_is_zero(k)); /* A2: C1 = [k]G = (x1, y1) */ if (!EC_POINT_mul(ec_group, cv->ephem_point, k, NULL, NULL, bn_ctx)) { goto end; } /* A3: check [h]P_B != O */ if (!EC_POINT_mul(ec_group, point, NULL, pub_key, h, bn_ctx)) { goto end; } if (EC_POINT_is_at_infinity(ec_group, point)) { goto end; } /* A4: compute ECDH [k]P_B = (x2, y2) */ if (!EC_POINT_mul(ec_group, point, NULL, pub_key, k, bn_ctx)) { goto end; } if (!(len = EC_POINT_point2oct(ec_group, point, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) { goto end; } OPENSSL_assert(len == nbytes * 2 + 1); /* A5: t = KDF(x2 || y2, klen) */ kdf(buf + 1, len - 1, cv->ciphertext, &cv->ciphertext_size); for (i = 0; i < cv->ciphertext_size; i++) { if (cv->ciphertext[i]) { break; } } if (i == cv->ciphertext_size) { continue; } break; } while (1); /* A6: C2 = M xor t */ for (i = 0; i < inlen; i++) { cv->ciphertext[i] ^= in[i]; } /* A7: C3 = Hash(x2 || M || y2) */ if (!EVP_DigestInit_ex(md_ctx, mac_md, NULL)) { goto end; } if (!EVP_DigestUpdate(md_ctx, buf + 1, nbytes)) { goto end; } if (!EVP_DigestUpdate(md_ctx, in, inlen)) { goto end; } if (!EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes)) { goto end; } if (!EVP_DigestFinal_ex(md_ctx, cv->mactag, &cv->mactag_size)) { goto end; } ok = 1; end: if (!ok && cv) { SM2_CIPHERTEXT_VALUE_free(cv); cv = NULL; } if (point) EC_POINT_free(point); if (n) BN_free(n); if (h) BN_free(h); if (k) BN_free(k); if (bn_ctx) BN_CTX_free(bn_ctx); if (md_ctx) EVP_MD_CTX_destroy(md_ctx); return cv; }
/* * 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 process_peer_commit(REQUEST *request, pwd_session_t *session, uint8_t *in, size_t in_len, BN_CTX *bn_ctx) { uint8_t *ptr; size_t data_len; BIGNUM *x = NULL, *y = NULL, *cofactor = NULL; EC_POINT *K = NULL, *point = NULL; int ret = 1; MEM(session->peer_scalar = BN_new()); MEM(session->k = BN_new()); MEM(session->peer_element = EC_POINT_new(session->group)); MEM(point = EC_POINT_new(session->group)); MEM(K = EC_POINT_new(session->group)); MEM(cofactor = BN_new()); MEM(x = BN_new()); MEM(y = BN_new()); if (!EC_GROUP_get_cofactor(session->group, cofactor, NULL)) { REDEBUG("Unable to get group co-factor"); goto finish; } /* element, x then y, followed by scalar */ ptr = (uint8_t *)in; data_len = BN_num_bytes(session->prime); /* * Did the peer send enough data? */ if (in_len < (2 * data_len + BN_num_bytes(session->order))) { REDEBUG("Invalid commit packet"); goto finish; } BN_bin2bn(ptr, data_len, x); ptr += data_len; BN_bin2bn(ptr, data_len, y); ptr += data_len; data_len = BN_num_bytes(session->order); BN_bin2bn(ptr, data_len, session->peer_scalar); /* validate received scalar */ if (BN_is_zero(session->peer_scalar) || BN_is_one(session->peer_scalar) || BN_cmp(session->peer_scalar, session->order) >= 0) { REDEBUG("Peer's scalar is not within the allowed range"); goto finish; } if (!EC_POINT_set_affine_coordinates_GFp(session->group, session->peer_element, x, y, bn_ctx)) { REDEBUG("Unable to get coordinates of peer's element"); goto finish; } /* validate received element */ if (!EC_POINT_is_on_curve(session->group, session->peer_element, bn_ctx) || EC_POINT_is_at_infinity(session->group, session->peer_element)) { REDEBUG("Peer's element is not a point on the elliptic curve"); goto finish; } /* check to ensure peer's element is not in a small sub-group */ if (BN_cmp(cofactor, BN_value_one())) { if (!EC_POINT_mul(session->group, point, NULL, session->peer_element, cofactor, NULL)) { REDEBUG("Unable to multiply element by co-factor"); goto finish; } if (EC_POINT_is_at_infinity(session->group, point)) { REDEBUG("Peer's element is in small sub-group"); goto finish; } } /* detect reflection attacks */ if (BN_cmp(session->peer_scalar, session->my_scalar) == 0 || EC_POINT_cmp(session->group, session->peer_element, session->my_element, bn_ctx) == 0) { REDEBUG("Reflection attack detected"); goto finish; } /* compute the shared key, k */ if ((!EC_POINT_mul(session->group, K, NULL, session->pwe, session->peer_scalar, bn_ctx)) || (!EC_POINT_add(session->group, K, K, session->peer_element, bn_ctx)) || (!EC_POINT_mul(session->group, K, NULL, K, session->private_value, bn_ctx))) { REDEBUG("Unable to compute shared key, k"); goto finish; } /* ensure that the shared key isn't in a small sub-group */ if (BN_cmp(cofactor, BN_value_one())) { if (!EC_POINT_mul(session->group, K, NULL, K, cofactor, NULL)) { REDEBUG("Unable to multiply k by co-factor"); goto finish; } } /* * This check is strictly speaking just for the case above where * co-factor > 1 but it was suggested that even though this is probably * never going to happen it is a simple and safe check "just to be * sure" so let's be safe. */ if (EC_POINT_is_at_infinity(session->group, K)) { REDEBUG("K is point-at-infinity"); goto finish; } if (!EC_POINT_get_affine_coordinates_GFp(session->group, K, session->k, NULL, bn_ctx)) { REDEBUG("Unable to get shared secret from K"); goto finish; } ret = 0; finish: EC_POINT_clear_free(K); EC_POINT_clear_free(point); BN_clear_free(cofactor); BN_clear_free(x); BN_clear_free(y); return ret; }
int ecdh_gm_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in, BN_CTX *bn_ctx) { int ret = 0; BUF_MEM * mem_h = NULL; BIGNUM * bn_s = NULL, *order = NULL, *cofactor = NULL; EC_POINT * ecp_h = NULL, *ecp_g = NULL; const ECDH_METHOD *default_method; EC_GROUP *group = NULL; EC_KEY *static_key = NULL, *ephemeral_key = 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); check(static_key, "could not get key object"); /* Extract group parameters */ group = EC_GROUP_dup(EC_KEY_get0_group(static_key)); order = BN_CTX_get(bn_ctx); cofactor = BN_CTX_get(bn_ctx); check(group && cofactor, "internal error"); if (!EC_GROUP_get_order(group, order, bn_ctx) || !EC_GROUP_get_cofactor(group, cofactor, bn_ctx)) goto err; /* Convert nonce to BIGNUM */ bn_s = BN_bin2bn((unsigned char *) s->data, s->length, bn_s); if (!bn_s) goto err; default_method = ECDH_get_default_method(); ECDH_set_default_method(ECDH_OpenSSL_Point()); /* complete the ECDH and get the resulting point h */ mem_h = ecdh_compute_key(ctx->static_key, in, bn_ctx); ECDH_set_default_method(default_method); ecp_h = EC_POINT_new(group); if (!mem_h || !ecp_h || !EC_POINT_oct2point(group, ecp_h, (unsigned char *) mem_h->data, mem_h->length, bn_ctx)) goto err; /* map to new generator */ ecp_g = EC_POINT_new(group); /* g' = g*s + h*1 */ if (!EC_POINT_mul(group, ecp_g, bn_s, ecp_h, BN_value_one(), bn_ctx)) 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 */ if (!EC_GROUP_set_generator(group, ecp_g, order, cofactor) || !EC_GROUP_check(group, bn_ctx) || !EC_KEY_set_group(ephemeral_key, group)) goto err; ret = 1; err: if (ecp_g) EC_POINT_clear_free(ecp_g); if (ecp_h) EC_POINT_clear_free(ecp_h); if (mem_h) BUF_MEM_free(mem_h); if (bn_s) BN_clear_free(bn_s); BN_CTX_end(bn_ctx); /* 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); if (group) EC_GROUP_clear_free(group); 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; }
int initialiseRingSigs() { if (fDebugRingSig) LogPrintf("initialiseRingSigs()\n"); if (!(ecGrp = EC_GROUP_new_by_curve_name(NID_secp256k1))) return errorN(1, "initialiseRingSigs(): EC_GROUP_new_by_curve_name failed."); if (!(bnCtx = BN_CTX_new())) return errorN(1, "initialiseRingSigs(): BN_CTX_new failed."); BN_CTX_start(bnCtx); //Create a new EC group for the keyImage with all of the characteristics of ecGrp. if(!(ecGrpKi = EC_GROUP_dup(ecGrp))){ return errorN(1, "initialiseRingSigs(): EC_GROUP_dup failed."); } // get order and cofactor bnOrder = BN_new(); if(!EC_GROUP_get_order(ecGrp, bnOrder, bnCtx)){ return errorN(1, "initialiseRingSigs(): EC_GROUP_get_order failed."); } BIGNUM *bnCofactor = BN_CTX_get(bnCtx); if(!EC_GROUP_get_cofactor(ecGrp, bnCofactor, bnCtx)){ return errorN(1, "initialiseRingSigs(): EC_GROUP_get_cofactor failed."); } // get the original generator EC_POINT *ptBase = const_cast<EC_POINT*>(EC_GROUP_get0_generator(ecGrp)); //PS: never clear this point // create key image basepoint variable EC_POINT *ptBaseKi = EC_POINT_new(ecGrpKi); BIGNUM *bnBaseKi = BN_CTX_get(bnCtx); // get original basepoint in BIG NUMS. EC_POINT_point2bn(ecGrp, ptBase, POINT_CONVERSION_COMPRESSED, bnBaseKi, bnCtx); //create "1" in BIG NUMS BIGNUM *bnBaseKiAdd = BN_CTX_get(bnCtx); std::string num_str = "1"; BN_dec2bn(&bnBaseKiAdd, num_str.c_str()); // add 1 to original base point and store in key image basepoint (BIG NUMS) BN_add(bnBaseKi, bnBaseKi, bnBaseKiAdd); // key image basepoint from bignum to point in ptBaseKi if(!EC_POINT_bn2point(ecGrp, bnBaseKi, ptBaseKi, bnCtx)) return errorN(1, "initialiseRingSigs(): EC_POINT_bn2point failed."); // set generator of ecGrpKi if(!EC_GROUP_set_generator(ecGrpKi, ptBaseKi, bnOrder, bnCofactor)){ return errorN(1, "initialiseRingSigs(): EC_GROUP_set_generator failed."); } if (fDebugRingSig) { // Debugging... const EC_POINT *generator = EC_GROUP_get0_generator(ecGrp); const EC_POINT *generatorKi = EC_GROUP_get0_generator(ecGrpKi); char *genPoint = EC_POINT_point2hex(ecGrp, generator, POINT_CONVERSION_UNCOMPRESSED, bnCtx); char *genPointKi = EC_POINT_point2hex(ecGrpKi, generatorKi, POINT_CONVERSION_UNCOMPRESSED, bnCtx); LogPrintf("generator ecGrp: %s\ngenerator ecGrpKi: %s\n", genPoint, genPointKi); } EC_POINT_free(ptBaseKi); BN_CTX_end(bnCtx); return 0; };
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; }
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 void eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data, const u8 *payload, size_t payload_len) { u8 *ptr; BIGNUM *x = NULL, *y = NULL, *cofactor = NULL; EC_POINT *K = NULL, *point = NULL; int res = 0; wpa_printf(MSG_DEBUG, "EAP-pwd: Received commit response"); if (((data->peer_scalar = BN_new()) == NULL) || ((data->k = BN_new()) == NULL) || ((cofactor = BN_new()) == NULL) || ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL) || ((point = EC_POINT_new(data->grp->group)) == NULL) || ((K = EC_POINT_new(data->grp->group)) == NULL) || ((data->peer_element = EC_POINT_new(data->grp->group)) == NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation " "fail"); goto fin; } if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (server): unable to get " "cofactor for curve"); goto fin; } /* element, x then y, followed by scalar */ ptr = (u8 *) payload; BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x); ptr += BN_num_bytes(data->grp->prime); BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y); ptr += BN_num_bytes(data->grp->prime); BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->peer_scalar); if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group, data->peer_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (server): setting peer element " "fail"); goto fin; } /* check to ensure peer's element is not in a small sub-group */ if (BN_cmp(cofactor, BN_value_one())) { if (!EC_POINT_mul(data->grp->group, point, NULL, data->peer_element, cofactor, NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (server): cannot " "multiply peer element by order"); goto fin; } if (EC_POINT_is_at_infinity(data->grp->group, point)) { wpa_printf(MSG_INFO, "EAP-PWD (server): peer element " "is at infinity!\n"); goto fin; } } /* compute the shared key, k */ if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe, data->peer_scalar, data->bnctx)) || (!EC_POINT_add(data->grp->group, K, K, data->peer_element, data->bnctx)) || (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value, data->bnctx))) { wpa_printf(MSG_INFO, "EAP-PWD (server): computing shared key " "fail"); goto fin; } /* ensure that the shared key isn't in a small sub-group */ if (BN_cmp(cofactor, BN_value_one())) { if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor, NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (server): cannot " "multiply shared key point by order!\n"); goto fin; } } /* * This check is strictly speaking just for the case above where * co-factor > 1 but it was suggested that even though this is probably * never going to happen it is a simple and safe check "just to be * sure" so let's be safe. */ if (EC_POINT_is_at_infinity(data->grp->group, K)) { wpa_printf(MSG_INFO, "EAP-PWD (server): shared key point is " "at infinity"); goto fin; } if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k, NULL, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (server): unable to extract " "shared secret from secret point"); goto fin; } res = 1; fin: EC_POINT_free(K); EC_POINT_free(point); BN_free(cofactor); BN_free(x); BN_free(y); if (res) eap_pwd_state(data, PWD_Confirm_Req); else eap_pwd_state(data, FAILURE); }
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 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); }
int SM2_do_decrypt(const EVP_MD *kdf_md, const EVP_MD *mac_md, const SM2_CIPHERTEXT_VALUE *cv, unsigned char *out, size_t *outlen, EC_KEY *ec_key) { int ret = 0; const EC_GROUP *ec_group = EC_KEY_get0_group(ec_key); const BIGNUM *pri_key = EC_KEY_get0_private_key(ec_key); KDF_FUNC kdf = KDF_get_x9_63(kdf_md); EC_POINT *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; int nbytes; size_t size; int i; OPENSSL_assert(kdf_md && mac_md && cv && ec_key); OPENSSL_assert(cv->ephem_point && cv->ciphertext); if (!ec_group || !pri_key) { goto end; } if (!kdf) { goto end; } if (!out) { *outlen = cv->ciphertext_size; return 1; } if (*outlen < cv->ciphertext_size) { goto end; } /* init vars */ point = EC_POINT_new(ec_group); n = BN_new(); h = BN_new(); bn_ctx = BN_CTX_new(); md_ctx = EVP_MD_CTX_create(); if (!point || !n || !h || !bn_ctx || !md_ctx) { goto end; } /* init ec domain parameters */ if (!EC_GROUP_get_order(ec_group, n, bn_ctx)) { goto end; } if (!EC_GROUP_get_cofactor(ec_group, h, bn_ctx)) { goto end; } nbytes = (EC_GROUP_get_degree(ec_group) + 7) / 8; OPENSSL_assert(nbytes == BN_num_bytes(n)); #if 0 /* check sm2 curve and md is 256 bits */ OPENSSL_assert(nbytes == 32); OPENSSL_assert(EVP_MD_size(kdf_md) == 32); OPENSSL_assert(EVP_MD_size(mac_md) == 32); #endif /* B2: check [h]C1 != O */ if (!EC_POINT_mul(ec_group, point, NULL, cv->ephem_point, h, bn_ctx)) { goto end; } if (EC_POINT_is_at_infinity(ec_group, point)) { goto end; } /* B3: compute ECDH [d]C1 = (x2, y2) */ if (!EC_POINT_mul(ec_group, point, NULL, cv->ephem_point, pri_key, bn_ctx)) { goto end; } if (!(size = EC_POINT_point2oct(ec_group, point, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) { goto end; } OPENSSL_assert(size == 1 + nbytes * 2); /* B4: compute t = KDF(x2 || y2, clen) */ *outlen = cv->ciphertext_size; //FIXME: duplicated code kdf(buf + 1, size - 1, out, outlen); /* B5: compute M = C2 xor t */ for (i = 0; i < cv->ciphertext_size; i++) { out[i] ^= cv->ciphertext[i]; } *outlen = cv->ciphertext_size; /* B6: check Hash(x2 || M || y2) == C3 */ if (!EVP_DigestInit_ex(md_ctx, mac_md, NULL)) { goto end; } if (!EVP_DigestUpdate(md_ctx, buf + 1, nbytes)) { goto end; } if (!EVP_DigestUpdate(md_ctx, out, *outlen)) { goto end; } if (!EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes)) { goto end; } if (!EVP_DigestFinal_ex(md_ctx, mac, &maclen)) { goto end; } if (cv->mactag_size != maclen || memcmp(cv->mactag, mac, maclen)) { goto end; } ret = 1; end: if (point) EC_POINT_free(point); if (n) BN_free(n); if (h) BN_free(h); if (bn_ctx) BN_CTX_free(bn_ctx); if (md_ctx) EVP_MD_CTX_destroy(md_ctx); 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; }
int process_peer_commit (pwd_session_t *sess, uint8_t *commit, BN_CTX *bnctx) { uint8_t *ptr; BIGNUM *x = NULL, *y = NULL, *cofactor = NULL; EC_POINT *K = NULL, *point = NULL; int res = 1; if (((sess->peer_scalar = BN_new()) == NULL) || ((sess->k = BN_new()) == NULL) || ((cofactor = BN_new()) == NULL) || ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL) || ((point = EC_POINT_new(sess->group)) == NULL) || ((K = EC_POINT_new(sess->group)) == NULL) || ((sess->peer_element = EC_POINT_new(sess->group)) == NULL)) { DEBUG2("pwd: failed to allocate room to process peer's commit"); goto fin; } if (!EC_GROUP_get_cofactor(sess->group, cofactor, NULL)) { DEBUG2("pwd: unable to get group co-factor"); goto fin; } /* element, x then y, followed by scalar */ ptr = (uint8_t *)commit; BN_bin2bn(ptr, BN_num_bytes(sess->prime), x); ptr += BN_num_bytes(sess->prime); BN_bin2bn(ptr, BN_num_bytes(sess->prime), y); ptr += BN_num_bytes(sess->prime); BN_bin2bn(ptr, BN_num_bytes(sess->order), sess->peer_scalar); if (!EC_POINT_set_affine_coordinates_GFp(sess->group, sess->peer_element, x, y, bnctx)) { DEBUG2("pwd: unable to get coordinates of peer's element"); goto fin; } /* check to ensure peer's element is not in a small sub-group */ if (BN_cmp(cofactor, BN_value_one())) { if (!EC_POINT_mul(sess->group, point, NULL, sess->peer_element, cofactor, NULL)) { DEBUG2("pwd: unable to multiply element by co-factor"); goto fin; } if (EC_POINT_is_at_infinity(sess->group, point)) { DEBUG2("pwd: peer's element is in small sub-group"); goto fin; } } /* compute the shared key, k */ if ((!EC_POINT_mul(sess->group, K, NULL, sess->pwe, sess->peer_scalar, bnctx)) || (!EC_POINT_add(sess->group, K, K, sess->peer_element, bnctx)) || (!EC_POINT_mul(sess->group, K, NULL, K, sess->private_value, bnctx))) { DEBUG2("pwd: unable to compute shared key, k"); goto fin; } /* ensure that the shared key isn't in a small sub-group */ if (BN_cmp(cofactor, BN_value_one())) { if (!EC_POINT_mul(sess->group, K, NULL, K, cofactor, NULL)) { DEBUG2("pwd: unable to multiply k by co-factor"); goto fin; } } /* * This check is strictly speaking just for the case above where * co-factor > 1 but it was suggested that even though this is probably * never going to happen it is a simple and safe check "just to be * sure" so let's be safe. */ if (EC_POINT_is_at_infinity(sess->group, K)) { DEBUG2("pwd: k is point-at-infinity!"); goto fin; } if (!EC_POINT_get_affine_coordinates_GFp(sess->group, K, sess->k, NULL, bnctx)) { DEBUG2("pwd: unable to get shared secret from K"); goto fin; } res = 0; fin: EC_POINT_free(K); EC_POINT_free(point); BN_free(cofactor); BN_free(x); BN_free(y); return res; }
// unsigned char *pC 输出,密文 // unsigned char *pPxKey, unsigned char *pPyKey 公钥 // unsigned char *pM 明文 // unsigned long MLen 明文长度 unsigned char eccEncrypt(unsigned char *pC, unsigned char *pPxKey, unsigned char *pPyKey, unsigned char *pM, unsigned long MLen) { // NID_sm2p256v1 EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1); //// 相当于 //EC_KEY *ret = EC_KEY_new(); EC_GROUP *ec_group = EC_GROUP_new_by_curve_name(NID_sm2p256v1); KDF_FUNC kdf = KDF_get_x9_63(EVP_sm3());; EC_POINT *point = NULL; //// 设置私钥 //BIGNUM *d = NULL; //BN_hex2bn(&d, pPDKey); //EC_KEY_set_private_key(ec_key, d); int ret = 1; BIGNUM *x = BN_new();; BIGNUM *y = BN_new();; if (!BN_bin2bn(pPxKey, 32, x)) { goto end; } if (!BN_bin2bn(pPyKey, 32, y)) { goto end; } if (!EC_KEY_set_public_key_affine_coordinates(ec_key, x, y)) { goto end; } const EC_POINT *pub_key = EC_KEY_get0_public_key(ec_key); /* init ec domain parameters */ BIGNUM *n = NULL; BIGNUM *h = NULL; BIGNUM *k = NULL; n = BN_new(); h = BN_new(); k = BN_new(); BN_CTX *bn_ctx = NULL; bn_ctx = BN_CTX_new(); if (!EC_GROUP_get_order(ec_group, n, bn_ctx)) { goto end; } if (!EC_GROUP_get_cofactor(ec_group, h, bn_ctx)) { goto end; } int nbytes = (EC_GROUP_get_degree(ec_group) + 7) / 8; EC_POINT *ec_point = EC_POINT_new(ec_group); point = EC_POINT_new(ec_group); unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1]; size_t len; char *ciphertext = (char *)OPENSSL_malloc(MLen); size_t ciphertext_size = MLen; do { /* A1: rand k in [1, n-1] */ do { BN_rand_range(k, n); } while (BN_is_zero(k)); /* A2: C1 = [k]G = (x1, y1) */ if (!EC_POINT_mul(ec_group, ec_point, k, NULL, NULL, bn_ctx)) { goto end; } #if 1 if (!(len = EC_POINT_point2oct(ec_group, ec_point, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) { goto end; } BN_bin2bn(buf, 65, n); printf(BN_bn2hex(n)); printf("\n"); printf(BN_bn2hex(k)); #endif /* A3: check [h]P_B != O */ if (!EC_POINT_mul(ec_group, point, NULL, pub_key, h, bn_ctx)) { goto end; } if (EC_POINT_is_at_infinity(ec_group, point)) { goto end; } /* A4: compute ECDH [k]P_B = (x2, y2) */ if (!EC_POINT_mul(ec_group, point, NULL, pub_key, k, bn_ctx)) { goto end; } if (!(len = EC_POINT_point2oct(ec_group, point, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) { goto end; } OPENSSL_assert(len == nbytes * 2 + 1); /* A5: t = KDF(x2 || y2, klen) */ kdf(buf + 1, len - 1, (unsigned char *)ciphertext, &ciphertext_size); // 防止全0 size_t i = 0; for (i = 0; i < ciphertext_size; i++) { if (ciphertext[i]) { break; } } if (i == ciphertext_size) { continue; } break; } while (1); /* A6: C2 = M xor t */ for (size_t i = 0; i < MLen; i++) { ciphertext[i] ^= pM[i]; } unsigned char dgst[EVP_MAX_MD_SIZE]; unsigned int dgstlen; EVP_MD_CTX *md_ctx = EVP_MD_CTX_create(); if (1) { /* A7: C3 = Hash(x2 || M || y2) */ if (!EVP_DigestInit_ex(md_ctx, EVP_sm3(), NULL)) { goto end; } if (!EVP_DigestUpdate(md_ctx, buf + 1, nbytes)) { goto end; } if (!EVP_DigestUpdate(md_ctx, pM, MLen)) { goto end; } if (!EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes)) { goto end; } if (!EVP_DigestFinal_ex(md_ctx, dgst, &dgstlen)) { goto end; } } EC_POINT_point2oct(ec_group, point, POINT_CONVERSION_UNCOMPRESSED, pC, 65, NULL); memcpy(&pC[65], ciphertext, MLen); memcpy(&pC[65 + MLen], dgst, dgstlen); ret = 0; end: if (point) EC_POINT_free(point); if (n) BN_free(n); if (h) BN_free(h); if (k) BN_free(k); if (bn_ctx) BN_CTX_free(bn_ctx); if (md_ctx) EVP_MD_CTX_destroy(md_ctx); return ret; }