22// Licensed under the Apache License, Version 2.0, see LICENSE for details.
33// SPDX-License-Identifier: Apache-2.0
44
5+ #include "sw/device/lib/base/hardened_memory.h"
56#include "sw/device/lib/base/memory.h"
67#include "sw/device/lib/crypto/include/datatypes.h"
78#include "sw/device/lib/crypto/include/ecc_p256.h"
7576 *
7677 * @param d Private key.
7778 * @param qx Public key x coordinate.
78- * @param qx Public key y coordinate.
79+ * @param qy Public key y coordinate.
7980 * @param[out] ss Shared secret key.
8081 * @param[out] valid Whether the input arguments were valid.
8182 * @return Status code (OK or error).
@@ -102,11 +103,7 @@ static status_t ecdh_p256(cryptotest_ecdh_private_key_t d,
102103 }
103104
104105 // Construct the private key object.
105- // TODO(#20762): once key-import exists for ECDH, use that instead.
106106 uint32_t private_keyblob [kP256MaskedPrivateKeyWords * 2 ];
107- memset (private_keyblob , 0 , sizeof (private_keyblob ));
108- memcpy (private_keyblob , d .d0 , d .d0_len );
109- memcpy (private_keyblob + kP256MaskedPrivateKeyWords , d .d1 , d .d1_len );
110107 otcrypto_blinded_key_t private_key = {
111108 .config =
112109 {
@@ -120,21 +117,54 @@ static status_t ecdh_p256(cryptotest_ecdh_private_key_t d,
120117 .keyblob_length = sizeof (private_keyblob ),
121118 .keyblob = private_keyblob ,
122119 };
123- private_key .checksum = integrity_blinded_checksum (& private_key );
120+
121+ uint32_t p256_share0_data [kP256MaskedPrivateKeyWords ] = {0 };
122+ uint32_t p256_share1_data [kP256MaskedPrivateKeyWords ] = {0 };
123+ memcpy (p256_share0_data , d .d0 , d .d0_len );
124+ memcpy (p256_share1_data , d .d1 , d .d1_len );
125+
126+ otcrypto_const_word32_buf_t share0 =
127+ OTCRYPTO_MAKE_BUF (otcrypto_const_word32_buf_t , p256_share0_data ,
128+ kP256MaskedPrivateKeyWords );
129+ otcrypto_const_word32_buf_t share1 =
130+ OTCRYPTO_MAKE_BUF (otcrypto_const_word32_buf_t , p256_share1_data ,
131+ kP256MaskedPrivateKeyWords );
132+
133+ otcrypto_status_t priv_status =
134+ otcrypto_ecc_p256_private_key_import (share0 , share1 , & private_key );
135+ if (priv_status .value == kOtcryptoStatusValueBadArgs ) {
136+ * valid = false;
137+ memset (ss , 0 , kP256SharedSecretBytes );
138+ return OK_STATUS ();
139+ }
140+ TRY (priv_status );
124141
125142 // Construct the public key object.
126- // TODO(#20762): once key-import exists for ECDH, use that instead.
127143 uint32_t public_key_buf [kP256CoordinateWords * 2 ];
128- memset (public_key_buf , 0 , sizeof (public_key_buf ));
129- memcpy (public_key_buf , qx .coordinate , qx .coordinate_len );
130- memcpy (public_key_buf + kP256CoordinateWords , qy .coordinate ,
131- qy .coordinate_len );
132144 otcrypto_unblinded_key_t public_key = {
133145 .key_mode = kOtcryptoKeyModeEcdhP256 ,
134146 .key_length = sizeof (public_key_buf ),
135147 .key = public_key_buf ,
136148 };
137- public_key .checksum = integrity_unblinded_checksum (& public_key );
149+
150+ uint32_t p256_x_data [kP256CoordinateWords ] = {0 };
151+ uint32_t p256_y_data [kP256CoordinateWords ] = {0 };
152+ memcpy (p256_x_data , qx .coordinate , qx .coordinate_len );
153+ memcpy (p256_y_data , qy .coordinate , qy .coordinate_len );
154+
155+ otcrypto_const_word32_buf_t x = OTCRYPTO_MAKE_BUF (
156+ otcrypto_const_word32_buf_t , p256_x_data , kP256CoordinateWords );
157+ otcrypto_const_word32_buf_t y = OTCRYPTO_MAKE_BUF (
158+ otcrypto_const_word32_buf_t , p256_y_data , kP256CoordinateWords );
159+
160+ otcrypto_status_t pub_status =
161+ otcrypto_ecc_p256_public_key_import (x , y , & public_key );
162+ if (pub_status .value == kOtcryptoStatusValueBadArgs ) {
163+ * valid = false;
164+ memset (ss , 0 , kP256SharedSecretBytes );
165+ return OK_STATUS ();
166+ }
167+ TRY (pub_status );
138168
139169 // Create a destination for the shared secret.
140170 size_t shared_secret_words = kP256SharedSecretBytes / sizeof (uint32_t );
@@ -174,16 +204,14 @@ static status_t ecdh_p256(cryptotest_ecdh_private_key_t d,
174204 }
175205
176206 // Unmask the shared secret.
177- uint32_t share0 [shared_secret_words ];
178- uint32_t share1 [shared_secret_words ];
179- otcrypto_word32_buf_t share0_buf =
180- OTCRYPTO_MAKE_BUF ( otcrypto_word32_buf_t , share0 , ARRAYSIZE (share0 ));
181- otcrypto_word32_buf_t share1_buf =
182- OTCRYPTO_MAKE_BUF ( otcrypto_word32_buf_t , share1 , ARRAYSIZE (share1 ));
207+ uint32_t dest_share0 [shared_secret_words ];
208+ uint32_t dest_share1 [shared_secret_words ];
209+ otcrypto_word32_buf_t share0_buf = OTCRYPTO_MAKE_BUF (
210+ otcrypto_word32_buf_t , dest_share0 , ARRAYSIZE (dest_share0 ));
211+ otcrypto_word32_buf_t share1_buf = OTCRYPTO_MAKE_BUF (
212+ otcrypto_word32_buf_t , dest_share1 , ARRAYSIZE (dest_share1 ));
183213 TRY (otcrypto_export_blinded_key (& shared_secret , & share0_buf , & share1_buf ));
184- for (size_t i = 0 ; i < shared_secret_words ; i ++ ) {
185- ss [i ] = share0 [i ] ^ share1 [i ];
186- }
214+ TRY (hardened_xor (dest_share0 , dest_share1 , shared_secret_words , ss ));
187215 return OK_STATUS ();
188216}
189217
@@ -198,7 +226,7 @@ static status_t ecdh_p256(cryptotest_ecdh_private_key_t d,
198226 *
199227 * @param d Private key.
200228 * @param qx Public key x coordinate.
201- * @param qx Public key y coordinate.
229+ * @param qy Public key y coordinate.
202230 * @param[out] ss Shared secret key.
203231 * @param[out] valid Whether the input arguments were valid.
204232 * @return Status code (OK or error).
@@ -225,13 +253,7 @@ static status_t ecdh_p384(cryptotest_ecdh_private_key_t d,
225253 }
226254
227255 // Construct the private key object.
228- // TODO(#20762): once key-import exists for ECDH, use that instead.
229- // Note: the test harness does not produce the extra masking bytes; leave
230- // them zeroed.
231256 uint32_t private_keyblob [kP384MaskedPrivateKeyWords * 2 ];
232- memset (private_keyblob , 0 , sizeof (private_keyblob ));
233- memcpy (private_keyblob , d .d0 , d .d0_len );
234- memcpy (private_keyblob + kP384MaskedPrivateKeyWords , d .d1 , d .d1_len );
235257 otcrypto_blinded_key_t private_key = {
236258 .config =
237259 {
@@ -245,21 +267,56 @@ static status_t ecdh_p384(cryptotest_ecdh_private_key_t d,
245267 .keyblob_length = sizeof (private_keyblob ),
246268 .keyblob = private_keyblob ,
247269 };
248- private_key .checksum = integrity_blinded_checksum (& private_key );
270+
271+ // Note: the test harness might not produce the extra masking bytes; leaving
272+ // them safely zeroed by explicitly copying into padded buffers.
273+ uint32_t p384_share0_data [kP384MaskedPrivateKeyWords ] = {0 };
274+ uint32_t p384_share1_data [kP384MaskedPrivateKeyWords ] = {0 };
275+ memcpy (p384_share0_data , d .d0 , d .d0_len );
276+ memcpy (p384_share1_data , d .d1 , d .d1_len );
277+
278+ otcrypto_const_word32_buf_t share0 =
279+ OTCRYPTO_MAKE_BUF (otcrypto_const_word32_buf_t , p384_share0_data ,
280+ kP384MaskedPrivateKeyWords );
281+ otcrypto_const_word32_buf_t share1 =
282+ OTCRYPTO_MAKE_BUF (otcrypto_const_word32_buf_t , p384_share1_data ,
283+ kP384MaskedPrivateKeyWords );
284+
285+ otcrypto_status_t priv_status =
286+ otcrypto_ecc_p384_private_key_import (share0 , share1 , & private_key );
287+ if (priv_status .value == kOtcryptoStatusValueBadArgs ) {
288+ * valid = false;
289+ memset (ss , 0 , kP384SharedSecretBytes );
290+ return OK_STATUS ();
291+ }
292+ TRY (priv_status );
249293
250294 // Construct the public key object.
251- // TODO(#20762): once key-import exists for ECDH, use that instead.
252295 uint32_t public_key_buf [kP384CoordinateWords * 2 ];
253- memset (public_key_buf , 0 , sizeof (public_key_buf ));
254- memcpy (public_key_buf , qx .coordinate , qx .coordinate_len );
255- memcpy (public_key_buf + kP384CoordinateWords , qy .coordinate ,
256- qy .coordinate_len );
257296 otcrypto_unblinded_key_t public_key = {
258297 .key_mode = kOtcryptoKeyModeEcdhP384 ,
259298 .key_length = sizeof (public_key_buf ),
260299 .key = public_key_buf ,
261300 };
262- public_key .checksum = integrity_unblinded_checksum (& public_key );
301+
302+ uint32_t p384_x_data [kP384CoordinateWords ] = {0 };
303+ uint32_t p384_y_data [kP384CoordinateWords ] = {0 };
304+ memcpy (p384_x_data , qx .coordinate , qx .coordinate_len );
305+ memcpy (p384_y_data , qy .coordinate , qy .coordinate_len );
306+
307+ otcrypto_const_word32_buf_t x = OTCRYPTO_MAKE_BUF (
308+ otcrypto_const_word32_buf_t , p384_x_data , kP384CoordinateWords );
309+ otcrypto_const_word32_buf_t y = OTCRYPTO_MAKE_BUF (
310+ otcrypto_const_word32_buf_t , p384_y_data , kP384CoordinateWords );
311+
312+ otcrypto_status_t pub_status =
313+ otcrypto_ecc_p384_public_key_import (x , y , & public_key );
314+ if (pub_status .value == kOtcryptoStatusValueBadArgs ) {
315+ * valid = false;
316+ memset (ss , 0 , kP384SharedSecretBytes );
317+ return OK_STATUS ();
318+ }
319+ TRY (pub_status );
263320
264321 // Create a destination for the shared secret.
265322 size_t shared_secret_words = kP384SharedSecretBytes / sizeof (uint32_t );
@@ -299,16 +356,14 @@ static status_t ecdh_p384(cryptotest_ecdh_private_key_t d,
299356 }
300357
301358 // Unmask the shared secret.
302- uint32_t share0 [shared_secret_words ];
303- uint32_t share1 [shared_secret_words ];
304- otcrypto_word32_buf_t share0_buf =
305- OTCRYPTO_MAKE_BUF ( otcrypto_word32_buf_t , share0 , ARRAYSIZE (share0 ));
306- otcrypto_word32_buf_t share1_buf =
307- OTCRYPTO_MAKE_BUF ( otcrypto_word32_buf_t , share1 , ARRAYSIZE (share1 ));
359+ uint32_t dest_share0 [shared_secret_words ];
360+ uint32_t dest_share1 [shared_secret_words ];
361+ otcrypto_word32_buf_t share0_buf = OTCRYPTO_MAKE_BUF (
362+ otcrypto_word32_buf_t , dest_share0 , ARRAYSIZE (dest_share0 ));
363+ otcrypto_word32_buf_t share1_buf = OTCRYPTO_MAKE_BUF (
364+ otcrypto_word32_buf_t , dest_share1 , ARRAYSIZE (dest_share1 ));
308365 TRY (otcrypto_export_blinded_key (& shared_secret , & share0_buf , & share1_buf ));
309- for (size_t i = 0 ; i < shared_secret_words ; i ++ ) {
310- ss [i ] = share0 [i ] ^ share1 [i ];
311- }
366+ TRY (hardened_xor (dest_share0 , dest_share1 , shared_secret_words , ss ));
312367 return OK_STATUS ();
313368}
314369
0 commit comments