Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix CVE-2023-5363 #537

Merged
merged 3 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

*) 修复CVE-2023-4807

*) 修复CVE-2023-5363

Changes between 8.4.0-pre2 and 8.4.0-pre3 [08 Oct 2023]

*) 支持零知识证明算法-NIZKPoK 和实现 ZKP 范围证明工具
Expand Down
36 changes: 36 additions & 0 deletions crypto/evp/evp_enc.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,42 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx,
return 0;
}

#ifndef FIPS_MODULE
/*
* Fix for CVE-2023-5363
* Passing in a size as part of the init call takes effect late
* so, force such to occur before the initialisation.
*
* The FIPS provider's internal library context is used in a manner
* such that this is not an issue.
*/
if (params != NULL) {
OSSL_PARAM param_lens[3] = { OSSL_PARAM_END, OSSL_PARAM_END,
OSSL_PARAM_END };
OSSL_PARAM *q = param_lens;
const OSSL_PARAM *p;

p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL)
memcpy(q++, p, sizeof(*q));

/*
* Note that OSSL_CIPHER_PARAM_AEAD_IVLEN is a synomym for
* OSSL_CIPHER_PARAM_IVLEN so both are covered here.
*/
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL)
memcpy(q++, p, sizeof(*q));

if (q != param_lens) {
if (!EVP_CIPHER_CTX_set_params(ctx, param_lens)) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_LENGTH);
return 0;
}
}
}
#endif

if (enc) {
if (ctx->cipher->einit == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
Expand Down
253 changes: 253 additions & 0 deletions test/evp_extra_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -4605,6 +4605,253 @@ const OPTIONS *test_get_options(void)
return options;
}

static int aes_gcm_encrypt(const unsigned char *gcm_key, size_t gcm_key_s,
const unsigned char *gcm_iv, size_t gcm_ivlen,
const unsigned char *gcm_pt, size_t gcm_pt_s,
const unsigned char *gcm_aad, size_t gcm_aad_s,
const unsigned char *gcm_ct, size_t gcm_ct_s,
const unsigned char *gcm_tag, size_t gcm_tag_s)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int outlen, tmplen;
unsigned char outbuf[1024];
unsigned char outtag[16];
OSSL_PARAM params[2] = {
OSSL_PARAM_END, OSSL_PARAM_END
};

if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
|| !TEST_ptr(cipher = EVP_CIPHER_fetch(testctx, "AES-256-GCM", "")))
goto err;

params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN,
&gcm_ivlen);

if (!TEST_true(EVP_EncryptInit_ex2(ctx, cipher, gcm_key, gcm_iv, params))
|| (gcm_aad != NULL
&& !TEST_true(EVP_EncryptUpdate(ctx, NULL, &outlen,
gcm_aad, gcm_aad_s)))
|| !TEST_true(EVP_EncryptUpdate(ctx, outbuf, &outlen,
gcm_pt, gcm_pt_s))
|| !TEST_true(EVP_EncryptFinal_ex(ctx, outbuf, &tmplen)))
goto err;

params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
outtag, sizeof(outtag));

if (!TEST_true(EVP_CIPHER_CTX_get_params(ctx, params))
|| !TEST_mem_eq(outbuf, outlen, gcm_ct, gcm_ct_s)
|| !TEST_mem_eq(outtag, gcm_tag_s, gcm_tag, gcm_tag_s))
goto err;

ret = 1;
err:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);

return ret;
}

static int aes_gcm_decrypt(const unsigned char *gcm_key, size_t gcm_key_s,
const unsigned char *gcm_iv, size_t gcm_ivlen,
const unsigned char *gcm_pt, size_t gcm_pt_s,
const unsigned char *gcm_aad, size_t gcm_aad_s,
const unsigned char *gcm_ct, size_t gcm_ct_s,
const unsigned char *gcm_tag, size_t gcm_tag_s)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int outlen;
unsigned char outbuf[1024];
OSSL_PARAM params[2] = {
OSSL_PARAM_END, OSSL_PARAM_END
};

if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
goto err;

if ((cipher = EVP_CIPHER_fetch(testctx, "AES-256-GCM", "")) == NULL)
goto err;

params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN,
&gcm_ivlen);

if (!TEST_true(EVP_DecryptInit_ex2(ctx, cipher, gcm_key, gcm_iv, params))
|| (gcm_aad != NULL
&& !TEST_true(EVP_DecryptUpdate(ctx, NULL, &outlen,
gcm_aad, gcm_aad_s)))
|| !TEST_true(EVP_DecryptUpdate(ctx, outbuf, &outlen,
gcm_ct, gcm_ct_s))
|| !TEST_mem_eq(outbuf, outlen, gcm_pt, gcm_pt_s))
goto err;

params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
(void*)gcm_tag, gcm_tag_s);

if (!TEST_true(EVP_CIPHER_CTX_set_params(ctx, params))
||!TEST_true(EVP_DecryptFinal_ex(ctx, outbuf, &outlen)))
goto err;

ret = 1;
err:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);

return ret;
}

static int test_aes_gcm_ivlen_change_cve_2023_5363(void)
{
/* AES-GCM test data obtained from NIST public test vectors */
static const unsigned char gcm_key[] = {
0xd0, 0xc2, 0x67, 0xc1, 0x9f, 0x30, 0xd8, 0x0b, 0x89, 0x14, 0xbb, 0xbf,
0xb7, 0x2f, 0x73, 0xb8, 0xd3, 0xcd, 0x5f, 0x6a, 0x78, 0x70, 0x15, 0x84,
0x8a, 0x7b, 0x30, 0xe3, 0x8f, 0x16, 0xf1, 0x8b,
};
static const unsigned char gcm_iv[] = {
0xb6, 0xdc, 0xda, 0x95, 0xac, 0x99, 0x77, 0x76, 0x25, 0xae, 0x87, 0xf8,
0xa3, 0xa9, 0xdd, 0x64, 0xd7, 0x9b, 0xbd, 0x5f, 0x4a, 0x0e, 0x54, 0xca,
0x1a, 0x9f, 0xa2, 0xe3, 0xf4, 0x5f, 0x5f, 0xc2, 0xce, 0xa7, 0xb6, 0x14,
0x12, 0x6f, 0xf0, 0xaf, 0xfd, 0x3e, 0x17, 0x35, 0x6e, 0xa0, 0x16, 0x09,
0xdd, 0xa1, 0x3f, 0xd8, 0xdd, 0xf3, 0xdf, 0x4f, 0xcb, 0x18, 0x49, 0xb8,
0xb3, 0x69, 0x2c, 0x5d, 0x4f, 0xad, 0x30, 0x91, 0x08, 0xbc, 0xbe, 0x24,
0x01, 0x0f, 0xbe, 0x9c, 0xfb, 0x4f, 0x5d, 0x19, 0x7f, 0x4c, 0x53, 0xb0,
0x95, 0x90, 0xac, 0x7b, 0x1f, 0x7b, 0xa0, 0x99, 0xe1, 0xf3, 0x48, 0x54,
0xd0, 0xfc, 0xa9, 0xcc, 0x91, 0xf8, 0x1f, 0x9b, 0x6c, 0x9a, 0xe0, 0xdc,
0x63, 0xea, 0x7d, 0x2a, 0x4a, 0x7d, 0xa5, 0xed, 0x68, 0x57, 0x27, 0x6b,
0x68, 0xe0, 0xf2, 0xb8, 0x51, 0x50, 0x8d, 0x3d,
};
static const unsigned char gcm_pt[] = {
0xb8, 0xb6, 0x88, 0x36, 0x44, 0xe2, 0x34, 0xdf, 0x24, 0x32, 0x91, 0x07,
0x4f, 0xe3, 0x6f, 0x81,
};
static const unsigned char gcm_ct[] = {
0xff, 0x4f, 0xb3, 0xf3, 0xf9, 0xa2, 0x51, 0xd4, 0x82, 0xc2, 0xbe, 0xf3,
0xe2, 0xd0, 0xec, 0xed,
};
static const unsigned char gcm_tag[] = {
0xbd, 0x06, 0x38, 0x09, 0xf7, 0xe1, 0xc4, 0x72, 0x0e, 0xf2, 0xea, 0x63,
0xdb, 0x99, 0x6c, 0x21,
};

return aes_gcm_encrypt(gcm_key, sizeof(gcm_key), gcm_iv, sizeof(gcm_iv),
gcm_pt, sizeof(gcm_pt), NULL, 0,
gcm_ct, sizeof(gcm_ct), gcm_tag, sizeof(gcm_tag))
&& aes_gcm_decrypt(gcm_key, sizeof(gcm_key), gcm_iv, sizeof(gcm_iv),
gcm_pt, sizeof(gcm_pt), NULL, 0,
gcm_ct, sizeof(gcm_ct), gcm_tag, sizeof(gcm_tag));
}

#ifndef OPENSSL_NO_RC4
static int rc4_encrypt(const unsigned char *rc4_key, size_t rc4_key_s,
const unsigned char *rc4_pt, size_t rc4_pt_s,
const unsigned char *rc4_ct, size_t rc4_ct_s)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int outlen, tmplen;
unsigned char outbuf[1024];
OSSL_PARAM params[2] = {
OSSL_PARAM_END, OSSL_PARAM_END
};

if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
|| !TEST_ptr(cipher = EVP_CIPHER_fetch(testctx, "RC4", "")))
goto err;

params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN,
&rc4_key_s);

if (!TEST_true(EVP_EncryptInit_ex2(ctx, cipher, rc4_key, NULL, params))
|| !TEST_true(EVP_EncryptUpdate(ctx, outbuf, &outlen,
rc4_pt, rc4_pt_s))
|| !TEST_true(EVP_EncryptFinal_ex(ctx, outbuf, &tmplen)))
goto err;

if (!TEST_mem_eq(outbuf, outlen, rc4_ct, rc4_ct_s))
goto err;

ret = 1;
err:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);

return ret;
}

static int rc4_decrypt(const unsigned char *rc4_key, size_t rc4_key_s,
const unsigned char *rc4_pt, size_t rc4_pt_s,
const unsigned char *rc4_ct, size_t rc4_ct_s)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int outlen;
unsigned char outbuf[1024];
OSSL_PARAM params[2] = {
OSSL_PARAM_END, OSSL_PARAM_END
};

if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
goto err;

if ((cipher = EVP_CIPHER_fetch(testctx, "RC4", "")) == NULL)
goto err;

params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN,
&rc4_key_s);

if (!TEST_true(EVP_DecryptInit_ex2(ctx, cipher, rc4_key, NULL, params))
|| !TEST_true(EVP_DecryptUpdate(ctx, outbuf, &outlen,
rc4_ct, rc4_ct_s))
|| !TEST_mem_eq(outbuf, outlen, rc4_pt, rc4_pt_s))
goto err;

ret = 1;
err:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);

return ret;
}

static int test_aes_rc4_keylen_change_cve_2023_5363(void)
{
/* RC4 test data obtained from RFC 6229 */
static const struct {
unsigned char key[5];
unsigned char padding[11];
} rc4_key = {
{ /* Five bytes of key material */
0x83, 0x32, 0x22, 0x77, 0x2a,
},
{ /* Random padding to 16 bytes */
0x80, 0xad, 0x97, 0xbd, 0xc9, 0x73, 0xdf, 0x8a, 0xaa, 0x32, 0x91
}
};
static const unsigned char rc4_pt[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char rc4_ct[] = {
0x80, 0xad, 0x97, 0xbd, 0xc9, 0x73, 0xdf, 0x8a,
0x2e, 0x87, 0x9e, 0x92, 0xa4, 0x97, 0xef, 0xda
};

if (lgcyprov == NULL)
return TEST_skip("Test requires legacy provider to be loaded");

return rc4_encrypt(rc4_key.key, sizeof(rc4_key.key),
rc4_pt, sizeof(rc4_pt), rc4_ct, sizeof(rc4_ct))
&& rc4_decrypt(rc4_key.key, sizeof(rc4_key.key),
rc4_pt, sizeof(rc4_pt), rc4_ct, sizeof(rc4_ct));
}
#endif

int setup_tests(void)
{
OPTION_CHOICE o;
Expand Down Expand Up @@ -4740,6 +4987,12 @@ int setup_tests(void)
ADD_TEST(test_EVP_sm4_ccm);
#endif

/* Test cases for CVE-2023-5363 */
ADD_TEST(test_aes_gcm_ivlen_change_cve_2023_5363);
#ifndef OPENSSL_NO_RC4
ADD_TEST(test_aes_rc4_keylen_change_cve_2023_5363);
#endif

return 1;
}

Expand Down
Loading