// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
#include "gtest/gtest.h"
#include <stdint.h>
#include <memory>
#include "blapi.h"
#include "secitem.h"
#include "freebl_scoped_ptrs.h"
class CmacAesTest :
public ::testing::Test {
protected :
bool Compare(
const uint8_t *actual,
const uint8_t *expected,
unsigned int length) {
return strncmp((
const char *)actual, (
const char *)expected, length) ==
0 ;
}
};
TEST_F(CmacAesTest, CreateInvalidSize) {
uint8_t key[
1 ] = {
0 x00};
ScopedCMACContext ctx(CMAC_Create(CMAC_AES, key,
sizeof (key)));
ASSERT_EQ(ctx, nullptr);
}
TEST_F(CmacAesTest, CreateRightSize) {
uint8_t *key = PORT_NewArray(uint8_t, AES_128_KEY_LENGTH);
ScopedCMACContext ctx(CMAC_Create(CMAC_AES, key, AES_128_KEY_LENGTH));
ASSERT_NE(ctx, nullptr);
PORT_Free(key);
}
// The following tests were taken from NIST's Cryptographic Standards and
// Guidelines page for AES-CMAC Examples with Intermediate Values. These same
// test vectors for AES-128 can be found in RFC 4493, Section 4.
static const uint8_t kNistKeys[][AES_256_KEY_LENGTH] = {
{
0 x2B,
0 x7E,
0 x15,
0 x16,
0 x28,
0 xAE,
0 xD2,
0 xA6,
0 xAB,
0 xF7,
0 x15,
0 x88,
0 x09,
0 xCF,
0 x4F,
0 x3C,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00},
{
0 x8E,
0 x73,
0 xB0,
0 xF7,
0 xDA,
0 x0E,
0 x64,
0 x52,
0 xC8,
0 x10,
0 xF3,
0 x2B,
0 x80,
0 x90,
0 x79,
0 xE5,
0 x62,
0 xF8,
0 xEA,
0 xD2,
0 x52,
0 x2C,
0 x6B,
0 x7B,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00},
{
0 x60,
0 x3D,
0 xEB,
0 x10,
0 x15,
0 xCA,
0 x71,
0 xBE,
0 x2B,
0 x73,
0 xAE,
0 xF0,
0 x85,
0 x7D,
0 x77,
0 x81,
0 x1F,
0 x35,
0 x2C,
0 x07,
0 x3B,
0 x61,
0 x08,
0 xD7,
0 x2D,
0 x98,
0 x10,
0 xA3,
0 x09,
0 x14,
0 xDF,
0 xF4}};
static const size_t kNistKeyLengthsCount = PR_ARRAY_SIZE(kNistKeys);
static const unsigned int kNistKeyLengths[kNistKeyLengthsCount] = {
AES_128_KEY_LENGTH, AES_192_KEY_LENGTH, AES_256_KEY_LENGTH};
static const uint8_t kNistPlaintext[
64 ] = {
0 x6B,
0 xC1,
0 xBE,
0 xE2,
0 x2E,
0 x40,
0 x9F,
0 x96,
0 xE9,
0 x3D,
0 x7E,
0 x11,
0 x73,
0 x93,
0 x17,
0 x2A,
0 xAE,
0 x2D,
0 x8A,
0 x57,
0 x1E,
0 x03,
0 xAC,
0 x9C,
0 x9E,
0 xB7,
0 x6F,
0 xAC,
0 x45,
0 xAF,
0 x8E,
0 x51,
0 x30,
0 xC8,
0 x1C,
0 x46,
0 xA3,
0 x5C,
0 xE4,
0 x11,
0 xE5,
0 xFB,
0 xC1,
0 x19,
0 x1A,
0 x0A,
0 x52,
0 xEF,
0 xF6,
0 x9F,
0 x24,
0 x45,
0 xDF,
0 x4F,
0 x9B,
0 x17,
0 xAD,
0 x2B,
0 x41,
0 x7B,
0 xE6,
0 x6C,
0 x37,
0 x10};
static const unsigned int kNistPlaintextLengths[] = {
0 ,
16 ,
20 ,
64 };
static const size_t kNistPlaintextLengthsCount =
PR_ARRAY_SIZE(kNistPlaintextLengths);
// This table contains the result of a CMAC over kNistPlaintext using keys from
// kNistKeys. For each key, there are kNistPlaintextLengthsCount answers, all
// listed one after the other as the input is truncated to the different sizes
// in kNistPlaintextLengths.
static const uint8_t kNistKnown[][AES_BLOCK_SIZE] = {
{
0 xBB,
0 x1D,
0 x69,
0 x29,
0 xE9,
0 x59,
0 x37,
0 x28,
0 x7F,
0 xA3,
0 x7D,
0 x12,
0 x9B,
0 x75,
0 x67,
0 x46},
{
0 x07,
0 x0A,
0 x16,
0 xB4,
0 x6B,
0 x4D,
0 x41,
0 x44,
0 xF7,
0 x9B,
0 xDD,
0 x9D,
0 xD0,
0 x4A,
0 x28,
0 x7C},
{
0 x7D,
0 x85,
0 x44,
0 x9E,
0 xA6,
0 xEA,
0 x19,
0 xC8,
0 x23,
0 xA7,
0 xBF,
0 x78,
0 x83,
0 x7D,
0 xFA,
0 xDE},
{
0 x51,
0 xF0,
0 xBE,
0 xBF,
0 x7E,
0 x3B,
0 x9D,
0 x92,
0 xFC,
0 x49,
0 x74,
0 x17,
0 x79,
0 x36,
0 x3C,
0 xFE},
{
0 xD1,
0 x7D,
0 xDF,
0 x46,
0 xAD,
0 xAA,
0 xCD,
0 xE5,
0 x31,
0 xCA,
0 xC4,
0 x83,
0 xDE,
0 x7A,
0 x93,
0 x67},
{
0 x9E,
0 x99,
0 xA7,
0 xBF,
0 x31,
0 xE7,
0 x10,
0 x90,
0 x06,
0 x62,
0 xF6,
0 x5E,
0 x61,
0 x7C,
0 x51,
0 x84},
{
0 x3D,
0 x75,
0 xC1,
0 x94,
0 xED,
0 x96,
0 x07,
0 x04,
0 x44,
0 xA9,
0 xFA,
0 x7E,
0 xC7,
0 x40,
0 xEC,
0 xF8},
{
0 xA1,
0 xD5,
0 xDF,
0 x0E,
0 xED,
0 x79,
0 x0F,
0 x79,
0 x4D,
0 x77,
0 x58,
0 x96,
0 x59,
0 xF3,
0 x9A,
0 x11},
{
0 x02,
0 x89,
0 x62,
0 xF6,
0 x1B,
0 x7B,
0 xF8,
0 x9E,
0 xFC,
0 x6B,
0 x55,
0 x1F,
0 x46,
0 x67,
0 xD9,
0 x83},
{
0 x28,
0 xA7,
0 x02,
0 x3F,
0 x45,
0 x2E,
0 x8F,
0 x82,
0 xBD,
0 x4B,
0 xF2,
0 x8D,
0 x8C,
0 x37,
0 xC3,
0 x5C},
{
0 x15,
0 x67,
0 x27,
0 xDC,
0 x08,
0 x78,
0 x94,
0 x4A,
0 x02,
0 x3C,
0 x1F,
0 xE0,
0 x3B,
0 xAD,
0 x6D,
0 x93},
{
0 xE1,
0 x99,
0 x21,
0 x90,
0 x54,
0 x9F,
0 x6E,
0 xD5,
0 x69,
0 x6A,
0 x2C,
0 x05,
0 x6C,
0 x31,
0 x54,
0 x10}};
PR_STATIC_ASSERT(PR_ARRAY_SIZE(kNistKnown) ==
kNistKeyLengthsCount * kNistPlaintextLengthsCount);
TEST_F(CmacAesTest, AesNistAligned) {
for (
unsigned int key_index =
0 ; key_index < kNistKeyLengthsCount;
key_index++) {
ScopedCMACContext ctx(CMAC_Create(CMAC_AES, kNistKeys[key_index],
kNistKeyLengths[key_index]));
ASSERT_NE(ctx, nullptr);
for (
unsigned int plaintext_index =
0 ;
plaintext_index < kNistPlaintextLengthsCount; plaintext_index++) {
CMAC_Begin(ctx.get());
unsigned int known_index =
(key_index * kNistPlaintextLengthsCount) + plaintext_index;
CMAC_Update(ctx.get(), kNistPlaintext,
kNistPlaintextLengths[plaintext_index]);
uint8_t output[AES_BLOCK_SIZE];
CMAC_Finish(ctx.get(), output, NULL, AES_BLOCK_SIZE);
ASSERT_TRUE(Compare(output, kNistKnown[known_index], AES_BLOCK_SIZE));
}
}
}
TEST_F(CmacAesTest, AesNistUnaligned) {
for (
unsigned int key_index =
0 ; key_index < kNistKeyLengthsCount;
key_index++) {
unsigned int key_length = kNistKeyLengths[key_index];
ScopedCMACContext ctx(
CMAC_Create(CMAC_AES, kNistKeys[key_index], key_length));
ASSERT_NE(ctx, nullptr);
// Skip the zero-length test.
for (
unsigned int plaintext_index =
1 ;
plaintext_index < kNistPlaintextLengthsCount; plaintext_index++) {
unsigned int known_index =
(key_index * kNistPlaintextLengthsCount) + plaintext_index;
unsigned int plaintext_length = kNistPlaintextLengths[plaintext_index];
// Test all possible offsets and make sure that misaligned updates
// produce the desired result. That is, do two updates:
// 0 ... offset
// offset ... len - offset
// and ensure the result is the same as doing one update.
for (
unsigned int offset =
1 ; offset < plaintext_length; offset++) {
CMAC_Begin(ctx.get());
CMAC_Update(ctx.get(), kNistPlaintext, offset);
CMAC_Update(ctx.get(), kNistPlaintext + offset,
plaintext_length - offset);
uint8_t output[AES_BLOCK_SIZE];
CMAC_Finish(ctx.get(), output, NULL, AES_BLOCK_SIZE);
ASSERT_TRUE(Compare(output, kNistKnown[known_index], AES_BLOCK_SIZE));
}
}
}
}
TEST_F(CmacAesTest, AesNistTruncated) {
for (
unsigned int key_index =
0 ; key_index < kNistKeyLengthsCount;
key_index++) {
unsigned int key_length = kNistKeyLengths[key_index];
ScopedCMACContext ctx(
CMAC_Create(CMAC_AES, kNistKeys[key_index], key_length));
ASSERT_TRUE(ctx != nullptr);
// Skip the zero-length test.
for (
unsigned int plaintext_index =
1 ;
plaintext_index < kNistPlaintextLengthsCount; plaintext_index++) {
unsigned int known_index =
(key_index * kNistPlaintextLengthsCount) + plaintext_index;
unsigned int plaintext_length = kNistPlaintextLengths[plaintext_index];
// Test truncated outputs to ensure that we always get the desired values.
for (
unsigned int out_len =
1 ; out_len < AES_BLOCK_SIZE; out_len++) {
CMAC_Begin(ctx.get());
CMAC_Update(ctx.get(), kNistPlaintext, plaintext_length);
unsigned int actual_out_len =
0 ;
uint8_t output[AES_BLOCK_SIZE];
CMAC_Finish(ctx.get(), output, &actual_out_len, out_len);
ASSERT_TRUE(actual_out_len == out_len);
ASSERT_TRUE(Compare(output, kNistKnown[known_index], out_len));
}
}
}
}
Messung V0.5 in Prozent C=89 H=95 G=91
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-05)
¤
*© Formatika GbR, Deutschland