1 /* stsafe.c
2 *
3 * Copyright (C) 2006-2021 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL.
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20 */
21
22 #include <wolfssl/wolfcrypt/port/st/stsafe.h>
23 #include <wolfssl/wolfcrypt/logging.h>
24
25 #ifndef STSAFE_INTERFACE_PRINTF
26 #define STSAFE_INTERFACE_PRINTF(...)
27 #endif
28
29 #ifdef WOLFSSL_STSAFEA100
30
SSL_STSAFE_LoadDeviceCertificate(byte ** pRawCertificate,word32 * pRawCertificateLen)31 int SSL_STSAFE_LoadDeviceCertificate(byte** pRawCertificate,
32 word32* pRawCertificateLen)
33 {
34 int err;
35
36 if (pRawCertificate == NULL || pRawCertificateLen == NULL) {
37 return BAD_FUNC_ARG;
38 }
39
40 #ifdef USE_STSAFE_VERBOSE
41 WOLFSSL_MSG("SSL_STSAFE_LoadDeviceCertificate");
42 #endif
43
44 /* Try reading device certificate from ST-SAFE Zone 0 */
45 err = stsafe_interface_read_device_certificate_raw(
46 pRawCertificate, (uint32_t*)pRawCertificateLen);
47 if (err == STSAFE_A_OK) {
48 #if 0
49 /* example for loading into WOLFSSL_CTX */
50 err = wolfSSL_CTX_use_certificate_buffer(ctx,
51 *pRawCertificate, *pRawCertificateLen, SSL_FILETYPE_ASN1);
52 if (err != WOLFSSL_SUCCESS) {
53 /* failed */
54 }
55 /* can free now */
56 XFREE(*pRawCertificate, NULL, DYNAMIC_TEMP_BUFFER);
57 *pRawCertificate = NULL;
58 #endif
59 }
60 else {
61 err = WC_HW_E;
62 }
63
64 return err;
65 }
66
67 #ifdef HAVE_PK_CALLBACKS
68
69 /**
70 * \brief Key Gen Callback (used by TLS server)
71 */
SSL_STSAFE_CreateKeyCb(WOLFSSL * ssl,ecc_key * key,word32 keySz,int ecc_curve,void * ctx)72 int SSL_STSAFE_CreateKeyCb(WOLFSSL* ssl, ecc_key* key, word32 keySz,
73 int ecc_curve, void* ctx)
74 {
75 int err;
76 byte pubKeyRaw[STSAFE_MAX_PUBKEY_RAW_LEN];
77 StSafeA_KeySlotNumber slot;
78 StSafeA_CurveId curve_id;
79
80 (void)ssl;
81 (void)ctx;
82
83 #ifdef USE_STSAFE_VERBOSE
84 WOLFSSL_MSG("CreateKeyCb: STSAFE");
85 #endif
86
87 /* get curve */
88 curve_id = stsafe_get_ecc_curve_id(ecc_curve);
89
90 /* generate new ephemeral key on device */
91 err = stsafe_interface_create_key(&slot, curve_id, (uint8_t*)&pubKeyRaw[0]);
92 if (err != STSAFE_A_OK) {
93 #ifdef USE_STSAFE_VERBOSE
94 STSAFE_INTERFACE_PRINTF("stsafe_interface_create_key error: %d\n", err);
95 #endif
96 err = WC_HW_E;
97 return err;
98 }
99
100 /* load generated public key into key, used by wolfSSL */
101 err = wc_ecc_import_unsigned(key, &pubKeyRaw[0], &pubKeyRaw[keySz],
102 NULL, ecc_curve);
103
104 return err;
105 }
106
107 /**
108 * \brief Verify Peer Cert Callback.
109 */
SSL_STSAFE_VerifyPeerCertCb(WOLFSSL * ssl,const unsigned char * sig,unsigned int sigSz,const unsigned char * hash,unsigned int hashSz,const unsigned char * keyDer,unsigned int keySz,int * result,void * ctx)110 int SSL_STSAFE_VerifyPeerCertCb(WOLFSSL* ssl,
111 const unsigned char* sig, unsigned int sigSz,
112 const unsigned char* hash, unsigned int hashSz,
113 const unsigned char* keyDer, unsigned int keySz,
114 int* result, void* ctx)
115 {
116 int err;
117 byte sigRS[STSAFE_MAX_SIG_LEN];
118 byte *r, *s;
119 word32 r_len = STSAFE_MAX_SIG_LEN/2, s_len = STSAFE_MAX_SIG_LEN/2;
120 byte pubKeyX[STSAFE_MAX_PUBKEY_RAW_LEN/2];
121 byte pubKeyY[STSAFE_MAX_PUBKEY_RAW_LEN/2];
122 word32 pubKeyX_len = sizeof(pubKeyX);
123 word32 pubKeyY_len = sizeof(pubKeyY);
124 ecc_key key;
125 word32 inOutIdx = 0;
126 StSafeA_CurveId curve_id;
127 int ecc_curve;
128
129 (void)ssl;
130 (void)ctx;
131
132 #ifdef USE_STSAFE_VERBOSE
133 WOLFSSL_MSG("VerifyPeerCertCB: STSAFE");
134 #endif
135
136 err = wc_ecc_init(&key);
137 if (err != 0) {
138 return err;
139 }
140
141 /* Decode the public key */
142 err = wc_EccPublicKeyDecode(keyDer, &inOutIdx, &key, keySz);
143 if (err == 0) {
144 /* Extract Raw X and Y coordinates of the public key */
145 err = wc_ecc_export_public_raw(&key, pubKeyX, &pubKeyX_len,
146 pubKeyY, &pubKeyY_len);
147 }
148 if (err == 0) {
149 int key_sz;
150
151 /* determine curve */
152 ecc_curve = key.dp->id;
153 curve_id = stsafe_get_ecc_curve_id(ecc_curve);
154 key_sz = stsafe_get_key_size(curve_id);
155
156 /* Extract R and S from signature */
157 XMEMSET(sigRS, 0, sizeof(sigRS));
158 r = &sigRS[0];
159 s = &sigRS[key_sz];
160 err = wc_ecc_sig_to_rs(sig, sigSz, r, &r_len, s, &s_len);
161 (void)r_len;
162 (void)s_len;
163 }
164
165 if (err == 0) {
166 /* Verify signature */
167 err = stsafe_interface_verify(curve_id, (uint8_t*)hash, sigRS,
168 pubKeyX, pubKeyY, (int32_t*)result);
169 if (err != STSAFE_A_OK) {
170 #ifdef USE_STSAFE_VERBOSE
171 STSAFE_INTERFACE_PRINTF("stsafe_interface_verify error: %d\n", err);
172 #endif
173 err = WC_HW_E;
174 }
175 }
176
177 wc_ecc_free(&key);
178 return err;
179 }
180
181 /**
182 * \brief Sign Certificate Callback.
183 */
SSL_STSAFE_SignCertificateCb(WOLFSSL * ssl,const byte * in,word32 inSz,byte * out,word32 * outSz,const byte * key,word32 keySz,void * ctx)184 int SSL_STSAFE_SignCertificateCb(WOLFSSL* ssl, const byte* in,
185 word32 inSz, byte* out, word32* outSz,
186 const byte* key, word32 keySz, void* ctx)
187 {
188 int err;
189 byte digest[STSAFE_MAX_KEY_LEN];
190 byte sigRS[STSAFE_MAX_SIG_LEN];
191 byte *r, *s;
192 StSafeA_CurveId curve_id;
193 int key_sz;
194
195 (void)ssl;
196 (void)ctx;
197
198 #ifdef USE_STSAFE_VERBOSE
199 WOLFSSL_MSG("SignCertificateCb: STSAFE");
200 #endif
201
202 curve_id = stsafe_get_curve_mode();
203 key_sz = stsafe_get_key_size(curve_id);
204
205 /* Build input digest */
206 if (inSz > key_sz)
207 inSz = key_sz;
208 XMEMSET(&digest[0], 0, sizeof(digest));
209 XMEMCPY(&digest[key_sz - inSz], in, inSz);
210
211 /* Sign using slot 0: Result is R then S */
212 /* Sign will always use the curve type in slot 0 (the TLS curve needs to match) */
213 XMEMSET(sigRS, 0, sizeof(sigRS));
214 err = stsafe_interface_sign(STSAFE_A_SLOT_0, curve_id, digest, sigRS);
215 if (err != STSAFE_A_OK) {
216 #ifdef USE_STSAFE_VERBOSE
217 STSAFE_INTERFACE_PRINTF("stsafe_interface_sign error: %d\n", err);
218 #endif
219 err = WC_HW_E;
220 return err;
221 }
222
223 /* Convert R and S to signature */
224 r = &sigRS[0];
225 s = &sigRS[key_sz];
226 err = wc_ecc_rs_raw_to_sig((const byte*)r, key_sz, (const byte*)s, key_sz,
227 out, outSz);
228 if (err != 0) {
229 #ifdef USE_STSAFE_VERBOSE
230 WOLFSSL_MSG("Error converting RS to Signature");
231 #endif
232 }
233
234 return err;
235 }
236
237
238 /**
239 * \brief Create pre master secret using peer's public key and self private key.
240 */
SSL_STSAFE_SharedSecretCb(WOLFSSL * ssl,ecc_key * otherKey,unsigned char * pubKeyDer,unsigned int * pubKeySz,unsigned char * out,unsigned int * outlen,int side,void * ctx)241 int SSL_STSAFE_SharedSecretCb(WOLFSSL* ssl, ecc_key* otherKey,
242 unsigned char* pubKeyDer, unsigned int* pubKeySz,
243 unsigned char* out, unsigned int* outlen,
244 int side, void* ctx)
245 {
246 int err;
247 byte otherKeyX[STSAFE_MAX_KEY_LEN];
248 byte otherKeyY[STSAFE_MAX_KEY_LEN];
249 word32 otherKeyX_len = sizeof(otherKeyX);
250 word32 otherKeyY_len = sizeof(otherKeyY);
251 byte pubKeyRaw[STSAFE_MAX_PUBKEY_RAW_LEN];
252 StSafeA_KeySlotNumber slot;
253 StSafeA_CurveId curve_id;
254 ecc_key tmpKey;
255 int ecc_curve;
256 int key_sz;
257
258 (void)ssl;
259 (void)ctx;
260
261 #ifdef USE_STSAFE_VERBOSE
262 WOLFSSL_MSG("SharedSecretCb: STSAFE");
263 #endif
264
265 err = wc_ecc_init(&tmpKey);
266 if (err != 0) {
267 return err;
268 }
269
270 /* set curve */
271 ecc_curve = otherKey->dp->id;
272 curve_id = stsafe_get_ecc_curve_id(ecc_curve);
273 key_sz = stsafe_get_key_size(curve_id);
274
275 /* for client: create and export public key */
276 if (side == WOLFSSL_CLIENT_END) {
277 /* Export otherKey raw X and Y */
278 err = wc_ecc_export_public_raw(otherKey,
279 &otherKeyX[0], (word32*)&otherKeyX_len,
280 &otherKeyY[0], (word32*)&otherKeyY_len);
281 if (err != 0) {
282 return err;
283 }
284
285 err = stsafe_interface_create_key(&slot, curve_id, (uint8_t*)&pubKeyRaw[0]);
286 if (err != STSAFE_A_OK) {
287 #ifdef USE_STSAFE_VERBOSE
288 STSAFE_INTERFACE_PRINTF("stsafe_interface_create_key error: %d\n", err);
289 #endif
290 err = WC_HW_E;
291 return err;
292 }
293
294 /* convert raw unsigned public key to X.963 format for TLS */
295 err = wc_ecc_init(&tmpKey);
296 if (err == 0) {
297 err = wc_ecc_import_unsigned(&tmpKey, &pubKeyRaw[0], &pubKeyRaw[key_sz],
298 NULL, ecc_curve);
299 if (err == 0) {
300 err = wc_ecc_export_x963(&tmpKey, pubKeyDer, pubKeySz);
301 }
302 wc_ecc_free(&tmpKey);
303 }
304 }
305 /* for server: import public key */
306 else if (side == WOLFSSL_SERVER_END) {
307 /* import peer's key and export as raw unsigned for hardware */
308 err = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, &tmpKey, ecc_curve);
309 if (err == 0) {
310 err = wc_ecc_export_public_raw(&tmpKey, otherKeyX, &otherKeyX_len,
311 otherKeyY, &otherKeyY_len);
312 }
313 }
314 else {
315 err = BAD_FUNC_ARG;
316 }
317
318 wc_ecc_free(&tmpKey);
319
320 if (err != 0) {
321 return err;
322 }
323
324 /* Compute shared secret */
325 err = stsafe_interface_shared_secret(curve_id, &otherKeyX[0], &otherKeyY[0],
326 out, (int32_t*)outlen);
327 if (err != STSAFE_A_OK) {
328 #ifdef USE_STSAFE_VERBOSE
329 STSAFE_INTERFACE_PRINTF("stsafe_interface_shared_secret error: %d\n", err);
330 #endif
331 err = WC_HW_E;
332 }
333
334 return err;
335 }
336
SSL_STSAFE_SetupPkCallbacks(WOLFSSL_CTX * ctx)337 int SSL_STSAFE_SetupPkCallbacks(WOLFSSL_CTX* ctx)
338 {
339 wolfSSL_CTX_SetEccKeyGenCb(ctx, SSL_STSAFE_CreateKeyCb);
340 wolfSSL_CTX_SetEccSignCb(ctx, SSL_STSAFE_SignCertificateCb);
341 wolfSSL_CTX_SetEccVerifyCb(ctx, SSL_STSAFE_VerifyPeerCertCb);
342 wolfSSL_CTX_SetEccSharedSecretCb(ctx, SSL_STSAFE_SharedSecretCb);
343 wolfSSL_CTX_SetDevId(ctx, 0); /* enables wolfCrypt `wc_ecc_*` ST-Safe use */
344 return 0;
345 }
346
SSL_STSAFE_SetupPkCallbackCtx(WOLFSSL * ssl,void * user_ctx)347 int SSL_STSAFE_SetupPkCallbackCtx(WOLFSSL* ssl, void* user_ctx)
348 {
349 wolfSSL_SetEccKeyGenCtx(ssl, user_ctx);
350 wolfSSL_SetEccSharedSecretCtx(ssl, user_ctx);
351 wolfSSL_SetEccSignCtx(ssl, user_ctx);
352 wolfSSL_SetEccVerifyCtx(ssl, user_ctx);
353 return 0;
354 }
355
356
357 #endif /* HAVE_PK_CALLBACKS */
358
359 #ifdef WOLF_CRYPTO_CB
360
wolfSSL_STSAFE_CryptoDevCb(int devId,wc_CryptoInfo * info,void * ctx)361 int wolfSSL_STSAFE_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
362 {
363 int rc = CRYPTOCB_UNAVAILABLE;
364 wolfSTSAFE_CryptoCb_Ctx* stsCtx = (wolfSTSAFE_CryptoCb_Ctx*)ctx;
365
366 if (info == NULL || ctx == NULL)
367 return BAD_FUNC_ARG;
368
369 (void)devId;
370 (void)stsCtx;
371
372 if (info->algo_type == WC_ALGO_TYPE_SEED) {
373 /* use the STSAFE hardware for RNG seed */
374 #if !defined(WC_NO_RNG) && defined(USE_STSAFE_RNG_SEED)
375 while (info->seed.sz > 0) {
376 rc = stsafe_interface_getrandom(info->seed.seed, info->seed.sz);
377 if (rc < 0) {
378 return rc;
379 }
380 info->seed.seed += rc;
381 info->seed.sz -= rc;
382 }
383 rc = 0;
384 #else
385 rc = CRYPTOCB_UNAVAILABLE;
386 #endif
387 }
388 #ifdef HAVE_ECC
389 else if (info->algo_type == WC_ALGO_TYPE_PK) {
390 #ifdef USE_STSAFE_VERBOSE
391 STSAFE_INTERFACE_PRINTF("STSAFE Pk: Type %d\n", info->pk.type);
392 #endif
393
394 if (info->pk.type == WC_PK_TYPE_EC_KEYGEN) {
395 byte pubKeyRaw[STSAFE_MAX_PUBKEY_RAW_LEN];
396 StSafeA_KeySlotNumber slot;
397 StSafeA_CurveId curve_id;
398 int ecc_curve, key_sz;
399
400 WOLFSSL_MSG("STSAFE: ECC KeyGen");
401
402 /* get curve */
403 ecc_curve = info->pk.eckg.curveId;
404 curve_id = stsafe_get_ecc_curve_id(ecc_curve);
405 key_sz = stsafe_get_key_size(curve_id);
406
407 /* generate new ephemeral key on device */
408 rc = stsafe_interface_create_key(&slot, curve_id,
409 (uint8_t*)pubKeyRaw);
410 if (rc != STSAFE_A_OK) {
411 #ifdef USE_STSAFE_VERBOSE
412 STSAFE_INTERFACE_PRINTF("stsafe_interface_create_key error: %d\n", rc);
413 #endif
414 rc = WC_HW_E;
415 return rc;
416 }
417
418 /* load generated public key into key, used by wolfSSL */
419 rc = wc_ecc_import_unsigned(info->pk.eckg.key, pubKeyRaw,
420 &pubKeyRaw[key_sz], NULL, ecc_curve);
421 }
422 else if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) {
423 byte digest[STSAFE_MAX_KEY_LEN];
424 byte sigRS[STSAFE_MAX_SIG_LEN];
425 byte *r, *s;
426 StSafeA_CurveId curve_id;
427 word32 inSz = info->pk.eccsign.inlen;
428 int key_sz;
429
430 WOLFSSL_MSG("STSAFE: ECC Sign");
431
432 curve_id = stsafe_get_curve_mode();
433 key_sz = stsafe_get_key_size(curve_id);
434
435 /* truncate input to match key size */
436 if (inSz > key_sz)
437 inSz = key_sz;
438
439 /* Build input digest */
440 XMEMSET(&digest[0], 0, sizeof(digest));
441 XMEMCPY(&digest[key_sz - inSz], info->pk.eccsign.in, inSz);
442
443 /* Sign using slot 0: Result is R then S */
444 /* Sign will always use the curve type in slot 0
445 (the TLS curve needs to match) */
446 XMEMSET(sigRS, 0, sizeof(sigRS));
447 rc = stsafe_interface_sign(STSAFE_A_SLOT_0, curve_id,
448 (uint8_t*)info->pk.eccsign.in, sigRS);
449 if (rc != STSAFE_A_OK) {
450 #ifdef USE_STSAFE_VERBOSE
451 STSAFE_INTERFACE_PRINTF("stsafe_interface_sign error: %d\n", rc);
452 #endif
453 rc = WC_HW_E;
454 return rc;
455 }
456
457 /* Convert R and S to signature */
458 r = &sigRS[0];
459 s = &sigRS[key_sz];
460 rc = wc_ecc_rs_raw_to_sig((const byte*)r, key_sz, (const byte*)s,
461 key_sz, info->pk.eccsign.out, info->pk.eccsign.outlen);
462 if (rc != 0) {
463 WOLFSSL_MSG("Error converting RS to Signature");
464 }
465 }
466 else if (info->pk.type == WC_PK_TYPE_ECDSA_VERIFY) {
467 byte sigRS[STSAFE_MAX_SIG_LEN];
468 byte *r, *s;
469 word32 r_len = STSAFE_MAX_SIG_LEN/2, s_len = STSAFE_MAX_SIG_LEN/2;
470 byte pubKeyX[STSAFE_MAX_PUBKEY_RAW_LEN/2];
471 byte pubKeyY[STSAFE_MAX_PUBKEY_RAW_LEN/2];
472 word32 pubKeyX_len = sizeof(pubKeyX);
473 word32 pubKeyY_len = sizeof(pubKeyY);
474 StSafeA_CurveId curve_id;
475 int ecc_curve, key_sz;
476
477 WOLFSSL_MSG("STSAFE: ECC Verify");
478
479 if (info->pk.eccverify.key == NULL)
480 return BAD_FUNC_ARG;
481
482 /* determine curve */
483 ecc_curve = info->pk.eccverify.key->dp->id;
484 curve_id = stsafe_get_ecc_curve_id(ecc_curve);
485 key_sz = stsafe_get_key_size(curve_id);
486
487 /* Extract Raw X and Y coordinates of the public key */
488 rc = wc_ecc_export_public_raw(info->pk.eccverify.key,
489 pubKeyX, &pubKeyX_len,
490 pubKeyY, &pubKeyY_len);
491 if (rc == 0) {
492 /* Extract R and S from signature */
493 XMEMSET(sigRS, 0, sizeof(sigRS));
494 r = &sigRS[0];
495 s = &sigRS[key_sz];
496 rc = wc_ecc_sig_to_rs(info->pk.eccverify.sig,
497 info->pk.eccverify.siglen, r, &r_len, s, &s_len);
498 (void)r_len;
499 (void)s_len;
500 }
501 if (rc == 0) {
502 /* Verify signature */
503 rc = stsafe_interface_verify(curve_id,
504 (uint8_t*)info->pk.eccverify.hash, sigRS, pubKeyX, pubKeyY,
505 (int32_t*)info->pk.eccverify.res);
506 if (rc != STSAFE_A_OK) {
507 #ifdef USE_STSAFE_VERBOSE
508 STSAFE_INTERFACE_PRINTF("stsafe_interface_verify error: %d\n", rc);
509 #endif
510 rc = WC_HW_E;
511 }
512 }
513 }
514 else if (info->pk.type == WC_PK_TYPE_ECDH) {
515 byte otherKeyX[STSAFE_MAX_KEY_LEN];
516 byte otherKeyY[STSAFE_MAX_KEY_LEN];
517 word32 otherKeyX_len = sizeof(otherKeyX);
518 word32 otherKeyY_len = sizeof(otherKeyY);
519 StSafeA_CurveId curve_id;
520 int ecc_curve;
521
522 WOLFSSL_MSG("STSAFE: PMS");
523
524 if (info->pk.ecdh.public_key == NULL)
525 return BAD_FUNC_ARG;
526
527 /* get curve */
528 ecc_curve = info->pk.ecdh.public_key->dp->id;
529 curve_id = stsafe_get_ecc_curve_id(ecc_curve);
530
531 /* Export otherKey raw X and Y */
532 rc = wc_ecc_export_public_raw(info->pk.ecdh.public_key,
533 &otherKeyX[0], (word32*)&otherKeyX_len,
534 &otherKeyY[0], (word32*)&otherKeyY_len);
535 if (rc == 0) {
536 /* Compute shared secret */
537 *info->pk.ecdh.outlen = 0;
538 rc = stsafe_interface_shared_secret(curve_id,
539 otherKeyX, otherKeyY,
540 info->pk.ecdh.out, (int32_t*)info->pk.ecdh.outlen);
541 if (rc != STSAFE_A_OK) {
542 #ifdef USE_STSAFE_VERBOSE
543 STSAFE_INTERFACE_PRINTF("stsafe_interface_shared_secret error: %d\n", rc);
544 #endif
545 rc = WC_HW_E;
546 }
547 }
548 }
549 }
550 #endif /* HAVE_ECC */
551
552 /* need to return negative here for error */
553 if (rc != 0 && rc != CRYPTOCB_UNAVAILABLE) {
554 WOLFSSL_MSG("STSAFE: CryptoCb failed");
555 #ifdef USE_STSAFE_VERBOSE
556 STSAFE_INTERFACE_PRINTF("STSAFE: CryptoCb failed %d\n", rc);
557 #endif
558 rc = WC_HW_E;
559 }
560
561 return rc;
562 }
563
564 #endif /* WOLF_CRYPTO_CB */
565
566 #endif /* WOLFSSL_STSAFEA100 */
567