static int priv_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) { const BIGNUM *key; if (BIO_indent(out, indent, 128) == 0) return 0; BIO_printf(out, "Private key: "); key = GOST_KEY_get0_private_key(pkey->pkey.gost); if (key == NULL) BIO_printf(out, "<undefined)"); else BN_print(out, key); BIO_printf(out, "\n"); return pub_print_gost01(out, pkey, indent, pctx); }
int gost2001_compute_public(GOST_KEY *ec) { const EC_GROUP *group = GOST_KEY_get0_group(ec); EC_POINT *pub_key = NULL; const BIGNUM *priv_key = NULL; BN_CTX *ctx = NULL; int ok = 0; if (group == NULL) { GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, GOST_R_KEY_IS_NOT_INITIALIZED); return 0; } ctx = BN_CTX_new(); if (ctx == NULL) { GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); return 0; } BN_CTX_start(ctx); if ((priv_key = GOST_KEY_get0_private_key(ec)) == NULL) goto err; pub_key = EC_POINT_new(group); if (pub_key == NULL) goto err; if (EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx) == 0) goto err; if (GOST_KEY_set_public_key(ec, pub_key) == 0) goto err; ok = 1; if (ok == 0) { err: GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); } EC_POINT_free(pub_key); if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } return ok; }
/* 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 param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from) { GOST_KEY *eto = to->pkey.gost; const GOST_KEY *efrom = from->pkey.gost; int ret = 1; if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) { GOSTerr(GOST_F_PARAM_COPY_GOST01, GOST_R_INCOMPATIBLE_ALGORITHMS); return 0; } if (efrom == NULL) { GOSTerr(GOST_F_PARAM_COPY_GOST01, GOST_R_KEY_PARAMETERS_MISSING); return 0; } if (eto == NULL) { eto = GOST_KEY_new(); if (eto == NULL) { GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_MALLOC_FAILURE); return 0; } if (EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto) == 0) { GOST_KEY_free(eto); return 0; } } GOST_KEY_set_group(eto, GOST_KEY_get0_group(efrom)); GOST_KEY_set_digest(eto, GOST_KEY_get_digest(efrom)); if (GOST_KEY_get0_private_key(eto) != NULL) ret = gost2001_compute_public(eto); return ret; }
static int priv_encode_gost01(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk) { ASN1_OBJECT *algobj = OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(pk->pkey.gost))); ASN1_STRING *params = encode_gost01_algor_params(pk); unsigned char *priv_buf = NULL; int priv_len; ASN1_INTEGER *asn1key = NULL; if (params == NULL) return 0; asn1key = BN_to_ASN1_INTEGER(GOST_KEY_get0_private_key(pk->pkey.gost), NULL); if (asn1key == NULL) { ASN1_STRING_free(params); return 0; } priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf); ASN1_INTEGER_free(asn1key); return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params, priv_buf, priv_len); }
ECDSA_SIG * gost2001_do_sign(BIGNUM *md, GOST_KEY *eckey) { ECDSA_SIG *newsig = NULL; BIGNUM *order = NULL; const EC_GROUP *group; const BIGNUM *priv_key; BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL, *k = NULL, *e = NULL; EC_POINT *C = NULL; BN_CTX *ctx = BN_CTX_new(); int ok = 0; if (ctx == NULL) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); return NULL; } BN_CTX_start(ctx); newsig = ECDSA_SIG_new(); if (newsig == NULL) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } s = newsig->s; r = newsig->r; group = GOST_KEY_get0_group(eckey); if ((order = BN_CTX_get(ctx)) == NULL) goto err; if (EC_GROUP_get_order(group, order, ctx) == 0) goto err; priv_key = GOST_KEY_get0_private_key(eckey); if ((e = BN_CTX_get(ctx)) == NULL) goto err; if (BN_mod(e, md, order, ctx) == 0) goto err; if (BN_is_zero(e)) BN_one(e); if ((k = BN_CTX_get(ctx)) == NULL) goto err; if ((X = BN_CTX_get(ctx)) == NULL) goto err; if ((C = EC_POINT_new(group)) == NULL) goto err; do { do { if (!BN_rand_range(k, order)) { GOSTerr(GOST_F_GOST2001_DO_SIGN, GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); goto err; } /* * We do not want timing information to leak the length * of k, so we compute G*k using an equivalent scalar * of fixed bit-length. */ if (BN_add(k, k, order) == 0) goto err; if (BN_num_bits(k) <= BN_num_bits(order)) if (BN_add(k, k, order) == 0) goto err; if (EC_POINT_mul(group, C, k, NULL, NULL, ctx) == 0) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); goto err; } if (EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx) == 0) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); goto err; } if (BN_nnmod(r, X, order, ctx) == 0) goto err; } while (BN_is_zero(r)); /* s = (r*priv_key+k*e) mod order */ if (tmp == NULL) { if ((tmp = BN_CTX_get(ctx)) == NULL) goto err; } if (BN_mod_mul(tmp, priv_key, r, order, ctx) == 0) goto err; if (tmp2 == NULL) { if ((tmp2 = BN_CTX_get(ctx)) == NULL) goto err; } if (BN_mod_mul(tmp2, k, e, order, ctx) == 0) goto err; if (BN_mod_add(s, tmp, tmp2, order, ctx) == 0) goto err; } while (BN_is_zero(s)); ok = 1; err: EC_POINT_free(C); if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (ok == 0) { ECDSA_SIG_free(newsig); newsig = NULL; } return newsig; }