mte/unikernel/duniverse/ocaml-x509/tests/ocsp.ml
2025-11-11 02:07:51 +01:00

128 lines
4.4 KiB
OCaml

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 ;
]