PQC: CryptoCb support for signature algorithms

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 <t.frauenschlaeger@me.com>
This commit is contained in:
Tobias Frauenschläger
2023-12-06 17:44:20 +01:00
parent 4f8fd98d0d
commit 8e6d151403
10 changed files with 784 additions and 70 deletions

View File

@ -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;

View File

@ -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);
}

View File

@ -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(

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -71,6 +71,13 @@
#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
#include <wolfssl/wolfcrypt/sha512.h>
#endif
#if defined(HAVE_PQC) && defined(HAVE_DILITHIUM)
#include <wolfssl/wolfcrypt/dilithium.h>
#endif
#if defined(HAVE_PQC) && defined(HAVE_FALCON)
#include <wolfssl/wolfcrypt/falcon.h>
#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,

View File

@ -31,6 +31,10 @@
#include <wolfssl/wolfcrypt/types.h>
#ifdef WOLF_CRYPTO_CB
#include <wolfssl/wolfcrypt/cryptocb.h>
#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

View File

@ -31,6 +31,10 @@
#include <wolfssl/wolfcrypt/types.h>
#ifdef WOLF_CRYPTO_CB
#include <wolfssl/wolfcrypt/cryptocb.h>
#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

View File

@ -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 {