From 49d1b859d4035d841b31636fd15e2e4206b09e93 Mon Sep 17 00:00:00 2001 From: TakayukiMatsuo Date: Mon, 22 Feb 2021 17:51:44 +0900 Subject: [PATCH 1/9] Add wolfSSL_EVP_Encode/Decode APIs --- tests/api.c | 490 ++++++++++++++++++++++++++++++++++++++++++ wolfcrypt/src/evp.c | 404 ++++++++++++++++++++++++++++++++++ wolfssl/openssl/evp.h | 53 +++++ 3 files changed, 947 insertions(+) diff --git a/tests/api.c b/tests/api.c index 6a2283663..0d554d583 100644 --- a/tests/api.c +++ b/tests/api.c @@ -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(); diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 8f4471e80..e821cda46 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -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 */ diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index 98cc122f0..0885379e2 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -59,6 +59,10 @@ #endif #include +#if defined(WOLFSSL_BASE64_ENCODE) || defined(WOLFSSL_BASE64_DECODE) +#include +#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); From b495e121795c6916516224ca2100ed1ad128e3c5 Mon Sep 17 00:00:00 2001 From: TakayukiMatsuo Date: Tue, 23 Feb 2021 02:29:37 +0900 Subject: [PATCH 2/9] Fix such as "for loop initial declaration" --- tests/api.c | 1 + wolfcrypt/src/evp.c | 39 ++++++++++++++++++++------------------- wolfssl/openssl/evp.h | 8 ++++---- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/tests/api.c b/tests/api.c index 0d554d583..830b0ef72 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2610,6 +2610,7 @@ static void test_wolfSSL_EVP_EncodeUpdate(void) total += outl; + AssertIntNE(total,0); AssertIntNE(outl,0); AssertIntEQ(XSTRNCMP( (const char*)encOutBuff,(const char*)enc2,sizeof(enc2) ),0); diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index e821cda46..0089e5856 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -6880,12 +6880,12 @@ int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp, /* 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) +static struct WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new_ex(void* heap); +struct 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) +static struct 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 ); @@ -7058,6 +7058,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, word32 inLen; int res; int pad = 0; + int i; WOLFSSL_ENTER("wolfSSL_EVP_DecodeUpdate"); @@ -7081,21 +7082,21 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, a block(4bytes) for decoding*/ if( ctx->remaining > 0 && inl > 0) { int cpysz; - unsigned char e; + unsigned char e0; cpysz = min( (BASE64_DECODE_BLOCK_SIZE - ctx->remaining), inl ); - for (int i = 0; cpysz > 0 && inLen > 0;i++) { + for ( 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++]; + e0 = in[j++]; - if (e == '=') + if (e0 == '=') pad = 1; - *(ctx->data + ctx->remaining + i) = e; + *(ctx->data + ctx->remaining + i) = e0; inLen--; cpysz--; } @@ -7202,18 +7203,18 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, if (inLen > 0) { XMEMSET(ctx->data, 0, sizeof(ctx->data)); - int i = 0; - unsigned char e; + i = 0; + unsigned char el; while ( inLen > 0) { - e = in[j++]; - if (e== '\n' || e == '\r' || e == ' ') { + el = in[j++]; + if (el== '\n' || el == '\r' || el == ' ') { inLen--; continue; } - if (e == '=') { + if (el == '=') { pad = 1; } - ctx->data[i++] = e; + ctx->data[i++] = el; ctx->remaining++; inLen--; } @@ -7225,15 +7226,15 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, } /* if the last data is '\n', remove it */ - char e = in[j - 1]; - if (e == '\n') { - e = (in[j - 2]); - if (e == '=') + char es = in[j - 1]; + if (es == '\n') { + es = (in[j - 2]); + if (es == '=') return 0; else return 1; } - if (e == '=') + if (es == '=') return 0; else return 1; diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index 0885379e2..bdee14476 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -382,14 +382,14 @@ struct WOLFSSL_EVP_PKEY_CTX { #define BASE64_ENCODED_BLOCK_SIZE 64 #define BASE64_DECODE_BLOCK_SIZE 4 -typedef struct WOLFSSL_EVP_ENCODE_CTX -{ +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; +}; +typedef struct WOLFSSL_EVP_ENCODE_CTX WOLFSSL_EVP_ENCODE_CTX; -WOLFSSL_API WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new(void); +WOLFSSL_API struct 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 */ From c0a9f86de3647b6a3f37ab13866ba60cc264e42a Mon Sep 17 00:00:00 2001 From: TakayukiMatsuo Date: Wed, 24 Feb 2021 01:33:51 +0900 Subject: [PATCH 3/9] Move some variable declarations to the beginning of the block --- wolfcrypt/src/evp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 0089e5856..b7e3139ec 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -6887,8 +6887,9 @@ struct WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new(void) } static struct WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new_ex(void* heap) { + WOLFSSL_EVP_ENCODE_CTX* ctx = NULL; 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 ); + 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) ); @@ -7059,6 +7060,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, int res; int pad = 0; int i; + char es; WOLFSSL_ENTER("wolfSSL_EVP_DecodeUpdate"); @@ -7201,10 +7203,10 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, } /* copy left data to ctx */ if (inLen > 0) { + unsigned char el; XMEMSET(ctx->data, 0, sizeof(ctx->data)); i = 0; - unsigned char el; while ( inLen > 0) { el = in[j++]; if (el== '\n' || el == '\r' || el == ' ') { @@ -7226,7 +7228,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, } /* if the last data is '\n', remove it */ - char es = in[j - 1]; + es = in[j - 1]; if (es == '\n') { es = (in[j - 2]); if (es == '=') From da75a4f803395c276727a2e02ee803e4ffab39be Mon Sep 17 00:00:00 2001 From: TakayukiMatsuo Date: Thu, 4 Mar 2021 18:39:47 +0900 Subject: [PATCH 4/9] Add comment to each added function and fix return value of wolfSSL_EVP_DecodedFinal --- wolfcrypt/src/evp.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index b7e3139ec..d1f89ff67 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -6881,10 +6881,16 @@ int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp, /* Base64 encoding APIs */ #if defined(WOLFSSL_BASE64_ENCODE) || defined(WOLFSSL_BASE64_DECODE) static struct WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new_ex(void* heap); +/* wolfSSL_EVP_ENCODE_CTX_new allocates WOLFSSL_EVP_ENCODE_CTX + * Returns WOLFSSL_EVP_ENCODE_CTX structure on success, NULL on failure. + */ struct WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new(void) { return wolfSSL_EVP_ENCODE_CTX_new_ex(NULL); } +/* wolfSSL_EVP_ENCODE_CTX_new_ex is a helper function of + * wolfSSL_EVP_ENCODE_CTX_new to allocate WOLFSSL_EVP_ENCODE_CTX structure. + */ static struct WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new_ex(void* heap) { WOLFSSL_EVP_ENCODE_CTX* ctx = NULL; @@ -6898,6 +6904,8 @@ static struct WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new_ex(void* heap) } return NULL; } +/* wolfSSL_EVP_ENCODE_CTX_free frees specified WOLFSSL_EVP_ENCODE_CTX struc. + */ void wolfSSL_EVP_ENCODE_CTX_free(WOLFSSL_EVP_ENCODE_CTX* ctx) { WOLFSSL_ENTER("wolfSSL_EVP_ENCODE_CTX_free"); @@ -6907,6 +6915,9 @@ void wolfSSL_EVP_ENCODE_CTX_free(WOLFSSL_EVP_ENCODE_CTX* ctx) } #endif /* WOLFSSL_BASE64_ENCODE || WOLFSSL_BASE64_DECODE */ #if defined(WOLFSSL_BASE64_ENCODE) +/* wolfSSL_EVP_EncodeInit initializes specified WOLFSSL_EVP_ENCODE_CTX ojbect + * for the subsequent wolfSSL_EVP_EncodeUpdate. + */ void wolfSSL_EVP_EncodeInit(WOLFSSL_EVP_ENCODE_CTX* ctx) { WOLFSSL_ENTER("wolfSSL_EVP_EncodeInit"); @@ -6917,6 +6928,12 @@ void wolfSSL_EVP_EncodeInit(WOLFSSL_EVP_ENCODE_CTX* ctx) XMEMSET(ctx->data,0, sizeof(ctx->data)); } } +/* wolfSSL_EVP_EncodeUpdate encodes the input data in 64-byte units + * and outputs it to out. If less than 64 bytes of data remain, save it in + * ctx. The data given in the subsequent wolfSSL_EVP_EncodeUpdate + * is combined with the data stored in CTX and used for encoding. + * Returns 1 on success, 0 on error. + */ int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, unsigned char*out, int *outl, const unsigned char*in, int inl) { @@ -6981,6 +6998,8 @@ int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, return 1; /* returns 1 on success, 0 on error */ } +/* wolfSSL_EVP_EncodeFinal encodes data in ctx and outputs to out. + */ void wolfSSL_EVP_EncodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx, unsigned char*out, int *outl) { @@ -7042,6 +7061,9 @@ static WC_INLINE int Base64_SkipNewline(const byte* in, word32* inLen, *outJ = j; return 0; } +/* wolfSSL_EVP_DecodeInit initializes specified WOLFSSL_EVP_ENCODE_CTX struct + * for subsequent wolfSSL_EVP_DecodeUpdate. + */ void wolfSSL_EVP_DecodeInit(WOLFSSL_EVP_ENCODE_CTX* ctx) { WOLFSSL_ENTER("wolfSSL_EVP_DecodeInit"); @@ -7051,6 +7073,13 @@ void wolfSSL_EVP_DecodeInit(WOLFSSL_EVP_ENCODE_CTX* ctx) XMEMSET(ctx->data,0, sizeof(ctx->data)); } } +/* wolfSSL_EVP_DecodeUpdate encodes the input data in 4-byte units + * and outputs it to out. If less than 4 bytes of data remain, save it in + * ctx. The data given in the subsequent wolfSSL_EVP_DecodeUpdate + * is combined with the data stored in CTX and used for decoding. + * Returns 1 or 0 on success, -1 on error. Return value 0 indicates that + * clients should call wolfSSL_EVP_DecodeFinal as next call. + */ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, unsigned char*out, int *outl, const unsigned char*in, int inl) { @@ -7242,6 +7271,10 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, return 1; } +/* wolfSSL_EVP_DecodeFinal decode remaining data in ctx + * to outputs to out. + * Returns 1 on success, -1 on failure. + */ int wolfSSL_EVP_DecodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx, unsigned char*out, int *outl) { @@ -7272,7 +7305,7 @@ int wolfSSL_EVP_DecodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx, } else { *outl = 0; - return 0; + return -1; } } else { From 9fd8fde7140d0a808bfa2840950d1d19ecff8a6e Mon Sep 17 00:00:00 2001 From: TakayukiMatsuo Date: Tue, 16 Mar 2021 11:55:18 +0900 Subject: [PATCH 5/9] Add fixes along the review commnents. --- wolfcrypt/src/coding.c | 3 +- wolfcrypt/src/evp.c | 220 ++++++++++++++++--------------------- wolfssl/openssl/evp.h | 2 +- wolfssl/wolfcrypt/coding.h | 2 + 4 files changed, 100 insertions(+), 127 deletions(-) diff --git a/wolfcrypt/src/coding.c b/wolfcrypt/src/coding.c index 8959397b6..4764d1f57 100644 --- a/wolfcrypt/src/coding.c +++ b/wolfcrypt/src/coding.c @@ -113,7 +113,8 @@ static WC_INLINE byte Base64_Char2Val(byte c) } #endif -static WC_INLINE int Base64_SkipNewline(const byte* in, word32 *inLen, word32 *outJ) +int Base64_SkipNewline(const byte* in, word32 *inLen, + word32 *outJ) { word32 len = *inLen; word32 j = *outJ; diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index d1f89ff67..890d6f31b 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -6880,26 +6880,20 @@ int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp, /* Base64 encoding APIs */ #if defined(WOLFSSL_BASE64_ENCODE) || defined(WOLFSSL_BASE64_DECODE) -static struct WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new_ex(void* heap); + /* wolfSSL_EVP_ENCODE_CTX_new allocates WOLFSSL_EVP_ENCODE_CTX * Returns WOLFSSL_EVP_ENCODE_CTX structure on success, NULL on failure. */ struct WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new(void) -{ - return wolfSSL_EVP_ENCODE_CTX_new_ex(NULL); -} -/* wolfSSL_EVP_ENCODE_CTX_new_ex is a helper function of - * wolfSSL_EVP_ENCODE_CTX_new to allocate WOLFSSL_EVP_ENCODE_CTX structure. - */ -static struct WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new_ex(void* heap) { WOLFSSL_EVP_ENCODE_CTX* ctx = NULL; WOLFSSL_ENTER("wolfSSL_EVP_ENCODE_CTX_new"); - ctx = (WOLFSSL_EVP_ENCODE_CTX*)XMALLOC( sizeof(WOLFSSL_EVP_ENCODE_CTX),heap,DYNAMIC_TYPE_OPENSSL ); + ctx = (WOLFSSL_EVP_ENCODE_CTX*)XMALLOC( sizeof(WOLFSSL_EVP_ENCODE_CTX), + NULL, DYNAMIC_TYPE_OPENSSL ); - if(ctx != NULL) { - XMEMSET(ctx,0,sizeof(WOLFSSL_EVP_ENCODE_CTX) ); - ctx->heap = heap; + if (ctx != NULL) { + XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_ENCODE_CTX) ); + ctx->heap = NULL; return ctx; } return NULL; @@ -6909,13 +6903,13 @@ static struct WOLFSSL_EVP_ENCODE_CTX* wolfSSL_EVP_ENCODE_CTX_new_ex(void* heap) 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); + if (ctx != NULL) { + XFREE(ctx, ctx->heap, DYNAMIC_TYPE_OPENSSL); } } #endif /* WOLFSSL_BASE64_ENCODE || WOLFSSL_BASE64_DECODE */ #if defined(WOLFSSL_BASE64_ENCODE) -/* wolfSSL_EVP_EncodeInit initializes specified WOLFSSL_EVP_ENCODE_CTX ojbect +/* wolfSSL_EVP_EncodeInit initializes specified WOLFSSL_EVP_ENCODE_CTX object * for the subsequent wolfSSL_EVP_EncodeUpdate. */ void wolfSSL_EVP_EncodeInit(WOLFSSL_EVP_ENCODE_CTX* ctx) @@ -6923,19 +6917,19 @@ void wolfSSL_EVP_EncodeInit(WOLFSSL_EVP_ENCODE_CTX* ctx) WOLFSSL_ENTER("wolfSSL_EVP_EncodeInit"); /* clean up ctx */ - if(ctx != NULL) { + if (ctx != NULL) { ctx->remaining = 0; - XMEMSET(ctx->data,0, sizeof(ctx->data)); + XMEMSET(ctx->data, 0, sizeof(ctx->data)); } } -/* wolfSSL_EVP_EncodeUpdate encodes the input data in 64-byte units - * and outputs it to out. If less than 64 bytes of data remain, save it in +/* wolfSSL_EVP_EncodeUpdate encodes the input data in 48-byte units + * and outputs it to out. If less than 48 bytes of data remain, save it in * ctx. The data given in the subsequent wolfSSL_EVP_EncodeUpdate * is combined with the data stored in CTX and used for encoding. * Returns 1 on success, 0 on error. */ int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, - unsigned char*out, int *outl, const unsigned char*in, int inl) + unsigned char* out, int* outl, const unsigned char* in, int inl) { int cpysz; int res; @@ -6943,25 +6937,28 @@ int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, WOLFSSL_ENTER("wolfSSL_EVP_EncodeUpdate"); - if( ctx == NULL || out == NULL || in == NULL || outl == NULL ) + 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); + /* 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 ) { + 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) + res = Base64_Encode(ctx->data, BASE64_ENCODE_BLOCK_SIZE, out, + &outsz); + if (res == 0) *outl = outsz; else return 0; /* return with error */ @@ -6972,12 +6969,14 @@ int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, return 1; } } - /* Here, there is no data left in ctx, so try processing the data of the specified input data. */ + /* Here, there is no data left in ctx, so try processing the data of + * the specified input data. + */ - while( inl >= BASE64_ENCODE_BLOCK_SIZE) { + 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) { + 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; @@ -6990,9 +6989,9 @@ int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, } /* 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); + if (inl > 0) { + XMEMSET(ctx->data, 0, sizeof(ctx->data)); + XMEMCPY(ctx->data, in, inl); ctx->remaining = inl; } @@ -7001,66 +7000,36 @@ int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, /* wolfSSL_EVP_EncodeFinal encodes data in ctx and outputs to out. */ void wolfSSL_EVP_EncodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx, - unsigned char*out, int *outl) + unsigned char* out, int* outl) { word32 outsz = 0; int res; WOLFSSL_ENTER("wolfSSL_EVP_EncodeFinal"); - if( outl == NULL) + if (outl == NULL) return; - if( ctx == NULL || out == NULL ) { + 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) + 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)); + 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; -} + /* wolfSSL_EVP_DecodeInit initializes specified WOLFSSL_EVP_ENCODE_CTX struct * for subsequent wolfSSL_EVP_DecodeUpdate. */ @@ -7068,9 +7037,9 @@ void wolfSSL_EVP_DecodeInit(WOLFSSL_EVP_ENCODE_CTX* ctx) { WOLFSSL_ENTER("wolfSSL_EVP_DecodeInit"); /* clean up ctx */ - if(ctx != NULL) { + if (ctx != NULL) { ctx->remaining = 0; - XMEMSET(ctx->data,0, sizeof(ctx->data)); + XMEMSET(ctx->data, 0, sizeof(ctx->data)); } } /* wolfSSL_EVP_DecodeUpdate encodes the input data in 4-byte units @@ -7081,7 +7050,7 @@ void wolfSSL_EVP_DecodeInit(WOLFSSL_EVP_ENCODE_CTX* ctx) * clients should call wolfSSL_EVP_DecodeFinal as next call. */ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, - unsigned char*out, int *outl, const unsigned char*in, int inl) + unsigned char* out, int* outl, const unsigned char* in, int inl) { word32 outsz = 0; word32 j = 0; @@ -7089,14 +7058,18 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, int res; int pad = 0; int i; - char es; + int cpySz; + unsigned char c; + int pad3 = 0; + int pad4 = 0; + byte e[4]; WOLFSSL_ENTER("wolfSSL_EVP_DecodeUpdate"); if (outl == NULL) return -1; - if (ctx == NULL || out == NULL || in == NULL ) { + if (ctx == NULL || out == NULL || in == NULL) { *outl = 0; return -1; } @@ -7111,25 +7084,23 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, /* 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 e0; + if ( ctx->remaining > 0 && inl > 0) { - cpysz = min( (BASE64_DECODE_BLOCK_SIZE - ctx->remaining), inl ); + cpySz = min((BASE64_DECODE_BLOCK_SIZE - ctx->remaining), inl); - for ( i = 0; cpysz > 0 && inLen > 0;i++) { + for ( 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 */ } - e0 = in[j++]; + c = in[j++]; - if (e0 == '=') + if (c == '=') pad = 1; - *(ctx->data + ctx->remaining + i) = e0; + *(ctx->data + ctx->remaining + i) = c; inLen--; - cpysz--; + cpySz--; } outsz = sizeof(ctx->data); @@ -7149,11 +7120,6 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, /* 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; @@ -7232,20 +7198,20 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, } /* copy left data to ctx */ if (inLen > 0) { - unsigned char el; + XMEMSET(ctx->data, 0, sizeof(ctx->data)); i = 0; - while ( inLen > 0) { - el = in[j++]; - if (el== '\n' || el == '\r' || el == ' ') { + while (inLen > 0) { + c = in[j++]; + if (c== '\n' || c == '\r' || c == ' ') { inLen--; continue; } - if (el == '=') { + if (c == '=') { pad = 1; } - ctx->data[i++] = el; + ctx->data[i++] = c; ctx->remaining++; inLen--; } @@ -7257,15 +7223,15 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, } /* if the last data is '\n', remove it */ - es = in[j - 1]; - if (es == '\n') { - es = (in[j - 2]); - if (es == '=') + c = in[j - 1]; + if (c == '\n') { + c = (in[j - 2]); + if (c == '=') return 0; else return 1; } - if (es == '=') + if (c == '=') return 0; else return 1; @@ -7276,7 +7242,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, * Returns 1 on success, -1 on failure. */ int wolfSSL_EVP_DecodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx, - unsigned char*out, int *outl) + unsigned char* out, int* outl) { word32 outsz = 0; word32 inLen; @@ -7285,36 +7251,40 @@ int wolfSSL_EVP_DecodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx, 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; - } + if (outl == NULL) + return -1; + if (ctx == NULL || out == NULL ) { + *outl = 0; + return -1; + } - outsz = ctx->remaining; - res = Base64_Decode(ctx->data, ctx->remaining, out, &outsz); - if (res == 0) { - *outl = outsz; - return 1; - } - else { - *outl = 0; + if (ctx->remaining > 0) { + inLen = ctx->remaining; + if ((res = Base64_SkipNewline(ctx->data, &inLen, &j)) != 0) { + *outl = 0; + if (res == BUFFER_E) /* means no valid data to decode in buffer */ + return 1; /* returns as success with no output */ + 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 1; + return -1; } } - - return -1; + else { + *outl = 0; + return 1; + } } #endif /* WOLFSSL_BASE64_DECODE */ diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index bdee14476..b0bffc14b 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -385,7 +385,7 @@ struct WOLFSSL_EVP_PKEY_CTX { struct WOLFSSL_EVP_ENCODE_CTX { void* heap; int remaining; /* num of bytes in data[] */ - byte data[128]; /* storage for unprocessed raw data */ + byte data[BASE64_ENCODE_BLOCK_SIZE];/* storage for unprocessed raw data */ }; typedef struct WOLFSSL_EVP_ENCODE_CTX WOLFSSL_EVP_ENCODE_CTX; diff --git a/wolfssl/wolfcrypt/coding.h b/wolfssl/wolfcrypt/coding.h index 88b1caf94..e7e2aedc1 100644 --- a/wolfssl/wolfcrypt/coding.h +++ b/wolfssl/wolfcrypt/coding.h @@ -79,6 +79,8 @@ WOLFSSL_API int Base64_Decode(const byte* in, word32 inLen, byte* out, int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen); #endif + WOLFSSL_LOCAL int Base64_SkipNewline(const byte* in, word32* inLen, + word32* outJ); #ifdef __cplusplus } /* extern "C" */ From 3bd7127188bd05e3801d60557fdae550cb782554 Mon Sep 17 00:00:00 2001 From: TakayukiMatsuo Date: Wed, 17 Mar 2021 06:58:51 +0900 Subject: [PATCH 6/9] Wrap some long lines. --- tests/api.c | 16 ++++++++++------ wolfcrypt/src/evp.c | 6 +++--- wolfssl/openssl/evp.h | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/api.c b/tests/api.c index 830b0ef72..227db1c1c 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2598,7 +2598,7 @@ static void test_wolfSSL_EVP_EncodeUpdate(void) total += outl; AssertIntNE(outl, 0); /* some output is expected this time*/ - AssertIntEQ(outl, BASE64_ENCODED_BLOCK_SIZE +1); /* 64 bytes and LF */ + AssertIntEQ(outl, BASE64_ENCODE_RESULT_BLOCK_SIZE +1); /* 64 bytes and LF */ AssertIntEQ( XSTRNCMP((const char*)encOutBuff,(const char*)enc1,sizeof(enc1) ),0); @@ -2669,7 +2669,8 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) WOLFSSL_EVP_ENCODE_CTX* ctx = wolfSSL_EVP_ENCODE_CTX_new(); wolfSSL_EVP_DecodeInit(ctx); - const unsigned char enc1[] = {"VGhpcyBpcyBhIGJhc2U2NCBkZWNvZGluZyB0ZXN0Lg==\n"}; + const unsigned char enc1[] = + {"VGhpcyBpcyBhIGJhc2U2NCBkZWNvZGluZyB0ZXN0Lg==\n"}; /* const unsigned char plain1[] = {"This is a base64 decoding test."} */ @@ -2736,7 +2737,8 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) /* decode correct base64 string */ - const unsigned char enc2[] = {"VGhpcyBpcyBhIGJhc2U2NCBkZWNvZGluZyB0ZXN0Lg==\n"}; + const unsigned char enc2[] = + {"VGhpcyBpcyBhIGJhc2U2NCBkZWNvZGluZyB0ZXN0Lg==\n"}; const unsigned char plain2[] = {"This is a base64 decoding test."}; @@ -2768,7 +2770,8 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) /* decode correct base64 string which does not have '\n' in its last*/ - const unsigned char enc3[] = {"VGhpcyBpcyBhIGJhc2U2NCBkZWNvZGluZyB0ZXN0Lg=="}; /* 44 chars */ + const unsigned char enc3[] = + {"VGhpcyBpcyBhIGJhc2U2NCBkZWNvZGluZyB0ZXN0Lg=="}; /* 44 chars */ const unsigned char plain3[] = {"This is a base64 decoding test."}; /* 31 chars */ @@ -2801,8 +2804,9 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) /* decode string which has a padding char ('=') in the illegal position*/ - const unsigned char enc4[] = {"VGhpcyBpcyBhIGJhc2U2N=CBkZWNvZGluZyB0ZXN0Lg==\n"}; - /* ^-- illegal padding */ + const unsigned char enc4[] = + {"VGhpcyBpcyBhIGJhc2U2N=CBkZWNvZGluZyB0ZXN0Lg==\n"}; + wolfSSL_EVP_EncodeInit(ctx); diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 890d6f31b..02f8db385 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -6955,7 +6955,7 @@ int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, /* 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; + outsz = BASE64_ENCODE_RESULT_BLOCK_SIZE + 1; res = Base64_Encode(ctx->data, BASE64_ENCODE_BLOCK_SIZE, out, &outsz); if (res == 0) @@ -6974,7 +6974,7 @@ int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, */ while (inl >= BASE64_ENCODE_BLOCK_SIZE) { - outsz = BASE64_ENCODED_BLOCK_SIZE + 1; /* 64 byte and one for LF*/ + outsz = BASE64_ENCODE_RESULT_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; @@ -7015,7 +7015,7 @@ void wolfSSL_EVP_EncodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx, return; } /* process remaining data in ctx */ - outsz = BASE64_ENCODED_BLOCK_SIZE + 1; /* 64 byte and one for LF*/ + outsz = BASE64_ENCODE_RESULT_BLOCK_SIZE + 1; /* 64 byte and one for LF*/ res = Base64_Encode(ctx->data, ctx->remaining ,out, &outsz); if (res == 0) *outl = outsz; diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index b0bffc14b..aa6c61b2a 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -379,7 +379,7 @@ struct WOLFSSL_EVP_PKEY_CTX { #if defined(WOLFSSL_BASE64_ENCODE) || defined(WOLFSSL_BASE64_DECODE) #define BASE64_ENCODE_BLOCK_SIZE 48 -#define BASE64_ENCODED_BLOCK_SIZE 64 +#define BASE64_ENCODE_RESULT_BLOCK_SIZE 64 #define BASE64_DECODE_BLOCK_SIZE 4 struct WOLFSSL_EVP_ENCODE_CTX { From 5456765dca201fc96901f40bb242e9d831ef241c Mon Sep 17 00:00:00 2001 From: TakayukiMatsuo Date: Fri, 26 Mar 2021 17:05:25 +0900 Subject: [PATCH 7/9] Changed API names to call in unit tests. --- tests/api.c | 114 ++++++++++++++++++++++++++-------------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/tests/api.c b/tests/api.c index 227db1c1c..9b0c30fff 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2398,15 +2398,15 @@ 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()"); + printf(testingFmt, "EVP_ENCODE_CTX_new()"); - WOLFSSL_EVP_ENCODE_CTX* ctx = NULL; + EVP_ENCODE_CTX* ctx = NULL; - AssertNotNull( ctx = wolfSSL_EVP_ENCODE_CTX_new()); + AssertNotNull( ctx = 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); + EVP_ENCODE_CTX_free(ctx); printf(resultFmt, passed); #endif /* OPENSSL_EXTRA && (WOLFSSL_BASE64_ENCODE || WOLFSSL_BASE64_DECODE)*/ @@ -2415,11 +2415,11 @@ 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; + printf(testingFmt, "EVP_ENCODE_CTX_free()"); + EVP_ENCODE_CTX* ctx = NULL; - AssertNotNull( ctx = wolfSSL_EVP_ENCODE_CTX_new()); - wolfSSL_EVP_ENCODE_CTX_free(ctx); + AssertNotNull( ctx = EVP_ENCODE_CTX_new()); + EVP_ENCODE_CTX_free(ctx); printf(resultFmt, passed); #endif /*OPENSSL_EXTRA && (WOLFSSL_BASE64_ENCODE || WOLFSSL_BASE64_DECODE)*/ } @@ -2427,10 +2427,10 @@ static void test_wolfSSL_EVP_ENCODE_CTX_free(void) 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; + printf(testingFmt, "EVP_EncodeInit()"); + EVP_ENCODE_CTX* ctx = NULL; - AssertNotNull( ctx = wolfSSL_EVP_ENCODE_CTX_new()); + AssertNotNull( ctx = EVP_ENCODE_CTX_new()); AssertIntEQ( ctx->remaining,0); AssertIntEQ( ctx->data[0],0); AssertIntEQ( ctx->data[sizeof(ctx->data) -1],0); @@ -2439,20 +2439,20 @@ static void test_wolfSSL_EVP_EncodeInit(void) ctx->remaining = 10; XMEMSET( ctx->data, 0x77, sizeof(ctx->data)); - wolfSSL_EVP_EncodeInit(ctx); + 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); + 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()"); + printf(testingFmt, "EVP_EncodeUpdate()"); int outl; int total; @@ -2469,14 +2469,14 @@ static void test_wolfSSL_EVP_EncodeUpdate(void) unsigned char encOutBuff[300]; - WOLFSSL_EVP_ENCODE_CTX* ctx = NULL; - AssertNotNull( ctx = wolfSSL_EVP_ENCODE_CTX_new()); + EVP_ENCODE_CTX* ctx = NULL; + AssertNotNull( ctx = EVP_ENCODE_CTX_new()); - wolfSSL_EVP_EncodeInit(ctx); + EVP_EncodeInit(ctx); /* illegal parameter test */ AssertIntEQ( - wolfSSL_EVP_EncodeUpdate( + EVP_EncodeUpdate( NULL, /* pass NULL as ctx */ encOutBuff, &outl, @@ -2486,7 +2486,7 @@ static void test_wolfSSL_EVP_EncodeUpdate(void) ); AssertIntEQ( - wolfSSL_EVP_EncodeUpdate( + EVP_EncodeUpdate( ctx, NULL, /* pass NULL as out buff */ &outl, @@ -2496,7 +2496,7 @@ static void test_wolfSSL_EVP_EncodeUpdate(void) ); AssertIntEQ( - wolfSSL_EVP_EncodeUpdate( + EVP_EncodeUpdate( ctx, encOutBuff, NULL, /* pass NULL as outl */ @@ -2506,7 +2506,7 @@ static void test_wolfSSL_EVP_EncodeUpdate(void) ); AssertIntEQ( - wolfSSL_EVP_EncodeUpdate( + EVP_EncodeUpdate( ctx, encOutBuff, &outl, @@ -2518,7 +2518,7 @@ static void test_wolfSSL_EVP_EncodeUpdate(void) /* meaningless parameter test */ AssertIntEQ( - wolfSSL_EVP_EncodeUpdate( + EVP_EncodeUpdate( ctx, encOutBuff, &outl, @@ -2529,10 +2529,10 @@ static void test_wolfSSL_EVP_EncodeUpdate(void) /* very small data encoding test */ - wolfSSL_EVP_EncodeInit(ctx); + EVP_EncodeInit(ctx); AssertIntEQ( - wolfSSL_EVP_EncodeUpdate( + EVP_EncodeUpdate( ctx, encOutBuff, &outl, @@ -2542,7 +2542,7 @@ static void test_wolfSSL_EVP_EncodeUpdate(void) ); AssertIntEQ(outl,0); - wolfSSL_EVP_EncodeFinal( + EVP_EncodeFinal( ctx, encOutBuff + outl, &outl); @@ -2558,14 +2558,14 @@ static void test_wolfSSL_EVP_EncodeUpdate(void) * encoded and just stored in ctx */ - wolfSSL_EVP_EncodeInit(ctx); + EVP_EncodeInit(ctx); total = 0; outl = 0; XMEMSET( encOutBuff,0, sizeof(encOutBuff)); AssertIntEQ( - wolfSSL_EVP_EncodeUpdate( + EVP_EncodeUpdate( ctx, encOutBuff, /* buffer for output */ &outl, /* size of output */ @@ -2587,7 +2587,7 @@ static void test_wolfSSL_EVP_EncodeUpdate(void) * the stored data and the new input together */ AssertIntEQ( - wolfSSL_EVP_EncodeUpdate( + EVP_EncodeUpdate( ctx, encOutBuff + outl, /* buffer for output */ &outl, /* size of output */ @@ -2603,7 +2603,7 @@ static void test_wolfSSL_EVP_EncodeUpdate(void) XSTRNCMP((const char*)encOutBuff,(const char*)enc1,sizeof(enc1) ),0); /* call wolfSSL_EVP_EncodeFinal to flush all the unprocessed input */ - wolfSSL_EVP_EncodeFinal( + EVP_EncodeFinal( ctx, encOutBuff + outl, &outl); @@ -2615,7 +2615,7 @@ static void test_wolfSSL_EVP_EncodeUpdate(void) AssertIntEQ(XSTRNCMP( (const char*)encOutBuff,(const char*)enc2,sizeof(enc2) ),0); - wolfSSL_EVP_ENCODE_CTX_free(ctx); + EVP_ENCODE_CTX_free(ctx); printf(resultFmt, passed); #endif /* OPENSSL_EXTRA && WOLFSSL_BASE64_ENCODE*/ } @@ -2635,11 +2635,11 @@ static void test_wolfSSL_EVP_EncodeFinal(void) static void test_wolfSSL_EVP_DecodeInit(void) { #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_BASE64_DECODE) - printf(testingFmt, "wolfSSL_EVP_DecodeInit()"); + printf(testingFmt, "EVP_DecodeInit()"); - WOLFSSL_EVP_ENCODE_CTX* ctx = NULL; + EVP_ENCODE_CTX* ctx = NULL; - AssertNotNull( ctx = wolfSSL_EVP_ENCODE_CTX_new()); + AssertNotNull( ctx = EVP_ENCODE_CTX_new()); AssertIntEQ( ctx->remaining,0); AssertIntEQ( ctx->data[0],0); AssertIntEQ( ctx->data[sizeof(ctx->data) -1],0); @@ -2648,26 +2648,26 @@ static void test_wolfSSL_EVP_DecodeInit(void) ctx->remaining = 10; XMEMSET( ctx->data, 0x77, sizeof(ctx->data)); - wolfSSL_EVP_DecodeInit(ctx); + 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); + 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()"); + printf(testingFmt, "EVP_DecodeUpdate()"); int outl; unsigned char decOutBuff[300]; - WOLFSSL_EVP_ENCODE_CTX* ctx = wolfSSL_EVP_ENCODE_CTX_new(); - wolfSSL_EVP_DecodeInit(ctx); + EVP_ENCODE_CTX* ctx = EVP_ENCODE_CTX_new(); + EVP_DecodeInit(ctx); const unsigned char enc1[] = {"VGhpcyBpcyBhIGJhc2U2NCBkZWNvZGluZyB0ZXN0Lg==\n"}; @@ -2678,7 +2678,7 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) /* pass NULL as ctx */ AssertIntEQ( - wolfSSL_EVP_DecodeUpdate( + EVP_DecodeUpdate( NULL, /* pass NULL as ctx */ decOutBuff, &outl, @@ -2690,7 +2690,7 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) /* pass NULL as output */ AssertIntEQ( - wolfSSL_EVP_DecodeUpdate( + EVP_DecodeUpdate( ctx, NULL, /* pass NULL as out buff */ &outl, @@ -2702,7 +2702,7 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) /* pass NULL as outl */ AssertIntEQ( - wolfSSL_EVP_DecodeUpdate( + EVP_DecodeUpdate( ctx, decOutBuff, NULL, /* pass NULL as outl */ @@ -2713,7 +2713,7 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) /* pass NULL as input */ AssertIntEQ( - wolfSSL_EVP_DecodeUpdate( + EVP_DecodeUpdate( ctx, decOutBuff, &outl, @@ -2726,7 +2726,7 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) /* pass zero length input */ AssertIntEQ( - wolfSSL_EVP_DecodeUpdate( + EVP_DecodeUpdate( ctx, decOutBuff, &outl, @@ -2742,10 +2742,10 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) const unsigned char plain2[] = {"This is a base64 decoding test."}; - wolfSSL_EVP_EncodeInit(ctx); + EVP_EncodeInit(ctx); AssertIntEQ( - wolfSSL_EVP_DecodeUpdate( + EVP_DecodeUpdate( ctx, decOutBuff, &outl, @@ -2757,7 +2757,7 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) AssertIntEQ(outl,sizeof(plain2) -1); AssertIntEQ( - wolfSSL_EVP_DecodeFinal( + EVP_DecodeFinal( ctx, decOutBuff + outl, &outl), @@ -2775,10 +2775,10 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) const unsigned char plain3[] = {"This is a base64 decoding test."}; /* 31 chars */ - wolfSSL_EVP_EncodeInit(ctx); + EVP_EncodeInit(ctx); AssertIntEQ( - wolfSSL_EVP_DecodeUpdate( + EVP_DecodeUpdate( ctx, decOutBuff, &outl, @@ -2793,7 +2793,7 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) sizeof(plain3) -1 ),0); AssertIntEQ( - wolfSSL_EVP_DecodeFinal( + EVP_DecodeFinal( ctx, decOutBuff + outl, &outl), @@ -2808,10 +2808,10 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) {"VGhpcyBpcyBhIGJhc2U2N=CBkZWNvZGluZyB0ZXN0Lg==\n"}; - wolfSSL_EVP_EncodeInit(ctx); + EVP_EncodeInit(ctx); AssertIntEQ( - wolfSSL_EVP_DecodeUpdate( + EVP_DecodeUpdate( ctx, decOutBuff, &outl, @@ -2827,10 +2827,10 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) const unsigned char enc01[] = {"g=\n"}; const unsigned char plain4[] = {"Th"}; - wolfSSL_EVP_EncodeInit(ctx); + EVP_EncodeInit(ctx); AssertIntEQ( - wolfSSL_EVP_DecodeUpdate( + EVP_DecodeUpdate( ctx, decOutBuff, &outl, @@ -2841,7 +2841,7 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) AssertIntEQ(outl,0); AssertIntEQ( - wolfSSL_EVP_DecodeUpdate( + EVP_DecodeUpdate( ctx, decOutBuff + outl, &outl, @@ -2852,7 +2852,7 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) AssertIntEQ(outl,sizeof(plain4)-1); - wolfSSL_EVP_DecodeFinal( + EVP_DecodeFinal( ctx, decOutBuff + outl, &outl); @@ -2864,7 +2864,7 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) (const char*)plain4,sizeof(plain4)-1 ), 0); - wolfSSL_EVP_ENCODE_CTX_free(ctx); + EVP_ENCODE_CTX_free(ctx); printf(resultFmt, passed); #endif /* OPENSSL && WOLFSSL_BASE_DECODE */ @@ -2872,7 +2872,7 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) static void test_wolfSSL_EVP_DecodeFinal(void) { #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_BASE64_DECODE) - printf(testingFmt, "wolfSSL_EVP_DecodeFinal()"); + printf(testingFmt, "EVP_DecodeFinal()"); /* tests for wolfSSL_EVP_DecodeFinal are included in * test_wolfSSL_EVP_DecodeUpdate */ From f7477b932d23f722c9c136b786a1f2fd60a2cc86 Mon Sep 17 00:00:00 2001 From: TakayukiMatsuo Date: Fri, 26 Mar 2021 17:06:14 +0900 Subject: [PATCH 8/9] Add return value checks and fixed typos. --- wolfcrypt/src/evp.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 02f8db385..31de9063b 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -6942,7 +6942,7 @@ int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, *outl = 0; - /* if the remaining data exit in the ctx, add input data to them + /* if the remaining data exists in the ctx, add input data to them * to create a block(48bytes) for encoding */ if (ctx->remaining > 0 && inl > 0) { @@ -6958,6 +6958,7 @@ int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, outsz = BASE64_ENCODE_RESULT_BLOCK_SIZE + 1; res = Base64_Encode(ctx->data, BASE64_ENCODE_BLOCK_SIZE, out, &outsz); + ctx->remaining = 0; if (res == 0) *outl = outsz; else @@ -6988,7 +6989,7 @@ int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, } } - /* if remaining data exit, copy them into ctx for the next call*/ + /* if remaining data exists, copy them into ctx for the next call*/ if (inl > 0) { XMEMSET(ctx->data, 0, sizeof(ctx->data)); XMEMCPY(ctx->data, in, inl); @@ -7014,6 +7015,10 @@ void wolfSSL_EVP_EncodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx, *outl = 0; return; } + if (ctx->remaining >= BASE64_ENCODE_RESULT_BLOCK_SIZE) { + *outl = 0; + return; + } /* process remaining data in ctx */ outsz = BASE64_ENCODE_RESULT_BLOCK_SIZE + 1; /* 64 byte and one for LF*/ res = Base64_Encode(ctx->data, ctx->remaining ,out, &outsz); @@ -7118,7 +7123,16 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, } } - /* process data in input buffer */ + /* Base64_Decode is not a streaming process, so it processes + * the input data and exits. If a line break or whitespace + * character is found in the input data, it will be skipped, + * but if the end point of the input data is reached as a result, + * Base64_Decode will stop processing there. The data cleansing is + * required before Base64_Decode so that the processing does not + * stop within 4 bytes, which is the unit of Base64 decoding processing. + * The logic that exists before calling Base64_Decode in a While Loop is + * a data cleansing process that removes line breaks and whitespace. + */ while (inLen > 3) { if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) { if (res == BUFFER_E) { @@ -7188,7 +7202,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, /* decode four bytes */ outsz = sizeof(ctx->data); res = Base64_Decode( e, BASE64_DECODE_BLOCK_SIZE, out, &outsz); - if (res == ASN_INPUT_E) { + if (res < 0) { *outl = 0; return -1; } From 195ca2b3f04818c744c57b298faf523bafabdcea Mon Sep 17 00:00:00 2001 From: TakayukiMatsuo Date: Thu, 3 Jun 2021 20:02:48 +0900 Subject: [PATCH 9/9] Add corner test cases for EVP_EncodeFinal and EVP_DecodeFinal --- tests/api.c | 16 ++++++++++++++++ wolfcrypt/src/evp.c | 5 +++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/tests/api.c b/tests/api.c index 9b0c30fff..424d82938 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2615,6 +2615,16 @@ static void test_wolfSSL_EVP_EncodeUpdate(void) AssertIntEQ(XSTRNCMP( (const char*)encOutBuff,(const char*)enc2,sizeof(enc2) ),0); + /* test with illeagal parameters */ + outl = 1; + EVP_EncodeFinal(NULL, encOutBuff + outl, &outl); + AssertIntEQ(outl, 0); + outl = 1; + EVP_EncodeFinal(ctx, NULL, &outl); + AssertIntEQ(outl, 0); + EVP_EncodeFinal(ctx, encOutBuff + outl, NULL); + EVP_EncodeFinal(NULL, NULL, NULL); + EVP_ENCODE_CTX_free(ctx); printf(resultFmt, passed); #endif /* OPENSSL_EXTRA && WOLFSSL_BASE64_ENCODE*/ @@ -2852,6 +2862,12 @@ static void test_wolfSSL_EVP_DecodeUpdate(void) AssertIntEQ(outl,sizeof(plain4)-1); + /* test with illegal parameters */ + AssertIntEQ(EVP_DecodeFinal(NULL,decOutBuff + outl,&outl), -1); + AssertIntEQ(EVP_DecodeFinal(ctx,NULL,&outl), -1); + AssertIntEQ(EVP_DecodeFinal(ctx,decOutBuff + outl, NULL), -1); + AssertIntEQ(EVP_DecodeFinal(NULL,NULL, NULL), -1); + EVP_DecodeFinal( ctx, decOutBuff + outl, diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 31de9063b..697edf344 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -6958,9 +6958,10 @@ int wolfSSL_EVP_EncodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, outsz = BASE64_ENCODE_RESULT_BLOCK_SIZE + 1; res = Base64_Encode(ctx->data, BASE64_ENCODE_BLOCK_SIZE, out, &outsz); - ctx->remaining = 0; - if (res == 0) + if (res == 0) { + ctx->remaining = 0; *outl = outsz; + } else return 0; /* return with error */ }