mirror of https://github.com/ctz/rustls
Merge pki-types history into rustls monorepo
This commit is contained in:
commit
047658675c
|
@ -1710,7 +1710,7 @@ dependencies = [
|
|||
"log",
|
||||
"ring 0.17.5",
|
||||
"rustls-pemfile 2.0.0-alpha.1",
|
||||
"rustls-pki-types",
|
||||
"rustls-pki-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustls-webpki 0.102.0-alpha.6",
|
||||
"rustversion",
|
||||
"subtle",
|
||||
|
@ -1730,7 +1730,7 @@ dependencies = [
|
|||
"rayon",
|
||||
"rustls 0.22.0-alpha.4",
|
||||
"rustls-pemfile 2.0.0-alpha.1",
|
||||
"rustls-pki-types",
|
||||
"rustls-pki-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1754,7 +1754,7 @@ dependencies = [
|
|||
"rcgen",
|
||||
"rustls 0.22.0-alpha.4",
|
||||
"rustls-pemfile 2.0.0-alpha.1",
|
||||
"rustls-pki-types",
|
||||
"rustls-pki-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"webpki-roots 0.26.0-alpha.1",
|
||||
|
@ -1776,9 +1776,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "4aaa4fe93b39faddb6a8f99568c3e5880680156da0d46818e884a071381f67fe"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"rustls-pki-types",
|
||||
"rustls-pki-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pki-types"
|
||||
version = "0.2.1"
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pki-types"
|
||||
version = "0.2.1"
|
||||
|
@ -1804,7 +1808,7 @@ dependencies = [
|
|||
"rcgen",
|
||||
"rsa",
|
||||
"rustls 0.22.0-alpha.4",
|
||||
"rustls-pki-types",
|
||||
"rustls-pki-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustls-webpki 0.102.0-alpha.6",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -1832,7 +1836,7 @@ checksum = "34d9ed3a8267782ba32d257ff5b197b63eef19a467dbd1be011caaae35ee416e"
|
|||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"ring 0.17.5",
|
||||
"rustls-pki-types",
|
||||
"rustls-pki-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"untrusted 0.9.0",
|
||||
]
|
||||
|
||||
|
@ -2326,7 +2330,7 @@ version = "0.26.0-alpha.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42157929d7ca9c353222a4d1763c52ef86d25d0fd2eca66076df5975fd4e25ed"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
"rustls-pki-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -6,6 +6,8 @@ members = [
|
|||
"connect-tests",
|
||||
# tests and example code
|
||||
"examples",
|
||||
# the pki-types library
|
||||
"pki-types",
|
||||
# the main library and tests
|
||||
"rustls",
|
||||
# example of custom provider
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
[package]
|
||||
name = "rustls-pki-types"
|
||||
version = "0.2.1"
|
||||
edition = "2021"
|
||||
rust-version = "1.60"
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "Shared types for the rustls PKI ecosystem"
|
||||
documentation = "https://docs.rs/rustls-pki-types"
|
||||
homepage = "https://github.com/rustls/pki-types"
|
||||
repository = "https://github.com/rustls/pki-types"
|
||||
categories = ["network-programming", "data-structures", "cryptography"]
|
||||
|
||||
[features]
|
||||
default = ["alloc"]
|
||||
alloc = []
|
||||
std = ["alloc"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2023 Dirkjan Ochtman
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2023 Dirkjan Ochtman <dirkjan@ochtman.nl>
|
||||
|
||||
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.
|
|
@ -0,0 +1,40 @@
|
|||
# rustls-pki-types
|
||||
|
||||
[![Build Status](https://github.com/rustls/pki-types/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/rustls/pki-types/actions/workflows/ci.yml?query=branch%3Amain)
|
||||
[![Documentation](https://docs.rs/rustls-pki-types/badge.svg)](https://docs.rs/rustls-pki-types/)
|
||||
[![Chat](https://img.shields.io/discord/976380008299917365?logo=discord)](https://discord.gg/MCSB76RU96)
|
||||
|
||||
This crate provides types for representing X.509 certificates, keys and other types as commonly
|
||||
used in the rustls ecosystem. It is intended to be used by crates that need to work with such X.509
|
||||
types, such as [rustls](https://crates.io/crates/rustls),
|
||||
[rustls-webpki](https://crates.io/crates/rustls-webpki),
|
||||
[rustls-pemfile](https://crates.io/crates/rustls-pemfile), and others.
|
||||
|
||||
Some of these crates used to define their own trivial wrappers around DER-encoded bytes.
|
||||
However, in order to avoid inconvenient dependency edges, these were all disconnected. By
|
||||
using a common low-level crate of types with long-term stable API, we hope to avoid the
|
||||
downsides of unnecessary dependency edges while providing interoperability between crates.
|
||||
|
||||
## Features
|
||||
|
||||
- Interoperability between different crates in the rustls ecosystem
|
||||
- Long-term stable API
|
||||
- No dependencies
|
||||
- Support for `no_std` contexts, with optional support for `alloc`
|
||||
|
||||
## DER and PEM
|
||||
|
||||
Many of the types defined in this crate represent DER-encoded data. DER is a binary encoding of
|
||||
the ASN.1 format commonly used in web PKI specifications. It is a binary encoding, so it is
|
||||
relatively compact when stored in memory. However, as a binary format, it is not very easy to
|
||||
work with for humans and in contexts where binary data is inconvenient. For this reason,
|
||||
many tools and protocols use a ASCII-based encoding of DER, called PEM. In addition to the
|
||||
base64-encoded DER, PEM objects are delimited by header and footer lines which indicate the type
|
||||
of object contained in the PEM blob.
|
||||
|
||||
The [rustls-pemfile](https://docs.rs/rustls-pemfile) crate can be used to parse PEM files.
|
||||
|
||||
## Creating new certificates and keys
|
||||
|
||||
This crate does not provide any functionality for creating new certificates or keys. However,
|
||||
the [rcgen](https://docs.rs/rcgen) crate can be used to create new certificates and keys.
|
|
@ -0,0 +1,491 @@
|
|||
//! This crate provides types for representing X.509 certificates, keys and other types as
|
||||
//! commonly used in the rustls ecosystem. It is intended to be used by crates that need to work
|
||||
//! with such X.509 types, such as [rustls](https://crates.io/crates/rustls),
|
||||
//! [rustls-webpki](https://crates.io/crates/rustls-webpki),
|
||||
//! [rustls-pemfile](https://crates.io/crates/rustls-pemfile), and others.
|
||||
//!
|
||||
//! Some of these crates used to define their own trivial wrappers around DER-encoded bytes.
|
||||
//! However, in order to avoid inconvenient dependency edges, these were all disconnected. By
|
||||
//! using a common low-level crate of types with long-term stable API, we hope to avoid the
|
||||
//! downsides of unnecessary dependency edges while providing good interoperability between crates.
|
||||
//!
|
||||
//! ## DER and PEM
|
||||
//!
|
||||
//! Many of the types defined in this crate represent DER-encoded data. DER is a binary encoding of
|
||||
//! the ASN.1 format commonly used in web PKI specifications. It is a binary encoding, so it is
|
||||
//! relatively compact when stored in memory. However, as a binary format, it is not very easy to
|
||||
//! work with for humans and in contexts where binary data is inconvenient. For this reason,
|
||||
//! many tools and protocols use a ASCII-based encoding of DER, called PEM. In addition to the
|
||||
//! base64-encoded DER, PEM objects are delimited by header and footer lines which indicate the type
|
||||
//! of object contained in the PEM blob.
|
||||
//!
|
||||
//! The [rustls-pemfile](https://docs.rs/rustls-pemfile) crate can be used to parse PEM files.
|
||||
//!
|
||||
//! ## Creating new certificates and keys
|
||||
//!
|
||||
//! This crate does not provide any functionality for creating new certificates or keys. However,
|
||||
//! the [rcgen](https://docs.rs/rcgen) crate can be used to create new certificates and keys.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![warn(unreachable_pub, clippy::use_self)]
|
||||
#![deny(missing_docs)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt;
|
||||
use core::ops::Deref;
|
||||
use core::time::Duration;
|
||||
#[cfg(feature = "std")]
|
||||
use std::time::SystemTime;
|
||||
|
||||
/// A DER-encoded X.509 private key, in one of several formats
|
||||
///
|
||||
/// See variant inner types for more detailed information.
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PrivateKeyDer<'a> {
|
||||
/// An RSA private key
|
||||
Pkcs1(PrivatePkcs1KeyDer<'a>),
|
||||
/// A Sec1 private key
|
||||
Sec1(PrivateSec1KeyDer<'a>),
|
||||
/// A PKCS#8 private key
|
||||
Pkcs8(PrivatePkcs8KeyDer<'a>),
|
||||
}
|
||||
|
||||
impl<'a> PrivateKeyDer<'a> {
|
||||
/// Yield the DER-encoded bytes of the private key
|
||||
pub fn secret_der(&self) -> &[u8] {
|
||||
match self {
|
||||
PrivateKeyDer::Pkcs1(key) => key.secret_pkcs1_der(),
|
||||
PrivateKeyDer::Sec1(key) => key.secret_sec1_der(),
|
||||
PrivateKeyDer::Pkcs8(key) => key.secret_pkcs8_der(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<PrivatePkcs1KeyDer<'a>> for PrivateKeyDer<'a> {
|
||||
fn from(key: PrivatePkcs1KeyDer<'a>) -> Self {
|
||||
Self::Pkcs1(key)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<PrivateSec1KeyDer<'a>> for PrivateKeyDer<'a> {
|
||||
fn from(key: PrivateSec1KeyDer<'a>) -> Self {
|
||||
Self::Sec1(key)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<PrivatePkcs8KeyDer<'a>> for PrivateKeyDer<'a> {
|
||||
fn from(key: PrivatePkcs8KeyDer<'a>) -> Self {
|
||||
Self::Pkcs8(key)
|
||||
}
|
||||
}
|
||||
|
||||
/// A DER-encoded plaintext RSA private key; as specified in PKCS#1/RFC 3447
|
||||
///
|
||||
/// RSA private keys are identified in PEM context as `RSA PRIVATE KEY` and when stored in a
|
||||
/// file usually use a `.pem` or `.key` extension. For more on PEM files, refer to the crate
|
||||
/// documentation.
|
||||
#[derive(PartialEq)]
|
||||
pub struct PrivatePkcs1KeyDer<'a>(Der<'a>);
|
||||
|
||||
impl PrivatePkcs1KeyDer<'_> {
|
||||
/// Yield the DER-encoded bytes of the private key
|
||||
pub fn secret_pkcs1_der(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a [u8]> for PrivatePkcs1KeyDer<'a> {
|
||||
fn from(slice: &'a [u8]) -> Self {
|
||||
Self(Der(DerInner::Borrowed(slice)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<'a> From<Vec<u8>> for PrivatePkcs1KeyDer<'a> {
|
||||
fn from(vec: Vec<u8>) -> Self {
|
||||
Self(Der(DerInner::Owned(vec)))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for PrivatePkcs1KeyDer<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("PrivatePkcs1KeyDer")
|
||||
.field(&"[secret key elided]")
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A Sec1-encoded plaintext private key; as specified in RFC 5915
|
||||
///
|
||||
/// Sec1 private keys are identified in PEM context as `EC PRIVATE KEY` and when stored in a
|
||||
/// file usually use a `.pem` or `.key` extension. For more on PEM files, refer to the crate
|
||||
/// documentation.
|
||||
#[derive(PartialEq)]
|
||||
pub struct PrivateSec1KeyDer<'a>(Der<'a>);
|
||||
|
||||
impl PrivateSec1KeyDer<'_> {
|
||||
/// Yield the DER-encoded bytes of the private key
|
||||
pub fn secret_sec1_der(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a [u8]> for PrivateSec1KeyDer<'a> {
|
||||
fn from(slice: &'a [u8]) -> Self {
|
||||
Self(Der(DerInner::Borrowed(slice)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<'a> From<Vec<u8>> for PrivateSec1KeyDer<'a> {
|
||||
fn from(vec: Vec<u8>) -> Self {
|
||||
Self(Der(DerInner::Owned(vec)))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for PrivateSec1KeyDer<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("PrivatePkcs1KeyDer")
|
||||
.field(&"[secret key elided]")
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A DER-encoded plaintext private key; as specified in PKCS#8/RFC 5958
|
||||
///
|
||||
/// PKCS#8 private keys are identified in PEM context as `PRIVATE KEY` and when stored in a
|
||||
/// file usually use a `.pem` or `.key` extension. For more on PEM files, refer to the crate
|
||||
/// documentation.
|
||||
#[derive(PartialEq)]
|
||||
pub struct PrivatePkcs8KeyDer<'a>(Der<'a>);
|
||||
|
||||
impl PrivatePkcs8KeyDer<'_> {
|
||||
/// Yield the DER-encoded bytes of the private key
|
||||
pub fn secret_pkcs8_der(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a [u8]> for PrivatePkcs8KeyDer<'a> {
|
||||
fn from(slice: &'a [u8]) -> Self {
|
||||
Self(Der(DerInner::Borrowed(slice)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<'a> From<Vec<u8>> for PrivatePkcs8KeyDer<'a> {
|
||||
fn from(vec: Vec<u8>) -> Self {
|
||||
Self(Der(DerInner::Owned(vec)))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for PrivatePkcs8KeyDer<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("PrivatePkcs1KeyDer")
|
||||
.field(&"[secret key elided]")
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A trust anchor (a.k.a. root CA)
|
||||
///
|
||||
/// Traditionally, certificate verification libraries have represented trust anchors as full X.509
|
||||
/// root certificates. However, those certificates contain a lot more data than is needed for
|
||||
/// verifying certificates. The [`TrustAnchor`] representation allows an application to store
|
||||
/// just the essential elements of trust anchors.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct TrustAnchor<'a> {
|
||||
/// Value of the `subject` field of the trust anchor
|
||||
pub subject: Der<'a>,
|
||||
/// Value of the `subjectPublicKeyInfo` field of the trust anchor
|
||||
pub subject_public_key_info: Der<'a>,
|
||||
/// Value of DER-encoded `NameConstraints`, containing name constraints to the trust anchor, if any
|
||||
pub name_constraints: Option<Der<'a>>,
|
||||
}
|
||||
|
||||
impl TrustAnchor<'_> {
|
||||
/// Yield a `'static` lifetime of the `TrustAnchor` by allocating owned `Der` variants
|
||||
#[cfg(feature = "alloc")]
|
||||
pub fn to_owned(&self) -> TrustAnchor<'static> {
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::borrow::ToOwned;
|
||||
TrustAnchor {
|
||||
subject: self.subject.as_ref().to_owned().into(),
|
||||
subject_public_key_info: self
|
||||
.subject_public_key_info
|
||||
.as_ref()
|
||||
.to_owned()
|
||||
.into(),
|
||||
name_constraints: self
|
||||
.name_constraints
|
||||
.as_ref()
|
||||
.map(|nc| nc.as_ref().to_owned().into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A Certificate Revocation List; as specified in RFC 5280
|
||||
///
|
||||
/// Certificate revocation lists are identified in PEM context as `X509 CRL` and when stored in a
|
||||
/// file usually use a `.crl` extension. For more on PEM files, refer to the crate documentation.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct CertificateRevocationListDer<'a>(Der<'a>);
|
||||
|
||||
impl AsRef<[u8]> for CertificateRevocationListDer<'_> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for CertificateRevocationListDer<'_> {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a [u8]> for CertificateRevocationListDer<'a> {
|
||||
fn from(slice: &'a [u8]) -> Self {
|
||||
Self(Der::from(slice))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<'a> From<Vec<u8>> for CertificateRevocationListDer<'a> {
|
||||
fn from(vec: Vec<u8>) -> Self {
|
||||
Self(Der::from(vec))
|
||||
}
|
||||
}
|
||||
|
||||
/// A DER-encoded X.509 certificate; as specified in RFC 5280
|
||||
///
|
||||
/// Certificates are identified in PEM context as `CERTIFICATE` and when stored in a
|
||||
/// file usually use a `.pem`, `.cer` or `.crt` extension. For more on PEM files, refer to the
|
||||
/// crate documentation.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct CertificateDer<'a>(Der<'a>);
|
||||
|
||||
impl AsRef<[u8]> for CertificateDer<'_> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for CertificateDer<'_> {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a [u8]> for CertificateDer<'a> {
|
||||
fn from(slice: &'a [u8]) -> Self {
|
||||
Self(Der::from(slice))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<'a> From<Vec<u8>> for CertificateDer<'a> {
|
||||
fn from(vec: Vec<u8>) -> Self {
|
||||
Self(Der::from(vec))
|
||||
}
|
||||
}
|
||||
|
||||
/// An abstract signature verification algorithm.
|
||||
///
|
||||
/// One of these is needed per supported pair of public key type (identified
|
||||
/// with `public_key_alg_id()`) and `signatureAlgorithm` (identified with
|
||||
/// `signature_alg_id()`). Note that both of these `AlgorithmIdentifier`s include
|
||||
/// the parameters encoding, so separate `SignatureVerificationAlgorithm`s are needed
|
||||
/// for each possible public key or signature parameters.
|
||||
pub trait SignatureVerificationAlgorithm: Send + Sync {
|
||||
/// Verify a signature.
|
||||
///
|
||||
/// `public_key` is the `subjectPublicKey` value from a `SubjectPublicKeyInfo` encoding
|
||||
/// and is untrusted. The key's `subjectPublicKeyInfo` matches the [`AlgorithmIdentifier`]
|
||||
/// returned by `public_key_alg_id()`.
|
||||
///
|
||||
/// `message` is the data over which the signature was allegedly computed.
|
||||
/// It is not hashed; implementations of this trait function must do hashing
|
||||
/// if that is required by the algorithm they implement.
|
||||
///
|
||||
/// `signature` is the signature allegedly over `message`.
|
||||
///
|
||||
/// Return `Ok(())` only if `signature` is a valid signature on `message`.
|
||||
///
|
||||
/// Return `Err(InvalidSignature)` if the signature is invalid, including if the `public_key`
|
||||
/// encoding is invalid. There is no need or opportunity to produce errors
|
||||
/// that are more specific than this.
|
||||
fn verify_signature(
|
||||
&self,
|
||||
public_key: &[u8],
|
||||
message: &[u8],
|
||||
signature: &[u8],
|
||||
) -> Result<(), InvalidSignature>;
|
||||
|
||||
/// Return the `AlgorithmIdentifier` that must equal a public key's
|
||||
/// `subjectPublicKeyInfo` value for this `SignatureVerificationAlgorithm`
|
||||
/// to be used for signature verification.
|
||||
fn public_key_alg_id(&self) -> AlgorithmIdentifier;
|
||||
|
||||
/// Return the `AlgorithmIdentifier` that must equal the `signatureAlgorithm` value
|
||||
/// on the data to be verified for this `SignatureVerificationAlgorithm` to be used
|
||||
/// for signature verification.
|
||||
fn signature_alg_id(&self) -> AlgorithmIdentifier;
|
||||
}
|
||||
|
||||
/// A detail-less error when a signature is not valid.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct InvalidSignature;
|
||||
|
||||
/// A DER encoding of the PKIX AlgorithmIdentifier type:
|
||||
///
|
||||
/// ```ASN.1
|
||||
/// AlgorithmIdentifier ::= SEQUENCE {
|
||||
/// algorithm OBJECT IDENTIFIER,
|
||||
/// parameters ANY DEFINED BY algorithm OPTIONAL }
|
||||
/// -- contains a value of the type
|
||||
/// -- registered for use with the
|
||||
/// -- algorithm object identifier value
|
||||
/// ```
|
||||
/// (from <https://www.rfc-editor.org/rfc/rfc5280#section-4.1.1.2>)
|
||||
///
|
||||
/// The outer sequence encoding is *not included*, so this is the DER encoding
|
||||
/// of an OID for `algorithm` plus the `parameters` value.
|
||||
///
|
||||
/// For example, this is the `rsaEncryption` algorithm:
|
||||
///
|
||||
/// ```
|
||||
/// let rsa_encryption = rustls_pki_types::AlgorithmIdentifier::from_slice(
|
||||
/// &[
|
||||
/// // algorithm: 1.2.840.113549.1.1.1
|
||||
/// 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
|
||||
/// // parameters: NULL
|
||||
/// 0x05, 0x00
|
||||
/// ]
|
||||
/// );
|
||||
/// ```
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct AlgorithmIdentifier(&'static [u8]);
|
||||
|
||||
impl AlgorithmIdentifier {
|
||||
/// Makes a new `AlgorithmIdentifier` from a static octet slice.
|
||||
///
|
||||
/// This does not validate the contents of the slice.
|
||||
pub const fn from_slice(bytes: &'static [u8]) -> Self {
|
||||
Self(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for AlgorithmIdentifier {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for AlgorithmIdentifier {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
/// A timestamp, tracking the number of non-leap seconds since the Unix epoch.
|
||||
///
|
||||
/// The Unix epoch is defined January 1, 1970 00:00:00 UTC.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
|
||||
pub struct UnixTime(u64);
|
||||
|
||||
impl UnixTime {
|
||||
/// The current time, as a `UnixTime`
|
||||
#[cfg(feature = "std")]
|
||||
pub fn now() -> Self {
|
||||
Self::since_unix_epoch(
|
||||
SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.unwrap(), // Safe: this code did not exist before 1970.
|
||||
)
|
||||
}
|
||||
|
||||
/// Convert a `Duration` since the start of 1970 to a `UnixTime`
|
||||
///
|
||||
/// The `duration` must be relative to the Unix epoch.
|
||||
pub fn since_unix_epoch(duration: Duration) -> Self {
|
||||
Self(duration.as_secs())
|
||||
}
|
||||
|
||||
/// Number of seconds since the Unix epoch
|
||||
pub fn as_secs(&self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// DER-encoded data, either owned or borrowed
|
||||
///
|
||||
/// This wrapper type is used to represent DER-encoded data in a way that is agnostic to whether
|
||||
/// the data is owned (by a `Vec<u8>`) or borrowed (by a `&[u8]`). Support for the owned
|
||||
/// variant is only available when the `alloc` feature is enabled.
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Der<'a>(DerInner<'a>);
|
||||
|
||||
impl<'a> Der<'a> {
|
||||
/// A const constructor to create a `Der` from a borrowed slice
|
||||
pub const fn from_slice(der: &'a [u8]) -> Self {
|
||||
Self(DerInner::Borrowed(der))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Der<'_> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
match &self.0 {
|
||||
#[cfg(feature = "alloc")]
|
||||
DerInner::Owned(vec) => vec.as_ref(),
|
||||
DerInner::Borrowed(slice) => slice,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Der<'_> {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a [u8]> for Der<'a> {
|
||||
fn from(slice: &'a [u8]) -> Self {
|
||||
Self(DerInner::Borrowed(slice))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl From<Vec<u8>> for Der<'static> {
|
||||
fn from(vec: Vec<u8>) -> Self {
|
||||
Self(DerInner::Owned(vec))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Der<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Der")
|
||||
.field(&self.as_ref())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
enum DerInner<'a> {
|
||||
#[cfg(feature = "alloc")]
|
||||
Owned(Vec<u8>),
|
||||
Borrowed(&'a [u8]),
|
||||
}
|
Loading…
Reference in New Issue