diff --git a/Makefile.am b/Makefile.am index 74d55b3c8..ec4f72093 100644 --- a/Makefile.am +++ b/Makefile.am @@ -105,6 +105,9 @@ install-generic-config: $(mkinstalldirs) $(DESTDIR)$(bindir) $(INSTALL_SCRIPT) @GENERIC_CONFIG@ $(DESTDIR)$(bindir) +uninstall-local: + -rm -f $(DESTDIR)$(bindir)/@GENERIC_CONFIG@ + merge-clean: @find ./ | $(GREP) \.gcda | xargs rm -f @find ./ | $(GREP) \.gcno | xargs rm -f diff --git a/commit-tests.sh b/commit-tests.sh index f26f1ed16..c6ee86b2c 100755 --- a/commit-tests.sh +++ b/commit-tests.sh @@ -23,7 +23,7 @@ RESULT=$? # make sure full config is ok echo -e "\n\nTesting full config as well...\n\n" -./configure --enable-opensslExtra --enable-fastmath --enable-dtls --enable-aesgcm --enable-hc128 --enable-sniffer --enable-psk --enable-rabbit; +./configure --enable-opensslExtra --enable-fastmath --enable-dtls --enable-aesgcm --enable-aesccm --enable-hc128 --enable-sniffer --enable-psk --enable-rabbit; RESULT=$? [ $RESULT -ne 0 ] && echo -e "\n\nFull config ./configure failed" && exit 1 diff --git a/configure.ac b/configure.ac index ea61653bf..6bec93bea 100644 --- a/configure.ac +++ b/configure.ac @@ -14,12 +14,12 @@ AC_CONFIG_MACRO_DIR([m4]) AC_CANONICAL_TARGET AC_USE_SYSTEM_EXTENSIONS -AM_INIT_AUTOMAKE([-Wall -Werror -Wno-portability foreign tar-ustar subdir-objects]) +AM_INIT_AUTOMAKE([1.12 -Wall -Werror -Wno-portability foreign tar-ustar subdir-objects serial-tests]) AC_CANONICAL_HOST AC_CANONICAL_BUILD -AC_PREREQ([2.61]) +AC_PREREQ([2.65]) AC_CONFIG_HEADERS([config.h:config.in])dnl Keep filename to 8.3 for MS-DOS. @@ -329,6 +329,22 @@ fi AM_CONDITIONAL([BUILD_AESGCM], [test "x$ENABLED_AESGCM" = "xyes"]) + +# AES-CCM +AC_ARG_ENABLE([aesccm], + [ --enable-aesccm Enable CyaSSL AES-CCM support (default: disabled)], + [ ENABLED_AESCCM=$enableval ], + [ ENABLED_AESCCM=no ] + ) + +if test "$ENABLED_AESCCM" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_AESCCM -DCYASSL_SHA384 -DCYASSL_SHA512" +fi + +AM_CONDITIONAL([BUILD_AESCCM], [test "x$ENABLED_AESCCM" = "xyes"]) + + # AES-NI AC_ARG_ENABLE([aesni], [ --enable-aesni Enable CyaSSL AES-NI support (default: disabled)], @@ -421,6 +437,11 @@ then ENABLED_SHA512="yes" fi +if test "$ENABLED_AESCCM" = "yes" +then + ENABLED_SHA512="yes" +fi + AM_CONDITIONAL([BUILD_SHA512], [test "x$ENABLED_SHA512" = "xyes"]) @@ -663,6 +684,7 @@ then AC_MSG_ERROR([Valgrind not found.]) fi enable_shared=no + AM_CFLAGS="$AM_CFLAGS -DHAVE_VALGRIND" fi AM_CONDITIONAL([USE_VALGRIND], [test "x$ENABLED_VALGRIND" = "xyes"]) @@ -811,6 +833,7 @@ echo " * fastmath: $ENABLED_FASTMATH" echo " * sniffer: $ENABLED_SNIFFER" echo " * AES-NI: $ENABLED_AESNI" echo " * AES-GCM: $ENABLED_AESGCM" +echo " * AES-CCM: $ENABLED_AESCCM" echo " * RIPEMD: $ENABLED_RIPEMD" echo " * SHA-512: $ENABLED_SHA512" echo " * keygen: $ENABLED_KEYGEN" diff --git a/ctaocrypt/benchmark/benchmark.c b/ctaocrypt/benchmark/benchmark.c index bc466cc38..aaa0c65c4 100644 --- a/ctaocrypt/benchmark/benchmark.c +++ b/ctaocrypt/benchmark/benchmark.c @@ -60,6 +60,7 @@ void bench_hc128(void); void bench_rabbit(void); void bench_aes(int); void bench_aesgcm(void); +void bench_aesccm(void); void bench_md5(void); void bench_sha(void); @@ -90,6 +91,9 @@ int main(int argc, char** argv) #ifdef HAVE_AESGCM bench_aesgcm(); #endif +#ifdef HAVE_AESCCM + bench_aesccm(); +#endif #ifndef NO_RC4 bench_arc4(); #endif @@ -202,12 +206,11 @@ void bench_aesgcm(void) double start, total, persec; int i; - AesGcmSetKey(&enc, key, 16, iv); - AesGcmSetExpIV(&enc, iv+4); + AesGcmSetKey(&enc, key, 16); start = current_time(); for(i = 0; i < megs; i++) - AesGcmEncrypt(&enc, cipher, plain, sizeof(plain), + AesGcmEncrypt(&enc, cipher, plain, sizeof(plain), iv, 12, tag, 16, additional, 13); total = current_time() - start; @@ -219,6 +222,29 @@ void bench_aesgcm(void) #endif +#ifdef HAVE_AESCCM +void bench_aesccm(void) +{ + Aes enc; + double start, total, persec; + int i; + + AesCcmSetKey(&enc, key, 16); + start = current_time(); + + for(i = 0; i < megs; i++) + AesCcmEncrypt(&enc, cipher, plain, sizeof(plain), iv, 12, + tag, 16, additional, 13); + + total = current_time() - start; + + persec = 1 / total * megs; + printf("AES-CCM %d megs took %5.3f seconds, %6.2f MB/s\n", megs, total, + persec); +} +#endif + + #ifndef NO_DES3 void bench_des(void) { @@ -469,7 +495,6 @@ void bench_rsa(void) byte message[] = "Everyone gets Friday off."; byte enc[512]; /* for up to 4096 bit */ - byte* output; const int len = (int)strlen((char*)message); double start, total, each, milliEach; @@ -501,8 +526,10 @@ void bench_rsa(void) start = current_time(); - for (i = 0; i < times; i++) - RsaPrivateDecryptInline(enc, (word32)bytes, &output, &rsaKey); + for (i = 0; i < times; i++) { + byte out[512]; /* for up to 4096 bit */ + RsaPrivateDecrypt(enc, (word32)bytes, out, sizeof(out), &rsaKey); + } total = current_time() - start; each = total / times; /* per second */ diff --git a/ctaocrypt/src/aes.c b/ctaocrypt/src/aes.c index b8bfbcb3a..448ed130c 100644 --- a/ctaocrypt/src/aes.c +++ b/ctaocrypt/src/aes.c @@ -1807,8 +1807,6 @@ void AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) */ enum { - IMPLICIT_IV_SZ = 4, - EXPLICIT_IV_SZ = 8, CTR_SZ = 4 }; @@ -1834,36 +1832,6 @@ static INLINE void IncrementGcmCounter(byte* inOutCtr) } -/* - * The explicit IV is set by the caller. A common practice is to treat it as - * a sequence number seeded with a random number. The caller manages - * incrementing the explicit IV when appropriate. - */ - -void AesGcmSetExpIV(Aes* aes, const byte* iv) -{ - XMEMCPY((byte*)aes->reg + IMPLICIT_IV_SZ, iv, EXPLICIT_IV_SZ); -} - - -void AesGcmGetExpIV(Aes* aes, byte* iv) -{ - XMEMCPY(iv, (byte*)aes->reg + IMPLICIT_IV_SZ, EXPLICIT_IV_SZ); -} - - -void AesGcmIncExpIV(Aes* aes) -{ - int i; - byte* iv = (byte*)aes->reg + IMPLICIT_IV_SZ; - - for (i = EXPLICIT_IV_SZ - 1; i >= 0; i--) { - if (++iv[i]) - return; - } -} - - #if defined(GCM_SMALL) || defined(GCM_TABLE) static INLINE void FlattenSzInBits(byte* buf, word32 sz) @@ -1929,20 +1897,17 @@ static void GenerateM0(Aes* aes) #endif /* GCM_TABLE */ -void AesGcmSetKey(Aes* aes, const byte* key, word32 len, - const byte* implicitIV) +void AesGcmSetKey(Aes* aes, const byte* key, word32 len) { - byte fullIV[AES_BLOCK_SIZE]; + byte iv[AES_BLOCK_SIZE]; if (!((len == 16) || (len == 24) || (len == 32))) return; - XMEMSET(fullIV, 0, AES_BLOCK_SIZE); - XMEMCPY(fullIV, implicitIV, IMPLICIT_IV_SZ); - AesSetKeyLocal(aes, key, len, fullIV, AES_ENCRYPTION); + XMEMSET(iv, 0, AES_BLOCK_SIZE); + AesSetKeyLocal(aes, key, len, iv, AES_ENCRYPTION); - XMEMSET(fullIV, 0, AES_BLOCK_SIZE); - AesEncrypt(aes, fullIV, aes->H); + AesEncrypt(aes, iv, aes->H); #ifdef GCM_TABLE GenerateM0(aes); #endif /* GCM_TABLE */ @@ -2449,6 +2414,7 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) { @@ -2461,9 +2427,8 @@ void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, CYASSL_ENTER("AesGcmEncrypt"); - /* Initialize the counter with the MS 96 bits of IV, and the counter - * portion set to "1". */ - XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE); + XMEMSET(ctr, 0, AES_BLOCK_SIZE); + XMEMCPY(ctr, iv, ivSz); InitGcmCounter(ctr); while (blocks--) { @@ -2489,6 +2454,7 @@ void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, const byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) { @@ -2501,9 +2467,8 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, CYASSL_ENTER("AesGcmDecrypt"); - /* Initialize the counter with the MS 96 bits of IV, and the counter - * portion set to "1". */ - XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE); + XMEMSET(ctr, 0, AES_BLOCK_SIZE); + XMEMCPY(ctr, iv, ivSz); InitGcmCounter(ctr); /* Calculate the authTag again using the received auth data and the @@ -2541,6 +2506,224 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, #endif /* HAVE_AESGCM */ +#ifdef HAVE_AESCCM + +void AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) +{ + byte nonce[AES_BLOCK_SIZE]; + + if (!((keySz == 16) || (keySz == 24) || (keySz == 32))) + return; + + XMEMSET(nonce, 0, sizeof(nonce)); + AesSetKeyLocal(aes, key, keySz, nonce, AES_ENCRYPTION); +} + + +static void roll_x(Aes* aes, const byte* in, word32 inSz, byte* out) +{ + /* process the bulk of the data */ + while (inSz >= AES_BLOCK_SIZE) { + xorbuf(out, in, AES_BLOCK_SIZE); + in += AES_BLOCK_SIZE; + inSz -= AES_BLOCK_SIZE; + + AesEncrypt(aes, out, out); + } + + /* process remainder of the data */ + if (inSz > 0) { + xorbuf(out, in, inSz); + AesEncrypt(aes, out, out); + } +} + + +static void roll_auth(Aes* aes, const byte* in, word32 inSz, byte* out) +{ + word32 authLenSz; + word32 remainder; + + /* encode the length in */ + if (inSz <= 0xFEFF) { + authLenSz = 2; + out[0] ^= ((inSz & 0xFF00) >> 8); + out[1] ^= (inSz & 0x00FF); + } + else if (inSz <= 0xFFFFFFFF) { + authLenSz = 6; + out[0] ^= 0xFF; out[1] ^= 0xFE; + out[2] ^= ((inSz & 0xFF000000) >> 24); + out[3] ^= ((inSz & 0x00FF0000) >> 16); + out[4] ^= ((inSz & 0x0000FF00) >> 8); + out[5] ^= (inSz & 0x000000FF); + } + /* Note, the protocol handles auth data up to 2^64, but we are + * using 32-bit sizes right now, so the bigger data isn't handled + * else if (inSz <= 0xFFFFFFFFFFFFFFFF) {} */ + else + return; + + /* start fill out the rest of the first block */ + remainder = AES_BLOCK_SIZE - authLenSz; + if (inSz >= remainder) { + /* plenty of bulk data to fill the remainder of this block */ + xorbuf(out + authLenSz, in, remainder); + inSz -= remainder; + in += remainder; + } + else { + /* not enough bulk data, copy what is available, and pad zero */ + xorbuf(out + authLenSz, in, inSz); + inSz = 0; + } + AesEncrypt(aes, out, out); + + if (inSz > 0) + roll_x(aes, in, inSz, out); +} + + +static INLINE void AesCcmCtrInc(byte* B, word32 lenSz) +{ + word32 i; + + for (i = 0; i < lenSz; i++) { + if (++B[AES_BLOCK_SIZE - 1 - i] != 0) return; + } +} + + +void AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + byte A[AES_BLOCK_SIZE]; + byte B[AES_BLOCK_SIZE]; + word32 i, lenSz; + + XMEMCPY(B+1, nonce, nonceSz); + lenSz = AES_BLOCK_SIZE - 1 - nonceSz; + B[0] = (authInSz > 0 ? 64 : 0) + + (8 * ((authTagSz - 2) / 2)) + + (lenSz - 1); + for (i = 0; i < lenSz; i++) + B[AES_BLOCK_SIZE - 1 - i] = (inSz >> (8 * i)) & 0xFF; + + AesEncrypt(aes, B, A); + if (authInSz > 0) + roll_auth(aes, authIn, authInSz, A); + if (inSz > 0) + roll_x(aes, in, inSz, A); + XMEMCPY(authTag, A, authTagSz); + + B[0] = (lenSz - 1); + for (i = 0; i < lenSz; i++) + B[AES_BLOCK_SIZE - 1 - i] = 0; + AesEncrypt(aes, B, A); + xorbuf(authTag, A, authTagSz); + + B[15] = 1; + while (inSz >= AES_BLOCK_SIZE) { + AesEncrypt(aes, B, A); + xorbuf(A, in, AES_BLOCK_SIZE); + XMEMCPY(out, A, AES_BLOCK_SIZE); + + AesCcmCtrInc(B, lenSz); + inSz -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + if (inSz > 0) { + AesEncrypt(aes, B, A); + xorbuf(A, in, inSz); + XMEMCPY(out, A, inSz); + } + + XMEMSET(A, 0, AES_BLOCK_SIZE); + XMEMSET(B, 0, AES_BLOCK_SIZE); +} + + +int AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + byte A[AES_BLOCK_SIZE]; + byte B[AES_BLOCK_SIZE]; + byte* o; + word32 i, lenSz, oSz, result = 0; + + o = out; + oSz = inSz; + XMEMCPY(B+1, nonce, nonceSz); + lenSz = AES_BLOCK_SIZE - 1 - nonceSz; + + B[0] = (lenSz - 1); + for (i = 0; i < lenSz; i++) + B[AES_BLOCK_SIZE - 1 - i] = 0; + B[15] = 1; + + while (oSz >= AES_BLOCK_SIZE) { + AesEncrypt(aes, B, A); + xorbuf(A, in, AES_BLOCK_SIZE); + XMEMCPY(o, A, AES_BLOCK_SIZE); + + AesCcmCtrInc(B, lenSz); + oSz -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + o += AES_BLOCK_SIZE; + } + if (inSz > 0) { + AesEncrypt(aes, B, A); + xorbuf(A, in, oSz); + XMEMCPY(o, A, oSz); + } + + for (i = 0; i < lenSz; i++) + B[AES_BLOCK_SIZE - 1 - i] = 0; + AesEncrypt(aes, B, A); + + o = out; + oSz = inSz; + + B[0] = (authInSz > 0 ? 64 : 0) + + (8 * ((authTagSz - 2) / 2)) + + (lenSz - 1); + for (i = 0; i < lenSz; i++) + B[AES_BLOCK_SIZE - 1 - i] = (inSz >> (8 * i)) & 0xFF; + + AesEncrypt(aes, B, A); + if (authInSz > 0) + roll_auth(aes, authIn, authInSz, A); + if (inSz > 0) + roll_x(aes, o, oSz, A); + + B[0] = (lenSz - 1); + for (i = 0; i < lenSz; i++) + B[AES_BLOCK_SIZE - 1 - i] = 0; + AesEncrypt(aes, B, B); + xorbuf(A, B, authTagSz); + + if (XMEMCMP(A, authTag, authTagSz) != 0) { + /* If the authTag check fails, don't keep the decrypted data. + * Unfortunately, you need the decrypted data to calculate the + * check value. */ + XMEMSET(out, 0, inSz); + result = AES_CCM_AUTH_E; + } + + XMEMSET(A, 0, AES_BLOCK_SIZE); + XMEMSET(B, 0, AES_BLOCK_SIZE); + o = NULL; + + return result; +} + +#endif + #endif /* STM32F2_CRYPTO */ int AesSetIV(Aes* aes, const byte* iv) diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index 6629f8e66..96cba9cd4 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -1815,7 +1815,7 @@ static word32 BytePrecision(word32 value) { word32 i; for (i = sizeof(value); i; --i) - if (value >> (i - 1) * 8) + if (value >> ((i - 1) * BIT_SIZE)) break; return i; @@ -1832,7 +1832,7 @@ static word32 SetLength(word32 length, byte* output) output[i++] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH); for (j = BytePrecision(length); j; --j) { - output[i] = (byte)(length >> (j - 1) * 8); + output[i] = (byte)(length >> ((j - 1) * BIT_SIZE)); i++; } } diff --git a/ctaocrypt/src/des3.c b/ctaocrypt/src/des3.c index 06353ffd2..25a5a690f 100644 --- a/ctaocrypt/src/des3.c +++ b/ctaocrypt/src/des3.c @@ -663,7 +663,7 @@ void Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) void Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) { word32 blocks = sz / DES_BLOCK_SIZE; - byte hold[16]; + byte hold[DES_BLOCK_SIZE]; while (blocks--) { XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); diff --git a/ctaocrypt/src/error.c b/ctaocrypt/src/error.c index 6cfe8e729..b4d1eb258 100644 --- a/ctaocrypt/src/error.c +++ b/ctaocrypt/src/error.c @@ -273,6 +273,10 @@ void CTaoCryptErrorString(int error, char* buffer) XSTRNCPY(buffer, "AES-GCM Authentication check fail", max); break; + case AES_CCM_AUTH_E: + XSTRNCPY(buffer, "AES-CCM Authentication check fail", max); + break; + default: XSTRNCPY(buffer, "unknown error number", max); diff --git a/ctaocrypt/test/test.c b/ctaocrypt/test/test.c index 08842fd30..f9bff0550 100644 --- a/ctaocrypt/test/test.c +++ b/ctaocrypt/test/test.c @@ -112,6 +112,7 @@ int des_test(void); int des3_test(void); int aes_test(void); int aesgcm_test(void); +int aesccm_test(void); int rsa_test(void); int dh_test(void); int dsa_test(void); @@ -292,6 +293,13 @@ void ctaocrypt_test(void* args) else printf( "AES-GCM test passed!\n"); #endif + +#ifdef HAVE_AESCCM + if ( (ret = aesccm_test()) ) + err_sys("AES-CCM test failed!\n", ret); + else + printf( "AES-CCM test passed!\n"); +#endif #endif if ( (ret = random_test()) ) @@ -1194,11 +1202,16 @@ int hc128_test(void) HC128 enc; HC128 dec; - Hc128_SetKey(&enc, (byte*)keys[i], (byte*)ivs[i]); - Hc128_SetKey(&dec, (byte*)keys[i], (byte*)ivs[i]); + /* align keys/ivs in plain/cipher buffers */ + memcpy(plain, keys[i], 16); + memcpy(cipher, ivs[i], 16); - Hc128_Process(&enc, cipher, (byte*)test_hc128[i].input, - (word32)test_hc128[i].outLen); + Hc128_SetKey(&enc, plain, cipher); + Hc128_SetKey(&dec, plain, cipher); + + /* align input */ + memcpy(plain, test_hc128[i].input, test_hc128[i].outLen); + Hc128_Process(&enc, cipher, plain, (word32)test_hc128[i].outLen); Hc128_Process(&dec, plain, cipher, (word32)test_hc128[i].outLen); if (memcmp(plain, test_hc128[i].input, test_hc128[i].outLen)) @@ -1219,22 +1232,17 @@ int rabbit_test(void) byte cipher[16]; byte plain[16]; - const char* keys[] = /* align with 3 extra bytes cause null is added */ + const char* keys[] = { - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00", - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\xAC\xC3\x51\xDC\xF1\x62\xFC\x3B\xFE\x36\x3D\x2E\x29\x13\x28\x91" - "\x00\x00\x00" }; - const char* ivs[] = /* align with 3 extra bytes casue null is added */ + const char* ivs[] = { - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00", - "\x59\x7E\x26\xC1\x75\xF5\x73\xC3" - "\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00", + "\x59\x7E\x26\xC1\x75\xF5\x73\xC3", 0 }; @@ -1265,12 +1273,21 @@ int rabbit_test(void) for (i = 0; i < times; ++i) { Rabbit enc; Rabbit dec; + byte* iv; - RabbitSetKey(&enc, (byte*)keys[i], (byte*)ivs[i]); - RabbitSetKey(&dec, (byte*)keys[i], (byte*)ivs[i]); + /* align keys/ivs in plain/cipher buffers */ + memcpy(plain, keys[i], 16); + if (ivs[i]) { + memcpy(cipher, ivs[i], 8); + iv = cipher; + } else + iv = NULL; + RabbitSetKey(&enc, plain, iv); + RabbitSetKey(&dec, plain, iv); - RabbitProcess(&enc, cipher, (byte*)test_rabbit[i].input, - (word32)test_rabbit[i].outLen); + /* align input */ + memcpy(plain, test_rabbit[i].input, test_rabbit[i].outLen); + RabbitProcess(&enc, cipher, plain, (word32)test_rabbit[i].outLen); RabbitProcess(&dec, plain, cipher, (word32)test_rabbit[i].outLen); if (memcmp(plain, test_rabbit[i].input, test_rabbit[i].outLen)) @@ -1501,7 +1518,7 @@ int aesgcm_test(void) const byte iv[] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, - 0xde, 0xca, 0xf8, 0x88, 0x00, 0x00, 0x00, 0x00 + 0xde, 0xca, 0xf8, 0x88 }; const byte p[] = @@ -1541,27 +1558,27 @@ int aesgcm_test(void) 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }; - byte t2[16]; - byte p2[60]; - byte c2[60]; + byte t2[sizeof(t)]; + byte p2[sizeof(c)]; + byte c2[sizeof(p)]; int result; - memset(t2, 0, 16); - memset(c2, 0, 60); - memset(p2, 0, 60); + memset(t2, 0, sizeof(t2)); + memset(c2, 0, sizeof(c2)); + memset(p2, 0, sizeof(p2)); - AesGcmSetKey(&enc, k, sizeof(k), iv); - AesGcmSetExpIV(&enc, iv + /*AES_GCM_IMP_IV_SZ*/ 4); + AesGcmSetKey(&enc, k, sizeof(k)); /* AES-GCM encrypt and decrypt both use AES encrypt internally */ - AesGcmEncrypt(&enc, c2, p, sizeof(c2), t2, sizeof(t2), a, sizeof(a)); + AesGcmEncrypt(&enc, c2, p, sizeof(c2), iv, sizeof(iv), + t2, sizeof(t2), a, sizeof(a)); if (memcmp(c, c2, sizeof(c2))) return -68; if (memcmp(t, t2, sizeof(t2))) return -69; - result = AesGcmDecrypt(&enc, - p2, c2, sizeof(p2), t2, sizeof(t2), a, sizeof(a)); + result = AesGcmDecrypt(&enc, p2, c2, sizeof(p2), iv, sizeof(iv), + t2, sizeof(t2), a, sizeof(a)); if (result != 0) return -70; if (memcmp(p, p2, sizeof(p2))) @@ -1571,6 +1588,93 @@ int aesgcm_test(void) } #endif /* HAVE_AESGCM */ +#ifdef HAVE_AESCCM +int aesccm_test(void) +{ + Aes enc; + + /* key */ + const byte k[] = + { + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf + }; + + /* nonce */ + const byte iv[] = + { + 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xa0, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5 + }; + + /* plaintext */ + const byte p[] = + { + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e + }; + + const byte a[] = + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + + const byte c[] = + { + 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2, + 0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80, + 0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84 + }; + + const byte t[] = + { + 0x17, 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 + }; + + byte t2[sizeof(t)]; + byte p2[sizeof(p)]; + byte c2[sizeof(c)]; + + int result; + + memset(t2, 0, sizeof(t2)); + memset(c2, 0, sizeof(c2)); + memset(p2, 0, sizeof(p2)); + + AesCcmSetKey(&enc, k, sizeof(k)); + /* AES-CCM encrypt and decrypt both use AES encrypt internally */ + AesCcmEncrypt(&enc, c2, p, sizeof(c2), iv, sizeof(iv), + t2, sizeof(t2), a, sizeof(a)); + if (memcmp(c, c2, sizeof(c2))) + return -107; + if (memcmp(t, t2, sizeof(t2))) + return -108; + + result = AesCcmDecrypt(&enc, p2, c2, sizeof(p2), iv, sizeof(iv), + t2, sizeof(t2), a, sizeof(a)); + if (result != 0) + return -109; + if (memcmp(p, p2, sizeof(p2))) + return -110; + + /* Test the authentication failure */ + t2[0]++; /* Corrupt the authentication tag. */ + result = AesCcmDecrypt(&enc, p2, c, sizeof(p2), iv, sizeof(iv), + t2, sizeof(t2), a, sizeof(a)); + if (result == 0) + return -111; + + /* Clear c2 to compare against p2. p2 should be set to zero in case of + * authentication fail. */ + memset(c2, 0, sizeof(c2)); + if (memcmp(p2, c2, sizeof(p2))) + return -112; + + return 0; +} +#endif /* HAVE_AESCCM */ + #endif /* NO_AES */ diff --git a/cyassl/ctaocrypt/aes.h b/cyassl/ctaocrypt/aes.h index 8f1dc327d..4272973da 100644 --- a/cyassl/ctaocrypt/aes.h +++ b/cyassl/ctaocrypt/aes.h @@ -93,18 +93,27 @@ CYASSL_API void AesDecryptDirect(Aes* aes, byte* out, const byte* in); CYASSL_API int AesSetKeyDirect(Aes* aes, const byte* key, word32 len, const byte* iv, int dir); #ifdef HAVE_AESGCM -CYASSL_API void AesGcmSetKey(Aes* aes, const byte* key, word32 len, - const byte* implicitIV); -CYASSL_API void AesGcmSetExpIV(Aes* aes, const byte* iv); -CYASSL_API void AesGcmGetExpIV(Aes* aes, byte* iv); -CYASSL_API void AesGcmIncExpIV(Aes* aes); +CYASSL_API void AesGcmSetKey(Aes* aes, const byte* key, word32 len); CYASSL_API void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz); CYASSL_API int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, const byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz); #endif /* HAVE_AESGCM */ +#ifdef HAVE_AESCCM +CYASSL_API void AesCcmSetKey(Aes* aes, const byte* key, word32 keySz); +CYASSL_API void AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +CYASSL_API int AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +#endif /* HAVE_AESCCM */ #ifdef __cplusplus diff --git a/cyassl/ctaocrypt/error.h b/cyassl/ctaocrypt/error.h index 8a0d58628..308fb1d81 100644 --- a/cyassl/ctaocrypt/error.h +++ b/cyassl/ctaocrypt/error.h @@ -99,6 +99,7 @@ enum { ALT_NAME_E = -177, /* alt name size problem, too big */ AES_GCM_AUTH_E = -180, /* AES-GCM Authentication check failure */ + AES_CCM_AUTH_E = -181, /* AES-CCM Authentication check failure */ MIN_CODE_E = -200 /* errors -101 - -199 */ }; diff --git a/cyassl/ctaocrypt/settings.h b/cyassl/ctaocrypt/settings.h index c8075760e..2890ebd18 100644 --- a/cyassl/ctaocrypt/settings.h +++ b/cyassl/ctaocrypt/settings.h @@ -72,6 +72,13 @@ #include +/* stream ciphers except arc4 need 32bit alignment, intel ok without */ +#if defined(__x86_64__) || defined(__ia64__) || defined(__i386__) + #define NO_XSTREAM_ALIGNMENT +#else + #define XSTREAM_ALIGNMENT +#endif + #ifdef IPHONE #define SIZEOF_LONG_LONG 8 #endif diff --git a/cyassl/ctaocrypt/types.h b/cyassl/ctaocrypt/types.h index 083a87621..82bbaec5b 100644 --- a/cyassl/ctaocrypt/types.h +++ b/cyassl/ctaocrypt/types.h @@ -177,12 +177,14 @@ enum { #define XSTRNSTR(s1,s2,n) mystrnstr((s1),(s2),(n)) #define XSTRNCMP(s1,s2,n) strncmp((s1),(s2),(n)) #define XSTRNCAT(s1,s2,n) strncat((s1),(s2),(n)) + #define XSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n)) #endif -#ifdef HAVE_ECC +#if defined(HAVE_ECC) || defined(HAVE_OCSP) #ifndef CTYPE_USER #include #define XTOUPPER(c) toupper((c)) + #define XISALPHA(c) isalpha((c)) #endif #endif @@ -225,7 +227,8 @@ enum { DYNAMIC_TYPE_DTLS_POOL = 34, DYNAMIC_TYPE_SOCKADDR = 35, DYNAMIC_TYPE_LIBZ = 36, - DYNAMIC_TYPE_ECC = 37 + DYNAMIC_TYPE_ECC = 37, + DYNAMIC_TYPE_TMP_BUFFER = 38 }; /* stack protection */ diff --git a/cyassl/internal.h b/cyassl/internal.h index 6ba7663ab..45eba0a69 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -162,6 +162,10 @@ void c32to24(word32 in, word24 out); #define BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 #define BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 #endif + #if defined (HAVE_AESCCM) + #define BUILD_TLS_RSA_WITH_AES_128_CCM_8_SHA256 + #define BUILD_TLS_RSA_WITH_AES_256_CCM_8_SHA384 + #endif #endif #if !defined(NO_PSK) && !defined(NO_AES) && !defined(NO_TLS) @@ -284,6 +288,10 @@ void c32to24(word32 in, word24 out); #define AES_BLOCK_SIZE 16 #endif +#if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + #define HAVE_AEAD +#endif + /* actual cipher values, 2nd byte */ enum { @@ -353,7 +361,14 @@ enum { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0x2f, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0x30, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0x31, - TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0x32 + TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0x32, + + /* AES-CCM, first byte is 0xC0 but isn't ECC, + * also, in some of the other AES-CCM suites + * there will be second byte number conflicts + * with non-ECC AES-GCM */ + TLS_RSA_WITH_AES_128_CCM_8_SHA256 = 0xa0, + TLS_RSA_WITH_AES_256_CCM_8_SHA384 = 0xa1 }; @@ -459,9 +474,6 @@ enum Misc { AES_256_KEY_SIZE = 32, /* for 256 bit */ AES_192_KEY_SIZE = 24, /* for 192 bit */ AES_IV_SIZE = 16, /* always block size */ - AES_GCM_IMP_IV_SZ = 4, /* Implicit part of IV */ - AES_GCM_EXP_IV_SZ = 8, /* Explicit part of IV */ - AES_GCM_CTR_IV_SZ = 4, /* Counter part of IV */ AES_128_KEY_SIZE = 16, /* for 128 bit */ AEAD_SEQ_OFFSET = 4, /* Auth Data: Sequence number */ @@ -471,6 +483,9 @@ enum Misc { AEAD_LEN_OFFSET = 11, /* Auth Data: Length */ AEAD_AUTH_TAG_SZ = 16, /* Size of the authentication tag */ AEAD_AUTH_DATA_SZ = 13, /* Size of the data to authenticate */ + AEAD_IMP_IV_SZ = 4, /* Size of the implicit IV */ + AEAD_EXP_IV_SZ = 8, /* Size of the explicit IV */ + AEAD_NONCE_SZ = AEAD_EXP_IV_SZ + AEAD_IMP_IV_SZ, HC_128_KEY_SIZE = 16, /* 128 bits */ HC_128_IV_SIZE = 16, /* also 128 bits */ @@ -681,9 +696,9 @@ typedef struct { word32 length; /* total buffer length used */ word32 idx; /* idx to part of length already consumed */ byte* buffer; /* place holder for static or dynamic buffer */ - ALIGN16 byte staticBuffer[STATIC_BUFFER_LEN]; word32 bufferSize; /* current buffer size */ byte dynamicFlag; /* dynamic memory currently in use */ + ALIGN16 byte staticBuffer[STATIC_BUFFER_LEN]; } bufferStatic; /* Cipher Suites holder */ @@ -714,6 +729,13 @@ int SetCipherList(Suites*, const char* list); int EmbedReceive(CYASSL *ssl, char *buf, int sz, void *ctx); CYASSL_LOCAL int EmbedSend(CYASSL *ssl, char *buf, int sz, void *ctx); + + #ifdef HAVE_OCSP + CYASSL_LOCAL + int EmbedOcspLookup(void*, const char*, int, byte*, int, byte**); + CYASSL_LOCAL + void EmbedOcspRespFree(void*, byte*); + #endif #endif #ifdef CYASSL_DTLS @@ -785,10 +807,11 @@ struct CYASSL_OCSP { byte enabled; byte useOverrideUrl; byte useNonce; - char overrideName[80]; - char overridePath[80]; - int overridePort; + char overrideUrl[80]; OCSP_Entry* ocspList; + void* IOCB_OcspCtx; + CallbackIOOcsp CBIOOcsp; + CallbackIOOcspRespFree CBIOOcspRespFree; }; @@ -957,6 +980,7 @@ enum BulkCipherAlgorithm { idea, aes, aes_gcm, + aes_ccm, hc128, /* CyaSSL extensions */ rabbit }; @@ -1038,6 +1062,11 @@ typedef struct Keys { byte server_write_key[AES_256_KEY_SIZE]; byte client_write_IV[AES_IV_SIZE]; /* max sizes */ byte server_write_IV[AES_IV_SIZE]; +#ifdef HAVE_AEAD + byte aead_exp_IV[AEAD_EXP_IV_SZ]; + byte aead_enc_imp_IV[AEAD_IMP_IV_SZ]; + byte aead_dec_imp_IV[AEAD_IMP_IV_SZ]; +#endif word32 peer_sequence_number; word32 sequence_number; diff --git a/cyassl/openssl/evp.h b/cyassl/openssl/evp.h index 3bfe4280b..1ffc3b6aa 100644 --- a/cyassl/openssl/evp.h +++ b/cyassl/openssl/evp.h @@ -123,7 +123,7 @@ typedef struct CYASSL_EVP_CIPHER_CTX { int keyLen; /* user may set for variable */ unsigned char enc; /* if encrypt side, then true */ unsigned char cipherType; - unsigned char iv[64]; /* working iv pointer into cipher */ + unsigned char iv[AES_BLOCK_SIZE]; /* working iv pointer into cipher */ CYASSL_Cipher cipher; } CYASSL_EVP_CIPHER_CTX; diff --git a/cyassl/ssl.h b/cyassl/ssl.h index 0035e1341..fdd6a3221 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -798,6 +798,16 @@ CYASSL_API void CyaSSL_SetIOWriteCtx(CYASSL* ssl, void *ctx); CYASSL_API void CyaSSL_SetIOReadFlags( CYASSL* ssl, int flags); CYASSL_API void CyaSSL_SetIOWriteFlags(CYASSL* ssl, int flags); +typedef int (*CallbackIOOcsp)(void*, const char*, int, + unsigned char*, int, unsigned char**); +typedef void (*CallbackIOOcspRespFree)(void*,unsigned char*); +#ifdef HAVE_OCSP +CYASSL_API void CyaSSL_SetIOOcsp(CYASSL_CTX *ocsp, CallbackIOOcsp cb); +CYASSL_API void CyaSSL_SetIOOcspRespFree(CYASSL_CTX *ocsp, + CallbackIOOcspRespFree cb); +CYASSL_API void CyaSSL_SetIOOcspCtx(CYASSL_CTX *ocsp, void *octx); +#endif + /* CA cache callbacks */ enum { CYASSL_SSLV3 = 0, diff --git a/cyassl/test.h b/cyassl/test.h index 3e01edf69..99b005c62 100644 --- a/cyassl/test.h +++ b/cyassl/test.h @@ -482,12 +482,13 @@ static INLINE int udp_read_connect(SOCKET_T sockfd) return sockfd; } -static INLINE void udp_accept(SOCKET_T* sockfd, int* clientfd, func_args* args) +static INLINE void udp_accept(SOCKET_T* sockfd, int* clientfd, int useAnyAddr, + func_args* args) { SOCKADDR_IN_T addr; (void)args; - build_addr(&addr, yasslIP, yasslPort); + build_addr(&addr, (useAnyAddr ? INADDR_ANY : yasslIP), yasslPort); tcp_socket(sockfd, 1); @@ -523,7 +524,7 @@ static INLINE void tcp_accept(SOCKET_T* sockfd, int* clientfd, func_args* args, socklen_t client_len = sizeof(client); if (udp) { - udp_accept(sockfd, clientfd, args); + udp_accept(sockfd, clientfd, useAnyAddr, args); return; } diff --git a/src/internal.c b/src/internal.c index 70cbfc3c4..ac0f387bf 100644 --- a/src/internal.c +++ b/src/internal.c @@ -204,7 +204,6 @@ static INLINE void c32toa(word32 u32, byte* c) /* convert a 24 bit integer into a 32 bit one */ static INLINE void c24to32(const word24 u24, word32* u32) { - *u32 = 0; *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2]; } @@ -212,7 +211,6 @@ static INLINE void c24to32(const word24 u24, word32* u32) /* convert opaque to 16 bit integer */ static INLINE void ato16(const byte* c, word16* u16) { - *u16 = 0; *u16 = (c[0] << 8) | (c[1]); } @@ -220,7 +218,6 @@ static INLINE void ato16(const byte* c, word16* u16) /* convert opaque to 32 bit integer */ static INLINE void ato32(const byte* c, word32* u32) { - *u32 = 0; *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; } @@ -770,6 +767,20 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveRSA, byte havePSK, } #endif +#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_AES_128_CCM_8_SHA256; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8_SHA384 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_AES_256_CCM_8_SHA384; + } +#endif + #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 if (tls1_2 && haveDH && haveRSA) { suites->suites[idx++] = 0; @@ -2462,7 +2473,7 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx) if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) if (XSTRNCMP((char*)ssl->buffers.domainName.buffer, dCert.subjectCN, - ssl->buffers.domainName.length - 1)) { + ssl->buffers.domainName.length - 1) != 0) { ret = DOMAIN_NAME_MISMATCH; /* try to get peer key still */ } @@ -2603,7 +2614,7 @@ static int DoHelloRequest(CYASSL* ssl, const byte* input, word32* inOutIdx) *inOutIdx += padSz; /* verify */ - if (XMEMCMP(mac, verify, ssl->specs.hash_size)) { + if (XMEMCMP(mac, verify, ssl->specs.hash_size) != 0) { CYASSL_MSG(" hello_request verify mac error"); return VERIFY_MAC_ERROR; } @@ -2642,7 +2653,7 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff) if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo); #endif if (sniff == NO_SNIFF) { - if (XMEMCMP(input + idx, &ssl->verifyHashes, finishedSz)) { + if (XMEMCMP(input + idx, &ssl->verifyHashes, finishedSz) != 0) { CYASSL_MSG("Verify finished error on hashes"); return VERIFY_FINISHED_ERROR; } @@ -2663,7 +2674,7 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff) idx += padSz; /* verify mac */ - if (XMEMCMP(mac, verifyMAC, ssl->specs.hash_size)) { + if (XMEMCMP(mac, verifyMAC, ssl->specs.hash_size) != 0) { CYASSL_MSG("Verify finished error on mac"); return VERIFY_MAC_ERROR; } @@ -2709,18 +2720,29 @@ static int DoHandShakeMsgType(CYASSL* ssl, byte* input, word32* inOutIdx, if (ssl->options.handShakeState == HANDSHAKE_DONE && type != hello_request){ CYASSL_MSG("HandShake message after handshake complete"); + SendAlert(ssl, alert_fatal, unexpected_message); return OUT_OF_ORDER_E; } if (ssl->options.side == CLIENT_END && ssl->options.dtls == 0 && ssl->options.serverState == NULL_STATE && type != server_hello) { CYASSL_MSG("First server message not server hello"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == CLIENT_END && ssl->options.dtls && + type == server_hello_done && + ssl->options.serverState < SERVER_HELLO_COMPLETE) { + CYASSL_MSG("Server hello done received before server hello in DTLS"); + SendAlert(ssl, alert_fatal, unexpected_message); return OUT_OF_ORDER_E; } if (ssl->options.side == SERVER_END && ssl->options.clientState == NULL_STATE && type != client_hello) { CYASSL_MSG("First client message not client hello"); + SendAlert(ssl, alert_fatal, unexpected_message); return OUT_OF_ORDER_E; } @@ -2933,6 +2955,17 @@ static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify) } +#ifdef HAVE_AEAD +static INLINE void AeadIncrementExpIV(CYASSL* ssl) +{ + int i; + for (i = AEAD_EXP_IV_SZ-1; i >= 0; i--) { + if (++ssl->keys.aead_exp_IV[i]) return; + } +} +#endif + + static INLINE int Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz) { (void)out; @@ -2961,10 +2994,13 @@ static INLINE int Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz) case aes: #ifdef CYASSL_AESNI if ((word)input % 16) { - byte buff[MAX_RECORD_SIZE + MAX_COMP_EXTRA+MAX_MSG_EXTRA]; - XMEMCPY(buff, input, sz); - AesCbcEncrypt(ssl->encrypt.aes, buff, buff, sz); - XMEMCPY(out, buff, sz); + byte* tmp = (byte*)XMALLOC(sz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) return MEMORY_E; + XMEMCPY(tmp, input, sz); + AesCbcEncrypt(ssl->encrypt.aes, tmp, tmp, sz); + XMEMCPY(out, tmp, sz); + XFREE(tmp, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); break; } #endif @@ -2976,6 +3012,7 @@ static INLINE int Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz) case aes_gcm: { byte additional[AES_BLOCK_SIZE]; + byte nonce[AEAD_NONCE_SZ]; XMEMSET(additional, 0, AES_BLOCK_SIZE); @@ -2989,26 +3026,92 @@ static INLINE int Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz) /* Store the length of the plain text minus the explicit * IV length minus the authentication tag size. */ - c16toa(sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, + c16toa(sz - AEAD_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, additional + AEAD_LEN_OFFSET); + XMEMCPY(nonce, + ssl->keys.aead_enc_imp_IV, AEAD_IMP_IV_SZ); + XMEMCPY(nonce + AEAD_IMP_IV_SZ, + ssl->keys.aead_exp_IV, AEAD_EXP_IV_SZ); AesGcmEncrypt(ssl->encrypt.aes, - out + AES_GCM_EXP_IV_SZ, input + AES_GCM_EXP_IV_SZ, - sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, + out + AEAD_EXP_IV_SZ, input + AEAD_EXP_IV_SZ, + sz - AEAD_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, + nonce, AEAD_NONCE_SZ, out + sz - AEAD_AUTH_TAG_SZ, AEAD_AUTH_TAG_SZ, additional, AEAD_AUTH_DATA_SZ); - AesGcmIncExpIV(ssl->encrypt.aes); + AeadIncrementExpIV(ssl); + XMEMSET(nonce, 0, AEAD_NONCE_SZ); + } + break; + #endif + + #ifdef HAVE_AESCCM + case aes_ccm: + { + byte additional[AES_BLOCK_SIZE]; + byte nonce[AEAD_NONCE_SZ]; + + XMEMSET(additional, 0, AES_BLOCK_SIZE); + + /* sequence number field is 64-bits, we only use 32-bits */ + c32toa(GetSEQIncrement(ssl, 0), + additional + AEAD_SEQ_OFFSET); + + /* Store the type, version. Unfortunately, they are in + * the input buffer ahead of the plaintext. */ + XMEMCPY(additional + AEAD_TYPE_OFFSET, input - 5, 3); + + /* Store the length of the plain text minus the explicit + * IV length minus the authentication tag size. */ + c16toa(sz - AEAD_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, + additional + AEAD_LEN_OFFSET); + XMEMCPY(nonce, + ssl->keys.aead_enc_imp_IV, AEAD_IMP_IV_SZ); + XMEMCPY(nonce + AEAD_IMP_IV_SZ, + ssl->keys.aead_exp_IV, AEAD_EXP_IV_SZ); + AesCcmEncrypt(ssl->encrypt.aes, + out + AEAD_EXP_IV_SZ, input + AEAD_EXP_IV_SZ, + sz - AEAD_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, + nonce, AEAD_NONCE_SZ, + out + sz - AEAD_AUTH_TAG_SZ, AEAD_AUTH_TAG_SZ, + additional, AEAD_AUTH_DATA_SZ); + AeadIncrementExpIV(ssl); + XMEMSET(nonce, 0, AEAD_NONCE_SZ); } break; #endif #ifdef HAVE_HC128 case hc128: + #ifdef XSTREAM_ALIGNMENT + if ((word)input % 4) { + byte* tmp = (byte*)XMALLOC(sz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) return MEMORY_E; + XMEMCPY(tmp, input, sz); + Hc128_Process(ssl->encrypt.hc128, tmp, tmp, sz); + XMEMCPY(out, tmp, sz); + XFREE(tmp, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + break; + } + #endif Hc128_Process(ssl->encrypt.hc128, out, input, sz); break; #endif #ifdef BUILD_RABBIT case rabbit: + #ifdef XSTREAM_ALIGNMENT + if ((word)input % 4) { + byte* tmp = (byte*)XMALLOC(sz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) return MEMORY_E; + XMEMCPY(tmp, input, sz); + RabbitProcess(ssl->encrypt.rabbit, tmp, tmp, sz); + XMEMCPY(out, tmp, sz); + XFREE(tmp, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + break; + } + #endif RabbitProcess(ssl->encrypt.rabbit, out, input, sz); break; #endif @@ -3065,8 +3168,8 @@ static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input, case aes_gcm: { byte additional[AES_BLOCK_SIZE]; + byte nonce[AEAD_NONCE_SZ]; - AesGcmSetExpIV(ssl->decrypt.aes, input); XMEMSET(additional, 0, AES_BLOCK_SIZE); /* sequence number field is 64-bits, we only use 32-bits */ @@ -3076,17 +3179,57 @@ static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input, additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; - c16toa(sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, + c16toa(sz - AEAD_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, additional + AEAD_LEN_OFFSET); + XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AEAD_IMP_IV_SZ); + XMEMCPY(nonce + AEAD_IMP_IV_SZ, input, AEAD_EXP_IV_SZ); if (AesGcmDecrypt(ssl->decrypt.aes, - plain + AES_GCM_EXP_IV_SZ, - input + AES_GCM_EXP_IV_SZ, - sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, + plain + AEAD_EXP_IV_SZ, + input + AEAD_EXP_IV_SZ, + sz - AEAD_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, + nonce, AEAD_NONCE_SZ, input + sz - AEAD_AUTH_TAG_SZ, AEAD_AUTH_TAG_SZ, additional, AEAD_AUTH_DATA_SZ) < 0) { SendAlert(ssl, alert_fatal, bad_record_mac); + XMEMSET(nonce, 0, AEAD_NONCE_SZ); return VERIFY_MAC_ERROR; } + XMEMSET(nonce, 0, AEAD_NONCE_SZ); + break; + } + #endif + + #ifdef HAVE_AESCCM + case aes_ccm: + { + byte additional[AES_BLOCK_SIZE]; + byte nonce[AEAD_NONCE_SZ]; + + XMEMSET(additional, 0, AES_BLOCK_SIZE); + + /* sequence number field is 64-bits, we only use 32-bits */ + c32toa(GetSEQIncrement(ssl, 1), additional + AEAD_SEQ_OFFSET); + + additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; + additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; + additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; + + c16toa(sz - AEAD_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, + additional + AEAD_LEN_OFFSET); + XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AEAD_IMP_IV_SZ); + XMEMCPY(nonce + AEAD_IMP_IV_SZ, input, AEAD_EXP_IV_SZ); + if (AesCcmDecrypt(ssl->decrypt.aes, + plain + AEAD_EXP_IV_SZ, + input + AEAD_EXP_IV_SZ, + sz - AEAD_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, + nonce, AEAD_NONCE_SZ, + input + sz - AEAD_AUTH_TAG_SZ, AEAD_AUTH_TAG_SZ, + additional, AEAD_AUTH_DATA_SZ) < 0) { + SendAlert(ssl, alert_fatal, bad_record_mac); + XMEMSET(nonce, 0, AEAD_NONCE_SZ); + return VERIFY_MAC_ERROR; + } + XMEMSET(nonce, 0, AEAD_NONCE_SZ); break; } #endif @@ -3171,7 +3314,7 @@ static int DecryptMessage(CYASSL* ssl, byte* input, word32 sz, word32* idx) if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) *idx += ssl->specs.block_size; /* go past TLSv1.1 IV */ if (ssl->specs.cipher_type == aead) - *idx += AES_GCM_EXP_IV_SZ; + *idx += AEAD_EXP_IV_SZ; } return decryptResult; @@ -3453,6 +3596,7 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx) if (ssl->options.handShakeState != HANDSHAKE_DONE) { CYASSL_MSG("Received App data before handshake complete"); + SendAlert(ssl, alert_fatal, unexpected_message); return OUT_OF_ORDER_E; } @@ -3483,7 +3627,7 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx) } } else if (ssl->specs.cipher_type == aead) { - ivExtra = AES_GCM_EXP_IV_SZ; + ivExtra = AEAD_EXP_IV_SZ; digestSz = AEAD_AUTH_TAG_SZ; } @@ -3562,7 +3706,7 @@ static int DoAlert(CYASSL* ssl, byte* input, word32* inOutIdx, int* type) *inOutIdx += (ssl->specs.hash_size + padSz); /* verify */ - if (XMEMCMP(mac, verify, ssl->specs.hash_size)) { + if (XMEMCMP(mac, verify, ssl->specs.hash_size) != 0) { CYASSL_MSG(" alert verify mac error"); return VERIFY_MAC_ERROR; } @@ -4121,11 +4265,11 @@ static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz, sz += pad; } -#ifdef BUILD_AESGCM +#ifdef HAVE_AEAD if (ssl->specs.cipher_type == aead) { - ivSz = AES_GCM_EXP_IV_SZ; + ivSz = AEAD_EXP_IV_SZ; sz += (ivSz + 16 - digestSz); - AesGcmGetExpIV(ssl->encrypt.aes, iv); + XMEMCPY(iv, ssl->keys.aead_exp_IV, AEAD_EXP_IV_SZ); } #endif size = (word16)(sz - headerSz); /* include mac and digest */ @@ -4584,14 +4728,18 @@ int SendAlert(CYASSL* ssl, int severity, int type) if (ssl->keys.encryptionOn && ssl->options.handShakeState == HANDSHAKE_DONE) sendSz = BuildMessage(ssl, output, input, ALERT_SIZE, alert); else { - RecordLayerHeader *const rl = (RecordLayerHeader*)output; - rl->type = alert; - rl->pvMajor = ssl->version.major; - rl->pvMinor = ssl->version.minor; - c16toa(ALERT_SIZE, rl->length); - XMEMCPY(output + RECORD_HEADER_SZ, input, ALERT_SIZE); + AddRecordHeader(output, ALERT_SIZE, alert, ssl); + output += RECORD_HEADER_SZ; + #ifdef CYASSL_DTLS + output += DTLS_RECORD_EXTRA; + #endif + XMEMCPY(output, input, ALERT_SIZE); + sendSz = RECORD_HEADER_SZ + ALERT_SIZE; + #ifdef CYASSL_DTLS + sendSz += DTLS_RECORD_EXTRA; + #endif } #ifdef CYASSL_CALLBACKS @@ -5035,6 +5183,14 @@ const char* const cipher_names[] = "NTRU-AES256-SHA", #endif +#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8_SHA256 + "AES128-CCM-8-SHA256", +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8_SHA384 + "AES256-CCM-8-SHA384", +#endif + #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA "ECDHE-RSA-AES128-SHA", #endif @@ -5255,6 +5411,14 @@ int cipher_name_idx[] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA, #endif +#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8_SHA256 + TLS_RSA_WITH_AES_128_CCM_8_SHA256, +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8_SHA384 + TLS_RSA_WITH_AES_256_CCM_8_SHA384, +#endif + #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, #endif @@ -5427,7 +5591,7 @@ int SetCipherList(Suites* s, const char* list) for (i = 0; i < suiteSz; i++) if (XSTRNCMP(name, cipher_names[i], sizeof(name)) == 0) { - if (XSTRSTR(name, "EC")) + if (XSTRSTR(name, "EC") || XSTRSTR(name, "CCM")) s->suites[idx++] = ECC_BYTE; /* ECC suite */ else s->suites[idx++] = 0x00; /* normal */ @@ -6106,7 +6270,7 @@ int SetCipherList(Suites* s, const char* list) return VERIFY_SIGN_ERROR; } else { - if (ret != sizeof(hash) || XMEMCMP(out, hash, sizeof(hash))) + if (ret != sizeof(hash) || XMEMCMP(out, hash,sizeof(hash)) != 0) return VERIFY_SIGN_ERROR; } } @@ -6817,8 +6981,6 @@ int SetCipherList(Suites* s, const char* list) Md5 md5; Sha sha; byte hash[FINISHED_SZ]; - byte* signBuffer = hash; - word32 signSz = sizeof(hash); /* md5 */ InitMd5(&md5); @@ -6835,7 +6997,9 @@ int SetCipherList(Suites* s, const char* list) ShaFinal(&sha, &hash[MD5_DIGEST_SIZE]); if (ssl->specs.sig_algo == rsa_sa_algo) { - byte encodedSig[MAX_ENCODED_SIG_SZ]; + byte* signBuffer = hash; + word32 signSz = sizeof(hash); + byte encodedSig[MAX_ENCODED_SIG_SZ]; if (IsAtLeastTLSv1_2(ssl)) { byte* digest; int hType; @@ -7019,8 +7183,6 @@ int SetCipherList(Suites* s, const char* list) Md5 md5; Sha sha; byte hash[FINISHED_SZ]; - byte* signBuffer = hash; - word32 signSz = sizeof(hash); /* md5 */ InitMd5(&md5); @@ -7037,7 +7199,9 @@ int SetCipherList(Suites* s, const char* list) ShaFinal(&sha, &hash[MD5_DIGEST_SIZE]); if (ssl->specs.sig_algo == rsa_sa_algo) { - byte encodedSig[MAX_ENCODED_SIG_SZ]; + byte* signBuffer = hash; + word32 signSz = sizeof(hash); + byte encodedSig[MAX_ENCODED_SIG_SZ]; if (IsAtLeastTLSv1_2(ssl)) { byte* digest; int typeH; @@ -7244,6 +7408,14 @@ int SetCipherList(Suites* s, const char* list) return 1; break; + case TLS_RSA_WITH_AES_128_CCM_8_SHA256 : + case TLS_RSA_WITH_AES_256_CCM_8_SHA384 : + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_RSA_SIG) + return 1; + break; + default: CYASSL_MSG("Unsupported cipher suite, CipherRequires ECC"); return 0; @@ -8043,6 +8215,7 @@ int SetCipherList(Suites* s, const char* list) if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { CYASSL_MSG("Client sending keyexchange at wrong time"); + SendAlert(ssl, alert_fatal, unexpected_message); return OUT_OF_ORDER_E; } diff --git a/src/io.c b/src/io.c index a6344ebfd..259297325 100644 --- a/src/io.c +++ b/src/io.c @@ -463,6 +463,276 @@ int EmbedGenerateCookie(byte *buf, int sz, void *ctx) #endif /* CYASSL_DTLS */ +#ifdef HAVE_OCSP + +#ifdef TEST_IPV6 + typedef struct sockaddr_in6 SOCKADDR_IN_T; + #define AF_INET_V AF_INET6 +#else + typedef struct sockaddr_in SOCKADDR_IN_T; + #define AF_INET_V AF_INET +#endif + + +static INLINE int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port) +{ + SOCKADDR_IN_T addr; + const char* host = ip; + + /* peer could be in human readable form */ + if (ip != INADDR_ANY && isalpha(ip[0])) { + struct hostent* entry = gethostbyname(ip); + + if (entry) { + struct sockaddr_in tmp; + XMEMSET(&tmp, 0, sizeof(struct sockaddr_in)); + XMEMCPY(&tmp.sin_addr.s_addr, entry->h_addr_list[0], + entry->h_length); + host = inet_ntoa(tmp.sin_addr); + } + else { + CYASSL_MSG("no addr entry for OCSP responder"); + return -1; + } + } + + *sockfd = socket(AF_INET_V, SOCK_STREAM, 0); + XMEMSET(&addr, 0, sizeof(SOCKADDR_IN_T)); + + addr.sin_family = AF_INET_V; + addr.sin_port = htons(port); + if (host == INADDR_ANY) + addr.sin_addr.s_addr = INADDR_ANY; + else + addr.sin_addr.s_addr = inet_addr(host); + + if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) { + CYASSL_MSG("OCSP responder tcp connect failed"); + return -1; + } + + return 0; +} + + +static int build_http_request(const char* domainName, const char* path, + int ocspReqSz, byte* buf, int bufSize) +{ + return snprintf((char*)buf, bufSize, + "POST %s HTTP/1.1\r\n" + "Host: %s\r\n" + "Content-Length: %d\r\n" + "Content-Type: application/ocsp-request\r\n" + "\r\n", + path, domainName, ocspReqSz); +} + + +static int decode_http_response(byte* httpBuf, int httpBufSz, byte** dst) +{ + int idx = 0; + int stop = 0; + int len = 0; + byte* contentType = NULL; + byte* contentLength = NULL; + char* buf = (char*)httpBuf; /* kludge so I'm not constantly casting */ + + if (XSTRNCASECMP(buf, "HTTP/1", 6) != 0) + return 0; + + idx = 9; /* sets to the first byte after "HTTP/1.X ", which should be the + * HTTP result code */ + + if (XSTRNCASECMP(&buf[idx], "200 OK", 6) != 0) + return 0; + + idx += 8; + + while (idx < httpBufSz && !stop) { + if (buf[idx] == '\r' && buf[idx+1] == '\n') { + stop = 1; + idx += 2; + } + else { + if (contentType == NULL && + XSTRNCASECMP(&buf[idx], "Content-Type:", 13) == 0) { + idx += 13; + if (buf[idx] == ' ') idx++; + if (XSTRNCASECMP(&buf[idx], + "application/ocsp-response", 25) != 0) { + return 0; + } + idx += 27; + } + else if (contentLength == NULL && + XSTRNCASECMP(&buf[idx], "Content-Length:", 15) == 0) { + idx += 15; + if (buf[idx] == ' ') idx++; + while (buf[idx] >= '0' && buf[idx] <= '9' && idx < httpBufSz) { + len = (len * 10) + (buf[idx] - '0'); + idx++; + } + idx += 2; /* skip the crlf */ + } + else { + /* Advance idx past the next \r\n */ + char* end = XSTRSTR(&buf[idx], "\r\n"); + idx = (int)(end - buf + 2); + stop = 1; + } + } + } + + if (len > 0) { + *dst = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_IN_BUFFER); + XMEMCPY(*dst, httpBuf + idx, len); + } + + return len; +} + + +static int decode_url(const char* url, int urlSz, + char* outName, char* outPath, int* outPort) +{ + if (outName != NULL && outPath != NULL && outPort != NULL) + { + if (url == NULL || urlSz == 0) + { + *outName = 0; + *outPath = 0; + *outPort = 0; + } + else + { + int i, cur; + + /* need to break the url down into scheme, address, and port */ + /* "http://example.com:8080/" */ + if (XSTRNCMP(url, "http://", 7) == 0) { + cur = 7; + } else cur = 0; + + i = 0; + while (url[cur] != 0 && url[cur] != ':' && url[cur] != '/') { + outName[i++] = url[cur++]; + } + outName[i] = 0; + /* Need to pick out the path after the domain name */ + + if (cur < urlSz && url[cur] == ':') { + char port[6]; + int j; + i = 0; + cur++; + while (cur < urlSz && url[cur] != 0 && url[cur] != '/' && + i < 6) { + port[i++] = url[cur++]; + } + + *outPort = 0; + for (j = 0; j < i; j++) { + if (port[j] < '0' || port[j] > '9') return -1; + *outPort = (*outPort * 10) + (port[j] - '0'); + } + } + else + *outPort = 80; + + if (cur < urlSz && url[cur] == '/') { + i = 0; + while (cur < urlSz && url[cur] != 0 && i < 80) { + outPath[i++] = url[cur++]; + } + outPath[i] = 0; + } + else { + outPath[0] = '/'; + outPath[1] = 0; + } + } + } + + return 0; +} + + +#define SCRATCH_BUFFER_SIZE 2048 + +int EmbedOcspLookup(void* ctx, const char* url, int urlSz, + byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf) +{ + char domainName[80], path[80]; + int port, httpBufSz, sfd; + int ocspRespSz = 0; + byte* httpBuf = NULL; + + (void)ctx; + + if (ocspReqBuf == NULL || ocspReqSz == 0) { + CYASSL_MSG("OCSP request is required for lookup"); + return -1; + } + + if (ocspRespBuf == NULL) { + CYASSL_MSG("Cannot save OCSP response"); + return -1; + } + + if (decode_url(url, urlSz, domainName, path, &port) < 0) { + CYASSL_MSG("Unable to decode OCSP URL"); + return -1; + } + + httpBufSz = SCRATCH_BUFFER_SIZE; + httpBuf = (byte*)XMALLOC(httpBufSz, NULL, DYNAMIC_TYPE_IN_BUFFER); + + if (httpBuf == NULL) { + CYASSL_MSG("Unable to create OCSP response buffer"); + return -1; + } + *ocspRespBuf = httpBuf; + + httpBufSz = build_http_request(domainName, path, ocspReqSz, + httpBuf, httpBufSz); + + if ((tcp_connect(&sfd, domainName, port) == 0) && (sfd > 0)) { + int written; + written = (int)write(sfd, httpBuf, httpBufSz); + if (written == httpBufSz) { + written = (int)write(sfd, ocspReqBuf, ocspReqSz); + if (written == ocspReqSz) { + httpBufSz = (int)read(sfd, httpBuf, SCRATCH_BUFFER_SIZE); + if (httpBufSz > 0) { + ocspRespSz = decode_http_response(httpBuf, httpBufSz, + ocspRespBuf); + } + } + } + close(sfd); + if (ocspRespSz == 0) { + CYASSL_MSG("OCSP response was not OK, no OCSP response"); + return -1; + } + } else { + CYASSL_MSG("OCSP Responder connection failed"); + return -1; + } + + return ocspRespSz; +} + + +void EmbedOcspRespFree(void* ctx, byte *resp) +{ + (void)ctx; + + if (resp) + XFREE(resp, NULL, DYNAMIC_TYPE_IN_BUFFER); +} + + +#endif #endif /* CYASSL_USER_IO */ @@ -501,3 +771,22 @@ CYASSL_API void CyaSSL_SetIOWriteFlags(CYASSL* ssl, int flags) ssl->wflags = flags; } +#ifdef HAVE_OCSP + +CYASSL_API void CyaSSL_SetIOOcsp(CYASSL_CTX* ctx, CallbackIOOcsp cb) +{ + ctx->ocsp.CBIOOcsp = cb; +} + +CYASSL_API void CyaSSL_SetIOOcspRespFree(CYASSL_CTX* ctx, + CallbackIOOcspRespFree cb) +{ + ctx->ocsp.CBIOOcspRespFree = cb; +} + +CYASSL_API void CyaSSL_SetIOOcspCtx(CYASSL_CTX* ctx, void *octx) +{ + ctx->ocsp.IOCB_OcspCtx = octx; +} + +#endif diff --git a/src/keys.c b/src/keys.c index cb5f845a4..2ab48a93c 100644 --- a/src/keys.c +++ b/src/keys.c @@ -37,12 +37,13 @@ int SetCipherSpecs(CYASSL* ssl) { -#ifdef HAVE_ECC - /* ECC extensions */ + /* ECC extensions, or AES-CCM */ if (ssl->options.cipherSuite0 == ECC_BYTE) { switch (ssl->options.cipherSuite) { +#ifdef HAVE_ECC + #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA : ssl->specs.bulk_cipher_algorithm = aes; @@ -327,7 +328,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; + ssl->specs.iv_size = AEAD_IMP_IV_SZ; break; #endif @@ -344,7 +345,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; + ssl->specs.iv_size = AEAD_IMP_IV_SZ; break; #endif @@ -361,7 +362,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; + ssl->specs.iv_size = AEAD_IMP_IV_SZ; break; #endif @@ -378,7 +379,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; + ssl->specs.iv_size = AEAD_IMP_IV_SZ; break; #endif @@ -395,7 +396,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; + ssl->specs.iv_size = AEAD_IMP_IV_SZ; break; #endif @@ -412,7 +413,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; + ssl->specs.iv_size = AEAD_IMP_IV_SZ; break; #endif @@ -429,7 +430,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; + ssl->specs.iv_size = AEAD_IMP_IV_SZ; break; #endif @@ -446,17 +447,49 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; + ssl->specs.iv_size = AEAD_IMP_IV_SZ; break; #endif +#endif /* HAVE_ECC */ + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8_SHA256 + case TLS_RSA_WITH_AES_128_CCM_8_SHA256 : + ssl->specs.bulk_cipher_algorithm = aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AEAD_IMP_IV_SZ; + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8_SHA384 + case TLS_RSA_WITH_AES_256_CCM_8_SHA384 : + ssl->specs.bulk_cipher_algorithm = aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AEAD_IMP_IV_SZ; + break; +#endif default: CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs ECC"); return UNSUPPORTED_SUITE; } /* switch */ } /* if */ -#endif /* HAVE_ECC */ if (ssl->options.cipherSuite0 != ECC_BYTE) { /* normal suites */ switch (ssl->options.cipherSuite) { @@ -881,7 +914,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; + ssl->specs.iv_size = AEAD_IMP_IV_SZ; break; #endif @@ -898,7 +931,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; + ssl->specs.iv_size = AEAD_IMP_IV_SZ; break; #endif @@ -915,7 +948,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; + ssl->specs.iv_size = AEAD_IMP_IV_SZ; break; #endif @@ -932,7 +965,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; + ssl->specs.iv_size = AEAD_IMP_IV_SZ; break; #endif @@ -1006,7 +1039,7 @@ static int SetPrefix(byte* sha_input, int idx) static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, - byte side, void* heap, RNG* rng) + byte side, void* heap) { #ifdef BUILD_ARC4 word32 sz = specs->key_size; @@ -1136,7 +1169,6 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, #ifdef BUILD_AESGCM if (specs->bulk_cipher_algorithm == aes_gcm) { - byte iv[AES_GCM_EXP_IV_SZ]; enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); if (enc->aes == NULL) return MEMORY_E; @@ -1144,21 +1176,51 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec->aes == NULL) return MEMORY_E; - /* Initialize the AES-GCM explicit IV to a random number. */ - RNG_GenerateBlock(rng, iv, sizeof(iv)); - AesGcmSetExpIV(enc->aes, iv); - if (side == CLIENT_END) { - AesGcmSetKey(enc->aes, keys->client_write_key, specs->key_size, - keys->client_write_IV); - AesGcmSetKey(dec->aes, keys->server_write_key, specs->key_size, - keys->server_write_IV); + AesGcmSetKey(enc->aes, keys->client_write_key, specs->key_size); + XMEMCPY(keys->aead_enc_imp_IV, + keys->client_write_IV, AEAD_IMP_IV_SZ); + AesGcmSetKey(dec->aes, keys->server_write_key, specs->key_size); + XMEMCPY(keys->aead_dec_imp_IV, + keys->server_write_IV, AEAD_IMP_IV_SZ); } else { - AesGcmSetKey(enc->aes, keys->server_write_key, specs->key_size, - keys->server_write_IV); - AesGcmSetKey(dec->aes, keys->client_write_key, specs->key_size, - keys->client_write_IV); + AesGcmSetKey(enc->aes, keys->server_write_key, specs->key_size); + XMEMCPY(keys->aead_enc_imp_IV, + keys->server_write_IV, AEAD_IMP_IV_SZ); + AesGcmSetKey(dec->aes, keys->client_write_key, specs->key_size); + XMEMCPY(keys->aead_dec_imp_IV, + keys->client_write_IV, AEAD_IMP_IV_SZ); + } + enc->setup = 1; + dec->setup = 1; + } +#endif + +#ifdef HAVE_AESCCM + if (specs->bulk_cipher_algorithm == aes_ccm) { + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc->aes == NULL) + return MEMORY_E; + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec->aes == NULL) + return MEMORY_E; + + if (side == CLIENT_END) { + AesCcmSetKey(enc->aes, keys->client_write_key, specs->key_size); + XMEMCPY(keys->aead_enc_imp_IV, + keys->client_write_IV, AEAD_IMP_IV_SZ); + AesCcmSetKey(dec->aes, keys->server_write_key, specs->key_size); + XMEMCPY(keys->aead_dec_imp_IV, + keys->server_write_IV, AEAD_IMP_IV_SZ); + } + else { + AesCcmSetKey(enc->aes, keys->server_write_key, specs->key_size); + XMEMCPY(keys->aead_enc_imp_IV, + keys->server_write_IV, AEAD_IMP_IV_SZ); + AesCcmSetKey(dec->aes, keys->client_write_key, specs->key_size); + XMEMCPY(keys->aead_dec_imp_IV, + keys->client_write_IV, AEAD_IMP_IV_SZ); } enc->setup = 1; dec->setup = 1; @@ -1175,7 +1237,6 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, keys->sequence_number = 0; keys->peer_sequence_number = 0; keys->encryptionOn = 0; - (void)rng; (void)side; (void)heap; (void)enc; @@ -1209,8 +1270,15 @@ int StoreKeys(CYASSL* ssl, const byte* keyData) i += sz; XMEMCPY(ssl->keys.server_write_IV, &keyData[i], sz); +#ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + /* Initialize the AES-GCM explicit IV to a random number. */ + RNG_GenerateBlock(ssl->rng, ssl->keys.aead_exp_IV, AEAD_EXP_IV_SZ); + } +#endif + return SetKeys(&ssl->encrypt, &ssl->decrypt, &ssl->keys, &ssl->specs, - ssl->options.side, ssl->heap, ssl->rng); + ssl->options.side, ssl->heap); } #ifndef NO_OLD_TLS diff --git a/src/ocsp.c b/src/ocsp.c index c012f27e5..1826e6ee8 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -54,6 +54,7 @@ CYASSL_API int ocsp_test(unsigned char* buf, int sz); #define CYASSL_OCSP_ENABLE 0x0001 /* Enable OCSP lookups */ #define CYASSL_OCSP_URL_OVERRIDE 0x0002 /* Use the override URL instead of URL * in certificate */ +#define CYASSL_OCSP_NO_NONCE 0x0004 /* Disables the request nonce */ typedef struct sockaddr_in SOCKADDR_IN_T; #define AF_INET_V AF_INET @@ -65,6 +66,10 @@ int CyaSSL_OCSP_Init(CYASSL_OCSP* ocsp) if (ocsp != NULL) { XMEMSET(ocsp, 0, sizeof(*ocsp)); ocsp->useNonce = 1; + #ifndef CYASSL_USER_IO + ocsp->CBIOOcsp = EmbedOcspLookup; + ocsp->CBIOOcspRespFree = EmbedOcspRespFree; + #endif return 0; } @@ -100,201 +105,20 @@ void CyaSSL_OCSP_Cleanup(CYASSL_OCSP* ocsp) } -static int decode_url(const char* url, int urlSz, - char* outName, char* outPath, int* outPort) -{ - if (outName != NULL && outPath != NULL && outPort != NULL) - { - if (url == NULL || urlSz == 0) - { - *outName = 0; - *outPath = 0; - *outPort = 0; - } - else - { - int i, cur; - - /* need to break the url down into scheme, address, and port */ - /* "http://example.com:8080/" */ - if (XSTRNCMP(url, "http://", 7) == 0) { - cur = 7; - } else cur = 0; - - i = 0; - while (url[cur] != 0 && url[cur] != ':' && url[cur] != '/') { - outName[i++] = url[cur++]; - } - outName[i] = 0; - /* Need to pick out the path after the domain name */ - - if (cur < urlSz && url[cur] == ':') { - char port[6]; - int j; - i = 0; - cur++; - while (cur < urlSz && url[cur] != 0 && url[cur] != '/' && - i < 6) { - port[i++] = url[cur++]; - } - - *outPort = 0; - for (j = 0; j < i; j++) { - if (port[j] < '0' || port[j] > '9') return -1; - *outPort = (*outPort * 10) + (port[j] - '0'); - } - } - else - *outPort = 80; - - if (cur < urlSz && url[cur] == '/') { - i = 0; - while (cur < urlSz && url[cur] != 0 && i < 80) { - outPath[i++] = url[cur++]; - } - outPath[i] = 0; - } - else { - outPath[0] = '/'; - outPath[1] = 0; - } - } - } - - return 0; -} - - int CyaSSL_OCSP_set_override_url(CYASSL_OCSP* ocsp, const char* url) { if (ocsp != NULL) { int urlSz = (int)XSTRLEN(url); - decode_url(url, urlSz, - ocsp->overrideName, ocsp->overridePath, &ocsp->overridePort); - return 1; + if (urlSz < (int)sizeof(ocsp->overrideUrl)) { + XSTRNCPY(ocsp->overrideUrl, url, urlSz); + return 1; + } } return 0; } -static INLINE void tcp_socket(SOCKET_T* sockfd, SOCKADDR_IN_T* addr, - const char* peer, word16 port) -{ - const char* host = peer; - - /* peer could be in human readable form */ - if (peer != INADDR_ANY && isalpha(peer[0])) { - struct hostent* entry = gethostbyname(peer); - - if (entry) { - struct sockaddr_in tmp; - memset(&tmp, 0, sizeof(struct sockaddr_in)); - memcpy(&tmp.sin_addr.s_addr, entry->h_addr_list[0], - entry->h_length); - host = inet_ntoa(tmp.sin_addr); - } - else { - CYASSL_MSG("no entry for host"); - } - } - - *sockfd = socket(AF_INET_V, SOCK_STREAM, 0); - memset(addr, 0, sizeof(SOCKADDR_IN_T)); - - addr->sin_family = AF_INET_V; - addr->sin_port = htons(port); - if (host == INADDR_ANY) - addr->sin_addr.s_addr = INADDR_ANY; - else - addr->sin_addr.s_addr = inet_addr(host); -} - - -static INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port) -{ - SOCKADDR_IN_T addr; - tcp_socket(sockfd, &addr, ip, port); - - if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) { - CYASSL_MSG("tcp connect failed"); - } -} - - -static int build_http_request(const char* domainName, const char* path, - int ocspReqSz, byte* buf, int bufSize) -{ - return snprintf((char*)buf, bufSize, - "POST %s HTTP/1.1\r\n" - "Host: %s\r\n" - "Content-Length: %d\r\n" - "Content-Type: application/ocsp-request\r\n" - "\r\n", - path, domainName, ocspReqSz); -} - - -static int decode_http_response(byte* httpBuf, int httpBufSz, byte** dst) -{ - int idx = 0; - int stop = 0; - int len = 0; - byte* contentType = NULL; - byte* contentLength = NULL; - char* buf = (char*)httpBuf; /* kludge so I'm not constantly casting */ - - if (strncasecmp(buf, "HTTP/1", 6) != 0) - return 0; - - idx = 9; /* sets to the first byte after "HTTP/1.X ", which should be the - * HTTP result code */ - - if (strncasecmp(&buf[idx], "200 OK", 6) != 0) - return 0; - - idx += 8; - - while (idx < httpBufSz && !stop) { - if (buf[idx] == '\r' && buf[idx+1] == '\n') { - stop = 1; - idx += 2; - } - else { - if (contentType == NULL && - strncasecmp(&buf[idx], "Content-Type:", 13) == 0) { - idx += 13; - if (buf[idx] == ' ') idx++; - if (strncasecmp(&buf[idx], "application/ocsp-response", 25) != 0) - return 0; - idx += 27; - } else if (contentLength == NULL && - strncasecmp(&buf[idx], "Content-Length:", 15) == 0) { - idx += 15; - if (buf[idx] == ' ') idx++; - while (buf[idx] >= '0' && buf[idx] <= '9' && idx < httpBufSz) { - len = (len * 10) + (buf[idx] - '0'); - idx++; - } - idx += 2; /* skip the crlf */ - } else { - /* Advance idx past the next \r\n */ - char* end = XSTRSTR(&buf[idx], "\r\n"); - idx = (int)(end - buf + 2); - stop = 1; - } - } - } - - if (len > 0) { - *dst = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_IN_BUFFER); - XMEMCPY(*dst, httpBuf + idx, len); - } - - return len; -} - - static int InitOCSP_Entry(OCSP_Entry* ocspe, DecodedCert* cert) { CYASSL_ENTER("InitOCSP_Entry"); @@ -382,61 +206,6 @@ static CertStatus* find_cert_status(OCSP_Entry* ocspe, DecodedCert* cert) } -#define SCRATCH_BUFFER_SIZE 2048 - -static int http_ocsp_transaction(CYASSL_OCSP* ocsp, DecodedCert* cert, - byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf) -{ - SOCKET_T sfd = -1; - byte httpBuf[SCRATCH_BUFFER_SIZE]; - int httpBufSz = SCRATCH_BUFFER_SIZE; - char domainName[80], path[80]; - int port, ocspRespSz; - - if (ocsp->useOverrideUrl || cert->extAuthInfo == NULL) { - if (ocsp->overrideName != NULL) { - XMEMCPY(domainName, ocsp->overrideName, 80); - XMEMCPY(path, ocsp->overridePath, 80); - port = ocsp->overridePort; - } else - return OCSP_NEED_URL; - } else { - if (!decode_url((const char*)cert->extAuthInfo, cert->extAuthInfoSz, - domainName, path, &port)) - return OCSP_NEED_URL; - } - - httpBufSz = build_http_request(domainName, path, ocspReqSz, - httpBuf, httpBufSz); - - tcp_connect(&sfd, domainName, port); - if (sfd > 0) { - int written; - written = (int)write(sfd, httpBuf, httpBufSz); - if (written == httpBufSz) { - written = (int)write(sfd, ocspReqBuf, ocspReqSz); - if (written == ocspReqSz) { - httpBufSz = (int)read(sfd, httpBuf, SCRATCH_BUFFER_SIZE); - if (httpBufSz > 0) { - ocspRespSz = decode_http_response(httpBuf, httpBufSz, - ocspRespBuf); - } - } - } - close(sfd); - if (ocspRespSz == 0) { - CYASSL_MSG("HTTP response was not OK, no OCSP response"); - return OCSP_LOOKUP_FAIL; - } - } else { - CYASSL_MSG("OCSP Responder connection failed"); - return OCSP_LOOKUP_FAIL; - } - - return ocspRespSz; -} - - static int xstat2err(int stat) { switch (stat) { @@ -456,13 +225,15 @@ static int xstat2err(int stat) int CyaSSL_OCSP_Lookup_Cert(CYASSL_OCSP* ocsp, DecodedCert* cert) { byte* ocspReqBuf = NULL; - int ocspReqSz = SCRATCH_BUFFER_SIZE; + int ocspReqSz = 2048; byte* ocspRespBuf = NULL; OcspRequest ocspRequest; OcspResponse ocspResponse; int result = 0; OCSP_Entry* ocspe; CertStatus* certStatus; + const char *url; + int urlSz; /* If OCSP lookups are disabled, return success. */ if (!ocsp->enabled) { @@ -501,7 +272,20 @@ int CyaSSL_OCSP_Lookup_Cert(CYASSL_OCSP* ocsp, DecodedCert* cert) return result; } } - + + if (ocsp->useOverrideUrl || cert->extAuthInfo == NULL) { + if (ocsp->overrideUrl != NULL) { + url = ocsp->overrideUrl; + urlSz = (int)XSTRLEN(url); + } + else + return OCSP_NEED_URL; + } + else { + url = (const char *)cert->extAuthInfo; + urlSz = cert->extAuthInfoSz; + } + ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER); if (ocspReqBuf == NULL) { CYASSL_MSG("\talloc OCSP request buffer failed"); @@ -509,8 +293,12 @@ int CyaSSL_OCSP_Lookup_Cert(CYASSL_OCSP* ocsp, DecodedCert* cert) } InitOcspRequest(&ocspRequest, cert, ocsp->useNonce, ocspReqBuf, ocspReqSz); ocspReqSz = EncodeOcspRequest(&ocspRequest); - result = http_ocsp_transaction(ocsp, cert, - ocspReqBuf, ocspReqSz, &ocspRespBuf); + + if (ocsp->CBIOOcsp) { + result = ocsp->CBIOOcsp(ocsp->IOCB_OcspCtx, url, urlSz, + ocspReqBuf, ocspReqSz, &ocspRespBuf); + } + if (result >= 0) { InitOcspResponse(&ocspResponse, certStatus, ocspRespBuf, result); OcspResponseDecode(&ocspResponse); @@ -530,11 +318,15 @@ int CyaSSL_OCSP_Lookup_Cert(CYASSL_OCSP* ocsp, DecodedCert* cert) } } } + else { + result = OCSP_LOOKUP_FAIL; + } + if (ocspReqBuf != NULL) { XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER); } - if (ocspRespBuf != NULL) { - XFREE(ocspRespBuf, NULL, DYNAMIC_TYPE_IN_BUFFER); + if (ocspRespBuf != NULL && ocsp->CBIOOcspRespFree) { + ocsp->CBIOOcspRespFree(ocsp->IOCB_OcspCtx, ocspRespBuf); } return result; diff --git a/src/ssl.c b/src/ssl.c index 673fc72cb..2017d3533 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2291,21 +2291,15 @@ int CyaSSL_CTX_use_NTRUPrivateKey_file(CYASSL_CTX* ctx, const char* file) int format) { CYASSL_ENTER("SSL_CTX_use_RSAPrivateKey_file"); - if (ProcessFile(ctx, file,format,PRIVATEKEY_TYPE,NULL,0, NULL) - == SSL_SUCCESS) - return SSL_SUCCESS; - return SSL_FAILURE; + return CyaSSL_CTX_use_PrivateKey_file(ctx, file, format); } int CyaSSL_use_RSAPrivateKey_file(CYASSL* ssl, const char* file, int format) { CYASSL_ENTER("CyaSSL_use_RSAPrivateKey_file"); - if (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE, ssl, 0, NULL) - == SSL_SUCCESS) - return SSL_SUCCESS; - return SSL_FAILURE; + return CyaSSL_use_PrivateKey_file(ssl, file, format); } #endif /* OPENSSL_EXTRA */ @@ -4242,7 +4236,7 @@ int CyaSSL_set_compression(CYASSL* ssl) InitMd5(&myMD); /* only support MD5 for now */ - if (XSTRNCMP(md, "MD5", 3)) return 0; + if (XSTRNCMP(md, "MD5", 3) != 0) return 0; /* only support CBC DES and AES for now */ if (XSTRNCMP(type, "DES-CBC", 7) == 0) { @@ -5436,6 +5430,11 @@ int CyaSSL_set_compression(CYASSL* ssl) case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 : return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; + case TLS_RSA_WITH_AES_128_CCM_8_SHA256 : + return "TLS_RSA_WITH_AES_128_CCM_8_SHA256"; + case TLS_RSA_WITH_AES_256_CCM_8_SHA384 : + return "TLS_RSA_WITH_AES_256_CCM_8_SHA384"; + default: return "NONE"; } diff --git a/tests/include.am b/tests/include.am index 43d5c2c47..5b420fc42 100644 --- a/tests/include.am +++ b/tests/include.am @@ -27,6 +27,7 @@ EXTRA_DIST += tests/test.conf \ tests/test-aesgcm.conf \ tests/test-aesgcm-ecc.conf \ tests/test-aesgcm-openssl.conf \ + tests/test-aesccm.conf \ tests/test-dtls.conf \ tests/test-rabbit.conf \ tests/test-null.conf \ diff --git a/tests/suites.c b/tests/suites.c index 3bcb23e21..bc22cc865 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -370,6 +370,17 @@ int SuiteTest(void) } #endif +#if defined(HAVE_AESCCM) + /* add aesccm extra suites */ + strcpy(argv0[1], "tests/test-aesccm.conf"); + printf("starting aesccm extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + exit(EXIT_FAILURE); + } +#endif + #ifdef CYASSL_DTLS /* add dtls extra suites */ strcpy(argv0[1], "tests/test-dtls.conf"); diff --git a/tests/test-aesccm.conf b/tests/test-aesccm.conf new file mode 100644 index 000000000..eba2a9ea7 --- /dev/null +++ b/tests/test-aesccm.conf @@ -0,0 +1,16 @@ +# server TLSv1.2 AES128-CCM-8-SHA256 +-v 3 +-l AES128-CCM-8-SHA256 + +# client TLSv1.2 AES128-CCM-8-SHA256 +-v 3 +-l AES128-CCM-8-SHA256 + +# server TLSv1.2 AES256-CCM-8-SHA384 +-v 3 +-l AES256-CCM-8-SHA384 + +# client TLSv1.2 AES256-CCM-8-SHA384 +-v 3 +-l AES256-CCM-8-SHA384 + diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index 956a3d1f3..80a8c878f 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -66,7 +66,7 @@ int main(int argc, char** argv) args.argv = server_args.argv = argv; CyaSSL_Init(); -#ifdef DEBUG_CYASSL +#if defined(DEBUG_CYASSL) && !defined(HAVE_VALGRIND) CyaSSL_Debugging_ON(); #endif