提交 f55838f3 编写于 作者: R Richard Levitte

OSSL_STORE: Make the 'file' scheme loader handle MSBLOB and PVK files

This involves exposing two pvkfmt.c functions, but only internally.
Reviewed-by: NDavid von Oheimb <david.von.oheimb@siemens.com>
(Merged from https://github.com/openssl/openssl/pull/11756)
上级 bac4bffb
......@@ -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
......
/*
* 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
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册