From 0c3b9c733f3b7690613515df71fa492fcf925770 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 4 Mar 2022 15:03:58 -0800 Subject: [PATCH] Fixes for KCAPI ECDH/DH and page alignment. ZD 13763 --- configure.ac | 2 +- wolfcrypt/src/asn.c | 3 +- wolfcrypt/src/ecc.c | 2 +- wolfcrypt/src/port/kcapi/kcapi_aes.c | 18 +++-- wolfcrypt/src/port/kcapi/kcapi_dh.c | 66 ++++++++++++++-- wolfcrypt/src/port/kcapi/kcapi_ecc.c | 112 ++++++++++++++++++++++----- wolfcrypt/src/port/kcapi/kcapi_rsa.c | 4 +- 7 files changed, 170 insertions(+), 37 deletions(-) diff --git a/configure.ac b/configure.ac index 1c076891a..35b855d42 100644 --- a/configure.ac +++ b/configure.ac @@ -2103,7 +2103,7 @@ fi if test "$ENABLED_KCAPI_DH" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KCAPI_DH" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KCAPI_DH -DWOLFSSL_DH_EXTRA" fi if test "$ENABLED_KCAPI_ECC" = "yes" diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 5111adcf4..45f3dc0df 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -5381,7 +5381,8 @@ int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, #ifndef HAVE_USER_RSA #if defined(WOLFSSL_ASN_TEMPLATE) || (!defined(NO_CERTS) && \ - (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA))) + (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || \ + defined(WOLFSSL_KCAPI_RSA))) /* Byte offset of numbers in RSA key. */ size_t rsaIntOffset[] = { OFFSETOF(RsaKey, n), diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 02522f0a7..0d2cd538c 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -9851,7 +9851,7 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, &keySz, keySz, WC_TYPE_UNSIGNED_BIN); if (err == MP_OKAY) { err = wc_export_int(key->pubkey.y, - &key->pubkey_raw[WOLFSSL_KCAPI_ECC + keySz], &keySz, keySz, + &key->pubkey_raw[KCAPI_PARAM_SZ + 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 3bdcca966..e29099304 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_aes.c +++ b/wolfcrypt/src/port/kcapi/kcapi_aes.c @@ -236,6 +236,7 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte* data = NULL; word32 dataSz = authInSz + sz + authTagSz; ssize_t rc; + size_t pageSz = (size_t)sysconf(_SC_PAGESIZE); /* argument checks */ if (aes == NULL || authTagSz > AES_BLOCK_SIZE) { @@ -254,8 +255,8 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, } if (ret == 0) { - data = (byte*)XMALLOC(dataSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (data == NULL) { + ret = posix_memalign((void*)&data, pageSz, dataSz); + if (ret < 0) { ret = MEMORY_E; } } @@ -303,8 +304,10 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, XMEMCPY(authTag, data + authInSz + sz, authTagSz); } + /* Using free as this is in an environment that will have it + * available along with posix_memalign. */ if (data != NULL) { - XFREE(data, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + free(data); } if (aes != NULL && aes->handle != NULL) { kcapi_aead_destroy(aes->handle); @@ -327,6 +330,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, word32 dataSz = authInSz + sz + authTagSz; word32 outSz = authInSz + sz; ssize_t rc; + size_t pageSz = (size_t)sysconf(_SC_PAGESIZE); /* argument checks */ if (aes == NULL || (sz != 0 && (in == NULL || out == NULL)) || @@ -346,8 +350,8 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, } if (ret == 0) { - data = (byte*)XMALLOC(dataSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (data == NULL) { + ret = posix_memalign((void*)&data, pageSz, dataSz); + if (ret < 0) { ret = MEMORY_E; } } @@ -395,8 +399,10 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, XMEMCPY(out, data + authInSz, sz); } + /* Using free as this is in an environment that will have it + * available along with posix_memalign. */ if (data != NULL) { - XFREE(data, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + free(data); } if (aes != NULL && aes->handle != NULL) { kcapi_aead_destroy(aes->handle); diff --git a/wolfcrypt/src/port/kcapi/kcapi_dh.c b/wolfcrypt/src/port/kcapi/kcapi_dh.c index e05664964..f62f13848 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_dh.c +++ b/wolfcrypt/src/port/kcapi/kcapi_dh.c @@ -158,23 +158,75 @@ int KcapiDh_MakeKey(DhKey* key, byte* pub, word32* pubSz) ret = KcapiDh_SetParams(key); } if (ret == 0) { - ret = kcapi_kpp_keygen(key->handle, pub, *pubSz, + ret = kcapi_kpp_setkey(key->handle, NULL, 0); + if (ret >= 0) { + ret = 0; + } + } + if (ret == 0) { + ret = (int)kcapi_kpp_keygen(key->handle, pub, *pubSz, KCAPI_ACCESS_HEURISTIC); } return ret; } +#ifdef WOLFSSL_DH_EXTRA +static int KcapiDh_SetPrivKey(DhKey* key) +{ + int ret; + unsigned char* priv; + int len; + + len = ret = mp_unsigned_bin_size(&key->priv); + if (ret >= 0) { + priv = (unsigned char*)XMALLOC(len, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (priv == NULL) { + ret = MEMORY_E; + } + } + if (ret >= 0) { + ret = mp_to_unsigned_bin(&key->priv, priv); + } + if (ret >= 0) { + ret = kcapi_kpp_setkey(key->handle, priv, len); + if (ret >= 0) { + ret = 0; + } + } + + return ret; +} +#endif + int KcapiDh_SharedSecret(DhKey* private_key, const byte* pub, word32 pubSz, byte* out, word32* outlen) { - int ret; + int ret = 0; - ret = kcapi_kpp_ssgen(private_key->handle, pub, pubSz, out, *outlen, - KCAPI_ACCESS_HEURISTIC); - if (ret >= 0) { - *outlen = ret; - ret = 0; + if (private_key->handle == NULL) { + ret = kcapi_kpp_init(&private_key->handle, WC_NAME_DH, 0); + if (ret != 0) { + WOLFSSL_MSG("KcapiDh_SharedSecret: Failed to initialization"); + } + if (ret == 0) { + ret = KcapiDh_SetParams(private_key); + } + } + +#ifdef WOLFSSL_DH_EXTRA + if (!mp_iszero(&private_key->priv)) { + ret = KcapiDh_SetPrivKey(private_key); + } +#endif + + if (ret == 0) { + ret = (int)kcapi_kpp_ssgen(private_key->handle, pub, pubSz, out, + *outlen, KCAPI_ACCESS_HEURISTIC); + if (ret >= 0) { + *outlen = ret; + ret = 0; + } } return ret; diff --git a/wolfcrypt/src/port/kcapi/kcapi_ecc.c b/wolfcrypt/src/port/kcapi/kcapi_ecc.c index 4390b6d81..54c483495 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_ecc.c +++ b/wolfcrypt/src/port/kcapi/kcapi_ecc.c @@ -42,6 +42,7 @@ #endif #define ECDSA_KEY_VERSION 1 +#define ECDH_KEY_VERSION 1 static const char WC_NAME_ECDH[] = "ecdh"; #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -81,6 +82,7 @@ static int KcapiEcc_CurveId(int curve_id, word32* kcapiCurveId) int KcapiEcc_MakeKey(ecc_key* key, int keysize, int curve_id) { int ret = 0; + int sz = 0; word32 kcapiCurveId; if (curve_id == ECC_CURVE_DEF) { @@ -117,15 +119,24 @@ int KcapiEcc_MakeKey(ecc_key* key, int keysize, int curve_id) ret = kcapi_kpp_ecdh_setcurve(key->handle, kcapiCurveId); } if (ret == 0) { - ret = (int)kcapi_kpp_keygen(key->handle, key->pubkey_raw, + ret = kcapi_kpp_setkey(key->handle, NULL, 0); + if (ret >= 0) { + ret = 0; + } + } + if (ret == 0) { + sz = ret = (int)kcapi_kpp_keygen(key->handle, key->pubkey_raw, sizeof(key->pubkey_raw), KCAPI_ACCESS_HEURISTIC); } if (ret >= 0) { - ret = mp_read_unsigned_bin(key->pubkey.x, key->pubkey_raw, ret / 2); + ret = mp_read_unsigned_bin(key->pubkey.x, key->pubkey_raw, sz / 2); } if (ret == 0) { - ret = mp_read_unsigned_bin(key->pubkey.y, key->pubkey_raw + ret / 2, - ret / 2); + ret = mp_read_unsigned_bin(key->pubkey.y, key->pubkey_raw + sz / 2, + sz / 2); + } + if (ret == 0) { + key->type = ECC_PRIVATEKEY; } if ((ret != 0) && (key->handle != NULL)) { kcapi_kpp_destroy(key->handle); @@ -140,13 +151,70 @@ int KcapiEcc_SharedSecret(ecc_key* private_key, ecc_key* public_key, byte* out, word32* outlen) { int ret; + 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; - ret = (int)kcapi_kpp_ssgen(private_key->handle, public_key->pubkey_raw, - public_key->dp->size * 2, out, *outlen, - KCAPI_ACCESS_HEURISTIC); - if (ret >= 0) { - *outlen = ret; - ret = 0; + 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) { + ret = kcapi_kpp_ecdh_setcurve(private_key->handle, kcapiCurveId); + } + } + + /* if a private key value is set, load and use it */ + if (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) { + ret = kcapi_kpp_setkey(private_key->handle, priv, keySz); + if (ret >= 0) { + ret = 0; + } + } + } + if (ret == 0) { + /* setup aligned pointers */ + if (((size_t)pub % pageSz != 0) || + ((size_t)out % pageSz != 0)) { + ret = posix_memalign((void*)&buf_aligned, pageSz, pageSz * 2); + if (ret < 0) { + ret = MEMORY_E; + } + } + } + if (ret == 0) { + out_aligned = ((size_t)out % pageSz == 0) ? out : buf_aligned; + if ((size_t)pub % pageSz == 0) { + pub_aligned = (byte*)pub; + } + else { + pub_aligned = buf_aligned + pageSz; + XMEMCPY(pub_aligned, pub, public_key->dp->size * 2); + } + + ret = (int)kcapi_kpp_ssgen(private_key->handle, pub_aligned, + public_key->dp->size * 2, out_aligned, + *outlen, KCAPI_ACCESS_HEURISTIC); + if (ret >= 0) { + *outlen = ret/2; + if (out_aligned != out) { + XMEMCPY(out, out_aligned, ret); + } + ret = 0; + } + } + + /* Using free as this is in an environment that will have it + * available along with posix_memalign. */ + if (buf_aligned != NULL) { + free(buf_aligned); } return ret; @@ -157,19 +225,22 @@ int KcapiEcc_SharedSecret(ecc_key* private_key, ecc_key* public_key, byte* out, static int KcapiEcc_SetPrivKey(ecc_key* key) { int ret; - unsigned char priv[KCAPI_PARAM_SZ + MAX_ECC_BYTES]; + byte priv[KCAPI_PARAM_SZ + MAX_ECC_BYTES]; word32 keySz = key->dp->size; word32 kcapiCurveId; ret = KcapiEcc_CurveId(key->dp->id, &kcapiCurveId); - if (ret == MP_OKAY) { + if (ret == 0) { priv[0] = ECDSA_KEY_VERSION; priv[1] = kcapiCurveId; ret = wc_export_int(&key->k, priv + 2, &keySz, keySz, WC_TYPE_UNSIGNED_BIN); } - if (ret == MP_OKAY) { + if (ret == 0) { ret = kcapi_akcipher_setkey(key->handle, priv, KCAPI_PARAM_SZ + keySz); + if (ret >= 0) { + ret = 0; + } } return ret; @@ -179,9 +250,9 @@ int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, word32* sigLen) { int ret = 0; - unsigned char* buf_aligned = NULL; - unsigned char* hash_aligned = NULL; - unsigned char* sig_aligned = NULL; + byte* buf_aligned = NULL; + byte* hash_aligned = NULL; + byte* sig_aligned = NULL; size_t pageSz = (size_t)sysconf(_SC_PAGESIZE); if (key->handle == NULL) { @@ -204,7 +275,7 @@ int KcapiEcc_Sign(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, if (ret == 0) { sig_aligned = ((size_t)sig % pageSz == 0) ? sig : buf_aligned; if ((size_t)hash % pageSz == 0) { - hash_aligned = (unsigned char*)hash; + hash_aligned = (byte*)hash; } else { hash_aligned = buf_aligned + pageSz; @@ -240,11 +311,14 @@ int KcapiEcc_SetPubKey(ecc_key* key) word32 kcapiCurveId; ret = KcapiEcc_CurveId(key->dp->id, &kcapiCurveId); - if (ret == MP_OKAY) { + if (ret == 0) { key->pubkey_raw[0] = ECDSA_KEY_VERSION; key->pubkey_raw[1] = kcapiCurveId; ret = kcapi_akcipher_setpubkey(key->handle, key->pubkey_raw, len); + if (ret >= 0) { + ret = 0; + } } return ret; @@ -254,7 +328,7 @@ int KcapiEcc_Verify(ecc_key* key, const byte* hash, word32 hashLen, byte* sig, word32 sigLen) { int ret = 0; - unsigned char* sigHash_aligned = NULL; + byte* sigHash_aligned = NULL; size_t pageSz = (size_t)sysconf(_SC_PAGESIZE); if (key->handle == NULL) { diff --git a/wolfcrypt/src/port/kcapi/kcapi_rsa.c b/wolfcrypt/src/port/kcapi/kcapi_rsa.c index 09da322b0..828c4c1c8 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_rsa.c +++ b/wolfcrypt/src/port/kcapi/kcapi_rsa.c @@ -254,7 +254,7 @@ int KcapiRsa_Decrypt(RsaKey* key, const byte* in, word32 inLen, byte* out, } } if (ret == 0) { - ret = kcapi_akcipher_decrypt(key->handle, in, inLen, out, *outLen, + ret = (int)kcapi_akcipher_decrypt(key->handle, in, inLen, out, *outLen, KCAPI_ACCESS_HEURISTIC); if (ret >= 0) { *outLen = ret; @@ -345,7 +345,7 @@ int KcapiRsa_Encrypt(RsaKey* key, const byte* in, word32 inLen, byte* out, } } if (ret == 0) { - ret = kcapi_akcipher_encrypt(key->handle, in, inLen, out, *outLen, + ret = (int)kcapi_akcipher_encrypt(key->handle, in, inLen, out, *outLen, KCAPI_ACCESS_HEURISTIC); if (ret >= 0) { *outLen = ret;