-
Notifications
You must be signed in to change notification settings - Fork 135
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for KEMRecipientInfo as defined in RFC9629 (#1485)
- Loading branch information
1 parent
8b96039
commit e0c3e08
Showing
6 changed files
with
157 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
//! KEMRecipientInfo-related types | ||
use crate::{ | ||
content_info::CmsVersion, | ||
enveloped_data::{EncryptedKey, RecipientIdentifier, UserKeyingMaterial}, | ||
}; | ||
use const_oid::ObjectIdentifier; | ||
use der::{asn1::OctetString, Sequence}; | ||
use spki::AlgorithmIdentifierOwned; | ||
|
||
/// From [RFC9629 Section 3] | ||
/// ```text | ||
/// id-ori OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) | ||
/// rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) 13 } | ||
/// | ||
/// id-ori-kem OBJECT IDENTIFIER ::= { id-ori 3 } | ||
/// ``` | ||
/// [RFC9629 Section 3]: https://datatracker.ietf.org/doc/html/rfc9629#section-3 | ||
pub const ID_ORI_KEM: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.9.16.13.3"); | ||
|
||
/// The `KEMRecipientInfo` type is defined in [RFC9629 Section 3] | ||
/// ```text | ||
/// KEMRecipientInfo ::= SEQUENCE { | ||
/// version CMSVersion, -- always set to 0 | ||
/// rid RecipientIdentifier, | ||
/// kem KEMAlgorithmIdentifier, | ||
/// kemct OCTET STRING, | ||
/// kdf KeyDerivationAlgorithmIdentifier, | ||
/// kekLength INTEGER (1..65535), | ||
/// ukm [0] EXPLICIT UserKeyingMaterial OPTIONAL, | ||
/// wrap KeyEncryptionAlgorithmIdentifier, | ||
/// encryptedKey EncryptedKey } | ||
/// ``` | ||
/// [RFC9629 Section 3]: https://datatracker.ietf.org/doc/html/rfc9629#section-3 | ||
#[derive(Clone, Debug, Eq, PartialEq, Sequence)] | ||
#[allow(missing_docs)] | ||
pub struct KemRecipientInfo { | ||
pub version: CmsVersion, | ||
pub rid: RecipientIdentifier, | ||
pub kem: AlgorithmIdentifierOwned, | ||
pub kem_ct: OctetString, | ||
pub kdf: AlgorithmIdentifierOwned, | ||
pub kek_length: u16, | ||
#[asn1(context_specific = "0", tag_mode = "EXPLICIT", optional = "true")] | ||
pub ukm: Option<UserKeyingMaterial>, | ||
pub wrap: AlgorithmIdentifierOwned, | ||
pub encrypted_key: EncryptedKey, | ||
} | ||
|
||
/// The `CMSORIforKEMOtherInfo` type is defined in [RFC9629 Section 5] | ||
/// ```text | ||
/// CMSORIforKEMOtherInfo ::= SEQUENCE { | ||
/// wrap KeyEncryptionAlgorithmIdentifier, | ||
/// kekLength INTEGER (1..65535), | ||
/// ukm [0] EXPLICIT UserKeyingMaterial OPTIONAL } | ||
/// ``` | ||
/// [RFC9629 Section 5]: https://datatracker.ietf.org/doc/html/rfc9629#section-5 | ||
#[derive(Clone, Debug, Eq, PartialEq, Sequence)] | ||
#[allow(missing_docs)] | ||
pub struct CmsOriForKemOtherInfo { | ||
pub wrap: AlgorithmIdentifierOwned, | ||
pub kek_length: u16, | ||
#[asn1(context_specific = "0", tag_mode = "EXPLICIT", optional = "true")] | ||
pub ukm: Option<UserKeyingMaterial>, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file added
BIN
+1.04 KB
cms/tests/examples/1.3.6.1.4.1.22554.5.6.1_ML-KEM-512-ipd_kemri_auth.der
Binary file not shown.
Binary file added
BIN
+1.02 KB
cms/tests/examples/1.3.6.1.4.1.22554.5.6.1_ML-KEM-512-ipd_kemri_id-alg-hkdf-with-sha256.der
Binary file not shown.
Binary file added
BIN
+1.06 KB
cms/tests/examples/1.3.6.1.4.1.22554.5.6.1_ML-KEM-512-ipd_kemri_ukm.der
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
use cms::authenveloped_data::AuthEnvelopedData; | ||
use cms::content_info::{CmsVersion, ContentInfo}; | ||
use cms::enveloped_data::{EnvelopedData, RecipientIdentifier, RecipientInfo}; | ||
use cms::kemri::ID_ORI_KEM; | ||
use const_oid::ObjectIdentifier; | ||
use der::{Decode, Encode}; | ||
use hex_literal::hex; | ||
|
||
#[test] | ||
fn kemri_auth_enveloped_data() { | ||
let data = include_bytes!("examples/1.3.6.1.4.1.22554.5.6.1_ML-KEM-512-ipd_kemri_auth.der"); | ||
let ci = ContentInfo::from_der(data).unwrap(); | ||
let aed = AuthEnvelopedData::from_der(&ci.content.to_der().unwrap()).unwrap(); | ||
for ri in aed.recip_infos.0.iter() { | ||
if let RecipientInfo::Ori(ori) = ri { | ||
let ori_value = ori.ori_value.to_der().unwrap(); | ||
assert_eq!(ori.ori_type, ID_ORI_KEM); | ||
let kemri = cms::kemri::KemRecipientInfo::from_der(&ori_value).unwrap(); | ||
let reenc = kemri.to_der().unwrap(); | ||
assert_eq!(reenc, ori_value); | ||
} else { | ||
panic!("Unexpected recipient info type"); | ||
} | ||
} | ||
} | ||
|
||
#[test] | ||
fn kemri_enveloped_data() { | ||
let data = include_bytes!( | ||
"examples/1.3.6.1.4.1.22554.5.6.1_ML-KEM-512-ipd_kemri_id-alg-hkdf-with-sha256.der" | ||
); | ||
let ci = ContentInfo::from_der(data).unwrap(); | ||
let ed = EnvelopedData::from_der(&ci.content.to_der().unwrap()).unwrap(); | ||
for ri in ed.recip_infos.0.iter() { | ||
if let RecipientInfo::Ori(ori) = ri { | ||
let ori_value = ori.ori_value.to_der().unwrap(); | ||
assert_eq!(ori.ori_type, ID_ORI_KEM); | ||
let kemri = cms::kemri::KemRecipientInfo::from_der(&ori_value).unwrap(); | ||
let reenc = kemri.to_der().unwrap(); | ||
assert_eq!(reenc, ori_value); | ||
} else { | ||
panic!("Unexpected recipient info type"); | ||
} | ||
} | ||
} | ||
|
||
#[test] | ||
fn kemri_enveloped_data_ukm() { | ||
let data = include_bytes!("examples/1.3.6.1.4.1.22554.5.6.1_ML-KEM-512-ipd_kemri_ukm.der"); | ||
let ci = ContentInfo::from_der(data).unwrap(); | ||
let ed = EnvelopedData::from_der(&ci.content.to_der().unwrap()).unwrap(); | ||
for ri in ed.recip_infos.0.iter() { | ||
if let RecipientInfo::Ori(ori) = ri { | ||
let ori_value = ori.ori_value.to_der().unwrap(); | ||
assert_eq!(ori.ori_type, ID_ORI_KEM); | ||
let kemri = cms::kemri::KemRecipientInfo::from_der(&ori_value).unwrap(); | ||
|
||
assert_eq!(kemri.version, CmsVersion::V0); | ||
|
||
if let RecipientIdentifier::SubjectKeyIdentifier(skid) = &kemri.rid { | ||
let rid = hex!("B17B1D588029CA33201230C50CE75F57E6AAC916"); | ||
assert_eq!(skid.0.as_bytes(), rid); | ||
} else { | ||
panic!("Unexpected recipient identifier type"); | ||
} | ||
|
||
pub const ML_KEM_512_IPD: ObjectIdentifier = | ||
ObjectIdentifier::new_unwrap("1.3.6.1.4.1.22554.5.6.1"); | ||
assert_eq!(kemri.kem.oid, ML_KEM_512_IPD); | ||
|
||
pub const ID_KMAC128: ObjectIdentifier = | ||
ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.21"); | ||
assert_eq!(kemri.kdf.oid, ID_KMAC128); | ||
|
||
assert_eq!( | ||
kemri.ukm.clone().unwrap().as_bytes(), | ||
"This is some User Keying Material\n".as_bytes() | ||
); | ||
|
||
let enc_key = hex!( | ||
"B9F524FB59CAD7420127B1FEA61D5F15F5BED04078AB7A3BEDD501B6B215D6AA417BDA0303C78A6C" | ||
); | ||
assert_eq!(kemri.encrypted_key.as_bytes(), enc_key); | ||
|
||
let reenc = kemri.to_der().unwrap(); | ||
assert_eq!(reenc, ori_value); | ||
} else { | ||
panic!("Unexpected recipient info type"); | ||
} | ||
} | ||
} |