summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2018-10-12 16:56:44 +0200
committerRichard Levitte <levitte@openssl.org>2020-05-13 18:51:15 +0200
commitf55838f34dd5c65420662f7eacf6c6ffd7f261a2 (patch)
treed6b825c43e806c1ed7d6c6d17ce00637baa14572 /crypto
parentbac4bffbfbfaf2d16d248e8bc32023d1d2d48d10 (diff)
OSSL_STORE: Make the 'file' scheme loader handle MSBLOB and PVK files
This involves exposing two pvkfmt.c functions, but only internally. Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com> (Merged from https://github.com/openssl/openssl/pull/11756)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/err/openssl.txt4
-rw-r--r--crypto/include/internal/pem_int.h23
-rw-r--r--crypto/pem/pvkfmt.c39
-rw-r--r--crypto/store/loader_file.c86
4 files changed, 131 insertions, 21 deletions
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 8449ecea74..9fa051f5c3 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -1000,12 +1000,12 @@ PEM_F_D2I_PKCS8PRIVATEKEY_BIO:120:d2i_PKCS8PrivateKey_bio
PEM_F_D2I_PKCS8PRIVATEKEY_FP:121:d2i_PKCS8PrivateKey_fp
PEM_F_DO_B2I:132:do_b2i
PEM_F_DO_B2I_BIO:133:do_b2i_bio
-PEM_F_DO_BLOB_HEADER:134:do_blob_header
+PEM_F_OSSL_DO_BLOB_HEADER:134:ossl_do_blob_header
PEM_F_DO_I2B:146:do_i2b
PEM_F_DO_PK8PKEY:126:do_pk8pkey
PEM_F_DO_PK8PKEY_FP:125:do_pk8pkey_fp
PEM_F_DO_PVK_BODY:135:do_PVK_body
-PEM_F_DO_PVK_HEADER:136:do_PVK_header
+PEM_F_OSSL_DO_PVK_HEADER:136:ossl_do_PVK_header
PEM_F_GET_HEADER_AND_DATA:143:get_header_and_data
PEM_F_GET_NAME:144:get_name
PEM_F_I2B_PVK:137:i2b_PVK
diff --git a/crypto/include/internal/pem_int.h b/crypto/include/internal/pem_int.h
new file mode 100644
index 0000000000..e065ac75a5
--- /dev/null
+++ b/crypto/include/internal/pem_int.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2018 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef HEADER_PEM_INT_H
+# define HEADER_PEM_INT_H
+
+# include <openssl/pem.h>
+
+/* Found in crypto/pem/pvkfmt.c */
+int ossl_do_blob_header(const unsigned char **in, unsigned int length,
+ unsigned int *pmagic, unsigned int *pbitlen,
+ int *pisdss, int *pispub);
+int ossl_do_PVK_header(const unsigned char **in, unsigned int length,
+ int skip_magic,
+ unsigned int *psaltlen, unsigned int *pkeylen);
+
+#endif
diff --git a/crypto/pem/pvkfmt.c b/crypto/pem/pvkfmt.c
index 1a24ce755a..e2f5702880 100644
--- a/crypto/pem/pvkfmt.c
+++ b/crypto/pem/pvkfmt.c
@@ -20,6 +20,7 @@
#include "internal/cryptlib.h"
#include <openssl/pem.h>
+#include "internal/pem_int.h"
#include <openssl/rand.h>
#include <openssl/bn.h>
#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
@@ -89,9 +90,9 @@ static EVP_PKEY *b2i_rsa(const unsigned char **in,
static EVP_PKEY *b2i_dss(const unsigned char **in,
unsigned int bitlen, int ispub);
-static int do_blob_header(const unsigned char **in, unsigned int length,
- unsigned int *pmagic, unsigned int *pbitlen,
- int *pisdss, int *pispub)
+int ossl_do_blob_header(const unsigned char **in, unsigned int length,
+ unsigned int *pmagic, unsigned int *pbitlen,
+ int *pisdss, int *pispub)
{
const unsigned char *p = *in;
if (length < 16)
@@ -99,13 +100,13 @@ static int do_blob_header(const unsigned char **in, unsigned int length,
/* bType */
if (*p == MS_PUBLICKEYBLOB) {
if (*pispub == 0) {
- PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
+ PEMerr(PEM_F_OSSL_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
return 0;
}
*pispub = 1;
} else if (*p == MS_PRIVATEKEYBLOB) {
if (*pispub == 1) {
- PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
+ PEMerr(PEM_F_OSSL_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
return 0;
}
*pispub = 0;
@@ -114,7 +115,7 @@ static int do_blob_header(const unsigned char **in, unsigned int length,
p++;
/* Version */
if (*p++ != 0x2) {
- PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_VERSION_NUMBER);
+ PEMerr(PEM_F_OSSL_DO_BLOB_HEADER, PEM_R_BAD_VERSION_NUMBER);
return 0;
}
/* Ignore reserved, aiKeyAlg */
@@ -129,7 +130,7 @@ static int do_blob_header(const unsigned char **in, unsigned int length,
/* fall thru */
case MS_RSA1MAGIC:
if (*pispub == 0) {
- PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
+ PEMerr(PEM_F_OSSL_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
return 0;
}
break;
@@ -139,13 +140,13 @@ static int do_blob_header(const unsigned char **in, unsigned int length,
/* fall thru */
case MS_RSA2MAGIC:
if (*pispub == 1) {
- PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
+ PEMerr(PEM_F_OSSL_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
return 0;
}
break;
default:
- PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_MAGIC_NUMBER);
+ PEMerr(PEM_F_OSSL_DO_BLOB_HEADER, PEM_R_BAD_MAGIC_NUMBER);
return -1;
}
*in = p;
@@ -191,7 +192,7 @@ static EVP_PKEY *do_b2i(const unsigned char **in, unsigned int length,
const unsigned char *p = *in;
unsigned int bitlen, magic;
int isdss;
- if (do_blob_header(&p, length, &magic, &bitlen, &isdss, &ispub) <= 0) {
+ if (ossl_do_blob_header(&p, length, &magic, &bitlen, &isdss, &ispub) <= 0) {
PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_HEADER_PARSE_ERROR);
return NULL;
}
@@ -218,7 +219,7 @@ static EVP_PKEY *do_b2i_bio(BIO *in, int ispub)
return NULL;
}
p = hdr_buf;
- if (do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) <= 0)
+ if (ossl_do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) <= 0)
return NULL;
length = blob_length(bitlen, isdss, ispub);
@@ -617,26 +618,26 @@ int i2b_PublicKey_bio(BIO *out, const EVP_PKEY *pk)
# ifndef OPENSSL_NO_RC4
-static int do_PVK_header(const unsigned char **in, unsigned int length,
- int skip_magic,
- unsigned int *psaltlen, unsigned int *pkeylen)
+int ossl_do_PVK_header(const unsigned char **in, unsigned int length,
+ int skip_magic,
+ unsigned int *psaltlen, unsigned int *pkeylen)
{
const unsigned char *p = *in;
unsigned int pvk_magic, is_encrypted;
if (skip_magic) {
if (length < 20) {
- PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
+ PEMerr(PEM_F_OSSL_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
return 0;
}
} else {
if (length < 24) {
- PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
+ PEMerr(PEM_F_OSSL_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
return 0;
}
pvk_magic = read_ledword(&p);
if (pvk_magic != MS_PVKMAGIC) {
- PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_BAD_MAGIC_NUMBER);
+ PEMerr(PEM_F_OSSL_DO_PVK_HEADER, PEM_R_BAD_MAGIC_NUMBER);
return 0;
}
}
@@ -653,7 +654,7 @@ static int do_PVK_header(const unsigned char **in, unsigned int length,
return 0;
if (is_encrypted && *psaltlen == 0) {
- PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_INCONSISTENT_HEADER);
+ PEMerr(PEM_F_OSSL_DO_PVK_HEADER, PEM_R_INCONSISTENT_HEADER);
return 0;
}
@@ -766,7 +767,7 @@ EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
}
p = pvk_hdr;
- if (!do_PVK_header(&p, 24, 0, &saltlen, &keylen))
+ if (!ossl_do_PVK_header(&p, 24, 0, &saltlen, &keylen))
return 0;
buflen = (int)keylen + saltlen;
buf = OPENSSL_malloc(buflen);
diff --git a/crypto/store/loader_file.c b/crypto/store/loader_file.c
index 05938a27c8..9f6158ff79 100644
--- a/crypto/store/loader_file.c
+++ b/crypto/store/loader_file.c
@@ -18,6 +18,7 @@
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
+#include "internal/pem_int.h"
#include <openssl/pkcs12.h> /* For the PKCS8 stuff o.O */
#include <openssl/rsa.h> /* For d2i_RSAPrivateKey */
#include <openssl/safestack.h>
@@ -1181,6 +1182,84 @@ static int file_read_pem(BIO *bp, char **pem_name, char **pem_header,
return 1;
}
+static OSSL_STORE_INFO *file_try_read_msblob(BIO *bp, int *matchcount)
+{
+#ifdef OPENSSL_NO_DSA
+ return NULL;
+#else
+ OSSL_STORE_INFO *result = NULL;
+ int ispub = -1;
+
+ {
+ unsigned int magic = 0, bitlen = 0;
+ int isdss = 0;
+ unsigned char peekbuf[16] = { 0, };
+ const unsigned char *p = peekbuf;
+
+ if (BIO_buffer_peek(bp, peekbuf, sizeof(peekbuf)) <= 0)
+ return 0;
+ if (!ossl_do_blob_header(&p, sizeof(peekbuf), &magic, &bitlen,
+ &isdss, &ispub))
+ return 0;
+ }
+
+ (*matchcount)++;
+
+ {
+ EVP_PKEY *tmp = ispub
+ ? b2i_PublicKey_bio(bp)
+ : b2i_PrivateKey_bio(bp);
+
+ if (tmp == NULL
+ || (result = OSSL_STORE_INFO_new_PKEY(tmp)) == NULL) {
+ EVP_PKEY_free(tmp);
+ return 0;
+ }
+ }
+
+ return result;
+#endif
+}
+
+static OSSL_STORE_INFO *file_try_read_PVK(BIO *bp, const UI_METHOD *ui_method,
+ void *ui_data, const char *uri,
+ int *matchcount)
+{
+#if defined(OPENSSL_NO_DSA) || defined(OPENSSL_NO_RC4)
+ return NULL;
+#else
+ OSSL_STORE_INFO *result = NULL;
+
+ {
+ unsigned int saltlen = 0, keylen = 0;
+ unsigned char peekbuf[24] = { 0, };
+ const unsigned char *p = peekbuf;
+
+ if (BIO_buffer_peek(bp, peekbuf, sizeof(peekbuf)) <= 0)
+ return 0;
+ if (!ossl_do_PVK_header(&p, sizeof(peekbuf), 0, &saltlen, &keylen))
+ return 0;
+ }
+
+ (*matchcount)++;
+
+ {
+ EVP_PKEY *tmp = NULL;
+ struct pem_pass_data pass_data;
+
+ if (!file_fill_pem_pass_data(&pass_data, "PVK pass phrase", uri,
+ ui_method, ui_data)
+ || (tmp = b2i_PVK_bio(bp, file_get_pem_pass, &pass_data)) == NULL
+ || (result = OSSL_STORE_INFO_new_PKEY(tmp)) == NULL) {
+ EVP_PKEY_free(tmp);
+ return 0;
+ }
+ }
+
+ return result;
+#endif
+}
+
static int file_read_asn1(BIO *bp, unsigned char **data, long *len)
{
BUF_MEM *mem = NULL;
@@ -1370,6 +1449,13 @@ static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
goto endloop;
}
} else {
+ if ((result = file_try_read_msblob(ctx->_.file.file,
+ &matchcount)) != NULL
+ || (result = file_try_read_PVK(ctx->_.file.file,
+ ui_method, ui_data, ctx->uri,
+ &matchcount)) != NULL)
+ goto endloop;
+
if (!file_read_asn1(ctx->_.file.file, &data, &len)) {
ctx->errcnt++;
goto endloop;