Software APIs
aes_masking_off_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 "hw/ip/aes/model/aes_modes.h"
8 #include "sw/device/lib/base/multibits.h"
11 #include "sw/device/lib/dif/dif_csrng_shared.h"
14 #include "sw/device/lib/testing/aes_testutils.h"
15 #include "sw/device/lib/testing/csrng_testutils.h"
16 #include "sw/device/lib/testing/test_framework/check.h"
18 
19 enum {
20  kTestTimeout = (1000 * 1000),
21 };
22 
23 // The mask share, used to mask kKey. Note that the masking should not be done
24 // manually. Software is expected to get the key in two shares right from the
25 // beginning.
26 static const uint8_t kKeyShare1[] = {
27  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
28  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
29  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
30 };
31 
32 static_assert(kDtAesCount >= 1, "This test requires at least one AES instance");
33 static_assert(kDtCsrngCount >= 1,
34  "This test requires at least one CSRNG instance");
35 static_assert(kDtEdnCount >= 1, "This test requires at least one EDN instance");
36 
37 static dt_aes_t kTestAes = (dt_aes_t)0;
38 static dt_csrng_t kTestCsrng = (dt_csrng_t)0;
39 static dt_edn_t kTestEdn = (dt_edn_t)0;
40 
41 OTTF_DEFINE_TEST_CONFIG();
42 
43 status_t execute_test(const dif_csrng_t *csrng, const dif_edn_t *edn0) {
44  // Perform the known-answer testing on the CSRNG SW application interface.
45  CHECK_STATUS_OK(aes_testutils_csrng_kat(csrng));
46 
47  // Test AES with masking switched off.
48  //
49  // For this to work:
50  // - CSRNG needs to generate the required seed to have the AES masking PRNG
51  // output an all-zero vector and forward that to AES over EDN.
52  // - AES needs to be configured with the CTRL_AUX_SHADOWED.FORCE_MASKS bit
53  // set.
54  // - Share 1 of the initial key must be an all-zero vector.
55  //
56  // Since the masking is transparent to software, software cannot actually
57  // verify that the masking is off. Instead, DV needs to probe into the design.
58  LOG_INFO("Testing AES with masking switched off");
59 
60  // Initialize EDN and CSRNG to generate the required seed.
61  CHECK_STATUS_OK(aes_testutils_masking_prng_zero_output_seed(csrng, edn0));
62 
63  // Initialise AES.
64  dif_aes_t aes;
65  CHECK_DIF_OK(dif_aes_init_from_dt(kTestAes, &aes));
66  CHECK_DIF_OK(dif_aes_reset(&aes));
67 
68  // Mask the key. Note that this should not be done manually. Software is
69  // expected to get the key in two shares right from the beginning.
70  uint8_t key_share0[sizeof(kAesModesKey128)];
71  for (int i = 0; i < sizeof(kAesModesKey128); ++i) {
72  key_share0[i] = kAesModesKey128[i] ^ kKeyShare1[i];
73  }
74 
75  // "Convert" key share byte arrays to `dif_aes_key_share_t`.
77  memcpy(key.share0, key_share0, sizeof(key.share0));
78  memcpy(key.share1, kKeyShare1, sizeof(key.share1));
79 
80  // Setup ECB encryption transaction with the CTRL_AUX_SHADOWED.FORCE_MASKS bit
81  // set.
82  dif_aes_transaction_t transaction = {
83  .operation = kDifAesOperationEncrypt,
84  .mode = kDifAesModeEcb,
85  .key_len = kDifAesKey128,
86  .key_provider = kDifAesKeySoftwareProvided,
87  .mask_reseeding = kDifAesReseedPer8kBlock,
88  .manual_operation = kDifAesManualOperationAuto,
89  .reseed_on_key_change = false,
90  .force_masks = true,
91  .ctrl_aux_lock = false,
92  };
93  CHECK_DIF_OK(dif_aes_start(&aes, &transaction, &key, NULL));
94 
95  // Trigger a reseed of the internal PRNGs. This will load the seed generated
96  // by CSRNG to be loaded into the AES masking PRNG. After this point, the AES
97  // masking PRNG outputs an all-zero vector.
98  AES_TESTUTILS_WAIT_FOR_STATUS(&aes, kDifAesStatusIdle, true, kTestTimeout);
99  CHECK_DIF_OK(dif_aes_trigger(&aes, kDifAesTriggerPrngReseed));
100  AES_TESTUTILS_WAIT_FOR_STATUS(&aes, kDifAesStatusIdle, true, kTestTimeout);
101 
102  // Trigger the clearing of the output data registers. After this point, also
103  // the PRNG buffer stage will output an all-zero vector.
104  CHECK_DIF_OK(dif_aes_trigger(&aes, kDifAesTriggerDataOutClear));
105  AES_TESTUTILS_WAIT_FOR_STATUS(&aes, kDifAesStatusIdle, true, kTestTimeout);
106 
107  // "Convert" plain data byte arrays to `dif_aes_data_t` array.
108  enum {
109  kAesNumBlocks = 4,
110  };
111  dif_aes_data_t plain_text[kAesNumBlocks];
112  dif_aes_data_t cipher_text[kAesNumBlocks];
113  memcpy(plain_text[0].data, kAesModesPlainText, sizeof(kAesModesPlainText));
114 
115  // Encrypt kAesNumBlocks blocks.
116  AES_TESTUTILS_WAIT_FOR_STATUS(&aes, kDifAesStatusInputReady, true,
117  kTestTimeout);
118  CHECK_DIF_OK(dif_aes_process_data(&aes, plain_text, cipher_text,
119  (size_t)kAesNumBlocks));
120 
121  // Check the produced cipher text.
122  CHECK_ARRAYS_EQ((uint8_t *)cipher_text[0].data, kAesModesCipherTextEcb128,
123  sizeof(kAesModesCipherTextEcb128));
124  return OK_STATUS();
125 }
126 
127 bool test_main(void) {
128  // Test seed generation using CSRNG SW application interface.
129  //
130  // We try to generate the seed leading to an all-zero output of the AES
131  // masking PRNG using the CSRNG SW application interface. Unlike the HW
132  // application interfaces of CSRNG that connect to the EDNs, this interface
133  // allows for probing the internal state of the CSRNG instance after
134  // individual commands. This gives us higher visibility. If for some reason
135  // this phase isn't succesful, we don't even need to try it on the HW
136  // interfaces.
137  LOG_INFO("Testing CSRNG SW application interface");
138 
139  // Disable EDN connected to AES as well as CSRNG.
140  dif_csrng_t csrng;
141  dif_edn_t edn;
142  CHECK_DIF_OK(dif_csrng_init_from_dt(kTestCsrng, &csrng));
143  CHECK_DIF_OK(dif_edn_init_from_dt(kTestEdn, &edn));
144  CHECK_DIF_OK(dif_edn_stop(&edn));
145  CHECK_DIF_OK(dif_csrng_stop(&csrng));
146 
147  // Re-enable CSRNG.
148  CHECK_DIF_OK(dif_csrng_configure(&csrng));
149 
150  return status_ok(execute_test(&csrng, &edn));
151 }