* https://www.openssl.org/source/license.html
*/
+#include <string.h>
#include <openssl/core_names.h>
#include <openssl/params.h>
+#include <openssl/evp.h>
+#include "internal/sizes.h"
+#include "internal/param_build_set.h"
#include "crypto/rsa.h"
+#include "e_os.h" /* strcasecmp for Windows() */
+
/*
* The intention with the "backend" source file is to offer backend support
* for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
sk_BIGNUM_const_free(coeffs);
return ret;
}
+
+int rsa_pss_params_30_todata(const RSA_PSS_PARAMS_30 *pss, const char *propq,
+ OSSL_PARAM_BLD *bld, OSSL_PARAM params[])
+{
+ if (!rsa_pss_params_30_is_unrestricted(pss)) {
+ int hashalg_nid = rsa_pss_params_30_hashalg(pss);
+ int maskgenalg_nid = rsa_pss_params_30_maskgenalg(pss);
+ int maskgenhashalg_nid = rsa_pss_params_30_maskgenhashalg(pss);
+ int saltlen = rsa_pss_params_30_saltlen(pss);
+ int default_hashalg_nid = rsa_pss_params_30_hashalg(NULL);
+ int default_maskgenalg_nid = rsa_pss_params_30_maskgenalg(NULL);
+ int default_maskgenhashalg_nid = rsa_pss_params_30_maskgenhashalg(NULL);
+ const char *mdname =
+ (hashalg_nid == default_hashalg_nid
+ ? NULL : rsa_oaeppss_nid2name(hashalg_nid));
+ const char *mgfname =
+ (maskgenalg_nid == default_maskgenalg_nid
+ ? NULL : rsa_oaeppss_nid2name(maskgenalg_nid));
+ const char *mgf1mdname =
+ (maskgenhashalg_nid == default_maskgenhashalg_nid
+ ? NULL : rsa_oaeppss_nid2name(maskgenhashalg_nid));
+ const char *key_md = OSSL_PKEY_PARAM_RSA_DIGEST;
+ const char *key_mgf = OSSL_PKEY_PARAM_RSA_MASKGENFUNC;
+ const char *key_mgf1_md = OSSL_PKEY_PARAM_RSA_MGF1_DIGEST;
+ const char *key_saltlen = OSSL_PKEY_PARAM_RSA_PSS_SALTLEN;
+
+ /*
+ * To ensure that the key isn't seen as unrestricted by the recipient,
+ * we make sure that at least one PSS-related parameter is passed, even
+ * if it has a default value; saltlen.
+ */
+ if ((mdname != NULL
+ && !ossl_param_build_set_utf8_string(bld, params, key_md, mdname))
+ || (mgfname != NULL
+ && !ossl_param_build_set_utf8_string(bld, params,
+ key_mgf, mgfname))
+ || (mgf1mdname != NULL
+ && !ossl_param_build_set_utf8_string(bld, params,
+ key_mgf1_md, mgf1mdname))
+ || (!ossl_param_build_set_int(bld, params, key_saltlen, saltlen)))
+ return 0;
+ }
+ return 1;
+}
+
+int rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params,
+ const OSSL_PARAM params[], OPENSSL_CTX *libctx)
+{
+ const OSSL_PARAM *param_md, *param_mgf, *param_mgf1md, *param_saltlen;
+ EVP_MD *md = NULL, *mgf1md = NULL;
+ int saltlen;
+ int ret = 0;
+
+ if (pss_params == NULL)
+ return 0;
+
+ param_md =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_DIGEST);
+ param_mgf =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_MASKGENFUNC);
+ param_mgf1md =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_MGF1_DIGEST);
+ param_saltlen =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_PSS_SALTLEN);
+
+ /*
+ * If we get any of the parameters, we know we have at least some
+ * restrictions, so we start by setting default values, and let each
+ * parameter override their specific restriction data.
+ */
+ if (param_md != NULL || param_mgf != NULL || param_mgf1md != NULL
+ || param_saltlen != NULL)
+ if (!rsa_pss_params_30_set_defaults(pss_params))
+ return 0;
+
+ if (param_mgf != NULL) {
+ int default_maskgenalg_nid = rsa_pss_params_30_maskgenalg(NULL);
+ const char *mgfname = NULL;
+
+ if (param_mgf->data_type == OSSL_PARAM_UTF8_STRING)
+ mgfname = param_mgf->data;
+ else if (!OSSL_PARAM_get_utf8_ptr(param_mgf, &mgfname))
+ return 0;
+
+ /* TODO Revisit this if / when a new MGF algorithm appears */
+ if (strcasecmp(param_mgf->data,
+ rsa_mgf_nid2name(default_maskgenalg_nid)) != 0)
+ return 0;
+ }
+
+ /*
+ * We're only interested in the NIDs that correspond to the MDs, so the
+ * exact propquery is unimportant in the EVP_MD_fetch() calls below.
+ */
+
+ if (param_md != NULL) {
+ const char *mdname = NULL;
+
+ if (param_md->data_type == OSSL_PARAM_UTF8_STRING)
+ mdname = param_md->data;
+ else if (!OSSL_PARAM_get_utf8_ptr(param_mgf, &mdname))
+ goto err;
+
+ if ((md = EVP_MD_fetch(libctx, mdname, NULL)) == NULL
+ || !rsa_pss_params_30_set_hashalg(pss_params,
+ rsa_oaeppss_md2nid(md)))
+ goto err;
+ }
+
+ if (param_mgf1md != NULL) {
+ const char *mgf1mdname = NULL;
+
+ if (param_mgf1md->data_type == OSSL_PARAM_UTF8_STRING)
+ mgf1mdname = param_mgf1md->data;
+ else if (!OSSL_PARAM_get_utf8_ptr(param_mgf, &mgf1mdname))
+ goto err;
+
+ if ((mgf1md = EVP_MD_fetch(libctx, mgf1mdname, NULL)) == NULL
+ || !rsa_pss_params_30_set_maskgenhashalg(pss_params,
+ rsa_oaeppss_md2nid(mgf1md)))
+ goto err;
+ }
+
+ if (param_saltlen != NULL) {
+ if (!OSSL_PARAM_get_int(param_saltlen, &saltlen)
+ || !rsa_pss_params_30_set_saltlen(pss_params, saltlen))
+ goto err;
+ }
+
+ ret = 1;
+
+ err:
+ EVP_MD_free(md);
+ EVP_MD_free(mgf1md);
+ return ret;
+}
BN_clear_free(r->dmp1);
BN_clear_free(r->dmq1);
BN_clear_free(r->iqmp);
- /* TODO(3.0): Support PSS in FIPS_MODULE */
#ifndef FIPS_MODULE
RSA_PSS_PARAMS_free(r->pss);
sk_RSA_PRIME_INFO_pop_free(r->prime_infos, rsa_multip_info_free);
const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *r)
{
+#ifdef FIPS_MODULE
+ return NULL;
+#else
return r->pss;
+#endif
+}
+
+/* Internal */
+RSA_PSS_PARAMS_30 *rsa_get0_pss_params_30(RSA *r)
+{
+ return &r->pss_params;
}
void RSA_clear_flags(RSA *r, int flags)
#include <openssl/rsa.h>
#include "internal/refcount.h"
+#include "crypto/rsa.h"
#define RSA_MAX_PRIME_NUM 5
#define RSA_MIN_MODULUS_BITS 512
BIGNUM *dmp1;
BIGNUM *dmq1;
BIGNUM *iqmp;
- /* If a PSS only key this contains the parameter restrictions */
+
+ /*
+ * If a PSS only key this contains the parameter restrictions.
+ * There are two structures for the same thing, used in different cases.
+ */
+ /* This is used uniquely by OpenSSL provider implementations. */
+ RSA_PSS_PARAMS_30 pss_params;
+#ifndef FIPS_MODULE
+ /* This is used uniquely by rsa_ameth.c and rsa_pmeth.c. */
RSA_PSS_PARAMS *pss;
+#endif
+
#ifndef FIPS_MODULE
/* for multi-prime RSA, defined in RFC 8017 */
STACK_OF(RSA_PRIME_INFO) *prime_infos;
}
+/*
+ * The defaults for PSS restrictions are defined in RFC 8017, A.2.3 RSASSA-PSS
+ * (https://tools.ietf.org/html/rfc8017#appendix-A.2.3):
+ *
+ * If the default values of the hashAlgorithm, maskGenAlgorithm, and
+ * trailerField fields of RSASSA-PSS-params are used, then the algorithm
+ * identifier will have the following value:
+ *
+ * rSASSA-PSS-Default-Identifier RSASSA-AlgorithmIdentifier ::= {
+ * algorithm id-RSASSA-PSS,
+ * parameters RSASSA-PSS-params : {
+ * hashAlgorithm sha1,
+ * maskGenAlgorithm mgf1SHA1,
+ * saltLength 20,
+ * trailerField trailerFieldBC
+ * }
+ * }
+ *
+ * RSASSA-AlgorithmIdentifier ::= AlgorithmIdentifier {
+ * {PKCS1Algorithms}
+ * }
+ */
+static const RSA_PSS_PARAMS_30 default_RSASSA_PSS_params = {
+ NID_sha1, /* default hashAlgorithm */
+ {
+ NID_mgf1, /* default maskGenAlgorithm */
+ NID_sha1 /* default MGF1 hash */
+ },
+ 20, /* default saltLength */
+ 1 /* default trailerField (0xBC) */
+};
+
+int rsa_pss_params_30_set_defaults(RSA_PSS_PARAMS_30 *rsa_pss_params)
+{
+ if (rsa_pss_params == NULL)
+ return 0;
+ *rsa_pss_params = default_RSASSA_PSS_params;
+ return 1;
+}
+
+int rsa_pss_params_30_is_unrestricted(const RSA_PSS_PARAMS_30 *rsa_pss_params)
+{
+ static RSA_PSS_PARAMS_30 pss_params_cmp = { 0, };
+
+ return rsa_pss_params == NULL
+ || memcmp(rsa_pss_params, &pss_params_cmp,
+ sizeof(*rsa_pss_params)) == 0;
+}
+
+int rsa_pss_params_30_copy(RSA_PSS_PARAMS_30 *to,
+ const RSA_PSS_PARAMS_30 *from)
+{
+ memcpy(to, from, sizeof(*to));
+ return 1;
+}
+
+int rsa_pss_params_30_set_hashalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int hashalg_nid)
+{
+ if (rsa_pss_params == NULL)
+ return 0;
+ rsa_pss_params->hash_algorithm_nid = hashalg_nid;
+ return 1;
+}
+
+int rsa_pss_params_30_set_maskgenalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int maskgenalg_nid)
+{
+ if (rsa_pss_params == NULL)
+ return 0;
+ rsa_pss_params->mask_gen.algorithm_nid = maskgenalg_nid;
+ return 1;
+}
+
+int rsa_pss_params_30_set_maskgenhashalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int maskgenhashalg_nid)
+{
+ if (rsa_pss_params == NULL)
+ return 0;
+ rsa_pss_params->mask_gen.hash_algorithm_nid = maskgenhashalg_nid;
+ return 1;
+}
+
+int rsa_pss_params_30_set_saltlen(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int saltlen)
+{
+ if (rsa_pss_params == NULL)
+ return 0;
+ rsa_pss_params->salt_len = saltlen;
+ return 1;
+}
+
+int rsa_pss_params_30_set_trailerfield(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int trailerfield)
+{
+ if (rsa_pss_params == NULL)
+ return 0;
+ rsa_pss_params->trailer_field = trailerfield;
+ return 1;
+}
+
+int rsa_pss_params_30_hashalg(const RSA_PSS_PARAMS_30 *rsa_pss_params)
+{
+ if (rsa_pss_params == NULL)
+ return default_RSASSA_PSS_params.hash_algorithm_nid;
+ return rsa_pss_params->hash_algorithm_nid;
+}
+
+int rsa_pss_params_30_maskgenalg(const RSA_PSS_PARAMS_30 *rsa_pss_params)
+{
+ if (rsa_pss_params == NULL)
+ return default_RSASSA_PSS_params.mask_gen.algorithm_nid;
+ return rsa_pss_params->mask_gen.algorithm_nid;
+}
+
+int rsa_pss_params_30_maskgenhashalg(const RSA_PSS_PARAMS_30 *rsa_pss_params)
+{
+ if (rsa_pss_params == NULL)
+ return default_RSASSA_PSS_params.hash_algorithm_nid;
+ return rsa_pss_params->mask_gen.hash_algorithm_nid;
+}
+
+int rsa_pss_params_30_saltlen(const RSA_PSS_PARAMS_30 *rsa_pss_params)
+{
+ if (rsa_pss_params == NULL)
+ return default_RSASSA_PSS_params.salt_len;
+ return rsa_pss_params->salt_len;
+}
+
+int rsa_pss_params_30_trailerfield(const RSA_PSS_PARAMS_30 *rsa_pss_params)
+{
+ if (rsa_pss_params == NULL)
+ return default_RSASSA_PSS_params.trailer_field;
+ return rsa_pss_params->trailer_field;
+}
+
#if defined(_MSC_VER)
# pragma optimize("",on)
#endif
#include <openssl/core.h>
#include <openssl/rsa.h>
+typedef struct rsa_pss_params_30_st {
+ int hash_algorithm_nid;
+ struct {
+ int algorithm_nid; /* Currently always NID_mgf1 */
+ int hash_algorithm_nid;
+ } mask_gen;
+ unsigned int salt_len;
+ unsigned int trailer_field;
+} RSA_PSS_PARAMS_30;
+
+RSA_PSS_PARAMS_30 *rsa_get0_pss_params_30(RSA *r);
+int rsa_pss_params_30_set_defaults(RSA_PSS_PARAMS_30 *rsa_pss_params);
+int rsa_pss_params_30_copy(RSA_PSS_PARAMS_30 *to,
+ const RSA_PSS_PARAMS_30 *from);
+int rsa_pss_params_30_is_unrestricted(const RSA_PSS_PARAMS_30 *rsa_pss_params);
+int rsa_pss_params_30_set_hashalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int hashalg_nid);
+int rsa_pss_params_30_set_maskgenalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int maskgenalg_nid);
+int rsa_pss_params_30_set_maskgenhashalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int maskgenhashalg_nid);
+int rsa_pss_params_30_set_saltlen(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int saltlen);
+int rsa_pss_params_30_set_trailerfield(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int trailerfield);
+int rsa_pss_params_30_hashalg(const RSA_PSS_PARAMS_30 *rsa_pss_params);
+int rsa_pss_params_30_maskgenalg(const RSA_PSS_PARAMS_30 *rsa_pss_params);
+int rsa_pss_params_30_maskgenhashalg(const RSA_PSS_PARAMS_30 *rsa_pss_params);
+int rsa_pss_params_30_saltlen(const RSA_PSS_PARAMS_30 *rsa_pss_params);
+int rsa_pss_params_30_trailerfield(const RSA_PSS_PARAMS_30 *rsa_pss_params);
+
const char *rsa_mgf_nid2name(int mgf);
int rsa_oaeppss_md2nid(const EVP_MD *md);
const char *rsa_oaeppss_nid2name(int md);
int rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]);
int rsa_fromdata(RSA *rsa, const OSSL_PARAM params[]);
+int rsa_pss_params_30_todata(const RSA_PSS_PARAMS_30 *pss, const char *propq,
+ OSSL_PARAM_BLD *bld, OSSL_PARAM params[]);
+int rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params,
+ const OSSL_PARAM params[], OPENSSL_CTX *libctx);
int rsa_padding_check_PKCS1_type_2_TLS(OPENSSL_CTX *ctx, unsigned char *to,
size_t tlen, const unsigned char *from,
#define OSSL_PKEY_PARAM_DIGEST OSSL_ALG_PARAM_DIGEST
#define OSSL_PKEY_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES
#define OSSL_PKEY_PARAM_DIGEST_SIZE "digest-size"
+#define OSSL_PKEY_PARAM_MASKGENFUNC "mgf"
#define OSSL_PKEY_PARAM_MGF1_DIGEST "mgf1-digest"
#define OSSL_PKEY_PARAM_MGF1_PROPERTIES "mgf1-properties"
/* Key generation parameters */
-#define OSSL_PKEY_PARAM_RSA_BITS OSSL_PKEY_PARAM_BITS
-#define OSSL_PKEY_PARAM_RSA_PRIMES "primes"
+#define OSSL_PKEY_PARAM_RSA_BITS OSSL_PKEY_PARAM_BITS
+#define OSSL_PKEY_PARAM_RSA_PRIMES "primes"
+#define OSSL_PKEY_PARAM_RSA_DIGEST OSSL_PKEY_PARAM_DIGEST
+#define OSSL_PKEY_PARAM_RSA_MASKGENFUNC OSSL_PKEY_PARAM_MASKGENFUNC
+#define OSSL_PKEY_PARAM_RSA_MGF1_DIGEST OSSL_PKEY_PARAM_MGF1_DIGEST
+#define OSSL_PKEY_PARAM_RSA_PSS_SALTLEN "saltlen"
/* Key generation parameters */
#define OSSL_PKEY_PARAM_FFC_TYPE "type"
#define OSSL_SIGNATURE_PARAM_PAD_MODE OSSL_PKEY_PARAM_PAD_MODE
#define OSSL_SIGNATURE_PARAM_DIGEST OSSL_PKEY_PARAM_DIGEST
#define OSSL_SIGNATURE_PARAM_PROPERTIES OSSL_PKEY_PARAM_PROPERTIES
-#define OSSL_SIGNATURE_PARAM_PSS_SALTLEN "pss-saltlen"
+#define OSSL_SIGNATURE_PARAM_PSS_SALTLEN "saltlen"
#define OSSL_SIGNATURE_PARAM_MGF1_DIGEST OSSL_PKEY_PARAM_MGF1_DIGEST
#define OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES \
OSSL_PKEY_PARAM_MGF1_PROPERTIES