mirror of https://github.com/wolfSSL/wolfssl
add PEM read bio private key function and update reading a memory bio
This commit is contained in:
parent
f9eb8f8f6d
commit
921eb03a01
17
src/bio.c
17
src/bio.c
|
@ -173,7 +173,7 @@ size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio)
|
|||
}
|
||||
|
||||
if (bio->type == WOLFSSL_BIO_MEMORY) {
|
||||
return bio->memLen;
|
||||
return bio->wrSz;
|
||||
}
|
||||
|
||||
/* 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");
|
||||
|
||||
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 */
|
||||
|
@ -247,6 +247,7 @@ int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size)
|
|||
WOLFSSL_MSG("Memory allocation error");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
bio->memLen = bio->wrSz;
|
||||
bio->wrIdx = 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");
|
||||
|
||||
if (b == NULL) {
|
||||
return WOLFSSL_FAILURE;
|
||||
if (b == NULL || b->type == WOLFSSL_BIO_MEMORY) {
|
||||
return SSL_FAILURE;
|
||||
}
|
||||
|
||||
b->readRq = 0;
|
||||
|
@ -346,6 +347,10 @@ int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num)
|
|||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
|
||||
if (bio->type == WOLFSSL_BIO_MEMORY) {
|
||||
return SSL_FAILURE;
|
||||
}
|
||||
|
||||
if (bio->pair != NULL) {
|
||||
/* special case if asking to read 0 bytes */
|
||||
if (num == 0) {
|
||||
|
@ -394,6 +399,10 @@ int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (bio->type != WOLFSSL_BIO_BIO) {
|
||||
return SSL_FAILURE;
|
||||
}
|
||||
|
||||
if (bio->pair != NULL) {
|
||||
if (num == 0) {
|
||||
*buf = (char*)bio->mem + bio->wrIdx;
|
||||
|
|
229
src/ssl.c
229
src/ssl.c
|
@ -6847,7 +6847,18 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out,
|
|||
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) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -11761,7 +11772,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||
if (bio == NULL)
|
||||
return bio;
|
||||
|
||||
bio->memLen = len;
|
||||
bio->memLen = bio->wrSz = len;
|
||||
bio->mem = (byte*)XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL);
|
||||
if (bio->mem == NULL) {
|
||||
XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL);
|
||||
|
@ -11909,6 +11920,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||
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
|
||||
if (bio && bio->type == WOLFSSL_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 ret;
|
||||
|
@ -11973,6 +12038,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||
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
|
||||
if (bio && bio->type == WOLFSSL_BIO_FILE) {
|
||||
return (int)XFWRITE(data, 1, len, bio->file);
|
||||
|
@ -14637,6 +14706,12 @@ static void ExternalFreeX509(WOLFSSL_X509* x509)
|
|||
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);
|
||||
if (asn1->data == NULL) {
|
||||
return SSL_FAILURE;
|
||||
|
@ -15966,9 +16041,7 @@ WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* top)
|
|||
|
||||
int wolfSSL_BIO_pending(WOLFSSL_BIO* bio)
|
||||
{
|
||||
if (bio && bio->type == WOLFSSL_BIO_MEMORY)
|
||||
return bio->memLen;
|
||||
return 0;
|
||||
return (int)wolfSSL_BIO_ctrl_pending(bio);
|
||||
}
|
||||
|
||||
|
||||
|
@ -21819,6 +21892,7 @@ int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key,
|
|||
int pemSz;
|
||||
int type;
|
||||
int ret;
|
||||
byte* tmp;
|
||||
|
||||
(void)cipher;
|
||||
(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);
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
if (bio->mem != NULL) {
|
||||
XFREE(bio->mem, NULL, DYNAMIC_TYPE_OPENSSL);
|
||||
tmp = (byte*)XMALLOC(pemSz, bio->heap, 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);
|
||||
if (ret < 0) {
|
||||
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) */
|
||||
|
||||
|
@ -23631,17 +23712,127 @@ int wolfSSL_PEM_write_DSA_PUBKEY(FILE *fp, WOLFSSL_DSA *x)
|
|||
|
||||
#endif /* #ifndef NO_DSA */
|
||||
|
||||
|
||||
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;
|
||||
(void)key;
|
||||
(void)cb;
|
||||
(void)arg;
|
||||
WOLFSSL_EVP_PKEY* pkey = NULL;
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
Encryptedinfo* info;
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
|
36
tests/api.c
36
tests/api.c
|
@ -13383,6 +13383,12 @@ static void test_wolfSSL_private_keys(void)
|
|||
AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey,
|
||||
&server_key, (long)sizeof_server_key_der_2048));
|
||||
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
|
||||
|
||||
|
@ -13408,21 +13414,45 @@ static void test_wolfSSL_PEM_PrivateKey(void)
|
|||
(defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)) && \
|
||||
defined(USE_CERT_BUFFERS_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;
|
||||
unsigned char extra[10];
|
||||
int i;
|
||||
|
||||
printf(testingFmt, "wolfSSL_PEM_PrivateKey()");
|
||||
|
||||
bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
|
||||
AssertNotNull(bio);
|
||||
XMEMSET(extra, 0, sizeof(extra));
|
||||
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,
|
||||
&server_key, (long)sizeof_server_key_der_2048));
|
||||
AssertIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL),
|
||||
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);
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_free(pkey2);
|
||||
|
||||
printf(resultFmt, passed);
|
||||
#endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */
|
||||
|
|
|
@ -124,6 +124,7 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX;
|
|||
#define SSL_use_certificate wolfSSL_use_certificate
|
||||
#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_ASN1 wolfSSL_use_PrivateKey_ASN1
|
||||
#define SSL_use_RSAPrivateKey_ASN1 wolfSSL_use_RSAPrivateKey_ASN1
|
||||
|
|
Loading…
Reference in New Issue