Support key check in EVP interface
[openssl.git] / crypto / rsa / rsa_ameth.c
index 9b4300b2d7def0ad5d8e2e3a98e87a7034b3189d..97a37ba47d3e853805143d93787c5c836e957701 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -44,11 +44,8 @@ static int rsa_param_encode(const EVP_PKEY *pkey,
         return 1;
     }
     /* Encode PSS parameters */
-    if (!ASN1_item_pack(rsa->pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), pstr)) {
-        ASN1_STRING_free(*pstr);
-        *pstr = NULL;
+    if (ASN1_item_pack(rsa->pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), pstr) == NULL)
         return 0;
-    }
 
     *pstrtype = V_ASN1_SEQUENCE;
     return 1;
@@ -155,12 +152,14 @@ static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
 
     if (rklen <= 0) {
         RSAerr(RSA_F_RSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+        ASN1_STRING_free(str);
         return 0;
     }
 
     if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
                          strtype, str, rk, rklen)) {
         RSAerr(RSA_F_RSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+        ASN1_STRING_free(str);
         return 0;
     }
 
@@ -251,8 +250,9 @@ static int rsa_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss,
     if (pss->hashAlgorithm) {
         if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0)
             goto err;
-    } else if (BIO_puts(bp, "sha1 (default)") <= 0)
+    } else if (BIO_puts(bp, "sha1 (default)") <= 0) {
         goto err;
+    }
 
     if (BIO_puts(bp, "\n") <= 0)
         goto err;
@@ -271,10 +271,12 @@ static int rsa_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss,
         if (maskHash != NULL) {
             if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0)
                 goto err;
-        } else if (BIO_puts(bp, "INVALID") <= 0)
+        } else if (BIO_puts(bp, "INVALID") <= 0) {
             goto err;
-    } else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0)
+        }
+    } else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) {
         goto err;
+    }
     BIO_puts(bp, "\n");
 
     if (!BIO_indent(bp, indent, 128))
@@ -284,8 +286,9 @@ static int rsa_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss,
     if (pss->saltLength) {
         if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0)
             goto err;
-    } else if (BIO_puts(bp, "14 (default)") <= 0)
+    } else if (BIO_puts(bp, "14 (default)") <= 0) {
         goto err;
+    }
     BIO_puts(bp, "\n");
 
     if (!BIO_indent(bp, indent, 128))
@@ -295,8 +298,9 @@ static int rsa_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss,
     if (pss->trailerField) {
         if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0)
             goto err;
-    } else if (BIO_puts(bp, "BC (default)") <= 0)
+    } else if (BIO_puts(bp, "BC (default)") <= 0) {
         goto err;
+    }
     BIO_puts(bp, "\n");
 
     rv = 1;
@@ -398,6 +402,7 @@ static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
     if (OBJ_obj2nid(sigalg->algorithm) == EVP_PKEY_RSA_PSS) {
         int rv;
         RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg);
+
         rv = rsa_pss_param_print(bp, 0, pss, indent);
         RSA_PSS_PARAMS_free(pss);
         if (!rv)
@@ -491,7 +496,7 @@ static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md)
     /* need to embed algorithm ID inside another */
     if (!rsa_md_to_algor(&algtmp, mgf1md))
         goto err;
-    if (!ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp))
+    if (ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp) == NULL)
          goto err;
     *palg = X509_ALGOR_new();
     if (*palg == NULL)
@@ -536,11 +541,11 @@ static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
         return NULL;
     if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen))
         return NULL;
-    if (saltlen == -1)
+    if (saltlen == -1) {
         saltlen = EVP_MD_size(sigmd);
-    else if (saltlen == -2) {
+    else if (saltlen == -2) {
         saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
-        if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0)
+        if ((EVP_PKEY_bits(pk) & 0x7) == 1)
             saltlen--;
     }
 
@@ -564,9 +569,11 @@ RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd,
     if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd))
         goto err;
     if (mgf1md == NULL)
-            mgf1md = sigmd;
+        mgf1md = sigmd;
     if (!rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md))
         goto err;
+    if (!rsa_md_to_algor(&pss->maskHash, mgf1md))
+        goto err;
     return pss;
  err:
     RSA_PSS_PARAMS_free(pss);
@@ -576,15 +583,12 @@ RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd,
 static ASN1_STRING *rsa_ctx_to_pss_string(EVP_PKEY_CTX *pkctx)
 {
     RSA_PSS_PARAMS *pss = rsa_ctx_to_pss(pkctx);
-    ASN1_STRING *os = NULL;
+    ASN1_STRING *os;
 
     if (pss == NULL)
         return NULL;
 
-    if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) {
-        ASN1_STRING_free(os);
-        os = NULL;
-    }
+    os = ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), NULL);
     RSA_PSS_PARAMS_free(pss);
     return os;
 }
@@ -663,8 +667,9 @@ int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
             RSAerr(RSA_F_RSA_PSS_GET_PARAM, RSA_R_INVALID_SALT_LENGTH);
             return 0;
         }
-    } else
+    } else {
         *psaltlen = 20;
+    }
 
     /*
      * low-level routines support only trailer field 0xbc (value 1) and
@@ -672,7 +677,7 @@ int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
      */
     if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) {
         RSAerr(RSA_F_RSA_PSS_GET_PARAM, RSA_R_INVALID_TRAILER);
-        return 0; 
+        return 0;
     }
 
     return 1;
@@ -787,6 +792,41 @@ static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
     return 2;
 }
 
+static int rsa_sig_info_set(X509_SIG_INFO *siginf, const X509_ALGOR *sigalg,
+                            const ASN1_STRING *sig)
+{
+    int rv = 0;
+    int mdnid, saltlen;
+    uint32_t flags;
+    const EVP_MD *mgf1md = NULL, *md = NULL;
+    RSA_PSS_PARAMS *pss;
+
+    /* Sanity check: make sure it is PSS */
+    if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS)
+        return 0;
+    /* Decode PSS parameters */
+    pss = rsa_pss_decode(sigalg);
+    if (!rsa_pss_get_param(pss, &md, &mgf1md, &saltlen))
+        goto err;
+    mdnid = EVP_MD_type(md);
+    /*
+     * For TLS need SHA256, SHA384 or SHA512, digest and MGF1 digest must
+     * match and salt length must equal digest size
+     */
+    if ((mdnid == NID_sha256 || mdnid == NID_sha384 || mdnid == NID_sha512)
+            && mdnid == EVP_MD_type(mgf1md) && saltlen == EVP_MD_size(md))
+        flags = X509_SIG_INFO_TLS;
+    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,
+                      flags);
+    rv = 1;
+    err:
+    RSA_PSS_PARAMS_free(pss);
+    return rv;
+}
+
 #ifndef OPENSSL_NO_CMS
 static RSA_OAEP_PARAMS *rsa_oaep_decode(const X509_ALGOR *alg)
 {
@@ -944,6 +984,11 @@ static int rsa_cms_encrypt(CMS_RecipientInfo *ri)
 }
 #endif
 
+static int rsa_pkey_check(const EVP_PKEY *pkey)
+{
+    return RSA_check_key_ex(pkey->pkey.rsa, NULL);
+}
+
 const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
     {
      EVP_PKEY_RSA,
@@ -974,7 +1019,10 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
      old_rsa_priv_decode,
      old_rsa_priv_encode,
      rsa_item_verify,
-     rsa_item_sign},
+     rsa_item_sign,
+     rsa_sig_info_set,
+     rsa_pkey_check
+    },
 
     {
      EVP_PKEY_RSA2,
@@ -1011,4 +1059,6 @@ const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth = {
      0, 0,
      rsa_item_verify,
      rsa_item_sign,
+     0,
+     rsa_pkey_check
 };