|
2 | 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
3 | 3 | // SPDX-License-Identifier: Apache-2.0 |
4 | 4 |
|
| 5 | +#include "sw/device/lib/base/hardened_memory.h" |
5 | 6 | #include "sw/device/lib/crypto/drivers/otbn.h" |
6 | 7 | #include "sw/device/lib/crypto/impl/keyblob.h" |
7 | 8 | #include "sw/device/lib/crypto/include/config.h" |
@@ -128,29 +129,72 @@ static status_t sign_then_verify_test(void) { |
128 | 129 |
|
129 | 130 | OTTF_DEFINE_TEST_CONFIG(); |
130 | 131 |
|
| 132 | +/** |
| 133 | + * A test where a known input is signed and is compared to the expected output. |
| 134 | + * In addition, it draws randomness to share the known input using |
| 135 | + * hardened_memshred. The input is shared using the hardened_sub_mod function |
| 136 | + * using the P-384 curve order n. |
| 137 | + */ |
131 | 138 | static status_t sign_kat(void) { |
132 | 139 | uint32_t keyblob_len = 2 * kP384SecretScalarWords; |
133 | 140 |
|
| 141 | + // P-384 curve order n, padded to 448 bits (14 words) for our math operations. |
| 142 | + static const uint32_t kP384Order[kP384SecretScalarWords] = { |
| 143 | + 0xCCC52973, 0xECEC196A, 0x48B0A77A, 0x581A0DB2, 0xF4372DDF, |
| 144 | + 0xC7634D81, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
| 145 | + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000}; |
| 146 | + |
| 147 | + uint32_t unmasked_val[kP384SecretScalarWords]; |
| 148 | + uint32_t share1_rand[kP384SecretScalarWords]; |
| 149 | + uint32_t share0[kP384SecretScalarWords]; |
| 150 | + uint32_t share1[kP384SecretScalarWords]; |
| 151 | + |
| 152 | + memset(unmasked_val, 0, kP384SecretScalarBytes); |
| 153 | + memcpy(unmasked_val, kKATSecretScalar, kP384TestVectorScalarInpBytes); |
| 154 | + |
| 155 | + // Generate a random value and reduce it modulo n to get a valid share1 |
| 156 | + TRY(hardened_memshred(share1_rand, kP384SecretScalarWords)); |
| 157 | + TRY(hardened_mod_reduce(share1_rand, kP384Order, kP384SecretScalarWords, |
| 158 | + share1)); |
| 159 | + |
| 160 | + // Calculate share0 = (unmasked_val - share1) mod n |
| 161 | + TRY(hardened_sub_mod(unmasked_val, share1, kP384Order, kP384SecretScalarWords, |
| 162 | + share0)); |
| 163 | + |
134 | 164 | // Allocate space for a masked secret scalar. |
135 | 165 | uint32_t keyblob_scalar[keyblob_len]; |
136 | 166 | otcrypto_blinded_key_t secret_scalar = { |
137 | 167 | .config = kPrivateKeyConfig, |
138 | 168 | .keyblob_length = sizeof(keyblob_scalar), |
139 | 169 | .keyblob = keyblob_scalar, |
140 | 170 | }; |
141 | | - memset(keyblob_scalar, 0, 2 * kP384SecretScalarBytes); |
142 | | - memcpy(keyblob_scalar, kKATSecretScalar, kP384TestVectorScalarInpBytes); |
| 171 | + memcpy(keyblob_scalar, share0, kP384SecretScalarBytes); |
| 172 | + // We copy over the full random bits |
| 173 | + memcpy(keyblob_scalar + kP384SecretScalarWords, share1, |
| 174 | + kP384SecretScalarBytes); |
143 | 175 | secret_scalar.checksum = integrity_blinded_checksum(&secret_scalar); |
144 | 176 |
|
| 177 | + memset(unmasked_val, 0, kP384SecretScalarBytes); |
| 178 | + memcpy(unmasked_val, kKATKey, kP384TestVectorScalarInpBytes); |
| 179 | + |
| 180 | + // Generate new random noise and reduce it modulo n |
| 181 | + TRY(hardened_memshred(share1_rand, kP384SecretScalarWords)); |
| 182 | + TRY(hardened_mod_reduce(share1_rand, kP384Order, kP384SecretScalarWords, |
| 183 | + share1)); |
| 184 | + |
| 185 | + // Calculate share0 = (unmasked_val - share1) mod n |
| 186 | + TRY(hardened_sub_mod(unmasked_val, share1, kP384Order, kP384SecretScalarWords, |
| 187 | + share0)); |
| 188 | + |
145 | 189 | // Allocate space for a masked private key. |
146 | 190 | uint32_t keyblob_sk[keyblob_len]; |
147 | 191 | otcrypto_blinded_key_t private_key = { |
148 | 192 | .config = kPrivateKeyConfig, |
149 | 193 | .keyblob_length = sizeof(keyblob_sk), |
150 | 194 | .keyblob = keyblob_sk, |
151 | 195 | }; |
152 | | - memset(keyblob_sk, 0, 2 * kP384SecretScalarBytes); |
153 | | - memcpy(keyblob_sk, kKATKey, kP384TestVectorScalarInpBytes); |
| 196 | + memcpy(keyblob_sk, share0, kP384SecretScalarBytes); |
| 197 | + memcpy(keyblob_sk + kP384SecretScalarWords, share1, kP384SecretScalarBytes); |
154 | 198 | private_key.checksum = integrity_blinded_checksum(&private_key); |
155 | 199 |
|
156 | 200 | // Hash the message. |
|
0 commit comments