From e4f9268b00ccf5e93f30044821dfbc629203bd7e Mon Sep 17 00:00:00 2001 From: MSVSphere Packaging Team Date: Fri, 8 Nov 2024 00:47:38 +0300 Subject: [PATCH] import nss-3.101.0-9.el10 --- SOURCES/fips_algorithms.h | 7 + SOURCES/nss-3.101-fix-shlibsign-fips.patch | 12 + .../nss-3.101-replace-xyber_with-mlkem.patch | 21477 ++++++++++++++++ SPECS/nss.spec | 12 +- 4 files changed, 21507 insertions(+), 1 deletion(-) create mode 100644 SOURCES/nss-3.101-fix-shlibsign-fips.patch create mode 100644 SOURCES/nss-3.101-replace-xyber_with-mlkem.patch diff --git a/SOURCES/fips_algorithms.h b/SOURCES/fips_algorithms.h index 30f8688..af90b78 100644 --- a/SOURCES/fips_algorithms.h +++ b/SOURCES/fips_algorithms.h @@ -184,5 +184,12 @@ SFTKFIPSAlgorithmList sftk_fips_mechs[] = { offsetof(CK_SP800_108_KDF_PARAMS, prfType) }, { CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA, { 112, CK_MAX, CKF_KDF }, 1, SFTKFIPSChkHashSp800, offsetof(CK_SP800_108_KDF_PARAMS, prfType) }, + /* concatentate fuctions used in hybrid operations */ + /* The following functions add data at the end of a base key. If the base + * key is FIPS, and the resulting keys are strong enough, then the + * resulting key will also be FIPS and the resulting operations will be + * FIPS approved. */ + { CKM_CONCATENATE_BASE_AND_KEY, { 112, CK_MAX, CKF_DERIVE }, 1, SFTKFIPSNone }, + { CKM_CONCATENATE_BASE_AND_DATA, { 112, CK_MAX, CKF_DERIVE }, 1, SFTKFIPSNone }, }; const int SFTK_NUMBER_FIPS_ALGORITHMS = PR_ARRAY_SIZE(sftk_fips_mechs); diff --git a/SOURCES/nss-3.101-fix-shlibsign-fips.patch b/SOURCES/nss-3.101-fix-shlibsign-fips.patch new file mode 100644 index 0000000..70e83f5 --- /dev/null +++ b/SOURCES/nss-3.101-fix-shlibsign-fips.patch @@ -0,0 +1,12 @@ +diff -up ./cmd/shlibsign/shlibsign.c.shlibsign ./cmd/shlibsign/shlibsign.c +--- ./cmd/shlibsign/shlibsign.c.shlibsign 2024-06-07 09:26:03.000000000 -0700 ++++ ./cmd/shlibsign/shlibsign.c 2024-10-31 10:49:28.637449054 -0700 +@@ -1426,7 +1426,7 @@ main(int argc, char **argv) + } else { + /* NON FIPS mode == C_GetFunctionList */ + pC_GetFunctionList = (CK_C_GetFunctionList) +- PR_FindFunctionSymbol(lib, "C_GetFunctionList"); ++ PR_FindFunctionSymbol(lib, "NSC_GetFunctionList"); + } + assert(pC_GetFunctionList != NULL); + if (!pC_GetFunctionList) { diff --git a/SOURCES/nss-3.101-replace-xyber_with-mlkem.patch b/SOURCES/nss-3.101-replace-xyber_with-mlkem.patch new file mode 100644 index 0000000..edf1980 --- /dev/null +++ b/SOURCES/nss-3.101-replace-xyber_with-mlkem.patch @@ -0,0 +1,21477 @@ +diff -up ./cmd/lib/secutil.c.mlkem ./cmd/lib/secutil.c +--- ./cmd/lib/secutil.c.mlkem 2024-10-31 14:54:15.444515725 -0700 ++++ ./cmd/lib/secutil.c 2024-10-31 14:54:15.458515881 -0700 +@@ -4179,43 +4179,40 @@ SECU_ParseSSLVersionRangeString(const ch + return SECSuccess; + } + ++#define NAME_AND_LEN(s) sizeof(s)-1,s ++static const struct SSLNamedGroupString { ++ int len; ++ char *name; ++ SSLNamedGroup grp; ++} sslNamedGroupStringArray[] = { ++ { NAME_AND_LEN("P256"), ssl_grp_ec_secp256r1 }, ++ { NAME_AND_LEN("P384"), ssl_grp_ec_secp384r1 }, ++ { NAME_AND_LEN("P521"), ssl_grp_ec_secp521r1 }, ++ { NAME_AND_LEN("x25519"), ssl_grp_ec_curve25519 }, ++ { NAME_AND_LEN("FF2048"), ssl_grp_ffdhe_2048 }, ++ { NAME_AND_LEN("FF3072"), ssl_grp_ffdhe_3072 }, ++ { NAME_AND_LEN("FF4096"), ssl_grp_ffdhe_4096 }, ++ { NAME_AND_LEN("FF6144"), ssl_grp_ffdhe_6144 }, ++ { NAME_AND_LEN("FF8192"), ssl_grp_ffdhe_8192 }, ++ { NAME_AND_LEN("mlkem768x25519"), ssl_grp_kem_mlkem768x25519 }, ++ { NAME_AND_LEN("mlkem768secp256r1"), ssl_grp_kem_mlkem768secp256r1 }, ++}; ++ ++static const size_t sslNamedGroupStringLen=PR_ARRAY_SIZE(sslNamedGroupStringArray); ++ ++ + static SSLNamedGroup + groupNameToNamedGroup(char *name) + { +- if (PL_strlen(name) == 4) { +- if (!strncmp(name, "P256", 4)) { +- return ssl_grp_ec_secp256r1; +- } +- if (!strncmp(name, "P384", 4)) { +- return ssl_grp_ec_secp384r1; +- } +- if (!strncmp(name, "P521", 4)) { +- return ssl_grp_ec_secp521r1; +- } +- } +- if (PL_strlen(name) == 6) { +- if (!strncmp(name, "x25519", 6)) { +- return ssl_grp_ec_curve25519; +- } +- if (!strncmp(name, "FF2048", 6)) { +- return ssl_grp_ffdhe_2048; +- } +- if (!strncmp(name, "FF3072", 6)) { +- return ssl_grp_ffdhe_3072; +- } +- if (!strncmp(name, "FF4096", 6)) { +- return ssl_grp_ffdhe_4096; +- } +- if (!strncmp(name, "FF6144", 6)) { +- return ssl_grp_ffdhe_6144; +- } +- if (!strncmp(name, "FF8192", 6)) { +- return ssl_grp_ffdhe_8192; +- } +- } +- if (PL_strlen(name) == 11) { +- if (!strncmp(name, "xyber768d00", 11)) { +- return ssl_grp_kem_xyber768d00; ++ int len = PL_strlen(name); ++ int i; ++ ++ for (i=0; i < sslNamedGroupStringLen; i++) { ++ const struct SSLNamedGroupString *ngs = &sslNamedGroupStringArray[i]; ++ if (len == ngs->len) { ++ if (!strncmp(name, ngs->name, len)) { ++ return ngs->grp; ++ } + } + } + +@@ -4285,6 +4282,26 @@ done: + return SECSuccess; + } + ++const char * ++SECU_NamedGroupToGroupName(SSLNamedGroup grp) { ++ int i; ++ static char unknownBuf[32]; ++ ++ if (grp == ssl_grp_none) { ++ return "None"; ++ } ++ ++ for (i=0; i < sslNamedGroupStringLen; i++) { ++ const struct SSLNamedGroupString *ngs = &sslNamedGroupStringArray[i]; ++ if (grp == ngs->grp) { ++ return ngs->name; ++ } ++ } ++ snprintf(unknownBuf, sizeof(unknownBuf), "Unknown %d\n", grp); ++ ++ return unknownBuf; ++} ++ + SSLSignatureScheme + schemeNameToScheme(const char *name) + { +diff -up ./cmd/lib/secutil.h.mlkem ./cmd/lib/secutil.h +--- ./cmd/lib/secutil.h.mlkem 2024-10-31 14:54:15.444515725 -0700 ++++ ./cmd/lib/secutil.h 2024-10-31 14:54:15.458515881 -0700 +@@ -409,6 +409,8 @@ SECStatus parseGroupList(const char *arg + SECStatus parseSigSchemeList(const char *arg, + const SSLSignatureScheme **enabledSigSchemes, + unsigned int *enabledSigSchemeCount); ++const char *SECU_NamedGroupToGroupName(SSLNamedGroup grp); ++ + typedef struct { + SECItem label; + PRBool hasContext; +diff -up ./cmd/selfserv/selfserv.c.mlkem ./cmd/selfserv/selfserv.c +--- ./cmd/selfserv/selfserv.c.mlkem 2024-10-31 14:54:15.445515736 -0700 ++++ ./cmd/selfserv/selfserv.c 2024-10-31 14:54:15.458515881 -0700 +@@ -229,7 +229,7 @@ PrintParameterUsage() + "-I comma separated list of enabled groups for TLS key exchange.\n" + " The following values are valid:\n" + " P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192,\n" +- " xyber768d00\n" ++ " mlkem768x25519, mlkem768secp256r1\n" + "-J comma separated list of enabled signature schemes in preference order.\n" + " The following values are valid:\n" + " rsa_pkcs1_sha1, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512,\n" +@@ -422,9 +422,11 @@ printSecurityInfo(PRFileDesc *fd) + channel.isFIPS ? " FIPS" : ""); + FPRINTF(stderr, + "selfserv: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n" ++ " Key Exchange Group:%s\n" + " Compression: %s, Extended Master Secret: %s\n", + channel.authKeyBits, suite.authAlgorithmName, +- channel.keaKeyBits, suite.keaTypeName, ++ channel.keaKeyBits, suite.keaTypeName, ++ SECU_NamedGroupToGroupName(channel.keaGroup), + channel.compressionMethodName, + channel.extendedMasterSecretUsed ? "Yes" : "No"); + } +diff -up ./cmd/strsclnt/strsclnt.c.mlkem ./cmd/strsclnt/strsclnt.c +--- ./cmd/strsclnt/strsclnt.c.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./cmd/strsclnt/strsclnt.c 2024-10-31 14:54:15.458515881 -0700 +@@ -298,9 +298,11 @@ printSecurityInfo(PRFileDesc *fd) + channel.isFIPS ? " FIPS" : ""); + FPRINTF(stderr, + "strsclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n" ++ " Key Exchange Group:%s\n" + " Compression: %s\n", + channel.authKeyBits, suite.authAlgorithmName, + channel.keaKeyBits, suite.keaTypeName, ++ SECU_NamedGroupToGroupName(channel.keaGroup), + channel.compressionMethodName); + } + } +diff -up ./cmd/tstclnt/tstclnt.c.mlkem ./cmd/tstclnt/tstclnt.c +--- ./cmd/tstclnt/tstclnt.c.mlkem 2024-10-31 14:54:15.445515736 -0700 ++++ ./cmd/tstclnt/tstclnt.c 2024-10-31 14:54:15.459515892 -0700 +@@ -177,10 +177,12 @@ printSecurityInfo(PRFileDesc *fd) + channel.isFIPS ? " FIPS" : ""); + FPRINTF(stderr, + "tstclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n" ++ " Key Exchange Group:%s\n" + " Compression: %s, Extended Master Secret: %s\n" + " Signature Scheme: %s\n", + channel.authKeyBits, suite.authAlgorithmName, + channel.keaKeyBits, suite.keaTypeName, ++ SECU_NamedGroupToGroupName(channel.keaGroup), + channel.compressionMethodName, + channel.extendedMasterSecretUsed ? "Yes" : "No", + signatureSchemeName(channel.signatureScheme)); +@@ -307,7 +309,7 @@ PrintParameterUsage() + fprintf(stderr, "%-20s Comma separated list of enabled groups for TLS key exchange.\n" + "%-20s The following values are valid:\n" + "%-20s P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192\n" +- "%-20s xyber768d00\n", ++ "%-20s mlkem768x25519, mlkem768secp256r1\n", + "-I", "", "", ""); + fprintf(stderr, "%-20s Comma separated list of signature schemes in preference order.\n" + "%-20s The following values are valid:\n" +diff -up ./gtests/nss_bogo_shim/config.json.mlkem ./gtests/nss_bogo_shim/config.json +--- ./gtests/nss_bogo_shim/config.json.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/nss_bogo_shim/config.json 2024-10-31 14:54:15.459515892 -0700 +@@ -65,6 +65,8 @@ + "KyberKeyShareIncludedSecond":"Boring sends Xyber768 even if is not the client's first preference", + "KyberKeyShareIncludedThird":"Boring sends Xyber768 even if is not the client's first preference", + ++ "NoCommonSignatureAlgorithms-TLS12-Fallback":"Boring will consider RSA key exchange if a common signature algorithm cannot be found", ++ + "####################":"####################", + "### TLS1/11 failures due to unsupported signature algorithms":"", + "####################":"####################", +diff -up ./gtests/nss_bogo_shim/nss_bogo_shim.cc.mlkem ./gtests/nss_bogo_shim/nss_bogo_shim.cc +--- ./gtests/nss_bogo_shim/nss_bogo_shim.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/nss_bogo_shim/nss_bogo_shim.cc 2024-10-31 14:54:15.459515892 -0700 +@@ -435,13 +435,6 @@ class TestAgent { + if (rv != SECSuccess) { + return false; + } +- // Xyber768 is disabled by policy by default, so if it's requested +- // we need to update the policy flags as well. +- for (auto group : groups) { +- if (group == ssl_grp_kem_xyber768d00) { +- NSS_SetAlgorithmPolicy(SEC_OID_XYBER768D00, NSS_USE_ALG_IN_SSL_KX, 0); +- } +- } + } + + return true; +diff -up ./gtests/pk11_gtest/pk11_kem_unittest.cc.mlkem ./gtests/pk11_gtest/pk11_kem_unittest.cc +--- ./gtests/pk11_gtest/pk11_kem_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/pk11_gtest/pk11_kem_unittest.cc 2024-10-31 14:54:15.459515892 -0700 +@@ -13,7 +13,9 @@ + + namespace nss_test { + +-class Pkcs11KEMTest : public ::testing::Test { ++class Pkcs11KEMTest ++ : public ::testing::Test, ++ public ::testing::WithParamInterface { + protected: + PK11SymKey *Encapsulate(const ScopedSECKEYPublicKey &pub, + CK_MECHANISM_TYPE target, PK11AttrFlags attrFlags, +@@ -65,22 +67,46 @@ class Pkcs11KEMTest : public ::testing:: + + SECITEM_FreeItem(&attrValue, PR_FALSE); + } ++ ++ CK_MECHANISM_TYPE keyGenMech() { ++ switch (GetParam()) { ++ case CKP_NSS_KYBER_768_ROUND3: ++ return CKM_NSS_KYBER_KEY_PAIR_GEN; ++ case CKP_NSS_ML_KEM_768: ++ return CKM_NSS_ML_KEM_KEY_PAIR_GEN; ++ default: ++ EXPECT_TRUE(false); ++ return 0; ++ } ++ } ++ ++ CK_MECHANISM_TYPE encapsMech() { ++ switch (GetParam()) { ++ case CKP_NSS_KYBER_768_ROUND3: ++ return CKM_NSS_KYBER; ++ case CKP_NSS_ML_KEM_768: ++ return CKM_NSS_ML_KEM; ++ default: ++ EXPECT_TRUE(false); ++ return 0; ++ } ++ } + }; + +-TEST_F(Pkcs11KEMTest, KemConsistencyTest) { +- Pkcs11KeyPairGenerator generator(CKM_NSS_KYBER_KEY_PAIR_GEN); ++TEST_P(Pkcs11KEMTest, KemConsistencyTest) { ++ Pkcs11KeyPairGenerator generator(keyGenMech()); + ScopedSECKEYPrivateKey priv; + ScopedSECKEYPublicKey pub; + generator.GenerateKey(&priv, &pub, false); + +- ASSERT_EQ((unsigned int)KYBER768_PUBLIC_KEY_BYTES, +- (unsigned int)pub->u.kyber.publicValue.len); ++ ASSERT_NE(nullptr, pub); ++ ASSERT_NE(nullptr, priv); + + // Copy the public key to simulate receiving the key as an octet string + ScopedSECKEYPublicKey pubCopy(SECKEY_CopyPublicKey(pub.get())); + ASSERT_NE(nullptr, pubCopy); + +- ScopedPK11SlotInfo slot(PK11_GetBestSlot(CKM_NSS_KYBER, nullptr)); ++ ScopedPK11SlotInfo slot(PK11_GetBestSlot(encapsMech(), nullptr)); + ASSERT_NE(nullptr, slot); + + ASSERT_NE((unsigned int)CK_INVALID_HANDLE, +@@ -91,9 +117,6 @@ TEST_F(Pkcs11KEMTest, KemConsistencyTest + pubCopy, CKM_SALSA20_POLY1305, PK11_ATTR_PRIVATE | PK11_ATTR_UNMODIFIABLE, + CKF_ENCRYPT, &ciphertext)); + +- ASSERT_EQ((unsigned int)KYBER768_CIPHERTEXT_BYTES, +- (unsigned int)ciphertext->len); +- + ASSERT_EQ(CKM_SALSA20_POLY1305, PK11_GetMechanism(sharedSecret.get())); + + CK_BBOOL ckTrue = CK_TRUE; +@@ -119,4 +142,7 @@ TEST_F(Pkcs11KEMTest, KemConsistencyTest + EXPECT_EQ(0, SECITEM_CompareItem(item1, item2)); + } + ++INSTANTIATE_TEST_SUITE_P(Pkcs11KEMTest, Pkcs11KEMTest, ++ ::testing::Values(CKP_NSS_ML_KEM_768)); ++ + } // namespace nss_test +diff -up ./gtests/pk11_gtest/pk11_keygen.cc.mlkem ./gtests/pk11_gtest/pk11_keygen.cc +--- ./gtests/pk11_gtest/pk11_keygen.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/pk11_gtest/pk11_keygen.cc 2024-10-31 14:54:15.459515892 -0700 +@@ -158,6 +158,11 @@ std::unique_ptr Pkcs11KeyPa + return std::unique_ptr( + new KyberParamHolder(CKP_NSS_KYBER_768_ROUND3)); + ++ case CKM_NSS_ML_KEM_KEY_PAIR_GEN: ++ std::cerr << "Generate ML-KEM768 pair" << std::endl; ++ return std::unique_ptr( ++ new KyberParamHolder(CKP_NSS_ML_KEM_768)); ++ + default: + ADD_FAILURE() << "unknown OID " << mech_; + } +diff -up ./gtests/ssl_gtest/manifest.mn.mlkem ./gtests/ssl_gtest/manifest.mn +--- ./gtests/ssl_gtest/manifest.mn.mlkem 2024-10-31 14:54:15.419515446 -0700 ++++ ./gtests/ssl_gtest/manifest.mn 2024-10-31 14:54:15.459515892 -0700 +@@ -13,6 +13,7 @@ CSRCS = \ + + CPPSRCS = \ + bloomfilter_unittest.cc \ ++ selfencrypt_unittest.cc \ + ssl_0rtt_unittest.cc \ + ssl_aead_unittest.cc \ + ssl_agent_unittest.cc \ +@@ -42,24 +43,23 @@ CPPSRCS = \ + ssl_record_unittest.cc \ + ssl_recordsep_unittest.cc \ + ssl_recordsize_unittest.cc \ +- ssl_resumption_unittest.cc \ + ssl_renegotiation_unittest.cc \ ++ ssl_resumption_unittest.cc \ + ssl_skip_unittest.cc \ + ssl_staticrsa_unittest.cc \ + ssl_tls13compat_unittest.cc \ + ssl_v2_client_hello_unittest.cc \ + ssl_version_unittest.cc \ + ssl_versionpolicy_unittest.cc \ +- selfencrypt_unittest.cc \ + test_io.cc \ + tls_agent.cc \ + tls_connect.cc \ +- tls_hkdf_unittest.cc \ + tls_filter.cc \ ++ tls_hkdf_unittest.cc \ ++ tls_mlkem_unittest.cc \ + tls_protect.cc \ + tls_psk_unittest.cc \ + tls_subcerts_unittest.cc \ +- tls_xyber_unittest.cc \ + $(SSLKEYLOGFILE_FILES) \ + $(NULL) + +diff -up ./gtests/ssl_gtest/ssl_0rtt_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_0rtt_unittest.cc +--- ./gtests/ssl_gtest/ssl_0rtt_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_0rtt_unittest.cc 2024-10-31 14:54:15.459515892 -0700 +@@ -197,8 +197,9 @@ TEST_P(TlsZeroRttReplayTest, ZeroRttRepl + TEST_P(TlsConnectTls13, ZeroRttOptionsSetLate) { + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); + Connect(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + SendReceive(); // Need to read so that we absorb the session ticket. +- CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); ++ CheckKeys(); + Reset(); + StartConnect(); + // Now turn on 0-RTT but too late for the ticket. +diff -up ./gtests/ssl_gtest/ssl_auth_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_auth_unittest.cc +--- ./gtests/ssl_gtest/ssl_auth_unittest.cc.mlkem 2024-10-31 14:54:15.452515814 -0700 ++++ ./gtests/ssl_gtest/ssl_auth_unittest.cc 2024-10-31 14:54:15.459515892 -0700 +@@ -46,6 +46,7 @@ TEST_P(TlsConnectTls12Plus, ServerAuthRs + PR_ARRAY_SIZE(kSignatureSchemePss)); + server_->SetSignatureSchemes(kSignatureSchemePss, + PR_ARRAY_SIZE(kSignatureSchemePss)); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + Connect(); + CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_pss, + ssl_sig_rsa_pss_pss_sha256); +@@ -76,6 +77,7 @@ TEST_P(TlsConnectTls12Plus, ServerAuthRs + PR_ARRAY_SIZE(kSignatureSchemePss)); + server_->SetSignatureSchemes(kSignatureSchemePss, + PR_ARRAY_SIZE(kSignatureSchemePss)); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + Connect(); + CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_pss, + ssl_sig_rsa_pss_pss_sha256); +@@ -919,7 +921,7 @@ TEST_P(TlsConnectClientAuth, ClientAuthE + client_->SetupClientAuth(std::get<2>(GetParam()), true); + server_->RequestClientAuth(true); + Connect(); +- CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa); ++ CheckKeys(ssl_auth_ecdsa); + } + + TEST_P(TlsConnectClientAuth, ClientAuthWithEch) { +@@ -932,7 +934,7 @@ TEST_P(TlsConnectClientAuth, ClientAuthW + client_->SetupClientAuth(std::get<2>(GetParam()), true); + server_->RequestClientAuth(true); + Connect(); +- CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa); ++ CheckKeys(ssl_auth_ecdsa); + } + + TEST_P(TlsConnectClientAuth, ClientAuthBigRsa) { +@@ -1276,14 +1278,14 @@ static const SSLSignatureScheme kSignatu + static const SSLSignatureScheme kSignatureSchemeRsaSha256[] = { + ssl_sig_rsa_pkcs1_sha256}; + +-static SSLNamedGroup NamedGroupForEcdsa384(uint16_t version) { ++static SSLNamedGroup NamedGroupForEcdsa384(const TlsConnectTestBase *ctbase) { + // NSS tries to match the group size to the symmetric cipher. In TLS 1.1 and + // 1.0, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA is the highest priority suite, so + // we use P-384. With TLS 1.2 on we pick AES-128 GCM so use x25519. +- if (version <= SSL_LIBRARY_VERSION_TLS_1_1) { ++ if (ctbase->GetVersion() <= SSL_LIBRARY_VERSION_TLS_1_1) { + return ssl_grp_ec_secp384r1; + } +- return ssl_grp_ec_curve25519; ++ return ctbase->GetDefaultGroupFromKEA(ctbase->GetDefaultKEA()); + } + + // When signature algorithms match up, this should connect successfully; even +@@ -1295,7 +1297,7 @@ TEST_P(TlsConnectGeneric, SignatureAlgor + server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384, + PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); + Connect(); +- CheckKeys(ssl_kea_ecdh, NamedGroupForEcdsa384(version_), ssl_auth_ecdsa, ++ CheckKeys(GetDefaultKEA(), NamedGroupForEcdsa384(this), ssl_auth_ecdsa, + ssl_sig_ecdsa_secp384r1_sha384); + } + +@@ -1314,7 +1316,7 @@ TEST_P(TlsConnectGeneric, SignatureAlgor + SSL_SignaturePrefSet(client_->ssl_fd(), clientAlgorithms, + PR_ARRAY_SIZE(clientAlgorithms))); + Connect(); +- CheckKeys(ssl_kea_ecdh, NamedGroupForEcdsa384(version_), ssl_auth_ecdsa, ++ CheckKeys(GetDefaultKEA(), NamedGroupForEcdsa384(this), ssl_auth_ecdsa, + ssl_sig_ecdsa_secp384r1_sha384); + } + +@@ -1325,7 +1327,7 @@ TEST_P(TlsConnectGeneric, SignatureAlgor + server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384, + PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); + Connect(); +- CheckKeys(ssl_kea_ecdh, NamedGroupForEcdsa384(version_), ssl_auth_ecdsa, ++ CheckKeys(GetDefaultKEA(), NamedGroupForEcdsa384(this), ssl_auth_ecdsa, + ssl_sig_ecdsa_secp384r1_sha384); + } + +@@ -1417,6 +1419,7 @@ TEST_P(TlsConnectTls12, SignatureAlgorit + + TEST_P(TlsConnectTls13, UnsupportedSignatureSchemeAlert) { + EnsureTlsSetup(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + auto filter = + MakeTlsFilter(server_, ssl_sig_none); + filter->EnableDecryption(); +@@ -1428,6 +1431,8 @@ TEST_P(TlsConnectTls13, UnsupportedSigna + + TEST_P(TlsConnectTls13, InconsistentSignatureSchemeAlert) { + EnsureTlsSetup(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + + // This won't work because we use an RSA cert by default. + auto filter = MakeTlsFilter( +@@ -1575,6 +1580,7 @@ static SECStatus AuthCompleteBlock(TlsAg + // processed by the client, SSL_AuthCertificateComplete() is called. + TEST_F(TlsConnectDatagram13, AuthCompleteBeforeFinished) { + client_->SetAuthCertificateCallback(AuthCompleteBlock); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + MakeTlsFilter(server_, client_, [this]() { + EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0)); + }); +@@ -2008,8 +2014,7 @@ class TlsSignatureSchemeConfiguration + EnsureTlsSetup(); + configPeer->SetSignatureSchemes(&signature_scheme_, 1); + Connect(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, auth_type_, +- signature_scheme_); ++ CheckKeys(auth_type_, signature_scheme_); + } + + std::string certificate_; +@@ -2043,7 +2048,7 @@ TEST_P(TlsSignatureSchemeConfiguration, + client_->SetSignatureSchemes(&signature_scheme_, 1); + server_->SetSignatureSchemes(&signature_scheme_, 1); + Connect(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, auth_type_, signature_scheme_); ++ CheckKeys(auth_type_, signature_scheme_); + } + + class Tls12CertificateRequestReplacer : public TlsHandshakeFilter { +diff -up ./gtests/ssl_gtest/ssl_damage_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_damage_unittest.cc +--- ./gtests/ssl_gtest/ssl_damage_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_damage_unittest.cc 2024-10-31 14:54:15.459515892 -0700 +@@ -60,6 +60,8 @@ TEST_F(TlsConnectTest, DamageSecretHandl + + TEST_P(TlsConnectGenericPre13, DamageServerSignature) { + EnsureTlsSetup(); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + auto filter = MakeTlsFilter( + server_, kTlsHandshakeServerKeyExchange); + ExpectAlert(client_, kTlsAlertDecryptError); +@@ -70,6 +72,8 @@ TEST_P(TlsConnectGenericPre13, DamageSer + + TEST_P(TlsConnectTls13, DamageServerSignature) { + EnsureTlsSetup(); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + auto filter = MakeTlsFilter( + server_, kTlsHandshakeCertificateVerify); + filter->EnableDecryption(); +diff -up ./gtests/ssl_gtest/ssl_dhe_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_dhe_unittest.cc +--- ./gtests/ssl_gtest/ssl_dhe_unittest.cc.mlkem 2024-10-31 14:54:15.452515814 -0700 ++++ ./gtests/ssl_gtest/ssl_dhe_unittest.cc 2024-10-31 14:54:15.459515892 -0700 +@@ -29,7 +29,7 @@ TEST_P(TlsConnectGeneric, ConnectDhe) { + + TEST_P(TlsConnectTls13, SharesForBothEcdheAndDhe) { + EnsureTlsSetup(); +- client_->ConfigNamedGroups(kAllDHEGroups); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + + auto groups_capture = + std::make_shared(client_, ssl_supported_groups_xtn); +@@ -41,7 +41,7 @@ TEST_P(TlsConnectTls13, SharesForBothEcd + + Connect(); + +- CheckKeys(); ++ CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); + + bool ec, dh; + auto track_group_type = [&ec, &dh](SSLNamedGroup group) { +diff -up ./gtests/ssl_gtest/ssl_drop_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_drop_unittest.cc +--- ./gtests/ssl_gtest/ssl_drop_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_drop_unittest.cc 2024-10-31 14:54:15.460515903 -0700 +@@ -201,6 +201,8 @@ class TlsDropDatagram13 : public TlsConn + // ACKs + TEST_P(TlsDropDatagram13, DropClientFirstFlightOnce) { + client_filters_.drop_->Reset({0}); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + StartConnect(); + client_->Handshake(); + server_->Handshake(); +@@ -210,6 +212,8 @@ TEST_P(TlsDropDatagram13, DropClientFirs + + TEST_P(TlsDropDatagram13, DropServerFirstFlightOnce) { + server_filters_.drop_->Reset(0xff); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + StartConnect(); + client_->Handshake(); + // Send the first flight, all dropped. +@@ -224,6 +228,8 @@ TEST_P(TlsDropDatagram13, DropServerFirs + // TODO(ekr@rtfm.com): We should generate an empty ACK. + TEST_P(TlsDropDatagram13, DropServerFirstRecordOnce) { + server_filters_.drop_->Reset({0}); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + StartConnect(); + client_->Handshake(); + server_->Handshake(); +@@ -236,6 +242,8 @@ TEST_P(TlsDropDatagram13, DropServerFirs + // produce an ACK. + TEST_P(TlsDropDatagram13, DropServerSecondRecordOnce) { + server_filters_.drop_->Reset({1}); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + StartConnect(); + client_->Handshake(); + server_->Handshake(); +@@ -299,6 +307,8 @@ TEST_P(TlsDropDatagram13, DropClientCert + // Shrink the MTU down so that certs get split and drop the first piece. + TEST_P(TlsDropDatagram13, DropFirstHalfOfServerCertificate) { + server_filters_.drop_->Reset({2}); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + StartConnect(); + ShrinkPostServerHelloMtu(); + client_->Handshake(); +@@ -326,6 +336,8 @@ TEST_P(TlsDropDatagram13, DropFirstHalfO + // Shrink the MTU down so that certs get split and drop the second piece. + TEST_P(TlsDropDatagram13, DropSecondHalfOfServerCertificate) { + server_filters_.drop_->Reset({3}); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + StartConnect(); + ShrinkPostServerHelloMtu(); + client_->Handshake(); +@@ -414,6 +426,8 @@ class TlsFragmentationAndRecoveryTest : + + private: + void FirstFlightDropCertificate() { ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + StartConnect(); + client_->Handshake(); + +@@ -561,6 +575,8 @@ TEST_P(TlsDropDatagram13, NoDropsDuringZ + + TEST_P(TlsDropDatagram13, DropEEDuringZeroRtt) { + SetupForZeroRtt(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + SetFilters(); + std::cerr << "Starting second handshake" << std::endl; + client_->Set0RttEnabled(true); +@@ -606,6 +622,8 @@ class TlsReorderDatagram13 : public TlsD + // of the flight and will still produce an ACK. + TEST_P(TlsDropDatagram13, ReorderServerEE) { + server_filters_.drop_->Reset({1}); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + StartConnect(); + client_->Handshake(); + server_->Handshake(); +@@ -684,6 +702,8 @@ TEST_F(TlsConnectDatagram13, SendOutOfOr + // Shrink the MTU down so that certs get split and then swap the first and + // second pieces of the server certificate. + TEST_P(TlsReorderDatagram13, ReorderServerCertificate) { ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + StartConnect(); + ShrinkPostServerHelloMtu(); + client_->Handshake(); +diff -up ./gtests/ssl_gtest/ssl_ecdh_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_ecdh_unittest.cc +--- ./gtests/ssl_gtest/ssl_ecdh_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_ecdh_unittest.cc 2024-10-31 14:54:15.460515903 -0700 +@@ -490,7 +490,7 @@ TEST_P(TlsKeyExchangeTest13, EqualPriori + + Connect(); + +- CheckKeys(); ++ CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); + const std::vector shares = {ssl_grp_ec_curve25519}; + CheckKEXDetails(client_groups, shares); + } +diff -up ./gtests/ssl_gtest/ssl_exporter_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_exporter_unittest.cc +--- ./gtests/ssl_gtest/ssl_exporter_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_exporter_unittest.cc 2024-10-31 14:54:15.460515903 -0700 +@@ -82,8 +82,11 @@ TEST_P(TlsConnectGenericPre13, ExporterC + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF}; + + EnsureTlsSetup(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + Connect(); +- CheckKeys(); ++ CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); ++ + + static const size_t exporter_len = 10; + uint8_t client_value[exporter_len] = {0}; +diff -up ./gtests/ssl_gtest/ssl_extension_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_extension_unittest.cc +--- ./gtests/ssl_gtest/ssl_extension_unittest.cc.mlkem 2024-10-31 14:54:15.452515814 -0700 ++++ ./gtests/ssl_gtest/ssl_extension_unittest.cc 2024-10-31 14:54:15.460515903 -0700 +@@ -1314,6 +1314,9 @@ TEST_P(TlsDisallowedUnadvertisedExtensio + + TEST_P(TlsConnectStream, IncludePadding) { + EnsureTlsSetup(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); ++ + SSL_EnableTls13GreaseEch(client_->ssl_fd(), PR_FALSE); // Don't GREASE + + // This needs to be long enough to push a TLS 1.0 ClientHello over 255, but +@@ -1372,7 +1375,7 @@ TEST_F(TlsConnectStreamTls13, ClientHell + PR_TRUE) == SECSuccess); + Connect(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); ++ CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_mlkem768x25519, ssl_auth_psk, ssl_sig_none); + } + + /* This test checks that the ClientHello extension order is actually permuted +diff -up ./gtests/ssl_gtest/ssl_gtest.gyp.mlkem ./gtests/ssl_gtest/ssl_gtest.gyp +--- ./gtests/ssl_gtest/ssl_gtest.gyp.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_gtest.gyp 2024-10-31 14:54:15.460515903 -0700 +@@ -31,8 +31,8 @@ + 'ssl_ems_unittest.cc', + 'ssl_exporter_unittest.cc', + 'ssl_extension_unittest.cc', +- 'ssl_fuzz_unittest.cc', + 'ssl_fragment_unittest.cc', ++ 'ssl_fuzz_unittest.cc', + 'ssl_gather_unittest.cc', + 'ssl_gtest.cc', + 'ssl_hrr_unittest.cc', +@@ -43,8 +43,8 @@ + 'ssl_record_unittest.cc', + 'ssl_recordsep_unittest.cc', + 'ssl_recordsize_unittest.cc', +- 'ssl_resumption_unittest.cc', + 'ssl_renegotiation_unittest.cc', ++ 'ssl_resumption_unittest.cc', + 'ssl_skip_unittest.cc', + 'ssl_staticrsa_unittest.cc', + 'ssl_tls13compat_unittest.cc', +@@ -54,13 +54,14 @@ + 'test_io.cc', + 'tls_agent.cc', + 'tls_connect.cc', ++ 'tls_ech_unittest.cc', + 'tls_filter.cc', ++ 'tls_grease_unittest.cc', + 'tls_hkdf_unittest.cc', +- 'tls_ech_unittest.cc', ++ 'tls_mlkem_unittest.cc', + 'tls_protect.cc', + 'tls_psk_unittest.cc', + 'tls_subcerts_unittest.cc', +- 'tls_grease_unittest.cc', + 'tls_xyber_unittest.cc', + ], + 'dependencies': [ +diff -up ./gtests/ssl_gtest/ssl_hrr_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_hrr_unittest.cc +--- ./gtests/ssl_gtest/ssl_hrr_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_hrr_unittest.cc 2024-10-31 14:54:15.460515903 -0700 +@@ -22,6 +22,7 @@ TEST_P(TlsConnectTls13, HelloRetryReques + const PRInt32 k0RttDataLen = static_cast(strlen(k0RttData)); + + SetupForZeroRtt(); // initial handshake as normal ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + + static const std::vector groups = {ssl_grp_ec_secp384r1, + ssl_grp_ec_secp521r1}; +@@ -107,6 +108,7 @@ TEST_P(TlsConnectTls13, SecondClientHell + auto orig_client = + std::make_shared(client_->name(), TlsAgent::CLIENT, variant_); + client_.swap(orig_client); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1, + SSL_LIBRARY_VERSION_TLS_1_3); + client_->ConfigureSessionCache(RESUME_BOTH); +@@ -370,6 +372,7 @@ TEST_P(TlsConnectTls13, RetryCallbackRet + size_t cb_called = 0; + EXPECT_EQ(SECSuccess, SSL_HelloRetryRequestCallback(server_->ssl_fd(), + RetryHello, &cb_called)); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + + // Do the first message exchange. + StartConnect(); +@@ -417,6 +420,7 @@ TEST_P(TlsConnectTls13, RetryCallbackRet + size_t cb_called = 0; + EXPECT_EQ(SECSuccess, SSL_HelloRetryRequestCallback(server_->ssl_fd(), + RetryHello, &cb_called)); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + + // Do the first message exchange. + StartConnect(); +@@ -950,7 +954,7 @@ TEST_P(TlsKeyExchange13, ConnectEcdhePre + client_->ConfigNamedGroups(client_groups); + server_->ConfigNamedGroups(server_groups); + Connect(); +- CheckKeys(); ++ CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519); + static const std::vector expectedShares = { + ssl_grp_ec_secp384r1}; + CheckKEXDetails(client_groups, expectedShares, ssl_grp_ec_curve25519); +@@ -997,7 +1001,7 @@ TEST_P(TlsKeyExchange13, ConnectEcdhePre + EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); + + Connect(); +- CheckKeys(); ++ CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519); + CheckKEXDetails(client_groups, client_groups); + } + +@@ -1043,7 +1047,7 @@ TEST_P(TlsKeyExchange13, + EXPECT_EQ(2U, cb_called); + EXPECT_TRUE(shares_capture2_->captured()) << "client should send shares"; + +- CheckKeys(); ++ CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519); + static const std::vector client_shares( + client_groups.begin(), client_groups.begin() + 2); + CheckKEXDetails(client_groups, client_shares, server_groups[0]); +diff -up ./gtests/ssl_gtest/ssl_keyupdate_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_keyupdate_unittest.cc +--- ./gtests/ssl_gtest/ssl_keyupdate_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_keyupdate_unittest.cc 2024-10-31 14:54:15.460515903 -0700 +@@ -1180,6 +1180,8 @@ TEST_F(TlsConnectDatagram13, DTLSKU_Wron + + TEST_F(TlsConnectDatagram13, DTLSKU_DamagedLength) { + EnsureTlsSetup(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + // Filter replacing the length value with 0. + auto filter = MakeTlsFilter(client_, 3, 0); + filter->EnableDecryption(); +@@ -1217,6 +1219,8 @@ TEST_F(TlsConnectDatagram13, DTLSKU_Dama + + TEST_F(TlsConnectDatagram13, DTLSKU_DamagedFragmentLength) { + EnsureTlsSetup(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + // Filter replacing the fragment length with 1. + auto filter = MakeTlsFilter(client_, 10, 1); + filter->EnableDecryption(); +@@ -1498,4 +1502,4 @@ TEST_F(TlsConnectDatagram13, DTLSKU_TooE + client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT); + } + +-} // namespace nss_test +\ No newline at end of file ++} // namespace nss_test +diff -up ./gtests/ssl_gtest/ssl_loopback_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_loopback_unittest.cc +--- ./gtests/ssl_gtest/ssl_loopback_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_loopback_unittest.cc 2024-10-31 14:54:15.460515903 -0700 +@@ -37,7 +37,7 @@ TEST_P(TlsConnectGeneric, ConnectEcdsa) + SetExpectedVersion(std::get<1>(GetParam())); + Reset(TlsAgent::kServerEcdsa256); + Connect(); +- CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa); ++ CheckKeys(ssl_auth_ecdsa); + } + + TEST_P(TlsConnectGeneric, CipherSuiteMismatch) { +diff -up ./gtests/ssl_gtest/ssl_recordsep_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_recordsep_unittest.cc +--- ./gtests/ssl_gtest/ssl_recordsep_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_recordsep_unittest.cc 2024-10-31 14:54:15.460515903 -0700 +@@ -344,6 +344,8 @@ static void SendForwardReceive(std::shar + } + + TEST_P(TlsConnectStream, ReplaceRecordLayer) { ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + StartConnect(); + client_->SetServerKeyBits(server_->server_key_bits()); + +@@ -387,7 +389,7 @@ TEST_P(TlsConnectStream, ReplaceRecordLa + client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED); + server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED); + } +- CheckKeys(); ++ CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); // why? + + // Reading and writing application data should work. + SendForwardReceive(client_, client_stage, server_); +@@ -445,6 +447,8 @@ static SECStatus AuthCompleteBlock(TlsAg + } + + TEST_P(TlsConnectStream, ReplaceRecordLayerAsyncLateAuth) { ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + StartConnect(); + client_->SetServerKeyBits(server_->server_key_bits()); + +@@ -494,7 +498,7 @@ TEST_P(TlsConnectStream, ReplaceRecordLa + client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED); + server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED); + } +- CheckKeys(); ++ CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); // why? + + // Reading and writing application data should work. + SendForwardReceive(client_, client_stage, server_); +diff -up ./gtests/ssl_gtest/ssl_recordsize_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_recordsize_unittest.cc +--- ./gtests/ssl_gtest/ssl_recordsize_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_recordsize_unittest.cc 2024-10-31 14:54:15.461515914 -0700 +@@ -275,6 +275,7 @@ TEST_F(TlsConnectStreamTls13, ClientHell + auto filter = + MakeTlsFilter(client_, kTlsHandshakeClientHello); + ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + // Add PSK with label long enough to push CH length into [256, 511]. + std::vector label(100); + EXPECT_EQ(SECSuccess, +@@ -723,4 +724,4 @@ TEST_P(TlsConnectGeneric, RecordSizeLimi + } + } + +-} // namespace nss_test +\ No newline at end of file ++} // namespace nss_test +diff -up ./gtests/ssl_gtest/ssl_resumption_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_resumption_unittest.cc +--- ./gtests/ssl_gtest/ssl_resumption_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_resumption_unittest.cc 2024-10-31 14:54:15.461515914 -0700 +@@ -175,11 +175,15 @@ TEST_P(TlsConnectGenericResumption, Conn + TEST_P(TlsConnectGenericPre13, ResumeWithHigherVersionTls13) { + uint16_t lower_version = version_; + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + Connect(); + SendReceive(); + CheckKeys(); + + Reset(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + EnsureTlsSetup(); + auto psk_ext = std::make_shared( +@@ -244,6 +248,8 @@ TEST_P(TlsConnectGenericPre13, ResumeWit + // connection. This looks like compatibility mode, we just want to ensure + // that we get TLS 1.3 rather than 1.2 (and no resumption). + Reset(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + auto client_sid = MakeTlsFilter(client_); + auto server_sid = MakeTlsFilter(server_); + ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID); +@@ -359,12 +365,14 @@ TEST_P(TlsConnectGenericResumption, Conn + TEST_P(TlsConnectGeneric, ConnectWithExpiredTicketAtServer) { + // This causes a ticket resumption. + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + Connect(); + SendReceive(); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); + ExpectResumption(RESUME_NONE); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + + SSLExtensionType xtn = (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) + ? ssl_tls13_pre_shared_key_xtn +@@ -453,7 +461,7 @@ TEST_P(TlsConnectGeneric, ServerSNICertT + Connect(); + ScopedCERTCertificate cert2(SSL_PeerCertificate(client_->ssl_fd())); + ASSERT_NE(nullptr, cert2.get()); +- CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa); ++ CheckKeys(ssl_auth_ecdsa); + EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert)); + } + +@@ -613,7 +621,7 @@ TEST_P(TlsConnectGenericResumption, Resu + client_->EnableSingleCipher(ChooseOneCipher(version_)); + Connect(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); ++ CheckKeys(ssl_auth_rsa_sign); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); +@@ -628,7 +636,7 @@ TEST_P(TlsConnectGenericResumption, Resu + auto ticket_capture = + MakeTlsFilter(client_, ticket_extension); + Connect(); +- CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); ++ CheckKeys(ssl_auth_rsa_sign); + EXPECT_EQ(0U, ticket_capture->extension().len()); + } + +@@ -655,7 +663,7 @@ TEST_P(TlsConnectStream, ResumptionOverr + server_->EnableSingleCipher(ChooseOneCipher(version_)); + Connect(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); ++ CheckKeys(); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); +@@ -793,8 +801,7 @@ TEST_F(TlsConnectTest, TestTls13Resumpti + MakeTlsFilter(client_, ssl_tls13_pre_shared_key_xtn); + Connect(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, +- ssl_sig_rsa_pss_rsae_sha256); ++ CheckKeys(ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); + // The filter will go away when we reset, so save the captured extension. + DataBuffer initialTicket(c1->extension()); + ASSERT_LT(0U, initialTicket.len()); +@@ -811,8 +818,7 @@ TEST_F(TlsConnectTest, TestTls13Resumpti + ExpectResumption(RESUME_TICKET); + Connect(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, +- ssl_sig_rsa_pss_rsae_sha256); ++ CheckKeys(ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); + ASSERT_LT(0U, c2->extension().len()); + + ScopedCERTCertificate cert2(SSL_PeerCertificate(client_->ssl_fd())); +@@ -1089,7 +1095,7 @@ TEST_F(TlsConnectTest, TestTls13Resumpti + Handshake(); + + SendReceive(); +- CheckKeys(); ++ CheckKeys(ssl_kea_ecdh); + } + + TEST_F(TlsConnectTest, TestTls13ResumptionForcedDowngrade) { +@@ -1144,15 +1150,15 @@ TEST_P(TlsConnectGenericResumption, ReCo + server_->EnableSingleCipher(ChooseOneCipher(version_)); + Connect(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, +- ssl_sig_rsa_pss_rsae_sha256); ++ CheckKeys(ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); + // Resume + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + ExpectResumption(RESUME_TICKET); + Connect(); + // Only the client knows this. +- CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519, ++ CheckKeysResumption(GetDefaultKEA(), ssl_grp_none, ++ GetDefaultGroupFromKEA(GetDefaultKEA()), + ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); + } + +@@ -1161,13 +1167,13 @@ TEST_P(TlsConnectGenericPre13, ReConnect + server_->EnableSingleCipher(ChooseOneCipher(version_)); + Connect(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, +- ssl_sig_rsa_pss_rsae_sha256); ++ CheckKeys(ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); + // Resume + Reset(); + ExpectResumption(RESUME_SESSIONID); + Connect(); +- CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519, ++ CheckKeysResumption(GetDefaultKEA(), ssl_grp_none, ++ GetDefaultGroupFromKEA(GetDefaultKEA()), + ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); + } + +@@ -1176,15 +1182,15 @@ TEST_P(TlsConnectGenericResumption, ReCo + server_->EnableSingleCipher(ChooseOneCipher(version_)); + Connect(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, +- ssl_sig_rsa_pss_rsae_sha256); ++ CheckKeys(ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); + // Resume + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + ExpectResumption(RESUME_TICKET); + Connect(); + // Only the client knows this. +- CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519, ++ CheckKeysResumption(GetDefaultKEA(), ssl_grp_none, ++ GetDefaultGroupFromKEA(GetDefaultKEA()), + ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); + // Resume connection again + Reset(); +@@ -1192,7 +1198,8 @@ TEST_P(TlsConnectGenericResumption, ReCo + ExpectResumption(RESUME_TICKET, 2); + Connect(); + // Only the client knows this. +- CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519, ++ CheckKeysResumption(GetDefaultKEA(), ssl_grp_none, ++ GetDefaultGroupFromKEA(GetDefaultKEA()), + ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); + } + +@@ -1219,11 +1226,15 @@ void CheckGetInfoResult(PRTime now, uint + // when resuming using an external token. + TEST_P(TlsConnectGenericResumptionToken, CheckSessionId) { + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + auto original_sid = MakeTlsFilter(client_); + Connect(); + SendReceive(); + + Reset(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + ExpectResumption(RESUME_TICKET); + +diff -up ./gtests/ssl_gtest/ssl_skip_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_skip_unittest.cc +--- ./gtests/ssl_gtest/ssl_skip_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_skip_unittest.cc 2024-10-31 14:54:15.461515914 -0700 +@@ -114,6 +114,9 @@ class Tls13SkipTest : public TlsConnectT + void SetUp() override { + TlsConnectTestBase::SetUp(); + EnsureTlsSetup(); ++ // until we can fix filters to work with MLKEM ++ client_->ConfigNamedGroups(kNonPQDHEGroups); ++ server_->ConfigNamedGroups(kNonPQDHEGroups); + } + + void ServerSkipTest(std::shared_ptr filter, int32_t error) { +diff -up ./gtests/ssl_gtest/ssl_tls13compat_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_tls13compat_unittest.cc +--- ./gtests/ssl_gtest/ssl_tls13compat_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_tls13compat_unittest.cc 2024-10-31 14:54:15.461515914 -0700 +@@ -482,6 +482,7 @@ TEST_F(TlsConnectDatagram13, CompatModeD + client_->SetOption(SSL_ENABLE_TLS13_COMPAT_MODE, PR_TRUE); + auto client_records = MakeTlsFilter(client_); + auto server_records = MakeTlsFilter(server_); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + Connect(); + + ASSERT_EQ(2U, client_records->count()); // CH, Fin +@@ -522,6 +523,7 @@ class AddSessionIdFilter : public TlsHan + // mode. It should be ignored instead. + TEST_F(TlsConnectDatagram13, CompatModeDtlsServer) { + EnsureTlsSetup(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + auto client_records = std::make_shared(client_); + client_->SetFilter( + std::make_shared(ChainedPacketFilterInit( +diff -up ./gtests/ssl_gtest/ssl_version_unittest.cc.mlkem ./gtests/ssl_gtest/ssl_version_unittest.cc +--- ./gtests/ssl_gtest/ssl_version_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_version_unittest.cc 2024-10-31 14:54:15.461515914 -0700 +@@ -370,6 +370,7 @@ TEST_F(DtlsConnectTest, DtlsSupportedVer + SSL_LIBRARY_VERSION_TLS_1_3); + auto capture = MakeTlsFilter( + client_, ssl_tls13_supported_versions_xtn); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + Connect(); + + ASSERT_EQ(7U, capture->extension().len()); +@@ -393,6 +394,7 @@ TEST_F(DtlsConnectTest, Dtls13VersionWor + + // Toggle the workaround, then verify both encodings are present. + EnsureTlsSetup(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + SSL_SetDtls13VersionWorkaround(client_->ssl_fd(), PR_TRUE); + SSL_SetDtls13VersionWorkaround(client_->ssl_fd(), PR_FALSE); + SSL_SetDtls13VersionWorkaround(client_->ssl_fd(), PR_TRUE); +diff -up ./gtests/ssl_gtest/tls_agent.cc.mlkem ./gtests/ssl_gtest/tls_agent.cc +--- ./gtests/ssl_gtest/tls_agent.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/tls_agent.cc 2024-10-31 14:54:15.461515914 -0700 +@@ -493,15 +493,21 @@ void TlsAgent::DisableAllCiphers() { + // Not actually all groups, just the ones that we are actually willing + // to use. + const std::vector kAllDHEGroups = { +- ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, +- ssl_grp_ec_secp521r1, ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072, +- ssl_grp_ffdhe_4096, ssl_grp_ffdhe_6144, ssl_grp_ffdhe_8192, +- ssl_grp_kem_xyber768d00, ++ ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, ++ ssl_grp_ec_secp521r1, ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072, ++ ssl_grp_ffdhe_4096, ssl_grp_ffdhe_6144, ssl_grp_ffdhe_8192, ++ ssl_grp_kem_mlkem768x25519, ssl_grp_kem_mlkem768secp256r1, ++}; ++ ++const std::vector kNonPQDHEGroups = { ++ ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, ++ ssl_grp_ec_secp521r1, ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072, ++ ssl_grp_ffdhe_4096, ssl_grp_ffdhe_6144, ssl_grp_ffdhe_8192, + }; + + const std::vector kECDHEGroups = { + ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, +- ssl_grp_ec_secp521r1, ssl_grp_kem_xyber768d00, ++ ssl_grp_ec_secp521r1, + }; + + const std::vector kFFDHEGroups = { +@@ -510,12 +516,14 @@ const std::vector kFFDHEG + + // Defined because the big DHE groups are ridiculously slow. + const std::vector kFasterDHEGroups = { +- ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, +- ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072, ssl_grp_kem_xyber768d00, ++ ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, ++ ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072, ++ ssl_grp_kem_mlkem768x25519, ssl_grp_kem_mlkem768secp256r1, + }; + + const std::vector kEcdhHybridGroups = { +- ssl_grp_kem_xyber768d00, ++ ssl_grp_kem_mlkem768x25519, ++ ssl_grp_kem_mlkem768secp256r1, + }; + + void TlsAgent::EnableCiphersByKeyExchange(SSLKEAType kea) { +@@ -683,9 +691,10 @@ void TlsAgent::CheckKEA(SSLKEAType kea, + if (kea_size == 0) { + switch (kea_group) { + case ssl_grp_ec_curve25519: +- case ssl_grp_kem_xyber768d00: ++ case ssl_grp_kem_mlkem768x25519: + kea_size = 255; + break; ++ case ssl_grp_kem_mlkem768secp256r1: + case ssl_grp_ec_secp256r1: + kea_size = 256; + break; +@@ -1315,6 +1324,10 @@ void TlsAgentTestBase::Reset(const std:: + if (version_) { + agent_->SetVersionRange(version_, version_); + } ++ const std::vector groups = { ++ ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, ++ ssl_grp_ffdhe_2048}; ++ agent_->ConfigNamedGroups(groups); + agent_->adapter()->SetPeer(sink_adapter_); + agent_->StartConnect(); + } +diff -up ./gtests/ssl_gtest/tls_agent.h.mlkem ./gtests/ssl_gtest/tls_agent.h +--- ./gtests/ssl_gtest/tls_agent.h.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/tls_agent.h 2024-10-31 14:54:15.461515914 -0700 +@@ -52,6 +52,7 @@ class TlsCipherSpec; + struct TlsRecord; + + const extern std::vector kAllDHEGroups; ++const extern std::vector kNonPQDHEGroups; + const extern std::vector kECDHEGroups; + const extern std::vector kFFDHEGroups; + const extern std::vector kFasterDHEGroups; +diff -up ./gtests/ssl_gtest/tls_connect.cc.mlkem ./gtests/ssl_gtest/tls_connect.cc +--- ./gtests/ssl_gtest/tls_connect.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/tls_connect.cc 2024-10-31 14:54:15.461515914 -0700 +@@ -505,21 +505,23 @@ void TlsConnectTestBase::CheckEarlyDataL + EXPECT_EQ(expected_size, static_cast(preinfo.maxEarlyDataSize)); + } + +-void TlsConnectTestBase::CheckKeys(SSLKEAType kea_type, SSLNamedGroup kea_group, +- SSLAuthType auth_type, +- SSLSignatureScheme sig_scheme) const { +- if (kea_group != ssl_grp_none) { +- client_->CheckKEA(kea_type, kea_group); +- server_->CheckKEA(kea_type, kea_group); ++SSLKEAType TlsConnectTestBase::GetDefaultKEA(void) const { ++ if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { ++ return ssl_kea_ecdh_hybrid; + } +- server_->CheckAuthType(auth_type, sig_scheme); +- client_->CheckAuthType(auth_type, sig_scheme); ++ return ssl_kea_ecdh; + } + +-void TlsConnectTestBase::CheckKeys(SSLKEAType kea_type, +- SSLAuthType auth_type) const { ++SSLAuthType TlsConnectTestBase::GetDefaultAuth(void) const { ++ return ssl_auth_rsa_sign; ++} ++ ++SSLNamedGroup TlsConnectTestBase::GetDefaultGroupFromKEA(SSLKEAType kea_type) const { + SSLNamedGroup group; + switch (kea_type) { ++ case ssl_kea_ecdh_hybrid: ++ group = ssl_grp_kem_mlkem768x25519; ++ break; + case ssl_kea_ecdh: + group = ssl_grp_ec_curve25519; + break; +@@ -534,7 +536,10 @@ void TlsConnectTestBase::CheckKeys(SSLKE + group = ssl_grp_none; + break; + } ++ return group; ++} + ++SSLSignatureScheme TlsConnectTestBase::GetDefaultSchemeFromAuth(SSLAuthType auth_type) const { + SSLSignatureScheme scheme; + switch (auth_type) { + case ssl_auth_rsa_decrypt: +@@ -561,11 +566,54 @@ void TlsConnectTestBase::CheckKeys(SSLKE + scheme = static_cast(0x0100); + break; + } ++ return scheme; ++} ++void TlsConnectTestBase::CheckKeys(SSLKEAType kea_type, SSLNamedGroup kea_group, ++ SSLAuthType auth_type, ++ SSLSignatureScheme sig_scheme) const { ++ if (kea_group != ssl_grp_none) { ++ client_->CheckKEA(kea_type, kea_group); ++ server_->CheckKEA(kea_type, kea_group); ++ } ++ server_->CheckAuthType(auth_type, sig_scheme); ++ client_->CheckAuthType(auth_type, sig_scheme); ++} ++ ++void TlsConnectTestBase::CheckKeys(SSLKEAType kea_type, ++ SSLNamedGroup kea_group) const { ++ SSLAuthType auth_type = GetDefaultAuth(); ++ SSLSignatureScheme scheme = GetDefaultSchemeFromAuth(auth_type); ++ CheckKeys(kea_type, kea_group, auth_type, scheme); ++} ++ ++void TlsConnectTestBase::CheckKeys( SSLAuthType auth_type, ++ SSLSignatureScheme sig_scheme) const { ++ SSLKEAType kea_type = GetDefaultKEA(); ++ SSLNamedGroup group = GetDefaultGroupFromKEA(kea_type); ++ CheckKeys(kea_type, group, auth_type, sig_scheme); ++} ++ ++void TlsConnectTestBase::CheckKeys(SSLKEAType kea_type, ++ SSLAuthType auth_type) const { ++ SSLNamedGroup group = GetDefaultGroupFromKEA(kea_type); ++ SSLSignatureScheme scheme = GetDefaultSchemeFromAuth(auth_type); + CheckKeys(kea_type, group, auth_type, scheme); + } + ++void TlsConnectTestBase::CheckKeys(SSLKEAType kea_type) const { ++ SSLAuthType auth_type = GetDefaultAuth(); ++ CheckKeys(kea_type, auth_type); ++} ++ ++void TlsConnectTestBase::CheckKeys(SSLAuthType auth_type) const { ++ SSLKEAType kea_type = GetDefaultKEA(); ++ CheckKeys(kea_type, auth_type); ++} ++ + void TlsConnectTestBase::CheckKeys() const { +- CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); ++ SSLKEAType kea_type = GetDefaultKEA(); ++ SSLAuthType auth_type = GetDefaultAuth(); ++ CheckKeys(kea_type, auth_type); + } + + void TlsConnectTestBase::CheckKeysResumption(SSLKEAType kea_type, +diff -up ./gtests/ssl_gtest/tls_connect.h.mlkem ./gtests/ssl_gtest/tls_connect.h +--- ./gtests/ssl_gtest/tls_connect.h.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/tls_connect.h 2024-10-31 14:54:15.461515914 -0700 +@@ -83,11 +83,23 @@ class TlsConnectTestBase : public ::test + void ConnectWithCipherSuite(uint16_t cipher_suite); + void CheckEarlyDataLimit(const std::shared_ptr& agent, + size_t expected_size); ++ // Get the default KEA for our tls version ++ SSLKEAType GetDefaultKEA(void) const; ++ // Get the default auth for our tls version ++ SSLAuthType GetDefaultAuth(void) const; ++ // Find the default group for a given KEA ++ SSLNamedGroup GetDefaultGroupFromKEA(SSLKEAType kea_type) const; ++ // Find the default scheam for a given auth ++ SSLSignatureScheme GetDefaultSchemeFromAuth(SSLAuthType auth_type) const; + // Check that the keys used in the handshake match expectations. + void CheckKeys(SSLKEAType kea_type, SSLNamedGroup kea_group, + SSLAuthType auth_type, SSLSignatureScheme sig_scheme) const; +- // This version guesses some of the values. ++ // These version guesses some of the values. ++ void CheckKeys(SSLKEAType kea_type, SSLNamedGroup kea_group) const; ++ void CheckKeys(SSLAuthType auth_type, SSLSignatureScheme sig_scheme) const; + void CheckKeys(SSLKEAType kea_type, SSLAuthType auth_type) const; ++ void CheckKeys(SSLKEAType kea_type) const; ++ void CheckKeys(SSLAuthType auth_type) const; + // This version assumes defaults. + void CheckKeys() const; + // Check that keys on resumed sessions. +@@ -103,6 +115,7 @@ class TlsConnectTestBase : public ::test + + void ConfigureVersion(uint16_t version); + void SetExpectedVersion(uint16_t version); ++ uint16_t GetVersion(void) const { return version_; }; + // Expect resumption of a particular type. + void ExpectResumption(SessionResumptionMode expected, + uint8_t num_resumed = 1); +diff -up ./gtests/ssl_gtest/tls_mlkem_unittest.cc.mlkem ./gtests/ssl_gtest/tls_mlkem_unittest.cc +--- ./gtests/ssl_gtest/tls_mlkem_unittest.cc.mlkem 2024-10-31 14:54:15.462515926 -0700 ++++ ./gtests/ssl_gtest/tls_mlkem_unittest.cc 2024-10-31 14:54:15.462515926 -0700 +@@ -0,0 +1,516 @@ ++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim: set ts=2 et sw=2 tw=80: */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this file, ++ * You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#include "ssl.h" ++#include "sslerr.h" ++#include "sslproto.h" ++#include "secmodti.h" /* for SEC_OID_MLKEM768SECP256R1, remove when shipped upstream */ ++ ++extern "C" { ++// This is not something that should make you happy. ++#include "libssl_internals.h" ++} ++ ++#include "gtest_utils.h" ++#include "nss_scoped_ptrs.h" ++#include "tls_connect.h" ++#include "tls_filter.h" ++#include "tls_parser.h" ++ ++namespace nss_test { ++ ++TEST_P(TlsKeyExchangeTest13, Mlkem768x25519Supported) { ++ EnsureKeyShareSetup(); ++ ConfigNamedGroups({ssl_grp_kem_mlkem768x25519}); ++ ++ Connect(); ++ CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_mlkem768x25519, ssl_auth_rsa_sign, ++ ssl_sig_rsa_pss_rsae_sha256); ++} ++ ++TEST_P(TlsKeyExchangeTest13, Mlkem768Secp256r1Supported) { ++ EnsureKeyShareSetup(); ++ ConfigNamedGroups({ssl_grp_kem_mlkem768secp256r1}); ++ ++ Connect(); ++ CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_mlkem768secp256r1, ++ ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); ++} ++ ++TEST_P(TlsKeyExchangeTest, Tls12ClientMlkem768StartNotSupported) { ++ EnsureKeyShareSetup(); ++ client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, ++ SSL_LIBRARY_VERSION_TLS_1_2); ++ server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, ++ SSL_LIBRARY_VERSION_TLS_1_3); ++ client_->DisableAllCiphers(); ++ client_->EnableCiphersByKeyExchange(ssl_kea_ecdh); ++ client_->EnableCiphersByKeyExchange(ssl_kea_ecdh_hybrid); ++ EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares( ++ client_->ssl_fd(), ++ kECDHEGroups.size() + kEcdhHybridGroups.size())); ++ ++ Connect(); ++ std::vector groups = GetGroupDetails(groups_capture_); ++ for (auto group : groups) { ++ EXPECT_NE(group, ssl_grp_kem_mlkem768x25519); ++ EXPECT_NE(group, ssl_grp_kem_mlkem768secp256r1); ++ } ++} ++ ++TEST_P(TlsKeyExchangeTest13, Tls12ServerMlkem768x25519NotSupported) { ++ if (variant_ == ssl_variant_datagram) { ++ /* Bug 1874451 - reenable this test */ ++ return; ++ } ++ ++ EnsureKeyShareSetup(); ++ ++ client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, ++ SSL_LIBRARY_VERSION_TLS_1_3); ++ server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, ++ SSL_LIBRARY_VERSION_TLS_1_2); ++ ++ client_->DisableAllCiphers(); ++ client_->EnableCiphersByKeyExchange(ssl_kea_ecdh); ++ client_->EnableCiphersByKeyExchange(ssl_kea_ecdh_hybrid); ++ client_->ConfigNamedGroups( ++ {ssl_grp_kem_mlkem768x25519, ssl_grp_ec_curve25519}); ++ EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); ++ ++ server_->EnableCiphersByKeyExchange(ssl_kea_ecdh); ++ server_->EnableCiphersByKeyExchange(ssl_kea_ecdh_hybrid); ++ server_->ConfigNamedGroups( ++ {ssl_grp_kem_mlkem768x25519, ssl_grp_ec_curve25519}); ++ ++ Connect(); ++ CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, ++ ssl_sig_rsa_pss_rsae_sha256); ++} ++ ++TEST_P(TlsKeyExchangeTest13, Tls12ServerMlkem768Secp256r1NotSupported) { ++ if (variant_ == ssl_variant_datagram) { ++ /* Bug 1874451 - reenable this test */ ++ return; ++ } ++ ++ EnsureKeyShareSetup(); ++ ++ client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, ++ SSL_LIBRARY_VERSION_TLS_1_3); ++ server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, ++ SSL_LIBRARY_VERSION_TLS_1_2); ++ ++ client_->DisableAllCiphers(); ++ client_->EnableCiphersByKeyExchange(ssl_kea_ecdh); ++ client_->EnableCiphersByKeyExchange(ssl_kea_ecdh_hybrid); ++ client_->ConfigNamedGroups( ++ {ssl_grp_kem_mlkem768secp256r1, ssl_grp_ec_secp256r1}); ++ EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); ++ ++ server_->EnableCiphersByKeyExchange(ssl_kea_ecdh); ++ server_->EnableCiphersByKeyExchange(ssl_kea_ecdh_hybrid); ++ server_->ConfigNamedGroups( ++ {ssl_grp_kem_mlkem768secp256r1, ssl_grp_ec_secp256r1}); ++ ++ Connect(); ++ CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign, ++ ssl_sig_rsa_pss_rsae_sha256); ++} ++ ++TEST_P(TlsKeyExchangeTest13, Mlkem768x25519ClientDisabledByPolicy) { ++ EnsureKeyShareSetup(); ++ client_->SetPolicy(SEC_OID_MLKEM768X25519, 0, NSS_USE_ALG_IN_SSL_KX); ++ ConfigNamedGroups({ssl_grp_kem_mlkem768x25519, ssl_grp_ec_secp256r1}); ++ ++ Connect(); ++ CheckKEXDetails({ssl_grp_ec_secp256r1}, {ssl_grp_ec_secp256r1}); ++} ++ ++TEST_P(TlsKeyExchangeTest13, Mlkem768x25519ServerDisabledByPolicy) { ++ EnsureKeyShareSetup(); ++ server_->SetPolicy(SEC_OID_MLKEM768X25519, 0, NSS_USE_ALG_IN_SSL_KX); ++ ConfigNamedGroups({ssl_grp_kem_mlkem768x25519, ssl_grp_ec_secp256r1}); ++ ++ Connect(); ++ CheckKEXDetails({ssl_grp_kem_mlkem768x25519, ssl_grp_ec_secp256r1}, ++ {ssl_grp_kem_mlkem768x25519}, ssl_grp_ec_secp256r1); ++} ++ ++TEST_P(TlsKeyExchangeTest13, Mlkem768Secp256r1ClientDisabledByPolicy) { ++ EnsureKeyShareSetup(); ++ client_->SetPolicy(SEC_OID_MLKEM768SECP256R1, 0, NSS_USE_ALG_IN_SSL_KX); ++ ConfigNamedGroups({ssl_grp_kem_mlkem768secp256r1, ssl_grp_ec_secp256r1}); ++ ++ Connect(); ++ CheckKEXDetails({ssl_grp_ec_secp256r1}, {ssl_grp_ec_secp256r1}); ++} ++ ++TEST_P(TlsKeyExchangeTest13, Mlkem768Secp256r1ServerDisabledByPolicy) { ++ if (variant_ == ssl_variant_datagram) { ++ /* Bug 1874451 - reenable this test */ ++ return; ++ } ++ EnsureKeyShareSetup(); ++ server_->SetPolicy(SEC_OID_MLKEM768SECP256R1, 0, NSS_USE_ALG_IN_SSL_KX); ++ ConfigNamedGroups({ssl_grp_kem_mlkem768secp256r1, ssl_grp_ec_secp256r1}); ++ ++ Connect(); ++ CheckKEXDetails({ssl_grp_kem_mlkem768secp256r1, ssl_grp_ec_secp256r1}, ++ {ssl_grp_kem_mlkem768secp256r1}, ssl_grp_ec_secp256r1); ++} ++ ++static void CheckECDHShareReuse( ++ const std::shared_ptr& capture) { ++ EXPECT_TRUE(capture->captured()); ++ const DataBuffer& ext = capture->extension(); ++ DataBuffer hybrid_share[4]; ++ DataBuffer ecdh_share[4]; ++ int hybrid_offset[4]; ++ SSLNamedGroup hybrid_ec_type[4]; ++ SSLNamedGroup ec_type[4]; ++ int ecdh_index[4]; ++ int nextHybrid = 0; ++ int nextECDH = 0; ++ ++ size_t offset = 0; ++ uint32_t ext_len; ++ ext.Read(0, 2, &ext_len); ++ EXPECT_EQ(ext.len() - 2, ext_len); ++ offset += 2; ++ ++ uint32_t named_group; ++ uint32_t named_group_len; ++ ext.Read(offset, 2, &named_group); ++ ext.Read(offset + 2, 2, &named_group_len); ++ while (offset < ext.len()) { ++ switch (named_group) { ++ case ssl_grp_kem_mlkem768x25519: ++ hybrid_share[nextHybrid] = DataBuffer(ext.data() + offset + 2 + 2, named_group_len); ++ hybrid_offset[nextHybrid] = KYBER768_PUBLIC_KEY_BYTES; ++ hybrid_ec_type[nextHybrid] = ssl_grp_ec_curve25519; ++ nextHybrid++; ++ break; ++ case ssl_grp_kem_mlkem768secp256r1: ++ hybrid_share[nextHybrid] = DataBuffer(ext.data() + offset + 2 + 2, named_group_len); ++ hybrid_offset[nextHybrid] = 0; ++ hybrid_ec_type[nextHybrid] = ssl_grp_ec_secp256r1; ++ nextHybrid++; ++ case ssl_grp_ec_curve25519: ++ case ssl_grp_ec_secp256r1: ++ ecdh_share[nextECDH] = DataBuffer(ext.data() + offset + 2 + 2, named_group_len); ++ ec_type[nextECDH] = (SSLNamedGroup) named_group; ++ nextECDH++; ++ } ++ offset += 2 + 2 + named_group_len; ++ ext.Read(offset, 2, &named_group); ++ ext.Read(offset + 2, 2, &named_group_len); ++ } ++ EXPECT_EQ(offset, ext.len()); ++ ++ ASSERT_TRUE(nextECDH > 0); ++ ASSERT_TRUE(nextHybrid > 0); ++ /* setup the hybrid ecdh indeces */ ++ for (int i=0; i < nextHybrid; i++) { ++ ecdh_index[i] = -1; ++ for (int j=0; j < nextECDH; j++) { ++ if (hybrid_ec_type[i] == ec_type[j]) { ++ ecdh_index[i] = j; ++ break; ++ } ++ } ++ ASSERT_TRUE(ecdh_index[i] != -1); ++ } ++ for (int i=0; i < nextECDH; i++) { ++ ASSERT_TRUE(ecdh_share[i].data()); ++ } ++ for (int i=0; i < nextHybrid; i++) { ++ int j = ecdh_index[i]; ++ ASSERT_TRUE(hybrid_share[i].data()); ++ ASSERT_GT(hybrid_share[i].len(), ecdh_share[j].len()); ++ EXPECT_EQ(0, memcmp(hybrid_share[i].data() + hybrid_offset[i], ++ ecdh_share[j].data(), ecdh_share[j].len())); ++ } ++} ++ ++TEST_P(TlsKeyExchangeTest13, Mlkem768x25519ShareReuseFirst) { ++ if (variant_ == ssl_variant_datagram) { ++ /* Bug 1874451 - reenable this test */ ++ return; ++ } ++ EnsureKeyShareSetup(); ++ ConfigNamedGroups({ssl_grp_kem_mlkem768x25519, ssl_grp_ec_curve25519}); ++ EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); ++ ++ Connect(); ++ ++ CheckKEXDetails({ssl_grp_kem_mlkem768x25519, ssl_grp_ec_curve25519}, ++ {ssl_grp_kem_mlkem768x25519, ssl_grp_ec_curve25519}); ++ CheckECDHShareReuse(shares_capture_); ++} ++ ++TEST_P(TlsKeyExchangeTest13, Mlkem768x25519ShareReuseSecond) { ++ if (variant_ == ssl_variant_datagram) { ++ /* Bug 1874451 - reenable this test */ ++ return; ++ } ++ EnsureKeyShareSetup(); ++ ConfigNamedGroups({ssl_grp_ec_curve25519, ssl_grp_kem_mlkem768x25519}); ++ EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); ++ ++ Connect(); ++ ++ CheckKEXDetails({ssl_grp_ec_curve25519, ssl_grp_kem_mlkem768x25519}, ++ {ssl_grp_ec_curve25519, ssl_grp_kem_mlkem768x25519}); ++ CheckECDHShareReuse(shares_capture_); ++} ++ ++TEST_P(TlsKeyExchangeTest13, Mlkem768Secp256r1ShareReuseFirst) { ++ if (variant_ == ssl_variant_datagram) { ++ /* Bug 1874451 - reenable this test */ ++ return; ++ } ++ EnsureKeyShareSetup(); ++ ConfigNamedGroups({ssl_grp_kem_mlkem768secp256r1, ssl_grp_ec_secp256r1}); ++ EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); ++ ++ Connect(); ++ ++ CheckKEXDetails({ssl_grp_kem_mlkem768secp256r1, ssl_grp_ec_secp256r1}, ++ {ssl_grp_kem_mlkem768secp256r1, ssl_grp_ec_secp256r1}); ++ CheckECDHShareReuse(shares_capture_); ++} ++ ++TEST_P(TlsKeyExchangeTest13, Mlkem768Secp256r1ShareReuseSecond) { ++ if (variant_ == ssl_variant_datagram) { ++ /* Bug 1874451 - reenable this test */ ++ return; ++ } ++ EnsureKeyShareSetup(); ++ ConfigNamedGroups({ssl_grp_ec_secp256r1, ssl_grp_kem_mlkem768secp256r1}); ++ EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); ++ ++ Connect(); ++ ++ CheckKEXDetails({ssl_grp_ec_secp256r1, ssl_grp_kem_mlkem768secp256r1}, ++ {ssl_grp_ec_secp256r1, ssl_grp_kem_mlkem768secp256r1}); ++ CheckECDHShareReuse(shares_capture_); ++} ++ ++class Mlkem768x25519ShareDamager : public TlsExtensionFilter { ++ public: ++ typedef enum { ++ downgrade, ++ extend, ++ truncate, ++ zero_ecdh, ++ modify_ecdh, ++ modify_mlkem, ++ modify_mlkem_pubkey_mod_q, ++ } damage_type; ++ ++ Mlkem768x25519ShareDamager(const std::shared_ptr& a, ++ damage_type damage) ++ : TlsExtensionFilter(a), damage_(damage) {} ++ ++ virtual PacketFilter::Action FilterExtension(uint16_t extension_type, ++ const DataBuffer& input, ++ DataBuffer* output) { ++ if (extension_type != ssl_tls13_key_share_xtn) { ++ return KEEP; ++ } ++ ++ // Find the Mlkem768x25519 share ++ size_t offset = 0; ++ if (agent()->role() == TlsAgent::CLIENT) { ++ offset += 2; // skip KeyShareClientHello length ++ } ++ ++ uint32_t named_group; ++ uint32_t named_group_len; ++ input.Read(offset, 2, &named_group); ++ input.Read(offset + 2, 2, &named_group_len); ++ while (named_group != ssl_grp_kem_mlkem768x25519) { ++ offset += 2 + 2 + named_group_len; ++ input.Read(offset, 2, &named_group); ++ input.Read(offset + 2, 2, &named_group_len); ++ } ++ EXPECT_EQ(named_group, ssl_grp_kem_mlkem768x25519); ++ ++ DataBuffer hybrid_key_share(input.data() + offset, 2 + 2 + named_group_len); ++ ++ // Damage the Mlkem768x25519 share ++ uint32_t mlkem_component_len = ++ hybrid_key_share.len() - 2 - 2 - X25519_PUBLIC_KEY_BYTES; ++ unsigned char* ecdh_component = ++ hybrid_key_share.data() + 2 + 2 + mlkem_component_len; ++ unsigned char* mlkem_component = hybrid_key_share.data() + 2 + 2; ++ switch (damage_) { ++ case Mlkem768x25519ShareDamager::downgrade: ++ // Downgrade a Mlkem768x25519 share to X25519 ++ memcpy(mlkem_component, ecdh_component, X25519_PUBLIC_KEY_BYTES); ++ hybrid_key_share.Truncate(2 + 2 + X25519_PUBLIC_KEY_BYTES); ++ hybrid_key_share.Write(0, ssl_grp_ec_curve25519, 2); ++ hybrid_key_share.Write(2, X25519_PUBLIC_KEY_BYTES, 2); ++ break; ++ case Mlkem768x25519ShareDamager::truncate: ++ // Truncate a Mlkem768x25519 share before the X25519 component ++ hybrid_key_share.Truncate(2 + 2 + mlkem_component_len); ++ hybrid_key_share.Write(2, mlkem_component_len, 2); ++ break; ++ case Mlkem768x25519ShareDamager::extend: ++ // Append 4 bytes to a Mlkem768x25519 share ++ uint32_t current_len; ++ hybrid_key_share.Read(2, 2, ¤t_len); ++ hybrid_key_share.Write(hybrid_key_share.len(), current_len, 4); ++ hybrid_key_share.Write(2, current_len + 4, 2); ++ break; ++ case Mlkem768x25519ShareDamager::zero_ecdh: ++ // Replace an X25519 component with 0s ++ memset(ecdh_component, 0, X25519_PUBLIC_KEY_BYTES); ++ break; ++ case Mlkem768x25519ShareDamager::modify_ecdh: ++ // Flip a bit in the X25519 component ++ ecdh_component[0] ^= 0x01; ++ break; ++ case Mlkem768x25519ShareDamager::modify_mlkem: ++ // Flip a bit in the mlkem component ++ mlkem_component[0] ^= 0x01; ++ break; ++ case Mlkem768x25519ShareDamager::modify_mlkem_pubkey_mod_q: ++ if (agent()->role() == TlsAgent::CLIENT) { ++ // Replace the client's public key with an sequence of 12-bit values ++ // in the same equivalence class mod 3329. The FIPS-203 input ++ // validation check should fail. ++ for (size_t i = 0; i < mlkem_component_len - 32; i += 3) { ++ // Pairs of 12-bit coefficients are packed into 3 bytes. ++ // Unpack them, change equivalence class if possible, and repack. ++ uint16_t coeff0 = ++ mlkem_component[i] | ((mlkem_component[i + 1] & 0x0f) << 8); ++ uint16_t coeff1 = (mlkem_component[i + 1] & 0xf0 >> 4) | ++ ((mlkem_component[i + 2]) << 4); ++ if (coeff0 < 4096 - 3329) { ++ coeff0 += 3329; ++ } ++ if (coeff1 < 4096 - 3329) { ++ coeff1 += 3329; ++ } ++ mlkem_component[i] = coeff0; ++ mlkem_component[i + 1] = (coeff0 >> 8) + ((coeff1 & 0x0f) << 4); ++ mlkem_component[i + 2] = coeff1 >> 4; ++ } ++ } ++ break; ++ } ++ ++ *output = input; ++ output->Splice(hybrid_key_share, offset, 2 + 2 + named_group_len); ++ ++ // Fix the KeyShareClientHello length if necessary ++ if (agent()->role() == TlsAgent::CLIENT && ++ hybrid_key_share.len() != 2 + 2 + named_group_len) { ++ output->Write(0, output->len() - 2, 2); ++ } ++ ++ return CHANGE; ++ } ++ ++ private: ++ damage_type damage_; ++}; ++ ++class TlsMlkem768x25519DamageTest ++ : public TlsConnectTestBase, ++ public ::testing::WithParamInterface< ++ Mlkem768x25519ShareDamager::damage_type> { ++ public: ++ TlsMlkem768x25519DamageTest() ++ : TlsConnectTestBase(ssl_variant_stream, SSL_LIBRARY_VERSION_TLS_1_3) {} ++ ++ protected: ++ void Damage(const std::shared_ptr& agent) { ++ EnsureTlsSetup(); ++ client_->ConfigNamedGroups( ++ {ssl_grp_ec_curve25519, ssl_grp_kem_mlkem768x25519}); ++ server_->ConfigNamedGroups( ++ {ssl_grp_kem_mlkem768x25519, ssl_grp_ec_curve25519}); ++ EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); ++ MakeTlsFilter(agent, GetParam()); ++ } ++}; ++ ++TEST_P(TlsMlkem768x25519DamageTest, DamageClientShare) { ++ Damage(client_); ++ ++ switch (GetParam()) { ++ case Mlkem768x25519ShareDamager::extend: ++ case Mlkem768x25519ShareDamager::truncate: ++ ConnectExpectAlert(server_, kTlsAlertIllegalParameter); ++ server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE); ++ break; ++ case Mlkem768x25519ShareDamager::zero_ecdh: ++ ConnectExpectAlert(server_, kTlsAlertIllegalParameter); ++ server_->CheckErrorCode(SEC_ERROR_INVALID_KEY); ++ break; ++ case Mlkem768x25519ShareDamager::modify_mlkem_pubkey_mod_q: ++ ConnectExpectAlert(server_, kTlsAlertIllegalParameter); ++ server_->CheckErrorCode(SEC_ERROR_INVALID_ARGS); ++ break; ++ case Mlkem768x25519ShareDamager::downgrade: ++ case Mlkem768x25519ShareDamager::modify_ecdh: ++ case Mlkem768x25519ShareDamager::modify_mlkem: ++ client_->ExpectSendAlert(kTlsAlertBadRecordMac); ++ server_->ExpectSendAlert(kTlsAlertBadRecordMac); ++ ConnectExpectFail(); ++ client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); ++ server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); ++ break; ++ } ++} ++ ++TEST_P(TlsMlkem768x25519DamageTest, DamageServerShare) { ++ Damage(server_); ++ ++ switch (GetParam()) { ++ case Mlkem768x25519ShareDamager::extend: ++ case Mlkem768x25519ShareDamager::truncate: ++ client_->ExpectSendAlert(kTlsAlertIllegalParameter); ++ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ++ ConnectExpectFail(); ++ client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE); ++ break; ++ case Mlkem768x25519ShareDamager::zero_ecdh: ++ client_->ExpectSendAlert(kTlsAlertIllegalParameter); ++ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ++ ConnectExpectFail(); ++ client_->CheckErrorCode(SEC_ERROR_INVALID_KEY); ++ break; ++ case Mlkem768x25519ShareDamager::downgrade: ++ case Mlkem768x25519ShareDamager::modify_ecdh: ++ case Mlkem768x25519ShareDamager::modify_mlkem: ++ client_->ExpectSendAlert(kTlsAlertBadRecordMac); ++ server_->ExpectSendAlert(kTlsAlertBadRecordMac); ++ ConnectExpectFail(); ++ client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); ++ server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); ++ break; ++ case Mlkem768x25519ShareDamager::modify_mlkem_pubkey_mod_q: ++ // The server doesn't send a public key, so nothing is changed. ++ break; ++ } ++} ++ ++INSTANTIATE_TEST_SUITE_P( ++ TlsMlkem768x25519DamageTest, TlsMlkem768x25519DamageTest, ++ ::testing::Values(Mlkem768x25519ShareDamager::downgrade, ++ Mlkem768x25519ShareDamager::extend, ++ Mlkem768x25519ShareDamager::truncate, ++ Mlkem768x25519ShareDamager::zero_ecdh, ++ Mlkem768x25519ShareDamager::modify_ecdh, ++ Mlkem768x25519ShareDamager::modify_mlkem, ++ Mlkem768x25519ShareDamager::modify_mlkem_pubkey_mod_q)); ++ ++} // namespace nss_test +diff -up ./gtests/ssl_gtest/tls_psk_unittest.cc.mlkem ./gtests/ssl_gtest/tls_psk_unittest.cc +--- ./gtests/ssl_gtest/tls_psk_unittest.cc.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/tls_psk_unittest.cc 2024-10-31 14:54:15.462515926 -0700 +@@ -68,7 +68,7 @@ TEST_P(Tls13PskTest, NormalExternal) { + AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); + Connect(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); ++ CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_mlkem768x25519, ssl_auth_psk, ssl_sig_none); + client_->RemovePsk(kPskDummyLabel_); + server_->RemovePsk(kPskDummyLabel_); + +@@ -91,7 +91,7 @@ TEST_P(Tls13PskTest, KeyTooLarge) { + AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); + Connect(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); ++ CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_mlkem768x25519, ssl_auth_psk, ssl_sig_none); + } + + // Attempt to use a PSK with the wrong PRF hash. +@@ -117,7 +117,7 @@ TEST_P(Tls13PskTest, LabelMismatch) { + client_->AddPsk(scoped_psk_, std::string("foo"), kPskHash_); + server_->AddPsk(scoped_psk_, std::string("bar"), kPskHash_); + Connect(); +- CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); ++ CheckKeys(); + } + + SSLHelloRetryRequestAction RetryFirstHello( +@@ -148,7 +148,7 @@ TEST_P(Tls13PskTest, ResPskRetryStateles + Handshake(); + CheckConnected(); + EXPECT_EQ(2U, cb_called); +- CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); ++ CheckKeys(); + SendReceive(); + } + +@@ -174,7 +174,7 @@ TEST_P(Tls13PskTest, ExtPskRetryStateles + Handshake(); + CheckConnected(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); ++ CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_mlkem768x25519, ssl_auth_psk, ssl_sig_none); + } + + // Server not configured with PSK and sends a certificate instead of +@@ -182,7 +182,7 @@ TEST_P(Tls13PskTest, ExtPskRetryStateles + TEST_P(Tls13PskTest, ClientOnly) { + client_->AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); + Connect(); +- CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); ++ CheckKeys(); + } + + // Set a PSK, remove psk_key_exchange_modes. +@@ -247,7 +247,7 @@ TEST_P(Tls13PskTest, PreferEpsk) { + Handshake(); + CheckConnected(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); ++ CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_mlkem768x25519, ssl_auth_psk, ssl_sig_none); + } + + // Enable resumption, but connect (initially) with an EPSK. +@@ -260,7 +260,7 @@ TEST_P(Tls13PskTest, SuppressNewSessionT + nst_capture->EnableDecryption(); + Connect(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); ++ CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_mlkem768x25519, ssl_auth_psk, ssl_sig_none); + EXPECT_EQ(SECFailure, SSL_SendSessionTicket(server_->ssl_fd(), nullptr, 0)); + EXPECT_EQ(0U, nst_capture->buffer().len()); + if (variant_ == ssl_variant_stream) { +@@ -275,7 +275,7 @@ TEST_P(Tls13PskTest, SuppressNewSessionT + ExpectResumption(RESUME_NONE); + Connect(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); ++ CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_mlkem768x25519, ssl_auth_psk, ssl_sig_none); + } + + TEST_P(Tls13PskTest, BadConfigValues) { +@@ -314,7 +314,7 @@ TEST_P(Tls13PskTest, FallbackUnsupported + client_->EnableSingleCipher(TLS_AES_128_GCM_SHA256); + Connect(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); ++ CheckKeys(); + } + + // That fallback should not occur if there is no cipher overlap. +@@ -342,7 +342,7 @@ TEST_P(Tls13PskTest, SuppressHandshakeCe + + Connect(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); ++ CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_mlkem768x25519, ssl_auth_psk, ssl_sig_none); + EXPECT_EQ(0U, cr_cert_capture->buffer().len()); + } + +@@ -422,7 +422,7 @@ TEST_P(Tls13PskTestWithCiphers, 0RttCiph + ExpectEarlyDataAccepted(true); + CheckConnected(); + SendReceive(); +- CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); ++ CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_mlkem768x25519, ssl_auth_psk, ssl_sig_none); + } + + TEST_P(Tls13PskTestWithCiphers, 0RttMaxEarlyData) { +diff -up ./gtests/ssl_gtest/tls_subcerts_unittest.cc.mlkem ./gtests/ssl_gtest/tls_subcerts_unittest.cc +--- ./gtests/ssl_gtest/tls_subcerts_unittest.cc.mlkem 2024-10-31 14:54:15.441515691 -0700 ++++ ./gtests/ssl_gtest/tls_subcerts_unittest.cc 2024-10-31 14:54:15.462515926 -0700 +@@ -448,6 +448,7 @@ class ReplaceDCSigScheme : public TlsHan + // Aborted because of incorrect DC signature algorithm indication. + TEST_P(TlsConnectTls13, DCAbortBadExpectedCertVerifyAlg) { + Reset(kEcdsaDelegatorId); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + client_->EnableDelegatedCredentials(); + server_->AddDelegatedCredential(TlsAgent::kServerEcdsa256, + ssl_sig_ecdsa_secp256r1_sha256, kDCValidFor, +@@ -568,6 +569,7 @@ TEST_P(TlsConnectTls13, DCConnectClientN + // Connected without DC because server doesn't support TLS 1.3. + TEST_P(TlsConnectTls13, DCConnectServerNoTls13) { + Reset(kEcdsaDelegatorId); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + client_->EnableDelegatedCredentials(); + server_->AddDelegatedCredential(kDCId, kDCScheme, kDCValidFor, now()); + +@@ -612,6 +614,7 @@ TEST_P(TlsConnectTls13, DCConnectExpecte + TEST_P(TlsConnectTls13, DCCheckPreliminaryInfo) { + Reset(kEcdsaDelegatorId); + EnsureTlsSetup(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + client_->EnableDelegatedCredentials(); + server_->AddDelegatedCredential(TlsAgent::kServerEcdsa256, + ssl_sig_ecdsa_secp256r1_sha256, kDCValidFor, +@@ -637,6 +640,7 @@ TEST_P(TlsConnectTls13, DCCheckPrelimina + TEST_P(TlsConnectTls13, DCCheckPreliminaryInfoNoDC) { + Reset(kEcdsaDelegatorId); + EnsureTlsSetup(); ++ client_->ConfigNamedGroups(kNonPQDHEGroups); + client_->EnableDelegatedCredentials(); + auto filter = MakeTlsFilter(server_); + filter->SetHandshakeTypes( +diff -up ./lib/freebl/kyber.c.mlkem ./lib/freebl/kyber.c +--- ./lib/freebl/kyber.c.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/freebl/kyber.c 2024-10-31 14:54:15.462515926 -0700 +@@ -14,6 +14,9 @@ + + #include "kyber-pqcrystals-ref.h" + #include "kyber.h" ++#include "verified/internal/libcrux_core.h" ++#include "verified/libcrux_mlkem768_portable.h" ++#include "verified/libcrux_mlkem768.h" + + /* Consistency check between kyber-pqcrystals-ref.h and kyber.h */ + PR_STATIC_ASSERT(KYBER768_PUBLIC_KEY_BYTES == pqcrystals_kyber768_PUBLICKEYBYTES); +@@ -23,12 +26,22 @@ PR_STATIC_ASSERT(KYBER_SHARED_SECRET_BYT + PR_STATIC_ASSERT(KYBER_KEYPAIR_COIN_BYTES == pqcrystals_kyber768_KEYPAIRCOINBYTES); + PR_STATIC_ASSERT(KYBER_ENC_COIN_BYTES == pqcrystals_kyber768_ENCCOINBYTES); + ++/* Consistency check between libcrux_mlkem768_portable.h and kyber.h */ ++PR_STATIC_ASSERT(KYBER768_PUBLIC_KEY_BYTES == LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_PUBLIC_KEY_SIZE_768); ++PR_STATIC_ASSERT(KYBER768_PRIVATE_KEY_BYTES == LIBCRUX_ML_KEM_MLKEM768_SECRET_KEY_SIZE_768); ++PR_STATIC_ASSERT(KYBER768_CIPHERTEXT_BYTES == LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_CIPHERTEXT_SIZE_768); ++PR_STATIC_ASSERT(KYBER_SHARED_SECRET_BYTES == LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE); ++PR_STATIC_ASSERT(KYBER_KEYPAIR_COIN_BYTES == 64); ++PR_STATIC_ASSERT(KYBER_ENC_COIN_BYTES == 32); ++ + static bool + valid_params(KyberParams params) + { + switch (params) { + case params_kyber768_round3: + case params_kyber768_round3_test_mode: ++ case params_ml_kem768: ++ case params_ml_kem768_test_mode: + return true; + default: + return false; +@@ -41,6 +54,8 @@ valid_pubkey(KyberParams params, const S + switch (params) { + case params_kyber768_round3: + case params_kyber768_round3_test_mode: ++ case params_ml_kem768: ++ case params_ml_kem768_test_mode: + return pubkey && pubkey->len == KYBER768_PUBLIC_KEY_BYTES; + default: + return false; +@@ -53,6 +68,8 @@ valid_privkey(KyberParams params, const + switch (params) { + case params_kyber768_round3: + case params_kyber768_round3_test_mode: ++ case params_ml_kem768: ++ case params_ml_kem768_test_mode: + return privkey && privkey->len == KYBER768_PRIVATE_KEY_BYTES; + default: + return false; +@@ -65,6 +82,8 @@ valid_ciphertext(KyberParams params, con + switch (params) { + case params_kyber768_round3: + case params_kyber768_round3_test_mode: ++ case params_ml_kem768: ++ case params_ml_kem768_test_mode: + return ciphertext && ciphertext->len == KYBER768_CIPHERTEXT_BYTES; + default: + return false; +@@ -77,6 +96,8 @@ valid_secret(KyberParams params, const S + switch (params) { + case params_kyber768_round3: + case params_kyber768_round3_test_mode: ++ case params_ml_kem768: ++ case params_ml_kem768_test_mode: + return secret && secret->len == KYBER_SHARED_SECRET_BYTES; + default: + return false; +@@ -89,6 +110,8 @@ valid_keypair_seed(KyberParams params, c + switch (params) { + case params_kyber768_round3: + case params_kyber768_round3_test_mode: ++ case params_ml_kem768: ++ case params_ml_kem768_test_mode: + return !seed || seed->len == KYBER_KEYPAIR_COIN_BYTES; + default: + return false; +@@ -100,8 +123,10 @@ valid_enc_seed(KyberParams params, const + { + switch (params) { + case params_kyber768_round3: ++ case params_ml_kem768: + return !seed; + case params_kyber768_round3_test_mode: ++ case params_ml_kem768_test_mode: + return !seed || seed->len == KYBER_SHARED_SECRET_BYTES; + default: + return false; +@@ -135,6 +160,10 @@ Kyber_NewKey(KyberParams params, const S + NSS_CLASSIFY(coins, KYBER_KEYPAIR_COIN_BYTES); + if (params == params_kyber768_round3 || params == params_kyber768_round3_test_mode) { + pqcrystals_kyber768_ref_keypair_derand(pubkey->data, privkey->data, coins); ++ } else if (params == params_ml_kem768 || params == params_ml_kem768_test_mode) { ++ libcrux_ml_kem_mlkem768_MlKem768KeyPair keys = libcrux_ml_kem_mlkem768_portable_generate_key_pair(coins); ++ memcpy(pubkey->data, keys.pk.value, KYBER768_PUBLIC_KEY_BYTES); ++ memcpy(privkey->data, keys.sk.value, KYBER768_PRIVATE_KEY_BYTES); + } else { + /* unreachable */ + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); +@@ -171,6 +200,19 @@ Kyber_Encapsulate(KyberParams params, co + NSS_CLASSIFY(coins, KYBER_ENC_COIN_BYTES); + if (params == params_kyber768_round3 || params == params_kyber768_round3_test_mode) { + pqcrystals_kyber768_ref_enc_derand(ciphertext->data, secret->data, pubkey->data, coins); ++ } else if (params == params_ml_kem768 || params == params_ml_kem768_test_mode) { ++ libcrux_ml_kem_types_MlKemPublicKey_15 pk_value; ++ memcpy(pk_value.value, pubkey->data, KYBER768_PUBLIC_KEY_BYTES); ++ ++ bool valid_pk = libcrux_ml_kem_mlkem768_portable_validate_public_key(&pk_value); ++ if (!valid_pk) { ++ PORT_SetError(SEC_ERROR_INVALID_ARGS); ++ return SECFailure; ++ } ++ ++ tuple_3c encap = libcrux_ml_kem_mlkem768_portable_encapsulate(&pk_value, coins); ++ memcpy(ciphertext->data, encap.fst.value, KYBER768_CIPHERTEXT_BYTES); ++ memcpy(secret->data, encap.snd, KYBER_SHARED_SECRET_BYTES); + } else { + /* unreachable */ + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); +@@ -195,6 +237,20 @@ Kyber_Decapsulate(KyberParams params, co + + if (params == params_kyber768_round3 || params == params_kyber768_round3_test_mode) { + pqcrystals_kyber768_ref_dec(secret->data, ciphertext->data, privkey->data); ++ } else if (params == params_ml_kem768 || params == params_ml_kem768_test_mode) { ++ libcrux_ml_kem_types_MlKemPrivateKey_55 private_key; ++ memcpy(private_key.value, privkey->data, KYBER768_PRIVATE_KEY_BYTES); ++ ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext cipher_text; ++ memcpy(cipher_text.value, ciphertext->data, KYBER768_CIPHERTEXT_BYTES); ++ ++ bool valid = libcrux_ml_kem_mlkem768_portable_validate_private_key(&private_key, &cipher_text); ++ if (!valid) { ++ PORT_SetError(SEC_ERROR_INVALID_ARGS); ++ return SECFailure; ++ } ++ ++ libcrux_ml_kem_mlkem768_portable_decapsulate(&private_key, &cipher_text, secret->data); + } else { + // unreachable + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); +diff -up ./lib/freebl/Makefile.mlkem ./lib/freebl/Makefile +--- ./lib/freebl/Makefile.mlkem 2024-10-31 14:54:15.437515647 -0700 ++++ ./lib/freebl/Makefile 2024-10-31 14:54:15.462515926 -0700 +@@ -610,6 +610,14 @@ endif # NSS_DISABLE_CHACHAPOLY + VERIFIED_SRCS += Hacl_Hash_SHA3.c Hacl_P256.c Hacl_P384.c Hacl_P521.c + VERIFIED_SRCS += Hacl_Ed25519.c + VERIFIED_SRCS += Hacl_Curve25519_51.c ++VERIFIED_SRCS += libcrux_mlkem768_portable.c libcrux_mlkem_portable.c libcrux_core.c ++ ++# Bug 1918767 / Bug 1918711 - by setting KRML_MUSTINLINE=inline here, we ++# avoid it being defined to `inline __forceinline` (for msvc) or `inline ++# __attribute__((always_inline))` (for gcc/clang) in ++# verified/karamel/include/krml/internal/target.h. These other ++# configurations can cause excessive stack usage. ++DEFINES += -DKRML_MUSTINLINE=inline + + ifeq (,$(filter-out x86_64 aarch64,$(CPU_ARCH))) + # All 64-bit architectures get the 64 bit version. +diff -up ./lib/freebl/verified/eurydice_glue.h.mlkem ./lib/freebl/verified/eurydice_glue.h +--- ./lib/freebl/verified/eurydice_glue.h.mlkem 2024-10-31 14:54:15.462515926 -0700 ++++ ./lib/freebl/verified/eurydice_glue.h 2024-10-31 14:54:15.462515926 -0700 +@@ -0,0 +1,385 @@ ++#pragma once ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++#include "krml/internal/target.h" ++#include "krml/lowstar_endianness.h" ++ ++#define LowStar_Ignore_ignore(e, t, _ret_t) ((void)e) ++ ++// SLICES, ARRAYS, ETC. ++ ++#if defined(__cplusplus) ++#define CLITERAL(type) type ++#else ++#define CLITERAL(type) (type) ++#endif ++ ++// We represent a slice as a pair of an (untyped) pointer, along with the length ++// of the slice, i.e. the number of elements in the slice (this is NOT the ++// number of bytes). This design choice has two important consequences. ++// - if you need to use `ptr`, you MUST cast it to a proper type *before* ++// performing pointer ++// arithmetic on it (remember that C desugars pointer arithmetic based on the ++// type of the address) ++// - if you need to use `len` for a C style function (e.g. memcpy, memcmp), you ++// need to multiply it ++// by sizeof t, where t is the type of the elements. ++typedef struct { ++ void *ptr; ++ size_t len; ++} Eurydice_slice; ++ ++// Helper macro to create a slice out of a pointer x, a start index in x ++// (included), and an end index in x (excluded). The argument x must be suitably ++// cast to something that can decay (see remark above about how pointer ++// arithmetic works in C), meaning either pointer or array type. ++#define EURYDICE_SLICE(x, start, end) \ ++ (CLITERAL(Eurydice_slice){ .ptr = (void *)(x + start), .len = end - start }) ++#define EURYDICE_SLICE_LEN(s, _) s.len ++// This macro is a pain because in case the dereferenced element type is an ++// array, you cannot simply write `t x` as it would yield `int[4] x` instead, ++// which is NOT correct C syntax, so we add a dedicated phase in Eurydice that ++// adds an extra argument to this macro at the last minute so that we have the ++// correct type of *pointers* to elements. ++#define Eurydice_slice_index(s, i, t, t_ptr_t) (((t_ptr_t)s.ptr)[i]) ++#define Eurydice_slice_subslice(s, r, t, _) \ ++ EURYDICE_SLICE((t *)s.ptr, r.start, r.end) ++// Variant for when the start and end indices are statically known (i.e., the ++// range argument `r` is a literal). ++#define Eurydice_slice_subslice2(s, start, end, t) \ ++ EURYDICE_SLICE((t *)s.ptr, start, end) ++#define Eurydice_slice_subslice_to(s, subslice_end_pos, t, _) \ ++ EURYDICE_SLICE((t *)s.ptr, 0, subslice_end_pos) ++#define Eurydice_slice_subslice_from(s, subslice_start_pos, t, _) \ ++ EURYDICE_SLICE((t *)s.ptr, subslice_start_pos, s.len) ++#define Eurydice_array_to_slice(end, x, t) \ ++ EURYDICE_SLICE(x, 0, \ ++ end) /* x is already at an array type, no need for cast */ ++#define Eurydice_array_to_subslice(_arraylen, x, r, t, _) \ ++ EURYDICE_SLICE((t *)x, r.start, r.end) ++// Same as above, variant for when start and end are statically known ++#define Eurydice_array_to_subslice2(x, start, end, t) \ ++ EURYDICE_SLICE((t *)x, start, end) ++#define Eurydice_array_to_subslice_to(_size, x, r, t, _range_t) \ ++ EURYDICE_SLICE((t *)x, 0, r) ++#define Eurydice_array_to_subslice_from(size, x, r, t, _range_t) \ ++ EURYDICE_SLICE((t *)x, r, size) ++#define Eurydice_array_repeat(dst, len, init, t) \ ++ ERROR "should've been desugared" ++#define Eurydice_slice_len(s, t) EURYDICE_SLICE_LEN(s, t) ++#define Eurydice_slice_copy(dst, src, t) \ ++ memcpy(dst.ptr, src.ptr, dst.len * sizeof(t)) ++#define core_array___Array_T__N__23__as_slice(len_, ptr_, t, _ret_t) \ ++ ((Eurydice_slice){ .ptr = ptr_, .len = len_ }) ++ ++#define core_array___core__clone__Clone_for__Array_T__N___20__clone( \ ++ len, src, dst, elem_type, _ret_t) \ ++ (memcpy(dst, src, len * sizeof(elem_type))) ++#define core_array_TryFromSliceError uint8_t ++ ++#define Eurydice_array_eq(sz, a1, a2, t, _) \ ++ (memcmp(a1, a2, sz * sizeof(t)) == 0) ++#define core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( \ ++ sz, a1, a2, t, _, _ret_t) \ ++ Eurydice_array_eq(sz, a1, a2, t, _) ++#define core_array_equality___core__cmp__PartialEq__0___Slice_U____for__Array_T__N___3__eq( \ ++ sz, a1, a2, t, _, _ret_t) \ ++ Eurydice_array_eq(sz, a1, ((a2)->ptr), t, _) ++ ++#define Eurydice_slice_split_at(slice, mid, element_type, ret_t) \ ++ (CLITERAL(ret_t){ \ ++ .fst = EURYDICE_SLICE((element_type *)slice.ptr, 0, mid), \ ++ .snd = EURYDICE_SLICE((element_type *)slice.ptr, mid, slice.len) }) ++#define Eurydice_slice_split_at_mut(slice, mid, element_type, ret_t) \ ++ (CLITERAL(ret_t){ \ ++ .fst = { .ptr = slice.ptr, .len = mid }, \ ++ .snd = { .ptr = (char *)slice.ptr + mid * sizeof(element_type), \ ++ .len = slice.len - mid } }) ++ ++// Conversion of slice to an array, rewritten (by Eurydice) to name the ++// destination array, since arrays are not values in C. ++// N.B.: see note in karamel/lib/Inlining.ml if you change this. ++#define Eurydice_slice_to_array2(dst, src, _, t_arr) \ ++ Eurydice_slice_to_array3(&(dst)->tag, (char *)&(dst)->val.case_Ok, src, \ ++ sizeof(t_arr)) ++ ++static inline void ++Eurydice_slice_to_array3(uint8_t *dst_tag, char *dst_ok, ++ Eurydice_slice src, size_t sz) ++{ ++ *dst_tag = 0; ++ memcpy(dst_ok, src.ptr, sz); ++} ++ ++// CORE STUFF (conversions, endianness, ...) ++ ++static inline void ++core_num__u32_8__to_be_bytes(uint32_t src, uint8_t dst[4]) ++{ ++ // TODO: why not store32_be? ++ uint32_t x = htobe32(src); ++ memcpy(dst, &x, 4); ++} ++ ++static inline uint32_t ++core_num__u32_8__from_le_bytes(uint8_t buf[4]) ++{ ++ return load32_le(buf); ++} ++ ++static inline void ++core_num__u64_9__to_le_bytes(uint64_t v, uint8_t buf[8]) ++{ ++ store64_le(buf, v); ++} ++static inline uint64_t ++core_num__u64_9__from_le_bytes(uint8_t buf[8]) ++{ ++ return load64_le(buf); ++} ++ ++static inline int64_t ++core_convert_num___core__convert__From_i32__for_i64__59__from(int32_t x) ++{ ++ return x; ++} ++ ++static inline uint64_t ++core_convert_num___core__convert__From_u8__for_u64__66__from(uint8_t x) ++{ ++ return x; ++} ++ ++static inline uint64_t ++core_convert_num___core__convert__From_u16__for_u64__70__from(uint16_t x) ++{ ++ return x; ++} ++ ++static inline size_t ++core_convert_num___core__convert__From_u16__for_usize__96__from(uint16_t x) ++{ ++ return x; ++} ++ ++static inline uint32_t ++core_num__u8_6__count_ones(uint8_t x0) ++{ ++#ifdef _MSC_VER ++ return __popcnt(x0); ++#else ++ return __builtin_popcount(x0); ++#endif ++} ++ ++// unsigned overflow wraparound semantics in C ++static inline uint16_t ++core_num__u16_7__wrapping_add(uint16_t x, uint16_t y) ++{ ++ return x + y; ++} ++static inline uint8_t ++core_num__u8_6__wrapping_sub(uint8_t x, uint8_t y) ++{ ++ return x - y; ++} ++ ++static inline void ++core_ops_arith__i32_319__add_assign(int32_t *x0, ++ int32_t *x1) ++{ ++ *x0 = *x0 + *x1; ++} ++ ++static inline uint8_t ++Eurydice_bitand_pv_u8(uint8_t *p, uint8_t v) ++{ ++ return (*p) & v; ++} ++static inline uint8_t ++Eurydice_shr_pv_u8(uint8_t *p, int32_t v) ++{ ++ return (*p) >> v; ++} ++ ++#define core_num_nonzero_private_NonZeroUsizeInner size_t ++static inline core_num_nonzero_private_NonZeroUsizeInner ++core_num_nonzero_private___core__clone__Clone_for_core__num__nonzero__private__NonZeroUsizeInner__26__clone( ++ core_num_nonzero_private_NonZeroUsizeInner *x0) ++{ ++ return *x0; ++} ++ ++// ITERATORS ++#define Eurydice_range_iter_next(iter_ptr, t, ret_t) \ ++ (((iter_ptr)->start == (iter_ptr)->end) \ ++ ? (CLITERAL(ret_t){ .tag = core_option_None }) \ ++ : (CLITERAL(ret_t){ .tag = core_option_Some, \ ++ .f0 = (iter_ptr)->start++ })) ++ ++// Old name (TODO: remove once everyone has upgraded to the latest Charon) ++#define core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___3__next \ ++ Eurydice_range_iter_next ++ ++#define core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next \ ++ Eurydice_range_iter_next ++ ++// See note in karamel/lib/Inlining.ml if you change this ++#define Eurydice_into_iter(x, t, _ret_t) (x) ++#define core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter \ ++ Eurydice_into_iter ++// This name changed on 20240627 ++#define core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter \ ++ Eurydice_into_iter ++ ++typedef struct { ++ Eurydice_slice slice; ++ size_t chunk_size; ++} Eurydice_chunks; ++ ++// Can't use macros Eurydice_slice_subslice_{to,from} because they require a ++// type, and this static inline function cannot receive a type as an argument. ++// Instead, we receive the element size and use it to peform manual offset ++// computations rather than going through the macros. ++static inline Eurydice_slice ++chunk_next(Eurydice_chunks *chunks, ++ size_t element_size) ++{ ++ size_t chunk_size = chunks->slice.len >= chunks->chunk_size ++ ? chunks->chunk_size ++ : chunks->slice.len; ++ Eurydice_slice curr_chunk; ++ curr_chunk.ptr = chunks->slice.ptr; ++ curr_chunk.len = chunk_size; ++ chunks->slice.ptr = (char *)(chunks->slice.ptr) + chunk_size * element_size; ++ chunks->slice.len = chunks->slice.len - chunk_size; ++ return curr_chunk; ++} ++ ++#define core_slice___Slice_T___chunks(slice_, sz_, t, _ret_t) \ ++ ((Eurydice_chunks){ .slice = slice_, .chunk_size = sz_ }) ++#define core_slice___Slice_T___chunks_exact(slice_, sz_, t, _ret_t) \ ++ ((Eurydice_chunks){ \ ++ .slice = { .ptr = slice_.ptr, .len = slice_.len - (slice_.len % sz_) }, \ ++ .chunk_size = sz_ }) ++#define core_slice_iter_Chunks Eurydice_chunks ++#define core_slice_iter_ChunksExact Eurydice_chunks ++#define Eurydice_chunks_next(iter, t, ret_t) \ ++ (((iter)->slice.len == 0) ? ((ret_t){ .tag = core_option_None }) \ ++ : ((ret_t){ .tag = core_option_Some, \ ++ .f0 = chunk_next(iter, sizeof(t)) })) ++#define core_slice_iter___core__iter__traits__iterator__Iterator_for_core__slice__iter__Chunks__a__T___70__next \ ++ Eurydice_chunks_next ++// This name changed on 20240627 ++#define core_slice_iter___core__iter__traits__iterator__Iterator_for_core__slice__iter__Chunks__a__T___71__next \ ++ Eurydice_chunks_next ++#define core_slice_iter__core__slice__iter__ChunksExact__a__T__89__next( \ ++ iter, t, _ret_t) \ ++ core_slice_iter__core__slice__iter__Chunks__a__T__70__next(iter, t) ++ ++typedef struct { ++ Eurydice_slice s; ++ size_t index; ++} Eurydice_slice_iterator; ++ ++#define core_slice___Slice_T___iter(x, t, _ret_t) \ ++ ((Eurydice_slice_iterator){ .s = x, .index = 0 }) ++#define core_slice_iter_Iter Eurydice_slice_iterator ++#define core_slice_iter__core__slice__iter__Iter__a__T__181__next(iter, t, \ ++ ret_t) \ ++ (((iter)->index == (iter)->s.len) \ ++ ? (CLITERAL(ret_t){ .tag = core_option_None }) \ ++ : (CLITERAL(ret_t){ \ ++ .tag = core_option_Some, \ ++ .f0 = ((iter)->index++, \ ++ &((t *)((iter)->s.ptr))[(iter)->index - 1]) })) ++ ++// STRINGS ++ ++typedef const char *Prims_string; ++ ++// MISC (UNTESTED) ++ ++typedef void *core_fmt_Formatter; ++typedef void *core_fmt_Arguments; ++typedef void *core_fmt_rt_Argument; ++#define core_fmt_rt__core__fmt__rt__Argument__a__1__new_display(x1, x2, x3, \ ++ x4) \ ++ NULL ++ ++// VECTORS (ANCIENT, POSSIBLY UNTESTED) ++ ++/* For now these are passed by value -- three words. We could conceivably change ++ * the representation to heap-allocate this struct and only pass around the ++ * pointer (one word). */ ++typedef struct { ++ void *ptr; ++ size_t len; /* the number of elements */ ++ size_t alloc_size; /* the size of the allocation, in number of BYTES */ ++} Eurydice_vec_s, *Eurydice_vec; ++ ++/* Here, we set everything to zero rather than use a non-standard GCC ++ * statement-expression -- this suitably initializes ptr to NULL and len and ++ * size to 0. */ ++#define EURYDICE_VEC_NEW(_) calloc(1, sizeof(Eurydice_vec_s)) ++#define EURYDICE_VEC_PUSH(v, x, t) \ ++ do { \ ++ /* Grow the vector if capacity has been reached. */ \ ++ if (v->len == v->alloc_size / sizeof(t)) { \ ++ /* Assuming that this does not exceed SIZE_MAX, because code proven \ ++ * correct by Aeneas. Would this even happen in practice? */ \ ++ size_t new_size; \ ++ if (v->alloc_size == 0) \ ++ new_size = 8 * sizeof(t); \ ++ else if (v->alloc_size <= SIZE_MAX / 2) \ ++ /* TODO: discuss growth policy */ \ ++ new_size = 2 * v->alloc_size; \ ++ else \ ++ new_size = (SIZE_MAX / sizeof(t)) * sizeof(t); \ ++ v->ptr = realloc(v->ptr, new_size); \ ++ v->alloc_size = new_size; \ ++ } \ ++ ((t *)v->ptr)[v->len] = x; \ ++ v->len++; \ ++ } while (0) ++ ++#define EURYDICE_VEC_DROP(v, t) \ ++ do { \ ++ free(v->ptr); \ ++ free(v); \ ++ } while (0) ++ ++#define EURYDICE_VEC_INDEX(v, i, t) &((t *)v->ptr)[i] ++#define EURYDICE_VEC_LEN(v, t) (v)->len ++ ++/* TODO: remove GCC-isms */ ++#define EURYDICE_BOX_NEW(x, t) \ ++ ({ \ ++ t *p = malloc(sizeof(t)); \ ++ *p = x; \ ++ p; \ ++ }) ++ ++#define EURYDICE_REPLACE(ptr, new_v, t) \ ++ ({ \ ++ t old_v = *ptr; \ ++ *ptr = new_v; \ ++ old_v; \ ++ }) ++ ++#if defined(__cplusplus) ++} ++#endif +diff -up ./lib/freebl/verified/internal/libcrux_core.h.mlkem ./lib/freebl/verified/internal/libcrux_core.h +--- ./lib/freebl/verified/internal/libcrux_core.h.mlkem 2024-10-31 14:54:15.462515926 -0700 ++++ ./lib/freebl/verified/internal/libcrux_core.h 2024-10-31 14:54:15.462515926 -0700 +@@ -0,0 +1,491 @@ ++/* ++ * SPDX-FileCopyrightText: 2024 Cryspen Sarl ++ * ++ * SPDX-License-Identifier: MIT or Apache-2.0 ++ * ++ * This code was generated with the following revisions: ++ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d ++ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46 ++ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0 ++ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7 ++ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb ++ */ ++ ++#ifndef __internal_libcrux_core_H ++#define __internal_libcrux_core_H ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++#include "../libcrux_core.h" ++#include "eurydice_glue.h" ++ ++#define CORE_NUM__U32_8__BITS (32U) ++ ++static inline uint32_t core_num__u8_6__count_ones(uint8_t x0); ++ ++#define LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE ((size_t)32U) ++ ++void libcrux_ml_kem_constant_time_ops_compare_ciphertexts_select_shared_secret_in_constant_time( ++ Eurydice_slice lhs_c, Eurydice_slice rhs_c, Eurydice_slice lhs_s, ++ Eurydice_slice rhs_s, uint8_t ret[32U]); ++ ++#define LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_COEFFICIENT ((size_t)12U) ++ ++#define LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT ((size_t)256U) ++ ++#define LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_RING_ELEMENT \ ++ (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * (size_t)12U) ++ ++#define LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT \ ++ (LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_RING_ELEMENT / (size_t)8U) ++ ++#define LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE ((size_t)32U) ++ ++#define LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE ((size_t)32U) ++ ++typedef struct libcrux_ml_kem_utils_extraction_helper_Keypair1024_s { ++ uint8_t fst[1536U]; ++ uint8_t snd[1568U]; ++} libcrux_ml_kem_utils_extraction_helper_Keypair1024; ++ ++typedef struct libcrux_ml_kem_utils_extraction_helper_Keypair512_s { ++ uint8_t fst[768U]; ++ uint8_t snd[800U]; ++} libcrux_ml_kem_utils_extraction_helper_Keypair512; ++ ++typedef struct libcrux_ml_kem_utils_extraction_helper_Keypair768_s { ++ uint8_t fst[1152U]; ++ uint8_t snd[1184U]; ++} libcrux_ml_kem_utils_extraction_helper_Keypair768; ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemPublicKey)#14} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_b6 ++with const generics ++- SIZE= 1568 ++*/ ++libcrux_ml_kem_types_MlKemPublicKey_1f libcrux_ml_kem_types_from_b6_961( ++ uint8_t value[1568U]); ++ ++/** ++ Create a new [`MlKemKeyPair`] from the secret and public key. ++*/ ++/** ++This function found in impl ++{libcrux_ml_kem::types::MlKemKeyPair} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_17 ++with const generics ++- PRIVATE_KEY_SIZE= 3168 ++- PUBLIC_KEY_SIZE= 1568 ++*/ ++libcrux_ml_kem_mlkem1024_MlKem1024KeyPair libcrux_ml_kem_types_from_17_821( ++ libcrux_ml_kem_types_MlKemPrivateKey_95 sk, ++ libcrux_ml_kem_types_MlKemPublicKey_1f pk); ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemPrivateKey)#8} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_05 ++with const generics ++- SIZE= 3168 ++*/ ++libcrux_ml_kem_types_MlKemPrivateKey_95 libcrux_ml_kem_types_from_05_891( ++ uint8_t value[3168U]); ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemCiphertext)#2} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_01 ++with const generics ++- SIZE= 1568 ++*/ ++libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext libcrux_ml_kem_types_from_01_331( ++ uint8_t value[1568U]); ++ ++/** ++ A reference to the raw byte slice. ++*/ ++/** ++This function found in impl {libcrux_ml_kem::types::MlKemPublicKey#18} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.as_slice_cb ++with const generics ++- SIZE= 1568 ++*/ ++uint8_t *libcrux_ml_kem_types_as_slice_cb_3d1( ++ libcrux_ml_kem_types_MlKemPublicKey_1f *self); ++ ++/** ++This function found in impl {(core::convert::AsRef<@Slice> for ++libcrux_ml_kem::types::MlKemCiphertext)#1} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.as_ref_00 ++with const generics ++- SIZE= 1568 ++*/ ++Eurydice_slice libcrux_ml_kem_types_as_ref_00_d81( ++ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *self); ++ ++/** ++ Pad the `slice` with `0`s at the end. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.utils.into_padded_array ++with const generics ++- LEN= 1600 ++*/ ++void libcrux_ml_kem_utils_into_padded_array_6d4(Eurydice_slice slice, ++ uint8_t ret[1600U]); ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemPublicKey)#14} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_b6 ++with const generics ++- SIZE= 1184 ++*/ ++libcrux_ml_kem_types_MlKemPublicKey_15 libcrux_ml_kem_types_from_b6_960( ++ uint8_t value[1184U]); ++ ++/** ++ Create a new [`MlKemKeyPair`] from the secret and public key. ++*/ ++/** ++This function found in impl ++{libcrux_ml_kem::types::MlKemKeyPair} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_17 ++with const generics ++- PRIVATE_KEY_SIZE= 2400 ++- PUBLIC_KEY_SIZE= 1184 ++*/ ++libcrux_ml_kem_mlkem768_MlKem768KeyPair libcrux_ml_kem_types_from_17_820( ++ libcrux_ml_kem_types_MlKemPrivateKey_55 sk, ++ libcrux_ml_kem_types_MlKemPublicKey_15 pk); ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemPrivateKey)#8} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_05 ++with const generics ++- SIZE= 2400 ++*/ ++libcrux_ml_kem_types_MlKemPrivateKey_55 libcrux_ml_kem_types_from_05_890( ++ uint8_t value[2400U]); ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemCiphertext)#2} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_01 ++with const generics ++- SIZE= 1088 ++*/ ++libcrux_ml_kem_mlkem768_MlKem768Ciphertext libcrux_ml_kem_types_from_01_330( ++ uint8_t value[1088U]); ++ ++/** ++ A reference to the raw byte slice. ++*/ ++/** ++This function found in impl {libcrux_ml_kem::types::MlKemPublicKey#18} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.as_slice_cb ++with const generics ++- SIZE= 1184 ++*/ ++uint8_t *libcrux_ml_kem_types_as_slice_cb_3d0( ++ libcrux_ml_kem_types_MlKemPublicKey_15 *self); ++ ++/** ++This function found in impl {(core::convert::AsRef<@Slice> for ++libcrux_ml_kem::types::MlKemCiphertext)#1} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.as_ref_00 ++with const generics ++- SIZE= 1088 ++*/ ++Eurydice_slice libcrux_ml_kem_types_as_ref_00_d80( ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext *self); ++ ++/** ++ Pad the `slice` with `0`s at the end. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.utils.into_padded_array ++with const generics ++- LEN= 1120 ++*/ ++void libcrux_ml_kem_utils_into_padded_array_6d3(Eurydice_slice slice, ++ uint8_t ret[1120U]); ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemPublicKey)#14} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_b6 ++with const generics ++- SIZE= 800 ++*/ ++libcrux_ml_kem_types_MlKemPublicKey_be libcrux_ml_kem_types_from_b6_96( ++ uint8_t value[800U]); ++ ++/** ++ Create a new [`MlKemKeyPair`] from the secret and public key. ++*/ ++/** ++This function found in impl ++{libcrux_ml_kem::types::MlKemKeyPair} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_17 ++with const generics ++- PRIVATE_KEY_SIZE= 1632 ++- PUBLIC_KEY_SIZE= 800 ++*/ ++libcrux_ml_kem_types_MlKemKeyPair_cb libcrux_ml_kem_types_from_17_82( ++ libcrux_ml_kem_types_MlKemPrivateKey_5e sk, ++ libcrux_ml_kem_types_MlKemPublicKey_be pk); ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemPrivateKey)#8} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_05 ++with const generics ++- SIZE= 1632 ++*/ ++libcrux_ml_kem_types_MlKemPrivateKey_5e libcrux_ml_kem_types_from_05_89( ++ uint8_t value[1632U]); ++ ++/** ++A monomorphic instance of core.result.Result ++with types uint8_t[32size_t], core_array_TryFromSliceError ++ ++*/ ++typedef struct core_result_Result_00_s { ++ core_result_Result_86_tags tag; ++ union { ++ uint8_t case_Ok[32U]; ++ core_array_TryFromSliceError case_Err; ++ } val; ++} core_result_Result_00; ++ ++/** ++This function found in impl {core::result::Result} ++*/ ++/** ++A monomorphic instance of core.result.unwrap_41 ++with types uint8_t[32size_t], core_array_TryFromSliceError ++ ++*/ ++void core_result_unwrap_41_33(core_result_Result_00 self, uint8_t ret[32U]); ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemCiphertext)#2} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_01 ++with const generics ++- SIZE= 768 ++*/ ++libcrux_ml_kem_types_MlKemCiphertext_e8 libcrux_ml_kem_types_from_01_33( ++ uint8_t value[768U]); ++ ++/** ++ A reference to the raw byte slice. ++*/ ++/** ++This function found in impl {libcrux_ml_kem::types::MlKemPublicKey#18} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.as_slice_cb ++with const generics ++- SIZE= 800 ++*/ ++uint8_t *libcrux_ml_kem_types_as_slice_cb_3d( ++ libcrux_ml_kem_types_MlKemPublicKey_be *self); ++ ++/** ++ Pad the `slice` with `0`s at the end. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.utils.into_padded_array ++with const generics ++- LEN= 33 ++*/ ++void libcrux_ml_kem_utils_into_padded_array_6d2(Eurydice_slice slice, ++ uint8_t ret[33U]); ++ ++/** ++ Pad the `slice` with `0`s at the end. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.utils.into_padded_array ++with const generics ++- LEN= 34 ++*/ ++void libcrux_ml_kem_utils_into_padded_array_6d1(Eurydice_slice slice, ++ uint8_t ret[34U]); ++ ++/** ++This function found in impl {(core::convert::AsRef<@Slice> for ++libcrux_ml_kem::types::MlKemCiphertext)#1} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.as_ref_00 ++with const generics ++- SIZE= 768 ++*/ ++Eurydice_slice libcrux_ml_kem_types_as_ref_00_d8( ++ libcrux_ml_kem_types_MlKemCiphertext_e8 *self); ++ ++/** ++ Pad the `slice` with `0`s at the end. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.utils.into_padded_array ++with const generics ++- LEN= 800 ++*/ ++void libcrux_ml_kem_utils_into_padded_array_6d0(Eurydice_slice slice, ++ uint8_t ret[800U]); ++ ++/** ++ Pad the `slice` with `0`s at the end. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.utils.into_padded_array ++with const generics ++- LEN= 64 ++*/ ++void libcrux_ml_kem_utils_into_padded_array_6d(Eurydice_slice slice, ++ uint8_t ret[64U]); ++ ++/** ++A monomorphic instance of core.result.Result ++with types uint8_t[24size_t], core_array_TryFromSliceError ++ ++*/ ++typedef struct core_result_Result_6f_s { ++ core_result_Result_86_tags tag; ++ union { ++ uint8_t case_Ok[24U]; ++ core_array_TryFromSliceError case_Err; ++ } val; ++} core_result_Result_6f; ++ ++/** ++This function found in impl {core::result::Result} ++*/ ++/** ++A monomorphic instance of core.result.unwrap_41 ++with types uint8_t[24size_t], core_array_TryFromSliceError ++ ++*/ ++void core_result_unwrap_41_76(core_result_Result_6f self, uint8_t ret[24U]); ++ ++/** ++A monomorphic instance of core.result.Result ++with types uint8_t[20size_t], core_array_TryFromSliceError ++ ++*/ ++typedef struct core_result_Result_7a_s { ++ core_result_Result_86_tags tag; ++ union { ++ uint8_t case_Ok[20U]; ++ core_array_TryFromSliceError case_Err; ++ } val; ++} core_result_Result_7a; ++ ++/** ++This function found in impl {core::result::Result} ++*/ ++/** ++A monomorphic instance of core.result.unwrap_41 ++with types uint8_t[20size_t], core_array_TryFromSliceError ++ ++*/ ++void core_result_unwrap_41_ea(core_result_Result_7a self, uint8_t ret[20U]); ++ ++/** ++A monomorphic instance of core.result.Result ++with types uint8_t[10size_t], core_array_TryFromSliceError ++ ++*/ ++typedef struct core_result_Result_cd_s { ++ core_result_Result_86_tags tag; ++ union { ++ uint8_t case_Ok[10U]; ++ core_array_TryFromSliceError case_Err; ++ } val; ++} core_result_Result_cd; ++ ++/** ++This function found in impl {core::result::Result} ++*/ ++/** ++A monomorphic instance of core.result.unwrap_41 ++with types uint8_t[10size_t], core_array_TryFromSliceError ++ ++*/ ++void core_result_unwrap_41_07(core_result_Result_cd self, uint8_t ret[10U]); ++ ++/** ++A monomorphic instance of core.result.Result ++with types int16_t[16size_t], core_array_TryFromSliceError ++ ++*/ ++typedef struct core_result_Result_c0_s { ++ core_result_Result_86_tags tag; ++ union { ++ int16_t case_Ok[16U]; ++ core_array_TryFromSliceError case_Err; ++ } val; ++} core_result_Result_c0; ++ ++/** ++This function found in impl {core::result::Result} ++*/ ++/** ++A monomorphic instance of core.result.unwrap_41 ++with types int16_t[16size_t], core_array_TryFromSliceError ++ ++*/ ++void core_result_unwrap_41_30(core_result_Result_c0 self, int16_t ret[16U]); ++ ++typedef struct Eurydice_slice_uint8_t_4size_t__x2_s { ++ Eurydice_slice fst[4U]; ++ Eurydice_slice snd[4U]; ++} Eurydice_slice_uint8_t_4size_t__x2; ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#define __internal_libcrux_core_H_DEFINED ++#endif +diff -up ./lib/freebl/verified/internal/libcrux_mlkem_portable.h.mlkem ./lib/freebl/verified/internal/libcrux_mlkem_portable.h +--- ./lib/freebl/verified/internal/libcrux_mlkem_portable.h.mlkem 2024-10-31 14:54:15.462515926 -0700 ++++ ./lib/freebl/verified/internal/libcrux_mlkem_portable.h 2024-10-31 14:54:15.462515926 -0700 +@@ -0,0 +1,373 @@ ++/* ++ * SPDX-FileCopyrightText: 2024 Cryspen Sarl ++ * ++ * SPDX-License-Identifier: MIT or Apache-2.0 ++ * ++ * This code was generated with the following revisions: ++ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d ++ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46 ++ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0 ++ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7 ++ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb ++ */ ++ ++#ifndef __internal_libcrux_mlkem_portable_H ++#define __internal_libcrux_mlkem_portable_H ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++#include "../libcrux_mlkem_portable.h" ++#include "eurydice_glue.h" ++#include "internal/libcrux_core.h" ++#include "internal/libcrux_sha3_internal.h" ++ ++extern const int16_t libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[128U]; ++ ++#define LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT \ ++ (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT / \ ++ LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR) ++ ++/** ++A monomorphic instance of libcrux_ml_kem.polynomial.PolynomialRingElement ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++ ++*/ ++typedef struct libcrux_ml_kem_polynomial_PolynomialRingElement_f0_s { ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficients[16U]; ++} libcrux_ml_kem_polynomial_PolynomialRingElement_f0; ++ ++/** ++ Validate an ML-KEM public key. ++ ++ This implements the Modulus check in 7.2 2. ++ Note that the size check in 7.2 1 is covered by the `PUBLIC_KEY_SIZE` in the ++ `public_key` type. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.validate_public_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++- RANKED_BYTES_PER_RING_ELEMENT= 1536 ++- PUBLIC_KEY_SIZE= 1568 ++*/ ++bool libcrux_ml_kem_ind_cca_validate_public_key_b71(uint8_t *public_key); ++ ++/** ++ Validate an ML-KEM private key. ++ ++ This implements the Hash check in 7.3 3. ++ Note that the size checks in 7.2 1 and 2 are covered by the `SECRET_KEY_SIZE` ++ and `CIPHERTEXT_SIZE` in the `private_key` and `ciphertext` types. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.validate_private_key ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]] ++with const generics ++- K= 4 ++- SECRET_KEY_SIZE= 3168 ++- CIPHERTEXT_SIZE= 1568 ++*/ ++bool libcrux_ml_kem_ind_cca_validate_private_key_dc( ++ libcrux_ml_kem_types_MlKemPrivateKey_95 *private_key, ++ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *_ciphertext); ++ ++/** ++ Packed API ++ ++ Generate a key pair. ++ ++ Depending on the `Vector` and `Hasher` used, this requires different hardware ++ features ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.generate_keypair ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 4 ++- CPA_PRIVATE_KEY_SIZE= 1536 ++- PRIVATE_KEY_SIZE= 3168 ++- PUBLIC_KEY_SIZE= 1568 ++- BYTES_PER_RING_ELEMENT= 1536 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++*/ ++libcrux_ml_kem_mlkem1024_MlKem1024KeyPair ++libcrux_ml_kem_ind_cca_generate_keypair_f61(uint8_t randomness[64U]); ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.encapsulate ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 4 ++- CIPHERTEXT_SIZE= 1568 ++- PUBLIC_KEY_SIZE= 1568 ++- T_AS_NTT_ENCODED_SIZE= 1536 ++- C1_SIZE= 1408 ++- C2_SIZE= 160 ++- VECTOR_U_COMPRESSION_FACTOR= 11 ++- VECTOR_V_COMPRESSION_FACTOR= 5 ++- VECTOR_U_BLOCK_LEN= 352 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++*/ ++tuple_21 libcrux_ml_kem_ind_cca_encapsulate_eb1( ++ libcrux_ml_kem_types_MlKemPublicKey_1f *public_key, ++ uint8_t randomness[32U]); ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.decapsulate ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 4 ++- SECRET_KEY_SIZE= 3168 ++- CPA_SECRET_KEY_SIZE= 1536 ++- PUBLIC_KEY_SIZE= 1568 ++- CIPHERTEXT_SIZE= 1568 ++- T_AS_NTT_ENCODED_SIZE= 1536 ++- C1_SIZE= 1408 ++- C2_SIZE= 160 ++- VECTOR_U_COMPRESSION_FACTOR= 11 ++- VECTOR_V_COMPRESSION_FACTOR= 5 ++- C1_BLOCK_SIZE= 352 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++- IMPLICIT_REJECTION_HASH_INPUT_SIZE= 1600 ++*/ ++void libcrux_ml_kem_ind_cca_decapsulate_1f1( ++ libcrux_ml_kem_types_MlKemPrivateKey_95 *private_key, ++ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *ciphertext, uint8_t ret[32U]); ++ ++/** ++ Validate an ML-KEM public key. ++ ++ This implements the Modulus check in 7.2 2. ++ Note that the size check in 7.2 1 is covered by the `PUBLIC_KEY_SIZE` in the ++ `public_key` type. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.validate_public_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++- RANKED_BYTES_PER_RING_ELEMENT= 768 ++- PUBLIC_KEY_SIZE= 800 ++*/ ++bool libcrux_ml_kem_ind_cca_validate_public_key_b70(uint8_t *public_key); ++ ++/** ++ Validate an ML-KEM private key. ++ ++ This implements the Hash check in 7.3 3. ++ Note that the size checks in 7.2 1 and 2 are covered by the `SECRET_KEY_SIZE` ++ and `CIPHERTEXT_SIZE` in the `private_key` and `ciphertext` types. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.validate_private_key ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]] ++with const generics ++- K= 2 ++- SECRET_KEY_SIZE= 1632 ++- CIPHERTEXT_SIZE= 768 ++*/ ++bool libcrux_ml_kem_ind_cca_validate_private_key_03( ++ libcrux_ml_kem_types_MlKemPrivateKey_5e *private_key, ++ libcrux_ml_kem_types_MlKemCiphertext_e8 *_ciphertext); ++ ++/** ++ Packed API ++ ++ Generate a key pair. ++ ++ Depending on the `Vector` and `Hasher` used, this requires different hardware ++ features ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.generate_keypair ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 2 ++- CPA_PRIVATE_KEY_SIZE= 768 ++- PRIVATE_KEY_SIZE= 1632 ++- PUBLIC_KEY_SIZE= 800 ++- BYTES_PER_RING_ELEMENT= 768 ++- ETA1= 3 ++- ETA1_RANDOMNESS_SIZE= 192 ++*/ ++libcrux_ml_kem_types_MlKemKeyPair_cb ++libcrux_ml_kem_ind_cca_generate_keypair_f60(uint8_t randomness[64U]); ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.encapsulate ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 2 ++- CIPHERTEXT_SIZE= 768 ++- PUBLIC_KEY_SIZE= 800 ++- T_AS_NTT_ENCODED_SIZE= 768 ++- C1_SIZE= 640 ++- C2_SIZE= 128 ++- VECTOR_U_COMPRESSION_FACTOR= 10 ++- VECTOR_V_COMPRESSION_FACTOR= 4 ++- VECTOR_U_BLOCK_LEN= 320 ++- ETA1= 3 ++- ETA1_RANDOMNESS_SIZE= 192 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++*/ ++tuple_ec libcrux_ml_kem_ind_cca_encapsulate_eb0( ++ libcrux_ml_kem_types_MlKemPublicKey_be *public_key, ++ uint8_t randomness[32U]); ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.decapsulate ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 2 ++- SECRET_KEY_SIZE= 1632 ++- CPA_SECRET_KEY_SIZE= 768 ++- PUBLIC_KEY_SIZE= 800 ++- CIPHERTEXT_SIZE= 768 ++- T_AS_NTT_ENCODED_SIZE= 768 ++- C1_SIZE= 640 ++- C2_SIZE= 128 ++- VECTOR_U_COMPRESSION_FACTOR= 10 ++- VECTOR_V_COMPRESSION_FACTOR= 4 ++- C1_BLOCK_SIZE= 320 ++- ETA1= 3 ++- ETA1_RANDOMNESS_SIZE= 192 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++- IMPLICIT_REJECTION_HASH_INPUT_SIZE= 800 ++*/ ++void libcrux_ml_kem_ind_cca_decapsulate_1f0( ++ libcrux_ml_kem_types_MlKemPrivateKey_5e *private_key, ++ libcrux_ml_kem_types_MlKemCiphertext_e8 *ciphertext, uint8_t ret[32U]); ++ ++/** ++ Validate an ML-KEM public key. ++ ++ This implements the Modulus check in 7.2 2. ++ Note that the size check in 7.2 1 is covered by the `PUBLIC_KEY_SIZE` in the ++ `public_key` type. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.validate_public_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++- RANKED_BYTES_PER_RING_ELEMENT= 1152 ++- PUBLIC_KEY_SIZE= 1184 ++*/ ++bool libcrux_ml_kem_ind_cca_validate_public_key_b7(uint8_t *public_key); ++ ++/** ++ Validate an ML-KEM private key. ++ ++ This implements the Hash check in 7.3 3. ++ Note that the size checks in 7.2 1 and 2 are covered by the `SECRET_KEY_SIZE` ++ and `CIPHERTEXT_SIZE` in the `private_key` and `ciphertext` types. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.validate_private_key ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] ++with const generics ++- K= 3 ++- SECRET_KEY_SIZE= 2400 ++- CIPHERTEXT_SIZE= 1088 ++*/ ++bool libcrux_ml_kem_ind_cca_validate_private_key_05( ++ libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext *_ciphertext); ++ ++/** ++ Packed API ++ ++ Generate a key pair. ++ ++ Depending on the `Vector` and `Hasher` used, this requires different hardware ++ features ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.generate_keypair ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 3 ++- CPA_PRIVATE_KEY_SIZE= 1152 ++- PRIVATE_KEY_SIZE= 2400 ++- PUBLIC_KEY_SIZE= 1184 ++- BYTES_PER_RING_ELEMENT= 1152 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++*/ ++libcrux_ml_kem_mlkem768_MlKem768KeyPair ++libcrux_ml_kem_ind_cca_generate_keypair_f6(uint8_t randomness[64U]); ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.encapsulate ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 3 ++- CIPHERTEXT_SIZE= 1088 ++- PUBLIC_KEY_SIZE= 1184 ++- T_AS_NTT_ENCODED_SIZE= 1152 ++- C1_SIZE= 960 ++- C2_SIZE= 128 ++- VECTOR_U_COMPRESSION_FACTOR= 10 ++- VECTOR_V_COMPRESSION_FACTOR= 4 ++- VECTOR_U_BLOCK_LEN= 320 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++*/ ++tuple_3c libcrux_ml_kem_ind_cca_encapsulate_eb( ++ libcrux_ml_kem_types_MlKemPublicKey_15 *public_key, ++ uint8_t randomness[32U]); ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.decapsulate ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 3 ++- SECRET_KEY_SIZE= 2400 ++- CPA_SECRET_KEY_SIZE= 1152 ++- PUBLIC_KEY_SIZE= 1184 ++- CIPHERTEXT_SIZE= 1088 ++- T_AS_NTT_ENCODED_SIZE= 1152 ++- C1_SIZE= 960 ++- C2_SIZE= 128 ++- VECTOR_U_COMPRESSION_FACTOR= 10 ++- VECTOR_V_COMPRESSION_FACTOR= 4 ++- C1_BLOCK_SIZE= 320 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++- IMPLICIT_REJECTION_HASH_INPUT_SIZE= 1120 ++*/ ++void libcrux_ml_kem_ind_cca_decapsulate_1f( ++ libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]); ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#define __internal_libcrux_mlkem_portable_H_DEFINED ++#endif +diff -up ./lib/freebl/verified/internal/libcrux_sha3_internal.h.mlkem ./lib/freebl/verified/internal/libcrux_sha3_internal.h +--- ./lib/freebl/verified/internal/libcrux_sha3_internal.h.mlkem 2024-10-31 14:54:15.463515937 -0700 ++++ ./lib/freebl/verified/internal/libcrux_sha3_internal.h 2024-10-31 14:54:15.463515937 -0700 +@@ -0,0 +1,1551 @@ ++/* ++ * SPDX-FileCopyrightText: 2024 Cryspen Sarl ++ * ++ * SPDX-License-Identifier: MIT or Apache-2.0 ++ * ++ * This code was generated with the following revisions: ++ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d ++ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46 ++ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0 ++ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7 ++ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb ++ */ ++ ++#ifndef __internal_libcrux_sha3_internal_H ++#define __internal_libcrux_sha3_internal_H ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++#include "../libcrux_sha3_internal.h" ++#include "eurydice_glue.h" ++ ++typedef libcrux_sha3_generic_keccak_KeccakState_48 ++ libcrux_sha3_portable_KeccakState; ++ ++/** ++ Create a new SHAKE-128 state object. ++*/ ++static KRML_MUSTINLINE libcrux_sha3_generic_keccak_KeccakState_48 ++libcrux_sha3_portable_incremental_shake128_init(void) ++{ ++ return libcrux_sha3_generic_keccak_new_1e_cf(); ++} ++ ++/** ++ Absorb ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_incremental_shake128_absorb_final( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice data0) ++{ ++ Eurydice_slice buf[1U] = { data0 }; ++ libcrux_sha3_generic_keccak_absorb_final_40(s, buf); ++} ++ ++/** ++ Squeeze another block ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_incremental_shake128_squeeze_next_block( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out0) ++{ ++ Eurydice_slice buf[1U] = { out0 }; ++ libcrux_sha3_generic_keccak_squeeze_next_block_c2(s, buf); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_three_blocks ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_first_three_blocks_5c( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ Eurydice_slice_uint8_t_1size_t__x2 uu____0 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)168U); ++ Eurydice_slice o0[1U]; ++ memcpy(o0, uu____0.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice o10[1U]; ++ memcpy(o10, uu____0.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_first_block_7b(s, o0); ++ Eurydice_slice_uint8_t_1size_t__x2 uu____1 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(o10, (size_t)168U); ++ Eurydice_slice o1[1U]; ++ memcpy(o1, uu____1.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice o2[1U]; ++ memcpy(o2, uu____1.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_next_block_c2(s, o1); ++ libcrux_sha3_generic_keccak_squeeze_next_block_c2(s, o2); ++} ++ ++/** ++ Squeeze three blocks ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_incremental_shake128_squeeze_first_three_blocks( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out0) ++{ ++ Eurydice_slice buf[1U] = { out0 }; ++ libcrux_sha3_generic_keccak_squeeze_first_three_blocks_5c(s, buf); ++} ++ ++#define libcrux_sha3_Sha224 0 ++#define libcrux_sha3_Sha256 1 ++#define libcrux_sha3_Sha384 2 ++#define libcrux_sha3_Sha512 3 ++ ++typedef uint8_t libcrux_sha3_Algorithm; ++ ++/** ++ Returns the output size of a digest. ++*/ ++static inline size_t ++libcrux_sha3_digest_size(libcrux_sha3_Algorithm mode) ++{ ++ size_t uu____0; ++ switch (mode) { ++ case libcrux_sha3_Sha224: { ++ uu____0 = (size_t)28U; ++ break; ++ } ++ case libcrux_sha3_Sha256: { ++ uu____0 = (size_t)32U; ++ break; ++ } ++ case libcrux_sha3_Sha384: { ++ uu____0 = (size_t)48U; ++ break; ++ } ++ case libcrux_sha3_Sha512: { ++ uu____0 = (size_t)64U; ++ break; ++ } ++ default: { ++ KRML_HOST_EPRINTF("KaRaMeL incomplete match at %s:%d\n", __FILE__, ++ __LINE__); ++ KRML_HOST_EXIT(253U); ++ } ++ } ++ return uu____0; ++} ++ ++static const size_t libcrux_sha3_generic_keccak__PI[24U] = { ++ (size_t)6U, (size_t)12U, (size_t)18U, (size_t)24U, (size_t)3U, ++ (size_t)9U, (size_t)10U, (size_t)16U, (size_t)22U, (size_t)1U, ++ (size_t)7U, (size_t)13U, (size_t)19U, (size_t)20U, (size_t)4U, ++ (size_t)5U, (size_t)11U, (size_t)17U, (size_t)23U, (size_t)2U, ++ (size_t)8U, (size_t)14U, (size_t)15U, (size_t)21U ++}; ++ ++static const size_t libcrux_sha3_generic_keccak__ROTC[24U] = { ++ (size_t)1U, (size_t)62U, (size_t)28U, (size_t)27U, (size_t)36U, ++ (size_t)44U, (size_t)6U, (size_t)55U, (size_t)20U, (size_t)3U, ++ (size_t)10U, (size_t)43U, (size_t)25U, (size_t)39U, (size_t)41U, ++ (size_t)45U, (size_t)15U, (size_t)21U, (size_t)8U, (size_t)18U, ++ (size_t)2U, (size_t)61U, (size_t)56U, (size_t)14U ++}; ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_five_blocks ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_first_five_blocks_3e( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ Eurydice_slice_uint8_t_1size_t__x2 uu____0 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)168U); ++ Eurydice_slice o0[1U]; ++ memcpy(o0, uu____0.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice o10[1U]; ++ memcpy(o10, uu____0.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_first_block_7b(s, o0); ++ Eurydice_slice_uint8_t_1size_t__x2 uu____1 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(o10, (size_t)168U); ++ Eurydice_slice o1[1U]; ++ memcpy(o1, uu____1.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice o20[1U]; ++ memcpy(o20, uu____1.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_next_block_c2(s, o1); ++ Eurydice_slice_uint8_t_1size_t__x2 uu____2 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(o20, (size_t)168U); ++ Eurydice_slice o2[1U]; ++ memcpy(o2, uu____2.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice o30[1U]; ++ memcpy(o30, uu____2.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_next_block_c2(s, o2); ++ Eurydice_slice_uint8_t_1size_t__x2 uu____3 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(o30, (size_t)168U); ++ Eurydice_slice o3[1U]; ++ memcpy(o3, uu____3.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice o4[1U]; ++ memcpy(o4, uu____3.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_next_block_c2(s, o3); ++ libcrux_sha3_generic_keccak_squeeze_next_block_c2(s, o4); ++} ++ ++/** ++ Squeeze five blocks ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_incremental_shake128_squeeze_first_five_blocks( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out0) ++{ ++ Eurydice_slice buf[1U] = { out0 }; ++ libcrux_sha3_generic_keccak_squeeze_first_five_blocks_3e(s, buf); ++} ++ ++/** ++ Absorb some data for SHAKE-256 for the last time ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_incremental_shake256_absorb_final( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice data) ++{ ++ Eurydice_slice buf[1U] = { data }; ++ libcrux_sha3_generic_keccak_absorb_final_400(s, buf); ++} ++ ++/** ++ Create a new SHAKE-256 state object. ++*/ ++static KRML_MUSTINLINE libcrux_sha3_generic_keccak_KeccakState_48 ++libcrux_sha3_portable_incremental_shake256_init(void) ++{ ++ return libcrux_sha3_generic_keccak_new_1e_cf(); ++} ++ ++/** ++ Squeeze the first SHAKE-256 block ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_incremental_shake256_squeeze_first_block( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out) ++{ ++ Eurydice_slice buf[1U] = { out }; ++ libcrux_sha3_generic_keccak_squeeze_first_block_7b0(s, buf); ++} ++ ++/** ++ Squeeze the next SHAKE-256 block ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_incremental_shake256_squeeze_next_block( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out) ++{ ++ Eurydice_slice buf[1U] = { out }; ++ libcrux_sha3_generic_keccak_squeeze_next_block_c20(s, buf); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.KeccakXofState ++with types uint64_t ++with const generics ++- $1size_t ++- $136size_t ++*/ ++typedef struct libcrux_sha3_generic_keccak_KeccakXofState_4f_s { ++ libcrux_sha3_generic_keccak_KeccakState_48 inner; ++ uint8_t buf[1U][136U]; ++ size_t buf_len; ++ bool sponge; ++} libcrux_sha3_generic_keccak_KeccakXofState_4f; ++ ++typedef libcrux_sha3_generic_keccak_KeccakXofState_4f ++ libcrux_sha3_portable_incremental_Shake256Absorb; ++ ++/** ++ Consume the internal buffer and the required amount of the input to pad to ++ `RATE`. ++ ++ Returns the `consumed` bytes from `inputs` if there's enough buffered ++ content to consume, and `0` otherwise. ++ If `consumed > 0` is returned, `self.buf` contains a full block to be ++ loaded. ++*/ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.fill_buffer_9d ++with types uint64_t ++with const generics ++- PARALLEL_LANES= 1 ++- RATE= 136 ++*/ ++static inline size_t ++libcrux_sha3_generic_keccak_fill_buffer_9d_15( ++ libcrux_sha3_generic_keccak_KeccakXofState_4f *self, ++ Eurydice_slice inputs[1U]) ++{ ++ size_t input_len = Eurydice_slice_len(inputs[0U], uint8_t); ++ size_t consumed = (size_t)0U; ++ if (self->buf_len > (size_t)0U) { ++ if (self->buf_len + input_len >= (size_t)136U) { ++ consumed = (size_t)136U - self->buf_len; ++ { ++ size_t i = (size_t)0U; ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice_from( ++ (size_t)136U, self->buf[i], self->buf_len, uint8_t, size_t); ++ Eurydice_slice_copy( ++ uu____0, ++ Eurydice_slice_subslice_to(inputs[i], consumed, uint8_t, size_t), ++ uint8_t); ++ } ++ self->buf_len = self->buf_len + consumed; ++ } ++ } ++ return consumed; ++} ++ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_full_9d ++with types uint64_t ++with const generics ++- PARALLEL_LANES= 1 ++- RATE= 136 ++*/ ++static inline size_t ++libcrux_sha3_generic_keccak_absorb_full_9d_7a( ++ libcrux_sha3_generic_keccak_KeccakXofState_4f *self, ++ Eurydice_slice inputs[1U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakXofState_4f *uu____0 = self; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_inputs0[1U]; ++ memcpy(copy_of_inputs0, inputs, (size_t)1U * sizeof(Eurydice_slice)); ++ size_t input_consumed = ++ libcrux_sha3_generic_keccak_fill_buffer_9d_15(uu____0, copy_of_inputs0); ++ if (input_consumed > (size_t)0U) { ++ Eurydice_slice borrowed[1U]; ++ { ++ uint8_t buf[136U] = { 0U }; ++ borrowed[0U] = core_array___Array_T__N__23__as_slice( ++ (size_t)136U, buf, uint8_t, Eurydice_slice); ++ } ++ { ++ size_t i = (size_t)0U; ++ borrowed[i] = ++ Eurydice_array_to_slice((size_t)136U, self->buf[i], uint8_t); ++ } ++ uint64_t(*uu____2)[5U] = self->inner.st; ++ Eurydice_slice uu____3[1U]; ++ memcpy(uu____3, borrowed, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_portable_keccak_load_block_5a_35(uu____2, uu____3); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&self->inner); ++ self->buf_len = (size_t)0U; ++ } ++ size_t input_to_consume = ++ Eurydice_slice_len(inputs[0U], uint8_t) - input_consumed; ++ size_t num_blocks = input_to_consume / (size_t)136U; ++ size_t remainder = input_to_consume % (size_t)136U; ++ for (size_t i = (size_t)0U; i < num_blocks; i++) { ++ size_t i0 = i; ++ uint64_t(*uu____4)[5U] = self->inner.st; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_inputs[1U]; ++ memcpy(copy_of_inputs, inputs, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret[1U]; ++ libcrux_sha3_portable_keccak_slice_n_5a( ++ copy_of_inputs, input_consumed + i0 * (size_t)136U, (size_t)136U, ret); ++ libcrux_sha3_portable_keccak_load_block_5a_35(uu____4, ret); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&self->inner); ++ } ++ return remainder; ++} ++ ++/** ++ Absorb ++ ++ This function takes any number of bytes to absorb and buffers if it's not ++ enough. The function assumes that all input slices in `blocks` have the same ++ length. ++ ++ Only a multiple of `RATE` blocks are absorbed. ++ For the remaining bytes [`absorb_final`] needs to be called. ++ ++ This works best with relatively small `inputs`. ++*/ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_9d ++with types uint64_t ++with const generics ++- PARALLEL_LANES= 1 ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_9d_45( ++ libcrux_sha3_generic_keccak_KeccakXofState_4f *self, ++ Eurydice_slice inputs[1U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakXofState_4f *uu____0 = self; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_inputs[1U]; ++ memcpy(copy_of_inputs, inputs, (size_t)1U * sizeof(Eurydice_slice)); ++ size_t input_remainder_len = ++ libcrux_sha3_generic_keccak_absorb_full_9d_7a(uu____0, copy_of_inputs); ++ if (input_remainder_len > (size_t)0U) { ++ size_t input_len = Eurydice_slice_len(inputs[0U], uint8_t); ++ { ++ size_t i = (size_t)0U; ++ Eurydice_slice uu____2 = Eurydice_array_to_subslice2( ++ self->buf[i], self->buf_len, self->buf_len + input_remainder_len, ++ uint8_t); ++ Eurydice_slice_copy( ++ uu____2, ++ Eurydice_slice_subslice_from( ++ inputs[i], input_len - input_remainder_len, uint8_t, size_t), ++ uint8_t); ++ } ++ self->buf_len = self->buf_len + input_remainder_len; ++ } ++} ++ ++/** ++ Shake256 absorb ++*/ ++/** ++This function found in impl ++{(libcrux_sha3::portable::incremental::XofAbsorb<136: usize> for ++libcrux_sha3::portable::incremental::Shake256Absorb)#2} ++*/ ++static inline void ++libcrux_sha3_portable_incremental_absorb_7d( ++ libcrux_sha3_generic_keccak_KeccakXofState_4f *self, Eurydice_slice input) ++{ ++ Eurydice_slice buf[1U] = { input }; ++ libcrux_sha3_generic_keccak_absorb_9d_45(self, buf); ++} ++ ++typedef libcrux_sha3_generic_keccak_KeccakXofState_4f ++ libcrux_sha3_portable_incremental_Shake256Squeeze; ++ ++/** ++ Absorb a final block. ++ ++ The `inputs` block may be empty. Everything in the `inputs` block beyond ++ `RATE` bytes is ignored. ++*/ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final_9d ++with types uint64_t ++with const generics ++- PARALLEL_LANES= 1 ++- RATE= 136 ++- DELIMITER= 31 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_final_9d_b6( ++ libcrux_sha3_generic_keccak_KeccakXofState_4f *self, ++ Eurydice_slice inputs[1U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakXofState_4f *uu____0 = self; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_inputs[1U]; ++ memcpy(copy_of_inputs, inputs, (size_t)1U * sizeof(Eurydice_slice)); ++ size_t input_remainder_len = ++ libcrux_sha3_generic_keccak_absorb_full_9d_7a(uu____0, copy_of_inputs); ++ size_t input_len = Eurydice_slice_len(inputs[0U], uint8_t); ++ uint8_t blocks[1U][200U] = { { 0U } }; ++ { ++ size_t i = (size_t)0U; ++ if (self->buf_len > (size_t)0U) { ++ Eurydice_slice uu____2 = Eurydice_array_to_subslice2( ++ blocks[i], (size_t)0U, self->buf_len, uint8_t); ++ Eurydice_slice_copy(uu____2, ++ Eurydice_array_to_subslice2(self->buf[i], (size_t)0U, ++ self->buf_len, uint8_t), ++ uint8_t); ++ } ++ if (input_remainder_len > (size_t)0U) { ++ Eurydice_slice uu____3 = Eurydice_array_to_subslice2( ++ blocks[i], self->buf_len, self->buf_len + input_remainder_len, ++ uint8_t); ++ Eurydice_slice_copy( ++ uu____3, ++ Eurydice_slice_subslice_from( ++ inputs[i], input_len - input_remainder_len, uint8_t, size_t), ++ uint8_t); ++ } ++ blocks[i][self->buf_len + input_remainder_len] = 31U; ++ size_t uu____4 = i; ++ size_t uu____5 = (size_t)136U - (size_t)1U; ++ blocks[uu____4][uu____5] = (uint32_t)blocks[uu____4][uu____5] | 128U; ++ } ++ uint64_t(*uu____6)[5U] = self->inner.st; ++ uint8_t uu____7[1U][200U]; ++ memcpy(uu____7, blocks, (size_t)1U * sizeof(uint8_t[200U])); ++ libcrux_sha3_portable_keccak_load_block_full_5a_050(uu____6, uu____7); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&self->inner); ++} ++ ++/** ++ Shake256 absorb final ++*/ ++/** ++This function found in impl ++{(libcrux_sha3::portable::incremental::XofAbsorb<136: usize> for ++libcrux_sha3::portable::incremental::Shake256Absorb)#2} ++*/ ++static inline libcrux_sha3_generic_keccak_KeccakXofState_4f ++libcrux_sha3_portable_incremental_absorb_final_7d( ++ libcrux_sha3_generic_keccak_KeccakXofState_4f self, Eurydice_slice input) ++{ ++ Eurydice_slice buf[1U] = { input }; ++ libcrux_sha3_generic_keccak_absorb_final_9d_b6(&self, buf); ++ return self; ++} ++ ++/** ++ An all zero block ++*/ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.zero_block_9d ++with types uint64_t ++with const generics ++- PARALLEL_LANES= 1 ++- RATE= 136 ++*/ ++static inline void ++libcrux_sha3_generic_keccak_zero_block_9d_5e( ++ uint8_t ret[136U]) ++{ ++ ret[0U] = 0U; ++ ret[1U] = 0U; ++ ret[2U] = 0U; ++ ret[3U] = 0U; ++ ret[4U] = 0U; ++ ret[5U] = 0U; ++ ret[6U] = 0U; ++ ret[7U] = 0U; ++ ret[8U] = 0U; ++ ret[9U] = 0U; ++ ret[10U] = 0U; ++ ret[11U] = 0U; ++ ret[12U] = 0U; ++ ret[13U] = 0U; ++ ret[14U] = 0U; ++ ret[15U] = 0U; ++ ret[16U] = 0U; ++ ret[17U] = 0U; ++ ret[18U] = 0U; ++ ret[19U] = 0U; ++ ret[20U] = 0U; ++ ret[21U] = 0U; ++ ret[22U] = 0U; ++ ret[23U] = 0U; ++ ret[24U] = 0U; ++ ret[25U] = 0U; ++ ret[26U] = 0U; ++ ret[27U] = 0U; ++ ret[28U] = 0U; ++ ret[29U] = 0U; ++ ret[30U] = 0U; ++ ret[31U] = 0U; ++ ret[32U] = 0U; ++ ret[33U] = 0U; ++ ret[34U] = 0U; ++ ret[35U] = 0U; ++ ret[36U] = 0U; ++ ret[37U] = 0U; ++ ret[38U] = 0U; ++ ret[39U] = 0U; ++ ret[40U] = 0U; ++ ret[41U] = 0U; ++ ret[42U] = 0U; ++ ret[43U] = 0U; ++ ret[44U] = 0U; ++ ret[45U] = 0U; ++ ret[46U] = 0U; ++ ret[47U] = 0U; ++ ret[48U] = 0U; ++ ret[49U] = 0U; ++ ret[50U] = 0U; ++ ret[51U] = 0U; ++ ret[52U] = 0U; ++ ret[53U] = 0U; ++ ret[54U] = 0U; ++ ret[55U] = 0U; ++ ret[56U] = 0U; ++ ret[57U] = 0U; ++ ret[58U] = 0U; ++ ret[59U] = 0U; ++ ret[60U] = 0U; ++ ret[61U] = 0U; ++ ret[62U] = 0U; ++ ret[63U] = 0U; ++ ret[64U] = 0U; ++ ret[65U] = 0U; ++ ret[66U] = 0U; ++ ret[67U] = 0U; ++ ret[68U] = 0U; ++ ret[69U] = 0U; ++ ret[70U] = 0U; ++ ret[71U] = 0U; ++ ret[72U] = 0U; ++ ret[73U] = 0U; ++ ret[74U] = 0U; ++ ret[75U] = 0U; ++ ret[76U] = 0U; ++ ret[77U] = 0U; ++ ret[78U] = 0U; ++ ret[79U] = 0U; ++ ret[80U] = 0U; ++ ret[81U] = 0U; ++ ret[82U] = 0U; ++ ret[83U] = 0U; ++ ret[84U] = 0U; ++ ret[85U] = 0U; ++ ret[86U] = 0U; ++ ret[87U] = 0U; ++ ret[88U] = 0U; ++ ret[89U] = 0U; ++ ret[90U] = 0U; ++ ret[91U] = 0U; ++ ret[92U] = 0U; ++ ret[93U] = 0U; ++ ret[94U] = 0U; ++ ret[95U] = 0U; ++ ret[96U] = 0U; ++ ret[97U] = 0U; ++ ret[98U] = 0U; ++ ret[99U] = 0U; ++ ret[100U] = 0U; ++ ret[101U] = 0U; ++ ret[102U] = 0U; ++ ret[103U] = 0U; ++ ret[104U] = 0U; ++ ret[105U] = 0U; ++ ret[106U] = 0U; ++ ret[107U] = 0U; ++ ret[108U] = 0U; ++ ret[109U] = 0U; ++ ret[110U] = 0U; ++ ret[111U] = 0U; ++ ret[112U] = 0U; ++ ret[113U] = 0U; ++ ret[114U] = 0U; ++ ret[115U] = 0U; ++ ret[116U] = 0U; ++ ret[117U] = 0U; ++ ret[118U] = 0U; ++ ret[119U] = 0U; ++ ret[120U] = 0U; ++ ret[121U] = 0U; ++ ret[122U] = 0U; ++ ret[123U] = 0U; ++ ret[124U] = 0U; ++ ret[125U] = 0U; ++ ret[126U] = 0U; ++ ret[127U] = 0U; ++ ret[128U] = 0U; ++ ret[129U] = 0U; ++ ret[130U] = 0U; ++ ret[131U] = 0U; ++ ret[132U] = 0U; ++ ret[133U] = 0U; ++ ret[134U] = 0U; ++ ret[135U] = 0U; ++} ++ ++/** ++ Generate a new keccak xof state. ++*/ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.new_9d ++with types uint64_t ++with const generics ++- PARALLEL_LANES= 1 ++- RATE= 136 ++*/ ++static inline libcrux_sha3_generic_keccak_KeccakXofState_4f ++libcrux_sha3_generic_keccak_new_9d_47(void) ++{ ++ libcrux_sha3_generic_keccak_KeccakXofState_4f lit; ++ lit.inner = libcrux_sha3_generic_keccak_new_1e_cf(); ++ uint8_t ret[136U]; ++ libcrux_sha3_generic_keccak_zero_block_9d_5e(ret); ++ memcpy(lit.buf[0U], ret, (size_t)136U * sizeof(uint8_t)); ++ lit.buf_len = (size_t)0U; ++ lit.sponge = false; ++ return lit; ++} ++ ++/** ++ Shake256 new state ++*/ ++/** ++This function found in impl ++{(libcrux_sha3::portable::incremental::XofAbsorb<136: usize> for ++libcrux_sha3::portable::incremental::Shake256Absorb)#2} ++*/ ++static inline libcrux_sha3_generic_keccak_KeccakXofState_4f ++libcrux_sha3_portable_incremental_new_7d(void) ++{ ++ return libcrux_sha3_generic_keccak_new_9d_47(); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.KeccakXofState ++with types uint64_t ++with const generics ++- $1size_t ++- $168size_t ++*/ ++typedef struct libcrux_sha3_generic_keccak_KeccakXofState_78_s { ++ libcrux_sha3_generic_keccak_KeccakState_48 inner; ++ uint8_t buf[1U][168U]; ++ size_t buf_len; ++ bool sponge; ++} libcrux_sha3_generic_keccak_KeccakXofState_78; ++ ++typedef libcrux_sha3_generic_keccak_KeccakXofState_78 ++ libcrux_sha3_portable_incremental_Shake128Absorb; ++ ++/** ++ Consume the internal buffer and the required amount of the input to pad to ++ `RATE`. ++ ++ Returns the `consumed` bytes from `inputs` if there's enough buffered ++ content to consume, and `0` otherwise. ++ If `consumed > 0` is returned, `self.buf` contains a full block to be ++ loaded. ++*/ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.fill_buffer_9d ++with types uint64_t ++with const generics ++- PARALLEL_LANES= 1 ++- RATE= 168 ++*/ ++static inline size_t ++libcrux_sha3_generic_keccak_fill_buffer_9d_150( ++ libcrux_sha3_generic_keccak_KeccakXofState_78 *self, ++ Eurydice_slice inputs[1U]) ++{ ++ size_t input_len = Eurydice_slice_len(inputs[0U], uint8_t); ++ size_t consumed = (size_t)0U; ++ if (self->buf_len > (size_t)0U) { ++ if (self->buf_len + input_len >= (size_t)168U) { ++ consumed = (size_t)168U - self->buf_len; ++ { ++ size_t i = (size_t)0U; ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice_from( ++ (size_t)168U, self->buf[i], self->buf_len, uint8_t, size_t); ++ Eurydice_slice_copy( ++ uu____0, ++ Eurydice_slice_subslice_to(inputs[i], consumed, uint8_t, size_t), ++ uint8_t); ++ } ++ self->buf_len = self->buf_len + consumed; ++ } ++ } ++ return consumed; ++} ++ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_full_9d ++with types uint64_t ++with const generics ++- PARALLEL_LANES= 1 ++- RATE= 168 ++*/ ++static inline size_t ++libcrux_sha3_generic_keccak_absorb_full_9d_7a0( ++ libcrux_sha3_generic_keccak_KeccakXofState_78 *self, ++ Eurydice_slice inputs[1U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakXofState_78 *uu____0 = self; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_inputs0[1U]; ++ memcpy(copy_of_inputs0, inputs, (size_t)1U * sizeof(Eurydice_slice)); ++ size_t input_consumed = ++ libcrux_sha3_generic_keccak_fill_buffer_9d_150(uu____0, copy_of_inputs0); ++ if (input_consumed > (size_t)0U) { ++ Eurydice_slice borrowed[1U]; ++ { ++ uint8_t buf[168U] = { 0U }; ++ borrowed[0U] = core_array___Array_T__N__23__as_slice( ++ (size_t)168U, buf, uint8_t, Eurydice_slice); ++ } ++ { ++ size_t i = (size_t)0U; ++ borrowed[i] = ++ Eurydice_array_to_slice((size_t)168U, self->buf[i], uint8_t); ++ } ++ uint64_t(*uu____2)[5U] = self->inner.st; ++ Eurydice_slice uu____3[1U]; ++ memcpy(uu____3, borrowed, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_portable_keccak_load_block_5a_350(uu____2, uu____3); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&self->inner); ++ self->buf_len = (size_t)0U; ++ } ++ size_t input_to_consume = ++ Eurydice_slice_len(inputs[0U], uint8_t) - input_consumed; ++ size_t num_blocks = input_to_consume / (size_t)168U; ++ size_t remainder = input_to_consume % (size_t)168U; ++ for (size_t i = (size_t)0U; i < num_blocks; i++) { ++ size_t i0 = i; ++ uint64_t(*uu____4)[5U] = self->inner.st; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_inputs[1U]; ++ memcpy(copy_of_inputs, inputs, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret[1U]; ++ libcrux_sha3_portable_keccak_slice_n_5a( ++ copy_of_inputs, input_consumed + i0 * (size_t)168U, (size_t)168U, ret); ++ libcrux_sha3_portable_keccak_load_block_5a_350(uu____4, ret); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&self->inner); ++ } ++ return remainder; ++} ++ ++/** ++ Absorb ++ ++ This function takes any number of bytes to absorb and buffers if it's not ++ enough. The function assumes that all input slices in `blocks` have the same ++ length. ++ ++ Only a multiple of `RATE` blocks are absorbed. ++ For the remaining bytes [`absorb_final`] needs to be called. ++ ++ This works best with relatively small `inputs`. ++*/ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_9d ++with types uint64_t ++with const generics ++- PARALLEL_LANES= 1 ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_9d_450( ++ libcrux_sha3_generic_keccak_KeccakXofState_78 *self, ++ Eurydice_slice inputs[1U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakXofState_78 *uu____0 = self; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_inputs[1U]; ++ memcpy(copy_of_inputs, inputs, (size_t)1U * sizeof(Eurydice_slice)); ++ size_t input_remainder_len = ++ libcrux_sha3_generic_keccak_absorb_full_9d_7a0(uu____0, copy_of_inputs); ++ if (input_remainder_len > (size_t)0U) { ++ size_t input_len = Eurydice_slice_len(inputs[0U], uint8_t); ++ { ++ size_t i = (size_t)0U; ++ Eurydice_slice uu____2 = Eurydice_array_to_subslice2( ++ self->buf[i], self->buf_len, self->buf_len + input_remainder_len, ++ uint8_t); ++ Eurydice_slice_copy( ++ uu____2, ++ Eurydice_slice_subslice_from( ++ inputs[i], input_len - input_remainder_len, uint8_t, size_t), ++ uint8_t); ++ } ++ self->buf_len = self->buf_len + input_remainder_len; ++ } ++} ++ ++/** ++This function found in impl ++{(libcrux_sha3::portable::incremental::XofAbsorb<168: usize> for ++libcrux_sha3::portable::incremental::Shake128Absorb)} ++*/ ++static inline void ++libcrux_sha3_portable_incremental_absorb_1c( ++ libcrux_sha3_generic_keccak_KeccakXofState_78 *self, Eurydice_slice input) ++{ ++ Eurydice_slice buf[1U] = { input }; ++ libcrux_sha3_generic_keccak_absorb_9d_450(self, buf); ++} ++ ++typedef libcrux_sha3_generic_keccak_KeccakXofState_78 ++ libcrux_sha3_portable_incremental_Shake128Squeeze; ++ ++/** ++ Absorb a final block. ++ ++ The `inputs` block may be empty. Everything in the `inputs` block beyond ++ `RATE` bytes is ignored. ++*/ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final_9d ++with types uint64_t ++with const generics ++- PARALLEL_LANES= 1 ++- RATE= 168 ++- DELIMITER= 31 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_final_9d_b60( ++ libcrux_sha3_generic_keccak_KeccakXofState_78 *self, ++ Eurydice_slice inputs[1U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakXofState_78 *uu____0 = self; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_inputs[1U]; ++ memcpy(copy_of_inputs, inputs, (size_t)1U * sizeof(Eurydice_slice)); ++ size_t input_remainder_len = ++ libcrux_sha3_generic_keccak_absorb_full_9d_7a0(uu____0, copy_of_inputs); ++ size_t input_len = Eurydice_slice_len(inputs[0U], uint8_t); ++ uint8_t blocks[1U][200U] = { { 0U } }; ++ { ++ size_t i = (size_t)0U; ++ if (self->buf_len > (size_t)0U) { ++ Eurydice_slice uu____2 = Eurydice_array_to_subslice2( ++ blocks[i], (size_t)0U, self->buf_len, uint8_t); ++ Eurydice_slice_copy(uu____2, ++ Eurydice_array_to_subslice2(self->buf[i], (size_t)0U, ++ self->buf_len, uint8_t), ++ uint8_t); ++ } ++ if (input_remainder_len > (size_t)0U) { ++ Eurydice_slice uu____3 = Eurydice_array_to_subslice2( ++ blocks[i], self->buf_len, self->buf_len + input_remainder_len, ++ uint8_t); ++ Eurydice_slice_copy( ++ uu____3, ++ Eurydice_slice_subslice_from( ++ inputs[i], input_len - input_remainder_len, uint8_t, size_t), ++ uint8_t); ++ } ++ blocks[i][self->buf_len + input_remainder_len] = 31U; ++ size_t uu____4 = i; ++ size_t uu____5 = (size_t)168U - (size_t)1U; ++ blocks[uu____4][uu____5] = (uint32_t)blocks[uu____4][uu____5] | 128U; ++ } ++ uint64_t(*uu____6)[5U] = self->inner.st; ++ uint8_t uu____7[1U][200U]; ++ memcpy(uu____7, blocks, (size_t)1U * sizeof(uint8_t[200U])); ++ libcrux_sha3_portable_keccak_load_block_full_5a_05(uu____6, uu____7); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&self->inner); ++} ++ ++/** ++This function found in impl ++{(libcrux_sha3::portable::incremental::XofAbsorb<168: usize> for ++libcrux_sha3::portable::incremental::Shake128Absorb)} ++*/ ++static inline libcrux_sha3_generic_keccak_KeccakXofState_78 ++libcrux_sha3_portable_incremental_absorb_final_1c( ++ libcrux_sha3_generic_keccak_KeccakXofState_78 self, Eurydice_slice input) ++{ ++ Eurydice_slice buf[1U] = { input }; ++ libcrux_sha3_generic_keccak_absorb_final_9d_b60(&self, buf); ++ return self; ++} ++ ++/** ++ An all zero block ++*/ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.zero_block_9d ++with types uint64_t ++with const generics ++- PARALLEL_LANES= 1 ++- RATE= 168 ++*/ ++static inline void ++libcrux_sha3_generic_keccak_zero_block_9d_5e0( ++ uint8_t ret[168U]) ++{ ++ ret[0U] = 0U; ++ ret[1U] = 0U; ++ ret[2U] = 0U; ++ ret[3U] = 0U; ++ ret[4U] = 0U; ++ ret[5U] = 0U; ++ ret[6U] = 0U; ++ ret[7U] = 0U; ++ ret[8U] = 0U; ++ ret[9U] = 0U; ++ ret[10U] = 0U; ++ ret[11U] = 0U; ++ ret[12U] = 0U; ++ ret[13U] = 0U; ++ ret[14U] = 0U; ++ ret[15U] = 0U; ++ ret[16U] = 0U; ++ ret[17U] = 0U; ++ ret[18U] = 0U; ++ ret[19U] = 0U; ++ ret[20U] = 0U; ++ ret[21U] = 0U; ++ ret[22U] = 0U; ++ ret[23U] = 0U; ++ ret[24U] = 0U; ++ ret[25U] = 0U; ++ ret[26U] = 0U; ++ ret[27U] = 0U; ++ ret[28U] = 0U; ++ ret[29U] = 0U; ++ ret[30U] = 0U; ++ ret[31U] = 0U; ++ ret[32U] = 0U; ++ ret[33U] = 0U; ++ ret[34U] = 0U; ++ ret[35U] = 0U; ++ ret[36U] = 0U; ++ ret[37U] = 0U; ++ ret[38U] = 0U; ++ ret[39U] = 0U; ++ ret[40U] = 0U; ++ ret[41U] = 0U; ++ ret[42U] = 0U; ++ ret[43U] = 0U; ++ ret[44U] = 0U; ++ ret[45U] = 0U; ++ ret[46U] = 0U; ++ ret[47U] = 0U; ++ ret[48U] = 0U; ++ ret[49U] = 0U; ++ ret[50U] = 0U; ++ ret[51U] = 0U; ++ ret[52U] = 0U; ++ ret[53U] = 0U; ++ ret[54U] = 0U; ++ ret[55U] = 0U; ++ ret[56U] = 0U; ++ ret[57U] = 0U; ++ ret[58U] = 0U; ++ ret[59U] = 0U; ++ ret[60U] = 0U; ++ ret[61U] = 0U; ++ ret[62U] = 0U; ++ ret[63U] = 0U; ++ ret[64U] = 0U; ++ ret[65U] = 0U; ++ ret[66U] = 0U; ++ ret[67U] = 0U; ++ ret[68U] = 0U; ++ ret[69U] = 0U; ++ ret[70U] = 0U; ++ ret[71U] = 0U; ++ ret[72U] = 0U; ++ ret[73U] = 0U; ++ ret[74U] = 0U; ++ ret[75U] = 0U; ++ ret[76U] = 0U; ++ ret[77U] = 0U; ++ ret[78U] = 0U; ++ ret[79U] = 0U; ++ ret[80U] = 0U; ++ ret[81U] = 0U; ++ ret[82U] = 0U; ++ ret[83U] = 0U; ++ ret[84U] = 0U; ++ ret[85U] = 0U; ++ ret[86U] = 0U; ++ ret[87U] = 0U; ++ ret[88U] = 0U; ++ ret[89U] = 0U; ++ ret[90U] = 0U; ++ ret[91U] = 0U; ++ ret[92U] = 0U; ++ ret[93U] = 0U; ++ ret[94U] = 0U; ++ ret[95U] = 0U; ++ ret[96U] = 0U; ++ ret[97U] = 0U; ++ ret[98U] = 0U; ++ ret[99U] = 0U; ++ ret[100U] = 0U; ++ ret[101U] = 0U; ++ ret[102U] = 0U; ++ ret[103U] = 0U; ++ ret[104U] = 0U; ++ ret[105U] = 0U; ++ ret[106U] = 0U; ++ ret[107U] = 0U; ++ ret[108U] = 0U; ++ ret[109U] = 0U; ++ ret[110U] = 0U; ++ ret[111U] = 0U; ++ ret[112U] = 0U; ++ ret[113U] = 0U; ++ ret[114U] = 0U; ++ ret[115U] = 0U; ++ ret[116U] = 0U; ++ ret[117U] = 0U; ++ ret[118U] = 0U; ++ ret[119U] = 0U; ++ ret[120U] = 0U; ++ ret[121U] = 0U; ++ ret[122U] = 0U; ++ ret[123U] = 0U; ++ ret[124U] = 0U; ++ ret[125U] = 0U; ++ ret[126U] = 0U; ++ ret[127U] = 0U; ++ ret[128U] = 0U; ++ ret[129U] = 0U; ++ ret[130U] = 0U; ++ ret[131U] = 0U; ++ ret[132U] = 0U; ++ ret[133U] = 0U; ++ ret[134U] = 0U; ++ ret[135U] = 0U; ++ ret[136U] = 0U; ++ ret[137U] = 0U; ++ ret[138U] = 0U; ++ ret[139U] = 0U; ++ ret[140U] = 0U; ++ ret[141U] = 0U; ++ ret[142U] = 0U; ++ ret[143U] = 0U; ++ ret[144U] = 0U; ++ ret[145U] = 0U; ++ ret[146U] = 0U; ++ ret[147U] = 0U; ++ ret[148U] = 0U; ++ ret[149U] = 0U; ++ ret[150U] = 0U; ++ ret[151U] = 0U; ++ ret[152U] = 0U; ++ ret[153U] = 0U; ++ ret[154U] = 0U; ++ ret[155U] = 0U; ++ ret[156U] = 0U; ++ ret[157U] = 0U; ++ ret[158U] = 0U; ++ ret[159U] = 0U; ++ ret[160U] = 0U; ++ ret[161U] = 0U; ++ ret[162U] = 0U; ++ ret[163U] = 0U; ++ ret[164U] = 0U; ++ ret[165U] = 0U; ++ ret[166U] = 0U; ++ ret[167U] = 0U; ++} ++ ++/** ++ Generate a new keccak xof state. ++*/ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.new_9d ++with types uint64_t ++with const generics ++- PARALLEL_LANES= 1 ++- RATE= 168 ++*/ ++static inline libcrux_sha3_generic_keccak_KeccakXofState_78 ++libcrux_sha3_generic_keccak_new_9d_470(void) ++{ ++ libcrux_sha3_generic_keccak_KeccakXofState_78 lit; ++ lit.inner = libcrux_sha3_generic_keccak_new_1e_cf(); ++ uint8_t ret[168U]; ++ libcrux_sha3_generic_keccak_zero_block_9d_5e0(ret); ++ memcpy(lit.buf[0U], ret, (size_t)168U * sizeof(uint8_t)); ++ lit.buf_len = (size_t)0U; ++ lit.sponge = false; ++ return lit; ++} ++ ++/** ++This function found in impl ++{(libcrux_sha3::portable::incremental::XofAbsorb<168: usize> for ++libcrux_sha3::portable::incremental::Shake128Absorb)} ++*/ ++static inline libcrux_sha3_generic_keccak_KeccakXofState_78 ++libcrux_sha3_portable_incremental_new_1c(void) ++{ ++ return libcrux_sha3_generic_keccak_new_9d_470(); ++} ++ ++/** ++ `out` has the exact size we want here. It must be less than or equal to `RATE`. ++*/ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_5a ++with const generics ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_5a_81( ++ uint64_t (*state)[5U], Eurydice_slice out[1U]) ++{ ++ size_t num_full_blocks = Eurydice_slice_len(out[0U], uint8_t) / (size_t)8U; ++ size_t last_block_len = Eurydice_slice_len(out[0U], uint8_t) % (size_t)8U; ++ for (size_t i = (size_t)0U; i < num_full_blocks; i++) { ++ size_t i0 = i; ++ Eurydice_slice uu____0 = Eurydice_slice_subslice2( ++ out[0U], i0 * (size_t)8U, i0 * (size_t)8U + (size_t)8U, uint8_t); ++ uint8_t ret[8U]; ++ core_num__u64_9__to_le_bytes(state[i0 / (size_t)5U][i0 % (size_t)5U], ret); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)8U, ret, uint8_t), uint8_t); ++ } ++ if (last_block_len != (size_t)0U) { ++ Eurydice_slice uu____1 = Eurydice_slice_subslice2( ++ out[0U], num_full_blocks * (size_t)8U, ++ num_full_blocks * (size_t)8U + last_block_len, uint8_t); ++ uint8_t ret[8U]; ++ core_num__u64_9__to_le_bytes( ++ state[num_full_blocks / (size_t)5U][num_full_blocks % (size_t)5U], ret); ++ Eurydice_slice_copy( ++ uu____1, ++ Eurydice_array_to_subslice2(ret, (size_t)0U, last_block_len, uint8_t), ++ uint8_t); ++ } ++} ++ ++/** ++ Squeeze `N` x `LEN` bytes. ++*/ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_9d ++with types uint64_t ++with const generics ++- PARALLEL_LANES= 1 ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_9d_ba( ++ libcrux_sha3_generic_keccak_KeccakXofState_4f *self, ++ Eurydice_slice out[1U]) ++{ ++ if (self->sponge) { ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&self->inner); ++ } ++ size_t out_len = Eurydice_slice_len(out[0U], uint8_t); ++ size_t blocks = out_len / (size_t)136U; ++ size_t last = out_len - out_len % (size_t)136U; ++ size_t mid; ++ if ((size_t)136U >= out_len) { ++ mid = out_len; ++ } else { ++ mid = (size_t)136U; ++ } ++ Eurydice_slice_uint8_t_1size_t__x2 uu____0 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, mid); ++ Eurydice_slice out00[1U]; ++ memcpy(out00, uu____0.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice out_rest[1U]; ++ memcpy(out_rest, uu____0.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_portable_keccak_store_5a_81(self->inner.st, out00); ++ core_ops_range_Range_b3 iter = ++ core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( ++ (CLITERAL(core_ops_range_Range_b3){ .start = (size_t)1U, ++ .end = blocks }), ++ core_ops_range_Range_b3, core_ops_range_Range_b3); ++ while (true) { ++ if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( ++ &iter, size_t, core_option_Option_b3) ++ .tag == core_option_None) { ++ break; ++ } else { ++ Eurydice_slice_uint8_t_1size_t__x2 uu____1 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(out_rest, ++ (size_t)136U); ++ Eurydice_slice out0[1U]; ++ memcpy(out0, uu____1.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice tmp[1U]; ++ memcpy(tmp, uu____1.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&self->inner); ++ libcrux_sha3_portable_keccak_store_5a_81(self->inner.st, out0); ++ memcpy(out_rest, tmp, (size_t)1U * sizeof(Eurydice_slice)); ++ } ++ } ++ if (last < out_len) { ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&self->inner); ++ libcrux_sha3_portable_keccak_store_5a_81(self->inner.st, out_rest); ++ } ++ self->sponge = true; ++} ++ ++/** ++ Shake256 squeeze ++*/ ++/** ++This function found in impl ++{(libcrux_sha3::portable::incremental::XofSqueeze<136: usize> for ++libcrux_sha3::portable::incremental::Shake256Squeeze)#3} ++*/ ++static inline void ++libcrux_sha3_portable_incremental_squeeze_8a( ++ libcrux_sha3_generic_keccak_KeccakXofState_4f *self, Eurydice_slice out) ++{ ++ Eurydice_slice buf[1U] = { out }; ++ libcrux_sha3_generic_keccak_squeeze_9d_ba(self, buf); ++} ++ ++/** ++ `out` has the exact size we want here. It must be less than or equal to `RATE`. ++*/ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_5a ++with const generics ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_5a_810( ++ uint64_t (*state)[5U], Eurydice_slice out[1U]) ++{ ++ size_t num_full_blocks = Eurydice_slice_len(out[0U], uint8_t) / (size_t)8U; ++ size_t last_block_len = Eurydice_slice_len(out[0U], uint8_t) % (size_t)8U; ++ for (size_t i = (size_t)0U; i < num_full_blocks; i++) { ++ size_t i0 = i; ++ Eurydice_slice uu____0 = Eurydice_slice_subslice2( ++ out[0U], i0 * (size_t)8U, i0 * (size_t)8U + (size_t)8U, uint8_t); ++ uint8_t ret[8U]; ++ core_num__u64_9__to_le_bytes(state[i0 / (size_t)5U][i0 % (size_t)5U], ret); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)8U, ret, uint8_t), uint8_t); ++ } ++ if (last_block_len != (size_t)0U) { ++ Eurydice_slice uu____1 = Eurydice_slice_subslice2( ++ out[0U], num_full_blocks * (size_t)8U, ++ num_full_blocks * (size_t)8U + last_block_len, uint8_t); ++ uint8_t ret[8U]; ++ core_num__u64_9__to_le_bytes( ++ state[num_full_blocks / (size_t)5U][num_full_blocks % (size_t)5U], ret); ++ Eurydice_slice_copy( ++ uu____1, ++ Eurydice_array_to_subslice2(ret, (size_t)0U, last_block_len, uint8_t), ++ uint8_t); ++ } ++} ++ ++/** ++ Squeeze `N` x `LEN` bytes. ++*/ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_9d ++with types uint64_t ++with const generics ++- PARALLEL_LANES= 1 ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_9d_ba0( ++ libcrux_sha3_generic_keccak_KeccakXofState_78 *self, ++ Eurydice_slice out[1U]) ++{ ++ if (self->sponge) { ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&self->inner); ++ } ++ size_t out_len = Eurydice_slice_len(out[0U], uint8_t); ++ size_t blocks = out_len / (size_t)168U; ++ size_t last = out_len - out_len % (size_t)168U; ++ size_t mid; ++ if ((size_t)168U >= out_len) { ++ mid = out_len; ++ } else { ++ mid = (size_t)168U; ++ } ++ Eurydice_slice_uint8_t_1size_t__x2 uu____0 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, mid); ++ Eurydice_slice out00[1U]; ++ memcpy(out00, uu____0.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice out_rest[1U]; ++ memcpy(out_rest, uu____0.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_portable_keccak_store_5a_810(self->inner.st, out00); ++ core_ops_range_Range_b3 iter = ++ core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( ++ (CLITERAL(core_ops_range_Range_b3){ .start = (size_t)1U, ++ .end = blocks }), ++ core_ops_range_Range_b3, core_ops_range_Range_b3); ++ while (true) { ++ if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( ++ &iter, size_t, core_option_Option_b3) ++ .tag == core_option_None) { ++ break; ++ } else { ++ Eurydice_slice_uint8_t_1size_t__x2 uu____1 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(out_rest, ++ (size_t)168U); ++ Eurydice_slice out0[1U]; ++ memcpy(out0, uu____1.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice tmp[1U]; ++ memcpy(tmp, uu____1.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&self->inner); ++ libcrux_sha3_portable_keccak_store_5a_810(self->inner.st, out0); ++ memcpy(out_rest, tmp, (size_t)1U * sizeof(Eurydice_slice)); ++ } ++ } ++ if (last < out_len) { ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&self->inner); ++ libcrux_sha3_portable_keccak_store_5a_810(self->inner.st, out_rest); ++ } ++ self->sponge = true; ++} ++ ++/** ++ Shake128 squeeze ++*/ ++/** ++This function found in impl ++{(libcrux_sha3::portable::incremental::XofSqueeze<168: usize> for ++libcrux_sha3::portable::incremental::Shake128Squeeze)#1} ++*/ ++static inline void ++libcrux_sha3_portable_incremental_squeeze_10( ++ libcrux_sha3_generic_keccak_KeccakXofState_78 *self, Eurydice_slice out) ++{ ++ Eurydice_slice buf[1U] = { out }; ++ libcrux_sha3_generic_keccak_squeeze_9d_ba0(self, buf); ++} ++ ++/** ++This function found in impl {(core::clone::Clone for ++libcrux_sha3::portable::KeccakState)} ++*/ ++static inline libcrux_sha3_generic_keccak_KeccakState_48 ++libcrux_sha3_portable_clone_3d( ++ libcrux_sha3_generic_keccak_KeccakState_48 *self) ++{ ++ return self[0U]; ++} ++ ++/** ++This function found in impl {(core::convert::From for ++u32)#1} ++*/ ++static inline uint32_t ++libcrux_sha3_from_eb(libcrux_sha3_Algorithm v) ++{ ++ uint32_t uu____0; ++ switch (v) { ++ case libcrux_sha3_Sha224: { ++ uu____0 = 1U; ++ break; ++ } ++ case libcrux_sha3_Sha256: { ++ uu____0 = 2U; ++ break; ++ } ++ case libcrux_sha3_Sha384: { ++ uu____0 = 3U; ++ break; ++ } ++ case libcrux_sha3_Sha512: { ++ uu____0 = 4U; ++ break; ++ } ++ default: { ++ KRML_HOST_EPRINTF("KaRaMeL incomplete match at %s:%d\n", __FILE__, ++ __LINE__); ++ KRML_HOST_EXIT(253U); ++ } ++ } ++ return uu____0; ++} ++ ++/** ++This function found in impl {(core::convert::From for ++libcrux_sha3::Algorithm)} ++*/ ++static inline libcrux_sha3_Algorithm ++libcrux_sha3_from_2d(uint32_t v) ++{ ++ libcrux_sha3_Algorithm uu____0; ++ switch (v) { ++ case 1U: { ++ uu____0 = libcrux_sha3_Sha224; ++ break; ++ } ++ case 2U: { ++ uu____0 = libcrux_sha3_Sha256; ++ break; ++ } ++ case 3U: { ++ uu____0 = libcrux_sha3_Sha384; ++ break; ++ } ++ case 4U: { ++ uu____0 = libcrux_sha3_Sha512; ++ break; ++ } ++ default: { ++ KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, ++ "panic!"); ++ KRML_HOST_EXIT(255U); ++ } ++ } ++ return uu____0; ++} ++ ++typedef uint8_t libcrux_sha3_Sha3_512Digest[64U]; ++ ++typedef uint8_t libcrux_sha3_Sha3_384Digest[48U]; ++ ++typedef uint8_t libcrux_sha3_Sha3_256Digest[32U]; ++ ++typedef uint8_t libcrux_sha3_Sha3_224Digest[28U]; ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#define __internal_libcrux_sha3_internal_H_DEFINED ++#endif +diff -up ./lib/freebl/verified/libcrux_core.c.mlkem ./lib/freebl/verified/libcrux_core.c +--- ./lib/freebl/verified/libcrux_core.c.mlkem 2024-10-31 14:54:15.463515937 -0700 ++++ ./lib/freebl/verified/libcrux_core.c 2024-10-31 14:54:15.463515937 -0700 +@@ -0,0 +1,712 @@ ++/* ++ * SPDX-FileCopyrightText: 2024 Cryspen Sarl ++ * ++ * SPDX-License-Identifier: MIT or Apache-2.0 ++ * ++ * This code was generated with the following revisions: ++ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d ++ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46 ++ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0 ++ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7 ++ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb ++ */ ++ ++#include "internal/libcrux_core.h" ++ ++/** ++ Return 1 if `value` is not zero and 0 otherwise. ++*/ ++static uint8_t ++inz(uint8_t value) ++{ ++ uint16_t value0 = (uint16_t)value; ++ uint16_t result = (((uint32_t)value0 | ++ (uint32_t)core_num__u16_7__wrapping_add(~value0, 1U)) & ++ 0xFFFFU) >> ++ 8U & ++ 1U; ++ return (uint8_t)result; ++} ++ ++static KRML_NOINLINE uint8_t ++is_non_zero(uint8_t value) ++{ ++ return inz(value); ++} ++ ++/** ++ Return 1 if the bytes of `lhs` and `rhs` do not exactly ++ match and 0 otherwise. ++*/ ++static uint8_t ++compare(Eurydice_slice lhs, Eurydice_slice rhs) ++{ ++ uint8_t r = 0U; ++ for (size_t i = (size_t)0U; i < Eurydice_slice_len(lhs, uint8_t); i++) { ++ size_t i0 = i; ++ r = (uint32_t)r | ++ ((uint32_t)Eurydice_slice_index(lhs, i0, uint8_t, uint8_t *) ^ ++ (uint32_t)Eurydice_slice_index(rhs, i0, uint8_t, uint8_t *)); ++ } ++ return is_non_zero(r); ++} ++ ++static KRML_NOINLINE uint8_t ++compare_ciphertexts_in_constant_time(Eurydice_slice lhs, Eurydice_slice rhs) ++{ ++ return compare(lhs, rhs); ++} ++ ++/** ++ If `selector` is not zero, return the bytes in `rhs`; return the bytes in ++ `lhs` otherwise. ++*/ ++static void ++select_ct(Eurydice_slice lhs, Eurydice_slice rhs, uint8_t selector, ++ uint8_t ret[32U]) ++{ ++ uint8_t mask = core_num__u8_6__wrapping_sub(is_non_zero(selector), 1U); ++ uint8_t out[32U] = { 0U }; ++ for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE; ++ i++) { ++ size_t i0 = i; ++ out[i0] = ((uint32_t)Eurydice_slice_index(lhs, i0, uint8_t, uint8_t *) & ++ (uint32_t)mask) | ++ ((uint32_t)Eurydice_slice_index(rhs, i0, uint8_t, uint8_t *) & ++ (uint32_t)~mask); ++ } ++ memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); ++} ++ ++static KRML_NOINLINE void ++select_shared_secret_in_constant_time( ++ Eurydice_slice lhs, Eurydice_slice rhs, uint8_t selector, ++ uint8_t ret[32U]) ++{ ++ select_ct(lhs, rhs, selector, ret); ++} ++ ++void ++libcrux_ml_kem_constant_time_ops_compare_ciphertexts_select_shared_secret_in_constant_time( ++ Eurydice_slice lhs_c, Eurydice_slice rhs_c, Eurydice_slice lhs_s, ++ Eurydice_slice rhs_s, uint8_t ret[32U]) ++{ ++ uint8_t selector = compare_ciphertexts_in_constant_time(lhs_c, rhs_c); ++ uint8_t ret0[32U]; ++ select_shared_secret_in_constant_time(lhs_s, rhs_s, selector, ret0); ++ memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemPublicKey)#14} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_b6 ++with const generics ++- SIZE= 1568 ++*/ ++libcrux_ml_kem_types_MlKemPublicKey_1f ++libcrux_ml_kem_types_from_b6_961( ++ uint8_t value[1568U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_value[1568U]; ++ memcpy(copy_of_value, value, (size_t)1568U * sizeof(uint8_t)); ++ libcrux_ml_kem_types_MlKemPublicKey_1f lit; ++ memcpy(lit.value, copy_of_value, (size_t)1568U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++ Create a new [`MlKemKeyPair`] from the secret and public key. ++*/ ++/** ++This function found in impl ++{libcrux_ml_kem::types::MlKemKeyPair} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_17 ++with const generics ++- PRIVATE_KEY_SIZE= 3168 ++- PUBLIC_KEY_SIZE= 1568 ++*/ ++libcrux_ml_kem_mlkem1024_MlKem1024KeyPair ++libcrux_ml_kem_types_from_17_821( ++ libcrux_ml_kem_types_MlKemPrivateKey_95 sk, ++ libcrux_ml_kem_types_MlKemPublicKey_1f pk) ++{ ++ return ( ++ CLITERAL(libcrux_ml_kem_mlkem1024_MlKem1024KeyPair){ .sk = sk, .pk = pk }); ++} ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemPrivateKey)#8} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_05 ++with const generics ++- SIZE= 3168 ++*/ ++libcrux_ml_kem_types_MlKemPrivateKey_95 ++libcrux_ml_kem_types_from_05_891( ++ uint8_t value[3168U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_value[3168U]; ++ memcpy(copy_of_value, value, (size_t)3168U * sizeof(uint8_t)); ++ libcrux_ml_kem_types_MlKemPrivateKey_95 lit; ++ memcpy(lit.value, copy_of_value, (size_t)3168U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemCiphertext)#2} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_01 ++with const generics ++- SIZE= 1568 ++*/ ++libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext ++libcrux_ml_kem_types_from_01_331( ++ uint8_t value[1568U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_value[1568U]; ++ memcpy(copy_of_value, value, (size_t)1568U * sizeof(uint8_t)); ++ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext lit; ++ memcpy(lit.value, copy_of_value, (size_t)1568U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++ A reference to the raw byte slice. ++*/ ++/** ++This function found in impl {libcrux_ml_kem::types::MlKemPublicKey#18} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.as_slice_cb ++with const generics ++- SIZE= 1568 ++*/ ++uint8_t * ++libcrux_ml_kem_types_as_slice_cb_3d1( ++ libcrux_ml_kem_types_MlKemPublicKey_1f *self) ++{ ++ return self->value; ++} ++ ++/** ++This function found in impl {(core::convert::AsRef<@Slice> for ++libcrux_ml_kem::types::MlKemCiphertext)#1} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.as_ref_00 ++with const generics ++- SIZE= 1568 ++*/ ++Eurydice_slice ++libcrux_ml_kem_types_as_ref_00_d81( ++ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *self) ++{ ++ return Eurydice_array_to_slice((size_t)1568U, self->value, uint8_t); ++} ++ ++/** ++ Pad the `slice` with `0`s at the end. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.utils.into_padded_array ++with const generics ++- LEN= 1600 ++*/ ++void ++libcrux_ml_kem_utils_into_padded_array_6d4(Eurydice_slice slice, ++ uint8_t ret[1600U]) ++{ ++ uint8_t out[1600U] = { 0U }; ++ uint8_t *uu____0 = out; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2(uu____0, (size_t)0U, ++ Eurydice_slice_len(slice, uint8_t), uint8_t), ++ slice, uint8_t); ++ memcpy(ret, out, (size_t)1600U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemPublicKey)#14} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_b6 ++with const generics ++- SIZE= 1184 ++*/ ++libcrux_ml_kem_types_MlKemPublicKey_15 ++libcrux_ml_kem_types_from_b6_960( ++ uint8_t value[1184U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_value[1184U]; ++ memcpy(copy_of_value, value, (size_t)1184U * sizeof(uint8_t)); ++ libcrux_ml_kem_types_MlKemPublicKey_15 lit; ++ memcpy(lit.value, copy_of_value, (size_t)1184U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++ Create a new [`MlKemKeyPair`] from the secret and public key. ++*/ ++/** ++This function found in impl ++{libcrux_ml_kem::types::MlKemKeyPair} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_17 ++with const generics ++- PRIVATE_KEY_SIZE= 2400 ++- PUBLIC_KEY_SIZE= 1184 ++*/ ++libcrux_ml_kem_mlkem768_MlKem768KeyPair ++libcrux_ml_kem_types_from_17_820( ++ libcrux_ml_kem_types_MlKemPrivateKey_55 sk, ++ libcrux_ml_kem_types_MlKemPublicKey_15 pk) ++{ ++ return ( ++ CLITERAL(libcrux_ml_kem_mlkem768_MlKem768KeyPair){ .sk = sk, .pk = pk }); ++} ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemPrivateKey)#8} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_05 ++with const generics ++- SIZE= 2400 ++*/ ++libcrux_ml_kem_types_MlKemPrivateKey_55 ++libcrux_ml_kem_types_from_05_890( ++ uint8_t value[2400U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_value[2400U]; ++ memcpy(copy_of_value, value, (size_t)2400U * sizeof(uint8_t)); ++ libcrux_ml_kem_types_MlKemPrivateKey_55 lit; ++ memcpy(lit.value, copy_of_value, (size_t)2400U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemCiphertext)#2} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_01 ++with const generics ++- SIZE= 1088 ++*/ ++libcrux_ml_kem_mlkem768_MlKem768Ciphertext ++libcrux_ml_kem_types_from_01_330( ++ uint8_t value[1088U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_value[1088U]; ++ memcpy(copy_of_value, value, (size_t)1088U * sizeof(uint8_t)); ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext lit; ++ memcpy(lit.value, copy_of_value, (size_t)1088U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++ A reference to the raw byte slice. ++*/ ++/** ++This function found in impl {libcrux_ml_kem::types::MlKemPublicKey#18} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.as_slice_cb ++with const generics ++- SIZE= 1184 ++*/ ++uint8_t * ++libcrux_ml_kem_types_as_slice_cb_3d0( ++ libcrux_ml_kem_types_MlKemPublicKey_15 *self) ++{ ++ return self->value; ++} ++ ++/** ++This function found in impl {(core::convert::AsRef<@Slice> for ++libcrux_ml_kem::types::MlKemCiphertext)#1} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.as_ref_00 ++with const generics ++- SIZE= 1088 ++*/ ++Eurydice_slice ++libcrux_ml_kem_types_as_ref_00_d80( ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext *self) ++{ ++ return Eurydice_array_to_slice((size_t)1088U, self->value, uint8_t); ++} ++ ++/** ++ Pad the `slice` with `0`s at the end. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.utils.into_padded_array ++with const generics ++- LEN= 1120 ++*/ ++void ++libcrux_ml_kem_utils_into_padded_array_6d3(Eurydice_slice slice, ++ uint8_t ret[1120U]) ++{ ++ uint8_t out[1120U] = { 0U }; ++ uint8_t *uu____0 = out; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2(uu____0, (size_t)0U, ++ Eurydice_slice_len(slice, uint8_t), uint8_t), ++ slice, uint8_t); ++ memcpy(ret, out, (size_t)1120U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemPublicKey)#14} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_b6 ++with const generics ++- SIZE= 800 ++*/ ++libcrux_ml_kem_types_MlKemPublicKey_be ++libcrux_ml_kem_types_from_b6_96( ++ uint8_t value[800U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_value[800U]; ++ memcpy(copy_of_value, value, (size_t)800U * sizeof(uint8_t)); ++ libcrux_ml_kem_types_MlKemPublicKey_be lit; ++ memcpy(lit.value, copy_of_value, (size_t)800U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++ Create a new [`MlKemKeyPair`] from the secret and public key. ++*/ ++/** ++This function found in impl ++{libcrux_ml_kem::types::MlKemKeyPair} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_17 ++with const generics ++- PRIVATE_KEY_SIZE= 1632 ++- PUBLIC_KEY_SIZE= 800 ++*/ ++libcrux_ml_kem_types_MlKemKeyPair_cb ++libcrux_ml_kem_types_from_17_82( ++ libcrux_ml_kem_types_MlKemPrivateKey_5e sk, ++ libcrux_ml_kem_types_MlKemPublicKey_be pk) ++{ ++ return (CLITERAL(libcrux_ml_kem_types_MlKemKeyPair_cb){ .sk = sk, .pk = pk }); ++} ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemPrivateKey)#8} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_05 ++with const generics ++- SIZE= 1632 ++*/ ++libcrux_ml_kem_types_MlKemPrivateKey_5e ++libcrux_ml_kem_types_from_05_89( ++ uint8_t value[1632U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_value[1632U]; ++ memcpy(copy_of_value, value, (size_t)1632U * sizeof(uint8_t)); ++ libcrux_ml_kem_types_MlKemPrivateKey_5e lit; ++ memcpy(lit.value, copy_of_value, (size_t)1632U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++This function found in impl {core::result::Result} ++*/ ++/** ++A monomorphic instance of core.result.unwrap_41 ++with types uint8_t[32size_t], core_array_TryFromSliceError ++ ++*/ ++void ++core_result_unwrap_41_33(core_result_Result_00 self, uint8_t ret[32U]) ++{ ++ if (self.tag == core_result_Ok) { ++ uint8_t f0[32U]; ++ memcpy(f0, self.val.case_Ok, (size_t)32U * sizeof(uint8_t)); ++ memcpy(ret, f0, (size_t)32U * sizeof(uint8_t)); ++ } else { ++ KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, ++ "unwrap not Ok"); ++ KRML_HOST_EXIT(255U); ++ } ++} ++ ++/** ++This function found in impl {(core::convert::From<@Array> for ++libcrux_ml_kem::types::MlKemCiphertext)#2} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.from_01 ++with const generics ++- SIZE= 768 ++*/ ++libcrux_ml_kem_types_MlKemCiphertext_e8 ++libcrux_ml_kem_types_from_01_33( ++ uint8_t value[768U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_value[768U]; ++ memcpy(copy_of_value, value, (size_t)768U * sizeof(uint8_t)); ++ libcrux_ml_kem_types_MlKemCiphertext_e8 lit; ++ memcpy(lit.value, copy_of_value, (size_t)768U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++ A reference to the raw byte slice. ++*/ ++/** ++This function found in impl {libcrux_ml_kem::types::MlKemPublicKey#18} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.as_slice_cb ++with const generics ++- SIZE= 800 ++*/ ++uint8_t * ++libcrux_ml_kem_types_as_slice_cb_3d( ++ libcrux_ml_kem_types_MlKemPublicKey_be *self) ++{ ++ return self->value; ++} ++ ++/** ++ Pad the `slice` with `0`s at the end. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.utils.into_padded_array ++with const generics ++- LEN= 33 ++*/ ++void ++libcrux_ml_kem_utils_into_padded_array_6d2(Eurydice_slice slice, ++ uint8_t ret[33U]) ++{ ++ uint8_t out[33U] = { 0U }; ++ uint8_t *uu____0 = out; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2(uu____0, (size_t)0U, ++ Eurydice_slice_len(slice, uint8_t), uint8_t), ++ slice, uint8_t); ++ memcpy(ret, out, (size_t)33U * sizeof(uint8_t)); ++} ++ ++/** ++ Pad the `slice` with `0`s at the end. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.utils.into_padded_array ++with const generics ++- LEN= 34 ++*/ ++void ++libcrux_ml_kem_utils_into_padded_array_6d1(Eurydice_slice slice, ++ uint8_t ret[34U]) ++{ ++ uint8_t out[34U] = { 0U }; ++ uint8_t *uu____0 = out; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2(uu____0, (size_t)0U, ++ Eurydice_slice_len(slice, uint8_t), uint8_t), ++ slice, uint8_t); ++ memcpy(ret, out, (size_t)34U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(core::convert::AsRef<@Slice> for ++libcrux_ml_kem::types::MlKemCiphertext)#1} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.types.as_ref_00 ++with const generics ++- SIZE= 768 ++*/ ++Eurydice_slice ++libcrux_ml_kem_types_as_ref_00_d8( ++ libcrux_ml_kem_types_MlKemCiphertext_e8 *self) ++{ ++ return Eurydice_array_to_slice((size_t)768U, self->value, uint8_t); ++} ++ ++/** ++ Pad the `slice` with `0`s at the end. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.utils.into_padded_array ++with const generics ++- LEN= 800 ++*/ ++void ++libcrux_ml_kem_utils_into_padded_array_6d0(Eurydice_slice slice, ++ uint8_t ret[800U]) ++{ ++ uint8_t out[800U] = { 0U }; ++ uint8_t *uu____0 = out; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2(uu____0, (size_t)0U, ++ Eurydice_slice_len(slice, uint8_t), uint8_t), ++ slice, uint8_t); ++ memcpy(ret, out, (size_t)800U * sizeof(uint8_t)); ++} ++ ++/** ++ Pad the `slice` with `0`s at the end. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.utils.into_padded_array ++with const generics ++- LEN= 64 ++*/ ++void ++libcrux_ml_kem_utils_into_padded_array_6d(Eurydice_slice slice, ++ uint8_t ret[64U]) ++{ ++ uint8_t out[64U] = { 0U }; ++ uint8_t *uu____0 = out; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2(uu____0, (size_t)0U, ++ Eurydice_slice_len(slice, uint8_t), uint8_t), ++ slice, uint8_t); ++ memcpy(ret, out, (size_t)64U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {core::result::Result} ++*/ ++/** ++A monomorphic instance of core.result.unwrap_41 ++with types uint8_t[24size_t], core_array_TryFromSliceError ++ ++*/ ++void ++core_result_unwrap_41_76(core_result_Result_6f self, uint8_t ret[24U]) ++{ ++ if (self.tag == core_result_Ok) { ++ uint8_t f0[24U]; ++ memcpy(f0, self.val.case_Ok, (size_t)24U * sizeof(uint8_t)); ++ memcpy(ret, f0, (size_t)24U * sizeof(uint8_t)); ++ } else { ++ KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, ++ "unwrap not Ok"); ++ KRML_HOST_EXIT(255U); ++ } ++} ++ ++/** ++This function found in impl {core::result::Result} ++*/ ++/** ++A monomorphic instance of core.result.unwrap_41 ++with types uint8_t[20size_t], core_array_TryFromSliceError ++ ++*/ ++void ++core_result_unwrap_41_ea(core_result_Result_7a self, uint8_t ret[20U]) ++{ ++ if (self.tag == core_result_Ok) { ++ uint8_t f0[20U]; ++ memcpy(f0, self.val.case_Ok, (size_t)20U * sizeof(uint8_t)); ++ memcpy(ret, f0, (size_t)20U * sizeof(uint8_t)); ++ } else { ++ KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, ++ "unwrap not Ok"); ++ KRML_HOST_EXIT(255U); ++ } ++} ++ ++/** ++This function found in impl {core::result::Result} ++*/ ++/** ++A monomorphic instance of core.result.unwrap_41 ++with types uint8_t[10size_t], core_array_TryFromSliceError ++ ++*/ ++void ++core_result_unwrap_41_07(core_result_Result_cd self, uint8_t ret[10U]) ++{ ++ if (self.tag == core_result_Ok) { ++ uint8_t f0[10U]; ++ memcpy(f0, self.val.case_Ok, (size_t)10U * sizeof(uint8_t)); ++ memcpy(ret, f0, (size_t)10U * sizeof(uint8_t)); ++ } else { ++ KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, ++ "unwrap not Ok"); ++ KRML_HOST_EXIT(255U); ++ } ++} ++ ++/** ++This function found in impl {core::result::Result} ++*/ ++/** ++A monomorphic instance of core.result.unwrap_41 ++with types int16_t[16size_t], core_array_TryFromSliceError ++ ++*/ ++void ++core_result_unwrap_41_30(core_result_Result_c0 self, int16_t ret[16U]) ++{ ++ if (self.tag == core_result_Ok) { ++ int16_t f0[16U]; ++ memcpy(f0, self.val.case_Ok, (size_t)16U * sizeof(int16_t)); ++ memcpy(ret, f0, (size_t)16U * sizeof(int16_t)); ++ } else { ++ KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, ++ "unwrap not Ok"); ++ KRML_HOST_EXIT(255U); ++ } ++} ++ ++/** ++This function found in impl {core::result::Result} ++*/ ++/** ++A monomorphic instance of core.result.unwrap_41 ++with types uint8_t[8size_t], core_array_TryFromSliceError ++ ++*/ ++void ++core_result_unwrap_41_0e(core_result_Result_56 self, uint8_t ret[8U]) ++{ ++ if (self.tag == core_result_Ok) { ++ uint8_t f0[8U]; ++ memcpy(f0, self.val.case_Ok, (size_t)8U * sizeof(uint8_t)); ++ memcpy(ret, f0, (size_t)8U * sizeof(uint8_t)); ++ } else { ++ KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, ++ "unwrap not Ok"); ++ KRML_HOST_EXIT(255U); ++ } ++} +diff -up ./lib/freebl/verified/libcrux_core.h.mlkem ./lib/freebl/verified/libcrux_core.h +--- ./lib/freebl/verified/libcrux_core.h.mlkem 2024-10-31 14:54:15.463515937 -0700 ++++ ./lib/freebl/verified/libcrux_core.h 2024-10-31 14:54:15.463515937 -0700 +@@ -0,0 +1,219 @@ ++/* ++ * SPDX-FileCopyrightText: 2024 Cryspen Sarl ++ * ++ * SPDX-License-Identifier: MIT or Apache-2.0 ++ * ++ * This code was generated with the following revisions: ++ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d ++ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46 ++ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0 ++ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7 ++ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb ++ */ ++ ++#ifndef __libcrux_core_H ++#define __libcrux_core_H ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++#include "eurydice_glue.h" ++ ++/** ++A monomorphic instance of core.ops.range.Range ++with types size_t ++ ++*/ ++typedef struct core_ops_range_Range_b3_s { ++ size_t start; ++ size_t end; ++} core_ops_range_Range_b3; ++ ++#define core_result_Ok 0 ++#define core_result_Err 1 ++ ++typedef uint8_t core_result_Result_86_tags; ++ ++#define core_option_None 0 ++#define core_option_Some 1 ++ ++typedef uint8_t core_option_Option_ef_tags; ++ ++/** ++A monomorphic instance of core.option.Option ++with types size_t ++ ++*/ ++typedef struct core_option_Option_b3_s { ++ core_option_Option_ef_tags tag; ++ size_t f0; ++} core_option_Option_b3; ++ ++static inline uint64_t core_num__u64_9__from_le_bytes(uint8_t x0[8U]); ++ ++static inline void core_num__u64_9__to_le_bytes(uint64_t x0, uint8_t x1[8U]); ++ ++/** ++A monomorphic instance of libcrux_ml_kem.types.MlKemPublicKey ++with const generics ++- $1568size_t ++*/ ++typedef struct libcrux_ml_kem_types_MlKemPublicKey_1f_s { ++ uint8_t value[1568U]; ++} libcrux_ml_kem_types_MlKemPublicKey_1f; ++ ++/** ++A monomorphic instance of libcrux_ml_kem.types.MlKemPrivateKey ++with const generics ++- $3168size_t ++*/ ++typedef struct libcrux_ml_kem_types_MlKemPrivateKey_95_s { ++ uint8_t value[3168U]; ++} libcrux_ml_kem_types_MlKemPrivateKey_95; ++ ++typedef struct libcrux_ml_kem_mlkem1024_MlKem1024KeyPair_s { ++ libcrux_ml_kem_types_MlKemPrivateKey_95 sk; ++ libcrux_ml_kem_types_MlKemPublicKey_1f pk; ++} libcrux_ml_kem_mlkem1024_MlKem1024KeyPair; ++ ++typedef struct libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext_s { ++ uint8_t value[1568U]; ++} libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext; ++ ++/** ++A monomorphic instance of K. ++with types libcrux_ml_kem_types_MlKemCiphertext[[$1568size_t]], ++uint8_t[32size_t] ++ ++*/ ++typedef struct tuple_21_s { ++ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext fst; ++ uint8_t snd[32U]; ++} tuple_21; ++ ++/** ++A monomorphic instance of libcrux_ml_kem.types.MlKemPublicKey ++with const generics ++- $1184size_t ++*/ ++typedef struct libcrux_ml_kem_types_MlKemPublicKey_15_s { ++ uint8_t value[1184U]; ++} libcrux_ml_kem_types_MlKemPublicKey_15; ++ ++/** ++A monomorphic instance of libcrux_ml_kem.types.MlKemPrivateKey ++with const generics ++- $2400size_t ++*/ ++typedef struct libcrux_ml_kem_types_MlKemPrivateKey_55_s { ++ uint8_t value[2400U]; ++} libcrux_ml_kem_types_MlKemPrivateKey_55; ++ ++typedef struct libcrux_ml_kem_mlkem768_MlKem768KeyPair_s { ++ libcrux_ml_kem_types_MlKemPrivateKey_55 sk; ++ libcrux_ml_kem_types_MlKemPublicKey_15 pk; ++} libcrux_ml_kem_mlkem768_MlKem768KeyPair; ++ ++typedef struct libcrux_ml_kem_mlkem768_MlKem768Ciphertext_s { ++ uint8_t value[1088U]; ++} libcrux_ml_kem_mlkem768_MlKem768Ciphertext; ++ ++/** ++A monomorphic instance of K. ++with types libcrux_ml_kem_types_MlKemCiphertext[[$1088size_t]], ++uint8_t[32size_t] ++ ++*/ ++typedef struct tuple_3c_s { ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext fst; ++ uint8_t snd[32U]; ++} tuple_3c; ++ ++/** ++A monomorphic instance of libcrux_ml_kem.types.MlKemPublicKey ++with const generics ++- $800size_t ++*/ ++typedef struct libcrux_ml_kem_types_MlKemPublicKey_be_s { ++ uint8_t value[800U]; ++} libcrux_ml_kem_types_MlKemPublicKey_be; ++ ++/** ++A monomorphic instance of libcrux_ml_kem.types.MlKemPrivateKey ++with const generics ++- $1632size_t ++*/ ++typedef struct libcrux_ml_kem_types_MlKemPrivateKey_5e_s { ++ uint8_t value[1632U]; ++} libcrux_ml_kem_types_MlKemPrivateKey_5e; ++ ++/** ++A monomorphic instance of libcrux_ml_kem.types.MlKemKeyPair ++with const generics ++- $1632size_t ++- $800size_t ++*/ ++typedef struct libcrux_ml_kem_types_MlKemKeyPair_cb_s { ++ libcrux_ml_kem_types_MlKemPrivateKey_5e sk; ++ libcrux_ml_kem_types_MlKemPublicKey_be pk; ++} libcrux_ml_kem_types_MlKemKeyPair_cb; ++ ++/** ++A monomorphic instance of libcrux_ml_kem.types.MlKemCiphertext ++with const generics ++- $768size_t ++*/ ++typedef struct libcrux_ml_kem_types_MlKemCiphertext_e8_s { ++ uint8_t value[768U]; ++} libcrux_ml_kem_types_MlKemCiphertext_e8; ++ ++/** ++A monomorphic instance of K. ++with types libcrux_ml_kem_types_MlKemCiphertext[[$768size_t]], uint8_t[32size_t] ++ ++*/ ++typedef struct tuple_ec_s { ++ libcrux_ml_kem_types_MlKemCiphertext_e8 fst; ++ uint8_t snd[32U]; ++} tuple_ec; ++ ++/** ++A monomorphic instance of core.result.Result ++with types uint8_t[8size_t], core_array_TryFromSliceError ++ ++*/ ++typedef struct core_result_Result_56_s { ++ core_result_Result_86_tags tag; ++ union { ++ uint8_t case_Ok[8U]; ++ core_array_TryFromSliceError case_Err; ++ } val; ++} core_result_Result_56; ++ ++/** ++This function found in impl {core::result::Result} ++*/ ++/** ++A monomorphic instance of core.result.unwrap_41 ++with types uint8_t[8size_t], core_array_TryFromSliceError ++ ++*/ ++void core_result_unwrap_41_0e(core_result_Result_56 self, uint8_t ret[8U]); ++ ++typedef struct Eurydice_slice_uint8_t_x2_s { ++ Eurydice_slice fst; ++ Eurydice_slice snd; ++} Eurydice_slice_uint8_t_x2; ++ ++typedef struct Eurydice_slice_uint8_t_1size_t__x2_s { ++ Eurydice_slice fst[1U]; ++ Eurydice_slice snd[1U]; ++} Eurydice_slice_uint8_t_1size_t__x2; ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#define __libcrux_core_H_DEFINED ++#endif +diff -up ./lib/freebl/verified/libcrux_mlkem768.h.mlkem ./lib/freebl/verified/libcrux_mlkem768.h +--- ./lib/freebl/verified/libcrux_mlkem768.h.mlkem 2024-10-31 14:54:15.463515937 -0700 ++++ ./lib/freebl/verified/libcrux_mlkem768.h 2024-10-31 14:54:15.463515937 -0700 +@@ -0,0 +1,92 @@ ++/* ++ * SPDX-FileCopyrightText: 2024 Cryspen Sarl ++ * ++ * SPDX-License-Identifier: MIT or Apache-2.0 ++ * ++ * This code was generated with the following revisions: ++ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d ++ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46 ++ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0 ++ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7 ++ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb ++ */ ++ ++#ifndef __libcrux_mlkem768_H ++#define __libcrux_mlkem768_H ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++#include "eurydice_glue.h" ++#include "libcrux_core.h" ++ ++#define LIBCRUX_ML_KEM_MLKEM768_VECTOR_U_COMPRESSION_FACTOR_768 ((size_t)10U) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_C1_BLOCK_SIZE_768 \ ++ (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * \ ++ LIBCRUX_ML_KEM_MLKEM768_VECTOR_U_COMPRESSION_FACTOR_768 / (size_t)8U) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_RANK_768 ((size_t)3U) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_C1_SIZE_768 \ ++ (LIBCRUX_ML_KEM_MLKEM768_C1_BLOCK_SIZE_768 * LIBCRUX_ML_KEM_MLKEM768_RANK_768) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_VECTOR_V_COMPRESSION_FACTOR_768 ((size_t)4U) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_C2_SIZE_768 \ ++ (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * \ ++ LIBCRUX_ML_KEM_MLKEM768_VECTOR_V_COMPRESSION_FACTOR_768 / (size_t)8U) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_CIPHERTEXT_SIZE_768 \ ++ (LIBCRUX_ML_KEM_MLKEM768_C1_SIZE_768 + LIBCRUX_ML_KEM_MLKEM768_C2_SIZE_768) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_T_AS_NTT_ENCODED_SIZE_768 \ ++ (LIBCRUX_ML_KEM_MLKEM768_RANK_768 * \ ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * \ ++ LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_COEFFICIENT / (size_t)8U) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_PUBLIC_KEY_SIZE_768 \ ++ (LIBCRUX_ML_KEM_MLKEM768_T_AS_NTT_ENCODED_SIZE_768 + (size_t)32U) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_SECRET_KEY_SIZE_768 \ ++ (LIBCRUX_ML_KEM_MLKEM768_RANK_768 * \ ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * \ ++ LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_COEFFICIENT / (size_t)8U) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_ETA1 ((size_t)2U) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_ETA1_RANDOMNESS_SIZE \ ++ (LIBCRUX_ML_KEM_MLKEM768_ETA1 * (size_t)64U) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_ETA2 ((size_t)2U) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_ETA2_RANDOMNESS_SIZE \ ++ (LIBCRUX_ML_KEM_MLKEM768_ETA2 * (size_t)64U) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_IMPLICIT_REJECTION_HASH_INPUT_SIZE \ ++ (LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE + \ ++ LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_CIPHERTEXT_SIZE_768) ++ ++typedef libcrux_ml_kem_types_MlKemPrivateKey_55 ++ libcrux_ml_kem_mlkem768_MlKem768PrivateKey; ++ ++typedef libcrux_ml_kem_types_MlKemPublicKey_15 ++ libcrux_ml_kem_mlkem768_MlKem768PublicKey; ++ ++#define LIBCRUX_ML_KEM_MLKEM768_RANKED_BYTES_PER_RING_ELEMENT_768 \ ++ (LIBCRUX_ML_KEM_MLKEM768_RANK_768 * \ ++ LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_RING_ELEMENT / (size_t)8U) ++ ++#define LIBCRUX_ML_KEM_MLKEM768_SECRET_KEY_SIZE_768 \ ++ (LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_SECRET_KEY_SIZE_768 + \ ++ LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_PUBLIC_KEY_SIZE_768 + \ ++ LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE + \ ++ LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE) ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#define __libcrux_mlkem768_H_DEFINED ++#endif +diff -up ./lib/freebl/verified/libcrux_mlkem768_portable.c.mlkem ./lib/freebl/verified/libcrux_mlkem768_portable.c +--- ./lib/freebl/verified/libcrux_mlkem768_portable.c.mlkem 2024-10-31 14:54:15.463515937 -0700 ++++ ./lib/freebl/verified/libcrux_mlkem768_portable.c 2024-10-31 14:54:15.463515937 -0700 +@@ -0,0 +1,209 @@ ++/* ++ * SPDX-FileCopyrightText: 2024 Cryspen Sarl ++ * ++ * SPDX-License-Identifier: MIT or Apache-2.0 ++ * ++ * This code was generated with the following revisions: ++ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d ++ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46 ++ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0 ++ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7 ++ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb ++ */ ++ ++#include "libcrux_mlkem768_portable.h" ++ ++#include "internal/libcrux_mlkem_portable.h" ++ ++/** ++ Portable decapsulate ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.ind_cca.instantiations.portable.decapsulate with const generics ++- K= 3 ++- SECRET_KEY_SIZE= 2400 ++- CPA_SECRET_KEY_SIZE= 1152 ++- PUBLIC_KEY_SIZE= 1184 ++- CIPHERTEXT_SIZE= 1088 ++- T_AS_NTT_ENCODED_SIZE= 1152 ++- C1_SIZE= 960 ++- C2_SIZE= 128 ++- VECTOR_U_COMPRESSION_FACTOR= 10 ++- VECTOR_V_COMPRESSION_FACTOR= 4 ++- C1_BLOCK_SIZE= 320 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++- IMPLICIT_REJECTION_HASH_INPUT_SIZE= 1120 ++*/ ++static void ++decapsulate_67( ++ libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) ++{ ++ libcrux_ml_kem_ind_cca_decapsulate_1f(private_key, ciphertext, ret); ++} ++ ++/** ++ Decapsulate ML-KEM 768 ++ ++ Generates an [`MlKemSharedSecret`]. ++ The input is a reference to an [`MlKem768PrivateKey`] and an ++ [`MlKem768Ciphertext`]. ++*/ ++void ++libcrux_ml_kem_mlkem768_portable_decapsulate( ++ libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) ++{ ++ decapsulate_67(private_key, ciphertext, ret); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.ind_cca.instantiations.portable.encapsulate with const generics ++- K= 3 ++- CIPHERTEXT_SIZE= 1088 ++- PUBLIC_KEY_SIZE= 1184 ++- T_AS_NTT_ENCODED_SIZE= 1152 ++- C1_SIZE= 960 ++- C2_SIZE= 128 ++- VECTOR_U_COMPRESSION_FACTOR= 10 ++- VECTOR_V_COMPRESSION_FACTOR= 4 ++- VECTOR_U_BLOCK_LEN= 320 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++*/ ++static tuple_3c ++encapsulate_02( ++ libcrux_ml_kem_types_MlKemPublicKey_15 *public_key, ++ uint8_t randomness[32U]) ++{ ++ libcrux_ml_kem_types_MlKemPublicKey_15 *uu____0 = public_key; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_randomness[32U]; ++ memcpy(copy_of_randomness, randomness, (size_t)32U * sizeof(uint8_t)); ++ return libcrux_ml_kem_ind_cca_encapsulate_eb(uu____0, copy_of_randomness); ++} ++ ++/** ++ Encapsulate ML-KEM 768 ++ ++ Generates an ([`MlKem768Ciphertext`], [`MlKemSharedSecret`]) tuple. ++ The input is a reference to an [`MlKem768PublicKey`] and [`SHARED_SECRET_SIZE`] ++ bytes of `randomness`. ++*/ ++tuple_3c ++libcrux_ml_kem_mlkem768_portable_encapsulate( ++ libcrux_ml_kem_types_MlKemPublicKey_15 *public_key, ++ uint8_t randomness[32U]) ++{ ++ libcrux_ml_kem_types_MlKemPublicKey_15 *uu____0 = public_key; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_randomness[32U]; ++ memcpy(copy_of_randomness, randomness, (size_t)32U * sizeof(uint8_t)); ++ return encapsulate_02(uu____0, copy_of_randomness); ++} ++ ++/** ++ Portable generate key pair. ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.ind_cca.instantiations.portable.generate_keypair with const ++generics ++- K= 3 ++- CPA_PRIVATE_KEY_SIZE= 1152 ++- PRIVATE_KEY_SIZE= 2400 ++- PUBLIC_KEY_SIZE= 1184 ++- BYTES_PER_RING_ELEMENT= 1152 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++*/ ++static libcrux_ml_kem_mlkem768_MlKem768KeyPair ++generate_keypair_87( ++ uint8_t randomness[64U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_randomness[64U]; ++ memcpy(copy_of_randomness, randomness, (size_t)64U * sizeof(uint8_t)); ++ return libcrux_ml_kem_ind_cca_generate_keypair_f6(copy_of_randomness); ++} ++ ++/** ++ Generate ML-KEM 768 Key Pair ++*/ ++libcrux_ml_kem_mlkem768_MlKem768KeyPair ++libcrux_ml_kem_mlkem768_portable_generate_key_pair(uint8_t randomness[64U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_randomness[64U]; ++ memcpy(copy_of_randomness, randomness, (size_t)64U * sizeof(uint8_t)); ++ return generate_keypair_87(copy_of_randomness); ++} ++ ++/** ++ Portable private key validation ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.ind_cca.instantiations.portable.validate_private_key with const ++generics ++- K= 3 ++- SECRET_KEY_SIZE= 2400 ++- CIPHERTEXT_SIZE= 1088 ++*/ ++static KRML_MUSTINLINE bool ++validate_private_key_e8( ++ libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext) ++{ ++ return libcrux_ml_kem_ind_cca_validate_private_key_05(private_key, ++ ciphertext); ++} ++ ++/** ++ Validate a private key. ++ ++ Returns `true` if valid, and `false` otherwise. ++*/ ++bool ++libcrux_ml_kem_mlkem768_portable_validate_private_key( ++ libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext) ++{ ++ return validate_private_key_e8(private_key, ciphertext); ++} ++ ++/** ++ Portable public key validation ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.ind_cca.instantiations.portable.validate_public_key with const ++generics ++- K= 3 ++- RANKED_BYTES_PER_RING_ELEMENT= 1152 ++- PUBLIC_KEY_SIZE= 1184 ++*/ ++static KRML_MUSTINLINE bool ++validate_public_key_7d(uint8_t *public_key) ++{ ++ return libcrux_ml_kem_ind_cca_validate_public_key_b7(public_key); ++} ++ ++/** ++ Validate a public key. ++ ++ Returns `true` if valid, and `false` otherwise. ++*/ ++bool ++libcrux_ml_kem_mlkem768_portable_validate_public_key( ++ libcrux_ml_kem_types_MlKemPublicKey_15 *public_key) ++{ ++ return validate_public_key_7d(public_key->value); ++} +diff -up ./lib/freebl/verified/libcrux_mlkem768_portable.h.mlkem ./lib/freebl/verified/libcrux_mlkem768_portable.h +--- ./lib/freebl/verified/libcrux_mlkem768_portable.h.mlkem 2024-10-31 14:54:15.463515937 -0700 ++++ ./lib/freebl/verified/libcrux_mlkem768_portable.h 2024-10-31 14:54:15.463515937 -0700 +@@ -0,0 +1,74 @@ ++/* ++ * SPDX-FileCopyrightText: 2024 Cryspen Sarl ++ * ++ * SPDX-License-Identifier: MIT or Apache-2.0 ++ * ++ * This code was generated with the following revisions: ++ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d ++ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46 ++ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0 ++ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7 ++ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb ++ */ ++ ++#ifndef __libcrux_mlkem768_portable_H ++#define __libcrux_mlkem768_portable_H ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++#include "eurydice_glue.h" ++#include "libcrux_core.h" ++ ++/** ++ Decapsulate ML-KEM 768 ++ ++ Generates an [`MlKemSharedSecret`]. ++ The input is a reference to an [`MlKem768PrivateKey`] and an ++ [`MlKem768Ciphertext`]. ++*/ ++void libcrux_ml_kem_mlkem768_portable_decapsulate( ++ libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]); ++ ++/** ++ Encapsulate ML-KEM 768 ++ ++ Generates an ([`MlKem768Ciphertext`], [`MlKemSharedSecret`]) tuple. ++ The input is a reference to an [`MlKem768PublicKey`] and [`SHARED_SECRET_SIZE`] ++ bytes of `randomness`. ++*/ ++tuple_3c libcrux_ml_kem_mlkem768_portable_encapsulate( ++ libcrux_ml_kem_types_MlKemPublicKey_15 *public_key, ++ uint8_t randomness[32U]); ++ ++/** ++ Generate ML-KEM 768 Key Pair ++*/ ++libcrux_ml_kem_mlkem768_MlKem768KeyPair ++libcrux_ml_kem_mlkem768_portable_generate_key_pair(uint8_t randomness[64U]); ++ ++/** ++ Validate a private key. ++ ++ Returns `true` if valid, and `false` otherwise. ++*/ ++bool libcrux_ml_kem_mlkem768_portable_validate_private_key( ++ libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext); ++ ++/** ++ Validate a public key. ++ ++ Returns `true` if valid, and `false` otherwise. ++*/ ++bool libcrux_ml_kem_mlkem768_portable_validate_public_key( ++ libcrux_ml_kem_types_MlKemPublicKey_15 *public_key); ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#define __libcrux_mlkem768_portable_H_DEFINED ++#endif +diff -up ./lib/freebl/verified/libcrux_mlkem_portable.c.mlkem ./lib/freebl/verified/libcrux_mlkem_portable.c +--- ./lib/freebl/verified/libcrux_mlkem_portable.c.mlkem 2024-10-31 14:54:15.465515959 -0700 ++++ ./lib/freebl/verified/libcrux_mlkem_portable.c 2024-10-31 14:54:15.465515959 -0700 +@@ -0,0 +1,9295 @@ ++/* ++ * SPDX-FileCopyrightText: 2024 Cryspen Sarl ++ * ++ * SPDX-License-Identifier: MIT or Apache-2.0 ++ * ++ * This code was generated with the following revisions: ++ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d ++ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46 ++ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0 ++ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7 ++ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb ++ */ ++ ++#include "internal/libcrux_mlkem_portable.h" ++ ++#include "internal/libcrux_core.h" ++#include "internal/libcrux_sha3_internal.h" ++ ++KRML_MUSTINLINE void ++libcrux_ml_kem_hash_functions_portable_G( ++ Eurydice_slice input, uint8_t ret[64U]) ++{ ++ uint8_t digest[64U] = { 0U }; ++ libcrux_sha3_portable_sha512( ++ Eurydice_array_to_slice((size_t)64U, digest, uint8_t), input); ++ memcpy(ret, digest, (size_t)64U * sizeof(uint8_t)); ++} ++ ++KRML_MUSTINLINE void ++libcrux_ml_kem_hash_functions_portable_H( ++ Eurydice_slice input, uint8_t ret[32U]) ++{ ++ uint8_t digest[32U] = { 0U }; ++ libcrux_sha3_portable_sha256( ++ Eurydice_array_to_slice((size_t)32U, digest, uint8_t), input); ++ memcpy(ret, digest, (size_t)32U * sizeof(uint8_t)); ++} ++ ++const int16_t libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[128U] = { ++ (int16_t)-1044, (int16_t)-758, (int16_t)-359, (int16_t)-1517, ++ (int16_t)1493, (int16_t)1422, (int16_t)287, (int16_t)202, ++ (int16_t)-171, (int16_t)622, (int16_t)1577, (int16_t)182, ++ (int16_t)962, (int16_t)-1202, (int16_t)-1474, (int16_t)1468, ++ (int16_t)573, (int16_t)-1325, (int16_t)264, (int16_t)383, ++ (int16_t)-829, (int16_t)1458, (int16_t)-1602, (int16_t)-130, ++ (int16_t)-681, (int16_t)1017, (int16_t)732, (int16_t)608, ++ (int16_t)-1542, (int16_t)411, (int16_t)-205, (int16_t)-1571, ++ (int16_t)1223, (int16_t)652, (int16_t)-552, (int16_t)1015, ++ (int16_t)-1293, (int16_t)1491, (int16_t)-282, (int16_t)-1544, ++ (int16_t)516, (int16_t)-8, (int16_t)-320, (int16_t)-666, ++ (int16_t)-1618, (int16_t)-1162, (int16_t)126, (int16_t)1469, ++ (int16_t)-853, (int16_t)-90, (int16_t)-271, (int16_t)830, ++ (int16_t)107, (int16_t)-1421, (int16_t)-247, (int16_t)-951, ++ (int16_t)-398, (int16_t)961, (int16_t)-1508, (int16_t)-725, ++ (int16_t)448, (int16_t)-1065, (int16_t)677, (int16_t)-1275, ++ (int16_t)-1103, (int16_t)430, (int16_t)555, (int16_t)843, ++ (int16_t)-1251, (int16_t)871, (int16_t)1550, (int16_t)105, ++ (int16_t)422, (int16_t)587, (int16_t)177, (int16_t)-235, ++ (int16_t)-291, (int16_t)-460, (int16_t)1574, (int16_t)1653, ++ (int16_t)-246, (int16_t)778, (int16_t)1159, (int16_t)-147, ++ (int16_t)-777, (int16_t)1483, (int16_t)-602, (int16_t)1119, ++ (int16_t)-1590, (int16_t)644, (int16_t)-872, (int16_t)349, ++ (int16_t)418, (int16_t)329, (int16_t)-156, (int16_t)-75, ++ (int16_t)817, (int16_t)1097, (int16_t)603, (int16_t)610, ++ (int16_t)1322, (int16_t)-1285, (int16_t)-1465, (int16_t)384, ++ (int16_t)-1215, (int16_t)-136, (int16_t)1218, (int16_t)-1335, ++ (int16_t)-874, (int16_t)220, (int16_t)-1187, (int16_t)-1659, ++ (int16_t)-1185, (int16_t)-1530, (int16_t)-1278, (int16_t)794, ++ (int16_t)-1510, (int16_t)-854, (int16_t)-870, (int16_t)478, ++ (int16_t)-108, (int16_t)-308, (int16_t)996, (int16_t)991, ++ (int16_t)958, (int16_t)-1460, (int16_t)1522, (int16_t)1628 ++}; ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_vector_type_from_i16_array( ++ Eurydice_slice array) ++{ ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector lit; ++ int16_t ret[16U]; ++ core_result_Result_c0 dst; ++ Eurydice_slice_to_array2( ++ &dst, Eurydice_slice_subslice2(array, (size_t)0U, (size_t)16U, int16_t), ++ Eurydice_slice, int16_t[16U]); ++ core_result_unwrap_41_30(dst, ret); ++ memcpy(lit.elements, ret, (size_t)16U * sizeof(int16_t)); ++ return lit; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_from_i16_array_0d(Eurydice_slice array) ++{ ++ return libcrux_ml_kem_vector_portable_vector_type_from_i16_array(array); ++} ++ ++KRML_MUSTINLINE uint8_t_x11 ++libcrux_ml_kem_vector_portable_serialize_serialize_11_int(Eurydice_slice v) ++{ ++ uint8_t r0 = (uint8_t)Eurydice_slice_index(v, (size_t)0U, int16_t, int16_t *); ++ uint8_t r1 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)1U, int16_t, ++ int16_t *) & ++ (int16_t)31) ++ << 3U | ++ (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)0U, int16_t, ++ int16_t *) >> ++ 8U); ++ uint8_t r2 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)2U, int16_t, ++ int16_t *) & ++ (int16_t)3) ++ << 6U | ++ (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)1U, int16_t, ++ int16_t *) >> ++ 5U); ++ uint8_t r3 = ++ (uint8_t)(Eurydice_slice_index(v, (size_t)2U, int16_t, int16_t *) >> 2U & ++ (int16_t)255); ++ uint8_t r4 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)3U, int16_t, ++ int16_t *) & ++ (int16_t)127) ++ << 1U | ++ (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)2U, int16_t, ++ int16_t *) >> ++ 10U); ++ uint8_t r5 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)4U, int16_t, ++ int16_t *) & ++ (int16_t)15) ++ << 4U | ++ (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)3U, int16_t, ++ int16_t *) >> ++ 7U); ++ uint8_t r6 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)5U, int16_t, ++ int16_t *) & ++ (int16_t)1) ++ << 7U | ++ (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)4U, int16_t, ++ int16_t *) >> ++ 4U); ++ uint8_t r7 = ++ (uint8_t)(Eurydice_slice_index(v, (size_t)5U, int16_t, int16_t *) >> 1U & ++ (int16_t)255); ++ uint8_t r8 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)6U, int16_t, ++ int16_t *) & ++ (int16_t)63) ++ << 2U | ++ (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)5U, int16_t, ++ int16_t *) >> ++ 9U); ++ uint8_t r9 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)7U, int16_t, ++ int16_t *) & ++ (int16_t)7) ++ << 5U | ++ (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)6U, int16_t, ++ int16_t *) >> ++ 6U); ++ uint8_t r10 = ++ (uint8_t)(Eurydice_slice_index(v, (size_t)7U, int16_t, int16_t *) >> 3U); ++ return (CLITERAL(uint8_t_x11){ .fst = r0, ++ .snd = r1, ++ .thd = r2, ++ .f3 = r3, ++ .f4 = r4, ++ .f5 = r5, ++ .f6 = r6, ++ .f7 = r7, ++ .f8 = r8, ++ .f9 = r9, ++ .f10 = r10 }); ++} ++ ++KRML_MUSTINLINE void ++libcrux_ml_kem_vector_portable_serialize_serialize_11( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, ++ uint8_t ret[22U]) ++{ ++ uint8_t_x11 r0_10 = libcrux_ml_kem_vector_portable_serialize_serialize_11_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)0U, (size_t)8U, int16_t)); ++ uint8_t_x11 r11_21 = ++ libcrux_ml_kem_vector_portable_serialize_serialize_11_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)8U, (size_t)16U, ++ int16_t)); ++ uint8_t result[22U] = { 0U }; ++ result[0U] = r0_10.fst; ++ result[1U] = r0_10.snd; ++ result[2U] = r0_10.thd; ++ result[3U] = r0_10.f3; ++ result[4U] = r0_10.f4; ++ result[5U] = r0_10.f5; ++ result[6U] = r0_10.f6; ++ result[7U] = r0_10.f7; ++ result[8U] = r0_10.f8; ++ result[9U] = r0_10.f9; ++ result[10U] = r0_10.f10; ++ result[11U] = r11_21.fst; ++ result[12U] = r11_21.snd; ++ result[13U] = r11_21.thd; ++ result[14U] = r11_21.f3; ++ result[15U] = r11_21.f4; ++ result[16U] = r11_21.f5; ++ result[17U] = r11_21.f6; ++ result[18U] = r11_21.f7; ++ result[19U] = r11_21.f8; ++ result[20U] = r11_21.f9; ++ result[21U] = r11_21.f10; ++ memcpy(ret, result, (size_t)22U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++void ++libcrux_ml_kem_vector_portable_serialize_11_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, ++ uint8_t ret[22U]) ++{ ++ libcrux_ml_kem_vector_portable_serialize_serialize_11(a, ret); ++} ++ ++KRML_MUSTINLINE int16_t_x8 ++libcrux_ml_kem_vector_portable_serialize_deserialize_11_int( ++ Eurydice_slice bytes) ++{ ++ int16_t r0 = ++ ((int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *) & ++ (int16_t)7) ++ << 8U | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *); ++ int16_t r1 = ++ ((int16_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, uint8_t *) & ++ (int16_t)63) ++ << 5U | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *) >> ++ 3U; ++ int16_t r2 = ++ (((int16_t)Eurydice_slice_index(bytes, (size_t)4U, uint8_t, uint8_t *) & ++ (int16_t)1) ++ << 10U | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)3U, uint8_t, uint8_t *) ++ << 2U) | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, uint8_t *) >> ++ 6U; ++ int16_t r3 = ++ ((int16_t)Eurydice_slice_index(bytes, (size_t)5U, uint8_t, uint8_t *) & ++ (int16_t)15) ++ << 7U | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)4U, uint8_t, uint8_t *) >> ++ 1U; ++ int16_t r4 = ++ ((int16_t)Eurydice_slice_index(bytes, (size_t)6U, uint8_t, uint8_t *) & ++ (int16_t)127) ++ << 4U | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)5U, uint8_t, uint8_t *) >> ++ 4U; ++ int16_t r5 = ++ (((int16_t)Eurydice_slice_index(bytes, (size_t)8U, uint8_t, uint8_t *) & ++ (int16_t)3) ++ << 9U | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)7U, uint8_t, uint8_t *) ++ << 1U) | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)6U, uint8_t, uint8_t *) >> ++ 7U; ++ int16_t r6 = ++ ((int16_t)Eurydice_slice_index(bytes, (size_t)9U, uint8_t, uint8_t *) & ++ (int16_t)31) ++ << 6U | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)8U, uint8_t, uint8_t *) >> ++ 2U; ++ int16_t r7 = ++ (int16_t)Eurydice_slice_index(bytes, (size_t)10U, uint8_t, uint8_t *) ++ << 3U | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)9U, uint8_t, uint8_t *) >> ++ 5U; ++ return (CLITERAL(int16_t_x8){ .fst = r0, ++ .snd = r1, ++ .thd = r2, ++ .f3 = r3, ++ .f4 = r4, ++ .f5 = r5, ++ .f6 = r6, ++ .f7 = r7 }); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_vector_type_zero(void) ++{ ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector lit; ++ lit.elements[0U] = (int16_t)0; ++ lit.elements[1U] = (int16_t)0; ++ lit.elements[2U] = (int16_t)0; ++ lit.elements[3U] = (int16_t)0; ++ lit.elements[4U] = (int16_t)0; ++ lit.elements[5U] = (int16_t)0; ++ lit.elements[6U] = (int16_t)0; ++ lit.elements[7U] = (int16_t)0; ++ lit.elements[8U] = (int16_t)0; ++ lit.elements[9U] = (int16_t)0; ++ lit.elements[10U] = (int16_t)0; ++ lit.elements[11U] = (int16_t)0; ++ lit.elements[12U] = (int16_t)0; ++ lit.elements[13U] = (int16_t)0; ++ lit.elements[14U] = (int16_t)0; ++ lit.elements[15U] = (int16_t)0; ++ return lit; ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_serialize_deserialize_11(Eurydice_slice bytes) ++{ ++ int16_t_x8 v0_7 = libcrux_ml_kem_vector_portable_serialize_deserialize_11_int( ++ Eurydice_slice_subslice2(bytes, (size_t)0U, (size_t)11U, uint8_t)); ++ int16_t_x8 v8_15 = ++ libcrux_ml_kem_vector_portable_serialize_deserialize_11_int( ++ Eurydice_slice_subslice2(bytes, (size_t)11U, (size_t)22U, uint8_t)); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v = ++ libcrux_ml_kem_vector_portable_vector_type_zero(); ++ v.elements[0U] = v0_7.fst; ++ v.elements[1U] = v0_7.snd; ++ v.elements[2U] = v0_7.thd; ++ v.elements[3U] = v0_7.f3; ++ v.elements[4U] = v0_7.f4; ++ v.elements[5U] = v0_7.f5; ++ v.elements[6U] = v0_7.f6; ++ v.elements[7U] = v0_7.f7; ++ v.elements[8U] = v8_15.fst; ++ v.elements[9U] = v8_15.snd; ++ v.elements[10U] = v8_15.thd; ++ v.elements[11U] = v8_15.f3; ++ v.elements[12U] = v8_15.f4; ++ v.elements[13U] = v8_15.f5; ++ v.elements[14U] = v8_15.f6; ++ v.elements[15U] = v8_15.f7; ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_deserialize_11_0d(Eurydice_slice a) ++{ ++ return libcrux_ml_kem_vector_portable_serialize_deserialize_11(a); ++} ++ ++KRML_MUSTINLINE void ++libcrux_ml_kem_vector_portable_vector_type_to_i16_array( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector x, ++ int16_t ret[16U]) ++{ ++ memcpy(ret, x.elements, (size_t)16U * sizeof(int16_t)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++void ++libcrux_ml_kem_vector_portable_to_i16_array_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector x, ++ int16_t ret[16U]) ++{ ++ libcrux_ml_kem_vector_portable_vector_type_to_i16_array(x, ret); ++} ++ ++const uint8_t ++ libcrux_ml_kem_vector_rej_sample_table_REJECTION_SAMPLE_SHUFFLE_TABLE ++ [256U][16U] = { { 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 10U, 11U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 10U, 11U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 10U, 11U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 255U, ++ 255U, 255U, 255U }, ++ { 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 255U, ++ 255U, 255U, 255U }, ++ { 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 10U, 11U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, ++ 255U, 255U, 255U, 255U }, ++ { 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, ++ 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, ++ 13U, 255U, 255U }, ++ { 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 14U, 15U, 255U, ++ 255U, 255U, 255U }, ++ { 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 10U, 11U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 14U, ++ 15U, 255U, 255U }, ++ { 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 12U, 13U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 14U, ++ 15U, 255U, 255U }, ++ { 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 10U, 11U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 14U, ++ 15U, 255U, 255U }, ++ { 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, ++ 15U, 255U, 255U }, ++ { 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, ++ 255U, 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, ++ 15U, 255U, 255U }, ++ { 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, ++ 255U, 255U, 255U, 255U }, ++ { 0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, ++ 15U, 255U, 255U }, ++ { 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, ++ 15U, 255U, 255U }, ++ { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, ++ 13U, 14U, 15U } }; ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ZERO_0d(void) ++{ ++ return libcrux_ml_kem_vector_portable_vector_type_zero(); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_arithmetic_add( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ size_t uu____0 = i0; ++ lhs.elements[uu____0] = lhs.elements[uu____0] + rhs->elements[i0]; ++ } ++ return lhs; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_add_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) ++{ ++ return libcrux_ml_kem_vector_portable_arithmetic_add(lhs, rhs); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_arithmetic_sub( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ size_t uu____0 = i0; ++ lhs.elements[uu____0] = lhs.elements[uu____0] - rhs->elements[i0]; ++ } ++ return lhs; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_sub_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) ++{ ++ return libcrux_ml_kem_vector_portable_arithmetic_sub(lhs, rhs); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_arithmetic_multiply_by_constant( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ size_t uu____0 = i0; ++ v.elements[uu____0] = v.elements[uu____0] * c; ++ } ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_multiply_by_constant_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) ++{ ++ return libcrux_ml_kem_vector_portable_arithmetic_multiply_by_constant(v, c); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_arithmetic_bitwise_and_with_constant( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ size_t uu____0 = i0; ++ v.elements[uu____0] = v.elements[uu____0] & c; ++ } ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_bitwise_and_with_constant_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) ++{ ++ return libcrux_ml_kem_vector_portable_arithmetic_bitwise_and_with_constant(v, ++ c); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_arithmetic_cond_subtract_3329( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ core_ops_range_Range_b3 iter = ++ core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( ++ (CLITERAL(core_ops_range_Range_b3){ ++ .start = (size_t)0U, ++ .end = LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR }), ++ core_ops_range_Range_b3, core_ops_range_Range_b3); ++ while (true) { ++ core_option_Option_b3 uu____0 = ++ core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( ++ &iter, size_t, core_option_Option_b3); ++ if (!(uu____0.tag == core_option_None)) { ++ size_t i = uu____0.f0; ++ if (v.elements[i] >= (int16_t)3329) { ++ size_t uu____1 = i; ++ v.elements[uu____1] = v.elements[uu____1] - (int16_t)3329; ++ } ++ continue; ++ } ++ return v; ++ } ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_cond_subtract_3329_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ return libcrux_ml_kem_vector_portable_arithmetic_cond_subtract_3329(v); ++} ++ ++/** ++ Signed Barrett Reduction ++ ++ Given an input `value`, `barrett_reduce` outputs a representative `result` ++ such that: ++ ++ - result ≡ value (mod FIELD_MODULUS) ++ - the absolute value of `result` is bound as follows: ++ ++ `|result| ≤ FIELD_MODULUS / 2 · (|value|/BARRETT_R + 1) ++ ++ In particular, if `|value| < BARRETT_R`, then `|result| < FIELD_MODULUS`. ++*/ ++int16_t ++libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( ++ int16_t value) ++{ ++ int32_t t = (int32_t)value * ++ LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_MULTIPLIER + ++ (LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_R >> 1U); ++ int16_t quotient = ++ (int16_t)(t >> ++ (uint32_t) ++ LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_SHIFT); ++ return value - quotient * LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ v.elements[i0] = ++ libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( ++ v.elements[i0]); ++ } ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_barrett_reduce_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ return libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce(v); ++} ++ ++/** ++ Signed Montgomery Reduction ++ ++ Given an input `value`, `montgomery_reduce` outputs a representative `o` ++ such that: ++ ++ - o ≡ value · MONTGOMERY_R^(-1) (mod FIELD_MODULUS) ++ - the absolute value of `o` is bound as follows: ++ ++ `|result| ≤ (|value| / MONTGOMERY_R) + (FIELD_MODULUS / 2) ++ ++ In particular, if `|value| ≤ FIELD_MODULUS * MONTGOMERY_R`, then `|o| < (3 · ++ FIELD_MODULUS) / 2`. ++*/ ++int16_t ++libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( ++ int32_t value) ++{ ++ int32_t k = ++ (int32_t)(int16_t)value * ++ (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_INVERSE_OF_MODULUS_MOD_MONTGOMERY_R; ++ int32_t k_times_modulus = ++ (int32_t)(int16_t)k * (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; ++ int16_t c = ++ (int16_t)(k_times_modulus >> ++ (uint32_t) ++ LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT); ++ int16_t value_high = ++ (int16_t)(value >> ++ (uint32_t) ++ LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT); ++ return value_high - c; ++} ++ ++/** ++ If `fe` is some field element 'x' of the Kyber field and `fer` is congruent to ++ `y · MONTGOMERY_R`, this procedure outputs a value that is congruent to ++ `x · y`, as follows: ++ ++ `fe · fer ≡ x · y · MONTGOMERY_R (mod FIELD_MODULUS)` ++ ++ `montgomery_reduce` takes the value `x · y · MONTGOMERY_R` and outputs a ++ representative `x · y · MONTGOMERY_R * MONTGOMERY_R^{-1} ≡ x · y (mod ++ FIELD_MODULUS)`. ++*/ ++KRML_MUSTINLINE int16_t ++libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( ++ int16_t fe, int16_t fer) ++{ ++ return libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( ++ (int32_t)fe * (int32_t)fer); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_by_constant( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ v.elements[i0] = ++ libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( ++ v.elements[i0], c); ++ } ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_montgomery_multiply_by_constant_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t r) ++{ ++ return libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_by_constant( ++ v, r); ++} ++ ++/** ++ The `compress_*` functions implement the `Compress` function specified in the ++ NIST FIPS 203 standard (Page 18, Expression 4.5), which is defined as: ++ ++ ```plaintext ++ Compress_d: ℤq -> ℤ_{2ᵈ} ++ Compress_d(x) = ⌈(2ᵈ/q)·x⌋ ++ ``` ++ ++ Since `⌈x⌋ = ⌊x + 1/2⌋` we have: ++ ++ ```plaintext ++ Compress_d(x) = ⌊(2ᵈ/q)·x + 1/2⌋ ++ = ⌊(2^{d+1}·x + q) / 2q⌋ ++ ``` ++ ++ For further information about the function implementations, consult the ++ `implementation_notes.pdf` document in this directory. ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++uint8_t ++libcrux_ml_kem_vector_portable_compress_compress_message_coefficient( ++ uint16_t fe) ++{ ++ int16_t shifted = (int16_t)1664 - (int16_t)fe; ++ int16_t mask = shifted >> 15U; ++ int16_t shifted_to_positive = mask ^ shifted; ++ int16_t shifted_positive_in_range = shifted_to_positive - (int16_t)832; ++ return (uint8_t)(shifted_positive_in_range >> 15U & (int16_t)1); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_compress_compress_1( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ v.elements[i0] = (int16_t) ++ libcrux_ml_kem_vector_portable_compress_compress_message_coefficient( ++ (uint16_t)v.elements[i0]); ++ } ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_compress_1_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ return libcrux_ml_kem_vector_portable_compress_compress_1(v); ++} ++ ++KRML_MUSTINLINE uint32_t ++libcrux_ml_kem_vector_portable_arithmetic_get_n_least_significant_bits( ++ uint8_t n, uint32_t value) ++{ ++ return value & ((1U << (uint32_t)n) - 1U); ++} ++ ++int16_t ++libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( ++ uint8_t coefficient_bits, uint16_t fe) ++{ ++ uint64_t compressed = (uint64_t)fe << (uint32_t)coefficient_bits; ++ compressed = compressed + 1664ULL; ++ compressed = compressed * 10321340ULL; ++ compressed = compressed >> 35U; ++ return (int16_t) ++ libcrux_ml_kem_vector_portable_arithmetic_get_n_least_significant_bits( ++ coefficient_bits, (uint32_t)compressed); ++} ++ ++KRML_MUSTINLINE void ++libcrux_ml_kem_vector_portable_ntt_ntt_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *v, int16_t zeta, ++ size_t i, size_t j) ++{ ++ int16_t t = ++ libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( ++ v->elements[j], zeta); ++ v->elements[j] = v->elements[i] - t; ++ v->elements[i] = v->elements[i] + t; ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_ntt_layer_1_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, ++ int16_t zeta1, int16_t zeta2, int16_t zeta3) ++{ ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta0, (size_t)0U, ++ (size_t)2U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta0, (size_t)1U, ++ (size_t)3U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta1, (size_t)4U, ++ (size_t)6U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta1, (size_t)5U, ++ (size_t)7U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta2, (size_t)8U, ++ (size_t)10U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta2, (size_t)9U, ++ (size_t)11U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta3, (size_t)12U, ++ (size_t)14U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta3, (size_t)13U, ++ (size_t)15U); ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_layer_1_step_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, ++ int16_t zeta1, int16_t zeta2, int16_t zeta3) ++{ ++ return libcrux_ml_kem_vector_portable_ntt_ntt_layer_1_step(a, zeta0, zeta1, ++ zeta2, zeta3); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_ntt_layer_2_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, ++ int16_t zeta1) ++{ ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta0, (size_t)0U, ++ (size_t)4U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta0, (size_t)1U, ++ (size_t)5U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta0, (size_t)2U, ++ (size_t)6U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta0, (size_t)3U, ++ (size_t)7U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta1, (size_t)8U, ++ (size_t)12U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta1, (size_t)9U, ++ (size_t)13U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta1, (size_t)10U, ++ (size_t)14U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta1, (size_t)11U, ++ (size_t)15U); ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_layer_2_step_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, ++ int16_t zeta1) ++{ ++ return libcrux_ml_kem_vector_portable_ntt_ntt_layer_2_step(a, zeta0, zeta1); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_ntt_layer_3_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta) ++{ ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)0U, (size_t)8U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)1U, (size_t)9U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)2U, ++ (size_t)10U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)3U, ++ (size_t)11U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)4U, ++ (size_t)12U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)5U, ++ (size_t)13U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)6U, ++ (size_t)14U); ++ libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)7U, ++ (size_t)15U); ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_layer_3_step_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta) ++{ ++ return libcrux_ml_kem_vector_portable_ntt_ntt_layer_3_step(a, zeta); ++} ++ ++KRML_MUSTINLINE void ++libcrux_ml_kem_vector_portable_ntt_inv_ntt_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *v, int16_t zeta, ++ size_t i, size_t j) ++{ ++ int16_t a_minus_b = v->elements[j] - v->elements[i]; ++ v->elements[i] = ++ libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( ++ v->elements[i] + v->elements[j]); ++ v->elements[j] = ++ libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( ++ a_minus_b, zeta); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_1_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, ++ int16_t zeta1, int16_t zeta2, int16_t zeta3) ++{ ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta0, (size_t)0U, ++ (size_t)2U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta0, (size_t)1U, ++ (size_t)3U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta1, (size_t)4U, ++ (size_t)6U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta1, (size_t)5U, ++ (size_t)7U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta2, (size_t)8U, ++ (size_t)10U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta2, (size_t)9U, ++ (size_t)11U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta3, (size_t)12U, ++ (size_t)14U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta3, (size_t)13U, ++ (size_t)15U); ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_inv_ntt_layer_1_step_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, ++ int16_t zeta1, int16_t zeta2, int16_t zeta3) ++{ ++ return libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_1_step( ++ a, zeta0, zeta1, zeta2, zeta3); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_2_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, ++ int16_t zeta1) ++{ ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta0, (size_t)0U, ++ (size_t)4U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta0, (size_t)1U, ++ (size_t)5U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta0, (size_t)2U, ++ (size_t)6U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta0, (size_t)3U, ++ (size_t)7U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta1, (size_t)8U, ++ (size_t)12U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta1, (size_t)9U, ++ (size_t)13U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta1, (size_t)10U, ++ (size_t)14U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta1, (size_t)11U, ++ (size_t)15U); ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_inv_ntt_layer_2_step_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, ++ int16_t zeta1) ++{ ++ return libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_2_step(a, zeta0, ++ zeta1); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_3_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta) ++{ ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)0U, ++ (size_t)8U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)1U, ++ (size_t)9U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)2U, ++ (size_t)10U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)3U, ++ (size_t)11U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)4U, ++ (size_t)12U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)5U, ++ (size_t)13U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)6U, ++ (size_t)14U); ++ libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)7U, ++ (size_t)15U); ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_inv_ntt_layer_3_step_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta) ++{ ++ return libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_3_step(a, zeta); ++} ++ ++/** ++ Compute the product of two Kyber binomials with respect to the ++ modulus `X² - zeta`. ++ ++ This function almost implements Algorithm 11 of the ++ NIST FIPS 203 standard, which is reproduced below: ++ ++ ```plaintext ++ Input: a₀, a₁, b₀, b₁ ∈ ℤq. ++ Input: γ ∈ ℤq. ++ Output: c₀, c₁ ∈ ℤq. ++ ++ c₀ ← a₀·b₀ + a₁·b₁·γ ++ c₁ ← a₀·b₁ + a₁·b₀ ++ return c₀, c₁ ++ ``` ++ We say "almost" because the coefficients output by this function are in ++ the Montgomery domain (unlike in the specification). ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++KRML_MUSTINLINE void ++libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *a, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *b, int16_t zeta, ++ size_t i, size_t j, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *out) ++{ ++ int16_t o0 = libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( ++ (int32_t)a->elements[i] * (int32_t)b->elements[i] + ++ (int32_t) ++ libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( ++ (int32_t)a->elements[j] * (int32_t)b->elements[j]) * ++ (int32_t)zeta); ++ int16_t o1 = ++ libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( ++ (int32_t)a->elements[i] * (int32_t)b->elements[j] + ++ (int32_t)a->elements[j] * (int32_t)b->elements[i]); ++ out->elements[i] = o0; ++ out->elements[j] = o1; ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_ntt_multiply( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *lhs, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs, ++ int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) ++{ ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector out = ++ libcrux_ml_kem_vector_portable_vector_type_zero(); ++ libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( ++ lhs, rhs, zeta0, (size_t)0U, (size_t)1U, &out); ++ libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( ++ lhs, rhs, -zeta0, (size_t)2U, (size_t)3U, &out); ++ libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( ++ lhs, rhs, zeta1, (size_t)4U, (size_t)5U, &out); ++ libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( ++ lhs, rhs, -zeta1, (size_t)6U, (size_t)7U, &out); ++ libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( ++ lhs, rhs, zeta2, (size_t)8U, (size_t)9U, &out); ++ libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( ++ lhs, rhs, -zeta2, (size_t)10U, (size_t)11U, &out); ++ libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( ++ lhs, rhs, zeta3, (size_t)12U, (size_t)13U, &out); ++ libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( ++ lhs, rhs, -zeta3, (size_t)14U, (size_t)15U, &out); ++ return out; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_multiply_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *lhs, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs, ++ int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) ++{ ++ return libcrux_ml_kem_vector_portable_ntt_ntt_multiply(lhs, rhs, zeta0, zeta1, ++ zeta2, zeta3); ++} ++ ++KRML_MUSTINLINE void ++libcrux_ml_kem_vector_portable_serialize_serialize_1( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, ++ uint8_t ret[2U]) ++{ ++ uint8_t result[2U] = { 0U }; ++ KRML_MAYBE_FOR8( ++ i, (size_t)0U, (size_t)8U, (size_t)1U, size_t i0 = i; ++ size_t uu____0 = (size_t)0U; ++ result[uu____0] = (uint32_t)result[uu____0] | ++ (uint32_t)(uint8_t)v.elements[i0] << (uint32_t)i0;); ++ KRML_MAYBE_FOR8(i, (size_t)8U, (size_t)16U, (size_t)1U, size_t i0 = i; ++ size_t uu____1 = (size_t)1U; ++ result[uu____1] = (uint32_t)result[uu____1] | ++ (uint32_t)(uint8_t)v.elements[i0] ++ << (uint32_t)(i0 - (size_t)8U);); ++ memcpy(ret, result, (size_t)2U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++void ++libcrux_ml_kem_vector_portable_serialize_1_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, ++ uint8_t ret[2U]) ++{ ++ libcrux_ml_kem_vector_portable_serialize_serialize_1(a, ret); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_serialize_deserialize_1(Eurydice_slice v) ++{ ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector result = ++ libcrux_ml_kem_vector_portable_vector_type_zero(); ++ KRML_MAYBE_FOR8( ++ i, (size_t)0U, (size_t)8U, (size_t)1U, size_t i0 = i; ++ result.elements[i0] = (int16_t)((uint32_t)Eurydice_slice_index( ++ v, (size_t)0U, uint8_t, uint8_t *) >> ++ (uint32_t)i0 & ++ 1U);); ++ for (size_t i = (size_t)8U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ result.elements[i0] = (int16_t)((uint32_t)Eurydice_slice_index( ++ v, (size_t)1U, uint8_t, uint8_t *) >> ++ (uint32_t)(i0 - (size_t)8U) & ++ 1U); ++ } ++ return result; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_deserialize_1_0d(Eurydice_slice a) ++{ ++ return libcrux_ml_kem_vector_portable_serialize_deserialize_1(a); ++} ++ ++KRML_MUSTINLINE uint8_t_x4 ++libcrux_ml_kem_vector_portable_serialize_serialize_4_int(Eurydice_slice v) ++{ ++ uint8_t result0 = ++ (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)1U, int16_t, int16_t *) ++ << 4U | ++ (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)0U, int16_t, ++ int16_t *); ++ uint8_t result1 = ++ (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)3U, int16_t, int16_t *) ++ << 4U | ++ (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)2U, int16_t, ++ int16_t *); ++ uint8_t result2 = ++ (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)5U, int16_t, int16_t *) ++ << 4U | ++ (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)4U, int16_t, ++ int16_t *); ++ uint8_t result3 = ++ (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)7U, int16_t, int16_t *) ++ << 4U | ++ (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)6U, int16_t, ++ int16_t *); ++ return (CLITERAL(uint8_t_x4){ ++ .fst = result0, .snd = result1, .thd = result2, .f3 = result3 }); ++} ++ ++KRML_MUSTINLINE void ++libcrux_ml_kem_vector_portable_serialize_serialize_4( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, ++ uint8_t ret[8U]) ++{ ++ uint8_t_x4 result0_3 = ++ libcrux_ml_kem_vector_portable_serialize_serialize_4_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)0U, (size_t)8U, ++ int16_t)); ++ uint8_t_x4 result4_7 = ++ libcrux_ml_kem_vector_portable_serialize_serialize_4_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)8U, (size_t)16U, ++ int16_t)); ++ uint8_t result[8U] = { 0U }; ++ result[0U] = result0_3.fst; ++ result[1U] = result0_3.snd; ++ result[2U] = result0_3.thd; ++ result[3U] = result0_3.f3; ++ result[4U] = result4_7.fst; ++ result[5U] = result4_7.snd; ++ result[6U] = result4_7.thd; ++ result[7U] = result4_7.f3; ++ memcpy(ret, result, (size_t)8U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++void ++libcrux_ml_kem_vector_portable_serialize_4_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, ++ uint8_t ret[8U]) ++{ ++ libcrux_ml_kem_vector_portable_serialize_serialize_4(a, ret); ++} ++ ++KRML_MUSTINLINE int16_t_x8 ++libcrux_ml_kem_vector_portable_serialize_deserialize_4_int( ++ Eurydice_slice bytes) ++{ ++ int16_t v0 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)0U, ++ uint8_t, uint8_t *) & ++ 15U); ++ int16_t v1 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)0U, ++ uint8_t, uint8_t *) >> ++ 4U & ++ 15U); ++ int16_t v2 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)1U, ++ uint8_t, uint8_t *) & ++ 15U); ++ int16_t v3 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)1U, ++ uint8_t, uint8_t *) >> ++ 4U & ++ 15U); ++ int16_t v4 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)2U, ++ uint8_t, uint8_t *) & ++ 15U); ++ int16_t v5 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)2U, ++ uint8_t, uint8_t *) >> ++ 4U & ++ 15U); ++ int16_t v6 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)3U, ++ uint8_t, uint8_t *) & ++ 15U); ++ int16_t v7 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)3U, ++ uint8_t, uint8_t *) >> ++ 4U & ++ 15U); ++ return (CLITERAL(int16_t_x8){ .fst = v0, ++ .snd = v1, ++ .thd = v2, ++ .f3 = v3, ++ .f4 = v4, ++ .f5 = v5, ++ .f6 = v6, ++ .f7 = v7 }); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_serialize_deserialize_4(Eurydice_slice bytes) ++{ ++ int16_t_x8 v0_7 = libcrux_ml_kem_vector_portable_serialize_deserialize_4_int( ++ Eurydice_slice_subslice2(bytes, (size_t)0U, (size_t)4U, uint8_t)); ++ int16_t_x8 v8_15 = libcrux_ml_kem_vector_portable_serialize_deserialize_4_int( ++ Eurydice_slice_subslice2(bytes, (size_t)4U, (size_t)8U, uint8_t)); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v = ++ libcrux_ml_kem_vector_portable_vector_type_zero(); ++ v.elements[0U] = v0_7.fst; ++ v.elements[1U] = v0_7.snd; ++ v.elements[2U] = v0_7.thd; ++ v.elements[3U] = v0_7.f3; ++ v.elements[4U] = v0_7.f4; ++ v.elements[5U] = v0_7.f5; ++ v.elements[6U] = v0_7.f6; ++ v.elements[7U] = v0_7.f7; ++ v.elements[8U] = v8_15.fst; ++ v.elements[9U] = v8_15.snd; ++ v.elements[10U] = v8_15.thd; ++ v.elements[11U] = v8_15.f3; ++ v.elements[12U] = v8_15.f4; ++ v.elements[13U] = v8_15.f5; ++ v.elements[14U] = v8_15.f6; ++ v.elements[15U] = v8_15.f7; ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_deserialize_4_0d(Eurydice_slice a) ++{ ++ return libcrux_ml_kem_vector_portable_serialize_deserialize_4(a); ++} ++ ++KRML_MUSTINLINE uint8_t_x5 ++libcrux_ml_kem_vector_portable_serialize_serialize_5_int(Eurydice_slice v) ++{ ++ uint8_t r0 = ++ (uint8_t)(Eurydice_slice_index(v, (size_t)0U, int16_t, int16_t *) | ++ Eurydice_slice_index(v, (size_t)1U, int16_t, int16_t *) << 5U); ++ uint8_t r1 = ++ (uint8_t)((Eurydice_slice_index(v, (size_t)1U, int16_t, int16_t *) >> 3U | ++ Eurydice_slice_index(v, (size_t)2U, int16_t, int16_t *) ++ << 2U) | ++ Eurydice_slice_index(v, (size_t)3U, int16_t, int16_t *) << 7U); ++ uint8_t r2 = ++ (uint8_t)(Eurydice_slice_index(v, (size_t)3U, int16_t, int16_t *) >> 1U | ++ Eurydice_slice_index(v, (size_t)4U, int16_t, int16_t *) << 4U); ++ uint8_t r3 = ++ (uint8_t)((Eurydice_slice_index(v, (size_t)4U, int16_t, int16_t *) >> 4U | ++ Eurydice_slice_index(v, (size_t)5U, int16_t, int16_t *) ++ << 1U) | ++ Eurydice_slice_index(v, (size_t)6U, int16_t, int16_t *) << 6U); ++ uint8_t r4 = ++ (uint8_t)(Eurydice_slice_index(v, (size_t)6U, int16_t, int16_t *) >> 2U | ++ Eurydice_slice_index(v, (size_t)7U, int16_t, int16_t *) << 3U); ++ return (CLITERAL(uint8_t_x5){ ++ .fst = r0, .snd = r1, .thd = r2, .f3 = r3, .f4 = r4 }); ++} ++ ++KRML_MUSTINLINE void ++libcrux_ml_kem_vector_portable_serialize_serialize_5( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, ++ uint8_t ret[10U]) ++{ ++ uint8_t_x5 r0_4 = libcrux_ml_kem_vector_portable_serialize_serialize_5_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)0U, (size_t)8U, int16_t)); ++ uint8_t_x5 r5_9 = libcrux_ml_kem_vector_portable_serialize_serialize_5_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)8U, (size_t)16U, ++ int16_t)); ++ uint8_t result[10U] = { 0U }; ++ result[0U] = r0_4.fst; ++ result[1U] = r0_4.snd; ++ result[2U] = r0_4.thd; ++ result[3U] = r0_4.f3; ++ result[4U] = r0_4.f4; ++ result[5U] = r5_9.fst; ++ result[6U] = r5_9.snd; ++ result[7U] = r5_9.thd; ++ result[8U] = r5_9.f3; ++ result[9U] = r5_9.f4; ++ memcpy(ret, result, (size_t)10U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++void ++libcrux_ml_kem_vector_portable_serialize_5_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, ++ uint8_t ret[10U]) ++{ ++ libcrux_ml_kem_vector_portable_serialize_serialize_5(a, ret); ++} ++ ++KRML_MUSTINLINE int16_t_x8 ++libcrux_ml_kem_vector_portable_serialize_deserialize_5_int( ++ Eurydice_slice bytes) ++{ ++ int16_t v0 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)0U, ++ uint8_t, uint8_t *) & ++ 31U); ++ int16_t v1 = (int16_t)(((uint32_t)Eurydice_slice_index(bytes, (size_t)1U, ++ uint8_t, uint8_t *) & ++ 3U) << 3U | ++ (uint32_t)Eurydice_slice_index(bytes, (size_t)0U, ++ uint8_t, uint8_t *) >> ++ 5U); ++ int16_t v2 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)1U, ++ uint8_t, uint8_t *) >> ++ 2U & ++ 31U); ++ int16_t v3 = (int16_t)(((uint32_t)Eurydice_slice_index(bytes, (size_t)2U, ++ uint8_t, uint8_t *) & ++ 15U) ++ << 1U | ++ (uint32_t)Eurydice_slice_index(bytes, (size_t)1U, ++ uint8_t, uint8_t *) >> ++ 7U); ++ int16_t v4 = (int16_t)(((uint32_t)Eurydice_slice_index(bytes, (size_t)3U, ++ uint8_t, uint8_t *) & ++ 1U) << 4U | ++ (uint32_t)Eurydice_slice_index(bytes, (size_t)2U, ++ uint8_t, uint8_t *) >> ++ 4U); ++ int16_t v5 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)3U, ++ uint8_t, uint8_t *) >> ++ 1U & ++ 31U); ++ int16_t v6 = (int16_t)(((uint32_t)Eurydice_slice_index(bytes, (size_t)4U, ++ uint8_t, uint8_t *) & ++ 7U) << 2U | ++ (uint32_t)Eurydice_slice_index(bytes, (size_t)3U, ++ uint8_t, uint8_t *) >> ++ 6U); ++ int16_t v7 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)4U, ++ uint8_t, uint8_t *) >> ++ 3U); ++ return (CLITERAL(int16_t_x8){ .fst = v0, ++ .snd = v1, ++ .thd = v2, ++ .f3 = v3, ++ .f4 = v4, ++ .f5 = v5, ++ .f6 = v6, ++ .f7 = v7 }); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_serialize_deserialize_5(Eurydice_slice bytes) ++{ ++ int16_t_x8 v0_7 = libcrux_ml_kem_vector_portable_serialize_deserialize_5_int( ++ Eurydice_slice_subslice2(bytes, (size_t)0U, (size_t)5U, uint8_t)); ++ int16_t_x8 v8_15 = libcrux_ml_kem_vector_portable_serialize_deserialize_5_int( ++ Eurydice_slice_subslice2(bytes, (size_t)5U, (size_t)10U, uint8_t)); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v = ++ libcrux_ml_kem_vector_portable_vector_type_zero(); ++ v.elements[0U] = v0_7.fst; ++ v.elements[1U] = v0_7.snd; ++ v.elements[2U] = v0_7.thd; ++ v.elements[3U] = v0_7.f3; ++ v.elements[4U] = v0_7.f4; ++ v.elements[5U] = v0_7.f5; ++ v.elements[6U] = v0_7.f6; ++ v.elements[7U] = v0_7.f7; ++ v.elements[8U] = v8_15.fst; ++ v.elements[9U] = v8_15.snd; ++ v.elements[10U] = v8_15.thd; ++ v.elements[11U] = v8_15.f3; ++ v.elements[12U] = v8_15.f4; ++ v.elements[13U] = v8_15.f5; ++ v.elements[14U] = v8_15.f6; ++ v.elements[15U] = v8_15.f7; ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_deserialize_5_0d(Eurydice_slice a) ++{ ++ return libcrux_ml_kem_vector_portable_serialize_deserialize_5(a); ++} ++ ++KRML_MUSTINLINE uint8_t_x5 ++libcrux_ml_kem_vector_portable_serialize_serialize_10_int(Eurydice_slice v) ++{ ++ uint8_t r0 = ++ (uint8_t)(Eurydice_slice_index(v, (size_t)0U, int16_t, int16_t *) & ++ (int16_t)255); ++ uint8_t r1 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)1U, int16_t, ++ int16_t *) & ++ (int16_t)63) ++ << 2U | ++ (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)0U, int16_t, ++ int16_t *) >> ++ 8U & ++ (int16_t)3); ++ uint8_t r2 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)2U, int16_t, ++ int16_t *) & ++ (int16_t)15) ++ << 4U | ++ (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)1U, int16_t, ++ int16_t *) >> ++ 6U & ++ (int16_t)15); ++ uint8_t r3 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)3U, int16_t, ++ int16_t *) & ++ (int16_t)3) ++ << 6U | ++ (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)2U, int16_t, ++ int16_t *) >> ++ 4U & ++ (int16_t)63); ++ uint8_t r4 = ++ (uint8_t)(Eurydice_slice_index(v, (size_t)3U, int16_t, int16_t *) >> 2U & ++ (int16_t)255); ++ return (CLITERAL(uint8_t_x5){ ++ .fst = r0, .snd = r1, .thd = r2, .f3 = r3, .f4 = r4 }); ++} ++ ++KRML_MUSTINLINE void ++libcrux_ml_kem_vector_portable_serialize_serialize_10( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, ++ uint8_t ret[20U]) ++{ ++ uint8_t_x5 r0_4 = libcrux_ml_kem_vector_portable_serialize_serialize_10_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)0U, (size_t)4U, int16_t)); ++ uint8_t_x5 r5_9 = libcrux_ml_kem_vector_portable_serialize_serialize_10_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)4U, (size_t)8U, int16_t)); ++ uint8_t_x5 r10_14 = libcrux_ml_kem_vector_portable_serialize_serialize_10_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)8U, (size_t)12U, ++ int16_t)); ++ uint8_t_x5 r15_19 = libcrux_ml_kem_vector_portable_serialize_serialize_10_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)12U, (size_t)16U, ++ int16_t)); ++ uint8_t result[20U] = { 0U }; ++ result[0U] = r0_4.fst; ++ result[1U] = r0_4.snd; ++ result[2U] = r0_4.thd; ++ result[3U] = r0_4.f3; ++ result[4U] = r0_4.f4; ++ result[5U] = r5_9.fst; ++ result[6U] = r5_9.snd; ++ result[7U] = r5_9.thd; ++ result[8U] = r5_9.f3; ++ result[9U] = r5_9.f4; ++ result[10U] = r10_14.fst; ++ result[11U] = r10_14.snd; ++ result[12U] = r10_14.thd; ++ result[13U] = r10_14.f3; ++ result[14U] = r10_14.f4; ++ result[15U] = r15_19.fst; ++ result[16U] = r15_19.snd; ++ result[17U] = r15_19.thd; ++ result[18U] = r15_19.f3; ++ result[19U] = r15_19.f4; ++ memcpy(ret, result, (size_t)20U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++void ++libcrux_ml_kem_vector_portable_serialize_10_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, ++ uint8_t ret[20U]) ++{ ++ libcrux_ml_kem_vector_portable_serialize_serialize_10(a, ret); ++} ++ ++KRML_MUSTINLINE int16_t_x8 ++libcrux_ml_kem_vector_portable_serialize_deserialize_10_int( ++ Eurydice_slice bytes) ++{ ++ int16_t r0 = ++ ((int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *) & ++ (int16_t)3) ++ << 8U | ++ ((int16_t)Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *) & ++ (int16_t)255); ++ int16_t r1 = ++ ((int16_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, uint8_t *) & ++ (int16_t)15) ++ << 6U | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *) >> ++ 2U; ++ int16_t r2 = ++ ((int16_t)Eurydice_slice_index(bytes, (size_t)3U, uint8_t, uint8_t *) & ++ (int16_t)63) ++ << 4U | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, uint8_t *) >> ++ 4U; ++ int16_t r3 = ++ (int16_t)Eurydice_slice_index(bytes, (size_t)4U, uint8_t, uint8_t *) ++ << 2U | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)3U, uint8_t, uint8_t *) >> ++ 6U; ++ int16_t r4 = ++ ((int16_t)Eurydice_slice_index(bytes, (size_t)6U, uint8_t, uint8_t *) & ++ (int16_t)3) ++ << 8U | ++ ((int16_t)Eurydice_slice_index(bytes, (size_t)5U, uint8_t, uint8_t *) & ++ (int16_t)255); ++ int16_t r5 = ++ ((int16_t)Eurydice_slice_index(bytes, (size_t)7U, uint8_t, uint8_t *) & ++ (int16_t)15) ++ << 6U | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)6U, uint8_t, uint8_t *) >> ++ 2U; ++ int16_t r6 = ++ ((int16_t)Eurydice_slice_index(bytes, (size_t)8U, uint8_t, uint8_t *) & ++ (int16_t)63) ++ << 4U | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)7U, uint8_t, uint8_t *) >> ++ 4U; ++ int16_t r7 = ++ (int16_t)Eurydice_slice_index(bytes, (size_t)9U, uint8_t, uint8_t *) ++ << 2U | ++ (int16_t)Eurydice_slice_index(bytes, (size_t)8U, uint8_t, uint8_t *) >> ++ 6U; ++ return (CLITERAL(int16_t_x8){ .fst = r0, ++ .snd = r1, ++ .thd = r2, ++ .f3 = r3, ++ .f4 = r4, ++ .f5 = r5, ++ .f6 = r6, ++ .f7 = r7 }); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_serialize_deserialize_10(Eurydice_slice bytes) ++{ ++ int16_t_x8 v0_7 = libcrux_ml_kem_vector_portable_serialize_deserialize_10_int( ++ Eurydice_slice_subslice2(bytes, (size_t)0U, (size_t)10U, uint8_t)); ++ int16_t_x8 v8_15 = ++ libcrux_ml_kem_vector_portable_serialize_deserialize_10_int( ++ Eurydice_slice_subslice2(bytes, (size_t)10U, (size_t)20U, uint8_t)); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v = ++ libcrux_ml_kem_vector_portable_vector_type_zero(); ++ v.elements[0U] = v0_7.fst; ++ v.elements[1U] = v0_7.snd; ++ v.elements[2U] = v0_7.thd; ++ v.elements[3U] = v0_7.f3; ++ v.elements[4U] = v0_7.f4; ++ v.elements[5U] = v0_7.f5; ++ v.elements[6U] = v0_7.f6; ++ v.elements[7U] = v0_7.f7; ++ v.elements[8U] = v8_15.fst; ++ v.elements[9U] = v8_15.snd; ++ v.elements[10U] = v8_15.thd; ++ v.elements[11U] = v8_15.f3; ++ v.elements[12U] = v8_15.f4; ++ v.elements[13U] = v8_15.f5; ++ v.elements[14U] = v8_15.f6; ++ v.elements[15U] = v8_15.f7; ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_deserialize_10_0d(Eurydice_slice a) ++{ ++ return libcrux_ml_kem_vector_portable_serialize_deserialize_10(a); ++} ++ ++KRML_MUSTINLINE uint8_t_x3 ++libcrux_ml_kem_vector_portable_serialize_serialize_12_int(Eurydice_slice v) ++{ ++ uint8_t r0 = ++ (uint8_t)(Eurydice_slice_index(v, (size_t)0U, int16_t, int16_t *) & ++ (int16_t)255); ++ uint8_t r1 = ++ (uint8_t)(Eurydice_slice_index(v, (size_t)0U, int16_t, int16_t *) >> 8U | ++ (Eurydice_slice_index(v, (size_t)1U, int16_t, int16_t *) & ++ (int16_t)15) ++ << 4U); ++ uint8_t r2 = ++ (uint8_t)(Eurydice_slice_index(v, (size_t)1U, int16_t, int16_t *) >> 4U & ++ (int16_t)255); ++ return (CLITERAL(uint8_t_x3){ .fst = r0, .snd = r1, .thd = r2 }); ++} ++ ++KRML_MUSTINLINE void ++libcrux_ml_kem_vector_portable_serialize_serialize_12( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, ++ uint8_t ret[24U]) ++{ ++ uint8_t_x3 r0_2 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)0U, (size_t)2U, int16_t)); ++ uint8_t_x3 r3_5 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)2U, (size_t)4U, int16_t)); ++ uint8_t_x3 r6_8 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)4U, (size_t)6U, int16_t)); ++ uint8_t_x3 r9_11 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)6U, (size_t)8U, int16_t)); ++ uint8_t_x3 r12_14 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)8U, (size_t)10U, ++ int16_t)); ++ uint8_t_x3 r15_17 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)10U, (size_t)12U, ++ int16_t)); ++ uint8_t_x3 r18_20 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)12U, (size_t)14U, ++ int16_t)); ++ uint8_t_x3 r21_23 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( ++ Eurydice_array_to_subslice2(v.elements, (size_t)14U, (size_t)16U, ++ int16_t)); ++ uint8_t result[24U] = { 0U }; ++ result[0U] = r0_2.fst; ++ result[1U] = r0_2.snd; ++ result[2U] = r0_2.thd; ++ result[3U] = r3_5.fst; ++ result[4U] = r3_5.snd; ++ result[5U] = r3_5.thd; ++ result[6U] = r6_8.fst; ++ result[7U] = r6_8.snd; ++ result[8U] = r6_8.thd; ++ result[9U] = r9_11.fst; ++ result[10U] = r9_11.snd; ++ result[11U] = r9_11.thd; ++ result[12U] = r12_14.fst; ++ result[13U] = r12_14.snd; ++ result[14U] = r12_14.thd; ++ result[15U] = r15_17.fst; ++ result[16U] = r15_17.snd; ++ result[17U] = r15_17.thd; ++ result[18U] = r18_20.fst; ++ result[19U] = r18_20.snd; ++ result[20U] = r18_20.thd; ++ result[21U] = r21_23.fst; ++ result[22U] = r21_23.snd; ++ result[23U] = r21_23.thd; ++ memcpy(ret, result, (size_t)24U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++void ++libcrux_ml_kem_vector_portable_serialize_12_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, ++ uint8_t ret[24U]) ++{ ++ libcrux_ml_kem_vector_portable_serialize_serialize_12(a, ret); ++} ++ ++KRML_MUSTINLINE int16_t_x2 ++libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( ++ Eurydice_slice bytes) ++{ ++ int16_t byte0 = ++ (int16_t)Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *); ++ int16_t byte1 = ++ (int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *); ++ int16_t byte2 = ++ (int16_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, uint8_t *); ++ int16_t r0 = (byte1 & (int16_t)15) << 8U | (byte0 & (int16_t)255); ++ int16_t r1 = byte2 << 4U | (byte1 >> 4U & (int16_t)15); ++ return (CLITERAL(int16_t_x2){ .fst = r0, .snd = r1 }); ++} ++ ++KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_serialize_deserialize_12(Eurydice_slice bytes) ++{ ++ int16_t_x2 v0_1 = libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( ++ Eurydice_slice_subslice2(bytes, (size_t)0U, (size_t)3U, uint8_t)); ++ int16_t_x2 v2_3 = libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( ++ Eurydice_slice_subslice2(bytes, (size_t)3U, (size_t)6U, uint8_t)); ++ int16_t_x2 v4_5 = libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( ++ Eurydice_slice_subslice2(bytes, (size_t)6U, (size_t)9U, uint8_t)); ++ int16_t_x2 v6_7 = libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( ++ Eurydice_slice_subslice2(bytes, (size_t)9U, (size_t)12U, uint8_t)); ++ int16_t_x2 v8_9 = libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( ++ Eurydice_slice_subslice2(bytes, (size_t)12U, (size_t)15U, uint8_t)); ++ int16_t_x2 v10_11 = ++ libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( ++ Eurydice_slice_subslice2(bytes, (size_t)15U, (size_t)18U, uint8_t)); ++ int16_t_x2 v12_13 = ++ libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( ++ Eurydice_slice_subslice2(bytes, (size_t)18U, (size_t)21U, uint8_t)); ++ int16_t_x2 v14_15 = ++ libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( ++ Eurydice_slice_subslice2(bytes, (size_t)21U, (size_t)24U, uint8_t)); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector re = ++ libcrux_ml_kem_vector_portable_vector_type_zero(); ++ re.elements[0U] = v0_1.fst; ++ re.elements[1U] = v0_1.snd; ++ re.elements[2U] = v2_3.fst; ++ re.elements[3U] = v2_3.snd; ++ re.elements[4U] = v4_5.fst; ++ re.elements[5U] = v4_5.snd; ++ re.elements[6U] = v6_7.fst; ++ re.elements[7U] = v6_7.snd; ++ re.elements[8U] = v8_9.fst; ++ re.elements[9U] = v8_9.snd; ++ re.elements[10U] = v10_11.fst; ++ re.elements[11U] = v10_11.snd; ++ re.elements[12U] = v12_13.fst; ++ re.elements[13U] = v12_13.snd; ++ re.elements[14U] = v14_15.fst; ++ re.elements[15U] = v14_15.snd; ++ return re; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_deserialize_12_0d(Eurydice_slice a) ++{ ++ return libcrux_ml_kem_vector_portable_serialize_deserialize_12(a); ++} ++ ++KRML_MUSTINLINE size_t ++libcrux_ml_kem_vector_portable_sampling_rej_sample( ++ Eurydice_slice a, Eurydice_slice result) ++{ ++ size_t sampled = (size_t)0U; ++ for (size_t i = (size_t)0U; i < Eurydice_slice_len(a, uint8_t) / (size_t)3U; ++ i++) { ++ size_t i0 = i; ++ int16_t b1 = (int16_t)Eurydice_slice_index(a, i0 * (size_t)3U + (size_t)0U, ++ uint8_t, uint8_t *); ++ int16_t b2 = (int16_t)Eurydice_slice_index(a, i0 * (size_t)3U + (size_t)1U, ++ uint8_t, uint8_t *); ++ int16_t b3 = (int16_t)Eurydice_slice_index(a, i0 * (size_t)3U + (size_t)2U, ++ uint8_t, uint8_t *); ++ int16_t d1 = (b2 & (int16_t)15) << 8U | b1; ++ int16_t d2 = b3 << 4U | b2 >> 4U; ++ bool uu____0; ++ int16_t uu____1; ++ bool uu____2; ++ size_t uu____3; ++ int16_t uu____4; ++ size_t uu____5; ++ int16_t uu____6; ++ if (d1 < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS) { ++ if (sampled < (size_t)16U) { ++ Eurydice_slice_index(result, sampled, int16_t, int16_t *) = d1; ++ sampled++; ++ uu____1 = d2; ++ uu____6 = LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; ++ uu____0 = uu____1 < uu____6; ++ if (uu____0) { ++ uu____3 = sampled; ++ uu____2 = uu____3 < (size_t)16U; ++ if (uu____2) { ++ uu____4 = d2; ++ uu____5 = sampled; ++ Eurydice_slice_index(result, uu____5, int16_t, int16_t *) = uu____4; ++ sampled++; ++ continue; ++ } ++ } ++ continue; ++ } ++ } ++ uu____1 = d2; ++ uu____6 = LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; ++ uu____0 = uu____1 < uu____6; ++ if (uu____0) { ++ uu____3 = sampled; ++ uu____2 = uu____3 < (size_t)16U; ++ if (uu____2) { ++ uu____4 = d2; ++ uu____5 = sampled; ++ Eurydice_slice_index(result, uu____5, int16_t, int16_t *) = uu____4; ++ sampled++; ++ continue; ++ } ++ } ++ } ++ return sampled; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++size_t ++libcrux_ml_kem_vector_portable_rej_sample_0d(Eurydice_slice a, ++ Eurydice_slice out) ++{ ++ return libcrux_ml_kem_vector_portable_sampling_rej_sample(a, out); ++} ++ ++/** ++This function found in impl {(core::clone::Clone for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++inline libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_vector_type_clone_3b( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *self) ++{ ++ return self[0U]; ++} ++ ++/** ++This function found in impl ++{libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.polynomial.ZERO_89 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++ZERO_89_c3(void) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 lit; ++ lit.coefficients[0U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[1U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[2U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[3U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[4U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[5U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[6U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[7U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[8U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[9U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[10U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[11U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[12U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[13U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[14U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ lit.coefficients[15U] = libcrux_ml_kem_vector_portable_ZERO_0d(); ++ return lit; ++} ++ ++/** ++ Only use with public values. ++ ++ This MUST NOT be used with secret inputs, like its caller ++ `deserialize_ring_elements_reduced`. ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_to_reduced_ring_element with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++ ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++deserialize_to_reduced_ring_element_45(Eurydice_slice serialized) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = ZERO_89_c3(); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(serialized, uint8_t) / (size_t)24U; i++) { ++ size_t i0 = i; ++ Eurydice_slice bytes = Eurydice_slice_subslice2( ++ serialized, i0 * (size_t)24U, i0 * (size_t)24U + (size_t)24U, uint8_t); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = ++ libcrux_ml_kem_vector_portable_deserialize_12_0d(bytes); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_cond_subtract_3329_0d(coefficient); ++ re.coefficients[i0] = uu____0; ++ } ++ return re; ++} ++ ++/** ++ This function deserializes ring elements and reduces the result by the field ++ modulus. ++ ++ This function MUST NOT be used on secret inputs. ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_ring_elements_reduced with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- PUBLIC_KEY_SIZE= 1568 ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++deserialize_ring_elements_reduced_4f4( ++ Eurydice_slice public_key, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[4U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 deserialized_pk[4U]; ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, ++ deserialized_pk[i] = ZERO_89_c3();); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(public_key, uint8_t) / ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; ++ i++) { ++ size_t i0 = i; ++ Eurydice_slice ring_element = Eurydice_slice_subslice2( ++ public_key, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ uint8_t); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____0 = ++ deserialize_to_reduced_ring_element_45(ring_element); ++ deserialized_pk[i0] = uu____0; ++ } ++ memcpy( ++ ret, deserialized_pk, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.vector.portable.arithmetic.shift_right ++with const generics ++- SHIFT_BY= 15 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++shift_right_b0(libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ v.elements[i0] = v.elements[i0] >> (uint32_t)(int32_t)15; ++ } ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.vector.portable.shift_right_0d ++with const generics ++- SHIFT_BY= 15 ++*/ ++static libcrux_ml_kem_vector_portable_vector_type_PortableVector ++shift_right_0d_01(libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ return shift_right_b0(v); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.vector.traits.to_unsigned_representative with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++ ++*/ ++static libcrux_ml_kem_vector_portable_vector_type_PortableVector ++to_unsigned_representative_84( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a) ++{ ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector t = ++ shift_right_0d_01(a); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector fm = ++ libcrux_ml_kem_vector_portable_bitwise_and_with_constant_0d( ++ t, LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS); ++ return libcrux_ml_kem_vector_portable_add_0d(a, &fm); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.serialize_uncompressed_ring_element with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++serialize_uncompressed_ring_element_3c( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, uint8_t ret[384U]) ++{ ++ uint8_t serialized[384U] = { 0U }; ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = ++ to_unsigned_representative_84(re->coefficients[i0]); ++ uint8_t bytes[24U]; ++ libcrux_ml_kem_vector_portable_serialize_12_0d(coefficient, bytes); ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ serialized, (size_t)24U * i0, (size_t)24U * i0 + (size_t)24U, uint8_t); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)24U, bytes, uint8_t), uint8_t); ++ } ++ memcpy(ret, serialized, (size_t)384U * sizeof(uint8_t)); ++} ++ ++/** ++ Call [`serialize_uncompressed_ring_element`] for each ring element. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.serialize_secret_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++- OUT_LEN= 1536 ++*/ ++static KRML_MUSTINLINE void ++serialize_secret_key_a31( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *key, ++ uint8_t ret[1536U]) ++{ ++ uint8_t out[1536U] = { 0U }; ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)4U, key, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = key[i0]; ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ out, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ (i0 + (size_t)1U) * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ uint8_t); ++ uint8_t ret0[384U]; ++ serialize_uncompressed_ring_element_3c(&re, ret0); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)384U, ret0, uint8_t), uint8_t); ++ } ++ memcpy(ret, out, (size_t)1536U * sizeof(uint8_t)); ++} ++ ++/** ++ Concatenate `t` and `ρ` into the public key. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.serialize_public_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++- RANKED_BYTES_PER_RING_ELEMENT= 1536 ++- PUBLIC_KEY_SIZE= 1568 ++*/ ++static KRML_MUSTINLINE void ++serialize_public_key_671( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *t_as_ntt, ++ Eurydice_slice seed_for_a, uint8_t ret[1568U]) ++{ ++ uint8_t public_key_serialized[1568U] = { 0U }; ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ public_key_serialized, (size_t)0U, (size_t)1536U, uint8_t); ++ uint8_t ret0[1536U]; ++ serialize_secret_key_a31(t_as_ntt, ret0); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)1536U, ret0, uint8_t), uint8_t); ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice_from((size_t)1568U, public_key_serialized, ++ (size_t)1536U, uint8_t, size_t), ++ seed_for_a, uint8_t); ++ memcpy(ret, public_key_serialized, (size_t)1568U * sizeof(uint8_t)); ++} ++ ++/** ++ Validate an ML-KEM public key. ++ ++ This implements the Modulus check in 7.2 2. ++ Note that the size check in 7.2 1 is covered by the `PUBLIC_KEY_SIZE` in the ++ `public_key` type. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.validate_public_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++- RANKED_BYTES_PER_RING_ELEMENT= 1536 ++- PUBLIC_KEY_SIZE= 1568 ++*/ ++bool ++libcrux_ml_kem_ind_cca_validate_public_key_b71(uint8_t *public_key) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 deserialized_pk[4U]; ++ deserialize_ring_elements_reduced_4f4( ++ Eurydice_array_to_subslice_to((size_t)1568U, public_key, (size_t)1536U, ++ uint8_t, size_t), ++ deserialized_pk); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *uu____0 = deserialized_pk; ++ uint8_t public_key_serialized[1568U]; ++ serialize_public_key_671( ++ uu____0, ++ Eurydice_array_to_subslice_from((size_t)1568U, public_key, (size_t)1536U, ++ uint8_t, size_t), ++ public_key_serialized); ++ return core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( ++ (size_t)1568U, public_key, public_key_serialized, uint8_t, uint8_t, bool); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.H_f1 ++with const generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++H_f1_191(Eurydice_slice input, uint8_t ret[32U]) ++{ ++ libcrux_ml_kem_hash_functions_portable_H(input, ret); ++} ++ ++/** ++ Validate an ML-KEM private key. ++ ++ This implements the Hash check in 7.3 3. ++ Note that the size checks in 7.2 1 and 2 are covered by the `SECRET_KEY_SIZE` ++ and `CIPHERTEXT_SIZE` in the `private_key` and `ciphertext` types. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.validate_private_key ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]] ++with const generics ++- K= 4 ++- SECRET_KEY_SIZE= 3168 ++- CIPHERTEXT_SIZE= 1568 ++*/ ++bool ++libcrux_ml_kem_ind_cca_validate_private_key_dc( ++ libcrux_ml_kem_types_MlKemPrivateKey_95 *private_key, ++ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *_ciphertext) ++{ ++ uint8_t t[32U]; ++ H_f1_191(Eurydice_array_to_subslice2( ++ private_key->value, (size_t)384U * (size_t)4U, ++ (size_t)768U * (size_t)4U + (size_t)32U, uint8_t), ++ t); ++ Eurydice_slice expected = Eurydice_array_to_subslice2( ++ private_key->value, (size_t)768U * (size_t)4U + (size_t)32U, ++ (size_t)768U * (size_t)4U + (size_t)64U, uint8_t); ++ return core_array_equality___core__cmp__PartialEq__0___Slice_U____for__Array_T__N___3__eq( ++ (size_t)32U, t, &expected, uint8_t, uint8_t, bool); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.G_f1 ++with const generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++G_f1_381(Eurydice_slice input, uint8_t ret[64U]) ++{ ++ libcrux_ml_kem_hash_functions_portable_G(input, ret); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::variant::Variant for ++libcrux_ml_kem::variant::MlKem)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.variant.cpa_keygen_seed_d8 ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]] ++with const generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++cpa_keygen_seed_d8_72( ++ Eurydice_slice key_generation_seed, uint8_t ret[64U]) ++{ ++ uint8_t seed[33U] = { 0U }; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2( ++ seed, (size_t)0U, ++ LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t), ++ key_generation_seed, uint8_t); ++ seed[LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE] = ++ (uint8_t)(size_t)4U; ++ uint8_t ret0[64U]; ++ G_f1_381(Eurydice_array_to_slice((size_t)33U, seed, uint8_t), ret0); ++ memcpy(ret, ret0, (size_t)64U * sizeof(uint8_t)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.sample_matrix_A.closure ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]] with const ++generics ++- K= 4 ++*/ ++static void ++closure_fc1( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[4U]) ++{ ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, ++ ret[i] = ZERO_89_c3();); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PortableHash ++with const generics ++- $4size_t ++*/ ++typedef struct PortableHash_d1_s { ++ libcrux_sha3_generic_keccak_KeccakState_48 shake128_state[4U]; ++} PortableHash_d1; ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_init_absorb with const generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE PortableHash_d1 ++shake128_init_absorb_791(uint8_t input[4U][34U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakState_48 shake128_state[4U]; ++ KRML_MAYBE_FOR4( ++ i, (size_t)0U, (size_t)4U, (size_t)1U, ++ shake128_state[i] = libcrux_sha3_portable_incremental_shake128_init();); ++ KRML_MAYBE_FOR4( ++ i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; ++ libcrux_sha3_portable_incremental_shake128_absorb_final( ++ &shake128_state[i0], ++ Eurydice_array_to_slice((size_t)34U, input[i0], uint8_t));); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ libcrux_sha3_generic_keccak_KeccakState_48 copy_of_shake128_state[4U]; ++ memcpy(copy_of_shake128_state, shake128_state, ++ (size_t)4U * sizeof(libcrux_sha3_generic_keccak_KeccakState_48)); ++ PortableHash_d1 lit; ++ memcpy(lit.shake128_state, copy_of_shake128_state, ++ (size_t)4U * sizeof(libcrux_sha3_generic_keccak_KeccakState_48)); ++ return lit; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_init_absorb_f1 with const ++generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE PortableHash_d1 ++shake128_init_absorb_f1_771(uint8_t input[4U][34U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_input[4U][34U]; ++ memcpy(copy_of_input, input, (size_t)4U * sizeof(uint8_t[34U])); ++ return shake128_init_absorb_791(copy_of_input); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_squeeze_three_blocks with const ++generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++shake128_squeeze_three_blocks_eb1( ++ PortableHash_d1 *st, uint8_t ret[4U][504U]) ++{ ++ uint8_t out[4U][504U] = { { 0U } }; ++ KRML_MAYBE_FOR4( ++ i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; ++ libcrux_sha3_portable_incremental_shake128_squeeze_first_three_blocks( ++ &st->shake128_state[i0], ++ Eurydice_array_to_slice((size_t)504U, out[i0], uint8_t));); ++ memcpy(ret, out, (size_t)4U * sizeof(uint8_t[504U])); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_squeeze_three_blocks_f1 with ++const generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++shake128_squeeze_three_blocks_f1_841( ++ PortableHash_d1 *self, uint8_t ret[4U][504U]) ++{ ++ shake128_squeeze_three_blocks_eb1(self, ret); ++} ++ ++/** ++ If `bytes` contains a set of uniformly random bytes, this function ++ uniformly samples a ring element `â` that is treated as being the NTT ++ representation of the corresponding polynomial `a`. ++ ++ Since rejection sampling is used, it is possible the supplied bytes are ++ not enough to sample the element, in which case an `Err` is returned and the ++ caller must try again with a fresh set of bytes. ++ ++ This function partially implements Algorithm ++ 6 of the NIST FIPS 203 standard, We say "partially" because this ++ implementation only accepts a finite set of bytes as input and returns an error ++ if the set is not enough; Algorithm 6 of the FIPS 203 standard on the other ++ hand samples from an infinite stream of bytes until the ring element is filled. ++ Algorithm 6 is reproduced below: ++ ++ ```plaintext ++ Input: byte stream B ∈ 𝔹*. ++ Output: array â ∈ ℤ₂₅₆. ++ ++ i ← 0 ++ j ← 0 ++ while j < 256 do ++ d₁ ← B[i] + 256·(B[i+1] mod 16) ++ d₂ ← ⌊B[i+1]/16⌋ + 16·B[i+2] ++ if d₁ < q then ++ â[j] ← d₁ ++ j ← j + 1 ++ end if ++ if d₂ < q and j < 256 then ++ â[j] ← d₂ ++ j ← j + 1 ++ end if ++ i ← i + 3 ++ end while ++ return â ++ ``` ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.sampling.sample_from_uniform_distribution_next with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- K= 4 ++- N= 504 ++*/ ++static KRML_MUSTINLINE bool ++sample_from_uniform_distribution_next_173( ++ uint8_t randomness[4U][504U], size_t *sampled_coefficients, ++ int16_t (*out)[272U]) ++{ ++ KRML_MAYBE_FOR4( ++ i0, (size_t)0U, (size_t)4U, (size_t)1U, size_t i1 = i0; ++ for (size_t i = (size_t)0U; i < (size_t)504U / (size_t)24U; i++) { ++ size_t r = i; ++ if (sampled_coefficients[i1] < ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ randomness[i1], r * (size_t)24U, r * (size_t)24U + (size_t)24U, ++ uint8_t); ++ size_t sampled = libcrux_ml_kem_vector_portable_rej_sample_0d( ++ uu____0, Eurydice_array_to_subslice2( ++ out[i1], sampled_coefficients[i1], ++ sampled_coefficients[i1] + (size_t)16U, int16_t)); ++ size_t uu____1 = i1; ++ sampled_coefficients[uu____1] = ++ sampled_coefficients[uu____1] + sampled; ++ } ++ }); ++ bool done = true; ++ KRML_MAYBE_FOR4( ++ i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; ++ if (sampled_coefficients[i0] >= ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { ++ sampled_coefficients[i0] = ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; ++ } else { done = false; }); ++ return done; ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_squeeze_block with const ++generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++shake128_squeeze_block_3b1(PortableHash_d1 *st, ++ uint8_t ret[4U][168U]) ++{ ++ uint8_t out[4U][168U] = { { 0U } }; ++ KRML_MAYBE_FOR4( ++ i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; ++ libcrux_sha3_portable_incremental_shake128_squeeze_next_block( ++ &st->shake128_state[i0], ++ Eurydice_array_to_slice((size_t)168U, out[i0], uint8_t));); ++ memcpy(ret, out, (size_t)4U * sizeof(uint8_t[168U])); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_squeeze_block_f1 with const ++generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++shake128_squeeze_block_f1_8e1( ++ PortableHash_d1 *self, uint8_t ret[4U][168U]) ++{ ++ shake128_squeeze_block_3b1(self, ret); ++} ++ ++/** ++ If `bytes` contains a set of uniformly random bytes, this function ++ uniformly samples a ring element `â` that is treated as being the NTT ++ representation of the corresponding polynomial `a`. ++ ++ Since rejection sampling is used, it is possible the supplied bytes are ++ not enough to sample the element, in which case an `Err` is returned and the ++ caller must try again with a fresh set of bytes. ++ ++ This function partially implements Algorithm ++ 6 of the NIST FIPS 203 standard, We say "partially" because this ++ implementation only accepts a finite set of bytes as input and returns an error ++ if the set is not enough; Algorithm 6 of the FIPS 203 standard on the other ++ hand samples from an infinite stream of bytes until the ring element is filled. ++ Algorithm 6 is reproduced below: ++ ++ ```plaintext ++ Input: byte stream B ∈ 𝔹*. ++ Output: array â ∈ ℤ₂₅₆. ++ ++ i ← 0 ++ j ← 0 ++ while j < 256 do ++ d₁ ← B[i] + 256·(B[i+1] mod 16) ++ d₂ ← ⌊B[i+1]/16⌋ + 16·B[i+2] ++ if d₁ < q then ++ â[j] ← d₁ ++ j ← j + 1 ++ end if ++ if d₂ < q and j < 256 then ++ â[j] ← d₂ ++ j ← j + 1 ++ end if ++ i ← i + 3 ++ end while ++ return â ++ ``` ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.sampling.sample_from_uniform_distribution_next with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- K= 4 ++- N= 168 ++*/ ++static KRML_MUSTINLINE bool ++sample_from_uniform_distribution_next_174( ++ uint8_t randomness[4U][168U], size_t *sampled_coefficients, ++ int16_t (*out)[272U]) ++{ ++ KRML_MAYBE_FOR4( ++ i0, (size_t)0U, (size_t)4U, (size_t)1U, size_t i1 = i0; ++ for (size_t i = (size_t)0U; i < (size_t)168U / (size_t)24U; i++) { ++ size_t r = i; ++ if (sampled_coefficients[i1] < ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ randomness[i1], r * (size_t)24U, r * (size_t)24U + (size_t)24U, ++ uint8_t); ++ size_t sampled = libcrux_ml_kem_vector_portable_rej_sample_0d( ++ uu____0, Eurydice_array_to_subslice2( ++ out[i1], sampled_coefficients[i1], ++ sampled_coefficients[i1] + (size_t)16U, int16_t)); ++ size_t uu____1 = i1; ++ sampled_coefficients[uu____1] = ++ sampled_coefficients[uu____1] + sampled; ++ } ++ }); ++ bool done = true; ++ KRML_MAYBE_FOR4( ++ i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; ++ if (sampled_coefficients[i0] >= ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { ++ sampled_coefficients[i0] = ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; ++ } else { done = false; }); ++ return done; ++} ++ ++/** ++This function found in impl ++{libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.polynomial.from_i16_array_89 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++from_i16_array_89_33(Eurydice_slice a) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result = ZERO_89_c3(); ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_from_i16_array_0d( ++ Eurydice_slice_subslice2(a, i0 * (size_t)16U, ++ (i0 + (size_t)1U) * (size_t)16U, int16_t)); ++ result.coefficients[i0] = uu____0; ++ } ++ return result; ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.sampling.sample_from_xof.closure ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]] with const ++generics ++- K= 4 ++*/ ++static libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++closure_e41( ++ int16_t s[272U]) ++{ ++ return from_i16_array_89_33( ++ Eurydice_array_to_subslice2(s, (size_t)0U, (size_t)256U, int16_t)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.sampling.sample_from_xof ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]] with const ++generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++sample_from_xof_461( ++ uint8_t seeds[4U][34U], ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[4U]) ++{ ++ size_t sampled_coefficients[4U] = { 0U }; ++ int16_t out[4U][272U] = { { 0U } }; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_seeds[4U][34U]; ++ memcpy(copy_of_seeds, seeds, (size_t)4U * sizeof(uint8_t[34U])); ++ PortableHash_d1 xof_state = shake128_init_absorb_f1_771(copy_of_seeds); ++ uint8_t randomness0[4U][504U]; ++ shake128_squeeze_three_blocks_f1_841(&xof_state, randomness0); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_randomness0[4U][504U]; ++ memcpy(copy_of_randomness0, randomness0, (size_t)4U * sizeof(uint8_t[504U])); ++ bool done = sample_from_uniform_distribution_next_173( ++ copy_of_randomness0, sampled_coefficients, out); ++ while (true) { ++ if (done) { ++ break; ++ } else { ++ uint8_t randomness[4U][168U]; ++ shake128_squeeze_block_f1_8e1(&xof_state, randomness); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_randomness[4U][168U]; ++ memcpy(copy_of_randomness, randomness, ++ (size_t)4U * sizeof(uint8_t[168U])); ++ done = sample_from_uniform_distribution_next_174( ++ copy_of_randomness, sampled_coefficients, out); ++ } ++ } ++ /* Passing arrays by value in Rust generates a copy in C */ ++ int16_t copy_of_out[4U][272U]; ++ memcpy(copy_of_out, out, (size_t)4U * sizeof(int16_t[272U])); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret0[4U]; ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, ++ ret0[i] = closure_e41(copy_of_out[i]);); ++ memcpy( ++ ret, ret0, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.sample_matrix_A ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]] with const ++generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++sample_matrix_A_e71( ++ uint8_t seed[34U], bool transpose, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[4U][4U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 A_transpose[4U][4U]; ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, ++ closure_fc1(A_transpose[i]);); ++ KRML_MAYBE_FOR4( ++ i0, (size_t)0U, (size_t)4U, (size_t)1U, size_t i1 = i0; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_seed[34U]; ++ memcpy(copy_of_seed, seed, (size_t)34U * sizeof(uint8_t)); ++ uint8_t seeds[4U][34U]; KRML_MAYBE_FOR4( ++ i, (size_t)0U, (size_t)4U, (size_t)1U, ++ memcpy(seeds[i], copy_of_seed, (size_t)34U * sizeof(uint8_t));); ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, size_t j = i; ++ seeds[j][32U] = (uint8_t)i1; seeds[j][33U] = (uint8_t)j;); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_seeds[4U][34U]; ++ memcpy(copy_of_seeds, seeds, (size_t)4U * sizeof(uint8_t[34U])); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 sampled[4U]; ++ sample_from_xof_461(copy_of_seeds, sampled); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)4U, sampled, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t j = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 sample = sampled[j]; ++ if (transpose) { ++ A_transpose[j][i1] = sample; ++ } else { ++ A_transpose[i1][j] = sample; ++ } ++ } ++ ++ ); ++ memcpy(ret, A_transpose, ++ (size_t)4U * ++ sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0[4U])); ++} ++ ++/** ++A monomorphic instance of K. ++with types libcrux_ml_kem_polynomial_PolynomialRingElement ++libcrux_ml_kem_vector_portable_vector_type_PortableVector[4size_t], uint8_t ++ ++*/ ++typedef struct tuple_710_s { ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 fst[4U]; ++ uint8_t snd; ++} tuple_710; ++ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRFxN ++with const generics ++- K= 4 ++- LEN= 128 ++*/ ++static KRML_MUSTINLINE void ++PRFxN_1c2(uint8_t (*input)[33U], ++ uint8_t ret[4U][128U]) ++{ ++ uint8_t out[4U][128U] = { { 0U } }; ++ KRML_MAYBE_FOR4( ++ i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; ++ libcrux_sha3_portable_shake256( ++ Eurydice_array_to_slice((size_t)128U, out[i0], uint8_t), ++ Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t));); ++ memcpy(ret, out, (size_t)4U * sizeof(uint8_t[128U])); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRFxN_f1 ++with const generics ++- K= 4 ++- LEN= 128 ++*/ ++static KRML_MUSTINLINE void ++PRFxN_f1_d52(uint8_t (*input)[33U], ++ uint8_t ret[4U][128U]) ++{ ++ PRFxN_1c2(input, ret); ++} ++ ++/** ++ Given a series of uniformly random bytes in `randomness`, for some number ++ `eta`, the `sample_from_binomial_distribution_{eta}` functions sample a ring ++ element from a binomial distribution centered at 0 that uses two sets of `eta` ++ coin flips. If, for example, `eta = ETA`, each ring coefficient is a value `v` ++ such such that `v ∈ {-ETA, -ETA + 1, ..., 0, ..., ETA + 1, ETA}` and: ++ ++ ```plaintext ++ - If v < 0, Pr[v] = Pr[-v] ++ - If v >= 0, Pr[v] = BINOMIAL_COEFFICIENT(2 * ETA; ETA - v) / 2 ^ (2 * ETA) ++ ``` ++ ++ The values `v < 0` are mapped to the appropriate `KyberFieldElement`. ++ ++ The expected value is: ++ ++ ```plaintext ++ E[X] = (-ETA)Pr[-ETA] + (-(ETA - 1))Pr[-(ETA - 1)] + ... + (ETA - 1)Pr[ETA - 1] ++ + (ETA)Pr[ETA] = 0 since Pr[-v] = Pr[v] when v < 0. ++ ``` ++ ++ And the variance is: ++ ++ ```plaintext ++ Var(X) = E[(X - E[X])^2] ++ = E[X^2] ++ = sum_(v=-ETA to ETA)v^2 * (BINOMIAL_COEFFICIENT(2 * ETA; ETA - v) / ++ 2^(2 * ETA)) = ETA / 2 ++ ``` ++ ++ This function implements Algorithm 7 of the NIST FIPS 203 ++ standard, which is reproduced below: ++ ++ ```plaintext ++ Input: byte array B ∈ 𝔹^{64η}. ++ Output: array f ∈ ℤ₂₅₆. ++ ++ b ← BytesToBits(B) ++ for (i ← 0; i < 256; i++) ++ x ← ∑(j=0 to η - 1) b[2iη + j] ++ y ← ∑(j=0 to η - 1) b[2iη + η + j] ++ f[i] ← x−y mod q ++ end for ++ return f ++ ``` ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.sampling.sample_from_binomial_distribution_2 with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++ ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++sample_from_binomial_distribution_2_7b(Eurydice_slice randomness) ++{ ++ int16_t sampled_i16s[256U] = { 0U }; ++ for (size_t i0 = (size_t)0U; ++ i0 < Eurydice_slice_len(randomness, uint8_t) / (size_t)4U; i0++) { ++ size_t chunk_number = i0; ++ Eurydice_slice byte_chunk = Eurydice_slice_subslice2( ++ randomness, chunk_number * (size_t)4U, ++ chunk_number * (size_t)4U + (size_t)4U, uint8_t); ++ uint32_t random_bits_as_u32 = ++ (((uint32_t)Eurydice_slice_index(byte_chunk, (size_t)0U, uint8_t, ++ uint8_t *) | ++ (uint32_t)Eurydice_slice_index(byte_chunk, (size_t)1U, uint8_t, ++ uint8_t *) ++ << 8U) | ++ (uint32_t)Eurydice_slice_index(byte_chunk, (size_t)2U, uint8_t, ++ uint8_t *) ++ << 16U) | ++ (uint32_t)Eurydice_slice_index(byte_chunk, (size_t)3U, uint8_t, ++ uint8_t *) ++ << 24U; ++ uint32_t even_bits = random_bits_as_u32 & 1431655765U; ++ uint32_t odd_bits = random_bits_as_u32 >> 1U & 1431655765U; ++ uint32_t coin_toss_outcomes = even_bits + odd_bits; ++ for (uint32_t i = 0U; i < CORE_NUM__U32_8__BITS / 4U; i++) { ++ uint32_t outcome_set = i; ++ uint32_t outcome_set0 = outcome_set * 4U; ++ int16_t outcome_1 = ++ (int16_t)(coin_toss_outcomes >> (uint32_t)outcome_set0 & 3U); ++ int16_t outcome_2 = ++ (int16_t)(coin_toss_outcomes >> (uint32_t)(outcome_set0 + 2U) & 3U); ++ size_t offset = (size_t)(outcome_set0 >> 2U); ++ sampled_i16s[(size_t)8U * chunk_number + offset] = outcome_1 - outcome_2; ++ } ++ } ++ return from_i16_array_89_33( ++ Eurydice_array_to_slice((size_t)256U, sampled_i16s, int16_t)); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.sampling.sample_from_binomial_distribution_3 with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++ ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++sample_from_binomial_distribution_3_14(Eurydice_slice randomness) ++{ ++ int16_t sampled_i16s[256U] = { 0U }; ++ for (size_t i0 = (size_t)0U; ++ i0 < Eurydice_slice_len(randomness, uint8_t) / (size_t)3U; i0++) { ++ size_t chunk_number = i0; ++ Eurydice_slice byte_chunk = Eurydice_slice_subslice2( ++ randomness, chunk_number * (size_t)3U, ++ chunk_number * (size_t)3U + (size_t)3U, uint8_t); ++ uint32_t random_bits_as_u24 = ++ ((uint32_t)Eurydice_slice_index(byte_chunk, (size_t)0U, uint8_t, ++ uint8_t *) | ++ (uint32_t)Eurydice_slice_index(byte_chunk, (size_t)1U, uint8_t, ++ uint8_t *) ++ << 8U) | ++ (uint32_t)Eurydice_slice_index(byte_chunk, (size_t)2U, uint8_t, ++ uint8_t *) ++ << 16U; ++ uint32_t first_bits = random_bits_as_u24 & 2396745U; ++ uint32_t second_bits = random_bits_as_u24 >> 1U & 2396745U; ++ uint32_t third_bits = random_bits_as_u24 >> 2U & 2396745U; ++ uint32_t coin_toss_outcomes = first_bits + second_bits + third_bits; ++ for (int32_t i = (int32_t)0; i < (int32_t)24 / (int32_t)6; i++) { ++ int32_t outcome_set = i; ++ int32_t outcome_set0 = outcome_set * (int32_t)6; ++ int16_t outcome_1 = ++ (int16_t)(coin_toss_outcomes >> (uint32_t)outcome_set0 & 7U); ++ int16_t outcome_2 = (int16_t)(coin_toss_outcomes >> ++ (uint32_t)(outcome_set0 + (int32_t)3) & ++ 7U); ++ size_t offset = (size_t)(outcome_set0 / (int32_t)6); ++ sampled_i16s[(size_t)4U * chunk_number + offset] = outcome_1 - outcome_2; ++ } ++ } ++ return from_i16_array_89_33( ++ Eurydice_array_to_slice((size_t)256U, sampled_i16s, int16_t)); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.sampling.sample_from_binomial_distribution with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- ETA= 2 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++sample_from_binomial_distribution_ca(Eurydice_slice randomness) ++{ ++ return sample_from_binomial_distribution_2_7b(randomness); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ntt.ntt_at_layer_7 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++ntt_at_layer_7_60( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) ++{ ++ size_t step = LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT / (size_t)2U; ++ for (size_t i = (size_t)0U; i < step; i++) { ++ size_t j = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector t = ++ libcrux_ml_kem_vector_portable_multiply_by_constant_0d( ++ re->coefficients[j + step], (int16_t)-1600); ++ re->coefficients[j + step] = ++ libcrux_ml_kem_vector_portable_sub_0d(re->coefficients[j], &t); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1 = ++ libcrux_ml_kem_vector_portable_add_0d(re->coefficients[j], &t); ++ re->coefficients[j] = uu____1; ++ } ++} ++ ++typedef struct libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2_s { ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector fst; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector snd; ++} libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2; ++ ++/** ++A monomorphic instance of libcrux_ml_kem.vector.traits.montgomery_multiply_fe ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static libcrux_ml_kem_vector_portable_vector_type_PortableVector ++montgomery_multiply_fe_05( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t fer) ++{ ++ return libcrux_ml_kem_vector_portable_montgomery_multiply_by_constant_0d(v, ++ fer); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ntt.ntt_layer_int_vec_step ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2 ++ ntt_layer_int_vec_step_88( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector b, ++ int16_t zeta_r) ++{ ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector t = ++ montgomery_multiply_fe_05(b, zeta_r); ++ b = libcrux_ml_kem_vector_portable_sub_0d(a, &t); ++ a = libcrux_ml_kem_vector_portable_add_0d(a, &t); ++ return ( ++ CLITERAL(libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2){ ++ .fst = a, .snd = b }); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ntt.ntt_at_layer_4_plus ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++ntt_at_layer_4_plus_8c( ++ size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, ++ size_t layer) ++{ ++ size_t step = (size_t)1U << (uint32_t)layer; ++ for (size_t i0 = (size_t)0U; i0 < (size_t)128U >> (uint32_t)layer; i0++) { ++ size_t round = i0; ++ zeta_i[0U] = zeta_i[0U] + (size_t)1U; ++ size_t offset = round * step * (size_t)2U; ++ size_t offset_vec = offset / (size_t)16U; ++ size_t step_vec = step / (size_t)16U; ++ for (size_t i = offset_vec; i < offset_vec + step_vec; i++) { ++ size_t j = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2 uu____0 = ++ ntt_layer_int_vec_step_88( ++ re->coefficients[j], re->coefficients[j + step_vec], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector x = uu____0.fst; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector y = uu____0.snd; ++ re->coefficients[j] = x; ++ re->coefficients[j + step_vec] = y; ++ } ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ntt.ntt_at_layer_3 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++ntt_at_layer_3_34( ++ size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) ++{ ++ KRML_MAYBE_FOR16( ++ i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; ++ zeta_i[0U] = zeta_i[0U] + (size_t)1U; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_ntt_layer_3_step_0d( ++ re->coefficients[round], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); ++ re->coefficients[round] = uu____0;); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ntt.ntt_at_layer_2 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++ntt_at_layer_2_26( ++ size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) ++{ ++ KRML_MAYBE_FOR16( ++ i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; ++ zeta_i[0U] = zeta_i[0U] + (size_t)1U; ++ re->coefficients[round] = ++ libcrux_ml_kem_vector_portable_ntt_layer_2_step_0d( ++ re->coefficients[round], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + ++ (size_t)1U]); ++ zeta_i[0U] = zeta_i[0U] + (size_t)1U;); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ntt.ntt_at_layer_1 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++ntt_at_layer_1_3c( ++ size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) ++{ ++ KRML_MAYBE_FOR16( ++ i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; ++ zeta_i[0U] = zeta_i[0U] + (size_t)1U; ++ re->coefficients[round] = ++ libcrux_ml_kem_vector_portable_ntt_layer_1_step_0d( ++ re->coefficients[round], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + ++ (size_t)1U], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + ++ (size_t)2U], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + ++ (size_t)3U]); ++ zeta_i[0U] = zeta_i[0U] + (size_t)3U;); ++} ++ ++/** ++This function found in impl ++{libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.polynomial.poly_barrett_reduce_89 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++poly_barrett_reduce_89_d8( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_barrett_reduce_0d( ++ self->coefficients[i0]); ++ self->coefficients[i0] = uu____0; ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ntt.ntt_binomially_sampled_ring_element ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++ntt_binomially_sampled_ring_element_63( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) ++{ ++ ntt_at_layer_7_60(re); ++ size_t zeta_i = (size_t)1U; ++ ntt_at_layer_4_plus_8c(&zeta_i, re, (size_t)6U); ++ ntt_at_layer_4_plus_8c(&zeta_i, re, (size_t)5U); ++ ntt_at_layer_4_plus_8c(&zeta_i, re, (size_t)4U); ++ ntt_at_layer_3_34(&zeta_i, re); ++ ntt_at_layer_2_26(&zeta_i, re); ++ ntt_at_layer_1_3c(&zeta_i, re); ++ poly_barrett_reduce_89_d8(re); ++} ++ ++/** ++ Sample a vector of ring elements from a centered binomial distribution and ++ convert them into their NTT representations. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.sample_vector_cbd_then_ntt ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]] with const ++generics ++- K= 4 ++- ETA= 2 ++- ETA_RANDOMNESS_SIZE= 128 ++*/ ++static KRML_MUSTINLINE tuple_710 ++sample_vector_cbd_then_ntt_781( ++ uint8_t prf_input[33U], uint8_t domain_separator) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re_as_ntt[4U]; ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, ++ re_as_ntt[i] = ZERO_89_c3();); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input[33U]; ++ memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); ++ uint8_t prf_inputs[4U][33U]; ++ KRML_MAYBE_FOR4( ++ i, (size_t)0U, (size_t)4U, (size_t)1U, ++ memcpy(prf_inputs[i], copy_of_prf_input, (size_t)33U * sizeof(uint8_t));); ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; ++ prf_inputs[i0][32U] = domain_separator; ++ domain_separator = (uint32_t)domain_separator + 1U;); ++ uint8_t prf_outputs[4U][128U]; ++ PRFxN_f1_d52(prf_inputs, prf_outputs); ++ KRML_MAYBE_FOR4( ++ i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; ++ re_as_ntt[i0] = sample_from_binomial_distribution_ca( ++ Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t)); ++ ntt_binomially_sampled_ring_element_63(&re_as_ntt[i0]);); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 copy_of_re_as_ntt[4U]; ++ memcpy( ++ copy_of_re_as_ntt, re_as_ntt, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ tuple_710 lit; ++ memcpy( ++ lit.fst, copy_of_re_as_ntt, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ lit.snd = domain_separator; ++ return lit; ++} ++ ++/** ++ Given two `KyberPolynomialRingElement`s in their NTT representations, ++ compute their product. Given two polynomials in the NTT domain `f^` and `ĵ`, ++ the `iᵗʰ` coefficient of the product `k̂` is determined by the calculation: ++ ++ ```plaintext ++ ĥ[2·i] + ĥ[2·i + 1]X = (f^[2·i] + f^[2·i + 1]X)·(ĝ[2·i] + ĝ[2·i + 1]X) mod (X² ++ - ζ^(2·BitRev₇(i) + 1)) ++ ``` ++ ++ This function almost implements Algorithm 10 of the ++ NIST FIPS 203 standard, which is reproduced below: ++ ++ ```plaintext ++ Input: Two arrays fˆ ∈ ℤ₂₅₆ and ĝ ∈ ℤ₂₅₆. ++ Output: An array ĥ ∈ ℤq. ++ ++ for(i ← 0; i < 128; i++) ++ (ĥ[2i], ĥ[2i+1]) ← BaseCaseMultiply(fˆ[2i], fˆ[2i+1], ĝ[2i], ĝ[2i+1], ++ ζ^(2·BitRev₇(i) + 1)) end for return ĥ ++ ``` ++ We say "almost" because the coefficients of the ring element output by ++ this function are in the Montgomery domain. ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++/** ++This function found in impl ++{libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.polynomial.ntt_multiply_89 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++ntt_multiply_89_3b(libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *rhs) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 out = ZERO_89_c3(); ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_ntt_multiply_0d( ++ &self->coefficients[i0], &rhs->coefficients[i0], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[(size_t)64U + ++ (size_t)4U * i0], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[(size_t)64U + ++ (size_t)4U * i0 + ++ (size_t)1U], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[(size_t)64U + ++ (size_t)4U * i0 + ++ (size_t)2U], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[(size_t)64U + ++ (size_t)4U * i0 + ++ (size_t)3U]); ++ out.coefficients[i0] = uu____0; ++ } ++ return out; ++} ++ ++/** ++ Given two polynomial ring elements `lhs` and `rhs`, compute the pointwise ++ sum of their constituent coefficients. ++*/ ++/** ++This function found in impl ++{libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.polynomial.add_to_ring_element_89 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++add_to_ring_element_89_1e1( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *rhs) ++{ ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)16U, self->coefficients, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector), ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector); ++ i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_add_0d(self->coefficients[i0], ++ &rhs->coefficients[i0]); ++ self->coefficients[i0] = uu____0; ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.vector.traits.to_standard_domain ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static libcrux_ml_kem_vector_portable_vector_type_PortableVector ++to_standard_domain_21( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ return libcrux_ml_kem_vector_portable_montgomery_multiply_by_constant_0d( ++ v, LIBCRUX_ML_KEM_VECTOR_TRAITS_MONTGOMERY_R_SQUARED_MOD_FIELD_MODULUS); ++} ++ ++/** ++This function found in impl ++{libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.polynomial.add_standard_error_reduce_89 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++add_standard_error_reduce_89_64( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { ++ size_t j = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector ++ coefficient_normal_form = to_standard_domain_21(self->coefficients[j]); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_barrett_reduce_0d( ++ libcrux_ml_kem_vector_portable_add_0d(coefficient_normal_form, ++ &error->coefficients[j])); ++ self->coefficients[j] = uu____0; ++ } ++} ++ ++/** ++ Compute  ◦ ŝ + ê ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.compute_As_plus_e ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++compute_As_plus_e_c71( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 (*matrix_A)[4U], ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *s_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[4U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result[4U]; ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, ++ result[i] = ZERO_89_c3();); ++ for (size_t i0 = (size_t)0U; ++ i0 < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)4U, matrix_A, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0[4U]), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0[4U]); ++ i0++) { ++ size_t i1 = i0; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *row = matrix_A[i1]; ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)4U, row, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t j = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *matrix_element = ++ &row[j]; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = ++ ntt_multiply_89_3b(matrix_element, &s_as_ntt[j]); ++ add_to_ring_element_89_1e1(&result[i1], &product); ++ } ++ add_standard_error_reduce_89_64(&result[i1], &error_as_ntt[i1]); ++ } ++ memcpy( ++ ret, result, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.generate_keypair ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 4 ++- PRIVATE_KEY_SIZE= 1536 ++- PUBLIC_KEY_SIZE= 1568 ++- RANKED_BYTES_PER_RING_ELEMENT= 1536 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++*/ ++static libcrux_ml_kem_utils_extraction_helper_Keypair1024 ++generate_keypair_a21( ++ Eurydice_slice key_generation_seed) ++{ ++ uint8_t hashed[64U]; ++ cpa_keygen_seed_d8_72(key_generation_seed, hashed); ++ Eurydice_slice_uint8_t_x2 uu____0 = Eurydice_slice_split_at( ++ Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), (size_t)32U, ++ uint8_t, Eurydice_slice_uint8_t_x2); ++ Eurydice_slice seed_for_A0 = uu____0.fst; ++ Eurydice_slice seed_for_secret_and_error = uu____0.snd; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 A_transpose[4U][4U]; ++ uint8_t ret[34U]; ++ libcrux_ml_kem_utils_into_padded_array_6d1(seed_for_A0, ret); ++ sample_matrix_A_e71(ret, true, A_transpose); ++ uint8_t prf_input[33U]; ++ libcrux_ml_kem_utils_into_padded_array_6d2(seed_for_secret_and_error, ++ prf_input); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input0[33U]; ++ memcpy(copy_of_prf_input0, prf_input, (size_t)33U * sizeof(uint8_t)); ++ tuple_710 uu____2 = sample_vector_cbd_then_ntt_781(copy_of_prf_input0, 0U); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[4U]; ++ memcpy( ++ secret_as_ntt, uu____2.fst, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ uint8_t domain_separator = uu____2.snd; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input[33U]; ++ memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_as_ntt[4U]; ++ memcpy( ++ error_as_ntt, ++ sample_vector_cbd_then_ntt_781(copy_of_prf_input, domain_separator).fst, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 t_as_ntt[4U]; ++ compute_As_plus_e_c71(A_transpose, secret_as_ntt, error_as_ntt, t_as_ntt); ++ uint8_t seed_for_A[32U]; ++ core_result_Result_00 dst; ++ Eurydice_slice_to_array2(&dst, seed_for_A0, Eurydice_slice, uint8_t[32U]); ++ core_result_unwrap_41_33(dst, seed_for_A); ++ uint8_t public_key_serialized[1568U]; ++ serialize_public_key_671( ++ t_as_ntt, Eurydice_array_to_slice((size_t)32U, seed_for_A, uint8_t), ++ public_key_serialized); ++ uint8_t secret_key_serialized[1536U]; ++ serialize_secret_key_a31(secret_as_ntt, secret_key_serialized); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_secret_key_serialized[1536U]; ++ memcpy(copy_of_secret_key_serialized, secret_key_serialized, ++ (size_t)1536U * sizeof(uint8_t)); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_public_key_serialized[1568U]; ++ memcpy(copy_of_public_key_serialized, public_key_serialized, ++ (size_t)1568U * sizeof(uint8_t)); ++ libcrux_ml_kem_utils_extraction_helper_Keypair1024 lit; ++ memcpy(lit.fst, copy_of_secret_key_serialized, ++ (size_t)1536U * sizeof(uint8_t)); ++ memcpy(lit.snd, copy_of_public_key_serialized, ++ (size_t)1568U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++ Serialize the secret key. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.serialize_kem_secret_key ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]] ++with const generics ++- K= 4 ++- SERIALIZED_KEY_LEN= 3168 ++*/ ++static KRML_MUSTINLINE void ++serialize_kem_secret_key_7d( ++ Eurydice_slice private_key, Eurydice_slice public_key, ++ Eurydice_slice implicit_rejection_value, uint8_t ret[3168U]) ++{ ++ uint8_t out[3168U] = { 0U }; ++ size_t pointer = (size_t)0U; ++ uint8_t *uu____0 = out; ++ size_t uu____1 = pointer; ++ size_t uu____2 = pointer; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2( ++ uu____0, uu____1, uu____2 + Eurydice_slice_len(private_key, uint8_t), ++ uint8_t), ++ private_key, uint8_t); ++ pointer = pointer + Eurydice_slice_len(private_key, uint8_t); ++ uint8_t *uu____3 = out; ++ size_t uu____4 = pointer; ++ size_t uu____5 = pointer; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2( ++ uu____3, uu____4, uu____5 + Eurydice_slice_len(public_key, uint8_t), ++ uint8_t), ++ public_key, uint8_t); ++ pointer = pointer + Eurydice_slice_len(public_key, uint8_t); ++ Eurydice_slice uu____6 = Eurydice_array_to_subslice2( ++ out, pointer, pointer + LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t); ++ uint8_t ret0[32U]; ++ H_f1_191(public_key, ret0); ++ Eurydice_slice_copy( ++ uu____6, Eurydice_array_to_slice((size_t)32U, ret0, uint8_t), uint8_t); ++ pointer = pointer + LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE; ++ uint8_t *uu____7 = out; ++ size_t uu____8 = pointer; ++ size_t uu____9 = pointer; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2( ++ uu____7, uu____8, ++ uu____9 + Eurydice_slice_len(implicit_rejection_value, uint8_t), ++ uint8_t), ++ implicit_rejection_value, uint8_t); ++ memcpy(ret, out, (size_t)3168U * sizeof(uint8_t)); ++} ++ ++/** ++ Packed API ++ ++ Generate a key pair. ++ ++ Depending on the `Vector` and `Hasher` used, this requires different hardware ++ features ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.generate_keypair ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 4 ++- CPA_PRIVATE_KEY_SIZE= 1536 ++- PRIVATE_KEY_SIZE= 3168 ++- PUBLIC_KEY_SIZE= 1568 ++- BYTES_PER_RING_ELEMENT= 1536 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++*/ ++libcrux_ml_kem_mlkem1024_MlKem1024KeyPair ++libcrux_ml_kem_ind_cca_generate_keypair_f61(uint8_t randomness[64U]) ++{ ++ Eurydice_slice ind_cpa_keypair_randomness = Eurydice_array_to_subslice2( ++ randomness, (size_t)0U, ++ LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t); ++ Eurydice_slice implicit_rejection_value = Eurydice_array_to_subslice_from( ++ (size_t)64U, randomness, ++ LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t, ++ size_t); ++ libcrux_ml_kem_utils_extraction_helper_Keypair1024 uu____0 = ++ generate_keypair_a21(ind_cpa_keypair_randomness); ++ uint8_t ind_cpa_private_key[1536U]; ++ memcpy(ind_cpa_private_key, uu____0.fst, (size_t)1536U * sizeof(uint8_t)); ++ uint8_t public_key[1568U]; ++ memcpy(public_key, uu____0.snd, (size_t)1568U * sizeof(uint8_t)); ++ uint8_t secret_key_serialized[3168U]; ++ serialize_kem_secret_key_7d( ++ Eurydice_array_to_slice((size_t)1536U, ind_cpa_private_key, uint8_t), ++ Eurydice_array_to_slice((size_t)1568U, public_key, uint8_t), ++ implicit_rejection_value, secret_key_serialized); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_secret_key_serialized[3168U]; ++ memcpy(copy_of_secret_key_serialized, secret_key_serialized, ++ (size_t)3168U * sizeof(uint8_t)); ++ libcrux_ml_kem_types_MlKemPrivateKey_95 private_key = ++ libcrux_ml_kem_types_from_05_891(copy_of_secret_key_serialized); ++ libcrux_ml_kem_types_MlKemPrivateKey_95 uu____2 = private_key; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_public_key[1568U]; ++ memcpy(copy_of_public_key, public_key, (size_t)1568U * sizeof(uint8_t)); ++ return libcrux_ml_kem_types_from_17_821( ++ uu____2, libcrux_ml_kem_types_from_b6_961(copy_of_public_key)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::variant::Variant for ++libcrux_ml_kem::variant::MlKem)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.variant.entropy_preprocess_d8 ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]] ++with const generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++entropy_preprocess_d8_d1(Eurydice_slice randomness, ++ uint8_t ret[32U]) ++{ ++ uint8_t out[32U] = { 0U }; ++ Eurydice_slice_copy(Eurydice_array_to_slice((size_t)32U, out, uint8_t), ++ randomness, uint8_t); ++ memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++ This function deserializes ring elements and reduces the result by the field ++ modulus. ++ ++ This function MUST NOT be used on secret inputs. ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_ring_elements_reduced with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- PUBLIC_KEY_SIZE= 1536 ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++deserialize_ring_elements_reduced_4f3( ++ Eurydice_slice public_key, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[4U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 deserialized_pk[4U]; ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, ++ deserialized_pk[i] = ZERO_89_c3();); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(public_key, uint8_t) / ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; ++ i++) { ++ size_t i0 = i; ++ Eurydice_slice ring_element = Eurydice_slice_subslice2( ++ public_key, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ uint8_t); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____0 = ++ deserialize_to_reduced_ring_element_45(ring_element); ++ deserialized_pk[i0] = uu____0; ++ } ++ memcpy( ++ ret, deserialized_pk, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++ Sample a vector of ring elements from a centered binomial distribution. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.sample_ring_element_cbd ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]] with const ++generics ++- K= 4 ++- ETA2_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++*/ ++static KRML_MUSTINLINE tuple_710 ++sample_ring_element_cbd_a81(uint8_t prf_input[33U], uint8_t domain_separator) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_1[4U]; ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, ++ error_1[i] = ZERO_89_c3();); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input[33U]; ++ memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); ++ uint8_t prf_inputs[4U][33U]; ++ KRML_MAYBE_FOR4( ++ i, (size_t)0U, (size_t)4U, (size_t)1U, ++ memcpy(prf_inputs[i], copy_of_prf_input, (size_t)33U * sizeof(uint8_t));); ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; ++ prf_inputs[i0][32U] = domain_separator; ++ domain_separator = (uint32_t)domain_separator + 1U;); ++ uint8_t prf_outputs[4U][128U]; ++ PRFxN_f1_d52(prf_inputs, prf_outputs); ++ KRML_MAYBE_FOR4( ++ i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____1 = ++ sample_from_binomial_distribution_ca( ++ Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t)); ++ error_1[i0] = uu____1;); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 copy_of_error_1[4U]; ++ memcpy( ++ copy_of_error_1, error_1, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ tuple_710 lit; ++ memcpy( ++ lit.fst, copy_of_error_1, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ lit.snd = domain_separator; ++ return lit; ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRF ++with const generics ++- LEN= 128 ++*/ ++static KRML_MUSTINLINE void ++PRF_7c0(Eurydice_slice input, uint8_t ret[128U]) ++{ ++ uint8_t digest[128U] = { 0U }; ++ libcrux_sha3_portable_shake256( ++ Eurydice_array_to_slice((size_t)128U, digest, uint8_t), input); ++ memcpy(ret, digest, (size_t)128U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRF_f1 ++with const generics ++- K= 4 ++- LEN= 128 ++*/ ++static KRML_MUSTINLINE void ++PRF_f1_2e4(Eurydice_slice input, ++ uint8_t ret[128U]) ++{ ++ PRF_7c0(input, ret); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.invert_ntt.invert_ntt_at_layer_1 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++invert_ntt_at_layer_1_4b( ++ size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) ++{ ++ KRML_MAYBE_FOR16( ++ i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; ++ zeta_i[0U] = zeta_i[0U] - (size_t)1U; ++ re->coefficients[round] = ++ libcrux_ml_kem_vector_portable_inv_ntt_layer_1_step_0d( ++ re->coefficients[round], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - ++ (size_t)1U], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - ++ (size_t)2U], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - ++ (size_t)3U]); ++ zeta_i[0U] = zeta_i[0U] - (size_t)3U;); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.invert_ntt.invert_ntt_at_layer_2 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++invert_ntt_at_layer_2_2b( ++ size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) ++{ ++ KRML_MAYBE_FOR16( ++ i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; ++ zeta_i[0U] = zeta_i[0U] - (size_t)1U; ++ re->coefficients[round] = ++ libcrux_ml_kem_vector_portable_inv_ntt_layer_2_step_0d( ++ re->coefficients[round], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - ++ (size_t)1U]); ++ zeta_i[0U] = zeta_i[0U] - (size_t)1U;); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.invert_ntt.invert_ntt_at_layer_3 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++invert_ntt_at_layer_3_97( ++ size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) ++{ ++ KRML_MAYBE_FOR16( ++ i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; ++ zeta_i[0U] = zeta_i[0U] - (size_t)1U; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_inv_ntt_layer_3_step_0d( ++ re->coefficients[round], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); ++ re->coefficients[round] = uu____0;); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.invert_ntt.inv_ntt_layer_int_vec_step_reduce with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++ ++*/ ++static KRML_MUSTINLINE ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2 ++ inv_ntt_layer_int_vec_step_reduce_aa( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector b, ++ int16_t zeta_r) ++{ ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a_minus_b = ++ libcrux_ml_kem_vector_portable_sub_0d(b, &a); ++ a = libcrux_ml_kem_vector_portable_barrett_reduce_0d( ++ libcrux_ml_kem_vector_portable_add_0d(a, &b)); ++ b = montgomery_multiply_fe_05(a_minus_b, zeta_r); ++ return ( ++ CLITERAL(libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2){ ++ .fst = a, .snd = b }); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.invert_ntt.invert_ntt_at_layer_4_plus ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++invert_ntt_at_layer_4_plus_04( ++ size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, ++ size_t layer) ++{ ++ size_t step = (size_t)1U << (uint32_t)layer; ++ for (size_t i0 = (size_t)0U; i0 < (size_t)128U >> (uint32_t)layer; i0++) { ++ size_t round = i0; ++ zeta_i[0U] = zeta_i[0U] - (size_t)1U; ++ size_t offset = round * step * (size_t)2U; ++ size_t offset_vec = ++ offset / LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; ++ size_t step_vec = ++ step / LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; ++ for (size_t i = offset_vec; i < offset_vec + step_vec; i++) { ++ size_t j = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2 uu____0 = ++ inv_ntt_layer_int_vec_step_reduce_aa( ++ re->coefficients[j], re->coefficients[j + step_vec], ++ libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector x = uu____0.fst; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector y = uu____0.snd; ++ re->coefficients[j] = x; ++ re->coefficients[j + step_vec] = y; ++ } ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.invert_ntt.invert_ntt_montgomery ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++invert_ntt_montgomery_c91( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) ++{ ++ size_t zeta_i = ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT / (size_t)2U; ++ invert_ntt_at_layer_1_4b(&zeta_i, re); ++ invert_ntt_at_layer_2_2b(&zeta_i, re); ++ invert_ntt_at_layer_3_97(&zeta_i, re); ++ invert_ntt_at_layer_4_plus_04(&zeta_i, re, (size_t)4U); ++ invert_ntt_at_layer_4_plus_04(&zeta_i, re, (size_t)5U); ++ invert_ntt_at_layer_4_plus_04(&zeta_i, re, (size_t)6U); ++ invert_ntt_at_layer_4_plus_04(&zeta_i, re, (size_t)7U); ++ poly_barrett_reduce_89_d8(re); ++} ++ ++/** ++This function found in impl ++{libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.polynomial.add_error_reduce_89 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++add_error_reduce_89_5d( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { ++ size_t j = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector ++ coefficient_normal_form = ++ libcrux_ml_kem_vector_portable_montgomery_multiply_by_constant_0d( ++ self->coefficients[j], (int16_t)1441); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_barrett_reduce_0d( ++ libcrux_ml_kem_vector_portable_add_0d(coefficient_normal_form, ++ &error->coefficients[j])); ++ self->coefficients[j] = uu____0; ++ } ++} ++ ++/** ++ Compute u := InvertNTT(Aᵀ ◦ r̂) + e₁ ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.compute_vector_u ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++compute_vector_u_931( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 (*a_as_ntt)[4U], ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *r_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error_1, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[4U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result[4U]; ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, ++ result[i] = ZERO_89_c3();); ++ for (size_t i0 = (size_t)0U; ++ i0 < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)4U, a_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0[4U]), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0[4U]); ++ i0++) { ++ size_t i1 = i0; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *row = a_as_ntt[i1]; ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)4U, row, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t j = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *a_element = &row[j]; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = ++ ntt_multiply_89_3b(a_element, &r_as_ntt[j]); ++ add_to_ring_element_89_1e1(&result[i1], &product); ++ } ++ invert_ntt_montgomery_c91(&result[i1]); ++ add_error_reduce_89_5d(&result[i1], &error_1[i1]); ++ } ++ memcpy( ++ ret, result, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.vector.traits.decompress_1 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static libcrux_ml_kem_vector_portable_vector_type_PortableVector ++decompress_1_3e(libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_ZERO_0d(); ++ return libcrux_ml_kem_vector_portable_bitwise_and_with_constant_0d( ++ libcrux_ml_kem_vector_portable_sub_0d(uu____0, &v), (int16_t)1665); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_then_decompress_message with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++ ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++deserialize_then_decompress_message_f7(uint8_t serialized[32U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = ZERO_89_c3(); ++ KRML_MAYBE_FOR16( ++ i, (size_t)0U, (size_t)16U, (size_t)1U, size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector ++ coefficient_compressed = ++ libcrux_ml_kem_vector_portable_deserialize_1_0d( ++ Eurydice_array_to_subslice2(serialized, (size_t)2U * i0, ++ (size_t)2U * i0 + (size_t)2U, ++ uint8_t)); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ decompress_1_3e(coefficient_compressed); ++ re.coefficients[i0] = uu____0;); ++ return re; ++} ++ ++/** ++This function found in impl ++{libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.polynomial.add_message_error_reduce_89 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++add_message_error_reduce_89_c4( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *message, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector ++ coefficient_normal_form = ++ libcrux_ml_kem_vector_portable_montgomery_multiply_by_constant_0d( ++ result.coefficients[i0], (int16_t)1441); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector tmp = ++ libcrux_ml_kem_vector_portable_add_0d(self->coefficients[i0], ++ &message->coefficients[i0]); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector tmp0 = ++ libcrux_ml_kem_vector_portable_add_0d(coefficient_normal_form, &tmp); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_barrett_reduce_0d(tmp0); ++ result.coefficients[i0] = uu____0; ++ } ++ return result; ++} ++ ++/** ++ Compute InverseNTT(tᵀ ◦ r̂) + e₂ + message ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.compute_ring_element_v ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++compute_ring_element_v_541( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *t_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *r_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error_2, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *message) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result = ZERO_89_c3(); ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = ++ ntt_multiply_89_3b(&t_as_ntt[i0], &r_as_ntt[i0]); ++ add_to_ring_element_89_1e1(&result, &product);); ++ invert_ntt_montgomery_c91(&result); ++ result = add_message_error_reduce_89_c4(error_2, message, result); ++ return result; ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.vector.portable.compress.compress ++with const generics ++- COEFFICIENT_BITS= 10 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++compress_dc(libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ int16_t uu____0 = ++ libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( ++ (uint8_t)(int32_t)10, (uint16_t)v.elements[i0]); ++ v.elements[i0] = uu____0; ++ } ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.vector.portable.compress_0d ++with const generics ++- COEFFICIENT_BITS= 10 ++*/ ++static libcrux_ml_kem_vector_portable_vector_type_PortableVector ++compress_0d_96( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ return compress_dc(v); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.vector.portable.compress.compress ++with const generics ++- COEFFICIENT_BITS= 11 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++compress_dc0(libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ int16_t uu____0 = ++ libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( ++ (uint8_t)(int32_t)11, (uint16_t)v.elements[i0]); ++ v.elements[i0] = uu____0; ++ } ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.vector.portable.compress_0d ++with const generics ++- COEFFICIENT_BITS= 11 ++*/ ++static libcrux_ml_kem_vector_portable_vector_type_PortableVector ++compress_0d_960(libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ return compress_dc0(v); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.serialize.compress_then_serialize_11 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- OUT_LEN= 352 ++*/ ++static KRML_MUSTINLINE void ++compress_then_serialize_11_ef0( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, uint8_t ret[352U]) ++{ ++ uint8_t serialized[352U] = { 0U }; ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = ++ compress_0d_960(to_unsigned_representative_84(re->coefficients[i0])); ++ uint8_t bytes[22U]; ++ libcrux_ml_kem_vector_portable_serialize_11_0d(coefficient, bytes); ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ serialized, (size_t)22U * i0, (size_t)22U * i0 + (size_t)22U, uint8_t); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)22U, bytes, uint8_t), uint8_t); ++ } ++ memcpy(ret, serialized, (size_t)352U * sizeof(uint8_t)); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.compress_then_serialize_ring_element_u with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- COMPRESSION_FACTOR= 11 ++- OUT_LEN= 352 ++*/ ++static KRML_MUSTINLINE void ++compress_then_serialize_ring_element_u_2e0( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, uint8_t ret[352U]) ++{ ++ uint8_t uu____0[352U]; ++ compress_then_serialize_11_ef0(re, uu____0); ++ memcpy(ret, uu____0, (size_t)352U * sizeof(uint8_t)); ++} ++ ++/** ++ Call [`compress_then_serialize_ring_element_u`] on each ring element. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.compress_then_serialize_u ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++- OUT_LEN= 1408 ++- COMPRESSION_FACTOR= 11 ++- BLOCK_LEN= 352 ++*/ ++static void ++compress_then_serialize_u_281( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 input[4U], ++ Eurydice_slice out) ++{ ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)4U, input, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = input[i0]; ++ Eurydice_slice uu____0 = Eurydice_slice_subslice2( ++ out, i0 * ((size_t)1408U / (size_t)4U), ++ (i0 + (size_t)1U) * ((size_t)1408U / (size_t)4U), uint8_t); ++ uint8_t ret[352U]; ++ compress_then_serialize_ring_element_u_2e0(&re, ret); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)352U, ret, uint8_t), uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.vector.portable.compress.compress ++with const generics ++- COEFFICIENT_BITS= 4 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++compress_dc1(libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ int16_t uu____0 = ++ libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( ++ (uint8_t)(int32_t)4, (uint16_t)v.elements[i0]); ++ v.elements[i0] = uu____0; ++ } ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.vector.portable.compress_0d ++with const generics ++- COEFFICIENT_BITS= 4 ++*/ ++static libcrux_ml_kem_vector_portable_vector_type_PortableVector ++compress_0d_961(libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ return compress_dc1(v); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.serialize.compress_then_serialize_4 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++compress_then_serialize_4_80( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re, ++ Eurydice_slice serialized) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = ++ compress_0d_961(to_unsigned_representative_84(re.coefficients[i0])); ++ uint8_t bytes[8U]; ++ libcrux_ml_kem_vector_portable_serialize_4_0d(coefficient, bytes); ++ Eurydice_slice_copy( ++ Eurydice_slice_subslice2(serialized, (size_t)8U * i0, ++ (size_t)8U * i0 + (size_t)8U, uint8_t), ++ Eurydice_array_to_slice((size_t)8U, bytes, uint8_t), uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.vector.portable.compress.compress ++with const generics ++- COEFFICIENT_BITS= 5 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++compress_dc2(libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ int16_t uu____0 = ++ libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( ++ (uint8_t)(int32_t)5, (uint16_t)v.elements[i0]); ++ v.elements[i0] = uu____0; ++ } ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.vector.portable.compress_0d ++with const generics ++- COEFFICIENT_BITS= 5 ++*/ ++static libcrux_ml_kem_vector_portable_vector_type_PortableVector ++compress_0d_962(libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ return compress_dc2(v); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.serialize.compress_then_serialize_5 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++compress_then_serialize_5_3c( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re, ++ Eurydice_slice serialized) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficients = ++ compress_0d_962(to_unsigned_representative_84(re.coefficients[i0])); ++ uint8_t bytes[10U]; ++ libcrux_ml_kem_vector_portable_serialize_5_0d(coefficients, bytes); ++ Eurydice_slice_copy( ++ Eurydice_slice_subslice2(serialized, (size_t)10U * i0, ++ (size_t)10U * i0 + (size_t)10U, uint8_t), ++ Eurydice_array_to_slice((size_t)10U, bytes, uint8_t), uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.compress_then_serialize_ring_element_v with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- COMPRESSION_FACTOR= 5 ++- OUT_LEN= 160 ++*/ ++static KRML_MUSTINLINE void ++compress_then_serialize_ring_element_v_650( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re, Eurydice_slice out) ++{ ++ compress_then_serialize_5_3c(re, out); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.encrypt ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]] with const ++generics ++- K= 4 ++- CIPHERTEXT_SIZE= 1568 ++- T_AS_NTT_ENCODED_SIZE= 1536 ++- C1_LEN= 1408 ++- C2_LEN= 160 ++- U_COMPRESSION_FACTOR= 11 ++- V_COMPRESSION_FACTOR= 5 ++- BLOCK_LEN= 352 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++*/ ++static void ++encrypt_7b1(Eurydice_slice public_key, uint8_t message[32U], ++ Eurydice_slice randomness, uint8_t ret[1568U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 t_as_ntt[4U]; ++ deserialize_ring_elements_reduced_4f3( ++ Eurydice_slice_subslice_to(public_key, (size_t)1536U, uint8_t, size_t), ++ t_as_ntt); ++ Eurydice_slice seed = ++ Eurydice_slice_subslice_from(public_key, (size_t)1536U, uint8_t, size_t); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 A[4U][4U]; ++ uint8_t ret0[34U]; ++ libcrux_ml_kem_utils_into_padded_array_6d1(seed, ret0); ++ sample_matrix_A_e71(ret0, false, A); ++ uint8_t prf_input[33U]; ++ libcrux_ml_kem_utils_into_padded_array_6d2(randomness, prf_input); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input0[33U]; ++ memcpy(copy_of_prf_input0, prf_input, (size_t)33U * sizeof(uint8_t)); ++ tuple_710 uu____1 = sample_vector_cbd_then_ntt_781(copy_of_prf_input0, 0U); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 r_as_ntt[4U]; ++ memcpy( ++ r_as_ntt, uu____1.fst, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ uint8_t domain_separator0 = uu____1.snd; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input[33U]; ++ memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); ++ tuple_710 uu____3 = ++ sample_ring_element_cbd_a81(copy_of_prf_input, domain_separator0); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_1[4U]; ++ memcpy( ++ error_1, uu____3.fst, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ uint8_t domain_separator = uu____3.snd; ++ prf_input[32U] = domain_separator; ++ uint8_t prf_output[128U]; ++ PRF_f1_2e4(Eurydice_array_to_slice((size_t)33U, prf_input, uint8_t), ++ prf_output); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_2 = ++ sample_from_binomial_distribution_ca( ++ Eurydice_array_to_slice((size_t)128U, prf_output, uint8_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 u[4U]; ++ compute_vector_u_931(A, r_as_ntt, error_1, u); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_message[32U]; ++ memcpy(copy_of_message, message, (size_t)32U * sizeof(uint8_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 message_as_ring_element = ++ deserialize_then_decompress_message_f7(copy_of_message); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 v = ++ compute_ring_element_v_541(t_as_ntt, r_as_ntt, &error_2, ++ &message_as_ring_element); ++ uint8_t ciphertext[1568U] = { 0U }; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____5[4U]; ++ memcpy( ++ uu____5, u, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ compress_then_serialize_u_281( ++ uu____5, Eurydice_array_to_subslice2(ciphertext, (size_t)0U, ++ (size_t)1408U, uint8_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____6 = v; ++ compress_then_serialize_ring_element_v_650( ++ uu____6, Eurydice_array_to_subslice_from((size_t)1568U, ciphertext, ++ (size_t)1408U, uint8_t, size_t)); ++ memcpy(ret, ciphertext, (size_t)1568U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::variant::Variant for ++libcrux_ml_kem::variant::MlKem)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.variant.kdf_d8 ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]] ++with const generics ++- K= 4 ++- CIPHERTEXT_SIZE= 1568 ++*/ ++static KRML_MUSTINLINE void ++kdf_d8_93(Eurydice_slice shared_secret, ++ uint8_t ret[32U]) ++{ ++ uint8_t out[32U] = { 0U }; ++ Eurydice_slice_copy(Eurydice_array_to_slice((size_t)32U, out, uint8_t), ++ shared_secret, uint8_t); ++ memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.encapsulate ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 4 ++- CIPHERTEXT_SIZE= 1568 ++- PUBLIC_KEY_SIZE= 1568 ++- T_AS_NTT_ENCODED_SIZE= 1536 ++- C1_SIZE= 1408 ++- C2_SIZE= 160 ++- VECTOR_U_COMPRESSION_FACTOR= 11 ++- VECTOR_V_COMPRESSION_FACTOR= 5 ++- VECTOR_U_BLOCK_LEN= 352 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++*/ ++tuple_21 ++libcrux_ml_kem_ind_cca_encapsulate_eb1( ++ libcrux_ml_kem_types_MlKemPublicKey_1f *public_key, ++ uint8_t randomness[32U]) ++{ ++ uint8_t randomness0[32U]; ++ entropy_preprocess_d8_d1( ++ Eurydice_array_to_slice((size_t)32U, randomness, uint8_t), randomness0); ++ uint8_t to_hash[64U]; ++ libcrux_ml_kem_utils_into_padded_array_6d( ++ Eurydice_array_to_slice((size_t)32U, randomness0, uint8_t), to_hash); ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice_from( ++ (size_t)64U, to_hash, LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t, ++ size_t); ++ uint8_t ret[32U]; ++ H_f1_191(Eurydice_array_to_slice( ++ (size_t)1568U, libcrux_ml_kem_types_as_slice_cb_3d1(public_key), ++ uint8_t), ++ ret); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)32U, ret, uint8_t), uint8_t); ++ uint8_t hashed[64U]; ++ G_f1_381(Eurydice_array_to_slice((size_t)64U, to_hash, uint8_t), hashed); ++ Eurydice_slice_uint8_t_x2 uu____1 = Eurydice_slice_split_at( ++ Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), ++ LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, ++ Eurydice_slice_uint8_t_x2); ++ Eurydice_slice shared_secret = uu____1.fst; ++ Eurydice_slice pseudorandomness = uu____1.snd; ++ Eurydice_slice uu____2 = Eurydice_array_to_slice( ++ (size_t)1568U, libcrux_ml_kem_types_as_slice_cb_3d1(public_key), uint8_t); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_randomness[32U]; ++ memcpy(copy_of_randomness, randomness0, (size_t)32U * sizeof(uint8_t)); ++ uint8_t ciphertext[1568U]; ++ encrypt_7b1(uu____2, copy_of_randomness, pseudorandomness, ciphertext); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_ciphertext[1568U]; ++ memcpy(copy_of_ciphertext, ciphertext, (size_t)1568U * sizeof(uint8_t)); ++ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext ciphertext0 = ++ libcrux_ml_kem_types_from_01_331(copy_of_ciphertext); ++ uint8_t shared_secret_array[32U]; ++ kdf_d8_93(shared_secret, shared_secret_array); ++ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext uu____5 = ciphertext0; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_shared_secret_array[32U]; ++ memcpy(copy_of_shared_secret_array, shared_secret_array, ++ (size_t)32U * sizeof(uint8_t)); ++ tuple_21 lit; ++ lit.fst = uu____5; ++ memcpy(lit.snd, copy_of_shared_secret_array, (size_t)32U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_to_uncompressed_ring_element with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++ ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++deserialize_to_uncompressed_ring_element_27(Eurydice_slice serialized) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = ZERO_89_c3(); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(serialized, uint8_t) / (size_t)24U; i++) { ++ size_t i0 = i; ++ Eurydice_slice bytes = Eurydice_slice_subslice2( ++ serialized, i0 * (size_t)24U, i0 * (size_t)24U + (size_t)24U, uint8_t); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_deserialize_12_0d(bytes); ++ re.coefficients[i0] = uu____0; ++ } ++ return re; ++} ++ ++/** ++ Call [`deserialize_to_uncompressed_ring_element`] for each ring element. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.deserialize_secret_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE void ++deserialize_secret_key_7b1( ++ Eurydice_slice secret_key, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[4U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[4U]; ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, ++ secret_as_ntt[i] = ZERO_89_c3();); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(secret_key, uint8_t) / ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; ++ i++) { ++ size_t i0 = i; ++ Eurydice_slice secret_bytes = Eurydice_slice_subslice2( ++ secret_key, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ uint8_t); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____0 = ++ deserialize_to_uncompressed_ring_element_27(secret_bytes); ++ secret_as_ntt[i0] = uu____0; ++ } ++ memcpy( ++ ret, secret_as_ntt, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.ind_cpa.unpacked.IndCpaPrivateKeyUnpacked with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- $4size_t ++*/ ++typedef struct IndCpaPrivateKeyUnpacked_42_s { ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[4U]; ++} IndCpaPrivateKeyUnpacked_42; ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.vector.portable.compress.decompress_ciphertext_coefficient with ++const generics ++- COEFFICIENT_BITS= 10 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++decompress_ciphertext_coefficient_84( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ int32_t decompressed = (int32_t)v.elements[i0] * ++ (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; ++ decompressed = (decompressed << 1U) + ((int32_t)1 << (uint32_t)(int32_t)10); ++ decompressed = decompressed >> (uint32_t)((int32_t)10 + (int32_t)1); ++ v.elements[i0] = (int16_t)decompressed; ++ } ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.vector.portable.decompress_ciphertext_coefficient_0d with const ++generics ++- COEFFICIENT_BITS= 10 ++*/ ++static libcrux_ml_kem_vector_portable_vector_type_PortableVector ++decompress_ciphertext_coefficient_0d_b3( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ return decompress_ciphertext_coefficient_84(v); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_then_decompress_10 with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++ ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++deserialize_then_decompress_10_50(Eurydice_slice serialized) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = ZERO_89_c3(); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(serialized, uint8_t) / (size_t)20U; i++) { ++ size_t i0 = i; ++ Eurydice_slice bytes = Eurydice_slice_subslice2( ++ serialized, i0 * (size_t)20U, i0 * (size_t)20U + (size_t)20U, uint8_t); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = ++ libcrux_ml_kem_vector_portable_deserialize_10_0d(bytes); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ decompress_ciphertext_coefficient_0d_b3(coefficient); ++ re.coefficients[i0] = uu____0; ++ } ++ return re; ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.vector.portable.compress.decompress_ciphertext_coefficient with ++const generics ++- COEFFICIENT_BITS= 11 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++decompress_ciphertext_coefficient_840( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ int32_t decompressed = (int32_t)v.elements[i0] * ++ (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; ++ decompressed = (decompressed << 1U) + ((int32_t)1 << (uint32_t)(int32_t)11); ++ decompressed = decompressed >> (uint32_t)((int32_t)11 + (int32_t)1); ++ v.elements[i0] = (int16_t)decompressed; ++ } ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.vector.portable.decompress_ciphertext_coefficient_0d with const ++generics ++- COEFFICIENT_BITS= 11 ++*/ ++static libcrux_ml_kem_vector_portable_vector_type_PortableVector ++decompress_ciphertext_coefficient_0d_b30( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ return decompress_ciphertext_coefficient_840(v); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_then_decompress_11 with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++ ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++deserialize_then_decompress_11_1f(Eurydice_slice serialized) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = ZERO_89_c3(); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(serialized, uint8_t) / (size_t)22U; i++) { ++ size_t i0 = i; ++ Eurydice_slice bytes = Eurydice_slice_subslice2( ++ serialized, i0 * (size_t)22U, i0 * (size_t)22U + (size_t)22U, uint8_t); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = ++ libcrux_ml_kem_vector_portable_deserialize_11_0d(bytes); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ decompress_ciphertext_coefficient_0d_b30(coefficient); ++ re.coefficients[i0] = uu____0; ++ } ++ return re; ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_then_decompress_ring_element_u with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- COMPRESSION_FACTOR= 11 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++deserialize_then_decompress_ring_element_u_c20(Eurydice_slice serialized) ++{ ++ return deserialize_then_decompress_11_1f(serialized); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ntt.ntt_vector_u ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- VECTOR_U_COMPRESSION_FACTOR= 11 ++*/ ++static KRML_MUSTINLINE void ++ntt_vector_u_6f0( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) ++{ ++ size_t zeta_i = (size_t)0U; ++ ntt_at_layer_4_plus_8c(&zeta_i, re, (size_t)7U); ++ ntt_at_layer_4_plus_8c(&zeta_i, re, (size_t)6U); ++ ntt_at_layer_4_plus_8c(&zeta_i, re, (size_t)5U); ++ ntt_at_layer_4_plus_8c(&zeta_i, re, (size_t)4U); ++ ntt_at_layer_3_34(&zeta_i, re); ++ ntt_at_layer_2_26(&zeta_i, re); ++ ntt_at_layer_1_3c(&zeta_i, re); ++ poly_barrett_reduce_89_d8(re); ++} ++ ++/** ++ Call [`deserialize_then_decompress_ring_element_u`] on each ring element ++ in the `ciphertext`. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.deserialize_then_decompress_u ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++- CIPHERTEXT_SIZE= 1568 ++- U_COMPRESSION_FACTOR= 11 ++*/ ++static KRML_MUSTINLINE void ++deserialize_then_decompress_u_1a1( ++ uint8_t *ciphertext, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[4U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 u_as_ntt[4U]; ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, ++ u_as_ntt[i] = ZERO_89_c3();); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice((size_t)1568U, ciphertext, uint8_t), ++ uint8_t) / ++ (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * ++ (size_t)11U / (size_t)8U); ++ i++) { ++ size_t i0 = i; ++ Eurydice_slice u_bytes = Eurydice_array_to_subslice2( ++ ciphertext, ++ i0 * (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * ++ (size_t)11U / (size_t)8U), ++ i0 * (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * ++ (size_t)11U / (size_t)8U) + ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * ++ (size_t)11U / (size_t)8U, ++ uint8_t); ++ u_as_ntt[i0] = deserialize_then_decompress_ring_element_u_c20(u_bytes); ++ ntt_vector_u_6f0(&u_as_ntt[i0]); ++ } ++ memcpy( ++ ret, u_as_ntt, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.vector.portable.compress.decompress_ciphertext_coefficient with ++const generics ++- COEFFICIENT_BITS= 4 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++decompress_ciphertext_coefficient_841( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ int32_t decompressed = (int32_t)v.elements[i0] * ++ (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; ++ decompressed = (decompressed << 1U) + ((int32_t)1 << (uint32_t)(int32_t)4); ++ decompressed = decompressed >> (uint32_t)((int32_t)4 + (int32_t)1); ++ v.elements[i0] = (int16_t)decompressed; ++ } ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.vector.portable.decompress_ciphertext_coefficient_0d with const ++generics ++- COEFFICIENT_BITS= 4 ++*/ ++static libcrux_ml_kem_vector_portable_vector_type_PortableVector ++decompress_ciphertext_coefficient_0d_b31( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ return decompress_ciphertext_coefficient_841(v); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.serialize.deserialize_then_decompress_4 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++deserialize_then_decompress_4_94(Eurydice_slice serialized) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = ZERO_89_c3(); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(serialized, uint8_t) / (size_t)8U; i++) { ++ size_t i0 = i; ++ Eurydice_slice bytes = Eurydice_slice_subslice2( ++ serialized, i0 * (size_t)8U, i0 * (size_t)8U + (size_t)8U, uint8_t); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = ++ libcrux_ml_kem_vector_portable_deserialize_4_0d(bytes); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ decompress_ciphertext_coefficient_0d_b31(coefficient); ++ re.coefficients[i0] = uu____0; ++ } ++ return re; ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.vector.portable.compress.decompress_ciphertext_coefficient with ++const generics ++- COEFFICIENT_BITS= 5 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector ++decompress_ciphertext_coefficient_842( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { ++ size_t i0 = i; ++ int32_t decompressed = (int32_t)v.elements[i0] * ++ (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; ++ decompressed = (decompressed << 1U) + ((int32_t)1 << (uint32_t)(int32_t)5); ++ decompressed = decompressed >> (uint32_t)((int32_t)5 + (int32_t)1); ++ v.elements[i0] = (int16_t)decompressed; ++ } ++ return v; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.vector.portable.decompress_ciphertext_coefficient_0d with const ++generics ++- COEFFICIENT_BITS= 5 ++*/ ++static libcrux_ml_kem_vector_portable_vector_type_PortableVector ++decompress_ciphertext_coefficient_0d_b32( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v) ++{ ++ return decompress_ciphertext_coefficient_842(v); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.serialize.deserialize_then_decompress_5 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++deserialize_then_decompress_5_100(Eurydice_slice serialized) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = ZERO_89_c3(); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(serialized, uint8_t) / (size_t)10U; i++) { ++ size_t i0 = i; ++ Eurydice_slice bytes = Eurydice_slice_subslice2( ++ serialized, i0 * (size_t)10U, i0 * (size_t)10U + (size_t)10U, uint8_t); ++ re.coefficients[i0] = ++ libcrux_ml_kem_vector_portable_deserialize_5_0d(bytes); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1 = ++ decompress_ciphertext_coefficient_0d_b32(re.coefficients[i0]); ++ re.coefficients[i0] = uu____1; ++ } ++ return re; ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_then_decompress_ring_element_v with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- COMPRESSION_FACTOR= 5 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++deserialize_then_decompress_ring_element_v_930(Eurydice_slice serialized) ++{ ++ return deserialize_then_decompress_5_100(serialized); ++} ++ ++/** ++This function found in impl ++{libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.polynomial.subtract_reduce_89 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++ ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++subtract_reduce_89_61(libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 b) ++{ ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector ++ coefficient_normal_form = ++ libcrux_ml_kem_vector_portable_montgomery_multiply_by_constant_0d( ++ b.coefficients[i0], (int16_t)1441); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_barrett_reduce_0d( ++ libcrux_ml_kem_vector_portable_sub_0d(self->coefficients[i0], ++ &coefficient_normal_form)); ++ b.coefficients[i0] = uu____0; ++ } ++ return b; ++} ++ ++/** ++ The following functions compute various expressions involving ++ vectors and matrices. The computation of these expressions has been ++ abstracted away into these functions in order to save on loop iterations. ++ Compute v − InverseNTT(sᵀ ◦ NTT(u)) ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.compute_message ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++compute_message_c91( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *v, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *secret_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *u_as_ntt) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result = ZERO_89_c3(); ++ KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = ++ ntt_multiply_89_3b(&secret_as_ntt[i0], &u_as_ntt[i0]); ++ add_to_ring_element_89_1e1(&result, &product);); ++ invert_ntt_montgomery_c91(&result); ++ result = subtract_reduce_89_61(v, result); ++ return result; ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.compress_then_serialize_message with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++ ++*/ ++static KRML_MUSTINLINE void ++compress_then_serialize_message_d4( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re, uint8_t ret[32U]) ++{ ++ uint8_t serialized[32U] = { 0U }; ++ KRML_MAYBE_FOR16( ++ i, (size_t)0U, (size_t)16U, (size_t)1U, size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = ++ to_unsigned_representative_84(re.coefficients[i0]); ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector ++ coefficient_compressed = ++ libcrux_ml_kem_vector_portable_compress_1_0d(coefficient); ++ uint8_t bytes[2U]; libcrux_ml_kem_vector_portable_serialize_1_0d( ++ coefficient_compressed, bytes); ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ serialized, (size_t)2U * i0, (size_t)2U * i0 + (size_t)2U, uint8_t); ++ Eurydice_slice_copy(uu____0, ++ Eurydice_array_to_slice((size_t)2U, bytes, uint8_t), ++ uint8_t);); ++ memcpy(ret, serialized, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++ This function implements Algorithm 14 of the ++ NIST FIPS 203 specification; this is the Kyber CPA-PKE decryption algorithm. ++ ++ Algorithm 14 is reproduced below: ++ ++ ```plaintext ++ Input: decryption key dkₚₖₑ ∈ 𝔹^{384k}. ++ Input: ciphertext c ∈ 𝔹^{32(dᵤk + dᵥ)}. ++ Output: message m ∈ 𝔹^{32}. ++ ++ c₁ ← c[0 : 32dᵤk] ++ c₂ ← c[32dᵤk : 32(dᵤk + dᵥ)] ++ u ← Decompress_{dᵤ}(ByteDecode_{dᵤ}(c₁)) ++ v ← Decompress_{dᵥ}(ByteDecode_{dᵥ}(c₂)) ++ ŝ ← ByteDecode₁₂(dkₚₖₑ) ++ w ← v - NTT-¹(ŝᵀ ◦ NTT(u)) ++ m ← ByteEncode₁(Compress₁(w)) ++ return m ++ ``` ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.decrypt_unpacked ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++- CIPHERTEXT_SIZE= 1568 ++- VECTOR_U_ENCODED_SIZE= 1408 ++- U_COMPRESSION_FACTOR= 11 ++- V_COMPRESSION_FACTOR= 5 ++*/ ++static void ++decrypt_unpacked_6b1(IndCpaPrivateKeyUnpacked_42 *secret_key, ++ uint8_t *ciphertext, uint8_t ret[32U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 u_as_ntt[4U]; ++ deserialize_then_decompress_u_1a1(ciphertext, u_as_ntt); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 v = ++ deserialize_then_decompress_ring_element_v_930( ++ Eurydice_array_to_subslice_from((size_t)1568U, ciphertext, ++ (size_t)1408U, uint8_t, size_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 message = ++ compute_message_c91(&v, secret_key->secret_as_ntt, u_as_ntt); ++ uint8_t ret0[32U]; ++ compress_then_serialize_message_d4(message, ret0); ++ memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.decrypt ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 4 ++- CIPHERTEXT_SIZE= 1568 ++- VECTOR_U_ENCODED_SIZE= 1408 ++- U_COMPRESSION_FACTOR= 11 ++- V_COMPRESSION_FACTOR= 5 ++*/ ++static void ++decrypt_121(Eurydice_slice secret_key, uint8_t *ciphertext, ++ uint8_t ret[32U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[4U]; ++ deserialize_secret_key_7b1(secret_key, secret_as_ntt); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 copy_of_secret_as_ntt[4U]; ++ memcpy( ++ copy_of_secret_as_ntt, secret_as_ntt, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ IndCpaPrivateKeyUnpacked_42 secret_key_unpacked; ++ memcpy( ++ secret_key_unpacked.secret_as_ntt, copy_of_secret_as_ntt, ++ (size_t)4U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ uint8_t ret0[32U]; ++ decrypt_unpacked_6b1(&secret_key_unpacked, ciphertext, ret0); ++ memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRF ++with const generics ++- LEN= 32 ++*/ ++static KRML_MUSTINLINE void ++PRF_7c(Eurydice_slice input, uint8_t ret[32U]) ++{ ++ uint8_t digest[32U] = { 0U }; ++ libcrux_sha3_portable_shake256( ++ Eurydice_array_to_slice((size_t)32U, digest, uint8_t), input); ++ memcpy(ret, digest, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRF_f1 ++with const generics ++- K= 4 ++- LEN= 32 ++*/ ++static KRML_MUSTINLINE void ++PRF_f1_2e3(Eurydice_slice input, uint8_t ret[32U]) ++{ ++ PRF_7c(input, ret); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.decapsulate ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$4size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 4 ++- SECRET_KEY_SIZE= 3168 ++- CPA_SECRET_KEY_SIZE= 1536 ++- PUBLIC_KEY_SIZE= 1568 ++- CIPHERTEXT_SIZE= 1568 ++- T_AS_NTT_ENCODED_SIZE= 1536 ++- C1_SIZE= 1408 ++- C2_SIZE= 160 ++- VECTOR_U_COMPRESSION_FACTOR= 11 ++- VECTOR_V_COMPRESSION_FACTOR= 5 ++- C1_BLOCK_SIZE= 352 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++- IMPLICIT_REJECTION_HASH_INPUT_SIZE= 1600 ++*/ ++void ++libcrux_ml_kem_ind_cca_decapsulate_1f1( ++ libcrux_ml_kem_types_MlKemPrivateKey_95 *private_key, ++ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *ciphertext, ++ uint8_t ret[32U]) ++{ ++ Eurydice_slice_uint8_t_x2 uu____0 = Eurydice_slice_split_at( ++ Eurydice_array_to_slice((size_t)3168U, private_key->value, uint8_t), ++ (size_t)1536U, uint8_t, Eurydice_slice_uint8_t_x2); ++ Eurydice_slice ind_cpa_secret_key = uu____0.fst; ++ Eurydice_slice secret_key0 = uu____0.snd; ++ Eurydice_slice_uint8_t_x2 uu____1 = Eurydice_slice_split_at( ++ secret_key0, (size_t)1568U, uint8_t, Eurydice_slice_uint8_t_x2); ++ Eurydice_slice ind_cpa_public_key = uu____1.fst; ++ Eurydice_slice secret_key = uu____1.snd; ++ Eurydice_slice_uint8_t_x2 uu____2 = Eurydice_slice_split_at( ++ secret_key, LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t, ++ Eurydice_slice_uint8_t_x2); ++ Eurydice_slice ind_cpa_public_key_hash = uu____2.fst; ++ Eurydice_slice implicit_rejection_value = uu____2.snd; ++ uint8_t decrypted[32U]; ++ decrypt_121(ind_cpa_secret_key, ciphertext->value, decrypted); ++ uint8_t to_hash0[64U]; ++ libcrux_ml_kem_utils_into_padded_array_6d( ++ Eurydice_array_to_slice((size_t)32U, decrypted, uint8_t), to_hash0); ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice_from( ++ (size_t)64U, to_hash0, LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, ++ uint8_t, size_t), ++ ind_cpa_public_key_hash, uint8_t); ++ uint8_t hashed[64U]; ++ G_f1_381(Eurydice_array_to_slice((size_t)64U, to_hash0, uint8_t), hashed); ++ Eurydice_slice_uint8_t_x2 uu____3 = Eurydice_slice_split_at( ++ Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), ++ LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, ++ Eurydice_slice_uint8_t_x2); ++ Eurydice_slice shared_secret0 = uu____3.fst; ++ Eurydice_slice pseudorandomness = uu____3.snd; ++ uint8_t to_hash[1600U]; ++ libcrux_ml_kem_utils_into_padded_array_6d4(implicit_rejection_value, to_hash); ++ Eurydice_slice uu____4 = Eurydice_array_to_subslice_from( ++ (size_t)1600U, to_hash, LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, ++ uint8_t, size_t); ++ Eurydice_slice_copy(uu____4, libcrux_ml_kem_types_as_ref_00_d81(ciphertext), ++ uint8_t); ++ uint8_t implicit_rejection_shared_secret0[32U]; ++ PRF_f1_2e3(Eurydice_array_to_slice((size_t)1600U, to_hash, uint8_t), ++ implicit_rejection_shared_secret0); ++ Eurydice_slice uu____5 = ind_cpa_public_key; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_decrypted[32U]; ++ memcpy(copy_of_decrypted, decrypted, (size_t)32U * sizeof(uint8_t)); ++ uint8_t expected_ciphertext[1568U]; ++ encrypt_7b1(uu____5, copy_of_decrypted, pseudorandomness, ++ expected_ciphertext); ++ uint8_t implicit_rejection_shared_secret[32U]; ++ kdf_d8_93(Eurydice_array_to_slice((size_t)32U, ++ implicit_rejection_shared_secret0, uint8_t), ++ implicit_rejection_shared_secret); ++ uint8_t shared_secret[32U]; ++ kdf_d8_93(shared_secret0, shared_secret); ++ uint8_t ret0[32U]; ++ libcrux_ml_kem_constant_time_ops_compare_ciphertexts_select_shared_secret_in_constant_time( ++ libcrux_ml_kem_types_as_ref_00_d81(ciphertext), ++ Eurydice_array_to_slice((size_t)1568U, expected_ciphertext, uint8_t), ++ Eurydice_array_to_slice((size_t)32U, shared_secret, uint8_t), ++ Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret, ++ uint8_t), ++ ret0); ++ memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++ This function deserializes ring elements and reduces the result by the field ++ modulus. ++ ++ This function MUST NOT be used on secret inputs. ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_ring_elements_reduced with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- PUBLIC_KEY_SIZE= 800 ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++deserialize_ring_elements_reduced_4f2( ++ Eurydice_slice public_key, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[2U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 deserialized_pk[2U]; ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, ++ deserialized_pk[i] = ZERO_89_c3();); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(public_key, uint8_t) / ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; ++ i++) { ++ size_t i0 = i; ++ Eurydice_slice ring_element = Eurydice_slice_subslice2( ++ public_key, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ uint8_t); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____0 = ++ deserialize_to_reduced_ring_element_45(ring_element); ++ deserialized_pk[i0] = uu____0; ++ } ++ memcpy( ++ ret, deserialized_pk, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++ Call [`serialize_uncompressed_ring_element`] for each ring element. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.serialize_secret_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++- OUT_LEN= 768 ++*/ ++static KRML_MUSTINLINE void ++serialize_secret_key_a30( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *key, ++ uint8_t ret[768U]) ++{ ++ uint8_t out[768U] = { 0U }; ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)2U, key, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = key[i0]; ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ out, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ (i0 + (size_t)1U) * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ uint8_t); ++ uint8_t ret0[384U]; ++ serialize_uncompressed_ring_element_3c(&re, ret0); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)384U, ret0, uint8_t), uint8_t); ++ } ++ memcpy(ret, out, (size_t)768U * sizeof(uint8_t)); ++} ++ ++/** ++ Concatenate `t` and `ρ` into the public key. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.serialize_public_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++- RANKED_BYTES_PER_RING_ELEMENT= 768 ++- PUBLIC_KEY_SIZE= 800 ++*/ ++static KRML_MUSTINLINE void ++serialize_public_key_670( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *t_as_ntt, ++ Eurydice_slice seed_for_a, uint8_t ret[800U]) ++{ ++ uint8_t public_key_serialized[800U] = { 0U }; ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ public_key_serialized, (size_t)0U, (size_t)768U, uint8_t); ++ uint8_t ret0[768U]; ++ serialize_secret_key_a30(t_as_ntt, ret0); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)768U, ret0, uint8_t), uint8_t); ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice_from((size_t)800U, public_key_serialized, ++ (size_t)768U, uint8_t, size_t), ++ seed_for_a, uint8_t); ++ memcpy(ret, public_key_serialized, (size_t)800U * sizeof(uint8_t)); ++} ++ ++/** ++ Validate an ML-KEM public key. ++ ++ This implements the Modulus check in 7.2 2. ++ Note that the size check in 7.2 1 is covered by the `PUBLIC_KEY_SIZE` in the ++ `public_key` type. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.validate_public_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++- RANKED_BYTES_PER_RING_ELEMENT= 768 ++- PUBLIC_KEY_SIZE= 800 ++*/ ++bool ++libcrux_ml_kem_ind_cca_validate_public_key_b70(uint8_t *public_key) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 deserialized_pk[2U]; ++ deserialize_ring_elements_reduced_4f2( ++ Eurydice_array_to_subslice_to((size_t)800U, public_key, (size_t)768U, ++ uint8_t, size_t), ++ deserialized_pk); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *uu____0 = deserialized_pk; ++ uint8_t public_key_serialized[800U]; ++ serialize_public_key_670( ++ uu____0, ++ Eurydice_array_to_subslice_from((size_t)800U, public_key, (size_t)768U, ++ uint8_t, size_t), ++ public_key_serialized); ++ return core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( ++ (size_t)800U, public_key, public_key_serialized, uint8_t, uint8_t, bool); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.H_f1 ++with const generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++H_f1_190(Eurydice_slice input, uint8_t ret[32U]) ++{ ++ libcrux_ml_kem_hash_functions_portable_H(input, ret); ++} ++ ++/** ++ Validate an ML-KEM private key. ++ ++ This implements the Hash check in 7.3 3. ++ Note that the size checks in 7.2 1 and 2 are covered by the `SECRET_KEY_SIZE` ++ and `CIPHERTEXT_SIZE` in the `private_key` and `ciphertext` types. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.validate_private_key ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]] ++with const generics ++- K= 2 ++- SECRET_KEY_SIZE= 1632 ++- CIPHERTEXT_SIZE= 768 ++*/ ++bool ++libcrux_ml_kem_ind_cca_validate_private_key_03( ++ libcrux_ml_kem_types_MlKemPrivateKey_5e *private_key, ++ libcrux_ml_kem_types_MlKemCiphertext_e8 *_ciphertext) ++{ ++ uint8_t t[32U]; ++ H_f1_190(Eurydice_array_to_subslice2( ++ private_key->value, (size_t)384U * (size_t)2U, ++ (size_t)768U * (size_t)2U + (size_t)32U, uint8_t), ++ t); ++ Eurydice_slice expected = Eurydice_array_to_subslice2( ++ private_key->value, (size_t)768U * (size_t)2U + (size_t)32U, ++ (size_t)768U * (size_t)2U + (size_t)64U, uint8_t); ++ return core_array_equality___core__cmp__PartialEq__0___Slice_U____for__Array_T__N___3__eq( ++ (size_t)32U, t, &expected, uint8_t, uint8_t, bool); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.G_f1 ++with const generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++G_f1_380(Eurydice_slice input, uint8_t ret[64U]) ++{ ++ libcrux_ml_kem_hash_functions_portable_G(input, ret); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::variant::Variant for ++libcrux_ml_kem::variant::MlKem)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.variant.cpa_keygen_seed_d8 ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]] ++with const generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++cpa_keygen_seed_d8_4d( ++ Eurydice_slice key_generation_seed, uint8_t ret[64U]) ++{ ++ uint8_t seed[33U] = { 0U }; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2( ++ seed, (size_t)0U, ++ LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t), ++ key_generation_seed, uint8_t); ++ seed[LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE] = ++ (uint8_t)(size_t)2U; ++ uint8_t ret0[64U]; ++ G_f1_380(Eurydice_array_to_slice((size_t)33U, seed, uint8_t), ret0); ++ memcpy(ret, ret0, (size_t)64U * sizeof(uint8_t)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.sample_matrix_A.closure ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]] with const ++generics ++- K= 2 ++*/ ++static void ++closure_fc0( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[2U]) ++{ ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, ++ ret[i] = ZERO_89_c3();); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PortableHash ++with const generics ++- $2size_t ++*/ ++typedef struct PortableHash_8b_s { ++ libcrux_sha3_generic_keccak_KeccakState_48 shake128_state[2U]; ++} PortableHash_8b; ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_init_absorb with const generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE PortableHash_8b ++shake128_init_absorb_790(uint8_t input[2U][34U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakState_48 shake128_state[2U]; ++ KRML_MAYBE_FOR2( ++ i, (size_t)0U, (size_t)2U, (size_t)1U, ++ shake128_state[i] = libcrux_sha3_portable_incremental_shake128_init();); ++ KRML_MAYBE_FOR2( ++ i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; ++ libcrux_sha3_portable_incremental_shake128_absorb_final( ++ &shake128_state[i0], ++ Eurydice_array_to_slice((size_t)34U, input[i0], uint8_t));); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ libcrux_sha3_generic_keccak_KeccakState_48 copy_of_shake128_state[2U]; ++ memcpy(copy_of_shake128_state, shake128_state, ++ (size_t)2U * sizeof(libcrux_sha3_generic_keccak_KeccakState_48)); ++ PortableHash_8b lit; ++ memcpy(lit.shake128_state, copy_of_shake128_state, ++ (size_t)2U * sizeof(libcrux_sha3_generic_keccak_KeccakState_48)); ++ return lit; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_init_absorb_f1 with const ++generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE PortableHash_8b ++shake128_init_absorb_f1_770(uint8_t input[2U][34U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_input[2U][34U]; ++ memcpy(copy_of_input, input, (size_t)2U * sizeof(uint8_t[34U])); ++ return shake128_init_absorb_790(copy_of_input); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_squeeze_three_blocks with const ++generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++shake128_squeeze_three_blocks_eb0( ++ PortableHash_8b *st, uint8_t ret[2U][504U]) ++{ ++ uint8_t out[2U][504U] = { { 0U } }; ++ KRML_MAYBE_FOR2( ++ i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; ++ libcrux_sha3_portable_incremental_shake128_squeeze_first_three_blocks( ++ &st->shake128_state[i0], ++ Eurydice_array_to_slice((size_t)504U, out[i0], uint8_t));); ++ memcpy(ret, out, (size_t)2U * sizeof(uint8_t[504U])); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_squeeze_three_blocks_f1 with ++const generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++shake128_squeeze_three_blocks_f1_840( ++ PortableHash_8b *self, uint8_t ret[2U][504U]) ++{ ++ shake128_squeeze_three_blocks_eb0(self, ret); ++} ++ ++/** ++ If `bytes` contains a set of uniformly random bytes, this function ++ uniformly samples a ring element `â` that is treated as being the NTT ++ representation of the corresponding polynomial `a`. ++ ++ Since rejection sampling is used, it is possible the supplied bytes are ++ not enough to sample the element, in which case an `Err` is returned and the ++ caller must try again with a fresh set of bytes. ++ ++ This function partially implements Algorithm ++ 6 of the NIST FIPS 203 standard, We say "partially" because this ++ implementation only accepts a finite set of bytes as input and returns an error ++ if the set is not enough; Algorithm 6 of the FIPS 203 standard on the other ++ hand samples from an infinite stream of bytes until the ring element is filled. ++ Algorithm 6 is reproduced below: ++ ++ ```plaintext ++ Input: byte stream B ∈ 𝔹*. ++ Output: array â ∈ ℤ₂₅₆. ++ ++ i ← 0 ++ j ← 0 ++ while j < 256 do ++ d₁ ← B[i] + 256·(B[i+1] mod 16) ++ d₂ ← ⌊B[i+1]/16⌋ + 16·B[i+2] ++ if d₁ < q then ++ â[j] ← d₁ ++ j ← j + 1 ++ end if ++ if d₂ < q and j < 256 then ++ â[j] ← d₂ ++ j ← j + 1 ++ end if ++ i ← i + 3 ++ end while ++ return â ++ ``` ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.sampling.sample_from_uniform_distribution_next with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- K= 2 ++- N= 504 ++*/ ++static KRML_MUSTINLINE bool ++sample_from_uniform_distribution_next_171( ++ uint8_t randomness[2U][504U], size_t *sampled_coefficients, ++ int16_t (*out)[272U]) ++{ ++ KRML_MAYBE_FOR2( ++ i0, (size_t)0U, (size_t)2U, (size_t)1U, size_t i1 = i0; ++ for (size_t i = (size_t)0U; i < (size_t)504U / (size_t)24U; i++) { ++ size_t r = i; ++ if (sampled_coefficients[i1] < ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ randomness[i1], r * (size_t)24U, r * (size_t)24U + (size_t)24U, ++ uint8_t); ++ size_t sampled = libcrux_ml_kem_vector_portable_rej_sample_0d( ++ uu____0, Eurydice_array_to_subslice2( ++ out[i1], sampled_coefficients[i1], ++ sampled_coefficients[i1] + (size_t)16U, int16_t)); ++ size_t uu____1 = i1; ++ sampled_coefficients[uu____1] = ++ sampled_coefficients[uu____1] + sampled; ++ } ++ }); ++ bool done = true; ++ KRML_MAYBE_FOR2( ++ i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; ++ if (sampled_coefficients[i0] >= ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { ++ sampled_coefficients[i0] = ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; ++ } else { done = false; }); ++ return done; ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_squeeze_block with const ++generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++shake128_squeeze_block_3b0(PortableHash_8b *st, ++ uint8_t ret[2U][168U]) ++{ ++ uint8_t out[2U][168U] = { { 0U } }; ++ KRML_MAYBE_FOR2( ++ i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; ++ libcrux_sha3_portable_incremental_shake128_squeeze_next_block( ++ &st->shake128_state[i0], ++ Eurydice_array_to_slice((size_t)168U, out[i0], uint8_t));); ++ memcpy(ret, out, (size_t)2U * sizeof(uint8_t[168U])); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_squeeze_block_f1 with const ++generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++shake128_squeeze_block_f1_8e0( ++ PortableHash_8b *self, uint8_t ret[2U][168U]) ++{ ++ shake128_squeeze_block_3b0(self, ret); ++} ++ ++/** ++ If `bytes` contains a set of uniformly random bytes, this function ++ uniformly samples a ring element `â` that is treated as being the NTT ++ representation of the corresponding polynomial `a`. ++ ++ Since rejection sampling is used, it is possible the supplied bytes are ++ not enough to sample the element, in which case an `Err` is returned and the ++ caller must try again with a fresh set of bytes. ++ ++ This function partially implements Algorithm ++ 6 of the NIST FIPS 203 standard, We say "partially" because this ++ implementation only accepts a finite set of bytes as input and returns an error ++ if the set is not enough; Algorithm 6 of the FIPS 203 standard on the other ++ hand samples from an infinite stream of bytes until the ring element is filled. ++ Algorithm 6 is reproduced below: ++ ++ ```plaintext ++ Input: byte stream B ∈ 𝔹*. ++ Output: array â ∈ ℤ₂₅₆. ++ ++ i ← 0 ++ j ← 0 ++ while j < 256 do ++ d₁ ← B[i] + 256·(B[i+1] mod 16) ++ d₂ ← ⌊B[i+1]/16⌋ + 16·B[i+2] ++ if d₁ < q then ++ â[j] ← d₁ ++ j ← j + 1 ++ end if ++ if d₂ < q and j < 256 then ++ â[j] ← d₂ ++ j ← j + 1 ++ end if ++ i ← i + 3 ++ end while ++ return â ++ ``` ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.sampling.sample_from_uniform_distribution_next with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- K= 2 ++- N= 168 ++*/ ++static KRML_MUSTINLINE bool ++sample_from_uniform_distribution_next_172( ++ uint8_t randomness[2U][168U], size_t *sampled_coefficients, ++ int16_t (*out)[272U]) ++{ ++ KRML_MAYBE_FOR2( ++ i0, (size_t)0U, (size_t)2U, (size_t)1U, size_t i1 = i0; ++ for (size_t i = (size_t)0U; i < (size_t)168U / (size_t)24U; i++) { ++ size_t r = i; ++ if (sampled_coefficients[i1] < ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ randomness[i1], r * (size_t)24U, r * (size_t)24U + (size_t)24U, ++ uint8_t); ++ size_t sampled = libcrux_ml_kem_vector_portable_rej_sample_0d( ++ uu____0, Eurydice_array_to_subslice2( ++ out[i1], sampled_coefficients[i1], ++ sampled_coefficients[i1] + (size_t)16U, int16_t)); ++ size_t uu____1 = i1; ++ sampled_coefficients[uu____1] = ++ sampled_coefficients[uu____1] + sampled; ++ } ++ }); ++ bool done = true; ++ KRML_MAYBE_FOR2( ++ i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; ++ if (sampled_coefficients[i0] >= ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { ++ sampled_coefficients[i0] = ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; ++ } else { done = false; }); ++ return done; ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.sampling.sample_from_xof.closure ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]] with const ++generics ++- K= 2 ++*/ ++static libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++closure_e40( ++ int16_t s[272U]) ++{ ++ return from_i16_array_89_33( ++ Eurydice_array_to_subslice2(s, (size_t)0U, (size_t)256U, int16_t)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.sampling.sample_from_xof ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]] with const ++generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++sample_from_xof_460( ++ uint8_t seeds[2U][34U], ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[2U]) ++{ ++ size_t sampled_coefficients[2U] = { 0U }; ++ int16_t out[2U][272U] = { { 0U } }; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_seeds[2U][34U]; ++ memcpy(copy_of_seeds, seeds, (size_t)2U * sizeof(uint8_t[34U])); ++ PortableHash_8b xof_state = shake128_init_absorb_f1_770(copy_of_seeds); ++ uint8_t randomness0[2U][504U]; ++ shake128_squeeze_three_blocks_f1_840(&xof_state, randomness0); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_randomness0[2U][504U]; ++ memcpy(copy_of_randomness0, randomness0, (size_t)2U * sizeof(uint8_t[504U])); ++ bool done = sample_from_uniform_distribution_next_171( ++ copy_of_randomness0, sampled_coefficients, out); ++ while (true) { ++ if (done) { ++ break; ++ } else { ++ uint8_t randomness[2U][168U]; ++ shake128_squeeze_block_f1_8e0(&xof_state, randomness); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_randomness[2U][168U]; ++ memcpy(copy_of_randomness, randomness, ++ (size_t)2U * sizeof(uint8_t[168U])); ++ done = sample_from_uniform_distribution_next_172( ++ copy_of_randomness, sampled_coefficients, out); ++ } ++ } ++ /* Passing arrays by value in Rust generates a copy in C */ ++ int16_t copy_of_out[2U][272U]; ++ memcpy(copy_of_out, out, (size_t)2U * sizeof(int16_t[272U])); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret0[2U]; ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, ++ ret0[i] = closure_e40(copy_of_out[i]);); ++ memcpy( ++ ret, ret0, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.sample_matrix_A ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]] with const ++generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++sample_matrix_A_e70( ++ uint8_t seed[34U], bool transpose, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[2U][2U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 A_transpose[2U][2U]; ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, ++ closure_fc0(A_transpose[i]);); ++ KRML_MAYBE_FOR2( ++ i0, (size_t)0U, (size_t)2U, (size_t)1U, size_t i1 = i0; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_seed[34U]; ++ memcpy(copy_of_seed, seed, (size_t)34U * sizeof(uint8_t)); ++ uint8_t seeds[2U][34U]; KRML_MAYBE_FOR2( ++ i, (size_t)0U, (size_t)2U, (size_t)1U, ++ memcpy(seeds[i], copy_of_seed, (size_t)34U * sizeof(uint8_t));); ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, size_t j = i; ++ seeds[j][32U] = (uint8_t)i1; seeds[j][33U] = (uint8_t)j;); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_seeds[2U][34U]; ++ memcpy(copy_of_seeds, seeds, (size_t)2U * sizeof(uint8_t[34U])); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 sampled[2U]; ++ sample_from_xof_460(copy_of_seeds, sampled); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)2U, sampled, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t j = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 sample = sampled[j]; ++ if (transpose) { ++ A_transpose[j][i1] = sample; ++ } else { ++ A_transpose[i1][j] = sample; ++ } ++ } ++ ++ ); ++ memcpy(ret, A_transpose, ++ (size_t)2U * ++ sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0[2U])); ++} ++ ++/** ++A monomorphic instance of K. ++with types libcrux_ml_kem_polynomial_PolynomialRingElement ++libcrux_ml_kem_vector_portable_vector_type_PortableVector[2size_t], uint8_t ++ ++*/ ++typedef struct tuple_740_s { ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 fst[2U]; ++ uint8_t snd; ++} tuple_740; ++ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRFxN ++with const generics ++- K= 2 ++- LEN= 192 ++*/ ++static KRML_MUSTINLINE void ++PRFxN_1c0(uint8_t (*input)[33U], ++ uint8_t ret[2U][192U]) ++{ ++ uint8_t out[2U][192U] = { { 0U } }; ++ KRML_MAYBE_FOR2( ++ i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; ++ libcrux_sha3_portable_shake256( ++ Eurydice_array_to_slice((size_t)192U, out[i0], uint8_t), ++ Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t));); ++ memcpy(ret, out, (size_t)2U * sizeof(uint8_t[192U])); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRFxN_f1 ++with const generics ++- K= 2 ++- LEN= 192 ++*/ ++static KRML_MUSTINLINE void ++PRFxN_f1_d50(uint8_t (*input)[33U], ++ uint8_t ret[2U][192U]) ++{ ++ PRFxN_1c0(input, ret); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.sampling.sample_from_binomial_distribution with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- ETA= 3 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++sample_from_binomial_distribution_ca0(Eurydice_slice randomness) ++{ ++ return sample_from_binomial_distribution_3_14(randomness); ++} ++ ++/** ++ Sample a vector of ring elements from a centered binomial distribution and ++ convert them into their NTT representations. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.sample_vector_cbd_then_ntt ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]] with const ++generics ++- K= 2 ++- ETA= 3 ++- ETA_RANDOMNESS_SIZE= 192 ++*/ ++static KRML_MUSTINLINE tuple_740 ++sample_vector_cbd_then_ntt_780( ++ uint8_t prf_input[33U], uint8_t domain_separator) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re_as_ntt[2U]; ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, ++ re_as_ntt[i] = ZERO_89_c3();); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input[33U]; ++ memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); ++ uint8_t prf_inputs[2U][33U]; ++ KRML_MAYBE_FOR2( ++ i, (size_t)0U, (size_t)2U, (size_t)1U, ++ memcpy(prf_inputs[i], copy_of_prf_input, (size_t)33U * sizeof(uint8_t));); ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; ++ prf_inputs[i0][32U] = domain_separator; ++ domain_separator = (uint32_t)domain_separator + 1U;); ++ uint8_t prf_outputs[2U][192U]; ++ PRFxN_f1_d50(prf_inputs, prf_outputs); ++ KRML_MAYBE_FOR2( ++ i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; ++ re_as_ntt[i0] = sample_from_binomial_distribution_ca0( ++ Eurydice_array_to_slice((size_t)192U, prf_outputs[i0], uint8_t)); ++ ntt_binomially_sampled_ring_element_63(&re_as_ntt[i0]);); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 copy_of_re_as_ntt[2U]; ++ memcpy( ++ copy_of_re_as_ntt, re_as_ntt, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ tuple_740 lit; ++ memcpy( ++ lit.fst, copy_of_re_as_ntt, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ lit.snd = domain_separator; ++ return lit; ++} ++ ++/** ++ Given two polynomial ring elements `lhs` and `rhs`, compute the pointwise ++ sum of their constituent coefficients. ++*/ ++/** ++This function found in impl ++{libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.polynomial.add_to_ring_element_89 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++add_to_ring_element_89_1e0( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *rhs) ++{ ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)16U, self->coefficients, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector), ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector); ++ i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_add_0d(self->coefficients[i0], ++ &rhs->coefficients[i0]); ++ self->coefficients[i0] = uu____0; ++ } ++} ++ ++/** ++ Compute  ◦ ŝ + ê ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.compute_As_plus_e ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++compute_As_plus_e_c70( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 (*matrix_A)[2U], ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *s_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[2U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result[2U]; ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, ++ result[i] = ZERO_89_c3();); ++ for (size_t i0 = (size_t)0U; ++ i0 < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)2U, matrix_A, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0[2U]), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0[2U]); ++ i0++) { ++ size_t i1 = i0; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *row = matrix_A[i1]; ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)2U, row, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t j = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *matrix_element = ++ &row[j]; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = ++ ntt_multiply_89_3b(matrix_element, &s_as_ntt[j]); ++ add_to_ring_element_89_1e0(&result[i1], &product); ++ } ++ add_standard_error_reduce_89_64(&result[i1], &error_as_ntt[i1]); ++ } ++ memcpy( ++ ret, result, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.generate_keypair ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 2 ++- PRIVATE_KEY_SIZE= 768 ++- PUBLIC_KEY_SIZE= 800 ++- RANKED_BYTES_PER_RING_ELEMENT= 768 ++- ETA1= 3 ++- ETA1_RANDOMNESS_SIZE= 192 ++*/ ++static libcrux_ml_kem_utils_extraction_helper_Keypair512 ++generate_keypair_a20( ++ Eurydice_slice key_generation_seed) ++{ ++ uint8_t hashed[64U]; ++ cpa_keygen_seed_d8_4d(key_generation_seed, hashed); ++ Eurydice_slice_uint8_t_x2 uu____0 = Eurydice_slice_split_at( ++ Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), (size_t)32U, ++ uint8_t, Eurydice_slice_uint8_t_x2); ++ Eurydice_slice seed_for_A0 = uu____0.fst; ++ Eurydice_slice seed_for_secret_and_error = uu____0.snd; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 A_transpose[2U][2U]; ++ uint8_t ret[34U]; ++ libcrux_ml_kem_utils_into_padded_array_6d1(seed_for_A0, ret); ++ sample_matrix_A_e70(ret, true, A_transpose); ++ uint8_t prf_input[33U]; ++ libcrux_ml_kem_utils_into_padded_array_6d2(seed_for_secret_and_error, ++ prf_input); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input0[33U]; ++ memcpy(copy_of_prf_input0, prf_input, (size_t)33U * sizeof(uint8_t)); ++ tuple_740 uu____2 = sample_vector_cbd_then_ntt_780(copy_of_prf_input0, 0U); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[2U]; ++ memcpy( ++ secret_as_ntt, uu____2.fst, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ uint8_t domain_separator = uu____2.snd; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input[33U]; ++ memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_as_ntt[2U]; ++ memcpy( ++ error_as_ntt, ++ sample_vector_cbd_then_ntt_780(copy_of_prf_input, domain_separator).fst, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 t_as_ntt[2U]; ++ compute_As_plus_e_c70(A_transpose, secret_as_ntt, error_as_ntt, t_as_ntt); ++ uint8_t seed_for_A[32U]; ++ core_result_Result_00 dst; ++ Eurydice_slice_to_array2(&dst, seed_for_A0, Eurydice_slice, uint8_t[32U]); ++ core_result_unwrap_41_33(dst, seed_for_A); ++ uint8_t public_key_serialized[800U]; ++ serialize_public_key_670( ++ t_as_ntt, Eurydice_array_to_slice((size_t)32U, seed_for_A, uint8_t), ++ public_key_serialized); ++ uint8_t secret_key_serialized[768U]; ++ serialize_secret_key_a30(secret_as_ntt, secret_key_serialized); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_secret_key_serialized[768U]; ++ memcpy(copy_of_secret_key_serialized, secret_key_serialized, ++ (size_t)768U * sizeof(uint8_t)); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_public_key_serialized[800U]; ++ memcpy(copy_of_public_key_serialized, public_key_serialized, ++ (size_t)800U * sizeof(uint8_t)); ++ libcrux_ml_kem_utils_extraction_helper_Keypair512 lit; ++ memcpy(lit.fst, copy_of_secret_key_serialized, ++ (size_t)768U * sizeof(uint8_t)); ++ memcpy(lit.snd, copy_of_public_key_serialized, ++ (size_t)800U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++ Serialize the secret key. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.serialize_kem_secret_key ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]] ++with const generics ++- K= 2 ++- SERIALIZED_KEY_LEN= 1632 ++*/ ++static KRML_MUSTINLINE void ++serialize_kem_secret_key_19( ++ Eurydice_slice private_key, Eurydice_slice public_key, ++ Eurydice_slice implicit_rejection_value, uint8_t ret[1632U]) ++{ ++ uint8_t out[1632U] = { 0U }; ++ size_t pointer = (size_t)0U; ++ uint8_t *uu____0 = out; ++ size_t uu____1 = pointer; ++ size_t uu____2 = pointer; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2( ++ uu____0, uu____1, uu____2 + Eurydice_slice_len(private_key, uint8_t), ++ uint8_t), ++ private_key, uint8_t); ++ pointer = pointer + Eurydice_slice_len(private_key, uint8_t); ++ uint8_t *uu____3 = out; ++ size_t uu____4 = pointer; ++ size_t uu____5 = pointer; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2( ++ uu____3, uu____4, uu____5 + Eurydice_slice_len(public_key, uint8_t), ++ uint8_t), ++ public_key, uint8_t); ++ pointer = pointer + Eurydice_slice_len(public_key, uint8_t); ++ Eurydice_slice uu____6 = Eurydice_array_to_subslice2( ++ out, pointer, pointer + LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t); ++ uint8_t ret0[32U]; ++ H_f1_190(public_key, ret0); ++ Eurydice_slice_copy( ++ uu____6, Eurydice_array_to_slice((size_t)32U, ret0, uint8_t), uint8_t); ++ pointer = pointer + LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE; ++ uint8_t *uu____7 = out; ++ size_t uu____8 = pointer; ++ size_t uu____9 = pointer; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2( ++ uu____7, uu____8, ++ uu____9 + Eurydice_slice_len(implicit_rejection_value, uint8_t), ++ uint8_t), ++ implicit_rejection_value, uint8_t); ++ memcpy(ret, out, (size_t)1632U * sizeof(uint8_t)); ++} ++ ++/** ++ Packed API ++ ++ Generate a key pair. ++ ++ Depending on the `Vector` and `Hasher` used, this requires different hardware ++ features ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.generate_keypair ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 2 ++- CPA_PRIVATE_KEY_SIZE= 768 ++- PRIVATE_KEY_SIZE= 1632 ++- PUBLIC_KEY_SIZE= 800 ++- BYTES_PER_RING_ELEMENT= 768 ++- ETA1= 3 ++- ETA1_RANDOMNESS_SIZE= 192 ++*/ ++libcrux_ml_kem_types_MlKemKeyPair_cb ++libcrux_ml_kem_ind_cca_generate_keypair_f60(uint8_t randomness[64U]) ++{ ++ Eurydice_slice ind_cpa_keypair_randomness = Eurydice_array_to_subslice2( ++ randomness, (size_t)0U, ++ LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t); ++ Eurydice_slice implicit_rejection_value = Eurydice_array_to_subslice_from( ++ (size_t)64U, randomness, ++ LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t, ++ size_t); ++ libcrux_ml_kem_utils_extraction_helper_Keypair512 uu____0 = ++ generate_keypair_a20(ind_cpa_keypair_randomness); ++ uint8_t ind_cpa_private_key[768U]; ++ memcpy(ind_cpa_private_key, uu____0.fst, (size_t)768U * sizeof(uint8_t)); ++ uint8_t public_key[800U]; ++ memcpy(public_key, uu____0.snd, (size_t)800U * sizeof(uint8_t)); ++ uint8_t secret_key_serialized[1632U]; ++ serialize_kem_secret_key_19( ++ Eurydice_array_to_slice((size_t)768U, ind_cpa_private_key, uint8_t), ++ Eurydice_array_to_slice((size_t)800U, public_key, uint8_t), ++ implicit_rejection_value, secret_key_serialized); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_secret_key_serialized[1632U]; ++ memcpy(copy_of_secret_key_serialized, secret_key_serialized, ++ (size_t)1632U * sizeof(uint8_t)); ++ libcrux_ml_kem_types_MlKemPrivateKey_5e private_key = ++ libcrux_ml_kem_types_from_05_89(copy_of_secret_key_serialized); ++ libcrux_ml_kem_types_MlKemPrivateKey_5e uu____2 = private_key; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_public_key[800U]; ++ memcpy(copy_of_public_key, public_key, (size_t)800U * sizeof(uint8_t)); ++ return libcrux_ml_kem_types_from_17_82( ++ uu____2, libcrux_ml_kem_types_from_b6_96(copy_of_public_key)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::variant::Variant for ++libcrux_ml_kem::variant::MlKem)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.variant.entropy_preprocess_d8 ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]] ++with const generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++entropy_preprocess_d8_6c(Eurydice_slice randomness, ++ uint8_t ret[32U]) ++{ ++ uint8_t out[32U] = { 0U }; ++ Eurydice_slice_copy(Eurydice_array_to_slice((size_t)32U, out, uint8_t), ++ randomness, uint8_t); ++ memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++ This function deserializes ring elements and reduces the result by the field ++ modulus. ++ ++ This function MUST NOT be used on secret inputs. ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_ring_elements_reduced with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- PUBLIC_KEY_SIZE= 768 ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++deserialize_ring_elements_reduced_4f1( ++ Eurydice_slice public_key, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[2U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 deserialized_pk[2U]; ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, ++ deserialized_pk[i] = ZERO_89_c3();); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(public_key, uint8_t) / ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; ++ i++) { ++ size_t i0 = i; ++ Eurydice_slice ring_element = Eurydice_slice_subslice2( ++ public_key, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ uint8_t); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____0 = ++ deserialize_to_reduced_ring_element_45(ring_element); ++ deserialized_pk[i0] = uu____0; ++ } ++ memcpy( ++ ret, deserialized_pk, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRFxN ++with const generics ++- K= 2 ++- LEN= 128 ++*/ ++static KRML_MUSTINLINE void ++PRFxN_1c1(uint8_t (*input)[33U], ++ uint8_t ret[2U][128U]) ++{ ++ uint8_t out[2U][128U] = { { 0U } }; ++ KRML_MAYBE_FOR2( ++ i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; ++ libcrux_sha3_portable_shake256( ++ Eurydice_array_to_slice((size_t)128U, out[i0], uint8_t), ++ Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t));); ++ memcpy(ret, out, (size_t)2U * sizeof(uint8_t[128U])); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRFxN_f1 ++with const generics ++- K= 2 ++- LEN= 128 ++*/ ++static KRML_MUSTINLINE void ++PRFxN_f1_d51(uint8_t (*input)[33U], ++ uint8_t ret[2U][128U]) ++{ ++ PRFxN_1c1(input, ret); ++} ++ ++/** ++ Sample a vector of ring elements from a centered binomial distribution. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.sample_ring_element_cbd ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]] with const ++generics ++- K= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++*/ ++static KRML_MUSTINLINE tuple_740 ++sample_ring_element_cbd_a80(uint8_t prf_input[33U], uint8_t domain_separator) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_1[2U]; ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, ++ error_1[i] = ZERO_89_c3();); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input[33U]; ++ memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); ++ uint8_t prf_inputs[2U][33U]; ++ KRML_MAYBE_FOR2( ++ i, (size_t)0U, (size_t)2U, (size_t)1U, ++ memcpy(prf_inputs[i], copy_of_prf_input, (size_t)33U * sizeof(uint8_t));); ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; ++ prf_inputs[i0][32U] = domain_separator; ++ domain_separator = (uint32_t)domain_separator + 1U;); ++ uint8_t prf_outputs[2U][128U]; ++ PRFxN_f1_d51(prf_inputs, prf_outputs); ++ KRML_MAYBE_FOR2( ++ i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____1 = ++ sample_from_binomial_distribution_ca( ++ Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t)); ++ error_1[i0] = uu____1;); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 copy_of_error_1[2U]; ++ memcpy( ++ copy_of_error_1, error_1, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ tuple_740 lit; ++ memcpy( ++ lit.fst, copy_of_error_1, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ lit.snd = domain_separator; ++ return lit; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRF_f1 ++with const generics ++- K= 2 ++- LEN= 128 ++*/ ++static KRML_MUSTINLINE void ++PRF_f1_2e2(Eurydice_slice input, ++ uint8_t ret[128U]) ++{ ++ PRF_7c0(input, ret); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.invert_ntt.invert_ntt_montgomery ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++invert_ntt_montgomery_c90( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) ++{ ++ size_t zeta_i = ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT / (size_t)2U; ++ invert_ntt_at_layer_1_4b(&zeta_i, re); ++ invert_ntt_at_layer_2_2b(&zeta_i, re); ++ invert_ntt_at_layer_3_97(&zeta_i, re); ++ invert_ntt_at_layer_4_plus_04(&zeta_i, re, (size_t)4U); ++ invert_ntt_at_layer_4_plus_04(&zeta_i, re, (size_t)5U); ++ invert_ntt_at_layer_4_plus_04(&zeta_i, re, (size_t)6U); ++ invert_ntt_at_layer_4_plus_04(&zeta_i, re, (size_t)7U); ++ poly_barrett_reduce_89_d8(re); ++} ++ ++/** ++ Compute u := InvertNTT(Aᵀ ◦ r̂) + e₁ ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.compute_vector_u ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++compute_vector_u_930( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 (*a_as_ntt)[2U], ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *r_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error_1, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[2U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result[2U]; ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, ++ result[i] = ZERO_89_c3();); ++ for (size_t i0 = (size_t)0U; ++ i0 < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)2U, a_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0[2U]), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0[2U]); ++ i0++) { ++ size_t i1 = i0; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *row = a_as_ntt[i1]; ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)2U, row, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t j = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *a_element = &row[j]; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = ++ ntt_multiply_89_3b(a_element, &r_as_ntt[j]); ++ add_to_ring_element_89_1e0(&result[i1], &product); ++ } ++ invert_ntt_montgomery_c90(&result[i1]); ++ add_error_reduce_89_5d(&result[i1], &error_1[i1]); ++ } ++ memcpy( ++ ret, result, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++ Compute InverseNTT(tᵀ ◦ r̂) + e₂ + message ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.compute_ring_element_v ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++compute_ring_element_v_540( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *t_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *r_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error_2, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *message) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result = ZERO_89_c3(); ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = ++ ntt_multiply_89_3b(&t_as_ntt[i0], &r_as_ntt[i0]); ++ add_to_ring_element_89_1e0(&result, &product);); ++ invert_ntt_montgomery_c90(&result); ++ result = add_message_error_reduce_89_c4(error_2, message, result); ++ return result; ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.serialize.compress_then_serialize_10 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- OUT_LEN= 320 ++*/ ++static KRML_MUSTINLINE void ++compress_then_serialize_10_88( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, uint8_t ret[320U]) ++{ ++ uint8_t serialized[320U] = { 0U }; ++ for (size_t i = (size_t)0U; ++ i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = ++ compress_0d_96(to_unsigned_representative_84(re->coefficients[i0])); ++ uint8_t bytes[20U]; ++ libcrux_ml_kem_vector_portable_serialize_10_0d(coefficient, bytes); ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ serialized, (size_t)20U * i0, (size_t)20U * i0 + (size_t)20U, uint8_t); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)20U, bytes, uint8_t), uint8_t); ++ } ++ memcpy(ret, serialized, (size_t)320U * sizeof(uint8_t)); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.compress_then_serialize_ring_element_u with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- COMPRESSION_FACTOR= 10 ++- OUT_LEN= 320 ++*/ ++static KRML_MUSTINLINE void ++compress_then_serialize_ring_element_u_2e( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, uint8_t ret[320U]) ++{ ++ uint8_t uu____0[320U]; ++ compress_then_serialize_10_88(re, uu____0); ++ memcpy(ret, uu____0, (size_t)320U * sizeof(uint8_t)); ++} ++ ++/** ++ Call [`compress_then_serialize_ring_element_u`] on each ring element. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.compress_then_serialize_u ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++- OUT_LEN= 640 ++- COMPRESSION_FACTOR= 10 ++- BLOCK_LEN= 320 ++*/ ++static void ++compress_then_serialize_u_280( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 input[2U], ++ Eurydice_slice out) ++{ ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)2U, input, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = input[i0]; ++ Eurydice_slice uu____0 = Eurydice_slice_subslice2( ++ out, i0 * ((size_t)640U / (size_t)2U), ++ (i0 + (size_t)1U) * ((size_t)640U / (size_t)2U), uint8_t); ++ uint8_t ret[320U]; ++ compress_then_serialize_ring_element_u_2e(&re, ret); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)320U, ret, uint8_t), uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.compress_then_serialize_ring_element_v with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- COMPRESSION_FACTOR= 4 ++- OUT_LEN= 128 ++*/ ++static KRML_MUSTINLINE void ++compress_then_serialize_ring_element_v_65( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re, Eurydice_slice out) ++{ ++ compress_then_serialize_4_80(re, out); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.encrypt ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]] with const ++generics ++- K= 2 ++- CIPHERTEXT_SIZE= 768 ++- T_AS_NTT_ENCODED_SIZE= 768 ++- C1_LEN= 640 ++- C2_LEN= 128 ++- U_COMPRESSION_FACTOR= 10 ++- V_COMPRESSION_FACTOR= 4 ++- BLOCK_LEN= 320 ++- ETA1= 3 ++- ETA1_RANDOMNESS_SIZE= 192 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++*/ ++static void ++encrypt_7b0(Eurydice_slice public_key, uint8_t message[32U], ++ Eurydice_slice randomness, uint8_t ret[768U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 t_as_ntt[2U]; ++ deserialize_ring_elements_reduced_4f1( ++ Eurydice_slice_subslice_to(public_key, (size_t)768U, uint8_t, size_t), ++ t_as_ntt); ++ Eurydice_slice seed = ++ Eurydice_slice_subslice_from(public_key, (size_t)768U, uint8_t, size_t); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 A[2U][2U]; ++ uint8_t ret0[34U]; ++ libcrux_ml_kem_utils_into_padded_array_6d1(seed, ret0); ++ sample_matrix_A_e70(ret0, false, A); ++ uint8_t prf_input[33U]; ++ libcrux_ml_kem_utils_into_padded_array_6d2(randomness, prf_input); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input0[33U]; ++ memcpy(copy_of_prf_input0, prf_input, (size_t)33U * sizeof(uint8_t)); ++ tuple_740 uu____1 = sample_vector_cbd_then_ntt_780(copy_of_prf_input0, 0U); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 r_as_ntt[2U]; ++ memcpy( ++ r_as_ntt, uu____1.fst, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ uint8_t domain_separator0 = uu____1.snd; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input[33U]; ++ memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); ++ tuple_740 uu____3 = ++ sample_ring_element_cbd_a80(copy_of_prf_input, domain_separator0); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_1[2U]; ++ memcpy( ++ error_1, uu____3.fst, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ uint8_t domain_separator = uu____3.snd; ++ prf_input[32U] = domain_separator; ++ uint8_t prf_output[128U]; ++ PRF_f1_2e2(Eurydice_array_to_slice((size_t)33U, prf_input, uint8_t), ++ prf_output); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_2 = ++ sample_from_binomial_distribution_ca( ++ Eurydice_array_to_slice((size_t)128U, prf_output, uint8_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 u[2U]; ++ compute_vector_u_930(A, r_as_ntt, error_1, u); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_message[32U]; ++ memcpy(copy_of_message, message, (size_t)32U * sizeof(uint8_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 message_as_ring_element = ++ deserialize_then_decompress_message_f7(copy_of_message); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 v = ++ compute_ring_element_v_540(t_as_ntt, r_as_ntt, &error_2, ++ &message_as_ring_element); ++ uint8_t ciphertext[768U] = { 0U }; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____5[2U]; ++ memcpy( ++ uu____5, u, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ compress_then_serialize_u_280( ++ uu____5, Eurydice_array_to_subslice2(ciphertext, (size_t)0U, (size_t)640U, ++ uint8_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____6 = v; ++ compress_then_serialize_ring_element_v_65( ++ uu____6, Eurydice_array_to_subslice_from((size_t)768U, ciphertext, ++ (size_t)640U, uint8_t, size_t)); ++ memcpy(ret, ciphertext, (size_t)768U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::variant::Variant for ++libcrux_ml_kem::variant::MlKem)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.variant.kdf_d8 ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]] ++with const generics ++- K= 2 ++- CIPHERTEXT_SIZE= 768 ++*/ ++static KRML_MUSTINLINE void ++kdf_d8_32(Eurydice_slice shared_secret, ++ uint8_t ret[32U]) ++{ ++ uint8_t out[32U] = { 0U }; ++ Eurydice_slice_copy(Eurydice_array_to_slice((size_t)32U, out, uint8_t), ++ shared_secret, uint8_t); ++ memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.encapsulate ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 2 ++- CIPHERTEXT_SIZE= 768 ++- PUBLIC_KEY_SIZE= 800 ++- T_AS_NTT_ENCODED_SIZE= 768 ++- C1_SIZE= 640 ++- C2_SIZE= 128 ++- VECTOR_U_COMPRESSION_FACTOR= 10 ++- VECTOR_V_COMPRESSION_FACTOR= 4 ++- VECTOR_U_BLOCK_LEN= 320 ++- ETA1= 3 ++- ETA1_RANDOMNESS_SIZE= 192 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++*/ ++tuple_ec ++libcrux_ml_kem_ind_cca_encapsulate_eb0( ++ libcrux_ml_kem_types_MlKemPublicKey_be *public_key, ++ uint8_t randomness[32U]) ++{ ++ uint8_t randomness0[32U]; ++ entropy_preprocess_d8_6c( ++ Eurydice_array_to_slice((size_t)32U, randomness, uint8_t), randomness0); ++ uint8_t to_hash[64U]; ++ libcrux_ml_kem_utils_into_padded_array_6d( ++ Eurydice_array_to_slice((size_t)32U, randomness0, uint8_t), to_hash); ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice_from( ++ (size_t)64U, to_hash, LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t, ++ size_t); ++ uint8_t ret[32U]; ++ H_f1_190(Eurydice_array_to_slice( ++ (size_t)800U, libcrux_ml_kem_types_as_slice_cb_3d(public_key), ++ uint8_t), ++ ret); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)32U, ret, uint8_t), uint8_t); ++ uint8_t hashed[64U]; ++ G_f1_380(Eurydice_array_to_slice((size_t)64U, to_hash, uint8_t), hashed); ++ Eurydice_slice_uint8_t_x2 uu____1 = Eurydice_slice_split_at( ++ Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), ++ LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, ++ Eurydice_slice_uint8_t_x2); ++ Eurydice_slice shared_secret = uu____1.fst; ++ Eurydice_slice pseudorandomness = uu____1.snd; ++ Eurydice_slice uu____2 = Eurydice_array_to_slice( ++ (size_t)800U, libcrux_ml_kem_types_as_slice_cb_3d(public_key), uint8_t); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_randomness[32U]; ++ memcpy(copy_of_randomness, randomness0, (size_t)32U * sizeof(uint8_t)); ++ uint8_t ciphertext[768U]; ++ encrypt_7b0(uu____2, copy_of_randomness, pseudorandomness, ciphertext); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_ciphertext[768U]; ++ memcpy(copy_of_ciphertext, ciphertext, (size_t)768U * sizeof(uint8_t)); ++ libcrux_ml_kem_types_MlKemCiphertext_e8 ciphertext0 = ++ libcrux_ml_kem_types_from_01_33(copy_of_ciphertext); ++ uint8_t shared_secret_array[32U]; ++ kdf_d8_32(shared_secret, shared_secret_array); ++ libcrux_ml_kem_types_MlKemCiphertext_e8 uu____5 = ciphertext0; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_shared_secret_array[32U]; ++ memcpy(copy_of_shared_secret_array, shared_secret_array, ++ (size_t)32U * sizeof(uint8_t)); ++ tuple_ec lit; ++ lit.fst = uu____5; ++ memcpy(lit.snd, copy_of_shared_secret_array, (size_t)32U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++ Call [`deserialize_to_uncompressed_ring_element`] for each ring element. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.deserialize_secret_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE void ++deserialize_secret_key_7b0( ++ Eurydice_slice secret_key, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[2U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[2U]; ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, ++ secret_as_ntt[i] = ZERO_89_c3();); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(secret_key, uint8_t) / ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; ++ i++) { ++ size_t i0 = i; ++ Eurydice_slice secret_bytes = Eurydice_slice_subslice2( ++ secret_key, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ uint8_t); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____0 = ++ deserialize_to_uncompressed_ring_element_27(secret_bytes); ++ secret_as_ntt[i0] = uu____0; ++ } ++ memcpy( ++ ret, secret_as_ntt, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.ind_cpa.unpacked.IndCpaPrivateKeyUnpacked with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- $2size_t ++*/ ++typedef struct IndCpaPrivateKeyUnpacked_ae_s { ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[2U]; ++} IndCpaPrivateKeyUnpacked_ae; ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_then_decompress_ring_element_u with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- COMPRESSION_FACTOR= 10 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++deserialize_then_decompress_ring_element_u_c2(Eurydice_slice serialized) ++{ ++ return deserialize_then_decompress_10_50(serialized); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ntt.ntt_vector_u ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- VECTOR_U_COMPRESSION_FACTOR= 10 ++*/ ++static KRML_MUSTINLINE void ++ntt_vector_u_6f( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) ++{ ++ size_t zeta_i = (size_t)0U; ++ ntt_at_layer_4_plus_8c(&zeta_i, re, (size_t)7U); ++ ntt_at_layer_4_plus_8c(&zeta_i, re, (size_t)6U); ++ ntt_at_layer_4_plus_8c(&zeta_i, re, (size_t)5U); ++ ntt_at_layer_4_plus_8c(&zeta_i, re, (size_t)4U); ++ ntt_at_layer_3_34(&zeta_i, re); ++ ntt_at_layer_2_26(&zeta_i, re); ++ ntt_at_layer_1_3c(&zeta_i, re); ++ poly_barrett_reduce_89_d8(re); ++} ++ ++/** ++ Call [`deserialize_then_decompress_ring_element_u`] on each ring element ++ in the `ciphertext`. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.deserialize_then_decompress_u ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++- CIPHERTEXT_SIZE= 768 ++- U_COMPRESSION_FACTOR= 10 ++*/ ++static KRML_MUSTINLINE void ++deserialize_then_decompress_u_1a0( ++ uint8_t *ciphertext, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[2U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 u_as_ntt[2U]; ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, ++ u_as_ntt[i] = ZERO_89_c3();); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice((size_t)768U, ciphertext, uint8_t), ++ uint8_t) / ++ (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * ++ (size_t)10U / (size_t)8U); ++ i++) { ++ size_t i0 = i; ++ Eurydice_slice u_bytes = Eurydice_array_to_subslice2( ++ ciphertext, ++ i0 * (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * ++ (size_t)10U / (size_t)8U), ++ i0 * (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * ++ (size_t)10U / (size_t)8U) + ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * ++ (size_t)10U / (size_t)8U, ++ uint8_t); ++ u_as_ntt[i0] = deserialize_then_decompress_ring_element_u_c2(u_bytes); ++ ntt_vector_u_6f(&u_as_ntt[i0]); ++ } ++ memcpy( ++ ret, u_as_ntt, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_then_decompress_ring_element_v with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- COMPRESSION_FACTOR= 4 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++deserialize_then_decompress_ring_element_v_93(Eurydice_slice serialized) ++{ ++ return deserialize_then_decompress_4_94(serialized); ++} ++ ++/** ++ The following functions compute various expressions involving ++ vectors and matrices. The computation of these expressions has been ++ abstracted away into these functions in order to save on loop iterations. ++ Compute v − InverseNTT(sᵀ ◦ NTT(u)) ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.compute_message ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++compute_message_c90( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *v, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *secret_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *u_as_ntt) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result = ZERO_89_c3(); ++ KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = ++ ntt_multiply_89_3b(&secret_as_ntt[i0], &u_as_ntt[i0]); ++ add_to_ring_element_89_1e0(&result, &product);); ++ invert_ntt_montgomery_c90(&result); ++ result = subtract_reduce_89_61(v, result); ++ return result; ++} ++ ++/** ++ This function implements Algorithm 14 of the ++ NIST FIPS 203 specification; this is the Kyber CPA-PKE decryption algorithm. ++ ++ Algorithm 14 is reproduced below: ++ ++ ```plaintext ++ Input: decryption key dkₚₖₑ ∈ 𝔹^{384k}. ++ Input: ciphertext c ∈ 𝔹^{32(dᵤk + dᵥ)}. ++ Output: message m ∈ 𝔹^{32}. ++ ++ c₁ ← c[0 : 32dᵤk] ++ c₂ ← c[32dᵤk : 32(dᵤk + dᵥ)] ++ u ← Decompress_{dᵤ}(ByteDecode_{dᵤ}(c₁)) ++ v ← Decompress_{dᵥ}(ByteDecode_{dᵥ}(c₂)) ++ ŝ ← ByteDecode₁₂(dkₚₖₑ) ++ w ← v - NTT-¹(ŝᵀ ◦ NTT(u)) ++ m ← ByteEncode₁(Compress₁(w)) ++ return m ++ ``` ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.decrypt_unpacked ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++- CIPHERTEXT_SIZE= 768 ++- VECTOR_U_ENCODED_SIZE= 640 ++- U_COMPRESSION_FACTOR= 10 ++- V_COMPRESSION_FACTOR= 4 ++*/ ++static void ++decrypt_unpacked_6b0(IndCpaPrivateKeyUnpacked_ae *secret_key, ++ uint8_t *ciphertext, uint8_t ret[32U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 u_as_ntt[2U]; ++ deserialize_then_decompress_u_1a0(ciphertext, u_as_ntt); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 v = ++ deserialize_then_decompress_ring_element_v_93( ++ Eurydice_array_to_subslice_from((size_t)768U, ciphertext, ++ (size_t)640U, uint8_t, size_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 message = ++ compute_message_c90(&v, secret_key->secret_as_ntt, u_as_ntt); ++ uint8_t ret0[32U]; ++ compress_then_serialize_message_d4(message, ret0); ++ memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.decrypt ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 2 ++- CIPHERTEXT_SIZE= 768 ++- VECTOR_U_ENCODED_SIZE= 640 ++- U_COMPRESSION_FACTOR= 10 ++- V_COMPRESSION_FACTOR= 4 ++*/ ++static void ++decrypt_120(Eurydice_slice secret_key, uint8_t *ciphertext, ++ uint8_t ret[32U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[2U]; ++ deserialize_secret_key_7b0(secret_key, secret_as_ntt); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 copy_of_secret_as_ntt[2U]; ++ memcpy( ++ copy_of_secret_as_ntt, secret_as_ntt, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ IndCpaPrivateKeyUnpacked_ae secret_key_unpacked; ++ memcpy( ++ secret_key_unpacked.secret_as_ntt, copy_of_secret_as_ntt, ++ (size_t)2U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ uint8_t ret0[32U]; ++ decrypt_unpacked_6b0(&secret_key_unpacked, ciphertext, ret0); ++ memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRF_f1 ++with const generics ++- K= 2 ++- LEN= 32 ++*/ ++static KRML_MUSTINLINE void ++PRF_f1_2e1(Eurydice_slice input, uint8_t ret[32U]) ++{ ++ PRF_7c(input, ret); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.decapsulate ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$2size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 2 ++- SECRET_KEY_SIZE= 1632 ++- CPA_SECRET_KEY_SIZE= 768 ++- PUBLIC_KEY_SIZE= 800 ++- CIPHERTEXT_SIZE= 768 ++- T_AS_NTT_ENCODED_SIZE= 768 ++- C1_SIZE= 640 ++- C2_SIZE= 128 ++- VECTOR_U_COMPRESSION_FACTOR= 10 ++- VECTOR_V_COMPRESSION_FACTOR= 4 ++- C1_BLOCK_SIZE= 320 ++- ETA1= 3 ++- ETA1_RANDOMNESS_SIZE= 192 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++- IMPLICIT_REJECTION_HASH_INPUT_SIZE= 800 ++*/ ++void ++libcrux_ml_kem_ind_cca_decapsulate_1f0( ++ libcrux_ml_kem_types_MlKemPrivateKey_5e *private_key, ++ libcrux_ml_kem_types_MlKemCiphertext_e8 *ciphertext, uint8_t ret[32U]) ++{ ++ Eurydice_slice_uint8_t_x2 uu____0 = Eurydice_slice_split_at( ++ Eurydice_array_to_slice((size_t)1632U, private_key->value, uint8_t), ++ (size_t)768U, uint8_t, Eurydice_slice_uint8_t_x2); ++ Eurydice_slice ind_cpa_secret_key = uu____0.fst; ++ Eurydice_slice secret_key0 = uu____0.snd; ++ Eurydice_slice_uint8_t_x2 uu____1 = Eurydice_slice_split_at( ++ secret_key0, (size_t)800U, uint8_t, Eurydice_slice_uint8_t_x2); ++ Eurydice_slice ind_cpa_public_key = uu____1.fst; ++ Eurydice_slice secret_key = uu____1.snd; ++ Eurydice_slice_uint8_t_x2 uu____2 = Eurydice_slice_split_at( ++ secret_key, LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t, ++ Eurydice_slice_uint8_t_x2); ++ Eurydice_slice ind_cpa_public_key_hash = uu____2.fst; ++ Eurydice_slice implicit_rejection_value = uu____2.snd; ++ uint8_t decrypted[32U]; ++ decrypt_120(ind_cpa_secret_key, ciphertext->value, decrypted); ++ uint8_t to_hash0[64U]; ++ libcrux_ml_kem_utils_into_padded_array_6d( ++ Eurydice_array_to_slice((size_t)32U, decrypted, uint8_t), to_hash0); ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice_from( ++ (size_t)64U, to_hash0, LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, ++ uint8_t, size_t), ++ ind_cpa_public_key_hash, uint8_t); ++ uint8_t hashed[64U]; ++ G_f1_380(Eurydice_array_to_slice((size_t)64U, to_hash0, uint8_t), hashed); ++ Eurydice_slice_uint8_t_x2 uu____3 = Eurydice_slice_split_at( ++ Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), ++ LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, ++ Eurydice_slice_uint8_t_x2); ++ Eurydice_slice shared_secret0 = uu____3.fst; ++ Eurydice_slice pseudorandomness = uu____3.snd; ++ uint8_t to_hash[800U]; ++ libcrux_ml_kem_utils_into_padded_array_6d0(implicit_rejection_value, to_hash); ++ Eurydice_slice uu____4 = Eurydice_array_to_subslice_from( ++ (size_t)800U, to_hash, LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, ++ uint8_t, size_t); ++ Eurydice_slice_copy(uu____4, libcrux_ml_kem_types_as_ref_00_d8(ciphertext), ++ uint8_t); ++ uint8_t implicit_rejection_shared_secret0[32U]; ++ PRF_f1_2e1(Eurydice_array_to_slice((size_t)800U, to_hash, uint8_t), ++ implicit_rejection_shared_secret0); ++ Eurydice_slice uu____5 = ind_cpa_public_key; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_decrypted[32U]; ++ memcpy(copy_of_decrypted, decrypted, (size_t)32U * sizeof(uint8_t)); ++ uint8_t expected_ciphertext[768U]; ++ encrypt_7b0(uu____5, copy_of_decrypted, pseudorandomness, ++ expected_ciphertext); ++ uint8_t implicit_rejection_shared_secret[32U]; ++ kdf_d8_32(Eurydice_array_to_slice((size_t)32U, ++ implicit_rejection_shared_secret0, uint8_t), ++ implicit_rejection_shared_secret); ++ uint8_t shared_secret[32U]; ++ kdf_d8_32(shared_secret0, shared_secret); ++ uint8_t ret0[32U]; ++ libcrux_ml_kem_constant_time_ops_compare_ciphertexts_select_shared_secret_in_constant_time( ++ libcrux_ml_kem_types_as_ref_00_d8(ciphertext), ++ Eurydice_array_to_slice((size_t)768U, expected_ciphertext, uint8_t), ++ Eurydice_array_to_slice((size_t)32U, shared_secret, uint8_t), ++ Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret, ++ uint8_t), ++ ret0); ++ memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++ This function deserializes ring elements and reduces the result by the field ++ modulus. ++ ++ This function MUST NOT be used on secret inputs. ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_ring_elements_reduced with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- PUBLIC_KEY_SIZE= 1184 ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++deserialize_ring_elements_reduced_4f0( ++ Eurydice_slice public_key, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 deserialized_pk[3U]; ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, ++ deserialized_pk[i] = ZERO_89_c3();); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(public_key, uint8_t) / ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; ++ i++) { ++ size_t i0 = i; ++ Eurydice_slice ring_element = Eurydice_slice_subslice2( ++ public_key, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ uint8_t); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____0 = ++ deserialize_to_reduced_ring_element_45(ring_element); ++ deserialized_pk[i0] = uu____0; ++ } ++ memcpy( ++ ret, deserialized_pk, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++ Call [`serialize_uncompressed_ring_element`] for each ring element. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.serialize_secret_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++- OUT_LEN= 1152 ++*/ ++static KRML_MUSTINLINE void ++serialize_secret_key_a3( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *key, ++ uint8_t ret[1152U]) ++{ ++ uint8_t out[1152U] = { 0U }; ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)3U, key, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = key[i0]; ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ out, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ (i0 + (size_t)1U) * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ uint8_t); ++ uint8_t ret0[384U]; ++ serialize_uncompressed_ring_element_3c(&re, ret0); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)384U, ret0, uint8_t), uint8_t); ++ } ++ memcpy(ret, out, (size_t)1152U * sizeof(uint8_t)); ++} ++ ++/** ++ Concatenate `t` and `ρ` into the public key. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.serialize_public_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++- RANKED_BYTES_PER_RING_ELEMENT= 1152 ++- PUBLIC_KEY_SIZE= 1184 ++*/ ++static KRML_MUSTINLINE void ++serialize_public_key_67( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *t_as_ntt, ++ Eurydice_slice seed_for_a, uint8_t ret[1184U]) ++{ ++ uint8_t public_key_serialized[1184U] = { 0U }; ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ public_key_serialized, (size_t)0U, (size_t)1152U, uint8_t); ++ uint8_t ret0[1152U]; ++ serialize_secret_key_a3(t_as_ntt, ret0); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)1152U, ret0, uint8_t), uint8_t); ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice_from((size_t)1184U, public_key_serialized, ++ (size_t)1152U, uint8_t, size_t), ++ seed_for_a, uint8_t); ++ memcpy(ret, public_key_serialized, (size_t)1184U * sizeof(uint8_t)); ++} ++ ++/** ++ Validate an ML-KEM public key. ++ ++ This implements the Modulus check in 7.2 2. ++ Note that the size check in 7.2 1 is covered by the `PUBLIC_KEY_SIZE` in the ++ `public_key` type. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.validate_public_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++- RANKED_BYTES_PER_RING_ELEMENT= 1152 ++- PUBLIC_KEY_SIZE= 1184 ++*/ ++bool ++libcrux_ml_kem_ind_cca_validate_public_key_b7(uint8_t *public_key) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 deserialized_pk[3U]; ++ deserialize_ring_elements_reduced_4f0( ++ Eurydice_array_to_subslice_to((size_t)1184U, public_key, (size_t)1152U, ++ uint8_t, size_t), ++ deserialized_pk); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *uu____0 = deserialized_pk; ++ uint8_t public_key_serialized[1184U]; ++ serialize_public_key_67( ++ uu____0, ++ Eurydice_array_to_subslice_from((size_t)1184U, public_key, (size_t)1152U, ++ uint8_t, size_t), ++ public_key_serialized); ++ return core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( ++ (size_t)1184U, public_key, public_key_serialized, uint8_t, uint8_t, bool); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.H_f1 ++with const generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++H_f1_19(Eurydice_slice input, uint8_t ret[32U]) ++{ ++ libcrux_ml_kem_hash_functions_portable_H(input, ret); ++} ++ ++/** ++ Validate an ML-KEM private key. ++ ++ This implements the Hash check in 7.3 3. ++ Note that the size checks in 7.2 1 and 2 are covered by the `SECRET_KEY_SIZE` ++ and `CIPHERTEXT_SIZE` in the `private_key` and `ciphertext` types. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.validate_private_key ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] ++with const generics ++- K= 3 ++- SECRET_KEY_SIZE= 2400 ++- CIPHERTEXT_SIZE= 1088 ++*/ ++bool ++libcrux_ml_kem_ind_cca_validate_private_key_05( ++ libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext *_ciphertext) ++{ ++ uint8_t t[32U]; ++ H_f1_19(Eurydice_array_to_subslice2( ++ private_key->value, (size_t)384U * (size_t)3U, ++ (size_t)768U * (size_t)3U + (size_t)32U, uint8_t), ++ t); ++ Eurydice_slice expected = Eurydice_array_to_subslice2( ++ private_key->value, (size_t)768U * (size_t)3U + (size_t)32U, ++ (size_t)768U * (size_t)3U + (size_t)64U, uint8_t); ++ return core_array_equality___core__cmp__PartialEq__0___Slice_U____for__Array_T__N___3__eq( ++ (size_t)32U, t, &expected, uint8_t, uint8_t, bool); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.G_f1 ++with const generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++G_f1_38(Eurydice_slice input, uint8_t ret[64U]) ++{ ++ libcrux_ml_kem_hash_functions_portable_G(input, ret); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::variant::Variant for ++libcrux_ml_kem::variant::MlKem)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.variant.cpa_keygen_seed_d8 ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] ++with const generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++cpa_keygen_seed_d8_b0( ++ Eurydice_slice key_generation_seed, uint8_t ret[64U]) ++{ ++ uint8_t seed[33U] = { 0U }; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2( ++ seed, (size_t)0U, ++ LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t), ++ key_generation_seed, uint8_t); ++ seed[LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE] = ++ (uint8_t)(size_t)3U; ++ uint8_t ret0[64U]; ++ G_f1_38(Eurydice_array_to_slice((size_t)33U, seed, uint8_t), ret0); ++ memcpy(ret, ret0, (size_t)64U * sizeof(uint8_t)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.sample_matrix_A.closure ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const ++generics ++- K= 3 ++*/ ++static void ++closure_fc( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) ++{ ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, ++ ret[i] = ZERO_89_c3();); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PortableHash ++with const generics ++- $3size_t ++*/ ++typedef struct PortableHash_58_s { ++ libcrux_sha3_generic_keccak_KeccakState_48 shake128_state[3U]; ++} PortableHash_58; ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_init_absorb with const generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE PortableHash_58 ++shake128_init_absorb_79(uint8_t input[3U][34U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakState_48 shake128_state[3U]; ++ KRML_MAYBE_FOR3( ++ i, (size_t)0U, (size_t)3U, (size_t)1U, ++ shake128_state[i] = libcrux_sha3_portable_incremental_shake128_init();); ++ KRML_MAYBE_FOR3( ++ i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; ++ libcrux_sha3_portable_incremental_shake128_absorb_final( ++ &shake128_state[i0], ++ Eurydice_array_to_slice((size_t)34U, input[i0], uint8_t));); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ libcrux_sha3_generic_keccak_KeccakState_48 copy_of_shake128_state[3U]; ++ memcpy(copy_of_shake128_state, shake128_state, ++ (size_t)3U * sizeof(libcrux_sha3_generic_keccak_KeccakState_48)); ++ PortableHash_58 lit; ++ memcpy(lit.shake128_state, copy_of_shake128_state, ++ (size_t)3U * sizeof(libcrux_sha3_generic_keccak_KeccakState_48)); ++ return lit; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_init_absorb_f1 with const ++generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE PortableHash_58 ++shake128_init_absorb_f1_77(uint8_t input[3U][34U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_input[3U][34U]; ++ memcpy(copy_of_input, input, (size_t)3U * sizeof(uint8_t[34U])); ++ return shake128_init_absorb_79(copy_of_input); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_squeeze_three_blocks with const ++generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++shake128_squeeze_three_blocks_eb( ++ PortableHash_58 *st, uint8_t ret[3U][504U]) ++{ ++ uint8_t out[3U][504U] = { { 0U } }; ++ KRML_MAYBE_FOR3( ++ i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; ++ libcrux_sha3_portable_incremental_shake128_squeeze_first_three_blocks( ++ &st->shake128_state[i0], ++ Eurydice_array_to_slice((size_t)504U, out[i0], uint8_t));); ++ memcpy(ret, out, (size_t)3U * sizeof(uint8_t[504U])); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_squeeze_three_blocks_f1 with ++const generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++shake128_squeeze_three_blocks_f1_84( ++ PortableHash_58 *self, uint8_t ret[3U][504U]) ++{ ++ shake128_squeeze_three_blocks_eb(self, ret); ++} ++ ++/** ++ If `bytes` contains a set of uniformly random bytes, this function ++ uniformly samples a ring element `â` that is treated as being the NTT ++ representation of the corresponding polynomial `a`. ++ ++ Since rejection sampling is used, it is possible the supplied bytes are ++ not enough to sample the element, in which case an `Err` is returned and the ++ caller must try again with a fresh set of bytes. ++ ++ This function partially implements Algorithm ++ 6 of the NIST FIPS 203 standard, We say "partially" because this ++ implementation only accepts a finite set of bytes as input and returns an error ++ if the set is not enough; Algorithm 6 of the FIPS 203 standard on the other ++ hand samples from an infinite stream of bytes until the ring element is filled. ++ Algorithm 6 is reproduced below: ++ ++ ```plaintext ++ Input: byte stream B ∈ 𝔹*. ++ Output: array â ∈ ℤ₂₅₆. ++ ++ i ← 0 ++ j ← 0 ++ while j < 256 do ++ d₁ ← B[i] + 256·(B[i+1] mod 16) ++ d₂ ← ⌊B[i+1]/16⌋ + 16·B[i+2] ++ if d₁ < q then ++ â[j] ← d₁ ++ j ← j + 1 ++ end if ++ if d₂ < q and j < 256 then ++ â[j] ← d₂ ++ j ← j + 1 ++ end if ++ i ← i + 3 ++ end while ++ return â ++ ``` ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.sampling.sample_from_uniform_distribution_next with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- K= 3 ++- N= 504 ++*/ ++static KRML_MUSTINLINE bool ++sample_from_uniform_distribution_next_17( ++ uint8_t randomness[3U][504U], size_t *sampled_coefficients, ++ int16_t (*out)[272U]) ++{ ++ KRML_MAYBE_FOR3( ++ i0, (size_t)0U, (size_t)3U, (size_t)1U, size_t i1 = i0; ++ for (size_t i = (size_t)0U; i < (size_t)504U / (size_t)24U; i++) { ++ size_t r = i; ++ if (sampled_coefficients[i1] < ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ randomness[i1], r * (size_t)24U, r * (size_t)24U + (size_t)24U, ++ uint8_t); ++ size_t sampled = libcrux_ml_kem_vector_portable_rej_sample_0d( ++ uu____0, Eurydice_array_to_subslice2( ++ out[i1], sampled_coefficients[i1], ++ sampled_coefficients[i1] + (size_t)16U, int16_t)); ++ size_t uu____1 = i1; ++ sampled_coefficients[uu____1] = ++ sampled_coefficients[uu____1] + sampled; ++ } ++ }); ++ bool done = true; ++ KRML_MAYBE_FOR3( ++ i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; ++ if (sampled_coefficients[i0] >= ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { ++ sampled_coefficients[i0] = ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; ++ } else { done = false; }); ++ return done; ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_squeeze_block with const ++generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++shake128_squeeze_block_3b(PortableHash_58 *st, ++ uint8_t ret[3U][168U]) ++{ ++ uint8_t out[3U][168U] = { { 0U } }; ++ KRML_MAYBE_FOR3( ++ i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; ++ libcrux_sha3_portable_incremental_shake128_squeeze_next_block( ++ &st->shake128_state[i0], ++ Eurydice_array_to_slice((size_t)168U, out[i0], uint8_t));); ++ memcpy(ret, out, (size_t)3U * sizeof(uint8_t[168U])); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.hash_functions.portable.shake128_squeeze_block_f1 with const ++generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++shake128_squeeze_block_f1_8e( ++ PortableHash_58 *self, uint8_t ret[3U][168U]) ++{ ++ shake128_squeeze_block_3b(self, ret); ++} ++ ++/** ++ If `bytes` contains a set of uniformly random bytes, this function ++ uniformly samples a ring element `â` that is treated as being the NTT ++ representation of the corresponding polynomial `a`. ++ ++ Since rejection sampling is used, it is possible the supplied bytes are ++ not enough to sample the element, in which case an `Err` is returned and the ++ caller must try again with a fresh set of bytes. ++ ++ This function partially implements Algorithm ++ 6 of the NIST FIPS 203 standard, We say "partially" because this ++ implementation only accepts a finite set of bytes as input and returns an error ++ if the set is not enough; Algorithm 6 of the FIPS 203 standard on the other ++ hand samples from an infinite stream of bytes until the ring element is filled. ++ Algorithm 6 is reproduced below: ++ ++ ```plaintext ++ Input: byte stream B ∈ 𝔹*. ++ Output: array â ∈ ℤ₂₅₆. ++ ++ i ← 0 ++ j ← 0 ++ while j < 256 do ++ d₁ ← B[i] + 256·(B[i+1] mod 16) ++ d₂ ← ⌊B[i+1]/16⌋ + 16·B[i+2] ++ if d₁ < q then ++ â[j] ← d₁ ++ j ← j + 1 ++ end if ++ if d₂ < q and j < 256 then ++ â[j] ← d₂ ++ j ← j + 1 ++ end if ++ i ← i + 3 ++ end while ++ return â ++ ``` ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.sampling.sample_from_uniform_distribution_next with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- K= 3 ++- N= 168 ++*/ ++static KRML_MUSTINLINE bool ++sample_from_uniform_distribution_next_170( ++ uint8_t randomness[3U][168U], size_t *sampled_coefficients, ++ int16_t (*out)[272U]) ++{ ++ KRML_MAYBE_FOR3( ++ i0, (size_t)0U, (size_t)3U, (size_t)1U, size_t i1 = i0; ++ for (size_t i = (size_t)0U; i < (size_t)168U / (size_t)24U; i++) { ++ size_t r = i; ++ if (sampled_coefficients[i1] < ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice2( ++ randomness[i1], r * (size_t)24U, r * (size_t)24U + (size_t)24U, ++ uint8_t); ++ size_t sampled = libcrux_ml_kem_vector_portable_rej_sample_0d( ++ uu____0, Eurydice_array_to_subslice2( ++ out[i1], sampled_coefficients[i1], ++ sampled_coefficients[i1] + (size_t)16U, int16_t)); ++ size_t uu____1 = i1; ++ sampled_coefficients[uu____1] = ++ sampled_coefficients[uu____1] + sampled; ++ } ++ }); ++ bool done = true; ++ KRML_MAYBE_FOR3( ++ i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; ++ if (sampled_coefficients[i0] >= ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { ++ sampled_coefficients[i0] = ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; ++ } else { done = false; }); ++ return done; ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.sampling.sample_from_xof.closure ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const ++generics ++- K= 3 ++*/ ++static libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++closure_e4( ++ int16_t s[272U]) ++{ ++ return from_i16_array_89_33( ++ Eurydice_array_to_subslice2(s, (size_t)0U, (size_t)256U, int16_t)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.sampling.sample_from_xof ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const ++generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++sample_from_xof_46( ++ uint8_t seeds[3U][34U], ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) ++{ ++ size_t sampled_coefficients[3U] = { 0U }; ++ int16_t out[3U][272U] = { { 0U } }; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_seeds[3U][34U]; ++ memcpy(copy_of_seeds, seeds, (size_t)3U * sizeof(uint8_t[34U])); ++ PortableHash_58 xof_state = shake128_init_absorb_f1_77(copy_of_seeds); ++ uint8_t randomness0[3U][504U]; ++ shake128_squeeze_three_blocks_f1_84(&xof_state, randomness0); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_randomness0[3U][504U]; ++ memcpy(copy_of_randomness0, randomness0, (size_t)3U * sizeof(uint8_t[504U])); ++ bool done = sample_from_uniform_distribution_next_17( ++ copy_of_randomness0, sampled_coefficients, out); ++ while (true) { ++ if (done) { ++ break; ++ } else { ++ uint8_t randomness[3U][168U]; ++ shake128_squeeze_block_f1_8e(&xof_state, randomness); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_randomness[3U][168U]; ++ memcpy(copy_of_randomness, randomness, ++ (size_t)3U * sizeof(uint8_t[168U])); ++ done = sample_from_uniform_distribution_next_170( ++ copy_of_randomness, sampled_coefficients, out); ++ } ++ } ++ /* Passing arrays by value in Rust generates a copy in C */ ++ int16_t copy_of_out[3U][272U]; ++ memcpy(copy_of_out, out, (size_t)3U * sizeof(int16_t[272U])); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret0[3U]; ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, ++ ret0[i] = closure_e4(copy_of_out[i]);); ++ memcpy( ++ ret, ret0, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.sample_matrix_A ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const ++generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++sample_matrix_A_e7( ++ uint8_t seed[34U], bool transpose, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U][3U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 A_transpose[3U][3U]; ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, ++ closure_fc(A_transpose[i]);); ++ KRML_MAYBE_FOR3( ++ i0, (size_t)0U, (size_t)3U, (size_t)1U, size_t i1 = i0; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_seed[34U]; ++ memcpy(copy_of_seed, seed, (size_t)34U * sizeof(uint8_t)); ++ uint8_t seeds[3U][34U]; KRML_MAYBE_FOR3( ++ i, (size_t)0U, (size_t)3U, (size_t)1U, ++ memcpy(seeds[i], copy_of_seed, (size_t)34U * sizeof(uint8_t));); ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t j = i; ++ seeds[j][32U] = (uint8_t)i1; seeds[j][33U] = (uint8_t)j;); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_seeds[3U][34U]; ++ memcpy(copy_of_seeds, seeds, (size_t)3U * sizeof(uint8_t[34U])); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 sampled[3U]; ++ sample_from_xof_46(copy_of_seeds, sampled); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)3U, sampled, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t j = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 sample = sampled[j]; ++ if (transpose) { ++ A_transpose[j][i1] = sample; ++ } else { ++ A_transpose[i1][j] = sample; ++ } ++ } ++ ++ ); ++ memcpy(ret, A_transpose, ++ (size_t)3U * ++ sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0[3U])); ++} ++ ++/** ++A monomorphic instance of K. ++with types libcrux_ml_kem_polynomial_PolynomialRingElement ++libcrux_ml_kem_vector_portable_vector_type_PortableVector[3size_t], uint8_t ++ ++*/ ++typedef struct tuple_b0_s { ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 fst[3U]; ++ uint8_t snd; ++} tuple_b0; ++ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRFxN ++with const generics ++- K= 3 ++- LEN= 128 ++*/ ++static KRML_MUSTINLINE void ++PRFxN_1c(uint8_t (*input)[33U], ++ uint8_t ret[3U][128U]) ++{ ++ uint8_t out[3U][128U] = { { 0U } }; ++ KRML_MAYBE_FOR3( ++ i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; ++ libcrux_sha3_portable_shake256( ++ Eurydice_array_to_slice((size_t)128U, out[i0], uint8_t), ++ Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t));); ++ memcpy(ret, out, (size_t)3U * sizeof(uint8_t[128U])); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRFxN_f1 ++with const generics ++- K= 3 ++- LEN= 128 ++*/ ++static KRML_MUSTINLINE void ++PRFxN_f1_d5(uint8_t (*input)[33U], ++ uint8_t ret[3U][128U]) ++{ ++ PRFxN_1c(input, ret); ++} ++ ++/** ++ Sample a vector of ring elements from a centered binomial distribution and ++ convert them into their NTT representations. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.sample_vector_cbd_then_ntt ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const ++generics ++- K= 3 ++- ETA= 2 ++- ETA_RANDOMNESS_SIZE= 128 ++*/ ++static KRML_MUSTINLINE tuple_b0 ++sample_vector_cbd_then_ntt_78( ++ uint8_t prf_input[33U], uint8_t domain_separator) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re_as_ntt[3U]; ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, ++ re_as_ntt[i] = ZERO_89_c3();); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input[33U]; ++ memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); ++ uint8_t prf_inputs[3U][33U]; ++ KRML_MAYBE_FOR3( ++ i, (size_t)0U, (size_t)3U, (size_t)1U, ++ memcpy(prf_inputs[i], copy_of_prf_input, (size_t)33U * sizeof(uint8_t));); ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; ++ prf_inputs[i0][32U] = domain_separator; ++ domain_separator = (uint32_t)domain_separator + 1U;); ++ uint8_t prf_outputs[3U][128U]; ++ PRFxN_f1_d5(prf_inputs, prf_outputs); ++ KRML_MAYBE_FOR3( ++ i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; ++ re_as_ntt[i0] = sample_from_binomial_distribution_ca( ++ Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t)); ++ ntt_binomially_sampled_ring_element_63(&re_as_ntt[i0]);); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 copy_of_re_as_ntt[3U]; ++ memcpy( ++ copy_of_re_as_ntt, re_as_ntt, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ tuple_b0 lit; ++ memcpy( ++ lit.fst, copy_of_re_as_ntt, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ lit.snd = domain_separator; ++ return lit; ++} ++ ++/** ++ Given two polynomial ring elements `lhs` and `rhs`, compute the pointwise ++ sum of their constituent coefficients. ++*/ ++/** ++This function found in impl ++{libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.polynomial.add_to_ring_element_89 ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++add_to_ring_element_89_1e( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *rhs) ++{ ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)16U, self->coefficients, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector), ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector); ++ i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = ++ libcrux_ml_kem_vector_portable_add_0d(self->coefficients[i0], ++ &rhs->coefficients[i0]); ++ self->coefficients[i0] = uu____0; ++ } ++} ++ ++/** ++ Compute  ◦ ŝ + ê ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.compute_As_plus_e ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++compute_As_plus_e_c7( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 (*matrix_A)[3U], ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *s_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result[3U]; ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, ++ result[i] = ZERO_89_c3();); ++ for (size_t i0 = (size_t)0U; ++ i0 < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)3U, matrix_A, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0[3U]), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0[3U]); ++ i0++) { ++ size_t i1 = i0; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *row = matrix_A[i1]; ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)3U, row, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t j = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *matrix_element = ++ &row[j]; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = ++ ntt_multiply_89_3b(matrix_element, &s_as_ntt[j]); ++ add_to_ring_element_89_1e(&result[i1], &product); ++ } ++ add_standard_error_reduce_89_64(&result[i1], &error_as_ntt[i1]); ++ } ++ memcpy( ++ ret, result, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.generate_keypair ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 3 ++- PRIVATE_KEY_SIZE= 1152 ++- PUBLIC_KEY_SIZE= 1184 ++- RANKED_BYTES_PER_RING_ELEMENT= 1152 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++*/ ++static libcrux_ml_kem_utils_extraction_helper_Keypair768 ++generate_keypair_a2( ++ Eurydice_slice key_generation_seed) ++{ ++ uint8_t hashed[64U]; ++ cpa_keygen_seed_d8_b0(key_generation_seed, hashed); ++ Eurydice_slice_uint8_t_x2 uu____0 = Eurydice_slice_split_at( ++ Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), (size_t)32U, ++ uint8_t, Eurydice_slice_uint8_t_x2); ++ Eurydice_slice seed_for_A0 = uu____0.fst; ++ Eurydice_slice seed_for_secret_and_error = uu____0.snd; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 A_transpose[3U][3U]; ++ uint8_t ret[34U]; ++ libcrux_ml_kem_utils_into_padded_array_6d1(seed_for_A0, ret); ++ sample_matrix_A_e7(ret, true, A_transpose); ++ uint8_t prf_input[33U]; ++ libcrux_ml_kem_utils_into_padded_array_6d2(seed_for_secret_and_error, ++ prf_input); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input0[33U]; ++ memcpy(copy_of_prf_input0, prf_input, (size_t)33U * sizeof(uint8_t)); ++ tuple_b0 uu____2 = sample_vector_cbd_then_ntt_78(copy_of_prf_input0, 0U); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[3U]; ++ memcpy( ++ secret_as_ntt, uu____2.fst, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ uint8_t domain_separator = uu____2.snd; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input[33U]; ++ memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_as_ntt[3U]; ++ memcpy( ++ error_as_ntt, ++ sample_vector_cbd_then_ntt_78(copy_of_prf_input, domain_separator).fst, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 t_as_ntt[3U]; ++ compute_As_plus_e_c7(A_transpose, secret_as_ntt, error_as_ntt, t_as_ntt); ++ uint8_t seed_for_A[32U]; ++ core_result_Result_00 dst; ++ Eurydice_slice_to_array2(&dst, seed_for_A0, Eurydice_slice, uint8_t[32U]); ++ core_result_unwrap_41_33(dst, seed_for_A); ++ uint8_t public_key_serialized[1184U]; ++ serialize_public_key_67( ++ t_as_ntt, Eurydice_array_to_slice((size_t)32U, seed_for_A, uint8_t), ++ public_key_serialized); ++ uint8_t secret_key_serialized[1152U]; ++ serialize_secret_key_a3(secret_as_ntt, secret_key_serialized); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_secret_key_serialized[1152U]; ++ memcpy(copy_of_secret_key_serialized, secret_key_serialized, ++ (size_t)1152U * sizeof(uint8_t)); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_public_key_serialized[1184U]; ++ memcpy(copy_of_public_key_serialized, public_key_serialized, ++ (size_t)1184U * sizeof(uint8_t)); ++ libcrux_ml_kem_utils_extraction_helper_Keypair768 lit; ++ memcpy(lit.fst, copy_of_secret_key_serialized, ++ (size_t)1152U * sizeof(uint8_t)); ++ memcpy(lit.snd, copy_of_public_key_serialized, ++ (size_t)1184U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++ Serialize the secret key. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.serialize_kem_secret_key ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] ++with const generics ++- K= 3 ++- SERIALIZED_KEY_LEN= 2400 ++*/ ++static KRML_MUSTINLINE void ++serialize_kem_secret_key_5d( ++ Eurydice_slice private_key, Eurydice_slice public_key, ++ Eurydice_slice implicit_rejection_value, uint8_t ret[2400U]) ++{ ++ uint8_t out[2400U] = { 0U }; ++ size_t pointer = (size_t)0U; ++ uint8_t *uu____0 = out; ++ size_t uu____1 = pointer; ++ size_t uu____2 = pointer; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2( ++ uu____0, uu____1, uu____2 + Eurydice_slice_len(private_key, uint8_t), ++ uint8_t), ++ private_key, uint8_t); ++ pointer = pointer + Eurydice_slice_len(private_key, uint8_t); ++ uint8_t *uu____3 = out; ++ size_t uu____4 = pointer; ++ size_t uu____5 = pointer; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2( ++ uu____3, uu____4, uu____5 + Eurydice_slice_len(public_key, uint8_t), ++ uint8_t), ++ public_key, uint8_t); ++ pointer = pointer + Eurydice_slice_len(public_key, uint8_t); ++ Eurydice_slice uu____6 = Eurydice_array_to_subslice2( ++ out, pointer, pointer + LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t); ++ uint8_t ret0[32U]; ++ H_f1_19(public_key, ret0); ++ Eurydice_slice_copy( ++ uu____6, Eurydice_array_to_slice((size_t)32U, ret0, uint8_t), uint8_t); ++ pointer = pointer + LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE; ++ uint8_t *uu____7 = out; ++ size_t uu____8 = pointer; ++ size_t uu____9 = pointer; ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice2( ++ uu____7, uu____8, ++ uu____9 + Eurydice_slice_len(implicit_rejection_value, uint8_t), ++ uint8_t), ++ implicit_rejection_value, uint8_t); ++ memcpy(ret, out, (size_t)2400U * sizeof(uint8_t)); ++} ++ ++/** ++ Packed API ++ ++ Generate a key pair. ++ ++ Depending on the `Vector` and `Hasher` used, this requires different hardware ++ features ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.generate_keypair ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 3 ++- CPA_PRIVATE_KEY_SIZE= 1152 ++- PRIVATE_KEY_SIZE= 2400 ++- PUBLIC_KEY_SIZE= 1184 ++- BYTES_PER_RING_ELEMENT= 1152 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++*/ ++libcrux_ml_kem_mlkem768_MlKem768KeyPair ++libcrux_ml_kem_ind_cca_generate_keypair_f6(uint8_t randomness[64U]) ++{ ++ Eurydice_slice ind_cpa_keypair_randomness = Eurydice_array_to_subslice2( ++ randomness, (size_t)0U, ++ LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t); ++ Eurydice_slice implicit_rejection_value = Eurydice_array_to_subslice_from( ++ (size_t)64U, randomness, ++ LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t, ++ size_t); ++ libcrux_ml_kem_utils_extraction_helper_Keypair768 uu____0 = ++ generate_keypair_a2(ind_cpa_keypair_randomness); ++ uint8_t ind_cpa_private_key[1152U]; ++ memcpy(ind_cpa_private_key, uu____0.fst, (size_t)1152U * sizeof(uint8_t)); ++ uint8_t public_key[1184U]; ++ memcpy(public_key, uu____0.snd, (size_t)1184U * sizeof(uint8_t)); ++ uint8_t secret_key_serialized[2400U]; ++ serialize_kem_secret_key_5d( ++ Eurydice_array_to_slice((size_t)1152U, ind_cpa_private_key, uint8_t), ++ Eurydice_array_to_slice((size_t)1184U, public_key, uint8_t), ++ implicit_rejection_value, secret_key_serialized); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_secret_key_serialized[2400U]; ++ memcpy(copy_of_secret_key_serialized, secret_key_serialized, ++ (size_t)2400U * sizeof(uint8_t)); ++ libcrux_ml_kem_types_MlKemPrivateKey_55 private_key = ++ libcrux_ml_kem_types_from_05_890(copy_of_secret_key_serialized); ++ libcrux_ml_kem_types_MlKemPrivateKey_55 uu____2 = private_key; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_public_key[1184U]; ++ memcpy(copy_of_public_key, public_key, (size_t)1184U * sizeof(uint8_t)); ++ return libcrux_ml_kem_types_from_17_820( ++ uu____2, libcrux_ml_kem_types_from_b6_960(copy_of_public_key)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::variant::Variant for ++libcrux_ml_kem::variant::MlKem)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.variant.entropy_preprocess_d8 ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] ++with const generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++entropy_preprocess_d8_9f(Eurydice_slice randomness, ++ uint8_t ret[32U]) ++{ ++ uint8_t out[32U] = { 0U }; ++ Eurydice_slice_copy(Eurydice_array_to_slice((size_t)32U, out, uint8_t), ++ randomness, uint8_t); ++ memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++ This function deserializes ring elements and reduces the result by the field ++ modulus. ++ ++ This function MUST NOT be used on secret inputs. ++*/ ++/** ++A monomorphic instance of ++libcrux_ml_kem.serialize.deserialize_ring_elements_reduced with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- PUBLIC_KEY_SIZE= 1152 ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++deserialize_ring_elements_reduced_4f( ++ Eurydice_slice public_key, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 deserialized_pk[3U]; ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, ++ deserialized_pk[i] = ZERO_89_c3();); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(public_key, uint8_t) / ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; ++ i++) { ++ size_t i0 = i; ++ Eurydice_slice ring_element = Eurydice_slice_subslice2( ++ public_key, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ uint8_t); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____0 = ++ deserialize_to_reduced_ring_element_45(ring_element); ++ deserialized_pk[i0] = uu____0; ++ } ++ memcpy( ++ ret, deserialized_pk, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++ Sample a vector of ring elements from a centered binomial distribution. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.sample_ring_element_cbd ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const ++generics ++- K= 3 ++- ETA2_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++*/ ++static KRML_MUSTINLINE tuple_b0 ++sample_ring_element_cbd_a8(uint8_t prf_input[33U], uint8_t domain_separator) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_1[3U]; ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, ++ error_1[i] = ZERO_89_c3();); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input[33U]; ++ memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); ++ uint8_t prf_inputs[3U][33U]; ++ KRML_MAYBE_FOR3( ++ i, (size_t)0U, (size_t)3U, (size_t)1U, ++ memcpy(prf_inputs[i], copy_of_prf_input, (size_t)33U * sizeof(uint8_t));); ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; ++ prf_inputs[i0][32U] = domain_separator; ++ domain_separator = (uint32_t)domain_separator + 1U;); ++ uint8_t prf_outputs[3U][128U]; ++ PRFxN_f1_d5(prf_inputs, prf_outputs); ++ KRML_MAYBE_FOR3( ++ i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____1 = ++ sample_from_binomial_distribution_ca( ++ Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t)); ++ error_1[i0] = uu____1;); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 copy_of_error_1[3U]; ++ memcpy( ++ copy_of_error_1, error_1, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ tuple_b0 lit; ++ memcpy( ++ lit.fst, copy_of_error_1, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ lit.snd = domain_separator; ++ return lit; ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRF_f1 ++with const generics ++- K= 3 ++- LEN= 128 ++*/ ++static KRML_MUSTINLINE void ++PRF_f1_2e0(Eurydice_slice input, ++ uint8_t ret[128U]) ++{ ++ PRF_7c0(input, ret); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.invert_ntt.invert_ntt_montgomery ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++invert_ntt_montgomery_c9( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) ++{ ++ size_t zeta_i = ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT / (size_t)2U; ++ invert_ntt_at_layer_1_4b(&zeta_i, re); ++ invert_ntt_at_layer_2_2b(&zeta_i, re); ++ invert_ntt_at_layer_3_97(&zeta_i, re); ++ invert_ntt_at_layer_4_plus_04(&zeta_i, re, (size_t)4U); ++ invert_ntt_at_layer_4_plus_04(&zeta_i, re, (size_t)5U); ++ invert_ntt_at_layer_4_plus_04(&zeta_i, re, (size_t)6U); ++ invert_ntt_at_layer_4_plus_04(&zeta_i, re, (size_t)7U); ++ poly_barrett_reduce_89_d8(re); ++} ++ ++/** ++ Compute u := InvertNTT(Aᵀ ◦ r̂) + e₁ ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.compute_vector_u ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++compute_vector_u_93( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 (*a_as_ntt)[3U], ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *r_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error_1, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result[3U]; ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, ++ result[i] = ZERO_89_c3();); ++ for (size_t i0 = (size_t)0U; ++ i0 < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)3U, a_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0[3U]), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0[3U]); ++ i0++) { ++ size_t i1 = i0; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *row = a_as_ntt[i1]; ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)3U, row, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t j = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *a_element = &row[j]; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = ++ ntt_multiply_89_3b(a_element, &r_as_ntt[j]); ++ add_to_ring_element_89_1e(&result[i1], &product); ++ } ++ invert_ntt_montgomery_c9(&result[i1]); ++ add_error_reduce_89_5d(&result[i1], &error_1[i1]); ++ } ++ memcpy( ++ ret, result, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++ Compute InverseNTT(tᵀ ◦ r̂) + e₂ + message ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.compute_ring_element_v ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++compute_ring_element_v_54( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *t_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *r_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error_2, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *message) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result = ZERO_89_c3(); ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = ++ ntt_multiply_89_3b(&t_as_ntt[i0], &r_as_ntt[i0]); ++ add_to_ring_element_89_1e(&result, &product);); ++ invert_ntt_montgomery_c9(&result); ++ result = add_message_error_reduce_89_c4(error_2, message, result); ++ return result; ++} ++ ++/** ++ Call [`compress_then_serialize_ring_element_u`] on each ring element. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.compress_then_serialize_u ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++- OUT_LEN= 960 ++- COMPRESSION_FACTOR= 10 ++- BLOCK_LEN= 320 ++*/ ++static void ++compress_then_serialize_u_28( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 input[3U], ++ Eurydice_slice out) ++{ ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice( ++ (size_t)3U, input, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0), ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0); ++ i++) { ++ size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = input[i0]; ++ Eurydice_slice uu____0 = Eurydice_slice_subslice2( ++ out, i0 * ((size_t)960U / (size_t)3U), ++ (i0 + (size_t)1U) * ((size_t)960U / (size_t)3U), uint8_t); ++ uint8_t ret[320U]; ++ compress_then_serialize_ring_element_u_2e(&re, ret); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)320U, ret, uint8_t), uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.encrypt ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const ++generics ++- K= 3 ++- CIPHERTEXT_SIZE= 1088 ++- T_AS_NTT_ENCODED_SIZE= 1152 ++- C1_LEN= 960 ++- C2_LEN= 128 ++- U_COMPRESSION_FACTOR= 10 ++- V_COMPRESSION_FACTOR= 4 ++- BLOCK_LEN= 320 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++*/ ++static void ++encrypt_7b(Eurydice_slice public_key, uint8_t message[32U], ++ Eurydice_slice randomness, uint8_t ret[1088U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 t_as_ntt[3U]; ++ deserialize_ring_elements_reduced_4f( ++ Eurydice_slice_subslice_to(public_key, (size_t)1152U, uint8_t, size_t), ++ t_as_ntt); ++ Eurydice_slice seed = ++ Eurydice_slice_subslice_from(public_key, (size_t)1152U, uint8_t, size_t); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 A[3U][3U]; ++ uint8_t ret0[34U]; ++ libcrux_ml_kem_utils_into_padded_array_6d1(seed, ret0); ++ sample_matrix_A_e7(ret0, false, A); ++ uint8_t prf_input[33U]; ++ libcrux_ml_kem_utils_into_padded_array_6d2(randomness, prf_input); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input0[33U]; ++ memcpy(copy_of_prf_input0, prf_input, (size_t)33U * sizeof(uint8_t)); ++ tuple_b0 uu____1 = sample_vector_cbd_then_ntt_78(copy_of_prf_input0, 0U); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 r_as_ntt[3U]; ++ memcpy( ++ r_as_ntt, uu____1.fst, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ uint8_t domain_separator0 = uu____1.snd; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_prf_input[33U]; ++ memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); ++ tuple_b0 uu____3 = ++ sample_ring_element_cbd_a8(copy_of_prf_input, domain_separator0); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_1[3U]; ++ memcpy( ++ error_1, uu____3.fst, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ uint8_t domain_separator = uu____3.snd; ++ prf_input[32U] = domain_separator; ++ uint8_t prf_output[128U]; ++ PRF_f1_2e0(Eurydice_array_to_slice((size_t)33U, prf_input, uint8_t), ++ prf_output); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_2 = ++ sample_from_binomial_distribution_ca( ++ Eurydice_array_to_slice((size_t)128U, prf_output, uint8_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 u[3U]; ++ compute_vector_u_93(A, r_as_ntt, error_1, u); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_message[32U]; ++ memcpy(copy_of_message, message, (size_t)32U * sizeof(uint8_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 message_as_ring_element = ++ deserialize_then_decompress_message_f7(copy_of_message); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 v = ++ compute_ring_element_v_54(t_as_ntt, r_as_ntt, &error_2, ++ &message_as_ring_element); ++ uint8_t ciphertext[1088U] = { 0U }; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____5[3U]; ++ memcpy( ++ uu____5, u, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ compress_then_serialize_u_28( ++ uu____5, Eurydice_array_to_subslice2(ciphertext, (size_t)0U, (size_t)960U, ++ uint8_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____6 = v; ++ compress_then_serialize_ring_element_v_65( ++ uu____6, Eurydice_array_to_subslice_from((size_t)1088U, ciphertext, ++ (size_t)960U, uint8_t, size_t)); ++ memcpy(ret, ciphertext, (size_t)1088U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::variant::Variant for ++libcrux_ml_kem::variant::MlKem)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.variant.kdf_d8 ++with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] ++with const generics ++- K= 3 ++- CIPHERTEXT_SIZE= 1088 ++*/ ++static KRML_MUSTINLINE void ++kdf_d8_c5(Eurydice_slice shared_secret, ++ uint8_t ret[32U]) ++{ ++ uint8_t out[32U] = { 0U }; ++ Eurydice_slice_copy(Eurydice_array_to_slice((size_t)32U, out, uint8_t), ++ shared_secret, uint8_t); ++ memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.encapsulate ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 3 ++- CIPHERTEXT_SIZE= 1088 ++- PUBLIC_KEY_SIZE= 1184 ++- T_AS_NTT_ENCODED_SIZE= 1152 ++- C1_SIZE= 960 ++- C2_SIZE= 128 ++- VECTOR_U_COMPRESSION_FACTOR= 10 ++- VECTOR_V_COMPRESSION_FACTOR= 4 ++- VECTOR_U_BLOCK_LEN= 320 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++*/ ++tuple_3c ++libcrux_ml_kem_ind_cca_encapsulate_eb( ++ libcrux_ml_kem_types_MlKemPublicKey_15 *public_key, ++ uint8_t randomness[32U]) ++{ ++ uint8_t randomness0[32U]; ++ entropy_preprocess_d8_9f( ++ Eurydice_array_to_slice((size_t)32U, randomness, uint8_t), randomness0); ++ uint8_t to_hash[64U]; ++ libcrux_ml_kem_utils_into_padded_array_6d( ++ Eurydice_array_to_slice((size_t)32U, randomness0, uint8_t), to_hash); ++ Eurydice_slice uu____0 = Eurydice_array_to_subslice_from( ++ (size_t)64U, to_hash, LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t, ++ size_t); ++ uint8_t ret[32U]; ++ H_f1_19(Eurydice_array_to_slice( ++ (size_t)1184U, libcrux_ml_kem_types_as_slice_cb_3d0(public_key), ++ uint8_t), ++ ret); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)32U, ret, uint8_t), uint8_t); ++ uint8_t hashed[64U]; ++ G_f1_38(Eurydice_array_to_slice((size_t)64U, to_hash, uint8_t), hashed); ++ Eurydice_slice_uint8_t_x2 uu____1 = Eurydice_slice_split_at( ++ Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), ++ LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, ++ Eurydice_slice_uint8_t_x2); ++ Eurydice_slice shared_secret = uu____1.fst; ++ Eurydice_slice pseudorandomness = uu____1.snd; ++ Eurydice_slice uu____2 = Eurydice_array_to_slice( ++ (size_t)1184U, libcrux_ml_kem_types_as_slice_cb_3d0(public_key), uint8_t); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_randomness[32U]; ++ memcpy(copy_of_randomness, randomness0, (size_t)32U * sizeof(uint8_t)); ++ uint8_t ciphertext[1088U]; ++ encrypt_7b(uu____2, copy_of_randomness, pseudorandomness, ciphertext); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_ciphertext[1088U]; ++ memcpy(copy_of_ciphertext, ciphertext, (size_t)1088U * sizeof(uint8_t)); ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext ciphertext0 = ++ libcrux_ml_kem_types_from_01_330(copy_of_ciphertext); ++ uint8_t shared_secret_array[32U]; ++ kdf_d8_c5(shared_secret, shared_secret_array); ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext uu____5 = ciphertext0; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_shared_secret_array[32U]; ++ memcpy(copy_of_shared_secret_array, shared_secret_array, ++ (size_t)32U * sizeof(uint8_t)); ++ tuple_3c lit; ++ lit.fst = uu____5; ++ memcpy(lit.snd, copy_of_shared_secret_array, (size_t)32U * sizeof(uint8_t)); ++ return lit; ++} ++ ++/** ++ Call [`deserialize_to_uncompressed_ring_element`] for each ring element. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.deserialize_secret_key ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE void ++deserialize_secret_key_7b( ++ Eurydice_slice secret_key, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[3U]; ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, ++ secret_as_ntt[i] = ZERO_89_c3();); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(secret_key, uint8_t) / ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; ++ i++) { ++ size_t i0 = i; ++ Eurydice_slice secret_bytes = Eurydice_slice_subslice2( ++ secret_key, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + ++ LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, ++ uint8_t); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____0 = ++ deserialize_to_uncompressed_ring_element_27(secret_bytes); ++ secret_as_ntt[i0] = uu____0; ++ } ++ memcpy( ++ ret, secret_as_ntt, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++A monomorphic instance of ++libcrux_ml_kem.ind_cpa.unpacked.IndCpaPrivateKeyUnpacked with types ++libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics ++- $3size_t ++*/ ++typedef struct IndCpaPrivateKeyUnpacked_f8_s { ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[3U]; ++} IndCpaPrivateKeyUnpacked_f8; ++ ++/** ++ Call [`deserialize_then_decompress_ring_element_u`] on each ring element ++ in the `ciphertext`. ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.deserialize_then_decompress_u ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++- CIPHERTEXT_SIZE= 1088 ++- U_COMPRESSION_FACTOR= 10 ++*/ ++static KRML_MUSTINLINE void ++deserialize_then_decompress_u_1a( ++ uint8_t *ciphertext, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 u_as_ntt[3U]; ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, ++ u_as_ntt[i] = ZERO_89_c3();); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len( ++ Eurydice_array_to_slice((size_t)1088U, ciphertext, uint8_t), ++ uint8_t) / ++ (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * ++ (size_t)10U / (size_t)8U); ++ i++) { ++ size_t i0 = i; ++ Eurydice_slice u_bytes = Eurydice_array_to_subslice2( ++ ciphertext, ++ i0 * (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * ++ (size_t)10U / (size_t)8U), ++ i0 * (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * ++ (size_t)10U / (size_t)8U) + ++ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * ++ (size_t)10U / (size_t)8U, ++ uint8_t); ++ u_as_ntt[i0] = deserialize_then_decompress_ring_element_u_c2(u_bytes); ++ ntt_vector_u_6f(&u_as_ntt[i0]); ++ } ++ memcpy( ++ ret, u_as_ntt, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++} ++ ++/** ++ The following functions compute various expressions involving ++ vectors and matrices. The computation of these expressions has been ++ abstracted away into these functions in order to save on loop iterations. ++ Compute v − InverseNTT(sᵀ ◦ NTT(u)) ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.matrix.compute_message ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++*/ ++static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ++compute_message_c9( ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *v, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *secret_as_ntt, ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *u_as_ntt) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result = ZERO_89_c3(); ++ KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = ++ ntt_multiply_89_3b(&secret_as_ntt[i0], &u_as_ntt[i0]); ++ add_to_ring_element_89_1e(&result, &product);); ++ invert_ntt_montgomery_c9(&result); ++ result = subtract_reduce_89_61(v, result); ++ return result; ++} ++ ++/** ++ This function implements Algorithm 14 of the ++ NIST FIPS 203 specification; this is the Kyber CPA-PKE decryption algorithm. ++ ++ Algorithm 14 is reproduced below: ++ ++ ```plaintext ++ Input: decryption key dkₚₖₑ ∈ 𝔹^{384k}. ++ Input: ciphertext c ∈ 𝔹^{32(dᵤk + dᵥ)}. ++ Output: message m ∈ 𝔹^{32}. ++ ++ c₁ ← c[0 : 32dᵤk] ++ c₂ ← c[32dᵤk : 32(dᵤk + dᵥ)] ++ u ← Decompress_{dᵤ}(ByteDecode_{dᵤ}(c₁)) ++ v ← Decompress_{dᵥ}(ByteDecode_{dᵥ}(c₂)) ++ ŝ ← ByteDecode₁₂(dkₚₖₑ) ++ w ← v - NTT-¹(ŝᵀ ◦ NTT(u)) ++ m ← ByteEncode₁(Compress₁(w)) ++ return m ++ ``` ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.decrypt_unpacked ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++- CIPHERTEXT_SIZE= 1088 ++- VECTOR_U_ENCODED_SIZE= 960 ++- U_COMPRESSION_FACTOR= 10 ++- V_COMPRESSION_FACTOR= 4 ++*/ ++static void ++decrypt_unpacked_6b(IndCpaPrivateKeyUnpacked_f8 *secret_key, ++ uint8_t *ciphertext, uint8_t ret[32U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 u_as_ntt[3U]; ++ deserialize_then_decompress_u_1a(ciphertext, u_as_ntt); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 v = ++ deserialize_then_decompress_ring_element_v_93( ++ Eurydice_array_to_subslice_from((size_t)1088U, ciphertext, ++ (size_t)960U, uint8_t, size_t)); ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 message = ++ compute_message_c9(&v, secret_key->secret_as_ntt, u_as_ntt); ++ uint8_t ret0[32U]; ++ compress_then_serialize_message_d4(message, ret0); ++ memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cpa.decrypt ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector ++with const generics ++- K= 3 ++- CIPHERTEXT_SIZE= 1088 ++- VECTOR_U_ENCODED_SIZE= 960 ++- U_COMPRESSION_FACTOR= 10 ++- V_COMPRESSION_FACTOR= 4 ++*/ ++static void ++decrypt_12(Eurydice_slice secret_key, uint8_t *ciphertext, ++ uint8_t ret[32U]) ++{ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[3U]; ++ deserialize_secret_key_7b(secret_key, secret_as_ntt); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 copy_of_secret_as_ntt[3U]; ++ memcpy( ++ copy_of_secret_as_ntt, secret_as_ntt, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ IndCpaPrivateKeyUnpacked_f8 secret_key_unpacked; ++ memcpy( ++ secret_key_unpacked.secret_as_ntt, copy_of_secret_as_ntt, ++ (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); ++ uint8_t ret0[32U]; ++ decrypt_unpacked_6b(&secret_key_unpacked, ciphertext, ret0); ++ memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_ml_kem::hash_functions::Hash for ++libcrux_ml_kem::hash_functions::portable::PortableHash)} ++*/ ++/** ++A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRF_f1 ++with const generics ++- K= 3 ++- LEN= 32 ++*/ ++static KRML_MUSTINLINE void ++PRF_f1_2e(Eurydice_slice input, uint8_t ret[32U]) ++{ ++ PRF_7c(input, ret); ++} ++ ++/** ++A monomorphic instance of libcrux_ml_kem.ind_cca.decapsulate ++with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, ++libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], ++libcrux_ml_kem_variant_MlKem with const generics ++- K= 3 ++- SECRET_KEY_SIZE= 2400 ++- CPA_SECRET_KEY_SIZE= 1152 ++- PUBLIC_KEY_SIZE= 1184 ++- CIPHERTEXT_SIZE= 1088 ++- T_AS_NTT_ENCODED_SIZE= 1152 ++- C1_SIZE= 960 ++- C2_SIZE= 128 ++- VECTOR_U_COMPRESSION_FACTOR= 10 ++- VECTOR_V_COMPRESSION_FACTOR= 4 ++- C1_BLOCK_SIZE= 320 ++- ETA1= 2 ++- ETA1_RANDOMNESS_SIZE= 128 ++- ETA2= 2 ++- ETA2_RANDOMNESS_SIZE= 128 ++- IMPLICIT_REJECTION_HASH_INPUT_SIZE= 1120 ++*/ ++void ++libcrux_ml_kem_ind_cca_decapsulate_1f( ++ libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, ++ libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) ++{ ++ Eurydice_slice_uint8_t_x2 uu____0 = Eurydice_slice_split_at( ++ Eurydice_array_to_slice((size_t)2400U, private_key->value, uint8_t), ++ (size_t)1152U, uint8_t, Eurydice_slice_uint8_t_x2); ++ Eurydice_slice ind_cpa_secret_key = uu____0.fst; ++ Eurydice_slice secret_key0 = uu____0.snd; ++ Eurydice_slice_uint8_t_x2 uu____1 = Eurydice_slice_split_at( ++ secret_key0, (size_t)1184U, uint8_t, Eurydice_slice_uint8_t_x2); ++ Eurydice_slice ind_cpa_public_key = uu____1.fst; ++ Eurydice_slice secret_key = uu____1.snd; ++ Eurydice_slice_uint8_t_x2 uu____2 = Eurydice_slice_split_at( ++ secret_key, LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t, ++ Eurydice_slice_uint8_t_x2); ++ Eurydice_slice ind_cpa_public_key_hash = uu____2.fst; ++ Eurydice_slice implicit_rejection_value = uu____2.snd; ++ uint8_t decrypted[32U]; ++ decrypt_12(ind_cpa_secret_key, ciphertext->value, decrypted); ++ uint8_t to_hash0[64U]; ++ libcrux_ml_kem_utils_into_padded_array_6d( ++ Eurydice_array_to_slice((size_t)32U, decrypted, uint8_t), to_hash0); ++ Eurydice_slice_copy( ++ Eurydice_array_to_subslice_from( ++ (size_t)64U, to_hash0, LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, ++ uint8_t, size_t), ++ ind_cpa_public_key_hash, uint8_t); ++ uint8_t hashed[64U]; ++ G_f1_38(Eurydice_array_to_slice((size_t)64U, to_hash0, uint8_t), hashed); ++ Eurydice_slice_uint8_t_x2 uu____3 = Eurydice_slice_split_at( ++ Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), ++ LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, ++ Eurydice_slice_uint8_t_x2); ++ Eurydice_slice shared_secret0 = uu____3.fst; ++ Eurydice_slice pseudorandomness = uu____3.snd; ++ uint8_t to_hash[1120U]; ++ libcrux_ml_kem_utils_into_padded_array_6d3(implicit_rejection_value, to_hash); ++ Eurydice_slice uu____4 = Eurydice_array_to_subslice_from( ++ (size_t)1120U, to_hash, LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, ++ uint8_t, size_t); ++ Eurydice_slice_copy(uu____4, libcrux_ml_kem_types_as_ref_00_d80(ciphertext), ++ uint8_t); ++ uint8_t implicit_rejection_shared_secret0[32U]; ++ PRF_f1_2e(Eurydice_array_to_slice((size_t)1120U, to_hash, uint8_t), ++ implicit_rejection_shared_secret0); ++ Eurydice_slice uu____5 = ind_cpa_public_key; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_decrypted[32U]; ++ memcpy(copy_of_decrypted, decrypted, (size_t)32U * sizeof(uint8_t)); ++ uint8_t expected_ciphertext[1088U]; ++ encrypt_7b(uu____5, copy_of_decrypted, pseudorandomness, expected_ciphertext); ++ uint8_t implicit_rejection_shared_secret[32U]; ++ kdf_d8_c5(Eurydice_array_to_slice((size_t)32U, ++ implicit_rejection_shared_secret0, uint8_t), ++ implicit_rejection_shared_secret); ++ uint8_t shared_secret[32U]; ++ kdf_d8_c5(shared_secret0, shared_secret); ++ uint8_t ret0[32U]; ++ libcrux_ml_kem_constant_time_ops_compare_ciphertexts_select_shared_secret_in_constant_time( ++ libcrux_ml_kem_types_as_ref_00_d80(ciphertext), ++ Eurydice_array_to_slice((size_t)1088U, expected_ciphertext, uint8_t), ++ Eurydice_array_to_slice((size_t)32U, shared_secret, uint8_t), ++ Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret, ++ uint8_t), ++ ret0); ++ memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); ++} +diff -up ./lib/freebl/verified/libcrux_mlkem_portable.h.mlkem ./lib/freebl/verified/libcrux_mlkem_portable.h +--- ./lib/freebl/verified/libcrux_mlkem_portable.h.mlkem 2024-10-31 14:54:15.465515959 -0700 ++++ ./lib/freebl/verified/libcrux_mlkem_portable.h 2024-10-31 14:54:15.465515959 -0700 +@@ -0,0 +1,643 @@ ++/* ++ * SPDX-FileCopyrightText: 2024 Cryspen Sarl ++ * ++ * SPDX-License-Identifier: MIT or Apache-2.0 ++ * ++ * This code was generated with the following revisions: ++ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d ++ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46 ++ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0 ++ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7 ++ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb ++ */ ++ ++#ifndef __libcrux_mlkem_portable_H ++#define __libcrux_mlkem_portable_H ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++#include "eurydice_glue.h" ++#include "libcrux_core.h" ++#include "libcrux_sha3.h" ++#include "libcrux_sha3_internal.h" ++ ++void libcrux_ml_kem_hash_functions_portable_G(Eurydice_slice input, ++ uint8_t ret[64U]); ++ ++void libcrux_ml_kem_hash_functions_portable_H(Eurydice_slice input, ++ uint8_t ret[32U]); ++ ++#define LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR ((size_t)16U) ++ ++#define LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS ((int16_t)3329) ++ ++#define LIBCRUX_ML_KEM_VECTOR_TRAITS_MONTGOMERY_R_SQUARED_MOD_FIELD_MODULUS \ ++ ((int16_t)1353) ++ ++#define LIBCRUX_ML_KEM_VECTOR_TRAITS_INVERSE_OF_MODULUS_MOD_MONTGOMERY_R \ ++ (62209U) ++ ++typedef struct libcrux_ml_kem_vector_portable_vector_type_PortableVector_s { ++ int16_t elements[16U]; ++} libcrux_ml_kem_vector_portable_vector_type_PortableVector; ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_vector_type_from_i16_array(Eurydice_slice array); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_from_i16_array_0d(Eurydice_slice array); ++ ++typedef struct uint8_t_x11_s { ++ uint8_t fst; ++ uint8_t snd; ++ uint8_t thd; ++ uint8_t f3; ++ uint8_t f4; ++ uint8_t f5; ++ uint8_t f6; ++ uint8_t f7; ++ uint8_t f8; ++ uint8_t f9; ++ uint8_t f10; ++} uint8_t_x11; ++ ++uint8_t_x11 libcrux_ml_kem_vector_portable_serialize_serialize_11_int( ++ Eurydice_slice v); ++ ++void libcrux_ml_kem_vector_portable_serialize_serialize_11( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, ++ uint8_t ret[22U]); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++void libcrux_ml_kem_vector_portable_serialize_11_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, ++ uint8_t ret[22U]); ++ ++typedef struct int16_t_x8_s { ++ int16_t fst; ++ int16_t snd; ++ int16_t thd; ++ int16_t f3; ++ int16_t f4; ++ int16_t f5; ++ int16_t f6; ++ int16_t f7; ++} int16_t_x8; ++ ++int16_t_x8 libcrux_ml_kem_vector_portable_serialize_deserialize_11_int( ++ Eurydice_slice bytes); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_vector_type_zero(void); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_serialize_deserialize_11(Eurydice_slice bytes); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_deserialize_11_0d(Eurydice_slice a); ++ ++void libcrux_ml_kem_vector_portable_vector_type_to_i16_array( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector x, ++ int16_t ret[16U]); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++void libcrux_ml_kem_vector_portable_to_i16_array_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector x, ++ int16_t ret[16U]); ++ ++extern const uint8_t ++ libcrux_ml_kem_vector_rej_sample_table_REJECTION_SAMPLE_SHUFFLE_TABLE[256U] ++ [16U]; ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ZERO_0d(void); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_arithmetic_add( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_add_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_arithmetic_sub( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_sub_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_arithmetic_multiply_by_constant( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_multiply_by_constant_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_arithmetic_bitwise_and_with_constant( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_bitwise_and_with_constant_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_arithmetic_cond_subtract_3329( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_cond_subtract_3329_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v); ++ ++#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_MULTIPLIER \ ++ ((int32_t)20159) ++ ++#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_SHIFT ((int32_t)26) ++ ++#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_R \ ++ ((int32_t)1 << (uint32_t) \ ++ LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_SHIFT) ++ ++/** ++ Signed Barrett Reduction ++ ++ Given an input `value`, `barrett_reduce` outputs a representative `result` ++ such that: ++ ++ - result ≡ value (mod FIELD_MODULUS) ++ - the absolute value of `result` is bound as follows: ++ ++ `|result| ≤ FIELD_MODULUS / 2 · (|value|/BARRETT_R + 1) ++ ++ In particular, if `|value| < BARRETT_R`, then `|result| < FIELD_MODULUS`. ++*/ ++int16_t libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( ++ int16_t value); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_barrett_reduce_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v); ++ ++#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT (16U) ++ ++#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_R \ ++ ((int32_t)1 << (uint32_t) \ ++ LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT) ++ ++/** ++ Signed Montgomery Reduction ++ ++ Given an input `value`, `montgomery_reduce` outputs a representative `o` ++ such that: ++ ++ - o ≡ value · MONTGOMERY_R^(-1) (mod FIELD_MODULUS) ++ - the absolute value of `o` is bound as follows: ++ ++ `|result| ≤ (|value| / MONTGOMERY_R) + (FIELD_MODULUS / 2) ++ ++ In particular, if `|value| ≤ FIELD_MODULUS * MONTGOMERY_R`, then `|o| < (3 · ++ FIELD_MODULUS) / 2`. ++*/ ++int16_t libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( ++ int32_t value); ++ ++/** ++ If `fe` is some field element 'x' of the Kyber field and `fer` is congruent to ++ `y · MONTGOMERY_R`, this procedure outputs a value that is congruent to ++ `x · y`, as follows: ++ ++ `fe · fer ≡ x · y · MONTGOMERY_R (mod FIELD_MODULUS)` ++ ++ `montgomery_reduce` takes the value `x · y · MONTGOMERY_R` and outputs a ++ representative `x · y · MONTGOMERY_R * MONTGOMERY_R^{-1} ≡ x · y (mod ++ FIELD_MODULUS)`. ++*/ ++int16_t libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( ++ int16_t fe, int16_t fer); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_by_constant( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_montgomery_multiply_by_constant_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t r); ++ ++/** ++ The `compress_*` functions implement the `Compress` function specified in the ++ NIST FIPS 203 standard (Page 18, Expression 4.5), which is defined as: ++ ++ ```plaintext ++ Compress_d: ℤq -> ℤ_{2ᵈ} ++ Compress_d(x) = ⌈(2ᵈ/q)·x⌋ ++ ``` ++ ++ Since `⌈x⌋ = ⌊x + 1/2⌋` we have: ++ ++ ```plaintext ++ Compress_d(x) = ⌊(2ᵈ/q)·x + 1/2⌋ ++ = ⌊(2^{d+1}·x + q) / 2q⌋ ++ ``` ++ ++ For further information about the function implementations, consult the ++ `implementation_notes.pdf` document in this directory. ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++uint8_t libcrux_ml_kem_vector_portable_compress_compress_message_coefficient( ++ uint16_t fe); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_compress_compress_1( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_compress_1_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v); ++ ++uint32_t libcrux_ml_kem_vector_portable_arithmetic_get_n_least_significant_bits( ++ uint8_t n, uint32_t value); ++ ++int16_t libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( ++ uint8_t coefficient_bits, uint16_t fe); ++ ++void libcrux_ml_kem_vector_portable_ntt_ntt_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *v, int16_t zeta, ++ size_t i, size_t j); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_ntt_layer_1_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, ++ int16_t zeta1, int16_t zeta2, int16_t zeta3); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_layer_1_step_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, ++ int16_t zeta1, int16_t zeta2, int16_t zeta3); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_ntt_layer_2_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, ++ int16_t zeta1); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_layer_2_step_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, ++ int16_t zeta1); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_ntt_layer_3_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_layer_3_step_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta); ++ ++void libcrux_ml_kem_vector_portable_ntt_inv_ntt_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *v, int16_t zeta, ++ size_t i, size_t j); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_1_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, ++ int16_t zeta1, int16_t zeta2, int16_t zeta3); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_inv_ntt_layer_1_step_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, ++ int16_t zeta1, int16_t zeta2, int16_t zeta3); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_2_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, ++ int16_t zeta1); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_inv_ntt_layer_2_step_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, ++ int16_t zeta1); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_3_step( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_inv_ntt_layer_3_step_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta); ++ ++/** ++ Compute the product of two Kyber binomials with respect to the ++ modulus `X² - zeta`. ++ ++ This function almost implements Algorithm 11 of the ++ NIST FIPS 203 standard, which is reproduced below: ++ ++ ```plaintext ++ Input: a₀, a₁, b₀, b₁ ∈ ℤq. ++ Input: γ ∈ ℤq. ++ Output: c₀, c₁ ∈ ℤq. ++ ++ c₀ ← a₀·b₀ + a₁·b₁·γ ++ c₁ ← a₀·b₁ + a₁·b₀ ++ return c₀, c₁ ++ ``` ++ We say "almost" because the coefficients output by this function are in ++ the Montgomery domain (unlike in the specification). ++ ++ The NIST FIPS 203 standard can be found at ++ . ++*/ ++void libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *a, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *b, int16_t zeta, ++ size_t i, size_t j, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *out); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_ntt_multiply( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *lhs, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs, ++ int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_ntt_multiply_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *lhs, ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs, ++ int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3); ++ ++void libcrux_ml_kem_vector_portable_serialize_serialize_1( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, ++ uint8_t ret[2U]); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++void libcrux_ml_kem_vector_portable_serialize_1_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, ++ uint8_t ret[2U]); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_serialize_deserialize_1(Eurydice_slice v); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_deserialize_1_0d(Eurydice_slice a); ++ ++typedef struct uint8_t_x4_s { ++ uint8_t fst; ++ uint8_t snd; ++ uint8_t thd; ++ uint8_t f3; ++} uint8_t_x4; ++ ++uint8_t_x4 libcrux_ml_kem_vector_portable_serialize_serialize_4_int( ++ Eurydice_slice v); ++ ++void libcrux_ml_kem_vector_portable_serialize_serialize_4( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, ++ uint8_t ret[8U]); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++void libcrux_ml_kem_vector_portable_serialize_4_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, ++ uint8_t ret[8U]); ++ ++int16_t_x8 libcrux_ml_kem_vector_portable_serialize_deserialize_4_int( ++ Eurydice_slice bytes); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_serialize_deserialize_4(Eurydice_slice bytes); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_deserialize_4_0d(Eurydice_slice a); ++ ++typedef struct uint8_t_x5_s { ++ uint8_t fst; ++ uint8_t snd; ++ uint8_t thd; ++ uint8_t f3; ++ uint8_t f4; ++} uint8_t_x5; ++ ++uint8_t_x5 libcrux_ml_kem_vector_portable_serialize_serialize_5_int( ++ Eurydice_slice v); ++ ++void libcrux_ml_kem_vector_portable_serialize_serialize_5( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, ++ uint8_t ret[10U]); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++void libcrux_ml_kem_vector_portable_serialize_5_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, ++ uint8_t ret[10U]); ++ ++int16_t_x8 libcrux_ml_kem_vector_portable_serialize_deserialize_5_int( ++ Eurydice_slice bytes); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_serialize_deserialize_5(Eurydice_slice bytes); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_deserialize_5_0d(Eurydice_slice a); ++ ++uint8_t_x5 libcrux_ml_kem_vector_portable_serialize_serialize_10_int( ++ Eurydice_slice v); ++ ++void libcrux_ml_kem_vector_portable_serialize_serialize_10( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, ++ uint8_t ret[20U]); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++void libcrux_ml_kem_vector_portable_serialize_10_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, ++ uint8_t ret[20U]); ++ ++int16_t_x8 libcrux_ml_kem_vector_portable_serialize_deserialize_10_int( ++ Eurydice_slice bytes); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_serialize_deserialize_10(Eurydice_slice bytes); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_deserialize_10_0d(Eurydice_slice a); ++ ++typedef struct uint8_t_x3_s { ++ uint8_t fst; ++ uint8_t snd; ++ uint8_t thd; ++} uint8_t_x3; ++ ++uint8_t_x3 libcrux_ml_kem_vector_portable_serialize_serialize_12_int( ++ Eurydice_slice v); ++ ++void libcrux_ml_kem_vector_portable_serialize_serialize_12( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector v, ++ uint8_t ret[24U]); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++void libcrux_ml_kem_vector_portable_serialize_12_0d( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector a, ++ uint8_t ret[24U]); ++ ++typedef struct int16_t_x2_s { ++ int16_t fst; ++ int16_t snd; ++} int16_t_x2; ++ ++int16_t_x2 libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( ++ Eurydice_slice bytes); ++ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_serialize_deserialize_12(Eurydice_slice bytes); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_deserialize_12_0d(Eurydice_slice a); ++ ++size_t libcrux_ml_kem_vector_portable_sampling_rej_sample( ++ Eurydice_slice a, Eurydice_slice result); ++ ++/** ++This function found in impl {(libcrux_ml_kem::vector::traits::Operations for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++size_t libcrux_ml_kem_vector_portable_rej_sample_0d(Eurydice_slice a, ++ Eurydice_slice out); ++ ++/** ++This function found in impl {(core::clone::Clone for ++libcrux_ml_kem::vector::portable::vector_type::PortableVector)} ++*/ ++libcrux_ml_kem_vector_portable_vector_type_PortableVector ++libcrux_ml_kem_vector_portable_vector_type_clone_3b( ++ libcrux_ml_kem_vector_portable_vector_type_PortableVector *self); ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#define __libcrux_mlkem_portable_H_DEFINED ++#endif +diff -up ./lib/freebl/verified/libcrux_sha3.h.mlkem ./lib/freebl/verified/libcrux_sha3.h +--- ./lib/freebl/verified/libcrux_sha3.h.mlkem 2024-10-31 14:54:15.465515959 -0700 ++++ ./lib/freebl/verified/libcrux_sha3.h 2024-10-31 14:54:15.465515959 -0700 +@@ -0,0 +1,221 @@ ++/* ++ * SPDX-FileCopyrightText: 2024 Cryspen Sarl ++ * ++ * SPDX-License-Identifier: MIT or Apache-2.0 ++ * ++ * This code was generated with the following revisions: ++ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d ++ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46 ++ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0 ++ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7 ++ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb ++ */ ++ ++#ifndef __libcrux_sha3_H ++#define __libcrux_sha3_H ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++#include "eurydice_glue.h" ++#include "libcrux_core.h" ++#include "libcrux_sha3_internal.h" ++ ++/** ++ A portable SHA3 512 implementation. ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_sha512(Eurydice_slice digest, ++ Eurydice_slice data) ++{ ++ Eurydice_slice buf0[1U] = { data }; ++ Eurydice_slice buf[1U] = { digest }; ++ libcrux_sha3_portable_keccakx1_e4(buf0, buf); ++} ++ ++/** ++ A portable SHA3 256 implementation. ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_sha256(Eurydice_slice digest, ++ Eurydice_slice data) ++{ ++ Eurydice_slice buf0[1U] = { data }; ++ Eurydice_slice buf[1U] = { digest }; ++ libcrux_sha3_portable_keccakx1_e40(buf0, buf); ++} ++ ++/** ++ A portable SHAKE256 implementation. ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_shake256( ++ Eurydice_slice digest, Eurydice_slice data) ++{ ++ Eurydice_slice buf0[1U] = { data }; ++ Eurydice_slice buf[1U] = { digest }; ++ libcrux_sha3_portable_keccakx1_e41(buf0, buf); ++} ++ ++/** ++ A portable SHA3 224 implementation. ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_sha224(Eurydice_slice digest, ++ Eurydice_slice data) ++{ ++ Eurydice_slice buf0[1U] = { data }; ++ Eurydice_slice buf[1U] = { digest }; ++ libcrux_sha3_portable_keccakx1_e42(buf0, buf); ++} ++ ++/** ++ A portable SHA3 384 implementation. ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_sha384(Eurydice_slice digest, ++ Eurydice_slice data) ++{ ++ Eurydice_slice buf0[1U] = { data }; ++ Eurydice_slice buf[1U] = { digest }; ++ libcrux_sha3_portable_keccakx1_e43(buf0, buf); ++} ++ ++/** ++ SHA3 224 ++ ++ Preconditions: ++ - `digest.len() == 28` ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_sha224_ema(Eurydice_slice digest, ++ Eurydice_slice payload) ++{ ++ libcrux_sha3_portable_sha224(digest, payload); ++} ++ ++/** ++ SHA3 224 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_sha224(Eurydice_slice data, ++ uint8_t ret[28U]) ++{ ++ uint8_t out[28U] = { 0U }; ++ libcrux_sha3_sha224_ema(Eurydice_array_to_slice((size_t)28U, out, uint8_t), ++ data); ++ memcpy(ret, out, (size_t)28U * sizeof(uint8_t)); ++} ++ ++/** ++ SHA3 256 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_sha256_ema(Eurydice_slice digest, ++ Eurydice_slice payload) ++{ ++ libcrux_sha3_portable_sha256(digest, payload); ++} ++ ++/** ++ SHA3 256 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_sha256(Eurydice_slice data, ++ uint8_t ret[32U]) ++{ ++ uint8_t out[32U] = { 0U }; ++ libcrux_sha3_sha256_ema(Eurydice_array_to_slice((size_t)32U, out, uint8_t), ++ data); ++ memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); ++} ++ ++/** ++ SHA3 384 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_sha384_ema(Eurydice_slice digest, ++ Eurydice_slice payload) ++{ ++ libcrux_sha3_portable_sha384(digest, payload); ++} ++ ++/** ++ SHA3 384 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_sha384(Eurydice_slice data, ++ uint8_t ret[48U]) ++{ ++ uint8_t out[48U] = { 0U }; ++ libcrux_sha3_sha384_ema(Eurydice_array_to_slice((size_t)48U, out, uint8_t), ++ data); ++ memcpy(ret, out, (size_t)48U * sizeof(uint8_t)); ++} ++ ++/** ++ SHA3 512 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_sha512_ema(Eurydice_slice digest, ++ Eurydice_slice payload) ++{ ++ libcrux_sha3_portable_sha512(digest, payload); ++} ++ ++/** ++ SHA3 512 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_sha512(Eurydice_slice data, ++ uint8_t ret[64U]) ++{ ++ uint8_t out[64U] = { 0U }; ++ libcrux_sha3_sha512_ema(Eurydice_array_to_slice((size_t)64U, out, uint8_t), ++ data); ++ memcpy(ret, out, (size_t)64U * sizeof(uint8_t)); ++} ++ ++/** ++ A portable SHAKE128 implementation. ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_shake128( ++ Eurydice_slice digest, Eurydice_slice data) ++{ ++ Eurydice_slice buf0[1U] = { data }; ++ Eurydice_slice buf[1U] = { digest }; ++ libcrux_sha3_portable_keccakx1_e44(buf0, buf); ++} ++ ++/** ++ SHAKE 128 ++ ++ Writes `out.len()` bytes. ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_shake128_ema(Eurydice_slice out, ++ Eurydice_slice data) ++{ ++ libcrux_sha3_portable_shake128(out, data); ++} ++ ++/** ++ SHAKE 256 ++ ++ Writes `out.len()` bytes. ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_shake256_ema(Eurydice_slice out, ++ Eurydice_slice data) ++{ ++ libcrux_sha3_portable_shake256(out, data); ++} ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#define __libcrux_sha3_H_DEFINED ++#endif +diff -up ./lib/freebl/verified/libcrux_sha3_internal.h.mlkem ./lib/freebl/verified/libcrux_sha3_internal.h +--- ./lib/freebl/verified/libcrux_sha3_internal.h.mlkem 2024-10-31 14:54:15.466515970 -0700 ++++ ./lib/freebl/verified/libcrux_sha3_internal.h 2024-10-31 14:54:15.466515970 -0700 +@@ -0,0 +1,3449 @@ ++/* ++ * SPDX-FileCopyrightText: 2024 Cryspen Sarl ++ * ++ * SPDX-License-Identifier: MIT or Apache-2.0 ++ * ++ * This code was generated with the following revisions: ++ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d ++ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46 ++ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0 ++ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7 ++ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb ++ */ ++ ++#ifndef __libcrux_sha3_internal_H ++#define __libcrux_sha3_internal_H ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++#include "eurydice_glue.h" ++#include "libcrux_core.h" ++ ++static const uint64_t libcrux_sha3_generic_keccak_ROUNDCONSTANTS[24U] = { ++ 1ULL, ++ 32898ULL, ++ 9223372036854808714ULL, ++ 9223372039002292224ULL, ++ 32907ULL, ++ 2147483649ULL, ++ 9223372039002292353ULL, ++ 9223372036854808585ULL, ++ 138ULL, ++ 136ULL, ++ 2147516425ULL, ++ 2147483658ULL, ++ 2147516555ULL, ++ 9223372036854775947ULL, ++ 9223372036854808713ULL, ++ 9223372036854808579ULL, ++ 9223372036854808578ULL, ++ 9223372036854775936ULL, ++ 32778ULL, ++ 9223372039002259466ULL, ++ 9223372039002292353ULL, ++ 9223372036854808704ULL, ++ 2147483649ULL, ++ 9223372039002292232ULL ++}; ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_zero_5a(void) ++{ ++ return 0ULL; ++} ++ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__veor5q_u64( ++ uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e) ++{ ++ uint64_t ab = a ^ b; ++ uint64_t cd = c ^ d; ++ uint64_t abcd = ab ^ cd; ++ return abcd ^ e; ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor5_5a( ++ uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e) ++{ ++ return libcrux_sha3_portable_keccak__veor5q_u64(a, b, c, d, e); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 1 ++- RIGHT= 63 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d6(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)1 | x >> (uint32_t)(int32_t)63; ++} ++ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vrax1q_u64(uint64_t a, uint64_t b) ++{ ++ uint64_t uu____0 = a; ++ return uu____0 ^ libcrux_sha3_portable_keccak_rotate_left_d6(b); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left1_and_xor_5a(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vrax1q_u64(a, b); ++} ++ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vbcaxq_u64(uint64_t a, uint64_t b, uint64_t c) ++{ ++ return a ^ (b & ~c); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_and_not_xor_5a( ++ uint64_t a, uint64_t b, uint64_t c) ++{ ++ return libcrux_sha3_portable_keccak__vbcaxq_u64(a, b, c); ++} ++ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__veorq_n_u64(uint64_t a, uint64_t c) ++{ ++ return a ^ c; ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_constant_5a(uint64_t a, uint64_t c) ++{ ++ return libcrux_sha3_portable_keccak__veorq_n_u64(a, c); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_5a(uint64_t a, uint64_t b) ++{ ++ return a ^ b; ++} ++ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_slice_1( ++ Eurydice_slice a[1U], size_t start, size_t len, Eurydice_slice ret[1U]) ++{ ++ ret[0U] = Eurydice_slice_subslice2(a[0U], start, start + len, uint8_t); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_slice_n_5a( ++ Eurydice_slice a[1U], size_t start, size_t len, Eurydice_slice ret[1U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_a[1U]; ++ memcpy(copy_of_a, a, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret0[1U]; ++ libcrux_sha3_portable_keccak_slice_1(copy_of_a, start, len, ret0); ++ memcpy(ret, ret0, (size_t)1U * sizeof(Eurydice_slice)); ++} ++ ++static KRML_MUSTINLINE Eurydice_slice_uint8_t_1size_t__x2 ++libcrux_sha3_portable_keccak_split_at_mut_1(Eurydice_slice out[1U], ++ size_t mid) ++{ ++ Eurydice_slice_uint8_t_x2 uu____0 = Eurydice_slice_split_at_mut( ++ out[0U], mid, uint8_t, Eurydice_slice_uint8_t_x2); ++ Eurydice_slice out00 = uu____0.fst; ++ Eurydice_slice out01 = uu____0.snd; ++ Eurydice_slice_uint8_t_1size_t__x2 lit; ++ lit.fst[0U] = out00; ++ lit.snd[0U] = out01; ++ return lit; ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++static KRML_MUSTINLINE Eurydice_slice_uint8_t_1size_t__x2 ++libcrux_sha3_portable_keccak_split_at_mut_n_5a(Eurydice_slice a[1U], ++ size_t mid) ++{ ++ return libcrux_sha3_portable_keccak_split_at_mut_1(a, mid); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.KeccakState ++with types uint64_t ++with const generics ++- $1size_t ++*/ ++typedef struct libcrux_sha3_generic_keccak_KeccakState_48_s { ++ uint64_t st[5U][5U]; ++} libcrux_sha3_generic_keccak_KeccakState_48; ++ ++/** ++ Create a new Shake128 x4 state. ++*/ ++/** ++This function found in impl {libcrux_sha3::generic_keccak::KeccakState[TraitClause@0]#1} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.new_1e ++with types uint64_t ++with const generics ++- N= 1 ++*/ ++static KRML_MUSTINLINE libcrux_sha3_generic_keccak_KeccakState_48 ++libcrux_sha3_generic_keccak_new_1e_cf(void) ++{ ++ libcrux_sha3_generic_keccak_KeccakState_48 lit; ++ lit.st[0U][0U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[0U][1U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[0U][2U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[0U][3U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[0U][4U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[1U][0U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[1U][1U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[1U][2U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[1U][3U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[1U][4U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[2U][0U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[2U][1U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[2U][2U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[2U][3U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[2U][4U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[3U][0U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[3U][1U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[3U][2U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[3U][3U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[3U][4U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[4U][0U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[4U][1U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[4U][2U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[4U][3U] = libcrux_sha3_portable_keccak_zero_5a(); ++ lit.st[4U][4U] = libcrux_sha3_portable_keccak_zero_5a(); ++ return lit; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block ++with const generics ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_65( ++ uint64_t (*s)[5U], Eurydice_slice blocks[1U]) ++{ ++ for (size_t i = (size_t)0U; i < (size_t)168U / (size_t)8U; i++) { ++ size_t i0 = i; ++ uint8_t uu____0[8U]; ++ core_result_Result_56 dst; ++ Eurydice_slice_to_array2( ++ &dst, ++ Eurydice_slice_subslice2(blocks[0U], (size_t)8U * i0, ++ (size_t)8U * i0 + (size_t)8U, uint8_t), ++ Eurydice_slice, uint8_t[8U]); ++ core_result_unwrap_41_0e(dst, uu____0); ++ size_t uu____1 = i0 / (size_t)5U; ++ size_t uu____2 = i0 % (size_t)5U; ++ s[uu____1][uu____2] = ++ s[uu____1][uu____2] ^ core_num__u64_9__from_le_bytes(uu____0); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full ++with const generics ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_full_d4( ++ uint64_t (*s)[5U], uint8_t blocks[1U][200U]) ++{ ++ Eurydice_slice buf[1U] = { ++ Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t) ++ }; ++ libcrux_sha3_portable_keccak_load_block_65(s, buf); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full_5a ++with const generics ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_full_5a_05( ++ uint64_t (*a)[5U], uint8_t b[1U][200U]) ++{ ++ uint64_t(*uu____0)[5U] = a; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_b[1U][200U]; ++ memcpy(copy_of_b, b, (size_t)1U * sizeof(uint8_t[200U])); ++ libcrux_sha3_portable_keccak_load_block_full_d4(uu____0, copy_of_b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 36 ++- RIGHT= 28 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d60(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)36 | x >> (uint32_t)(int32_t)28; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 36 ++- RIGHT= 28 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_74(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d60(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 36 ++- RIGHT= 28 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_03(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_74(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 3 ++- RIGHT= 61 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d61(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)3 | x >> (uint32_t)(int32_t)61; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 3 ++- RIGHT= 61 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_740(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d61(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 3 ++- RIGHT= 61 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_030(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_740(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 41 ++- RIGHT= 23 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d62(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)41 | x >> (uint32_t)(int32_t)23; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 41 ++- RIGHT= 23 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_741(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d62(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 41 ++- RIGHT= 23 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_031(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_741(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 18 ++- RIGHT= 46 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d63(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)18 | x >> (uint32_t)(int32_t)46; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 18 ++- RIGHT= 46 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_742(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d63(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 18 ++- RIGHT= 46 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_032(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_742(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 1 ++- RIGHT= 63 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_743(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d6(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 1 ++- RIGHT= 63 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_033(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_743(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 44 ++- RIGHT= 20 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d64(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)44 | x >> (uint32_t)(int32_t)20; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 44 ++- RIGHT= 20 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_744(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d64(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 44 ++- RIGHT= 20 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_034(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_744(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 10 ++- RIGHT= 54 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d65(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)10 | x >> (uint32_t)(int32_t)54; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 10 ++- RIGHT= 54 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_745(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d65(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 10 ++- RIGHT= 54 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_035(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_745(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 45 ++- RIGHT= 19 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d66(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)45 | x >> (uint32_t)(int32_t)19; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 45 ++- RIGHT= 19 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_746(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d66(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 45 ++- RIGHT= 19 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_036(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_746(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 2 ++- RIGHT= 62 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d67(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)2 | x >> (uint32_t)(int32_t)62; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 2 ++- RIGHT= 62 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_747(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d67(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 2 ++- RIGHT= 62 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_037(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_747(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 62 ++- RIGHT= 2 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d68(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)62 | x >> (uint32_t)(int32_t)2; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 62 ++- RIGHT= 2 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_748(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d68(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 62 ++- RIGHT= 2 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_038(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_748(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 6 ++- RIGHT= 58 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d69(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)6 | x >> (uint32_t)(int32_t)58; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 6 ++- RIGHT= 58 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_749(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d69(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 6 ++- RIGHT= 58 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_039(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_749(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 43 ++- RIGHT= 21 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d610(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)43 | x >> (uint32_t)(int32_t)21; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 43 ++- RIGHT= 21 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_7410(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d610(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 43 ++- RIGHT= 21 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_0310(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_7410(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 15 ++- RIGHT= 49 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d611(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)15 | x >> (uint32_t)(int32_t)49; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 15 ++- RIGHT= 49 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_7411(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d611(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 15 ++- RIGHT= 49 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_0311(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_7411(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 61 ++- RIGHT= 3 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d612(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)61 | x >> (uint32_t)(int32_t)3; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 61 ++- RIGHT= 3 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_7412(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d612(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 61 ++- RIGHT= 3 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_0312(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_7412(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 28 ++- RIGHT= 36 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d613(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)28 | x >> (uint32_t)(int32_t)36; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 28 ++- RIGHT= 36 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_7413(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d613(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 28 ++- RIGHT= 36 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_0313(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_7413(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 55 ++- RIGHT= 9 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d614(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)55 | x >> (uint32_t)(int32_t)9; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 55 ++- RIGHT= 9 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_7414(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d614(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 55 ++- RIGHT= 9 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_0314(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_7414(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 25 ++- RIGHT= 39 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d615(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)25 | x >> (uint32_t)(int32_t)39; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 25 ++- RIGHT= 39 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_7415(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d615(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 25 ++- RIGHT= 39 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_0315(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_7415(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 21 ++- RIGHT= 43 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d616(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)21 | x >> (uint32_t)(int32_t)43; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 21 ++- RIGHT= 43 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_7416(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d616(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 21 ++- RIGHT= 43 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_0316(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_7416(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 56 ++- RIGHT= 8 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d617(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)56 | x >> (uint32_t)(int32_t)8; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 56 ++- RIGHT= 8 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_7417(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d617(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 56 ++- RIGHT= 8 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_0317(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_7417(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 27 ++- RIGHT= 37 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d618(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)27 | x >> (uint32_t)(int32_t)37; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 27 ++- RIGHT= 37 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_7418(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d618(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 27 ++- RIGHT= 37 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_0318(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_7418(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 20 ++- RIGHT= 44 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d619(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)20 | x >> (uint32_t)(int32_t)44; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 20 ++- RIGHT= 44 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_7419(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d619(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 20 ++- RIGHT= 44 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_0319(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_7419(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 39 ++- RIGHT= 25 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d620(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)39 | x >> (uint32_t)(int32_t)25; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 39 ++- RIGHT= 25 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_7420(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d620(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 39 ++- RIGHT= 25 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_0320(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_7420(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 8 ++- RIGHT= 56 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d621(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)8 | x >> (uint32_t)(int32_t)56; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 8 ++- RIGHT= 56 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_7421(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d621(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 8 ++- RIGHT= 56 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_0321(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_7421(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left ++with const generics ++- LEFT= 14 ++- RIGHT= 50 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_rotate_left_d622(uint64_t x) ++{ ++ return x << (uint32_t)(int32_t)14 | x >> (uint32_t)(int32_t)50; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 ++with const generics ++- LEFT= 14 ++- RIGHT= 50 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak__vxarq_u64_7422(uint64_t a, uint64_t b) ++{ ++ uint64_t ab = a ^ b; ++ return libcrux_sha3_portable_keccak_rotate_left_d622(ab); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a ++with const generics ++- LEFT= 14 ++- RIGHT= 50 ++*/ ++static KRML_MUSTINLINE uint64_t ++libcrux_sha3_portable_keccak_xor_and_rotate_5a_0322(uint64_t a, uint64_t b) ++{ ++ return libcrux_sha3_portable_keccak__vxarq_u64_7422(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.theta_rho ++with types uint64_t ++with const generics ++- N= 1 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_theta_rho_a7( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s) ++{ ++ uint64_t c[5U] = { ++ libcrux_sha3_portable_keccak_xor5_5a(s->st[0U][0U], s->st[1U][0U], ++ s->st[2U][0U], s->st[3U][0U], ++ s->st[4U][0U]), ++ libcrux_sha3_portable_keccak_xor5_5a(s->st[0U][1U], s->st[1U][1U], ++ s->st[2U][1U], s->st[3U][1U], ++ s->st[4U][1U]), ++ libcrux_sha3_portable_keccak_xor5_5a(s->st[0U][2U], s->st[1U][2U], ++ s->st[2U][2U], s->st[3U][2U], ++ s->st[4U][2U]), ++ libcrux_sha3_portable_keccak_xor5_5a(s->st[0U][3U], s->st[1U][3U], ++ s->st[2U][3U], s->st[3U][3U], ++ s->st[4U][3U]), ++ libcrux_sha3_portable_keccak_xor5_5a(s->st[0U][4U], s->st[1U][4U], ++ s->st[2U][4U], s->st[3U][4U], ++ s->st[4U][4U]) ++ }; ++ uint64_t uu____0 = libcrux_sha3_portable_keccak_rotate_left1_and_xor_5a( ++ c[((size_t)0U + (size_t)4U) % (size_t)5U], ++ c[((size_t)0U + (size_t)1U) % (size_t)5U]); ++ uint64_t uu____1 = libcrux_sha3_portable_keccak_rotate_left1_and_xor_5a( ++ c[((size_t)1U + (size_t)4U) % (size_t)5U], ++ c[((size_t)1U + (size_t)1U) % (size_t)5U]); ++ uint64_t uu____2 = libcrux_sha3_portable_keccak_rotate_left1_and_xor_5a( ++ c[((size_t)2U + (size_t)4U) % (size_t)5U], ++ c[((size_t)2U + (size_t)1U) % (size_t)5U]); ++ uint64_t uu____3 = libcrux_sha3_portable_keccak_rotate_left1_and_xor_5a( ++ c[((size_t)3U + (size_t)4U) % (size_t)5U], ++ c[((size_t)3U + (size_t)1U) % (size_t)5U]); ++ uint64_t t[5U] = { uu____0, uu____1, uu____2, uu____3, ++ libcrux_sha3_portable_keccak_rotate_left1_and_xor_5a( ++ c[((size_t)4U + (size_t)4U) % (size_t)5U], ++ c[((size_t)4U + (size_t)1U) % (size_t)5U]) }; ++ s->st[0U][0U] = libcrux_sha3_portable_keccak_xor_5a(s->st[0U][0U], t[0U]); ++ s->st[1U][0U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_03(s->st[1U][0U], t[0U]); ++ s->st[2U][0U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_030(s->st[2U][0U], t[0U]); ++ s->st[3U][0U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_031(s->st[3U][0U], t[0U]); ++ s->st[4U][0U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_032(s->st[4U][0U], t[0U]); ++ s->st[0U][1U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_033(s->st[0U][1U], t[1U]); ++ s->st[1U][1U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_034(s->st[1U][1U], t[1U]); ++ s->st[2U][1U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_035(s->st[2U][1U], t[1U]); ++ s->st[3U][1U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_036(s->st[3U][1U], t[1U]); ++ s->st[4U][1U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_037(s->st[4U][1U], t[1U]); ++ s->st[0U][2U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_038(s->st[0U][2U], t[2U]); ++ s->st[1U][2U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_039(s->st[1U][2U], t[2U]); ++ s->st[2U][2U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_0310(s->st[2U][2U], t[2U]); ++ s->st[3U][2U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_0311(s->st[3U][2U], t[2U]); ++ s->st[4U][2U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_0312(s->st[4U][2U], t[2U]); ++ s->st[0U][3U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_0313(s->st[0U][3U], t[3U]); ++ s->st[1U][3U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_0314(s->st[1U][3U], t[3U]); ++ s->st[2U][3U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_0315(s->st[2U][3U], t[3U]); ++ s->st[3U][3U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_0316(s->st[3U][3U], t[3U]); ++ s->st[4U][3U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_0317(s->st[4U][3U], t[3U]); ++ s->st[0U][4U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_0318(s->st[0U][4U], t[4U]); ++ s->st[1U][4U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_0319(s->st[1U][4U], t[4U]); ++ s->st[2U][4U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_0320(s->st[2U][4U], t[4U]); ++ s->st[3U][4U] = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_0321(s->st[3U][4U], t[4U]); ++ uint64_t uu____27 = ++ libcrux_sha3_portable_keccak_xor_and_rotate_5a_0322(s->st[4U][4U], t[4U]); ++ s->st[4U][4U] = uu____27; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.pi ++with types uint64_t ++with const generics ++- N= 1 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_pi_d5( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s) ++{ ++ uint64_t old[5U][5U]; ++ memcpy(old, s->st, (size_t)5U * sizeof(uint64_t[5U])); ++ s->st[0U][1U] = old[1U][1U]; ++ s->st[0U][2U] = old[2U][2U]; ++ s->st[0U][3U] = old[3U][3U]; ++ s->st[0U][4U] = old[4U][4U]; ++ s->st[1U][0U] = old[0U][3U]; ++ s->st[1U][1U] = old[1U][4U]; ++ s->st[1U][2U] = old[2U][0U]; ++ s->st[1U][3U] = old[3U][1U]; ++ s->st[1U][4U] = old[4U][2U]; ++ s->st[2U][0U] = old[0U][1U]; ++ s->st[2U][1U] = old[1U][2U]; ++ s->st[2U][2U] = old[2U][3U]; ++ s->st[2U][3U] = old[3U][4U]; ++ s->st[2U][4U] = old[4U][0U]; ++ s->st[3U][0U] = old[0U][4U]; ++ s->st[3U][1U] = old[1U][0U]; ++ s->st[3U][2U] = old[2U][1U]; ++ s->st[3U][3U] = old[3U][2U]; ++ s->st[3U][4U] = old[4U][3U]; ++ s->st[4U][0U] = old[0U][2U]; ++ s->st[4U][1U] = old[1U][3U]; ++ s->st[4U][2U] = old[2U][4U]; ++ s->st[4U][3U] = old[3U][0U]; ++ s->st[4U][4U] = old[4U][1U]; ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.chi ++with types uint64_t ++with const generics ++- N= 1 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_chi_3e( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s) ++{ ++ uint64_t old[5U][5U]; ++ memcpy(old, s->st, (size_t)5U * sizeof(uint64_t[5U])); ++ KRML_MAYBE_FOR5( ++ i0, (size_t)0U, (size_t)5U, (size_t)1U, size_t i1 = i0; KRML_MAYBE_FOR5( ++ i, (size_t)0U, (size_t)5U, (size_t)1U, size_t j = i; ++ s->st[i1][j] = libcrux_sha3_portable_keccak_and_not_xor_5a( ++ s->st[i1][j], old[i1][(j + (size_t)2U) % (size_t)5U], ++ old[i1][(j + (size_t)1U) % (size_t)5U]););); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.iota ++with types uint64_t ++with const generics ++- N= 1 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_iota_00( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, size_t i) ++{ ++ s->st[0U][0U] = libcrux_sha3_portable_keccak_xor_constant_5a( ++ s->st[0U][0U], libcrux_sha3_generic_keccak_ROUNDCONSTANTS[i]); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.keccakf1600 ++with types uint64_t ++with const generics ++- N= 1 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_keccakf1600_b8( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s) ++{ ++ for (size_t i = (size_t)0U; i < (size_t)24U; i++) { ++ size_t i0 = i; ++ libcrux_sha3_generic_keccak_theta_rho_a7(s); ++ libcrux_sha3_generic_keccak_pi_d5(s); ++ libcrux_sha3_generic_keccak_chi_3e(s); ++ libcrux_sha3_generic_keccak_iota_00(s, i0); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 168 ++- DELIM= 31 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_final_40( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice last[1U]) ++{ ++ size_t last_len = Eurydice_slice_len(last[0U], uint8_t); ++ uint8_t blocks[1U][200U] = { { 0U } }; ++ { ++ size_t i = (size_t)0U; ++ if (last_len > (size_t)0U) { ++ Eurydice_slice uu____0 = ++ Eurydice_array_to_subslice2(blocks[i], (size_t)0U, last_len, uint8_t); ++ Eurydice_slice_copy(uu____0, last[i], uint8_t); ++ } ++ blocks[i][last_len] = 31U; ++ size_t uu____1 = i; ++ size_t uu____2 = (size_t)168U - (size_t)1U; ++ blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; ++ } ++ uint64_t(*uu____3)[5U] = s->st; ++ uint8_t uu____4[1U][200U]; ++ memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); ++ libcrux_sha3_portable_keccak_load_block_full_5a_05(uu____3, uu____4); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block ++with const generics ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_9b( ++ uint64_t (*s)[5U], Eurydice_slice out[1U]) ++{ ++ for (size_t i = (size_t)0U; i < (size_t)168U / (size_t)8U; i++) { ++ size_t i0 = i; ++ Eurydice_slice uu____0 = Eurydice_slice_subslice2( ++ out[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t); ++ uint8_t ret[8U]; ++ core_num__u64_9__to_le_bytes(s[i0 / (size_t)5U][i0 % (size_t)5U], ret); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)8U, ret, uint8_t), uint8_t); ++ } ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_5a ++with const generics ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_5a_49( ++ uint64_t (*a)[5U], Eurydice_slice b[1U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_9b(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_next_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_next_block_c2( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++ libcrux_sha3_portable_keccak_store_block_5a_49(s->st, out); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_first_block_7b( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_5a_49(s->st, out); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block ++with const generics ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_650( ++ uint64_t (*s)[5U], Eurydice_slice blocks[1U]) ++{ ++ for (size_t i = (size_t)0U; i < (size_t)136U / (size_t)8U; i++) { ++ size_t i0 = i; ++ uint8_t uu____0[8U]; ++ core_result_Result_56 dst; ++ Eurydice_slice_to_array2( ++ &dst, ++ Eurydice_slice_subslice2(blocks[0U], (size_t)8U * i0, ++ (size_t)8U * i0 + (size_t)8U, uint8_t), ++ Eurydice_slice, uint8_t[8U]); ++ core_result_unwrap_41_0e(dst, uu____0); ++ size_t uu____1 = i0 / (size_t)5U; ++ size_t uu____2 = i0 % (size_t)5U; ++ s[uu____1][uu____2] = ++ s[uu____1][uu____2] ^ core_num__u64_9__from_le_bytes(uu____0); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full ++with const generics ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_full_d40( ++ uint64_t (*s)[5U], uint8_t blocks[1U][200U]) ++{ ++ Eurydice_slice buf[1U] = { ++ Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t) ++ }; ++ libcrux_sha3_portable_keccak_load_block_650(s, buf); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full_5a ++with const generics ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_full_5a_050( ++ uint64_t (*a)[5U], uint8_t b[1U][200U]) ++{ ++ uint64_t(*uu____0)[5U] = a; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_b[1U][200U]; ++ memcpy(copy_of_b, b, (size_t)1U * sizeof(uint8_t[200U])); ++ libcrux_sha3_portable_keccak_load_block_full_d40(uu____0, copy_of_b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 136 ++- DELIM= 31 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_final_400( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice last[1U]) ++{ ++ size_t last_len = Eurydice_slice_len(last[0U], uint8_t); ++ uint8_t blocks[1U][200U] = { { 0U } }; ++ { ++ size_t i = (size_t)0U; ++ if (last_len > (size_t)0U) { ++ Eurydice_slice uu____0 = ++ Eurydice_array_to_subslice2(blocks[i], (size_t)0U, last_len, uint8_t); ++ Eurydice_slice_copy(uu____0, last[i], uint8_t); ++ } ++ blocks[i][last_len] = 31U; ++ size_t uu____1 = i; ++ size_t uu____2 = (size_t)136U - (size_t)1U; ++ blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; ++ } ++ uint64_t(*uu____3)[5U] = s->st; ++ uint8_t uu____4[1U][200U]; ++ memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); ++ libcrux_sha3_portable_keccak_load_block_full_5a_050(uu____3, uu____4); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block ++with const generics ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_9b0( ++ uint64_t (*s)[5U], Eurydice_slice out[1U]) ++{ ++ for (size_t i = (size_t)0U; i < (size_t)136U / (size_t)8U; i++) { ++ size_t i0 = i; ++ Eurydice_slice uu____0 = Eurydice_slice_subslice2( ++ out[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t); ++ uint8_t ret[8U]; ++ core_num__u64_9__to_le_bytes(s[i0 / (size_t)5U][i0 % (size_t)5U], ret); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)8U, ret, uint8_t), uint8_t); ++ } ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_5a ++with const generics ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_5a_490( ++ uint64_t (*a)[5U], Eurydice_slice b[1U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_9b0(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_first_block_7b0( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_5a_490(s->st, out); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_next_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_next_block_c20( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++ libcrux_sha3_portable_keccak_store_block_5a_490(s->st, out); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_5a ++with const generics ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_5a_35( ++ uint64_t (*a)[5U], Eurydice_slice b[1U]) ++{ ++ uint64_t(*uu____0)[5U] = a; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_b[1U]; ++ memcpy(copy_of_b, b, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_portable_keccak_load_block_650(uu____0, copy_of_b); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_5a ++with const generics ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_5a_350( ++ uint64_t (*a)[5U], Eurydice_slice b[1U]) ++{ ++ uint64_t(*uu____0)[5U] = a; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_b[1U]; ++ memcpy(copy_of_b, b, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_portable_keccak_load_block_65(uu____0, copy_of_b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_block_403( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice blocks[1U]) ++{ ++ uint64_t(*uu____0)[5U] = s->st; ++ Eurydice_slice uu____1[1U]; ++ memcpy(uu____1, blocks, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_portable_keccak_load_block_5a_350(uu____0, uu____1); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full ++with const generics ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_full_7e3( ++ uint64_t (*s)[5U], uint8_t ret[1U][200U]) ++{ ++ uint8_t out[200U] = { 0U }; ++ Eurydice_slice buf[1U] = { ++ Eurydice_array_to_slice((size_t)200U, out, uint8_t) ++ }; ++ libcrux_sha3_portable_keccak_store_block_9b(s, buf); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_out[200U]; ++ memcpy(copy_of_out, out, (size_t)200U * sizeof(uint8_t)); ++ memcpy(ret[0U], copy_of_out, (size_t)200U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full_5a ++with const generics ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_full_5a_273(uint64_t (*a)[5U], ++ uint8_t ret[1U][200U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_full_7e3(a, ret); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_and_last ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_first_and_last_883( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ uint8_t b[1U][200U]; ++ libcrux_sha3_portable_keccak_store_block_full_5a_273(s->st, b); ++ { ++ size_t i = (size_t)0U; ++ Eurydice_slice uu____0 = out[i]; ++ uint8_t *uu____1 = b[i]; ++ core_ops_range_Range_b3 lit; ++ lit.start = (size_t)0U; ++ lit.end = Eurydice_slice_len(out[i], uint8_t); ++ Eurydice_slice_copy( ++ uu____0, ++ Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, ++ core_ops_range_Range_b3), ++ uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_last ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 168 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_last_ca3( ++ libcrux_sha3_generic_keccak_KeccakState_48 s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&s); ++ uint8_t b[1U][200U]; ++ libcrux_sha3_portable_keccak_store_block_full_5a_273(s.st, b); ++ { ++ size_t i = (size_t)0U; ++ Eurydice_slice uu____0 = out[i]; ++ uint8_t *uu____1 = b[i]; ++ core_ops_range_Range_b3 lit; ++ lit.start = (size_t)0U; ++ lit.end = Eurydice_slice_len(out[i], uint8_t); ++ Eurydice_slice_copy( ++ uu____0, ++ Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, ++ core_ops_range_Range_b3), ++ uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.keccak ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 168 ++- DELIM= 31 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_keccak_064( ++ Eurydice_slice data[1U], Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakState_48 s = ++ libcrux_sha3_generic_keccak_new_1e_cf(); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(data[0U], uint8_t) / (size_t)168U; i++) { ++ size_t i0 = i; ++ libcrux_sha3_generic_keccak_KeccakState_48 *uu____0 = &s; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret[1U]; ++ libcrux_sha3_portable_keccak_slice_n_5a(copy_of_data, i0 * (size_t)168U, ++ (size_t)168U, ret); ++ libcrux_sha3_generic_keccak_absorb_block_403(uu____0, ret); ++ } ++ size_t rem = Eurydice_slice_len(data[0U], uint8_t) % (size_t)168U; ++ libcrux_sha3_generic_keccak_KeccakState_48 *uu____2 = &s; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret[1U]; ++ libcrux_sha3_portable_keccak_slice_n_5a( ++ copy_of_data, Eurydice_slice_len(data[0U], uint8_t) - rem, rem, ret); ++ libcrux_sha3_generic_keccak_absorb_final_40(uu____2, ret); ++ size_t outlen = Eurydice_slice_len(out[0U], uint8_t); ++ size_t blocks = outlen / (size_t)168U; ++ size_t last = outlen - outlen % (size_t)168U; ++ if (blocks == (size_t)0U) { ++ libcrux_sha3_generic_keccak_squeeze_first_and_last_883(&s, out); ++ } else { ++ Eurydice_slice_uint8_t_1size_t__x2 uu____4 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)168U); ++ Eurydice_slice o0[1U]; ++ memcpy(o0, uu____4.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice o1[1U]; ++ memcpy(o1, uu____4.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_first_block_7b(&s, o0); ++ core_ops_range_Range_b3 iter = ++ core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( ++ (CLITERAL(core_ops_range_Range_b3){ .start = (size_t)1U, ++ .end = blocks }), ++ core_ops_range_Range_b3, core_ops_range_Range_b3); ++ while (true) { ++ if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( ++ &iter, size_t, core_option_Option_b3) ++ .tag == core_option_None) { ++ break; ++ } else { ++ Eurydice_slice_uint8_t_1size_t__x2 uu____5 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(o1, (size_t)168U); ++ Eurydice_slice o[1U]; ++ memcpy(o, uu____5.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice orest[1U]; ++ memcpy(orest, uu____5.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_next_block_c2(&s, o); ++ memcpy(o1, orest, (size_t)1U * sizeof(Eurydice_slice)); ++ } ++ } ++ if (last < outlen) { ++ libcrux_sha3_generic_keccak_squeeze_last_ca3(s, o1); ++ } ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable.keccakx1 ++with const generics ++- RATE= 168 ++- DELIM= 31 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccakx1_e44( ++ Eurydice_slice data[1U], Eurydice_slice out[1U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_keccak_064(copy_of_data, out); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block ++with const generics ++- RATE= 104 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_653( ++ uint64_t (*s)[5U], Eurydice_slice blocks[1U]) ++{ ++ for (size_t i = (size_t)0U; i < (size_t)104U / (size_t)8U; i++) { ++ size_t i0 = i; ++ uint8_t uu____0[8U]; ++ core_result_Result_56 dst; ++ Eurydice_slice_to_array2( ++ &dst, ++ Eurydice_slice_subslice2(blocks[0U], (size_t)8U * i0, ++ (size_t)8U * i0 + (size_t)8U, uint8_t), ++ Eurydice_slice, uint8_t[8U]); ++ core_result_unwrap_41_0e(dst, uu____0); ++ size_t uu____1 = i0 / (size_t)5U; ++ size_t uu____2 = i0 % (size_t)5U; ++ s[uu____1][uu____2] = ++ s[uu____1][uu____2] ^ core_num__u64_9__from_le_bytes(uu____0); ++ } ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_5a ++with const generics ++- RATE= 104 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_5a_353( ++ uint64_t (*a)[5U], Eurydice_slice b[1U]) ++{ ++ uint64_t(*uu____0)[5U] = a; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_b[1U]; ++ memcpy(copy_of_b, b, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_portable_keccak_load_block_653(uu____0, copy_of_b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 104 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_block_402( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice blocks[1U]) ++{ ++ uint64_t(*uu____0)[5U] = s->st; ++ Eurydice_slice uu____1[1U]; ++ memcpy(uu____1, blocks, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_portable_keccak_load_block_5a_353(uu____0, uu____1); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full ++with const generics ++- RATE= 104 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_full_d43( ++ uint64_t (*s)[5U], uint8_t blocks[1U][200U]) ++{ ++ Eurydice_slice buf[1U] = { ++ Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t) ++ }; ++ libcrux_sha3_portable_keccak_load_block_653(s, buf); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full_5a ++with const generics ++- RATE= 104 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_full_5a_053( ++ uint64_t (*a)[5U], uint8_t b[1U][200U]) ++{ ++ uint64_t(*uu____0)[5U] = a; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_b[1U][200U]; ++ memcpy(copy_of_b, b, (size_t)1U * sizeof(uint8_t[200U])); ++ libcrux_sha3_portable_keccak_load_block_full_d43(uu____0, copy_of_b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 104 ++- DELIM= 6 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_final_404( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice last[1U]) ++{ ++ size_t last_len = Eurydice_slice_len(last[0U], uint8_t); ++ uint8_t blocks[1U][200U] = { { 0U } }; ++ { ++ size_t i = (size_t)0U; ++ if (last_len > (size_t)0U) { ++ Eurydice_slice uu____0 = ++ Eurydice_array_to_subslice2(blocks[i], (size_t)0U, last_len, uint8_t); ++ Eurydice_slice_copy(uu____0, last[i], uint8_t); ++ } ++ blocks[i][last_len] = 6U; ++ size_t uu____1 = i; ++ size_t uu____2 = (size_t)104U - (size_t)1U; ++ blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; ++ } ++ uint64_t(*uu____3)[5U] = s->st; ++ uint8_t uu____4[1U][200U]; ++ memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); ++ libcrux_sha3_portable_keccak_load_block_full_5a_053(uu____3, uu____4); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block ++with const generics ++- RATE= 104 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_9b3( ++ uint64_t (*s)[5U], Eurydice_slice out[1U]) ++{ ++ for (size_t i = (size_t)0U; i < (size_t)104U / (size_t)8U; i++) { ++ size_t i0 = i; ++ Eurydice_slice uu____0 = Eurydice_slice_subslice2( ++ out[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t); ++ uint8_t ret[8U]; ++ core_num__u64_9__to_le_bytes(s[i0 / (size_t)5U][i0 % (size_t)5U], ret); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)8U, ret, uint8_t), uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full ++with const generics ++- RATE= 104 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_full_7e2( ++ uint64_t (*s)[5U], uint8_t ret[1U][200U]) ++{ ++ uint8_t out[200U] = { 0U }; ++ Eurydice_slice buf[1U] = { ++ Eurydice_array_to_slice((size_t)200U, out, uint8_t) ++ }; ++ libcrux_sha3_portable_keccak_store_block_9b3(s, buf); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_out[200U]; ++ memcpy(copy_of_out, out, (size_t)200U * sizeof(uint8_t)); ++ memcpy(ret[0U], copy_of_out, (size_t)200U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full_5a ++with const generics ++- RATE= 104 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_full_5a_272(uint64_t (*a)[5U], ++ uint8_t ret[1U][200U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_full_7e2(a, ret); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_and_last ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 104 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_first_and_last_882( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ uint8_t b[1U][200U]; ++ libcrux_sha3_portable_keccak_store_block_full_5a_272(s->st, b); ++ { ++ size_t i = (size_t)0U; ++ Eurydice_slice uu____0 = out[i]; ++ uint8_t *uu____1 = b[i]; ++ core_ops_range_Range_b3 lit; ++ lit.start = (size_t)0U; ++ lit.end = Eurydice_slice_len(out[i], uint8_t); ++ Eurydice_slice_copy( ++ uu____0, ++ Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, ++ core_ops_range_Range_b3), ++ uint8_t); ++ } ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_5a ++with const generics ++- RATE= 104 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_5a_493( ++ uint64_t (*a)[5U], Eurydice_slice b[1U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_9b3(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 104 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_first_block_7b3( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_5a_493(s->st, out); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_next_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 104 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_next_block_c23( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++ libcrux_sha3_portable_keccak_store_block_5a_493(s->st, out); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_last ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 104 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_last_ca2( ++ libcrux_sha3_generic_keccak_KeccakState_48 s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&s); ++ uint8_t b[1U][200U]; ++ libcrux_sha3_portable_keccak_store_block_full_5a_272(s.st, b); ++ { ++ size_t i = (size_t)0U; ++ Eurydice_slice uu____0 = out[i]; ++ uint8_t *uu____1 = b[i]; ++ core_ops_range_Range_b3 lit; ++ lit.start = (size_t)0U; ++ lit.end = Eurydice_slice_len(out[i], uint8_t); ++ Eurydice_slice_copy( ++ uu____0, ++ Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, ++ core_ops_range_Range_b3), ++ uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.keccak ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 104 ++- DELIM= 6 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_keccak_063( ++ Eurydice_slice data[1U], Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakState_48 s = ++ libcrux_sha3_generic_keccak_new_1e_cf(); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(data[0U], uint8_t) / (size_t)104U; i++) { ++ size_t i0 = i; ++ libcrux_sha3_generic_keccak_KeccakState_48 *uu____0 = &s; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret[1U]; ++ libcrux_sha3_portable_keccak_slice_n_5a(copy_of_data, i0 * (size_t)104U, ++ (size_t)104U, ret); ++ libcrux_sha3_generic_keccak_absorb_block_402(uu____0, ret); ++ } ++ size_t rem = Eurydice_slice_len(data[0U], uint8_t) % (size_t)104U; ++ libcrux_sha3_generic_keccak_KeccakState_48 *uu____2 = &s; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret[1U]; ++ libcrux_sha3_portable_keccak_slice_n_5a( ++ copy_of_data, Eurydice_slice_len(data[0U], uint8_t) - rem, rem, ret); ++ libcrux_sha3_generic_keccak_absorb_final_404(uu____2, ret); ++ size_t outlen = Eurydice_slice_len(out[0U], uint8_t); ++ size_t blocks = outlen / (size_t)104U; ++ size_t last = outlen - outlen % (size_t)104U; ++ if (blocks == (size_t)0U) { ++ libcrux_sha3_generic_keccak_squeeze_first_and_last_882(&s, out); ++ } else { ++ Eurydice_slice_uint8_t_1size_t__x2 uu____4 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)104U); ++ Eurydice_slice o0[1U]; ++ memcpy(o0, uu____4.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice o1[1U]; ++ memcpy(o1, uu____4.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_first_block_7b3(&s, o0); ++ core_ops_range_Range_b3 iter = ++ core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( ++ (CLITERAL(core_ops_range_Range_b3){ .start = (size_t)1U, ++ .end = blocks }), ++ core_ops_range_Range_b3, core_ops_range_Range_b3); ++ while (true) { ++ if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( ++ &iter, size_t, core_option_Option_b3) ++ .tag == core_option_None) { ++ break; ++ } else { ++ Eurydice_slice_uint8_t_1size_t__x2 uu____5 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(o1, (size_t)104U); ++ Eurydice_slice o[1U]; ++ memcpy(o, uu____5.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice orest[1U]; ++ memcpy(orest, uu____5.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_next_block_c23(&s, o); ++ memcpy(o1, orest, (size_t)1U * sizeof(Eurydice_slice)); ++ } ++ } ++ if (last < outlen) { ++ libcrux_sha3_generic_keccak_squeeze_last_ca2(s, o1); ++ } ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable.keccakx1 ++with const generics ++- RATE= 104 ++- DELIM= 6 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccakx1_e43( ++ Eurydice_slice data[1U], Eurydice_slice out[1U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_keccak_063(copy_of_data, out); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block ++with const generics ++- RATE= 144 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_652( ++ uint64_t (*s)[5U], Eurydice_slice blocks[1U]) ++{ ++ for (size_t i = (size_t)0U; i < (size_t)144U / (size_t)8U; i++) { ++ size_t i0 = i; ++ uint8_t uu____0[8U]; ++ core_result_Result_56 dst; ++ Eurydice_slice_to_array2( ++ &dst, ++ Eurydice_slice_subslice2(blocks[0U], (size_t)8U * i0, ++ (size_t)8U * i0 + (size_t)8U, uint8_t), ++ Eurydice_slice, uint8_t[8U]); ++ core_result_unwrap_41_0e(dst, uu____0); ++ size_t uu____1 = i0 / (size_t)5U; ++ size_t uu____2 = i0 % (size_t)5U; ++ s[uu____1][uu____2] = ++ s[uu____1][uu____2] ^ core_num__u64_9__from_le_bytes(uu____0); ++ } ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_5a ++with const generics ++- RATE= 144 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_5a_352( ++ uint64_t (*a)[5U], Eurydice_slice b[1U]) ++{ ++ uint64_t(*uu____0)[5U] = a; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_b[1U]; ++ memcpy(copy_of_b, b, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_portable_keccak_load_block_652(uu____0, copy_of_b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 144 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_block_401( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice blocks[1U]) ++{ ++ uint64_t(*uu____0)[5U] = s->st; ++ Eurydice_slice uu____1[1U]; ++ memcpy(uu____1, blocks, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_portable_keccak_load_block_5a_352(uu____0, uu____1); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full ++with const generics ++- RATE= 144 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_full_d42( ++ uint64_t (*s)[5U], uint8_t blocks[1U][200U]) ++{ ++ Eurydice_slice buf[1U] = { ++ Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t) ++ }; ++ libcrux_sha3_portable_keccak_load_block_652(s, buf); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full_5a ++with const generics ++- RATE= 144 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_full_5a_052( ++ uint64_t (*a)[5U], uint8_t b[1U][200U]) ++{ ++ uint64_t(*uu____0)[5U] = a; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_b[1U][200U]; ++ memcpy(copy_of_b, b, (size_t)1U * sizeof(uint8_t[200U])); ++ libcrux_sha3_portable_keccak_load_block_full_d42(uu____0, copy_of_b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 144 ++- DELIM= 6 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_final_403( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice last[1U]) ++{ ++ size_t last_len = Eurydice_slice_len(last[0U], uint8_t); ++ uint8_t blocks[1U][200U] = { { 0U } }; ++ { ++ size_t i = (size_t)0U; ++ if (last_len > (size_t)0U) { ++ Eurydice_slice uu____0 = ++ Eurydice_array_to_subslice2(blocks[i], (size_t)0U, last_len, uint8_t); ++ Eurydice_slice_copy(uu____0, last[i], uint8_t); ++ } ++ blocks[i][last_len] = 6U; ++ size_t uu____1 = i; ++ size_t uu____2 = (size_t)144U - (size_t)1U; ++ blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; ++ } ++ uint64_t(*uu____3)[5U] = s->st; ++ uint8_t uu____4[1U][200U]; ++ memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); ++ libcrux_sha3_portable_keccak_load_block_full_5a_052(uu____3, uu____4); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block ++with const generics ++- RATE= 144 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_9b2( ++ uint64_t (*s)[5U], Eurydice_slice out[1U]) ++{ ++ for (size_t i = (size_t)0U; i < (size_t)144U / (size_t)8U; i++) { ++ size_t i0 = i; ++ Eurydice_slice uu____0 = Eurydice_slice_subslice2( ++ out[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t); ++ uint8_t ret[8U]; ++ core_num__u64_9__to_le_bytes(s[i0 / (size_t)5U][i0 % (size_t)5U], ret); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)8U, ret, uint8_t), uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full ++with const generics ++- RATE= 144 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_full_7e1( ++ uint64_t (*s)[5U], uint8_t ret[1U][200U]) ++{ ++ uint8_t out[200U] = { 0U }; ++ Eurydice_slice buf[1U] = { ++ Eurydice_array_to_slice((size_t)200U, out, uint8_t) ++ }; ++ libcrux_sha3_portable_keccak_store_block_9b2(s, buf); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_out[200U]; ++ memcpy(copy_of_out, out, (size_t)200U * sizeof(uint8_t)); ++ memcpy(ret[0U], copy_of_out, (size_t)200U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full_5a ++with const generics ++- RATE= 144 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_full_5a_271(uint64_t (*a)[5U], ++ uint8_t ret[1U][200U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_full_7e1(a, ret); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_and_last ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 144 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_first_and_last_881( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ uint8_t b[1U][200U]; ++ libcrux_sha3_portable_keccak_store_block_full_5a_271(s->st, b); ++ { ++ size_t i = (size_t)0U; ++ Eurydice_slice uu____0 = out[i]; ++ uint8_t *uu____1 = b[i]; ++ core_ops_range_Range_b3 lit; ++ lit.start = (size_t)0U; ++ lit.end = Eurydice_slice_len(out[i], uint8_t); ++ Eurydice_slice_copy( ++ uu____0, ++ Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, ++ core_ops_range_Range_b3), ++ uint8_t); ++ } ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_5a ++with const generics ++- RATE= 144 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_5a_492( ++ uint64_t (*a)[5U], Eurydice_slice b[1U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_9b2(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 144 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_first_block_7b2( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_5a_492(s->st, out); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_next_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 144 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_next_block_c22( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++ libcrux_sha3_portable_keccak_store_block_5a_492(s->st, out); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_last ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 144 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_last_ca1( ++ libcrux_sha3_generic_keccak_KeccakState_48 s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&s); ++ uint8_t b[1U][200U]; ++ libcrux_sha3_portable_keccak_store_block_full_5a_271(s.st, b); ++ { ++ size_t i = (size_t)0U; ++ Eurydice_slice uu____0 = out[i]; ++ uint8_t *uu____1 = b[i]; ++ core_ops_range_Range_b3 lit; ++ lit.start = (size_t)0U; ++ lit.end = Eurydice_slice_len(out[i], uint8_t); ++ Eurydice_slice_copy( ++ uu____0, ++ Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, ++ core_ops_range_Range_b3), ++ uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.keccak ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 144 ++- DELIM= 6 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_keccak_062( ++ Eurydice_slice data[1U], Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakState_48 s = ++ libcrux_sha3_generic_keccak_new_1e_cf(); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(data[0U], uint8_t) / (size_t)144U; i++) { ++ size_t i0 = i; ++ libcrux_sha3_generic_keccak_KeccakState_48 *uu____0 = &s; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret[1U]; ++ libcrux_sha3_portable_keccak_slice_n_5a(copy_of_data, i0 * (size_t)144U, ++ (size_t)144U, ret); ++ libcrux_sha3_generic_keccak_absorb_block_401(uu____0, ret); ++ } ++ size_t rem = Eurydice_slice_len(data[0U], uint8_t) % (size_t)144U; ++ libcrux_sha3_generic_keccak_KeccakState_48 *uu____2 = &s; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret[1U]; ++ libcrux_sha3_portable_keccak_slice_n_5a( ++ copy_of_data, Eurydice_slice_len(data[0U], uint8_t) - rem, rem, ret); ++ libcrux_sha3_generic_keccak_absorb_final_403(uu____2, ret); ++ size_t outlen = Eurydice_slice_len(out[0U], uint8_t); ++ size_t blocks = outlen / (size_t)144U; ++ size_t last = outlen - outlen % (size_t)144U; ++ if (blocks == (size_t)0U) { ++ libcrux_sha3_generic_keccak_squeeze_first_and_last_881(&s, out); ++ } else { ++ Eurydice_slice_uint8_t_1size_t__x2 uu____4 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)144U); ++ Eurydice_slice o0[1U]; ++ memcpy(o0, uu____4.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice o1[1U]; ++ memcpy(o1, uu____4.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_first_block_7b2(&s, o0); ++ core_ops_range_Range_b3 iter = ++ core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( ++ (CLITERAL(core_ops_range_Range_b3){ .start = (size_t)1U, ++ .end = blocks }), ++ core_ops_range_Range_b3, core_ops_range_Range_b3); ++ while (true) { ++ if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( ++ &iter, size_t, core_option_Option_b3) ++ .tag == core_option_None) { ++ break; ++ } else { ++ Eurydice_slice_uint8_t_1size_t__x2 uu____5 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(o1, (size_t)144U); ++ Eurydice_slice o[1U]; ++ memcpy(o, uu____5.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice orest[1U]; ++ memcpy(orest, uu____5.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_next_block_c22(&s, o); ++ memcpy(o1, orest, (size_t)1U * sizeof(Eurydice_slice)); ++ } ++ } ++ if (last < outlen) { ++ libcrux_sha3_generic_keccak_squeeze_last_ca1(s, o1); ++ } ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable.keccakx1 ++with const generics ++- RATE= 144 ++- DELIM= 6 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccakx1_e42( ++ Eurydice_slice data[1U], Eurydice_slice out[1U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_keccak_062(copy_of_data, out); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_block_400( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice blocks[1U]) ++{ ++ uint64_t(*uu____0)[5U] = s->st; ++ Eurydice_slice uu____1[1U]; ++ memcpy(uu____1, blocks, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_portable_keccak_load_block_5a_35(uu____0, uu____1); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full ++with const generics ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_full_7e0( ++ uint64_t (*s)[5U], uint8_t ret[1U][200U]) ++{ ++ uint8_t out[200U] = { 0U }; ++ Eurydice_slice buf[1U] = { ++ Eurydice_array_to_slice((size_t)200U, out, uint8_t) ++ }; ++ libcrux_sha3_portable_keccak_store_block_9b0(s, buf); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_out[200U]; ++ memcpy(copy_of_out, out, (size_t)200U * sizeof(uint8_t)); ++ memcpy(ret[0U], copy_of_out, (size_t)200U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full_5a ++with const generics ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_full_5a_270(uint64_t (*a)[5U], ++ uint8_t ret[1U][200U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_full_7e0(a, ret); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_and_last ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_first_and_last_880( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ uint8_t b[1U][200U]; ++ libcrux_sha3_portable_keccak_store_block_full_5a_270(s->st, b); ++ { ++ size_t i = (size_t)0U; ++ Eurydice_slice uu____0 = out[i]; ++ uint8_t *uu____1 = b[i]; ++ core_ops_range_Range_b3 lit; ++ lit.start = (size_t)0U; ++ lit.end = Eurydice_slice_len(out[i], uint8_t); ++ Eurydice_slice_copy( ++ uu____0, ++ Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, ++ core_ops_range_Range_b3), ++ uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_last ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 136 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_last_ca0( ++ libcrux_sha3_generic_keccak_KeccakState_48 s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&s); ++ uint8_t b[1U][200U]; ++ libcrux_sha3_portable_keccak_store_block_full_5a_270(s.st, b); ++ { ++ size_t i = (size_t)0U; ++ Eurydice_slice uu____0 = out[i]; ++ uint8_t *uu____1 = b[i]; ++ core_ops_range_Range_b3 lit; ++ lit.start = (size_t)0U; ++ lit.end = Eurydice_slice_len(out[i], uint8_t); ++ Eurydice_slice_copy( ++ uu____0, ++ Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, ++ core_ops_range_Range_b3), ++ uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.keccak ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 136 ++- DELIM= 31 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_keccak_061( ++ Eurydice_slice data[1U], Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakState_48 s = ++ libcrux_sha3_generic_keccak_new_1e_cf(); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(data[0U], uint8_t) / (size_t)136U; i++) { ++ size_t i0 = i; ++ libcrux_sha3_generic_keccak_KeccakState_48 *uu____0 = &s; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret[1U]; ++ libcrux_sha3_portable_keccak_slice_n_5a(copy_of_data, i0 * (size_t)136U, ++ (size_t)136U, ret); ++ libcrux_sha3_generic_keccak_absorb_block_400(uu____0, ret); ++ } ++ size_t rem = Eurydice_slice_len(data[0U], uint8_t) % (size_t)136U; ++ libcrux_sha3_generic_keccak_KeccakState_48 *uu____2 = &s; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret[1U]; ++ libcrux_sha3_portable_keccak_slice_n_5a( ++ copy_of_data, Eurydice_slice_len(data[0U], uint8_t) - rem, rem, ret); ++ libcrux_sha3_generic_keccak_absorb_final_400(uu____2, ret); ++ size_t outlen = Eurydice_slice_len(out[0U], uint8_t); ++ size_t blocks = outlen / (size_t)136U; ++ size_t last = outlen - outlen % (size_t)136U; ++ if (blocks == (size_t)0U) { ++ libcrux_sha3_generic_keccak_squeeze_first_and_last_880(&s, out); ++ } else { ++ Eurydice_slice_uint8_t_1size_t__x2 uu____4 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)136U); ++ Eurydice_slice o0[1U]; ++ memcpy(o0, uu____4.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice o1[1U]; ++ memcpy(o1, uu____4.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_first_block_7b0(&s, o0); ++ core_ops_range_Range_b3 iter = ++ core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( ++ (CLITERAL(core_ops_range_Range_b3){ .start = (size_t)1U, ++ .end = blocks }), ++ core_ops_range_Range_b3, core_ops_range_Range_b3); ++ while (true) { ++ if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( ++ &iter, size_t, core_option_Option_b3) ++ .tag == core_option_None) { ++ break; ++ } else { ++ Eurydice_slice_uint8_t_1size_t__x2 uu____5 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(o1, (size_t)136U); ++ Eurydice_slice o[1U]; ++ memcpy(o, uu____5.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice orest[1U]; ++ memcpy(orest, uu____5.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_next_block_c20(&s, o); ++ memcpy(o1, orest, (size_t)1U * sizeof(Eurydice_slice)); ++ } ++ } ++ if (last < outlen) { ++ libcrux_sha3_generic_keccak_squeeze_last_ca0(s, o1); ++ } ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable.keccakx1 ++with const generics ++- RATE= 136 ++- DELIM= 31 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccakx1_e41( ++ Eurydice_slice data[1U], Eurydice_slice out[1U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_keccak_061(copy_of_data, out); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 136 ++- DELIM= 6 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_final_402( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice last[1U]) ++{ ++ size_t last_len = Eurydice_slice_len(last[0U], uint8_t); ++ uint8_t blocks[1U][200U] = { { 0U } }; ++ { ++ size_t i = (size_t)0U; ++ if (last_len > (size_t)0U) { ++ Eurydice_slice uu____0 = ++ Eurydice_array_to_subslice2(blocks[i], (size_t)0U, last_len, uint8_t); ++ Eurydice_slice_copy(uu____0, last[i], uint8_t); ++ } ++ blocks[i][last_len] = 6U; ++ size_t uu____1 = i; ++ size_t uu____2 = (size_t)136U - (size_t)1U; ++ blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; ++ } ++ uint64_t(*uu____3)[5U] = s->st; ++ uint8_t uu____4[1U][200U]; ++ memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); ++ libcrux_sha3_portable_keccak_load_block_full_5a_050(uu____3, uu____4); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.keccak ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 136 ++- DELIM= 6 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_keccak_060( ++ Eurydice_slice data[1U], Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakState_48 s = ++ libcrux_sha3_generic_keccak_new_1e_cf(); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(data[0U], uint8_t) / (size_t)136U; i++) { ++ size_t i0 = i; ++ libcrux_sha3_generic_keccak_KeccakState_48 *uu____0 = &s; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret[1U]; ++ libcrux_sha3_portable_keccak_slice_n_5a(copy_of_data, i0 * (size_t)136U, ++ (size_t)136U, ret); ++ libcrux_sha3_generic_keccak_absorb_block_400(uu____0, ret); ++ } ++ size_t rem = Eurydice_slice_len(data[0U], uint8_t) % (size_t)136U; ++ libcrux_sha3_generic_keccak_KeccakState_48 *uu____2 = &s; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret[1U]; ++ libcrux_sha3_portable_keccak_slice_n_5a( ++ copy_of_data, Eurydice_slice_len(data[0U], uint8_t) - rem, rem, ret); ++ libcrux_sha3_generic_keccak_absorb_final_402(uu____2, ret); ++ size_t outlen = Eurydice_slice_len(out[0U], uint8_t); ++ size_t blocks = outlen / (size_t)136U; ++ size_t last = outlen - outlen % (size_t)136U; ++ if (blocks == (size_t)0U) { ++ libcrux_sha3_generic_keccak_squeeze_first_and_last_880(&s, out); ++ } else { ++ Eurydice_slice_uint8_t_1size_t__x2 uu____4 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)136U); ++ Eurydice_slice o0[1U]; ++ memcpy(o0, uu____4.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice o1[1U]; ++ memcpy(o1, uu____4.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_first_block_7b0(&s, o0); ++ core_ops_range_Range_b3 iter = ++ core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( ++ (CLITERAL(core_ops_range_Range_b3){ .start = (size_t)1U, ++ .end = blocks }), ++ core_ops_range_Range_b3, core_ops_range_Range_b3); ++ while (true) { ++ if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( ++ &iter, size_t, core_option_Option_b3) ++ .tag == core_option_None) { ++ break; ++ } else { ++ Eurydice_slice_uint8_t_1size_t__x2 uu____5 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(o1, (size_t)136U); ++ Eurydice_slice o[1U]; ++ memcpy(o, uu____5.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice orest[1U]; ++ memcpy(orest, uu____5.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_next_block_c20(&s, o); ++ memcpy(o1, orest, (size_t)1U * sizeof(Eurydice_slice)); ++ } ++ } ++ if (last < outlen) { ++ libcrux_sha3_generic_keccak_squeeze_last_ca0(s, o1); ++ } ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable.keccakx1 ++with const generics ++- RATE= 136 ++- DELIM= 6 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccakx1_e40( ++ Eurydice_slice data[1U], Eurydice_slice out[1U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_keccak_060(copy_of_data, out); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block ++with const generics ++- RATE= 72 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_651( ++ uint64_t (*s)[5U], Eurydice_slice blocks[1U]) ++{ ++ for (size_t i = (size_t)0U; i < (size_t)72U / (size_t)8U; i++) { ++ size_t i0 = i; ++ uint8_t uu____0[8U]; ++ core_result_Result_56 dst; ++ Eurydice_slice_to_array2( ++ &dst, ++ Eurydice_slice_subslice2(blocks[0U], (size_t)8U * i0, ++ (size_t)8U * i0 + (size_t)8U, uint8_t), ++ Eurydice_slice, uint8_t[8U]); ++ core_result_unwrap_41_0e(dst, uu____0); ++ size_t uu____1 = i0 / (size_t)5U; ++ size_t uu____2 = i0 % (size_t)5U; ++ s[uu____1][uu____2] = ++ s[uu____1][uu____2] ^ core_num__u64_9__from_le_bytes(uu____0); ++ } ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_5a ++with const generics ++- RATE= 72 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_5a_351( ++ uint64_t (*a)[5U], Eurydice_slice b[1U]) ++{ ++ uint64_t(*uu____0)[5U] = a; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_b[1U]; ++ memcpy(copy_of_b, b, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_portable_keccak_load_block_651(uu____0, copy_of_b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 72 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_block_40( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice blocks[1U]) ++{ ++ uint64_t(*uu____0)[5U] = s->st; ++ Eurydice_slice uu____1[1U]; ++ memcpy(uu____1, blocks, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_portable_keccak_load_block_5a_351(uu____0, uu____1); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full ++with const generics ++- RATE= 72 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_full_d41( ++ uint64_t (*s)[5U], uint8_t blocks[1U][200U]) ++{ ++ Eurydice_slice buf[1U] = { ++ Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t) ++ }; ++ libcrux_sha3_portable_keccak_load_block_651(s, buf); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full_5a ++with const generics ++- RATE= 72 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_load_block_full_5a_051( ++ uint64_t (*a)[5U], uint8_t b[1U][200U]) ++{ ++ uint64_t(*uu____0)[5U] = a; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_b[1U][200U]; ++ memcpy(copy_of_b, b, (size_t)1U * sizeof(uint8_t[200U])); ++ libcrux_sha3_portable_keccak_load_block_full_d41(uu____0, copy_of_b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 72 ++- DELIM= 6 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_absorb_final_401( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice last[1U]) ++{ ++ size_t last_len = Eurydice_slice_len(last[0U], uint8_t); ++ uint8_t blocks[1U][200U] = { { 0U } }; ++ { ++ size_t i = (size_t)0U; ++ if (last_len > (size_t)0U) { ++ Eurydice_slice uu____0 = ++ Eurydice_array_to_subslice2(blocks[i], (size_t)0U, last_len, uint8_t); ++ Eurydice_slice_copy(uu____0, last[i], uint8_t); ++ } ++ blocks[i][last_len] = 6U; ++ size_t uu____1 = i; ++ size_t uu____2 = (size_t)72U - (size_t)1U; ++ blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; ++ } ++ uint64_t(*uu____3)[5U] = s->st; ++ uint8_t uu____4[1U][200U]; ++ memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); ++ libcrux_sha3_portable_keccak_load_block_full_5a_051(uu____3, uu____4); ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block ++with const generics ++- RATE= 72 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_9b1( ++ uint64_t (*s)[5U], Eurydice_slice out[1U]) ++{ ++ for (size_t i = (size_t)0U; i < (size_t)72U / (size_t)8U; i++) { ++ size_t i0 = i; ++ Eurydice_slice uu____0 = Eurydice_slice_subslice2( ++ out[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t); ++ uint8_t ret[8U]; ++ core_num__u64_9__to_le_bytes(s[i0 / (size_t)5U][i0 % (size_t)5U], ret); ++ Eurydice_slice_copy( ++ uu____0, Eurydice_array_to_slice((size_t)8U, ret, uint8_t), uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full ++with const generics ++- RATE= 72 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_full_7e( ++ uint64_t (*s)[5U], uint8_t ret[1U][200U]) ++{ ++ uint8_t out[200U] = { 0U }; ++ Eurydice_slice buf[1U] = { ++ Eurydice_array_to_slice((size_t)200U, out, uint8_t) ++ }; ++ libcrux_sha3_portable_keccak_store_block_9b1(s, buf); ++ /* Passing arrays by value in Rust generates a copy in C */ ++ uint8_t copy_of_out[200U]; ++ memcpy(copy_of_out, out, (size_t)200U * sizeof(uint8_t)); ++ memcpy(ret[0U], copy_of_out, (size_t)200U * sizeof(uint8_t)); ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full_5a ++with const generics ++- RATE= 72 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_full_5a_27( ++ uint64_t (*a)[5U], uint8_t ret[1U][200U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_full_7e(a, ret); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_and_last ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 72 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_first_and_last_88( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ uint8_t b[1U][200U]; ++ libcrux_sha3_portable_keccak_store_block_full_5a_27(s->st, b); ++ { ++ size_t i = (size_t)0U; ++ Eurydice_slice uu____0 = out[i]; ++ uint8_t *uu____1 = b[i]; ++ core_ops_range_Range_b3 lit; ++ lit.start = (size_t)0U; ++ lit.end = Eurydice_slice_len(out[i], uint8_t); ++ Eurydice_slice_copy( ++ uu____0, ++ Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, ++ core_ops_range_Range_b3), ++ uint8_t); ++ } ++} ++ ++/** ++This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: ++usize> for u64)} ++*/ ++/** ++A monomorphic instance of libcrux_sha3.portable_keccak.store_block_5a ++with const generics ++- RATE= 72 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccak_store_block_5a_491( ++ uint64_t (*a)[5U], Eurydice_slice b[1U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_9b1(a, b); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 72 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_first_block_7b1( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_portable_keccak_store_block_5a_491(s->st, out); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_next_block ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 72 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_next_block_c21( ++ libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_keccakf1600_b8(s); ++ libcrux_sha3_portable_keccak_store_block_5a_491(s->st, out); ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_last ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 72 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_squeeze_last_ca( ++ libcrux_sha3_generic_keccak_KeccakState_48 s, Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_keccakf1600_b8(&s); ++ uint8_t b[1U][200U]; ++ libcrux_sha3_portable_keccak_store_block_full_5a_27(s.st, b); ++ { ++ size_t i = (size_t)0U; ++ Eurydice_slice uu____0 = out[i]; ++ uint8_t *uu____1 = b[i]; ++ core_ops_range_Range_b3 lit; ++ lit.start = (size_t)0U; ++ lit.end = Eurydice_slice_len(out[i], uint8_t); ++ Eurydice_slice_copy( ++ uu____0, ++ Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, ++ core_ops_range_Range_b3), ++ uint8_t); ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.generic_keccak.keccak ++with types uint64_t ++with const generics ++- N= 1 ++- RATE= 72 ++- DELIM= 6 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_generic_keccak_keccak_06( ++ Eurydice_slice data[1U], Eurydice_slice out[1U]) ++{ ++ libcrux_sha3_generic_keccak_KeccakState_48 s = ++ libcrux_sha3_generic_keccak_new_1e_cf(); ++ for (size_t i = (size_t)0U; ++ i < Eurydice_slice_len(data[0U], uint8_t) / (size_t)72U; i++) { ++ size_t i0 = i; ++ libcrux_sha3_generic_keccak_KeccakState_48 *uu____0 = &s; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret[1U]; ++ libcrux_sha3_portable_keccak_slice_n_5a(copy_of_data, i0 * (size_t)72U, ++ (size_t)72U, ret); ++ libcrux_sha3_generic_keccak_absorb_block_40(uu____0, ret); ++ } ++ size_t rem = Eurydice_slice_len(data[0U], uint8_t) % (size_t)72U; ++ libcrux_sha3_generic_keccak_KeccakState_48 *uu____2 = &s; ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice ret[1U]; ++ libcrux_sha3_portable_keccak_slice_n_5a( ++ copy_of_data, Eurydice_slice_len(data[0U], uint8_t) - rem, rem, ret); ++ libcrux_sha3_generic_keccak_absorb_final_401(uu____2, ret); ++ size_t outlen = Eurydice_slice_len(out[0U], uint8_t); ++ size_t blocks = outlen / (size_t)72U; ++ size_t last = outlen - outlen % (size_t)72U; ++ if (blocks == (size_t)0U) { ++ libcrux_sha3_generic_keccak_squeeze_first_and_last_88(&s, out); ++ } else { ++ Eurydice_slice_uint8_t_1size_t__x2 uu____4 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)72U); ++ Eurydice_slice o0[1U]; ++ memcpy(o0, uu____4.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice o1[1U]; ++ memcpy(o1, uu____4.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_first_block_7b1(&s, o0); ++ core_ops_range_Range_b3 iter = ++ core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( ++ (CLITERAL(core_ops_range_Range_b3){ .start = (size_t)1U, ++ .end = blocks }), ++ core_ops_range_Range_b3, core_ops_range_Range_b3); ++ while (true) { ++ if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( ++ &iter, size_t, core_option_Option_b3) ++ .tag == core_option_None) { ++ break; ++ } else { ++ Eurydice_slice_uint8_t_1size_t__x2 uu____5 = ++ libcrux_sha3_portable_keccak_split_at_mut_n_5a(o1, (size_t)72U); ++ Eurydice_slice o[1U]; ++ memcpy(o, uu____5.fst, (size_t)1U * sizeof(Eurydice_slice)); ++ Eurydice_slice orest[1U]; ++ memcpy(orest, uu____5.snd, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_squeeze_next_block_c21(&s, o); ++ memcpy(o1, orest, (size_t)1U * sizeof(Eurydice_slice)); ++ } ++ } ++ if (last < outlen) { ++ libcrux_sha3_generic_keccak_squeeze_last_ca(s, o1); ++ } ++ } ++} ++ ++/** ++A monomorphic instance of libcrux_sha3.portable.keccakx1 ++with const generics ++- RATE= 72 ++- DELIM= 6 ++*/ ++static KRML_MUSTINLINE void ++libcrux_sha3_portable_keccakx1_e4( ++ Eurydice_slice data[1U], Eurydice_slice out[1U]) ++{ ++ /* Passing arrays by value in Rust generates a copy in C */ ++ Eurydice_slice copy_of_data[1U]; ++ memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); ++ libcrux_sha3_generic_keccak_keccak_06(copy_of_data, out); ++} ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#define __libcrux_sha3_internal_H_DEFINED ++#endif +diff -up ./lib/pk11wrap/pk11akey.c.mlkem ./lib/pk11wrap/pk11akey.c +--- ./lib/pk11wrap/pk11akey.c.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/pk11wrap/pk11akey.c 2024-10-31 14:54:15.466515970 -0700 +@@ -235,12 +235,17 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, + } + break; + case kyberKey: +- keyType = CKK_NSS_KYBER; + switch (pubKey->u.kyber.params) { + case params_kyber768_round3: + case params_kyber768_round3_test_mode: ++ keyType = CKK_NSS_KYBER; + kemParams = CKP_NSS_KYBER_768_ROUND3; + break; ++ case params_ml_kem768: ++ case params_ml_kem768_test_mode: ++ keyType = CKK_NSS_ML_KEM; ++ kemParams = CKP_NSS_ML_KEM_768; ++ break; + default: + kemParams = CKP_INVALID_ID; + break; +@@ -661,6 +666,7 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot + keyType = edKey; + break; + case CKK_NSS_KYBER: ++ case CKK_NSS_ML_KEM: + keyType = kyberKey; + break; + default: +@@ -832,7 +838,12 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot + if (crv != CKR_OK) + break; + +- if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_NSS_KYBER)) { ++ if (keyClass != CKO_PUBLIC_KEY) { ++ crv = CKR_OBJECT_HANDLE_INVALID; ++ break; ++ } ++ ++ if (pk11KeyType != CKK_NSS_KYBER && pk11KeyType != CKK_NSS_ML_KEM) { + crv = CKR_OBJECT_HANDLE_INVALID; + break; + } +@@ -846,6 +857,9 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot + case CKP_NSS_KYBER_768_ROUND3: + pubKey->u.kyber.params = params_kyber768_round3; + break; ++ case CKP_NSS_ML_KEM_768: ++ pubKey->u.kyber.params = params_ml_kem768; ++ break; + default: + pubKey->u.kyber.params = params_kyber_invalid; + break; +@@ -909,6 +923,7 @@ PK11_MakePrivKey(PK11SlotInfo *slot, Key + keyType = edKey; + break; + case CKK_NSS_KYBER: ++ case CKK_NSS_ML_KEM: + keyType = kyberKey; + break; + default: +@@ -1525,6 +1540,17 @@ PK11_GenerateKeyPairWithOpFlags(PK11Slot + keyType = kyberKey; + test_mech.mechanism = CKM_NSS_KYBER; + break; ++ case CKM_NSS_ML_KEM_KEY_PAIR_GEN: ++ kemParams = (CK_NSS_KEM_PARAMETER_SET_TYPE *)param; ++ attrs = kyberPubTemplate; ++ PK11_SETATTRS(attrs, CKA_NSS_PARAMETER_SET, ++ kemParams, ++ sizeof(CK_NSS_KEM_PARAMETER_SET_TYPE)); ++ attrs++; ++ pubTemplate = kyberPubTemplate; ++ keyType = kyberKey; ++ test_mech.mechanism = CKM_NSS_ML_KEM; ++ break; + case CKM_EC_EDWARDS_KEY_PAIR_GEN: + ecParams = (SECKEYECParams *)param; + attrs = ecPubTemplate; +diff -up ./lib/pk11wrap/pk11mech.c.mlkem ./lib/pk11wrap/pk11mech.c +--- ./lib/pk11wrap/pk11mech.c.mlkem 2024-10-31 14:54:15.446515747 -0700 ++++ ./lib/pk11wrap/pk11mech.c 2024-10-31 14:54:15.466515970 -0700 +@@ -431,6 +431,8 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type, + return CKK_GENERIC_SECRET; + case CKM_NSS_KYBER_KEY_PAIR_GEN: + return CKK_NSS_KYBER; ++ case CKM_NSS_ML_KEM_KEY_PAIR_GEN: ++ return CKK_NSS_ML_KEM; + default: + return pk11_lookup(type)->keyType; + } +diff -up ./lib/pk11wrap/pk11pars.c.mlkem ./lib/pk11wrap/pk11pars.c +--- ./lib/pk11wrap/pk11pars.c.mlkem 2024-10-31 14:54:15.438515658 -0700 ++++ ./lib/pk11wrap/pk11pars.c 2024-10-31 14:54:15.466515970 -0700 +@@ -247,6 +247,10 @@ static const oidValDef curveOptList[] = + NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, + { CIPHER_NAME("XYBER768D00"), SEC_OID_XYBER768D00, + NSS_USE_ALG_IN_SSL_KX }, ++ { CIPHER_NAME("MLKEM768X25519"), SEC_OID_MLKEM768X25519, ++ NSS_USE_ALG_IN_SSL_KX }, ++ { CIPHER_NAME("MLKEM768SECP256R1"), SEC_OID_MLKEM768SECP256R1, ++ NSS_USE_ALG_IN_SSL_KX }, + /* ANSI X9.62 named elliptic curves (characteristic two field) */ + { CIPHER_NAME("C2PNB163V1"), SEC_OID_ANSIX962_EC_C2PNB163V1, + NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, +diff -up ./lib/pk11wrap/pk11skey.c.mlkem ./lib/pk11wrap/pk11skey.c +--- ./lib/pk11wrap/pk11skey.c.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/pk11wrap/pk11skey.c 2024-10-31 14:54:15.466515970 -0700 +@@ -3083,6 +3083,8 @@ pk11_KyberCiphertextLength(SECKEYKyberPu + switch (pubKey->params) { + case params_kyber768_round3: + case params_kyber768_round3_test_mode: ++ case params_ml_kem768: ++ case params_ml_kem768_test_mode: + return KYBER768_CIPHERTEXT_BYTES; + default: + // unreachable +@@ -3135,16 +3137,18 @@ PK11_Encapsulate(SECKEYPublicKey *pubKey + *outCiphertext = NULL; + + CK_MECHANISM_TYPE kemType; +- switch (pubKey->keyType) { +- case kyberKey: ++ CK_NSS_KEM_PARAMETER_SET_TYPE kemParameterSet = PK11_ReadULongAttribute(slot, pubKey->pkcs11ID, CKA_NSS_PARAMETER_SET); ++ switch (kemParameterSet) { ++ case CKP_NSS_KYBER_768_ROUND3: + kemType = CKM_NSS_KYBER; + break; ++ case CKP_NSS_ML_KEM_768: ++ kemType = CKM_NSS_ML_KEM; ++ break; + default: +- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); ++ PORT_SetError(SEC_ERROR_INVALID_KEY); + return SECFailure; + } +- +- CK_NSS_KEM_PARAMETER_SET_TYPE kemParameterSet = PK11_ReadULongAttribute(slot, pubKey->pkcs11ID, CKA_NSS_PARAMETER_SET); + CK_MECHANISM mech = { kemType, &kemParameterSet, sizeof(kemParameterSet) }; + + sharedSecret = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, NULL); +@@ -3238,16 +3242,18 @@ PK11_Decapsulate(SECKEYPrivateKey *privK + *outKey = NULL; + + CK_MECHANISM_TYPE kemType; +- switch (privKey->keyType) { +- case kyberKey: ++ CK_NSS_KEM_PARAMETER_SET_TYPE kemParameterSet = PK11_ReadULongAttribute(slot, privKey->pkcs11ID, CKA_NSS_PARAMETER_SET); ++ switch (kemParameterSet) { ++ case CKP_NSS_KYBER_768_ROUND3: + kemType = CKM_NSS_KYBER; + break; ++ case CKP_NSS_ML_KEM_768: ++ kemType = CKM_NSS_ML_KEM; ++ break; + default: +- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); ++ PORT_SetError(SEC_ERROR_INVALID_KEY); + return SECFailure; + } +- +- CK_NSS_KEM_PARAMETER_SET_TYPE kemParameterSet = PK11_ReadULongAttribute(slot, privKey->pkcs11ID, CKA_NSS_PARAMETER_SET); + CK_MECHANISM mech = { kemType, &kemParameterSet, sizeof(kemParameterSet) }; + + sharedSecret = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, NULL); +diff -up ./lib/pk11wrap/secmodti.h.mlkem ./lib/pk11wrap/secmodti.h +--- ./lib/pk11wrap/secmodti.h.mlkem 2024-10-31 14:54:15.427515535 -0700 ++++ ./lib/pk11wrap/secmodti.h 2024-10-31 14:54:15.466515970 -0700 +@@ -207,5 +207,6 @@ struct PK11GenericObjectStr { + * header file that only NSS sees. Currently it's only available through + * the policy code */ + #define SEC_OID_TLS_REQUIRE_EMS SEC_OID_PRIVATE_1 ++#define SEC_OID_MLKEM768SECP256R1 SEC_OID_PRIVATE_2 + + #endif /* _SECMODTI_H_ */ +diff -up ./lib/softoken/fipsaudt.c.mlkem ./lib/softoken/fipsaudt.c +--- ./lib/softoken/fipsaudt.c.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/softoken/fipsaudt.c 2024-10-31 14:54:15.466515970 -0700 +@@ -319,3 +319,51 @@ sftk_AuditDigestKey(CK_SESSION_HANDLE hS + (PRUint32)hSession, (PRUint32)hKey, (PRUint32)rv); + sftk_LogAuditMessage(severity, NSS_AUDIT_DIGEST_KEY, msg); + } ++ ++void ++sftk_AuditEncapsulate(CK_SESSION_HANDLE hSession, ++ CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hPublicKey, ++ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, ++ CK_OBJECT_HANDLE_PTR phKey, CK_BYTE_PTR pCiphertext, ++ CK_ULONG_PTR pulCiphertextLen, CK_RV rv) ++{ ++ char msg[256]; ++ char mech[MECHANISM_BUFSIZE]; ++ char shKey[32]; ++ NSSAuditSeverity severity = (rv == CKR_OK) ? NSS_AUDIT_INFO : NSS_AUDIT_ERROR; ++ ++ sftk_PrintMechanism(mech, sizeof mech, pMechanism); ++ sftk_PrintReturnedObjectHandle(shKey, sizeof shKey, "phKey", phKey, rv); ++ PR_snprintf(msg, sizeof msg, ++ "C_Encapsulate(hSession=0x%08lX, pMechanism=%s, " ++ "hPublicKey=0x%08lX, pTemplate=%p, ulAttributeCount=%lu, " ++ "phKey=%p pCipherText=%p, pulCiphertextLen=%p)=0x%08lX%s", ++ (PRUint32)hSession, mech, ++ (PRUint32)hPublicKey, pTemplate, (PRUint32)ulAttributeCount, ++ phKey, pCiphertext, pulCiphertextLen, (PRUint32)rv, shKey); ++ sftk_LogAuditMessage(severity, NSS_AUDIT_ENCAPSULATE_KEY, msg); ++} ++ ++void ++sftk_AuditDecapsulate(CK_SESSION_HANDLE hSession, ++ CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hPrivateKey, ++ CK_BYTE_PTR pCiphertext, CK_ULONG ulCiphertextLen, ++ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, ++ CK_OBJECT_HANDLE_PTR phKey, CK_RV rv) ++{ ++ char msg[256]; ++ char mech[MECHANISM_BUFSIZE]; ++ char shKey[32]; ++ NSSAuditSeverity severity = (rv == CKR_OK) ? NSS_AUDIT_INFO : NSS_AUDIT_ERROR; ++ ++ sftk_PrintMechanism(mech, sizeof mech, pMechanism); ++ sftk_PrintReturnedObjectHandle(shKey, sizeof shKey, "phKey", phKey, rv); ++ PR_snprintf(msg, sizeof msg, ++ "C_Decapsulate(hSession=0x%08lX, pMechanism=%s, " ++ "hPrivateKey=0x%08lX, pCipherText=%p, ulCiphertextLen=%lu,", ++ "pTemplate=%p, ulAttributeCount=%lu, phKey=%p)=0x%08lX%s", ++ (PRUint32)hSession, mech, ++ (PRUint32)hPrivateKey, pCiphertext, (PRUint32)ulCiphertextLen, ++ pTemplate, (PRUint32)ulAttributeCount, phKey, (PRUint32)rv, shKey); ++ sftk_LogAuditMessage(severity, NSS_AUDIT_DECAPSULATE_KEY, msg); ++} +diff -up ./lib/softoken/fipstokn.c.mlkem ./lib/softoken/fipstokn.c +--- ./lib/softoken/fipstokn.c.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/softoken/fipstokn.c 2024-10-31 14:54:15.467515982 -0700 +@@ -24,6 +24,7 @@ + #include "pkcs11i.h" + #include "prenv.h" + #include "prprf.h" ++#include "kem.h" + + #include + +@@ -261,6 +262,30 @@ static CK_FUNCTION_LIST_3_0 sftk_fipsTab + + }; + ++CK_RV FC_Encapsulate(CK_SESSION_HANDLE hSession, ++ CK_MECHANISM_PTR pMechanism, ++ CK_OBJECT_HANDLE hPublicKey, ++ CK_ATTRIBUTE_PTR pTemplate, ++ CK_ULONG ulAttributeCount, ++ CK_OBJECT_HANDLE_PTR phKey, ++ CK_BYTE_PTR pCiphertext, ++ CK_ULONG_PTR pulCiphertextLen); ++ ++CK_RV FC_Decapsulate(CK_SESSION_HANDLE hSession, ++ CK_MECHANISM_PTR pMechanism, ++ CK_OBJECT_HANDLE hPrivateKey, ++ CK_BYTE_PTR pCiphertext, ++ CK_ULONG ulCiphertextLen, ++ CK_ATTRIBUTE_PTR pTemplate, ++ CK_ULONG ulAttributeCount, ++ CK_OBJECT_HANDLE_PTR phKey); ++ ++CK_NSS_KEM_FUNCTIONS sftk_fips_kem_funcList = { ++ { 1, 0 }, ++ FC_Encapsulate, ++ FC_Decapsulate ++}; ++ + /* forward declaration of special GetInfo functions */ + CK_RV FC_GetInfoV2(CK_INFO_PTR pInfo); + CK_RV NSC_GetInfoV2(CK_INFO_PTR pInfo); +@@ -302,10 +327,11 @@ static CK_INTERFACE fips_interfaces[] = + { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_fipsTable, NSS_INTERFACE_FLAGS }, + { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_fipsTable_v2, NSS_INTERFACE_FLAGS }, + { (CK_UTF8CHAR_PTR) "Vendor NSS Module Interface", &sftk_module_funcList, NSS_INTERFACE_FLAGS }, +- { (CK_UTF8CHAR_PTR) "Vendor NSS FIPS Interface", &sftk_fips_funcList, NSS_INTERFACE_FLAGS } ++ { (CK_UTF8CHAR_PTR) "Vendor NSS FIPS Interface", &sftk_fips_funcList, NSS_INTERFACE_FLAGS }, ++ { (CK_UTF8CHAR_PTR) "Vendor NSS KEM Interface", &sftk_fips_kem_funcList, NSS_INTERFACE_FLAGS } + }; + /* must match the count of interfaces in fips_interfaces above*/ +-#define FIPS_INTERFACE_COUNT 4 ++#define FIPS_INTERFACE_COUNT 5 + + /* CKO_NOT_A_KEY can be any object class that's not a key object. */ + #define CKO_NOT_A_KEY CKO_DATA +@@ -350,6 +376,8 @@ sftk_mapLinuxAuditType(NSSAuditSeverity + case NSS_AUDIT_LOAD_KEY: + case NSS_AUDIT_UNWRAP_KEY: + case NSS_AUDIT_WRAP_KEY: ++ case NSS_AUDIT_ENCAPSULATE_KEY: ++ case NSS_AUDIT_DECAPSULATE_KEY: + return AUDIT_CRYPTO_KEY_USER; + case NSS_AUDIT_CRYPT: + return (severity == NSS_AUDIT_ERROR) ? AUDIT_CRYPTO_FAILURE_USER : AUDIT_CRYPTO_KEY_USER; +@@ -2078,3 +2106,75 @@ FC_MessageVerifyFinal(CK_SESSION_HANDLE + CHECK_FORK(); + return NSC_MessageVerifyFinal(hSession); + } ++ ++/* ++ * vendor specific encapsulate/decapsulate ++ */ ++CK_RV ++FC_Encapsulate(CK_SESSION_HANDLE hSession, ++ CK_MECHANISM_PTR pMechanism, ++ CK_OBJECT_HANDLE hPublicKey, ++ CK_ATTRIBUTE_PTR pTemplate, ++ CK_ULONG ulAttributeCount, ++ CK_OBJECT_HANDLE_PTR phKey, ++ CK_BYTE_PTR pCiphertext, ++ CK_ULONG_PTR pulCiphertextLen) ++{ ++ CK_BBOOL *boolptr; ++ SFTK_FIPSCHECK(); ++ CHECK_FORK(); ++ ++ /* all secret keys must be sensitive, if the upper level code tries to say ++ * otherwise, reject it. */ ++ boolptr = (CK_BBOOL *)fc_getAttribute(pTemplate, ++ ulAttributeCount, CKA_SENSITIVE); ++ if (boolptr != NULL) { ++ if (!(*boolptr)) { ++ return CKR_ATTRIBUTE_VALUE_INVALID; ++ } ++ } ++ ++ rv = NSC_Encapsulate(hSession, pMechanism, hPublicKey, pTemplate, ++ ulAttributeCount, phKey, pCiphertext, ++ pulCiphertextLen); ++ if (sftk_audit_enabled) { ++ sftk_AuditEncapsulate(hSession, pMechanism, hPublicKey, pTemplate, ++ ulAttributeCount, phKey, pCiphertext, ++ pulCiphertextLen, rv); ++ } ++ return rv; ++} ++ ++CK_RV ++FC_Decapsulate(CK_SESSION_HANDLE hSession, ++ CK_MECHANISM_PTR pMechanism, ++ CK_OBJECT_HANDLE hPrivateKey, ++ CK_BYTE_PTR pCiphertext, ++ CK_ULONG ulCiphertextLen, ++ CK_ATTRIBUTE_PTR pTemplate, ++ CK_ULONG ulAttributeCount, ++ CK_OBJECT_HANDLE_PTR phKey) ++{ ++ CK_BBOOL *boolptr; ++ SFTK_FIPSCHECK(); ++ CHECK_FORK(); ++ ++ /* all secret keys must be sensitive, if the upper level code tries to say ++ * otherwise, reject it. */ ++ boolptr = (CK_BBOOL *)fc_getAttribute(pTemplate, ++ ulAttributeCount, CKA_SENSITIVE); ++ if (boolptr != NULL) { ++ if (!(*boolptr)) { ++ return CKR_ATTRIBUTE_VALUE_INVALID; ++ } ++ } ++ ++ rv = NSC_Decapsulate(hSession, pMechanism, hPrivateKey, pCiphertext, ++ ulCiphertextLen, pTemplate, ulAttributeCount, phKey); ++ if (sftk_audit_enabled) { ++ sftk_AuditDecapsulate(hSession, pMechanism, hPrivateKey, pCiphertext, ++ ulCiphertextLen, pTemplate, ulAttributeCount, ++ phKey, rv); ++ } ++ return rv; ++} +diff -up ./lib/softoken/kem.c.mlkem ./lib/softoken/kem.c +--- ./lib/softoken/kem.c.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/softoken/kem.c 2024-10-31 14:54:15.467515982 -0700 +@@ -6,6 +6,7 @@ + #include "kem.h" + #include "pkcs11i.h" + #include "pkcs11n.h" ++#include "secerr.h" + #include "secitem.h" + #include "secport.h" + #include "softoken.h" +@@ -14,8 +15,8 @@ KyberParams + sftk_kyber_PK11ParamToInternal(CK_NSS_KEM_PARAMETER_SET_TYPE pk11ParamSet) + { + switch (pk11ParamSet) { +- case CKP_NSS_KYBER_768_ROUND3: +- return params_kyber768_round3; ++ case CKP_NSS_ML_KEM_768: ++ return params_ml_kem768; + default: + return params_kyber_invalid; + } +@@ -27,6 +28,8 @@ sftk_kyber_AllocPubKeyItem(KyberParams p + switch (params) { + case params_kyber768_round3: + case params_kyber768_round3_test_mode: ++ case params_ml_kem768: ++ case params_ml_kem768_test_mode: + return SECITEM_AllocItem(NULL, pubkey, KYBER768_PUBLIC_KEY_BYTES); + default: + return NULL; +@@ -39,6 +42,8 @@ sftk_kyber_AllocPrivKeyItem(KyberParams + switch (params) { + case params_kyber768_round3: + case params_kyber768_round3_test_mode: ++ case params_ml_kem768: ++ case params_ml_kem768_test_mode: + return SECITEM_AllocItem(NULL, privkey, KYBER768_PRIVATE_KEY_BYTES); + default: + return NULL; +@@ -51,6 +56,8 @@ sftk_kyber_AllocCiphertextItem(KyberPara + switch (params) { + case params_kyber768_round3: + case params_kyber768_round3_test_mode: ++ case params_ml_kem768: ++ case params_ml_kem768_test_mode: + return SECITEM_AllocItem(NULL, ciphertext, KYBER768_CIPHERTEXT_BYTES); + default: + return NULL; +@@ -64,7 +71,7 @@ sftk_kyber_ValidateParams(const CK_NSS_K + return PR_FALSE; + } + switch (*params) { +- case CKP_NSS_KYBER_768_ROUND3: ++ case CKP_NSS_ML_KEM_768: + return PR_TRUE; + default: + return PR_FALSE; +@@ -78,7 +85,7 @@ sftk_kem_ValidateMechanism(CK_MECHANISM_ + return PR_FALSE; + } + switch (pMechanism->mechanism) { +- case CKM_NSS_KYBER: ++ case CKM_NSS_ML_KEM: + return pMechanism->ulParameterLen == sizeof(CK_NSS_KEM_PARAMETER_SET_TYPE) && sftk_kyber_ValidateParams(pMechanism->pParameter); + default: + return PR_FALSE; +@@ -88,14 +95,17 @@ sftk_kem_ValidateMechanism(CK_MECHANISM_ + static CK_ULONG + sftk_kem_CiphertextLen(CK_MECHANISM_PTR pMechanism) + { +- /* Assumes pMechanism has been validated with sftk_kem_ValidateMechanism */ +- if (pMechanism->mechanism != CKM_NSS_KYBER) { ++#ifdef DEBUG ++ if (!sftk_kem_ValidateMechanism(pMechanism)) { + PORT_Assert(0); + return 0; + } ++#endif ++ ++ /* Assumes pMechanism has been validated with sftk_kem_ValidateMechanism */ + CK_NSS_KEM_PARAMETER_SET_TYPE *pParameterSet = pMechanism->pParameter; + switch (*pParameterSet) { +- case CKP_NSS_KYBER_768_ROUND3: ++ case CKP_NSS_ML_KEM_768: + return KYBER768_CIPHERTEXT_BYTES; + default: + /* unreachable if pMechanism has been validated */ +@@ -185,14 +195,17 @@ NSC_Encapsulate(CK_SESSION_HANDLE hSessi + uint8_t secretBuf[KYBER_SHARED_SECRET_BYTES] = { 0 }; + SECItem secret = { siBuffer, secretBuf, sizeof secretBuf }; + ++ key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_ENCAPSULATE, key, 0); ++ key->source = SFTK_SOURCE_KEM; ++ + switch (pMechanism->mechanism) { +- case CKM_NSS_KYBER: { ++ case CKM_NSS_ML_KEM: + PORT_Assert(secret.len == KYBER_SHARED_SECRET_BYTES); + CK_NSS_KEM_PARAMETER_SET_TYPE *pParameter = pMechanism->pParameter; + KyberParams kyberParams = sftk_kyber_PK11ParamToInternal(*pParameter); + SECStatus rv = Kyber_Encapsulate(kyberParams, /* seed */ NULL, &pubKey, &ciphertext, &secret); + if (rv != SECSuccess) { +- crv = CKR_FUNCTION_FAILED; ++ crv = (PORT_GetError() == SEC_ERROR_INVALID_ARGS) ? CKR_ARGUMENTS_BAD : CKR_FUNCTION_FAILED; + goto cleanup; + } + +@@ -210,26 +223,26 @@ NSC_Encapsulate(CK_SESSION_HANDLE hSessi + *phKey = key->handle; + *pulCiphertextLen = ciphertext.len; + break; +- } + default: + crv = CKR_MECHANISM_INVALID; + goto cleanup; + } + + cleanup: ++ PORT_Memset(secretBuf, 0, sizeof(secretBuf)); + if (session) { + sftk_FreeSession(session); + } + if (key) { + status = sftk_FreeObject(key); + if (status == SFTK_DestroyFailure) { +- return CKR_DEVICE_ERROR; ++ crv = CKR_DEVICE_ERROR; + } + } + if (encapsulationKeyObject) { + status = sftk_FreeObject(encapsulationKeyObject); + if (status == SFTK_DestroyFailure) { +- return CKR_DEVICE_ERROR; ++ crv = CKR_DEVICE_ERROR; + } + } + if (encapsulationKey) { +@@ -315,14 +328,17 @@ NSC_Decapsulate(CK_SESSION_HANDLE hSessi + uint8_t secretBuf[KYBER_SHARED_SECRET_BYTES] = { 0 }; + SECItem secret = { siBuffer, secretBuf, sizeof secretBuf }; + ++ key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_DECAPSULATE, key, 0); ++ key->source = SFTK_SOURCE_KEM; ++ + switch (pMechanism->mechanism) { +- case CKM_NSS_KYBER: { ++ case CKM_NSS_ML_KEM: + PORT_Assert(secret.len == KYBER_SHARED_SECRET_BYTES); + CK_NSS_KEM_PARAMETER_SET_TYPE *pParameter = pMechanism->pParameter; + KyberParams kyberParams = sftk_kyber_PK11ParamToInternal(*pParameter); + SECStatus rv = Kyber_Decapsulate(kyberParams, &privKey, &ciphertext, &secret); + if (rv != SECSuccess) { +- crv = CKR_FUNCTION_FAILED; ++ crv = (PORT_GetError() == SEC_ERROR_INVALID_ARGS) ? CKR_ARGUMENTS_BAD : CKR_FUNCTION_FAILED; + goto cleanup; + } + +@@ -337,26 +353,26 @@ NSC_Decapsulate(CK_SESSION_HANDLE hSessi + } + *phKey = key->handle; + break; +- } + default: + crv = CKR_MECHANISM_INVALID; + goto cleanup; + } + + cleanup: ++ PORT_Memset(secretBuf, 0, sizeof(secretBuf)); + if (session) { + sftk_FreeSession(session); + } + if (key) { + status = sftk_FreeObject(key); + if (status == SFTK_DestroyFailure) { +- return CKR_DEVICE_ERROR; ++ crv = CKR_DEVICE_ERROR; + } + } + if (decapsulationKeyObject) { + status = sftk_FreeObject(decapsulationKeyObject); + if (status == SFTK_DestroyFailure) { +- return CKR_DEVICE_ERROR; ++ crv = CKR_DEVICE_ERROR; + } + } + if (decapsulationKey) { +diff -up ./lib/softoken/pkcs11c.c.mlkem ./lib/softoken/pkcs11c.c +--- ./lib/softoken/pkcs11c.c.mlkem 2024-10-31 14:54:15.453515825 -0700 ++++ ./lib/softoken/pkcs11c.c 2024-10-31 14:54:15.467515982 -0700 +@@ -5825,8 +5825,12 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS + break; + + case CKM_NSS_KYBER_KEY_PAIR_GEN: ++ crv = CKR_MECHANISM_INVALID; ++ break; ++ ++ case CKM_NSS_ML_KEM_KEY_PAIR_GEN: + sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); +- key_type = CKK_NSS_KYBER; ++ key_type = CKK_NSS_ML_KEM; + + SECItem privKey = { siBuffer, NULL, 0 }; + SECItem pubKey = { siBuffer, NULL, 0 }; +@@ -6009,7 +6013,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS + &cktrue, sizeof(CK_BBOOL)); + } + +- if (crv == CKR_OK && key_type != CKK_NSS_KYBER) { ++ if (crv == CKR_OK && key_type != CKK_NSS_ML_KEM) { + /* Perform FIPS 140-2 pairwise consistency check. */ + crv = sftk_PairwiseConsistencyCheck(hSession, slot, + publicKey, privateKey, key_type); +@@ -7255,6 +7259,7 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_ + HMACContext *hmac; + unsigned int bufLen; + SFTKSource saltKeySource = SFTK_SOURCE_DEFAULT; ++ SFTKSource saltKeyIsFIPS = PR_FALSE; + + switch (params->ulSaltType) { + case CKF_HKDF_SALT_NULL: +@@ -7293,6 +7298,7 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_ + keySize*PR_BITS_PER_BYTE); + } + saltKeySource = saltKey->source; ++ saltKeyIsFIPS = saltKey->isFIPS; + saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE); + if (saltKey_att == NULL) { + sftk_FreeObject(saltKey); +@@ -7310,9 +7316,10 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_ + * turn off the FIPS indicator for other usages */ + if (isFIPS && key && sourceKey) { + PRBool fipsOK = PR_FALSE; +- /* case one: mix the kea with a previous or default ++ /* case one: mix the kea/kem with a previous or default + * salt */ +- if ((sourceKey->source == SFTK_SOURCE_KEA) && ++ if (((sourceKey->source == SFTK_SOURCE_KEA) || ++ (sourceKey->source == SFTK_SOURCE_KEM)) && + (saltKeySource == SFTK_SOURCE_HKDF_EXPAND) && + (saltLen == rawHash->length)) { + fipsOK = PR_TRUE; +@@ -7322,7 +7329,7 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_ + (NSS_SecureMemcmpZero(sourceKeyBytes, sourceKeyLen) == 0) && + (sourceKeyLen == rawHash->length) && + (saltKeySource == SFTK_SOURCE_HKDF_EXPAND) && +- (saltLen == rawHash->length)) { ++ (saltLen == rawHash->length) && saltKeyIsFIPS) { + fipsOK = PR_TRUE; + } + if (!fipsOK) { +@@ -8476,6 +8483,8 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession + + crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); + PORT_ZFree(buf, tmpKeySize); ++ /* preserve the source of the original base key */ ++ key->source = sourceKey->source; + sftk_FreeAttribute(att2); + sftk_FreeObject(paramKey); + break; +diff -up ./lib/softoken/pkcs11.c.mlkem ./lib/softoken/pkcs11.c +--- ./lib/softoken/pkcs11.c.mlkem 2024-10-31 14:54:15.453515825 -0700 ++++ ./lib/softoken/pkcs11.c 2024-10-31 14:54:15.468515993 -0700 +@@ -648,9 +648,9 @@ static const struct mechanismList mechan + { CKM_NSS_IKE_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE }, + { CKM_NSS_IKE1_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE }, + { CKM_NSS_IKE1_APP_B_PRF_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE }, +- /* -------------------- Kyber Operations ----------------------- */ +- { CKM_NSS_KYBER_KEY_PAIR_GEN, { 0, 0, CKF_GENERATE_KEY_PAIR }, PR_TRUE }, +- { CKM_NSS_KYBER, { 0, 0, 0 }, PR_TRUE }, ++ /* -------------------- ML KEM Operations ----------------------- */ ++ { CKM_NSS_ML_KEM_KEY_PAIR_GEN, { 0, 0, CKF_GENERATE_KEY_PAIR }, PR_TRUE }, ++ { CKM_NSS_ML_KEM, { 0, 0, 0 }, PR_TRUE }, + }; + static const CK_ULONG mechanismCount = sizeof(mechanisms) / sizeof(mechanisms[0]); + +@@ -1096,6 +1096,7 @@ sftk_handlePublicKeyObject(SFTKSession * + wrap = CK_FALSE; + break; + case CKK_NSS_KYBER: ++ case CKK_NSS_ML_KEM: + if (!sftk_hasAttribute(object, CKA_NSS_PARAMETER_SET)) { + return CKR_TEMPLATE_INCOMPLETE; + } +@@ -1309,6 +1310,7 @@ sftk_handlePrivateKeyObject(SFTKSession + createObjectInfo = PR_FALSE; + break; + case CKK_NSS_KYBER: ++ case CKK_NSS_ML_KEM: + if (!sftk_hasAttribute(object, CKA_KEY_TYPE)) { + return CKR_TEMPLATE_INCOMPLETE; + } +@@ -2002,6 +2004,7 @@ sftk_GetPubKey(SFTKObject *object, CK_KE + } + break; + case CKK_NSS_KYBER: ++ case CKK_NSS_ML_KEM: + crv = CKR_OK; + break; + default: +@@ -2160,6 +2163,7 @@ sftk_mkPrivKey(SFTKObject *object, CK_KE + break; + + case CKK_NSS_KYBER: ++ case CKK_NSS_ML_KEM: + break; + + default: +diff -up ./lib/softoken/pkcs11i.h.mlkem ./lib/softoken/pkcs11i.h +--- ./lib/softoken/pkcs11i.h.mlkem 2024-10-31 14:54:15.433515602 -0700 ++++ ./lib/softoken/pkcs11i.h 2024-10-31 14:54:15.468515993 -0700 +@@ -157,6 +157,7 @@ typedef enum { + typedef enum { + SFTK_SOURCE_DEFAULT=0, + SFTK_SOURCE_KEA, ++ SFTK_SOURCE_KEM, + SFTK_SOURCE_HKDF_EXPAND, + SFTK_SOURCE_HKDF_EXTRACT + } SFTKSource; +diff -up ./lib/softoken/softoken.h.mlkem ./lib/softoken/softoken.h +--- ./lib/softoken/softoken.h.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/softoken/softoken.h 2024-10-31 14:54:15.468515993 -0700 +@@ -137,6 +137,24 @@ extern void sftk_AuditDeriveKey(CK_SESSI + extern void sftk_AuditDigestKey(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hKey, CK_RV rv); + ++extern void sftk_AuditEncapsulate(CK_SESSION_HANDLE hSession, ++ CK_MECHANISM_PTR pMechanism, ++ CK_OBJECT_HANDLE hPublicKey, ++ CK_ATTRIBUTE_PTR pTemplate, ++ CK_ULONG ulAttributeCount, ++ CK_OBJECT_HANDLE_PTR phKey, ++ CK_BYTE_PTR pCiphertext, ++ CK_ULONG_PTR pulCiphertextLen, CK_RV rv); ++ ++extern void sftk_AuditDecapsulate(CK_SESSION_HANDLE hSession, ++ CK_MECHANISM_PTR pMechanism, ++ CK_OBJECT_HANDLE hPrivateKey, ++ CK_BYTE_PTR pCiphertext, ++ CK_ULONG ulCiphertextLen, ++ CK_ATTRIBUTE_PTR pTemplate, ++ CK_ULONG ulAttributeCount, ++ CK_OBJECT_HANDLE_PTR phKey, CK_RV rv); ++ + /* + ** FIPS 140-2 Error state + */ +diff -up ./lib/softoken/softoknt.h.mlkem ./lib/softoken/softoknt.h +--- ./lib/softoken/softoknt.h.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/softoken/softoknt.h 2024-10-31 14:54:15.468515993 -0700 +@@ -40,7 +40,9 @@ typedef enum { + NSS_AUDIT_SELF_TEST, + NSS_AUDIT_SET_PIN, + NSS_AUDIT_UNWRAP_KEY, +- NSS_AUDIT_WRAP_KEY ++ NSS_AUDIT_WRAP_KEY, ++ NSS_AUDIT_ENCAPSULATE_KEY, ++ NSS_AUDIT_DECAPSULATE_KEY + } NSSAuditType; + + #endif /* _SOFTOKNT_H_ */ +diff -up ./lib/ssl/sslimpl.h.mlkem ./lib/ssl/sslimpl.h +--- ./lib/ssl/sslimpl.h.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/ssl/sslimpl.h 2024-10-31 14:54:15.468515993 -0700 +@@ -130,7 +130,7 @@ typedef enum { SSLAppOpRead = 0, + #define DTLS_RETRANSMIT_FINISHED_MS 30000 + + /* default number of entries in namedGroupPreferences */ +-#define SSL_NAMED_GROUP_COUNT 32 ++#define SSL_NAMED_GROUP_COUNT 33 + + /* The maximum DH and RSA bit-length supported. */ + #define SSL_MAX_DH_KEY_BITS 8192 +diff -up ./lib/ssl/sslsock.c.mlkem ./lib/ssl/sslsock.c +--- ./lib/ssl/sslsock.c.mlkem 2024-10-31 14:54:15.419515446 -0700 ++++ ./lib/ssl/sslsock.c 2024-10-31 14:54:15.468515993 -0700 +@@ -22,6 +22,7 @@ + #include "tls13ech.h" + #include "tls13psk.h" + #include "tls13subcerts.h" ++#include "secmodti.h" /* until SEC_OID_MLKEM768SECP256R1 is upstream */ + + static const sslSocketOps ssl_default_ops = { /* No SSL. */ + ssl_DefConnect, +@@ -159,15 +160,21 @@ static const PRUint16 srtpCiphers[] = { + ssl_grp_ffdhe_##size, size, ssl_kea_dh, \ + SEC_OID_TLS_FFDHE_##size, PR_TRUE \ + } ++#define HYGROUP(kem, ec, size, kem_oid, ec_oid, assumeSupported) \ ++ { \ ++ ssl_grp_kem_##kem##ec, size, ssl_kea_ecdh_hybrid, \ ++ SEC_OID_##kem_oid##ec_oid, assumeSupported \ ++ } + + const sslNamedGroupDef ssl_named_groups[] = { +- /* Note that 256 for 25519 is a lie, but we only use it for checking bit +- * security and expect 256 bits there (not 255). */ ++ /* Note that 256 for 25519 and hybrid is a lie, but we only use it for ++ * checking bit security and expect 256 bits there (not 255). */ ++ HYGROUP(mlkem768, x25519, 256, MLKEM768, X25519, PR_TRUE), + { ssl_grp_ec_curve25519, 256, ssl_kea_ecdh, SEC_OID_CURVE25519, PR_TRUE }, ++ HYGROUP(mlkem768, secp256r1, 256, MLKEM768, SECP256R1, PR_TRUE), + ECGROUP(secp256r1, 256, SECP256R1, PR_TRUE), + ECGROUP(secp384r1, 384, SECP384R1, PR_TRUE), + ECGROUP(secp521r1, 521, SECP521R1, PR_TRUE), +- { ssl_grp_kem_xyber768d00, 256, ssl_kea_ecdh_hybrid, SEC_OID_XYBER768D00, PR_TRUE }, + FFGROUP(2048), + FFGROUP(3072), + FFGROUP(4096), +diff -up ./lib/ssl/sslt.h.mlkem ./lib/ssl/sslt.h +--- ./lib/ssl/sslt.h.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/ssl/sslt.h 2024-10-31 14:54:15.469516004 -0700 +@@ -260,7 +260,8 @@ typedef enum { + ssl_grp_ffdhe_4096 = 258, + ssl_grp_ffdhe_6144 = 259, + ssl_grp_ffdhe_8192 = 260, +- ssl_grp_kem_xyber768d00 = 25497, /* draft-tls-westerbaan-xyber768d00-02 */ ++ ssl_grp_kem_mlkem768x25519 = 4588, ++ ssl_grp_kem_mlkem768secp256r1 = 4587, + ssl_grp_none = 65537, /* special value */ + ssl_grp_ffdhe_custom = 65538 /* special value */ + } SSLNamedGroup; +diff -up ./lib/ssl/tls13con.c.mlkem ./lib/ssl/tls13con.c +--- ./lib/ssl/tls13con.c.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/ssl/tls13con.c 2024-10-31 16:03:17.443439047 -0700 +@@ -374,16 +374,24 @@ tls13_CreateKEMKeyPair(sslSocket *ss, co + sslKeyPair **outKeyPair) + { + PORT_Assert(groupDef); +- if (groupDef->name != ssl_grp_kem_xyber768d00) { +- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); +- return SECFailure; +- } + + sslKeyPair *keyPair = NULL; + SECKEYPrivateKey *privKey = NULL; + SECKEYPublicKey *pubKey = NULL; +- CK_MECHANISM_TYPE mechanism = CKM_NSS_KYBER_KEY_PAIR_GEN; +- CK_NSS_KEM_PARAMETER_SET_TYPE paramSet = CKP_NSS_KYBER_768_ROUND3; ++ CK_MECHANISM_TYPE mechanism; ++ CK_NSS_KEM_PARAMETER_SET_TYPE paramSet; ++ ++ switch (groupDef->name) { ++ case ssl_grp_kem_mlkem768x25519: ++ case ssl_grp_kem_mlkem768secp256r1: ++ mechanism = CKM_NSS_ML_KEM_KEY_PAIR_GEN; ++ paramSet = CKP_NSS_ML_KEM_768; ++ break; ++ default: ++ PORT_Assert(0); ++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); ++ return SECFailure; ++ } + + PK11SlotInfo *slot = PK11_GetBestSlot(mechanism, ss->pkcs11PinArg); + if (!slot) { +@@ -430,6 +438,76 @@ loser: + return SECFailure; + } + ++/* only copy the ECDh component of an ephemeral KeyPair */ ++sslEphemeralKeyPair * ++tls13_CopyDHEphemeralKeyPair(sslEphemeralKeyPair *copyKeyPair, ++ const sslNamedGroupDef *groupDef) { ++ /* We could use ssl_CopyEphemeralKeyPair here, but we would need to free ++ * the KEM components. So we only copy the ECDH keys */ ++ sslEphemeralKeyPair *keyPair = PORT_ZNew(sslEphemeralKeyPair); ++ if (!keyPair) { ++ return NULL; ++ } ++ PR_INIT_CLIST(&keyPair->link); ++ keyPair->group = groupDef; ++ keyPair->keys = ssl_GetKeyPairRef(copyKeyPair->keys); ++ return keyPair; ++} ++ ++/* ++ * find a hybrid key Pair they might contain the same ecdh key so we ++ * can reuse them. Each ec group can map to more than one hybrid Pair ++ */ ++sslEphemeralKeyPair * ++tls13_FindHybridKeyPair(sslSocket *ss, const sslNamedGroupDef *groupDef) ++{ ++ sslEphemeralKeyPair *hybridPair = NULL; ++ switch (groupDef->name) { ++ case ssl_grp_ec_secp256r1: ++ /* future, this may be a loop to check multiple named groups */ ++ hybridPair = ssl_LookupEphemeralKeyPair(ss, ++ ssl_LookupNamedGroup(ssl_grp_kem_mlkem768secp256r1)); ++ break; ++ case ssl_grp_ec_curve25519: ++ /* future, this will be a loop to check multiple named groups */ ++ hybridPair = ssl_LookupEphemeralKeyPair(ss, ++ ssl_LookupNamedGroup(ssl_grp_kem_mlkem768x25519)); ++ break; ++ default: ++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); ++ return NULL; ++ } ++ return hybridPair; ++} ++ ++/* ++ * Find a corresponding KEM form another hybrid key ++ */ ++#ifdef notdef ++sslKeyPair * ++tls13_FindKEMKeyPairFromHybrid(sslSocket *ss, const sslNamedGroupDef *groupDef) ++{ ++ sslEphemeralKeyPair *hybridPair = NULL; ++ switch (groupDef->name) { ++ case ssl_grp_kem_mlkem768x25519: ++ /* future, this may be a loop to check multiple named groups */ ++ hybridPair = ssl_LookupEphemeralKeyPair(ss, ++ ssl_LookupNamedGroup(ssl_grp_kem_mlkem768secp256r1)); ++ break; ++ case ssl_grp_kem_mlkem768secp256r1: ++ /* future, this will be a loop to check multiple named groups */ ++ hybridPair = ssl_LookupEphemeralKeyPair(ss, ++ ssl_LookupNamedGroup(ssl_grp_kem_mlkem768x25519)); ++ break; ++ default: ++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); ++ return NULL; ++ } ++ return hybridPair->kemKeys; ++} ++#endif ++ ++ + SECStatus + tls13_CreateKeyShare(sslSocket *ss, const sslNamedGroupDef *groupDef, + sslEphemeralKeyPair **outKeyPair) +@@ -437,24 +515,48 @@ tls13_CreateKeyShare(sslSocket *ss, cons + SECStatus rv; + const ssl3DHParams *params; + sslEphemeralKeyPair *keyPair = NULL; ++ const sslNamedGroupDef *dhGroup = NULL; + + PORT_Assert(groupDef); + switch (groupDef->keaType) { + case ssl_kea_ecdh_hybrid: +- if (groupDef->name != ssl_grp_kem_xyber768d00) { ++ switch (groupDef->name) { ++ case ssl_grp_kem_mlkem768secp256r1: ++ dhGroup = ssl_LookupNamedGroup(ssl_grp_ec_secp256r1); ++ break; ++ case ssl_grp_kem_mlkem768x25519: ++ dhGroup = ssl_LookupNamedGroup(ssl_grp_ec_curve25519); ++ break; ++ default: + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } +- rv = ssl_CreateECDHEphemeralKeyPair(ss, ssl_LookupNamedGroup(ssl_grp_ec_curve25519), &keyPair); +- if (rv != SECSuccess) { ++ if (dhGroup == NULL) { ++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } ++ keyPair = ssl_LookupEphemeralKeyPair(ss, dhGroup); ++ if (keyPair) { ++ keyPair= ssl_CopyEphemeralKeyPair(keyPair); ++ } ++ if (!keyPair) { ++ rv = ssl_CreateECDHEphemeralKeyPair(ss, dhGroup, &keyPair); ++ if (rv != SECSuccess) { ++ return SECFailure; ++ } ++ } + keyPair->group = groupDef; + break; + case ssl_kea_ecdh: +- rv = ssl_CreateECDHEphemeralKeyPair(ss, groupDef, &keyPair); +- if (rv != SECSuccess) { +- return SECFailure; ++ keyPair = tls13_FindHybridKeyPair(ss, groupDef); ++ if (keyPair) { ++ keyPair = tls13_CopyDHEphemeralKeyPair(keyPair, groupDef); ++ } ++ if (!keyPair) { ++ rv = ssl_CreateECDHEphemeralKeyPair(ss, groupDef, &keyPair); ++ if (rv != SECSuccess) { ++ return SECFailure; ++ } + } + break; + case ssl_kea_dh: +@@ -474,11 +576,27 @@ tls13_CreateKeyShare(sslSocket *ss, cons + // If we're creating an ECDH + KEM hybrid share and we're the client, then + // we still need to generate the KEM key pair. Otherwise we're done. + if (groupDef->keaType == ssl_kea_ecdh_hybrid && !ss->sec.isServer) { ++#ifdef notdef ++ sslKeyPair *kemPair = NULL; ++ kemPair = tls13_FindKEMKeyPairFromHybrid(ss, groupDef); ++ if (kemPair) { ++ kemPair = ssl_GetKeyPairRef(kemPair); ++ } ++ if (!kemPair) { ++ rv = tls13_CreateKEMKeyPair(ss, groupDef, &kemPair); ++ if (rv != SECSuccess) { ++ ssl_FreeEphemeralKeyPair(keyPair); ++ return SECFailure; ++ } ++ } ++ keyPair->kemKeys = kemPair; ++#else + rv = tls13_CreateKEMKeyPair(ss, groupDef, &keyPair->kemKeys); + if (rv != SECSuccess) { + ssl_FreeEphemeralKeyPair(keyPair); + return SECFailure; + } ++#endif + } + + *outKeyPair = keyPair; +@@ -658,21 +776,45 @@ tls13_ImportKEMKeyShare(SECKEYPublicKey + { + SECItem pk = { siBuffer, NULL, 0 }; + SECStatus rv; ++ size_t expected_len; + +- if (entry->group->name != ssl_grp_kem_xyber768d00) { +- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); +- return SECFailure; ++ switch (entry->group->name) { ++ case ssl_grp_kem_mlkem768secp256r1: ++ expected_len = SECP256_PUBLIC_KEY_BYTES + KYBER768_PUBLIC_KEY_BYTES; ++ break; ++ case ssl_grp_kem_mlkem768x25519: ++ expected_len = X25519_PUBLIC_KEY_BYTES + KYBER768_PUBLIC_KEY_BYTES; ++ break; ++ default: ++ PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); ++ return SECFailure; + } + +- if (entry->key_exchange.len != X25519_PUBLIC_KEY_BYTES + KYBER768_PUBLIC_KEY_BYTES) { ++ if (entry->key_exchange.len != expected_len) { + PORT_SetError(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE); + return SECFailure; + } +- pk.data = entry->key_exchange.data + X25519_PUBLIC_KEY_BYTES; +- pk.len = entry->key_exchange.len - X25519_PUBLIC_KEY_BYTES; + +- peerKey->keyType = kyberKey; +- peerKey->u.kyber.params = params_kyber768_round3; ++ switch (entry->group->name) { ++ case ssl_grp_kem_mlkem768secp256r1: ++ peerKey->keyType = kyberKey; ++ peerKey->u.kyber.params = params_ml_kem768; ++ /* key_exchange.data is `secp256 || mlkem768` */ ++ pk.data = entry->key_exchange.data + SECP256_PUBLIC_KEY_BYTES; ++ pk.len = KYBER768_PUBLIC_KEY_BYTES; ++ break; ++ case ssl_grp_kem_mlkem768x25519: ++ peerKey->keyType = kyberKey; ++ peerKey->u.kyber.params = params_ml_kem768; ++ /* key_exchange.data is `mlkem768 || x25519` */ ++ pk.data = entry->key_exchange.data; ++ pk.len = KYBER768_PUBLIC_KEY_BYTES; ++ break; ++ default: ++ PORT_Assert(0); ++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); ++ return SECFailure; ++ } + + rv = SECITEM_CopyItem(peerKey->arena, &peerKey->u.kyber.publicValue, &pk); + if (rv != SECSuccess) { +@@ -690,13 +832,21 @@ tls13_HandleKEMCiphertext(sslSocket *ss, + SECStatus rv; + + switch (entry->group->name) { +- case ssl_grp_kem_xyber768d00: ++ case ssl_grp_kem_mlkem768secp256r1: ++ if (entry->key_exchange.len != SECP256_PUBLIC_KEY_BYTES + KYBER768_CIPHERTEXT_BYTES) { ++ ssl_MapLowLevelError(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE); ++ return SECFailure; ++ } ++ ct.data = entry->key_exchange.data + SECP256_PUBLIC_KEY_BYTES; ++ ct.len = KYBER768_CIPHERTEXT_BYTES; ++ break; ++ case ssl_grp_kem_mlkem768x25519: + if (entry->key_exchange.len != X25519_PUBLIC_KEY_BYTES + KYBER768_CIPHERTEXT_BYTES) { + ssl_MapLowLevelError(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE); + return SECFailure; + } +- ct.data = entry->key_exchange.data + X25519_PUBLIC_KEY_BYTES; +- ct.len = entry->key_exchange.len - X25519_PUBLIC_KEY_BYTES; ++ ct.data = entry->key_exchange.data; ++ ct.len = KYBER768_CIPHERTEXT_BYTES; + break; + default: + PORT_Assert(0); +@@ -736,7 +886,7 @@ tls13_HandleKEMKey(sslSocket *ss, + goto loser; + } + +- PK11SlotInfo *slot = PK11_GetBestSlot(CKM_NSS_KYBER, ss->pkcs11PinArg); ++ PK11SlotInfo *slot = PK11_GetBestSlot(CKM_NSS_ML_KEM, ss->pkcs11PinArg); + if (!slot) { + goto loser; + } +@@ -757,7 +907,7 @@ tls13_HandleKEMKey(sslSocket *ss, + PK11_FreeSlot(peerKey->pkcs11Slot); + + PORT_DestroyCheapArena(&arena); +- return SECSuccess; ++ return rv; + + loser: + PORT_DestroyCheapArena(&arena); +@@ -775,8 +925,11 @@ tls13_HandleKeyShare(sslSocket *ss, + SECKEYPublicKey *peerKey; + CK_MECHANISM_TYPE mechanism; + PK11SymKey *key; ++ unsigned char *ec_data; + SECStatus rv; + int keySize = 0; ++ const sslNamedGroupDef *dhGroup = NULL; ++ int dhLen = 0; + + PORT_InitCheapArena(&arena, DER_DEFAULT_CHUNKSIZE); + peerKey = PORT_ArenaZNew(&arena.arena, SECKEYPublicKey); +@@ -789,14 +942,32 @@ tls13_HandleKeyShare(sslSocket *ss, + + switch (entry->group->keaType) { + case ssl_kea_ecdh_hybrid: +- if (entry->group->name != ssl_grp_kem_xyber768d00 || entry->key_exchange.len < X25519_PUBLIC_KEY_BYTES) { ++ switch (entry->group->name) { ++ case ssl_grp_kem_mlkem768secp256r1: ++ dhLen = SECP256_PUBLIC_KEY_BYTES; ++ /* secp256 share is at the beginning */ ++ ec_data = entry->key_exchange.len < dhLen ++ ? NULL ++ : entry->key_exchange.data; ++ dhGroup = ssl_LookupNamedGroup(ssl_grp_ec_secp256r1); ++ break; ++ case ssl_grp_kem_mlkem768x25519: ++ dhLen = X25519_PUBLIC_KEY_BYTES; ++ /* x25519 share is at the end */ ++ ec_data = entry->key_exchange.len < dhLen ++ ? NULL ++ : entry->key_exchange.data + entry->key_exchange.len - dhLen; ++ dhGroup = ssl_LookupNamedGroup(ssl_grp_ec_curve25519); ++ break; ++ default: ++ ec_data = NULL; ++ break; ++ } ++ if (!ec_data) { + PORT_SetError(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE); + goto loser; + } +- rv = ssl_ImportECDHKeyShare(peerKey, +- entry->key_exchange.data, +- X25519_PUBLIC_KEY_BYTES, +- ssl_LookupNamedGroup(ssl_grp_ec_curve25519)); ++ rv = ssl_ImportECDHKeyShare(peerKey, ec_data, dhLen, dhGroup); + mechanism = CKM_ECDH1_DERIVE; + break; + case ssl_kea_ecdh: +@@ -2665,10 +2836,19 @@ tls13_HandleClientKeyShare(sslSocket *ss + if (rv != SECSuccess) { + goto loser; /* Error set by tls13_HandleKEMKey */ + } +- // We may need to handle different "combiners" here in the future. For +- // now this is specific to xyber768d00. +- PORT_Assert(peerShare->group->name == ssl_grp_kem_xyber768d00); +- ss->ssl3.hs.dheSecret = PK11_ConcatSymKeys(dheSecret, kemSecret, CKM_HKDF_DERIVE, CKA_DERIVE); ++ switch (peerShare->group->name) { ++ case ssl_grp_kem_mlkem768secp256r1: ++ ss->ssl3.hs.dheSecret = PK11_ConcatSymKeys(dheSecret, kemSecret, CKM_HKDF_DERIVE, CKA_DERIVE); ++ break; ++ case ssl_grp_kem_mlkem768x25519: ++ ss->ssl3.hs.dheSecret = PK11_ConcatSymKeys(kemSecret, dheSecret, CKM_HKDF_DERIVE, CKA_DERIVE); ++ break; ++ default: ++ PORT_Assert(0); ++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); ++ ss->ssl3.hs.dheSecret = NULL; ++ break; ++ } + if (!ss->ssl3.hs.dheSecret) { + goto loser; /* Error set by PK11_ConcatSymKeys */ + } +@@ -3512,10 +3692,19 @@ tls13_HandleServerKeyShare(sslSocket *ss + if (rv != SECSuccess) { + goto loser; /* Error set by tls13_HandleKEMCiphertext */ + } +- // We may need to handle different "combiners" here in the future. For +- // now this is specific to xyber768d00. +- PORT_Assert(entry->group->name == ssl_grp_kem_xyber768d00); +- ss->ssl3.hs.dheSecret = PK11_ConcatSymKeys(dheSecret, kemSecret, CKM_HKDF_DERIVE, CKA_DERIVE); ++ switch (entry->group->name) { ++ case ssl_grp_kem_mlkem768secp256r1: ++ ss->ssl3.hs.dheSecret = PK11_ConcatSymKeys(dheSecret, kemSecret, CKM_HKDF_DERIVE, CKA_DERIVE); ++ break; ++ case ssl_grp_kem_mlkem768x25519: ++ ss->ssl3.hs.dheSecret = PK11_ConcatSymKeys(kemSecret, dheSecret, CKM_HKDF_DERIVE, CKA_DERIVE); ++ break; ++ default: ++ PORT_Assert(0); ++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); ++ ss->ssl3.hs.dheSecret = NULL; ++ break; ++ } + if (!ss->ssl3.hs.dheSecret) { + goto loser; /* Error set by PK11_ConcatSymKeys */ + } +diff -up ./lib/ssl/tls13exthandle.c.mlkem ./lib/ssl/tls13exthandle.c +--- ./lib/ssl/tls13exthandle.c.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/ssl/tls13exthandle.c 2024-10-31 14:54:15.469516004 -0700 +@@ -12,6 +12,8 @@ + #include "pk11pub.h" + #include "ssl3ext.h" + #include "ssl3exthandle.h" ++#include "sslt.h" ++#include "tls13con.h" + #include "tls13ech.h" + #include "tls13exthandle.h" + #include "tls13psk.h" +@@ -78,32 +80,77 @@ tls13_SizeOfKeyShareEntry(const sslEphem + + if (keyPair->kemKeys) { + PORT_Assert(!keyPair->kemCt); +- PORT_Assert(keyPair->group->name == ssl_grp_kem_xyber768d00); ++ PORT_Assert(keyPair->group->name == ssl_grp_kem_mlkem768secp256r1 || keyPair->group->name == ssl_grp_kem_mlkem768x25519); + pubKey = keyPair->kemKeys->pubKey; + size += pubKey->u.kyber.publicValue.len; + } + if (keyPair->kemCt) { + PORT_Assert(!keyPair->kemKeys); +- PORT_Assert(keyPair->group->name == ssl_grp_kem_xyber768d00); ++ PORT_Assert(keyPair->group->name == ssl_grp_kem_mlkem768secp256r1 || keyPair->group->name == ssl_grp_kem_mlkem768x25519); + size += keyPair->kemCt->len; + } + + return size; + } + +-SECStatus +-tls13_EncodeKeyShareEntry(sslBuffer *buf, sslEphemeralKeyPair *keyPair) ++static SECStatus ++tls13_WriteMLKEM768Secp256r1KeyExchangeInfo(sslBuffer *buf, sslEphemeralKeyPair *keyPair) + { +- SECStatus rv; +- unsigned int size = tls13_SizeOfKeyShareEntry(keyPair); ++ PORT_Assert(keyPair->group->name == ssl_grp_kem_mlkem768secp256r1); ++ PORT_Assert(keyPair->keys->pubKey->keyType == ecKey); + +- rv = sslBuffer_AppendNumber(buf, keyPair->group->name, 2); +- if (rv != SECSuccess) ++ // Encode the p256 key first, then the Kyber768 key or ciphertext. ++ SECStatus rv; ++ rv = sslBuffer_Append(buf, keyPair->keys->pubKey->u.ec.publicValue.data, ++ keyPair->keys->pubKey->u.ec.publicValue.len); ++ if (rv != SECSuccess) { + return rv; +- rv = sslBuffer_AppendNumber(buf, size - 4, 2); +- if (rv != SECSuccess) ++ } ++ ++ if (keyPair->kemKeys) { ++ PORT_Assert(!keyPair->kemCt); ++ rv = sslBuffer_Append(buf, keyPair->kemKeys->pubKey->u.kyber.publicValue.data, keyPair->kemKeys->pubKey->u.kyber.publicValue.len); ++ } else if (keyPair->kemCt) { ++ rv = sslBuffer_Append(buf, keyPair->kemCt->data, keyPair->kemCt->len); ++ } else { ++ PORT_Assert(0); ++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); ++ rv = SECFailure; ++ } ++ return rv; ++} ++ ++static SECStatus ++tls13_WriteMLKEM768X25519KeyExchangeInfo(sslBuffer *buf, sslEphemeralKeyPair *keyPair) ++{ ++ PORT_Assert(keyPair->group->name == ssl_grp_kem_mlkem768x25519); ++ PORT_Assert(keyPair->keys->pubKey->keyType == ecKey); ++ ++ // Encode the ML-KEM-768 key or ciphertext first, then the X25519 share. ++ SECStatus rv; ++ if (keyPair->kemKeys) { ++ PORT_Assert(!keyPair->kemCt); ++ rv = sslBuffer_Append(buf, keyPair->kemKeys->pubKey->u.kyber.publicValue.data, keyPair->kemKeys->pubKey->u.kyber.publicValue.len); ++ } else if (keyPair->kemCt) { ++ rv = sslBuffer_Append(buf, keyPair->kemCt->data, keyPair->kemCt->len); ++ } else { ++ PORT_Assert(0); ++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); ++ rv = SECFailure; ++ } ++ if (rv != SECSuccess) { + return rv; ++ } ++ ++ rv = sslBuffer_Append(buf, keyPair->keys->pubKey->u.ec.publicValue.data, ++ keyPair->keys->pubKey->u.ec.publicValue.len); ++ return rv; ++} + ++static SECStatus ++tls13_WriteKeyExchangeInfo(sslBuffer *buf, sslEphemeralKeyPair *keyPair) ++{ ++ SECStatus rv; + const SECKEYPublicKey *pubKey = keyPair->keys->pubKey; + switch (pubKey->keyType) { + case ecKey: +@@ -116,25 +163,40 @@ tls13_EncodeKeyShareEntry(sslBuffer *buf + default: + PORT_Assert(0); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); ++ rv = SECFailure; + break; + } + ++ return rv; ++} ++ ++SECStatus ++tls13_EncodeKeyShareEntry(sslBuffer *buf, sslEphemeralKeyPair *keyPair) ++{ ++ SECStatus rv; ++ unsigned int size = tls13_SizeOfKeyShareEntry(keyPair); ++ ++ rv = sslBuffer_AppendNumber(buf, keyPair->group->name, 2); + if (rv != SECSuccess) { + return rv; + } + +- if (keyPair->kemKeys) { +- PORT_Assert(!keyPair->kemCt); +- PORT_Assert(keyPair->group->name == ssl_grp_kem_xyber768d00); +- pubKey = keyPair->kemKeys->pubKey; +- rv = sslBuffer_Append(buf, pubKey->u.kyber.publicValue.data, pubKey->u.kyber.publicValue.len); +- } +- if (keyPair->kemCt) { +- PORT_Assert(!keyPair->kemKeys); +- PORT_Assert(keyPair->group->name == ssl_grp_kem_xyber768d00); +- rv = sslBuffer_Append(buf, keyPair->kemCt->data, keyPair->kemCt->len); ++ rv = sslBuffer_AppendNumber(buf, size - 4, 2); ++ if (rv != SECSuccess) { ++ return rv; + } + ++ switch (keyPair->group->name) { ++ case ssl_grp_kem_mlkem768x25519: ++ rv = tls13_WriteMLKEM768X25519KeyExchangeInfo(buf, keyPair); ++ break; ++ case ssl_grp_kem_mlkem768secp256r1: ++ rv = tls13_WriteMLKEM768Secp256r1KeyExchangeInfo(buf, keyPair); ++ break; ++ default: ++ rv = tls13_WriteKeyExchangeInfo(buf, keyPair); ++ break; ++ } + return rv; + } + +diff -up ./lib/util/eccutil.h.mlkem ./lib/util/eccutil.h +--- ./lib/util/eccutil.h.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/util/eccutil.h 2024-10-31 14:54:15.469516004 -0700 +@@ -6,6 +6,7 @@ + #define _FREEBL_H_ + + #define X25519_PUBLIC_KEY_BYTES 32U ++#define SECP256_PUBLIC_KEY_BYTES 65U + + /* deprecated */ + typedef enum { +diff -up ./lib/util/kyber.h.mlkem ./lib/util/kyber.h +--- ./lib/util/kyber.h.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/util/kyber.h 2024-10-31 14:54:15.469516004 -0700 +@@ -27,6 +27,18 @@ typedef enum { + * the use of a seed in `Kyber_Encapsulate` for testing. + */ + params_kyber768_round3_test_mode, ++ ++ /* ++ * The ML-KEM parameters specified in FIPS 203. ++ * https://csrc.nist.gov/pubs/fips/203/final ++ */ ++ params_ml_kem768, ++ ++ /* ++ * Identical to params_ml_kem768 except that this parameter set allows ++ * the use of a seed in `Kyber_Encapsulate` for testing. ++ */ ++ params_ml_kem768_test_mode, + } KyberParams; + + #endif /* KYBER_UTIL_H */ +diff -up ./lib/util/pkcs11n.h.mlkem ./lib/util/pkcs11n.h +--- ./lib/util/pkcs11n.h.mlkem 2024-10-31 14:54:15.421515468 -0700 ++++ ./lib/util/pkcs11n.h 2024-10-31 14:54:15.469516004 -0700 +@@ -56,6 +56,7 @@ + #define CKK_NSS_CHACHA20 (CKK_NSS + 4) + + #define CKK_NSS_KYBER (CKK_NSS + 5) ++#define CKK_NSS_ML_KEM (CKK_NSS + 6) + + /* + * NSS-defined certificate types +@@ -67,6 +68,8 @@ + #define CKA_DIGEST 0x81000000L + #define CKA_NSS_GENERATE 0x81000001L + #define CKA_NSS_GENERATE_KEY_PAIR 0x81000002L ++#define CKA_NSS_ENCAPSULATE 0x81000003L ++#define CKA_NSS_DECAPSULATE 0x81000004L + #define CKA_NSS_MESSAGE 0x82000000L + #define CKA_NSS_MESSAGE_MASK 0xff000000L + #define CKA_FLAGS_ONLY 0 /* CKA_CLASS */ +@@ -268,6 +271,10 @@ + #define CKM_NSS_KYBER_KEY_PAIR_GEN (CKM_NSS + 45) + #define CKM_NSS_KYBER (CKM_NSS + 46) + ++/* ML-KEM */ ++#define CKM_NSS_ML_KEM_KEY_PAIR_GEN (CKM_NSS + 48) ++#define CKM_NSS_ML_KEM (CKM_NSS + 49) ++ + /* + * HISTORICAL: + * Do not attempt to use these. They are only used by NSS's internal +@@ -290,6 +297,7 @@ + /* Parameter set identifiers */ + #define CKP_NSS (CKM_VENDOR_DEFINED | NSSCK_VENDOR_NSS) + #define CKP_NSS_KYBER_768_ROUND3 (CKP_NSS + 1) ++#define CKP_NSS_ML_KEM_768 (CKP_NSS + 2) + + /* FIPS Indicator defines */ + #define CKS_NSS_UNINITIALIZED 0xffffffffUL +diff -up ./lib/util/secoid.c.mlkem ./lib/util/secoid.c +--- ./lib/util/secoid.c.mlkem 2024-10-31 14:54:15.428515546 -0700 ++++ ./lib/util/secoid.c 2024-10-31 14:54:15.470516015 -0700 +@@ -644,6 +644,9 @@ CONST_OID curve25519[] = { 0x2B, 0x06, 0 + CONST_OID ed25519PublicKey[] = { 0x2B, 0x65, 0x70 }; + CONST_OID ed25519Signature[] = { 0x2B, 0x65, 0x70 }; + ++/*https://www.rfc-editor.org/rfc/rfc8410#section-3*/ ++CONST_OID x25519PublicKey[] = { 0x2b, 0x65, 0x6e }; ++ + #define OI(x) \ + { \ + siDEROID, (unsigned char *)x, sizeof x \ +@@ -1890,11 +1893,19 @@ const static SECOidData oids[SEC_OID_TOT + ODE(SEC_OID_RC2_64_CBC, "RC2-64-CBC", CKM_RC2_CBC, INVALID_CERT_EXTENSION), + ODE(SEC_OID_RC2_128_CBC, "RC2-128-CBC", CKM_RC2_CBC, INVALID_CERT_EXTENSION), + ODE(SEC_OID_ECDH_KEA, "ECDH", CKM_ECDH1_DERIVE, INVALID_CERT_EXTENSION), ++ OD(x25519PublicKey, SEC_OID_X25519, ++ "X25519 key exchange", CKM_EC_MONTGOMERY_KEY_PAIR_GEN, INVALID_CERT_EXTENSION), ++ ++ ODE(SEC_OID_MLKEM768X25519, ++ "ML-KEM-768+X25519 key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION), ++ + + /* this will change upstream. for now apps shouldn't use it */ + /* we need it for the policy code. */ + ODE(SEC_OID_PRIVATE_1, + "TLS Require EMS", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION), ++ ODE(SEC_OID_PRIVATE_2, ++ "ML-KEM-768+SECP256 key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION), + + }; + +diff -up ./lib/util/secoidt.h.mlkem ./lib/util/secoidt.h +--- ./lib/util/secoidt.h.mlkem 2024-10-31 14:54:15.428515546 -0700 ++++ ./lib/util/secoidt.h 2024-10-31 14:54:15.470516015 -0700 +@@ -530,9 +530,14 @@ typedef enum { + SEC_OID_RC2_64_CBC = 385, + SEC_OID_RC2_128_CBC = 386, + SEC_OID_ECDH_KEA = 387, +- /* this will change upstream. for now apps shouldn't use it */ ++ SEC_OID_X25519 = 388, ++ ++ SEC_OID_MLKEM768X25519 = 389, ++ ++ /* these will change upstream. for now apps shouldn't use it */ + /* give it an obscure name here */ +- SEC_OID_PRIVATE_1 = 388, ++ SEC_OID_PRIVATE_1 = 390, ++ SEC_OID_PRIVATE_2 = 391, + + SEC_OID_TOTAL + } SECOidTag; +diff -up ./tests/bogo/bogo.sh.mlkem ./tests/bogo/bogo.sh +--- ./tests/bogo/bogo.sh.mlkem 2024-06-07 09:26:03.000000000 -0700 ++++ ./tests/bogo/bogo.sh 2024-10-31 14:54:15.470516015 -0700 +@@ -13,7 +13,7 @@ + ######################################################################## + + # Currently used BorringSSL version +-BOGO_VERSION=f5e0c8f92a22679b0cd8d24d0d670769c1cc07f3 ++BOGO_VERSION=73030794f7aaf4f614486b511908841852807936 + + bogo_init() + { +diff -up ./tests/ssl/sslcov.txt.mlkem ./tests/ssl/sslcov.txt +--- ./tests/ssl/sslcov.txt.mlkem 2024-10-31 14:54:15.454515836 -0700 ++++ ./tests/ssl/sslcov.txt 2024-10-31 14:54:15.470516015 -0700 +@@ -147,3 +147,9 @@ + ECC TLS13 :1301 TLS13_ECDHE_WITH_AES_128_GCM_SHA256 + ECC TLS13 :1302 TLS13_ECDHE_WITH_AES_256_GCM_SHA384 + ECC TLS13 :1303 TLS13_ECDHE_WITH_CHACHA20_POLY1305_SHA256 ++MLKEM256 TLS13 :1301 TLS13_MLKEMP256_WITH_AES_128_GCM_SHA256 ++MLKEM256 TLS13 :1302 TLS13_MLKEMP256_WITH_AES_256_GCM_SHA384 ++MLKEM256 TLS13 :1303 TLS13_MLKEMP256_WITH_CHACHA20_POLY1305_SHA256 ++MLKEM219 TLS13 :1301 TLS13_MLKEMX25519_WITH_AES_128_GCM_SHA256 ++MLKEM219 TLS13 :1302 TLS13_MLKEMX25519_WITH_AES_256_GCM_SHA384 ++MLKEM219 TLS13 :1303 TLS13_MLKEMX25519_WITH_CHACHA20_POLY1305_SHA256 +diff -up ./tests/ssl/ssl.sh.mlkem ./tests/ssl/ssl.sh +--- ./tests/ssl/ssl.sh.mlkem 2024-10-31 15:03:27.098674318 -0700 ++++ ./tests/ssl/ssl.sh 2024-10-31 15:03:27.100674340 -0700 +@@ -121,8 +121,12 @@ ssl_init() + CIPHER_SUITES="-c ${EC_SUITES}${NON_EC_SUITES}" + TLS13_CIPHER_SUITES="-c ${TLS13_SUITES}${EC_SUITES}${NON_EC_SUITES}" + ++ # FIPS specific options for both clients and servers ++ FIPS_OPTIONS="" + # in fips mode, turn off curve25519 until it's NIST approved +- FIPS_OPTIONS="-I P256,P384,P521,FF2048,FF3072,FF4096,FF6144,FF8192" ++ ALL_GROUPS="P256,P384,P521,x25519,FF2048,FF3072,FF4096,FF6144,FF8192,mlkem768secp256r1,mlkem768x25519" ++ NON_PQ_GROUPS="P256,P384,P521,x25519,FF2048,FF3072,FF4096,FF6144,FF8192" ++ FIPS_GROUPS="P256,P384,P521,FF2048,FF3072,FF4096,FF6144,FF8192,mlkem768secp256r1,mlkem768x25519" + + # in non-fips mode, tstclnt may run without the db password in some + # cases, but in fips mode it's always needed +@@ -312,10 +316,12 @@ ssl_cov() + + SAVE_SERVER_OPTIONS=${SERVER_OPTIONS} + if [ "${SERVER_MODE}" = "fips" ] ; then +- SERVER_OPTIONS="${SERVER_OPTIONS} ${FIPS_OPTIONS}" ++ SERVER_OPTIONS="${SERVER_OPTIONS} -I ${FIPS_GROUPS} ${FIPS_OPTIONS}" + fi + SAVE_CLIENT_OPTIONS=${CLIENT_OPTIONS} ++ CLIENT_GROUPS=${NON_PQ_GROUPS} + if [ "${CLIENT_MODE}" = "fips" ] ; then ++ CLIENT_GROUPS=${FIPS_GROUPS} + CLIENT_OPTIONS="${CLIENT_OPTIONS} ${FIPS_OPTIONS}" + fi + +@@ -340,7 +346,7 @@ ssl_cov() + ;; + esac + +- echo "$SCRIPTNAME: running $testname ----------------------------" ++ echo "$SCRIPTNAME: running $testname ------------------" + VMAX="ssl3" + if [ "$testmax" = "TLS10" ]; then + VMAX="tls1.0" +@@ -375,13 +381,19 @@ ssl_cov() + VMIN="ssl3" + fi + ++ TLS_GROUPS=${CLIENT_GROUPS} ++ if [ "$ectype" = "MLKEM256" ]; then ++ TLS_GROUPS="mlkem768secp256r1" ++ elif [ "$ectype" = "MLKEM219" ]; then ++ TLS_GROUPS="mlkem768x25519" ++ fi ++ echo "TLS_GROUPS=${TLS_GROUPS}" + +- +- echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} \\" ++ echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -I \"${TLS_GROUPS}\" -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} \\" + echo " -f -d ${P_R_CLIENTDIR} $verbose -w nss < ${REQUEST_FILE}" + + rm ${TMP}/$HOST.tmp.$$ 2>/dev/null +- ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} -f \ ++ ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -I "${TLS_GROUPS}" -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} -f \ + -d ${P_R_CLIENTDIR} $verbose -w nss < ${REQUEST_FILE} \ + >${TMP}/$HOST.tmp.$$ 2>&1 + ret=$? diff --git a/SPECS/nss.spec b/SPECS/nss.spec index 233909b..123fdd8 100644 --- a/SPECS/nss.spec +++ b/SPECS/nss.spec @@ -3,7 +3,7 @@ # NOTE: To avoid NVR clashes of nspr* packages: # - reset %%{nspr_release} to 1, when updating %%{nspr_version} # - increment %%{nspr_version}, when updating the NSS part only -%global baserelease 7 +%global baserelease 9 %global nss_release %baserelease # use "%%global nspr_release %%[%%baserelease+n]" to handle offsets when # release number between nss and nspr are different. @@ -190,9 +190,11 @@ Patch84: nss-3.101-fix-pkcs12-pbkdf1-encoding.patch Patch85: nss-3.101-fix-cms-abi-break.patch Patch86: nss-3.101-long-pwd-fix.patch Patch87: nss-3.101-fix-cavs-test.patch +Patch88: nss-3.101-fix-shlibsign-fips.patch # RHEL-10 specific Patch90: nss-3.101-disable_dsa.patch +Patch91: nss-3.101-replace-xyber_with-mlkem.patch # NSS reverse patches Patch300: nss-3.79-distrusted-certs.patch @@ -1168,6 +1170,14 @@ fi %changelog +* Fri Nov 1 2024 Bob Relyea - 3.101.0-9 +- Add ml-kem support and remove xyber support +- Fix shlibsign when the system is in FIPS mode + +* Tue Oct 29 2024 Troy Dawson - 3.101.0-8 +- Bump release for October 2024 mass rebuild: + Resolves: RHEL-64018 + * Wed Sep 4 2024 Bob Relyea - 3.101.0-7 - fix cms abi breakage - fix long password issue on pbmac encodings