Skip to content

Commit 6692649

Browse files
authored
Merge pull request #277 from rizlik/test_ecdsa_compared_with_sw
tests: add ecdsa cross validation with software implementation
2 parents 7eaba42 + 71c9b43 commit 6692649

File tree

1 file changed

+258
-0
lines changed

1 file changed

+258
-0
lines changed

test/wh_test_crypto.c

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,258 @@ static int whTest_CryptoEccCacheDuplicate(whClientContext* client)
690690

691691
return ret;
692692
}
693+
694+
#if defined(HAVE_ECC_SIGN) && defined(HAVE_ECC_VERIFY) && \
695+
!defined(WOLF_CRYPTO_CB_ONLY_ECC)
696+
697+
/* Key sizes in bytes for each curve */
698+
#define WH_TEST_ECC_P256_KEY_SIZE 32
699+
#define WH_TEST_ECC_P384_KEY_SIZE 48
700+
#define WH_TEST_ECC_P521_KEY_SIZE 66
701+
702+
/* Use maximum digest size for all curves to test hash truncation edge cases.
703+
* ECDSA implementations must properly truncate hashes larger than the curve
704+
* order. */
705+
#define WH_TEST_ECC_HASH_SIZE WC_MAX_DIGEST_SIZE
706+
707+
static int whTest_CryptoEccCrossVerify_OneCurve(whClientContext* ctx,
708+
WC_RNG* rng,
709+
int keySize,
710+
int curveId,
711+
const char* name)
712+
{
713+
ecc_key hsmKey[1] = {0};
714+
ecc_key swKey[1] = {0};
715+
uint8_t hash[WH_TEST_ECC_HASH_SIZE] = {0};
716+
uint8_t sig[ECC_MAX_SIG_SIZE] = {0};
717+
uint8_t pubX[ECC_MAXSIZE] = {0};
718+
uint8_t pubY[ECC_MAXSIZE] = {0};
719+
word32 pubXLen = 0;
720+
word32 pubYLen = 0;
721+
word32 sigLen = 0;
722+
int res = 0;
723+
whKeyId keyId = WH_KEYID_ERASED;
724+
int hsmKeyInit = 0;
725+
int swKeyInit = 0;
726+
int ret = WH_ERROR_OK;
727+
int i;
728+
729+
/* Use non-repeating pattern to detect hash truncation bugs */
730+
for (i = 0; i < WH_TEST_ECC_HASH_SIZE; i++) {
731+
hash[i] = (uint8_t)i;
732+
}
733+
734+
WH_TEST_PRINT(" Testing %s curve...\n", name);
735+
736+
pubXLen = keySize;
737+
pubYLen = keySize;
738+
739+
/* Test 1: HSM sign + Software verify */
740+
ret = wc_ecc_init_ex(hsmKey, NULL, WH_DEV_ID);
741+
if (ret != 0) {
742+
WH_ERROR_PRINT("%s: Failed to init HSM key: %d\n", name, ret);
743+
}
744+
else {
745+
hsmKeyInit = 1;
746+
}
747+
if (ret == 0) {
748+
ret = wc_ecc_make_key(rng, keySize, hsmKey);
749+
if (ret != 0) {
750+
WH_ERROR_PRINT("%s: Failed to generate HSM key: %d\n", name, ret);
751+
}
752+
}
753+
if (ret == 0) {
754+
/* Export public key from HSM */
755+
ret = wc_ecc_export_public_raw(hsmKey, pubX, &pubXLen, pubY, &pubYLen);
756+
if (ret != 0) {
757+
WH_ERROR_PRINT("%s: Failed to export HSM public key: %d\n", name,
758+
ret);
759+
}
760+
}
761+
if (ret == 0) {
762+
/* Sign with HSM */
763+
sigLen = sizeof(sig);
764+
ret = wc_ecc_sign_hash(hash, sizeof(hash), sig, &sigLen, rng, hsmKey);
765+
if (ret != 0) {
766+
WH_ERROR_PRINT("%s: HSM sign failed: %d\n", name, ret);
767+
}
768+
}
769+
if (ret == 0) {
770+
/* Import public key into software key for verification */
771+
ret = wc_ecc_init_ex(swKey, NULL, INVALID_DEVID);
772+
if (ret != 0) {
773+
WH_ERROR_PRINT("%s: Failed to init SW key: %d\n", name, ret);
774+
}
775+
else {
776+
swKeyInit = 1;
777+
}
778+
}
779+
if (ret == 0) {
780+
ret = wc_ecc_import_unsigned(swKey, pubX, pubY, NULL, curveId);
781+
if (ret != 0) {
782+
WH_ERROR_PRINT("%s: Failed to import public to SW: %d\n", name,
783+
ret);
784+
}
785+
}
786+
if (ret == 0) {
787+
/* Verify with software */
788+
res = 0;
789+
ret = wc_ecc_verify_hash(sig, sigLen, hash, sizeof(hash), &res, swKey);
790+
if (ret != 0) {
791+
WH_ERROR_PRINT("%s: SW verify failed: %d\n", name, ret);
792+
}
793+
else if (res != 1) {
794+
WH_ERROR_PRINT("%s: HSM sign + SW verify: signature invalid\n",
795+
name);
796+
ret = -1;
797+
}
798+
else {
799+
WH_TEST_PRINT(" HSM sign + SW verify: PASS\n");
800+
}
801+
}
802+
/* Cleanup Test 1 keys */
803+
if (swKeyInit) {
804+
wc_ecc_free(swKey);
805+
swKeyInit = 0;
806+
}
807+
if (hsmKeyInit) {
808+
if (wh_Client_EccGetKeyId(hsmKey, &keyId) == 0 &&
809+
!WH_KEYID_ISERASED(keyId)) {
810+
(void)wh_Client_KeyEvict(ctx, keyId);
811+
}
812+
wc_ecc_free(hsmKey);
813+
hsmKeyInit = 0;
814+
}
815+
816+
/* Test 2: Software sign + HSM verify */
817+
if (ret == 0) {
818+
memset(sig, 0, sizeof(sig));
819+
memset(pubX, 0, sizeof(pubX));
820+
memset(pubY, 0, sizeof(pubY));
821+
pubXLen = keySize;
822+
pubYLen = keySize;
823+
keyId = WH_KEYID_ERASED;
824+
825+
ret = wc_ecc_init_ex(swKey, NULL, INVALID_DEVID);
826+
if (ret != 0) {
827+
WH_ERROR_PRINT("%s: Failed to init SW key: %d\n", name, ret);
828+
}
829+
else {
830+
swKeyInit = 1;
831+
}
832+
}
833+
if (ret == 0) {
834+
ret = wc_ecc_make_key(rng, keySize, swKey);
835+
if (ret != 0) {
836+
WH_ERROR_PRINT("%s: Failed to generate SW key: %d\n", name, ret);
837+
}
838+
}
839+
if (ret == 0) {
840+
/* Export public key from software */
841+
ret = wc_ecc_export_public_raw(swKey, pubX, &pubXLen, pubY, &pubYLen);
842+
if (ret != 0) {
843+
WH_ERROR_PRINT("%s: Failed to export SW public key: %d\n", name,
844+
ret);
845+
}
846+
}
847+
if (ret == 0) {
848+
/* Sign with software */
849+
sigLen = sizeof(sig);
850+
ret = wc_ecc_sign_hash(hash, sizeof(hash), sig, &sigLen, rng, swKey);
851+
if (ret != 0) {
852+
WH_ERROR_PRINT("%s: SW sign failed: %d\n", name, ret);
853+
}
854+
}
855+
if (ret == 0) {
856+
/* Import public key into HSM key for verification */
857+
ret = wc_ecc_init_ex(hsmKey, NULL, WH_DEV_ID);
858+
if (ret != 0) {
859+
WH_ERROR_PRINT("%s: Failed to init HSM key: %d\n", name, ret);
860+
}
861+
else {
862+
hsmKeyInit = 1;
863+
}
864+
}
865+
if (ret == 0) {
866+
ret = wc_ecc_import_unsigned(hsmKey, pubX, pubY, NULL, curveId);
867+
if (ret != 0) {
868+
WH_ERROR_PRINT("%s: Failed to import public to HSM: %d\n", name,
869+
ret);
870+
}
871+
}
872+
if (ret == 0) {
873+
/* Verify with HSM */
874+
res = 0;
875+
ret = wc_ecc_verify_hash(sig, sigLen, hash, sizeof(hash), &res, hsmKey);
876+
if (ret != 0) {
877+
WH_ERROR_PRINT("%s: HSM verify failed: %d\n", name, ret);
878+
}
879+
else if (res != 1) {
880+
WH_ERROR_PRINT("%s: SW sign + HSM verify: signature invalid\n",
881+
name);
882+
ret = -1;
883+
}
884+
else {
885+
WH_TEST_PRINT(" SW sign + HSM verify: PASS\n");
886+
}
887+
}
888+
/* Cleanup Test 2 keys */
889+
if (hsmKeyInit) {
890+
if (wh_Client_EccGetKeyId(hsmKey, &keyId) == 0 &&
891+
!WH_KEYID_ISERASED(keyId)) {
892+
(void)wh_Client_KeyEvict(ctx, keyId);
893+
}
894+
wc_ecc_free(hsmKey);
895+
}
896+
if (swKeyInit) {
897+
wc_ecc_free(swKey);
898+
}
899+
900+
return ret;
901+
}
902+
903+
/**
904+
* Test ECDSA cross-verification between HSM and software implementations.
905+
* This detects bugged hardware that might verify its own bad signatures.
906+
*
907+
* Tests two scenarios per curve:
908+
* 1. HSM sign + Software verify
909+
* 2. Software sign + HSM verify
910+
*/
911+
static int whTest_CryptoEccCrossVerify(whClientContext* ctx, WC_RNG* rng)
912+
{
913+
int ret = WH_ERROR_OK;
914+
915+
WH_TEST_PRINT("Testing ECDSA cross-verification (HSM<->SW)...\n");
916+
917+
#if !defined(NO_ECC256)
918+
if (ret == 0) {
919+
ret = whTest_CryptoEccCrossVerify_OneCurve(
920+
ctx, rng, WH_TEST_ECC_P256_KEY_SIZE, ECC_SECP256R1, "P-256");
921+
}
922+
#endif
923+
924+
#if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
925+
if (ret == 0) {
926+
ret = whTest_CryptoEccCrossVerify_OneCurve(
927+
ctx, rng, WH_TEST_ECC_P384_KEY_SIZE, ECC_SECP384R1, "P-384");
928+
}
929+
#endif
930+
931+
#if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
932+
if (ret == 0) {
933+
ret = whTest_CryptoEccCrossVerify_OneCurve(
934+
ctx, rng, WH_TEST_ECC_P521_KEY_SIZE, ECC_SECP521R1, "P-521");
935+
}
936+
#endif
937+
938+
if (ret == 0) {
939+
WH_TEST_PRINT("ECDSA cross-verification SUCCESS\n");
940+
}
941+
942+
return ret;
943+
}
944+
#endif /* HAVE_ECC_SIGN && HAVE_ECC_VERIFY && !WOLF_CRYPTO_CB_ONLY_ECC */
693945
#endif /* HAVE_ECC */
694946

695947
#ifdef HAVE_ED25519
@@ -5146,6 +5398,12 @@ int whTest_CryptoClientConfig(whClientConfig* config)
51465398
if (ret == 0) {
51475399
ret = whTest_CryptoEccCacheDuplicate(client);
51485400
}
5401+
#if defined(HAVE_ECC_SIGN) && defined(HAVE_ECC_VERIFY) && \
5402+
!defined(WOLF_CRYPTO_CB_ONLY_ECC)
5403+
if (ret == 0) {
5404+
ret = whTest_CryptoEccCrossVerify(client, rng);
5405+
}
5406+
#endif
51495407
#endif /* HAVE_ECC */
51505408

51515409
#ifdef HAVE_ED25519

0 commit comments

Comments
 (0)