Compare commits

...

2 Commits

7 changed files with 114 additions and 1 deletions

52
Cargo.lock generated
View File

@@ -818,6 +818,15 @@ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
[[package]]
name = "hybrid-array"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2d35805454dc9f8662a98d6d61886ffe26bd465f5960e0e55345c70d5c0d2a9"
dependencies = [
"typenum",
]
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.64" version = "0.1.64"
@@ -922,6 +931,25 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "keccak"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654"
dependencies = [
"cpufeatures",
]
[[package]]
name = "kem"
version = "0.3.0-pre.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b8645470337db67b01a7f966decf7d0bafedbae74147d33e641c67a91df239f"
dependencies = [
"rand_core 0.6.4",
"zeroize",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.5.0" version = "1.5.0"
@@ -992,6 +1020,19 @@ dependencies = [
"adler2", "adler2",
] ]
[[package]]
name = "ml-kem"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97befee0c869cb56f3118f49d0f9bb68c9e3f380dec23c1100aedc4ec3ba239a"
dependencies = [
"hybrid-array",
"kem",
"rand_core 0.6.4",
"sha3",
"zeroize",
]
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.30.1" version = "0.30.1"
@@ -1757,6 +1798,16 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "sha3"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
dependencies = [
"digest",
"keccak",
]
[[package]] [[package]]
name = "shell-words" name = "shell-words"
version = "1.1.0" version = "1.1.0"
@@ -2023,6 +2074,7 @@ dependencies = [
"hex", "hex",
"indicatif", "indicatif",
"json5", "json5",
"ml-kem",
"openpgp-card", "openpgp-card",
"openpgp-card-pcsc", "openpgp-card-pcsc",
"p256", "p256",

View File

@@ -55,6 +55,7 @@ swift-secure-enclave-tool-rs = "1.0"
json5 = "0.4" json5 = "0.4"
external-command-rs = "0.1" external-command-rs = "0.1"
percent-encoding = "2.3" percent-encoding = "2.3"
ml-kem = { version = "0.2.1", features = ["zeroize"] }
[profile.release] [profile.release]
codegen-units = 1 codegen-units = 1

View File

@@ -469,6 +469,7 @@ pub fn try_decrypt_key(config: &Option<TinyEncryptConfig>,
TinyEncryptEnvelopType::PivP256 | TinyEncryptEnvelopType::PivP384 => try_decrypt_piv_key_ecdh(config, envelop, pin, slot, silent), TinyEncryptEnvelopType::PivP256 | TinyEncryptEnvelopType::PivP384 => try_decrypt_piv_key_ecdh(config, envelop, pin, slot, silent),
TinyEncryptEnvelopType::KeyP256 => try_decrypt_se_key_ecdh(config, envelop), TinyEncryptEnvelopType::KeyP256 => try_decrypt_se_key_ecdh(config, envelop),
TinyEncryptEnvelopType::ExtP256 | TinyEncryptEnvelopType::ExtP384 => try_decrypt_ext_key_ecdh(config, envelop), TinyEncryptEnvelopType::ExtP256 | TinyEncryptEnvelopType::ExtP384 => try_decrypt_ext_key_ecdh(config, envelop),
// TODO EXT ML-KEM 768 & 1024
TinyEncryptEnvelopType::PivRsa => try_decrypt_piv_key_rsa(config, envelop, pin, slot, silent), TinyEncryptEnvelopType::PivRsa => try_decrypt_piv_key_rsa(config, envelop, pin, slot, silent),
#[cfg(feature = "macos")] #[cfg(feature = "macos")]
TinyEncryptEnvelopType::StaticKyber1024 => try_decrypt_key_ecdh_static_kyber1204(config, envelop), TinyEncryptEnvelopType::StaticKyber1024 => try_decrypt_key_ecdh_static_kyber1204(config, envelop),

View File

@@ -333,6 +333,7 @@ pub fn encrypt_envelops(cryptor: Cryptor, key: &[u8], envelops: &[&TinyEncryptCo
TinyEncryptEnvelopType::PivP384 | TinyEncryptEnvelopType::ExtP384 => { TinyEncryptEnvelopType::PivP384 | TinyEncryptEnvelopType::ExtP384 => {
encrypted_envelops.push(encrypt_envelop_ecdh_p384(cryptor, key, envelop)?); encrypted_envelops.push(encrypt_envelop_ecdh_p384(cryptor, key, envelop)?);
} }
// TODO ML-KEM 768 & 1024
TinyEncryptEnvelopType::StaticKyber1024 => { TinyEncryptEnvelopType::StaticKyber1024 => {
encrypted_envelops.push(encrypt_envelop_ecdh_kyber1204(cryptor, key, envelop)?); encrypted_envelops.push(encrypt_envelop_ecdh_kyber1204(cryptor, key, envelop)?);
} }

View File

@@ -78,4 +78,5 @@ mod util_keychainkey;
mod util_simple_pbe; mod util_simple_pbe;
mod util_log; mod util_log;
mod temporary_key; mod temporary_key;
mod util_mlkem;

View File

@@ -98,6 +98,12 @@ pub enum TinyEncryptEnvelopType {
// External ECDH P384 // External ECDH P384
#[serde(rename = "ext-p384")] #[serde(rename = "ext-p384")]
ExtP384, ExtP384,
// External ML-KEM 768
#[serde(rename = "ext-mlkem768")]
ExtMlKem768,
// External ML-KEM 1024
#[serde(rename = "ext-mlkem1024")]
ExtMlKem1024,
// PIV RSA // PIV RSA
#[serde(rename = "piv-rsa")] #[serde(rename = "piv-rsa")]
PivRsa, PivRsa,
@@ -124,6 +130,8 @@ impl TinyEncryptEnvelopType {
TinyEncryptEnvelopType::KeyP256 => "key-p256", TinyEncryptEnvelopType::KeyP256 => "key-p256",
TinyEncryptEnvelopType::ExtP256 => "ext-p256", TinyEncryptEnvelopType::ExtP256 => "ext-p256",
TinyEncryptEnvelopType::ExtP384 => "ext-p384", TinyEncryptEnvelopType::ExtP384 => "ext-p384",
TinyEncryptEnvelopType::ExtMlKem768 => "ext-mlkem768",
TinyEncryptEnvelopType::ExtMlKem1024 => "ext-mlkem1024",
TinyEncryptEnvelopType::PivP256 => "piv-p256", TinyEncryptEnvelopType::PivP256 => "piv-p256",
TinyEncryptEnvelopType::PivP384 => "piv-p384", TinyEncryptEnvelopType::PivP384 => "piv-p384",
TinyEncryptEnvelopType::PivRsa => "piv-rsa", TinyEncryptEnvelopType::PivRsa => "piv-rsa",
@@ -142,6 +150,8 @@ impl TinyEncryptEnvelopType {
"key-p256" => Some(TinyEncryptEnvelopType::KeyP256), "key-p256" => Some(TinyEncryptEnvelopType::KeyP256),
"ext-p256" => Some(TinyEncryptEnvelopType::ExtP256), "ext-p256" => Some(TinyEncryptEnvelopType::ExtP256),
"ext-p384" => Some(TinyEncryptEnvelopType::ExtP384), "ext-p384" => Some(TinyEncryptEnvelopType::ExtP384),
"ext-mlkem768" => Some(TinyEncryptEnvelopType::ExtMlKem768),
"ext-mlkem1024" => Some(TinyEncryptEnvelopType::ExtMlKem1024),
"piv-p256" => Some(TinyEncryptEnvelopType::PivP256), "piv-p256" => Some(TinyEncryptEnvelopType::PivP256),
"piv-p384" => Some(TinyEncryptEnvelopType::PivP384), "piv-p384" => Some(TinyEncryptEnvelopType::PivP384),
"piv-rsa" => Some(TinyEncryptEnvelopType::PivRsa), "piv-rsa" => Some(TinyEncryptEnvelopType::PivRsa),
@@ -162,6 +172,8 @@ impl TinyEncryptEnvelopType {
| TinyEncryptEnvelopType::PgpX25519 | TinyEncryptEnvelopType::PgpX25519
| TinyEncryptEnvelopType::ExtP256 | TinyEncryptEnvelopType::ExtP256
| TinyEncryptEnvelopType::ExtP384 | TinyEncryptEnvelopType::ExtP384
| TinyEncryptEnvelopType::ExtMlKem768
| TinyEncryptEnvelopType::ExtMlKem1024
| TinyEncryptEnvelopType::PivP256 | TinyEncryptEnvelopType::PivP256
| TinyEncryptEnvelopType::PivP384 | TinyEncryptEnvelopType::PivP384
| TinyEncryptEnvelopType::PivRsa | TinyEncryptEnvelopType::PivRsa
@@ -184,7 +196,9 @@ impl TinyEncryptEnvelopType {
// GPG is unknown(hardware/software) // GPG is unknown(hardware/software)
TinyEncryptEnvelopType::Gpg TinyEncryptEnvelopType::Gpg
| TinyEncryptEnvelopType::ExtP256 | TinyEncryptEnvelopType::ExtP256
| TinyEncryptEnvelopType::ExtP384 => None, | TinyEncryptEnvelopType::ExtP384
| TinyEncryptEnvelopType::ExtMlKem768
| TinyEncryptEnvelopType::ExtMlKem1024 => None,
} }
} }
} }

43
src/util_mlkem.rs Normal file
View File

@@ -0,0 +1,43 @@
use ml_kem::kem::Encapsulate;
use ml_kem::{Encoded, EncodedSizeUser, KemCore, MlKem1024, MlKem768};
use rust_util::{opt_result, simple_error, XResult};
pub fn ml_kem_768_encapsulate(public_key: &[u8]) -> XResult<(Vec<u8>, Vec<u8>)> {
let encapsulation_key_encoded: Encoded<<MlKem768 as KemCore>::EncapsulationKey> = opt_result!(
public_key.try_into(),
"Parse ML-KEM 768 encapsulation key failed: {}"
);
let encapsulation_key =
<MlKem768 as KemCore>::EncapsulationKey::from_bytes(&encapsulation_key_encoded);
let mut rng = rand::rngs::OsRng;
let (ciphertext, shared_key) = opt_result!(
encapsulation_key.encapsulate(&mut rng),
"Encapsulate shared key failed: {:?}"
);
Ok((ciphertext.0.to_vec(), shared_key.0.to_vec()))
}
pub fn ml_kem_1024_encapsulate(public_key: &[u8]) -> XResult<(Vec<u8>, Vec<u8>)> {
let encapsulation_key_encoded: Encoded<<MlKem1024 as KemCore>::EncapsulationKey> = opt_result!(
public_key.try_into(),
"Parse ML-KEM 1024 encapsulation key failed: {}"
);
let encapsulation_key =
<MlKem1024 as KemCore>::EncapsulationKey::from_bytes(&encapsulation_key_encoded);
let mut rng = rand::rngs::OsRng;
let (ciphertext, shared_key) = opt_result!(
encapsulation_key.encapsulate(&mut rng),
"Encapsulate shared key failed: {:?}"
);
Ok((ciphertext.0.to_vec(), shared_key.0.to_vec()))
}
pub fn try_ml_kem_encapsulate(public_key: &[u8]) -> XResult<(Vec<u8>, Vec<u8>)> {
if let Ok((ciphertext, shared_key)) = ml_kem_768_encapsulate(public_key) {
return Ok((ciphertext, shared_key));
}
if let Ok((ciphertext, shared_key)) = ml_kem_1024_encapsulate(public_key) {
return Ok((ciphertext, shared_key));
}
simple_error!("Not ML-KEM 768 or ML-KEM 1024.")
}