Add WISeKey/SealSQ VaultIC secure element port

This commit is contained in:
David Garske
2026-08-04 18:49:31 -07:00
parent b802e461d8
commit 558f1d9d64
7 changed files with 724 additions and 0 deletions
+6
View File
@@ -521,6 +521,11 @@ if(WOLFSSL_IOTSAFE)
list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_IOTSAFE")
endif()
add_option("WOLFSSL_VAULTIC" "Enable WISeKey/SealSQ VaultIC support (default: disabled)" "no" "yes;no")
if(WOLFSSL_VAULTIC)
list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_VAULTIC")
endif()
add_option("WOLFSSL_WOLFSENTRY" "Enable wolfSentry support (default: disabled)" "no" "yes;no")
if(WOLFSSL_WOLFSENTRY)
foreach(_o WOLFSSL_MD5)
@@ -4564,6 +4569,7 @@ set(HEADER_EXCLUDE
"wolfssl/wolfcrypt/port/cypress"
"wolfssl/wolfcrypt/port/Espressif"
"wolfssl/wolfcrypt/port/iotsafe"
"wolfssl/wolfcrypt/port/sealsq"
"wolfssl/wolfcrypt/port/nxp"
"wolfssl/wolfcrypt/port/pic"
"wolfssl/wolfcrypt/port/Renesas"
+20
View File
@@ -11801,6 +11801,13 @@ AC_ARG_ENABLE([iotsafe-hwrng],
[ ENABLED_IOTSAFE_HWRNG=no ]
)
# WISeKey/SealSQ VaultIC secure element
AC_ARG_ENABLE([vaultic],
[AS_HELP_STRING([--enable-vaultic],[Enable WISeKey/SealSQ VaultIC secure element support (default: disabled)])],
[ ENABLED_VAULTIC=$enableval ],
[ ENABLED_VAULTIC=no ]
)
# Make clean
AC_ARG_ENABLE([makeclean],
[AS_HELP_STRING([--enable-makeclean], [Enables forced "make clean" at the
@@ -12604,6 +12611,17 @@ then
ENABLED_IOTSAFE_HWRNG=yes
fi
if test "$ENABLED_VAULTIC" != "no"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_VAULTIC"
ENABLED_VAULTIC=yes
# VaultIC port is implemented via PK callbacks
if test "$ENABLED_PKCALLBACKS" = "no"; then
ENABLED_PKCALLBACKS=yes
AM_CFLAGS="$AM_CFLAGS -DHAVE_PK_CALLBACKS"
fi
fi
if test "x$ENABLED_WOLFENGINE" = "xyes"
then
AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_ECB"
@@ -13140,6 +13158,7 @@ AM_CONDITIONAL([BUILD_CAAM],[test "x$ENABLED_CAAM" != "xno"])
AM_CONDITIONAL([BUILD_QNXCAAM],[test "x$ENABLED_CAAM_QNX" = "xyes"])
AM_CONDITIONAL([BUILD_IOTSAFE],[test "x$ENABLED_IOTSAFE" = "xyes"])
AM_CONDITIONAL([BUILD_IOTSAFE_HWRNG],[test "x$ENABLED_IOTSAFE_HWRNG" = "xyes"])
AM_CONDITIONAL([BUILD_VAULTIC],[test "x$ENABLED_VAULTIC" = "xyes"])
AM_CONDITIONAL([BUILD_SE050],[test "x$ENABLED_SE050" = "xyes"])
AM_CONDITIONAL([BUILD_STSAFE],[test "x$ENABLED_STSAFE" != "xno"])
AM_CONDITIONAL([BUILD_RTL8735B],[test "x$ENABLED_RTL8735B" != "xno"])
@@ -13749,6 +13768,7 @@ echo " * PK callbacks: $ENABLED_PKCALLBACKS"
echo " * Crypto callbacks: $ENABLED_CRYPTOCB"
echo " * i.MX CAAM: $ENABLED_CAAM"
echo " * IoT-Safe: $ENABLED_IOTSAFE"
echo " * WISeKey/SealSQ VaultIC: $ENABLED_VAULTIC"
echo " * IoT-Safe HWRNG: $ENABLED_IOTSAFE_HWRNG"
echo " * NXP SE050: $ENABLED_SE050"
echo " * STMicro STSAFE: $ENABLED_STSAFE"
+5
View File
@@ -237,6 +237,11 @@ if BUILD_IOTSAFE
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/iotsafe/iotsafe.c
endif
if BUILD_VAULTIC
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/sealsq/vaultic.c
endif
EXTRA_DIST += wolfcrypt/src/port/sealsq/README.md
if BUILD_CAAM
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/caam/wolfcaam_init.c
+174
View File
@@ -0,0 +1,174 @@
# WISeKey / SealSQ VaultIC Port
This port offloads TLS ECC P-256 operations to a WISeKey/SealSQ VaultIC secure
element (for example the VaultIC 408 on the DEVKIT_VIC408) using wolfSSL's
public-key (PK) callbacks. The private key never leaves the chip.
## What it does
`wolfcrypt/src/port/sealsq/vaultic.c` provides:
* `WOLFSSL_VAULTIC_EccSignCb` - ECDSA P-256 sign on the device
* `WOLFSSL_VAULTIC_EccVerifyCb` - ECDSA P-256 verify on the device
* `WOLFSSL_VAULTIC_EccKeyGenCb` - ephemeral P-256 key generation on the device
* `WOLFSSL_VAULTIC_EccSharedSecretCb` - ECDH P-256 shared secret on the device
* `WOLFSSL_VAULTIC_LoadCertificates` - read the device and CA certificates
stored on the chip into a `WOLFSSL_CTX`
* `WOLFSSL_VAULTIC_SetupPkCallbacks` / `WOLFSSL_VAULTIC_SetupPkCallbackCtx` -
register the callbacks on a `WOLFSSL_CTX` / `WOLFSSL`
The key-generation and shared-secret (ECDH) callbacks can be compiled out by
defining `VLT_TLS_NO_ECDH`, matching the vendor library configuration.
## Dependencies
This port is glue only. It requires the external SealSQ **VaultIC-TLS SDK**,
which provides `vaultic_tls.h` and the `vlt_tls_*` P-256 API that talks to the
chip. That SDK is distributed by SealSQ and is not part of wolfSSL.
## Building
Enable the port and point the compiler/linker at the vendor SDK:
```sh
./configure --enable-vaultic \
CFLAGS="-I/path/to/VaultIC-TLS/vaultic_tls-4xx/src" \
LIBS="-lvaultic_tls_408"
make
```
`--enable-vaultic` defines `WOLFSSL_VAULTIC` and enables PK callbacks
(`HAVE_PK_CALLBACKS`) automatically. The port compiles to nothing when
`WOLFSSL_VAULTIC` is not defined.
### Building the port outside libwolfssl
Like other wolfSSL port files, `vaultic.c` is meant to be compiled as part of
libwolfssl (via `--enable-vaultic`), where it inherits the wolfSSL
configuration through `config.h`. If instead you compile `vaultic.c` in a
separate target (for example the SealSQ devkit builds it into its own
`vaultic_wolfssl` library alongside an `add_subdirectory(wolfssl)` CMake
build), two things are required so the file sees the wolfSSL configuration:
* Define `WOLFSSL_USE_OPTIONS_H` when compiling `vaultic.c`, so
`settings.h` pulls in the generated `wolfssl/options.h`. Without it the
wolfSSL headers fall back to defaults (`ecc_key` is incomplete,
`ECC_SECP256R1` is undeclared).
* Enable PK callbacks through the wolfSSL build option
(autotools `--enable-pkcallbacks`, CMake `WOLFSSL_PKCALLBACKS=yes`), not a
bare `-DHAVE_PK_CALLBACKS` compile flag. The generated `options.h` contains
`#undef HAVE_PK_CALLBACKS` for disabled options, which cancels a
command-line define once `options.h` is included.
## Usage
```c
WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfTLS_client_method());
/* register the VaultIC ECC PK callbacks */
WOLFSSL_VAULTIC_SetupPkCallbacks(ctx);
/* load the device + CA certificates stored on the chip */
WOLFSSL_VAULTIC_LoadCertificates(ctx);
WOLFSSL* ssl = wolfSSL_new(ctx);
WOLFSSL_VAULTIC_SetupPkCallbackCtx(ssl, NULL);
/* ... proceed with the TLS handshake ... */
```
The VaultIC-TLS SDK must be initialized (`vlt_tls_init()`) before the
handshake and closed (`vlt_tls_close()`) afterwards; see the SealSQ devkit
sample applications.
## Building and provisioning with the SealSQ devkit
The SealSQ VaultIC-TLS devkit (for example `DEVKIT_VIC408_TLS_RPI`) drives the
whole build/provision/run flow with shell scripts. High-level orientation and
the files that matter:
* SDK library: `VaultIC-TLS/vaultic_tls/vaultic_tls-4xx/src` (`vaultic_tls.h`
API, `vaultic_tls_config.h`), on top of the low-level chip library
`vaultic_tls/vaultic_elib_408` (its Raspberry Pi I2C/SPI drivers live under
`src/arch/embedded/raspberry/pi3`, e.g. `vaultic_twi_driver.c`).
* Glue build: `vaultic_tls/vaultic_wolfssl/CMakeLists.txt` compiles this
port's `vaultic.c` and links it against `wolfssl` and `vaultic_tls_408`.
* Config: `demos/config.cfg` selects `PRODUCT` (408), `VAULTIC_COMM`
(`SPI` or `I2C`), and log level.
* Scripts: `demos/wolfssl/tls_client/scripts` - `install.sh` (set up the
CMake build trees), `build.sh` (build the perso apps, the glue, and the
demos), `perso_client_vaultic.sh` (provision the chip), `run_server.sh` and
`run_client_vaultic.sh` (start the plain server, then the VaultIC client).
Steps:
1. Set `demos/config.cfg` (`PRODUCT=408`, `VAULTIC_COMM=I2C` or `SPI`), then
run `install.sh` and `build.sh`. Point the glue at a wolfSSL tree that
contains this port (the devkit's `wolfssl_patch` copy is no longer needed
once the port is upstream). When the glue compiles `vaultic.c` in its own
library, apply the two flags from "Building the port outside libwolfssl"
above.
2. Provision the chip once with `perso_client_vaultic.sh`. It runs the
`perso_tls` app (`vaultic_tls-4xx/apps/perso_tls`) with the device key,
device cert, and root CA cert from `VaultIC-TLS/certificates`
(`deviceKey.der`, `deviceCert.der`, `rootCACert.der`), submitting the
manufacturer password supplied by your SealSQ FAE, then runs
`check_tls_perso` (`vaultic_tls-4xx/apps/check_tls_perso`) to read the
certificates back off the chip and confirm success.
3. Run `run_server.sh` in one shell and `run_client_vaultic.sh` in another to
perform TLS 1.2 and TLS 1.3 handshakes whose ECC operations run on the
VaultIC.
## Raspberry Pi I2C and clock stretching
This section is about the external VaultIC-TLS SDK's I2C transport on a
Raspberry Pi, not about the wolfSSL port itself, but it is the most common
thing that blocks bring-up, so it is documented here. The VaultIC is an I2C
(or SPI) secure element; when it is attached over I2C it stretches the clock
(holds SCL low) while it performs internal operations, and the Raspberry Pi
I2C hardware has long-standing trouble with clock-stretching peripherals.
Symptoms of the problem are `TWI Send/Receive failure` (status `CF0D`/`CF0F`),
`Block Protocol WARNING (comm error)` / `resync request` messages, and finally
`Block Protocol ERROR (too many rsync requests)`. Short exchanges (for example
reading a status) may succeed while longer, multi-block transfers (for example
the certificate writes done during personalization) fail.
### Raspberry Pi 2/3/4 (BCM I2C)
The classic workaround is to lower the I2C bus clock so the timing margins are
wide enough to tolerate the stretching. The VaultIC-TLS SDK's own I2C driver
tries to do this by writing the BCM I2C `DIV` register directly through
`/dev/mem` (which is why it wants to be run with `sudo`), using hardcoded
controller base addresses for the Pi 2/3 (`0x3f804000`) and Pi 4
(`0xfe804000`). A bus clock around 50 kHz is typically reliable.
### Raspberry Pi 5 (RP1 / DesignWare I2C) - use a bit-banged bus
The Pi 5 does not work with the SDK's built-in bitrate control: its I2C
controller lives in the RP1 chip (a Synopsys DesignWare controller behind
PCIe) at a different address, so the SDK's `/dev/mem` register poke targets a
controller that is not there and has no effect. Worse, the RP1 DesignWare
controller itself hangs on the VaultIC's clock stretching during longer
transfers, reporting `i2c_designware ...: SDA stuck at low` in `dmesg`.
Lowering `dtparam=i2c_arm_baudrate` (even down to 10 kHz) does not fix this,
because the failure is the controller mishandling the stretch, not a timing
margin.
The reliable fix on the Pi 5 is to drive the same SDA/SCL pins with the
kernel's software (bit-banged) I2C driver, which polls SCL and therefore
honours clock stretching correctly. In `/boot/firmware/config.txt`, disable
the hardware I2C on those pins and add a software bus on GPIO 2 (SDA) and
GPIO 3 (SCL):
```
# dtparam=i2c_arm=on
dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3,i2c_gpio_delay_us=4
```
After rebooting, find the new bus (its `name` reads `i2c-gpio`, for example
`/dev/i2c-13`) and point the SDK's I2C device path at it (the VaultIC-TLS
elib hardcodes `/dev/i2c-1` in its Raspberry Pi TWI driver). With the
bit-banged bus, personalization and full TLS 1.2 / TLS 1.3 handshakes to the
VaultIC 408 complete with no I2C errors.
Alternatively, wiring the VaultIC over SPI avoids clock stretching entirely.
+445
View File
@@ -0,0 +1,445 @@
/* vaultic.c
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* 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 3 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-1335, USA
*/
/* WISeKey/SealSQ VaultIC secure element port. Offloads TLS ECC P-256
* operations (sign / verify / keygen / ECDH shared secret) to the VaultIC via
* wolfSSL's PK callbacks, and loads the device + CA certificates stored on the
* chip into a WOLFSSL_CTX. Requires the external SealSQ VaultIC-TLS SDK
* (vaultic_tls.h and the vlt_tls_* P256 API) on the include/link path. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#ifdef WOLFSSL_VAULTIC
#ifndef HAVE_PK_CALLBACKS
#error WOLFSSL_VAULTIC requires HAVE_PK_CALLBACKS
#endif
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/port/sealsq/vaultic.h>
#include "vaultic_tls.h" /* vendor VaultIC-TLS SDK (external) */
#define P256_BYTE_SZ 32
#ifndef VLT_TLS_NO_ECDH
/**
* \brief Key Gen Callback (used by TLS server)
*/
int WOLFSSL_VAULTIC_EccKeyGenCb(WOLFSSL* ssl, ecc_key* key, word32 keySz,
int ecc_curve, void* ctx)
{
int err;
byte pubKeyX[P256_BYTE_SZ] = {0};
byte pubKeyY[P256_BYTE_SZ] = {0};
(void)ssl;
(void)ctx;
WOLFSSL_MSG("WOLFSSL_VAULTIC_EccKeyGenCb");
/* check requested curve params */
if (ecc_curve != ECC_SECP256R1) {
WOLFSSL_MSG("ecc_curve != ECC_SECP256R1");
return NOT_COMPILED_IN;
}
if (keySz != P256_BYTE_SZ) {
WOLFSSL_MSG("keysize != 32. We are supporting ECC P256 case only");
return NOT_COMPILED_IN;
}
/* generate new ephemeral key on device */
if (vlt_tls_keygen_P256(pubKeyX, pubKeyY) != 0) {
WOLFSSL_MSG("vlt_tls_keygen_P256");
return WC_HW_E;
}
/* load generated public key into key, used by wolfSSL */
if ((err = wc_ecc_import_unsigned(key, pubKeyX, pubKeyY, NULL,
ecc_curve)) != 0) {
WOLFSSL_MSG("wc_ecc_import_unsigned");
}
return err;
}
#endif
/**
* \brief Verify Certificate Callback.
*
*/
int WOLFSSL_VAULTIC_EccVerifyCb(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)
{
int err;
byte signature[2*P256_BYTE_SZ] = {0};
byte *r, *s;
word32 r_len = P256_BYTE_SZ, s_len = P256_BYTE_SZ;
byte pubKeyX[P256_BYTE_SZ] = {0};
byte pubKeyY[P256_BYTE_SZ] = {0};
word32 pubKeyX_len = sizeof(pubKeyX);
word32 pubKeyY_len = sizeof(pubKeyY);
ecc_key key;
word32 inOutIdx = 0;
WOLFSSL_MSG("WOLFSSL_VAULTIC_EccVerifyCb");
(void)ssl;
(void)ctx;
*result = 0;
if (keyDer == NULL || sig == NULL || hash == NULL || result == NULL) {
return BAD_FUNC_ARG;
}
if ((err = wc_ecc_init(&key)) != 0) {
WOLFSSL_MSG("wc_ecc_init");
return err;
}
/* Decode the public key */
if ((err = wc_EccPublicKeyDecode(keyDer, &inOutIdx, &key, keySz)) != 0) {
WOLFSSL_MSG("wc_EccPublicKeyDecode");
wc_ecc_free(&key);
return err;
}
/* Extract Raw X and Y coordinates of the public key */
if ((err = wc_ecc_export_public_raw(&key, pubKeyX, &pubKeyX_len,
pubKeyY, &pubKeyY_len)) != 0) {
WOLFSSL_MSG("wc_ecc_export_public_raw");
wc_ecc_free(&key);
return err;
}
/* Left pad public key */
vlt_tls_left_pad_P256(pubKeyX, pubKeyX_len);
vlt_tls_left_pad_P256(pubKeyY, pubKeyY_len);
/* Check requested curve */
if (key.dp->id != ECC_SECP256R1) {
WOLFSSL_MSG("id != ECC_SECP256R1");
wc_ecc_free(&key);
return NOT_COMPILED_IN;
}
/* Extract R and S from signature */
XMEMSET(signature, 0, sizeof(signature));
r = &signature[0];
s = &signature[sizeof(signature)/2];
err = wc_ecc_sig_to_rs(sig, sigSz, r, &r_len, s, &s_len);
wc_ecc_free(&key);
if (err != 0) {
WOLFSSL_MSG("wc_ecc_sig_to_rs");
return err;
}
/* Left pad r & s */
vlt_tls_left_pad_P256(r, r_len);
vlt_tls_left_pad_P256(s, s_len);
/* Verify signature with VaultIC */
if (vlt_tls_verify_signature_P256(hash, hashSz, signature, pubKeyX,
pubKeyY) != 0) {
WOLFSSL_MSG("vlt_tls_verify_signature_P256");
return WC_HW_E;
}
else {
*result = 1;
return 0;
}
}
/**
* \brief Sign Certificate Callback.
*/
int WOLFSSL_VAULTIC_EccSignCb(WOLFSSL* ssl, const byte* in,
word32 inSz, byte* out, word32* outSz,
const byte* key, word32 keySz, void* ctx)
{
int err;
byte sig_R[P256_BYTE_SZ] = {0};
byte sig_S[P256_BYTE_SZ] = {0};
(void)ssl;
(void)ctx;
(void)key;
(void)keySz;
WOLFSSL_MSG("WOLFSSL_VAULTIC_EccSignCb");
/* Sign input message using VaultIC */
if (vlt_tls_compute_signature_P256(in, inSz, sig_R, sig_S) != 0) {
WOLFSSL_MSG("vlt_tls_compute_signature_P256");
return WC_HW_E;
}
/* Convert R and S to signature */
if ((err = wc_ecc_rs_raw_to_sig(sig_R, P256_BYTE_SZ, sig_S, P256_BYTE_SZ,
out, outSz)) != 0) {
WOLFSSL_MSG("wc_ecc_rs_raw_to_sig");
return err;
}
return err;
}
#ifndef VLT_TLS_NO_ECDH
/**
* \brief Create pre master secret using peer's public key and self private key.
*/
int WOLFSSL_VAULTIC_EccSharedSecretCb(WOLFSSL* ssl, ecc_key* otherPubKey,
unsigned char* pubKeyDer, unsigned int* pubKeySz,
unsigned char* out, unsigned int* outlen,
int side, void* ctx)
{
int err;
byte otherPubKeyX[P256_BYTE_SZ] = {0};
byte otherPubKeyY[P256_BYTE_SZ] = {0};
word32 otherPubKeyX_len = sizeof(otherPubKeyX);
word32 otherPubKeyY_len = sizeof(otherPubKeyY);
byte pubKeyX[P256_BYTE_SZ] = {0};
byte pubKeyY[P256_BYTE_SZ] = {0};
ecc_key tmpKey;
(void)ssl;
(void)ctx;
WOLFSSL_MSG("WOLFSSL_VAULTIC_EccSharedSecretCb");
/* check requested curve */
if (otherPubKey->dp->id != ECC_SECP256R1) {
WOLFSSL_MSG("id != ECC_SECP256R1");
return NOT_COMPILED_IN;
}
/* for client: create and export public key */
if (side == WOLFSSL_CLIENT_END) {
/* Export otherPubKey raw X and Y */
err = wc_ecc_export_public_raw(otherPubKey,
&otherPubKeyX[0], &otherPubKeyX_len,
&otherPubKeyY[0], &otherPubKeyY_len);
if (err != 0) {
WOLFSSL_MSG("wc_ecc_export_public_raw");
return err;
}
vlt_tls_left_pad_P256(otherPubKeyX, otherPubKeyX_len);
vlt_tls_left_pad_P256(otherPubKeyY, otherPubKeyY_len);
/* TLS v1.2 and older we must generate a key here for the client only.
* TLS v1.3 calls key gen early with key share */
if (wolfSSL_GetVersion(ssl) < WOLFSSL_TLSV1_3) {
if (vlt_tls_keygen_P256(pubKeyX, pubKeyY) != 0) {
WOLFSSL_MSG("vlt_tls_keygen_P256");
return WC_HW_E;
}
/* convert raw unsigned public key to X.963 format for TLS */
if ((err = wc_ecc_init(&tmpKey)) != 0) {
WOLFSSL_MSG("wc_ecc_init");
return err;
}
if ((err = wc_ecc_import_unsigned(&tmpKey, pubKeyX, pubKeyY,
NULL, ECC_SECP256R1)) != 0) {
WOLFSSL_MSG("wc_ecc_import_unsigned");
wc_ecc_free(&tmpKey);
return err;
}
if ((err = wc_ecc_export_x963(&tmpKey, pubKeyDer, pubKeySz)) != 0) {
WOLFSSL_MSG("wc_ecc_export_x963");
wc_ecc_free(&tmpKey);
return err;
}
wc_ecc_free(&tmpKey);
}
}
/* for server: import public key */
else if (side == WOLFSSL_SERVER_END) {
if ((err = wc_ecc_init(&tmpKey)) != 0) {
WOLFSSL_MSG("wc_ecc_init");
return err;
}
/* import peer's key and export as raw unsigned for hardware */
if ((err = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, &tmpKey,
ECC_SECP256R1)) != 0) {
WOLFSSL_MSG("wc_ecc_import_x963_ex");
wc_ecc_free(&tmpKey);
return err;
}
if ((err = wc_ecc_export_public_raw(&tmpKey, otherPubKeyX,
&otherPubKeyX_len, otherPubKeyY, &otherPubKeyY_len)) != 0) {
WOLFSSL_MSG("wc_ecc_export_public_raw");
wc_ecc_free(&tmpKey);
return err;
}
vlt_tls_left_pad_P256(otherPubKeyX, otherPubKeyX_len);
vlt_tls_left_pad_P256(otherPubKeyY, otherPubKeyY_len);
wc_ecc_free(&tmpKey);
}
else {
return BAD_FUNC_ARG;
}
/* Compute shared secret */
if (vlt_tls_compute_shared_secret_P256(otherPubKeyX, otherPubKeyY,
out) != 0) {
WOLFSSL_MSG("vlt_tls_compute_shared_secret_P256");
return WC_HW_E;
}
*outlen = P256_BYTE_SZ;
return 0;
}
#endif
/**
* \brief Read VaultIC Certificates and add them to wolfssl context
*/
int WOLFSSL_VAULTIC_LoadCertificates(WOLFSSL_CTX* ctx)
{
int ret = -1;
/* CA certificate */
unsigned char *ca_cert = NULL;
int sizeof_ca_cert = 0;
/* Device certificate */
unsigned char *device_cert = NULL;
int sizeof_device_cert = 0;
/* Read Device certificate in VaultIC */
WOLFSSL_MSG("Read Device Certificate in VaultIC");
if ((sizeof_device_cert = vlt_tls_get_cert_size(SSL_VIC_DEVICE_CERT))
== -1) {
WOLFSSL_MSG("No Device Certificate found in VaultIC");
return -1;
}
device_cert = (unsigned char*)XMALLOC(sizeof_device_cert, NULL,
DYNAMIC_TYPE_ECC_BUFFER);
if (device_cert == NULL) {
WOLFSSL_MSG("malloc device_cert");
return MEMORY_E;
}
if (vlt_tls_read_cert(device_cert, SSL_VIC_DEVICE_CERT) != 0) {
WOLFSSL_MSG("vlt_tls_read_cert Device");
goto free_cert_buffers;
}
WOLFSSL_MSG("[Device certificate]");
WOLFSSL_BUFFER(device_cert, sizeof_device_cert);
/* Read CA certificate in VaultIC */
WOLFSSL_MSG("Read CA Certificate in VaultIC");
if ((sizeof_ca_cert = vlt_tls_get_cert_size(SSL_VIC_CA_CERT)) == -1) {
WOLFSSL_MSG("No CA Certificate found in VaultIC");
goto free_cert_buffers;
}
ca_cert = (unsigned char*)XMALLOC(sizeof_ca_cert, NULL,
DYNAMIC_TYPE_ECC_BUFFER);
if (ca_cert == NULL) {
WOLFSSL_MSG("malloc ca_cert");
goto free_cert_buffers;
}
if (vlt_tls_read_cert(ca_cert, SSL_VIC_CA_CERT) != 0) {
WOLFSSL_MSG("vlt_tls_read_cert CA");
goto free_cert_buffers;
}
WOLFSSL_MSG("[CA certificate]");
WOLFSSL_BUFFER(ca_cert, sizeof_ca_cert);
/* Load CA certificate into WOLFSSL_CTX */
if ((ret = wolfSSL_CTX_load_verify_buffer(ctx, ca_cert,
sizeof_ca_cert, WOLFSSL_FILETYPE_ASN1)) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("failed to load CA certificate");
goto free_cert_buffers;
}
/* Load Device certificate into WOLFSSL_CTX */
if ((ret = wolfSSL_CTX_use_certificate_buffer(ctx, device_cert,
sizeof_device_cert, WOLFSSL_FILETYPE_ASN1)) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("failed to load Device certificate");
goto free_cert_buffers;
}
/* VaultIC certificates successfully injected into wolfSSL */
ret = 0;
free_cert_buffers:
if (ca_cert != NULL)
XFREE(ca_cert, NULL, DYNAMIC_TYPE_ECC_BUFFER);
if (device_cert != NULL)
XFREE(device_cert, NULL, DYNAMIC_TYPE_ECC_BUFFER);
return ret;
}
int WOLFSSL_VAULTIC_SetupPkCallbacks(WOLFSSL_CTX* ctx)
{
wolfSSL_CTX_SetEccSignCb(ctx, WOLFSSL_VAULTIC_EccSignCb);
wolfSSL_CTX_SetEccVerifyCb(ctx, WOLFSSL_VAULTIC_EccVerifyCb);
#ifndef VLT_TLS_NO_ECDH
wolfSSL_CTX_SetEccKeyGenCb(ctx, WOLFSSL_VAULTIC_EccKeyGenCb);
wolfSSL_CTX_SetEccSharedSecretCb(ctx, WOLFSSL_VAULTIC_EccSharedSecretCb);
#endif
return 0;
}
int WOLFSSL_VAULTIC_SetupPkCallbackCtx(WOLFSSL* ssl, void* user_ctx)
{
#ifndef VLT_TLS_NO_ECDH
wolfSSL_SetEccKeyGenCtx(ssl, user_ctx);
wolfSSL_SetEccSharedSecretCtx(ssl, user_ctx);
#endif
wolfSSL_SetEccSignCtx(ssl, user_ctx);
wolfSSL_SetEccVerifyCtx(ssl, user_ctx);
return 0;
}
#endif /* WOLFSSL_VAULTIC */
+4
View File
@@ -226,6 +226,10 @@ if BUILD_IOTSAFE
nobase_include_HEADERS+= wolfssl/wolfcrypt/port/iotsafe/iotsafe.h
endif
if BUILD_VAULTIC
nobase_include_HEADERS+= wolfssl/wolfcrypt/port/sealsq/vaultic.h
endif
if BUILD_PSA
nobase_include_HEADERS+= wolfssl/wolfcrypt/port/psa/psa.h
endif
+70
View File
@@ -0,0 +1,70 @@
/* vaultic.h
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* 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 3 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-1335, USA
*/
/* WISeKey/SealSQ VaultIC secure element port (PK callbacks) */
#ifndef _WOLFPORT_VAULTIC_H_
#define _WOLFPORT_VAULTIC_H_
#include <wolfssl/wolfcrypt/settings.h>
#ifdef WOLFSSL_VAULTIC
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/ecc.h>
#ifdef __cplusplus
extern "C" {
#endif
WOLFSSL_API int WOLFSSL_VAULTIC_EccKeyGenCb(WOLFSSL* ssl, ecc_key* key,
word32 keySz, int ecc_curve, void* ctx);
WOLFSSL_API int WOLFSSL_VAULTIC_EccVerifyCb(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);
WOLFSSL_API int WOLFSSL_VAULTIC_EccSignCb(WOLFSSL* ssl,
const byte* in, word32 inSz,
byte* out, word32* outSz,
const byte* key, word32 keySz, void* ctx);
WOLFSSL_API int WOLFSSL_VAULTIC_EccSharedSecretCb(WOLFSSL* ssl,
ecc_key* otherKey,
unsigned char* pubKeyDer, unsigned int* pubKeySz,
unsigned char* out, unsigned int* outlen,
int side, void* ctx);
WOLFSSL_API int WOLFSSL_VAULTIC_LoadCertificates(WOLFSSL_CTX* ctx);
/* Helper API's for setting up callbacks */
WOLFSSL_API int WOLFSSL_VAULTIC_SetupPkCallbacks(WOLFSSL_CTX* ctx);
WOLFSSL_API int WOLFSSL_VAULTIC_SetupPkCallbackCtx(WOLFSSL* ssl, void* user_ctx);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* WOLFSSL_VAULTIC */
#endif /* _WOLFPORT_VAULTIC_H_ */