Skip to content

Commit ae7098b

Browse files
committed
Address code review follow-ups for Falcon refactor
Fix pre-existing wc_Falcon_KeyToDer pubKeyLen typo: it was passing FALCON_LEVELx_KEY_SIZE (secret-key size) as the pubKeyLen argument to SetAsymKeyDer, producing DER with padding/junk bytes instead of the real public key. Now passes FALCON_LEVELx_PUB_KEY_SIZE. Restore the "Note for some CPUs smaller than 32 bit..." header comment to the oid_sum.h generator so it survives regeneration. Was silently dropped by the previous regen. Make Falcon private-key decode accept both wire formats: * wc_Falcon_PrivateKeyDecode no longer routes the full DER back through parse_private_key's legacy OCTET(OCTET(priv||pub)) parser. After DecodeAsymKey extracts privKey and pubKey separately, either use them directly (RFC 5958, as oqs-provider emits) or split the concatenated priv||pub if the legacy double-OCTET wrapping is present. * ProcessBufferTryDecodeFalcon now auto-detects the level via the OID (by trying each level through wc_Falcon_PrivateKeyDecode), and falls back to wc_falcon_import_private_only only when the DER length actually matches a Falcon raw-blob size. The previous length-based level guess erroneously matched Falcon-1024 against an ML-DSA-65 seed-priv PKCS8, masking the correct Dilithium dispatch. Minor: sweep "see mlkem.h" comments in Espressif user_settings.h templates to "see wc_mlkem.h" to match the renamed header, and point the INSTALL SPHINCS+ note at wolfSSL#10261 where the native SLH-DSA replacement is landing. Verified end-to-end against oqs-provider 0.10.0 on OpenSSL 3.0.13: * Four-way X.509 cert matrix (oqs<->wolfSSL, level 1 + 5) passes. * wolfSSL_CTX_use_PrivateKey_file loads both oqs-provider RFC 5958 PEM keys and wolfSSL legacy-format DER bench keys. * make check passes with --enable-falcon --with-liboqs.
1 parent f700a1f commit ae7098b

11 files changed

Lines changed: 124 additions & 49 deletions

File tree

IDE/Espressif/ESP-IDF/examples/template/components/wolfssl/include/user_settings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@
234234
#define WOLFSSL_NO_ML_KEM_768
235235
#define NO_SESSION_CACHE
236236
#else
237-
/* Only needed for older wolfssl versions, see mlkem.h */
237+
/* Only needed for older wolfssl versions, see wc_mlkem.h */
238238
#define WOLFSSL_KYBER1024
239239
/* optional alternative sizes: */
240240
/* #define WOLFSSL_KYBER768 */

IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/components/wolfssl/include/user_settings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@
234234
#define WOLFSSL_NO_ML_KEM_768
235235
#define NO_SESSION_CACHE
236236
#else
237-
/* Only needed for older wolfssl versions, see mlkem.h */
237+
/* Only needed for older wolfssl versions, see wc_mlkem.h */
238238
#define WOLFSSL_KYBER1024
239239
/* optional alternative sizes: */
240240
/* #define WOLFSSL_KYBER768 */

IDE/Espressif/ESP-IDF/examples/wolfssl_client/components/wolfssl/include/user_settings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@
234234
#define WOLFSSL_NO_ML_KEM_768
235235
#define NO_SESSION_CACHE
236236
#else
237-
/* Only needed for older wolfssl versions, see mlkem.h */
237+
/* Only needed for older wolfssl versions, see wc_mlkem.h */
238238
#define WOLFSSL_KYBER1024
239239
/* optional alternative sizes: */
240240
/* #define WOLFSSL_KYBER768 */

IDE/Espressif/ESP-IDF/examples/wolfssl_server/components/wolfssl/include/user_settings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@
234234
#define WOLFSSL_NO_ML_KEM_768
235235
#define NO_SESSION_CACHE
236236
#else
237-
/* Only needed for older wolfssl versions, see mlkem.h */
237+
/* Only needed for older wolfssl versions, see wc_mlkem.h */
238238
#define WOLFSSL_KYBER1024
239239
/* optional alternative sizes: */
240240
/* #define WOLFSSL_KYBER768 */

IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl/include/user_settings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@
234234
#define WOLFSSL_NO_ML_KEM_768
235235
#define NO_SESSION_CACHE
236236
#else
237-
/* Only needed for older wolfssl versions, see mlkem.h */
237+
/* Only needed for older wolfssl versions, see wc_mlkem.h */
238238
#define WOLFSSL_KYBER1024
239239
/* optional alternative sizes: */
240240
/* #define WOLFSSL_KYBER768 */

INSTALL

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@
260260
(CMake: -DWOLFSSL_OQS=yes -DWOLFSSL_FALCON=yes). Passing --with-liboqs
261261
without --enable-falcon (or vice versa) is now an error.
262262

263+
SPHINCS+ is in the middle of being replaced with native SLH-DSA; see
264+
PR #10261. Until that lands, SPHINCS+ continues to build via liboqs.
265+
263266
The following NIST Competition Round 3 finalist algorithms were supported,
264267
but have been removed after 5.3.3
265268
- SABER (KEM)

examples/configs/user_settings_espressif.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@
234234
#define WOLFSSL_NO_ML_KEM_768
235235
#define NO_SESSION_CACHE
236236
#else
237-
/* Only needed for older wolfssl versions, see mlkem.h */
237+
/* Only needed for older wolfssl versions, see wc_mlkem.h */
238238
#define WOLFSSL_KYBER1024
239239
/* optional alternative sizes: */
240240
/* #define WOLFSSL_KYBER768 */

scripts/asn1_oid_sum.pl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ sub print_header {
201201
#ifndef WOLF_CRYPT_OID_SUM_H
202202
#define WOLF_CRYPT_OID_SUM_H
203203
204+
/* Note for some CPUs smaller than 32 bit, the upper 16 bits of new OID
205+
* values may be ignored. If collisions are encountered, consider WC_16BIT_CPU
206+
* and/or WOLFSSL_OLD_OID_SUM to force smaller, old OID values. */
207+
204208
"
205209
}
206210

src/ssl_load.c

Lines changed: 84 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -825,16 +825,74 @@ static int ProcessBufferTryDecodeFalcon(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
825825
/* Initialize Falcon key. */
826826
ret = wc_falcon_init(key);
827827
if (ret == 0) {
828-
/* Set up key to parse the format specified. */
829-
if ((*keyFormat == FALCON_LEVEL1k) || ((*keyFormat == 0) &&
830-
((der->length == FALCON_LEVEL1_KEY_SIZE) ||
831-
(der->length == FALCON_LEVEL1_PRV_KEY_SIZE)))) {
832-
ret = wc_falcon_set_level(key, 1);
828+
byte level = 0;
829+
word32 idx;
830+
831+
if (*keyFormat == FALCON_LEVEL1k) {
832+
level = 1;
833+
}
834+
else if (*keyFormat == FALCON_LEVEL5k) {
835+
level = 5;
833836
}
834-
else if ((*keyFormat == FALCON_LEVEL5k) || ((*keyFormat == 0) &&
835-
((der->length == FALCON_LEVEL5_KEY_SIZE) ||
836-
(der->length == FALCON_LEVEL5_PRV_KEY_SIZE)))) {
837-
ret = wc_falcon_set_level(key, 5);
837+
838+
if (level != 0) {
839+
/* Caller told us the level via the OID sum - decode directly. */
840+
ret = wc_falcon_set_level(key, level);
841+
if (ret == 0) {
842+
idx = 0;
843+
ret = wc_Falcon_PrivateKeyDecode(der->buffer, &idx, key,
844+
der->length);
845+
if (ret != 0) {
846+
/* Accept raw priv||pub blob for the declared level. */
847+
ret = wc_falcon_import_private_only(der->buffer,
848+
der->length, key);
849+
}
850+
}
851+
}
852+
else if (*keyFormat == 0) {
853+
/* Key format unknown. Try both levels as a PKCS8-wrapped key
854+
* (OID drives the choice inside wc_Falcon_PrivateKeyDecode); if
855+
* that fails, try raw blob matching on length. */
856+
idx = 0;
857+
if (wc_falcon_set_level(key, 1) == 0 &&
858+
wc_Falcon_PrivateKeyDecode(der->buffer, &idx, key,
859+
der->length) == 0) {
860+
level = 1;
861+
}
862+
else {
863+
idx = 0;
864+
if (wc_falcon_set_level(key, 5) == 0 &&
865+
wc_Falcon_PrivateKeyDecode(der->buffer, &idx, key,
866+
der->length) == 0) {
867+
level = 5;
868+
}
869+
}
870+
if (level == 0 &&
871+
(der->length == FALCON_LEVEL1_KEY_SIZE ||
872+
der->length == FALCON_LEVEL1_PRV_KEY_SIZE)) {
873+
if (wc_falcon_set_level(key, 1) == 0 &&
874+
wc_falcon_import_private_only(der->buffer, der->length,
875+
key) == 0) {
876+
level = 1;
877+
}
878+
}
879+
if (level == 0 &&
880+
(der->length == FALCON_LEVEL5_KEY_SIZE ||
881+
der->length == FALCON_LEVEL5_PRV_KEY_SIZE)) {
882+
if (wc_falcon_set_level(key, 5) == 0 &&
883+
wc_falcon_import_private_only(der->buffer, der->length,
884+
key) == 0) {
885+
level = 5;
886+
}
887+
}
888+
if (level == 0) {
889+
/* Not a Falcon key; let caller try another algorithm. */
890+
WOLFSSL_MSG("Not a Falcon key");
891+
wc_falcon_free(key);
892+
XFREE(key, heap, DYNAMIC_TYPE_FALCON);
893+
return 0;
894+
}
895+
ret = 0;
838896
}
839897
else {
840898
wc_falcon_free(key);
@@ -843,38 +901,27 @@ static int ProcessBufferTryDecodeFalcon(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
843901
}
844902

845903
if (ret == 0) {
846-
/* Decode as a Falcon private key. */
847-
ret = wc_falcon_import_private_only(der->buffer, der->length, key);
848-
if (ret == 0) {
849-
/* Get the minimum Falcon key size from SSL or SSL context object.
850-
*/
851-
int minKeySz = ssl ? ssl->options.minFalconKeySz :
852-
ctx->minFalconKeySz;
853-
854-
/* Format is known. */
855-
if (*keyFormat == FALCON_LEVEL1k) {
856-
*keyType = falcon_level1_sa_algo;
857-
*keySize = FALCON_LEVEL1_KEY_SIZE;
858-
}
859-
else {
860-
*keyType = falcon_level5_sa_algo;
861-
*keySize = FALCON_LEVEL5_KEY_SIZE;
862-
}
904+
/* Get the minimum Falcon key size from SSL or SSL context object. */
905+
int minKeySz = ssl ? ssl->options.minFalconKeySz :
906+
ctx->minFalconKeySz;
863907

864-
/* Check that the size of the Falcon key is enough. */
865-
if (*keySize < minKeySz) {
866-
WOLFSSL_MSG("Falcon private key too small");
867-
ret = FALCON_KEY_SIZE_E;
868-
}
908+
if (key->level == 1) {
909+
*keyFormat = FALCON_LEVEL1k;
910+
*keyType = falcon_level1_sa_algo;
911+
*keySize = FALCON_LEVEL1_KEY_SIZE;
869912
}
870-
/* Not a Falcon key but check whether we know what it is. */
871-
else if (*keyFormat == 0) {
872-
WOLFSSL_MSG("Not a Falcon key");
873-
/* Format unknown so keep trying. */
874-
ret = 0;
913+
else {
914+
*keyFormat = FALCON_LEVEL5k;
915+
*keyType = falcon_level5_sa_algo;
916+
*keySize = FALCON_LEVEL5_KEY_SIZE;
917+
}
918+
919+
/* Check that the size of the Falcon key is enough. */
920+
if (*keySize < minKeySz) {
921+
WOLFSSL_MSG("Falcon private key too small");
922+
ret = FALCON_KEY_SIZE_E;
875923
}
876924

877-
/* Free dynamically allocated data in key. */
878925
wc_falcon_free(key);
879926
}
880927
else if ((ret == WC_NO_ERR_TRACE(ALGO_ID_E)) && (*keyFormat == 0)) {

wolfcrypt/src/falcon.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -844,12 +844,29 @@ int wc_Falcon_PrivateKeyDecode(const byte* input, word32* inOutIdx,
844844
ret = DecodeAsymKey(input, inOutIdx, inSz, privKey, &privKeyLen,
845845
pubKey, &pubKeyLen, keytype);
846846
if (ret == 0) {
847-
if (pubKeyLen == 0) {
848-
ret = wc_falcon_import_private_key(input, inSz, NULL, 0, key);
847+
word32 skSz = (key->level == 1) ? FALCON_LEVEL1_KEY_SIZE
848+
: FALCON_LEVEL5_KEY_SIZE;
849+
word32 pkSz = (key->level == 1) ? FALCON_LEVEL1_PUB_KEY_SIZE
850+
: FALCON_LEVEL5_PUB_KEY_SIZE;
851+
852+
/* Legacy wolfSSL layout: privateKey OCTET STRING carries priv||pub
853+
* concatenated and there is no separate publicKey field. Split the
854+
* buffer so the size validation below handles both layouts. */
855+
if (pubKeyLen == 0 && privKeyLen == skSz + pkSz) {
856+
XMEMCPY(pubKey, privKey + skSz, pkSz);
857+
pubKeyLen = pkSz;
858+
privKeyLen = skSz;
859+
}
860+
861+
if (privKeyLen != skSz || pubKeyLen != pkSz) {
862+
ret = BAD_FUNC_ARG;
849863
}
850864
else {
851-
ret = wc_falcon_import_private_key(input, inSz, pubKey,
852-
pubKeyLen, key);
865+
ret = wc_falcon_import_public(pubKey, pubKeyLen, key);
866+
if (ret == 0) {
867+
XMEMCPY(key->k, privKey, privKeyLen);
868+
key->prvKeySet = 1;
869+
}
853870
}
854871
}
855872

@@ -955,12 +972,12 @@ int wc_Falcon_KeyToDer(falcon_key* key, byte* output, word32 inLen)
955972

956973
if (key->level == 1) {
957974
return SetAsymKeyDer(key->k, FALCON_LEVEL1_KEY_SIZE, key->p,
958-
FALCON_LEVEL1_KEY_SIZE, output, inLen,
975+
FALCON_LEVEL1_PUB_KEY_SIZE, output, inLen,
959976
FALCON_LEVEL1k);
960977
}
961978
else if (key->level == 5) {
962979
return SetAsymKeyDer(key->k, FALCON_LEVEL5_KEY_SIZE, key->p,
963-
FALCON_LEVEL5_KEY_SIZE, output, inLen,
980+
FALCON_LEVEL5_PUB_KEY_SIZE, output, inLen,
964981
FALCON_LEVEL5k);
965982
}
966983

0 commit comments

Comments
 (0)