diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2022-12-16 18:01:16 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2022-12-16 18:01:16 +0000 |
commit | af1b6b2ed018a7660757abb9d8d0a87c4e4abe30 (patch) | |
tree | b21aa411dae47d94216d3811c053361a07950aff | |
parent | 29a232bf9d140bfbc9ad36eab6d94b5214c763cf (diff) | |
parent | 50c0040a04842ca232bfa0cb54ee15db7cd8fd50 (diff) | |
download | pkcs1-af1b6b2ed018a7660757abb9d8d0a87c4e4abe30.tar.gz |
Merge "Upgrade pkcs1 to 0.4.1" am: 50c0040a04
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/pkcs1/+/2348523
Change-Id: I3d70ef8b85248dd41f62639f1c9d54cc28864d16
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | .cargo_vcs_info.json | 2 | ||||
-rw-r--r-- | Android.bp | 5 | ||||
-rw-r--r-- | CHANGELOG.md | 8 | ||||
-rw-r--r-- | Cargo.toml | 10 | ||||
-rw-r--r-- | Cargo.toml.orig | 4 | ||||
-rw-r--r-- | LICENSE-MIT | 25 | ||||
-rw-r--r-- | METADATA | 13 | ||||
-rw-r--r-- | src/lib.rs | 9 | ||||
-rw-r--r-- | src/params.rs | 301 | ||||
-rw-r--r-- | src/traits.rs | 4 | ||||
-rw-r--r-- | tests/params.rs | 178 |
11 files changed, 541 insertions, 18 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index c6845d7..8acf345 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,6 +1,6 @@ { "git": { - "sha1": "edbfb4db0ddfd1f95c7ed29ca480e4a93ec1737e" + "sha1": "40fbcf36aa1d1e20685424576da37b7df0279d3b" }, "path_in_vcs": "pkcs1" }
\ No newline at end of file @@ -1,8 +1,6 @@ // This file is generated by cargo2android.py --config cargo2android.json. // Do not modify this file as changes will be overridden on upgrade. - - package { default_applicable_licenses: ["external_rust_crates_pkcs1_license"], } @@ -37,7 +35,7 @@ rust_library_host { name: "libpkcs1", crate_name: "pkcs1", cargo_env_compat: true, - cargo_pkg_version: "0.4.0", + cargo_pkg_version: "0.4.1", srcs: ["src/lib.rs"], edition: "2021", features: [ @@ -48,6 +46,7 @@ rust_library_host { rustlibs: [ "libder", "libpkcs8", + "libspki", "libzeroize", ], apex_available: [ diff --git a/CHANGELOG.md b/CHANGELOG.md index e607ae7..7e95122 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.4.1 (2022-10-10) +### Added +- `RsaPssParams` support ([#698]) +- `RsaOaepParams` support ([#733]) + +[#698]: https://github.com/RustCrypto/formats/pull/698 +[#733]: https://github.com/RustCrypto/formats/pull/733 + ## 0.4.0 (2022-05-08) ### Changed - Replace document types with `doc::{Document, SecretDocument}` types ([#571]) @@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.57" name = "pkcs1" -version = "0.4.0" +version = "0.4.1" authors = ["RustCrypto Developers"] description = """ Pure Rust implementation of Public-Key Cryptography Standards (PKCS) #1: @@ -36,7 +36,6 @@ categories = [ ] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/formats/tree/master/pkcs1" -resolver = "2" [package.metadata.docs.rs] all-features = true @@ -54,11 +53,18 @@ version = "0.9" optional = true default-features = false +[dependencies.spki] +version = "0.6" + [dependencies.zeroize] version = "1" optional = true default-features = false +[dev-dependencies.const-oid] +version = "0.9" +features = ["db"] + [dev-dependencies.hex-literal] version = "0.3" diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 00f6414..fb1fa3f 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "pkcs1" -version = "0.4.0" # Also update html_root_url in lib.rs when bumping this +version = "0.4.1" description = """ Pure Rust implementation of Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.2 (RFC 8017) @@ -16,6 +16,7 @@ rust-version = "1.57" [dependencies] der = { version = "0.6", features = ["oid"], path = "../der" } +spki = { version = "0.6", path = "../spki" } # optional dependencies pkcs8 = { version = "0.9", optional = true, default-features = false, path = "../pkcs8" } @@ -24,6 +25,7 @@ zeroize = { version = "1", optional = true, default-features = false } [dev-dependencies] hex-literal = "0.3" tempfile = "3" +const-oid = { version = "0.9", path = "../const-oid", features = ["db"] } [features] alloc = ["der/alloc", "pkcs8/alloc", "zeroize/alloc"] diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..68ddaa3 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2021-2022 The RustCrypto Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. @@ -1,3 +1,7 @@ +# This project was upgraded with external_updater. +# Usage: tools/external_updater/updater.sh update rust/crates/pkcs1 +# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md + name: "pkcs1" description: "Pure Rust implementation of Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.2 (RFC 8017)." third_party { @@ -7,14 +11,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/pkcs1/pkcs1-0.4.0.crate" + value: "https://static.crates.io/crates/pkcs1/pkcs1-0.4.1.crate" } - version: "0.4.0" - # Dual-licensed, using the least restrictive per go/thirdpartylicenses#same. + version: "0.4.1" license_type: NOTICE last_upgrade_date { year: 2022 - month: 9 - day: 6 + month: 12 + day: 13 } } @@ -2,9 +2,8 @@ #![cfg_attr(docsrs, feature(doc_cfg))] #![doc = include_str!("../README.md")] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_root_url = "https://docs.rs/pkcs1/0.4.0-pre" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] #![forbid(unsafe_code, clippy::unwrap_used)] #![warn(missing_docs, rust_2018_idioms, unused_qualifications)] @@ -19,6 +18,7 @@ extern crate alloc; extern crate std; mod error; +mod params; mod private_key; mod public_key; mod traits; @@ -29,8 +29,9 @@ pub use der::{ asn1::{ObjectIdentifier, UIntRef}, }; -pub use self::{ +pub use crate::{ error::{Error, Result}, + params::{RsaOaepParams, RsaPssParams, TrailerField}, private_key::RsaPrivateKey, public_key::RsaPublicKey, traits::{DecodeRsaPrivateKey, DecodeRsaPublicKey}, diff --git a/src/params.rs b/src/params.rs new file mode 100644 index 0000000..e803473 --- /dev/null +++ b/src/params.rs @@ -0,0 +1,301 @@ +//! PKCS#1 RSA parameters. + +use crate::{Error, Result}; +use der::asn1::{AnyRef, ObjectIdentifier}; +use der::{ + asn1::ContextSpecificRef, Decode, DecodeValue, Encode, EncodeValue, FixedTag, Reader, Sequence, + Tag, TagMode, TagNumber, Writer, +}; +use spki::AlgorithmIdentifier; + +const OID_SHA_1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.26"); +const OID_MGF_1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.8"); +const OID_PSPECIFIED: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.9"); + +// TODO(tarcieri): make `AlgorithmIdentifier` generic around params; use `OID_SHA_1` +const SEQ_OID_SHA_1_DER: &[u8] = &[0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a]; + +const SHA_1_AI: AlgorithmIdentifier<'_> = AlgorithmIdentifier { + oid: OID_SHA_1, + parameters: None, +}; + +const SALT_LEN_DEFAULT: u8 = 20; + +/// `TrailerField` as defined in [RFC 8017 Appendix 2.3]. +/// ```text +/// TrailerField ::= INTEGER { trailerFieldBC(1) } +/// ``` +/// [RFC 8017 Appendix 2.3]: https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.2.3 +#[derive(Clone, Debug, Copy, PartialEq, Eq)] +#[repr(u8)] +pub enum TrailerField { + /// the only supported value (0xbc, default) + BC = 1, +} + +impl Default for TrailerField { + fn default() -> Self { + Self::BC + } +} + +impl<'a> DecodeValue<'a> for TrailerField { + fn decode_value<R: Reader<'a>>(decoder: &mut R, header: der::Header) -> der::Result<Self> { + match u8::decode_value(decoder, header)? { + 1 => Ok(TrailerField::BC), + _ => Err(Self::TAG.value_error()), + } + } +} + +impl EncodeValue for TrailerField { + fn value_len(&self) -> der::Result<der::Length> { + Ok(der::Length::ONE) + } + + fn encode_value(&self, writer: &mut dyn Writer) -> der::Result<()> { + (*self as u8).encode_value(writer) + } +} + +impl FixedTag for TrailerField { + const TAG: Tag = Tag::Integer; +} + +/// PKCS#1 RSASSA-PSS parameters as defined in [RFC 8017 Appendix 2.3] +/// +/// ASN.1 structure containing a serialized RSASSA-PSS parameters: +/// ```text +/// RSASSA-PSS-params ::= SEQUENCE { +/// hashAlgorithm [0] HashAlgorithm DEFAULT sha1, +/// maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1, +/// saltLength [2] INTEGER DEFAULT 20, +/// trailerField [3] TrailerField DEFAULT trailerFieldBC +/// } +/// HashAlgorithm ::= AlgorithmIdentifier +/// MaskGenAlgorithm ::= AlgorithmIdentifier +/// ``` +/// +/// [RFC 8017 Appendix 2.3]: https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.2.3 +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct RsaPssParams<'a> { + /// Hash Algorithm + pub hash: AlgorithmIdentifier<'a>, + + /// Mask Generation Function (MGF) + pub mask_gen: AlgorithmIdentifier<'a>, + + /// Salt length + pub salt_len: u8, + + /// Trailer field (i.e. [`TrailerField::BC`]) + pub trailer_field: TrailerField, +} + +impl<'a> Default for RsaPssParams<'a> { + fn default() -> Self { + Self { + hash: SHA_1_AI, + mask_gen: default_mgf1_sha1(), + salt_len: SALT_LEN_DEFAULT, + trailer_field: Default::default(), + } + } +} + +impl<'a> DecodeValue<'a> for RsaPssParams<'a> { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: der::Header) -> der::Result<Self> { + reader.read_nested(header.length, |reader| { + Ok(Self { + hash: reader + .context_specific(TagNumber::N0, TagMode::Explicit)? + .unwrap_or(SHA_1_AI), + mask_gen: reader + .context_specific(TagNumber::N1, TagMode::Explicit)? + .unwrap_or_else(default_mgf1_sha1), + salt_len: reader + .context_specific(TagNumber::N2, TagMode::Explicit)? + .unwrap_or(SALT_LEN_DEFAULT), + trailer_field: reader + .context_specific(TagNumber::N3, TagMode::Explicit)? + .unwrap_or_default(), + }) + }) + } +} + +impl<'a> Sequence<'a> for RsaPssParams<'a> { + fn fields<F, T>(&self, f: F) -> der::Result<T> + where + F: FnOnce(&[&dyn Encode]) -> der::Result<T>, + { + f(&[ + &if self.hash == SHA_1_AI { + None + } else { + Some(ContextSpecificRef { + tag_number: TagNumber::N0, + tag_mode: TagMode::Explicit, + value: &self.hash, + }) + }, + &if self.mask_gen == default_mgf1_sha1() { + None + } else { + Some(ContextSpecificRef { + tag_number: TagNumber::N1, + tag_mode: TagMode::Explicit, + value: &self.mask_gen, + }) + }, + &if self.salt_len == SALT_LEN_DEFAULT { + None + } else { + Some(ContextSpecificRef { + tag_number: TagNumber::N2, + tag_mode: TagMode::Explicit, + value: &self.salt_len, + }) + }, + &if self.trailer_field == TrailerField::default() { + None + } else { + Some(ContextSpecificRef { + tag_number: TagNumber::N3, + tag_mode: TagMode::Explicit, + value: &self.trailer_field, + }) + }, + ]) + } +} + +impl<'a> TryFrom<&'a [u8]> for RsaPssParams<'a> { + type Error = Error; + + fn try_from(bytes: &'a [u8]) -> Result<Self> { + Ok(Self::from_der(bytes)?) + } +} + +/// Default Mask Generation Function (MGF): SHA-1. +fn default_mgf1_sha1<'a>() -> AlgorithmIdentifier<'a> { + AlgorithmIdentifier { + oid: OID_MGF_1, + parameters: Some( + AnyRef::new(Tag::Sequence, SEQ_OID_SHA_1_DER) + .expect("error creating default MGF1 params"), + ), + } +} + +/// PKCS#1 RSAES-OAEP parameters as defined in [RFC 8017 Appendix 2.1] +/// +/// ASN.1 structure containing a serialized RSAES-OAEP parameters: +/// ```text +/// RSAES-OAEP-params ::= SEQUENCE { +/// hashAlgorithm [0] HashAlgorithm DEFAULT sha1, +/// maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1, +/// pSourceAlgorithm [2] PSourceAlgorithm DEFAULT pSpecifiedEmpty +/// } +/// HashAlgorithm ::= AlgorithmIdentifier +/// MaskGenAlgorithm ::= AlgorithmIdentifier +/// PSourceAlgorithm ::= AlgorithmIdentifier +/// ``` +/// +/// [RFC 8017 Appendix 2.1]: https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.2.1 +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct RsaOaepParams<'a> { + /// Hash Algorithm + pub hash: AlgorithmIdentifier<'a>, + + /// Mask Generation Function (MGF) + pub mask_gen: AlgorithmIdentifier<'a>, + + /// The source (and possibly the value) of the label L + pub p_source: AlgorithmIdentifier<'a>, +} + +impl<'a> Default for RsaOaepParams<'a> { + fn default() -> Self { + Self { + hash: SHA_1_AI, + mask_gen: default_mgf1_sha1(), + p_source: default_pempty_string(), + } + } +} + +impl<'a> DecodeValue<'a> for RsaOaepParams<'a> { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: der::Header) -> der::Result<Self> { + reader.read_nested(header.length, |reader| { + Ok(Self { + hash: reader + .context_specific(TagNumber::N0, TagMode::Explicit)? + .unwrap_or(SHA_1_AI), + mask_gen: reader + .context_specific(TagNumber::N1, TagMode::Explicit)? + .unwrap_or_else(default_mgf1_sha1), + p_source: reader + .context_specific(TagNumber::N2, TagMode::Explicit)? + .unwrap_or_else(default_pempty_string), + }) + }) + } +} + +impl<'a> Sequence<'a> for RsaOaepParams<'a> { + fn fields<F, T>(&self, f: F) -> der::Result<T> + where + F: FnOnce(&[&dyn Encode]) -> der::Result<T>, + { + f(&[ + &if self.hash == SHA_1_AI { + None + } else { + Some(ContextSpecificRef { + tag_number: TagNumber::N0, + tag_mode: TagMode::Explicit, + value: &self.hash, + }) + }, + &if self.mask_gen == default_mgf1_sha1() { + None + } else { + Some(ContextSpecificRef { + tag_number: TagNumber::N1, + tag_mode: TagMode::Explicit, + value: &self.mask_gen, + }) + }, + &if self.p_source == default_pempty_string() { + None + } else { + Some(ContextSpecificRef { + tag_number: TagNumber::N2, + tag_mode: TagMode::Explicit, + value: &self.p_source, + }) + }, + ]) + } +} + +impl<'a> TryFrom<&'a [u8]> for RsaOaepParams<'a> { + type Error = Error; + + fn try_from(bytes: &'a [u8]) -> Result<Self> { + Ok(Self::from_der(bytes)?) + } +} + +/// Default Source Algorithm, empty string +fn default_pempty_string<'a>() -> AlgorithmIdentifier<'a> { + AlgorithmIdentifier { + oid: OID_PSPECIFIED, + parameters: Some( + AnyRef::new(Tag::OctetString, &[]).expect("error creating default OAEP params"), + ), + } +} diff --git a/src/traits.rs b/src/traits.rs index edf06c1..c70820c 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -191,7 +191,7 @@ impl<T: pkcs8::DecodePublicKey> DecodeRsaPublicKey for T { } #[cfg(all(feature = "alloc", feature = "pkcs8"))] -#[cfg_attr(docsrs, doc(all(feature = "alloc", feature = "pkcs8")))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "pkcs8"))))] impl<T: pkcs8::EncodePrivateKey> EncodeRsaPrivateKey for T { fn to_pkcs1_der(&self) -> Result<SecretDocument> { let pkcs8_doc = self.to_pkcs8_der()?; @@ -202,7 +202,7 @@ impl<T: pkcs8::EncodePrivateKey> EncodeRsaPrivateKey for T { } #[cfg(all(feature = "alloc", feature = "pkcs8"))] -#[cfg_attr(docsrs, doc(all(feature = "alloc", feature = "pkcs8")))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "pkcs8"))))] impl<T: pkcs8::EncodePublicKey> EncodeRsaPublicKey for T { fn to_pkcs1_der(&self) -> Result<Document> { let doc = self.to_public_key_der()?; diff --git a/tests/params.rs b/tests/params.rs new file mode 100644 index 0000000..6954934 --- /dev/null +++ b/tests/params.rs @@ -0,0 +1,178 @@ +//! PKCS#1 algorithm params tests + +use const_oid::db; +use der::{ + asn1::{ObjectIdentifier, OctetStringRef}, + Decode, Encode, +}; +use hex_literal::hex; +use pkcs1::{RsaOaepParams, RsaPssParams, TrailerField}; + +/// Default PSS parameters using all default values (SHA1, MGF1) +const RSA_PSS_PARAMETERS_DEFAULTS: &[u8] = &hex!("3000"); +/// Example PSS parameters using SHA256 instead of SHA1 +const RSA_PSS_PARAMETERS_SHA2_256: &[u8] = &hex!("3030a00d300b0609608648016503040201a11a301806092a864886f70d010108300b0609608648016503040201a203020120"); + +/// Default OAEP parameters using all default values (SHA1, MGF1, Empty) +const RSA_OAEP_PARAMETERS_DEFAULTS: &[u8] = &hex!("3000"); +/// Example OAEP parameters using SHA256 instead of SHA1 and 'abc' as label +const RSA_OAEP_PARAMETERS_SHA2_256: &[u8] = &hex!("303fa00d300b0609608648016503040201a11a301806092a864886f70d010108300b0609608648016503040201a212301006092a864886f70d0101090403abcdef"); + +#[test] +fn decode_pss_param() { + let param = RsaPssParams::try_from(RSA_PSS_PARAMETERS_SHA2_256).unwrap(); + + assert!(param + .hash + .assert_algorithm_oid(db::rfc5912::ID_SHA_256) + .is_ok()); + assert_eq!(param.hash.parameters, None); + assert!(param + .mask_gen + .assert_algorithm_oid(db::rfc5912::ID_MGF_1) + .is_ok()); + assert_eq!( + param + .mask_gen + .parameters_any() + .unwrap() + .sequence(|reader| Ok(ObjectIdentifier::decode(reader)?)) + .unwrap(), + db::rfc5912::ID_SHA_256 + ); + assert_eq!(param.salt_len, 32); + assert_eq!(param.trailer_field, TrailerField::BC); +} + +#[test] +fn encode_pss_param() { + let mut buf = [0_u8; 256]; + let param = RsaPssParams::try_from(RSA_PSS_PARAMETERS_SHA2_256).unwrap(); + assert_eq!( + param.encode_to_slice(&mut buf).unwrap(), + RSA_PSS_PARAMETERS_SHA2_256 + ); +} + +#[test] +fn decode_pss_param_default() { + let param = RsaPssParams::try_from(RSA_PSS_PARAMETERS_DEFAULTS).unwrap(); + + assert!(param + .hash + .assert_algorithm_oid(db::rfc5912::ID_SHA_1) + .is_ok()); + assert_eq!(param.hash.parameters, None); + assert!(param + .mask_gen + .assert_algorithm_oid(db::rfc5912::ID_MGF_1) + .is_ok()); + assert_eq!( + param + .mask_gen + .parameters_any() + .unwrap() + .sequence(|reader| Ok(ObjectIdentifier::decode(reader)?)) + .unwrap(), + db::rfc5912::ID_SHA_1 + ); + assert_eq!(param.salt_len, 20); + assert_eq!(param.trailer_field, TrailerField::BC); + assert_eq!(param, Default::default()) +} + +#[test] +fn encode_pss_param_default() { + let mut buf = [0_u8; 256]; + assert_eq!( + RsaPssParams::default().encode_to_slice(&mut buf).unwrap(), + RSA_PSS_PARAMETERS_DEFAULTS + ); +} + +#[test] +fn decode_oaep_param() { + let param = RsaOaepParams::try_from(RSA_OAEP_PARAMETERS_SHA2_256).unwrap(); + + assert!(param + .hash + .assert_algorithm_oid(db::rfc5912::ID_SHA_256) + .is_ok()); + assert_eq!(param.hash.parameters, None); + assert!(param + .mask_gen + .assert_algorithm_oid(db::rfc5912::ID_MGF_1) + .is_ok()); + assert_eq!( + param + .mask_gen + .parameters_any() + .unwrap() + .sequence(|reader| Ok(ObjectIdentifier::decode(reader)?)) + .unwrap(), + db::rfc5912::ID_SHA_256 + ); + assert!(param + .p_source + .assert_algorithm_oid(db::rfc5912::ID_P_SPECIFIED) + .is_ok()); + assert_eq!( + param.p_source.parameters_any().unwrap().octet_string(), + OctetStringRef::new(&[0xab, 0xcd, 0xef]) + ); +} + +#[test] +fn encode_oaep_param() { + let mut buf = [0_u8; 256]; + let param = RsaOaepParams::try_from(RSA_OAEP_PARAMETERS_SHA2_256).unwrap(); + assert_eq!( + param.encode_to_slice(&mut buf).unwrap(), + RSA_OAEP_PARAMETERS_SHA2_256 + ); +} + +#[test] +fn decode_oaep_param_default() { + let param = RsaOaepParams::try_from(RSA_OAEP_PARAMETERS_DEFAULTS).unwrap(); + + assert!(param + .hash + .assert_algorithm_oid(db::rfc5912::ID_SHA_1) + .is_ok()); + assert_eq!(param.hash.parameters, None); + assert!(param + .mask_gen + .assert_algorithm_oid(db::rfc5912::ID_MGF_1) + .is_ok()); + assert_eq!( + param + .mask_gen + .parameters_any() + .unwrap() + .sequence(|reader| Ok(ObjectIdentifier::decode(reader)?)) + .unwrap(), + db::rfc5912::ID_SHA_1 + ); + assert!(param + .p_source + .assert_algorithm_oid(db::rfc5912::ID_P_SPECIFIED) + .is_ok()); + assert!(param + .p_source + .parameters_any() + .unwrap() + .octet_string() + .unwrap() + .is_empty(),); + assert_eq!(param, Default::default()) +} + +#[test] +fn encode_oaep_param_default() { + let mut buf = [0_u8; 256]; + assert_eq!( + RsaOaepParams::default().encode_to_slice(&mut buf).unwrap(), + RSA_OAEP_PARAMETERS_DEFAULTS + ); +} |