Software APIs
aes_test.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "sw/device/lib/crypto/drivers/aes.h"
6 
8 #include "sw/device/lib/crypto/drivers/entropy.h"
9 #include "sw/device/lib/crypto/impl/status.h"
11 #include "sw/device/lib/testing/test_framework/check.h"
13 
14 // NIST 800-38a F.5.1 CTR-AES128.Encrypt test vectors.
15 static const uint32_t kSecretKey[] = {
16  // Key: 2b7e151628aed2a6abf7158809cf4f3c
17  0x16157e2b,
18  0xa6d2ae28,
19  0x8815f7ab,
20  0x3c4fcf09,
21 };
22 
23 static const aes_block_t kIv = {
24  .data =
25  {
26  // Init Counter: f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
27  0xf3f2f1f0,
28  0xf7f6f5f4,
29  0xfbfaf9f8,
30  0xfffefdfc,
31  },
32 };
33 
34 // Expected counter after 4 blocks.
35 static const aes_block_t kFinalIv = {
36  .data =
37  {
38  // kIv + 4 = f0f1f2f3f4f5f6f7f8f9fafbfcfdff03
39  0xf3f2f1f0,
40  0xf7f6f5f4,
41  0xfbfaf9f8,
42  0x03fffdfc,
43  },
44 };
45 
46 static const aes_block_t kPlaintext[] = {
47  // Block#1: 6bc1bee22e409f96e93d7e117393172a
48  {.data = 0xe2bec16b, 0x969f402e, 0x117e3de9, 0x2a179373},
49  // Block#2: ae2d8a571e03ac9c9eb76fac45af8e51
50  {.data = 0x578a2dae, 0x9cac031e, 0xac6fb79e, 0x518eaf45},
51  // Block#3: 30c81c46a35ce411e5fbc1191a0a52ef
52  {.data = 0x461cc830, 0x11e45ca3, 0x19c1fbe5, 0xef520a1a},
53  // Block#4: f69f2445df4f9b17ad2b417be66c3710
54  {.data = 0x45249ff6, 0x179b4fdf, 0x7b412bad, 0x10376ce6},
55 };
56 
57 static const aes_block_t kCiphertext[] = {
58  // Block#1: 874d6191b620e3261bef6864990db6ce
59  {.data = 0x91614d87, 0x26e320b6, 0x6468ef1b, 0xceb60d99},
60  // Block#2: 9806f66b7970fdff8617187bb9fffdff
61  {.data = 0x6bf60698, 0xfffd7079, 0x7b181786, 0xfffdffb9},
62  // Block#3: 5ae4df3edbd5d35e5b4f09020db03eab
63  {.data = 0x3edfe45a, 0x5ed3d5db, 0x02094f5b, 0xab3eb00d},
64  // Block#4: 1e031dda2fbe03d1792170a0f3009cee
65  {.data = 0xda1d031e, 0xd103be2f, 0xa0702179, 0xee9c00f3},
66 };
67 
68 static status_t run_aes_test(void) {
69  // This is a weak share intended to exercise correct configuration of the
70  // hardware; in general, the key should be generated by either generating
71  // two shares and setting key = a ^ b, or generating a mask and setting
72  // a = key ^ mask, b = mask.
73  const uint32_t share0[8] = {~kSecretKey[0],
74  ~kSecretKey[1],
75  ~kSecretKey[2],
76  ~kSecretKey[3],
77  0,
78  0,
79  0,
80  0};
81  const uint32_t share1[8] = {UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX,
82  0, 0, 0, 0};
83 
84  LOG_INFO("Configuring the AES hardware.");
85  aes_key_t key = {
86  .mode = kAesCipherModeCtr,
87  .sideload = kHardenedBoolFalse,
88  .key_len = 4,
89  .key_shares = {share0, share1},
90  };
91  TRY(aes_encrypt_begin(key, &kIv));
92 
93  aes_block_t ciphertext[ARRAYSIZE(kCiphertext)] = {0};
94  aes_block_t *out = NULL;
95  for (size_t i = 0; i < ARRAYSIZE(kPlaintext); ++i) {
96  LOG_INFO("Processing block %d.", i);
97  TRY(aes_update(out, &kPlaintext[i]));
98  out = &ciphertext[i];
99  }
100  TRY(aes_update(out, NULL));
101 
102  CHECK_ARRAYS_EQ((uint32_t *)ciphertext, (uint32_t *)kCiphertext,
103  sizeof(ciphertext) / (sizeof(uint32_t)));
104 
105  LOG_INFO("Cleaning up.");
106  aes_block_t final_iv;
107  TRY(aes_end(&final_iv));
108 
109  CHECK_ARRAYS_EQ(final_iv.data, kFinalIv.data, kAesBlockNumWords);
110 
111  return OTCRYPTO_OK;
112 }
113 
114 OTTF_DEFINE_TEST_CONFIG();
115 
116 bool test_main(void) {
117  CHECK_STATUS_OK(entropy_complex_init());
118  CHECK_STATUS_OK(run_aes_test());
119 
120  return true;
121 }