Software APIs
drbg.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 
6 
9 #include "sw/device/lib/base/status.h"
10 #include "sw/device/lib/crypto/drivers/entropy.h"
11 #include "sw/device/lib/crypto/impl/integrity.h"
14 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
15 #include "sw/device/lib/ujson/ujson.h"
16 #include "sw/device/tests/crypto/cryptotest/json/drbg_commands.h"
17 
18 status_t handle_drbg(ujson_t *uj) {
19  cryptotest_drbg_input_t uj_input;
20  // Deserialize test arguments from UART
21  TRY(ujson_deserialize_cryptotest_drbg_input_t(uj, &uj_input));
22 
23  // Entropy for initialization
24  uint8_t entropy_buf[kEntropySeedBytes];
25  memset(entropy_buf, 0, kEntropySeedBytes);
26  memcpy(entropy_buf, uj_input.entropy, uj_input.entropy_len);
27  otcrypto_const_byte_buf_t entropy = {
28  .len = kEntropySeedBytes,
29  .data = entropy_buf,
30  };
31 
32  // Personalization string
33  uint8_t perso_string_buf[uj_input.personalization_string_len];
34  memcpy(perso_string_buf, uj_input.personalization_string,
35  uj_input.personalization_string_len);
36  otcrypto_const_byte_buf_t perso_string = {
37  .len = uj_input.personalization_string_len,
38  .data = perso_string_buf,
39  };
40 
41  // Reseed entropy
42  uint8_t reseed_entropy_buf[uj_input.reseed_entropy_len];
43  memcpy(reseed_entropy_buf, uj_input.reseed_entropy,
44  uj_input.reseed_entropy_len);
45  otcrypto_const_byte_buf_t reseed_entropy = {
46  .len = uj_input.reseed_entropy_len,
47  .data = uj_input.reseed_entropy,
48  };
49 
50  // Reseed additional input
51  uint8_t reseed_addl_buf[uj_input.reseed_additional_input_len];
52  memcpy(reseed_addl_buf, uj_input.reseed_additional_input,
53  uj_input.reseed_additional_input_len);
54  otcrypto_const_byte_buf_t reseed_addl = {
55  .len = uj_input.reseed_additional_input_len,
56  .data = uj_input.reseed_additional_input,
57  };
58 
59  // First additional input
60  uint8_t addl_1_buf[uj_input.additional_input_1_len];
61  memcpy(addl_1_buf, uj_input.additional_input_1,
62  uj_input.additional_input_1_len);
63  otcrypto_const_byte_buf_t addl_1 = {
64  .len = uj_input.additional_input_1_len,
65  .data = uj_input.additional_input_1,
66  };
67 
68  // Second additional input
69  uint8_t addl_2_buf[uj_input.additional_input_2_len];
70  memcpy(addl_2_buf, uj_input.additional_input_2,
71  uj_input.additional_input_2_len);
72  otcrypto_const_byte_buf_t addl_2 = {
73  .len = uj_input.additional_input_2_len,
74  .data = uj_input.additional_input_2,
75  };
76 
77  // Buffer for random output
78  cryptotest_drbg_output_t uj_output = {
79  .output_len = uj_input.output_len,
80  };
81  size_t output_words = ceil_div(uj_output.output_len, sizeof(uint32_t));
82  otcrypto_word32_buf_t output = {
83  .len = output_words,
84  .data = (uint32_t *)uj_output.output,
85  };
86 
87  // Instantiate DRBG system. We cannot use the FIPS-compliant APIs
88  // because the test vector specifies an entropy string to use.
89  TRY(otcrypto_drbg_manual_instantiate(entropy, perso_string));
90 
91  // Reseed if the test says we need to
92  if (uj_input.reseed) {
93  TRY(otcrypto_drbg_manual_reseed(reseed_entropy, reseed_addl));
94  }
95 
96  // Add first additional input (the test vectors require generating
97  // `output_len` bits of output here, but they may be discarded).
98  TRY(otcrypto_drbg_manual_generate(addl_1, output));
99 
100  // Add second additional input and generate random output
101  TRY(otcrypto_drbg_manual_generate(addl_2, output));
102 
103  // Uninstantiate the DRBG system
105 
106  // Send output to host via UART
107  RESP_OK(ujson_serialize_cryptotest_drbg_output_t, uj, &uj_output);
108  return OK_STATUS(0);
109 }