3131/** Maximum AES key size. */
3232#define MAX_AES_KEY_SIZE AES_256_KEY_SIZE
3333/** Maximum authentication data. */
34- #define MAX_AUTH_DATA 1024
34+ #define MAX_AUTH_DATA 4096
3535/** Maximum plaintext to encrypt for GCM */
3636#define MAX_AES_GCM_PLAINTEXT ((1ULL << 36) - 32)
3737/** Maximum RSA-PSS signature size */
@@ -82,10 +82,14 @@ struct wolfssl_cipher_ctx {
8282 size_t iv_size ;
8383
8484 /* For GCM mode. */
85- /** Authentication data to use. */
86- unsigned char auth_data [MAX_AUTH_DATA ];
87- /** Size of authentication data to use. */
85+ /** Authentication data to use (static, maximum 4096 bytes). */
86+ unsigned char auth_data_static [MAX_AUTH_DATA ];
87+ /** Authentication data to use (allocated dynamically). */
88+ unsigned char * auth_data_heap ;
89+ /** Size of authentication data to use (static). */
8890 size_t auth_data_size ;
91+ /** Size of authentication data to use (heap). */
92+ size_t auth_alloc ;
8993 /** Calculated authentication tag. */
9094 unsigned char tag [GCM_TAG_SIZE ];
9195 /** Size of calculated authentication tag. */
@@ -240,6 +244,7 @@ int wolfssl_cipher_init(gnutls_cipher_algorithm_t algorithm, void **_ctx,
240244 ctx -> tag_set_ext = 0 ;
241245 ctx -> algorithm = 0 ;
242246 ctx -> data_size = 0 ;
247+ ctx -> auth_data_heap = NULL ;
243248
244249 ctx -> algorithm = algorithm ;
245250 ctx -> mode = get_cipher_mode (algorithm );
@@ -671,12 +676,47 @@ int wolfssl_cipher_auth(void *_ctx, const void *auth_data,
671676 return GNUTLS_E_INVALID_REQUEST ;
672677 }
673678
674- /* Check authentication data will fit in cache. */
675- if (ctx -> auth_data_size + auth_size > sizeof (ctx -> auth_data )) {
676- WGW_ERROR ("Auth data too big: %ld + %ld > %ld" , ctx -> auth_data_size ,
677- auth_size , sizeof (ctx -> auth_data ));
678- return GNUTLS_E_SHORT_MEMORY_BUFFER ;
679- }
679+ /* Check authentication data will fit in the static cache,
680+ * switch to heap if it doesn't. */
681+ if (ctx -> auth_data_heap == NULL &&
682+ ctx -> auth_data_size + auth_size > sizeof (ctx -> auth_data_static )) {
683+ WGW_LOG ("Auth data too big: %ld + %ld > %ld" , ctx -> auth_data_size ,
684+ auth_size , sizeof (ctx -> auth_data_static ));
685+ WGW_LOG ("Switching to dynamic allocation" );
686+
687+ size_t new_sz = sizeof (ctx -> auth_data_static );
688+ while (new_sz < ctx -> auth_data_size + auth_size )
689+ new_sz *= 2 ;
690+
691+ ctx -> auth_data_heap = gnutls_malloc (new_sz );
692+ if (!ctx -> auth_data_heap ) {
693+ WGW_ERROR ("gnutls_malloc failed for auth_data_heap" );
694+ return GNUTLS_E_MEMORY_ERROR ;
695+ }
696+ ctx -> auth_alloc = new_sz ;
697+ XMEMCPY (ctx -> auth_data_heap , ctx -> auth_data_static ,
698+ ctx -> auth_data_size );
699+ WGW_LOG ("Spilled AAD to heap (%zu bytes)" , new_sz );
700+ }
701+
702+ /* We are already storing in the heap, we check
703+ * if we need to grow it. */
704+ if (ctx -> auth_data_heap &&
705+ ctx -> auth_data_size + auth_size > ctx -> auth_alloc ) {
706+ WGW_LOG ("New auth data too big, reallocating" );
707+ size_t new_sz = ctx -> auth_alloc ;
708+ while (new_sz < ctx -> auth_data_size + auth_size )
709+ new_sz *= 2 ;
710+
711+ unsigned char * p = gnutls_realloc (ctx -> auth_data_heap , new_sz );
712+ if (!p ) {
713+ WGW_ERROR ("gnutls_realloc failed for auth_data_heap" );
714+ return GNUTLS_E_MEMORY_ERROR ;
715+ }
716+ ctx -> auth_data_heap = p ;
717+ ctx -> auth_alloc = new_sz ;
718+ WGW_LOG ("Grew AAD heap to %zu bytes" , new_sz );
719+ }
680720
681721 /* Streaming must be a multiple of block size except for last. */
682722 if ((ctx -> auth_data_size % AES_BLOCK_SIZE ) != 0 ) {
@@ -685,8 +725,11 @@ int wolfssl_cipher_auth(void *_ctx, const void *auth_data,
685725 }
686726
687727 /* Store AAD for later use in encrypt/decrypt operations. */
688- XMEMCPY (ctx -> auth_data + ctx -> auth_data_size , auth_data , auth_size );
689- ctx -> auth_data_size += auth_size ;
728+ unsigned char * dst = ctx -> auth_data_heap ?
729+ ctx -> auth_data_heap : ctx -> auth_data_static ;
730+
731+ XMEMCPY (dst + ctx -> auth_data_size , auth_data , auth_size );
732+ ctx -> auth_data_size += auth_size ;
690733
691734 WGW_LOG ("AAD added successfully" );
692735 return 0 ;
@@ -751,7 +794,7 @@ int wolfssl_cipher_encrypt(void *_ctx, const void *src, size_t src_size,
751794 unsigned char * ptr ;
752795 unsigned char * encr ;
753796
754- WGW_LOG ("Caching platintext " );
797+ WGW_LOG ("Caching plaintext " );
755798
756799 ctx -> enc = 1 ;
757800
@@ -782,11 +825,13 @@ int wolfssl_cipher_encrypt(void *_ctx, const void *src, size_t src_size,
782825 WGW_ERROR ("realloc of gmac data failed" );
783826 return GNUTLS_E_INVALID_REQUEST ;
784827 }
828+ unsigned char * aad = ctx -> auth_data_heap ?
829+ ctx -> auth_data_heap : ctx -> auth_data_static ;
785830
786831 /* Do encryption with the data we have. */
787832 ret = wc_AesGcmEncrypt (& ctx -> cipher .aes_ctx , encr ,
788833 ctx -> data , ctx -> data_size , ctx -> iv , ctx -> iv_size ,
789- ctx -> tag , ctx -> tag_size , ctx -> auth_data , ctx -> auth_data_size );
834+ ctx -> tag , ctx -> tag_size , aad , ctx -> auth_data_size );
790835 if (ret != 0 ) {
791836 WGW_WOLFSSL_ERROR ("wc_AesGcmEncrypt" , ret );
792837 gnutls_free (encr );
@@ -894,7 +939,7 @@ int wolfssl_cipher_decrypt(void *_ctx, const void *src, size_t src_size,
894939 unsigned char * ptr ;
895940 unsigned char * decr ;
896941
897- WGW_LOG ("Caching platintext " );
942+ WGW_LOG ("Caching plaintext " );
898943
899944 ctx -> enc = 1 ;
900945
@@ -922,14 +967,18 @@ int wolfssl_cipher_decrypt(void *_ctx, const void *src, size_t src_size,
922967 }
923968
924969 WGW_LOG ("wc_AesGcmDecrypt" );
970+
971+ unsigned char * aad = ctx -> auth_data_heap ?
972+ ctx -> auth_data_heap : ctx -> auth_data_static ;
973+
925974 /* If caller hasn't set tag then we are creating it. */
926975 if (!ctx -> tag_set_ext ) {
927976 /* Encrypt the ciphertext to get the plaintext.
928977 * Tag will have been created on plaintext which is of no use.
929978 */
930979 ret = wc_AesGcmEncrypt (& ctx -> cipher .aes_ctx , decr , ctx -> data ,
931980 ctx -> data_size , ctx -> iv , ctx -> iv_size ,
932- ctx -> tag , ctx -> tag_size , ctx -> auth_data , ctx -> auth_data_size );
981+ ctx -> tag , ctx -> tag_size , aad , ctx -> auth_data_size );
933982 if (ret != 0 ) {
934983 WGW_WOLFSSL_ERROR ("wc_AesGcmEncrypt" , ret );
935984 gnutls_free (decr );
@@ -938,7 +987,7 @@ int wolfssl_cipher_decrypt(void *_ctx, const void *src, size_t src_size,
938987 /* Encrypt the plaintext to create the tag. */
939988 ret = wc_AesGcmEncrypt (& ctx -> cipher .aes_ctx , decr , decr ,
940989 ctx -> data_size , ctx -> iv , ctx -> iv_size ,
941- ctx -> tag , ctx -> tag_size , ctx -> auth_data , ctx -> auth_data_size );
990+ ctx -> tag , ctx -> tag_size , aad , ctx -> auth_data_size );
942991 if (ret != 0 ) {
943992 WGW_WOLFSSL_ERROR ("wc_AesGcmEncrypt" , ret );
944993 gnutls_free (decr );
@@ -950,7 +999,7 @@ int wolfssl_cipher_decrypt(void *_ctx, const void *src, size_t src_size,
950999 /* Do decryption with cipehtext, IV, authentication data and tag. */
9511000 ret = wc_AesGcmDecrypt (& ctx -> cipher .aes_ctx , decr ,
9521001 ctx -> data , ctx -> data_size , ctx -> iv , ctx -> iv_size ,
953- ctx -> tag , ctx -> tag_size , ctx -> auth_data , ctx -> auth_data_size );
1002+ ctx -> tag , ctx -> tag_size , aad , ctx -> auth_data_size );
9541003 if (ret != 0 ) {
9551004 WGW_WOLFSSL_ERROR ("wc_AesGcmEncrypt" , ret );
9561005 gnutls_free (decr );
@@ -1044,9 +1093,12 @@ void wolfssl_cipher_tag(void *_ctx, void *tag, size_t tag_size)
10441093 if (ctx -> mode == GCM ) {
10451094 WGW_LOG ("wc_AesGcmEncrypt" );
10461095
1096+ unsigned char * aad = ctx -> auth_data_heap ?
1097+ ctx -> auth_data_heap : ctx -> auth_data_static ;
1098+
10471099 /* Do authentication with no plaintext. */
10481100 ret = wc_AesGcmEncrypt (& ctx -> cipher .aes_ctx , NULL , NULL , 0 , ctx -> iv ,
1049- ctx -> iv_size , ctx -> tag , ctx -> tag_size , ctx -> auth_data ,
1101+ ctx -> iv_size , ctx -> tag , ctx -> tag_size , aad ,
10501102 ctx -> auth_data_size );
10511103 if (ret != 0 ) {
10521104 WGW_WOLFSSL_ERROR ("wc_AesGcmEncrypt" , ret );
@@ -1264,6 +1316,9 @@ void wolfssl_cipher_deinit(void *_ctx)
12641316 ctx -> initialized = 0 ;
12651317 ctx -> enc_initialized = 0 ;
12661318 ctx -> dec_initialized = 0 ;
1319+ if (ctx -> auth_data_heap ) {
1320+ gnutls_free (ctx -> auth_data_heap );
1321+ }
12671322 }
12681323
12691324 gnutls_free (ctx );
0 commit comments