1 /*!
2     \ingroup IoTSafe
3     \brief This function enables the IoT-Safe support on the given context.
4 
5     \param ctx pointer to the WOLFSSL_CTX object on which the IoT-safe support must be enabled
6     \return 0 on success
7     \return WC_HW_E on hardware error
8 
9     _Example_
10     \code
11     WOLFSSL_CTX *ctx;
12     ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
13     if (!ctx)
14         return NULL;
15     wolfSSL_CTX_iotsafe_enable(ctx);
16     \endcode
17 
18     \sa wolfSSL_iotsafe_on
19     \sa wolfIoTSafe_SetCSIM_read_cb
20     \sa wolfIoTSafe_SetCSIM_write_cb
21 */
22 WOLFSSL_API int wolfSSL_CTX_iotsafe_enable(WOLFSSL_CTX *ctx);
23 
24 
25 /*!
26     \ingroup IoTSafe
27     \brief This function connects the IoT-Safe TLS callbacks to the given SSL session.
28     \brief This should be called to connect a SSL session to IoT-Safe applet when the
29            ID of the slots are one-byte long.
30            If IoT-SAFE slots have an ID of two or more bytes, \ref wolfSSL_iotsafe_on_ex "wolfSSL_iotsafe_on_ex()"
31            should be used instead.
32 
33     \param ssl pointer to the WOLFSSL object where the callbacks will be enabled
34     \param privkey_id id of the iot-safe applet slot containing the private key for the host
35     \param ecdh_keypair_slot id of the iot-safe applet slot to store the ECDH keypair
36     \param peer_pubkey_slot id of the iot-safe applet slot to store the other endpoint's public key for ECDH
37     \param peer_cert_slot id of the iot-safe applet slot to store the other endpoint's public key for verification
38     \return 0 upon success
39     \return NOT_COMPILED_IN if HAVE_PK_CALLBACKS is disabled
40     \return BAD_FUNC_ARG if the ssl pointer is invalid
41 
42     _Example_
43     \code
44     // Define key ids for IoT-Safe
45     #define PRIVKEY_ID 0x02
46     #define ECDH_KEYPAIR_ID 0x03
47     #define PEER_PUBKEY_ID 0x04
48     #define PEER_CERT_ID 0x05
49     // Create new ssl session
50     WOLFSSL *ssl;
51     ssl = wolfSSL_new(ctx);
52     if (!ssl)
53         return NULL;
54     // Enable IoT-Safe and associate key slots
55     ret = wolfSSL_CTX_iotsafe_enable(ctx);
56     if (ret == 0) {
57         ret = wolfSSL_iotsafe_on(ssl, PRIVKEY_ID, ECDH_KEYPAIR_ID, PEER_PUBKEY_ID, PEER_CERT_ID);
58     }
59     \endcode
60 
61     \sa wolfSSL_iotsafe_on_ex
62     \sa wolfSSL_CTX_iotsafe_enable
63 */
64 WOLFSSL_API int wolfSSL_iotsafe_on(WOLFSSL *ssl, byte privkey_id,
65        byte ecdh_keypair_slot, byte peer_pubkey_slot, byte peer_cert_slot);
66 
67 
68 /*!
69     \ingroup IoTSafe
70     \brief This function connects the IoT-Safe TLS callbacks to the given SSL session.
71            This is equivalent to \ref wolfSSL_iotsafe_on "wolfSSL_iotsafe_on" except that the IDs for the IoT-SAFE
72            slots can be passed by reference, and the length of the ID fields can be specified via
73            the parameter "id_size".
74 
75 
76     \param ssl pointer to the WOLFSSL object where the callbacks will be enabled
77     \param privkey_id pointer to the id of the iot-safe applet slot containing the private key for the host
78     \param ecdh_keypair_slot pointer to the id of the iot-safe applet slot to store the ECDH keypair
79     \param peer_pubkey_slot pointer to the of id the iot-safe applet slot to store the other endpoint's public key for ECDH
80     \param peer_cert_slot pointer to the id of the iot-safe applet slot to store the other endpoint's public key for verification
81     \param id_size size of each slot ID
82     \return 0 upon success
83     \return NOT_COMPILED_IN if HAVE_PK_CALLBACKS is disabled
84     \return BAD_FUNC_ARG if the ssl pointer is invalid
85 
86     _Example_
87     \code
88     // Define key ids for IoT-Safe (16 bit, little endian)
89     #define PRIVKEY_ID 0x0201
90     #define ECDH_KEYPAIR_ID 0x0301
91     #define PEER_PUBKEY_ID 0x0401
92     #define PEER_CERT_ID 0x0501
93     #define ID_SIZE (sizeof(word16))
94 
95     word16 privkey = PRIVKEY_ID,
96              ecdh_keypair = ECDH_KEYPAIR_ID,
97              peer_pubkey = PEER_PUBKEY_ID,
98              peer_cert = PEER_CERT_ID;
99 
100 
101 
102     // Create new ssl session
103     WOLFSSL *ssl;
104     ssl = wolfSSL_new(ctx);
105     if (!ssl)
106         return NULL;
107     // Enable IoT-Safe and associate key slots
108     ret = wolfSSL_CTX_iotsafe_enable(ctx);
109     if (ret == 0) {
110         ret = wolfSSL_CTX_iotsafe_on_ex(ssl, &privkey, &ecdh_keypair, &peer_pubkey, &peer_cert, ID_SIZE);
111     }
112     \endcode
113 
114     \sa wolfSSL_iotsafe_on
115     \sa wolfSSL_CTX_iotsafe_enable
116 */
117 WOLFSSL_API int wolfSSL_iotsafe_on_ex(WOLFSSL *ssl, byte *privkey_id,
118        byte *ecdh_keypair_slot, byte *peer_pubkey_slot, byte *peer_cert_slot, word16 id_size);
119 
120 
121 /*!
122     \ingroup IoTSafe
123     \brief Associates a read callback for the AT+CSIM commands. This input function is
124     usually associated to a read event of a UART channel communicating with the modem.
125     The read callback associated is global and changes for all the contexts that use
126     IoT-safe support at the same time.
127     \param rf Read callback associated to a UART read event. The callback function takes
128     two arguments (buf, len) and return the number of characters read, up to len. When a
129     newline is encountered, the callback should return the number of characters received
130     so far, including the newline character.
131 
132     _Example_
133     \code
134 
135     // USART read function, defined elsewhere
136     int usart_read(char *buf, int len);
137 
138     wolfIoTSafe_SetCSIM_read_cb(usart_read);
139 
140     \endcode
141 
142     \sa wolfIoTSafe_SetCSIM_write_cb
143 */
144 WOLFSSL_API void wolfIoTSafe_SetCSIM_read_cb(wolfSSL_IOTSafe_CSIM_read_cb rf);
145 
146 /*!
147     \ingroup IoTSafe
148     \brief Associates a write callback for the AT+CSIM commands. This output function is
149     usually associated to a write event on a UART channel communicating with the modem.
150     The write callback associated is global and changes for all the contexts that use
151     IoT-safe support at the same time.
152     \param rf Write callback associated to a UART write event. The callback function takes
153     two arguments (buf, len) and return the number of characters written, up to len.
154 
155     _Example_
156     \code
157     // USART write function, defined elsewhere
158     int usart_write(const char *buf, int len);
159     wolfIoTSafe_SetCSIM_write_cb(usart_write);
160     \endcode
161 
162     \sa wolfIoTSafe_SetCSIM_read_cb
163 */
164 WOLFSSL_API void wolfIoTSafe_SetCSIM_write_cb(wolfSSL_IOTSafe_CSIM_write_cb wf);
165 
166 
167 
168 /*!
169     \ingroup IoTSafe
170     \brief Generate a random buffer of given size, using the IoT-Safe function
171     GetRandom. This function is automatically used by the wolfCrypt RNG object.
172 
173     \param out the buffer where the random sequence of bytes is stored.
174     \param sz the size of the random sequence to generate, in bytes
175     \return 0 upon success
176 
177 */
178 WOLFSSL_API int wolfIoTSafe_GetRandom(unsigned char* out, word32 sz);
179 
180 
181 /*!
182     \ingroup IoTSafe
183     \brief Import a certificate stored in a file on IoT-Safe applet, and
184     store it locally in memory. Works with one-byte file ID field.
185 
186     \param id The file id in the IoT-Safe applet where the certificate is stored
187     \param output the buffer where the certificate will be imported
188     \param sz the maximum size available in the buffer output
189     \return the length of the certificate imported
190     \return < 0 in case of failure
191 
192     _Example_
193     \code
194     #define CRT_CLIENT_FILE_ID 0x03
195     unsigned char cert_buffer[2048];
196     // Get the certificate into the buffer
197     cert_buffer_size = wolfIoTSafe_GetCert(CRT_CLIENT_FILE_ID, cert_buffer, 2048);
198     if (cert_buffer_size < 1) {
199         printf("Bad cli cert\n");
200         return -1;
201     }
202     printf("Loaded Client certificate from IoT-Safe, size = %lu\n", cert_buffer_size);
203 
204     // Use the certificate buffer as identity for the TLS client context
205     if (wolfSSL_CTX_use_certificate_buffer(cli_ctx, cert_buffer,
206                 cert_buffer_size, SSL_FILETYPE_ASN1) != SSL_SUCCESS) {
207         printf("Cannot load client cert\n");
208         return -1;
209     }
210     printf("Client certificate successfully imported.\n");
211     \endcode
212 
213 */
214 WOLFSSL_API int wolfIoTSafe_GetCert(uint8_t id, unsigned char *output, unsigned long sz);
215 
216 
217 /*!
218     \ingroup IoTSafe
219     \brief Import a certificate stored in a file on IoT-Safe applet, and
220     store it locally in memory. Equivalent to \ref wolfIoTSafe_GetCert "wolfIoTSafe_GetCert",
221     except that it can be invoked with a file ID of two or more bytes.
222 
223     \param id Pointer to the file id in the IoT-Safe applet where the certificate is stored
224     \param id_sz Size of the file id in bytes
225     \param output the buffer where the certificate will be imported
226     \param sz the maximum size available in the buffer output
227     \return the length of the certificate imported
228     \return < 0 in case of failure
229 
230     _Example_
231     \code
232     #define CRT_CLIENT_FILE_ID 0x0302
233     #define ID_SIZE (sizeof(word16))
234     unsigned char cert_buffer[2048];
235     word16 client_file_id = CRT_CLIENT_FILE_ID;
236 
237 
238 
239     // Get the certificate into the buffer
240     cert_buffer_size = wolfIoTSafe_GetCert_ex(&client_file_id, ID_SIZE, cert_buffer, 2048);
241     if (cert_buffer_size < 1) {
242         printf("Bad cli cert\n");
243         return -1;
244     }
245     printf("Loaded Client certificate from IoT-Safe, size = %lu\n", cert_buffer_size);
246 
247     // Use the certificate buffer as identity for the TLS client context
248     if (wolfSSL_CTX_use_certificate_buffer(cli_ctx, cert_buffer,
249                 cert_buffer_size, SSL_FILETYPE_ASN1) != SSL_SUCCESS) {
250         printf("Cannot load client cert\n");
251         return -1;
252     }
253     printf("Client certificate successfully imported.\n");
254     \endcode
255 
256 */
257 WOLFSSL_API int wolfIoTSafe_GetCert_ex(uint8_t *id, uint16_t id_sz, unsigned char *output, unsigned long sz);
258 
259 /*!
260     \ingroup IoTSafe
261     \brief Import an ECC 256-bit public key, stored in the IoT-Safe applet, into an ecc_key
262     object.
263 
264     \param key the ecc_key object that will contain the key imported from the IoT-Safe applet
265     \param id The key id in the IoT-Safe applet where the public key is stored
266     \return 0 upon success
267     \return < 0 in case of failure
268 
269 
270     \sa wc_iotsafe_ecc_export_public
271     \sa wc_iotsafe_ecc_export_private
272 
273 */
274 WOLFSSL_API int wc_iotsafe_ecc_import_public(ecc_key *key, byte key_id);
275 
276 /*!
277     \ingroup IoTSafe
278     \brief Export an ECC 256-bit public key, from ecc_key object to a writable public-key slot into the IoT-Safe applet.
279     \param key the ecc_key object containing the key to be exported
280     \param id The key id in the IoT-Safe applet where the public key will be stored
281     \return 0 upon success
282     \return < 0 in case of failure
283 
284 
285     \sa wc_iotsafe_ecc_import_public_ex
286     \sa wc_iotsafe_ecc_export_private
287 
288 */
289 WOLFSSL_API int wc_iotsafe_ecc_export_public(ecc_key *key, byte key_id);
290 
291 
292 /*!
293     \ingroup IoTSafe
294     \brief Export an ECC 256-bit public key, from ecc_key object to a writable public-key slot into the IoT-Safe applet.
295            Equivalent to \ref wc_iotsafe_ecc_import_public "wc_iotsafe_ecc_import_public",
296            except that it can be invoked with a key ID of two or more bytes.
297     \param key the ecc_key object containing the key to be exported
298     \param id The pointer to the key id in the IoT-Safe applet where the public key will be stored
299     \param id_size The key id size
300 
301     \return 0 upon success
302     \return < 0 in case of failure
303 
304 
305     \sa wc_iotsafe_ecc_import_public
306     \sa wc_iotsafe_ecc_export_private
307 
308 */
309 WOLFSSL_API int wc_iotsafe_ecc_import_public_ex(ecc_key *key, byte *key_id, word16 id_size);
310 
311 /*!
312     \ingroup IoTSafe
313     \brief Export an ECC 256-bit key, from ecc_key object to a writable private-key slot into the IoT-Safe applet.
314     \param key the ecc_key object containing the key to be exported
315     \param id The key id in the IoT-Safe applet where the private key will be stored
316     \return 0 upon success
317     \return < 0 in case of failure
318 
319 
320     \sa wc_iotsafe_ecc_export_private_ex
321     \sa wc_iotsafe_ecc_import_public
322     \sa wc_iotsafe_ecc_export_public
323 
324 */
325 WOLFSSL_API int wc_iotsafe_ecc_export_private(ecc_key *key, byte key_id);
326 
327 /*!
328     \ingroup IoTSafe
329     \brief Export an ECC 256-bit key, from ecc_key object to a writable private-key slot into the IoT-Safe applet.
330            Equivalent to \ref wc_iotsafe_ecc_export_private "wc_iotsafe_ecc_export_private",
331            except that it can be invoked with a key ID of two or more bytes.
332 
333     \param key the ecc_key object containing the key to be exported
334     \param id The pointer to the key id in the IoT-Safe applet where the private key will be stored
335     \param id_size The key id size
336     \return 0 upon success
337     \return < 0 in case of failure
338 
339 
340     \sa wc_iotsafe_ecc_export_private
341     \sa wc_iotsafe_ecc_import_public
342     \sa wc_iotsafe_ecc_export_public
343 
344 */
345 WOLFSSL_API int wc_iotsafe_ecc_export_private_ex(ecc_key *key, byte *key_id, word16 id_size);
346 
347 /*!
348     \ingroup IoTSafe
349     \brief Sign a pre-computed 256-bit HASH, using a private key previously stored, or pre-provisioned,
350     in the IoT-Safe applet.
351 
352     \param in pointer to the buffer containing the message hash to sign
353     \param inlen length of the message hash to sign
354     \param out buffer in which to store the generated signature
355     \param outlen max length of the output buffer. Will store the bytes
356     \param id key id in the IoT-Safe applet for the slot containing the private key to sign the payload
357     written to out upon successfully generating a message signature
358     \return 0 upon success
359     \return < 0 in case of failure
360 
361     \sa wc_iotsafe_ecc_sign_hash_ex
362     \sa wc_iotsafe_ecc_verify_hash
363     \sa wc_iotsafe_ecc_gen_k
364 
365 */
366 WOLFSSL_API int wc_iotsafe_ecc_sign_hash(byte *in, word32 inlen, byte *out, word32 *outlen, byte key_id);
367 
368 /*!
369     \ingroup IoTSafe
370     \brief Sign a pre-computed 256-bit HASH, using a private key previously stored, or pre-provisioned,
371            in the IoT-Safe applet. Equivalent to \ref wc_iotsafe_ecc_sign_hash "wc_iotsafe_ecc_sign_hash",
372            except that it can be invoked with a key ID of two or more bytes.
373 
374     \param in pointer to the buffer containing the message hash to sign
375     \param inlen length of the message hash to sign
376     \param out buffer in which to store the generated signature
377     \param outlen max length of the output buffer. Will store the bytes
378     \param id pointer to a key id in the IoT-Safe applet for the slot containing the private key to sign the payload
379         written to out upon successfully generating a message signature
380     \param id_size The key id size
381     \return 0 upon success
382     \return < 0 in case of failure
383 
384     \sa wc_iotsafe_ecc_sign_hash
385     \sa wc_iotsafe_ecc_verify_hash
386     \sa wc_iotsafe_ecc_gen_k
387 
388 */
389 WOLFSSL_API int wc_iotsafe_ecc_sign_hash_ex(byte *in, word32 inlen, byte *out, word32 *outlen, byte *key_id, word16 id_size);
390 
391 /*!
392     \ingroup IoTSafe
393     \brief Verify an ECC signature against a pre-computed 256-bit HASH, using a public key previously stored, or pre-provisioned,
394     in the IoT-Safe applet. Result is written to res. 1 is valid, 0 is invalid.
395     Note: Do not use the return value to test for valid. Only use res.
396 
397     \return 0 upon success (even if the signature is not valid)
398     \return < 0 in case of failure.
399 
400     \param sig  buffer containing the signature to verify
401     \param hash The hash (message digest) that was signed
402     \param hashlen The length of the hash (octets)
403     \param res Result of signature, 1==valid, 0==invalid
404     \param key_id The id of the slot where the public ECC key is stored in the IoT-Safe applet
405 
406     \sa wc_iotsafe_ecc_verify_hash_ex
407     \sa wc_iotsafe_ecc_sign_hash
408     \sa wc_iotsafe_ecc_gen_k
409 
410 */
411 WOLFSSL_API int wc_iotsafe_ecc_verify_hash(byte *sig, word32 siglen, byte *hash, word32 hashlen, int *res, byte key_id);
412 
413 /*!
414     \ingroup IoTSafe
415     \brief Verify an ECC signature against a pre-computed 256-bit HASH, using a public key previously stored, or pre-provisioned,
416     in the IoT-Safe applet. Result is written to res. 1 is valid, 0 is invalid.
417     Note: Do not use the return value to test for valid. Only use res.
418     Equivalent to \ref wc_iotsafe_ecc_verify_hash "wc_iotsafe_ecc_verify_hash",
419     except that it can be invoked with a key ID of two or more bytes.
420 
421     \return 0 upon success (even if the signature is not valid)
422     \return < 0 in case of failure.
423 
424     \param sig  buffer containing the signature to verify
425     \param hash The hash (message digest) that was signed
426     \param hashlen The length of the hash (octets)
427     \param res Result of signature, 1==valid, 0==invalid
428     \param key_id The id of the slot where the public ECC key is stored in the IoT-Safe applet
429     \param id_size The key id size
430 
431     \sa wc_iotsafe_ecc_verify_hash
432     \sa wc_iotsafe_ecc_sign_hash
433     \sa wc_iotsafe_ecc_gen_k
434 
435 */
436 WOLFSSL_API int wc_iotsafe_ecc_verify_hash_ex(byte *sig, word32 siglen, byte *hash, word32 hashlen, int *res, byte *key_id, word16 id_size);
437 
438 /*!
439     \ingroup IoTSafe
440     \brief Generate an ECC 256-bit keypair and store it in a (writable) slot into the IoT-Safe applet.
441     \param key_id The id of the slot where the ECC key pair is stored in the IoT-Safe applet.
442     \return 0 upon success
443     \return < 0 in case of failure.
444 
445     \sa wc_iotsafe_ecc_gen_k_ex
446     \sa wc_iotsafe_ecc_sign_hash
447     \sa wc_iotsafe_ecc_verify_hash
448 */
449 WOLFSSL_API int wc_iotsafe_ecc_gen_k(byte key_id);
450 
451 /*!
452     \ingroup IoTSafe
453     \brief Generate an ECC 256-bit keypair and store it in a (writable) slot into the IoT-Safe applet.
454            Equivalent to \ref wc_iotsafe_ecc_gen_k "wc_iotsafe_ecc_gen_k",
455            except that it can be invoked with a key ID of two or more bytes.
456     \param key_id The id of the slot where the ECC key pair is stored in the IoT-Safe applet.
457     \param id_size The key id size
458     \return 0 upon success
459     \return < 0 in case of failure.
460 
461     \sa wc_iotsafe_ecc_gen_k
462     \sa wc_iotsafe_ecc_sign_hash_ex
463     \sa wc_iotsafe_ecc_verify_hash_ex
464 */
465 WOLFSSL_API int wc_iotsafe_ecc_gen_k(byte key_id);
466