// Setters for the GOST private key components void OSSLGOSTPrivateKey::setD(const ByteString& d) { GOSTPrivateKey::setD(d); EC_KEY* ec = (EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey); if (ec == NULL) { ByteString der = dummyKey; const unsigned char *p = &der[0]; if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p, (long) der.size()) == NULL) { ERROR_MSG("d2i_PrivateKey failed"); return; } ec = (EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey); } const BIGNUM* priv = OSSL::byteString2bn(d); if (EC_KEY_set_private_key(ec, priv) <= 0) { ERROR_MSG("EC_KEY_set_private_key failed"); return; } #ifdef notyet if (gost2001_compute_public(ec) <= 0) ERROR_MSG("gost2001_compute_public failed"); #endif }
/* * EVP_PKEY_METHOD callback derive. * Implements VKO R 34.10-2001/2012 algorithms */ int pkey_gost_ec_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); int dgst_nid = NID_undef; if (!data || !data->shared_ukm) { GOSTerr(GOST_F_PKEY_GOST_EC_DERIVE, GOST_R_UKM_NOT_SET); return 0; } if (key == NULL) { *keylen = 32; return 32; } EVP_PKEY_get_default_digest_nid(my_key, &dgst_nid); *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, dgst_nid); return (*keylen) ? 1 : 0; }
/* * 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; }
// Argh! This is one more of these OpenSSL-style schizophrenic APIs, where // depending on whether a parameter is NULL or not, different values are // expected... static int bcrypt_derive(EVP_PKEY_CTX *ctx, unsigned char *outKey, size_t *outKeyLen) { *outKeyLen = X25519_KEYLEN; // First usage: a query for how many bytes the caller needs to allocate. if (outKey == NULL) return 1; // Second usage: writing into outkey the derived secret. // Note: this does NOT give you the actual bytes for the SECRET_HANDLE. (See // http://stackoverflow.com/questions/87694/im-using-wincrypt-for-diffie-hellman-can-i-export-the-shared-secret-in-plain // for something vaguely related). BCryptExportKey works for a KEY_HANDLE, not // a SECRET_HANDLE... and the type is defined as void* in the public Windows // 10 headers. bcrypt_x25519_key *pkey = EVP_PKEY_get0(EVP_PKEY_CTX_get0_pkey(ctx)); bcrypt_x25519_key *peerkey = EVP_PKEY_get0(EVP_PKEY_CTX_get0_peerkey(ctx)); BCRYPT_SECRET_HANDLE hSecret = NULL; if (!NT_SUCCESS(BCryptSecretAgreement(pkey->pair, peerkey->pair, &hSecret, 0))) { fprintf(stderr, "Cannot compute agreement\n"); return 0; } // Writing out a dummy value in the meanwhile... memset(outKey, 0, X25519_KEYLEN); return 1; }
static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv) { switch (EVP_PKEY_base_id(pkey)) { case NID_id_GostR3410_94: { DSA *dsa = EVP_PKEY_get0(pkey); if (!dsa) { dsa = DSA_new(); EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),dsa); } dsa->priv_key = BN_dup(priv); if (!EVP_PKEY_missing_parameters(pkey)) gost94_compute_public(dsa); break; } case NID_id_GostR3410_2001: { EC_KEY *ec = EVP_PKEY_get0(pkey); if (!ec) { ec = EC_KEY_new(); EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),ec); } if (!EC_KEY_set_private_key(ec,priv)) return 0; if (!EVP_PKEY_missing_parameters(pkey)) gost2001_compute_public(ec); break; } } return 1; }
/* Allocates new gost_pmeth_data structure and assigns it as data */ static int pkey_gost_init(EVP_PKEY_CTX *ctx) { struct gost_pmeth_data *data; EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); data = OPENSSL_malloc(sizeof(struct gost_pmeth_data)); if (!data) return 0; memset(data, 0, sizeof(struct gost_pmeth_data)); if (pkey && EVP_PKEY_get0(pkey)) { switch (EVP_PKEY_base_id(pkey)) { case NID_id_GostR3410_94: data->sign_param_nid = gost94_nid_by_params(EVP_PKEY_get0(pkey)); break; case NID_id_GostR3410_2001: data->sign_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group (EVP_PKEY_get0((EVP_PKEY *)pkey))); break; default: return 0; } } EVP_PKEY_CTX_set_data(ctx, data); return 1; }
/* --------- printing keys --------------------------------*/ static int print_gost_94(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx, int type) { int param_nid = NID_undef; if (type == 2) { BIGNUM *key; if (!BIO_indent(out,indent,128)) return 0; BIO_printf(out,"Private key: "); key = gost_get0_priv_key(pkey); if (!key) BIO_printf(out,"<undefined>"); else BN_print(out,key); BIO_printf(out,"\n"); } if (type >= 1) { BIGNUM *pubkey; pubkey = ((DSA *)EVP_PKEY_get0((EVP_PKEY *)pkey))->pub_key; BIO_indent(out,indent,128); BIO_printf(out,"Public key: "); BN_print(out,pubkey); BIO_printf(out,"\n"); } param_nid = gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey)); BIO_indent(out,indent,128); BIO_printf(out, "Parameter set: %s\n",OBJ_nid2ln(param_nid)); 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; }
static int param_copy_gost_ec(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_GOST_EC, GOST_R_INCOMPATIBLE_ALGORITHMS); return 0; } if (!efrom) { GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_KEY_PARAMETERS_MISSING); return 0; } if (!eto) { eto = EC_KEY_new(); if (!eto) { GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_MALLOC_FAILURE); return 0; } if (!EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto)) { GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR); EC_KEY_free(eto); return 0; } } if (!EC_KEY_set_group(eto, EC_KEY_get0_group(efrom))) { GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR); return 0; } if (EC_KEY_get0_private_key(eto)) { return gost_ec_compute_public(eto); } return 1; }
/* * Parses GOST algorithm parameters from X509_ALGOR and modifies pkey setting * NID and parameters */ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg) { ASN1_OBJECT *palg_obj = NULL; int ptype = V_ASN1_UNDEF; int pkey_nid = NID_undef, param_nid = NID_undef; void *_pval; ASN1_STRING *pval = NULL; const unsigned char *p; GOST_KEY_PARAMS *gkp = NULL; X509_ALGOR_get0(&palg_obj, &ptype, &_pval, palg); pval = _pval; if (ptype != V_ASN1_SEQUENCE) { GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, GOST_R_BAD_KEY_PARAMETERS_FORMAT); return 0; } p = pval->data; pkey_nid = OBJ_obj2nid(palg_obj); gkp = d2i_GOST_KEY_PARAMS(NULL, &p, pval->length); if (!gkp) { GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, GOST_R_BAD_PKEY_PARAMETERS_FORMAT); return 0; } param_nid = OBJ_obj2nid(gkp->key_params); GOST_KEY_PARAMS_free(gkp); if(!EVP_PKEY_set_type(pkey, pkey_nid)) { GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, ERR_R_INTERNAL_ERROR); return 0; } switch (pkey_nid) { case NID_id_GostR3410_94: { DSA *dsa = EVP_PKEY_get0(pkey); if (!dsa) { dsa = DSA_new(); if (!EVP_PKEY_assign(pkey, pkey_nid, dsa)) return 0; } if (!fill_GOST94_params(dsa, param_nid)) return 0; break; } case NID_id_GostR3410_2001: { EC_KEY *ec = EVP_PKEY_get0(pkey); if (!ec) { ec = EC_KEY_new(); if (!EVP_PKEY_assign(pkey, pkey_nid, ec)) return 0; } if (!fill_GOST2001_params(ec, param_nid)) return 0; } } return 1; }
BIGNUM* gost_get0_priv_key(const EVP_PKEY *pkey) { switch (EVP_PKEY_base_id(pkey)) { case NID_id_GostR3410_94: { DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey); if (!dsa) { return NULL; } if (!dsa->priv_key) return NULL; return dsa->priv_key; break; } case NID_id_GostR3410_2001: { EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey); const BIGNUM* priv; if (!ec) { return NULL; } if (!(priv=EC_KEY_get0_private_key(ec))) return NULL; return (BIGNUM *)priv; break; } } return NULL; }
static int param_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b) { const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a); const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b); if (!BN_cmp(da->q,db->q)) return 1; return 0; }
// Setters for the GOST private key components void OSSLGOSTPrivateKey::setD(const ByteString& inD) { GOSTPrivateKey::setD(inD); EC_KEY* inEC = (EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey); if (inEC == NULL) { const unsigned char* p = dummyKey; if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p, (long) sizeof(dummyKey)) == NULL) { ERROR_MSG("d2i_PrivateKey failed"); return; } inEC = (EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey); } const BIGNUM* priv = OSSL::byteString2bn(inD); if (EC_KEY_set_private_key(inEC, priv) <= 0) { ERROR_MSG("EC_KEY_set_private_key failed"); return; } BN_clear_free((BIGNUM*)priv); #ifdef notyet if (gost2001_compute_public(inEC) <= 0) ERROR_MSG("gost2001_compute_public failed"); #endif }
/* Allocates new gost_pmeth_data structure and assigns it as data */ static int pkey_gost_init(EVP_PKEY_CTX *ctx) { struct gost_pmeth_data *data; EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); data = OPENSSL_malloc(sizeof(*data)); if (!data) return 0; memset(data, 0, sizeof(*data)); if (pkey && EVP_PKEY_get0(pkey)) { switch (EVP_PKEY_base_id(pkey)) { case NID_id_GostR3410_2001: case NID_id_GostR3410_2012_256: case NID_id_GostR3410_2012_512: { const EC_GROUP *group = EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey)); if (group != NULL) { data->sign_param_nid = EC_GROUP_get_curve_name(group); break; } /* else */ } default: OPENSSL_free(data); return 0; } } EVP_PKEY_CTX_set_data(ctx, data); return 1; }
static int param_copy_gost94(EVP_PKEY *to, const EVP_PKEY *from) { const DSA *dfrom = EVP_PKEY_get0((EVP_PKEY *)from); DSA *dto = EVP_PKEY_get0(to); if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) { GOSTerr(GOST_F_PARAM_COPY_GOST94, GOST_R_INCOMPATIBLE_ALGORITHMS); return 0; } if (!dfrom) { GOSTerr(GOST_F_PARAM_COPY_GOST94, GOST_R_KEY_PARAMETERS_MISSING); return 0; } if (!dto) { dto = DSA_new(); EVP_PKEY_assign(to,EVP_PKEY_base_id(from),dto); } #define COPYBIGNUM(a,b,x) if (a->x) BN_free(a->x); a->x=BN_dup(b->x); COPYBIGNUM(dto,dfrom,p) COPYBIGNUM(dto,dfrom,q) COPYBIGNUM(dto,dfrom,g) if (dto->priv_key) gost94_compute_public(dto); return 1; }
static int print_gost_01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx, int type) { int param_nid = NID_undef; if (type == 2) { BIGNUM *key; if (!BIO_indent(out,indent,128)) return 0; BIO_printf(out,"Private key: "); key = gost_get0_priv_key(pkey); if (!key) BIO_printf(out,"<undefined)"); else BN_print(out,key); BIO_printf(out,"\n"); } if (type >= 1) { BN_CTX *ctx = BN_CTX_new(); BIGNUM *X,*Y; const EC_POINT *pubkey; const EC_GROUP *group; if (!ctx) { GOSTerr(GOST_F_PRINT_GOST_01,ERR_R_MALLOC_FAILURE); return 0; } BN_CTX_start(ctx); X = BN_CTX_get(ctx); Y = BN_CTX_get(ctx); pubkey = EC_KEY_get0_public_key((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey)); group = EC_KEY_get0_group((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey)); if (!EC_POINT_get_affine_coordinates_GFp(group,pubkey,X,Y,ctx)) { GOSTerr(GOST_F_PRINT_GOST_01,ERR_R_EC_LIB); BN_CTX_free(ctx); return 0; } if (!BIO_indent(out,indent,128)) return 0; BIO_printf(out,"Public key:\n"); if (!BIO_indent(out,indent+3,128)) return 0; 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); } param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey))); if (!BIO_indent(out,indent,128)) return 0; BIO_printf(out,"Parameter set: %s\n",OBJ_nid2ln(param_nid)); return 1; }
static int pub_decode_gost01(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; EC_POINT *pub_key; BIGNUM *X,*Y; ASN1_OCTET_STRING *octet= NULL; int len; const EC_GROUP *group; 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; group = EC_KEY_get0_group(EVP_PKEY_get0(pk)); octet = d2i_ASN1_OCTET_STRING(NULL,&pubkey_buf,pub_len); if (!octet) { GOSTerr(GOST_F_PUB_DECODE_GOST01,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]; } len=octet->length/2; ASN1_OCTET_STRING_free(octet); Y= getbnfrombuf(databuf,len); X= getbnfrombuf(databuf+len,len); OPENSSL_free(databuf); pub_key = EC_POINT_new(group); if (!EC_POINT_set_affine_coordinates_GFp(group ,pub_key,X,Y,NULL)) { GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_EC_LIB); EC_POINT_free(pub_key); BN_free(X); BN_free(Y); return 0; } BN_free(X); BN_free(Y); if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk),pub_key)) { GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_EC_LIB); EC_POINT_free(pub_key); return 0; } EC_POINT_free(pub_key); return 1; }
static int param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b) { if (EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)a)))== EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)b)))) { return 1; } return 0; }
static int pub_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b) { const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a); const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b); if (da && db && da->pub_key && db->pub_key && !BN_cmp(da->pub_key, db->pub_key)) { return 1; } return 0; }
static int pub_cmp_gost01(const EVP_PKEY *a,const EVP_PKEY *b) { const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a); const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b); const EC_POINT *ka,*kb; int ret=0; if (!ea || !eb) return 0; ka = EC_KEY_get0_public_key(ea); kb = EC_KEY_get0_public_key(eb); if (!ka || !kb) return 0; ret = (0==EC_POINT_cmp(EC_KEY_get0_group(ea),ka,kb,NULL)) ; return ret; }
ssize_t tls_get_connection_info(struct tls *ctx, char *buf, size_t buflen) { SSL *conn = ctx->ssl_conn; const char *ocsp_pfx = "", *ocsp_info = ""; const char *proto = "-", *cipher = "-"; char dh[64]; int used_dh_bits = ctx->used_dh_bits, used_ecdh_nid = ctx->used_ecdh_nid; if (conn != NULL) { proto = SSL_get_version(conn); cipher = SSL_get_cipher(conn); #ifdef SSL_get_server_tmp_key if (ctx->flags & TLS_CLIENT) { EVP_PKEY *pk = NULL; int ok = SSL_get_server_tmp_key(conn, &pk); int pk_type = EVP_PKEY_id(pk); if (ok && pk) { if (pk_type == EVP_PKEY_DH) { DH *dh = EVP_PKEY_get0(pk); used_dh_bits = DH_size(dh) * 8; } else if (pk_type == EVP_PKEY_EC) { EC_KEY *ecdh = EVP_PKEY_get0(pk); const EC_GROUP *eg = EC_KEY_get0_group(ecdh); used_ecdh_nid = EC_GROUP_get_curve_name(eg); } EVP_PKEY_free(pk); } } #endif } if (used_dh_bits) { snprintf(dh, sizeof dh, "/DH=%d", used_dh_bits); } else if (used_ecdh_nid) { snprintf(dh, sizeof dh, "/ECDH=%s", OBJ_nid2sn(used_ecdh_nid)); } else { dh[0] = 0; } if (ctx->ocsp_result) { ocsp_info = ctx->ocsp_result; ocsp_pfx = "/OCSP="; } return snprintf(buf, buflen, "%s/%s%s%s%s", proto, cipher, dh, ocsp_pfx, ocsp_info); }
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; }
static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { struct gost_mac_pmeth_data *data = (struct gost_mac_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_Gost28147_89_MAC) { GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_DIGEST_TYPE); return 0; } data->md = (EVP_MD *)p2; return 1; } break; case EVP_PKEY_CTRL_PKCS7_ENCRYPT: case EVP_PKEY_CTRL_PKCS7_DECRYPT: case EVP_PKEY_CTRL_PKCS7_SIGN: return 1; case EVP_PKEY_CTRL_SET_MAC_KEY: if (p1 != 32) { GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_MAC_KEY_LENGTH); return 0; } memcpy(data->key,p2,32); data->key_set = 1; return 1; case EVP_PKEY_CTRL_DIGESTINIT: { EVP_MD_CTX *mctx = p2; void *key; if (!data->key_set) { EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); if (!pkey) { GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,GOST_R_MAC_KEY_NOT_SET); return 0; } key = EVP_PKEY_get0(pkey); if (!key) { GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,GOST_R_MAC_KEY_NOT_SET); return 0; } } else { key = &(data->key); } return mctx->digest->md_ctrl(mctx,EVP_MD_CTRL_SET_KEY,32,key); } } return -2; }
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); BN_bn2bin(dsa->pub_key,databuf); 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_ec_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbs_len) { DSA_SIG *unpacked_sig = NULL; EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); int order = 0; if (!siglen) return 0; if (!pkey) return 0; switch (EVP_PKEY_base_id(pkey)) { case NID_id_GostR3410_2001: case NID_id_GostR3410_2012_256: order = 64; break; case NID_id_GostR3410_2012_512: order = 128; break; default: return 0; } if (!sig) { *siglen = order; return 1; } unpacked_sig = gost_ec_sign(tbs, tbs_len, EVP_PKEY_get0(pkey)); if (!unpacked_sig) { return 0; } return pack_sign_cp(unpacked_sig, order / 2, sig, siglen); }
/* ---------- 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; }
static int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder) { int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group (EVP_PKEY_get0((EVP_PKEY *)pkey))); return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder); }
static int ossl_hmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); EVP_PKEY *pk; ASN1_OCTET_STRING *key; switch (type) { case EVP_PKEY_CTRL_SET_MAC_KEY: if ((!p2 && p1 > 0) || (p1 < -1)) return 0; if (!ASN1_OCTET_STRING_set(&hctx->ktmp, p2, p1)) return 0; break; case EVP_PKEY_CTRL_MD: hctx->md = p2; break; case EVP_PKEY_CTRL_DIGESTINIT: pk = EVP_PKEY_CTX_get0_pkey(ctx); key = EVP_PKEY_get0(pk); if (!HMAC_Init_ex(hctx->ctx, key->data, key->length, hctx->md, NULL)) return 0; break; default: return -2; } return 1; }
/* ---------------------------------------------------------------------*/ static int param_missing_gost94(const EVP_PKEY *pk) { const DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk); if (!dsa) return 1; if (!dsa->q) return 1; return 0; }
static int param_missing_gost01(const EVP_PKEY *pk) { const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk); if (!ec) return 1; if (!EC_KEY_get0_group(ec)) return 1; return 0; }