Commit 4783b2e1 authored by Georgi Kodinov's avatar Georgi Kodinov

Bug #35087: Inserting duplicate values at one time with DES_ENCRYPT leads

  to wrong results
      
3 problems found with DES_ENCRYPT/DES_DECRYPT :

1. The max length was not calculated properly. Fixed in fix_length_and_dec()
2. DES_ENCRYPT had a side effect of sometimes reallocating and changing 
the value of its argument. Fixed by explicitly pre-allocating the necessary
space to pad the argument with trailing '*' (stars) when calculating the 
DES digest.
3. in DES_ENCRYPT the string buffer for the result value was not 
reallocated to the correct size and only string length was assigned to it. 
Fixed by making sure there's enough space to hold the result.
parent 4fbfa8db
select des_encrypt('hello'); select des_encrypt('hello');
des_encrypt('hello') des_encrypt('hello')
€Ö2nV“Ø} €Ö2nV“Ø}
#
# Bug #11643: des_encrypt() causes server to die
#
CREATE TABLE t1 (des VARBINARY(200) NOT NULL DEFAULT '') ENGINE=MyISAM;
INSERT INTO t1 VALUES ('1234'), ('12345'), ('123456'), ('1234567');
UPDATE t1 SET des=DES_ENCRYPT('1234');
SELECT LENGTH(des) FROM t1;
LENGTH(des)
9
9
9
9
SELECT DES_DECRYPT(des) FROM t1;
DES_DECRYPT(des)
1234
1234
1234
1234
SELECT
LENGTH(DES_ENCRYPT('1234')),
LENGTH(DES_ENCRYPT('12345')),
LENGTH(DES_ENCRYPT('123456')),
LENGTH(DES_ENCRYPT('1234567'));
LENGTH(DES_ENCRYPT('1234')) LENGTH(DES_ENCRYPT('12345')) LENGTH(DES_ENCRYPT('123456')) LENGTH(DES_ENCRYPT('1234567'))
9 9 9 9
SELECT
DES_DECRYPT(DES_ENCRYPT('1234')),
DES_DECRYPT(DES_ENCRYPT('12345')),
DES_DECRYPT(DES_ENCRYPT('123456')),
DES_DECRYPT(DES_ENCRYPT('1234567'));
DES_DECRYPT(DES_ENCRYPT('1234')) DES_DECRYPT(DES_ENCRYPT('12345')) DES_DECRYPT(DES_ENCRYPT('123456')) DES_DECRYPT(DES_ENCRYPT('1234567'))
1234 12345 123456 1234567
DROP TABLE t1;
End of 5.0 tests
...@@ -9,3 +9,31 @@ ...@@ -9,3 +9,31 @@
select des_encrypt('hello'); select des_encrypt('hello');
# End of 4.1 tests # End of 4.1 tests
--echo #
--echo # Bug #11643: des_encrypt() causes server to die
--echo #
CREATE TABLE t1 (des VARBINARY(200) NOT NULL DEFAULT '') ENGINE=MyISAM;
INSERT INTO t1 VALUES ('1234'), ('12345'), ('123456'), ('1234567');
UPDATE t1 SET des=DES_ENCRYPT('1234');
SELECT LENGTH(des) FROM t1;
SELECT DES_DECRYPT(des) FROM t1;
SELECT
LENGTH(DES_ENCRYPT('1234')),
LENGTH(DES_ENCRYPT('12345')),
LENGTH(DES_ENCRYPT('123456')),
LENGTH(DES_ENCRYPT('1234567'));
SELECT
DES_DECRYPT(DES_ENCRYPT('1234')),
DES_DECRYPT(DES_ENCRYPT('12345')),
DES_DECRYPT(DES_ENCRYPT('123456')),
DES_DECRYPT(DES_ENCRYPT('1234567'));
DROP TABLE t1;
--Echo End of 5.0 tests
...@@ -473,17 +473,21 @@ String *Item_func_des_encrypt::val_str(String *str) ...@@ -473,17 +473,21 @@ String *Item_func_des_encrypt::val_str(String *str)
string marking change of string length. string marking change of string length.
*/ */
tail= (8-(res_length) % 8); // 1..8 marking extra length tail= 8 - (res_length % 8); // 1..8 marking extra length
res_length+=tail; res_length+=tail;
tmp_arg.realloc(res_length);
tmp_arg.length(0);
tmp_arg.append(res->ptr(), res->length());
code= ER_OUT_OF_RESOURCES; code= ER_OUT_OF_RESOURCES;
if (tail && res->append(append_str, tail) || tmp_value.alloc(res_length+1)) if (tmp_arg.append(append_str, tail) || tmp_value.alloc(res_length+1))
goto error; goto error;
(*res)[res_length-1]=tail; // save extra length tmp_arg[res_length-1]=tail; // save extra length
tmp_value.realloc(res_length+1);
tmp_value.length(res_length+1); tmp_value.length(res_length+1);
tmp_value[0]=(char) (128 | key_number); tmp_value[0]=(char) (128 | key_number);
// Real encryption // Real encryption
bzero((char*) &ivec,sizeof(ivec)); bzero((char*) &ivec,sizeof(ivec));
DES_ede3_cbc_encrypt((const uchar*) (res->ptr()), DES_ede3_cbc_encrypt((const uchar*) (tmp_arg.ptr()),
(uchar*) (tmp_value.ptr()+1), (uchar*) (tmp_value.ptr()+1),
res_length, res_length,
&keyschedule.ks1, &keyschedule.ks1,
......
...@@ -306,13 +306,17 @@ class Item_func_old_password :public Item_str_func ...@@ -306,13 +306,17 @@ class Item_func_old_password :public Item_str_func
class Item_func_des_encrypt :public Item_str_func class Item_func_des_encrypt :public Item_str_func
{ {
String tmp_value; String tmp_value,tmp_arg;
public: public:
Item_func_des_encrypt(Item *a) :Item_str_func(a) {} Item_func_des_encrypt(Item *a) :Item_str_func(a) {}
Item_func_des_encrypt(Item *a, Item *b): Item_str_func(a,b) {} Item_func_des_encrypt(Item *a, Item *b): Item_str_func(a,b) {}
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec() void fix_length_and_dec()
{ maybe_null=1; max_length = args[0]->max_length+8; } {
maybe_null=1;
/* 9 = MAX ((8- (arg_len % 8)) + 1) */
max_length = args[0]->max_length + 9;
}
const char *func_name() const { return "des_encrypt"; } const char *func_name() const { return "des_encrypt"; }
}; };
...@@ -323,7 +327,12 @@ class Item_func_des_decrypt :public Item_str_func ...@@ -323,7 +327,12 @@ class Item_func_des_decrypt :public Item_str_func
Item_func_des_decrypt(Item *a) :Item_str_func(a) {} Item_func_des_decrypt(Item *a) :Item_str_func(a) {}
Item_func_des_decrypt(Item *a, Item *b): Item_str_func(a,b) {} Item_func_des_decrypt(Item *a, Item *b): Item_str_func(a,b) {}
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec() { maybe_null=1; max_length = args[0]->max_length; } void fix_length_and_dec()
{
maybe_null=1;
/* 9 = MAX ((8- (arg_len % 8)) + 1) */
max_length = args[0]->max_length - 9;
}
const char *func_name() const { return "des_decrypt"; } const char *func_name() const { return "des_decrypt"; }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment