Skip to content

Commit d42c2ef

Browse files
vaintroubvuvova
authored andcommitted
MDEV-25785 Add support for OpenSSL 3.0
Summary of changes - MD_CTX_SIZE is increased - EVP_CIPHER_CTX_buf_noconst(ctx) does not work anymore, points to nobody knows where. The assumption made previously was that (since the function does not seem to be documented) was that it points to the last partial source block. Add own partial block buffer for NOPAD encryption instead - SECLEVEL in CipherString in openssl.cnf had been downgraded to 0, from 1, to make TLSv1.0 and TLSv1.1 possible (according to https://github.com/openssl/openssl/blob/openssl-3.0.0/NEWS.md even though the manual for SSL_CTX_get_security_level claims that it should not be necessary) - Workaround Ssl_cipher_list issue, it now returns TLSv1.3 ciphers, in addition to what was set in --ssl-cipher - ctx_buf buffer now must be aligned to 16 bytes with openssl( previously with WolfSSL only), ot crashes will happen - updated aes-t , to be better debuggable using function, rather than a huge multiline macro added test that does "nopad" encryption piece-wise, to test replacement of EVP_CIPHER_CTX_buf_noconst
1 parent a855d6d commit d42c2ef

File tree

8 files changed

+134
-56
lines changed

8 files changed

+134
-56
lines changed

cmake/ssl.cmake

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,13 @@ MACRO (MYSQL_CHECK_SSL)
139139
SET(SSL_INTERNAL_INCLUDE_DIRS "")
140140
SET(SSL_DEFINES "-DHAVE_OPENSSL")
141141

142+
# Silence "deprecated in OpenSSL 3.0"
143+
IF((NOT OPENSSL_VERSION) # 3.0 not determined by older cmake
144+
OR NOT(OPENSSL_VERSION VERSION_LESS "3.0.0"))
145+
SET(SSL_DEFINES "${SSL_DEFINES} -DOPENSSL_API_COMPAT=0x10100000L")
146+
SET(CMAKE_REQUIRED_DEFINITIONS -DOPENSSL_API_COMPAT=0x10100000L)
147+
ENDIF()
148+
142149
SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
143150
SET(CMAKE_REQUIRED_LIBRARIES ${SSL_LIBRARIES})
144151
SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
@@ -152,6 +159,7 @@ MACRO (MYSQL_CHECK_SSL)
152159
HAVE_X509_check_host)
153160
SET(CMAKE_REQUIRED_INCLUDES)
154161
SET(CMAKE_REQUIRED_LIBRARIES)
162+
SET(CMAKE_REQUIRED_DEFINITIONS)
155163
ELSE()
156164
IF(WITH_SSL STREQUAL "system")
157165
MESSAGE(FATAL_ERROR "Cannot find appropriate system libraries for SSL. Use WITH_SSL=bundled to enable SSL support")

include/mysql/service_my_crypt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ extern "C" {
4545
/* The max key length of all supported algorithms */
4646
#define MY_AES_MAX_KEY_LENGTH 32
4747

48-
#define MY_AES_CTX_SIZE 656
48+
#define MY_AES_CTX_SIZE 672
4949

5050
enum my_aes_mode {
5151
MY_AES_ECB, MY_AES_CBC

include/ssl_compat.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#define SSL_LIBRARY OpenSSL_version(OPENSSL_VERSION)
2525
#define ERR_remove_state(X) ERR_clear_error()
2626
#define EVP_CIPHER_CTX_SIZE 176
27-
#define EVP_MD_CTX_SIZE 48
27+
#define EVP_MD_CTX_SIZE 72
2828
#undef EVP_MD_CTX_init
2929
#define EVP_MD_CTX_init(X) do { memset((X), 0, EVP_MD_CTX_SIZE); EVP_MD_CTX_reset(X); } while(0)
3030
#undef EVP_CIPHER_CTX_init
@@ -74,7 +74,6 @@
7474
#endif
7575

7676
#define DH_set0_pqg(D,P,Q,G) ((D)->p= (P), (D)->g= (G))
77-
#define EVP_CIPHER_CTX_buf_noconst(ctx) ((ctx)->buf)
7877
#define EVP_CIPHER_CTX_encrypting(ctx) ((ctx)->encrypt)
7978
#define EVP_CIPHER_CTX_SIZE sizeof(EVP_CIPHER_CTX)
8079

mysql-test/lib/openssl.cnf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ ssl_conf = ssl_section
99
system_default = system_default_section
1010

1111
[system_default_section]
12-
CipherString = ALL:@SECLEVEL=1
12+
CipherString = ALL:@SECLEVEL=0

mysql-test/main/ssl_cipher.result

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ connect ssl_con,localhost,root,,,,,SSL;
6161
SHOW STATUS LIKE 'Ssl_cipher';
6262
Variable_name Value
6363
Ssl_cipher AES128-SHA
64-
SHOW STATUS LIKE 'Ssl_cipher_list';
65-
Variable_name Value
66-
Ssl_cipher_list AES128-SHA
64+
SELECT VARIABLE_VALUE like '%AES128-SHA%' FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='Ssl_cipher_list';
65+
VARIABLE_VALUE like '%AES128-SHA%'
66+
1
6767
disconnect ssl_con;
6868
connection default;

mysql-test/main/ssl_cipher.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,6 @@ let $restart_parameters=--ssl-cipher=AES128-SHA;
9898
source include/restart_mysqld.inc;
9999
connect (ssl_con,localhost,root,,,,,SSL);
100100
SHOW STATUS LIKE 'Ssl_cipher';
101-
SHOW STATUS LIKE 'Ssl_cipher_list';
101+
SELECT VARIABLE_VALUE like '%AES128-SHA%' FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='Ssl_cipher_list';
102102
disconnect ssl_con;
103103
connection default;

mysys_ssl/my_crypt.cc

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,7 @@
2929
#include <ssl_compat.h>
3030
#include <cstdint>
3131

32-
#ifdef HAVE_WOLFSSL
3332
#define CTX_ALIGN 16
34-
#else
35-
#define CTX_ALIGN 0
36-
#endif
3733

3834
class MyCTX
3935
{
@@ -100,8 +96,9 @@ class MyCTX_nopad : public MyCTX
10096
{
10197
public:
10298
const uchar *key;
103-
uint klen, buf_len;
99+
uint klen, source_tail_len;
104100
uchar oiv[MY_AES_BLOCK_SIZE];
101+
uchar source_tail[MY_AES_BLOCK_SIZE];
105102

106103
MyCTX_nopad() : MyCTX() { }
107104
~MyCTX_nopad() { }
@@ -112,7 +109,7 @@ class MyCTX_nopad : public MyCTX
112109
compile_time_assert(MY_AES_CTX_SIZE >= sizeof(MyCTX_nopad));
113110
this->key= key;
114111
this->klen= klen;
115-
this->buf_len= 0;
112+
this->source_tail_len= 0;
116113
if (ivlen)
117114
memcpy(oiv, iv, ivlen);
118115
DBUG_ASSERT(ivlen == 0 || ivlen == sizeof(oiv));
@@ -123,26 +120,41 @@ class MyCTX_nopad : public MyCTX
123120
return res;
124121
}
125122

123+
/** Update last partial source block, stored in source_tail array. */
124+
void update_source_tail(const uchar* src, uint slen)
125+
{
126+
if (!slen)
127+
return;
128+
uint new_tail_len= (source_tail_len + slen) % MY_AES_BLOCK_SIZE;
129+
if (new_tail_len)
130+
{
131+
if (slen + source_tail_len < MY_AES_BLOCK_SIZE)
132+
{
133+
memcpy(source_tail + source_tail_len, src, slen);
134+
}
135+
else
136+
{
137+
DBUG_ASSERT(slen > new_tail_len);
138+
memcpy(source_tail, src + slen - new_tail_len, new_tail_len);
139+
}
140+
}
141+
source_tail_len= new_tail_len;
142+
}
143+
126144
int update(const uchar *src, uint slen, uchar *dst, uint *dlen)
127145
{
128-
buf_len+= slen;
146+
update_source_tail(src, slen);
129147
return MyCTX::update(src, slen, dst, dlen);
130148
}
131149

132150
int finish(uchar *dst, uint *dlen)
133151
{
134-
buf_len %= MY_AES_BLOCK_SIZE;
135-
if (buf_len)
152+
if (source_tail_len)
136153
{
137-
uchar *buf= EVP_CIPHER_CTX_buf_noconst(ctx);
138154
/*
139155
Not much we can do, block ciphers cannot encrypt data that aren't
140156
a multiple of the block length. At least not without padding.
141157
Let's do something CTR-like for the last partial block.
142-
143-
NOTE this assumes that there are only buf_len bytes in the buf.
144-
If OpenSSL will change that, we'll need to change the implementation
145-
of this class too.
146158
*/
147159
uchar mask[MY_AES_BLOCK_SIZE];
148160
uint mlen;
@@ -154,10 +166,10 @@ class MyCTX_nopad : public MyCTX
154166
return rc;
155167
DBUG_ASSERT(mlen == sizeof(mask));
156168

157-
for (uint i=0; i < buf_len; i++)
158-
dst[i]= buf[i] ^ mask[i];
169+
for (uint i=0; i < source_tail_len; i++)
170+
dst[i]= source_tail[i] ^ mask[i];
159171
}
160-
*dlen= buf_len;
172+
*dlen= source_tail_len;
161173
return MY_AES_OK;
162174
}
163175
};

unittest/mysys/aes-t.c

Lines changed: 90 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,96 @@
2121
#include <string.h>
2222
#include <ctype.h>
2323

24-
#define DO_TEST(mode, nopad, slen, fill, dlen, hash) \
25-
SKIP_BLOCK_IF(mode == 0xDEADBEAF, nopad ? 4 : 5, #mode " not supported") \
26-
{ \
27-
memset(src, fill, src_len= slen); \
28-
ok(my_aes_crypt(mode, nopad | ENCRYPTION_FLAG_ENCRYPT, \
29-
src, src_len, dst, &dst_len, \
30-
key, sizeof(key), iv, sizeof(iv)) == MY_AES_OK, \
31-
"encrypt " #mode " %u %s", src_len, nopad ? "nopad" : "pad"); \
32-
if (!nopad) \
33-
ok (dst_len == my_aes_get_size(mode, src_len), "my_aes_get_size");\
34-
my_md5(md5, (char*)dst, dst_len); \
35-
ok(dst_len == dlen && memcmp(md5, hash, sizeof(md5)) == 0, "md5"); \
36-
ok(my_aes_crypt(mode, nopad | ENCRYPTION_FLAG_DECRYPT, \
37-
dst, dst_len, ddst, &ddst_len, \
38-
key, sizeof(key), iv, sizeof(iv)) == MY_AES_OK, \
39-
"decrypt " #mode " %u", dst_len); \
40-
ok(ddst_len == src_len && memcmp(src, ddst, src_len) == 0, "memcmp"); \
24+
25+
/** Test streaming encryption, bytewise update.*/
26+
static int aes_crypt_bytewise(enum my_aes_mode mode, int flags, const unsigned char *src,
27+
unsigned int slen, unsigned char *dst, unsigned int *dlen,
28+
const unsigned char *key, unsigned int klen,
29+
const unsigned char *iv, unsigned int ivlen)
30+
{
31+
/* Allocate context on odd address on stack, in order to
32+
catch misalignment errors.*/
33+
void *ctx= (char *)alloca(MY_AES_CTX_SIZE+1)+1;
34+
35+
int res1, res2;
36+
uint d1= 0, d2;
37+
uint i;
38+
39+
if ((res1= my_aes_crypt_init(ctx, mode, flags, key, klen, iv, ivlen)))
40+
return res1;
41+
for (i= 0; i < slen; i++)
42+
{
43+
uint tmp_d1=0;
44+
res1= my_aes_crypt_update(ctx, src+i,1, dst, &tmp_d1);
45+
if (res1)
46+
return res1;
47+
d1+= tmp_d1;
48+
dst+= tmp_d1;
49+
}
50+
res2= my_aes_crypt_finish(ctx, dst, &d2);
51+
*dlen= d1 + d2;
52+
return res1 ? res1 : res2;
53+
}
54+
55+
56+
#ifndef HAVE_EncryptAes128Ctr
57+
const uint MY_AES_CTR=0xDEADBEAF;
58+
#endif
59+
#ifndef HAVE_EncryptAes128Gcm
60+
const uint MY_AES_GCM=0xDEADBEAF;
61+
#endif
62+
63+
#define MY_AES_UNSUPPORTED(x) (x == 0xDEADBEAF)
64+
65+
static void do_test(uint mode, const char *mode_str, int nopad, uint slen,
66+
char fill, size_t dlen, const char *hash)
67+
{
68+
uchar key[16]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6};
69+
uchar iv[16]= {2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7};
70+
uchar src[1000], dst[1100], dst2[1100], ddst[1000];
71+
uchar md5[MY_MD5_HASH_SIZE];
72+
uint src_len, dst_len, dst_len2, ddst_len;
73+
int result;
74+
75+
if (MY_AES_UNSUPPORTED(mode))
76+
{
77+
skip(nopad?7:6, "%s not supported", mode_str);
78+
return;
79+
}
80+
memset(src, fill, src_len= slen);
81+
result= my_aes_crypt(mode, nopad | ENCRYPTION_FLAG_ENCRYPT, src, src_len,
82+
dst, &dst_len, key, sizeof(key), iv, sizeof(iv));
83+
ok(result == MY_AES_OK, "encrypt %s %u %s", mode_str, src_len,
84+
nopad ? "nopad" : "pad");
85+
86+
if (nopad)
87+
{
88+
result= aes_crypt_bytewise(mode, nopad | ENCRYPTION_FLAG_ENCRYPT, src,
89+
src_len, dst2, &dst_len2, key, sizeof(key),
90+
iv, sizeof(iv));
91+
ok(result == MY_AES_OK, "encrypt bytewise %s %u", mode_str, src_len);
92+
/* Compare with non-bytewise encryption result*/
93+
ok(dst_len == dst_len2 && memcmp(dst, dst2, dst_len) == 0,
94+
"memcmp bytewise %s %u", mode_str, src_len);
95+
}
96+
else
97+
{
98+
int dst_len_real= my_aes_get_size(mode, src_len);
99+
ok(dst_len_real= dst_len, "my_aes_get_size");
41100
}
101+
my_md5(md5, (char *) dst, dst_len);
102+
ok(dst_len == dlen, "md5 len");
103+
ok(memcmp(md5, hash, sizeof(md5)) == 0, "md5");
104+
result= my_aes_crypt(mode, nopad | ENCRYPTION_FLAG_DECRYPT,
105+
dst, dst_len, ddst, &ddst_len, key, sizeof(key), iv,
106+
sizeof(iv));
107+
108+
ok(result == MY_AES_OK, "decrypt %s %u", mode_str, dst_len);
109+
ok(ddst_len == src_len && memcmp(src, ddst, src_len) == 0, "memcmp");
110+
}
42111

43-
#define DO_TEST_P(M,S,F,D,H) DO_TEST(M,0,S,F,D,H)
44-
#define DO_TEST_N(M,S,F,D,H) DO_TEST(M,ENCRYPTION_FLAG_NOPAD,S,F,D,H)
112+
#define DO_TEST_P(M, S, F, D, H) do_test(M, #M, 0, S, F, D, H)
113+
#define DO_TEST_N(M, S, F, D, H) do_test(M, #M, ENCRYPTION_FLAG_NOPAD, S, F, D, H)
45114

46115
/* useful macro for debugging */
47116
#define PRINT_MD5() \
@@ -53,25 +122,15 @@
53122
printf("\"\n"); \
54123
} while(0);
55124

56-
#ifndef HAVE_EncryptAes128Ctr
57-
const uint MY_AES_CTR=0xDEADBEAF;
58-
#endif
59-
#ifndef HAVE_EncryptAes128Gcm
60-
const uint MY_AES_GCM=0xDEADBEAF;
61-
#endif
62125

63126
int
64127
main(int argc __attribute__((unused)),char *argv[])
65128
{
66-
uchar key[16]= {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6};
67-
uchar iv[16]= {2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7};
68-
uchar src[1000], dst[1100], ddst[1000];
69-
uchar md5[MY_MD5_HASH_SIZE];
70-
uint src_len, dst_len, ddst_len;
71129

72130
MY_INIT(argv[0]);
73131

74-
plan(87);
132+
plan(122);
133+
75134
DO_TEST_P(MY_AES_ECB, 200, '.', 208, "\xd8\x73\x8e\x3a\xbc\x66\x99\x13\x7f\x90\x23\x52\xee\x97\x6f\x9a");
76135
DO_TEST_P(MY_AES_ECB, 128, '?', 144, "\x19\x58\x33\x85\x4c\xaa\x7f\x06\xd1\xb2\xec\xd7\xb7\x6a\xa9\x5b");
77136
DO_TEST_P(MY_AES_CBC, 159, '%', 160, "\x4b\x03\x18\x3d\xf1\xa7\xcd\xa1\x46\xb3\xc6\x8a\x92\xc0\x0f\xc9");

0 commit comments

Comments
 (0)