int ecc_sign_verify_test(enum wc_HashType hash_type, enum wc_SignatureType sig_type, const byte* fileBuf, int fileLen, byte* verifyFileBuf, int* verifyFileLen, int* pmaxSigSz, int* pmaxCurveSigSz, int curveId, int keySz) { int ret; ecc_key eccKey; RNG rng; byte* sigBuf = NULL; word32 sigLen; byte eccPubKeyBuf[ECC_BUFSIZE], eccPrivKeyBuf[ECC_BUFSIZE]; word32 eccPubKeyLen, eccPrivKeyLen; word32 maxCurveSigSz; #ifdef DEBUG_SIG_TEST printf("ECC Signature: Curve %s, Size %d\n", wc_ecc_get_name(curveId), keySz); #endif /* Init */ wc_InitRng(&rng); /* Generate key */ wc_ecc_init(&eccKey); ret = wc_ecc_make_key_ex(&rng, keySz, &eccKey, curveId); if(ret != 0) { printf("ECC Make Key Failed! %d\n", ret); goto exit; } ret = wc_ecc_sig_size(&eccKey); if (ret < 0) { printf("ECC Sig SizeFailed! %d\n", ret); goto exit; } maxCurveSigSz = 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; } #ifdef DEBUG_SIG_TEST printf("ECC Public Key: Len %d\n", eccPubKeyLen); hexdump(eccPubKeyBuf, eccPubKeyLen, 16); #endif /* 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; } #ifdef DEBUG_SIG_TEST printf("ECC Private Key: Len %d\n", eccPrivKeyLen); hexdump(eccPrivKeyBuf, eccPrivKeyLen, 16); #endif if (verifyFileBuf) { sigLen = *verifyFileLen; sigBuf = verifyFileBuf; } else { /* Get signature length and allocate buffer */ sigLen = wc_SignatureGetSize(sig_type, &eccKey, sizeof(eccKey)); if(sigLen <= 0) { printf("ECC Signature type %d not supported!\n", sig_type); ret = EXIT_FAILURE; goto exit; } sigBuf = malloc(sigLen); if(!sigBuf) { printf("ECC Signature malloc failed!\n"); ret = EXIT_FAILURE; goto exit; } #ifdef DEBUG_SIG_TEST printf("ECC Signature Len: %d\n", sigLen); #endif /* Perform hash and sign to create signature */ ret = wc_SignatureGenerate( hash_type, sig_type, fileBuf, fileLen, sigBuf, &sigLen, &eccKey, sizeof(eccKey), &rng); *verifyFileLen = sigLen; #ifdef DEBUG_SIG_TEST printf("ECC Signature Generation: %s (%d)\n", (ret == 0) ? "Pass" : "Fail", ret); #endif if(ret < 0) { ret = EXIT_FAILURE; goto exit; } } #ifdef DEBUG_SIG_TEST printf("Signature Data:\n"); hexdump(sigBuf, sigLen, 16); #endif /* 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_ex(eccPubKeyBuf, eccPubKeyLen, &eccKey, curveId); 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)); #ifdef DEBUG_SIG_TEST printf("ECC Signature Verification: %s (%d)\n", (ret == 0) ? "Pass" : "Fail", ret); #endif if (ret < 0) { ret = EXIT_FAILURE; } if (pmaxSigSz && *pmaxSigSz < sigLen) { #ifdef DEBUG_SIG_TEST_MAX printf("Curve: Max %d->%d\n", *pmaxSigSz, sigLen); hexdump(sigBuf, sigLen, 16); #endif *pmaxSigSz = sigLen; } if (pmaxCurveSigSz && *pmaxCurveSigSz < maxCurveSigSz) { *pmaxCurveSigSz = maxCurveSigSz; } exit: /* Free */ if(sigBuf) { free(sigBuf); } wc_ecc_free(&eccKey); wc_FreeRng(&rng); return ret; }
int wc_SignatureVerify( enum wc_HashType hash_type, enum wc_SignatureType sig_type, const byte* data, word32 data_len, const byte* sig, word32 sig_len, const void* key, word32 key_len) { int ret, hash_len; byte *hash_data = NULL; /* Check arguments */ if (data == NULL || data_len <= 0 || sig == NULL || sig_len <= 0 || key == NULL || key_len <= 0) { return BAD_FUNC_ARG; } /* Validate signature len (1 to max is okay) */ if ((int)sig_len > wc_SignatureGetSize(sig_type, key, key_len)) { WOLFSSL_MSG("wc_SignatureVerify: Invalid sig type/len"); return BAD_FUNC_ARG; } /* Validate hash size */ hash_len = wc_HashGetDigestSize(hash_type); if (hash_len <= 0) { WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len"); return BAD_FUNC_ARG; } /* Allocate temporary buffer for hash data */ hash_data = XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (hash_data == NULL) { return MEMORY_E; } /* Perform hash of data */ ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); if(ret == 0) { /* Verify signature using hash as data */ switch(sig_type) { #ifdef HAVE_ECC case WC_SIGNATURE_TYPE_ECC: { int is_valid_sig = 0; /* Perform verification of signature using provided ECC key */ ret = wc_ecc_verify_hash(sig, sig_len, hash_data, hash_len, &is_valid_sig, (ecc_key*)key); if (ret != 0 || is_valid_sig != 1) { ret = SIG_VERIFY_E; } break; } #endif #ifndef NO_RSA case WC_SIGNATURE_TYPE_RSA: { byte *plain_data = XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (plain_data) { /* Perform verification of signature using provided RSA key */ ret = wc_RsaSSL_Verify(sig, sig_len, plain_data, hash_len, (RsaKey*)key); if (ret != hash_len || XMEMCMP(plain_data, hash_data, hash_len) != 0) { ret = SIG_VERIFY_E; } XFREE(plain_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); } else { ret = MEMORY_E; } break; } #endif case WC_SIGNATURE_TYPE_NONE: default: ret = BAD_FUNC_ARG; break; } } if (hash_data) { XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); } return ret; }
int main(void) { board_init(); board_console_init(BOARD_DEBUG_BAUD); SysTick_Config(BOARD_SYSTICK_100MS); PRINTF("ubirch #1 r0.2 RSA/ECC encryption/signature benchmark\r\n"); if (init_ltc() != 0) PRINTF("No LTC, may crash\r\n"); if (init_trng() != 0) error("failed to initialize TRNG"); if (init_board_key(2048) != 0) error("failed to generate key pair"); if (init_recipient_public_key(recipient_pubkey, recipient_pubkey_length)) error("failed to load recipient public key"); byte cipher[256]; // 256 bytes is large enough to store 2048 bit RSA ciphertext word32 plaintextLength = strlen(plaintext); word32 cipherLength = sizeof(cipher); PRINTF("- signing message with board private key\r\n"); uint32_t total = 0; int signatureLength = 0; byte *signature = NULL; for (int i = 0; i < BENCHMARK_LOOPS; i++) { const uint32_t start = timer_read(); signatureLength = wc_SignatureGetSize(WC_SIGNATURE_TYPE_RSA, &board_rsa_key, sizeof(board_rsa_key)); signature = malloc((size_t) signatureLength); if (wc_SignatureGenerate( WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, (const byte *) plaintext, plaintextLength, signature, (word32 *) &signatureLength, &board_rsa_key, sizeof(board_rsa_key), &rng) != 0) error("failed to sign plain text message"); const uint32_t elapsed = timer_read() - start; total += elapsed; char loop_str[64]; sprintf(loop_str, "%d", i); timestamp(loop_str, elapsed); } timestamp("Average:", total / BENCHMARK_LOOPS); PRINTF("-- SIGNATURE\r\n"); PRINTF("- encrypting message\r\n"); total = 0; int r = -1; for (int i = 0; i < BENCHMARK_LOOPS; i++) { const uint32_t start = timer_read(); r = wc_RsaPublicEncrypt((const byte *) plaintext, plaintextLength, cipher, cipherLength, &recipient_public_key, &rng); if (r < 0) error("failed to encrypt message"); const uint32_t elapsed = timer_read() - start; total += elapsed; char loop_str[64]; sprintf(loop_str, "%d", i); timestamp(loop_str, elapsed); } timestamp("Average:", total / BENCHMARK_LOOPS); PRINTF("-- CIPHER (%d bytes)\r\n", r); wc_FreeRsaKey(&board_rsa_key); wc_FreeRsaKey(&recipient_public_key); PRINTF("THE END\r\n"); while (true) { uint8_t ch = (uint8_t) GETCHAR(); if (ch == '\r') PUTCHAR('\n'); PUTCHAR(ch); } }
int wc_SignatureGenerate( enum wc_HashType hash_type, enum wc_SignatureType sig_type, const byte* data, word32 data_len, byte* sig, word32 *sig_len, const void* key, word32 key_len, RNG* rng) { int ret, hash_len; byte *hash_data = NULL; /* Supress possible unused arg if all signature types are disabled */ (void)rng; /* Check arguments */ if (data == NULL || data_len <= 0 || sig == NULL || sig_len == NULL || *sig_len <= 0 || key == NULL || key_len <= 0) { return BAD_FUNC_ARG; } /* Validate signature len (needs to be at least max) */ if ((int)*sig_len < wc_SignatureGetSize(sig_type, key, key_len)) { WOLFSSL_MSG("wc_SignatureGenerate: Invalid sig type/len"); return BAD_FUNC_ARG; } /* Validate hash size */ hash_len = wc_HashGetDigestSize(hash_type); if (hash_len <= 0) { WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len"); return BAD_FUNC_ARG; } /* Allocate temporary buffer for hash data */ hash_data = XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (hash_data == NULL) { return MEMORY_E; } /* Perform hash of data */ ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); if (ret == 0) { /* Create signature using hash as data */ switch(sig_type) { #ifdef HAVE_ECC case WC_SIGNATURE_TYPE_ECC: { /* Create signature using provided ECC key */ ret = wc_ecc_sign_hash(hash_data, hash_len, sig, sig_len, rng, (ecc_key*)key); break; } #endif #ifndef NO_RSA case WC_SIGNATURE_TYPE_RSA: /* Create signature using provided RSA key */ ret = wc_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, (RsaKey*)key, rng); if (ret > 0) { *sig_len = ret; } break; #endif case WC_SIGNATURE_TYPE_NONE: default: ret = BAD_FUNC_ARG; break; } } if (hash_data) { XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); } return ret; }