mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 10:20:50 +02:00
cryptocb: add WC_PK_TYPE_EC_MAKE_PUB for ECC public-key derivation offload
Under WOLF_CRYPTO_CB_ONLY_ECC, HAVE_ECC_MAKE_PUB is now enabled and backed by the dispatch alone, failing closed with NO_VALID_DEVID when no device handles the operation (previously NOT_COMPILED_IN).
This commit is contained in:
@@ -251,3 +251,32 @@ void wc_CryptoCb_InfoString(wc_CryptoInfo* info);
|
||||
\sa wc_AesInit
|
||||
*/
|
||||
int wc_CryptoCb_AesSetKey(Aes* aes, const byte* key, word32 keySz);
|
||||
|
||||
/*!
|
||||
\ingroup CryptoCb
|
||||
|
||||
\brief Offload deriving an ECC public key Q = d*G from its private key to a
|
||||
CryptoCB device.
|
||||
|
||||
Used by wc_ecc_make_pub / wc_ecc_make_pub_ex. The callback boundary is
|
||||
math-free: the resulting public point crosses as X9.63 uncompressed bytes
|
||||
(0x04 || X || Y, each ordinate zero-padded to the curve size) in
|
||||
wc_CryptoInfo.pk.ecc_make_pub (\c pubOut / \c pubOutSz). This wrapper performs
|
||||
all bignum (de)serialization, so a device handler only deals with byte arrays
|
||||
and never with wolfCrypt's internal mp_int representation. The private scalar
|
||||
is taken from the ecc_key (resident in a secure element, or key->k); curve
|
||||
identity comes from key->dp.
|
||||
|
||||
\param key ECC key providing the device id, curve identity, heap hint and
|
||||
the private scalar
|
||||
\param pubOut [out] resulting affine public point Q = d*G
|
||||
|
||||
\return 0 on success
|
||||
\return CRYPTOCB_UNAVAILABLE if no device handles the operation, or key or
|
||||
pubOut is NULL (wolfCrypt falls back to software, which reports
|
||||
the argument error)
|
||||
|
||||
\sa wc_CryptoCb_RegisterDevice
|
||||
\sa wc_ecc_make_pub
|
||||
*/
|
||||
int wc_CryptoCb_EccMakePub(ecc_key* key, ecc_point* pubOut);
|
||||
|
||||
@@ -153,6 +153,47 @@ static int swdev_ecc_get_sig_size(wc_CryptoInfo* info)
|
||||
*info->pk.ecc_get_sig_size.sigSize = sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int swdev_ecc_make_pub(wc_CryptoInfo* info)
|
||||
{
|
||||
int ret;
|
||||
ecc_key* key = info->pk.ecc_make_pub.key;
|
||||
ecc_point* pub = wc_ecc_new_point_h(key->heap);
|
||||
|
||||
if (pub == NULL)
|
||||
return MEMORY_E;
|
||||
|
||||
/* derive Q = d*G in software, then emit X9.63 uncompressed bytes. The
|
||||
* point is serialized with the curve size from key->dp so custom-curve
|
||||
* keys (idx == ECC_CUSTOM_IDX) work too; wc_ecc_export_point_der rejects
|
||||
* negative curve indices. */
|
||||
ret = wc_ecc_make_pub(key, pub);
|
||||
if (ret == 0) {
|
||||
byte* out = info->pk.ecc_make_pub.pubOut;
|
||||
word32 curveSz = (word32)key->dp->size;
|
||||
word32 ptSz = 1 + 2 * curveSz;
|
||||
word32 xSz = curveSz;
|
||||
word32 ySz = curveSz;
|
||||
|
||||
if (*info->pk.ecc_make_pub.pubOutSz < ptSz) {
|
||||
ret = BUFFER_E;
|
||||
}
|
||||
else {
|
||||
out[0] = ECC_POINT_UNCOMP;
|
||||
ret = wc_export_int(pub->x, out + 1, &xSz, curveSz,
|
||||
WC_TYPE_UNSIGNED_BIN);
|
||||
if (ret == MP_OKAY)
|
||||
ret = wc_export_int(pub->y, out + 1 + curveSz, &ySz, curveSz,
|
||||
WC_TYPE_UNSIGNED_BIN);
|
||||
if (ret == MP_OKAY)
|
||||
*info->pk.ecc_make_pub.pubOutSz = ptSz;
|
||||
}
|
||||
}
|
||||
|
||||
wc_ecc_del_point_h(pub, key->heap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* HAVE_ECC */
|
||||
|
||||
#ifndef NO_SHA256
|
||||
@@ -712,6 +753,8 @@ WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info,
|
||||
return swdev_ecc_get_size(info);
|
||||
case WC_PK_TYPE_EC_GET_SIG_SIZE:
|
||||
return swdev_ecc_get_sig_size(info);
|
||||
case WC_PK_TYPE_EC_MAKE_PUB:
|
||||
return swdev_ecc_make_pub(info);
|
||||
#endif /* HAVE_ECC */
|
||||
default:
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
|
||||
@@ -157,6 +157,7 @@ static const char* GetPkTypeStr(int pk)
|
||||
case WC_PK_TYPE_EC_KEYGEN: return "ECC KeyGen";
|
||||
case WC_PK_TYPE_EC_GET_SIZE: return "ECC GetSize";
|
||||
case WC_PK_TYPE_EC_GET_SIG_SIZE: return "ECC GetSigSize";
|
||||
case WC_PK_TYPE_EC_MAKE_PUB: return "ECC MakePub";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -878,6 +879,65 @@ int wc_CryptoCb_EccGetSigSize(const ecc_key* key, int* sigSize)
|
||||
|
||||
return wc_CryptoCb_TranslateErrorCode(ret);
|
||||
}
|
||||
|
||||
int wc_CryptoCb_EccMakePub(ecc_key* key, ecc_point* pubOut)
|
||||
{
|
||||
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
CryptoCb* dev;
|
||||
|
||||
if (key == NULL || pubOut == NULL || key->dp == NULL)
|
||||
return ret;
|
||||
|
||||
if (key->dp->size > MAX_ECC_BYTES)
|
||||
return ret;
|
||||
|
||||
dev = wc_CryptoCb_FindDevice(key->devId, WC_ALGO_TYPE_PK);
|
||||
if (dev && dev->cb) {
|
||||
wc_CryptoInfo cryptoInfo;
|
||||
word32 curveSz = (word32)key->dp->size;
|
||||
word32 ptSz = 1 + 2 * curveSz; /* X9.63 uncompressed length */
|
||||
word32 outSz = ptSz;
|
||||
WC_DECLARE_VAR(buf, byte, (1 + 2 * MAX_ECC_BYTES), key->heap);
|
||||
WC_ALLOC_VAR_EX(buf, byte, (1 + 2 * MAX_ECC_BYTES), key->heap,
|
||||
DYNAMIC_TYPE_ECC_BUFFER, return MEMORY_E);
|
||||
|
||||
/* zero the result buffer so a handler that returns success without
|
||||
* writing output is rejected deterministically by the tag check */
|
||||
XMEMSET(buf, 0, ptSz);
|
||||
|
||||
XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
|
||||
cryptoInfo.algo_type = WC_ALGO_TYPE_PK;
|
||||
cryptoInfo.pk.type = WC_PK_TYPE_EC_MAKE_PUB;
|
||||
cryptoInfo.pk.ecc_make_pub.key = key;
|
||||
cryptoInfo.pk.ecc_make_pub.pubOut = buf;
|
||||
cryptoInfo.pk.ecc_make_pub.pubOutSz = &outSz;
|
||||
|
||||
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
|
||||
|
||||
/* deserialize X9.63 uncompressed result into pubOut; reject a result
|
||||
* whose size is not exactly the curve's X9.63 length */
|
||||
if (ret == 0) {
|
||||
if (outSz != ptSz || buf[0] != ECC_POINT_UNCOMP) {
|
||||
ret = BUFFER_E;
|
||||
}
|
||||
else {
|
||||
int err = mp_read_unsigned_bin(pubOut->x, buf + 1, curveSz);
|
||||
if (err == MP_OKAY)
|
||||
err = mp_read_unsigned_bin(pubOut->y, buf + 1 + curveSz,
|
||||
curveSz);
|
||||
if (err == MP_OKAY)
|
||||
err = mp_set(pubOut->z, 1);
|
||||
if (err != MP_OKAY)
|
||||
ret = err;
|
||||
}
|
||||
}
|
||||
|
||||
WC_FREE_VAR_EX(buf, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
|
||||
}
|
||||
|
||||
return wc_CryptoCb_TranslateErrorCode(ret);
|
||||
}
|
||||
|
||||
#endif /* HAVE_ECC */
|
||||
|
||||
#ifdef HAVE_CURVE25519
|
||||
|
||||
+43
-6
@@ -291,8 +291,7 @@ ECC Curve Sizes:
|
||||
#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \
|
||||
!defined(WOLFSSL_MICROCHIP_TA100) && \
|
||||
!defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_SILABS_SE_ACCEL) && \
|
||||
!defined(WOLFSSL_KCAPI_ECC) && !defined(NO_ECC_MAKE_PUB) && \
|
||||
!defined(WOLF_CRYPTO_CB_ONLY_ECC)
|
||||
!defined(WOLFSSL_KCAPI_ECC) && !defined(NO_ECC_MAKE_PUB)
|
||||
#undef HAVE_ECC_MAKE_PUB
|
||||
#define HAVE_ECC_MAKE_PUB
|
||||
#endif
|
||||
@@ -5433,8 +5432,8 @@ static WC_INLINE void wc_ecc_reset(ecc_key* key)
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_ECC_MAKE_PUB
|
||||
/* compute the public key Q = d*G in software
|
||||
#if defined(HAVE_ECC_MAKE_PUB) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)
|
||||
/* compute the public key Q = d*G in software.
|
||||
*
|
||||
* key private key holding the scalar d, must be present and in range
|
||||
* curve [in]curve for key, cannot be NULL
|
||||
@@ -5549,7 +5548,7 @@ static int ecc_make_pub_sw(ecc_key* key, ecc_curve_spec* curve,
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* HAVE_ECC_MAKE_PUB */
|
||||
#endif /* HAVE_ECC_MAKE_PUB && !WOLF_CRYPTO_CB_ONLY_ECC */
|
||||
|
||||
/* create the public ECC key from a private key
|
||||
*
|
||||
@@ -5572,6 +5571,7 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve,
|
||||
int err = MP_OKAY;
|
||||
#ifdef HAVE_ECC_MAKE_PUB
|
||||
ecc_point* pub;
|
||||
int doneInCb = 0;
|
||||
#endif /* HAVE_ECC_MAKE_PUB */
|
||||
|
||||
(void)rng;
|
||||
@@ -5605,8 +5605,45 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve,
|
||||
#endif
|
||||
}
|
||||
|
||||
if (err == MP_OKAY) {
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* offload Q = d*G to the device; fall through to software only when the
|
||||
* device reports the operation unavailable.
|
||||
*
|
||||
* Under WOLF_CRYPTO_CB_FIND the devId gate is dropped so a find callback
|
||||
* can route a key initialized with INVALID_DEVID. This helper is also
|
||||
* shared by internal callers that compute a point from a transient scalar
|
||||
* in key->k - the ECDSA software-sign nonce R = k*G (ecc_sign_hash_sw),
|
||||
* keygen public-part derivation, and verify-time public-key recovery.
|
||||
* Reaching the software signer means the device already declined to sign
|
||||
* (the whole-sign offload wc_CryptoCb_EccSign ran first), so a find
|
||||
* callback that hands this make-pub to a device notwithstanding the
|
||||
* INVALID_DEVID is expected to likewise decline it. If it does not decline
|
||||
* *and* the device ignores key->k (e.g. relying on an internal key
|
||||
* representation), it returns d*G instead of the requested k*G and the
|
||||
* resulting signature is wrong - but such a scenario is very unlikely. */
|
||||
#ifndef WOLF_CRYPTO_CB_FIND
|
||||
if ((err == MP_OKAY) && (key->devId != INVALID_DEVID))
|
||||
#else
|
||||
if (err == MP_OKAY)
|
||||
#endif
|
||||
{
|
||||
err = wc_CryptoCb_EccMakePub(key, pub);
|
||||
if (err != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
|
||||
doneInCb = 1;
|
||||
else
|
||||
err = MP_OKAY; /* device declined the offload; fall back */
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((err == MP_OKAY) && !doneInCb) {
|
||||
#ifdef WOLF_CRYPTO_CB_ONLY_ECC
|
||||
/* software derivation is stripped and no device handled the op;
|
||||
* fail closed */
|
||||
(void)curve;
|
||||
err = NO_VALID_DEVID;
|
||||
#else
|
||||
err = ecc_make_pub_sw(key, curve, pub, rng);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (err != MP_OKAY
|
||||
|
||||
@@ -245,6 +245,12 @@ typedef struct wc_CryptoInfo {
|
||||
const ecc_key* key;
|
||||
int* sigSize;
|
||||
} ecc_get_sig_size;
|
||||
struct {
|
||||
ecc_key* key; /* routing (devId), curve (key->dp), heap,
|
||||
* resident/sw private scalar d */
|
||||
byte* pubOut; /* [out] X9.63 0x04||X||Y, uncompressed */
|
||||
word32* pubOutSz; /* in: buf size; out: bytes written */
|
||||
} ecc_make_pub;
|
||||
#endif /* HAVE_ECC */
|
||||
#ifdef HAVE_CURVE25519
|
||||
struct {
|
||||
@@ -730,6 +736,8 @@ WOLFSSL_LOCAL int wc_CryptoCb_EccCheckPrivKey(ecc_key* key, const byte* pubKey,
|
||||
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_EccGetSize(const ecc_key* key, int* keySize);
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_EccGetSigSize(const ecc_key* key, int* sigSize);
|
||||
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_EccMakePub(ecc_key* key, ecc_point* pubOut);
|
||||
#endif /* HAVE_ECC */
|
||||
|
||||
#ifdef HAVE_CURVE25519
|
||||
|
||||
@@ -1597,6 +1597,9 @@ enum wc_PkType {
|
||||
#undef _WC_PK_TYPE_MAX
|
||||
#define _WC_PK_TYPE_MAX WC_PK_TYPE_PQC_STATEFUL_SIG_SIGS_LEFT
|
||||
#endif
|
||||
WC_PK_TYPE_EC_MAKE_PUB = 34,
|
||||
#undef _WC_PK_TYPE_MAX
|
||||
#define _WC_PK_TYPE_MAX WC_PK_TYPE_EC_MAKE_PUB
|
||||
WC_PK_TYPE_MAX = _WC_PK_TYPE_MAX
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user