MSBLOB & PVK: Make it possible to write EVP_PKEYs with provided internal key

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)
This commit is contained in:
Richard Levitte 2020-12-10 14:00:05 +01:00
parent 054cde1756
commit e77c13f8b7
2 changed files with 26 additions and 8 deletions

View File

@ -18,13 +18,14 @@
*/ */
#include "internal/deprecated.h" #include "internal/deprecated.h"
#include "internal/cryptlib.h"
#include <openssl/pem.h> #include <openssl/pem.h>
#include "crypto/pem.h"
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/dsa.h> #include <openssl/dsa.h>
#include <openssl/rsa.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 * 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 char *p;
unsigned int bitlen = 0, magic = 0, keyalg = 0; unsigned int bitlen = 0, magic = 0, keyalg = 0;
int outlen, noinc = 0; int outlen = -1, noinc = 0;
int pktype = EVP_PKEY_id(pk); 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) { if (pktype == EVP_PKEY_RSA) {
bitlen = check_bitlen_rsa(EVP_PKEY_get0_RSA(pk), ispub, &magic); bitlen = check_bitlen_rsa(EVP_PKEY_get0_RSA(pk), ispub, &magic);
keyalg = MS_KEYALG_RSA_KEYX; 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; keyalg = MS_KEYALG_DSS_SIGN;
#endif #endif
} }
if (bitlen == 0) if (bitlen == 0) {
return -1; goto end;
}
outlen = 16 + blob_length(bitlen, outlen = 16 + blob_length(bitlen,
keyalg == MS_KEYALG_DSS_SIGN ? 1 : 0, ispub); keyalg == MS_KEYALG_DSS_SIGN ? 1 : 0, ispub);
if (out == NULL) if (out == NULL)
return outlen; goto end;
if (*out) if (*out)
p = *out; p = *out;
else { else {
if ((p = OPENSSL_malloc(outlen)) == NULL) { if ((p = OPENSSL_malloc(outlen)) == NULL) {
ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
return -1; outlen = -1;
goto end;
} }
*out = p; *out = p;
noinc = 1; noinc = 1;
@ -507,6 +520,10 @@ static int do_i2b(unsigned char **out, const EVP_PKEY *pk, int ispub)
#endif #endif
if (!noinc) if (!noinc)
*out += outlen; *out += outlen;
end:
#ifndef OPENSSL_NO_PROVIDER_CODE
EVP_PKEY_free(pkcopy);
#endif
return outlen; return outlen;
} }

View File

@ -88,6 +88,7 @@ IF[{- !$disabled{"engine"} -}]
ENDIF ENDIF
SOURCE[loader_attic]=e_loader_attic.c ../crypto/pem/pvkfmt.c SOURCE[loader_attic]=e_loader_attic.c ../crypto/pem/pvkfmt.c
DEFINE[loader_attic]=OPENSSL_NO_PROVIDER_CODE
DEPEND[loader_attic]=../libcrypto DEPEND[loader_attic]=../libcrypto
INCLUDE[loader_attic]=../include INCLUDE[loader_attic]=../include
IF[{- defined $target{shared_defflag} -}] IF[{- defined $target{shared_defflag} -}]