From 5fe6f1c875acb1adbc0701f7d98151dc147f29c2 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 17 Mar 2022 14:41:35 -0700 Subject: [PATCH 1/8] For KCAPI do not force enable ECC curves, set K or seed callback, disable AES GCM tests with non standard IV. --- configure.ac | 39 ++++++++++++++++++++---------------- wolfcrypt/test/test.c | 12 +++++++---- wolfssl/wolfcrypt/settings.h | 3 +++ 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/configure.ac b/configure.ac index 668dd2f31..72e394fec 100644 --- a/configure.ac +++ b/configure.ac @@ -2075,19 +2075,21 @@ then AS_IF([test "$enable_kcapi_hash" != "no"], [ENABLED_KCAPI_HASH=yes]) AS_IF([test "$enable_kcapi_hmac" != "no"], [ENABLED_KCAPI_HMAC=yes]) AS_IF([test "$enable_kcapi_aes" != "no"], [ENABLED_KCAPI_AES=yes]) -# currently the PK alg KCAPI options run into build failures, so disabling here for now. -# AS_IF([test "$enable_kcapi_rsa" != "no"], [ENABLED_KCAPI_RSA=yes]) -# AS_IF([test "$enable_kcapi_dh" != "no"], [ENABLED_KCAPI_DH=yes]) -# AS_IF([test "$enable_kcapi_ecc" != "no"], [ENABLED_KCAPI_ECC=yes]) + AS_IF([test "$enable_kcapi_rsa" != "no"], [ENABLED_KCAPI_RSA=yes]) + AS_IF([test "$enable_kcapi_dh" != "no"], [ENABLED_KCAPI_DH=yes]) + AS_IF([test "$enable_kcapi_ecc" != "no"], [ENABLED_KCAPI_ECC=yes]) fi -AS_IF([test "$ENABLED_KCAPI_HASH" != "no" || - test "$ENABLED_KCAPI_HMAC" != "no" || - test "$ENABLED_KCAPI_AES" != "no" || - test "$ENABLED_KCAPI_RSA" != "no" || - test "$ENABLED_KCAPI_DH" != "no" || - test "$ENABLED_KCAPI_ECC" != "no"], - [LIBS="$LIBS -lkcapi"]) +if test "$ENABLED_KCAPI_HASH" != "no" || + test "$ENABLED_KCAPI_HMAC" != "no" || + test "$ENABLED_KCAPI_AES" != "no" || + test "$ENABLED_KCAPI_RSA" != "no" || + test "$ENABLED_KCAPI_DH" != "no" || + test "$ENABLED_KCAPI_ECC" != "no" +then + LIBS="$LIBS -lkcapi" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KCAPI" +fi if test "$ENABLED_KCAPI_HASH" = "yes" then @@ -3594,16 +3596,10 @@ AS_CASE([$FIPS_VERSION], -DHAVE_FIPS_VERSION_MINOR=$HAVE_FIPS_VERSION_MINOR \ -DHAVE_ECC_CDH \ -DWC_RSA_NO_PADDING \ - -DWOLFSSL_ECDSA_SET_K \ -DWOLFSSL_VALIDATE_ECC_IMPORT \ -DECC_USER_CURVES \ - -DHAVE_ECC192 \ - -DHAVE_ECC224 \ - -DHAVE_ECC256 \ -DHAVE_ECC384 \ -DHAVE_ECC521 \ - -DWOLFSSL_ECDSA_SET_K \ - -DWC_RNG_SEED_CB \ -DWOLFSSL_VALIDATE_FFC_IMPORT \ -DHAVE_FFDHE_Q \ -DHAVE_FFDHE_3072 \ @@ -3611,6 +3607,15 @@ AS_CASE([$FIPS_VERSION], -DHAVE_FFDHE_6144 \ -DHAVE_FFDHE_8192" + # KCAPI API does not support custom k for sign, don't force enable ECC key sizes and do not use seed callback + AS_IF([test "x$ENABLED_KCAPI_ECC" = "xno"], + [AM_CFLAGS="$AM_CFLAGS \ + -DWC_RNG_SEED_CB \ + -DWOLFSSL_ECDSA_SET_K \ + -DHAVE_ECC192 \ + -DHAVE_ECC224 \ + -DHAVE_ECC256"]) + DEFAULT_MAX_CLASSIC_ASYM_KEY_BITS=8192 # force various features to FIPS 140-3 defaults, unless overridden with v5-dev: diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 4cbab9b33..31d59a835 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -1120,13 +1120,15 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ return err_sys("AES-GCM test failed!\n", ret); #endif #if !defined(WOLFSSL_AFALG_XILINX_AES) && !defined(WOLFSSL_XILINX_CRYPT) && \ - !(defined(WOLF_CRYPTO_CB) && \ + !defined(WOLFSSL_KCAPI_AES) && !(defined(WOLF_CRYPTO_CB) && \ (defined(HAVE_INTEL_QA_SYNC) || defined(HAVE_CAVIUM_OCTEON_SYNC))) if ((ret = aesgcm_default_test()) != 0) { return err_sys("AES-GCM test failed!\n", ret); } #endif - TEST_PASS("AES-GCM test passed!\n"); + if (ret == 0) { + TEST_PASS("AES-GCM test passed!\n"); + } #endif #if defined(HAVE_AESCCM) && defined(WOLFSSL_AES_128) @@ -21039,7 +21041,8 @@ done: #endif -#if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_SET_K) +#if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_SET_K) && \ + !defined(WOLFSSL_KCAPI_ECC) static int ecc_test_sign_vectors(WC_RNG* rng) { int ret; @@ -24118,7 +24121,8 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test(void) #endif #endif -#if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_SET_K) +#if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_SET_K) && \ + !defined(WOLFSSL_KCAPI_ECC) ret = ecc_test_sign_vectors(&rng); if (ret != 0) { printf("ecc_test_sign_vectors failed! %d\n", ret); diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 6484387f1..22c09269e 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -1627,9 +1627,12 @@ extern void uITRON4_free(void *p) ; #define WOLFSSL_AES_GCM_FIXED_IV_AAD #endif #ifdef WOLFSSL_KCAPI_ECC + #undef ECC_USER_CURVES #define ECC_USER_CURVES #undef NO_ECC256 + #undef HAVE_ECC384 #define HAVE_ECC384 + #undef HAVE_ECC521 #define HAVE_ECC521 #endif From 1b0e5f4806bc75ceb3d2eb1f6beffe8507fa0624 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 17 Mar 2022 14:42:23 -0700 Subject: [PATCH 2/8] Allow disabling DRBG with KCAPI. Add KCAPI `/dev/hwrng` support. --- configure.ac | 4 ++-- wolfcrypt/src/random.c | 29 +++++++++++++++++++++++++++-- wolfssl/wolfcrypt/random.h | 5 +++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 72e394fec..15e753b2c 100644 --- a/configure.ac +++ b/configure.ac @@ -3888,8 +3888,8 @@ if test "x$ENABLED_HASHDRBG" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_HASHDRBG" else - # turn on Hash DRBG if FIPS is on - if test "x$ENABLED_FIPS" = "xyes" + # turn on Hash DRBG if FIPS is on (don't force on for KCAPI) + if test "x$ENABLED_FIPS" = "xyes" && test "x$ENABLED_KCAPI" = "xno" then AM_CFLAGS="$AM_CFLAGS -DHAVE_HASHDRBG" ENABLED_HASHDRBG=yes diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index d2bb66329..14e3ca202 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -2786,8 +2786,33 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } #endif - - /* End wc_GenerateSeed */ + +#if defined(CUSTOM_RAND_GENERATE_BLOCK) && defined(WOLFSSL_KCAPI) +#include +int wc_hwrng_generate_block(byte *output, word32 sz) +{ + int fd; + int len; + int ret = 0; + fd = open("/dev/hwrng", O_RDONLY); + if (fd == -1) + return OPEN_RAN_E; + while(sz) + { + len = (int)read(fd, output, sz); + if (len == -1) + { + ret = READ_RAN_E; + break; + } + sz -= len; + output += len; + } + close(fd); + return ret; +} +#endif + #endif /* WC_NO_RNG */ #endif /* HAVE_FIPS */ diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index 963596dfb..ff4ef0de5 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -99,6 +99,11 @@ * #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc * extern int myRngFunc(byte* output, word32 sz); */ + #if defined(CUSTOM_RAND_GENERATE_BLOCK) && defined(WOLFSSL_KCAPI) + #undef CUSTOM_RAND_GENERATE_BLOCK + #define CUSTOM_RAND_GENERATE_BLOCK wc_hwrng_generate_block + WOLFSSL_LOCAL int wc_hwrng_generate_block(byte *output, word32 sz); + #endif #elif defined(HAVE_HASHDRBG) #ifdef NO_SHA256 #error "Hash DRBG requires SHA-256." From 9f2dc408a0970efa04935108c8a128fb7f8edf56 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 17 Mar 2022 14:44:11 -0700 Subject: [PATCH 3/8] Fixes for KCAPI AES GCM. Add guards for algorithm macros on KCAPI. --- wolfcrypt/src/port/kcapi/kcapi_aes.c | 72 ++++++++++++++++----------- wolfcrypt/src/port/kcapi/kcapi_dh.c | 4 +- wolfcrypt/src/port/kcapi/kcapi_ecc.c | 4 +- wolfcrypt/src/port/kcapi/kcapi_hash.c | 1 - wolfcrypt/src/port/kcapi/kcapi_hmac.c | 5 +- wolfcrypt/src/port/kcapi/kcapi_rsa.c | 5 +- 6 files changed, 51 insertions(+), 40 deletions(-) diff --git a/wolfcrypt/src/port/kcapi/kcapi_aes.c b/wolfcrypt/src/port/kcapi/kcapi_aes.c index e29099304..5eb89602d 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_aes.c +++ b/wolfcrypt/src/port/kcapi/kcapi_aes.c @@ -234,8 +234,8 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, { int ret = 0; byte* data = NULL; - word32 dataSz = authInSz + sz + authTagSz; - ssize_t rc; + word32 dataSz; + int inbuflen, outbuflen; size_t pageSz = (size_t)sysconf(_SC_PAGESIZE); /* argument checks */ @@ -255,16 +255,22 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, } if (ret == 0) { - ret = posix_memalign((void*)&data, pageSz, dataSz); - if (ret < 0) { - ret = MEMORY_E; + ret = kcapi_aead_init(&aes->handle, WC_NAME_AESGCM, 0); + if (ret != 0) { + WOLFSSL_MSG("Error with first time setup of kcapi"); } } if (ret == 0) { - ret = kcapi_aead_init(&aes->handle, WC_NAME_AESGCM, 0); - if (ret != 0) { - WOLFSSL_MSG("Error with first time setup of kcapi"); + inbuflen = (int)kcapi_aead_inbuflen_enc( aes->handle, sz, authInSz, + authTagSz); + outbuflen = (int)kcapi_aead_outbuflen_enc(aes->handle, sz, authInSz, + authTagSz); + dataSz = (inbuflen > outbuflen) ? inbuflen : outbuflen; + + ret = posix_memalign((void*)&data, pageSz, dataSz); + if (ret < 0) { + ret = MEMORY_E; } } @@ -287,16 +293,18 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, XMEMCPY(data, authIn, authInSz); XMEMCPY(data + authInSz, in, sz); - rc = kcapi_aead_encrypt(aes->handle, data, dataSz, iv, data, dataSz, - KCAPI_ACCESS_HEURISTIC); - if (rc < 0) { + ret = (int)kcapi_aead_encrypt(aes->handle, data, inbuflen, iv, data, + outbuflen, KCAPI_ACCESS_HEURISTIC); + if (ret < 0) { WOLFSSL_MSG("GcmEncrypt failed"); - ret = (int)rc; } - else if ((word32)rc != dataSz) { + else if (ret != outbuflen) { WOLFSSL_MSG("GcmEncrypt produced wrong output length"); ret = BAD_FUNC_ARG; } + else { + ret = 0; /* success */ + } } if (ret == 0) { @@ -327,9 +335,8 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, { int ret = 0; byte* data = NULL; - word32 dataSz = authInSz + sz + authTagSz; - word32 outSz = authInSz + sz; - ssize_t rc; + word32 dataSz; + int inbuflen, outbuflen; size_t pageSz = (size_t)sysconf(_SC_PAGESIZE); /* argument checks */ @@ -350,16 +357,22 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, } if (ret == 0) { - ret = posix_memalign((void*)&data, pageSz, dataSz); - if (ret < 0) { - ret = MEMORY_E; + ret = kcapi_aead_init(&aes->handle, WC_NAME_AESGCM, 0); + if (ret != 0) { + WOLFSSL_MSG("Error with first time setup of kcapi"); } } if (ret == 0) { - ret = kcapi_aead_init(&aes->handle, WC_NAME_AESGCM, 0); - if (ret != 0) { - WOLFSSL_MSG("Error with first time setup of kcapi"); + inbuflen = (int)kcapi_aead_inbuflen_dec( aes->handle, sz, authInSz, + authTagSz); + outbuflen = (int)kcapi_aead_outbuflen_dec(aes->handle, sz, authInSz, + authTagSz); + dataSz = (inbuflen > outbuflen) ? inbuflen : outbuflen; + + ret = posix_memalign((void*)&data, pageSz, dataSz); + if (ret < 0) { + ret = MEMORY_E; } } @@ -380,19 +393,20 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, XMEMCPY(data + authInSz, in, sz); XMEMCPY(data + authInSz + sz, authTag, authTagSz); - rc = kcapi_aead_decrypt(aes->handle, data, dataSz, iv, data, outSz, - KCAPI_ACCESS_HEURISTIC); - if (rc < 0) { + ret = (int)kcapi_aead_decrypt(aes->handle, data, inbuflen, iv, data, + outbuflen, KCAPI_ACCESS_HEURISTIC); + if (ret < 0) { WOLFSSL_MSG("GcmDecrypt failed"); - if (rc == -EBADMSG) + if (ret == -EBADMSG) ret = AES_GCM_AUTH_E; - else - ret = (int)rc; } - else if ((word32)rc != outSz) { + else if (ret != outbuflen) { WOLFSSL_MSG("GcmDecrypt produced wrong output length"); ret = BAD_FUNC_ARG; } + else { + ret = 0; /* success */ + } } if (ret == 0) { diff --git a/wolfcrypt/src/port/kcapi/kcapi_dh.c b/wolfcrypt/src/port/kcapi/kcapi_dh.c index f62f13848..72c65ead5 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_dh.c +++ b/wolfcrypt/src/port/kcapi/kcapi_dh.c @@ -26,7 +26,7 @@ #include -#if defined(WOLFSSL_KCAPI_DH) +#if defined(WOLFSSL_KCAPI_DH) && !defined(NO_DH) #include #include @@ -232,4 +232,4 @@ int KcapiDh_SharedSecret(DhKey* private_key, const byte* pub, word32 pubSz, return ret; } -#endif /* WOLFSSL_KCAPI_DH */ +#endif /* WOLFSSL_KCAPI_DH && !NO_DH */ diff --git a/wolfcrypt/src/port/kcapi/kcapi_ecc.c b/wolfcrypt/src/port/kcapi/kcapi_ecc.c index 54c483495..d4b9cc74d 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_ecc.c +++ b/wolfcrypt/src/port/kcapi/kcapi_ecc.c @@ -26,7 +26,7 @@ #include -#if defined(WOLFSSL_KCAPI_ECC) +#if defined(WOLFSSL_KCAPI_ECC) && defined(HAVE_ECC) #include #include @@ -367,4 +367,4 @@ int KcapiEcc_Verify(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, } #endif -#endif /* WOLFSSL_KCAPI_ECC */ +#endif /* WOLFSSL_KCAPI_ECC && HAVE_ECC */ diff --git a/wolfcrypt/src/port/kcapi/kcapi_hash.c b/wolfcrypt/src/port/kcapi/kcapi_hash.c index 47976e543..a14957b40 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_hash.c +++ b/wolfcrypt/src/port/kcapi/kcapi_hash.c @@ -642,4 +642,3 @@ int wc_Sha512_256Copy(wc_Sha512* src, wc_Sha512* dst) #endif /* WOLFSSL_SHA512 */ #endif /* WOLFSSL_KCAPI_HASH */ - diff --git a/wolfcrypt/src/port/kcapi/kcapi_hmac.c b/wolfcrypt/src/port/kcapi/kcapi_hmac.c index 41d06da0f..525001536 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_hmac.c +++ b/wolfcrypt/src/port/kcapi/kcapi_hmac.c @@ -26,7 +26,7 @@ #include -#if defined(WOLFSSL_KCAPI_HMAC) +#if defined(WOLFSSL_KCAPI_HMAC) && !defined(NO_HMAC) #define FIPS_NO_WRAPPERS @@ -334,5 +334,4 @@ int wc_HmacFinal(Hmac* hmac, byte* hash) return ret; } -#endif /* WOLFSSL_KCAPI_HMAC */ - +#endif /* WOLFSSL_KCAPI_HMAC && !NO_HMAC */ diff --git a/wolfcrypt/src/port/kcapi/kcapi_rsa.c b/wolfcrypt/src/port/kcapi/kcapi_rsa.c index 828c4c1c8..f11ee2fb7 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_rsa.c +++ b/wolfcrypt/src/port/kcapi/kcapi_rsa.c @@ -26,7 +26,7 @@ #include -#if defined(WOLFSSL_KCAPI_RSA) +#if defined(WOLFSSL_KCAPI_RSA) && !defined(NO_RSA) #include #include @@ -356,5 +356,4 @@ int KcapiRsa_Encrypt(RsaKey* key, const byte* in, word32 inLen, byte* out, return ret; } -#endif /* WOLFSSL_KCAPI_RSA */ - +#endif /* WOLFSSL_KCAPI_RSA && !NO_RSA */ From 318350f63bb8bb45c49dcc5bb9bb74b1fd9882cb Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 17 Mar 2022 14:47:29 -0700 Subject: [PATCH 4/8] Fix for `ecc_check_privkey_gen` with KCAPI. Fix KCAPI ECDSA to ensure we don't leak handle for multiple sign/verify calls. --- wolfcrypt/src/ecc.c | 58 ++++------ wolfcrypt/src/port/kcapi/kcapi_ecc.c | 136 +++++++++++++++-------- wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h | 20 ++-- 3 files changed, 123 insertions(+), 91 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index fe44ca04c..2f5c775ee 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -8604,10 +8604,6 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) int err; ecc_point* base = NULL; ecc_point* res = NULL; -#ifdef WOLFSSL_KCAPI_ECC - ecc_key pubKey; - word32 len; -#endif #ifdef WOLFSSL_NO_MALLOC ecc_point lcl_base; ecc_point lcl_res; @@ -8672,7 +8668,27 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) if (err == MP_OKAY) err = mp_set(base->z, 1); -#ifndef WOLFSSL_KCAPI_ECC +#ifdef WOLFSSL_KCAPI_ECC + if (err == MP_OKAY) { + byte pubkey_raw[MAX_ECC_BYTES * 2]; + word32 pubkey_sz = (word32)sizeof(pubkey_raw); + + err = KcapiEcc_LoadKey(key, pubkey_raw, &pubkey_sz); + if (err == 0) { + err = mp_read_unsigned_bin(res->x, pubkey_raw, + pubkey_sz/2); + } + if (err == MP_OKAY) { + err = mp_read_unsigned_bin(res->y, pubkey_raw + pubkey_sz/2, + pubkey_sz/2); + } + if (err == MP_OKAY) { + err = mp_set(res->z, 1); + } + } + (void)a; + (void)prime; +#else #ifdef ECC_TIMING_RESISTANT if (err == MP_OKAY) err = wc_ecc_mulmod_ex2(&key->k, base, res, a, prime, curve->order, @@ -8682,29 +8698,10 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) err = wc_ecc_mulmod_ex2(&key->k, base, res, a, prime, curve->order, NULL, 1, key->heap); #endif -#else - /* Using Shared Secret to perform scalar multiplication - * Calculates the x ordinidate only. - */ - if (err == MP_OKAY) { - err = wc_ecc_init(&pubKey); - if (err == MP_OKAY) { - wc_ecc_copy_point(base, &pubKey.pubkey); - } - if (err == MP_OKAY) { - err = KcapiEcc_SetPubKey(&pubKey); - } - if (err == MP_OKAY) { - len = key->dp->size; - err = KcapiEcc_SharedSecret(key, &pubKey, pubKey.pubkey_raw, - &len); - } - } -#endif /* !WOLFSSL_KCAPI_ECC */ +#endif /* WOLFSSL_KCAPI_ECC */ } if (err == MP_OKAY) { -#ifndef WOLFSSL_KCAPI_ECC /* compare result to public key */ if (mp_cmp(res->x, key->pubkey.x) != MP_EQ || mp_cmp(res->y, key->pubkey.y) != MP_EQ || @@ -8712,17 +8709,6 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) /* didn't match */ err = ECC_PRIV_KEY_E; } -#else - err = mp_read_unsigned_bin(pubKey.pubkey.x, pubKey.pubkey_raw, len); - /* compare result to public key - y can be negative! */ - if (err == MP_OKAY && ((!mp_isone(res->z)) || - mp_cmp(pubKey.pubkey.x, key->pubkey.x) != MP_EQ)) { - /* didn't match */ - err = ECC_PRIV_KEY_E; - } - (void)a; - (void)prime; -#endif } wc_ecc_curve_free(curve); diff --git a/wolfcrypt/src/port/kcapi/kcapi_ecc.c b/wolfcrypt/src/port/kcapi/kcapi_ecc.c index d4b9cc74d..8cf8cd067 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_ecc.c +++ b/wolfcrypt/src/port/kcapi/kcapi_ecc.c @@ -34,6 +34,9 @@ #include #include +#ifndef ECC_CURVE_NIST_P256 +#define ECC_CURVE_NIST_P256 2 +#endif #ifndef ECC_CURVE_NIST_P384 #define ECC_CURVE_NIST_P384 3 #endif @@ -79,70 +82,96 @@ static int KcapiEcc_CurveId(int curve_id, word32* kcapiCurveId) return ret; } -int KcapiEcc_MakeKey(ecc_key* key, int keysize, int curve_id) +int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz) { int ret = 0; - int sz = 0; - word32 kcapiCurveId; + word32 kcapiCurveId = 0; - if (curve_id == ECC_CURVE_DEF) { - switch (keysize) { - case 32: - curve_id = ECC_SECP256R1; - break; - case 48: - curve_id = ECC_SECP384R1; - break; - case 66: - curve_id = ECC_SECP521R1; - break; - default: - ret = BAD_FUNC_ARG; - break; - } - } - if (ret == 0) { - ret = KcapiEcc_CurveId(curve_id, &kcapiCurveId); + if (key == NULL || key->dp == NULL) { + ret = BAD_FUNC_ARG; } - if (key->handle != NULL) { - kcapi_kpp_destroy(key->handle); - key->handle = NULL; - } if (ret == 0) { + ret = KcapiEcc_CurveId(key->dp->id, &kcapiCurveId); + } + + /* if handle doesn't exist create one */ + if (ret == 0 && key->handle == NULL) { ret = kcapi_kpp_init(&key->handle, WC_NAME_ECDH, 0); - if (ret != 0) { - WOLFSSL_MSG("KcapiEcc_MakeKey: Failed to initialize"); + if (ret == 0) { + ret = kcapi_kpp_ecdh_setcurve(key->handle, kcapiCurveId); + if (ret >= 0) { + ret = 0; + } } } - if (ret == 0) { - ret = kcapi_kpp_ecdh_setcurve(key->handle, kcapiCurveId); + + /* if a private key value is set, load and use it. + * otherwise use existing key->handle */ + if (ret == 0 && mp_iszero(&key->k) != MP_YES) { + byte priv[MAX_ECC_BYTES]; + word32 keySz = key->dp->size; + ret = wc_export_int(&key->k, priv, &keySz, keySz, WC_TYPE_UNSIGNED_BIN); + if (ret == 0) { + ret = kcapi_kpp_setkey(key->handle, priv, keySz); + if (ret >= 0) { + ret = 0; + } + } } - if (ret == 0) { - ret = kcapi_kpp_setkey(key->handle, NULL, 0); + + /* optionally load public key */ + if (ret == 0 && pubkey_raw != NULL && pubkey_sz != NULL) { + ret = (int)kcapi_kpp_keygen(key->handle, pubkey_raw, *pubkey_sz, + KCAPI_ACCESS_HEURISTIC); if (ret >= 0) { + *pubkey_sz = ret; ret = 0; } } - if (ret == 0) { - sz = ret = (int)kcapi_kpp_keygen(key->handle, key->pubkey_raw, - sizeof(key->pubkey_raw), KCAPI_ACCESS_HEURISTIC); + + return ret; +} + +int KcapiEcc_MakeKey(ecc_key* key, int keysize, int curve_id) +{ + int ret = 0; + word32 pubkey_sz = (word32)sizeof(key->pubkey_raw); + + /* free existing handle */ + if (key != NULL && key->handle != NULL) { + kcapi_kpp_destroy(key->handle); + key->handle = NULL; } - if (ret >= 0) { - ret = mp_read_unsigned_bin(key->pubkey.x, key->pubkey_raw, sz / 2); + + /* check arguments */ + if (key == NULL || key->dp == NULL) { + ret = BAD_FUNC_ARG; + } + + ret = KcapiEcc_LoadKey(key, key->pubkey_raw, &pubkey_sz); + if (ret == 0) { + ret = mp_read_unsigned_bin(key->pubkey.x, + key->pubkey_raw, pubkey_sz / 2); } if (ret == 0) { - ret = mp_read_unsigned_bin(key->pubkey.y, key->pubkey_raw + sz / 2, - sz / 2); + ret = mp_read_unsigned_bin(key->pubkey.y, + key->pubkey_raw + pubkey_sz / 2, pubkey_sz / 2); } if (ret == 0) { key->type = ECC_PRIVATEKEY; } - if ((ret != 0) && (key->handle != NULL)) { + + /* if error release handle now */ + if (ret != 0 && key->handle != NULL) { kcapi_kpp_destroy(key->handle); key->handle = NULL; } + /* These are not used. The key->dp is set */ + (void)keysize; + (void)curve_id; + return ret; } @@ -163,11 +192,14 @@ int KcapiEcc_SharedSecret(ecc_key* private_key, ecc_key* public_key, byte* out, ret = kcapi_kpp_init(&private_key->handle, WC_NAME_ECDH, 0); if (ret == 0) { ret = kcapi_kpp_ecdh_setcurve(private_key->handle, kcapiCurveId); + if (ret >= 0) { + ret = 0; + } } } /* if a private key value is set, load and use it */ - if (mp_iszero(&private_key->k) != MP_YES) { + if (ret == 0 && mp_iszero(&private_key->k) != MP_YES) { byte priv[MAX_ECC_BYTES]; word32 keySz = private_key->dp->size; ret = wc_export_int(&private_key->k, priv, &keySz, keySz, @@ -254,6 +286,7 @@ int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, byte* hash_aligned = NULL; byte* sig_aligned = NULL; size_t pageSz = (size_t)sysconf(_SC_PAGESIZE); + int handleInit = 0; if (key->handle == NULL) { ret = kcapi_akcipher_init(&key->handle, WC_NAME_ECDSA, 0); @@ -261,6 +294,7 @@ int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, WOLFSSL_MSG("KcapiEcc_Sign: Failed to initialize"); } if (ret == 0) { + handleInit = 1; ret = KcapiEcc_SetPrivKey(key); } } @@ -282,8 +316,7 @@ int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, XMEMCPY(hash_aligned, hash, hashLen); } ret = (int)kcapi_akcipher_sign(key->handle, hash_aligned, hashLen, - sig_aligned, *sigLen, - KCAPI_ACCESS_HEURISTIC); + sig_aligned, *sigLen, KCAPI_ACCESS_HEURISTIC); if (ret >= 0) { *sigLen = ret; ret = 0; @@ -298,6 +331,11 @@ int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, free(buf_aligned); } + if (handleInit) { + kcapi_kpp_destroy(key->handle); + key->handle = NULL; + } + return ret; } #endif @@ -330,17 +368,18 @@ int KcapiEcc_Verify(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, int ret = 0; byte* sigHash_aligned = NULL; size_t pageSz = (size_t)sysconf(_SC_PAGESIZE); + int handleInit = 0; if (key->handle == NULL) { ret = kcapi_akcipher_init(&key->handle, WC_NAME_ECDSA, 0); if (ret != 0) { WOLFSSL_MSG("KcapiEcc_Verify: Failed to initialize"); } + if (ret == 0) { + handleInit = 1; + ret = KcapiEcc_SetPubKey(key); + } } - if (ret == 0) { - ret = KcapiEcc_SetPubKey(key); - } - if (ret == 0) { ret = posix_memalign((void*)&sigHash_aligned, pageSz, sigLen + hashLen); if (ret < 0) { @@ -363,6 +402,11 @@ int KcapiEcc_Verify(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, if (sigHash_aligned != NULL) { free(sigHash_aligned); } + + if (handleInit) { + kcapi_kpp_destroy(key->handle); + key->handle = NULL; + } return ret; } #endif diff --git a/wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h b/wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h index de4359144..234f035f2 100644 --- a/wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h +++ b/wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h @@ -36,16 +36,18 @@ #define WC_ECCKEY_TYPE_DEFINED #endif -int KcapiEcc_SetPubKey(ecc_key* key); +WOLFSSL_LOCAL int KcapiEcc_SetPubKey(ecc_key* key); -void KcapiEcc_Free(ecc_key* key); -int KcapiEcc_MakeKey(ecc_key* key, int keysize, int curve_id); -int KcapiEcc_SharedSecret(ecc_key* private_key, ecc_key* public_key, byte* out, - word32* outlen); -int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, - word32* sigLen); -int KcapiEcc_Verify(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, - word32 sigLen); +WOLFSSL_LOCAL void KcapiEcc_Free(ecc_key* key); +WOLFSSL_LOCAL int KcapiEcc_MakeKey(ecc_key* key, int keysize, int curve_id); +WOLFSSL_LOCAL int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, + word32* pubkey_sz); +WOLFSSL_LOCAL int KcapiEcc_SharedSecret(ecc_key* private_key, + ecc_key* public_key, byte* out, word32* outlen); +WOLFSSL_LOCAL int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, + byte* sig, word32* sigLen); +WOLFSSL_LOCAL int KcapiEcc_Verify(ecc_key* key, const byte* hash, word32 hashLen, + byte* sig, word32 sigLen); #endif /* WOLF_CRYPT_KCAPI_ECC_H */ From 8d695f97c9e3bdf5a911b067f316ff610f90c575 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 18 Mar 2022 07:08:30 -0700 Subject: [PATCH 5/8] Fix for KCAPI `KcapiEcc_LoadKey` parameter to `kcapi_kpp_keygen`. Added option to release handle on load. Fixes for KCAPI sign output length. Added additional argument checking. --- wolfcrypt/src/ecc.c | 4 +- wolfcrypt/src/port/kcapi/kcapi_ecc.c | 69 ++++++++++++++++++------ wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h | 4 +- 3 files changed, 56 insertions(+), 21 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 2f5c775ee..339c9b5ee 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -5572,7 +5572,7 @@ static int wc_ecc_sign_hash_hw(const byte* in, word32 inlen, return err; } #elif defined(WOLFSSL_KCAPI_ECC) - err = KcapiEcc_Sign(key, in, inlen, out, outlen); + err = KcapiEcc_Sign(key, in, inlen, out, *outlen); if (err != MP_OKAY) { return err; } @@ -8673,7 +8673,7 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) byte pubkey_raw[MAX_ECC_BYTES * 2]; word32 pubkey_sz = (word32)sizeof(pubkey_raw); - err = KcapiEcc_LoadKey(key, pubkey_raw, &pubkey_sz); + err = KcapiEcc_LoadKey(key, pubkey_raw, &pubkey_sz, 1); if (err == 0) { err = mp_read_unsigned_bin(res->x, pubkey_raw, pubkey_sz/2); diff --git a/wolfcrypt/src/port/kcapi/kcapi_ecc.c b/wolfcrypt/src/port/kcapi/kcapi_ecc.c index 8cf8cd067..07afee76b 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_ecc.c +++ b/wolfcrypt/src/port/kcapi/kcapi_ecc.c @@ -82,16 +82,19 @@ static int KcapiEcc_CurveId(int curve_id, word32* kcapiCurveId) return ret; } -int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz) +int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz, + int release_handle) { int ret = 0; word32 kcapiCurveId = 0; + word32 keySz; if (key == NULL || key->dp == NULL) { ret = BAD_FUNC_ARG; } if (ret == 0) { + keySz = key->dp->size; ret = KcapiEcc_CurveId(key->dp->id, &kcapiCurveId); } @@ -110,7 +113,6 @@ int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz) * otherwise use existing key->handle */ if (ret == 0 && mp_iszero(&key->k) != MP_YES) { byte priv[MAX_ECC_BYTES]; - word32 keySz = key->dp->size; ret = wc_export_int(&key->k, priv, &keySz, keySz, WC_TYPE_UNSIGNED_BIN); if (ret == 0) { ret = kcapi_kpp_setkey(key->handle, priv, keySz); @@ -122,7 +124,7 @@ int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz) /* optionally load public key */ if (ret == 0 && pubkey_raw != NULL && pubkey_sz != NULL) { - ret = (int)kcapi_kpp_keygen(key->handle, pubkey_raw, *pubkey_sz, + ret = (int)kcapi_kpp_keygen(key->handle, pubkey_raw, keySz*2, KCAPI_ACCESS_HEURISTIC); if (ret >= 0) { *pubkey_sz = ret; @@ -130,6 +132,11 @@ int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz) } } + if (release_handle && key != NULL && key->handle != NULL) { + kcapi_kpp_destroy(key->handle); + key->handle = NULL; + } + return ret; } @@ -149,7 +156,7 @@ int KcapiEcc_MakeKey(ecc_key* key, int keysize, int curve_id) ret = BAD_FUNC_ARG; } - ret = KcapiEcc_LoadKey(key, key->pubkey_raw, &pubkey_sz); + ret = KcapiEcc_LoadKey(key, key->pubkey_raw, &pubkey_sz, 0); if (ret == 0) { ret = mp_read_unsigned_bin(key->pubkey.x, key->pubkey_raw, pubkey_sz / 2); @@ -179,15 +186,24 @@ int KcapiEcc_MakeKey(ecc_key* key, int keysize, int curve_id) int KcapiEcc_SharedSecret(ecc_key* private_key, ecc_key* public_key, byte* out, word32* outlen) { - int ret; + int ret = 0; word32 kcapiCurveId = 0; byte* buf_aligned = NULL; byte* pub_aligned = NULL; byte* out_aligned = NULL; size_t pageSz = (size_t)sysconf(_SC_PAGESIZE); - byte* pub = public_key->pubkey_raw; + byte* pub; + word32 keySz; - ret = KcapiEcc_CurveId(private_key->dp->id, &kcapiCurveId); + if (private_key == NULL || private_key->dp == NULL || public_key == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + pub = public_key->pubkey_raw; + keySz = private_key->dp->size; + ret = KcapiEcc_CurveId(private_key->dp->id, &kcapiCurveId); + } if (ret == 0 && private_key->handle == NULL) { ret = kcapi_kpp_init(&private_key->handle, WC_NAME_ECDH, 0); if (ret == 0) { @@ -201,7 +217,6 @@ int KcapiEcc_SharedSecret(ecc_key* private_key, ecc_key* public_key, byte* out, /* if a private key value is set, load and use it */ if (ret == 0 && mp_iszero(&private_key->k) != MP_YES) { byte priv[MAX_ECC_BYTES]; - word32 keySz = private_key->dp->size; ret = wc_export_int(&private_key->k, priv, &keySz, keySz, WC_TYPE_UNSIGNED_BIN); if (ret == 0) { @@ -221,6 +236,12 @@ int KcapiEcc_SharedSecret(ecc_key* private_key, ecc_key* public_key, byte* out, } } } + if (ret == 0) { + /* validate the output is large enough */ + if (*outlen < keySz*2) { + ret = BUFFER_E; + } + } if (ret == 0) { out_aligned = ((size_t)out % pageSz == 0) ? out : buf_aligned; if ((size_t)pub % pageSz == 0) { @@ -228,14 +249,13 @@ int KcapiEcc_SharedSecret(ecc_key* private_key, ecc_key* public_key, byte* out, } else { pub_aligned = buf_aligned + pageSz; - XMEMCPY(pub_aligned, pub, public_key->dp->size * 2); + XMEMCPY(pub_aligned, pub, keySz * 2); } ret = (int)kcapi_kpp_ssgen(private_key->handle, pub_aligned, - public_key->dp->size * 2, out_aligned, - *outlen, KCAPI_ACCESS_HEURISTIC); + keySz * 2, out_aligned, keySz * 2, KCAPI_ACCESS_HEURISTIC); if (ret >= 0) { - *outlen = ret/2; + *outlen = ret / 2; if (out_aligned != out) { XMEMCPY(out, out_aligned, ret); } @@ -279,7 +299,7 @@ static int KcapiEcc_SetPrivKey(ecc_key* key) } int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, - word32* sigLen) + word32 sigLen) { int ret = 0; byte* buf_aligned = NULL; @@ -287,8 +307,13 @@ int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, byte* sig_aligned = NULL; size_t pageSz = (size_t)sysconf(_SC_PAGESIZE); int handleInit = 0; + word32 keySz; - if (key->handle == NULL) { + if (key == NULL || key->dp == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0 && key->handle == NULL) { ret = kcapi_akcipher_init(&key->handle, WC_NAME_ECDSA, 0); if (ret != 0) { WOLFSSL_MSG("KcapiEcc_Sign: Failed to initialize"); @@ -306,6 +331,13 @@ int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, } } } + if (ret == 0) { + /* make sure signature output is large enough */ + keySz = key->dp->size; + if (sigLen < keySz*2) { + ret = BUFFER_E; + } + } if (ret == 0) { sig_aligned = ((size_t)sig % pageSz == 0) ? sig : buf_aligned; if ((size_t)hash % pageSz == 0) { @@ -316,9 +348,8 @@ int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, XMEMCPY(hash_aligned, hash, hashLen); } ret = (int)kcapi_akcipher_sign(key->handle, hash_aligned, hashLen, - sig_aligned, *sigLen, KCAPI_ACCESS_HEURISTIC); + sig_aligned, keySz*2, KCAPI_ACCESS_HEURISTIC); if (ret >= 0) { - *sigLen = ret; ret = 0; if (sig_aligned != sig) { XMEMCPY(sig, sig_aligned, ret); @@ -370,7 +401,11 @@ int KcapiEcc_Verify(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, size_t pageSz = (size_t)sysconf(_SC_PAGESIZE); int handleInit = 0; - if (key->handle == NULL) { + if (key == NULL || key->dp == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0 && key->handle == NULL) { ret = kcapi_akcipher_init(&key->handle, WC_NAME_ECDSA, 0); if (ret != 0) { WOLFSSL_MSG("KcapiEcc_Verify: Failed to initialize"); diff --git a/wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h b/wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h index 234f035f2..113c18cfe 100644 --- a/wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h +++ b/wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h @@ -41,11 +41,11 @@ WOLFSSL_LOCAL int KcapiEcc_SetPubKey(ecc_key* key); WOLFSSL_LOCAL void KcapiEcc_Free(ecc_key* key); WOLFSSL_LOCAL int KcapiEcc_MakeKey(ecc_key* key, int keysize, int curve_id); WOLFSSL_LOCAL int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, - word32* pubkey_sz); + word32* pubkey_sz, int release_handle); WOLFSSL_LOCAL int KcapiEcc_SharedSecret(ecc_key* private_key, ecc_key* public_key, byte* out, word32* outlen); WOLFSSL_LOCAL int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, - byte* sig, word32* sigLen); + byte* sig, word32 sigLen); WOLFSSL_LOCAL int KcapiEcc_Verify(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, word32 sigLen); From c9e3094cb07eb9664741f3bf318a1d70d099b405 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 18 Mar 2022 11:59:56 -0700 Subject: [PATCH 6/8] Fixes for KCAPI ECC verify. Cleanup of the `pubkey_raw`. Fix KCAPI AES possible used uninitialized. --- wolfcrypt/src/ecc.c | 18 +++---- wolfcrypt/src/port/kcapi/kcapi_aes.c | 4 +- wolfcrypt/src/port/kcapi/kcapi_ecc.c | 64 ++++++++++++++++++------ wolfssl/wolfcrypt/ecc.h | 2 +- wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h | 2 - 5 files changed, 60 insertions(+), 30 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 339c9b5ee..a1c971531 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -8670,16 +8670,16 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) #ifdef WOLFSSL_KCAPI_ECC if (err == MP_OKAY) { - byte pubkey_raw[MAX_ECC_BYTES * 2]; - word32 pubkey_sz = (word32)sizeof(pubkey_raw); + word32 pubkey_sz = (word32)sizeof(key->pubkey_raw); - err = KcapiEcc_LoadKey(key, pubkey_raw, &pubkey_sz, 1); + err = KcapiEcc_LoadKey(key, key->pubkey_raw, &pubkey_sz, 1); if (err == 0) { - err = mp_read_unsigned_bin(res->x, pubkey_raw, + err = mp_read_unsigned_bin(res->x, key->pubkey_raw, pubkey_sz/2); } if (err == MP_OKAY) { - err = mp_read_unsigned_bin(res->y, pubkey_raw + pubkey_sz/2, + err = mp_read_unsigned_bin(res->y, + key->pubkey_raw + pubkey_sz/2, pubkey_sz/2); } if (err == MP_OKAY) { @@ -9190,14 +9190,14 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) /* For SECP256R1 only save raw public key for hardware */ - if (curve_id == ECC_SECP256R1 && inLen <= sizeof(key->pubkey_raw)) { + if (curve_id == ECC_SECP256R1 && inLen <= (word32)sizeof(key->pubkey_raw)) { #ifdef HAVE_COMP_KEY if (!compressed) #endif XMEMCPY(key->pubkey_raw, (byte*)in, inLen); } #elif defined(WOLFSSL_KCAPI_ECC) - XMEMCPY(key->pubkey_raw + KCAPI_PARAM_SZ, (byte*)in, inLen); + XMEMCPY(key->pubkey_raw, (byte*)in, inLen); #endif if (err == MP_OKAY) { @@ -9870,11 +9870,11 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, #elif defined(WOLFSSL_KCAPI_ECC) if (err == MP_OKAY) { word32 keySz = key->dp->size; - err = wc_export_int(key->pubkey.x, key->pubkey_raw + KCAPI_PARAM_SZ, + err = wc_export_int(key->pubkey.x, key->pubkey_raw, &keySz, keySz, WC_TYPE_UNSIGNED_BIN); if (err == MP_OKAY) { err = wc_export_int(key->pubkey.y, - &key->pubkey_raw[KCAPI_PARAM_SZ + keySz], &keySz, keySz, + &key->pubkey_raw[keySz], &keySz, keySz, WC_TYPE_UNSIGNED_BIN); } } diff --git a/wolfcrypt/src/port/kcapi/kcapi_aes.c b/wolfcrypt/src/port/kcapi/kcapi_aes.c index 5eb89602d..4a11a306f 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_aes.c +++ b/wolfcrypt/src/port/kcapi/kcapi_aes.c @@ -235,7 +235,7 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, int ret = 0; byte* data = NULL; word32 dataSz; - int inbuflen, outbuflen; + int inbuflen = 0, outbuflen = 0; size_t pageSz = (size_t)sysconf(_SC_PAGESIZE); /* argument checks */ @@ -336,7 +336,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, int ret = 0; byte* data = NULL; word32 dataSz; - int inbuflen, outbuflen; + int inbuflen = 0, outbuflen = 0; size_t pageSz = (size_t)sysconf(_SC_PAGESIZE); /* argument checks */ diff --git a/wolfcrypt/src/port/kcapi/kcapi_ecc.c b/wolfcrypt/src/port/kcapi/kcapi_ecc.c index 07afee76b..38592b43c 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_ecc.c +++ b/wolfcrypt/src/port/kcapi/kcapi_ecc.c @@ -124,11 +124,16 @@ int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz, /* optionally load public key */ if (ret == 0 && pubkey_raw != NULL && pubkey_sz != NULL) { - ret = (int)kcapi_kpp_keygen(key->handle, pubkey_raw, keySz*2, - KCAPI_ACCESS_HEURISTIC); - if (ret >= 0) { - *pubkey_sz = ret; - ret = 0; + if (*pubkey_sz < keySz*2) { + ret = BUFFER_E; + } + if (ret == 0) { + ret = (int)kcapi_kpp_keygen(key->handle, pubkey_raw, keySz*2, + KCAPI_ACCESS_HEURISTIC); + if (ret >= 0) { + *pubkey_sz = ret; + ret = 0; + } } } @@ -137,7 +142,7 @@ int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz, key->handle = NULL; } - return ret; + return ret; } int KcapiEcc_MakeKey(ecc_key* key, int keysize, int curve_id) @@ -289,9 +294,13 @@ static int KcapiEcc_SetPrivKey(ecc_key* key) WC_TYPE_UNSIGNED_BIN); } if (ret == 0) { - ret = kcapi_akcipher_setkey(key->handle, priv, KCAPI_PARAM_SZ + keySz); + /* call with NULL to so KCAPI treats incoming data as hash */ + ret = kcapi_akcipher_setkey(key->handle, NULL, 0); if (ret >= 0) { - ret = 0; + ret = kcapi_akcipher_setkey(key->handle, priv, KCAPI_PARAM_SZ + keySz); + if (ret >= 0) { + ret = 0; + } } } @@ -356,6 +365,7 @@ int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, } } } + /* Using free as this is in an environment that will have it * available along with posix_memalign. */ if (buf_aligned != NULL) { @@ -373,20 +383,28 @@ int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, #ifdef HAVE_ECC_VERIFY -int KcapiEcc_SetPubKey(ecc_key* key) +static int KcapiEcc_SetPubKey(ecc_key* key) { int ret; - int len = KCAPI_PARAM_SZ + key->dp->size * 2; word32 kcapiCurveId; + word32 keySz = key->dp->size; + byte pub[KCAPI_PARAM_SZ + (MAX_ECC_BYTES * 2)]; + int pubLen; ret = KcapiEcc_CurveId(key->dp->id, &kcapiCurveId); if (ret == 0) { - key->pubkey_raw[0] = ECDSA_KEY_VERSION; - key->pubkey_raw[1] = kcapiCurveId; + pub[0] = ECDSA_KEY_VERSION; + pub[1] = kcapiCurveId; + XMEMCPY(&pub[KCAPI_PARAM_SZ], key->pubkey_raw, keySz * 2); + pubLen = KCAPI_PARAM_SZ + (keySz * 2); - ret = kcapi_akcipher_setpubkey(key->handle, key->pubkey_raw, len); + /* call with NULL to so KCAPI treats incoming data as hash */ + ret = kcapi_akcipher_setpubkey(key->handle, NULL, 0); if (ret >= 0) { - ret = 0; + ret = kcapi_akcipher_setpubkey(key->handle, pub, pubLen); + if (ret >= 0) { + ret = 0; + } } } @@ -400,6 +418,8 @@ int KcapiEcc_Verify(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, byte* sigHash_aligned = NULL; size_t pageSz = (size_t)sysconf(_SC_PAGESIZE); int handleInit = 0; + word32 keySz = 0; + byte* outbuf = NULL; if (key == NULL || key->dp == NULL) { ret = BAD_FUNC_ARG; @@ -421,15 +441,24 @@ int KcapiEcc_Verify(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, ret = MEMORY_E; } } + if (ret == 0) { + keySz = key->dp->size; + ret = posix_memalign((void*)&outbuf, pageSz, keySz * 2); + if (ret < 0) { + ret = MEMORY_E; + } + } if (ret == 0) { XMEMCPY(sigHash_aligned, sig, sigLen); XMEMCPY(sigHash_aligned + sigLen, hash, hashLen); ret = (int)kcapi_akcipher_verify(key->handle, sigHash_aligned, - sigLen + hashLen, NULL, hashLen, KCAPI_ACCESS_HEURISTIC); + sigLen + hashLen, outbuf, keySz * 2, + KCAPI_ACCESS_HEURISTIC); if (ret >= 0) { ret = 0; } + (void)outbuf; /* not used */ } /* Using free as this is in an environment that will have it @@ -437,7 +466,10 @@ int KcapiEcc_Verify(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, if (sigHash_aligned != NULL) { free(sigHash_aligned); } - + if (outbuf != NULL) { + free(outbuf); + } + if (handleInit) { kcapi_kpp_destroy(key->handle); key->handle = NULL; diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 772a36015..a7899837b 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -466,7 +466,7 @@ struct ecc_key { #endif #ifdef WOLFSSL_KCAPI_ECC struct kcapi_handle* handle; - byte pubkey_raw[KCAPI_PARAM_SZ + MAX_ECC_BYTES * 2]; + byte pubkey_raw[MAX_ECC_BYTES * 2]; #endif #ifdef WOLFSSL_ASYNC_CRYPT diff --git a/wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h b/wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h index 113c18cfe..823cafb21 100644 --- a/wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h +++ b/wolfssl/wolfcrypt/port/kcapi/kcapi_ecc.h @@ -36,8 +36,6 @@ #define WC_ECCKEY_TYPE_DEFINED #endif -WOLFSSL_LOCAL int KcapiEcc_SetPubKey(ecc_key* key); - WOLFSSL_LOCAL void KcapiEcc_Free(ecc_key* key); WOLFSSL_LOCAL int KcapiEcc_MakeKey(ecc_key* key, int keysize, int curve_id); WOLFSSL_LOCAL int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, From 8bafa7f601fde14edda1f9a6c2a6804baab44aed Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 21 Mar 2022 11:02:19 -0700 Subject: [PATCH 7/8] Fix for KCAPI ECC sign (was not returning the signature, since ret always 0). --- wolfcrypt/src/port/kcapi/kcapi_ecc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/port/kcapi/kcapi_ecc.c b/wolfcrypt/src/port/kcapi/kcapi_ecc.c index 38592b43c..6a5b1514d 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_ecc.c +++ b/wolfcrypt/src/port/kcapi/kcapi_ecc.c @@ -290,7 +290,7 @@ static int KcapiEcc_SetPrivKey(ecc_key* key) if (ret == 0) { priv[0] = ECDSA_KEY_VERSION; priv[1] = kcapiCurveId; - ret = wc_export_int(&key->k, priv + 2, &keySz, keySz, + ret = wc_export_int(&key->k, priv + KCAPI_PARAM_SZ, &keySz, keySz, WC_TYPE_UNSIGNED_BIN); } if (ret == 0) { @@ -359,10 +359,10 @@ int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, ret = (int)kcapi_akcipher_sign(key->handle, hash_aligned, hashLen, sig_aligned, keySz*2, KCAPI_ACCESS_HEURISTIC); if (ret >= 0) { - ret = 0; if (sig_aligned != sig) { XMEMCPY(sig, sig_aligned, ret); } + ret = 0; /* mark success */ } } From 6e550c8d75b0ef51ba4ad4c295f04b1d72870719 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 21 Mar 2022 11:43:30 -0700 Subject: [PATCH 8/8] Fix for KCAPI ECC KeyGen. Disable ECC consistency checks with KCAPI. Allow public `AddSignature` (used to be public). Fix KCAPI ECC SharedSecret output size. --- wolfcrypt/src/ecc.c | 33 ++++++++++++++------- wolfcrypt/src/port/kcapi/kcapi_ecc.c | 44 ++++++++++++++++------------ wolfcrypt/test/test.c | 14 +++++---- wolfssl/wolfcrypt/asn.h | 2 +- 4 files changed, 59 insertions(+), 34 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index a1c971531..d772cbec3 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -1250,12 +1250,14 @@ static int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen #if !defined(WOLFSSL_SP_MATH) && \ !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \ - !defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_SE050) + !defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_SILABS_SE_ACCEL) && \ + !defined(WOLFSSL_SE050) static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a, mp_int* prime, mp_int* order); #endif static int _ecc_validate_public_key(ecc_key* key, int partial, int priv); -#if FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN) +#if (FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN)) && \ + !defined(WOLFSSL_KCAPI_ECC) static int _ecc_pairwise_consistency_test(ecc_key* key, WC_RNG* rng); #endif @@ -5198,7 +5200,8 @@ int wc_ecc_make_key_ex2(WC_RNG* rng, int keysize, ecc_key* key, int curve_id, err = _ecc_make_key_ex(rng, keysize, key, curve_id, flags); -#if FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN) +#if (FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN)) && \ + !defined(WOLFSSL_KCAPI_ECC) if (err == MP_OKAY) { err = _ecc_validate_public_key(key, 0, 0); } @@ -8670,9 +8673,11 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) #ifdef WOLFSSL_KCAPI_ECC if (err == MP_OKAY) { - word32 pubkey_sz = (word32)sizeof(key->pubkey_raw); - - err = KcapiEcc_LoadKey(key, key->pubkey_raw, &pubkey_sz, 1); + word32 pubkey_sz = (word32)key->dp->size*2; + if (key->handle == NULL) { + /* if handle loaded, then pubkey_raw already populated */ + err = KcapiEcc_LoadKey(key, key->pubkey_raw, &pubkey_sz, 1); + } if (err == 0) { err = mp_read_unsigned_bin(res->x, key->pubkey_raw, pubkey_sz/2); @@ -8721,7 +8726,8 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) #endif /* FIPS_VERSION_GE(5,0) || WOLFSSL_VALIDATE_ECC_KEYGEN || * (!WOLFSSL_SP_MATH && WOLFSSL_VALIDATE_ECC_IMPORT) */ -#if FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN) +#if (FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN)) && \ + !defined(WOLFSSL_KCAPI_ECC) /* check privkey generator helper, creates prime needed */ static int ecc_check_privkey_gen_helper(ecc_key* key) @@ -8740,6 +8746,9 @@ static int ecc_check_privkey_gen_helper(ecc_key* key) #elif defined(WOLFSSL_SILABS_SE_ACCEL) /* Hardware based private key, so this operation is not supported */ err = MP_OKAY; /* just report success */ +#elif defined(WOLFSSL_KCAPI_ECC) + /* Hardware based private key, so this operation is not supported */ + err = MP_OKAY; /* just report success */ #else err = MP_OKAY; ALLOC_CURVE_SPECS(2, err); @@ -8822,7 +8831,7 @@ static int _ecc_pairwise_consistency_test(ecc_key* key, WC_RNG* rng) return err; } -#endif /* FIPS v5 or later || WOLFSSL_VALIDATE_ECC_KEYGEN */ +#endif /* (FIPS v5 or later || WOLFSSL_VALIDATE_ECC_KEYGEN) &&!WOLFSSL_KCAPI_ECC */ #ifndef WOLFSSL_SP_MATH /* validate order * pubkey = point at infinity, 0 on success */ @@ -9082,7 +9091,11 @@ static int _ecc_validate_public_key(ecc_key* key, int partial, int priv) /* private keys must be in the range [1, n-1] */ if ((err == MP_OKAY) && (key->type == ECC_PRIVATEKEY) && (mp_iszero(&key->k) || mp_isneg(&key->k) || - (mp_cmp(&key->k, curve->order) != MP_LT))) { + (mp_cmp(&key->k, curve->order) != MP_LT)) + #ifdef WOLFSSL_KCAPI_ECC + && key->handle == NULL + #endif + ) { err = ECC_PRIV_KEY_E; } @@ -9104,7 +9117,7 @@ static int _ecc_validate_public_key(ecc_key* key, int partial, int priv) #endif FREE_CURVE_SPECS(); -#endif /* WOLFSSL_ATECC508A */ +#endif /* HW Based Crypto */ #else err = WC_KEY_SIZE_E; #endif /* !WOLFSSL_SP_MATH */ diff --git a/wolfcrypt/src/port/kcapi/kcapi_ecc.c b/wolfcrypt/src/port/kcapi/kcapi_ecc.c index 6a5b1514d..631e0593b 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_ecc.c +++ b/wolfcrypt/src/port/kcapi/kcapi_ecc.c @@ -88,6 +88,7 @@ int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz, int ret = 0; word32 kcapiCurveId = 0; word32 keySz; + int handleInit = 0; if (key == NULL || key->dp == NULL) { ret = BAD_FUNC_ARG; @@ -102,6 +103,7 @@ int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz, if (ret == 0 && key->handle == NULL) { ret = kcapi_kpp_init(&key->handle, WC_NAME_ECDH, 0); if (ret == 0) { + handleInit = 1; ret = kcapi_kpp_ecdh_setcurve(key->handle, kcapiCurveId); if (ret >= 0) { ret = 0; @@ -109,20 +111,26 @@ int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz, } } - /* if a private key value is set, load and use it. - * otherwise use existing key->handle */ - if (ret == 0 && mp_iszero(&key->k) != MP_YES) { - byte priv[MAX_ECC_BYTES]; - ret = wc_export_int(&key->k, priv, &keySz, keySz, WC_TYPE_UNSIGNED_BIN); - if (ret == 0) { - ret = kcapi_kpp_setkey(key->handle, priv, keySz); - if (ret >= 0) { - ret = 0; + /* set the key */ + if (ret == 0) { + if (mp_iszero(&key->k) != MP_YES) { + /* if a private key value is set, load and use it */ + byte priv[MAX_ECC_BYTES]; + ret = wc_export_int(&key->k, priv, &keySz, keySz, WC_TYPE_UNSIGNED_BIN); + if (ret == 0) { + ret = kcapi_kpp_setkey(key->handle, priv, keySz); } } + else { + /* generate new ephemeral key */ + ret = kcapi_kpp_setkey(key->handle, NULL, 0); + } + if (ret >= 0) { + ret = 0; + } } - /* optionally load public key */ + /* optionally export public key */ if (ret == 0 && pubkey_raw != NULL && pubkey_sz != NULL) { if (*pubkey_sz < keySz*2) { ret = BUFFER_E; @@ -137,7 +145,7 @@ int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz, } } - if (release_handle && key != NULL && key->handle != NULL) { + if (handleInit && release_handle && key != NULL && key->handle != NULL) { kcapi_kpp_destroy(key->handle); key->handle = NULL; } @@ -170,6 +178,9 @@ int KcapiEcc_MakeKey(ecc_key* key, int keysize, int curve_id) ret = mp_read_unsigned_bin(key->pubkey.y, key->pubkey_raw + pubkey_sz / 2, pubkey_sz / 2); } + if (ret == 0) { + ret = mp_set(key->pubkey.z, 1); + } if (ret == 0) { key->type = ECC_PRIVATEKEY; } @@ -241,12 +252,6 @@ int KcapiEcc_SharedSecret(ecc_key* private_key, ecc_key* public_key, byte* out, } } } - if (ret == 0) { - /* validate the output is large enough */ - if (*outlen < keySz*2) { - ret = BUFFER_E; - } - } if (ret == 0) { out_aligned = ((size_t)out % pageSz == 0) ? out : buf_aligned; if ((size_t)pub % pageSz == 0) { @@ -262,9 +267,12 @@ int KcapiEcc_SharedSecret(ecc_key* private_key, ecc_key* public_key, byte* out, if (ret >= 0) { *outlen = ret / 2; if (out_aligned != out) { + /* don't overflow out */ + if (ret > (int)*outlen) + ret = (int)*outlen; XMEMCPY(out, out_aligned, ret); } - ret = 0; + ret = 0; /* success */ } } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 31d59a835..2c5da8bf2 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -21717,7 +21717,7 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) word32 y; #endif -#ifdef HAVE_ECC_SIGN +#if defined(HAVE_ECC_SIGN) && !defined(WOLFSSL_KCAPI_ECC) WC_DECLARE_VAR(sig, byte, ECC_SIG_SIZE, HEAP_HINT); WC_DECLARE_VAR(digest, byte, ECC_DIGEST_SIZE, HEAP_HINT); int i; @@ -21751,7 +21751,7 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, ERROR_OUT(-9901, done); #endif -#ifdef HAVE_ECC_SIGN +#if defined(HAVE_ECC_SIGN) && !defined(WOLFSSL_KCAPI_ECC) if (sig == NULL || digest == NULL) ERROR_OUT(-9902, done); #endif @@ -21997,7 +21997,9 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, #endif /* HAVE_ECC_KEY_IMPORT */ #endif /* HAVE_ECC_KEY_EXPORT */ -#if !defined(ECC_TIMING_RESISTANT) || (defined(ECC_TIMING_RESISTANT) && !defined(WC_NO_RNG)) + /* For KCAPI cannot sign using generated ECDH key */ +#if !defined(ECC_TIMING_RESISTANT) || (defined(ECC_TIMING_RESISTANT) && \ + !defined(WC_NO_RNG) && !defined(WOLFSSL_KCAPI_ECC)) #ifdef HAVE_ECC_SIGN /* ECC w/out Shamir has issue with all 0 digest */ /* WC_BIGINT doesn't have 0 len well on hardware */ @@ -22079,10 +22081,12 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, } #endif /* HAVE_ECC_VERIFY */ #endif /* HAVE_ECC_SIGN */ -#endif /* !ECC_TIMING_RESISTANT || (ECC_TIMING_RESISTANT && !WC_NO_RNG) */ +#endif /* !ECC_TIMING_RESISTANT || (ECC_TIMING_RESISTANT && + * !WC_NO_RNG && !WOLFSSL_KCAPI_ECC) */ #if defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) && \ - !defined(WOLFSSL_ATECC508) && !defined(WOLFSSL_ATECC608A) + !defined(WOLFSSL_ATECC508) && !defined(WOLFSSL_ATECC608A) && \ + !defined(WOLFSSL_KCAPI_ECC) x = ECC_KEY_EXPORT_BUF_SIZE; ret = wc_ecc_export_private_only(userA, exportBuf, &x); if (ret != 0) diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 4fca5344f..108a5ede2 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1840,7 +1840,7 @@ WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz, WOLFSSL_LOCAL int CheckCSRSignaturePubKey(const byte* cert, word32 certSz, void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID); #endif /* WOLFSSL_CERT_REQ */ -WOLFSSL_LOCAL int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz, +WOLFSSL_ASN_API int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz, int sigAlgoType); WOLFSSL_LOCAL int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm);