diff options
Diffstat (limited to 'crypto/rsa/rsa_backend.c')
-rw-r--r-- | crypto/rsa/rsa_backend.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c index 8c16a56db5..01ee875058 100644 --- a/crypto/rsa/rsa_backend.c +++ b/crypto/rsa/rsa_backend.c @@ -16,9 +16,11 @@ #include <string.h> #include <openssl/core_names.h> #include <openssl/params.h> +#include <openssl/err.h> #include <openssl/evp.h> #include "internal/sizes.h" #include "internal/param_build_set.h" +#include "crypto/asn1.h" #include "crypto/rsa.h" #include "e_os.h" /* strcasecmp for Windows() */ @@ -319,3 +321,156 @@ int ossl_rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params, EVP_MD_free(mgf1md); return ret; } + +#ifndef FIPS_MODULE +RSA_PSS_PARAMS *ossl_rsa_pss_decode(const X509_ALGOR *alg) +{ + RSA_PSS_PARAMS *pss; + + pss = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_PSS_PARAMS), + alg->parameter); + + if (pss == NULL) + return NULL; + + if (pss->maskGenAlgorithm != NULL) { + pss->maskHash = ossl_x509_algor_mgf1_decode(pss->maskGenAlgorithm); + if (pss->maskHash == NULL) { + RSA_PSS_PARAMS_free(pss); + return NULL; + } + } + + return pss; +} + +static int ossl_rsa_sync_to_pss_params_30(RSA *rsa) +{ + const RSA_PSS_PARAMS *legacy_pss = NULL; + RSA_PSS_PARAMS_30 *pss = NULL; + + if (rsa != NULL + && (legacy_pss = RSA_get0_pss_params(rsa)) != NULL + && (pss = ossl_rsa_get0_pss_params_30(rsa)) != NULL) { + const EVP_MD *md = NULL, *mgf1md = NULL; + int md_nid, mgf1md_nid, saltlen, trailerField; + RSA_PSS_PARAMS_30 pss_params; + + /* + * We don't care about the validity of the fields here, we just + * want to synchronise values. Verifying here makes it impossible + * to even read a key with invalid values, making it hard to test + * a bad situation. + * + * Other routines use ossl_rsa_pss_get_param(), so the values will + * be checked, eventually. + */ + if (!ossl_rsa_pss_get_param_unverified(legacy_pss, &md, &mgf1md, + &saltlen, &trailerField)) + return 0; + md_nid = EVP_MD_type(md); + mgf1md_nid = EVP_MD_type(mgf1md); + if (!ossl_rsa_pss_params_30_set_defaults(&pss_params) + || !ossl_rsa_pss_params_30_set_hashalg(&pss_params, md_nid) + || !ossl_rsa_pss_params_30_set_maskgenhashalg(&pss_params, + mgf1md_nid) + || !ossl_rsa_pss_params_30_set_saltlen(&pss_params, saltlen) + || !ossl_rsa_pss_params_30_set_trailerfield(&pss_params, + trailerField)) + return 0; + *pss = pss_params; + } + return 1; +} + +int ossl_rsa_pss_get_param_unverified(const RSA_PSS_PARAMS *pss, + const EVP_MD **pmd, const EVP_MD **pmgf1md, + int *psaltlen, int *ptrailerField) +{ + RSA_PSS_PARAMS_30 pss_params; + + /* Get the defaults from the ONE place */ + (void)ossl_rsa_pss_params_30_set_defaults(&pss_params); + + if (pss == NULL) + return 0; + *pmd = ossl_x509_algor_get_md(pss->hashAlgorithm); + if (*pmd == NULL) + return 0; + *pmgf1md = ossl_x509_algor_get_md(pss->maskHash); + if (*pmgf1md == NULL) + return 0; + if (pss->saltLength) + *psaltlen = ASN1_INTEGER_get(pss->saltLength); + else + *psaltlen = ossl_rsa_pss_params_30_saltlen(&pss_params); + if (pss->trailerField) + *ptrailerField = ASN1_INTEGER_get(pss->trailerField); + else + *ptrailerField = ossl_rsa_pss_params_30_trailerfield(&pss_params);; + + return 1; +} + +int ossl_rsa_param_decode(RSA *rsa, const X509_ALGOR *alg) +{ + RSA_PSS_PARAMS *pss; + const ASN1_OBJECT *algoid; + const void *algp; + int algptype; + + X509_ALGOR_get0(&algoid, &algptype, &algp, alg); + if (OBJ_obj2nid(algoid) != EVP_PKEY_RSA_PSS) + return 1; + if (algptype == V_ASN1_UNDEF) + return 1; + if (algptype != V_ASN1_SEQUENCE) { + ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PSS_PARAMETERS); + return 0; + } + if ((pss = ossl_rsa_pss_decode(alg)) == NULL + || !ossl_rsa_set0_pss_params(rsa, pss)) { + RSA_PSS_PARAMS_free(pss); + return 0; + } + if (!ossl_rsa_sync_to_pss_params_30(rsa)) + return 0; + return 1; +} + +RSA *ossl_rsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, + OSSL_LIB_CTX *libctx, const char *propq) +{ + const unsigned char *p; + RSA *rsa; + int pklen; + const X509_ALGOR *alg; + + if (!PKCS8_pkey_get0(NULL, &p, &pklen, &alg, p8inf)) + return 0; + rsa = d2i_RSAPrivateKey(NULL, &p, pklen); + if (rsa == NULL) { + ERR_raise(ERR_LIB_RSA, ERR_R_RSA_LIB); + return NULL; + } + if (!ossl_rsa_param_decode(rsa, alg)) { + RSA_free(rsa); + return NULL; + } + + RSA_clear_flags(rsa, RSA_FLAG_TYPE_MASK); + switch (OBJ_obj2nid(alg->algorithm)) { + case EVP_PKEY_RSA: + RSA_set_flags(rsa, RSA_FLAG_TYPE_RSA); + break; + case EVP_PKEY_RSA_PSS: + RSA_set_flags(rsa, RSA_FLAG_TYPE_RSASSAPSS); + break; + default: + /* Leave the type bits zero */ + break; + } + + return rsa; +} +#endif |