diff --git a/oqsprov/oqsprov_keys.c b/oqsprov/oqsprov_keys.c index fcfe4f5e..357f4d44 100644 --- a/oqsprov/oqsprov_keys.c +++ b/oqsprov/oqsprov_keys.c @@ -695,6 +695,7 @@ static OQSX_KEY *oqsx_key_op(const X509_ALGOR *palg, const unsigned char *p, ERR_raise(ERR_LIB_USER, OQSPROV_R_INVALID_ENCODING); goto err_key_op; } + key->privkeylen_cmp[i] = privlen; } else privlen = key->privkeylen_cmp[i]; } else { // PQC key @@ -883,16 +884,18 @@ static int oqsx_key_recreate_classickey(OQSX_KEY *key, oqsx_key_op_t op) if (get_oqsname_fromtls(name) == 0) { const unsigned char *enc_privkey = key->comp_privkey[i]; if (!key->oqsx_provider_ctx.oqsx_evp_ctx->evp_info - ->raw_key_support) + ->raw_key_support) { + EVP_PKEY *npk; key->classical_pkey = d2i_PrivateKey( key->oqsx_provider_ctx.oqsx_evp_ctx->evp_info ->keytype, NULL, &enc_privkey, key->privkeylen_cmp[i]); - else + } else { key->classical_pkey = EVP_PKEY_new_raw_private_key( key->oqsx_provider_ctx.oqsx_evp_ctx->evp_info ->keytype, NULL, enc_privkey, key->privkeylen_cmp[i]); + } if (!key->classical_pkey) { ERR_raise(ERR_LIB_USER, OQSPROV_R_INVALID_ENCODING); OPENSSL_free(name); @@ -1072,7 +1075,7 @@ OQSX_KEY *oqsx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, STACK_OF(ASN1_TYPE) *sk = NULL; ASN1_TYPE *aType = NULL; unsigned char *concat_key, *buf; - int count, aux, i, buflen, rsa_diff = 0; + int count, aux, i, buflen, key_diff = 0; if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8inf)) return 0; @@ -1094,13 +1097,17 @@ OQSX_KEY *oqsx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, return NULL; } else { count = sk_ASN1_TYPE_num(sk); + plen = 2 * plen; // get more than necessary in case its needed concat_key = OPENSSL_zalloc(plen); PKCS8_PRIV_KEY_INFO *p8inf_internal = NULL; + const X509_ALGOR *palg_internal; + int keytype, nid; aux = 0; for (i = 0; i < count; i++) { aType = sk_ASN1_TYPE_pop(sk); p8inf_internal = PKCS8_PRIV_KEY_INFO_new(); + nid = 1; char *name; if ((name = get_cmpname(OBJ_obj2nid(palg->algorithm), count - 1 - i)) @@ -1118,7 +1125,7 @@ OQSX_KEY *oqsx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, p8inf_internal = d2i_PKCS8_PRIV_KEY_INFO(&p8inf_internal, &buf2, buflen); - if (!PKCS8_pkey_get0(NULL, &buf, &buflen, NULL, + if (!PKCS8_pkey_get0(NULL, &buf, &buflen, &palg_internal, p8inf_internal)) { OPENSSL_free(name); ASN1_TYPE_free(aType); @@ -1128,17 +1135,63 @@ OQSX_KEY *oqsx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, return NULL; } - aux += buflen; - memcpy(concat_key + plen - 1 - aux, buf, buflen); + keytype = OBJ_obj2nid(palg_internal->algorithm); + + // Checking OPTIONAL params on EC + if (keytype == EVP_PKEY_EC) { + nid = OBJ_obj2nid(palg_internal->parameter->value.object); + for (int j = 0; j < OSSL_NELEM(nids_sig); j++) { + if ((nids_sig[j].nid == nid) + && (nids_sig[j].length_private_key > buflen)) { + EC_KEY *ec_pkey; + const unsigned char *buf3 = buf; + unsigned char *buf4, *buf5; + + if (buflen + != nids_sig[j].kex_length_secret + + 7) { // no ECParameter and no + // Pubkey + OPENSSL_free(name); + ASN1_TYPE_free(aType); + PKCS8_PRIV_KEY_INFO_free(p8inf_internal); + OPENSSL_clear_free(concat_key, plen); + sk_ASN1_TYPE_free(sk); + return NULL; + } + ec_pkey = EC_KEY_new_by_curve_name(nid); + ec_pkey = d2i_ECPrivateKey(&ec_pkey, &buf3, buflen); + EC_KEY_set_enc_flags(ec_pkey, 0); + buf4 = OPENSSL_malloc( + nids_sig[j].length_private_key); + buf5 = buf4; + buflen = i2d_ECPrivateKey(ec_pkey, &buf5); + + aux += buflen; + memcpy(concat_key + plen - 1 - aux, buf4, buflen); + nid = 0; // use as flag to not memcpy twice + + OPENSSL_clear_free(buf4, buflen); + EC_KEY_free(ec_pkey); + break; + } + } + } + // if is a RSA key the actual encoding size might be different // from max size we calculate that difference for to facilitate // the key reconstruction - if (!strncmp(name, "rsa", 3) || !strncmp(name, "pss", 3)) { + if (keytype == EVP_PKEY_RSA) { if (name[3] == '3') // 3072 - rsa_diff = nids_sig[5].length_private_key - buflen; + key_diff = nids_sig[5].length_private_key - buflen; else // 2048 - rsa_diff = nids_sig[6].length_private_key - buflen; + key_diff = nids_sig[6].length_private_key - buflen; } + + if (nid) { + aux += buflen; + memcpy(concat_key + plen - 1 - aux, buf, buflen); + } + OPENSSL_free(name); PKCS8_PRIV_KEY_INFO_free(p8inf_internal); ASN1_TYPE_free(aType); @@ -1146,12 +1199,12 @@ OQSX_KEY *oqsx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, p = OPENSSL_memdup(concat_key + plen - 1 - aux, aux); OPENSSL_clear_free(concat_key, plen); - plen = aux; + plen = aux; // update plen to correct size sk_ASN1_TYPE_free(sk); } } - oqsx = oqsx_key_op(palg, p, plen + rsa_diff, KEY_OP_PRIVATE, libctx, propq); + oqsx = oqsx_key_op(palg, p, plen + key_diff, KEY_OP_PRIVATE, libctx, propq); if (get_keytype(OBJ_obj2nid(palg->algorithm)) != KEY_TYPE_CMP_SIG) { ASN1_OCTET_STRING_free(oct); } else {