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