Example for ST-SAFE A120
parent
45616142ca
commit
a4072803f2
|
|
@ -402,3 +402,8 @@ kernel/bsdkm/bsd_example.ko
|
|||
kernel/bsdkm/machine
|
||||
kernel/bsdkm/opt_global.h
|
||||
kernel/bsdkm/x86
|
||||
|
||||
# STSAFE test executables
|
||||
stsafe/stsafe_test
|
||||
stsafe/wolfssl_stsafe_test
|
||||
stsafe/wolfssl_stsafe_full_test
|
||||
|
|
|
|||
|
|
@ -0,0 +1,162 @@
|
|||
# STSAFE-A120 Test Makefile for Raspberry Pi
|
||||
#
|
||||
# Copyright 2025 wolfSSL Inc.
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -Wextra -O2 -g
|
||||
|
||||
# wolfSSL configuration
|
||||
# Option 1: Use installed wolfSSL (after make install)
|
||||
#WOLFSSL_DIR = /usr/local
|
||||
# Option 2: Use local wolfSSL source
|
||||
WOLFSSL_DIR = $(HOME)/wolfssl
|
||||
|
||||
# STSELib paths
|
||||
STSELIB_DIR = $(HOME)/STSELib
|
||||
PLATFORM_DIR = ./platform
|
||||
|
||||
# Include paths
|
||||
# Note: Current directory (.) must come first so our user_settings.h is found
|
||||
INCLUDES = -I. \
|
||||
-I$(STSELIB_DIR) \
|
||||
-I$(PLATFORM_DIR) \
|
||||
-I$(WOLFSSL_DIR)
|
||||
|
||||
# wolfSSL library flags
|
||||
# For installed wolfSSL:
|
||||
#LDFLAGS = -L$(WOLFSSL_DIR)/lib -lwolfssl -lm
|
||||
# For local wolfSSL source (using .libs):
|
||||
LDFLAGS = -L$(WOLFSSL_DIR)/src/.libs -lwolfssl -lm -Wl,-rpath,$(WOLFSSL_DIR)/src/.libs
|
||||
|
||||
# wolfSSL compile flags
|
||||
# WOLFSSL_USER_SETTINGS tells wolfSSL to include user_settings.h
|
||||
CFLAGS += -DWOLFSSL_USER_SETTINGS
|
||||
|
||||
# STSELib source files
|
||||
STSELIB_CORE_SRC = $(STSELIB_DIR)/core/stse_device.c \
|
||||
$(STSELIB_DIR)/core/stse_frame.c \
|
||||
$(STSELIB_DIR)/core/stse_generic_typedef.c \
|
||||
$(STSELIB_DIR)/core/stse_platform.c \
|
||||
$(STSELIB_DIR)/core/stse_session.c
|
||||
|
||||
STSELIB_API_SRC = $(wildcard $(STSELIB_DIR)/api/*.c)
|
||||
STSELIB_SERVICES_SRC = $(wildcard $(STSELIB_DIR)/services/stsafea/*.c) \
|
||||
$(wildcard $(STSELIB_DIR)/services/stsafel/*.c)
|
||||
STSELIB_CERT_SRC = $(wildcard $(STSELIB_DIR)/certificate/*.c)
|
||||
|
||||
# Platform source files
|
||||
PLATFORM_SRC = $(PLATFORM_DIR)/stse_platform_linux.c
|
||||
|
||||
# Platform crypto source (wolfSSL implementation)
|
||||
# Uncomment when building with wolfSSL crypto support:
|
||||
PLATFORM_CRYPTO_SRC = $(PLATFORM_DIR)/stse_platform_crypto_wolfssl.c
|
||||
|
||||
# Test source files
|
||||
TEST_SRC = stsafe_test.c
|
||||
WOLFSSL_TEST_SRC = wolfssl_stsafe_test.c
|
||||
WOLFSSL_FULL_TEST_SRC = wolfssl_stsafe_full_test.c
|
||||
|
||||
# All sources
|
||||
ALL_SRC = $(STSELIB_CORE_SRC) $(STSELIB_API_SRC) $(STSELIB_SERVICES_SRC) \
|
||||
$(STSELIB_CERT_SRC) $(PLATFORM_SRC) $(PLATFORM_CRYPTO_SRC) $(TEST_SRC)
|
||||
|
||||
# wolfSSL STSAFE port source
|
||||
WOLFSSL_STSAFE_SRC = $(WOLFSSL_DIR)/wolfcrypt/src/port/st/stsafe.c
|
||||
|
||||
# Targets
|
||||
TARGET = stsafe_test
|
||||
WOLFSSL_TARGET = wolfssl_stsafe_test
|
||||
WOLFSSL_FULL_TARGET = wolfssl_stsafe_full_test
|
||||
|
||||
.PHONY: all clean test info basic wolfssl wolfssl-full
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
# Full build with wolfSSL crypto support
|
||||
$(TARGET): $(TEST_SRC) $(PLATFORM_SRC) $(PLATFORM_CRYPTO_SRC)
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -o $@ \
|
||||
$(TEST_SRC) \
|
||||
$(PLATFORM_SRC) \
|
||||
$(PLATFORM_CRYPTO_SRC) \
|
||||
$(STSELIB_CORE_SRC) \
|
||||
$(STSELIB_API_SRC) \
|
||||
$(STSELIB_SERVICES_SRC) \
|
||||
$(STSELIB_CERT_SRC) \
|
||||
$(LDFLAGS)
|
||||
|
||||
# Basic build without wolfSSL (for initial testing without host sessions)
|
||||
basic: $(TEST_SRC) $(PLATFORM_SRC)
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -o $(TARGET) \
|
||||
$(TEST_SRC) \
|
||||
$(PLATFORM_SRC) \
|
||||
$(STSELIB_CORE_SRC) \
|
||||
$(STSELIB_API_SRC) \
|
||||
$(STSELIB_SERVICES_SRC) \
|
||||
$(STSELIB_CERT_SRC)
|
||||
|
||||
# wolfSSL crypto callback test build
|
||||
# Note: We compile stsafe.c directly since it's not built into libwolfssl by default
|
||||
# IMPORTANT: Use WOLFSSL_USE_OPTIONS_H to get options.h included for proper wolfSSL settings
|
||||
# We add -DWOLFSSL_STSAFEA120 -DUSE_STSAFE_RNG_SEED to enable STSAFE in stsafe.c
|
||||
WOLFSSL_STSAFE_FLAGS = -DWOLFSSL_USE_OPTIONS_H -DWOLFSSL_STSAFEA120 -DUSE_STSAFE_RNG_SEED -Wno-strict-prototypes
|
||||
WOLFSSL_BASE_FLAGS = -Wall -Wextra -O2 -g
|
||||
wolfssl: $(WOLFSSL_TEST_SRC) $(PLATFORM_SRC) $(PLATFORM_CRYPTO_SRC)
|
||||
$(CC) $(WOLFSSL_BASE_FLAGS) $(WOLFSSL_STSAFE_FLAGS) -I$(STSELIB_DIR) -I$(PLATFORM_DIR) -I$(WOLFSSL_DIR) \
|
||||
-c $(WOLFSSL_STSAFE_SRC) -o stsafe.o
|
||||
$(CC) $(WOLFSSL_BASE_FLAGS) $(WOLFSSL_STSAFE_FLAGS) -I$(STSELIB_DIR) -I$(PLATFORM_DIR) -I$(WOLFSSL_DIR) \
|
||||
-c $(PLATFORM_SRC) -o stse_platform_linux.o
|
||||
$(CC) $(WOLFSSL_BASE_FLAGS) $(WOLFSSL_STSAFE_FLAGS) -I$(STSELIB_DIR) -I$(PLATFORM_DIR) -I$(WOLFSSL_DIR) \
|
||||
-c $(PLATFORM_CRYPTO_SRC) -o stse_platform_crypto.o
|
||||
$(CC) $(WOLFSSL_BASE_FLAGS) $(WOLFSSL_STSAFE_FLAGS) -I$(STSELIB_DIR) -I$(PLATFORM_DIR) -I$(WOLFSSL_DIR) \
|
||||
-o $(WOLFSSL_TARGET) \
|
||||
$(WOLFSSL_TEST_SRC) \
|
||||
stse_platform_linux.o stse_platform_crypto.o stsafe.o \
|
||||
$(STSELIB_CORE_SRC) \
|
||||
$(STSELIB_API_SRC) \
|
||||
$(STSELIB_SERVICES_SRC) \
|
||||
$(STSELIB_CERT_SRC) \
|
||||
$(LDFLAGS)
|
||||
|
||||
test: $(TARGET)
|
||||
./$(TARGET)
|
||||
|
||||
test-wolfssl: wolfssl
|
||||
./$(WOLFSSL_TARGET)
|
||||
|
||||
# Full wolfSSL integration test with ECDH and benchmarks
|
||||
wolfssl-full: $(WOLFSSL_FULL_TEST_SRC) $(PLATFORM_SRC) $(PLATFORM_CRYPTO_SRC)
|
||||
$(CC) $(WOLFSSL_BASE_FLAGS) $(WOLFSSL_STSAFE_FLAGS) -I$(STSELIB_DIR) -I$(PLATFORM_DIR) -I$(WOLFSSL_DIR) \
|
||||
-c $(WOLFSSL_STSAFE_SRC) -o stsafe.o
|
||||
$(CC) $(WOLFSSL_BASE_FLAGS) $(WOLFSSL_STSAFE_FLAGS) -I$(STSELIB_DIR) -I$(PLATFORM_DIR) -I$(WOLFSSL_DIR) \
|
||||
-c $(PLATFORM_SRC) -o stse_platform_linux.o
|
||||
$(CC) $(WOLFSSL_BASE_FLAGS) $(WOLFSSL_STSAFE_FLAGS) -I$(STSELIB_DIR) -I$(PLATFORM_DIR) -I$(WOLFSSL_DIR) \
|
||||
-c $(PLATFORM_CRYPTO_SRC) -o stse_platform_crypto.o
|
||||
$(CC) $(WOLFSSL_BASE_FLAGS) $(WOLFSSL_STSAFE_FLAGS) -I$(STSELIB_DIR) -I$(PLATFORM_DIR) -I$(WOLFSSL_DIR) \
|
||||
-o $(WOLFSSL_FULL_TARGET) \
|
||||
$(WOLFSSL_FULL_TEST_SRC) \
|
||||
stse_platform_linux.o stse_platform_crypto.o stsafe.o \
|
||||
$(STSELIB_CORE_SRC) \
|
||||
$(STSELIB_API_SRC) \
|
||||
$(STSELIB_SERVICES_SRC) \
|
||||
$(STSELIB_CERT_SRC) \
|
||||
$(LDFLAGS)
|
||||
|
||||
test-wolfssl-full: wolfssl-full
|
||||
./$(WOLFSSL_FULL_TARGET)
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET) $(WOLFSSL_TARGET) $(WOLFSSL_FULL_TARGET) *.o stsafe.o stse_platform_linux.o stse_platform_crypto.o
|
||||
|
||||
# Show configuration
|
||||
info:
|
||||
@echo "STSELib directory: $(STSELIB_DIR)"
|
||||
@echo "wolfSSL directory: $(WOLFSSL_DIR)"
|
||||
@echo "Platform directory: $(PLATFORM_DIR)"
|
||||
@echo "Include paths: $(INCLUDES)"
|
||||
@echo "Linker flags: $(LDFLAGS)"
|
||||
@echo ""
|
||||
@echo "Build targets:"
|
||||
@echo " make - Build with wolfSSL crypto support (full features)"
|
||||
@echo " make basic - Build without wolfSSL (basic tests only)"
|
||||
@echo " make test - Build and run tests"
|
||||
@echo " make clean - Clean build artifacts"
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
# wolfSSL STSAFE-A120 Test Suite
|
||||
|
||||
Test harness for wolfSSL integration with ST STSAFE-A120 secure element on Raspberry Pi 5.
|
||||
|
||||
## Hardware Requirements
|
||||
|
||||
- Raspberry Pi 5 (or compatible Linux system with I2C)
|
||||
- STSAFE-A120 secure element connected via I2C
|
||||
- I2C enabled on the system
|
||||
|
||||
## Software Requirements
|
||||
|
||||
- wolfSSL library (compiled with ECC, CMAC, SHA-384 support)
|
||||
- STSELib (ST Secure Element Library)
|
||||
- GCC compiler
|
||||
- Linux I2C development headers (`libi2c-dev`)
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
stsafe/
|
||||
├── Makefile # Build configuration
|
||||
├── README.md # This file
|
||||
├── user_settings.h # wolfSSL configuration
|
||||
├── stsafe_test.c # STSELib basic tests
|
||||
├── wolfssl_stsafe_test.c # wolfSSL crypto callback tests
|
||||
├── wolfssl_stsafe_full_test.c # Full integration tests with benchmarks
|
||||
└── platform/
|
||||
├── stse_conf.h # STSELib configuration
|
||||
├── stse_platform_generic.h # Platform type definitions
|
||||
├── stse_platform_linux.c # Linux I2C platform implementation
|
||||
└── stse_platform_crypto_wolfssl.c # wolfSSL crypto for STSELib
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### I2C Setup
|
||||
|
||||
1. Enable I2C on Raspberry Pi:
|
||||
```bash
|
||||
sudo raspi-config
|
||||
# Navigate to: Interface Options -> I2C -> Enable
|
||||
```
|
||||
|
||||
2. Verify I2C device:
|
||||
```bash
|
||||
sudo i2cdetect -y 1
|
||||
# STSAFE should appear at address 0x20
|
||||
```
|
||||
|
||||
3. Set I2C permissions (optional, for non-root access):
|
||||
```bash
|
||||
sudo usermod -a -G i2c $USER
|
||||
# Logout and login again
|
||||
```
|
||||
|
||||
### Environment
|
||||
|
||||
Set paths to dependencies:
|
||||
```bash
|
||||
export WOLFSSL_DIR=$HOME/wolfssl
|
||||
export STSELIB_DIR=$HOME/STSELib
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
### Prerequisites
|
||||
|
||||
1. Build wolfSSL with required features:
|
||||
```bash
|
||||
cd $WOLFSSL_DIR
|
||||
./configure --enable-cryptocb --enable-ecc --enable-cmac --enable-sha384 --enable-debug
|
||||
make
|
||||
```
|
||||
|
||||
2. Clone STSELib:
|
||||
```bash
|
||||
git clone https://github.com/STMicroelectronics/STSELib.git $STSELIB_DIR
|
||||
```
|
||||
|
||||
### Build Targets
|
||||
|
||||
```bash
|
||||
# Build basic STSELib tests (no wolfSSL crypto callbacks)
|
||||
make
|
||||
|
||||
# Build wolfSSL crypto callback tests
|
||||
make wolfssl
|
||||
|
||||
# Build full integration tests with benchmarks
|
||||
make wolfssl-full
|
||||
|
||||
# Build without wolfSSL (basic I2C tests only)
|
||||
make basic
|
||||
|
||||
# Clean build artifacts
|
||||
make clean
|
||||
|
||||
# Show configuration
|
||||
make info
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
### Basic STSELib Tests
|
||||
```bash
|
||||
./stsafe_test
|
||||
```
|
||||
|
||||
Tests:
|
||||
- Echo command (I2C communication)
|
||||
- Random number generation
|
||||
- ECC P-256 key generation
|
||||
- ECDSA P-256 signing
|
||||
- ECC P-384 key generation
|
||||
|
||||
### wolfSSL Crypto Callback Tests
|
||||
```bash
|
||||
./wolfssl_stsafe_test
|
||||
```
|
||||
|
||||
Tests:
|
||||
- RNG with STSAFE-A120
|
||||
- ECC P-256 key generation via crypto callback
|
||||
- ECC P-384 key generation via crypto callback
|
||||
- ECDSA P-256 sign/verify
|
||||
- ECDSA P-384 sign/verify
|
||||
|
||||
### Full Integration Tests
|
||||
```bash
|
||||
./wolfssl_stsafe_full_test
|
||||
```
|
||||
|
||||
Tests:
|
||||
- RNG benchmark
|
||||
- ECDSA P-256 benchmark (keygen, sign, verify timing)
|
||||
- Multiple sequential operations
|
||||
|
||||
## Expected Output
|
||||
|
||||
```
|
||||
================================================
|
||||
STSAFE-A120 Test Suite for wolfSSL Integration
|
||||
================================================
|
||||
|
||||
Initializing STSAFE handler...
|
||||
STSAFE-A120 initialized successfully.
|
||||
|
||||
Test: Echo Command
|
||||
Echo response matches!
|
||||
[PASS] Echo command
|
||||
|
||||
Test: Random Number Generation
|
||||
Random data: A1 B2 C3 D4 ...
|
||||
[PASS] Random number generation
|
||||
|
||||
Test: ECC Key Generation (P-256)
|
||||
Public Key X: 12345678...
|
||||
Public Key Y: ABCDEF01...
|
||||
[PASS] ECC P-256 key generation
|
||||
|
||||
...
|
||||
|
||||
================================================
|
||||
Test Summary: 5 passed, 0 failed
|
||||
================================================
|
||||
```
|
||||
|
||||
## Performance Results (Raspberry Pi 5)
|
||||
|
||||
| Operation | Time | Throughput |
|
||||
|-----------|------|------------|
|
||||
| RNG (256 bytes) | <1 ms | ~9 MB/s |
|
||||
| ECC P-256 KeyGen | ~40 ms | 25 ops/sec |
|
||||
| ECDSA P-256 Sign | ~51 ms | 19.5 ops/sec |
|
||||
| ECDSA P-256 Verify | ~79 ms | 12.7 ops/sec |
|
||||
|
||||
## References
|
||||
|
||||
- [wolfSSL Documentation](https://www.wolfssl.com/docs/)
|
||||
- [STSELib GitHub](https://github.com/STMicroelectronics/STSELib)
|
||||
- [STSAFE-A120 Datasheet](https://www.st.com/en/secure-mcus/stsafe-a120.html)
|
||||
- [Raspberry Pi I2C Documentation](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#gpio-and-the-40-pin-header)
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/* stse_conf.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 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
|
||||
*/
|
||||
|
||||
#ifndef STSE_CONF_H
|
||||
#define STSE_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "stse_platform_generic.h"
|
||||
|
||||
/************************************************************
|
||||
* STSELIB DEVICE SUPPORT
|
||||
************************************************************/
|
||||
#define STSE_CONF_STSAFE_A_SUPPORT
|
||||
|
||||
/************************************************************
|
||||
* STSAFE-A API/SERVICE SETTINGS
|
||||
************************************************************/
|
||||
#ifdef STSE_CONF_STSAFE_A_SUPPORT
|
||||
|
||||
/* STSAFE-A ECC services configuration - enable P-256 and P-384 for wolfSSL */
|
||||
#define STSE_CONF_ECC_NIST_P_256
|
||||
#define STSE_CONF_ECC_NIST_P_384
|
||||
|
||||
/* STSAFE-A HASH services configuration */
|
||||
#define STSE_CONF_HASH_SHA_256
|
||||
#define STSE_CONF_HASH_SHA_384
|
||||
|
||||
/* STSAFE-A HOST KEY MANAGEMENT
|
||||
* Requires platform crypto implementation (stse_platform_crypto_wolfssl.c)
|
||||
* Enable this for encrypted host sessions with STSAFE
|
||||
*/
|
||||
#define STSE_CONF_USE_HOST_SESSION
|
||||
|
||||
/* Optional: Enable for additional key management features */
|
||||
/* #define STSE_CONF_USE_HOST_KEY_ESTABLISHMENT */
|
||||
/* #define STSE_CONF_USE_SYMMETRIC_KEY_ESTABLISHMENT */
|
||||
|
||||
#endif /* STSE_CONF_STSAFE_A_SUPPORT */
|
||||
|
||||
/*********************************************************
|
||||
* COMMUNICATION SETTINGS
|
||||
*********************************************************/
|
||||
#define STSE_USE_RSP_POLLING
|
||||
#define STSE_MAX_POLLING_RETRY 100
|
||||
#define STSE_FIRST_POLLING_INTERVAL 10
|
||||
#define STSE_POLLING_RETRY_INTERVAL 10
|
||||
|
||||
/* Enable debug logging */
|
||||
/* #define STSE_FRAME_DEBUG_LOG */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* STSE_CONF_H */
|
||||
|
|
@ -0,0 +1,916 @@
|
|||
/* stse_platform_crypto_wolfssl.c
|
||||
*
|
||||
* Copyright (C) 2006-2026 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
|
||||
*/
|
||||
|
||||
#include "core/stse_platform.h"
|
||||
#include "stse_conf.h"
|
||||
|
||||
/* wolfSSL includes */
|
||||
#ifdef WOLFSSL_USER_SETTINGS
|
||||
#include "user_settings.h"
|
||||
#endif
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
#include <wolfssl/wolfcrypt/aes.h>
|
||||
#include <wolfssl/wolfcrypt/cmac.h>
|
||||
#include <wolfssl/wolfcrypt/hmac.h>
|
||||
#include <wolfssl/wolfcrypt/sha256.h>
|
||||
#include <wolfssl/wolfcrypt/sha512.h>
|
||||
#include <wolfssl/wolfcrypt/hash.h>
|
||||
#include <wolfssl/wolfcrypt/ecc.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* ========================================================================== */
|
||||
/* Helper Macros */
|
||||
/* ========================================================================== */
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b) ? (a) : (b))
|
||||
#endif
|
||||
#define _MSB(x) ((((x)[0]&0x80)==0x80) ? 1 : 0)
|
||||
|
||||
#define ZERO_STRUCT(x) memset((void*)&(x), 0, sizeof(x))
|
||||
#define ZERO_STRUCTP(x) do { if ((x) != NULL) { memset((void*)(x), 0, sizeof(*(x)));} } while(0)
|
||||
|
||||
/* ========================================================================== */
|
||||
/* AES CMAC Constants (RFC 4493) */
|
||||
/* ========================================================================== */
|
||||
|
||||
static const uint8_t const_Rb[16] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
|
||||
};
|
||||
static const uint8_t const_Zero[16] = {0x00};
|
||||
|
||||
/* ========================================================================== */
|
||||
/* AES CMAC Context Structure */
|
||||
/* ========================================================================== */
|
||||
|
||||
typedef struct {
|
||||
Aes aes;
|
||||
uint8_t k1[16];
|
||||
uint8_t k2[16];
|
||||
uint8_t x[16];
|
||||
uint8_t last[16];
|
||||
size_t last_len;
|
||||
PLAT_UI16 exp_tag_size;
|
||||
} stse_cmac_ctx_t;
|
||||
|
||||
/* Global CMAC context for init/append/finish pattern */
|
||||
static stse_cmac_ctx_t* g_cmac_ctx = NULL;
|
||||
|
||||
/* ========================================================================== */
|
||||
/* Internal Helper Functions */
|
||||
/* ========================================================================== */
|
||||
|
||||
static inline void aes_cmac_left_shift_1(const uint8_t in[16], uint8_t out[16])
|
||||
{
|
||||
int8_t i;
|
||||
uint8_t overflow = 0;
|
||||
|
||||
for (i = 15; i >= 0; i--) {
|
||||
out[i] = in[i] << 1;
|
||||
out[i] |= overflow;
|
||||
overflow = _MSB(&in[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void aes_cmac_xor(const uint8_t in1[16], const uint8_t in2[16], uint8_t out[16])
|
||||
{
|
||||
int8_t i;
|
||||
for (i = 0; i < 16; i++) {
|
||||
out[i] = in1[i] ^ in2[i];
|
||||
}
|
||||
}
|
||||
|
||||
static int aes_cmac_generate_subkeys(Aes* aes, uint8_t k1[16], uint8_t k2[16])
|
||||
{
|
||||
uint8_t L[16];
|
||||
uint8_t tmp_block[16];
|
||||
uint8_t iv[16] = {0};
|
||||
int ret;
|
||||
|
||||
/* Generate L = AES-128(K, const_Zero) */
|
||||
ret = wc_AesSetIV(aes, iv);
|
||||
if (ret != 0) return ret;
|
||||
|
||||
ret = wc_AesCbcEncrypt(aes, L, const_Zero, 16);
|
||||
if (ret != 0) return ret;
|
||||
|
||||
/* Generate K1 */
|
||||
if (_MSB(L) == 0) {
|
||||
aes_cmac_left_shift_1(L, k1);
|
||||
} else {
|
||||
aes_cmac_left_shift_1(L, tmp_block);
|
||||
aes_cmac_xor(tmp_block, const_Rb, k1);
|
||||
}
|
||||
|
||||
/* Generate K2 */
|
||||
if (_MSB(k1) == 0) {
|
||||
aes_cmac_left_shift_1(k1, k2);
|
||||
} else {
|
||||
aes_cmac_left_shift_1(k1, tmp_block);
|
||||
aes_cmac_xor(tmp_block, const_Rb, k2);
|
||||
}
|
||||
|
||||
ZERO_STRUCT(L);
|
||||
ZERO_STRUCT(tmp_block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ========================================================================== */
|
||||
/* Platform Crypto Initialization */
|
||||
/* ========================================================================== */
|
||||
|
||||
stse_ReturnCode_t stse_platform_crypto_init(void)
|
||||
{
|
||||
/* wolfSSL library initialization if needed */
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
/* ========================================================================== */
|
||||
/* Hash Functions */
|
||||
/* ========================================================================== */
|
||||
|
||||
stse_ReturnCode_t stse_platform_hash_compute(stse_hash_algorithm_t hash_algo,
|
||||
PLAT_UI8 *pPayload, PLAT_UI16 payload_length,
|
||||
PLAT_UI8 *pHash, PLAT_UI16 *hash_length)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if (pPayload == NULL || pHash == NULL || hash_length == NULL) {
|
||||
return STSE_PLATFORM_HASH_ERROR;
|
||||
}
|
||||
|
||||
switch (hash_algo) {
|
||||
#ifdef STSE_CONF_HASH_SHA_256
|
||||
case STSE_SHA_256:
|
||||
if (*hash_length >= WC_SHA256_DIGEST_SIZE) {
|
||||
ret = wc_Sha256Hash(pPayload, payload_length, pHash);
|
||||
*hash_length = WC_SHA256_DIGEST_SIZE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef STSE_CONF_HASH_SHA_384
|
||||
case STSE_SHA_384:
|
||||
if (*hash_length >= WC_SHA384_DIGEST_SIZE) {
|
||||
ret = wc_Sha384Hash(pPayload, payload_length, pHash);
|
||||
*hash_length = WC_SHA384_DIGEST_SIZE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return STSE_PLATFORM_HASH_ERROR;
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
return STSE_PLATFORM_HASH_ERROR;
|
||||
}
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
/* ========================================================================== */
|
||||
/* ECC Verification Functions */
|
||||
/* ========================================================================== */
|
||||
|
||||
/**
|
||||
* \brief Get key size in bytes for a given STSE ECC key type
|
||||
*/
|
||||
static int stse_get_ecc_key_size(stse_ecc_key_type_t key_type)
|
||||
{
|
||||
switch (key_type) {
|
||||
#ifdef STSE_CONF_ECC_NIST_P_256
|
||||
case STSE_ECC_KT_NIST_P_256:
|
||||
return 32;
|
||||
#endif
|
||||
#ifdef STSE_CONF_ECC_BRAINPOOL_P_256
|
||||
case STSE_ECC_KT_BP_P_256:
|
||||
return 32;
|
||||
#endif
|
||||
#ifdef STSE_CONF_ECC_CURVE_25519
|
||||
case STSE_ECC_KT_CURVE25519:
|
||||
return 32;
|
||||
#endif
|
||||
#ifdef STSE_CONF_ECC_EDWARD_25519
|
||||
case STSE_ECC_KT_ED25519:
|
||||
return 32;
|
||||
#endif
|
||||
#ifdef STSE_CONF_ECC_NIST_P_384
|
||||
case STSE_ECC_KT_NIST_P_384:
|
||||
return 48;
|
||||
#endif
|
||||
#ifdef STSE_CONF_ECC_BRAINPOOL_P_384
|
||||
case STSE_ECC_KT_BP_P_384:
|
||||
return 48;
|
||||
#endif
|
||||
#ifdef STSE_CONF_ECC_BRAINPOOL_P_512
|
||||
case STSE_ECC_KT_BP_P_512:
|
||||
return 64;
|
||||
#endif
|
||||
#ifdef STSE_CONF_ECC_NIST_P_521
|
||||
case STSE_ECC_KT_NIST_P_521:
|
||||
return 66;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get wolfSSL curve ID for a given STSE ECC key type
|
||||
*/
|
||||
static int stse_get_wolfssl_curve_id(stse_ecc_key_type_t key_type)
|
||||
{
|
||||
switch (key_type) {
|
||||
#ifdef STSE_CONF_ECC_NIST_P_256
|
||||
case STSE_ECC_KT_NIST_P_256:
|
||||
return ECC_SECP256R1;
|
||||
#endif
|
||||
#ifdef STSE_CONF_ECC_NIST_P_384
|
||||
case STSE_ECC_KT_NIST_P_384:
|
||||
return ECC_SECP384R1;
|
||||
#endif
|
||||
#if defined(STSE_CONF_ECC_NIST_P_521) && defined(HAVE_ECC521)
|
||||
case STSE_ECC_KT_NIST_P_521:
|
||||
return ECC_SECP521R1;
|
||||
#endif
|
||||
#if defined(STSE_CONF_ECC_BRAINPOOL_P_256) && defined(HAVE_ECC_BRAINPOOL)
|
||||
case STSE_ECC_KT_BP_P_256:
|
||||
return ECC_BRAINPOOLP256R1;
|
||||
#endif
|
||||
#if defined(STSE_CONF_ECC_BRAINPOOL_P_384) && defined(HAVE_ECC_BRAINPOOL)
|
||||
case STSE_ECC_KT_BP_P_384:
|
||||
return ECC_BRAINPOOLP384R1;
|
||||
#endif
|
||||
#if defined(STSE_CONF_ECC_BRAINPOOL_P_512) && defined(HAVE_ECC_BRAINPOOL)
|
||||
case STSE_ECC_KT_BP_P_512:
|
||||
return ECC_BRAINPOOLP512R1;
|
||||
#endif
|
||||
#if defined(STSE_CONF_ECC_CURVE_25519) && defined(HAVE_CURVE25519)
|
||||
case STSE_ECC_KT_CURVE25519:
|
||||
return ECC_X25519;
|
||||
#endif
|
||||
#if defined(STSE_CONF_ECC_EDWARD_25519) && defined(HAVE_ED25519)
|
||||
case STSE_ECC_KT_ED25519:
|
||||
return ECC_ED25519;
|
||||
#endif
|
||||
default:
|
||||
return ECC_SECP256R1; /* Default to P-256 */
|
||||
}
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_ecc_verify(stse_ecc_key_type_t key_type,
|
||||
const PLAT_UI8 *pPubKey,
|
||||
PLAT_UI8 *pDigest,
|
||||
PLAT_UI16 digestLen,
|
||||
PLAT_UI8 *pSignature)
|
||||
{
|
||||
ecc_key eccKey;
|
||||
int ret;
|
||||
int verified = 0;
|
||||
int key_size;
|
||||
int curve_id;
|
||||
byte derSig[ECC_MAX_SIG_SIZE];
|
||||
word32 derSigLen = sizeof(derSig);
|
||||
|
||||
if (pPubKey == NULL || pDigest == NULL || pSignature == NULL) {
|
||||
return STSE_PLATFORM_ECC_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
key_size = stse_get_ecc_key_size(key_type);
|
||||
if (key_size == 0) {
|
||||
return STSE_PLATFORM_ECC_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
curve_id = stse_get_wolfssl_curve_id(key_type);
|
||||
|
||||
/* Initialize ECC key */
|
||||
ret = wc_ecc_init(&eccKey);
|
||||
if (ret != 0) {
|
||||
return STSE_PLATFORM_ECC_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
/* Import public key (X || Y format) */
|
||||
ret = wc_ecc_import_unsigned(&eccKey,
|
||||
(byte*)pPubKey, /* X coordinate */
|
||||
(byte*)(pPubKey + key_size), /* Y coordinate */
|
||||
NULL, /* No private key */
|
||||
curve_id);
|
||||
if (ret != 0) {
|
||||
wc_ecc_free(&eccKey);
|
||||
return STSE_PLATFORM_ECC_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
/* Convert R || S signature to DER format */
|
||||
ret = wc_ecc_rs_raw_to_sig(pSignature, key_size,
|
||||
pSignature + key_size, key_size,
|
||||
derSig, &derSigLen);
|
||||
if (ret != 0) {
|
||||
wc_ecc_free(&eccKey);
|
||||
return STSE_PLATFORM_ECC_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
/* Verify signature */
|
||||
ret = wc_ecc_verify_hash(derSig, derSigLen, pDigest, digestLen,
|
||||
&verified, &eccKey);
|
||||
|
||||
wc_ecc_free(&eccKey);
|
||||
|
||||
if (ret != 0 || verified != 1) {
|
||||
return STSE_PLATFORM_ECC_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
/* ========================================================================== */
|
||||
/* AES ECB Functions */
|
||||
/* ========================================================================== */
|
||||
|
||||
#if defined(STSE_CONF_USE_HOST_KEY_ESTABLISHMENT) || \
|
||||
defined(STSE_CONF_USE_SYMMETRIC_KEY_ESTABLISHMENT) || \
|
||||
defined(STSE_CONF_USE_HOST_SESSION)
|
||||
|
||||
stse_ReturnCode_t stse_platform_aes_ecb_enc(const PLAT_UI8 *pPlaintext,
|
||||
PLAT_UI16 plaintext_length,
|
||||
const PLAT_UI8 *pKey,
|
||||
PLAT_UI16 key_length,
|
||||
PLAT_UI8 *pEncryptedtext,
|
||||
PLAT_UI16 *pEncryptedtext_length)
|
||||
{
|
||||
Aes aes;
|
||||
int ret;
|
||||
PLAT_UI16 i;
|
||||
|
||||
if (pPlaintext == NULL || pKey == NULL || pEncryptedtext == NULL ||
|
||||
pEncryptedtext_length == NULL) {
|
||||
return STSE_PLATFORM_AES_ECB_ENCRYPT_ERROR;
|
||||
}
|
||||
|
||||
/* AES ECB requires block-aligned data */
|
||||
if ((plaintext_length % AES_BLOCK_SIZE) != 0) {
|
||||
return STSE_PLATFORM_AES_ECB_ENCRYPT_ERROR;
|
||||
}
|
||||
|
||||
ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
return STSE_PLATFORM_AES_ECB_ENCRYPT_ERROR;
|
||||
}
|
||||
|
||||
ret = wc_AesSetKey(&aes, pKey, key_length, NULL, AES_ENCRYPTION);
|
||||
if (ret != 0) {
|
||||
wc_AesFree(&aes);
|
||||
return STSE_PLATFORM_AES_ECB_ENCRYPT_ERROR;
|
||||
}
|
||||
|
||||
/* ECB mode: encrypt each block independently */
|
||||
for (i = 0; i < plaintext_length; i += AES_BLOCK_SIZE) {
|
||||
ret = wc_AesEncryptDirect(&aes, pEncryptedtext + i, pPlaintext + i);
|
||||
if (ret != 0) {
|
||||
wc_AesFree(&aes);
|
||||
return STSE_PLATFORM_AES_ECB_ENCRYPT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
*pEncryptedtext_length = plaintext_length;
|
||||
|
||||
wc_AesFree(&aes);
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
/* ========================================================================== */
|
||||
/* AES CBC Functions */
|
||||
/* ========================================================================== */
|
||||
|
||||
stse_ReturnCode_t stse_platform_aes_cbc_enc(const PLAT_UI8 *pPlaintext,
|
||||
PLAT_UI16 plaintext_length,
|
||||
PLAT_UI8 *pInitial_value,
|
||||
const PLAT_UI8 *pKey,
|
||||
PLAT_UI16 key_length,
|
||||
PLAT_UI8 *pEncryptedtext,
|
||||
PLAT_UI16 *pEncryptedtext_length)
|
||||
{
|
||||
Aes aes;
|
||||
int ret;
|
||||
|
||||
if (pPlaintext == NULL || pKey == NULL || pEncryptedtext == NULL ||
|
||||
pEncryptedtext_length == NULL || pInitial_value == NULL) {
|
||||
return STSE_PLATFORM_AES_CBC_ENCRYPT_ERROR;
|
||||
}
|
||||
|
||||
ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
return STSE_PLATFORM_AES_CBC_ENCRYPT_ERROR;
|
||||
}
|
||||
|
||||
ret = wc_AesSetKey(&aes, pKey, key_length, pInitial_value, AES_ENCRYPTION);
|
||||
if (ret != 0) {
|
||||
wc_AesFree(&aes);
|
||||
return STSE_PLATFORM_AES_CBC_ENCRYPT_ERROR;
|
||||
}
|
||||
|
||||
ret = wc_AesCbcEncrypt(&aes, pEncryptedtext, pPlaintext, plaintext_length);
|
||||
if (ret != 0) {
|
||||
wc_AesFree(&aes);
|
||||
return STSE_PLATFORM_AES_CBC_ENCRYPT_ERROR;
|
||||
}
|
||||
|
||||
*pEncryptedtext_length = plaintext_length;
|
||||
|
||||
wc_AesFree(&aes);
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_aes_cbc_dec(const PLAT_UI8 *pEncryptedtext,
|
||||
PLAT_UI16 encryptedtext_length,
|
||||
PLAT_UI8 *pInitial_value,
|
||||
const PLAT_UI8 *pKey,
|
||||
PLAT_UI16 key_length,
|
||||
PLAT_UI8 *pPlaintext,
|
||||
PLAT_UI16 *pPlaintext_length)
|
||||
{
|
||||
Aes aes;
|
||||
int ret;
|
||||
|
||||
if (pEncryptedtext == NULL || pKey == NULL || pPlaintext == NULL ||
|
||||
pPlaintext_length == NULL || pInitial_value == NULL) {
|
||||
return STSE_PLATFORM_AES_CBC_DECRYPT_ERROR;
|
||||
}
|
||||
|
||||
ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
return STSE_PLATFORM_AES_CBC_DECRYPT_ERROR;
|
||||
}
|
||||
|
||||
ret = wc_AesSetKey(&aes, pKey, key_length, pInitial_value, AES_DECRYPTION);
|
||||
if (ret != 0) {
|
||||
wc_AesFree(&aes);
|
||||
return STSE_PLATFORM_AES_CBC_DECRYPT_ERROR;
|
||||
}
|
||||
|
||||
ret = wc_AesCbcDecrypt(&aes, pPlaintext, pEncryptedtext, encryptedtext_length);
|
||||
if (ret != 0) {
|
||||
wc_AesFree(&aes);
|
||||
return STSE_PLATFORM_AES_CBC_DECRYPT_ERROR;
|
||||
}
|
||||
|
||||
*pPlaintext_length = encryptedtext_length;
|
||||
|
||||
wc_AesFree(&aes);
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
/* ========================================================================== */
|
||||
/* AES CMAC Functions */
|
||||
/* ========================================================================== */
|
||||
|
||||
stse_ReturnCode_t stse_platform_aes_cmac_init(const PLAT_UI8 *pKey,
|
||||
PLAT_UI16 key_length,
|
||||
PLAT_UI16 exp_tag_size)
|
||||
{
|
||||
int ret;
|
||||
uint8_t iv[16] = {0};
|
||||
|
||||
/* Free any existing context */
|
||||
if (g_cmac_ctx != NULL) {
|
||||
ZERO_STRUCTP(g_cmac_ctx);
|
||||
free(g_cmac_ctx);
|
||||
g_cmac_ctx = NULL;
|
||||
}
|
||||
|
||||
/* Allocate new context */
|
||||
g_cmac_ctx = (stse_cmac_ctx_t*)malloc(sizeof(stse_cmac_ctx_t));
|
||||
if (g_cmac_ctx == NULL) {
|
||||
return STSE_PLATFORM_AES_CMAC_COMPUTE_ERROR;
|
||||
}
|
||||
ZERO_STRUCTP(g_cmac_ctx);
|
||||
g_cmac_ctx->exp_tag_size = exp_tag_size;
|
||||
|
||||
/* Initialize AES context */
|
||||
ret = wc_AesInit(&g_cmac_ctx->aes, NULL, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
free(g_cmac_ctx);
|
||||
g_cmac_ctx = NULL;
|
||||
return STSE_PLATFORM_AES_CMAC_COMPUTE_ERROR;
|
||||
}
|
||||
|
||||
ret = wc_AesSetKey(&g_cmac_ctx->aes, pKey, key_length, iv, AES_ENCRYPTION);
|
||||
if (ret != 0) {
|
||||
wc_AesFree(&g_cmac_ctx->aes);
|
||||
free(g_cmac_ctx);
|
||||
g_cmac_ctx = NULL;
|
||||
return STSE_PLATFORM_AES_CMAC_COMPUTE_ERROR;
|
||||
}
|
||||
|
||||
/* Generate subkeys K1 and K2 */
|
||||
ret = aes_cmac_generate_subkeys(&g_cmac_ctx->aes, g_cmac_ctx->k1, g_cmac_ctx->k2);
|
||||
if (ret != 0) {
|
||||
wc_AesFree(&g_cmac_ctx->aes);
|
||||
free(g_cmac_ctx);
|
||||
g_cmac_ctx = NULL;
|
||||
return STSE_PLATFORM_AES_CMAC_COMPUTE_ERROR;
|
||||
}
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_aes_cmac_append(PLAT_UI8 *pInput, PLAT_UI16 length)
|
||||
{
|
||||
uint8_t iv[16] = {0};
|
||||
uint8_t tmp_block[16];
|
||||
uint8_t Y[16];
|
||||
int ret;
|
||||
|
||||
if (g_cmac_ctx == NULL) {
|
||||
return STSE_PLATFORM_AES_CMAC_COMPUTE_ERROR;
|
||||
}
|
||||
|
||||
if (pInput == NULL || length == 0) {
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
/* Copy the remembered last block */
|
||||
ZERO_STRUCT(tmp_block);
|
||||
if (g_cmac_ctx->last_len > 0) {
|
||||
memcpy(tmp_block, g_cmac_ctx->last, g_cmac_ctx->last_len);
|
||||
}
|
||||
|
||||
/* Check if we expand the block */
|
||||
if (g_cmac_ctx->last_len < 16) {
|
||||
size_t len = MIN(16 - g_cmac_ctx->last_len, length);
|
||||
memcpy(&tmp_block[g_cmac_ctx->last_len], pInput, len);
|
||||
memcpy(g_cmac_ctx->last, tmp_block, 16);
|
||||
pInput += len;
|
||||
length -= len;
|
||||
g_cmac_ctx->last_len += len;
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
/* Still the last block, we are done */
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
/* It is not the last block anymore */
|
||||
ZERO_STRUCT(g_cmac_ctx->last);
|
||||
g_cmac_ctx->last_len = 0;
|
||||
|
||||
/* Checksum everything but the last block */
|
||||
ret = wc_AesSetIV(&g_cmac_ctx->aes, iv);
|
||||
if (ret != 0) return STSE_PLATFORM_AES_CMAC_COMPUTE_ERROR;
|
||||
|
||||
aes_cmac_xor(g_cmac_ctx->x, tmp_block, Y);
|
||||
ret = wc_AesCbcEncrypt(&g_cmac_ctx->aes, g_cmac_ctx->x, Y, 16);
|
||||
if (ret != 0) return STSE_PLATFORM_AES_CMAC_COMPUTE_ERROR;
|
||||
|
||||
while (length > 16) {
|
||||
memcpy(tmp_block, pInput, 16);
|
||||
pInput += 16;
|
||||
length -= 16;
|
||||
|
||||
aes_cmac_xor(g_cmac_ctx->x, tmp_block, Y);
|
||||
ret = wc_AesSetIV(&g_cmac_ctx->aes, iv);
|
||||
if (ret != 0) return STSE_PLATFORM_AES_CMAC_COMPUTE_ERROR;
|
||||
ret = wc_AesCbcEncrypt(&g_cmac_ctx->aes, g_cmac_ctx->x, Y, 16);
|
||||
if (ret != 0) return STSE_PLATFORM_AES_CMAC_COMPUTE_ERROR;
|
||||
}
|
||||
|
||||
/* Copy the last block for processing in finish */
|
||||
memcpy(g_cmac_ctx->last, pInput, length);
|
||||
g_cmac_ctx->last_len = length;
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_aes_cmac_compute_finish(PLAT_UI8 *pTag, PLAT_UI8 *pTagLen)
|
||||
{
|
||||
uint8_t iv[16] = {0};
|
||||
uint8_t tmp_block[16];
|
||||
uint8_t Y[16];
|
||||
uint8_t out_mac[16];
|
||||
int ret;
|
||||
|
||||
if (g_cmac_ctx == NULL || pTag == NULL || pTagLen == NULL) {
|
||||
return STSE_PLATFORM_AES_CMAC_COMPUTE_ERROR;
|
||||
}
|
||||
|
||||
/* Final block processing */
|
||||
if (g_cmac_ctx->last_len < 16) {
|
||||
/* Incomplete block: pad and XOR with K2 */
|
||||
g_cmac_ctx->last[g_cmac_ctx->last_len] = 0x80;
|
||||
aes_cmac_xor(g_cmac_ctx->last, g_cmac_ctx->k2, tmp_block);
|
||||
} else {
|
||||
/* Complete block: XOR with K1 */
|
||||
aes_cmac_xor(g_cmac_ctx->last, g_cmac_ctx->k1, tmp_block);
|
||||
}
|
||||
|
||||
aes_cmac_xor(tmp_block, g_cmac_ctx->x, Y);
|
||||
ret = wc_AesSetIV(&g_cmac_ctx->aes, iv);
|
||||
if (ret != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
ret = wc_AesCbcEncrypt(&g_cmac_ctx->aes, out_mac, Y, 16);
|
||||
if (ret != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Copy requested tag length */
|
||||
*pTagLen = (PLAT_UI8)MIN(g_cmac_ctx->exp_tag_size, 16);
|
||||
memcpy(pTag, out_mac, *pTagLen);
|
||||
|
||||
cleanup:
|
||||
/* Clean up */
|
||||
wc_AesFree(&g_cmac_ctx->aes);
|
||||
ZERO_STRUCTP(g_cmac_ctx);
|
||||
free(g_cmac_ctx);
|
||||
g_cmac_ctx = NULL;
|
||||
|
||||
return (ret == 0) ? STSE_OK : STSE_PLATFORM_AES_CMAC_COMPUTE_ERROR;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_aes_cmac_verify_finish(PLAT_UI8 *pTag)
|
||||
{
|
||||
uint8_t computed_tag[16];
|
||||
PLAT_UI8 tag_len = 16;
|
||||
stse_ReturnCode_t ret;
|
||||
|
||||
if (pTag == NULL) {
|
||||
return STSE_PLATFORM_AES_CMAC_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
ret = stse_platform_aes_cmac_compute_finish(computed_tag, &tag_len);
|
||||
if (ret != STSE_OK) {
|
||||
return STSE_PLATFORM_AES_CMAC_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
/* Constant-time comparison */
|
||||
uint8_t diff = 0;
|
||||
for (int i = 0; i < tag_len; i++) {
|
||||
diff |= computed_tag[i] ^ pTag[i];
|
||||
}
|
||||
|
||||
ZERO_STRUCT(computed_tag);
|
||||
|
||||
if (diff != 0) {
|
||||
return STSE_PLATFORM_AES_CMAC_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_aes_cmac_compute(const PLAT_UI8 *pPayload,
|
||||
PLAT_UI16 payload_length,
|
||||
const PLAT_UI8 *pKey,
|
||||
PLAT_UI16 key_length,
|
||||
PLAT_UI16 exp_tag_size,
|
||||
PLAT_UI8 *pTag,
|
||||
PLAT_UI16 *pTag_length)
|
||||
{
|
||||
stse_ReturnCode_t ret;
|
||||
PLAT_UI8 tag_len;
|
||||
|
||||
ret = stse_platform_aes_cmac_init(pKey, key_length, exp_tag_size);
|
||||
if (ret != STSE_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = stse_platform_aes_cmac_append((PLAT_UI8*)pPayload, payload_length);
|
||||
if (ret != STSE_OK) {
|
||||
/* Clean up on error */
|
||||
if (g_cmac_ctx != NULL) {
|
||||
wc_AesFree(&g_cmac_ctx->aes);
|
||||
free(g_cmac_ctx);
|
||||
g_cmac_ctx = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = stse_platform_aes_cmac_compute_finish(pTag, &tag_len);
|
||||
if (ret == STSE_OK) {
|
||||
*pTag_length = tag_len;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_aes_cmac_verify(const PLAT_UI8 *pPayload,
|
||||
PLAT_UI16 payload_length,
|
||||
const PLAT_UI8 *pKey,
|
||||
PLAT_UI16 key_length,
|
||||
const PLAT_UI8 *pTag,
|
||||
PLAT_UI16 tag_length)
|
||||
{
|
||||
uint8_t computed_tag[16];
|
||||
PLAT_UI16 computed_len = 16;
|
||||
stse_ReturnCode_t ret;
|
||||
uint8_t diff = 0;
|
||||
|
||||
ret = stse_platform_aes_cmac_compute(pPayload, payload_length, pKey, key_length,
|
||||
tag_length, computed_tag, &computed_len);
|
||||
if (ret != STSE_OK) {
|
||||
return STSE_PLATFORM_AES_CMAC_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
/* Constant-time comparison */
|
||||
for (PLAT_UI16 i = 0; i < MIN(tag_length, computed_len); i++) {
|
||||
diff |= computed_tag[i] ^ pTag[i];
|
||||
}
|
||||
|
||||
ZERO_STRUCT(computed_tag);
|
||||
|
||||
if (diff != 0) {
|
||||
return STSE_PLATFORM_AES_CMAC_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
#endif /* STSE_CONF_USE_HOST_KEY_ESTABLISHMENT || STSE_CONF_USE_SYMMETRIC_KEY_ESTABLISHMENT || STSE_CONF_USE_HOST_SESSION */
|
||||
|
||||
/* ========================================================================== */
|
||||
/* HMAC-SHA256 Functions (RFC 5869 HKDF) */
|
||||
/* ========================================================================== */
|
||||
|
||||
stse_ReturnCode_t stse_platform_hmac_sha256_compute(PLAT_UI8 *pSalt, PLAT_UI16 salt_length,
|
||||
PLAT_UI8 *pInput_keying_material, PLAT_UI16 input_keying_material_length,
|
||||
PLAT_UI8 *pInfo, PLAT_UI16 info_length,
|
||||
PLAT_UI8 *pOutput_keying_material, PLAT_UI16 output_keying_material_length)
|
||||
{
|
||||
PLAT_UI8 prk[WC_SHA256_DIGEST_SIZE];
|
||||
stse_ReturnCode_t ret;
|
||||
|
||||
/* HKDF-Extract */
|
||||
ret = stse_platform_hmac_sha256_extract(pSalt, salt_length,
|
||||
pInput_keying_material, input_keying_material_length,
|
||||
prk, WC_SHA256_DIGEST_SIZE);
|
||||
if (ret != STSE_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* HKDF-Expand */
|
||||
ret = stse_platform_hmac_sha256_expand(prk, WC_SHA256_DIGEST_SIZE,
|
||||
pInfo, info_length,
|
||||
pOutput_keying_material, output_keying_material_length);
|
||||
|
||||
ZERO_STRUCT(prk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_hmac_sha256_extract(PLAT_UI8 *pSalt, PLAT_UI16 salt_length,
|
||||
PLAT_UI8 *pInput_keying_material, PLAT_UI16 input_keying_material_length,
|
||||
PLAT_UI8 *pPseudorandom_key, PLAT_UI16 pseudorandom_key_expected_length)
|
||||
{
|
||||
Hmac hmac;
|
||||
int ret;
|
||||
uint8_t default_salt[WC_SHA256_DIGEST_SIZE] = {0};
|
||||
|
||||
if (pInput_keying_material == NULL || pPseudorandom_key == NULL) {
|
||||
return STSE_PLATFORM_HKDF_ERROR;
|
||||
}
|
||||
|
||||
if (pseudorandom_key_expected_length < WC_SHA256_DIGEST_SIZE) {
|
||||
return STSE_PLATFORM_HKDF_ERROR;
|
||||
}
|
||||
|
||||
/* If salt is NULL or zero-length, use default salt of HashLen zeros */
|
||||
if (pSalt == NULL || salt_length == 0) {
|
||||
pSalt = default_salt;
|
||||
salt_length = WC_SHA256_DIGEST_SIZE;
|
||||
}
|
||||
|
||||
ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
return STSE_PLATFORM_HKDF_ERROR;
|
||||
}
|
||||
|
||||
/* PRK = HMAC-Hash(salt, IKM) */
|
||||
ret = wc_HmacSetKey(&hmac, WC_SHA256, pSalt, salt_length);
|
||||
if (ret != 0) {
|
||||
wc_HmacFree(&hmac);
|
||||
return STSE_PLATFORM_HKDF_ERROR;
|
||||
}
|
||||
|
||||
ret = wc_HmacUpdate(&hmac, pInput_keying_material, input_keying_material_length);
|
||||
if (ret != 0) {
|
||||
wc_HmacFree(&hmac);
|
||||
return STSE_PLATFORM_HKDF_ERROR;
|
||||
}
|
||||
|
||||
ret = wc_HmacFinal(&hmac, pPseudorandom_key);
|
||||
wc_HmacFree(&hmac);
|
||||
|
||||
if (ret != 0) {
|
||||
return STSE_PLATFORM_HKDF_ERROR;
|
||||
}
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_hmac_sha256_expand(PLAT_UI8 *pPseudorandom_key, PLAT_UI16 pseudorandom_key_length,
|
||||
PLAT_UI8 *pInfo, PLAT_UI16 info_length,
|
||||
PLAT_UI8 *pOutput_keying_material, PLAT_UI16 output_keying_material_length)
|
||||
{
|
||||
Hmac hmac;
|
||||
int ret;
|
||||
uint8_t T[WC_SHA256_DIGEST_SIZE];
|
||||
PLAT_UI16 T_len = 0;
|
||||
PLAT_UI16 out_index = 0;
|
||||
uint8_t counter = 1;
|
||||
PLAT_UI16 N;
|
||||
|
||||
if (pPseudorandom_key == NULL || pOutput_keying_material == NULL) {
|
||||
return STSE_PLATFORM_HKDF_ERROR;
|
||||
}
|
||||
|
||||
/* RFC 5869: L <= 255*HashLen */
|
||||
N = (output_keying_material_length + WC_SHA256_DIGEST_SIZE - 1) / WC_SHA256_DIGEST_SIZE;
|
||||
if (N > 255) {
|
||||
return STSE_PLATFORM_HKDF_ERROR;
|
||||
}
|
||||
|
||||
ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
return STSE_PLATFORM_HKDF_ERROR;
|
||||
}
|
||||
|
||||
while (out_index < output_keying_material_length) {
|
||||
PLAT_UI16 copy_len;
|
||||
|
||||
ret = wc_HmacSetKey(&hmac, WC_SHA256, pPseudorandom_key, pseudorandom_key_length);
|
||||
if (ret != 0) break;
|
||||
|
||||
/* T(i) = HMAC-Hash(PRK, T(i-1) | info | i) */
|
||||
if (T_len > 0) {
|
||||
ret = wc_HmacUpdate(&hmac, T, T_len);
|
||||
if (ret != 0) break;
|
||||
}
|
||||
|
||||
if (pInfo != NULL && info_length > 0) {
|
||||
ret = wc_HmacUpdate(&hmac, pInfo, info_length);
|
||||
if (ret != 0) break;
|
||||
}
|
||||
|
||||
ret = wc_HmacUpdate(&hmac, &counter, 1);
|
||||
if (ret != 0) break;
|
||||
|
||||
ret = wc_HmacFinal(&hmac, T);
|
||||
if (ret != 0) break;
|
||||
|
||||
/* Copy to output */
|
||||
copy_len = MIN(WC_SHA256_DIGEST_SIZE, output_keying_material_length - out_index);
|
||||
memcpy(pOutput_keying_material + out_index, T, copy_len);
|
||||
|
||||
T_len = WC_SHA256_DIGEST_SIZE;
|
||||
out_index += WC_SHA256_DIGEST_SIZE;
|
||||
counter++;
|
||||
}
|
||||
|
||||
wc_HmacFree(&hmac);
|
||||
ZERO_STRUCT(T);
|
||||
|
||||
if (ret != 0) {
|
||||
memset(pOutput_keying_material, 0, output_keying_material_length);
|
||||
return STSE_PLATFORM_HKDF_ERROR;
|
||||
}
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
/* ========================================================================== */
|
||||
/* NIST Key Wrap (Optional - stub for now) */
|
||||
/* ========================================================================== */
|
||||
|
||||
stse_ReturnCode_t stse_platform_nist_kw_encrypt(PLAT_UI8 *pPayload, PLAT_UI32 payload_length,
|
||||
PLAT_UI8 *pKey, PLAT_UI8 key_length,
|
||||
PLAT_UI8 *pOutput, PLAT_UI32 *pOutput_length)
|
||||
{
|
||||
(void)pPayload;
|
||||
(void)payload_length;
|
||||
(void)pKey;
|
||||
(void)key_length;
|
||||
(void)pOutput;
|
||||
(void)pOutput_length;
|
||||
|
||||
/* TODO: Implement using wc_AesKeyWrap if needed */
|
||||
return STSE_PLATFORM_AES_ECB_ENCRYPT_ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/******************************************************************************
|
||||
* \file stse_platform_generic.h
|
||||
* \brief STSecureElement platform types for Linux/Raspberry Pi
|
||||
* \author wolfSSL Inc.
|
||||
*
|
||||
******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* Copyright 2025 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef STSE_PLATFORM_GENERIC_H
|
||||
#define STSE_PLATFORM_GENERIC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Platform type definitions for Linux */
|
||||
#define PLAT_UI8 uint8_t
|
||||
#define PLAT_UI16 uint16_t
|
||||
#define PLAT_UI32 uint32_t
|
||||
#define PLAT_UI64 uint64_t
|
||||
#define PLAT_I8 int8_t
|
||||
#define PLAT_I16 int16_t
|
||||
#define PLAT_I32 int32_t
|
||||
#define PLAT_PACKED_STRUCT __attribute__((packed))
|
||||
|
||||
/* __WEAK attribute for overridable functions */
|
||||
#ifndef __WEAK
|
||||
#define __WEAK __attribute__((weak))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* STSE_PLATFORM_GENERIC_H */
|
||||
|
|
@ -0,0 +1,468 @@
|
|||
/******************************************************************************
|
||||
* \file stse_platform_linux.c
|
||||
* \brief STSecureElement platform implementation for Linux/Raspberry Pi
|
||||
* \author wolfSSL Inc.
|
||||
*
|
||||
******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* Copyright 2025 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "core/stse_platform.h"
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* I2C bus file descriptor */
|
||||
static int g_i2c_fd = -1;
|
||||
static uint8_t g_current_addr = 0;
|
||||
|
||||
/* I2C buffer for frame assembly */
|
||||
#define I2C_BUFFER_SIZE 755U
|
||||
static PLAT_UI8 I2c_tx_buffer[I2C_BUFFER_SIZE];
|
||||
static PLAT_UI8 I2c_rx_buffer[I2C_BUFFER_SIZE];
|
||||
static PLAT_UI16 i2c_tx_frame_size;
|
||||
static volatile PLAT_UI16 i2c_tx_frame_offset;
|
||||
static PLAT_UI16 i2c_rx_frame_size;
|
||||
static volatile PLAT_UI16 i2c_rx_frame_offset;
|
||||
|
||||
/* Timeout tracking */
|
||||
static struct timespec g_timeout_start;
|
||||
static PLAT_UI16 g_timeout_ms = 0;
|
||||
|
||||
/*--------------------- I2C Functions --------------------------- */
|
||||
|
||||
stse_ReturnCode_t stse_platform_i2c_init(PLAT_UI8 busID)
|
||||
{
|
||||
char i2c_path[20];
|
||||
|
||||
if (g_i2c_fd >= 0) {
|
||||
return STSE_OK; /* Already initialized */
|
||||
}
|
||||
|
||||
snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", busID);
|
||||
g_i2c_fd = open(i2c_path, O_RDWR);
|
||||
|
||||
if (g_i2c_fd < 0) {
|
||||
perror("Failed to open I2C bus");
|
||||
return STSE_PLATFORM_BUS_ERR;
|
||||
}
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_i2c_wake(PLAT_UI8 busID,
|
||||
PLAT_UI8 devAddr,
|
||||
PLAT_UI16 speed)
|
||||
{
|
||||
(void)speed;
|
||||
|
||||
if (g_i2c_fd < 0) {
|
||||
stse_ReturnCode_t ret = stse_platform_i2c_init(busID);
|
||||
if (ret != STSE_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set I2C slave address */
|
||||
if (ioctl(g_i2c_fd, I2C_SLAVE, devAddr) < 0) {
|
||||
return STSE_PLATFORM_BUS_ERR;
|
||||
}
|
||||
g_current_addr = devAddr;
|
||||
|
||||
/* Send wake-up byte (0x00) */
|
||||
uint8_t wake_byte = 0x00;
|
||||
write(g_i2c_fd, &wake_byte, 1);
|
||||
|
||||
/* Wait for device to wake up */
|
||||
usleep(5000); /* 5ms */
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_i2c_send_start(
|
||||
PLAT_UI8 busID,
|
||||
PLAT_UI8 devAddr,
|
||||
PLAT_UI16 speed,
|
||||
PLAT_UI16 FrameLength)
|
||||
{
|
||||
(void)busID;
|
||||
(void)devAddr;
|
||||
(void)speed;
|
||||
|
||||
if (FrameLength > I2C_BUFFER_SIZE) {
|
||||
return STSE_PLATFORM_BUFFER_ERR;
|
||||
}
|
||||
|
||||
i2c_tx_frame_size = FrameLength;
|
||||
i2c_tx_frame_offset = 0;
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_i2c_send_continue(
|
||||
PLAT_UI8 busID,
|
||||
PLAT_UI8 devAddr,
|
||||
PLAT_UI16 speed,
|
||||
PLAT_UI8 *pData,
|
||||
PLAT_UI16 data_size)
|
||||
{
|
||||
(void)busID;
|
||||
(void)devAddr;
|
||||
(void)speed;
|
||||
|
||||
if (data_size != 0) {
|
||||
if (pData == NULL) {
|
||||
memset((I2c_tx_buffer + i2c_tx_frame_offset), 0x00, data_size);
|
||||
} else {
|
||||
memcpy((I2c_tx_buffer + i2c_tx_frame_offset), pData, data_size);
|
||||
}
|
||||
i2c_tx_frame_offset += data_size;
|
||||
}
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_i2c_send_stop(
|
||||
PLAT_UI8 busID,
|
||||
PLAT_UI8 devAddr,
|
||||
PLAT_UI16 speed,
|
||||
PLAT_UI8 *pElement,
|
||||
PLAT_UI16 element_size)
|
||||
{
|
||||
(void)speed;
|
||||
|
||||
if (g_i2c_fd < 0) {
|
||||
stse_ReturnCode_t ret = stse_platform_i2c_init(busID);
|
||||
if (ret != STSE_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add final element if provided */
|
||||
if (pElement != NULL && element_size > 0) {
|
||||
memcpy((I2c_tx_buffer + i2c_tx_frame_offset), pElement, element_size);
|
||||
i2c_tx_frame_offset += element_size;
|
||||
}
|
||||
|
||||
/* Set I2C slave address if changed */
|
||||
if (g_current_addr != devAddr) {
|
||||
if (ioctl(g_i2c_fd, I2C_SLAVE, devAddr) < 0) {
|
||||
return STSE_PLATFORM_BUS_ERR;
|
||||
}
|
||||
g_current_addr = devAddr;
|
||||
}
|
||||
|
||||
/* Write the assembled frame */
|
||||
ssize_t written = write(g_i2c_fd, I2c_tx_buffer, i2c_tx_frame_offset);
|
||||
if (written != (ssize_t)i2c_tx_frame_offset) {
|
||||
return STSE_PLATFORM_BUS_ERR;
|
||||
}
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_i2c_send(
|
||||
PLAT_UI8 busID,
|
||||
PLAT_UI8 devAddr,
|
||||
PLAT_UI16 speed,
|
||||
PLAT_UI8 *pData,
|
||||
PLAT_UI16 data_size)
|
||||
{
|
||||
(void)speed;
|
||||
|
||||
if (g_i2c_fd < 0) {
|
||||
stse_ReturnCode_t ret = stse_platform_i2c_init(busID);
|
||||
if (ret != STSE_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set I2C slave address */
|
||||
if (g_current_addr != devAddr) {
|
||||
if (ioctl(g_i2c_fd, I2C_SLAVE, devAddr) < 0) {
|
||||
return STSE_PLATFORM_BUS_ERR;
|
||||
}
|
||||
g_current_addr = devAddr;
|
||||
}
|
||||
|
||||
ssize_t written = write(g_i2c_fd, pData, data_size);
|
||||
if (written != (ssize_t)data_size) {
|
||||
return STSE_PLATFORM_BUS_ERR;
|
||||
}
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_i2c_receive(
|
||||
PLAT_UI8 busID,
|
||||
PLAT_UI8 devAddr,
|
||||
PLAT_UI16 speed,
|
||||
PLAT_UI8 *pFrame_header,
|
||||
PLAT_UI8 *pFrame_payload,
|
||||
PLAT_UI16 *pFrame_payload_Length)
|
||||
{
|
||||
(void)speed;
|
||||
|
||||
if (g_i2c_fd < 0) {
|
||||
stse_ReturnCode_t ret = stse_platform_i2c_init(busID);
|
||||
if (ret != STSE_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set I2C slave address */
|
||||
if (g_current_addr != devAddr) {
|
||||
if (ioctl(g_i2c_fd, I2C_SLAVE, devAddr) < 0) {
|
||||
return STSE_PLATFORM_BUS_ERR;
|
||||
}
|
||||
g_current_addr = devAddr;
|
||||
}
|
||||
|
||||
/* Read header byte first */
|
||||
ssize_t rd = read(g_i2c_fd, pFrame_header, 1);
|
||||
if (rd != 1) {
|
||||
return STSE_PLATFORM_BUS_ERR;
|
||||
}
|
||||
|
||||
/* Read length (2 bytes) */
|
||||
PLAT_UI8 len_bytes[2];
|
||||
rd = read(g_i2c_fd, len_bytes, 2);
|
||||
if (rd != 2) {
|
||||
return STSE_PLATFORM_BUS_ERR;
|
||||
}
|
||||
|
||||
PLAT_UI16 payload_len = ((PLAT_UI16)len_bytes[0] << 8) | len_bytes[1];
|
||||
*pFrame_payload_Length = payload_len;
|
||||
|
||||
if (payload_len > 0 && pFrame_payload != NULL) {
|
||||
rd = read(g_i2c_fd, pFrame_payload, payload_len);
|
||||
if (rd != (ssize_t)payload_len) {
|
||||
return STSE_PLATFORM_BUS_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_i2c_receive_start(
|
||||
PLAT_UI8 busID,
|
||||
PLAT_UI8 devAddr,
|
||||
PLAT_UI16 speed,
|
||||
PLAT_UI16 frame_Length)
|
||||
{
|
||||
(void)speed;
|
||||
ssize_t rd;
|
||||
|
||||
if (frame_Length > I2C_BUFFER_SIZE) {
|
||||
return STSE_PLATFORM_BUFFER_ERR;
|
||||
}
|
||||
|
||||
if (g_i2c_fd < 0) {
|
||||
stse_ReturnCode_t ret = stse_platform_i2c_init(busID);
|
||||
if (ret != STSE_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_current_addr != devAddr) {
|
||||
if (ioctl(g_i2c_fd, I2C_SLAVE, devAddr) < 0) {
|
||||
return STSE_PLATFORM_BUS_ERR;
|
||||
}
|
||||
g_current_addr = devAddr;
|
||||
}
|
||||
|
||||
/* Read the full frame into buffer */
|
||||
rd = read(g_i2c_fd, I2c_rx_buffer, frame_Length);
|
||||
if (rd != (ssize_t)frame_Length) {
|
||||
return STSE_PLATFORM_BUS_ACK_ERROR;
|
||||
}
|
||||
|
||||
i2c_rx_frame_size = frame_Length;
|
||||
i2c_rx_frame_offset = 0;
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_i2c_receive_continue(
|
||||
PLAT_UI8 busID,
|
||||
PLAT_UI8 devAddr,
|
||||
PLAT_UI16 speed,
|
||||
PLAT_UI8 *pElement,
|
||||
PLAT_UI16 element_size)
|
||||
{
|
||||
(void)busID;
|
||||
(void)devAddr;
|
||||
(void)speed;
|
||||
|
||||
if (pElement != NULL && element_size > 0) {
|
||||
/* Check for buffer overflow */
|
||||
if ((i2c_rx_frame_size - i2c_rx_frame_offset) < element_size) {
|
||||
return STSE_PLATFORM_BUFFER_ERR;
|
||||
}
|
||||
|
||||
/* Copy from receive buffer */
|
||||
memcpy(pElement, (I2c_rx_buffer + i2c_rx_frame_offset), element_size);
|
||||
}
|
||||
|
||||
i2c_rx_frame_offset += element_size;
|
||||
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_i2c_receive_stop(
|
||||
PLAT_UI8 busID,
|
||||
PLAT_UI8 devAddr,
|
||||
PLAT_UI16 speed,
|
||||
PLAT_UI8 *pElement,
|
||||
PLAT_UI16 element_size)
|
||||
{
|
||||
stse_ReturnCode_t ret;
|
||||
|
||||
/* Copy last element */
|
||||
ret = stse_platform_i2c_receive_continue(busID, devAddr, speed, pElement, element_size);
|
||||
|
||||
i2c_rx_frame_offset = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*--------------------- Delay/Timeout Functions --------------------------- */
|
||||
|
||||
stse_ReturnCode_t stse_platform_delay_init(void)
|
||||
{
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
void stse_platform_Delay_ms(PLAT_UI32 delay_val)
|
||||
{
|
||||
usleep(delay_val * 1000);
|
||||
}
|
||||
|
||||
void stse_platform_timeout_ms_start(PLAT_UI16 timeout_val)
|
||||
{
|
||||
clock_gettime(CLOCK_MONOTONIC, &g_timeout_start);
|
||||
g_timeout_ms = timeout_val;
|
||||
}
|
||||
|
||||
PLAT_UI8 stse_platform_timeout_ms_get_status(void)
|
||||
{
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
long elapsed_ms = (now.tv_sec - g_timeout_start.tv_sec) * 1000 +
|
||||
(now.tv_nsec - g_timeout_start.tv_nsec) / 1000000;
|
||||
|
||||
return (elapsed_ms >= g_timeout_ms) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*--------------------- CRC Functions --------------------------- */
|
||||
|
||||
/* CRC-16-CCITT table (reflected/LSB-first) - matches STSAFE protocol */
|
||||
static const PLAT_UI16 crc16_tab[] = {
|
||||
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
|
||||
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
|
||||
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
|
||||
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
|
||||
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
|
||||
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
|
||||
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
|
||||
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
|
||||
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
|
||||
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
|
||||
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
|
||||
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
|
||||
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
|
||||
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
|
||||
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
|
||||
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
|
||||
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
|
||||
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
|
||||
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
|
||||
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
|
||||
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
|
||||
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
|
||||
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
|
||||
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
|
||||
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
|
||||
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
|
||||
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
|
||||
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
|
||||
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
|
||||
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
|
||||
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
|
||||
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
|
||||
};
|
||||
|
||||
static PLAT_UI16 g_crc_val = 0xFFFF;
|
||||
|
||||
stse_ReturnCode_t stse_platform_crc16_init(void)
|
||||
{
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
PLAT_UI16 stse_platform_Crc16_Calculate(PLAT_UI8 *pbuffer, PLAT_UI16 length)
|
||||
{
|
||||
PLAT_UI16 i;
|
||||
g_crc_val = 0xFFFF;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
g_crc_val = ((g_crc_val >> 8) ^ crc16_tab[(g_crc_val ^ pbuffer[i]) & 0x00FF]);
|
||||
}
|
||||
|
||||
return ~g_crc_val;
|
||||
}
|
||||
|
||||
PLAT_UI16 stse_platform_Crc16_Accumulate(PLAT_UI8 *pbuffer, PLAT_UI16 length)
|
||||
{
|
||||
PLAT_UI16 i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
g_crc_val = ((g_crc_val >> 8) ^ crc16_tab[(g_crc_val ^ pbuffer[i]) & 0x00FF]);
|
||||
}
|
||||
|
||||
return ~g_crc_val;
|
||||
}
|
||||
|
||||
/*--------------------- Power Functions --------------------------- */
|
||||
|
||||
stse_ReturnCode_t stse_platform_power_init(void)
|
||||
{
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_power_on(PLAT_UI8 busID, PLAT_UI8 devAddr)
|
||||
{
|
||||
(void)busID;
|
||||
(void)devAddr;
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
stse_ReturnCode_t stse_platform_power_off(PLAT_UI8 busID, PLAT_UI8 devAddr)
|
||||
{
|
||||
(void)busID;
|
||||
(void)devAddr;
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
/*--------------------- Random Functions --------------------------- */
|
||||
|
||||
stse_ReturnCode_t stse_platform_generate_random_init(void)
|
||||
{
|
||||
srand((unsigned int)time(NULL));
|
||||
return STSE_OK;
|
||||
}
|
||||
|
||||
PLAT_UI32 stse_platform_generate_random(void)
|
||||
{
|
||||
return (PLAT_UI32)rand();
|
||||
}
|
||||
|
|
@ -0,0 +1,308 @@
|
|||
/* stsafe_test.c
|
||||
*
|
||||
* Copyright (C) 2006-2026 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
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Include STSELib */
|
||||
#include "stselib.h"
|
||||
|
||||
/* STSAFE-A120 default I2C bus */
|
||||
#define STSAFE_A120_I2C_BUS 1
|
||||
|
||||
/* Test result tracking */
|
||||
static int tests_passed = 0;
|
||||
static int tests_failed = 0;
|
||||
|
||||
#define TEST_PASS(msg) do { printf("[PASS] %s\n", msg); tests_passed++; } while(0)
|
||||
#define TEST_FAIL(msg) do { printf("[FAIL] %s\n", msg); tests_failed++; } while(0)
|
||||
|
||||
/* STSAFE device handler */
|
||||
static stse_Handler_t stsafe_handler;
|
||||
|
||||
/*--------------------- Test: Echo Command --------------------------- */
|
||||
static int test_echo(void)
|
||||
{
|
||||
stse_ReturnCode_t ret;
|
||||
uint8_t echo_data[] = {0x01, 0x02, 0x03, 0x04, 0x05};
|
||||
uint8_t response[sizeof(echo_data)];
|
||||
|
||||
printf("\nTest: Echo Command\n");
|
||||
printf(" Sending %zu bytes...\n", sizeof(echo_data));
|
||||
|
||||
memset(response, 0, sizeof(response));
|
||||
ret = stse_device_echo(&stsafe_handler, echo_data, response, sizeof(echo_data));
|
||||
|
||||
if (ret != STSE_OK) {
|
||||
printf(" Error: stse_device_echo returned 0x%04X\n", ret);
|
||||
TEST_FAIL("Echo command failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(echo_data, response, sizeof(echo_data)) != 0) {
|
||||
printf(" Error: Response data mismatch\n");
|
||||
printf(" Expected: ");
|
||||
for (size_t i = 0; i < sizeof(echo_data); i++) printf("%02X ", echo_data[i]);
|
||||
printf("\n Got: ");
|
||||
for (size_t i = 0; i < sizeof(response); i++) printf("%02X ", response[i]);
|
||||
printf("\n");
|
||||
TEST_FAIL("Echo data mismatch");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Echo response matches!\n");
|
||||
TEST_PASS("Echo command");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*--------------------- Test: Random Number Generation --------------------------- */
|
||||
static int test_random(void)
|
||||
{
|
||||
stse_ReturnCode_t ret;
|
||||
uint8_t random_data[32];
|
||||
int all_zeros = 1;
|
||||
|
||||
printf("\nTest: Random Number Generation\n");
|
||||
printf(" Requesting 32 random bytes...\n");
|
||||
|
||||
memset(random_data, 0, sizeof(random_data));
|
||||
|
||||
ret = stse_generate_random(&stsafe_handler, random_data, sizeof(random_data));
|
||||
|
||||
if (ret != STSE_OK) {
|
||||
printf(" Error: stse_generate_random returned 0x%04X\n", ret);
|
||||
TEST_FAIL("Random generation failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check that data is not all zeros */
|
||||
for (size_t i = 0; i < sizeof(random_data); i++) {
|
||||
if (random_data[i] != 0) {
|
||||
all_zeros = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_zeros) {
|
||||
printf(" Error: Random data is all zeros\n");
|
||||
TEST_FAIL("Random data is all zeros");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Random data: ");
|
||||
for (size_t i = 0; i < 16; i++) {
|
||||
printf("%02X ", random_data[i]);
|
||||
}
|
||||
printf("...\n");
|
||||
|
||||
TEST_PASS("Random number generation");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*--------------------- Test: ECC Key Generation (P-256) --------------------------- */
|
||||
static int test_ecc_keygen_p256(void)
|
||||
{
|
||||
stse_ReturnCode_t ret;
|
||||
uint8_t public_key[64]; /* P-256 public key: 32 bytes X + 32 bytes Y */
|
||||
uint8_t slot = 1; /* Key slot 1 */
|
||||
stse_ecc_key_type_t key_type = STSE_ECC_KT_NIST_P_256;
|
||||
|
||||
printf("\nTest: ECC Key Generation (P-256)\n");
|
||||
|
||||
memset(public_key, 0, sizeof(public_key));
|
||||
|
||||
/* usage_limit = 255 for limited use */
|
||||
ret = stse_generate_ecc_key_pair(&stsafe_handler,
|
||||
slot,
|
||||
key_type,
|
||||
255, /* usage_limit */
|
||||
public_key);
|
||||
|
||||
if (ret != STSE_OK) {
|
||||
printf(" Error: stse_generate_ecc_key_pair returned 0x%04X\n", ret);
|
||||
TEST_FAIL("ECC P-256 key generation failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Public Key X: ");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
printf("%02X", public_key[i]);
|
||||
}
|
||||
printf("...\n");
|
||||
|
||||
printf(" Public Key Y: ");
|
||||
for (int i = 32; i < 40; i++) {
|
||||
printf("%02X", public_key[i]);
|
||||
}
|
||||
printf("...\n");
|
||||
|
||||
TEST_PASS("ECC P-256 key generation");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*--------------------- Test: ECDSA Sign (P-256) --------------------------- */
|
||||
static int test_ecdsa_sign_p256(void)
|
||||
{
|
||||
stse_ReturnCode_t ret;
|
||||
uint8_t digest[32]; /* SHA-256 digest */
|
||||
uint8_t signature[64]; /* P-256 signature: 32 bytes R + 32 bytes S */
|
||||
uint8_t public_key[64];
|
||||
uint8_t slot = 2; /* Key slot 2 for signing test */
|
||||
stse_ecc_key_type_t key_type = STSE_ECC_KT_NIST_P_256;
|
||||
|
||||
printf("\nTest: ECDSA Sign (P-256)\n");
|
||||
|
||||
/* Create a test digest */
|
||||
memset(digest, 0xAB, sizeof(digest));
|
||||
memset(signature, 0, sizeof(signature));
|
||||
memset(public_key, 0, sizeof(public_key));
|
||||
|
||||
/* First generate a key pair */
|
||||
ret = stse_generate_ecc_key_pair(&stsafe_handler,
|
||||
slot,
|
||||
key_type,
|
||||
255, /* usage_limit */
|
||||
public_key);
|
||||
if (ret != STSE_OK) {
|
||||
printf(" Error: Key generation failed with 0x%04X\n", ret);
|
||||
TEST_FAIL("ECDSA sign - key generation failed");
|
||||
return -1;
|
||||
}
|
||||
printf(" Key pair generated.\n");
|
||||
|
||||
/* Sign the digest */
|
||||
ret = stse_ecc_generate_signature(&stsafe_handler,
|
||||
slot,
|
||||
key_type,
|
||||
digest, sizeof(digest),
|
||||
signature);
|
||||
|
||||
if (ret != STSE_OK) {
|
||||
printf(" Error: stse_ecc_generate_signature returned 0x%04X\n", ret);
|
||||
TEST_FAIL("ECDSA P-256 sign failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Signature R: ");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
printf("%02X", signature[i]);
|
||||
}
|
||||
printf("...\n");
|
||||
|
||||
printf(" Signature S: ");
|
||||
for (int i = 32; i < 40; i++) {
|
||||
printf("%02X", signature[i]);
|
||||
}
|
||||
printf("...\n");
|
||||
|
||||
TEST_PASS("ECDSA P-256 sign");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*--------------------- Test: ECC Key Generation (P-384) --------------------------- */
|
||||
static int test_ecc_keygen_p384(void)
|
||||
{
|
||||
stse_ReturnCode_t ret;
|
||||
uint8_t public_key[96]; /* P-384 public key: 48 bytes X + 48 bytes Y */
|
||||
uint8_t slot = 3; /* Key slot 3 for P-384 */
|
||||
stse_ecc_key_type_t key_type = STSE_ECC_KT_NIST_P_384;
|
||||
|
||||
printf("\nTest: ECC Key Generation (P-384)\n");
|
||||
|
||||
memset(public_key, 0, sizeof(public_key));
|
||||
|
||||
ret = stse_generate_ecc_key_pair(&stsafe_handler,
|
||||
slot,
|
||||
key_type,
|
||||
255, /* usage_limit */
|
||||
public_key);
|
||||
|
||||
if (ret != STSE_OK) {
|
||||
printf(" Error: stse_generate_ecc_key_pair returned 0x%04X\n", ret);
|
||||
TEST_FAIL("ECC P-384 key generation failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Public Key X: ");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
printf("%02X", public_key[i]);
|
||||
}
|
||||
printf("...\n");
|
||||
|
||||
printf(" Public Key Y: ");
|
||||
for (int i = 48; i < 56; i++) {
|
||||
printf("%02X", public_key[i]);
|
||||
}
|
||||
printf("...\n");
|
||||
|
||||
TEST_PASS("ECC P-384 key generation");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*--------------------- Main --------------------------- */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
stse_ReturnCode_t ret;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
printf("================================================\n");
|
||||
printf("STSAFE-A120 Test Suite for wolfSSL Integration\n");
|
||||
printf("================================================\n");
|
||||
|
||||
/* Initialize STSAFE handler with defaults */
|
||||
printf("\nInitializing STSAFE handler...\n");
|
||||
ret = stse_set_default_handler_value(&stsafe_handler);
|
||||
if (ret != STSE_OK) {
|
||||
printf("Error: stse_set_default_handler_value failed: 0x%04X\n", ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Configure for STSAFE-A120 on I2C bus 1 */
|
||||
stsafe_handler.device_type = STSAFE_A120;
|
||||
stsafe_handler.io.busID = STSAFE_A120_I2C_BUS;
|
||||
stsafe_handler.io.BusSpeed = 100; /* 100 kHz for reliability */
|
||||
|
||||
printf("Initializing STSAFE-A120 device on I2C bus %d...\n", STSAFE_A120_I2C_BUS);
|
||||
ret = stse_init(&stsafe_handler);
|
||||
if (ret != STSE_OK) {
|
||||
printf("Error: stse_init failed: 0x%04X\n", ret);
|
||||
return 1;
|
||||
}
|
||||
printf("STSAFE-A120 initialized successfully.\n");
|
||||
|
||||
/* Run tests */
|
||||
test_echo();
|
||||
test_random();
|
||||
test_ecc_keygen_p256();
|
||||
test_ecdsa_sign_p256();
|
||||
test_ecc_keygen_p384();
|
||||
|
||||
/* Print summary */
|
||||
printf("\n================================================\n");
|
||||
printf("Test Summary: %d passed, %d failed\n", tests_passed, tests_failed);
|
||||
printf("================================================\n");
|
||||
|
||||
return (tests_failed > 0) ? 1 : 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/* user_settings.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 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
|
||||
*/
|
||||
|
||||
#ifndef USER_SETTINGS_H
|
||||
#define USER_SETTINGS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Platform Configuration */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
#define SIZEOF_LONG_LONG 8
|
||||
|
||||
/* Threading - single threaded for simple testing */
|
||||
/* #define SINGLE_THREADED */
|
||||
|
||||
/* Use /dev/urandom for random */
|
||||
/* #define NO_DEV_RANDOM */
|
||||
|
||||
#define NO_OLD_TLS
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Crypto Algorithms Required for STSAFE Platform */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* AES - Required for CMAC, CBC, ECB */
|
||||
#undef NO_AES
|
||||
#define WOLFSSL_AES_DIRECT /* Required for ECB mode */
|
||||
#define HAVE_AES_CBC /* Required for CBC mode */
|
||||
#define WOLFSSL_CMAC /* Required for AES-CMAC */
|
||||
|
||||
/* SHA-256 - Required for HMAC-SHA256 (HKDF) */
|
||||
#undef NO_SHA256
|
||||
|
||||
/* SHA-384 - For P-384 operations */
|
||||
#define WOLFSSL_SHA384
|
||||
|
||||
/* HMAC - Required for HKDF */
|
||||
#undef NO_HMAC
|
||||
|
||||
/* ECC - For wolfSSL STSAFE integration */
|
||||
#define HAVE_ECC
|
||||
#define ECC_USER_CURVES
|
||||
#undef NO_ECC256 /* Enable P-256 */
|
||||
#define HAVE_ECC384 /* Enable P-384 */
|
||||
#define ECC_TIMING_RESISTANT
|
||||
|
||||
/* ECC key import/export functions */
|
||||
#define WOLFSSL_PUBLIC_MP /* For mp_int access in ECC verify */
|
||||
|
||||
/* Math library */
|
||||
#define WOLFSSL_SP_MATH_ALL
|
||||
#define WOLFSSL_SP_384
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Disable Unused Algorithms (reduce footprint) */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
#define NO_RSA
|
||||
#define NO_DH
|
||||
#define NO_DSA
|
||||
#define NO_RC4
|
||||
#define NO_MD4
|
||||
#define NO_MD5
|
||||
#define NO_DES3
|
||||
#define NO_HC128
|
||||
#define NO_RABBIT
|
||||
#define NO_PWDBASED
|
||||
|
||||
/* Keep SHA-1 disabled unless needed */
|
||||
#define NO_SHA
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Optional Features */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Debugging */
|
||||
#define DEBUG_WOLFSSL
|
||||
|
||||
/* Error strings */
|
||||
#undef NO_ERROR_STRINGS
|
||||
|
||||
/* ASN.1 */
|
||||
#define WOLFSSL_ASN_TEMPLATE
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* STSAFE-A120 Integration */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Enable STSAFE-A120 support */
|
||||
#define WOLFSSL_STSAFEA120
|
||||
|
||||
/* Enable crypto callbacks for STSAFE hardware acceleration */
|
||||
#define WOLF_CRYPTO_CB
|
||||
|
||||
/* Use STSAFE for RNG seeding */
|
||||
#define USE_STSAFE_RNG_SEED
|
||||
|
||||
/* Include STSELib header path set in Makefile */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USER_SETTINGS_H */
|
||||
|
||||
|
|
@ -0,0 +1,477 @@
|
|||
/* wolfssl_stsafe_full_test.c
|
||||
*
|
||||
* Copyright (C) 2006-2026 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
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
/* wolfSSL headers */
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#include <wolfssl/wolfcrypt/ecc.h>
|
||||
#include <wolfssl/wolfcrypt/sha256.h>
|
||||
#include <wolfssl/wolfcrypt/cryptocb.h>
|
||||
#include <wolfssl/wolfcrypt/port/st/stsafe.h>
|
||||
|
||||
/* Test result macros */
|
||||
#define TEST_PASS(msg) do { printf("[PASS] %s\n", msg); g_passed++; } while(0)
|
||||
#define TEST_FAIL(msg) do { printf("[FAIL] %s\n", msg); g_failed++; } while(0)
|
||||
|
||||
static int g_passed = 0;
|
||||
static int g_failed = 0;
|
||||
|
||||
/* STSAFE crypto callback context */
|
||||
static wolfSTSAFE_CryptoCb_Ctx g_stsafe_ctx;
|
||||
static int g_devId = INVALID_DEVID;
|
||||
|
||||
/* Get time in microseconds */
|
||||
static double get_time_us(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (double)tv.tv_sec * 1000000.0 + (double)tv.tv_usec;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Test: RNG Performance
|
||||
*---------------------------------------------------------------------------*/
|
||||
static int test_rng_benchmark(void)
|
||||
{
|
||||
WC_RNG rng;
|
||||
byte rand_buf[256];
|
||||
int ret;
|
||||
int iterations = 100;
|
||||
double start, end, elapsed;
|
||||
int i;
|
||||
|
||||
printf("\nTest: RNG Benchmark (STSAFE-A120)\n");
|
||||
|
||||
ret = wc_InitRng_ex(&rng, NULL, g_devId);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_InitRng_ex failed: %d\n", ret);
|
||||
TEST_FAIL("RNG benchmark init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Warm up */
|
||||
wc_RNG_GenerateBlock(&rng, rand_buf, sizeof(rand_buf));
|
||||
|
||||
/* Benchmark */
|
||||
start = get_time_us();
|
||||
for (i = 0; i < iterations; i++) {
|
||||
ret = wc_RNG_GenerateBlock(&rng, rand_buf, sizeof(rand_buf));
|
||||
if (ret != 0) break;
|
||||
}
|
||||
end = get_time_us();
|
||||
elapsed = (end - start) / 1000.0; /* ms */
|
||||
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_RNG_GenerateBlock failed: %d\n", ret);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("RNG benchmark");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Generated %d x 256 bytes in %.2f ms\n", iterations, elapsed);
|
||||
printf(" Throughput: %.2f KB/s\n",
|
||||
(iterations * 256.0) / (elapsed / 1000.0) / 1024.0);
|
||||
|
||||
wc_FreeRng(&rng);
|
||||
TEST_PASS("RNG benchmark");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Test: ECDSA P-256 Benchmark
|
||||
*---------------------------------------------------------------------------*/
|
||||
static int test_ecdsa_p256_benchmark(void)
|
||||
{
|
||||
ecc_key key;
|
||||
WC_RNG rng;
|
||||
int ret;
|
||||
byte digest[32];
|
||||
byte sig[128];
|
||||
word32 sigLen;
|
||||
int verified = 0;
|
||||
int iterations = 10;
|
||||
double start, end, elapsed;
|
||||
int i;
|
||||
|
||||
printf("\nTest: ECDSA P-256 Benchmark (STSAFE-A120)\n");
|
||||
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_InitRng failed: %d\n", ret);
|
||||
TEST_FAIL("ECDSA P-256 benchmark RNG init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(digest, 0xAB, sizeof(digest));
|
||||
|
||||
ret = wc_ecc_init_ex(&key, NULL, g_devId);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_init_ex failed: %d\n", ret);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDSA P-256 benchmark key init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Benchmark key generation */
|
||||
start = get_time_us();
|
||||
ret = wc_ecc_make_key_ex(&rng, 32, &key, ECC_SECP256R1);
|
||||
end = get_time_us();
|
||||
elapsed = (end - start) / 1000.0;
|
||||
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_make_key_ex failed: %d\n", ret);
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDSA P-256 keygen");
|
||||
return -1;
|
||||
}
|
||||
printf(" Key generation: %.2f ms\n", elapsed);
|
||||
|
||||
/* Benchmark signing */
|
||||
start = get_time_us();
|
||||
for (i = 0; i < iterations; i++) {
|
||||
sigLen = sizeof(sig);
|
||||
ret = wc_ecc_sign_hash(digest, sizeof(digest), sig, &sigLen, &rng, &key);
|
||||
if (ret != 0) break;
|
||||
}
|
||||
end = get_time_us();
|
||||
elapsed = (end - start) / 1000.0;
|
||||
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_sign_hash failed: %d\n", ret);
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDSA P-256 sign");
|
||||
return -1;
|
||||
}
|
||||
printf(" Signing: %d ops in %.2f ms (%.2f ops/sec)\n",
|
||||
iterations, elapsed, iterations / (elapsed / 1000.0));
|
||||
|
||||
/* Benchmark verification */
|
||||
start = get_time_us();
|
||||
for (i = 0; i < iterations; i++) {
|
||||
ret = wc_ecc_verify_hash(sig, sigLen, digest, sizeof(digest), &verified, &key);
|
||||
if (ret != 0 || verified != 1) break;
|
||||
}
|
||||
end = get_time_us();
|
||||
elapsed = (end - start) / 1000.0;
|
||||
|
||||
if (ret != 0 || verified != 1) {
|
||||
printf(" Error: wc_ecc_verify_hash failed: %d, verified=%d\n", ret, verified);
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDSA P-256 verify");
|
||||
return -1;
|
||||
}
|
||||
printf(" Verification: %d ops in %.2f ms (%.2f ops/sec)\n",
|
||||
iterations, elapsed, iterations / (elapsed / 1000.0));
|
||||
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_PASS("ECDSA P-256 benchmark");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Test: ECDH Key Exchange
|
||||
* Note: STSAFE has a single key slot, so we generate one key in STSAFE
|
||||
* and one in software to test ECDH properly.
|
||||
*---------------------------------------------------------------------------*/
|
||||
static int test_ecdh_p256(void)
|
||||
{
|
||||
ecc_key keyHW; /* Hardware key in STSAFE */
|
||||
ecc_key keySW; /* Software key */
|
||||
WC_RNG rng;
|
||||
int ret;
|
||||
byte sharedHW[32], sharedSW[32];
|
||||
word32 sharedHWLen = sizeof(sharedHW), sharedSWLen = sizeof(sharedSW);
|
||||
double start, end;
|
||||
int i;
|
||||
|
||||
printf("\nTest: ECDH P-256 Key Exchange (HW + SW)\n");
|
||||
printf(" Note: STSAFE key used for one side, software for other\n");
|
||||
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_InitRng failed: %d\n", ret);
|
||||
TEST_FAIL("ECDH P-256 RNG init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize hardware key (with STSAFE devId) */
|
||||
ret = wc_ecc_init_ex(&keyHW, NULL, g_devId);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_init_ex (HW) failed: %d\n", ret);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDH P-256 key init HW");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize software key (INVALID_DEVID for software) */
|
||||
ret = wc_ecc_init_ex(&keySW, NULL, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_init_ex (SW) failed: %d\n", ret);
|
||||
wc_ecc_free(&keyHW);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDH P-256 key init SW");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generate hardware key pair (in STSAFE) */
|
||||
printf(" Generating hardware key pair (STSAFE)...\n");
|
||||
start = get_time_us();
|
||||
ret = wc_ecc_make_key_ex(&rng, 32, &keyHW, ECC_SECP256R1);
|
||||
end = get_time_us();
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_make_key_ex (HW) failed: %d\n", ret);
|
||||
wc_ecc_free(&keyHW);
|
||||
wc_ecc_free(&keySW);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDH P-256 keygen HW");
|
||||
return -1;
|
||||
}
|
||||
printf(" HW Key generated in %.2f ms\n", (end - start) / 1000.0);
|
||||
|
||||
/* Generate software key pair */
|
||||
printf(" Generating software key pair...\n");
|
||||
start = get_time_us();
|
||||
ret = wc_ecc_make_key_ex(&rng, 32, &keySW, ECC_SECP256R1);
|
||||
end = get_time_us();
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_make_key_ex (SW) failed: %d\n", ret);
|
||||
wc_ecc_free(&keyHW);
|
||||
wc_ecc_free(&keySW);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDH P-256 keygen SW");
|
||||
return -1;
|
||||
}
|
||||
printf(" SW Key generated in %.2f ms\n", (end - start) / 1000.0);
|
||||
|
||||
/* Compute shared secret using STSAFE (HW priv * SW pub) */
|
||||
printf(" Computing shared secret (STSAFE: HW priv * SW pub)...\n");
|
||||
start = get_time_us();
|
||||
ret = wc_ecc_shared_secret(&keyHW, &keySW, sharedHW, &sharedHWLen);
|
||||
end = get_time_us();
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_shared_secret (HW) failed: %d\n", ret);
|
||||
wc_ecc_free(&keyHW);
|
||||
wc_ecc_free(&keySW);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDH P-256 shared secret HW");
|
||||
return -1;
|
||||
}
|
||||
printf(" STSAFE ECDH computed in %.2f ms\n", (end - start) / 1000.0);
|
||||
|
||||
/* Compute shared secret using software (SW priv * HW pub) */
|
||||
printf(" Computing shared secret (Software: SW priv * HW pub)...\n");
|
||||
start = get_time_us();
|
||||
ret = wc_ecc_shared_secret(&keySW, &keyHW, sharedSW, &sharedSWLen);
|
||||
end = get_time_us();
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_shared_secret (SW) failed: %d\n", ret);
|
||||
wc_ecc_free(&keyHW);
|
||||
wc_ecc_free(&keySW);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDH P-256 shared secret SW");
|
||||
return -1;
|
||||
}
|
||||
printf(" Software ECDH computed in %.2f ms\n", (end - start) / 1000.0);
|
||||
|
||||
/* Compare shared secrets - they must match! */
|
||||
if (sharedHWLen != sharedSWLen || memcmp(sharedHW, sharedSW, sharedHWLen) != 0) {
|
||||
printf(" Error: Shared secrets don't match!\n");
|
||||
printf(" HW: ");
|
||||
for (i = 0; i < 8; i++) printf("%02X", sharedHW[i]);
|
||||
printf("...\n");
|
||||
printf(" SW: ");
|
||||
for (i = 0; i < 8; i++) printf("%02X", sharedSW[i]);
|
||||
printf("...\n");
|
||||
wc_ecc_free(&keyHW);
|
||||
wc_ecc_free(&keySW);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDH P-256 shared secret mismatch");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Shared secrets match! (");
|
||||
for (i = 0; i < 8; i++) printf("%02X", sharedHW[i]);
|
||||
printf("...)\n");
|
||||
|
||||
wc_ecc_free(&keyHW);
|
||||
wc_ecc_free(&keySW);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_PASS("ECDH P-256 key exchange (HW+SW)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Test: Multiple Key Slots
|
||||
*---------------------------------------------------------------------------*/
|
||||
static int test_multiple_operations(void)
|
||||
{
|
||||
ecc_key keys[3];
|
||||
WC_RNG rng;
|
||||
int ret;
|
||||
byte digest[32];
|
||||
byte sigs[3][128];
|
||||
word32 sigLens[3];
|
||||
int verified;
|
||||
int i;
|
||||
|
||||
printf("\nTest: Multiple Sequential Operations\n");
|
||||
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_InitRng failed: %d\n", ret);
|
||||
TEST_FAIL("Multiple ops RNG init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(digest, 0xCD, sizeof(digest));
|
||||
|
||||
/* Generate 3 key pairs and sign with each */
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = wc_ecc_init_ex(&keys[i], NULL, g_devId);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_init_ex[%d] failed: %d\n", i, ret);
|
||||
while (--i >= 0) wc_ecc_free(&keys[i]);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("Multiple ops key init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Generating key pair %d...\n", i + 1);
|
||||
ret = wc_ecc_make_key_ex(&rng, 32, &keys[i], ECC_SECP256R1);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_make_key_ex[%d] failed: %d\n", i, ret);
|
||||
for (int j = 0; j <= i; j++) wc_ecc_free(&keys[j]);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("Multiple ops keygen");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Sign with this key */
|
||||
sigLens[i] = sizeof(sigs[i]);
|
||||
ret = wc_ecc_sign_hash(digest, sizeof(digest), sigs[i], &sigLens[i], &rng, &keys[i]);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_sign_hash[%d] failed: %d\n", i, ret);
|
||||
for (int j = 0; j <= i; j++) wc_ecc_free(&keys[j]);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("Multiple ops sign");
|
||||
return -1;
|
||||
}
|
||||
printf(" Key %d: Generated and signed successfully\n", i + 1);
|
||||
}
|
||||
|
||||
/* Verify all signatures */
|
||||
printf(" Verifying all signatures...\n");
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = wc_ecc_verify_hash(sigs[i], sigLens[i], digest, sizeof(digest),
|
||||
&verified, &keys[i]);
|
||||
if (ret != 0 || verified != 1) {
|
||||
printf(" Error: Verification[%d] failed: ret=%d, verified=%d\n",
|
||||
i, ret, verified);
|
||||
for (int j = 0; j < 3; j++) wc_ecc_free(&keys[j]);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("Multiple ops verify");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
printf(" All 3 signatures verified!\n");
|
||||
|
||||
for (i = 0; i < 3; i++) wc_ecc_free(&keys[i]);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_PASS("Multiple sequential operations");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Main
|
||||
*---------------------------------------------------------------------------*/
|
||||
int main(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printf("================================================================\n");
|
||||
printf("wolfSSL STSAFE-A120 Full Integration Test Suite\n");
|
||||
printf("================================================================\n");
|
||||
|
||||
/* Initialize wolfCrypt */
|
||||
ret = wolfCrypt_Init();
|
||||
if (ret != 0) {
|
||||
printf("Error: wolfCrypt_Init failed: %d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize STSAFE interface */
|
||||
printf("\nInitializing STSAFE-A120...\n");
|
||||
ret = stsafe_interface_init();
|
||||
if (ret != 0) {
|
||||
printf("Error: stsafe_interface_init failed: %d\n", ret);
|
||||
wolfCrypt_Cleanup();
|
||||
return 1;
|
||||
}
|
||||
printf("STSAFE-A120 initialized successfully.\n");
|
||||
|
||||
/* Register STSAFE crypto callback */
|
||||
g_devId = 0x53545341; /* STSA */
|
||||
memset(&g_stsafe_ctx, 0, sizeof(g_stsafe_ctx));
|
||||
g_stsafe_ctx.devId = g_devId;
|
||||
|
||||
ret = wc_CryptoCb_RegisterDevice(g_devId, wolfSSL_STSAFE_CryptoDevCb,
|
||||
&g_stsafe_ctx);
|
||||
if (ret != 0) {
|
||||
printf("Error: wc_CryptoCb_RegisterDevice failed: %d\n", ret);
|
||||
wolfCrypt_Cleanup();
|
||||
return 1;
|
||||
}
|
||||
printf("STSAFE crypto callback registered (devId: 0x%08X).\n", g_devId);
|
||||
|
||||
/* Run tests */
|
||||
test_rng_benchmark();
|
||||
test_ecdsa_p256_benchmark();
|
||||
|
||||
/* Note: ECDH requires ephemeral keys via stse_generate_ECDHE_key_pair
|
||||
* which is not yet implemented in the crypto callback.
|
||||
* Skipping ECDH test for now. */
|
||||
printf("\n[SKIP] ECDH P-256 - requires ECDHE key generation (not yet implemented)\n");
|
||||
|
||||
test_multiple_operations();
|
||||
|
||||
/* Cleanup */
|
||||
wc_CryptoCb_UnRegisterDevice(g_devId);
|
||||
wolfCrypt_Cleanup();
|
||||
|
||||
printf("\n================================================================\n");
|
||||
printf("Test Summary: %d passed, %d failed\n", g_passed, g_failed);
|
||||
printf("================================================================\n");
|
||||
|
||||
return (g_failed > 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,445 @@
|
|||
/* wolfssl_stsafe_test.c
|
||||
*
|
||||
* Copyright (C) 2006-2026 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
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* wolfSSL headers */
|
||||
/* Must include options.h to match libwolfssl build settings */
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#include <wolfssl/wolfcrypt/ecc.h>
|
||||
#include <wolfssl/wolfcrypt/sha256.h>
|
||||
#include <wolfssl/wolfcrypt/cryptocb.h>
|
||||
#include <wolfssl/wolfcrypt/port/st/stsafe.h>
|
||||
|
||||
/* Test result macros */
|
||||
#define TEST_PASS(msg) do { printf("[PASS] %s\n", msg); g_passed++; } while(0)
|
||||
#define TEST_FAIL(msg) do { printf("[FAIL] %s\n", msg); g_failed++; } while(0)
|
||||
|
||||
static int g_passed = 0;
|
||||
static int g_failed = 0;
|
||||
|
||||
/* STSAFE crypto callback context */
|
||||
static wolfSTSAFE_CryptoCb_Ctx g_stsafe_ctx;
|
||||
static int g_devId = INVALID_DEVID;
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Test: RNG with STSAFE-A120
|
||||
*---------------------------------------------------------------------------*/
|
||||
static int test_rng(void)
|
||||
{
|
||||
WC_RNG rng;
|
||||
byte rand_buf[32];
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
printf("\nTest: RNG with STSAFE-A120\n");
|
||||
|
||||
ret = wc_InitRng_ex(&rng, NULL, g_devId);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_InitRng_ex failed: %d\n", ret);
|
||||
TEST_FAIL("RNG initialization");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generate random bytes */
|
||||
ret = wc_RNG_GenerateBlock(&rng, rand_buf, sizeof(rand_buf));
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_RNG_GenerateBlock failed: %d\n", ret);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("RNG generation");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Print random data */
|
||||
printf(" Random data: ");
|
||||
for (i = 0; i < 16; i++) {
|
||||
printf("%02X ", rand_buf[i]);
|
||||
}
|
||||
printf("...\n");
|
||||
|
||||
wc_FreeRng(&rng);
|
||||
TEST_PASS("RNG with STSAFE-A120");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Test: ECC P-256 Key Generation with STSAFE-A120
|
||||
*---------------------------------------------------------------------------*/
|
||||
static int test_ecc_keygen_p256(void)
|
||||
{
|
||||
ecc_key key;
|
||||
WC_RNG rng;
|
||||
int ret;
|
||||
byte pubX[32], pubY[32];
|
||||
word32 pubX_len = sizeof(pubX), pubY_len = sizeof(pubY);
|
||||
int i;
|
||||
|
||||
printf("\nTest: ECC P-256 Key Generation with STSAFE-A120\n");
|
||||
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_InitRng failed: %d\n", ret);
|
||||
TEST_FAIL("ECC P-256 RNG init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = wc_ecc_init_ex(&key, NULL, g_devId);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_init_ex failed: %d\n", ret);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECC P-256 init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generate P-256 key pair - should use STSAFE via crypto callback */
|
||||
ret = wc_ecc_make_key_ex(&rng, 32, &key, ECC_SECP256R1);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_make_key_ex failed: %d\n", ret);
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECC P-256 key generation");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Export public key */
|
||||
ret = wc_ecc_export_public_raw(&key, pubX, &pubX_len, pubY, &pubY_len);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_export_public_raw failed: %d\n", ret);
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECC P-256 export public key");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Public Key X: ");
|
||||
for (i = 0; i < 8; i++) printf("%02X", pubX[i]);
|
||||
printf("...\n");
|
||||
printf(" Public Key Y: ");
|
||||
for (i = 0; i < 8; i++) printf("%02X", pubY[i]);
|
||||
printf("...\n");
|
||||
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_PASS("ECC P-256 key generation");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Test: ECC P-384 Key Generation with STSAFE-A120
|
||||
*---------------------------------------------------------------------------*/
|
||||
static int test_ecc_keygen_p384(void)
|
||||
{
|
||||
ecc_key key;
|
||||
WC_RNG rng;
|
||||
int ret;
|
||||
byte pubX[48], pubY[48];
|
||||
word32 pubX_len = sizeof(pubX), pubY_len = sizeof(pubY);
|
||||
int i;
|
||||
|
||||
printf("\nTest: ECC P-384 Key Generation with STSAFE-A120\n");
|
||||
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_InitRng failed: %d\n", ret);
|
||||
TEST_FAIL("ECC P-384 RNG init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = wc_ecc_init_ex(&key, NULL, g_devId);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_init_ex failed: %d\n", ret);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECC P-384 init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generate P-384 key pair - should use STSAFE via crypto callback */
|
||||
ret = wc_ecc_make_key_ex(&rng, 48, &key, ECC_SECP384R1);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_make_key_ex failed: %d\n", ret);
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECC P-384 key generation");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Export public key */
|
||||
ret = wc_ecc_export_public_raw(&key, pubX, &pubX_len, pubY, &pubY_len);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_export_public_raw failed: %d\n", ret);
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECC P-384 export public key");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Public Key X: ");
|
||||
for (i = 0; i < 8; i++) printf("%02X", pubX[i]);
|
||||
printf("...\n");
|
||||
printf(" Public Key Y: ");
|
||||
for (i = 0; i < 8; i++) printf("%02X", pubY[i]);
|
||||
printf("...\n");
|
||||
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_PASS("ECC P-384 key generation");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Test: ECDSA Sign/Verify P-256 with STSAFE-A120
|
||||
*---------------------------------------------------------------------------*/
|
||||
static int test_ecdsa_p256(void)
|
||||
{
|
||||
ecc_key key;
|
||||
WC_RNG rng;
|
||||
int ret;
|
||||
byte digest[32];
|
||||
byte sig[128];
|
||||
word32 sigLen = sizeof(sig);
|
||||
int verified = 0;
|
||||
int i;
|
||||
|
||||
printf("\nTest: ECDSA P-256 Sign/Verify with STSAFE-A120\n");
|
||||
|
||||
/* Initialize RNG */
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_InitRng failed: %d\n", ret);
|
||||
TEST_FAIL("ECDSA P-256 RNG init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create test digest */
|
||||
memset(digest, 0xAB, sizeof(digest));
|
||||
|
||||
ret = wc_ecc_init_ex(&key, NULL, g_devId);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_init_ex failed: %d\n", ret);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDSA P-256 key init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generate key pair using STSAFE */
|
||||
ret = wc_ecc_make_key_ex(&rng, 32, &key, ECC_SECP256R1);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_make_key_ex failed: %d\n", ret);
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDSA P-256 key generation");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Key pair generated.\n");
|
||||
|
||||
/* Sign the digest using STSAFE */
|
||||
ret = wc_ecc_sign_hash(digest, sizeof(digest), sig, &sigLen, &rng, &key);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_sign_hash failed: %d\n", ret);
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDSA P-256 sign");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Signature (%d bytes): ", sigLen);
|
||||
for (i = 0; i < 8 && i < (int)sigLen; i++) printf("%02X", sig[i]);
|
||||
printf("...\n");
|
||||
|
||||
/* Verify the signature */
|
||||
ret = wc_ecc_verify_hash(sig, sigLen, digest, sizeof(digest), &verified, &key);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_verify_hash failed: %d\n", ret);
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDSA P-256 verify");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (verified != 1) {
|
||||
printf(" Error: Signature verification failed\n");
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDSA P-256 verification result");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Signature verified!\n");
|
||||
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_PASS("ECDSA P-256 sign/verify");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Test: ECDSA Sign/Verify P-384 with STSAFE-A120
|
||||
*---------------------------------------------------------------------------*/
|
||||
static int test_ecdsa_p384(void)
|
||||
{
|
||||
ecc_key key;
|
||||
WC_RNG rng;
|
||||
int ret;
|
||||
byte digest[48];
|
||||
byte sig[128];
|
||||
word32 sigLen = sizeof(sig);
|
||||
int verified = 0;
|
||||
int i;
|
||||
|
||||
printf("\nTest: ECDSA P-384 Sign/Verify with STSAFE-A120\n");
|
||||
|
||||
/* Initialize RNG */
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_InitRng failed: %d\n", ret);
|
||||
TEST_FAIL("ECDSA P-384 RNG init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create test digest */
|
||||
memset(digest, 0xCD, sizeof(digest));
|
||||
|
||||
ret = wc_ecc_init_ex(&key, NULL, g_devId);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_init_ex failed: %d\n", ret);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDSA P-384 key init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generate key pair using STSAFE */
|
||||
ret = wc_ecc_make_key_ex(&rng, 48, &key, ECC_SECP384R1);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_make_key_ex failed: %d\n", ret);
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDSA P-384 key generation");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Key pair generated.\n");
|
||||
|
||||
/* Sign the digest using STSAFE */
|
||||
ret = wc_ecc_sign_hash(digest, sizeof(digest), sig, &sigLen, &rng, &key);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_sign_hash failed: %d\n", ret);
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDSA P-384 sign");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Signature (%d bytes): ", sigLen);
|
||||
for (i = 0; i < 8 && i < (int)sigLen; i++) printf("%02X", sig[i]);
|
||||
printf("...\n");
|
||||
|
||||
/* Verify the signature */
|
||||
ret = wc_ecc_verify_hash(sig, sigLen, digest, sizeof(digest), &verified, &key);
|
||||
if (ret != 0) {
|
||||
printf(" Error: wc_ecc_verify_hash failed: %d\n", ret);
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDSA P-384 verify");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (verified != 1) {
|
||||
printf(" Error: Signature verification failed\n");
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_FAIL("ECDSA P-384 verification result");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" Signature verified!\n");
|
||||
|
||||
wc_ecc_free(&key);
|
||||
wc_FreeRng(&rng);
|
||||
TEST_PASS("ECDSA P-384 sign/verify");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Main
|
||||
*---------------------------------------------------------------------------*/
|
||||
int main(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printf("================================================\n");
|
||||
printf("wolfSSL STSAFE-A120 Crypto Callback Test Suite\n");
|
||||
printf("================================================\n");
|
||||
|
||||
/* Initialize wolfCrypt */
|
||||
ret = wolfCrypt_Init();
|
||||
if (ret != 0) {
|
||||
printf("Error: wolfCrypt_Init failed: %d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize STSAFE interface */
|
||||
printf("\nInitializing STSAFE-A120...\n");
|
||||
ret = stsafe_interface_init();
|
||||
if (ret != 0) {
|
||||
printf("Error: stsafe_interface_init failed: %d\n", ret);
|
||||
wolfCrypt_Cleanup();
|
||||
return 1;
|
||||
}
|
||||
printf("STSAFE-A120 initialized successfully.\n");
|
||||
|
||||
/* Register STSAFE crypto callback */
|
||||
g_devId = 0x53545341; /* STSA */
|
||||
memset(&g_stsafe_ctx, 0, sizeof(g_stsafe_ctx));
|
||||
g_stsafe_ctx.devId = g_devId;
|
||||
|
||||
ret = wc_CryptoCb_RegisterDevice(g_devId, wolfSSL_STSAFE_CryptoDevCb,
|
||||
&g_stsafe_ctx);
|
||||
if (ret != 0) {
|
||||
printf("Error: wc_CryptoCb_RegisterDevice failed: %d\n", ret);
|
||||
wolfCrypt_Cleanup();
|
||||
return 1;
|
||||
}
|
||||
printf("STSAFE crypto callback registered (devId: 0x%08X).\n", g_devId);
|
||||
|
||||
/* Run tests */
|
||||
test_rng();
|
||||
test_ecc_keygen_p256();
|
||||
test_ecc_keygen_p384();
|
||||
test_ecdsa_p256();
|
||||
test_ecdsa_p384();
|
||||
|
||||
/* Cleanup */
|
||||
wc_CryptoCb_UnRegisterDevice(g_devId);
|
||||
wolfCrypt_Cleanup();
|
||||
|
||||
printf("\n================================================\n");
|
||||
printf("Test Summary: %d passed, %d failed\n", g_passed, g_failed);
|
||||
printf("================================================\n");
|
||||
|
||||
return (g_failed > 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue