Update SCP03 tests with PlatformSCP03 integration tests and documentation
- Add PlatformSCP03 integration test cases (test_scp03_platform_integration, test_scp03_platform_key_file) - Update test helpers with mock session creation - Update README with PlatformSCP03 configuration guide - Add references to NXP AN12413 and AN12436 - Fix test assertions to work with opaque session type
This commit is contained in:
+204
@@ -0,0 +1,204 @@
|
||||
/**
|
||||
* @file se050_rng.c
|
||||
* @brief SE050 True Random Number Generator
|
||||
*
|
||||
* Clean-room implementation of SE050 TRNG interface.
|
||||
*
|
||||
* License: MIT (Clean-room implementation)
|
||||
*/
|
||||
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#include "se050_wireguard.h"
|
||||
#include "se050_crypto_utils.h"
|
||||
#include "se050_session_internal.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/**
|
||||
* @brief RNG context structure
|
||||
*/
|
||||
struct se050_rng_ctx {
|
||||
se050_session_ctx_t *session; /**< Associated session */
|
||||
uint32_t rng_counter; /**< RNG generation counter */
|
||||
uint8_t entropy_pool[64]; /**< Entropy pool for mixing */
|
||||
size_t entropy_len; /**< Current entropy pool size */
|
||||
};
|
||||
|
||||
/* ============================================================================
|
||||
* RNG Management
|
||||
* ============================================================================ */
|
||||
|
||||
se050_status_t se050_rng_init(se050_rng_ctx_t **ctx, se050_session_ctx_t *session)
|
||||
{
|
||||
se050_rng_ctx_t *rng;
|
||||
|
||||
if (!ctx || !session) {
|
||||
return SE050_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Allocate RNG context */
|
||||
rng = (se050_rng_ctx_t *)calloc(1, sizeof(*rng));
|
||||
if (!rng) {
|
||||
return SE050_ERR_FAIL;
|
||||
}
|
||||
|
||||
rng->session = session;
|
||||
rng->rng_counter = 0;
|
||||
rng->entropy_len = 0;
|
||||
|
||||
/* Zeroize entropy pool */
|
||||
memzero_explicit(rng->entropy_pool, sizeof(rng->entropy_pool));
|
||||
|
||||
*ctx = rng;
|
||||
return SE050_OK;
|
||||
}
|
||||
|
||||
void se050_rng_free(se050_rng_ctx_t *ctx)
|
||||
{
|
||||
if (!ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Securely zeroize entropy pool */
|
||||
if (ctx->entropy_len > 0) {
|
||||
memzero_explicit(ctx->entropy_pool, ctx->entropy_len);
|
||||
ctx->entropy_len = 0;
|
||||
}
|
||||
|
||||
/* Free RNG context */
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Random Number Generation
|
||||
* ============================================================================ */
|
||||
|
||||
se050_status_t se050_rng_generate(se050_rng_ctx_t *ctx, uint8_t *output, size_t length)
|
||||
{
|
||||
uint8_t cmd[64];
|
||||
uint8_t rsp[256];
|
||||
int ret;
|
||||
size_t cmd_len, rsp_len;
|
||||
size_t offset = 0;
|
||||
|
||||
if (!ctx || !output) {
|
||||
return SE050_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (length == 0 || length > sizeof(rsp) - 2) {
|
||||
return SE050_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
while (offset < length) {
|
||||
size_t chunk_len = length - offset;
|
||||
if (chunk_len > 240) {
|
||||
chunk_len = 240; /* Maximum chunk size */
|
||||
}
|
||||
|
||||
/* Build GET_RANDOM APDU */
|
||||
cmd[0] = 0x80; /* CLA */
|
||||
cmd[1] = 0xC0; /* INS - GET_RANDOM */
|
||||
cmd[2] = 0x00; /* P1 */
|
||||
cmd[3] = 0x00; /* P2 */
|
||||
cmd[4] = 0x00; /* LC */
|
||||
cmd[5] = (uint8_t)chunk_len; /* LE - requested length */
|
||||
|
||||
cmd_len = 6;
|
||||
|
||||
/* Send command */
|
||||
ret = se050_i2c_write(ctx->session->hal, cmd, (int)cmd_len);
|
||||
if (ret < 0) {
|
||||
return SE050_ERR_I2C;
|
||||
}
|
||||
|
||||
/* Receive response */
|
||||
rsp_len = sizeof(rsp);
|
||||
ret = se050_i2c_read(ctx->session->hal, rsp, (int)rsp_len);
|
||||
if (ret < 0) {
|
||||
return SE050_ERR_I2C;
|
||||
}
|
||||
rsp_len = (size_t)ret;
|
||||
|
||||
/* Check response status */
|
||||
if (rsp_len < 2) {
|
||||
return SE050_ERR_RNG;
|
||||
}
|
||||
|
||||
uint16_t sw = (uint16_t)((rsp[rsp_len - 2] << 8) | rsp[rsp_len - 1]);
|
||||
if (sw != 0x9000) {
|
||||
return SE050_ERR_RNG;
|
||||
}
|
||||
|
||||
/* Copy random data (excluding status word) */
|
||||
size_t data_len = rsp_len - 2;
|
||||
if (data_len > chunk_len) {
|
||||
data_len = chunk_len;
|
||||
}
|
||||
|
||||
memcpy(output + offset, rsp, data_len);
|
||||
offset += data_len;
|
||||
|
||||
/* Increment counter */
|
||||
ctx->rng_counter++;
|
||||
}
|
||||
|
||||
return SE050_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate random bytes using host crypto fallback
|
||||
* This is a fallback implementation if SE050 TRNG is not available.
|
||||
*/
|
||||
se050_status_t se050_rng_generate_fallback(uint8_t *output, size_t length)
|
||||
{
|
||||
#ifdef __linux__
|
||||
int fd;
|
||||
ssize_t ret;
|
||||
|
||||
/* Use /dev/urandom as fallback */
|
||||
fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return SE050_ERR_RNG;
|
||||
}
|
||||
|
||||
ret = read(fd, output, length);
|
||||
close(fd);
|
||||
|
||||
if (ret != (ssize_t)length) {
|
||||
return SE050_ERR_RNG;
|
||||
}
|
||||
|
||||
return SE050_OK;
|
||||
#else
|
||||
/* Simple LCG-based fallback (NOT SECURE - for testing only) */
|
||||
static uint32_t lcg_state = 0x12345678;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
lcg_state = lcg_state * 1103515245 + 12345;
|
||||
output[i] = (uint8_t)((lcg_state >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
return SE050_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate a random 32-byte key
|
||||
*/
|
||||
se050_status_t se050_rng_generate_key(se050_rng_ctx_t *ctx, uint8_t *key)
|
||||
{
|
||||
return se050_rng_generate(ctx, key, 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate a random nonce
|
||||
*/
|
||||
se050_status_t se050_rng_generate_nonce(se050_rng_ctx_t *ctx, uint8_t *nonce, size_t length)
|
||||
{
|
||||
return se050_rng_generate(ctx, nonce, length);
|
||||
}
|
||||
Reference in New Issue
Block a user