Files
wolfssl/scripts/falcon-interop.c
T
Daniele Lacamera effc05a171 Falcon: remove FN-DSA / FIPS 206 references from code comments and text
Scrub the temporary "FN-DSA" name and the "FIPS 206" designation from all
in-tree comments, build text, and message strings, leaving the algorithm
named only as "Falcon". The eventual standardized name is not announced.

The differential known-answer test message ("wolfSSL FN-DSA differential
KAT") is a signed input, so the Falcon-512/1024 public keys and signatures
in wolfcrypt/test/test.c (and the mirrored Falcon-512 vector in
IDE/m33mu-falcon-verify/kat.h) were regenerated with liboqs over the new
message "wolfSSL Falcon differential KAT", preserving the differential
property (liboqs-produced signatures verified by the native verifier).

Verified: testwolfcrypt Falcon test passes; the m33mu verify-only harness
passes (BKPT 0x7f) with the regenerated vector.
2026-07-22 09:52:26 +02:00

174 lines
6.5 KiB
C

/* falcon-interop.c
*
* Copyright (C) 2006-2026 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 3 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
*/
/* Phase-5 Falcon interop harness.
*
* Cross-checks the native wolfCrypt Falcon implementation (wc_falcon_*,
* <wolfssl/wolfcrypt/falcon.h>) against liboqs (open-quantum-safe), called
* DIRECTLY through its OQS_SIG_* API. (The legacy wc_falcon_* wrapper now maps
* to the native code, so it is NOT used here as the "liboqs side".)
*
* Both encode Falcon identically (public key header 0x09/0x0A + 14-bit packed
* h; signature header 0x39/0x3A + 40-byte nonce + compressed s2), so keys and
* signatures are cross-usable. The interop matrix, run for both levels:
*
* (1) liboqs keygen+sign -> native verify
* (2) liboqs keygen+sign -> liboqs verify (baseline)
* (3) native keygen+sign -> native verify
* (4) native keygen+sign -> liboqs verify
*
* Build wolfSSL with native Falcon (no liboqs needed by the library itself):
* ./configure --enable-falcon && make
* Then compile + run against the built lib + liboqs:
* gcc -I. -I<oqs>/include scripts/falcon-interop.c \
* src/.libs/libwolfssl.a <oqs>/lib/liboqs.a -lm -lcrypto -lpthread \
* -o falcon-interop && ./falcon-interop
*
* Exit status is 0 only if every cell passes.
*/
#include <wolfssl/options.h>
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/falcon.h>
#include <wolfssl/wolfcrypt/random.h>
#include <oqs/oqs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if !defined(HAVE_FALCON)
#error "This harness requires wolfSSL built with --enable-falcon"
#endif
static const char* kMsg = "wolfSSL Falcon native<->liboqs interop message";
typedef struct {
byte level; /* FALCON_LEVEL1 / FALCON_LEVEL5 */
const char* oqsAlg;
} falcon_params;
static int oqs_verify(OQS_SIG* o, const byte* pub, const byte* sig,
size_t sigLen) {
return OQS_SIG_verify(o, (const uint8_t*)kMsg, strlen(kMsg), sig, sigLen,
pub) == OQS_SUCCESS ? 0 : -1;
}
static int native_verify(byte level, const byte* pub, word32 pubLen,
const byte* sig, word32 sigLen) {
falcon_key k;
int res = 0, ret;
if (wc_falcon_init(&k) != 0) return -1;
ret = wc_falcon_set_level(&k, level);
if (ret == 0) ret = wc_falcon_import_public(pub, pubLen, &k);
if (ret == 0) ret = wc_falcon_verify_msg(sig, sigLen, (const byte*)kMsg,
(word32)strlen(kMsg), &res, &k);
wc_falcon_free(&k);
return (ret == 0 && res == 1) ? 0 : -1;
}
static int run_level(const falcon_params* p, WC_RNG* rng) {
OQS_SIG* o = OQS_SIG_new(p->oqsAlg);
int rc = 0;
byte *oqsPub = NULL, *oqsSec = NULL, *oqsSig = NULL;
size_t oqsSigLen = 0;
word32 pubLen = (p->level == FALCON_LEVEL1) ?
FALCON_LEVEL1_PUB_KEY_SIZE : FALCON_LEVEL5_PUB_KEY_SIZE;
if (o == NULL) { printf(" L%d: OQS_SIG_new failed\n", p->level); return -1; }
oqsPub = malloc(o->length_public_key);
oqsSec = malloc(o->length_secret_key);
oqsSig = malloc(o->length_signature);
if (!oqsPub || !oqsSec || !oqsSig) { rc = -1; goto done; }
/* liboqs keygen + sign (shared by cells 1 and 2). */
if (OQS_SIG_keypair(o, oqsPub, oqsSec) != OQS_SUCCESS) { rc=-1; goto done; }
if (OQS_SIG_sign(o, oqsSig, &oqsSigLen, (const uint8_t*)kMsg, strlen(kMsg),
oqsSec) != OQS_SUCCESS) { rc=-1; goto done; }
/* (1) liboqs sign -> native verify */
if (native_verify(p->level, oqsPub, pubLen, oqsSig, (word32)oqsSigLen) != 0) {
printf(" L%d cell(1) liboqs->native FAIL\n", p->level); rc=-1;
} else printf(" L%d cell(1) liboqs->native PASS\n", p->level);
/* (2) liboqs sign -> liboqs verify */
if (oqs_verify(o, oqsPub, oqsSig, oqsSigLen) != 0) {
printf(" L%d cell(2) liboqs->liboqs FAIL\n", p->level); rc=-1;
} else printf(" L%d cell(2) liboqs->liboqs PASS\n", p->level);
#ifdef WC_FALCON_HAVE_NATIVE_SIGN
{
falcon_key nk;
byte natPub[FALCON_MAX_PUB_KEY_SIZE];
byte natSig[FALCON_MAX_SIG_SIZE];
word32 natPubLen = sizeof(natPub), natSigLen = sizeof(natSig);
int ret, res = 0;
ret = wc_falcon_init(&nk);
if (ret == 0) ret = wc_falcon_set_level(&nk, p->level);
if (ret == 0) ret = wc_falcon_make_key(&nk, rng);
if (ret == 0) ret = wc_falcon_export_public(&nk, natPub, &natPubLen);
if (ret == 0) ret = wc_falcon_sign_msg((const byte*)kMsg,
(word32)strlen(kMsg), natSig, &natSigLen, &nk, rng);
/* (3) native sign -> native verify */
res = 0;
if (ret == 0) ret = wc_falcon_verify_msg(natSig, natSigLen,
(const byte*)kMsg, (word32)strlen(kMsg), &res, &nk);
if (ret != 0 || res != 1) {
printf(" L%d cell(3) native->native FAIL\n", p->level); rc=-1;
} else printf(" L%d cell(3) native->native PASS\n", p->level);
/* (4) native sign -> liboqs verify */
if (ret == 0 && oqs_verify(o, natPub, natSig, natSigLen) == 0) {
printf(" L%d cell(4) native->liboqs PASS\n", p->level);
} else {
printf(" L%d cell(4) native->liboqs FAIL\n", p->level); rc=-1;
}
wc_falcon_free(&nk);
}
#else
printf(" L%d cell(3) native->native SKIP (native sign unavailable)\n", p->level);
printf(" L%d cell(4) native->liboqs SKIP (native sign unavailable)\n", p->level);
#endif
done:
free(oqsPub); free(oqsSec); free(oqsSig);
OQS_SIG_free(o);
return rc;
}
int main(void) {
WC_RNG rng;
int f = 0;
falcon_params l1 = { FALCON_LEVEL1, OQS_SIG_alg_falcon_512 };
falcon_params l5 = { FALCON_LEVEL5, OQS_SIG_alg_falcon_1024 };
printf("Falcon native<->liboqs interop matrix\n");
if (wc_InitRng(&rng) != 0) { printf("rng init failed\n"); return 1; }
f |= run_level(&l1, &rng);
f |= run_level(&l5, &rng);
wc_FreeRng(&rng);
printf("%s\n", f == 0 ? "ALL PASS" : "FAIL");
return f != 0;
}