Skip to content

Commit

Permalink
MDEV-31474 KDF() function
Browse files Browse the repository at this point in the history
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
  • Loading branch information
vuvova committed Sep 30, 2023
1 parent 03c68f4 commit 4f9396b
Show file tree
Hide file tree
Showing 10 changed files with 481 additions and 0 deletions.
3 changes: 3 additions & 0 deletions cmake/ssl.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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}")
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
64 changes: 64 additions & 0 deletions mysql-test/main/func_kdf,old.rdiff
Original file line number Diff line number Diff line change
@@ -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 changes: 4 additions & 0 deletions mysql-test/main/func_kdf.combinations
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[new]

[old]
# remove when no longer building with OpenSSL 1.0
158 changes: 158 additions & 0 deletions mysql-test/main/func_kdf.result
Original file line number Diff line number Diff line change
@@ -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 changes: 57 additions & 0 deletions mysql-test/main/func_kdf.test
Original file line number Diff line number Diff line change
@@ -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 #

2 changes: 2 additions & 0 deletions mysql-test/suite.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down
41 changes: 41 additions & 0 deletions sql/item_create.cc
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,20 @@ class Create_func_aes_decrypt : public Create_native_func
};


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:
Expand Down Expand Up @@ -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*
Expand Down Expand Up @@ -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)},
Expand Down

0 comments on commit 4f9396b

Please sign in to comment.