static int pub_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b) { const GOST_KEY *ea = a->pkey.gost; const GOST_KEY *eb = b->pkey.gost; const EC_POINT *ka, *kb; int ret = 0; if (ea == NULL || eb == NULL) return 0; ka = GOST_KEY_get0_public_key(ea); kb = GOST_KEY_get0_public_key(eb); if (ka == NULL || kb == NULL) return 0; ret = (0 == EC_POINT_cmp(GOST_KEY_get0_group(ea), ka, kb, NULL)); return ret; }
static int pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) { BN_CTX *ctx = BN_CTX_new(); BIGNUM *X, *Y; const EC_POINT *pubkey; const EC_GROUP *group; if (ctx == NULL) { GOSTerr(GOST_F_PUB_PRINT_GOST01, ERR_R_MALLOC_FAILURE); return 0; } BN_CTX_start(ctx); if ((X = BN_CTX_get(ctx)) == NULL) goto err; if ((Y = BN_CTX_get(ctx)) == NULL) goto err; pubkey = GOST_KEY_get0_public_key(pkey->pkey.gost); group = GOST_KEY_get0_group(pkey->pkey.gost); if (EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y, ctx) == 0) { GOSTerr(GOST_F_PUB_PRINT_GOST01, ERR_R_EC_LIB); goto err; } if (BIO_indent(out, indent, 128) == 0) goto err; BIO_printf(out, "Public key:\n"); if (BIO_indent(out, indent + 3, 128) == 0) goto err; BIO_printf(out, "X:"); BN_print(out, X); BIO_printf(out, "\n"); BIO_indent(out, indent + 3, 128); BIO_printf(out, "Y:"); BN_print(out, Y); BIO_printf(out, "\n"); BN_CTX_end(ctx); BN_CTX_free(ctx); return param_print_gost01(out, pkey, indent, pctx); err: BN_CTX_end(ctx); BN_CTX_free(ctx); return 0; }
/* Implementation of CryptoPro VKO 34.10-2001 algorithm */ int VKO_compute_key(BIGNUM *X, BIGNUM *Y, const GOST_KEY *pkey, GOST_KEY *priv_key, const BIGNUM *ukm) { BIGNUM *p = NULL, *order = NULL; const BIGNUM *key = GOST_KEY_get0_private_key(priv_key); const EC_GROUP *group = GOST_KEY_get0_group(priv_key); const EC_POINT *pub_key = GOST_KEY_get0_public_key(pkey); EC_POINT *pnt; BN_CTX *ctx = NULL; int ok = 0; pnt = EC_POINT_new(group); if (pnt == NULL) goto err; ctx = BN_CTX_new(); if (ctx == NULL) goto err; BN_CTX_start(ctx); if ((p = BN_CTX_get(ctx)) == NULL) goto err; if ((order = BN_CTX_get(ctx)) == NULL) goto err; if (EC_GROUP_get_order(group, order, ctx) == 0) goto err; if (BN_mod_mul(p, key, ukm, order, ctx) == 0) goto err; if (EC_POINT_mul(group, pnt, NULL, pub_key, p, ctx) == 0) goto err; if (EC_POINT_get_affine_coordinates_GFp(group, pnt, X, Y, ctx) == 0) goto err; ok = 1; err: if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } EC_POINT_free(pnt); return ok; }
static int pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk) { ASN1_OBJECT *algobj = NULL; ASN1_OCTET_STRING *octet = NULL; ASN1_STRING *params = NULL; void *pval = NULL; unsigned char *buf = NULL, *sptr; int key_size, ret = 0; const EC_POINT *pub_key; BIGNUM *X = NULL, *Y = NULL; const GOST_KEY *ec = pk->pkey.gost; int ptype = V_ASN1_UNDEF; algobj = OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(ec))); if (pk->save_parameters) { params = encode_gost01_algor_params(pk); if (params == NULL) return 0; pval = params; ptype = V_ASN1_SEQUENCE; } key_size = GOST_KEY_get_size(ec); pub_key = GOST_KEY_get0_public_key(ec); if (pub_key == NULL) { GOSTerr(GOST_F_PUB_ENCODE_GOST01, GOST_R_PUBLIC_KEY_UNDEFINED); goto err; } octet = ASN1_OCTET_STRING_new(); if (octet == NULL) { GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE); goto err; } ret = ASN1_STRING_set(octet, NULL, 2 * key_size); if (ret == 0) { GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_INTERNAL_ERROR); goto err; } sptr = ASN1_STRING_data(octet); X = BN_new(); Y = BN_new(); if (X == NULL || Y == NULL) { GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE); goto err; } if (EC_POINT_get_affine_coordinates_GFp(GOST_KEY_get0_group(ec), pub_key, X, Y, NULL) == 0) { GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_EC_LIB); goto err; } GOST_bn2le(X, sptr, key_size); GOST_bn2le(Y, sptr + key_size, key_size); BN_free(Y); BN_free(X); ret = i2d_ASN1_OCTET_STRING(octet, &buf); ASN1_BIT_STRING_free(octet); if (ret < 0) return 0; return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret); err: BN_free(Y); BN_free(X); ASN1_BIT_STRING_free(octet); ASN1_STRING_free(params); return 0; }
int gost2001_do_verify(BIGNUM *md, ECDSA_SIG *sig, GOST_KEY *ec) { BN_CTX *ctx = BN_CTX_new(); const EC_GROUP *group = GOST_KEY_get0_group(ec); BIGNUM *order; BIGNUM *e = NULL, *R = NULL, *v = NULL, *z1 = NULL, *z2 = NULL; BIGNUM *X = NULL, *tmp = NULL; EC_POINT *C = NULL; const EC_POINT *pub_key = NULL; int ok = 0; if (ctx == NULL) goto err; BN_CTX_start(ctx); if ((order = BN_CTX_get(ctx)) == NULL) goto err; if ((e = BN_CTX_get(ctx)) == NULL) goto err; if ((z1 = BN_CTX_get(ctx)) == NULL) goto err; if ((z2 = BN_CTX_get(ctx)) == NULL) goto err; if ((tmp = BN_CTX_get(ctx)) == NULL) goto err; if ((X = BN_CTX_get(ctx)) == NULL) goto err; if ((R = BN_CTX_get(ctx)) == NULL) goto err; if ((v = BN_CTX_get(ctx)) == NULL) goto err; if (EC_GROUP_get_order(group, order, ctx) == 0) goto err; pub_key = GOST_KEY_get0_public_key(ec); if (BN_is_zero(sig->s) || BN_is_zero(sig->r) || BN_cmp(sig->s, order) >= 1 || BN_cmp(sig->r, order) >= 1) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); goto err; } if (BN_mod(e, md, order, ctx) == 0) goto err; if (BN_is_zero(e)) BN_one(e); if ((v = BN_mod_inverse(v, e, order, ctx)) == NULL) goto err; if (BN_mod_mul(z1, sig->s, v, order, ctx) == 0) goto err; if (BN_sub(tmp, order, sig->r) == 0) goto err; if (BN_mod_mul(z2, tmp, v, order, ctx) == 0) goto err; if ((C = EC_POINT_new(group)) == NULL) goto err; if (EC_POINT_mul(group, C, z1, pub_key, z2, ctx) == 0) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx) == 0) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (BN_mod(R, X, order, ctx) == 0) goto err; if (BN_cmp(R, sig->r) != 0) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); } else { ok = 1; } err: EC_POINT_free(C); if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } return ok; }