Skip to content

Commit 77785f2

Browse files
committed
Fix AES-GCM decryption on OpenSSL 1.0.2-fips
Signed-off-by: Cory Snider <[email protected]>
1 parent 7382a1b commit 77785f2

File tree

1 file changed

+22
-4
lines changed

1 file changed

+22
-4
lines changed

goopenssl.h

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,22 +144,40 @@ go_openssl_EVP_CIPHER_CTX_open_wrapper(const GO_EVP_CIPHER_CTX_PTR ctx,
144144
const unsigned char *aad, int aad_len,
145145
const unsigned char *tag)
146146
{
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+
}
148161
if (aad_len == 0) aad = (const unsigned char *)"";
149162

150163
if (go_openssl_EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, nonce) != 1)
151164
return 0;
152165

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+
153174
int discard_len, out_len;
154175
if (go_openssl_EVP_DecryptUpdate(ctx, NULL, &discard_len, aad, aad_len) != 1
155176
|| go_openssl_EVP_DecryptUpdate(ctx, out, &out_len, in, in_len) != 1)
156177
{
157178
return 0;
158179
}
159180

160-
if (go_openssl_EVP_CIPHER_CTX_ctrl(ctx, GO_EVP_CTRL_GCM_SET_TAG, 16, (unsigned char *)(tag)) != 1)
161-
return 0;
162-
163181
if (go_openssl_EVP_DecryptFinal_ex(ctx, out + out_len, &discard_len) != 1)
164182
return 0;
165183

0 commit comments

Comments
 (0)