Added processing of user cert chain in DER format. Added arg check on "wolfSSL_get_certificate" to fix NULL dereference if certificate not yet set via "wolfSSL_use_certificate_buffer" or "wolfSSL_use_certificate_file". Added "wolfSSL_CTX_use_certificate_chain_buffer_format" to expose way to import certificate chain buffer as ASN1 (since "wolfSSL_CTX_use_certificate_chain_buffer" assumes PEM) . Changed ProcessFile from static and added as local in internal.h.

This commit is contained in:
David Garske
2016-09-22 14:02:32 -07:00
parent cfc5de8c5a
commit c3c3419138
3 changed files with 184 additions and 132 deletions

211
src/ssl.c
View File

@@ -3783,63 +3783,17 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
}
/* process the buffer buff, length sz, into ctx of format and type
used tracks bytes consumed, userChain specifies a user cert chain
to pass during the handshake */
static int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
/* process user cert chain to pass during the handshake */
static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff,
long sz, int format, int type, WOLFSSL* ssl,
long* used, int userChain)
long* used, EncryptedInfo* info)
{
DerBuffer* der = NULL; /* holds DER or RAW (for NTRU) */
int ret;
int eccKey = 0;
int rsaKey = 0;
int ret = 0;
void* heap = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL);
#ifdef WOLFSSL_SMALL_STACK
EncryptedInfo* info = NULL;
#else
EncryptedInfo info[1];
#endif
(void)rsaKey;
if (used)
*used = sz; /* used bytes default to sz, PEM chain may shorten*/
if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM
&& format != SSL_FILETYPE_RAW)
return SSL_BAD_FILETYPE;
if (ctx == NULL && ssl == NULL)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_SMALL_STACK
info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (info == NULL)
return MEMORY_E;
#endif
info->set = 0;
info->ctx = ctx;
info->consumed = 0;
if (format == SSL_FILETYPE_PEM) {
ret = PemToDer(buff, sz, type, &der, heap, info, &eccKey);
if (used)
*used = info->consumed;
if (ret < 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
FreeDer(&der);
return ret;
}
/* we may have a user cert chain, try to consume */
if (userChain && type == CERT_TYPE && info->consumed < sz) {
if (type == CERT_TYPE && info->consumed < sz) {
#ifdef WOLFSSL_SMALL_STACK
byte staticBuffer[1]; /* force heap usage */
#else
@@ -3847,7 +3801,7 @@ static int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
#endif
byte* chainBuffer = staticBuffer;
int dynamicBuffer = 0;
word32 bufferSz = sizeof(staticBuffer);
word32 bufferSz = FILE_BUFFER_SIZE;
long consumed = info->consumed;
word32 idx = 0;
int gotOne = 0;
@@ -3858,10 +3812,6 @@ static int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
/* will shrink to actual size */
chainBuffer = (byte*)XMALLOC(bufferSz, heap, DYNAMIC_TYPE_FILE);
if (chainBuffer == NULL) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
FreeDer(&der);
return MEMORY_E;
}
dynamicBuffer = 1;
@@ -3869,11 +3819,33 @@ static int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
WOLFSSL_MSG("Processing Cert Chain");
while (consumed < sz) {
int eccKey = 0;
DerBuffer* part = NULL;
word32 remain = (word32)(sz - consumed);
info->consumed = 0;
ret = PemToDer(buff + consumed, sz - consumed, type, &part,
if (format == SSL_FILETYPE_PEM) {
ret = PemToDer(buff + consumed, remain, type, &part,
heap, info, &eccKey);
}
else {
int length = remain;
if (format == SSL_FILETYPE_ASN1) {
/* get length of der (read sequence) */
word32 inOutIdx = 0;
if (GetSequence(buff + consumed, &inOutIdx, &length, remain) < 0) {
ret = SSL_NO_PEM_HEADER;
}
length += inOutIdx; /* include leading squence */
}
info->consumed = length;
if (ret == 0) {
ret = AllocDer(&part, length, type, heap);
if (ret == 0) {
XMEMCPY(part->buffer, buff + consumed, length);
}
}
}
if (ret == 0) {
gotOne = 1;
if ((idx + part->length) > bufferSz) {
@@ -3893,7 +3865,7 @@ static int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
FreeDer(&part);
if (ret == SSL_NO_PEM_HEADER && gotOne) {
WOLFSSL_MSG("We got one good PEM so stuff at end ok");
WOLFSSL_MSG("We got one good cert, so stuff at end ok");
break;
}
@@ -3901,10 +3873,6 @@ static int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
WOLFSSL_MSG(" Error in Cert in Chain");
if (dynamicBuffer)
XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
#ifdef WOLFSSL_SMALL_STACK
XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
FreeDer(&der);
return ret;
}
WOLFSSL_MSG(" Consumed another Cert in Chain");
@@ -3934,7 +3902,86 @@ static int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
if (dynamicBuffer)
XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
}
return ret;
}
/* process the buffer buff, length sz, into ctx of format and type
used tracks bytes consumed, userChain specifies a user cert chain
to pass during the handshake */
int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
long sz, int format, int type, WOLFSSL* ssl,
long* used, int userChain)
{
DerBuffer* der = NULL; /* holds DER or RAW (for NTRU) */
int ret = 0;
int eccKey = 0;
int rsaKey = 0;
void* heap = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL);
#ifdef WOLFSSL_SMALL_STACK
EncryptedInfo* info = NULL;
#else
EncryptedInfo info[1];
#endif
(void)rsaKey;
if (used)
*used = sz; /* used bytes default to sz, PEM chain may shorten*/
/* check args */
if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM
&& format != SSL_FILETYPE_RAW)
return SSL_BAD_FILETYPE;
if (ctx == NULL && ssl == NULL)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_SMALL_STACK
info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (info == NULL)
return MEMORY_E;
#endif
info->set = 0;
info->ctx = ctx;
info->consumed = 0;
if (format == SSL_FILETYPE_PEM) {
ret = PemToDer(buff, sz, type, &der, heap, info, &eccKey);
}
else { /* ASN1 (DER) or RAW (NTRU) */
int length = (int)sz;
if (format == SSL_FILETYPE_ASN1) {
/* get length of der (read sequence) */
word32 inOutIdx = 0;
if (GetSequence(buff, &inOutIdx, &length, (word32)sz) < 0) {
ret = ASN_PARSE_E;
}
length += inOutIdx; /* include leading squence */
}
info->consumed = length;
if (ret == 0) {
ret = AllocDer(&der, (word32)length, type, heap);
if (ret == 0) {
XMEMCPY(der->buffer, buff, length);
}
}
}
if (used) {
*used = info->consumed;
}
/* process user chain */
if (ret >= 0) {
if (userChain) {
ret = ProcessUserChain(ctx, buff, sz, format, type, ssl, used, info);
}
}
/* check for error */
if (ret < 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -3942,19 +3989,6 @@ static int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
FreeDer(&der);
return ret;
}
}
}
else { /* ASN1 (DER) or RAW (NTRU) */
ret = AllocDer(&der, (word32)sz, type, heap);
if (ret < 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
XMEMCPY(der->buffer, buff, sz);
}
#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
/* for SSL_FILETYPE_PEM, PemToDer manage the decryption if required */
@@ -8775,12 +8809,18 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
}
int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX* ctx,
const unsigned char* in, long sz, int format)
{
WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer_format");
return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 1);
}
int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx,
const unsigned char* in, long sz)
{
WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer");
return ProcessBuffer(ctx, in, sz, SSL_FILETYPE_PEM, CERT_TYPE, NULL,
NULL, 1);
return wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, in, sz,
SSL_FILETYPE_PEM);
}
@@ -11833,6 +11873,10 @@ WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl)
if (ssl->buffers.weOwnCert) {
if (ssl->ourCert == NULL) {
if (ssl->buffers.certificate == NULL) {
WOLFSSL_MSG("Certificate buffer not set!");
return NULL;
}
ssl->ourCert = wolfSSL_X509_d2i(NULL,
ssl->buffers.certificate->buffer,
ssl->buffers.certificate->length);
@@ -11842,17 +11886,20 @@ WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl)
else { /* if cert not owned get parent ctx cert or return null */
if (ssl->ctx) {
if (ssl->ctx->ourCert == NULL) {
if (ssl->ctx->certificate == NULL) {
WOLFSSL_MSG("Ctx Certificate buffer not set!");
return NULL;
}
ssl->ctx->ourCert = wolfSSL_X509_d2i(NULL,
ssl->ctx->certificate->buffer,
ssl->ctx->certificate->length);
}
return ssl->ctx->ourCert;
}
else {
}
return NULL;
}
}
}
#endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */
#endif /* NO_CERTS */

View File

@@ -2905,6 +2905,9 @@ typedef struct EncryptedInfo {
DerBuffer** pDer, void* heap, EncryptedInfo* info,
int* eccKey);
WOLFSSL_LOCAL int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
long sz, int format, int type, WOLFSSL* ssl,
long* used, int userChain);
WOLFSSL_LOCAL int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format,
int type, WOLFSSL* ssl, int userChain,
WOLFSSL_CRL* crl);

View File

@@ -1090,6 +1090,8 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL*, void* key, unsigned int len,
const unsigned char*, long, int);
WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX*,
const unsigned char*, long, int);
WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX*,
const unsigned char*, long, int);
WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX*,
const unsigned char*, long);