Skip to content

Commit

Permalink
Start collection of basic data types
Browse files Browse the repository at this point in the history
  • Loading branch information
djc committed Aug 30, 2023
1 parent 8aa6571 commit bbc05a8
Show file tree
Hide file tree
Showing 2 changed files with 330 additions and 13 deletions.
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[package]
name = "rustls-pki-types"
version = "0.1.0"
version = "1.0.0-alpha.1"
edition = "2021"
rust-version = "1.60"
license = "MIT OR Apache-2.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
[features]
default = ["alloc"]
alloc = []
335 changes: 326 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,331 @@
pub fn add(left: usize, right: usize) -> usize {
left + right
#![no_std]
#![warn(unreachable_pub)]
#![warn(clippy::use_self)]

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::fmt;
use core::ops::Deref;

/// 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> {
Pkcs1(PrivatePkcs1KeyDer<'a>),
Sec1(PrivateSec1KeyDer<'a>),
Pkcs8(PrivatePkcs8KeyDer<'a>),
}

impl<'a> PrivateKeyDer<'a> {
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(),
}
}
}

/// A DER-encoded plaintext RSA private key; as specified in PKCS#1/RFC 3447
///
/// A common format for storing private keys is
/// [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail).
/// PEM blocks for RSA (PKCS#1) private keys are commonly stored in files with a `.pem` or `.key`
/// suffix, and look like this:
///
/// ```txt
/// -----BEGIN RSA PRIVATE KEY-----
/// <base64-encoded certificate content>
/// -----END RSA PRIVATE KEY-----
/// ```
///
/// The [`rustls-pemfile`](https://docs.rs/rustls-pemfile/latest/rustls_pemfile/) crate can be used
/// to parse PEM files. The [`rcgen`](https://docs.rs/rcgen/latest/rcgen/) crate can be used to
/// generate certificates and private keys.
#[derive(PartialEq)]
pub struct PrivatePkcs1KeyDer<'a>(Der<'a>);

impl PrivatePkcs1KeyDer<'_> {
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
///
/// A common format for storing private keys is
/// [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail).
/// PEM blocks for Sec1 private keys are commonly stored in files with a `.pem` or `.key`
/// suffix, and look like this:
///
/// ```txt
/// -----BEGIN EC PRIVATE KEY-----
/// <base64-encoded certificate content>
/// -----END EC PRIVATE KEY-----
/// ```
///
/// The [`rustls-pemfile`](https://docs.rs/rustls-pemfile/latest/rustls_pemfile/) crate can be used
/// to parse PEM files. The [`rcgen`](https://docs.rs/rcgen/latest/rcgen/) crate can be used to
/// generate certificates and private keys.
#[derive(PartialEq)]
pub struct PrivateSec1KeyDer<'a>(Der<'a>);

impl PrivateSec1KeyDer<'_> {
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
///
/// A common format for storing private keys is
/// [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail).
/// PEM blocks for PKCS#8 private keys are commonly stored in files with a `.pem` or `.key`
/// suffix, and look like this:
///
/// ```txt
/// -----BEGIN PRIVATE KEY-----
/// <base64-encoded certificate content>
/// -----END PRIVATE KEY-----
/// ```
///
/// The [`rustls-pemfile`](https://docs.rs/rustls-pemfile/latest/rustls_pemfile/) crate can be used
/// to parse PEM files. The [`rcgen`](https://docs.rs/rcgen/latest/rcgen/) crate can be used to
/// generate certificates and private keys.
/// ```
#[derive(PartialEq)]
pub struct PrivatePkcs8KeyDer<'a>(Der<'a>);

impl PrivatePkcs8KeyDer<'_> {
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), represented as a DER-encoded X.509 certificate
///
/// 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> {
pub subject: Der<'a>,
pub subject_public_key_info: Der<'a>,
pub name_constraints: Option<Der<'a>>,
}

impl TrustAnchor<'_> {
#[cfg(feature = "alloc")]
pub fn to_owned(&self) -> TrustAnchor<'static> {
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
#[derive(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
///
/// A common format for storing certificates is
/// [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail).
/// PEM certificates are commonly stored in files with a `.pem`, `.cer` or `.crt` suffix, and look
/// like this:
///
/// ```txt
/// -----BEGIN BEGIN EC PRIVATE KEY-----
/// <base64-encoded certificate content>
/// -----END CERTIFICATE-----
/// ```
///
/// The [`rustls-pemfile`](https://docs.rs/rustls-pemfile/latest/rustls_pemfile/) crate can be used
/// to parse PEM files. The [`rcgen`](https://docs.rs/rcgen/latest/rcgen/) crate can be used to
/// generate certificates and private keys.
/// ```
#[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()
}
}

#[cfg(test)]
mod tests {
use super::*;
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))
}
}

#[derive(Clone, PartialEq)]
pub struct Der<'a>(DerInner<'a>);

impl<'a> Der<'a> {
// Trait methods cannot be const, so we additionally offer some traditional constructors.
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,
}
}
}

#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
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<'a> From<Vec<u8>> for Der<'a> {
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]),
}

0 comments on commit bbc05a8

Please sign in to comment.