This commit is contained in:
c0repwn3r 2023-05-02 12:51:48 -04:00
commit 171e9f3a20
Signed by: core
GPG Key ID: FDBF740DADDCEECF
13 changed files with 1128 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

12
.idea/e3pf.iml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="CPP_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/libepf/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/libepf/target" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/misc.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/e3pf.iml" filepath="$PROJECT_DIR$/.idea/e3pf.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

149
Cargo.lock generated Normal file
View File

@ -0,0 +1,149 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "libepf"
version = "0.1.0"
dependencies = [
"hex",
"pem",
"rmp-serde",
"serde",
"serde_arrays",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]]
name = "paste"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
[[package]]
name = "pem"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b13fe415cdf3c8e44518e18a7c95a13431d9bdf6d15367d82b23c377fdd441a"
dependencies = [
"base64",
"serde",
]
[[package]]
name = "proc-macro2"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rmp"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f"
dependencies = [
"byteorder",
"num-traits",
"paste",
]
[[package]]
name = "rmp-serde"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5b13be192e0220b8afb7222aa5813cb62cc269ebb5cac346ca6487681d2913e"
dependencies = [
"byteorder",
"rmp",
"serde",
]
[[package]]
name = "serde"
version = "1.0.160"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_arrays"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38636132857f68ec3d5f3eb121166d2af33cb55174c4d5ff645db6165cbef0fd"
dependencies = [
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.160"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"

4
Cargo.toml Normal file
View File

@ -0,0 +1,4 @@
[workspace]
members = [
"libepf"
]

7
libepf/Cargo.lock generated Normal file
View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "e3pf"
version = "0.1.0"

13
libepf/Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
name = "libepf"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { version = "1", features = ["derive"] }
serde_arrays = "0.1" # TODO: Remove. Pending on serde supporting const generics
rmp-serde = "1"
pem = "2"
hex = "0.4"

1
libepf/src/lib.rs Normal file
View File

@ -0,0 +1 @@
pub mod pki;

253
libepf/src/pki.rs Normal file
View File

@ -0,0 +1,253 @@
use std::collections::HashMap;
use std::error::Error;
use std::fmt::{Display, Formatter};
use pem::Pem;
use serde::{Deserialize, Serialize};
pub const EPFPKI_PUBLIC_KEY_LENGTH: usize = 32;
pub const EPFPKI_SIGNATURE_LENGTH: usize = 64;
pub type EpfPublicKey = [u8; 32];
pub type EpfPrivateKey = [u8; 64];
#[derive(Serialize, Deserialize, PartialEq, Debug, Eq)]
pub struct EPFCertificate {
pub details: EPFCertificateDetails,
pub fingerprint: String,
#[serde(with = "serde_arrays")]
pub signature: [u8; EPFPKI_SIGNATURE_LENGTH]
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Eq)]
pub struct EPFCertificateDetails {
pub name: String,
pub not_before: u64,
pub not_after: u64,
pub public_key: [u8; EPFPKI_PUBLIC_KEY_LENGTH],
pub issuer_name: String,
pub issuer_fingerprint: String,
pub claims: HashMap<String, String>
}
pub trait EpfPkiSerializable {
const PEM_BANNER: &'static str;
fn as_bytes(&self) -> Result<Vec<u8>, rmp_serde::encode::Error>;
fn from_bytes(bytes: &[u8]) -> Result<Self, rmp_serde::decode::Error> where Self: Sized;
fn as_pem(&self) -> Result<Vec<u8>, Box<dyn Error>>;
fn from_pem(bytes: &[u8]) -> Result<Self, Box<dyn Error>> where Self: Sized;
}
#[cfg_attr(tarpaulin, ignore)]
impl Display for EPFCertificate {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
writeln!(f, "EPFCertificate {{")?;
writeln!(f, "\tDetails: {{")?;
writeln!(f, "\t\tName: {}", self.details.name)?;
writeln!(f, "\t\tNot Before: {}", self.details.not_before)?;
writeln!(f, "\t\tNot After: {}", self.details.not_after)?;
writeln!(f, "\t\tPublic Key: {}", hex::encode(self.details.public_key))?;
writeln!(f, "\t\tIssuer: {{")?;
writeln!(f, "\t\t\tName: {}", self.details.issuer_name)?;
writeln!(f, "\t\t\tFingerprint: {}", self.details.issuer_fingerprint)?;
writeln!(f, "\t\t}}")?;
writeln!(f, "\t}}")?;
writeln!(f, "\tFingerprint: {}", self.fingerprint)?;
writeln!(f, "\tSignature: {}", hex::encode(self.signature))?;
writeln!(f, "}}")
}
}
impl EpfPkiSerializable for EPFCertificate {
const PEM_BANNER: &'static str = "EPF CERTIFICATE";
fn as_bytes(&self) -> Result<Vec<u8>, rmp_serde::encode::Error> {
rmp_serde::to_vec(self)
}
fn from_bytes(bytes: &[u8]) -> Result<Self, rmp_serde::decode::Error> {
rmp_serde::from_slice(bytes)
}
fn as_pem(&self) -> Result<Vec<u8>, Box<dyn Error>> {
Ok(pem::encode(&Pem::new(Self::PEM_BANNER, self.as_bytes()?)).as_bytes().to_vec())
}
fn from_pem(bytes: &[u8]) -> Result<Self, Box<dyn Error>> where Self: Sized {
let pem = pem::parse(bytes)?;
if pem.tag() != Self::PEM_BANNER {
return Err("Not a certificate".into())
}
Ok(Self::from_bytes(pem.contents())?)
}
}
impl EpfPkiSerializable for EpfPublicKey {
const PEM_BANNER: &'static str = "EPF PUBLIC KEY";
fn as_bytes(&self) -> Result<Vec<u8>, rmp_serde::encode::Error> {
Ok(self.to_vec())
}
fn from_bytes(bytes: &[u8]) -> Result<Self, rmp_serde::decode::Error> {
bytes.try_into().map_err(|_| rmp_serde::decode::Error::LengthMismatch(bytes.len() as u32))
}
fn as_pem(&self) -> Result<Vec<u8>, Box<dyn Error>> {
Ok(pem::encode(&Pem::new(Self::PEM_BANNER, self.as_bytes()?)).as_bytes().to_vec())
}
fn from_pem(bytes: &[u8]) -> Result<Self, Box<dyn Error>> where Self: Sized {
let pem = pem::parse(bytes)?;
if pem.tag() != Self::PEM_BANNER {
return Err("Not a public key".into())
}
Ok(Self::from_bytes(pem.contents())?)
}
}
impl EpfPkiSerializable for EpfPrivateKey {
const PEM_BANNER: &'static str = "EPF PRIVATE KEY";
fn as_bytes(&self) -> Result<Vec<u8>, rmp_serde::encode::Error> {
Ok(self.to_vec())
}
fn from_bytes(bytes: &[u8]) -> Result<Self, rmp_serde::decode::Error> {
bytes.try_into().map_err(|_| rmp_serde::decode::Error::LengthMismatch(bytes.len() as u32))
}
fn as_pem(&self) -> Result<Vec<u8>, Box<dyn Error>> {
Ok(pem::encode(&Pem::new(Self::PEM_BANNER, self.as_bytes()?)).as_bytes().to_vec())
}
fn from_pem(bytes: &[u8]) -> Result<Self, Box<dyn Error>> where Self: Sized {
let pem = pem::parse(bytes)?;
if pem.tag() != Self::PEM_BANNER {
return Err("Incorrect PEM tag".into())
}
Ok(Self::from_bytes(pem.contents())?)
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use crate::pki::{EPFCertificate, EPFCertificateDetails, EPFPKI_PUBLIC_KEY_LENGTH, EPFPKI_SIGNATURE_LENGTH, EpfPkiSerializable, EpfPrivateKey, EpfPublicKey};
#[test]
pub fn certificate_serialization() {
assert_eq!(cert().as_bytes().unwrap(), cert_bytes())
}
#[test]
pub fn certificate_deserialization() {
assert_eq!(EPFCertificate::from_bytes(&cert_bytes()).unwrap(), cert())
}
#[test]
pub fn certificate_serialization_pem() {
assert_eq!(cert().as_pem().unwrap(), cert_pem())
}
#[test]
pub fn certificate_deserialization_pem() {
assert_eq!(EPFCertificate::from_pem(&cert_pem()).unwrap(), cert())
}
#[test]
#[should_panic]
pub fn certificate_deserialization_pem_wrong_tag() {
EPFCertificate::from_pem(&null_public_key_pem()).unwrap();
}
#[test]
pub fn pubkey_serialization() {
assert_eq!(([0u8; 32]).as_bytes().unwrap(), [0u8; 32].to_vec())
}
#[test]
pub fn pubkey_deserialization() {
assert_eq!(EpfPublicKey::from_bytes(&[0u8; 32]).unwrap(), [0u8; 32])
}
#[test]
pub fn pubkey_serialization_pem() {
assert_eq!(([0u8; 32]).as_pem().unwrap(), null_public_key_pem())
}
#[test]
pub fn pubkey_deserialization_pem() {
assert_eq!(EpfPublicKey::from_pem(&null_public_key_pem()).unwrap(), [0u8; 32])
}
#[test]
#[should_panic]
pub fn pubkey_deserialization_pem_wrong_tag() {
EpfPublicKey::from_pem(&null_private_key_pem()).unwrap();
}
#[test]
pub fn privkey_serialization() {
assert_eq!(([0u8; 64]).as_bytes().unwrap(), [0u8; 64].to_vec())
}
#[test]
pub fn privkey_deserialization() {
assert_eq!(EpfPrivateKey::from_bytes(&[0u8; 64]).unwrap(), [0u8; 64])
}
#[test]
pub fn privkey_serialization_pem() {
assert_eq!(([0u8; 64]).as_pem().unwrap(), null_private_key_pem())
}
#[test]
pub fn privkey_deserialization_pem() {
assert_eq!(EpfPrivateKey::from_pem(&null_private_key_pem()).unwrap(), [0u8; 64])
}
#[test]
pub fn cert_display() {
println!("{}", cert());
}
#[test]
#[should_panic]
pub fn privkey_deserialization_pem_wrong_tag() {
EPFCertificate::from_pem(&null_public_key_pem()).unwrap();
}
fn cert() -> EPFCertificate {
EPFCertificate {
details: EPFCertificateDetails {
name: "Invalid Testing Certificate".to_string(),
not_before: 0,
not_after: 0,
public_key: [0u8; EPFPKI_PUBLIC_KEY_LENGTH],
issuer_name: "Invalid Testing Certificate Issuer".to_string(),
issuer_fingerprint: "0000000000000000000000000000000000000000000000000000000000000000".to_string(),
claims: HashMap::new()
},
fingerprint: "0000000000000000000000000000000000000000000000000000000000000000".to_string(),
signature: [0u8; EPFPKI_SIGNATURE_LENGTH],
}
}
fn cert_bytes() -> Vec<u8> {
vec![147, 151, 187, 73, 110, 118, 97, 108, 105, 100, 32, 84, 101, 115, 116, 105, 110, 103, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 0, 0, 220, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 34, 73, 110, 118, 97, 108, 105, 100, 32, 84, 101, 115, 116, 105, 110, 103, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 73, 115, 115, 117, 101, 114, 217, 64, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 128, 217, 64, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 220, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
fn cert_pem() -> Vec<u8> {
vec![45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 69, 80, 70, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 13, 10, 107, 53, 101, 55, 83, 87, 53, 50, 89, 87, 120, 112, 90, 67, 66, 85, 90, 88, 78, 48, 97, 87, 53, 110, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 65, 65, 68, 99, 65, 67, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 13, 10, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 78, 107, 105, 83, 87, 53, 50, 89, 87, 120, 112, 90, 67, 66, 85, 90, 88, 78, 48, 97, 87, 53, 110, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 13, 10, 73, 69, 108, 122, 99, 51, 86, 108, 99, 116, 108, 65, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 13, 10, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 73, 68, 90, 81, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 13, 10, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 65, 119, 77, 68, 68, 99, 65, 69, 65, 65, 13, 10, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 13, 10, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 13, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 69, 80, 70, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 13, 10]
}
fn null_public_key_pem() -> Vec<u8> {
vec![45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 69, 80, 70, 32, 80, 85, 66, 76, 73, 67, 32, 75, 69, 89, 45, 45, 45, 45, 45, 13, 10, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 61, 13, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 69, 80, 70, 32, 80, 85, 66, 76, 73, 67, 32, 75, 69, 89, 45, 45, 45, 45, 45, 13, 10]
}
fn null_private_key_pem() -> Vec<u8> {
vec![45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 69, 80, 70, 32, 80, 82, 73, 86, 65, 84, 69, 32, 75, 69, 89, 45, 45, 45, 45, 45, 13, 10, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 13, 10, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 61, 61, 13, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 69, 80, 70, 32, 80, 82, 73, 86, 65, 84, 69, 32, 75, 69, 89, 45, 45, 45, 45, 45, 13, 10]
}
}

660
tarpaulin-report.html Normal file

File diff suppressed because one or more lines are too long