MSBLOB & PVK: Make it possible to write EVP_PKEYs with provided internal key
authorRichard Levitte <levitte@openssl.org>
Thu, 10 Dec 2020 13:00:05 +0000 (14:00 +0100)
committerRichard Levitte <levitte@openssl.org>
Thu, 17 Dec 2020 11:02:08 +0000 (12:02 +0100)
So far, the MSBLOB and PVK writers could only handle EVP_PKEYs with
legacy internal keys.

Specially to be able to compile the loader_attic engine, we use the C
macro OPENSSL_NO_PROVIDER_CODE to avoid building the provider specific
things when we don't need them.  The alternative is to suck half of
crypto/evp/ into loader_attic, and that's just not feasible.

Fixes #13503

Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/13661)

crypto/pem/pvkfmt.c
engines/build.info

index b0aa76b3f522a2953d3a13860a30510c909867bd..de673be005f3eda1244310d7e91074f1e2809dd9 100644 (file)
  */
 #include "internal/deprecated.h"
 
-#include "internal/cryptlib.h"
 #include <openssl/pem.h>
-#include "crypto/pem.h"
 #include <openssl/rand.h>
 #include <openssl/bn.h>
 #include <openssl/dsa.h>
 #include <openssl/rsa.h>
+#include "internal/cryptlib.h"
+#include "crypto/pem.h"
+#include "crypto/evp.h"
 
 /*
  * Utility function: read a DWORD (4 byte unsigned integer) in little endian
@@ -461,9 +462,19 @@ static int do_i2b(unsigned char **out, const EVP_PKEY *pk, int ispub)
 {
     unsigned char *p;
     unsigned int bitlen = 0, magic = 0, keyalg = 0;
-    int outlen, noinc = 0;
-    int pktype = EVP_PKEY_id(pk);
+    int outlen = -1, noinc = 0;
+    int pktype;
+#ifndef OPENSSL_NO_PROVIDER_CODE
+    EVP_PKEY *pkcopy = NULL;
+
+    if (evp_pkey_is_provided(pk)) {
+        if (!evp_pkey_copy_downgraded(&pkcopy, pk))
+            goto end;
+        pk = pkcopy;
+    }
+#endif
 
+    pktype = EVP_PKEY_id(pk);
     if (pktype == EVP_PKEY_RSA) {
         bitlen = check_bitlen_rsa(EVP_PKEY_get0_RSA(pk), ispub, &magic);
         keyalg = MS_KEYALG_RSA_KEYX;
@@ -473,18 +484,20 @@ static int do_i2b(unsigned char **out, const EVP_PKEY *pk, int ispub)
         keyalg = MS_KEYALG_DSS_SIGN;
 #endif
     }
-    if (bitlen == 0)
-        return -1;
+    if (bitlen == 0) {
+        goto end;
+    }
     outlen = 16 + blob_length(bitlen,
                               keyalg == MS_KEYALG_DSS_SIGN ? 1 : 0, ispub);
     if (out == NULL)
-        return outlen;
+        goto end;
     if (*out)
         p = *out;
     else {
         if ((p = OPENSSL_malloc(outlen)) == NULL) {
             ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
-            return -1;
+            outlen = -1;
+            goto end;
         }
         *out = p;
         noinc = 1;
@@ -507,6 +520,10 @@ static int do_i2b(unsigned char **out, const EVP_PKEY *pk, int ispub)
 #endif
     if (!noinc)
         *out += outlen;
+ end:
+#ifndef OPENSSL_NO_PROVIDER_CODE
+    EVP_PKEY_free(pkcopy);
+#endif
     return outlen;
 }
 
index e47f2d44a59f414faf26cc1d0378db0952c6723e..e27503594697cc818d4eb60cdeeab8bc7da9b914 100644 (file)
@@ -88,6 +88,7 @@ IF[{- !$disabled{"engine"} -}]
     ENDIF
 
     SOURCE[loader_attic]=e_loader_attic.c ../crypto/pem/pvkfmt.c
+    DEFINE[loader_attic]=OPENSSL_NO_PROVIDER_CODE
     DEPEND[loader_attic]=../libcrypto
     INCLUDE[loader_attic]=../include
     IF[{- defined $target{shared_defflag} -}]