forked from wolfSSL/wolfssl
ssl: refactoring PemToDer to reduce stack usage:
--- variable header moved to the heap (80 bytes saved) --- variable footer moved to the heap (80 bytes saved) --- variable password moved to the heap (80 bytes saved) fixes memory leak in CyaSSL_RAND_bytes
This commit is contained in:
173
src/ssl.c
173
src/ssl.c
@@ -1788,92 +1788,80 @@ int CyaSSL_Init(void)
|
|||||||
|
|
||||||
#ifndef NO_CERTS
|
#ifndef NO_CERTS
|
||||||
|
|
||||||
|
static const char* BEGIN_CERT = "-----BEGIN CERTIFICATE-----";
|
||||||
|
static const char* END_CERT = "-----END CERTIFICATE-----";
|
||||||
|
static const char* BEGIN_CERT_REQ = "-----BEGIN CERTIFICATE REQUEST-----";
|
||||||
|
static const char* END_CERT_REQ = "-----END CERTIFICATE REQUEST-----";
|
||||||
|
static const char* BEGIN_DH_PARAM = "-----BEGIN DH PARAMETERS-----";
|
||||||
|
static const char* END_DH_PARAM = "-----END DH PARAMETERS-----";
|
||||||
|
static const char* BEGIN_X509_CRL = "-----BEGIN X509 CRL-----";
|
||||||
|
static const char* END_X509_CRL = "-----END X509 CRL-----";
|
||||||
|
static const char* BEGIN_RSA_PRIV = "-----BEGIN RSA PRIVATE KEY-----";
|
||||||
|
static const char* END_RSA_PRIV = "-----END RSA PRIVATE KEY-----";
|
||||||
|
static const char* BEGIN_PRIV_KEY = "-----BEGIN PRIVATE KEY-----";
|
||||||
|
static const char* END_PRIV_KEY = "-----END PRIVATE KEY-----";
|
||||||
|
static const char* BEGIN_ENC_PRIV_KEY = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
|
||||||
|
static const char* END_ENC_PRIV_KEY = "-----END ENCRYPTED PRIVATE KEY-----";
|
||||||
|
static const char* BEGIN_EC_PRIV = "-----BEGIN EC PRIVATE KEY-----";
|
||||||
|
static const char* END_EC_PRIV = "-----END EC PRIVATE KEY-----";
|
||||||
|
static const char* BEGIN_DSA_PRIV = "-----BEGIN DSA PRIVATE KEY-----";
|
||||||
|
static const char* END_DSA_PRIV = "-----END DSA PRIVATE KEY-----";
|
||||||
|
|
||||||
/* Remove PEM header/footer, convert to ASN1, store any encrypted data
|
/* Remove PEM header/footer, convert to ASN1, store any encrypted data
|
||||||
info->consumed tracks of PEM bytes consumed in case multiple parts */
|
info->consumed tracks of PEM bytes consumed in case multiple parts */
|
||||||
int PemToDer(const unsigned char* buff, long longSz, int type,
|
int PemToDer(const unsigned char* buff, long longSz, int type,
|
||||||
buffer* der, void* heap, EncryptedInfo* info, int* eccKey)
|
buffer* der, void* heap, EncryptedInfo* info, int* eccKey)
|
||||||
{
|
{
|
||||||
char header[PEM_LINE_LEN];
|
const char* header = NULL;
|
||||||
char footer[PEM_LINE_LEN];
|
const char* footer = NULL;
|
||||||
char* headerEnd;
|
char* headerEnd;
|
||||||
char* footerEnd;
|
char* footerEnd;
|
||||||
char* consumedEnd;
|
char* consumedEnd;
|
||||||
char* bufferEnd = (char*)(buff + longSz);
|
char* bufferEnd = (char*)(buff + longSz);
|
||||||
long neededSz;
|
long neededSz;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int pkcs8 = 0;
|
|
||||||
int pkcs8Enc = 0;
|
|
||||||
int dynamicType = 0;
|
int dynamicType = 0;
|
||||||
int sz = (int)longSz;
|
int sz = (int)longSz;
|
||||||
|
|
||||||
(void)heap;
|
switch (type) {
|
||||||
(void)dynamicType;
|
case CA_TYPE: /* same as below */
|
||||||
|
case CERT_TYPE: header= BEGIN_CERT; footer= END_CERT; break;
|
||||||
|
case CRL_TYPE: header= BEGIN_X509_CRL; footer= END_X509_CRL; break;
|
||||||
|
case DH_PARAM_TYPE: header= BEGIN_DH_PARAM; footer= END_DH_PARAM; break;
|
||||||
|
case CERTREQ_TYPE: header= BEGIN_CERT_REQ; footer= END_CERT_REQ; break;
|
||||||
|
default: header= BEGIN_RSA_PRIV; footer= END_RSA_PRIV; break;
|
||||||
|
}
|
||||||
|
|
||||||
if (type == CERT_TYPE || type == CA_TYPE) {
|
switch (type) {
|
||||||
XSTRNCPY(header, "-----BEGIN CERTIFICATE-----", sizeof(header));
|
case CA_TYPE: dynamicType = DYNAMIC_TYPE_CA; break;
|
||||||
XSTRNCPY(footer, "-----END CERTIFICATE-----", sizeof(footer));
|
case CERT_TYPE: dynamicType = DYNAMIC_TYPE_CERT; break;
|
||||||
dynamicType = (type == CA_TYPE) ? DYNAMIC_TYPE_CA
|
case CRL_TYPE: dynamicType = DYNAMIC_TYPE_CRL; break;
|
||||||
: DYNAMIC_TYPE_CERT;
|
default: dynamicType = DYNAMIC_TYPE_KEY; break;
|
||||||
} else if (type == CERTREQ_TYPE) {
|
|
||||||
XSTRNCPY(header, "-----BEGIN CERTIFICATE REQUEST-----",
|
|
||||||
sizeof(header));
|
|
||||||
XSTRNCPY(footer, "-----END CERTIFICATE REQUEST-----",
|
|
||||||
sizeof(footer));
|
|
||||||
dynamicType = DYNAMIC_TYPE_KEY;
|
|
||||||
} else if (type == DH_PARAM_TYPE) {
|
|
||||||
XSTRNCPY(header, "-----BEGIN DH PARAMETERS-----", sizeof(header));
|
|
||||||
XSTRNCPY(footer, "-----END DH PARAMETERS-----", sizeof(footer));
|
|
||||||
dynamicType = DYNAMIC_TYPE_KEY;
|
|
||||||
} else if (type == CRL_TYPE) {
|
|
||||||
XSTRNCPY(header, "-----BEGIN X509 CRL-----", sizeof(header));
|
|
||||||
XSTRNCPY(footer, "-----END X509 CRL-----", sizeof(footer));
|
|
||||||
dynamicType = DYNAMIC_TYPE_CRL;
|
|
||||||
} else {
|
|
||||||
XSTRNCPY(header, "-----BEGIN RSA PRIVATE KEY-----", sizeof(header));
|
|
||||||
XSTRNCPY(footer, "-----END RSA PRIVATE KEY-----", sizeof(footer));
|
|
||||||
dynamicType = DYNAMIC_TYPE_KEY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find header */
|
/* find header */
|
||||||
|
for (;;) {
|
||||||
headerEnd = XSTRNSTR((char*)buff, header, sz);
|
headerEnd = XSTRNSTR((char*)buff, header, sz);
|
||||||
if (!headerEnd && type == PRIVATEKEY_TYPE) { /* may be pkcs8 */
|
|
||||||
XSTRNCPY(header, "-----BEGIN PRIVATE KEY-----", sizeof(header));
|
|
||||||
XSTRNCPY(footer, "-----END PRIVATE KEY-----", sizeof(footer));
|
|
||||||
|
|
||||||
headerEnd = XSTRNSTR((char*)buff, header, sz);
|
if (headerEnd || type != PRIVATEKEY_TYPE) {
|
||||||
if (headerEnd)
|
break;
|
||||||
pkcs8 = 1;
|
} else if (header == BEGIN_RSA_PRIV) {
|
||||||
else {
|
header = BEGIN_PRIV_KEY; footer = END_PRIV_KEY;
|
||||||
XSTRNCPY(header, "-----BEGIN ENCRYPTED PRIVATE KEY-----",
|
} else if (header == BEGIN_PRIV_KEY) {
|
||||||
sizeof(header));
|
header = BEGIN_ENC_PRIV_KEY; footer = END_ENC_PRIV_KEY;
|
||||||
XSTRNCPY(footer, "-----END ENCRYPTED PRIVATE KEY-----",
|
} else if (header == BEGIN_ENC_PRIV_KEY) {
|
||||||
sizeof(footer));
|
header = BEGIN_EC_PRIV; footer = END_EC_PRIV;
|
||||||
|
} else if (header == BEGIN_ENC_PRIV_KEY) {
|
||||||
|
header = BEGIN_DSA_PRIV; footer = END_DSA_PRIV;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
headerEnd = XSTRNSTR((char*)buff, header, sz);
|
|
||||||
if (headerEnd) {
|
|
||||||
pkcs8Enc = 1;
|
|
||||||
(void)pkcs8Enc; /* only opensslextra will read */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!headerEnd && type == PRIVATEKEY_TYPE) { /* may be ecc */
|
|
||||||
XSTRNCPY(header, "-----BEGIN EC PRIVATE KEY-----", sizeof(header));
|
|
||||||
XSTRNCPY(footer, "-----END EC PRIVATE KEY-----", sizeof(footer));
|
|
||||||
|
|
||||||
headerEnd = XSTRNSTR((char*)buff, header, sz);
|
|
||||||
if (headerEnd)
|
|
||||||
*eccKey = 1;
|
|
||||||
}
|
|
||||||
if (!headerEnd && type == PRIVATEKEY_TYPE) { /* may be dsa */
|
|
||||||
XSTRNCPY(header, "-----BEGIN DSA PRIVATE KEY-----", sizeof(header));
|
|
||||||
XSTRNCPY(footer, "-----END DSA PRIVATE KEY-----", sizeof(footer));
|
|
||||||
|
|
||||||
headerEnd = XSTRNSTR((char*)buff, header, sz);
|
|
||||||
}
|
|
||||||
if (!headerEnd) {
|
if (!headerEnd) {
|
||||||
CYASSL_MSG("Couldn't find PEM header");
|
CYASSL_MSG("Couldn't find PEM header");
|
||||||
return SSL_NO_PEM_HEADER;
|
return SSL_NO_PEM_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
headerEnd += XSTRLEN(header);
|
headerEnd += XSTRLEN(header);
|
||||||
|
|
||||||
/* eat end of line */
|
/* eat end of line */
|
||||||
@@ -1884,8 +1872,13 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
|
|||||||
else
|
else
|
||||||
return SSL_BAD_FILE;
|
return SSL_BAD_FILE;
|
||||||
|
|
||||||
|
if (type == PRIVATEKEY_TYPE) {
|
||||||
|
if (eccKey)
|
||||||
|
*eccKey = header == BEGIN_EC_PRIV;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
|
#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
|
||||||
{
|
{
|
||||||
/* remove encrypted header if there */
|
/* remove encrypted header if there */
|
||||||
char encHeader[] = "Proc-Type";
|
char encHeader[] = "Proc-Type";
|
||||||
char* line = XSTRNSTR(headerEnd, encHeader, PEM_LINE_LEN);
|
char* line = XSTRNSTR(headerEnd, encHeader, PEM_LINE_LEN);
|
||||||
@@ -1925,12 +1918,13 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
|
|||||||
newline++;
|
newline++;
|
||||||
headerEnd = newline;
|
headerEnd = newline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
|
#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
|
||||||
|
|
||||||
/* find footer */
|
/* find footer */
|
||||||
footerEnd = XSTRNSTR((char*)buff, footer, sz);
|
footerEnd = XSTRNSTR((char*)buff, footer, sz);
|
||||||
if (!footerEnd) return SSL_BAD_FILE;
|
if (!footerEnd)
|
||||||
|
return SSL_BAD_FILE;
|
||||||
|
|
||||||
consumedEnd = footerEnd + XSTRLEN(footer);
|
consumedEnd = footerEnd + XSTRLEN(footer);
|
||||||
|
|
||||||
@@ -1949,43 +1943,60 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
|
|||||||
|
|
||||||
/* set up der buffer */
|
/* set up der buffer */
|
||||||
neededSz = (long)(footerEnd - headerEnd);
|
neededSz = (long)(footerEnd - headerEnd);
|
||||||
if (neededSz > sz || neededSz < 0) return SSL_BAD_FILE;
|
if (neededSz > sz || neededSz < 0)
|
||||||
der->buffer = (byte*) XMALLOC(neededSz, heap, dynamicType);
|
return SSL_BAD_FILE;
|
||||||
if (!der->buffer) return MEMORY_ERROR;
|
|
||||||
|
der->buffer = (byte*)XMALLOC(neededSz, heap, dynamicType);
|
||||||
|
if (!der->buffer)
|
||||||
|
return MEMORY_ERROR;
|
||||||
|
|
||||||
der->length = (word32)neededSz;
|
der->length = (word32)neededSz;
|
||||||
|
|
||||||
if (Base64_Decode((byte*)headerEnd, (word32)neededSz, der->buffer,
|
if (Base64_Decode((byte*)headerEnd, (word32)neededSz, der->buffer,
|
||||||
&der->length) < 0)
|
&der->length) < 0)
|
||||||
return SSL_BAD_FILE;
|
return SSL_BAD_FILE;
|
||||||
|
|
||||||
if (pkcs8) {
|
if (header == BEGIN_PRIV_KEY) {
|
||||||
/* convert and adjust length */
|
/* pkcs8 key, convert and adjust length */
|
||||||
if ( (ret = ToTraditional(der->buffer, der->length)) < 0 ) {
|
if ((ret = ToTraditional(der->buffer, der->length)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
|
||||||
der->length = ret;
|
der->length = ret;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#if (defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)) && !defined(NO_PWDBASED)
|
#if (defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)) && !defined(NO_PWDBASED)
|
||||||
if (pkcs8Enc) {
|
if (header == BEGIN_ENC_PRIV_KEY) {
|
||||||
int passwordSz;
|
int passwordSz;
|
||||||
|
#ifdef CYASSL_SMALL_STACK
|
||||||
|
char* password = NULL;
|
||||||
|
#else
|
||||||
char password[80];
|
char password[80];
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!info || !info->ctx || !info->ctx->passwd_cb)
|
if (!info || !info->ctx || !info->ctx->passwd_cb)
|
||||||
return SSL_BAD_FILE; /* no callback error */
|
return SSL_BAD_FILE; /* no callback error */
|
||||||
|
|
||||||
|
#ifdef CYASSL_SMALL_STACK
|
||||||
|
password = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (password == NULL)
|
||||||
|
return MEMORY_E;
|
||||||
|
#endif
|
||||||
passwordSz = info->ctx->passwd_cb(password, sizeof(password), 0,
|
passwordSz = info->ctx->passwd_cb(password, sizeof(password), 0,
|
||||||
info->ctx->userdata);
|
info->ctx->userdata);
|
||||||
/* convert and adjust length */
|
/* convert and adjust length */
|
||||||
if ( (ret = ToTraditionalEnc(der->buffer, der->length, password,
|
ret = ToTraditionalEnc(der->buffer, der->length, password, passwordSz);
|
||||||
passwordSz)) < 0 ) {
|
|
||||||
|
#ifdef CYASSL_SMALL_STACK
|
||||||
|
XFREE(password, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
|
||||||
der->length = ret;
|
der->length = ret;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -10013,11 +10024,11 @@ int CyaSSL_RAND_bytes(unsigned char* buf, int num)
|
|||||||
|
|
||||||
CYASSL_ENTER("RAND_bytes");
|
CYASSL_ENTER("RAND_bytes");
|
||||||
|
|
||||||
#ifdef CYASSL_SMALL_STACK
|
#ifdef CYASSL_SMALL_STACK
|
||||||
tmpRNG = (RNG*)XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
tmpRNG = (RNG*)XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
if (tmpRNG == NULL)
|
if (tmpRNG == NULL)
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (InitRng(tmpRNG) == 0)
|
if (InitRng(tmpRNG) == 0)
|
||||||
rng = tmpRNG;
|
rng = tmpRNG;
|
||||||
@@ -10031,6 +10042,10 @@ int CyaSSL_RAND_bytes(unsigned char* buf, int num)
|
|||||||
ret = SSL_SUCCESS;
|
ret = SSL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CYASSL_SMALL_STACK
|
||||||
|
XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user