128 lines
4.4 KiB
OCaml
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 ;
|
|
]
|