open X509 (* How files for test1 were generated: key.pem: openssl genpkey -algorithm RSA -out key.pem -outform PEM certificate.pem: openssl req -new -x509 -days 3650 -key key.pem -out certificate.pem -subj '/CN=example.com/' -sha256 test1.pem: openssl req -new -key key.pem -nodes -out test1.csr \ -subj '/CN=test1.example.com/' openssl x509 -req -days 3650 -in test1.csr -CA certificate.pem \ -CAkey key.pem -set_serial 10000 -out test1.pem openssl x509 -in test1.pem -noout -text request.der: openssl ocsp -issuer certificate.pem \ -cert test1.pem \ -no_nonce -reqout request.der openssl ocsp -reqin request.der -text response.der: openssl ocsp -index index.txt -rsigner certificate.pem \ -rkey key.pem -CA certificate.pem \ -reqin request.der -respout response.der openssl ocsp -respin response.der -CAfile certificate.pem -text *) let mmap file = let ic = open_in file in let ln = in_channel_length ic in let rs = Bytes.create ln in really_input ic rs 0 ln; close_in ic; Bytes.unsafe_to_string rs let data file = mmap ("./ocsp/" ^ file) let responder_cert = match Certificate.decode_pem (data "certificate.pem") with | Ok c -> c | Error _ -> assert false let responder_dn = Certificate.subject responder_cert let test1_serial = "\x27\x10" let responder_key = match Private_key.decode_pem (data "key.pem") with | Ok k -> k | Error _ -> assert false let cert_dn_testable = Alcotest.testable Distinguished_name.pp Distinguished_name.equal let test_request () = let open OCSP.Request in match decode_der (data "request.der") with | Error _ -> Alcotest.fail "could not decode OCSP request" | Ok request -> (* Fmt.pr "request=%a" pp request; *) (* TODO: verify *) match cert_ids request with | [certid] -> let serialNumber = OCSP.cert_id_serial certid in Alcotest.(check string __LOC__ test1_serial serialNumber) | _ -> Alcotest.fail "something wrong with OCSP request" let test_response () = let open OCSP.Response in match decode_der (data "response.der") with | Error e -> Alcotest.failf "could not decode OCSP response: %a" Asn.pp_error e | Ok response -> (* Fmt.pr "response=%a" pp response; *) (match validate response (Private_key.public responder_key) with | Ok () -> () | Error _ -> Alcotest.fail "cannot verify the signature of OCSP response"); let responder = match responder_id response with | Ok (`ByName r) -> r | Ok _ -> Alcotest.fail "expected responder identifyed by name" | Error (`Msg e) -> Alcotest.fail e in let response = match responses response with | Ok [r] -> r | Ok _ -> Alcotest.fail "must be exactly one response" | Error (`Msg e) -> Alcotest.fail e in let certid = single_response_cert_id response in let serialNumber = OCSP.cert_id_serial certid in Alcotest.(check string __LOC__ test1_serial serialNumber); Alcotest.(check cert_dn_testable __LOC__ responder responder_dn) let test_simple_responder () = match OCSP.Request.decode_der (data "request.der") with | Error _ -> Alcotest.fail "could not decode OCSP request" | Ok request -> let certids = OCSP.Request.cert_ids request in let now = Ptime_clock.now () in let response_logic cert_id = let serial = OCSP.cert_id_serial cert_id in let cert_status = if String.equal test1_serial serial then `Revoked (now, None) else `Good in OCSP.Response.create_single_response cert_id cert_status now in let responses = List.map response_logic certids in let responder_id = `ByName responder_dn in (* Fmt.pr "keytype = %a" Key_type.pp (Private_key.key_type responder_key); *) match OCSP.Response.create_success ~certs:[responder_cert] responder_key responder_id now responses with | Error (`Msg e) -> Alcotest.fail e | Ok resp -> match OCSP.Response.validate resp (Private_key.public responder_key) with | Ok () -> () | Error e -> let pp_e ppf = function | #Validation.signature_error as e -> X509.Validation.pp_signature_error ppf e | `No_signature -> Fmt.string ppf "no signature" | `Time_invalid -> Fmt.string ppf "time invalid" in Alcotest.failf "cannot verify the signature of OCSP response: %a" pp_e e let tests = [ "OpenSSL request", `Quick, test_request ; "OpenSSL response", `Quick, test_response ; "Simple OCSP responder", `Quick, test_simple_responder ; ]