Codebase list openssl / 59f5e75
Correctly calculate the length of SM2 plaintext given the ciphertext Previously the length of the SM2 plaintext could be incorrectly calculated. The plaintext length was calculated by taking the ciphertext length and taking off an "overhead" value. The overhead value was assumed to have a "fixed" element of 10 bytes. This is incorrect since in some circumstances it can be more than 10 bytes. Additionally the overhead included the length of two integers C1x and C1y, which were assumed to be the same length as the field size (32 bytes for the SM2 curve). However in some cases these integers can have an additional padding byte when the msb is set, to disambiguate them from negative integers. Additionally the integers can also be less than 32 bytes in length in some cases. If the calculated overhead is incorrect and larger than the actual value this can result in the calculated plaintext length being too small. Applications are likely to allocate buffer sizes based on this and therefore a buffer overrun can occur. CVE-2021-3711 Issue reported by John Ouyang. Reviewed-by: Paul Dale <pauli@openssl.org> Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com> Matt Caswell 2 years ago
4 changed file(s) with 13 addition(s) and 23 deletion(s). Raw diff Collapse all Expand all
6060 return field_size;
6161 }
6262
63 int sm2_plaintext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len,
64 size_t *pt_size)
65 {
66 const size_t field_size = ec_field_size(EC_KEY_get0_group(key));
67 const int md_size = EVP_MD_size(digest);
68 size_t overhead;
69
70 if (md_size < 0) {
71 SM2err(SM2_F_SM2_PLAINTEXT_SIZE, SM2_R_INVALID_DIGEST);
72 return 0;
73 }
74 if (field_size == 0) {
75 SM2err(SM2_F_SM2_PLAINTEXT_SIZE, SM2_R_INVALID_FIELD);
76 return 0;
77 }
78
79 overhead = 10 + 2 * field_size + (size_t)md_size;
80 if (msg_len <= overhead) {
63 int sm2_plaintext_size(const unsigned char *ct, size_t ct_size, size_t *pt_size)
64 {
65 struct SM2_Ciphertext_st *sm2_ctext = NULL;
66
67 sm2_ctext = d2i_SM2_Ciphertext(NULL, &ct, ct_size);
68
69 if (sm2_ctext == NULL) {
8170 SM2err(SM2_F_SM2_PLAINTEXT_SIZE, SM2_R_INVALID_ENCODING);
8271 return 0;
8372 }
8473
85 *pt_size = msg_len - overhead;
74 *pt_size = sm2_ctext->C2->length;
75 SM2_Ciphertext_free(sm2_ctext);
76
8677 return 1;
8778 }
8879
150150 const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md;
151151
152152 if (out == NULL) {
153 if (!sm2_plaintext_size(ec, md, inlen, outlen))
153 if (!sm2_plaintext_size(in, inlen, outlen))
154154 return -1;
155155 else
156156 return 1;
5959 int sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len,
6060 size_t *ct_size);
6161
62 int sm2_plaintext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len,
63 size_t *pt_size);
62 int sm2_plaintext_size(const unsigned char *ct, size_t ct_size, size_t *pt_size);
6463
6564 int sm2_encrypt(const EC_KEY *key,
6665 const EVP_MD *digest,
184184 if (!TEST_mem_eq(ctext, ctext_len, expected, ctext_len))
185185 goto done;
186186
187 if (!TEST_true(sm2_plaintext_size(key, digest, ctext_len, &ptext_len))
187 if (!TEST_true(sm2_plaintext_size(ctext, ctext_len, &ptext_len))
188188 || !TEST_int_eq(ptext_len, msg_len))
189189 goto done;
190190