* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/bn.h>
#include <openssl/cms.h>
#include <openssl/core_names.h>
-#include "internal/param_build.h"
+#include "openssl/param_build.h"
#include "crypto/asn1.h"
#include "crypto/evp.h"
#include "crypto/rsa.h"
{
const EVP_MD *sigmd, *mgf1md;
EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
+ RSA *rsa = EVP_PKEY_get0_RSA(pk);
int saltlen;
if (EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) <= 0)
if (saltlen == -1) {
saltlen = EVP_MD_size(sigmd);
} else if (saltlen == -2 || saltlen == -3) {
- saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
+ saltlen = RSA_size(rsa) - EVP_MD_size(sigmd) - 2;
if ((EVP_PKEY_bits(pk) & 0x7) == 1)
saltlen--;
if (saltlen < 0)
uint32_t flags;
const EVP_MD *mgf1md = NULL, *md = NULL;
RSA_PSS_PARAMS *pss;
+ int secbits;
/* Sanity check: make sure it is PSS */
if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS)
else
flags = 0;
/* Note: security bits half number of digest bits */
- X509_SIG_INFO_set(siginf, mdnid, EVP_PKEY_RSA_PSS, EVP_MD_size(md) * 4,
+ secbits = EVP_MD_size(md) * 4;
+ /*
+ * SHA1 and MD5 are known to be broken. Reduce security bits so that
+ * they're no longer accepted at security level 1. The real values don't
+ * really matter as long as they're lower than 80, which is our security
+ * level 1.
+ * https://eprint.iacr.org/2020/014 puts a chosen-prefix attack for SHA1 at
+ * 2^63.4
+ * https://documents.epfl.ch/users/l/le/lenstra/public/papers/lat.pdf
+ * puts a chosen-prefix attack for MD5 at 2^39.
+ */
+ if (mdnid == NID_sha1)
+ secbits = 64;
+ else if (mdnid == NID_md5_sha1)
+ secbits = 68;
+ else if (mdnid == NID_md5)
+ secbits = 39;
+ X509_SIG_INFO_set(siginf, mdnid, EVP_PKEY_RSA_PSS, secbits,
flags);
rv = 1;
err:
DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
-static void *rsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
- int want_domainparams)
+static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
+ EVP_KEYMGMT *to_keymgmt)
{
- RSA *rsa = pk->pkey.rsa;
- OSSL_PARAM_BLD tmpl;
+ RSA *rsa = from->pkey.rsa;
+ OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
const BIGNUM *n = RSA_get0_n(rsa), *e = RSA_get0_e(rsa);
const BIGNUM *d = RSA_get0_d(rsa);
STACK_OF(BIGNUM_const) *primes = NULL, *exps = NULL, *coeffs = NULL;
int numprimes = 0, numexps = 0, numcoeffs = 0;
OSSL_PARAM *params = NULL;
- void *provkey = NULL;
+ int selection = 0;
+ int rv = 0;
+ if (tmpl == NULL)
+ return 0;
/*
- * There are no domain parameters for RSA keys, or rather, they are
- * included in the key data itself.
+ * If the RSA method is foreign, then we can't be sure of anything, and
+ * can therefore not export or pretend to export.
*/
- if (want_domainparams)
+ if (RSA_get_method(rsa) != RSA_PKCS1_OpenSSL())
goto err;
- /* Get all the primes and CRT params */
- if ((primes = sk_BIGNUM_const_new_null()) == NULL
- || (exps = sk_BIGNUM_const_new_null()) == NULL
- || (coeffs = sk_BIGNUM_const_new_null()) == NULL)
+ /* Public parameters must always be present */
+ if (n == NULL || e == NULL)
goto err;
- if (!rsa_get0_all_params(rsa, primes, exps, coeffs))
+ /* |e| and |n| are always present */
+ if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, e))
goto err;
-
- /* Public parameters must always be present */
- if (n == NULL || e == NULL)
+ if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, n))
goto err;
+ selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
if (d != NULL) {
- /* It's a private key, so we should have everything else too */
+ int i;
+
+ /* Get all the primes and CRT params */
+ if ((primes = sk_BIGNUM_const_new_null()) == NULL
+ || (exps = sk_BIGNUM_const_new_null()) == NULL
+ || (coeffs = sk_BIGNUM_const_new_null()) == NULL)
+ goto err;
+
+ if (!rsa_get0_all_params(rsa, primes, exps, coeffs))
+ goto err;
+
numprimes = sk_BIGNUM_const_num(primes);
numexps = sk_BIGNUM_const_num(exps);
numcoeffs = sk_BIGNUM_const_num(coeffs);
- if (numprimes < 2 || numexps < 2 || numcoeffs < 1)
- goto err;
-
/*
- * assert that an OSSL_PARAM_BLD has enough space.
- * (the current 10 places doesn't have space for multi-primes)
+ * It's permisssible to have zero primes, i.e. no CRT params.
+ * Otherwise, there must be at least two, as many exponents,
+ * and one coefficient less.
*/
- if (!ossl_assert(/* n, e */ 2 + /* d */ 1 + /* numprimes */ 1
- + numprimes + numexps + numcoeffs
- <= OSSL_PARAM_BLD_MAX))
+ if (numprimes != 0
+ && (numprimes < 2 || numexps < 2 || numcoeffs < 1))
goto err;
- }
-
- ossl_param_bld_init(&tmpl);
- if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_N, n)
- || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_E, e))
- goto err;
-
- if (d != NULL) {
- int i;
- if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_D, d))
+ if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_D, d))
goto err;
+ selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
for (i = 0; i < numprimes; i++) {
const BIGNUM *num = sk_BIGNUM_const_value(primes, i);
- if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_FACTOR,
+ if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_FACTOR,
num))
goto err;
}
for (i = 0; i < numexps; i++) {
const BIGNUM *num = sk_BIGNUM_const_value(exps, i);
- if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_EXPONENT,
+ if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_EXPONENT,
num))
goto err;
}
for (i = 0; i < numcoeffs; i++) {
const BIGNUM *num = sk_BIGNUM_const_value(coeffs, i);
- if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_COEFFICIENT,
+ if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_COEFFICIENT,
num))
goto err;
}
}
- if ((params = ossl_param_bld_to_param(&tmpl)) == NULL)
+ if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
goto err;
/* We export, the provider imports */
- provkey = evp_keymgmt_importkey(keymgmt, params);
+ rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
err:
sk_BIGNUM_const_free(primes);
sk_BIGNUM_const_free(exps);
sk_BIGNUM_const_free(coeffs);
- ossl_param_bld_free(params);
- return provkey;
+ OSSL_PARAM_BLD_free_params(params);
+ OSSL_PARAM_BLD_free(tmpl);
+ return rv;
+}
+
+static int rsa_pkey_import_from(const OSSL_PARAM params[], void *key)
+{
+ EVP_PKEY *pkey = key;
+ RSA *rsa = RSA_new();
+
+ if (rsa == NULL) {
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (!rsa_fromdata(rsa, params)
+ || !EVP_PKEY_assign_RSA(pkey, rsa)) {
+ RSA_free(rsa);
+ return 0;
+ }
+ return 1;
}
const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
0, 0, 0, 0,
rsa_pkey_dirty_cnt,
- rsa_pkey_export_to
+ rsa_pkey_export_to,
+ rsa_pkey_import_from
},
{
0, 0, 0, 0,
rsa_pkey_dirty_cnt,
- rsa_pkey_export_to
+ rsa_pkey_export_to,
+ rsa_pkey_import_from
};