diff --git a/src/keytypes/asymmetric.rs b/src/keytypes/asymmetric.rs index 1af2653..cc39787 100644 --- a/src/keytypes/asymmetric.rs +++ b/src/keytypes/asymmetric.rs @@ -117,3 +117,129 @@ impl KeyRestriction for AsymmetricRestriction { impl RestrictableKeyType for Asymmetric { type Restriction = AsymmetricRestriction; } + +#[cfg(test)] +mod tests { + use crate::keytypes::{Asymmetric, AsymmetricRestriction, User}; + use crate::tests::utils; + use crate::KeyRestriction; + + #[test] + fn test_restriction_str() { + let mut keyring = utils::new_test_keyring(); + let description = &b"description"[..]; + let key = keyring + .add_key::("test_restriction_str", description) + .unwrap(); + + let cases = [ + ( + AsymmetricRestriction::BuiltinTrusted, + "builtin_trusted".into(), + ), + ( + AsymmetricRestriction::BuiltinAndSecondaryTrusted, + "builtin_and_secondary_trusted".into(), + ), + ( + AsymmetricRestriction::Key { + key: key.clone(), + chained: false, + }, + format!("key_or_keyring:{}", key.serial()), + ), + ( + AsymmetricRestriction::Key { + key: key.clone(), + chained: true, + }, + format!("key_or_keyring:{}:chain", key.serial()), + ), + ( + AsymmetricRestriction::Keyring { + keyring: keyring.clone(), + chained: false, + }, + format!("key_or_keyring:{}", keyring.serial()), + ), + ( + AsymmetricRestriction::Keyring { + keyring: keyring.clone(), + chained: true, + }, + format!("key_or_keyring:{}:chain", keyring.serial()), + ), + ( + AsymmetricRestriction::Chained, + "key_or_keyring:0:chain".into(), + ), + ]; + + for (restriction, expected) in cases.iter() { + assert_eq!(restriction.restriction(), expected.as_ref()); + } + } + + #[test] + fn test_restrict_keyring_chain() { + let mut keyring = utils::new_test_keyring(); + + // Create and populate a keyring for root certificates. + let mut root = keyring.add_keyring("root-certs").unwrap(); + let root1_certificate = &include_bytes!("data/ca/ca-1.root.crt.der")[..]; + let root2_certificate = &include_bytes!("data/ca/ca-2.root.crt.der")[..]; + root.add_key::("root1", root1_certificate) + .unwrap(); + root.add_key::("root2", root2_certificate) + .unwrap(); + + // Create a keyring to restrict. + let mut chain = keyring.add_keyring("chain").unwrap(); + let restriction = AsymmetricRestriction::Keyring { + keyring: root, + chained: true, + }; + chain + .restrict_by_type::(restriction) + .unwrap(); + + // Add certificates in order. + let intermediate_a = &include_bytes!("data/ca/ca.intermediate.crt.der")[..]; + chain + .add_key::("intermediate_a", intermediate_a) + .unwrap(); + let intermediate_b = &include_bytes!("data/ca/intermediate.term.crt.der")[..]; + chain + .add_key::("intermediate_b", intermediate_b) + .unwrap(); + let terminal = &include_bytes!("data/ca/ca-1.term.crt.der")[..]; + chain + .add_key::("terminal", terminal) + .unwrap(); + } + + #[test] + fn test_restrict_keyring_fail() { + let mut keyring = utils::new_test_keyring(); + + // Create and populate a keyring for root certificates. + let root = keyring.add_keyring("root-certs").unwrap(); + + // Create a keyring to restrict. + let mut chain = keyring.add_keyring("chain").unwrap(); + let restriction = AsymmetricRestriction::Keyring { + keyring: root, + chained: true, + }; + chain + .restrict_by_type::(restriction) + .unwrap(); + + // Add certificates in order. + let terminal = &include_bytes!("data/ca/self.term.crt.der")[..]; + let err = chain + .add_key::("self", terminal) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + } +} diff --git a/src/keytypes/data/ca/.gitignore b/src/keytypes/data/ca/.gitignore new file mode 100644 index 0000000..97b6d30 --- /dev/null +++ b/src/keytypes/data/ca/.gitignore @@ -0,0 +1,7 @@ +*.key +*.crt +*.csr +*.pem + +certindex* +serial* diff --git a/src/keytypes/data/ca/Makefile b/src/keytypes/data/ca/Makefile new file mode 100644 index 0000000..f75528f --- /dev/null +++ b/src/keytypes/data/ca/Makefile @@ -0,0 +1,37 @@ +PROJECT := rust-keyutils +OPENSSL_CONF := openssl.cnf + +MAIN_CERT_NAME := ca-1 +MAIN_ROOT_CERT := $(MAIN_CERT_NAME).root.crt +ROOT_CERTS := $(MAIN_ROOT_CERT) ca-2.root.crt +INTERMEDIATE_CERTS := ca.intermediate.crt +CA_CERTS := $(ROOT_CERTS) $(INTERMEDIATE_CERTS) +SERVER_CERTS := intermediate.term.crt $(MAIN_CERT_NAME).term.crt self.term.crt + +SIGNING_BITS := certindex serial + +all: $(foreach cert,$(CA_CERTS) $(SERVER_CERTS),$(cert).der) + +certindex: + touch certindex + +serial: + echo 1000 > serial + +%.root.crt %.key: $(OPENSSL_CONF) + openssl req -config $< -new -subj "/CN=$(PROJECT) CA $*" -x509 -passout pass:$(PROJECT) -newkey rsa:4096 -keyout $*.key -out $@ -extensions v3_root_ca + +%.intermediate.crt %.key: $(OPENSSL_CONF) $(SIGNING_BITS) $(MAIN_ROOT_CERT) + openssl req -config $< -new -subj "/CN=$(PROJECT) Intermediate CA" -passout pass:$(PROJECT) -newkey rsa:4096 -keyout $*.key -out $@.csr -extensions v3_intermediate_ca + openssl ca -config $< -notext -passin pass:$(PROJECT) -batch -in $@.csr -out $@ + +self.term.crt %.key: $(OPENSSL_CONF) $(SIGNING_BITS) + openssl req -config $< -new -subj "/CN=$(PROJECT) self-signed Certificate" -passout pass:$(PROJECT) -newkey rsa:4096 -keyout $*.term.key -out $@.csr -extensions v3_server_cert + openssl x509 -req -signkey $*.term.key -passin pass:$(PROJECT) -days 3650 -in $@.csr -out $@ + +%.term.crt %.key: $(OPENSSL_CONF) $(SIGNING_BITS) $(CA_CERTS) + openssl req -config $< -new -subj "/CN=$(PROJECT) $*-signed Certificate" -passout pass:$(PROJECT) -newkey rsa:4096 -keyout $*.term.key -out $@.csr -extensions v3_server_cert + openssl ca -config $< -notext -passin pass:$(PROJECT) -batch -in $@.csr -out $@ -name $* + +%.crt.der: %.crt + openssl x509 -outform der -in $< -out $@ diff --git a/src/keytypes/data/ca/ca-1.root.crt.der b/src/keytypes/data/ca/ca-1.root.crt.der new file mode 100644 index 0000000..6150a0a Binary files /dev/null and b/src/keytypes/data/ca/ca-1.root.crt.der differ diff --git a/src/keytypes/data/ca/ca-1.term.crt.der b/src/keytypes/data/ca/ca-1.term.crt.der new file mode 100644 index 0000000..31f25ef Binary files /dev/null and b/src/keytypes/data/ca/ca-1.term.crt.der differ diff --git a/src/keytypes/data/ca/ca-2.root.crt.der b/src/keytypes/data/ca/ca-2.root.crt.der new file mode 100644 index 0000000..ae1557d Binary files /dev/null and b/src/keytypes/data/ca/ca-2.root.crt.der differ diff --git a/src/keytypes/data/ca/ca.intermediate.crt.der b/src/keytypes/data/ca/ca.intermediate.crt.der new file mode 100644 index 0000000..a191cc8 Binary files /dev/null and b/src/keytypes/data/ca/ca.intermediate.crt.der differ diff --git a/src/keytypes/data/ca/intermediate.term.crt.der b/src/keytypes/data/ca/intermediate.term.crt.der new file mode 100644 index 0000000..5e19b2e Binary files /dev/null and b/src/keytypes/data/ca/intermediate.term.crt.der differ diff --git a/src/keytypes/data/ca/openssl.cnf b/src/keytypes/data/ca/openssl.cnf new file mode 100644 index 0000000..e1bd80e --- /dev/null +++ b/src/keytypes/data/ca/openssl.cnf @@ -0,0 +1,75 @@ +[ca] +default_ca = ca-1 + +[ca_policy] + +[ca-1] +dir = ./ +new_certs_dir = $dir +certificate = $dir/ca-1.root.crt +private_key = $dir/ca-1.key + +database = $dir/certindex +serial = $dir/serial +default_days = 3650 +default_md = sha512 +policy = ca_policy + +[intermediate] +dir = ./ +new_certs_dir = $dir +certificate = $dir/ca.intermediate.crt +private_key = $dir/ca.key + +database = $dir/certindex +serial = $dir/serial +default_days = 3650 +default_md = sha512 +policy = ca_policy + +[self] +dir = ./ +new_certs_dir = $dir +#certificate = $dir/ca.intermediate.crt +private_key = $dir/self.term.key + +database = $dir/certindex +serial = $dir/serial +default_days = 3650 +default_md = sha512 +policy = ca_policy + +[req] +distinguished_name = req_distinguished_name +prompt = no + +[req_distinguished_name] +countryName = US +stateOrProvinceName = New York +localityName = Nowhere +organizationName = Github +emailAddress = mathstuf+keyutils@gmail.com + +[v3_root_ca] +# Extensions for a typical CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[v3_intermediate_ca] +# Extensions for a typical intermediate CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[v3_server_cert] +# Extensions for server certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = server +nsComment = "OpenSSL Generated Server Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth diff --git a/src/keytypes/data/ca/self.term.crt.der b/src/keytypes/data/ca/self.term.crt.der new file mode 100644 index 0000000..3c1c96b Binary files /dev/null and b/src/keytypes/data/ca/self.term.crt.der differ diff --git a/src/keytypes/mod.rs b/src/keytypes/mod.rs index ae74301..e1b0773 100644 --- a/src/keytypes/mod.rs +++ b/src/keytypes/mod.rs @@ -33,6 +33,7 @@ use std::fmt; pub mod asymmetric; pub use self::asymmetric::Asymmetric; +pub use self::asymmetric::AsymmetricRestriction; pub mod big_key; pub use self::big_key::BigKey;