diff --git a/doc/crypt.tex b/doc/crypt.tex index 4e68dce55..111e2d1fa 100644 --- a/doc/crypt.tex +++ b/doc/crypt.tex @@ -6622,6 +6622,688 @@ \subsection{DSA Key Import} This function generates a private DSA key containing both \textit{x} and \textit{y} parts. + +\chapter{Post-Quantum Cryptography (PQC)} + +LibTomCrypt includes implementations of the three NIST post-quantum cryptographic standards: + +\begin{itemize} +\item \textbf{ML-KEM} (FIPS 203) --- Module-Lattice-Based Key-Encapsulation Mechanism, formerly known as CRYSTALS-Kyber. +\item \textbf{ML-DSA} (FIPS 204) --- Module-Lattice-Based Digital Signature Algorithm, formerly known as CRYSTALS-Dilithium. +\item \textbf{SLH-DSA} (FIPS 205) --- Stateless Hash-Based Digital Signature Algorithm, formerly known as SPHINCS+. +\end{itemize} + +These algorithms are designed to be secure against attacks by both classical and quantum computers. +All three are enabled by defining \code{LTC\_MLKEM}, \code{LTC\_MLDSA}, and \code{LTC\_SLHDSA} respectively +in \textit{tomcrypt\_custom.h}. +ML-KEM, ML-DSA, and the SLH-DSA SHAKE variants require \code{LTC\_SHA3} to be enabled. +The SLH-DSA SHA-2 variants require \code{LTC\_SHA256} (and \code{LTC\_SHA512} for the 192-bit and 256-bit security levels). +In addition to the raw FIPS key formats, the library also provides DER import/export helpers for +\textit{SubjectPublicKeyInfo}, \textit{X.509} certificates, and \textit{PKCS \#8} key containers. + +All PQC functions follow the same conventions as the rest of LibTomCrypt: they return \code{CRYPT\_OK} on success, +use \code{unsigned char *} for byte buffers and \code{unsigned long} for lengths, +and use the standard \code{prng\_state}/\code{wprng} interface for randomness. + +\mysection{ML-KEM (FIPS 203)} + +ML-KEM is a Key Encapsulation Mechanism (KEM). Unlike traditional public-key encryption, a KEM does not encrypt +a message directly. Instead, it generates a random shared secret and a ciphertext. The shared secret can then be +used as a symmetric key. + +\subsection{Parameter Sets} + +ML-KEM supports three parameter sets with increasing security levels: + +\begin{center} +\begin{tabular}{|l|c|c|c|c|} +\hline +\textbf{Parameter Set (alg ID)} & \textbf{Public Key} & \textbf{Secret Key} & \textbf{Ciphertext} & \textbf{Shared Secret} \\ +\hline +LTC\_MLKEM\_512 & 800 bytes & 1632 bytes & 768 bytes & 32 bytes \\ +LTC\_MLKEM\_768 & 1184 bytes & 2400 bytes & 1088 bytes & 32 bytes \\ +LTC\_MLKEM\_1024 & 1568 bytes & 3168 bytes & 1568 bytes & 32 bytes \\ +\hline +\end{tabular} +\end{center} + +\subsection{Size Query} + +\index{mlkem\_get\_sizes()} +\begin{verbatim} +int mlkem_get_sizes(int alg, + unsigned long *public_key_sz, + unsigned long *secret_key_sz, + unsigned long *ciphertext_sz, + unsigned long *shared_secret_sz); +\end{verbatim} + +Returns the key, ciphertext, and shared secret sizes in bytes for the parameter set specified by \textit{alg}. +Any output pointer may be \code{NULL} if the caller does not need that particular size. +Returns \code{CRYPT\_OK} on success, or \code{CRYPT\_INVALID\_ARG} if \textit{alg} is not a valid ML-KEM parameter set. + +\subsection{Key Generation} + +\index{mlkem\_make\_key()} +\begin{verbatim} +int mlkem_make_key(prng_state *prng, int wprng, + int alg, mlkem_key *key); +\end{verbatim} + +Generates an ML-KEM key pair (both encapsulation and decapsulation keys). +The \textit{prng} and \textit{wprng} parameters specify the PRNG to use for randomness. +The \textit{alg} parameter selects the parameter set +(\code{LTC\_MLKEM\_512}, \code{LTC\_MLKEM\_768}, or \code{LTC\_MLKEM\_1024}). +The resulting key is stored in \textit{key} and has type \code{PK\_PRIVATE}. +The caller must eventually call \code{mlkem\_free()} to release the key. + +\index{mlkem\_make\_key\_from\_seed()} +\begin{verbatim} +int mlkem_make_key_from_seed(int alg, + const unsigned char *seed, unsigned long seedlen, + mlkem_key *key); +\end{verbatim} + +Creates an ML-KEM key pair deterministically from a seed. +The \textit{seedlen} must be exactly 64 bytes; otherwise the function returns +\code{CRYPT\_INVALID\_ARG}. +The \textit{alg} parameter selects the parameter set +(\code{LTC\_MLKEM\_512}, \code{LTC\_MLKEM\_768}, or \code{LTC\_MLKEM\_1024}). +The resulting key is stored in \textit{key} and has type \code{PK\_PRIVATE}. +This function is primarily useful for deterministic key reconstruction and for importing RFC 9935 seed-based private keys. + +\subsection{Key Export and Import} + +\index{mlkem\_export()} +\begin{verbatim} +int mlkem_export(unsigned char *out, unsigned long *outlen, + int which, const mlkem_key *key); +\end{verbatim} + +To export a key, the function \textit{mlkem\_export} is provided. + +It has support for the following output formats: + +\begin{figure}[H] +\begin{center} +\begin{tabular}{|c|c|} +\hline \textbf{which} & \textbf{output format} \\ +\hline PK\_PRIVATE & Raw decapsulation key \\ +\hline PK\_PRIVATE \& PK\_STD & PKCS \#8 \\ +\hline PK\_PUBLIC & Raw encapsulation key \\ +\hline PK\_PUBLIC \& PK\_STD & SubjectPublicKeyInfo \\ +\hline +\end{tabular} +\end{center} +\caption{Possible mlkem\_export() output formats} +\end{figure} + +The standard formats are DER encoded. +For \code{PK\_PRIVATE \& PK\_STD}, the current implementation emits a PKCS \#8 structure +containing the expanded ML-KEM private key. + +\index{mlkem\_export\_raw()} +\begin{verbatim} +int mlkem_export_raw(unsigned char *out, unsigned long *outlen, + int which, const mlkem_key *key); +\end{verbatim} + +Exports a key to a raw byte buffer in the format defined by FIPS 203. +The \textit{out} buffer must be large enough to hold the key; on entry, \textit{*outlen} is the +buffer size, and on exit it is set to the number of bytes written. +Set \textit{which} to \code{PK\_PUBLIC} to export the encapsulation (public) key, +or \code{PK\_PRIVATE} to export the decapsulation (secret) key. +The required buffer sizes can be obtained from \code{mlkem\_get\_sizes()} or the parameter table above. +Returns \code{CRYPT\_BUFFER\_OVERFLOW} if the buffer is too small (with \textit{*outlen} set to the required size). + +\index{mlkem\_import()} +\begin{verbatim} +int mlkem_import(const unsigned char *in, unsigned long inlen, + mlkem_key *key); +\end{verbatim} + +The \textit{mlkem\_import} function can be used to import a public key in DER-encoded +\textit{SubjectPublicKeyInfo} format. + +\index{mlkem\_import\_raw()} +\begin{verbatim} +int mlkem_import_raw(const unsigned char *in, unsigned long inlen, + int which, int alg, mlkem_key *key); +\end{verbatim} + +Imports a key from a raw byte buffer. +The \textit{inlen} must exactly match the expected key size for the given \textit{alg} and \textit{which}. +Set \textit{which} to \code{PK\_PUBLIC} to import an encapsulation key, or \code{PK\_PRIVATE} +to import a decapsulation key. When importing a private key, the embedded public key is automatically +extracted so the key can also be used for encapsulation. +The caller must eventually call \code{mlkem\_free()} to release the imported key. + +\index{mlkem\_import\_x509()} +\begin{verbatim} +int mlkem_import_x509(const unsigned char *in, unsigned long inlen, + mlkem_key *key); +\end{verbatim} + +To import a public key from a DER-encoded \textit{X.509} certificate, one can use the function +\textit{mlkem\_import\_x509}. + +\index{mlkem\_import\_pkcs8()} +\begin{verbatim} +int mlkem_import_pkcs8(const unsigned char *in, unsigned long inlen, + const password_ctx *pw_ctx, mlkem_key *key); +\end{verbatim} + +To import a private key in the \textit{OneAsymmetricKey} a.k.a. \textit{PKCS \#8} format, +either plain or PBES encrypted, one can use the function \textit{mlkem\_import\_pkcs8}. +The importer accepts the raw expanded private key encoding as well as the RFC 9935 seed-based +and combined encodings. + +\subsection{Encapsulation} + +\index{mlkem\_encaps()} +\begin{verbatim} +int mlkem_encaps(unsigned char *ct, unsigned long *ctlen, + unsigned char *shared_secret, unsigned long *sslen, + prng_state *prng, int wprng, + const mlkem_key *key); +\end{verbatim} + +Performs ML-KEM encapsulation: generates a random 32-byte shared secret and a ciphertext +that encapsulates it under the given public key. +The \textit{ct} buffer receives the ciphertext and \textit{shared\_secret} receives the shared secret. +On entry, \textit{*ctlen} and \textit{*sslen} specify the buffer sizes; on exit they are set to the actual sizes. +The \textit{key} must contain at least a public key (either \code{PK\_PUBLIC} or \code{PK\_PRIVATE}). +Returns \code{CRYPT\_BUFFER\_OVERFLOW} if either buffer is too small. + +\subsection{Decapsulation} + +\index{mlkem\_decaps()} +\begin{verbatim} +int mlkem_decaps(unsigned char *shared_secret, unsigned long *sslen, + const unsigned char *ct, unsigned long ctlen, + const mlkem_key *key); +\end{verbatim} + +Performs ML-KEM decapsulation: recovers the shared secret from a ciphertext using a private key. +The \textit{key} must be of type \code{PK\_PRIVATE}. +On entry, \textit{*sslen} specifies the buffer size; on exit it is set to 32 (the shared secret size). +If the ciphertext is invalid, a pseudorandom value is returned instead of an error code --- +this is the ``implicit rejection'' behavior required by the ML-KEM specification to prevent +chosen-ciphertext attacks. The function always returns \code{CRYPT\_OK} on successful decapsulation +(regardless of whether the ciphertext was valid). +Returns \code{CRYPT\_PK\_NOT\_PRIVATE} if the key is not a private key, +or \code{CRYPT\_INVALID\_PACKET} if \textit{ctlen} does not match the expected ciphertext size. + +\subsection{Key Cleanup} + +\index{mlkem\_free()} +\begin{verbatim} +void mlkem_free(mlkem_key *key); +\end{verbatim} + +Frees all memory associated with an ML-KEM key and zeros sensitive data. +After this call the \textit{key} structure is zeroed and must not be used until re-initialized +by \code{mlkem\_make\_key()} or \code{mlkem\_import\_raw()}. + +\subsection{Example} + +\begin{small} +\begin{verbatim} +mlkem_key key, pubkey; +unsigned char ct[1568], ss1[32], ss2[32], pk[1568]; +unsigned long ctlen, sslen, pklen; +int prng_idx = find_prng("yarrow"); + +/* Generate key pair */ +mlkem_make_key(&yarrow_prng, prng_idx, LTC_MLKEM_768, &key); + +/* Export public key */ +pklen = sizeof(pk); +mlkem_export_raw(pk, &pklen, PK_PUBLIC, &key); +mlkem_import_raw(pk, pklen, PK_PUBLIC, LTC_MLKEM_768, &pubkey); + +/* Encapsulate */ +ctlen = sizeof(ct); +sslen = sizeof(ss1); +mlkem_encaps(ct, &ctlen, ss1, &sslen, &yarrow_prng, prng_idx, &pubkey); + +/* Decapsulate */ +sslen = sizeof(ss2); +mlkem_decaps(ss2, &sslen, ct, ctlen, &key); +/* ss1 and ss2 are now equal */ + +mlkem_free(&key); +mlkem_free(&pubkey); +\end{verbatim} +\end{small} + + +\mysection{ML-DSA (FIPS 204)} + +ML-DSA is a digital signature algorithm based on module lattices. It supports hedged signing +(using randomness to protect against side-channel attacks) and optional context strings. + +\subsection{Parameter Sets} + +\begin{center} +\begin{tabular}{|l|c|c|c|} +\hline +\textbf{Parameter Set (alg ID)} & \textbf{Public Key} & \textbf{Secret Key} & \textbf{Signature} \\ +\hline +LTC\_MLDSA\_44 & 1312 bytes & 2560 bytes & 2420 bytes \\ +LTC\_MLDSA\_65 & 1952 bytes & 4032 bytes & 3309 bytes \\ +LTC\_MLDSA\_87 & 2592 bytes & 4896 bytes & 4627 bytes \\ +\hline +\end{tabular} +\end{center} + +\subsection{Size Query} + +\index{mldsa\_get\_sizes()} +\begin{verbatim} +int mldsa_get_sizes(int alg, + unsigned long *public_key_sz, + unsigned long *secret_key_sz, + unsigned long *signature_sz); +\end{verbatim} + +Returns the public key, secret key, and signature sizes in bytes for the parameter set specified by \textit{alg}. +Any output pointer may be \code{NULL} if the caller does not need that particular size. +Returns \code{CRYPT\_OK} on success, or \code{CRYPT\_INVALID\_ARG} if \textit{alg} is not a valid ML-DSA parameter set. + +\subsection{Key Generation} + +\index{mldsa\_make\_key()} +\begin{verbatim} +int mldsa_make_key(prng_state *prng, int wprng, + int alg, mldsa_key *key); +\end{verbatim} + +Generates an ML-DSA key pair (both signing and verification keys). +The \textit{prng} and \textit{wprng} parameters specify the PRNG to use for randomness. +The \textit{alg} parameter selects the parameter set +(\code{LTC\_MLDSA\_44}, \code{LTC\_MLDSA\_65}, or \code{LTC\_MLDSA\_87}). +The resulting key is stored in \textit{key} and has type \code{PK\_PRIVATE}. +The caller must eventually call \code{mldsa\_free()} to release the key. + +\index{mldsa\_make\_key\_from\_seed()} +\begin{verbatim} +int mldsa_make_key_from_seed(int alg, + const unsigned char *seed, unsigned long seedlen, + mldsa_key *key); +\end{verbatim} + +Creates an ML-DSA key pair deterministically from a seed. +The \textit{seedlen} must be exactly 32 bytes; otherwise the function returns +\code{CRYPT\_INVALID\_ARG}. +The \textit{alg} parameter selects the parameter set +(\code{LTC\_MLDSA\_44}, \code{LTC\_MLDSA\_65}, or \code{LTC\_MLDSA\_87}). +The resulting key is stored in \textit{key} and has type \code{PK\_PRIVATE}. +This function is primarily useful for deterministic key reconstruction and for importing RFC 9881 seed-based private keys. + +\subsection{Key Export and Import} + +\index{mldsa\_export()} +\begin{verbatim} +int mldsa_export(unsigned char *out, unsigned long *outlen, + int which, const mldsa_key *key); +\end{verbatim} + +To export a key, the function \textit{mldsa\_export} is provided. + +It has support for the following output formats: + +\begin{figure}[H] +\begin{center} +\begin{tabular}{|c|c|} +\hline \textbf{which} & \textbf{output format} \\ +\hline PK\_PRIVATE & Raw signing key \\ +\hline PK\_PRIVATE \& PK\_STD & PKCS \#8 \\ +\hline PK\_PUBLIC & Raw verification key \\ +\hline PK\_PUBLIC \& PK\_STD & SubjectPublicKeyInfo \\ +\hline +\end{tabular} +\end{center} +\caption{Possible mldsa\_export() output formats} +\end{figure} + +The standard formats are DER encoded. +For \code{PK\_PRIVATE \& PK\_STD}, the current implementation emits a PKCS \#8 structure +containing the expanded ML-DSA private key. + +\index{mldsa\_export\_raw()} +\begin{verbatim} +int mldsa_export_raw(unsigned char *out, unsigned long *outlen, + int which, const mldsa_key *key); +\end{verbatim} + +Exports a key to a raw byte buffer in the format defined by FIPS 204. +On entry, \textit{*outlen} is the buffer size; on exit it is set to the number of bytes written. +Set \textit{which} to \code{PK\_PUBLIC} to export the verification (public) key, +or \code{PK\_PRIVATE} to export the signing (secret) key. +The required buffer sizes can be obtained from \code{mldsa\_get\_sizes()} or the parameter table above. +Returns \code{CRYPT\_BUFFER\_OVERFLOW} if the buffer is too small (with \textit{*outlen} set to the required size). + +\index{mldsa\_import()} +\begin{verbatim} +int mldsa_import(const unsigned char *in, unsigned long inlen, + mldsa_key *key); +\end{verbatim} + +The \textit{mldsa\_import} function can be used to import a public key in DER-encoded +\textit{SubjectPublicKeyInfo} format. + +\index{mldsa\_import\_raw()} +\begin{verbatim} +int mldsa_import_raw(const unsigned char *in, unsigned long inlen, + int which, int alg, mldsa_key *key); +\end{verbatim} + +Imports a key from a raw byte buffer. +The \textit{inlen} must exactly match the expected key size for the given \textit{alg} and \textit{which}. +Set \textit{which} to \code{PK\_PUBLIC} to import a verification key, or \code{PK\_PRIVATE} +to import a signing key. When importing a private key, the corresponding public key is +reconstructed automatically so the key can also be used for verification. +The caller must eventually call \code{mldsa\_free()} to release the imported key. + +\index{mldsa\_import\_x509()} +\begin{verbatim} +int mldsa_import_x509(const unsigned char *in, unsigned long inlen, + mldsa_key *key); +\end{verbatim} + +To import a public key from a DER-encoded \textit{X.509} certificate, one can use the function +\textit{mldsa\_import\_x509}. + +\index{mldsa\_import\_pkcs8()} +\begin{verbatim} +int mldsa_import_pkcs8(const unsigned char *in, unsigned long inlen, + const password_ctx *pw_ctx, mldsa_key *key); +\end{verbatim} + +To import a private key in the \textit{OneAsymmetricKey} a.k.a. \textit{PKCS \#8} format, +either plain or PBES encrypted, one can use the function \textit{mldsa\_import\_pkcs8}. +The importer accepts the raw expanded private key encoding as well as the RFC 9881 seed-based +and combined encodings. + +\subsection{Signing} + +\index{mldsa\_sign()} +\begin{verbatim} +int mldsa_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + prng_state *prng, int wprng, + const mldsa_key *key); +\end{verbatim} + +Signs a message using a private key. +The signature is written to \textit{sig}; on entry \textit{*siglen} is the buffer size, +on exit it is set to the actual signature size. +The \textit{ctx} parameter is an optional context string (up to 255 bytes per FIPS 204) +that binds the signature to a particular application context; pass \code{NULL} and 0 if not needed. +The \textit{prng} and \textit{wprng} parameters provide randomness for hedged signing, which helps +protect against side-channel attacks. +The \textit{key} must be of type \code{PK\_PRIVATE}. +Returns \code{CRYPT\_BUFFER\_OVERFLOW} if the signature buffer is too small. + +\subsection{Verification} + +\index{mldsa\_verify()} +\begin{verbatim} +int mldsa_verify(const unsigned char *sig, unsigned long siglen, + const unsigned char *msg, unsigned long msglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const mldsa_key *key); +\end{verbatim} + +Verifies an ML-DSA signature against a message and public key. +Sets \textit{*stat} to 1 if the signature is valid, or 0 if it is invalid. +The \textit{ctx} and \textit{ctxlen} parameters must match the context string used during signing. +The function returns \code{CRYPT\_OK} even if the signature is invalid --- the caller must +check \textit{*stat} to determine validity. + +\subsection{Key Cleanup} + +\index{mldsa\_free()} +\begin{verbatim} +void mldsa_free(mldsa_key *key); +\end{verbatim} + +Frees all memory associated with an ML-DSA key and zeros sensitive data. +After this call the \textit{key} structure is zeroed and must not be used until re-initialized. + +\subsection{Example} + +\begin{small} +\begin{verbatim} +mldsa_key key; +unsigned char sig[4627]; +unsigned long siglen; +int stat, prng_idx = find_prng("yarrow"); + +mldsa_make_key(&yarrow_prng, prng_idx, LTC_MLDSA_65, &key); + +siglen = sizeof(sig); +mldsa_sign(msg, msglen, sig, &siglen, NULL, 0, + &yarrow_prng, prng_idx, &key); + +mldsa_verify(sig, siglen, msg, msglen, NULL, 0, &stat, &key); +/* stat == 1 means valid */ + +mldsa_free(&key); +\end{verbatim} +\end{small} + + +\mysection{SLH-DSA (FIPS 205)} + +SLH-DSA is a stateless hash-based digital signature algorithm. Unlike ML-KEM and ML-DSA which are +lattice-based, SLH-DSA relies only on the security of hash functions. This makes it a conservative +choice but results in larger signatures. + +\subsection{Parameter Sets} + +SLH-DSA has 24 parameter sets: 12 Pure SLH-DSA variants and 12 HashSLH-DSA variants. +Each family contains 6 SHA-2 based parameter sets and 6 SHAKE based parameter sets, with ``small'' (S) and +``fast'' (F) variants at each security level. +The S variants produce smaller signatures but are slower; the F variants are faster but produce larger signatures. +SHA-2 and SHAKE variants at the same security level have identical key and signature sizes but differ in the +hash function used internally. +The HashSLH-DSA parameter sets use the same API as the pure variants; the selected algorithm identifier determines +the pre-hash function used by the signature scheme. + +\begin{center} +\begin{tabular}{|l|c|c|c|} +\hline +\textbf{Parameter Set (alg ID)} & \textbf{Public Key} & \textbf{Secret Key} & \textbf{Signature} \\ +\hline +LTC\_SLHDSA\_SHA2\_128S & 32 bytes & 64 bytes & 7856 bytes \\ +LTC\_SLHDSA\_SHA2\_128F & 32 bytes & 64 bytes & 17088 bytes \\ +LTC\_SLHDSA\_SHA2\_192S & 48 bytes & 96 bytes & 16224 bytes \\ +LTC\_SLHDSA\_SHA2\_192F & 48 bytes & 96 bytes & 35664 bytes \\ +LTC\_SLHDSA\_SHA2\_256S & 64 bytes & 128 bytes & 29792 bytes \\ +LTC\_SLHDSA\_SHA2\_256F & 64 bytes & 128 bytes & 49856 bytes \\ +\hline +LTC\_SLHDSA\_SHAKE\_128S & 32 bytes & 64 bytes & 7856 bytes \\ +LTC\_SLHDSA\_SHAKE\_128F & 32 bytes & 64 bytes & 17088 bytes \\ +LTC\_SLHDSA\_SHAKE\_192S & 48 bytes & 96 bytes & 16224 bytes \\ +LTC\_SLHDSA\_SHAKE\_192F & 48 bytes & 96 bytes & 35664 bytes \\ +LTC\_SLHDSA\_SHAKE\_256S & 64 bytes & 128 bytes & 29792 bytes \\ +LTC\_SLHDSA\_SHAKE\_256F & 64 bytes & 128 bytes & 49856 bytes \\ +\hline +\end{tabular} +\end{center} + +The HashSLH-DSA parameter sets use the same public-key, private-key, and signature sizes as the corresponding +Pure SLH-DSA parameter sets at the same security level and performance profile. + +\subsection{Size Query} + +\index{slhdsa\_get\_sizes()} +\begin{verbatim} +int slhdsa_get_sizes(int alg, + unsigned long *public_key_sz, + unsigned long *secret_key_sz, + unsigned long *signature_sz); +\end{verbatim} + +Returns the public key, secret key, and signature sizes in bytes for the parameter set specified by \textit{alg}. +Any output pointer may be \code{NULL} if the caller does not need that particular size. +This function works for all 24 parameter sets (Pure SLH-DSA and HashSLH-DSA, both SHA-2 and SHAKE variants). +Returns \code{CRYPT\_OK} on success, or \code{CRYPT\_INVALID\_ARG} if \textit{alg} is not a valid SLH-DSA parameter set. + +\subsection{Key Generation} + +\index{slhdsa\_make\_key()} +\begin{verbatim} +int slhdsa_make_key(prng_state *prng, int wprng, + int alg, slhdsa_key *key); +\end{verbatim} + +Generates an SLH-DSA key pair (both signing and verification keys). +The \textit{prng} and \textit{wprng} parameters specify the PRNG to use for randomness. +The \textit{alg} parameter selects one of the 24 parameter sets (e.g. \code{LTC\_SLHDSA\_SHAKE\_128F}, +\code{LTC\_SLHDSA\_SHA2\_256S}, \code{LTC\_SLHDSA\_HASH\_SHA2\_128S\_WITH\_SHA256}, +\code{LTC\_SLHDSA\_HASH\_SHAKE\_256F\_WITH\_SHAKE256}, etc.). +The resulting key is stored in \textit{key} and has type \code{PK\_PRIVATE}. +Note that SLH-DSA key generation involves computing a Merkle tree root, which can be slow +for the ``small'' (S) parameter sets. +The caller must eventually call \code{slhdsa\_free()} to release the key. + +\subsection{Key Export and Import} + +\index{slhdsa\_export()} +\begin{verbatim} +int slhdsa_export(unsigned char *out, unsigned long *outlen, + int which, const slhdsa_key *key); +\end{verbatim} + +To export a key, the function \textit{slhdsa\_export} is provided. + +It has support for the following output formats: + +\begin{figure}[H] +\begin{center} +\begin{tabular}{|c|c|} +\hline \textbf{which} & \textbf{output format} \\ +\hline PK\_PRIVATE & Raw signing key \\ +\hline PK\_PRIVATE \& PK\_STD & PKCS \#8 \\ +\hline PK\_PUBLIC & Raw verification key \\ +\hline PK\_PUBLIC \& PK\_STD & SubjectPublicKeyInfo \\ +\hline +\end{tabular} +\end{center} +\caption{Possible slhdsa\_export() output formats} +\end{figure} + +The standard formats are DER encoded. + +\index{slhdsa\_export\_raw()} +\begin{verbatim} +int slhdsa_export_raw(unsigned char *out, unsigned long *outlen, + int which, const slhdsa_key *key); +\end{verbatim} + +Exports a key to a raw byte buffer in the format defined by FIPS 205. +On entry, \textit{*outlen} is the buffer size; on exit it is set to the number of bytes written. +Set \textit{which} to \code{PK\_PUBLIC} to export the verification (public) key, +or \code{PK\_PRIVATE} to export the signing (secret) key. +The required buffer sizes can be obtained from \code{slhdsa\_get\_sizes()} or the parameter table above. +Returns \code{CRYPT\_BUFFER\_OVERFLOW} if the buffer is too small (with \textit{*outlen} set to the required size). + +\index{slhdsa\_import()} +\begin{verbatim} +int slhdsa_import(const unsigned char *in, unsigned long inlen, + slhdsa_key *key); +\end{verbatim} + +The \textit{slhdsa\_import} function can be used to import a public key in DER-encoded +\textit{SubjectPublicKeyInfo} format. + +\index{slhdsa\_import\_raw()} +\begin{verbatim} +int slhdsa_import_raw(const unsigned char *in, unsigned long inlen, + int which, int alg, slhdsa_key *key); +\end{verbatim} + +Imports a key from a raw byte buffer. +The \textit{inlen} must exactly match the expected key size for the given \textit{alg} and \textit{which}. +Set \textit{which} to \code{PK\_PUBLIC} to import a verification key, or \code{PK\_PRIVATE} +to import a signing key. When importing a private key, the public key is automatically +extracted (it is embedded in the secret key format). +The caller must eventually call \code{slhdsa\_free()} to release the imported key. + +\index{slhdsa\_import\_x509()} +\begin{verbatim} +int slhdsa_import_x509(const unsigned char *in, unsigned long inlen, + slhdsa_key *key); +\end{verbatim} + +To import a public key from a DER-encoded \textit{X.509} certificate, one can use the function +\textit{slhdsa\_import\_x509}. + +\index{slhdsa\_import\_pkcs8()} +\begin{verbatim} +int slhdsa_import_pkcs8(const unsigned char *in, unsigned long inlen, + const password_ctx *pw_ctx, slhdsa_key *key); +\end{verbatim} + +To import a private key in the \textit{OneAsymmetricKey} a.k.a. \textit{PKCS \#8} format, +either plain or PBES encrypted, one can use the function \textit{slhdsa\_import\_pkcs8}. +The private key payload uses the raw SLH-DSA private-key octets defined for the selected parameter set. + +\subsection{Signing} + +\index{slhdsa\_sign()} +\begin{verbatim} +int slhdsa_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + prng_state *prng, int wprng, + const slhdsa_key *key); +\end{verbatim} + +Signs a message using a private key. +The signature is written to \textit{sig}; on entry \textit{*siglen} is the buffer size, +on exit it is set to the actual signature size. SLH-DSA signatures are large +(between 7,856 and 49,856 bytes depending on the parameter set), so the buffer should be +allocated accordingly using the size returned by \code{slhdsa\_get\_sizes()}. +The \textit{ctx} parameter is an optional context string (up to 255 bytes per FIPS 205); +pass \code{NULL} and 0 if not needed. +The \textit{prng} and \textit{wprng} parameters provide randomness for non-deterministic signing. +The \textit{key} must be of type \code{PK\_PRIVATE}. +Returns \code{CRYPT\_BUFFER\_OVERFLOW} if the signature buffer is too small. + +\subsection{Verification} + +\index{slhdsa\_verify()} +\begin{verbatim} +int slhdsa_verify(const unsigned char *sig, unsigned long siglen, + const unsigned char *msg, unsigned long msglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const slhdsa_key *key); +\end{verbatim} + +Verifies an SLH-DSA signature against a message and public key. +Sets \textit{*stat} to 1 if the signature is valid, or 0 if it is invalid. +The \textit{ctx} and \textit{ctxlen} parameters must match the context string used during signing. +The function returns \code{CRYPT\_OK} even if the signature is invalid --- the caller must +check \textit{*stat} to determine validity. + +\subsection{Key Cleanup} + +\index{slhdsa\_free()} +\begin{verbatim} +void slhdsa_free(slhdsa_key *key); +\end{verbatim} + +Frees all memory associated with an SLH-DSA key and zeros sensitive data. +After this call the \textit{key} structure is zeroed and must not be used until re-initialized. + +\clearpage \chapter{The PKA Union} \index{ltc\_pka\_key} @@ -6637,7 +7319,11 @@ \chapter{The PKA Union} LTC_PKA_EC, LTC_PKA_X25519, LTC_PKA_ED25519, + LTC_PKA_MLDSA, + LTC_PKA_SLHDSA, + LTC_PKA_MLKEM, LTC_PKA_DH, + LTC_PKA_NUM }; typedef struct { @@ -6658,6 +7344,37 @@ \chapter{The PKA Union} #ifdef LTC_MRSA rsa_key rsa; #endif +#ifdef LTC_MLKEM + struct { + int alg; + int type; + unsigned char *pk; + unsigned long pklen; + unsigned char *sk; + unsigned long sklen; + } mlkem; +#endif +#ifdef LTC_MLDSA + struct { + int alg; + int type; + unsigned char *pk; + unsigned long pklen; + unsigned char *sk; + unsigned long sklen; + } mldsa; +#endif +#ifdef LTC_SLHDSA + struct { + int alg; + int type; + unsigned char *pk; + unsigned long pklen; + unsigned char *sk; + unsigned long sklen; + } slhdsa; +#endif + char dummy; } u; enum ltc_pka_id id; } ltc_pka_key; @@ -7929,12 +8646,12 @@ \subsection{PKCS PEM files} \begin{small} \begin{tabular}{|l|l|l|l|l|} \hline \textbf{Identifier} & \textbf{Key type} & \textbf{File content} & \textbf{Standard} & \textbf{Algorithm} \\ -\hline \texttt{BEGIN CERTIFICATE} & Public & Plain & \texttt{X.509} & DH, DSA, ECC, Ed25519, RSA, X25519 \\ +\hline \texttt{BEGIN CERTIFICATE} & Public & Plain & \texttt{X.509} & DH, DSA, ECC, Ed25519, ML-DSA, ML-KEM, RSA, SLH-DSA, X25519 \\ \hline \texttt{BEGIN DSA PRIVATE KEY} & Private & Maybe encrypted & \texttt{OpenSSL\footnote{There are two de-facto standard for DSA private key structures, LibTomCrypt implements OpenSSL's}} & DSA \\ \hline \texttt{BEGIN EC PRIVATE KEY} & Private & Maybe encrypted & \texttt{RFC 5915} & ECC \\ -\hline \texttt{BEGIN ENCRYPTED PRIVATE KEY} & Private & Encrypted & \texttt{PKCS \#8} & DH, DSA, ECC, Ed25519, RSA, X25519 \\ -\hline \texttt{BEGIN PRIVATE KEY} & Private & Plain & \texttt{PKCS \#8} & DH, DSA, ECC, Ed25519, RSA, X25519 \\ -\hline \texttt{BEGIN PUBLIC KEY} & Public & Plain & \texttt{X.509\footnote{Specifically, SubjectPublicKeyInfo}} & DH, DSA, ECC, Ed25519, RSA, X25519 \\ +\hline \texttt{BEGIN ENCRYPTED PRIVATE KEY} & Private & Encrypted & \texttt{PKCS \#8} & DH, DSA, ECC, Ed25519, ML-DSA, ML-KEM, RSA, SLH-DSA, X25519 \\ +\hline \texttt{BEGIN PRIVATE KEY} & Private & Plain & \texttt{PKCS \#8} & DH, DSA, ECC, Ed25519, ML-DSA, ML-KEM, RSA, SLH-DSA, X25519 \\ +\hline \texttt{BEGIN PUBLIC KEY} & Public & Plain & \texttt{X.509\footnote{Specifically, SubjectPublicKeyInfo}} & DH, DSA, ECC, Ed25519, ML-DSA, ML-KEM, RSA, SLH-DSA, X25519 \\ \hline \texttt{BEGIN RSA PRIVATE KEY} & Private & Maybe encrypted & \texttt{PKCS \#1} & RSA \\ \hline \texttt{BEGIN RSA PUBLIC KEY} & Public & Plain & \texttt{PKCS \#1} & RSA \\ \hline @@ -10511,8 +11228,6 @@ \subsection{Elliptic Curve Cryptography - $GF(p)$} These two ECC verify functions have been deprecated in favor of \code{ecc\_verify\_hash\_v2()}. Please check Chapter \ref{ecc-verify} for details. - -\clearpage \addcontentsline{toc}{chapter}{Index} \printindex diff --git a/libtomcrypt_VS2008.vcproj b/libtomcrypt_VS2008.vcproj index 69a5e2d69..7df8188b3 100644 --- a/libtomcrypt_VS2008.vcproj +++ b/libtomcrypt_VS2008.vcproj @@ -1059,6 +1059,10 @@ RelativePath="src\headers\tomcrypt_pkcs.h" > + + @@ -2812,6 +2816,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/makefile.mingw b/makefile.mingw index 5d388f55e..3f3a8c1d3 100644 --- a/makefile.mingw +++ b/makefile.mingw @@ -219,7 +219,11 @@ src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_set.o src/pk/rsa/rsa_sign_hash.o \ src/pk/rsa/rsa_sign_saltlen_get.o src/pk/rsa/rsa_verify_hash.o src/pk/x25519/x25519_export.o \ src/pk/x25519/x25519_import.o src/pk/x25519/x25519_import_pkcs8.o src/pk/x25519/x25519_import_raw.o \ src/pk/x25519/x25519_import_x509.o src/pk/x25519/x25519_make_key.o \ -src/pk/x25519/x25519_shared_secret.o src/prngs/chacha20.o src/prngs/fortuna.o src/prngs/rc4.o \ +src/pk/x25519/x25519_shared_secret.o src/pqc/mldsa.o src/pqc/mldsa_export.o src/pqc/mldsa_import.o \ +src/pqc/mldsa_import_pkcs8.o src/pqc/mldsa_import_x509.o src/pqc/mlkem.o src/pqc/mlkem_export.o \ +src/pqc/mlkem_import.o src/pqc/mlkem_import_pkcs8.o src/pqc/mlkem_import_x509.o src/pqc/slhdsa.o \ +src/pqc/slhdsa_export.o src/pqc/slhdsa_import.o src/pqc/slhdsa_import_pkcs8.o \ +src/pqc/slhdsa_import_x509.o src/prngs/chacha20.o src/prngs/fortuna.o src/prngs/rc4.o \ src/prngs/rng_get_bytes.o src/prngs/rng_make_prng.o src/prngs/sober128.o src/prngs/sprng.o \ src/prngs/yarrow.o src/stream/chacha/chacha_crypt.o src/stream/chacha/chacha_done.o \ src/stream/chacha/chacha_ivctr32.o src/stream/chacha/chacha_ivctr64.o \ @@ -242,15 +246,16 @@ tests/dh_test.o tests/dsa_test.o tests/ecc_test.o tests/ed25519_test.o tests/fil tests/misc_test.o tests/modes_test.o tests/mpi_test.o tests/multi_test.o \ tests/no_null_termination_check_test.o tests/no_prng.o tests/padding_test.o tests/pem_test.o \ tests/pk_oid_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o \ -tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o \ -tests/scrypt_test.o tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o +tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/pqc_mldsa_test.o tests/pqc_mlkem_test.o \ +tests/pqc_slhdsa_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o tests/scrypt_test.o \ +tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o #The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ src/headers/tomcrypt_cipher.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_hash.h \ src/headers/tomcrypt_mac.h src/headers/tomcrypt_macros.h src/headers/tomcrypt_math.h \ src/headers/tomcrypt_misc.h src/headers/tomcrypt_pk.h src/headers/tomcrypt_pkcs.h \ -src/headers/tomcrypt_prng.h +src/headers/tomcrypt_pqc.h src/headers/tomcrypt_prng.h HEADERS=$(HEADERS_PUB) src/headers/tomcrypt_private.h diff --git a/makefile.msvc b/makefile.msvc index 9f530931c..538f498c7 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -212,7 +212,11 @@ src/pk/rsa/rsa_make_key.obj src/pk/rsa/rsa_set.obj src/pk/rsa/rsa_sign_hash.obj src/pk/rsa/rsa_sign_saltlen_get.obj src/pk/rsa/rsa_verify_hash.obj src/pk/x25519/x25519_export.obj \ src/pk/x25519/x25519_import.obj src/pk/x25519/x25519_import_pkcs8.obj src/pk/x25519/x25519_import_raw.obj \ src/pk/x25519/x25519_import_x509.obj src/pk/x25519/x25519_make_key.obj \ -src/pk/x25519/x25519_shared_secret.obj src/prngs/chacha20.obj src/prngs/fortuna.obj src/prngs/rc4.obj \ +src/pk/x25519/x25519_shared_secret.obj src/pqc/mldsa.obj src/pqc/mldsa_export.obj src/pqc/mldsa_import.obj \ +src/pqc/mldsa_import_pkcs8.obj src/pqc/mldsa_import_x509.obj src/pqc/mlkem.obj src/pqc/mlkem_export.obj \ +src/pqc/mlkem_import.obj src/pqc/mlkem_import_pkcs8.obj src/pqc/mlkem_import_x509.obj src/pqc/slhdsa.obj \ +src/pqc/slhdsa_export.obj src/pqc/slhdsa_import.obj src/pqc/slhdsa_import_pkcs8.obj \ +src/pqc/slhdsa_import_x509.obj src/prngs/chacha20.obj src/prngs/fortuna.obj src/prngs/rc4.obj \ src/prngs/rng_get_bytes.obj src/prngs/rng_make_prng.obj src/prngs/sober128.obj src/prngs/sprng.obj \ src/prngs/yarrow.obj src/stream/chacha/chacha_crypt.obj src/stream/chacha/chacha_done.obj \ src/stream/chacha/chacha_ivctr32.obj src/stream/chacha/chacha_ivctr64.obj \ @@ -235,15 +239,16 @@ tests/dh_test.obj tests/dsa_test.obj tests/ecc_test.obj tests/ed25519_test.obj t tests/misc_test.obj tests/modes_test.obj tests/mpi_test.obj tests/multi_test.obj \ tests/no_null_termination_check_test.obj tests/no_prng.obj tests/padding_test.obj tests/pem_test.obj \ tests/pk_oid_test.obj tests/pkcs_1_eme_test.obj tests/pkcs_1_emsa_test.obj tests/pkcs_1_oaep_test.obj \ -tests/pkcs_1_pss_test.obj tests/pkcs_1_test.obj tests/prng_test.obj tests/rotate_test.obj tests/rsa_test.obj \ -tests/scrypt_test.obj tests/ssh_test.obj tests/store_test.obj tests/test.obj tests/x25519_test.obj +tests/pkcs_1_pss_test.obj tests/pkcs_1_test.obj tests/pqc_mldsa_test.obj tests/pqc_mlkem_test.obj \ +tests/pqc_slhdsa_test.obj tests/prng_test.obj tests/rotate_test.obj tests/rsa_test.obj tests/scrypt_test.obj \ +tests/ssh_test.obj tests/store_test.obj tests/test.obj tests/x25519_test.obj #The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ src/headers/tomcrypt_cipher.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_hash.h \ src/headers/tomcrypt_mac.h src/headers/tomcrypt_macros.h src/headers/tomcrypt_math.h \ src/headers/tomcrypt_misc.h src/headers/tomcrypt_pk.h src/headers/tomcrypt_pkcs.h \ -src/headers/tomcrypt_prng.h +src/headers/tomcrypt_pqc.h src/headers/tomcrypt_prng.h HEADERS=$(HEADERS_PUB) src/headers/tomcrypt_private.h diff --git a/makefile.unix b/makefile.unix index df169e288..0b478d8dc 100644 --- a/makefile.unix +++ b/makefile.unix @@ -233,7 +233,11 @@ src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_set.o src/pk/rsa/rsa_sign_hash.o \ src/pk/rsa/rsa_sign_saltlen_get.o src/pk/rsa/rsa_verify_hash.o src/pk/x25519/x25519_export.o \ src/pk/x25519/x25519_import.o src/pk/x25519/x25519_import_pkcs8.o src/pk/x25519/x25519_import_raw.o \ src/pk/x25519/x25519_import_x509.o src/pk/x25519/x25519_make_key.o \ -src/pk/x25519/x25519_shared_secret.o src/prngs/chacha20.o src/prngs/fortuna.o src/prngs/rc4.o \ +src/pk/x25519/x25519_shared_secret.o src/pqc/mldsa.o src/pqc/mldsa_export.o src/pqc/mldsa_import.o \ +src/pqc/mldsa_import_pkcs8.o src/pqc/mldsa_import_x509.o src/pqc/mlkem.o src/pqc/mlkem_export.o \ +src/pqc/mlkem_import.o src/pqc/mlkem_import_pkcs8.o src/pqc/mlkem_import_x509.o src/pqc/slhdsa.o \ +src/pqc/slhdsa_export.o src/pqc/slhdsa_import.o src/pqc/slhdsa_import_pkcs8.o \ +src/pqc/slhdsa_import_x509.o src/prngs/chacha20.o src/prngs/fortuna.o src/prngs/rc4.o \ src/prngs/rng_get_bytes.o src/prngs/rng_make_prng.o src/prngs/sober128.o src/prngs/sprng.o \ src/prngs/yarrow.o src/stream/chacha/chacha_crypt.o src/stream/chacha/chacha_done.o \ src/stream/chacha/chacha_ivctr32.o src/stream/chacha/chacha_ivctr64.o \ @@ -256,15 +260,16 @@ tests/dh_test.o tests/dsa_test.o tests/ecc_test.o tests/ed25519_test.o tests/fil tests/misc_test.o tests/modes_test.o tests/mpi_test.o tests/multi_test.o \ tests/no_null_termination_check_test.o tests/no_prng.o tests/padding_test.o tests/pem_test.o \ tests/pk_oid_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o \ -tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o \ -tests/scrypt_test.o tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o +tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/pqc_mldsa_test.o tests/pqc_mlkem_test.o \ +tests/pqc_slhdsa_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o tests/scrypt_test.o \ +tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o #The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ src/headers/tomcrypt_cipher.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_hash.h \ src/headers/tomcrypt_mac.h src/headers/tomcrypt_macros.h src/headers/tomcrypt_math.h \ src/headers/tomcrypt_misc.h src/headers/tomcrypt_pk.h src/headers/tomcrypt_pkcs.h \ -src/headers/tomcrypt_prng.h +src/headers/tomcrypt_pqc.h src/headers/tomcrypt_prng.h HEADERS=$(HEADERS_PUB) src/headers/tomcrypt_private.h diff --git a/makefile_include.mk b/makefile_include.mk index 52013d7f3..0327fe72f 100644 --- a/makefile_include.mk +++ b/makefile_include.mk @@ -404,7 +404,11 @@ src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_set.o src/pk/rsa/rsa_sign_hash.o \ src/pk/rsa/rsa_sign_saltlen_get.o src/pk/rsa/rsa_verify_hash.o src/pk/x25519/x25519_export.o \ src/pk/x25519/x25519_import.o src/pk/x25519/x25519_import_pkcs8.o src/pk/x25519/x25519_import_raw.o \ src/pk/x25519/x25519_import_x509.o src/pk/x25519/x25519_make_key.o \ -src/pk/x25519/x25519_shared_secret.o src/prngs/chacha20.o src/prngs/fortuna.o src/prngs/rc4.o \ +src/pk/x25519/x25519_shared_secret.o src/pqc/mldsa.o src/pqc/mldsa_export.o src/pqc/mldsa_import.o \ +src/pqc/mldsa_import_pkcs8.o src/pqc/mldsa_import_x509.o src/pqc/mlkem.o src/pqc/mlkem_export.o \ +src/pqc/mlkem_import.o src/pqc/mlkem_import_pkcs8.o src/pqc/mlkem_import_x509.o src/pqc/slhdsa.o \ +src/pqc/slhdsa_export.o src/pqc/slhdsa_import.o src/pqc/slhdsa_import_pkcs8.o \ +src/pqc/slhdsa_import_x509.o src/prngs/chacha20.o src/prngs/fortuna.o src/prngs/rc4.o \ src/prngs/rng_get_bytes.o src/prngs/rng_make_prng.o src/prngs/sober128.o src/prngs/sprng.o \ src/prngs/yarrow.o src/stream/chacha/chacha_crypt.o src/stream/chacha/chacha_done.o \ src/stream/chacha/chacha_ivctr32.o src/stream/chacha/chacha_ivctr64.o \ @@ -432,15 +436,16 @@ tests/dh_test.o tests/dsa_test.o tests/ecc_test.o tests/ed25519_test.o tests/fil tests/misc_test.o tests/modes_test.o tests/mpi_test.o tests/multi_test.o \ tests/no_null_termination_check_test.o tests/no_prng.o tests/padding_test.o tests/pem_test.o \ tests/pk_oid_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o \ -tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o \ -tests/scrypt_test.o tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o +tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/pqc_mldsa_test.o tests/pqc_mlkem_test.o \ +tests/pqc_slhdsa_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o tests/scrypt_test.o \ +tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o # The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ src/headers/tomcrypt_cipher.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_hash.h \ src/headers/tomcrypt_mac.h src/headers/tomcrypt_macros.h src/headers/tomcrypt_math.h \ src/headers/tomcrypt_misc.h src/headers/tomcrypt_pk.h src/headers/tomcrypt_pkcs.h \ -src/headers/tomcrypt_prng.h +src/headers/tomcrypt_pqc.h src/headers/tomcrypt_prng.h HEADERS=$(HEADERS_PUB) src/headers/tomcrypt_private.h diff --git a/sources.cmake b/sources.cmake index a192ed391..6fb3243ee 100644 --- a/sources.cmake +++ b/sources.cmake @@ -124,6 +124,7 @@ src/headers/tomcrypt_math.h src/headers/tomcrypt_misc.h src/headers/tomcrypt_pk.h src/headers/tomcrypt_pkcs.h +src/headers/tomcrypt_pqc.h src/headers/tomcrypt_private.h src/headers/tomcrypt_prng.h src/mac/blake2/blake2bmac.c @@ -496,6 +497,21 @@ src/pk/x25519/x25519_import_raw.c src/pk/x25519/x25519_import_x509.c src/pk/x25519/x25519_make_key.c src/pk/x25519/x25519_shared_secret.c +src/pqc/mldsa.c +src/pqc/mldsa_export.c +src/pqc/mldsa_import.c +src/pqc/mldsa_import_pkcs8.c +src/pqc/mldsa_import_x509.c +src/pqc/mlkem.c +src/pqc/mlkem_export.c +src/pqc/mlkem_import.c +src/pqc/mlkem_import_pkcs8.c +src/pqc/mlkem_import_x509.c +src/pqc/slhdsa.c +src/pqc/slhdsa_export.c +src/pqc/slhdsa_import.c +src/pqc/slhdsa_import_pkcs8.c +src/pqc/slhdsa_import_x509.c src/prngs/chacha20.c src/prngs/fortuna.c src/prngs/rc4.c @@ -549,6 +565,7 @@ src/headers/tomcrypt_math.h src/headers/tomcrypt_misc.h src/headers/tomcrypt_pk.h src/headers/tomcrypt_pkcs.h +src/headers/tomcrypt_pqc.h src/headers/tomcrypt_prng.h ) diff --git a/src/headers/tomcrypt.h b/src/headers/tomcrypt.h index 8fddb432c..e456132b1 100644 --- a/src/headers/tomcrypt.h +++ b/src/headers/tomcrypt.h @@ -88,6 +88,7 @@ enum { #include "tomcrypt_mac.h" #include "tomcrypt_prng.h" #include "tomcrypt_pk.h" +#include "tomcrypt_pqc.h" #include "tomcrypt_math.h" #include "tomcrypt_misc.h" #include "tomcrypt_argchk.h" diff --git a/src/headers/tomcrypt_custom.h b/src/headers/tomcrypt_custom.h index 970e9c67b..fcc70c99a 100644 --- a/src/headers/tomcrypt_custom.h +++ b/src/headers/tomcrypt_custom.h @@ -453,6 +453,11 @@ /* Ed25519 & X25519 */ #define LTC_CURVE25519 +/* Post-Quantum Cryptography */ +#define LTC_MLKEM +#define LTC_MLDSA +#define LTC_SLHDSA + /* ECC */ #define LTC_MECC diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h index a6b893128..15f74724a 100644 --- a/src/headers/tomcrypt_pk.h +++ b/src/headers/tomcrypt_pk.h @@ -39,6 +39,9 @@ enum ltc_pka_id { LTC_PKA_EC, LTC_PKA_X25519, LTC_PKA_ED25519, + LTC_PKA_MLDSA, + LTC_PKA_SLHDSA, + LTC_PKA_MLKEM, LTC_PKA_DH, LTC_PKA_NUM }; @@ -639,6 +642,36 @@ typedef struct { #endif #ifdef LTC_MRSA rsa_key rsa; +#endif +#ifdef LTC_MLKEM + struct { + int alg; + int type; + unsigned char *pk; + unsigned long pklen; + unsigned char *sk; + unsigned long sklen; + } mlkem; +#endif +#ifdef LTC_MLDSA + struct { + int alg; + int type; + unsigned char *pk; + unsigned long pklen; + unsigned char *sk; + unsigned long sklen; + } mldsa; +#endif +#ifdef LTC_SLHDSA + struct { + int alg; + int type; + unsigned char *pk; + unsigned long pklen; + unsigned char *sk; + unsigned long sklen; + } slhdsa; #endif char dummy; } u; diff --git a/src/headers/tomcrypt_pqc.h b/src/headers/tomcrypt_pqc.h new file mode 100644 index 000000000..016e7db2d --- /dev/null +++ b/src/headers/tomcrypt_pqc.h @@ -0,0 +1,176 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* ---- Post-Quantum Cryptography ---- */ + +/* ---- ML-KEM (FIPS 203) ---- */ +#ifdef LTC_MLKEM + +/** ML-KEM parameter set identifiers */ +enum ltc_mlkem_id { + LTC_MLKEM_512 = 0, + LTC_MLKEM_768 = 1, + LTC_MLKEM_1024 = 2 +}; + +/** ML-KEM key */ +typedef struct mlkem_key { + /** Algorithm identifier (ltc_mlkem_id) */ + int alg; + /** Type of key, PK_PRIVATE or PK_PUBLIC */ + int type; + /** Public key (encapsulation key) */ + unsigned char *pk; + unsigned long pklen; + /** Secret key (decapsulation key, private only) */ + unsigned char *sk; + unsigned long sklen; +} mlkem_key; + +int mlkem_make_key(prng_state *prng, int wprng, int alg, mlkem_key *key); +int mlkem_make_key_from_seed(int alg, const unsigned char *seed, unsigned long seedlen, mlkem_key *key); +void mlkem_free(mlkem_key *key); + +int mlkem_export(unsigned char *out, unsigned long *outlen, int which, const mlkem_key *key); +int mlkem_export_raw(unsigned char *out, unsigned long *outlen, int which, const mlkem_key *key); +int mlkem_import(const unsigned char *in, unsigned long inlen, mlkem_key *key); +int mlkem_import_raw(const unsigned char *in, unsigned long inlen, int which, int alg, mlkem_key *key); +int mlkem_import_x509(const unsigned char *in, unsigned long inlen, mlkem_key *key); +int mlkem_import_pkcs8(const unsigned char *in, unsigned long inlen, const password_ctx *pw_ctx, mlkem_key *key); + +int mlkem_encaps(unsigned char *ct, unsigned long *ctlen, + unsigned char *shared_secret, unsigned long *sslen, + prng_state *prng, int wprng, + const mlkem_key *key); + +int mlkem_decaps(unsigned char *shared_secret, unsigned long *sslen, + const unsigned char *ct, unsigned long ctlen, + const mlkem_key *key); + +int mlkem_get_sizes(int alg, unsigned long *public_key_sz, unsigned long *secret_key_sz, unsigned long *ciphertext_sz, unsigned long *shared_secret_sz); + +#endif /* LTC_MLKEM */ + + +/* ---- ML-DSA (FIPS 204) ---- */ +#ifdef LTC_MLDSA + +/** ML-DSA parameter set identifiers */ +enum ltc_mldsa_id { + LTC_MLDSA_44 = 0, + LTC_MLDSA_65 = 1, + LTC_MLDSA_87 = 2 +}; + +/** ML-DSA key */ +typedef struct mldsa_key { + /** Algorithm identifier (ltc_mldsa_id) */ + int alg; + /** Type of key, PK_PRIVATE or PK_PUBLIC */ + int type; + /** Public key (verification key) */ + unsigned char *pk; + unsigned long pklen; + /** Secret key (signing key, private only) */ + unsigned char *sk; + unsigned long sklen; +} mldsa_key; + +int mldsa_make_key(prng_state *prng, int wprng, int alg, mldsa_key *key); +int mldsa_make_key_from_seed(int alg, const unsigned char *seed, unsigned long seedlen, mldsa_key *key); +void mldsa_free(mldsa_key *key); + +int mldsa_export(unsigned char *out, unsigned long *outlen, int which, const mldsa_key *key); +int mldsa_export_raw(unsigned char *out, unsigned long *outlen, int which, const mldsa_key *key); +int mldsa_import(const unsigned char *in, unsigned long inlen, mldsa_key *key); +int mldsa_import_raw(const unsigned char *in, unsigned long inlen, int which, int alg, mldsa_key *key); +int mldsa_import_x509(const unsigned char *in, unsigned long inlen, mldsa_key *key); +int mldsa_import_pkcs8(const unsigned char *in, unsigned long inlen, const password_ctx *pw_ctx, mldsa_key *key); + +int mldsa_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + prng_state *prng, int wprng, + const mldsa_key *key); + +int mldsa_verify(const unsigned char *sig, unsigned long siglen, + const unsigned char *msg, unsigned long msglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const mldsa_key *key); + +int mldsa_get_sizes(int alg, unsigned long *public_key_sz, unsigned long *secret_key_sz, unsigned long *signature_sz); + +#endif /* LTC_MLDSA */ + + +/* ---- SLH-DSA (FIPS 205) ---- */ +#ifdef LTC_SLHDSA + +/** SLH-DSA parameter set identifiers */ +enum ltc_slhdsa_id { + LTC_SLHDSA_SHA2_128S = 0, + LTC_SLHDSA_SHA2_128F = 1, + LTC_SLHDSA_SHA2_192S = 2, + LTC_SLHDSA_SHA2_192F = 3, + LTC_SLHDSA_SHA2_256S = 4, + LTC_SLHDSA_SHA2_256F = 5, + LTC_SLHDSA_SHAKE_128S = 6, + LTC_SLHDSA_SHAKE_128F = 7, + LTC_SLHDSA_SHAKE_192S = 8, + LTC_SLHDSA_SHAKE_192F = 9, + LTC_SLHDSA_SHAKE_256S = 10, + LTC_SLHDSA_SHAKE_256F = 11, + LTC_SLHDSA_HASH_SHA2_128S_WITH_SHA256 = 12, + LTC_SLHDSA_HASH_SHA2_128F_WITH_SHA256 = 13, + LTC_SLHDSA_HASH_SHA2_192S_WITH_SHA512 = 14, + LTC_SLHDSA_HASH_SHA2_192F_WITH_SHA512 = 15, + LTC_SLHDSA_HASH_SHA2_256S_WITH_SHA512 = 16, + LTC_SLHDSA_HASH_SHA2_256F_WITH_SHA512 = 17, + LTC_SLHDSA_HASH_SHAKE_128S_WITH_SHAKE128 = 18, + LTC_SLHDSA_HASH_SHAKE_128F_WITH_SHAKE128 = 19, + LTC_SLHDSA_HASH_SHAKE_192S_WITH_SHAKE256 = 20, + LTC_SLHDSA_HASH_SHAKE_192F_WITH_SHAKE256 = 21, + LTC_SLHDSA_HASH_SHAKE_256S_WITH_SHAKE256 = 22, + LTC_SLHDSA_HASH_SHAKE_256F_WITH_SHAKE256 = 23 +}; + +/** SLH-DSA key */ +typedef struct slhdsa_key { + /** Algorithm identifier (ltc_slhdsa_id) */ + int alg; + /** Type of key, PK_PRIVATE or PK_PUBLIC */ + int type; + /** Public key (verification key) */ + unsigned char *pk; + unsigned long pklen; + /** Secret key (signing key, private only) */ + unsigned char *sk; + unsigned long sklen; +} slhdsa_key; + +int slhdsa_make_key(prng_state *prng, int wprng, int alg, slhdsa_key *key); +void slhdsa_free(slhdsa_key *key); + +int slhdsa_export(unsigned char *out, unsigned long *outlen, int which, const slhdsa_key *key); +int slhdsa_export_raw(unsigned char *out, unsigned long *outlen, int which, const slhdsa_key *key); +int slhdsa_import(const unsigned char *in, unsigned long inlen, slhdsa_key *key); +int slhdsa_import_raw(const unsigned char *in, unsigned long inlen, int which, int alg, slhdsa_key *key); +int slhdsa_import_x509(const unsigned char *in, unsigned long inlen, slhdsa_key *key); +int slhdsa_import_pkcs8(const unsigned char *in, unsigned long inlen, const password_ctx *pw_ctx, slhdsa_key *key); + +int slhdsa_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + prng_state *prng, int wprng, + const slhdsa_key *key); + +int slhdsa_verify(const unsigned char *sig, unsigned long siglen, + const unsigned char *msg, unsigned long msglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const slhdsa_key *key); + +int slhdsa_get_sizes(int alg, unsigned long *public_key_sz, unsigned long *secret_key_sz, unsigned long *signature_sz); + +#endif /* LTC_SLHDSA */ diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index 4de5e5edc..27123c7b0 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -59,6 +59,36 @@ enum ltc_oid_id { LTC_OID_EC_PRIMEF, LTC_OID_X25519, LTC_OID_ED25519, + LTC_OID_MLDSA_44, + LTC_OID_MLDSA_65, + LTC_OID_MLDSA_87, + LTC_OID_SLHDSA_SHA2_128S, + LTC_OID_SLHDSA_SHA2_128F, + LTC_OID_SLHDSA_SHA2_192S, + LTC_OID_SLHDSA_SHA2_192F, + LTC_OID_SLHDSA_SHA2_256S, + LTC_OID_SLHDSA_SHA2_256F, + LTC_OID_SLHDSA_SHAKE_128S, + LTC_OID_SLHDSA_SHAKE_128F, + LTC_OID_SLHDSA_SHAKE_192S, + LTC_OID_SLHDSA_SHAKE_192F, + LTC_OID_SLHDSA_SHAKE_256S, + LTC_OID_SLHDSA_SHAKE_256F, + LTC_OID_HASH_SLHDSA_SHA2_128S_WITH_SHA256, + LTC_OID_HASH_SLHDSA_SHA2_128F_WITH_SHA256, + LTC_OID_HASH_SLHDSA_SHA2_192S_WITH_SHA512, + LTC_OID_HASH_SLHDSA_SHA2_192F_WITH_SHA512, + LTC_OID_HASH_SLHDSA_SHA2_256S_WITH_SHA512, + LTC_OID_HASH_SLHDSA_SHA2_256F_WITH_SHA512, + LTC_OID_HASH_SLHDSA_SHAKE_128S_WITH_SHAKE128, + LTC_OID_HASH_SLHDSA_SHAKE_128F_WITH_SHAKE128, + LTC_OID_HASH_SLHDSA_SHAKE_192S_WITH_SHAKE256, + LTC_OID_HASH_SLHDSA_SHAKE_192F_WITH_SHAKE256, + LTC_OID_HASH_SLHDSA_SHAKE_256S_WITH_SHAKE256, + LTC_OID_HASH_SLHDSA_SHAKE_256F_WITH_SHAKE256, + LTC_OID_MLKEM_512, + LTC_OID_MLKEM_768, + LTC_OID_MLKEM_1024, LTC_OID_DH, LTC_OID_NUM }; @@ -652,6 +682,16 @@ int ec25519_crypto_ctx( unsigned char *out, unsigned long *outlen, const unsigned char *ctx, unsigned long ctxlen); #endif /* LTC_CURVE25519 */ +#ifdef LTC_MLKEM +int mlkem_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, mlkem_key *key); +#endif +#ifdef LTC_MLDSA +int mldsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, mldsa_key *key); +#endif +#ifdef LTC_SLHDSA +int slhdsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, slhdsa_key *key); +#endif + #ifdef LTC_DER #define LTC_ASN1_IS_TYPE(e, t) (((e) != NULL) && ((e)->type == (t))) diff --git a/src/misc/crypt/crypt.c b/src/misc/crypt/crypt.c index a07a191ba..f924551bf 100644 --- a/src/misc/crypt/crypt.c +++ b/src/misc/crypt/crypt.c @@ -378,6 +378,15 @@ const char *crypt_build_settings = " X25519\n" #endif #endif +#if defined(LTC_MLKEM) + " ML-KEM\n" +#endif +#if defined(LTC_MLDSA) + " ML-DSA\n" +#endif +#if defined(LTC_SLHDSA) + " SLH-DSA\n" +#endif #if defined(LTC_PK_MAX_RETRIES) " "NAME_VALUE(LTC_PK_MAX_RETRIES)"\n" #endif diff --git a/src/misc/pem/pem_pkcs.c b/src/misc/pem/pem_pkcs.c index 17aa47705..03f8872c9 100644 --- a/src/misc/pem/pem_pkcs.c +++ b/src/misc/pem/pem_pkcs.c @@ -63,6 +63,42 @@ static const struct { [LTC_OID_X25519] = { LTC_PKA_X25519, (pkcs8_import_fn)x25519_import_pkcs8_asn1 }, [LTC_OID_ED25519] = { LTC_PKA_ED25519, (pkcs8_import_fn)ed25519_import_pkcs8_asn1 }, #endif +#ifdef LTC_MLDSA + [LTC_OID_MLDSA_44] = { LTC_PKA_MLDSA, (pkcs8_import_fn)mldsa_import_pkcs8_asn1 }, + [LTC_OID_MLDSA_65] = { LTC_PKA_MLDSA, (pkcs8_import_fn)mldsa_import_pkcs8_asn1 }, + [LTC_OID_MLDSA_87] = { LTC_PKA_MLDSA, (pkcs8_import_fn)mldsa_import_pkcs8_asn1 }, +#endif +#ifdef LTC_SLHDSA + [LTC_OID_SLHDSA_SHA2_128S] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_SLHDSA_SHA2_128F] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_SLHDSA_SHA2_192S] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_SLHDSA_SHA2_192F] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_SLHDSA_SHA2_256S] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_SLHDSA_SHA2_256F] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_SLHDSA_SHAKE_128S] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_SLHDSA_SHAKE_128F] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_SLHDSA_SHAKE_192S] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_SLHDSA_SHAKE_192F] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_SLHDSA_SHAKE_256S] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_SLHDSA_SHAKE_256F] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_HASH_SLHDSA_SHA2_128S_WITH_SHA256] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_HASH_SLHDSA_SHA2_128F_WITH_SHA256] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_HASH_SLHDSA_SHA2_192S_WITH_SHA512] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_HASH_SLHDSA_SHA2_192F_WITH_SHA512] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_HASH_SLHDSA_SHA2_256S_WITH_SHA512] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_HASH_SLHDSA_SHA2_256F_WITH_SHA512] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_HASH_SLHDSA_SHAKE_128S_WITH_SHAKE128] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_HASH_SLHDSA_SHAKE_128F_WITH_SHAKE128] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_HASH_SLHDSA_SHAKE_192S_WITH_SHAKE256] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_HASH_SLHDSA_SHAKE_192F_WITH_SHAKE256] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_HASH_SLHDSA_SHAKE_256S_WITH_SHAKE256] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, + [LTC_OID_HASH_SLHDSA_SHAKE_256F_WITH_SHAKE256] = { LTC_PKA_SLHDSA, (pkcs8_import_fn)slhdsa_import_pkcs8_asn1 }, +#endif +#ifdef LTC_MLKEM + [LTC_OID_MLKEM_512] = { LTC_PKA_MLKEM, (pkcs8_import_fn)mlkem_import_pkcs8_asn1 }, + [LTC_OID_MLKEM_768] = { LTC_PKA_MLKEM, (pkcs8_import_fn)mlkem_import_pkcs8_asn1 }, + [LTC_OID_MLKEM_1024] = { LTC_PKA_MLKEM, (pkcs8_import_fn)mlkem_import_pkcs8_asn1 }, +#endif }; static int s_import_pkcs8(unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, const password_ctx *pw_ctx) @@ -122,6 +158,15 @@ static const import_fn s_import_openssl_fns[LTC_PKA_NUM] = { [LTC_PKA_X25519] = (import_fn)x25519_import, [LTC_PKA_ED25519] = (import_fn)ed25519_import, #endif +#ifdef LTC_MLDSA + [LTC_PKA_MLDSA] = (import_fn)mldsa_import, +#endif +#ifdef LTC_SLHDSA + [LTC_PKA_SLHDSA] = (import_fn)slhdsa_import, +#endif +#ifdef LTC_MLKEM + [LTC_PKA_MLKEM] = (import_fn)mlkem_import, +#endif }; static int s_decode(struct get_char *g, ltc_pka_key *k, const password_ctx *pw_ctx) diff --git a/src/pk/asn1/der/integer/der_decode_integer.c b/src/pk/asn1/der/integer/der_decode_integer.c index e2555b92a..4481ac238 100644 --- a/src/pk/asn1/der/integer/der_decode_integer.c +++ b/src/pk/asn1/der/integer/der_decode_integer.c @@ -25,6 +25,11 @@ int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num) LTC_ARGCHK(num != NULL); LTC_ARGCHK(in != NULL); + /* DER INTEGER decodes into an MPI, so fail cleanly when no math provider is active. */ + if (ltc_mp.name == NULL) { + return CRYPT_INVALID_ARG; + } + /* min DER INTEGER is 0x02 01 00 == 0 */ if (inlen < (1 + 1 + 1)) { return CRYPT_INVALID_PACKET; diff --git a/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c b/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c index ada1bd67a..422e12d9c 100644 --- a/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c +++ b/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c @@ -153,6 +153,12 @@ static int s_der_decode_sequence_flexi(const unsigned char *in, unsigned long *i goto error; } + /* Flexi INTEGER nodes are MPI-backed, so reject no-math builds before ltc_mp_init(). */ + if (ltc_mp.name == NULL) { + err = CRYPT_INVALID_ARG; + goto error; + } + /* init field */ l->size = 1; if ((err = ltc_mp_init(&l->data)) != CRYPT_OK) { diff --git a/src/pk/asn1/oid/pk_get.c b/src/pk/asn1/oid/pk_get.c index 1fd5872e2..cb6801bee 100644 --- a/src/pk/asn1/oid/pk_get.c +++ b/src/pk/asn1/oid/pk_get.c @@ -18,6 +18,36 @@ static const oid_table_entry pka_oids[] = { { LTC_OID_EC_PRIMEF, LTC_PKA_EC, "1.2.840.10045.1.1" }, { LTC_OID_X25519, LTC_PKA_X25519, "1.3.101.110" }, { LTC_OID_ED25519, LTC_PKA_ED25519, "1.3.101.112" }, + { LTC_OID_MLDSA_44, LTC_PKA_MLDSA, "2.16.840.1.101.3.4.3.17" }, + { LTC_OID_MLDSA_65, LTC_PKA_MLDSA, "2.16.840.1.101.3.4.3.18" }, + { LTC_OID_MLDSA_87, LTC_PKA_MLDSA, "2.16.840.1.101.3.4.3.19" }, + { LTC_OID_SLHDSA_SHA2_128S, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.20" }, + { LTC_OID_SLHDSA_SHA2_128F, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.21" }, + { LTC_OID_SLHDSA_SHA2_192S, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.22" }, + { LTC_OID_SLHDSA_SHA2_192F, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.23" }, + { LTC_OID_SLHDSA_SHA2_256S, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.24" }, + { LTC_OID_SLHDSA_SHA2_256F, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.25" }, + { LTC_OID_SLHDSA_SHAKE_128S, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.26" }, + { LTC_OID_SLHDSA_SHAKE_128F, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.27" }, + { LTC_OID_SLHDSA_SHAKE_192S, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.28" }, + { LTC_OID_SLHDSA_SHAKE_192F, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.29" }, + { LTC_OID_SLHDSA_SHAKE_256S, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.30" }, + { LTC_OID_SLHDSA_SHAKE_256F, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.31" }, + { LTC_OID_HASH_SLHDSA_SHA2_128S_WITH_SHA256, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.35" }, + { LTC_OID_HASH_SLHDSA_SHA2_128F_WITH_SHA256, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.36" }, + { LTC_OID_HASH_SLHDSA_SHA2_192S_WITH_SHA512, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.37" }, + { LTC_OID_HASH_SLHDSA_SHA2_192F_WITH_SHA512, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.38" }, + { LTC_OID_HASH_SLHDSA_SHA2_256S_WITH_SHA512, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.39" }, + { LTC_OID_HASH_SLHDSA_SHA2_256F_WITH_SHA512, LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.40" }, + { LTC_OID_HASH_SLHDSA_SHAKE_128S_WITH_SHAKE128,LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.41" }, + { LTC_OID_HASH_SLHDSA_SHAKE_128F_WITH_SHAKE128,LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.42" }, + { LTC_OID_HASH_SLHDSA_SHAKE_192S_WITH_SHAKE256,LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.43" }, + { LTC_OID_HASH_SLHDSA_SHAKE_192F_WITH_SHAKE256,LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.44" }, + { LTC_OID_HASH_SLHDSA_SHAKE_256S_WITH_SHAKE256,LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.45" }, + { LTC_OID_HASH_SLHDSA_SHAKE_256F_WITH_SHAKE256,LTC_PKA_SLHDSA, "2.16.840.1.101.3.4.3.46" }, + { LTC_OID_MLKEM_512, LTC_PKA_MLKEM, "2.16.840.1.101.3.4.4.1" }, + { LTC_OID_MLKEM_768, LTC_PKA_MLKEM, "2.16.840.1.101.3.4.4.2" }, + { LTC_OID_MLKEM_1024,LTC_PKA_MLKEM, "2.16.840.1.101.3.4.4.3" }, { LTC_OID_DH, LTC_PKA_DH, "1.2.840.113549.1.3.1" }, }; diff --git a/src/pk/asn1/x509/x509_import_spki.c b/src/pk/asn1/x509/x509_import_spki.c index 8b360852e..13fff8e17 100644 --- a/src/pk/asn1/x509/x509_import_spki.c +++ b/src/pk/asn1/x509/x509_import_spki.c @@ -25,6 +25,15 @@ static const import_fn s_import_x509_fns[LTC_PKA_NUM] = { [LTC_PKA_X25519] = (import_fn)x25519_import_x509, [LTC_PKA_ED25519] = (import_fn)ed25519_import_x509, #endif +#ifdef LTC_MLKEM + [LTC_PKA_MLKEM] = (import_fn)mlkem_import_x509, +#endif +#ifdef LTC_MLDSA + [LTC_PKA_MLDSA] = (import_fn)mldsa_import_x509, +#endif +#ifdef LTC_SLHDSA + [LTC_PKA_SLHDSA] = (import_fn)slhdsa_import_x509, +#endif }; int x509_import_spki(const unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, ltc_asn1_list **root) diff --git a/src/pk/pka_key.c b/src/pk/pka_key.c index d88ee3d30..9668ee505 100644 --- a/src/pk/pka_key.c +++ b/src/pk/pka_key.c @@ -37,6 +37,21 @@ void pka_key_free(ltc_pka_key *key) case LTC_PKA_EC: #if defined(LTC_MECC) ecc_free(&key->u.ecc); +#endif + break; + case LTC_PKA_MLDSA: +#if defined(LTC_MLDSA) + mldsa_free((mldsa_key*)&key->u.mldsa); +#endif + break; + case LTC_PKA_SLHDSA: +#if defined(LTC_SLHDSA) + slhdsa_free((slhdsa_key*)&key->u.slhdsa); +#endif + break; + case LTC_PKA_MLKEM: +#if defined(LTC_MLKEM) + mlkem_free((mlkem_key*)&key->u.mlkem); #endif break; default: diff --git a/src/pqc/mldsa.c b/src/pqc/mldsa.c new file mode 100644 index 000000000..6d531487d --- /dev/null +++ b/src/pqc/mldsa.c @@ -0,0 +1,1877 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file mldsa.c + ML-DSA (FIPS 204) implementation: polynomial arithmetic, NTT, packing, + signing, and verification. + Based on the CRYSTALS-Dilithium reference implementation (public domain). +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_MLDSA + +/* Constants */ + +#define MLDSA_N 256 +#define MLDSA_Q 8380417 +#define MLDSA_D 13 +#define MLDSA_QINV 58728449 /* Q^{-1} mod 2^32 */ + +#define MLDSA_SEEDBYTES 32 +#define MLDSA_CRHBYTES 64 +#define MLDSA_TRBYTES 64 +#define MLDSA_RNDBYTES 32 + +#define MLDSA_K_MAX 8 +#define MLDSA_L_MAX 7 + +#define MLDSA_POLYT1_PACKEDBYTES 320 +#define MLDSA_POLYT0_PACKEDBYTES 416 + +#define MLDSA_SHAKE128_RATE 168 +#define MLDSA_SHAKE256_RATE 136 + +/* Runtime parameter set */ + +typedef struct { + int k, l, eta, tau, omega; + int beta; + int gamma1, gamma2; + int ctilde_bytes; + unsigned long polyz_packed, polyw1_packed, polyeta_packed; + unsigned long pk_bytes, sk_bytes, sig_bytes; +} mldsa_params; + +/* Polynomial types */ + +typedef struct { + int coeffs[MLDSA_N]; +} mldsa_poly; + +typedef struct { + mldsa_poly vec[MLDSA_L_MAX]; +} mldsa_polyvecl; + +typedef struct { + mldsa_poly vec[MLDSA_K_MAX]; +} mldsa_polyveck; + +/* Montgomery / Barrett reduction */ + +static int s_mldsa_montgomery_reduce(long64 a) +{ + int t; + t = (long64)(int)a * MLDSA_QINV; + t = (a - (long64)t * MLDSA_Q) >> 32; + return t; +} + +static int s_mldsa_reduce32(int a) +{ + int t; + t = (a + (1 << 22)) >> 23; + t = a - t * MLDSA_Q; + return t; +} + +static int s_mldsa_caddq(int a) +{ + a += (a >> 31) & MLDSA_Q; + return a; +} + + +/* NTT */ + +static const int s_mldsa_zetas[MLDSA_N] = { + 0, 25847, -2608894, -518909, 237124, -777960, -876248, 466468, + 1826347, 2353451, -359251, -2091905, 3119733, -2884855, 3111497, 2680103, + 2725464, 1024112, -1079900, 3585928, -549488, -1119584, 2619752, -2108549, + -2118186, -3859737, -1399561, -3277672, 1757237, -19422, 4010497, 280005, + 2706023, 95776, 3077325, 3530437, -1661693, -3592148, -2537516, 3915439, + -3861115, -3043716, 3574422, -2867647, 3539968, -300467, 2348700, -539299, + -1699267, -1643818, 3505694, -3821735, 3507263, -2140649, -1600420, 3699596, + 811944, 531354, 954230, 3881043, 3900724, -2556880, 2071892, -2797779, + -3930395, -1528703, -3677745, -3041255, -1452451, 3475950, 2176455, -1585221, + -1257611, 1939314, -4083598, -1000202, -3190144, -3157330, -3632928, 126922, + 3412210, -983419, 2147896, 2715295, -2967645, -3693493, -411027, -2477047, + -671102, -1228525, -22981, -1308169, -381987, 1349076, 1852771, -1430430, + -3343383, 264944, 508951, 3097992, 44288, -1100098, 904516, 3958618, + -3724342, -8578, 1653064, -3249728, 2389356, -210977, 759969, -1316856, + 189548, -3553272, 3159746, -1851402, -2409325, -177440, 1315589, 1341330, + 1285669, -1584928, -812732, -1439742, -3019102, -3881060, -3628969, 3839961, + 2091667, 3407706, 2316500, 3817976, -3342478, 2244091, -2446433, -3562462, + 266997, 2434439, -1235728, 3513181, -3520352, -3759364, -1197226, -3193378, + 900702, 1859098, 909542, 819034, 495491, -1613174, -43260, -522500, + -655327, -3122442, 2031748, 3207046, -3556995, -525098, -768622, -3595838, + 342297, 286988, -2437823, 4108315, 3437287, -3342277, 1735879, 203044, + 2842341, 2691481, -2590150, 1265009, 4055324, 1247620, 2486353, 1595974, + -3767016, 1250494, 2635921, -3548272, -2994039, 1869119, 1903435, -1050970, + -1333058, 1237275, -3318210, -1430225, -451100, 1312455, 3306115, -1962642, + -1279661, 1917081, -2546312, -1374803, 1500165, 777191, 2235880, 3406031, + -542412, -2831860, -1671176, -1846953, -2584293, -3724270, 594136, -3776993, + -2013608, 2432395, 2454455, -164721, 1957272, 3369112, 185531, -1207385, + -3183426, 162844, 1616392, 3014001, 810149, 1652634, -3694233, -1799107, + -3038916, 3523897, 3866901, 269760, 2213111, -975884, 1717735, 472078, + -426683, 1723600, -1803090, 1910376, -1667432, -1104333, -260646, -3833893, + -2939036, -2235985, -420899, -2286327, 183443, -976891, 1612842, -3545687, + -554416, 3919660, -48306, -1362209, 3937738, 1400424, -846154, 1976782 +}; + +static void s_mldsa_ntt(int a[MLDSA_N]) +{ + unsigned int len, start, j, k; + int zeta, t; + + k = 0; + for (len = 128; len > 0; len >>= 1) { + for (start = 0; start < (unsigned)MLDSA_N; start = j + len) { + zeta = s_mldsa_zetas[++k]; + for (j = start; j < start + len; ++j) { + t = s_mldsa_montgomery_reduce((long64)zeta * a[j + len]); + a[j + len] = a[j] - t; + a[j] = a[j] + t; + } + } + } +} + +static void s_mldsa_invntt_tomont(int a[MLDSA_N]) +{ + unsigned int start, len, j, k; + int t, zeta; + const int f = 41978; /* mont^2/256 */ + + k = 256; + for (len = 1; len < (unsigned)MLDSA_N; len <<= 1) { + for (start = 0; start < (unsigned)MLDSA_N; start = j + len) { + zeta = -s_mldsa_zetas[--k]; + for (j = start; j < start + len; ++j) { + t = a[j]; + a[j] = t + a[j + len]; + a[j + len] = t - a[j + len]; + a[j + len] = s_mldsa_montgomery_reduce((long64)zeta * a[j + len]); + } + } + } + + for (j = 0; j < (unsigned)MLDSA_N; ++j) { + a[j] = s_mldsa_montgomery_reduce((long64)f * a[j]); + } +} + +/* Rounding */ + +static int s_power2round(int *a0, int a) +{ + int a1; + a1 = (a + (1 << (MLDSA_D - 1)) - 1) >> MLDSA_D; + *a0 = a - (a1 << MLDSA_D); + return a1; +} + +static int s_decompose(int *a0, int a, int gamma2) +{ + int a1; + + a1 = (a + 127) >> 7; + if (gamma2 == (MLDSA_Q - 1) / 32) { + a1 = (a1 * 1025 + (1 << 21)) >> 22; + a1 &= 15; + } else { + /* gamma2 == (MLDSA_Q - 1) / 88 */ + a1 = (a1 * 11275 + (1 << 23)) >> 24; + a1 ^= ((43 - a1) >> 31) & a1; + } + + *a0 = a - a1 * 2 * gamma2; + *a0 -= (((MLDSA_Q - 1) / 2 - *a0) >> 31) & MLDSA_Q; + return a1; +} + +static unsigned int s_make_hint(int a0, int a1, int gamma2) +{ + if (a0 > gamma2 || a0 < -gamma2 || (a0 == -gamma2 && a1 != 0)) + return 1; + return 0; +} + +static int s_use_hint(int a, unsigned int hint, int gamma2) +{ + int a0, a1; + + a1 = s_decompose(&a0, a, gamma2); + if (hint == 0) + return a1; + + if (gamma2 == (MLDSA_Q - 1) / 32) { + if (a0 > 0) + return (a1 + 1) & 15; + else + return (a1 - 1) & 15; + } else { + /* gamma2 == (MLDSA_Q - 1) / 88 */ + if (a0 > 0) + return (a1 == 43) ? 0 : a1 + 1; + else + return (a1 == 0) ? 43 : a1 - 1; + } +} + +/* Parameter lookup */ + +static int s_mldsa_get_params(int alg, mldsa_params *p) +{ + LTC_ARGCHK(p != NULL); + + XMEMSET(p, 0, sizeof(*p)); + + switch (alg) { + case LTC_MLDSA_44: + p->k = 4; p->l = 4; p->eta = 2; p->tau = 39; + p->beta = 78; p->gamma1 = (1 << 17); + p->gamma2 = (MLDSA_Q - 1) / 88; p->omega = 80; + p->ctilde_bytes = 32; + break; + case LTC_MLDSA_65: + p->k = 6; p->l = 5; p->eta = 4; p->tau = 49; + p->beta = 196; p->gamma1 = (1 << 19); + p->gamma2 = (MLDSA_Q - 1) / 32; p->omega = 55; + p->ctilde_bytes = 48; + break; + case LTC_MLDSA_87: + p->k = 8; p->l = 7; p->eta = 2; p->tau = 60; + p->beta = 120; p->gamma1 = (1 << 19); + p->gamma2 = (MLDSA_Q - 1) / 32; p->omega = 75; + p->ctilde_bytes = 64; + break; + default: + return CRYPT_INVALID_ARG; + } + + p->polyz_packed = (p->gamma1 == (1 << 17)) ? 576u : 640u; + p->polyw1_packed = (p->gamma2 == (MLDSA_Q - 1) / 88) ? 192u : 128u; + p->polyeta_packed = (p->eta == 2) ? 96u : 128u; + p->pk_bytes = MLDSA_SEEDBYTES + (unsigned long)p->k * MLDSA_POLYT1_PACKEDBYTES; + p->sk_bytes = 2u * MLDSA_SEEDBYTES + MLDSA_TRBYTES + + (unsigned long)p->l * p->polyeta_packed + + (unsigned long)p->k * p->polyeta_packed + + (unsigned long)p->k * MLDSA_POLYT0_PACKEDBYTES; + p->sig_bytes = (unsigned long)p->ctilde_bytes + + (unsigned long)p->l * p->polyz_packed + + (unsigned long)p->omega + (unsigned long)p->k; + + return CRYPT_OK; +} + +/* Symmetric primitives using libtomcrypt SHA3 */ + +static int s_shake256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) +{ + int err; + hash_state md; + + if ((err = sha3_shake_init(&md, 256)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, in, inlen)) != CRYPT_OK) return err; + return sha3_shake_done(&md, out, outlen); +} + +static int s_shake128_stream_init(hash_state *state, + const unsigned char seed[MLDSA_SEEDBYTES], + unsigned int nonce) +{ + int err; + unsigned char t[2]; + t[0] = (unsigned char)(nonce & 0xff); + t[1] = (unsigned char)(nonce >> 8); + + if ((err = sha3_shake_init(state, 128)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(state, seed, MLDSA_SEEDBYTES)) != CRYPT_OK) return err; + return sha3_shake_process(state, t, 2); +} + +static int s_shake256_stream_init(hash_state *state, + const unsigned char *seed, + unsigned long seedlen, + unsigned int nonce) +{ + int err; + unsigned char t[2]; + t[0] = (unsigned char)(nonce & 0xff); + t[1] = (unsigned char)(nonce >> 8); + + if ((err = sha3_shake_init(state, 256)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(state, seed, seedlen)) != CRYPT_OK) return err; + return sha3_shake_process(state, t, 2); +} + +/* Poly operations */ + +static void s_mldsa_poly_reduce(mldsa_poly *a) +{ + unsigned int i; + for (i = 0; i < MLDSA_N; ++i) + a->coeffs[i] = s_mldsa_reduce32(a->coeffs[i]); +} + +static void s_poly_caddq(mldsa_poly *a) +{ + unsigned int i; + for (i = 0; i < MLDSA_N; ++i) + a->coeffs[i] = s_mldsa_caddq(a->coeffs[i]); +} + +static void s_mldsa_poly_add(mldsa_poly *c, const mldsa_poly *a, const mldsa_poly *b) +{ + unsigned int i; + for (i = 0; i < MLDSA_N; ++i) + c->coeffs[i] = a->coeffs[i] + b->coeffs[i]; +} + +static void s_mldsa_poly_sub(mldsa_poly *c, const mldsa_poly *a, const mldsa_poly *b) +{ + unsigned int i; + for (i = 0; i < MLDSA_N; ++i) + c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; +} + +static void s_poly_shiftl(mldsa_poly *a) +{ + unsigned int i; + for (i = 0; i < MLDSA_N; ++i) + a->coeffs[i] <<= MLDSA_D; +} + +static void s_mldsa_poly_ntt(mldsa_poly *a) +{ + s_mldsa_ntt(a->coeffs); +} + +static void s_mldsa_poly_invntt_tomont(mldsa_poly *a) +{ + s_mldsa_invntt_tomont(a->coeffs); +} + +static void s_poly_pointwise_montgomery(mldsa_poly *c, const mldsa_poly *a, const mldsa_poly *b) +{ + unsigned int i; + for (i = 0; i < MLDSA_N; ++i) + c->coeffs[i] = s_mldsa_montgomery_reduce((long64)a->coeffs[i] * b->coeffs[i]); +} + +static void s_poly_power2round(mldsa_poly *a1, mldsa_poly *a0, const mldsa_poly *a) +{ + unsigned int i; + for (i = 0; i < MLDSA_N; ++i) + a1->coeffs[i] = s_power2round(&a0->coeffs[i], a->coeffs[i]); +} + +static void s_poly_decompose(mldsa_poly *a1, mldsa_poly *a0, const mldsa_poly *a, int gamma2) +{ + unsigned int i; + for (i = 0; i < MLDSA_N; ++i) + a1->coeffs[i] = s_decompose(&a0->coeffs[i], a->coeffs[i], gamma2); +} + +static unsigned int s_poly_make_hint(mldsa_poly *h, const mldsa_poly *a0, + const mldsa_poly *a1, int gamma2) +{ + unsigned int i, s = 0; + for (i = 0; i < MLDSA_N; ++i) { + h->coeffs[i] = s_make_hint(a0->coeffs[i], a1->coeffs[i], gamma2); + s += h->coeffs[i]; + } + return s; +} + +static void s_poly_use_hint(mldsa_poly *b, const mldsa_poly *a, const mldsa_poly *h, int gamma2) +{ + unsigned int i; + for (i = 0; i < MLDSA_N; ++i) + b->coeffs[i] = s_use_hint(a->coeffs[i], h->coeffs[i], gamma2); +} + +static int s_poly_chknorm(const mldsa_poly *a, int B) +{ + unsigned int i; + int t; + + if (B > (MLDSA_Q - 1) / 8) + return 1; + + for (i = 0; i < MLDSA_N; ++i) { + t = a->coeffs[i] >> 31; + t = a->coeffs[i] - (t & 2 * a->coeffs[i]); + if (t >= B) + return 1; + } + return 0; +} + +/* Sampling */ + +static unsigned int s_rej_uniform(int *a, unsigned int len, + const unsigned char *buf, unsigned int buflen) +{ + unsigned int ctr, pos; + ulong32 t; + + ctr = pos = 0; + while (ctr < len && pos + 3 <= buflen) { + t = buf[pos++]; + t |= (ulong32)buf[pos++] << 8; + t |= (ulong32)buf[pos++] << 16; + t &= 0x7FFFFF; + + if (t < (ulong32)MLDSA_Q) + a[ctr++] = (int)t; + } + + return ctr; +} + +static int s_poly_uniform(mldsa_poly *a, const unsigned char seed[MLDSA_SEEDBYTES], + unsigned int nonce) +{ + unsigned int ctr, off, i; + /* SHAKE128 rate = 168. We need ceil(768/168)=5 blocks initially */ + #define S_POLY_UNIFORM_NBLOCKS ((768 + MLDSA_SHAKE128_RATE - 1) / MLDSA_SHAKE128_RATE) + unsigned int buflen = S_POLY_UNIFORM_NBLOCKS * MLDSA_SHAKE128_RATE; + unsigned char buf[S_POLY_UNIFORM_NBLOCKS * MLDSA_SHAKE128_RATE + 2]; + hash_state state; + int err; + + if ((err = s_shake128_stream_init(&state, seed, nonce)) != CRYPT_OK) return err; + if ((err = sha3_shake_done(&state, buf, buflen)) != CRYPT_OK) return err; + + ctr = s_rej_uniform(a->coeffs, MLDSA_N, buf, buflen); + + while (ctr < MLDSA_N) { + off = buflen % 3; + for (i = 0; i < off; ++i) + buf[i] = buf[buflen - off + i]; + + /* sha3_shake_done supports incremental squeezing */ + if ((err = sha3_shake_done(&state, buf + off, MLDSA_SHAKE128_RATE)) != CRYPT_OK) return err; + buflen = MLDSA_SHAKE128_RATE + off; + ctr += s_rej_uniform(a->coeffs + ctr, MLDSA_N - ctr, buf, buflen); + } + #undef S_POLY_UNIFORM_NBLOCKS + + return CRYPT_OK; +} + +static unsigned int s_rej_eta(int *a, unsigned int len, + const unsigned char *buf, unsigned int buflen, + int eta) +{ + unsigned int ctr, pos; + ulong32 t0, t1; + + ctr = pos = 0; + while (ctr < len && pos < buflen) { + t0 = buf[pos] & 0x0F; + t1 = buf[pos++] >> 4; + + if (eta == 2) { + if (t0 < 15) { + t0 = t0 - (205 * t0 >> 10) * 5; + a[ctr++] = 2 - (int)t0; + } + if (t1 < 15 && ctr < len) { + t1 = t1 - (205 * t1 >> 10) * 5; + a[ctr++] = 2 - (int)t1; + } + } else { + /* eta == 4 */ + if (t0 < 9) + a[ctr++] = 4 - (int)t0; + if (t1 < 9 && ctr < len) + a[ctr++] = 4 - (int)t1; + } + } + + return ctr; +} + +static int s_poly_uniform_eta(mldsa_poly *a, const unsigned char seed[MLDSA_CRHBYTES], + unsigned int nonce, int eta) +{ + unsigned int ctr; + /* For eta==2: need 136 bytes. For eta==4: need 227 bytes. + ceil(227/136)=2 blocks of SHAKE256 (rate 136) = 272 bytes max */ + unsigned char buf[2 * MLDSA_SHAKE256_RATE]; + unsigned int buflen; + hash_state state; + int err; + + if (eta == 2) + buflen = 136; + else + buflen = 227; + + if ((err = s_shake256_stream_init(&state, seed, MLDSA_CRHBYTES, nonce)) != CRYPT_OK) return err; + if ((err = sha3_shake_done(&state, buf, buflen)) != CRYPT_OK) return err; + + ctr = s_rej_eta(a->coeffs, MLDSA_N, buf, buflen, eta); + + while (ctr < MLDSA_N) { + /* sha3_shake_done supports incremental squeezing */ + if ((err = sha3_shake_done(&state, buf, MLDSA_SHAKE256_RATE)) != CRYPT_OK) return err; + ctr += s_rej_eta(a->coeffs + ctr, MLDSA_N - ctr, buf, MLDSA_SHAKE256_RATE, eta); + } + + return CRYPT_OK; +} + +/* Polynomial packing */ + +static void s_polyeta_pack(unsigned char *r, const mldsa_poly *a, int eta) +{ + unsigned int i; + unsigned char t[8]; + + if (eta == 2) { + for (i = 0; i < MLDSA_N / 8; ++i) { + t[0] = (unsigned char)(eta - a->coeffs[8 * i + 0]); + t[1] = (unsigned char)(eta - a->coeffs[8 * i + 1]); + t[2] = (unsigned char)(eta - a->coeffs[8 * i + 2]); + t[3] = (unsigned char)(eta - a->coeffs[8 * i + 3]); + t[4] = (unsigned char)(eta - a->coeffs[8 * i + 4]); + t[5] = (unsigned char)(eta - a->coeffs[8 * i + 5]); + t[6] = (unsigned char)(eta - a->coeffs[8 * i + 6]); + t[7] = (unsigned char)(eta - a->coeffs[8 * i + 7]); + + r[3 * i + 0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); + r[3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); + r[3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); + } + } else { + /* eta == 4 */ + for (i = 0; i < MLDSA_N / 2; ++i) { + t[0] = (unsigned char)(eta - a->coeffs[2 * i + 0]); + t[1] = (unsigned char)(eta - a->coeffs[2 * i + 1]); + r[i] = t[0] | (t[1] << 4); + } + } +} + +static void s_polyeta_unpack(mldsa_poly *r, const unsigned char *a, int eta) +{ + unsigned int i; + + if (eta == 2) { + for (i = 0; i < MLDSA_N / 8; ++i) { + r->coeffs[8 * i + 0] = (a[3 * i + 0] >> 0) & 7; + r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 7; + r->coeffs[8 * i + 2] = ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 7; + r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 7; + r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 7; + r->coeffs[8 * i + 5] = ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 7; + r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 7; + r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 7; + + r->coeffs[8 * i + 0] = eta - r->coeffs[8 * i + 0]; + r->coeffs[8 * i + 1] = eta - r->coeffs[8 * i + 1]; + r->coeffs[8 * i + 2] = eta - r->coeffs[8 * i + 2]; + r->coeffs[8 * i + 3] = eta - r->coeffs[8 * i + 3]; + r->coeffs[8 * i + 4] = eta - r->coeffs[8 * i + 4]; + r->coeffs[8 * i + 5] = eta - r->coeffs[8 * i + 5]; + r->coeffs[8 * i + 6] = eta - r->coeffs[8 * i + 6]; + r->coeffs[8 * i + 7] = eta - r->coeffs[8 * i + 7]; + } + } else { + /* eta == 4 */ + for (i = 0; i < MLDSA_N / 2; ++i) { + r->coeffs[2 * i + 0] = a[i] & 0x0F; + r->coeffs[2 * i + 1] = a[i] >> 4; + r->coeffs[2 * i + 0] = eta - r->coeffs[2 * i + 0]; + r->coeffs[2 * i + 1] = eta - r->coeffs[2 * i + 1]; + } + } +} + +static void s_polyt1_pack(unsigned char *r, const mldsa_poly *a) +{ + unsigned int i; + + for (i = 0; i < MLDSA_N / 4; ++i) { + r[5 * i + 0] = (unsigned char)(a->coeffs[4 * i + 0] >> 0); + r[5 * i + 1] = (unsigned char)((a->coeffs[4 * i + 0] >> 8) | (a->coeffs[4 * i + 1] << 2)); + r[5 * i + 2] = (unsigned char)((a->coeffs[4 * i + 1] >> 6) | (a->coeffs[4 * i + 2] << 4)); + r[5 * i + 3] = (unsigned char)((a->coeffs[4 * i + 2] >> 4) | (a->coeffs[4 * i + 3] << 6)); + r[5 * i + 4] = (unsigned char)(a->coeffs[4 * i + 3] >> 2); + } +} + +static void s_polyt1_unpack(mldsa_poly *r, const unsigned char *a) +{ + unsigned int i; + + for (i = 0; i < MLDSA_N / 4; ++i) { + r->coeffs[4 * i + 0] = ((a[5 * i + 0] >> 0) | ((ulong32)a[5 * i + 1] << 8)) & 0x3FF; + r->coeffs[4 * i + 1] = ((a[5 * i + 1] >> 2) | ((ulong32)a[5 * i + 2] << 6)) & 0x3FF; + r->coeffs[4 * i + 2] = ((a[5 * i + 2] >> 4) | ((ulong32)a[5 * i + 3] << 4)) & 0x3FF; + r->coeffs[4 * i + 3] = ((a[5 * i + 3] >> 6) | ((ulong32)a[5 * i + 4] << 2)) & 0x3FF; + } +} + +static void s_polyt0_pack(unsigned char *r, const mldsa_poly *a) +{ + unsigned int i; + ulong32 t[8]; + + for (i = 0; i < MLDSA_N / 8; ++i) { + t[0] = (1 << (MLDSA_D - 1)) - a->coeffs[8 * i + 0]; + t[1] = (1 << (MLDSA_D - 1)) - a->coeffs[8 * i + 1]; + t[2] = (1 << (MLDSA_D - 1)) - a->coeffs[8 * i + 2]; + t[3] = (1 << (MLDSA_D - 1)) - a->coeffs[8 * i + 3]; + t[4] = (1 << (MLDSA_D - 1)) - a->coeffs[8 * i + 4]; + t[5] = (1 << (MLDSA_D - 1)) - a->coeffs[8 * i + 5]; + t[6] = (1 << (MLDSA_D - 1)) - a->coeffs[8 * i + 6]; + t[7] = (1 << (MLDSA_D - 1)) - a->coeffs[8 * i + 7]; + + r[13 * i + 0] = (unsigned char)(t[0]); + r[13 * i + 1] = (unsigned char)(t[0] >> 8); + r[13 * i + 1] |= (unsigned char)(t[1] << 5); + r[13 * i + 2] = (unsigned char)(t[1] >> 3); + r[13 * i + 3] = (unsigned char)(t[1] >> 11); + r[13 * i + 3] |= (unsigned char)(t[2] << 2); + r[13 * i + 4] = (unsigned char)(t[2] >> 6); + r[13 * i + 4] |= (unsigned char)(t[3] << 7); + r[13 * i + 5] = (unsigned char)(t[3] >> 1); + r[13 * i + 6] = (unsigned char)(t[3] >> 9); + r[13 * i + 6] |= (unsigned char)(t[4] << 4); + r[13 * i + 7] = (unsigned char)(t[4] >> 4); + r[13 * i + 8] = (unsigned char)(t[4] >> 12); + r[13 * i + 8] |= (unsigned char)(t[5] << 1); + r[13 * i + 9] = (unsigned char)(t[5] >> 7); + r[13 * i + 9] |= (unsigned char)(t[6] << 6); + r[13 * i + 10] = (unsigned char)(t[6] >> 2); + r[13 * i + 11] = (unsigned char)(t[6] >> 10); + r[13 * i + 11] |= (unsigned char)(t[7] << 3); + r[13 * i + 12] = (unsigned char)(t[7] >> 5); + } +} + +static void s_polyt0_unpack(mldsa_poly *r, const unsigned char *a) +{ + unsigned int i; + + for (i = 0; i < MLDSA_N / 8; ++i) { + r->coeffs[8 * i + 0] = a[13 * i + 0]; + r->coeffs[8 * i + 0] |= (ulong32)a[13 * i + 1] << 8; + r->coeffs[8 * i + 0] &= 0x1FFF; + + r->coeffs[8 * i + 1] = a[13 * i + 1] >> 5; + r->coeffs[8 * i + 1] |= (ulong32)a[13 * i + 2] << 3; + r->coeffs[8 * i + 1] |= (ulong32)a[13 * i + 3] << 11; + r->coeffs[8 * i + 1] &= 0x1FFF; + + r->coeffs[8 * i + 2] = a[13 * i + 3] >> 2; + r->coeffs[8 * i + 2] |= (ulong32)a[13 * i + 4] << 6; + r->coeffs[8 * i + 2] &= 0x1FFF; + + r->coeffs[8 * i + 3] = a[13 * i + 4] >> 7; + r->coeffs[8 * i + 3] |= (ulong32)a[13 * i + 5] << 1; + r->coeffs[8 * i + 3] |= (ulong32)a[13 * i + 6] << 9; + r->coeffs[8 * i + 3] &= 0x1FFF; + + r->coeffs[8 * i + 4] = a[13 * i + 6] >> 4; + r->coeffs[8 * i + 4] |= (ulong32)a[13 * i + 7] << 4; + r->coeffs[8 * i + 4] |= (ulong32)a[13 * i + 8] << 12; + r->coeffs[8 * i + 4] &= 0x1FFF; + + r->coeffs[8 * i + 5] = a[13 * i + 8] >> 1; + r->coeffs[8 * i + 5] |= (ulong32)a[13 * i + 9] << 7; + r->coeffs[8 * i + 5] &= 0x1FFF; + + r->coeffs[8 * i + 6] = a[13 * i + 9] >> 6; + r->coeffs[8 * i + 6] |= (ulong32)a[13 * i + 10] << 2; + r->coeffs[8 * i + 6] |= (ulong32)a[13 * i + 11] << 10; + r->coeffs[8 * i + 6] &= 0x1FFF; + + r->coeffs[8 * i + 7] = a[13 * i + 11] >> 3; + r->coeffs[8 * i + 7] |= (ulong32)a[13 * i + 12] << 5; + r->coeffs[8 * i + 7] &= 0x1FFF; + + r->coeffs[8 * i + 0] = (1 << (MLDSA_D - 1)) - r->coeffs[8 * i + 0]; + r->coeffs[8 * i + 1] = (1 << (MLDSA_D - 1)) - r->coeffs[8 * i + 1]; + r->coeffs[8 * i + 2] = (1 << (MLDSA_D - 1)) - r->coeffs[8 * i + 2]; + r->coeffs[8 * i + 3] = (1 << (MLDSA_D - 1)) - r->coeffs[8 * i + 3]; + r->coeffs[8 * i + 4] = (1 << (MLDSA_D - 1)) - r->coeffs[8 * i + 4]; + r->coeffs[8 * i + 5] = (1 << (MLDSA_D - 1)) - r->coeffs[8 * i + 5]; + r->coeffs[8 * i + 6] = (1 << (MLDSA_D - 1)) - r->coeffs[8 * i + 6]; + r->coeffs[8 * i + 7] = (1 << (MLDSA_D - 1)) - r->coeffs[8 * i + 7]; + } +} + +static void s_polyz_pack(unsigned char *r, const mldsa_poly *a, int gamma1) +{ + unsigned int i; + ulong32 t[4]; + + if (gamma1 == (1 << 17)) { + for (i = 0; i < MLDSA_N / 4; ++i) { + t[0] = gamma1 - a->coeffs[4 * i + 0]; + t[1] = gamma1 - a->coeffs[4 * i + 1]; + t[2] = gamma1 - a->coeffs[4 * i + 2]; + t[3] = gamma1 - a->coeffs[4 * i + 3]; + + r[9 * i + 0] = (unsigned char)(t[0]); + r[9 * i + 1] = (unsigned char)(t[0] >> 8); + r[9 * i + 2] = (unsigned char)(t[0] >> 16); + r[9 * i + 2] |= (unsigned char)(t[1] << 2); + r[9 * i + 3] = (unsigned char)(t[1] >> 6); + r[9 * i + 4] = (unsigned char)(t[1] >> 14); + r[9 * i + 4] |= (unsigned char)(t[2] << 4); + r[9 * i + 5] = (unsigned char)(t[2] >> 4); + r[9 * i + 6] = (unsigned char)(t[2] >> 12); + r[9 * i + 6] |= (unsigned char)(t[3] << 6); + r[9 * i + 7] = (unsigned char)(t[3] >> 2); + r[9 * i + 8] = (unsigned char)(t[3] >> 10); + } + } else { + /* gamma1 == (1 << 19) */ + for (i = 0; i < MLDSA_N / 2; ++i) { + t[0] = gamma1 - a->coeffs[2 * i + 0]; + t[1] = gamma1 - a->coeffs[2 * i + 1]; + + r[5 * i + 0] = (unsigned char)(t[0]); + r[5 * i + 1] = (unsigned char)(t[0] >> 8); + r[5 * i + 2] = (unsigned char)(t[0] >> 16); + r[5 * i + 2] |= (unsigned char)(t[1] << 4); + r[5 * i + 3] = (unsigned char)(t[1] >> 4); + r[5 * i + 4] = (unsigned char)(t[1] >> 12); + } + } +} + +static void s_polyz_unpack(mldsa_poly *r, const unsigned char *a, int gamma1) +{ + unsigned int i; + + if (gamma1 == (1 << 17)) { + for (i = 0; i < MLDSA_N / 4; ++i) { + r->coeffs[4 * i + 0] = a[9 * i + 0]; + r->coeffs[4 * i + 0] |= (ulong32)a[9 * i + 1] << 8; + r->coeffs[4 * i + 0] |= (ulong32)a[9 * i + 2] << 16; + r->coeffs[4 * i + 0] &= 0x3FFFF; + + r->coeffs[4 * i + 1] = a[9 * i + 2] >> 2; + r->coeffs[4 * i + 1] |= (ulong32)a[9 * i + 3] << 6; + r->coeffs[4 * i + 1] |= (ulong32)a[9 * i + 4] << 14; + r->coeffs[4 * i + 1] &= 0x3FFFF; + + r->coeffs[4 * i + 2] = a[9 * i + 4] >> 4; + r->coeffs[4 * i + 2] |= (ulong32)a[9 * i + 5] << 4; + r->coeffs[4 * i + 2] |= (ulong32)a[9 * i + 6] << 12; + r->coeffs[4 * i + 2] &= 0x3FFFF; + + r->coeffs[4 * i + 3] = a[9 * i + 6] >> 6; + r->coeffs[4 * i + 3] |= (ulong32)a[9 * i + 7] << 2; + r->coeffs[4 * i + 3] |= (ulong32)a[9 * i + 8] << 10; + r->coeffs[4 * i + 3] &= 0x3FFFF; + + r->coeffs[4 * i + 0] = gamma1 - r->coeffs[4 * i + 0]; + r->coeffs[4 * i + 1] = gamma1 - r->coeffs[4 * i + 1]; + r->coeffs[4 * i + 2] = gamma1 - r->coeffs[4 * i + 2]; + r->coeffs[4 * i + 3] = gamma1 - r->coeffs[4 * i + 3]; + } + } else { + /* gamma1 == (1 << 19) */ + for (i = 0; i < MLDSA_N / 2; ++i) { + r->coeffs[2 * i + 0] = a[5 * i + 0]; + r->coeffs[2 * i + 0] |= (ulong32)a[5 * i + 1] << 8; + r->coeffs[2 * i + 0] |= (ulong32)a[5 * i + 2] << 16; + r->coeffs[2 * i + 0] &= 0xFFFFF; + + r->coeffs[2 * i + 1] = a[5 * i + 2] >> 4; + r->coeffs[2 * i + 1] |= (ulong32)a[5 * i + 3] << 4; + r->coeffs[2 * i + 1] |= (ulong32)a[5 * i + 4] << 12; + r->coeffs[2 * i + 1] &= 0xFFFFF; + + r->coeffs[2 * i + 0] = gamma1 - r->coeffs[2 * i + 0]; + r->coeffs[2 * i + 1] = gamma1 - r->coeffs[2 * i + 1]; + } + } +} + +static void s_polyw1_pack(unsigned char *r, const mldsa_poly *a, int gamma2) +{ + unsigned int i; + + if (gamma2 == (MLDSA_Q - 1) / 88) { + for (i = 0; i < MLDSA_N / 4; ++i) { + r[3 * i + 0] = (unsigned char)(a->coeffs[4 * i + 0]); + r[3 * i + 0] |= (unsigned char)(a->coeffs[4 * i + 1] << 6); + r[3 * i + 1] = (unsigned char)(a->coeffs[4 * i + 1] >> 2); + r[3 * i + 1] |= (unsigned char)(a->coeffs[4 * i + 2] << 4); + r[3 * i + 2] = (unsigned char)(a->coeffs[4 * i + 2] >> 4); + r[3 * i + 2] |= (unsigned char)(a->coeffs[4 * i + 3] << 2); + } + } else { + /* gamma2 == (MLDSA_Q - 1) / 32 */ + for (i = 0; i < MLDSA_N / 2; ++i) + r[i] = (unsigned char)(a->coeffs[2 * i + 0] | (a->coeffs[2 * i + 1] << 4)); + } +} + +/* Now implement s_poly_uniform_gamma1 */ +static int s_poly_uniform_gamma1(mldsa_poly *a, const unsigned char seed[MLDSA_CRHBYTES], + unsigned int nonce, const mldsa_params *p) +{ + /* polyz_packed bytes: 576 or 640. SHAKE256 rate=136. + ceil(640/136) = 5 blocks = 680 bytes max */ + unsigned char buf[5 * MLDSA_SHAKE256_RATE]; + unsigned int buflen; + hash_state state; + int err; + + buflen = (unsigned int)p->polyz_packed; + if (buflen > sizeof(buf)) + buflen = sizeof(buf); + + if ((err = s_shake256_stream_init(&state, seed, MLDSA_CRHBYTES, nonce)) != CRYPT_OK) return err; + if ((err = sha3_shake_done(&state, buf, buflen)) != CRYPT_OK) return err; + + s_polyz_unpack(a, buf, p->gamma1); + return CRYPT_OK; +} + +static int s_poly_challenge(mldsa_poly *c, const unsigned char *seed, + int ctilde_bytes, int tau) +{ + unsigned int i, b, pos; + ulong64 signs; + unsigned char buf[MLDSA_SHAKE256_RATE]; + hash_state state; + int err; + + if ((err = sha3_shake_init(&state, 256)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&state, seed, ctilde_bytes)) != CRYPT_OK) return err; + if ((err = sha3_shake_done(&state, buf, MLDSA_SHAKE256_RATE)) != CRYPT_OK) return err; + + signs = 0; + for (i = 0; i < 8; ++i) + signs |= (ulong64)buf[i] << (8 * i); + pos = 8; + + for (i = 0; i < MLDSA_N; ++i) + c->coeffs[i] = 0; + + for (i = MLDSA_N - (unsigned int)tau; i < MLDSA_N; ++i) { + do { + if (pos >= MLDSA_SHAKE256_RATE) { + /* sha3_shake_done supports incremental squeezing */ + if ((err = sha3_shake_done(&state, buf, MLDSA_SHAKE256_RATE)) != CRYPT_OK) return err; + pos = 0; + } + + b = buf[pos++]; + } while (b > i); + + c->coeffs[i] = c->coeffs[b]; + c->coeffs[b] = 1 - 2 * (int)(signs & 1); + signs >>= 1; + } + + return CRYPT_OK; +} + +/* Polyvec operations (runtime k/l) */ + +static int s_polyvec_matrix_expand(mldsa_polyvecl *mat, int k, int l, + const unsigned char rho[MLDSA_SEEDBYTES]) +{ + int i, j, err; + + for (i = 0; i < k; ++i) + for (j = 0; j < l; ++j) { + if ((err = s_poly_uniform(&mat[i].vec[j], rho, (unsigned int)((i << 8) + j))) != CRYPT_OK) + return err; + } + + return CRYPT_OK; +} + +static void s_polyvec_matrix_pointwise_montgomery(mldsa_polyveck *t, + const mldsa_polyvecl *mat, + const mldsa_polyvecl *v, + int k, int l) +{ + int i, j; + mldsa_poly tmp; + + for (i = 0; i < k; ++i) { + s_poly_pointwise_montgomery(&t->vec[i], &mat[i].vec[0], &v->vec[0]); + for (j = 1; j < l; ++j) { + s_poly_pointwise_montgomery(&tmp, &mat[i].vec[j], &v->vec[j]); + s_mldsa_poly_add(&t->vec[i], &t->vec[i], &tmp); + } + } +} + +/* ---- polyvecl operations ---- */ + +static int s_polyvecl_uniform_eta(mldsa_polyvecl *v, + const unsigned char seed[MLDSA_CRHBYTES], + unsigned int nonce, int l, int eta) +{ + int i, err; + for (i = 0; i < l; ++i) { + if ((err = s_poly_uniform_eta(&v->vec[i], seed, nonce++, eta)) != CRYPT_OK) + return err; + } + return CRYPT_OK; +} + +static int s_polyvecl_uniform_gamma1(mldsa_polyvecl *v, + const unsigned char seed[MLDSA_CRHBYTES], + unsigned int nonce, int l, + const mldsa_params *p) +{ + int i, err; + for (i = 0; i < l; ++i) { + if ((err = s_poly_uniform_gamma1(&v->vec[i], seed, (unsigned int)(l * nonce + i), p)) != CRYPT_OK) + return err; + } + return CRYPT_OK; +} + +static void s_polyvecl_reduce(mldsa_polyvecl *v, int l) +{ + int i; + for (i = 0; i < l; ++i) + s_mldsa_poly_reduce(&v->vec[i]); +} + +static void s_polyvecl_add(mldsa_polyvecl *w, const mldsa_polyvecl *u, + const mldsa_polyvecl *v, int l) +{ + int i; + for (i = 0; i < l; ++i) + s_mldsa_poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +static void s_polyvecl_ntt(mldsa_polyvecl *v, int l) +{ + int i; + for (i = 0; i < l; ++i) + s_mldsa_poly_ntt(&v->vec[i]); +} + +static void s_polyvecl_invntt_tomont(mldsa_polyvecl *v, int l) +{ + int i; + for (i = 0; i < l; ++i) + s_mldsa_poly_invntt_tomont(&v->vec[i]); +} + +static void s_polyvecl_pointwise_poly_montgomery(mldsa_polyvecl *r, + const mldsa_poly *a, + const mldsa_polyvecl *v, int l) +{ + int i; + for (i = 0; i < l; ++i) + s_poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]); +} + +static int s_polyvecl_chknorm(const mldsa_polyvecl *v, int bound, int l) +{ + int i; + for (i = 0; i < l; ++i) + if (s_poly_chknorm(&v->vec[i], bound)) + return 1; + return 0; +} + +/* ---- polyveck operations ---- */ + +static int s_polyveck_uniform_eta(mldsa_polyveck *v, + const unsigned char seed[MLDSA_CRHBYTES], + unsigned int nonce, int k, int eta) +{ + int i, err; + for (i = 0; i < k; ++i) { + if ((err = s_poly_uniform_eta(&v->vec[i], seed, nonce++, eta)) != CRYPT_OK) + return err; + } + return CRYPT_OK; +} + +static void s_polyveck_reduce(mldsa_polyveck *v, int k) +{ + int i; + for (i = 0; i < k; ++i) + s_mldsa_poly_reduce(&v->vec[i]); +} + +static void s_polyveck_caddq(mldsa_polyveck *v, int k) +{ + int i; + for (i = 0; i < k; ++i) + s_poly_caddq(&v->vec[i]); +} + +static void s_polyveck_add(mldsa_polyveck *w, const mldsa_polyveck *u, + const mldsa_polyveck *v, int k) +{ + int i; + for (i = 0; i < k; ++i) + s_mldsa_poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +static void s_polyveck_sub(mldsa_polyveck *w, const mldsa_polyveck *u, + const mldsa_polyveck *v, int k) +{ + int i; + for (i = 0; i < k; ++i) + s_mldsa_poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +static void s_polyveck_shiftl(mldsa_polyveck *v, int k) +{ + int i; + for (i = 0; i < k; ++i) + s_poly_shiftl(&v->vec[i]); +} + +static void s_polyveck_ntt(mldsa_polyveck *v, int k) +{ + int i; + for (i = 0; i < k; ++i) + s_mldsa_poly_ntt(&v->vec[i]); +} + +static void s_polyveck_invntt_tomont(mldsa_polyveck *v, int k) +{ + int i; + for (i = 0; i < k; ++i) + s_mldsa_poly_invntt_tomont(&v->vec[i]); +} + +static void s_polyveck_pointwise_poly_montgomery(mldsa_polyveck *r, + const mldsa_poly *a, + const mldsa_polyveck *v, int k) +{ + int i; + for (i = 0; i < k; ++i) + s_poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]); +} + +static int s_polyveck_chknorm(const mldsa_polyveck *v, int bound, int k) +{ + int i; + for (i = 0; i < k; ++i) + if (s_poly_chknorm(&v->vec[i], bound)) + return 1; + return 0; +} + +static void s_polyveck_power2round(mldsa_polyveck *v1, mldsa_polyveck *v0, + const mldsa_polyveck *v, int k) +{ + int i; + for (i = 0; i < k; ++i) + s_poly_power2round(&v1->vec[i], &v0->vec[i], &v->vec[i]); +} + +static void s_polyveck_decompose(mldsa_polyveck *v1, mldsa_polyveck *v0, + const mldsa_polyveck *v, int k, int gamma2) +{ + int i; + for (i = 0; i < k; ++i) + s_poly_decompose(&v1->vec[i], &v0->vec[i], &v->vec[i], gamma2); +} + +static unsigned int s_polyveck_make_hint(mldsa_polyveck *h, + const mldsa_polyveck *v0, + const mldsa_polyveck *v1, + int k, int gamma2) +{ + unsigned int i, s = 0; + for (i = 0; i < (unsigned)k; ++i) + s += s_poly_make_hint(&h->vec[i], &v0->vec[i], &v1->vec[i], gamma2); + return s; +} + +static void s_polyveck_use_hint(mldsa_polyveck *w, const mldsa_polyveck *u, + const mldsa_polyveck *h, int k, int gamma2) +{ + int i; + for (i = 0; i < k; ++i) + s_poly_use_hint(&w->vec[i], &u->vec[i], &h->vec[i], gamma2); +} + +static void s_polyveck_pack_w1(unsigned char *r, const mldsa_polyveck *w1, + int k, unsigned long polyw1_packed, int gamma2) +{ + int i; + for (i = 0; i < k; ++i) + s_polyw1_pack(r + (unsigned long)i * polyw1_packed, &w1->vec[i], gamma2); +} + +/* Packing (key and signature) */ + +static void s_pack_pk(unsigned char *pk, const unsigned char rho[MLDSA_SEEDBYTES], + const mldsa_polyveck *t1, int k) +{ + unsigned int i; + + XMEMCPY(pk, rho, MLDSA_SEEDBYTES); + pk += MLDSA_SEEDBYTES; + + for (i = 0; i < (unsigned)k; ++i) + s_polyt1_pack(pk + i * MLDSA_POLYT1_PACKEDBYTES, &t1->vec[i]); +} + +static void s_unpack_pk(unsigned char rho[MLDSA_SEEDBYTES], mldsa_polyveck *t1, + const unsigned char *pk, int k) +{ + unsigned int i; + + XMEMCPY(rho, pk, MLDSA_SEEDBYTES); + pk += MLDSA_SEEDBYTES; + + for (i = 0; i < (unsigned)k; ++i) + s_polyt1_unpack(&t1->vec[i], pk + i * MLDSA_POLYT1_PACKEDBYTES); +} + +static void s_pack_sk(unsigned char *sk, + const unsigned char rho[MLDSA_SEEDBYTES], + const unsigned char tr[MLDSA_TRBYTES], + const unsigned char key[MLDSA_SEEDBYTES], + const mldsa_polyveck *t0, + const mldsa_polyvecl *s1, + const mldsa_polyveck *s2, + const mldsa_params *p) +{ + unsigned int i; + + XMEMCPY(sk, rho, MLDSA_SEEDBYTES); + sk += MLDSA_SEEDBYTES; + + XMEMCPY(sk, key, MLDSA_SEEDBYTES); + sk += MLDSA_SEEDBYTES; + + XMEMCPY(sk, tr, MLDSA_TRBYTES); + sk += MLDSA_TRBYTES; + + for (i = 0; i < (unsigned)p->l; ++i) + s_polyeta_pack(sk + i * p->polyeta_packed, &s1->vec[i], p->eta); + sk += (unsigned long)p->l * p->polyeta_packed; + + for (i = 0; i < (unsigned)p->k; ++i) + s_polyeta_pack(sk + i * p->polyeta_packed, &s2->vec[i], p->eta); + sk += (unsigned long)p->k * p->polyeta_packed; + + for (i = 0; i < (unsigned)p->k; ++i) + s_polyt0_pack(sk + i * MLDSA_POLYT0_PACKEDBYTES, &t0->vec[i]); +} + +static void s_unpack_sk(unsigned char rho[MLDSA_SEEDBYTES], + unsigned char tr[MLDSA_TRBYTES], + unsigned char key[MLDSA_SEEDBYTES], + mldsa_polyveck *t0, + mldsa_polyvecl *s1, + mldsa_polyveck *s2, + const unsigned char *sk, + const mldsa_params *p) +{ + unsigned int i; + + XMEMCPY(rho, sk, MLDSA_SEEDBYTES); + sk += MLDSA_SEEDBYTES; + + XMEMCPY(key, sk, MLDSA_SEEDBYTES); + sk += MLDSA_SEEDBYTES; + + XMEMCPY(tr, sk, MLDSA_TRBYTES); + sk += MLDSA_TRBYTES; + + for (i = 0; i < (unsigned)p->l; ++i) + s_polyeta_unpack(&s1->vec[i], sk + i * p->polyeta_packed, p->eta); + sk += (unsigned long)p->l * p->polyeta_packed; + + for (i = 0; i < (unsigned)p->k; ++i) + s_polyeta_unpack(&s2->vec[i], sk + i * p->polyeta_packed, p->eta); + sk += (unsigned long)p->k * p->polyeta_packed; + + for (i = 0; i < (unsigned)p->k; ++i) + s_polyt0_unpack(&t0->vec[i], sk + i * MLDSA_POLYT0_PACKEDBYTES); +} + +static void s_pack_sig(unsigned char *sig, + const unsigned char *c, int ctilde_bytes, + const mldsa_polyvecl *z, + const mldsa_polyveck *h, + const mldsa_params *p) +{ + unsigned int i, j, k; + + XMEMCPY(sig, c, ctilde_bytes); + sig += ctilde_bytes; + + for (i = 0; i < (unsigned)p->l; ++i) + s_polyz_pack(sig + i * p->polyz_packed, &z->vec[i], p->gamma1); + sig += (unsigned long)p->l * p->polyz_packed; + + /* Encode h */ + for (i = 0; i < (unsigned long)p->omega + (unsigned long)p->k; ++i) + sig[i] = 0; + + k = 0; + for (i = 0; i < (unsigned)p->k; ++i) { + for (j = 0; j < MLDSA_N; ++j) + if (h->vec[i].coeffs[j] != 0) + sig[k++] = (unsigned char)j; + sig[p->omega + i] = (unsigned char)k; + } +} + +static int s_unpack_sig(unsigned char *c, int ctilde_bytes, + mldsa_polyvecl *z, + mldsa_polyveck *h, + const unsigned char *sig, + const mldsa_params *p) +{ + unsigned int i, j, k; + + XMEMCPY(c, sig, ctilde_bytes); + sig += ctilde_bytes; + + for (i = 0; i < (unsigned)p->l; ++i) + s_polyz_unpack(&z->vec[i], sig + i * p->polyz_packed, p->gamma1); + sig += (unsigned long)p->l * p->polyz_packed; + + /* Decode h */ + k = 0; + for (i = 0; i < (unsigned)p->k; ++i) { + for (j = 0; j < MLDSA_N; ++j) + h->vec[i].coeffs[j] = 0; + + if (sig[p->omega + i] < k || sig[p->omega + i] > (unsigned)p->omega) + return 1; + + for (j = k; j < sig[p->omega + i]; ++j) { + /* Coefficients are ordered for strong unforgeability */ + if (j > k && sig[j] <= sig[j - 1]) return 1; + h->vec[i].coeffs[sig[j]] = 1; + } + + k = sig[p->omega + i]; + } + + /* Extra indices are zero for strong unforgeability */ + for (j = k; j < (unsigned)p->omega; ++j) + if (sig[j]) + return 1; + + return 0; +} + +/* Sign / verify core */ + +static int s_sign_internal(unsigned char *sig, unsigned long *siglen, + const unsigned char *msg, unsigned long msglen, + const unsigned char *pre, unsigned long prelen, + const unsigned char rnd[MLDSA_RNDBYTES], + const unsigned char *sk, + const mldsa_params *p) +{ + unsigned int n; + unsigned char seedbuf[2 * MLDSA_SEEDBYTES + MLDSA_TRBYTES + 2 * MLDSA_CRHBYTES]; + unsigned char *rho, *tr, *key, *mu, *rhoprime; + unsigned int nonce = 0; + mldsa_polyvecl mat[MLDSA_K_MAX], s1, y, z; + mldsa_polyveck t0, s2, w1, w0, h; + mldsa_poly cp; + hash_state state; + int err; + + XMEMSET(mat, 0, sizeof(mat)); + XMEMSET(&s1, 0, sizeof(s1)); + XMEMSET(&s2, 0, sizeof(s2)); + XMEMSET(&t0, 0, sizeof(t0)); + + rho = seedbuf; + tr = rho + MLDSA_SEEDBYTES; + key = tr + MLDSA_TRBYTES; + mu = key + MLDSA_SEEDBYTES; + rhoprime = mu + MLDSA_CRHBYTES; + s_unpack_sk(rho, tr, key, &t0, &s1, &s2, sk, p); + + /* Compute mu = CRH(tr, pre, msg) */ + if ((err = sha3_shake_init(&state, 256)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&state, tr, MLDSA_TRBYTES)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&state, pre, prelen)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&state, msg, msglen)) != CRYPT_OK) return err; + if ((err = sha3_shake_done(&state, mu, MLDSA_CRHBYTES)) != CRYPT_OK) return err; + + /* Compute rhoprime = CRH(key, rnd, mu) */ + if ((err = sha3_shake_init(&state, 256)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&state, key, MLDSA_SEEDBYTES)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&state, rnd, MLDSA_RNDBYTES)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&state, mu, MLDSA_CRHBYTES)) != CRYPT_OK) return err; + if ((err = sha3_shake_done(&state, rhoprime, MLDSA_CRHBYTES)) != CRYPT_OK) return err; + + /* Expand matrix and transform vectors */ + if ((err = s_polyvec_matrix_expand(mat, p->k, p->l, rho)) != CRYPT_OK) return err; + s_polyvecl_ntt(&s1, p->l); + s_polyveck_ntt(&s2, p->k); + s_polyveck_ntt(&t0, p->k); + +rej: + /* Sample intermediate vector y */ + if ((err = s_polyvecl_uniform_gamma1(&y, rhoprime, nonce++, p->l, p)) != CRYPT_OK) return err; + + /* Matrix-vector multiplication */ + z = y; + s_polyvecl_ntt(&z, p->l); + s_polyvec_matrix_pointwise_montgomery(&w1, mat, &z, p->k, p->l); + s_polyveck_reduce(&w1, p->k); + s_polyveck_invntt_tomont(&w1, p->k); + + /* Decompose w and call the random oracle */ + s_polyveck_caddq(&w1, p->k); + s_polyveck_decompose(&w1, &w0, &w1, p->k, p->gamma2); + s_polyveck_pack_w1(sig, &w1, p->k, p->polyw1_packed, p->gamma2); + + if ((err = sha3_shake_init(&state, 256)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&state, mu, MLDSA_CRHBYTES)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&state, sig, (unsigned long)p->k * p->polyw1_packed)) != CRYPT_OK) return err; + if ((err = sha3_shake_done(&state, sig, p->ctilde_bytes)) != CRYPT_OK) return err; + if ((err = s_poly_challenge(&cp, sig, p->ctilde_bytes, p->tau)) != CRYPT_OK) return err; + s_mldsa_poly_ntt(&cp); + + /* Compute z, reject if it reveals secret */ + s_polyvecl_pointwise_poly_montgomery(&z, &cp, &s1, p->l); + s_polyvecl_invntt_tomont(&z, p->l); + s_polyvecl_add(&z, &z, &y, p->l); + s_polyvecl_reduce(&z, p->l); + if (s_polyvecl_chknorm(&z, p->gamma1 - p->beta, p->l)) + goto rej; + + /* Check that subtracting cs2 does not change high bits of w and low bits + * do not reveal secret information */ + s_polyveck_pointwise_poly_montgomery(&h, &cp, &s2, p->k); + s_polyveck_invntt_tomont(&h, p->k); + s_polyveck_sub(&w0, &w0, &h, p->k); + s_polyveck_reduce(&w0, p->k); + if (s_polyveck_chknorm(&w0, p->gamma2 - p->beta, p->k)) + goto rej; + + /* Compute hints for w1 */ + s_polyveck_pointwise_poly_montgomery(&h, &cp, &t0, p->k); + s_polyveck_invntt_tomont(&h, p->k); + s_polyveck_reduce(&h, p->k); + if (s_polyveck_chknorm(&h, p->gamma2, p->k)) + goto rej; + + s_polyveck_add(&w0, &w0, &h, p->k); + n = s_polyveck_make_hint(&h, &w0, &w1, p->k, p->gamma2); + if (n > (unsigned)p->omega) + goto rej; + + /* Write signature */ + s_pack_sig(sig, sig, p->ctilde_bytes, &z, &h, p); + *siglen = p->sig_bytes; + return CRYPT_OK; +} + +static int s_verify_internal(const unsigned char *sig, unsigned long siglen, + const unsigned char *msg, unsigned long msglen, + const unsigned char *pre, unsigned long prelen, + const unsigned char *pk, + const mldsa_params *p) +{ + unsigned int i; + unsigned char *buf = NULL; + unsigned char rho[MLDSA_SEEDBYTES]; + unsigned char mu[MLDSA_CRHBYTES]; + unsigned char c[64]; /* max ctilde_bytes = 64 */ + unsigned char c2[64]; + mldsa_poly cp; + mldsa_polyvecl mat[MLDSA_K_MAX], z; + mldsa_polyveck t1, w1, h; + hash_state state; + int err; + + XMEMSET(mat, 0, sizeof(mat)); + XMEMSET(&z, 0, sizeof(z)); + XMEMSET(&t1, 0, sizeof(t1)); + + if (siglen != p->sig_bytes) + return CRYPT_INVALID_PACKET; + + buf = XMALLOC((unsigned long)p->k * p->polyw1_packed); + if (buf == NULL) + return CRYPT_MEM; + + s_unpack_pk(rho, &t1, pk, p->k); + if (s_unpack_sig(c, p->ctilde_bytes, &z, &h, sig, p)) { + XFREE(buf); + return CRYPT_INVALID_PACKET; + } + if (s_polyvecl_chknorm(&z, p->gamma1 - p->beta, p->l)) { + XFREE(buf); + return CRYPT_INVALID_PACKET; + } + + /* Compute CRH(H(rho, t1), pre, msg) */ + if ((err = s_shake256(mu, MLDSA_TRBYTES, pk, p->pk_bytes)) != CRYPT_OK) { + XFREE(buf); + return err; + } + if ((err = sha3_shake_init(&state, 256)) != CRYPT_OK) { XFREE(buf); return err; } + if ((err = sha3_shake_process(&state, mu, MLDSA_TRBYTES)) != CRYPT_OK) { XFREE(buf); return err; } + if ((err = sha3_shake_process(&state, pre, prelen)) != CRYPT_OK) { XFREE(buf); return err; } + if ((err = sha3_shake_process(&state, msg, msglen)) != CRYPT_OK) { XFREE(buf); return err; } + if ((err = sha3_shake_done(&state, mu, MLDSA_CRHBYTES)) != CRYPT_OK) { XFREE(buf); return err; } + + /* Matrix-vector multiplication; compute Az - c2^dt1 */ + if ((err = s_poly_challenge(&cp, c, p->ctilde_bytes, p->tau)) != CRYPT_OK) { XFREE(buf); return err; } + if ((err = s_polyvec_matrix_expand(mat, p->k, p->l, rho)) != CRYPT_OK) { XFREE(buf); return err; } + + s_polyvecl_ntt(&z, p->l); + s_polyvec_matrix_pointwise_montgomery(&w1, mat, &z, p->k, p->l); + + s_mldsa_poly_ntt(&cp); + s_polyveck_shiftl(&t1, p->k); + s_polyveck_ntt(&t1, p->k); + s_polyveck_pointwise_poly_montgomery(&t1, &cp, &t1, p->k); + + s_polyveck_sub(&w1, &w1, &t1, p->k); + s_polyveck_reduce(&w1, p->k); + s_polyveck_invntt_tomont(&w1, p->k); + + /* Reconstruct w1 */ + s_polyveck_caddq(&w1, p->k); + s_polyveck_use_hint(&w1, &w1, &h, p->k, p->gamma2); + s_polyveck_pack_w1(buf, &w1, p->k, p->polyw1_packed, p->gamma2); + + /* Call random oracle and verify challenge */ + if ((err = sha3_shake_init(&state, 256)) != CRYPT_OK) { XFREE(buf); return err; } + if ((err = sha3_shake_process(&state, mu, MLDSA_CRHBYTES)) != CRYPT_OK) { XFREE(buf); return err; } + if ((err = sha3_shake_process(&state, buf, (unsigned long)p->k * p->polyw1_packed)) != CRYPT_OK) { XFREE(buf); return err; } + if ((err = sha3_shake_done(&state, c2, p->ctilde_bytes)) != CRYPT_OK) { XFREE(buf); return err; } + + XFREE(buf); + + for (i = 0; i < (unsigned)p->ctilde_bytes; ++i) + if (c[i] != c2[i]) + return CRYPT_INVALID_PACKET; + + return CRYPT_OK; +} + +/* Public API */ + +static int s_mldsa_make_key_seed(int alg, + const unsigned char seedbuf[MLDSA_SEEDBYTES], + mldsa_key *key) +{ + mldsa_params p; + unsigned char expanded[2 * MLDSA_SEEDBYTES + MLDSA_CRHBYTES]; + unsigned char hashbuf[MLDSA_SEEDBYTES + 2]; + unsigned char tr[MLDSA_TRBYTES]; + const unsigned char *rho, *rhoprime, *kk; + mldsa_polyvecl mat[MLDSA_K_MAX], s1, s1hat; + mldsa_polyveck s2, t1, t0; + int err = CRYPT_OK; + + LTC_ARGCHK(key != NULL); + + XMEMSET(mat, 0, sizeof(mat)); + XMEMSET(&s1, 0, sizeof(s1)); + XMEMSET(&s2, 0, sizeof(s2)); + XMEMSET(key, 0, sizeof(*key)); + + if ((err = s_mldsa_get_params(alg, &p)) != CRYPT_OK) goto cleanup; + + /* Expand seed: SHAKE256(xi || k || l) -> rho || rhoprime || key */ + XMEMCPY(hashbuf, seedbuf, MLDSA_SEEDBYTES); + hashbuf[MLDSA_SEEDBYTES] = (unsigned char)p.k; + hashbuf[MLDSA_SEEDBYTES + 1] = (unsigned char)p.l; + if ((err = s_shake256(expanded, 2 * MLDSA_SEEDBYTES + MLDSA_CRHBYTES, + hashbuf, MLDSA_SEEDBYTES + 2)) != CRYPT_OK) { + goto cleanup; + } + + rho = expanded; + rhoprime = rho + MLDSA_SEEDBYTES; + kk = rhoprime + MLDSA_CRHBYTES; + + /* Expand matrix */ + if ((err = s_polyvec_matrix_expand(mat, p.k, p.l, rho)) != CRYPT_OK) goto cleanup; + + /* Sample short vectors s1 and s2 */ + if ((err = s_polyvecl_uniform_eta(&s1, rhoprime, 0, p.l, p.eta)) != CRYPT_OK) goto cleanup; + if ((err = s_polyveck_uniform_eta(&s2, rhoprime, (unsigned)p.l, p.k, p.eta)) != CRYPT_OK) goto cleanup; + + /* Matrix-vector multiplication */ + s1hat = s1; + s_polyvecl_ntt(&s1hat, p.l); + s_polyvec_matrix_pointwise_montgomery(&t1, mat, &s1hat, p.k, p.l); + s_polyveck_reduce(&t1, p.k); + s_polyveck_invntt_tomont(&t1, p.k); + + /* Add error vector s2 */ + s_polyveck_add(&t1, &t1, &s2, p.k); + + /* Extract t1 and write public key */ + s_polyveck_caddq(&t1, p.k); + s_polyveck_power2round(&t1, &t0, &t1, p.k); + + /* Allocate key storage */ + key->pk = XMALLOC(p.pk_bytes); + key->sk = XMALLOC(p.sk_bytes); + if (key->pk == NULL || key->sk == NULL) { + err = CRYPT_MEM; + goto cleanup; + } + + s_pack_pk(key->pk, rho, &t1, p.k); + + /* Compute H(rho, t1) = tr */ + if ((err = s_shake256(tr, MLDSA_TRBYTES, key->pk, p.pk_bytes)) != CRYPT_OK) { + goto cleanup; + } + + s_pack_sk(key->sk, rho, tr, kk, &t0, &s1, &s2, &p); + + key->alg = alg; + key->type = PK_PRIVATE; + key->pklen = p.pk_bytes; + key->sklen = p.sk_bytes; + +cleanup: + if (err != CRYPT_OK) { + mldsa_free(key); + } + zeromem(hashbuf, sizeof(hashbuf)); + zeromem(expanded, sizeof(expanded)); + zeromem(tr, sizeof(tr)); + return err; +} + +/** + Generate an ML-DSA key pair deterministically from a seed. + @param alg The parameter set (LTC_MLDSA_44, LTC_MLDSA_65, or LTC_MLDSA_87) + @param seed The input seed (exactly 32 bytes) + @param seedlen Length of the seed in bytes + @param key [out] Destination for the newly created key pair + @return CRYPT_OK if successful +*/ +int mldsa_make_key_from_seed(int alg, const unsigned char *seed, unsigned long seedlen, + mldsa_key *key) +{ + LTC_ARGCHK(seed != NULL); + LTC_ARGCHK(key != NULL); + + if (seedlen != MLDSA_SEEDBYTES) { + return CRYPT_INVALID_ARG; + } + + return s_mldsa_make_key_seed(alg, seed, key); +} + +/** + Generate an ML-DSA key pair. + @param prng An active PRNG state + @param wprng The index of the desired PRNG + @param alg The parameter set (LTC_MLDSA_44, LTC_MLDSA_65, or LTC_MLDSA_87) + @param key [out] Destination for the newly created key pair + @return CRYPT_OK if successful +*/ +int mldsa_make_key(prng_state *prng, int wprng, int alg, mldsa_key *key) +{ + unsigned char seedbuf[MLDSA_SEEDBYTES]; + int err; + + LTC_ARGCHK(key != NULL); + + if ((err = prng_is_valid(wprng)) != CRYPT_OK) return err; + if (prng_descriptor[wprng].read(seedbuf, MLDSA_SEEDBYTES, prng) != MLDSA_SEEDBYTES) + return CRYPT_ERROR_READPRNG; + + err = s_mldsa_make_key_seed(alg, seedbuf, key); + zeromem(seedbuf, sizeof(seedbuf)); + return err; +} + +/** + Free an ML-DSA key from memory. + @param key The key to free +*/ +void mldsa_free(mldsa_key *key) +{ + if (key == NULL) return; + if (key->sk != NULL) { + zeromem(key->sk, key->sklen); + XFREE(key->sk); + } + if (key->pk != NULL) { + XFREE(key->pk); + } + XMEMSET(key, 0, sizeof(*key)); +} + +/** + Export an ML-DSA key to a byte buffer. + @param out [out] Destination for the exported key + @param outlen [in/out] Max size and resulting size of the exported key + @param which PK_PUBLIC for the verification key, PK_PRIVATE for the signing key + @param key The key to export + @return CRYPT_OK if successful +*/ +int mldsa_export_raw(unsigned char *out, unsigned long *outlen, int which, const mldsa_key *key) +{ + mldsa_params p; + unsigned long needed; + int err; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = s_mldsa_get_params(key->alg, &p)) != CRYPT_OK) return err; + + if (which == PK_PUBLIC) { + needed = p.pk_bytes; + if (*outlen < needed) { *outlen = needed; return CRYPT_BUFFER_OVERFLOW; } + if (key->pk == NULL) return CRYPT_PK_NOT_PRIVATE; + XMEMCPY(out, key->pk, needed); + } else if (which == PK_PRIVATE) { + if (key->type != PK_PRIVATE) return CRYPT_PK_NOT_PRIVATE; + needed = p.sk_bytes; + if (*outlen < needed) { *outlen = needed; return CRYPT_BUFFER_OVERFLOW; } + XMEMCPY(out, key->sk, needed); + } else { + return CRYPT_INVALID_ARG; + } + + *outlen = needed; + return CRYPT_OK; +} + +/** + Import an ML-DSA key from a byte buffer. + @param in The buffer to import from + @param inlen Length of the buffer + @param which PK_PUBLIC for a verification key, PK_PRIVATE for a signing key + @param alg The parameter set (LTC_MLDSA_44, LTC_MLDSA_65, or LTC_MLDSA_87) + @param key [out] Destination for the imported key + @return CRYPT_OK if successful +*/ +int mldsa_import_raw(const unsigned char *in, unsigned long inlen, int which, int alg, mldsa_key *key) +{ + mldsa_params p; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = s_mldsa_get_params(alg, &p)) != CRYPT_OK) return err; + + XMEMSET(key, 0, sizeof(*key)); + key->alg = alg; + + if (which == PK_PUBLIC) { + if (inlen != p.pk_bytes) return CRYPT_INVALID_PACKET; + key->pk = XMALLOC(p.pk_bytes); + if (key->pk == NULL) return CRYPT_MEM; + XMEMCPY(key->pk, in, p.pk_bytes); + key->pklen = p.pk_bytes; + key->type = PK_PUBLIC; + } else if (which == PK_PRIVATE) { + if (inlen != p.sk_bytes) return CRYPT_INVALID_PACKET; + key->sk = XMALLOC(p.sk_bytes); + if (key->sk == NULL) return CRYPT_MEM; + XMEMCPY(key->sk, in, p.sk_bytes); + key->sklen = p.sk_bytes; + + /* Reconstruct pk from sk: pk = (rho, t1) where rho is at offset 0 of sk. + We need to extract rho and recompute t1 from sk components. Actually, + the pk is NOT embedded in the sk for ML-DSA (unlike ML-KEM). + We need to reconstruct it: unpack sk to get rho,key,tr,s1,s2,t0, + then compute t = A*s1 + s2, t1 = power2round(t). */ + { + unsigned char rho[MLDSA_SEEDBYTES], tr[MLDSA_TRBYTES], kk[MLDSA_SEEDBYTES]; + mldsa_polyvecl mat[MLDSA_K_MAX], s1, s1hat; + mldsa_polyveck s2, t0, t1, t0_dummy; + + XMEMSET(mat, 0, sizeof(mat)); + XMEMSET(&s1, 0, sizeof(s1)); + XMEMSET(&s2, 0, sizeof(s2)); + + s_unpack_sk(rho, tr, kk, &t0, &s1, &s2, in, &p); + + /* Expand matrix */ + if ((err = s_polyvec_matrix_expand(mat, p.k, p.l, rho)) != CRYPT_OK) { + mldsa_free(key); + return err; + } + + s1hat = s1; + s_polyvecl_ntt(&s1hat, p.l); + s_polyvec_matrix_pointwise_montgomery(&t1, mat, &s1hat, p.k, p.l); + s_polyveck_reduce(&t1, p.k); + s_polyveck_invntt_tomont(&t1, p.k); + s_polyveck_add(&t1, &t1, &s2, p.k); + s_polyveck_caddq(&t1, p.k); + s_polyveck_power2round(&t1, &t0_dummy, &t1, p.k); + + key->pk = XMALLOC(p.pk_bytes); + if (key->pk == NULL) { + mldsa_free(key); + return CRYPT_MEM; + } + s_pack_pk(key->pk, rho, &t1, p.k); + key->pklen = p.pk_bytes; + } + + key->type = PK_PRIVATE; + } else { + return CRYPT_INVALID_ARG; + } + + return CRYPT_OK; +} + +/** + Sign a message with ML-DSA. + @param msg The message to sign + @param msglen Length of the message + @param sig [out] The signature + @param siglen [in/out] Max size and resulting size of the signature + @param ctx Optional context string (can be NULL if ctxlen is 0) + @param ctxlen Length of the context string (max 255 bytes per FIPS 204) + @param prng An active PRNG state (for hedged signing) + @param wprng The index of the desired PRNG + @param key The private (signing) key + @return CRYPT_OK if successful +*/ +int mldsa_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + prng_state *prng, int wprng, + const mldsa_key *key) +{ + mldsa_params p; + unsigned char pre[257]; + unsigned char rnd[MLDSA_RNDBYTES]; + unsigned long i; + int err; + + LTC_ARGCHK(msg != NULL || msglen == 0); + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(siglen != NULL); + LTC_ARGCHK(key != NULL); + + if (key->type != PK_PRIVATE) return CRYPT_PK_NOT_PRIVATE; + if (ctxlen > 255) return CRYPT_INVALID_ARG; + + if ((err = s_mldsa_get_params(key->alg, &p)) != CRYPT_OK) return err; + if (*siglen < p.sig_bytes) { *siglen = p.sig_bytes; return CRYPT_BUFFER_OVERFLOW; } + if ((err = prng_is_valid(wprng)) != CRYPT_OK) return err; + + /* Prepare pre = (0, ctxlen, ctx) */ + pre[0] = 0; + pre[1] = (unsigned char)ctxlen; + if (ctxlen > 0 && ctx != NULL) { + for (i = 0; i < ctxlen; i++) + pre[2 + i] = ctx[i]; + } + + /* Hedged signing: get randomness */ + if (prng_descriptor[wprng].read(rnd, MLDSA_RNDBYTES, prng) != MLDSA_RNDBYTES) + return CRYPT_ERROR_READPRNG; + + err = s_sign_internal(sig, siglen, msg, msglen, pre, 2 + ctxlen, rnd, key->sk, &p); + + zeromem(rnd, sizeof(rnd)); + return err; +} + +/** + Verify a signature with ML-DSA. + @param sig The signature to verify + @param siglen Length of the signature + @param msg The message that was signed + @param msglen Length of the message + @param ctx Optional context string (can be NULL if ctxlen is 0) + @param ctxlen Length of the context string (max 255 bytes per FIPS 204) + @param stat [out] Result of the verification: 1==valid, 0==invalid + @param key The public (verification) key + @return CRYPT_OK if successful (even if the signature is invalid) +*/ +int mldsa_verify(const unsigned char *sig, unsigned long siglen, + const unsigned char *msg, unsigned long msglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const mldsa_key *key) +{ + mldsa_params p; + unsigned char pre[257]; + unsigned long i; + int err; + + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(msg != NULL || msglen == 0); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + + *stat = 0; + + if (ctxlen > 255) return CRYPT_INVALID_ARG; + if (key->pk == NULL) return CRYPT_INVALID_ARG; + + if ((err = s_mldsa_get_params(key->alg, &p)) != CRYPT_OK) return err; + + /* Prepare pre = (0, ctxlen, ctx) */ + pre[0] = 0; + pre[1] = (unsigned char)ctxlen; + if (ctxlen > 0 && ctx != NULL) { + for (i = 0; i < ctxlen; i++) + pre[2 + i] = ctx[i]; + } + + err = s_verify_internal(sig, siglen, msg, msglen, pre, 2 + ctxlen, key->pk, &p); + if (err == CRYPT_OK) + *stat = 1; + else if (err == CRYPT_INVALID_PACKET) + err = CRYPT_OK; /* Verification failed but no internal error */ + + return err; +} + +/** + Get the sizes for a given ML-DSA parameter set. + Any output pointer may be NULL if the caller does not need that value. + @param alg The parameter set (LTC_MLDSA_44, LTC_MLDSA_65, or LTC_MLDSA_87) + @param public_key_sz [out] Public key size in bytes + @param secret_key_sz [out] Secret key size in bytes + @param signature_sz [out] Signature size in bytes + @return CRYPT_OK if successful +*/ +int mldsa_get_sizes(int alg, unsigned long *public_key_sz, unsigned long *secret_key_sz, + unsigned long *signature_sz) +{ + mldsa_params p; + int err; + + if ((err = s_mldsa_get_params(alg, &p)) != CRYPT_OK) return err; + + if (public_key_sz != NULL) *public_key_sz = p.pk_bytes; + if (secret_key_sz != NULL) *secret_key_sz = p.sk_bytes; + if (signature_sz != NULL) *signature_sz = p.sig_bytes; + + return CRYPT_OK; +} + +#endif /* LTC_MLDSA */ diff --git a/src/pqc/mldsa_export.c b/src/pqc/mldsa_export.c new file mode 100644 index 000000000..d1fc52477 --- /dev/null +++ b/src/pqc/mldsa_export.c @@ -0,0 +1,114 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file mldsa_export.c + Export a ML-DSA key to a binary packet +*/ + +#ifdef LTC_MLDSA + +static int s_mldsa_alg_to_oid(int alg, enum ltc_oid_id *oid_id) +{ + LTC_ARGCHK(oid_id != NULL); + + switch (alg) { + case LTC_MLDSA_44: + *oid_id = LTC_OID_MLDSA_44; + return CRYPT_OK; + case LTC_MLDSA_65: + *oid_id = LTC_OID_MLDSA_65; + return CRYPT_OK; + case LTC_MLDSA_87: + *oid_id = LTC_OID_MLDSA_87; + return CRYPT_OK; + default: + return CRYPT_PK_INVALID_TYPE; + } +} + +/** + Export a ML-DSA key to a binary packet + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the ML-DSA key + @param which Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int mldsa_export(unsigned char *out, unsigned long *outlen, + int which, const mldsa_key *key) +{ + int err, std; + enum ltc_oid_id oid_id; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + std = which & PK_STD; + which &= ~PK_STD; + + if ((err = s_mldsa_alg_to_oid(key->alg, &oid_id)) != CRYPT_OK) { + return err; + } + + if (which == PK_PRIVATE) { + const char *OID; + unsigned long version, oid[16], oidlen; + unsigned char *private_key; + unsigned long private_key_len; + ltc_asn1_list alg_id[1]; + + if (key->type != PK_PRIVATE || key->sk == NULL) return CRYPT_PK_INVALID_TYPE; + + if (std != PK_STD) { + return mldsa_export_raw(out, outlen, which, key); + } + + if ((err = pk_get_oid(oid_id, &OID)) != CRYPT_OK) { + return err; + } + oidlen = LTC_ARRAY_SIZE(oid); + if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { + return err; + } + LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); + + if ((err = der_length_octet_string(key->sklen, &private_key_len)) != CRYPT_OK) { + return err; + } + private_key = XMALLOC(private_key_len); + if (private_key == NULL) { + return CRYPT_MEM; + } + + err = der_encode_octet_string(key->sk, key->sklen, private_key, &private_key_len); + if (err == CRYPT_OK) { + version = 0; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1uL, &version, + LTC_ASN1_SEQUENCE, 1uL, alg_id, + LTC_ASN1_OCTET_STRING, private_key_len, private_key, + LTC_ASN1_EOL, 0uL, NULL); + } + + XFREE(private_key); + return err; + } + + if (which != PK_PUBLIC) { + return CRYPT_INVALID_ARG; + } + if (key->pk == NULL) return CRYPT_PK_INVALID_TYPE; + + if (std == PK_STD) { + return x509_encode_subject_public_key_info(out, outlen, oid_id, + key->pk, key->pklen, + LTC_ASN1_EOL, NULL, 0uL); + } + + return mldsa_export_raw(out, outlen, which, key); +} + +#endif diff --git a/src/pqc/mldsa_import.c b/src/pqc/mldsa_import.c new file mode 100644 index 000000000..739d0c1dc --- /dev/null +++ b/src/pqc/mldsa_import.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file mldsa_import.c + Import a ML-DSA key from a SubjectPublicKeyInfo +*/ + +#ifdef LTC_MLDSA + +typedef struct { + enum ltc_oid_id oid; + int alg; +} mldsa_oid_map; + +static const mldsa_oid_map s_mldsa_oid_map[] = { + { LTC_OID_MLDSA_44, LTC_MLDSA_44 }, + { LTC_OID_MLDSA_65, LTC_MLDSA_65 }, + { LTC_OID_MLDSA_87, LTC_MLDSA_87 }, +}; + +/** + Import a ML-DSA public key + @param in The packet to read + @param inlen The length of the input packet + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int mldsa_import(const unsigned char *in, unsigned long inlen, mldsa_key *key) +{ + unsigned char *pub; + unsigned long pub_len, max_pub_len; + unsigned long i; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = mldsa_get_sizes(LTC_MLDSA_87, &max_pub_len, NULL, NULL)) != CRYPT_OK) { + return err; + } + + pub = XMALLOC(max_pub_len); + if (pub == NULL) { + return CRYPT_MEM; + } + + err = CRYPT_PK_INVALID_TYPE; + for (i = 0; i < LTC_ARRAY_SIZE(s_mldsa_oid_map); ++i) { + pub_len = max_pub_len; + err = x509_decode_subject_public_key_info(in, inlen, s_mldsa_oid_map[i].oid, + pub, &pub_len, + LTC_ASN1_EOL, NULL, 0uL); + if (err == CRYPT_OK) { + err = mldsa_import_raw(pub, pub_len, PK_PUBLIC, s_mldsa_oid_map[i].alg, key); + break; + } + } + + XFREE(pub); + return err; +} + +#endif diff --git a/src/pqc/mldsa_import_pkcs8.c b/src/pqc/mldsa_import_pkcs8.c new file mode 100644 index 000000000..e60997e04 --- /dev/null +++ b/src/pqc/mldsa_import_pkcs8.c @@ -0,0 +1,162 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file mldsa_import_pkcs8.c + Import a ML-DSA key in PKCS#8 format +*/ + +#ifdef LTC_MLDSA + +static int s_mldsa_oid_to_alg(enum ltc_oid_id oid_id, int *alg) +{ + LTC_ARGCHK(alg != NULL); + + switch (oid_id) { + case LTC_OID_MLDSA_44: + *alg = LTC_MLDSA_44; + return CRYPT_OK; + case LTC_OID_MLDSA_65: + *alg = LTC_MLDSA_65; + return CRYPT_OK; + case LTC_OID_MLDSA_87: + *alg = LTC_MLDSA_87; + return CRYPT_OK; + default: + return CRYPT_PK_INVALID_TYPE; + } +} + +int mldsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, + mldsa_key *key) +{ + ltc_asn1_list *decoded = NULL; + ltc_asn1_list *seed = NULL, *raw_key = NULL; + ltc_asn1_list seed_custom[1]; + der_flexi_check flexi_should[4]; + enum ltc_oid_id oid_id; + int alg, err; + unsigned char *raw_buf = NULL; + unsigned char seed_buf[32]; + unsigned long inlen, raw_buf_len, key_len, n; + mldsa_key seed_key; + + LTC_ARGCHK(alg_id != NULL); + LTC_ARGCHK(priv_key != NULL); + LTC_ARGCHK(key != NULL); + XMEMSET(&seed_key, 0, sizeof(seed_key)); + + if ((err = pk_get_oid_from_asn1(alg_id->child, &oid_id)) != CRYPT_OK) { + return err; + } + if ((err = s_mldsa_oid_to_alg(oid_id, &alg)) != CRYPT_OK) { + return err; + } + + if ((err = mldsa_get_sizes(alg, NULL, &key_len, NULL)) != CRYPT_OK) { + return err; + } + if (priv_key->size == key_len) { + return mldsa_import_raw(priv_key->data, priv_key->size, PK_PRIVATE, alg, key); + } + + raw_buf = XMALLOC(key_len); + if (raw_buf == NULL) { + return CRYPT_MEM; + } + raw_buf_len = key_len; + err = der_decode_octet_string(priv_key->data, priv_key->size, raw_buf, &raw_buf_len); + if (err == CRYPT_OK) { + err = (raw_buf_len == key_len) + ? mldsa_import_raw(raw_buf, raw_buf_len, PK_PRIVATE, alg, key) + : CRYPT_INVALID_PACKET; + XFREE(raw_buf); + return err; + } + XFREE(raw_buf); + + LTC_SET_ASN1_CUSTOM_PRIMITIVE(seed_custom, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, + LTC_ASN1_OCTET_STRING, seed_buf, sizeof(seed_buf)); + err = der_decode_custom_type(priv_key->data, priv_key->size, seed_custom); + if (err == CRYPT_OK) { + return mldsa_make_key_from_seed(alg, seed_buf, seed_custom[0].size, key); + } + + inlen = priv_key->size; + err = der_decode_sequence_flexi(priv_key->data, &inlen, &decoded); + if (err != CRYPT_OK) { + return err; + } + + n = 0; + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, &seed); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, &raw_key); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); + err = der_flexi_sequence_cmp(decoded, flexi_should); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { + goto cleanup; + } + + if (seed == NULL || raw_key == NULL) { + err = CRYPT_INVALID_PACKET; + goto cleanup; + } + if ((err = mldsa_make_key_from_seed(alg, seed->data, seed->size, &seed_key)) != CRYPT_OK) { + goto cleanup; + } + if (seed_key.sklen != raw_key->size || + XMEMCMP(seed_key.sk, raw_key->data, raw_key->size) != 0) { + err = CRYPT_INVALID_PACKET; + goto cleanup; + } + + err = mldsa_import_raw(raw_key->data, raw_key->size, PK_PRIVATE, alg, key); + +cleanup: + mldsa_free(&seed_key); + der_free_sequence_flexi(decoded); + return err; +} + +/** + Import a ML-DSA private key in PKCS#8 format + @param in The packet to import from + @param inlen It's length (octets) + @param pw_ctx The password context when decrypting the private key + @param key [out] Destination for newly imported key + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int mldsa_import_pkcs8(const unsigned char *in, unsigned long inlen, const password_ctx *pw_ctx, mldsa_key *key) +{ + int alg, err; + ltc_asn1_list *l = NULL; + ltc_asn1_list *alg_id, *priv_key; + enum ltc_oid_id oid_id; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l); + if (err != CRYPT_OK) { + return err; + } + + if ((err = pkcs8_get_children(l, &oid_id, &alg_id, &priv_key)) != CRYPT_OK) { + goto cleanup; + } + err = s_mldsa_oid_to_alg(oid_id, &alg); + if (err != CRYPT_OK) { + err = CRYPT_INVALID_PACKET; + goto cleanup; + } + LTC_UNUSED_PARAM(alg); + + err = mldsa_import_pkcs8_asn1(alg_id, priv_key, key); + +cleanup: + der_free_sequence_flexi(l); + return err; +} + +#endif diff --git a/src/pqc/mldsa_import_x509.c b/src/pqc/mldsa_import_x509.c new file mode 100644 index 000000000..7be402c34 --- /dev/null +++ b/src/pqc/mldsa_import_x509.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file mldsa_import_x509.c + Import a ML-DSA key from a X.509 certificate +*/ + +#ifdef LTC_MLDSA + +typedef struct { + mldsa_key *key; + int alg; +} mldsa_x509_ctx; + +typedef struct { + enum ltc_oid_id oid; + int alg; +} mldsa_oid_map_x509; + +static const mldsa_oid_map_x509 s_mldsa_oid_map_x509[] = { + { LTC_OID_MLDSA_44, LTC_MLDSA_44 }, + { LTC_OID_MLDSA_65, LTC_MLDSA_65 }, + { LTC_OID_MLDSA_87, LTC_MLDSA_87 }, +}; + +static int s_mldsa_decode(const unsigned char *in, unsigned long inlen, mldsa_x509_ctx *ctx) +{ + return mldsa_import_raw(in, inlen, PK_PUBLIC, ctx->alg, ctx->key); +} + +/** + Import a ML-DSA public key from a X.509 certificate + @param in The DER encoded X.509 certificate + @param inlen The length of the certificate + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int mldsa_import_x509(const unsigned char *in, unsigned long inlen, mldsa_key *key) +{ + mldsa_x509_ctx ctx; + unsigned long i; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + err = CRYPT_PK_INVALID_TYPE; + for (i = 0; i < LTC_ARRAY_SIZE(s_mldsa_oid_map_x509); ++i) { + ctx.key = key; + ctx.alg = s_mldsa_oid_map_x509[i].alg; + err = x509_decode_public_key_from_certificate(in, inlen, + s_mldsa_oid_map_x509[i].oid, + LTC_ASN1_EOL, NULL, NULL, + (public_key_decode_cb)s_mldsa_decode, &ctx); + if (err == CRYPT_OK) { + break; + } + } + + return err; +} + +#endif diff --git a/src/pqc/mlkem.c b/src/pqc/mlkem.c new file mode 100644 index 000000000..3cd6e5689 --- /dev/null +++ b/src/pqc/mlkem.c @@ -0,0 +1,1230 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file mlkem.c + ML-KEM (FIPS 203) implementation: polynomial arithmetic, IND-CPA scheme, + KEM operations, and public API. + Based on the CRYSTALS-Kyber reference implementation (public domain). +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_MLKEM + +/* Exact 16-bit types for lattice arithmetic. + * Assumes short is 16-bit, which holds on all platforms libtomcrypt targets. */ +typedef signed short ishort16; +typedef unsigned short ushort16; + +/* ---- ML-KEM constants ---- */ +#define MLKEM_N 256 +#define MLKEM_Q 3329 +#define MLKEM_SYMBYTES 32 +#define MLKEM_SSBYTES 32 +#define MLKEM_POLYBYTES 384 +#define MLKEM_K_MAX 4 +#define MLKEM_QINV (-3327) /* q^{-1} mod 2^16 */ +#define MLKEM_XOF_BLOCKBYTES 168 /* SHAKE128 rate */ + +/* ---- Runtime parameter set ---- */ +typedef struct { + int k, eta1, eta2, du, dv; + unsigned long polyvec_bytes, polyvec_compressed_bytes, poly_compressed_bytes; + unsigned long indcpa_pk_bytes, indcpa_sk_bytes, indcpa_ct_bytes; + unsigned long pk_bytes, sk_bytes, ct_bytes; +} mlkem_params; + +/* ---- Polynomial types ---- */ +typedef struct { + ishort16 coeffs[MLKEM_N]; +} mlkem_poly; + +typedef struct { + mlkem_poly vec[MLKEM_K_MAX]; +} mlkem_polyvec; + +/* Montgomery / Barrett reduction */ + +static ishort16 s_mlkem_montgomery_reduce(int a) +{ + ishort16 t; + t = (ishort16)a * MLKEM_QINV; + t = (a - (int)t * MLKEM_Q) >> 16; + return t; +} + +static ishort16 s_mlkem_barrett_reduce(ishort16 a) +{ + ishort16 t; + const ishort16 v = ((1 << 26) + MLKEM_Q / 2) / MLKEM_Q; + t = ((int)v * a + (1 << 25)) >> 26; + t *= MLKEM_Q; + return a - t; +} + +static ishort16 s_mlkem_fqmul(ishort16 a, ishort16 b) +{ + return s_mlkem_montgomery_reduce((int)a * b); +} + +/* NTT */ + +static const ishort16 s_mlkem_zetas[128] = { + -1044, -758, -359, -1517, 1493, 1422, 287, 202, + -171, 622, 1577, 182, 962, -1202, -1474, 1468, + 573, -1325, 264, 383, -829, 1458, -1602, -130, + -681, 1017, 732, 608, -1542, 411, -205, -1571, + 1223, 652, -552, 1015, -1293, 1491, -282, -1544, + 516, -8, -320, -666, -1618, -1162, 126, 1469, + -853, -90, -271, 830, 107, -1421, -247, -951, + -398, 961, -1508, -725, 448, -1065, 677, -1275, + -1103, 430, 555, 843, -1251, 871, 1550, 105, + 422, 587, 177, -235, -291, -460, 1574, 1653, + -246, 778, 1159, -147, -777, 1483, -602, 1119, + -1590, 644, -872, 349, 418, 329, -156, -75, + 817, 1097, 603, 610, 1322, -1285, -1465, 384, + -1215, -136, 1218, -1335, -874, 220, -1187, -1659, + -1185, -1530, -1278, 794, -1510, -854, -870, 478, + -108, -308, 996, 991, 958, -1460, 1522, 1628 +}; + +static void s_mlkem_ntt(ishort16 r[256]) +{ + unsigned int len, start, j, k; + ishort16 t, zeta; + + k = 1; + for (len = 128; len >= 2; len >>= 1) { + for (start = 0; start < 256; start = j + len) { + zeta = s_mlkem_zetas[k++]; + for (j = start; j < start + len; j++) { + t = s_mlkem_fqmul(zeta, r[j + len]); + r[j + len] = r[j] - t; + r[j] = r[j] + t; + } + } + } +} + +static void s_mlkem_invntt(ishort16 r[256]) +{ + unsigned int start, len, j, k; + ishort16 t, zeta; + const ishort16 f = 1441; /* mont^2/128 */ + + k = 127; + for (len = 2; len <= 128; len <<= 1) { + for (start = 0; start < 256; start = j + len) { + zeta = s_mlkem_zetas[k--]; + for (j = start; j < start + len; j++) { + t = r[j]; + r[j] = s_mlkem_barrett_reduce(t + r[j + len]); + r[j + len] = r[j + len] - t; + r[j + len] = s_mlkem_fqmul(zeta, r[j + len]); + } + } + } + + for (j = 0; j < 256; j++) + r[j] = s_mlkem_fqmul(r[j], f); +} + +static void s_mlkem_basemul(ishort16 r[2], const ishort16 a[2], const ishort16 b[2], ishort16 zeta) +{ + r[0] = s_mlkem_fqmul(a[1], b[1]); + r[0] = s_mlkem_fqmul(r[0], zeta); + r[0] += s_mlkem_fqmul(a[0], b[0]); + r[1] = s_mlkem_fqmul(a[0], b[1]); + r[1] += s_mlkem_fqmul(a[1], b[0]); +} + +/* CBD (Centered Binomial Distribution) */ + +static ulong32 s_mlkem_load32_le(const unsigned char *x) +{ + ulong32 r; + LOAD32L(r, x); + return r; +} + +static ulong32 s_mlkem_load24_le(const unsigned char *x) +{ + return ((ulong32)(x[0] & 255)) + | ((ulong32)(x[1] & 255) << 8) + | ((ulong32)(x[2] & 255) << 16); +} + +static void s_mlkem_cbd2(mlkem_poly *r, const unsigned char *buf) +{ + unsigned int i, j; + ulong32 t, d; + ishort16 a, b; + + for (i = 0; i < MLKEM_N / 8; i++) { + t = s_mlkem_load32_le(buf + 4 * i); + d = t & 0x55555555u; + d += (t >> 1) & 0x55555555u; + + for (j = 0; j < 8; j++) { + a = (d >> (4 * j + 0)) & 0x3; + b = (d >> (4 * j + 2)) & 0x3; + r->coeffs[8 * i + j] = a - b; + } + } +} + +static void s_mlkem_cbd3(mlkem_poly *r, const unsigned char *buf) +{ + unsigned int i, j; + ulong32 t, d; + ishort16 a, b; + + for (i = 0; i < MLKEM_N / 4; i++) { + t = s_mlkem_load24_le(buf + 3 * i); + d = t & 0x00249249u; + d += (t >> 1) & 0x00249249u; + d += (t >> 2) & 0x00249249u; + + for (j = 0; j < 4; j++) { + a = (d >> (6 * j + 0)) & 0x7; + b = (d >> (6 * j + 3)) & 0x7; + r->coeffs[4 * i + j] = a - b; + } + } +} + +static void s_mlkem_poly_cbd_eta(mlkem_poly *r, const unsigned char *buf, int eta) +{ + if (eta == 3) { + s_mlkem_cbd3(r, buf); + } else { + s_mlkem_cbd2(r, buf); + } +} + +/* Constant-time operations */ + +static int s_mlkem_ct_verify(const unsigned char *a, const unsigned char *b, unsigned long len) +{ + unsigned long i; + unsigned char r = 0; + + for (i = 0; i < len; i++) + r |= a[i] ^ b[i]; + + return (-(ulong64)r) >> 63; +} + +static void s_mlkem_cmov(unsigned char *r, const unsigned char *x, unsigned long len, unsigned char b) +{ + unsigned long i; + +#if defined(__GNUC__) || defined(__clang__) + __asm__("" : "+r"(b) : /* no inputs */); +#endif + + b = -b; + for (i = 0; i < len; i++) + r[i] ^= b & (r[i] ^ x[i]); +} + +static void s_mlkem_cmov_int16(ishort16 *r, ishort16 v, ushort16 b) +{ + b = -b; + *r ^= b & ((*r) ^ v); +} + +/* Parameter lookup */ + +static int s_mlkem_get_params(int alg, mlkem_params *p) +{ + LTC_ARGCHK(p != NULL); + + XMEMSET(p, 0, sizeof(*p)); + + switch (alg) { + case LTC_MLKEM_512: + p->k = 2; p->eta1 = 3; p->eta2 = 2; p->du = 10; p->dv = 4; + break; + case LTC_MLKEM_768: + p->k = 3; p->eta1 = 2; p->eta2 = 2; p->du = 10; p->dv = 4; + break; + case LTC_MLKEM_1024: + p->k = 4; p->eta1 = 2; p->eta2 = 2; p->du = 11; p->dv = 5; + break; + default: + return CRYPT_INVALID_ARG; + } + + p->polyvec_bytes = (unsigned long)p->k * MLKEM_POLYBYTES; + p->polyvec_compressed_bytes = (unsigned long)p->k * (p->du == 11 ? 352 : 320); + p->poly_compressed_bytes = p->dv == 5 ? 160 : 128; + p->indcpa_pk_bytes = p->polyvec_bytes + MLKEM_SYMBYTES; + p->indcpa_sk_bytes = p->polyvec_bytes; + p->indcpa_ct_bytes = p->polyvec_compressed_bytes + p->poly_compressed_bytes; + p->pk_bytes = p->indcpa_pk_bytes; + p->sk_bytes = p->indcpa_sk_bytes + p->indcpa_pk_bytes + 2 * MLKEM_SYMBYTES; + p->ct_bytes = p->indcpa_ct_bytes; + + return CRYPT_OK; +} + +/* Symmetric primitives using libtomcrypt SHA3 */ + +static int s_mlkem_hash_h(unsigned char out[32], const unsigned char *in, unsigned long inlen) +{ + int idx; + unsigned long outlen = 32; + idx = find_hash("sha3-256"); + if (idx == -1) return CRYPT_INVALID_HASH; + return hash_memory(idx, in, inlen, out, &outlen); +} + +static int s_mlkem_hash_g(unsigned char out[64], const unsigned char *in, unsigned long inlen) +{ + int idx; + unsigned long outlen = 64; + idx = find_hash("sha3-512"); + if (idx == -1) return CRYPT_INVALID_HASH; + return hash_memory(idx, in, inlen, out, &outlen); +} + +static int s_mlkem_xof_absorb(hash_state *state, const unsigned char seed[MLKEM_SYMBYTES], + unsigned char x, unsigned char y) +{ + int err; + unsigned char extseed[MLKEM_SYMBYTES + 2]; + + XMEMCPY(extseed, seed, MLKEM_SYMBYTES); + extseed[MLKEM_SYMBYTES + 0] = x; + extseed[MLKEM_SYMBYTES + 1] = y; + + if ((err = sha3_shake_init(state, 128)) != CRYPT_OK) return err; + return sha3_shake_process(state, extseed, sizeof(extseed)); +} + +static int s_mlkem_xof_squeeze(hash_state *state, unsigned char *out, unsigned long outlen) +{ + return sha3_shake_done(state, out, outlen); +} + +static int s_mlkem_prf(unsigned char *out, unsigned long outlen, + const unsigned char key[MLKEM_SYMBYTES], unsigned char nonce) +{ + int err; + hash_state md; + unsigned char extkey[MLKEM_SYMBYTES + 1]; + + XMEMCPY(extkey, key, MLKEM_SYMBYTES); + extkey[MLKEM_SYMBYTES] = nonce; + + if ((err = sha3_shake_init(&md, 256)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, extkey, sizeof(extkey))) != CRYPT_OK) return err; + return sha3_shake_done(&md, out, outlen); +} + +static int s_mlkem_rkprf(unsigned char out[MLKEM_SSBYTES], + const unsigned char key[MLKEM_SYMBYTES], + const unsigned char *ct, unsigned long ctlen) +{ + int err; + hash_state md; + + if ((err = sha3_shake_init(&md, 256)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, key, MLKEM_SYMBYTES)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, ct, ctlen)) != CRYPT_OK) return err; + return sha3_shake_done(&md, out, MLKEM_SSBYTES); +} + +/* Polynomial operations */ + +static void s_mlkem_poly_compress(unsigned char *r, const mlkem_poly *a, int dv) +{ + unsigned int i, j; + ishort16 u; + ulong32 d0; + unsigned char t[8]; + + if (dv == 4) { + for (i = 0; i < MLKEM_N / 8; i++) { + for (j = 0; j < 8; j++) { + u = a->coeffs[8 * i + j]; + u += (u >> 15) & MLKEM_Q; + d0 = u << 4; + d0 += 1665; + d0 *= 80635; + d0 >>= 28; + t[j] = d0 & 0xf; + } + r[0] = t[0] | (t[1] << 4); + r[1] = t[2] | (t[3] << 4); + r[2] = t[4] | (t[5] << 4); + r[3] = t[6] | (t[7] << 4); + r += 4; + } + } else { /* dv == 5 */ + for (i = 0; i < MLKEM_N / 8; i++) { + for (j = 0; j < 8; j++) { + u = a->coeffs[8 * i + j]; + u += (u >> 15) & MLKEM_Q; + d0 = u << 5; + d0 += 1664; + d0 *= 40318; + d0 >>= 27; + t[j] = d0 & 0x1f; + } + r[0] = (t[0] >> 0) | (t[1] << 5); + r[1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7); + r[2] = (t[3] >> 1) | (t[4] << 4); + r[3] = (t[4] >> 4) | (t[5] << 1) | (t[6] << 6); + r[4] = (t[6] >> 2) | (t[7] << 3); + r += 5; + } + } +} + +static void s_mlkem_poly_decompress(mlkem_poly *r, const unsigned char *a, int dv) +{ + unsigned int i; + + if (dv == 4) { + for (i = 0; i < MLKEM_N / 2; i++) { + r->coeffs[2 * i + 0] = (((ushort16)(a[0] & 15) * MLKEM_Q) + 8) >> 4; + r->coeffs[2 * i + 1] = (((ushort16)(a[0] >> 4) * MLKEM_Q) + 8) >> 4; + a += 1; + } + } else { /* dv == 5 */ + unsigned int j; + unsigned char t[8]; + for (i = 0; i < MLKEM_N / 8; i++) { + t[0] = (a[0] >> 0); + t[1] = (a[0] >> 5) | (a[1] << 3); + t[2] = (a[1] >> 2); + t[3] = (a[1] >> 7) | (a[2] << 1); + t[4] = (a[2] >> 4) | (a[3] << 4); + t[5] = (a[3] >> 1); + t[6] = (a[3] >> 6) | (a[4] << 2); + t[7] = (a[4] >> 3); + a += 5; + + for (j = 0; j < 8; j++) + r->coeffs[8 * i + j] = ((ulong32)(t[j] & 31) * MLKEM_Q + 16) >> 5; + } + } +} + +static void s_mlkem_poly_tobytes(unsigned char *r, const mlkem_poly *a) +{ + unsigned int i; + ushort16 t0, t1; + + for (i = 0; i < MLKEM_N / 2; i++) { + t0 = a->coeffs[2 * i]; + t0 += ((ishort16)t0 >> 15) & MLKEM_Q; + t1 = a->coeffs[2 * i + 1]; + t1 += ((ishort16)t1 >> 15) & MLKEM_Q; + r[3 * i + 0] = (t0 >> 0); + r[3 * i + 1] = (t0 >> 8) | (t1 << 4); + r[3 * i + 2] = (t1 >> 4); + } +} + +static void s_mlkem_poly_frombytes(mlkem_poly *r, const unsigned char *a) +{ + unsigned int i; + for (i = 0; i < MLKEM_N / 2; i++) { + r->coeffs[2 * i] = ((a[3 * i + 0] >> 0) | ((ushort16)a[3 * i + 1] << 8)) & 0xFFF; + r->coeffs[2 * i + 1] = ((a[3 * i + 1] >> 4) | ((ushort16)a[3 * i + 2] << 4)) & 0xFFF; + } +} + +static void s_mlkem_poly_frommsg(mlkem_poly *r, const unsigned char msg[MLKEM_SYMBYTES]) +{ + unsigned int i, j; + + for (i = 0; i < MLKEM_N / 8; i++) { + for (j = 0; j < 8; j++) { + r->coeffs[8 * i + j] = 0; + s_mlkem_cmov_int16(r->coeffs + 8 * i + j, (MLKEM_Q + 1) / 2, (msg[i] >> j) & 1); + } + } +} + +static void s_mlkem_poly_tomsg(unsigned char msg[MLKEM_SYMBYTES], const mlkem_poly *a) +{ + unsigned int i, j; + ulong32 t; + + for (i = 0; i < MLKEM_N / 8; i++) { + msg[i] = 0; + for (j = 0; j < 8; j++) { + t = a->coeffs[8 * i + j]; + t <<= 1; + t += 1665; + t *= 80635; + t >>= 28; + t &= 1; + msg[i] |= t << j; + } + } +} + +static void s_mlkem_poly_reduce(mlkem_poly *r) +{ + unsigned int i; + for (i = 0; i < MLKEM_N; i++) + r->coeffs[i] = s_mlkem_barrett_reduce(r->coeffs[i]); +} + +static void s_mlkem_poly_getnoise(mlkem_poly *r, const unsigned char seed[MLKEM_SYMBYTES], + unsigned char nonce, int eta) +{ + unsigned char buf[3 * MLKEM_N / 4] = {0}; /* max for eta=3 */ + unsigned long buflen = (unsigned long)eta * MLKEM_N / 4; + s_mlkem_prf(buf, buflen, seed, nonce); + s_mlkem_poly_cbd_eta(r, buf, eta); +} + +static void s_mlkem_poly_ntt(mlkem_poly *r) +{ + s_mlkem_ntt(r->coeffs); + s_mlkem_poly_reduce(r); +} + +static void s_mlkem_poly_invntt_tomont(mlkem_poly *r) +{ + s_mlkem_invntt(r->coeffs); +} + +static void s_mlkem_poly_basemul_montgomery(mlkem_poly *r, const mlkem_poly *a, const mlkem_poly *b) +{ + unsigned int i; + for (i = 0; i < MLKEM_N / 4; i++) { + s_mlkem_basemul(&r->coeffs[4 * i], &a->coeffs[4 * i], + &b->coeffs[4 * i], s_mlkem_zetas[64 + i]); + s_mlkem_basemul(&r->coeffs[4 * i + 2], &a->coeffs[4 * i + 2], + &b->coeffs[4 * i + 2], -s_mlkem_zetas[64 + i]); + } +} + +static void s_mlkem_poly_tomont(mlkem_poly *r) +{ + unsigned int i; + const ishort16 f = (1ULL << 32) % MLKEM_Q; + for (i = 0; i < MLKEM_N; i++) + r->coeffs[i] = s_mlkem_montgomery_reduce((int)r->coeffs[i] * f); +} + +static void s_mlkem_poly_add(mlkem_poly *r, const mlkem_poly *a, const mlkem_poly *b) +{ + unsigned int i; + for (i = 0; i < MLKEM_N; i++) + r->coeffs[i] = a->coeffs[i] + b->coeffs[i]; +} + +static void s_mlkem_poly_sub(mlkem_poly *r, const mlkem_poly *a, const mlkem_poly *b) +{ + unsigned int i; + for (i = 0; i < MLKEM_N; i++) + r->coeffs[i] = a->coeffs[i] - b->coeffs[i]; +} + +/* Polynomial vector operations */ + +static void s_mlkem_polyvec_compress(unsigned char *r, const mlkem_polyvec *a, const mlkem_params *p) +{ + unsigned int i, j, k; + ulong64 d0; + + if (p->du == 11) { + ushort16 t[8]; + for (i = 0; i < (unsigned)p->k; i++) { + for (j = 0; j < MLKEM_N / 8; j++) { + for (k = 0; k < 8; k++) { + t[k] = a->vec[i].coeffs[8 * j + k]; + t[k] += ((ishort16)t[k] >> 15) & MLKEM_Q; + d0 = t[k]; + d0 <<= 11; + d0 += 1664; + d0 *= 645084; + d0 >>= 31; + t[k] = d0 & 0x7ff; + } + r[ 0] = (t[0] >> 0); + r[ 1] = (t[0] >> 8) | (t[1] << 3); + r[ 2] = (t[1] >> 5) | (t[2] << 6); + r[ 3] = (t[2] >> 2); + r[ 4] = (t[2] >> 10) | (t[3] << 1); + r[ 5] = (t[3] >> 7) | (t[4] << 4); + r[ 6] = (t[4] >> 4) | (t[5] << 7); + r[ 7] = (t[5] >> 1); + r[ 8] = (t[5] >> 9) | (t[6] << 2); + r[ 9] = (t[6] >> 6) | (t[7] << 5); + r[10] = (t[7] >> 3); + r += 11; + } + } + } else { /* du == 10 */ + ushort16 t[4]; + for (i = 0; i < (unsigned)p->k; i++) { + for (j = 0; j < MLKEM_N / 4; j++) { + for (k = 0; k < 4; k++) { + t[k] = a->vec[i].coeffs[4 * j + k]; + t[k] += ((ishort16)t[k] >> 15) & MLKEM_Q; + d0 = t[k]; + d0 <<= 10; + d0 += 1665; + d0 *= 1290167; + d0 >>= 32; + t[k] = d0 & 0x3ff; + } + r[0] = (t[0] >> 0); + r[1] = (t[0] >> 8) | (t[1] << 2); + r[2] = (t[1] >> 6) | (t[2] << 4); + r[3] = (t[2] >> 4) | (t[3] << 6); + r[4] = (t[3] >> 2); + r += 5; + } + } + } +} + +static void s_mlkem_polyvec_decompress(mlkem_polyvec *r, const unsigned char *a, const mlkem_params *p) +{ + unsigned int i, j, k; + + if (p->du == 11) { + ushort16 t[8]; + for (i = 0; i < (unsigned)p->k; i++) { + for (j = 0; j < MLKEM_N / 8; j++) { + t[0] = (a[0] >> 0) | ((ushort16)a[ 1] << 8); + t[1] = (a[1] >> 3) | ((ushort16)a[ 2] << 5); + t[2] = (a[2] >> 6) | ((ushort16)a[ 3] << 2) | ((ushort16)a[4] << 10); + t[3] = (a[4] >> 1) | ((ushort16)a[ 5] << 7); + t[4] = (a[5] >> 4) | ((ushort16)a[ 6] << 4); + t[5] = (a[6] >> 7) | ((ushort16)a[ 7] << 1) | ((ushort16)a[8] << 9); + t[6] = (a[8] >> 2) | ((ushort16)a[ 9] << 6); + t[7] = (a[9] >> 5) | ((ushort16)a[10] << 3); + a += 11; + + for (k = 0; k < 8; k++) + r->vec[i].coeffs[8 * j + k] = ((ulong32)(t[k] & 0x7FF) * MLKEM_Q + 1024) >> 11; + } + } + } else { /* du == 10 */ + ushort16 t[4]; + for (i = 0; i < (unsigned)p->k; i++) { + for (j = 0; j < MLKEM_N / 4; j++) { + t[0] = (a[0] >> 0) | ((ushort16)a[1] << 8); + t[1] = (a[1] >> 2) | ((ushort16)a[2] << 6); + t[2] = (a[2] >> 4) | ((ushort16)a[3] << 4); + t[3] = (a[3] >> 6) | ((ushort16)a[4] << 2); + a += 5; + + for (k = 0; k < 4; k++) + r->vec[i].coeffs[4 * j + k] = ((ulong32)(t[k] & 0x3FF) * MLKEM_Q + 512) >> 10; + } + } + } +} + +static void s_mlkem_polyvec_tobytes(unsigned char *r, const mlkem_polyvec *a, int k) +{ + int i; + for (i = 0; i < k; i++) + s_mlkem_poly_tobytes(r + i * MLKEM_POLYBYTES, &a->vec[i]); +} + +static void s_mlkem_polyvec_frombytes(mlkem_polyvec *r, const unsigned char *a, int k) +{ + int i; + for (i = 0; i < k; i++) + s_mlkem_poly_frombytes(&r->vec[i], a + i * MLKEM_POLYBYTES); +} + +static void s_mlkem_polyvec_ntt(mlkem_polyvec *r, int k) +{ + int i; + for (i = 0; i < k; i++) + s_mlkem_poly_ntt(&r->vec[i]); +} + +static void s_mlkem_polyvec_invntt_tomont(mlkem_polyvec *r, int k) +{ + int i; + for (i = 0; i < k; i++) + s_mlkem_poly_invntt_tomont(&r->vec[i]); +} + +static void s_mlkem_polyvec_basemul_acc_montgomery(mlkem_poly *r, const mlkem_polyvec *a, + const mlkem_polyvec *b, int k) +{ + int i; + mlkem_poly t; + + s_mlkem_poly_basemul_montgomery(r, &a->vec[0], &b->vec[0]); + for (i = 1; i < k; i++) { + s_mlkem_poly_basemul_montgomery(&t, &a->vec[i], &b->vec[i]); + s_mlkem_poly_add(r, r, &t); + } + + s_mlkem_poly_reduce(r); +} + +static void s_mlkem_polyvec_reduce(mlkem_polyvec *r, int k) +{ + int i; + for (i = 0; i < k; i++) + s_mlkem_poly_reduce(&r->vec[i]); +} + +static void s_mlkem_polyvec_add(mlkem_polyvec *r, const mlkem_polyvec *a, + const mlkem_polyvec *b, int k) +{ + int i; + for (i = 0; i < k; i++) + s_mlkem_poly_add(&r->vec[i], &a->vec[i], &b->vec[i]); +} + +/* IND-CPA: rejection sampling and matrix generation */ + +static unsigned int s_mlkem_rej_uniform(ishort16 *r, unsigned int len, + const unsigned char *buf, unsigned int buflen) +{ + unsigned int ctr, pos; + ushort16 val0, val1; + + ctr = pos = 0; + while (ctr < len && pos + 3 <= buflen) { + val0 = ((buf[pos + 0] >> 0) | ((ushort16)buf[pos + 1] << 8)) & 0xFFF; + val1 = ((buf[pos + 1] >> 4) | ((ushort16)buf[pos + 2] << 4)) & 0xFFF; + pos += 3; + + if (val0 < MLKEM_Q) + r[ctr++] = val0; + if (ctr < len && val1 < MLKEM_Q) + r[ctr++] = val1; + } + + return ctr; +} + +#define GEN_MATRIX_NBLOCKS ((12*MLKEM_N/8*(1 << 12)/MLKEM_Q + MLKEM_XOF_BLOCKBYTES)/MLKEM_XOF_BLOCKBYTES) + +static int s_mlkem_gen_matrix(mlkem_polyvec *a, const unsigned char seed[MLKEM_SYMBYTES], + int transposed, int k) +{ + unsigned int ctr, i, j, buflen; + unsigned char buf[GEN_MATRIX_NBLOCKS * MLKEM_XOF_BLOCKBYTES + MLKEM_XOF_BLOCKBYTES]; + hash_state state; + int err; + + for (i = 0; i < (unsigned)k; i++) { + for (j = 0; j < (unsigned)k; j++) { + if (transposed) + err = s_mlkem_xof_absorb(&state, seed, (unsigned char)i, (unsigned char)j); + else + err = s_mlkem_xof_absorb(&state, seed, (unsigned char)j, (unsigned char)i); + if (err != CRYPT_OK) return err; + + buflen = GEN_MATRIX_NBLOCKS * MLKEM_XOF_BLOCKBYTES; + if ((err = s_mlkem_xof_squeeze(&state, buf, buflen)) != CRYPT_OK) return err; + ctr = s_mlkem_rej_uniform(a[i].vec[j].coeffs, MLKEM_N, buf, buflen); + + while (ctr < MLKEM_N) { + if ((err = s_mlkem_xof_squeeze(&state, buf, MLKEM_XOF_BLOCKBYTES)) != CRYPT_OK) return err; + ctr += s_mlkem_rej_uniform(a[i].vec[j].coeffs + ctr, MLKEM_N - ctr, + buf, MLKEM_XOF_BLOCKBYTES); + } + } + } + + return CRYPT_OK; +} + +/* IND-CPA scheme */ + +static int s_mlkem_indcpa_keypair(unsigned char *pk, unsigned char *sk, + const unsigned char coins[MLKEM_SYMBYTES], + const mlkem_params *p) +{ + unsigned int i; + unsigned char buf[2 * MLKEM_SYMBYTES]; + const unsigned char *publicseed = buf; + const unsigned char *noiseseed = buf + MLKEM_SYMBYTES; + unsigned char nonce = 0; + mlkem_polyvec a[MLKEM_K_MAX], e, pkpv, skpv; + int err; + + XMEMCPY(buf, coins, MLKEM_SYMBYTES); + buf[MLKEM_SYMBYTES] = (unsigned char)p->k; + if ((err = s_mlkem_hash_g(buf, buf, MLKEM_SYMBYTES + 1)) != CRYPT_OK) return err; + + if ((err = s_mlkem_gen_matrix(a, publicseed, 0, p->k)) != CRYPT_OK) return err; + + for (i = 0; i < (unsigned)p->k; i++) + s_mlkem_poly_getnoise(&skpv.vec[i], noiseseed, nonce++, p->eta1); + for (i = 0; i < (unsigned)p->k; i++) + s_mlkem_poly_getnoise(&e.vec[i], noiseseed, nonce++, p->eta1); + + s_mlkem_polyvec_ntt(&skpv, p->k); + s_mlkem_polyvec_ntt(&e, p->k); + + for (i = 0; i < (unsigned)p->k; i++) { + s_mlkem_polyvec_basemul_acc_montgomery(&pkpv.vec[i], &a[i], &skpv, p->k); + s_mlkem_poly_tomont(&pkpv.vec[i]); + } + + s_mlkem_polyvec_add(&pkpv, &pkpv, &e, p->k); + s_mlkem_polyvec_reduce(&pkpv, p->k); + + s_mlkem_polyvec_tobytes(sk, &skpv, p->k); + s_mlkem_polyvec_tobytes(pk, &pkpv, p->k); + XMEMCPY(pk + p->polyvec_bytes, publicseed, MLKEM_SYMBYTES); + + return CRYPT_OK; +} + +static int s_mlkem_indcpa_enc(unsigned char *c, + const unsigned char m[MLKEM_SYMBYTES], + const unsigned char *pk, + const unsigned char coins[MLKEM_SYMBYTES], + const mlkem_params *p) +{ + unsigned int i; + unsigned char seed[MLKEM_SYMBYTES]; + unsigned char nonce = 0; + mlkem_polyvec sp, pkpv, ep, at[MLKEM_K_MAX], b; + mlkem_poly v, k, epp; + int err; + + s_mlkem_polyvec_frombytes(&pkpv, pk, p->k); + XMEMCPY(seed, pk + p->polyvec_bytes, MLKEM_SYMBYTES); + s_mlkem_poly_frommsg(&k, m); + if ((err = s_mlkem_gen_matrix(at, seed, 1, p->k)) != CRYPT_OK) return err; + + for (i = 0; i < (unsigned)p->k; i++) + s_mlkem_poly_getnoise(&sp.vec[i], coins, nonce++, p->eta1); + for (i = 0; i < (unsigned)p->k; i++) + s_mlkem_poly_getnoise(&ep.vec[i], coins, nonce++, p->eta2); + s_mlkem_poly_getnoise(&epp, coins, nonce++, p->eta2); + + s_mlkem_polyvec_ntt(&sp, p->k); + + for (i = 0; i < (unsigned)p->k; i++) + s_mlkem_polyvec_basemul_acc_montgomery(&b.vec[i], &at[i], &sp, p->k); + + s_mlkem_polyvec_basemul_acc_montgomery(&v, &pkpv, &sp, p->k); + + s_mlkem_polyvec_invntt_tomont(&b, p->k); + s_mlkem_poly_invntt_tomont(&v); + + s_mlkem_polyvec_add(&b, &b, &ep, p->k); + s_mlkem_poly_add(&v, &v, &epp); + s_mlkem_poly_add(&v, &v, &k); + s_mlkem_polyvec_reduce(&b, p->k); + s_mlkem_poly_reduce(&v); + + s_mlkem_polyvec_compress(c, &b, p); + s_mlkem_poly_compress(c + p->polyvec_compressed_bytes, &v, p->dv); + + return CRYPT_OK; +} + +static void s_mlkem_indcpa_dec(unsigned char m[MLKEM_SYMBYTES], + const unsigned char *c, + const unsigned char *sk, + const mlkem_params *p) +{ + mlkem_polyvec b, skpv; + mlkem_poly v, mp; + + s_mlkem_polyvec_decompress(&b, c, p); + s_mlkem_poly_decompress(&v, c + p->polyvec_compressed_bytes, p->dv); + s_mlkem_polyvec_frombytes(&skpv, sk, p->k); + + s_mlkem_polyvec_ntt(&b, p->k); + s_mlkem_polyvec_basemul_acc_montgomery(&mp, &skpv, &b, p->k); + s_mlkem_poly_invntt_tomont(&mp); + + s_mlkem_poly_sub(&mp, &v, &mp); + s_mlkem_poly_reduce(&mp); + + s_mlkem_poly_tomsg(m, &mp); +} + +/* KEM operations */ + +static int s_mlkem_kem_keypair(unsigned char *pk, unsigned char *sk, + const unsigned char coins[2 * MLKEM_SYMBYTES], + const mlkem_params *p) +{ + int err; + + if ((err = s_mlkem_indcpa_keypair(pk, sk, coins, p)) != CRYPT_OK) return err; + XMEMCPY(sk + p->indcpa_sk_bytes, pk, p->pk_bytes); + if ((err = s_mlkem_hash_h(sk + p->sk_bytes - 2 * MLKEM_SYMBYTES, pk, p->pk_bytes)) != CRYPT_OK) + return err; + /* Value z for pseudo-random output on reject */ + XMEMCPY(sk + p->sk_bytes - MLKEM_SYMBYTES, coins + MLKEM_SYMBYTES, MLKEM_SYMBYTES); + + return CRYPT_OK; +} + +static int s_mlkem_validate_private_key(const unsigned char *sk, + const mlkem_params *p) +{ + unsigned char h[MLKEM_SYMBYTES]; + int err; + + if ((err = s_mlkem_hash_h(h, sk + p->indcpa_sk_bytes, p->pk_bytes)) != CRYPT_OK) { + return err; + } + + return XMEMCMP(h, sk + p->sk_bytes - 2 * MLKEM_SYMBYTES, MLKEM_SYMBYTES) == 0 + ? CRYPT_OK + : CRYPT_INVALID_PACKET; +} + +static int s_mlkem_kem_enc(unsigned char *ct, unsigned char *ss, + const unsigned char *pk, + const unsigned char coins[MLKEM_SYMBYTES], + const mlkem_params *p) +{ + unsigned char buf[2 * MLKEM_SYMBYTES]; + unsigned char kr[2 * MLKEM_SYMBYTES]; + int err; + + XMEMCPY(buf, coins, MLKEM_SYMBYTES); + + /* Multitarget countermeasure for coins + contributory KEM */ + if ((err = s_mlkem_hash_h(buf + MLKEM_SYMBYTES, pk, p->pk_bytes)) != CRYPT_OK) return err; + if ((err = s_mlkem_hash_g(kr, buf, 2 * MLKEM_SYMBYTES)) != CRYPT_OK) return err; + + /* coins are in kr+MLKEM_SYMBYTES */ + if ((err = s_mlkem_indcpa_enc(ct, buf, pk, kr + MLKEM_SYMBYTES, p)) != CRYPT_OK) return err; + + XMEMCPY(ss, kr, MLKEM_SYMBYTES); + return CRYPT_OK; +} + +static int s_mlkem_kem_dec(unsigned char *ss, + const unsigned char *ct, + const unsigned char *sk, + const mlkem_params *p) +{ + int fail, err; + unsigned char buf[2 * MLKEM_SYMBYTES]; + unsigned char kr[2 * MLKEM_SYMBYTES]; + unsigned char cmp[MLKEM_K_MAX * 352 + 160]; /* max ct size */ + const unsigned char *pk = sk + p->indcpa_sk_bytes; + + s_mlkem_indcpa_dec(buf, ct, sk, p); + + /* Multitarget countermeasure for coins + contributory KEM */ + XMEMCPY(buf + MLKEM_SYMBYTES, sk + p->sk_bytes - 2 * MLKEM_SYMBYTES, MLKEM_SYMBYTES); + if ((err = s_mlkem_hash_g(kr, buf, 2 * MLKEM_SYMBYTES)) != CRYPT_OK) return err; + + /* coins are in kr+MLKEM_SYMBYTES */ + if ((err = s_mlkem_indcpa_enc(cmp, buf, pk, kr + MLKEM_SYMBYTES, p)) != CRYPT_OK) return err; + + fail = s_mlkem_ct_verify(ct, cmp, p->ct_bytes); + + /* Compute rejection key */ + if ((err = s_mlkem_rkprf(ss, sk + p->sk_bytes - MLKEM_SYMBYTES, ct, p->ct_bytes)) != CRYPT_OK) + return err; + + /* Copy true key to return buffer if fail is false */ + s_mlkem_cmov(ss, kr, MLKEM_SYMBYTES, (unsigned char)!fail); + + return CRYPT_OK; +} + +/* Public API */ + +/** + Generate an ML-KEM key pair. + @param prng An active PRNG state + @param wprng The index of the desired PRNG + @param alg The parameter set (LTC_MLKEM_512, LTC_MLKEM_768, or LTC_MLKEM_1024) + @param key [out] Destination for the newly created key pair + @return CRYPT_OK if successful +*/ +int mlkem_make_key(prng_state *prng, int wprng, int alg, mlkem_key *key) +{ + unsigned char coins[2 * MLKEM_SYMBYTES]; + int err; + + LTC_ARGCHK(key != NULL); + + if ((err = prng_is_valid(wprng)) != CRYPT_OK) return err; + if (prng_descriptor[wprng].read(coins, sizeof(coins), prng) != sizeof(coins)) + return CRYPT_ERROR_READPRNG; + + err = mlkem_make_key_from_seed(alg, coins, sizeof(coins), key); + zeromem(coins, sizeof(coins)); + return err; +} + +/** + Generate an ML-KEM key pair deterministically from a seed. + @param alg The parameter set (LTC_MLKEM_512, LTC_MLKEM_768, or LTC_MLKEM_1024) + @param seed The input seed (exactly 64 bytes) + @param seedlen Length of the seed in bytes + @param key [out] Destination for the newly created key pair + @return CRYPT_OK if successful +*/ +int mlkem_make_key_from_seed(int alg, const unsigned char *seed, unsigned long seedlen, mlkem_key *key) +{ + mlkem_params p; + int err; + + LTC_ARGCHK(seed != NULL); + LTC_ARGCHK(key != NULL); + + if (seedlen != 2uL * MLKEM_SYMBYTES) { + return CRYPT_INVALID_ARG; + } + if ((err = s_mlkem_get_params(alg, &p)) != CRYPT_OK) { + return err; + } + + XMEMSET(key, 0, sizeof(*key)); + key->pk = XMALLOC(p.pk_bytes); + key->sk = XMALLOC(p.sk_bytes); + if (key->pk == NULL || key->sk == NULL) { + mlkem_free(key); + return CRYPT_MEM; + } + + if ((err = s_mlkem_kem_keypair(key->pk, key->sk, seed, &p)) != CRYPT_OK) { + zeromem(key->sk, p.sk_bytes); + mlkem_free(key); + return err; + } + + key->alg = alg; + key->type = PK_PRIVATE; + key->pklen = p.pk_bytes; + key->sklen = p.sk_bytes; + err = s_mlkem_validate_private_key(key->sk, &p); + if (err != CRYPT_OK) { + mlkem_free(key); + } + return err; +} + +/** + Free an ML-KEM key from memory. + @param key The key to free +*/ +void mlkem_free(mlkem_key *key) +{ + if (key == NULL) return; + if (key->sk != NULL) { + zeromem(key->sk, key->sklen); + XFREE(key->sk); + } + if (key->pk != NULL) { + XFREE(key->pk); + } + XMEMSET(key, 0, sizeof(*key)); +} + +/** + Export an ML-KEM key to a byte buffer. + @param out [out] Destination for the exported key + @param outlen [in/out] Max size and resulting size of the exported key + @param which PK_PUBLIC for the encapsulation key, PK_PRIVATE for the decapsulation key + @param key The key to export + @return CRYPT_OK if successful +*/ +int mlkem_export_raw(unsigned char *out, unsigned long *outlen, int which, const mlkem_key *key) +{ + mlkem_params p; + unsigned long needed; + int err; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = s_mlkem_get_params(key->alg, &p)) != CRYPT_OK) return err; + + if (which == PK_PUBLIC) { + needed = p.pk_bytes; + if (*outlen < needed) { *outlen = needed; return CRYPT_BUFFER_OVERFLOW; } + if (key->pk == NULL) return CRYPT_PK_NOT_PRIVATE; + XMEMCPY(out, key->pk, needed); + } else if (which == PK_PRIVATE) { + if (key->type != PK_PRIVATE) return CRYPT_PK_NOT_PRIVATE; + needed = p.sk_bytes; + if (*outlen < needed) { *outlen = needed; return CRYPT_BUFFER_OVERFLOW; } + XMEMCPY(out, key->sk, needed); + } else { + return CRYPT_INVALID_ARG; + } + + *outlen = needed; + return CRYPT_OK; +} + +/** + Import an ML-KEM key from a byte buffer. + @param in The buffer to import from + @param inlen Length of the buffer + @param which PK_PUBLIC for an encapsulation key, PK_PRIVATE for a decapsulation key + @param alg The parameter set (LTC_MLKEM_512, LTC_MLKEM_768, or LTC_MLKEM_1024) + @param key [out] Destination for the imported key + @return CRYPT_OK if successful +*/ +int mlkem_import_raw(const unsigned char *in, unsigned long inlen, int which, int alg, mlkem_key *key) +{ + mlkem_params p; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = s_mlkem_get_params(alg, &p)) != CRYPT_OK) return err; + + XMEMSET(key, 0, sizeof(*key)); + key->alg = alg; + + if (which == PK_PUBLIC) { + if (inlen != p.pk_bytes) return CRYPT_INVALID_PACKET; + key->pk = XMALLOC(p.pk_bytes); + if (key->pk == NULL) return CRYPT_MEM; + XMEMCPY(key->pk, in, p.pk_bytes); + key->pklen = p.pk_bytes; + key->type = PK_PUBLIC; + } else if (which == PK_PRIVATE) { + if (inlen != p.sk_bytes) return CRYPT_INVALID_PACKET; + key->sk = XMALLOC(p.sk_bytes); + /* Extract pk from sk (it's embedded at offset indcpa_sk_bytes) */ + key->pk = XMALLOC(p.pk_bytes); + if (key->sk == NULL || key->pk == NULL) { + mlkem_free(key); + return CRYPT_MEM; + } + XMEMCPY(key->sk, in, p.sk_bytes); + XMEMCPY(key->pk, in + p.indcpa_sk_bytes, p.pk_bytes); + key->sklen = p.sk_bytes; + key->pklen = p.pk_bytes; + key->type = PK_PRIVATE; + if ((err = s_mlkem_validate_private_key(key->sk, &p)) != CRYPT_OK) { + mlkem_free(key); + return err; + } + } else { + return CRYPT_INVALID_ARG; + } + + return CRYPT_OK; +} + +/** + ML-KEM encapsulation: generate a shared secret and ciphertext from a public key. + @param ct [out] The ciphertext + @param ctlen [in/out] Max size and resulting size of the ciphertext + @param shared_secret [out] The shared secret (32 bytes) + @param sslen [in/out] Max size and resulting size of the shared secret + @param prng An active PRNG state + @param wprng The index of the desired PRNG + @param key The public (encapsulation) key + @return CRYPT_OK if successful +*/ +int mlkem_encaps(unsigned char *ct, unsigned long *ctlen, + unsigned char *shared_secret, unsigned long *sslen, + prng_state *prng, int wprng, + const mlkem_key *key) +{ + mlkem_params p; + unsigned char coins[MLKEM_SYMBYTES]; + int err; + + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(ctlen != NULL); + LTC_ARGCHK(shared_secret != NULL); + LTC_ARGCHK(sslen != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(key->pk != NULL); + + if ((err = s_mlkem_get_params(key->alg, &p)) != CRYPT_OK) return err; + if (*ctlen < p.ct_bytes) { *ctlen = p.ct_bytes; return CRYPT_BUFFER_OVERFLOW; } + if (*sslen < MLKEM_SSBYTES) { *sslen = MLKEM_SSBYTES; return CRYPT_BUFFER_OVERFLOW; } + if ((err = prng_is_valid(wprng)) != CRYPT_OK) return err; + if (prng_descriptor[wprng].read(coins, sizeof(coins), prng) != sizeof(coins)) + return CRYPT_ERROR_READPRNG; + + err = s_mlkem_kem_enc(ct, shared_secret, key->pk, coins, &p); + + *ctlen = p.ct_bytes; + *sslen = MLKEM_SSBYTES; + + zeromem(coins, sizeof(coins)); + return err; +} + +/** + ML-KEM decapsulation: recover a shared secret from a ciphertext using a private key. + @param shared_secret [out] The shared secret (32 bytes) + @param sslen [in/out] Max size and resulting size of the shared secret + @param ct The ciphertext + @param ctlen Length of the ciphertext + @param key The private (decapsulation) key + @return CRYPT_OK if successful + + @note On implicit rejection (invalid ciphertext), a pseudorandom value is + returned instead of an error, as required by the ML-KEM specification. +*/ +int mlkem_decaps(unsigned char *shared_secret, unsigned long *sslen, + const unsigned char *ct, unsigned long ctlen, + const mlkem_key *key) +{ + mlkem_params p; + int err; + + LTC_ARGCHK(shared_secret != NULL); + LTC_ARGCHK(sslen != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(key != NULL); + + if (key->type != PK_PRIVATE) return CRYPT_PK_NOT_PRIVATE; + if ((err = s_mlkem_get_params(key->alg, &p)) != CRYPT_OK) return err; + if (ctlen != p.ct_bytes) return CRYPT_INVALID_PACKET; + if (*sslen < MLKEM_SSBYTES) { *sslen = MLKEM_SSBYTES; return CRYPT_BUFFER_OVERFLOW; } + + err = s_mlkem_kem_dec(shared_secret, ct, key->sk, &p); + *sslen = MLKEM_SSBYTES; + return err; +} + +/** + Get the sizes for a given ML-KEM parameter set. + Any output pointer may be NULL if the caller does not need that value. + @param alg The parameter set (LTC_MLKEM_512, LTC_MLKEM_768, or LTC_MLKEM_1024) + @param public_key_sz [out] Public key size in bytes + @param secret_key_sz [out] Secret key size in bytes + @param ciphertext_sz [out] Ciphertext size in bytes + @param shared_secret_sz [out] Shared secret size in bytes (always 32) + @return CRYPT_OK if successful +*/ +int mlkem_get_sizes(int alg, unsigned long *public_key_sz, unsigned long *secret_key_sz, + unsigned long *ciphertext_sz, unsigned long *shared_secret_sz) +{ + mlkem_params p; + int err; + + if ((err = s_mlkem_get_params(alg, &p)) != CRYPT_OK) return err; + + if (public_key_sz != NULL) *public_key_sz = p.pk_bytes; + if (secret_key_sz != NULL) *secret_key_sz = p.sk_bytes; + if (ciphertext_sz != NULL) *ciphertext_sz = p.ct_bytes; + if (shared_secret_sz != NULL) *shared_secret_sz = MLKEM_SSBYTES; + + return CRYPT_OK; +} + +#endif /* LTC_MLKEM */ diff --git a/src/pqc/mlkem_export.c b/src/pqc/mlkem_export.c new file mode 100644 index 000000000..cd6246c72 --- /dev/null +++ b/src/pqc/mlkem_export.c @@ -0,0 +1,114 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file mlkem_export.c + Export an ML-KEM key to a binary packet +*/ + +#ifdef LTC_MLKEM + +static int s_mlkem_alg_to_oid(int alg, enum ltc_oid_id *oid_id) +{ + LTC_ARGCHK(oid_id != NULL); + + switch (alg) { + case LTC_MLKEM_512: + *oid_id = LTC_OID_MLKEM_512; + return CRYPT_OK; + case LTC_MLKEM_768: + *oid_id = LTC_OID_MLKEM_768; + return CRYPT_OK; + case LTC_MLKEM_1024: + *oid_id = LTC_OID_MLKEM_1024; + return CRYPT_OK; + default: + return CRYPT_PK_INVALID_TYPE; + } +} + +/** + Export an ML-KEM key to a binary packet + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the ML-KEM key + @param which Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int mlkem_export(unsigned char *out, unsigned long *outlen, + int which, const mlkem_key *key) +{ + int err, std; + enum ltc_oid_id oid_id; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + std = which & PK_STD; + which &= ~PK_STD; + + if ((err = s_mlkem_alg_to_oid(key->alg, &oid_id)) != CRYPT_OK) { + return err; + } + + if (which == PK_PRIVATE) { + const char *OID; + unsigned long version, oid[16], oidlen; + unsigned char *private_key; + unsigned long private_key_len; + ltc_asn1_list alg_id[1]; + + if (key->type != PK_PRIVATE || key->sk == NULL) return CRYPT_PK_INVALID_TYPE; + + if (std != PK_STD) { + return mlkem_export_raw(out, outlen, which, key); + } + + if ((err = pk_get_oid(oid_id, &OID)) != CRYPT_OK) { + return err; + } + oidlen = LTC_ARRAY_SIZE(oid); + if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { + return err; + } + LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); + + if ((err = der_length_octet_string(key->sklen, &private_key_len)) != CRYPT_OK) { + return err; + } + private_key = XMALLOC(private_key_len); + if (private_key == NULL) { + return CRYPT_MEM; + } + + err = der_encode_octet_string(key->sk, key->sklen, private_key, &private_key_len); + if (err == CRYPT_OK) { + version = 0; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1uL, &version, + LTC_ASN1_SEQUENCE, 1uL, alg_id, + LTC_ASN1_OCTET_STRING, private_key_len, private_key, + LTC_ASN1_EOL, 0uL, NULL); + } + + XFREE(private_key); + return err; + } + + if (which != PK_PUBLIC) { + return CRYPT_INVALID_ARG; + } + if (key->pk == NULL) return CRYPT_PK_INVALID_TYPE; + + if (std == PK_STD) { + return x509_encode_subject_public_key_info(out, outlen, oid_id, + key->pk, key->pklen, + LTC_ASN1_EOL, NULL, 0uL); + } + + return mlkem_export_raw(out, outlen, which, key); +} + +#endif diff --git a/src/pqc/mlkem_import.c b/src/pqc/mlkem_import.c new file mode 100644 index 000000000..65815e841 --- /dev/null +++ b/src/pqc/mlkem_import.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file mlkem_import.c + Import a ML-KEM key from a SubjectPublicKeyInfo +*/ + +#ifdef LTC_MLKEM + +typedef struct { + enum ltc_oid_id oid; + int alg; +} mlkem_oid_map; + +static const mlkem_oid_map s_mlkem_oid_map[] = { + { LTC_OID_MLKEM_512, LTC_MLKEM_512 }, + { LTC_OID_MLKEM_768, LTC_MLKEM_768 }, + { LTC_OID_MLKEM_1024, LTC_MLKEM_1024 }, +}; + +/** + Import a ML-KEM public key + @param in The packet to read + @param inlen The length of the input packet + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int mlkem_import(const unsigned char *in, unsigned long inlen, mlkem_key *key) +{ + unsigned char *pub; + unsigned long pub_len, max_pub_len; + unsigned long i; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = mlkem_get_sizes(LTC_MLKEM_1024, &max_pub_len, NULL, NULL, NULL)) != CRYPT_OK) { + return err; + } + + pub = XMALLOC(max_pub_len); + if (pub == NULL) { + return CRYPT_MEM; + } + + err = CRYPT_PK_INVALID_TYPE; + for (i = 0; i < LTC_ARRAY_SIZE(s_mlkem_oid_map); ++i) { + pub_len = max_pub_len; + err = x509_decode_subject_public_key_info(in, inlen, s_mlkem_oid_map[i].oid, + pub, &pub_len, + LTC_ASN1_EOL, NULL, 0uL); + if (err == CRYPT_OK) { + err = mlkem_import_raw(pub, pub_len, PK_PUBLIC, s_mlkem_oid_map[i].alg, key); + break; + } + } + + XFREE(pub); + return err; +} + +#endif diff --git a/src/pqc/mlkem_import_pkcs8.c b/src/pqc/mlkem_import_pkcs8.c new file mode 100644 index 000000000..e8af9ac16 --- /dev/null +++ b/src/pqc/mlkem_import_pkcs8.c @@ -0,0 +1,158 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file mlkem_import_pkcs8.c + Import a ML-KEM key in PKCS#8 format +*/ + +#ifdef LTC_MLKEM + +static int s_mlkem_oid_to_alg(enum ltc_oid_id oid_id, int *alg) +{ + LTC_ARGCHK(alg != NULL); + + switch (oid_id) { + case LTC_OID_MLKEM_512: + *alg = LTC_MLKEM_512; + return CRYPT_OK; + case LTC_OID_MLKEM_768: + *alg = LTC_MLKEM_768; + return CRYPT_OK; + case LTC_OID_MLKEM_1024: + *alg = LTC_MLKEM_1024; + return CRYPT_OK; + default: + return CRYPT_PK_INVALID_TYPE; + } +} + +int mlkem_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, + mlkem_key *key) +{ + ltc_asn1_list *decoded = NULL; + ltc_asn1_list *seed = NULL, *raw_key = NULL; + ltc_asn1_list seed_custom[1]; + der_flexi_check flexi_should[4]; + enum ltc_oid_id oid_id; + int alg, err; + unsigned char *raw_buf = NULL; + unsigned char seed_buf[64]; + unsigned long inlen, raw_buf_len, key_len, n; + mlkem_key seed_key; + + LTC_ARGCHK(alg_id != NULL); + LTC_ARGCHK(priv_key != NULL); + LTC_ARGCHK(key != NULL); + XMEMSET(&seed_key, 0, sizeof(seed_key)); + + if ((err = pk_get_oid_from_asn1(alg_id->child, &oid_id)) != CRYPT_OK) { + return err; + } + if ((err = s_mlkem_oid_to_alg(oid_id, &alg)) != CRYPT_OK) { + return err; + } + + if ((err = mlkem_get_sizes(alg, NULL, &key_len, NULL, NULL)) != CRYPT_OK) { + return err; + } + if (priv_key->size == key_len) { + return mlkem_import_raw(priv_key->data, priv_key->size, PK_PRIVATE, alg, key); + } + + raw_buf = XMALLOC(key_len); + if (raw_buf == NULL) { + return CRYPT_MEM; + } + raw_buf_len = key_len; + err = der_decode_octet_string(priv_key->data, priv_key->size, raw_buf, &raw_buf_len); + if (err == CRYPT_OK) { + err = (raw_buf_len == key_len) + ? mlkem_import_raw(raw_buf, raw_buf_len, PK_PRIVATE, alg, key) + : CRYPT_INVALID_PACKET; + XFREE(raw_buf); + return err; + } + XFREE(raw_buf); + + LTC_SET_ASN1_CUSTOM_PRIMITIVE(seed_custom, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, + LTC_ASN1_OCTET_STRING, seed_buf, sizeof(seed_buf)); + err = der_decode_custom_type(priv_key->data, priv_key->size, seed_custom); + if (err == CRYPT_OK) { + return mlkem_make_key_from_seed(alg, seed_buf, seed_custom[0].size, key); + } + + inlen = priv_key->size; + err = der_decode_sequence_flexi(priv_key->data, &inlen, &decoded); + if (err != CRYPT_OK) { + return err; + } + + n = 0; + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, &seed); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, &raw_key); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); + err = der_flexi_sequence_cmp(decoded, flexi_should); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { + goto cleanup; + } + + if (seed == NULL || raw_key == NULL) { + err = CRYPT_INVALID_PACKET; + goto cleanup; + } + if ((err = mlkem_make_key_from_seed(alg, seed->data, seed->size, &seed_key)) != CRYPT_OK) { + goto cleanup; + } + if (seed_key.sklen != raw_key->size || + XMEMCMP(seed_key.sk, raw_key->data, raw_key->size) != 0) { + err = CRYPT_INVALID_PACKET; + goto cleanup; + } + + err = mlkem_import_raw(raw_key->data, raw_key->size, PK_PRIVATE, alg, key); + +cleanup: + mlkem_free(&seed_key); + der_free_sequence_flexi(decoded); + return err; +} + +/** + Import a ML-KEM private key in PKCS#8 format + @param in The packet to import from + @param inlen It's length (octets) + @param pw_ctx The password context when decrypting the private key + @param key [out] Destination for newly imported key + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int mlkem_import_pkcs8(const unsigned char *in, unsigned long inlen, const password_ctx *pw_ctx, mlkem_key *key) +{ + int alg, err; + ltc_asn1_list *l = NULL; + ltc_asn1_list *alg_id, *priv_key; + enum ltc_oid_id oid_id; + + LTC_ARGCHK(in != NULL); + + err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l); + if (err != CRYPT_OK) { + return err; + } + + if ((err = pkcs8_get_children(l, &oid_id, &alg_id, &priv_key)) != CRYPT_OK) { + goto cleanup; + } + if ((err = s_mlkem_oid_to_alg(oid_id, &alg)) != CRYPT_OK) { + goto cleanup; + } + LTC_UNUSED_PARAM(alg); + err = mlkem_import_pkcs8_asn1(alg_id, priv_key, key); + +cleanup: + der_free_sequence_flexi(l); + return err; +} + +#endif diff --git a/src/pqc/mlkem_import_x509.c b/src/pqc/mlkem_import_x509.c new file mode 100644 index 000000000..e57aa6704 --- /dev/null +++ b/src/pqc/mlkem_import_x509.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file mlkem_import_x509.c + Import a ML-KEM key from a X.509 certificate +*/ + +#ifdef LTC_MLKEM + +typedef struct { + mlkem_key *key; + int alg; +} mlkem_x509_ctx; + +typedef struct { + enum ltc_oid_id oid; + int alg; +} mlkem_oid_map_x509; + +static const mlkem_oid_map_x509 s_mlkem_oid_map_x509[] = { + { LTC_OID_MLKEM_512, LTC_MLKEM_512 }, + { LTC_OID_MLKEM_768, LTC_MLKEM_768 }, + { LTC_OID_MLKEM_1024, LTC_MLKEM_1024 }, +}; + +static int s_mlkem_decode(const unsigned char *in, unsigned long inlen, mlkem_x509_ctx *ctx) +{ + return mlkem_import_raw(in, inlen, PK_PUBLIC, ctx->alg, ctx->key); +} + +/** + Import a ML-KEM public key from a X.509 certificate + @param in The DER encoded X.509 certificate + @param inlen The length of the certificate + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int mlkem_import_x509(const unsigned char *in, unsigned long inlen, mlkem_key *key) +{ + mlkem_x509_ctx ctx; + unsigned long i; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + err = CRYPT_PK_INVALID_TYPE; + for (i = 0; i < LTC_ARRAY_SIZE(s_mlkem_oid_map_x509); ++i) { + ctx.key = key; + ctx.alg = s_mlkem_oid_map_x509[i].alg; + err = x509_decode_public_key_from_certificate(in, inlen, + s_mlkem_oid_map_x509[i].oid, + LTC_ASN1_EOL, NULL, NULL, + (public_key_decode_cb)s_mlkem_decode, &ctx); + if (err == CRYPT_OK) { + break; + } + } + + return err; +} + +#endif diff --git a/src/pqc/slhdsa.c b/src/pqc/slhdsa.c new file mode 100644 index 000000000..6a06b6cf3 --- /dev/null +++ b/src/pqc/slhdsa.c @@ -0,0 +1,1906 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file slhdsa.c + SLH-DSA (FIPS 205) implementation: WOTS+, FORS, Merkle trees, signing, + and verification (SHAKE-simple and SHA2-simple variants). + Based on the SPHINCS+ reference implementation (public domain). +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_SLHDSA + +/* Constants */ + +#define SPX_N_MAX 32 +#define SPX_ADDR_BYTES 32 /* max address bytes (SHAKE uses 32, SHA-2 uses 22) */ +#define SPX_WOTS_W 16 +#define SPX_WOTS_LOGW 4 +#define SPX_FULL_HEIGHT_MAX 68 +#define SPX_D_MAX 22 +#define SPX_TREE_HEIGHT_MAX 10 /* max(full_height/d) across all param sets */ +#define SPX_FORS_HEIGHT_MAX 14 +#define SPX_FORS_TREES_MAX 35 +#define SPX_WOTS_LEN_MAX 67 /* max len1(64) + len2(3) = 67 for n=32 */ +#define SPX_WOTS_BYTES_MAX (SPX_WOTS_LEN_MAX * SPX_N_MAX) /* 67*32 = 2144 */ + +/* Address types */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +/* Runtime parameter set */ + +typedef struct { + unsigned int n; + unsigned int full_height; + unsigned int d; + unsigned int fors_height; + unsigned int fors_trees; + unsigned int wots_w; + unsigned int wots_logw; + unsigned int wots_len1; + unsigned int wots_len2; + unsigned int wots_len; + unsigned int wots_bytes; + unsigned int tree_height; + unsigned int fors_msg_bytes; + unsigned int fors_bytes; + unsigned long pk_bytes; + unsigned long sk_bytes; + unsigned long sig_bytes; + int is_shake; + /* Address layout */ + unsigned int addr_bytes; + unsigned int off_layer; + unsigned int off_tree; + unsigned int off_type; + unsigned int off_kp_addr; + unsigned int off_chain_addr; + unsigned int off_hash_addr; + unsigned int off_tree_hgt; + unsigned int off_tree_index; + /* Number of bytes for keypair addr field */ + unsigned int kp_addr_len; +} slhdsa_params; + +static int s_slhdsa_is_hash_alg(int alg) +{ + return alg >= LTC_SLHDSA_HASH_SHA2_128S_WITH_SHA256 + && alg <= LTC_SLHDSA_HASH_SHAKE_256F_WITH_SHAKE256; +} + +static int s_slhdsa_hash_mode(int alg) +{ + switch (alg) { + case LTC_SLHDSA_HASH_SHA2_128S_WITH_SHA256: + case LTC_SLHDSA_HASH_SHA2_128F_WITH_SHA256: + return 1; + case LTC_SLHDSA_HASH_SHA2_192S_WITH_SHA512: + case LTC_SLHDSA_HASH_SHA2_192F_WITH_SHA512: + case LTC_SLHDSA_HASH_SHA2_256S_WITH_SHA512: + case LTC_SLHDSA_HASH_SHA2_256F_WITH_SHA512: + return 2; + case LTC_SLHDSA_HASH_SHAKE_128S_WITH_SHAKE128: + case LTC_SLHDSA_HASH_SHAKE_128F_WITH_SHAKE128: + return 3; + case LTC_SLHDSA_HASH_SHAKE_192S_WITH_SHAKE256: + case LTC_SLHDSA_HASH_SHAKE_192F_WITH_SHAKE256: + case LTC_SLHDSA_HASH_SHAKE_256S_WITH_SHAKE256: + case LTC_SLHDSA_HASH_SHAKE_256F_WITH_SHAKE256: + return 4; + default: + return 0; + } +} + +static int s_slhdsa_base_alg(int alg) +{ + switch (alg) { + case LTC_SLHDSA_HASH_SHA2_128S_WITH_SHA256: + return LTC_SLHDSA_SHA2_128S; + case LTC_SLHDSA_HASH_SHA2_128F_WITH_SHA256: + return LTC_SLHDSA_SHA2_128F; + case LTC_SLHDSA_HASH_SHA2_192S_WITH_SHA512: + return LTC_SLHDSA_SHA2_192S; + case LTC_SLHDSA_HASH_SHA2_192F_WITH_SHA512: + return LTC_SLHDSA_SHA2_192F; + case LTC_SLHDSA_HASH_SHA2_256S_WITH_SHA512: + return LTC_SLHDSA_SHA2_256S; + case LTC_SLHDSA_HASH_SHA2_256F_WITH_SHA512: + return LTC_SLHDSA_SHA2_256F; + case LTC_SLHDSA_HASH_SHAKE_128S_WITH_SHAKE128: + return LTC_SLHDSA_SHAKE_128S; + case LTC_SLHDSA_HASH_SHAKE_128F_WITH_SHAKE128: + return LTC_SLHDSA_SHAKE_128F; + case LTC_SLHDSA_HASH_SHAKE_192S_WITH_SHAKE256: + return LTC_SLHDSA_SHAKE_192S; + case LTC_SLHDSA_HASH_SHAKE_192F_WITH_SHAKE256: + return LTC_SLHDSA_SHAKE_192F; + case LTC_SLHDSA_HASH_SHAKE_256S_WITH_SHAKE256: + return LTC_SLHDSA_SHAKE_256S; + case LTC_SLHDSA_HASH_SHAKE_256F_WITH_SHAKE256: + return LTC_SLHDSA_SHAKE_256F; + default: + return alg; + } +} + +static int s_slhdsa_hash_oid_der(int alg, const unsigned char **oid, unsigned long *oidlen) +{ + static const unsigned char sha256_oid[] = { 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 }; + static const unsigned char sha512_oid[] = { 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03 }; + static const unsigned char shake128_oid[] = { 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0B }; + static const unsigned char shake256_oid[] = { 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0C }; + + LTC_ARGCHK(oid != NULL); + LTC_ARGCHK(oidlen != NULL); + + switch (s_slhdsa_hash_mode(alg)) { + case 1: + *oid = sha256_oid; + *oidlen = sizeof(sha256_oid); + return CRYPT_OK; + case 2: + *oid = sha512_oid; + *oidlen = sizeof(sha512_oid); + return CRYPT_OK; + case 3: + *oid = shake128_oid; + *oidlen = sizeof(shake128_oid); + return CRYPT_OK; + case 4: + *oid = shake256_oid; + *oidlen = sizeof(shake256_oid); + return CRYPT_OK; + default: + return CRYPT_INVALID_ARG; + } +} + +static int s_slhdsa_hash_message_memory(int alg, + const unsigned char *msg, unsigned long msglen, + unsigned char *out, unsigned long *outlen) +{ + int hash_idx; + + LTC_ARGCHK(msg != NULL || msglen == 0); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + switch (s_slhdsa_hash_mode(alg)) { + case 1: + hash_idx = find_hash("sha256"); + if (hash_idx == -1) return CRYPT_INVALID_HASH; + return hash_memory(hash_idx, msg, msglen, out, outlen); + case 2: + hash_idx = find_hash("sha512"); + if (hash_idx == -1) return CRYPT_INVALID_HASH; + return hash_memory(hash_idx, msg, msglen, out, outlen); + case 3: + return sha3_shake_memory(128, msg, msglen, out, outlen); + case 4: + return sha3_shake_memory(256, msg, msglen, out, outlen); + default: + return CRYPT_INVALID_ARG; + } +} + +static int s_slhdsa_prepare_message(unsigned char **m_prime, + unsigned long *m_prime_len, + const unsigned char *msg, unsigned long msglen, + const unsigned char *ctx, unsigned long ctxlen, + int alg) +{ + unsigned long prelen, oidlen = 0, phm_len = 0; + const unsigned char *oid = NULL; + unsigned char phm[64]; + int err = CRYPT_OK; + + LTC_ARGCHK(m_prime != NULL); + LTC_ARGCHK(m_prime_len != NULL); + LTC_ARGCHK(msg != NULL || msglen == 0); + + if (ctxlen > 255) { + return CRYPT_INVALID_ARG; + } + + if (!s_slhdsa_is_hash_alg(alg)) { + prelen = 2 + ctxlen; + *m_prime_len = prelen + msglen; + *m_prime = XMALLOC(*m_prime_len > 0 ? *m_prime_len : 1); + if (*m_prime == NULL) return CRYPT_MEM; + + (*m_prime)[0] = 0x00; + (*m_prime)[1] = (unsigned char)ctxlen; + if (ctxlen > 0 && ctx != NULL) { + XMEMCPY(*m_prime + 2, ctx, ctxlen); + } + if (msglen > 0 && msg != NULL) { + XMEMCPY(*m_prime + prelen, msg, msglen); + } + return CRYPT_OK; + } + + if ((err = s_slhdsa_hash_oid_der(alg, &oid, &oidlen)) != CRYPT_OK) { + return err; + } + phm_len = sizeof(phm); + if ((err = s_slhdsa_hash_message_memory(alg, msg, msglen, phm, &phm_len)) != CRYPT_OK) { + return err; + } + + *m_prime_len = 2 + ctxlen + oidlen + phm_len; + *m_prime = XMALLOC(*m_prime_len > 0 ? *m_prime_len : 1); + if (*m_prime == NULL) { + zeromem(phm, sizeof(phm)); + return CRYPT_MEM; + } + + (*m_prime)[0] = 0x01; + (*m_prime)[1] = (unsigned char)ctxlen; + if (ctxlen > 0 && ctx != NULL) { + XMEMCPY(*m_prime + 2, ctx, ctxlen); + } + XMEMCPY(*m_prime + 2 + ctxlen, oid, oidlen); + XMEMCPY(*m_prime + 2 + ctxlen + oidlen, phm, phm_len); + zeromem(phm, sizeof(phm)); + + return CRYPT_OK; +} + +/* Parameter lookup */ + +static int s_slhdsa_get_params(int alg, slhdsa_params *p) +{ + LTC_ARGCHK(p != NULL); + + XMEMSET(p, 0, sizeof(*p)); + + p->wots_w = SPX_WOTS_W; + p->wots_logw = SPX_WOTS_LOGW; + + switch (s_slhdsa_base_alg(alg)) { + case LTC_SLHDSA_SHA2_128S: + case LTC_SLHDSA_SHAKE_128S: + p->n = 16; p->full_height = 63; p->d = 7; + p->fors_height = 12; p->fors_trees = 14; + p->is_shake = (alg == LTC_SLHDSA_SHAKE_128S) ? 1 : 0; + break; + case LTC_SLHDSA_SHA2_128F: + case LTC_SLHDSA_SHAKE_128F: + p->n = 16; p->full_height = 66; p->d = 22; + p->fors_height = 6; p->fors_trees = 33; + p->is_shake = (alg == LTC_SLHDSA_SHAKE_128F) ? 1 : 0; + break; + case LTC_SLHDSA_SHA2_192S: + case LTC_SLHDSA_SHAKE_192S: + p->n = 24; p->full_height = 63; p->d = 7; + p->fors_height = 14; p->fors_trees = 17; + p->is_shake = (alg == LTC_SLHDSA_SHAKE_192S) ? 1 : 0; + break; + case LTC_SLHDSA_SHA2_192F: + case LTC_SLHDSA_SHAKE_192F: + p->n = 24; p->full_height = 66; p->d = 22; + p->fors_height = 8; p->fors_trees = 33; + p->is_shake = (alg == LTC_SLHDSA_SHAKE_192F) ? 1 : 0; + break; + case LTC_SLHDSA_SHA2_256S: + case LTC_SLHDSA_SHAKE_256S: + p->n = 32; p->full_height = 64; p->d = 8; + p->fors_height = 14; p->fors_trees = 22; + p->is_shake = (alg == LTC_SLHDSA_SHAKE_256S) ? 1 : 0; + break; + case LTC_SLHDSA_SHA2_256F: + case LTC_SLHDSA_SHAKE_256F: + p->n = 32; p->full_height = 68; p->d = 17; + p->fors_height = 9; p->fors_trees = 35; + p->is_shake = (alg == LTC_SLHDSA_SHAKE_256F) ? 1 : 0; + break; + default: + return CRYPT_INVALID_ARG; + } + + /* Derived WOTS+ parameters */ + p->wots_len1 = 8 * p->n / p->wots_logw; + /* wots_len2 = floor(log(len1 * (w-1)) / log(w)) + 1, precomputed */ + if (p->n <= 8) { + p->wots_len2 = 2; + } else if (p->n <= 136) { + p->wots_len2 = 3; + } else { + p->wots_len2 = 4; + } + p->wots_len = p->wots_len1 + p->wots_len2; + p->wots_bytes = p->wots_len * p->n; + + /* Derived tree parameters */ + p->tree_height = p->full_height / p->d; + p->fors_msg_bytes = (p->fors_height * p->fors_trees + 7) / 8; + p->fors_bytes = (p->fors_height + 1) * p->fors_trees * p->n; + + /* Key and signature sizes */ + p->pk_bytes = 2 * (unsigned long)p->n; + p->sk_bytes = 4 * (unsigned long)p->n; + p->sig_bytes = (unsigned long)p->n + (unsigned long)p->fors_bytes + + (unsigned long)p->d * (unsigned long)p->wots_bytes + + (unsigned long)p->full_height * (unsigned long)p->n; + + /* Address offsets depend on variant */ + if (p->is_shake) { + p->addr_bytes = 32; + p->off_layer = 3; + p->off_tree = 8; + p->off_type = 19; + p->off_kp_addr = 20; + p->off_chain_addr = 27; + p->off_hash_addr = 31; + p->off_tree_hgt = 27; + p->off_tree_index = 28; + p->kp_addr_len = 4; + } else { + p->addr_bytes = 22; + p->off_layer = 0; + p->off_tree = 1; + p->off_type = 9; + p->off_kp_addr = 10; + p->off_chain_addr = 17; + p->off_hash_addr = 21; + p->off_tree_hgt = 17; + p->off_tree_index = 18; + p->kp_addr_len = 4; + } + + return CRYPT_OK; +} + +/* Address manipulation */ + +static void s_set_layer_addr(unsigned char addr[SPX_ADDR_BYTES], + ulong32 layer, const slhdsa_params *p) +{ + addr[p->off_layer] = (unsigned char)layer; +} + +static void s_set_tree_addr(unsigned char addr[SPX_ADDR_BYTES], + ulong64 tree, const slhdsa_params *p) +{ + int i; + for (i = 7; i >= 0; i--) { + addr[p->off_tree + i] = (unsigned char)(tree & 0xff); + tree >>= 8; + } +} + +static void s_set_type(unsigned char addr[SPX_ADDR_BYTES], + ulong32 type, const slhdsa_params *p) +{ + addr[p->off_type] = (unsigned char)type; +} + +static void s_copy_subtree_addr(unsigned char out[SPX_ADDR_BYTES], + const unsigned char in[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + XMEMCPY(out, in, p->off_tree + 8); +} + +static void s_set_keypair_addr(unsigned char addr[SPX_ADDR_BYTES], + ulong32 keypair, const slhdsa_params *p) +{ + addr[p->off_kp_addr + 0] = (unsigned char)(keypair >> 24); + addr[p->off_kp_addr + 1] = (unsigned char)(keypair >> 16); + addr[p->off_kp_addr + 2] = (unsigned char)(keypair >> 8); + addr[p->off_kp_addr + 3] = (unsigned char)(keypair); +} + +static void s_copy_keypair_addr(unsigned char out[SPX_ADDR_BYTES], + const unsigned char in[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + XMEMCPY(out, in, p->off_tree + 8); + XMEMCPY(out + p->off_kp_addr, in + p->off_kp_addr, p->kp_addr_len); +} + +static void s_set_chain_addr(unsigned char addr[SPX_ADDR_BYTES], + ulong32 chain, const slhdsa_params *p) +{ + addr[p->off_chain_addr] = (unsigned char)chain; +} + +static void s_set_hash_addr(unsigned char addr[SPX_ADDR_BYTES], + ulong32 hash, const slhdsa_params *p) +{ + addr[p->off_hash_addr] = (unsigned char)hash; +} + +static void s_set_tree_height(unsigned char addr[SPX_ADDR_BYTES], + ulong32 tree_height, const slhdsa_params *p) +{ + addr[p->off_tree_hgt] = (unsigned char)tree_height; +} + +static void s_set_tree_index(unsigned char addr[SPX_ADDR_BYTES], + ulong32 tree_index, const slhdsa_params *p) +{ + addr[p->off_tree_index + 0] = (unsigned char)(tree_index >> 24); + addr[p->off_tree_index + 1] = (unsigned char)(tree_index >> 16); + addr[p->off_tree_index + 2] = (unsigned char)(tree_index >> 8); + addr[p->off_tree_index + 3] = (unsigned char)(tree_index); +} + +/* Byte conversion utilities */ + +static void s_ull_to_bytes(unsigned char *out, unsigned int outlen, ulong64 in) +{ + int i; + for (i = (int)outlen - 1; i >= 0; i--) { + out[i] = (unsigned char)(in & 0xff); + in >>= 8; + } +} + +static ulong64 s_bytes_to_ull(const unsigned char *in, unsigned int inlen) +{ + ulong64 retval = 0; + unsigned int i; + for (i = 0; i < inlen; i++) { + retval |= ((ulong64)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/* ========================================================================= */ +/* SHAKE-based hash functions */ +/* ========================================================================= */ + +/** + * Tweakable hash (SHAKE-simple variant). + * thash(pub_seed, addr, in, inblocks) = SHAKE256(pub_seed || addr || in)[0:n] + */ +static int s_thash_shake(unsigned char *out, const unsigned char *in, + unsigned int inblocks, const unsigned char *pub_seed, + unsigned char addr[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + hash_state md; + int err; + unsigned long outlen = p->n; + + if ((err = sha3_shake_init(&md, 256)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, pub_seed, p->n)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, addr, p->addr_bytes)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, in, (unsigned long)inblocks * p->n)) != CRYPT_OK) return err; + return sha3_shake_done(&md, out, outlen); +} + +/** + * PRF(pub_seed, sk_seed, addr) = SHAKE256(pub_seed || addr || sk_seed)[0:n] + */ +static int s_prf_addr_shake(unsigned char *out, const unsigned char *pub_seed, + const unsigned char *sk_seed, + unsigned char addr[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + hash_state md; + int err; + unsigned long outlen = p->n; + + if ((err = sha3_shake_init(&md, 256)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, pub_seed, p->n)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, addr, p->addr_bytes)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, sk_seed, p->n)) != CRYPT_OK) return err; + return sha3_shake_done(&md, out, outlen); +} + +/** + * Compute the message-dependent randomness R (SHAKE variant). + * R = SHAKE256(sk_prf || optrand || m)[0:n] + */ +static int s_gen_message_random_shake(unsigned char *R, + const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, unsigned long mlen, + const slhdsa_params *p) +{ + hash_state md; + int err; + unsigned long outlen = p->n; + + if ((err = sha3_shake_init(&md, 256)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, sk_prf, p->n)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, optrand, p->n)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, m, mlen)) != CRYPT_OK) return err; + return sha3_shake_done(&md, R, outlen); +} + +/** + * Compute the message digest and leaf index from R, PK and M (SHAKE variant). + * SHAKE256(R || PK || M) -> (digest, tree, leaf_idx) + */ +static int s_hash_message_shake(unsigned char *digest, ulong64 *tree, ulong32 *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, unsigned long mlen, + const slhdsa_params *p) +{ + unsigned int tree_bits, tree_bytes, leaf_bits, leaf_bytes, dgst_bytes; + unsigned char buf[SPX_FORS_HEIGHT_MAX * SPX_FORS_TREES_MAX / 8 + 1 + 8 + 4]; + unsigned char *bufp; + hash_state md; + int err; + unsigned long outlen; + + tree_bits = p->tree_height * (p->d - 1); + tree_bytes = (tree_bits + 7) / 8; + leaf_bits = p->tree_height; + leaf_bytes = (leaf_bits + 7) / 8; + dgst_bytes = p->fors_msg_bytes + tree_bytes + leaf_bytes; + + outlen = dgst_bytes; + + if ((err = sha3_shake_init(&md, 256)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, R, p->n)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, pk, p->pk_bytes)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, m, mlen)) != CRYPT_OK) return err; + if ((err = sha3_shake_done(&md, buf, outlen)) != CRYPT_OK) return err; + + bufp = buf; + XMEMCPY(digest, bufp, p->fors_msg_bytes); + bufp += p->fors_msg_bytes; + + if (p->d == 1) { + *tree = 0; + } else { + *tree = s_bytes_to_ull(bufp, tree_bytes); + *tree &= (~(ulong64)0) >> (64 - tree_bits); + } + bufp += tree_bytes; + + *leaf_idx = (ulong32)s_bytes_to_ull(bufp, leaf_bytes); + *leaf_idx &= (~(ulong32)0) >> (32 - leaf_bits); + + return CRYPT_OK; +} + +/* ========================================================================= */ +/* SHA-2-based hash functions */ +/* ========================================================================= */ + +/** + * Return the libtomcrypt hash index for SHA-256 or SHA-512. + * For n < 24 (128-bit security): SHA-256 + * For n >= 24 (192/256-bit security): SHA-512 + */ +static int s_sha2_hash_idx(const slhdsa_params *p) +{ + if (p->n >= 24) + return find_hash("sha512"); + return find_hash("sha256"); +} + +/** + * Tweakable hash (SHA-2-simple variant). + * thash(pub_seed, addr, in, inblocks) = SHA-X(pub_seed || addr_c || in)[0:n] + * + * For single-block (inblocks == 1), always use SHA-256. + * For multi-block (inblocks > 1) with n >= 24, use SHA-512 for performance. + */ +static int s_thash_sha2(unsigned char *out, const unsigned char *in, + unsigned int inblocks, const unsigned char *pub_seed, + unsigned char addr[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + hash_state md; + int hash_idx, err; + unsigned char hash_out[64]; /* max SHA-512 output */ + + /* Choose hash function */ + if (inblocks > 1 && p->n >= 24) { + hash_idx = find_hash("sha512"); + } else { + hash_idx = find_hash("sha256"); + } + if (hash_idx == -1) return CRYPT_INVALID_HASH; + + if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].process(&md, pub_seed, p->n)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].process(&md, addr, p->addr_bytes)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].process(&md, in, (unsigned long)inblocks * p->n)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].done(&md, hash_out)) != CRYPT_OK) return err; + + /* Truncate to n bytes */ + XMEMCPY(out, hash_out, p->n); + + zeromem(hash_out, sizeof(hash_out)); + return CRYPT_OK; +} + +/** + * PRF(pub_seed, sk_seed, addr) for SHA-2 variant. + * PRF = SHA-256(pub_seed || addr_c || sk_seed)[0:n] + * Always uses SHA-256 regardless of security level. + */ +static int s_prf_addr_sha2(unsigned char *out, const unsigned char *pub_seed, + const unsigned char *sk_seed, + unsigned char addr[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + hash_state md; + int hash_idx, err; + unsigned char hash_out[32]; /* SHA-256 output */ + + hash_idx = find_hash("sha256"); + if (hash_idx == -1) return CRYPT_INVALID_HASH; + + if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].process(&md, pub_seed, p->n)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].process(&md, addr, p->addr_bytes)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].process(&md, sk_seed, p->n)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].done(&md, hash_out)) != CRYPT_OK) return err; + + XMEMCPY(out, hash_out, p->n); + + zeromem(hash_out, sizeof(hash_out)); + return CRYPT_OK; +} + +/** + * Compute the message-dependent randomness R (SHA-2 variant). + * R = HMAC-SHA-X(sk_prf, optrand || m)[0:n] + * For n < 24: SHA-256; for n >= 24: SHA-512. + */ +static int s_gen_message_random_sha2(unsigned char *R, + const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, unsigned long mlen, + const slhdsa_params *p) +{ + int hash_idx, err; + unsigned char hmac_out[64]; /* max SHA-512 HMAC */ + unsigned long hmac_len; + + hash_idx = s_sha2_hash_idx(p); + if (hash_idx == -1) return CRYPT_INVALID_HASH; + + hmac_len = hash_descriptor[hash_idx].hashsize; + + err = hmac_memory_multi(hash_idx, + sk_prf, (unsigned long)p->n, + hmac_out, &hmac_len, + optrand, (unsigned long)p->n, + m, mlen, + LTC_NULL); + if (err != CRYPT_OK) return err; + + XMEMCPY(R, hmac_out, p->n); + zeromem(hmac_out, sizeof(hmac_out)); + return CRYPT_OK; +} + +/** + * MGF1 helper for SHA-2 hash_message. + * Generates dgst_len bytes of output from mgf_seed of mgf_seed_len bytes. + * MGF1-SHA-X: for i=0,1,...: out += SHA-X(mgf_seed || i_be32), truncate. + */ +static int s_mgf1_sha2(unsigned char *out, unsigned long dgst_len, + const unsigned char *mgf_seed, unsigned long mgf_seed_len, + int hash_idx) +{ + hash_state md; + unsigned char hash_out[64]; /* max SHA-512 */ + unsigned char counter_buf[4]; + unsigned long hlen, remaining, copy_len; + ulong32 counter; + int err; + + hlen = hash_descriptor[hash_idx].hashsize; + remaining = dgst_len; + counter = 0; + + while (remaining > 0) { + counter_buf[0] = (unsigned char)(counter >> 24); + counter_buf[1] = (unsigned char)(counter >> 16); + counter_buf[2] = (unsigned char)(counter >> 8); + counter_buf[3] = (unsigned char)(counter); + + if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].process(&md, mgf_seed, mgf_seed_len)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].process(&md, counter_buf, 4)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].done(&md, hash_out)) != CRYPT_OK) return err; + + copy_len = remaining < hlen ? remaining : hlen; + XMEMCPY(out, hash_out, copy_len); + out += copy_len; + remaining -= copy_len; + counter++; + } + + zeromem(hash_out, sizeof(hash_out)); + return CRYPT_OK; +} + +/** + * Compute the message digest and leaf index from R, PK and M (SHA-2 variant). + * + * Per FIPS 205 Section 11.2: + * seed = SHA-X(R || PK.seed || PK.root || M) + * digest = MGF1-SHA-X(R || PK.seed || seed, dgst_bytes) + * Then extract (md, tree_idx, leaf_idx) from digest. + */ +static int s_hash_message_sha2(unsigned char *digest, ulong64 *tree, ulong32 *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, unsigned long mlen, + const slhdsa_params *p) +{ + unsigned int tree_bits, tree_bytes, leaf_bits, leaf_bytes, dgst_bytes; + unsigned char buf[SPX_FORS_HEIGHT_MAX * SPX_FORS_TREES_MAX / 8 + 1 + 8 + 4]; + unsigned char *bufp; + unsigned char seed[64]; /* max SHA-512 output */ + unsigned char *mgf_input; + unsigned long mgf_input_len, hlen; + hash_state md; + int hash_idx, err; + + hash_idx = s_sha2_hash_idx(p); + if (hash_idx == -1) return CRYPT_INVALID_HASH; + + hlen = hash_descriptor[hash_idx].hashsize; + + tree_bits = p->tree_height * (p->d - 1); + tree_bytes = (tree_bits + 7) / 8; + leaf_bits = p->tree_height; + leaf_bytes = (leaf_bits + 7) / 8; + dgst_bytes = p->fors_msg_bytes + tree_bytes + leaf_bytes; + + /* Step 1: seed = SHA-X(R || PK.seed || PK.root || M) */ + if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].process(&md, R, p->n)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].process(&md, pk, p->pk_bytes)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].process(&md, m, mlen)) != CRYPT_OK) return err; + if ((err = hash_descriptor[hash_idx].done(&md, seed)) != CRYPT_OK) return err; + + /* Step 2: MGF1-SHA-X(R || PK.seed || seed, dgst_bytes) */ + mgf_input_len = (unsigned long)p->n + (unsigned long)p->n + hlen; + mgf_input = XMALLOC(mgf_input_len); + if (mgf_input == NULL) return CRYPT_MEM; + + XMEMCPY(mgf_input, R, p->n); + XMEMCPY(mgf_input + p->n, pk, p->n); /* PK.seed */ + XMEMCPY(mgf_input + 2 * p->n, seed, hlen); + + err = s_mgf1_sha2(buf, dgst_bytes, mgf_input, mgf_input_len, hash_idx); + XFREE(mgf_input); + zeromem(seed, sizeof(seed)); + if (err != CRYPT_OK) return err; + + /* Extract digest, tree index, and leaf index */ + bufp = buf; + XMEMCPY(digest, bufp, p->fors_msg_bytes); + bufp += p->fors_msg_bytes; + + if (p->d == 1) { + *tree = 0; + } else { + *tree = s_bytes_to_ull(bufp, tree_bytes); + *tree &= (~(ulong64)0) >> (64 - tree_bits); + } + bufp += tree_bytes; + + *leaf_idx = (ulong32)s_bytes_to_ull(bufp, leaf_bytes); + *leaf_idx &= (~(ulong32)0) >> (32 - leaf_bits); + + return CRYPT_OK; +} + +/* ========================================================================= */ +/* Dispatch wrappers */ +/* ========================================================================= */ + +static int s_thash(unsigned char *out, const unsigned char *in, + unsigned int inblocks, const unsigned char *pub_seed, + unsigned char addr[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + if (p->is_shake) + return s_thash_shake(out, in, inblocks, pub_seed, addr, p); + else + return s_thash_sha2(out, in, inblocks, pub_seed, addr, p); +} + +static int s_prf_addr(unsigned char *out, const unsigned char *pub_seed, + const unsigned char *sk_seed, + unsigned char addr[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + if (p->is_shake) + return s_prf_addr_shake(out, pub_seed, sk_seed, addr, p); + else + return s_prf_addr_sha2(out, pub_seed, sk_seed, addr, p); +} + +static int s_gen_message_random(unsigned char *R, + const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, unsigned long mlen, + const slhdsa_params *p) +{ + if (p->is_shake) + return s_gen_message_random_shake(R, sk_prf, optrand, m, mlen, p); + else + return s_gen_message_random_sha2(R, sk_prf, optrand, m, mlen, p); +} + +static int s_hash_message(unsigned char *digest, ulong64 *tree, ulong32 *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, unsigned long mlen, + const slhdsa_params *p) +{ + if (p->is_shake) + return s_hash_message_shake(digest, tree, leaf_idx, R, pk, m, mlen, p); + else + return s_hash_message_sha2(digest, tree, leaf_idx, R, pk, m, mlen, p); +} + +/* WOTS+ */ + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * Interprets in as start-th value of the chain. + */ +static int s_gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const unsigned char *pub_seed, + unsigned char addr[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + ulong32 i; + int err; + + XMEMCPY(out, in, p->n); + + for (i = start; i < (start + steps) && i < p->wots_w; i++) { + s_set_hash_addr(addr, i, p); + if ((err = s_thash(out, out, 1, pub_seed, addr, p)) != CRYPT_OK) return err; + } + return CRYPT_OK; +} + +/** + * base_w algorithm: interprets an array of bytes as integers in base w. + */ +static void s_base_w(unsigned int *output, int out_len, + const unsigned char *input, const slhdsa_params *p) +{ + int in_idx = 0; + int out_idx = 0; + unsigned char total; + int bits = 0; + int consumed; + + (void)p; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in_idx]; + in_idx++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out_idx] = (total >> bits) & (SPX_WOTS_W - 1); + out_idx++; + } +} + +/** + * Computes the WOTS+ checksum over a message (in base_w). + */ +static void s_wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w, + const slhdsa_params *p) +{ + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN_MAX * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + unsigned int csum_bytes_len; + + for (i = 0; i < p->wots_len1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + csum = csum << ((8 - ((p->wots_len2 * SPX_WOTS_LOGW) % 8)) % 8); + csum_bytes_len = (p->wots_len2 * SPX_WOTS_LOGW + 7) / 8; + s_ull_to_bytes(csum_bytes, csum_bytes_len, csum); + s_base_w(csum_base_w, (int)p->wots_len2, csum_bytes, p); +} + +/** + * Takes a message and derives the matching chain lengths. + */ +static void s_chain_lengths(unsigned int *lengths, const unsigned char *msg, + const slhdsa_params *p) +{ + s_base_w(lengths, (int)p->wots_len1, msg, p); + s_wots_checksum(lengths + p->wots_len1, lengths, p); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + */ +static int s_wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, + const unsigned char *msg, + const unsigned char *pub_seed, + unsigned char addr[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + unsigned int lengths[SPX_WOTS_LEN_MAX]; + ulong32 i; + int err; + + s_chain_lengths(lengths, msg, p); + + for (i = 0; i < p->wots_len; i++) { + s_set_chain_addr(addr, i, p); + if ((err = s_gen_chain(pk + (unsigned long)i * p->n, + sig + (unsigned long)i * p->n, + lengths[i], SPX_WOTS_W - 1 - lengths[i], + pub_seed, addr, p)) != CRYPT_OK) return err; + } + return CRYPT_OK; +} + +/** + * Generate a WOTS leaf node (public key hash). + * This also generates the WOTS signature if wots_sign_leaf matches leaf_idx. + * + * This function corresponds to wots_gen_leafx1 from the reference implementation. + * + * @param dest [out] The computed leaf node (n bytes) + * @param pub_seed The public seed + * @param sk_seed The secret seed + * @param leaf_idx Current leaf index + * @param wots_sig [out] If not NULL and leaf_idx == wots_sign_leaf, the WOTS sig is written here + * @param wots_sign_leaf The leaf index to sign with (~0 if not signing) + * @param wots_steps Chain lengths for the message being signed + * @param leaf_addr Working WOTS address + * @param pk_addr Working WOTS-PK address + * @param p Parameter set + */ +static int s_wots_gen_leaf(unsigned char *dest, + const unsigned char *pub_seed, + const unsigned char *sk_seed, + ulong32 leaf_idx, + unsigned char *wots_sig, + ulong32 wots_sign_leaf, + const unsigned int *wots_steps, + unsigned char leaf_addr[SPX_ADDR_BYTES], + unsigned char pk_addr[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + unsigned int i, k; + unsigned char pk_buffer[SPX_WOTS_BYTES_MAX]; + unsigned char *buffer; + ulong32 wots_k_mask; + int err; + + if (leaf_idx == wots_sign_leaf) { + wots_k_mask = 0; + } else { + wots_k_mask = (ulong32)~0; + } + + s_set_keypair_addr(leaf_addr, leaf_idx, p); + s_set_keypair_addr(pk_addr, leaf_idx, p); + + for (i = 0, buffer = pk_buffer; i < p->wots_len; i++, buffer += p->n) { + ulong32 wots_k = (wots_steps != NULL) ? (wots_steps[i] | wots_k_mask) : ((ulong32)~0); + + /* Start with the secret seed */ + s_set_chain_addr(leaf_addr, i, p); + s_set_hash_addr(leaf_addr, 0, p); + s_set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF, p); + + if ((err = s_prf_addr(buffer, pub_seed, sk_seed, leaf_addr, p)) != CRYPT_OK) + return err; + + s_set_type(leaf_addr, SPX_ADDR_TYPE_WOTS, p); + + /* Iterate down the WOTS chain */ + for (k = 0; ; k++) { + /* Check if this is the value that needs to be saved as a + part of the WOTS signature */ + if (k == wots_k && wots_sig != NULL) { + XMEMCPY(wots_sig + (unsigned long)i * p->n, buffer, p->n); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) break; + + /* Iterate one step on the chain */ + s_set_hash_addr(leaf_addr, k, p); + if ((err = s_thash(buffer, buffer, 1, pub_seed, leaf_addr, p)) != CRYPT_OK) + return err; + } + } + + /* Do the final thash to generate the public key */ + return s_thash(dest, pk_buffer, p->wots_len, pub_seed, pk_addr, p); +} + +/* Tree operations */ + +/** + * Computes a root node given a leaf and an auth path. + */ +static int s_compute_root(unsigned char *root, const unsigned char *leaf, + ulong32 leaf_idx, ulong32 idx_offset, + const unsigned char *auth_path, ulong32 tree_height, + const unsigned char *pub_seed, + unsigned char addr[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + ulong32 i; + unsigned char buffer[2 * SPX_N_MAX]; + int err; + + if (leaf_idx & 1) { + XMEMCPY(buffer + p->n, leaf, p->n); + XMEMCPY(buffer, auth_path, p->n); + } else { + XMEMCPY(buffer, leaf, p->n); + XMEMCPY(buffer + p->n, auth_path, p->n); + } + auth_path += p->n; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + s_set_tree_height(addr, i + 1, p); + s_set_tree_index(addr, leaf_idx + idx_offset, p); + + if (leaf_idx & 1) { + if ((err = s_thash(buffer + p->n, buffer, 2, pub_seed, addr, p)) != CRYPT_OK) return err; + XMEMCPY(buffer, auth_path, p->n); + } else { + if ((err = s_thash(buffer, buffer, 2, pub_seed, addr, p)) != CRYPT_OK) return err; + XMEMCPY(buffer + p->n, auth_path, p->n); + } + auth_path += p->n; + } + + leaf_idx >>= 1; + idx_offset >>= 1; + s_set_tree_height(addr, tree_height, p); + s_set_tree_index(addr, leaf_idx + idx_offset, p); + return s_thash(root, buffer, 2, pub_seed, addr, p); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * + * This is the treehashx1 variant that supports generating WOTS signatures + * during traversal (needed by merkle_sign). + * + * @param root [out] Root of the tree (n bytes) + * @param auth_path [out] Authentication path (tree_height * n bytes) + * @param pub_seed Public seed + * @param sk_seed Secret seed + * @param leaf_idx Target leaf index + * @param idx_offset Offset applied to leaf indices + * @param tree_height Height of the tree + * @param tree_addr Address structure for the tree + * @param wots_sig [out] If not NULL, WOTS signature for wots_sign_leaf + * @param wots_sign_leaf Leaf to sign with (~0 if not signing) + * @param wots_steps Chain lengths for signing + * @param wots_addr Working WOTS address (for leaf generation) + * @param p Parameter set + */ +static int s_treehashx1(unsigned char *root, unsigned char *auth_path, + const unsigned char *pub_seed, + const unsigned char *sk_seed, + ulong32 leaf_idx, ulong32 idx_offset, + ulong32 tree_height, + unsigned char tree_addr[SPX_ADDR_BYTES], + unsigned char *wots_sig, + ulong32 wots_sign_leaf, + const unsigned int *wots_steps, + unsigned char wots_addr[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + unsigned char *stack; + ulong32 idx; + ulong32 max_idx = ((ulong32)1 << tree_height) - 1; + int err; + + /* Allocate stack: tree_height * n bytes for intermediate nodes */ + stack = XMALLOC((unsigned long)tree_height * p->n); + if (stack == NULL) return CRYPT_MEM; + + for (idx = 0; ; idx++) { + unsigned char current[2 * SPX_N_MAX]; + unsigned char leaf_addr[SPX_ADDR_BYTES]; + unsigned char pk_addr[SPX_ADDR_BYTES]; + + XMEMSET(leaf_addr, 0, SPX_ADDR_BYTES); + XMEMSET(pk_addr, 0, SPX_ADDR_BYTES); + + s_copy_subtree_addr(leaf_addr, wots_addr, p); + s_copy_subtree_addr(pk_addr, wots_addr, p); + s_set_type(pk_addr, SPX_ADDR_TYPE_WOTSPK, p); + + /* Generate the leaf node */ + err = s_wots_gen_leaf(¤t[p->n], pub_seed, sk_seed, + idx + idx_offset, + wots_sig, wots_sign_leaf, wots_steps, + leaf_addr, pk_addr, p); + if (err != CRYPT_OK) { XFREE(stack); return err; } + + /* Combine with previously generated nodes */ + { + ulong32 internal_idx_offset = idx_offset; + ulong32 internal_idx = idx; + ulong32 internal_leaf = leaf_idx; + ulong32 h; + + for (h = 0; ; h++, internal_idx >>= 1, internal_leaf >>= 1) { + if (h == tree_height) { + XMEMCPY(root, ¤t[p->n], p->n); + XFREE(stack); + return CRYPT_OK; + } + + if ((internal_idx ^ internal_leaf) == 0x01) { + XMEMCPY(&auth_path[h * p->n], ¤t[p->n], p->n); + } + + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Combine left and right nodes */ + internal_idx_offset >>= 1; + s_set_tree_height(tree_addr, h + 1, p); + s_set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset, p); + + XMEMCPY(¤t[0], &stack[h * p->n], p->n); + err = s_thash(¤t[p->n], ¤t[0], 2, pub_seed, tree_addr, p); + if (err != CRYPT_OK) { XFREE(stack); return err; } + } + + XMEMCPY(&stack[h * p->n], ¤t[p->n], p->n); + } + } +} + +/** + * Simplified treehash for FORS: uses a callback-style leaf generation. + * This version generates FORS leaf nodes directly. + * + * @param root [out] Root of the tree (n bytes) + * @param auth_path [out] Authentication path + * @param pub_seed Public seed + * @param sk_seed Secret seed + * @param leaf_idx Target leaf index + * @param idx_offset Offset applied to leaf indices + * @param tree_height Height of the tree + * @param tree_addr Address structure for the tree + * @param fors_leaf_addr FORS leaf address + * @param p Parameter set + */ +static int s_treehash_fors(unsigned char *root, unsigned char *auth_path, + const unsigned char *pub_seed, + const unsigned char *sk_seed, + ulong32 leaf_idx, ulong32 idx_offset, + ulong32 tree_height, + unsigned char tree_addr[SPX_ADDR_BYTES], + unsigned char fors_leaf_addr[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + unsigned char *stack; + ulong32 idx; + ulong32 max_idx = ((ulong32)1 << tree_height) - 1; + int err; + + stack = XMALLOC((unsigned long)tree_height * p->n); + if (stack == NULL) return CRYPT_MEM; + + for (idx = 0; ; idx++) { + unsigned char current[2 * SPX_N_MAX]; + + /* Generate the FORS leaf */ + s_set_tree_index(fors_leaf_addr, idx + idx_offset, p); + s_set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF, p); + if ((err = s_prf_addr(¤t[p->n], pub_seed, sk_seed, fors_leaf_addr, p)) != CRYPT_OK) { + XFREE(stack); + return err; + } + + s_set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE, p); + if ((err = s_thash(¤t[p->n], ¤t[p->n], 1, pub_seed, fors_leaf_addr, p)) != CRYPT_OK) { + XFREE(stack); + return err; + } + + /* Combine with previously generated nodes */ + { + ulong32 internal_idx_offset = idx_offset; + ulong32 internal_idx = idx; + ulong32 internal_leaf = leaf_idx; + ulong32 h; + + for (h = 0; ; h++, internal_idx >>= 1, internal_leaf >>= 1) { + if (h == tree_height) { + XMEMCPY(root, ¤t[p->n], p->n); + XFREE(stack); + return CRYPT_OK; + } + + if ((internal_idx ^ internal_leaf) == 0x01) { + XMEMCPY(&auth_path[h * p->n], ¤t[p->n], p->n); + } + + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + internal_idx_offset >>= 1; + s_set_tree_height(tree_addr, h + 1, p); + s_set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset, p); + + XMEMCPY(¤t[0], &stack[h * p->n], p->n); + err = s_thash(¤t[p->n], ¤t[0], 2, pub_seed, tree_addr, p); + if (err != CRYPT_OK) { XFREE(stack); return err; } + } + + XMEMCPY(&stack[h * p->n], ¤t[p->n], p->n); + } + } +} + +/* FORS */ + +/** + * Interprets m as fors_height-bit unsigned integers. + */ +static void s_message_to_indices(ulong32 *indices, const unsigned char *m, + const slhdsa_params *p) +{ + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < p->fors_trees; i++) { + indices[i] = 0; + for (j = 0; j < p->fors_height; j++) { + indices[i] ^= (((ulong32)(m[offset >> 3] >> (offset & 0x7))) & 1u) << j; + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + */ +static int s_fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const unsigned char *pub_seed, + const unsigned char *sk_seed, + const unsigned char fors_addr[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + ulong32 indices[SPX_FORS_TREES_MAX]; + unsigned char *roots; + unsigned char fors_tree_addr[SPX_ADDR_BYTES]; + unsigned char fors_leaf_addr[SPX_ADDR_BYTES]; + unsigned char fors_pk_addr[SPX_ADDR_BYTES]; + ulong32 idx_offset; + unsigned int i; + int err; + + roots = XMALLOC((unsigned long)p->fors_trees * p->n); + if (roots == NULL) return CRYPT_MEM; + + XMEMSET(fors_tree_addr, 0, SPX_ADDR_BYTES); + XMEMSET(fors_leaf_addr, 0, SPX_ADDR_BYTES); + XMEMSET(fors_pk_addr, 0, SPX_ADDR_BYTES); + + s_copy_keypair_addr(fors_tree_addr, fors_addr, p); + s_copy_keypair_addr(fors_leaf_addr, fors_addr, p); + s_copy_keypair_addr(fors_pk_addr, fors_addr, p); + s_set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK, p); + + s_message_to_indices(indices, m, p); + + for (i = 0; i < p->fors_trees; i++) { + idx_offset = i * ((ulong32)1 << p->fors_height); + + s_set_tree_height(fors_tree_addr, 0, p); + s_set_tree_index(fors_tree_addr, indices[i] + idx_offset, p); + s_set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF, p); + + /* Include the secret key part that produces the selected leaf node. */ + if ((err = s_prf_addr(sig, pub_seed, sk_seed, fors_tree_addr, p)) != CRYPT_OK) { + XFREE(roots); + return err; + } + s_set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE, p); + sig += p->n; + + /* Compute the authentication path for this leaf node. */ + err = s_treehash_fors(roots + (unsigned long)i * p->n, sig, + pub_seed, sk_seed, + indices[i], idx_offset, p->fors_height, + fors_tree_addr, fors_leaf_addr, p); + if (err != CRYPT_OK) { + XFREE(roots); + return err; + } + + sig += (unsigned long)p->n * p->fors_height; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + err = s_thash(pk, roots, p->fors_trees, pub_seed, fors_pk_addr, p); + XFREE(roots); + return err; +} + +/** + * Derives the FORS public key from a signature. + */ +static int s_fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, + const unsigned char *m, + const unsigned char *pub_seed, + const unsigned char fors_addr[SPX_ADDR_BYTES], + const slhdsa_params *p) +{ + ulong32 indices[SPX_FORS_TREES_MAX]; + unsigned char *roots; + unsigned char leaf[SPX_N_MAX]; + unsigned char fors_tree_addr[SPX_ADDR_BYTES]; + unsigned char fors_pk_addr[SPX_ADDR_BYTES]; + ulong32 idx_offset; + unsigned int i; + int err; + + roots = XMALLOC((unsigned long)p->fors_trees * p->n); + if (roots == NULL) return CRYPT_MEM; + + XMEMSET(fors_tree_addr, 0, SPX_ADDR_BYTES); + XMEMSET(fors_pk_addr, 0, SPX_ADDR_BYTES); + + s_copy_keypair_addr(fors_tree_addr, fors_addr, p); + s_copy_keypair_addr(fors_pk_addr, fors_addr, p); + + s_set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE, p); + s_set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK, p); + + s_message_to_indices(indices, m, p); + + for (i = 0; i < p->fors_trees; i++) { + idx_offset = i * ((ulong32)1 << p->fors_height); + + s_set_tree_height(fors_tree_addr, 0, p); + s_set_tree_index(fors_tree_addr, indices[i] + idx_offset, p); + + /* Derive the leaf from the included secret key part. */ + err = s_thash(leaf, sig, 1, pub_seed, fors_tree_addr, p); + if (err != CRYPT_OK) { XFREE(roots); return err; } + sig += p->n; + + /* Derive the corresponding root node of this tree. */ + err = s_compute_root(roots + (unsigned long)i * p->n, leaf, + indices[i], idx_offset, + sig, p->fors_height, pub_seed, fors_tree_addr, p); + if (err != CRYPT_OK) { XFREE(roots); return err; } + sig += (unsigned long)p->n * p->fors_height; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + err = s_thash(pk, roots, p->fors_trees, pub_seed, fors_pk_addr, p); + XFREE(roots); + return err; +} + +/* Merkle */ + +/** + * Generate a Merkle signature (WOTS signature followed by authentication path). + */ +static int s_merkle_sign(unsigned char *sig, unsigned char *root, + const unsigned char *pub_seed, + const unsigned char *sk_seed, + unsigned char wots_addr[SPX_ADDR_BYTES], + unsigned char tree_addr[SPX_ADDR_BYTES], + ulong32 idx_leaf, + const slhdsa_params *p) +{ + unsigned char *auth_path = sig + p->wots_bytes; + unsigned int steps[SPX_WOTS_LEN_MAX]; + + s_chain_lengths(steps, root, p); + + s_set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE, p); + + return s_treehashx1(root, auth_path, pub_seed, sk_seed, + idx_leaf, 0, p->tree_height, + tree_addr, sig, idx_leaf, steps, + wots_addr, p); +} + +/** + * Compute root node of the top-most subtree. + */ +static int s_merkle_gen_root(unsigned char *root, + const unsigned char *pub_seed, + const unsigned char *sk_seed, + const slhdsa_params *p) +{ + unsigned char auth_path[SPX_TREE_HEIGHT_MAX * SPX_N_MAX + SPX_WOTS_BYTES_MAX]; + unsigned char top_tree_addr[SPX_ADDR_BYTES]; + unsigned char wots_addr[SPX_ADDR_BYTES]; + + XMEMSET(top_tree_addr, 0, SPX_ADDR_BYTES); + XMEMSET(wots_addr, 0, SPX_ADDR_BYTES); + + s_set_layer_addr(top_tree_addr, p->d - 1, p); + s_set_layer_addr(wots_addr, p->d - 1, p); + + return s_merkle_sign(auth_path, root, pub_seed, sk_seed, + wots_addr, top_tree_addr, + (ulong32)~0, /* ~0 means "don't generate an auth path" */ + p); +} + +/* Sign / verify core */ + +static int s_sign_core(unsigned char *sig, unsigned long *siglen, + const unsigned char *m, unsigned long mlen, + const unsigned char *sk, + const unsigned char *optrand, + const slhdsa_params *p) +{ + const unsigned char *sk_seed = sk; + const unsigned char *sk_prf = sk + p->n; + const unsigned char *pk = sk + 2 * p->n; + const unsigned char *pub_seed = pk; + unsigned char mhash[SPX_FORS_HEIGHT_MAX * SPX_FORS_TREES_MAX / 8 + 1]; + unsigned char root[SPX_N_MAX]; + ulong64 tree; + ulong32 idx_leaf; + unsigned char wots_addr[SPX_ADDR_BYTES]; + unsigned char tree_addr[SPX_ADDR_BYTES]; + ulong32 i; + int err; + + XMEMSET(wots_addr, 0, SPX_ADDR_BYTES); + XMEMSET(tree_addr, 0, SPX_ADDR_BYTES); + + s_set_type(wots_addr, SPX_ADDR_TYPE_WOTS, p); + s_set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE, p); + + /* Compute the digest randomization value R. */ + if ((err = s_gen_message_random(sig, sk_prf, optrand, m, mlen, p)) != CRYPT_OK) return err; + + /* Derive the message digest and leaf index from R, PK and M. */ + if ((err = s_hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, p)) != CRYPT_OK) return err; + sig += p->n; + + s_set_tree_addr(wots_addr, tree, p); + s_set_keypair_addr(wots_addr, idx_leaf, p); + + /* Sign the message hash using FORS. */ + if ((err = s_fors_sign(sig, root, mhash, pub_seed, sk_seed, wots_addr, p)) != CRYPT_OK) return err; + sig += p->fors_bytes; + + for (i = 0; i < p->d; i++) { + s_set_layer_addr(tree_addr, i, p); + s_set_tree_addr(tree_addr, tree, p); + + s_copy_subtree_addr(wots_addr, tree_addr, p); + s_set_keypair_addr(wots_addr, idx_leaf, p); + + if ((err = s_merkle_sign(sig, root, pub_seed, sk_seed, + wots_addr, tree_addr, idx_leaf, p)) != CRYPT_OK) return err; + sig += p->wots_bytes + (unsigned long)p->tree_height * p->n; + + /* Update the indices for the next layer. */ + idx_leaf = (ulong32)(tree & (((ulong64)1 << p->tree_height) - 1)); + tree = tree >> p->tree_height; + } + + *siglen = p->sig_bytes; + return CRYPT_OK; +} + +static int s_verify_core(const unsigned char *sig, unsigned long siglen, + const unsigned char *m, unsigned long mlen, + const unsigned char *pk, + const slhdsa_params *p) +{ + const unsigned char *pub_seed = pk; + const unsigned char *pub_root = pk + p->n; + unsigned char mhash[SPX_FORS_HEIGHT_MAX * SPX_FORS_TREES_MAX / 8 + 1]; + unsigned char wots_pk[SPX_WOTS_BYTES_MAX]; + unsigned char root[SPX_N_MAX]; + unsigned char leaf[SPX_N_MAX]; + unsigned int i; + ulong64 tree; + ulong32 idx_leaf; + unsigned char wots_addr[SPX_ADDR_BYTES]; + unsigned char tree_addr[SPX_ADDR_BYTES]; + unsigned char wots_pk_addr[SPX_ADDR_BYTES]; + int err; + + if (siglen != p->sig_bytes) return CRYPT_INVALID_PACKET; + + XMEMSET(wots_addr, 0, SPX_ADDR_BYTES); + XMEMSET(tree_addr, 0, SPX_ADDR_BYTES); + XMEMSET(wots_pk_addr, 0, SPX_ADDR_BYTES); + + s_set_type(wots_addr, SPX_ADDR_TYPE_WOTS, p); + s_set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE, p); + s_set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK, p); + + /* Derive the message digest and leaf index from R || PK || M. */ + if ((err = s_hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, p)) != CRYPT_OK) return err; + sig += p->n; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + s_set_tree_addr(wots_addr, tree, p); + s_set_keypair_addr(wots_addr, idx_leaf, p); + + if ((err = s_fors_pk_from_sig(root, sig, mhash, pub_seed, wots_addr, p)) != CRYPT_OK) return err; + sig += p->fors_bytes; + + /* For each subtree.. */ + for (i = 0; i < p->d; i++) { + s_set_layer_addr(tree_addr, i, p); + s_set_tree_addr(tree_addr, tree, p); + + s_copy_subtree_addr(wots_addr, tree_addr, p); + s_set_keypair_addr(wots_addr, idx_leaf, p); + + s_copy_keypair_addr(wots_pk_addr, wots_addr, p); + + /* The WOTS public key is only correct if the signature was correct. */ + if ((err = s_wots_pk_from_sig(wots_pk, sig, root, pub_seed, wots_addr, p)) != CRYPT_OK) + return err; + sig += p->wots_bytes; + + /* Compute the leaf node using the WOTS public key. */ + if ((err = s_thash(leaf, wots_pk, p->wots_len, pub_seed, wots_pk_addr, p)) != CRYPT_OK) + return err; + + /* Compute the root node of this subtree. */ + if ((err = s_compute_root(root, leaf, idx_leaf, 0, sig, p->tree_height, + pub_seed, tree_addr, p)) != CRYPT_OK) return err; + sig += (unsigned long)p->tree_height * p->n; + + /* Update the indices for the next layer. */ + idx_leaf = (ulong32)(tree & (((ulong64)1 << p->tree_height) - 1)); + tree = tree >> p->tree_height; + } + + /* Check if the root node equals the root node in the public key. */ + { + unsigned int j; + unsigned char diff = 0; + for (j = 0; j < p->n; j++) { + diff |= root[j] ^ pub_root[j]; + } + if (diff != 0) return CRYPT_INVALID_PACKET; + } + + return CRYPT_OK; +} + +/* Public API */ + +/** + Generate an SLH-DSA key pair. + @param prng An active PRNG state + @param wprng The index of the desired PRNG + @param alg The parameter set (one of ltc_slhdsa_id) + @param key [out] Destination for the newly created key pair + @return CRYPT_OK if successful +*/ +int slhdsa_make_key(prng_state *prng, int wprng, int alg, slhdsa_key *key) +{ + slhdsa_params p; + unsigned char seed[3 * SPX_N_MAX]; /* SK_SEED || SK_PRF || PUB_SEED */ + int err; + + LTC_ARGCHK(key != NULL); + + if ((err = s_slhdsa_get_params(alg, &p)) != CRYPT_OK) return err; + if ((err = prng_is_valid(wprng)) != CRYPT_OK) return err; + + /* Generate random seed: SK_SEED || SK_PRF || PUB_SEED */ + if (prng_descriptor[wprng].read(seed, 3 * p.n, prng) != 3 * p.n) + return CRYPT_ERROR_READPRNG; + + /* Allocate key storage: + * sk = [SK_SEED || SK_PRF || PUB_SEED || root] (4*n bytes) + * pk = [PUB_SEED || root] (2*n bytes) */ + key->sk = XMALLOC(p.sk_bytes); + key->pk = XMALLOC(p.pk_bytes); + if (key->sk == NULL || key->pk == NULL) { + if (key->sk) { XFREE(key->sk); key->sk = NULL; } + if (key->pk) { XFREE(key->pk); key->pk = NULL; } + zeromem(seed, sizeof(seed)); + return CRYPT_MEM; + } + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + XMEMCPY(key->sk, seed, 3 * p.n); + XMEMCPY(key->pk, seed + 2 * p.n, p.n); /* PUB_SEED */ + + /* Compute root node of the top-most subtree. */ + err = s_merkle_gen_root(key->sk + 3 * p.n, key->pk, key->sk, &p); + if (err != CRYPT_OK) { + zeromem(key->sk, p.sk_bytes); + XFREE(key->sk); key->sk = NULL; + XFREE(key->pk); key->pk = NULL; + zeromem(seed, sizeof(seed)); + return err; + } + + XMEMCPY(key->pk + p.n, key->sk + 3 * p.n, p.n); /* root */ + + key->alg = alg; + key->type = PK_PRIVATE; + key->pklen = p.pk_bytes; + key->sklen = p.sk_bytes; + + zeromem(seed, sizeof(seed)); + return CRYPT_OK; +} + +/** + Free an SLH-DSA key from memory. + @param key The key to free +*/ +void slhdsa_free(slhdsa_key *key) +{ + if (key == NULL) return; + if (key->sk != NULL) { + zeromem(key->sk, key->sklen); + XFREE(key->sk); + } + if (key->pk != NULL) { + XFREE(key->pk); + } + XMEMSET(key, 0, sizeof(*key)); +} + +/** + Export an SLH-DSA key to a byte buffer. + @param out [out] Destination for the exported key + @param outlen [in/out] Max size and resulting size of the exported key + @param which PK_PUBLIC for the verification key, PK_PRIVATE for the signing key + @param key The key to export + @return CRYPT_OK if successful +*/ +int slhdsa_export_raw(unsigned char *out, unsigned long *outlen, int which, const slhdsa_key *key) +{ + slhdsa_params p; + unsigned long needed; + int err; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = s_slhdsa_get_params(key->alg, &p)) != CRYPT_OK) return err; + + if (which == PK_PUBLIC) { + needed = p.pk_bytes; + if (*outlen < needed) { *outlen = needed; return CRYPT_BUFFER_OVERFLOW; } + if (key->pk == NULL) return CRYPT_PK_NOT_PRIVATE; + XMEMCPY(out, key->pk, needed); + } else if (which == PK_PRIVATE) { + if (key->type != PK_PRIVATE) return CRYPT_PK_NOT_PRIVATE; + needed = p.sk_bytes; + if (*outlen < needed) { *outlen = needed; return CRYPT_BUFFER_OVERFLOW; } + XMEMCPY(out, key->sk, needed); + } else { + return CRYPT_INVALID_ARG; + } + + *outlen = needed; + return CRYPT_OK; +} + +/** + Import an SLH-DSA key from a byte buffer. + @param in The buffer to import from + @param inlen Length of the buffer + @param which PK_PUBLIC for a verification key, PK_PRIVATE for a signing key + @param alg The parameter set (one of ltc_slhdsa_id) + @param key [out] Destination for the imported key + @return CRYPT_OK if successful +*/ +int slhdsa_import_raw(const unsigned char *in, unsigned long inlen, int which, int alg, slhdsa_key *key) +{ + slhdsa_params p; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = s_slhdsa_get_params(alg, &p)) != CRYPT_OK) return err; + + XMEMSET(key, 0, sizeof(*key)); + key->alg = alg; + + if (which == PK_PUBLIC) { + if (inlen != p.pk_bytes) return CRYPT_INVALID_PACKET; + key->pk = XMALLOC(p.pk_bytes); + if (key->pk == NULL) return CRYPT_MEM; + XMEMCPY(key->pk, in, p.pk_bytes); + key->pklen = p.pk_bytes; + key->type = PK_PUBLIC; + } else if (which == PK_PRIVATE) { + if (inlen != p.sk_bytes) return CRYPT_INVALID_PACKET; + key->sk = XMALLOC(p.sk_bytes); + if (key->sk == NULL) return CRYPT_MEM; + XMEMCPY(key->sk, in, p.sk_bytes); + key->sklen = p.sk_bytes; + + /* Reconstruct pk from sk: + * sk = [SK_SEED || SK_PRF || PUB_SEED || root] + * pk = [PUB_SEED || root] */ + key->pk = XMALLOC(p.pk_bytes); + if (key->pk == NULL) { + slhdsa_free(key); + return CRYPT_MEM; + } + XMEMCPY(key->pk, in + 2 * p.n, 2 * p.n); /* PUB_SEED || root */ + key->pklen = p.pk_bytes; + key->type = PK_PRIVATE; + } else { + return CRYPT_INVALID_ARG; + } + + return CRYPT_OK; +} + +/** + Sign a message with SLH-DSA. + @param msg The message to sign + @param msglen Length of the message + @param sig [out] The signature + @param siglen [in/out] Max size and resulting size of the signature + @param ctx Optional context string (can be NULL if ctxlen is 0) + @param ctxlen Length of the context string (max 255 bytes per FIPS 205) + @param prng An active PRNG state (for hedged signing) + @param wprng The index of the desired PRNG + @param key The private (signing) key + @return CRYPT_OK if successful +*/ +int slhdsa_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + prng_state *prng, int wprng, + const slhdsa_key *key) +{ + slhdsa_params p; + unsigned char optrand[SPX_N_MAX]; + unsigned char *m_prime = NULL; + unsigned long m_prime_len; + int err; + + LTC_ARGCHK(msg != NULL || msglen == 0); + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(siglen != NULL); + LTC_ARGCHK(key != NULL); + + if (key->type != PK_PRIVATE) return CRYPT_PK_NOT_PRIVATE; + + if ((err = s_slhdsa_get_params(key->alg, &p)) != CRYPT_OK) return err; + if (*siglen < p.sig_bytes) { *siglen = p.sig_bytes; return CRYPT_BUFFER_OVERFLOW; } + if ((err = prng_is_valid(wprng)) != CRYPT_OK) return err; + + if ((err = s_slhdsa_prepare_message(&m_prime, &m_prime_len, + msg, msglen, ctx, ctxlen, key->alg)) != CRYPT_OK) { + return err; + } + + /* Hedged signing: generate random opt_rand */ + if (prng_descriptor[wprng].read(optrand, p.n, prng) != p.n) { + XFREE(m_prime); + return CRYPT_ERROR_READPRNG; + } + + err = s_sign_core(sig, siglen, m_prime, m_prime_len, key->sk, optrand, &p); + + zeromem(optrand, sizeof(optrand)); + XFREE(m_prime); + return err; +} + +/** + Verify a signature with SLH-DSA. + @param sig The signature to verify + @param siglen Length of the signature + @param msg The message that was signed + @param msglen Length of the message + @param ctx Optional context string (can be NULL if ctxlen is 0) + @param ctxlen Length of the context string (max 255 bytes per FIPS 205) + @param stat [out] Result of the verification: 1==valid, 0==invalid + @param key The public (verification) key + @return CRYPT_OK if successful (even if the signature is invalid) +*/ +int slhdsa_verify(const unsigned char *sig, unsigned long siglen, + const unsigned char *msg, unsigned long msglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const slhdsa_key *key) +{ + slhdsa_params p; + unsigned char *m_prime = NULL; + unsigned long m_prime_len; + int err; + + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(msg != NULL || msglen == 0); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + + *stat = 0; + + if (key->pk == NULL) return CRYPT_INVALID_ARG; + + if ((err = s_slhdsa_get_params(key->alg, &p)) != CRYPT_OK) return err; + + if ((err = s_slhdsa_prepare_message(&m_prime, &m_prime_len, + msg, msglen, ctx, ctxlen, key->alg)) != CRYPT_OK) { + return err; + } + + err = s_verify_core(sig, siglen, m_prime, m_prime_len, key->pk, &p); + XFREE(m_prime); + + if (err == CRYPT_OK) + *stat = 1; + else if (err == CRYPT_INVALID_PACKET) + err = CRYPT_OK; /* Verification failed but no internal error */ + + return err; +} + +/** + Get the sizes for a given SLH-DSA parameter set. + Any output pointer may be NULL if the caller does not need that value. + @param alg The parameter set (one of ltc_slhdsa_id) + @param public_key_sz [out] Public key size in bytes + @param secret_key_sz [out] Secret key size in bytes + @param signature_sz [out] Signature size in bytes + @return CRYPT_OK if successful +*/ +int slhdsa_get_sizes(int alg, unsigned long *public_key_sz, unsigned long *secret_key_sz, + unsigned long *signature_sz) +{ + slhdsa_params p; + int err; + + if ((err = s_slhdsa_get_params(alg, &p)) != CRYPT_OK) return err; + + if (public_key_sz != NULL) *public_key_sz = p.pk_bytes; + if (secret_key_sz != NULL) *secret_key_sz = p.sk_bytes; + if (signature_sz != NULL) *signature_sz = p.sig_bytes; + + return CRYPT_OK; +} + +#endif /* LTC_SLHDSA */ diff --git a/src/pqc/slhdsa_export.c b/src/pqc/slhdsa_export.c new file mode 100644 index 000000000..7db9ad899 --- /dev/null +++ b/src/pqc/slhdsa_export.c @@ -0,0 +1,160 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file slhdsa_export.c + Export a SLH-DSA key to a binary packet +*/ + +#ifdef LTC_SLHDSA + +static int s_slhdsa_alg_to_oid(int alg, enum ltc_oid_id *oid_id) +{ + LTC_ARGCHK(oid_id != NULL); + + switch (alg) { + case LTC_SLHDSA_SHA2_128S: + *oid_id = LTC_OID_SLHDSA_SHA2_128S; + return CRYPT_OK; + case LTC_SLHDSA_SHA2_128F: + *oid_id = LTC_OID_SLHDSA_SHA2_128F; + return CRYPT_OK; + case LTC_SLHDSA_SHA2_192S: + *oid_id = LTC_OID_SLHDSA_SHA2_192S; + return CRYPT_OK; + case LTC_SLHDSA_SHA2_192F: + *oid_id = LTC_OID_SLHDSA_SHA2_192F; + return CRYPT_OK; + case LTC_SLHDSA_SHA2_256S: + *oid_id = LTC_OID_SLHDSA_SHA2_256S; + return CRYPT_OK; + case LTC_SLHDSA_SHA2_256F: + *oid_id = LTC_OID_SLHDSA_SHA2_256F; + return CRYPT_OK; + case LTC_SLHDSA_SHAKE_128S: + *oid_id = LTC_OID_SLHDSA_SHAKE_128S; + return CRYPT_OK; + case LTC_SLHDSA_SHAKE_128F: + *oid_id = LTC_OID_SLHDSA_SHAKE_128F; + return CRYPT_OK; + case LTC_SLHDSA_SHAKE_192S: + *oid_id = LTC_OID_SLHDSA_SHAKE_192S; + return CRYPT_OK; + case LTC_SLHDSA_SHAKE_192F: + *oid_id = LTC_OID_SLHDSA_SHAKE_192F; + return CRYPT_OK; + case LTC_SLHDSA_SHAKE_256S: + *oid_id = LTC_OID_SLHDSA_SHAKE_256S; + return CRYPT_OK; + case LTC_SLHDSA_SHAKE_256F: + *oid_id = LTC_OID_SLHDSA_SHAKE_256F; + return CRYPT_OK; + case LTC_SLHDSA_HASH_SHA2_128S_WITH_SHA256: + *oid_id = LTC_OID_HASH_SLHDSA_SHA2_128S_WITH_SHA256; + return CRYPT_OK; + case LTC_SLHDSA_HASH_SHA2_128F_WITH_SHA256: + *oid_id = LTC_OID_HASH_SLHDSA_SHA2_128F_WITH_SHA256; + return CRYPT_OK; + case LTC_SLHDSA_HASH_SHA2_192S_WITH_SHA512: + *oid_id = LTC_OID_HASH_SLHDSA_SHA2_192S_WITH_SHA512; + return CRYPT_OK; + case LTC_SLHDSA_HASH_SHA2_192F_WITH_SHA512: + *oid_id = LTC_OID_HASH_SLHDSA_SHA2_192F_WITH_SHA512; + return CRYPT_OK; + case LTC_SLHDSA_HASH_SHA2_256S_WITH_SHA512: + *oid_id = LTC_OID_HASH_SLHDSA_SHA2_256S_WITH_SHA512; + return CRYPT_OK; + case LTC_SLHDSA_HASH_SHA2_256F_WITH_SHA512: + *oid_id = LTC_OID_HASH_SLHDSA_SHA2_256F_WITH_SHA512; + return CRYPT_OK; + case LTC_SLHDSA_HASH_SHAKE_128S_WITH_SHAKE128: + *oid_id = LTC_OID_HASH_SLHDSA_SHAKE_128S_WITH_SHAKE128; + return CRYPT_OK; + case LTC_SLHDSA_HASH_SHAKE_128F_WITH_SHAKE128: + *oid_id = LTC_OID_HASH_SLHDSA_SHAKE_128F_WITH_SHAKE128; + return CRYPT_OK; + case LTC_SLHDSA_HASH_SHAKE_192S_WITH_SHAKE256: + *oid_id = LTC_OID_HASH_SLHDSA_SHAKE_192S_WITH_SHAKE256; + return CRYPT_OK; + case LTC_SLHDSA_HASH_SHAKE_192F_WITH_SHAKE256: + *oid_id = LTC_OID_HASH_SLHDSA_SHAKE_192F_WITH_SHAKE256; + return CRYPT_OK; + case LTC_SLHDSA_HASH_SHAKE_256S_WITH_SHAKE256: + *oid_id = LTC_OID_HASH_SLHDSA_SHAKE_256S_WITH_SHAKE256; + return CRYPT_OK; + case LTC_SLHDSA_HASH_SHAKE_256F_WITH_SHAKE256: + *oid_id = LTC_OID_HASH_SLHDSA_SHAKE_256F_WITH_SHAKE256; + return CRYPT_OK; + default: + return CRYPT_PK_INVALID_TYPE; + } +} + +/** + Export a SLH-DSA key to a binary packet + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the SLH-DSA key + @param which Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int slhdsa_export(unsigned char *out, unsigned long *outlen, + int which, const slhdsa_key *key) +{ + int err, std; + enum ltc_oid_id oid_id; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + std = which & PK_STD; + which &= ~PK_STD; + + if ((err = s_slhdsa_alg_to_oid(key->alg, &oid_id)) != CRYPT_OK) { + return err; + } + + if (which == PK_PRIVATE) { + const char *OID; + unsigned long version, oid[16], oidlen; + ltc_asn1_list alg_id[1]; + + if (key->type != PK_PRIVATE || key->sk == NULL) return CRYPT_PK_INVALID_TYPE; + + if (std != PK_STD) { + return slhdsa_export_raw(out, outlen, which, key); + } + + if ((err = pk_get_oid(oid_id, &OID)) != CRYPT_OK) { + return err; + } + oidlen = LTC_ARRAY_SIZE(oid); + if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { + return err; + } + LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); + version = 0; + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1uL, &version, + LTC_ASN1_SEQUENCE, 1uL, alg_id, + LTC_ASN1_OCTET_STRING, key->sklen, key->sk, + LTC_ASN1_EOL, 0uL, NULL); + } + + if (which != PK_PUBLIC) { + return CRYPT_INVALID_ARG; + } + if (key->pk == NULL) return CRYPT_PK_INVALID_TYPE; + + if (std == PK_STD) { + return x509_encode_subject_public_key_info(out, outlen, oid_id, + key->pk, key->pklen, + LTC_ASN1_EOL, NULL, 0uL); + } + + return slhdsa_export_raw(out, outlen, which, key); +} + +#endif diff --git a/src/pqc/slhdsa_import.c b/src/pqc/slhdsa_import.c new file mode 100644 index 000000000..7b1256814 --- /dev/null +++ b/src/pqc/slhdsa_import.c @@ -0,0 +1,92 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file slhdsa_import.c + Import a SLH-DSA key from a SubjectPublicKeyInfo +*/ + +#ifdef LTC_SLHDSA + +typedef struct { + enum ltc_oid_id oid; + int alg; +} slhdsa_oid_map; + +static const slhdsa_oid_map s_slhdsa_oid_map[] = { + { LTC_OID_SLHDSA_SHA2_128S, LTC_SLHDSA_SHA2_128S }, + { LTC_OID_SLHDSA_SHA2_128F, LTC_SLHDSA_SHA2_128F }, + { LTC_OID_SLHDSA_SHA2_192S, LTC_SLHDSA_SHA2_192S }, + { LTC_OID_SLHDSA_SHA2_192F, LTC_SLHDSA_SHA2_192F }, + { LTC_OID_SLHDSA_SHA2_256S, LTC_SLHDSA_SHA2_256S }, + { LTC_OID_SLHDSA_SHA2_256F, LTC_SLHDSA_SHA2_256F }, + { LTC_OID_SLHDSA_SHAKE_128S, LTC_SLHDSA_SHAKE_128S }, + { LTC_OID_SLHDSA_SHAKE_128F, LTC_SLHDSA_SHAKE_128F }, + { LTC_OID_SLHDSA_SHAKE_192S, LTC_SLHDSA_SHAKE_192S }, + { LTC_OID_SLHDSA_SHAKE_192F, LTC_SLHDSA_SHAKE_192F }, + { LTC_OID_SLHDSA_SHAKE_256S, LTC_SLHDSA_SHAKE_256S }, + { LTC_OID_SLHDSA_SHAKE_256F, LTC_SLHDSA_SHAKE_256F }, + { LTC_OID_HASH_SLHDSA_SHA2_128S_WITH_SHA256, LTC_SLHDSA_HASH_SHA2_128S_WITH_SHA256 }, + { LTC_OID_HASH_SLHDSA_SHA2_128F_WITH_SHA256, LTC_SLHDSA_HASH_SHA2_128F_WITH_SHA256 }, + { LTC_OID_HASH_SLHDSA_SHA2_192S_WITH_SHA512, LTC_SLHDSA_HASH_SHA2_192S_WITH_SHA512 }, + { LTC_OID_HASH_SLHDSA_SHA2_192F_WITH_SHA512, LTC_SLHDSA_HASH_SHA2_192F_WITH_SHA512 }, + { LTC_OID_HASH_SLHDSA_SHA2_256S_WITH_SHA512, LTC_SLHDSA_HASH_SHA2_256S_WITH_SHA512 }, + { LTC_OID_HASH_SLHDSA_SHA2_256F_WITH_SHA512, LTC_SLHDSA_HASH_SHA2_256F_WITH_SHA512 }, + { LTC_OID_HASH_SLHDSA_SHAKE_128S_WITH_SHAKE128, LTC_SLHDSA_HASH_SHAKE_128S_WITH_SHAKE128 }, + { LTC_OID_HASH_SLHDSA_SHAKE_128F_WITH_SHAKE128, LTC_SLHDSA_HASH_SHAKE_128F_WITH_SHAKE128 }, + { LTC_OID_HASH_SLHDSA_SHAKE_192S_WITH_SHAKE256, LTC_SLHDSA_HASH_SHAKE_192S_WITH_SHAKE256 }, + { LTC_OID_HASH_SLHDSA_SHAKE_192F_WITH_SHAKE256, LTC_SLHDSA_HASH_SHAKE_192F_WITH_SHAKE256 }, + { LTC_OID_HASH_SLHDSA_SHAKE_256S_WITH_SHAKE256, LTC_SLHDSA_HASH_SHAKE_256S_WITH_SHAKE256 }, + { LTC_OID_HASH_SLHDSA_SHAKE_256F_WITH_SHAKE256, LTC_SLHDSA_HASH_SHAKE_256F_WITH_SHAKE256 }, +}; + +/** + Import a SLH-DSA public key + @param in The packet to read + @param inlen The length of the input packet + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int slhdsa_import(const unsigned char *in, unsigned long inlen, slhdsa_key *key) +{ + unsigned char *pub; + unsigned long max_pub_len, pub_len; + unsigned long i; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + max_pub_len = 0; + for (i = 0; i < LTC_ARRAY_SIZE(s_slhdsa_oid_map); ++i) { + if ((err = slhdsa_get_sizes(s_slhdsa_oid_map[i].alg, &pub_len, NULL, NULL)) != CRYPT_OK) { + return err; + } + if (pub_len > max_pub_len) { + max_pub_len = pub_len; + } + } + + pub = XMALLOC(max_pub_len); + if (pub == NULL) { + return CRYPT_MEM; + } + + err = CRYPT_PK_INVALID_TYPE; + for (i = 0; i < LTC_ARRAY_SIZE(s_slhdsa_oid_map); ++i) { + pub_len = max_pub_len; + err = x509_decode_subject_public_key_info(in, inlen, s_slhdsa_oid_map[i].oid, + pub, &pub_len, + LTC_ASN1_EOL, NULL, 0uL); + if (err == CRYPT_OK) { + err = slhdsa_import_raw(pub, pub_len, PK_PUBLIC, s_slhdsa_oid_map[i].alg, key); + break; + } + } + + XFREE(pub); + return err; +} + +#endif diff --git a/src/pqc/slhdsa_import_pkcs8.c b/src/pqc/slhdsa_import_pkcs8.c new file mode 100644 index 000000000..a69ce8c73 --- /dev/null +++ b/src/pqc/slhdsa_import_pkcs8.c @@ -0,0 +1,178 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file slhdsa_import_pkcs8.c + Import a SLH-DSA key in PKCS#8 format +*/ + +#ifdef LTC_SLHDSA + +static int s_slhdsa_oid_to_alg(enum ltc_oid_id oid_id, int *alg) +{ + LTC_ARGCHK(alg != NULL); + + switch (oid_id) { + case LTC_OID_SLHDSA_SHA2_128S: + *alg = LTC_SLHDSA_SHA2_128S; + return CRYPT_OK; + case LTC_OID_SLHDSA_SHA2_128F: + *alg = LTC_SLHDSA_SHA2_128F; + return CRYPT_OK; + case LTC_OID_SLHDSA_SHA2_192S: + *alg = LTC_SLHDSA_SHA2_192S; + return CRYPT_OK; + case LTC_OID_SLHDSA_SHA2_192F: + *alg = LTC_SLHDSA_SHA2_192F; + return CRYPT_OK; + case LTC_OID_SLHDSA_SHA2_256S: + *alg = LTC_SLHDSA_SHA2_256S; + return CRYPT_OK; + case LTC_OID_SLHDSA_SHA2_256F: + *alg = LTC_SLHDSA_SHA2_256F; + return CRYPT_OK; + case LTC_OID_SLHDSA_SHAKE_128S: + *alg = LTC_SLHDSA_SHAKE_128S; + return CRYPT_OK; + case LTC_OID_SLHDSA_SHAKE_128F: + *alg = LTC_SLHDSA_SHAKE_128F; + return CRYPT_OK; + case LTC_OID_SLHDSA_SHAKE_192S: + *alg = LTC_SLHDSA_SHAKE_192S; + return CRYPT_OK; + case LTC_OID_SLHDSA_SHAKE_192F: + *alg = LTC_SLHDSA_SHAKE_192F; + return CRYPT_OK; + case LTC_OID_SLHDSA_SHAKE_256S: + *alg = LTC_SLHDSA_SHAKE_256S; + return CRYPT_OK; + case LTC_OID_SLHDSA_SHAKE_256F: + *alg = LTC_SLHDSA_SHAKE_256F; + return CRYPT_OK; + case LTC_OID_HASH_SLHDSA_SHA2_128S_WITH_SHA256: + *alg = LTC_SLHDSA_HASH_SHA2_128S_WITH_SHA256; + return CRYPT_OK; + case LTC_OID_HASH_SLHDSA_SHA2_128F_WITH_SHA256: + *alg = LTC_SLHDSA_HASH_SHA2_128F_WITH_SHA256; + return CRYPT_OK; + case LTC_OID_HASH_SLHDSA_SHA2_192S_WITH_SHA512: + *alg = LTC_SLHDSA_HASH_SHA2_192S_WITH_SHA512; + return CRYPT_OK; + case LTC_OID_HASH_SLHDSA_SHA2_192F_WITH_SHA512: + *alg = LTC_SLHDSA_HASH_SHA2_192F_WITH_SHA512; + return CRYPT_OK; + case LTC_OID_HASH_SLHDSA_SHA2_256S_WITH_SHA512: + *alg = LTC_SLHDSA_HASH_SHA2_256S_WITH_SHA512; + return CRYPT_OK; + case LTC_OID_HASH_SLHDSA_SHA2_256F_WITH_SHA512: + *alg = LTC_SLHDSA_HASH_SHA2_256F_WITH_SHA512; + return CRYPT_OK; + case LTC_OID_HASH_SLHDSA_SHAKE_128S_WITH_SHAKE128: + *alg = LTC_SLHDSA_HASH_SHAKE_128S_WITH_SHAKE128; + return CRYPT_OK; + case LTC_OID_HASH_SLHDSA_SHAKE_128F_WITH_SHAKE128: + *alg = LTC_SLHDSA_HASH_SHAKE_128F_WITH_SHAKE128; + return CRYPT_OK; + case LTC_OID_HASH_SLHDSA_SHAKE_192S_WITH_SHAKE256: + *alg = LTC_SLHDSA_HASH_SHAKE_192S_WITH_SHAKE256; + return CRYPT_OK; + case LTC_OID_HASH_SLHDSA_SHAKE_192F_WITH_SHAKE256: + *alg = LTC_SLHDSA_HASH_SHAKE_192F_WITH_SHAKE256; + return CRYPT_OK; + case LTC_OID_HASH_SLHDSA_SHAKE_256S_WITH_SHAKE256: + *alg = LTC_SLHDSA_HASH_SHAKE_256S_WITH_SHAKE256; + return CRYPT_OK; + case LTC_OID_HASH_SLHDSA_SHAKE_256F_WITH_SHAKE256: + *alg = LTC_SLHDSA_HASH_SHAKE_256F_WITH_SHAKE256; + return CRYPT_OK; + default: + return CRYPT_PK_INVALID_TYPE; + } +} + +int slhdsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, slhdsa_key *key) +{ + enum ltc_oid_id oid_id; + int alg, err; + unsigned char *raw_buf = NULL; + unsigned long key_len, raw_buf_len; + + LTC_ARGCHK(alg_id != NULL); + LTC_ARGCHK(priv_key != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = pk_get_oid_from_asn1(alg_id->child, &oid_id)) != CRYPT_OK) { + return err; + } + if ((err = s_slhdsa_oid_to_alg(oid_id, &alg)) != CRYPT_OK) { + return err; + } + + if ((err = slhdsa_get_sizes(alg, NULL, &key_len, NULL)) != CRYPT_OK) { + return err; + } + if (priv_key->size == key_len) { + return slhdsa_import_raw(priv_key->data, priv_key->size, PK_PRIVATE, alg, key); + } + + raw_buf = XMALLOC(key_len); + if (raw_buf == NULL) { + return CRYPT_MEM; + } + raw_buf_len = key_len; + err = der_decode_octet_string(priv_key->data, priv_key->size, raw_buf, &raw_buf_len); + if (err == CRYPT_OK) { + err = (raw_buf_len == key_len) + ? slhdsa_import_raw(raw_buf, raw_buf_len, PK_PRIVATE, alg, key) + : CRYPT_INVALID_PACKET; + } + XFREE(raw_buf); + if (err != CRYPT_OK) { + return err; + } + + return CRYPT_OK; +} + +/** + Import a SLH-DSA private key in PKCS#8 format + @param in The packet to import from + @param inlen It's length (octets) + @param pw_ctx The password context when decrypting the private key + @param key [out] Destination for newly imported key + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int slhdsa_import_pkcs8(const unsigned char *in, unsigned long inlen, const password_ctx *pw_ctx, slhdsa_key *key) +{ + int alg, err; + ltc_asn1_list *l = NULL; + ltc_asn1_list *alg_id, *priv_key; + enum ltc_oid_id oid_id; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l); + if (err != CRYPT_OK) { + return err; + } + + if ((err = pkcs8_get_children(l, &oid_id, &alg_id, &priv_key)) != CRYPT_OK) { + goto cleanup; + } + err = s_slhdsa_oid_to_alg(oid_id, &alg); + if (err != CRYPT_OK) { + err = CRYPT_INVALID_PACKET; + goto cleanup; + } + LTC_UNUSED_PARAM(alg); + + err = slhdsa_import_pkcs8_asn1(alg_id, priv_key, key); + +cleanup: + der_free_sequence_flexi(l); + return err; +} + +#endif diff --git a/src/pqc/slhdsa_import_x509.c b/src/pqc/slhdsa_import_x509.c new file mode 100644 index 000000000..52d48911e --- /dev/null +++ b/src/pqc/slhdsa_import_x509.c @@ -0,0 +1,86 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file slhdsa_import_x509.c + Import a SLH-DSA key from a X.509 certificate +*/ + +#ifdef LTC_SLHDSA + +typedef struct { + slhdsa_key *key; + int alg; +} slhdsa_x509_ctx; + +typedef struct { + enum ltc_oid_id oid; + int alg; +} slhdsa_oid_map_x509; + +static const slhdsa_oid_map_x509 s_slhdsa_oid_map_x509[] = { + { LTC_OID_SLHDSA_SHA2_128S, LTC_SLHDSA_SHA2_128S }, + { LTC_OID_SLHDSA_SHA2_128F, LTC_SLHDSA_SHA2_128F }, + { LTC_OID_SLHDSA_SHA2_192S, LTC_SLHDSA_SHA2_192S }, + { LTC_OID_SLHDSA_SHA2_192F, LTC_SLHDSA_SHA2_192F }, + { LTC_OID_SLHDSA_SHA2_256S, LTC_SLHDSA_SHA2_256S }, + { LTC_OID_SLHDSA_SHA2_256F, LTC_SLHDSA_SHA2_256F }, + { LTC_OID_SLHDSA_SHAKE_128S, LTC_SLHDSA_SHAKE_128S }, + { LTC_OID_SLHDSA_SHAKE_128F, LTC_SLHDSA_SHAKE_128F }, + { LTC_OID_SLHDSA_SHAKE_192S, LTC_SLHDSA_SHAKE_192S }, + { LTC_OID_SLHDSA_SHAKE_192F, LTC_SLHDSA_SHAKE_192F }, + { LTC_OID_SLHDSA_SHAKE_256S, LTC_SLHDSA_SHAKE_256S }, + { LTC_OID_SLHDSA_SHAKE_256F, LTC_SLHDSA_SHAKE_256F }, + { LTC_OID_HASH_SLHDSA_SHA2_128S_WITH_SHA256, LTC_SLHDSA_HASH_SHA2_128S_WITH_SHA256 }, + { LTC_OID_HASH_SLHDSA_SHA2_128F_WITH_SHA256, LTC_SLHDSA_HASH_SHA2_128F_WITH_SHA256 }, + { LTC_OID_HASH_SLHDSA_SHA2_192S_WITH_SHA512, LTC_SLHDSA_HASH_SHA2_192S_WITH_SHA512 }, + { LTC_OID_HASH_SLHDSA_SHA2_192F_WITH_SHA512, LTC_SLHDSA_HASH_SHA2_192F_WITH_SHA512 }, + { LTC_OID_HASH_SLHDSA_SHA2_256S_WITH_SHA512, LTC_SLHDSA_HASH_SHA2_256S_WITH_SHA512 }, + { LTC_OID_HASH_SLHDSA_SHA2_256F_WITH_SHA512, LTC_SLHDSA_HASH_SHA2_256F_WITH_SHA512 }, + { LTC_OID_HASH_SLHDSA_SHAKE_128S_WITH_SHAKE128, LTC_SLHDSA_HASH_SHAKE_128S_WITH_SHAKE128 }, + { LTC_OID_HASH_SLHDSA_SHAKE_128F_WITH_SHAKE128, LTC_SLHDSA_HASH_SHAKE_128F_WITH_SHAKE128 }, + { LTC_OID_HASH_SLHDSA_SHAKE_192S_WITH_SHAKE256, LTC_SLHDSA_HASH_SHAKE_192S_WITH_SHAKE256 }, + { LTC_OID_HASH_SLHDSA_SHAKE_192F_WITH_SHAKE256, LTC_SLHDSA_HASH_SHAKE_192F_WITH_SHAKE256 }, + { LTC_OID_HASH_SLHDSA_SHAKE_256S_WITH_SHAKE256, LTC_SLHDSA_HASH_SHAKE_256S_WITH_SHAKE256 }, + { LTC_OID_HASH_SLHDSA_SHAKE_256F_WITH_SHAKE256, LTC_SLHDSA_HASH_SHAKE_256F_WITH_SHAKE256 }, +}; + +static int s_slhdsa_decode(const unsigned char *in, unsigned long inlen, slhdsa_x509_ctx *ctx) +{ + return slhdsa_import_raw(in, inlen, PK_PUBLIC, ctx->alg, ctx->key); +} + +/** + Import a SLH-DSA public key from a X.509 certificate + @param in The DER encoded X.509 certificate + @param inlen The length of the certificate + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int slhdsa_import_x509(const unsigned char *in, unsigned long inlen, slhdsa_key *key) +{ + slhdsa_x509_ctx ctx; + unsigned long i; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + err = CRYPT_PK_INVALID_TYPE; + for (i = 0; i < LTC_ARRAY_SIZE(s_slhdsa_oid_map_x509); ++i) { + ctx.key = key; + ctx.alg = s_slhdsa_oid_map_x509[i].alg; + err = x509_decode_public_key_from_certificate(in, inlen, + s_slhdsa_oid_map_x509[i].oid, + LTC_ASN1_EOL, NULL, NULL, + (public_key_decode_cb)s_slhdsa_decode, &ctx); + if (err == CRYPT_OK) { + break; + } + } + + return err; +} + +#endif diff --git a/tests/pem/openssl_ML-DSA-44_pk.pem b/tests/pem/openssl_ML-DSA-44_pk.pem new file mode 100644 index 000000000..7d3ff6b1a --- /dev/null +++ b/tests/pem/openssl_ML-DSA-44_pk.pem @@ -0,0 +1,30 @@ +-----BEGIN PUBLIC KEY----- +MIIFMjALBglghkgBZQMEAxEDggUhAFZG+tnmR+uk5xEaWOY2EDZmyXmaE7Slm+a0 +6n7QORNU67wsvlG46MI3TdeoaOJSaU9afU4PEMt4C0+ILS0hjQq4mP+pGJ6MgYLw +zo/DhE/34T0iRASnDe3sdhUajX93kB8hUNTHwwNXkH7qdFeUioTUMy0JNRkuM25o +O+hIO5DhK5FwXR+i3CFnqu8Y1mL75AOpNSdIJoQ4lAmOKeM0l/CyvMZrE9AvlKpZ +NUG4GnmJ1bBTU5eG1CytFZZi4B9HeV0gr2CE/kOpq0mDb2wstKbQO+A/IIPC75B3 +pcL7qi15zAfobIp9tA/2WKOZ0I/6PfDkRO1KhaRB6WOLvlHIzGFSGdNd7jvGfHnm +RWZPRxcDi9v/1UCYGXGncyHeMX/mvhDROJ8bWWv8RYbXrrzej5djm6c1QYMeK4pd +4n+vhekvZaxuc72SFl7SV5MT3DqpnJknDXthvu/W7DwwMGjqW2q05TJqqzvDhBOU +e+GaHEOZTCJ5e9oM4fWb91TesajETW/erDJ7L7hJxYBMdq944WjiW5PzCIRuZe6y +WUaXABJmuVNTTxyhPonstSEJEiPyTHB/yml1jrAppK9ZS1g41fEY2S642sESuG7a +X4UfUXV//uT+4IrdSGZ4vxzny2T2FxA9XJ6KYZ2l3loS3xUzSWyl2sOITn3dcZh0 +TuQEhAOpfoWxaFlnnRKldvOqtJ5DfuJv7jUTX5g5qa0hesW54cpfxbTv7JOUAVFT +8wdo9U8LH2us/fbl0oHWsYdJDqgA77QrwO8xy+O8Bi18JdLnkrSEwwAQzrmJ/aFI +NhPmAY2w9ZYPEk4EFv7ODW8ZA1xMpSiV5rDwgwNO8eevn/crb57gone11RiIuUka +LUxCMr9zueZ44ifyMmfSuf3gZgQD9GO18CmgYGzdNytxkUatrvhPzVu3LpZ8G0qg +BB109yjf7nhbXTMxD2N3bkLMWA8e68uh3kfimpA0SMfSXS1ehwP/vPYTUXamF7KH +a1Io0O1ukiuIPNy2LAvQLGjPplSDrhKjhPZB748xRwHxWzXtXL/vcBnFn8NnG+w4 +ONIj8kTDI5Lt32i6or7QWLxQ+H1V3hpDimj3Qj7kuuRwstvf0dxJxwJl3O+A0NsE +TZfcKXExYnl27O+psxeYtTveAIjqZdmvOQonQRXrzWlb8uinz9046WlCZRUxwr6L +9mrfDXLoQ4Wd2q0m9Yz5yPS9FArPyi/VYYf83sPnwwiY0hmQ+9com92u5/yEYE6f +DV337TQqe/DDZhz3M/bzJAjRKFZxhkZoQ1Ya8tn/LU9//hpI/NM0hWPArhSnG4RZ +5MTzsX42swq/eFKBTyeZ9hQdWnuPEujUxYFB+UBxrsm7OXYFkIb/8GE7J+d+5Av0 +wJYB8D7qJ7ulJaSOkXhrVgBcMd97Eb0EfPJBRyREc2wFR0KhYWD6PuQrfrppwHhO +366djWJU0Rtpe3doYbP4a8XArcm1ceoQrjkSsABT1fSJtYkCIHPxhypzuaKvSPdE +yUyjeSh0+i0cb2UjpLE/XiGhALpn56BL/AfUhrqYlroLf1Ptpqsgd+xwaA4LMQ/G +SRH5oyxddPwN6grNQSEcekAXdsPHfmyIedRWGMNkadfI351AhE4xtSxBeoDO5ELq +PhfKMhu5s43TxbzeyNML12Mlhb+1koNFhfi/0WL4dkqovAS5NKStZOZxzCCDqERh +1rdTOHRSXcSFsDrRlVt05gcWJqlw2cjg6JaccUUNaECLyKBhJbY= +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_ML-DSA-44_sk.pem b/tests/pem/openssl_ML-DSA-44_sk.pem new file mode 100644 index 000000000..69c08c8c9 --- /dev/null +++ b/tests/pem/openssl_ML-DSA-44_sk.pem @@ -0,0 +1,57 @@ +-----BEGIN PRIVATE KEY----- +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 +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_ML-DSA-44_x509.pem b/tests/pem/openssl_ML-DSA-44_x509.pem new file mode 100644 index 000000000..831b06286 --- /dev/null +++ b/tests/pem/openssl_ML-DSA-44_x509.pem @@ -0,0 +1,85 @@ +-----BEGIN CERTIFICATE----- +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 +AAAAABUoNkA= +-----END CERTIFICATE----- diff --git a/tests/pem/openssl_ML-DSA-65_pk.pem b/tests/pem/openssl_ML-DSA-65_pk.pem new file mode 100644 index 000000000..73efba05d --- /dev/null +++ b/tests/pem/openssl_ML-DSA-65_pk.pem @@ -0,0 +1,44 @@ +-----BEGIN PUBLIC KEY----- +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 +F2shVx5s +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_ML-DSA-65_sk.pem b/tests/pem/openssl_ML-DSA-65_sk.pem new file mode 100644 index 000000000..79d16aa83 --- /dev/null +++ b/tests/pem/openssl_ML-DSA-65_sk.pem @@ -0,0 +1,88 @@ +-----BEGIN PRIVATE KEY----- +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 +YNHz506CNXEWxqm0vDoPx0l/ +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_ML-DSA-65_x509.pem b/tests/pem/openssl_ML-DSA-65_x509.pem new file mode 100644 index 000000000..e9def5b5f --- /dev/null +++ b/tests/pem/openssl_ML-DSA-65_x509.pem @@ -0,0 +1,117 @@ +-----BEGIN CERTIFICATE----- +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 +Gg== +-----END CERTIFICATE----- diff --git a/tests/pem/openssl_ML-DSA-87_pk.pem b/tests/pem/openssl_ML-DSA-87_pk.pem new file mode 100644 index 000000000..48fec3a48 --- /dev/null +++ b/tests/pem/openssl_ML-DSA-87_pk.pem @@ -0,0 +1,57 @@ +-----BEGIN PUBLIC KEY----- +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 +huT6X1dJIIVKkrPgKeTJqeUlW3317g== +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_ML-DSA-87_sk.pem b/tests/pem/openssl_ML-DSA-87_sk.pem new file mode 100644 index 000000000..b59bef518 --- /dev/null +++ b/tests/pem/openssl_ML-DSA-87_sk.pem @@ -0,0 +1,106 @@ +-----BEGIN PRIVATE KEY----- +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 +0WLBwubkJ64Ilb/qv20O9j1X +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_ML-DSA-87_x509.pem b/tests/pem/openssl_ML-DSA-87_x509.pem new file mode 100644 index 000000000..4dbe932f2 --- /dev/null +++ b/tests/pem/openssl_ML-DSA-87_x509.pem @@ -0,0 +1,157 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/tests/pem/openssl_ML-KEM-1024_pk.pem b/tests/pem/openssl_ML-KEM-1024_pk.pem new file mode 100644 index 000000000..96dabf00a --- /dev/null +++ b/tests/pem/openssl_ML-KEM-1024_pk.pem @@ -0,0 +1,36 @@ +-----BEGIN PUBLIC KEY----- +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 +Q0jH8ACP +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_ML-KEM-1024_sk.pem b/tests/pem/openssl_ML-KEM-1024_sk.pem new file mode 100644 index 000000000..565883d0d --- /dev/null +++ b/tests/pem/openssl_ML-KEM-1024_sk.pem @@ -0,0 +1,71 @@ +-----BEGIN PRIVATE KEY----- +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 +nos= +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_ML-KEM-512_pk.pem b/tests/pem/openssl_ML-KEM-512_pk.pem new file mode 100644 index 000000000..4c7c6aabb --- /dev/null +++ b/tests/pem/openssl_ML-KEM-512_pk.pem @@ -0,0 +1,20 @@ +-----BEGIN PUBLIC KEY----- +MIIDMjALBglghkgBZQMEBAEDggMhAKc8U5shf746BkXmGeO4mi67hTkVnVMnC328 +oC7it2unroFHjNm3JQshppVRFXACwQBqrwwQDS7mtvPsTW7Kn7kXMwz8TMN5dkUL +AxeyGX5VeYWLsVNyGNmxXYB5IXkKVZb1sNqECCTrenG1Ph4LiivqGCDIXWMDD5k2 +WxfqEmZZFOHhkqxLMbL6tb9ppcmqa8krPLUGEOpKCujlC/ApGPNaCv01iP23N/vF +IM7JKhOFWb/SLGUhEWRrXuV7mmWYLS9mOdKxDf4liS8bJOO1PIcSwvECUNyKZuyw +KC9FX/q3NfHJX4CGn45gNX7jfJVQJEwQc92liWN4m7tHdl1Dk26pq3ohR0f0TaCg +L1qXm44sAScZO8kFktYcTDyyZt6EibmsDzcqoqimBrwHmfWhvuz2rmRpfgNWIix0 +DeRLDkUKtccnhxtamU3kRMUsWykDtbxVPx/ZTbNQN0KQmqfABy1TTTOALGkKMBkl +xDTDeFDIvUO4Nd7EFKB2DnkwvfI1KPzCdXM5qYJnAeWiyxxzp81iMjfzJFWTwAzr +dPSjoTrGJt/za1sgRkPwKCoCXJuHgmZUyjb3tgsyR150V7oSjv6hkHJbpmOYoF2l +KyyUWc8bXzgQGjXzsT9cPONMgTg1MXYHYKhUExXzHDUUYTPVn+mafuHTu+8sV+fA +KpSQCiZhaq53yWxQqLXGVaLUMTBBjHIrtmbKNoX7GsV4u9swV4dYIGXzq4H1EPTs +EsZUCfvKZZ7oB2K4U6o7H1BgrfBIYetnRP2AwtyZBoI4sCWKr54idywosPQwM7fG +LBeiur4Mp6h1a7OVk/PAzePAcQhGgOJhmFiQRH1VM2ronB2nTynpA+yJG0lSPgTG +QbTCXlEGQmrQMmQUIxUrVUnEuchZfK8IfNC6GDsHG0nEIBeaU0tzUe1Ax3tXyjqM +AT87G0SRS2/cDxxYFL7hkLn6caBwQIMjmbBUG6oas7bqNJzSmd9yXGjbjD64wL1n +Wn8SM0ZoeYKYNcujovRcHB62EKuxBBlXF6WvCfzv4dsOcFPHz5nvy/0noqP+gYgD +ZWK2kteu +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_ML-KEM-512_sk.pem b/tests/pem/openssl_ML-KEM-512_sk.pem new file mode 100644 index 000000000..a88b1918b --- /dev/null +++ b/tests/pem/openssl_ML-KEM-512_sk.pem @@ -0,0 +1,39 @@ +-----BEGIN PRIVATE KEY----- +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 +kXk= +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_ML-KEM-768_pk.pem b/tests/pem/openssl_ML-KEM-768_pk.pem new file mode 100644 index 000000000..ec1aa7b36 --- /dev/null +++ b/tests/pem/openssl_ML-KEM-768_pk.pem @@ -0,0 +1,28 @@ +-----BEGIN PUBLIC KEY----- +MIIEsjALBglghkgBZQMEBAIDggShAG3kjC6FUbdBreYhT/akPKJwdJzkRkzHFzgM +QqU1NBIhPoDFBe0Loj4GE697jp0KF3YIMamVsrMzorS4FJgnwIxDRAGDEHPbFq7n +D1iEor9BdLIVABAhkWFUJW8oBgAzXkycbLbjTt9QIGlaURtra+eKIG83vfEbhptW +jp5kJp06VMMRY7XzGTMmAEOzqvurNotGR2hKIMdrpvbXI31brIg8NysbUQHaIFbA +Sh9hN/zXwmqWXHmByBm1sTh2hmp6v7pSIkvgTIw2sRLLYHOJYlz6bm7GQMyiatDI +OJH7MSsEV4dzMcErmFAzTdWKKaa1Ko+iDtmBMUcFgy1VgekKl11KAxtVXcP0EYk1 +nU2YHs53a7lyjQ6Jt4mrbR4jWUiWHC5lKg/qzIUrBJZpEz0XJcIVCBqaFaPUacj0 +wq0anDwjVzBmbK6qoFeBOsaUTpd4hhgCqJiRE0C7k5MilC16VLKxkRHnyPH4LMja +CJmIkatLXJ1mW97JWDRnrGE8Gr98BfiCD30UYNdFwpkCuspqnQopnz9Br+NMVecV +Ul7qyNPng23qIRsbAwh8tOjimxdCj8Ybr76iulVExbuGx3kJmWmUA4fzF/RCSw+2 +MMJkLCGMGEXKU3EaY3fWOz7cSKbrqmKhQW2qosRFjBzIJY4kwHqSwuv5r5Mnw1OA +IEA8coUTIDXYt7lHvPq6u2kwBkpAAlzVRrr2ngrxl9khlM2VBW8bEq/qzBO3Ywbk +wz6mbo6aspgmHTKmlPYTOAaVhuUztehze7gIWeG3Ww+iydJ5EiMFvOuJv4jSXSz1 +Inoltf8lXDvyxhK8DnJ2KvZorYRrHFYgrIqkfZLYYkgKTgUyrFdXVqtihRDzI1P5 +zhWyMLPEfoK2pI2IJU7EnL1cBrLFJKp7yA4AzsynZwhUtT+Uuyl4lTKpZWugCVWC +NGJ7n6dKUmrlkXcWj+ToDooCB0lpkk2owiwrYHIbIucaWzDAKJw3g8tnsgw8hqGM +bqLimUqiBRTykIeiJB5TtNtEQBQ1RZoCwLxcGbEEw89wLTDSsRrpAoCss1bny14C +prmMGOU5hAITlqyli/W5iVtoVcDkvad1nPISY7wJrMRkVrOnyk3aXLFbYyCzHYui +IBshYeRGJFhKy1pwctokSxscMjPAhau1T5PUF+C7FpNLk/8Se0XpyvV0YGDzkUTM +XoP8RD9WSQLrBU57UDy1h1lcGKBmRXvFic4mU/tSjmjMhX6YLRHIZKB2TG9yHmCF +S0oMsz3lSooKyQtzDbm0O0m0L7ySfA6iOTQEk/dJjsbGPqz1r/Ixl1W4secKWhtH +giI4zfvYuh6XWWzgFKBCjKShkCYTgINEAJPwfSMJK0ppX8wwS5qHUFyIqgcDaGYi +VF1ZNaO8HGpxIuW3ozxGmbtgtddprOvgahsotsVlK3OQyrebH+8TDG/VC2O6bMiC +LsSwoMWgD+jHos0JAUwkY2tokKoGUPDEMCp6uhUKH1bgErEhhrSDyKrkAiEHJzMT +IGO0MdvovPX0idGBvLfBziSZfxOYdQnj413yvAembdusFV0RkuXy3KCDVJYGYVv1 +Vy6xEkvF +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_ML-KEM-768_sk.pem b/tests/pem/openssl_ML-KEM-768_sk.pem new file mode 100644 index 000000000..8425ba73f --- /dev/null +++ b/tests/pem/openssl_ML-KEM-768_sk.pem @@ -0,0 +1,55 @@ +-----BEGIN PRIVATE KEY----- +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 +4KA= +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-128f_pk.pem b/tests/pem/openssl_SLH-DSA-SHA2-128f_pk.pem new file mode 100644 index 000000000..65c7b766a --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-128f_pk.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MDAwCwYJYIZIAWUDBAMVAyEA0RtPrNG/pSj+lH+XYkQMfPYfKuunCr0fq5uRnGv4 +SOU= +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-128f_sk.pem b/tests/pem/openssl_SLH-DSA-SHA2-128f_sk.pem new file mode 100644 index 000000000..aa88ac0cb --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-128f_sk.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MFICAQAwCwYJYIZIAWUDBAMVBEA1lg4CCurnTC94IstEyqr2rle53arfbjKJhKZs +FBn2oNEbT6zRv6Uo/pR/l2JEDHz2Hyrrpwq9H6ubkZxr+Ejl +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-128f_x509.pem b/tests/pem/openssl_SLH-DSA-SHA2-128f_x509.pem new file mode 100644 index 000000000..4f3d39815 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-128f_x509.pem @@ -0,0 +1,363 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-128s_pk.pem b/tests/pem/openssl_SLH-DSA-SHA2-128s_pk.pem new file mode 100644 index 000000000..459593b69 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-128s_pk.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MDAwCwYJYIZIAWUDBAMUAyEAueNkSlUIUcv2YcDL1avShv6Dr9L+YYLSVDu3uvb1 +Jwk= +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-128s_sk.pem b/tests/pem/openssl_SLH-DSA-SHA2-128s_sk.pem new file mode 100644 index 000000000..23f609b66 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-128s_sk.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MFICAQAwCwYJYIZIAWUDBAMUBEBgZT7mw3+QfGFarrsdPPcuUeqzs1MGILndoOXP +FLpS8bnjZEpVCFHL9mHAy9Wr0ob+g6/S/mGC0lQ7t7r29ScJ +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-128s_x509.pem b/tests/pem/openssl_SLH-DSA-SHA2-128s_x509.pem new file mode 100644 index 000000000..cdb36eecb --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-128s_x509.pem @@ -0,0 +1,171 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-192f_pk.pem b/tests/pem/openssl_SLH-DSA-SHA2-192f_pk.pem new file mode 100644 index 000000000..2e1dbed56 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-192f_pk.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEAwCwYJYIZIAWUDBAMXAzEA2zkbAGFMYUgjTniq9wHHOtkNNMy/st4bpj7czk3+ +pSLhf0/BvidnnCbwzOk+Ry4i +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-192f_sk.pem b/tests/pem/openssl_SLH-DSA-SHA2-192f_sk.pem new file mode 100644 index 000000000..0d60b8fa7 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-192f_sk.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MHICAQAwCwYJYIZIAWUDBAMXBGBAEsQTugRaD9VO7wExjzcYXO4HdV3cwLSMLV/m +H3ldQUFbG4efpVdp2evkUlke0zXbORsAYUxhSCNOeKr3Acc62Q00zL+y3humPtzO +Tf6lIuF/T8G+J2ecJvDM6T5HLiI= +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-192f_x509.pem b/tests/pem/openssl_SLH-DSA-SHA2-192f_x509.pem new file mode 100644 index 000000000..d857e7a81 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-192f_x509.pem @@ -0,0 +1,751 @@ +-----BEGIN CERTIFICATE----- +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 +FE0TtbTjZglDT5lA6EVo +-----END CERTIFICATE----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-192s_pk.pem b/tests/pem/openssl_SLH-DSA-SHA2-192s_pk.pem new file mode 100644 index 000000000..03c5763b0 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-192s_pk.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEAwCwYJYIZIAWUDBAMWAzEAro8jyREeOprwVhevuAEXGSTP2zhCXv1EBvL7+bKa +xHXtiAwCs6/dJgqLRwKFDDxA +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-192s_sk.pem b/tests/pem/openssl_SLH-DSA-SHA2-192s_sk.pem new file mode 100644 index 000000000..3c5bd0f7b --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-192s_sk.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MHICAQAwCwYJYIZIAWUDBAMWBGAdRzeipR0t1igxK/zxNFW0o+oF2bJlsM723nhY +/t88XO/B0638T2JCGyE6KncNui+ujyPJER46mvBWF6+4ARcZJM/bOEJe/UQG8vv5 +sprEde2IDAKzr90mCotHAoUMPEA= +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-192s_x509.pem b/tests/pem/openssl_SLH-DSA-SHA2-192s_x509.pem new file mode 100644 index 000000000..0dfb0d2cd --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-192s_x509.pem @@ -0,0 +1,346 @@ +-----BEGIN CERTIFICATE----- +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 +TuVM7r0BjpnRHmKqOQOn +-----END CERTIFICATE----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-256f_pk.pem b/tests/pem/openssl_SLH-DSA-SHA2-256f_pk.pem new file mode 100644 index 000000000..ef0ecda99 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-256f_pk.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFAwCwYJYIZIAWUDBAMZA0EA753F2qJlsmSZqFAYFoZmVXU0VjUPkufuikUBaWj1 +T2OvhoRswcZyj0b2YhOeGBM0rb7/AR+uFxCd04ms3d9EPQ== +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-256f_sk.pem b/tests/pem/openssl_SLH-DSA-SHA2-256f_sk.pem new file mode 100644 index 000000000..a9e195551 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-256f_sk.pem @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIGTAgEAMAsGCWCGSAFlAwQDGQSBgPiFpG7nIWOA1u3W+JPiWedAMIZyfbJoq6g/ +um+1GeI9lVVTQdR4/KqRTmx5IUZUKFeymXRMt/FePp+Ex7u8xZjvncXaomWyZJmo +UBgWhmZVdTRWNQ+S5+6KRQFpaPVPY6+GhGzBxnKPRvZiE54YEzStvv8BH64XEJ3T +iazd30Q9 +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-256f_x509.pem b/tests/pem/openssl_SLH-DSA-SHA2-256f_x509.pem new file mode 100644 index 000000000..a263017c3 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-256f_x509.pem @@ -0,0 +1,1047 @@ +-----BEGIN CERTIFICATE----- +MILDyzCB9qADAgECAhQd3F8DhoiBOxG/j/ar9G7cHkpMJTALBglghkgBZQMEAxkw +ETEPMA0GA1UEAwwGQ3J5cHRYMCAXDTI2MDQxNDE2MTUxOVoYDzIzMDAwMTI3MTYx +NTE5WjARMQ8wDQYDVQQDDAZDcnlwdFgwUDALBglghkgBZQMEAxkDQQDvncXaomWy +ZJmoUBgWhmZVdTRWNQ+S5+6KRQFpaPVPY6+GhGzBxnKPRvZiE54YEzStvv8BH64X +EJ3Tiazd30Q9ozIwMDAdBgNVHQ4EFgQUiQHeNBbFMUJel4NSeQQd8qfpptwwDwYD +VR0TAQH/BAUwAwEB/zALBglghkgBZQMEAxkDgsLBAC2aZ+lZnP4/fVjYnGNEI0Do +0Sj0TsKSlJKPCD5oUpQCF3AYJ9JcxXB+oKhDf+EHlFXRl8w1/hDK6IkTBBZqG9H+ +CvMLUN0CCrq9KDBnfbh6c0o3iJ2jRiFUFpeij0Xic14GLIcy9WPrsyLW1PYigN0a +KG1p9T4WY0zPEwYY29sGmL4bFh5/Bv3D30p5D91ZqI6AI/8kup/vueOxK2LUWDni +OJH21QRblaSlpMnTIjY8VPWUD/zBCC1DMeuh2kmwOEOr6vF/tc8S+QWsD4s7MLVq +PpcJEhnYJv/OUPz1alEbl/C3FDy292UqQER3FCm9FBFOTLsQld1CotLz2pM6ThP0 +xIGEi8O3IlgAsg3yBzC5hD4nMd5XEGuRs6S851B/EeND6x4lvs5vEmPXc+u+B7Ri +J8tG9d/NFDcpKofUGa+prNXO+0Ie0DhjcDEDYm8Gao/KXXUGrSO8Ulp6E3XM9oCK +P+oEXJhrv7yyxpQvlTixKYIuOd+Gh5ensCMr/atT/yoIWMcU0H+g2zBK/NGShuOf +DteLXi8k1rp0dEIfMeKAmFsh3CZtbRSZp50mmL5imFVbZ8Hm94n7qnRnxOX4wH1p +BcVrR9hI86xgj509hLdiUuHU04LAq1L7ozm8/dPJ8h8LfY1nZVE0CNl3B0QJedrO +LD8gQdOUMCOGGO5QORrzt2vkNN+VHLctJQcZHMozq4fOLtAITzhtyXFBjed1NC8o +iPW+NPTrS6C4pD1OaZIEBf44IA0CAibtNVjC2CTeodb5yGzdnHmPrnwASX/IVZc4 +xdQmeGlKrHYbyBT19pc8tDjD4Y0gf3PPy6z9XUxXv+6mYSuCd2ovp2Ocnwob68Mo +HkkOAHE0zUDfNOhWo9qo6TxpxkigpfKUBvAb3sGQS+xGu7KVVLw3ERHsFZHlTDa9 +Ftpmz2W9hz3ZGYuu35adQWr8+8ezr8NhU15hUz5pA+4G28fT+bXK/VP2NiXQdwB9 +LtuK67Lu8DArjWpTMYAUtSgvqT2yaQzGb5634tiY2OHQ/NUsqNNL+iuMbOxR0TmM +EsS6Qag6NdVEdNOenakH0QMOOpu6GCP4fyp/YckrmcpwMNhMryEz9/eFMs0orIc5 +raCKtMr1r9UsNK7SAUDcJoS1vGV0yU1AKqlnO9E3zxWJzPRjiMU3TeIgq2sSsckZ +p4KSV7oZakhZYIZcsfcV3l4Dp+Naes0SniawFjsGG4ZI1bEfxU2iXUGrl+Y1AUP6 +WxVZF4spPYJLbFpDqu/htOmkTVyP3cniNjaUv3QUoOdWICVAc3rhXLx53A2bbsEZ +Em0LghjfRdri/DWNUvUGmEuwxciz5f0hHdVyHZ8KJp+dz+6AMgUNG8/Z4Rx/b3wy +r3GZRCYYg3E0VEeTTlEo/Me/4U7Hq9JwibqcuC5fbLWdFioxlsbEvsTZXFTP9Xc0 +jgGGiFaWNpEOBlr8j4zCGA92+LktPCB6642dhW0GOFeqrJc7PofcnxFdferRYIeJ +h4CtPgLQCfXGhXePAql72DcDtwkE1Z22r0JMt9qia4JBbUGD/DNrh4bQh0Al3MV5 +/tR/CYAQNRWW+EvEfFikBru3krrqFPv1GmnxHz6GSYn7lJaLsdRaOQCmqNbf8T3L +HZuHuRYtvjsV7IOhZhjKCnmRnV1WDdc3TSuERCIVcYRwVwI3GjhzzMVDIhp4aBSr +rfN1mgzCvJ8g7bglmMTR5bJsFNW/qkwWYtN8ZB6VzBzWdU78wcoZpQJ2LY0JCcmL +V+lQlnpjOvtaYInA/GHPowNpS5zxEBih7X6Mt3xYp7357PKrUuEnR/IHOgefznCz +XcYvpU/dGdc7h3qmPChJHNzXod54lQntWmPqQGk1DjCXHqtBIFbVhJoXN0m12Wg0 +N9cW3VMnd756+wnkVPEWdocwQ9ftewZxR3gA8wlgUqxYP00HZHMoFR6m99cdx/tm +P5TM/0OdIKVomSTGspCl9TtIK5vsjisM6VFN0TkWJk77U6LeCBEc1rXvabS/qdTI +ZQfGSepEQeGlKV1GuYehaE8xgwfEnFUOcccO4nbqG56xU4GRfzi38mOGUfdvjpFe +CWeUA4J75KcHAFPb7lrB57Jl1FDy8fQ4kfc/O1PeaFnSIiz8q+4A4255M+XZRb3j +tQEUgkD47/CkzGGCnZ0mGCb2FOOgT09lcPR4X9omI4Nbgc4fnFnLdiNv5Eyg4TKE +1xuaEPxjOxfZqXROM27kr87ik68RYVi8DiNkQrMXd7vxMZdB1iP8F4NGxXMTyOSS +Hr/WcMVbSvNaBESWOPuFKyjY1VtM+eTRqhDLRAQd/TfZ8CNBBuOp1sUzI9NbwRah +ISYRNPLFDYO/Ysv1Thwmf8+2IqOL8f+1BCYnDeIYUbwc0hbUKKkk3K3WSgd9IKaY +MohXI4YBr8MAbwV6rrAMzqi8p3rtdjs2IBzNcXdoEiB7fiHUxKdV3mvZ6rDGFaMe +LuxgVVx7Z+x9Rwk4vVBCNByZVtrPCRU6PARexvPUPLrXpiMKLXu6ESx41kP/Iood +qXfeWWUMSjA/nekJe0azqhwBY3+2juOvyAYYXgIVNHRDh6Y6hy4J+j2S65LVxDdf +Rk/aEGhmkTVxeJu2u3BJ1v9JSzGDtFlnisVDD99ZwfjtwY38m2eqdeBQmFD6l57i +5uPUsAuxCbLRR9tCoCxp6C0UW7mwL2uq/6aqq+vXMVCTDeG5b0BCJ+CXA3U2d4kY +IFqJ+RAmZ1sFESALLIFeon9qxkcMFUUIbTLQnY/tAVzU9mmtTRC0UI8E/adg80Hu +qvgVsm/75s+sDcd+Xh6geWgFCIhBS3GS9nvsHrWKm47DcpQ63Jfose0Y0wF4Nnof +hmt0ovgHoGPRZ9QRtW/Q761/fqmCJtOtWrJ/2NoNFWMLiBy5ixBlV3fD1NMR19mR +LyxTYbR6gR2NMUkxBXjJqw/lsah0kILwmynPP/n9C/iYnic972OxaJYi1aQHqTrp +8vCeeqTeSwYlV60eiZ7YqIN6v9fT9UmhvkINCVSj6SrEq570kqhg74sugPySA+Gg +/kD9tL3htlJPQMjPcB3UoG23Xgxpm+oQcjU/xMUapKr7fhOXCFxRUw9uOoQypZ73 +aUXXrm6qlJL2OzmfyKKXOAt1SrZYipH8KhgwnKnf/FDONZzj07S9g1/wqXoEVbTC +xtUlzl2zBSkMyk0rLd6sSdGcEUcQ1bNDpoJ/CPzpjMSagnSrh3mxR9k3b+D0O1K3 +kmUI8j1dY+Kw4dcK3cuvKfQ7z5cp/mY62u1fZwMaofghkYrbJyEWbFTt28U5Ku/l +vQxf6hPBW6dXECha66T1/UqbtjiJ64AIL0zld08D3w1aypzatS3l0nTu7eGrwFri +TXT5FQ9fCoAitMI7QHk8XV/MjN8dJimXmTcRn8c74hiVh1bOoWJLDeJoxA9XzyAo +lo5IiUxGBLHdH5HD8B55mH9Oe05Y5LuuZ4JQfQ/hjvzMVt9poGUjs4hwSCRK1nRg +DHp6htoO/zgdSKRk64SWrpTnOrY1mBg/R3cCSwtc0iYFSgnU6jp8Eys4yIdOTXxI +8fW1Xnob5iJ8CWxMmkUJjD8Sz3zQBW/qCNJoL37iFIB7qYRT/hUZ1ZEPyhl2huRj +FttB1oVTlmb1lgvTJVfHfWa4N+4pRznwtnXsAUrozAw57EAYElwnerqHAKqlFnnn +c02xaty4hKt7h4FQZcPBcs3y50hQH0cgbdLatj+gl37cTDrkuEEhntElHd1EEk4S +tdbBeQkuiH/ME2yRwJoHfK+Wuuzb2fj1UMQfaB4NrOD4PMk5dSCBB4LAun7NnRxf +zfnibMqFmMMwQwPknj3D7L2rIo3yTIN5tDQuZztYamW0zHUoDWNaG0mMastN6Veb +LFyQJyFuBYZdpG0rl2EcPqSvgzZPfEurU4SAQiwt1TIXLogVaeXJUfIO2uxntgpR +y3VEA9SLLMkdJPYztsd2SU3kkdLVu+Rqsxz6/3lmdZiK0sgUYnIQ3RyTvtsRtUnj +MQcTZZqaHld+UZQhq8uSssMbpCSMS1wQAjfOIJbZrzDEqGA2u6U/e4sPIS+Gbhb1 +RXE2O35I6aulDxdfP2coJ9ezF6xt2HQB2N3h2hmHah88jQ3EMm0eeIkGX/jlUPCU +haSGXnF/obH+OlSc9CLuJ8TDSh7Gqq4vY8uVSdPdqB+SQt9yiQpHghjVbI6i87xh +nP43f3PdQc3ldi9HSgwSfSezXi2PXBeu2sprp5hsy2LCZhy/NgLU5YwHYIHDqhWu +AlTEp6RfLai3TXkR+/4u/kJgyRWOZX33Fcovk6likn9bHEpk+X7iphe6qicaaQt3 +NAY7X6YObitUverC+UWv+sN4ahVEjnjMP3PIUF9K2A48UBXEpSpZECo6ElM5qBgV +57wY2+zrWxUcK7agksL1exAVmYEPTFFClx1oefKSJIypu3EV8Hb7KbjhNHtH/Qch +QgXsyBltvkQC4OKOuwP0FkBHNkseEE+O/nDcNYyDCLEFA0qfaG+QSDlzc0ZjJUZE +KUShsvohVi2qcQo2V0QdgeUE6oK3cScs/bKyyXBjG4sTMj9xWqMZ28MLmOm/QREK +ieHPf964HjjbUvAmgaNMBbIdRaL0HKsQxE5fICqdxSp+Few2yvgKd7ebf7gcLBS1 +LHfI6TGaTMv2ZLf8Js5o/gLbBDKUYXwsx1/Mbave1I+cLZclKIalLiJM9En+goeq +TrrwvX5lrEck5ebULbsJ2f2Asha7qYDW++hnjKrjiooBy1aDSLVdo7IGhD5qDgVX +zjzFLvIjfAlHpFfixeJeNeS+IOrVq2pbS24wvdd+Kpsee7n5wSyninxkc8qHezjs +yhWwf41mjVBgIjAIMaH0wsuWyPwgSY6bafskVukweRffMwGBzxJGQBnFgg8BFLfo +PGEjjo1M4Qrydld+Q2LaF7paGGJnJRyDpg80DVMzRAZGxmT0Ev5/PFBE7uNbCLHz +0mYZmYPxPFQPgAL7FY6I57jjNE/h/Ko75N6P8JWf7/c6b/QVc0vLOYGvK2xweYOO +Nj/uo7gM8kU79V2H1clAiCM/DLEIBJTH1fskwUQ0uPoXbo0pfytrsokeo+v3niRr +jG2Ir6HCKi02F715MXcGtWadgVOQ1QtSAroYbPot0/I3ifSFADAJLUZUsS+QHUQH +v/+/V3oXLPlPAo1VHcVbbTqk2SYZYLJy5GPz1tFUNAAPckT2dpQHsWqw6qvJvfzL +iQ9zs07GAjfmHbT+BSPONey83LSJxnhwNyTZCtU+OGhLzd/yUY20Txvf8rCd/H5D +/VH3enynGxShtD3eGR0cbaMhxAGP06WQ8rIHzzAhOSLEaornndJoyeObS1erT712 +IcoJgKilvmSY0WaKsvdetnKyBaDblu55Rt5RvGpig9ZC/a57ZBZi/4vvqwiwelGb +EbgnPP5j4hRt7MJFAyB0Ib6ltNKPjV+Qv7qKJ0DNCy6bgoZv+yN5F/MLjTOonuj9 +lbS/YubO4w5guKVUnmi+Tu1mrFcMbGNqcQqCr6qbuW13siEvmRz+OuQghJc7ADPA +YvEQDRYoxooeUgASiUnyNoiGgxXOwZaOBDg8NSU/v9Fd47VvL/i1Ncv3arVbv76a +H7Uf0zivOyKouPzmFwNRDi2NZuXWDrW6gagTxc3/VomoN8eBSOaY9PuDN9DeKd4U +MY023vrDMHNkcUKkUiGZqgIwQ14xtIqcrcozKRDsP0m1lXKnc4meNA4D4tKTdLpp +p2kO6VV03SpHSI3ke0ryZcZzUtENyS5oEpZnZIStvxysZzpga/XUJ/SFiEHcS8fx +N26HS2GsghQ9eL1BKDsPi9bSCqLXqaZmUtknu+R0IZkGRn9kn9gyb2XeJ34K2E+Y +WcptWyNA2mFRs2Siz7/4wrK7mtNPTwWAk/y8f5/BRv9DBXRZpoAq1KZm8Vcx09qM +sk1xWU69HRFOgENVUfQ1XMIPWaUS+l9Vu/Uh8CLZgtpB5NX9Y3rDIRVKVSlAmbyb +7ciTi+Wi8D7CgtsL+tU35eaRtmqcV8/8CeHtrpx1KFRmU8i4EidTZGu1vvMeaEGn +DkhR4m1SrQsflSLMGhCcKMQkSyJAHFE//+ufMplNMAKg2veeEWuCtEq1tiJQ1EnQ +9OYyCbWTFZBf9WmiqeF4f5V0ft25EfioFemu1gUtMrc6S4TWdaNiwf/NDm7V1P3B +mh6WADGxuS5H31bQUt6Tuu+M+8xgNQiT0Pc4vOd5qAwdLiJjIQTyC6/WGRqZwcez +4FOHN5sDpfJYZKQGmjC6efFjCsZXj+VQBoKto0cXpVm1C9A7PEWlSRSoPM5oBLz1 +K0PzOvOwXkub9pBpgvh2mzUSU6limwtn21bmg7ECoZAVRwQOmA3E/2L8vfQ1cfZE +h9QKyHkDCuusMQBOuRKwfnp7dQ9xC9/LNomPUjH0/4Hx8pK/UhMLmjPujwuiOCtV +MVR40c7DOFAoD8eIfG9UXC2VKPx1WjA9YTtD9RBFSxPjqLOeOD2WczqqHmPsTZcp +MvsPDkgnouuPAmOjq12YpZC8wqJfzha5KuA19217HsXiu1dZxeP8VCLZN2u9TTNw +8wxT+FDjJUNBkNylF2f+jVnCP+nL3MopfOMou9f+CNQfMarj0yGdi4HROhAZ/v/B +gP9u7/IhmzteRm6t18380lWCukFqX+d3JpKkCJt3KQTwKjShRUd8qgCsTw+4M0ai +ga5uUJRQkjShPtEr+QdkM+dUWju32W/eaOWIx5OOoxlvp57zEmnLeBeg1f93Jxwy +CmfRpszzVKI3d6DX80WuTJ9GdTdA+SjW4yn6QPEtDsAyboNY9THNiP7xl54COsuO +A2ZMEw0m6KFWpLjBS0UQSLR9B++QQ0YMi6U28YVpRxjQDh0xRDS6/ND7fhFiii6B +gPVrhUqxqrDL+u7wFWMyIlOPeqn6u6KkRqmbubc/fx3a5h4jgad/KzxReSK+xAbn +Q6kTwkG0T8x2ZZdeNut0SMoXJ4kGAxiwSJesY0X9NTfEvrXztmpUAc5JInuJMGaZ +ma+V8LFFjqF140o9yA4pahT9kpNUwU5bFtvM6S7rF/OWzrF/za1refyx0/XGwAX1 +9bKeIOlsOOc9G/GnJZnanr0XHS/VZPWQNCGwPsmq4yGOUK3Zh66PVuwA9ujmCBUK +KB5urQA9OtB7vPqx1dRbRrdSpmkrP3PAgPPHQqSocdEwxRNWwkAF6KEbmOMnmiWQ +kkuC749FgdPkbNntZ+Ag2uwTyS5LkOwKTMXhL8p/Ka7/akTK0hrGbPDjzUcgdvTc +HMoYURWltjmWMRzhMYESt+0dph7AT3wmhBgxFNR4Ys9i7jWx/xKutZ9fy5+FvQPQ +9c2GEcUdeth2bL0atjSbDv5cu7jN2jz/J46S0u3wPJuLQS4FsCaALiSd2hvOpxnk +/30cX60faCbR7kJxTw++tE3X8EsjjEzRvIqvXaCc28plx2gzMco4pPfWMImzZmqz +Xl0Bwa3TrEheQQXqUe4qvcP4+LclTgyuHgdoNH+liEoqwzXuikY6N8VakmVczlGd +yDd6t50ZD8MsA+qXVBytKJ2w7LtVcT6w4I5dicZN+fS4Wglu5v1cyLSAOkVzKhDc +PT62LDXT1+ayUjwkZJ2QVlRI47TdfmD2yaFwSK52CZ6WFVxGDwrvAMFGrxjT743c +2exRbQiIDaYPsDrYR3YieUeoXANSA7zXtMEdAKA+2MjJlSXjlCZuYi+biHJWidX1 +KBi38reZ+i+m+ppP/+Ua89VSQkRXE84za990xT0bLQ6u8f1hZMYuObRR3eoUSrin +e6DA79DgApO16kvSmC1sfi4lvm3k7hkxkl9OWjzo9FOb4cnO+uv9CtomL37YLJwY +iet/GqvdBhmsHqZFWSrninU8Syzet6XYPTzRrKwbeyNyjDsqApbHBlJKA2PRpuwE +rm60LyqO5IttGuwlPlyMDVR4tNT3vRF6r1Ru41PnNvgIvrU6cB03bz05nvfAKIgh +M5WP69F/DeUvNpZemingTUpS2Jrw3PvXfveuzZJ/PMOo1ptNOigz3TkIuszIzxCh +mLqcIaZaYChCezHh9cNjy0i6Q6+uj8caDT6XhHb4js2mkt0kBWxcnbUbWjTZJOZ5 +epcy2wwn27wZcrLoHFq1iH/zCAT2axAtosu97MbZ6Y1oN/fIkk37skZ0pk6gIc0b +0yWXnSYEWrPz/vuKnH00f+DykzAyn4+zYTqalEI1vLBLWEeGMweW2nqrXyubIxc/ +TgxfFQUG8y0dAkYKO7wSU+EC9IzQGiiSwgXdznJODr1+ODvU8y9mh1V5ZmU7d9pD +OWMD6ZiRBRsVXnwEMjHpqtcpa8gGcc/C4oI5RLllus6SH3n+7Hi3kZmnSkyx/QXY +x/hKgRNZgU0Edw2OEp9hH1APnsLDA3Ikz4b6Y98BGJUtq2aANLttdM3WsN12xUeR +ZEcs8uDDiWGIsE02lW9Cvy4gjd4xMii0YeB8iyFgc2NBkPuHplSR5RL7xlJiD1B0 +Z6F+/8OTJ3VAflfM1cyM25Oz7H/3sPBklDiORgo8756EqAVzTVmAyAb8VNs7PZk4 +Cgl9lYvtYXLCWzDJyVyhGJ5UCKsjhPHymCNupNbhM9EqMVFEJJ/zqKAIMY5DBqbf +WIBmaCavcfhwZ8lwUEWJs7zVZ9ofHvGS/YC0HJDecnTk9LWRjYZAzaLeQWPNz+Mu +225XbxGA7ts5DzMK/JXhmp2oBVKMhFVR23hRTJ0Y0SI9tdrG5qjaLKUfWtveprR5 +tphn1Ee6u/VECBkPmjcn3SL4wmvg90Pg6W0E3Tk7ax/tecxWTq0eHFuMAf+kJWrl +IWPNXwOnyd0+d9DYBceocwuwmTzIA/kSBcbMwE1Rv1Vgnqk9fD1igAHxcqQJRzu1 +vdaN2LNu3QFjTtDqQxmZ85E6rcuJzK+uGgQHyq9E72a1D7bN4DWB8ouTUePudT0O +GbKR+tgSYrqIdVuFRaZyLdtC43fgmoPhxuWQ1oLVTYJYf78nV6s/8en/Xtqtc/vK +n7zmSAgb48/8/hIgv7/XDCmJJvuh0xL/WOf3NKpz7WY5LuOaI5qTj3FzjZDmk19b +7CwDmafFk1g15Sx0rzYVUPr//Pfo+yPRs2D8281HvowsZ6RXaCJFkNST6h5BtgHA +sr4doIT6V87fyDW4b1VamB/+qB651CqmelAyXVN68KJ9d0tw7VMp+Uthf1XNq1Yb +ALYoCVCbDxTdSuUtSUkJbJ9SKdfmm5ZOHIeXARceXPCWidhQXr0QPUhY1pSyNfgn +14/kQbq9++T/V0z1gEoa1r4vB0x/68+vKerDk9LfZ+qj52uGdEIEpeUbYET4X2HW +OIO4zfpSxfSiePA6oLOBSJAP/QVZppaWp0plDd4hRaJkSaz7griOtvxRi4UugIzC +qBNWV5QFWK5N1+muqHK/p22Oih9zlguh6z+9F9A8cjZoo4u9VpMOo5+cnQ68sBr2 +nTjVTY26todfphErAfNZW8eq5FYzt3E/OJ5say3mPTG9QB75cWCJNObW0U9XVRM7 +XjWZzIDhcUIX+9WNOYqEvMQUCm/7WROYgoD6AV4fZqfCpm+TK+7M8uyM/v9gz4wQ +Yvchg5SKhg//V8Rytl7QhNqgeliGdvupFOiufpltX9lZ07VUzAaZ210tMWflW55n +jr4CYMWC3Il5M7gen9y5Ely5BDf+qn/4Kz965EtzTBrByPEbV7iRfTnYj+v5BhEV +b1r5s6BFqZW+MoR1uGGi+nGhH6gEdJhr/+5CiL6Okh3SGB3AbEv9mlfmc/7Gozod +45otcFftFg1aIM7DTmt2DJFPPV/eTyhOcUw9FtcC6wXOxvQXCbcldXIbkxBiT64j +xi4I2DPoNHAzdbB9p9lnWlqRv6nkesWiqKv1bJZSHNdHVCcn3EjJiycaod3FRG1w +kAfSeJLvXi3ReDMC7jYrXWXg+6E0g57PoyJt174+T7MZs2kkkuStY80Dj1zYkvSK +uaXXqtq6/bNWlLqLjmTowhA8OF5UIKSkEEA9OT+nSKTTmjBkpGLTs7nXx0CJ5n+K +LLljaAM6YEltRLllBufFCKX0i+0lNdGPht+xRgLRxlC5XSCdI1hN0NyAuoGFkTPc +6bYyGMjKXDXmYpxH5DlclvNkiXAE348E3xnmyC6AD3HY6p27gBmyRo1w/tiG8hGx +WMEbOHje6T6Is/6lHeAy6OfFvde0sKmK2ajGSVFSsDaZLaif6VxscKLxjQS7SzmF +x7FuyuJtoScUIYJHs8SgfmS9nmSY+Wow9xr/pW/5Q4dnXnVbU/vB9L4ytfSXE1Ql +gAw5hezBroSrOqfOvXy8Ik88kDJzdIBoXoShQNoJNRomnLX3oZWOzG0uJPDCjKsZ +UUV60JewLIORrDKSt43e7tmUpnvn5ILcD4jOrRsAvnwrpKnxTDXtTnmqauSv2Qj2 +xotvzojLpU3W41Tb81sDrYoYiiHx8qZuUk+ZECYrnyiiaCIbtHLEFlQG7333vftt +3b0nnYRlyvqadsWylVLrNGkz8r4ZA8AJw+EbZnJEA8C654gW6ec+XrGMg/xechDh +D5DaUrZsq9uDOQV9UqOBbUtO/qZTPpS5lXLvJMZNqwT77MqlWQREgFcPh2piHXhg +FFgbL5Yn/7ROUlmrKiGmpN/q+J0Y/b4EQpfg2RVoHxE5syilJDN3+c1T3hK5G7sQ +/GrTtFeG7Nf1tK/tqWO4Zi5HT+HV2FmZmJi8WtQMDc+ym95UUfnHyM16BeTDzF8u +DtgzcBDgncqEfuGq4kcsFlgHyRzjG+26XL+SEAVKxc4xihWpki+BEuHIacyXSIjA +kzIVV48Hz4TP/nAYdTay2VuIjVwjR/Ff56ITrE6zmNkjjFWEjRNPyTsyeBhGi/cR +l5DJAw1min7hUqUcQ/eCXMNGrAkIsX5KXnpyTBSL7ouQuWEyfq48z+USlFe6iGgj +aLnsogCbO6+0qwtza7LACzaKLsjAzYCxAtdFxK2GniQjDyGKo1GDCQ71xXVmqbT8 +rbziTswwJsokhhV8G6qA2NcPNZREOoCKge3tqri9Oj1h38JL4cyxRwxv9d3d13D3 +fO/2bk7luOeVeQzjGg55WYKV6ezkhJgxkJDF/Nm0otnSki5ILbB4suMp/ULyt0R6 +gnUUZkVWNsi+Y5hL0WnheAi9FvmjYzMqPoh30zvSmGeAXDQXI8rYy0N20+1ofc8V +Vo4m7lnoK5zKvgg/iN1sM+PGJVg2kDoVGpAaDQB8xflmDtwXWNxGO06RhtgsF152 +WZ+Xy1bNtVd6QqXpxbePfO84cFWT9StAeZmkjsRm4aMGfur/BsbUB7naQuzEYaPM +37R2OCdvuXpevelHD5u+MiFvt54h4TMwVzAaifToAYskbWmMO2cTJi/xYiQAerbZ +fxN97U1sLmdkJ4DGfmkLu/KSrYG+NXG8R46ITiCOLlVnggaDT+oO+HIrOJ1lMM0Z +LBCRWAFOQNik8uTA9YUT42TAddBlqZryzyvAziYPe4XoLwqFaGxNlFNblrpr5Js4 +qnJ8xiG9i1q28dt6f1Mzwck7W669cz+hyYZeJvY/05UWtEumVtlIrWfoZZSg6Kk4 +uVEyZp3dmsZnhgiq4bArj/SR01FBh7C9MGxmRnYl/i/hcfuMOL+k7BPIvUumbMR7 +zQi6eO+Oy51RdG9EhCHxUf524XLxcfbZ44xWt3yfewhxMI2gCHNQOKuxLaRyLrWr +TaGxkfH1WYHXXQX5ln7YKuORGm3+9qR6A8gV/jqo2bU8iq30qmYwI+iN2k9xlUyd +ZeTNEWQ7Om+ohC3ed4FXzsIRgc02g/lOA3eia2cIC6Yqwaj06u3AF2gDOPd5Ny54 +KcB3mYyxeaNxdxF4g9WKZWjmBkKwKxq8VlvcHGTuxupV8oha9nGo2NKxEbt11Qzl +WUI0OjQoFtf73UMABYtkI6nmQUbsSzOiG+tYmKFSzPZkwmsQnoHOBpU8XzReFzBJ +TAFxwRhDZsQ9EfQ++Ctynv2ENDKTCnMJgEUfnExh4t1DiQyLSqCyL9qXxCZo9QaR +qN1Pr77E8bL4xWBsoWq/S6TRk8FnwXrQ4Bz4c5XboSOhZiOSTwnzDGyDUYbSGjXh +SnDluf+H/OLWgGrPW1JS03ApbVQ/oB/wzGSRFx8YpBL5eSWCa+d0gChQvllVRBKh +VOXwHQztpU8lvMPflDpWr67fQooWDVl1h+MpK1bC+yNGMKXrWq9px/aavfqNM9Fr +iHuHjPTocFaMBlddCc0+Y4Y0FZmnxIYbwghXvk/eMK95lXAWnhuG2m4I4RXhlBVg +FL1Usy2dfCIkM8FRiqANa2YSjAwKNGgzKrPZOu9tY/obe7M/Y1KATH5L729ybmQA +5VgKbGv49O2mu3jrU5SWK0GJHTj/79xJQmpjRsXX5NkbJJVGJ5CIKgmAUBFJuzVd +Z6S1uKViwjCSky0nkjINXMom/HziFHRqjv2zqtVNcsE6riOidTbXBakJ3PJqJd2Q +wvbCUbvwCquZtlktwWBlDoQWUFi2qfyyUv/Rp96sb3WyIHxOFoakMXAsjrd4ZqsW +xeF9CtxWfsldC7GLoPBRkIcKAfGKT0MWBWkh4kGUfJLsrhsshiRw61bV7hxBaSgM +/TrOkAT3a37u01fV0qTy/KCM7cVczBbSXdbt9rHbf2pLrG71rloRCXMZ37UHZdJT +NCW0T7eApajOdgigaFaSZp7d5/D5riRDPA0vFsp8n6l3e6yFa5lnss7JizyulCxT +Bm9PMoKLteqw/AiskAIGNZrTzVIO9KhoqbIfOgzZcJnApcJ1yeLuan/5+dsnccaO +gUipDQ/0nBZwKXRJo2x9PWV4KrAXAiFmRkLUv0sXn9ubUTbKn+uWLl6lFP299P37 +wc38LMpV/Xul4sZCpdmo40oasbsKiXUoaARH9osI7XJjbGOKP2JdrY8o8spd5sS2 +JvnAoUHbyvDv09fA+9H/rjkegmFxQQ/Lf6opjIO2cfXo3zqqnj7jFhOjJxffnLkF +yv8ImwcIHETFITui6XcfVAFexsHCpali9IamPM7FeVl27VfXJdWnDykunc7lsg2K +MWGE/Jc48o0FqpGHqQnAKBVPA5vUYEsp+6Uyj+qQAB4lIrjO921OBSdW+a3ZInDO +wezOltuk5zP3pEwY0qHvqWzmXNmGM3pD+AaBzlFwOWYIUM4R0dnz8LWf2Qh5GZfF +Jw00AHl+9PLj+HtDqaeilQonYOY9NFftZRYpfACVG8tCfwvDsVJCDPIvxLAoaDz5 +AFA7etCfiIX8yTWDOOySN3FOKV+Q/jETfau06gfc4v7aaQJzmm/XA/UF8i3lzQRH +rWxdHOjkwzm6BMrqszClj5bcN8bXPFZNFPcSuJcgAR/LRRh5i9U1N7h5SdGUtOGv +E/inG1mHwuc5W+wTwS2DIHoKhLcr7wOQOhfccDnAsAvfppSnTX5nN+rCEl8cf1d7 +S4hDj5qfdtbDADtnvt7ouO3qL93jXDWxC+T5s3U0CtXfz05NQS/fA1PqS3G5EMxp +N/XNMa9/LjutzM0X4BQnlShSy/j3bKb1r8fer+5CVApgzzPjsb5nl7yqH3rWAxKS +C6SK3bhjjiVOL/qMJiOGlEPeDQ2IW4FVVZCU6u27OWY6Qvgg59E3mntQcVUWegR4 +2psx4MFMeAEN/TiqpQAFs7m94Oxr819ROnWIJoFjULicciHrGSrtLFqKr2vhUh8e ++/vWk8kRSzbp7S2UalLw4CHGmcDsSnJOWJ62KRP7YEv4iqPvpUIgpnGxtlqcG+Av +mtYqvz7GtUQz6AhZqi5yEf6x+SpiO7UrEquM1V9wpIbZo3RnVH51pYKC9WADlpI9 +3FW9KFPQIar+KLil+TzaxIO1KTtPUKj3/G+FQh2ZbCaO9kbRPW4Gi6M8bPOccXOJ +lSrgrfRHXibnQG7DgWiGoJVgjQA6eAU1PcFdKi2IsJ86Hh+EYETADsHx4jSaEXp3 +5izQnN4QL3VznYZZyo7EVDnu8FRdC3YGAQzVjwK3Mwnin4OCGJTlnqf4QzgIGa3o +oTy9JyXE1g/6mnfPQUn/1Fk7+aXazi2i8fFTfLKecCwWEIJw5pDP/4PrgRnnhErv +ziWCnw1JznKjfFKkM0MNuAI2tSaHIg90dQjoVxYK9nLDjnSvu1Nk2WITUFqoovrY +uoxUhXEKPctvKmHjlJTN/sK6Fb0Vj/hPZgab9x2rOH8b0IKVxvApeSA8dn/1SDet +rh1wSLu5Y1r5grFLUCgZq1Z/pAB1q3sarJWyWEB2MH0360VAjYZTjUTieuwV2sWq +lQZHIKntIF4+UfuHUV1Tfd0a3WpeIPTgjFcPlOMNa4GhzE5J4Ja6KExlQPr9pxgY +C8hIOd+6GBFGfCstDt40nbo3HIIPE1M32pGrOI4hH5PQzLskdCwiwbEPw+kwU4s9 +GXSlrxGeZAnFSVrl4hyQPRqD6RbbqykzjtN6QUmCoWPueBL7UaTM0xUb2xkiqpzG +jtjqhWzYmn4tHkhF9gE93YF0NINQ0FQ2BJlpSHTmfurQejasmEN+ADnkGmPzniBY ++Sfi2pS4mtH4q/HdSX1thi7/yfwjU3ewUn9vC1z4dW7AMj+jLrBSLexXJ/19solq +gQavpRIz957UFGjiSyfuDPqCPIBAUAF4Q2ef84nZYmEYsYb7Wm2wb7PASPjYhzd4 +mA0iz3yLMLXd7Ph/hVRgzmVG5Web4jvcjn2s1dG0X8BEHas1lvEfpyEnl4np0XIw +eMdFoG8bj7ghrm8W4YniUdSrlw/NKh3jHzfrjtpxgdEjkjKbMrApY3LjExCYGdZP +bqLtRmEHRFcmCmr643CG1jNVC5BhVQ1MYpLgZA3XGaSsqQ3PWTGKCq751rvUb8Ei +osOoZ+bnQiGwBT3A405r5H3DdF3sPycthCoGH3OZRKnbiwiyxSh8y4405/5gNm1E +IrOgVNdxffXzi1z3eBZmsmdzov5aO9cpnqaGGzUORkkGc+6rbDSv5chNmwaNtJ00 +ORx1/CHo2ng8x8t+Ja7ZUdbz6zSBGfrEtA9FMgeTj99yu0liv3UMGg0nI/Him3g8 +kzERKgylCgc1PJaqYjN97dPm1Q/77WpdSAlbI6npam8+wuT9q0mg2gbQCPN3p5u2 +/cmfTky+ZjPsO1hnAMsrC5NFloJOrddPoP840txEpRD1pO2UhV8qoU1DEWZMhbhj +CrhtOd6qQhzfw7riL2W/8/hgyFHLYFAC8WyxEv4fDLmLxbMpI1dn42s+Gv9RAd11 +EsYDnDgf3aMpBu1TxLxH54Os6W/OhX/eBZDXFwJOJZWH7D3GF85Nq9JKe2AdBAIP +016vhj0hN9scDU0Lu/rqah7mNle+XftmnZX+9EFcO8Jo34vLJL6RSiBEww90W/Mg +e2bH6fcclssDgSiW6m9z51pMEzRNRmQA0dXarM5UGH2GPioyPy38sGbBIhmvFPyV +0u27NzKxOfr87ar02E5tppIIdm7z5u6lh7M7hgoR41uu03jgg7matsID/Et2ew1Y +QRAYZWLM/MZ1/NPFskzyMD9W4O4uJu1elrbxm4wEnJUt2PncGsjlkyMzM3pE9/D+ +8wF6zBzMthUohbBfa45fJQ8M51NQdh/DZds3pQAP30BD0KpeiF/baUXdz6xigJVe +kkmR8087wPyG0zL3D9zQfuxMibffq2PNhx9wc7fBghzff1ugSvGtyBhtFbm8bhjs +ogYEnvm95hUyanv3xbu06PO/dTRvdiOEPtAyR7GchW6BRlsgqQiGVwyIHvRaue7c +/S+rEPp/+apiSC/zEtOW/OUVJdw7TixNk40Bs3NQsB/YAyNdNQUn5Y4q8KBZGHwi +NiAZH09FipHw9VMLU+ZqfRE4J3BrnTmL3I1AG81f5bqO3fQQCawgtGiXD7gtVmZM +U4KlMjmsUHuashIEbXovGpprPxTAuWPrDq/T150pc+Byzz7G0rqbStwcHbv7MRTs +4xerO+ZqUWzkR07rpIFQoGt4nnS4cPq8G8mpWLg02+ZlLOjmtJLwamjUV/tiD362 +u5ZjMuZuiMl7LPMoOgRXbF7C19kOsD7bDeYMA2k7ZXqoIZTSeNLhkmOp1FUtTH9W +JrHDclNq+7AEdmQi6ssnkEyvy4+RLURtgxQnvp4iAvXdapnQKZhfgwC0lORcZ7zD +MN6CcP2CTrP758UNVgtvU+iXv/7EE8GbvwCWmehyeLeooX8i9PXtpzp2i6uAs6Ix +n/Eo/SgkrIwY4hnSvduoouWv8EyUF5ZSNYKIM8yf7Pz9XK04tbRw3CHhwFc/ZJGa +Or2PY1heq8rfzXdn8wzP4V5YXazXXR5Qqo/o/od1czc4YY4eJFVodDQqSseiKr0n +l4k6d/4aTGJ+O4aAXDLb330uUSX/Yu9S9FY8XXMsmDqMr1qHn0S5SAtcqWJvzz95 +14MgbvR9VUQ0kHTJPKjmQ759BimyceaUor3JQ7iThcSCQM5+wY3xo9lpcjSDH1eo +0PEwtXFUKvfWZGRfa40+6wyUeEZRFM9U4cPoIistUOXgKMa29AfcJdoxrvSJS+F4 +SRBzpTWkzAE2G0/gUCYkJYvanb1+wYd4T/ug/6c2dxnc47fP9LDB5Yv2mbUOfnBi +5Z+ztztb4mDucOUjYQGFLKwM8FQSrm7+lOotXw1x91b5BZvFLVQrBlEajfAMkmzi +CQkrxtYu/A45NxVKbJXgDALj4xl2fkp+gC9TR+5/GdRtlJSuyMrUfpvriOu+JIIm +YtnOQeTMnLCjF+flMYlZrNkArY5zI57SiVB3vpntw5qKfSPbT1G//TuWtF31jc2y +WACFEK5XydN2qoGhPajaYuEX+AdlAestDEEHo1zYambIQSy+rIWNx9Hj8SKk7U9l +w5NOZeiWNe1sI9iHynGsxRa0CEaR27TvaHB9AdQqzz8VLeSWq3QDHTu2KH4r4SFp +7nBdALq0iag9T35DCgDYCot2A3kVp324irLJXdAMlnc62RVqyEKIpWl6cuNWHqAK +YZ9sAkAnPJjgdZABOknRyJhkeNS2CjSPboO8MRDPoFLl6M8iiLCGOjjRtYEwjbce +/SCynvBF9qoVk4kLX7LlKgG/v3GYXsY5ZYJR0+k7v/x1Fc5RtbIvra2ELDI7U+IT +mbpHTsw+dECdiIT2YLev0jr4UIxeZZVVlWqWhjWZjNLIrmurGj8iKLhPb9MCZfWI +ODIhEDMf7snxLD//4ZxUcyA8BAiwjuoqqgkKU050s270e8fSNvAZqqnpZpETBp6f +jSawuHmp7IwzV6SDZy1payBAs4by48d1TQBYSR4B/BJMzwHMLOcU1GiM/kYokq+n +DiBgpQK45LpSb6N3ISyqXwsdT3ItG17L8ztu3jHCrtkUD+ZqfJUyh1sTB9Ik9rFd +B3c0Km2r4Tu8pb5l0LyEeRP/A4wNixWUnbEoVnwyhAs/r6K0P2hBhw0tMLCFwYay +RqROm6Ep0kY+GtFwBKgoHBKwux3lzSGnyMKSJrbolnP6vtVRB0d7lw9zDzz7HNLi +cHfgpyZzaKr0G70mPYidqJA5auPeagfffABr+C/hH6FnkQx5vIu+oMixfW4Byd7x +EvzymAM+tWZix+gO5osOS8+GYGt/nffpaZzvNkK18BHhkp2P+pHq2XcoGDQd5UKf +Sxnqxi24x8eaMwStFIKB67PO0CyD1ToDHVAczGBAfeMrd97GVh52APE3jo7XJ4bC +DD46Q9arwYAkrE6jPFKwKrkLKJsNOFkpUdvDZCsYW+HfZsc1y6ObgYJoM7ni9vUL +muDYHCxRQ+lleWxoqUb1qLxzYHxP0yEC47OOwTV62JYKMOyCti/xkL6rEkncFi3y +TZy7AGe7mlckwp1yIs0gYua/VpYfy95QrEeUw9hYkr3Z+4khzlAvqlmPMF4/ZQ6o +jCN3WxUfmeXdNTVKHaJejnud7XCpCF2NZG1gpCKklCQAT88v2BvK77IguPyIQlhS +hI4RSzlAX7NrhUneRBLoFwDcH1Wk6eZevbINs+GnP54bN+yzzCGB7dLSJIrAGs/V +gJ6c+OXQmyZYJ06jxZD05841lOoSJOBRe1p4k6XO0emXBFT58hSSmFocT6db5ca/ +GHfC9di41qcnSOwIL8JoUr+I2lsCh22rsqrdAS6GNuTGAMxzKO8SA4HbrhyDvV8p +wqOgZq2htOTZ7vpdMQfHeaj71N69YiRex2xymAb5CLb5wF8LQWBu/WG305/crjV9 +VsizkodEAFtrhxz1EafIm5omNjxIgdXgs1Tn2MZYaa8BwVvy5XJBvuxuwroiqeWg +yb4uXFR0PdrorTQYvQRx3EEPFN5Cvbm5MdYBHW4B6g/+64mCn+J7m4XSaPkndwhy +LNla9XNFrlsOOLmw9AWZm0VrRRCCxvdoaGn2QYwbYWsDzPAdkakc/YhtTmYeEgp9 +CbtycT47x3qvYy13/96JOqNb+1A0RHGs9S7HIvVYnF7hUjpIatAtWZFPfOD7lIPE +UBGQnOrIHAEC+E15yiAz58p07FAkJUXE5Oki5I4qfLdIdnAdFDOm/FXY3BwQ9zu/ +TjGXVDdMsJ/oIXEFUVHGhH54bM0yRwj345rx1HM/TfjAVvXFRtKGnGNCSsrnyZa+ +fbZVENmCgmCHi6PA6o/hNF6VdzZPbrznkCaCetI0OOqaFOFCHsLfya4QUrZY6GG0 +dKNYv5sW9Be6UDVhS1L71FdqQ/U6IwNBwzIK6Rig/Tl6SjPM7kfezwJYtKWLCQhi +E4ruQmbyuAxbbHXnaOdFj2c6llp00f/7fW8qM1A39LKEbMV7kDHfug0LivTFqWDG +PgvaPwm2P1o1PMw1BA6l6PYMWs2shxssHosUdAP8JYOqQjn09aR/bxfs6ePxqtLj +giF7UC5JwQvBzLe2BvraDPYzxXRZ/NdKMcE5DZo/Lm3MstAYNH+zT0jtojveXA53 +daqN1bQjjB69azXAUW7lLRQQAaxuVoNgMAPQkaYjmcGlBAOPcPA/fDqIMa3iEkoO ++1Eagfa0CoKwz4O2BxCf5NWapQ+a+vrBFb/3y0fGGEMIgi86KpJW0QUsI3Siu9BX +ZCaCmVmD25ABB4I2V5luy20RRvUuG4sLm/kfp+s5LPy1dDNnrKC1wAlxxDBbHzO2 +EWahVCXlVTujukwAgiHxhulbyBbrDpBaXg9PLbp2X1AaDsrHflofp5oSlM7QopGz +ZiWNPgwyBe+ZIC9ZaMtkEILpIW1AeHj4cm1o/MPoDzYWiNBT6uy3sH1SCvxpzwn0 +8BbRVvnzVl0mePemxrJsOqPMJOa9zN3m01f4OPjo4VzEM7qpfVP89rIiQGE4ZC5x +HRPoOmkty3c49FM4BUkEkKy3K2hl5fj6SD+/01PAJxApz0qdleta6guKCxyi8qah +9MhnyU7gv6gwNhtd2fSxK6idmZ09OoU0allBu8QDFmk8KvQ5lnHQxuGJMbj5E40o +JAz4bWIUcLRo8TndbWwjSQry+g4whcOG+ckihXbZUgBM429lWzt9zAP5AQv72wAI +r4O8gZx8f5IGgjqZXFaAcd0sKuiK1JZs7d91IN6AASQJAoC265e1mT5ZR8yCje54 +bYgX8DXEB4M+uTNnUQUjxVR0oXnUxwQeBnvA8flkh+alBsc7S7gV8ECvhhfdAdL/ +4PPg4cgUhOfhs4CW0hIFlSDqvLAiT17VKAFy/NG+JxlEIHS0js8vEseMwxEfclSB ++JLzoaUnrglCfQLkp8NGXZ40wTNcw/W3h2zofgVn7T5UZC+fDlnnL7/0pGnKMNtX +Q2vg//Bedt/LRXjU9AUQ/wMs5F9AaD0+HczE1aK8kUV1ddmZ22T/+i1pKi6VtNeg +8o5/qS6zj2op4rWuWfe0C4/vIjlXHYiw4hJDQhdZxXF67WEv9ZsK0EJO9MB0c/Yz +bgwBmMcU7yQ1m2Z851ZAGGtqsAZg2yP3NU1zIZy6erzXgHLZZkWuCUgnaj748ed4 +X7SDH50anmZB0rc/cfy0RLA5P4IdyHNLChwYsSNW5uv5qIsX659ZlJc9HbIwF8yA +sxvkISpYJPPrB2Af1/SPVUC9E5zh4gt+nV6T55WOdPgvlrSL0a2gRRUnNUM0vuGY +kzo0XqR4Os03dixHeQvybqOrBrQjamRkzqEVgAzmKTSFrFn1IDdbxvbE1yvw0P49 +VY5/UkUeWeuFDfJyEMkE0n9o5XZCLxWGfc5qd4MglmiYR1biJZtVXt90OwJS/Thq +qvmV3WYHGCoChSjzv3qS2hNMVTgRm+kicrGSsKYC7ncSsmuuPdlQvlVdyMAAvYva +FqznWgpZHAhCmO5RQAkxpuLhQ/pArtnN2tpTZuNeU8MdGBwLtKgYoLcY4K/f23Kn +v4duwPcdwLVk/9dMybdSZZHH1hinNk1IXjVPWn3ZiHXMpToXFsEGswKF1fGZlr/x +NXoND3Bowj5GjK+bkj118VwUzEvJt1Hlzgtn2nc+6G75aoam9205abtqnNWTXJIC +vGwONbKXDqlwfaFb5FSPXfC95colp8udaAMlHGaojm++OKe7ACn2mnGtrudEPJlR +h3EI3vUcgPfLhf1ypg7TjrM3bVU9oeLkS7is+1CRHY8xrx14QZ2BrGGuChgNczRX +EXYM0h31fodPwDX+auSQbJxELkZCM2LXKTbg2dHCNtIXiN0S0lHzHK4XShaaAhuJ +HjTgbdsQ5OCAztUZKRgHOy0j5KkZz47pXROC3hZBwDDzUQAZ/622sfkeVFpfh9+p +xamME6dRIB94ovqAXjQAoWfAUbJLoo3/ARRJDt7ihmv1zwZB41En1NhgRFOTL7UI +dLMEvg1XC/tVtjckWDOrefLaay7BBEtPaTsZSjNkYW6KoWmiP5EaTVbSmobp6LeG +PxfzqSZe3u+Y9COylD0cVpQlxzwiv3qkygb/tJu9oUBtyhyUGlV9Id1A/a5p47O3 +j65guy+SQ7tun85wuzZw2BAlA6dCnpM1UzR53C0m31ms2IB+5kJwspALZxtlHTU5 +aSmfVXyIuH58yUZ+S3T/9c94VFB2spVPR6Zzb2kpRxPlg3ySq6qLhqg+gqoCGCH2 +xuO2roJ5O8PdrMirS6jWob4fA3x8sn/Pn1exjWHlxxLCkA47YRdQtDjMI3AFOd4Y +IZ4vjwedart0Y5fCeg40vq/n6QjiqHpMmA+zw7QMJXthxU+yRrUCEfCtgRtq2DDo +i2qjr1LQPzRvkHh9omi74Q3RGZJI1KkFnm3L/Rk9HXedr89XtwW5NCihVmbfKRjh +1G94HYu5Wp8BPnRr3tJ9AsTnRaE/U0bIcB+L+LdC/enTQ4X//wcKmi6AoFOdEmWL +7yZSeJJEsshj96bUH3IvTIz8b0pkMbq//hKG0oEU2vXGYYILQLt2/4dYnd331d94 +4kTex0dmOjbbeksb33xPOkKXiGphSJnMJnCc8RjHvXGv4kFKD/ln+KzJgD9N6/+b +j/YXD6kqmwPw62vR2TPbJtEDS8dFb69pNTWkeRQAZ+ewJTGlvjaxbuS1jNwzrHjq +e2cgFrJi0EQe+VjuWQnRuOZ/FmrJpJlHx3JBmn27bm6+kMVRTKqOjceAM7MxoJD3 +f0KHIRlcMwE53hi6YdQm1+z/7YW1z6+WwT5OYAPYSDwlWVpgG53fRipvdtvcZAH9 +UBtCG9zjoEhBewQVW7C1aQPZaudWYGnkYCj4o8RxgZUz8sv8xKIgbQcgy8Hfr6bc +LtQ9laT4bTiIGrkKIxDuWvIAZfEcfASeZSnPBxZXfKqyYjnF4S28e8qwTwDvmF6j +dBTKz2UHlxc1GrNipq+g7bKVnbqP2rYYs9nBitD/uRzocTXizuktkIfU/24QhwX6 +axp5j9L6OFEinfNSkoOx0eTgHcbk6jM2HTEUHZBwNqEPxM2sUhNXAIUvQMG3rLf5 +BS6yguJr5vYHcvGiveTdWdnIcaRbeZsKLvGOAbf8aoyT8tCHhRgGsBHxCyxU4wo9 +njyo9SyY8TZA8T4wUr1c7MObN5M1kJscx8fapQtlP4OMPCWIgsBOu+hZ3X2xI33y +WNcUQyl7Yzxi49L4K0g/Ykh5jDForN1jwfxxignjQtr5HHCto5ines4Ms4szzC1o +Vvx5gZwGMFLkHSEifdI7tXkObDaeLSaorYtVxb1uTAIFb+axfg0/MEaayIOFy7qm +dLJrsZh6Pa+crddkTUfwNwT4zICwRqBOjSZFC4y30QaxmEqGL3zsXICVzv2WyWNT +WVy5uuwuPejRiOnOzcrFzSj1toB3GJIqQPo8F1McC/OqkhuPV8WqjycIlua1w3xy +36agSWX5GrJoeRwcF3zN9i4KMz9Ez6gVsliQLyd2Rcer2DtTSud2iksPsDMv47Db +dnRXTh0PABF2MmSX9tQ3QQBXqCMsGlYtrUMSpIgOzAO+4uqfgGgk+wTr1p9tPj0X +uA0GjjQwwmpEUo5bofkmzTf1/ghRB9QY926h7OktX3geDyWNOk0d58jZOz/MLfp9 +MUuYF0nejTOGeZwTZM34xqHkGbJ2opnh5lU4dXlbKcmTPzvPU/cEZtX3TNWLYgR8 +iBKTGL4D7BIsaPems3z92eH4iz35I1f6g2PdgiOzl0cx/m9UIkw3pe+0nhbTj8Ke +CjSWkEDZAWsGSMo32Ka290+Q8yaFWKB6FvhpEwwAj/15khRTvpU/d0+d/yWtvboE +UrAt48uZ+2Ay+US2+rqYit/P74wyT3VU/ZtxZ7Ro0oyVvkmgtwtuBZMEX4qpSMq/ +qp7qae1H+RErR57zHWDUgJSsYZOUiuTYccJIQsWJZmx9Lr5WqfD39jcVESLnzY2U +BV2QAeOxVsDzO/yNZOBuQyWnMWj3lirQ4tn8Lncn4GerBbCbhLYgUBv31oVh7JfN +sxEIY3b48n7WknCQPK1Hui+Dm4Xew7eqFp3OqOiLwTSeTh9WPl5Fqz2vT16VR1Kh +Bl4D784CpFxCYxnWYif78OtKiwL0LSQlZGB/jddxf99xq6ys93Nzm7BWuNIeJQSU +/k9fjbM2mfK9/k+9fInC8xxBSMIEXDlZtAJ47Cp+pZZsoQD+QOdZFobeueUvCrRR +ROOyH8e/lETR7BNliz5UHsy7XmMWbrnuETHPppPe1xMfboYJMOvusijjoxyq/PBW +66Rxf2uW9Divi7K5jQKex3dTlE6NY6ZB/GxuRflwng444BMbF1S2eeFf9np5UNsX +OW8OspynvCvFCWZsX0Y+TiZwxc1SR6+e4mP+vzPFnXXwUVppC9EeWlDxeA/3pJI5 +ySBlYdJ/6z2IswLtnKWdz/WaHiIjaGVS6crlRnIWb25KiDpngafXuo0MR9IbQAjC +DUmMxTmSfAOqGU9NYU6uvFnJtAKQmYT8uTSVjr9CUG4cxrm7zUkbUPjwXzI3oTtB +HOXdpAP1yDRyzEzRDKnAF3GAtIriXW6mK72lbs3JgkHDZW1BH49hjEe/ZAsWylWn +xnwQU+OjGR8TU5E6nwEYJe5Gv6QMNIA2XVtT8S+6T9rmCyey+0miOapNTCz69TYZ +YMToBL4esCzDXdcKP1BqPWr/0q6S6/Qe81CGDbbDG5bV0TfD03srjHZd7oAE5+DI +8E7OtxNHW9WwMa+5DHhx9uJfDpkQ9VHvv7MH2OU46tj+ol7otyEhdzsi97UtKiRm +02HZ6XS8oDSQ0m/DYMAIE+mnL2KA8RT/VZ4lAvrwpYZd5bECn0R5CPR2RAZda/FX +7yfrD//kGNEXxa0MRkuK1dqH5ptJQrlOmqyf0bk6ALh1Ti1K4DfhJlzFZFeAvY7Q +9948UhUayleR6uy75y0g4M96Zgeav31xy3zMoB2MEAYsQIDvjHtOcRiWdH1lvvlC +uzIQ4tXsBf0x33lcXJALxtcxGFt+YnsFjRvUracHoflsBngFTNysW4S9iVp4bd34 ++zllCCKqrIkFMAlOp370B92FQAFYT1SHxu3lFijAwDVy08nA0QZCWE1pvREpTOXF +s2T+84u7Ugm50xZPy0llvIChazoP23bSQ1EAZMHzvivffNdHWDoTzXx0VxGesgGE +7N2oSobKXu06DIQyezFmaF7qDvg35dLkFGXDJ2Xy/PBfggQyCwLrlKh7GL2QAqF6 +URFDmr907F5I1s7Dk5grmp6ZrJX9zl0u3htGiA9Czx9rs3Cc2Bq/zrrwnNKuuCTf +up/6wLjnUMFC4NPRpcc0VZXCCQpx/UP1eWTNL34nWiOk3+kf7RufblPmszcoH8W4 +4NRGx3hropoz/Y+XCglQE9aESTS17ipHQNcaClO2Hm7+pW07bcbZnjBFkSJB9lgS +CcAq08+bPaK56d/+7xN9+0qWp5fFMM3rc+3sr4aCC3zbFaOnFACVvKMctSIemIH8 +wEqIgyCkRCA/xr/JWw5ox3xsGIeJrZvIgfb4YGNxj8YfyNfVKfkkMpT6f3yx9sgd +mEnBUdpq0O0CV3vdW8hIIpnbAwFA0SXqaYUZwX1K7H9cCEbsXLpnCvGF3jMBEI8v +t1W1TUB20J8/AkCBjx1UE+iprOb4BRSgKpQNncidR55geOLs23TLy2OfHAl06WI7 +FCYX22wKb9ll2/aSSr55oZx6BOi70I/qK4V9pb+l4gCscKm2yT/wbU8OwLI2dA34 +Cu+wzGadBV6rbfjqIYltRpjgWcKXbwZwYT0hA/9ZlTf2yRKi60xJ/1hN42um5XZx +fK9zOYnQL9tQFhx6/iAp6i5XhwyUz2WUTkECEnB4oVefdk34ZW/ePC084rEDHGv0 +21Z9XXvLv0bVOMFionuCXc7x0rwLSuIHIRiUiTlbd6B5nrp/AI+4kMkM0AkybBkI +0TDchO1qpjslsfCyEgRqR3wwfBDcVU3PdjNmcGmBm4ONbc9qIF7gn6mHP3kIu7Yh +tEOJ05+5cK6s/TUMHT1G7TytIYILKz0yqHhrK1tc1LuN5LnegxUAU+u1uQnQr4gV +4dmM2rzz6cnSf1gwRCl5uocVlIRW5m0WrGTBB0+1k2e4RawTAwKGLu40wn/dnV/Q +yiN1YgltiR18f5RUSy0CPFElfshZqVj/DAAokp3flXHXc6E1EK7ERFIRS3ci1x07 +gR7WMm0dGkm0loDweW0PWt/M+0fyuHyd6H693MVOR4fwKTI9uNlXwdW3t4CERpvT +YXkpc/t4Scv11jAWGkjKP7iZEB7p0NeHpoiEZuU1a32tOLBK0H8AGPjV73FvmKYY +QwsbKUt1lyTF/bdrMGCae8Kq2YPCh0mZdWTVvd1VBIiZWja9pmNeBdcyMYl+59Db +5OLCuuWdLEii3vQpot2Hyk06KRDSHPFouuzajGfGMjJUNLj26pBGCOMspSlbPIrF +xfAG1CH+A+4lfdGNcXT+2fch2AHUcHA+VjAL90tbfIx35LwCiClL8Azjp8iM+uHB +ZR2zkLoOpv+W5Z3hHl4ztKWiGmPm3HVVs4YnIgqu4+Yhu+8u58fFzzd2N6+U8bpL +VPodiMg8IWncWNqP9rL5P4vFAX+KBiaO4qBGOxaefqRIZMuLOXn4t+69hMYM9lPt +k4etbUtGLuYA3qCMUAUhLuLcy/My4KSQUraVAQROpGpv4tD5tO+DgiYmFOidarUF +Yv6ggVEj0YB1oIbWxyERA1VdJ3pY1RQDJJM4w//Ln1pcHh8DLUhJuX7ZtlpjTOqX +tNZs7QdzuHNkLP/hcmnMrKFTKvwZKHCDvqeuCNTzam0azMbJYHhvTcteimwITnpE +VScfptia10iOR9Bqh32OtWkQpTBaTKUl7k8UuXdox+o9RcMORrnkZATxCRILyGiO +IKSFAR5vo8nRWjkCkoa5HGPHOySfadxsxODPFCljzlFYEwrgZpX+MsoxqLnLSQKN +MXEIdtpPPuXKHfYPkntQ7l55BkPOoYRF7Tx3POjll+HJOsQjJESV3Ze3mFKZtD88 +1b4Lc33Qo50lV3ysQE9JHIwVgJnmzdXKW9bOlU1un+w3jJwIum6JEq1GcnneCbLZ +tkFeoN4cCQ0dFuNYwS5k//mQODb/egxI37UIlTWm2Brp6szLixmT7yLVVZimpVrF +QlZXeWLxgkJNKvsRyd1MFMrK/wE4LdG5FSrpwKck65MgCx16MEgUAQDyHYMscZua +ZCCdomnoBE4aOX2ROXKxUZTBtK1iD2ZUWvGbviejc1p7njEK29FKTo/XkYhgiYhL +cD5WRJaAd2cbz9Q50mxeh4yQWaVxPqkNO7vNUO4f14uradu2oWQvNabQPHn7oDxK +OAkVC7NE8TkYbYwON2D3kMMZSNr8edpslZFvFSpNKa1+bnh8//y0h7frm/Plw77x +Kp+1Uth6554E8bwF5SH/UKacqU4fBfu2kjOiSdD0QVZLCzatotOe+Dzzb4WFRVgu +R0IrZX/0BdtwREriSZS6e0NxIHtmXVlpv4Cr3IC89CUNg9aXbDFrDhTSV3XwJzvW +r99Za9YvqQHYeXLMzQLGYCFJLBirQkyY86vFN/rvrIi2jwzWZ0PCXeuikXWRnoTa +QSnOCPZJrXuyMwGzQ0KggRaWbSxtADK45J5pRoc8DDK/DG2iNn7oNBxwKmC+ZRf+ ++9j+Qz+GzcLbMxD5EVY3x/s2DEHrcJK/GAhu4sq3Ml/Til3LFMZ9gouj4qtmETf2 +9K/oWrlnP4TBeRf2kxMg9T3aB3z6+J/Zbq4UcK54EYd4j1MmAH2XCuAeHBLWu2U0 +r5GEOUxcom9JuSsY3Lja6Cb7cYM9UBHUlRsVuhfIb8jFCPevmNyuyrstKEV3aliC +IReqKbG54ZVNxkcO6Qc2sZSlS3UonZa80seiMkWjbNXTQcDVnflwL9cE4LOzkpG6 +iYz+Nti41py62F+8LgE+6Nv849NNhfwR/pDf0K6L5ltlAgGpRYY8LAeBFQyfBF9C +7BwWgNLuGSzY0SzgNLXIoANTl+WElYb+CBOwg0eE4eZ/F42t8HTynzom9Obwi2Rs +5abOTaBJxS1uBQ3zkWlC0qHyo7et93/sk6w0Qm+OQNkcPrZrHFNmqSq7gkiMwek8 +B+PMXBwxxbjrGAGXpa9rn002y7CEUAEKzU5QJ0v/VC8GpGNscyXUHjexA/8XKN0d +c8Q1M3r1Dwd+Y8rHPQhyHtosM7fC3nHkSvvGBOzODJWd1PRWHmKr6brXzEb7kXTY +2t21hSpva/t3ciKK5LwJRct0RBqLEemFbmckNBfY2veln2ZQUDcrUEtzruxKRuUJ +RDJ28vH7h5u3N7zV80MoJxUIu3KphPEbTwQxRQbuN0kWoftYsn5VCPFA/J2CXs7m +9Xgn+Sf6z5dXrSjuE4lGL//lYQOVLrfYOP2x75Vd1E53F7OxCA/uuR5ZPQ1xx3Fu +1Scrvv/F7Metf6Qg5+9/QYoiLDazhoA/vEukkiIJgEqVMxNkSlACTSmT0VHf2YdG +Vj//NnLpVMGlG2bzqov4ZZjeDdsbzXpuKPzO3y7YR5y4vUtigXn2RcfnI07EKpwQ +g3UgSWN9kN9IktvCD2DzTmd81+YldMB19doV2dmfBL6sVDOz6Gb0DKmj7lm25uuZ +S20MbaB6lMC3T5IGJ+g7fvjh9NgFHUVIe9qMArIOdg/B2N51gqVPMPPLRCnXGHLo +b2+5VH2yTrCWZAf3TpuVQHguTEgc3JTds949d3iZTWLHlci/7QIWXrJfH1Fmavq5 ++fBdr3OhgxuQ9bUmZJhkLjzisi/2+h7oMFvm1vp6MViP8oJ7OKEVDzUuBTzNhOo5 +o2AMZHUToxUiOJgTsE0dekPMXQN/Wc9Vv0mMX8VL4xs8S1jPtqC+kYDipFEJgVGV +9qWD0tQbWtzItydgduu8+Hy4T7pKuoPVNSHHyaF3IRpuTdsFJsfivMyIwDINMPA2 +m4SnnEH/YRbF7TcJoeFT98ajCFjQTf3eSU3GFe3htwqIBeQhtcgMQm5L4wVw7gZv +4Y0iWsFCDSSRNEXt9/qGum436gSki6cb+fd3YzOak20qnvXTC9GMaJqp8TmQI9AJ +h4q659XQ7SNI/wbvYPtNOCVUtv92Mwl6Gv2TkCU0CsBcJLwU/PlRwgvjkkoPFXkN +fXgxTJ3dB4KbLrDbTj/03iSBxQ1k1XL876bo4AH9cIPshAFMknqYaXn9nr6Ofp9g +3mM7UCJC1GP11x6mMfdNxTHdUFSfi9TS610Q0XydPXhGg7cJyco+Yi7We6kA1eo6 +lQS/fSmy40mI8bdRZJtLPF14wdqHloNf00sWtdBYmjyrmYcOaCyGc1qcCVU59n8G +29zLUXNCpc16GoFlp4ls6excFnzY5L+hXPkjovMEmeQifVThcR2HCU0fAzLNSF9H +2q7m8uJMLZCvrA7lwqv/Vy6r7oZ9rSIzEirRldZmxDA+IdFf8eVyfgBqNE31QuYB +OztBlAcX4fHC0rKjm83lMJ/rvTNXc5fgXTpVIULMaj1kYID8wc4Ju1MxDibI1FTH +n5+kxSyGmvogxppvTXoH1svIn58BZtFZIFdjZzt+XKAtQDoHCDdkzZOuaJ/9bVZE +jt8jUSZUrNSztzhV9DmtWUkdCQ0iWUGywPxWJsXcU2qjeKhchCYH/HrINYaY2j3j +LZ6GV5T/PdDj9q1RIO7KGB+ejAKtMX6FmTx2kdVaB3F5bdY5o5fi7p0g0vL5k0AB +eCrbJ+hx/SNFnozMcFOARX36BUBcXipgWSvDNH3QHr+33JX4hyVZYBDHrvk6qFUk +Slj5uI58CLx+GhFyNr+t1gtxMK33S7NeRItmFRLgYbmMFIYCJdGqeRjbBgWhVCwA +gEvGCiF7r+4u11VpRo8w5sjFZV8TRqcStMhNUndO74aBDVl5V2SoMw0VqoHAndec +4h+XkjyKmrmnMY3VCD6g9JwYbzmVOXcLU//MkBPd4JS7oW5uoP+LblN8/gryHjuX +0HoWD7Jz1W9rn9HkkQhFRpZy58JjB0ob0gyLqRJOygU520S7oBrb0w810pJ8X7DE +sJ13/VoWmjhPz/rDLBUOuXS/Ja3RZFPkr0uRQ26cMgos2LNiJnA3V2VIxtcKyXU0 +EqZS1+fjVRPDG0tPWK/nco9Of4euF2jx6mIAktXYZ5a6kzHo51GeNZg7+NZWP3uS +V1g0B4X7hKuuNMVjIB576z9Ha5amFUP6+VaODCM5nTL+aCpP3saAbXctT0/zDIEY +f+gCOxB+r3jJvCroFzUgRPx1/ZRNSl4YKPEGCwN9SBTBElEJ+JW3+fxrOmmzX7fr +c9JP0IWkMApj2sIvLewE6qnSa5zOEwkkuhfX8qFoz0kr5e+bDr785H0NXWbjkVAz +iguslNJBS0izaaImAJ0Ht/J2zUKbHRl27q/t8qkW4hEsvdEOQY9ZslCL2zkHmVkr +4oGFTSlijDOzqBEUPGcDr804Eqf2A16V8QcinKBk9zVf9Ji7PTcygH+xqH7GQiDn +8S1+JRK1NIVD6K4EzJZIvPGyqqHaa9qP20AdmI1ms8tROCzFXHsZDe6aW+4SuFYS +utrspTXDkT9I+d/ADy3zDW5q4jn29UJf4iIGyS8TGLiVBFwPuh6PA0YkaIBnsXJr +8+qTgpEZhqEsTV2PB8uffpyiL5YtfDMpCAYcI4eX5XZeRkLxFQcnSf78KSi+eUob +N/8pCi4hwQCBfrs9iJt715Mz3ss0Rpd68K6m0i9zCF6wUJq7VuQyTamFNri413+8 +V+EJHT1yzzfHSbmbavNQ6s+6pMBRuxSPM6LjAVC3eE4KGNziYJR1wR82nNyCDQfD +IUFxbpqU5tOtyGE2Dd8KqkgncSgKj2HgMJqi02sGZT0DmzVmFoMLrBTDQmzDRBt9 +cdtWlHKTw3a6TJ+/2ccYiDfdz76p9IeaGMp45n32wX9hsBURYsUny7GPKGIOqGJ6 +UsG1I0Dh+5VkK9s+APHFVB8OPMQV3I3RoYjoLXl4Lq/Q4qCxdR4vK7smiiGfBGFk +4misreWjqb1d0HpRhtyVakllsqzUH6u2i04Ip4UxuW74QCfqUChnQRqOXZoQMEWs +KbhnJj93q7eabfDzn6f7IYLZG3KiqjkvQsIKC29SfXRkN+daQXUmS/TCet56E/CN +K5Yc0+jOMcUv5y5AvvQLPP54DohSQQjtE6MON91Ve0TV0ssjzvCSAccVNdqHAAbV +3bKeh8SRgzo3znxlzy3xpkSTXj38E92juzTpDSL/zL9CxFnWv5qgiNrw0Cii+M18 +8R6O4xA2TMRwxeYb7eqE7KeGqv8/vLYlOb0y/v/q/t6ujhy6z0UY3wU7l4IGjNOf +6H531BiAVGP/+KADJU67+ohYDGbPPgLdTcc2cDf4+NuoAbXp2SQCTHDmYtUVuZYR +obeFaMmnCZlGQyYtIdRDWUa6Eu8YC/jDi5SXewIqFMtfnpdN7Zsz5RMEpALT63Ml +TywWpiTSRc8qj7IF9HgwXT52VOQwaTFiMil/hW14+vZTTsI/Tn9e3uHZU3Spczf8 +oe2ScS/rS1Y6hqci2B/vPCUfy22qJ58bLz8ZDU5vvTksZhN+YuzJBVpCzvSe/uYl +B92N7KLTCFuleGzvf88YpDq1tbXw6AwJDqBwWLT9r/s6Ps64HfnCn2DgNx9TH9GD +ToJrqXjWLyuo5IqcKn3b7R7gNHvtrPCueKbMEMqXrmWQ2X3JmkYiPKWsqdTK4kg8 +Lx2R9ED1RLlOLFakaSHUyy0H31A7600OS0gF5L4GoBAJV+z8743Qmq73wYCPlWE4 +pyNTQpErt0cR0Nzhto126Sg2m0tzas+aK7LjjubpYQMvzfcd1359MvVTSamwkgY1 +7D4MYzGKxLlnOpM6gfzs1Q7xL1htmo1TDJiFm8xt3L01QlgQEK23GwHUzJKPUM9v +wFWDTtGTW3bQNUzztGTDBBU/SNh3aTM6dwx7nnZ4zBt9N6Ryy/Nd0h+ADrszIhpo ++9ZyUmQKwrxUpuzYH8hPv7+t+P72195g0jzco6mcHu3C4BdV6o7hOrvTgD02O9Vj +3VpdZtMVVgFI/Yjph0jGrrYPSK7p2YLtlRLCgkmataiToJ72qUruDKmsG6VG+kSs +pdRbgvT0CpJrKafcUajm/F1Hg/KBkt7kvGp42vNz0iRCrO2V4NC2gO45c2h4x0cu +XDdp7/bVKFHkmDur+G2Q8vtNjBeq2VSHxvr5hkLAKC7VFdxUF+DUeQH+7ntmvk6N +b36K3NvW50G6PKs2/ZBRp9LdnHatz7ID/XX84hHJ3nZso1aGgaRGVohqj1hZaAzT +cmg2F7CTQVTunPja7pNDVEIrcIaQgPKkmSgr6V69HG3Smbwoxqlh6x906hVpnXc6 +FNmm/B32U/skMIZ+QxHKSyYr7Cv+TZUIQdIlo40yHP3sB0TgDGGIeDOolojLItIH +WlBTbj7U4YyV6GvYoxOoRPZWYi7NRtlhuaIqjYYaxl1nUt0XocscmyNjuS9v8H7C +WldJbbYwI9SvK1grgduionADeWqi+FeRlzS95IdS9g/kE2jnILVzomx5GtoA22cL +zhr8cOhlO9WgyOhYcHR8X8jKfQgs98S6M3cvHJ/+qK6n2mt7/Uo4LrTkwhw9CMJV +oWD/qsWPPlncobVvGXA9TrwdkJw184wxcvEPib6I3spXWwFBmtWEkCe0s9TKkxVV +6YdIFW6TSJ7IYyT7CWValUuKXkp0zSNcupu7KBWlZqa4EdE+yrKBTASvAAzUDAvA +WJ937GcgcWfHYBnWVYEUBvtKuRIpsRXAn/h1CXUyIHaduPIu1ApMfvFy39MkN4ML +zkn1vFujQSBVG5k1E6jJeIYET2McU5BPVPLUhOnZCm2AQTK+N1vg1xYb7f3vreBF +H4z00+lXRQAaxS59g0ZA2M+g5zBslXOnRYye4gLCBSLERDNcd6b0yvnI45dcC1NH +RSz78Q2IJAov95bJeaAr0RTIHaqEQ6HcA8QkZHurzS0FLfMvTawegP8r1NY/3h1l +tpGc0sODe/ZON5hRvetP1HGH51fGMskJyjHs4w//fAnQpD4LBvJrLKxYd4CyxhWG +OdXPSuPTZ5YORVeH6uXfrFO21NDJzonwXMf2xGghRajo3vlzMYenjdvKbmEWrAIk +jw19wD+NqNPzyngyUv9InNIW/UtNBbg0uBN/c8AMqEiolAO7kKtBbKxdWLJHfknX +JjX0Y+jA1r8ce5TKz4ken9+gy3AeHHM+Ex/R9T4Xfgm9IAR6wvn4pFlw61DhpcTd +RnVjBiYntKwE2AVkvcTbyxzGQH1b7dX1fiH6QO8U+EGF+tbqmQt46EaSy5xVrk4z +JBe4u8GZUbwSK8XMSRPoR+vp8LmPa7nGbgko6Bg5RD5C+GbbLFjbSvF/QCsi80lx +1TXJw143Y2xTX6jAJ8lTPIDX5lAkklUz2lIq6pi/X3JhsFPxGiQuW202WaXC1bF2 +BqMemAYXbcq2gkUoq7DzE98Rvbcz89B2jbLcmE2S3Yfq/uJQ23rZyeOLUH3Um2zs +BWSccjf3M7B4T+raN1xjSAWj7uF/gYCVXbGRjyPz58ufjTCktkuwP3BVmtZn5BJj +HUxNYl7oHyBexfjpVOAf8Ks5R8Z+4tg9lAiN5Lo48oQ4Hj7xOsx8IyMTPBlAViOq +gBwNNgoe1VEpEnMHaCc+sQ2teFAAGrByJLRw0rtnNewtcrCWqCnhN1R0bY0pJX5S +UUdjJJfH1SeMewRFFMRo2w2hb6kDlhUGGNPwqb0IFakluWl5FesLiDyXsVacE8Ko +m8BtThecZGu4jHrnyV/3U4NmLRAmpxr4Hnk1f0y1KNpWaffb4zN56bI1SvbUlU/h +ahlpHWW/7P6smjdyQYOutBj5AobPQzL0BioMGrllcnPW5mJ8+2eMc9u91Y+cymrX +/HlKjKEYaHLPFjHUtOALuxJPinbgpjie2JW/LRdc4ExXQEbWQnE+pzm8LKpDYrvz +/gfsVbFc02CaElTIXA6Z6ZEndZom3txMcRto93xdLZSNeC6WuqkjwuiSvkmylIQ5 +qSekln4IG5gzNW6UGnMjVemKRF9URrQ/r2r+wq02JPHyUDQ6495As1vVTGc79dFZ +PTX50jBThPy5qxj0USOjIy6PZBWiPfdIIA+mO0IUO/K/CsYgyarAW71qoET8+VUm +drs08v1Wk6mKd40TpuD9WCLWgulq+vUw6IX3QDjKoXcDb+MTBXkHm/55nTLWKYaL +l8jYFEywRNGrEU3kFHU0b1GpL++Fp4P9g/KNTfmqE4TYHLazzYZYSVoYpE7spvQ9 +sEEfjXg14VDORR7lSEWqNY1c2jUh17vClFTjtlMphN4ybV0V7VXSzr0KEI4e/bmN +iPH00fYcR7830Gdj+SXESi8F9PLb1DbheLvRNtlvmjPOXN4ra9o97P5yK4hAgqqP +uQ6PS1GGU/rhQ68UUutEL/H8cULW9ZZesYPfDP+Iywx9YzZvNUKxAY4P2torYDIQ +Fj6PwWqd6plile4R+xdsnCFn3mBO5uAG3vJ+AAbebFWye/ogxxHoW1/34HUkRrpZ +yBEXiYttWdEL1XeDv2RtwUsmYTmA6j6ZwAqSGT6nxk+Mq5+l2yhSccwEetgtVnzv +daeCIhIptUWZ06l50hzuJaONgd92InH5imVHqHSTN1wolXxu/S8R5UelGhFHWM0J +L8P1h9bSQDQ4bbJRRP2bCjBR/pxiEIhyT6Jous/jwjdNyNHkpU+65DYZRImF5+Js +qhayXY/17OgiU3R8GUz6YnYDFFWKpyHAD3unnylCsBmEhHwK9m2QytJ9PRAW6T3D +w46HD2ULnHNZklgZfpRt/Q1t47+E+ZFuISu4FbJk/UatHPTOFFhq7qhQCRZTkpUR +7IiiVVdx1szPD2xD+fALpQ6t0GU2MAm/UI57pHNqefD0poApAAIpu/x0qJA9j4Yd +9vSELOgbFtTAYPIhnktgRPvqDr6mu/UaA4TeJDMtT1JJtHzsUeSsxD+2SlPyuBfd +PGv9FK/oLHs0lB5NRnwB2evCHtvI3SeAQoiXGxlKhWcZJqljbaxjOavs+77tIQy8 +DcjtI5/lo08PK9IFeiSfZ75dlCf7iKnDMZyFGAGt8AOaGgICDQx3i1cbk2A1H0Xl +IAYaqBNBMJa7CO465QWJHrsI3FgUQxnoA00yxdgTN1f7QBVhSHHIhlHk4lcRMyxj +m6KRUwU1DchRBFhwGSrw69UbJc/iFurXEIJzlpLB0UliQrDHce06CzT6QfJAlLHu +NEDnngJs0FkNhwgBTjXalv8AUz9COcsZgjcawgGTqHkgEg2g4JCxFeCLzxYClRo0 +7vjerQF61JGg4s8nDwqmjX2PHaQqkrvm53a39S/U4o2lSai9OIQ3sYH9pbnvDX2P +M87aTeJDjBMm0dh9v3FArjfaLKbVFQnrHjLZeeScN+5eN7xwFx4cLVjIBcKX9BW1 +j1BK7QnX4s5kVLMeaElLorS1HwEbTw50G1avl6vqwxHs/Pfujxap/Fj5iKj61Rip +sARKymKrdLaS01HnpK9DOblRx0VS2GSEi/GCxbL+6szdrATdbvbxWtA+TXVmafqZ +9K/6Wy0U4Jm0H0Lz51QSd0T7rowHqwDUj9gYz/w7QkKs+RWwVC483nWjg6vxSi2C +QTJWiuz81cMitrQ4zaozkRVdhidFkTfwgXc8w2E7Fd6hUh3PMAIqdzIklz77Y1xE +TUKPo9+QnIAX0tgdyZ3TZ2SlFIJd/bGV04FOLfBZArMmsw3rV8T0clHaY/bWeMhN +ykv05867RokmYkaIqbNgB1VwG1I6c+K5mOwW4ZO83VzfymhHTSyvEfLsxXZ8lT3M +/Ndot7RITLNH1hC5fLJufEUazxmqSejhqVMssk8W8FFBzIL1/j8guiLt48o1P9KT +y0Y1OHqbZ/+2xpy7zsNbpTkVtLoRs4IJFGCmUQS4/GEOesZs88ofUO2uzXy1CM+J +FXrRWNlVuaCDRInTh4eoZj50u1QiUasSvknwpt8M6q9Q2pQNXvo0cDyUo3RL0LKz +dBkjEca6iOsPVHYWcC9O/mvFdMeg5NPjnnd58p3BeSMCfsZeDtTzB9CVyz7SnCT+ +7iBAZEiJNWe69+ANTlT/BUyWko+UPklHw4o6udGhAfROK3dm4lzjVH3NxaKrulfr +zdeDTNKnRU9uN528LmxcqwASneANjQrCEtkRpDFBPJSSyrXwj3lNLAxMeyitmpdq +n9LPN6ZvOk1rhWIYrvwb0qQovLT8gwCmNUVZsThktEQdL03LLRcURVaaBF5nIzJk +2DS/KBNwDAlQTpT8nyhnxjgu0HA73X6meVjxcCSi781tBkReeebjgI2qupHMtnQn +G7SN1stTNMyPZm7ws/2Uu4yQlrqWiyp9safth7IBOwz1UcTrvVlKVa12rRY9WKVr +HF547gURkYYxaF0HsLveKgG+4UXitnfeG7UyJ3Ra/2/0vhb4rDkzHK4HWA4ukbZ8 +wcSLf8KQAmV/jWluAI1lpO9Hh64XPwZB6Zi/n/QB67kZhdWwz0Wz6xgulkqph5z/ +sicS/WBbO0hya/SLz+gSHOXw47LRT5LK/M4OojCGO6rm05W/M2QdnqkS6BP95jR/ +Vk7+amH+Xm8++JXyVS9F/9cebmNAB5DUWT0+6FCmCwHtVkcALvVj1h1FLunwqa1v +28RTsZl4EpZPdc3TuxJwDckrFc7ZJ0yfnBIJoc+OHjJzQxBv2RAq4MSQPasze4jq +KoH+Oj5ABTt2jgFP6+fJmfW9Gt6VW+a7yvbDP2gAFto4fHfpTBogw7DVvHYCdNIR +4wbXw23Wii9ORA72Exi6cviVH+2X+rZKWKgofe2jBLiK9a5+F05wwSqy3GZcPXas +Em45tYToV+oUD1lGidSYvsOqgJ6MloxaQlrACz7D77qKtIv7u71rRwHs/DgPt8eB +692Tl5nFrMpS4Hrp5m7Teo2v/Au9gLJBphOSzIFjUuWreSHzpgnVU0MhO/QdWUTd +8rx71ccVQ8wWHURBLvJLDeOck/conjw+6lS0ZSylXvqQHraMAFvh7qhEeyHWGGLf +nVIaiD5YIGGaKk6k06VOMPR0Jlqj3wpB8rlDzXPKUVLOZO1WVYZ8g6plGdZPe7fR +Ii/+aGBzIOouLvaFOiWG8YERJHBV9iuC2VHFQGHXW9uav95Aa3Tzlea8RCdk2WZj +94XlkEgTMHAyDigqhKn8WF28loZA/uLiDvPltbAVX7hD1JO4P4WwaLVcIEpWIU2M +WfvvhjdO4yZOqBp8lSutnh2OF39ESAVEriTGuv7ICtsKm84L0BCXJpeNJfYH7RSC +mU73GrnIYHm9Pp3TweClRI7BOJf/7O4mQ4Qf7AVAuWG3kkbZxYoxXXVB6KCcbHuo +taFFYT/v/5bTOYDmHIC04eGH0N1+Aq1IWpWLbPAekOxAj0xjCSYbpv/tTr5Ce+6f +l7IedQCMdsjmCp3p47JFhgE1cPu4VCFO9ll3GGllbXhgnx3/49DGWCm8sLTtc0Rj +95mk8gnpF0Rp8c1ddfhLKZumxIKEG7SVNYoH2+ETpp1sac2keEWAvEaLc4obbN6W +45lWGQzTNlJAG68hUMrp77g0nreJlBe9wOX6yx9kSTvl2zso+KFXkwNYzrcyYIQ6 +Thzy92C299qsq8qF3WiUD+INJyb2IzkvWyWzT49NxxoHFI3I8L//8y81unuDgekG +y6m8YMpEOj2uu8Er9WMuchvIqffrZsy1NmiO/MWEI+NIpTqoa9Kxr29LJU/RTfpy +/CYhEUSkD9ESatdwHPYlq4EYDuXFFTvJoS6YfitnBTT+w0gZ8fg+iSdJ0pDPVhaq +uWeSUMcFi+upWNv+EIdnm/xFnbQHbih21R28eF88yezbX05TcjlUp+4v7EvOEY76 +F/kymR22sBhrDqCy+dFXuEGv55fS80CszxaqjS71cDRgIjW/lYPFMyAUaQ06Jp8N +UKhWQWM3lgdcQfGJ3Din9POpTAH8ZXfy2BKEVwV67qZE5wUAu8X+Cpm569Q2/0jB +JigIvPiJOWEx2fWvIw/0bCifa/FEua+yPYK7d2REcVX3EZDkSPWZvTWNWomOdz1C +c6v/XA3sic3bUwkoQDEj0aO4nV8u6d2rulhbpm/kbEEWTrFz4WzqutRn8uXmFqZO +INxbXMoo+lltWyEqAb3Tlc5w2zDmQhYh39qKQZKdTXkuEecI6mY6kneuVrDY6tkY +E0Q7uFMKzC4wDW6csXW8aVjkVtrm2taj5dwkWd5+5bYe4cZoRP+PZ5moGo8wnkKN +lfC23mUu6uwpcuO8+qLynbZLDImo0lFqAXq9GISZd2WxFCw1TkBGRO1YaqauzXr6 +Uc3vYfu+RmUrMQz1TTldEAcCA4effCyIz/670d01/jUQI/8HLxmHGzdDFM+0Scxf +0QKUNdtvL78wB2KgIVibRvRbxCt37ahtCS/edv+mARrzDL/bOv+dYNWCQmRlC4LW +CkNqdq9CCq4Hj3A3yY9EpgxadM2TtBdE+7F7y2I5AspqsmrdwR6wu7sqxLsu8Nns +HK5fA//SNwjylDlI2mkhxk2sCPt+hA+XWIxxqWXw8raChqJfskqd/uJPZ6TkxKJ+ +grkyKUGSeCwf6JDdWDPCdz2SMk1symxqsxhWx6FNu/4NY18lnHL7SMHN5JbdIE2F +B8mP/G9ImJKFz5qDGRjVPp797cE8dCXjoVAo15aAC3izdD9W2ESDrdBU2TnBnsUp +gbsofPjRB+1w2jmqISgcHrpxnWZ0Z4pUwsBH2lz2HUAL0VPhOpeljaaTnmBicJba +rse1Ts0IavEtToZCXH9m5YgyGIMGYUHGpfdbhN6p2Wj7AmlS/z+GqomtP9EA/Nqb +PuK2daPeooN5uPNJdxHzikJ2uZv1SDQ8pzz/LZwo8cpomhm3KtJ3xl+rLI96l1zG +Qj/lk4Sit66IKTCQsnhB02pQZh2VI17xVaZSgCCcJFE2NJDkbjTUJvle5sAbDK3k +q+3EDt60P+UGj/SVU9u62R3ceqX7llwts4DeWK3wIgaK8rnir+TXZ1GFHE3KBb4l +Jj8617U/PyY26wb7pKqAtvc7vNhdLhE3HwOkgnrK+ByXdqEcrDUmQ8gK8z3kMId3 +cLwRWGswYN2g+A2J/c9Vdj6L4TDafwU4XI3rTVHz6PMY3LElkxILnswQZDwtprmo +vyEgfrugo4DxkTse4N/zVi3s9B2ZDwLeWbVqOYJoMIch+sq7oCMhTTABQuQr5oKY +uY6HBmWuO4brnqlhcqOkhnYJEriZCdx+BbmBoNTbQkdTDk+UsDgbqbhTDQVl54V1 +sKmaUlN64NnXMy/T4j29CigC+1R/o1ycECXqmU6Ks8J0liU5uuWTLTqwb2EF0mjD +BV49yJDw7551FH9h6FCPufVqXdwbZmh/pIpiCaEP6FfgEEURu5nQFvdNSodAz8n1 +3NQyxpwRSEEje6K22YXLWnNYBMTqPWeFQnQlfI7vj4RmFFeGWj0+dDWQ3r9VlcE/ +s/+1wC+fa/fnVi0ZgTiHw8ONdiVOI0dkpHxpuD5Dy6uJWeuVe3plS/Xi2qNaMVQN +GUO5eEgTuWZqkCfyTkNX8xUXIVx0d3aa2wX44Z/SpIaInuVN10N3NJVcFZBr1XuE +wz5g+J8YDpBHiY7GWuYr0gZXdKAc1dQGpChWFprBiPuO5925Nq3YlURtlSiGC1cv +x8ikT1Ryo8N6jG4jU7xp1N4ZTHnYX3h3KiOBpbbxmSdFW6Cy6qLmtFvLd2YpwmGi +zeq01dSEetuM/sJPSxPJhGrKJWTlHePoj0yPH2epKJMciXujWBxevL7TAOE5dEgr +NmB3bLlP7bi2yK4dq5cLMrq4q+zoL0q6Y8F/N/gHRARLmqEjoJShU52W1ff53Bt3 +7sNF0wulp58gbNKF1/4WUXddOZTm85lHjaxwTOg/ULKdw4+eZ5kuBlkrj7sLiVh6 +/qoc9Lbnz0P8TvqxbXvFoiZAd3e6Hhhyamln0mDtLlkYWd50JbgVmvNm5QPePGOK +hRpBU8U23O159qrJt8+d8fJlDIpubfrFm76fQU82mdE7s7GcMY2dzMzSiMz4OA2H +gNFSwBhqFzXHVSZiyAr8t3GHt6Pkmtsm2PyR2fB8nGLM/4knr+ixOPuNB61/lAta +vuFTFFD5Jmb1t+RlGbzL4WOEGDlTXkP7j6KhDTMpSgw/QPtyDpi459fBFmDMHvLn +9AgO0925galW5fZfiqFUah3QYnu7u/hmaYCWQzCNEwLsLzq2QHTKNUBaORljvFw+ +tCpWr5aMsfngZLB8Q8KNe/wJ/oK8aArSYsXJ1eoNp6yPDcWvEXX58Q0b+OTXCM9c +vmEIgcHH/Ir1+C3HCqJreSZBT6Y+M9hChuSDI4/WnmMjfIA1Lho+EnKkZEv9nREj +A0PZO+FJJpCAQRwScZwGko5gfl8eMBnMR/34VS9Hh3GvOzpCHWDMDqxIe59ZJaRR +aFH7271RoFBVnm69KZjIcuwaCmM+ylAk2kwrQ/XJzNVCnMoftS9PD2SxfTgdJ5qk +WVabHKdTIpc9z2VVEqkJIEYVIiVbPxqETzpfRXRpatDKV3Jrc5X5LE0T/XhKXkwh +gG/Io6b0Vl3yKeBGDrz3yNnGu/TDYudMpUUH9OsEEeprJJI6XRKVDUTJW70WM95l +hY+fkfjWY60gV+vKWMaux3jh7jYsmTDwhsHyBzhrpd9VW3RUxyuvVyquzcD0L62z ++DiVt+8KwdcrmUqF7Ac1lqDnCpkTxeDQIzB1UEzRhe6Nt1baeDJ5wDs9SO9wDNct +SIsMJdT22R2y24sIDH0aYD3YWZdTukYXnlZChs/48eCYak2jF0qb5WkMiLO4BhJ+ +4q1RzKlHu9+f4WF0gqxuGY1nptz8mZjhfFTUK++TGB/e5a4saaH7nDaOhStPllKd +CIT1uYVqToPgHkKbdWhVatLV7n8pksrFrK2ReiZ1LCdGLDyBL8+/wuX7gPbN+BHZ +Bn5uPihdth4G0Ak95jRUktebR8gMIXTjyDZImXiuwF40mKcdtKc7Gi1Dj734xwLY +UJ33wPu3IfZjYv/PDg82YOshAgLhUzsGWIrxNV9Eu1dqNqpADy71t4ZJTqBUM6b3 +Oahvvr2EIB+XVj3E+hOWWStUJRT8p1ffSsIaA1nIm6mRZHLRVeAWaMm8ohstW3Zh +MDpAlLAsJ6AulKjgFggwb23gfUzm9oBlQ7rfWLdsvbUl+9ncywaiTI7ubeqmyPwg +W6/Yauobl4nIV6RTcCbNUYtWt7hApBHqXvG+Ndqi9PYibM517o2NYKCPWeBYLFBU +mtbb63oRy2wV+GutHOMNATLH+NN4ewYIX55LK/Mbh7y1EVxsAOR4JW62sddjI7rL +VqCdvyjtYEgcG3oGROHUjOBSiMhPCPU16W24HOOt03DCNDHrzVUfH8rksXB0ZXRB +2kfAFzvCEldsH3vRbk25ZY1/4+TGf6FrIQoCWsvrG8CRFX+8IWkuArv31bZpJURV +DXzxH0kHj7nLRP9Zv93psSQAI5bttrEOg/QWq5oDUCBHbbhCkBLUoI0nh0HHPpzq +zPHw6znDlxEBhYv3ibAcgnr+4YyOP5gz9ucvi7b7fn1knAW9CT1prb+J1s16p7HJ +jvfTyV9X/EJf29defkgzGWTqEOI4pAjDM7x02x0q1T9NPXwvH+3VR6mDKIvKbDeN +hbFx2XeAFWUXfGI6z+jKmqPNGf6ePWhKuVldKo0cZo/J9PIlMHlUwPVtJymNvbJ5 +KU79sw7VvFMxvuBb6P3h6P385ENc4NDWZRQDXWpnxWCgitf61A3ismkSaF4ygBR2 +p5lixFJ79U+e3Mpnw6CSNrLXECpAhgg270xdZrWPnHfqLfzPxEYyhvPw9+au+hZl +h10sULUgJVl46V+Zz4bA3NPkdTJk2z92KUZZtihEp4/e8TBQK1jE6H6UgCtqtncA +TQCgEIlpA1JfLKPv4fR8ZNMDMVf23OAxJXeyUSUDotnphkJyVo7jZ6CJqB4lur0k +KtkmvMG5Nb4KcXA6lT9Xh/poANw4YLimemVqn07Ck7hRbGAdvxk3oUHH8IKaLpcA +zzkZeaqhOs4f/vjLjk3DYiAhZxWkkxFcCvIw2ETvbdpmrjw3YMsMKygff6GBf08m +mvRmC3EVwoZ1DkJBNS4sZKn1wIFYP/w+uj5j9DTy05kX1Q1djzVcwwxaIQd/P0O5 +v7f4wczfdVuSm8cJ208NmDYkuGiCPX7rYc69abaK1z7D0eL3EhwwkXJ72rdXy34Y +YkU7m98v1DucdgYEzkEU3cQ6oQGVPxYb+yOMLYWaM8/U4Bop7VxiFf+UFW0yl9k6 +v3JSSQSsXvBNwcmr+uL7Rj4aImMzjg2oCW0DtsuiBhj0mWyIkLDKOzhglokfYayP +9TejT4BFm114bNgTrWm3i2VBhDrZu6DhWbrNSxCEOBeZ0eDVUsEn/OefnEmBoPcV +9QV+/+OBqQWHDe1jLIOuug7aOq2TGZpvIxJFaWzQBwZ/Fir5Qumbg6oE26FM+C8n +rrEyaVgktl9wCpCsGfk/VXbGt4eGzaHhhqKHK25h30hraugaiY/PidSy6X8OMNiF ++4l3I6FdIghsLlhw/OJ7sHKL/UNcszwbfaE7vrooGgABdBdlmx/BOXMFcvE0FgWm +Cg6zFpzPXVBUFWe7KqOUVC/QHzvkHP0iD7mVX+TE473Kydj3WXv6NN4fgQn0xTkC +TNL+AkoAFkrt1eig5xCLmGgEIzqsckxXxdqgz/9yIKffuQaZ+xeqox8z6DCpgoQ6 +qTL0nKqzVnWYQIHGjUZo1+Lmb7ZKrDjEg20KXbfru9C1RxsGhEmHEPVW3wiPKV/W +hRmS0INe7JryJnKfzrLnpVKuCknUFHp1KNOe29vOA5WVzl/qK3O5b53fkUVE7GCD +rrd+g/k/Cma+Foq/c3pn1XvnF0sR3SYrMiidbHHEfbOgEkpYHGJsrvbBjIy4Expr +al6JyUMC7iOCXxBObjYMGvSVgpRHw2s0QDHTGHeGxlI5x3ArdUP22QO4Pv5X34tb +9gEwsPuw+pi94T8H3XNCFicF8AaK8knyDpHAJLFKDQM7NnmFbKlmQcVUjf6ezBPf +FLxRcxjEq7TMBnUwFAuUSBvkMb+V6gyumrmbKpb1K2hVjqXvxsxZ+sfYWAeyBAE+ +PmK7wwkA9w3zEQfmarX7RbcizKfMU2zxYnwn+yuLReg3ORmBAN07axeiNBHhbkyD +qsO3T7jPYREfg1W6Q50YvNuVgYsv9Vhb3OkYwa/M/uARi63f4OfVpNI50XZHnJ/M +PMNo22tc/CUiWO37WArc60BO0lVFF8rFx4Y0ERNJt1q3dNBb7ew/LLQBOQztu4wE +nHhTdrkDCK5JxK7gBa/hutyAnxjcRY4hEJujaYnOHkMYc+8i8w+weFGSR1ZTWIZ7 +4k/WzDv8yg2zJWYbxBP+jut8MSBp/uRNnhL/gE+mjktXtMZurGkuL7jL7ZXc72PA +j4fr+0vhx2I/Ay87YrEt9Zdrw1DY6rgujK2ySrZXShmenaPmp8FCJUSHuqtDE824 +d4hqSo6Fb3WhyE1O3WUBKLUDtbtf84fbmt3WxlkW+tAwk2pmqU2i/DSQSsUqYB79 +cWCmputI3E2FbHZdzdDdjLRDmHYzq94PWG4PzeDTikLsWON+cXbcxyIzbf0mzxIf +37pqqxSdoHrXvvVKc9d1Za6wIHeIUqdxen2t8emR05FKtdO6dl45n+buepXzyg1D +Z6N/4uefEUEJKxeCw1ZafmcCYdIkJzOq8n0plWk/1HCCB1cr+bSgP5iHRp7szxi4 +s7ahmLo1YyuM4yrMcLXyvjjtER5jm/JjRYAsFIaxZCLQHvIM7aHmKWqVCDBsi/6I +kQodrCo3RAoucRMncpOrCCTUJiwxh8bbn06ZsisLjV9vqnHRmkt9r26V2MUUP0V0 +23k2mHFWfWVInI0B6rAtyGGeggIZOFe8WAFDlwiWF2buen2SSLQL5gdZtkN1+O4+ +X+3KhKIkNEyPq9U3ots/fqAomMC3uuIdU/Ao9WJQRGsgG8w+dAUJxGUp4O6sgXdy +PVMnEW+sxCkCsbJAkjMGqg2hXEc3mWa4cfKjV/tBb14964OnbGMRv/RjqemTujGg +FbTxpzdLTf5UGEvxEllVnGJKo7bnvm/sPXGS+ADSsp3b2pFnHcr9YJKaeUYb0WPH +sDI77Tu2rAq7yD3Y46NQf35ZL+JqQpk7M58W9OkBRW4tDc09u7MiHcnDBr984qm4 +YG+rKlDZ2qxRSLtMIahHw8xSxuqkFZsA1tiEQKAaLcaBynZGmyCliEdIwYbXgsFG +H3BHJh1kCp/19Z67P44BA4CWnqMo/Hxaen/OKKV3DfFEKbVt5ICyAlYrrt0CN76a +aPxIQTTjsdl7h6IuLM7ZANUHAXcMkhLgFw0LLztB++lIEfgDt9pKvTMnsTKfr+4t +HinM81K4kaUGdK1x5/NHwjwoJc2ssCiEMqoV+e4QhysdO9EzgvafpS4dI/tYwk6n +rRANmyaJbANW0564s6DrBNqn+UQ1+b3UhEufTwp5v4cgjUOPQ8+XTA3Q34a5gD9u +Zv/mtk53M9s5S9BMgKytU65j9eAvujkhZL6f6VevO+wqMm5MV6ue+4d98vRwc3Na +4xmMEGqRAEKpR4hVsq6hSUwMmmOSlUH4EzZvBtQGALbKyNpvFdmWMgZOIsZ681Me +1E5I753sp68SF5JrxseF8oNtw6r1vXOoXglwKAWDHN7qT6qVCEb30TcavoVLtGWu +IpifdmQwaq9WLSTLPUyhLnMYbm+lP5/G/N1N3AwJUd256Bki9d0o41Tj1Y2KnWKs +GoQo0fnAy64hMTGXEfhMR/TCTMi+doXeNE/3F3Povo06vRqBqGAiCsPapfD7bio0 +ZLcQIGjKlAUbDpvkZjQgB6X9TJp4K6SLHPb92idEsdU3SJaEhT/MV0GtR27NiikD +WfMUpbuQLv2ZcLodftB3rpX4v9mj3LKs1yNgxHoFQcqEpU8ULbyFG8RQAjjALwpJ +Qc10eRrrc8GRvAHy5JtLk3vNv9fEH4ODPUiw1XIGT6ex3EZg39o8xKQc8b4buWtn ++mim+98D3POEiXX2nw+ffSH0NubtTO2/XZwThrHoj/MqRs2I6FIy/yOa0u3ZnTLM +D9wMUSCS+eDkpF1PJvJ1JPIIISDKw8IBrqxe2uGb6WsnJDxERRb9YVuq99jEcDdA +E2nnM5kCJc6lmWi3ZHbYijphqlb2DCVfqcAOh5igTX/gbRUcUGbkjFdyVzjZehAj +EInnb4N4tBirXsaUgUyK5ws+lZ51OWvT6DAYqU9TNVZyfXal3tCG9+BWCVJmVqyG +tEsuAl6n299HXRFGxCkYKBtJ31XAEKLIgcsRySVhDuqpzEP+S76eIfAvaKV8WtiD +6wUotaeH9rfIjzV4ZwSoks6RMqCL2JEC/HJLEPExQj57UpQheWbvumYl7NKtIN+G +RJeVcp+RIUTpgz8I+DJ3IsrpT3gudSIm8cp+OdZRciS2Wo9heekmTWquhU/yfvgO +5yymi/NxEsLw77uQIPaPHXzW01tOKuEo7BsLA9gWEeT6JurNS2oHoWwmdEJBAO2D +XvU1aige8jmtG2ts3ScMIFo8kKnrkqSu1etxnxJi8lrbM8eENyYs52U/W6qsZ7jS +GAPrxBd8v1y3SOzLu14Zt08o9ShHNrmhj/wutUYheE+RIVNkWBjcnJB4txc21zgE +oCG0/9ny4rsUZZlL19Pg1EMFuW8Ho+Gw/MDK8OibpT0OGv6lhT4FjWvyys+rMCyM +irBXNjk8Pnu4ts3cUitfbHnp3tdU+G/41QA9l+cSHw4FKsreQjharpfbI1TPMtSY +Jr/MXATBZtGAAdc+Gqp2eTL+6U8Z9FxzoDuR7k5vT2Dig+LIwANjHss1czfkJcxB +tHbLtMmYtKuKrJ4O1M63P4TWfDH+142hQuQFW5tYgnCRP8/BaXnlsjwd6ezGLFgI +BQy44hRYvNy4ttRNeC3FkAe8Zq/+UgQfhWzbZ4mQQDrxNRMoXAAz1916MYUy3Ygm +Bevjh/oPebChMsBVeofNDqAS5KapE+YHZxk6/93jaPFqTI4UPcmOoBJ91xHMnj6Y +ej/+/2vSgFulzn3OwT9KFoXsyT6+dPRqaRajO8RuAYj2FcgJ4AEmluFR1jo40Zie +J5p/FB3SMW+tcmlyz25I7/Rqh1FOOoiMG/zUF8LdZKdt6RhQig6dfICrofTW4uRm +W6kbamtGhrkyEXAekNckcKfEPBjqHd/iVu+z+rFYaqr0jB76Pa8wS6UlBKxmyLbB +hh/M+MaRyW4c45dbmJ4hf+y6fVkNEh1nVMSFh4jMGCRkEYxsK58RWcfnNi0tZ1Nj +C3rlKWbJV7WwA89idlS9d0C8+0j74l/DEbef24o94MUHqEZ7gJvIuZtoZKiprLT9 +TB7B06lL6ZlgC8d6av11aTY2eL7GyyjZF2pDnI99+2KVKIF9UjXrgO8wJZrCH66o +57czzv0Pj7lgrzUcmE5GuTFx4nZuZOFr7o2C6zWwDIbujGs69/kw0qP/pHiQTQTb +v7Rl250a1tBwHekedPdGtrQ4cgAOy+tfRkEOayDnATNN20DIcUOq7mJarcftMNiw +cm0CWCzU6iuxSIyRwXvqSwKw4f04ogw4tdILRxUmy++Byl8esUcBXNZQuzls67nt +sCd1cPMoxkgWDKMeLv1ja+TUlvmAikMWwfqTcfGXOQmWVHJbabmT7lV0NbRft2AL +qm4VABn0wskubzh+lx0n6tr7gfaTPXUhcunb8ULJaQiiLdO79FUx9IgM9a6FlDJc +V/XZYHfSuw8Z9bNM4lC5jhhXheRvMrGu6SBYX7tzz2Y79f2UDe5CNpfq3HHRArEp +1E2uYd3hzPothUcH9Pr88TEfudt02APwrYrrgg6I+o0mrLkAXJBphCxrvFjvVsOD +N+aXKBm8hz4x2aiMQMiVo8BHcmpljjiqK6hjzvW/LkSAC3RuET5KB8NofWIeay7a +X7xQIzQXz6ywir/AqyhCUTMOXWbRwtlbMJVzc+4S+SASIvKN1zX7TdnqkpjOyB3r +BD8bqhudRzfIcMuiHveHNW+Bqzn4KZuapU+bW2G9V7zhrbqOklL+Nu13cX9N+9zv +37O2X80aGrcOueAuz3eIHp4mvVFHhBnMBeYqGremHWpZSjcI/Oe7pFSTh8epgKZy +rpGLfEj6GuWjboyg2biq8HPyYEhPRXKQsUvqKqWikGO1ZMvHOa/qn1FtC7YuIAsO +HhGGvAxw/57CiC10yg9Fri++UlBnVJA3GQEllrSrZLt105t6s7uRh3GUTc8Lo+k6 +oH5pdn1BQYQ9WMuvmOkqSPakIXYOtfswHnEIHVUxA8IYBtYwQNT5Z0PTXi08HCb2 +XsMcxjrAvsa+74EBT7K3hcWeyQypU2WYP/POdJwX0LHjhTVfGg5+4+7QK4mSWRBk +/LmVJdwcP41wVU0NIwAv59sLe7PgLEWgV4cSc+3Uhyz4juO9O6fLLY7mKhA5NUGa +HT+RHDcZZJDdTp3s3KtRESTHEdcMqS7BMxoCIUN8KE3swYTVtTheT9tJjDXqVnaN +FsWd4jwpm/yKghRQdwsmNTHdQZUJXOfILO9rrKu2Q1Pr/gYmEs8bJBB0mPkrs2G8 +FP5wuyxCnkWG258Vozj66N9AuC1+ZjyF5ZxFQJvAMK5b4tG7Vzfk5fMyEfnT6Qak +aa5cyvW4wm+VRbvRUXcrGs98wWD65bXdS5n1uRqy9DshOYLV4+TxlbTB4wpgqxVj +Q20W5uv9BjxMNFpDwVs8Zd1bpOLo3SOnN65rKZ8uosufUY/YwagJm7IMtenX0fC9 +0FNpVv49rwbrTr2grj3BvFTdGpONfpJKW/MgdFLd7GHCj/L/h9RvuLurlGVxf0BT +T2fsHaEof06j6s0l7m5qZ+8MzErTVBISBwnF7cF+DhvR5zoMT8U7fjrZaxJdUPtL +XY5QkwCibapz37oQnktsnBTuGf1RLCU/6BxmZ6dvcb6xy/SDgp0/RjZGVYoplmY3 +H6tP2qnl1XCKzLMOSnWJX0zE7YqCVKXOnLHTd1D3sHw2PlK5l9vRTETO2J+KPtsZ +jNrn9eWcqPYO54I9qkBVCGgeAHQB/sbiZGteKsvsojQWUeUoP+ZGKj7SeHrQc+1t +i5SRn5qcYkYj9L+rh+BJm711LPb5xoVr9Ha3MedI8hAnkN9BV4bBe+kfILFfA72r +Gcno5M818JjEz7hcfUhm4CgvhyNH+vOAMjsycywx2d0BH1o8uCso7mhtLDew86YO +aNHjCkOjccehsH6e1Vlf28mJf+b/0+OanFzUU6UaqxEA8sDeJQPlMtgL3/pnBzCY +/3GWIHvAe2OTBcjmlYJDvTPk5Ed5po8mBwYCmt8Fxfulm6CqIbqdUV8vuEMypyar +ZE0oOSS+k658GZ/wxwqY1juIy3ZIFw4nMA4rYZte6ZyT40/eTe6kxbQUlMoQOtNx +nASiCq+4GGePinM+b2z+7RvrvyiTdfo5sFw5+E4GDxJ9rnVuWcnkCe/gEwHyQKSA +4Ar+20LUUEVDRHMzQyqBYOzLp6r0KS7aaAoiVtP3hxrOWOeSacao5ZDVq6h91+fQ +Am9fqZUqMklxzH+v6ueaHSz0QSEnhUG0UNtqbSsLnddPptphl3gfWXM+NcF1/HAJ +ITMIPaoKn9H32Tdj81f1p3oXfTVzrvnn69dTbAz8tEDQjSMLOBXTUmmfV+X/kiuA +0MW07so7H6J/LyACr4pIhMAYFUWJ1w2dpltfqZCVIoJC53GP6VAv6Rx2Xf3kkIEV +xnqS9PnmJ3wF7BAfP9P1uW3rd+6FsHMc5ZJETo6cgUTXQ9q2OvFRO3ecdG6Jq/DG +4Vtp8yyq0bFh5CYYSEYWmKavuLNX25CVn3tmxXEAma/tMe2++gZyBOf66HfHSY55 +MPbsG6ydtjnv7X61ehZqQqAFAEON66jYMwgPslW5EjKbeohvK+fONSfT7IuuVs/9 +/+1/tBoNsKcSWCDSmBZsIY1Z2AlOW70nJEK/GTK31fFNTMubI78r+4a6utA8depw +T5TGMw8KELkHkkTyZlN3ZYok79ERu3V59/CzF4J8Bn/iGMILAe5ussKWQzotaVtq +UVLAVtFyPZve99NFomkJ0SDB3t41J20E+kHOeJ0IlMZ3KOevBpW2whTPVohu8kcB +0BXFeJlL6mZDrZaZWu2aw5Tcw3Yy9cDD5jnbe7Y2BdYrB1v7jCkjP9Yin9lz/qvs +708arIUj3XW8FydmhLOX0VT9Nht/0SfEiofOpVNQ0CJmNIqFr4/HuRZkTL2Mv+4L +n8vOHzq456SQkQZLGafNi0j2gP655aeJ6MoKXmTRxvmJzT7oHYhSbi8nlYGn9fx2 +8NEQjj69VJt+/z3+1iiKUyC3P64MB4jl+iEb6Jthc2fYNG+iYqmDKk8ZRk7CbPz1 +qpi0zfVjlhRqHA9mrkRCP6YTv4zAovgYtO1sPeSd8KZVleFuXpPOnar+qRSRVwQ1 +e3ucVPLyUHEz6+mVhdpFwFiw5lNoGW2ouDBwnJgQqDtu/Mvp9tFCe+64hKpOjdR6 +P0Uu3MGnYJqmmIJrGfKxkStVMccsFnuxyGTWz53aK30rSj8GDdcCU31EiB8VTUGB +fxo1fMM9xWBMGPE2kZdv/f4uid0uDoJZONSAcwCinTRZ9T1mTKz3CDPAQeVltOc/ +TBhHYcbeaWf0PgNjWT5AS7KQ8hqtGWYkY4lzZlV2t7FZIOhuvJVo3jX5oOCHa3Tm +AyPmocHALB+xRftuhgLatjnX4+PsIKLxrVwo4jw/FYSv1ndgMWk6JUqs2aHGeusY +7Mwt9gsp9XN+ksdu6q4jQjfW7ouF+RY2xU6XsnToGkRirLruW+fWQ1HrdLxO+NOY +o93dtvB8t1eK8/tQF3Kp5RkdIrMlqTdsFNnkov7U+ob/NzsGRAjG4lXRxC9PuU7K +QFL3hARGT1J02JMs53N6N4iq/DJGznjvjbOR0JKV/MgDBJtWQ4ef4kLSOVbW3rxL +gjo34/B5occxNyHY0aIxbManMpiCcqjQ0s1esGLh6CKmMbeiRyrXIh0ogy4rAf// +DL0awsD2pdf79ioL+PFBxP/S9wFV7KhMKHrZiMYbcsxa7j6nf1d9WnYfmecgOG+/ +Iz1UW1HwoAQPOvMaSwg7NXblc4ctxzslccFvaJhqbjwPW1y2pbGy2X9mwTPpiB2s +6QcIvEWXpalh5aNCZoQA2bny0McCzyIDFVXDetEtv0YJQJf9qy5ylYaUtX8+LIpr +2Xnf13KoB9zn/ioyNa0d1JzhQDJLrZ6okSvrFxQNV60CZicFWQB+ibUyU9hpD+kI +JC164ttUe55dPI55WrcEs0A+ae9tjR3wOFy4PkC5LhRxcZOy3omM36Apx5kbURtj +P0sNXGhsFdcQZxD1sII7ScLDLB3NgHlD+B90zqWyiojnMm1gXTNJkOf63YLyCTFc +W4eE9FvvR2vHSCAG8M134GH2IqDqc/wLGsQpO0ccjww+eXhz+xK8uuKBerp/Ap/J +boPHw50uYuRZHRAMzvN+XUpeHgXiWwiXVE/UkrX5ZPyWz9A+OEEx5/N+AGF/CdPC +Z1yKwRnQ+Yf3gZ1WJWOK4LabegQNtigsFRCD6MgN8UELshR2yw1bq2lXUIgMBbv8 +gtQqKwGp7HYAw8mFm8AsMMuFpBYCnFBDhCJRlXZ92wjN66KFiZFukUwOrFUlWVve +YYJ9jpJG+ZDCXwdWUr558OHhWktsg5HE4MDJqaJRIG6gOVtRbaZCzFwfWTg0M4QK +rOYI78+888B90d/QBrIqrc7CScUzosbiwRqMoWYp8HXUqRsNKuMpbJ7iq7GXBCGU +WmztEsB/WRIR1WZKDUlIi+EEJJRSHWByyj+GvkWJPsk3Lt/8K6As+vV3XQRDJ4nx +Hn/EFNN9gvmYLH06zwCGdgSuTXU2uPRtNm4SdB/E6KxYamTz9LP1z1p2vM6/Ir6g +FsMBgfOSqOibblpeehpnfnFzbviPOv0wMZNJ0f8Zmp/MNyl1I//YBOpmYP7lMWF3 +MgA1ghU8DlhTxc60/6MJuXniQpaL1PcQt9j6cQf5YBjarUzfFJsdpJlG2w3/ayID +2vf0DDGsjG7Biwm7layjdmEmvyLL0/HMs252bgmo2cM3kk+/q/yyqAM6Gkn+FjOF +z75aKphY45b8OdLv/BcnLX4zP+akSAGPybEEJLHnxeW/Vr1mJwZBb2tjtMktkO/S +gHMJnFKGDL0vecNMlr8cST1W3lBX3sJJbvZDVTmr4alUnCReMcXhFIJrqYedmgWC +twQUeaDI77VG9IesYs40mSMUvSY3rGnFmDXbVN5DxpuiaOfb08AEHS8Pa/mxHzr5 +zrmkkVmd5aWEBhwik7znKO5s7AqMJJlgMrfrnoLXhg7SXjqq59ZvvQEgs3zLUozO +y3iRn+NE1j2X2DUbe66qoyPZJwZem7ghbCtdt+0K4xEOmCO896+hDJnBTfyjHE55 +jDiaFFNxYrlESWEtDMmMJ9qjE7zYq4/uk182LmZL2N5JIlSEOzJIWNnJymYqiBh9 +GXW3xrOSeAFcP0dEmJjZMXs5aCIpFjz9J16Pf0hta7I0n6hIuQYcqwe3kCd/PBRL +C0ykXYm9eVGZsvN5/3mxAQ3wI6lc+BgabxOri8ZcdQm6tvhLz4ceWhk6PEGzhTG5 +47XmdXYjU96lsANCevFy6n8AQmUEucMbEZkVvj8hoxVJ5p9GbTSuZ663Yc28i3pL +Nz1pBP47RODX1/VxuKKlrYQmgmo7ny7LYapf0gDikchIWqk50Y3jurNYurVjwNrX +w5srUbUpzkFQ90mJb0qwjGhF23eYC4R1UKrC7gdf/ZkEM3vmbYoViwyMklz0ivf7 +zKj4dCisSBWLlyPlj6q7GsbjprvgpNyw/+CxwK7wak1qCCLUSEeZBIl0SRSygb8A +wUHV/TnIoV6oYX3gPp/n988HAcetcUSsPq9qY4g2ojh8VflQ4kZlOdtqKNPKa3VD +dtHWK4eo+sGOXdWLpDs+3615QUadro7If1Vn45/OMPsWQvYuHhliAqa1KDd78G+s +MyweZIb94agE7x1YYNfQcsi6bOuEFvflss1VLb8QhsyEEzvjEdDq/JolBM6S2L3Q +iey2NAPyeFSDQMoK3AzNZxF4ePQaV0Lfjh8TGi9s6VCHxuTNvPv5RJj+65jfu6IO +8ayCc7rGBalqUse+7BjK4cBeUpgYBrzoyPeRoapKmO3TQSLnKBSXG2R2U6Xf9+Uy +PWe44gyvDQVfU8S+Km+0dEgs0gBnSB8mjgrSxJ9WZ4/jsXfGHAOVy5caMNxLmkrv +4RAZ6/GbHGrlpU4Z611o8N45Vu5RB0VZv8dgNGsQwxc9B48pvEdphg2DMzLiZEYf +uyHv50icsBqNYMXT3EEmg/O0OCylaZdc7ALgtjwzp4zPYxP3BBX07Bgc+kBwgbVA +dPvjd6+fDBxbKY2XrJz3LQzxOnW5jvHwRqYv1duaLxB1Loxp4cSq57nQtI/p+887 +u6BTJzd/I8lxWz8okRaePfX7gA5QUY3Wa5ESGRU4PIK3Tp8nrXeujJwoyEaTTEWg +Y9FXp8GsBnteVVbsbTZ1cR85tcLqv3AB9rdIr8/TVSfJ0gwanWn89n8nFQLmvMmX +5Ni/4XjBQLjb7S/0s00gdpNxlBUqNrtIFbqVFSgNZg9dfm+OnqfcysXuUl/Ampdd +k6dqj//tH8se1Uol0OfmB3rza18l27DHg0wbAybOhYvXKnKzsPp6F1yK1p3DMMPC +vkeHr0RgzL/fsiUIMhR0F7XyW16iZCSBF1wtFvuTCvZzqMPgXbvugECJ8sK5PA7S +PeSgVdxnf+nox8AL1PZAlVOcbv9tsizZk3q9FGsX/G6wx2S/KNSCBNpd+5Bm9Yhc +hnriySaCruA8FB4XkRJcgm1tyCTG1mYPoKqI2wU/IKGCvwcjHZgiiDa/Lln1qWDM +jVAiJFAU6R3YioPV5rCYgQQiXkg7xMnARtbOiwlVI1jyD0AH6s7m0fkPEj5U3ab+ +54pjZZVsBJXnP+HweBy8Sl1++8A0hOBwIhvQV76KALZG3NpUf19z6H1NryfB0KO4 +/b0ojnRaIcMWsZKkoOLHe17Ryx3fdM+j0pvLnemGen6J0oJnbtux0zBQXmhSJIrh +8X7zu0YkqjZC7RBa2WYmca8cRn843Bb60h6iDhcWBL8avofd5l8/yX+T7eb10OG0 +DvquxWjxdv5B1hc0dscFeO77PQih1/aheoZFI2AAPLLIV0bLyXNuOgjZEBaneLjB +V3lb6nJnRYHksMSK5Olvk0qTtuVRd743n68A1Y/255TIJrs544T4y8uLn8hEn+UP +31EZvcQfmoCSJRsn6BJK2+71EJdJw4uF323/Tg9UtCmpw2KG7WII0s8fOorcIQrt +QaGL0QEzx5nzmIOee3rol5/iUJS7gxLl3G3dbwbDBjiKEDetFX60KZbReVjl8fK3 +Wz1TxBxxzsiE7YgP4n/vKzsQbCOcB1b20Oa5HD9PMCOPyp5br2u4YfATGE2TjSdS +cFI6zh5Dm9kEnmaCI38PnVRqpdQMDgt8zuYTkEjc6Yj2JnPxr8+EI6KAk2CfEi6x +EWEyKvXS2xmm6D7PSRtx+EsP5S/x54zj5hDEBNGWFUmqXZTO/WXFwSEC9cUS8Z9W +jF9WI77PgqMZFh2BUvrrX461hnfVDnM+QwG2P2BmUgt+E00R4IwFtemwdi7fhr56 +8wSNnbFdqy9bqCpbntZH4XYarbf/9Eid6fYBdOIY+FtHp0kgQY4m7wbssxHSPaoJ +5P/a/roBGC2cziSaoz5MGa7URbKDz1Nd6dTkPuEbHAvg7skgO1+STVZz61w28ku5 +IkEeQsRgfN8kp++s7VxjzyiQrSd/sjL3u+cviQdRusdL+klI2stOy4YCvkYVO8bC +1Eypqj/Om69udM/qVDPBMGfFc/CWIceUJJAX7A+0RLRBnOmCJ1QRhQpNUZir+Kmk +Mhah6d+w9LQavDr2W2XwxkHBwYKLarn8yRWFYXXOl01zVf83vpoBoXuDtxOdYub9 +Hacv5VshvddwmTO1G0K48msdqkXcBBdSZwthfeSm0eSzcG5UDQGFBTLnOdrBEt3g +VYxawMH6XYft8ZvnXtBmO0z4aJLWQtmyxwPkZcFpkDr0NYMo3Zxph5nX8LUDVIl9 +8frCHv6wGLPSXIq/aiE3/h59eoHq5pQJeKY98B8i94i+JcLc6Luvzhd7dXGoPcyJ +/Pst/GY1pHWgpWnDUKYplhFSUV8rwrP29RPndwuKOsmGh9Ur2oqIpmfmtlO+55wc +Iq+XMVaOjYwRJCLmlmB5IORd5zYnOjBhXHHapBM7Qbyk9dM0yNja0dhCj8Mvb8zH +PjsFGr54Ie8yOGKVIaOVg5VkPSioJK+WY3dLB/rqO/KFv+ZwxaoBozZluHXl9OJj +KIlLKYPnBiyksKMKQPgPXGLX+ZnkZLdxi/tp+r8krkFdaHITLNIoUr3+3gqYSzuZ +zSlNGjLF3KCmw568HzTgS54RiIekrF0mUrxiCdosB/z5XJeqZeLslKEEE6h0plhG +1qCG3Vtm5DC5nvrvBN2AXxlf2GhGZNebDF7FwxkjacZ4aXfCq2LVvHeJmRMdcEtD +sjGQADYUttLUgLhlRMX6bGeN70WiHxVOypcG+kMy1Dv5yjCYByiZ6WIBmyi0BuoE +iFIbDIqVL+41AUBBJe+8scwXSTj7Ahsw+R1nzCYnx+5abl5ghyORAbCdWbzBSPZB +ufPMo2rbiwNgdXAnEvXzPYvMeHtLTxuSJp2g/LOeU6VQlMUrkL6nJn0IABJv131q +ViyXKUcOoVy77AmzZ7n1TeR4xt6wdFWgZrGoadHDkaZP+iuWhzyJScCUkK2DSJeZ +TpGK2ac9jHHBmTraREC2XGeCxA3PUs8fo/omopGK+VL9qLMd2G/xlqDv6eDDG+bw +UAy+vAV6LlatLVL2WJi7kHFa5y9WjjMKEq7V3oietT4sINbwEJhYNURc6h+FFmG2 +40aR40aOe3RlY0gA1Tksye2mUHo+zrFFUi+2RnQNplc2Aadr3gOoMf9INNkTE41O +Uca1b3jX8RVgiVTwcDZXiQtb3Db8U6mTteiAleBQKAeLAMJRtajvPJYfr+tNHU7h +tM3yWKPfJmLOv0e9n404PQfl3OroCfn70cchNloDTTaBM48myG0cSklE0Fx+9HFh +VAehmPtnkNl6J/vRj4GfPfWXHIiCkJzEUaHCkAscnoUDwp1IEl/SGQXya0K4oSLY +cG9w/Pj4BK8rFW5+oqaSvQERu0l2cUe2dp8Juy/1nMJ9n0DT6q4d5hDVO9/GBTCu +xxxW8y/W38I4K2ujbwMOpdoIZwEJGS+q4sBaEw7/1HgedsIfQhKCKffoKsS3sVwS +q8dFfAwuEFyjT+ohNzb3nErgAZWIkfuaeyn++7/6peTNaPi4yjf0XJ7xlEq5CqHT +wY9aC4ydV8V5fTdsv10ONWJYjHSR/0sF5/CboL9kypn+WcxR3EscpYv80xMey6L/ +8xauJLYHJ4emmmgDrTO7q12CtIfvG0ZFfB1Ft+IfycZ7dSsU9KeDqGNSfTpPd3Rd +HdwfGW115zy7kPq7o7xUODfPeUAeO/rVlpLy2DHnSCZkW4d617tJZHBPSV1iRcon +OGxR4VMIvIlg5Yn7kbvCRHPCGJiCE52YtGDDsSETs9BYAKZ9alQ8kIXn713Ewdap +1XZ+pdQiyZ9oQtvKoMTOH/vj8G7GmGueAy5NFKaZBUTwzX0Toikf38SAWRHzmDv/ +KP5GSbVIVYsTuAGTCa08kQHUX+SW24Qgoaxyy47JYAUZH3QupAaqnwulPFkRS8Lk +vqqIchG16PE5yYpIZiFzPLe2by6fT0wXBT9hEpSowQXgrkoJs78NzEKII38ZhLH2 +at7apsjcpJgDkbipvb+H/kLG0aRLY/mGWsP2/Z2a8AUzyItHZlrFwpNcdnKAg8w+ +5NFXlBLNDZrCJG4f5jA3nujzHu7dzdFrC5c8r1aZDrzguSB0VSXlHaYwZXD8bUy4 +JrpR3zqB3XlF+ZJEgzl52SRu9ImjkWAZ0a7vuzTUPd9hfZT0SvKthdZGDMkU2uxf +YjJ/O33S1dbYCw/0uN76YK3vNCjVTzz0aDzK3EaOq+0rtU+i1wZtdB0Jc3+9WwIM +X/N/QP8ldXkl+uVENJ1RetBq28m6zqMZ9gHDHfmgv7QmSTTBiyzwCj7dFeueOZxA +o1juy3qY9YsEBsi5UdRzmzFzcJiXGMOtgZbTAsk/C+fJtg4LRE46WjYg6bYjK7dB +Fa183cfOLfcT3/N9jO/teuWZ551jJJjYZssAIzYWPZiLC9b9MKsLxtDIVkLThIpw +JW973WI79udN8KilxwWwu6GUUPOnn08Mimw0mw2lgaXXVMKbtOTafJy8hqp0GJO9 +hIUw4LTcscgLvXf3axoT/3zCLs6oDaG4lA6F/7NNdQIZHqsOnqbOA5wKQ49FZ4zZ +AqUKqRV87n2I+cEoeba6r+IuVZ/aQAdVhPMEkSpIRX7zNBQI9yACgwdo51I5JUnf +aZVii7yWp1i2YCHdbkivgrGsrRR1E+ChtmWuMpFJSqT51bNpvm7RZo4Hsmc6wPOR +GzYcBihtAY+8UNdOKfHxxisz1wHfUK5/4gd33C5hv5WSuZV0EWuw032Yflom4oVe +Hax0OwUhFLapUknezL1hOfDhsjILLUIpqLNDdTZxRBu9xi+i5kxryeIGoctZhBUG +YqR2TgyHxlXv9gPiQzCPWBzFncxzdRxorBZeMA6Uqby3YQtUZapcFkI68j2415za +gYK2JedD6VtXgokN3r1vXqb50o+EvknQ5iqb2dG7c4w7IAg0rLaRpJ9pxx9MW534 +BqYPM2kV4Df6TFvvlnYv5aYOlBsAiLLPjNaeKEztjT6Xkv96JhC0YeJ2SZ1Xz8yc +91NUpfDkqBtH/OOcxoO/0nxHCrnOjNS6D6jxDLVWB2nO5QWNOTtfplc0vRP7d4q3 +rM/0dYR4L21O3+ViXfoA2Ws47odUQ7IdBChlaEVyeS0J+hC5egKiaXnRo1IFNkVm +o6E9plDw/lGub/2EYuEsfGGq1UqZo7B3rU6l26HMhlSY5BbYqCt63DmVwTfj2ZiB +1nHrQjIq/qHQQaEZccEMF7JAmfHB8oqwtMv04wDx6TCDiufsF6opmlYUKj3dENwY +Hn/pJcG4a+5BsbmaaeQ9F/atJ5HZrM3S0mgUcGfs1BWgYxNRt0L/ARJKTF1GbrA+ +9SOT0KLGbEDt7c85p12llHVTnEpVRJPG1xzenDtFXgvTEdRxnRzx2jDjNCG5Fmok +sFq3w41uXHfQWMCHTuyln7cy0Thf/oUHDAygulJJyk7HFoLGiB0/PjSfC79CviDJ +Nzhr+YCe5/PI4n9aRDA0/0yYsePyDnMmNBcdjFLz08+GyY13579SI8nD2lNqOdkk +TuPmEVNXbcv/x19DD64vQl2ZiSZB6iWvS6714PDiN+oL5myRiapvyM7NnAzQDw+5 +PDltd/K76UTfzI/BJcZ96x80dmwLVmShvsBJzvLQ9JCOQQkPItI26o/h+vBtRL83 +/a/YvS1NqpOfXTTP0X+NMa68qS5ApPysSc4QlzFHnNcRTqJkJJ9aWNukHCwFKm+S +jtMsm+n2MnmiK6c0qj1p8rxxDuElJG6yoM3MNQpypWtcccjlQ2PwPZEK3afTiGYB +QII23V9EmABUddWnPVinEapzUshbUsRQZ0CVjJC3pyh9LpNLd5hF8R+sb8o8fQP4 +uQrszTC2AUUTgKV7b52qZ1pf12qO/rVMTAqQyDF0/8Mpmycc8IWKoI5Ir1DThCuF +JNZvGB3VBuy+Umdpa7lwJWmTCYRUB5NmWZU9GNp5MXY/0SAzP9eNCJdYaBEDPKHI +svgaGU7HT79Upzq6TRUMXFE693saaKyX9hmSd28y4Dq3o3J2tQLWAE64fcdrmiqg +T4MAU3m2mcyRu5/JlsapLQjJtH+27VkjwRfnToGCMTggNxcdqI/zeEMi1vjrL648 +p00eRSTDhiTdsgys3tPo2YpcQ6YlcRstxaPeV+vaOzRfr6GI6JZGWDvQ2jj7J/6C +tC+fDOBAQKH2Eks7L4rVpXMWpfHcMi5pstq42Vw3LcK2YW3OHjeZ7cqOJoU4MLHZ +uXljB55puPFZod7h3HwmwHBY7dnzbXEsH4XVPD6z/icG7GFS5MbSSQHGoXz5+OiQ +YXhynWOn81xqD45uqUHpnZVHMqKLslMloeQa6mMWRZc6E6O05b0Ku9+/nbo7G4tY +uzKMCOysMMuYebhopNppXeGf6mRC+tw0XTxeRr9Hxvy7MSVw2HwbMJsMu1PFuL20 +AJr36zwpVkEFxrsukZMdueAMnIZs9f21GXU4ah62+hTF1dN92QTEOJLbi87rjta2 +NYsWhQt3Tk64kaehFd8n+CvRxyY+tUg5tmDI1U12vqiBDRmMS3rzpEcMvrEktWRz +unOsaumLERQdPkiJ8Og942i9DjVBa3l1MDWfPDfZebRZ3/CpxjGWNuSHFfTfDTwK +7mghuPts6xJ/Mfm82vGXa86WJMcF9bV5XEjYXO2OPZ8qo+DpkanNLfkUcNpBCnd+ +KsOPm/xRl/GsG1wVVFnhcsyXH+73ys5Df+QYxcptSYqQluT3dl5h8cNSjV8SeP3y +yOoiZdarbsQTPoXb/mSiCWnrpw7n4o0q4QrKdovm02FOD74BQyTvFHhVFa5G6cQo +rCuV6ZdgTI4pyuiONxXnx+0F5VwyrmlNZnjvsa9kM0qJvojUFeU2cLduM3eWNQYc +ezsIwaCuGeM3XdvOeTLh0pdCyno0klcXazQymeBZiLd1mrfZZKAQw31HspsgfO95 +Ts1gV1PkUwNMldLRFtF4iIc8/8BFGCyTrAeFR69SelwR/mey9iVBe24Hp/exIuDj +vkiG2BIpQVv+1WUk6iizVXHyrnJV2GVRWsARURtklKjzE8WVNl1RcvGy7deKJXWA +37aPXrU6EN0zvQpfakErcBWb8+hAmmP91Qf/FZ/Gbf6QORPqkQW1EArsDkynNXuG +0+TG3f4ufLQI7JVTu6EDGeG8LhRfZrXtKsM28iZYjI/x+jkPwCz1Ni43OPCsv4Sc +hn3B+tuDwfsLSZR2+tcWwZSIY1soug9B74V7Nlj5snSK0sHeuPi9A8bhvdpBBJ9z +/SRs4og3RhGcF7pXaE8IdjUObcFbJj7TKMbpREkZDTHGkbQQ0QbIrWylZJcuy91C +VmV8ppn213psN5YOgw8EV86mV1eTILs5gDCPbh/5qOkZZSJ7hoqUXhgGOSoAlY8t +7oVfjOQ03niwQmC9I5VjKl61LAQmiPW39q5L9Gh5MTC4Gae4KVbq6a8/a4yiAO+H +8Zcp5LTNj2lxTKkJr5zmA4gxpV5QK4xgIWg1sOPMYDhPBTftAOATXSnksHdRSr++ +SbplMJ2LadiXP35b0wfq3Evaz6IuUucipcHT/flVrG3QCQQkbJM4P7W6Y23QxU3y +xniqe+P8X9Gxv1evmNX1v9jDP0Ro7fDRYeKsiDsqA40W0hEbJgUiL005ylJCdirB +rECVoT0L6/zgv6AvGws2BN+aEgOh84iL9NPalB9eGvSGQCj+XwWLlL9S2oxJy8/e +3Hh9UETKcjlgZ92D2f0spNEVhHn+SLaQbnB9SYlR0CCJqxFcLkpVfZT7ifqZTBIK +SNHPiuMwRtjPLVzgUyVBJm8MSBk7o1D4xurpL8Vr2p1caCCDdo7nWBr91gRIpU+h +6zlNG7A71mxSgRvReWyZmKDsByQyHN15ZF2i5J61gOYipD8g9aR4FqOjmcZ2HMWd +slfF2faZ04Ez5S4RCjDnYwZTbHW0KNjGggeaA9Xh2I6YGes+pgbLigHUhi/KSbeP +YTKRVYPJdW+Ny/ThTZI4sHWNJLxkyfVhLzyVWQQngtbcvKjP3ugCEHZRyrkDtqhB +Z2zT6rXzfIBNGjtCAhPauFW+2sD50utRIVk5F/6zPH8fg5apKXTDmr7CZXjQUDrQ +mXy2fUahb1lY78ld1Sju1Mz1eGLT60EsxCkwFbaUMzcO9MjGWcGorh2xZKUFiUds +h7//rxYaVw+NKtOLYqxg1d8CawiTSuDuQ0QchIsPTznkEYoEbaoFW03ZWQMNfirD +svA+soaHWTvreI6dmELeo/uVOSstbzzLS/iuf0h0C32l5JKEaAjzKhfFtBaNTZId +58imxC+Lhuc/9g/UHAFVN1p4hsV7nB0yfz0P2fFQAJrJ71f7ZW86aflB7HoZvbev +VYqI8I0Xh7fdWAYmbX6mMN8n45hBNqAokDmcJdd3oxqKqr+1+rxujrsoB6DAwReZ +vd046XE2d2XVL1GlUEpM1D3wntiz8NAIWITynz5ItM4s9gJgJ1tn7RSj35uT+fMx +6/bi0VZ6H1NYCXtZo0GYPcAjus0KqfQoLqCIHEGcywnH6rQ8GhaXmkewIz3tskmu +hQd7ffvtXURTAoF2CPbQ9jBbob33pzLQenqlzt2i1QngYA6fF+BXQwdDx03hlkqu ++SPgJyCJad7LeWDDoIzoq+aaR+JBt6onDrOxtkxkJ8WdLAqd3dullmeqQ4f5Tf9c +ywgXqf/fJbLLsFjD69KZ4pb6WBV1JU2brn+NKd4xH16n3WUgtk3cq8gVeJXQltvW +tmh3YgK+zwqZtoBsaRci7YnYMLLhnQNW3qYq+U9UGNJ0D9TXXfg+p4mI3s17+nOl +2aNfaUq7RRj0DhZj/Lsy5ewiMqv2wekK6fjNquGPRfeRX8OKa6Tby6hF8yVCF+sL +I5974JJDQgchpWGtBAR1ISAHUx7z93lsjfoJAczV+KKUUqCLSdnc6WMGXTYvWlut +pWWdiHV+NOZa5qS72U7SLTgYUAqhZvbVzbhitPBrwIVeu9qbCx6EIfF06Ue3Y2r5 +sv7gZYMYhumpOnMse2YhpLHkS+/QcIVgB+2Orzvr+1EX9KZox2OvLpTmY+qd/Vx/ +4//1DvyR0VJotk6OVItR7DIRWbPzJfoG0qmfEc4Ad5aMYn18jW5DeF0H3PIWc2aJ +tLu4KPIneqpFe9U9Cna2qFYXEpy4HaOGtKbJXR2+OQ/nxGDzDhh/HMYmkYkT9vGN +e3QruO/swkPbroO9A9YFZCnLT5bz9mXJKZpxD9fDhM+jWV6RwHgq8Q90l6mnKBwI +YZKI2csK/IPs4fjfE9b28SD2rxDU9n3UEzqfM7v2Fu2DN0O4ChLMD+DnZ75NaZEZ +yF7eSXA121Fn5GIRXvJkDy2lJQyXtISHIf4GYsOz11ItuZLy/zhtSAmeQWo1KNu0 +iieafPDSCrnq2EC30+YxIKHVvshez+02lmpNxCZNrtjivf560vHM5OP6FrJUUgmH +G6gtetGmbq140xEq+z+BKgj1dr55IUkNfVljiUaPOD6mhR2n7mv41uDffXyMhwJd +yOcPBqyVGfzEMxvL7E06lzesSusKtgnjk5/6A31cuxSfBe79Bel3FV8jvlgf8Pmp +nlD0N5pvQXKp5rJU0g9G9PeLOFx+dnek6t2Gxt1XgjEmMDnBw7P0M++pRInZvjYn +wUabsMniOXPihWLoXIstzpxKRhhR+0G67Yz9gyfH2Xy5AFmlteGR0xrCStvJPbWH +t3lheZE8ZW4TNimX49DHb6SiOIcfBa5qM3Rji2XiRjR42eYc4ZWhZieNVHU4a9Ic +avM7ELx3mOG3f2/hnptTbci9SODGR2sfPH2dkxBMO60IjcCrQb5cVMTUEl1EWA+R +NVF/qeWUsMgXNC3N4SJEDZzd6Apzg3QPmv6gho4wNpGCWjVPQFS4dsNKd/gvRSbg +6jP6URxxi5MKYiVpPzskSY08CpEUiZ02EiuGRHPDVpiAWcKc7FDXPM4vMSOjkYwU +gVCNiLtt9qddBpYXUKAfS2gqput9UjrV1QAyEWztg7QLc5XHAihJyoM2PqzuefQE +JsjhuED9KHnP1CG/aLC1WqgAJYEss82w3F66FpfehNTQo0CRl35EsLqCSozywQMz +phHFEARb0GjDHJsEJL8Xv8I9dJGmaiWnapveFJJooOZT0Z6Ktdb12Ndi2unt8ddX +5q8aiEMwEoXZxFfnpLMaw/zLizmWn04mSQTnE6miN+gi9q/CuKOWyjcTmlX0yraq +/BjwBEqUHBs0WR17wkkJEVICxIpo1o7eVlKynXWJOB1VMDodvLAlSDJB5Kk2BWdL +MgY0f0oV8I6BW4Rp6TOwsdkiioAXyOtNySGjSQiKOG3DXxPqWq2kMIOYdAX8nNXN ++eCwtguL+TBYcN73s7qpW7154CdnOeB6wsETbfZke1/KrqfHpoVmRT12PxvmpVM8 +YsDCTScBfCBgCe96sqfiAqU7QoMMykK1hpeDWcSAjgF6FCJP4KAl1JIe4CyFyoA5 +dEhOytWvUT91CnXttNntHVRqahaa44UFdQD3l4SZwXmSM4J2Zscsk5Uw3HwFOuOt +kI5QhISTm9o8/OQ1wEqbayLz0nxIEfmy47LxKzZY7Ip9746sbEmi0GsmCFhBS/aD +tu88yeIt/MSJw/dJ4dceXaX20TkbHgCqNyJElxI4QAqYaClCfWyGd1t5m6aS0FDo +zIUKUmDWB8+fQJtdn7kHBndxebkvoVBs0r5En4aiUpVrkjnT3eFdWvuwRej2BQGt +kumDnZRqObnqzdBHC1nG2T7cWGoIZbimBYTDzxafh5go3aLSUSjSyA08cxutIKDr +zMjFE6Ad0iKpHmVZBQ2Z2UR3v6xWKKo/BMyYDXzZJAGiFw64TRWJtpm1GH9XZUBr +TR3mfCVjk1Aq6WMyVklH6nAwKBVwt8AyFGOD6gNGOpjmO8uUacxsuUkxIXBTqirl +GV9vVJHveMf4jrBY0z3zjz9py1wANf0kfXJYPxghiZitSZVMsAssUXI+dD7jVFjM +9/HrP87SpTDLYrAsMUBKWQXlVyK0ksQgCzKZ59/YfNv9jwnDaVhC8wuLFwqLwi1A +ebcQjmz+WGBXwC9HlysGsudyKlvttOsZDFu95C/Bxi6fwsahMCCcQAm0OmUcIM/y +UA1T71n9/2FN/S5ia2Uz6nGbrs9V3kZN3Uu4s8hYZN5oL5Xj+6msColnHD89k9q6 +BANO6grz0NxZVmfnr1BOAS9tTaLbuKdN3r16zOCdnxURYCyMWS20qXZcAc97Vjim +Ewb+uuYjU2l6PpLDGVW+AhrpxCgFEjG2eePtbR6cpO7Cj+FwMT4xwceW6oUVfX2t +tATI/7qgLjalppPiiIrToqzNKeI2Ka+wM4tdjat2sf9mZ76w/bGYqjdhyGI0drv3 +VBc1zhGwEBDotqEpQEi8rGV12cZIgj+wQOgQI14FBcy60AV3gYjac4vnVbbymrcU +ZdJtNGl906L6yLnsAgKxoCD2T/AJqQW7pqJctRZGM+Om8PoNeEYLlh8N4n9cGv+0 +RE2gCUfg+bV+3y8Nzs99EsiglJzOyuwTcBwKI7veDMns7ynW0PcNKwZFY+0cBnYX +EsXa4+iRJbcOLlUp1Bo6qqm3zrBU8VDnILOE57SmTdFh+FkHPccA73YrSKw+dor+ +7lHLMCMsgirkV4xSdiikqo/rADoxUOEC8mNhSqb4JwioHmGM0XkXfRX13S4wXgZm +c/UNO8cQw0xkr4URinBaexTcHBDpXlqXXo3830LLQLmF4kLW17IWZ5lcSt9YIuHJ +PgfWxzWAqTW2zpWaZ8pWR1/Sk4pxvQ33Ve7z12e4o4txS0W81pW0/ztUW11EjN7K +2uRaElpjtns5LwmsTFSFKzM2KSQtvTotGgpyYVtPOq4Q27SL8akTX+nvlNQQkam6 +ggK+s9Po4ER+ElwUFAFZOmMX0gsOmOYL3FbDM2QYfiDlU240FLTxziSBoeTrFbsI +ZdyRLWbg+lUhW76NrJNu5+XMXcnGFFTxMdg2mVULqZ1VXj5DEIVGK2Wdt7NH1brW +oqDx52Pk4c5ZHcZfbzkzLm0SRnPuq85CYABlnJvNkn0QJKh43635ne6umLwVKSeq +yXinqyRddt8I5AgQ6TV6wsOfzNsU+d4EY5ydzm8nPTw0yWBUD/mtfKf7ZqrdhxAg +vwHGNVnSwaHFilQqTpCVIsxmEC+cVt365YH01f1GqNdHnmRyF27PAGLiGBB1xQSE +ozFKV2WzBuandnu0zbJGIaHvApe6kWx1bYLiVse6oLw1fz+5DT5EYfGzjOHezhrf +QjUFjCAfwe9+7kglH787+wdBgecVQKdjt2ZPAt+dYdYAjeku6Qb3oEkWoKcifOCd +0BWHL5dmEIwCfWn7MSJVgO0SSCWYIZwRgAI2J6F8vOCV2bqQVaYmZ7YAQtQEIUoS +MYEHvNSVX8FIR+Fd8r1i/SMuKjheVxd0I13t6t+2AgUBF+3BiJE0NGboJTJCRFM1 +kKXSbep6dZpg719JbYBucma2ZOuunFiUCqyNk1PjBzzT4glVpvjZe2KlSeL+pM0L +B0gWjMie5x7mDtsEUFehUAySJ6SDqLBm2PfOzgQiUYsuzj/QYNmrWZbwDgGDOrLk +8zV8bfrnv0Sk3A+GdQZUe+/DYO1z2EkifL//n8AGm6371mEPvVFMOYHSvWCqkyh8 +k+oVlqIKiUe/GVovo5uH83qfyS+TZe4GJy8SfLvUebDI5ttc11F/BZHEdE0PsLps +OEsTNIbHTIaPr1VArgO2JAFHfxYURN7HJEezNN8+77f9ydYMakDMQzR7tYLAzlvt +4jdjN2x7SLGhYbpP+o/PA6F3GIKD8FSQov2jv5qRIhXJkv7BWWK2wKc4UjoXUa+n +4GXAHRysCMofidNbdi+9ZXGR5ai9RCevsztY12N8sRAwMKj3GIfQVnRdD5icAoT1 +l3D4WodbGpiK7R6/SBN5B0CF26W/JtaJW8GsnLNu2WFc7GmarJP8GKmSsKIOARaq +CzpQVaXodATRM/l6TISt6xj6GA9ptw+8P44A9jEUTMCs0ILWz6Ev/MZcPmw5kJfl +ktWwNH0tiC0NcNNVJYKpOSBCAzsLf0mQx8P4N/dDXBihxIADpZ8lxKbZ7/t7sGr0 +pRTldNAXPG8Xj1HuuR4wb8+4o2eSaLXjlrROWtGtzJJQjq43qc7+5tvQeCT29tJ/ +NZ1qgXAGZMX8RhBTApXDh3siZTlh7YjsqDdXUOwD9bWowUZOB1sy5Vnv9MN8CLr/ +Xwrt1TlZrchBIrjCLLy9Vu/MlC3y6mPw+bojrlnSQZXnq701OXoVfYfoqQEHrTuq +T+Dc5wwShjvTbUFpEBUCmDAUhjtASteV5jaRqz5KAXRtdKkxBcRXc/zsdYrFmOp4 +XftlRRKhDzkJqCKByJPLtpr64Kl1H4SA/rLezZUiQMJcz5/patbqzstgp2vsmYAW +ASEdLNZVIXlx5RVnSQMUjFpn5nOE08wVJoJ1lV/YDumwJn7CGbkn/3SUhAspxv/Z +b7bkQhoSmHXeJA7+N4K1PsmFy4yN8KAGceESpbxLrEkKBZ/mRNCFP7uD6gI+C6+W +mSxay8jY8V00zH/Hb8a9jop0qF9/7bw9wpWJOZ43I7AwC8TkobZngG5uFEUh0j1F +hcfpZmGEMST6hTjGONgW1CxdjuMSP9WaNOEyWhqlwu4SzzMZqcIADcV2pcRRfUXL +YJSVvg9rweqyIFcP7p9zTL6tyj5YZYEIeELJTXSw1oLxuYq6IVb4wMWPtp/GdBGc +Rm7Hp7/iuYxgPzGt1lfZnIiHELzWYPslCI3wK89/41EDD+qK7acXZhMnVhXhRDlr +GTz6KfGRX/23/x6nAg+qBD8Y5JUcaAWWLt9D+YTKsLRg2LXWnhvwEniOevbE8dYP +Lgy9dMBdN+ibDFb3MpEzb/jV5h1GbKiozQSxhQVp842LDZYT0spjXOgd2rFs6nnw +OCccMu337XpUvnCuhT7W/M95xUkaNtXLPy2xO7nQ7ylyMBqMfmzU0jrsvAYyzdeG ++fPREXdOGgCqswMBylmtnwNlOECYzhTAzn0Plz1BxXRV/LKD0ceFoLWRzh7gbKQs +BUxnQQGD3UcvqErwkzUjoUjWHMPE+hCzWaatoYaWgP1GzbvRTgg2FIrhcqMtOM43 +2xgoGItvN9Humhg9r16sWgHrh2IxxskLlKlco/wtVxz/ycNsGZJBWCvX6oTvh4OA +F03z0flEZ4GBavu/H0XTEU8zSh0C5WNgMpdsvIQZiHJ19TTSe2tjiNYH16sF+udl +kMDVHX5J5Fca8fjRUfb/kMb3aLNFOB36dhwXyCnSLkMHhBwZzmQE/daAmVK9xRUK +sVzBIB+pA1I3JRZWWzLI36aXWDdzQMYIduQCV+QR3KfqMEKOtmMd6iPeO+zHUlcV +e6rmequVFaFdVoNtAYA2J4TXgcA6A+LxSnrJ+R8iVu2Xyubk19LqHFW8EzQ2KBTn +0IHQ/42ntBumzSwQhkjXMPoR6ubK7i/ZOf99/rKMVpDF17DJEUTxfy7baQ57XRnc +7jW87wv0UaBzeyM96430ujSCE2kKRbz07DI12ZGrlMNvEAeDs6Qm6715ODtBzKsA +om829IOaIiNqFziphrPKp65qCpeys2+uD3FMgF8yLhKDBiEn2zeutDGPg9SJqFQs +k2i/Z/Lvy2wJCB6E6qj7LLOcHVvv4UDIbjV5BvXdYRAVsi+U2GmS4ymOQoiDkr5W +maiQynomVu+8YdoDnCePNzBNHzM0+lLTQBTZ6nBBXNcOWBtyyj11xkBHWhcDPw8I +i5pzJoHhfZ+6T8NhahowcrRnxz3iCDQryVx86cYISZYQs3MHuQFS7s+c2OhQVG65 +8yM4T5QODbs/Au0QVRwydhJCY3gJ140GQSL1t3Pl7CKwmKiVvjA8NLGEq9W9OTmg +5afA7ytp/6lgDyFdn3avNj+SyaElRg3qPLYyuM+4yS9z8MNy/pZUitxBZGfV55xh +mTF4I6cp2LdL3o2x7PlYr7c/zdnmVgE606IWRXF1usTk23XbgmdHjuSUukrnc0NL +9r5EKdJ+ojxyb5Xdx6FCpzNRMOqzJh3KdBcObf9UsL/WhDrgUiUhBcoKhyRms50f +upZsGX8qZjizLiTjJMB6u150WIc1yzPwSVO2LXHwsCr3bXR1b/w1irwFY6xIPAvT +20IEKQQRpsS8KubzE1LGWCsxXJdGg3F61k751eC9OyMJUNUgHsUtFkmza1FJUEkd +KXnGb1DWf/PnAn8DuOCn7k+MmYvLW5bWhPvhecjSIvaAmYkwPLOVI+YFzbqmN0fu +amHkLPRrk2QIGWtaUs2MChieN8Ss1FLz/QYppLPte44qjCLFnR9YsAD8ieY8/30q +9HfJ/qF4+8jQIGUA/nlQ1JMRTTDZNXHIOx2rHKR4ECuebMVZke0QGN0Ba9b0Ar+G +080oohSKCuQ+09QnzddQS7rB8aC/zVQtuARWxmZxdXox48/GE3hV1FV3289gaur+ +q2ntxtGa8isaaflBNs0Eih6/IOqUTmjD531xaN/QN3LqjZIKKZr8d975Z36MZ7r5 +LOmOaabAGa3m5AinGbLc4HDALcOjd/ExKJSVPPGwA2MFDX8AWjgWHgoPP3NnwB0r +b65QuEDZYxr79i8RGd026M7uz24hl9tS1i5nlsfTpiDEjdyzHjAO3oYz02ZtzLhJ +hpSo9fMBCgC21yfFxKxTzIk1y6RztDJ/ztx3iaN1UygAbsjxapmM6r/QaO21obeM +2qw+NJUiVAsp77WAkvOoeId9pS2Kb8oC1WmEa9Sf6DsAbJOrqrtiw9A7v0Gv4dPf +AgnP0hONv2DJRIeTfiaSco8JWnvVKupUYQL+Fzi9w4zYx6P2Nhbyje4G3tfxRfpi +effTD55NjfD0JPTOtDPy6QDbl4EnvBjMT9S3OEQxckoErCJZgux/Quism0lxaGSP +wetlRRAL38LamiTSHLNA +-----END CERTIFICATE----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-256s_pk.pem b/tests/pem/openssl_SLH-DSA-SHA2-256s_pk.pem new file mode 100644 index 000000000..4b8f97a9b --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-256s_pk.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFAwCwYJYIZIAWUDBAMYA0EABSZd4agdHX3trfc+4vHL8Meg7FSwe9TsQd1FDGv5 +RkBTHzp5a6nF7q5DTriurtMg5GIKSUueiH9Wciq1ggoi4Q== +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-256s_sk.pem b/tests/pem/openssl_SLH-DSA-SHA2-256s_sk.pem new file mode 100644 index 000000000..ea51671d6 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-256s_sk.pem @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIGTAgEAMAsGCWCGSAFlAwQDGASBgMJmhWMsHC+ZaCdeI8NGfz8qwmL+3K/x78SY +QPkNr1U1Wu20BFU5XxVAdVAwO7kFamzk7yKWBqJDlPyuDZ/YX20FJl3hqB0dfe2t +9z7i8cvwx6DsVLB71OxB3UUMa/lGQFMfOnlrqcXurkNOuK6u0yDkYgpJS56If1Zy +KrWCCiLh +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHA2-256s_x509.pem b/tests/pem/openssl_SLH-DSA-SHA2-256s_x509.pem new file mode 100644 index 000000000..77f880bf8 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHA2-256s_x509.pem @@ -0,0 +1,629 @@ +-----BEGIN CERTIFICATE----- +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 +diPixZGf44SlUxO3QYWdCt7AtavoYfoHx/O5kxpDouC/twM/pz+8zQM1F60ob9YS +g/jelCJ1OuRa7/ySqpxYyrb4ahkv+jDjqKW3fFaGp7jO+Cf0UX2li7x0d5FcRyPS +vbvxL0p0YBQ/KNra0PtJc9hYo8hPk4/ySVrkn7pgMI/LelTloj2NQ7UarcZK2WRl +4eUn6aYneL3ZIz0ZEnbMf4ELzGtZZ1F3MNWU0VTtLZuWN0YQ5MEzH7aQov9pHswq +/1gxI9LIeo/tM05wWMAeFOoPZrXi1bltOTR8DXAepM9NXh+jFMWGbDCkEyCooFqI +chpJ1WAHeAmn6MNFO2aUOxlpjVBSBD1KoyfEY/YPCge2wwUIH2YGuFVCIDSe6nej +wid/wSzZIe2WV0qGPEA+m9qeYS6l5dez0GtloDsjyyJXCc5a/9nKhsrcrGLPQaHH +5dEkvVPYM7zDLHg6nueqKXz4RazCGmQicR1Fx5uDHsOc1DqlHFLNzTj2Z6yjhXxI +Qq/1TrQPkbX/r9GKlayKHl/UVDUKIRz1VD9skxxWKdVriMpIouMtTrdNYrac4KJG +Qk0WUmoJnUGnseGhdcBJaSDZGfJBx65N2mFnrdSB9bfE8d64T4WY0RcMXLKOo2/x +eKtv7yJ9k1tYTmM68F5qWTOve+gS8zMBhuG7lg3sV+EK7uHGEQLxKEdtlQa1N8h4 +JKeGH/uxyIrkCvmmgDlCG9JrTgaLA0N8mN72rKR/Ak4nd+lSBuNJ0c9fh5GQi9Jr +jQfMfIEGL6PhHVEj+fRWlK2m2lyOKKxhkwpYHNkJR6ndQNK5GaY2RTW7maH8Lu0E +WZBkMQSdu8Hruu6oe8zwqVkqwGe56dMJ9FcmGGnSmkhCMFqEM9YlSvtb0RvKrTU2 +hPJMexzjI9MlQgAkoW807Pqr2DRlSTNTNv/GPMmEdF/YZitNzMg2AGavgIiaKD6l +MXJySEtD7dZGY2J6S0f4yn3CdPbjPZCTqf6RBi3pIkct3+Ik66sa5kugHR3fxuru +fn7J56pgmfTblZRE4nMsmTR+FqxUyNd60tNbGQLtVimMZtdLKsL7fu09Hi7r+XQK +TESNVp+mm/i3iD2FOhAO5LIZwxAwPxGuD+Tm9CQlsIKkP5ebHOjPNy0XxWPrJsVh +8UKqsuHUezubrDHzxyfGoSKXPHLi18YBKtOhDTKnf+QDm75/HXgTmUm0hM0fdvH8 +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 +D6lrLGi2ZtL+NoCReeOn +-----END CERTIFICATE----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-128f_pk.pem b/tests/pem/openssl_SLH-DSA-SHAKE-128f_pk.pem new file mode 100644 index 000000000..3178295b4 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-128f_pk.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MDAwCwYJYIZIAWUDBAMbAyEAzKaH0PGWcrB7K85TgPMR9sZUkpShri9isdzbkdBM +d4Q= +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-128f_sk.pem b/tests/pem/openssl_SLH-DSA-SHAKE-128f_sk.pem new file mode 100644 index 000000000..3358009c3 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-128f_sk.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MFICAQAwCwYJYIZIAWUDBAMbBEBU7rgPl3R3DDS4y5nE8QhQH96+ByRCKKYQso2W +BrAGHMymh9DxlnKweyvOU4DzEfbGVJKUoa4vYrHc25HQTHeE +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-128f_x509.pem b/tests/pem/openssl_SLH-DSA-SHAKE-128f_x509.pem new file mode 100644 index 000000000..4092c82d2 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-128f_x509.pem @@ -0,0 +1,363 @@ +-----BEGIN CERTIFICATE----- +MIJDqzCB1qADAgECAhQP7/EonDmbPwAusFF21sWdkKlunTALBglghkgBZQMEAxsw +ETEPMA0GA1UEAwwGQ3J5cHRYMCAXDTI2MDQxNDE2MTUyMFoYDzIzMDAwMTI3MTYx +NTIwWjARMQ8wDQYDVQQDDAZDcnlwdFgwMDALBglghkgBZQMEAxsDIQDMpofQ8ZZy +sHsrzlOA8xH2xlSSlKGuL2Kx3NuR0Ex3hKMyMDAwHQYDVR0OBBYEFLtpNZzu5hKA +bgjCJAkjO9DZCZwbMA8GA1UdEwEB/wQFMAMBAf8wCwYJYIZIAWUDBAMbA4JCwQAt +g8MQxDaBEAhtGPVgduypST6efHU61BURPOPeacMdp/cN3PL0aAnGDmy3qVzcuDHB +o3njUmOlLkvRWt8HAQXo8rdusDyL3wKxX1pfKwYMge+q+4bZCnPS1Z0GwilKR9Zs +zL7z05QmdDgP2b/EZcI1+hdjWUIB3LnyTFaFdVZNaHWJbOHscfa53m9nmmhvN0m/ +MgJHl4SOavAy3Ta7lIdvzOQSt4XkwT0TkIlB3u60MVGv9rOPpNgDDZMCFU1cFWHp +g3+c73wOTVSUCWuxOHhJaEW736UxlQd2qMEMfalWMiAQFz0JXWoPK3zDNWcpXZii +XaUh5Dd2kQ03jOdV/a4m5qHeLnoV3QmLZOfrVwkEzwFfe07xhtso5ayg6uU7MfH7 +xSVE57sdZpm3Se7/ydMYNwzKUuj8XWSwY6xDrNWlKdrfqcyq29DY6wr55bkEbRiw +LUXYbCtXWUMkjgQdoqAv7dD2JlJ/cw5dRrrajh5o8/fZ1UCaaEXz2PTs7PHahDrb +zLEYHOMU2TxWc59H7sQ25xz00JOQCieMRGweKJMmq6F//m34HYmnBKN5ZS3tUuXL +NlIGyf5rGtYCcP5tU4WIxuhvHxMgX2HX77BSiN51g0W5pNgHpeXAMmKPkEILQdPr +/tDQbTrWzn9VXSxnzXYUV7mekh6qCLAgmnYudwpJ7hxy/O3rngl2cnio3DsKgWZJ +ONb1jkkHyWdVRP6QZyNvJSbGEd/iguuTGV3VHecEYnVyoux4r52sYXPMUWw3n8jd +ga7cQPCFUxccUPw9A97tKR/H/irlAxkEOVAhddJIWzBVFOPCLEr29k2rdpczBuVT +4VsFJbeNyGU1cpmfYi/PqndhjLSh5rrH1XhsmSgtp551aMoE3WGX+NzT128SuxLB +W2d84RGFdABhfLJ9AYuNDCTGJLn7djxEeLUIf7pAvdje2IGchLdNiLjKS9VMQBev +yGvIJgeht59lYGG++HHY7oIHi0QgZUM71q2dQ2wviFTdHBnw3AghqXEiYSCi5xop +2W9xEEs0Mv0ifCWKhlJYqmvU12EgxfFrNf35lcIPydNUgV3RiInjnNAry4u80xHK +08d5jeJy4AWRlorkMwSAOD2eAN3V8DHYAtwazel33N9gVYl9N7zI6lHA523TXvBQ +ffQFZTQPVs/e1lRLfH5eHYvpwfJDnMH3ZVwPdZLAkZD9m0yhejCEsyYxq5LFgh1D +5y2UtqELwGyB3BR3FBQBfOi3Xi4KSsM9a+8Uc/Y191Em4N7ldrp3ZRMghMHrBvB9 +xA4Xirt5rjN9fnEoQrMXyP2YR9TudPm551+5xjqynO0bHIrRUmlYVlpZ0pfTQ5SA +M/R3WK+bC/QG/FYVL2dQ1k62F4aD29bTftc1gU73Aby3Or6aBksfcxTctgfBNpaV +CH/3kdrzZd+0mfOn/SxkEcnOVEJHk48BGXJYEaFKAxl1WKDv7yxw3DwuH2GFKRbJ +FoeF2yCvbsGEO1rBqF+bGEvlUvtXdsC/x+v/Py+rFk5NXiop1/ZToJPG8qXkMMm1 +y/Trno2i9MTQbN16BL4kK2dgDc1bEFmAzHopacOYsqri2NRNSET35qZ2Jd7CSz86 +ncj7ko9bnWQTM2QpyW6aDTeY/ZmTXFAv9SJo/OjbG0UTAJZvDbn6qcOQ91umhDeN +njtKxS9Jr6iimr8dUYaUWgdqkRmt/6oJ+S0ppou92t2BHuEPSVkkj4oiJlHyyu2Z +fHjv0ZCaA1AOmBbfZ+aRA5YQeFlEh1VjyX/l6F8VwXT4uNCUvQYXmBb4gn3/KpQ4 +T+K91b6W8O6xRZNYve556SMa035wHPWAAdU3M4n2WH1EV7nYHgi1Z2NTanNgINZ/ +6Q1lTNdZYcS3Vd5MWnwiWI7W5Q30ZjDMruj28NqhG3LMpV2KMcOKByk3GvHrvEVW +Lti+RXzUynX6PU0buUibJuDQ/rCP6JKVCqX+SC5vpnLI2jImIbI7PUMuhDitj2fT +PtO/MqvP1G4hAQ52sMhl+AYUP6fqVYrFi+xprRyNdKYaCsTq8Th4PVY8rCQtOjx1 +IpwLraknY5Ha+euM9hIpMs5N+Zhuq1jQBmY4XHKSkNs+qfklK2+d/I8cW8lVCHHS +QTtAwcYqC0AAiR0RbpUdBV12lV9E3wXtnPxIBV+x0vllbpXntsoGXh5xDIWBUfmB +HVMKwNdJqNpYlhCDOzKan/glOgiA4PAN5br+F5UIRTUpXlZdAdiOo5qhmQDZpiL/ ++G0UxMqqRgmwMXeXZLL7twGwJS3W1GX4pOVK3pb3XcxFWAdiH0w+K04Zz70eDQCh +MZPk7muVQ8/Nl6U/6qofKLH4D8d/K2Rxl3+JA6rp7Ndpaw3iYX0rY5OrFNh4DCiQ +LsARoaTN7niJq0ihptLykUJ1WJ+ThdFFnw+x9OEwbary61kjBnTO05/8FgStyIAM +mlYw5dsopwK+4NGm8nCAIhU2ogdFmChNvCq2oVYr/J1790hArO/MeiIUpWZfquaO +ingnyvz/Yj5XN8YkIQnaWRSW//7QjtJqhQDo+nbVPIc3dXthMcxECd96xAQrXGZX ++hePeVW0keFiSMSUU/MAiNwKkUuhOvsVP97/AyGyK9JQ2Cosn9Er5mNtlRi23obc +dfJfr5oWXGRB1QVNXpvKQm4RBk6p4L+QElJh76PM1vUmwfbZjVk1yenPk9WdY4I2 +M+fJb1w4cUjyUOzr3gtKIQMGL9fgtMZ6RC8RjBJ7soAnt8bRH2cmxDjKojs5CuDy +U1oyPvYKJ6yZdXa+bTKxj2f1MNOZUuRM4w+i8b7m0l0/u6QwiRYHiTizsd70mZq+ +sezjy98YHfaFbq4bTO3eIFq0JpO/zi70ybOqxqr9V5ZWpufXubiuNFcTPkaB+udo +b+z6mMTYE/W6ZwasXsJrd7ydZhyqxt+1y3pOBhQkTMOGMv9UarmDbECYsPDEzXZv +tFhrvMfwBFNOzomr6JUIzjyneGkTqwKX9uC+W+c1U4ACxodlpgPUroIBMoPIzg98 +K4S/yjIhjFFW+GJ5MnwW9LCl3HiftHT4bahLSuAAGRGRrLQHggezHsVGyttOTpGc +JOpsE/Hn/yK/eaZLU7lqI5jWkj6eWWdgO5HYjZDk3A1LIQyAqvF6YMiOi9AJaIeJ +sd+AZFwrWjp4uBYxF9lXVzjXM76rCcqLNfl8H+H/Yn568HmMAlPGXKnWkp9zkw25 +zABbEBhJuitt7vv1eZ2BicuIEJKQW1nD7IbIHcAQ5RLTjVViSx/ZURKLjur/G0/V +51E73JQ9qCzV4Nu9/VcXmKXIxrQlJhN9mmy7H5g3Ged9HTiCtmE/B+gUQdE9YaWL +gvd16lMq8dzkvslQK4MpqAlr27YZBK+Ao8VNtyVjmu4nRfc6xQtUr91iyo7cJHrP +H+5yT0jwQprhm9orTs6hAbye7LDDOcpG3XHZ3un+vphsxNwLmYANjVR9zsLKXkBm +ykOz98TgDuhscxCTEUHLhokIbNDIT/8qkbJfAZbafFuAP1aLgfWMhEqM2QaHcVMG +y+u0xAGsXewflMgrWPz1BRX/ZR448y2+d6jyZcrYpOgx+rEkhF9oOJLRuVA215Sr +JgdGGck7GPCMOe8SEfMJN9yHf/1rjMsOhdY7hHI97tKKYpEL1maTIl9XaBIQX3fc +cR+tTk3UOxbSRe4iDtbRlzs7/RxKiXrgfNjEEvfnnbKeyu8E6U4bKR60WoMR81bv +qtJNZlg8tnVG08if73szGpNL7dJ+IsgL9wIGZCn+3cS+gIDGXDZbpKscPKzjZVv+ +HVlvrz3b9gbo6s7eb2+q2dmG0yi+YaHocvKvpHiN/jxc52qcItcnNrs4fx5XIcFr +zhx2MQ9NzJ2TVWJHjixaJswc2ZbmiEE8xRSi2pOJZ6TVV8SuT7mRadN3SN21+YSy +R0W/Gry//0SzJUvDy1poGu6VZMf86AxORqMJCQ4KDwlSNO3Uw+JYrcGgeR08o5kd +24RHoz6wJducLx+BRO/n+WZh2RDNggchu6CHrnvEunB5oXutdTJF3oySirv5LP/U +tMTGCoOKWakyjgLDf9/KEvTJXBVMmdklcmVDkDo8kr9xWDMuUYMGonLt8OqlI+11 +4HW4nwbRW9oX3FW6X7/S79EfKd9CC9uACGxHBUh8JtnvsygAnndim8KKyir5l/wn +KxS4i67VPG+GDa4wNLort49bTyGMkxX0dL1OhbASfdJPXyQ2YFkwWesp3H7R+9x9 +TmmcTbF/PJjF8CLJ9WRqblfCHXfIXP6MZEsddzNxX+QI1kNLt50CrOQt5EXhTDy9 +t/tVxOmJP6fb2usqetBTVVNp242WUh3XRQauTv5Rpr782Z22n3iZ9ix3G0/o2nN6 +ivH5by9HVMoTmtNtTpqVXu7yV6xnVxS8tj4leLKzbxMlBKGy4su6qD6CSXtphGEB +WABi0h9SeRXC1w4BnS2ojRLWDgY9hWq15FKqS7YNwcrp7Wc2D91+O3vmGJBEzrPg +SDUZAtmz4p7isJgnBBCiFYWBOexMQ8q2PrwjTHP/1KOtrc4oFbhtF/49PV3C2Muy +AAz5p5rwuFD2nAODckLcXESjiKLr52kfjBOcjdtTWZHHqQ8YehpcLfXRtLVEdrna +OS2Pebi4cwxGXPZ7ujQyz+jAxal50LJZhBnWlml5lzZuCZrWB4Dr6bKeg8yR0uiG +i9HbJoFa/V1FwmpfNBNzA8x65FDnZj8VtF4QFisEYiVe4eyMKYQKGlcDAgycWnPC +7Q4j4uAOoloxaMkc4s9BZYJMQuZbQmP+D/n8kDq+MWuVIEznTazPUwXQ3UJljZac +THX91cy4wesFdrzwQ1+xlXoDrPBorLfW4E0hTDn5jlg7kaE2SnrncZNQHKQEU6Jm +NREO7OUVfWsO4rMHVkEqZwSI46Eaxq+qtj6Zy6yvuPVLlYDuIlWkCLSUlIM1o6TT +G2iXqot1yn4Rtyj3XPLekE565+b2ZimFVlpZdaod7kFuclfMcOwjVREzafAwcrvm +PjsausOPx4CqksKcabs+rX090w4m9Pq+UI9/x7WcozGpUDlNX7kMQs8DQQwbKqCx +UAzApJejxWQjKqxvtnl76fCQFmzyE0Tqx4TW4koVm34czO2579Y+Eli03cKFpnIf +CTgKSKIa9B1dWODWjDu475xsRnrSNP/PLJJ2kFMKYECe6btUhj/jxannNKy9QI2a +CR5VHZPLC6tn9Tscrj2xDxNYuRjCdCGmnzMVbSZGZEc7lcnQ/qd7QrcIixQ5LGgr +//L+YLcwbSsFv5vdeOznRi4QojnZDfk1lZOqu7dT4qTRDTu+S4Ci8O6XQeadcBk9 +5uSP8w5xFemi6GbSJ4jKFQs9q8FlhU3QMkeHO1tbcvRY5reZr72h9+zXv/4Qhj70 +x4xIhM0GCujYNYYlOZpUJ8Ruq3poQdvXgKXrdzRGk+/dVmRTCfmXp7ID2qwSLn66 +fFoa7E7kWirrr/bTD4vKQLKvA//QclHPoOV2LdKaHJtK0DJtN0EUVmacYKpLuoSH +bFdcoNTlmX0vg+k15t2JMYaiwmIhXlxI41j+jM6FX2quFK1TU+HY8soSAk9Wmr/1 +Bv+4fXrEuC8PLtKqBq402J39mzYuHBd+nB+hv3W+cQHgaVepE43lzU7ug8p3zTin +XoemDLhTJzKb48JUqJ0+kuloXdyytfYsWzjw6P5c4tFSfGbeTcF1j2j4L700Cr2M +jI9zPj3zSK0aFEetL+bPLqV3ZSe8Xj1Ma4sl0D/L508aQVK1CKFNctOymp/SUrG5 +maP1+8AAEsphFkjj94eXNdQ6k/9q6uU64UBiFS7bA0gwqAcfFPO/9c5ml35K12UB +vp32fkXgZH18wo66hnegbRDqPu89dTKcNvW2j4Z8XwAm+bWEOmEjzGglBCRKXhN8 +t3BujBCxUAu3GQuKhelNVZSeTYmNjWwZTa4viOtC9+oTl5GRGlYcCXjYGbqXp10J +qs0+mVUC5eCY7S+r1CPpTh761X0OR12qawU0JmxszIfJklEez17ctVZf9HYrpo8e +YMDWNf7Gy1oDwaI2lzlc5NckIXpgu2hdH1QHD4Ws2PKcLsvQ/HbS5FHpK+LHNpXz +A6HIro44CP1/xFp8x+VAyoplzaFG/sQ1iwrQkJDnXCE713wnQLoWi1t4rzg3ncQj +NUGye9OREfYYbfhBuLRzIX50k1dgcN1UInjoZ/2XZJqGQVyAYgKh9Mi5x60F37+F +soLz4I+0CUWQXHjJm85frGU8K5qA2CVegY9ueM9AX7GlKUBr/rYABRDPvB06UWva +CXrjHEmPh9Nj8ZtA7eMRTTurCIMqTmlj3NK9lUz2n6470/ESPJO6lSpgFlYAdIjH +EOhNcuMlQ1mVK1zbWesSrYzU33ct0/1FQaIfuIoRylh4XPJvnDGFuz003BJ7lyZ4 +aWIag0Spglmp9hS8P8uCv+JCrVuXDdIqd79RClUbKB9YG6ARZkF/a8xU8orZzVd/ +EgUKkF3DAbmwTu8ohWxxjGtIZn9dZoQ4+co3HEkTJ+jkZ5V0f5gyS+dD8KxQjtOn +5TqUa0fa7S1Pgpk1mg8wNvfhAW51E3dqTyS0fj7HFlleeDC8UB9H7hhJ0Ri/CRx2 +popEH8+/9oNZc0qFkR9ercv8YMKMts0pRKfsLW41iox0OxhhdSztDyj8OBtkBuJQ +zBcPnN7dIraxVtgwY1Q39dz/s6Vmkczof3XnNRXBSRaxjP5JbjqArOe+fqK+R9jY +H9uznEY6mjaN5wj7xN2BM1lZrz01jKa9GKlfsc7pWGF3KRzw5wH0IqsEmxHYJBS3 +N6pf6W7BoW05Wh124v/iDvZsAlkWMNvAEOwYFkBSG5vrbXKcoC+8CoUijJkVBFVs +14YVQn0de6cWdJAGJn64c0oDr5J8muL2wsxjlTqG98ep1fgHNQ+T+d/ANfwyp/6P +SkRE5AMDVT3QJNPFDARAl3YuparmBnuwEPqh0hxXP8tBJh1bmtg2pwJQnEWAB6Zv +k23Z4a8mlHw4kEP1JJimvR6sZ1CCsuNgEaVv+qOU1ryb0wJZGNzlJCc4or7HlTn0 +/0xt1lahqKTcupgQPhxYS+bWubCeJlmnC646sNAzCHa/5XtNnjoVzmALUm3Nlcw/ +8jZdUvPStAB+n9Yc071puiIMbs3CvgiJH850FapC63rlYcwbNZS7cWw0PvfR80JO +wv5Ei0VHTAW75fw2ngc6LA+0dM32/vz2YppoMHgGqZObDb3rXJSCm/+08Ju0kQLO +RC6hyq4QkxNAkWew8pvE0oRnGktwfGvEPEEPnSeG+Fsp1vLft1nYbyGRzJxyVh0v +XH4vp8exrto8FFKh61oh9LhmxOanE6mW0p7DFAVyKDB3n41d4vQLmjnsRjiIebXQ +WPeaNAZ69OZBgZ9xJFduBogU3mC8sMglyzqPv5D5rFitQEcbahMA0Xriras6vcBG +tkBj8mpnZjEHJMvWqEMCaWMqtW5NxVjJfsShExwzMQ/3L4ov5nrm9CxRuaoouBrZ +/95FVfAE3PPIStfjjd2R7yISgwiczWvrc/+OMs3f18DlqZ1dMm1Z9mc1e28BGo7F +3kFO80NUMRiO7sl9hvQUHYpOQk6QkoR8Cr7zW53NvfMLmR1RDB7TyWb4RBvsPX79 +/IZBoPUl0lB39HlrMYfCSGqmOflhLgcZjG42nRpIAP4y2ij4XQlUhxI2gR5YPV+4 +ALkvMSmsJmbED1o9HsQ9DikoZPw/S85WqNXZtadLMthRTpNaeP5Ty129SikWQFBR +7BmbwSm8Nx5SNoyexk4A+iS+TkwxcTs7EB0kRiSvVSKtMGFzwJ39IHencVNLxMEJ +7OfUdxExtw3tUQNcIB82NZA50QNInRcyIQi1PS5BO3xnCBulqrCBuY/oVVV822KA +YVuiDaD2TPxKANsTXHYN/jf0MSG9iEpyCtCE6zbYVHJL/kZn6i97b9Wj1OLmlLa0 +rRjJtQ5fgWQmc/2WyaThBXfAPWkBQKpEo0rJMoE73LqpehWBNJ1gMVOUBmjbsmTe +5AOMChiixZfkz09fp/H64EO7BCRC4STncHwqbWVlgd6HIFkjaAmJ2d79H/aj8thu +M5ss2rJCN89R2syj1z26boE4AE2RNPJEpKbXsamCmhwKWTruKqo0jbGVW3z9pukR +uY6KKEyvafCWsnp8gDt049HqgppCwnmmWVYmAWDBya7uf4HB1uyXVNcsjLvM9VJN +dLLZyj3DuC2HnzANRtyiSumKUEqnMYofTF756y/l95z+RlKKA34skoeTGi7am/h9 +BQmbYisVq4MC8T/ivJApd8802ybbTVhgaGYTbuoImZmm9tJTII2InmYtEvvc8Ui3 ++Dv8v0n2a9hhrPm04Li90P1eAEBTKSlZDHGTAVPAz7NaRYZI5Dhz0iFPlmnVU+qN +p47Y1hbYUqXk7P2Do1EwLlpS+/kRUeblK6cOiHLaFJFVl6a1GqukDck87iQDHTfm +ildKtj87yftSo30hQ2F2GNUhbyuOfe3/ZZf2xL7ewTcFa85nlsCB7eHhR8s1lrCq +U84h0GUgErZLimXLRSR9u6fAfRSLbHDdd2z5njE4bKZ01X29m/OLdKiaeajCBiv4 +ze1VUZ1dvh98DGeIpPTHQohSN3GJ3NvgryOgZig307Hvmjy8gcCx9UVXpjKUmlny +ijM3JYMTPgoKT0AgfE1ancWH8lTIvuOx+zvvlbyVdSypTlRjR718F2B3NLYtxlJv +R++ScGYg8QoBmsKxcjLvvDUsyVQ7aMtT8Lfma1078Pte8R4AFPzCr8+aOUvsAa/A +e+nyxpwKTCUaciHmtDSbBQH+s7FZz0Hb0NeGEpTOc8aKk40asMxqtpEz8BnThyep +YJxcO22/rVlQbclHBIFDRIo7zaxPAAD98vzUVW8Vw6/uHUSUHL1GJbRyxCHS1hit +VxfrV6wNJbnyH8k5/gkJbPbjbpg5EWwuRLmTOMwhVSwWzxK+Zi+aol+1tY383/QB +J+W2Ds8e4HVCRNmCG3mbPQ978VlHQZFgTKos06otiKGnHzTa+H25nLlaGNOg/cY1 +kVTiURypy6peTDdr0YCKLT/7Y9tWPRa6Cc6+CsO0Hh5GC/0PRXoHMMhKG/KjiMyt +bS3NQ5Q4UpaqjYNy56/4kcsto1zI0zKfyiHAPESBYtKgnJVlBhFtW4s4rXWt2d3x +KqpgZJbMeQTY8bPT+K52szWovLdfXD5b5pxzOt/XfqmzRAV1ObWTtL8kqgexkgP6 +K60XWzLKFZk/0Xr9Isa/p8j9AETS3EzV3GTBOEgYb5FOGxkiWx+3weZcXhpL7O6+ +6V+rVIqcXIckfPNeAUWzN5EpuQobcM7iZUAybH4F8XeYJxRcXo0PW9/ylwikxUgr +fP6HedR8K7sO5WSPZk9Mb09rBzpM5Pd+S2gCVOP65M26yDtHUXziDOSH0VvYWnlM +/BKTa83VcVuLiQXWFwoQ60n+buH44DRUYb/JldgqeQJ+4ouDCk5PtR2KnFBhDTvd +gtf+BfPjWyrNuMpZUqoTWq/RMRvILdt3XwnME5xCjY+cDH9eA8cpdtuRwPmA/PjN +ZES/4Slkooa10HSxyLiNvj5bY/NYENX9azS70Y0T1RRO2Q7FgDsmjp58iQWcWlhm +IUEGhqvJvE6oyXANMXMbvHWchOpllm3cyj85lbNlZ9O37LgPxcu9pRxkohWvqIHL +X1/xvCs8KjYs5QSwzcDf7e+cKLGyX363jjviUqjTTo24upqKVsHPTSTGFMXXoXE5 +4UTUQISmrtHb0kEomBitDPCUdPhP97WlgCRDFPv4b2zWZ1DSq+/FXcoGIXx7Ez6a +5VZchsoIyeOD8ZNLaGhYZxpnxL9dRmCfFm0ye5q0XsR5Dy7Y3ptkicb3PlzXo8BL +EGJaNPA3kMDw1tcmWMW/Elg3y8G7eWmIrLy4RoXKOTvHIzsvhgv+4pVjp3UBi7kF +Ie7ymxFNXV7Wu3fvGxDfSRuCvpqnPbtVLWprwQlJVLphqUYOKWd80DO/hLhgKad9 +MTFPoo7u5K3u+gwjSUxwQasmYl8oAaKqYN3ivx6y1eI03H7lYEbC78kG0+ADFgRJ +zDoXGoPTQ+GLmxXcZszR7HgchBXJVw4blIvSPTkG0Nb6cFNE0dkC9Szf5QUDnpSY +zsmabDNliiTU27MgPGk3kpCK5MPpTbvNVeNBY/QVONfImS+6xTyfz11NkgcBmauK +PPwMTZmfNDFu9+MaigUMKHiPbtt6Y3fgyMPzkZ5jyZBYH/pz1lQO5FMudhShPVIs +r9jZvmbdEh0Y4LfSJf8XNPMCY3RWZ9ZBtmulvE+wPNqfcoiLuefrmd9Sn0hgpBgq +aIIJbpuwrd2uapQM1VLMnFbuSGxpJj1d8utgFFA/I09+7hoMgRZW2ghm6CgJGx9F +iXcKOijUN41/AeImPY8Sm0NgEQka+7yBqFqzRufkISPD5gkdsykCTIOI6mnQhNxs +4NcpC7YoRW2tKif0ow1qUhaIe7faEhrWMS72qoYDGR1MXqujsMPf6+jg3aXvk9nx +a98mRTAtNGCnbse4ooKXcrjp8o4DOsXirrHcAW5CRS5YWbq3Gvs1ZsZ2/801Jf2n +5YNDiOKUMpj2WJGARqaGO3fqkOV+Ir15ihmaWGL9iPUU4ihBY+D006r9Cb3tnHbr +QKFHuL2fk5ULzLzC4GGZ/MDUfGimMlKsOzYBJaPF0vZcPnaHYKkygmp+Sr9rPFu3 +0azS/7SuRDSiG2eSlo7IdtgIQ99TgzaxNHT0/+GHBJ+QLWGGSMj/gXcdvcOFSahz +mzKkO8wf5X3ts+hqg2zjPbTzLWVE2Gs/4thFmkM+2Iu8LaCK6M5OGeY4WzpDK9RT +kSMSfN9XpdGmYtffESX0BH1pMRVEWQkTTHR1IPMpIccpqGTGob67eHCochcNblR0 +U9vgTalRAk+rsL5XCBDLapFU96enI1BIEHcmS5Mjhn4sPwNL2nLprYJeCYxMEzDh +YAwErcb2kz5zam7ALlcyu/u/4yrpxcZ5bUEs6wGrnwvgHForEhPBs3ObkFJV1DzA +fBmsP4Y/azhduBk1MvXD8jfc6CqlFFvraRt1Nuk1kkyLp+RQ9X5nsGnjSIvoGpuG +SOpEeSfz52JJzwiXID63jqRX3RHTv3UFEh6Fi0ctv9qV8XGTRf39/9/9OpsK6w5b +vYenFih0/Bmjna6sbaEODYnn90An6iqmMl4jMbQbth5h9nwgAJ3rnxWoWZF17wm/ +XmyMHSVHh3aG9TUcv7zswsn5JqtuX+B/sQJtOnCY6FYpdoyqCHZl9MDOOeVtGsYb +18V5vQbeQdBZL9wo2UiK/cRdSgrF9P5y/Y1DFEFn2FH8PxO25a9ry2OYblGOxWZ8 +WZ8rv+SkbL+VwdxUxDnZSmt1aTGRjvnevQmiceN5stCGgQ+/RQTuXnBGl+aHbrRZ +psxbS/lJOp/v7xIQsGc7AnHh3f97zRv/dLfoZm1sokvMaPrlW2JU0S4g2q1VmflY +fQVl5RNXaytpYFfZiYMb6c6Hg3bBAZyfp758v1sG9EqjXB+NLo2I2HX7mUIzMHyp +6VDMBurjxVCOkLl7OCKiJ0HefG7kVYIlsQMCRIizYkMIRGH64ATTFzkM1E1DlgFo +HrdDFlEVOo74R10KuvwtyizPhx5mnWGbTz1pTSDJOEC+lECex4/kl3wJSfEbH7th +Qx235aw87OqSmHKkVBiHSZ52NgfSRvR4kza73jfLJXGkd5inphh7tDdD8TvQGo7L +2zB9G9TJ/lqDXkdN9fcJirJ2b60bytyieWB7S2hnh8MBfhJdCB0dnHDBdiuu2cg5 +ArZo4If99e3vcbFlFEUVBwOuzErVR5ay2s7xPKYju0IP+Gf2oib4frPIdZPl2LMy +Z+S/aPc2+131zLI+NCf+Wcuc3eUBNmizuHNrcqK47oUVr81uckCfjUCL5X1TMbJT +Gnt96/rKZrNRHwP8k3tnoakSQToxrSwY9wYb5TWDEvvvpJKCd6qZgrdq7jEXaFd/ +41fmykC50vFl7w0cutlLGscQjs/+dCg8lPz7R/vyJaLCIqm6KJf+BLARFEnn6AwY +Yl56qJpruRaglZpMV6oCOQyW6y39SRBBiqSC/+kf7KFl9cll0Szfm6oj1gHEMgUS +d20eW6fQ5ZvrbNhCI67srSChKeCz4Vxxgp4hVSQAFREC0qEnd7VXBF+cxnziiOEA +dhQXkAtedL4148B7hliGUzjKi/EMS4y7VziYOQnwIl5RhKvnWHBcp4LtljdZ+96x +FrLue3r9JTLhbGHTyCpLVA4JDe9dIeeq9xMlGJ62wuG48ueAQU9APKTYipj3E1Lq +UGkhjL+fenreqiWKhHSm78okSpIY9fKbkKQFaLnjVC3fvo1V9W2ZG/KKsvE8uQDR +45klTY7wDtKGYeyA78A4PxHtK8NgSTXqTMH2Bu2X4cR3NFvC3AHB34b5vjLHXJIU +cCc+MGZTJCbPpl71sclaiKJjDnik+xWbyOS6lj9lmCSnnVqTHYmXIlD0yALV7vVx +Jjr/P+v2qFlRCjHCu9iXfpCLbyPZlbUspnoACQwn6UHjZCb+eP9+Tc/BnE00PV8j +NWeuQ0QcAaC4cKTCA2UYjYqKQ1Q3kUT3u/WZ8XvFpj3qX3pRjo3z5ia9dY3E0Luw +utjtGa3xbPhIgrYWgBecPsdte14ZRpo6HvOTVC3E3ozKEdnG1QuRxT015rD6wefn +8sSmfGlEsyQJxOyXGRAL2kztvEykk8DHBhTIyd/OqAj8rqGlcES7sxoZypRTuFDs +BOE1dXZL+Bz4UbxLPeMkWWlTTdrK+DNsdOZe0B8iX7MDMkx1c8EEZUefWIVxv5EP +e4buYUtvUiT6J+WcaII6EacuIPU+PAA05i5curbwHMTqHOgqU69RIFt/4YMuVaSy +0FXTnUfyl02rfmPyTH9FBN4tHmIzeJzZjRkBOoGa76Q8OqADCiJCHhG54S7UIiwq +YTSMQ/Xxw6xhsZZev1FGx6OflOCUsR1T5xRSbLPTe0BPQ9Xde+lI2b/6iDXZn8IF +1qVc2FYQqov7BdFR7geH3CZ4Pv4E7PkGoNSwql0Gj9DhViVrff0GLsAt1Nry3xf5 +zEE3tj8vXrfAOZxJUAtXKM97M43GiOOfi6czTOKbal+blhoX0hqDfhmP/u21zJCI +JGUYUh1z5YKYZozLd1jbodyN/OkWDLOJlrHd+RovFZoDJFP2VV3Pl5iLTwcRXhia +28QoUYPIOd9MwfQPKMKrkevr9+OnAbBpvNRE4CabW4n2cQOmiQodBasguZmPHI/Q +APuIjCv56IjejUDC26kuod/6jFg98PuqdvZzLa7Ph7QAR42opCDGna+63KOHTg5L +Cpy/mlllj1c0j37W/XVpeihSBfmwyVlIgIOD9zJNFZAB//EL+bFx9HWZGt7OS0Mv +2IBtjzBP1dnS3I/MQtub4ud8PGkwoGthCFEZ/skLUba489IhA8zfi0ARi4k9P6ZR +9pXiQ9UEl0PEeYul7wz8z3WHwhboYYwsuq64IwCZd01QrZBOv6hONqQZ3oYxirAR +Urhuqre9PDI/WjSMJtiPOvuEDe7/yGKsDsLDaKYy7HEBIiRwQsDuVdQC+7g2TO0B +1+CGNR7cW8rdpH7RoJ5b3b9S0SranNa9NAImv6zUge62NFzqa3TVMZja5hVQCR++ +9dsda3USxFoocIUpogk6PHqGxpbFW4t+gyq4M8HBNhwg7mIYUwS0dxR/A1YuqBfM ++E/cH52bDx9VPfO/IgxQEXvvubjgu9xrG9+sdF4HQAo950CWX6n5EDYwDIFijhFb +BwB9WDZUkJp5H8P0XOW7e/nCjUbLAiwHvm9k3hQEo9787CvCqi+Cp5xac+vRIhmG +zglprJU1eMTuvHyMRaemThBde0vE/spHkhCgM2v17WBTSawhUn4DGC9w/ISlaSmd +1AvibYKnRw3eE04srLL621W7gy2KXn3Z4CiX06Jlb+5H+OFtAeHQlpsUuJqTrWg2 +89XwAvL/zuC9ItR2ygGcp22ddMEp/rq+nmH4f2p37waY0DK3ftlQXo00uTqOqL/q +iXLR2vcvBKi7J+7i8257MfUgOw5kmn7Fm8pwPHyCkxAGMXou2qLsTzgPnb7tDTr2 +Qpippmm/GOsW3zNX9IQFyfZm4P6k+gSaCjQGipA4ylgBMI9SB6oJa2c94VdVjtFP +FeCWGwIrOuFjGNV2VaSKdv/xdgVjAc3SPX+9sd0cUTgrOTupopVfJFDzJORNGq4F +8KY/Y59KseAY+ol2bZUs6vJQgHKaoV9At6j0KxEf52UMGpw+5fPYciEHlqn7uCA3 +xykMKT6RL5rQxsw3+hgD0HDjEtdAVAdK8X46rw1sFh3ffW4mUC8bS9fNkRW+vEuD +1fRWng6cqjZuol74d5jbCyKRbhB0VH1KmMOpw5jewoWLStDIb9qZfKELYXbiS1ow +tCYycqN0QrAuVgQpV8/hAHnfnHz0hXZJkGnNJMJnrVaPDhdKgzIDxydi4juaanDn +FzwNkv27kFQFF/1DjIjB0XGsWkxegxYHiZhs4ZN06/EKwBW9Bv8atCRXWKjyYpnG ++Zp93sxpTkDPh+jT1tcriQ6pzVQ5tuMSYRHCRR13p/d/07wwlnttblcv5Go+vEW4 +i3GsXH1e+uwWNM8cswM+FXAq9zf/sF0tATxqOQ5S8lLvDZVll8U2Pj5jWfznb7KG +HpLbYiYuaV+k7NMeIn6GUsh9NthGVASD/5Wbge/9lb/N1OJlq6vhkljUyN/6bqXA +fVWFEzxCs0lfKv2cqeaIZOyNHbGudaAFka/Ip9x7+GQ0BlL94SYiJcTUu/qtDcjY +VcMDHMqfol3Tf00iiV2WI/AbofCawqlgpM6Ux6Mrih1bgJs4rBdiyhOGoNL1K/kI +65H/jB7mvq/V5AVjz9I03deOkjDrT56nGCol2Q5TQI1tLTuCOKFsGcGGBeY5fd/6 +CAxy0iHp9BKA75JLfEHa849jRUsrh1KGoFlwcX+rVRsUu9oPDTu0QakBHkkcjpnL +p0DzR7475PavjFYpDlelTMD0jIPtRCMKDuzRH+2cDnDNHc1cGDNJThNhaFrzOJxv +MrDthijiJsZoBV1c864Kf/uvbUERUPfg/cuPZJJ1g4ailyqhNFgpRRA4FR9hG9/R +LZlk/Y2acnJrctBNmLfv+ruKpsfaPdVk+vtxLnMjh7KYD+UtaUALrUrY2VMEpN/P +LbHwFq7hKEoAs9LyvUQfJ6Zhbq+mGvzfeDooPROMQFE7SWVVm9emX3QIT4+oSgLk +Ox0Fd2N5cXCC0U8vZxqZ8KfxEcwn5TMkAxAnP5Xgp+6jMvmNODKeBNiKwOhCJIma +y+MB54ECswkhOof4qvFpPJVIt8YFSyPa1E00t7YN/kyVXrp2Elpm/i0hw6qc9of2 +7C3vhQz3AcEGMdtn5d2bBHQ33rgSqme/PQizpC/skUAzqQB5fyMwN4oyxcU0fYZZ +DvJXv/0dCVdQWD+xGFcJUX+WGwdvxyUnHop4shQKMVkhJozMmzA+ZSI5v8PRr7XH +qZgRN+ruvv6iFjKFMPWf/7JuO4EHr+6zEuonHz7ALyePVyBoVN57VNEld7vQ+k1M +JMu6AqTsP2xBWJlW0U/92F8IFOr3LYK/FQU+3luwuDvFoo7zfXKpZ0aKhXeoEidl +9U+UlI43k7rvvqgDn2B7PA31UCYVYVPnawnvSzkC72o5FmoYZ67BMLHhSWzzb1RE +U7OX5ZJXVNf/Hjs+P9kI19GkUgQJjHNkjKQ1V4FNf3FJeE0xfRnZavlgGJkrqHgo +kJS5hNTprUOBro1QM0EvJV2JmA76KQDLKgJl6jEFjN7ts1mPpYprpjOHPZJEtNDV +E9JO9Ey1ymaN+BqMx2+lOf3HyaCf0rNbCEcH9dJaPOux80M8jztInsB2DwGcbWx/ +c1Whe1UYeORqOCBTnvTyce/+TPolh5RUEvc85I7fy5FaqimNmWZuiPzf6J2B4dWa +2IhCd6patC+D+MQ/jFNydSG/VYLu0tDRcErsDZW/Xs4x4ib9YpzQYAraVgRNBAVc +A+6AOVbtWWN8N1KEa9df2EdXrNYrR/DehJ/7MI4gfKpVd3VgI3cgKaekPVt++DDE +8dlY9SmEeo2C1+2MCOz55iUtxlqfSGKbygTPCHlqW9+00uR22QHizpQv9t02CFnr +93/51QltQoOyHv0oB/ZFAHbSZOIj5W/qK3YaP0ubas74ecTtZYq9izoiu5+NrcxD +NfFoPpW6btdSdHt2Oxppu2qDIFhTqejsZiUsiiEwx/7+cis3gUKL+/msEU2iZkQw +yWhJxogNfKC6ZRZGj/k9R6oaSobgm4FBcQYQZ/xncOC4zKNaxA22id48b/9NPBLX +2jjFGBO8noHjwS5AWmjvxdwFuoVNKhXT3iZ1shc4FW9+nCt+CGm+Id/+AIi9BkGx +Pu9feLUvEHCN/SR36jiR/EO1IIAsSowwlYgKimkiPPJ/68H0hCE/zvRBnJYsamLE +LsvTLyG8o15dXEQH5nDR/vK/cI9lUxK8aLom2kz19BZ0sYM3Ed5hgWQEssK2CQI9 +XZahGZio8ZK47i8oOBxOCxtHFYR6rTIPRwN2bNn/Z+tZweLTyeS5P95hJIwk0X3I +4GI+dig0ua4ASd3F/mqALSThP6S33MQlBJazuFOzlZ/c5s0UxMUs9nKRJaC8DHY0 +b24cfofgQrOsSvU5dTfIFQDqfZklpCCD4WS0OaIOUETeVDhjuJP1yGWhobocJ5wD +F9WjroxFg18VcCHvuKCtrRTMWF14cJNiJZCJFZqhvZsnPbDhB4cwgRJTrH6ollie +es5VNwCW687gRDdvbXBaQAatWJWH+lJHFVIcp0u3LRdapnDfJo8YYo8SLX+Y1wBB +wFL4vsZY2y6SFYlhbDGv9b1d+Dq41PDmvOmfUYGR5ZknH2l5lGR22+oyEUANKv86 +vSTSxVB6eXUmqlcYRMzLNrr7ftG9Iu4mB5eqNYidOp9KH6QJ29QiK4UgaP4AX/yt +j42OC8q95ANOFFKpAwYhlyeZfIQkYrxcdYMJuukoQp3czkQ3cBUJyzzO5tcOLjUR +2tzCMZM4yJLN4UgC+fI9Isz7iOBoQdKRtISYdzkUuZ4ic3h3qLusf512HC/ho0xf +9uHaL1zJ+1YqmHINTknVcW/s6spHR4F3TtzVIlC4mZeIYdse47oYgaR6VocD5CVS +ybY5Ys3jKT+gHowTOrqckuf9ZPhTK6LUx+EI/RPVmULBgKmDjtsj8DZcki6vpM3f +thuf9p9+W1WJ5VYhZWO6kWuO3XQ1KWUvuuKPRqAGRVsck9uQXTmIVIQK9ZYacyzy +y24WxdembFSHXTHZyyONcIVJ4qMUkn1p4RGEtieicqYVPtoe3MY0lIOVQDqM3Cen +wFtcuX3tsY00UcOXP+XiR5c5lr33bQZIeapl/KMQMET1V4REV220F05CryNWGDfq +ZmXdKI3MrNbwV0hUN8ePp/whX5L/Xhu0sHCfPDuvjTyINQTgUO1HOF2rqDUsuF65 +wjIYqr55gLpNZgWp2qpOKxaIFnqL4aizEHfjSQCnhnuIUuv5SigHi3g6/8OQv0uH +knb6Y1nOFEX5W4VbfTqtpROI2TtxaY+tqtZl6oK+utE0Vc850X8tGV4kia+6FT4p +rlTXfx3HiFAgsxEXP0ttTCejO+jbo7rDmTn1lWne1hiR0Q2ZtbN7kuH0KePeaDfs +SM45CyzEEWr5uVBDqyrVLczmLhDmjrMLYz7S9tLWptJOOlrVgXXnM1wWjq+aS3JO +E8Ul+agBT6AMzm/DXOPAvhxGhBqH9XsLUHhAmxQwOXMsOVMgQff5xY09YU6pbn+/ +JA6qLBBXuMKRF7MP4BDo3ZvpMO1PjDGoZoR8KbMd2uSdbO4ABAnxpg8obD1TPH5t +Iqa+WfQp/8rovEk9gmcFfPJ5Pa9D/t5v0txXkRREenGuDk41yRehDfEj7p5jybAP +4+01YQTt4d7ee/yWg3fZ1Ab3nxuXeDHbJvxGXttnj81prHbDYgOkgluEb4DjK86W +hZJXNZWhCOYnLz/ts+133cC80E6rm9I3gOXhZrSgW1z8k4eQhsKyPBDXKpsJOENQ +uPBpmtXUk9Jl8RUVOiuyzzlQcKA+4mvhzPYs3hXu/A8PoavY6JQr97sGgsac0BsT +ZHjTY2OAeEgInz0CMEiNQHsYIJlwHfokR1mVL/GwZMvBAmnMlBCrUeocKGMTo96G +fv29unx0grDQwKf0D3ZQNQcFF+7G0QBG48jLuflwd7cdCMeILc1b5M7q4Fxr0qwJ +4CGBnL2dEhpctiyLZH9uo9zQAdesVjIgulMMSXCtLDJX1edIMSMMr3io2VniU9iK +78vyGLOiFfxK83o409R9NXGDocV0NZyAFJhIms/qiodvrCBR89+kbWv9rp2Quu3R +AA7KwdPsXamOgo7cbrXFqgcw5Op9AU+uw3K18NP/DWAVB89Go+BkQwsXp5UW9bIF +CYeaxIA422jhJ25pxa03sOfS0J6j2l2bnpPd4BkUk/gOO69cCGLiIP6o5HMXyE7t +Eg+qukWDYGzOUgFZPjdFmxXMpBmBxAX6LfXSAojf7fwstdv6q0JS540ZxtLdRP9Y +nqij0nvGtDLXcPr2TmGaBXRBHr8MXFRuBmJXdA5qqJSa44Tvc+4ndNBPAXyPfTQO +c25A64v9wHALLRWlyBO3lynMy1xSVuBSRCMsHXoYc4ang4ZRSqL3y8GNnAGNOPCP +HGMxg8n2vtaaPSmeI9Xs8eguH7E4dasI4nZ7EULvuMnrUd/HakMTOmDw41utuZ24 +toly1NCNk9sq5HpfHF3ShZ3ktzcCFKuEPKGjb6jKQ6vWRI+kCgIHLJfiaPnBaZsk +2hn+EpkiKUS62a76NDzEq9sbLNIelOX6pEbClJEqytsROOoEDNToihY9ZhEh3vjN +WqQy/ipufAX/ivWpix+KStXt7bvGBc+kZbjIy49sI87pWQsvRX8kcFzFs1k5wUwC +ynyZNnv3/3QOndStOcq6tbvA0wS255GIPkELqETWExdCIbJnLsIeOD9e2X+Ld0Kb +S3VPjLsEMFaiB7umzA/yQRKqAqiuTd/AMf7kFHJOE5/aJdC3oYNQAdBW+/ABSqEE +NM+0XS+nhg9zKTz2hkPRV68C9IQjpHNKr2Qnv2WNbxdn+ZGCPHbGzRhEssuwT3cM +OJNBov2XnOTcjA9ILNg2NdhWv17LWlJKV+qEng6/BPcWQfjwS4TIBmVfAbj7qBTH +fG3VGc+EZrZ4mCXSKoJOasGSKW+5xC8EuHXTn3laBnUmqHrfTNl6ftAEPPWFuHYZ +i6vc+8dQL8EAPODFe/GcoTAi/zMFuGe6OfJ5GcUgIfnIR6amJp5R8j3UOtLTRTgv +J3u2HD/Uh7UOSi6PwTWlkht/mJ6iLvzB9I8Q3k6Xqy4uthAykEWlSIiQy2JCtBNU +i7fLYR2+pqz/BtEm3SN2zNCZ7nz04gwAxMnd/xQWKVT1Ob4vECVYFGdEgk8DXxlV +DbwcWM2ZY8dHgzwC39btIL5bc2mansNPAdRd6CTPoYCAKRxJuN79ySwJr1fbBINo +zOMhWBvMVx8anTuxB5u91+i5S3DAdaHtTIEWjUO6LxmpV8xCrRkZ6XMyqp2IArqB +6kRwYXQnrJsmfu9ANLvJVHRcwXgLQZzKmm2dLm066frsumIg5jhDcE9AqpTBuXNL +oniAX/TOzBkRH09nOn9817Do/kK7TnBsGGtjFHQkai8JbOAVNWZgWGUvNtuXFAnl +0xLrQHaSgd0Kj1kGWVyoyf/n8S9vCKvY7PLHCXWRp3dignITt2FYT7g/BJRPEXG2 +VBtzuOZy9+O3l888dEIvZo7PhB/jf9mam8yNMEEyUkScJRijrTSUwua7HUxbUVC1 +Hhl/FZfknSSuD2lHyEf/JUfWpx5rknOH8xsuUYZ07xd6ResVijCJLkZcY/Cykc6z +S0F6wJ+sgprI4S3UzU7ZTDufpH2jnCyXFB2pDVT3Y9wEObHWT7fP5dN6PzIyYsrC +/MPV5+ToGIKKBqwUD8yp2GOkruGOqA7FgB/H0NNOt8bEg/JTgJgNKuDKP9Kn3G5N +ATebkbUa4YoQdvP5DqZ3Pnzyjt2HZvzDKYSAV7Df9TqqzMLikSRL0azf/rbOmhcA +1uSVdQhy9rYeWfDVxv+fI9tCamIJ/Q8INPZKyMpkoWFmUGYNdiRPeEws4pg8CcnE +6IgfjC6z6paG65oCHHwgPJZFeLt38BvpT3wj5enmlDAJpGJAPFJICxP2I3V4SaLT +iRqH+Dho/wFhSbj+riH9kOxTgEJ7G6wQpyRSvfhbq1qb2bX6FBFzZvsL58Zz2FgL +8PkFGQF6Pmz43f81m+74rYpNCaif9Z1w3mC7OGdlNNgoeE/3CpXQ8ZvTe9pe5NHw +G9ZX+y0/tTv9aEb3B63atMQhOlBMjjI+52ZZ/uchwDHb87aDXf5iOLhFtdBvJyGp +waIj2P1HyYVpZlB9jTSm/sKr94z5jpOdx0hF29dgMuDqWoEiyEti8t+xGaRut3at +oVEkyPTp2d+MRyAkMcGo16209xqdjqUEJ7Uln2UNjBW5gHkmBCYSKml5I7IPFXNO +mPHovTHgutB/TKN1lyfJrdSkg3iAzpOqIbf87UOvuhPT/nHxrDRR654F42bsBCOV +7FuBxxnNQRthxv4n6jw5Aj764Xj0TkCcZeHxRh/sxpTaGTj1xvZ923sc+CRvPBxk +4rkJ3c0nvx4hOrgJnFH8ZY5EFD4tzWT7fRa0w1scpLbaNCo5DUayAqzWVSqVP5OV +8i5wWx159auyQhxmmlRvawVLtRePUhvXqdvcOWRQWfU+XLqCtGOFeWbKZND22GP9 +kgZ9U5RrjJjXuNYPHOUuNhaL8x2fOefBn8dujPAtZuyJ8BGkMUAsKC4xinrfjuv3 +vtxTAsR3t4JcQ61O7UuuEyvWk0UIxu83zOWI6kCbRBkX85qbMTBQFHCny+vt4cBD +DBhAyaPCqfdfM+aExf6BuBLtSOW4XaPJTjBHoCd6uQd9FqQ68iN062O5Wk9C+61K +5JBKCQVA9akqH9nOiN/KIUoHSm/fQhJ64emSVukYGsA50UgNmcCMh5g61Xs+dx0f +gEYJEdM3UnoYpo313NTrT0nz9DlosLoaEHnuqSdEV49sge2GqCaEYnPt6klrK72C +k7IT2hGe7eELkD7am9oYxTMfgngIJkhBftflUJ1UdMOmNbT3HHGBxbbzKqLn1w/q +Vi6p8Fe4eOLstQ7JPmLuqSZ3m8Ky3B02B8KR2W4IyH9xo0pW5KWZyqP3KVdOKR+X +ujZ+QFIFMmejM0E8ob7572YsWWnTVgdmbsd3npzT8T5HxkZPxRCGCY36XNDsjNho +IObwoWXZj+FWD28PYDQu0M9c5SZNXVTEEX1CGcYKQxo2r7QEEGtvNtIjznZ5ILt/ +E8zwl7ZNWAbOrIioJyrXiJlLfXBiSZVU9phul3NpcnIg7WMjHL2aRHJjHGe4x3QP +icgYH4gBhPdzrmRxDMMe+/bSPsTNI4UdgdZADoovcj+oWX1lSrdDEc9FKy2mhBTv +/9jF0cdDw3ZSGKNFJFDECyx3rQn6hg83203ySpvyiBcZDdjNB699e4V9AxOLTuxt +ivDLtEVEJ6bhlWbm04mgBHMOqi5bjFbiKOxKdkOzU6ty2YPhznrWGZ4r8PV0XfjX +m7EXKEGZyH59PCrztyFEnBwylbqkrAyqLmEiqdy9DxKZ3iAOg0bEWyfzMDhXJh6z +wY7lzs381eoA/b69VuHWG82uVeww+GMrUpdzuhWTSzYsvC9ASDgR5uU1/iU9HeFk +vG26M5hD3RYROPvnGyOnoe4LLpP94hP108TSGS8cCvGmnhf4W47IWr4rzSAvO3Eo +2trqjEnfzrMV3CEx+s/KtI7jvt1ODHSv6s76AcO+RnoZjIi1GznWhSB+0U+V0hkR +P9Ghms/DO04HkQ8FKkkjSKvtlIW7tNqmbSSrTVbG1iJx1GtZpp4V5SXO3H3Q/4wj +i2Yt2JgXuFu+5gNJOb5d+j7aiQRo1Lk0OUdNZy/Wf1LUriikGFEx7dBntCfIl0JW +Fop03L7nTMlxprYqq1jq/pNzUGISCkEmbD93iQ3AhR1bJubuZfA64L8o8mnmWxGN +/ZwhYfGlmkg5nGg/k+L459SYYWZJWP6wDRzX0uUtofi9u2F9KxlG+UGU7l3rFSt9 +tzua1wVtUtAKvKofb+d8eb1hffkJe8vaCyVbLhs4HB2OaEdrkdX1LsIX6/qFi3W4 +tQrc8DSwJimeGzh3OAumrVGDFf1Bl9Snd+0+aMq0UPwxScudJm+sjDovgjnltn08 +9WiDX9IS4ukBAM++mZTeT12TrbLl3NTQ973qxOguzcMND2ZJ5WLsP35/IQLGXpC/ +dd35nWCD1obHOJbL9GfFy3943zxVaMYhpS9BQe5WcwFan++xBR06fOG8D2NS6hLT +RPBcvS6tslT3kDzlgjvinliv7VJQ4+l95fKfbrAoYaBfH2Xtn+XIq87Lebnep9j2 +3yIq0HEWnvT1mkkxJFkdAdbbbAV3Hvih9GHrRYlXU84VoNf5lQLPMloBTe1nGOlp +rxJtcX8Mozs81XQScPpRp3uQbkQl8JpGMZqwaC7S6tYsKM+8GA7MUzIWR1bItlrE +nQS7ZVer8plxo+tDO08VEa2yxJkcN47ObyaJyFP6dy69N0HNEx86Dn+SYy3hkqGX +DpGe3jH7AyIBIdZ0ulLQE5Y5VK3T7IWQ7HnywfVmOjhL0SGegPPV99mRK12g28In +flUWWH0ThCo48b7RQut3h4dYKwd3O4wTYlLQocBx2uArfhUDL2bDtB4bDDq70V0= +-----END CERTIFICATE----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-128s_pk.pem b/tests/pem/openssl_SLH-DSA-SHAKE-128s_pk.pem new file mode 100644 index 000000000..33c5aea74 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-128s_pk.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MDAwCwYJYIZIAWUDBAMaAyEA8BnVeEF7x81JDltLtrpTDXC3ld43Kug7uDDYhzpH +5TM= +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-128s_sk.pem b/tests/pem/openssl_SLH-DSA-SHAKE-128s_sk.pem new file mode 100644 index 000000000..d5f4363d3 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-128s_sk.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MFICAQAwCwYJYIZIAWUDBAMaBEB7rogexDBq0MrVndGhZM9Ip/DHPf3BMdYs9eML +zm2TkPAZ1XhBe8fNSQ5bS7a6Uw1wt5XeNyroO7gw2Ic6R+Uz +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-128s_x509.pem b/tests/pem/openssl_SLH-DSA-SHAKE-128s_x509.pem new file mode 100644 index 000000000..1ef402308 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-128s_x509.pem @@ -0,0 +1,171 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-192f_pk.pem b/tests/pem/openssl_SLH-DSA-SHAKE-192f_pk.pem new file mode 100644 index 000000000..e3f1efb56 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-192f_pk.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEAwCwYJYIZIAWUDBAMdAzEASaCrU5yiL0A/0qAg5DZqoqJwlTfYvfH074NLp8tE +ib7jde0ZqQL2DwQe5IdUFRfI +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-192f_sk.pem b/tests/pem/openssl_SLH-DSA-SHAKE-192f_sk.pem new file mode 100644 index 000000000..126800e10 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-192f_sk.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MHICAQAwCwYJYIZIAWUDBAMdBGAfLiGWaHJHuK7cRkilfIq7ElzRSb2p7Xd2oCxc +SSbC4BOc2hl7LoHHV8U24okZ5lxJoKtTnKIvQD/SoCDkNmqionCVN9i98fTvg0un +y0SJvuN17RmpAvYPBB7kh1QVF8g= +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-192f_x509.pem b/tests/pem/openssl_SLH-DSA-SHAKE-192f_x509.pem new file mode 100644 index 000000000..30382254c --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-192f_x509.pem @@ -0,0 +1,751 @@ +-----BEGIN CERTIFICATE----- +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 +grptOIIa1c2OoAFULng9 +-----END CERTIFICATE----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-192s_pk.pem b/tests/pem/openssl_SLH-DSA-SHAKE-192s_pk.pem new file mode 100644 index 000000000..4083607b6 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-192s_pk.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEAwCwYJYIZIAWUDBAMcAzEA+kg+Uy3W0yajj+T92AVw1/0Hh2RHXP4LhkfBLyeL +UIzxIfUFfvwu+a/kPS3Ke0Ru +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-192s_sk.pem b/tests/pem/openssl_SLH-DSA-SHAKE-192s_sk.pem new file mode 100644 index 000000000..2bc39afa6 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-192s_sk.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MHICAQAwCwYJYIZIAWUDBAMcBGCPViyYzFgskhv80UvTD6F4foinF/Z7CqPbHjI7 +oEDz+w8HDewZ3rddSoqr+52t1T76SD5TLdbTJqOP5P3YBXDX/QeHZEdc/guGR8Ev +J4tQjPEh9QV+/C75r+Q9Lcp7RG4= +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-192s_x509.pem b/tests/pem/openssl_SLH-DSA-SHAKE-192s_x509.pem new file mode 100644 index 000000000..c4d9ebce5 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-192s_x509.pem @@ -0,0 +1,346 @@ +-----BEGIN CERTIFICATE----- +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 +rZqLxMITFhoQbSpIo12q +-----END CERTIFICATE----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-256f_pk.pem b/tests/pem/openssl_SLH-DSA-SHAKE-256f_pk.pem new file mode 100644 index 000000000..358a1c7e2 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-256f_pk.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFAwCwYJYIZIAWUDBAMfA0EAjTMCf7dSy7kI47DnDyGGhevesZO2WAm/fCXO1ka7 +NC8qMaaNBATfQfXJu9n1M5r6+diiqzPOI8QziN8FxU1oow== +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-256f_sk.pem b/tests/pem/openssl_SLH-DSA-SHAKE-256f_sk.pem new file mode 100644 index 000000000..39a1fe59b --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-256f_sk.pem @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIGTAgEAMAsGCWCGSAFlAwQDHwSBgMVZdsa0IQvt7lOKPYtawZ7J35zp3zIgWQJW +ByhZ6BVrZmBSdkTD7jqSd8ErsTyiF0uwimICgrpGbRhMvNptbdKNMwJ/t1LLuQjj +sOcPIYaF696xk7ZYCb98Jc7WRrs0Lyoxpo0EBN9B9cm72fUzmvr52KKrM84jxDOI +3wXFTWij +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-256f_x509.pem b/tests/pem/openssl_SLH-DSA-SHAKE-256f_x509.pem new file mode 100644 index 000000000..2549bb0ba --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-256f_x509.pem @@ -0,0 +1,1047 @@ +-----BEGIN CERTIFICATE----- +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 +RQiRkVSEidG855BHxoJD +-----END CERTIFICATE----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-256s_pk.pem b/tests/pem/openssl_SLH-DSA-SHAKE-256s_pk.pem new file mode 100644 index 000000000..5a378186a --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-256s_pk.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFAwCwYJYIZIAWUDBAMeA0EAHOI8wNemjExTa9JIB1MIM3BnxVWHGLj8iGKNqvgx +x0aMwmkku2PtPCiH1LSE+/yS7/LjZW8yfdIHHcAM7N6O5Q== +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-256s_sk.pem b/tests/pem/openssl_SLH-DSA-SHAKE-256s_sk.pem new file mode 100644 index 000000000..9fb5847b3 --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-256s_sk.pem @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIGTAgEAMAsGCWCGSAFlAwQDHgSBgN1wX3/vz/MUGwgQO7WFRur3rE1LPirFjDje +e0dVJXjN/sBEfELWkUzx7jo/VtsWkwyyKhjtYQFlAF7hiGK4R74c4jzA16aMTFNr +0kgHUwgzcGfFVYcYuPyIYo2q+DHHRozCaSS7Y+08KIfUtIT7/JLv8uNlbzJ90gcd +wAzs3o7l +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_SLH-DSA-SHAKE-256s_x509.pem b/tests/pem/openssl_SLH-DSA-SHAKE-256s_x509.pem new file mode 100644 index 000000000..5e966d32c --- /dev/null +++ b/tests/pem/openssl_SLH-DSA-SHAKE-256s_x509.pem @@ -0,0 +1,629 @@ +-----BEGIN CERTIFICATE----- +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 +gYNsrbXSmSoHL0+mtn13 +-----END CERTIFICATE----- diff --git a/tests/pem/pkcs/openssl_ML-DSA-44_sk.pk8 b/tests/pem/pkcs/openssl_ML-DSA-44_sk.pk8 new file mode 100644 index 000000000..69c08c8c9 --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-DSA-44_sk.pk8 @@ -0,0 +1,57 @@ +-----BEGIN PRIVATE KEY----- +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 +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-DSA-44_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_ML-DSA-44_sk_pbes1.pk8 new file mode 100644 index 000000000..8a4ecae78 --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-DSA-44_sk_pbes1.pk8 @@ -0,0 +1,58 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-DSA-44_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_ML-DSA-44_sk_pbes2.pk8 new file mode 100644 index 000000000..2825d9a69 --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-DSA-44_sk_pbes2.pk8 @@ -0,0 +1,60 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +cMTjqJv2LXrC +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-DSA-65_sk.pk8 b/tests/pem/pkcs/openssl_ML-DSA-65_sk.pk8 new file mode 100644 index 000000000..79d16aa83 --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-DSA-65_sk.pk8 @@ -0,0 +1,88 @@ +-----BEGIN PRIVATE KEY----- +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 +YNHz506CNXEWxqm0vDoPx0l/ +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-DSA-65_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_ML-DSA-65_sk_pbes1.pk8 new file mode 100644 index 000000000..12225adc6 --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-DSA-65_sk_pbes1.pk8 @@ -0,0 +1,89 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +X7ZLxOsZ4CKWZzXxSiI= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-DSA-65_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_ML-DSA-65_sk_pbes2.pk8 new file mode 100644 index 000000000..5f8b3418a --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-DSA-65_sk_pbes2.pk8 @@ -0,0 +1,90 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-DSA-87_sk.pk8 b/tests/pem/pkcs/openssl_ML-DSA-87_sk.pk8 new file mode 100644 index 000000000..b59bef518 --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-DSA-87_sk.pk8 @@ -0,0 +1,106 @@ +-----BEGIN PRIVATE KEY----- +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 +0WLBwubkJ64Ilb/qv20O9j1X +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-DSA-87_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_ML-DSA-87_sk_pbes1.pk8 new file mode 100644 index 000000000..e819bd22d --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-DSA-87_sk_pbes1.pk8 @@ -0,0 +1,107 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +Hym9hLu6V59RWgXde4M= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-DSA-87_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_ML-DSA-87_sk_pbes2.pk8 new file mode 100644 index 000000000..4ca048c00 --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-DSA-87_sk_pbes2.pk8 @@ -0,0 +1,108 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIT1TBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQlyZLdHMZz2Zn7zqX +k45isAICCAAwDAYIKoZIhvcNAgsFADAdBglghkgBZQMEASoEEHRdYWobYuXmi44l +SZMVmbgEghNwVK39TmWRgrXKi/o9uNzo3ZUzYPUuTmo+S0l7f0DhpVtdJ/0gGNyy +qRW8Z6RWuqQDlFC+HtcMDGTwfNhG9PWbiFudg4OmUT2A1ZPbum4XdZ5OcGBNbV4m +vo9IuMJR2rPMydNYwr10ZVQFxL2Dwvk+nbh4BhfS/UyapYKlQna+wmaOOgtEjN7A +m4Y8hYHJBog3X52IkOF/aSUzX9q9W82qHbu/Vqu+W9Ph8ZeIe+fUGDKkPJ9BMjDt +6HVQtTX1mVURK/y0LNapTRR1F9yZZYtZlrKmifgWhhgbBL2yBFIo2NN8omU1MLtA +qkr4QJKHQYP+CczMAunbmwglqLr+RvdjCv47UQGX80gAHF9TMtaZ1Imc0kOK6q5k +cOHJVGpDsg4cZ9tUZz1dRc00E37cM3cc9WT1HFmHAwBlREF385LDwRZDA61Xi6Pf +34LNl84GZv/5yrBes0/VY/wejmQICF2fMNw6UVhsuCTuiSvstfiB/+L+rTnfiF2k +n2YCMISkw0KWWPb4FHz6sNHjq4vE/RcppghqH3ybLxAmHKzOQSdr/pOllODZGADP +AgWGSLduFZV7vjrjdj7MwXKQFSgTB+prWN2T7xd41E1iyPxE3rF1K3MvDbCkegQL +f56pUeJllbRPQIPk9Ml8XXI8+Xw6IZBxg9s5/U67budxBIKU9crj/CCGmeP6gtIV +yr5wGEV+ScZPSzsnpPTlpYKVODpgmjjPYQSGuloqR3W+k3S4Tpuu7ofQ7ZwjUtFy +F4LqovfkC0EfqeFKPsDHmr/dBl8/XN9W3XbrFwCRalgpqeVle/EcaGJohDOCML/V +JPlrEyzh2iov8Y7H8MNZyKKs701J4bb4cBkBr3FRQPQoEmZzG3SNFi0gx0kySFlt +fFs4BTRxSWboD4z8/c+AwDw2eUsP6Hh69aw5pumP9wSZOPnZBxi40/BTP/vcFLQx +R3L8aHvaC6nuSUvQZU02Pd5asHeniGT8GFqUplbj/YajL3HNXthYdoepHpw7gg7A +W7Orgqvf4XBSaHu45aujR1iMSz/dgVAaS987WkutpBoE4pqftRZUBSCZXnFJCLCl +83g5/+eKCQ5DVNryyAtcDri/yU/PJM+wYVL7JyABNuRxITWObTmy0GGWsEKPntBj +CnaGQtGzSvhXocy4n7PXMkQHoLXIjld+G9SCBgx7+2LX0Ils/JjgS3/ive9lWgLV +t74fjkCncZ8wIFCKoSjuSUVnzXodoLXm/Np9wM9tJ4JTwKMRgNhSORhHqm5LP3YC +ssi8JXA1/9mpjtcqFXOOrgPvAppom3xQzYT9NJpxISSayxOvqC4EAglnIsZroo0G +u1LkZW+AMgkSxpxCz2+fratjja8HBxvtF5AIyUbA9XZ0AgcnefCpISdmhfQuSHRB +L11HhmBGDO9iJnl4dhMU7a0kzPhn4wq/aurfGrfcW93R1tJhof8mkT8jwdhdoySr +Va7nkGpSGvkfGjNya7b4R0k5SKiSbWbWfVOKhWbxRjXTxPou9AZi+3wx1tQL1xM0 +YXfPBZKswLDyqkJDRhhk91yn9rfSTAci04TW1Mqu7m2/HOL4bIRPeWghyrEfMeet +fPCUj6TCf2qv/vxIpjGKCgLpAGCEIdyaGWKu7WgdphxQYSMSDRNO2GwUxrz8n2Ut +YF5Xl0Li6ZhiP/SjcTu75EGap5TNQzFSk8V7dKhjXfCC2SfQs2kQ8jQSun/+fwGy +IqUv+NQFFeKlJ6xYRnR4PQkmdPHhEebiYmoLRqmUbxlzZ6X2MX32zPjziHTSYEEi +vVxPUWzNxZwtafKN+C9FO9VsNaK8W1IeJ7S7kN2Dllc4/Uf6hBTRSXJsbVOSdt3i +G/C7E7LMM8csrTd+ZFc2oCdpqrWMihat2BL3vW63sEFoTpKQfN6Qssutk1Jdv5vM +Nq0uaVBUkiY0yAihezaITQrdzCKvFKFTcFM6ZzoO9P1MZ1bMsbeLimPvAzMoOnkz +AoOw2lrmZz0to3MZUM7mjpkEO/26m+x1PMmsHAu6R5UQbeB61AAPRhtxMgKAHP9B +Okb8ap4IVFHWlA1/zoIq/grCep43P+TfBSHfmaeMKEsg66zK9WmKSi7o1ej1jAtC +OnH0eOZtx9kgCUddy81lSV6JjAS3ce2o5KUZS4APfhxjgmDMzbNtcoPJXEszPrrU +StxjVLLoRfesnl+civevk7uGqxyZp+DCW9bb4YdSzfGDpMJMAyiKUDnffBqx/iJU +OUnH70/KZ4yRFTjJtx9+V95crkmwF1tcs++CX0Qf+/s4z3qhH9Fxvm3POoCwPaUw +l4VJeffR1QqGBrq0us+mArmWDzLxyaFDOvMZJaxm1YS+gIpxMKezjpYZvXQgGmkR +CAPLeJVeCNBHB8nnl4ILpurrCZD9BLsbgeDrtTEJMKQUDaPxj0ep71qNSS1IjLEG +9U8NkHAN37tmVHfTJgL8xEfP51QggsIJ1lpEPM+NceAdKef8wYBdM/BwZFxn/G2q +uIQukohYPFpBSMK4y51+3hyU9SHPxqiVGbY/GFmVWiOV8F9PT6ei/X35ZXO94rFv +6evvXYyOWttUm+tx/LlOiqClgvHqt9iZd1dfV9IKL9TovC3LK4JdAlG49EZv+POK +XypQeDC+S3rhTeQ4mdwDMTnN9tnrigEaGy7ammpV8ySnSOYpzTCtZUe9Fg+878y5 +ZQS64MUjz9198WJteHBh2pijeyNf3H1Cakmcuj+SMJSaAzVvfKtaxAyCzg2sj4sr +UL9cD8kVqiHpY+cKqV+wYFi1JO5/+jYvOHSKR/rqwPAYTb+zXx01Ds8C6uul9Eb8 +4aF+ZjldJBiIObXbBs6KDuP4wNCU99B7jUXTc634VdfjCzDjQqrugLF7X8EsJQkL +MF/0aK+vwpNRGTRnaN488lqaSqCIKYXTRRVXwUuCdgzyp8V/O+TTd1RafnojtnLt +YxuErdPBbXmwd88goItVAh0AD2trWmq5qAwTdRALq1yDhij22Wflyz6Nn77Du41q +k7F3hhQVShFCws6TzMDtg51aOghtAhhlcUuK9ai6nsTS5WPlvmLlS7MtF10cHafR +xLBfwXsZDwvhXKIjQoYDiVn9w3E3Ax8HmB2pgRpR8mLyzxq4EFLMtQsUfwV7DyvY +tFazNlpcNNguzwkV2c3Mrls4xIguU/kIdF3fvf9Cd+fxEpCUWkAJeL3FlmTsUmK1 +uoI0szTcIXVGoqHktIhmJ41fkxKXyLkiY346gMQj3eN7LZm55beMLFRtWf1/WyWv +3KJt4t4701zR5YQ+D52VdqnDI1k+zwZmhoRjdRgVPHKYc/CwkURrnmuK4OMN9m12 +i5HrzaxFyY+YwlFdfaejtlgO4bKb6QAtPjD1LmcNu/vPFSSPpaBZoHNtSylyPmq/ +vAyAT+5C25Al541mk65BCL3s5+fwGIriZtWTLmN3oTvfq41WeAm/06w9pBC07qUt +/MEqvi8ZRtIgc3G5HnWuIbizFR/V1TipKCq2FNVtE195E4JxL8dqbh6S8fGXgvQU +itTIkon850qb4B+EfsyCYnRwwRZrljZ3uRY8e6McnfRN4SKE33+6uk5Ch+JWmLdO ++c2pgrdrrU2nwmbD93Rkhc2T2I/8xIjosLcyVa0miKKjhA54K2UZC6tlgps6hgOm +SzGYDIJRkyG1NKzNnpvnch+Ol3Z0vrMENLPeE5BT3f8BTbA8xhaAfP+c6Jx2N5jg +07uWrdAYigPVj3TdXH748YnqaTctLenEIffZO5LfpQN5vleB5OFnIWpFHNFiCUNh +foyFICXp9+tFVOOBo6GyHyJ5R/YV1j29IhCiG4VJesJnQSVOFNSMPzqXYHqeQjG8 +JwhQH2tbymbKYL8vDilnv0S2H2t62lHWXjtvUDAOmBgKFZXmEbM4KNIHFaBwLnmn +fv0JdTJC/rsbl/sGx+mgUWvDPPKvatFo4VnaFx6V1QdghGf1REPsCPQ7GxYbfjXM +3mQQV+ZIGbRKqz4eQenDlOe/wjCzZsWLbK6V7wNQ/2HpucHsayvm6lATD+DEUJPK +8pmNXWMIr3OhmWzlmKTZsDWV5yoQWsQOdbuGVlMPuYUmNOPvR18ilx3eqOPlL4t7 +nBiUf/v3ZvT/41dGq3U9TvWz1aPCYeyQWzHVyHmZ4ihr/+oYTUW7Mj1/pmPUv8cW +zd2djDXCHFeReWygivTVoK8sxlFwld5S47uA1ZV6PzxtCwIGqx95Ye+HNmqpO9gk +WVnOkZemmYXNbxXrg+2rAZfUQmSM1ZLkiFzr1hAqfl8QU5cs8nc3iQeYdLs4NogQ +hqDNObo+oUg5OGa5WAnBy7B/H7kQdqnSYQyGIDlGcG2uAmBq3uTpiqdBqiff39Ee +GaLGDQ8HK82VF69PgiLrqMz7RrCfz/5ryxaS8d5aUOg9CERbLtgbZjP6lZ8OKzD6 +/E+mL5+/WWUpMzHWUMkBH3NyjVNZ0DiIT9YOYMwCV2NwR0DZ4TJS9mwGsqINYhOX +BUpr3p70dLcnNWo5CC7Q2jrGEHw5cdMEaoWap+r93OK+ow53Fi4mk8xKG0kG61yD +tS+V08dbtYK05HuvVWCt0nqh5ifh1n2/CGHm0eWm0ckkxC/EraS1xXQKllZlEpZ3 +mgNBigx1oMdafvBP0vccybCHzCExkQQjmIGagmiRBLxemxX6fBHxNjsVq+IvmS5D +SvRtxYFkZB0srWp2NhgkhBA8KJDx4jrSBU2RfLtb26yUqub9Jmqs2qiDduDHQjer +2Jeh25WoybnWvooHU6Up0y5V0/cc8HKur6cS7flOXrJj7x3fdf/429Kj6XNQpmET +wVe9Z5vBwQfbozdWdQmcVjW3epH5NcnjhUMtV9ZRhYvxacwBuJaZ+5isHfcu2+Gc +L2mquAnChpaWErswJrO8nzPL1TddNRqzuNDWfvnSGY6D+mqb9tBaZ6zVFErHdKmx +4gs/Lh8N7Tzg5Lws8N9Jd7AqHYYWuipoilzPUkuDG6rX6//XzSssgYODRJhQbBl2 +L3lSOXUL2mNuYbWsFj5KSHlQu+Xqt6IXJ4nXp8erkBFggvi3H2Y400K/EIq54+h7 +dDgi2LtXa8pK8BCPb1eQ040qZqW1LSTF65BXo82TH2XwG6qGc3dcYLZX/HOpR1oM +0X4Z7FAIKJU6vz6PxhHU0wSySyzPzVgpFHZs02qFq0wkwd1HCL7Fuc/GCnWnNblt +WYNfwlY/5HNuBf+9qh6c1upHQF+nuWc0TLK6vepwmFuT+Aqyw6w+vrfFO3t36Y6D +nZJq1uk90QqxBG4EiGjyH06JrQc7KKxqFQ3Tm6CXrOjaUPGbB9Er/ZS2cMQsfuyv +2ocNjrZxMO0L6trCYcaOo/689kOUd9AkqsoRP2ajjdR4pN+hV0A1bqi+8Vv2kQKR +JyMB6MnvFCqAftvHiR31qyJB6p5GATb9MNzwwwqz0p3hVD9jpl8Id8EKbmWnNExK +NPCCYweFh6UpOduGKvomyJJB0omSRrZkOgPOYudrCILZjssTKGQfk5xWlPdUBUlD +DTMgcImJ69DSZ4RC2vG5dw+RUeWYVnznYycamvWNy9T77KRtul3ESEscP1pQZLQf +VypK/YhxmKp8ICdPUxPsx/GnuelI8GcGu4zDwvaw8fTWEiG4idyaNlUZpmDFqvrd +vJ+m7rvVEV+Sl5Z5SnyBORIETs9yUKie8eKFvy9VFstzDAJ1V80o6Q0b8lA8138i +1ggc96kuz/14VbK/tM+hJDw/v/M7dda+2cS4V57D5tsSdyY3QL4pjJEolf7WAB3y +nT8RP7lrMMQSrxRoaMNAGW8mYrQQptVLta+OM6U48SBwuK52q2iKV8wqrRPpdc/q +5AH4f+iFpJt2HolYcON4eaeYDItQzUcLNCdH7t54ov0oMY8Zel4mYpTQvBcotszE +71Mdmr7ijEqbmGOVWPjw1XivG2pUqe6U/22wuAijPCoIQ2U3oAV7cQD1ZF+fNptP +fkizdzPtBGz8wf46PFgiaeQJZ32UEisVJQwK/RK4SWWfqAHj1Yu54UjxC97A5U9Y +pJhuK8/NiYnv6A6/UXAQpwu5ILVZw3W3J4/AYyYPC0LU838iQy2YbPVN+FkZaHZ8 +jCwxoWZeykI2ZkdukPudKawLD0EDE4yn7zBdh/0uS+cNpxilytsjFPhh4mK6EGqj +Ts1AClh/CTFFNtzh8soApLbdX/l5Eff+kJvFD+lLstmKWjAbNjBb7qQ3E3HfrGoF +9UlRxqvg1L+41NMh/SdgMkbpPccvxo7r4WjxzeS948P2h6MhTWL7fV5T9Vf1xDjR +nfG6qffpcrLS8crTVHBvO/6+4p2uNkmbfzFE4FqLoqgpNUYbmByLJuXgBBcze3zM +DPJw57KsKymT/7W3Y8Ch2tJzJsitSRe02m2yk7tonXTMd0prv4B2K6uyza/vFnPX +pRPUneDvk1Q5MlX8PmBzBXGLVS7HiNY+L7D1AE6R991gEXX1fLUUPkeiJ9tEGzP2 +WNrCUyKy9FyqddX4NACCR/sfskAtMcgPwFR8tKUGdacyh/byGHfb1j7p6WrLyQaK +eguop433IBSsKwKA4XNLhTbH7X4RlAWzRLRTu+b15iMOdStApLNtnETUqDxNWsaU +5u3YoKQB+0Wy7WcDCl7zwggRXO6TqsL8ZRCFde6k2gdZGZDVLmgIzc8= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-KEM-1024_sk.pk8 b/tests/pem/pkcs/openssl_ML-KEM-1024_sk.pk8 new file mode 100644 index 000000000..565883d0d --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-KEM-1024_sk.pk8 @@ -0,0 +1,71 @@ +-----BEGIN PRIVATE KEY----- +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 +nos= +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-KEM-1024_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_ML-KEM-1024_sk_pbes1.pk8 new file mode 100644 index 000000000..f2885a4f0 --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-KEM-1024_sk_pbes1.pk8 @@ -0,0 +1,71 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-KEM-1024_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_ML-KEM-1024_sk_pbes2.pk8 new file mode 100644 index 000000000..750d9945c --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-KEM-1024_sk_pbes2.pk8 @@ -0,0 +1,73 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +PXtYMbm4fQUNJGf9J7IoFDk4NZ2/10ojzA== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-KEM-512_sk.pk8 b/tests/pem/pkcs/openssl_ML-KEM-512_sk.pk8 new file mode 100644 index 000000000..a88b1918b --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-KEM-512_sk.pk8 @@ -0,0 +1,39 @@ +-----BEGIN PRIVATE KEY----- +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 +kXk= +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-KEM-512_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_ML-KEM-512_sk_pbes1.pk8 new file mode 100644 index 000000000..7f3646465 --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-KEM-512_sk_pbes1.pk8 @@ -0,0 +1,39 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-KEM-512_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_ML-KEM-512_sk_pbes2.pk8 new file mode 100644 index 000000000..e6c3b006e --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-KEM-512_sk_pbes2.pk8 @@ -0,0 +1,41 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +KMz7bJ4dJ5mfexRG2AwIugCWK3NHezDspg== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-KEM-768_sk.pk8 b/tests/pem/pkcs/openssl_ML-KEM-768_sk.pk8 new file mode 100644 index 000000000..8425ba73f --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-KEM-768_sk.pk8 @@ -0,0 +1,55 @@ +-----BEGIN PRIVATE KEY----- +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 +4KA= +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-KEM-768_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_ML-KEM-768_sk_pbes1.pk8 new file mode 100644 index 000000000..52fc7f7f3 --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-KEM-768_sk_pbes1.pk8 @@ -0,0 +1,55 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_ML-KEM-768_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_ML-KEM-768_sk_pbes2.pk8 new file mode 100644 index 000000000..3830720e0 --- /dev/null +++ b/tests/pem/pkcs/openssl_ML-KEM-768_sk_pbes2.pk8 @@ -0,0 +1,57 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +zVbnoCF6TO1Bb1hx4FcWxdsPK/nD/9svAQ== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128f_sk.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128f_sk.pk8 new file mode 100644 index 000000000..aa88ac0cb --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128f_sk.pk8 @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MFICAQAwCwYJYIZIAWUDBAMVBEA1lg4CCurnTC94IstEyqr2rle53arfbjKJhKZs +FBn2oNEbT6zRv6Uo/pR/l2JEDHz2Hyrrpwq9H6ubkZxr+Ejl +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128f_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128f_sk_pbes1.pk8 new file mode 100644 index 000000000..9002ed483 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128f_sk_pbes1.pk8 @@ -0,0 +1,5 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MHgwHAYKKoZIhvcNAQwBAzAOBAj++dEHcnBKBAICCAAEWCq2kNbLseH2me2NGcC+ +3JjjSTczUCulo20FRsMgsCW+g99LelnNNJQUdlugkerPKtcn+yMdDrTTDtleBEkG +AE6RXDwii3TcuyrW2HWo3LJ8OVQ9IKN46ow= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128f_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128f_sk_pbes2.pk8 new file mode 100644 index 000000000..119a85111 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128f_sk_pbes2.pk8 @@ -0,0 +1,7 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHDMF8GCSqGSIb3DQEFDTBSMDEGCSqGSIb3DQEFDDAkBBAZGxWFuIRd07ozc9My +eZmDAgIIADAMBggqhkiG9w0CCwUAMB0GCWCGSAFlAwQBKgQQsgYXiEdGI/JEYL5r +ibhfrQRg2d+7RiancBu6HT4Hr/r7F5gN94wIskMfHS/efjKIaCYtUxhkrkxNts8h +27SF2EsrvVlPl7N5KK+Tt7hGkvd87uoMNtSuPWEGh/+ZrRD3Z4NSycXskmh9OMKD +B8er0iNx +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128s_sk.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128s_sk.pk8 new file mode 100644 index 000000000..23f609b66 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128s_sk.pk8 @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MFICAQAwCwYJYIZIAWUDBAMUBEBgZT7mw3+QfGFarrsdPPcuUeqzs1MGILndoOXP +FLpS8bnjZEpVCFHL9mHAy9Wr0ob+g6/S/mGC0lQ7t7r29ScJ +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128s_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128s_sk_pbes1.pk8 new file mode 100644 index 000000000..44e43b6f5 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128s_sk_pbes1.pk8 @@ -0,0 +1,5 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MHgwHAYKKoZIhvcNAQwBAzAOBAgzvdh7GJl/XwICCAAEWCsJtY6IDvr7+EbL4HUK +P+B5JW9MYTNhsxeN7LrKME+NR3SzUM0LxQCtGmhZ1l+3oUTYRYCgE1pXBZYsd8BS +RMd52Wsx5oZkJAGOj8Xz/+06/GTKPlrxZmk= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128s_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128s_sk_pbes2.pk8 new file mode 100644 index 000000000..b5d8600aa --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-128s_sk_pbes2.pk8 @@ -0,0 +1,7 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHDMF8GCSqGSIb3DQEFDTBSMDEGCSqGSIb3DQEFDDAkBBDHnEddiI/4RDeaL8DA +RrzYAgIIADAMBggqhkiG9w0CCwUAMB0GCWCGSAFlAwQBKgQQ1QhOMCj49KNM+vGa +nCMnWARgX9fEHnS958lxH6y/FfEO2wOLEpovjayysIbe29dHuZ6wmnUW5qKr0/Cn +Vbd2t4HWf1A4aaBy6EG4deY69fC2jilYkyiSb2sRCQRNo5uG2wfTju2og9UkMviY +rD38gLQF +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192f_sk.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192f_sk.pk8 new file mode 100644 index 000000000..0d60b8fa7 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192f_sk.pk8 @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MHICAQAwCwYJYIZIAWUDBAMXBGBAEsQTugRaD9VO7wExjzcYXO4HdV3cwLSMLV/m +H3ldQUFbG4efpVdp2evkUlke0zXbORsAYUxhSCNOeKr3Acc62Q00zL+y3humPtzO +Tf6lIuF/T8G+J2ecJvDM6T5HLiI= +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192f_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192f_sk_pbes1.pk8 new file mode 100644 index 000000000..d65d3e1b3 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192f_sk_pbes1.pk8 @@ -0,0 +1,6 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIGYMBwGCiqGSIb3DQEMAQMwDgQII1Q+Q8nARIkCAggABHjH/kCXtMRHh2ylKQVa +ATqZSUKtzsS7h+bzN4sVGF+oyjqG/MtOb335/rEskHWov6GM4GGS+hzn34FD2n+H +5GloJOYC8ZsTbsHaKfW3je1ooHdxd856tvCamEddQfnPzHpkLgJroAjKIXKky9Tq +RC6suVu3iCULhdo= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192f_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192f_sk_pbes2.pk8 new file mode 100644 index 000000000..d0a7db46f --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192f_sk_pbes2.pk8 @@ -0,0 +1,7 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHkMF8GCSqGSIb3DQEFDTBSMDEGCSqGSIb3DQEFDDAkBBBmCNaJv/qoQ78ts3JT +gc80AgIIADAMBggqhkiG9w0CCwUAMB0GCWCGSAFlAwQBKgQQC0z61JY4lMBopXDh +5d3QbQSBgMGbi19uU0rfg71XuIpVDwfrSiRIq5fKP5Xa4oziRnCelsQxXgRiTMB+ +UoqECqOdVUMbXbvM/wcTVY8RY+Yg9/D9AkZSLTMTWLE4hw2qnwXLOHIDPip3D0Ov +hURnTWGVsLi+FeyIXk4kAOWcr4rYFgzIGwqU0x0o9gnOnooqXRU7 +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192s_sk.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192s_sk.pk8 new file mode 100644 index 000000000..3c5bd0f7b --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192s_sk.pk8 @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MHICAQAwCwYJYIZIAWUDBAMWBGAdRzeipR0t1igxK/zxNFW0o+oF2bJlsM723nhY +/t88XO/B0638T2JCGyE6KncNui+ujyPJER46mvBWF6+4ARcZJM/bOEJe/UQG8vv5 +sprEde2IDAKzr90mCotHAoUMPEA= +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192s_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192s_sk_pbes1.pk8 new file mode 100644 index 000000000..92860895b --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192s_sk_pbes1.pk8 @@ -0,0 +1,6 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIGYMBwGCiqGSIb3DQEMAQMwDgQINirhkCHm0dACAggABHgaPUR9iSGwZUGgCEMp +diSdVK3Y9rbr/5QMMvvWfQJJ2TGeJVoqJEMKksaM+q1mgRhF4YkBOzaMk6hMRaaz +pIVgM/G5hJ6YdCdKJ4ZZdkFYrbivJNhOHN1I6dCK+lk7xliJIhHjt93uKc8fRMQJ +Ss0c5DfFVCLgsKs= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192s_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192s_sk_pbes2.pk8 new file mode 100644 index 000000000..0af66547f --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-192s_sk_pbes2.pk8 @@ -0,0 +1,7 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHkMF8GCSqGSIb3DQEFDTBSMDEGCSqGSIb3DQEFDDAkBBBtwHzyKUIKT8clOzUH +hdjkAgIIADAMBggqhkiG9w0CCwUAMB0GCWCGSAFlAwQBKgQQA9+ee4a7vuFrYtcU +KhxZpQSBgBb7fqxgqiQrrdcXg/DSKZEvFsKXWZ++T2qi5xzfsefsbRKwTBA1KYLq +2+2K4bh/H5r1EEkdJeRBGHvqTVmGULOcH6rfz8NyxBhbSOPCvjHRr0hA0tr2Nzcr +1hUKzEM4afxQGJnTc99Wj3I/3fF9Bbn8wuXtrVVavFtUNxFxHdoN +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256f_sk.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256f_sk.pk8 new file mode 100644 index 000000000..a9e195551 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256f_sk.pk8 @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIGTAgEAMAsGCWCGSAFlAwQDGQSBgPiFpG7nIWOA1u3W+JPiWedAMIZyfbJoq6g/ +um+1GeI9lVVTQdR4/KqRTmx5IUZUKFeymXRMt/FePp+Ex7u8xZjvncXaomWyZJmo +UBgWhmZVdTRWNQ+S5+6KRQFpaPVPY6+GhGzBxnKPRvZiE54YEzStvv8BH64XEJ3T +iazd30Q9 +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256f_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256f_sk_pbes1.pk8 new file mode 100644 index 000000000..9a3f039c6 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256f_sk_pbes1.pk8 @@ -0,0 +1,6 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIG5MBwGCiqGSIb3DQEMAQMwDgQIrfqIOck0OswCAggABIGYqPCghjLIzRDW6TKO +NwM/BoxyqF6yQ/i/GhQnNZn1SypL+G8I16B5pbkNJrNkj15Cnq51Sy1M01iKhW3Y +F8R8ad3UJ0S7hflyOcOzHcqFpC3dzeWTWn/xNj6GtZfftbsXeIvOFlHyAceNDbMh +mZTQK+hE3RJ7DEyP3pQqA+6N4RhrE/i2tw2BO3J/AMqg5nkPvDqdmOivXUg= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256f_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256f_sk_pbes2.pk8 new file mode 100644 index 000000000..a3d2ffd44 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256f_sk_pbes2.pk8 @@ -0,0 +1,8 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBBDBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQpcV9LeKicwrXVEaQ +nyQDngICCAAwDAYIKoZIhvcNAgsFADAdBglghkgBZQMEASoEENou36nZE/ZWmdNM +WLeOA00EgaDWzO7GufOAY+8HZOu7TYAJIe08LrZXb9+2bSJqyxg7VV6mWOIi0WAc +oGBvtZKpHROWU74hAwPjBJIdbabRH+VjfP7ZjGdFmvZlJCwyLLQ5AxyEUPH8j73H +rwWbF+j4wS7wWDCkN6Q1PWtVNSNqf+XxgpiV6gHPsbKN0KTXNDHgsSYEhBLj994w +ty4DyptNElkDrgfZD6FxQepmzyMGUohl +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256s_sk.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256s_sk.pk8 new file mode 100644 index 000000000..ea51671d6 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256s_sk.pk8 @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIGTAgEAMAsGCWCGSAFlAwQDGASBgMJmhWMsHC+ZaCdeI8NGfz8qwmL+3K/x78SY +QPkNr1U1Wu20BFU5XxVAdVAwO7kFamzk7yKWBqJDlPyuDZ/YX20FJl3hqB0dfe2t +9z7i8cvwx6DsVLB71OxB3UUMa/lGQFMfOnlrqcXurkNOuK6u0yDkYgpJS56If1Zy +KrWCCiLh +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256s_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256s_sk_pbes1.pk8 new file mode 100644 index 000000000..ac8340c32 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256s_sk_pbes1.pk8 @@ -0,0 +1,6 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIG5MBwGCiqGSIb3DQEMAQMwDgQI/EVJTakP4HwCAggABIGYdfSQ6jSA4iEs8VO5 +Ri+sjCdafwFZDP3bwratjkUU6OnjUUxZAosvabMLkSXz/oXZzbFjpE0sVYVyL7wa +i2GnHHJuclpTrqJhBPv/eorMIdEhsU9YDl98OgdmGkTzQDCbQz843TO/3bezambT +OkCNxDRRe+kFLgpSSoVHgl6thtJSTNWDKiqut6a6t7ilid7a+X9W8LKXM30= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256s_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256s_sk_pbes2.pk8 new file mode 100644 index 000000000..0258d87be --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHA2-256s_sk_pbes2.pk8 @@ -0,0 +1,8 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBBDBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQTSs1VqVr5spd6UOu +xq3qtwICCAAwDAYIKoZIhvcNAgsFADAdBglghkgBZQMEASoEEFGrf828L/s81dQ7 +DiJtDEYEgaCJXOJMVf+PdjIwpfdUE3NPvxj8Oi0DZ7AM3/0q4ocCMOiNlEjjdqNp +WUugdros5pY9nPIIG9klnVfxaxLQbKq4BjDJM/daChuZ6AJZTS0OX6//Ya9WH8fh +oM8+YfxxUZlfspr62w2Tqil8OZebV4FZZ292842cAVw+lCI1RN6sY+unoBqW0Bok +bFYdirDrznsodXmz4QyFGv+CWcodRj95 +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128f_sk.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128f_sk.pk8 new file mode 100644 index 000000000..3358009c3 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128f_sk.pk8 @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MFICAQAwCwYJYIZIAWUDBAMbBEBU7rgPl3R3DDS4y5nE8QhQH96+ByRCKKYQso2W +BrAGHMymh9DxlnKweyvOU4DzEfbGVJKUoa4vYrHc25HQTHeE +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128f_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128f_sk_pbes1.pk8 new file mode 100644 index 000000000..7b67bb901 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128f_sk_pbes1.pk8 @@ -0,0 +1,5 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MHgwHAYKKoZIhvcNAQwBAzAOBAjoNSpTlrltPwICCAAEWK3Y07vX5J17xzfYsXnv +28A7u5KWno/t5/oDZ6Yvm7g8pZnmNEq8KDvxeMnd75XUPIck/4zUlIAw+chupc6P +Sx2tPyhx9VSHCnCL7N3R41eeKlhYKH5o/wM= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128f_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128f_sk_pbes2.pk8 new file mode 100644 index 000000000..9b5692bba --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128f_sk_pbes2.pk8 @@ -0,0 +1,7 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHDMF8GCSqGSIb3DQEFDTBSMDEGCSqGSIb3DQEFDDAkBBBIPcsVVkylDCesdhNN +u3i8AgIIADAMBggqhkiG9w0CCwUAMB0GCWCGSAFlAwQBKgQQdevzuPfHSkV+aWzd +HdL83gRgJC1W4Vb9MzNryKMdxXbNrSJVsViOsZSCUgL+gkaIBPBHRA80f3ToedgI +U+juv3QDJ/rVFZzEn2+3uNHi/mZGjd/y7c1T4rFGGUFUa16s5931IiyccsFgcIQQ +4a3C9GSw +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128s_sk.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128s_sk.pk8 new file mode 100644 index 000000000..d5f4363d3 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128s_sk.pk8 @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MFICAQAwCwYJYIZIAWUDBAMaBEB7rogexDBq0MrVndGhZM9Ip/DHPf3BMdYs9eML +zm2TkPAZ1XhBe8fNSQ5bS7a6Uw1wt5XeNyroO7gw2Ic6R+Uz +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128s_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128s_sk_pbes1.pk8 new file mode 100644 index 000000000..c78d7c782 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128s_sk_pbes1.pk8 @@ -0,0 +1,5 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MHgwHAYKKoZIhvcNAQwBAzAOBAg5hSfuMmJcbwICCAAEWJvNaVpediEhplI5kuDZ +x1eEiK4EYZMzRNGe3Rv0wfT/1Rjxy7AhAhQ3ryrOCUn648qu/lM66zFKI+uJoSuG +TjaxcXnVHF2S5YTw3CI0dw1ZlOmKT6cbc+E= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128s_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128s_sk_pbes2.pk8 new file mode 100644 index 000000000..09d58e924 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-128s_sk_pbes2.pk8 @@ -0,0 +1,7 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHDMF8GCSqGSIb3DQEFDTBSMDEGCSqGSIb3DQEFDDAkBBDH8brnRdv/Qp0WbjrX +UAH0AgIIADAMBggqhkiG9w0CCwUAMB0GCWCGSAFlAwQBKgQQhGKGtN7nM1ACmQ/G +TVzabwRgBMc7UKCPH6rk5ivxwNg0/P/sSHnM5lzx0BRxPTFx8fc2xs6KS8xBm3/X +e3SJ9Cbz19ZURWj0mnLFgjXf4ICuTvA9pM4Hos3O5vc+jiCAjFYmCJEgHjlaNTci +sOiSeIsy +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192f_sk.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192f_sk.pk8 new file mode 100644 index 000000000..126800e10 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192f_sk.pk8 @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MHICAQAwCwYJYIZIAWUDBAMdBGAfLiGWaHJHuK7cRkilfIq7ElzRSb2p7Xd2oCxc +SSbC4BOc2hl7LoHHV8U24okZ5lxJoKtTnKIvQD/SoCDkNmqionCVN9i98fTvg0un +y0SJvuN17RmpAvYPBB7kh1QVF8g= +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192f_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192f_sk_pbes1.pk8 new file mode 100644 index 000000000..bb1ac5ab0 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192f_sk_pbes1.pk8 @@ -0,0 +1,6 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIGYMBwGCiqGSIb3DQEMAQMwDgQI+2YLc92YrEsCAggABHj7fKFcwC/YXPH/rp/L +yXbnhWVM/nauoYztKp3MnQresUfkK461TDmQrcCfjs2b/ShQqJyRPgWYc8qUIwqK +113YeLedNEvq8dUpaxPg8Ad9LBQxSVEtn3btSGWZpGMyPuq+Yx9/N1ZkHEvwps83 +Z6hii1ihY08ZqYI= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192f_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192f_sk_pbes2.pk8 new file mode 100644 index 000000000..8e37d6c0d --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192f_sk_pbes2.pk8 @@ -0,0 +1,7 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHkMF8GCSqGSIb3DQEFDTBSMDEGCSqGSIb3DQEFDDAkBBBsuYPHyhP4TXWZIHpa +JlK9AgIIADAMBggqhkiG9w0CCwUAMB0GCWCGSAFlAwQBKgQQ8GTH9MsIyfnXn6ah +SeuM/QSBgMt3MprN6lB04fUcOwTlRkGmGTQtaEqNBVwSJxY5lfeCR+67y85Wh1vs +IUxhCRNYV+8Jkdm5Uxij0O70cjwDYHCLdtSd2cRTAwPISeYcbMi8VPSH8btLINBI +ehK6P546iUvvgSoN7D2EHoqtSFwM0eF9R8u82HrveEawxtB18zOp +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192s_sk.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192s_sk.pk8 new file mode 100644 index 000000000..2bc39afa6 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192s_sk.pk8 @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MHICAQAwCwYJYIZIAWUDBAMcBGCPViyYzFgskhv80UvTD6F4foinF/Z7CqPbHjI7 +oEDz+w8HDewZ3rddSoqr+52t1T76SD5TLdbTJqOP5P3YBXDX/QeHZEdc/guGR8Ev +J4tQjPEh9QV+/C75r+Q9Lcp7RG4= +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192s_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192s_sk_pbes1.pk8 new file mode 100644 index 000000000..0c843610a --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192s_sk_pbes1.pk8 @@ -0,0 +1,6 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIGYMBwGCiqGSIb3DQEMAQMwDgQI1be7kfx1mPkCAggABHgg+DZ+8C9WTgq0VsWD +o48fIhcVHziuz3VmVaC6e6WdHHAcWlJN/DZi/fvlRzbYeyEf5mFuESgznLzKbCmz +Tk0IW7JhScI5un2KrvJ47znA6/nC5xqMgIPjsGBzoTrqhEjfqxTkabW52+M2wr8i +rtCgaObrSSDS1vI= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192s_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192s_sk_pbes2.pk8 new file mode 100644 index 000000000..5fa28a105 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-192s_sk_pbes2.pk8 @@ -0,0 +1,7 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHkMF8GCSqGSIb3DQEFDTBSMDEGCSqGSIb3DQEFDDAkBBBejP+WqlaR5jFNEPBS +N3gCAgIIADAMBggqhkiG9w0CCwUAMB0GCWCGSAFlAwQBKgQQm1rVkdnOS7qDZ6Yn +0z0kEgSBgAWpnbP04I2CSHOhLyDReUqfuSwf/H5ot0x25ozk1CUM4OOrBQOFLU2D +77cVhpIaVCcjnJwARJPguoOiAP+ar6esQfo81Wi9L31MZ+71eif5AUynI6j7YQ+4 +cGf7JasFsH3QjAU82ajJ36ADBjlxvIqqP0Uqui9A6xUpG4kNmk8o +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256f_sk.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256f_sk.pk8 new file mode 100644 index 000000000..39a1fe59b --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256f_sk.pk8 @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIGTAgEAMAsGCWCGSAFlAwQDHwSBgMVZdsa0IQvt7lOKPYtawZ7J35zp3zIgWQJW +ByhZ6BVrZmBSdkTD7jqSd8ErsTyiF0uwimICgrpGbRhMvNptbdKNMwJ/t1LLuQjj +sOcPIYaF696xk7ZYCb98Jc7WRrs0Lyoxpo0EBN9B9cm72fUzmvr52KKrM84jxDOI +3wXFTWij +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256f_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256f_sk_pbes1.pk8 new file mode 100644 index 000000000..f4e78976c --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256f_sk_pbes1.pk8 @@ -0,0 +1,6 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIG5MBwGCiqGSIb3DQEMAQMwDgQIrZMZz/FmXN4CAggABIGYRsZe0kF+ayzMr28K +qhpwBATCP0GpYU4lqc2hXRurt9HJ93TgUDwQclsTLRasOmfRc0Yvu088U3gEGOl1 +O3A4LfKnpB1uygy19dvGhyUIHL2fg8Ykbk8xzYvCX4TmIiA54rwYM956cfe4bOux +P2O7xwhEWlm7EOYzQMIP3rRj/hMP9+uC+8L4/pBe5zYadYKFuWcdCkiPGFU= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256f_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256f_sk_pbes2.pk8 new file mode 100644 index 000000000..4120d79a8 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256f_sk_pbes2.pk8 @@ -0,0 +1,8 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBBDBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQu0+wQdGXjO6wNwLa +awXQNgICCAAwDAYIKoZIhvcNAgsFADAdBglghkgBZQMEASoEEKx0JCUUEg8UxEUE +k26t3WIEgaAOw5aXveyqGLEvw/uExdrFF3QDvLaq9h9v5rfABzjfzppk9NB6N/ER +gbU1Hm6XKVavlRgfp0Ex48BihfgcS0f/XYusf76ASS7GiuL9GkVbtCyGNVl4nJlH +ZSlr4iRxt4G7H5UNslrw8AFXYURpmGokoll2UZdTC81Mx8VIsFJfeEohrYrveJyd +bGR9kfhUTR/J6bChASiPkmbuvYLjUGRv +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256s_sk.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256s_sk.pk8 new file mode 100644 index 000000000..9fb5847b3 --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256s_sk.pk8 @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIGTAgEAMAsGCWCGSAFlAwQDHgSBgN1wX3/vz/MUGwgQO7WFRur3rE1LPirFjDje +e0dVJXjN/sBEfELWkUzx7jo/VtsWkwyyKhjtYQFlAF7hiGK4R74c4jzA16aMTFNr +0kgHUwgzcGfFVYcYuPyIYo2q+DHHRozCaSS7Y+08KIfUtIT7/JLv8uNlbzJ90gcd +wAzs3o7l +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256s_sk_pbes1.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256s_sk_pbes1.pk8 new file mode 100644 index 000000000..7e3aebedb --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256s_sk_pbes1.pk8 @@ -0,0 +1,6 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIG5MBwGCiqGSIb3DQEMAQMwDgQI7leqlL1jWPACAggABIGYfIz3vSA9zqCeS/qD +Jm6sEyO3JaVzWutyACLGao62QVm72FQ1w6O8yPoLDwM5ybPG6lzXg+G7HSd2RZUM +hECL8CSYgwV0zmLFfkoORVlitcCPBigZWH9POiphzo5V0GB9TzAwSc3KM7axU+6h +sYhmfLlMiOiFWhYEwi7Mv/vGLzVuGWd2uEp/aTJbv/xh+39N3WFnPDDLEmY= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256s_sk_pbes2.pk8 b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256s_sk_pbes2.pk8 new file mode 100644 index 000000000..903b8adfd --- /dev/null +++ b/tests/pem/pkcs/openssl_SLH-DSA-SHAKE-256s_sk_pbes2.pk8 @@ -0,0 +1,8 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBBDBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQWHbYGjqVbI3v5L8l +T0xdtQICCAAwDAYIKoZIhvcNAgsFADAdBglghkgBZQMEASoEEB0GCqN6Uj/oQ+Xj +9nuBWcgEgaCucJfC4UMzQoBjFfXEtCepthJ3EhSFLizSfOvWWDCSBJ1ccgleZBCP +8gMW10DByRFEzF4ek8eqkhw96kQcPmpF6S0WXAmi2H80TlMsKi0o3QphOc6eS207 +/KVomDuXJYY4KMtYGGYUZM5huiBDZV2AONvoIw7Cqq3+XTStijqond0FdxbKAhNm +RXk7AoeynQmZ2It9nd+eAgahxEcbE4FS +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/rfc9881_ML-DSA-44_seed.pk8 b/tests/pem/pkcs/rfc9881_ML-DSA-44_seed.pk8 new file mode 100644 index 000000000..93febbe04 --- /dev/null +++ b/tests/pem/pkcs/rfc9881_ML-DSA-44_seed.pk8 @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MDQCAQAwCwYJYIZIAWUDBAMRBCKAIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ +GhscHR4f +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/rfc9881_ML-DSA-65_seed.pk8 b/tests/pem/pkcs/rfc9881_ML-DSA-65_seed.pk8 new file mode 100644 index 000000000..733f324dc --- /dev/null +++ b/tests/pem/pkcs/rfc9881_ML-DSA-65_seed.pk8 @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MDQCAQAwCwYJYIZIAWUDBAMSBCKAIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ +GhscHR4f +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/rfc9881_ML-DSA-87_seed.pk8 b/tests/pem/pkcs/rfc9881_ML-DSA-87_seed.pk8 new file mode 100644 index 000000000..87b2f0f43 --- /dev/null +++ b/tests/pem/pkcs/rfc9881_ML-DSA-87_seed.pk8 @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MDQCAQAwCwYJYIZIAWUDBAMTBCKAIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ +GhscHR4f +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/rfc9909_SLH-DSA-SHA2-128s_sk.pk8 b/tests/pem/pkcs/rfc9909_SLH-DSA-SHA2-128s_sk.pk8 new file mode 100644 index 000000000..a13f1457a --- /dev/null +++ b/tests/pem/pkcs/rfc9909_SLH-DSA-SHA2-128s_sk.pk8 @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MFICAQAwCwYJYIZIAWUDBAMUBECiJjvKRYYINlIxYASVI9YhZ3+tkNUetgZ6Mn4N +HmSlASuBCex3fKpOHwJMz8+Ul9mRgFCSgPQlavKwevgCibSU +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/rfc9935_ML-KEM-1024_seed.pk8 b/tests/pem/pkcs/rfc9935_ML-KEM-1024_seed.pk8 new file mode 100644 index 000000000..e9d876880 --- /dev/null +++ b/tests/pem/pkcs/rfc9935_ML-KEM-1024_seed.pk8 @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MFQCAQAwCwYJYIZIAWUDBAQDBEKAQAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ +GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8= +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/rfc9935_ML-KEM-512_seed.pk8 b/tests/pem/pkcs/rfc9935_ML-KEM-512_seed.pk8 new file mode 100644 index 000000000..8222519fa --- /dev/null +++ b/tests/pem/pkcs/rfc9935_ML-KEM-512_seed.pk8 @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MFQCAQAwCwYJYIZIAWUDBAQBBEKAQAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ +GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8= +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/rfc9935_ML-KEM-768_seed.pk8 b/tests/pem/pkcs/rfc9935_ML-KEM-768_seed.pk8 new file mode 100644 index 000000000..4e7d5a0b9 --- /dev/null +++ b/tests/pem/pkcs/rfc9935_ML-KEM-768_seed.pk8 @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MFQCAQAwCwYJYIZIAWUDBAQCBEKAQAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ +GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8= +-----END PRIVATE KEY----- diff --git a/tests/pem/rfc9909_SLH-DSA-SHA2-128s_pk.pem b/tests/pem/rfc9909_SLH-DSA-SHA2-128s_pk.pem new file mode 100644 index 000000000..ccc73ac55 --- /dev/null +++ b/tests/pem/rfc9909_SLH-DSA-SHA2-128s_pk.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MDAwCwYJYIZIAWUDBAMUAyEAK4EJ7Hd8qk4fAkzPz5SX2ZGAUJKA9CVq8rB6+AKJ +tJQ= +-----END PUBLIC KEY----- diff --git a/tests/pem_test.c b/tests/pem_test.c index 4dc14cbd7..b8684e925 100644 --- a/tests/pem_test.c +++ b/tests/pem_test.c @@ -85,6 +85,9 @@ static int s_key_cmp(ltc_pka_key *key) break; case LTC_PKA_ED25519: case LTC_PKA_X25519: + case LTC_PKA_MLDSA: + case LTC_PKA_SLHDSA: + case LTC_PKA_MLKEM: case LTC_PKA_DH: return CRYPT_OK; default: diff --git a/tests/pqc_mldsa_test.c b/tests/pqc_mldsa_test.c new file mode 100644 index 000000000..8d897349f --- /dev/null +++ b/tests/pqc_mldsa_test.c @@ -0,0 +1,518 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_test.h" + +#ifdef LTC_MLDSA + +/* OpenSSL 4.0.0 ML-DSA vectors extracted from: + * test/recipes/30-test_evp_data/evppkey_ml_dsa_44_wycheproof_verify.txt + * test/recipes/30-test_evp_data/evppkey_ml_dsa_65_wycheproof_verify.txt + * test/recipes/30-test_evp_data/evppkey_ml_dsa_87_wycheproof_verify.txt + */ + +static const char mldsa_44_pubkey_hex[] = + "db9ac67708f2ba0fac1f92bd802f9be89ecab966feef59872a1a9ac90b1111170a561290ae86b13968f2506023c014ba09fa449a26e4e9d35595e73986506cc8" + "790e4d07a94d6c736f7ae78cc5e3e3cf025ce06a09252bef97fe92e94cbd107b1844d1a7c690d88bff9e9336f8f58e0bd5ee384de9c7ffbb149a6fcd87c77288" + "601d8843e28e0c7a60149d02ebc57b183c39888d98b61cd8ad48135ddb8a1666743bb689f44c1a92d52017b6a8fa493eeb839dffb086a9a6c399b194a52f0e41" + "64c96ff8a2a54337de24350a866b5fe4195257778e72511221778f1eae5fa93ed3532f696b9b0767aded85f62ea311027c7f5fc4182dcd2864b1c26bd6dcf72e" + "bdedf70471327be0ea1c2ae53e46489c6dbefa512a78fdd7be0ad3ada16a7f7b1ece49817b44868a2cc234bfdba556c32cc92ec2c5e8a5d206f2e4ee372d4168" + "1e67d1b7e7b0061870c57f600fafca85f98aed8ce4ba76bba961f9ed56e563220d3ced853b6b28e7527da0e0912bc932a23c8bab811429bbb4d49b2770bcda44" + "abb932b11c0a5866409fce39fed2b459c86c8f6e1ab0aefc5879503f4b21a49b4b2de6760c9b6aaf041144a656a26af39f4578e1d482ddc1360ef751d9784b86" + "0ec373d415360fe99f32e126a2ac1243430e8bed1bc90b19b3d219c2712edcf81c44b4331f6421088e662b695e1fd8fa5091f616ab60af70f159b63368f1ac60" + "d77b279ed47ef7f24ec2044bb6c2bc76d933ecd568f7e663392afc1d335abac6c03670adf87747dde90052f5cd45f7d30f43a4dc3c500ceb658fce235c171240" + "baca1b5a14733d774b9416c540f53eb83481afc98344b12a4309e6222b08d978430467497010314c6f6b8caf65361c216106395275a67d7500dbc120f7918c6f" + "8db7aa63fa965b4a22c70dc88f727d768ce2bfc7597fd470184e1c59a6b2e1204cc8c3d052c594d5771e0ccc8cfb191f47038b1c0672f07caf4747562d3d76a9" + "816fb1def1391cf0f05fcdbf2a0eb6c21ac24b26e74ee403133e80a79313ddb02c1fa386c6dd1d420195343e3a104aff6d60887f7304fa9e3bb59bb55f820dd8" + "5b1445c54e9a38dc1c7f3b88eb36a9f48d13455e51c934825ff3cd8bedb2b5422344120399eef83a360b83440ebdd8ea6e01c95159e3735bb4408500caa785ca" + "4049891c7331c4ea31ad9060ece768fd339e6904f88e27bad3b28845687be2cc9314f300fda56fe3ff2508e54c59123b068f86fe00213d5af8da1b1735423ed6" + "88f097c306dbc121b81f532fcaf872d9f80596642295d6e4bead478644081618ab903b39e9b5e7cc0b5f2742d8337b18d4ad4788db7443e946cafc1762a5da84" + "070e8c2fd86d6c633f0b44ee234ba11b9e1440c94a08d0437015279690405353059020fd2f58f15dab18754177244adfb81ceab79c7840bf3884a3d364afc8c4" + "53a425fd8c5378eaa7445f8c6256bfbd03a66c53e8cf27e2c52f14ef3294afe79cda408f5dff933ca0211a78a4e3be3d9a932558ed71ed19bbb57f87937fa3d4" + "a78128491ff096a261045bdd186325c42caa8c7564195a4d2499a1c17d21a52d1aacd221d9c8a1866963a20390f2fd43dcf56b308a1c01c38091fd3e04c12b69" + "5de497d48bcc268d50cb0bed793b8e6937e8d533afd568521f1c9377a3804d38e785674d7ce868d289938e33dda6edc76d25b15fcb38852b7803cfe62f08d9fb" + "d070957c4e6f134973964c9dc009985c8501e7d8f72e7ec285d5289fdd07f64d62acaa9737b039efa7a9d1d175577c6bcf9dddcf692877af38e75263bebe2453" + "155be61f0723c274388a532abe29dd7023e327085f4c9dda41839b7b3357ab9d"; + +static const char mldsa_44_msg_hex[] = + "48656c6c6f20776f726c64"; + +static const char mldsa_44_sig_hex[] = + "1aa69cb5ed35204534f25f40a17eb0d767f8981f5e7cec46d3bf3252bfc78e09d02ef0c82da6dde973611c849472890106158cb15ffa6ca891615e888efa0d2d" + "8a121b75ca440228ad32991be34249620f158ffd6f74d7b03bf919218ce259b500808ec157ead67b56b79e9e6607eafb9227b8a30adbec087d35bc1aec2f1a0c" + "4dd126dfcfb9fbf0bd74fb1e092495fa994ab5a7cd1333281aafe834694a6dc11e889c762b5645638e172dfab3060031ebcdc1fd455d5de6050bf71b074a4dd3" + "4af5ebf15487651f0f13e5d3cee231b9b347810bfc418196df9d7231780c09171b9aae732bea27a1649d8c03220f417e30a016b08ccb1d55c9337b4812e20e04" + "523f5d29a760a01b3a80d76285521206481ee1e44df09a76913ba54ae50c8eb973a3ced73950fbf39c4c0c1262a216821a442072c10cc82839ac57b898411be9" + "e810f893272a2546ff7d1d920f146210efc2b4528bc98a099a398302d301fc1dea31b3d8ff78246a66f690ef536b68e02bd7ea23a5378930dde7f1beb5174989" + "6a7944e5a40e6fbbb1f76c3fda09e32e0a58062c24cac7ddb8c1d2cbb352a81e336425c5f551246db45ecd0ab29dac88cdebf51c60bebc2e27c974f56da12c1f" + "ec4f5745850429b607f5ed7cd821f2c91fc2dda8c2c8e8ec278d1b2a5bf50ec70c5623fc681b4d1dccff96b324cb53ff97470f9de177c2006a89af8f18603a6d" + "4ea2625794695fe79cd30318a1e76307a4c2a353db1e076ad9b609a2489b94cb6dd821c3af31046bb7a5d43d190e09fce4969fe4e93c8393975e64cb2d9c2294" + "fc427ef5191c40937929b3b0e1b037e6b84cc0299d5af2b5410118bfd88ef6491af6f21233390ca7a19f1576e6c5a10a673796905562075047896e3a2379f64d" + "fbbc12b9bfe64939c2d05efbc5f6e4b5ca69ce1ed4b7d25e8c835b0612b33e13ed7a8a7233b4b3d58eead0bc4c841acb65a5ec0ed45e2584c23c2a162392b578" + "9c62358e4038864e20c10e10c67d940ce78993178dbeb3de1fea1e50e7c29f4d7d938c3bfe50229ea040102f30d5b3a64cb8e13420065d54a1ac50a77383bdff" + "3cae2340ebf15a1557fde897007c1b67d04f19431ca00cb0f08db87e90e166e0f4ce6fd69c6ecef1b3f70d9eb601b57a7bf931057c2afe2d3567b6bbec7891c6" + "64713385122fdd789c1d5a8a9cfd491f407c16d0b0c5dfc53a6862208e264b981bf2ddbdd1d7db9729b5265c4c3868a947c982880bc55b786153b89ef3324067" + "b35a928c51236bcbe9f860ad9eee5644478f894a9fe78d26a5a17d482612f1cb9983b864e6fba84591c0f73b7b27918819d2121d4af640f533e2939d3da0f0aa" + "6b9df80837a80165ae8b7579715192eb0f6cca78a43d8ad8d7abb56d816e3af2de59b88bfdcf6767abfb043d3ae24223d05001953faa292671c57ade1fe28988" + "075ab8d14ac98363412bd694c40ae85b1f104afcd0f25aa590f57ba4f5dfdf613bf8594e3f54baadfdf50c0881af2475590758a23b7eee725513e4d1ea9f4630" + "159c424a289f18a9879e5e173390f8e630f6ee2a6043d82a1983dc97c7acfea3b0c03e27e865d810d012daeec28dc454f59334edf24627d435701d329ff5e68d" + "19bbdca5ef7d5e00204fa947d08f81cb6484cabe60989d2f61fbe70940f7e4f449b3fcb103a89143d74b15d72e7913dce9193a0b9c5a7b2a97bde6d7f396ae80" + "b4b566f9f2e7345bc42ce3b002818e19f0f16416b850832cd02279ee8d58a381deaac09b1b4d4613f4d066805d2faea6716e015fe361c0526c6e4617a389ffdf" + "930213c1dc0c4c905c3106a7517dce7abea7a9341132f8ad98de3e42f6b75809fff38f6eeafb97398e79d50a5622338763c4e45a88ddda7fb87ab7f5cec61109" + "fdc1c5d4a16310275241fc34178028a49fd79581a05c3b6984eecd6cb9bd60a44da72600f8f2604a4ff4578126194fb2269c8e6e71447445e8e80bf8c6063dbb" + "f29c7ded58abbc0d2eed347bf495b6a9cbe68585a594aa0e65834bfbcccc3f6bf42fe4ef42d86232c3fb1412dd0b5f8a0489958f5c3b883bf7851337a35b13dd" + "2b6517626ff2d1064cd189beb402497dd6b8893d414dde7d1d51018c7a83766a2d8a29b80e8f428237732f7ee5ba878163f0aa8af5b60533b4d4621a38fdc543" + "83acb3325b5e876e21483eddcc64c419596e656d1557be31b530ea66054f79d4f4a755f9ee33c84fed5d552ec5e2eccd061cf4c4b5c3c16a70a7baecccfc208d" + "2430e78621c9ae5b0d080973b4e1df0a1f5c0415db6d3c85f9ea9041e9a9abdde71d6776a522aa957f708b14a33eda10ebbab93bb8ec2b7a04679f38eb44fc55" + "8ee698d3c6937e0e647dce898d7599fef6de32ae4d52adc722443610b2126559756aa36f3c79696b99be3d908f780fcbaef33b215693634d63ce2a0777dfbbc8" + "99d2be72efdbafbc10aefb26a1a63cdcfda00235b34db723c91624ee5f939024dfedba0863ad08f648767d41fc7fd6b317c51f4b1b87e21e07d488c9423581f9" + "bbdae43e4d32b37e8283960524f9a601ab69f5cd7fb01c9a8a5c64fe863519a1e9f3426398f691a96e1748491b4e209fca2ab29481a674621c797614ba16fbfd" + "fd1a4184e7f84667e720e6bcd9debef32c2b9e891a6e3c0423158f539838d8413e9fc707d5c65b23368b6edc95d9c3f8e20bbb844499311614945606c1487ef4" + "015d1e260fa8239abaa071be572163132bdb06ef21e31be0f9d4b6747134e4842bedcd3bf53b0d6f054693bc428e9a715d5a32a79e6a3cb8b81faf2c04087d88" + "16752637a2fe11eacb38341e024848562a29d4585e4ee56552ce9b1fad43b965a37bff8558921790ef0f4ac55bcac4327d1783f5e1e79bf01e96934bb4a8f5dd" + "06c83bb70b2377189d622a106100f0cbdd38e34c0565900c616561161b3261859133f83893feb22b0bafc82cf4f0dbafde0648e2f86260e6e747034e5cb3ece9" + "8087fbf74179c6306f0c460b5d609b9b3a66761472ee0b9dabb5dfa872d5c6bc9b33461a27b5427bd8833f874f479ecc5f0a20304b9a75aacc82420a87af6469" + "daaef53391ae8a25468e717dc47f464fce45a31147c0c4e12ac2f834567e4005b0827d13b3ec80cd8b7a907436e6624c6c8ac6a80add35cfa1a28872fb65cb3f" + "a46894d116a052f19b5fe20c7ead10bd24d27ad2b5683f299d1193ec6d9ff3379f3b3e39cb9991831f194af2041085508da4dcb7b8785cbdc4e04cf4d826d1ef" + "4a11036e4c5803c3aaa7669b4dd3bc12ff888984e9bbdace0e772ab59332b47300334757677578808e90929697a9cecfd6ed1b303d4250738a97a0aabac6d91e" + "283a4b696f7181828493aec8cdcfe1eaecfc0227484957595badbcbfc8fa000000000000000000000000000000000000121f323e"; + +static const char mldsa_65_pubkey_hex[] = + "f5408337d0fee65c28851226a5fa81b58464632c78e2a9bef70d330f2e3a5f74d9cf676aedd1067c91a5dd5d4edc46f868a93ffec9f44e254e44f682a153aead" + "f228e8db7c5fcfed30cc3408e261ab896876bee56660d2a7c1d7eac20c5754255206a178f7156295065ce7876f90c48f44bc37f3a00e32eefd3a4bb1e298fe28" + "3d106eaef92a33a594253a2a0790976a1d04636f8672d28c06c852ea8bb43b84bff512996e7616963d5b9a2906466a152c7ea9be178be35405683b44367af85d" + "2daad87630c1e21ba5490154f0141780f5ed0407cb0b975dd56d5930f9b26413b843b83f3693304b0038bd3e4bb398868060ea18c9c67099376470a50deb052e" + "4056743fbcdf0341b192663bd1c21ba3b3d5666e0d0e29c4e1ed0759ab0bd9d1d355011b94e0ff0c049b03ddb7138640667144fcacd7265f55a07e5387f1abd3" + "0c037cf14d436aa855f827049215440d8007f61460500d943f57ffb6bfee6fedd2fcec52882d7d8da1aab29e892c8beac3df3234b4a7d2eca3a45c6623c52bbd" + "d07c1c94314b706988a52029f8f8b06e874b741d72926652c78c6ace2cfd8864eadb2e4b39cafe6e03e4edbafa2747db9bc42f92af8b031e3e380846b1bfd15a" + "de88c285d6a6fffe91eafc8b17de6cbc68575f323cc09fc20e49e8efd76f9568bec486b78df4245428d8d0d5f53873e11de65fda4c770b521a8c67f5c51d48cc" + "26358954514447881fd9a42e5891dac7e1db5249d7861b322111e5fb929bee9ff5e9d5a2667ba93e63fc03040d2e82648f89e89dec1d1d2dfb9efeceb7940f7d" + "cbebeb5a239cc1c54d8f7d52cba220d0634e15df46a58280bc5a48840bd39274cfde150f9ad9a40f6398d715350925f0e0501944409f32331a362bdaaafb3d8c" + "e71c964332d6afb7e684f99951246d88081c86744ae68133f22c53a4b5ae258f230a98491d2d43a79a6d0f4d54a3b62013965ac7c82d0507125a38a0277f81cb" + "c1d46cef2a131c6f51b88ec0baae0c82a6a0e72831cb06f9116cff5111d597e01057d32805a008f52c9aec3311139bfb35982789ff83bdd0c31e9f1080e8ed8e" + "b99fde66bafb29e3357389fe3785b60c78e229ef073e1b65e34d848bd4d8a4f251551e2d38d2546afbc205d3c6dab34d2b962b1afb44f1d22fc10c6744fcd6b6" + "36afd3cb414b16c2e0d708fe9f51ff19120bde693b028b6d1e6dbe37b4b8b3bc7c6f7a842701603869d3ded572500f085502efc8d3cc62b30e5cdbcb5e86d9c0" + "d42973bf755df539cc0aea58f9148386db67bd2bf70cd12ccd96d5c66fb271416b772465228dc44b079178f9b766370b66a79b871faca246ca6f8f63be9f0668" + "297ac446cad5cf4a83318b1b00ecbd283f0eecee60a9a37a27abdbdbe382e307970002837dfc0bd3934ebd008918fd4bd383c02c9d37f694996e989a49075767" + "ebc4a2981ef5275455e026cb0bd70946cdd1fadaf251381d324f9efbb860d1b280c29685bab97d010676273b45cca12ac3966aae342c84e2357eccf252577743" + "b8787967b40b07ef2d3d9e6c1a3bcb059cba0fdb7f0d4f815c242b8e14acd3375e608e9230ba3cf8718f43882a3e1e661a2bbe81830d34741f33473e263b3790" + "abe67acf29f5df44865b2ffbc96975fd62738a64112deda5a2534fb0a23b3b3024df986391badf9041c593c313a7ca1e1fcffcb65b07b9a99337b4a4acf616cb" + "e1553eb9541f38aa6247342905995233a28172ca13396b2a9662970120f82b92a213f43de7a232ccca3268265c9ce042d50915430a6c455f32277da42f9962fb" + "9163b623231ebc080fa7b8e9f9021fcf85b98f9c483e4d2226b9326a5bcb2e7449ef029ae142d3a0f0c28bd4f7e9c51a12e1336f24dfacbc3f808a8f7dd68302" + "7bc948763b808fb0037394b8b41bc9b2ec7887e67584e03d11b15ca203b2bcb43f8881638c4e4eee7f846d09c7f89b7739df22b2c3acc235032ba8f7ae27b5b9" + "d25733143e80a4cdde6770719c1e66ec2ce683612233e88fafff84c0745a98aa1254c8219c6c556348c2b5d1beeb61532d6bf7bde153271dc647460beb65fe00" + "55b33fd6480dcbb9d7d471952cfa5be260c39721a8c5c89b9e966ae2dc9036451ec9f2c49433b2225e13f23e20c2bfba81a7b3a555883449238f7d48213e9f10" + "ce19e76f1bdcfc73ee5524bd7d8be0a4b46784e238233c04fb99383ec7726f9717e1179dd14fba9ad6c2ebd1699f0ab0e57e6cad23875b029e89cfda06f51266" + "ecd2eed4edafb51e82f2a506d57ba74da611774ca5fa2fff4a976519de425885e7d09219cf815b1767d4fc5a72c18918991a285086a6a766614a4d245387da50" + "f28dd778fb33ab88c0918feba3768c55bb1f07aec33cfeed33d6faa4d34fd7227b365533c1e67dbc89f0b20195cf1cbd480d333ade1c9bb28308085b72ced430" + "268c1492a27050c43668adc9cf8b8509447cfcd3c8f8d8eb554f704101786aa9ebca86991d250776a37a1f56fbf7d08e591f978da49c3870625879f70e2418ae" + "c5cba32fa8c346fa9038baebc35ad0068a4d03537aee14c2e71570a87490377fa8dd66f995aa044a522f0c7025a7ab2dd5ad30a64268dc112b7f9fa156df64d6" + "31f55f1d6edc55cec570a9c7372e29e02c8d4867bae249431dcf6ed2794a0183f0f7501201feca4a81d334c642fc8d38e9a90fa77429665e09e214797dfa455f" + "f47c4f219d3a2cb0176bc2236455123c1c5da714ad29d580fb194f87173a18dc"; + +static const char mldsa_65_msg_hex[] = + "48656c6c6f20776f726c64"; + +static const char mldsa_65_sig_hex[] = + "69da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b278c354d7197c4d6d7f83d1422b29b250" + "f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfa" + "e0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1" + "027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd433" + "86c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb88" + "3665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d" + "21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73" + "e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba63" + "0f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b8" + "0429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda43629" + "30adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5694e5398860e439a1e19d5a66f2fbc0" + "aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b" + "160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b" + "01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc08" + "52b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e5" + "64abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15" + "843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d07" + "36cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d73" + "48cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4" + "cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75" + "cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55003efdec5012b6272b87183694c505f0" + "446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4" + "c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed" + "8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0c" + "f4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677" + "677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e31944" + "3336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257" + "c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d5" + "36a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee9" + "37074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63" + "a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c176547a5383d948ed15484b79e21314" + "a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be" + "6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607" + "965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973" + "440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0" + "c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1c" + "e5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e" + "1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145" + "fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5" + "e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b0323" + "0cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d612331832ff8755460dc496aa99a61ea" + "053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c165" + "2d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1f" + "c68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67" + "e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e5639942" + "57df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0e" + "f3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e" + "246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e" + "717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287" + "e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d1" + "4eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3c3f6a6b6d0b161e777b8296d7dce7fd" + "162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f9300000000000000000000000005101318212b"; + +static const char mldsa_87_pubkey_hex[] = + "17a508179b35057099111733da28fd1a2265de7d8ab22d5279f13bca84cc42a5b8c9644c121e7e1b81723c5295be288fb6c36bfa188b6e08d913a152350947fa" + "2c8ccc3fd01b319f65a2058a1dff54133946cfeb408d0b6dfde6bbebd7e0591cfe83b8b5452ceef6c855f7d33e06a0d269345089ed0d3ad67d84d8a4a34d1683" + "6004cff125469e8c3387abd788b620e30c1fc23909117a0e34c42a6631d9791347b1b2a3c9ab3082416211afb7bc3f6ce630a7019af19f736cdfacb1e7db66b6" + "5ef56844d2a2b0753d09283a7a0b66f77596384e95f7ceddd1c4ba20edc11f1eaab695bb963f6eda1c383754aa372a0d7729bfa6e0f142131c2367ba3f89ce3d" + "e6c357f9a7225b7cb85f6b3e8a3a122e8501fd1446b8152a415c19dda1d2e4590cd994f6664b4d1abd7381468c3a085abe2741a0cfbb81880664b271677245c4" + "a471bf8bb8e0192eb32e4fb5e8560f3c50d6b19a353e486d0fcc2a35ac046286e707e095f61786d92212686a65d39b6863e0f8cec1e1997f2f845e4878ca9df6" + "50c746765296790863e51d012d32dffcbd746aa2276d04c0a57cd1b3d6ed06c0d66a0897aae5c49c97b6f19ae829baaafbfed28a52c05963c6eea9eff6952829" + "4207f8cda75280f7c486e6848791c8e37015479f2e13c28a9fe654dbde11689875203aaec51be3da7cab1cf31e4ec476c0c830cbdd04ac02167c0a6fbfdd6548" + "b1fa525d235c7e3fca8d63e6427503b0a45c0bfddb428b837c32e8755441077bfe1c0142bac357b012a46545bf4148d465472dcf89c9d73b62357087e229f53a" + "450d3cce41c8ee21a9d54b61e34a794f5b1406a70724ab0c3712c49df231ef30a956075e907c51b63dd1f9453dbe60e25b0f3cc0354dfd7c9119313919e77cb2" + "c92f544d3e5302b8827603e936b567e99bfe9904932585a9f01a5a1b5bce07565f1d84c6b1c5c86259e1fefcff18cd06861122be6836be21e40be4eaf6bcabee" + "8f634f95520aa914bb51c54dbd67d1b9dc5e38831e786c283979a963a3206b98e339edec4128b0502d4d47813869713e431a529a03c7f54b50123680f2b7f256" + "f5d2b40642203259b9e85c62253d5670ce372193f28b5aa48ddd643c54756a2cff808c109f74772961d8db6bb8a17547c8f29c7f5ff3ea06740b867d84917e07" + "f3978ad0281a20689eef58467e768b6178a9b36a567289fd39762bb3e4254031b2798a4550857f6af369d484392cddd7b48eaa2942e2cbfe754d5ee2da2b7fa7" + "1222e4a525ff5224d551a778ebd828e4e0499adc74ff0d59a5abc78ad6a8abafeedb3c99045a14423507f85597b1a7f540982f7d72ea13449110b442d54b7802" + "9b4c7fe3b49396dc6c3b7d58792538fa907963de10a4b724548142541cdf1512e0f7ff1b10a93de63541b8cc3268b4de20ed26739ee8973b6507ebe48965602c" + "35fa3f7d4278146b598d7d7044e16e97e9351f7c51ac25573b7232ae2432638e9166190e7f7a7dcb5096ecb5d10017cdea2a82b4f56c7385041c6919a7e36e11" + "beac77ec3f25df44e7b596c1542c1e376de3667c0e903fe25b57c338e9d93c5570c484f0ddab4f57d38f292b23599d9efc7a9fd9e078aaddca0acb1a196d6c45" + "d3c8be6f39e8cdbe3299e370b262e0bf6fb5f005cae2b12879289d00bd8039de6a571c310d87557f5c9a4f64a0bde7177a8464722a04bf87fa2cb0e312d4fa6e" + "536c61d65dc2c1baf144b0d1d1d75f4c860626ff773933efa9941d105c53a1d92c4f7c7bba4aa969590acef1e50901870f59715ac14d9846d83871a77367be57" + "c63f88bc2c02eabafe678f44925a3e605979282fcd3f284736a1d346c033cb782dd615e886683fc37cd87a91422857774c63c6659096eba393c56225ed8c3485" + "b4f89ecb07d53526281a6426ae7d67cda52fec5ac32320caae9b96000bcbe9e8782be88cb1ca6dcaffb74ef04c77e03a994bea2c89e4fcfa44cd0c9f4e30705a" + "8b7b20df8c76b05a4479400e07db03d243e9fe4c90d34e9245f1e574be9a388f5355482077e4e98b919de024e666fdd7d51ed2a0d58a823e7497eb07303cf1d6" + "d5f10a536be980220de5856727e5c13981839cfa19740988e7771a2b984f53ae3a5916ed881a4a90fe524f0bb3778355882864f8961fade32e656fcf9f524e74" + "8c8196a1f1bbc57bf8da7b36de9b0080f0c7bb8487a2b7bb7a81a8ff43a2539b367c9a48c70041520f05ca3dae316dbbe3118218216f52b7bcdba7557c4c9d86" + "1803a5e2ee01d3682e1261d7cae0a99fb8de909eb2bc1e112aa43cc2fa9c76a222bd85faaaba5d9ec2198ac45a295181a324a0592632b89e2752582cd5e01e1a" + "610e7563faee10b76d853109e257e7c0c248a9fb7933f514b07b4f4e3a4a3d2cd22e8cc45ebda3bef5948aa050f01eff85ae98d19f69c51e67ff89f2df0c5268" + "acfdd325e84591317e05cab4f9e6358f249c4ddf4019fbc8f511549a733898a50efa9e0793083de0b15b5bf78d9f63d8df830d42df2fefa27b89e0ede2a702eb" + "9467118fc0ed44edc63ad1b1935877c34843fea06fdf388bbf83e501723a13cc6cc2efbb9691fe28fc1d45270591e5bdf7aa1c82673544ee29d9e6c9da3328f2" + "1e9729bffd7f4e56de585909679a74037105fdac3f51ae35f69d9763d2e4cfeb1d4a8fdce99bf1aa21f866a9f523b2a9549e12258a4d19900cf5db37b67da19b" + "23563bd1d701c6106fccb28e4689c62e1a6cf1abd763d7239c2258b765610d4478be9f1650cb8d18923592ad0024076e52f9bd0a3894fe97bc0a1646b4c37f62" + "c27f32d0df270260f47c49a5caf110e4cf80168a7d54b1c70bed9bd5d9a143ce869a05cd44ee266aecd6bfedb39be79e7c7d5c11a99575ebc0f389cc55a4fe14" + "69a2d61b70bfe4b74e3e27521a037d2b9f4fdb377231e2ceb214ba90f6953865c683215203ce963875c6524c01b789e0389a9f0c386eb236f0dfba6c95df4f28" + "ccc7ae7cd473f9dcd20817cccdd211bcbc78b064e936e4ba2813df531128428ddf410e6ca07044aeb4cfcc0a16c995ec51c8af16a541ce18dbeb69a26635632d" + "cc24ee52a5eedce38c502cd0e356ec31341c893f92e6063c3a160a53d34b85e92357a8ebaaad8f206771be43ee48cc409825a7094bda529ee18776d9e67f1fa1" + "c1419514309d70ba2443be2f63b6943478d6c0f56dd058731e53de4c30bfc7d915e9284a56248e81944392881666680d4991f04269ec9a83b24b458ed59a6c27" + "4de452ab3013c103a4920543e6a7d22dadfd764f6ea39d49b910ee0dc216e547aa5fb4382a72a568ebe83ec00416fb5830dc21c24ae72416602870cb52c3a8a1" + "c4c12a4b287b9b800d31c287ca161f404a9e598a5358d28b3aae43e534846bcd0d7a9c7652ae01e6698c79e315aca8198f36de45af7084b1cb21ca2ba0ee3a54" + "7a7343a10ef9e3fd17b0a4060badd1409a0562cba25b84fd578268fac53cfbca08e6cf6e5419f57262eb5813c1d1324e0df1d483ade08d8f6c62498e262485ac" + "7c2872b11b42e5c1b797fc12e838b38a711d364d45cd1ed35f7faffdf4b0fb0eaa312fc3d5af77909b0649cbbacea10c9831273922b5b05172face9ce6cf324e" + "df6e2f5f5fa0a9f0463eee938b30adf3e55664f94d274cd87dea901a7e08e805"; + +static const char mldsa_87_msg_hex[] = + "48656c6c6f20776f726c64"; + +static const char mldsa_87_sig_hex[] = + "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906" + "949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9" + "435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f3" + "04e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35b" + "c4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03a" + "bc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec" + "6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f0" + "33b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a" + "530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16" + "544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3" + "a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3" + "e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a8060" + "13f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3" + "f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b59" + "93cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b" + "782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befc" + "df2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e68" + "32886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba45" + "9805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69" + "ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a" + "8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483c" + "be8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49" + "474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8" + "146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368" + "d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb" + "672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77" + "b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef" + "962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48" + "e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07" + "fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4" + "988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6" + "a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b" + "3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823" + "420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c" + "4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207" + "d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b" + "746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533" + "acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a" + "87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f1968" + "58aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae2" + "1009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c31" + "4c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0a" + "da5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b" + "78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7" + "c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc" + "817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc" + "63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097" + "a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650" + "e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05" + "a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f935" + "8d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7" + "220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce23" + "62901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b9" + "5f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173" + "394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5b" + "a30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2" + "996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a" + "54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25" + "f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c4" + "5090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b" + "802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f63" + "80c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c294" + "8a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb57539" + "5952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b579" + "1ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842" + "160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb" + "6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4d" + "f24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba" + "2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926" + "e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e" + "19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb796805" + "2f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c1000000000000000000000000000000" + "0000000000000000000000070a111518202731"; + +static int s_decode_hex(const char *hex, unsigned char *buf, unsigned long *len) +{ + return base16_decode(hex, XSTRLEN(hex), buf, len); +} + +static int s_mldsa_sign_verify(int alg) +{ + mldsa_key key, pubkey, imported_priv, imported_pub; + const unsigned char msg[] = "test message for ML-DSA"; + unsigned char der_buf[5200], sig[4700], pk_buf[2600], sk_buf[4900], cmp_buf[4900]; + unsigned long derlen, siglen, pklen, sklen, cmplen; + int stat, prng_idx; + + prng_idx = find_prng("yarrow"); + XMEMSET(&key, 0, sizeof(key)); + XMEMSET(&pubkey, 0, sizeof(pubkey)); + XMEMSET(&imported_priv, 0, sizeof(imported_priv)); + XMEMSET(&imported_pub, 0, sizeof(imported_pub)); + + /* keygen */ + DO(mldsa_make_key(&yarrow_prng, prng_idx, alg, &key)); + ENSURE(key.type == PK_PRIVATE); + + /* export/import private key in PKCS#8 format */ + derlen = sizeof(der_buf); + DO(mldsa_export(der_buf, &derlen, PK_PRIVATE | PK_STD, &key)); + DO(mldsa_import_pkcs8(der_buf, derlen, NULL, &imported_priv)); + + /* sign */ + siglen = sizeof(sig); + DO(mldsa_sign(msg, sizeof(msg), sig, &siglen, NULL, 0, + &yarrow_prng, prng_idx, &key)); + + sklen = sizeof(sk_buf); + DO(mldsa_export_raw(sk_buf, &sklen, PK_PRIVATE, &key)); + cmplen = sizeof(cmp_buf); + DO(mldsa_export_raw(cmp_buf, &cmplen, PK_PRIVATE, &imported_priv)); + COMPARE_TESTVECTOR(cmp_buf, cmplen, sk_buf, sklen, "ML-DSA private std round-trip", alg); + + /* export/import public key */ + pklen = sizeof(pk_buf); + DO(mldsa_export_raw(pk_buf, &pklen, PK_PUBLIC, &key)); + DO(mldsa_import_raw(pk_buf, pklen, PK_PUBLIC, alg, &pubkey)); + + cmplen = sizeof(cmp_buf); + DO(mldsa_export_raw(cmp_buf, &cmplen, PK_PUBLIC, &imported_priv)); + COMPARE_TESTVECTOR(cmp_buf, cmplen, pk_buf, pklen, "ML-DSA public from imported private", alg); + + /* export/import public key in SubjectPublicKeyInfo format */ + derlen = sizeof(der_buf); + DO(mldsa_export(der_buf, &derlen, PK_PUBLIC | PK_STD, &key)); + DO(mldsa_import(der_buf, derlen, &imported_pub)); + cmplen = sizeof(cmp_buf); + DO(mldsa_export_raw(cmp_buf, &cmplen, PK_PUBLIC, &imported_pub)); + COMPARE_TESTVECTOR(cmp_buf, cmplen, pk_buf, pklen, "ML-DSA public std round-trip", alg); + + /* sign/verify with exported/imported std keys */ + siglen = sizeof(sig); + DO(mldsa_sign(msg, sizeof(msg), sig, &siglen, NULL, 0, + &yarrow_prng, prng_idx, &imported_priv)); + stat = 0; + DO(mldsa_verify(sig, siglen, msg, sizeof(msg), NULL, 0, &stat, &imported_pub)); + ENSURE(stat == 1); + + /* verify with public key */ + stat = 0; + DO(mldsa_verify(sig, siglen, msg, sizeof(msg), NULL, 0, &stat, &pubkey)); + ENSURE(stat == 1); + + /* corrupted signature must fail */ + sig[0] ^= 1; + stat = 1; + DO(mldsa_verify(sig, siglen, msg, sizeof(msg), NULL, 0, &stat, &pubkey)); + ENSURE(stat == 0); + + /* export/import private key round-trip */ + sklen = sizeof(sk_buf); + DO(mldsa_export_raw(sk_buf, &sklen, PK_PRIVATE, &key)); + mldsa_free(&key); + DO(mldsa_import_raw(sk_buf, sklen, PK_PRIVATE, alg, &key)); + ENSURE(key.type == PK_PRIVATE); + + /* sign again after reimport */ + sig[0] ^= 1; /* undo corruption */ + siglen = sizeof(sig); + DO(mldsa_sign(msg, sizeof(msg), sig, &siglen, NULL, 0, + &yarrow_prng, prng_idx, &key)); + stat = 0; + DO(mldsa_verify(sig, siglen, msg, sizeof(msg), NULL, 0, &stat, &pubkey)); + ENSURE(stat == 1); + + /* sign with context string */ + siglen = sizeof(sig); + DO(mldsa_sign(msg, sizeof(msg), sig, &siglen, + (const unsigned char *)"ctx", 3, + &yarrow_prng, prng_idx, &key)); + stat = 0; + DO(mldsa_verify(sig, siglen, msg, sizeof(msg), + (const unsigned char *)"ctx", 3, &stat, &pubkey)); + ENSURE(stat == 1); + + /* wrong context must fail */ + stat = 1; + DO(mldsa_verify(sig, siglen, msg, sizeof(msg), + (const unsigned char *)"bad", 3, &stat, &pubkey)); + ENSURE(stat == 0); + + mldsa_free(&key); + mldsa_free(&pubkey); + mldsa_free(&imported_priv); + mldsa_free(&imported_pub); + return CRYPT_OK; +} + +static int s_mldsa_sizes_test(void) +{ + unsigned long pk, sk, sig; + + DO(mldsa_get_sizes(LTC_MLDSA_44, &pk, &sk, &sig)); + ENSURE(pk == 1312 && sk == 2560 && sig == 2420); + + DO(mldsa_get_sizes(LTC_MLDSA_65, &pk, &sk, &sig)); + ENSURE(pk == 1952 && sk == 4032 && sig == 3309); + + DO(mldsa_get_sizes(LTC_MLDSA_87, &pk, &sk, &sig)); + ENSURE(pk == 2592 && sk == 4896 && sig == 4627); + + SHOULD_FAIL(mldsa_get_sizes(99, &pk, &sk, &sig)); + + return CRYPT_OK; +} + +static int s_mldsa_from_seed_test(void) +{ + static const unsigned char seed[32] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F + }; + mldsa_key key1, key2; + unsigned char pk1[2600], pk2[2600], sk1[4900], sk2[4900]; + unsigned long pk1len, pk2len, sk1len, sk2len; + + XMEMSET(&key1, 0, sizeof(key1)); + XMEMSET(&key2, 0, sizeof(key2)); + + DO(mldsa_make_key_from_seed(LTC_MLDSA_44, seed, sizeof(seed), &key1)); + DO(mldsa_make_key_from_seed(LTC_MLDSA_44, seed, sizeof(seed), &key2)); + + pk1len = sizeof(pk1); + pk2len = sizeof(pk2); + sk1len = sizeof(sk1); + sk2len = sizeof(sk2); + DO(mldsa_export_raw(pk1, &pk1len, PK_PUBLIC, &key1)); + DO(mldsa_export_raw(pk2, &pk2len, PK_PUBLIC, &key2)); + DO(mldsa_export_raw(sk1, &sk1len, PK_PRIVATE, &key1)); + DO(mldsa_export_raw(sk2, &sk2len, PK_PRIVATE, &key2)); + + COMPARE_TESTVECTOR(pk1, pk1len, pk2, pk2len, "ML-DSA deterministic public key", 0); + COMPARE_TESTVECTOR(sk1, sk1len, sk2, sk2len, "ML-DSA deterministic private key", 0); + + SHOULD_FAIL(mldsa_make_key_from_seed(LTC_MLDSA_44, seed, sizeof(seed) - 1, &key2)); + + mldsa_free(&key1); + mldsa_free(&key2); + return CRYPT_OK; +} + +static int s_mldsa_openssl_verify_test(void) +{ + static const struct { + int alg; + const char *pubkey_hex; + const char *msg_hex; + const char *sig_hex; + } vectors[] = { + { LTC_MLDSA_44, mldsa_44_pubkey_hex, mldsa_44_msg_hex, mldsa_44_sig_hex }, + { LTC_MLDSA_65, mldsa_65_pubkey_hex, mldsa_65_msg_hex, mldsa_65_sig_hex }, + { LTC_MLDSA_87, mldsa_87_pubkey_hex, mldsa_87_msg_hex, mldsa_87_sig_hex } + }; + unsigned char pub[2600], msg[32], sig[4700]; + unsigned long publen, msglen, siglen; + unsigned long n; + + for (n = 0; n < sizeof(vectors) / sizeof(vectors[0]); n++) { + mldsa_key key; + int stat = 0; + + XMEMSET(&key, 0, sizeof(key)); + + publen = sizeof(pub); + msglen = sizeof(msg); + siglen = sizeof(sig); + DO(s_decode_hex(vectors[n].pubkey_hex, pub, &publen)); + DO(s_decode_hex(vectors[n].msg_hex, msg, &msglen)); + DO(s_decode_hex(vectors[n].sig_hex, sig, &siglen)); + + DO(mldsa_import_raw(pub, publen, PK_PUBLIC, vectors[n].alg, &key)); + DO(mldsa_verify(sig, siglen, msg, msglen, NULL, 0, &stat, &key)); + ENSURE(stat == 1); + + mldsa_free(&key); + } + + return CRYPT_OK; +} + +int pqc_mldsa_test(void) +{ + if (ltc_mp.name == NULL) return CRYPT_NOP; + + DO(s_mldsa_sizes_test()); + DO(s_mldsa_from_seed_test()); + DO(s_mldsa_openssl_verify_test()); + DO(s_mldsa_sign_verify(LTC_MLDSA_44)); + DO(s_mldsa_sign_verify(LTC_MLDSA_65)); + DO(s_mldsa_sign_verify(LTC_MLDSA_87)); + return CRYPT_OK; +} + +#else + +int pqc_mldsa_test(void) +{ + return CRYPT_NOP; +} + +#endif diff --git a/tests/pqc_mlkem_test.c b/tests/pqc_mlkem_test.c new file mode 100644 index 000000000..0c72ff174 --- /dev/null +++ b/tests/pqc_mlkem_test.c @@ -0,0 +1,340 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_test.h" + +#ifdef LTC_MLKEM + +/* OpenSSL 4.0.0 test vectors from test/evp_extra_test.c */ +static const char ml_kem_seed_hex[] = + "7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2d8626ed79d451140800e03b59b956f8210e556067407d13dc90fa9e8b872bfb8f"; + +static const char ml_kem_512_pubkey_hex[] = + "400865ed10b619aa5811139bc086825782b2b7124f757c83ae794444bc78a47896acf1262c81351077893bfc56f90449c2fa5f6e586dd37c0b9b581992638cb7" + "e7bcbbb99afe4781d80a50e69463fbd988722c3635423e27466c71dcc674527ccd728968cbcdc00c5c9035bb0af2c9922c7881a41dd2875273925131230f6ca5" + "9e9136b39f956c93b3b2d14c641b089e07d0a840c893ecd76bbf92c805456668d07c621491c5c054991a656f511619556eb97782e27a3c785124c70b0daba6c6" + "24d18e0f9793f96ba9e1599b17b30dccc0b4f3766a07b23b257309cd76aba072c2b9c9744394c6ab9cb6c54a97b5c57861a58dc0a03519832ee32a07654a070c" + "0c8c4e8648addc355f274fc6b92a087b3f9751923e44274f858c49caba72b65851b3adc48936955097cad9553f5a263f1844b52a020ff7ca89e881a01b95d957" + "a3153c0a5e0a1ccd66b1821a2b8632546e24c7cbbc4cb08808cac37f7da6b16f8aced052cdb2564948f1ab0f768a0d3286ccc7c3749c63c781530fa1ae670542" + "855004a645b522881ec1412bdae342085a9dd5f8126af96bbdb0c1af69a15562cb2a155a100309d1b641d08b2d4ed17bfbf0bc04265f9b10c108f850309504d7" + "72811bba8e2be16249aa737d879fc7fb255ee7a6a0a753bd93741c61658ec074f6e002b019345769113cc013ff7494ba8378b11a172260aaa53421bde03a3558" + "9d57e322fefa4100a4743926ab7d62258b87b31ccbb5e6b89cb10b271aa05d994bb5708b23ab327ecb93c0f3156869f0883da2064f795e0e2ab7d3c64d61d230" + "3fc3a29e1619923ca801e59fd752ca6e7649d303c9d20788e1214651b06995eb260c929a1344a849b25ca0a01f1eb52913686bba619e23714464031a78439287" + "fca78f4c0476223eea61b7f25a7ce42cca901b2aea129817894ba3470823854f3e5b28d86ba979e54671862d90470b1e7838972a81a48107d6ac0611406b21fb" + "cce1db7702ea9dd6ba6e40527b9dc663f3c93bad056dc28511f66c3e0b928db8879d22c592685cc775a6cd574ac3bce3b27591c821929076358a2200b377365f" + "7efb9e40c3bf0ff0432986ae4bc1a242ce9921aa9e22448819585dea308eb039"; + +static const char ml_kem_768_pubkey_hex[] = + "a8e651a1e685f22478a8954f007bc7711b930772c78f092e82878e3e937f367967532913a8d53dfdf4bfb1f8846746596705cf345142b972a3f16325c40c2952" + "a37b25897e5ef35fbaeb73a4acbeb6a0b89942ceb195531cfc0a07993954483e6cbc87c06aa74ff0cac5207e535b260aa98d1198c07da605c4d11020f6c9f7bb" + "68bb3456c73a01b710bc99d17739a51716aa01660c8b628b2f5602ba65f07ea993336e896e83f2c5731bbf03460c5b6c8afecb748ee391e98934a2c57d4d069f" + "50d88b30d6966f38c37bc649b82634ce7722645ccd625063364646d6d699db57b45eb67465e16de4d406a818b9eae1ca916a2594489708a43cea88b02a4c03d0" + "9b44815c97101caf5048bbcb247ae2366cdc254ba22129f45b3b0eb399ca91a303402830ec01db7b2ca480cf350409b216094b7b0c3ae33ce10a9124e89651ab" + "901ea253c8415bd7825f02bb229369af972028f22875ea55af16d3bc69f70c2ee8b75f28b47dd391f989ade314729c331fa04c1917b278c3eb602868512821ad" + "c825c64577ce1e63b1d9644a612948a3483c7f1b9a258000e30196944a403627609c76c7ea6b5de01764d24379117b9ea29848dc555c454bceae1ba5cc72c74a" + "b96b9c91b910d26b88b25639d4778ae26c7c6151a19c6cd7938454372465e4c5ec29245acb3db5379de3dabfa629a7c04a8353a8530c95acb732bb4bb81932bb" + "2ca7a848cd366801444abe23c83b366a87d6a3cf360924c002bae90af65c48060b3752f2badf1ab2722072554a5059753594e6a702761fc97684c8c4a7540a6b" + "07fbc9de87c974aa8809d928c7f4cbbf8045aea5bc667825fd05a521f1a4bf539210c7113bc37b3e58b0cbfc53c841cbb0371de2e511b989cb7c70c023366d78" + "f9c37ef047f8720be1c759a8d96b93f65a94114ffaf60d9a81795e995c71152a4691a5a602a9e1f3599e37c768c7bc108994c0669f3adc957d46b4b6256968e2" + "90d7892ea85464ee7a750f39c5e3152c2dfc56d8b0c924ba8a959a68096547f66423c838982a5794b9e1533771331a9a656c28828beb9126a60e95e8c5d90683" + "2c7710705576b1fb9507269ddaf8c95ce9719b2ca8dd112be10bcc9f4a37bd1b1eeeb33ecda76ae9f69a5d4b2923a86957671d619335be1c4c2c77ce87c41f98" + "a8cc466460fa300aaf5b301f0a1d09c88e65da4d8ee64f68c02189bbb3584baff716c85db654048a004333489393a07427cd3e217e6a345f6c2c2b13c27b3372" + "71c0b27b2dbaa00d237600b5b594e8cf2dd625ea76cf0ed899122c9796b4b0187004258049a477cd11d68c49b9a0e7b00bce8cac7864cbb375140084744c9306" + "2694ca795c4f40e7acc9c5a1884072d8c38dafb501ee4184dd5a819ec24ec1651261f962b17a7215aa4a748c15836c389137678204838d7195a85b4f98a1b574" + "c4cd7909cd1f833effd1485543229d3748d9b5cd6c17b9b3b84aef8bce13e683733659c79542d615782a71cdeee792bab51bdc4bbfe8308e663144ede8491830" + "ad98b4634f64aba8b9c042272653920f380c1a17ca87ced7aac41c82888793181a6f76e197b7b90ef90943bb3844912911d8551e5466c5767ab0bc61a1a3f736" + "162ec098a900b12dd8fabbfb3fe8cb1dc4e8315f2af0d32f0017ae136e19f028"; + +static const char ml_kem_1024_pubkey_hex[] = + "537911957c125148a87f41589cb222d0d19229e2cb55e1a044791e7ca61192a46460c3183d2bcd6de08a5e7651603acc349ca16cba18abb23a3e8c330d742159" + "8a6278ec7ebfabca0ef488b2290554753499c0452e453815309955b8150fa1a1e393386dc12fdb27b38c6745f2944016ec457f39b18d604a07a1abe07bc84405" + "0ffa8a06fa154a49d88fac775452d6a7c0e589bfb5c370c2c4b6201dda80c9ab2076ecc08b44522fda3326f033806dd2693f319739f40c4f42b24aca7098fb8f" + "f5f9ac20292d02b56ac746801acccc84863dee32878497b69438bf991776286650482c8d9d9587bc6a55b85c4d7fa74d02656b421c9e23e03a48d4b74425c26e" + "4a20dd9562a4da0793f3a352ccc0f18217d868c7f5002abe768b1fc73f05744e7cc28f10344062c10e08eccced3c1f7d392c01d979dd718d8398374665a16a98" + "70585c39d5589a50e133389c9b9a276c024260d9fc7711c81b6337b57da3c376d0cd74e14c73727b276656b9d8a4eb71896ff589d4b893e7110f3bb948ece291" + "dd86c0b7468a678c746980c12aa6b95e2b0cbe4331bb24a33a270153aa472c47312382ca365c5f35259d025746fc6595fe636c767510a69c1e8a176b7949958f" + "2697399497a2fc7364a12c8198295239c826cb5082086077282ed628651fc04c639b438522a9de309b14b086d6e923c551623bd72a733cb0dabc54a9416a99e7" + "2c9fda1cb3fb9ba06b8adb2422d68cadc553c98202a17656478ac044ef3456378abce9991e0141ba79094fa8f77a300805d2d32ffc62bf0ca4554c330c2bb704" + "2db35102f68b1a0062583865381c74dd913af70b26cf0923d0c4cb971692222552a8f4b788b4afd1341a9df415cf203900f5ccf7f65988949a75580d04963985" + "3100854b21f4018003502bb1ba95f556a5d67c7eb52410eba288a6d0635ca8a4f6d696d0a020c826938d34943c3808c79cc007768533216bc1b29da6c812eff3" + "340baa8d2e65344f09bd47894f5a3a4118715b3c5020679327f9189f7e10856b238bb9b0ab4ca85abf4b21f5c76bccd71850b22e045928276a0f2e951db0707c" + "6a116dc19113fa762dc5f20bd5d2ab5be71744dc9cbdb51ea757963aac56a90a0d8023bed1f5cae8a64da047279b353a096a835b0b2b023b6aa048989233079a" + "eb467e522fa27a5822921e5c551b4f537536e46f3a6a97e72c3b063104e09a040598940d872f6d871f5ef9b4355073b54769e45454e6a0819599408621ab4413" + "b35507b0df578ce2d511d52058d5749df38b29d6cc58870caf92f69a75161406e71c5ff92451a77522b8b2967a2d58a49a81661aa65ac09b08c9fe45abc3851f" + "99c730c45003aca2bf0f8424a19b7408a537d541c16f5682bfe3a7faea564f1298611a7f5f60922ba19de73b1917f1853273555199a649318b50773345c99746" + "0856972acb43fc81ab6321b1c33c2bb5098bd489d696a0f70679c1213873d08bdad42844927216047205633212310ee9a06cb10016c805503c341a36d87e5607" + "2eabe23731e34af7e2328f85cdb370ccaf00515b64c9c54bc837578447aacfaed5969aa351e7da4efa7b115c4c51f4a699779850295ca72d781ad41bc680532b" + "89e710e2189eb3c50817ba255c7474c95ca9110cc43b8ba8e682c7fb7b0fdc265c0483a65ca4514ee4b832aac5800c3b08e74f563951c1fbb210353efa1aa866" + "856bc1e034733b0485dab1d020c6bf765ff60b3b801984a90c2fe970bf1de97004a6cf44b4984ab58258b4af71221cd17530a700c32959c9436344b5316f09cc" + "ca7029a230d639dcb022d8ba79ba91cd6ab12ae1579c50c7bb10e30301a65cae3101d40c7ba927bb553148d1647024d4a06c8166d0b0b81269b7d5f4b34fb022" + "f69152f514004a7c685368552343bb60360fbb9945edf446d345bdcaa7455c74ba0a551e184620fef97688773d50b6433ca7a7ac5cb6b7f671a15376e5a6747a" + "623fa7bc6630373f5b1b512690a661377870a60a7a189683f9b0cf0466e1f750762631c4ab09f505c42dd28633569472735442851e321616d4009810777b6bd4" + "6fa7224461a5cc27405dfbac0d39b002cab33433f2a86eb8ce91c134a6386f860a1994eb4b6875a46d195581d173854b53d2293df3e9a822756cd8f212b325ca" + "29b4f9f8cfbadf2e41869abfbad10738ad04cc752bc20c394746850e0c4847db"; + +static int s_decode_hex(const char *hex, unsigned char *buf, unsigned long *len) +{ + return base16_decode(hex, XSTRLEN(hex), buf, len); +} + +static int s_mlkem_keygen_encaps_decaps(int alg) +{ + mlkem_key key, pubkey, imported_priv, imported_pub; + unsigned char ct[1600], ss1[32], ss2[32]; + unsigned char der_buf[4096], pk_buf[1600], sk_buf[3200], cmp_buf[3200]; + unsigned long ctlen, derlen, sslen, pklen, sklen, cmplen; + int prng_idx; + + prng_idx = find_prng("yarrow"); + XMEMSET(&key, 0, sizeof(key)); + XMEMSET(&pubkey, 0, sizeof(pubkey)); + XMEMSET(&imported_priv, 0, sizeof(imported_priv)); + XMEMSET(&imported_pub, 0, sizeof(imported_pub)); + + /* keygen */ + DO(mlkem_make_key(&yarrow_prng, prng_idx, alg, &key)); + ENSURE(key.type == PK_PRIVATE); + + /* export/import private key in PKCS#8 format */ + derlen = sizeof(der_buf); + DO(mlkem_export(der_buf, &derlen, PK_PRIVATE | PK_STD, &key)); + DO(mlkem_import_pkcs8(der_buf, derlen, NULL, &imported_priv)); + + sklen = sizeof(sk_buf); + DO(mlkem_export_raw(sk_buf, &sklen, PK_PRIVATE, &key)); + cmplen = sizeof(cmp_buf); + DO(mlkem_export_raw(cmp_buf, &cmplen, PK_PRIVATE, &imported_priv)); + COMPARE_TESTVECTOR(cmp_buf, cmplen, sk_buf, sklen, "ML-KEM private std round-trip", alg); + + /* export/import public key */ + pklen = sizeof(pk_buf); + DO(mlkem_export_raw(pk_buf, &pklen, PK_PUBLIC, &key)); + DO(mlkem_import_raw(pk_buf, pklen, PK_PUBLIC, alg, &pubkey)); + ENSURE(pubkey.type == PK_PUBLIC); + + cmplen = sizeof(cmp_buf); + DO(mlkem_export_raw(cmp_buf, &cmplen, PK_PUBLIC, &imported_priv)); + COMPARE_TESTVECTOR(cmp_buf, cmplen, pk_buf, pklen, "ML-KEM public from imported private", alg); + + /* export/import public key in SubjectPublicKeyInfo format */ + derlen = sizeof(der_buf); + DO(mlkem_export(der_buf, &derlen, PK_PUBLIC | PK_STD, &key)); + DO(mlkem_import(der_buf, derlen, &imported_pub)); + cmplen = sizeof(cmp_buf); + DO(mlkem_export_raw(cmp_buf, &cmplen, PK_PUBLIC, &imported_pub)); + COMPARE_TESTVECTOR(cmp_buf, cmplen, pk_buf, pklen, "ML-KEM public std round-trip", alg); + + /* encaps/decaps with exported/imported std keys */ + ctlen = sizeof(ct); + sslen = sizeof(ss1); + DO(mlkem_encaps(ct, &ctlen, ss1, &sslen, &yarrow_prng, prng_idx, &imported_pub)); + ENSURE(sslen == 32); + sslen = sizeof(ss2); + DO(mlkem_decaps(ss2, &sslen, ct, ctlen, &imported_priv)); + COMPARE_TESTVECTOR(ss1, 32, ss2, 32, "ML-KEM std export/import", alg); + + /* encaps with public key */ + ctlen = sizeof(ct); + sslen = sizeof(ss1); + DO(mlkem_encaps(ct, &ctlen, ss1, &sslen, &yarrow_prng, prng_idx, &pubkey)); + ENSURE(sslen == 32); + + /* decaps with private key */ + sslen = sizeof(ss2); + DO(mlkem_decaps(ss2, &sslen, ct, ctlen, &key)); + ENSURE(sslen == 32); + + /* shared secrets must match */ + COMPARE_TESTVECTOR(ss1, 32, ss2, 32, "ML-KEM shared secret", alg); + + /* decaps with corrupted ciphertext must produce different ss (implicit rejection) */ + ct[0] ^= 1; + sslen = sizeof(ss2); + DO(mlkem_decaps(ss2, &sslen, ct, ctlen, &key)); + ENSURE(XMEMCMP(ss1, ss2, 32) != 0); + + /* export/import private key round-trip */ + sklen = sizeof(sk_buf); + DO(mlkem_export_raw(sk_buf, &sklen, PK_PRIVATE, &key)); + mlkem_free(&key); + DO(mlkem_import_raw(sk_buf, sklen, PK_PRIVATE, alg, &key)); + ENSURE(key.type == PK_PRIVATE); + + /* decaps still works after import (undo corruption) */ + ct[0] ^= 1; + sslen = sizeof(ss2); + DO(mlkem_decaps(ss2, &sslen, ct, ctlen, &key)); + COMPARE_TESTVECTOR(ss1, 32, ss2, 32, "ML-KEM decaps after reimport", alg); + + mlkem_free(&key); + mlkem_free(&pubkey); + mlkem_free(&imported_priv); + mlkem_free(&imported_pub); + return CRYPT_OK; +} + +static int s_mlkem_sizes_test(void) +{ + unsigned long pk, sk, ct, ss; + + DO(mlkem_get_sizes(LTC_MLKEM_512, &pk, &sk, &ct, &ss)); + ENSURE(pk == 800 && sk == 1632 && ct == 768 && ss == 32); + + DO(mlkem_get_sizes(LTC_MLKEM_768, &pk, &sk, &ct, &ss)); + ENSURE(pk == 1184 && sk == 2400 && ct == 1088 && ss == 32); + + DO(mlkem_get_sizes(LTC_MLKEM_1024, &pk, &sk, &ct, &ss)); + ENSURE(pk == 1568 && sk == 3168 && ct == 1568 && ss == 32); + + SHOULD_FAIL(mlkem_get_sizes(99, &pk, &sk, &ct, &ss)); + + /* nullable pointers */ + DO(mlkem_get_sizes(LTC_MLKEM_768, NULL, NULL, NULL, &ss)); + ENSURE(ss == 32); + + return CRYPT_OK; +} + +static int s_mlkem_from_seed_test(void) +{ + static const unsigned char seed[64] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F + }; + mlkem_key key1, key2; + unsigned char pk1[1600], pk2[1600], sk1[3200], sk2[3200]; + unsigned long pk1len, pk2len, sk1len, sk2len; + + XMEMSET(&key1, 0, sizeof(key1)); + XMEMSET(&key2, 0, sizeof(key2)); + + DO(mlkem_make_key_from_seed(LTC_MLKEM_512, seed, sizeof(seed), &key1)); + DO(mlkem_make_key_from_seed(LTC_MLKEM_512, seed, sizeof(seed), &key2)); + + pk1len = sizeof(pk1); + pk2len = sizeof(pk2); + sk1len = sizeof(sk1); + sk2len = sizeof(sk2); + DO(mlkem_export_raw(pk1, &pk1len, PK_PUBLIC, &key1)); + DO(mlkem_export_raw(pk2, &pk2len, PK_PUBLIC, &key2)); + DO(mlkem_export_raw(sk1, &sk1len, PK_PRIVATE, &key1)); + DO(mlkem_export_raw(sk2, &sk2len, PK_PRIVATE, &key2)); + + COMPARE_TESTVECTOR(pk1, pk1len, pk2, pk2len, "ML-KEM deterministic public key", 0); + COMPARE_TESTVECTOR(sk1, sk1len, sk2, sk2len, "ML-KEM deterministic private key", 0); + + SHOULD_FAIL(mlkem_make_key_from_seed(LTC_MLKEM_512, seed, sizeof(seed) - 1, &key2)); + + mlkem_free(&key1); + mlkem_free(&key2); + return CRYPT_OK; +} + +static int s_mlkem_openssl_seed_test(void) +{ + static const struct { + int alg; + const char *pubkey_hex; + } vectors[] = { + { LTC_MLKEM_512, ml_kem_512_pubkey_hex }, + { LTC_MLKEM_768, ml_kem_768_pubkey_hex }, + { LTC_MLKEM_1024, ml_kem_1024_pubkey_hex } + }; + unsigned char seed[64], pubkey[1600], expected[1600]; + unsigned long seedlen, pklen, explen; + unsigned long n; + + seedlen = sizeof(seed); + DO(s_decode_hex(ml_kem_seed_hex, seed, &seedlen)); + ENSURE(seedlen == sizeof(seed)); + + for (n = 0; n < sizeof(vectors) / sizeof(vectors[0]); n++) { + mlkem_key key; + XMEMSET(&key, 0, sizeof(key)); + + DO(mlkem_make_key_from_seed(vectors[n].alg, seed, seedlen, &key)); + + pklen = sizeof(pubkey); + DO(mlkem_export_raw(pubkey, &pklen, PK_PUBLIC, &key)); + + explen = sizeof(expected); + DO(s_decode_hex(vectors[n].pubkey_hex, expected, &explen)); + COMPARE_TESTVECTOR(pubkey, pklen, expected, explen, "ML-KEM OpenSSL seed public key", vectors[n].alg); + + mlkem_free(&key); + } + + return CRYPT_OK; +} + +static int s_mlkem_error_test(void) +{ + mlkem_key key; + unsigned char ct[1600], ss[32]; + unsigned long ctlen, sslen; + int prng_idx; + + prng_idx = find_prng("yarrow"); + + /* invalid alg */ + SHOULD_FAIL(mlkem_make_key(&yarrow_prng, prng_idx, 99, &key)); + + /* encaps with private key is OK (uses embedded pk) */ + DO(mlkem_make_key(&yarrow_prng, prng_idx, LTC_MLKEM_512, &key)); + ctlen = sizeof(ct); + sslen = sizeof(ss); + DO(mlkem_encaps(ct, &ctlen, ss, &sslen, &yarrow_prng, prng_idx, &key)); + + /* decaps with public-only key must fail */ + { + mlkem_key pubkey; + unsigned char pk_buf[1600]; + unsigned long pklen = sizeof(pk_buf); + DO(mlkem_export_raw(pk_buf, &pklen, PK_PUBLIC, &key)); + DO(mlkem_import_raw(pk_buf, pklen, PK_PUBLIC, LTC_MLKEM_512, &pubkey)); + sslen = sizeof(ss); + SHOULD_FAIL(mlkem_decaps(ss, &sslen, ct, ctlen, &pubkey)); + mlkem_free(&pubkey); + } + + /* wrong ciphertext length */ + sslen = sizeof(ss); + SHOULD_FAIL(mlkem_decaps(ss, &sslen, ct, ctlen - 1, &key)); + + /* buffer too small */ + ctlen = 1; + sslen = sizeof(ss); + SHOULD_FAIL_WITH(mlkem_encaps(ct, &ctlen, ss, &sslen, &yarrow_prng, prng_idx, &key), + CRYPT_BUFFER_OVERFLOW); + + mlkem_free(&key); + return CRYPT_OK; +} + +int pqc_mlkem_test(void) +{ + if (ltc_mp.name == NULL) return CRYPT_NOP; + + DO(s_mlkem_sizes_test()); + DO(s_mlkem_from_seed_test()); + DO(s_mlkem_openssl_seed_test()); + DO(s_mlkem_error_test()); + DO(s_mlkem_keygen_encaps_decaps(LTC_MLKEM_512)); + DO(s_mlkem_keygen_encaps_decaps(LTC_MLKEM_768)); + DO(s_mlkem_keygen_encaps_decaps(LTC_MLKEM_1024)); + return CRYPT_OK; +} + +#else + +int pqc_mlkem_test(void) +{ + return CRYPT_NOP; +} + +#endif diff --git a/tests/pqc_slhdsa_test.c b/tests/pqc_slhdsa_test.c new file mode 100644 index 000000000..7fbb502c2 --- /dev/null +++ b/tests/pqc_slhdsa_test.c @@ -0,0 +1,294 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_test.h" + +#ifdef LTC_SLHDSA + +/* OpenSSL 4.0.0 test vectors from test/slh_dsa.inc */ +static const char slh_dsa_sha2_128s_0_keygen_priv_hex[] = + "aa9cc7dca491fc86bcb15a709a15e9b3905c800b6e2fb9b54b6b050ee5e4de9afa5464d1c661fed38b2a51ca3eae71bacae3d1865215e3d3850e8c1b8292bf42"; + +static const char slh_dsa_sha2_128f_0_keygen_priv_hex[] = + "e2bdaa37c8cffe5e8d5676c23267890c31441758f573285881cdc82ab911dd8472dc8d26df6ef708f4c41af9fd04b65a8927927229891d47a60d67ecef3d2c17"; + +static const char slh_dsa_sha2_192s_0_keygen_priv_hex[] = + "442e446e73330afb98704656328f4dd7334f8a9ab4d92cbe790f91c2e92a81afee0a7ec45a3d609346276f5a328755a17dd41608f59e492668d81d03441394fe" + "7a8e7e58705d7632ba8bc66d04c99ee5c721e4ff4bbe7815ccf923e81e10c475"; + +static const char slh_dsa_sha2_192f_0_keygen_priv_hex[] = + "942dd588b0e0636060b1023baf1df36002b9d3c7256904f948596f0f2f17505585f022423433b3a3ef50977b98b01e8e3e1d7dcf880c2ea3c8872122a996d5d6" + "233bdfbd57fa641fad3c81bbe6778b1f788195131b3fca91854ff3b075bf0009"; + +static const char slh_dsa_sha2_256s_0_keygen_priv_hex[] = + "ae6ca8664ec0b9179d4e33c4defe01fcd589f60ba4502fe7416f2acd96e139f13fda2069147f44eabd5bbf29c74a20cb0f0cc2a12bab5834b773530af504900a" + "134d5ed3c60b46344a84a45d4683b1ac55fb22886ba9478ea9ca93f27b9aa2c27c5c9908f086e57956f85de84b438ef1f082cd176dff3c5b8be710bc8699a143"; + +static const char slh_dsa_sha2_256f_0_keygen_priv_hex[] = + "37d1806dd090353064a982276aebd20e7318f36b17ec5209d4006651760ca043896630d51c45a8f7c1da31192f41204deb71bbc4fb47700a91ec47bb4acf3a38" + "dabbd00112520e60061da23f4c83a5c475a0ad3ab75f59e5c7b8ce2430deb480c07849dd9f8d993dce5685d0840134bd11592055f74cde3aa9e7d25b33c31067"; + +static const char slh_dsa_shake_128s_0_keygen_priv_hex[] = + "ecd0a05696c2ec6bfe85b8b1b2022486bfd8732b1a42cea236e9822aa9e724e637d664792198176c12e8121ccf69e684fcf6ffe2a04243dc3e8ed3ee6e44cdef"; + +static const char slh_dsa_shake_128f_0_keygen_priv_hex[] = + "bbc74306f75dc2daf7372b3c9841a4d6852c17b459f1692b8e9a1a0dace5ba26380c99304a0ddd32f344b95144e1fdef60bbc2340e08770fb41a80a76cb08e34"; + +static const char slh_dsa_shake_192s_0_keygen_priv_hex[] = + "2d5748b1acda8299e2e905545d2e66dfcec02461bc3673dd9d830416b1b82a665dd435a3f3a8e2124df59a0e2bc2ec73633ff65c724ae17045c094617549081c" + "940f2ef4d4a10e7559c7503fe1e96fb67b0e32acdcf712fbef610f8d21daac86"; + +static const char slh_dsa_shake_192f_0_keygen_priv_hex[] = + "3b7889d254f5ad87882dacbf3c58495667401601ec4739797e935cbc27f3d7cd627b611cbef7546c7f27751e18155cc4266b6fb56bd0d922e0482700a4280cc1" + "f07052804a8f46fded3954ba0a9da45d0d18867437777f60211bb9cd03a60d4b"; + +static const char slh_dsa_shake_256s_0_keygen_priv_hex[] = + "a653918fa557b5250d11e96a74f5d8c62b5ff67152acf227aaf4bf5211aa600e961b4e679ceb9d4e24df86ed22f405d8ede5623672f4737fc2fb65f8bf3b556c" + "315a5e795b701676e6b8309c89cc6ad0c3d69ff4f7f432dc61329fbb1be6069f0887b1a8f1b3a8b9770a0871630e46dd0479c5bd123e8eeb6be70f2999c466a1"; + +static const char slh_dsa_shake_256f_0_keygen_priv_hex[] = + "d50f77713cf59193fe5f10b8aaf1876b0d3e7e4181ed3fae346876269801758436c22b81940403157446d44f04c09fd28df72c6d4021b271544055783081b7c0" + "46d2ac50751a0c71ec850bb7d16a679a66901eee05389d4615940efd89c0182fdebcfbf3527cc768c5ec6cb5b6cc10a674390745d8612d0920187df658d3b7ef"; + +static int s_decode_hex(const char *hex, unsigned char *buf, unsigned long *len) +{ + return base16_decode(hex, XSTRLEN(hex), buf, len); +} + +static int s_slhdsa_sign_verify(int alg) +{ + slhdsa_key key, pubkey, imported_priv, imported_pub; + const unsigned char msg[] = "test message for SLH-DSA"; + unsigned char *sig, *pk_buf, *sk_buf, *std_buf, *cmp_buf; + unsigned long siglen, sig_sz, pklen, pk_sz, sklen, sk_sz, stdlen, std_sz, cmplen; + int stat, prng_idx; + + prng_idx = find_prng("yarrow"); + + DO(slhdsa_get_sizes(alg, &pk_sz, &sk_sz, &sig_sz)); + + sig = XMALLOC(sig_sz); + pk_buf = XMALLOC(pk_sz); + sk_buf = XMALLOC(sk_sz); + std_sz = sk_sz + 128uL; + std_buf = XMALLOC(std_sz); + cmp_buf = XMALLOC(sk_sz); + ENSURE(sig != NULL && pk_buf != NULL && sk_buf != NULL && std_buf != NULL && cmp_buf != NULL); + XMEMSET(&key, 0, sizeof(key)); + XMEMSET(&pubkey, 0, sizeof(pubkey)); + XMEMSET(&imported_priv, 0, sizeof(imported_priv)); + XMEMSET(&imported_pub, 0, sizeof(imported_pub)); + + /* keygen */ + DO(slhdsa_make_key(&yarrow_prng, prng_idx, alg, &key)); + ENSURE(key.type == PK_PRIVATE); + + /* export/import private key in PKCS#8 format */ + stdlen = std_sz; + DO(slhdsa_export(std_buf, &stdlen, PK_PRIVATE | PK_STD, &key)); + DO(slhdsa_import_pkcs8(std_buf, stdlen, NULL, &imported_priv)); + + /* sign */ + siglen = sig_sz; + DO(slhdsa_sign(msg, sizeof(msg), sig, &siglen, NULL, 0, + &yarrow_prng, prng_idx, &key)); + ENSURE(siglen == sig_sz); + + sklen = sk_sz; + DO(slhdsa_export_raw(sk_buf, &sklen, PK_PRIVATE, &key)); + cmplen = sk_sz; + DO(slhdsa_export_raw(cmp_buf, &cmplen, PK_PRIVATE, &imported_priv)); + COMPARE_TESTVECTOR(cmp_buf, cmplen, sk_buf, sklen, "SLH-DSA private std round-trip", alg); + + /* export/import public key */ + pklen = pk_sz; + DO(slhdsa_export_raw(pk_buf, &pklen, PK_PUBLIC, &key)); + DO(slhdsa_import_raw(pk_buf, pklen, PK_PUBLIC, alg, &pubkey)); + + cmplen = pk_sz; + DO(slhdsa_export_raw(cmp_buf, &cmplen, PK_PUBLIC, &imported_priv)); + COMPARE_TESTVECTOR(cmp_buf, cmplen, pk_buf, pklen, "SLH-DSA public from imported private", alg); + + /* export/import public key in SubjectPublicKeyInfo format */ + stdlen = std_sz; + DO(slhdsa_export(std_buf, &stdlen, PK_PUBLIC | PK_STD, &key)); + DO(slhdsa_import(std_buf, stdlen, &imported_pub)); + cmplen = pk_sz; + DO(slhdsa_export_raw(cmp_buf, &cmplen, PK_PUBLIC, &imported_pub)); + COMPARE_TESTVECTOR(cmp_buf, cmplen, pk_buf, pklen, "SLH-DSA public std round-trip", alg); + + /* sign/verify with exported/imported std keys */ + siglen = sig_sz; + DO(slhdsa_sign(msg, sizeof(msg), sig, &siglen, NULL, 0, + &yarrow_prng, prng_idx, &imported_priv)); + stat = 0; + DO(slhdsa_verify(sig, siglen, msg, sizeof(msg), NULL, 0, &stat, &imported_pub)); + ENSURE(stat == 1); + + /* verify */ + stat = 0; + DO(slhdsa_verify(sig, siglen, msg, sizeof(msg), NULL, 0, &stat, &pubkey)); + ENSURE(stat == 1); + + /* corrupted sig must fail */ + sig[0] ^= 1; + stat = 1; + DO(slhdsa_verify(sig, siglen, msg, sizeof(msg), NULL, 0, &stat, &pubkey)); + ENSURE(stat == 0); + + /* export/import private key round-trip */ + sklen = sk_sz; + DO(slhdsa_export_raw(sk_buf, &sklen, PK_PRIVATE, &key)); + slhdsa_free(&key); + DO(slhdsa_import_raw(sk_buf, sklen, PK_PRIVATE, alg, &key)); + + /* sign again after reimport */ + sig[0] ^= 1; + siglen = sig_sz; + DO(slhdsa_sign(msg, sizeof(msg), sig, &siglen, NULL, 0, + &yarrow_prng, prng_idx, &key)); + stat = 0; + DO(slhdsa_verify(sig, siglen, msg, sizeof(msg), NULL, 0, &stat, &pubkey)); + ENSURE(stat == 1); + + slhdsa_free(&key); + slhdsa_free(&pubkey); + slhdsa_free(&imported_priv); + slhdsa_free(&imported_pub); + XFREE(sig); + XFREE(pk_buf); + XFREE(sk_buf); + XFREE(std_buf); + XFREE(cmp_buf); + return CRYPT_OK; +} + +static int s_slhdsa_sizes_test(void) +{ + unsigned long pk, sk, sig; + + /* SHA-2 variants */ + DO(slhdsa_get_sizes(LTC_SLHDSA_SHA2_128S, &pk, &sk, &sig)); + ENSURE(pk == 32 && sk == 64 && sig == 7856); + DO(slhdsa_get_sizes(LTC_SLHDSA_SHA2_128F, &pk, &sk, &sig)); + ENSURE(pk == 32 && sk == 64 && sig == 17088); + DO(slhdsa_get_sizes(LTC_SLHDSA_SHA2_192S, &pk, &sk, &sig)); + ENSURE(pk == 48 && sk == 96 && sig == 16224); + DO(slhdsa_get_sizes(LTC_SLHDSA_SHA2_192F, &pk, &sk, &sig)); + ENSURE(pk == 48 && sk == 96 && sig == 35664); + DO(slhdsa_get_sizes(LTC_SLHDSA_SHA2_256S, &pk, &sk, &sig)); + ENSURE(pk == 64 && sk == 128 && sig == 29792); + DO(slhdsa_get_sizes(LTC_SLHDSA_SHA2_256F, &pk, &sk, &sig)); + ENSURE(pk == 64 && sk == 128 && sig == 49856); + + /* SHAKE variants */ + DO(slhdsa_get_sizes(LTC_SLHDSA_SHAKE_128S, &pk, &sk, &sig)); + ENSURE(pk == 32 && sk == 64 && sig == 7856); + DO(slhdsa_get_sizes(LTC_SLHDSA_SHAKE_128F, &pk, &sk, &sig)); + ENSURE(pk == 32 && sk == 64 && sig == 17088); + DO(slhdsa_get_sizes(LTC_SLHDSA_SHAKE_192S, &pk, &sk, &sig)); + ENSURE(pk == 48 && sk == 96 && sig == 16224); + DO(slhdsa_get_sizes(LTC_SLHDSA_SHAKE_192F, &pk, &sk, &sig)); + ENSURE(pk == 48 && sk == 96 && sig == 35664); + DO(slhdsa_get_sizes(LTC_SLHDSA_SHAKE_256S, &pk, &sk, &sig)); + ENSURE(pk == 64 && sk == 128 && sig == 29792); + DO(slhdsa_get_sizes(LTC_SLHDSA_SHAKE_256F, &pk, &sk, &sig)); + ENSURE(pk == 64 && sk == 128 && sig == 49856); + + SHOULD_FAIL(slhdsa_get_sizes(99, &pk, &sk, &sig)); + + return CRYPT_OK; +} + +static int s_slhdsa_openssl_keygen_test(void) +{ + static const struct { + int alg; + const char *priv_hex; + } vectors[] = { + { LTC_SLHDSA_SHA2_128S, slh_dsa_sha2_128s_0_keygen_priv_hex }, + { LTC_SLHDSA_SHA2_128F, slh_dsa_sha2_128f_0_keygen_priv_hex }, + { LTC_SLHDSA_SHA2_192S, slh_dsa_sha2_192s_0_keygen_priv_hex }, + { LTC_SLHDSA_SHA2_192F, slh_dsa_sha2_192f_0_keygen_priv_hex }, + { LTC_SLHDSA_SHA2_256S, slh_dsa_sha2_256s_0_keygen_priv_hex }, + { LTC_SLHDSA_SHA2_256F, slh_dsa_sha2_256f_0_keygen_priv_hex }, + { LTC_SLHDSA_SHAKE_128S, slh_dsa_shake_128s_0_keygen_priv_hex }, + { LTC_SLHDSA_SHAKE_128F, slh_dsa_shake_128f_0_keygen_priv_hex }, + { LTC_SLHDSA_SHAKE_192S, slh_dsa_shake_192s_0_keygen_priv_hex }, + { LTC_SLHDSA_SHAKE_192F, slh_dsa_shake_192f_0_keygen_priv_hex }, + { LTC_SLHDSA_SHAKE_256S, slh_dsa_shake_256s_0_keygen_priv_hex }, + { LTC_SLHDSA_SHAKE_256F, slh_dsa_shake_256f_0_keygen_priv_hex } + }; + unsigned char sk[128], pk[64], expected[128]; + unsigned long sklen, pklen, explen; + unsigned long n; + + for (n = 0; n < sizeof(vectors) / sizeof(vectors[0]); n++) { + slhdsa_key key; + XMEMSET(&key, 0, sizeof(key)); + + explen = sizeof(expected); + DO(s_decode_hex(vectors[n].priv_hex, expected, &explen)); + + DO(slhdsa_import_raw(expected, explen, PK_PRIVATE, vectors[n].alg, &key)); + + sklen = sizeof(sk); + DO(slhdsa_export_raw(sk, &sklen, PK_PRIVATE, &key)); + COMPARE_TESTVECTOR(sk, sklen, expected, explen, "SLH-DSA OpenSSL private key", vectors[n].alg); + + pklen = sizeof(pk); + DO(slhdsa_export_raw(pk, &pklen, PK_PUBLIC, &key)); + COMPARE_TESTVECTOR(pk, pklen, expected + explen / 2, explen / 2, "SLH-DSA OpenSSL public key", vectors[n].alg); + + slhdsa_free(&key); + } + + return CRYPT_OK; +} + +int pqc_slhdsa_test(void) +{ + if (ltc_mp.name == NULL) return CRYPT_NOP; + + DO(s_slhdsa_sizes_test()); + DO(s_slhdsa_openssl_keygen_test()); + /* All 6 fast variants (covers both SHA-2 and SHAKE at all security levels) */ + DO(s_slhdsa_sign_verify(LTC_SLHDSA_SHA2_128F)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_SHA2_192F)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_SHA2_256F)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_SHAKE_128F)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_SHAKE_192F)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_SHAKE_256F)); + /* One small variant to verify S-parameter code paths */ + DO(s_slhdsa_sign_verify(LTC_SLHDSA_SHAKE_128S)); + /* HashSLH-DSA fast variants cover SHA-256, SHA-512, SHAKE128, and SHAKE256 pre-hash paths */ + DO(s_slhdsa_sign_verify(LTC_SLHDSA_HASH_SHA2_128F_WITH_SHA256)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_HASH_SHA2_192F_WITH_SHA512)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_HASH_SHA2_256F_WITH_SHA512)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_HASH_SHAKE_128F_WITH_SHAKE128)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_HASH_SHAKE_192F_WITH_SHAKE256)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_HASH_SHAKE_256F_WITH_SHAKE256)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_HASH_SHAKE_128S_WITH_SHAKE128)); +#ifdef LTC_SLHDSA_TEST_SLOW + /* Remaining small variants (very slow) */ + DO(s_slhdsa_sign_verify(LTC_SLHDSA_SHA2_128S)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_SHA2_192S)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_SHA2_256S)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_SHAKE_192S)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_SHAKE_256S)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_HASH_SHA2_128S_WITH_SHA256)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_HASH_SHA2_192S_WITH_SHA512)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_HASH_SHA2_256S_WITH_SHA512)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_HASH_SHAKE_192S_WITH_SHAKE256)); + DO(s_slhdsa_sign_verify(LTC_SLHDSA_HASH_SHAKE_256S_WITH_SHAKE256)); +#endif + return CRYPT_OK; +} + +#else + +int pqc_slhdsa_test(void) +{ + return CRYPT_NOP; +} + +#endif diff --git a/tests/sources.cmake b/tests/sources.cmake index ae348a644..f53d378d6 100644 --- a/tests/sources.cmake +++ b/tests/sources.cmake @@ -28,6 +28,9 @@ pkcs_1_emsa_test.c pkcs_1_oaep_test.c pkcs_1_pss_test.c pkcs_1_test.c +pqc_mldsa_test.c +pqc_mlkem_test.c +pqc_slhdsa_test.c prng_test.c rotate_test.c rsa_test.c diff --git a/tests/test.c b/tests/test.c index a26604ec4..8902c093c 100644 --- a/tests/test.c +++ b/tests/test.c @@ -37,6 +37,9 @@ static const test_function test_functions[] = LTC_TEST_FN(file_test), LTC_TEST_FN(multi_test), LTC_TEST_FN(pem_test), + LTC_TEST_FN(pqc_mlkem_test), + LTC_TEST_FN(pqc_mldsa_test), + LTC_TEST_FN(pqc_slhdsa_test), LTC_TEST_FN(deprecated_test), /* keep the prng_test always at the end as * it has to be handled specially when diff --git a/tests/tomcrypt_test.h b/tests/tomcrypt_test.h index 747ede567..06b1655a4 100644 --- a/tests/tomcrypt_test.h +++ b/tests/tomcrypt_test.h @@ -48,6 +48,9 @@ int scrypt_test(void); int no_null_termination_check_test(void); int pk_oid_test(void); int deprecated_test(void); +int pqc_mlkem_test(void); +int pqc_mldsa_test(void); +int pqc_slhdsa_test(void); #ifdef LTC_PKCS_1 struct ltc_prng_descriptor* no_prng_desc_get(void);