static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { DH *dh = NULL; if (ctx->pkey == NULL) { DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET); return 0; } dh = DH_new(); if (!dh) return 0; EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh); /* Note: if error return, pkey is freed by parent routine */ if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) return 0; return DH_generate_key(pkey->pkey.dh); }
static int pkey_gost2001_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); EC_KEY *ec = NULL; if (!data || data->sign_param_nid == NID_undef) { GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN, GOST_R_NO_PARAMETERS_SET); return 0; } ec = EC_KEY_new(); if (!fill_GOST_EC_params(ec, data->sign_param_nid) || !EVP_PKEY_assign(pkey, NID_id_GostR3410_2001, ec)) { EC_KEY_free(ec); return 0; } return 1; }
static int pkey_gost_mac_keygen_base(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey, int mac_nid) { struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); struct gost_mac_key *keydata; if (!data || !data->key_set) { GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN, GOST_R_MAC_KEY_NOT_SET); return 0; } keydata = OPENSSL_malloc(sizeof(struct gost_mac_key)); if (keydata == NULL) return 0; memcpy(keydata->key, data->key, 32); keydata->mac_param_nid = data->mac_param_nid; keydata->mac_size = data->mac_size; EVP_PKEY_assign(pkey, mac_nid, keydata); return 1; }
static int gost94_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) { ASN1_OBJECT *obj=NULL; DSA *dsa = EVP_PKEY_get0(pkey); int nid; if (d2i_ASN1_OBJECT(&obj,pder,derlen)==NULL) { return 0; } nid = OBJ_obj2nid(obj); ASN1_OBJECT_free(obj); if (!dsa) { dsa=DSA_new(); if (!EVP_PKEY_assign(pkey,NID_id_GostR3410_94,dsa)) return 0; } if (!fill_GOST94_params(dsa,nid)) return 0; return 1; }
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_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; }
static int gost_decode_nid_params(EVP_PKEY *pkey, int pkey_nid, int param_nid) { void *key_ptr = EVP_PKEY_get0(pkey); switch (pkey_nid) { case NID_id_GostR3410_2012_256: case NID_id_GostR3410_2012_512: case NID_id_GostR3410_2001: if (!key_ptr) { key_ptr = EC_KEY_new(); if (!EVP_PKEY_assign(pkey, pkey_nid, key_ptr)) { EC_KEY_free(key_ptr); break; } } return fill_GOST_EC_params(key_ptr, param_nid); } return 0; }
static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) { ASN1_OBJECT *obj = NULL; int nid; EC_KEY *ec = EVP_PKEY_get0(pkey); if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) { return 0; } nid = OBJ_obj2nid(obj); ASN1_OBJECT_free(obj); if (!ec) { ec = EC_KEY_new(); if (!EVP_PKEY_assign(pkey, NID_id_GostR3410_2001, ec)) return 0; } if (!fill_GOST2001_params(ec, nid)) return 0; return 1; }
static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) { const unsigned char *p; int pklen; X509_ALGOR *alg; RSA *rsa = NULL; if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &alg, pubkey)) return 0; if ((rsa = d2i_RSAPublicKey(NULL, &p, pklen)) == NULL) { RSAerr(RSA_F_RSA_PUB_DECODE, ERR_R_RSA_LIB); return 0; } if (!rsa_param_decode(rsa, alg)) { RSA_free(rsa); return 0; } EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa); return 1; }
static int rsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) { const unsigned char *p; RSA *rsa; int pklen; const X509_ALGOR *alg; if (!PKCS8_pkey_get0(NULL, &p, &pklen, &alg, p8)) return 0; rsa = d2i_RSAPrivateKey(NULL, &p, pklen); if (rsa == NULL) { RSAerr(RSA_F_RSA_PRIV_DECODE, ERR_R_RSA_LIB); return 0; } if (!rsa_param_decode(rsa, alg)) { RSA_free(rsa); return 0; } EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa); 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 pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { RSA *rsa = NULL; RSA_PKEY_CTX *rctx = ctx->data; BN_GENCB *pcb; int ret; if (rctx->pub_exp == NULL) { rctx->pub_exp = BN_new(); if (rctx->pub_exp == NULL || !BN_set_word(rctx->pub_exp, RSA_F4)) return 0; } rsa = RSA_new(); if (rsa == NULL) return 0; if (ctx->pkey_gencb) { pcb = BN_GENCB_new(); if (pcb == NULL) { RSA_free(rsa); return 0; } evp_pkey_set_cb_translate(pcb, ctx); } else { pcb = NULL; } ret = RSA_generate_multi_prime_key(rsa, rctx->nbits, rctx->primes, rctx->pub_exp, pcb); BN_GENCB_free(pcb); if (ret > 0 && !rsa_set_pss_param(rsa, ctx)) { RSA_free(rsa); return 0; } if (ret > 0) EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, rsa); else RSA_free(rsa); return ret; }
static int gost_set_priv_key(EVP_PKEY *pkey, BIGNUM *priv) { switch (EVP_PKEY_base_id(pkey)) { case NID_id_GostR3410_2012_512: case NID_id_GostR3410_2012_256: 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)) gost_ec_compute_public(ec); break; } default: return 0; } 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); if (databuf == NULL) { GOSTerr(GOST_F_PUB_DECODE_GOST94, ERR_R_MALLOC_FAILURE); ASN1_OCTET_STRING_free(octet); return 0; } 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 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; }
int EVP_PKEY_assign_DH(EVP_PKEY *pkey, DH *key) { return EVP_PKEY_assign(pkey, EVP_PKEY_DH, key); }
/* Setup EVP_PKEY using public, private or generation */ static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg, const unsigned char *p, int plen, ecx_key_op_t op) { ECX_KEY *key = NULL; unsigned char *privkey, *pubkey; if (op != KEY_OP_KEYGEN) { if (palg != NULL) { int ptype; /* Algorithm parameters must be absent */ X509_ALGOR_get0(NULL, &ptype, NULL, palg); if (ptype != V_ASN1_UNDEF) { ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING); return 0; } } if (p == NULL || plen != KEYLENID(id)) { ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING); return 0; } } key = OPENSSL_zalloc(sizeof(*key)); if (key == NULL) { ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE); return 0; } pubkey = key->pubkey; if (op == KEY_OP_PUBLIC) { memcpy(pubkey, p, plen); } else { privkey = key->privkey = OPENSSL_secure_malloc(KEYLENID(id)); if (privkey == NULL) { ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE); goto err; } if (op == KEY_OP_KEYGEN) { if (RAND_priv_bytes(privkey, KEYLENID(id)) <= 0) { OPENSSL_secure_free(privkey); key->privkey = NULL; goto err; } if (id == EVP_PKEY_X25519) { privkey[0] &= 248; privkey[X25519_KEYLEN - 1] &= 127; privkey[X25519_KEYLEN - 1] |= 64; } else if (id == EVP_PKEY_X448) { privkey[0] &= 252; privkey[X448_KEYLEN - 1] |= 128; } } else { memcpy(privkey, p, KEYLENID(id)); } switch (id) { case EVP_PKEY_X25519: X25519_public_from_private(pubkey, privkey); break; case EVP_PKEY_ED25519: ED25519_public_from_private(pubkey, privkey); break; case EVP_PKEY_X448: X448_public_from_private(pubkey, privkey); break; case EVP_PKEY_ED448: ED448_public_from_private(pubkey, privkey); break; } } EVP_PKEY_assign(pkey, id, key); return 1; err: OPENSSL_free(key); return 0; }
static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { DH *dh = NULL; DH_PKEY_CTX *dctx = ctx->data; BN_GENCB *pcb, cb; int ret; if (dctx->rfc5114_param) { switch (dctx->rfc5114_param) { case 1: dh = DH_get_1024_160(); break; case 2: dh = DH_get_2048_224(); break; case 3: dh = DH_get_2048_256(); break; default: return -2; } EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh); return 1; } if (ctx->pkey_gencb) { pcb = &cb; evp_pkey_set_cb_translate(pcb, ctx); } else pcb = NULL; #ifndef OPENSSL_NO_DSA if (dctx->use_dsa) { DSA *dsa_dh; dsa_dh = dsa_dh_generate(dctx, pcb); if (!dsa_dh) return 0; dh = DSA_dup_DH(dsa_dh); DSA_free(dsa_dh); if (!dh) return 0; EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh); return 1; } #endif dh = DH_new(); if (!dh) return 0; ret = DH_generate_parameters_ex(dh, dctx->prime_len, dctx->generator, pcb); if (ret) EVP_PKEY_assign_DH(pkey, dh); else DH_free(dh); return ret; }
int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len ) { GOST_KEY_TRANSPORT *gkt=NULL; unsigned char shared_key[32], ukm[8],crypted_key[44]; const struct gost_cipher_info *param=get_encryption_params(NULL); EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(ctx); struct gost_pmeth_data *data = (gost_pmeth_data*)EVP_PKEY_CTX_get_data(ctx); gost_ctx cctx; int key_is_ephemeral=1; EVP_PKEY *mykey = EVP_PKEY_CTX_get0_peerkey(ctx); /* Do not use vizir cipher parameters with cryptopro */ if (!get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS) && param == gost_cipher_list) { param= gost_cipher_list+1; } if (mykey) { /* If key already set, it is not ephemeral */ key_is_ephemeral=0; if (!gost_get0_priv_key(mykey)) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR); goto err; } } else { /* Otherwise generate ephemeral key */ key_is_ephemeral = 1; if (out) { mykey = EVP_PKEY_new(); EVP_PKEY_assign(mykey, EVP_PKEY_base_id(pubk),DSA_new()); EVP_PKEY_copy_parameters(mykey,pubk); if (!gost_sign_keygen((DSA*)EVP_PKEY_get0(mykey))) { goto err; } } } if (out) make_cp_exchange_key(gost_get0_priv_key(mykey),pubk,shared_key); if (data->shared_ukm) { TINYCLR_SSL_MEMCPY(ukm,data->shared_ukm,8); } else if (out) { if (RAND_bytes(ukm,8)<=0) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOST_R_RANDOM_GENERATOR_FAILURE); goto err; } } if (out) { gost_init(&cctx,param->sblock); keyWrapCryptoPro(&cctx,shared_key,ukm,key,crypted_key); } gkt = GOST_KEY_TRANSPORT_new(); if (!gkt) { goto memerr; } if(!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, ukm,8)) { goto memerr; } if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,crypted_key+40,4)) { goto memerr; } if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,crypted_key+8,32)) { goto memerr; } if (key_is_ephemeral) { if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,out?mykey:pubk)) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY); goto err; } if (out) EVP_PKEY_free(mykey); } ASN1_OBJECT_free(gkt->key_agreement_info->cipher); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); *outlen = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL); if (*outlen == 0) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO); goto err; } if (!key_is_ephemeral) { /* Set control "public key from client certificate used" */ if (EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOST_R_CTRL_CALL_FAILED); goto err; } } GOST_KEY_TRANSPORT_free(gkt); return 1; memerr: if (key_is_ephemeral) { EVP_PKEY_free(mykey); } GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOST_R_MALLOC_FAILURE); err: GOST_KEY_TRANSPORT_free(gkt); return -1; }
int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key) { return EVP_PKEY_assign(pkey, EVP_PKEY_RSA, key); }
int pkey_GOST01cp_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_len, const unsigned char *key, size_t key_len) { GOST_KEY_TRANSPORT *gkt = NULL; EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx); const struct gost_cipher_info *param = get_encryption_params(NULL); unsigned char ukm[8], shared_key[32], crypted_key[44]; int ret = 0; int key_is_ephemeral = 1; gost_ctx cctx; EVP_PKEY *sec_key = EVP_PKEY_CTX_get0_peerkey(pctx); if (data->shared_ukm) { memcpy(ukm, data->shared_ukm, 8); } else if (out) { if (RAND_bytes(ukm, 8) <= 0) { GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_RANDOM_GENERATOR_FAILURE); return 0; } } /* Check for private key in the peer_key of context */ if (sec_key) { key_is_ephemeral = 0; if (!gost_get0_priv_key(sec_key)) { GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR); goto err; } } else { key_is_ephemeral = 1; if (out) { sec_key = EVP_PKEY_new(); EVP_PKEY_assign(sec_key, EVP_PKEY_base_id(pubk), EC_KEY_new()); EVP_PKEY_copy_parameters(sec_key, pubk); if (!gost2001_keygen(EVP_PKEY_get0(sec_key))) { goto err; } } } if (!get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS) && param == gost_cipher_list) { param = gost_cipher_list + 1; } if (out) { VKO_compute_key(shared_key, 32, EC_KEY_get0_public_key(EVP_PKEY_get0(pubk)), EVP_PKEY_get0(sec_key), ukm); gost_init(&cctx, param->sblock); keyWrapCryptoPro(&cctx, shared_key, ukm, key, crypted_key); } gkt = GOST_KEY_TRANSPORT_new(); if (!gkt) { goto err; } if (!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, ukm, 8)) { goto err; } if (!ASN1_OCTET_STRING_set(gkt->key_info->imit, crypted_key + 40, 4)) { goto err; } if (!ASN1_OCTET_STRING_set (gkt->key_info->encrypted_key, crypted_key + 8, 32)) { goto err; } if (key_is_ephemeral) { if (!X509_PUBKEY_set (&gkt->key_agreement_info->ephem_key, out ? sec_key : pubk)) { GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_CANNOT_PACK_EPHEMERAL_KEY); goto err; } } ASN1_OBJECT_free(gkt->key_agreement_info->cipher); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); if (key_is_ephemeral) EVP_PKEY_free(sec_key); if (!key_is_ephemeral) { /* Set control "public key from client certificate used" */ if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0) { GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_CTRL_CALL_FAILED); goto err; } } if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt, out ? &out : NULL)) > 0) ret = 1; GOST_KEY_TRANSPORT_free(gkt); return ret; err: if (key_is_ephemeral) EVP_PKEY_free(sec_key); GOST_KEY_TRANSPORT_free(gkt); return -1; }
int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) { return EVP_PKEY_assign(pkey, EVP_PKEY_EC, key); }