mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-02 12:14:38 +02:00
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:
211
src/ssl.c
211
src/ssl.c
@@ -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 */
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user