fix bio gets and enhance x509 get public key

This commit is contained in:
Jacob Barthelmeh
2017-02-08 09:16:48 -07:00
parent 734e728fba
commit c8233177c3
6 changed files with 227 additions and 44 deletions

View File

@ -38,7 +38,7 @@ WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bio, int cmd, long larg, void *pa
/* helper function for wolfSSL_BIO_gets /* helper function for wolfSSL_BIO_gets
* size till a newline is hit * size till a newline is hit
* returns the number of bytes * returns the number of bytes including the new line character
*/ */
static int wolfSSL_getLineLength(char* in, int inSz) static int wolfSSL_getLineLength(char* in, int inSz)
{ {
@ -46,11 +46,11 @@ static int wolfSSL_getLineLength(char* in, int inSz)
for (i = 0; i < inSz; i++) { for (i = 0; i < inSz; i++) {
if (in[i] == '\n') { if (in[i] == '\n') {
break; return i + 1; /* includes new line character */
} }
} }
return i + 1; /* +1 to return number of bytes not index */ return inSz; /* rest of buffer is all one line */
} }
@ -72,6 +72,10 @@ int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz)
switch (bio->type) { switch (bio->type) {
#ifndef NO_FILESYSTEM #ifndef NO_FILESYSTEM
case WOLFSSL_BIO_FILE: case WOLFSSL_BIO_FILE:
if (bio->file == NULL) {
return WOLFSSL_BIO_ERROR;
}
#if defined(MICRIUM) || defined(LSR_FS) || defined(EBSNET) #if defined(MICRIUM) || defined(LSR_FS) || defined(EBSNET)
WOLFSSL_MSG("XFGETS not ported for this system yet"); WOLFSSL_MSG("XFGETS not ported for this system yet");
ret = XFGETS(buf, sz, bio->file); ret = XFGETS(buf, sz, bio->file);
@ -103,10 +107,15 @@ int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz)
cSz = wolfSSL_getLineLength((char*)c, cSz); cSz = wolfSSL_getLineLength((char*)c, cSz);
/* check case where line was bigger then buffer and buffer /* check case where line was bigger then buffer and buffer
* needs end terminator */ * needs end terminator */
if (cSz > sz) { if (cSz >= sz) {
cSz = sz - 1; cSz = sz - 1;
buf[cSz] = '\0'; buf[cSz] = '\0';
} }
else {
/* not minus 1 here because placing terminator after
msg and have checked that sz is large enough */
buf[cSz] = '\0';
}
ret = wolfSSL_BIO_read(bio, (void*)buf, cSz); ret = wolfSSL_BIO_read(bio, (void*)buf, cSz);
/* ret is read after the switch statment */ /* ret is read after the switch statment */
@ -125,10 +134,15 @@ int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz)
cSz = wolfSSL_getLineLength(c, cSz); cSz = wolfSSL_getLineLength(c, cSz);
/* check case where line was bigger then buffer and buffer /* check case where line was bigger then buffer and buffer
* needs end terminator */ * needs end terminator */
if (cSz > sz) { if (cSz >= sz) {
cSz = sz - 1; cSz = sz - 1;
buf[cSz] = '\0'; buf[cSz] = '\0';
} }
else {
/* not minus 1 here because placing terminator after
msg and have checked that sz is large enough */
buf[cSz] = '\0';
}
ret = wolfSSL_BIO_nread(bio, &c, cSz); ret = wolfSSL_BIO_nread(bio, &c, cSz);
if (ret > 0 && ret < sz) { if (ret > 0 && ret < sz) {

123
src/ssl.c
View File

@ -17220,34 +17220,6 @@ WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL* crl)
WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509)
{
WOLFSSL_EVP_PKEY* key = NULL;
if (x509 != NULL) {
key = (WOLFSSL_EVP_PKEY*)XMALLOC(
sizeof(WOLFSSL_EVP_PKEY), x509->heap,
DYNAMIC_TYPE_PUBLIC_KEY);
if (key != NULL) {
key->type = EVP_PKEY_RSA; /*x509->pubKeyOID;*/
key->save_type = 0;
key->pkey.ptr = (char*)XMALLOC(
x509->pubKey.length, x509->heap,
DYNAMIC_TYPE_PUBLIC_KEY);
if (key->pkey.ptr == NULL) {
XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
return NULL;
}
XMEMCPY(key->pkey.ptr,
x509->pubKey.buffer, x509->pubKey.length);
key->pkey_sz = x509->pubKey.length;
#ifdef HAVE_ECC
key->pkey_curve = (int)x509->pkCurveOID;
#endif /* HAVE_ECC */
}
}
return key;
}
int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* key) int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* key)
{ {
@ -17334,6 +17306,14 @@ void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key)
break; break;
#endif /* NO_RSA */ #endif /* NO_RSA */
#ifdef HAVE_ECC
case EVP_PKEY_EC:
if (key->ecc != NULL && key->ownEcc == 1) {
wolfSSL_EC_KEY_free(key->ecc);
}
break;
#endif /* HAVE_ECC */
default: default:
break; break;
} }
@ -24478,6 +24458,91 @@ int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key,
} }
#endif /* HAVE_ECC */ #endif /* HAVE_ECC */
WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509)
{
WOLFSSL_EVP_PKEY* key = NULL;
if (x509 != NULL) {
key = (WOLFSSL_EVP_PKEY*)XMALLOC(
sizeof(WOLFSSL_EVP_PKEY), x509->heap,
DYNAMIC_TYPE_PUBLIC_KEY);
if (key != NULL) {
XMEMSET(key, 0, sizeof(WOLFSSL_EVP_PKEY));
if (x509->pubKeyOID == RSAk) {
key->type = EVP_PKEY_RSA;
}
else {
key->type = EVP_PKEY_EC;
}
key->save_type = 0;
key->pkey.ptr = (char*)XMALLOC(
x509->pubKey.length, x509->heap,
DYNAMIC_TYPE_PUBLIC_KEY);
if (key->pkey.ptr == NULL) {
XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
return NULL;
}
XMEMCPY(key->pkey.ptr, x509->pubKey.buffer, x509->pubKey.length);
key->pkey_sz = x509->pubKey.length;
#ifdef HAVE_ECC
key->pkey_curve = (int)x509->pkCurveOID;
#endif /* HAVE_ECC */
/* decode RSA key */
#ifndef NO_RSA
if (key->type == EVP_PKEY_RSA) {
key->ownRsa = 1;
key->rsa = wolfSSL_RSA_new();
if (key->rsa == NULL) {
XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
return NULL;
}
if (wolfSSL_RSA_LoadDer_ex(key->rsa,
(const unsigned char*)key->pkey.ptr, key->pkey_sz,
WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) {
XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
wolfSSL_RSA_free(key->rsa);
return NULL;
}
}
#endif /* NO_RSA */
/* decode ECC key */
#ifdef HAVE_ECC
if (key->type == EVP_PKEY_EC) {
key->ownEcc = 1;
key->ecc = wolfSSL_EC_KEY_new();
if (key->ecc == NULL || key->ecc->internal == NULL) {
XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
return NULL;
}
/* not using wolfSSL_EC_KEY_LoadDer because public key in x509
* is in the format of x963 (no sequence at start of buffer) */
if (wc_ecc_import_x963((const unsigned char*)key->pkey.ptr,
key->pkey_sz, (ecc_key*)key->ecc->internal) < 0) {
WOLFSSL_MSG("wc_ecc_import_x963 failed");
XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
wolfSSL_EC_KEY_free(key->ecc);
return NULL;
}
if (SetECKeyExternal(key->ecc) != SSL_SUCCESS) {
WOLFSSL_MSG("SetECKeyExternal failed");
XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
wolfSSL_EC_KEY_free(key->ecc);
return NULL;
}
key->ecc->inSet = 1;
}
#endif /* HAVE_ECC */
}
}
return key;
}
#endif /* OPENSSL_EXTRA */ #endif /* OPENSSL_EXTRA */
@ -26292,7 +26357,7 @@ WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode)
(void)filename; (void)filename;
(void)mode; (void)mode;
return NULL; return NULL;
#endif #endif /* NO_FILESYSTEM */
} }

View File

@ -13716,7 +13716,34 @@ static void test_wolfSSL_CTX_add_extra_chain_cert(void)
x509 = wolfSSL_X509_load_certificate_file(clientFile, WOLFSSL_FILETYPE_PEM); x509 = wolfSSL_X509_load_certificate_file(clientFile, WOLFSSL_FILETYPE_PEM);
AssertNotNull(x509); AssertNotNull(x509);
AssertIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), WOLFSSL_SUCCESS);
/* additional test of getting EVP_PKEY key size from X509 */
{
EVP_PKEY* pkey;
#if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256)
X509* ecX509;
#endif /* HAVE_ECC */
AssertNotNull(pkey = X509_get_pubkey(x509));
/* current RSA key is 2048 bit (256 bytes) */
AssertIntEQ(EVP_PKEY_size(pkey), 256);
EVP_PKEY_free(pkey);
#if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256)
AssertNotNull(ecX509 = wolfSSL_X509_load_certificate_buffer(
cliecc_cert_der_256, sizeof_cliecc_cert_der_256,
SSL_FILETYPE_ASN1));
AssertNotNull(pkey = X509_get_pubkey(ecX509));
/* current ECC key is 256 bit (32 bytes) */
AssertIntEQ(EVP_PKEY_size(pkey), 32);
X509_free(ecX509);
EVP_PKEY_free(pkey);
#endif /* HAVE_ECC */
}
AssertIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), SSL_SUCCESS);
AssertNull(SSL_CTX_get_default_passwd_cb(ctx)); AssertNull(SSL_CTX_get_default_passwd_cb(ctx));
AssertNull(SSL_CTX_get_default_passwd_cb_userdata(ctx)); AssertNull(SSL_CTX_get_default_passwd_cb_userdata(ctx));
@ -14551,7 +14578,7 @@ static void test_wolfSSL_BIO(void)
BIO_free(f_bio1); BIO_free(f_bio1);
BIO_free(f_bio2); BIO_free(f_bio2);
AssertNotNull(f_bio1 = BIO_new_file(svrCert, "rwb")); AssertNotNull(f_bio1 = BIO_new_file(svrCertFile, "rwb"));
AssertIntEQ((int)BIO_set_mem_eof_return(f_bio1, -1), 0); AssertIntEQ((int)BIO_set_mem_eof_return(f_bio1, -1), 0);
AssertIntEQ(BIO_read(f_bio1, cert, sizeof(cert)), sizeof(cert)); AssertIntEQ(BIO_read(f_bio1, cert, sizeof(cert)), sizeof(cert));
BIO_free(f_bio1); BIO_free(f_bio1);
@ -14977,6 +15004,7 @@ static void test_wolfSSL_BIO_gets(void)
BIO* bio; BIO* bio;
BIO* bio2; BIO* bio2;
char msg[] = "\nhello wolfSSL\n security plus\t---...**adf\na...b.c"; char msg[] = "\nhello wolfSSL\n security plus\t---...**adf\na...b.c";
char emp[] = "";
char buffer[20]; char buffer[20];
int bufferSz = 20; int bufferSz = 20;
@ -14989,6 +15017,9 @@ static void test_wolfSSL_BIO_gets(void)
AssertNotNull(bio2 = BIO_find_type(bio, BIO_TYPE_BIO)); AssertNotNull(bio2 = BIO_find_type(bio, BIO_TYPE_BIO));
AssertFalse(bio2 != BIO_next(bio)); AssertFalse(bio2 != BIO_next(bio));
/* make buffer filled with no terminating characters */
XMEMSET(buffer, 1, bufferSz);
/* BIO_gets reads a line of data */ /* BIO_gets reads a line of data */
AssertIntEQ(BIO_gets(bio, buffer, -3), 0); AssertIntEQ(BIO_gets(bio, buffer, -3), 0);
AssertIntEQ(BIO_gets(bio, buffer, bufferSz), 1); AssertIntEQ(BIO_gets(bio, buffer, bufferSz), 1);
@ -14998,6 +15029,75 @@ static void test_wolfSSL_BIO_gets(void)
AssertIntEQ(BIO_gets(bio, buffer, bufferSz), 8); AssertIntEQ(BIO_gets(bio, buffer, bufferSz), 8);
AssertIntEQ(BIO_gets(bio, buffer, -1), 0); AssertIntEQ(BIO_gets(bio, buffer, -1), 0);
/* check not null terminated string */
BIO_free(bio);
msg[0] = 0x33;
msg[1] = 0x33;
msg[2] = 0x33;
AssertNotNull(bio = BIO_new_mem_buf((void*)msg, 3));
AssertIntEQ(BIO_gets(bio, buffer, 3), 2);
AssertIntEQ(buffer[0], msg[0]);
AssertIntEQ(buffer[1], msg[1]);
AssertIntNE(buffer[2], msg[2]);
BIO_free(bio);
msg[3] = 0x33;
buffer[3] = 0x33;
AssertNotNull(bio = BIO_new_mem_buf((void*)msg, 3));
AssertIntEQ(BIO_gets(bio, buffer, bufferSz), 3);
AssertIntEQ(buffer[0], msg[0]);
AssertIntEQ(buffer[1], msg[1]);
AssertIntEQ(buffer[2], msg[2]);
AssertIntNE(buffer[3], 0x33); /* make sure null terminator was set */
/* check reading an empty string */
BIO_free(bio);
AssertNotNull(bio = BIO_new_mem_buf((void*)emp, sizeof(emp)));
AssertIntEQ(BIO_gets(bio, buffer, bufferSz), 1); /* just terminator */
AssertStrEQ(emp, buffer);
/* check error cases */
BIO_free(bio);
AssertIntEQ(BIO_gets(NULL, NULL, 0), SSL_FAILURE);
AssertNotNull(bio = BIO_new(BIO_s_mem()));
AssertIntEQ(BIO_gets(bio, buffer, 2), -1); /* nothing to read */
#if !defined(NO_FILESYSTEM)
{
BIO* f_bio;
XFILE f;
AssertNotNull(f_bio = BIO_new(BIO_s_file()));
AssertIntLE(BIO_gets(f_bio, buffer, bufferSz), 0);
f = XFOPEN(svrCertFile, "rb");
AssertIntEQ((int)BIO_set_fp(f_bio, f, BIO_CLOSE), SSL_SUCCESS);
AssertIntGT(BIO_gets(f_bio, buffer, bufferSz), 0);
BIO_free(f_bio);
}
#endif /* NO_FILESYSTEM */
BIO_free(bio);
BIO_free(bio2);
/* try with type BIO */
XMEMCPY(msg, "\nhello wolfSSL\n security plus\t---...**adf\na...b.c",
sizeof(msg));
AssertNotNull(bio = BIO_new(BIO_s_bio()));
AssertNotNull(bio2 = BIO_new(BIO_s_bio()));
AssertIntEQ(BIO_set_write_buf_size(bio, 10), SSL_SUCCESS);
AssertIntEQ(BIO_set_write_buf_size(bio2, sizeof(msg)), SSL_SUCCESS);
AssertIntEQ(BIO_make_bio_pair(bio, bio2), SSL_SUCCESS);
AssertIntEQ(BIO_write(bio2, msg, sizeof(msg)), sizeof(msg));
AssertIntEQ(BIO_gets(bio, buffer, -3), 0);
AssertIntEQ(BIO_gets(bio, buffer, bufferSz), 1);
AssertIntEQ(BIO_gets(bio, buffer, bufferSz), 14);
AssertStrEQ(buffer, "hello wolfSSL\n");
AssertIntEQ(BIO_gets(bio, buffer, bufferSz), 19);
AssertIntEQ(BIO_gets(bio, buffer, bufferSz), 8);
AssertIntEQ(BIO_gets(bio, buffer, -1), 0);
BIO_free(bio); BIO_free(bio);
BIO_free(bio2); BIO_free(bio2);

View File

@ -756,8 +756,14 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_size(WOLFSSL_EVP_PKEY *pkey)
#endif /* NO_RSA */ #endif /* NO_RSA */
case EVP_PKEY_EC: case EVP_PKEY_EC:
WOLFSSL_MSG("not implemented"); #ifdef HAVE_ECC
/* not implemented */ if (pkey->ecc == NULL || pkey->ecc->internal == NULL) {
WOLFSSL_MSG("No ECC key has been set");
return 0;
}
return wc_ecc_size((ecc_key*)(pkey->ecc->internal));
#endif /* HAVE_ECC */
default: default:
return 0; return 0;
} }

View File

@ -531,11 +531,6 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX;
/* yassl had set the default to be 500 */ /* yassl had set the default to be 500 */
#define SSL_get_default_timeout(ctx) 500 #define SSL_get_default_timeout(ctx) 500
/* Lighthttp compatibility */
#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \
defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
defined(HAVE_POCO_LIB) || defined(WOLFSSL_HAPROXY)
typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY;
#define X509_NAME_free wolfSSL_X509_NAME_free #define X509_NAME_free wolfSSL_X509_NAME_free
@ -604,7 +599,6 @@ enum {
#define sk_SSL_COMP_zero wolfSSL_sk_SSL_COMP_zero #define sk_SSL_COMP_zero wolfSSL_sk_SSL_COMP_zero
#define sk_SSL_CIPHER_value wolfSSL_sk_SSL_CIPHER_value #define sk_SSL_CIPHER_value wolfSSL_sk_SSL_CIPHER_value
#endif /* WOLFSSL_HAPROXY */ #endif /* WOLFSSL_HAPROXY */
#endif /* HAVE_STUNNEL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */
#define SSL_CTX_set_tmp_dh wolfSSL_CTX_set_tmp_dh #define SSL_CTX_set_tmp_dh wolfSSL_CTX_set_tmp_dh

View File

@ -207,6 +207,10 @@ typedef struct WOLFSSL_EVP_PKEY {
WOLFSSL_RSA* rsa; WOLFSSL_RSA* rsa;
byte ownRsa; /* if struct owns RSA and should free it */ byte ownRsa; /* if struct owns RSA and should free it */
#endif #endif
#ifdef HAVE_ECC
WOLFSSL_EC_KEY* ecc;
byte ownEcc; /* if struct owns ECC and should free it */
#endif
WC_RNG rng; WC_RNG rng;
#endif #endif
#ifdef HAVE_ECC #ifdef HAVE_ECC