upstream: https://github.com/mirage/mirage-crypto

Merge pull request #235 from hannesm/no-handcrafted-asn1

tests, mirage-crypto-ec: use asn1-combinators again

authored by

Hannes Mehnert and committed by
GitHub
8ac86fad 448ad358

+26 -130
+1
mirage-crypto-ec.opam
··· 36 36 "ppx_deriving_yojson" {with-test} 37 37 "ppx_deriving" {with-test} 38 38 "yojson" {with-test & >= "1.6.0"} 39 + "asn1-combinators" {with-test & >= "0.3.1"} 39 40 ] 40 41 conflicts: [ 41 42 "ocaml-freestanding"
+1 -1
tests/dune
··· 57 57 ecdsa_secp384r1_sha384_test.json ecdsa_secp384r1_sha512_test.json 58 58 ecdh_secp521r1_test.json ecdsa_secp521r1_sha512_test.json 59 59 x25519_test.json eddsa_test.json) 60 - (libraries alcotest mirage-crypto-ec wycheproof digestif) 60 + (libraries alcotest mirage-crypto-ec wycheproof digestif asn1-combinators) 61 61 (package mirage-crypto-ec)) 62 62 63 63 (tests
+24 -129
tests/test_ec_wycheproof.ml
··· 15 15 let hex = Alcotest.testable Wycheproof.pp_hex Wycheproof.equal_hex 16 16 17 17 module Asn = struct 18 - (* This is a handcrafted asn1 parser, sufficient for the wycheproof tests. 19 - The underlying reason is to avoid a dependency on asn1-grammars and 20 - mirage-crypto-pk (which depends on gmp and zarith, and are cumbersome to 21 - build on windows with CL.EXE). *) 22 - 23 - let guard p e = if p then Ok () else Error e 24 - 25 - let decode_len start_off buf = 26 - let len = string_get_uint8 buf start_off in 27 - if len >= 0x80 then 28 - let bytes = len - 0x80 in 29 - let rec g acc off = 30 - if off = bytes then 31 - Ok (acc, bytes + start_off + 1) 32 - else 33 - let this = string_get_uint8 buf (start_off + 1 + off) in 34 - let* () = guard (off = 0 && this >= 0x80) "badly encoded length" in 35 - let acc' = acc lsl 8 + this in 36 - let* () = guard (acc <= acc') "decode_len overflow in acc" in 37 - g (acc lsl 8 + string_get_uint8 buf (start_off + 1 + off)) (succ off) 38 - in 39 - g 0 0 40 - else 41 - Ok (len, start_off + 1) 42 - 43 - let decode_seq data = 44 - let* () = guard (String.length data > 2) "decode_seq: data too short" in 45 - let tag = string_get_uint8 data 0 in 46 - let* () = guard (tag = 0x30) "decode_seq: bad tag (should be 0x30)" in 47 - let* len, off = decode_len 1 data in 48 - let* () = guard (String.length data - off >= len) "decode_seq: too short" in 49 - Ok (String.sub data off len, 50 - if String.length data - off > len then 51 - Some (String.sub data (off + len) (String.length data - len - off)) 52 - else 53 - None) 54 - 55 - let decode_2_oid data = 56 - let decode_one off = 57 - let tag = string_get_uint8 data off in 58 - let* () = guard (tag = 0x06) "decode_oid: bad tag (should be 0x06)" in 59 - let len = string_get_uint8 data (off + 1) in 60 - let* () = guard (String.length data - 2 - off >= len) "decode_oid: data too short" in 61 - Ok (String.sub data (off + 2) len, off + 2 + len) 62 - in 63 - let* first, off = decode_one 0 in 64 - let* second, off = decode_one off in 65 - let* () = guard (off = String.length data) "decode_oid: leftover data" in 66 - Ok (first, second) 67 - 68 - let decode_bit_string data = 69 - let tag = string_get_uint8 data 0 in 70 - let* () = guard (tag = 0x03) "decode_bit_string: bad tag (expected 0x03)" in 71 - let* len, off = decode_len 1 data in 72 - let* () = guard (String.length data - off = len) "decode_bit_string: leftover or too short data" in 73 - let unused = string_get_uint8 data off in 74 - let* () = guard (unused = 0) "unused is not 0" in 75 - Ok (String.sub data (off + 1) (len - 1)) 76 - 77 - let decode_int_pair data = 78 - let decode_int off = 79 - let* () = guard (String.length data - off > 2) "decode_int: data too short" in 80 - let tag = string_get_uint8 data off in 81 - let* () = guard (tag = 0x02) "decode_int: bad tag (should be 0x02)" in 82 - let len = string_get_uint8 data (off + 1) in 83 - let* () = guard (String.length data - off - 2 >= len) "decode_int: too short" in 84 - let fix_one = if string_get_uint8 data (off + 2) = 0x00 then 1 else 0 in 85 - let* () = guard (string_get_uint8 data (off + 2) land 0x80 = 0) "decode_int: negative number" in 86 - let* () = 87 - if String.length data > off + 3 && fix_one = 1 then 88 - guard (string_get_uint8 data (off + 3) <> 0x00) "decode_int: leading extra 0 byte" 89 - else 90 - Ok () 91 - in 92 - Ok (String.sub data (fix_one + off + 2) (len - fix_one), off + len + 2) 93 - in 94 - let* first, off = decode_int 0 in 95 - let* second, off = decode_int off in 96 - let* () = guard (off = String.length data) "decode_int: leftover data" in 97 - Ok (first, second) 98 - 99 - let encode_oid = function 100 - | first :: second :: rt -> 101 - let oct1 = 40 * first + second in 102 - let octs = concat_map (fun x -> 103 - let fst = x / 16384 104 - and snd = x / 128 105 - and thr = x mod 128 106 - in 107 - assert (fst < 128); 108 - (if fst > 0 then [ 128 (* set high bit *) + fst ] else []) @ 109 - (if snd > 0 then [ 128 + snd ] else []) @ 110 - [ thr ]) 111 - rt 112 - in 113 - String.init (1 + List.length octs) (function 114 - | 0 -> char_of_int oct1 115 - | n -> char_of_int (List.nth octs (pred n))) 116 - | _ -> assert false 117 - 118 18 let parse_point curve s = 119 - let ec_public_key = encode_oid [ 1 ; 2 ; 840; 10045; 2; 1 ] in 120 - let prime_oid = encode_oid (match curve with 121 - | "secp256r1" -> [ 1 ; 2 ; 840; 10045; 3; 1; 7 ] 122 - | "secp384r1" -> [ 1 ; 3 ; 132; 0; 34 ] 123 - | "secp521r1" -> [ 1 ; 3 ; 132; 0; 35 ] 124 - | _ -> assert false) 19 + let seq2 a b = Asn.S.(sequence2 (required a) (required b)) in 20 + let term = Asn.S.(seq2 (seq2 oid oid) bit_string_octets) in 21 + let ec_public_key = Asn.OID.(base 1 2 <|| [ 840; 10045; 2; 1 ]) in 22 + let prime_oid = match curve with 23 + | "secp256r1" -> Asn.OID.(base 1 2 <|| [ 840; 10045; 3; 1; 7 ]) 24 + | "secp384r1" -> Asn.OID.(base 1 3 <|| [ 132; 0; 34 ]) 25 + | "secp521r1" -> Asn.OID.(base 1 3 <|| [ 132; 0; 35 ]) 26 + | _ -> assert false 125 27 in 126 - let* r = decode_seq s in 127 - match r with 128 - | _data, Some _ -> Error "expected no leftover" 129 - | data, None -> 130 - let* r = decode_seq data in 131 - match r with 132 - | _oids, None -> Error "expected some data" 133 - | oids, Some data -> 134 - let* oid1, oid2 = decode_2_oid oids in 135 - let* data = decode_bit_string data in 136 - if not (String.equal oid1 ec_public_key) then 137 - Error "ASN1: wrong oid 1" 138 - else if not (String.equal oid2 prime_oid) then 139 - Error "ASN1: wrong oid 2" 140 - else 141 - Ok data 28 + match Asn.decode (Asn.codec Asn.ber term) s with 29 + | Error _ -> Error "ASN1 parse error" 30 + | Ok (((oid1, oid2), data), rest) -> 31 + if String.length rest <> 0 then Error "ASN1 leftover" 32 + else if not (Asn.OID.equal oid1 ec_public_key) then 33 + Error "ASN1: wrong oid 1" 34 + else if not (Asn.OID.equal oid2 prime_oid) then Error "ASN1: wrong oid 2" 35 + else Ok data 142 36 143 - let parse_signature s = 144 - let* r = decode_seq s in 145 - match r with 146 - | _data, Some _ -> Error "expected no leftover" 147 - | data, None -> 148 - let* r, s = decode_int_pair data in 149 - Ok (r, s) 37 + let parse_signature cs = 38 + let asn = Asn.S.(sequence2 (required unsigned_integer) (required unsigned_integer)) in 39 + match Asn.(decode (codec der asn) cs) with 40 + | Error _ -> Error "ASN1 parse error" 41 + | Ok (r_s, rest) -> 42 + if String.length rest <> 0 then Error "ASN1 leftover" 43 + else 44 + Ok r_s 150 45 end 151 46 152 47 let to_string_result ~pp_error = function