Skip to content

Commit e009500

Browse files
committed
Bug #18295445: BACKPORT aes_encrypt/decrypt block mode and key length extensions to 5.6
This is a backport of WL#6781 to 5.6.
1 parent 4a85263 commit e009500

35 files changed

+3185
-364
lines changed

client/mysql_config_editor.cc

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
2+
Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License as published by
@@ -776,7 +776,7 @@ static my_bool check_and_create_login_file(void)
776776
{
777777
verbose_msg("File exists.\n");
778778

779-
file_size= stat_info.st_size;
779+
file_size= (size_t) stat_info.st_size;
780780

781781
#ifdef _WIN32
782782
if (1)
@@ -943,7 +943,7 @@ static void mask_password_and_print(char *buf)
943943
static void remove_options(DYNAMIC_STRING *file_buf, const char *path_name)
944944
{
945945
/* If nope of the options are specified remove the entire path. */
946-
if (!opt_remove_host && !opt_remove_pass && !opt_remove_user
946+
if (!opt_remove_host && !opt_remove_pass && !opt_remove_user
947947
&& !opt_remove_socket && !opt_remove_port)
948948
{
949949
remove_login_path(file_buf, path_name);
@@ -1295,7 +1295,7 @@ static int read_and_decrypt_file(DYNAMIC_STRING *file_buf)
12951295
12961296
@param plain [in] Plain text to be encrypted.
12971297
@param plain_len [in] Length of the plain text.
1298-
@param cipher [in] Encrypted cipher text.
1298+
@param cipher [out] Encrypted cipher text.
12991299
13001300
@return -1 if error encountered,
13011301
length encrypted, otherwise.
@@ -1306,9 +1306,12 @@ static int encrypt_buffer(const char *plain, int plain_len, char cipher[])
13061306
DBUG_ENTER("encrypt_buffer");
13071307
int aes_len;
13081308

1309-
aes_len= my_aes_get_size(plain_len);
1309+
aes_len= my_aes_get_size(plain_len, my_aes_128_ecb);
13101310

1311-
if (my_aes_encrypt(plain, plain_len, cipher, my_key, LOGIN_KEY_LEN) == aes_len)
1311+
if (my_aes_encrypt((const unsigned char *) plain, plain_len,
1312+
(unsigned char *) cipher,
1313+
(const unsigned char *) my_key, LOGIN_KEY_LEN,
1314+
my_aes_128_ecb, NULL) == aes_len)
13121315
DBUG_RETURN(aes_len);
13131316

13141317
verbose_msg("Error! Couldn't encrypt the buffer.\n");
@@ -1321,7 +1324,7 @@ static int encrypt_buffer(const char *plain, int plain_len, char cipher[])
13211324
13221325
@param cipher [in] Cipher text to be decrypted.
13231326
@param cipher_len [in] Length of the cipher text.
1324-
@param plain [in] Decrypted plain text.
1327+
@param plain [out] Decrypted plain text.
13251328
13261329
@return -1 if error encountered,
13271330
length decrypted, otherwise.
@@ -1332,8 +1335,11 @@ static int decrypt_buffer(const char *cipher, int cipher_len, char plain[])
13321335
DBUG_ENTER("decrypt_buffer");
13331336
int aes_length;
13341337

1335-
if ((aes_length= my_aes_decrypt(cipher, cipher_len, (char *) plain,
1336-
my_key, LOGIN_KEY_LEN)) > 0)
1338+
if ((aes_length= my_aes_decrypt((const unsigned char *) cipher, cipher_len,
1339+
(unsigned char *) plain,
1340+
(const unsigned char *) my_key,
1341+
LOGIN_KEY_LEN,
1342+
my_aes_128_ecb, NULL)) > 0)
13371343
DBUG_RETURN(aes_length);
13381344

13391345
verbose_msg("Error! Couldn't decrypt the buffer.\n");

include/my_aes.h

Lines changed: 91 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef MY_AES_INCLUDED
22
#define MY_AES_INCLUDED
33

4-
/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
4+
/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
55
66
This program is free software; you can redistribute it and/or modify
77
it under the terms of the GNU General Public License as published by
@@ -22,46 +22,108 @@
2222

2323
C_MODE_START
2424

25-
#define AES_KEY_LENGTH 128 /* Must be 128 192 or 256 */
26-
27-
/*
28-
my_aes_encrypt - Crypt buffer with AES encryption algorithm.
29-
source - Pointer to data for encryption
30-
source_length - size of encryption data
31-
dest - buffer to place encrypted data (must be large enough)
32-
key - Key to be used for encryption
33-
kel_length - Length of the key. Will handle keys of any length
25+
/** AES IV size is 16 bytes for all supported ciphers except ECB */
26+
#define MY_AES_IV_SIZE 16
27+
28+
29+
/** Supported AES cipher/block mode combos */
30+
enum my_aes_opmode
31+
{
32+
my_aes_128_ecb,
33+
my_aes_192_ecb,
34+
my_aes_256_ecb,
35+
my_aes_128_cbc,
36+
my_aes_192_cbc,
37+
my_aes_256_cbc,
38+
#ifndef HAVE_YASSL
39+
my_aes_128_cfb1,
40+
my_aes_192_cfb1,
41+
my_aes_256_cfb1,
42+
my_aes_128_cfb8,
43+
my_aes_192_cfb8,
44+
my_aes_256_cfb8,
45+
my_aes_128_cfb128,
46+
my_aes_192_cfb128,
47+
my_aes_256_cfb128,
48+
my_aes_128_ofb,
49+
my_aes_192_ofb,
50+
my_aes_256_ofb,
51+
#endif
52+
};
53+
54+
#define MY_AES_BEGIN my_aes_128_ecb
55+
#ifdef HAVE_YASSL
56+
#define MY_AES_END my_aes_256_cbc
57+
#else
58+
#define MY_AES_END my_aes_256_ofb
59+
#endif
60+
61+
/* If bad data discovered during decoding */
62+
#define MY_AES_BAD_DATA -1
63+
64+
/** String representations of the supported AES modes. Keep in sync with my_aes_opmode */
65+
extern const char *my_aes_opmode_names[];
66+
67+
/**
68+
Encrypt a buffer using AES
69+
70+
@param source [in] Pointer to data for encryption
71+
@param source_length [in] Size of encryption data
72+
@param dest [out] Buffer to place encrypted data (must be large enough)
73+
@param key [in] Key to be used for encryption
74+
@param key_length [in] Length of the key. Will handle keys of any length
75+
@param mode [in] encryption mode
76+
@param iv [in] 16 bytes initialization vector if needed. Otherwise NULL
77+
@return size of encrypted data, or negative in case of error
78+
*/
3479

35-
returns - size of encrypted data, or negative in case of error.
80+
int my_aes_encrypt(const unsigned char *source, uint32 source_length,
81+
unsigned char *dest,
82+
const unsigned char *key, uint32 key_length,
83+
enum my_aes_opmode mode, const unsigned char *iv);
84+
85+
/**
86+
Decrypt an AES encrypted buffer
87+
88+
@param source Pointer to data for decryption
89+
@param source_length size of encrypted data
90+
@param dest buffer to place decrypted data (must be large enough)
91+
@param key Key to be used for decryption
92+
@param key_length Length of the key. Will handle keys of any length
93+
@param mode encryption mode
94+
@param iv 16 bytes initialization vector if needed. Otherwise NULL
95+
@return size of original data.
3696
*/
3797

38-
int my_aes_encrypt(const char *source, int source_length, char *dest,
39-
const char *key, int key_length);
4098

41-
/*
42-
my_aes_decrypt - DeCrypt buffer with AES encryption algorithm.
43-
source - Pointer to data for decryption
44-
source_length - size of encrypted data
45-
dest - buffer to place decrypted data (must be large enough)
46-
key - Key to be used for decryption
47-
kel_length - Length of the key. Will handle keys of any length
99+
int my_aes_decrypt(const unsigned char *source, uint32 source_length,
100+
unsigned char *dest,
101+
const unsigned char *key, uint32 key_length,
102+
enum my_aes_opmode mode, const unsigned char *iv);
48103

49-
returns - size of original data, or negative in case of error.
104+
/**
105+
Calculate the size of a buffer large enough for encrypted data
106+
107+
@param source_length length of data to be encrypted
108+
@param mode encryption mode
109+
@return size of buffer required to store encrypted data
50110
*/
51111

112+
int my_aes_get_size(uint32 source_length, enum my_aes_opmode mode);
52113

53-
int my_aes_decrypt(const char *source, int source_length, char *dest,
54-
const char *key, int key_length);
114+
/**
115+
Return true if the AES cipher and block mode requires an IV
55116
56-
/*
57-
my_aes_get_size - get size of buffer which will be large enough for encrypted
58-
data
59-
source_length - length of data to be encrypted
117+
SYNOPSIS
118+
my_aes_needs_iv()
119+
@param mode encryption mode
60120
61-
returns - size of buffer required to store encrypted data
121+
@retval TRUE IV needed
122+
@retval FALSE IV not needed
62123
*/
63124

64-
int my_aes_get_size(int source_length);
125+
my_bool my_aes_needs_iv(my_aes_opmode opmode);
126+
65127

66128
C_MODE_END
67129

include/my_rnd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ extern "C" {
3030
#endif
3131

3232
double my_rnd_ssl(struct rand_struct *rand_st);
33+
int my_rand_buffer(unsigned char *buffer, size_t buffer_size);
3334

3435
#ifdef __cplusplus
3536
}

mysql-test/include/func_aes_block.inc

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#
2+
# Parameters:
3+
#
4+
# $block_mode
5+
6+
7+
--echo #### $block_mode
8+
9+
SET @IVA=REPEAT('a', 16);
10+
SET @IVB=REPEAT('b', 16);
11+
SET @KEY1=REPEAT('c', 16);
12+
SET @KEY2=REPEAT('d', 16);
13+
14+
15+
--echo #### 128-$block_mode
16+
17+
eval SET SESSION block_encryption_mode="aes-128-$block_mode";
18+
19+
--echo # must throw an error without an IV
20+
--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
21+
SELECT AES_ENCRYPT('a', @KEY1);
22+
23+
--echo block mode dependent. Must be non-0 and non-null
24+
SELECT LENGTH(AES_ENCRYPT('a', @KEY1, @IVA));
25+
26+
--echo block mode dependent
27+
SELECT TO_BASE64(AES_ENCRYPT('a', @KEY1, @IVA));
28+
29+
--echo # must be equal
30+
SELECT 'a' = AES_DECRYPT(AES_ENCRYPT('a', @KEY1, @IVA), @KEY1, @IVA);
31+
32+
--echo # must not be equal
33+
SELECT 'a' = AES_DECRYPT(AES_ENCRYPT('a',@KEY1, @IVA), @KEY1, @IVB);
34+
SELECT 'a' = AES_DECRYPT(AES_ENCRYPT('a',@KEY1, @IVA), @KEY2, @IVA);
35+
SELECT 'a' = AES_DECRYPT(AES_ENCRYPT('b',@KEY1, @IVA), @KEY1, @IVA);
36+
37+
38+
--echo #### 192-$block_mode
39+
40+
eval SET SESSION block_encryption_mode="aes-192-$block_mode";
41+
42+
--echo # must throw an error without an IV
43+
--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
44+
SELECT AES_ENCRYPT('a', @KEY1);
45+
46+
--echo # must be equal
47+
SELECT 'a' = AES_DECRYPT(AES_ENCRYPT('a',@KEY1, @IVA), @KEY1, @IVA);
48+
49+
--echo # must not be equal
50+
SELECT 'a' = AES_DECRYPT(AES_ENCRYPT('a',@KEY1, @IVA), @KEY1, @IVB);
51+
SELECT 'a' = AES_DECRYPT(AES_ENCRYPT('a',@KEY1, @IVA), @KEY2, @IVA);
52+
SELECT 'a' = AES_DECRYPT(AES_ENCRYPT('b',@KEY1, @IVA), @KEY1, @IVA);
53+
54+
55+
--echo #### 256-$block_mode
56+
57+
eval SET SESSION block_encryption_mode="aes-256-$block_mode";
58+
59+
--echo # must throw an error without an IV
60+
--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
61+
SELECT AES_ENCRYPT('a', @KEY1);
62+
63+
--echo # must be equal
64+
SELECT 'a' = AES_DECRYPT(AES_ENCRYPT('a',@KEY1, @IVA), @KEY1, @IVA);
65+
66+
--echo # must not be equal
67+
SELECT 'a' = AES_DECRYPT(AES_ENCRYPT('a',@KEY1, @IVA), @KEY1, @IVB);
68+
SELECT 'a' = AES_DECRYPT(AES_ENCRYPT('a',@KEY1, @IVA), @KEY2, @IVA);
69+
SELECT 'a' = AES_DECRYPT(AES_ENCRYPT('b',@KEY1, @IVA), @KEY1, @IVA);
70+
71+
SET SESSION block_encryption_mode=DEFAULT;
72+
73+
74+
--echo #### 128, 192 and 256 bit $block_mode
75+
76+
77+
eval CREATE TABLE aes_$block_mode(a VARCHAR(128), b128 VARCHAR(144),
78+
b192 VARCHAR(144), b256 CHAR(144));
79+
eval INSERT INTO aes_$block_mode (a) VALUES (REPEAT('a', 128));
80+
eval INSERT INTO aes_$block_mode (a) VALUES (REPEAT(0x00313233, 32));
81+
82+
eval SET SESSION block_encryption_mode="aes-128-$block_mode";
83+
eval UPDATE aes_$block_mode SET b128 = AES_ENCRYPT(a, @KEY1, @IVA);
84+
85+
eval SET SESSION block_encryption_mode="aes-192-$block_mode";
86+
eval UPDATE aes_$block_mode SET b192 = AES_ENCRYPT(a, @KEY1, @IVA);
87+
88+
eval SET SESSION block_encryption_mode="aes-256-$block_mode";
89+
eval UPDATE aes_$block_mode SET b256 = AES_ENCRYPT(a, @KEY1, @IVA);
90+
91+
--echo # must return 0
92+
eval SELECT COUNT(*) FROM aes_$block_mode WHERE b128 = b192 OR B192 = b256 OR b128=b256;
93+
94+
eval SET SESSION block_encryption_mode="aes-256-$block_mode";
95+
96+
--echo # must return 2
97+
eval SELECT COUNT(*) FROM aes_$block_mode WHERE a = AES_DECRYPT(b256, @KEY1, @IVA);
98+
99+
--echo # must return 0
100+
eval SELECT COUNT(*) FROM aes_$block_mode WHERE a = AES_DECRYPT(b256, 'b', @IVA);
101+
102+
--echo # must return 0
103+
eval SELECT COUNT(*) FROM aes_$block_mode WHERE a = AES_DECRYPT(b256, @KEY1, @IVB);
104+
105+
eval SET SESSION block_encryption_mode="aes-192-$block_mode";
106+
107+
--echo # must return 2
108+
eval SELECT COUNT(*) FROM aes_$block_mode WHERE a = AES_DECRYPT(b192, @KEY1, @IVA);
109+
110+
--echo # must return 0
111+
eval SELECT COUNT(*) FROM aes_$block_mode WHERE a = AES_DECRYPT(b192, @KEY2, @IVA);
112+
113+
--echo # must return 0
114+
eval SELECT COUNT(*) FROM aes_$block_mode WHERE a = AES_DECRYPT(b256, @KEY1, @IVB);
115+
116+
eval SET SESSION block_encryption_mode="aes-128-$block_mode";
117+
118+
--echo # must return 2
119+
eval SELECT COUNT(*) FROM aes_$block_mode WHERE a = AES_DECRYPT(b128, @KEY1, @IVA);
120+
121+
--echo # must return 0
122+
eval SELECT COUNT(*) FROM aes_$block_mode WHERE a = AES_DECRYPT(b128, @KEY2, @IVA);
123+
124+
--echo # must return 0
125+
eval SELECT COUNT(*) FROM aes_$block_mode WHERE a = AES_DECRYPT(b256, @KEY2, @IVB);
126+
127+
128+
SET SESSION block_encryption_mode=DEFAULT;
129+
eval DROP TABLE aes_$block_mode;

0 commit comments

Comments
 (0)