From cbe8214bd876f65b1ae6628c60ff90759ba869e2 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Wed, 11 May 2022 11:41:27 +1000 Subject: [PATCH] Add RSA key generation example --- .gitignore | 1 + pk/rsa-kg/Makefile | 12 ++- pk/rsa-kg/README.md | 17 +++- pk/rsa-kg/rsa-kg.c | 243 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 269 insertions(+), 4 deletions(-) create mode 100644 pk/rsa-kg/rsa-kg.c diff --git a/.gitignore b/.gitignore index 91b7b08a..de8952da 100644 --- a/.gitignore +++ b/.gitignore @@ -220,6 +220,7 @@ pk/ed25519_gen/gen_key_files pk/ed25519_gen/sign_and_verify pk/ecdh_generate_secret/ecdh_gen_secret pk/rsa-kg/rsa-kg-sv +pk/rsa-kg/rsa-kg pk/dh-pg/dh-pg-ka pk/test_cert_and_private_keypair/test-cert-privkey-pair pk/srp/srp_gen diff --git a/pk/rsa-kg/Makefile b/pk/rsa-kg/Makefile index 5e0a9874..970f7596 100644 --- a/pk/rsa-kg/Makefile +++ b/pk/rsa-kg/Makefile @@ -2,15 +2,21 @@ CC=gcc CFLAGS=-Wall LIBS= -lwolfssl -lm -all: rsa-kg-sv +all: rsa-kg-sv rsa-kg rsa-kg-sv.o: rsa-kg-sv.c rsa-key.h $(CC) -c -o $@ $< $(CFLAGS) rsa-kg-sv: rsa-kg-sv.o - $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + +rsa-kg.o: rsa-kg.c + $(CC) -c -o $@ $< $(CFLAGS) + +rsa-kg: rsa-kg.o + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) .PHONY: clean clean: - rm -f *.o rsa-kg-sv + rm -f *.o rsa-kg-sv rsa-kg diff --git a/pk/rsa-kg/README.md b/pk/rsa-kg/README.md index 19dbe6ea..d8500a31 100644 --- a/pk/rsa-kg/README.md +++ b/pk/rsa-kg/README.md @@ -13,6 +13,21 @@ How to use rsa-kg-sv.c NOTE: on error, the key and digest will be displayed so that they can be copied into rsa-key.h replacing the existing values. -4) Running 'make clean' will delete the executable and object files. +3) Running 'make clean' will delete the executable and object files. +How to use rsa-kg.c + +1) a. Compile wolfSSL with ./configure --enable-keygen, run + 'make', and then install by typing 'sudo make install'. + b. In the pk/rsa-kg directory run the Makefile by typing 'make'. +2) run the executable, for help run with -help. Basic command is as follows: + + ./rsa-kg + + Key sizes supported, in bits: 1024-4096. + + Specify the name of the output files with -priv and -pub. + +3) Running 'make clean' will delete the executable and object files. + diff --git a/pk/rsa-kg/rsa-kg.c b/pk/rsa-kg/rsa-kg.c new file mode 100644 index 00000000..f73e7ac3 --- /dev/null +++ b/pk/rsa-kg/rsa-kg.c @@ -0,0 +1,243 @@ +/* rsa-kg.c + * + * Copyright (C) 2006-2020 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 + */ + +/* +* An implementation of RSA key generation using wolfSSL +* Usage: +./rsa-kg -priv -pub +*/ + +#include +#include + +#include +#include +#include +#include +#include + +#define MAX_DER_SIZE 2500 +#define MIN_RSA_KEY_SIZE 1024 +#define MAX_RSA_KEY_SIZE 4096 +#define DEF_RSA_KEY_SIZE 2048 + +static const char* kRsaPubKey = "./rsa-public.der"; +static const char* kRsaPrivKey = "./rsa-private.der"; + +/* Shows usage information */ +void usage() +{ + fprintf(stderr, "rsa_kg :\n"); + fprintf(stderr, " -bits Size in bits of RSA keys generated\n"); + fprintf(stderr, " Range: 1024-4096\n"); + fprintf(stderr, " -priv Private key filename\n"); + fprintf(stderr, " -pub Public key filename\n"); + fprintf(stderr, "\n"); +} + +int main(int argc, char** argv) +{ +/* These examples require RSA and Key Gen */ +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) + RsaKey* pRsaKey = NULL; + WC_RNG rng; + int ret = 0; + int bits = DEF_RSA_KEY_SIZE; + int sz; + unsigned char derBuf[MAX_DER_SIZE]; + FILE* f; + const char* pubKey = kRsaPubKey; + const char* privKey = kRsaPrivKey; + + argc--; + argv++; + while (argc > 0) { + /* Number of bits in RSA key to generate */ + if (XSTRNCMP(*argv, "-bits", 6) == 0) { + ++argv; + if (--argc == 0) { + fprintf(stderr, "Missing bits value\n"); + usage(); + return 1; + } + bits = atoi(*argv); + } + else if (XSTRNCMP(*argv, "-priv", 6) == 0) { + ++argv; + if (--argc == 0) { + fprintf(stderr, "Missing private key filename\n"); + usage(); + return 1; + } + privKey = *argv; + } + else if (XSTRNCMP(*argv, "-pub", 6) == 0) { + ++argv; + if (--argc == 0) { + fprintf(stderr, "Missing public key filename\n"); + usage(); + return 1; + } + pubKey = *argv; + } + else if (XSTRNCMP(*argv, "-help", 6) == 0) { + usage(); + return 0; + } + else { + fprintf(stderr, "Unrecognized option: %s\n", *argv); + usage(); + return 1; + } + + argc--; + argv++; + } + + /* Check bit count if generating keys */ + if ((bits < MIN_RSA_KEY_SIZE || bits > MAX_RSA_KEY_SIZE)) { + fprintf(stderr, "Bits out of range (%d-%d): %d\n", MIN_RSA_KEY_SIZE, + MAX_RSA_KEY_SIZE, bits); + usage(); + return 1; + } +#ifdef WOLFSSL_SP_MATH + if (0) { + } +#ifndef WOLFSSL_SP_NO_2048 + else if (bits == 2048) { + } +#endif +#ifndef WOLFSSL_SP_NO_3072 + else if (bits == 3072) { + } +#endif +#ifdef WOLFSSL_SP_4096 + else if (bits == 4096) { + } +#endif + else { + fprintf(stderr, "Bit size not supported with SP_MATH: %d\n", bits); + fprintf(stderr, " wolfSSL compiled to support, in bits:"); +#ifndef WOLFSSL_SP_NO_2048 + fprintf(stderr, " 2048"); +#endif +#ifndef WOLFSSL_SP_NO_3072 + fprintf(stderr, " 3072"); +#endif +#ifdef WOLFSSL_SP_4096 + fprintf(stderr, " 4096"); +#endif + fprintf(stderr, "\n"); + return 1; + } +#endif + + wolfSSL_Debugging_ON(); + + wolfSSL_Init(); + + /* Allocate space for RSA key object. */ + pRsaKey = malloc(sizeof(RsaKey)); + if (!pRsaKey) { + printf("RSA_generate_key failed with error\n"); + return MEMORY_E; + } + + /* Create a random number generator for key generation. */ + ret = wc_InitRng(&rng); + if (ret != 0) { + printf("Init RNG failed %d\n", ret); + free(pRsaKey); + return ret; + } + + /* Initialize RSA key object. */ + ret = wc_InitRsaKey(pRsaKey, NULL); + if (ret != 0) { + printf("Init RSA key failed %d\n", ret); + wc_FreeRng(&rng); + free(pRsaKey); + return ret; + } + + printf("Generating RSA key\n"); + + /* Generate an RSA key pair. */ + if (wc_MakeRsaKey(pRsaKey, bits, WC_RSA_EXPONENT, &rng) != 0) { + printf("failed to create rsa key\n"); + } + else { + /* Open public key file. */ + f = fopen(pubKey, "wb"); + printf("writing public key to %s\n", pubKey); + if (f == NULL) { + printf("unable to write out public key\n"); + } + else { + /* Encode public key to DER. */ + sz = wc_RsaKeyToPublicDer(pRsaKey, derBuf, sizeof(derBuf)); + if (sz <= 0) { + printf("error with rsa to public der %d\n", sz); + } + else { + /* Write DER encoded public key to file. */ + fwrite(derBuf, 1, sz, f); + } + fclose(f); + } + + /* Open private key file. */ + f = fopen(privKey, "wb"); + printf("writing public key to %s\n", privKey); + if (f == NULL) { + printf("unable to write out public key\n"); + } + else { + /* Encode private key to DER. */ + sz = wc_RsaKeyToDer(pRsaKey, derBuf, sizeof(derBuf)); + if (sz <= 0) { + printf("error with rsa to public der %d\n", sz); + } + else { + /* Write DER encoded private key to file. */ + fwrite(derBuf, 1, sz, f); + } + fclose(f); + } + } + + /* Dispose of allocated memory. */ + wc_FreeRsaKey(pRsaKey); + wc_FreeRng(&rng); + free(pRsaKey); + wolfSSL_Cleanup(); + + return 0; +#else + (void)kRsaPubKey; + (void)kRsaPrivKey; + + printf("wolfSSL missing build features.\n"); + printf("Please build using `./configure --enable-keygen`\n"); + return 1; +#endif +}