123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687 |
- /* ext_kyber.c
- *
- * Copyright (C) 2006-2022 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <wolfssl/wolfcrypt/settings.h>
- #include <wolfssl/wolfcrypt/error-crypt.h>
- #ifdef WOLFSSL_HAVE_KYBER
- #include <wolfssl/wolfcrypt/ext_kyber.h>
- #ifdef NO_INLINE
- #include <wolfssl/wolfcrypt/misc.h>
- #else
- #define WOLFSSL_MISC_INCLUDED
- #include <wolfcrypt/src/misc.c>
- #endif
- #if defined (HAVE_LIBOQS)
- static const char* OQS_ID2name(int id) {
- switch (id) {
- case KYBER_LEVEL1: return OQS_KEM_alg_kyber_512;
- case KYBER_LEVEL3: return OQS_KEM_alg_kyber_768;
- case KYBER_LEVEL5: return OQS_KEM_alg_kyber_1024;
- default: break;
- }
- return NULL;
- }
- int ext_kyber_enabled(int id)
- {
- const char * name = OQS_ID2name(id);
- return OQS_KEM_alg_is_enabled(name);
- }
- #endif
- /******************************************************************************/
- /* Initializer and cleanup functions. */
- /**
- * Initialize the Kyber key.
- *
- * @param [in] type Type of key: KYBER512, KYBER768, KYBER1024.
- * @param [out] key Kyber key object to initialize.
- * @param [in] heap Dynamic memory hint.
- * @param [in] devId Device Id.
- * @return 0 on success.
- * @return BAD_FUNC_ARG when key is NULL or type is unrecognized.
- * @return NOT_COMPILED_IN when key type is not supported.
- */
- int wc_KyberKey_Init(int type, KyberKey* key, void* heap, int devId)
- {
- int ret = 0;
- /* Validate key. */
- if (key == NULL) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == 0) {
- /* Validate type. */
- switch (type) {
- case KYBER_LEVEL1:
- #ifdef HAVE_LIBOQS
- case KYBER_LEVEL3:
- case KYBER_LEVEL5:
- #endif /* HAVE_LIBOQS */
- break;
- default:
- /* No other values supported. */
- ret = BAD_FUNC_ARG;
- break;
- }
- }
- if (ret == 0) {
- /* Zero out all data. */
- XMEMSET(key, 0, sizeof(*key));
- /* Keep type for parameters. */
- key->type = type;
- }
- (void)devId;
- (void)heap;
- return ret;
- }
- /**
- * Free the Kyber key object.
- *
- * @param [in, out] key Kyber key object to dispose of.
- */
- void wc_KyberKey_Free(KyberKey* key)
- {
- if (key != NULL) {
- /* Ensure all private data is zeroed. */
- ForceZero(key, sizeof(*key));
- }
- }
- /******************************************************************************/
- /* Data size getters. */
- /**
- * Get the size in bytes of encoded private key for the key.
- *
- * @param [in] key Kyber key object.
- * @param [out] len Length of encoded private key in bytes.
- * @return 0 on success.
- * @return BAD_FUNC_ARG when key or len is NULL.
- * @return NOT_COMPILED_IN when key type is not supported.
- */
- int wc_KyberKey_PrivateKeySize(KyberKey* key, word32* len)
- {
- int ret = 0;
- /* Validate parameters. */
- if ((key == NULL) || (len == NULL)) {
- ret = BAD_FUNC_ARG;
- }
- #ifdef HAVE_LIBOQS
- /* NOTE: SHAKE and AES variants have the same length private key. */
- if (ret == 0) {
- switch (key->type) {
- case KYBER_LEVEL1:
- *len = OQS_KEM_kyber_512_length_secret_key;
- break;
- case KYBER_LEVEL3:
- *len = OQS_KEM_kyber_768_length_secret_key;
- break;
- case KYBER_LEVEL5:
- *len = OQS_KEM_kyber_1024_length_secret_key;
- break;
- default:
- /* No other values supported. */
- ret = BAD_FUNC_ARG;
- break;
- }
- }
- #endif /* HAVE_LIBOQS */
- #ifdef HAVE_PQM4
- (void)key;
- if (ret == 0) {
- *len = PQM4_PRIVATE_KEY_LENGTH;
- }
- #endif /* HAVE_PQM4 */
- return ret;
- }
- /**
- * Get the size in bytes of encoded public key for the key.
- *
- * @param [in] key Kyber key object.
- * @param [out] len Length of encoded public key in bytes.
- * @return 0 on success.
- * @return BAD_FUNC_ARG when key or len is NULL.
- * @return NOT_COMPILED_IN when key type is not supported.
- */
- int wc_KyberKey_PublicKeySize(KyberKey* key, word32* len)
- {
- int ret = 0;
- /* Validate parameters. */
- if ((key == NULL) || (len == NULL)) {
- ret = BAD_FUNC_ARG;
- }
- #ifdef HAVE_LIBOQS
- /* NOTE: SHAKE and AES variants have the same length public key. */
- if (ret == 0) {
- switch (key->type) {
- case KYBER_LEVEL1:
- *len = OQS_KEM_kyber_512_length_public_key;
- break;
- case KYBER_LEVEL3:
- *len = OQS_KEM_kyber_768_length_public_key;
- break;
- case KYBER_LEVEL5:
- *len = OQS_KEM_kyber_1024_length_public_key;
- break;
- default:
- /* No other values supported. */
- ret = BAD_FUNC_ARG;
- break;
- }
- }
- #endif /* HAVE_LIBOQS */
- #ifdef HAVE_PQM4
- (void)key;
- if (ret == 0) {
- *len = PQM4_PUBLIC_KEY_LENGTH;
- }
- #endif /* HAVE_PQM4 */
- return ret;
- }
- /**
- * Get the size in bytes of cipher text for key.
- *
- * @param [in] key Kyber key object.
- * @param [out] len Length of cipher text in bytes.
- * @return 0 on success.
- * @return BAD_FUNC_ARG when key or len is NULL.
- * @return NOT_COMPILED_IN when key type is not supported.
- */
- int wc_KyberKey_CipherTextSize(KyberKey* key, word32* len)
- {
- int ret = 0;
- /* Validate parameters. */
- if ((key == NULL) || (len == NULL)) {
- ret = BAD_FUNC_ARG;
- }
- #ifdef HAVE_LIBOQS
- /* NOTE: SHAKE and AES variants have the same length ciphertext. */
- if (ret == 0) {
- switch (key->type) {
- case KYBER_LEVEL1:
- *len = OQS_KEM_kyber_512_length_ciphertext;
- break;
- case KYBER_LEVEL3:
- *len = OQS_KEM_kyber_768_length_ciphertext;
- break;
- case KYBER_LEVEL5:
- *len = OQS_KEM_kyber_1024_length_ciphertext;
- break;
- default:
- /* No other values supported. */
- ret = BAD_FUNC_ARG;
- break;
- }
- }
- #endif /* HAVE_LIBOQS */
- #ifdef HAVE_PQM4
- (void)key;
- if (ret == 0) {
- *len = PQM4_CIPHERTEXT_LENGTH;
- }
- #endif /* HAVE_PQM4 */
- return ret;
- }
- /**
- * Size of a shared secret in bytes. Always KYBER_SS_SZ.
- *
- * @param [in] key Kyber key object. Not used.
- * @param [out] Size of the shared secret created with a Kyber key.
- * @return 0 on success.
- * @return 0 to indicate success.
- */
- int wc_KyberKey_SharedSecretSize(KyberKey* key, word32* len)
- {
- (void)key;
- /* Validate parameters. */
- if (len == NULL) {
- return BAD_FUNC_ARG;
- }
- *len = KYBER_SS_SZ;
- return 0;
- }
- /******************************************************************************/
- /* Cryptographic operations. */
- /**
- * Make a Kyber key object using a random number generator.
- *
- * NOTE: rng is ignored. OQS and PQM4 don't use our RNG.
- *
- * @param [in, out] key Kyber key ovject.
- * @param [in] rng Random number generator.
- * @return 0 on success.
- * @return BAD_FUNC_ARG when key or rng is NULL.
- * @return MEMORY_E when dynamic memory allocation failed.
- */
- int wc_KyberKey_MakeKey(KyberKey* key, WC_RNG* rng)
- {
- int ret = 0;
- const char* algName = NULL;
- OQS_KEM *kem = NULL;
- (void)rng;
- /* Validate parameter. */
- if (key == NULL) {
- return BAD_FUNC_ARG;
- }
- #ifdef HAVE_LIBOQS
- if (ret == 0) {
- algName = OQS_ID2name(key->type);
- if (algName == NULL) {
- ret = BAD_FUNC_ARG;
- }
- }
- 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) {
- ret = BAD_FUNC_ARG;
- }
- }
- if (ret == 0) {
- if (OQS_KEM_keypair(kem, key->pub, key->priv) !=
- OQS_SUCCESS) {
- ret = BAD_FUNC_ARG;
- }
- }
- #endif /* HAVE_LIBOQS */
- #ifdef HAVE_PQM4
- if (ret == 0) {
- if (crypto_kem_keypair(key->pub, key->priv) != 0) {
- WOLFSSL_MSG("PQM4 keygen failure");
- ret = BAD_FUNC_ARG;
- }
- }
- #endif /* HAVE_PQM4 */
- if (ret != 0) {
- ForceZero(key, sizeof(*key));
- }
- OQS_KEM_free(kem);
- return ret;
- }
- /**
- * Make a Kyber key object using random data.
- *
- * @param [in, out] key Kyber key ovject.
- * @param [in] rng Random number generator.
- * @return 0 on success.
- * @return BAD_FUNC_ARG when key or rand is NULL.
- * @return BUFFER_E when length is not KYBER_MAKEKEY_RAND_SZ.
- * @return NOT_COMPILED_IN when key type is not supported.
- * @return MEMORY_E when dynamic memory allocation failed.
- */
- int wc_KyberKey_MakeKeyWithRandom(KyberKey* key, const unsigned char* rand,
- int len)
- {
- (void)rand;
- (void)len;
- /* OQS and PQM4 don't support external randomness. */
- return wc_KyberKey_MakeKey(key, NULL);
- }
- /**
- * Encapsulate with random number generator and derive secret.
- *
- * @param [in] key Kyber key object.
- * @param [out] ct Cipher text.
- * @param [out] ss Shared secret generated.
- * @param [in] rng Random number generator.
- * @return 0 on success.
- * @return BAD_FUNC_ARG when key, ct, ss or RNG is NULL.
- * @return NOT_COMPILED_IN when key type is not supported.
- * @return MEMORY_E when dynamic memory allocation failed.
- */
- int wc_KyberKey_Encapsulate(KyberKey* key, unsigned char* ct, unsigned char* ss,
- WC_RNG* rng)
- {
- int ret = 0;
- const char * algName = NULL;
- OQS_KEM *kem = NULL;
- (void)rng;
- /* Validate parameters. */
- if ((key == NULL) || (ct == NULL) || (ss == NULL)) {
- ret = BAD_FUNC_ARG;
- }
- #ifdef HAVE_LIBOQS
- 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) {
- ret = BAD_FUNC_ARG;
- }
- }
- if (ret == 0) {
- if (OQS_KEM_encaps(kem, ct, ss, key->pub) != OQS_SUCCESS) {
- ret = BAD_FUNC_ARG;
- }
- }
- #endif /* HAVE_LIBOQS */
- #ifdef HAVE_PQM4
- if (ret == 0) {
- if (crypto_kem_enc(ct, ss, key->pub) != 0) {
- WOLFSSL_MSG("PQM4 Encapsulation failure.");
- ret = BAD_FUNC_ARG;
- }
- }
- #endif /* HAVE_PQM4 */
- OQS_KEM_free(kem);
- return ret;
- }
- /**
- * Encapsulate with random data and derive secret.
- *
- * @param [out] ct Cipher text.
- * @param [out] ss Shared secret generated.
- * @param [in] rand Random data.
- * @param [in] len Random data.
- * @return 0 on success.
- * @return BAD_FUNC_ARG when key, ct, ss or RNG is NULL.
- * @return BUFFER_E when len is not KYBER_ENC_RAND_SZ.
- * @return NOT_COMPILED_IN when key type is not supported.
- * @return MEMORY_E when dynamic memory allocation failed.
- */
- int wc_KyberKey_EncapsulateWithRandom(KyberKey* key, unsigned char* ct,
- unsigned char* ss, const unsigned char* rand, int len)
- {
- (void)rand;
- (void)len;
- /* OQS and PQM4 don't support external randomness. */
- return wc_KyberKey_Encapsulate(key, ct, ss, NULL);
- }
- /**
- * Decapsulate the cipher text to calculate the shared secret.
- *
- * Validates the cipher text by encapsulating and comparing with data passed in.
- *
- * @param [in] key Kyber key object.
- * @param [out] ss Shared secret.
- * @param [in] ct Cipher text.
- * @param [in] len Length of cipher text.
- * @return 0 on success.
- * @return BAD_FUNC_ARG when key, ss or cr are NULL.
- * @return NOT_COMPILED_IN when key type is not supported.
- * @return BUFFER_E when len is not the length of cipher text for the key type.
- * @return MEMORY_E when dynamic memory allocation failed.
- */
- int wc_KyberKey_Decapsulate(KyberKey* key, unsigned char* ss,
- const unsigned char* ct, word32 len)
- {
- int ret = 0;
- const char * algName = NULL;
- word32 ctlen = 0;
- OQS_KEM *kem = NULL;
- /* Validate parameters. */
- if ((key == NULL) || (ss == NULL) || (ct == NULL)) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == 0) {
- ret = wc_KyberKey_CipherTextSize(key, &ctlen);
- }
- if ((ret == 0) && (len != ctlen)) {
- ret = BUFFER_E;
- }
- #ifdef HAVE_LIBOQS
- 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) {
- ret = BAD_FUNC_ARG;
- }
- }
- if (ret == 0) {
- if (OQS_KEM_decaps(kem, ss, ct, key->priv) != OQS_SUCCESS) {
- ret = BAD_FUNC_ARG;
- }
- }
- #endif /* HAVE_LIBOQS */
- #ifdef HAVE_PQM4
- if (ret == 0) {
- if (crypto_kem_enc(ss, ct, key->priv) != 0) {
- WOLFSSL_MSG("PQM4 Decapsulation failure.");
- ret = BAD_FUNC_ARG;
- }
- }
- #endif /* HAVE_PQM4 */
- OQS_KEM_free(kem);
- return ret;
- }
- /******************************************************************************/
- /* Encoding and decoding functions. */
- /**
- * Decode the private key.
- *
- * We store the whole thing in the private key buffer. Note this means we cannot
- * do the encapsulation operation with the private key. But generally speaking
- * this is never done.
- *
- * @param [in, out] key Kyber key object.
- * @param [in] in Buffer holding encoded key.
- * @param [in] len Length of data in buffer.
- * @return 0 on success.
- * @return BAD_FUNC_ARG when key ot in is NULL.
- * @return NOT_COMPILED_IN when key type is not supported.
- * @return BUFFER_E when len is not the correct size.
- */
- int wc_KyberKey_DecodePrivateKey(KyberKey* key, unsigned char* in, word32 len)
- {
- int ret = 0;
- word32 privLen = 0;
- /* Validate parameters. */
- if ((key == NULL) || (in == NULL)) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == 0) {
- ret = wc_KyberKey_PrivateKeySize(key, &privLen);
- }
- /* Ensure the data is the correct length for the key type. */
- if ((ret == 0) && (len != privLen)) {
- ret = BUFFER_E;
- }
- if (ret == 0) {
- XMEMCPY(key->priv, in, privLen);
- }
- return ret;
- }
- /**
- * Decode public key.
- *
- * We store the whole thing in the public key buffer.
- *
- * @param [in, out] key Kyber key object.
- * @param [in] in Buffer holding encoded key.
- * @param [in] len Length of data in buffer.
- * @return 0 on success.
- * @return BAD_FUNC_ARG when key or in is NULL.
- * @return NOT_COMPILED_IN when key type is not supported.
- * @return BUFFER_E when len is not the correct size.
- */
- int wc_KyberKey_DecodePublicKey(KyberKey* key, unsigned char* in, word32 len)
- {
- int ret = 0;
- word32 pubLen = 0;
- /* Validate parameters. */
- if ((key == NULL) || (in == NULL)) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == 0) {
- ret = wc_KyberKey_PublicKeySize(key, &pubLen);
- }
- /* Ensure the data is the correct length for the key type. */
- if ((ret == 0) && (len != pubLen)) {
- ret = BUFFER_E;
- }
- if (ret == 0) {
- XMEMCPY(key->pub, in, pubLen);
- }
- return ret;
- }
- /**
- * Encode the private key.
- *
- * We stored it as a blob so we can just copy it over.
- *
- * @param [in] key Kyber key object.
- * @param [out] out Buffer to hold data.
- * @param [in] len Size of buffer in bytes.
- * @return 0 on success.
- * @return BAD_FUNC_ARG when key or out is NULL or private/public key not
- * available.
- * @return NOT_COMPILED_IN when key type is not supported.
- */
- int wc_KyberKey_EncodePrivateKey(KyberKey* key, unsigned char* out, word32 len)
- {
- int ret = 0;
- unsigned int privLen = 0;
- if ((key == NULL) || (out == NULL)) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == 0) {
- ret = wc_KyberKey_PrivateKeySize(key, &privLen);
- }
- /* Check buffer is big enough for encoding. */
- if ((ret == 0) && (len != privLen)) {
- ret = BUFFER_E;
- }
- if (ret == 0) {
- XMEMCPY(out, key->priv, privLen);
- }
- return ret;
- }
- /**
- * Encode the public key.
- *
- * We stored it as a blob so we can just copy it over.
- *
- * @param [in] key Kyber key object.
- * @param [out] out Buffer to hold data.
- * @param [in] len Size of buffer in bytes.
- * @return 0 on success.
- * @return BAD_FUNC_ARG when key or out is NULL or public key not available.
- * @return NOT_COMPILED_IN when key type is not supported.
- */
- int wc_KyberKey_EncodePublicKey(KyberKey* key, unsigned char* out, word32 len)
- {
- int ret = 0;
- unsigned int pubLen = 0;
- if ((key == NULL) || (out == NULL)) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == 0) {
- ret = wc_KyberKey_PublicKeySize(key, &pubLen);
- }
- /* Check buffer is big enough for encoding. */
- if ((ret == 0) && (len != pubLen)) {
- ret = BUFFER_E;
- }
- if (ret == 0) {
- XMEMCPY(out, key->pub, pubLen);
- }
- return ret;
- }
- #endif /* WOLFSSL_HAVE_KYBER */
|