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