Add wolfSSL_EVP_Encode/Decode APIs

pull/3793/head
TakayukiMatsuo 2021-02-22 17:51:44 +09:00
parent 41c4a25b25
commit 49d1b859d4
3 changed files with 947 additions and 0 deletions

View File

@ -2393,6 +2393,488 @@ static void test_ED448(void)
| EVP
*----------------------------------------------------------------------------*/
/* Test functions for base64 encode/decode */
static void test_wolfSSL_EVP_ENCODE_CTX_new(void)
{
#if defined(OPENSSL_EXTRA) && \
( defined(WOLFSSL_BASE64_ENCODE) || defined(WOLFSSL_BASE64_DECODE))
printf(testingFmt, "wolfSSL_EVP_ENCODE_CTX_new()");
WOLFSSL_EVP_ENCODE_CTX* ctx = NULL;
AssertNotNull( ctx = wolfSSL_EVP_ENCODE_CTX_new());
AssertIntEQ( ctx->remaining,0);
AssertIntEQ( ctx->data[0],0);
AssertIntEQ( ctx->data[sizeof(ctx->data) -1],0);
wolfSSL_EVP_ENCODE_CTX_free(ctx);
printf(resultFmt, passed);
#endif /* OPENSSL_EXTRA && (WOLFSSL_BASE64_ENCODE || WOLFSSL_BASE64_DECODE)*/
}
static void test_wolfSSL_EVP_ENCODE_CTX_free(void)
{
#if defined(OPENSSL_EXTRA) && \
( defined(WOLFSSL_BASE64_ENCODE) || defined(WOLFSSL_BASE64_DECODE))
printf(testingFmt, "wolfSSL_EVP_ENCODE_CTX_free()");
WOLFSSL_EVP_ENCODE_CTX* ctx = NULL;
AssertNotNull( ctx = wolfSSL_EVP_ENCODE_CTX_new());
wolfSSL_EVP_ENCODE_CTX_free(ctx);
printf(resultFmt, passed);
#endif /*OPENSSL_EXTRA && (WOLFSSL_BASE64_ENCODE || WOLFSSL_BASE64_DECODE)*/
}
static void test_wolfSSL_EVP_EncodeInit(void)
{
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_BASE64_ENCODE)
printf(testingFmt, "wolfSSL_EVP_EncodeInit()");
WOLFSSL_EVP_ENCODE_CTX* ctx = NULL;
AssertNotNull( ctx = wolfSSL_EVP_ENCODE_CTX_new());
AssertIntEQ( ctx->remaining,0);
AssertIntEQ( ctx->data[0],0);
AssertIntEQ( ctx->data[sizeof(ctx->data) -1],0);
/* make ctx dirty */
ctx->remaining = 10;
XMEMSET( ctx->data, 0x77, sizeof(ctx->data));
wolfSSL_EVP_EncodeInit(ctx);
AssertIntEQ( ctx->remaining,0);
AssertIntEQ( ctx->data[0],0);
AssertIntEQ( ctx->data[sizeof(ctx->data) -1],0);
wolfSSL_EVP_ENCODE_CTX_free(ctx);
printf(resultFmt, passed);
#endif /* OPENSSL_EXTRA && WOLFSSL_BASE64_ENCODE*/
}
static void test_wolfSSL_EVP_EncodeUpdate(void)
{
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_BASE64_ENCODE)
printf(testingFmt, "wolfSSL_EVP_EncodeUpdate()");
int outl;
int total;
const unsigned char plain0[] = {"Th"};
const unsigned char plain1[] = {"This is a base64 encodeing test."};
const unsigned char plain2[] = {"This is additional data."};
const unsigned char enc0[] = {"VGg=\n"};
/* expected encoded result for the first output 64 chars plus trailing LF*/
const unsigned char enc1[] = {"VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVpbmcgdGVzdC5UaGlzIGlzIGFkZGl0aW9u\n"};
const unsigned char enc2[] =
{"VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVpbmcgdGVzdC5UaGlzIGlzIGFkZGl0aW9u\nYWwgZGF0YS4=\n"};
unsigned char encOutBuff[300];
WOLFSSL_EVP_ENCODE_CTX* ctx = NULL;
AssertNotNull( ctx = wolfSSL_EVP_ENCODE_CTX_new());
wolfSSL_EVP_EncodeInit(ctx);
/* illegal parameter test */
AssertIntEQ(
wolfSSL_EVP_EncodeUpdate(
NULL, /* pass NULL as ctx */
encOutBuff,
&outl,
plain1,
sizeof(plain1)-1),
0 /* expected result code 0: fail */
);
AssertIntEQ(
wolfSSL_EVP_EncodeUpdate(
ctx,
NULL, /* pass NULL as out buff */
&outl,
plain1,
sizeof(plain1)-1),
0 /* expected result code 0: fail */
);
AssertIntEQ(
wolfSSL_EVP_EncodeUpdate(
ctx,
encOutBuff,
NULL, /* pass NULL as outl */
plain1,
sizeof(plain1)-1),
0 /* expected result code 0: fail */
);
AssertIntEQ(
wolfSSL_EVP_EncodeUpdate(
ctx,
encOutBuff,
&outl,
NULL, /* pass NULL as in */
sizeof(plain1)-1),
0 /* expected result code 0: fail */
);
/* meaningless parameter test */
AssertIntEQ(
wolfSSL_EVP_EncodeUpdate(
ctx,
encOutBuff,
&outl,
plain1,
0), /* pass zero input */
1 /* expected result code 1: success */
);
/* very small data encoding test */
wolfSSL_EVP_EncodeInit(ctx);
AssertIntEQ(
wolfSSL_EVP_EncodeUpdate(
ctx,
encOutBuff,
&outl,
plain0,
sizeof(plain0)-1),
1 /* expected result code 1: success */
);
AssertIntEQ(outl,0);
wolfSSL_EVP_EncodeFinal(
ctx,
encOutBuff + outl,
&outl);
AssertIntEQ( outl, sizeof(enc0)-1);
AssertIntEQ(
XSTRNCMP(
(const char*)encOutBuff,
(const char*)enc0,sizeof(enc0) ),
0);
/* pass small size( < 48bytes ) input, then make sure they are not
* encoded and just stored in ctx
*/
wolfSSL_EVP_EncodeInit(ctx);
total = 0;
outl = 0;
XMEMSET( encOutBuff,0, sizeof(encOutBuff));
AssertIntEQ(
wolfSSL_EVP_EncodeUpdate(
ctx,
encOutBuff, /* buffer for output */
&outl, /* size of output */
plain1, /* input */
sizeof(plain1)-1), /* size of input */
1); /* expected result code 1:success */
total += outl;
AssertIntEQ(outl, 0); /* no output expected */
AssertIntEQ(ctx->remaining, sizeof(plain1) -1);
AssertTrue(
XSTRNCMP((const char*)(ctx->data),
(const char*)plain1,
ctx->remaining) ==0 );
AssertTrue(encOutBuff[0] == 0);
/* call wolfSSL_EVP_EncodeUpdate again to make it encode
* the stored data and the new input together
*/
AssertIntEQ(
wolfSSL_EVP_EncodeUpdate(
ctx,
encOutBuff + outl, /* buffer for output */
&outl, /* size of output */
plain2, /* additional input */
sizeof(plain2) -1), /* size of additional input */
1); /* expected result code 1:success */
total += outl;
AssertIntNE(outl, 0); /* some output is expected this time*/
AssertIntEQ(outl, BASE64_ENCODED_BLOCK_SIZE +1); /* 64 bytes and LF */
AssertIntEQ(
XSTRNCMP((const char*)encOutBuff,(const char*)enc1,sizeof(enc1) ),0);
/* call wolfSSL_EVP_EncodeFinal to flush all the unprocessed input */
wolfSSL_EVP_EncodeFinal(
ctx,
encOutBuff + outl,
&outl);
total += outl;
AssertIntNE(outl,0);
AssertIntEQ(XSTRNCMP(
(const char*)encOutBuff,(const char*)enc2,sizeof(enc2) ),0);
wolfSSL_EVP_ENCODE_CTX_free(ctx);
printf(resultFmt, passed);
#endif /* OPENSSL_EXTRA && WOLFSSL_BASE64_ENCODE*/
}
static void test_wolfSSL_EVP_EncodeFinal(void)
{
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_BASE64_ENCODE)
printf(testingFmt, "wolfSSL_EVP_EncodeFinal()");
/* tests for wolfSSL_EVP_EncodeFinal are included in
* test_wolfSSL_EVP_EncodeUpdate
*/
printf(resultFmt, passed);
#endif /* OPENSSL_EXTRA && WOLFSSL_BASE64_ENCODE*/
}
static void test_wolfSSL_EVP_DecodeInit(void)
{
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_BASE64_DECODE)
printf(testingFmt, "wolfSSL_EVP_DecodeInit()");
WOLFSSL_EVP_ENCODE_CTX* ctx = NULL;
AssertNotNull( ctx = wolfSSL_EVP_ENCODE_CTX_new());
AssertIntEQ( ctx->remaining,0);
AssertIntEQ( ctx->data[0],0);
AssertIntEQ( ctx->data[sizeof(ctx->data) -1],0);
/* make ctx dirty */
ctx->remaining = 10;
XMEMSET( ctx->data, 0x77, sizeof(ctx->data));
wolfSSL_EVP_DecodeInit(ctx);
AssertIntEQ( ctx->remaining,0);
AssertIntEQ( ctx->data[0],0);
AssertIntEQ( ctx->data[sizeof(ctx->data) -1],0);
wolfSSL_EVP_ENCODE_CTX_free(ctx);
printf(resultFmt, passed);
#endif /* OPENSSL && WOLFSSL_BASE_DECODE */
}
static void test_wolfSSL_EVP_DecodeUpdate(void)
{
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_BASE64_DECODE)
printf(testingFmt, "wolfSSL_EVP_DecodeUpdate()");
int outl;
unsigned char decOutBuff[300];
WOLFSSL_EVP_ENCODE_CTX* ctx = wolfSSL_EVP_ENCODE_CTX_new();
wolfSSL_EVP_DecodeInit(ctx);
const unsigned char enc1[] = {"VGhpcyBpcyBhIGJhc2U2NCBkZWNvZGluZyB0ZXN0Lg==\n"};
/* const unsigned char plain1[] =
{"This is a base64 decoding test."} */
/* illegal parameter tests */
/* pass NULL as ctx */
AssertIntEQ(
wolfSSL_EVP_DecodeUpdate(
NULL, /* pass NULL as ctx */
decOutBuff,
&outl,
enc1,
sizeof(enc1)-1),
-1 /* expected result code -1: fail */
);
AssertIntEQ( outl, 0);
/* pass NULL as output */
AssertIntEQ(
wolfSSL_EVP_DecodeUpdate(
ctx,
NULL, /* pass NULL as out buff */
&outl,
enc1,
sizeof(enc1)-1),
-1 /* expected result code -1: fail */
);
AssertIntEQ( outl, 0);
/* pass NULL as outl */
AssertIntEQ(
wolfSSL_EVP_DecodeUpdate(
ctx,
decOutBuff,
NULL, /* pass NULL as outl */
enc1,
sizeof(enc1)-1),
-1 /* expected result code -1: fail */
);
/* pass NULL as input */
AssertIntEQ(
wolfSSL_EVP_DecodeUpdate(
ctx,
decOutBuff,
&outl,
NULL, /* pass NULL as in */
sizeof(enc1)-1),
-1 /* expected result code -1: fail */
);
AssertIntEQ( outl, 0);
/* pass zero length input */
AssertIntEQ(
wolfSSL_EVP_DecodeUpdate(
ctx,
decOutBuff,
&outl,
enc1,
0), /* pass zero as input len */
1 /* expected result code 1: success */
);
/* decode correct base64 string */
const unsigned char enc2[] = {"VGhpcyBpcyBhIGJhc2U2NCBkZWNvZGluZyB0ZXN0Lg==\n"};
const unsigned char plain2[] =
{"This is a base64 decoding test."};
wolfSSL_EVP_EncodeInit(ctx);
AssertIntEQ(
wolfSSL_EVP_DecodeUpdate(
ctx,
decOutBuff,
&outl,
enc2,
sizeof(enc2)-1),
0 /* expected result code 0: success */
);
AssertIntEQ(outl,sizeof(plain2) -1);
AssertIntEQ(
wolfSSL_EVP_DecodeFinal(
ctx,
decOutBuff + outl,
&outl),
1 /* expected result code 1: success */
);
AssertIntEQ(outl, 0); /* expected DecodeFinal outout no data */
AssertIntEQ(XSTRNCMP( (const char*)plain2,(const char*)decOutBuff,
sizeof(plain2) -1 ),0);
/* decode correct base64 string which does not have '\n' in its last*/
const unsigned char enc3[] = {"VGhpcyBpcyBhIGJhc2U2NCBkZWNvZGluZyB0ZXN0Lg=="}; /* 44 chars */
const unsigned char plain3[] =
{"This is a base64 decoding test."}; /* 31 chars */
wolfSSL_EVP_EncodeInit(ctx);
AssertIntEQ(
wolfSSL_EVP_DecodeUpdate(
ctx,
decOutBuff,
&outl,
enc3,
sizeof(enc3)-1),
0 /* expected result code 0: success */
);
AssertIntEQ(outl,sizeof(plain3)-1); /* 31 chars should be output */
AssertIntEQ(XSTRNCMP( (const char*)plain3,(const char*)decOutBuff,
sizeof(plain3) -1 ),0);
AssertIntEQ(
wolfSSL_EVP_DecodeFinal(
ctx,
decOutBuff + outl,
&outl),
1 /* expected result code 1: success */
);
AssertIntEQ(outl,0 );
/* decode string which has a padding char ('=') in the illegal position*/
const unsigned char enc4[] = {"VGhpcyBpcyBhIGJhc2U2N=CBkZWNvZGluZyB0ZXN0Lg==\n"};
/* ^-- illegal padding */
wolfSSL_EVP_EncodeInit(ctx);
AssertIntEQ(
wolfSSL_EVP_DecodeUpdate(
ctx,
decOutBuff,
&outl,
enc4,
sizeof(enc4)-1),
-1 /* expected result code -1: error */
);
AssertIntEQ(outl,0);
/* small data decode test */
const unsigned char enc00[] = {"VG"};
const unsigned char enc01[] = {"g=\n"};
const unsigned char plain4[] = {"Th"};
wolfSSL_EVP_EncodeInit(ctx);
AssertIntEQ(
wolfSSL_EVP_DecodeUpdate(
ctx,
decOutBuff,
&outl,
enc00,
sizeof(enc00)-1),
1 /* expected result code 1: success */
);
AssertIntEQ(outl,0);
AssertIntEQ(
wolfSSL_EVP_DecodeUpdate(
ctx,
decOutBuff + outl,
&outl,
enc01,
sizeof(enc01)-1),
0 /* expected result code 0: success */
);
AssertIntEQ(outl,sizeof(plain4)-1);
wolfSSL_EVP_DecodeFinal(
ctx,
decOutBuff + outl,
&outl);
AssertIntEQ( outl, 0);
AssertIntEQ(
XSTRNCMP(
(const char*)decOutBuff,
(const char*)plain4,sizeof(plain4)-1 ),
0);
wolfSSL_EVP_ENCODE_CTX_free(ctx);
printf(resultFmt, passed);
#endif /* OPENSSL && WOLFSSL_BASE_DECODE */
}
static void test_wolfSSL_EVP_DecodeFinal(void)
{
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_BASE64_DECODE)
printf(testingFmt, "wolfSSL_EVP_DecodeFinal()");
/* tests for wolfSSL_EVP_DecodeFinal are included in
* test_wolfSSL_EVP_DecodeUpdate
*/
printf(resultFmt, passed);
#endif /* OPENSSL && WOLFSSL_BASE_DECODE */
}
/* Test function for wolfSSL_EVP_get_cipherbynid.
*/
@ -40399,6 +40881,14 @@ void ApiTest(void)
test_wolfSSL_EVP_MD_hmac_signing();
test_wolfSSL_EVP_MD_rsa_signing();
test_wolfSSL_EVP_MD_ecc_signing();
test_wolfSSL_EVP_ENCODE_CTX_new();
test_wolfSSL_EVP_ENCODE_CTX_free();
test_wolfSSL_EVP_EncodeInit();
test_wolfSSL_EVP_EncodeUpdate();
test_wolfSSL_EVP_EncodeFinal();
test_wolfSSL_EVP_DecodeInit();
test_wolfSSL_EVP_DecodeUpdate();
test_wolfSSL_EVP_DecodeFinal();
test_wolfSSL_CTX_add_extra_chain_cert();
#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
test_wolfSSL_ERR_peek_last_error_line();

View File

@ -6878,6 +6878,410 @@ int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp,
}
#endif /* !defined(NO_PWDBASED) */
/* Base64 encoding APIs */
#if defined(WOLFSSL_BASE64_ENCODE) || defined(WOLFSSL_BASE64_DECODE)
static WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new_ex(void* heap);
WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new(void)
{
return wolfSSL_EVP_ENCODE_CTX_new_ex(NULL);
}
static WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new_ex(void* heap)
{
WOLFSSL_ENTER("wolfSSL_EVP_ENCODE_CTX_new");
WOLFSSL_EVP_ENCODE_CTX* ctx = (WOLFSSL_EVP_ENCODE_CTX*)XMALLOC( sizeof(WOLFSSL_EVP_ENCODE_CTX),heap,DYNAMIC_TYPE_OPENSSL );
if(ctx != NULL) {
XMEMSET(ctx,0,sizeof(WOLFSSL_EVP_ENCODE_CTX) );
ctx->heap = heap;
return ctx;
}
return NULL;
}
void wolfSSL_EVP_ENCODE_CTX_free(WOLFSSL_EVP_ENCODE_CTX* ctx)
{
WOLFSSL_ENTER("wolfSSL_EVP_ENCODE_CTX_free");
if(ctx != NULL) {
XFREE(ctx,ctx->heap,DYNAMIC_TYPE_OPENSSL);
}
}
#endif /* WOLFSSL_BASE64_ENCODE || WOLFSSL_BASE64_DECODE */
#if defined(WOLFSSL_BASE64_ENCODE)
void wolfSSL_EVP_EncodeInit(WOLFSSL_EVP_ENCODE_CTX* ctx)
{
WOLFSSL_ENTER("wolfSSL_EVP_EncodeInit");
/* clean up ctx */
if(ctx != NULL) {
ctx->remaining = 0;
XMEMSET(ctx->data,0, sizeof(ctx->data));
}
}
int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx,
unsigned char*out, int *outl, const unsigned char*in, int inl)
{
int cpysz;
int res;
word32 outsz = 0;
WOLFSSL_ENTER("wolfSSL_EVP_EncodeUpdate");
if( ctx == NULL || out == NULL || in == NULL || outl == NULL )
return 0;
*outl = 0;
/* if the remaining data exit in the ctx, add input data to them to create a block(48bytes) for encoding*/
if( ctx->remaining > 0 && inl > 0) {
cpysz = min( (BASE64_ENCODE_BLOCK_SIZE - ctx->remaining), inl );
XMEMCPY( ctx->data + ctx->remaining, in, cpysz);
ctx->remaining += cpysz;
in += cpysz;
inl -= cpysz;
/* check if a block for encoding exists in ctx.data, if so encode it */
if( ctx->remaining >= BASE64_ENCODE_BLOCK_SIZE ) {
/* Base64_Encode asks the out buff size via the 4th param*/
outsz = BASE64_ENCODED_BLOCK_SIZE + 1;
res = Base64_Encode(ctx->data, BASE64_ENCODE_BLOCK_SIZE, out, &outsz);
if( res == 0)
*outl = outsz;
else
return 0; /* return with error */
}
else {
/* could not create a block */
*outl = 0;
return 1;
}
}
/* Here, there is no data left in ctx, so try processing the data of the specified input data. */
while( inl >= BASE64_ENCODE_BLOCK_SIZE) {
outsz = BASE64_ENCODED_BLOCK_SIZE + 1; /* 64 byte and one for LF*/
res = Base64_Encode( in, BASE64_ENCODE_BLOCK_SIZE,out,&outsz);
if( res == 0) {
in += BASE64_ENCODE_BLOCK_SIZE;
inl -= BASE64_ENCODE_BLOCK_SIZE;
out += outsz;
*outl += outsz;
}
else {
*outl = 0;
return 0;
}
}
/* if remaining data exit, copy them into ctx for the next call*/
if( inl > 0 ) {
XMEMSET( ctx->data,0,sizeof(ctx->data));
XMEMCPY( ctx->data, in, inl);
ctx->remaining = inl;
}
return 1; /* returns 1 on success, 0 on error */
}
void wolfSSL_EVP_EncodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx,
unsigned char*out, int *outl)
{
word32 outsz = 0;
int res;
WOLFSSL_ENTER("wolfSSL_EVP_EncodeFinal");
if( outl == NULL)
return;
if( ctx == NULL || out == NULL ) {
*outl = 0;
return;
}
/* process remaining data in ctx */
outsz = BASE64_ENCODED_BLOCK_SIZE + 1; /* 64 byte and one for LF*/
res = Base64_Encode( ctx->data, ctx->remaining ,out, &outsz);
if( res == 0)
*outl = outsz;
else
*outl = 0;
ctx->remaining = 0;
XMEMSET( ctx->data,0,sizeof(ctx->data));
return;
}
#endif /* WOLFSSL_BASE64_ENCODE */
#if defined(WOLFSSL_BASE64_DECODE)
/* borrowed from coding.c */
static WC_INLINE int Base64_SkipNewline(const byte* in, word32* inLen,
word32* outJ)
{
word32 len = *inLen;
word32 j = *outJ;
if (len && (in[j] == ' ' || in[j] == '\r' || in[j] == '\n')) {
byte endLine = in[j++];
len--;
while (len && endLine == ' ') { /* allow trailing whitespace */
endLine = in[j++];
len--;
}
if (endLine == '\r') {
if (len) {
endLine = in[j++];
len--;
}
}
if (endLine != '\n') {
WOLFSSL_MSG("Bad end of line in Base64 Decode");
return ASN_INPUT_E;
}
}
if (!len) {
return BUFFER_E;
}
*inLen = len;
*outJ = j;
return 0;
}
void wolfSSL_EVP_DecodeInit(WOLFSSL_EVP_ENCODE_CTX* ctx)
{
WOLFSSL_ENTER("wolfSSL_EVP_DecodeInit");
/* clean up ctx */
if(ctx != NULL) {
ctx->remaining = 0;
XMEMSET(ctx->data,0, sizeof(ctx->data));
}
}
int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx,
unsigned char*out, int *outl, const unsigned char*in, int inl)
{
word32 outsz = 0;
word32 j = 0;
word32 inLen;
int res;
int pad = 0;
WOLFSSL_ENTER("wolfSSL_EVP_DecodeUpdate");
if (outl == NULL)
return -1;
if (ctx == NULL || out == NULL || in == NULL ) {
*outl = 0;
return -1;
}
if (inl == 0) {
*outl = 0;
return 1;
}
inLen = inl;
*outl = 0;
/* if the remaining data exist in the ctx, add input data to them to create
a block(4bytes) for decoding*/
if( ctx->remaining > 0 && inl > 0) {
int cpysz;
unsigned char e;
cpysz = min( (BASE64_DECODE_BLOCK_SIZE - ctx->remaining), inl );
for (int i = 0; cpysz > 0 && inLen > 0;i++) {
if ((res = Base64_SkipNewline(in, &inLen, &j))
== ASN_INPUT_E) {
return -1; /* detected an illegal char in input */
}
e = in[j++];
if (e == '=')
pad = 1;
*(ctx->data + ctx->remaining + i) = e;
inLen--;
cpysz--;
}
outsz = sizeof(ctx->data);
res = Base64_Decode( ctx->data, BASE64_DECODE_BLOCK_SIZE, out, &outsz);
if (res == 0) {
*outl += outsz;
out += outsz;
ctx->remaining = 0;
XMEMSET(ctx->data, 0, sizeof(ctx->data));
}
else {
*outl = 0;
return -1; /* return with error */
}
}
/* process data in input buffer */
while (inLen > 3) {
int pad3 = 0;
int pad4 = 0;
byte e[4];
if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) {
if (res == BUFFER_E) {
break;
}
else {
*outl = 0;
return -1;
}
}
e[0] = in[j++];
if (e[0] == '\0') {
break;
}
inLen--;
if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) {
if (res == BUFFER_E) {
break;
}
else {
*outl = 0;
return -1;
}
}
e[1] = in[j++];
inLen--;
if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) {
if (res == BUFFER_E) {
break;
}
else {
*outl = 0;
return -1;
}
}
e[2] = in[j++];
inLen--;
if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) {
if (res == BUFFER_E) {
break;
}
else {
*outl = 0;
return -1;
}
}
e[3] = in[j++];
inLen--;
if (e[0] == '=')
pad = 1;
if (e[1] == '=')
pad = 1;
if (e[2] == '=') {
pad = 1;
pad3 = 1;
}
if (e[3] == '=') {
pad = 1;
pad4 = 1;
}
if (pad3 && !pad4) {
*outl = 0;
return -1;
}
/* decode four bytes */
outsz = sizeof(ctx->data);
res = Base64_Decode( e, BASE64_DECODE_BLOCK_SIZE, out, &outsz);
if (res == ASN_INPUT_E) {
*outl = 0;
return -1;
}
*outl += outsz;
out += outsz;
}
/* copy left data to ctx */
if (inLen > 0) {
XMEMSET(ctx->data, 0, sizeof(ctx->data));
int i = 0;
unsigned char e;
while ( inLen > 0) {
e = in[j++];
if (e== '\n' || e == '\r' || e == ' ') {
inLen--;
continue;
}
if (e == '=') {
pad = 1;
}
ctx->data[i++] = e;
ctx->remaining++;
inLen--;
}
if (pad)
return 0; /* indicates that clients should call DecodeFinal */
else
return 1;
}
/* if the last data is '\n', remove it */
char e = in[j - 1];
if (e == '\n') {
e = (in[j - 2]);
if (e == '=')
return 0;
else
return 1;
}
if (e == '=')
return 0;
else
return 1;
}
int wolfSSL_EVP_DecodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx,
unsigned char*out, int *outl)
{
word32 outsz = 0;
word32 inLen;
word32 j = 0;
int res;
WOLFSSL_ENTER("wolfSSL_EVP_DecodeFinal");
if (ctx != NULL) {
if (ctx->remaining > 0) {
inLen = ctx->remaining;
if ((res = Base64_SkipNewline(ctx->data, &inLen, &j)) != 0) {
*outl = 0;
if (res == BUFFER_E)
return 1;
else
return -1;
}
outsz = ctx->remaining;
res = Base64_Decode(ctx->data, ctx->remaining, out, &outsz);
if (res == 0) {
*outl = outsz;
return 1;
}
else {
*outl = 0;
return 0;
}
}
else {
*outl = 0;
return 1;
}
}
return -1;
}
#endif /* WOLFSSL_BASE64_DECODE */
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
#endif /* WOLFSSL_EVP_INCLUDED */

View File

@ -59,6 +59,10 @@
#endif
#include <wolfssl/wolfcrypt/pwdbased.h>
#if defined(WOLFSSL_BASE64_ENCODE) || defined(WOLFSSL_BASE64_DECODE)
#include <wolfssl/wolfcrypt/coding.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -372,6 +376,39 @@ struct WOLFSSL_EVP_PKEY_CTX {
int nbits;
};
#if defined(WOLFSSL_BASE64_ENCODE) || defined(WOLFSSL_BASE64_DECODE)
#define BASE64_ENCODE_BLOCK_SIZE 48
#define BASE64_ENCODED_BLOCK_SIZE 64
#define BASE64_DECODE_BLOCK_SIZE 4
typedef struct WOLFSSL_EVP_ENCODE_CTX
{
void* heap;
int remaining; /* num of bytes in data[] */
byte data[128]; /* storage for unprocessed raw data */
}WOLFSSL_EVP_ENCODE_CTX;
WOLFSSL_API WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new(void);
WOLFSSL_API void wolfSSL_EVP_ENCODE_CTX_free(WOLFSSL_EVP_ENCODE_CTX* ctx);
#endif /* WOLFSSL_BASE64_ENCODE || WOLFSSL_BASE64_DECODE */
#if defined(WOLFSSL_BASE64_ENCODE)
WOLFSSL_API void wolfSSL_EVP_EncodeInit(WOLFSSL_EVP_ENCODE_CTX* ctx);
WOLFSSL_API int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx,
unsigned char*out, int *outl, const unsigned char*in, int inl);
WOLFSSL_API void wolfSSL_EVP_EncodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx,
unsigned char*out, int *outl);
#endif /* WOLFSSL_BASE64_ENCODE */
#if defined(WOLFSSL_BASE64_DECODE)
WOLFSSL_API void wolfSSL_EVP_DecodeInit(WOLFSSL_EVP_ENCODE_CTX* ctx);
WOLFSSL_API int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx,
unsigned char*out, int *outl, const unsigned char*in, int inl);
WOLFSSL_API int wolfSSL_EVP_DecodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx,
unsigned char*out, int *outl);
#endif /* WOLFSSL_BASE64_DECODE */
typedef int WOLFSSL_ENGINE ;
typedef WOLFSSL_ENGINE ENGINE;
typedef WOLFSSL_EVP_PKEY_CTX EVP_PKEY_CTX;
@ -937,6 +974,22 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX;
#define EVP_MD_name(x) x
#define EVP_CIPHER_nid wolfSSL_EVP_CIPHER_nid
/* Base64 encoding/decoding APIs */
#if defined(WOLFSSL_BASE64_ENCODE) || defined(WOLFSSL_BASE64_DECODE)
#define EVP_ENCODE_CTX WOLFSSL_EVP_ENCODE_CTX
#define EVP_ENCODE_CTX_new wolfSSL_EVP_ENCODE_CTX_new
#define EVP_ENCODE_CTX_free wolfSSL_EVP_ENCODE_CTX_free
#endif /* WOLFSSL_BASE64_ENCODE || WOLFSSL_BASE64_DECODE*/
#if defined(WOLFSSL_BASE64_ENCODE)
#define EVP_EncodeInit wolfSSL_EVP_EncodeInit
#define EVP_EncodeUpdate wolfSSL_EVP_EncodeUpdate
#define EVP_EncodeFinal wolfSSL_EVP_EncodeFinal
#endif /* WOLFSSL_BASE64_ENCODE */
#if defined(WOLFSSL_BASE64_DECODE)
#define EVP_DecodeInit wolfSSL_EVP_DecodeInit
#define EVP_DecodeUpdate wolfSSL_EVP_DecodeUpdate
#define EVP_DecodeFinal wolfSSL_EVP_DecodeFinal
#endif /* WOLFSSL_BASE64_DECODE */
WOLFSSL_API void printPKEY(WOLFSSL_EVP_PKEY *k);