Files
openthread/tests/unit/test_hkdf_sha256.cpp
T
Abtin Keshavarzian 7ec658e47a [common] add GetArrayLength() and GetArrayEnd() (#7413)
This commit adds two inline template functions to get the length of an
array and a pointer to the end of the array. These functions replace
similar macros that were used with OT core modules. The template
functions are safer to use since they would perform type checking at
compile time. The functions validate that the input variable is
indeed an array and unlike the macros they will not work with a
pointer variable.
2022-02-14 14:03:23 -08:00

168 lines
8.9 KiB
C++

/*
* Copyright (c) 2020, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <openthread/config.h>
#include "test_platform.h"
#include "test_util.h"
#include "test_util.hpp"
#include "common/array.hpp"
#include "common/debug.hpp"
#include "crypto/hkdf_sha256.hpp"
struct TestVector
{
const uint8_t *mInKey;
uint16_t mInKeyLength;
const uint8_t *mSalt;
uint16_t mSaltLength;
const uint8_t *mInfo;
uint16_t mInfoLength;
const uint8_t *mOutKey;
uint16_t mOutKeyLength;
};
void TestHkdfSha256(void)
{
enum
{
kMaxOuttKey = 128,
kFillByte = 0x77,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Test Case #1: RFC-5869 Appendix A.1
const uint8_t kInKey1[] = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b};
const uint8_t kSalt1[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c};
const uint8_t kInfo1[] = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9};
const uint8_t kOutKey1[] = {0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36,
0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56,
0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Test Case #2: RFC-5869 Appendix A.2
const uint8_t kInKey2[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f};
const uint8_t kSalt2[] = {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d,
0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b,
0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf};
const uint8_t kInfo2[] = {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd,
0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff};
const uint8_t kOutKey2[] = {0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a,
0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c,
0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb,
0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8,
0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec,
0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Test Case #3: RFC-5869 Appendix A.3
const uint8_t kInKey3[] = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b};
const uint8_t kOutKey3[] = {0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c,
0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, 0xc3, 0x45, 0x4e, 0x5f,
0x3c, 0x73, 0x8d, 0x2d, 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Test Case #4:
const uint8_t kInKey4[] = {'h', 'e', 'l', 'l', 'o'};
const uint8_t kSalt4[] = {0x8e, 0x94, 0xef, 0x80, 0x5b, 0x93, 0xe6, 0x83, 0xff, 0x18};
const uint8_t kOutKey4[] = {0x13, 0x48, 0x50, 0x67, 0xe2, 0x1a, 0xf1, 0x7c,
0x09, 0x00, 0xf7, 0x0d, 0x88, 0x5f, 0x02, 0x59};
const TestVector kTestVectors[] = {
{kInKey1, sizeof(kInKey1), kSalt1, sizeof(kSalt1), kInfo1, sizeof(kInfo1), kOutKey1, sizeof(kOutKey1)},
{kInKey2, sizeof(kInKey2), kSalt2, sizeof(kSalt2), kInfo2, sizeof(kInfo2), kOutKey2, sizeof(kOutKey2)},
{kInKey3, sizeof(kInKey3), nullptr, 0, nullptr, 0, kOutKey3, sizeof(kOutKey3)},
{kInKey4, sizeof(kInKey4), kSalt4, sizeof(kSalt4), nullptr, 0, kOutKey4, sizeof(kOutKey4)},
};
otInstance *instance = testInitInstance();
VerifyOrQuit(instance != nullptr);
for (const TestVector *test = &kTestVectors[0]; test < ot::GetArrayEnd(kTestVectors); test++)
{
ot::Crypto::HkdfSha256 hkdf;
uint8_t outKey[kMaxOuttKey];
ot::Crypto::Key testInputKey;
printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
DumpBuffer("\nInput Key", test->mInKey, test->mInKeyLength);
DumpBuffer("\nSalt", test->mSalt, test->mSaltLength);
DumpBuffer("\nInfo", test->mInfo, test->mInfoLength);
DumpBuffer("\nExpected Output Key", test->mOutKey, test->mOutKeyLength);
memset(outKey, kFillByte, sizeof(outKey));
memset(&testInputKey, 0x00, sizeof(testInputKey));
testInputKey.mKey = test->mInKey;
testInputKey.mKeyLength = test->mInKeyLength;
hkdf.Extract(test->mSalt, test->mSaltLength, testInputKey);
hkdf.Expand(test->mInfo, test->mInfoLength, outKey, test->mOutKeyLength);
DumpBuffer("\nCalculated Output Key", outKey, test->mOutKeyLength);
VerifyOrQuit(memcmp(outKey, test->mOutKey, test->mOutKeyLength) == 0, "HKDF-SHA-256 failed");
for (uint16_t i = test->mOutKeyLength + 1; i < sizeof(outKey); i++)
{
VerifyOrQuit(outKey[i] == kFillByte, "HKDF-SHA-256 wrote beyond output key length");
}
}
testFreeInstance(instance);
}
int main(void)
{
TestHkdfSha256();
printf("All tests passed\n");
return 0;
}