diff --git a/Cargo.lock b/Cargo.lock index 3f7f7e8c3..b3ccba7be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7765,6 +7765,13 @@ dependencies = [ "zeroize", ] +[[package]] +name = "x509test" +version = "0.1.0" +dependencies = [ + "rustls", +] + [[package]] name = "xshell" version = "0.2.2" diff --git a/labs/x509test/Cargo.toml b/labs/x509test/Cargo.toml new file mode 100644 index 000000000..05c92e867 --- /dev/null +++ b/labs/x509test/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "x509test" +version = "0.1.0" +edition = "2024" +rust-version.workspace = true + +[dependencies] +rustls = "^0.23.4" + +[lints] +workspace = true diff --git a/labs/x509test/src/bundle.p12 b/labs/x509test/src/bundle.p12 new file mode 100644 index 000000000..026a7bdc1 Binary files /dev/null and b/labs/x509test/src/bundle.p12 differ diff --git a/labs/x509test/src/cacert.pem b/labs/x509test/src/cacert.pem new file mode 100644 index 000000000..66938937e --- /dev/null +++ b/labs/x509test/src/cacert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIUcP2Ij9JBq8IQfZT5dhNLsbPXYwowDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCVUsxDzANBgNVBAgMBkxvbmRvbjETMBEGA1UECgwKZWxl +bWVudC5pbzEQMA4GA1UEAwwHdGVzdC1jYTAeFw0yNjA0MjcxMzIxMjdaFw0yNzA0 +MjcxMzIxMjdaMEUxCzAJBgNVBAYTAlVLMQ8wDQYDVQQIDAZMb25kb24xEzARBgNV +BAoMCmVsZW1lbnQuaW8xEDAOBgNVBAMMB3Rlc3QtY2EwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQD3R1GuEpYIBXuZ47E4Cd6GNuaaUgF9ygRuy1dFgoqY +wRt564jkOYB6Ht5le4R/rb3u6fIeu9j4X2k7DNJPc4H5smHX3ih4BJ5Yli2pzG9S +iUj7dFY69bDA02c4DQP/gjVQddbBUEolPj5L5Ig3a++7zaPloegB/AQ+f9NTceI8 +eehVQ2dWZlI45ltVlXPxUI5MFm3iSJ889ogX+OQMSouARm6/4d3VMTHpSkPPKpH0 +vgFzn/96/C6yWKz7Fis8lM6MRqd8Ka5O5eZ0hAhVktPkUfgVZKpEsCYNVCBqJgOU +OU8FcMLinK9Zp0k8xZkTBXQbFXsKQNTa9/alX9wi2+c41O9d1MmhkYUwkdNh7OJO +//jbm7E5x//10bVgPB7eEqDUA/M/LzSZPmw/94lOcHRHBJyo0mcP74Bcg+tHydwD +xUe8gETLb7ctrlZ+HXMozoeZLeieR7knlHdFbUyufmpsrs/ONLzkPKqG4nqEjhCi +B+PZLFkRM08677FVDTmHWTN2ARAjhdOGWQBSkoD/0qlNJ3cmaqRl4uApPNRCnEKL +HDLwDNA1AH0Y5RmJX9vblfOdmGNEygpxLQmQ5IsQbJS47orupSNnDToP+IjGheOe +r5e8pWTzGO+ptO1a8GaSurrfWLk5D4wVNp+i0rCU1yBa/vCpaUjmSxEn2sG/SyKX +jQIDAQABo1MwUTAdBgNVHQ4EFgQU2F6Rmhfww1sT23VCfSE3mt8+lhEwHwYDVR0j +BBgwFoAU2F6Rmhfww1sT23VCfSE3mt8+lhEwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAgEAJmUlRR7PrS5EXNy+fToAYkSt4xFlTfOeXN6JdQzCia+x +s5TFtqQe/giphQKLN/i9Mm3w0E0u8WA87TKlaWdrZrCivLEhwvieq0u3XwqY628z +8vlcqJuhM4Soe80AQiL51NeHp0WDhBTWnwCXF/e7GA4xryjg7zqhGZjY8+m61vSd +sLT/N05mSsW/m7ZAwxhe2XBVMXvHNTVuAbHX5+4mX9OXRAbnXg5Cexn1sKONsR1L +kN5VjSSvLmzX4AhV0oIRT23NfWBPJnq2s4S9DFDi2uYqE0BWUR1AZOagaVowFsJQ +q8ccwOQMdZZkAC3h2IIVNzYuFFeXkpZM6Bp7Js9IOJrDCL+A/UsndRkv9gX4SVgd +y9vQQBr5iaI5RTKkEiprnZhKOyBd3X/QpAoPRdhiGeImRpKt8vhF+JetGc2E1o+O +CSDpNjD6uI3SHSKt2mlOfeNoZms1pxY36gNYsytFGXf3qdb1I9cP4GRI6cz4JbmP +Y3eczjaqZMcOaPBBZlYz867C5sZi2tvqT75jlB+rVckKRIEl1bL4EZEpvRbK+nfJ +RFSPEY1fryCthLfa67ThB+IAonX4jU663sLoAQW1FEpJp3q08kKJOoCXlCMZ7g1P +eXmIj7ZEOIsufPdiYuKDp/aUdgUHmuCGyegfoCJze36SdFX5q6z8Aq5nKPtz+FM= +-----END CERTIFICATE----- diff --git a/labs/x509test/src/cert.pem b/labs/x509test/src/cert.pem new file mode 100644 index 000000000..99b23d586 --- /dev/null +++ b/labs/x509test/src/cert.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEKjCCAhKgAwIBAgIBADANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVSzEP +MA0GA1UECAwGTG9uZG9uMRMwEQYDVQQKDAplbGVtZW50LmlvMRAwDgYDVQQDDAd0 +ZXN0LWNhMB4XDTI2MDQyNzEzMzIzNVoXDTI3MDQyNzEzMzIzNVowKDEmMCQGCSqG +SIb3DQEJARYXdmRoLXg1MDl0ZXN0QG1hdHJpeC5vcmcwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCzMke0NO4fXtAnkvqqc9PHcf6tMAB7P7+xjWDTpKfJ +PHohC7IzTNR8u1+Oz76fCLq0bIWDbXS570YoA9hlj6UCH5a/+4NhsNYKTapbUVfq +LVk41oNKAFt7brKZ8tkvAG9GCSKztrc3xAG5+QmiEoVY1XSShz3WuD94LIp3me2R +doQcgSP3Gb6zIhpE8sI4MMRsyjU/k822SfiKOqrWKa+HuXTmNDC2UeCTj2++y0e4 +s2IRrniOjM84Ci2mMhv/L6cpwwhyI1PsL28tGAX1NhEdVdrQxcOyhh3T9Q2er8J1 +kJsfOEmLecNutiSi+mdYbY1pKc60St4KVBE89zAWIg/FAgMBAAGjQjBAMB0GA1Ud +DgQWBBQdCjaG9Xzjyxv9S7xlM1ryXhGyWTAfBgNVHSMEGDAWgBTYXpGaF/DDWxPb +dUJ9ITea3z6WETANBgkqhkiG9w0BAQsFAAOCAgEAhhIcWrFaAd4DuDlHHoqmL9rs +sLn3rx+v4Et+GRV0EjMIOX+tTPO3mUCUb8Ifvk8cC3fucoClKVG8snzIir4eUFOx +d6M7+GAoTLkh8V8XAre3Xo9O2vxB2V8m3IO8Sbnht9aWj9FeMB5Pb9yzTFr8GZPf +7jky+o9R9lrIrURprKBehStYTaNj5YIjYxDXwy+64yXyrckhA8vioFpUFz/CBQMz +B4DwEZRjtFNDxNKA/LcoSnTRfoTpclZIUtJ7YX/qC98QUleuNzpGHM3/59Tn7lzt +ykuWvCAFc3f1nELrEe2ffhCs5M9HNBtGJZ21iEK4LaIu4PBgRTuXDXfsZpC02VKi +s8S9G+er9IUyLpJ1dajY2jXhJuUvmcFLltlzUPYocWcQVVFFAkrrHnew5NzZUPOD ++LQYjNFszITmFc6V49Df23d/kDK+4QzpdtjEf+hjWdDtUDLsAvc48RylwoSIwxn+ +3poImhlL5uqHuyQfQqnEVo/DrV44qi3Qv+cBzC+DQ0SQQJ89keWNTGGAVRggY6lX +iQOKT/LtaDO8mtCwY9GT5ZqjynCnLygdG+GgE7sBaRhoj5FFIaXHD83Gcwpv/JI6 +giqgGwii4W8KvNkR/k1Z6C9+RvENbluqMRbQ3CXVNDbyU1MB6ZliRGTtbZvL0bd1 +/F4LixSyyHVXMUn4/1Q= +-----END CERTIFICATE----- diff --git a/labs/x509test/src/key.pem b/labs/x509test/src/key.pem new file mode 100644 index 000000000..02a4b6068 --- /dev/null +++ b/labs/x509test/src/key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCzMke0NO4fXtAn +kvqqc9PHcf6tMAB7P7+xjWDTpKfJPHohC7IzTNR8u1+Oz76fCLq0bIWDbXS570Yo +A9hlj6UCH5a/+4NhsNYKTapbUVfqLVk41oNKAFt7brKZ8tkvAG9GCSKztrc3xAG5 ++QmiEoVY1XSShz3WuD94LIp3me2RdoQcgSP3Gb6zIhpE8sI4MMRsyjU/k822SfiK +OqrWKa+HuXTmNDC2UeCTj2++y0e4s2IRrniOjM84Ci2mMhv/L6cpwwhyI1PsL28t +GAX1NhEdVdrQxcOyhh3T9Q2er8J1kJsfOEmLecNutiSi+mdYbY1pKc60St4KVBE8 +9zAWIg/FAgMBAAECggEADkeBFpIVMONsRjWxyygPBdib87mx1XW/VRWv/o14tVIg +D/Fk/NjazH8IiVJynSz5O8FeDkVdmidqpBZSWx123P7JaM5Q/4Azk39G259VbcVj +/mHRn8b8LeTPT0czw/QOlI/LzR2lPJ4I3oSYHkBy5yDzThiAIVPDSFSRoCA1oclO +oD/PiXADtfa3vkHTswmnT8JTZP7Dpe1zl5AZALQSFVZyQJ4oFxKqJMWc6LsYpHQ3 +AqAAHk7VFyJQGsFZ+D1EgXv3Tzh8YB1nfhjvAucj8VPP9gbDzf4uHEp8FJEHCEAb +lJcEyWNNcpLhSl5T6oY9hjnIkDrxEITdUts+jMRHLQKBgQDrL9ivhSZMZbytU5sv +20JTBFYpgK4TFHeaWnsOwO53AsPTFsl2s6cQ18UNbWIdxn2E7AiTqPVO++E6etNc +HUo76gR9/0gNXILNysQAP0Wzkwtz4c0pXx6pa4zZTihvIcwO0Q6NRAB4sOk+XgDP +Pu79nUSaO8O+d8EUOb+9P2gAZwKBgQDDDfhq12ElgUmhDW92iuD2LwDGg22U4qNQ +0dMXju268TPwx1dYYi/f2yzp/Tn4xKlIo9NZNOzf6GW0+cnOjzyGKCzUglME6Pei +X2Hn8nSD4j60bRCIcf5VfFRAUm9j/y9F/hE5JX+XSM5DKrw09IqzMuu3+Z9TKxRg +dKNOTUQi8wKBgE+d8PLqVl7Cii77AKwgw8Eq1KhUIZnf8eVVABeshI3RZ82MB0Oh +6cqv4Mt83hxKV6+p3/Vs2y6T4llTvz2NxNWnkUG+K/wp9zYHkHas9MGn49ak+Dkr +NEwSVqox5UpJ3LSfXRfBj49MBInSdN+z5GAC33h/BvLxw3E/Y4ODdYe9AoGAaWju +XAbjOBqDiOay2vQ4mLJUD/PMz44fRjjuhCe4r7NUJ4YC3P/K8YYH4rf3kUnuVhQ6 +zlW8wVBdTo1DEz7zLWkeuQVpChlAYl57kZbEgtVMn8LlEWfRU69p9IzYJ8kraf7g +nep25nHxDflVVqTlI+yb2IOtJ4v7ahj+e/1jmiMCgYBX57KyNSGew08r2ezjuV6f +wy/qfzJlieWhESZIckJcrDurfzR3xCj4n4xyC4GMTt3bGYs/rGTdkJGxJ6Bq4Ld2 +foobh78qDEn1mFVwUuW2kzOJsIlN3FQFSKK3upVdRmzXTvaJN4MKRjwmu6KYIpxA +03GLFlPRHwxXrJAV+om1nQ== +-----END PRIVATE KEY----- diff --git a/labs/x509test/src/main.rs b/labs/x509test/src/main.rs new file mode 100644 index 000000000..141329d08 --- /dev/null +++ b/labs/x509test/src/main.rs @@ -0,0 +1,42 @@ +use std::sync::Arc; + +use rustls::{ + RootCertStore, + pki_types::{CertificateDer, UnixTime, pem::PemObject}, + server::WebPkiClientVerifier, +}; + +// TODO: how to load from a PKCS12 bundle? cms::encrypted_data, I think +const KEY_BUNDLE: &[u8] = include_bytes!("bundle.p12"); + +const CA_CERT: &[u8] = include_bytes!("cacert.pem"); +const CERT_BUNDLE_PEM: &[u8] = include_bytes!("cert.pem"); +const PRIVATE_KEY_PEM: &[u8] = include_bytes!("key.pem"); + +fn main() { + // Load the trusted root certificates into a verifier. These would come from + // local configuration. + let mut root_store = RootCertStore::empty(); + for result in CertificateDer::pem_slice_iter(CA_CERT) { + root_store + .add(result.expect("Unable to parse certificate in root store")) + .expect("Unable to add certificate to root store"); + } + let verifier = WebPkiClientVerifier::builder(Arc::new(root_store)) + //.with_crls(...) + .build() + .unwrap(); + + // Verify the certificate chain presented by the device + let mut cert_iter = CertificateDer::pem_slice_iter(CERT_BUNDLE_PEM) + .map(|r| r.expect("Unable to parse cert in cert chain")); + let end_cert = cert_iter.next().expect("Empty certificate chain"); + let intermediate_certs: Vec<_> = cert_iter.collect(); + + verifier + .verify_client_cert(&end_cert, intermediate_certs.as_ref(), UnixTime::now()) + .expect("Unable to verify client certificate"); + + // TODO: verify that the end cert is valid for the user id in question + // TODO: verify a signature from the end cert +}