mirror of
https://github.com/openssl/openssl.git
synced 2026-01-25 02:56:43 +00:00
base64 encoder: Make ctx->length a constant
It is never changed anywhere. Fixes #29518 Reviewed-by: Saša Nedvědický <sashan@openssl.org> Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Matt Caswell <matt@openssl.org> MergeDate: Mon Jan 19 14:20:35 2026 (Merged from https://github.com/openssl/openssl/pull/29550)
This commit is contained in:
@@ -134,7 +134,7 @@ int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
|
||||
int srp = (ctx != NULL
|
||||
&& (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0);
|
||||
int wrap_cnt_by_input = *wrap_cnt / 4 * 3;
|
||||
const int ctx_length = (ctx != NULL) ? ctx->length : 0;
|
||||
const int ctx_length = (ctx != NULL) ? EVP_ENCODE_B64_LENGTH : 0;
|
||||
|
||||
if (srp) {
|
||||
e0 = base64_srp_bin2ascii_0;
|
||||
@@ -168,11 +168,11 @@ int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
|
||||
int wrap_cnt_nm3 = 0;
|
||||
while (i + 2 < dlen) {
|
||||
if (ctx != NULL) {
|
||||
if ((wrap_cnt_nm3 < ctx->length
|
||||
&& (wrap_cnt_nm3 + 3 + wrap_cnt_by_input) > ctx->length)
|
||||
if ((wrap_cnt_nm3 < EVP_ENCODE_B64_LENGTH
|
||||
&& (wrap_cnt_nm3 + 3 + wrap_cnt_by_input) > EVP_ENCODE_B64_LENGTH)
|
||||
&& ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0)) {
|
||||
|
||||
switch (ctx->length % 3) {
|
||||
switch (EVP_ENCODE_B64_LENGTH % 3) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
@@ -228,7 +228,9 @@ int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
|
||||
ret += 4;
|
||||
|
||||
if (ctx != NULL) {
|
||||
if ((i + 3 + wrap_cnt_by_input) % ctx->length == 0 && ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) && ctx->length % 3 == 0) {
|
||||
if ((i + 3 + wrap_cnt_by_input) % EVP_ENCODE_B64_LENGTH == 0
|
||||
&& ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0)
|
||||
&& EVP_ENCODE_B64_LENGTH % 3 == 0) {
|
||||
*(t++) = '\n';
|
||||
ret++;
|
||||
}
|
||||
@@ -249,7 +251,9 @@ int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
|
||||
ret += 4;
|
||||
|
||||
if (ctx != NULL) {
|
||||
if ((i + 1 + wrap_cnt_by_input) % ctx->length == 0 && ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) && ctx->length % 3 == 0) {
|
||||
if ((i + 1 + wrap_cnt_by_input) % EVP_ENCODE_B64_LENGTH == 0
|
||||
&& ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0)
|
||||
&& EVP_ENCODE_B64_LENGTH % 3 == 0) {
|
||||
*(t++) = '\n';
|
||||
ret++;
|
||||
}
|
||||
@@ -266,7 +270,9 @@ int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
|
||||
ret += 4;
|
||||
|
||||
if (ctx != NULL) {
|
||||
if ((i + 2 + wrap_cnt_by_input) % ctx->length == 0 && ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) && ctx->length % 3 == 0) {
|
||||
if ((i + 2 + wrap_cnt_by_input) % EVP_ENCODE_B64_LENGTH == 0
|
||||
&& ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0)
|
||||
&& EVP_ENCODE_B64_LENGTH % 3 == 0) {
|
||||
*(t++) = '\n';
|
||||
ret++;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/evp.h>
|
||||
#include "crypto/evp.h"
|
||||
@@ -364,7 +365,6 @@ void evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags)
|
||||
|
||||
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
|
||||
{
|
||||
ctx->length = 48;
|
||||
ctx->num = 0;
|
||||
ctx->line_num = 0;
|
||||
ctx->flags = 0;
|
||||
@@ -379,19 +379,19 @@ int EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
|
||||
*outl = 0;
|
||||
if (inl <= 0)
|
||||
return 0;
|
||||
OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
|
||||
if (ctx->length - ctx->num > inl) {
|
||||
assert(EVP_ENCODE_B64_LENGTH <= (int)sizeof(ctx->enc_data));
|
||||
if (EVP_ENCODE_B64_LENGTH - ctx->num > inl) {
|
||||
memcpy(&(ctx->enc_data[ctx->num]), in, inl);
|
||||
ctx->num += inl;
|
||||
return 1;
|
||||
}
|
||||
if (ctx->num != 0) {
|
||||
i = ctx->length - ctx->num;
|
||||
i = EVP_ENCODE_B64_LENGTH - ctx->num;
|
||||
memcpy(&(ctx->enc_data[ctx->num]), in, i);
|
||||
in += i;
|
||||
inl -= i;
|
||||
int wrap_cnt = 0;
|
||||
j = evp_encodeblock_int(ctx, out, ctx->enc_data, ctx->length,
|
||||
j = evp_encodeblock_int(ctx, out, ctx->enc_data, EVP_ENCODE_B64_LENGTH,
|
||||
&wrap_cnt);
|
||||
ctx->num = 0;
|
||||
out += j;
|
||||
@@ -399,39 +399,39 @@ int EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
|
||||
*out = '\0';
|
||||
}
|
||||
int wrap_cnt = 0;
|
||||
if (ctx->length % 3 != 0) {
|
||||
j = evp_encodeblock_int(ctx, out, in, inl - (inl % ctx->length),
|
||||
if (EVP_ENCODE_B64_LENGTH % 3 != 0) {
|
||||
j = evp_encodeblock_int(ctx, out, in, inl - (inl % EVP_ENCODE_B64_LENGTH),
|
||||
&wrap_cnt);
|
||||
} else {
|
||||
#if defined(__AVX2__)
|
||||
const int newlines = !(ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) ? ctx->length : 0;
|
||||
const int newlines = !(ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) ? EVP_ENCODE_B64_LENGTH : 0;
|
||||
|
||||
j = encode_base64_avx2(ctx,
|
||||
(unsigned char *)out,
|
||||
(const unsigned char *)in,
|
||||
inl - (inl % ctx->length), newlines, &wrap_cnt);
|
||||
inl - (inl % EVP_ENCODE_B64_LENGTH), newlines, &wrap_cnt);
|
||||
#elif defined(HAS_IA32CAP_IS_64)
|
||||
if ((OPENSSL_ia32cap_P[2] & (1u << 5)) != 0) {
|
||||
const int newlines = !(ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) ? ctx->length : 0;
|
||||
const int newlines = !(ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) ? EVP_ENCODE_B64_LENGTH : 0;
|
||||
|
||||
j = encode_base64_avx2(ctx,
|
||||
(unsigned char *)out,
|
||||
(const unsigned char *)in,
|
||||
inl - (inl % ctx->length), newlines, &wrap_cnt);
|
||||
inl - (inl % EVP_ENCODE_B64_LENGTH), newlines, &wrap_cnt);
|
||||
} else {
|
||||
j = evp_encodeblock_int(ctx, out, in, inl - (inl % ctx->length),
|
||||
j = evp_encodeblock_int(ctx, out, in, inl - (inl % EVP_ENCODE_B64_LENGTH),
|
||||
&wrap_cnt);
|
||||
}
|
||||
#else
|
||||
j = evp_encodeblock_int(ctx, out, in, inl - (inl % ctx->length),
|
||||
j = evp_encodeblock_int(ctx, out, in, inl - (inl % EVP_ENCODE_B64_LENGTH),
|
||||
&wrap_cnt);
|
||||
#endif
|
||||
}
|
||||
in += inl - (inl % ctx->length);
|
||||
inl -= inl - (inl % ctx->length);
|
||||
in += inl - (inl % EVP_ENCODE_B64_LENGTH);
|
||||
inl -= inl - (inl % EVP_ENCODE_B64_LENGTH);
|
||||
out += j;
|
||||
total += j;
|
||||
if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0 && ctx->length % 3 != 0) {
|
||||
if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0 && EVP_ENCODE_B64_LENGTH % 3 != 0) {
|
||||
*(out++) = '\n';
|
||||
total++;
|
||||
}
|
||||
@@ -487,7 +487,6 @@ void EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
|
||||
{
|
||||
/* Only ctx->num and ctx->flags are used during decoding. */
|
||||
ctx->num = 0;
|
||||
ctx->length = 0;
|
||||
ctx->line_num = 0;
|
||||
ctx->flags = 0;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
|
||||
#define EVP_CTRL_RET_UNSUPPORTED -1
|
||||
|
||||
/*
|
||||
* Length of the BASE64-encoded lines when encoding.
|
||||
* This needs to be divisible by 3 to keep the AVX2 optimized code path.
|
||||
*/
|
||||
#define EVP_ENCODE_B64_LENGTH 48
|
||||
|
||||
struct evp_md_ctx_st {
|
||||
const EVP_MD *reqdigest; /* The original requested digest */
|
||||
const EVP_MD *digest;
|
||||
@@ -272,12 +278,6 @@ int PKCS5_v2_PBKDF2_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass,
|
||||
struct evp_Encode_Ctx_st {
|
||||
/* number saved in a partial encode/decode */
|
||||
int num;
|
||||
/*
|
||||
* The length is either the output line length (in input bytes) or the
|
||||
* shortest input line length that is ok. Once decoding begins, the
|
||||
* length is adjusted up each time a longer line is decoded
|
||||
*/
|
||||
int length;
|
||||
/* data to encode */
|
||||
unsigned char enc_data[80];
|
||||
/* number read on current line */
|
||||
|
||||
@@ -30,8 +30,7 @@ static void fuzz_fill_encode_ctx(EVP_ENCODE_CTX *ctx, int max_fill)
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
ctx->enc_data[i] = (unsigned char)(rand() & 0xFF);
|
||||
ctx->length = (rand() % 80) + 1;
|
||||
ctx->line_num = rand() % (ctx->length + 1);
|
||||
ctx->line_num = rand() % (EVP_ENCODE_B64_LENGTH + 1);
|
||||
}
|
||||
static inline uint32_t next_u32(uint32_t *state)
|
||||
{
|
||||
@@ -100,18 +99,18 @@ static int evp_encodeupdate_old(EVP_ENCODE_CTX *ctx, unsigned char *out, int *ou
|
||||
*outl = 0;
|
||||
if (inl <= 0)
|
||||
return 0;
|
||||
OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
|
||||
if (ctx->length - ctx->num > inl) {
|
||||
OPENSSL_assert(EVP_ENCODE_B64_LENGTH <= (int)sizeof(ctx->enc_data));
|
||||
if (EVP_ENCODE_B64_LENGTH - ctx->num > inl) {
|
||||
memcpy(&(ctx->enc_data[ctx->num]), in, inl);
|
||||
ctx->num += inl;
|
||||
return 1;
|
||||
}
|
||||
if (ctx->num != 0) {
|
||||
i = ctx->length - ctx->num;
|
||||
i = EVP_ENCODE_B64_LENGTH - ctx->num;
|
||||
memcpy(&(ctx->enc_data[ctx->num]), in, i);
|
||||
in += i;
|
||||
inl -= i;
|
||||
j = evp_encodeblock_int_old(ctx, out, ctx->enc_data, ctx->length);
|
||||
j = evp_encodeblock_int_old(ctx, out, ctx->enc_data, EVP_ENCODE_B64_LENGTH);
|
||||
ctx->num = 0;
|
||||
out += j;
|
||||
total = j;
|
||||
@@ -121,10 +120,10 @@ static int evp_encodeupdate_old(EVP_ENCODE_CTX *ctx, unsigned char *out, int *ou
|
||||
}
|
||||
*out = '\0';
|
||||
}
|
||||
while (inl >= ctx->length) {
|
||||
j = evp_encodeblock_int_old(ctx, out, in, ctx->length);
|
||||
in += ctx->length;
|
||||
inl -= ctx->length;
|
||||
while (inl >= EVP_ENCODE_B64_LENGTH) {
|
||||
j = evp_encodeblock_int_old(ctx, out, in, EVP_ENCODE_B64_LENGTH);
|
||||
in += EVP_ENCODE_B64_LENGTH;
|
||||
inl -= EVP_ENCODE_B64_LENGTH;
|
||||
out += j;
|
||||
total += j;
|
||||
if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) {
|
||||
@@ -154,7 +153,8 @@ static void evp_encodefinal_old(EVP_ENCODE_CTX *ctx, unsigned char *out, int *ou
|
||||
}
|
||||
*outl = ret;
|
||||
}
|
||||
static int test_encode_line_lengths_reinforced(void)
|
||||
|
||||
static int test_encode_line_length_reinforced(void)
|
||||
{
|
||||
const int trials = 50;
|
||||
uint32_t seed = 12345;
|
||||
@@ -175,65 +175,59 @@ static int test_encode_line_lengths_reinforced(void)
|
||||
|
||||
for (int partial_ctx_fill = 0; partial_ctx_fill <= 80;
|
||||
partial_ctx_fill += 1) {
|
||||
for (int ctx_len = 1; ctx_len <= 80; ctx_len += 1) {
|
||||
ctx_simd = EVP_ENCODE_CTX_new();
|
||||
ctx_ref = EVP_ENCODE_CTX_new();
|
||||
ctx_simd = EVP_ENCODE_CTX_new();
|
||||
ctx_ref = EVP_ENCODE_CTX_new();
|
||||
|
||||
if (!ctx_simd || !ctx_ref) {
|
||||
TEST_error("Out of memory for contexts");
|
||||
if (!TEST_ptr(ctx_simd) || !TEST_ptr(ctx_ref))
|
||||
goto fail;
|
||||
|
||||
fuzz_fill_encode_ctx(ctx_simd, partial_ctx_fill);
|
||||
|
||||
memset(out_simd, 0xCC, sizeof(out_simd)); /* poison to catch short writes */
|
||||
memset(out_ref, 0xDD, sizeof(out_ref));
|
||||
|
||||
int outlen_simd = 0, outlen_ref = 0; /* bytes produced by Update */
|
||||
int finlen_simd = 0, finlen_ref = 0; /* bytes produced by Final */
|
||||
|
||||
EVP_EncodeInit(ctx_simd);
|
||||
EVP_EncodeInit(ctx_ref);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (i % 2 == 0) {
|
||||
/* Turn SRP alphabet OFF */
|
||||
ctx_simd->flags &= ~EVP_ENCODE_CTX_USE_SRP_ALPHABET;
|
||||
ctx_ref->flags &= ~EVP_ENCODE_CTX_USE_SRP_ALPHABET;
|
||||
} else {
|
||||
/* Turn SRP alphabet ON */
|
||||
ctx_simd->flags |= EVP_ENCODE_CTX_USE_SRP_ALPHABET;
|
||||
ctx_ref->flags |= EVP_ENCODE_CTX_USE_SRP_ALPHABET;
|
||||
}
|
||||
|
||||
int ret_simd = EVP_EncodeUpdate(ctx_simd, out_simd, &outlen_simd,
|
||||
input, (int)inl);
|
||||
int ret_ref = evp_encodeupdate_old(ctx_ref, out_ref, &outlen_ref,
|
||||
input, (int)inl);
|
||||
|
||||
if (!TEST_int_eq(ret_simd, ret_ref)
|
||||
|| !TEST_mem_eq(out_ref, outlen_ref, out_simd, outlen_simd)
|
||||
|| !TEST_int_eq(outlen_simd, outlen_ref))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fuzz_fill_encode_ctx(ctx_simd, partial_ctx_fill);
|
||||
EVP_EncodeFinal(ctx_simd, out_simd + outlen_simd,
|
||||
&finlen_simd);
|
||||
evp_encodefinal_old(ctx_ref, out_ref + outlen_ref,
|
||||
&finlen_ref);
|
||||
|
||||
memset(out_simd, 0xCC, sizeof(out_simd)); /* poison to catch short writes */
|
||||
memset(out_ref, 0xDD, sizeof(out_ref));
|
||||
int total_ref = outlen_ref + finlen_ref;
|
||||
int total_simd = outlen_simd + finlen_simd;
|
||||
|
||||
int outlen_simd = 0, outlen_ref = 0; /* bytes produced by Update */
|
||||
int finlen_simd = 0, finlen_ref = 0; /* bytes produced by Final */
|
||||
|
||||
EVP_EncodeInit(ctx_simd);
|
||||
EVP_EncodeInit(ctx_ref);
|
||||
ctx_simd->length = ctx_len;
|
||||
ctx_ref->length = ctx_len;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (i % 2 == 0) {
|
||||
/* Turn SRP alphabet OFF */
|
||||
ctx_simd->flags &= ~EVP_ENCODE_CTX_USE_SRP_ALPHABET;
|
||||
ctx_ref->flags &= ~EVP_ENCODE_CTX_USE_SRP_ALPHABET;
|
||||
} else {
|
||||
/* Turn SRP alphabet ON */
|
||||
ctx_simd->flags |= EVP_ENCODE_CTX_USE_SRP_ALPHABET;
|
||||
ctx_ref->flags |= EVP_ENCODE_CTX_USE_SRP_ALPHABET;
|
||||
}
|
||||
|
||||
int ret_simd = EVP_EncodeUpdate(ctx_simd, out_simd, &outlen_simd,
|
||||
input, (int)inl);
|
||||
int ret_ref = evp_encodeupdate_old(ctx_ref, out_ref, &outlen_ref,
|
||||
input, (int)inl);
|
||||
|
||||
if (!TEST_int_eq(ret_simd, ret_ref)
|
||||
|| !TEST_mem_eq(out_ref, outlen_ref, out_simd, outlen_simd)
|
||||
|| !TEST_int_eq(outlen_simd, outlen_ref))
|
||||
goto fail;
|
||||
|
||||
EVP_EncodeFinal(ctx_simd, out_simd + outlen_simd,
|
||||
&finlen_simd);
|
||||
evp_encodefinal_old(ctx_ref, out_ref + outlen_ref,
|
||||
&finlen_ref);
|
||||
|
||||
int total_ref = outlen_ref + finlen_ref;
|
||||
int total_simd = outlen_simd + finlen_simd;
|
||||
|
||||
if (!TEST_int_eq(finlen_simd, finlen_ref)
|
||||
|| !TEST_mem_eq(out_ref, total_ref, out_simd, total_simd))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
EVP_ENCODE_CTX_free(ctx_simd);
|
||||
EVP_ENCODE_CTX_free(ctx_ref);
|
||||
if (!TEST_int_eq(finlen_simd, finlen_ref)
|
||||
|| !TEST_mem_eq(out_ref, total_ref, out_simd, total_simd))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
EVP_ENCODE_CTX_free(ctx_simd);
|
||||
EVP_ENCODE_CTX_free(ctx_ref);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +241,7 @@ fail:
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
ADD_TEST(test_encode_line_lengths_reinforced);
|
||||
ADD_TEST(test_encode_line_length_reinforced);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user