trust_handler.rs (6406B)
1 // Copyright 2023 Adobe. All rights reserved. 2 // This file is licensed to you under the Apache License, 3 // Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 4 // or the MIT license (http://opensource.org/licenses/MIT), 5 // at your option. 6 7 // Unless required by applicable law or agreed to in writing, 8 // this software is distributed on an "AS IS" BASIS, WITHOUT 9 // WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or 10 // implied. See the LICENSE-MIT and LICENSE-APACHE files for the 11 // specific language governing permissions and limitations under 12 // each license. 13 14 use std::{ 15 collections::HashSet, 16 io::{read_to_string, Cursor, Read}, 17 panic::{RefUnwindSafe, UnwindSafe}, 18 str::FromStr, 19 }; 20 21 use asn1_rs::{oid, Oid}; 22 23 use crate::{hash_utils::hash_sha256, utils::base64, Error, Result}; 24 25 pub(crate) static EMAIL_PROTECTION_OID: Oid<'static> = oid!(1.3.6 .1 .5 .5 .7 .3 .4); 26 pub(crate) static TIMESTAMPING_OID: Oid<'static> = oid!(1.3.6 .1 .5 .5 .7 .3 .8); 27 pub(crate) static OCSP_SIGNING_OID: Oid<'static> = oid!(1.3.6 .1 .5 .5 .7 .3 .9); 28 pub(crate) static DOCUMENT_SIGNING_OID: Oid<'static> = oid!(1.3.6 .1 .5 .5 .7 .3 .36); 29 30 // Trait for supply configuration and handling of trust lists and EKU configuration store 31 // 32 // `RefUnwindSafe` + `UnwindSafe` were added to ensure `Store` is unwind safe and to preserve 33 // backwards compatbility. 34 pub(crate) trait TrustHandlerConfig: RefUnwindSafe + UnwindSafe + Sync + Send { 35 fn new() -> Self 36 where 37 Self: Sized; 38 39 // add trust anchors 40 fn load_trust_anchors_from_data(&mut self, trust_data: &mut dyn Read) -> Result<()>; 41 42 // add allowed list 43 fn load_allowed_list(&mut self, allowed_list: &mut dyn Read) -> Result<()>; 44 45 // append private trust anchors 46 fn append_private_trust_data(&mut self, private_anchors_data: &mut dyn Read) -> Result<()>; 47 48 // clear all entries in trust handler list 49 fn clear(&mut self); 50 51 // load EKU configuration 52 fn load_configuration(&mut self, config_data: &mut dyn Read) -> Result<()>; 53 54 // list off auxillary allowed EKU Oid 55 fn get_auxillary_ekus(&self) -> Vec<Oid>; 56 57 // list of all anchors 58 #[allow(dead_code)] // Only used in calls with allow dead_code 59 fn get_anchors(&self) -> Vec<Vec<u8>>; 60 61 // set of allowed cert hashes 62 #[allow(dead_code)] // Only used in calls with allow dead_code 63 fn get_allowed_list(&self) -> &HashSet<String>; 64 } 65 66 impl std::fmt::Debug for dyn TrustHandlerConfig { 67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 68 write!(f, "TrustHandler Installed") 69 } 70 } 71 72 pub(crate) fn has_allowed_oid<'a>( 73 eku: &x509_parser::extensions::ExtendedKeyUsage, 74 allowed_ekus: &'a [Oid], 75 ) -> Option<&'a Oid<'a>> { 76 if eku.email_protection { 77 return Some(&EMAIL_PROTECTION_OID); 78 } 79 80 if eku.time_stamping { 81 return Some(&TIMESTAMPING_OID); 82 } 83 84 if eku.ocsp_signing { 85 return Some(&OCSP_SIGNING_OID); 86 } 87 88 let mut last_oid = None; 89 if eku.other.iter().any(|v| { 90 allowed_ekus.iter().any(|oid| { 91 if oid == v { 92 last_oid = Some(oid); 93 true 94 } else { 95 false 96 } 97 }) 98 }) { 99 return last_oid; 100 } 101 None 102 } 103 104 // load set of validation EKUs, ignoring unrecognized Oid lines 105 #[allow(dead_code)] 106 pub(crate) fn load_eku_configuration(config_data: &mut dyn Read) -> Result<Vec<String>> { 107 let mut oid_vec = Vec::new(); 108 109 for line in read_to_string(config_data)?.lines() { 110 if Oid::from_str(line).is_ok() { 111 oid_vec.push(line.to_owned()); 112 } 113 } 114 Ok(oid_vec) 115 } 116 117 pub(crate) fn load_trust_from_data(trust_data: &[u8]) -> Result<Vec<Vec<u8>>> { 118 let mut certs = Vec::new(); 119 120 for pem_result in x509_parser::pem::Pem::iter_from_buffer(trust_data) { 121 let pem = pem_result.map_err(|_e| Error::CoseInvalidCert)?; 122 certs.push(pem.contents); 123 } 124 Ok(certs) 125 } 126 127 // Pass through trust for the case of claim signer usage since it has known trust with context 128 // configured to all email protection, timestamping, ocsp signing and document signing 129 #[derive(Debug)] 130 pub(crate) struct TrustPassThrough { 131 allowed_cert_set: HashSet<String>, 132 config_store: Vec<u8>, 133 } 134 135 impl TrustHandlerConfig for TrustPassThrough { 136 fn new() -> Self 137 where 138 Self: Sized, 139 { 140 TrustPassThrough { 141 allowed_cert_set: HashSet::new(), 142 config_store: Vec::new(), 143 } 144 } 145 146 fn load_trust_anchors_from_data(&mut self, _trust_data: &mut dyn std::io::Read) -> Result<()> { 147 Ok(()) 148 } 149 150 fn append_private_trust_data( 151 &mut self, 152 _private_anchors_data: &mut dyn std::io::Read, 153 ) -> Result<()> { 154 Ok(()) 155 } 156 157 fn clear(&mut self) {} 158 159 fn load_configuration(&mut self, config_data: &mut dyn Read) -> Result<()> { 160 config_data.read_to_end(&mut self.config_store)?; 161 Ok(()) 162 } 163 164 // list off auxillary allowed EKU Oid 165 fn get_auxillary_ekus(&self) -> Vec<Oid> { 166 let mut oids = Vec::new(); 167 if let Ok(oid_strings) = load_eku_configuration(&mut Cursor::new(&self.config_store)) { 168 for oid_str in &oid_strings { 169 if let Ok(oid) = Oid::from_str(oid_str) { 170 oids.push(oid); 171 } 172 } 173 } 174 if oids.is_empty() { 175 // return default 176 vec![ 177 EMAIL_PROTECTION_OID.to_owned(), 178 TIMESTAMPING_OID.to_owned(), 179 OCSP_SIGNING_OID.to_owned(), 180 DOCUMENT_SIGNING_OID.to_owned(), 181 ] 182 } else { 183 oids 184 } 185 } 186 187 fn get_anchors(&self) -> Vec<Vec<u8>> { 188 Vec::new() 189 } 190 191 fn load_allowed_list(&mut self, allowed_list: &mut dyn std::io::prelude::Read) -> Result<()> { 192 let mut buffer = Vec::new(); 193 allowed_list.read_to_end(&mut buffer)?; 194 195 if let Ok(cert_list) = load_trust_from_data(&buffer) { 196 for cert_der in &cert_list { 197 let cert_sha256 = hash_sha256(cert_der); 198 let cert_hash_base64 = base64::encode(&cert_sha256); 199 200 self.allowed_cert_set.insert(cert_hash_base64); 201 } 202 } 203 Ok(()) 204 } 205 206 fn get_allowed_list(&self) -> &std::collections::HashSet<String> { 207 &self.allowed_cert_set 208 } 209 }