Add utility for generating KDF contexts
Starting in v19, OEMCrypto implementers will need to implement KDF generation in OEMCrypto. To make it easier, this adds a utility to generate them based on the request context. PiperOrigin-RevId: 572693987 Change-Id: Ife382bf35ceede508499e3677de115ef12999dcc
This commit is contained in:
committed by
Robert Shih
parent
e85a6b9616
commit
078e1f6555
@@ -55,6 +55,9 @@
|
||||
*
|
||||
* @defgroup common_types Common Types
|
||||
* Enumerations and structures that are used by several OEMCrypto and ODK
|
||||
*
|
||||
* @defgroup odk_derivation Key Derivation Utils
|
||||
* Utilities and constants relating to key derivation.
|
||||
* functions.
|
||||
*********************************************************************/
|
||||
|
||||
@@ -784,6 +787,83 @@ bool CheckApiVersionAtMost(const ODK_NonceValues* nonce_values,
|
||||
|
||||
/// @}
|
||||
|
||||
/// @addtogroup odk_derivation
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* Contains the key label for the Mac key derivation. This contains
|
||||
* |ODK_MacKeyLabelWithZeroLength| number of bytes.
|
||||
*/
|
||||
extern const uint8_t ODK_MacKeyLabelWithZero[];
|
||||
|
||||
/** Contains the number of bytes in |ODK_MacKeyLabelWithZero|. */
|
||||
extern const size_t ODK_MacKeyLabelWithZeroLength;
|
||||
|
||||
/**
|
||||
* Contains the key label for the Encryption key derivation. This contains
|
||||
* |ODK_EncKeyLabelWithZeroLength| number of bytes.
|
||||
*/
|
||||
extern const uint8_t ODK_EncKeyLabelWithZero[];
|
||||
|
||||
/** Contains the number of bytes in |ODK_EncKeyLabelWithZero|. */
|
||||
extern const size_t ODK_EncKeyLabelWithZeroLength;
|
||||
|
||||
/**
|
||||
* Contains the suffix bytes (NIST 800-108 key length) for Mac key derivation.
|
||||
* This value is appended after the context string. This contains
|
||||
* ODK_MacKeySuffixLength number of bytes.
|
||||
*/
|
||||
extern const uint8_t ODK_MacKeySuffix[];
|
||||
|
||||
/** Contains the number of bytes in |ODK_MacKeySuffix|. */
|
||||
extern const size_t ODK_MacKeySuffixLength;
|
||||
|
||||
/**
|
||||
* Contains the suffix bytes (NIST 800-108 key length) for Encryption key
|
||||
* derivation. This value is appended after the context string. This contains
|
||||
* ODK_EncKeySuffixLength number of bytes.
|
||||
*/
|
||||
extern const uint8_t ODK_EncKeySuffix[];
|
||||
|
||||
/** Contains the number of bytes in |ODK_EncKeySuffix|. */
|
||||
extern const size_t ODK_EncKeySuffixLength;
|
||||
|
||||
/**
|
||||
* Generates the key-derivation contexts for the license exchange based on the
|
||||
* given context value.
|
||||
*
|
||||
* NOTE: if the mac_key_context/enc_key_context pointer are null and/or input
|
||||
* mac_key_context_length/enc_key_context_length is zero, this function returns
|
||||
* OEMCrypto_ERROR_SHORT_BUFFER and sets output
|
||||
* mac_key_context_length/enc_key_context_length to the size needed.
|
||||
*
|
||||
* @param[in] context: pointer to the context buffer.
|
||||
* @param[in] context_length: the length of the context buffer.
|
||||
* @param[out] mac_key_context: an output buffer to contain the MAC key context.
|
||||
* @param[in,out] mac_key_context_length: on input, contains the number of bytes
|
||||
* in |mac_key_context|; on return, will contain the context length.
|
||||
* @param[out] enc_key_context: an output buffer to contain the encryption key
|
||||
* context.
|
||||
* @param[in,out] enc_key_context_length: on input, contains the number of bytes
|
||||
* in |enc_key_context|; on return, will contain the context length.
|
||||
*
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval OEMCrypto_ERROR_SHORT_BUFFER: mac_key_context_length or
|
||||
* enc_key_context_length is too small
|
||||
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
*
|
||||
* @version
|
||||
* This method is new in version 19 of the API.
|
||||
*/
|
||||
OEMCryptoResult ODK_GenerateKeyContexts(const uint8_t* context,
|
||||
size_t context_length,
|
||||
uint8_t* mac_key_context,
|
||||
size_t* mac_key_context_length,
|
||||
uint8_t* enc_key_context,
|
||||
size_t* enc_key_context_length);
|
||||
|
||||
/// @}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,7 @@ extern "C" {
|
||||
#define ODK_MINOR_VERSION 0
|
||||
|
||||
/* ODK Version string. Date changed automatically on each release. */
|
||||
#define ODK_RELEASE_DATE "ODK v19.0 2023-10-09"
|
||||
#define ODK_RELEASE_DATE "ODK v19.0 2023-10-11"
|
||||
|
||||
/* The lowest version number for an ODK message. */
|
||||
#define ODK_FIRST_VERSION 16
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "OEMCryptoCENCCommon.h"
|
||||
#include "odk_message.h"
|
||||
#include "odk_overflow.h"
|
||||
#include "odk_serialize.h"
|
||||
@@ -589,3 +590,69 @@ bool CheckApiVersionAtMost(const ODK_NonceValues* nonce_values,
|
||||
(nonce_values->api_major_version == major_version &&
|
||||
nonce_values->api_minor_version <= minor_version);
|
||||
}
|
||||
|
||||
const uint8_t ODK_MacKeyLabelWithZero[] = "AUTHENTICATION";
|
||||
const size_t ODK_MacKeyLabelWithZeroLength = sizeof(ODK_MacKeyLabelWithZero);
|
||||
// This is the key size (512) in network byte order.
|
||||
const uint8_t ODK_MacKeySuffix[] = {0x00, 0x00, 0x02, 0x00};
|
||||
const size_t ODK_MacKeySuffixLength = sizeof(ODK_MacKeySuffix);
|
||||
|
||||
const uint8_t ODK_EncKeyLabelWithZero[] = "ENCRYPTION";
|
||||
const size_t ODK_EncKeyLabelWithZeroLength = sizeof(ODK_EncKeyLabelWithZero);
|
||||
// This is the key size (128) in network byte order.
|
||||
const uint8_t ODK_EncKeySuffix[] = {0x00, 0x00, 0x00, 0x80};
|
||||
const size_t ODK_EncKeySuffixLength = sizeof(ODK_EncKeySuffix);
|
||||
|
||||
OEMCryptoResult ODK_GenerateKeyContexts(const uint8_t* context,
|
||||
size_t context_length,
|
||||
uint8_t* mac_key_context,
|
||||
size_t* mac_key_context_length,
|
||||
uint8_t* enc_key_context,
|
||||
size_t* enc_key_context_length) {
|
||||
size_t real_mac_length;
|
||||
size_t real_enc_length;
|
||||
if (odk_add_overflow_ux(
|
||||
context_length,
|
||||
ODK_MacKeyLabelWithZeroLength + ODK_MacKeySuffixLength,
|
||||
&real_mac_length) ||
|
||||
real_mac_length > 0xffffffff ||
|
||||
odk_add_overflow_ux(
|
||||
context_length,
|
||||
ODK_EncKeyLabelWithZeroLength + ODK_EncKeySuffixLength,
|
||||
&real_enc_length) ||
|
||||
real_enc_length > 0xffffffff) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
bool short_buffer = false;
|
||||
if (mac_key_context_length) {
|
||||
short_buffer = real_mac_length > *mac_key_context_length;
|
||||
*mac_key_context_length = real_mac_length;
|
||||
}
|
||||
if (enc_key_context_length) {
|
||||
short_buffer = short_buffer || real_enc_length > *enc_key_context_length;
|
||||
*enc_key_context_length = real_enc_length;
|
||||
}
|
||||
if (short_buffer || !mac_key_context || !enc_key_context) {
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
|
||||
if (!context || !mac_key_context_length || !enc_key_context_length) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
|
||||
memcpy(mac_key_context, ODK_MacKeyLabelWithZero,
|
||||
ODK_MacKeyLabelWithZeroLength);
|
||||
memcpy(mac_key_context + ODK_MacKeyLabelWithZeroLength, context,
|
||||
context_length);
|
||||
memcpy(mac_key_context + ODK_MacKeyLabelWithZeroLength + context_length,
|
||||
ODK_MacKeySuffix, ODK_MacKeySuffixLength);
|
||||
|
||||
memcpy(enc_key_context, ODK_EncKeyLabelWithZero,
|
||||
ODK_EncKeyLabelWithZeroLength);
|
||||
memcpy(enc_key_context + ODK_EncKeyLabelWithZeroLength, context,
|
||||
context_length);
|
||||
memcpy(enc_key_context + ODK_EncKeyLabelWithZeroLength + context_length,
|
||||
ODK_EncKeySuffix, ODK_EncKeySuffixLength);
|
||||
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1376,6 +1376,130 @@ TEST(OdkOverflowTest, MultiplyUX) {
|
||||
EXPECT_TRUE(odk_mul_overflow_ux(4, SIZE_MAX >> 1, &result));
|
||||
}
|
||||
|
||||
TEST(OdkTest, GenerateKeyContexts_Success) {
|
||||
const uint8_t kContext[] = {
|
||||
0x0a, 0x4c, 0x08, 0x00, 0x12, 0x48, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
|
||||
0x10, 0x19, 0x07, 0xd9, 0xff, 0xde, 0x13, 0xaa, 0x95, 0xc1, 0x22, 0x67,
|
||||
0x80, 0x53, 0x36, 0x21, 0x36, 0xbd, 0xf8, 0x40, 0x8f, 0x82, 0x76, 0xe4,
|
||||
0xc2, 0xd8, 0x7e, 0xc5, 0x2b, 0x61, 0xaa, 0x1b, 0x9f, 0x64, 0x6e, 0x58,
|
||||
0x73, 0x49, 0x30, 0xac, 0xeb, 0xe8, 0x99, 0xb3, 0xe4, 0x64, 0x18, 0x9a,
|
||||
0x14, 0xa8, 0x72, 0x02, 0xfb, 0x02, 0x57, 0x4e, 0x70, 0x64, 0x0b, 0xd2,
|
||||
0x2e, 0xf4, 0x4b, 0x2d, 0x7e, 0x39, 0x12, 0x25, 0x0a, 0x23, 0x0a, 0x14,
|
||||
0x08, 0x01, 0x12, 0x10, 0x09, 0x15, 0x00, 0x7c, 0xaa, 0x9b, 0x59, 0x31,
|
||||
0xb7, 0x6a, 0x3a, 0x85, 0xf0, 0x46, 0x52, 0x3e, 0x10, 0x01, 0x1a, 0x09,
|
||||
0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x18, 0x01, 0x20,
|
||||
0x00, 0x2a, 0x0c, 0x31, 0x38, 0x38, 0x36, 0x37, 0x38, 0x37, 0x34, 0x30,
|
||||
0x35, 0x00, 0x00,
|
||||
};
|
||||
const uint8_t kMacKey[] = {
|
||||
0x41, 0x55, 0x54, 0x48, 0x45, 0x4e, 0x54, 0x49, 0x43, 0x41, 0x54, 0x49,
|
||||
0x4f, 0x4e, 0x00, 0x0a, 0x4c, 0x08, 0x00, 0x12, 0x48, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x10, 0x19, 0x07, 0xd9, 0xff, 0xde, 0x13, 0xaa, 0x95,
|
||||
0xc1, 0x22, 0x67, 0x80, 0x53, 0x36, 0x21, 0x36, 0xbd, 0xf8, 0x40, 0x8f,
|
||||
0x82, 0x76, 0xe4, 0xc2, 0xd8, 0x7e, 0xc5, 0x2b, 0x61, 0xaa, 0x1b, 0x9f,
|
||||
0x64, 0x6e, 0x58, 0x73, 0x49, 0x30, 0xac, 0xeb, 0xe8, 0x99, 0xb3, 0xe4,
|
||||
0x64, 0x18, 0x9a, 0x14, 0xa8, 0x72, 0x02, 0xfb, 0x02, 0x57, 0x4e, 0x70,
|
||||
0x64, 0x0b, 0xd2, 0x2e, 0xf4, 0x4b, 0x2d, 0x7e, 0x39, 0x12, 0x25, 0x0a,
|
||||
0x23, 0x0a, 0x14, 0x08, 0x01, 0x12, 0x10, 0x09, 0x15, 0x00, 0x7c, 0xaa,
|
||||
0x9b, 0x59, 0x31, 0xb7, 0x6a, 0x3a, 0x85, 0xf0, 0x46, 0x52, 0x3e, 0x10,
|
||||
0x01, 0x1a, 0x09, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
|
||||
0x18, 0x01, 0x20, 0x00, 0x2a, 0x0c, 0x31, 0x38, 0x38, 0x36, 0x37, 0x38,
|
||||
0x37, 0x34, 0x30, 0x35, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
|
||||
};
|
||||
const uint8_t kEncKey[] = {
|
||||
0x45, 0x4e, 0x43, 0x52, 0x59, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x0a,
|
||||
0x4c, 0x08, 0x00, 0x12, 0x48, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10,
|
||||
0x19, 0x07, 0xd9, 0xff, 0xde, 0x13, 0xaa, 0x95, 0xc1, 0x22, 0x67, 0x80,
|
||||
0x53, 0x36, 0x21, 0x36, 0xbd, 0xf8, 0x40, 0x8f, 0x82, 0x76, 0xe4, 0xc2,
|
||||
0xd8, 0x7e, 0xc5, 0x2b, 0x61, 0xaa, 0x1b, 0x9f, 0x64, 0x6e, 0x58, 0x73,
|
||||
0x49, 0x30, 0xac, 0xeb, 0xe8, 0x99, 0xb3, 0xe4, 0x64, 0x18, 0x9a, 0x14,
|
||||
0xa8, 0x72, 0x02, 0xfb, 0x02, 0x57, 0x4e, 0x70, 0x64, 0x0b, 0xd2, 0x2e,
|
||||
0xf4, 0x4b, 0x2d, 0x7e, 0x39, 0x12, 0x25, 0x0a, 0x23, 0x0a, 0x14, 0x08,
|
||||
0x01, 0x12, 0x10, 0x09, 0x15, 0x00, 0x7c, 0xaa, 0x9b, 0x59, 0x31, 0xb7,
|
||||
0x6a, 0x3a, 0x85, 0xf0, 0x46, 0x52, 0x3e, 0x10, 0x01, 0x1a, 0x09, 0x39,
|
||||
0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x18, 0x01, 0x20, 0x00,
|
||||
0x2a, 0x0c, 0x31, 0x38, 0x38, 0x36, 0x37, 0x38, 0x37, 0x34, 0x30, 0x35,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||
};
|
||||
|
||||
std::vector<uint8_t> mac_key(sizeof(kMacKey) + 24);
|
||||
std::vector<uint8_t> enc_key(sizeof(kEncKey) + 24);
|
||||
size_t mac_key_size = mac_key.size();
|
||||
size_t enc_key_size = enc_key.size();
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
ODK_GenerateKeyContexts(kContext, sizeof(kContext), &mac_key[0],
|
||||
&mac_key_size, &enc_key[0], &enc_key_size));
|
||||
ASSERT_EQ(mac_key_size, sizeof(kMacKey));
|
||||
ASSERT_EQ(enc_key_size, sizeof(kEncKey));
|
||||
mac_key.resize(mac_key_size);
|
||||
enc_key.resize(enc_key_size);
|
||||
|
||||
EXPECT_EQ(std::vector<uint8_t>(kMacKey, kMacKey + sizeof(kMacKey)), mac_key);
|
||||
EXPECT_EQ(std::vector<uint8_t>(kEncKey, kEncKey + sizeof(kEncKey)), enc_key);
|
||||
}
|
||||
|
||||
TEST(OdkTest, GenerateKeyContexts_ShortBuffer) {
|
||||
const uint8_t kContext[] = {1, 2, 3};
|
||||
size_t mac_key_size = 0;
|
||||
size_t enc_key_size = 0;
|
||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
||||
ODK_GenerateKeyContexts(kContext, sizeof(kContext), nullptr,
|
||||
&mac_key_size, nullptr, &enc_key_size));
|
||||
EXPECT_EQ(mac_key_size, sizeof(kContext) + 19);
|
||||
EXPECT_EQ(enc_key_size, sizeof(kContext) + 15);
|
||||
}
|
||||
|
||||
TEST(OdkTest, GenerateKeyContexts_ShortBufferMacOnly) {
|
||||
const uint8_t kContext[] = {1, 2, 3};
|
||||
uint8_t buffer[128];
|
||||
size_t mac_key_size = 0;
|
||||
size_t enc_key_size = sizeof(buffer);
|
||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
||||
ODK_GenerateKeyContexts(kContext, sizeof(kContext), nullptr,
|
||||
&mac_key_size, buffer, &enc_key_size));
|
||||
EXPECT_EQ(mac_key_size, sizeof(kContext) + 19);
|
||||
EXPECT_EQ(enc_key_size, sizeof(kContext) + 15);
|
||||
}
|
||||
|
||||
TEST(OdkTest, GenerateKeyContexts_ShortBufferEncOnly) {
|
||||
const uint8_t kContext[] = {1, 2, 3};
|
||||
uint8_t buffer[128];
|
||||
size_t mac_key_size = sizeof(buffer);
|
||||
size_t enc_key_size = 0;
|
||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
||||
ODK_GenerateKeyContexts(kContext, sizeof(kContext), buffer,
|
||||
&mac_key_size, buffer, &enc_key_size));
|
||||
EXPECT_EQ(mac_key_size, sizeof(kContext) + 19);
|
||||
EXPECT_EQ(enc_key_size, sizeof(kContext) + 15);
|
||||
}
|
||||
|
||||
TEST(OdkTest, GenerateKeyContexts_NullArgs) {
|
||||
const uint8_t kContext[] = {1, 2, 3};
|
||||
uint8_t buffer[24];
|
||||
size_t buffer_size = sizeof(buffer);
|
||||
size_t buffer_size2 = sizeof(buffer);
|
||||
|
||||
EXPECT_EQ(OEMCrypto_ERROR_INVALID_CONTEXT,
|
||||
ODK_GenerateKeyContexts(nullptr, sizeof(kContext), buffer,
|
||||
&buffer_size, buffer, &buffer_size2));
|
||||
buffer_size = buffer_size2 = sizeof(buffer); // Update to avoid short buffer.
|
||||
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
||||
ODK_GenerateKeyContexts(kContext, sizeof(kContext), nullptr,
|
||||
&buffer_size, buffer, &buffer_size2));
|
||||
buffer_size = buffer_size2 = sizeof(buffer); // Update to avoid short buffer.
|
||||
EXPECT_EQ(OEMCrypto_ERROR_INVALID_CONTEXT,
|
||||
ODK_GenerateKeyContexts(kContext, sizeof(kContext), buffer, nullptr,
|
||||
buffer, &buffer_size2));
|
||||
buffer_size = buffer_size2 = sizeof(buffer); // Update to avoid short buffer.
|
||||
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
||||
ODK_GenerateKeyContexts(kContext, sizeof(kContext), buffer,
|
||||
&buffer_size, nullptr, &buffer_size2));
|
||||
buffer_size = buffer_size2 = sizeof(buffer); // Update to avoid short buffer.
|
||||
EXPECT_EQ(OEMCrypto_ERROR_INVALID_CONTEXT,
|
||||
ODK_GenerateKeyContexts(kContext, sizeof(kContext), buffer,
|
||||
&buffer_size, buffer, nullptr));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace wvodk_test
|
||||
|
||||
Reference in New Issue
Block a user