@@ -144,22 +144,40 @@ 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 = (const unsigned char * )"" ;
147
+ if (in_len == 0 ) {
148
+ in = (const unsigned char * )"" ;
149
+ // OpenSSL 1.0.2 in FIPS mode contains a bug: it will fail to verify
150
+ // unless EVP_DecryptUpdate is called at least once with a non-NULL
151
+ // output buffer. OpenSSL will not dereference the output buffer when
152
+ // the input length is zero, so set it to an arbitrary non-NULL pointer
153
+ // to satisfy OpenSSL when the caller only has authenticated additional
154
+ // data (AAD) to verify. While a stack-allocated buffer could be used,
155
+ // that would risk a stack-corrupting buffer overflow if OpenSSL
156
+ // unexpectedly dereferenced it. Instead pass a value which would
157
+ // segfault if dereferenced on any modern platform where a NULL-pointer
158
+ // dereference would also segfault.
159
+ if (out == NULL ) out = (unsigned char * )1 ;
160
+ }
148
161
if (aad_len == 0 ) aad = (const unsigned char * )"" ;
149
162
150
163
if (go_openssl_EVP_DecryptInit_ex (ctx , NULL , NULL , NULL , nonce ) != 1 )
151
164
return 0 ;
152
165
166
+ // OpenSSL 1.0.x FIPS Object Module 2.0 versions below 2.0.5 require that
167
+ // the tag be set before the ciphertext, otherwise EVP_DecryptUpdate returns
168
+ // an error. At least one extant commercially-supported, FIPS validated
169
+ // build of OpenSSL 1.0.2 uses FIPS module version 2.0.1. Set the tag first
170
+ // to maximize compatibility with all OpenSSL version combinations.
171
+ if (go_openssl_EVP_CIPHER_CTX_ctrl (ctx , GO_EVP_CTRL_GCM_SET_TAG , 16 , (unsigned char * )(tag )) != 1 )
172
+ return 0 ;
173
+
153
174
int discard_len , out_len ;
154
175
if (go_openssl_EVP_DecryptUpdate (ctx , NULL , & discard_len , aad , aad_len ) != 1
155
176
|| go_openssl_EVP_DecryptUpdate (ctx , out , & out_len , in , in_len ) != 1 )
156
177
{
157
178
return 0 ;
158
179
}
159
180
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
181
if (go_openssl_EVP_DecryptFinal_ex (ctx , out + out_len , & discard_len ) != 1 )
164
182
return 0 ;
165
183
0 commit comments