Software APIs
rsa_2048_key_from_cofactor_functest.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 #include "sw/device/lib/crypto/drivers/entropy.h"
7 #include "sw/device/lib/crypto/impl/integrity.h"
8 #include "sw/device/lib/crypto/impl/rsa/rsa_datatypes.h"
11 #include "sw/device/lib/testing/profile.h"
12 #include "sw/device/lib/testing/test_framework/check.h"
14 
15 // Module for status messages.
16 #define MODULE_ID MAKE_MODULE_ID('t', 's', 't')
17 
18 enum {
19  kRsa2048CofactorNumWords = kRsa2048NumWords / 2,
20 };
21 
22 // Note: The private key and valid signatures for this test were generated
23 // out-of-band using the PyCryptodome Python library.
24 
25 // Test RSA-2048 key pair.
26 static uint32_t kTestModulus[kRsa2048NumWords] = {
27  0x40d984b1, 0x3611356d, 0x9eb2f35c, 0x031a892c, 0x16354662, 0x6a260bad,
28  0xb2b807d6, 0xb7de7ccb, 0x278492e0, 0x41adab06, 0x9e60110f, 0x1414eeff,
29  0x8b80e14e, 0x5eb5ae79, 0x0d98fa5b, 0x58bece1f, 0xcf6bdca8, 0x82f5611f,
30  0x351e3869, 0x075005d6, 0xe813fe23, 0xdd967a37, 0x682d1c41, 0x9fdd2d8c,
31  0x21bdd5fc, 0x4fc459c7, 0x508c9293, 0x1f9ac759, 0x55aacb04, 0x58389f05,
32  0x0d0b00fb, 0x59bb4141, 0x68f9e0bf, 0xc2f1a546, 0x0a71ad19, 0x9c400301,
33  0xa4f8ecb9, 0xcdf39538, 0xaabe9cb0, 0xd9f7b2dc, 0x0e8b292d, 0x8ef6c717,
34  0x720e9520, 0xb0c6a23e, 0xda1e92b1, 0x8b6b4800, 0x2f25082b, 0x7f2d6711,
35  0x426fc94f, 0x9926ba5a, 0x89bd4d2b, 0x977718d5, 0x5a8406be, 0x87d090f3,
36  0x639f9975, 0x5948488b, 0x1d3d9cd7, 0x28c7956b, 0xebb97a3e, 0x1edbf4e2,
37  0x105cc797, 0x924ec514, 0x146810df, 0xb1ab4a49,
38 };
39 static uint32_t kTestPrivateExponent[kRsa2048NumWords] = {
40  0x0b19915b, 0xa6a935e6, 0x426b2e10, 0xb4ff0629, 0x7322343b, 0x3f28c8d5,
41  0x190757ce, 0x87409d6b, 0xd88e282b, 0x01c13c2a, 0xebb79189, 0x74cbeab9,
42  0x93de5d54, 0xae1bc80a, 0x083a75f2, 0xd574d229, 0xeb46696e, 0x7648cfb6,
43  0xe7ad1b36, 0xbd0e81b2, 0x19c72703, 0xebea5085, 0xf8c7d152, 0x34dcf84d,
44  0xa437187f, 0x41e4f88e, 0xe4e35f9f, 0xcd8bc6f8, 0x7f98e2f2, 0xffdf75ca,
45  0x3698226e, 0x903f2a56, 0xbf21a6dc, 0x97cbf653, 0xe9d80cb3, 0x55dc1685,
46  0xe0ebae21, 0xc8171e18, 0x8e73d26d, 0xbbdbaac1, 0x886e8007, 0x673c9da4,
47  0xe2cb0698, 0xa9f1ba2d, 0xedab4f0a, 0x197e890c, 0x65e7e736, 0x1de28f24,
48  0x57cf5137, 0x631ff441, 0x22539942, 0xcee3fd41, 0xd22b5f8a, 0x995dd87a,
49  0xcaa6815c, 0x08ca0fd3, 0x8f996093, 0x30b7c446, 0xf69b11f7, 0xa298dd00,
50  0xfd4e8120, 0x059df602, 0x25feb268, 0x0f3f749e,
51 };
52 static uint32_t kTestPublicExponent = 65537;
53 
54 // Key mode for testing.
55 static otcrypto_key_mode_t kTestKeyMode = kOtcryptoKeyModeRsaSignPss;
56 
57 // The prime cofactor p for the test private key.
58 static uint32_t kTestPrimeP[kRsa2048CofactorNumWords] = {
59  0x69e8cdeb, 0xaab5698, 0x2adbf5a2, 0xc6f3fed7, 0x9b0f148c, 0x68a4b636,
60  0xc3c8948c, 0x5ee5c048, 0xb20f9f30, 0xaced9c36, 0xe2a0f71f, 0xf57f3401,
61  0x8fb749f8, 0x24f4b1f2, 0x2811dd24, 0xe45d624, 0x7e4fac27, 0x7049a420,
62  0x4ea4172b, 0x1d4f1d2d, 0x15c1dd03, 0x733ce8c1, 0xe5415c61, 0xa3680f9a,
63  0xa13ff562, 0xd12a0242, 0x3ef684a4, 0x5241db6e, 0x2e68b5f5, 0xaa3e5397,
64  0x45e9606a, 0xb8505888,
65 };
66 // The prime cofactor q for the test private key.
67 static uint32_t kTestPrimeQ[kRsa2048CofactorNumWords] = {
68  0xc69864d3, 0x6eca1793, 0xd985ff65, 0xa888cce8, 0xcadcabc5, 0x47d31ff8,
69  0x2eae994a, 0xba8594d, 0x956889ed, 0x117f0b01, 0x30ace812, 0x89aa41b9,
70  0x716c8c93, 0xb3e54154, 0x70020ae3, 0x3f3926af, 0x91ae5a18, 0xa058daef,
71  0xd5a8a0ee, 0xff73e9fb, 0xda00591c, 0x69220aec, 0xe9ee684b, 0x12f4ea77,
72  0xea538fb5, 0x505826e, 0xef416b24, 0x5c65d8d6, 0xce422bd4, 0x3f4f37ed,
73  0xdd6aff12, 0xf6c55808,
74 };
75 
76 /**
77  * Helper function to run the key-from-cofactor routine.
78  *
79  * Packages input into cryptolib-style structs and calls
80  * `otcrypto_rsa_private_key_from_public_and_cofactor` using the constant test
81  * public key and the given cofactor. Ensures that the resulting private
82  * exponent matches the test private exponent.
83  *
84  * @param cofactor Pointer to the cofactor data.
85  * @return OK or error.
86  */
87 static status_t run_key_from_cofactor(const uint32_t *cofactor) {
88  // Create two shares for the cofactor (second share is all-zero).
89  otcrypto_const_word32_buf_t cofactor_share0 = {
90  .data = cofactor,
91  .len = kRsa2048CofactorNumWords,
92  };
93  uint32_t cofactor_share1_data[kRsa2048CofactorNumWords] = {0};
94  otcrypto_const_word32_buf_t cofactor_share1 = {
95  .data = cofactor_share1_data,
96  .len = ARRAYSIZE(cofactor_share1_data),
97  };
98 
99  // Buffer for the modulus.
100  otcrypto_const_word32_buf_t modulus = {
101  .data = kTestModulus,
102  .len = ARRAYSIZE(kTestModulus),
103  };
104 
105  // Construct the private key buffer and configuration.
106  otcrypto_key_config_t private_key_config = {
107  .version = kOtcryptoLibVersion1,
108  .key_mode = kTestKeyMode,
109  .key_length = kOtcryptoRsa2048PrivateKeyBytes,
110  .hw_backed = kHardenedBoolFalse,
111  .security_level = kOtcryptoKeySecurityLevelLow,
112  };
113  size_t keyblob_words =
115  uint32_t keyblob[keyblob_words];
116  otcrypto_blinded_key_t private_key = {
117  .config = private_key_config,
118  .keyblob = keyblob,
119  .keyblob_length = kOtcryptoRsa2048PrivateKeyblobBytes,
120  };
121 
122  // Construct the public key buffer.
123  size_t public_key_words =
124  ceil_div(kOtcryptoRsa2048PublicKeyBytes, sizeof(uint32_t));
125  uint32_t public_key_data[public_key_words];
126  otcrypto_unblinded_key_t public_key = {
127  .key_mode = kTestKeyMode,
128  .key = public_key_data,
129  .key_length = kOtcryptoRsa2048PublicKeyBytes,
130  };
131 
132  // Construct the RSA key pair using the cofactor.
133  uint64_t t_start = profile_start();
135  kOtcryptoRsaSize2048, modulus, kTestPublicExponent, cofactor_share0,
136  cofactor_share1, &public_key, &private_key));
137  profile_end_and_print(t_start, "RSA keypair from cofactor");
138 
139  // Interpret the private key and ensure the private exponent matches the
140  // expected value. Note: This depends on the internal representation of RSA
141  // keyblobs, and will need to be updated if the representation changes.
142  TRY_CHECK(private_key.keyblob_length == sizeof(rsa_2048_private_key_t));
143  rsa_2048_private_key_t *sk = (rsa_2048_private_key_t *)private_key.keyblob;
144  TRY_CHECK_ARRAYS_EQ(sk->d.data, kTestPrivateExponent,
145  ARRAYSIZE(kTestPrivateExponent));
146 
147  // Check the other values too, just to be safe.
148  TRY_CHECK_ARRAYS_EQ(sk->n.data, kTestModulus, ARRAYSIZE(kTestModulus));
149  TRY_CHECK(public_key.key_length == sizeof(rsa_2048_public_key_t));
150  rsa_2048_public_key_t *pk = (rsa_2048_public_key_t *)public_key.key;
151  TRY_CHECK_ARRAYS_EQ(pk->n.data, kTestModulus, ARRAYSIZE(kTestModulus));
152  TRY_CHECK(pk->e == kTestPublicExponent);
153  return OK_STATUS();
154 }
155 
156 status_t keypair_from_p_test(void) {
157  return run_key_from_cofactor(kTestPrimeP);
158 }
159 
160 status_t keypair_from_q_test(void) {
161  return run_key_from_cofactor(kTestPrimeQ);
162 }
163 
164 OTTF_DEFINE_TEST_CONFIG();
165 
166 bool test_main(void) {
167  status_t test_result = OK_STATUS();
168  CHECK_STATUS_OK(entropy_complex_init());
169  EXECUTE_TEST(test_result, keypair_from_p_test);
170  EXECUTE_TEST(test_result, keypair_from_q_test);
171  return status_ok(test_result);
172 }