diff --git a/INSTALL b/INSTALL index 5da5efed2..0fe3898b9 100644 --- a/INSTALL +++ b/INSTALL @@ -137,11 +137,16 @@ Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat 3) Follow steps in "Unix-based Platforms" above. -15. Building with liboqs for TLS 1.3 KEM Groups [EXPERIMENTAL] +15. Building with liboqs for TLS 1.3 [EXPERIMENTAL] In order be able to use liboqs, you must have it built and installed on your - system. For example, on linux, this would be sufficient: + system. We support the 0.7.0 release of liboqs. You can get it by looking at + the "Assets" section of the following page: - $ cd liboqs + https://github.com/open-quantum-safe/liboqs/releases/tag/0.7.0 + + Once unpacked, this would be sufficient: + + $ cd liboqs-0.7.0 $ mkdir build $ cd build $ cmake -DOQS_USE_OPENSSL=0 .. @@ -155,8 +160,8 @@ $ ./configure --with-liboqs $ make all - Execute the following to see the liboqs-related options near the end of the - output of these commands: + Execute the following to see the liboqs-related options for KEM groups near + the end of the output of these commands: $ ./examples/server/server -? $ ./examples/client/client -? @@ -172,14 +177,59 @@ Using OQS KEM: P521_KYBER_LEVEL5 ``` - The following NIST Competition Round 3 Finalist KEMs are supported: - - CRYSTALS-KYBER - - SABER - - NTRU + For authentication, you can generate a certificate chain using the Open + Quantum Safe project's fork of OpenSSL. We support certificates and keys + generated by the 2021-08 snapshot of the OQS-OpenSSL_1_1_1-stable branch + of the fork. You can get it by looking at the "Assets" section of the + following page: + + https://github.com/open-quantum-safe/openssl/releases/tag/OQS-OpenSSL_1_1_1-stable-snapshot-2021-08 + + Once unpacked, this would be sufficient for building it: + + $ cd openssl-OQS-OpenSSL_1_1_1-stable-snapshot-2021-08/ + $ ./config no-shared + $ make all + + Note that installation is NOT required. + + There is a script for generating a Falcon NIST Level 1 and NIST Level 5 + certificate chain which can be found in the wolfssl-examples github repo at + certmanager/generate_falcon_chains.sh. Please find detailed instructions on + how to generate and verify the keys and certificates in + certmanager/README.md. + + Once the certificates and keys are generated, copy them from the + openssl-OQS-OpenSSL_1_1_1-stable-snapshot-2021-08/ directory to the certs + directory of wolfssl. Now you can run the server and client like this: + + $ examples/server/server -v 4 -l TLS_AES_256_GCM_SHA384 \ + -A certs/falcon_level5_root_cert.pem \ + -c certs/falcon_level1_entity_cert.pem \ + -k certs/falcon_level1_entity_key.pem \ + --oqs P521_KYBER_LEVEL5 + + $ examples/client/client -v 4 -l TLS_AES_256_GCM_SHA384 \ + -A certs/falcon_level1_root_cert.pem \ + -c certs/falcon_level5_entity_cert.pem \ + -k certs/falcon_level5_entity_key.pem \ + --oqs P521_KYBER_LEVEL5 + + Congratulations! You have just achieved a fully quantum-safe TLS 1.3 + connection! + + The following NIST Competition Round 3 Finalist algorithms are supported: + - CRYSTALS-KYBER (KEM) + - SABER (KEM) + - NTRU (KEM) + - FALCON (signature scheme) Links to more information about these algorithms can be found here: + https://csrc.nist.gov/projects/post-quantum-cryptography/round-3-submissions - NOTE: The quantum-safe algorithms provided by LIBOQS are unstandardized and + NOTE: The quantum-safe algorithms provided by liboqs are unstandardized and experimental. It is highly advised that they NOT be used in production - environments. + environments. All OIDs and codepoints are temporary and expected to + change in the future. You should have no expectation of backwards + compatibility. diff --git a/src/include.am b/src/include.am index 4d3e1a53c..daf320d19 100644 --- a/src/include.am +++ b/src/include.am @@ -688,6 +688,10 @@ src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_448.c endif endif +if BUILD_LIBOQS +src_libwolfssl_la_SOURCES += wolfcrypt/src/falcon.c +endif + if BUILD_LIBZ src_libwolfssl_la_SOURCES += wolfcrypt/src/compress.c endif diff --git a/src/internal.c b/src/internal.c index 38755ef72..9b66eceb8 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2000,6 +2000,11 @@ int InitSSL_Side(WOLFSSL* ssl, word16 side) ssl->options.haveECC = 1; /* server turns on with ECC key cert */ } #endif +#ifdef HAVE_LIBOQS + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.haveFalconSig = 1; /* always on client side */ + } +#endif #if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) if (ssl->options.side == WOLFSSL_CLIENT_END) { @@ -2062,6 +2067,9 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) #ifdef HAVE_ECC ctx->minEccKeySz = MIN_ECCKEY_SZ; ctx->eccTempKeySz = ECDHE_SIZE; +#endif +#ifdef HAVE_LIBOQS + ctx->minFalconKeySz = MIN_FALCONKEY_SZ; #endif ctx->verifyDepth = MAX_CHAIN_DEPTH; #ifdef OPENSSL_EXTRA @@ -2117,6 +2125,11 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) ctx->CBIOSend = GNRC_SendTo; #endif +#ifdef HAVE_LIBOQS + if (method->side == WOLFSSL_CLIENT_END) + ctx->haveFalconSig = 1; /* always on client side */ + /* server can turn on by loading key */ +#endif #ifdef HAVE_ECC if (method->side == WOLFSSL_CLIENT_END) { ctx->haveECDSAsig = 1; /* always on client side */ @@ -2649,6 +2662,22 @@ static WC_INLINE void AddSuiteHashSigAlgo(Suites* suites, byte macAlgo, } else #endif + #ifdef HAVE_LIBOQS + if (sigAlgo == falcon_level1_sa_algo) { + suites->hashSigAlgo[*inOutIdx] = FALCON_LEVEL1_SA_MAJOR; + *inOutIdx += 1; + suites->hashSigAlgo[*inOutIdx] = FALCON_LEVEL1_SA_MINOR; + *inOutIdx += 1; + } + else + if (sigAlgo == falcon_level5_sa_algo) { + suites->hashSigAlgo[*inOutIdx] = FALCON_LEVEL5_SA_MAJOR; + *inOutIdx += 1; + suites->hashSigAlgo[*inOutIdx] = FALCON_LEVEL5_SA_MINOR; + *inOutIdx += 1; + } + else + #endif #ifdef WC_RSA_PSS if (sigAlgo == rsa_pss_sa_algo) { /* RSA PSS is sig then mac */ @@ -2676,7 +2705,8 @@ static WC_INLINE void AddSuiteHashSigAlgo(Suites* suites, byte macAlgo, } void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig, - int haveAnon, int tls1_2, int keySz) + int haveFalconSig, int haveAnon, int tls1_2, + int keySz) { word16 idx = 0; @@ -2707,8 +2737,13 @@ void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig, AddSuiteHashSigAlgo(suites, no_mac, ed448_sa_algo, keySz, &idx); #endif } -#endif /* HAVE_ECC || HAVE_ED25519 || defined(HAVE_ED448 */ - +#endif /* HAVE_ECC || HAVE_ED25519 || HAVE_ED448 */ + if (haveFalconSig) { +#if defined(HAVE_LIBOQS) + AddSuiteHashSigAlgo(suites, no_mac, falcon_level1_sa_algo, keySz, &idx); + AddSuiteHashSigAlgo(suites, no_mac, falcon_level5_sa_algo, keySz, &idx); +#endif /* HAVE_LIBOQS */ + } if (haveRSAsig) { #ifdef WC_RSA_PSS if (tls1_2) { @@ -2757,8 +2792,8 @@ void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig, void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA, word16 havePSK, word16 haveDH, word16 haveECDSAsig, - word16 haveECC, word16 haveStaticECC, word16 haveAnon, - int side) + word16 haveECC, word16 haveStaticECC, word16 haveFalconSig, + word16 haveAnon, int side) { word16 idx = 0; int tls = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR; @@ -2780,6 +2815,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA, (void)haveRSA; /* some builds won't read */ (void)haveRSAsig; /* non ecc builds won't read */ (void)haveAnon; /* anon ciphers optional */ + (void)haveFalconSig; if (suites == NULL) { WOLFSSL_MSG("InitSuites pointer error"); @@ -3723,7 +3759,8 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA, if (suites->hashSigAlgoSz == 0) { InitSuitesHashSigAlgo(suites, haveECDSAsig | haveECC, - haveRSAsig | haveRSA, 0, tls1_2, keySz); + haveRSAsig | haveRSA, haveFalconSig, + 0, tls1_2, keySz); } } @@ -3771,6 +3808,20 @@ static WC_INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsTy *hashAlgo = input[1]; } break; +#ifdef HAVE_LIBOQS + case OQS_SA_MAJOR: + if (input[1] == FALCON_LEVEL1_SA_MINOR) { + *hsType = falcon_level1_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } else + if (input[1] == FALCON_LEVEL5_SA_MINOR) { + *hsType = falcon_level5_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } + break; +#endif default: *hashAlgo = input[0]; *hsType = input[1]; @@ -5680,13 +5731,14 @@ int InitSSL_Suites(WOLFSSL* ssl) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.haveAnon, ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveAnon, + ssl->options.side); } else { InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, TRUE, ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.haveAnon, - ssl->options.side); + ssl->options.haveStaticECC, ssl->options.haveFalconSig, + ssl->options.haveAnon, ssl->options.side); } #if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT) @@ -5872,6 +5924,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->options.haveECDSAsig = ctx->haveECDSAsig; ssl->options.haveECC = ctx->haveECC; ssl->options.haveStaticECC = ctx->haveStaticECC; + ssl->options.haveFalconSig = ctx->haveFalconSig; #ifndef NO_PSK ssl->options.havePSK = ctx->havePSK; @@ -5902,6 +5955,9 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #ifdef HAVE_ECC ssl->options.minEccKeySz = ctx->minEccKeySz; #endif +#ifdef HAVE_LIBOQS + ssl->options.minFalconKeySz = ctx->minFalconKeySz; +#endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) ssl->options.verifyDepth = ctx->verifyDepth; #endif @@ -6644,6 +6700,11 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey) wc_curve448_free((curve448_key*)*pKey); break; #endif /* HAVE_CURVE448 */ + #ifdef HAVE_LIBOQS + case DYNAMIC_TYPE_FALCON: + wc_falcon_free((falcon_key*)*pKey); + break; + #endif /* HAVE_LIBOQS */ #ifndef NO_DH case DYNAMIC_TYPE_DH: wc_FreeDhKey((DhKey*)*pKey); @@ -6706,6 +6767,11 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) sz = sizeof(curve448_key); break; #endif /* HAVE_CURVE448 */ + #ifdef HAVE_LIBOQS + case DYNAMIC_TYPE_FALCON: + sz = sizeof(falcon_key); + break; + #endif /* HAVE_LIBOQS */ #ifndef NO_DH case DYNAMIC_TYPE_DH: sz = sizeof(DhKey); @@ -6751,6 +6817,12 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) ret = 0; break; #endif /* HAVE_CURVE448 */ + #ifdef HAVE_LIBOQS + case DYNAMIC_TYPE_FALCON: + wc_falcon_init((falcon_key*)*pKey); + ret = 0; + break; + #endif #ifdef HAVE_CURVE448 case DYNAMIC_TYPE_CURVE448: wc_curve448_init((curve448_key*)*pKey); @@ -6775,7 +6847,8 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) } #if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ - defined(HAVE_CURVE25519) || defined(HAVE_ED448) || defined(HAVE_CURVE448) + defined(HAVE_CURVE25519) || defined(HAVE_ED448) || \ + defined(HAVE_CURVE448) || defined(HAVE_LIBOQS) static int ReuseKey(WOLFSSL* ssl, int type, void* pKey) { int ret = 0; @@ -6821,6 +6894,12 @@ static int ReuseKey(WOLFSSL* ssl, int type, void* pKey) ret = wc_curve448_init((curve448_key*)pKey); break; #endif /* HAVE_CURVE448 */ + #ifdef HAVE_LIBOQS + case DYNAMIC_TYPE_FALCON: + wc_falcon_free((falcon_key*)pKey); + ret = wc_falcon_init((falcon_key*)pKey); + break; + #endif /* HAVE_LIBOQS */ #ifndef NO_DH case DYNAMIC_TYPE_DH: wc_FreeDhKey((DhKey*)pKey); @@ -7056,6 +7135,10 @@ void SSL_ResourceFree(WOLFSSL* ssl) } #endif #endif +#ifdef HAVE_LIBOQS + FreeKey(ssl, DYNAMIC_TYPE_FALCON, (void**)&ssl->peerFalconKey); + ssl->peerFalconKeyPresent = 0; +#endif #ifdef HAVE_PK_CALLBACKS #ifdef HAVE_ECC XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC); @@ -7273,6 +7356,10 @@ void FreeHandshakeResources(WOLFSSL* ssl) FreeKey(ssl, DYNAMIC_TYPE_ED448, (void**)&ssl->peerEd448Key); ssl->peerEd448KeyPresent = 0; #endif /* HAVE_ED448 */ +#ifdef HAVE_LIBOQS + FreeKey(ssl, DYNAMIC_TYPE_FALCON, (void**)&ssl->peerFalconKey); + ssl->peerFalconKeyPresent = 0; +#endif /* HAVE_LIBOQS */ } #ifdef HAVE_ECC @@ -11719,6 +11806,24 @@ static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args) } break; #endif /* HAVE_ED448 */ + #ifdef HAVE_LIBOQS + case FALCON_LEVEL1k: + if (ssl->options.minFalconKeySz < 0 || + FALCON_LEVEL1_KEY_SIZE < (word16)ssl->options.minFalconKeySz) { + WOLFSSL_MSG( + "Falcon key size in cert chain error"); + ret = FALCON_KEY_SIZE_E; + } + break; + case FALCON_LEVEL5k: + if (ssl->options.minFalconKeySz < 0 || + FALCON_LEVEL5_KEY_SIZE < (word16)ssl->options.minFalconKeySz) { + WOLFSSL_MSG( + "Falcon key size in cert chain error"); + ret = FALCON_KEY_SIZE_E; + } + break; + #endif /* HAVE_LIBOQS */ default: WOLFSSL_MSG("Key size not checked"); /* key not being checked for size if not in @@ -12898,6 +13003,52 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, break; } #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ + #ifdef HAVE_LIBOQS + case FALCON_LEVEL1k: + case FALCON_LEVEL5k: + { + int keyRet = 0; + if (ssl->peerFalconKey == NULL) { + /* alloc/init on demand */ + keyRet = AllocKey(ssl, DYNAMIC_TYPE_FALCON, + (void**)&ssl->peerFalconKey); + } else if (ssl->peerFalconKeyPresent) { + keyRet = ReuseKey(ssl, DYNAMIC_TYPE_FALCON, + ssl->peerFalconKey); + ssl->peerFalconKeyPresent = 0; + } + + if (keyRet == 0) { + if (args->dCert->keyOID == FALCON_LEVEL1k) { + keyRet = wc_falcon_set_level(ssl->peerFalconKey, + 1); + } + else { + keyRet = wc_falcon_set_level(ssl->peerFalconKey, + 5); + } + } + + if (keyRet != 0 || + wc_falcon_import_public(args->dCert->publicKey, + args->dCert->pubKeySize, + ssl->peerFalconKey) != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerFalconKeyPresent = 1; + } + + /* check size of peer Falcon key */ + if (ret == 0 && ssl->peerFalconKeyPresent && + !ssl->options.verifyNone && + FALCON_MAX_KEY_SIZE < + ssl->options.minFalconKeySz) { + ret = FALCON_KEY_SIZE_E; + WOLFSSL_MSG("Peer Falcon key is too small"); + } + } + #endif /* HAVE_LIBOQS */ default: break; } @@ -20364,6 +20515,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) return "bad/unsupported protocol version"; #endif + case FALCON_KEY_SIZE_E: + return "Wrong key size for Falcon."; + default : return "unknown error number"; } @@ -21316,13 +21470,14 @@ Set the enabled cipher suites. */ int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) { - int ret = 0; - int idx = 0; - int haveRSAsig = 0; - int haveECDSAsig = 0; - int haveAnon = 0; - const int suiteSz = GetCipherNamesSize(); - char* next = (char*)list; + int ret = 0; + int idx = 0; + int haveRSAsig = 0; + int haveECDSAsig = 0; + int haveFalconSig = 0; + int haveAnon = 0; + const int suiteSz = GetCipherNamesSize(); + char* next = (char*)list; if (suites == NULL || list == NULL) { WOLFSSL_MSG("SetCipherList parameter error"); @@ -21392,6 +21547,9 @@ int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) defined(HAVE_ED448) haveECDSAsig = 1; #endif + #if defined(HAVE_LIBOQS) + haveFalconSig = 1; + #endif } else #endif @@ -21428,8 +21586,8 @@ int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) #endif suites->setSuites = 1; suites->suiteSz = (word16)idx; - InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon, 1, - keySz); + InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveFalconSig, + haveAnon, 1, keySz); } (void)ctx; @@ -21608,6 +21766,18 @@ static int MatchSigAlgo(WOLFSSL* ssl, int sigAlgo) return sigAlgo == ed448_sa_algo; } #endif +#ifdef HAVE_LIBOQS + if (ssl->pkCurveOID == CTC_FALCON_LEVEL1) { + /* Certificate has Falcon level 1 key, only match with Falcon level 1 + * sig alg */ + return sigAlgo == falcon_level1_sa_algo; + } + if (ssl->pkCurveOID == CTC_FALCON_LEVEL5) { + /* Certificate has Falcon level 5 key, only match with Falcon level 5 + * sig alg */ + return sigAlgo == falcon_level5_sa_algo; + } +#endif #ifdef WC_RSA_PSS /* RSA certificate and PSS sig alg. */ if (ssl->suites->sigAlgo == rsa_sa_algo) { @@ -21710,6 +21880,16 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) break; } #endif + #if defined(HAVE_LIBOQS) + if (ssl->pkCurveOID == CTC_FALCON_LEVEL1 || + ssl->pkCurveOID == CTC_FALCON_LEVEL5 ) { + /* Matched Falcon - set chosen and finished. */ + ssl->suites->sigAlgo = sigAlgo; + ssl->suites->hashAlgo = hashAlgo; + ret = 0; + break; + } + #endif #if defined(WOLFSSL_ECDSA_MATCH_HASH) && defined(USE_ECDSA_KEYSZ_HASH_ALGO) #error "WOLFSSL_ECDSA_MATCH_HASH and USE_ECDSA_KEYSZ_HASH_ALGO cannot " @@ -22074,7 +22254,9 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType, } #endif -/* Decode the private key - RSA/ECC/Ed25519/Ed448 - and creates a key object. +/* Decode the private key - RSA/ECC/Ed25519/Ed448/Falcon - and creates a key + * object. + * * The signature type is set as well. * The maximum length of a signature is returned. * @@ -22364,6 +22546,67 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } } #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ +#ifdef HAVE_LIBOQS + if (ssl->buffers.keyType == falcon_level1_sa_algo || + ssl->buffers.keyType == falcon_level5_sa_algo || + ssl->buffers.keyType == 0) { + + ssl->hsType = DYNAMIC_TYPE_FALCON; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + + if (ssl->buffers.keyType == falcon_level1_sa_algo) { + ret = wc_falcon_set_level((falcon_key*)ssl->hsKey, 1); + } + else if (ssl->buffers.keyType == falcon_level5_sa_algo) { + ret = wc_falcon_set_level((falcon_key*)ssl->hsKey, 5); + } + else { + /* What if ssl->buffers.keyType is 0? We might want to do something + * more graceful here. */ + ret = ALGO_ID_E; + } + + if (ret != 0) { + goto exit_dpk; + } + + #if defined(HAVE_ED448) + WOLFSSL_MSG("Trying Falcon private key, ED448 didn't work"); + #elif defined(HAVE_ED25519) + WOLFSSL_MSG("Trying Falcon private key, ED25519 didn't work"); + #elif defined(HAVE_ECC) + WOLFSSL_MSG("Trying Falcon private key, ECC didn't work"); + #elif !defined(NO_RSA) + WOLFSSL_MSG("Trying Falcon private key, RSA didn't work"); + #else + WOLFSSL_MSG("Trying Falcon private key"); + #endif + + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is a Falcon private key. */ + ret = wc_falcon_import_private_only(ssl->buffers.key->buffer, + ssl->buffers.key->length, + (falcon_key*)ssl->hsKey); + if (ret == 0) { + WOLFSSL_MSG("Using Falcon private key"); + + /* Check it meets the minimum Falcon key size requirements. */ + if (FALCON_MAX_KEY_SIZE < ssl->options.minFalconKeySz) { + WOLFSSL_MSG("Falcon key size too small"); + ERROR_OUT(FALCON_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = FALCON_MAX_SIG_SIZE; + + goto exit_dpk; + } + } +#endif /* HAVE_LIBOQS */ (void)idx; (void)keySz; @@ -28766,7 +29009,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.haveAnon, ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveAnon, + ssl->options.side); } /* suite size */ @@ -29119,7 +29363,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.haveAnon, ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveAnon, + ssl->options.side); } #ifdef OPENSSL_EXTRA @@ -29179,9 +29424,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* reset cipher suites to account for TLS version change */ InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, - ssl->options.haveDH, ssl->options.haveECDSAsig, - ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.haveAnon, ssl->options.side); + ssl->options.haveDH, ssl->options.haveECDSAsig, + ssl->options.haveECC, ssl->options.haveStaticECC, + ssl->options.haveFalconSig, ssl->options.haveAnon, + ssl->options.side); } } #endif diff --git a/src/ssl.c b/src/ssl.c index 7a5975e26..aba4ea5c4 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -115,6 +115,9 @@ #include #include #include + #if defined(HAVE_LIBOQS) + #include + #endif #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) #ifdef HAVE_OCSP #include @@ -1963,7 +1966,8 @@ int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.haveAnon, ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveAnon, + ssl->options.side); } WOLFSSL_LEAVE("wolfSSL_SetTmpDH", 0); @@ -3928,6 +3932,10 @@ WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap) #ifdef HAVE_ECC cm->minEccKeySz = MIN_ECCKEY_SZ; #endif + #ifdef HAVE_LIBOQS + cm->minFalconKeySz = MIN_FALCONKEY_SZ; + #endif + cm->heap = heap; } @@ -4414,7 +4422,8 @@ int wolfSSL_SetVersion(WOLFSSL* ssl, int version) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.haveAnon, ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveAnon, + ssl->options.side); return WOLFSSL_SUCCESS; } @@ -4871,6 +4880,22 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) } break; #endif /* HAVE_ED448 */ + #ifdef HAVE_LIBOQS + case FALCON_LEVEL1k: + if (cm->minFalconKeySz < 0 || + FALCON_LEVEL1_KEY_SIZE < (word16)cm->minFalconKeySz) { + ret = FALCON_KEY_SIZE_E; + WOLFSSL_MSG("\tCA Falcon level 1 key size error"); + } + break; + case FALCON_LEVEL5k: + if (cm->minFalconKeySz < 0 || + FALCON_LEVEL5_KEY_SIZE < (word16)cm->minFalconKeySz) { + ret = FALCON_KEY_SIZE_E; + WOLFSSL_MSG("\tCA Falcon level 5 key size error"); + } + break; + #endif /* HAVE_LIBOQS */ default: WOLFSSL_MSG("\tNo key size check done on CA"); @@ -5407,9 +5432,9 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der #endif if (ret != 0) { #if !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ - !defined(HAVE_ED448) - WOLFSSL_MSG("RSA decode failed and ECC/ED25519/ED448 not " - "enabled to try"); + !defined(HAVE_ED448) && !defined(HAVE_LIBOQS) + WOLFSSL_MSG("RSA decode failed and other algorithms " + "not enabled to try"); ret = WOLFSSL_BAD_FILE; #else ret = 0; /* continue trying other algorithms */ @@ -5600,11 +5625,7 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der ret = wc_ed448_init(key); if (ret == 0) { *idx = 0; - if (wc_Ed448PrivateKeyDecode(der->buffer, idx, key, - der->length) != 0) { - ret = WOLFSSL_BAD_FILE; - } - + ret = wc_Ed448PrivateKeyDecode(der->buffer, idx, key, der->length); if (ret == 0) { /* check for minimum key size and then free */ int minKeySz = ssl ? ssl->options.minEccKeySz : @@ -5644,6 +5665,71 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der #endif } #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ +#ifdef HAVE_LIBOQS + if (ret == 0 && ((*keyFormat == 0) || (*keyFormat == FALCON_LEVEL1k) || + (*keyFormat == FALCON_LEVEL5k))) { + /* make sure Falcon key can be used */ + falcon_key* key = (falcon_key*)XMALLOC(sizeof(falcon_key), heap, + DYNAMIC_TYPE_FALCON); + if (key == NULL) { + return MEMORY_E; + } + ret = wc_falcon_init(key); + if (ret == 0) { + if (*keyFormat == FALCON_LEVEL1k) { + ret = wc_falcon_set_level(key, 1); + } + else if (*keyFormat == FALCON_LEVEL5k) { + ret = wc_falcon_set_level(key, 5); + } + else { + /* What if *keyformat is 0? We might want to do something more + * graceful here. */ + wc_falcon_free(key); + ret = ALGO_ID_E; + } + } + + if (ret == 0) { + *idx = 0; + ret = wc_falcon_import_private_only(der->buffer, der->length, key); + if (ret == 0) { + /* check for minimum key size and then free */ + int minKeySz = ssl ? ssl->options.minFalconKeySz : + ctx->minFalconKeySz; + *keySz = FALCON_MAX_KEY_SIZE; + if (*keySz < minKeySz) { + WOLFSSL_MSG("Falcon private key too small"); + ret = FALCON_KEY_SIZE_E; + } + if (ssl) { + if (*keyFormat == FALCON_LEVEL1k) { + ssl->buffers.keyType = falcon_level1_sa_algo; + } + else { + ssl->buffers.keyType = falcon_level5_sa_algo; + } + ssl->buffers.keySz = *keySz; + } + else if (ctx) { + if (*keyFormat == FALCON_LEVEL1k) { + ctx->privateKeyType = falcon_level1_sa_algo; + } + else { + ctx->privateKeyType = falcon_level5_sa_algo; + } + ctx->privateKeySz = *keySz; + } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + *resetSuites = 1; + } + } + wc_falcon_free(key); + } + XFREE(key, heap, DYNAMIC_TYPE_FALCON); + } +#endif /* HAVE_LIBOQS */ return ret; } @@ -5977,12 +6063,21 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, else if (ctx) ctx->haveECDSAsig = 1; break; + case CTC_FALCON_LEVEL1: + case CTC_FALCON_LEVEL5: + WOLFSSL_MSG("Falcon cert signature"); + if (ssl) + ssl->options.haveFalconSig = 1; + else if (ctx) + ctx->haveFalconSig = 1; + break; default: WOLFSSL_MSG("Not ECDSA cert signature"); break; } - #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ + defined(HAVE_LIBOQS) if (ssl) { ssl->pkCurveOID = cert->pkCurveOID; #ifndef WC_STRICT_SIG @@ -5999,6 +6094,12 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, ssl->options.haveECC = 1; } #endif + #ifdef HAVE_LIBOQS + else if (cert->keyOID == FALCON_LEVEL1k || + cert->keyOID == FALCON_LEVEL5k) { + ssl->options.haveFalconSig = 1; + } + #endif #else ssl->options.haveECC = ssl->options.haveECDSAsig; #endif @@ -6019,6 +6120,12 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, ctx->haveECC = 1; } #endif + #ifdef HAVE_LIBOQS + else if (cert->keyOID == FALCON_LEVEL1k || + cert->keyOID == FALCON_LEVEL5k) { + ctx->haveFalconSig = 1; + } + #endif #else ctx->haveECC = ctx->haveECDSAsig; #endif @@ -6126,6 +6233,27 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } break; #endif /* HAVE_ED448 */ + #ifdef HAVE_LIBOQS + case FALCON_LEVEL1k: + case FALCON_LEVEL5k: + /* Falcon is fixed key size */ + keySz = FALCON_MAX_KEY_SIZE; + if (ssl && !ssl->options.verifyNone) { + if (ssl->options.minFalconKeySz < 0 || + keySz < (int)ssl->options.minFalconKeySz) { + ret = FALCON_KEY_SIZE_E; + WOLFSSL_MSG("Certificate Falcon key size error"); + } + } + else if (ctx && !ctx->verifyNone) { + if (ctx->minFalconKeySz < 0 || + keySz < (int)ctx->minFalconKeySz) { + ret = FALCON_KEY_SIZE_E; + WOLFSSL_MSG("Certificate Falcon key size error"); + } + } + break; + #endif /* HAVE_LIBOQS */ default: WOLFSSL_MSG("No key size check done on certificate"); @@ -6198,7 +6326,8 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.haveAnon, ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveAnon, + ssl->options.side); } return WOLFSSL_SUCCESS; @@ -15999,7 +16128,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.haveAnon, ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveAnon, + ssl->options.side); } #ifdef OPENSSL_EXTRA /** @@ -16051,7 +16181,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.haveAnon, ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveAnon, + ssl->options.side); } const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl) @@ -28284,7 +28415,8 @@ long wolfSSL_set_options(WOLFSSL* ssl, long op) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.haveAnon, ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveAnon, + ssl->options.side); return ssl->options.mask; } @@ -31569,6 +31701,12 @@ const WOLFSSL_ObjectInfo wolfssl_object_info[] = { #ifdef HAVE_ED25519 { NID_ED25519, ED25519k, oidKeyType, "ED25519", "ED25519"}, #endif + #ifdef HAVE_LIBOQS + { CTC_FALCON_LEVEL1, FALCON_LEVEL1k, oidKeyType, "Falcon Level 1", + "Falcon Level 1"}, + { CTC_FALCON_LEVEL5, FALCON_LEVEL5k, oidKeyType, "Falcon Level 5", + "Falcon Level 5"}, + #endif /* oidCurveType */ #ifdef HAVE_ECC @@ -36266,7 +36404,7 @@ struct WOLFSSL_HashSigInfo { { sha224_mac, rsa_sa_algo, CTC_SHA224wRSA }, #endif #ifndef NO_SHA - { sha_mac, rsa_sa_algo, CTC_SHAwRSA }, + { sha_mac, rsa_sa_algo, CTC_SHAwRSA }, #endif #ifdef WC_RSA_PSS #ifndef NO_SHA256 @@ -36297,18 +36435,22 @@ struct WOLFSSL_HashSigInfo { { sha224_mac, ecc_dsa_sa_algo, CTC_SHA224wECDSA }, #endif #ifndef NO_SHA - { sha_mac, ecc_dsa_sa_algo, CTC_SHAwECDSA }, + { sha_mac, ecc_dsa_sa_algo, CTC_SHAwECDSA }, #endif #endif #ifdef HAVE_ED25519 { no_mac, ed25519_sa_algo, CTC_ED25519 }, #endif -#ifdef HAVE_ED25519 - { no_mac, ed448_sa_algo, CTC_ED448 }, +#ifdef HAVE_ED448 + { no_mac, ed448_sa_algo, CTC_ED448 }, +#endif +#ifdef HAVE_LIBOQS + { no_mac, falcon_level1_sa_algo, CTC_FALCON_LEVEL1 }, + { no_mac, falcon_level5_sa_algo, CTC_FALCON_LEVEL5 }, #endif #ifndef NO_DSA #ifndef NO_SHA - { sha_mac, dsa_sa_algo, CTC_SHAwDSA }, + { sha_mac, dsa_sa_algo, CTC_SHAwDSA }, #endif #endif }; diff --git a/src/tls13.c b/src/tls13.c index 74e577d8b..81af312fb 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -5136,7 +5136,8 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx, WOLFSSL_ENTER("SendTls13CertificateRequest"); if (ssl->options.side == WOLFSSL_SERVER_END) - InitSuitesHashSigAlgo(ssl->suites, 1, 1, 0, 1, ssl->buffers.keySz); + InitSuitesHashSigAlgo(ssl->suites, 1, 1, 1, + 0, 1, ssl->buffers.keySz); ext = TLSX_Find(ssl->extensions, TLSX_SIGNATURE_ALGORITHMS); if (ext == NULL) @@ -5207,7 +5208,7 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx, #ifndef NO_CERTS #if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ - defined(HAVE_ED448) + defined(HAVE_ED448) || defined(HAVE_LIBOQS) /* Encode the signature algorithm into buffer. * * hashalgo The hash algorithm. @@ -5245,6 +5246,16 @@ static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) output[0] = rsa_pss_sa_algo; output[1] = hashAlgo; break; +#endif +#ifdef HAVE_LIBOQS + case falcon_level1_sa_algo: + output[0] = FALCON_LEVEL1_SA_MAJOR; + output[1] = FALCON_LEVEL1_SA_MINOR; + break; + case falcon_level5_sa_algo: + output[0] = FALCON_LEVEL5_SA_MAJOR; + output[1] = FALCON_LEVEL5_SA_MINOR; + break; #endif default: break; @@ -5289,6 +5300,23 @@ static WC_INLINE int DecodeTls13SigAlg(byte* input, byte* hashAlgo, else ret = INVALID_PARAMETER; break; +#ifdef HAVE_LIBOQS + case OQS_SA_MAJOR: + if (input[1] == FALCON_LEVEL1_SA_MINOR) { + *hsType = falcon_level1_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } else + if (input[1] == FALCON_LEVEL5_SA_MINOR) { + *hsType = falcon_level1_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } + else { + ret = INVALID_PARAMETER; + } + break; +#endif default: *hashAlgo = input[0]; *hsType = input[1]; @@ -5906,7 +5934,7 @@ static int SendTls13Certificate(WOLFSSL* ssl) } #if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ - defined(HAVE_ED448)) && \ + defined(HAVE_ED448) || defined(HAVE_LIBOQS)) && \ (!defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)) typedef struct Scv13Args { byte* output; /* not allocated */ @@ -6050,6 +6078,24 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) #ifdef HAVE_ED448 else if (ssl->hsType == DYNAMIC_TYPE_ED448) args->sigAlgo = ed448_sa_algo; + #endif + #ifdef HAVE_LIBOQS + else if (ssl->hsType == DYNAMIC_TYPE_FALCON) { + falcon_key* fkey = (falcon_key*)ssl->hsKey; + byte level = 0; + if (wc_falcon_get_level(fkey, &level) != 0) { + ERROR_OUT(ALGO_ID_E, exit_scv); + } + if (level == 1) { + args->sigAlgo = falcon_level1_sa_algo; + } + else if (level == 5) { + args->sigAlgo = falcon_level1_sa_algo; + } + else { + ERROR_OUT(ALGO_ID_E, exit_scv); + } + } #endif else { ERROR_OUT(ALGO_ID_E, exit_scv); @@ -6127,6 +6173,11 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) sig->length = ED448_SIG_SIZE; } #endif /* HAVE_ED448 */ + #ifdef HAVE_LIBOQS + if (ssl->hsType == DYNAMIC_TYPE_FALCON) { + sig->length = FALCON_MAX_SIG_SIZE; + } + #endif /* HAVE_LIBOQS */ /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_DO; @@ -6178,6 +6229,15 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) args->length = (word16)sig->length; } #endif + #ifdef HAVE_LIBOQS + if (ssl->hsType == DYNAMIC_TYPE_FALCON) { + ret = wc_falcon_sign_msg(args->sigData, args->sigDataSz, + args->verify + HASH_SIG_SIZE + + VERIFY_HEADER, (word32*)&sig->length, + (falcon_key*)ssl->hsKey); + args->length = (word16)sig->length; + } + #endif /* HAVE_LIBOQS */ #ifndef NO_RSA if (ssl->hsType == DYNAMIC_TYPE_RSA) { ret = RsaSign(ssl, sig->buffer, (word32)sig->length, @@ -6488,6 +6548,19 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, goto exit_dcv; } #endif + #ifdef HAVE_LIBOQS + if (args->sigAlgo == falcon_level1_sa_algo && !ssl->peerFalconKeyPresent) { + WOLFSSL_MSG("Peer sent Falcon Level 1 sig but different cert"); + ret = SIG_VERIFY_E; + goto exit_dcv; + } + if (args->sigAlgo == falcon_level5_sa_algo && !ssl->peerFalconKeyPresent) { + WOLFSSL_MSG("Peer sent Falcon Level 5 sig but different cert"); + ret = SIG_VERIFY_E; + goto exit_dcv; + } + #endif + #ifndef NO_RSA if (args->sigAlgo == rsa_sa_algo) { WOLFSSL_MSG("Peer sent PKCS#1.5 algo but not in certificate"); @@ -6558,6 +6631,20 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, ret = 0; } #endif + #ifdef HAVE_LIBOQS + if (ssl->peerFalconKeyPresent) { + WOLFSSL_MSG("Doing Falcon peer cert verify"); + + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + + CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); + ret = 0; + } + #endif /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_DO; @@ -6638,6 +6725,21 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, } } #endif + #ifdef HAVE_LIBOQS + if (ssl->peerFalconKeyPresent) { + int res = 0; + WOLFSSL_MSG("Doing Falcon peer cert verify"); + ret = wc_falcon_verify_msg(input + args->idx, args->sz, + args->sigData, args->sigDataSz, + &res, ssl->peerFalconKey); + + if ((ret >= 0) && (res == 1)) { + FreeKey(ssl, DYNAMIC_TYPE_FALCON, + (void**)&ssl->peerFalconKey); + ssl->peerFalconKeyPresent = 0; + } + } + #endif /* Check for error */ if (ret != 0) { @@ -8006,13 +8108,12 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, #endif #if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ - defined(HAVE_ED448) + defined(HAVE_ED448) || defined(HAVE_LIBOQS) case certificate_verify: WOLFSSL_MSG("processing certificate verify"); ret = DoTls13CertificateVerify(ssl, input, inOutIdx, size); break; -#endif /* !NO_RSA || HAVE_ECC */ - +#endif case finished: WOLFSSL_MSG("processing finished"); ret = DoTls13Finished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF); @@ -8444,8 +8545,9 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) case FIRST_REPLY_THIRD: #if (!defined(NO_CERTS) && (!defined(NO_RSA) || defined(HAVE_ECC) || \ - defined(HAVE_ED25519) || defined(HAVE_ED448))) && \ - (!defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)) + defined(HAVE_ED25519) || defined(HAVE_ED448) || \ + defined(HAVE_LIBOQS))) && (!defined(NO_WOLFSSL_SERVER) || \ + !defined(WOLFSSL_NO_CLIENT_AUTH)) if (!ssl->options.resuming && ssl->options.sendVerify) { ssl->error = SendTls13CertificateVerify(ssl); if (ssl->error != 0) { @@ -9003,7 +9105,8 @@ void wolfSSL_set_psk_client_cs_callback(WOLFSSL* ssl, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.haveAnon, ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveAnon, + ssl->options.side); } /* Set the PSK callback that returns the cipher suite for a client to use @@ -9053,7 +9156,8 @@ void wolfSSL_set_psk_client_tls13_callback(WOLFSSL* ssl, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.haveAnon, ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveAnon, + ssl->options.side); } /* Set the PSK callback that returns the cipher suite for a server to use @@ -9100,7 +9204,8 @@ void wolfSSL_set_psk_server_tls13_callback(WOLFSSL* ssl, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.haveAnon, ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveAnon, + ssl->options.side); } /* Get name of first supported cipher suite that uses the hash indicated. @@ -9387,7 +9492,7 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) case TLS13_CERT_SENT : #if !defined(NO_CERTS) && (!defined(NO_RSA) || defined(HAVE_ECC) || \ - defined(HAVE_ED25519) || defined(HAVE_ED448)) + defined(HAVE_ED25519) || defined(HAVE_ED448) || defined(HAVE_LIBOQS)) if (!ssl->options.resuming && ssl->options.sendVerify) { if ((ssl->error = SendTls13CertificateVerify(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 1d91b238e..400aa978b 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -131,6 +131,10 @@ ASN Options: #include #endif +#ifdef HAVE_LIBOQS + #include +#endif + #ifdef WOLFSSL_QNX_CAAM #include #endif @@ -3811,6 +3815,13 @@ static word32 SetBitString16Bit(word16 val, byte* output) #ifdef HAVE_ED448 static const byte sigEd448Oid[] = {43, 101, 113}; #endif /* HAVE_ED448 */ +#ifdef HAVE_LIBOQS + /* Falcon Level 1: 1 3 9999 3 1 */ + static const byte sigFalcon_Level1Oid[] = {43, 206, 15, 3, 1}; + + /* Falcon Level 5: 1 3 9999 3 4 */ + static const byte sigFalcon_Level5Oid[] = {43, 206, 15, 3, 4}; +#endif /* HAVE_LIBOQS */ /* keyType */ #ifndef NO_DSA @@ -3837,6 +3848,13 @@ static word32 SetBitString16Bit(word16 val, byte* output) #ifndef NO_DH static const byte keyDhOid[] = {42, 134, 72, 134, 247, 13, 1, 3, 1}; #endif /* !NO_DH */ +#ifdef HAVE_LIBOQS + /* Falcon Level 1: 1 3 9999 3 1 */ + static const byte keyFalcon_Level1Oid[] = {43, 206, 15, 3, 1}; + + /* Falcon Level 5: 1 3 9999 3 4 */ + static const byte keyFalcon_Level5Oid[] = {43, 206, 15, 3, 4}; +#endif /* HAVE_LIBOQS */ /* curveType */ #ifdef HAVE_ECC @@ -4249,6 +4267,16 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(sigEd448Oid); break; #endif + #ifdef HAVE_LIBOQS + case CTC_FALCON_LEVEL1: + oid = sigFalcon_Level1Oid; + *oidSz = sizeof(sigFalcon_Level1Oid); + break; + case CTC_FALCON_LEVEL5: + oid = sigFalcon_Level5Oid; + *oidSz = sizeof(sigFalcon_Level5Oid); + break; + #endif default: break; } @@ -4304,6 +4332,16 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(keyDhOid); break; #endif /* !NO_DH */ + #ifdef HAVE_LIBOQS + case FALCON_LEVEL1k: + oid = keyFalcon_Level1Oid; + *oidSz = sizeof(keyFalcon_Level1Oid); + break; + case FALCON_LEVEL5k: + oid = keyFalcon_Level5Oid; + *oidSz = sizeof(keyFalcon_Level5Oid); + break; + #endif default: break; } @@ -5510,7 +5548,7 @@ static const ASNItem pkcs8KeyASN[] = { #define pkcs8KeyASN_Length (sizeof(pkcs8KeyASN) / sizeof(ASNItem)) #endif -/* Remove PKCS #8 header around an RSA, ECDSA, Ed25519 or Ed448 key. +/* Remove PKCS #8 header around an RSA, ECDSA, Ed25519, Ed448, or Falcon key. * * @param [in] input Buffer holding BER data. * @param [in, out] inOutIdx On in, start of PKCS #8 encoding. @@ -6132,6 +6170,62 @@ int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz, } else #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT && !NO_ASN_CRYPT */ + #if defined(HAVE_LIBOQS) + if ((ks == FALCON_LEVEL1k) || (ks == FALCON_LEVEL5k)) { + #ifdef WOLFSSL_SMALL_STACK + falcon_key* key_pair = NULL; + #else + falcon_key key_pair[1]; + #endif + word32 keyIdx = 0; + + #ifdef WOLFSSL_SMALL_STACK + key_pair = (falcon_key*)XMALLOC(sizeof(falcon_key), NULL, + DYNAMIC_TYPE_FALCON); + if (key_pair == NULL) + return MEMORY_E; + #endif + ret = wc_falcon_init(key_pair); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(key_pair, NULL, DYNAMIC_TYPE_FALCON); + #endif + return ret; + } + + if (ks == FALCON_LEVEL1k) { + ret = wc_falcon_set_level(key_pair, 1); + } + else if (ks == FALCON_LEVEL5k) { + ret = wc_falcon_set_level(key_pair, 5); + } + + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(key_pair, NULL, DYNAMIC_TYPE_FALCON); + #endif + return ret; + } + if ((ret = wc_Falcon_PrivateKeyDecode(privKey, &keyIdx, key_pair, + privKeySz)) == 0) { + WOLFSSL_MSG("Checking Falcon_ key pair"); + keyIdx = 0; + if ((ret = wc_falcon_import_public(pubKey, pubKeySz, + key_pair)) == 0) { + /* public and private extracted successfully no check if is + * a pair and also do sanity checks on key. wc_ecc_check_key + * checks that private * base generator equals pubkey */ + if ((ret = wc_falcon_check_key(key_pair)) == 0) + ret = 1; + } + } + wc_falcon_free(key_pair); + #ifdef WOLFSSL_SMALL_STACK + XFREE(key_pair, NULL, DYNAMIC_TYPE_FALCON); + #endif + } + else + #endif /* HAVE_LIBOQS */ { ret = 0; } @@ -6433,9 +6527,43 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, XFREE(ed448, heap, DYNAMIC_TYPE_TMP_BUFFER); } #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT && !NO_ASN_CRYPT */ +#if defined(HAVE_LIBOQS) + if (*algoID == 0) { + falcon_key *falcon = (falcon_key *)XMALLOC(sizeof(*falcon), heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (falcon == NULL) + return MEMORY_E; - /* if flag is not set then is neither RSA or ECC key that could be - * found */ + if (wc_falcon_init(falcon) != 0) { + tmpIdx = 0; + if (wc_falcon_set_level(falcon, 1) == 0) { + if (wc_Falcon_PrivateKeyDecode(key, &tmpIdx, falcon, keySz) + == 0) { + *algoID = FALCON_LEVEL1k; + } + else { + WOLFSSL_MSG("Not Falcon Level 1 DER key"); + } + } + else if (wc_falcon_set_level(falcon, 5) == 0) { + if (wc_Falcon_PrivateKeyDecode(key, &tmpIdx, falcon, keySz) + == 0) { + *algoID = FALCON_LEVEL5k; + } + else { + WOLFSSL_MSG("Not Falcon Level 5 DER key"); + } + } + else { + WOLFSSL_MSG("GetKeyOID falcon initialization failed"); + } + wc_falcon_free(falcon); + } + XFREE(falcon, heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif /* HAVE_LIBOQS */ + + /* if flag is not set then this is not a key that we understand. */ if (*algoID == 0) { WOLFSSL_MSG("Bad key DER or compile options"); return BAD_FUNC_ARG; @@ -9497,7 +9625,7 @@ static int GetCertHeader(DecodedCert* cert) } #endif -#if defined(HAVE_ED25519) || defined(HAVE_ED448) +#if defined(HAVE_ED25519) || defined(HAVE_ED448) || defined(HAVE_LIBOQS) /* Store the key data under the BIT_STRING in dynamicly allocated data. * * @param [in, out] cert Certificate object. @@ -9912,6 +10040,16 @@ static int GetCertKey(DecodedCert* cert, const byte* source, word32* inOutIdx, ret = StoreKey(cert, source, &srcIdx, maxIdx); break; #endif /* HAVE_ED448 */ + #ifdef HAVE_LIBOQS + case FALCON_LEVEL1k: + cert->pkCurveOID = FALCON_LEVEL1k; + ret = StoreKey(cert, source, &srcIdx, maxIdx); + break; + case FALCON_LEVEL5k: + cert->pkCurveOID = FALCON_LEVEL5k; + ret = StoreKey(cert, source, &srcIdx, maxIdx); + break; + #endif /* HAVE_LIBOQS */ #ifndef NO_DSA case DSAk: cert->publicKey = source + pubIdx; @@ -12474,6 +12612,10 @@ static WC_INLINE int IsSigAlgoECC(int algoOID) #ifdef HAVE_CURVE448 || (algoOID == X448k) #endif + #ifdef HAVE_LIBOQS + || (algoOID == FALCON_LEVEL1k) + || (algoOID == FALCON_LEVEL5k) + #endif ); } @@ -12720,33 +12862,47 @@ void FreeSignatureCtx(SignatureCtx* sigCtx) #ifndef NO_RSA case RSAk: wc_FreeRsaKey(sigCtx->key.rsa); - XFREE(sigCtx->key.ptr, sigCtx->heap, DYNAMIC_TYPE_RSA); + XFREE(sigCtx->key.rsa, sigCtx->heap, DYNAMIC_TYPE_RSA); + sigCtx->key.rsa = NULL; break; #endif /* !NO_RSA */ #ifndef NO_DSA case DSAk: wc_FreeDsaKey(sigCtx->key.dsa); XFREE(sigCtx->key.dsa, sigCtx->heap, DYNAMIC_TYPE_DSA); + sigCtx->key.dsa = NULL; break; #endif #ifdef HAVE_ECC case ECDSAk: wc_ecc_free(sigCtx->key.ecc); XFREE(sigCtx->key.ecc, sigCtx->heap, DYNAMIC_TYPE_ECC); + sigCtx->key.ecc = NULL; break; #endif /* HAVE_ECC */ #ifdef HAVE_ED25519 case ED25519k: wc_ed25519_free(sigCtx->key.ed25519); XFREE(sigCtx->key.ed25519, sigCtx->heap, DYNAMIC_TYPE_ED25519); + sigCtx->key.ed25519 = NULL; break; #endif /* HAVE_ED25519 */ #ifdef HAVE_ED448 case ED448k: wc_ed448_free(sigCtx->key.ed448); XFREE(sigCtx->key.ed448, sigCtx->heap, DYNAMIC_TYPE_ED448); + sigCtx->key.ed448 = NULL; break; #endif /* HAVE_ED448 */ + #ifdef HAVE_LIBOQS + case FALCON_LEVEL1k: + case FALCON_LEVEL5k: + wc_falcon_free(sigCtx->key.falcon); + XFREE(sigCtx->key.falcon, sigCtx->heap, + DYNAMIC_TYPE_FALCON); + sigCtx->key.falcon = NULL; + break; + #endif /* HAVE_LIBOQS */ default: break; } /* switch (keyOID) */ @@ -12884,6 +13040,13 @@ static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID, */ break; #endif + #ifdef HAVE_LIBOQS + case CTC_FALCON_LEVEL1: + case CTC_FALCON_LEVEL5: + /* Hashes done in signing operation. */ + break; + #endif + default: ret = HASH_TYPE_E; WOLFSSL_MSG("Hash for Signature has unsupported type"); @@ -13169,6 +13332,56 @@ static int ConfirmSignature(SignatureCtx* sigCtx, #endif break; } + #endif + #if defined(HAVE_LIBOQS) + case FALCON_LEVEL1k: + { + sigCtx->verify = 0; + sigCtx->key.falcon = + (falcon_key*)XMALLOC(sizeof(falcon_key), + sigCtx->heap, + DYNAMIC_TYPE_FALCON); + if (sigCtx->key.falcon == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + if ((ret = wc_falcon_init(sigCtx->key.falcon)) < 0) { + goto exit_cs; + } + if ((ret = wc_falcon_set_level(sigCtx->key.falcon, 1)) + < 0) { + goto exit_cs; + } + if ((ret = wc_falcon_import_public(key, keySz, + sigCtx->key.falcon)) < 0) { + WOLFSSL_MSG("ASN Key import error Falcon Level 1"); + goto exit_cs; + } + break; + } + case FALCON_LEVEL5k: + { + sigCtx->verify = 0; + sigCtx->key.falcon = + (falcon_key*)XMALLOC(sizeof(falcon_key), + sigCtx->heap, + DYNAMIC_TYPE_FALCON); + if (sigCtx->key.falcon == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + if ((ret = wc_falcon_init(sigCtx->key.falcon)) < 0) { + goto exit_cs; + } + if ((ret = wc_falcon_set_level(sigCtx->key.falcon, 5)) + < 0) { + goto exit_cs; + } + if ((ret = wc_falcon_import_public(key, keySz, + sigCtx->key.falcon)) < 0) { + WOLFSSL_MSG("ASN Key import error Falcon Level 5"); + goto exit_cs; + } + break; + } #endif default: WOLFSSL_MSG("Verify Key type unknown"); @@ -13280,6 +13493,16 @@ static int ConfirmSignature(SignatureCtx* sigCtx, NULL, 0); break; } + #endif + #if defined(HAVE_LIBOQS) + case FALCON_LEVEL1k: + case FALCON_LEVEL5k: + { + ret = wc_falcon_verify_msg(sig, sigSz, buf, bufSz, + &sigCtx->verify, + sigCtx->key.falcon); + break; + } #endif default: break; @@ -13393,6 +13616,30 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif /* HAVE_ED448 */ + #ifdef HAVE_LIBOQS + case FALCON_LEVEL1k: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("FALCON_LEVEL1 Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + case FALCON_LEVEL5k: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("FALCON_LEVEL5 Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + #endif /* HAVE_LIBOQS */ default: break; } /* switch (keyOID) */ @@ -18430,6 +18677,12 @@ wcchar END_PUB_KEY = "-----END PUBLIC KEY-----"; wcchar BEGIN_EDDSA_PRIV = "-----BEGIN EDDSA PRIVATE KEY-----"; wcchar END_EDDSA_PRIV = "-----END EDDSA PRIVATE KEY-----"; #endif +#if defined(HAVE_LIBOQS) + wcchar BEGIN_FALCON_LEVEL1_PRIV = "-----BEGIN FALCON_LEVEL1 PRIVATE KEY-----"; + wcchar END_FALCON_LEVEL1_PRIV = "-----END FALCON_LEVEL1 PRIVATE KEY-----"; + wcchar BEGIN_FALCON_LEVEL5_PRIV = "-----BEGIN FALCON_LEVEL5 PRIVATE KEY-----"; + wcchar END_FALCON_LEVEL5_PRIV = "-----END FALCON_LEVEL5 PRIVATE KEY-----"; +#endif const int pem_struct_min_sz = XSTR_SIZEOF("-----BEGIN X509 CRL-----" "-----END X509 CRL-----"); @@ -18524,6 +18777,18 @@ int wc_PemGetHeaderFooter(int type, const char** header, const char** footer) ret = 0; break; #endif +#ifdef HAVE_LIBOQS + case FALCON_LEVEL1_TYPE: + if (header) *header = BEGIN_FALCON_LEVEL1_PRIV; + if (footer) *footer = END_FALCON_LEVEL1_PRIV; + ret = 0; + break; + case FALCON_LEVEL5_TYPE: + if (header) *header = BEGIN_FALCON_LEVEL5_PRIV; + if (footer) *footer = END_FALCON_LEVEL5_PRIV; + ret = 0; + break; +#endif case PUBLICKEY_TYPE: case ECC_PUBLICKEY_TYPE: if (header) *header = BEGIN_PUB_KEY; @@ -20672,6 +20937,50 @@ int wc_Ed448PublicKeyToDer(ed448_key* key, byte* output, word32 inLen, } #endif /* HAVE_ED448 && HAVE_ED448_KEY_EXPORT */ +#if defined(HAVE_LIBOQS) +/* Encode the public part of an Falcon key in DER. + * + * Pass NULL for output to get the size of the encoding. + * + * @param [in] key Falcon key object. + * @param [out] output Buffer to put encoded data in. + * @param [in] outLen Size of buffer in bytes. + * @param [in] withAlg Whether to use SubjectPublicKeyInfo format. + * @return Size of encoded data in bytes on success. + * @return BAD_FUNC_ARG when key is NULL. + * @return MEMORY_E when dynamic memory allocation failed. + */ +int wc_Falcon_PublicKeyToDer(falcon_key* key, byte* output, word32 inLen, + int withAlg) +{ + int ret; + byte pubKey[FALCON_MAX_PUB_KEY_SIZE]; + word32 pubKeyLen = (word32)sizeof(pubKey); + int keytype = 0; + + if (key == NULL || output == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + keytype = FALCON_LEVEL1k; + } + else if (key->level == 5) { + keytype = FALCON_LEVEL5k; + } + else { + return BAD_FUNC_ARG; + } + + ret = wc_falcon_export_public(key, pubKey, &pubKeyLen); + if (ret == 0) { + ret = SetAsymKeyDerPublic(pubKey, pubKeyLen, output, inLen, keytype, + withAlg); + } + + return ret; +} +#endif /* HAVE_LIBOQS */ #ifdef WOLFSSL_CERT_GEN @@ -22647,7 +22956,7 @@ static int SetValidity(byte* before, byte* after, int daysValid) /* encode info from cert into DER encoded format */ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, DsaKey* dsaKey, ed25519_key* ed25519Key, - ed448_key* ed448Key) + ed448_key* ed448Key, falcon_key* falconKey) { int ret; @@ -22656,7 +22965,7 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, /* make sure at least one key type is provided */ if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL && - dsaKey == NULL && ed448Key == NULL) { + dsaKey == NULL && ed448Key == NULL && falconKey == NULL) { return PUBLIC_KEY_E; } @@ -22732,6 +23041,18 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, } #endif +#if defined(HAVE_LIBOQS) + if ((cert->keyType == FALCON_LEVEL1_KEY) || + (cert->keyType == FALCON_LEVEL5_KEY)) { + if (falconKey == NULL) + return PUBLIC_KEY_E; + + der->publicKeySz = + wc_Falcon_PublicKeyToDer(falconKey, der->publicKey, + (word32)sizeof(der->publicKey), 1); + } +#endif + if (der->publicKeySz <= 0) return PUBLIC_KEY_E; @@ -23100,8 +23421,8 @@ static int WriteCertBody(DerCert* der, byte* buf) /* Make RSA signature from buffer (sz), write to sig (sigSz) */ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, int sz, byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey, - ed25519_key* ed25519Key, ed448_key* ed448Key, WC_RNG* rng, int sigAlgoType, - void* heap) + ed25519_key* ed25519Key, ed448_key* ed448Key, falcon_key* falconKey, + WC_RNG* rng, int sigAlgoType, void* heap) { int digestSz = 0, typeH = 0, ret = 0; @@ -23115,6 +23436,7 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, int sz, (void)eccKey; (void)ed25519Key; (void)ed448Key; + (void)falconKey; (void)rng; (void)heap; @@ -23196,6 +23518,16 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, int sz, ret = outSz; } #endif /* HAVE_ED448 && HAVE_ED448_SIGN */ + + #if defined(HAVE_LIBOQS) + if (!rsaKey && !eccKey && !ed25519Key && !ed448Key && falconKey) { + word32 outSz = sigSz; + ret = wc_falcon_sign_msg(buf, sz, sig, &outSz, falconKey); + if (ret == 0) + ret = outSz; + } + #endif /* HAVE_LIBOQS */ + break; } @@ -23361,7 +23693,7 @@ int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz, static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, DsaKey* dsaKey, ed25519_key* ed25519Key, - ed448_key* ed448Key) + ed448_key* ed448Key, falcon_key* falconKey) { #ifndef WOLFSSL_ASN_TEMPLATE int ret; @@ -23384,6 +23716,12 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, cert->keyType = ED25519_KEY; else if (ed448Key) cert->keyType = ED448_KEY; +#ifdef HAVE_LIBOQS + else if ((falconKey != NULL) && (falconKey->level == 1)) + cert->keyType = FALCON_LEVEL1_KEY; + else if ((falconKey != NULL) && (falconKey->level == 5)) + cert->keyType = FALCON_LEVEL5_KEY; +#endif else return BAD_FUNC_ARG; @@ -23394,7 +23732,7 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, #endif ret = EncodeCert(cert, der, rsaKey, eccKey, rng, dsaKey, ed25519Key, - ed448Key); + ed448Key, falconKey); if (ret == 0) { if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) ret = BUFFER_E; @@ -23438,6 +23776,12 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, else if (ed448Key) { cert->keyType = ED448_KEY; } + else if ((falconKey != NULL) && (falconKey->level == 1)) { + cert->keyType = FALCON_LEVEL1_KEY; + } + else if ((falconKey != NULL) && (falconKey->level == 5)) { + cert->keyType = FALCON_LEVEL5_KEY; + } else { ret = BAD_FUNC_ARG; } @@ -23641,11 +23985,12 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, void* key, WC_RNG* rng) { - RsaKey* rsaKey = NULL; - DsaKey* dsaKey = NULL; - ecc_key* eccKey = NULL; - ed25519_key* ed25519Key = NULL; - ed448_key* ed448Key = NULL; + RsaKey* rsaKey = NULL; + DsaKey* dsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + ed448_key* ed448Key = NULL; + falcon_key* falconKey = NULL; if (keyType == RSA_TYPE) rsaKey = (RsaKey*)key; @@ -23657,16 +24002,21 @@ int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, ed25519Key = (ed25519_key*)key; else if (keyType == ED448_TYPE) ed448Key = (ed448_key*)key; + else if (keyType == FALCON_LEVEL1_TYPE) + falconKey = (falcon_key*)key; + else if (keyType == FALCON_LEVEL5_TYPE) + falconKey = (falcon_key*)key; return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, dsaKey, - ed25519Key, ed448Key); + ed25519Key, ed448Key, falconKey); } + /* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */ int wc_MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) { return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, NULL, - NULL); + NULL, NULL); } #ifdef WOLFSSL_CERT_REQ @@ -23753,18 +24103,20 @@ static int SetReqAttrib(byte* output, char* pw, int pwPrintableString, /* encode info from cert into DER encoded format */ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, DsaKey* dsaKey, ecc_key* eccKey, - ed25519_key* ed25519Key, ed448_key* ed448Key) + ed25519_key* ed25519Key, ed448_key* ed448Key, + falcon_key* falconKey) { (void)eccKey; (void)ed25519Key; (void)ed448Key; + (void)falconKey; if (cert == NULL || der == NULL) return BAD_FUNC_ARG; if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL && - dsaKey == NULL && ed448Key == NULL) { - return PUBLIC_KEY_E; + dsaKey == NULL && ed448Key == NULL && falconKey == NULL) { + return PUBLIC_KEY_E; } /* init */ @@ -23845,6 +24197,16 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, (word32)sizeof(der->publicKey), 1); } #endif +#if defined(HAVE_LIBOQS) + if ((cert->keyType == FALCON_LEVEL1_KEY) || + (cert->keyType == FALCON_LEVEL5_KEY)) { + if (falconKey == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = wc_Falcon_PublicKeyToDer(falconKey, + der->publicKey, (word32)sizeof(der->publicKey), 1); + } +#endif + if (der->publicKeySz <= 0) return PUBLIC_KEY_E; @@ -24069,7 +24431,8 @@ static const ASNItem certReqBodyASN[] = { static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, DsaKey* dsaKey, ecc_key* eccKey, - ed25519_key* ed25519Key, ed448_key* ed448Key) + ed25519_key* ed25519Key, ed448_key* ed448Key, + falcon_key* falconKey) { #ifndef WOLFSSL_ASN_TEMPLATE int ret; @@ -24089,6 +24452,12 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, cert->keyType = ED25519_KEY; else if (ed448Key) cert->keyType = ED448_KEY; +#ifdef HAVE_LIBOQS + else if ((falconKey != NULL) && (falconKey->level == 1)) + cert->keyType = FALCON_LEVEL1_KEY; + else if ((falconKey != NULL) && (falconKey->level == 5)) + cert->keyType = FALCON_LEVEL5_KEY; +#endif else return BAD_FUNC_ARG; @@ -24099,7 +24468,8 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, return MEMORY_E; #endif - ret = EncodeCertReq(cert, der, rsaKey, dsaKey, eccKey, ed25519Key, ed448Key); + ret = EncodeCertReq(cert, der, rsaKey, dsaKey, eccKey, ed25519Key, ed448Key, + falconKey); if (ret == 0) { if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) @@ -24147,6 +24517,12 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, else if (ed448Key != NULL) { cert->keyType = ED448_KEY; } + else if ((falconKey != NULL) && (falconKey->level == 1)) { + cert->keyType = FALCON_LEVEL1_KEY; + } + else if ((falconKey != NULL) && (falconKey->level == 5)) { + cert->keyType = FALCON_LEVEL5_KEY; + } else { ret = BAD_FUNC_ARG; } @@ -24278,6 +24654,7 @@ int wc_MakeCertReq_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, ecc_key* eccKey = NULL; ed25519_key* ed25519Key = NULL; ed448_key* ed448Key = NULL; + falcon_key* falconKey = NULL; if (keyType == RSA_TYPE) rsaKey = (RsaKey*)key; @@ -24289,22 +24666,27 @@ int wc_MakeCertReq_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, ed25519Key = (ed25519_key*)key; else if (keyType == ED448_TYPE) ed448Key = (ed448_key*)key; + else if (keyType == FALCON_LEVEL1_TYPE) + falconKey = (falcon_key*)key; + else if (keyType == FALCON_LEVEL5_TYPE) + falconKey = (falcon_key*)key; - return MakeCertReq(cert, derBuffer, derSz, rsaKey, dsaKey, eccKey, ed25519Key, - ed448Key); + return MakeCertReq(cert, derBuffer, derSz, rsaKey, dsaKey, eccKey, + ed25519Key, ed448Key, falconKey); } int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, ecc_key* eccKey) { - return MakeCertReq(cert, derBuffer, derSz, rsaKey, NULL, eccKey, NULL, NULL); + return MakeCertReq(cert, derBuffer, derSz, rsaKey, NULL, eccKey, NULL, + NULL, NULL); } #endif /* WOLFSSL_CERT_REQ */ static int SignCert(int requestSz, int sType, byte* buf, word32 buffSz, RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key, - ed448_key* ed448Key, WC_RNG* rng) + ed448_key* ed448Key, falcon_key* falconKey, WC_RNG* rng) { int sigSz = 0; void* heap = NULL; @@ -24357,8 +24739,8 @@ static int SignCert(int requestSz, int sType, byte* buf, word32 buffSz, } sigSz = MakeSignature(certSignCtx, buf, requestSz, certSignCtx->sig, - MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, ed448Key, rng, sType, - heap); + MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, ed448Key, + falconKey, rng, sType, heap); #ifdef WOLFSSL_ASYNC_CRYPT if (sigSz == WC_PENDING_E) { /* Not free'ing certSignCtx->sig here because it could still be in use @@ -24384,10 +24766,11 @@ static int SignCert(int requestSz, int sType, byte* buf, word32 buffSz, int wc_SignCert_ex(int requestSz, int sType, byte* buf, word32 buffSz, int keyType, void* key, WC_RNG* rng) { - RsaKey* rsaKey = NULL; - ecc_key* eccKey = NULL; - ed25519_key* ed25519Key = NULL; - ed448_key* ed448Key = NULL; + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + ed448_key* ed448Key = NULL; + falcon_key* falconKey = NULL; if (keyType == RSA_TYPE) rsaKey = (RsaKey*)key; @@ -24397,16 +24780,21 @@ int wc_SignCert_ex(int requestSz, int sType, byte* buf, word32 buffSz, ed25519Key = (ed25519_key*)key; else if (keyType == ED448_TYPE) ed448Key = (ed448_key*)key; + else if (keyType == FALCON_LEVEL1_TYPE) + falconKey = (falcon_key*)key; + else if (keyType == FALCON_LEVEL5_TYPE) + falconKey = (falcon_key*)key; + return SignCert(requestSz, sType, buf, buffSz, rsaKey, eccKey, ed25519Key, - ed448Key, rng); + ed448Key, falconKey, rng); } int wc_SignCert(int requestSz, int sType, byte* buf, word32 buffSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) { return SignCert(requestSz, sType, buf, buffSz, rsaKey, eccKey, NULL, NULL, - rng); + NULL, rng); } int wc_MakeSelfCert(Cert* cert, byte* buf, word32 buffSz, @@ -24440,14 +24828,14 @@ int wc_GetSubjectRaw(byte **subjectRaw, Cert *cert) /* Set KID from public key */ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, ed25519_key* ed25519Key, ed448_key* ed448Key, - int kid_type) + falcon_key* falconKey, int kid_type) { byte *buf; int bufferSz, ret; if (cert == NULL || (rsakey == NULL && eckey == NULL && ed25519Key == NULL && - ed448Key == NULL) || + ed448Key == NULL && falconKey == NULL) || (kid_type != SKID_TYPE && kid_type != AKID_TYPE)) return BAD_FUNC_ARG; @@ -24480,6 +24868,12 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, bufferSz = wc_Ed448PublicKeyToDer(ed448Key, buf, MAX_PUBLIC_KEY_SZ, 0); } #endif +#if defined(HAVE_LIBOQS) + if (falconKey != NULL) { + bufferSz = wc_Falcon_PublicKeyToDer(falconKey, buf, MAX_PUBLIC_KEY_SZ, + 0); + } +#endif if (bufferSz <= 0) { XFREE(buf, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -24504,10 +24898,11 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) { - RsaKey* rsaKey = NULL; - ecc_key* eccKey = NULL; - ed25519_key* ed25519Key = NULL; - ed448_key* ed448Key = NULL; + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + ed448_key* ed448Key = NULL; + falcon_key* falconKey = NULL; if (keyType == RSA_TYPE) rsaKey = (RsaKey*)key; @@ -24517,23 +24912,29 @@ int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) ed25519Key = (ed25519_key*)key; else if (keyType == ED448_TYPE) ed448Key = (ed448_key*)key; + else if (keyType == FALCON_LEVEL1_TYPE) + falconKey = (falcon_key*)key; + else if (keyType == FALCON_LEVEL5_TYPE) + falconKey = (falcon_key*)key; return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, ed25519Key, ed448Key, - SKID_TYPE); + falconKey, SKID_TYPE); } /* Set SKID from RSA or ECC public key */ int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) { - return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, NULL, SKID_TYPE); + return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, NULL, NULL, + SKID_TYPE); } int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) { - RsaKey* rsaKey = NULL; - ecc_key* eccKey = NULL; - ed25519_key* ed25519Key = NULL; - ed448_key* ed448Key = NULL; + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + ed448_key* ed448Key = NULL; + falcon_key* falconKey = NULL; if (keyType == RSA_TYPE) rsaKey = (RsaKey*)key; @@ -24543,15 +24944,18 @@ int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) ed25519Key = (ed25519_key*)key; else if (keyType == ED448_TYPE) ed448Key = (ed448_key*)key; + else if (keyType == FALCON_LEVEL1_TYPE) + falconKey = (falcon_key*)key; return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, ed25519Key, ed448Key, - AKID_TYPE); + falconKey, AKID_TYPE); } /* Set SKID from RSA or ECC public key */ int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) { - return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, NULL, AKID_TYPE); + return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, NULL, NULL, + AKID_TYPE); } @@ -27698,6 +28102,76 @@ int wc_Ed448PublicKeyDecode(const byte* input, word32* inOutIdx, } #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ +#if defined(HAVE_LIBOQS) +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]; + word32 privKeyLen = (word32)sizeof(privKey); + word32 pubKeyLen = (word32)sizeof(pubKey); + int keytype = 0; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + keytype = FALCON_LEVEL1k; + } + else if (key->level == 5) { + keytype = FALCON_LEVEL5k; + } + else { + return BAD_FUNC_ARG; + } + + ret = DecodeAsymKey(input, inOutIdx, inSz, privKey, &privKeyLen, + pubKey, &pubKeyLen, keytype); + if (ret == 0) { + if (pubKeyLen == 0) { + ret = wc_falcon_import_private_only(privKey, privKeyLen, + key); + } + else { + ret = wc_falcon_import_private_key(privKey, privKeyLen, + pubKey, pubKeyLen, key); + } + } + return ret; +} + +int wc_Falcon_PublicKeyDecode(const byte* input, word32* inOutIdx, + falcon_key* key, word32 inSz) +{ + int ret = 0; + byte pubKey[FALCON_MAX_PUB_KEY_SIZE]; + word32 pubKeyLen = (word32)sizeof(pubKey); + int keytype = 0; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + keytype = FALCON_LEVEL1k; + } + else if (key->level == 5) { + keytype = FALCON_LEVEL5k; + } + else { + return BAD_FUNC_ARG; + } + + ret = DecodeAsymKeyPublic(input, inOutIdx, inSz, pubKey, &pubKeyLen, + keytype); + if (ret == 0) { + ret = wc_falcon_import_public(pubKey, pubKeyLen, key); + } + return ret; +} +#endif /* HAVE_LIBOQS */ + #if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT) int wc_Curve448PrivateKeyDecode(const byte* input, word32* inOutIdx, curve448_key* key, word32 inSz) @@ -27763,6 +28237,47 @@ int wc_Ed448PrivateKeyToDer(ed448_key* key, byte* output, word32 inLen) #endif /* HAVE_ED448 && HAVE_ED448_KEY_EXPORT */ +#if defined(HAVE_LIBOQS) +int wc_Falcon_KeyToDer(falcon_key* key, byte* output, word32 inLen) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + return SetAsymKeyDer(key->k, FALCON_LEVEL1_KEY_SIZE, key->p, + FALCON_LEVEL1_KEY_SIZE, output, inLen, + FALCON_LEVEL1k); + } + else if (key->level == 5) { + return SetAsymKeyDer(key->k, FALCON_LEVEL5_KEY_SIZE, key->p, + FALCON_LEVEL5_KEY_SIZE, output, inLen, + FALCON_LEVEL5k); + } + + return BAD_FUNC_ARG; +} + +int wc_Falcon_PrivateKeyToDer(falcon_key* key, byte* output, word32 inLen) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + return SetAsymKeyDer(key->k, FALCON_LEVEL1_KEY_SIZE, NULL, 0, output, + inLen, FALCON_LEVEL1k); + } + else if (key->level == 5) { + return SetAsymKeyDer(key->k, FALCON_LEVEL5_KEY_SIZE, NULL, 0, output, + inLen, FALCON_LEVEL5k); + } + + return BAD_FUNC_ARG; +} + +#endif /* HAVE_LIBOQS */ + #if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_EXPORT) /* Write private Curve448 key to DER format, * length on success else < 0 */ diff --git a/wolfcrypt/src/falcon.c b/wolfcrypt/src/falcon.c new file mode 100644 index 000000000..3bb2f5847 --- /dev/null +++ b/wolfcrypt/src/falcon.c @@ -0,0 +1,678 @@ +/* falcon.c + * + * Copyright (C) 2006-2021 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 + */ + +/* Based on ed448.c and Reworked for Falcon by Anthony Hu. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +/* in case user set HAVE_LIBOQS there */ +#include + +#include + +#ifdef HAVE_LIBOQS + +#include + + +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* Sign the message using the falcon private key. + * + * in [in] Message to sign. + * inLen [in] Length of the message in bytes. + * out [in] Buffer to write signature into. + * outLen [in/out] On in, size of buffer. + * On out, the length of the signature in bytes. + * key [in] Falcon key to use when signing + * returns BAD_FUNC_ARG when a parameter is NULL or public key not set, + * BUFFER_E when outLen is less than FALCON_LEVEL1_SIG_SIZE, + * 0 otherwise. + */ +int wc_falcon_sign_msg(const byte* in, word32 inLen, + byte* out, word32 *outLen, + falcon_key* key) +{ + int ret = 0; + OQS_SIG *oqssig = NULL; + + /* sanity check on arguments */ + if ((in == NULL) || (out == NULL) || (outLen == NULL) || (key == NULL)) { + ret = BAD_FUNC_ARG; + } + + if ((ret == 0) && (!key->prvKeySet)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + if (key->level == 1) { + oqssig = OQS_SIG_new(OQS_SIG_alg_falcon_512); + } + else if (key->level == 5) { + oqssig = OQS_SIG_new(OQS_SIG_alg_falcon_1024); + } + + if (oqssig == NULL) { + ret = SIG_TYPE_E; + } + } + + /* check and set up out length */ + if (ret == 0) { + if ((key->level == 1) && (*outLen < FALCON_LEVEL1_SIG_SIZE)) { + *outLen = FALCON_LEVEL1_SIG_SIZE; + ret = BUFFER_E; + } + else if ((key->level == 5) && (*outLen < FALCON_LEVEL5_SIG_SIZE)) { + *outLen = FALCON_LEVEL5_SIG_SIZE; + ret = BUFFER_E; + } + } + + if ((ret == 0) && + (OQS_SIG_sign(oqssig, out, (size_t *)outLen, in, inLen, key->k) + == OQS_ERROR)) { + ret = BAD_FUNC_ARG; + } + + if (oqssig != NULL) { + OQS_SIG_free(oqssig); + } + + return ret; +} + +/* Verify the message using the falcon public key. + * + * sig [in] Signature to verify. + * sigLen [in] Size of signature in bytes. + * msg [in] Message to verify. + * msgLen [in] Length of the message in bytes. + * res [out] *res is set to 1 on successful verification. + * key [in] Falcon key to use to verify. + * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and + * BUFFER_E when sigLen is less than FALCON_LEVEL1_SIG_SIZE, + * 0 otherwise. + */ +int wc_falcon_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, falcon_key* key) +{ + int ret = 0; + OQS_SIG *oqssig = NULL; + + if (key == NULL || sig == NULL || msg == NULL || res == NULL) { + ret = BAD_FUNC_ARG; + } + + if ((ret == 0) && (!key->pubKeySet)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + if (key->level == 1) { + oqssig = OQS_SIG_new(OQS_SIG_alg_falcon_512); + } + else if (key->level == 5) { + oqssig = OQS_SIG_new(OQS_SIG_alg_falcon_1024); + } + + if (oqssig == NULL) { + ret = SIG_TYPE_E; + } + } + + if ((ret == 0) && + (OQS_SIG_verify(oqssig, msg, msgLen, sig, sigLen, key->p) + == OQS_ERROR)) { + ret = SIG_VERIFY_E; + } + + if (ret == 0) { + *res = 1; + } + + if (oqssig != NULL) { + OQS_SIG_free(oqssig); + } + + return ret; +} + +/* Initialize the falcon private/public key. + * + * key [in] Falcon key. + * returns BAD_FUNC_ARG when key is NULL + */ +int wc_falcon_init(falcon_key* key) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + ForceZero(key, sizeof(key)); + return 0; +} + +/* Set the level of the falcon private/public key. + * + * key [out] Falcon key. + * level [in] Either 1 or 5. + * returns BAD_FUNC_ARG when key is NULL or level is not 1 and not 5. + */ +int wc_falcon_set_level(falcon_key* key, byte level) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (level != 1 && level != 5) { + return BAD_FUNC_ARG; + } + + key->level = level; + key->pubKeySet = 0; + key->prvKeySet = 0; + return 0; +} + +/* Get the level of the falcon private/public key. + * + * key [in] Falcon key. + * level [out] The level. + * returns BAD_FUNC_ARG when key is NULL or level has not been set. + */ +int wc_falcon_get_level(falcon_key* key, byte* level) +{ + if (key == NULL || level == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level != 1 && key->level != 5) { + return BAD_FUNC_ARG; + } + + *level = key->level; + return 0; +} + +/* Clears the falcon key data + * + * key [in] Falcon key. + */ +void wc_falcon_free(falcon_key* key) +{ + if (key != NULL) { + ForceZero(key, sizeof(key)); + } +} + +/* Export the falcon public key. + * + * key [in] Falcon public key. + * out [in] Array to hold public key. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when outLen is less than FALCON_LEVEL1_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_falcon_export_public(falcon_key* key, + byte* out, word32* outLen) +{ + /* sanity check on arguments */ + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + return BAD_FUNC_ARG; + } + + if ((key->level != 1) && (key->level != 5)) { + return BAD_FUNC_ARG; + } + + if (!key->pubKeySet) { + return BAD_FUNC_ARG; + } + + /* check and set up out length */ + if ((key->level == 1) && (*outLen < FALCON_LEVEL1_PUB_KEY_SIZE)) { + *outLen = FALCON_LEVEL1_PUB_KEY_SIZE; + return BUFFER_E; + } + else if ((key->level == 5) && (*outLen < FALCON_LEVEL5_PUB_KEY_SIZE)) { + *outLen = FALCON_LEVEL5_PUB_KEY_SIZE; + return BUFFER_E; + } + + if (key->level == 1) { + *outLen = FALCON_LEVEL1_PUB_KEY_SIZE; + XMEMCPY(out, key->p, FALCON_LEVEL1_PUB_KEY_SIZE); + } + else if (key->level == 5) { + *outLen = FALCON_LEVEL5_PUB_KEY_SIZE; + XMEMCPY(out, key->p, FALCON_LEVEL5_PUB_KEY_SIZE); + } + + return 0; +} + +/* Import a falcon public key from a byte array. + * Public key encoded in big-endian. + * + * in [in] Array holding public key. + * inLen [in] Number of bytes of data in array. + * key [in] Falcon public key. + * returns BAD_FUNC_ARG when a parameter is NULL or key format is not supported, + * 0 otherwise. + */ +int wc_falcon_import_public(const byte* in, word32 inLen, + falcon_key* key) +{ + /* sanity check on arguments */ + if ((in == NULL) || (key == NULL)) { + return BAD_FUNC_ARG; + } + + if ((key->level != 1) && (key->level != 5)) { + return BAD_FUNC_ARG; + } + + if ((key->level == 1) && (inLen != FALCON_LEVEL1_PUB_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + else if ((key->level == 5) && (inLen != FALCON_LEVEL5_PUB_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + + XMEMCPY(key->p, in, inLen); + key->pubKeySet = 1; + + return 0; +} + +static int parse_private_key(const byte* priv, word32 privSz, + byte** out, word32 *outSz, + falcon_key* key) { + word32 idx = 0; + int ret = 0; + int length = 0; + + /* sanity check on arguments */ + if ((priv == NULL) || (key == NULL)) { + return BAD_FUNC_ARG; + } + + if ((key->level != 1) && (key->level != 5)) { + return BAD_FUNC_ARG; + } + + /* At this point, it is still a PKCS8 private key. */ + if ((ret = ToTraditionalInline(priv, &idx, privSz)) < 0) { + return ret; + } + + /* Now it is a octet_string(concat(priv,pub)) */ + if ((ret = GetOctetString(priv, &idx, &length, privSz)) < 0) { + return ret; + } + + *out = (byte *)priv + idx; + *outSz = privSz - idx; + + /* And finally it is concat(priv,pub). Key size check. */ + if ((key->level == 1) && (*outSz != FALCON_LEVEL1_KEY_SIZE + + FALCON_LEVEL1_PUB_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + else if ((key->level == 5) && (*outSz != FALCON_LEVEL5_KEY_SIZE + + FALCON_LEVEL5_PUB_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + + return 0; +} + +/* Import a falcon private key from a byte array. + * + * priv [in] Array holding private key. + * privSz [in] Number of bytes of data in array. + * key [in] Falcon private key. + * returns BAD_FUNC_ARG when a parameter is NULL or privSz is less than + * FALCON_LEVEL1_KEY_SIZE, + * 0 otherwise. + */ +int wc_falcon_import_private_only(const byte* priv, word32 privSz, + falcon_key* key) +{ + int ret = 0; + byte *newPriv = NULL; + word32 newPrivSz = 0; + + if ((ret = parse_private_key(priv, privSz, &newPriv, &newPrivSz, key)) + != 0) { + 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); + } + key->prvKeySet = 1; + + return 0; +} + +/* Import a falcon private and public keys from byte array(s). + * + * priv [in] Array holding private key or private+public keys + * privSz [in] Number of bytes of data in private key array. + * pub [in] Array holding public key (or NULL). + * pubSz [in] Number of bytes of data in public key array (or 0). + * key [in] Falcon private/public key. + * returns BAD_FUNC_ARG when a required parameter is NULL or an invalid + * combination of keys/lengths is supplied, 0 otherwise. + */ +int wc_falcon_import_private_key(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + falcon_key* key) +{ + int ret = 0; + byte *newPriv = NULL; + word32 newPrivSz = 0; + + if ((ret = parse_private_key(priv, privSz, &newPriv, &newPrivSz, key)) + != 0) { + return ret; + } + + if (pub == NULL) { + if (pubSz != 0) { + return BAD_FUNC_ARG; + } + + if ((newPrivSz != FALCON_LEVEL1_PRV_KEY_SIZE) && + (newPrivSz != FALCON_LEVEL5_PRV_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + pub = newPriv + FALCON_LEVEL1_KEY_SIZE; + pubSz = FALCON_LEVEL1_PUB_KEY_SIZE; + } + else if (key->level == 5) { + pub = newPriv + FALCON_LEVEL5_KEY_SIZE; + pubSz = FALCON_LEVEL5_PUB_KEY_SIZE; + } + } + else if ((pubSz != FALCON_LEVEL1_PUB_KEY_SIZE) && + (pubSz != FALCON_LEVEL5_PUB_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + + /* import public key */ + ret = wc_falcon_import_public(pub, pubSz, key); + + 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); + } + key->prvKeySet = 1; + } + + return ret; +} + +/* Export the falcon private key. + * + * key [in] Falcon private key. + * out [in] Array to hold private key. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when outLen is less than FALCON_LEVEL1_KEY_SIZE, + * 0 otherwise. + */ +int wc_falcon_export_private_only(falcon_key* key, byte* out, word32* outLen) +{ + /* sanity checks on arguments */ + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + return BAD_FUNC_ARG; + } + + if ((key->level != 1) && (key->level != 5)) { + return BAD_FUNC_ARG; + } + + /* check and set up out length */ + if ((key->level == 1) && (*outLen < FALCON_LEVEL1_KEY_SIZE)) { + *outLen = FALCON_LEVEL1_KEY_SIZE; + return BUFFER_E; + } + else if ((key->level == 5) && (*outLen < FALCON_LEVEL5_KEY_SIZE)) { + *outLen = FALCON_LEVEL5_KEY_SIZE; + return BUFFER_E; + } + + if (key->level == 1) { + *outLen = FALCON_LEVEL1_KEY_SIZE; + } + else if (key->level == 5) { + *outLen = FALCON_LEVEL5_KEY_SIZE; + } + + XMEMCPY(out, key->k, *outLen); + + return 0; +} + +/* Export the falcon private and public key. + * + * key [in] Falcon private/public key. + * out [in] Array to hold private and public key. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * BUFFER_E when outLen is less than FALCON_LEVEL1_PRV_KEY_SIZE, + * 0 otherwise. + */ +int wc_falcon_export_private(falcon_key* key, byte* out, word32* outLen) +{ + /* sanity checks on arguments */ + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + return BAD_FUNC_ARG; + } + + if ((key->level != 1) && (key->level != 5)) { + return BAD_FUNC_ARG; + } + + if ((key->level == 1) && (*outLen < FALCON_LEVEL1_PRV_KEY_SIZE)) { + *outLen = FALCON_LEVEL1_PRV_KEY_SIZE; + return BUFFER_E; + } + else if ((key->level == 5) && (*outLen < FALCON_LEVEL5_PRV_KEY_SIZE)) { + *outLen = FALCON_LEVEL5_PRV_KEY_SIZE; + return BUFFER_E; + } + + + 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, + 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, + FALCON_LEVEL5_PUB_KEY_SIZE); + } + + return 0; +} + +/* Export the falcon private and public key. + * + * key [in] Falcon private/public key. + * priv [in] Array to hold private key. + * privSz [in/out] On in, the number of bytes in private key array. + * pub [in] Array to hold public key. + * pubSz [in/out] On in, the number of bytes in public key array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * BUFFER_E when privSz is less than FALCON_LEVEL1_PRV_KEY_SIZE or pubSz is less + * than FALCON_LEVEL1_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_falcon_export_key(falcon_key* key, byte* priv, word32 *privSz, + byte* pub, word32 *pubSz) +{ + int ret = 0; + + /* export private part */ + ret = wc_falcon_export_private(key, priv, privSz); + if (ret == 0) { + /* export public part */ + ret = wc_falcon_export_public(key, pub, pubSz); + } + + return ret; +} + +/* Check the public key of the falcon key matches the private key. + * + * key [in] Falcon private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * PUBLIC_KEY_E when the public key is not set or doesn't match, + * other -ve value on hash failure, + * 0 otherwise. + */ +int wc_falcon_check_key(falcon_key* key) +{ + /* Might want to try to sign and verify a random message here. */ + int ret = 0; + (void)key; + return ret; +} + +/* Returns the size of a falcon private key. + * + * key [in] Falcon private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * FALCON_LEVEL1_KEY_SIZE otherwise. + */ +int wc_falcon_size(falcon_key* key) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + return FALCON_LEVEL1_KEY_SIZE; + } + else if (key->level == 5) { + return FALCON_LEVEL5_KEY_SIZE; + } + + return BAD_FUNC_ARG; +} + +/* Returns the size of a falcon private plus public key. + * + * key [in] Falcon private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * FALCON_LEVEL1_PRV_KEY_SIZE otherwise. + */ +int wc_falcon_priv_size(falcon_key* key) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + return FALCON_LEVEL1_PRV_KEY_SIZE; + } + else if (key->level == 5) { + return FALCON_LEVEL5_PRV_KEY_SIZE; + } + + return BAD_FUNC_ARG; +} + +/* Returns the size of a falcon public key. + * + * key [in] Falcon private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * FALCON_LEVEL1_PUB_KEY_SIZE otherwise. + */ +int wc_falcon_pub_size(falcon_key* key) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + return FALCON_LEVEL1_PUB_KEY_SIZE; + } + else if (key->level == 5) { + return FALCON_LEVEL5_PUB_KEY_SIZE; + } + + return BAD_FUNC_ARG; +} + +/* Returns the size of a falcon signature. + * + * key [in] Falcon private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * FALCON_LEVEL1_SIG_SIZE otherwise. + */ +int wc_falcon_sig_size(falcon_key* key) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + return FALCON_LEVEL1_SIG_SIZE; + } + else if (key->level == 5) { + return FALCON_LEVEL5_SIG_SIZE; + } + + return BAD_FUNC_ARG; +} +#endif /* HAVE_LIBOQS */ diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 73c8aab23..a1de3a51a 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -175,6 +175,7 @@ enum wolfSSL_ErrorCodes { HTTP_VERSION_ERR = -448, /* HTTP Version error */ HTTP_APPSTR_ERR = -449, /* HTTP Application string error */ UNSUPPORTED_PROTO_VERSION = -450, /* bad/unsupported protocol version*/ + FALCON_KEY_SIZE_E = -451, /* Wrong key size for Falcon. */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 9edbf21eb..5cc507313 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -116,6 +116,9 @@ #ifdef HAVE_CURVE448 #include #endif +#ifdef HAVE_LIBOQS + #include +#endif #ifndef WOLFSSL_NO_DEF_TICKET_ENC_CB #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && \ !defined(WOLFSSL_TICKET_ENC_AES128_GCM) && \ @@ -1239,9 +1242,13 @@ enum Misc { #else #ifndef NO_PSK ENCRYPT_LEN = 512 + MAX_PSK_ID_LEN + 2, /* 4096 bit static buffer */ +#else +#ifdef HAVE_LIBOQS + ENCRYPT_LEN = 5000, /* allow 40000 bit static buffer for falcon */ #else ENCRYPT_LEN = 512, /* allow 4096 bit static buffer */ #endif +#endif #endif SIZEOF_SENDER = 4, /* clnt or srvr */ FINISHED_SZ = 36, /* WC_MD5_DIGEST_SIZE + WC_SHA_DIGEST_SIZE */ @@ -1448,10 +1455,21 @@ enum Misc { ED448_SA_MAJOR = 8, /* Most significant byte for ED448 */ ED448_SA_MINOR = 8, /* Least significant byte for ED448 */ + OQS_SA_MAJOR = 0xFE,/* Most significant byte used with OQS sig algos +*/ + /* These match what OQS has defined in their OpenSSL fork. */ + FALCON_LEVEL1_SA_MAJOR = 0xFE, + FALCON_LEVEL1_SA_MINOR = 0x0B, + FALCON_LEVEL5_SA_MAJOR = 0xFE, + FALCON_LEVEL5_SA_MINOR = 0x0E, + + MIN_RSA_SHA512_PSS_BITS = 512 * 2 + 8 * 8, /* Min key size */ MIN_RSA_SHA384_PSS_BITS = 384 * 2 + 8 * 8, /* Min key size */ -#ifndef NO_RSA +#if defined(HAVE_LIBOQS) + MAX_CERT_VERIFY_SZ = 20000, /* For Falcon */ +#elif !defined(NO_RSA) MAX_CERT_VERIFY_SZ = WOLFSSL_MAX_RSA_BITS / 8, /* max RSA bytes */ #elif defined(HAVE_ECC) MAX_CERT_VERIFY_SZ = ECC_MAX_SIG_SIZE, /* max ECC */ @@ -1479,7 +1497,9 @@ enum Misc { MAX_WOLFSSL_FILE_SIZE = 1024ul * 1024ul * 4, /* 4 mb file size alloc limit */ #endif -#ifdef WOLFSSL_HAPROXY +#if defined(HAVE_LIBOQS) + MAX_X509_SIZE = 5120, /* max static x509 buffer size; falcon is big */ +#elif defined(WOLFSSL_HAPROXY) MAX_X509_SIZE = 3072, /* max static x509 buffer size */ #else MAX_X509_SIZE = 2048, /* max static x509 buffer size */ @@ -1526,7 +1546,7 @@ enum Misc { /* number of items in the signature algo list */ #ifndef WOLFSSL_MAX_SIGALGO - #define WOLFSSL_MAX_SIGALGO 36 + #define WOLFSSL_MAX_SIGALGO 38 #endif @@ -1548,6 +1568,13 @@ enum Misc { #endif #define MIN_ECCKEY_SZ (WOLFSSL_MIN_ECC_BITS / 8) +#ifdef HAVE_LIBOQS +/* set minimum Falcon key size allowed */ +#ifndef MIN_FALCONKEY_SZ + #define MIN_FALCONKEY_SZ 897 +#endif +#endif + /* set minimum RSA key size allowed */ #ifndef WOLFSSL_MIN_RSA_BITS #ifdef WOLFSSL_MAX_STRENGTH @@ -1877,10 +1904,14 @@ struct Suites { WOLFSSL_LOCAL void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, - int haveRSAsig, int haveAnon, - int tls1_2, int keySz); -WOLFSSL_LOCAL void InitSuites(Suites*, ProtocolVersion, int, word16, word16, - word16, word16, word16, word16, word16, int); + int haveRSAsig, int haveFalconSig, + int haveAnon, int tls1_2, int keySz); +WOLFSSL_LOCAL void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, + word16 haveRSA, word16 havePSK, word16 haveDH, + word16 haveECDSAsig, word16 haveECC, + word16 haveStaticECC, word16 haveFalconSig, + word16 haveAnon, int side); + WOLFSSL_LOCAL int MatchSuite(WOLFSSL* ssl, Suites* peerSuites); WOLFSSL_LOCAL int SetCipherList(WOLFSSL_CTX*, Suites*, const char* list); WOLFSSL_LOCAL int SetSuitesHashSigAlgo(Suites*, const char* list); @@ -2088,6 +2119,10 @@ struct WOLFSSL_CERT_MANAGER { wolfSSL_Mutex refMutex; /* reference count mutex */ #endif int refCount; /* reference count */ +#ifdef HAVE_LIBOQS + short minFalconKeySz; /* minimum allowed Falcon key size */ +#endif + }; WOLFSSL_LOCAL int CM_SaveCertCache(WOLFSSL_CERT_MANAGER*, const char*); @@ -2772,6 +2807,7 @@ struct WOLFSSL_CTX { byte haveECC:1; /* ECC available */ byte haveDH:1; /* server DH parms set by user */ byte haveECDSAsig:1; /* server cert signed w/ ECDSA */ + byte haveFalconSig:1; /* server cert signed w/ Falcon */ byte haveStaticECC:1; /* static server ECC private key */ byte partialWrite:1; /* only one msg per write call */ byte quietShutdown:1; /* don't send close notify */ @@ -2830,6 +2866,9 @@ struct WOLFSSL_CTX { #endif #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) short minEccKeySz; /* minimum ECC key size */ +#endif +#ifdef HAVE_LIBOQS + short minFalconKeySz; /* minimum Falcon key size */ #endif unsigned long mask; /* store SSL_OP_ flags */ #ifdef OPENSSL_EXTRA @@ -3102,14 +3141,16 @@ enum KeyExchangeAlgorithm { /* Supported Authentication Schemes */ enum SignatureAlgorithm { - anonymous_sa_algo = 0, - rsa_sa_algo = 1, - dsa_sa_algo = 2, - ecc_dsa_sa_algo = 3, - rsa_pss_sa_algo = 8, - ed25519_sa_algo = 9, - rsa_pss_pss_algo = 10, - ed448_sa_algo = 11 + anonymous_sa_algo = 0, + rsa_sa_algo = 1, + dsa_sa_algo = 2, + ecc_dsa_sa_algo = 3, + rsa_pss_sa_algo = 8, + ed25519_sa_algo = 9, + rsa_pss_pss_algo = 10, + ed448_sa_algo = 11, + falcon_level1_sa_algo = 12, + falcon_level5_sa_algo = 13 }; #define PSS_RSAE_TO_PSS_PSS(macAlgo) \ @@ -3142,7 +3183,8 @@ enum ClientCertificateType { fortezza_kea_cert = 20, ecdsa_sign = 64, rsa_fixed_ecdh = 65, - ecdsa_fixed_ecdh = 66 + ecdsa_fixed_ecdh = 66, + falcon_sign = 67, }; @@ -3561,6 +3603,7 @@ typedef struct Options { word16 haveDH:1; /* server DH parms set by user */ word16 haveECDSAsig:1; /* server ECDSA signed cert */ word16 haveStaticECC:1; /* static server ECC private key */ + word16 haveFalconSig:1; /* server Falcon signed cert */ word16 havePeerCert:1; /* do we have peer's cert */ word16 havePeerVerify:1; /* and peer's cert verify */ word16 usingPSK_cipher:1; /* are using psk as cipher */ @@ -3667,6 +3710,9 @@ typedef struct Options { #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) short minEccKeySz; /* minimum ECC key size */ #endif +#if defined(HAVE_LIBOQS) + short minFalconKeySz; /* minimum Falcon key size */ +#endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) byte verifyDepth; /* maximum verification depth */ #endif @@ -3831,9 +3877,10 @@ struct WOLFSSL_X509 { buffer pubKey; int pubKeyOID; DNS_entry* altNamesNext; /* hint for retrieval */ -#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ + defined(HAVE_LIBOQS) word32 pkCurveOID; -#endif /* HAVE_ECC */ +#endif /* HAVE_ECC || HAVE_LIBOQS */ #ifndef NO_CERTS DerBuffer* derCert; /* may need */ #endif @@ -4241,6 +4288,10 @@ struct WOLFSSL { curve448_key* peerX448Key; byte peerX448KeyPresent; #endif +#ifdef HAVE_LIBOQS + falcon_key* peerFalconKey; + byte peerFalconKeyPresent; +#endif #ifdef HAVE_LIBZ z_stream c_stream; /* compression stream */ z_stream d_stream; /* decompression stream */ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 4cc9714bc..f54c928b6 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -999,14 +999,16 @@ enum Block_Sum { enum Key_Sum { - DSAk = 515, - RSAk = 645, - ECDSAk = 518, - ED25519k = 256, /* 1.3.101.112 */ - X25519k = 254, /* 1.3.101.110 */ - ED448k = 257, /* 1.3.101.113 */ - X448k = 255, /* 1.3.101.111 */ - DHk = 647, /* dhKeyAgreement OID: 1.2.840.113549.1.3.1 */ + DSAk = 515, + RSAk = 645, + ECDSAk = 518, + ED25519k = 256, /* 1.3.101.112 */ + X25519k = 254, /* 1.3.101.110 */ + ED448k = 257, /* 1.3.101.113 */ + X448k = 255, /* 1.3.101.111 */ + DHk = 647, /* dhKeyAgreement OID: 1.2.840.113549.1.3.1 */ + FALCON_LEVEL1k = 268, /* 1.3.9999.3.1 */ + FALCON_LEVEL5k = 271 /* 1.3.9999.3.4 */ }; #if !defined(NO_AES) || defined(HAVE_PKCS7) @@ -1240,6 +1242,9 @@ struct SignatureCtx { #endif #ifdef HAVE_ED448 struct ed448_key* ed448; + #endif + #ifdef HAVE_LIBOQS + struct falcon_key* falcon; #endif void* ptr; } key; @@ -1936,18 +1941,20 @@ WOLFSSL_LOCAL int wc_MIME_free_hdrs(MimeHdr* head); enum cert_enums { #ifdef WOLFSSL_CERT_EXT - NAME_ENTRIES = 12, + NAME_ENTRIES = 12, #else - NAME_ENTRIES = 11, + NAME_ENTRIES = 11, #endif - JOINT_LEN = 2, - EMAIL_JOINT_LEN = 9, - PILOT_JOINT_LEN = 10, - RSA_KEY = 10, - ECC_KEY = 12, - ED25519_KEY = 13, - ED448_KEY = 14, - DSA_KEY = 15 + JOINT_LEN = 2, + EMAIL_JOINT_LEN = 9, + PILOT_JOINT_LEN = 10, + RSA_KEY = 10, + ECC_KEY = 12, + ED25519_KEY = 13, + ED448_KEY = 14, + DSA_KEY = 15, + FALCON_LEVEL1_KEY = 16, + FALCON_LEVEL5_KEY = 17 }; #endif /* WOLFSSL_CERT_GEN */ diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 7f2ab82be..92b9aede8 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -75,6 +75,10 @@ This library defines the interface APIs for X509 certificates. typedef struct DhKey DhKey; #define WC_DH_TYPE_DEFINED #endif +#ifndef WC_FALCONKEY_TYPE_DEFINED + typedef struct falcon_key falcon_key; + #define WC_FALCONKEY_TYPE_DEFINED +#endif enum Ecc_Sum { ECC_SECP112R1_OID = 182, @@ -138,6 +142,8 @@ enum CertType { DETECT_CERT_TYPE, DH_PRIVATEKEY_TYPE, X942_PARAM_TYPE, + FALCON_LEVEL1_TYPE, + FALCON_LEVEL5_TYPE, }; @@ -169,7 +175,10 @@ enum Ctc_SigType { CTC_SHA3_512wRSA = 430, CTC_ED25519 = 256, - CTC_ED448 = 257 + CTC_ED448 = 257, + + CTC_FALCON_LEVEL1 = 268, + CTC_FALCON_LEVEL5 = 271 }; enum Ctc_Encoding { @@ -609,7 +618,8 @@ WOLFSSL_API int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz); ((defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT)) || \ (defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_EXPORT)) || \ (defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT)) || \ - (defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_EXPORT))) + (defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_EXPORT)) || \ + (defined(HAVE_LIBOQS))) #define WC_ENABLE_ASYM_KEY_EXPORT #endif @@ -617,7 +627,8 @@ WOLFSSL_API int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz); ((defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT)) || \ (defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_IMPORT)) || \ (defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)) || \ - (defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT))) + (defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT)) || \ + (defined(HAVE_LIBOQS))) #define WC_ENABLE_ASYM_KEY_IMPORT #endif @@ -656,6 +667,14 @@ WOLFSSL_API int wc_Ed448PublicKeyToDer(ed448_key*, byte*, word32, int); #endif #endif /* HAVE_ED448 */ +#ifdef HAVE_LIBOQS +WOLFSSL_API int wc_Falcon_PrivateKeyDecode(const byte*, word32*, falcon_key*, word32); +WOLFSSL_API int wc_Falcon_PublicKeyDecode(const byte*, word32*, falcon_key*, word32); +WOLFSSL_API int wc_Falcon_KeyToDer(falcon_key*, byte*, word32); +WOLFSSL_API int wc_Falcon_PrivateKeyToDer(falcon_key*, byte*, word32); +WOLFSSL_API int wc_Falcon_PublicKeyToDer(falcon_key*, byte*, word32, int); +#endif /* HAVE_LIBOQS */ + #ifdef HAVE_CURVE448 #ifdef HAVE_CURVE448_KEY_IMPORT WOLFSSL_API int wc_Curve448PrivateKeyDecode(const byte*, word32*, curve448_key*, word32); diff --git a/wolfssl/wolfcrypt/falcon.h b/wolfssl/wolfcrypt/falcon.h new file mode 100644 index 000000000..3ff83a4ba --- /dev/null +++ b/wolfssl/wolfcrypt/falcon.h @@ -0,0 +1,129 @@ +/* falcon.h + * + * Copyright (C) 2021 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 + */ + +/*! + \file wolfssl/wolfcrypt/falcon.h +*/ + +/* Interfaces for Falcon NIST Level 1 (Falcon512) and Falcon NIST Level 5 + * (Falcon1024). */ + +#ifndef WOLF_CRYPT_FALCON_H +#define WOLF_CRYPT_FALCON_H + +#include + +#ifdef HAVE_LIBOQS + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/* Macros Definitions */ + +#define FALCON_LEVEL1_KEY_SIZE OQS_SIG_falcon_512_length_secret_key +#define FALCON_LEVEL1_SIG_SIZE OQS_SIG_falcon_512_length_signature +#define FALCON_LEVEL1_PUB_KEY_SIZE OQS_SIG_falcon_512_length_public_key +#define FALCON_LEVEL1_PRV_KEY_SIZE (FALCON_LEVEL1_PUB_KEY_SIZE+FALCON_LEVEL1_KEY_SIZE) + +#define FALCON_LEVEL5_KEY_SIZE OQS_SIG_falcon_1024_length_secret_key +#define FALCON_LEVEL5_SIG_SIZE OQS_SIG_falcon_1024_length_signature +#define FALCON_LEVEL5_PUB_KEY_SIZE OQS_SIG_falcon_1024_length_public_key +#define FALCON_LEVEL5_PRV_KEY_SIZE (FALCON_LEVEL5_PUB_KEY_SIZE+FALCON_LEVEL5_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 + +/* Structs */ + +struct falcon_key { + bool pubKeySet; + bool prvKeySet; + byte level; + byte p[FALCON_MAX_PUB_KEY_SIZE]; + byte k[FALCON_MAX_PRV_KEY_SIZE]; +}; + +#ifndef WC_FALCONKEY_TYPE_DEFINED + typedef struct falcon_key falcon_key; + #define WC_FALCONKEY_TYPE_DEFINED +#endif + +/* Functions */ + +WOLFSSL_API +int wc_falcon_sign_msg(const byte* in, word32 inLen, byte* out, word32 *outLen, + falcon_key* key); +WOLFSSL_API +int wc_falcon_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, falcon_key* key); + +WOLFSSL_API +int wc_falcon_init(falcon_key* key); +WOLFSSL_API +int wc_falcon_set_level(falcon_key* key, byte level); +WOLFSSL_API +int wc_falcon_get_level(falcon_key* key, byte* level); +WOLFSSL_API +void wc_falcon_free(falcon_key* key); + +WOLFSSL_API +int wc_falcon_import_public(const byte* in, word32 inLen, falcon_key* key); +WOLFSSL_API +int wc_falcon_import_private_only(const byte* priv, word32 privSz, + falcon_key* key); +WOLFSSL_API +int wc_falcon_import_private_key(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + falcon_key* key); + +WOLFSSL_API +int wc_falcon_export_public(falcon_key*, byte* out, word32* outLen); +WOLFSSL_API +int wc_falcon_export_private_only(falcon_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_falcon_export_private(falcon_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_falcon_export_key(falcon_key* key, byte* priv, word32 *privSz, + byte* pub, word32 *pubSz); + +WOLFSSL_API +int wc_falcon_check_key(falcon_key* key); + +WOLFSSL_API +int wc_falcon_size(falcon_key* key); +WOLFSSL_API +int wc_falcon_priv_size(falcon_key* key); +WOLFSSL_API +int wc_falcon_pub_size(falcon_key* key); +WOLFSSL_API +int wc_falcon_sig_size(falcon_key* key); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_LIBOQS */ +#endif /* WOLF_CRYPT_FALCON_H */ diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index b44a774c5..b19b93fc1 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -21,6 +21,7 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/ge_operations.h \ wolfssl/wolfcrypt/curve448.h \ wolfssl/wolfcrypt/ed448.h \ + wolfssl/wolfcrypt/falcon.h \ wolfssl/wolfcrypt/fe_448.h \ wolfssl/wolfcrypt/ge_448.h \ wolfssl/wolfcrypt/eccsi.h \ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index d6a5e9148..964aa2c65 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -838,6 +838,7 @@ decouple library dependencies with standard string, memory and so on. DYNAMIC_TYPE_ED448 = 92, DYNAMIC_TYPE_AES = 93, DYNAMIC_TYPE_CMAC = 94, + DYNAMIC_TYPE_FALCON = 95, DYNAMIC_TYPE_SNIFFER_SERVER = 1000, DYNAMIC_TYPE_SNIFFER_SESSION = 1001, DYNAMIC_TYPE_SNIFFER_PB = 1002,