From 4e73ad854750ef545fbb03852cb7cab7d94fb664 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 18 Jun 2012 14:31:46 -0700 Subject: [PATCH 01/24] AES-GCM requires SHA-384, configure adds it automatically --- configure.ac | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 82856d0fd..670628241 100644 --- a/configure.ac +++ b/configure.ac @@ -298,7 +298,7 @@ AC_ARG_ENABLE(aesgcm, if test "$ENABLED_AESGCM" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM" + AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM -DCYASSL_SHA384 -DCYASSL_SHA512" fi AM_CONDITIONAL([BUILD_AESGCM], [test "x$ENABLED_AESGCM" = "xyes"]) @@ -355,6 +355,11 @@ then ENABLED_SHA512="yes" fi +if test "$ENABLED_AESGCM" = "yes" +then + ENABLED_SHA512="yes" +fi + AM_CONDITIONAL([BUILD_SHA512], [test "x$ENABLED_SHA512" = "xyes"]) From 918ea3a07424af314e9760b154821e13f8e5d443 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 18 Jun 2012 15:57:37 -0700 Subject: [PATCH 02/24] added the library framework for handling aes-gcm in TLS --- cyassl/internal.h | 46 ++++++++- src/internal.c | 238 +++++++++++++++++++++++++++++++++++++++++++++- src/keys.c | 168 ++++++++++++++++++++++++++++++++ src/ssl.c | 25 +++++ 4 files changed, 472 insertions(+), 5 deletions(-) diff --git a/cyassl/internal.h b/cyassl/internal.h index 0921740a4..583b1cd6d 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -44,6 +44,9 @@ #ifdef HAVE_OCSP #include #endif +#ifdef CYASSL_SHA512 + #include +#endif #ifdef CYASSL_CALLBACKS #include @@ -147,6 +150,10 @@ void c32to24(word32 in, word24 out); #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 #endif + #if defined (HAVE_AESGCM) + #define BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 + #define BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + #endif #endif #if !defined(NO_HC128) && !defined(NO_TLS) @@ -164,6 +171,10 @@ void c32to24(word32 in, word24 out); #if !defined (NO_SHA256) #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + #if defined (HAVE_AESGCM) + #define BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + #define BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + #endif #endif #endif @@ -178,6 +189,18 @@ void c32to24(word32 in, word24 out); #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + + #if defined (HAVE_AESGCM) + #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + #define BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + + #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + #define BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + #endif #endif #if !defined(NO_RC4) #define BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA @@ -275,7 +298,23 @@ enum { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x6b, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x67, TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x3d, - TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x3c + TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x3c, + + /* AES-GCM */ + TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x9c, + TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x9d, + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x9e, + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x9f, + + /* ECC AES-GCM, first byte is 0xC0 (ECC_BYTE) */ + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0x2b, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0x2c, + TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0x2d, + TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0x2e, + 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 }; @@ -763,7 +802,7 @@ int AlreadySigner(CYASSL_CERT_MANAGER* cm, byte* hash); /* All cipher suite related info */ typedef struct CipherSpecs { byte bulk_cipher_algorithm; - byte cipher_type; /* block or stream */ + byte cipher_type; /* block, stream, or aead */ byte mac_algorithm; byte kea; /* key exchange algo */ byte sig_algo; @@ -787,6 +826,7 @@ enum BulkCipherAlgorithm { des40, idea, aes, + aes_gcm, hc128, /* CyaSSL extensions */ rabbit }; @@ -857,7 +897,7 @@ enum ClientCertificateType { }; -enum CipherType { stream, block }; +enum CipherType { stream, block, aead }; /* keys and secrets */ diff --git a/src/internal.c b/src/internal.c index 27157dae7..59d942669 100644 --- a/src/internal.c +++ b/src/internal.c @@ -470,6 +470,90 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, tls = 1; #endif +#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_RSA_WITH_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_RSA_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveDH && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveDH && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveECDSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveECDSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveRSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveRSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveECDSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveECDSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384; + } +#endif + #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA if (tls && haveNTRU && haveRSA) { suites->suites[idx++] = 0; @@ -3708,7 +3792,55 @@ const char* const cipher_names[] = #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - "ECDH-ECDSA-DES-CBC3-SHA" + "ECDH-ECDSA-DES-CBC3-SHA", +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 + "AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + "AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + "DHE-RSA-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + "DHE-RSA-AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + "ECDHE-RSA-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + "ECDHE-RSA-AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + "ECDHE-EDCSA-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + "ECDHE-ECDSA-AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + "ECDH-RSA-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + "ECDH-RSA-AES128-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + "ECDH-ECDSA-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + "ECDH-ECDSA-AES256-GCM-SHA384" #endif }; @@ -3860,7 +3992,55 @@ int cipher_name_idx[] = #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 + TLS_RSA_WITH_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + TLS_RSA_WITH_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_DHE_TLS_RSA_WITH_AES_256_GCM_SHA384 + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 #endif }; @@ -5545,6 +5725,46 @@ int SetCipherList(Suites* s, const char* list) return 1; break; + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 : + if (requirement == ecc_dsa_sa_algo) + return 1; + break; + + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 : + if (requirement == ecc_dsa_sa_algo) + return 1; + break; + + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 : + if (requirement == ecc_static_diffie_hellman_kea) + return 1; + break; + + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 : + if (requirement == ecc_static_diffie_hellman_kea) + return 1; + break; + + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : + if (requirement == rsa_kea) + return 1; + break; + + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 : + if (requirement == rsa_kea) + return 1; + break; + + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 : + if (requirement == ecc_static_diffie_hellman_kea) + return 1; + break; + + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 : + if (requirement == ecc_static_diffie_hellman_kea) + return 1; + break; + default: CYASSL_MSG("Unsupported cipher suite, CipherRequires ECC"); return 0; @@ -5661,6 +5881,20 @@ int SetCipherList(Suites* s, const char* list) return 1; break; + case TLS_RSA_WITH_AES_128_GCM_SHA256 : + case TLS_RSA_WITH_AES_256_GCM_SHA384 : + if (requirement == rsa_kea) + return 1; + break; + + case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 : + case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 : + if (requirement == rsa_kea) + return 1; + if (requirement == diffie_hellman_kea) + return 1; + break; + default: CYASSL_MSG("Unsupported cipher suite, CipherRequires"); return 0; diff --git a/src/keys.c b/src/keys.c index 3fb4c8a60..6f759756c 100644 --- a/src/keys.c +++ b/src/keys.c @@ -311,6 +311,142 @@ int SetCipherSpecs(CYASSL* ssl) break; #endif +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = no_mac; + ssl->specs.kea = ecc_diffie_hellman_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 = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = no_mac; + ssl->specs.kea = ecc_diffie_hellman_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 = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = no_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_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 = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = no_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_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 = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = no_mac; + ssl->specs.kea = ecc_diffie_hellman_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 = 1; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = no_mac; + ssl->specs.kea = ecc_diffie_hellman_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 = 1; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = no_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + 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_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = no_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + 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_IV_SIZE; + + break; +#endif + default: CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs ECC"); return UNSUPPORTED_SUITE; @@ -646,6 +782,38 @@ int SetCipherSpecs(CYASSL* ssl) break; #endif +#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 + case TLS_RSA_WITH_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = no_mac; + ssl->specs.kea = rsa_kea; + 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 = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + case TLS_RSA_WITH_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = no_mac; + ssl->specs.kea = rsa_kea; + 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 = AES_IV_SIZE; + + break; +#endif + default: CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs"); return UNSUPPORTED_SUITE; diff --git a/src/ssl.c b/src/ssl.c index 2a5cfefb9..8f30c05d4 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -5000,6 +5000,23 @@ int CyaSSL_set_compression(CYASSL* ssl) case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA : return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : + return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 : + return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 : + return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 : + return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 : + return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 : + return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 : + return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 : + return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; + default: return "NONE"; } @@ -5048,6 +5065,14 @@ int CyaSSL_set_compression(CYASSL* ssl) return "TLS_NTRU_RSA_WITH_AES_128_CBC_SHA"; case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA : return "TLS_NTRU_RSA_WITH_AES_256_CBC_SHA"; + case TLS_RSA_WITH_AES_128_GCM_SHA256 : + return "TLS_RSA_WITH_AES_128_GCM_SHA256"; + case TLS_RSA_WITH_AES_256_GCM_SHA384 : + return "TLS_RSA_WITH_AES_256_GCM_SHA384"; + case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 : + return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; + case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 : + return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; default: return "NONE"; } /* switch */ From 737cd127e8ad8184b967869b4a81e8b28ffba236 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 26 Jun 2012 09:29:48 -0700 Subject: [PATCH 03/24] Changed AesGcmEncrypt and Decrypt to allow the same pointer to write and read buffers. --- ctaocrypt/src/aes.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/ctaocrypt/src/aes.c b/ctaocrypt/src/aes.c index 5eac4f93f..a79889621 100644 --- a/ctaocrypt/src/aes.c +++ b/ctaocrypt/src/aes.c @@ -1551,6 +1551,7 @@ void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte* c = out; byte h[AES_BLOCK_SIZE]; byte ctr[AES_BLOCK_SIZE]; + byte scratch[AES_BLOCK_SIZE]; CYASSL_ENTER("AesGcmEncrypt"); @@ -1565,19 +1566,18 @@ void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, while (blocks--) { IncrementGcmCounter(ctr); - AesEncrypt(aes, ctr, c); - xorbuf(c, p, AES_BLOCK_SIZE); + AesEncrypt(aes, ctr, scratch); + xorbuf(scratch, p, AES_BLOCK_SIZE); + XMEMCPY(c, scratch, AES_BLOCK_SIZE); p += AES_BLOCK_SIZE; c += AES_BLOCK_SIZE; } if (partial != 0) { - byte cPartial[AES_BLOCK_SIZE]; - IncrementGcmCounter(ctr); - AesEncrypt(aes, ctr, cPartial); - XMEMCPY(c, cPartial, partial); - xorbuf(c, p, partial); + AesEncrypt(aes, ctr, scratch); + xorbuf(scratch, p, partial); + XMEMCPY(c, scratch, partial); } GHASH(h, authIn, authInSz, out, sz, authTag, authTagSz); InitGcmCounter(ctr); @@ -1596,6 +1596,7 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte* p = out; byte h[AES_BLOCK_SIZE]; byte ctr[AES_BLOCK_SIZE]; + byte scratch[AES_BLOCK_SIZE]; CYASSL_ENTER("AesGcmDecrypt"); @@ -1624,8 +1625,9 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, while (blocks--) { IncrementGcmCounter(ctr); - AesEncrypt(aes, ctr, p); - xorbuf(p, c, AES_BLOCK_SIZE); + AesEncrypt(aes, ctr, scratch); + xorbuf(scratch, c, AES_BLOCK_SIZE); + XMEMCPY(p, scratch, AES_BLOCK_SIZE); p += AES_BLOCK_SIZE; c += AES_BLOCK_SIZE; @@ -1634,9 +1636,9 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte pPartial[AES_BLOCK_SIZE]; IncrementGcmCounter(ctr); - AesEncrypt(aes, ctr, pPartial); - XMEMCPY(p, pPartial, partial); - xorbuf(p, c, partial); + AesEncrypt(aes, ctr, scratch); + xorbuf(scratch, c, partial); + XMEMCPY(p, scratch, partial); } return 0; From 3a9a1956830476bd422508d2c6a04e0e3bad53cd Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 26 Jun 2012 09:30:48 -0700 Subject: [PATCH 04/24] Initial draft of AES GCM cipher suites. Missing SHA-384 support. --- cyassl/internal.h | 10 +++ src/internal.c | 220 +++++++++++++++++++++++++++++++++++----------- src/keys.c | 54 +++++++++--- 3 files changed, 218 insertions(+), 66 deletions(-) diff --git a/cyassl/internal.h b/cyassl/internal.h index 583b1cd6d..0f8d9d2a7 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -233,6 +233,11 @@ void c32to24(word32 in, word24 out); #define BUILD_AES #endif +#if defined(BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) || \ + defined(BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) + #define BUILD_AESGCM +#endif + #if defined(BUILD_TLS_RSA_WITH_HC_128_CBC_SHA) || \ defined(BUILD_TLS_RSA_WITH_HC_128_CBC_MD5) #define BUILD_HC128 @@ -398,6 +403,8 @@ 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_IMPLICIT_IV_SIZE = 4, /* Implicit half of IV */ + AES_GCM_EXPLICIT_IV_SIZE = 8, /* Explicit half of IV */ AES_128_KEY_SIZE = 16, /* for 128 bit */ HC_128_KEY_SIZE = 16, /* 128 bits */ @@ -1167,6 +1174,9 @@ struct CYASSL { Sha hashSha; /* sha hash of handshake msgs */ #ifndef NO_SHA256 Sha256 hashSha256; /* sha256 hash of handshake msgs */ +#endif +#ifdef CYASSL_SHA384 + Sha384 hashSha384; /* sha384 hash of handshake msgs */ #endif Hashes verifyHashes; Hashes certHashes; /* for cert verify */ diff --git a/src/internal.c b/src/internal.c index 59d942669..5709f5f5d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -886,6 +886,9 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) InitSha(&ssl->hashSha); #ifndef NO_SHA256 InitSha256(&ssl->hashSha256); +#endif +#ifdef CYASSL_SHA384 + InitSha384(&ssl->hashSha384); #endif InitRsaKey(&ssl->peerRsaKey, ctx->heap); @@ -1177,10 +1180,14 @@ static void HashOutput(CYASSL* ssl, const byte* output, int sz, int ivSz) Md5Update(&ssl->hashMd5, adj, sz); ShaUpdate(&ssl->hashSha, adj, sz); + if (IsAtLeastTLSv1_2(ssl)) { #ifndef NO_SHA256 - if (IsAtLeastTLSv1_2(ssl)) Sha256Update(&ssl->hashSha256, adj, sz); #endif +#ifdef CYASSL_SHA384 + Sha384Update(&ssl->hashSha384, adj, sz); +#endif + } } @@ -1199,10 +1206,14 @@ static void HashInput(CYASSL* ssl, const byte* input, int sz) Md5Update(&ssl->hashMd5, adj, sz); ShaUpdate(&ssl->hashSha, adj, sz); + if (IsAtLeastTLSv1_2(ssl)) { #ifndef NO_SHA256 - if (IsAtLeastTLSv1_2(ssl)) Sha256Update(&ssl->hashSha256, adj, sz); #endif +#ifdef CYASSL_SHA384 + Sha384Update(&ssl->hashSha384, adj, sz); +#endif + } } @@ -1624,6 +1635,12 @@ static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) if (IsAtLeastTLSv1_2(ssl)) sha256 = ssl->hashSha256; #endif +#if CYASSL_SHA384 + Sha384 sha384; + InitSha384(&sha384); + if (IsAtLeastTLSv1_2(ssl)) + sha384 = ssl->hashSha384; +#endif if (ssl->options.tls) BuildTlsFinished(ssl, hashes, sender); @@ -1639,6 +1656,10 @@ static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) if (IsAtLeastTLSv1_2(ssl)) ssl->hashSha256 = sha256; #endif +#ifdef CYASSL_SHA384 + if (IsAtLeastTLSv1_2(ssl)) + ssl->hashSha384 = sha384; +#endif } @@ -2017,24 +2038,30 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff) } } - ssl->hmac(ssl, verifyMAC, input + idx - headerSz, macSz, - handshake, 1); - idx += finishedSz; + if (ssl->specs.cipher_type != aead) { + ssl->hmac(ssl, verifyMAC, input + idx - headerSz, macSz, + handshake, 1); + idx += finishedSz; - /* read mac and fill */ - mac = input + idx; - idx += ssl->specs.hash_size; + /* read mac and fill */ + mac = input + idx; + idx += ssl->specs.hash_size; - if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) - padSz -= ssl->specs.block_size; + if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) + padSz -= ssl->specs.block_size; - idx += padSz; + idx += padSz; - /* verify mac */ - if (XMEMCMP(mac, verifyMAC, ssl->specs.hash_size)) { - CYASSL_MSG("Verify finished error on mac"); - return VERIFY_MAC_ERROR; - } + /* verify mac */ + if (XMEMCMP(mac, verifyMAC, ssl->specs.hash_size)) { + CYASSL_MSG("Verify finished error on mac"); + return VERIFY_MAC_ERROR; + } + } + else { + idx = idx + finishedSz + 16; + /* XXX the 16 should be from specs */ + } if (ssl->options.side == CLIENT_END) { ssl->options.serverState = SERVER_FINISHED_COMPLETE; @@ -2156,6 +2183,15 @@ static int DoHandShakeMsg(CYASSL* ssl, byte* input, word32* inOutIdx, } +static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify) +{ + if (verify) + return ssl->keys.peer_sequence_number++; + else + return ssl->keys.sequence_number++; +} + + static INLINE void Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz) { switch (ssl->specs.bulk_cipher_algorithm) { @@ -2186,6 +2222,35 @@ static INLINE void Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz) break; #endif + #ifdef BUILD_AESGCM + case aes_gcm: + { + byte additional[AES_BLOCK_SIZE]; + byte nonce[AES_BLOCK_SIZE]; + + if (ssl->options.side == SERVER_END) { + XMEMCPY(nonce, ssl->keys.server_write_IV, + AES_GCM_IMPLICIT_IV_SIZE); + } + else { + XMEMCPY(nonce, ssl->keys.client_write_IV, + AES_GCM_IMPLICIT_IV_SIZE); + } + XMEMCPY(nonce + AES_GCM_IMPLICIT_IV_SIZE, + input, AES_GCM_EXPLICIT_IV_SIZE); + XMEMSET(nonce + AES_GCM_IMPLICIT_IV_SIZE + + AES_GCM_EXPLICIT_IV_SIZE, 0, 4); + AesSetIV(&ssl->encrypt.aes, nonce); + + XMEMSET(additional, 0, 16); + c32toa(GetSEQIncrement(ssl, 0), additional + 4); + XMEMCPY(additional+8, input - 5, 5); + AesGcmEncrypt(&ssl->encrypt.aes, out+8, input+8, sz-24, + out + 8 + (sz - 24), 16, additional, 13); + } + break; + #endif + #ifdef HAVE_HC128 case hc128: Hc128_Process(&ssl->encrypt.hc128, out, input, sz); @@ -2204,7 +2269,7 @@ static INLINE void Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz) } -static INLINE void Decrypt(CYASSL* ssl, byte* plain, const byte* input, +static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input, word32 sz) { switch (ssl->specs.bulk_cipher_algorithm) { @@ -2226,6 +2291,41 @@ static INLINE void Decrypt(CYASSL* ssl, byte* plain, const byte* input, break; #endif + #ifdef BUILD_AESGCM + case aes_gcm: + { + byte additional[16]; + byte nonce[16]; + + /* use the other side's IV */ + if (ssl->options.side == SERVER_END) { + XMEMCPY(nonce, ssl->keys.client_write_IV, + AES_GCM_IMPLICIT_IV_SIZE); + } + else { + XMEMCPY(nonce, ssl->keys.server_write_IV, + AES_GCM_IMPLICIT_IV_SIZE); + } + XMEMCPY(nonce + AES_GCM_IMPLICIT_IV_SIZE, + input, AES_GCM_EXPLICIT_IV_SIZE); + XMEMSET(nonce + AES_GCM_IMPLICIT_IV_SIZE + + AES_GCM_EXPLICIT_IV_SIZE, 0, 4); + AesSetIV(&ssl->decrypt.aes, nonce); + XMEMSET(additional, 0, 4); + c32toa(GetSEQIncrement(ssl, 1), additional + 4); + additional[8] = ssl->curRL.type; + additional[9] = ssl->curRL.version.major; + additional[10] = ssl->curRL.version.minor; + c16toa(sz, additional + 11); + if (AesGcmDecrypt(&ssl->decrypt.aes, plain+8, input+8, sz-24, + input + 8 + (sz - 24), 16, additional, 13) < 0) { + SendAlert(ssl, alert_fatal, bad_record_mac); + return VERIFY_MAC_ERROR; + } + break; + } + #endif + #ifdef HAVE_HC128 case hc128: Hc128_Process(&ssl->decrypt.hc128, plain, input, sz); @@ -2241,27 +2341,25 @@ static INLINE void Decrypt(CYASSL* ssl, byte* plain, const byte* input, default: CYASSL_MSG("CyaSSL Decrypt programming error"); } + return 0; } /* decrypt input message in place */ static int DecryptMessage(CYASSL* ssl, byte* input, word32 sz, word32* idx) { - Decrypt(ssl, input, input, sz); - ssl->keys.encryptSz = sz; - if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) - *idx += ssl->specs.block_size; /* go past TLSv1.1 IV */ + int decryptResult = Decrypt(ssl, input, input, sz); - return 0; -} + if (decryptResult == 0) + { + ssl->keys.encryptSz = sz; + 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_EXPLICIT_IV_SIZE; + } - -static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify) -{ - if (verify) - return ssl->keys.peer_sequence_number++; - else - return ssl->keys.sequence_number++; + return decryptResult; } @@ -2288,6 +2386,10 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx) pad = *(input + idx + msgSz - ivExtra - 1); padByte = 1; } + if (ssl->specs.cipher_type == aead) { + ivExtra = 8; + digestSz = 16; + } dataSz = msgSz - ivExtra - digestSz - pad - padByte; if (dataSz < 0) { @@ -2299,7 +2401,8 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx) if (dataSz) { int rawSz = dataSz; /* keep raw size for hmac */ - ssl->hmac(ssl, verify, rawData, rawSz, application_data, 1); + if (ssl->specs.cipher_type != aead) + ssl->hmac(ssl, verify, rawData, rawSz, application_data, 1); #ifdef HAVE_LIBZ if (ssl->options.usingCompression) { @@ -2332,7 +2435,7 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx) /* verify */ if (dataSz) { - if (XMEMCMP(mac, verify, digestSz)) { + if (ssl->specs.cipher_type != aead && XMEMCMP(mac, verify, digestSz)) { CYASSL_MSG("App data verify mac error"); return VERIFY_MAC_ERROR; } @@ -2368,24 +2471,30 @@ static int DoAlert(CYASSL* ssl, byte* input, word32* inOutIdx, int* type) } CYASSL_ERROR(*type); - if (ssl->keys.encryptionOn) { - int aSz = ALERT_SIZE; - const byte* mac; - byte verify[SHA256_DIGEST_SIZE]; - int padSz = ssl->keys.encryptSz - aSz - ssl->specs.hash_size; - - ssl->hmac(ssl, verify, input + *inOutIdx - aSz, aSz, alert, 1); - - /* read mac and fill */ - mac = input + *inOutIdx; - *inOutIdx += (ssl->specs.hash_size + padSz); - - /* verify */ - if (XMEMCMP(mac, verify, ssl->specs.hash_size)) { - CYASSL_MSG(" alert verify mac error"); - return VERIFY_MAC_ERROR; - } - } + if (ssl->keys.encryptionOn) { + if (ssl->specs.cipher_type != aead) { + int aSz = ALERT_SIZE; + const byte* mac; + byte verify[SHA256_DIGEST_SIZE]; + int padSz = ssl->keys.encryptSz - aSz - ssl->specs.hash_size; + + ssl->hmac(ssl, verify, input + *inOutIdx - aSz, aSz, alert, 1); + + /* read mac and fill */ + mac = input + *inOutIdx; + *inOutIdx += (ssl->specs.hash_size + padSz); + + /* verify */ + if (XMEMCMP(mac, verify, ssl->specs.hash_size)) { + CYASSL_MSG(" alert verify mac error"); + return VERIFY_MAC_ERROR; + } + } + else { + *inOutIdx += 16; + /* XXX this should be a value out of the cipher specs */ + } + } return level; } @@ -2901,6 +3010,11 @@ static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz, sz += pad; } + if (ssl->specs.cipher_type == aead) { + ivSz = AES_GCM_EXPLICIT_IV_SIZE; + sz = sz + ivSz + 16 - digestSz; + RNG_GenerateBlock(&ssl->rng, iv, ivSz); + } size = (word16)(sz - headerSz); /* include mac and digest */ AddRecordHeader(output, size, (byte)type, ssl); @@ -2914,8 +3028,10 @@ static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz, if (type == handshake) HashOutput(ssl, output, headerSz + inSz, ivSz); - ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, type, 0); - idx += digestSz; + if (ssl->specs.cipher_type != aead) { + ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, type, 0); + idx += digestSz; + } if (ssl->specs.cipher_type == block) for (i = 0; i <= pad; i++) diff --git a/src/keys.c b/src/keys.c index 6f759756c..7617b004a 100644 --- a/src/keys.c +++ b/src/keys.c @@ -323,7 +323,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_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE; break; #endif @@ -340,7 +340,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_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE; break; #endif @@ -357,7 +357,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_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE; break; #endif @@ -374,7 +374,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_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE; break; #endif @@ -391,7 +391,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_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE; break; #endif @@ -408,7 +408,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_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE; break; #endif @@ -425,7 +425,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_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE; break; #endif @@ -442,7 +442,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_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE; break; #endif @@ -793,7 +793,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_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE; break; #endif @@ -809,7 +809,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_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE; break; #endif @@ -970,6 +970,27 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, } #endif +#ifdef BUILD_AESGCM + if (specs->bulk_cipher_algorithm == aes_gcm) { + if (side == CLIENT_END) { + AesSetKey(&enc->aes, keys->client_write_key, + specs->key_size, keys->client_write_IV, + AES_ENCRYPTION); + AesSetKey(&dec->aes, keys->server_write_key, + specs->key_size, keys->server_write_IV, + AES_ENCRYPTION); + } + else { + AesSetKey(&enc->aes, keys->server_write_key, + specs->key_size, keys->server_write_IV, + AES_ENCRYPTION); + AesSetKey(&dec->aes, keys->client_write_key, + specs->key_size, keys->client_write_IV, + AES_ENCRYPTION); + } + } +#endif + keys->sequence_number = 0; keys->peer_sequence_number = 0; keys->encryptionOn = 0; @@ -983,10 +1004,15 @@ int StoreKeys(CYASSL* ssl, const byte* keyData) { int sz = ssl->specs.hash_size, i; - XMEMCPY(ssl->keys.client_write_MAC_secret, keyData, sz); - i = sz; - XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz); - i += sz; + if (ssl->specs.cipher_type != aead) { + XMEMCPY(ssl->keys.client_write_MAC_secret, keyData, sz); + i = sz; + XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz); + i += sz; + } + else { + sz = 0; + } sz = ssl->specs.key_size; XMEMCPY(ssl->keys.client_write_key, &keyData[i], sz); From 4e3d7f494b10a90e0deb16129ba67120d91a19f5 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 26 Jun 2012 15:51:40 -0700 Subject: [PATCH 05/24] AES-GCM: fixed the encryption/decryption bug --- ctaocrypt/src/aes.c | 10 +- src/internal.c | 253 ++++++++++++++++++++++---------------------- src/keys.c | 18 ++-- 3 files changed, 140 insertions(+), 141 deletions(-) diff --git a/ctaocrypt/src/aes.c b/ctaocrypt/src/aes.c index a79889621..6df52836f 100644 --- a/ctaocrypt/src/aes.c +++ b/ctaocrypt/src/aes.c @@ -1551,7 +1551,7 @@ void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte* c = out; byte h[AES_BLOCK_SIZE]; byte ctr[AES_BLOCK_SIZE]; - byte scratch[AES_BLOCK_SIZE]; + byte scratch[AES_BLOCK_SIZE]; CYASSL_ENTER("AesGcmEncrypt"); @@ -1568,7 +1568,7 @@ void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, IncrementGcmCounter(ctr); AesEncrypt(aes, ctr, scratch); xorbuf(scratch, p, AES_BLOCK_SIZE); - XMEMCPY(c, scratch, AES_BLOCK_SIZE); + XMEMCPY(c, scratch, AES_BLOCK_SIZE); p += AES_BLOCK_SIZE; c += AES_BLOCK_SIZE; @@ -1576,7 +1576,7 @@ void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, if (partial != 0) { IncrementGcmCounter(ctr); AesEncrypt(aes, ctr, scratch); - xorbuf(scratch, p, partial); + xorbuf(scratch, p, partial); XMEMCPY(c, scratch, partial); } GHASH(h, authIn, authInSz, out, sz, authTag, authTagSz); @@ -1596,7 +1596,7 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte* p = out; byte h[AES_BLOCK_SIZE]; byte ctr[AES_BLOCK_SIZE]; - byte scratch[AES_BLOCK_SIZE]; + byte scratch[AES_BLOCK_SIZE]; CYASSL_ENTER("AesGcmDecrypt"); @@ -1627,7 +1627,7 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, IncrementGcmCounter(ctr); AesEncrypt(aes, ctr, scratch); xorbuf(scratch, c, AES_BLOCK_SIZE); - XMEMCPY(p, scratch, AES_BLOCK_SIZE); + XMEMCPY(p, scratch, AES_BLOCK_SIZE); p += AES_BLOCK_SIZE; c += AES_BLOCK_SIZE; diff --git a/src/internal.c b/src/internal.c index 5709f5f5d..9e375a12d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1187,7 +1187,7 @@ static void HashOutput(CYASSL* ssl, const byte* output, int sz, int ivSz) #ifdef CYASSL_SHA384 Sha384Update(&ssl->hashSha384, adj, sz); #endif - } + } } @@ -1213,7 +1213,7 @@ static void HashInput(CYASSL* ssl, const byte* input, int sz) #ifdef CYASSL_SHA384 Sha384Update(&ssl->hashSha384, adj, sz); #endif - } + } } @@ -1636,8 +1636,8 @@ static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) sha256 = ssl->hashSha256; #endif #if CYASSL_SHA384 - Sha384 sha384; - InitSha384(&sha384); + Sha384 sha384; + InitSha384(&sha384); if (IsAtLeastTLSv1_2(ssl)) sha384 = ssl->hashSha384; #endif @@ -2038,30 +2038,30 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff) } } - if (ssl->specs.cipher_type != aead) { - ssl->hmac(ssl, verifyMAC, input + idx - headerSz, macSz, - handshake, 1); - idx += finishedSz; + if (ssl->specs.cipher_type != aead) { + ssl->hmac(ssl, verifyMAC, input + idx - headerSz, macSz, + handshake, 1); + idx += finishedSz; - /* read mac and fill */ - mac = input + idx; - idx += ssl->specs.hash_size; + /* read mac and fill */ + mac = input + idx; + idx += ssl->specs.hash_size; - if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) - padSz -= ssl->specs.block_size; + if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) + padSz -= ssl->specs.block_size; - idx += padSz; + idx += padSz; - /* verify mac */ - if (XMEMCMP(mac, verifyMAC, ssl->specs.hash_size)) { - CYASSL_MSG("Verify finished error on mac"); - return VERIFY_MAC_ERROR; - } - } - else { - idx = idx + finishedSz + 16; - /* XXX the 16 should be from specs */ - } + /* verify mac */ + if (XMEMCMP(mac, verifyMAC, ssl->specs.hash_size)) { + CYASSL_MSG("Verify finished error on mac"); + return VERIFY_MAC_ERROR; + } + } + else { + idx = idx + finishedSz + 16; + /* XXX the 16 should be from specs */ + } if (ssl->options.side == CLIENT_END) { ssl->options.serverState = SERVER_FINISHED_COMPLETE; @@ -2222,34 +2222,35 @@ static INLINE void Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz) break; #endif - #ifdef BUILD_AESGCM - case aes_gcm: - { - byte additional[AES_BLOCK_SIZE]; - byte nonce[AES_BLOCK_SIZE]; + #ifdef BUILD_AESGCM + case aes_gcm: + { + byte additional[AES_BLOCK_SIZE]; + byte nonce[AES_BLOCK_SIZE]; - if (ssl->options.side == SERVER_END) { - XMEMCPY(nonce, ssl->keys.server_write_IV, - AES_GCM_IMPLICIT_IV_SIZE); - } - else { - XMEMCPY(nonce, ssl->keys.client_write_IV, - AES_GCM_IMPLICIT_IV_SIZE); - } - XMEMCPY(nonce + AES_GCM_IMPLICIT_IV_SIZE, - input, AES_GCM_EXPLICIT_IV_SIZE); - XMEMSET(nonce + AES_GCM_IMPLICIT_IV_SIZE + - AES_GCM_EXPLICIT_IV_SIZE, 0, 4); - AesSetIV(&ssl->encrypt.aes, nonce); - - XMEMSET(additional, 0, 16); - c32toa(GetSEQIncrement(ssl, 0), additional + 4); - XMEMCPY(additional+8, input - 5, 5); - AesGcmEncrypt(&ssl->encrypt.aes, out+8, input+8, sz-24, - out + 8 + (sz - 24), 16, additional, 13); - } - break; - #endif + if (ssl->options.side == SERVER_END) { + XMEMCPY(nonce, ssl->keys.server_write_IV, + AES_GCM_IMPLICIT_IV_SIZE); + } + else { + XMEMCPY(nonce, ssl->keys.client_write_IV, + AES_GCM_IMPLICIT_IV_SIZE); + } + XMEMCPY(nonce + AES_GCM_IMPLICIT_IV_SIZE, + input, AES_GCM_EXPLICIT_IV_SIZE); + XMEMSET(nonce + AES_GCM_IMPLICIT_IV_SIZE + + AES_GCM_EXPLICIT_IV_SIZE, 0, 4); + AesSetIV(&ssl->encrypt.aes, nonce); + + XMEMSET(additional, 0, 16); + c32toa(GetSEQIncrement(ssl, 0), additional + 4); + XMEMCPY(additional+8, input - 5, 5); + c16toa(sz - 24, additional+11); + AesGcmEncrypt(&ssl->encrypt.aes, out+8, input+8, sz-24, + out + sz - 16, 16, additional, 13); + } + break; + #endif #ifdef HAVE_HC128 case hc128: @@ -2293,37 +2294,37 @@ static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input, #ifdef BUILD_AESGCM case aes_gcm: - { - byte additional[16]; - byte nonce[16]; + { + byte additional[16]; + byte nonce[16]; - /* use the other side's IV */ - if (ssl->options.side == SERVER_END) { - XMEMCPY(nonce, ssl->keys.client_write_IV, - AES_GCM_IMPLICIT_IV_SIZE); - } - else { - XMEMCPY(nonce, ssl->keys.server_write_IV, - AES_GCM_IMPLICIT_IV_SIZE); - } - XMEMCPY(nonce + AES_GCM_IMPLICIT_IV_SIZE, - input, AES_GCM_EXPLICIT_IV_SIZE); - XMEMSET(nonce + AES_GCM_IMPLICIT_IV_SIZE + - AES_GCM_EXPLICIT_IV_SIZE, 0, 4); - AesSetIV(&ssl->decrypt.aes, nonce); - XMEMSET(additional, 0, 4); - c32toa(GetSEQIncrement(ssl, 1), additional + 4); - additional[8] = ssl->curRL.type; - additional[9] = ssl->curRL.version.major; - additional[10] = ssl->curRL.version.minor; - c16toa(sz, additional + 11); + /* use the other side's IV */ + if (ssl->options.side == SERVER_END) { + XMEMCPY(nonce, ssl->keys.client_write_IV, + AES_GCM_IMPLICIT_IV_SIZE); + } + else { + XMEMCPY(nonce, ssl->keys.server_write_IV, + AES_GCM_IMPLICIT_IV_SIZE); + } + XMEMCPY(nonce + AES_GCM_IMPLICIT_IV_SIZE, + input, AES_GCM_EXPLICIT_IV_SIZE); + XMEMSET(nonce + AES_GCM_IMPLICIT_IV_SIZE + + AES_GCM_EXPLICIT_IV_SIZE, 0, 4); + AesSetIV(&ssl->decrypt.aes, nonce); + XMEMSET(additional, 0, 4); + c32toa(GetSEQIncrement(ssl, 1), additional + 4); + additional[8] = ssl->curRL.type; + additional[9] = ssl->curRL.version.major; + additional[10] = ssl->curRL.version.minor; + c16toa(sz-24, additional + 11); if (AesGcmDecrypt(&ssl->decrypt.aes, plain+8, input+8, sz-24, - input + 8 + (sz - 24), 16, additional, 13) < 0) { - SendAlert(ssl, alert_fatal, bad_record_mac); - return VERIFY_MAC_ERROR; - } + input + 8 + (sz - 24), 16, additional, 13) < 0) { + SendAlert(ssl, alert_fatal, bad_record_mac); + return VERIFY_MAC_ERROR; + } break; - } + } #endif #ifdef HAVE_HC128 @@ -2341,23 +2342,23 @@ static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input, default: CYASSL_MSG("CyaSSL Decrypt programming error"); } - return 0; + return 0; } /* decrypt input message in place */ static int DecryptMessage(CYASSL* ssl, byte* input, word32 sz, word32* idx) { - int decryptResult = Decrypt(ssl, input, input, sz); + int decryptResult = Decrypt(ssl, input, input, sz); - if (decryptResult == 0) - { + if (decryptResult == 0) + { ssl->keys.encryptSz = sz; 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_EXPLICIT_IV_SIZE; - } + if (ssl->specs.cipher_type == aead) + *idx += AES_GCM_EXPLICIT_IV_SIZE; + } return decryptResult; } @@ -2386,10 +2387,10 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx) pad = *(input + idx + msgSz - ivExtra - 1); padByte = 1; } - if (ssl->specs.cipher_type == aead) { - ivExtra = 8; - digestSz = 16; - } + if (ssl->specs.cipher_type == aead) { + ivExtra = 8; + digestSz = 16; + } dataSz = msgSz - ivExtra - digestSz - pad - padByte; if (dataSz < 0) { @@ -2401,8 +2402,8 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx) if (dataSz) { int rawSz = dataSz; /* keep raw size for hmac */ - if (ssl->specs.cipher_type != aead) - ssl->hmac(ssl, verify, rawData, rawSz, application_data, 1); + if (ssl->specs.cipher_type != aead) + ssl->hmac(ssl, verify, rawData, rawSz, application_data, 1); #ifdef HAVE_LIBZ if (ssl->options.usingCompression) { @@ -2435,7 +2436,7 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx) /* verify */ if (dataSz) { - if (ssl->specs.cipher_type != aead && XMEMCMP(mac, verify, digestSz)) { + if (ssl->specs.cipher_type != aead && XMEMCMP(mac, verify, digestSz)) { CYASSL_MSG("App data verify mac error"); return VERIFY_MAC_ERROR; } @@ -2471,30 +2472,30 @@ static int DoAlert(CYASSL* ssl, byte* input, word32* inOutIdx, int* type) } CYASSL_ERROR(*type); - if (ssl->keys.encryptionOn) { - if (ssl->specs.cipher_type != aead) { - int aSz = ALERT_SIZE; - const byte* mac; - byte verify[SHA256_DIGEST_SIZE]; - int padSz = ssl->keys.encryptSz - aSz - ssl->specs.hash_size; - - ssl->hmac(ssl, verify, input + *inOutIdx - aSz, aSz, alert, 1); - - /* read mac and fill */ - mac = input + *inOutIdx; - *inOutIdx += (ssl->specs.hash_size + padSz); - - /* verify */ - if (XMEMCMP(mac, verify, ssl->specs.hash_size)) { - CYASSL_MSG(" alert verify mac error"); - return VERIFY_MAC_ERROR; - } - } - else { - *inOutIdx += 16; - /* XXX this should be a value out of the cipher specs */ - } - } + if (ssl->keys.encryptionOn) { + if (ssl->specs.cipher_type != aead) { + int aSz = ALERT_SIZE; + const byte* mac; + byte verify[SHA256_DIGEST_SIZE]; + int padSz = ssl->keys.encryptSz - aSz - ssl->specs.hash_size; + + ssl->hmac(ssl, verify, input + *inOutIdx - aSz, aSz, alert, 1); + + /* read mac and fill */ + mac = input + *inOutIdx; + *inOutIdx += (ssl->specs.hash_size + padSz); + + /* verify */ + if (XMEMCMP(mac, verify, ssl->specs.hash_size)) { + CYASSL_MSG(" alert verify mac error"); + return VERIFY_MAC_ERROR; + } + } + else { + *inOutIdx += 16; + /* XXX this should be a value out of the cipher specs */ + } + } return level; } @@ -3010,11 +3011,11 @@ static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz, sz += pad; } - if (ssl->specs.cipher_type == aead) { - ivSz = AES_GCM_EXPLICIT_IV_SIZE; - sz = sz + ivSz + 16 - digestSz; - RNG_GenerateBlock(&ssl->rng, iv, ivSz); - } + if (ssl->specs.cipher_type == aead) { + ivSz = AES_GCM_EXPLICIT_IV_SIZE; + sz = sz + ivSz + 16 - digestSz; + RNG_GenerateBlock(&ssl->rng, iv, ivSz); + } size = (word16)(sz - headerSz); /* include mac and digest */ AddRecordHeader(output, size, (byte)type, ssl); @@ -3028,10 +3029,10 @@ static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz, if (type == handshake) HashOutput(ssl, output, headerSz + inSz, ivSz); - if (ssl->specs.cipher_type != aead) { - ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, type, 0); - idx += digestSz; - } + if (ssl->specs.cipher_type != aead) { + ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, type, 0); + idx += digestSz; + } if (ssl->specs.cipher_type == block) for (i = 0; i <= pad; i++) diff --git a/src/keys.c b/src/keys.c index 7617b004a..02266b0d6 100644 --- a/src/keys.c +++ b/src/keys.c @@ -1002,17 +1002,15 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, /* TLS can call too */ int StoreKeys(CYASSL* ssl, const byte* keyData) { - int sz = ssl->specs.hash_size, i; + int sz, i = 0; - if (ssl->specs.cipher_type != aead) { - XMEMCPY(ssl->keys.client_write_MAC_secret, keyData, sz); - i = sz; - XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz); - i += sz; - } - else { - sz = 0; - } + if (ssl->specs.cipher_type != aead) { + sz = ssl->specs.hash_size; + XMEMCPY(ssl->keys.client_write_MAC_secret,&keyData[i], sz); + i += sz; + XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz); + i += sz; + } sz = ssl->specs.key_size; XMEMCPY(ssl->keys.client_write_key, &keyData[i], sz); From c2cf1fb708119fe7ff4afb30159513aa0395b47b Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 27 Jun 2012 10:34:43 -0700 Subject: [PATCH 06/24] added HMAC-SHA-384 --- ctaocrypt/src/hmac.c | 85 ++++++++++++++++++++++++++++++++--------- cyassl/ctaocrypt/hmac.h | 19 +++++++-- 2 files changed, 82 insertions(+), 22 deletions(-) diff --git a/ctaocrypt/src/hmac.c b/ctaocrypt/src/hmac.c index 1f777ab5b..298a4461a 100644 --- a/ctaocrypt/src/hmac.c +++ b/ctaocrypt/src/hmac.c @@ -34,7 +34,7 @@ static int InitHmac(Hmac* hmac, int type) hmac->innerHashKeyed = 0; hmac->macType = (byte)type; - if (!(type == MD5 || type == SHA || type == SHA256)) + if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384)) return BAD_FUNC_ARG; if (type == MD5) @@ -45,6 +45,10 @@ static int InitHmac(Hmac* hmac, int type) else if (type == SHA256) InitSha256(&hmac->hash.sha256); #endif +#ifdef CYASSL_SHA384 + else if (type == SHA384) + InitSha384(&hmac->hash.sha384); +#endif return 0; } @@ -54,34 +58,58 @@ void HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) { byte* ip = (byte*) hmac->ipad; byte* op = (byte*) hmac->opad; - word32 i; + word32 i, hmac_block_size = MD5_BLOCK_SIZE; InitHmac(hmac, type); - if (length <= HMAC_BLOCK_SIZE) - XMEMCPY(ip, key, length); - else { - if (hmac->macType == MD5) { + if (hmac->macType == MD5) { + if (length <= MD5_BLOCK_SIZE) { + XMEMCPY(ip, key, length); + } + else { Md5Update(&hmac->hash.md5, key, length); Md5Final(&hmac->hash.md5, ip); length = MD5_DIGEST_SIZE; } - else if (hmac->macType == SHA) { + } + else if (hmac->macType == SHA) { + if (length <= MD5_BLOCK_SIZE) { + XMEMCPY(ip, key, length); + } + else { ShaUpdate(&hmac->hash.sha, key, length); ShaFinal(&hmac->hash.sha, ip); length = SHA_DIGEST_SIZE; } + } #ifndef NO_SHA256 - else if (hmac->macType == SHA256) { + else if (hmac->macType == SHA256) { + if (length <= MD5_BLOCK_SIZE) { + XMEMCPY(ip, key, length); + } + else { Sha256Update(&hmac->hash.sha256, key, length); Sha256Final(&hmac->hash.sha256, ip); length = SHA256_DIGEST_SIZE; } -#endif } - XMEMSET(ip + length, 0, HMAC_BLOCK_SIZE - length); +#endif +#ifdef CYASSL_SHA384 + else if (hmac->macType == SHA384) { + hmac_block_size = SHA384_BLOCK_SIZE; + if (length <= SHA384_BLOCK_SIZE) { + XMEMCPY(ip, key, length); + } + else { + Sha384Update(&hmac->hash.sha384, key, length); + Sha384Final(&hmac->hash.sha384, ip); + length = SHA384_DIGEST_SIZE; + } + } +#endif + XMEMSET(ip + length, 0, hmac_block_size - length); - for(i = 0; i < HMAC_BLOCK_SIZE; i++) { + for(i = 0; i < hmac_block_size; i++) { op[i] = ip[i] ^ OPAD; ip[i] ^= IPAD; } @@ -91,12 +119,16 @@ void HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) static void HmacKeyInnerHash(Hmac* hmac) { if (hmac->macType == MD5) - Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, HMAC_BLOCK_SIZE); + Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, MD5_BLOCK_SIZE); else if (hmac->macType == SHA) - ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, HMAC_BLOCK_SIZE); + ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, MD5_BLOCK_SIZE); #ifndef NO_SHA256 else if (hmac->macType == SHA256) - Sha256Update(&hmac->hash.sha256, (byte*) hmac->ipad, HMAC_BLOCK_SIZE); + Sha256Update(&hmac->hash.sha256, (byte*) hmac->ipad, MD5_BLOCK_SIZE); +#endif +#ifdef CYASSL_SHA384 + else if (hmac->macType == SHA384) + Sha384Update(&hmac->hash.sha384, (byte*) hmac->ipad, SHA384_BLOCK_SIZE); #endif hmac->innerHashKeyed = 1; @@ -116,6 +148,10 @@ void HmacUpdate(Hmac* hmac, const byte* msg, word32 length) else if (hmac->macType == SHA256) Sha256Update(&hmac->hash.sha256, msg, length); #endif +#ifdef CYASSL_SHA384 + else if (hmac->macType == SHA384) + Sha384Update(&hmac->hash.sha384, msg, length); +#endif } @@ -128,30 +164,41 @@ void HmacFinal(Hmac* hmac, byte* hash) if (hmac->macType == MD5) { Md5Final(&hmac->hash.md5, (byte*) hmac->innerHash); - Md5Update(&hmac->hash.md5, (byte*) hmac->opad, HMAC_BLOCK_SIZE); + Md5Update(&hmac->hash.md5, (byte*) hmac->opad, MD5_BLOCK_SIZE); Md5Update(&hmac->hash.md5, (byte*) hmac->innerHash, MD5_DIGEST_SIZE); Md5Final(&hmac->hash.md5, hash); } - else if (hmac->macType ==SHA) { + else if (hmac->macType == SHA) { ShaFinal(&hmac->hash.sha, (byte*) hmac->innerHash); - ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, HMAC_BLOCK_SIZE); + ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, MD5_BLOCK_SIZE); ShaUpdate(&hmac->hash.sha, (byte*) hmac->innerHash, SHA_DIGEST_SIZE); ShaFinal(&hmac->hash.sha, hash); } #ifndef NO_SHA256 - else if (hmac->macType ==SHA256) { + else if (hmac->macType == SHA256) { Sha256Final(&hmac->hash.sha256, (byte*) hmac->innerHash); - Sha256Update(&hmac->hash.sha256, (byte*) hmac->opad, HMAC_BLOCK_SIZE); + Sha256Update(&hmac->hash.sha256, (byte*) hmac->opad, MD5_BLOCK_SIZE); Sha256Update(&hmac->hash.sha256, (byte*) hmac->innerHash, SHA256_DIGEST_SIZE); Sha256Final(&hmac->hash.sha256, hash); } #endif +#ifdef CYASSL_SHA384 + else if (hmac->macType == SHA384) { + Sha384Final(&hmac->hash.sha384, (byte*) hmac->innerHash); + + Sha384Update(&hmac->hash.sha384, (byte*) hmac->opad, SHA384_BLOCK_SIZE); + Sha384Update(&hmac->hash.sha384, (byte*) hmac->innerHash, + SHA384_DIGEST_SIZE); + + Sha384Final(&hmac->hash.sha384, hash); + } +#endif hmac->innerHashKeyed = 0; } diff --git a/cyassl/ctaocrypt/hmac.h b/cyassl/ctaocrypt/hmac.h index 6f022748b..0fa175e89 100644 --- a/cyassl/ctaocrypt/hmac.h +++ b/cyassl/ctaocrypt/hmac.h @@ -32,6 +32,10 @@ #include #endif +#ifdef CYASSL_SHA384 + #include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -40,13 +44,19 @@ enum { IPAD = 0x36, OPAD = 0x5C, -#ifndef NO_SHA256 +#if defined(CYASSL_SHA384) + INNER_HASH_SIZE = SHA384_DIGEST_SIZE, + HMAC_BLOCK_SIZE = SHA384_BLOCK_SIZE +#elif !defined(NO_SHA256) INNER_HASH_SIZE = SHA256_DIGEST_SIZE, + HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE + SHA384 = 5, #else INNER_HASH_SIZE = SHA_DIGEST_SIZE, - SHA256 = 2, /* hash type unique */ -#endif HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE + SHA256 = 2, /* hash type unique */ + SHA384 = 5, +#endif }; @@ -57,6 +67,9 @@ typedef union { #ifndef NO_SHA256 Sha256 sha256; #endif + #ifdef CYASSL_SHA384 + Sha384 sha384; + #endif } Hash; /* Hmac digest */ From 00cda6ab7200fa3d5de14dfaa30552bb648f6690 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 27 Jun 2012 14:41:16 -0700 Subject: [PATCH 07/24] tied SHA-384 into TLSv1.2 as appropriate --- ctaocrypt/src/aes.c | 2 -- cyassl/ctaocrypt/hmac.h | 8 ++--- src/internal.c | 11 ++++-- src/keys.c | 20 +++++------ src/tls.c | 76 ++++++++++++++++++++++++++++++----------- 5 files changed, 79 insertions(+), 38 deletions(-) diff --git a/ctaocrypt/src/aes.c b/ctaocrypt/src/aes.c index 6df52836f..ea815bc63 100644 --- a/ctaocrypt/src/aes.c +++ b/ctaocrypt/src/aes.c @@ -1633,8 +1633,6 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, c += AES_BLOCK_SIZE; } if (partial != 0) { - byte pPartial[AES_BLOCK_SIZE]; - IncrementGcmCounter(ctr); AesEncrypt(aes, ctr, scratch); xorbuf(scratch, c, partial); diff --git a/cyassl/ctaocrypt/hmac.h b/cyassl/ctaocrypt/hmac.h index 0fa175e89..a927e7ed7 100644 --- a/cyassl/ctaocrypt/hmac.h +++ b/cyassl/ctaocrypt/hmac.h @@ -49,13 +49,13 @@ enum { HMAC_BLOCK_SIZE = SHA384_BLOCK_SIZE #elif !defined(NO_SHA256) INNER_HASH_SIZE = SHA256_DIGEST_SIZE, - HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE - SHA384 = 5, + HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE, + SHA384 = 5 #else INNER_HASH_SIZE = SHA_DIGEST_SIZE, - HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE + HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE, SHA256 = 2, /* hash type unique */ - SHA384 = 5, + SHA384 = 5 #endif }; diff --git a/src/internal.c b/src/internal.c index 9e375a12d..8ea543476 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1631,12 +1631,17 @@ static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) Sha sha = ssl->hashSha; #ifndef NO_SHA256 Sha256 sha256; +#endif +#if CYASSL_SHA384 + Sha384 sha384; +#endif + +#ifndef NO_SHA256 InitSha256(&sha256); if (IsAtLeastTLSv1_2(ssl)) sha256 = ssl->hashSha256; #endif #if CYASSL_SHA384 - Sha384 sha384; InitSha384(&sha384); if (IsAtLeastTLSv1_2(ssl)) sha384 = ssl->hashSha384; @@ -1652,14 +1657,14 @@ static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) /* restore */ ssl->hashMd5 = md5; ssl->hashSha = sha; + if (IsAtLeastTLSv1_2(ssl)) { #ifndef NO_SHA256 - if (IsAtLeastTLSv1_2(ssl)) ssl->hashSha256 = sha256; #endif #ifdef CYASSL_SHA384 - if (IsAtLeastTLSv1_2(ssl)) ssl->hashSha384 = sha384; #endif + } } diff --git a/src/keys.c b/src/keys.c index 02266b0d6..84f4deae9 100644 --- a/src/keys.c +++ b/src/keys.c @@ -315,7 +315,7 @@ int SetCipherSpecs(CYASSL* ssl) case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : ssl->specs.bulk_cipher_algorithm = aes_gcm; ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = no_mac; + ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; ssl->specs.hash_size = SHA256_DIGEST_SIZE; @@ -332,7 +332,7 @@ int SetCipherSpecs(CYASSL* ssl) case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 : ssl->specs.bulk_cipher_algorithm = aes_gcm; ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = no_mac; + ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; ssl->specs.hash_size = SHA384_DIGEST_SIZE; @@ -349,7 +349,7 @@ int SetCipherSpecs(CYASSL* ssl) case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 : ssl->specs.bulk_cipher_algorithm = aes_gcm; ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = no_mac; + ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; ssl->specs.hash_size = SHA256_DIGEST_SIZE; @@ -366,7 +366,7 @@ int SetCipherSpecs(CYASSL* ssl) case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 : ssl->specs.bulk_cipher_algorithm = aes_gcm; ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = no_mac; + ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; ssl->specs.hash_size = SHA384_DIGEST_SIZE; @@ -383,7 +383,7 @@ int SetCipherSpecs(CYASSL* ssl) case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 : ssl->specs.bulk_cipher_algorithm = aes_gcm; ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = no_mac; + ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; ssl->specs.hash_size = SHA256_DIGEST_SIZE; @@ -400,7 +400,7 @@ int SetCipherSpecs(CYASSL* ssl) case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 : ssl->specs.bulk_cipher_algorithm = aes_gcm; ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = no_mac; + ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; ssl->specs.hash_size = SHA384_DIGEST_SIZE; @@ -417,7 +417,7 @@ int SetCipherSpecs(CYASSL* ssl) case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 : ssl->specs.bulk_cipher_algorithm = aes_gcm; ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = no_mac; + ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; ssl->specs.hash_size = SHA256_DIGEST_SIZE; @@ -434,7 +434,7 @@ int SetCipherSpecs(CYASSL* ssl) case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 : ssl->specs.bulk_cipher_algorithm = aes_gcm; ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = no_mac; + ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; ssl->specs.hash_size = SHA384_DIGEST_SIZE; @@ -786,7 +786,7 @@ int SetCipherSpecs(CYASSL* ssl) case TLS_RSA_WITH_AES_128_GCM_SHA256 : ssl->specs.bulk_cipher_algorithm = aes_gcm; ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = no_mac; + ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = rsa_kea; ssl->specs.hash_size = SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; @@ -802,7 +802,7 @@ int SetCipherSpecs(CYASSL* ssl) case TLS_RSA_WITH_AES_256_GCM_SHA384 : ssl->specs.bulk_cipher_algorithm = aes_gcm; ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = no_mac; + ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = rsa_kea; ssl->specs.hash_size = SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; diff --git a/src/tls.c b/src/tls.c index 447f0d819..c14af1e5b 100644 --- a/src/tls.c +++ b/src/tls.c @@ -53,28 +53,52 @@ static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha) } +#ifdef CYASSL_SHA384 + #define PHASH_MAX_DIGEST_SIZE SHA384_DIGEST_SIZE +#else + #define PHASH_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE +#endif -/* compute p_hash for MD5, SHA-1, or SHA-256 for TLSv1 PRF */ +/* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */ static void p_hash(byte* result, word32 resLen, const byte* secret, word32 secLen, const byte* seed, word32 seedLen, int hash) { - word32 len = hash == md5_mac ? MD5_DIGEST_SIZE : hash == sha_mac ? - SHA_DIGEST_SIZE : SHA256_DIGEST_SIZE; - word32 times = resLen / len; - word32 lastLen = resLen % len; + word32 len; + word32 times; + word32 lastLen; word32 lastTime; word32 i; word32 idx = 0; - byte previous[SHA256_DIGEST_SIZE]; /* max size */ - byte current[SHA256_DIGEST_SIZE]; /* max size */ + byte previous[PHASH_MAX_DIGEST_SIZE]; /* max size */ + byte current[PHASH_MAX_DIGEST_SIZE]; /* max size */ Hmac hmac; + if (hash == md5_mac) { + len = MD5_DIGEST_SIZE; + hash = MD5; + } + else if (hash == sha_mac) { + len = SHA_DIGEST_SIZE; + hash = SHA; + } else if (hash == sha256_mac) { + len = SHA256_DIGEST_SIZE; + hash = SHA256; + } +#ifdef CYASSL_SHA384 + else if (hash == sha384_mac) + { + len = SHA384_DIGEST_SIZE; + hash = SHA384; + } +#endif + + times = resLen / len; + lastLen = resLen % len; if (lastLen) times += 1; lastTime = times - 1; - HmacSetKey(&hmac, hash == md5_mac ? MD5 : hash == sha_mac ? SHA : SHA256, - secret, secLen); + HmacSetKey(&hmac, hash, secret, secLen); HmacUpdate(&hmac, seed, seedLen); /* A0 = seed */ HmacFinal(&hmac, previous); /* A1 */ @@ -99,7 +123,7 @@ static void p_hash(byte* result, word32 resLen, const byte* secret, /* compute TLSv1 PRF (pseudo random function using HMAC) */ static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen, const byte* label, word32 labLen, const byte* seed, word32 seedLen, - int useSha256) + int useAtLeastSha256, int hash_type) { word32 half = (secLen + 1) / 2; @@ -122,9 +146,13 @@ static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen, XMEMCPY(labelSeed, label, labLen); XMEMCPY(labelSeed + labLen, seed, seedLen); - if (useSha256) { + if (useAtLeastSha256) { + /* If a cipher suite wants an algorithm better than sha256, it + * should use better. */ + if (hash_type < sha256_mac) + hash_type = sha256_mac; p_hash(digest, digLen, secret, secLen, labelSeed, labLen + seedLen, - sha256_mac); + hash_type); return; } @@ -144,12 +172,20 @@ void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) Md5Final(&ssl->hashMd5, handshake_hash); ShaFinal(&ssl->hashSha, &handshake_hash[MD5_DIGEST_SIZE]); -#ifndef NO_SHA256 if (IsAtLeastTLSv1_2(ssl)) { - Sha256Final(&ssl->hashSha256, handshake_hash); - hashSz = SHA256_DIGEST_SIZE; - } +#ifndef NO_SHA256 + if (ssl->specs.mac_algorithm <= sha256_mac) { + Sha256Final(&ssl->hashSha256, handshake_hash); + hashSz = SHA256_DIGEST_SIZE; + } #endif +#ifdef CYASSL_SHA384 + if (ssl->specs.mac_algorithm == sha384_mac) { + Sha384Final(&ssl->hashSha384, handshake_hash); + hashSz = SHA384_DIGEST_SIZE; + } +#endif + } if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) side = tls_client; @@ -157,7 +193,8 @@ void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) side = tls_server; PRF(hashes->md5, TLS_FINISHED_SZ, ssl->arrays.masterSecret, SECRET_LEN, - side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl)); + side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl), + ssl->specs.mac_algorithm); } @@ -207,7 +244,8 @@ int DeriveTlsKeys(CYASSL* ssl) XMEMCPY(&seed[RAN_LEN], ssl->arrays.clientRandom, RAN_LEN); PRF(key_data, length, ssl->arrays.masterSecret, SECRET_LEN, key_label, - KEY_LABEL_SZ, seed, SEED_LEN, IsAtLeastTLSv1_2(ssl)); + KEY_LABEL_SZ, seed, SEED_LEN, IsAtLeastTLSv1_2(ssl), + ssl->specs.mac_algorithm); return StoreKeys(ssl, key_data); } @@ -223,7 +261,7 @@ int MakeTlsMasterSecret(CYASSL* ssl) PRF(ssl->arrays.masterSecret, SECRET_LEN, ssl->arrays.preMasterSecret, ssl->arrays.preMasterSz, master_label, MASTER_LABEL_SZ, - seed, SEED_LEN, IsAtLeastTLSv1_2(ssl)); + seed, SEED_LEN, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); #ifdef SHOW_SECRETS { From 6cdd8f46faad89fd0475e72307601cd4cc63e25f Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 28 Jun 2012 09:06:24 -0700 Subject: [PATCH 08/24] needed a bigger handshake hash array for SHA-384 cipher suites --- src/tls.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/tls.c b/src/tls.c index c14af1e5b..aa4ba6740 100644 --- a/src/tls.c +++ b/src/tls.c @@ -164,10 +164,17 @@ static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen, } +#ifdef CYASSL_SHA384 + #define HSHASH_SZ SHA384_DIGEST_SIZE +#else + #define HSHASH_SZ FINISHED_SZ +#endif + + void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) { const byte* side; - byte handshake_hash[FINISHED_SZ]; + byte handshake_hash[HSHASH_SZ]; word32 hashSz = FINISHED_SZ; Md5Final(&ssl->hashMd5, handshake_hash); From 9295917ef201cdf6ec7d25e4ba2efdd100834476 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 28 Jun 2012 11:28:41 -0700 Subject: [PATCH 09/24] Separated out the AES-GCM test as its own test case. --- ctaocrypt/test/test.c | 165 +++++++++++++++++++++++------------------- 1 file changed, 90 insertions(+), 75 deletions(-) diff --git a/ctaocrypt/test/test.c b/ctaocrypt/test/test.c index 18a976cf6..a3498abe9 100644 --- a/ctaocrypt/test/test.c +++ b/ctaocrypt/test/test.c @@ -99,6 +99,7 @@ int rabbit_test(); int des_test(); int des3_test(); int aes_test(); +int aesgcm_test(); int rsa_test(); int dh_test(); int dsa_test(); @@ -233,6 +234,13 @@ void ctaocrypt_test(void* args) err_sys("AES test failed!\n", ret); else printf( "AES test passed!\n"); + +#ifdef HAVE_AESGCM + if ( (ret = aesgcm_test()) ) + err_sys("AES-GCM test failed!\n", ret); + else + printf( "AES-GCM test passed!\n"); +#endif #endif if ( (ret = random_test()) ) @@ -1144,93 +1152,100 @@ int aes_test() } #endif /* CYASSL_AES_COUNTER */ + return 0; +} + #ifdef HAVE_AESGCM +int aesgcm_test() +{ + Aes enc; + + /* + * This is Test Case 16 from the document Galois/ + * Counter Mode of Operation (GCM) by McGrew and + * Viega. + */ + const byte k[] = { - /* - * This is Test Case 16 from the document Galois/ - * Counter Mode of Operation (GCM) by McGrew and - * Viega. - */ - const byte k[] = - { - 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, - 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, - 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, - 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 - }; + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 + }; - const byte iv[] = - { - 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, - 0xde, 0xca, 0xf8, 0x88, 0x00, 0x00, 0x00, 0x00 - }; - - const byte p[] = - { - 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, - 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, - 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, - 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, - 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, - 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, - 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, - 0xba, 0x63, 0x7b, 0x39 - }; - - const byte a[] = - { - 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xab, 0xad, 0xda, 0xd2 - }; - - const byte c[] = - { - 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, - 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, - 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, - 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, - 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, - 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, - 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, - 0xbc, 0xc9, 0xf6, 0x62 - }; + const byte iv[] = + { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, 0x00, 0x00, 0x00, 0x00 + }; + + const byte p[] = + { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39 + }; + + const byte a[] = + { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 + }; + + const byte c[] = + { + 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62 + }; - const byte t[] = - { - 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, - 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b - }; + const byte t[] = + { + 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, + 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b + }; - byte t2[16]; - byte p2[60]; - byte c2[60]; + byte t2[16]; + byte p2[60]; + byte c2[60]; - int result; + int result; - memset(t2, 0, 16); - memset(c2, 0, 60); - memset(p2, 0, 60); + memset(t2, 0, 16); + memset(c2, 0, 60); + memset(p2, 0, 60); - AesSetKey(&enc, k, sizeof(k), iv, AES_ENCRYPTION); - /* AES-GCM encrypt and decrypt both use AES encrypt internally */ - AesGcmEncrypt(&enc, c2, p, sizeof(c2), t2, sizeof(t2), a, sizeof(a)); - if (memcmp(c, c2, sizeof(c2))) - return -68; - if (memcmp(t, t2, sizeof(t2))) - return -69; + AesSetKey(&enc, k, sizeof(k), iv, AES_ENCRYPTION); + /* AES-GCM encrypt and decrypt both use AES encrypt internally */ + AesGcmEncrypt(&enc, c2, p, sizeof(c2), 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)); - if (result != 0) - return -70; - if (memcmp(p, p2, sizeof(p2))) - return -71; - } -#endif /* HAVE_AESGCM */ + result = AesGcmDecrypt(&enc, + p2, c2, sizeof(p2), t2, sizeof(t2), a, sizeof(a)); + if (result != 0) + return -70; + if (memcmp(p, p2, sizeof(p2))) + return -71; return 0; } +#endif /* HAVE_AESGCM */ + + #endif /* NO_AES */ From 2ce28d03288dfa3ddc851523ac1b0bb3a9f40f1f Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 28 Jun 2012 15:13:41 -0700 Subject: [PATCH 10/24] clean up from lots-o-warnings build --- src/internal.c | 4 ++-- src/tls.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/internal.c b/src/internal.c index 8ea543476..b4a1ec937 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1632,7 +1632,7 @@ static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) #ifndef NO_SHA256 Sha256 sha256; #endif -#if CYASSL_SHA384 +#ifdef CYASSL_SHA384 Sha384 sha384; #endif @@ -1641,7 +1641,7 @@ static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) if (IsAtLeastTLSv1_2(ssl)) sha256 = ssl->hashSha256; #endif -#if CYASSL_SHA384 +#ifdef CYASSL_SHA384 InitSha384(&sha384); if (IsAtLeastTLSv1_2(ssl)) sha384 = ssl->hashSha384; diff --git a/src/tls.c b/src/tls.c index aa4ba6740..f5ef46007 100644 --- a/src/tls.c +++ b/src/tls.c @@ -63,7 +63,7 @@ static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha) static void p_hash(byte* result, word32 resLen, const byte* secret, word32 secLen, const byte* seed, word32 seedLen, int hash) { - word32 len; + word32 len = MD5_DIGEST_SIZE; word32 times; word32 lastLen; word32 lastTime; @@ -75,7 +75,6 @@ static void p_hash(byte* result, word32 resLen, const byte* secret, Hmac hmac; if (hash == md5_mac) { - len = MD5_DIGEST_SIZE; hash = MD5; } else if (hash == sha_mac) { From 5dc0303deea5703d16e14f9a6d817986e3f406de Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 28 Jun 2012 23:09:13 -0700 Subject: [PATCH 11/24] cipher suite setup oversight fixes --- src/internal.c | 4 ++-- src/keys.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/internal.c b/src/internal.c index b4a1ec937..b273cea61 100644 --- a/src/internal.c +++ b/src/internal.c @@ -3954,7 +3954,7 @@ const char* const cipher_names[] = #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - "ECDH-RSA-AES128-GCM-SHA384", + "ECDH-RSA-AES256-GCM-SHA384", #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 @@ -4129,7 +4129,7 @@ int cipher_name_idx[] = TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, #endif -#ifdef BUILD_DHE_TLS_RSA_WITH_AES_256_GCM_SHA384 +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, #endif diff --git a/src/keys.c b/src/keys.c index 84f4deae9..846345af8 100644 --- a/src/keys.c +++ b/src/keys.c @@ -788,6 +788,7 @@ int SetCipherSpecs(CYASSL* ssl) 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; @@ -804,6 +805,41 @@ int SetCipherSpecs(CYASSL* ssl) 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 = AES_GCM_IMPLICIT_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = diffie_hellman_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 = AES_GCM_IMPLICIT_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = diffie_hellman_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; From b1e39f66a3ea9f40a54c5e6a70b15388bcba4c96 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Sat, 30 Jun 2012 15:50:25 -0700 Subject: [PATCH 12/24] fixed a cipher suite name typo, changed the selection of the ECDH-RSA ciphers in InitSuites() --- src/internal.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/internal.c b/src/internal.c index b273cea61..33e001b99 100644 --- a/src/internal.c +++ b/src/internal.c @@ -527,14 +527,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - if (tls1_2 && haveRSA && haveStaticECC) { + if (tls1_2 && (haveRSA || haveECDSA) && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256; } #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - if (tls1_2 && haveRSA && haveStaticECC) { + if (tls1_2 && (haveRSA || haveECDSA) && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384; } @@ -646,7 +646,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA - if (tls && haveRSA && haveStaticECC) { + if (tls && (haveRSA || haveECDSA) && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA; } @@ -660,7 +660,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - if (tls && haveRSA && haveStaticECC) { + if (tls && (haveRSA || haveECDSA) && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA; } @@ -3942,7 +3942,7 @@ const char* const cipher_names[] = #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - "ECDHE-EDCSA-AES128-GCM-SHA256", + "ECDHE-ECDSA-AES128-GCM-SHA256", #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 From be4ce974d062dd362e467249f9e1d5872d866644 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Sat, 30 Jun 2012 15:51:18 -0700 Subject: [PATCH 13/24] Updated to use TLSv1.2. Changed the string scanning to play better with other echo servers. --- examples/echoclient/echoclient.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/examples/echoclient/echoclient.c b/examples/echoclient/echoclient.c index a800555ec..e3af66543 100644 --- a/examples/echoclient/echoclient.c +++ b/examples/echoclient/echoclient.c @@ -69,7 +69,7 @@ void echoclient_test(void* args) #if defined(CYASSL_DTLS) method = DTLSv1_client_method(); #elif !defined(NO_TLS) - method = TLSv1_client_method(); + method = TLSv1_2_client_method(); #else method = SSLv3_client_method(); #endif @@ -105,7 +105,7 @@ void echoclient_test(void* args) while (fgets(send, sizeof(send), fin)) { - sendSz = (int)strlen(send) + 1; + sendSz = (int)strlen(send); if (SSL_write(ssl, send, sendSz) != sendSz) err_sys("SSL_write failed"); @@ -115,7 +115,7 @@ void echoclient_test(void* args) break; } - if (strncmp(send, "break", 4) == 0) { + if (strncmp(send, "break", 5) == 0) { fputs("sending server session close: break!\n", fout); break; } @@ -123,6 +123,7 @@ void echoclient_test(void* args) while (sendSz) { int got; if ( (got = SSL_read(ssl, reply, sizeof(reply))) > 0) { + reply[got] = 0; fputs(reply, fout); sendSz -= got; } @@ -165,6 +166,9 @@ void echoclient_test(void* args) args.argv = argv; CyaSSL_Init(); +#ifdef DEBUG_CYASSL + CyaSSL_Debugging_ON(); +#endif if (CurrentDir("echoclient") || CurrentDir("build")) ChangeDirBack(2); echoclient_test(&args); From 1f6c24f15a0b34b4a7c43aa0bc0e91535d946eed Mon Sep 17 00:00:00 2001 From: John Safranek Date: Sat, 30 Jun 2012 16:55:29 -0700 Subject: [PATCH 14/24] added aes-gcm to the benchmark tests --- ctaocrypt/benchmark/benchmark.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/ctaocrypt/benchmark/benchmark.c b/ctaocrypt/benchmark/benchmark.c index 701061e40..379de527c 100644 --- a/ctaocrypt/benchmark/benchmark.c +++ b/ctaocrypt/benchmark/benchmark.c @@ -54,6 +54,7 @@ void bench_arc4(); void bench_hc128(); void bench_rabbit(); void bench_aes(int); +void bench_aesgcm(); void bench_md5(); void bench_sha(); @@ -78,6 +79,9 @@ int main(int argc, char** argv) #ifndef NO_AES bench_aes(0); bench_aes(1); +#endif +#ifdef HAVE_AESGCM + bench_aesgcm(); #endif bench_arc4(); #ifdef HAVE_HC128 @@ -171,6 +175,33 @@ void bench_aes(int show) #endif +byte additional[13]; +byte tag[16]; + + +#ifdef HAVE_AESGCM +void bench_aesgcm() +{ + Aes enc; + double start, total, persec; + int i; + + AesSetKey(&enc, key, 16, iv, AES_ENCRYPTION); + start = current_time(); + + for(i = 0; i < megs; i++) + AesGcmEncrypt(&enc, cipher, plain, sizeof(plain), + tag, 16, additional, 13); + + total = current_time() - start; + + persec = 1 / total * megs; + printf("AES-GCM %d megs took %5.3f seconds, %6.2f MB/s\n", megs, total, + persec); +} +#endif + + #ifndef NO_DES3 void bench_des() { From fe645234807d8c8f25058b2387c0579f7a1545b8 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 2 Jul 2012 12:36:28 -0700 Subject: [PATCH 15/24] backed out an earlier change pending more research --- src/internal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/internal.c b/src/internal.c index 33e001b99..d77f2a6f9 100644 --- a/src/internal.c +++ b/src/internal.c @@ -527,14 +527,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - if (tls1_2 && (haveRSA || haveECDSA) && haveStaticECC) { + if (tls1_2 && haveRSA && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256; } #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - if (tls1_2 && (haveRSA || haveECDSA) && haveStaticECC) { + if (tls1_2 && haveRSA && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384; } @@ -646,7 +646,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA - if (tls && (haveRSA || haveECDSA) && haveStaticECC) { + if (tls && haveRSA && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA; } @@ -660,7 +660,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - if (tls && (haveRSA || haveECDSA) && haveStaticECC) { + if (tls && haveRSA && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA; } From 56d2180cf3d71af93d75390ecb654a16c6601838 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 9 Jul 2012 09:50:26 -0700 Subject: [PATCH 16/24] use CyaSSLv23_client_method() rather than TLSv1_1_client_method() to parallel echoserver.c --- examples/echoclient/echoclient.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/echoclient/echoclient.c b/examples/echoclient/echoclient.c index e3af66543..d33d2da86 100644 --- a/examples/echoclient/echoclient.c +++ b/examples/echoclient/echoclient.c @@ -69,7 +69,7 @@ void echoclient_test(void* args) #if defined(CYASSL_DTLS) method = DTLSv1_client_method(); #elif !defined(NO_TLS) - method = TLSv1_2_client_method(); + method = CyaSSLv23_client_method(); #else method = SSLv3_client_method(); #endif From 1ac6db9d1d61c973e0ecd29de14dbe677fda92df Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 9 Jul 2012 10:02:34 -0700 Subject: [PATCH 17/24] added basic hello extension support for TLSv1.2, renumbered the algorithm enumerations to match RFC --- cyassl/internal.h | 8 +++++--- src/internal.c | 43 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/cyassl/internal.h b/cyassl/internal.h index 9df65fab5..b8d322568 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -341,6 +341,7 @@ enum Misc { TLSv1_2_MINOR = 3, /* TLSv1_2 minor version number */ NO_COMPRESSION = 0, ZLIB_COMPRESSION = 221, /* CyaSSL zlib compression */ + HELLO_EXT_SIG_ALGO = 13, /* ID for the sig_algo hello extension */ SECRET_LEN = 48, /* pre RSA and all master */ ENCRYPT_LEN = 512, /* allow 4096 bit static buffer */ SIZEOF_SENDER = 4, /* clnt or srvr */ @@ -380,6 +381,7 @@ enum Misc { CERT_HEADER_SZ = 3, /* always 3 bytes */ REQ_HEADER_SZ = 2, /* cert request header sz */ HINT_LEN_SZ = 2, /* length of hint size field */ + HELLO_EXT_SZ = 14, /* length of the lazy hello extensions */ DTLS_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */ DTLS_RECORD_HEADER_SZ = 13, /* normal + epoch(2) + seq_num(6) */ @@ -841,7 +843,7 @@ enum BulkCipherAlgorithm { /* Supported Message Authentication Codes from page 43 */ enum MACAlgorithm { - no_mac = 10, + no_mac = 0, md5_mac, sha_mac, sha224_mac, @@ -854,7 +856,7 @@ enum MACAlgorithm { /* Supported Key Exchange Protocols */ enum KeyExchangeAlgorithm { - no_kea = 20, + no_kea = 0, rsa_kea, diffie_hellman_kea, fortezza_kea, @@ -867,7 +869,7 @@ enum KeyExchangeAlgorithm { /* Supported Authentication Schemes */ enum SignatureAlgorithm { - anonymous_sa_algo = 30, + anonymous_sa_algo = 0, rsa_sa_algo, dsa_sa_algo, ecc_dsa_sa_algo diff --git a/src/internal.c b/src/internal.c index d77f2a6f9..98db54346 100644 --- a/src/internal.c +++ b/src/internal.c @@ -55,7 +55,7 @@ #ifndef NO_CYASSL_CLIENT static int DoHelloVerifyRequest(CYASSL* ssl, const byte* input, word32*); - static int DoServerHello(CYASSL* ssl, const byte* input, word32*); + static int DoServerHello(CYASSL* ssl, const byte* input, word32*, word32); static int DoCertificateRequest(CYASSL* ssl, const byte* input, word32*); static int DoServerKeyExchange(CYASSL* ssl, const byte* input, word32*); #endif @@ -2125,7 +2125,7 @@ static int DoHandShakeMsg(CYASSL* ssl, byte* input, word32* inOutIdx, case server_hello: CYASSL_MSG("processing server hello"); - ret = DoServerHello(ssl, input, inOutIdx); + ret = DoServerHello(ssl, input, inOutIdx, size); break; case certificate_request: @@ -4384,7 +4384,10 @@ int SetCipherList(Suites* s, const char* list) length = sizeof(ProtocolVersion) + RAN_LEN + idSz + ENUM_LEN + ssl->suites.suiteSz + SUITE_LEN - + COMP_LEN + ENUM_LEN; + + COMP_LEN + ENUM_LEN; + + if (IsAtLeastTLSv1_2(ssl)) + length += HELLO_EXT_SZ; sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; @@ -4450,7 +4453,28 @@ int SetCipherList(Suites* s, const char* list) output[idx++] = ZLIB_COMPRESSION; else output[idx++] = NO_COMPRESSION; - + + if (IsAtLeastTLSv1_2(ssl)) + { + /* add in the extensions length */ + c16toa(HELLO_EXT_SZ-2, output + idx); + idx += 2; + + c16toa(HELLO_EXT_SIG_ALGO, output + idx); + idx += 2; + c16toa(HELLO_EXT_SZ-6, output + idx); + idx += 2; + + c16toa(HELLO_EXT_SZ-8, output + idx); + idx += 2; + output[idx++] = sha_mac; + output[idx++] = rsa_sa_algo; + output[idx++] = sha_mac; + output[idx++] = dsa_sa_algo; + output[idx++] = sha_mac; + output[idx++] = ecc_dsa_sa_algo; + } + HashOutput(ssl, output, sendSz, 0); ssl->options.clientState = CLIENT_HELLO_COMPLETE; @@ -4492,12 +4516,15 @@ int SetCipherList(Suites* s, const char* list) } - static int DoServerHello(CYASSL* ssl, const byte* input, word32* inOutIdx) + static int DoServerHello(CYASSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) { byte b; byte compression; ProtocolVersion pv; + word16 extSz; word32 i = *inOutIdx; + word32 begin = i; #ifdef CYASSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); @@ -4549,7 +4576,11 @@ int SetCipherList(Suites* s, const char* list) CYASSL_MSG("Server refused compression, turning off"); ssl->options.usingCompression = 0; /* turn off if server refused */ } - + + *inOutIdx = i; + if ( (i - begin) < helloSz) + *inOutIdx = begin + helloSz; /* skip extensions */ + ssl->options.serverState = SERVER_HELLO_COMPLETE; *inOutIdx = i; From bdacd5e8c4e92ff0667932e5a803eabd834e7e1e Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 9 Jul 2012 10:33:05 -0700 Subject: [PATCH 18/24] cleaned up lots-o-warnings build --- src/internal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 98db54346..4a166659a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4522,7 +4522,6 @@ int SetCipherList(Suites* s, const char* list) byte b; byte compression; ProtocolVersion pv; - word16 extSz; word32 i = *inOutIdx; word32 begin = i; From 87a8cfadd3effd01e5868695160baa4b4b67afe7 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 12 Jul 2012 15:20:56 -0700 Subject: [PATCH 19/24] Used consistent constants. --- ctaocrypt/src/hmac.c | 14 ++++++++------ cyassl/ctaocrypt/hmac.h | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ctaocrypt/src/hmac.c b/ctaocrypt/src/hmac.c index 298a4461a..880581e8c 100644 --- a/ctaocrypt/src/hmac.c +++ b/ctaocrypt/src/hmac.c @@ -73,7 +73,8 @@ void HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) } } else if (hmac->macType == SHA) { - if (length <= MD5_BLOCK_SIZE) { + hmac_block_size = SHA_BLOCK_SIZE; + if (length <= SHA_BLOCK_SIZE) { XMEMCPY(ip, key, length); } else { @@ -84,7 +85,8 @@ void HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) } #ifndef NO_SHA256 else if (hmac->macType == SHA256) { - if (length <= MD5_BLOCK_SIZE) { + hmac_block_size = SHA256_BLOCK_SIZE; + if (length <= SHA256_BLOCK_SIZE) { XMEMCPY(ip, key, length); } else { @@ -121,10 +123,10 @@ static void HmacKeyInnerHash(Hmac* hmac) if (hmac->macType == MD5) Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, MD5_BLOCK_SIZE); else if (hmac->macType == SHA) - ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, MD5_BLOCK_SIZE); + ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, SHA_BLOCK_SIZE); #ifndef NO_SHA256 else if (hmac->macType == SHA256) - Sha256Update(&hmac->hash.sha256, (byte*) hmac->ipad, MD5_BLOCK_SIZE); + Sha256Update(&hmac->hash.sha256, (byte*) hmac->ipad, SHA256_BLOCK_SIZE); #endif #ifdef CYASSL_SHA384 else if (hmac->macType == SHA384) @@ -172,7 +174,7 @@ void HmacFinal(Hmac* hmac, byte* hash) else if (hmac->macType == SHA) { ShaFinal(&hmac->hash.sha, (byte*) hmac->innerHash); - ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, MD5_BLOCK_SIZE); + ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, SHA_BLOCK_SIZE); ShaUpdate(&hmac->hash.sha, (byte*) hmac->innerHash, SHA_DIGEST_SIZE); ShaFinal(&hmac->hash.sha, hash); @@ -181,7 +183,7 @@ void HmacFinal(Hmac* hmac, byte* hash) else if (hmac->macType == SHA256) { Sha256Final(&hmac->hash.sha256, (byte*) hmac->innerHash); - Sha256Update(&hmac->hash.sha256, (byte*) hmac->opad, MD5_BLOCK_SIZE); + Sha256Update(&hmac->hash.sha256, (byte*) hmac->opad, SHA256_BLOCK_SIZE); Sha256Update(&hmac->hash.sha256, (byte*) hmac->innerHash, SHA256_DIGEST_SIZE); diff --git a/cyassl/ctaocrypt/hmac.h b/cyassl/ctaocrypt/hmac.h index a927e7ed7..ee11669d0 100644 --- a/cyassl/ctaocrypt/hmac.h +++ b/cyassl/ctaocrypt/hmac.h @@ -49,11 +49,11 @@ enum { HMAC_BLOCK_SIZE = SHA384_BLOCK_SIZE #elif !defined(NO_SHA256) INNER_HASH_SIZE = SHA256_DIGEST_SIZE, - HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE, + HMAC_BLOCK_SIZE = SHA256_BLOCK_SIZE, SHA384 = 5 #else INNER_HASH_SIZE = SHA_DIGEST_SIZE, - HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE, + HMAC_BLOCK_SIZE = SHA_BLOCK_SIZE, SHA256 = 2, /* hash type unique */ SHA384 = 5 #endif From ac79d3b14530807673086c7ae91eedeab289d300 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 17 Jul 2012 10:00:45 -0700 Subject: [PATCH 20/24] replaced magic numbers with named constants, renamed some constants --- ctaocrypt/src/aes.c | 44 ++++++++++-------- cyassl/internal.h | 18 ++++++-- src/internal.c | 107 +++++++++++++++++++++++++++----------------- src/keys.c | 24 +++++----- 4 files changed, 117 insertions(+), 76 deletions(-) diff --git a/ctaocrypt/src/aes.c b/ctaocrypt/src/aes.c index ea815bc63..91268a0fa 100644 --- a/ctaocrypt/src/aes.c +++ b/ctaocrypt/src/aes.c @@ -1475,10 +1475,29 @@ static void GMULT(byte* X, byte* Y) } +static INLINE void FlattenSzInBits(byte* buf, word32 sz) +{ + /* Multiply the sz by 8 */ + word32 szHi = (sz >> (8*sizeof(sz) - 3)); + sz <<= 3; + + /* copy over the words of the sz into the destination buffer */ + buf[0] = (szHi >> 24) & 0xff; + buf[1] = (szHi >> 16) & 0xff; + buf[2] = (szHi >> 8) & 0xff; + buf[3] = szHi & 0xff; + buf[4] = (sz >> 24) & 0xff; + buf[5] = (sz >> 16) & 0xff; + buf[6] = (sz >> 8) & 0xff; + buf[7] = sz & 0xff; +} + + static void GHASH(byte* h, const byte* a, word32 aSz, const byte* c, word32 cSz, byte* s, word32 sSz) { byte x[AES_BLOCK_SIZE]; + byte scratch[AES_BLOCK_SIZE]; word32 blocks, partial; XMEMSET(x, 0, AES_BLOCK_SIZE); @@ -1493,7 +1512,6 @@ static void GHASH(byte* h, const byte* a, word32 aSz, a += AES_BLOCK_SIZE; } if (partial != 0) { - byte scratch[AES_BLOCK_SIZE]; XMEMSET(scratch, 0, AES_BLOCK_SIZE); XMEMCPY(scratch, a, partial); xorbuf(x, scratch, AES_BLOCK_SIZE); @@ -1511,7 +1529,6 @@ static void GHASH(byte* h, const byte* a, word32 aSz, c += AES_BLOCK_SIZE; } if (partial != 0) { - byte scratch[AES_BLOCK_SIZE]; XMEMSET(scratch, 0, AES_BLOCK_SIZE); XMEMCPY(scratch, c, partial); xorbuf(x, scratch, AES_BLOCK_SIZE); @@ -1519,24 +1536,13 @@ static void GHASH(byte* h, const byte* a, word32 aSz, } } - /* Hash in the lengths in bits of A and C */ - { - byte len[AES_BLOCK_SIZE]; - XMEMSET(len, 0, AES_BLOCK_SIZE); - len[3] = aSz >> 29; - len[4] = aSz >> 21; - len[5] = aSz >> 13; - len[6] = aSz >> 5; - len[7] = aSz << 3; + /* Hash in the lengths of A and C in bits */ + FlattenSzInBits(&scratch[0], aSz); + FlattenSzInBits(&scratch[8], cSz); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, h); - len[11] = cSz >> 29; - len[12] = cSz >> 21; - len[13] = cSz >> 13; - len[14] = cSz >> 5; - len[15] = cSz << 3; - xorbuf(x, len, AES_BLOCK_SIZE); - GMULT(x, h); - } + /* Copy the result into s. */ XMEMCPY(s, x, sSz); } diff --git a/cyassl/internal.h b/cyassl/internal.h index 6294598e5..02d33f52f 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -381,7 +381,10 @@ enum Misc { CERT_HEADER_SZ = 3, /* always 3 bytes */ REQ_HEADER_SZ = 2, /* cert request header sz */ HINT_LEN_SZ = 2, /* length of hint size field */ - HELLO_EXT_SZ = 14, /* length of the lazy hello extensions */ + HELLO_EXT_SZ = 14, /* total length of the lazy hello extensions */ + HELLO_EXT_LEN = 12, /* length of the lazy hello extensions */ + HELLO_EXT_SIGALGO_SZ = 8, /* length of signature algo extension */ + HELLO_EXT_SIGALGO_LEN = 6, /* number of items in the signature algo list */ DTLS_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */ DTLS_RECORD_HEADER_SZ = 13, /* normal + epoch(2) + seq_num(6) */ @@ -405,10 +408,19 @@ 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_IMPLICIT_IV_SIZE = 4, /* Implicit half of IV */ - AES_GCM_EXPLICIT_IV_SIZE = 8, /* Explicit half of IV */ + 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 */ + AEAD_TYPE_OFFSET = 8, /* Auth Data: Type */ + AEAD_VMAJ_OFFSET = 9, /* Auth Data: Major Version */ + AEAD_VMIN_OFFSET = 10, /* Auth Data: Minor Version */ + 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 */ + HC_128_KEY_SIZE = 16, /* 128 bits */ HC_128_IV_SIZE = 16, /* also 128 bits */ diff --git a/src/internal.c b/src/internal.c index cb74aebf3..df3584320 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2064,8 +2064,7 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff) } } else { - idx = idx + finishedSz + 16; - /* XXX the 16 should be from specs */ + idx += (finishedSz + AEAD_AUTH_TAG_SZ); } if (ssl->options.side == CLIENT_END) { @@ -2233,26 +2232,40 @@ static INLINE void Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz) byte additional[AES_BLOCK_SIZE]; byte nonce[AES_BLOCK_SIZE]; + /* use this side's IV */ if (ssl->options.side == SERVER_END) { XMEMCPY(nonce, ssl->keys.server_write_IV, - AES_GCM_IMPLICIT_IV_SIZE); + AES_GCM_IMP_IV_SZ); } else { XMEMCPY(nonce, ssl->keys.client_write_IV, - AES_GCM_IMPLICIT_IV_SIZE); + AES_GCM_IMP_IV_SZ); } - XMEMCPY(nonce + AES_GCM_IMPLICIT_IV_SIZE, - input, AES_GCM_EXPLICIT_IV_SIZE); - XMEMSET(nonce + AES_GCM_IMPLICIT_IV_SIZE + - AES_GCM_EXPLICIT_IV_SIZE, 0, 4); + XMEMCPY(nonce + AES_GCM_IMP_IV_SZ, + input, AES_GCM_EXP_IV_SZ); + XMEMSET(nonce + AES_GCM_IMP_IV_SZ + AES_GCM_EXP_IV_SZ, + 0, AES_GCM_CTR_IV_SZ); AesSetIV(&ssl->encrypt.aes, nonce); - - XMEMSET(additional, 0, 16); - c32toa(GetSEQIncrement(ssl, 0), additional + 4); - XMEMCPY(additional+8, input - 5, 5); - c16toa(sz - 24, additional+11); - AesGcmEncrypt(&ssl->encrypt.aes, out+8, input+8, sz-24, - out + sz - 16, 16, additional, 13); + + 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 - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, + additional + AEAD_LEN_OFFSET); + 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 + sz - AEAD_AUTH_TAG_SZ, AEAD_AUTH_TAG_SZ, + additional, AEAD_AUTH_DATA_SZ); } break; #endif @@ -2300,31 +2313,41 @@ static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input, #ifdef BUILD_AESGCM case aes_gcm: { - byte additional[16]; - byte nonce[16]; + byte additional[AES_BLOCK_SIZE]; + byte nonce[AES_BLOCK_SIZE]; /* use the other side's IV */ if (ssl->options.side == SERVER_END) { XMEMCPY(nonce, ssl->keys.client_write_IV, - AES_GCM_IMPLICIT_IV_SIZE); + AES_GCM_IMP_IV_SZ); } else { XMEMCPY(nonce, ssl->keys.server_write_IV, - AES_GCM_IMPLICIT_IV_SIZE); + AES_GCM_IMP_IV_SZ); } - XMEMCPY(nonce + AES_GCM_IMPLICIT_IV_SIZE, - input, AES_GCM_EXPLICIT_IV_SIZE); - XMEMSET(nonce + AES_GCM_IMPLICIT_IV_SIZE + - AES_GCM_EXPLICIT_IV_SIZE, 0, 4); + XMEMCPY(nonce + AES_GCM_IMP_IV_SZ, + input, AES_GCM_EXP_IV_SZ); + XMEMSET(nonce + AES_GCM_IMP_IV_SZ + AES_GCM_EXP_IV_SZ, + 0, AES_GCM_CTR_IV_SZ); AesSetIV(&ssl->decrypt.aes, nonce); - XMEMSET(additional, 0, 4); - c32toa(GetSEQIncrement(ssl, 1), additional + 4); - additional[8] = ssl->curRL.type; - additional[9] = ssl->curRL.version.major; - additional[10] = ssl->curRL.version.minor; - c16toa(sz-24, additional + 11); - if (AesGcmDecrypt(&ssl->decrypt.aes, plain+8, input+8, sz-24, - input + 8 + (sz - 24), 16, additional, 13) < 0) { + + 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.version.major; + additional[AEAD_VMIN_OFFSET] = ssl->curRL.version.minor; + + c16toa(sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, + additional + AEAD_LEN_OFFSET); + 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, + input + sz - AEAD_AUTH_TAG_SZ, AEAD_AUTH_TAG_SZ, + additional, AEAD_AUTH_DATA_SZ) < 0) { SendAlert(ssl, alert_fatal, bad_record_mac); return VERIFY_MAC_ERROR; } @@ -2362,7 +2385,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_EXPLICIT_IV_SIZE; + *idx += AES_GCM_EXP_IV_SZ; } return decryptResult; @@ -2393,8 +2416,8 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx) padByte = 1; } if (ssl->specs.cipher_type == aead) { - ivExtra = 8; - digestSz = 16; + ivExtra = AES_GCM_EXP_IV_SZ; + digestSz = AEAD_AUTH_TAG_SZ; } dataSz = msgSz - ivExtra - digestSz - pad - padByte; @@ -2497,8 +2520,7 @@ static int DoAlert(CYASSL* ssl, byte* input, word32* inOutIdx, int* type) } } else { - *inOutIdx += 16; - /* XXX this should be a value out of the cipher specs */ + *inOutIdx += AEAD_AUTH_TAG_SZ; } } @@ -3017,8 +3039,8 @@ static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz, } if (ssl->specs.cipher_type == aead) { - ivSz = AES_GCM_EXPLICIT_IV_SIZE; - sz = sz + ivSz + 16 - digestSz; + ivSz = AES_GCM_EXP_IV_SZ; + sz += (ivSz + 16 - digestSz); RNG_GenerateBlock(&ssl->rng, iv, ivSz); } size = (word16)(sz - headerSz); /* include mac and digest */ @@ -4457,15 +4479,16 @@ int SetCipherList(Suites* s, const char* list) if (IsAtLeastTLSv1_2(ssl)) { /* add in the extensions length */ - c16toa(HELLO_EXT_SZ-2, output + idx); + c16toa(HELLO_EXT_LEN, output + idx); idx += 2; c16toa(HELLO_EXT_SIG_ALGO, output + idx); idx += 2; - c16toa(HELLO_EXT_SZ-6, output + idx); + c16toa(HELLO_EXT_SIGALGO_SZ, output + idx); idx += 2; - - c16toa(HELLO_EXT_SZ-8, output + idx); + /* This is a lazy list setup. Eventually, we'll need to support + * using other hash types or even other extensions. */ + c16toa(HELLO_EXT_SIGALGO_LEN, output + idx); idx += 2; output[idx++] = sha_mac; output[idx++] = rsa_sa_algo; diff --git a/src/keys.c b/src/keys.c index 846345af8..2c471b92b 100644 --- a/src/keys.c +++ b/src/keys.c @@ -323,7 +323,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_IMPLICIT_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; break; #endif @@ -340,7 +340,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_IMPLICIT_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; break; #endif @@ -357,7 +357,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_IMPLICIT_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; break; #endif @@ -374,7 +374,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_IMPLICIT_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; break; #endif @@ -391,7 +391,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_IMPLICIT_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; break; #endif @@ -408,7 +408,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_IMPLICIT_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; break; #endif @@ -425,7 +425,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_IMPLICIT_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; break; #endif @@ -442,7 +442,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_IMPLICIT_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; break; #endif @@ -794,7 +794,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_IMPLICIT_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; break; #endif @@ -811,7 +811,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_IMPLICIT_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; break; #endif @@ -828,7 +828,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_IMPLICIT_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; break; #endif @@ -845,7 +845,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_IMPLICIT_IV_SIZE; + ssl->specs.iv_size = AES_GCM_IMP_IV_SZ; break; #endif From cb178856a8996ab5685cdf093d057ef3bfbb1226 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 19 Jul 2012 14:44:08 -0700 Subject: [PATCH 21/24] added 64-bit (default), 32-bit version, and 8-bit table based AES-GCM for faster operation. Selection made at configure. --- configure.ac | 18 ++ ctaocrypt/benchmark/benchmark.c | 3 +- ctaocrypt/src/aes.c | 546 ++++++++++++++++++++++++++++---- ctaocrypt/test/test.c | 3 +- cyassl/ctaocrypt/aes.h | 9 + src/keys.c | 16 +- 6 files changed, 518 insertions(+), 77 deletions(-) diff --git a/configure.ac b/configure.ac index 670628241..7b36adfed 100644 --- a/configure.ac +++ b/configure.ac @@ -296,6 +296,24 @@ AC_ARG_ENABLE(aesgcm, [ ENABLED_AESGCM=no ] ) +if test "$ENABLED_AESGCM" = "word32" +then + AM_CFLAGS="$AM_CFLAGS -DGCM_WORD32" + ENABLED_AESGCM=yes +fi + +if test "$ENABLED_AESGCM" = "small" +then + AM_CFLAGS="$AM_CFLAGS -DGCM_SMALL" + ENABLED_AESGCM=yes +fi + +if test "$ENABLED_AESGCM" = "table" +then + AM_CFLAGS="$AM_CFLAGS -DGCM_TABLE" + ENABLED_AESGCM=yes +fi + if test "$ENABLED_AESGCM" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM -DCYASSL_SHA384 -DCYASSL_SHA512" diff --git a/ctaocrypt/benchmark/benchmark.c b/ctaocrypt/benchmark/benchmark.c index 379de527c..e7100ba95 100644 --- a/ctaocrypt/benchmark/benchmark.c +++ b/ctaocrypt/benchmark/benchmark.c @@ -186,7 +186,8 @@ void bench_aesgcm() double start, total, persec; int i; - AesSetKey(&enc, key, 16, iv, AES_ENCRYPTION); + AesGcmSetKey(&enc, key, 16); + AesSetIV(&enc, iv); start = current_time(); for(i = 0; i < megs; i++) diff --git a/ctaocrypt/src/aes.c b/ctaocrypt/src/aes.c index 91268a0fa..0385c0a7e 100644 --- a/ctaocrypt/src/aes.c +++ b/ctaocrypt/src/aes.c @@ -1428,52 +1428,7 @@ static INLINE void IncrementGcmCounter(byte* inOutCtr) } -static void RIGHTSHIFT(byte* x) -{ - int i; - int carryOut = 0; - int carryIn = 0; - - for (i = 0; i < AES_BLOCK_SIZE; i++) { - carryOut = x[i] & 0x01; - x[i] = (x[i] >> 1) | (carryIn ? 0x80 : 0); - carryIn = carryOut; - } -} - - -static void GMULT(byte* X, byte* Y) -{ - byte R[AES_BLOCK_SIZE]; - byte Z[AES_BLOCK_SIZE]; - byte V[AES_BLOCK_SIZE]; - int i, j; - - XMEMSET(R, 0, AES_BLOCK_SIZE); - R[0] = 0xE1; - XMEMSET(Z, 0, AES_BLOCK_SIZE); - XMEMCPY(V, X, AES_BLOCK_SIZE); - for (i = 0; i < AES_BLOCK_SIZE; i++) - { - byte y = Y[i]; - for (j = 0; j < 8; j++) - { - if (y & 0x80) { - xorbuf(Z, V, AES_BLOCK_SIZE); - } - - if (V[15] & 0x01) { - RIGHTSHIFT(V); - xorbuf(V, R, AES_BLOCK_SIZE); - } else { - RIGHTSHIFT(V); - } - y = y << 1; - } - } - XMEMCPY(X, Z, AES_BLOCK_SIZE); -} - +#if defined(GCM_SMALL) || defined(GCM_TABLE) static INLINE void FlattenSzInBits(byte* buf, word32 sz) { @@ -1493,12 +1448,98 @@ static INLINE void FlattenSzInBits(byte* buf, word32 sz) } -static void GHASH(byte* h, const byte* a, word32 aSz, +static INLINE void RIGHTSHIFTX(byte* x) +{ + int i; + int carryOut = 0; + int carryIn = 0; + int borrow = x[15] & 0x01; + + for (i = 0; i < AES_BLOCK_SIZE; i++) { + carryOut = x[i] & 0x01; + x[i] = (x[i] >> 1) | (carryIn ? 0x80 : 0); + carryIn = carryOut; + } + if (borrow) x[0] ^= 0xE1; +} + +#endif /* defined(GCM_SMALL) || defined(GCM_TABLE) */ + + +#ifdef GCM_TABLE + +static void GenerateM0(Aes* aes) +{ + int i, j; + byte (*m)[AES_BLOCK_SIZE] = aes->M0; + + XMEMCPY(m[128], aes->H, AES_BLOCK_SIZE); + + for (i = 64; i > 0; i /= 2) { + XMEMCPY(m[i], m[i*2], AES_BLOCK_SIZE); + RIGHTSHIFTX(m[i]); + } + + for (i = 2; i < 256; i *= 2) { + for (j = 1; j < i; j++) { + XMEMCPY(m[i+j], m[i], AES_BLOCK_SIZE); + xorbuf(m[i+j], m[j], AES_BLOCK_SIZE); + } + } + + XMEMSET(m[0], 0, AES_BLOCK_SIZE); +} + +#endif /* GCM_TABLE */ + + +void AesGcmSetKey(Aes* aes, const byte* key, word32 len) +{ + byte iv[AES_BLOCK_SIZE]; + + XMEMSET(iv, 0, AES_BLOCK_SIZE); + AesSetKey(aes, key, len, iv, AES_ENCRYPTION); + AesEncrypt(aes, iv, aes->H); +#ifdef GCM_TABLE + GenerateM0(aes); +#endif /* GCM_TABLE */ +} + + +#if defined(GCM_SMALL) + +static void GMULT(byte* X, byte* Y) +{ + byte Z[AES_BLOCK_SIZE]; + byte V[AES_BLOCK_SIZE]; + int i, j; + + XMEMSET(Z, 0, AES_BLOCK_SIZE); + XMEMCPY(V, X, AES_BLOCK_SIZE); + for (i = 0; i < AES_BLOCK_SIZE; i++) + { + byte y = Y[i]; + for (j = 0; j < 8; j++) + { + if (y & 0x80) { + xorbuf(Z, V, AES_BLOCK_SIZE); + } + + RIGHTSHIFTX(V); + y = y << 1; + } + } + XMEMCPY(X, Z, AES_BLOCK_SIZE); +} + + +static void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, word32 cSz, byte* s, word32 sSz) { byte x[AES_BLOCK_SIZE]; byte scratch[AES_BLOCK_SIZE]; word32 blocks, partial; + byte* h = aes->H; XMEMSET(x, 0, AES_BLOCK_SIZE); @@ -1546,6 +1587,395 @@ static void GHASH(byte* h, const byte* a, word32 aSz, XMEMCPY(s, x, sSz); } +/* end GCM_SMALL */ +#elif defined(GCM_TABLE) + +const static byte R[256][2] = { + {0x00, 0x00}, {0x01, 0xc2}, {0x03, 0x84}, {0x02, 0x46}, + {0x07, 0x08}, {0x06, 0xca}, {0x04, 0x8c}, {0x05, 0x4e}, + {0x0e, 0x10}, {0x0f, 0xd2}, {0x0d, 0x94}, {0x0c, 0x56}, + {0x09, 0x18}, {0x08, 0xda}, {0x0a, 0x9c}, {0x0b, 0x5e}, + {0x1c, 0x20}, {0x1d, 0xe2}, {0x1f, 0xa4}, {0x1e, 0x66}, + {0x1b, 0x28}, {0x1a, 0xea}, {0x18, 0xac}, {0x19, 0x6e}, + {0x12, 0x30}, {0x13, 0xf2}, {0x11, 0xb4}, {0x10, 0x76}, + {0x15, 0x38}, {0x14, 0xfa}, {0x16, 0xbc}, {0x17, 0x7e}, + {0x38, 0x40}, {0x39, 0x82}, {0x3b, 0xc4}, {0x3a, 0x06}, + {0x3f, 0x48}, {0x3e, 0x8a}, {0x3c, 0xcc}, {0x3d, 0x0e}, + {0x36, 0x50}, {0x37, 0x92}, {0x35, 0xd4}, {0x34, 0x16}, + {0x31, 0x58}, {0x30, 0x9a}, {0x32, 0xdc}, {0x33, 0x1e}, + {0x24, 0x60}, {0x25, 0xa2}, {0x27, 0xe4}, {0x26, 0x26}, + {0x23, 0x68}, {0x22, 0xaa}, {0x20, 0xec}, {0x21, 0x2e}, + {0x2a, 0x70}, {0x2b, 0xb2}, {0x29, 0xf4}, {0x28, 0x36}, + {0x2d, 0x78}, {0x2c, 0xba}, {0x2e, 0xfc}, {0x2f, 0x3e}, + {0x70, 0x80}, {0x71, 0x42}, {0x73, 0x04}, {0x72, 0xc6}, + {0x77, 0x88}, {0x76, 0x4a}, {0x74, 0x0c}, {0x75, 0xce}, + {0x7e, 0x90}, {0x7f, 0x52}, {0x7d, 0x14}, {0x7c, 0xd6}, + {0x79, 0x98}, {0x78, 0x5a}, {0x7a, 0x1c}, {0x7b, 0xde}, + {0x6c, 0xa0}, {0x6d, 0x62}, {0x6f, 0x24}, {0x6e, 0xe6}, + {0x6b, 0xa8}, {0x6a, 0x6a}, {0x68, 0x2c}, {0x69, 0xee}, + {0x62, 0xb0}, {0x63, 0x72}, {0x61, 0x34}, {0x60, 0xf6}, + {0x65, 0xb8}, {0x64, 0x7a}, {0x66, 0x3c}, {0x67, 0xfe}, + {0x48, 0xc0}, {0x49, 0x02}, {0x4b, 0x44}, {0x4a, 0x86}, + {0x4f, 0xc8}, {0x4e, 0x0a}, {0x4c, 0x4c}, {0x4d, 0x8e}, + {0x46, 0xd0}, {0x47, 0x12}, {0x45, 0x54}, {0x44, 0x96}, + {0x41, 0xd8}, {0x40, 0x1a}, {0x42, 0x5c}, {0x43, 0x9e}, + {0x54, 0xe0}, {0x55, 0x22}, {0x57, 0x64}, {0x56, 0xa6}, + {0x53, 0xe8}, {0x52, 0x2a}, {0x50, 0x6c}, {0x51, 0xae}, + {0x5a, 0xf0}, {0x5b, 0x32}, {0x59, 0x74}, {0x58, 0xb6}, + {0x5d, 0xf8}, {0x5c, 0x3a}, {0x5e, 0x7c}, {0x5f, 0xbe}, + {0xe1, 0x00}, {0xe0, 0xc2}, {0xe2, 0x84}, {0xe3, 0x46}, + {0xe6, 0x08}, {0xe7, 0xca}, {0xe5, 0x8c}, {0xe4, 0x4e}, + {0xef, 0x10}, {0xee, 0xd2}, {0xec, 0x94}, {0xed, 0x56}, + {0xe8, 0x18}, {0xe9, 0xda}, {0xeb, 0x9c}, {0xea, 0x5e}, + {0xfd, 0x20}, {0xfc, 0xe2}, {0xfe, 0xa4}, {0xff, 0x66}, + {0xfa, 0x28}, {0xfb, 0xea}, {0xf9, 0xac}, {0xf8, 0x6e}, + {0xf3, 0x30}, {0xf2, 0xf2}, {0xf0, 0xb4}, {0xf1, 0x76}, + {0xf4, 0x38}, {0xf5, 0xfa}, {0xf7, 0xbc}, {0xf6, 0x7e}, + {0xd9, 0x40}, {0xd8, 0x82}, {0xda, 0xc4}, {0xdb, 0x06}, + {0xde, 0x48}, {0xdf, 0x8a}, {0xdd, 0xcc}, {0xdc, 0x0e}, + {0xd7, 0x50}, {0xd6, 0x92}, {0xd4, 0xd4}, {0xd5, 0x16}, + {0xd0, 0x58}, {0xd1, 0x9a}, {0xd3, 0xdc}, {0xd2, 0x1e}, + {0xc5, 0x60}, {0xc4, 0xa2}, {0xc6, 0xe4}, {0xc7, 0x26}, + {0xc2, 0x68}, {0xc3, 0xaa}, {0xc1, 0xec}, {0xc0, 0x2e}, + {0xcb, 0x70}, {0xca, 0xb2}, {0xc8, 0xf4}, {0xc9, 0x36}, + {0xcc, 0x78}, {0xcd, 0xba}, {0xcf, 0xfc}, {0xce, 0x3e}, + {0x91, 0x80}, {0x90, 0x42}, {0x92, 0x04}, {0x93, 0xc6}, + {0x96, 0x88}, {0x97, 0x4a}, {0x95, 0x0c}, {0x94, 0xce}, + {0x9f, 0x90}, {0x9e, 0x52}, {0x9c, 0x14}, {0x9d, 0xd6}, + {0x98, 0x98}, {0x99, 0x5a}, {0x9b, 0x1c}, {0x9a, 0xde}, + {0x8d, 0xa0}, {0x8c, 0x62}, {0x8e, 0x24}, {0x8f, 0xe6}, + {0x8a, 0xa8}, {0x8b, 0x6a}, {0x89, 0x2c}, {0x88, 0xee}, + {0x83, 0xb0}, {0x82, 0x72}, {0x80, 0x34}, {0x81, 0xf6}, + {0x84, 0xb8}, {0x85, 0x7a}, {0x87, 0x3c}, {0x86, 0xfe}, + {0xa9, 0xc0}, {0xa8, 0x02}, {0xaa, 0x44}, {0xab, 0x86}, + {0xae, 0xc8}, {0xaf, 0x0a}, {0xad, 0x4c}, {0xac, 0x8e}, + {0xa7, 0xd0}, {0xa6, 0x12}, {0xa4, 0x54}, {0xa5, 0x96}, + {0xa0, 0xd8}, {0xa1, 0x1a}, {0xa3, 0x5c}, {0xa2, 0x9e}, + {0xb5, 0xe0}, {0xb4, 0x22}, {0xb6, 0x64}, {0xb7, 0xa6}, + {0xb2, 0xe8}, {0xb3, 0x2a}, {0xb1, 0x6c}, {0xb0, 0xae}, + {0xbb, 0xf0}, {0xba, 0x32}, {0xb8, 0x74}, {0xb9, 0xb6}, + {0xbc, 0xf8}, {0xbd, 0x3a}, {0xbf, 0x7c}, {0xbe, 0xbe} }; + + +static void GMULT(byte *x, byte m[256][AES_BLOCK_SIZE]) +{ + int i, j; + byte Z[AES_BLOCK_SIZE]; + byte a; + + XMEMSET(Z, 0, sizeof(Z)); + + for (i = 15; i > 0; i--) { + xorbuf(Z, m[x[i]], AES_BLOCK_SIZE); + a = Z[15]; + + for (j = 15; j > 0; j--) { + Z[j] = Z[j-1]; + } + + Z[0] = R[a][0]; + Z[1] ^= R[a][1]; + } + xorbuf(Z, m[x[0]], AES_BLOCK_SIZE); + + XMEMCPY(x, Z, AES_BLOCK_SIZE); +} + + +static void GHASH(Aes* aes, const byte* a, word32 aSz, + const byte* c, word32 cSz, byte* s, word32 sSz) +{ + byte x[AES_BLOCK_SIZE]; + byte scratch[AES_BLOCK_SIZE]; + word32 blocks, partial; + + XMEMSET(x, 0, AES_BLOCK_SIZE); + + /* Hash in A, the Additional Authentication Data */ + if (aSz != 0 && a != NULL) { + blocks = aSz / AES_BLOCK_SIZE; + partial = aSz % AES_BLOCK_SIZE; + while (blocks--) { + xorbuf(x, a, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + a += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, a, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + } + } + + /* Hash in C, the Ciphertext */ + if (cSz != 0 && c != NULL) { + blocks = cSz / AES_BLOCK_SIZE; + partial = cSz % AES_BLOCK_SIZE; + while (blocks--) { + xorbuf(x, c, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + c += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, c, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + } + } + + /* Hash in the lengths of A and C in bits */ + FlattenSzInBits(&scratch[0], aSz); + FlattenSzInBits(&scratch[8], cSz); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + + /* Copy the result into s. */ + XMEMCPY(s, x, sSz); +} + +/* end GCM_TABLE */ +#elif defined(WORD64_AVAILABLE) && !defined(GCM_WORD32) + +static void GMULT(word64* X, word64* Y) +{ + word64 Z[2] = {0,0}; + word64 V[2] = {X[0], X[1]}; + int i, j; + + for (i = 0; i < 2; i++) + { + word64 y = Y[i]; + for (j = 0; j < 64; j++) + { + if (y & 0x8000000000000000) { + Z[0] ^= V[0]; + Z[1] ^= V[1]; + } + + if (V[1] & 0x0000000000000001) { + V[1] >>= 1; + V[1] |= ((V[0] & 0x0000000000000001) ? 0x8000000000000000 : 0); + V[0] >>= 1; + V[0] ^= 0xE100000000000000; + } + else { + V[1] >>= 1; + V[1] |= ((V[0] & 0x0000000000000001) ? 0x8000000000000000 : 0); + V[0] >>= 1; + } + y <<= 1; + } + } + X[0] = Z[0]; + X[1] = Z[1]; +} + + +static void GHASH(Aes* aes, const byte* a, word32 aSz, + const byte* c, word32 cSz, byte* s, word32 sSz) +{ + word64 x[2] = {0,0}; + word32 blocks, partial; + word64 bigH[2]; + byte scratch[AES_BLOCK_SIZE]; + + ByteReverseWords64(bigH, (word64*)aes->H, AES_BLOCK_SIZE); + + /* Hash in A, the Additional Authentication Data */ + if (aSz != 0 && a != NULL) { + word64 bigA[2]; + blocks = aSz / AES_BLOCK_SIZE; + partial = aSz % AES_BLOCK_SIZE; + while (blocks--) { + ByteReverseWords64(bigA, (const word64*)a, AES_BLOCK_SIZE); + x[0] ^= bigA[0]; + x[1] ^= bigA[1]; + GMULT(x, bigH); + a += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, a, partial); + ByteReverseWords64(bigA, (const word64*)scratch, AES_BLOCK_SIZE); + x[0] ^= bigA[0]; + x[1] ^= bigA[1]; + GMULT(x, bigH); + } + } + + /* Hash in C, the Ciphertext */ + if (cSz != 0 && c != NULL) { + word64 bigC[2]; + blocks = cSz / AES_BLOCK_SIZE; + partial = cSz % AES_BLOCK_SIZE; + while (blocks--) { + ByteReverseWords64(bigC, (const word64*)c, AES_BLOCK_SIZE); + x[0] ^= bigC[0]; + x[1] ^= bigC[1]; + GMULT(x, bigH); + c += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, c, partial); + ByteReverseWords64(bigC, (const word64*)scratch, AES_BLOCK_SIZE); + x[0] ^= bigC[0]; + x[1] ^= bigC[1]; + GMULT(x, bigH); + } + } + + /* Hash in the lengths in bits of A and C */ + { + word64 len[2] = {aSz, cSz}; + + /* Lengths are in bytes. Convert to bits. */ + len[0] *= 8; + len[1] *= 8; + + x[0] ^= len[0]; + x[1] ^= len[1]; + GMULT(x, bigH); + } + ByteReverseWords64((word64*)scratch, (const word64*)x, AES_BLOCK_SIZE); + XMEMCPY(s, scratch, sSz); +} + +/* end defined(WORD64_AVAILABLE) && !defined(GCM_WORD32) */ +#else /* GCM_WORD32 */ + +static void GMULT(word32* X, word32* Y) +{ + word32 Z[4] = {0,0,0,0}; + word32 V[4] = {X[0], X[1], X[2], X[3]}; + int i, j; + + for (i = 0; i < 4; i++) + { + word32 y = Y[i]; + for (j = 0; j < 32; j++) + { + if (y & 0x80000000) { + Z[0] ^= V[0]; + Z[1] ^= V[1]; + Z[2] ^= V[2]; + Z[3] ^= V[3]; + } + + if (V[3] & 0x00000001) { + V[3] >>= 1; + V[3] |= ((V[2] & 0x00000001) ? 0x80000000 : 0); + V[2] >>= 1; + V[2] |= ((V[1] & 0x00000001) ? 0x80000000 : 0); + V[1] >>= 1; + V[1] |= ((V[0] & 0x00000001) ? 0x80000000 : 0); + V[0] >>= 1; + V[0] ^= 0xE1000000; + } else { + V[3] >>= 1; + V[3] |= ((V[2] & 0x00000001) ? 0x80000000 : 0); + V[2] >>= 1; + V[2] |= ((V[1] & 0x00000001) ? 0x80000000 : 0); + V[1] >>= 1; + V[1] |= ((V[0] & 0x00000001) ? 0x80000000 : 0); + V[0] >>= 1; + } + y <<= 1; + } + } + X[0] = Z[0]; + X[1] = Z[1]; + X[2] = Z[2]; + X[3] = Z[3]; +} + + +static void GHASH(Aes* aes, const byte* a, word32 aSz, + const byte* c, word32 cSz, byte* s, word32 sSz) +{ + word32 x[4] = {0,0,0,0}; + word32 blocks, partial; + word32 bigH[4]; + byte scratch[AES_BLOCK_SIZE]; + + ByteReverseWords(bigH, (word32*)aes->H, AES_BLOCK_SIZE); + + /* Hash in A, the Additional Authentication Data */ + if (aSz != 0 && a != NULL) { + word32 bigA[4]; + blocks = aSz / AES_BLOCK_SIZE; + partial = aSz % AES_BLOCK_SIZE; + while (blocks--) { + ByteReverseWords(bigA, (const word32*)a, AES_BLOCK_SIZE); + x[0] ^= bigA[0]; + x[1] ^= bigA[1]; + x[2] ^= bigA[2]; + x[3] ^= bigA[3]; + GMULT(x, bigH); + a += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, a, partial); + ByteReverseWords(bigA, (const word32*)scratch, AES_BLOCK_SIZE); + x[0] ^= bigA[0]; + x[1] ^= bigA[1]; + x[2] ^= bigA[2]; + x[3] ^= bigA[3]; + GMULT(x, bigH); + } + } + + /* Hash in C, the Ciphertext */ + if (cSz != 0 && c != NULL) { + word32 bigC[4]; + blocks = cSz / AES_BLOCK_SIZE; + partial = cSz % AES_BLOCK_SIZE; + while (blocks--) { + ByteReverseWords(bigC, (const word32*)c, AES_BLOCK_SIZE); + x[0] ^= bigC[0]; + x[1] ^= bigC[1]; + x[2] ^= bigC[2]; + x[3] ^= bigC[3]; + GMULT(x, bigH); + c += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, c, partial); + ByteReverseWords(bigC, (const word32*)scratch, AES_BLOCK_SIZE); + x[0] ^= bigC[0]; + x[1] ^= bigC[1]; + x[2] ^= bigC[2]; + x[3] ^= bigC[3]; + GMULT(x, bigH); + } + } + + /* Hash in the lengths in bits of A and C */ + { + word32 len[4]; + + /* Lengths are in bytes. Convert to bits. */ + len[0] = (aSz >> (8*sizeof(aSz) - 3)); + len[1] = aSz << 3; + len[2] = (cSz >> (8*sizeof(cSz) - 3)); + len[3] = cSz << 3; + + x[0] ^= len[0]; + x[1] ^= len[1]; + x[2] ^= len[2]; + x[3] ^= len[3]; + GMULT(x, bigH); + } + ByteReverseWords((word32*)scratch, (const word32*)x, AES_BLOCK_SIZE); + XMEMCPY(s, scratch, sSz); +} + +#endif /* end GCM_WORD32 */ + void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte* authTag, word32 authTagSz, @@ -1555,19 +1985,14 @@ void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, word32 partial = sz % AES_BLOCK_SIZE; const byte* p = in; byte* c = out; - byte h[AES_BLOCK_SIZE]; byte ctr[AES_BLOCK_SIZE]; byte scratch[AES_BLOCK_SIZE]; CYASSL_ENTER("AesGcmEncrypt"); - /* Set up the H block by encrypting an array of zeroes with the key. */ - XMEMSET(ctr, 0, AES_BLOCK_SIZE); - AesEncrypt(aes, ctr, h); - /* Initialize the counter with the MS 96 bits of IV, and the counter * portion set to "1". */ - XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE - 4); + XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE); InitGcmCounter(ctr); while (blocks--) { @@ -1585,10 +2010,10 @@ void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, xorbuf(scratch, p, partial); XMEMCPY(c, scratch, partial); } - GHASH(h, authIn, authInSz, out, sz, authTag, authTagSz); + GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz); InitGcmCounter(ctr); - AesEncrypt(aes, ctr, h); - xorbuf(authTag, h, authTagSz); + AesEncrypt(aes, ctr, scratch); + xorbuf(authTag, scratch, authTagSz); } @@ -1600,19 +2025,14 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, word32 partial = sz % AES_BLOCK_SIZE; const byte* c = in; byte* p = out; - byte h[AES_BLOCK_SIZE]; byte ctr[AES_BLOCK_SIZE]; byte scratch[AES_BLOCK_SIZE]; CYASSL_ENTER("AesGcmDecrypt"); - /* Set up the H block by encrypting an array of zeroes with the key. */ - XMEMSET(ctr, 0, AES_BLOCK_SIZE); - AesEncrypt(aes, ctr, h); - /* Initialize the counter with the MS 96 bits of IV, and the counter * portion set to "1". */ - XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE - 4); + XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE); InitGcmCounter(ctr); /* Calculate the authTag again using the received auth data and the @@ -1621,7 +2041,7 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte Tprime[AES_BLOCK_SIZE]; byte EKY0[AES_BLOCK_SIZE]; - GHASH(h, authIn, authInSz, in, sz, Tprime, sizeof(Tprime)); + GHASH(aes, authIn, authInSz, in, sz, Tprime, sizeof(Tprime)); AesEncrypt(aes, ctr, EKY0); xorbuf(Tprime, EKY0, sizeof(Tprime)); if (XMEMCMP(authTag, Tprime, authTagSz) != 0) { diff --git a/ctaocrypt/test/test.c b/ctaocrypt/test/test.c index a3498abe9..8dcb5cd4b 100644 --- a/ctaocrypt/test/test.c +++ b/ctaocrypt/test/test.c @@ -1226,7 +1226,8 @@ int aesgcm_test() memset(c2, 0, 60); memset(p2, 0, 60); - AesSetKey(&enc, k, sizeof(k), iv, AES_ENCRYPTION); + AesGcmSetKey(&enc, k, sizeof(k)); + AesSetIV(&enc, iv); /* AES-GCM encrypt and decrypt both use AES encrypt internally */ AesGcmEncrypt(&enc, c2, p, sizeof(c2), t2, sizeof(t2), a, sizeof(a)); if (memcmp(c, c2, sizeof(c2))) diff --git a/cyassl/ctaocrypt/aes.h b/cyassl/ctaocrypt/aes.h index 73e84b499..86875d4f1 100644 --- a/cyassl/ctaocrypt/aes.h +++ b/cyassl/ctaocrypt/aes.h @@ -68,6 +68,14 @@ typedef struct Aes { ALIGN16 word32 reg[AES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ ALIGN16 word32 tmp[AES_BLOCK_SIZE / sizeof(word32)]; /* same */ + +#ifdef HAVE_AESGCM + ALIGN16 byte H[AES_BLOCK_SIZE]; +#ifdef GCM_TABLE + /* key-based fast multiplication table. */ + ALIGN16 byte M0[256][AES_BLOCK_SIZE]; +#endif /* GCM_TABLE */ +#endif /* HAVE_AESGCM */ } Aes; @@ -81,6 +89,7 @@ CYASSL_API void AesEncryptDirect(Aes* aes, byte* out, const byte* in); CYASSL_API void AesDecryptDirect(Aes* aes, byte* out, const byte* in); #ifdef HAVE_AESGCM +CYASSL_API void AesGcmSetKey(Aes* aes, const byte* key, word32 len); CYASSL_API void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz); diff --git a/src/keys.c b/src/keys.c index 2c471b92b..d6ef0c6e6 100644 --- a/src/keys.c +++ b/src/keys.c @@ -1009,20 +1009,12 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, #ifdef BUILD_AESGCM if (specs->bulk_cipher_algorithm == aes_gcm) { if (side == CLIENT_END) { - AesSetKey(&enc->aes, keys->client_write_key, - specs->key_size, keys->client_write_IV, - AES_ENCRYPTION); - AesSetKey(&dec->aes, keys->server_write_key, - specs->key_size, keys->server_write_IV, - AES_ENCRYPTION); + AesGcmSetKey(&enc->aes, keys->client_write_key, specs->key_size); + AesGcmSetKey(&dec->aes, keys->server_write_key, specs->key_size); } else { - AesSetKey(&enc->aes, keys->server_write_key, - specs->key_size, keys->server_write_IV, - AES_ENCRYPTION); - AesSetKey(&dec->aes, keys->client_write_key, - specs->key_size, keys->client_write_IV, - AES_ENCRYPTION); + AesGcmSetKey(&enc->aes, keys->server_write_key, specs->key_size); + AesGcmSetKey(&dec->aes, keys->client_write_key, specs->key_size); } } #endif From 07ca2bce561c752eafc5debc4b9cef5d2cd221f2 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 19 Jul 2012 17:19:39 -0700 Subject: [PATCH 22/24] added endinanness protection to AES-GCM --- ctaocrypt/src/aes.c | 78 ++++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/ctaocrypt/src/aes.c b/ctaocrypt/src/aes.c index 0385c0a7e..15e486b03 100644 --- a/ctaocrypt/src/aes.c +++ b/ctaocrypt/src/aes.c @@ -1590,7 +1590,7 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, /* end GCM_SMALL */ #elif defined(GCM_TABLE) -const static byte R[256][2] = { +static const byte R[256][2] = { {0x00, 0x00}, {0x01, 0xc2}, {0x03, 0x84}, {0x02, 0x46}, {0x07, 0x08}, {0x06, 0xca}, {0x04, 0x8c}, {0x05, 0x4e}, {0x0e, 0x10}, {0x0f, 0xd2}, {0x0d, 0x94}, {0x0c, 0x56}, @@ -1779,9 +1779,11 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, word64 x[2] = {0,0}; word32 blocks, partial; word64 bigH[2]; - byte scratch[AES_BLOCK_SIZE]; - ByteReverseWords64(bigH, (word64*)aes->H, AES_BLOCK_SIZE); + XMEMCPY(bigH, aes->H, AES_BLOCK_SIZE); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(bigH, bigH, AES_BLOCK_SIZE); + #endif /* Hash in A, the Additional Authentication Data */ if (aSz != 0 && a != NULL) { @@ -1789,16 +1791,21 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, blocks = aSz / AES_BLOCK_SIZE; partial = aSz % AES_BLOCK_SIZE; while (blocks--) { - ByteReverseWords64(bigA, (const word64*)a, AES_BLOCK_SIZE); + XMEMCPY(bigA, a, AES_BLOCK_SIZE); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(bigA, bigA, AES_BLOCK_SIZE); + #endif x[0] ^= bigA[0]; x[1] ^= bigA[1]; GMULT(x, bigH); a += AES_BLOCK_SIZE; } if (partial != 0) { - XMEMSET(scratch, 0, AES_BLOCK_SIZE); - XMEMCPY(scratch, a, partial); - ByteReverseWords64(bigA, (const word64*)scratch, AES_BLOCK_SIZE); + XMEMSET(bigA, 0, AES_BLOCK_SIZE); + XMEMCPY(bigA, a, partial); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(bigA, bigA, AES_BLOCK_SIZE); + #endif x[0] ^= bigA[0]; x[1] ^= bigA[1]; GMULT(x, bigH); @@ -1811,16 +1818,21 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, blocks = cSz / AES_BLOCK_SIZE; partial = cSz % AES_BLOCK_SIZE; while (blocks--) { - ByteReverseWords64(bigC, (const word64*)c, AES_BLOCK_SIZE); + XMEMCPY(bigC, c, AES_BLOCK_SIZE); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(bigC, bigC, AES_BLOCK_SIZE); + #endif x[0] ^= bigC[0]; x[1] ^= bigC[1]; GMULT(x, bigH); c += AES_BLOCK_SIZE; } if (partial != 0) { - XMEMSET(scratch, 0, AES_BLOCK_SIZE); - XMEMCPY(scratch, c, partial); - ByteReverseWords64(bigC, (const word64*)scratch, AES_BLOCK_SIZE); + XMEMSET(bigC, 0, AES_BLOCK_SIZE); + XMEMCPY(bigC, c, partial); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(bigC, bigC, AES_BLOCK_SIZE); + #endif x[0] ^= bigC[0]; x[1] ^= bigC[1]; GMULT(x, bigH); @@ -1839,8 +1851,10 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, x[1] ^= len[1]; GMULT(x, bigH); } - ByteReverseWords64((word64*)scratch, (const word64*)x, AES_BLOCK_SIZE); - XMEMCPY(s, scratch, sSz); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(x, x, AES_BLOCK_SIZE); + #endif + XMEMCPY(s, x, sSz); } /* end defined(WORD64_AVAILABLE) && !defined(GCM_WORD32) */ @@ -1898,9 +1912,11 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, word32 x[4] = {0,0,0,0}; word32 blocks, partial; word32 bigH[4]; - byte scratch[AES_BLOCK_SIZE]; - ByteReverseWords(bigH, (word32*)aes->H, AES_BLOCK_SIZE); + XMEMCPY(bigH, aes->H, AES_BLOCK_SIZE); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(bigH, bigH, AES_BLOCK_SIZE); + #endif /* Hash in A, the Additional Authentication Data */ if (aSz != 0 && a != NULL) { @@ -1908,7 +1924,10 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, blocks = aSz / AES_BLOCK_SIZE; partial = aSz % AES_BLOCK_SIZE; while (blocks--) { - ByteReverseWords(bigA, (const word32*)a, AES_BLOCK_SIZE); + XMEMCPY(bigA, a, AES_BLOCK_SIZE); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(bigA, bigA, AES_BLOCK_SIZE); + #endif x[0] ^= bigA[0]; x[1] ^= bigA[1]; x[2] ^= bigA[2]; @@ -1917,9 +1936,11 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, a += AES_BLOCK_SIZE; } if (partial != 0) { - XMEMSET(scratch, 0, AES_BLOCK_SIZE); - XMEMCPY(scratch, a, partial); - ByteReverseWords(bigA, (const word32*)scratch, AES_BLOCK_SIZE); + XMEMSET(bigA, 0, AES_BLOCK_SIZE); + XMEMCPY(bigA, a, partial); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(bigA, bigA, AES_BLOCK_SIZE); + #endif x[0] ^= bigA[0]; x[1] ^= bigA[1]; x[2] ^= bigA[2]; @@ -1934,7 +1955,10 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, blocks = cSz / AES_BLOCK_SIZE; partial = cSz % AES_BLOCK_SIZE; while (blocks--) { - ByteReverseWords(bigC, (const word32*)c, AES_BLOCK_SIZE); + XMEMCPY(bigC, c, AES_BLOCK_SIZE); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(bigC, bigC, AES_BLOCK_SIZE); + #endif x[0] ^= bigC[0]; x[1] ^= bigC[1]; x[2] ^= bigC[2]; @@ -1943,9 +1967,11 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, c += AES_BLOCK_SIZE; } if (partial != 0) { - XMEMSET(scratch, 0, AES_BLOCK_SIZE); - XMEMCPY(scratch, c, partial); - ByteReverseWords(bigC, (const word32*)scratch, AES_BLOCK_SIZE); + XMEMSET(bigC, 0, AES_BLOCK_SIZE); + XMEMCPY(bigC, c, partial); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(bigC, bigC, AES_BLOCK_SIZE); + #endif x[0] ^= bigC[0]; x[1] ^= bigC[1]; x[2] ^= bigC[2]; @@ -1970,8 +1996,10 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, x[3] ^= len[3]; GMULT(x, bigH); } - ByteReverseWords((word32*)scratch, (const word32*)x, AES_BLOCK_SIZE); - XMEMCPY(s, scratch, sSz); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(x, x, AES_BLOCK_SIZE); + #endif + XMEMCPY(s, x, sSz); } #endif /* end GCM_WORD32 */ From aa164e5266c3d167de87ff9a43b3607c2ccbb666 Mon Sep 17 00:00:00 2001 From: toddouska Date: Mon, 23 Jul 2012 13:47:30 -0700 Subject: [PATCH 23/24] make compression more standard, no size prefix, default zlib comp, check verify before overwrite w/ decomp... still needs FIN and ALERT processing --- src/internal.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/src/internal.c b/src/internal.c index 9b25d09b8..00f6e3093 100644 --- a/src/internal.c +++ b/src/internal.c @@ -239,7 +239,8 @@ static INLINE void ato32(const byte* c, word32* u32) ssl->c_stream.zfree = (free_func)myFree; ssl->c_stream.opaque = (voidpf)ssl->heap; - if (deflateInit(&ssl->c_stream, 8) != Z_OK) return ZLIB_INIT_ERROR; + if (deflateInit(&ssl->c_stream, Z_DEFAULT_COMPRESSION) != Z_OK) + return ZLIB_INIT_ERROR; ssl->didStreamInit = 1; @@ -268,11 +269,6 @@ static INLINE void ato32(const byte* c, word32* u32) int err; int currTotal = ssl->c_stream.total_out; - /* put size in front of compression */ - c16toa((word16)inSz, out); - out += 2; - outSz -= 2; - ssl->c_stream.next_in = in; ssl->c_stream.avail_in = inSz; ssl->c_stream.next_out = out; @@ -281,7 +277,7 @@ static INLINE void ato32(const byte* c, word32* u32) err = deflate(&ssl->c_stream, Z_SYNC_FLUSH); if (err != Z_OK && err != Z_STREAM_END) return ZLIB_COMPRESS_ERROR; - return ssl->c_stream.total_out - currTotal + sizeof(word16); + return ssl->c_stream.total_out - currTotal; } @@ -290,12 +286,6 @@ static INLINE void ato32(const byte* c, word32* u32) { int err; int currTotal = ssl->d_stream.total_out; - word16 len; - - /* find size in front of compression */ - ato16(in, &len); - in += 2; - inSz -= 2; ssl->d_stream.next_in = in; ssl->d_stream.avail_in = inSz; @@ -2244,11 +2234,6 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx) if (padByte) idx++; -#ifdef HAVE_LIBZ - if (ssl->options.usingCompression) - XMEMMOVE(rawData, decomp, dataSz); -#endif - /* verify */ if (dataSz) { if (XMEMCMP(mac, verify, digestSz)) { @@ -2259,6 +2244,12 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx) else GetSEQIncrement(ssl, 1); /* even though no data, increment verify */ +#ifdef HAVE_LIBZ + /* decompress could be bigger, overwrite after verify */ + if (ssl->options.usingCompression) + XMEMMOVE(rawData, decomp, dataSz); +#endif + *inOutIdx = idx; return 0; } From cf7e8baa1986fae6a401e7ac762314a385664bb4 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 23 Jul 2012 15:15:40 -0700 Subject: [PATCH 24/24] moved aes-gcm cipher suites around in the list to follow the existing suites --- src/internal.c | 168 ++++++++++++++++++++++++------------------------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/src/internal.c b/src/internal.c index c959118ce..17543310b 100644 --- a/src/internal.c +++ b/src/internal.c @@ -470,90 +470,6 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, tls = 1; #endif -#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 - if (tls1_2 && haveRSA) { - suites->suites[idx++] = 0; - suites->suites[idx++] = TLS_RSA_WITH_AES_128_GCM_SHA256; - } -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 - if (tls1_2 && haveRSA) { - suites->suites[idx++] = 0; - suites->suites[idx++] = TLS_RSA_WITH_AES_256_GCM_SHA384; - } -#endif - -#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 - if (tls1_2 && haveDH && haveRSA) { - suites->suites[idx++] = 0; - suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_GCM_SHA256; - } -#endif - -#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - if (tls1_2 && haveDH && haveRSA) { - suites->suites[idx++] = 0; - suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_GCM_SHA384; - } -#endif - -#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - if (tls1_2 && haveRSA) { - suites->suites[idx++] = ECC_BYTE; - suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256; - } -#endif - -#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - if (tls1_2 && haveRSA) { - suites->suites[idx++] = ECC_BYTE; - suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384; - } -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - if (tls1_2 && haveECDSA) { - suites->suites[idx++] = ECC_BYTE; - suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; - } -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - if (tls1_2 && haveECDSA) { - suites->suites[idx++] = ECC_BYTE; - suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384; - } -#endif - -#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - if (tls1_2 && haveRSA && haveStaticECC) { - suites->suites[idx++] = ECC_BYTE; - suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256; - } -#endif - -#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - if (tls1_2 && haveRSA && haveStaticECC) { - suites->suites[idx++] = ECC_BYTE; - suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384; - } -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 - if (tls1_2 && haveECDSA && haveStaticECC) { - suites->suites[idx++] = ECC_BYTE; - suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256; - } -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 - if (tls1_2 && haveECDSA && haveStaticECC) { - suites->suites[idx++] = ECC_BYTE; - suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384; - } -#endif - #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA if (tls && haveNTRU && haveRSA) { suites->suites[idx++] = 0; @@ -582,6 +498,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveECDSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384; + } +#endif + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA if (tls && haveECDSA) { suites->suites[idx++] = ECC_BYTE; @@ -589,6 +512,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveECDSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384; + } +#endif + #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA if (tls && haveECDSA && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; @@ -596,6 +526,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveECDSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; + } +#endif + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA if (tls && haveECDSA) { suites->suites[idx++] = ECC_BYTE; @@ -603,6 +540,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveECDSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256; + } +#endif + #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA if (tls && haveECDSA && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; @@ -638,6 +582,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384; + } +#endif + #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA if (tls && haveRSA) { suites->suites[idx++] = ECC_BYTE; @@ -645,6 +596,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveRSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384; + } +#endif + #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA if (tls && haveRSA && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; @@ -652,6 +610,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256; + } +#endif + #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA if (tls && haveRSA) { suites->suites[idx++] = ECC_BYTE; @@ -659,6 +624,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveRSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256; + } +#endif + #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA if (tls && haveRSA && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; @@ -694,6 +666,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveDH && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_GCM_SHA384; + } +#endif + #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 if (tls1_2 && haveDH && haveRSA) { suites->suites[idx++] = 0; @@ -701,6 +680,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveDH && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_GCM_SHA256; + } +#endif + #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 if (tls1_2 && haveDH && haveRSA) { suites->suites[idx++] = 0; @@ -722,6 +708,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_RSA_WITH_AES_256_GCM_SHA384; + } +#endif + #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 if (tls1_2 && haveRSA) { suites->suites[idx++] = 0; @@ -729,6 +722,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_RSA_WITH_AES_128_GCM_SHA256; + } +#endif + #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 if (tls1_2 && haveRSA) { suites->suites[idx++] = 0;