@@ -144,22 +144,47 @@ go_openssl_EVP_CIPHER_CTX_open_wrapper(const GO_EVP_CIPHER_CTX_PTR ctx,
144
144
const unsigned char * aad , int aad_len ,
145
145
const unsigned char * tag )
146
146
{
147
- if (in_len == 0 ) in = "" ;
147
+ if (in_len == 0 ) {
148
+ in = "" ;
149
+ // When the caller only wants to verify authenticated additional data
150
+ // (AAD), no output buffer is technically needed as there is no data to
151
+ // decrypt. Unfortunately, AAD is specified by calling EVP_DecryptUpdate
152
+ // with out set to NULL, so decrypting a zero-length input with a NULL
153
+ // output buffer looks to OpenSSL like specifying an additional
154
+ // (zero-length) chunk of AAD. This is effectively a no-op and
155
+ // verification will proceed as expected, except for OpenSSL 1.0.2 in
156
+ // FIPS mode. It will fail to verify unless EVP_DecryptUpdate is called
157
+ // at least once with a non-NULL output buffer. OpenSSL will not
158
+ // dereference the output buffer when the input length is zero, so set
159
+ // it to an arbitrary non-NULL pointer to satisfy OpenSSL.
160
+ //
161
+ // While a stack-allocated buffer could be used, that would risk a
162
+ // buffer overflow which would then smash the stack if OpenSSL
163
+ // unexpectedly dereferenced it. Instead pass a value which would
164
+ // trigger a segfault if dereferenced on any modern platform where a
165
+ // NULL-pointer dereference would also segfault.
166
+ if (out == NULL ) out = (unsigned char * )1 ;
167
+ }
148
168
if (aad_len == 0 ) aad = "" ;
149
169
150
170
if (go_openssl_EVP_CipherInit_ex (ctx , NULL , NULL , NULL , nonce , GO_AES_DECRYPT ) != 1 )
151
171
return 0 ;
152
172
173
+ // OpenSSL 1.0.x FIPS Object Module 2.0 versions below 2.0.5 require that
174
+ // the tag be set before the ciphertext, otherwise EVP_DecryptUpdate returns
175
+ // an error. At least one extant commercially-supported, FIPS validated
176
+ // build of OpenSSL 1.0.2 uses FIPS module version 2.0.1. Set the tag first
177
+ // to maximize compatibility with all OpenSSL version combinations.
178
+ if (go_openssl_EVP_CIPHER_CTX_ctrl (ctx , GO_EVP_CTRL_GCM_SET_TAG , 16 , (unsigned char * )(tag )) != 1 )
179
+ return 0 ;
180
+
153
181
int discard_len , out_len ;
154
182
if (go_openssl_EVP_DecryptUpdate (ctx , NULL , & discard_len , aad , aad_len ) != 1
155
183
|| go_openssl_EVP_DecryptUpdate (ctx , out , & out_len , in , in_len ) != 1 )
156
184
{
157
185
return 0 ;
158
186
}
159
187
160
- if (go_openssl_EVP_CIPHER_CTX_ctrl (ctx , GO_EVP_CTRL_GCM_SET_TAG , 16 , (unsigned char * )(tag )) != 1 )
161
- return 0 ;
162
-
163
188
if (go_openssl_EVP_DecryptFinal_ex (ctx , out + out_len , & discard_len ) != 1 )
164
189
return 0 ;
165
190
0 commit comments