First pass at changes to move PemToDer into asn.c.

pull/1467/head
David Garske 2018-03-27 16:11:31 -07:00
parent 2ded38ec2b
commit f9e830bce7
11 changed files with 593 additions and 590 deletions

View File

@ -14974,9 +14974,6 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case SUITES_ERROR:
return "Suites Pointer Error";
case SSL_NO_PEM_HEADER:
return "No PEM Header Error";
case OUT_OF_ORDER_E:
return "Out of order message, fatal";

533
src/ssl.c
View File

@ -2931,59 +2931,6 @@ int wolfSSL_GetHmacSize(WOLFSSL* ssl)
#endif /* ATOMIC_USER */
#ifndef NO_CERTS
int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap)
{
int ret = BAD_FUNC_ARG;
if (pDer) {
int dynType = 0;
DerBuffer* der;
/* Determine dynamic type */
switch (type) {
case CA_TYPE: dynType = DYNAMIC_TYPE_CA; break;
case CERT_TYPE: dynType = DYNAMIC_TYPE_CERT; break;
case CRL_TYPE: dynType = DYNAMIC_TYPE_CRL; break;
case DSA_TYPE: dynType = DYNAMIC_TYPE_DSA; break;
case ECC_TYPE: dynType = DYNAMIC_TYPE_ECC; break;
case RSA_TYPE: dynType = DYNAMIC_TYPE_RSA; break;
default: dynType = DYNAMIC_TYPE_KEY; break;
}
/* Setup new buffer */
*pDer = (DerBuffer*)XMALLOC(sizeof(DerBuffer) + length, heap, dynType);
if (*pDer == NULL) {
return MEMORY_ERROR;
}
XMEMSET(*pDer, 0, sizeof(DerBuffer) + length);
der = *pDer;
der->type = type;
der->dynType = dynType; /* Cache this for FreeDer */
der->heap = heap;
der->buffer = (byte*)der + sizeof(DerBuffer);
der->length = length;
ret = 0; /* Success */
}
return ret;
}
void FreeDer(DerBuffer** pDer)
{
if (pDer && *pDer)
{
DerBuffer* der = (DerBuffer*)*pDer;
/* ForceZero private keys */
if (der->type == PRIVATEKEY_TYPE) {
ForceZero(der->buffer, der->length);
}
der->buffer = NULL;
der->length = 0;
XFREE(der, der->heap, der->dynType);
*pDer = NULL;
}
}
WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX* ctx)
{
@ -4645,318 +4592,6 @@ static int wolfssl_encrypt_buffer_key(byte* der, word32 derSz, byte* password,
#ifndef NO_CERTS
/* Remove PEM header/footer, convert to ASN1, store any encrypted data
info->consumed tracks of PEM bytes consumed in case multiple parts */
int PemToDer(const unsigned char* buff, long longSz, int type,
DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey)
{
const char* header = NULL;
const char* footer = NULL;
char* headerEnd;
char* footerEnd;
char* consumedEnd;
char* bufferEnd = (char*)(buff + longSz);
long neededSz;
int ret = 0;
int sz = (int)longSz;
int encrypted_key = 0;
DerBuffer* der;
WOLFSSL_ENTER("PemToDer");
switch (type) {
case CA_TYPE: /* same as below */
case TRUSTED_PEER_TYPE:
case CERT_TYPE: header=BEGIN_CERT; footer=END_CERT;
break;
case CRL_TYPE: header=BEGIN_X509_CRL; footer=END_X509_CRL;
break;
#ifndef NO_DH
case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM;
break;
#endif
#ifndef NO_DSA
case DSA_PARAM_TYPE: header=BEGIN_DSA_PARAM; footer=END_DSA_PARAM;
break;
#endif
#ifdef WOLFSSL_CERT_REQ
case CERTREQ_TYPE: header=BEGIN_CERT_REQ; footer=END_CERT_REQ;
break;
#endif
#ifndef NO_DSA
case DSA_TYPE: header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV;
break;
#endif
#ifdef HAVE_ECC
case ECC_TYPE: header=BEGIN_EC_PRIV; footer=END_EC_PRIV;
break;
#endif
case RSA_TYPE: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV;
break;
#ifdef HAVE_ED25519
case ED25519_TYPE: header=BEGIN_EDDSA_PRIV; footer=END_EDDSA_PRIV;
break;
#endif
case PUBLICKEY_TYPE: header=BEGIN_PUB_KEY; footer=END_PUB_KEY;
break;
default: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV;
break;
}
/* find header */
for (;;) {
headerEnd = XSTRNSTR((char*)buff, header, sz);
if (headerEnd || type != PRIVATEKEY_TYPE) {
break;
} else
if (header == BEGIN_RSA_PRIV) {
header = BEGIN_PRIV_KEY; footer = END_PRIV_KEY;
} else
if (header == BEGIN_PRIV_KEY) {
header = BEGIN_ENC_PRIV_KEY; footer = END_ENC_PRIV_KEY;
} else
#ifdef HAVE_ECC
if (header == BEGIN_ENC_PRIV_KEY) {
header = BEGIN_EC_PRIV; footer = END_EC_PRIV;
} else
if (header == BEGIN_EC_PRIV) {
header = BEGIN_DSA_PRIV; footer = END_DSA_PRIV;
} else
#endif
#ifdef HAVE_ED25519
#ifdef HAVE_ECC
if (header == BEGIN_DSA_PRIV)
#else
if (header == BEGIN_ENC_PRIV_KEY)
#endif
{
header = BEGIN_EDDSA_PRIV; footer = END_EDDSA_PRIV;
} else
#endif
{
break;
}
}
if (!headerEnd) {
WOLFSSL_MSG("Couldn't find PEM header");
return SSL_NO_PEM_HEADER;
}
headerEnd += XSTRLEN(header);
if ((headerEnd + 1) >= bufferEnd)
return WOLFSSL_BAD_FILE;
/* eat end of line */
if (headerEnd[0] == '\n')
headerEnd++;
else if (headerEnd[1] == '\n')
headerEnd += 2;
else {
if (info)
info->consumed = (long)(headerEnd+2 - (char*)buff);
return WOLFSSL_BAD_FILE;
}
if (type == PRIVATEKEY_TYPE) {
if (eccKey) {
#ifdef HAVE_ECC
*eccKey = header == BEGIN_EC_PRIV;
#else
*eccKey = 0;
#endif
}
}
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
defined(HAVE_WEBSERVER)
{
/* remove encrypted header if there */
const char* const encHeader = "Proc-Type";
word32 headerEndSz = (word32)(bufferEnd - headerEnd);
char* line = XSTRNSTR(headerEnd, encHeader, min(headerEndSz,
PEM_LINE_LEN));
if (line != NULL) {
word32 lineSz;
char* finish;
word32 finishSz;
char* start = NULL;
word32 startSz;
char* newline;
if (line >= bufferEnd) {
return WOLFSSL_BAD_FILE;
}
lineSz = (word32)(bufferEnd - line);
#ifndef NO_DES3
start = XSTRNSTR(line, "DES", min(lineSz, PEM_LINE_LEN));
#endif
#ifndef NO_AES
if (start == NULL) {
start = XSTRNSTR(line, "AES", min(lineSz, PEM_LINE_LEN));
}
#endif
(void)lineSz;
if (start == NULL) return WOLFSSL_BAD_FILE;
if (info == NULL) return WOLFSSL_BAD_FILE;
if (start >= bufferEnd) {
return WOLFSSL_BAD_FILE;
}
startSz = (word32)(bufferEnd - start);
finish = XSTRNSTR(start, ",", min(startSz, PEM_LINE_LEN));
if ((start != NULL) && (finish != NULL) && (start < finish)) {
if (finish >= bufferEnd) {
return WOLFSSL_BAD_FILE;
}
finishSz = (word32)(bufferEnd - finish);
newline = XSTRNSTR(finish, "\r", min(finishSz, PEM_LINE_LEN));
if (NAME_SZ < (finish - start)) /* buffer size of info->name*/
return BUFFER_E;
if (XMEMCPY(info->name, start, finish - start) == NULL)
return WOLFSSL_FATAL_ERROR;
info->name[finish - start] = 0;
if (finishSz < sizeof(info->iv) + 1)
return BUFFER_E;
if (XMEMCPY(info->iv, finish + 1, sizeof(info->iv)) == NULL)
return WOLFSSL_FATAL_ERROR;
if (newline == NULL)
newline = XSTRNSTR(finish, "\n", min(finishSz,
PEM_LINE_LEN));
if ((newline != NULL) && (newline > finish)) {
info->ivSz = (word32)(newline - (finish + 1));
info->set = 1;
}
else
return WOLFSSL_BAD_FILE;
}
else
return WOLFSSL_BAD_FILE;
/* eat blank line */
while (newline < bufferEnd &&
(*newline == '\r' || *newline == '\n'))
newline++;
headerEnd = newline;
encrypted_key = 1;
}
}
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || HAVE_WEBSERVER */
/* find footer */
footerEnd = XSTRNSTR((char*)buff, footer, sz);
if (!footerEnd) {
if (info)
info->consumed = longSz; /* No more certs if no footer */
return WOLFSSL_BAD_FILE;
}
consumedEnd = footerEnd + XSTRLEN(footer);
if (consumedEnd < bufferEnd) { /* handle no end of line on last line */
/* eat end of line */
if (consumedEnd[0] == '\n')
consumedEnd++;
else if ((consumedEnd + 1 < bufferEnd) && consumedEnd[1] == '\n')
consumedEnd += 2;
else {
if (info)
info->consumed = (long)(consumedEnd+2 - (char*)buff);
return WOLFSSL_BAD_FILE;
}
}
if (info)
info->consumed = (long)(consumedEnd - (char*)buff);
/* set up der buffer */
neededSz = (long)(footerEnd - headerEnd);
if (neededSz > sz || neededSz <= 0)
return WOLFSSL_BAD_FILE;
ret = AllocDer(pDer, (word32)neededSz, type, heap);
if (ret < 0) {
return ret;
}
der = *pDer;
if (Base64_Decode((byte*)headerEnd, (word32)neededSz,
der->buffer, &der->length) < 0)
return WOLFSSL_BAD_FILE;
if (header == BEGIN_PRIV_KEY && !encrypted_key) {
/* pkcs8 key, convert and adjust length */
if ((ret = ToTraditional(der->buffer, der->length)) < 0)
return ret;
der->length = ret;
return 0;
}
#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
defined(HAVE_WEBSERVER)) && !defined(NO_PWDBASED)
if (encrypted_key || header == BEGIN_ENC_PRIV_KEY) {
int passwordSz;
#ifdef WOLFSSL_SMALL_STACK
char* password = NULL;
#else
char password[NAME_SZ];
#endif
if (!info || !info->ctx || !info->ctx->passwd_cb)
return WOLFSSL_BAD_FILE; /* no callback error */
#ifdef WOLFSSL_SMALL_STACK
password = (char*)XMALLOC(NAME_SZ, heap, DYNAMIC_TYPE_STRING);
if (password == NULL)
return MEMORY_E;
#endif
passwordSz = info->ctx->passwd_cb(password, NAME_SZ, 0,
info->ctx->userdata);
/* convert and adjust length */
if (header == BEGIN_ENC_PRIV_KEY) {
ret = ToTraditionalEnc(der->buffer, der->length,
password, passwordSz);
#ifdef WOLFSSL_SMALL_STACK
XFREE(password, NULL, DYNAMIC_TYPE_STRING);
#endif
if (ret < 0) {
return ret;
}
der->length = ret;
}
/* decrypt the key */
else {
ret = wolfssl_decrypt_buffer_key(der, (byte*)password,
passwordSz, info);
#ifdef WOLFSSL_SMALL_STACK
XFREE(password, heap, DYNAMIC_TYPE_STRING);
#endif
if (ret != WOLFSSL_SUCCESS) {
return ret;
}
}
}
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || HAVE_WEBSERVER ||
NO_PWDBASED */
return 0;
}
/* 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,
@ -5010,7 +4645,7 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff,
/* get length of der (read sequence) */
word32 inOutIdx = 0;
if (GetSequence(buff + consumed, &inOutIdx, &length, remain) < 0) {
ret = SSL_NO_PEM_HEADER;
ret = ASN_NO_PEM_HEADER;
}
length += inOutIdx; /* include leading squence */
}
@ -5043,7 +4678,7 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff,
}
FreeDer(&part);
if (ret == SSL_NO_PEM_HEADER && gotOne) {
if (ret == ASN_NO_PEM_HEADER && gotOne) {
WOLFSSL_MSG("We got one good cert, so stuff at end ok");
break;
}
@ -6789,162 +6424,6 @@ int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
#endif /* WOLFSSL_DER_LOAD */
#ifdef WOLFSSL_CERT_GEN
/* load pem cert from file into der buffer, return der size or error */
int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz)
{
#ifdef WOLFSSL_SMALL_STACK
EncryptedInfo* info = NULL;
byte staticBuffer[1]; /* force XMALLOC */
#else
EncryptedInfo info[1];
byte staticBuffer[FILE_BUFFER_SIZE];
#endif
byte* fileBuf = staticBuffer;
int dynamic = 0;
int ret = 0;
int ecc = 0;
long sz = 0;
XFILE file = XFOPEN(fileName, "rb");
DerBuffer* converted = NULL;
WOLFSSL_ENTER("wolfSSL_PemCertToDer");
if (file == XBADFILE) {
ret = WOLFSSL_BAD_FILE;
}
else {
XFSEEK(file, 0, XSEEK_END);
sz = XFTELL(file);
XREWIND(file);
if (sz <= 0) {
ret = WOLFSSL_BAD_FILE;
}
else if (sz > (long)sizeof(staticBuffer)) {
#ifdef WOLFSSL_STATIC_MEMORY
WOLFSSL_MSG("File was larger then static buffer");
return MEMORY_E;
#endif
fileBuf = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_FILE);
if (fileBuf == NULL)
ret = MEMORY_E;
else
dynamic = 1;
}
if (ret == 0) {
if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) {
ret = WOLFSSL_BAD_FILE;
}
else {
#ifdef WOLFSSL_SMALL_STACK
info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
DYNAMIC_TYPE_ENCRYPTEDINFO);
if (info == NULL)
ret = MEMORY_E;
else
#endif
{
ret = PemToDer(fileBuf, sz, CA_TYPE, &converted,
0, info, &ecc);
#ifdef WOLFSSL_SMALL_STACK
XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
#endif
}
}
if (ret == 0) {
if (converted->length < (word32)derSz) {
XMEMCPY(derBuf, converted->buffer, converted->length);
ret = converted->length;
}
else
ret = BUFFER_E;
}
FreeDer(&converted);
}
XFCLOSE(file);
if (dynamic)
XFREE(fileBuf, 0, DYNAMIC_TYPE_FILE);
}
return ret;
}
#endif /* WOLFSSL_CERT_GEN */
#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
/* load pem public key from file into der buffer, return der size or error */
int wolfSSL_PemPubKeyToDer(const char* fileName,
unsigned char* derBuf, int derSz)
{
#ifdef WOLFSSL_SMALL_STACK
byte staticBuffer[1]; /* force XMALLOC */
#else
byte staticBuffer[FILE_BUFFER_SIZE];
#endif
byte* fileBuf = staticBuffer;
int dynamic = 0;
int ret = 0;
long sz = 0;
XFILE file = XFOPEN(fileName, "rb");
DerBuffer* converted = NULL;
WOLFSSL_ENTER("wolfSSL_PemPubKeyToDer");
if (file == XBADFILE) {
ret = WOLFSSL_BAD_FILE;
}
else {
XFSEEK(file, 0, XSEEK_END);
sz = XFTELL(file);
XREWIND(file);
if (sz <= 0) {
ret = WOLFSSL_BAD_FILE;
}
else if (sz > (long)sizeof(staticBuffer)) {
#ifdef WOLFSSL_STATIC_MEMORY
WOLFSSL_MSG("File was larger then static buffer");
return MEMORY_E;
#endif
fileBuf = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_FILE);
if (fileBuf == NULL)
ret = MEMORY_E;
else
dynamic = 1;
}
if (ret == 0) {
if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz)
ret = WOLFSSL_BAD_FILE;
else
ret = PemToDer(fileBuf, sz, PUBLICKEY_TYPE, &converted,
0, NULL, NULL);
if (ret == 0) {
if (converted->length < (word32)derSz) {
XMEMCPY(derBuf, converted->buffer, converted->length);
ret = converted->length;
}
else
ret = BUFFER_E;
}
FreeDer(&converted);
}
XFCLOSE(file);
if (dynamic)
XFREE(fileBuf, 0, DYNAMIC_TYPE_FILE);
}
return ret;
}
#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */
int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
int format)
@ -29221,7 +28700,7 @@ void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl)
}
#ifdef WOLFSSL_NGINX
if (l == 0)
WOLFSSL_ERROR(SSL_NO_PEM_HEADER);
WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
#endif
pemSz = (int)i;
x509 = wolfSSL_X509_load_certificate_buffer(pem, pemSz,
@ -30518,7 +29997,7 @@ unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line)
return 0;
}
#ifdef WOLFSSL_NGINX
if (ret == -SSL_NO_PEM_HEADER)
if (ret == -ASN_NO_PEM_HEADER)
return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
#endif
return (unsigned long)ret;
@ -31356,7 +30835,7 @@ unsigned long wolfSSL_ERR_peek_last_error(void)
WOLFSSL_MSG("Issue peeking at error node in queue");
return 0;
}
if (ret == -SSL_NO_PEM_HEADER)
if (ret == -ASN_NO_PEM_HEADER)
return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
return (unsigned long)ret;
}
@ -32093,7 +31572,7 @@ unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line,
}
ret = -ret;
if (ret == SSL_NO_PEM_HEADER)
if (ret == ASN_NO_PEM_HEADER)
return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
if (ret != WANT_READ && ret != WANT_WRITE &&
ret != ZERO_RETURN && ret != WOLFSSL_ERROR_ZERO_RETURN &&

View File

@ -7546,6 +7546,531 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz,
#endif /* WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN || OPENSSL_EXTRA */
int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap)
{
int ret = BAD_FUNC_ARG;
if (pDer) {
int dynType = 0;
DerBuffer* der;
/* Determine dynamic type */
switch (type) {
case CA_TYPE: dynType = DYNAMIC_TYPE_CA; break;
case CERT_TYPE: dynType = DYNAMIC_TYPE_CERT; break;
case CRL_TYPE: dynType = DYNAMIC_TYPE_CRL; break;
case DSA_TYPE: dynType = DYNAMIC_TYPE_DSA; break;
case ECC_TYPE: dynType = DYNAMIC_TYPE_ECC; break;
case RSA_TYPE: dynType = DYNAMIC_TYPE_RSA; break;
default: dynType = DYNAMIC_TYPE_KEY; break;
}
/* Setup new buffer */
*pDer = (DerBuffer*)XMALLOC(sizeof(DerBuffer) + length, heap, dynType);
if (*pDer == NULL) {
return MEMORY_E;
}
XMEMSET(*pDer, 0, sizeof(DerBuffer) + length);
der = *pDer;
der->type = type;
der->dynType = dynType; /* Cache this for FreeDer */
der->heap = heap;
der->buffer = (byte*)der + sizeof(DerBuffer);
der->length = length;
ret = 0; /* Success */
}
return ret;
}
void FreeDer(DerBuffer** pDer)
{
if (pDer && *pDer)
{
DerBuffer* der = (DerBuffer*)*pDer;
/* ForceZero private keys */
if (der->type == PRIVATEKEY_TYPE) {
ForceZero(der->buffer, der->length);
}
der->buffer = NULL;
der->length = 0;
XFREE(der, der->heap, der->dynType);
*pDer = NULL;
}
}
/* Remove PEM header/footer, convert to ASN1, store any encrypted data
info->consumed tracks of PEM bytes consumed in case multiple parts */
int PemToDer(const unsigned char* buff, long longSz, int type,
DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey)
{
const char* header = NULL;
const char* footer = NULL;
char* headerEnd;
char* footerEnd;
char* consumedEnd;
char* bufferEnd = (char*)(buff + longSz);
long neededSz;
int ret = 0;
int sz = (int)longSz;
int encrypted_key = 0;
DerBuffer* der;
WOLFSSL_ENTER("PemToDer");
switch (type) {
case CA_TYPE: /* same as below */
case TRUSTED_PEER_TYPE:
case CERT_TYPE: header=BEGIN_CERT; footer=END_CERT;
break;
case CRL_TYPE: header=BEGIN_X509_CRL; footer=END_X509_CRL;
break;
#ifndef NO_DH
case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM;
break;
#endif
#ifndef NO_DSA
case DSA_PARAM_TYPE: header=BEGIN_DSA_PARAM; footer=END_DSA_PARAM;
break;
#endif
#ifdef WOLFSSL_CERT_REQ
case CERTREQ_TYPE: header=BEGIN_CERT_REQ; footer=END_CERT_REQ;
break;
#endif
#ifndef NO_DSA
case DSA_TYPE: header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV;
break;
#endif
#ifdef HAVE_ECC
case ECC_TYPE: header=BEGIN_EC_PRIV; footer=END_EC_PRIV;
break;
#endif
case RSA_TYPE: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV;
break;
#ifdef HAVE_ED25519
case ED25519_TYPE: header=BEGIN_EDDSA_PRIV; footer=END_EDDSA_PRIV;
break;
#endif
case PUBLICKEY_TYPE: header=BEGIN_PUB_KEY; footer=END_PUB_KEY;
break;
default: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV;
break;
}
/* find header */
for (;;) {
headerEnd = XSTRNSTR((char*)buff, header, sz);
if (headerEnd || type != PRIVATEKEY_TYPE) {
break;
} else
if (header == BEGIN_RSA_PRIV) {
header = BEGIN_PRIV_KEY; footer = END_PRIV_KEY;
} else
if (header == BEGIN_PRIV_KEY) {
header = BEGIN_ENC_PRIV_KEY; footer = END_ENC_PRIV_KEY;
} else
#ifdef HAVE_ECC
if (header == BEGIN_ENC_PRIV_KEY) {
header = BEGIN_EC_PRIV; footer = END_EC_PRIV;
} else
if (header == BEGIN_EC_PRIV) {
header = BEGIN_DSA_PRIV; footer = END_DSA_PRIV;
} else
#endif
#ifdef HAVE_ED25519
if (header == BEGIN_DSA_PRIV) {
header = BEGIN_EDDSA_PRIV; footer = END_EDDSA_PRIV;
} else
#endif
{
break;
}
}
if (!headerEnd) {
WOLFSSL_MSG("Couldn't find PEM header");
return ASN_NO_PEM_HEADER;
}
headerEnd += XSTRLEN(header);
if ((headerEnd + 1) >= bufferEnd)
return BUFFER_E;
/* eat end of line */
if (headerEnd[0] == '\n')
headerEnd++;
else if (headerEnd[1] == '\n')
headerEnd += 2;
else {
if (info)
info->consumed = (long)(headerEnd+2 - (char*)buff);
return BUFFER_E;
}
if (type == PRIVATEKEY_TYPE) {
if (eccKey) {
#ifdef HAVE_ECC
*eccKey = header == BEGIN_EC_PRIV;
#else
*eccKey = 0;
#endif
}
}
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
defined(HAVE_WEBSERVER)
{
/* remove encrypted header if there */
const char* const encHeader = "Proc-Type";
word32 headerEndSz = (word32)(bufferEnd - headerEnd);
char* line = XSTRNSTR(headerEnd, encHeader, min(headerEndSz,
PEM_LINE_LEN));
if (line != NULL) {
word32 lineSz;
char* finish;
word32 finishSz;
char* start = NULL;
word32 startSz;
char* newline;
if (line >= bufferEnd) {
return BUFFER_E;
}
lineSz = (word32)(bufferEnd - line);
#ifndef NO_DES3
start = XSTRNSTR(line, "DES", min(lineSz, PEM_LINE_LEN));
#endif
#ifndef NO_AES
if (start == NULL) {
start = XSTRNSTR(line, "AES", min(lineSz, PEM_LINE_LEN));
}
#endif
(void)lineSz;
if (start == NULL) return BUFFER_E;
if (info == NULL) return BUFFER_E;
if (start >= bufferEnd) {
return BUFFER_E;
}
startSz = (word32)(bufferEnd - start);
finish = XSTRNSTR(start, ",", min(startSz, PEM_LINE_LEN));
if ((start != NULL) && (finish != NULL) && (start < finish)) {
if (finish >= bufferEnd) {
return BUFFER_E;
}
finishSz = (word32)(bufferEnd - finish);
newline = XSTRNSTR(finish, "\r", min(finishSz, PEM_LINE_LEN));
if (NAME_SZ < (finish - start)) /* buffer size of info->name*/
return BUFFER_E;
if (XMEMCPY(info->name, start, finish - start) == NULL)
return WOLFSSL_FATAL_ERROR;
info->name[finish - start] = 0;
if (finishSz < sizeof(info->iv) + 1)
return BUFFER_E;
if (XMEMCPY(info->iv, finish + 1, sizeof(info->iv)) == NULL)
return WOLFSSL_FATAL_ERROR;
if (newline == NULL)
newline = XSTRNSTR(finish, "\n", min(finishSz,
PEM_LINE_LEN));
if ((newline != NULL) && (newline > finish)) {
info->ivSz = (word32)(newline - (finish + 1));
info->set = 1;
}
else
return BUFFER_E;
}
else
return BUFFER_E;
/* eat blank line */
while (newline < bufferEnd &&
(*newline == '\r' || *newline == '\n'))
newline++;
headerEnd = newline;
encrypted_key = 1;
}
}
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || HAVE_WEBSERVER */
/* find footer */
footerEnd = XSTRNSTR((char*)buff, footer, sz);
if (!footerEnd) {
if (info)
info->consumed = longSz; /* No more certs if no footer */
return BUFFER_E;
}
consumedEnd = footerEnd + XSTRLEN(footer);
if (consumedEnd < bufferEnd) { /* handle no end of line on last line */
/* eat end of line */
if (consumedEnd[0] == '\n')
consumedEnd++;
else if ((consumedEnd + 1 < bufferEnd) && consumedEnd[1] == '\n')
consumedEnd += 2;
else {
if (info)
info->consumed = (long)(consumedEnd+2 - (char*)buff);
return BUFFER_E;
}
}
if (info)
info->consumed = (long)(consumedEnd - (char*)buff);
/* set up der buffer */
neededSz = (long)(footerEnd - headerEnd);
if (neededSz > sz || neededSz <= 0)
return BUFFER_E;
ret = AllocDer(pDer, (word32)neededSz, type, heap);
if (ret < 0) {
return ret;
}
der = *pDer;
if (Base64_Decode((byte*)headerEnd, (word32)neededSz,
der->buffer, &der->length) < 0)
return BUFFER_E;
if (header == BEGIN_PRIV_KEY && !encrypted_key) {
/* pkcs8 key, convert and adjust length */
if ((ret = ToTraditional(der->buffer, der->length)) < 0)
return ret;
der->length = ret;
return 0;
}
#if (defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)) && !defined(NO_PWDBASED)
if (encrypted_key || header == BEGIN_ENC_PRIV_KEY) {
int passwordSz;
#ifdef WOLFSSL_SMALL_STACK
char* password = NULL;
#else
char password[NAME_SZ];
#endif
if (!info || !info->ctx || !info->ctx->passwd_cb)
return BUFFER_E; /* no callback error */
#ifdef WOLFSSL_SMALL_STACK
password = (char*)XMALLOC(NAME_SZ, heap, DYNAMIC_TYPE_STRING);
if (password == NULL)
return MEMORY_E;
#endif
passwordSz = info->ctx->passwd_cb(password, NAME_SZ, 0,
info->ctx->userdata);
/* convert and adjust length */
if (header == BEGIN_ENC_PRIV_KEY) {
ret = ToTraditionalEnc(der->buffer, der->length,
password, passwordSz);
#ifdef WOLFSSL_SMALL_STACK
XFREE(password, NULL, DYNAMIC_TYPE_STRING);
#endif
if (ret < 0) {
return ret;
}
der->length = ret;
}
/* decrypt the key */
else {
ret = wolfssl_decrypt_buffer_key(der, (byte*)password,
passwordSz, info);
#ifdef WOLFSSL_SMALL_STACK
XFREE(password, heap, DYNAMIC_TYPE_STRING);
#endif
if (ret != WOLFSSL_SUCCESS) {
return ret;
}
}
}
#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER || NO_PWDBASED */
return 0;
}
int wc_PemToDer(const unsigned char* buff, long longSz, int type,
DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey)
{
return PemToDer(buff, longSz, type, pDer, heap, info, eccKey);
}
#ifndef NO_FILESYSTEM
#ifdef WOLFSSL_CERT_GEN
/* load pem cert from file into der buffer, return der size or error */
int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz)
{
#ifdef WOLFSSL_SMALL_STACK
EncryptedInfo* info = NULL;
byte staticBuffer[1]; /* force XMALLOC */
#else
EncryptedInfo info[1];
byte staticBuffer[FILE_BUFFER_SIZE];
#endif
byte* fileBuf = staticBuffer;
int dynamic = 0;
int ret = 0;
int ecc = 0;
long sz = 0;
XFILE file = XFOPEN(fileName, "rb");
DerBuffer* converted = NULL;
WOLFSSL_ENTER("wolfSSL_PemCertToDer");
if (file == XBADFILE) {
ret = BUFFER_E;
}
else {
XFSEEK(file, 0, XSEEK_END);
sz = XFTELL(file);
XREWIND(file);
if (sz <= 0) {
ret = BUFFER_E;
}
else if (sz > (long)sizeof(staticBuffer)) {
#ifdef WOLFSSL_STATIC_MEMORY
WOLFSSL_MSG("File was larger then static buffer");
return MEMORY_E;
#endif
fileBuf = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_FILE);
if (fileBuf == NULL)
ret = MEMORY_E;
else
dynamic = 1;
}
if (ret == 0) {
if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) {
ret = BUFFER_E;
}
else {
#ifdef WOLFSSL_SMALL_STACK
info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
DYNAMIC_TYPE_ENCRYPTEDINFO);
if (info == NULL)
ret = MEMORY_E;
else
#endif
{
ret = PemToDer(fileBuf, sz, CA_TYPE, &converted,
0, info, &ecc);
#ifdef WOLFSSL_SMALL_STACK
XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
#endif
}
}
if (ret == 0) {
if (converted->length < (word32)derSz) {
XMEMCPY(derBuf, converted->buffer, converted->length);
ret = converted->length;
}
else
ret = BUFFER_E;
}
FreeDer(&converted);
}
XFCLOSE(file);
if (dynamic)
XFREE(fileBuf, 0, DYNAMIC_TYPE_FILE);
}
return ret;
}
#endif /* WOLFSSL_CERT_GEN */
#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
/* load pem public key from file into der buffer, return der size or error */
int wolfSSL_PemPubKeyToDer(const char* fileName,
unsigned char* derBuf, int derSz)
{
#ifdef WOLFSSL_SMALL_STACK
byte staticBuffer[1]; /* force XMALLOC */
#else
byte staticBuffer[FILE_BUFFER_SIZE];
#endif
byte* fileBuf = staticBuffer;
int dynamic = 0;
int ret = 0;
long sz = 0;
XFILE file = XFOPEN(fileName, "rb");
DerBuffer* converted = NULL;
WOLFSSL_ENTER("wolfSSL_PemPubKeyToDer");
if (file == XBADFILE) {
ret = BUFFER_E;
}
else {
XFSEEK(file, 0, XSEEK_END);
sz = XFTELL(file);
XREWIND(file);
if (sz <= 0) {
ret = BUFFER_E;
}
else if (sz > (long)sizeof(staticBuffer)) {
#ifdef WOLFSSL_STATIC_MEMORY
WOLFSSL_MSG("File was larger then static buffer");
return MEMORY_E;
#endif
fileBuf = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_FILE);
if (fileBuf == NULL)
ret = MEMORY_E;
else
dynamic = 1;
}
if (ret == 0) {
if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz)
ret = BUFFER_E;
else
ret = PemToDer(fileBuf, sz, PUBLICKEY_TYPE, &converted,
0, NULL, NULL);
if (ret == 0) {
if (converted->length < (word32)derSz) {
XMEMCPY(derBuf, converted->buffer, converted->length);
ret = converted->length;
}
else
ret = BUFFER_E;
}
FreeDer(&converted);
}
XFCLOSE(file);
if (dynamic)
XFREE(fileBuf, 0, DYNAMIC_TYPE_FILE);
}
return ret;
}
#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */
#endif /* !NO_FILESYSTEM */
#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || \
(defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA)))
/* USER RSA ifdef portions used instead of refactor in consideration for

View File

@ -263,6 +263,9 @@ const char* wc_GetErrorString(int error)
case ASN_OCSP_CONFIRM_E :
return "ASN OCSP sig error, confirm failure";
case ASN_NO_PEM_HEADER:
return "ASN no PEM Header Error";
case BAD_STATE_E:
return "Bad state operation";

View File

@ -1090,7 +1090,7 @@ int error_test(void)
int j = 0;
/* Values that are not or no longer error codes. */
int missing[] = { -122, -123, -124, -127, -128, -129,
-162, -163, -164, -165, -166, -167, -168, -169,
-163, -164, -165, -166, -167, -168, -169,
-179, -233,
0 };

View File

@ -104,7 +104,7 @@ enum wolfSSL_ErrorCodes {
COOKIE_ERROR = -369, /* dtls cookie error */
SEQUENCE_ERROR = -370, /* dtls sequence error */
SUITES_ERROR = -371, /* suites pointer error */
SSL_NO_PEM_HEADER = -372, /* no PEM header found */
OUT_OF_ORDER_E = -373, /* out of order message */
BAD_KEA_TYPE_E = -374, /* bad KEA type found */
SANITY_CIPHER_E = -375, /* sanity check on cipher error */

View File

@ -1521,17 +1521,6 @@ WOLFSSL_LOCAL int DoTls13ServerHello(WOLFSSL* ssl, const byte* input,
word32* inOutIdx, word32 helloSz);
#endif
#ifndef NO_CERTS
/* wolfSSL DER buffer */
typedef struct DerBuffer {
byte* buffer;
void* heap;
word32 length;
int type; /* enum CertType */
int dynType; /* DYNAMIC_TYPE_* */
} DerBuffer;
#endif /* !NO_CERTS */
enum {
FORCED_FREE = 1,
@ -3665,31 +3654,9 @@ void FreeSSL(WOLFSSL*, void* heap);
WOLFSSL_API void SSL_ResourceFree(WOLFSSL*); /* Micrium uses */
enum {
IV_SZ = 32, /* max iv sz */
NAME_SZ = 80 /* max one line */
};
typedef struct EncryptedInfo {
char name[NAME_SZ]; /* encryption name */
byte iv[IV_SZ]; /* encrypted IV */
word32 ivSz; /* encrypted IV size */
long consumed; /* tracks PEM bytes consumed */
byte set; /* if encryption set */
WOLFSSL_CTX* ctx; /* CTX owner */
} EncryptedInfo;
#ifndef NO_CERTS
WOLFSSL_LOCAL int AllocDer(DerBuffer** der, word32 length, int type, void* heap);
WOLFSSL_LOCAL void FreeDer(DerBuffer** der);
WOLFSSL_LOCAL int PemToDer(const unsigned char* buff, long sz, int type,
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);

View File

@ -514,11 +514,6 @@ WOLFSSL_API int wolfSSL_use_RSAPrivateKey_file(WOLFSSL*, const char*, int);
/* load NTRU private key blob */
#endif
#ifndef WOLFSSL_PEMCERT_TODER_DEFINED
WOLFSSL_API int wolfSSL_PemCertToDer(const char*, unsigned char*, int);
#define WOLFSSL_PEMCERT_TODER_DEFINED
#endif
#endif /* !NO_FILESYSTEM && !NO_CERTS */
WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD*);
@ -1710,17 +1705,6 @@ WOLFSSL_API int wolfSSL_KeyPemToDer(const unsigned char*, int,
unsigned char*, int, const char*);
WOLFSSL_API int wolfSSL_CertPemToDer(const unsigned char*, int,
unsigned char*, int, int);
#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
#ifndef WOLFSSL_PEMPUBKEY_TODER_DEFINED
#ifndef NO_FILESYSTEM
WOLFSSL_API int wolfSSL_PemPubKeyToDer(const char* fileName,
unsigned char* derBuf, int derSz);
#endif
WOLFSSL_API int wolfSSL_PubKeyPemToDer(const unsigned char*, int,
unsigned char*, int);
#define WOLFSSL_PEMPUBKEY_TODER_DEFINED
#endif /* WOLFSSL_PEMPUBKEY_TODER_DEFINED */
#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER*/
typedef void (*CallbackCACache)(unsigned char* der, int sz, int type);
typedef void (*CbMissingCRL)(const char* url);

View File

@ -914,6 +914,15 @@ WOLFSSL_LOCAL int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der);
WOLFSSL_LOCAL void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId);
WOLFSSL_LOCAL void FreeSignatureCtx(SignatureCtx* sigCtx);
#ifndef NO_CERTS
WOLFSSL_LOCAL int PemToDer(const unsigned char* buff, long sz, int type,
DerBuffer** pDer, void* heap, EncryptedInfo* info,
int* eccKey);
WOLFSSL_LOCAL int AllocDer(DerBuffer** der, word32 length, int type, void* heap);
WOLFSSL_LOCAL void FreeDer(DerBuffer** der);
#endif /* !NO_CERTS */
#ifdef WOLFSSL_CERT_GEN
@ -928,15 +937,6 @@ enum cert_enums {
ED25519_KEY = 13
};
#ifndef WOLFSSL_PEMCERT_TODER_DEFINED
#ifndef NO_FILESYSTEM
/* forward from wolfSSL */
WOLFSSL_API
int wolfSSL_PemCertToDer(const char* fileName,unsigned char* derBuf,int derSz);
#define WOLFSSL_PEMCERT_TODER_DEFINED
#endif
#endif
#endif /* WOLFSSL_CERT_GEN */

View File

@ -50,6 +50,9 @@
#define WC_RNG_TYPE_DEFINED
#endif
struct WOLFSSL_CTX;
/* Certificate file Type */
enum CertType {
CERT_TYPE = 0,
@ -112,6 +115,29 @@ enum Ctc_Misc {
#endif /* WOLFSSL_CERT_EXT */
};
/* DER buffer */
typedef struct DerBuffer {
byte* buffer;
void* heap;
word32 length;
int type; /* enum CertType */
int dynType; /* DYNAMIC_TYPE_* */
} DerBuffer;
enum {
IV_SZ = 32, /* max iv sz */
NAME_SZ = 80 /* max one line */
};
typedef struct EncryptedInfo {
char name[NAME_SZ]; /* encryption name */
byte iv[IV_SZ]; /* encrypted IV */
word32 ivSz; /* encrypted IV size */
long consumed; /* tracks PEM bytes consumed */
byte set; /* if encryption set */
struct WOLFSSL_CTX* ctx; /* CTX owner */
} EncryptedInfo;
#ifdef WOLFSSL_CERT_GEN
@ -209,6 +235,7 @@ typedef struct Cert {
} Cert;
/* Initialize and Set Certificate defaults:
version = 3 (0x2)
serial = 0 (Will be randomly generated)
@ -299,6 +326,7 @@ WOLFSSL_API int wc_SetExtKeyUsageOID(Cert *cert, const char *oid, word32 sz,
#endif /* WOLFSSL_CERT_GEN */
#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
#ifndef WOLFSSL_PEMPUBKEY_TODER_DEFINED
#ifndef NO_FILESYSTEM
@ -322,6 +350,25 @@ WOLFSSL_API int wc_SetExtKeyUsageOID(Cert *cert, const char *oid, word32 sz,
word32 outputSz, byte *cipherIno, int type);
#endif
WOLFSSL_API int wc_PemToDer(const unsigned char* buff, long longSz, int type,
DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey);
#ifdef WOLFSSL_CERT_GEN
#ifndef NO_FILESYSTEM
WOLFSSL_API int wolfSSL_PemCertToDer(const char* fileName,
unsigned char* derBuf, int derSz);
#endif
#endif /* WOLFSSL_CERT_GEN */
#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
#ifndef NO_FILESYSTEM
WOLFSSL_API int wolfSSL_PemPubKeyToDer(const char* fileName,
unsigned char* derBuf, int derSz);
#endif
WOLFSSL_API int wolfSSL_PubKeyPemToDer(const unsigned char*, int,
unsigned char*, int);
#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */
#ifdef HAVE_ECC
/* private key helpers */
WOLFSSL_API int wc_EccPrivateKeyDecode(const byte*, word32*,

View File

@ -100,6 +100,7 @@ enum {
ASN_NTRU_KEY_E = -159, /* ASN ntru key decode error, invalid input */
ASN_CRIT_EXT_E = -160, /* ASN unsupported critical extension */
ASN_ALT_NAME_E = -161, /* ASN alternate name error */
ASN_NO_PEM_HEADER = -162, /* ASN no PEM header found */
ECC_BAD_ARG_E = -170, /* ECC input argument of wrong type */
ASN_ECC_KEY_E = -171, /* ASN ECC bad input */