Changes needed for RSA key generation (#30)

Co-authored-by: neelimap <neelimaps@neominds.in>
Reviewed-on: http://13.234.246.121:3000/Neominds/ossl35vx69/pulls/30
Co-authored-by: Neelima P S <neelima.ps@neominds.in>
Co-committed-by: Neelima P S <neelima.ps@neominds.in>
This commit is contained in:
2026-07-30 19:55:54 +05:30
committed by neelimap
co-authored by neelimap
parent 0d0e6f73c4
commit 67cbb5af87
3 changed files with 281 additions and 4 deletions
@@ -708,6 +708,8 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
if (!CRYPTO_atomic_or(&optsdone, opts, &tmp, optsdone_lock))
return 0;
RAND_set_rand_method(RAND_OpenSSL());
return 1;
}
@@ -820,9 +822,7 @@ int ipcrypto_init_internal(SEM_ID semId)
{
init = 1;
#ifndef _WRS_CONFIG_OPENSSL_FIPSMODULE
RAND_set_rand_method(vxRandLibMeth());
#endif
OpenSSL_add_all_algorithms();
@@ -0,0 +1,228 @@
#include <vxWorks.h>
#include <sysLib.h>
#include <wdLib.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/rand.h>
#include "sysLib.h"
#define ENTROPY_SAMPLE_COUNT 64 /* Number of interrupt samples to collect */
#define ENTROPY_BUFFER_SIZE 32 /* Output entropy buffer size in bytes */
/* Structure to hold entropy collection state */
typedef struct {
UINT32 samples[ENTROPY_SAMPLE_COUNT];
int sample_index;
UINT32 last_tick;
WDOG_ID watchdog;
UINT8 entropy_pool[ENTROPY_BUFFER_SIZE];
int pool_filled;
} EntropyCollector;
/* Forward declarations */
static void entropyWatchdogCallback(void *arg);
/*******************************************************************************
* entropyWatchdogCallback - Callback function invoked at interrupt context
*
* This function runs in interrupt context (system tick interrupt). It samples
* the current system tick count and computes jitter as the delta between
* consecutive interrupts. VxWorks watchdogs execute in interrupt context,
* so this function must NOT:
* - Call any blocking functions
* - Use printf()
* - Use C++ objects with constructors/destructors
* - Use memory allocation (malloc/new)
*
* See: VxWorks Programmer's Guide - C++ limitations in interrupt context [citation:1][citation:2]
*******************************************************************************/
static void entropyWatchdogCallback(void *arg) {
EntropyCollector *collector = (EntropyCollector*)arg;
UINT32 current_tick;
UINT32 jitter;
if (collector == NULL) {
return;
}
/* Get current system tick count - high resolution timing source */
current_tick = sysTimestamp();
/* Calculate jitter as timing delta between successive interrupts */
if (collector->last_tick != 0) {
jitter = current_tick - collector->last_tick;
/* Store jitter sample if we haven't collected enough */
if (collector->sample_index < ENTROPY_SAMPLE_COUNT) {
collector->samples[collector->sample_index++] = jitter;
}
}
/* Update last tick for next measurement */
collector->last_tick = current_tick;
/*
* Reschedule watchdog for next interrupt (non-periodic to avoid
* predictable patterns - this actually increases entropy)
*/
if (collector->sample_index < ENTROPY_SAMPLE_COUNT) {
/* Randomize next delay using existing entropy for better jitter */
int next_delay = 1 + (collector->samples[collector->sample_index - 1] % 10);
wdStart(collector->watchdog, next_delay,
(FUNCPTR)entropyWatchdogCallback, (_Vx_usr_arg_t)collector);
}
}
/*******************************************************************************
* mixEntropyIntoPool - Mix collected jitter samples into entropy pool using
* a simple hash function (Jenkins one-at-a-time)
*
* This function runs in task context, NOT interrupt context.
*******************************************************************************/
static void mixEntropyIntoPool(EntropyCollector *collector) {
UINT32 hash = 0;
int i, j;
UINT8 *pool = collector->entropy_pool;
/* Mix all jitter samples into the entropy pool */
for (i = 0; i < ENTROPY_SAMPLE_COUNT && i < collector->sample_index; i++) {
UINT32 sample = collector->samples[i];
/* Jenkins one-at-a-time hash mixing */
for (j = 0; j < sizeof(UINT32); j++) {
hash += (sample >> (j * 8)) & 0xFF;
hash += (hash << 10);
hash ^= (hash >> 6);
}
/* XOR sample into pool at rotating position */
pool[i % ENTROPY_BUFFER_SIZE] ^= (sample & 0xFF);
pool[(i + 1) % ENTROPY_BUFFER_SIZE] ^= ((sample >> 8) & 0xFF);
pool[(i + 2) % ENTROPY_BUFFER_SIZE] ^= ((sample >> 16) & 0xFF);
pool[(i + 3) % ENTROPY_BUFFER_SIZE] ^= ((sample >> 24) & 0xFF);
}
/* Final mixing pass */
for (i = 0; i < ENTROPY_BUFFER_SIZE; i++) {
hash += pool[i];
hash += (hash << 10);
hash ^= (hash >> 6);
pool[i] ^= (hash & 0xFF);
}
/* Second mixing pass for avalanche effect */
for (i = ENTROPY_BUFFER_SIZE - 1; i >= 0; i--) {
hash += pool[i];
hash += (hash << 10);
hash ^= (hash >> 6);
pool[i] ^= (hash & 0xFF);
}
collector->pool_filled = 1;
}
/*******************************************************************************
* collectEntropyFromInterruptJitter - Main function to collect entropy
*
* This function creates a watchdog timer that samples interrupt jitter
* by exploiting timing variations in the system tick interrupt handler.
*
* Returns: Pointer to entropy buffer (32 bytes) on success, NULL on failure
*
* Usage example:
* UINT8 *entropy = collectEntropyFromInterruptJitter();
* if (entropy) {
* RAND_add(entropy, 32, 32.0); // Seed OpenSSL with 32 bytes of entropy
* free(entropy);
* }
*
* IMPORTANT: This function MUST be called from task context, NOT interrupt context.
* The watchdog callback runs in interrupt context, but the collection and mixing
* happen in the calling task's context.
*******************************************************************************/
UINT8* collectEntropyFromInterruptJitter(void) {
EntropyCollector *collector;
UINT8 *result = NULL;
/*neelimaps*/
sysTimestampEnable();
UINT32 tick;
unsigned long freq;
/* 2. Get the timestamp value */
tick = sysTimestamp();
/* 3. Print it - Note: %u for unsigned int */
printf("sysTimestamp = %u ticks in %s\n", tick, __func__);
/*neelimaps*/
/* Allocate collector structure (in task context - OK to use malloc) */
collector = (EntropyCollector*)malloc(sizeof(EntropyCollector));
if (collector == NULL) {
return NULL;
}
/* Initialize collector */
memset(collector, 0, sizeof(EntropyCollector));
collector->last_tick = 0;
collector->sample_index = 0;
collector->pool_filled = 0;
/* Create watchdog timer */
collector->watchdog = wdCreate();
if (collector->watchdog == NULL) {
free(collector);
return NULL;
}
/* Start the first watchdog - initial delay of 1 tick */
if (wdStart(collector->watchdog, 1,
(FUNCPTR)entropyWatchdogCallback,
(_Vx_usr_arg_t)collector) != OK) {
wdDelete(collector->watchdog);
free(collector);
return NULL;
}
/*
* Wait for entropy collection to complete.
* In a real implementation, you'd want to add a timeout.
*/
while (collector->sample_index < ENTROPY_SAMPLE_COUNT) {
taskDelay(1); /* Yield to let watchdog callbacks run */
}
/* Stop and delete watchdog */
wdCancel(collector->watchdog);
wdDelete(collector->watchdog);
/* Mix collected samples into entropy pool */
mixEntropyIntoPool(collector);
/* Allocate and copy result */
result = (UINT8*)malloc(ENTROPY_BUFFER_SIZE);
if (result) {
memcpy(result, collector->entropy_pool, ENTROPY_BUFFER_SIZE);
}
/* Cleanup */
free(collector);
return result;
}
void seedOpenSSLWithJitterEntropy(void) {
sysTimestampEnable();
UINT8 *entropy = collectEntropyFromInterruptJitter();
if (entropy) {
/* Add 32 bytes of entropy with estimated 256 bits of randomness */
RAND_add(entropy, ENTROPY_BUFFER_SIZE, ENTROPY_BUFFER_SIZE * 8.0);
free(entropy);
printf("OpenSSL RNG seeded with interrupt jitter entropy\n");
} else {
printf("Failed to collect entropy from interrupt jitter\n");
}
}
@@ -16,6 +16,9 @@
#include "prov/seeding.h"
#include <version.h>
#include <taskLib.h>
#include "sysLib.h"
extern unsigned char *collectEntropyFromInterruptJitter(void);
#if defined(OPENSSL_RAND_SEED_NONE)
/* none means none */
@@ -36,7 +39,7 @@
int randSecure (void)
{
return OK;
return 1;
}
STATUS randUBytes (unsigned char * randBuf, int numOfBytes)
@@ -121,6 +124,50 @@ int ossl_pool_add_nonce_data(RAND_POOL *pool)
size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
{
#ifdef VX69_TIMESTAMP_ENTROPY_SUPPORT
#if defined(OPENSSL_SYS_VXWORKS)
/* vxRandLib based entropy method */
size_t bytes_needed;
unsigned char *original_buffer;
bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
if (bytes_needed > 0) {
int retryCount = 0;
STATUS result = ERROR;
unsigned char *buffer;
buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
original_buffer = buffer;
size_t needed;
needed = bytes_needed;
while (needed) {
if (needed < 32) {
memcpy(buffer,collectEntropyFromInterruptJitter(),needed);
needed = 0;
}
else {
memcpy(buffer, collectEntropyFromInterruptJitter(),32);
needed -= 32;
buffer += 32;
}
}
}
ossl_rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
return ossl_rand_pool_entropy_available(pool);
#else
/*
* SEED_NONE means none, without randlib we dont have entropy and
* rely on it being added externally
*/
return ossl_rand_pool_entropy_available(pool);
#endif /* defined(RAND_SEED_VXRANDLIB) */
#else
#if defined(OPENSSL_SYS_VXWORKS)
/* vxRandLib based entropy method */
size_t bytes_needed;
@@ -165,4 +212,6 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
*/
return ossl_rand_pool_entropy_available(pool);
#endif /* defined(RAND_SEED_VXRANDLIB) */
#endif
}