mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-31474 KDF() function
KDF(key_str, salt [, {info | iterations} [, kdf_name [, width ]]]) kdf_name is "hkdf" or "pbkdf2_hmac" (default). width (in bits) can be any number divisible by 8, by default it's taken from @@block_encryption_mode iterations must be positive, and is 1000 by default OpenSSL 1.0 doesn't support HKDF, so it'll return NULL. This OpenSSL version is still used in SLES 12 and CentOS 7
This commit is contained in:
@@ -60,6 +60,7 @@ MACRO (MYSQL_USE_BUNDLED_SSL)
|
||||
SET(HAVE_EncryptAes128Ctr ON CACHE INTERNAL "wolfssl does support AES-CTR")
|
||||
SET(HAVE_EncryptAes128Gcm OFF CACHE INTERNAL "wolfssl does not support AES-GCM")
|
||||
SET(HAVE_X509_check_host ON CACHE INTERNAL "wolfssl does support X509_check_host")
|
||||
SET(HAVE_hkdf ON CACHE INTERNAL "wolfssl does support EVP_PKEY API")
|
||||
CHANGE_SSL_SETTINGS("bundled")
|
||||
ADD_SUBDIRECTORY(extra/wolfssl)
|
||||
MESSAGE_ONCE(SSL_LIBRARIES "SSL_LIBRARIES = ${SSL_LIBRARIES}")
|
||||
@@ -158,6 +159,8 @@ MACRO (MYSQL_CHECK_SSL)
|
||||
HAVE_EncryptAes128Gcm)
|
||||
CHECK_SYMBOL_EXISTS(X509_check_host "openssl/x509v3.h"
|
||||
HAVE_X509_check_host)
|
||||
CHECK_SYMBOL_EXISTS(EVP_PKEY_CTX_set_hkdf_md "string.h;stdarg.h;openssl/kdf.h"
|
||||
HAVE_hkdf)
|
||||
SET(CMAKE_REQUIRED_INCLUDES)
|
||||
SET(CMAKE_REQUIRED_LIBRARIES)
|
||||
SET(CMAKE_REQUIRED_DEFINITIONS)
|
||||
|
@@ -499,6 +499,7 @@
|
||||
#cmakedefine HAVE_COMPRESS 1
|
||||
#cmakedefine HAVE_EncryptAes128Ctr 1
|
||||
#cmakedefine HAVE_EncryptAes128Gcm 1
|
||||
#cmakedefine HAVE_hkdf 1
|
||||
|
||||
/*
|
||||
Stuff that always need to be defined (compile breaks without it)
|
||||
|
64
mysql-test/main/func_kdf,old.rdiff
Normal file
64
mysql-test/main/func_kdf,old.rdiff
Normal file
@@ -0,0 +1,64 @@
|
||||
--- main/func_kdf.result
|
||||
+++ main/func_kdf.reject
|
||||
@@ -21,10 +21,14 @@
|
||||
48565B49B42FBF88537AFA1D4C0FA2C6
|
||||
select hex(kdf('foo', 'bar', 'info', 'hkdf'));
|
||||
hex(kdf('foo', 'bar', 'info', 'hkdf'))
|
||||
-710583081D40A55F0B573A76E02D8975
|
||||
+NULL
|
||||
+Warnings:
|
||||
+Warning 1235 This version of MariaDB doesn't yet support 'kdf(..., 'hkdf')'
|
||||
select hex(kdf('foo', 'bar', 'infa', 'hkdf'));
|
||||
hex(kdf('foo', 'bar', 'infa', 'hkdf'))
|
||||
-612875F859CFB4EE0DFEFF9F2A18E836
|
||||
+NULL
|
||||
+Warnings:
|
||||
+Warning 1235 This version of MariaDB doesn't yet support 'kdf(..., 'hkdf')'
|
||||
select hex(kdf('foo', 'bar', 'info', 'pbkdf2_hmac'));
|
||||
hex(kdf('foo', 'bar', 'info', 'pbkdf2_hmac'))
|
||||
NULL
|
||||
@@ -55,7 +59,9 @@
|
||||
NULL
|
||||
select hex(kdf('foo', 'bar', NULL, 'hkdf'));
|
||||
hex(kdf('foo', 'bar', NULL, 'hkdf'))
|
||||
-4AFD0088E56CAF7CB5C94F6C101D58D5
|
||||
+NULL
|
||||
+Warnings:
|
||||
+Warning 1235 This version of MariaDB doesn't yet support 'kdf(..., 'hkdf')'
|
||||
select hex(kdf('foo', 'bar', NULL, 'pbkdf2_hmac'));
|
||||
hex(kdf('foo', 'bar', NULL, 'pbkdf2_hmac'))
|
||||
NULL
|
||||
@@ -81,10 +87,14 @@
|
||||
set @@block_encryption_mode='aes-192-cbc';
|
||||
select hex(kdf('foo', 'bar', 'info', 'hkdf'));
|
||||
hex(kdf('foo', 'bar', 'info', 'hkdf'))
|
||||
-710583081D40A55F0B573A76E02D8975AA11A4595954C0A1
|
||||
+NULL
|
||||
+Warnings:
|
||||
+Warning 1235 This version of MariaDB doesn't yet support 'kdf(..., 'hkdf')'
|
||||
select hex(kdf('foo', 'bar', 'info', 'hkdf', 256));
|
||||
hex(kdf('foo', 'bar', 'info', 'hkdf', 256))
|
||||
-710583081D40A55F0B573A76E02D8975AA11A4595954C0A1487D6D33ABAB93C3
|
||||
+NULL
|
||||
+Warnings:
|
||||
+Warning 1235 This version of MariaDB doesn't yet support 'kdf(..., 'hkdf')'
|
||||
select hex(kdf('foo', 'bar', 2000, 'pbkdf2_hmac'));
|
||||
hex(kdf('foo', 'bar', 2000, 'pbkdf2_hmac'))
|
||||
430D4780B57254EF39EE13CE53DB381A552151AA62A9FA92
|
||||
@@ -110,10 +120,14 @@
|
||||
Warning 3047 Invalid argument error: 0 in function kdf.
|
||||
select length(kdf('foo', 'bar', 'info', 'hkdf', 32768));
|
||||
length(kdf('foo', 'bar', 'info', 'hkdf', 32768))
|
||||
-4096
|
||||
+NULL
|
||||
+Warnings:
|
||||
+Warning 1235 This version of MariaDB doesn't yet support 'kdf(..., 'hkdf')'
|
||||
select length(kdf('foo', 'bar', 'info', 'hkdf', 65536));
|
||||
length(kdf('foo', 'bar', 'info', 'hkdf', 65536))
|
||||
-8192
|
||||
+NULL
|
||||
+Warnings:
|
||||
+Warning 1235 This version of MariaDB doesn't yet support 'kdf(..., 'hkdf')'
|
||||
select length(kdf('foo', 'bar', 'info', 'hkdf', 65537));
|
||||
length(kdf('foo', 'bar', 'info', 'hkdf', 65537))
|
||||
NULL
|
4
mysql-test/main/func_kdf.combinations
Normal file
4
mysql-test/main/func_kdf.combinations
Normal file
@@ -0,0 +1,4 @@
|
||||
[new]
|
||||
|
||||
[old]
|
||||
# remove when no longer building with OpenSSL 1.0
|
158
mysql-test/main/func_kdf.result
Normal file
158
mysql-test/main/func_kdf.result
Normal file
@@ -0,0 +1,158 @@
|
||||
#
|
||||
# MDEV-31474 KDF() function
|
||||
#
|
||||
select hex(kdf('foo', 'bar'));
|
||||
hex(kdf('foo', 'bar'))
|
||||
76BA6DEC5C3F6A60704D730A2A4BAA1C
|
||||
select hex(kdf('foo', 'bar'));
|
||||
hex(kdf('foo', 'bar'))
|
||||
76BA6DEC5C3F6A60704D730A2A4BAA1C
|
||||
select hex(kdf('faa', 'bar'));
|
||||
hex(kdf('faa', 'bar'))
|
||||
62A8C6FD3E6FDA7ECE6D37CF1C95E3CC
|
||||
select hex(kdf('foo', 'bor'));
|
||||
hex(kdf('foo', 'bor'))
|
||||
F0FE3B0884C9733A520EC8C2EE711137
|
||||
select hex(kdf('foo', 'bar', 10));
|
||||
hex(kdf('foo', 'bar', 10))
|
||||
1D25A9E01C2078FF10DECEC874B3F21E
|
||||
select hex(kdf('foo', 'bar', 11));
|
||||
hex(kdf('foo', 'bar', 11))
|
||||
48565B49B42FBF88537AFA1D4C0FA2C6
|
||||
select hex(kdf('foo', 'bar', 'info', 'hkdf'));
|
||||
hex(kdf('foo', 'bar', 'info', 'hkdf'))
|
||||
710583081D40A55F0B573A76E02D8975
|
||||
select hex(kdf('foo', 'bar', 'infa', 'hkdf'));
|
||||
hex(kdf('foo', 'bar', 'infa', 'hkdf'))
|
||||
612875F859CFB4EE0DFEFF9F2A18E836
|
||||
select hex(kdf('foo', 'bar', 'info', 'pbkdf2_hmac'));
|
||||
hex(kdf('foo', 'bar', 'info', 'pbkdf2_hmac'))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect INTEGER value: 'info'
|
||||
Warning 3047 Invalid argument error: 0 in function kdf.
|
||||
select hex(kdf('foo', 'bar', -1, 'pbkdf2_hmac'));
|
||||
hex(kdf('foo', 'bar', -1, 'pbkdf2_hmac'))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: -1 in function kdf.
|
||||
select hex(kdf('foo', 'bar', 0, 'pbkdf2_hmac'));
|
||||
hex(kdf('foo', 'bar', 0, 'pbkdf2_hmac'))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: 0 in function kdf.
|
||||
select hex(kdf('foo', 'bar', 1, 'pbkdf2_hmac'));
|
||||
hex(kdf('foo', 'bar', 1, 'pbkdf2_hmac'))
|
||||
DB658012DC3E52AEC1F4933C280B6E10
|
||||
select hex(kdf('foo', 'bar', 10, 'pbkdf2_hmac'));
|
||||
hex(kdf('foo', 'bar', 10, 'pbkdf2_hmac'))
|
||||
1D25A9E01C2078FF10DECEC874B3F21E
|
||||
select hex(kdf(NULL, 'bar'));
|
||||
hex(kdf(NULL, 'bar'))
|
||||
NULL
|
||||
select hex(kdf('foo', NULL));
|
||||
hex(kdf('foo', NULL))
|
||||
NULL
|
||||
select hex(kdf('foo', 'bar', NULL, 'hkdf'));
|
||||
hex(kdf('foo', 'bar', NULL, 'hkdf'))
|
||||
4AFD0088E56CAF7CB5C94F6C101D58D5
|
||||
select hex(kdf('foo', 'bar', NULL, 'pbkdf2_hmac'));
|
||||
hex(kdf('foo', 'bar', NULL, 'pbkdf2_hmac'))
|
||||
NULL
|
||||
select hex(kdf('foo', 'bar', 2000, NULL));
|
||||
hex(kdf('foo', 'bar', 2000, NULL))
|
||||
NULL
|
||||
select hex(kdf('foo', 'bar', 2000, 'foo'));
|
||||
hex(kdf('foo', 'bar', 2000, 'foo'))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: 'foo' in function kdf.
|
||||
select hex(kdf('foo', 'bar', 2000, '\n\n\n\0!!!'));
|
||||
hex(kdf('foo', 'bar', 2000, '\n\n\n\0!!!'))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: '
|
||||
|
||||
|
||||
\0000!!!' in function kdf.
|
||||
select hex(kdf('foo', 'bar', 1000, 'pbkdf2_hmac', NULL));
|
||||
hex(kdf('foo', 'bar', 1000, 'pbkdf2_hmac', NULL))
|
||||
NULL
|
||||
select hex(kdf('foo', 'bar', 1000, 'pbkdf2_hmac', -8));
|
||||
hex(kdf('foo', 'bar', 1000, 'pbkdf2_hmac', -8))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: -8 in function kdf.
|
||||
select hex(kdf('foo', 'bar', 1000, 'pbkdf2_hmac', 10));
|
||||
hex(kdf('foo', 'bar', 1000, 'pbkdf2_hmac', 10))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: 10 in function kdf.
|
||||
select hex(kdf('foo', 'bar', 1000, 'pbkdf2_hmac', 16));
|
||||
hex(kdf('foo', 'bar', 1000, 'pbkdf2_hmac', 16))
|
||||
76BA
|
||||
set @@block_encryption_mode='aes-192-cbc';
|
||||
select hex(kdf('foo', 'bar', 'info', 'hkdf'));
|
||||
hex(kdf('foo', 'bar', 'info', 'hkdf'))
|
||||
710583081D40A55F0B573A76E02D8975AA11A4595954C0A1
|
||||
select hex(kdf('foo', 'bar', 'info', 'hkdf', 256));
|
||||
hex(kdf('foo', 'bar', 'info', 'hkdf', 256))
|
||||
710583081D40A55F0B573A76E02D8975AA11A4595954C0A1487D6D33ABAB93C3
|
||||
select hex(kdf('foo', 'bar', 2000, 'pbkdf2_hmac'));
|
||||
hex(kdf('foo', 'bar', 2000, 'pbkdf2_hmac'))
|
||||
430D4780B57254EF39EE13CE53DB381A552151AA62A9FA92
|
||||
select hex(kdf('foo', 'bar', 2000, 'pbkdf2_hmac', 256));
|
||||
hex(kdf('foo', 'bar', 2000, 'pbkdf2_hmac', 256))
|
||||
430D4780B57254EF39EE13CE53DB381A552151AA62A9FA922B9949DF270AE10C
|
||||
set @key=kdf('password', 'salt', 2048);
|
||||
select hex(aes_encrypt('secret', @key, '1234123412341234'));
|
||||
hex(aes_encrypt('secret', @key, '1234123412341234'))
|
||||
9EED553CDDEE426D5635EF559E015ECA
|
||||
select aes_decrypt(x'9EED553CDDEE426D5635EF559E015ECA', @key, '1234123412341234');
|
||||
aes_decrypt(x'9EED553CDDEE426D5635EF559E015ECA', @key, '1234123412341234')
|
||||
secret
|
||||
select length(kdf('foo', 'bar', 'info', 'hkdf', -1));
|
||||
length(kdf('foo', 'bar', 'info', 'hkdf', -1))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: -1 in function kdf.
|
||||
select length(kdf('foo', 'bar', 'info', 'hkdf', 0));
|
||||
length(kdf('foo', 'bar', 'info', 'hkdf', 0))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: 0 in function kdf.
|
||||
select length(kdf('foo', 'bar', 'info', 'hkdf', 32768));
|
||||
length(kdf('foo', 'bar', 'info', 'hkdf', 32768))
|
||||
4096
|
||||
select length(kdf('foo', 'bar', 'info', 'hkdf', 65536));
|
||||
length(kdf('foo', 'bar', 'info', 'hkdf', 65536))
|
||||
8192
|
||||
select length(kdf('foo', 'bar', 'info', 'hkdf', 65537));
|
||||
length(kdf('foo', 'bar', 'info', 'hkdf', 65537))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: 65537 in function kdf.
|
||||
select length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', -1));
|
||||
length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', -1))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: -1 in function kdf.
|
||||
select length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', 0));
|
||||
length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', 0))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: 0 in function kdf.
|
||||
select length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', 32768));
|
||||
length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', 32768))
|
||||
4096
|
||||
select length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', 65536));
|
||||
length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', 65536))
|
||||
8192
|
||||
select length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', 65537));
|
||||
length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', 65537))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: 65537 in function kdf.
|
||||
#
|
||||
# End of 11.3 tests
|
||||
#
|
57
mysql-test/main/func_kdf.test
Normal file
57
mysql-test/main/func_kdf.test
Normal file
@@ -0,0 +1,57 @@
|
||||
--echo #
|
||||
--echo # MDEV-31474 KDF() function
|
||||
--echo #
|
||||
select hex(kdf('foo', 'bar'));
|
||||
select hex(kdf('foo', 'bar')); # same result every time
|
||||
select hex(kdf('faa', 'bar'));
|
||||
select hex(kdf('foo', 'bor'));
|
||||
|
||||
select hex(kdf('foo', 'bar', 10));
|
||||
select hex(kdf('foo', 'bar', 11));
|
||||
|
||||
select hex(kdf('foo', 'bar', 'info', 'hkdf'));
|
||||
select hex(kdf('foo', 'bar', 'infa', 'hkdf'));
|
||||
select hex(kdf('foo', 'bar', 'info', 'pbkdf2_hmac'));
|
||||
select hex(kdf('foo', 'bar', -1, 'pbkdf2_hmac'));
|
||||
select hex(kdf('foo', 'bar', 0, 'pbkdf2_hmac'));
|
||||
select hex(kdf('foo', 'bar', 1, 'pbkdf2_hmac'));
|
||||
select hex(kdf('foo', 'bar', 10, 'pbkdf2_hmac'));
|
||||
|
||||
select hex(kdf(NULL, 'bar'));
|
||||
select hex(kdf('foo', NULL));
|
||||
select hex(kdf('foo', 'bar', NULL, 'hkdf'));
|
||||
select hex(kdf('foo', 'bar', NULL, 'pbkdf2_hmac'));
|
||||
select hex(kdf('foo', 'bar', 2000, NULL));
|
||||
select hex(kdf('foo', 'bar', 2000, 'foo'));
|
||||
select hex(kdf('foo', 'bar', 2000, '\n\n\n\0!!!'));
|
||||
select hex(kdf('foo', 'bar', 1000, 'pbkdf2_hmac', NULL));
|
||||
select hex(kdf('foo', 'bar', 1000, 'pbkdf2_hmac', -8));
|
||||
select hex(kdf('foo', 'bar', 1000, 'pbkdf2_hmac', 10));
|
||||
select hex(kdf('foo', 'bar', 1000, 'pbkdf2_hmac', 16));
|
||||
|
||||
set @@block_encryption_mode='aes-192-cbc';
|
||||
select hex(kdf('foo', 'bar', 'info', 'hkdf'));
|
||||
select hex(kdf('foo', 'bar', 'info', 'hkdf', 256));
|
||||
select hex(kdf('foo', 'bar', 2000, 'pbkdf2_hmac'));
|
||||
select hex(kdf('foo', 'bar', 2000, 'pbkdf2_hmac', 256));
|
||||
|
||||
set @key=kdf('password', 'salt', 2048);
|
||||
select hex(aes_encrypt('secret', @key, '1234123412341234'));
|
||||
select aes_decrypt(x'9EED553CDDEE426D5635EF559E015ECA', @key, '1234123412341234');
|
||||
|
||||
select length(kdf('foo', 'bar', 'info', 'hkdf', -1));
|
||||
select length(kdf('foo', 'bar', 'info', 'hkdf', 0));
|
||||
select length(kdf('foo', 'bar', 'info', 'hkdf', 32768));
|
||||
select length(kdf('foo', 'bar', 'info', 'hkdf', 65536));
|
||||
select length(kdf('foo', 'bar', 'info', 'hkdf', 65537));
|
||||
|
||||
select length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', -1));
|
||||
select length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', 0));
|
||||
select length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', 32768));
|
||||
select length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', 65536));
|
||||
select length(kdf('foo', 'bar', 100, 'pbkdf2_hmac', 65537));
|
||||
|
||||
--echo #
|
||||
--echo # End of 11.3 tests
|
||||
--echo #
|
||||
|
@@ -84,6 +84,8 @@ sub skip_combinations {
|
||||
$skip{'main/ssl_7937.combinations'} = [ 'x509v3' ]
|
||||
unless $ssl_lib =~ /WolfSSL/ or $openssl_ver ge "1.0.2";
|
||||
|
||||
$skip{'main/func_kdf.combinations'} = [ $ssl_lib =~ /OpenSSL 1\.0\./ ? 'new' : 'old' ];
|
||||
|
||||
$skip{'main/ssl_verify_ip.test'} = 'x509v3 support required'
|
||||
unless $openssl_ver ge "1.0.2";
|
||||
|
||||
|
@@ -155,6 +155,20 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
class Create_func_kdf : public Create_native_func
|
||||
{
|
||||
public:
|
||||
virtual Item *create_native(THD *thd, const LEX_CSTRING *name,
|
||||
List<Item> *item_list);
|
||||
|
||||
static Create_func_kdf s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_kdf() = default;
|
||||
virtual ~Create_func_kdf() = default;
|
||||
};
|
||||
|
||||
|
||||
class Create_func_asin : public Create_func_arg1
|
||||
{
|
||||
public:
|
||||
@@ -2986,6 +3000,32 @@ Create_func_aes_decrypt::create_native(THD *thd, const LEX_CSTRING *name,
|
||||
}
|
||||
|
||||
|
||||
Create_func_kdf Create_func_kdf::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_kdf::create_native(THD *thd, const LEX_CSTRING *name,
|
||||
List<Item> *item_list)
|
||||
{
|
||||
uint arg_count= item_list->elements;
|
||||
Item *a[5];
|
||||
for (uint i=0; i < MY_MIN(array_elements(a), arg_count); i++)
|
||||
a[i]= item_list->pop();
|
||||
switch (arg_count)
|
||||
{
|
||||
case 2:
|
||||
return new (thd->mem_root) Item_func_kdf(thd, a[0], a[1]);
|
||||
case 3:
|
||||
return new (thd->mem_root) Item_func_kdf(thd, a[0], a[1], a[2]);
|
||||
case 4:
|
||||
return new (thd->mem_root) Item_func_kdf(thd, a[0], a[1], a[2], a[3]);
|
||||
case 5:
|
||||
return new (thd->mem_root) Item_func_kdf(thd, a[0], a[1], a[2], a[3], a[4]);
|
||||
}
|
||||
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
Create_func_asin Create_func_asin::s_singleton;
|
||||
|
||||
Item*
|
||||
@@ -5941,6 +5981,7 @@ const Native_func_registry func_array[] =
|
||||
{ { STRING_WITH_LEN("JSON_UNQUOTE") }, BUILDER(Create_func_json_unquote)},
|
||||
{ { STRING_WITH_LEN("JSON_VALID") }, BUILDER(Create_func_json_valid)},
|
||||
{ { STRING_WITH_LEN("JSON_VALUE") }, BUILDER(Create_func_json_value)},
|
||||
{ { STRING_WITH_LEN("KDF") }, BUILDER(Create_func_kdf)},
|
||||
{ { STRING_WITH_LEN("LAST_DAY") }, BUILDER(Create_func_last_day)},
|
||||
{ { STRING_WITH_LEN("LAST_INSERT_ID") }, BUILDER(Create_func_last_insert_id)},
|
||||
{ { STRING_WITH_LEN("LCASE") }, BUILDER(Create_func_lcase)},
|
||||
|
@@ -56,6 +56,10 @@ C_MODE_END
|
||||
#include "sql_statistics.h"
|
||||
#include "strfunc.h"
|
||||
|
||||
#ifdef HAVE_hkdf
|
||||
#include <openssl/kdf.h>
|
||||
#endif
|
||||
|
||||
/* fmtlib include (https://fmt.dev/). */
|
||||
#define FMT_STATIC_THOUSANDS_SEPARATOR ','
|
||||
#define FMT_HEADER_ONLY 1
|
||||
@@ -434,6 +438,122 @@ bool Item_func_aes_decrypt::fix_length_and_dec(THD *thd)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool Item_func_kdf::fix_length_and_dec(THD *thd)
|
||||
{
|
||||
if (arg_count > 4 && args[4]->const_item())
|
||||
{
|
||||
if (((key_length= (uint)args[4]->val_int()) % 8) || key_length > 65536)
|
||||
key_length= 0;
|
||||
}
|
||||
else if (arg_count <= 4)
|
||||
key_length= block_encryption_mode_to_key_length(thd->variables.block_encryption_mode);
|
||||
else
|
||||
key_length= 0;
|
||||
key_length/= 8;
|
||||
max_length= key_length ? key_length : 256/8;
|
||||
set_maybe_null();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void invalid_argument_error(const char *func, const char *val)
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_STD_INVALID_ARGUMENT, ER_THD(thd, ER_STD_INVALID_ARGUMENT),
|
||||
val, func);
|
||||
}
|
||||
|
||||
String *Item_func_kdf::val_str(String *buf)
|
||||
{
|
||||
// KDF(key_str, salt [, {info | iterations} [, kdf_name [, width ]]])
|
||||
DBUG_ASSERT(fixed());
|
||||
StringBuffer<80> key_buf, salt_buf;
|
||||
String *key= args[0]->val_str(&key_buf);
|
||||
String *salt= args[1]->val_str(&salt_buf);
|
||||
bool use_hkdf= false;
|
||||
size_t klen= key_length;
|
||||
bool ok= false;
|
||||
|
||||
if (!key || !salt)
|
||||
goto ret_null;
|
||||
|
||||
if (arg_count > 3)
|
||||
{
|
||||
if (String *s= args[3]->val_str(buf))
|
||||
{
|
||||
if (strcasecmp(s->c_ptr(), "hkdf") == 0)
|
||||
use_hkdf= true;
|
||||
else if (strcasecmp(s->c_ptr(), "pbkdf2_hmac") != 0)
|
||||
{
|
||||
invalid_argument_error(func_name(), ErrConvStringQ(s).ptr());
|
||||
goto ret_null;
|
||||
}
|
||||
}
|
||||
else
|
||||
goto ret_null;
|
||||
}
|
||||
if (!klen)
|
||||
{
|
||||
klen= args[4]->val_int();
|
||||
if (!klen || klen % 8 || klen > 65536)
|
||||
{
|
||||
if (!args[4]->null_value)
|
||||
invalid_argument_error(func_name(),
|
||||
ErrConvInteger({(ssize_t)klen, args[4]->unsigned_flag}).ptr());
|
||||
goto ret_null;
|
||||
}
|
||||
klen/= 8;
|
||||
}
|
||||
buf->reserve(klen);
|
||||
buf->length(klen);
|
||||
|
||||
if (use_hkdf)
|
||||
{
|
||||
#ifdef HAVE_hkdf
|
||||
StringBuffer<80> info_buf;
|
||||
String *info= arg_count > 2 ? args[2]->val_str(&info_buf) : 0;
|
||||
|
||||
EVP_PKEY_CTX *ctx= EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
|
||||
ok= EVP_PKEY_derive_init(ctx) > 0 &&
|
||||
EVP_PKEY_CTX_set_hkdf_md(ctx, EVP_sha512()) > 0 &&
|
||||
EVP_PKEY_CTX_set1_hkdf_key(ctx, (const uchar*)key->ptr(), key->length()) > 0 &&
|
||||
EVP_PKEY_CTX_set1_hkdf_salt(ctx, (const uchar*)salt->ptr(), salt->length()) > 0 &&
|
||||
(!info || EVP_PKEY_CTX_add1_hkdf_info(ctx, (const uchar*)info->ptr(), info->length()) > 0) &&
|
||||
EVP_PKEY_derive(ctx, (uchar*)buf->ptr(), &klen) > 0;
|
||||
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
#else
|
||||
THD *thd= current_thd;
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_NOT_SUPPORTED_YET, ER_THD(thd, ER_NOT_SUPPORTED_YET),
|
||||
"kdf(..., 'hkdf')");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
longlong iter= arg_count > 2 ? args[2]->val_int() : 1000;
|
||||
if (iter <= 0)
|
||||
{
|
||||
if (!args[2]->null_value)
|
||||
invalid_argument_error(func_name(),
|
||||
ErrConvInteger({iter, args[2]->unsigned_flag}).ptr());
|
||||
}
|
||||
else
|
||||
ok= PKCS5_PBKDF2_HMAC(key->ptr(), key->length(),
|
||||
(const uchar*)salt->ptr(), salt->length(), (int)iter,
|
||||
EVP_sha512(), (int)klen, (uchar*)buf->ptr());
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
null_value= 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
ret_null:
|
||||
null_value=1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Item_func_to_base64::fix_length_and_dec(THD *thd)
|
||||
{
|
||||
|
@@ -133,6 +133,8 @@ public:
|
||||
:Item_str_func(thd, a, b, c) { }
|
||||
Item_str_binary_checksum_func(THD *thd, Item *a, Item *b, Item *c, Item *d)
|
||||
:Item_str_func(thd, a, b, c, d) { }
|
||||
Item_str_binary_checksum_func(THD *thd, Item *a, Item *b, Item *c, Item *d, Item *e)
|
||||
:Item_str_func(thd, a, b, c, d, e) { }
|
||||
bool eq(const Item *item, bool binary_cmp) const
|
||||
{
|
||||
/*
|
||||
@@ -295,6 +297,35 @@ public:
|
||||
{ return get_item_copy<Item_func_aes_decrypt>(thd, this); }
|
||||
};
|
||||
|
||||
class Item_func_kdf :public Item_str_binary_checksum_func
|
||||
{
|
||||
uint key_length;
|
||||
public:
|
||||
Item_func_kdf(THD *thd, Item *a, Item *b)
|
||||
: Item_str_binary_checksum_func(thd, a, b) {}
|
||||
Item_func_kdf(THD *thd, Item *a, Item *b, Item *c)
|
||||
: Item_str_binary_checksum_func(thd, a, b, c) {}
|
||||
Item_func_kdf(THD *thd, Item *a, Item *b, Item *c, Item *d)
|
||||
: Item_str_binary_checksum_func(thd, a, b, c, d) {}
|
||||
Item_func_kdf(THD *thd, Item *a, Item *b, Item *c, Item *d, Item *e)
|
||||
: Item_str_binary_checksum_func(thd, a, b, c, d, e) {}
|
||||
bool fix_length_and_dec(THD *thd) override;
|
||||
String *val_str(String *) override;
|
||||
bool check_vcol_func_processor(void *arg) override
|
||||
{
|
||||
if (arg_count > 4)
|
||||
return FALSE;
|
||||
return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC);
|
||||
}
|
||||
LEX_CSTRING func_name_cstring() const override
|
||||
{
|
||||
static LEX_CSTRING name= {STRING_WITH_LEN("kdf") };
|
||||
return name;
|
||||
}
|
||||
Item *get_copy(THD *thd) override
|
||||
{ return get_item_copy<Item_func_kdf>(thd, this); }
|
||||
};
|
||||
|
||||
class Item_func_natural_sort_key : public Item_str_func
|
||||
{
|
||||
public:
|
||||
|
Reference in New Issue
Block a user