diff --git a/.gitignore b/.gitignore index 7905ad9b..9af727b4 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,5 @@ crypto/keys/ecc_keys crypto/keys/*.der crypto/keys/*.x963 +signature/signature + diff --git a/signature/Makefile b/signature/Makefile new file mode 100644 index 00000000..840a875c --- /dev/null +++ b/signature/Makefile @@ -0,0 +1,13 @@ +CC=gcc +CFLAGS=-Wall +LIBS= -lwolfssl + +all: signature + +signature: signature.o + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + +.PHONY: clean + +clean: + rm -f *.o signature diff --git a/signature/README.md b/signature/README.md new file mode 100644 index 00000000..056d8214 --- /dev/null +++ b/signature/README.md @@ -0,0 +1,15 @@ +# wolfSSL Signature Example + +This directory contains: + +A simple example of using wolfSSL to sign and verify binary data using SHA512 and ECC256. + +This example creates a signature from a hash of the file and signs it using a generated ECC key. Then it performs a verification using the signature and public key. + + +## Compiling and Running the Example + +``` +$ make +$ ./firmware [filename] +``` diff --git a/signature/signature.c b/signature/signature.c new file mode 100644 index 00000000..71b076be --- /dev/null +++ b/signature/signature.c @@ -0,0 +1,211 @@ +/* signature.c + * + * Copyright (C) 2006-2015 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 +#include +#include +#include +#include +#include +#include + +void hexdump(const void *buffer, word32 len, byte cols) +{ + word32 i; + + for(i = 0; i < len + ((len % cols) ? (cols - len % cols) : 0); i++) + { + /* print hex data */ + if(i < len) { + printf("%02X ", ((byte*)buffer)[i] & 0xFF); + } + + if(i % cols == (cols - 1)) { + printf("\n"); + } + } +} + + +int main(int argc, char** argv) +{ + int ret = 0; + ecc_key eccKey; + RNG rng; + int fileLen; + byte* fileBuf = NULL; + FILE* file; + byte* sigBuf = NULL; + word32 sigLen; + enum wc_HashType hash_type = WC_HASH_TYPE_SHA512; + enum wc_SignatureType sig_type = WC_SIGNATURE_TYPE_ECC; + byte eccPubKeyBuf[ECC_BUFSIZE], eccPrivKeyBuf[ECC_BUFSIZE]; + word32 eccPubKeyLen, eccPrivKeyLen; + + /* Check arguments */ + if (argc < 2) { + printf("Usage: signature \n"); + printf(" : 1=MD2, 2=MD4, 3=MD5, 4=SHA, 5=SHA256, 6=SHA384, 7=SHA512 (def)\n"); + return 1; + } + if(argc >= 3) { + hash_type = atoi(argv[2]); + } + + /* Verify hash type is supported */ + if (wc_HashGetDigestSize(hash_type) <= 0) { + printf("Hash type %d not supported!\n", hash_type); + return 1; + } + + printf("Signature Example: Hash=%d\n", hash_type); + + /* Init */ + wc_InitRng(&rng); + + /* Open file */ + file = fopen(argv[1], "rb"); + if (file == NULL) { + printf("File %s does not exist!\n", argv[1]); + ret = EXIT_FAILURE; + goto exit; + } + + /* Determine length of file */ + fseek(file, 0, SEEK_END); + fileLen = (int) ftell(file); + fseek(file, 0, SEEK_SET); + printf("File %s is %d bytes\n", argv[1], fileLen); + + /* Allocate buffer for image */ + fileBuf = malloc(fileLen); + if(!fileBuf) { + printf("File buffer malloc failed!\n"); + ret = EXIT_FAILURE; + goto exit; + } + + /* Load file into buffer */ + ret = (int)fread(fileBuf, 1, fileLen, file); + if(ret != fileLen) { + printf("Error reading file! %d", ret); + ret = EXIT_FAILURE; + goto exit; + } + + /* Generate key */ + wc_ecc_init(&eccKey); + ret = wc_ecc_make_key(&rng, 32, &eccKey); + if(ret != 0) { + printf("Make ECC Key Failed! %d\n", ret); + } + + /* Display public key data */ + eccPubKeyLen = ECC_BUFSIZE; + ret = wc_ecc_export_x963(&eccKey, eccPubKeyBuf, &eccPubKeyLen); + if (ret != 0) { + printf("ECC public key x963 export failed! %d\n", ret); + ret = EXIT_FAILURE; + goto exit; + } + printf("ECC Public Key: Len %d\n", eccPubKeyLen); + hexdump(eccPubKeyBuf, eccPubKeyLen, 16); + + /* Display private key data */ + eccPrivKeyLen = ECC_BUFSIZE; + ret = wc_ecc_export_private_only(&eccKey, eccPrivKeyBuf, &eccPrivKeyLen); + if (ret != 0) { + printf("ECC private key export failed! %d\n", ret); + ret = EXIT_FAILURE; + goto exit; + } + printf("ECC Private Key: Len %d\n", eccPrivKeyLen); + hexdump(eccPrivKeyBuf, eccPrivKeyLen, 16); + + /* Get signature length and allocate buffer */ + sigLen = wc_SignatureGetSize(sig_type, &eccKey, sizeof(eccKey)); + if(sigLen <= 0) { + printf("Signature type %d not supported!\n", sig_type); + ret = EXIT_FAILURE; + goto exit; + } + sigBuf = malloc(sigLen); + if(!sigBuf) { + printf("Signature malloc failed!\n"); + ret = EXIT_FAILURE; + goto exit; + } + printf("Signature Len: %d\n", sigLen); + + /* Perform hash and sign to create signature */ + ret = wc_SignatureGenerate( + hash_type, sig_type, + fileBuf, fileLen, + sigBuf, &sigLen, + &eccKey, sizeof(eccKey), + &rng); + printf("Signature Generation: %s (%d)\n", (ret == 0) ? "Pass" : "Fail", ret); + if(ret != 0) { + ret = EXIT_FAILURE; + goto exit; + } + + printf("Signature Data:\n"); + hexdump(sigBuf, sigLen, 16); + + /* Perform signature verification */ + /* Release and init new key */ + wc_ecc_free(&eccKey); + wc_ecc_init(&eccKey); + + /* Import the public key */ + ret = wc_ecc_import_x963(eccPubKeyBuf, eccPubKeyLen, &eccKey); + if (ret != 0) { + printf("ECC public key import failed! %d\n", ret); + ret = EXIT_FAILURE; + goto exit; + } + + /* Perform signature verification using public key */ + ret = wc_SignatureVerify( + hash_type, sig_type, + fileBuf, fileLen, + sigBuf, sigLen, + &eccKey, sizeof(eccKey)); + printf("Signature Verification: %s (%d)\n", (ret == 0) ? "Pass" : "Fail", ret); + if(ret != 0) { + ret = EXIT_FAILURE; + goto exit; + } + +exit: + /* Free */ + if(fileBuf) { + free(fileBuf); + } + if(sigBuf) { + free(sigBuf); + } + wc_ecc_free(&eccKey); + wc_FreeRng(&rng); + + return ret; +}