From 8e6d151403e93580b46bead7dbe0e3c093a1c8bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Wed, 6 Dec 2023 17:44:20 +0100 Subject: [PATCH 1/3] PQC: CryptoCb support for signature algorithms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add initial support of the crypto callback API to the two PQC signature algorithms Dilithium and Falcon. This ultimatelly enables the usage of external hardware modules (e.g. secure elements) for these algorithms. Signed-off-by: Tobias Frauenschläger --- src/internal.c | 108 ++++++++++++++++++- src/ssl.c | 49 +++++++++ wolfcrypt/src/asn.c | 15 ++- wolfcrypt/src/cryptocb.c | 162 +++++++++++++++++++++++++++++ wolfcrypt/src/dilithium.c | 189 ++++++++++++++++++++++++++++------ wolfcrypt/src/falcon.c | 173 ++++++++++++++++++++++++++----- wolfssl/wolfcrypt/cryptocb.h | 56 ++++++++++ wolfssl/wolfcrypt/dilithium.h | 36 ++++++- wolfssl/wolfcrypt/falcon.h | 37 ++++++- wolfssl/wolfcrypt/types.h | 29 +++++- 10 files changed, 784 insertions(+), 70 deletions(-) diff --git a/src/internal.c b/src/internal.c index 31334eb43..fc462c14e 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7787,13 +7787,13 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) #if defined(HAVE_PQC) #if defined(HAVE_FALCON) case DYNAMIC_TYPE_FALCON: - wc_falcon_init((falcon_key*)*pKey); + wc_falcon_init_ex((falcon_key*)*pKey, ssl->heap, ssl->devId); ret = 0; break; #endif /* HAVE_FALCON */ #if defined(HAVE_DILITHIUM) case DYNAMIC_TYPE_DILITHIUM: - wc_dilithium_init((dilithium_key*)*pKey); + wc_dilithium_init_ex((dilithium_key*)*pKey, ssl->heap, ssl->devId); ret = 0; break; #endif /* HAVE_DILITHIUM */ @@ -27451,6 +27451,54 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType, } #endif } + else if (hsType == DYNAMIC_TYPE_DILITHIUM) { +#if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + dilithium_key* dilithiumKey; + + dilithiumKey = (dilithium_key*)XMALLOC(sizeof(dilithium_key), heap, + DYNAMIC_TYPE_DILITHIUM); + if (dilithiumKey == NULL) { + return MEMORY_E; + } + + if (label) { + ret = wc_dilithium_init_label(dilithiumKey, (char*)data, heap, devId); + } + else if (id) { + ret = wc_dilithium_init_id(dilithiumKey, data, length, heap, devId); + } + if (ret == 0) { + *pkey = (void*)dilithiumKey; + } + else { + XFREE(dilithiumKey, heap, DYNAMIC_TYPE_DILITHIUM); + } +#endif + } + else if (hsType == DYNAMIC_TYPE_FALCON) { +#if defined(HAVE_PQC) && defined(HAVE_FALCON) + falcon_key* falconKey; + + falconKey = (falcon_key*)XMALLOC(sizeof(falcon_key), heap, + DYNAMIC_TYPE_FALCON); + if (falconKey == NULL) { + return MEMORY_E; + } + + if (label) { + ret = wc_falcon_init_label(falconKey, (char*)data, heap, devId); + } + else if (id) { + ret = wc_falcon_init_id(falconKey, data, length, heap, devId); + } + if (ret == 0) { + *pkey = (void*)falconKey; + } + else { + XFREE(falconKey, heap, DYNAMIC_TYPE_FALCON); + } +#endif + } return ret; } @@ -27499,6 +27547,10 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) ssl->hsType = DYNAMIC_TYPE_RSA; else if (ssl->buffers.keyType == ecc_dsa_sa_algo) ssl->hsType = DYNAMIC_TYPE_ECC; + else if (ssl->buffers.keyType == falcon_level5_sa_algo) + ssl->hsType = DYNAMIC_TYPE_FALCON; + else if (ssl->buffers.keyType == dilithium_level5_sa_algo) + ssl->hsType = DYNAMIC_TYPE_DILITHIUM; ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_dpk; @@ -27554,6 +27606,58 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } #else ret = NOT_COMPILED_IN; + #endif + } + else if (ssl->buffers.keyType == falcon_level5_sa_algo) { + #if defined(HAVE_PQC) && defined(HAVE_FALCON) + if (ssl->buffers.keyLabel) { + ret = wc_falcon_init_label((falcon_key*)ssl->hsKey, + (char*)ssl->buffers.key->buffer, + ssl->heap, ssl->buffers.keyDevId); + } + else if (ssl->buffers.keyId) { + ret = wc_falcon_init_id((falcon_key*)ssl->hsKey, + ssl->buffers.key->buffer, + ssl->buffers.key->length, ssl->heap, + ssl->buffers.keyDevId); + } + if (ret == 0) { + if (ssl->buffers.keySz < ssl->options.minFalconKeySz) { + WOLFSSL_MSG("Falcon key size too small"); + ERROR_OUT(FALCON_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = (word16)wc_falcon_sig_size((falcon_key*)ssl->hsKey); + } + #else + ret = NOT_COMPILED_IN; + #endif + } + else if (ssl->buffers.keyType == dilithium_level5_sa_algo) { + #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + if (ssl->buffers.keyLabel) { + ret = wc_dilithium_init_label((dilithium_key*)ssl->hsKey, + (char*)ssl->buffers.key->buffer, + ssl->heap, ssl->buffers.keyDevId); + } + else if (ssl->buffers.keyId) { + ret = wc_dilithium_init_id((dilithium_key*)ssl->hsKey, + ssl->buffers.key->buffer, + ssl->buffers.key->length, ssl->heap, + ssl->buffers.keyDevId); + } + if (ret == 0) { + if (ssl->buffers.keySz < ssl->options.minDilithiumKeySz) { + WOLFSSL_MSG("Dilithium key size too small"); + ERROR_OUT(DILITHIUM_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = (word16)wc_dilithium_sig_size((dilithium_key*)ssl->hsKey); + } + #else + ret = NOT_COMPILED_IN; #endif } goto exit_dpk; diff --git a/src/ssl.c b/src/ssl.c index 1cdd8b3b2..55b6e881c 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -7734,6 +7734,9 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, #if defined(HAVE_FALCON) case FALCON_LEVEL1k: case FALCON_LEVEL5k: + #ifdef WOLF_PRIVATE_KEY_ID + keyType = falcon_level5_sa_algo; + #endif /* Falcon is fixed key size */ keySz = FALCON_MAX_KEY_SIZE; if (ssl && !ssl->options.verifyNone) { @@ -7756,6 +7759,9 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, case DILITHIUM_LEVEL2k: case DILITHIUM_LEVEL3k: case DILITHIUM_LEVEL5k: + #ifdef WOLF_PRIVATE_KEY_ID + keyType = dilithium_level5_sa_algo; + #endif /* Dilithium is fixed key size */ keySz = DILITHIUM_MAX_KEY_SIZE; if (ssl && !ssl->options.verifyNone) { @@ -9090,6 +9096,19 @@ static int check_cert_key(DerBuffer* cert, DerBuffer* key, void* heap, type = DYNAMIC_TYPE_ECC; } #endif + #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + if ((der->keyOID == DILITHIUM_LEVEL2k) || + (der->keyOID == DILITHIUM_LEVEL3k) || + (der->keyOID == DILITHIUM_LEVEL5k)) { + type = DYNAMIC_TYPE_DILITHIUM; + } + #endif + #if defined(HAVE_PQC) && defined(HAVE_FALCON) + if ((der->keyOID == FALCON_LEVEL1k) || + (der->keyOID == FALCON_LEVEL5k)) { + type = DYNAMIC_TYPE_FALCON; + } + #endif ret = CreateDevPrivateKey(&pkey, buff, size, type, isKeyLabel, isKeyId, heap, devId); @@ -9111,6 +9130,23 @@ static int check_cert_key(DerBuffer* cert, DerBuffer* key, void* heap, der->publicKey, der->pubKeySize); } #endif + #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + if ((der->keyOID == DILITHIUM_LEVEL2k) || + (der->keyOID == DILITHIUM_LEVEL3k) || + (der->keyOID == DILITHIUM_LEVEL5k)) { + ret = wc_CryptoCb_PqcSignatureCheckPrivKey(pkey, + WC_PQC_SIG_TYPE_DILITHIUM, + der->publicKey, der->pubKeySize); + } + #endif + #if defined(HAVE_PQC) && defined(HAVE_FALCON) + if ((der->keyOID == FALCON_LEVEL1k) || + (der->keyOID == FALCON_LEVEL5k)) { + ret = wc_CryptoCb_PqcSignatureCheckPrivKey(pkey, + WC_PQC_SIG_TYPE_FALCON, + der->publicKey, der->pubKeySize); + } + #endif } #else /* devId was set, don't check, for now */ @@ -9130,6 +9166,19 @@ static int check_cert_key(DerBuffer* cert, DerBuffer* key, void* heap, if (der->keyOID == ECDSAk) { wc_ecc_free((ecc_key*)pkey); } + #endif + #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + if ((der->keyOID == DILITHIUM_LEVEL2k) || + (der->keyOID == DILITHIUM_LEVEL3k) || + (der->keyOID == DILITHIUM_LEVEL5k)) { + wc_dilithium_free((dilithium_key*)pkey); + } + #endif + #if defined(HAVE_PQC) && defined(HAVE_FALCON) + if ((der->keyOID == FALCON_LEVEL1k) || + (der->keyOID == FALCON_LEVEL5k)) { + wc_falcon_free((falcon_key*)pkey); + } #endif XFREE(pkey, heap, type); } diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 24c6d0a04..9439ed65b 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -16440,7 +16440,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx, if (sigCtx->key.falcon == NULL) { ERROR_OUT(MEMORY_E, exit_cs); } - if ((ret = wc_falcon_init(sigCtx->key.falcon)) < 0) { + if ((ret = wc_falcon_init_ex(sigCtx->key.falcon, + sigCtx->heap, sigCtx->devId)) < 0) { goto exit_cs; } if ((ret = wc_falcon_set_level(sigCtx->key.falcon, 1)) @@ -16465,7 +16466,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx, if (sigCtx->key.falcon == NULL) { ERROR_OUT(MEMORY_E, exit_cs); } - if ((ret = wc_falcon_init(sigCtx->key.falcon)) < 0) { + if ((ret = wc_falcon_init_ex(sigCtx->key.falcon, + sigCtx->heap, sigCtx->devId)) < 0) { goto exit_cs; } if ((ret = wc_falcon_set_level(sigCtx->key.falcon, 5)) @@ -16492,7 +16494,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx, if (sigCtx->key.dilithium == NULL) { ERROR_OUT(MEMORY_E, exit_cs); } - if ((ret = wc_dilithium_init(sigCtx->key.dilithium)) < 0) { + if ((ret = wc_dilithium_init_ex(sigCtx->key.dilithium, + sigCtx->heap, sigCtx->devId)) < 0) { goto exit_cs; } if ((ret = wc_dilithium_set_level( @@ -16517,7 +16520,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx, if (sigCtx->key.dilithium == NULL) { ERROR_OUT(MEMORY_E, exit_cs); } - if ((ret = wc_dilithium_init(sigCtx->key.dilithium)) < 0) { + if ((ret = wc_dilithium_init_ex(sigCtx->key.dilithium, + sigCtx->heap, sigCtx->devId)) < 0) { goto exit_cs; } if ((ret = wc_dilithium_set_level( @@ -16542,7 +16546,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx, if (sigCtx->key.dilithium == NULL) { ERROR_OUT(MEMORY_E, exit_cs); } - if ((ret = wc_dilithium_init(sigCtx->key.dilithium)) < 0) { + if ((ret = wc_dilithium_init_ex(sigCtx->key.dilithium, + sigCtx->heap, sigCtx->devId)) < 0) { goto exit_cs; } if ((ret = wc_dilithium_set_level( diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index ce49e4671..3996ceaa4 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -785,6 +785,168 @@ int wc_CryptoCb_Ed25519Verify(const byte* sig, word32 sigLen, } #endif /* HAVE_ED25519 */ +#if defined(HAVE_PQC) && (defined(HAVE_FALCON) || defined(HAVE_DILITHIUM)) +int wc_CryptoCb_PqcSigGetDevId(int type, void* key) +{ + int devId = INVALID_DEVID; + + if (key == NULL) + return devId; + + /* get devId */ +#if defined(HAVE_DILITHIUM) + if (type == WC_PQC_SIG_TYPE_DILITHIUM) { + devId = ((dilithium_key*) key)->devId; + } +#endif +#if defined(HAVE_FALCON) + if (type == WC_PQC_SIG_TYPE_FALCON) { + devId = ((falcon_key*) key)->devId; + } +#endif + + return devId; +} + +int wc_CryptoCb_MakePqcSignatureKey(WC_RNG* rng, int type, int keySize, + void* key) +{ + int ret = CRYPTOCB_UNAVAILABLE; + int devId = INVALID_DEVID; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* get devId */ + devId = wc_CryptoCb_PqcSigGetDevId(type, key); + if (devId == INVALID_DEVID) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_PK); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_PQC_SIG_KEYGEN; + cryptoInfo.pk.pqc_sig_kg.rng = rng; + cryptoInfo.pk.pqc_sig_kg.size = keySize; + cryptoInfo.pk.pqc_sig_kg.key = key; + cryptoInfo.pk.pqc_sig_kg.type = type; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_PqcSign(const byte* in, word32 inlen, byte* out, word32 *outlen, + WC_RNG* rng, int type, void* key) +{ + int ret = CRYPTOCB_UNAVAILABLE; + int devId = INVALID_DEVID; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* get devId */ + devId = wc_CryptoCb_PqcSigGetDevId(type, key); + if (devId == INVALID_DEVID) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_PK); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_PQC_SIG_SIGN; + cryptoInfo.pk.pqc_sign.in = in; + cryptoInfo.pk.pqc_sign.inlen = inlen; + cryptoInfo.pk.pqc_sign.out = out; + cryptoInfo.pk.pqc_sign.outlen = outlen; + cryptoInfo.pk.pqc_sign.rng = rng; + cryptoInfo.pk.pqc_sign.key = key; + cryptoInfo.pk.pqc_sign.type = type; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_PqcVerify(const byte* sig, word32 siglen, const byte* msg, + word32 msglen, int* res, int type, void* key) +{ + int ret = CRYPTOCB_UNAVAILABLE; + int devId = INVALID_DEVID; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* get devId */ + devId = wc_CryptoCb_PqcSigGetDevId(type, key); + if (devId == INVALID_DEVID) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_PK); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_PQC_SIG_VERIFY; + cryptoInfo.pk.pqc_verify.sig = sig; + cryptoInfo.pk.pqc_verify.siglen = siglen; + cryptoInfo.pk.pqc_verify.msg = msg; + cryptoInfo.pk.pqc_verify.msglen = msglen; + cryptoInfo.pk.pqc_verify.res = res; + cryptoInfo.pk.pqc_verify.key = key; + cryptoInfo.pk.pqc_verify.type = type; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_PqcSignatureCheckPrivKey(void* key, int type, + const byte* pubKey, word32 pubKeySz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + int devId = INVALID_DEVID; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* get devId */ + devId = wc_CryptoCb_PqcSigGetDevId(type, key); + if (devId == INVALID_DEVID) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_PK); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY; + cryptoInfo.pk.pqc_sig_check.key = key; + cryptoInfo.pk.pqc_sig_check.pubKey = pubKey; + cryptoInfo.pk.pqc_sig_check.pubKeySz = pubKeySz; + cryptoInfo.pk.pqc_sig_check.type = type; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* HAVE_PQC && (HAVE_FALCON || HAVE_DILITHIUM) */ + #ifndef NO_AES #ifdef HAVE_AESGCM int wc_CryptoCb_AesGcmEncrypt(Aes* aes, byte* out, diff --git a/wolfcrypt/src/dilithium.c b/wolfcrypt/src/dilithium.c index 93e79e965..fd12c0365 100644 --- a/wolfcrypt/src/dilithium.c +++ b/wolfcrypt/src/dilithium.c @@ -62,15 +62,30 @@ int wc_dilithium_sign_msg(const byte* in, word32 inLen, dilithium_key* key, WC_RNG* rng) { int ret = 0; -#ifdef HAVE_LIBOQS - OQS_SIG *oqssig = NULL; - size_t localOutLen = 0; /* sanity check on arguments */ if ((in == NULL) || (out == NULL) || (outLen == NULL) || (key == NULL)) { - ret = BAD_FUNC_ARG; + return BAD_FUNC_ARG; } +#ifdef WOLF_CRYPTO_CB + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + ret = wc_CryptoCb_PqcSign(in, inLen, out, outLen, rng, + WC_PQC_SIG_TYPE_DILITHIUM, key); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + ret = 0; + } +#endif + +#ifdef HAVE_LIBOQS + OQS_SIG *oqssig = NULL; + size_t localOutLen = 0; + if ((ret == 0) && (!key->prvKeySet)) { ret = BAD_FUNC_ARG; } @@ -90,6 +105,10 @@ int wc_dilithium_sign_msg(const byte* in, word32 inLen, } } + if ((ret == 0) && (oqssig == NULL)) { + ret = BUFFER_E; + } + /* check and set up out length */ if (ret == 0) { if ((key->level == 2) && (*outLen < DILITHIUM_LEVEL2_SIG_SIZE)) { @@ -148,13 +167,28 @@ int wc_dilithium_verify_msg(const byte* sig, word32 sigLen, const byte* msg, word32 msgLen, int* res, dilithium_key* key) { int ret = 0; -#ifdef HAVE_LIBOQS - OQS_SIG *oqssig = NULL; if (key == NULL || sig == NULL || msg == NULL || res == NULL) { - ret = BAD_FUNC_ARG; + return BAD_FUNC_ARG; } +#ifdef WOLF_CRYPTO_CB + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + ret = wc_CryptoCb_PqcVerify(sig, sigLen, msg, msgLen, res, + WC_PQC_SIG_TYPE_DILITHIUM, key); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + ret = 0; + } +#endif + +#ifdef HAVE_LIBOQS + OQS_SIG *oqssig = NULL; + if ((ret == 0) && (!key->pubKeySet)) { ret = BAD_FUNC_ARG; } @@ -174,6 +208,10 @@ int wc_dilithium_verify_msg(const byte* sig, word32 sigLen, const byte* msg, } } + if ((ret == 0) && (oqssig == NULL)) { + ret = BUFFER_E; + } + if ((ret == 0) && (OQS_SIG_verify(oqssig, msg, msgLen, sig, sigLen, key->p) == OQS_ERROR)) { @@ -200,15 +238,92 @@ int wc_dilithium_verify_msg(const byte* sig, word32 sigLen, const byte* msg, * returns BAD_FUNC_ARG when key is NULL */ int wc_dilithium_init(dilithium_key* key) +{ + return wc_dilithium_init_ex(key, NULL, INVALID_DEVID); +} + +/* Initialize the dilithium private/public key. + * + * key [in] Dilithium key. + * heap [in] Heap hint. + * devId[in] Device ID. + * returns BAD_FUNC_ARG when key is NULL + */ +int wc_dilithium_init_ex(dilithium_key* key, void* heap, int devId) { if (key == NULL) { return BAD_FUNC_ARG; } ForceZero(key, sizeof(*key)); + +#ifdef WOLF_CRYPTO_CB + key->devCtx = NULL; + key->devId = devId; +#endif +#ifdef WOLF_PRIVATE_KEY_ID + key->idLen = 0; + key->labelLen = 0; +#endif + + (void) heap; + (void) devId; + return 0; } +#ifdef WOLF_PRIVATE_KEY_ID +int wc_dilithium_init_id(dilithium_key* key, const unsigned char* id, int len, + void* heap, int devId) +{ + int ret = 0; + + if (key == NULL) + ret = BAD_FUNC_ARG; + if (ret == 0 && (len < 0 || len > DILITHIUM_MAX_ID_LEN)) + ret = BUFFER_E; + + if (ret == 0) + ret = wc_dilithium_init_ex(key, heap, devId); + if (ret == 0 && id != NULL && len != 0) { + XMEMCPY(key->id, id, (size_t)len); + key->idLen = len; + } + + /* Set the maxiumum level here */ + wc_dilithium_set_level(key, 5); + + return ret; +} + +int wc_dilithium_init_label(dilithium_key* key, const char* label, void* heap, + int devId) +{ + int ret = 0; + int labelLen = 0; + + if (key == NULL || label == NULL) + ret = BAD_FUNC_ARG; + if (ret == 0) { + labelLen = (int)XSTRLEN(label); + if (labelLen == 0 || labelLen > DILITHIUM_MAX_LABEL_LEN) + ret = BUFFER_E; + } + + if (ret == 0) + ret = wc_dilithium_init_ex(key, heap, devId); + if (ret == 0) { + XMEMCPY(key->label, label, (size_t)labelLen); + key->labelLen = labelLen; + } + + /* Set the maxiumum level here */ + wc_dilithium_set_level(key, 5); + + return ret; +} +#endif + /* Set the level of the dilithium private/public key. * * key [out] Dilithium key. @@ -422,15 +537,7 @@ int wc_dilithium_import_private_only(const byte* priv, word32 privSz, return ret; } - if (key->level == 2) { - XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL2_KEY_SIZE); - } - else if (key->level == 3) { - XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL3_KEY_SIZE); - } - else if (key->level == 5) { - XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL5_KEY_SIZE); - } + XMEMCPY(key->k, newPriv, newPrivSz); key->prvKeySet = 1; return 0; @@ -494,15 +601,7 @@ int wc_dilithium_import_private_key(const byte* priv, word32 privSz, if (ret == 0) { /* make the private key (priv + pub) */ - if (key->level == 2) { - XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL2_KEY_SIZE); - } - else if (key->level == 3) { - XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL3_KEY_SIZE); - } - else if (key->level == 5) { - XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL5_KEY_SIZE); - } + XMEMCPY(key->k, newPriv, newPrivSz); key->prvKeySet = 1; } @@ -597,20 +696,20 @@ int wc_dilithium_export_private(dilithium_key* key, byte* out, word32* outLen) if (key->level == 2) { *outLen = DILITHIUM_LEVEL2_PRV_KEY_SIZE; - XMEMCPY(out, key->k, DILITHIUM_LEVEL2_PRV_KEY_SIZE); - XMEMCPY(out + DILITHIUM_LEVEL2_PRV_KEY_SIZE, key->p, + XMEMCPY(out, key->k, DILITHIUM_LEVEL2_KEY_SIZE); + XMEMCPY(out + DILITHIUM_LEVEL2_KEY_SIZE, key->p, DILITHIUM_LEVEL2_PUB_KEY_SIZE); } else if (key->level == 3) { *outLen = DILITHIUM_LEVEL3_PRV_KEY_SIZE; - XMEMCPY(out, key->k, DILITHIUM_LEVEL3_PRV_KEY_SIZE); - XMEMCPY(out + DILITHIUM_LEVEL3_PRV_KEY_SIZE, key->p, + XMEMCPY(out, key->k, DILITHIUM_LEVEL3_KEY_SIZE); + XMEMCPY(out + DILITHIUM_LEVEL3_KEY_SIZE, key->p, DILITHIUM_LEVEL3_PUB_KEY_SIZE); } else if (key->level == 5) { *outLen = DILITHIUM_LEVEL5_PRV_KEY_SIZE; - XMEMCPY(out, key->k, DILITHIUM_LEVEL5_PRV_KEY_SIZE); - XMEMCPY(out + DILITHIUM_LEVEL5_PRV_KEY_SIZE, key->p, + XMEMCPY(out, key->k, DILITHIUM_LEVEL5_KEY_SIZE); + XMEMCPY(out + DILITHIUM_LEVEL5_KEY_SIZE, key->p, DILITHIUM_LEVEL5_PUB_KEY_SIZE); } @@ -659,8 +758,29 @@ int wc_dilithium_check_key(dilithium_key* key) return BAD_FUNC_ARG; } - /* Assume everything is fine. */ - return 0; + int ret = 0; + + /* The public key is also decoded and stored within the private key buffer + * behind the private key. Hence, we can compare both stored public keys. */ + if (key->level == 2) { + ret = XMEMCMP(key->p, key->k + DILITHIUM_LEVEL2_KEY_SIZE, + DILITHIUM_LEVEL2_PUB_KEY_SIZE); + } + else if (key->level == 3) { + ret = XMEMCMP(key->p, key->k + DILITHIUM_LEVEL3_KEY_SIZE, + DILITHIUM_LEVEL3_PUB_KEY_SIZE); + } + else if (key->level == 5) { + ret = XMEMCMP(key->p, key->k + DILITHIUM_LEVEL5_KEY_SIZE, + DILITHIUM_LEVEL5_PUB_KEY_SIZE); + } + + if (ret != 0) { + ret = PUBLIC_KEY_E; + } + + return ret; + } /* Returns the size of a dilithium private key. @@ -767,7 +887,8 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx, dilithium_key* key, word32 inSz) { int ret = 0; - byte privKey[DILITHIUM_MAX_KEY_SIZE], pubKey[DILITHIUM_MAX_PUB_KEY_SIZE]; + byte privKey[DILITHIUM_MAX_PRV_KEY_SIZE]; + byte pubKey[DILITHIUM_MAX_PUB_KEY_SIZE]; word32 privKeyLen = (word32)sizeof(privKey); word32 pubKeyLen = (word32)sizeof(pubKey); int keytype = 0; diff --git a/wolfcrypt/src/falcon.c b/wolfcrypt/src/falcon.c index ae9947ef8..111119c6c 100644 --- a/wolfcrypt/src/falcon.c +++ b/wolfcrypt/src/falcon.c @@ -62,15 +62,30 @@ int wc_falcon_sign_msg(const byte* in, word32 inLen, falcon_key* key, WC_RNG* rng) { int ret = 0; -#ifdef HAVE_LIBOQS - OQS_SIG *oqssig = NULL; - size_t localOutLen = 0; /* sanity check on arguments */ if ((in == NULL) || (out == NULL) || (outLen == NULL) || (key == NULL)) { - ret = BAD_FUNC_ARG; + return BAD_FUNC_ARG; } +#ifdef WOLF_CRYPTO_CB + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + ret = wc_CryptoCb_PqcSign(in, inLen, out, outLen, rng, + WC_PQC_SIG_TYPE_FALCON, key); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + ret = 0; + } +#endif + +#ifdef HAVE_LIBOQS + OQS_SIG *oqssig = NULL; + size_t localOutLen = 0; + if ((ret == 0) && (!key->prvKeySet)) { ret = BAD_FUNC_ARG; } @@ -88,6 +103,10 @@ int wc_falcon_sign_msg(const byte* in, word32 inLen, } } + if ((ret == 0) && (oqssig == NULL)) { + ret = BUFFER_E; + } + /* check and set up out length */ if (ret == 0) { if ((key->level == 1) && (*outLen < FALCON_LEVEL1_SIG_SIZE)) { @@ -142,13 +161,28 @@ int wc_falcon_verify_msg(const byte* sig, word32 sigLen, const byte* msg, word32 msgLen, int* res, falcon_key* key) { int ret = 0; -#ifdef HAVE_LIBOQS - OQS_SIG *oqssig = NULL; if (key == NULL || sig == NULL || msg == NULL || res == NULL) { - ret = BAD_FUNC_ARG; + return BAD_FUNC_ARG; } +#ifdef WOLF_CRYPTO_CB + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + ret = wc_CryptoCb_PqcVerify(sig, sigLen, msg, msgLen, res, + WC_PQC_SIG_TYPE_FALCON, key); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + ret = 0; + } +#endif + +#ifdef HAVE_LIBOQS + OQS_SIG *oqssig = NULL; + if ((ret == 0) && (!key->pubKeySet)) { ret = BAD_FUNC_ARG; } @@ -166,6 +200,10 @@ int wc_falcon_verify_msg(const byte* sig, word32 sigLen, const byte* msg, } } + if ((ret == 0) && (oqssig == NULL)) { + ret = BUFFER_E; + } + if ((ret == 0) && (OQS_SIG_verify(oqssig, msg, msgLen, sig, sigLen, key->p) == OQS_ERROR)) { @@ -192,15 +230,92 @@ int wc_falcon_verify_msg(const byte* sig, word32 sigLen, const byte* msg, * returns BAD_FUNC_ARG when key is NULL */ int wc_falcon_init(falcon_key* key) +{ + return wc_falcon_init_ex(key, NULL, INVALID_DEVID); +} + +/* Initialize the falcon private/public key. + * + * key [in] Falcon key. + * heap [in] Heap hint. + * devId[in] Device ID. + * returns BAD_FUNC_ARG when key is NULL + */ +int wc_falcon_init_ex(falcon_key* key, void* heap, int devId) { if (key == NULL) { return BAD_FUNC_ARG; } ForceZero(key, sizeof(*key)); + +#ifdef WOLF_CRYPTO_CB + key->devCtx = NULL; + key->devId = devId; +#endif +#ifdef WOLF_PRIVATE_KEY_ID + key->idLen = 0; + key->labelLen = 0; +#endif + + (void) heap; + (void) devId; + return 0; } +#ifdef WOLF_PRIVATE_KEY_ID +int wc_falcon_init_id(falcon_key* key, const unsigned char* id, int len, + void* heap, int devId) +{ + int ret = 0; + + if (key == NULL) + ret = BAD_FUNC_ARG; + if (ret == 0 && (len < 0 || len > FALCON_MAX_ID_LEN)) + ret = BUFFER_E; + + if (ret == 0) + ret = wc_falcon_init_ex(key, heap, devId); + if (ret == 0 && id != NULL && len != 0) { + XMEMCPY(key->id, id, (size_t)len); + key->idLen = len; + } + + /* Set the maxiumum level here */ + wc_falcon_set_level(key, 5); + + return ret; +} + +int wc_falcon_init_label(falcon_key* key, const char* label, void* heap, + int devId) +{ + int ret = 0; + int labelLen = 0; + + if (key == NULL || label == NULL) + ret = BAD_FUNC_ARG; + if (ret == 0) { + labelLen = (int)XSTRLEN(label); + if (labelLen == 0 || labelLen > FALCON_MAX_LABEL_LEN) + ret = BUFFER_E; + } + + if (ret == 0) + ret = wc_falcon_init_ex(key, heap, devId); + if (ret == 0) { + XMEMCPY(key->label, label, (size_t)labelLen); + key->labelLen = labelLen; + } + + /* Set the maxiumum level here */ + wc_falcon_set_level(key, 5); + + return ret; +} +#endif + /* Set the level of the falcon private/public key. * * key [out] Falcon key. @@ -399,12 +514,7 @@ int wc_falcon_import_private_only(const byte* priv, word32 privSz, return ret; } - if (key->level == 1) { - XMEMCPY(key->k, newPriv, FALCON_LEVEL1_KEY_SIZE); - } - else if (key->level == 5) { - XMEMCPY(key->k, newPriv, FALCON_LEVEL5_KEY_SIZE); - } + XMEMCPY(key->k, newPriv, newPrivSz); key->prvKeySet = 1; return 0; @@ -462,12 +572,7 @@ int wc_falcon_import_private_key(const byte* priv, word32 privSz, if (ret == 0) { /* make the private key (priv + pub) */ - if (key->level == 1) { - XMEMCPY(key->k, newPriv, FALCON_LEVEL1_KEY_SIZE); - } - else if (key->level == 5) { - XMEMCPY(key->k, newPriv, FALCON_LEVEL5_KEY_SIZE); - } + XMEMCPY(key->k, newPriv, newPrivSz); key->prvKeySet = 1; } @@ -550,14 +655,14 @@ int wc_falcon_export_private(falcon_key* key, byte* out, word32* outLen) if (key->level == 1) { *outLen = FALCON_LEVEL1_PRV_KEY_SIZE; - XMEMCPY(out, key->k, FALCON_LEVEL1_PRV_KEY_SIZE); - XMEMCPY(out + FALCON_LEVEL1_PRV_KEY_SIZE, key->p, + XMEMCPY(out, key->k, FALCON_LEVEL1_KEY_SIZE); + XMEMCPY(out + FALCON_LEVEL1_KEY_SIZE, key->p, FALCON_LEVEL1_PUB_KEY_SIZE); } else if (key->level == 5) { *outLen = FALCON_LEVEL5_PRV_KEY_SIZE; - XMEMCPY(out, key->k, FALCON_LEVEL5_PRV_KEY_SIZE); - XMEMCPY(out + FALCON_LEVEL5_PRV_KEY_SIZE, key->p, + XMEMCPY(out, key->k, FALCON_LEVEL5_KEY_SIZE); + XMEMCPY(out + FALCON_LEVEL5_KEY_SIZE, key->p, FALCON_LEVEL5_PUB_KEY_SIZE); } @@ -606,8 +711,24 @@ int wc_falcon_check_key(falcon_key* key) return BAD_FUNC_ARG; } - /* Assume everything is fine. */ - return 0; + int ret = 0; + + /* The public key is also decoded and stored within the private key buffer + * behind the private key. Hence, we can compare both stored public keys. */ + if (key->level == 1) { + ret = XMEMCMP(key->p, key->k + FALCON_LEVEL1_KEY_SIZE, + FALCON_LEVEL1_PUB_KEY_SIZE); + } + else if (key->level == 5) { + ret = XMEMCMP(key->p, key->k + FALCON_LEVEL5_KEY_SIZE, + FALCON_LEVEL5_PUB_KEY_SIZE); + } + + if (ret != 0) { + ret = PUBLIC_KEY_E; + } + + return ret; } /* Returns the size of a falcon private key. @@ -702,7 +823,7 @@ int wc_Falcon_PrivateKeyDecode(const byte* input, word32* inOutIdx, falcon_key* key, word32 inSz) { int ret = 0; - byte privKey[FALCON_MAX_KEY_SIZE], pubKey[FALCON_MAX_PUB_KEY_SIZE]; + byte privKey[FALCON_MAX_PRV_KEY_SIZE], pubKey[FALCON_MAX_PUB_KEY_SIZE]; word32 privKeyLen = (word32)sizeof(privKey); word32 pubKeyLen = (word32)sizeof(pubKey); int keytype = 0; diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index 04548e386..759eec2a7 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -71,6 +71,13 @@ #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) #include #endif +#if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + #include +#endif +#if defined(HAVE_PQC) && defined(HAVE_FALCON) + #include +#endif + #ifdef WOLF_CRYPTO_CB_CMD /* CryptoCb Commands */ @@ -201,6 +208,39 @@ typedef struct wc_CryptoInfo { byte contextLen; } ed25519verify; #endif + #if defined(HAVE_PQC) && \ + (defined(HAVE_FALCON) || defined(HAVE_DILITHIUM)) + struct { + WC_RNG* rng; + int size; + void* key; + int type; /* enum wc_PqcSignatureType */ + } pqc_sig_kg; + struct { + const byte* in; + word32 inlen; + byte* out; + word32* outlen; + WC_RNG* rng; + void* key; + int type; /* enum wc_PqcSignatureType */ + } pqc_sign; + struct { + const byte* sig; + word32 siglen; + const byte* msg; + word32 msglen; + int* res; + void* key; + int type; /* enum wc_PqcSignatureType */ + } pqc_verify; + struct { + void* key; + const byte* pubKey; + word32 pubKeySz; + int type; /* enum wc_PqcSignatureType */ + } pqc_sig_check; + #endif #if HAVE_ANONYMOUS_INLINE_AGGREGATES }; #endif @@ -452,6 +492,22 @@ WOLFSSL_LOCAL int wc_CryptoCb_Ed25519Verify(const byte* sig, word32 sigLen, const byte* context, byte contextLen); #endif /* HAVE_ED25519 */ +#if defined(HAVE_PQC) && (defined(HAVE_FALCON) || defined(HAVE_DILITHIUM)) +WOLFSSL_LOCAL int wc_CryptoCb_PqcSigGetDevId(int type, void* key); + +WOLFSSL_LOCAL int wc_CryptoCb_MakePqcSignatureKey(WC_RNG* rng, int type, + int keySize, void* key); + +WOLFSSL_LOCAL int wc_CryptoCb_PqcSign(const byte* in, word32 inlen, byte* out, + word32 *outlen, WC_RNG* rng, int type, void* key); + +WOLFSSL_LOCAL int wc_CryptoCb_PqcVerify(const byte* sig, word32 siglen, + const byte* msg, word32 msglen, int* res, int type, void* key); + +WOLFSSL_LOCAL int wc_CryptoCb_PqcSignatureCheckPrivKey(void* key, int type, + const byte* pubKey, word32 pubKeySz); +#endif /* HAVE_PQC && (HAVE_FALCON || HAVE_DILITHIUM) */ + #ifndef NO_AES #ifdef HAVE_AESGCM WOLFSSL_LOCAL int wc_CryptoCb_AesGcmEncrypt(Aes* aes, byte* out, diff --git a/wolfssl/wolfcrypt/dilithium.h b/wolfssl/wolfcrypt/dilithium.h index 2b5998ffd..5472d092e 100644 --- a/wolfssl/wolfcrypt/dilithium.h +++ b/wolfssl/wolfcrypt/dilithium.h @@ -31,6 +31,10 @@ #include +#ifdef WOLF_CRYPTO_CB + #include +#endif + #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) #ifdef HAVE_LIBOQS @@ -61,17 +65,34 @@ #define DILITHIUM_LEVEL5_PRV_KEY_SIZE (DILITHIUM_LEVEL5_PUB_KEY_SIZE+DILITHIUM_LEVEL5_KEY_SIZE) #endif -#define DILITHIUM_MAX_KEY_SIZE DILITHIUM_LEVEL5_PRV_KEY_SIZE +#define DILITHIUM_MAX_KEY_SIZE DILITHIUM_LEVEL5_KEY_SIZE #define DILITHIUM_MAX_SIG_SIZE DILITHIUM_LEVEL5_SIG_SIZE #define DILITHIUM_MAX_PUB_KEY_SIZE DILITHIUM_LEVEL5_PUB_KEY_SIZE #define DILITHIUM_MAX_PRV_KEY_SIZE DILITHIUM_LEVEL5_PRV_KEY_SIZE +#ifdef WOLF_PRIVATE_KEY_ID +#define DILITHIUM_MAX_ID_LEN 32 +#define DILITHIUM_MAX_LABEL_LEN 32 +#endif + /* Structs */ struct dilithium_key { bool pubKeySet; bool prvKeySet; byte level; /* 2,3 or 5 */ + +#ifdef WOLF_CRYPTO_CB + void* devCtx; + int devId; +#endif +#ifdef WOLF_PRIVATE_KEY_ID + byte id[DILITHIUM_MAX_ID_LEN]; + int idLen; + char label[DILITHIUM_MAX_LABEL_LEN]; + int labelLen; +#endif + byte p[DILITHIUM_MAX_PUB_KEY_SIZE]; byte k[DILITHIUM_MAX_PRV_KEY_SIZE]; }; @@ -92,6 +113,19 @@ int wc_dilithium_verify_msg(const byte* sig, word32 sigLen, const byte* msg, WOLFSSL_API int wc_dilithium_init(dilithium_key* key); + +WOLFSSL_API +int wc_dilithium_init_ex(dilithium_key* key, void* heap, int devId); + +#ifdef WOLF_PRIVATE_KEY_ID +WOLFSSL_API +int wc_dilithium_init_id(dilithium_key* key, const unsigned char* id, int len, + void* heap, int devId); +WOLFSSL_API +int wc_dilithium_init_label(dilithium_key* key, const char* label, void* heap, + int devId); +#endif + WOLFSSL_API int wc_dilithium_set_level(dilithium_key* key, byte level); WOLFSSL_API diff --git a/wolfssl/wolfcrypt/falcon.h b/wolfssl/wolfcrypt/falcon.h index c444a302b..9d4bff8be 100644 --- a/wolfssl/wolfcrypt/falcon.h +++ b/wolfssl/wolfcrypt/falcon.h @@ -31,6 +31,10 @@ #include +#ifdef WOLF_CRYPTO_CB + #include +#endif + #if defined(HAVE_PQC) && defined(HAVE_FALCON) #ifdef HAVE_LIBOQS @@ -56,17 +60,35 @@ #define FALCON_LEVEL5_PRV_KEY_SIZE (FALCON_LEVEL5_PUB_KEY_SIZE+FALCON_LEVEL5_KEY_SIZE) #endif -#define FALCON_MAX_KEY_SIZE FALCON_LEVEL5_PRV_KEY_SIZE +#define FALCON_MAX_KEY_SIZE FALCON_LEVEL5_KEY_SIZE #define FALCON_MAX_SIG_SIZE FALCON_LEVEL5_SIG_SIZE #define FALCON_MAX_PUB_KEY_SIZE FALCON_LEVEL5_PUB_KEY_SIZE #define FALCON_MAX_PRV_KEY_SIZE FALCON_LEVEL5_PRV_KEY_SIZE +#ifdef WOLF_PRIVATE_KEY_ID +#define FALCON_MAX_ID_LEN 32 +#define FALCON_MAX_LABEL_LEN 32 +#endif + + /* Structs */ struct falcon_key { bool pubKeySet; bool prvKeySet; byte level; + +#ifdef WOLF_CRYPTO_CB + void* devCtx; + int devId; +#endif +#ifdef WOLF_PRIVATE_KEY_ID + byte id[FALCON_MAX_ID_LEN]; + int idLen; + char label[FALCON_MAX_LABEL_LEN]; + int labelLen; +#endif + byte p[FALCON_MAX_PUB_KEY_SIZE]; byte k[FALCON_MAX_PRV_KEY_SIZE]; }; @@ -87,6 +109,19 @@ int wc_falcon_verify_msg(const byte* sig, word32 sigLen, const byte* msg, WOLFSSL_API int wc_falcon_init(falcon_key* key); + +WOLFSSL_API +int wc_falcon_init_ex(falcon_key* key, void* heap, int devId); + +#ifdef WOLF_PRIVATE_KEY_ID +WOLFSSL_API +int wc_falcon_init_id(falcon_key* key, const unsigned char* id, int len, + void* heap, int devId); +WOLFSSL_API +int wc_falcon_init_label(falcon_key* key, const char* label, void* heap, + int devId); +#endif + WOLFSSL_API int wc_falcon_set_level(falcon_key* key, byte level); WOLFSSL_API diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 53d022161..1d2f72c20 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1169,9 +1169,36 @@ typedef struct w64wrapper { WC_PK_TYPE_ED25519_KEYGEN = 15, WC_PK_TYPE_CURVE25519_KEYGEN = 16, WC_PK_TYPE_RSA_GET_SIZE = 17, - WC_PK_TYPE_MAX = WC_PK_TYPE_RSA_GET_SIZE + #define _WC_PK_TYPE_MAX WC_PK_TYPE_RSA_GET_SIZE + #if defined(HAVE_PQC) && (defined(HAVE_DILITHIUM) || defined(HAVE_FALCON)) + WC_PK_TYPE_PQC_SIG_KEYGEN = 18, + WC_PK_TYPE_PQC_SIG_SIGN = 19, + WC_PK_TYPE_PQC_SIG_VERIFY = 20, + WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY = 21, + #undef _WC_PK_TYPE_MAX + #define _WC_PK_TYPE_MAX WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY + #endif + WC_PK_TYPE_MAX = _WC_PK_TYPE_MAX }; + #if defined(HAVE_PQC) + /* Post quantum signature algorithms */ + enum wc_PqcSignatureType { + WC_PQC_SIG_TYPE_NONE = 0, + #define _WC_PQC_SIG_TYPE_MAX WC_PQC_SIG_TYPE_NONE + #if defined(HAVE_DILITHIUM) + WC_PQC_SIG_TYPE_DILITHIUM = 1, + #undef _WC_PQC_SIG_TYPE_MAX + #define _WC_PQC_SIG_TYPE_MAX WC_PQC_SIG_TYPE_DILITHIUM + #endif + #if defined(HAVE_FALCON) + WC_PQC_SIG_TYPE_FALCON = 2, + #undef _WC_PQC_SIG_TYPE_MAX + #define _WC_PQC_SIG_TYPE_MAX WC_PQC_SIG_TYPE_FALCON + #endif + WC_PQC_SIG_TYPE_MAX = _WC_PQC_SIG_TYPE_MAX + }; + #endif /* settings detection for compile vs runtime math incompatibilities */ enum { From 4d259da60a5d57c443267aa2eab53ea712edc075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Wed, 20 Dec 2023 16:22:07 +0100 Subject: [PATCH 2/3] PQC: CryptoCb support for KEM algorithm Kyber MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for crypto callback and device id for all three Kyber PQC KEM function calls. Signed-off-by: Tobias Frauenschläger --- src/internal.c | 6 +- src/tls.c | 4 +- wolfcrypt/src/cryptocb.c | 123 ++++++++++++++++++++++++++++++++++ wolfcrypt/src/ext_kyber.c | 65 +++++++++++++++--- wolfssl/wolfcrypt/cryptocb.h | 48 +++++++++++++ wolfssl/wolfcrypt/ext_kyber.h | 10 +++ wolfssl/wolfcrypt/types.h | 27 ++++++-- 7 files changed, 266 insertions(+), 17 deletions(-) diff --git a/src/internal.c b/src/internal.c index fc462c14e..22cd79d1f 100644 --- a/src/internal.c +++ b/src/internal.c @@ -27462,7 +27462,8 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType, } if (label) { - ret = wc_dilithium_init_label(dilithiumKey, (char*)data, heap, devId); + ret = wc_dilithium_init_label(dilithiumKey, (char*)data, + heap, devId); } else if (id) { ret = wc_dilithium_init_id(dilithiumKey, data, length, heap, devId); @@ -27654,7 +27655,8 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } /* Return the maximum signature length. */ - *length = (word16)wc_dilithium_sig_size((dilithium_key*)ssl->hsKey); + *length = (word16)wc_dilithium_sig_size( + (dilithium_key*)ssl->hsKey); } #else ret = NOT_COMPILED_IN; diff --git a/src/tls.c b/src/tls.c index b8b7e8c54..ec6fafb68 100644 --- a/src/tls.c +++ b/src/tls.c @@ -8415,7 +8415,7 @@ static int TLSX_KeyShare_ProcessPqc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) return BAD_FUNC_ARG; } - ret = wc_KyberKey_Init(type, kem, ssl->heap, INVALID_DEVID); + ret = wc_KyberKey_Init(type, kem, ssl->heap, ssl->devId); if (ret != 0) { wc_ecc_free(&eccpubkey); WOLFSSL_MSG("Error creating Kyber KEM"); @@ -8907,7 +8907,7 @@ static int server_generate_pqc_ciphertext(WOLFSSL* ssl, return MEMORY_E; } - ret = wc_KyberKey_Init(type, kem, ssl->heap, INVALID_DEVID); + ret = wc_KyberKey_Init(type, kem, ssl->heap, ssl->devId); if (ret != 0) { wc_ecc_free(&eccpubkey); WOLFSSL_MSG("Error creating Kyber KEM"); diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index 3996ceaa4..07b37f1ba 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -785,6 +785,129 @@ int wc_CryptoCb_Ed25519Verify(const byte* sig, word32 sigLen, } #endif /* HAVE_ED25519 */ +#if defined(HAVE_PQC) && defined(WOLFSSL_HAVE_KYBER) +int wc_CryptoCb_PqcKemGetDevId(int type, void* key) +{ + int devId = INVALID_DEVID; + + if (key == NULL) + return devId; + + /* get devId */ +#if defined(WOLFSSL_HAVE_KYBER) + if (type == WC_PQC_KEM_TYPE_KYBER) { + devId = ((KyberKey*) key)->devId; + } +#endif + + return devId; +} + +int wc_CryptoCb_MakePqcKemKey(WC_RNG* rng, int type, int keySize, void* key) +{ + int ret = CRYPTOCB_UNAVAILABLE; + int devId = INVALID_DEVID; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* get devId */ + devId = wc_CryptoCb_PqcKemGetDevId(type, key); + if (devId == INVALID_DEVID) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_PK); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_PQC_KEM_KEYGEN; + cryptoInfo.pk.pqc_kem_kg.rng = rng; + cryptoInfo.pk.pqc_kem_kg.size = keySize; + cryptoInfo.pk.pqc_kem_kg.key = key; + cryptoInfo.pk.pqc_kem_kg.type = type; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_PqcEncapsulate(byte* ciphertext, word32 ciphertextLen, + byte* sharedSecret, word32 sharedSecretLen, WC_RNG* rng, int type, + void* key) +{ + int ret = CRYPTOCB_UNAVAILABLE; + int devId = INVALID_DEVID; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* get devId */ + devId = wc_CryptoCb_PqcKemGetDevId(type, key); + if (devId == INVALID_DEVID) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_PK); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_PQC_KEM_ENCAPS; + cryptoInfo.pk.pqc_encaps.ciphertext = ciphertext; + cryptoInfo.pk.pqc_encaps.ciphertextLen = ciphertextLen; + cryptoInfo.pk.pqc_encaps.sharedSecret = sharedSecret; + cryptoInfo.pk.pqc_encaps.sharedSecretLen = sharedSecretLen; + cryptoInfo.pk.pqc_encaps.rng = rng; + cryptoInfo.pk.pqc_encaps.key = key; + cryptoInfo.pk.pqc_encaps.type = type; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_PqcDecapsulate(const byte* ciphertext, word32 ciphertextLen, + byte* sharedSecret, word32 sharedSecretLen, int type, void* key) +{ + int ret = CRYPTOCB_UNAVAILABLE; + int devId = INVALID_DEVID; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* get devId */ + devId = wc_CryptoCb_PqcKemGetDevId(type, key); + if (devId == INVALID_DEVID) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_PK); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_PQC_KEM_DECAPS; + cryptoInfo.pk.pqc_decaps.ciphertext = ciphertext; + cryptoInfo.pk.pqc_decaps.ciphertextLen = ciphertextLen; + cryptoInfo.pk.pqc_decaps.sharedSecret = sharedSecret; + cryptoInfo.pk.pqc_decaps.sharedSecretLen = sharedSecretLen; + cryptoInfo.pk.pqc_decaps.key = key; + cryptoInfo.pk.pqc_decaps.type = type; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* HAVE_PQC && WOLFSSL_HAVE_KYBER */ + #if defined(HAVE_PQC) && (defined(HAVE_FALCON) || defined(HAVE_DILITHIUM)) int wc_CryptoCb_PqcSigGetDevId(int type, void* key) { diff --git a/wolfcrypt/src/ext_kyber.c b/wolfcrypt/src/ext_kyber.c index ea2ac83b1..0e694c097 100644 --- a/wolfcrypt/src/ext_kyber.c +++ b/wolfcrypt/src/ext_kyber.c @@ -101,10 +101,15 @@ int wc_KyberKey_Init(int type, KyberKey* key, void* heap, int devId) /* Keep type for parameters. */ key->type = type; + +#ifdef WOLF_CRYPTO_CB + key->devCtx = NULL; + key->devId = devId; +#endif } - (void)devId; (void)heap; + (void)devId; return ret; } @@ -312,13 +317,25 @@ int wc_KyberKey_MakeKey(KyberKey* key, WC_RNG* rng) OQS_KEM *kem = NULL; #endif - (void)rng; - /* Validate parameter. */ if (key == NULL) { return BAD_FUNC_ARG; } +#ifdef WOLF_CRYPTO_CB + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + ret = wc_CryptoCb_MakePqcKemKey(rng, WC_PQC_KEM_TYPE_KYBER, + key->type, key); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + ret = 0; + } +#endif + #ifdef HAVE_LIBOQS if (ret == 0) { algName = OQS_ID2name(key->type); @@ -327,12 +344,6 @@ int wc_KyberKey_MakeKey(KyberKey* key, WC_RNG* rng) } } - if (ret == 0) { - algName = OQS_ID2name(key->type); - if (algName == NULL) { - ret = BAD_FUNC_ARG; - } - } if (ret == 0) { kem = OQS_KEM_new(algName); if (kem == NULL) { @@ -403,6 +414,9 @@ int wc_KyberKey_Encapsulate(KyberKey* key, unsigned char* ct, unsigned char* ss, WC_RNG* rng) { int ret = 0; +#ifdef WOLF_CRYPTO_CB + word32 ctlen = 0; +#endif #ifdef HAVE_LIBOQS const char * algName = NULL; OQS_KEM *kem = NULL; @@ -415,6 +429,24 @@ int wc_KyberKey_Encapsulate(KyberKey* key, unsigned char* ct, unsigned char* ss, ret = BAD_FUNC_ARG; } +#ifdef WOLF_CRYPTO_CB + if (ret == 0) { + ret = wc_KyberKey_CipherTextSize(key, &ctlen); + } + if ((ret == 0) + #ifndef WOLF_CRYPTO_CB_FIND + && (key->devId != INVALID_DEVID) + #endif + ) { + ret = wc_CryptoCb_PqcEncapsulate(ct, ctlen, ss, KYBER_SS_SZ, rng, + WC_PQC_KEM_TYPE_KYBER, key); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + ret = 0; + } +#endif + #ifdef HAVE_LIBOQS if (ret == 0) { algName = OQS_ID2name(key->type); @@ -509,6 +541,21 @@ int wc_KyberKey_Decapsulate(KyberKey* key, unsigned char* ss, ret = BUFFER_E; } +#ifdef WOLF_CRYPTO_CB + if ((ret == 0) + #ifndef WOLF_CRYPTO_CB_FIND + && (key->devId != INVALID_DEVID) + #endif + ) { + ret = wc_CryptoCb_PqcDecapsulate(ct, ctlen, ss, KYBER_SS_SZ, + WC_PQC_KEM_TYPE_KYBER, key); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + ret = 0; + } +#endif + #ifdef HAVE_LIBOQS if (ret == 0) { algName = OQS_ID2name(key->type); diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index 759eec2a7..8f6677750 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -71,6 +71,14 @@ #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) #include #endif +#ifdef HAVE_PQC + #include +#ifdef WOLFSSL_WC_KYBER + #include +#elif defined(HAVE_LIBOQS) || defined(HAVE_PQM4) + #include +#endif +#endif #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) #include #endif @@ -208,6 +216,31 @@ typedef struct wc_CryptoInfo { byte contextLen; } ed25519verify; #endif + #if defined(HAVE_PQC) && defined(WOLFSSL_HAVE_KYBER) + struct { + WC_RNG* rng; + int size; + void* key; + int type; /* enum wc_PqcKemType */ + } pqc_kem_kg; + struct { + byte* ciphertext; + word32 ciphertextLen; + byte* sharedSecret; + word32 sharedSecretLen; + WC_RNG* rng; + void* key; + int type; /* enum wc_PqcKemType */ + } pqc_encaps; + struct { + const byte* ciphertext; + word32 ciphertextLen; + byte* sharedSecret; + word32 sharedSecretLen; + void* key; + int type; /* enum wc_PqcKemType */ + } pqc_decaps; + #endif #if defined(HAVE_PQC) && \ (defined(HAVE_FALCON) || defined(HAVE_DILITHIUM)) struct { @@ -492,6 +525,21 @@ WOLFSSL_LOCAL int wc_CryptoCb_Ed25519Verify(const byte* sig, word32 sigLen, const byte* context, byte contextLen); #endif /* HAVE_ED25519 */ +#if defined(HAVE_PQC) && defined(WOLFSSL_HAVE_KYBER) +WOLFSSL_LOCAL int wc_CryptoCb_PqcKemGetDevId(int type, void* key); + +WOLFSSL_LOCAL int wc_CryptoCb_MakePqcKemKey(WC_RNG* rng, int type, + int keySize, void* key); + +WOLFSSL_LOCAL int wc_CryptoCb_PqcEncapsulate(byte* ciphertext, + word32 ciphertextLen, byte* sharedSecret, word32 sharedSecretLen, + WC_RNG* rng, int type, void* key); + +WOLFSSL_LOCAL int wc_CryptoCb_PqcDecapsulate(const byte* ciphertext, + word32 ciphertextLen, byte* sharedSecret, word32 sharedSecretLen, + int type, void* key); +#endif /* HAVE_PQC && WOLFSSL_HAVE_KYBER */ + #if defined(HAVE_PQC) && (defined(HAVE_FALCON) || defined(HAVE_DILITHIUM)) WOLFSSL_LOCAL int wc_CryptoCb_PqcSigGetDevId(int type, void* key); diff --git a/wolfssl/wolfcrypt/ext_kyber.h b/wolfssl/wolfcrypt/ext_kyber.h index 53c175d77..0ea7108b1 100644 --- a/wolfssl/wolfcrypt/ext_kyber.h +++ b/wolfssl/wolfcrypt/ext_kyber.h @@ -22,6 +22,10 @@ #ifndef EXT_KYBER_H #define EXT_KYBER_H +#ifdef WOLF_CRYPTO_CB + #include +#endif + #ifdef WOLFSSL_HAVE_KYBER #include @@ -56,6 +60,12 @@ struct KyberKey { * Note we don't save the variant (SHAKE vs AES) as that is decided at * configuration time. */ int type; + +#ifdef WOLF_CRYPTO_CB + void* devCtx; + int devId; +#endif + byte priv[EXT_KYBER_MAX_PRIV_SZ]; byte pub[EXT_KYBER_MAX_PUB_SZ]; }; diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 1d2f72c20..5db92f3d8 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1170,11 +1170,18 @@ typedef struct w64wrapper { WC_PK_TYPE_CURVE25519_KEYGEN = 16, WC_PK_TYPE_RSA_GET_SIZE = 17, #define _WC_PK_TYPE_MAX WC_PK_TYPE_RSA_GET_SIZE + #if defined(HAVE_PQC) && defined(WOLFSSL_HAVE_KYBER) + WC_PK_TYPE_PQC_KEM_KEYGEN = 18, + WC_PK_TYPE_PQC_KEM_ENCAPS = 19, + WC_PK_TYPE_PQC_KEM_DECAPS = 20, + #undef _WC_PK_TYPE_MAX + #define _WC_PK_TYPE_MAX WC_PK_TYPE_PQC_KEM_DECAPS + #endif #if defined(HAVE_PQC) && (defined(HAVE_DILITHIUM) || defined(HAVE_FALCON)) - WC_PK_TYPE_PQC_SIG_KEYGEN = 18, - WC_PK_TYPE_PQC_SIG_SIGN = 19, - WC_PK_TYPE_PQC_SIG_VERIFY = 20, - WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY = 21, + WC_PK_TYPE_PQC_SIG_KEYGEN = 21, + WC_PK_TYPE_PQC_SIG_SIGN = 22, + WC_PK_TYPE_PQC_SIG_VERIFY = 23, + WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY = 24, #undef _WC_PK_TYPE_MAX #define _WC_PK_TYPE_MAX WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY #endif @@ -1182,6 +1189,18 @@ typedef struct w64wrapper { }; #if defined(HAVE_PQC) + /* Post quantum KEM algorithms */ + enum wc_PqcKemType { + WC_PQC_KEM_TYPE_NONE = 0, + #define _WC_PQC_KEM_TYPE_MAX WC_PQC_KEM_TYPE_NONE + #if defined(WOLFSSL_HAVE_KYBER) + WC_PQC_KEM_TYPE_KYBER = 1, + #undef _WC_PQC_KEM_TYPE_MAX + #define _WC_PQC_KEM_TYPE_MAX WC_PQC_KEM_TYPE_KYBER + #endif + WC_PQC_KEM_TYPE_MAX = _WC_PQC_KEM_TYPE_MAX + }; + /* Post quantum signature algorithms */ enum wc_PqcSignatureType { WC_PQC_SIG_TYPE_NONE = 0, From 68ea31c52a104896422dad5ef6168f071bba4f24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Thu, 18 Jan 2024 17:07:39 +0100 Subject: [PATCH 3/3] Fix install step for liboqs port header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure the header file of the liboqs port is properly installed during a call to `make install`. Signed-off-by: Tobias Frauenschläger --- wolfssl/wolfcrypt/include.am | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 373f09b22..148b8a6d2 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -115,8 +115,7 @@ noinst_HEADERS+= \ wolfssl/wolfcrypt/port/Renesas/renesas_sync.h \ wolfssl/wolfcrypt/port/Renesas/renesas_cmn.h \ wolfssl/wolfcrypt/port/Renesas/renesas_tsip_types.h \ - wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h \ - wolfssl/wolfcrypt/port/liboqs/liboqs.h + wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h if BUILD_CRYPTOAUTHLIB nobase_include_HEADERS+= wolfssl/wolfcrypt/port/atmel/atmel.h @@ -145,6 +144,10 @@ nobase_include_HEADERS+= wolfssl/wolfcrypt/port/aria/aria-crypt.h nobase_include_HEADERS+= wolfssl/wolfcrypt/port/aria/aria-cryptocb.h endif +if BUILD_LIBOQS +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/liboqs/liboqs.h +endif + if BUILD_ASYNCCRYPT nobase_include_HEADERS+= wolfssl/wolfcrypt/async.h endif