From b1096e7c327e962715120d29f1e85fd3a3f5568d Mon Sep 17 00:00:00 2001 From: Paul Adelsbach Date: Tue, 17 Mar 2026 12:50:54 -0700 Subject: [PATCH] Extend minimal and rdseed examples --- .gitignore | 2 + crypto/aes/Makefile | 7 +- crypto/aes/aesgcm-file-encrypt-minimal.c | 206 +++++++++++++++++++++++ crypto/aes/aesgcm-minimal.c | 50 +----- crypto/aes/rdseed/Makefile | 14 ++ crypto/aes/rdseed/aesgcm-rdseed.c | 196 +++++++++++++++++++++ crypto/aes/rdseed/user_settings.h | 90 ++++++++++ 7 files changed, 515 insertions(+), 50 deletions(-) create mode 100644 crypto/aes/aesgcm-file-encrypt-minimal.c create mode 100644 crypto/aes/rdseed/Makefile create mode 100644 crypto/aes/rdseed/aesgcm-rdseed.c create mode 100644 crypto/aes/rdseed/user_settings.h diff --git a/.gitignore b/.gitignore index cf659be9..960aa45b 100644 --- a/.gitignore +++ b/.gitignore @@ -137,6 +137,8 @@ crypto/aes/aesctr-file-encrypt crypto/aes/aesgcm-file-encrypt crypto/aes/aesgcm-oneshot crypto/aes/aesgcm-minimal +crypto/aes/aesgcm-file-encrypt-minimal +crypto/aes/rdseed/aesgcm-rdseed crypto/camellia/camellia-encrypt crypto/pkcs12/pkcs12-create-example crypto/pkcs12/pkcs12-example diff --git a/crypto/aes/Makefile b/crypto/aes/Makefile index eb891f19..1036efaf 100644 --- a/crypto/aes/Makefile +++ b/crypto/aes/Makefile @@ -3,7 +3,7 @@ CFLAGS=-Wall WOLFSSL_INSTALL_DIR=/usr/local LIBS=-L$(WOLFSSL_INSTALL_DIR)/lib -lwolfssl -lm -all: aes-file-encrypt aescfb-file-encrypt aesctr-file-encrypt aesgcm-file-encrypt aesgcm-oneshot aesgcm-minimal +all: aes-file-encrypt aescfb-file-encrypt aesctr-file-encrypt aesgcm-file-encrypt aesgcm-file-encrypt-minimal aesgcm-oneshot aesgcm-minimal aes-file-encrypt: aes-file-encrypt.o $(CC) -o $@ $^ $(CFLAGS) $(LIBS) @@ -23,7 +23,10 @@ aesgcm-oneshot: aesgcm-oneshot.o aesgcm-minimal: aesgcm-minimal.o $(CC) -o $@ $^ $(CFLAGS) $(LIBS) +aesgcm-file-encrypt-minimal: aesgcm-file-encrypt-minimal.o + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + .PHONY: clean clean: - rm -f *.o aes-file-encrypt aescfb-file-encrypt aesctr-file-encrypt aesgcm-file-encrypt text* aesgcm-oneshot aesgcm-minimal + rm -f *.o aes-file-encrypt aescfb-file-encrypt aesctr-file-encrypt aesgcm-file-encrypt aesgcm-file-encrypt-minimal text* aesgcm-oneshot aesgcm-minimal diff --git a/crypto/aes/aesgcm-file-encrypt-minimal.c b/crypto/aes/aesgcm-file-encrypt-minimal.c new file mode 100644 index 00000000..3a4c437a --- /dev/null +++ b/crypto/aes/aesgcm-file-encrypt-minimal.c @@ -0,0 +1,206 @@ +/* aesgcm-file-encrypt-minimal.c + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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-1335, USA + */ + +#ifndef WOLFSSL_USER_SETTINGS + #include +#endif +#include +#include + +#include +#include +#include + +#define KEY_SZ AES_256_KEY_SIZE +#define NONCE_SZ GCM_NONCE_MID_SZ +#define TAG_SZ AES_BLOCK_SIZE + +static int GenerateKeyAndIv(byte* key, byte* iv) +{ + WC_RNG rng; + int ret; + + ret = wc_InitRng(&rng); + if (ret != 0) { + return ret; + } + + ret = wc_RNG_GenerateBlock(&rng, key, KEY_SZ); + if (ret == 0) { + ret = wc_RNG_GenerateBlock(&rng, iv, NONCE_SZ); + } + wc_FreeRng(&rng); + return ret; +} + +static int Encrypt(const byte* key, const byte* iv, const byte* plaintext, + word32 plaintextSz, byte* ciphertext, byte* tag) +{ + int ret; + Aes aes; + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key, KEY_SZ); + } + if (ret == 0) { + ret = wc_AesGcmEncrypt(&aes, ciphertext, plaintext, plaintextSz, iv, + NONCE_SZ, tag, TAG_SZ, NULL, 0); + } + wc_AesFree(&aes); + return ret; +} + +static int ReadFile(const char* path, byte** data, long* sz) +{ + FILE* file; + long fileSz; + byte* buf; + + *data = NULL; + *sz = 0; + + file = fopen(path, "rb"); + if (file == NULL) { + return -1; + } + + if (fseek(file, 0, SEEK_END) != 0) { + fclose(file); + return -1; + } + fileSz = ftell(file); + if (fileSz < 0) { + fclose(file); + return -1; + } + if (fseek(file, 0, SEEK_SET) != 0) { + fclose(file); + return -1; + } + + buf = (byte*)malloc((size_t)fileSz); + if (buf == NULL && fileSz != 0) { + fclose(file); + return -1; + } + + if (fileSz != 0 && fread(buf, 1, (size_t)fileSz, file) != (size_t)fileSz) { + free(buf); + fclose(file); + return -1; + } + + fclose(file); + *data = buf; + *sz = fileSz; + return 0; +} + +static int WriteFile(const char* path, const byte* iv, const byte* tag, + const byte* ciphertext, long ciphertextSz) +{ + FILE* file; + + file = fopen(path, "wb"); + if (file == NULL) { + return -1; + } + + if (fwrite(iv, 1, NONCE_SZ, file) != NONCE_SZ || + fwrite(tag, 1, TAG_SZ, file) != TAG_SZ || + (ciphertextSz != 0 && + fwrite(ciphertext, 1, (size_t)ciphertextSz, file) != + (size_t)ciphertextSz)) { + fclose(file); + return -1; + } + + fclose(file); + return 0; +} + +static void print_hex(const char* label, const byte* data, word32 sz) +{ + int i; + printf("%s: ", label); + for (i = 0; i < sz; i++) { + printf("%02x", data[i]); + } + printf("\n"); +} + +int main(int argc, char** argv) +{ + byte key[KEY_SZ]; + byte iv[NONCE_SZ]; + byte tag[TAG_SZ]; + byte* plaintext = NULL; + byte* ciphertext = NULL; + long plaintextSz = 0; + int ret = 1; + + if (argc != 3) { + printf("Usage: %s \n", argv[0]); + return 1; + } + + if (ReadFile(argv[1], &plaintext, &plaintextSz) != 0) { + printf("Failed to read input file: %s\n", argv[1]); + return 1; + } + + ciphertext = (byte*)malloc((size_t)plaintextSz); + if (ciphertext == NULL && plaintextSz != 0) { + printf("Failed to allocate ciphertext buffer\n"); + goto exit; + } + + ret = GenerateKeyAndIv(key, iv); + if (ret != 0) { + printf("Key/IV generation failed: %d\n", ret); + goto exit; + } + + ret = Encrypt(key, iv, plaintext, (word32)plaintextSz, ciphertext, tag); + if (ret != 0) { + printf("Encryption failed: %d\n", ret); + goto exit; + } + + if (WriteFile(argv[2], iv, tag, ciphertext, plaintextSz) != 0) { + printf("Failed to write output file: %s\n", argv[2]); + ret = 1; + goto exit; + } + + print_hex("Key", key, sizeof(key)); + print_hex("IV", iv, sizeof(iv)); + print_hex("Tag", tag, sizeof(tag)); + printf("Wrote %ld bytes of ciphertext to %s\n", plaintextSz, argv[2]); + printf("Output format: IV || TAG || ciphertext\n"); + ret = 0; + +exit: + free(ciphertext); + free(plaintext); + return ret; +} diff --git a/crypto/aes/aesgcm-minimal.c b/crypto/aes/aesgcm-minimal.c index 311fee10..7c2b3431 100644 --- a/crypto/aes/aesgcm-minimal.c +++ b/crypto/aes/aesgcm-minimal.c @@ -23,7 +23,6 @@ #include #endif #include -#include #include #include @@ -33,58 +32,12 @@ #define NONCE_SZ GCM_NONCE_MID_SZ #define TAG_SZ AES_BLOCK_SIZE -/* Optional setup path: seed wolfSSL RNG via RDSEED when available. */ -#if defined(__x86_64__) - #define RDSEED_ENABLED 1 -#endif - -#if defined(WC_RNG_SEED_CB) && defined(RDSEED_ENABLED) -#include - -/* wc_RngSeed_Cb: feed wolfSSL DRBG seed using RDSEED. */ -__attribute__((target("rdseed"))) -static int RdseedSeedCb(OS_Seed* os, byte* seed, word32 sz) -{ - word32 i = 0; - (void)os; - - while (i < sz) { - unsigned long long v = 0; - int ok = 0; - int tries; - word32 n; - - for (tries = 0; tries < 16; tries++) { - if (_rdseed64_step(&v)) { - ok = 1; - break; - } - } - if (!ok) { - return RNG_FAILURE_E; - } - - n = (sz - i < (word32)sizeof(v)) ? (sz - i) : (word32)sizeof(v); - memcpy(seed + i, &v, n); - i += n; - } - return 0; -} -#endif - static int GenerateKeyAndIv(byte* key, byte* iv) { WC_RNG rng; int ret; - /* Setup: initialize RNG and (optionally) override seed source. */ -#if defined(WC_RNG_SEED_CB) && defined(RDSEED_ENABLED) - wc_SetSeed_Cb(RdseedSeedCb); ret = wc_InitRng(&rng); - wc_SetSeed_Cb(NULL); -#else - ret = wc_InitRng(&rng); -#endif if (ret != 0) { return ret; } @@ -137,8 +90,9 @@ static int Decrypt(const byte* key, const byte* iv, const byte* ciphertext, void print_hex(const char* label, const byte* data, word32 sz) { + int i; printf("%s: ", label); - for (word32 i = 0; i < sz; i++) { + for (i = 0; i < sz; i++) { printf("%02x", data[i]); } printf("\n"); diff --git a/crypto/aes/rdseed/Makefile b/crypto/aes/rdseed/Makefile new file mode 100644 index 00000000..5c362ec8 --- /dev/null +++ b/crypto/aes/rdseed/Makefile @@ -0,0 +1,14 @@ +CC=gcc +CFLAGS=-Wall -DWOLFSSL_USER_SETTINGS -I. +WOLFSSL_INSTALL_DIR=/usr/local +LIBS=-L$(WOLFSSL_INSTALL_DIR)/lib -lwolfssl -lm + +all: aesgcm-rdseed + +aesgcm-rdseed: aesgcm-rdseed.o + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + +.PHONY: clean + +clean: + rm -f *.o aesgcm-rdseed diff --git a/crypto/aes/rdseed/aesgcm-rdseed.c b/crypto/aes/rdseed/aesgcm-rdseed.c new file mode 100644 index 00000000..2a692cd1 --- /dev/null +++ b/crypto/aes/rdseed/aesgcm-rdseed.c @@ -0,0 +1,196 @@ +/* aesgcm-rdseed.c + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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-1335, USA + */ + +#ifndef WOLFSSL_USER_SETTINGS + #include +#endif +#include +#include +#include + +#include +#include + +/* ------------------------------------------------------------------------- */ +/* I/O: redirect XPRINTF to stdio when available */ +/* ------------------------------------------------------------------------- */ +#ifndef XPRINTF + #include + #define XPRINTF printf +#endif + +#if defined(__x86_64__) && defined(WC_RNG_SEED_CB) +#include + +#define KEY_SZ AES_256_KEY_SIZE +#define NONCE_SZ GCM_NONCE_MID_SZ +#define TAG_SZ AES_BLOCK_SIZE + +/* Feed wolfSSL DRBG seed material using the RDSEED instruction. */ +__attribute__((target("rdseed"))) /* GCC style, build with -mrdseed + if not available */ +static int RdseedSeedCb(OS_Seed* os, byte* seed, word32 sz) +{ + word32 i = 0; + (void)os; + + while (i < sz) { + unsigned long long v = 0; + int ok = 0; + int tries; + word32 n; + + for (tries = 0; tries < 16; tries++) { + if (_rdseed64_step(&v)) { + ok = 1; + break; + } + } + if (!ok) { + return RNG_FAILURE_E; + } + + n = (sz - i < (word32)sizeof(v)) ? (sz - i) : (word32)sizeof(v); + memcpy(seed + i, &v, n); + i += n; + } + return 0; +} + +static int GenerateKeyAndIv(byte* key, byte* iv) +{ + WC_RNG rng; + int ret; + + wc_SetSeed_Cb(RdseedSeedCb); + ret = wc_InitRng(&rng); + wc_SetSeed_Cb(NULL); + if (ret != 0) { + return ret; + } + + ret = wc_RNG_GenerateBlock(&rng, key, KEY_SZ); + if (ret == 0) { + ret = wc_RNG_GenerateBlock(&rng, iv, NONCE_SZ); + } + wc_FreeRng(&rng); + return ret; +} + +static int Encrypt(const byte* key, const byte* iv, const byte* plaintext, + word32 plaintextSz, byte* ciphertext, byte* tag, const byte* aad, + word32 aadSz) +{ + int ret; + Aes aes; + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key, KEY_SZ); + } + if (ret == 0) { + ret = wc_AesGcmEncrypt(&aes, ciphertext, plaintext, plaintextSz, iv, + NONCE_SZ, tag, TAG_SZ, aad, aadSz); + } + wc_AesFree(&aes); + return ret; +} + +static int Decrypt(const byte* key, const byte* iv, const byte* ciphertext, + word32 ciphertextSz, byte* plaintext, const byte* tag, const byte* aad, + word32 aadSz) +{ + int ret; + Aes aes; + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key, KEY_SZ); + } + if (ret == 0) { + ret = wc_AesGcmDecrypt(&aes, plaintext, ciphertext, ciphertextSz, + iv, NONCE_SZ, tag, TAG_SZ, aad, aadSz); + } + wc_AesFree(&aes); + return ret; +} + +void print_hex(const char* label, const byte* data, word32 sz) +{ + int i; + XPRINTF("%s: ", label); + for (i = 0; i < sz; i++) { + XPRINTF("%02x", data[i]); + } + XPRINTF("\n"); +} + +int main(void) +{ + byte key[KEY_SZ]; + const byte aad[] = "example-aad"; + const byte plaintext[] = "single block msg"; + byte decrypted[sizeof(plaintext)]; + byte iv[NONCE_SZ]; + byte ciphertext[sizeof(plaintext)]; + byte tag[TAG_SZ]; + int ret; + + ret = GenerateKeyAndIv(key, iv); + if (ret != 0) { + XPRINTF("Key/IV generation failed: %d\n", ret); + return 1; + } + print_hex("Plaintext", plaintext, sizeof(plaintext)); + print_hex(" Key", key, sizeof(key)); + print_hex(" IV", iv, sizeof(iv)); + + ret = Encrypt(key, iv, plaintext, sizeof(plaintext), ciphertext, tag, + aad, (word32)(sizeof(aad) - 1)); + if (ret != 0) { + XPRINTF("Encryption failed: %d\n", ret); + return 1; + } + print_hex("Ciphertext", ciphertext, sizeof(ciphertext)); + print_hex(" Auth Tag", tag, sizeof(tag)); + + ret = Decrypt(key, iv, ciphertext, sizeof(ciphertext), decrypted, tag, + aad, (word32)(sizeof(aad) - 1)); + if (ret != 0) { + XPRINTF("Decryption failed: %d\n", ret); + return 1; + } + + if (memcmp(plaintext, decrypted, sizeof(plaintext)) != 0) { + XPRINTF("Round-trip mismatch\n"); + return 1; + } + print_hex("Decrypted", decrypted, sizeof(decrypted)); + + return 0; +} +#else +int main(void) +{ + XPRINTF("This example requires __x86_64__ and WC_RNG_SEED_CB.\n"); + return 1; +} +#endif diff --git a/crypto/aes/rdseed/user_settings.h b/crypto/aes/rdseed/user_settings.h new file mode 100644 index 00000000..f57b845d --- /dev/null +++ b/crypto/aes/rdseed/user_settings.h @@ -0,0 +1,90 @@ +/* user_settings.h + * + * wolfCrypt configuration for the aesgcm-rdseed example on x86 LynxOS-178. + * Enabled via -DWOLFSSL_USER_SETTINGS on the compiler command line. + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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-1335, USA + */ + +#ifndef H_USER_SETTINGS_ +#define H_USER_SETTINGS_ + +/* ------------------------------------------------------------------------- */ +/* Platform / OS */ +/* ------------------------------------------------------------------------- */ +#define WOLFCRYPT_ONLY +#define SINGLE_THREADED +#define NO_FILESYSTEM +#define NO_DEV_RANDOM +#define WOLFSSL_NO_SOCK +#define NO_MAIN_DRIVER +#define WOLFSSL_SMALL_STACK + +/* ------------------------------------------------------------------------- */ +/* RNG: use RDSEED to seed the DRBG via wc_SetSeed_Cb */ +/* ------------------------------------------------------------------------- */ +#define WC_RNG_SEED_CB +#define HAVE_HASHDRBG + +/* ------------------------------------------------------------------------- */ +/* AES-GCM (the only algorithm this example needs) */ +/* ------------------------------------------------------------------------- */ +#define HAVE_AESGCM +#define GCM_TABLE_4BIT +#define WOLFSSL_AES_256 + +/* ------------------------------------------------------------------------- */ +/* Math library */ +/* ------------------------------------------------------------------------- */ +#define WOLFSSL_SP_MATH_ALL +#define WOLFSSL_SP +#define WOLFSSL_SP_X86_64 +#define SP_WORD_SIZE 64 + +/* ------------------------------------------------------------------------- */ +/* Timing-resistance (safety-critical best practice) */ +/* ------------------------------------------------------------------------- */ +#define TFM_TIMING_RESISTANT +#define WC_RSA_BLINDING + +/* ------------------------------------------------------------------------- */ +/* Disable everything not required by this example */ +/* ------------------------------------------------------------------------- */ +#define NO_RSA +#define NO_DH +#define NO_DSA +#define NO_RC4 +#define NO_MD4 +#define NO_MD5 +#define NO_SHA +#define NO_DES3 +#define NO_RABBIT +#define NO_HC128 +#define NO_CERT +#define NO_SESSION_CACHE +#define NO_SIG_WRAPPER +#define NO_WOLFSSL_DIR +#define WOLFSSL_NO_PEM +#define NO_PWDBASED +#define NO_OLD_RNGNAME +#define NO_WRITEV +#define WOLFSSL_IGNORE_FILE_WARN +#define NO_ERROR_STRINGS + +#endif /* !H_USER_SETTINGS_ */