add PEM read bio private key function and update reading a memory bio

This commit is contained in:
Jacob Barthelmeh 2017-01-12 18:06:31 -07:00
parent f9eb8f8f6d
commit 921eb03a01
4 changed files with 257 additions and 26 deletions

View File

@ -173,7 +173,7 @@ size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio)
} }
if (bio->type == WOLFSSL_BIO_MEMORY) { if (bio->type == WOLFSSL_BIO_MEMORY) {
return bio->memLen; return bio->wrSz;
} }
/* type BIO_BIO then check paired buffer */ /* type BIO_BIO then check paired buffer */
@ -223,7 +223,7 @@ int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size)
WOLFSSL_ENTER("wolfSSL_BIO_set_write_buf_size"); WOLFSSL_ENTER("wolfSSL_BIO_set_write_buf_size");
if (bio == NULL || bio->type != WOLFSSL_BIO_BIO || size < 0) { if (bio == NULL || bio->type != WOLFSSL_BIO_BIO || size < 0) {
return SSL_FAILURE; return WOLFSSL_FAILURE;
} }
/* if already in pair then do not change size */ /* if already in pair then do not change size */
@ -247,6 +247,7 @@ int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size)
WOLFSSL_MSG("Memory allocation error"); WOLFSSL_MSG("Memory allocation error");
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
bio->memLen = bio->wrSz;
bio->wrIdx = 0; bio->wrIdx = 0;
bio->rdIdx = 0; bio->rdIdx = 0;
@ -296,8 +297,8 @@ int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b)
{ {
WOLFSSL_ENTER("wolfSSL_BIO_ctrl_reset_read_request"); WOLFSSL_ENTER("wolfSSL_BIO_ctrl_reset_read_request");
if (b == NULL) { if (b == NULL || b->type == WOLFSSL_BIO_MEMORY) {
return WOLFSSL_FAILURE; return SSL_FAILURE;
} }
b->readRq = 0; b->readRq = 0;
@ -346,6 +347,10 @@ int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num)
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
if (bio->type == WOLFSSL_BIO_MEMORY) {
return SSL_FAILURE;
}
if (bio->pair != NULL) { if (bio->pair != NULL) {
/* special case if asking to read 0 bytes */ /* special case if asking to read 0 bytes */
if (num == 0) { if (num == 0) {
@ -394,6 +399,10 @@ int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num)
return 0; return 0;
} }
if (bio->type != WOLFSSL_BIO_BIO) {
return SSL_FAILURE;
}
if (bio->pair != NULL) { if (bio->pair != NULL) {
if (num == 0) { if (num == 0) {
*buf = (char*)bio->mem + bio->wrIdx; *buf = (char*)bio->mem + bio->wrIdx;

229
src/ssl.c
View File

@ -6847,7 +6847,18 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out,
return NULL; return NULL;
} }
local = wolfSSL_PKEY_new(); if (out != NULL && *out != NULL) {
/* reuse structure */
WOLFSSL_MSG("Reusing WOLFSSL_EVP_PKEY structure");
if ((*out)->pkey.ptr != NULL) {
XFREE((*out)->pkey.ptr, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
}
local = *out;
}
else {
local = wolfSSL_PKEY_new();
}
if (local == NULL) { if (local == NULL) {
return NULL; return NULL;
} }
@ -11761,7 +11772,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
if (bio == NULL) if (bio == NULL)
return bio; return bio;
bio->memLen = len; bio->memLen = bio->wrSz = len;
bio->mem = (byte*)XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL); bio->mem = (byte*)XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL);
if (bio->mem == NULL) { if (bio->mem == NULL) {
XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL); XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL);
@ -11909,6 +11920,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
return wolfSSL_BIO_BIO_read(bio, buf, len); return wolfSSL_BIO_BIO_read(bio, buf, len);
} }
if (bio && bio->type == WOLFSSL_BIO_MEMORY) {
return wolfSSL_BIO_MEMORY_read(bio, buf, len);
}
#ifndef NO_FILESYSTEM #ifndef NO_FILESYSTEM
if (bio && bio->type == WOLFSSL_BIO_FILE) { if (bio && bio->type == WOLFSSL_BIO_FILE) {
return (int)XFREAD(buf, 1, len, bio->file); return (int)XFREAD(buf, 1, len, bio->file);
@ -11960,6 +11975,56 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
} }
/* for complete compatibility a bio memory write allocs its own memory
* untill the application runs out ....
*/
static int wolfSSL_BIO_MEMORY_write(WOLFSSL_BIO* bio, const void* data,
int len)
{
/* internal function where arguments have already been sanity checked */
int sz;
int ret;
const unsigned char* buf;
sz = wolfSSL_BIO_pending(bio);
if (sz < 0) {
WOLFSSL_MSG("Error getting memory data");
return sz;
}
if (bio->mem == NULL) {
bio->mem = (byte*)XMALLOC(len, bio->heap,
DYNAMIC_TYPE_OPENSSL);
if (bio->mem == NULL) {
WOLFSSL_MSG("Error on malloc");
return SSL_FAILURE;
}
bio->memLen = len;
}
/* check if will fit in current buffer size */
if ((ret = wolfSSL_BIO_get_mem_data(bio, &buf)) < sz + len) {
if (ret <= 0) {
return WOLFSSL_BIO_ERROR;
}
else {
bio->mem = (byte*)XREALLOC(bio->mem, sz + len, bio->heap,
DYNAMIC_TYPE_OPENSSL);
if (bio->mem == NULL) {
WOLFSSL_MSG("Error on realloc");
return SSL_FAILURE;
}
bio->memLen = sz + len;
}
}
XMEMCPY(bio->mem + sz, data, len);
bio->wrSz += len;
return len;
}
int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len)
{ {
int ret; int ret;
@ -11973,6 +12038,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
return wolfSSL_BIO_BIO_write(bio, data, len); return wolfSSL_BIO_BIO_write(bio, data, len);
} }
if (bio && bio->type == WOLFSSL_BIO_MEMORY) {
return wolfSSL_BIO_MEMORY_write(bio, data, len);
}
#ifndef NO_FILESYSTEM #ifndef NO_FILESYSTEM
if (bio && bio->type == WOLFSSL_BIO_FILE) { if (bio && bio->type == WOLFSSL_BIO_FILE) {
return (int)XFWRITE(data, 1, len, bio->file); return (int)XFWRITE(data, 1, len, bio->file);
@ -14637,6 +14706,12 @@ static void ExternalFreeX509(WOLFSSL_X509* x509)
return SSL_FAILURE; return SSL_FAILURE;
} }
/* free any existing data before copying */
if (asn1->data != NULL) {
XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
}
/* create new data buffer and copy over */
asn1->data = (char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL); asn1->data = (char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL);
if (asn1->data == NULL) { if (asn1->data == NULL) {
return SSL_FAILURE; return SSL_FAILURE;
@ -15966,9 +16041,7 @@ WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* top)
int wolfSSL_BIO_pending(WOLFSSL_BIO* bio) int wolfSSL_BIO_pending(WOLFSSL_BIO* bio)
{ {
if (bio && bio->type == WOLFSSL_BIO_MEMORY) return (int)wolfSSL_BIO_ctrl_pending(bio);
return bio->memLen;
return 0;
} }
@ -21819,6 +21892,7 @@ int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key,
int pemSz; int pemSz;
int type; int type;
int ret; int ret;
byte* tmp;
(void)cipher; (void)cipher;
(void)passwd; (void)passwd;
@ -21859,20 +21933,27 @@ int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key,
WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", pemSz); WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", pemSz);
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
if (bio->mem != NULL) { tmp = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
XFREE(bio->mem, NULL, DYNAMIC_TYPE_OPENSSL); if (tmp == NULL) {
return MEMORY_E;
} }
bio->mem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_OPENSSL);
bio->memLen = pemSz;
ret = wc_DerToPemEx(keyDer, key->pkey_sz, bio->mem, bio->memLen, ret = wc_DerToPemEx(keyDer, key->pkey_sz, tmp, pemSz,
NULL, type); NULL, type);
if (ret < 0) { if (ret < 0) {
WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", ret); WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", ret);
return WOLFSSL_FAILURE; XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
return SSL_FAILURE;
} }
return WOLFSSL_SUCCESS; ret = wolfSSL_BIO_write(bio, tmp, pemSz);
XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
if (ret != pemSz) {
WOLFSSL_MSG("Unable to write full PEM to BIO");
return SSL_FAILURE;
}
return SSL_SUCCESS;
} }
#endif /* defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) */ #endif /* defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) */
@ -23631,17 +23712,127 @@ int wolfSSL_PEM_write_DSA_PUBKEY(FILE *fp, WOLFSSL_DSA *x)
#endif /* #ifndef NO_DSA */ #endif /* #ifndef NO_DSA */
WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio,
WOLFSSL_EVP_PKEY** key, pem_password_cb* cb, void* arg) WOLFSSL_EVP_PKEY** key, pem_password_cb* cb, void* pass)
{ {
(void)bio; WOLFSSL_EVP_PKEY* pkey = NULL;
(void)key; #ifdef WOLFSSL_SMALL_STACK
(void)cb; Encryptedinfo* info;
(void)arg; #else
EncryptedInfo info[1];
#endif /* WOLFSSL_SMALL_STACK */
pem_password_cb* localCb = cb;
DerBuffer* der = NULL;
WOLFSSL_MSG("wolfSSL_PEM_read_bio_PrivateKey not implemented"); char* mem = NULL;
int memSz;
int ret;
int eccFlag = 0;
return NULL; WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PrivateKey");
if ((ret = wolfSSL_BIO_pending(bio)) > 0) {
memSz = ret;
mem = (char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
if (mem == NULL) {
WOLFSSL_MSG("Memory error");
return NULL;
}
if ((ret = wolfSSL_BIO_read(bio, mem, memSz)) <= 0) {
WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PrivateKey", ret);
XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
return NULL;
}
}
else {
WOLFSSL_MSG("No data to read from bio");
return NULL;
}
#ifdef WOLFSSL_SMALL_STACK
info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (info == NULL) {
WOLFSSL_MSG("Error getting memory for EncryptedInfo structure");
XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
return NULL;
}
#endif
XMEMSET(info, 0, sizeof(EncryptedInfo));
if (pass != NULL) {
info->ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
if (info->ctx == NULL) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
WOLFSSL_MSG("Error creating ctx for password");
XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
return NULL;
}
if (cb == NULL) {
localCb = &OurPasswordCb;
}
wolfSSL_CTX_set_default_passwd_cb(info->ctx, localCb);
wolfSSL_CTX_set_default_passwd_cb_userdata(info->ctx, pass);
}
ret = PemToDer((const unsigned char*)mem, memSz, PRIVATEKEY_TYPE, &der,
NULL, info, &eccFlag);
if (info->ctx) {
wolfSSL_CTX_free(info->ctx);
}
if (ret < 0) {
WOLFSSL_MSG("Bad Pem To Der");
}
else {
int type;
/* write left over data back to bio */
if ((memSz - (int)info->consumed) > 0) {
if (wolfSSL_BIO_write(bio, mem + (int)info->consumed,
memSz - (int)info->consumed) <= 0) {
WOLFSSL_MSG("Unable to advance bio read pointer");
}
}
if (eccFlag) {
type = ECDSAk;
}
else {
type = RSAk;
}
/* handle case where reuse is attempted */
if (key != NULL && *key != NULL) {
pkey = *key;
}
wolfSSL_d2i_PrivateKey(type, &pkey,
(const unsigned char**)&der->buffer, der->length);
if (pkey == NULL) {
WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY");
}
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
FreeDer(&der);
if (key != NULL) {
*key = pkey;
}
return pkey;
} }

View File

@ -13383,6 +13383,12 @@ static void test_wolfSSL_private_keys(void)
AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey,
&server_key, (long)sizeof_server_key_der_2048)); &server_key, (long)sizeof_server_key_der_2048));
AssertIntEQ(SSL_use_PrivateKey(ssl, pkey), WOLFSSL_SUCCESS); AssertIntEQ(SSL_use_PrivateKey(ssl, pkey), WOLFSSL_SUCCESS);
/* reuse PKEY structure and test
* this should be checked with a memory management sanity checker */
AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey,
&server_key, (long)sizeof_server_key_der_2048));
AssertIntEQ(SSL_use_PrivateKey(ssl, pkey), WOLFSSL_SUCCESS);
} }
#endif #endif
@ -13408,21 +13414,45 @@ static void test_wolfSSL_PEM_PrivateKey(void)
(defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)) && \ (defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)) && \
defined(USE_CERT_BUFFERS_2048) defined(USE_CERT_BUFFERS_2048)
const unsigned char* server_key = (const unsigned char*)server_key_der_2048; const unsigned char* server_key = (const unsigned char*)server_key_der_2048;
EVP_PKEY* pkey = NULL; EVP_PKEY* pkey = NULL;
EVP_PKEY* pkey2 = NULL;
BIO* bio; BIO* bio;
unsigned char extra[10];
int i;
printf(testingFmt, "wolfSSL_PEM_PrivateKey()"); printf(testingFmt, "wolfSSL_PEM_PrivateKey()");
bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); XMEMSET(extra, 0, sizeof(extra));
AssertNotNull(bio); AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()));
AssertIntEQ(BIO_set_write_buf_size(bio, 4096), SSL_FAILURE);
AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey,
&server_key, (long)sizeof_server_key_der_2048)); &server_key, (long)sizeof_server_key_der_2048));
AssertIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), AssertIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL),
WOLFSSL_SUCCESS); WOLFSSL_SUCCESS);
/* test of creating new EVP_PKEY */
AssertNotNull((pkey2 = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)));
AssertIntEQ((int)XMEMCMP(pkey->pkey.ptr, pkey2->pkey.ptr, pkey->pkey_sz),0);
/* test of reuse of EVP_PKEY */
AssertNull(PEM_read_bio_PrivateKey(bio, &pkey, NULL, NULL));
AssertIntEQ(BIO_pending(bio), 0);
AssertIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL),
SSL_SUCCESS);
AssertIntEQ(BIO_write(bio, extra, 10), 10); /*add 10 extra bytes after PEM*/
AssertNotNull(PEM_read_bio_PrivateKey(bio, &pkey, NULL, NULL));
AssertNotNull(pkey);
AssertIntEQ((int)XMEMCMP(pkey->pkey.ptr, pkey2->pkey.ptr, pkey->pkey_sz),0);
AssertIntEQ(BIO_pending(bio), 10); /* check 10 extra bytes still there */
AssertIntEQ(BIO_read(bio, extra, 10), 10);
for (i = 0; i < 10; i++) {
AssertIntEQ(extra[i], 0);
}
BIO_free(bio); BIO_free(bio);
EVP_PKEY_free(pkey); EVP_PKEY_free(pkey);
EVP_PKEY_free(pkey2);
printf(resultFmt, passed); printf(resultFmt, passed);
#endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */

View File

@ -124,6 +124,7 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX;
#define SSL_use_certificate wolfSSL_use_certificate #define SSL_use_certificate wolfSSL_use_certificate
#define SSL_use_certificate_ASN1 wolfSSL_use_certificate_ASN1 #define SSL_use_certificate_ASN1 wolfSSL_use_certificate_ASN1
#define d2i_PrivateKey wolfSSL_d2i_PrivateKey
#define SSL_use_PrivateKey wolfSSL_use_PrivateKey #define SSL_use_PrivateKey wolfSSL_use_PrivateKey
#define SSL_use_PrivateKey_ASN1 wolfSSL_use_PrivateKey_ASN1 #define SSL_use_PrivateKey_ASN1 wolfSSL_use_PrivateKey_ASN1
#define SSL_use_RSAPrivateKey_ASN1 wolfSSL_use_RSAPrivateKey_ASN1 #define SSL_use_RSAPrivateKey_ASN1 wolfSSL_use_RSAPrivateKey_ASN1