1 /* 2 * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #ifndef OPENSSL_HEADER_ML_KEM_H 11 # define OPENSSL_HEADER_ML_KEM_H 12 # pragma once 13 14 # include <openssl/e_os2.h> 15 # include <openssl/bio.h> 16 # include <openssl/core_dispatch.h> 17 # include <crypto/evp.h> 18 19 # define ML_KEM_DEGREE 256 20 /* 21 * With (q-1) an odd multiple of 256, and 17 ("zeta") as a primitive 256th root 22 * of unity, the polynomial (X^256+1) splits in Z_q[X] into 128 irreducible 23 * quadratic factors of the form (X^2 - zeta^(2i + 1)). This is used to 24 * implement efficient multiplication in the ring R_q via the "NTT" transform. 25 */ 26 # define ML_KEM_PRIME (ML_KEM_DEGREE * 13 + 1) 27 28 /* 29 * Various ML-KEM primitives need random input, 32-bytes at a time. Key 30 * generation consumes two random values (d, z) with "d" plus the rank (domain 31 * separation) further expanded to two derived seeds "rho" and "sigma", with 32 * "rho" used to generate the public matrix "A", and sigma to generate the 33 * private vector "s" and error vector "e". 34 * 35 * Encapsulation also consumes one random value m, that is 32-bytes long. The 36 * resulting shared secret "K" (also 32 bytes) and an internal random value "r" 37 * are derived from "m" concatenated with a digest of the received public key. 38 * Use of the public key hash means that the derived shared secret is 39 * "contributary", it uses randomness from both parties. 40 * 41 * The seed "rho" is appended to the public key and allows the recipient of the 42 * public key to re-compute the matrix "A" when performing encapsulation. 43 * 44 * Note that the matrix "m" we store in the public key is the transpose of the 45 * "A" matrix from FIPS 203! 46 */ 47 # define ML_KEM_RANDOM_BYTES 32 /* rho, sigma, ... */ 48 # define ML_KEM_SEED_BYTES (ML_KEM_RANDOM_BYTES * 2) /* Keygen (d, z) */ 49 50 # define ML_KEM_PKHASH_BYTES 32 /* Salts the shared-secret */ 51 # define ML_KEM_SHARED_SECRET_BYTES 32 52 53 # if ML_KEM_PKHASH_BYTES != ML_KEM_RANDOM_BYTES 54 # error "unexpected ML-KEM public key hash size" 55 # endif 56 57 /*- 58 * The ML-KEM specification can be found in 59 * https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf 60 * 61 * Section 8, Table 2, lists the parameters for the three variants: 62 * 63 * Variant n q k eta1 eta2 du dv secbits 64 * ---------- --- ---- - ---- ---- -- -- ------- 65 * ML-KEM-512 256 3329 2 3 2 10 4 128 66 * ML-KEM-768 256 3329 3 2 2 10 4 192 67 * ML-KEM-1024 256 3329 4 2 2 11 5 256 68 * 69 * where: 70 * 71 * - "n" (ML_KEM_DEGREE above) is the fixed degree of the quotient polynomial 72 * in the ring: "R_q" = Z[X]/(X^n + 1). 73 * - "q" (ML_KEM_PRIME above) is the fixed prime (256 * 13 + 1 = 3329) used in 74 * all ML-KEM variants. 75 * - "k" is the row rank of the square matrix "A", with entries in R_q, that 76 * defines the "noisy" linear equations: t = A * s + e. Also the rank of 77 * of the associated vectors. 78 * - "eta1" determines the amplitude of "s" and "e" vectors in key generation 79 * and the "y" vector in ML-KEM encapsulation (K-PKE encryption). 80 * - "eta2" determines the amplitude of "e1" and "e2" noise terms in ML-KEM 81 * encapsulation (K-PKE encryption). 82 * - "du" determines how many bits of each coefficient are retained in the 83 * compressed form of the "u" vector in the encapsulation ciphertext. 84 * - "dv" determines how many bits of each coefficient are retained in the 85 * compressed form of the "v" value in encapsulation ciphertext 86 * - "secbits" is required security strength of the RNG for the random inputs. 87 */ 88 89 /* 90 * Variant-specific constants and structures 91 * ----------------------------------------- 92 */ 93 # define EVP_PKEY_ML_KEM_512 NID_ML_KEM_512 94 # define ML_KEM_512_BITS 512 95 # define ML_KEM_512_RANK 2 96 # define ML_KEM_512_ETA1 3 97 # define ML_KEM_512_ETA2 2 98 # define ML_KEM_512_DU 10 99 # define ML_KEM_512_DV 4 100 # define ML_KEM_512_SECBITS 128 101 # define ML_KEM_512_SECURITY_CATEGORY 1 102 103 # define EVP_PKEY_ML_KEM_768 NID_ML_KEM_768 104 # define ML_KEM_768_BITS 768 105 # define ML_KEM_768_RANK 3 106 # define ML_KEM_768_ETA1 2 107 # define ML_KEM_768_ETA2 2 108 # define ML_KEM_768_DU 10 109 # define ML_KEM_768_DV 4 110 # define ML_KEM_768_SECBITS 192 111 # define ML_KEM_768_SECURITY_CATEGORY 3 112 113 # define EVP_PKEY_ML_KEM_1024 NID_ML_KEM_1024 114 # define ML_KEM_1024_BITS 1024 115 # define ML_KEM_1024_RANK 4 116 # define ML_KEM_1024_ETA1 2 117 # define ML_KEM_1024_ETA2 2 118 # define ML_KEM_1024_DU 11 119 # define ML_KEM_1024_DV 5 120 # define ML_KEM_1024_SECBITS 256 121 # define ML_KEM_1024_SECURITY_CATEGORY 5 122 123 # define ML_KEM_KEY_RANDOM_PCT (1 << 0) 124 # define ML_KEM_KEY_FIXED_PCT (1 << 1) 125 # define ML_KEM_KEY_PREFER_SEED (1 << 2) 126 # define ML_KEM_KEY_RETAIN_SEED (1 << 3) 127 /* Mask to check whether PCT on import is enabled */ 128 # define ML_KEM_KEY_PCT_TYPE \ 129 (ML_KEM_KEY_RANDOM_PCT | ML_KEM_KEY_FIXED_PCT) 130 /* Default provider flags */ 131 # define ML_KEM_KEY_PROV_FLAGS_DEFAULT \ 132 (ML_KEM_KEY_RANDOM_PCT | ML_KEM_KEY_PREFER_SEED | ML_KEM_KEY_RETAIN_SEED) 133 134 /* 135 * External variant-specific API 136 * ----------------------------- 137 */ 138 139 typedef struct { 140 const char *algorithm_name; 141 size_t prvkey_bytes; 142 size_t prvalloc; 143 size_t pubkey_bytes; 144 size_t puballoc; 145 size_t ctext_bytes; 146 size_t vector_bytes; 147 size_t u_vector_bytes; 148 int evp_type; 149 int bits; 150 int rank; 151 int du; 152 int dv; 153 int secbits; 154 int security_category; 155 } ML_KEM_VINFO; 156 157 /* Retrive global variant-specific parameters */ 158 const ML_KEM_VINFO *ossl_ml_kem_get_vinfo(int evp_type); 159 160 /* Known as ML_KEM_KEY via crypto/types.h */ 161 typedef struct ossl_ml_kem_key_st { 162 /* Variant metadata, for one of ML-KEM-{512,768,1024} */ 163 const ML_KEM_VINFO *vinfo; 164 165 /* 166 * Library context, initially used to fetch the SHA3 MDs, and later for 167 * random number generation. 168 */ 169 OSSL_LIB_CTX *libctx; 170 171 /* Pre-fetched SHA3 */ 172 EVP_MD *shake128_md; 173 EVP_MD *shake256_md; 174 EVP_MD *sha3_256_md; 175 EVP_MD *sha3_512_md; 176 177 /* 178 * Pointers into variable size storage, initially all NULL. Appropriate 179 * storage is allocated once a public or private key is specified, at 180 * which point the key becomes immutable. 181 */ 182 uint8_t *rho; /* Public matrix seed */ 183 uint8_t *pkhash; /* Public key hash */ 184 struct ossl_ml_kem_scalar_st *t; /* Public key vector */ 185 struct ossl_ml_kem_scalar_st *m; /* Pre-computed pubkey matrix */ 186 struct ossl_ml_kem_scalar_st *s; /* Private key secret vector */ 187 uint8_t *z; /* Private key FO failure secret */ 188 uint8_t *d; /* Private key seed */ 189 int prov_flags; /* prefer/retain seed and PCT flags */ 190 191 /* 192 * Fixed-size built-in buffer, which holds the |rho| and the public key 193 * |pkhash| in that order, once we have expanded key material. 194 */ 195 uint8_t rho_pkhash[64]; /* |rho| + |pkhash| */ 196 197 /* 198 * With seed-only keys, that are not yet expanded, this holds the 199 * |z| and |d| components in that order. 200 */ 201 uint8_t *seedbuf; /* |z| + |d| temporary secure storage buffer */ 202 uint8_t *encoded_dk; /* Unparsed P8 private key */ 203 } ML_KEM_KEY; 204 205 /* The public key is always present, when the private is */ 206 # define ossl_ml_kem_key_vinfo(key) ((key)->vinfo) 207 # define ossl_ml_kem_have_pubkey(key) ((key)->t != NULL) 208 # define ossl_ml_kem_have_prvkey(key) ((key)->s != NULL) 209 # define ossl_ml_kem_have_seed(key) ((key)->d != NULL) 210 # define ossl_ml_kem_have_dkenc(key) ((key)->encoded_dk != NULL) 211 # define ossl_ml_kem_decoded_key(key) ((key)->encoded_dk != NULL \ 212 || ((key)->s == NULL && (key)->d != NULL)) 213 214 /* 215 * ----- ML-KEM key lifecycle 216 */ 217 218 /* 219 * Allocate a "bare" key for given ML-KEM variant. Initially without any public 220 * or private key material. 221 */ 222 ML_KEM_KEY *ossl_ml_kem_key_new(OSSL_LIB_CTX *libctx, const char *properties, 223 int evp_type); 224 /* Reset a key clearing all public and private key material */ 225 void ossl_ml_kem_key_reset(ML_KEM_KEY *key); 226 /* Deallocate the key */ 227 void ossl_ml_kem_key_free(ML_KEM_KEY *key); 228 /* 229 * Duplicate a key, optionally including some key material, per the 230 * |selection|, see <openssl/core_dispatch.h>. 231 */ 232 ML_KEM_KEY *ossl_ml_kem_key_dup(const ML_KEM_KEY *key, int selection); 233 234 /* 235 * ----- Import or generate key material. 236 */ 237 238 /* 239 * Functions that augment "bare ML-KEM keys" with key material deserialised 240 * from an input buffer. It is an error for any key material to already be 241 * present. 242 * 243 * Return 1 on success, 0 otherwise. 244 */ 245 __owur 246 int ossl_ml_kem_parse_public_key(const uint8_t *in, size_t len, 247 ML_KEM_KEY *key); 248 __owur 249 int ossl_ml_kem_parse_private_key(const uint8_t *in, size_t len, 250 ML_KEM_KEY *key); 251 ML_KEM_KEY *ossl_ml_kem_set_seed(const uint8_t *seed, size_t seedlen, 252 ML_KEM_KEY *key); 253 __owur 254 int ossl_ml_kem_genkey(uint8_t *pubenc, size_t publen, ML_KEM_KEY *key); 255 256 /* 257 * Perform an ML-KEM operation with a given ML-KEM key. The key can generally 258 * be either a private or public key, with the exception of encoding a private 259 * key or performing KEM decapsulation. 260 */ 261 __owur 262 int ossl_ml_kem_encode_public_key(uint8_t *out, size_t len, 263 const ML_KEM_KEY *key); 264 __owur 265 int ossl_ml_kem_encode_private_key(uint8_t *out, size_t len, 266 const ML_KEM_KEY *key); 267 __owur 268 int ossl_ml_kem_encode_seed(uint8_t *out, size_t len, 269 const ML_KEM_KEY *key); 270 271 __owur 272 int ossl_ml_kem_encap_seed(uint8_t *ctext, size_t clen, 273 uint8_t *shared_secret, size_t slen, 274 const uint8_t *entropy, size_t elen, 275 const ML_KEM_KEY *key); 276 __owur 277 int ossl_ml_kem_encap_rand(uint8_t *ctext, size_t clen, 278 uint8_t *shared_secret, size_t slen, 279 const ML_KEM_KEY *key); 280 __owur 281 int ossl_ml_kem_decap(uint8_t *shared_secret, size_t slen, 282 const uint8_t *ctext, size_t clen, 283 const ML_KEM_KEY *key); 284 285 /* Compare the public key hashes of two keys */ 286 __owur 287 int ossl_ml_kem_pubkey_cmp(const ML_KEM_KEY *key1, const ML_KEM_KEY *key2); 288 289 #endif /* OPENSSL_HEADER_ML_KEM_H */ 290