diff --git a/signature/ecc-compare/Makefile b/signature/ecc-compare/Makefile new file mode 100644 index 00000000..e6ff2a9e --- /dev/null +++ b/signature/ecc-compare/Makefile @@ -0,0 +1,23 @@ +# Makefile for ECC signature verification comparison examples +CC=gcc +OPENSSL_CFLAGS=-Wall -I/usr/include/openssl +OPENSSL_LDFLAGS=-lssl -lcrypto +WOLFSSL_CFLAGS=-Wall -I/home/ubuntu/repos/wolfssl/ +WOLFSSL_LDFLAGS=-L/home/ubuntu/repos/wolfssl/src/.libs -lwolfssl -lm + +# Default target +all: ecc-verify-openssl-low ecc-verify-wolfssl + +# Rule for building OpenSSL low-level example +ecc-verify-openssl-low: ecc-verify-openssl-low.c + $(CC) -o $@ $< $(OPENSSL_CFLAGS) $(OPENSSL_LDFLAGS) + +# Rule for building wolfSSL example +ecc-verify-wolfssl: ecc-verify-wolfssl.c + $(CC) -o $@ $< $(WOLFSSL_CFLAGS) $(WOLFSSL_LDFLAGS) + +# Clean target +clean: + rm -f ecc-verify-openssl-low ecc-verify-wolfssl + +.PHONY: all clean diff --git a/signature/ecc-compare/README.md b/signature/ecc-compare/README.md new file mode 100644 index 00000000..ae7b7198 --- /dev/null +++ b/signature/ecc-compare/README.md @@ -0,0 +1,70 @@ +# ECC Signature Verification Comparison + +This directory contains examples demonstrating ECC signature verification using both OpenSSL and wolfSSL libraries with the same test values. + +## Software Bill of Materials (SBOM) + +| Component | Description | Version | +|-----------|-------------|---------| +| OpenSSL | Cryptography and SSL/TLS Toolkit | 3.0.x | +| wolfSSL | Embedded SSL/TLS Library | 5.6.x | +| C Standard Library | Standard C library | - | + +## Examples + +### OpenSSL Low-level API Example + +The `ecc-verify-openssl-low.c` example demonstrates how to verify an ECC signature using OpenSSL's low-level EC interfaces, specifically `ECDSA_verify()`. It uses: + +- Fixed ECC public key (single encoded value in uncompressed format) +- Fixed signature (DER format) +- Fixed data (pre-computed hash) + +### wolfSSL Example + +The `ecc-verify-wolfssl.c` example demonstrates how to verify the same ECC signature using wolfSSL's `wc_ecc_verify_hash` function. It uses the same fixed test values as the OpenSSL example. + +## Test Values + +Both examples use the following fixed test values: + +- **Public Key (uncompressed format)**: + ``` + 042FBFB32C9E2890FD742D991FD43B889191791E18337AD408CB12CA79325E88DD7D20A5182318EC9BD696DDF41128D8BF1A137D2446C7A5AF6AA60AFEF3E8610E + ``` + +- **Signature (DER format)**: + ``` + 30450220763B61459CF2FC3E821053702CC24C0E378C976FC6F83F0F0FF05BD85203B958022100A40A0A3AF50769EE740CBA8F9B5F4530F5E5A93EDEBBAB14A1F3BECE93FB5A47 + ``` + +- **Data (pre-computed hash)**: + ``` + E7BD43AEE750B0DA4B3F537E152C4A7407764037A57447CACD2096A5D60994BA + ``` + +## Building + +``` +make +``` + +This will build both examples. + +## Running + +### OpenSSL Example + +``` +./ecc-verify-openssl-low +``` + +### wolfSSL Example + +``` +./ecc-verify-wolfssl +``` + +## Expected Output + +Both examples should output the test values and verification results, showing successful signature verification. diff --git a/signature/ecc-compare/ecc-verify-openssl-low.c b/signature/ecc-compare/ecc-verify-openssl-low.c new file mode 100644 index 00000000..bc4c7f2d --- /dev/null +++ b/signature/ecc-compare/ecc-verify-openssl-low.c @@ -0,0 +1,251 @@ +/* ecc-verify-openssl-low.c + * + * Copyright (C) 2006-2025 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Helper function to convert hex string to binary */ +static int hex2bin(const char *hex, unsigned char *bin, int bin_size) +{ + int i; + int hex_len = strlen(hex); + + if (hex_len % 2 != 0) { + fprintf(stderr, "Error: Hex string must have even length\n"); + return -1; + } + + if (bin_size < hex_len / 2) { + fprintf(stderr, "Error: Binary buffer too small\n"); + return -1; + } + + for (i = 0; i < hex_len / 2; i++) { + unsigned char byte = 0; + int j; + + for (j = 0; j < 2; j++) { + char c = hex[i * 2 + j]; + byte <<= 4; + + if (c >= '0' && c <= '9') + byte |= c - '0'; + else if (c >= 'a' && c <= 'f') + byte |= c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + byte |= c - 'A' + 10; + else { + fprintf(stderr, "Error: Invalid hex character: %c\n", c); + return -1; + } + } + + bin[i] = byte; + } + + return hex_len / 2; +} + +/* Fixed test data in hex format (pre-computed hash) */ +static const char *fixed_data_hex = + "E7BD43AEE750B0DA4B3F537E152C4A7407764037A57447CACD2096A5D60994BA"; + +/* Fixed ECC public key in hex format (uncompressed format for P-256 curve) */ +static const char *fixed_pubkey_hex = + "042FBFB32C9E2890FD742D991FD43B889191791E18337AD408CB12CA79325E88DD" + "7D20A5182318EC9BD696DDF41128D8BF1A137D2446C7A5AF6AA60AFEF3E8610E"; + +/* Fixed signature in hex format (DER format) */ +static const char *fixed_signature_hex = + "30450220763B61459CF2FC3E821053702CC24C0E378C976FC6F83F0F0FF05BD85203B958" + "022100A40A0A3AF50769EE740CBA8F9B5F4530F5E5A93EDEBBAB14A1F3BECE93FB5A47"; + +/* Sample message that was signed (for display purposes) */ +static const char *sample_message = "sample message for signing"; + +/* Helper function to print OpenSSL errors */ +static void print_openssl_errors(void) +{ + unsigned long err; + while ((err = ERR_get_error()) != 0) { + char *err_str = ERR_error_string(err, NULL); + fprintf(stderr, "OpenSSL error: %s\n", err_str); + } +} + +/* Helper function to print binary data in hex format */ +static void print_hex(const char *label, const unsigned char *data, size_t len) +{ + size_t i; + + printf("%s (length=%zu):\n", label, len); + for (i = 0; i < len; i++) { + printf("%02X", data[i]); + if ((i + 1) % 16 == 0 || i == len - 1) + printf("\n"); + else if ((i + 1) % 8 == 0) + printf(" "); + else + printf(" "); + } + printf("\n"); +} + +int verify_ecc_signature(void) +{ + int ret = 0; + unsigned char fixed_data[128]; + unsigned char fixed_pubkey[128]; + unsigned char fixed_signature[128]; + int data_len, pubkey_len, sig_len; + EC_KEY *ec_key = NULL; + ECDSA_SIG *ecdsa_sig = NULL; + const unsigned char *p; + BIGNUM *r = NULL; + BIGNUM *s = NULL; + int verify_result; + + /* Convert hex strings to binary */ + data_len = hex2bin(fixed_data_hex, fixed_data, sizeof(fixed_data)); + if (data_len < 0) { + printf("Error: Failed to convert data hex string\n"); + ret = -1; + goto cleanup; + } + + pubkey_len = hex2bin(fixed_pubkey_hex, fixed_pubkey, sizeof(fixed_pubkey)); + if (pubkey_len < 0) { + printf("Error: Failed to convert pubkey hex string\n"); + ret = -1; + goto cleanup; + } + + sig_len = hex2bin(fixed_signature_hex, fixed_signature, sizeof(fixed_signature)); + if (sig_len < 0) { + printf("Error: Failed to convert signature hex string\n"); + ret = -1; + goto cleanup; + } + + /* Print the binary data for verification */ + printf("Data to verify: \"%s\"\n\n", sample_message); + print_hex("Data (pre-computed hash)", fixed_data, data_len); + print_hex("Public Key (uncompressed format)", fixed_pubkey, pubkey_len); + print_hex("Signature (DER format)", fixed_signature, sig_len); + + /* Initialize OpenSSL */ + ERR_load_crypto_strings(); + + /* Create a new EC_KEY for the prime256v1 curve */ + ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + if (ec_key == NULL) { + printf("Error: Failed to create EC_KEY\n"); + print_openssl_errors(); + ret = -1; + goto cleanup; + } + + /* Set the public key from the binary data */ + if (EC_KEY_oct2key(ec_key, fixed_pubkey, pubkey_len, NULL) != 1) { + printf("Error: Failed to set public key\n"); + print_openssl_errors(); + ret = -1; + goto cleanup; + } + + /* Parse the DER signature to extract r and s components */ + printf("\nExtracting r and s components from DER signature...\n"); + p = fixed_signature; + ecdsa_sig = d2i_ECDSA_SIG(NULL, &p, sig_len); + if (ecdsa_sig == NULL) { + printf("Error: Failed to parse DER signature\n"); + print_openssl_errors(); + ret = -1; + goto cleanup; + } + + /* Get r and s values */ + ECDSA_SIG_get0(ecdsa_sig, (const BIGNUM **)&r, (const BIGNUM **)&s); + if (r == NULL || s == NULL) { + printf("Error: Failed to get r and s values\n"); + print_openssl_errors(); + ret = -1; + goto cleanup; + } + + /* Print r and s values */ + unsigned char r_bin[128], s_bin[128]; + int r_len = BN_bn2bin(r, r_bin); + int s_len = BN_bn2bin(s, s_bin); + + print_hex("Signature r component", r_bin, r_len); + print_hex("Signature s component", s_bin, s_len); + + /* Verify the signature using ECDSA_verify */ + printf("\nVerifying signature using ECDSA_verify...\n"); + verify_result = ECDSA_verify(0, fixed_data, data_len, fixed_signature, sig_len, ec_key); + + if (verify_result == 1) { + printf("Signature verification successful!\n"); + ret = 0; /* Success */ + } else if (verify_result == 0) { + printf("Signature verification failed - invalid signature\n"); + print_openssl_errors(); + ret = -1; + } else { + printf("Signature verification error\n"); + print_openssl_errors(); + ret = -1; + } + +cleanup: + /* Clean up */ + if (ecdsa_sig) ECDSA_SIG_free(ecdsa_sig); + if (ec_key) EC_KEY_free(ec_key); + + /* Cleanup OpenSSL */ + CRYPTO_cleanup_all_ex_data(); + ERR_free_strings(); + + return ret; +} + +int main(void) +{ + int ret; + + printf("OpenSSL ECC Signature Verification Example (Low-level API)\n"); + printf("Using fixed test values for public key, signature, and data\n\n"); + + ret = verify_ecc_signature(); + + printf("\nVerification result: %s (ret = %d)\n", + (ret == 0) ? "SUCCESS" : "FAILURE", ret); + + return (ret == 0) ? 0 : 1; +} diff --git a/signature/ecc-compare/ecc-verify-wolfssl.c b/signature/ecc-compare/ecc-verify-wolfssl.c new file mode 100644 index 00000000..c75c9473 --- /dev/null +++ b/signature/ecc-compare/ecc-verify-wolfssl.c @@ -0,0 +1,229 @@ +/* ecc-verify-wolfssl.c + * + * Copyright (C) 2006-2025 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Helper function to convert hex string to binary */ +static int hex2bin(const char *hex, unsigned char *bin, int bin_size) +{ + int i; + int hex_len = strlen(hex); + + if (hex_len % 2 != 0) { + fprintf(stderr, "Error: Hex string must have even length\n"); + return -1; + } + + if (bin_size < hex_len / 2) { + fprintf(stderr, "Error: Binary buffer too small\n"); + return -1; + } + + for (i = 0; i < hex_len / 2; i++) { + unsigned char byte = 0; + int j; + + for (j = 0; j < 2; j++) { + char c = hex[i * 2 + j]; + byte <<= 4; + + if (c >= '0' && c <= '9') + byte |= c - '0'; + else if (c >= 'a' && c <= 'f') + byte |= c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + byte |= c - 'A' + 10; + else { + fprintf(stderr, "Error: Invalid hex character: %c\n", c); + return -1; + } + } + + bin[i] = byte; + } + + return hex_len / 2; +} + +/* Fixed test data in hex format (pre-computed hash) */ +static const char *fixed_data_hex = + "E7BD43AEE750B0DA4B3F537E152C4A7407764037A57447CACD2096A5D60994BA"; + +/* Fixed ECC public key in hex format (uncompressed format for P-256 curve) */ +static const char *fixed_pubkey_hex = + "042FBFB32C9E2890FD742D991FD43B889191791E18337AD408CB12CA79325E88DD" + "7D20A5182318EC9BD696DDF41128D8BF1A137D2446C7A5AF6AA60AFEF3E8610E"; + +/* Fixed signature in hex format (DER format) */ +static const char *fixed_signature_hex = + "30450220763B61459CF2FC3E821053702CC24C0E378C976FC6F83F0F0FF05BD85203B958" + "022100A40A0A3AF50769EE740CBA8F9B5F4530F5E5A93EDEBBAB14A1F3BECE93FB5A47"; + +/* Sample message that was signed (for display purposes) */ +static const char *sample_message = "sample message for signing"; + +/* Helper function to print wolfSSL errors */ +static void print_wolfssl_error(int err) +{ + fprintf(stderr, "wolfSSL error: %d (%s)\n", err, wc_GetErrorString(err)); +} + +/* Helper function to print binary data in hex format */ +static void print_hex(const char *label, const unsigned char *data, size_t len) +{ + size_t i; + + printf("%s (length=%zu):\n", label, len); + for (i = 0; i < len; i++) { + printf("%02X", data[i]); + if ((i + 1) % 16 == 0 || i == len - 1) + printf("\n"); + else if ((i + 1) % 8 == 0) + printf(" "); + else + printf(" "); + } + printf("\n"); +} + +int verify_ecc_signature(void) +{ + int ret = 0; + unsigned char fixed_data[128]; + unsigned char fixed_pubkey[128]; + unsigned char fixed_signature[128]; + int data_len, pubkey_len, sig_len; + ecc_key eccKey; + int verify_status = 0; + word32 idx = 0; + + /* Convert hex strings to binary */ + data_len = hex2bin(fixed_data_hex, fixed_data, sizeof(fixed_data)); + if (data_len < 0) { + printf("Error: Failed to convert data hex string\n"); + ret = -1; + goto cleanup; + } + + pubkey_len = hex2bin(fixed_pubkey_hex, fixed_pubkey, sizeof(fixed_pubkey)); + if (pubkey_len < 0) { + printf("Error: Failed to convert pubkey hex string\n"); + ret = -1; + goto cleanup; + } + + sig_len = hex2bin(fixed_signature_hex, fixed_signature, sizeof(fixed_signature)); + if (sig_len < 0) { + printf("Error: Failed to convert signature hex string\n"); + ret = -1; + goto cleanup; + } + + /* Print the binary data for verification */ + printf("Data to verify: \"%s\"\n\n", sample_message); + print_hex("Data (pre-computed hash)", fixed_data, data_len); + print_hex("Public Key (uncompressed format)", fixed_pubkey, pubkey_len); + print_hex("Signature (DER format)", fixed_signature, sig_len); + + /* Initialize wolfSSL */ + ret = wc_ecc_init(&eccKey); + if (ret != 0) { + printf("Error: Failed to initialize ECC key\n"); + print_wolfssl_error(ret); + goto cleanup; + } + + /* Import the public key */ + ret = wc_ecc_import_x963(fixed_pubkey, pubkey_len, &eccKey); + if (ret != 0) { + printf("Error: Failed to import public key\n"); + print_wolfssl_error(ret); + goto cleanup; + } + + /* Extract r and s components from DER signature for display purposes */ + printf("\nExtracting r and s components from DER signature...\n"); + + /* Create temporary buffer for r and s components */ + byte r_buf[MAX_ECC_BYTES]; + byte s_buf[MAX_ECC_BYTES]; + word32 r_size = sizeof(r_buf); + word32 s_size = sizeof(s_buf); + + /* Decode the DER signature to extract r and s components */ + ret = wc_ecc_sig_to_rs(fixed_signature, sig_len, r_buf, &r_size, s_buf, &s_size); + if (ret != 0) { + printf("Error: Failed to decode signature\n"); + print_wolfssl_error(ret); + goto cleanup; + } + + /* Display the r and s components */ + print_hex("Signature r component", r_buf, r_size); + print_hex("Signature s component", s_buf, s_size); + + /* Verify the signature using wc_ecc_verify_hash */ + printf("\nVerifying signature using wc_ecc_verify_hash...\n"); + ret = wc_ecc_verify_hash(fixed_signature, sig_len, fixed_data, data_len, &verify_status, &eccKey); + + if (ret == 0) { + if (verify_status == 1) { + printf("Signature verification successful!\n"); + ret = 0; /* Success */ + } else { + printf("Signature verification failed - invalid signature\n"); + ret = -1; + } + } else { + printf("Signature verification error\n"); + print_wolfssl_error(ret); + ret = -1; + } + +cleanup: + /* Clean up */ + wc_ecc_free(&eccKey); + + return ret; +} + +int main(void) +{ + int ret; + + printf("wolfSSL ECC Signature Verification Example\n"); + printf("Using fixed test values for public key, signature, and data\n\n"); + + ret = verify_ecc_signature(); + + printf("\nVerification result: %s (ret = %d)\n", + (ret == 0) ? "SUCCESS" : "FAILURE", ret); + + return (ret == 0) ? 0 : 1; +}