1mod bignum;
24mod ed25519;
25mod ed448;
26mod mldsa;
27mod mlkem;
28mod named_curve;
29mod p256;
30mod p384;
31mod pq_selftest;
32mod rsa;
33mod x25519;
34mod x448;
35
36use core::cmp::Ordering;
37
38use crate::drbg::HmacDrbgSha256;
39use crate::internal_alloc::Vec;
40use bignum::BigUint;
41use noxtls_core::{Error, Result};
42
43pub use ed25519::{
44 noxtls_ed25519_generate_private_key_auto,
45 noxtls_ed25519_public_key_from_subject_public_key_info, noxtls_ed25519_verify,
46 Ed25519PrivateKey, Ed25519PublicKey,
47};
48pub use ed448::{
49 noxtls_ed448_generate_private_key_auto, noxtls_ed448_public_key_from_subject_public_key_info,
50 noxtls_ed448_verify, Ed448PrivateKey, Ed448PublicKey,
51};
52pub use mldsa::{
53 noxtls_mldsa_generate_keypair_auto, noxtls_mldsa_public_key_from_subject_public_key_info,
54 noxtls_mldsa_verify, MlDsaPrivateKey, MlDsaPublicKey, OID_ID_MLDSA65,
55};
56pub use mlkem::{
57 noxtls_mlkem_decapsulate, noxtls_mlkem_encapsulate_auto, noxtls_mlkem_generate_keypair_auto,
58 noxtls_mlkem_generate_keypair_auto_for_parameter_set, MlKemParameterSet, MlKemPrivateKey,
59 MlKemPublicKey, MLKEM1024_CIPHERTEXT_LEN, MLKEM1024_PRIVATE_KEY_LEN, MLKEM1024_PUBLIC_KEY_LEN,
60 MLKEM512_CIPHERTEXT_LEN, MLKEM512_PRIVATE_KEY_LEN, MLKEM512_PUBLIC_KEY_LEN,
61 MLKEM_CIPHERTEXT_LEN, MLKEM_PRIVATE_KEY_LEN, MLKEM_PUBLIC_KEY_LEN, MLKEM_SHARED_SECRET_LEN,
62};
63pub use named_curve::{
64 noxtls_named_curve_from_mbedtls_name, noxtls_named_curve_info,
65 noxtls_named_ec_generate_private_key_auto, noxtls_named_ecdh_shared_secret,
66 noxtls_named_ecdsa_sign_digest, noxtls_named_ecdsa_verify_digest,
67 noxtls_secp256k1_ecdsa_sign_sha256, noxtls_secp521r1_ecdsa_sign_sha512, NamedCurve,
68 NamedCurveInfo, NamedEcPrivateKey, NamedEcPublicKey, NOXTLS_MBEDTLS_ECC_CURVES,
69};
70pub use p256::{
71 noxtls_p256_ecdh_shared_secret, noxtls_p256_ecdsa_sign_digest,
72 noxtls_p256_ecdsa_sign_digest_auto, noxtls_p256_ecdsa_sign_sha256,
73 noxtls_p256_ecdsa_sign_sha256_auto, noxtls_p256_ecdsa_verify_digest,
74 noxtls_p256_ecdsa_verify_sha256, noxtls_p256_generate_private_key_auto, P256PrivateKey,
75 P256PublicKey,
76};
77pub use p384::{
78 noxtls_p384_ecdh_shared_secret, noxtls_p384_ecdsa_sign_digest,
79 noxtls_p384_ecdsa_sign_digest_auto, noxtls_p384_ecdsa_sign_sha384,
80 noxtls_p384_ecdsa_sign_sha384_auto, noxtls_p384_ecdsa_verify_digest,
81 noxtls_p384_ecdsa_verify_sha384, noxtls_p384_generate_private_key_auto, P384PrivateKey,
82 P384PublicKey,
83};
84pub use pq_selftest::noxtls_run_pq_self_tests;
85#[cfg(feature = "hazardous-legacy-crypto")]
86pub use rsa::{noxtls_rsa_generate_keypair_auto, noxtls_rsa_generate_keypair_with_exponent_auto};
87pub use rsa::{
88 noxtls_rsa_generate_keypair_secure_auto, noxtls_rsa_generate_keypair_with_policy_auto,
89 noxtls_rsaes_oaep_sha256_decrypt, noxtls_rsaes_oaep_sha256_decrypt_crt_only,
90 noxtls_rsaes_oaep_sha256_encrypt_auto, noxtls_rsaes_pkcs1_v15_decrypt,
91 noxtls_rsaes_pkcs1_v15_decrypt_crt_only, noxtls_rsaes_pkcs1_v15_encrypt_auto,
92 noxtls_rsassa_pss_sha256_sign, noxtls_rsassa_pss_sha256_sign_auto,
93 noxtls_rsassa_pss_sha256_verify, noxtls_rsassa_pss_sha384_sign,
94 noxtls_rsassa_pss_sha384_sign_auto, noxtls_rsassa_pss_sha384_verify, noxtls_rsassa_pss_sign,
95 noxtls_rsassa_pss_verify, noxtls_rsassa_sha1_sign, noxtls_rsassa_sha1_verify,
96 noxtls_rsassa_sha256_sign, noxtls_rsassa_sha256_verify, noxtls_rsassa_sha384_sign,
97 noxtls_rsassa_sha384_verify, noxtls_rsassa_sha512_sign, noxtls_rsassa_sha512_verify,
98 RsaKeySizePolicy, RsaPrivateKey, RsaPssHashAlgorithm, RsaPublicKey,
99};
100pub use x25519::{
101 noxtls_x25519, noxtls_x25519_basepoint, noxtls_x25519_generate_private_key_auto,
102 noxtls_x25519_shared_secret, X25519PrivateKey, X25519PublicKey,
103};
104#[cfg(feature = "hazardous-legacy-crypto")]
105pub use x448::noxtls_x448_generate_private_key_auto;
106#[cfg(feature = "hazardous-legacy-crypto")]
107pub use x448::{noxtls_x448, noxtls_x448_basepoint, noxtls_x448_shared_secret};
108pub use x448::{X448PrivateKey, X448PublicKey};
109
110fn noxtls_parse_ffdhe_value(value: &[u8], label: &'static str) -> Result<BigUint> {
111 if value.is_empty() {
112 return Err(Error::InvalidLength(label));
113 }
114 Ok(BigUint::from_be_bytes(value))
115}
116
117fn noxtls_validate_ffdhe_prime(prime: &BigUint) -> Result<()> {
118 if prime.cmp(&BigUint::from_u128(3)) != Ordering::Greater || !prime.is_odd() {
119 return Err(Error::CryptoFailure(
120 "ffdhe prime must be an odd integer greater than 3",
121 ));
122 }
123 Ok(())
124}
125
126fn noxtls_validate_ffdhe_private(private_key: &BigUint, prime: &BigUint) -> Result<()> {
127 if private_key.cmp(&BigUint::from_u128(1)) != Ordering::Greater {
128 return Err(Error::CryptoFailure(
129 "ffdhe private key must be greater than 1",
130 ));
131 }
132 let upper = prime.sub(&BigUint::from_u128(1));
133 if private_key.cmp(&upper) != Ordering::Less {
134 return Err(Error::CryptoFailure(
135 "ffdhe private key must be less than p - 1",
136 ));
137 }
138 Ok(())
139}
140
141fn noxtls_validate_ffdhe_public(public_key: &BigUint, prime: &BigUint) -> Result<()> {
142 if public_key.cmp(&BigUint::from_u128(1)) != Ordering::Greater {
143 return Err(Error::CryptoFailure(
144 "ffdhe public key must be greater than 1",
145 ));
146 }
147 let upper = prime.sub(&BigUint::from_u128(1));
148 if public_key.cmp(&upper) != Ordering::Less {
149 return Err(Error::CryptoFailure(
150 "ffdhe public key must be less than p - 1",
151 ));
152 }
153 Ok(())
154}
155
156pub fn noxtls_ffdhe_public_key(
158 private_key: &[u8],
159 generator: &[u8],
160 prime: &[u8],
161) -> Result<Vec<u8>> {
162 let p = noxtls_parse_ffdhe_value(prime, "ffdhe prime must not be empty")?;
163 let g = noxtls_parse_ffdhe_value(generator, "ffdhe generator must not be empty")?;
164 let x = noxtls_parse_ffdhe_value(private_key, "ffdhe private key must not be empty")?;
165 noxtls_validate_ffdhe_prime(&p)?;
166 noxtls_validate_ffdhe_private(&x, &p)?;
167 noxtls_validate_ffdhe_public(&g, &p)?;
168 Ok(BigUint::mod_exp(&g, &x, &p).to_be_bytes())
169}
170
171pub fn noxtls_ffdhe_shared_secret(
173 private_key: &[u8],
174 peer_public_key: &[u8],
175 prime: &[u8],
176) -> Result<Vec<u8>> {
177 let p = noxtls_parse_ffdhe_value(prime, "ffdhe prime must not be empty")?;
178 let x = noxtls_parse_ffdhe_value(private_key, "ffdhe private key must not be empty")?;
179 let y = noxtls_parse_ffdhe_value(peer_public_key, "ffdhe peer public key must not be empty")?;
180 noxtls_validate_ffdhe_prime(&p)?;
181 noxtls_validate_ffdhe_private(&x, &p)?;
182 noxtls_validate_ffdhe_public(&y, &p)?;
183 Ok(BigUint::mod_exp(&y, &x, &p).to_be_bytes())
184}
185
186#[derive(Debug, Clone, Copy, Eq, PartialEq)]
188pub enum EccKeyAlgorithm {
189 Secp192R1,
191 Secp224R1,
193 P256,
195 P384,
197 P521,
199 Secp192K1,
201 Secp224K1,
203 Secp256K1,
205 BrainpoolP256R1,
207 BrainpoolP384R1,
209 BrainpoolP512R1,
211 X25519,
213 X448,
215 Ed25519,
217 Ed448,
219}
220
221#[derive(Debug, Clone)]
223pub enum EccPrivateKey {
224 P256(P256PrivateKey),
226 P384(P384PrivateKey),
228 Named(NamedEcPrivateKey),
230 X25519(X25519PrivateKey),
232 X448(X448PrivateKey),
234 Ed25519(Ed25519PrivateKey),
236 Ed448(Ed448PrivateKey),
238}
239
240#[derive(Debug, Clone, Eq, PartialEq)]
242pub enum EccPublicKey {
243 P256(P256PublicKey),
245 P384(P384PublicKey),
247 Named(NamedEcPublicKey),
249 X25519(X25519PublicKey),
251 X448(X448PublicKey),
253 Ed25519(Ed25519PublicKey),
255 Ed448(Ed448PublicKey),
257}
258
259pub fn noxtls_ecc_generate_keypair_auto(
276 noxtls_algorithm: EccKeyAlgorithm,
277 drbg: &mut HmacDrbgSha256,
278) -> Result<(EccPrivateKey, EccPublicKey)> {
279 match noxtls_algorithm {
280 EccKeyAlgorithm::Secp192R1 => {
281 let private = noxtls_named_ec_generate_private_key_auto(NamedCurve::Secp192R1, drbg)?;
282 let public = private.public_key()?;
283 Ok((EccPrivateKey::Named(private), EccPublicKey::Named(public)))
284 }
285 EccKeyAlgorithm::Secp224R1 => {
286 let private = noxtls_named_ec_generate_private_key_auto(NamedCurve::Secp224R1, drbg)?;
287 let public = private.public_key()?;
288 Ok((EccPrivateKey::Named(private), EccPublicKey::Named(public)))
289 }
290 EccKeyAlgorithm::P256 => {
291 let private = noxtls_p256_generate_private_key_auto(drbg)?;
292 let public = private.public_key()?;
293 Ok((EccPrivateKey::P256(private), EccPublicKey::P256(public)))
294 }
295 EccKeyAlgorithm::P384 => {
296 let private = noxtls_p384_generate_private_key_auto(drbg)?;
297 let public = private.public_key()?;
298 Ok((EccPrivateKey::P384(private), EccPublicKey::P384(public)))
299 }
300 EccKeyAlgorithm::P521 => {
301 let private = noxtls_named_ec_generate_private_key_auto(NamedCurve::Secp521R1, drbg)?;
302 let public = private.public_key()?;
303 Ok((EccPrivateKey::Named(private), EccPublicKey::Named(public)))
304 }
305 EccKeyAlgorithm::Secp192K1 => {
306 let private = noxtls_named_ec_generate_private_key_auto(NamedCurve::Secp192K1, drbg)?;
307 let public = private.public_key()?;
308 Ok((EccPrivateKey::Named(private), EccPublicKey::Named(public)))
309 }
310 EccKeyAlgorithm::Secp224K1 => {
311 let private = noxtls_named_ec_generate_private_key_auto(NamedCurve::Secp224K1, drbg)?;
312 let public = private.public_key()?;
313 Ok((EccPrivateKey::Named(private), EccPublicKey::Named(public)))
314 }
315 EccKeyAlgorithm::Secp256K1 => {
316 let private = noxtls_named_ec_generate_private_key_auto(NamedCurve::Secp256K1, drbg)?;
317 let public = private.public_key()?;
318 Ok((EccPrivateKey::Named(private), EccPublicKey::Named(public)))
319 }
320 EccKeyAlgorithm::BrainpoolP256R1 => {
321 let private = noxtls_named_ec_generate_private_key_auto(NamedCurve::BrainpoolP256R1, drbg)?;
322 let public = private.public_key()?;
323 Ok((EccPrivateKey::Named(private), EccPublicKey::Named(public)))
324 }
325 EccKeyAlgorithm::BrainpoolP384R1 => {
326 let private = noxtls_named_ec_generate_private_key_auto(NamedCurve::BrainpoolP384R1, drbg)?;
327 let public = private.public_key()?;
328 Ok((EccPrivateKey::Named(private), EccPublicKey::Named(public)))
329 }
330 EccKeyAlgorithm::BrainpoolP512R1 => {
331 let private = noxtls_named_ec_generate_private_key_auto(NamedCurve::BrainpoolP512R1, drbg)?;
332 let public = private.public_key()?;
333 Ok((EccPrivateKey::Named(private), EccPublicKey::Named(public)))
334 }
335 EccKeyAlgorithm::X25519 => {
336 let private = noxtls_x25519_generate_private_key_auto(drbg)?;
337 let public = private.clone().public_key();
338 Ok((EccPrivateKey::X25519(private), EccPublicKey::X25519(public)))
339 }
340 #[cfg(feature = "hazardous-legacy-crypto")]
341 EccKeyAlgorithm::X448 => {
342 let private = noxtls_x448_generate_private_key_auto(drbg)?;
343 let public = private.clone().public_key();
344 Ok((EccPrivateKey::X448(private), EccPublicKey::X448(public)))
345 }
346 #[cfg(not(feature = "hazardous-legacy-crypto"))]
347 EccKeyAlgorithm::X448 => Err(Error::StateError(
348 "x448 operations are disabled by default; enable `hazardous-legacy-crypto` to use non-constant-time x448 implementation",
349 )),
350 EccKeyAlgorithm::Ed25519 => {
351 let private = noxtls_ed25519_generate_private_key_auto(drbg)?;
352 let public = private.verifying_key();
353 Ok((
354 EccPrivateKey::Ed25519(private),
355 EccPublicKey::Ed25519(public),
356 ))
357 }
358 EccKeyAlgorithm::Ed448 => {
359 let private = noxtls_ed448_generate_private_key_auto(drbg)?;
360 let public = private.verifying_key();
361 Ok((
362 EccPrivateKey::Ed448(private),
363 EccPublicKey::Ed448(public),
364 ))
365 }
366 }
367}
368
369#[cfg(test)]
370mod tests {
371 use super::*;
372
373 #[test]
374 fn ecc_keygen_includes_standard_named_weierstrass_curves() {
375 let algorithms = [
376 EccKeyAlgorithm::Secp192R1,
377 EccKeyAlgorithm::Secp224R1,
378 EccKeyAlgorithm::P384,
379 EccKeyAlgorithm::P521,
380 EccKeyAlgorithm::Secp192K1,
381 EccKeyAlgorithm::Secp224K1,
382 EccKeyAlgorithm::Secp256K1,
383 EccKeyAlgorithm::BrainpoolP256R1,
384 EccKeyAlgorithm::BrainpoolP384R1,
385 EccKeyAlgorithm::BrainpoolP512R1,
386 EccKeyAlgorithm::Ed448,
387 ];
388
389 for algorithm in algorithms {
390 let mut drbg =
391 HmacDrbgSha256::noxtls_new(b"ecc-standard-curves-keygen-seed", b"nonce", b"pkc")
392 .expect("drbg init");
393 let (private, public) =
394 noxtls_ecc_generate_keypair_auto(algorithm, &mut drbg).expect("curve keygen");
395 match algorithm {
396 EccKeyAlgorithm::P384 => {
397 assert!(matches!(private, EccPrivateKey::P384(_)));
398 assert!(matches!(public, EccPublicKey::P384(_)));
399 }
400 EccKeyAlgorithm::Ed448 => {
401 assert!(matches!(private, EccPrivateKey::Ed448(_)));
402 assert!(matches!(public, EccPublicKey::Ed448(_)));
403 }
404 _ => {
405 assert!(matches!(private, EccPrivateKey::Named(_)));
406 assert!(matches!(public, EccPublicKey::Named(_)));
407 }
408 }
409 }
410 }
411}