summaryrefslogtreecommitdiffstats
path: root/crypto/rsa/rsa_backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/rsa/rsa_backend.c')
-rw-r--r--crypto/rsa/rsa_backend.c155
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