aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Homescu <ahomescu@google.com>2023-10-17 05:33:35 +0000
committerAndrei Homescu <ahomescu@google.com>2023-10-17 05:33:35 +0000
commitcfc10a48c9c41ab07dc6be784cfb21924816c298 (patch)
treee726628e5026cef9872427ab8c3ad3136d54ccb5
parentae5c9913e1c4452cf99c8dcecc0540c78c04fb22 (diff)
parentfc8029addeafaa6db706ec9597e34ff6fc2e8d75 (diff)
downloadpkcs1-cfc10a48c9c41ab07dc6be784cfb21924816c298.tar.gz
Merge remote-tracking branch 'aosp/main' into trusty-main
Change-Id: I9a0aa36d5c2f43b9a01ab46d0be8e6ef462a2e9e
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp62
-rw-r--r--CHANGELOG.md8
-rw-r--r--Cargo.toml10
-rw-r--r--Cargo.toml.orig4
-rw-r--r--LICENSE-MIT25
-rw-r--r--METADATA13
-rw-r--r--OWNERS3
-rw-r--r--cargo2android.json15
-rw-r--r--cargo2android_viz.bp3
-rw-r--r--src/lib.rs9
-rw-r--r--src/params.rs301
-rw-r--r--src/traits.rs4
-rw-r--r--tests/params.rs178
14 files changed, 619 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
diff --git a/Android.bp b/Android.bp
index 0a832ba..7a44be6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,13 +1,41 @@
// 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"],
+}
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "external_rust_crates_pkcs1_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-MIT",
+ ],
+ license_text: [
+ "LICENSE-APACHE",
+ ],
+}
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: [
@@ -18,11 +46,43 @@ rust_library_host {
rustlibs: [
"libder",
"libpkcs8",
+ "libspki",
"libzeroize",
],
+}
+
+rust_library_rlib {
+ name: "libpkcs1_nostd",
+ crate_name: "pkcs1",
+ cargo_env_compat: true,
+ cargo_pkg_version: "0.4.1",
+ srcs: ["src/lib.rs"],
+ edition: "2021",
+ features: [
+ "alloc",
+ "pkcs8",
+ "zeroize",
+ ],
+ rustlibs: [
+ "libder_nostd",
+ "libpkcs8_nostd",
+ "libspki_nostd",
+ "libzeroize_nostd",
+ ],
apex_available: [
"//apex_available:platform",
"com.android.virt",
],
+ prefer_rlib: true,
+ no_stdlibs: true,
+ stdlibs: [
+ "libcompiler_builtins.rust_sysroot",
+ "libcore.rust_sysroot",
+ ],
+ product_available: true,
vendor_available: true,
+ visibility: [
+ "//system/keymint:__subpackages__",
+ ]
+ ,
}
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])
diff --git a/Cargo.toml b/Cargo.toml
index e193698..b73c625 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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.
diff --git a/METADATA b/METADATA
index a0641dd..51c2998 100644
--- a/METADATA
+++ b/METADATA
@@ -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
}
}
diff --git a/OWNERS b/OWNERS
index 45dc4dd..19b0fa7 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1 +1,2 @@
-include platform/prebuilts/rust:master:/OWNERS
+
+include platform/prebuilts/rust:main:/OWNERS
diff --git a/cargo2android.json b/cargo2android.json
index e26e552..e6baa85 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -5,5 +5,18 @@
],
"run": true,
"vendor-available": true,
- "features": "alloc"
+ "features": "alloc",
+ "variants": [
+ {
+ },
+ {
+ "device": true,
+ "no-host": true,
+ "add-module-block": "cargo2android_viz.bp",
+ "dependency_suffix": "_nostd",
+ "force-rlib": true,
+ "suffix": "_nostd",
+ "no-std": true
+ }
+ ]
}
diff --git a/cargo2android_viz.bp b/cargo2android_viz.bp
new file mode 100644
index 0000000..6912520
--- /dev/null
+++ b/cargo2android_viz.bp
@@ -0,0 +1,3 @@
+visibility: [
+ "//system/keymint:__subpackages__",
+]
diff --git a/src/lib.rs b/src/lib.rs
index edbb128..9176c8d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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
+ );
+}