|
12 | 12 | // each license.
|
13 | 13 |
|
14 | 14 | use async_generic::async_generic;
|
| 15 | +use chrono::{DateTime, Utc}; |
15 | 16 | use ciborium::value::Value;
|
16 | 17 | use coset::{CoseSign1, Label};
|
17 |
| -#[cfg(not(target_arch = "wasm32"))] |
18 |
| -use { |
19 |
| - crate::crypto::cose::cert_chain_from_sign1, |
20 |
| - chrono::{DateTime, Utc}, |
21 |
| -}; |
22 | 18 |
|
23 | 19 | use crate::{
|
24 | 20 | crypto::{
|
25 | 21 | asn1::rfc3161::TstInfo,
|
26 | 22 | cose::{
|
27 |
| - check_end_entity_certificate_profile, validate_cose_tst_info, |
| 23 | + cert_chain_from_sign1, check_end_entity_certificate_profile, validate_cose_tst_info, |
28 | 24 | validate_cose_tst_info_async, CertificateTrustError, CertificateTrustPolicy, CoseError,
|
29 | 25 | },
|
30 | 26 | ocsp::OcspResponse,
|
@@ -101,7 +97,12 @@ pub fn check_ocsp_status(
|
101 | 97 |
|
102 | 98 | None => match fetch_policy {
|
103 | 99 | OcspFetchPolicy::FetchAllowed => {
|
104 |
| - fetch_and_check_ocsp_response(sign1, data, ctp, tst_info, validation_log) |
| 100 | + if _sync { |
| 101 | + fetch_and_check_ocsp_response(sign1, data, ctp, tst_info, validation_log) |
| 102 | + } else { |
| 103 | + fetch_and_check_ocsp_response_async(sign1, data, ctp, tst_info, validation_log) |
| 104 | + .await |
| 105 | + } |
105 | 106 | }
|
106 | 107 | OcspFetchPolicy::DoNotFetch => {
|
107 | 108 | if let Some(ocsp_response_ders) = ocsp_responses {
|
@@ -276,54 +277,53 @@ fn check_stapled_ocsp_response(
|
276 | 277 | }
|
277 | 278 |
|
278 | 279 | /// Fetches and validates an OCSP response for the given COSE signature.
|
279 |
| -// TO DO: Add async version of this? |
| 280 | +#[async_generic()] |
| 281 | +#[allow(unreachable_code)] // wasm-bindgen will immediately return error for synchronous use. |
| 282 | +#[allow(unused_variables)] |
280 | 283 | pub(crate) fn fetch_and_check_ocsp_response(
|
281 | 284 | sign1: &CoseSign1,
|
282 | 285 | data: &[u8],
|
283 | 286 | ctp: &CertificateTrustPolicy,
|
284 | 287 | _tst_info: Option<&TstInfo>,
|
285 | 288 | validation_log: &mut StatusTracker,
|
286 | 289 | ) -> Result<OcspResponse, CoseError> {
|
287 |
| - #[cfg(target_arch = "wasm32")] |
288 |
| - { |
289 |
| - let _ = (sign1, data, ctp, validation_log); |
290 |
| - Ok(OcspResponse::default()) |
291 |
| - } |
| 290 | + let certs = cert_chain_from_sign1(sign1)?; |
292 | 291 |
|
293 |
| - #[cfg(not(target_arch = "wasm32"))] |
294 |
| - { |
295 |
| - let certs = cert_chain_from_sign1(sign1)?; |
296 |
| - |
297 |
| - let Some(ocsp_der) = crate::crypto::ocsp::fetch_ocsp_response(&certs) else { |
298 |
| - return Ok(OcspResponse::default()); |
299 |
| - }; |
| 292 | + let ocsp_der: Vec<u8> = if _sync { |
| 293 | + match crate::crypto::ocsp::fetch_ocsp_response(&certs) { |
| 294 | + Some(der) => der, |
| 295 | + None => return Ok(OcspResponse::default()), |
| 296 | + } |
| 297 | + } else { |
| 298 | + match crate::crypto::ocsp::fetch_ocsp_response_async(&certs).await { |
| 299 | + Some(der) => der, |
| 300 | + None => return Ok(OcspResponse::default()), |
| 301 | + } |
| 302 | + }; |
300 | 303 |
|
301 |
| - let ocsp_response_der = ocsp_der; |
| 304 | + let ocsp_response_der = ocsp_der; |
302 | 305 |
|
303 |
| - let signing_time: Option<DateTime<Utc>> = |
304 |
| - validate_cose_tst_info(sign1, data, ctp, validation_log) |
305 |
| - .ok() |
306 |
| - .map(|tst_info| tst_info.gen_time.clone().into()); |
| 306 | + let signing_time: Option<DateTime<Utc>> = |
| 307 | + validate_cose_tst_info(sign1, data, ctp, validation_log) |
| 308 | + .ok() |
| 309 | + .map(|tst_info| tst_info.gen_time.clone().into()); |
307 | 310 |
|
308 |
| - // Check the OCSP response, but only if it is well-formed. |
309 |
| - // Revocation errors are reported in the validation log. |
310 |
| - let Ok(ocsp_data) = |
311 |
| - OcspResponse::from_der_checked(&ocsp_response_der, signing_time, validation_log) |
312 |
| - else { |
313 |
| - // TO REVIEW: This is how the old code worked, but is it correct to ignore a |
314 |
| - // malformed OCSP response? |
315 |
| - return Ok(OcspResponse::default()); |
| 311 | + // Check the OCSP response, but only if it is well-formed. |
| 312 | + // Revocation errors are reported in the validation log. |
| 313 | + let ocsp_data = |
| 314 | + match OcspResponse::from_der_checked(&ocsp_response_der, signing_time, validation_log) { |
| 315 | + Ok(data) => data, |
| 316 | + Err(_) => return Ok(OcspResponse::default()), |
316 | 317 | };
|
317 | 318 |
|
318 |
| - // If we get a valid response validate the certs. |
319 |
| - if ocsp_data.revoked_at.is_none() { |
320 |
| - if let Some(ocsp_certs) = &ocsp_data.ocsp_certs { |
321 |
| - check_end_entity_certificate_profile(&ocsp_certs[0], ctp, validation_log, None)?; |
322 |
| - } |
| 319 | + // If we get a valid response validate the certs. |
| 320 | + if ocsp_data.revoked_at.is_none() { |
| 321 | + if let Some(ocsp_certs) = &ocsp_data.ocsp_certs { |
| 322 | + check_end_entity_certificate_profile(&ocsp_certs[0], ctp, validation_log, None)?; |
323 | 323 | }
|
324 |
| - |
325 |
| - Ok(ocsp_data) |
326 | 324 | }
|
| 325 | + |
| 326 | + Ok(ocsp_data) |
327 | 327 | }
|
328 | 328 |
|
329 | 329 | /// Returns the DER-encoded OCSP response from the "rVals" unprotected header in a COSE_Sign1 message.
|
|
0 commit comments