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 finish; } if (!EC_GROUP_get_cofactor(sess->group, cofactor, NULL)) { DEBUG2("pwd: unable to get group co-factor"); goto finish; } /* 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 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(sess->group, point, NULL, sess->peer_element, cofactor, NULL)) { DEBUG2("pwd: unable to multiply element by co-factor"); goto finish; } if (EC_POINT_is_at_infinity(sess->group, point)) { DEBUG2("pwd: peer's element is in small sub-group"); goto finish; } } /* 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 finish; } /* 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 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(sess->group, K)) { DEBUG2("pwd: k is point-at-infinity!"); goto finish; } if (!EC_POINT_get_affine_coordinates_GFp(sess->group, K, sess->k, NULL, bnctx)) { DEBUG2("pwd: unable to get shared secret from K"); goto finish; } res = 0; finish: EC_POINT_free(K); EC_POINT_free(point); BN_free(cofactor); BN_free(x); BN_free(y); return res; }
// unsigned char *rgbHashData, 哈希数值 // unsigned char *rgbKeyPb, SM2公钥数据,Px Py 不含标志位 point_conversion_form_t // unsigned char *rs 待验证的签名数据 unsigned char eccVerifySignature(unsigned char *rgbHashData, unsigned char *rgbKeyPb, unsigned char *rs) { int ret = SM2_VERIFY_INNER_ERROR; EC_POINT *point = NULL; BN_CTX *ctx = NULL; BIGNUM *order = NULL; BIGNUM *e = NULL; BIGNUM *t = NULL; int i; EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1); BIGNUM *x = BN_new();; BIGNUM *y = BN_new();; if (!BN_bin2bn(rgbKeyPb, 32, x)) { goto err; } if (!BN_bin2bn(rgbKeyPb + 32, 32, y)) { goto err; } if (!EC_KEY_set_public_key_affine_coordinates(ec_key, x, y)) { goto err; } const EC_POINT *pub_key = EC_KEY_get0_public_key(ec_key); BIGNUM *r= BN_new(), *s = BN_new(); BN_bin2bn(rs, 32, r); BN_bin2bn(rs + 32, 32, s); //// 相当于 //EC_KEY *ret = EC_KEY_new(); EC_GROUP *ec_group = EC_GROUP_new_by_curve_name(NID_sm2p256v1); ctx = BN_CTX_new(); order = BN_new(); e = BN_new(); t = BN_new(); if (!ctx || !order || !e || !t) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_GROUP_get_order(ec_group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } /* check r, s in [1, n-1] and r + s != 0 (mod n) */ if (BN_is_zero(r) || BN_is_negative(r) || BN_ucmp(r, order) >= 0 || BN_is_zero(s) || BN_is_negative(s) || BN_ucmp(s, order) >= 0) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE); ret = 0; goto err; } /* check t = r + s != 0 */ if (!BN_mod_add(t, r, s, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if (BN_is_zero(t)) { ret = 0; goto err; } /* convert digest to e */ i = BN_num_bits(order); #if 0 if (8 * dgstlen > i) { dgstlen = (i + 7)/8; } #endif if (!BN_bin2bn(rgbHashData, 32, e)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } #if 0 if ((8 * dgstlen > i) && !BN_rshift(e, e, 8 - (i & 0x7))) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } #endif /* compute (x, y) = sG + tP, P is pub_key */ if (!(point = EC_POINT_new(ec_group))) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(ec_group, point, s, pub_key, t, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(ec_group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(ec_group, point, t, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(ec_group, point, t, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } if (!BN_nnmod(t, t, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* check (sG + tP).x + e == sig.r */ if (!BN_mod_add(t, t, e, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if (BN_ucmp(t, r) == 0) { ret = SM2_VERIFY_SUCCESS; } else { ret = SM2_VERIFY_FAILED; } err: if (point) EC_POINT_free(point); if (order) BN_free(order); if (e) BN_free(e); if (t) BN_free(t); if (ctx) BN_CTX_free(ctx); return 0; }
size_t ec_GFp_simple_point2oct(const EC_GROUP * group, const EC_POINT * point, point_conversion_form_t form, unsigned char *buf, size_t len, BN_CTX * ctx) { size_t ret; BN_CTX *new_ctx = NULL; int used_ctx = 0; BIGNUM *x, *y; size_t field_len, i, skip; if ((form != POINT_CONVERSION_COMPRESSED) && (form != POINT_CONVERSION_UNCOMPRESSED) && (form != POINT_CONVERSION_HYBRID)) { ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM); goto err; } if (EC_POINT_is_at_infinity(group, point)) { /* encodes to a single 0 octet */ if (buf != NULL) { if (len < 1) { ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); return 0; } buf[0] = 0; } return 1; } /* ret := required output buffer length */ field_len = BN_num_bytes(&group->field); ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; /* if 'buf' is NULL, just return required length */ if (buf != NULL) { if (len < ret) { ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); goto err; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } BN_CTX_start(ctx); used_ctx = 1; x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); if (y == NULL) goto err; if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err; if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y)) buf[0] = form + 1; else buf[0] = form; i = 1; skip = field_len - BN_num_bytes(x); if (skip > field_len) { ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); goto err; } while (skip > 0) { buf[i++] = 0; skip--; } skip = BN_bn2bin(x, buf + i); i += skip; if (i != 1 + field_len) { ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); goto err; } if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID) { skip = field_len - BN_num_bytes(y); if (skip > field_len) { ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); goto err; } while (skip > 0) { buf[i++] = 0; skip--; } skip = BN_bn2bin(y, buf + i); i += skip; } if (i != ret) { ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); goto err; } } if (used_ctx) BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; err: if (used_ctx) BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return 0; }
/* k in [1, n-1], (x, y) = kG */ static int sm2_sign_setup(EC_KEY *ec_key, BN_CTX *ctx_in, BIGNUM **kp, BIGNUM **xp) { int ret = 0; const EC_GROUP *ec_group; BN_CTX *ctx = NULL; BIGNUM *k = NULL; BIGNUM *x = NULL; BIGNUM *order = NULL; EC_POINT *point = NULL; if (ec_key == NULL || (ec_group = EC_KEY_get0_group(ec_key)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_MALLOC_FAILURE); return 0; } } else { ctx = ctx_in; } k = BN_new(); x = BN_new(); order = BN_new(); if (!k || !x || !order) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_GROUP_get_order(ec_group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if ((point = EC_POINT_new(ec_group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } do { /* get random k */ do { if (!BN_rand_range(k, order)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } while (BN_is_zero(k)); /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(ec_group, point, k, NULL, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(ec_group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(ec_group, point, x, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB); goto err; } } else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(ec_group, point, x, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB); goto err; } } //FIXME: do we need this? if (!BN_nnmod(x, x, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(x)); /* clear old values if necessary */ if (*kp != NULL) BN_clear_free(*kp); if (*xp != NULL) BN_clear_free(*xp); /* save the pre-computed values */ *kp = k; *xp = x; ret = 1; err: if (!ret) { if (k) BN_clear_free(k); if (x) BN_clear_free(x); } if (ctx_in == NULL) BN_CTX_free(ctx); if (order) BN_free(order); if (point) EC_POINT_free(point); return(ret); }