/* * Fill GOST 94 params, searching them in R3410_paramset array * by nid of paramset * */ int fill_GOST94_params (DSA * dsa, int nid) { R3410_params *params = R3410_paramset; while (params->nid != NID_undef && params->nid != nid) params++; if (params->nid == NID_undef) { GOSTerr (GOST_F_FILL_GOST94_PARAMS, GOST_R_UNSUPPORTED_PARAMETER_SET); return 0; } #define dump_signature(a,b,c) if (dsa->p) { BN_free (dsa->p); } dsa->p = NULL; BN_dec2bn (&(dsa->p), params->p); if (dsa->q) { BN_free (dsa->q); } dsa->q = NULL; BN_dec2bn (&(dsa->q), params->q); if (dsa->g) { BN_free (dsa->g); } dsa->g = NULL; BN_dec2bn (&(dsa->g), params->a); return 1; }
/* * EVP_PKEY_METHOD callback derive. Implements VKO R 34.10-2001 * algorithm */ int pkey_gost2001_derive (EVP_PKEY_CTX * ctx, unsigned char *key, size_t * keylen) { /* Public key of peer in the ctx field peerkey * Our private key in the ctx pkey * ukm is in the algorithm specific context data */ EVP_PKEY *my_key = EVP_PKEY_CTX_get0_pkey (ctx); EVP_PKEY *peer_key = EVP_PKEY_CTX_get0_peerkey (ctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data (ctx); if (!data->shared_ukm) { GOSTerr (GOST_F_PKEY_GOST2001_DERIVE, GOST_R_UKM_NOT_SET); return 0; } if (key == NULL) { *keylen = 32; return 32; } *keylen = VKO_compute_key (key, 32, EC_KEY_get0_public_key (EVP_PKEY_get0 (peer_key)), (EC_KEY *) EVP_PKEY_get0 (my_key), data->shared_ukm); return 1; }
/* ---------- Public key functions * --------------------------------------*/ static int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub) { X509_ALGOR *palg = NULL; const unsigned char *pubkey_buf = NULL; unsigned char *databuf; ASN1_OBJECT *palgobj = NULL; int pub_len, i, j; DSA *dsa; ASN1_OCTET_STRING *octet = NULL; if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub)) return 0; EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL); if (!decode_gost_algor_params(pk, palg)) return 0; octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len); if (!octet) { GOSTerr(GOST_F_PUB_DECODE_GOST94, ERR_R_MALLOC_FAILURE); return 0; } databuf = OPENSSL_malloc(octet->length); for (i = 0, j = octet->length - 1; i < octet->length; i++, j--) { databuf[j] = octet->data[i]; } dsa = EVP_PKEY_get0(pk); dsa->pub_key = BN_bin2bn(databuf, octet->length, NULL); ASN1_OCTET_STRING_free(octet); OPENSSL_free(databuf); return 1; }
int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md) { struct ossl_gost_imit_ctx *c = ctx->md_data; if (!c->key_set) { GOSTerr(GOST_F_GOST_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET); return 0; } if (c->count==0 && c->bytes_left) { unsigned char buffer[8]; memset(buffer, 0, 8); gost_imit_update(ctx, buffer, 8); } if (c->bytes_left) { int i; for (i=c->bytes_left;i<8;i++) { c->partial_block[i]=0; } mac_block_mesh(c,c->partial_block); } get_mac(c->buffer,32,md); return 1; }
static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) { int param_nid = 0; if (!strcmp(type, param_ctrl_string)) { if (!value) { return 0; } if (strlen(value) == 1) { switch (toupper((unsigned char)value[0])) { case 'A': param_nid = NID_id_GostR3410_2001_CryptoPro_A_ParamSet; break; case 'B': param_nid = NID_id_GostR3410_2001_CryptoPro_B_ParamSet; break; case 'C': param_nid = NID_id_GostR3410_2001_CryptoPro_C_ParamSet; break; case '0': param_nid = NID_id_GostR3410_2001_TestParamSet; break; default: return 0; break; } } else if ((strlen(value) == 2) && (toupper((unsigned char)value[0]) == 'X')) { switch (toupper((unsigned char)value[1])) { case 'A': param_nid = NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet; break; case 'B': param_nid = NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet; break; default: return 0; break; } } else { R3410_2001_params *p = R3410_2001_paramset; param_nid = OBJ_txt2nid(value); if (param_nid == NID_undef) { return 0; } for (; p->nid != NID_undef; p++) { if (p->nid == param_nid) break; } if (p->nid == NID_undef) { GOSTerr(GOST_F_PKEY_GOST_CTRL01_STR, GOST_R_INVALID_PARAMSET); return 0; } } return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET, param_nid, NULL); } return -2; }
int gost2001_keygen(GOST_KEY *ec) { BIGNUM *order = BN_new(), *d = BN_new(); const EC_GROUP *group = GOST_KEY_get0_group(ec); int rc = 0; if (order == NULL || d == NULL) goto err; if (EC_GROUP_get_order(group, order, NULL) == 0) goto err; do { if (BN_rand_range(d, order) == 0) { GOSTerr(GOST_F_GOST2001_KEYGEN, GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); goto err; } } while (BN_is_zero(d)); if (GOST_KEY_set_private_key(ec, d) == 0) goto err; rc = gost2001_compute_public(ec); err: BN_free(d); BN_free(order); return rc; }
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; }
static int print_gost_ec_pub(BIO *out, const EVP_PKEY *pkey, int indent) { BN_CTX *ctx; BIGNUM *X, *Y; const EC_POINT *pubkey; const EC_GROUP *group; EC_KEY *key = (EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey); int ok = 0; ctx = BN_CTX_new(); if (!ctx) { GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_MALLOC_FAILURE); return 0; } BN_CTX_start(ctx); X = BN_CTX_get(ctx); Y = BN_CTX_get(ctx); pubkey = (key) ? EC_KEY_get0_public_key(key) : NULL; group = (key) ? EC_KEY_get0_group(key) : NULL; if (!pubkey || !group) goto err; if (!EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y, ctx)) { GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_EC_LIB); goto err; } if (!BIO_indent(out, indent, 128)) goto err; BIO_printf(out, "Public key:\n"); if (!BIO_indent(out, indent + 3, 128)) goto err; BIO_printf(out, "X:"); BN_print(out, X); BIO_printf(out, "\n"); if (!BIO_indent(out, indent + 3, 128)) goto err; BIO_printf(out, "Y:"); BN_print(out, Y); BIO_printf(out, "\n"); ok = 1; err: BN_CTX_end(ctx); BN_CTX_free(ctx); return ok; }
static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key) { ASN1_STRING *params = ASN1_STRING_new(); GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new(); int pkey_param_nid = NID_undef; if (!params || !gkp) { GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE); ASN1_STRING_free(params); params = NULL; goto err; } switch (EVP_PKEY_base_id(key)) { case NID_id_GostR3410_2001: pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group (EVP_PKEY_get0((EVP_PKEY *)key))); break; case NID_id_GostR3410_94: pkey_param_nid = (int)gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key)); if (pkey_param_nid == NID_undef) { GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, GOST_R_INVALID_GOST94_PARMSET); ASN1_STRING_free(params); params = NULL; goto err; } break; } gkp->key_params = OBJ_nid2obj(pkey_param_nid); gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet); /* * gkp->cipher_params = OBJ_nid2obj(cipher_param_nid); */ params->length = i2d_GOST_KEY_PARAMS(gkp, ¶ms->data); if (params->length <= 0) { GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE); ASN1_STRING_free(params); params = NULL; goto err; } params->type = V_ASN1_SEQUENCE; err: GOST_KEY_PARAMS_free(gkp); return params; }
/* Set cipher parameters from ASN1 structure */ int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params) { int len=0; unsigned char *buf=NULL; unsigned char *p=NULL; struct ossl_gost_cipher_ctx *c = ctx->cipher_data; GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new(); ASN1_OCTET_STRING *os = NULL; if (!gcp) { GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); return 0; } if (!ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len)) { GOST_CIPHER_PARAMS_free(gcp); GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); return 0; } ASN1_OBJECT_free(gcp->enc_param_set); gcp->enc_param_set = OBJ_nid2obj(c->paramNID); len = i2d_GOST_CIPHER_PARAMS(gcp, NULL); p = buf = (unsigned char*)OPENSSL_malloc(len); if (!buf) { GOST_CIPHER_PARAMS_free(gcp); GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); return 0; } i2d_GOST_CIPHER_PARAMS(gcp, &p); GOST_CIPHER_PARAMS_free(gcp); os = ASN1_OCTET_STRING_new(); if(!os || !ASN1_OCTET_STRING_set(os, buf, len)) { OPENSSL_free(buf); GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); return 0; } OPENSSL_free(buf); ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os); return 1; }
/* ------------------ private key functions -----------------------------*/ static int priv_decode_gost(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf) { const unsigned char *pkey_buf = NULL, *p = NULL; int priv_len = 0; BIGNUM *pk_num = NULL; int ret = 0; X509_ALGOR *palg = NULL; ASN1_OBJECT *palg_obj = NULL; ASN1_INTEGER *priv_key = NULL; if (!PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf)) return 0; p = pkey_buf; if (!decode_gost_algor_params(pk, palg)) { return 0; } if (V_ASN1_OCTET_STRING == *p) { /* New format - Little endian octet string */ unsigned char rev_buf[32]; int i; ASN1_OCTET_STRING *s = d2i_ASN1_OCTET_STRING(NULL, &p, priv_len); if (!s || s->length != 32) { GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR); return 0; } for (i = 0; i < 32; i++) { rev_buf[31 - i] = s->data[i]; } ASN1_STRING_free(s); pk_num = getbnfrombuf(rev_buf, 32); } else { priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len); if (!priv_key) return 0; ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL); ASN1_INTEGER_free(priv_key); if (!ret) { GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR); return 0; } } ret = gost_set_priv_key(pk, pk_num); BN_free(pk_num); return ret; }
/* * * Generates GOST R 34.10-2001 * or GOST R 34.10-2012 keypair * */ int gost_ec_keygen(EC_KEY *ec) { BIGNUM *order = NULL, *d = NULL; const EC_GROUP *group = (ec) ? EC_KEY_get0_group(ec) : NULL; int ok = 0; if (!group) { GOSTerr(GOST_F_GOST_EC_KEYGEN, ERR_R_INTERNAL_ERROR); return 0; } order = BN_new(); d = BN_new(); if (!order || !d) { GOSTerr(GOST_F_GOST_EC_KEYGEN, ERR_R_MALLOC_FAILURE); goto end; } if (!EC_GROUP_get_order(group, order, NULL)) { GOSTerr(GOST_F_GOST_EC_KEYGEN, ERR_R_INTERNAL_ERROR); goto end; } do { if (!BN_rand_range(d, order)) { GOSTerr(GOST_F_GOST_EC_KEYGEN, GOST_R_RNG_ERROR); goto end; } } while (BN_is_zero(d)); if (!EC_KEY_set_private_key(ec, d)) { GOSTerr(GOST_F_GOST_EC_KEYGEN, ERR_R_INTERNAL_ERROR); goto end; } ok = 1; end: if (d) BN_free(d); if (order) BN_free(order); return (ok) ? gost_ec_compute_public(ec) : 0; }
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; }
static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk) { ASN1_OBJECT *algobj = NULL; ASN1_OCTET_STRING *octet = NULL; void *pval = NULL; unsigned char *buf=NULL,*databuf,*sptr; int i,j,data_len,ret=0; const EC_POINT *pub_key; BIGNUM *X,*Y,*order; const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk); int ptype = V_ASN1_UNDEF; algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk)); if (pk->save_parameters) { ASN1_STRING *params = encode_gost_algor_params(pk); pval = params; ptype = V_ASN1_SEQUENCE; } order = BN_new(); EC_GROUP_get_order(EC_KEY_get0_group(ec),order,NULL); pub_key=EC_KEY_get0_public_key(ec); if (!pub_key) { GOSTerr(GOST_F_PUB_ENCODE_GOST01, GOST_R_PUBLIC_KEY_UNDEFINED); return 0; } X=BN_new(); Y=BN_new(); EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec), pub_key,X,Y,NULL); data_len = 2*BN_num_bytes(order); BN_free(order); databuf = OPENSSL_malloc(data_len); memset(databuf,0,data_len); store_bignum(X,databuf+data_len/2,data_len/2); store_bignum(Y,databuf,data_len/2); BN_free(X); BN_free(Y); octet = ASN1_OCTET_STRING_new(); ASN1_STRING_set(octet,NULL,data_len); sptr=ASN1_STRING_data(octet); for (i=0,j=data_len-1;i<data_len;i++,j--) { sptr[i]=databuf[j]; } OPENSSL_free(databuf); 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); }
static int pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); uint8_t *keydata; if (!data->key_set) { GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN, GOST_R_MAC_KEY_NOT_SET); return 0; } keydata = malloc(32); if (keydata == NULL) { GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN, ERR_R_MALLOC_FAILURE); return 0; } memcpy(keydata, data->key, 32); EVP_PKEY_assign(pkey, NID_id_Gost28147_89_MAC, keydata); return 1; }
/* * Fills EC_KEY structure hidden in the app_data field of DSA structure * with parameter information, extracted from parameter array in * params.c file. * * Also fils DSA->q field with copy of EC_GROUP order field to make * DSA_size function work */ int fill_GOST2001_params(EC_KEY *eckey, int nid) { R3410_2001_params *params = R3410_2001_paramset; EC_GROUP *grp = NULL; BIGNUM *p = NULL, *q = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL; EC_POINT *P = NULL; BN_CTX *ctx = BN_CTX_new(); int ok = 0; BN_CTX_start(ctx); p = BN_CTX_get(ctx); a = BN_CTX_get(ctx); b = BN_CTX_get(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); q = BN_CTX_get(ctx); while (params->nid != NID_undef && params->nid != nid) params++; if (params->nid == NID_undef) { GOSTerr(GOST_F_FILL_GOST2001_PARAMS, GOST_R_UNSUPPORTED_PARAMETER_SET); goto err; } BN_hex2bn(&p, params->p); BN_hex2bn(&a, params->a); BN_hex2bn(&b, params->b); grp = EC_GROUP_new_curve_GFp(p, a, b, ctx); P = EC_POINT_new(grp); BN_hex2bn(&x, params->x); BN_hex2bn(&y, params->y); EC_POINT_set_affine_coordinates_GFp(grp, P, x, y, ctx); BN_hex2bn(&q, params->q); #ifdef DEBUG_KEYS fprintf(stderr, "Set params index %d oid %s\nq=", (params - R3410_2001_paramset), OBJ_nid2sn(params->nid)); BN_print_fp(stderr, q); fprintf(stderr, "\n"); #endif EC_GROUP_set_generator(grp, P, q, NULL); EC_GROUP_set_curve_name(grp, params->nid); EC_KEY_set_group(eckey, grp); ok = 1; err: EC_POINT_free(P); EC_GROUP_free(grp); BN_CTX_end(ctx); BN_CTX_free(ctx); return ok; }
static int pub_encode_gost94(X509_PUBKEY *pub, const EVP_PKEY *pk) { ASN1_OBJECT *algobj = NULL; ASN1_OCTET_STRING *octet = NULL; void *pval = NULL; unsigned char *buf = NULL, *databuf, *sptr; int i, j, data_len, ret = 0; int ptype = V_ASN1_UNDEF; DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk); algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk)); if (pk->save_parameters) { ASN1_STRING *params = encode_gost_algor_params(pk); pval = params; ptype = V_ASN1_SEQUENCE; } data_len = BN_num_bytes(dsa->pub_key); databuf = OPENSSL_malloc(data_len); if (databuf == NULL) { GOSTerr(GOST_F_PUB_ENCODE_GOST94, ERR_R_MALLOC_FAILURE); return 0; } BN_bn2bin(dsa->pub_key, databuf); octet = ASN1_OCTET_STRING_new(); if (octet == NULL) { GOSTerr(GOST_F_PUB_ENCODE_GOST94, ERR_R_MALLOC_FAILURE); OPENSSL_free(databuf); return 0; } ASN1_STRING_set(octet, NULL, data_len); sptr = ASN1_STRING_data(octet); for (i = 0, j = data_len - 1; i < data_len; i++, j--) { sptr[i] = databuf[j]; } OPENSSL_free(databuf); 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); }
/* * Computes signature and returns it as DSA_SIG structure */ DSA_SIG *gost_do_sign (const unsigned char *dgst, int dlen, DSA * dsa) { BIGNUM *k = NULL, *tmp = NULL, *tmp2 = NULL; DSA_SIG *newsig = DSA_SIG_new (); BIGNUM *md = hashsum2bn (dgst); /* check if H(M) mod q is zero */ BN_CTX *ctx = BN_CTX_new (); BN_CTX_start (ctx); if (!newsig) { GOSTerr (GOST_F_GOST_DO_SIGN, GOST_R_NO_MEMORY); goto err; } tmp = BN_CTX_get (ctx); k = BN_CTX_get (ctx); tmp2 = BN_CTX_get (ctx); BN_mod (tmp, md, dsa->q, ctx); if (BN_is_zero (tmp)) { BN_one (md); } do { do { /*Generate random number k less than q */ BN_rand_range (k, dsa->q); /* generate r = (a^x mod p) mod q */ BN_mod_exp (tmp, dsa->g, k, dsa->p, ctx); if (!(newsig->r)) newsig->r = BN_new (); BN_mod (newsig->r, tmp, dsa->q, ctx); } while (BN_is_zero (newsig->r)); /* generate s = (xr + k(Hm)) mod q */ BN_mod_mul (tmp, dsa->priv_key, newsig->r, dsa->q, ctx); BN_mod_mul (tmp2, k, md, dsa->q, ctx); if (!newsig->s) newsig->s = BN_new (); BN_mod_add (newsig->s, tmp, tmp2, dsa->q, ctx); } while (BN_is_zero (newsig->s)); err: BN_free (md); BN_CTX_end (ctx); BN_CTX_free (ctx); return newsig; }
/* * Computes GOST R 34.10-2001 public key * * */ int gost2001_compute_public(EC_KEY *ec) { const EC_GROUP *group = EC_KEY_get0_group(ec); EC_POINT *pub_key=NULL; const BIGNUM *priv_key=NULL; BN_CTX *ctx=NULL; int ok=0; if (!group) { GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,GOST_R_KEY_IS_NOT_INITIALIZED); return 0; } ctx=BN_CTX_new(); BN_CTX_start(ctx); if (!(priv_key=EC_KEY_get0_private_key(ec))) { GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,ERR_R_EC_LIB); goto err; } pub_key = EC_POINT_new(group); if (!EC_POINT_mul(group,pub_key,priv_key,NULL,NULL,ctx)) { GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,ERR_R_EC_LIB); goto err; } if (!EC_KEY_set_public_key(ec,pub_key)) { GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,ERR_R_EC_LIB); goto err; } ok = 256; err: BN_CTX_end(ctx); EC_POINT_free(pub_key); BN_CTX_free(ctx); return ok; }
static int pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); unsigned char *keydata; if (!data->key_set) { GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN, GOST_R_MAC_KEY_NOT_SET); return 0; } keydata = OPENSSL_malloc(32); memcpy(keydata, data->key, 32); EVP_PKEY_assign(pkey, NID_id_Gost28147_89_MAC, keydata); return 1; }
static int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from) { EC_KEY *eto = EVP_PKEY_get0(to); const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from); 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) { GOSTerr(GOST_F_PARAM_COPY_GOST01, GOST_R_KEY_PARAMETERS_MISSING); return 0; } if (!eto) { eto = EC_KEY_new(); EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto); } EC_KEY_set_group(eto, EC_KEY_get0_group(efrom)); if (EC_KEY_get0_private_key(eto)) { gost2001_compute_public(eto); } return 1; }
/* Unpack signature according to cryptopro rules */ DSA_SIG *unpack_cp_signature(const unsigned char *sig, size_t siglen) { DSA_SIG *s; s = DSA_SIG_new(); if (s == NULL) { GOSTerr(GOST_F_UNPACK_CP_SIGNATURE, ERR_R_MALLOC_FAILURE); return NULL; } s->s = BN_bin2bn(sig, siglen / 2, NULL); s->r = BN_bin2bn(sig + siglen / 2, siglen / 2, NULL); return s; }
GOST_KEY *GOST_KEY_new(void) { GOST_KEY *ret; ret = calloc(1, sizeof(GOST_KEY)); if (ret == NULL) { GOSTerr(GOST_F_GOST_KEY_NEW, ERR_R_MALLOC_FAILURE); return (NULL); } ret->references = 1; ret->digest_nid = NID_undef; return (ret); }
/* --------------------- control functions ------------------------------*/ static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { struct gost_pmeth_data *pctx = (struct gost_pmeth_data*)EVP_PKEY_CTX_get_data(ctx); switch (type) { case EVP_PKEY_CTRL_MD: { if (EVP_MD_type((const EVP_MD *)p2) != NID_id_GostR3411_94) { GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_INVALID_DIGEST_TYPE); return 0; } pctx->md = (EVP_MD *)p2; return 1; } break; case EVP_PKEY_CTRL_GET_MD: *(const EVP_MD **)p2 = pctx->md; return 1; case EVP_PKEY_CTRL_PKCS7_ENCRYPT: case EVP_PKEY_CTRL_PKCS7_DECRYPT: case EVP_PKEY_CTRL_PKCS7_SIGN: case EVP_PKEY_CTRL_DIGESTINIT: #ifndef OPENSSL_NO_CMS case EVP_PKEY_CTRL_CMS_ENCRYPT: case EVP_PKEY_CTRL_CMS_DECRYPT: case EVP_PKEY_CTRL_CMS_SIGN: #endif return 1; case EVP_PKEY_CTRL_GOST_PARAMSET: pctx->sign_param_nid = (int)p1; return 1; case EVP_PKEY_CTRL_SET_IV: pctx->shared_ukm=OPENSSL_malloc((int)p1); memcpy(pctx->shared_ukm,p2,(int) p1); return 1; case EVP_PKEY_CTRL_PEER_KEY: if (p1 == 0 || p1 == 1) /* call from EVP_PKEY_derive_set_peer */ return 1; if (p1 == 2) /* TLS: peer key used? */ return pctx->peer_key_used; if (p1 == 3) /* TLS: peer key used! */ return (pctx->peer_key_used = 1); return -2; } return -2; }
/* Unpack signature according to cryptopro rules */ DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen) { DSA_SIG *s; s = DSA_SIG_new(); if (s == NULL) { GOSTerr(GOST_F_UNPACK_CP_SIGNATURE,GOST_R_NO_MEMORY); return NULL; } s->s = getbnfrombuf(sig , siglen/2); s->r = getbnfrombuf(sig + siglen/2, siglen/2); return s; }
/* * Computes public keys for GOST R 34.10-94 algorithm * */ int gost94_compute_public(DSA *dsa) { /* Now fill algorithm parameters with correct values */ BN_CTX *ctx = BN_CTX_new(); if (!dsa->g) { GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC,GOST_R_KEY_IS_NOT_INITALIZED); return 0; } /* Compute public key y = a^x mod p */ dsa->pub_key=BN_new(); BN_mod_exp(dsa->pub_key, dsa->g,dsa->priv_key,dsa->p,ctx); BN_CTX_free(ctx); return 1; }
/* Unpack signature according to cryptopro rules */ DSA_SIG *unpack_cp_signature(const unsigned char *sigbuf, size_t siglen) { DSA_SIG *sig; BIGNUM *r = NULL, *s = NULL; sig = DSA_SIG_new(); if (sig == NULL) { GOSTerr(GOST_F_UNPACK_CP_SIGNATURE, ERR_R_MALLOC_FAILURE); return NULL; } s = BN_bin2bn(sigbuf, siglen / 2, NULL); r = BN_bin2bn(sigbuf + siglen / 2, siglen / 2, NULL); DSA_SIG_set0(sig, r, s); return sig; }
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 pkey_gost94_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); DSA *dsa = NULL; if (data->sign_param_nid == NID_undef) { GOSTerr(GOST_F_PKEY_GOST94_PARAMGEN, GOST_R_NO_PARAMETERS_SET); return 0; } dsa = DSA_new(); if (!fill_GOST94_params(dsa, data->sign_param_nid)) { DSA_free(dsa); return 0; } EVP_PKEY_assign(pkey, NID_id_GostR3410_94, dsa); return 1; }
static int pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) { struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); if (data == NULL) { pkey_gost_mac_init(ctx); } data = EVP_PKEY_CTX_get_data(ctx); if (!data) { GOSTerr(GOST_F_PKEY_GOST_MAC_SIGNCTX_INIT, GOST_R_MAC_KEY_NOT_SET); return 0; } return 1; }