From 42e3862970f51151ef25232f1eeec14fdfed6bfb Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 22 Dec 2022 22:39:06 +0100 Subject: [PATCH] Berry hkdf (#17487) * Berry crypto add `HKDF_HMAC_SHA256` * add HKDF option --- CHANGELOG.md | 1 + .../berry_tasmota/src/be_crypto_lib.c | 12 ++++ tasmota/my_user_config.h | 1 + .../xdrv_52_3_berry_crypto.ino | 69 +++++++++++++++++++ 4 files changed, 83 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d25f57a0..234ca510c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - Berry crypto add ``EC_P256`` and ``PBKDF2_HMAC_SHA256`` algorithms required by Matter protocol - Berry crypto add ``random`` to generate series of random bytes +- Berry crypto add ``HKDF_HMAC_SHA256`` ### Breaking Changed diff --git a/lib/libesp32/berry_tasmota/src/be_crypto_lib.c b/lib/libesp32/berry_tasmota/src/be_crypto_lib.c index 525f9b359..b38c3c092 100644 --- a/lib/libesp32/berry_tasmota/src/be_crypto_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_crypto_lib.c @@ -40,6 +40,8 @@ extern int m_hmac_sha256_out(bvm *vm); extern int m_pbkdf2_hmac_sha256_f(bvm *vm); +extern int m_hkdf_hmac_sha256_derive(bvm *vm); + extern const bclass be_class_md5; #include "solidify/solidified_crypto_pbkdf2_hmac_sha256.h" @@ -51,10 +53,12 @@ extern const bclass be_class_md5; #include "be_fixed_be_class_sha256.h" #include "be_fixed_be_class_hmac_sha256.h" #include "be_fixed_be_class_pbkdf2_hmac_sha256.h" +#include "be_fixed_be_class_hkdf_hmac_sha256.h" #include "be_fixed_crypto.h" const be_const_member_t be_crypto_members[] = { // name with prefix '/' indicates a Berry class + // entries need to be sorted (ignoring the prefix char) #ifdef USE_BERRY_CRYPTO_AES_CTR { "/AES_CTR", (intptr_t) &be_class_aes_ctr }, #endif // USE_BERRY_CRYPTO_AES_CTR @@ -71,6 +75,10 @@ const be_const_member_t be_crypto_members[] = { { "/EC_P256", (intptr_t) &be_class_ec_p256 }, #endif // USE_BERRY_CRYPTO_EC_P256 +#ifdef USE_BERRY_CRYPTO_HKDF_HMAC_SHA256 + { "/HKDF_HMAC_SHA256", (intptr_t) &be_class_hkdf_hmac_sha256 }, +#endif // USE_BERRY_CRYPTO_HKDF_HMAC_SHA256 + #ifdef USE_BERRY_CRYPTO_HMAC_SHA256 { "/HMAC_SHA256", (intptr_t) &be_class_hmac_sha256 }, #endif // USE_BERRY_CRYPTO_HMAC_SHA256 @@ -144,6 +152,10 @@ class be_class_pbkdf2_hmac_sha256 (scope: global, name: PBKDF2_HMAC_SHA256) { derive, closure(PBKDF2_HMAC_SHA256_closure) } +class be_class_hkdf_hmac_sha256 (scope: global, name: HKDF_HMAC_SHA256) { + derive, static_func(m_hkdf_hmac_sha256_derive) +} + module crypto (scope: global) { member, func(be_class_crypto_member) random, func(m_crypto_random) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index ff9b1c9a9..feea40b0f 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -1112,6 +1112,7 @@ #define USE_BERRY_CRYPTO_SHA256 // enable SHA256 hash function #define USE_BERRY_CRYPTO_HMAC_SHA256 // enable HMAC SHA256 hash function // #define USE_BERRY_CRYPTO_PBKDF2_HMAC_SHA256 // PBKDF2 with HMAC SHA256, used in Matter protocol + // #define USE_BERRY_CRYPTO_HKDF_HMAC_SHA256 // HKDF with HMAC SHA256, used in Matter protocol #define USE_CSE7761 // Add support for CSE7761 Energy monitor as used in Sonoff Dual R3 // -- LVGL Graphics Library --------------------------------- diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_crypto.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_crypto.ino index d9672d5ba..a07e5a649 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_crypto.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_crypto.ino @@ -673,6 +673,75 @@ extern "C" { } } +/*********************************************************************************************\ + * HKDF_HMAC_SHA256 + * +\*********************************************************************************************/ +extern "C" { + // crypto.HKDF_HMAC_SHA256().derive(ikm:bytes(), salt:bytes(), info:bytes(), out_bytes:int) -> bytes(out_bytes) + // Derive key with HKDF based on HMAC SHA256 + int32_t m_hkdf_hmac_sha256_derive(bvm *vm); + int32_t m_hkdf_hmac_sha256_derive(bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 4 && be_isbytes(vm, 1) && be_isbytes(vm, 2) && be_isbytes(vm, 3) && be_isint(vm, 4)) { + size_t ikm_len; + const void * ikm = be_tobytes(vm, 1, &ikm_len); + if (ikm_len == 0) { be_raise(vm, "value_error", "ikm must not be empty"); } + + size_t salt_len; + const void * salt = be_tobytes(vm, 2, &salt_len); + if (salt_len == 0) { salt = &br_hkdf_no_salt; } + + size_t info_len; + const void * info = be_tobytes(vm, 3, &info_len); + + int32_t out_bytes = be_toint(vm, 4); + if (out_bytes < 1 || out_bytes > 256) { be_raise(vm, "value_error", "invalid out_bytes"); } + + br_hkdf_context hc; + br_hkdf_init(&hc, &br_sha256_vtable, salt, salt_len); + br_hkdf_inject(&hc, ikm, ikm_len); + br_hkdf_flip(&hc); + uint8_t out[out_bytes]; + br_hkdf_produce(&hc, info, info_len, out, out_bytes); + + be_pushbytes(vm, out, out_bytes); + be_return(vm); + } + be_raise(vm, kTypeError, nullptr); + } +/* Test vectors +# https://www.rfc-editor.org/rfc/rfc5869 + +import crypto + +# Test Case 1 +hk = crypto.HKDF_HMAC_SHA256() +ikm = bytes("0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B") +salt = bytes("000102030405060708090A0B0C") +info = bytes("F0F1F2F3F4F5F6F7F8F9") +k = hk.derive(ikm, salt, info, 42) +assert(k == bytes("3CB25F25FAACD57A90434F64D0362F2A2D2D0A90CF1A5A4C5DB02D56ECC4C5BF34007208D5B887185865")) + +# Test Case 2 +hk = crypto.HKDF_HMAC_SHA256() +ikm = bytes("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f") +salt = bytes("606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf") +info = bytes("b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff") +k = hk.derive(ikm, salt, info, 82) +assert(k == bytes("b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87")) + +# Test Case 3 +hk = crypto.HKDF_HMAC_SHA256() +ikm = bytes("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b") +salt = bytes() +info = bytes() +k = hk.derive(ikm, salt, info, 42) +assert(k == bytes("8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8")) + +*/ +} + /*********************************************************************************************\ * PBKDF2_HMAC_SHA256 *