mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-29 18:27:29 +02:00
add hkdf-extract to iotsafe implementation + sample application
This commit is contained in:
140
IDE/iotsafe-raspberrypi/README.md
Normal file
140
IDE/iotsafe-raspberrypi/README.md
Normal file
@ -0,0 +1,140 @@
|
||||
## wolfSSL IoT-SAFE Example
|
||||
|
||||
|
||||
### Description
|
||||
|
||||
This demo example will run an example TLS 1.3 client using wolfSSL, using an IoT-SAFE applet supporting the [IoT.05-v1-IoT standard](https://www.gsma.com/iot/wp-content/uploads/2019/12/IoT.05-v1-IoT-Security-Applet-Interface-Description.pdf).
|
||||
|
||||
|
||||
### Evaluation Platform
|
||||
|
||||
* Any platform with POSIX-compliant OS such as RaspberryPi
|
||||
* Any ICC form-factor with IoT-SAFE applet (see below section for the specific IoT-SAFE configuration)
|
||||
* Any serial modem for interfacing between the platform and IoT-SAFE
|
||||
|
||||
|
||||
### TLS 1.3
|
||||
|
||||
The TLS 1.3 configuration used in this example will use:
|
||||
* The mutual authentication between client and server is done with ECC certificate.
|
||||
* The key exchange performed is done with ECDHE.
|
||||
* The application traffic cipher used is any AEAD.
|
||||
|
||||
No PSK authentication, early data, session resumption are used in this demo.
|
||||
|
||||
|
||||
### IoT-SAFE Configuration
|
||||
|
||||
The below preprocessor macros can be found in the `client-tls13.c`.
|
||||
|
||||
The applet that has been tested with this demo has the current configuration:
|
||||
|
||||
| Key slot | Name | Description |
|
||||
| -------- | -------------------- | ------------------------------------------------------------ |
|
||||
| 0x01 | `PRIVKEY_ID` | pre-provisioned with the client ECC private key |
|
||||
| 0x02 | `CRT_CLIENT_FILE_ID` | pre-provisioned with the client ECC public key certificate |
|
||||
| 0x03 | `CRT_SERVER_FILE_ID` | pre-provisioned with the server ECC public key certificate |
|
||||
| 0x04 | `ECDH_KEYPAIR_ID` | used to generate the ECDH key pair that will be used during the TLS session |
|
||||
| 0x05 | `PEER_PUBKEY_ID` | used to store the ECDH public key received from the peer during the TLS session |
|
||||
|
||||
The following file is used to read the client's certificate and will be used to authenticate the client:
|
||||
|
||||
| File Slot | Name | Description |
|
||||
| --------- | -------------------- | ---------------------------------------------------------- |
|
||||
| 0x02 | `CRT_CLIENT_FILE_ID` | pre-provisioned with the client ECC public key certificate |
|
||||
|
||||
The following file is used to read the server's certificate and will be used to authenticate the server by trusting the server certificate (trust here means no CA chain verification is performed, only comparing the server certificate sent from the server with the one stored in the IoT-SAFE):
|
||||
|
||||
| File Slot | Name | Description |
|
||||
| --------- | -------------------- | ---------------------------------------------------------- |
|
||||
| 0x03 | `CRT_SERVER_FILE_ID` | pre-provisioned with the server ECC public key certificate |
|
||||
|
||||
How the applet configuration (such as putting the client key pair with the corresponding client certificate and the server certificate the client can trust) is performed during its initial and on-field lifetime depends on the infrastructure and is out-of-scope of this demo.
|
||||
|
||||
|
||||
### IoT-SAFE Interface
|
||||
|
||||
The below code explanations can be found in the `client-tls13.c`.
|
||||
|
||||
In this demo, the client is the IoT-SAFE capable endpoint.
|
||||
|
||||
First, it creates a wolfSSL context `ctx` with TLS 1.3.
|
||||
|
||||
```c
|
||||
wolfSSL_CTX_new(wolfTLSv1_3_client_method());
|
||||
```
|
||||
|
||||
In order to activate IoT-SAFE support in this context, the following function is
|
||||
called:
|
||||
|
||||
```c
|
||||
wolfSSL_CTX_iotsafe_enable(ctx);
|
||||
```
|
||||
|
||||
Extracting the client and server certificate can be done by the following functions:
|
||||
|
||||
```c
|
||||
wolfIoTSafe_GetCert(
|
||||
CRT_CLIENT_FILE_ID,
|
||||
cert_buffer,
|
||||
sizeof(cert_buffer));
|
||||
```
|
||||
|
||||
```c
|
||||
wolfIoTSafe_GetCert(
|
||||
CRT_SERVER_FILE_ID,
|
||||
cert_buffer,
|
||||
sizeof(cert_buffer));
|
||||
```
|
||||
|
||||
in which the extracted certificate inside the `cer_buffer` can be later loaded to the `ctx`.
|
||||
|
||||
Additionally, after the TLS session `ssl` creation, shown below:
|
||||
|
||||
```c
|
||||
ssl = wolfSSL_new(ctx);
|
||||
```
|
||||
|
||||
the client associates the pre-provisioned keys and the available slots in the
|
||||
IoT-SAFE applet to the current session:
|
||||
|
||||
|
||||
```c
|
||||
wolfSSL_iotsafe_on(ssl, PRIVKEY_ID, ECDH_KEYPAIR_ID, PEER_PUBKEY_ID, PEER_CERT_ID);
|
||||
```
|
||||
|
||||
|
||||
### Compiling
|
||||
|
||||
First, user needs to build wolfSSL with the following options:
|
||||
```
|
||||
./configure --enable-tls13 --enable-pkcallbacks --enable-debug --enable-iotsafe --enable-hkdf
|
||||
```
|
||||
|
||||
Additionally, user can pass `CFLAGS="-DDEBUG_WOLFSSL -DWOLFSSL_DEBUG_TLS -DDEBUG_IOTSAFE"` if more debugging information is to be used. This can clutter the demo stdout more than `--enable-debug` does, but this is very useful to see the overall TLS 1.3 handshaking process with IoT-SAFE.
|
||||
|
||||
Hence, the full wolfSSL build for the demo is:
|
||||
```
|
||||
./configure CFLAGS="-DDEBUG_WOLFSSL -DWOLFSSL_DEBUG_TLS -DDEBUG_IOTSAFE" --enable-tls13 --enable-pkcallbacks --enable-debug --enable-iotsafe
|
||||
```
|
||||
|
||||
### Running
|
||||
|
||||
After building wolfSSL, from this directory, run `make` and a help usage will be shown.
|
||||
|
||||
Run below to build a minimal demo:
|
||||
```
|
||||
make all
|
||||
```
|
||||
|
||||
Run below to enable printing UART IO:
|
||||
```
|
||||
make all ENABLE_DEBUG_UART_IO_EXTRA=on
|
||||
```
|
||||
|
||||
Run the built `./main.bin` to print the help usage.
|
||||
|
||||
An example to run the demo connecting to a server:
|
||||
```
|
||||
./main.bin -ip <ipaddress> -h <full-hostname> -p <port> -t 25 -d /dev/ttyUSB0|/dev/tty/ACM0
|
||||
```
|
499
IDE/iotsafe-raspberrypi/client-tls13.c
Normal file
499
IDE/iotsafe-raspberrypi/client-tls13.c
Normal file
@ -0,0 +1,499 @@
|
||||
/* client-tls13.c
|
||||
*
|
||||
* Copyright (C) 2006-2020 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/* C Standard Library */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
|
||||
/* POSIX Library */
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
|
||||
/* wolfSSL Library */
|
||||
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/ssl.h>
|
||||
#include <wolfssl/wolfio.h>
|
||||
#include <wolfssl/wolfcrypt/port/iotsafe/iotsafe.h>
|
||||
#include <wolfssl/error-ssl.h>
|
||||
|
||||
|
||||
|
||||
/* IoTSAFE Certificate slots */
|
||||
|
||||
/* File Slot '02' is pre-provisioned with
|
||||
* the client ECC public key certificate.
|
||||
*/
|
||||
#define CRT_CLIENT_FILE_ID 0x02
|
||||
|
||||
/* File Slot '03' is pre-provisioned with the
|
||||
* server ECC public key certificate.
|
||||
*/
|
||||
#define CRT_SERVER_FILE_ID 0x03
|
||||
|
||||
/* IoTSAFE Key slots */
|
||||
|
||||
/* Key slot '01' is pre-provisioned with
|
||||
* the client ECC private key.
|
||||
*/
|
||||
#define PRIVKEY_ID 0x01
|
||||
|
||||
/* Key slot '04' is used to generate the ECDH
|
||||
* key pair that will be used during the TLS
|
||||
* session.
|
||||
*/
|
||||
#define ECDH_KEYPAIR_ID 0x04
|
||||
|
||||
/* Key slot '05' is used to store the ECDH public
|
||||
* key received from the peer during the TLS
|
||||
* session.
|
||||
*/
|
||||
#define PEER_PUBKEY_ID 0x05
|
||||
|
||||
/* Key slot '05' is used to store the public key
|
||||
* used for ECC verification - disabled in IoTSAFE.
|
||||
*/
|
||||
#define PEER_CERT_ID 0x05
|
||||
|
||||
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
extern int client_loop(const char *peer_ip, const char *peer_name, const char *peer_port, const char *temperature);
|
||||
|
||||
#if defined(USE_SECRET_CALLBACK)
|
||||
|
||||
static int Tls13SecretCallback(WOLFSSL* ssl, int id, const unsigned char* secret, int secretSz, void* ctx);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Function Definitions */
|
||||
|
||||
#if defined(USE_SECRET_CALLBACK)
|
||||
|
||||
#ifndef WOLFSSL_SSLKEYLOGFILE_OUTPUT
|
||||
#define WOLFSSL_SSLKEYLOGFILE_OUTPUT "sslkeylog.log"
|
||||
#endif
|
||||
|
||||
/* Callback function for TLS v1.3 secrets for use with Wireshark */
|
||||
static int Tls13SecretCallback(WOLFSSL* ssl, int id, const unsigned char* secret,
|
||||
int secretSz, void* ctx)
|
||||
{
|
||||
int i;
|
||||
const char* str = NULL;
|
||||
unsigned char clientRandom[32];
|
||||
size_t clientRandomSz;
|
||||
XFILE fp = stderr;
|
||||
if (ctx) {
|
||||
fp = XFOPEN((const char*)ctx, "ab");
|
||||
if (fp == XBADFILE) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
clientRandomSz = wolfSSL_get_client_random(ssl, clientRandom,
|
||||
sizeof(clientRandom));
|
||||
|
||||
switch (id) {
|
||||
case CLIENT_EARLY_TRAFFIC_SECRET:
|
||||
str = "CLIENT_EARLY_TRAFFIC_SECRET"; break;
|
||||
case EARLY_EXPORTER_SECRET:
|
||||
str = "EARLY_EXPORTER_SECRET"; break;
|
||||
case CLIENT_HANDSHAKE_TRAFFIC_SECRET:
|
||||
str = "CLIENT_HANDSHAKE_TRAFFIC_SECRET"; break;
|
||||
case SERVER_HANDSHAKE_TRAFFIC_SECRET:
|
||||
str = "SERVER_HANDSHAKE_TRAFFIC_SECRET"; break;
|
||||
case CLIENT_TRAFFIC_SECRET:
|
||||
str = "CLIENT_TRAFFIC_SECRET_0"; break;
|
||||
case SERVER_TRAFFIC_SECRET:
|
||||
str = "SERVER_TRAFFIC_SECRET_0"; break;
|
||||
case EXPORTER_SECRET:
|
||||
str = "EXPORTER_SECRET"; break;
|
||||
}
|
||||
|
||||
fprintf(fp, "%s ", str);
|
||||
for (i = 0; i < (int)clientRandomSz; i++) {
|
||||
fprintf(fp, "%02x", clientRandom[i]);
|
||||
}
|
||||
fprintf(fp, " ");
|
||||
for (i = 0; i < secretSz; i++) {
|
||||
fprintf(fp, "%02x", secret[i]);
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
|
||||
if (fp != stderr) {
|
||||
XFCLOSE(fp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* USE_SECRET_CALLBACK */
|
||||
|
||||
|
||||
|
||||
int client_loop(const char *peer_ip, const char *peer_name, const char *peer_port, const char *temperature)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Declare TCP objects */
|
||||
int sockfd = -1;
|
||||
struct sockaddr_in servAddr = {0};
|
||||
|
||||
/* Declare TCP messaging buffer */
|
||||
char buff[2048] = {0};
|
||||
size_t len = 0;
|
||||
|
||||
/* Declare certificate temporary buffer */
|
||||
uint8_t cert_buffer[2048] = {0};
|
||||
uint32_t cert_buffer_size = 0;
|
||||
uint8_t *cert_iter = NULL;
|
||||
|
||||
/* Declare wolfSSL objects */
|
||||
WOLFSSL_CTX* ctx = NULL;
|
||||
WOLFSSL* ssl = NULL;
|
||||
WC_RNG rng = {0};
|
||||
char randombytes[16] = {0};
|
||||
|
||||
/* Construct HTTP POST */
|
||||
|
||||
// Header
|
||||
strcat(buff, "POST /iot/device HTTP/1.1\r\n");
|
||||
strcat(buff, "Content-Type: application/json\r\n");
|
||||
strcat(buff, "Content-Length: 1000\r\n");
|
||||
strcat(buff, "Accept: */*\r\n");
|
||||
strcat(buff, "Host: ");
|
||||
strcat(buff, peer_name);
|
||||
strcat(buff, ":");
|
||||
strcat(buff, peer_port);
|
||||
strcat(buff, "\r\n");
|
||||
|
||||
// Delimiter
|
||||
strcat(buff, "\r\n");
|
||||
|
||||
// Body
|
||||
srand(time(NULL));
|
||||
int devid = rand() % 100;
|
||||
char snum[5] = {0};
|
||||
snprintf(snum, sizeof(snum), "%d", devid);
|
||||
|
||||
strcat(buff, "{");
|
||||
strcat(buff, "\"deviceId\": \"");
|
||||
strcat(buff, snum);
|
||||
strcat(buff, "\",");
|
||||
strcat(buff, "\"sensorType\": \"Temperature\",");
|
||||
strcat(buff, "\"sensorValue\": \"");
|
||||
strcat(buff, temperature);
|
||||
strcat(buff, "\",");
|
||||
strcat(buff, "\"sensorUnit\": \"Celcius\",");
|
||||
strcat(buff, "\"sensorTime\": 1582181510");
|
||||
strcat(buff, "}");
|
||||
strcat(buff, "\r\n");
|
||||
|
||||
printf("\n\nPOST REQUEST\n\n%s\n\n", buff);
|
||||
|
||||
/*---------------------------------*/
|
||||
/* Start of Socket */
|
||||
/*---------------------------------*/
|
||||
printf("---- Preparing TCP socket\n");
|
||||
|
||||
/* Create a socket that uses an internet IPv4 address,
|
||||
* Sets the socket to be stream based (TCP),
|
||||
* 0 means choose the default protocol. */
|
||||
printf("---- Creating socket\n");
|
||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
fprintf(stderr, "ERROR: failed to create the socket\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Fill in the server address */
|
||||
printf("Peer port: %s\n", peer_port);
|
||||
servAddr.sin_family = AF_INET; // Using IPv4
|
||||
servAddr.sin_port = htons(atoi(peer_port));
|
||||
|
||||
/* Get the server IPv4 address from the command line call */
|
||||
printf("---- Checking peer IP address\n");
|
||||
printf("Peer IP address: %s <IPv4 address>\n", peer_ip);
|
||||
if (inet_pton(AF_INET, peer_ip, &servAddr.sin_addr) != 1)
|
||||
{
|
||||
fprintf(stderr, "ERROR: invalid peer IP address\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Connect to the server */
|
||||
printf("---- Connecting to the peer socket\n");
|
||||
if ((ret = connect(sockfd, (struct sockaddr*) &servAddr, sizeof(servAddr)))
|
||||
== -1)
|
||||
{
|
||||
fprintf(stderr, "ERROR: failed to connect\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
printf("---- TCP socket connection established\n");
|
||||
|
||||
/*---------------------------------*/
|
||||
/* Start of Security */
|
||||
/*---------------------------------*/
|
||||
printf("---- Preparing wolfSSL TLS 1.3\n");
|
||||
|
||||
/* Initialize wolfSSL */
|
||||
printf("---- Initializing wolfSSL\n");
|
||||
if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to initialize the library\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Allow debug print in wolfSSL */
|
||||
printf("---- Allowing debug print in wolfSSL\n");
|
||||
if ((ret = wolfSSL_Debugging_ON()) != 0)
|
||||
{
|
||||
fprintf(stderr, "WARNING: Failed to enable wolfSSL debug print\n");
|
||||
}
|
||||
|
||||
/* Initialize RNG */
|
||||
printf("---- Initializing RNG\n");
|
||||
if ((ret = wc_InitRng(&rng)) != 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to initialize the random number generator\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Obtain a sample RND */
|
||||
printf("---- Testing getting RND\n");
|
||||
if ((ret = wc_RNG_GenerateBlock(
|
||||
&rng,
|
||||
(byte*)randombytes,
|
||||
sizeof(randombytes)))
|
||||
!= 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to get random numbers\n");
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Random bytes: ");
|
||||
for (uint8_t i = 0; i < sizeof(randombytes); i++)
|
||||
printf("%02X", (unsigned int)randombytes[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Create and initialize WOLFSSL_CTX */
|
||||
printf("---- Creating wolfSSL TLS 1.3 context object\n");
|
||||
if ((ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())) == NULL)
|
||||
{
|
||||
fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialize IoTSAFE */
|
||||
printf("---- Enabling IoTSAFE\n");
|
||||
if ((ret = wolfSSL_CTX_iotsafe_enable(ctx)) != 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to initialize IoTSAFE\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Extract client certificate from IoTSAFE*/
|
||||
printf("---- Extracting client certificate from IoTSAFE\n");
|
||||
if ((cert_buffer_size = wolfIoTSafe_GetCert(
|
||||
CRT_CLIENT_FILE_ID,
|
||||
cert_buffer,
|
||||
sizeof(cert_buffer)))
|
||||
< 1)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Bad client certificate\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Print extracted client certificate */
|
||||
printf("---- Printing extracted client certificate\n");
|
||||
cert_iter = (uint8_t*)&cert_buffer;
|
||||
printf("Extracted client certificate in HEX:\n");
|
||||
for (uint32_t i = 0; i < cert_buffer_size; i++)
|
||||
printf("%02X", (unsigned int)*(cert_iter++));
|
||||
printf("\n");
|
||||
|
||||
/* Load client certificate */
|
||||
printf("---- Loading client certificate\n");
|
||||
if ((ret = wolfSSL_CTX_use_certificate_buffer(ctx, cert_buffer,
|
||||
cert_buffer_size, WOLFSSL_FILETYPE_ASN1))
|
||||
!= WOLFSSL_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to load client certificate\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Extract server certificate from IoTSAFE*/
|
||||
printf("---- Extracting server certificate from IoTSAFE\n");
|
||||
if ((cert_buffer_size = wolfIoTSafe_GetCert(
|
||||
CRT_SERVER_FILE_ID,
|
||||
cert_buffer,
|
||||
sizeof(cert_buffer)))
|
||||
< 1)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Bad server certificate\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Print extracted server certificate */
|
||||
printf("---- Printing extracted server certificate\n");
|
||||
cert_iter = (uint8_t*)&cert_buffer;
|
||||
printf("Extracted server certificate in HEX:\n");
|
||||
for (uint32_t i = 0; i < cert_buffer_size; i++)
|
||||
printf("%02X", (unsigned int)*(cert_iter++));
|
||||
printf("\n");
|
||||
|
||||
/* Load server certificate */
|
||||
printf("---- Loading server certificate\n");
|
||||
if ((ret = wolfSSL_CTX_trust_peer_buffer(ctx, cert_buffer,
|
||||
cert_buffer_size, WOLFSSL_FILETYPE_ASN1))
|
||||
!= WOLFSSL_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to load server certificate\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set client to authenticate server */
|
||||
printf("---- Enabling client to authenticate server\n");
|
||||
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL);
|
||||
|
||||
/* Create a WOLFSSL object */
|
||||
printf("---- Creating wolfSSL TLS 1.3 connection object\n");
|
||||
if ((ssl = wolfSSL_new(ctx)) == NULL)
|
||||
{
|
||||
fprintf(stderr, "ERROR: failed to create WOLFSSL object\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Attach IoTSAFE usage to the wolfSSL */
|
||||
printf("---- Using IoTSAFE for TLS 1.3\n");
|
||||
if ((ret = wolfSSL_iotsafe_on(
|
||||
ssl, PRIVKEY_ID, ECDH_KEYPAIR_ID,
|
||||
PEER_PUBKEY_ID, PEER_CERT_ID))
|
||||
!= 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to use IoTSAFE\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Attach wolfSSL to the socket */
|
||||
printf("---- Attaching TLS 1.3 to the socket\n");
|
||||
if ((ret = wolfSSL_set_fd(ssl, sockfd)) != WOLFSSL_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to set the file descriptor\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#ifdef USE_SECRET_CALLBACK
|
||||
/* Logging usage for wireshark */
|
||||
printf("---- Attaching TLS 1.3 secret callback for wireshark\n");
|
||||
if ((ret = wolfSSL_set_tls13_secret_cb(
|
||||
ssl,
|
||||
Tls13SecretCallback,
|
||||
(void*)WOLFSSL_SSLKEYLOGFILE_OUTPUT))
|
||||
!= WOLFSSL_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to set the secret callback\n");
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Connect to wolfSSL on the server side */
|
||||
printf("---- Start TLS 1.3 handshaking\n");
|
||||
if ((ret = wolfSSL_connect(ssl)) != WOLFSSL_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "ERROR: failed to connect to wolfSSL\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
printf("---- wolfSSL TLS 1.3 connection established\n");
|
||||
|
||||
/*---------------------------------*/
|
||||
/* Start of Communication */
|
||||
/*---------------------------------*/
|
||||
printf("---- Communication starts\n");
|
||||
|
||||
/* Get a message for the server from stdin */
|
||||
printf("Enter message for server:\n");
|
||||
printf("[OUT]:\n");
|
||||
printf("\n\n%s\n\n", buff);
|
||||
|
||||
len = strlen(buff);
|
||||
|
||||
/* Send the message to the server */
|
||||
printf("Sending message to the server\n");
|
||||
if ((size_t) (ret = wolfSSL_write(ssl, buff, len)) != len)
|
||||
{
|
||||
fprintf(stderr, "ERROR: failed to write entire message\n");
|
||||
fprintf(stderr, "%d bytes of %d bytes were sent\n", ret, (int) len);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Read the server data into our buff array */
|
||||
printf("Receiving message from the server\n");
|
||||
memset(buff, 0, sizeof(buff));
|
||||
if ((ret = wolfSSL_read(ssl, buff, sizeof(buff) - 1)) < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: failed to read\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Print to stdout any data the server sends */
|
||||
printf("[IN] :\n%s\n", buff);
|
||||
|
||||
/* Return reporting a success */
|
||||
ret = 0;
|
||||
|
||||
printf("---- Communication ends\n");
|
||||
|
||||
exit:
|
||||
/* Cleanup and return */
|
||||
if (sockfd != -1)
|
||||
close(sockfd); /* Close the connection to the server */
|
||||
if (ssl)
|
||||
wolfSSL_free(ssl); /* Free the wolfSSL object */
|
||||
if (ctx)
|
||||
wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */
|
||||
wc_FreeRng(&rng); /* Cleanup the RNG */
|
||||
wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */
|
||||
|
||||
return ret;
|
||||
}
|
288
IDE/iotsafe-raspberrypi/main.c
Normal file
288
IDE/iotsafe-raspberrypi/main.c
Normal file
@ -0,0 +1,288 @@
|
||||
/* main.c
|
||||
*
|
||||
* Copyright (C) 2006-2020 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL. (formerly known as CyaSSL)
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/* IoT-SAFE example
|
||||
* main for POSIX serial communication.
|
||||
*/
|
||||
|
||||
/* C Standard Library */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
/* POSIX Library */
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <termios.h>
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
|
||||
/* wolfSSL Library */
|
||||
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
#include <wolfssl/ssl.h>
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#include <wolfssl/wolfcrypt/port/iotsafe/iotsafe.h>
|
||||
|
||||
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
static int serial_fd = -1;
|
||||
|
||||
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
extern int client_loop(const char *peer_ip, const char *peer_name, const char *peer_port, const char *temperature);
|
||||
|
||||
static void print_buffer_hex(const char *buf, int len);
|
||||
static void print_buffer_char(const char *buf, int len);
|
||||
|
||||
static int usart_init(const char *dev_name, int *fd);
|
||||
static int usart_clean(int fd);
|
||||
static int usart_read(char *buf, int len);
|
||||
static int usart_write(const char *buf, int len);
|
||||
|
||||
static void show_usage(const char *program);
|
||||
|
||||
|
||||
|
||||
/* Function Definitions */
|
||||
|
||||
static void print_buffer_hex(const char *buf, int len)
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
printf("%02X", (unsigned int)*(buf++));
|
||||
}
|
||||
|
||||
static void print_buffer_char(const char *buf, int len)
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
printf("%c", *(buf++));
|
||||
}
|
||||
|
||||
static int usart_init(const char *dev_name, int *fd)
|
||||
{
|
||||
int portfd = open(dev_name, O_RDWR | O_NOCTTY);
|
||||
if (portfd < 0)
|
||||
{
|
||||
*fd = -1;
|
||||
return errno;
|
||||
}
|
||||
|
||||
struct termios tty;
|
||||
tcgetattr(portfd, &tty);
|
||||
cfsetospeed(&tty, B115200);
|
||||
cfsetispeed(&tty, B115200);
|
||||
tty.c_cflag = (tty.c_cflag & ~CSIZE) | (CS8);
|
||||
tty.c_iflag &= ~(IGNBRK | IXON | IXOFF | IXANY| INLCR | ICRNL);
|
||||
tty.c_oflag &= ~OPOST;
|
||||
tty.c_oflag &= ~(ONLCR|OCRNL);
|
||||
tty.c_cflag &= ~(PARENB | PARODD | CSTOPB);
|
||||
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
|
||||
tty.c_iflag &= ~ISTRIP;
|
||||
tty.c_cc[VMIN] = 0;
|
||||
tty.c_cc[VTIME] = 5;
|
||||
tcsetattr(portfd, TCSANOW, &tty);
|
||||
|
||||
*fd = portfd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usart_clean(int fd)
|
||||
{
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
static int usart_read(char *buf, int len)
|
||||
{
|
||||
if (!buf || len < 0)
|
||||
return -1;
|
||||
|
||||
#ifdef DEBUG_UART_IO
|
||||
printf("UART Read Expected : %d bytes\n", len);
|
||||
#endif
|
||||
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
char c;
|
||||
memset(buf, 0, len);
|
||||
|
||||
// Read 1 byte at one time until *buf is full or a POSIX read error like timeout occurs.
|
||||
do
|
||||
{
|
||||
ret = read(serial_fd, &c, 1U);
|
||||
if (ret > 0)
|
||||
{
|
||||
buf[i++] = c;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
} while (i < len && ret > 0);
|
||||
|
||||
#ifdef DEBUG_UART_IO
|
||||
printf("UART Read Actual : %d bytes\n", i);
|
||||
#ifdef DEBUG_UART_IO_EXTRA_VERBOSE
|
||||
printf("[READ in HEX ] <- ");
|
||||
print_buffer_hex(buf, i);
|
||||
printf("\n");
|
||||
#endif
|
||||
printf("[READ in CHAR] <- ");
|
||||
print_buffer_char(buf, i);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int usart_write(const char *buf, int len)
|
||||
{
|
||||
if (!buf || len < 0)
|
||||
return -1;
|
||||
|
||||
#ifdef DEBUG_UART_IO
|
||||
printf("UART Write Expected: %d bytes\n", len);
|
||||
#endif
|
||||
|
||||
int sent = write(serial_fd, buf, len);
|
||||
|
||||
if (sent < 0)
|
||||
sent = 0;
|
||||
|
||||
#ifdef DEBUG_UART_IO
|
||||
printf("UART Write Actual : %d bytes\n", sent);
|
||||
#ifdef DEBUG_UART_IO_EXTRA_VERBOSE
|
||||
printf("[WRITE in HEX ] -> ");
|
||||
print_buffer_hex(buf, sent);
|
||||
printf("\n");
|
||||
#endif
|
||||
printf("[WRITE in CHAR] -> ");
|
||||
print_buffer_char(buf, sent);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
static void show_usage(const char *program)
|
||||
{
|
||||
printf("\nUsage:\n");
|
||||
printf("\t%s -ip SERVER_IP_ADDRESS -h SERVER_HOST_NAME -p PORT_NUMBER -t TEMPERATURE -d DEVICE_FILE_PATH\n", program);
|
||||
printf("\n");
|
||||
printf("\t-ip <server IPv4 address eg: 127.0.0.1>\n");
|
||||
printf("\t-h <server name eg: xxx.amazon.com>\n");
|
||||
printf("\t-p <server port eg: 443>\n");
|
||||
printf("\t-t <temperature eg: 25Celcius>\n");
|
||||
printf("\t-d <serial device eg: /dev/ttyACM0>\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
char ip[30] = {0};
|
||||
char name[50] = {0};
|
||||
char port[8] = {0};
|
||||
char temperature[10] = {0};
|
||||
char device[30] = {0};
|
||||
|
||||
if (argc == 11)
|
||||
{
|
||||
if (strcmp(argv[1], "-ip") == 0)
|
||||
strcpy((char*)&ip, argv[2]);
|
||||
else
|
||||
show_usage(argv[0]);
|
||||
|
||||
if (strcmp(argv[3], "-h") == 0)
|
||||
strcpy((char*)&name, argv[4]);
|
||||
else
|
||||
show_usage(argv[0]);
|
||||
|
||||
if (strcmp(argv[5], "-p") == 0)
|
||||
strcpy((char*)&port, argv[6]);
|
||||
else
|
||||
show_usage(argv[0]);
|
||||
|
||||
if (strcmp(argv[7], "-t") == 0)
|
||||
strcpy((char*)&temperature, argv[8]);
|
||||
else
|
||||
show_usage(argv[0]);
|
||||
|
||||
if (strcmp(argv[9], "-d") == 0)
|
||||
strcpy((char*)&device, argv[10]);
|
||||
else
|
||||
show_usage(argv[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
show_usage(argv[0]);
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
|
||||
printf("#####################\n");
|
||||
printf("wolfSSL IoT-SAFE Demo\n");
|
||||
printf("#####################\n");
|
||||
|
||||
printf("---- Initializing serial I/O\n");
|
||||
|
||||
printf("---- Opening serial I/O\n");
|
||||
printf("Serial device: %s\n", (const char*)&device);
|
||||
if ((ret = usart_init((const char*)&device, &serial_fd)) != 0)
|
||||
{
|
||||
printf("ERROR: Error opening %s: Error %i (%s)\n",
|
||||
(const char*)&device, ret, strerror(ret));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
printf("---- Setting serial I/O read callback\n");
|
||||
wolfIoTSafe_SetCSIM_read_cb(&usart_read);
|
||||
|
||||
printf("---- Setting serial I/O write callback\n");
|
||||
wolfIoTSafe_SetCSIM_write_cb(&usart_write);
|
||||
|
||||
printf("---- Finish initializing serial I/O\n");
|
||||
|
||||
client_loop(ip, name, port, temperature);
|
||||
|
||||
printf("---- Cleaning serial I/O\n");
|
||||
|
||||
printf("---- Closing serial I/O\n");
|
||||
if ((ret = usart_clean(serial_fd)) != 0)
|
||||
{
|
||||
printf("ERROR: Error closing %s: Error %i (%s)\n",
|
||||
(const char*)&device, ret, strerror(ret));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
printf("---- Finish cleaning serial I/O\n");
|
||||
|
||||
return 0;
|
||||
}
|
@ -261,7 +261,7 @@ static int iotsafe_cmd_add_tlv_ex(char *cmd, byte tag, uint16_t len,
|
||||
cur_csim_len += (len_csim_str[1] - '0') * 10;
|
||||
if (len_csim_str[0] >= '0' &&
|
||||
len_csim_str[0] <= '9') {
|
||||
cur_csim_len += len_csim_str[0] * 100;
|
||||
cur_csim_len += (len_csim_str[0] - '0') * 100;
|
||||
} else if (len_csim_str[0] != ' ') {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
@ -453,7 +453,7 @@ static int iotsafe_readfile(uint8_t *file_id, uint16_t file_id_sz,
|
||||
return ret;
|
||||
}
|
||||
|
||||
filesz_s = search_tlv(resp + 4, ret, 0x20);
|
||||
filesz_s = search_tlv(resp, ret, 0x20);
|
||||
if ((filesz_s) && (XSTRLEN(filesz_s)) >= 8) {
|
||||
uint8_t fs_msb, fs_lsb;
|
||||
if (hex_to_bytes(filesz_s + 4, &fs_msb, 1) < 0)
|
||||
@ -719,6 +719,51 @@ static int iotsafe_put_public_key(byte *pubkey_id, unsigned long id_size,
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#ifdef HAVE_HKDF
|
||||
//hkdf extract
|
||||
static int iotsafe_hkdf_extract(byte* prk, const byte* salt, word32 saltLen,
|
||||
byte* ikm, word32 ikmLen, int digest)
|
||||
{
|
||||
int ret;
|
||||
char *resp;
|
||||
uint16_t hash_algo = 0;
|
||||
|
||||
WOLFSSL_MSG("Enter iotsafe_hkdf_extract");
|
||||
switch (digest) {
|
||||
case WC_SHA256:
|
||||
hash_algo = (uint16_t)1;
|
||||
break;
|
||||
case WC_SHA384:
|
||||
hash_algo = (uint16_t)2;
|
||||
break;
|
||||
case WC_SHA512:
|
||||
hash_algo = (uint16_t)4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
uint16_t hash_algo_be = XHTONS(hash_algo);
|
||||
|
||||
iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, IOTSAFE_INS_HKDF_EXTRACT, 0, 0);
|
||||
iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_SECRET, ikmLen, ikm);
|
||||
iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_SALT, saltLen,salt);
|
||||
iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_HASH_ALGO, 2, (const byte*)&hash_algo_be);
|
||||
iotsafe_cmd_complete(csim_cmd);
|
||||
if (expect_csim_response(csim_cmd, (word32)XSTRLEN(csim_cmd), &resp) < 1) {
|
||||
WOLFSSL_MSG("Unexpected reply from HKDF extract");
|
||||
ret = WC_HW_E;
|
||||
} else {
|
||||
|
||||
ret = hexbuffer_conv(resp, prk, 32);
|
||||
if (ret < 0)
|
||||
ret = WC_HW_E;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int iotsafe_sign_hash(byte *privkey_idx, uint16_t id_size,
|
||||
uint16_t hash_algo, uint8_t sign_algo, const byte *hash, word32 hashLen,
|
||||
@ -960,6 +1005,41 @@ static int wolfIoT_ecc_keygen(WOLFSSL* ssl, struct ecc_key* key,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef HAVE_HKDF
|
||||
|
||||
//hkdf extract iot safe
|
||||
static int wolfIoT_hkdf_extract(byte* prk, const byte* salt, word32 saltLen,
|
||||
byte* ikm, word32 ikmLen, int digest, void* ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
int ret;
|
||||
|
||||
WOLFSSL_MSG("IOTSAFE: Called wolfIoT_hkdf_extract\n");
|
||||
|
||||
#ifdef DEBUG_IOTSAFE
|
||||
printf("IOTSAFE PK HKDF Extract\n");
|
||||
printf("salt: ");
|
||||
for(word32 i = 0; i < saltLen; i++)
|
||||
printf("%02X", salt[i]);
|
||||
|
||||
printf("\nikm: ");
|
||||
for(word32 i = 0; i < ikmLen; i++)
|
||||
printf("%02X", ikm[i]);
|
||||
|
||||
printf("\nhash: %d\n", digest);
|
||||
#endif
|
||||
if(saltLen != 0){
|
||||
ret = iotsafe_hkdf_extract(prk, salt, saltLen, ikm, ikmLen, digest);
|
||||
}
|
||||
else{
|
||||
return NOT_COMPILED_IN;
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static int wolfIoT_ecc_sign(WOLFSSL* ssl,
|
||||
const unsigned char* in, unsigned int inSz,
|
||||
@ -1429,6 +1509,9 @@ int wolfSSL_CTX_iotsafe_enable(WOLFSSL_CTX *ctx)
|
||||
wolfSSL_CTX_SetEccVerifyCb(ctx, wolfIoT_ecc_verify);
|
||||
wolfSSL_CTX_SetEccKeyGenCb(ctx, wolfIoT_ecc_keygen);
|
||||
wolfSSL_CTX_SetEccSharedSecretCb(ctx, wolfIoT_ecc_shared_secret);
|
||||
#ifdef HAVE_HKDF
|
||||
wolfSSL_CTX_SetHKDFExtractCb(ctx, wolfIoT_hkdf_extract);
|
||||
#endif
|
||||
#ifndef NO_DH
|
||||
wolfSSL_CTX_SetDhAgreeCb(ctx, wolfIoT_dh_agree);
|
||||
#endif /* NO_DH */
|
||||
|
@ -116,6 +116,7 @@ typedef struct wc_IOTSAFE IOTSAFE;
|
||||
#define IOTSAFE_INS_GETRESPONSE 0xC0
|
||||
#define IOTSAFE_INS_GETDATA 0xCB
|
||||
#define IOTSAFE_INS_READ_KEY 0xCD
|
||||
#define IOTSAFE_INS_HKDF_EXTRACT 0x4A
|
||||
|
||||
/* Tags */
|
||||
#define IOTSAFE_TAG_ECC_KEY_FIELD 0x34
|
||||
@ -134,6 +135,8 @@ typedef struct wc_IOTSAFE IOTSAFE;
|
||||
#define IOTSAFE_TAG_HASH_ALGO 0x91
|
||||
#define IOTSAFE_TAG_SIGN_ALGO 0x92
|
||||
#define IOTSAFE_TAG_MODE_OF_OPERATION 0xA1
|
||||
#define IOTSAFE_TAG_SECRET 0xD1
|
||||
#define IOTSAFE_TAG_SALT 0xD5
|
||||
|
||||
/* Flags - data */
|
||||
#define IOTSAFE_GETDATA_FILE 0xC3
|
||||
|
Reference in New Issue
Block a user