From a2038000519fbdef7a174b76d289aa86a5d16538 Mon Sep 17 00:00:00 2001 From: Etienne Millon Date: Tue, 23 Jul 2019 12:00:06 +0200 Subject: [PATCH] Remove ppx_expect dependency (#43) ppx_expect is in theory usable in Mirage since it strips the code in the released binaries; but for now it causes some cross-compilation issues because of C stubs that rely on POSIX APIs. So for now let's do without it! See janestreet/ppx_expect#15 --- fiat-p256.opam | 2 - p256/cstruct_util.ml | 19 -- p256/cstruct_util.mli | 4 - p256/dune | 2 - p256/fiat_p256.ml | 36 +-- p256/montgomery_ladder.ml | 60 ----- p256/parameters.ml | 8 +- p256/parameters.mli | 7 +- p256/point.ml | 173 +------------- p256/point.mli | 17 +- p256/scalar.ml | 53 ----- p256/scalar.mli | 6 - test/{ => functional}/dune | 0 test/{ => functional}/test_fiat_p256.ml | 0 test/{ => functional}/test_fiat_p256.mli | 0 {wycheproof => test/helpers/wycheproof}/dune | 0 .../helpers/wycheproof}/wycheproof.ml | 0 .../helpers/wycheproof}/wycheproof.mli | 0 test/unit/dune | 3 + test/unit/test_p256.ml | 221 ++++++++++++++++++ test/unit/test_p256.mli | 0 {test_wycheproof => test/wycheproof}/dune | 0 .../wycheproof}/ecdh_secp256r1_test.json | 0 {test_wycheproof => test/wycheproof}/test.ml | 0 {test_wycheproof => test/wycheproof}/test.mli | 0 25 files changed, 247 insertions(+), 364 deletions(-) rename test/{ => functional}/dune (100%) rename test/{ => functional}/test_fiat_p256.ml (100%) rename test/{ => functional}/test_fiat_p256.mli (100%) rename {wycheproof => test/helpers/wycheproof}/dune (100%) rename {wycheproof => test/helpers/wycheproof}/wycheproof.ml (100%) rename {wycheproof => test/helpers/wycheproof}/wycheproof.mli (100%) create mode 100644 test/unit/dune create mode 100644 test/unit/test_p256.ml create mode 100644 test/unit/test_p256.mli rename {test_wycheproof => test/wycheproof}/dune (100%) rename {test_wycheproof => test/wycheproof}/ecdh_secp256r1_test.json (100%) rename {test_wycheproof => test/wycheproof}/test.ml (100%) rename {test_wycheproof => test/wycheproof}/test.mli (100%) diff --git a/fiat-p256.opam b/fiat-p256.opam index a534dac..cc1cee5 100644 --- a/fiat-p256.opam +++ b/fiat-p256.opam @@ -25,10 +25,8 @@ depends: [ "cstruct" {>= "3.5.0"} "dune" {build & >= "1.6.0"} "hex" - "hex" {with-test} "ppx_deriving_yojson" {with-test} "rresult" {with-test} - "ppx_expect" "yojson" {with-test & >= "1.6.0"} ] synopsis: "Primitives for Elliptic Curve Cryptography taken from Fiat" diff --git a/p256/cstruct_util.ml b/p256/cstruct_util.ml index 3e42e92..36c3e1d 100644 --- a/p256/cstruct_util.ml +++ b/p256/cstruct_util.ml @@ -1,10 +1,3 @@ -let pp_hex_le fmt cs = - let n = Cstruct.len cs in - for i = n - 1 downto 0 do - let byte = Cstruct.get_uint8 cs i in - Format.fprintf fmt "%02x" byte - done - let compare_be a b = let first_diff = ref None in let a_len = Cstruct.len a in @@ -24,15 +17,3 @@ let compare_be a b = 0 | Some d -> d - -let%expect_test "compare_be" = - let test a b = print_int (compare_be a b) in - test (Cstruct.of_string "aa") (Cstruct.of_string "ab"); - [%expect {| -1 |}]; - test (Cstruct.of_string "ab") (Cstruct.of_string "aa"); - [%expect {| 1 |}]; - test (Cstruct.of_string "aa") (Cstruct.of_string "aa"); - [%expect {| 0 |}]; - test (Cstruct.of_string "abx") (Cstruct.of_string "aaz"); - [%expect {| 1 |}]; - () diff --git a/p256/cstruct_util.mli b/p256/cstruct_util.mli index d879578..fcfb2e8 100644 --- a/p256/cstruct_util.mli +++ b/p256/cstruct_util.mli @@ -1,7 +1,3 @@ -val pp_hex_le : Format.formatter -> Cstruct.t -> unit -(** Display the contents of a cstruct as hex data, seen as a little endian - number. *) - val compare_be : Cstruct.t -> Cstruct.t -> int (** Compare two cstructs, interpreting them as big endian numbers. Raises [Invalid_argument _] if they have a different length. *) diff --git a/p256/dune b/p256/dune index 6efc7c8..5e3b47b 100644 --- a/p256/dune +++ b/p256/dune @@ -4,8 +4,6 @@ (libraries bigarray-compat cstruct hex) (c_names p256_stubs) (c_flags (:include discover/cflags.sexp)) - (preprocess (pps ppx_expect)) - (inline_tests) ) (rule diff --git a/p256/fiat_p256.ml b/p256/fiat_p256.ml index 7f42407..f6a9334 100644 --- a/p256/fiat_p256.ml +++ b/p256/fiat_p256.ml @@ -1,38 +1,7 @@ let dh ~scalar ~point = Point.x_of_finite_point (Montgomery_ladder.scalar_mult scalar point) -let base_point = Point.of_hex_exn Parameters.g - -let public scalar = Montgomery_ladder.scalar_mult scalar base_point - -let%expect_test "dh" = - let test d p = - Format.printf "%a\n" Cstruct_util.pp_hex_le (dh ~scalar:d ~point:p) - in - let d_a = - Scalar.of_hex_exn - (`Hex - "200102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") - in - let d_b = - Scalar.of_hex_exn - (`Hex - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") - in - let p_a = public d_a in - let p_b = public d_b in - test d_b p_a; - [%expect - {| 2e3e4065a62a7f425aaf8aae3d158f367c733300b5002e0b62f4bc6260789e1b |}]; - test d_a p_b; - [%expect - {| 2e3e4065a62a7f425aaf8aae3d158f367c733300b5002e0b62f4bc6260789e1b |}]; - test d_a p_a; - [%expect - {| 2ea4e810837da217a5bfd05f01d12459eeda830b6e0dec7f8afa425c5b55c507 |}]; - test d_b p_b; - [%expect - {| a7666bcc3818472194460f7df22d80a5886da0e1679eac930175ce1ff733c7ca |}] +let public scalar = Montgomery_ladder.scalar_mult scalar Point.params_g type error = Error.point_error @@ -73,7 +42,6 @@ let gen_key ~rng = let key_exchange secret received = match point_of_cs received with - | Error _ as err -> - err + | Error _ as err -> err | Ok other_party_public_key -> Ok (dh ~scalar:secret ~point:other_party_public_key) diff --git a/p256/montgomery_ladder.ml b/p256/montgomery_ladder.ml index d583759..178b24b 100644 --- a/p256/montgomery_ladder.ml +++ b/p256/montgomery_ladder.ml @@ -10,63 +10,3 @@ let scalar_mult d p = r0 := Point.double !r0 ) done; !r0 - -let%expect_test "scalar mult" = - let test ~scalar ~point = - let scalar = Scalar.of_hex_exn scalar in - let point = Point.of_hex_exn point in - let res = scalar_mult scalar point in - Format.printf "%a\n" Point.pp res - in - let point = - `Hex - "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5" - in - test - ~scalar: - (`Hex - "0000000000000000000000000000000000000000000000000000000000000001") - ~point; - [%expect - {| 046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 |}]; - test - ~scalar: - (`Hex - "0000000000000000000000000000000000000000000000000000000000000002") - ~point; - [%expect - {| 047cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997807775510db8ed040293d9ac69f7430dbba7dade63ce982299e04b79d227873d1 |}]; - test - ~scalar: - (`Hex - "0000000000000000000000000000000000000000000000000000000000000004") - ~point; - [%expect - {| 04e2534a3532d08fbba02dde659ee62bd0031fe2db785596ef509302446b030852e0f1575a4c633cc719dfee5fda862d764efc96c3f30ee0055c42c23f184ed8c6 |}]; - test - ~scalar: - (`Hex - "0612465c89a023ab17855b0a6bcebfd3febb53aef84138647b5352e02c10c346") - ~point: - (`Hex - "0462d5bd3372af75fe85a040715d0f502428e07046868b0bfdfa61d731afe44f26ac333a93a9e70a81cd5a95b5bf8d13990eb741c8c38872b4a07d275a014e30cf"); - [%expect - {| 0453020d908b0219328b658b525f26780e3ae12bcd952bb25a93bc0895e1714285b2ba871dd1652c3f467df15c6b70647efbcbbab5cbf7f55e6ff336f843d628a1 |}]; - test - ~scalar: - (`Hex - "0a0d622a47e48f6bc1038ace438c6f528aa00ad2bd1da5f13ee46bf5f633d71a") - ~point: - (`Hex - "043cbc1b31b43f17dc200dd70c2944c04c6cb1b082820c234a300b05b7763844c74fde0a4ef93887469793270eb2ff148287da9265b0334f9e2609aac16e8ad503"); - [%expect - {| 047fffffffffffffffffffffffeecf2230ffffffffffffffffffffffffffffffff00000001c7c30643abed0af0a49fe352cb483ff9b97dccdf427c658e8793240d |}]; - test - ~scalar: - (`Hex - "55d55f11bb8da1ea318bca7266f0376662441ea87270aa2077f1b770c4854a48") - ~point: - (`Hex - "04000000000000000000000000000000000000000000000000000000000000000066485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4"); - [%expect - {| 04cfe4077c8730b1c9384581d36bff5542bc417c9eff5c2afcb98cc8829b2ce8487764c65671a66a3ecf1ec63cf49b5c36119162ace73f8d8be270e27cdaf4677c |}] diff --git a/p256/parameters.ml b/p256/parameters.ml index 6cc39b0..b0e3167 100644 --- a/p256/parameters.ml +++ b/p256/parameters.ml @@ -4,9 +4,11 @@ let a = let b = `Hex "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B" -let g = - `Hex - "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5" +let g_x = + `Hex "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" + +let g_y = + `Hex "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5" let p = `Hex "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF" diff --git a/p256/parameters.mli b/p256/parameters.mli index 017f1bb..b6b0834 100644 --- a/p256/parameters.mli +++ b/p256/parameters.mli @@ -6,8 +6,11 @@ val a : Hex.t val b : Hex.t -val g : Hex.t -(** The base point, in uncompressed form. *) +val g_x : Hex.t +(** The base point's x coordinate. *) + +val g_y : Hex.t +(** The base point's y coordinate. *) val p : Hex.t (** The prime number corresponding to [Fe]. *) diff --git a/p256/point.ml b/p256/point.ml index 9a65021..be5111d 100644 --- a/p256/point.ml +++ b/p256/point.ml @@ -44,45 +44,7 @@ let validate_finite_point ~x ~y = let f_z = Fe.one () in Ok {f_x; f_y; f_z} else Error `Not_on_curve - | _ -> - Error `Invalid_range - -let%expect_test "validate_finite_point" = - let is_ok = function - | Ok _ -> - true - | Error _ -> - false - in - let test ~x ~y = - Printf.printf "%b" - (is_ok - (validate_finite_point ~x:(Hex.to_cstruct x) ~y:(Hex.to_cstruct y))) - in - test - ~x: - (`Hex - "62d5bd3372af75fe85a040715d0f502428e07046868b0bfdfa61d731afe44f26") - ~y: - (`Hex - "ac333a93a9e70a81cd5a95b5bf8d13990eb741c8c38872b4a07d275a014e30cf"); - [%expect {| true |}]; - test - ~x: - (`Hex - "0000000000000000000000000000000000000000000000000000000000000000") - ~y: - (`Hex - "0000000000000000000000000000000000000000000000000000000000000000"); - [%expect {| false |}]; - let zero = `Hex (String.make 64 '0') in - let sb = - `Hex "66485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4" - in - test ~x:zero ~y:sb; - [%expect {| true |}]; - test ~x:Parameters.p ~y:sb; - [%expect {| false |}] + | _ -> Error `Invalid_range let first_byte cs = if Cstruct.len cs = 0 then None else Some (Cstruct.get_uint8 cs 0) @@ -101,43 +63,6 @@ let of_cstruct cs = | _, _ -> Error `Invalid_format -let of_hex h = of_cstruct (Hex.to_cstruct h) - -let%expect_test "of_hex" = - let test hex = - let ok = - match of_hex hex with - | Ok _ -> - true - | Error _ -> - false - in - Printf.printf "%b" ok - in - test (`Hex "00"); - [%expect {| true |}]; - test (`Hex "0001"); - [%expect {| false |}]; - test - (`Hex - "0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - [%expect {| false |}]; - test - (`Hex - "0462d5bd3372af75fe85a040715d0f502428e07046868b0bfdfa61d731afe44f26ac333a93a9e70a81cd5a95b5bf8d13990eb741c8c38872b4a07d275a014e30cf"); - [%expect {| true |}]; - test (`Hex "0400"); - [%expect {| false |}]; - test (`Hex "ff"); - [%expect {| false |}] - -let of_hex_exn h = - match of_hex h with - | Ok p -> - p - | Error e -> - failwith (Format.asprintf "of_hex_exn: %a" Error.pp_point_error e) - let to_affine p = if is_infinity p then None else @@ -170,110 +95,28 @@ let to_cstruct p = let rev_x = Cstruct.rev x and rev_y = Cstruct.rev y in Cstruct.concat [four; rev_x; rev_y] -let pp fmt p = Cstruct_util.pp_hex_le fmt (Cstruct.rev (to_cstruct p)) - external double_c : t -> t -> unit = "fiat_p256_caml_point_double" [@@noalloc] let double p = let out = {f_x = Fe.create (); f_y = Fe.create (); f_z = Fe.create ()} in double_c out p; out -let%expect_test "double" = - let print_point = Format.printf "%a\n" pp in - let test p = print_point @@ double p in - let p = - of_hex_exn - (`Hex - "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5") - in - test p; - [%expect - {| - 047cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997807775510db8ed040293d9ac69f7430dbba7dade63ce982299e04b79d227873d1 |}]; - test (at_infinity ()); - [%expect {| 00 |}]; - test - (of_hex_exn - (`Hex - "046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a")); - [%expect - {| - 047cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978f888aaee24712fc0d6c26539608bcf244582521ac3167dd661fb4862dd878c2e |}] - external add_c : t -> t -> t -> unit = "fiat_p256_caml_point_add" [@@noalloc] let add fe_p fe_q = let out = {f_x = Fe.create (); f_y = Fe.create (); f_z = Fe.create ()} in add_c out fe_p fe_q; out -let%expect_test "add" = - let test p q = - let r = add p q in - Format.printf "%a\n" pp r - in - let p = - of_hex_exn - (`Hex - "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5") - in - let q = - of_hex_exn - (`Hex - "046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a") - in - test p (at_infinity ()); - [%expect - {| - 046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 |}]; - test (at_infinity ()) (at_infinity ()); - [%expect {| 00 |}]; - test p p; - [%expect - {| - 047cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997807775510db8ed040293d9ac69f7430dbba7dade63ce982299e04b79d227873d1 |}]; - test p q; - [%expect {| 00 |}]; - test q q; - [%expect - {| - 047cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978f888aaee24712fc0d6c26539608bcf244582521ac3167dd661fb4862dd878c2e -|}]; - test - (of_hex_exn - (`Hex - "04b719d9cc1c48ebe628eb717c7eb7f619350a4beec1338e31b6b99da50b8b3e1b95306f9fa3bb49fad08751f648f3a074c16ac4aa02bd057a8a22150c2b719b1d")) - (of_hex_exn - (`Hex - "043f894c1ede3f1d6c6ae483e5d260afe006303d19d5c49e2595461bb91fd0ff96c0ac188423e2dd175dbb6e2fc449fd37cee52177764a21d24e74f84261491a7f")); - [%expect - "042e831e3b63a3d7c195f2fb4654b90e8cecd0d80b10448ff6699221e626a5095a95d666ef1f3114b49f6e4dac5f758a1ee81878164fd4e6e870e6ed5c0432e95b"]; - test - (of_hex_exn - (`Hex - "042e831e3b63a3d7c195f2fb4654b90e8cecd0d80b10448ff6699221e626a5095a95d666ef1f3114b49f6e4dac5f758a1ee81878164fd4e6e870e6ed5c0432e95b")) - (of_hex_exn - (`Hex - "041690393bb369ad609b7a43b25f11a5e62bcc298e8dde31ac5aa28c820cce7fb255f9c348aece766354b536211e307d02f38dda103b14a26796875444ef90d232")); - [%expect - "0453020d908b0219328b658b525f26780e3ae12bcd952bb25a93bc0895e1714285b2ba871dd1652c3f467df15c6b70647efbcbbab5cbf7f55e6ff336f843d628a1"] - -let%expect_test "double vs add" = - let p = - of_hex_exn - (`Hex - "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5") - in - let print_point = Format.printf "%a\n" pp in - print_point @@ add p @@ add p @@ add p p; - [%expect - {| 04e2534a3532d08fbba02dde659ee62bd0031fe2db785596ef509302446b030852e0f1575a4c633cc719dfee5fda862d764efc96c3f30ee0055c42c23f184ed8c6 |}]; - print_point @@ double @@ double p; - [%expect - {| 04e2534a3532d08fbba02dde659ee62bd0031fe2db785596ef509302446b030852e0f1575a4c633cc719dfee5fda862d764efc96c3f30ee0055c42c23f184ed8c6 |}] - let x_of_finite_point p = match to_affine p with | None -> assert false | Some (x, _) -> Cstruct.rev x + +let params_g = + let x = Hex.to_cstruct Parameters.g_x in + let y = Hex.to_cstruct Parameters.g_y in + match validate_finite_point ~x ~y with + | Ok p -> p + | Error _ -> assert false diff --git a/p256/point.mli b/p256/point.mli index 2ef947c..3d6098a 100644 --- a/p256/point.mli +++ b/p256/point.mli @@ -31,22 +31,11 @@ val of_cstruct : @see *) -val of_hex : - Hex.t - -> ( t - , [> `Invalid_format | `Invalid_length | `Invalid_range | `Not_on_curve] - ) - result -(** Convert from hex. See [of_cstruct]. *) - -val of_hex_exn : Hex.t -> t -(** Convert from hex, raising an exception if data is invalid. See [of_hex]. *) - val to_cstruct : t -> Cstruct.t (** Convert to a cstruct. See [of_cstruct] for the format. *) -val pp : Format.formatter -> t -> unit -(** Display a point in the format documented in [of_cstruct]. *) - val x_of_finite_point : t -> Cstruct.t (** Return only the X coordinate of a point that is not at infinity. *) + +val params_g : t +(** The curve's base point *) diff --git a/p256/scalar.ml b/p256/scalar.ml index 3f08663..a18f990 100644 --- a/p256/scalar.ml +++ b/p256/scalar.ml @@ -1,7 +1,5 @@ type t = Scalar of Cstruct.t -let pp fmt (Scalar s) = Cstruct_util.pp_hex_le fmt s - let is_in_range cs = let zero = Cstruct.create 32 in let n = Hex.to_cstruct Parameters.n in @@ -12,57 +10,6 @@ let of_cstruct cs = else if is_in_range cs then Ok (Scalar (Cstruct.rev cs)) else Error `Invalid_range -let of_hex h = - let cs = Hex.to_cstruct h in - of_cstruct cs - -let pp_err pp fmt = function - | Error e -> - Error.pp_scalar_error fmt e - | Ok x -> - pp fmt x - -let%expect_test "of_hex" = - let test h = - let s = of_hex h in - Format.printf "%a\n" (pp_err pp) s - in - test - (`Hex "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"); - [%expect - {| 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f |}]; - test - (`Hex "0000000000000000000000000000000000000000000000000000000000000003"); - [%expect - {| 0000000000000000000000000000000000000000000000000000000000000003 |}]; - test - (`Hex - "2000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"); - [%expect {| Cannot parse scalar: invalid length |}]; - test - (`Hex "0000000000000000000000000000000000000000000000000000000000000000"); - [%expect {| Cannot parse scalar: invalid range |}]; - test - (`Hex - (* n-1 *) - "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550"); - [%expect - {| ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550 |}]; - test Parameters.n; - [%expect {| Cannot parse scalar: invalid range |}]; - test - (`Hex - (* n+1 *) - "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632552"); - [%expect {| Cannot parse scalar: invalid range |}] - -let of_hex_exn h = - match of_hex h with - | Ok p -> - p - | Error e -> - failwith (Format.asprintf "of_hex_exn: %a" Error.pp_scalar_error e) - let bit_at (Scalar s) i = let byte_num = i / 8 in let bit_num = i mod 8 in diff --git a/p256/scalar.mli b/p256/scalar.mli index c89c930..74db387 100644 --- a/p256/scalar.mli +++ b/p256/scalar.mli @@ -6,12 +6,6 @@ val of_cstruct : Cstruct.t -> (t, Error.scalar_error) result It should be 32 bytes long, in big endian format. Returns an error when the number is zero, or if it is larger than or equal to the group order. *) -val of_hex : Hex.t -> (t, Error.scalar_error) result -(** Like [of_cstruct] but read from hex data. *) - -val of_hex_exn : Hex.t -> t -(** Like [of_hex] but raises if there is an error. *) - val bit_at : t -> int -> bool (** [bit_at d n] returns the [n]th bit from [d], where bit 0 is the least significant bit. *) diff --git a/test/dune b/test/functional/dune similarity index 100% rename from test/dune rename to test/functional/dune diff --git a/test/test_fiat_p256.ml b/test/functional/test_fiat_p256.ml similarity index 100% rename from test/test_fiat_p256.ml rename to test/functional/test_fiat_p256.ml diff --git a/test/test_fiat_p256.mli b/test/functional/test_fiat_p256.mli similarity index 100% rename from test/test_fiat_p256.mli rename to test/functional/test_fiat_p256.mli diff --git a/wycheproof/dune b/test/helpers/wycheproof/dune similarity index 100% rename from wycheproof/dune rename to test/helpers/wycheproof/dune diff --git a/wycheproof/wycheproof.ml b/test/helpers/wycheproof/wycheproof.ml similarity index 100% rename from wycheproof/wycheproof.ml rename to test/helpers/wycheproof/wycheproof.ml diff --git a/wycheproof/wycheproof.mli b/test/helpers/wycheproof/wycheproof.mli similarity index 100% rename from wycheproof/wycheproof.mli rename to test/helpers/wycheproof/wycheproof.mli diff --git a/test/unit/dune b/test/unit/dune new file mode 100644 index 0000000..31d0488 --- /dev/null +++ b/test/unit/dune @@ -0,0 +1,3 @@ +(test + (name test_p256) + (libraries alcotest fiat_p256)) diff --git a/test/unit/test_p256.ml b/test/unit/test_p256.ml new file mode 100644 index 0000000..95527ec --- /dev/null +++ b/test/unit/test_p256.ml @@ -0,0 +1,221 @@ +module Testable = struct + let fiat_error = Alcotest.testable Fiat_p256.pp_error ( = ) + + let ok_or_error = Alcotest.result Alcotest.unit fiat_error +end + +let key_pair_of_hex h = Fiat_p256.gen_key ~rng:(fun _ -> Hex.to_cstruct h) + +let scalar_of_hex h = fst (key_pair_of_hex h) + +let pp_hex_le fmt cs = + let n = Cstruct.len cs in + for i = n - 1 downto 0 do + let byte = Cstruct.get_uint8 cs i in + Format.fprintf fmt "%02x" byte + done + +let pp_result ppf = function + | Ok cs -> pp_hex_le ppf cs + | Error e -> Format.fprintf ppf "%a" Fiat_p256.pp_error e + +let key_exchange = + let test ~name d p ~expected = + ( name + , `Quick + , fun () -> + Fiat_p256.key_exchange d p + |> Format.asprintf "%a" pp_result + |> Alcotest.check Alcotest.string __LOC__ expected ) + in + let d_a, p_a = + key_pair_of_hex + (`Hex + "200102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + in + let d_b, p_b = + key_pair_of_hex + (`Hex + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + in + [ test ~name:"b*A" d_b p_a + ~expected: + "2e3e4065a62a7f425aaf8aae3d158f367c733300b5002e0b62f4bc6260789e1b" + ; test ~name:"a*B" d_a p_b + ~expected: + "2e3e4065a62a7f425aaf8aae3d158f367c733300b5002e0b62f4bc6260789e1b" + ; test ~name:"a*A" d_a p_a + ~expected: + "2ea4e810837da217a5bfd05f01d12459eeda830b6e0dec7f8afa425c5b55c507" + ; test ~name:"b*B" d_b p_b + ~expected: + "a7666bcc3818472194460f7df22d80a5886da0e1679eac930175ce1ff733c7ca" ] + +let scalar_mult = + let test ~scalar ~point ~expected = + let scalar = scalar_of_hex scalar in + let point = Hex.to_cstruct point in + (scalar, point, expected) + in + let run i (scalar, point, expected) = + ( Printf.sprintf "Scalar mult (#%d)" i + , `Quick + , fun () -> + Fiat_p256.key_exchange scalar point + |> Format.asprintf "%a" pp_result + |> Alcotest.check Alcotest.string __LOC__ expected ) + in + let point = + `Hex + "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5" + in + List.mapi run + [ test + ~scalar: + (`Hex + "0000000000000000000000000000000000000000000000000000000000000001") + ~point + ~expected: + "96c298d84539a1f4a033eb2d817d0377f240a463e5e6bcf847422ce1f2d1176b" + ; test + ~scalar: + (`Hex + "0000000000000000000000000000000000000000000000000000000000000002") + ~point + ~expected: + "78996647fc480ba6351bf277e26989c0c31ab5040338528a7e4f038d187bf27c" + ; test + ~scalar: + (`Hex + "0000000000000000000000000000000000000000000000000000000000000004") + ~point + ~expected: + "5208036b44029350ef965578dbe21f03d02be69e65de2da0bb8fd032354a53e2" + ; test + ~scalar: + (`Hex + "0612465c89a023ab17855b0a6bcebfd3febb53aef84138647b5352e02c10c346") + ~point: + (`Hex + "0462d5bd3372af75fe85a040715d0f502428e07046868b0bfdfa61d731afe44f26ac333a93a9e70a81cd5a95b5bf8d13990eb741c8c38872b4a07d275a014e30cf") + ~expected: + "854271e19508bc935ab22b95cd2be13a0e78265f528b658b3219028b900d0253" + ; test + ~scalar: + (`Hex + "0a0d622a47e48f6bc1038ace438c6f528aa00ad2bd1da5f13ee46bf5f633d71a") + ~point: + (`Hex + "043cbc1b31b43f17dc200dd70c2944c04c6cb1b082820c234a300b05b7763844c74fde0a4ef93887469793270eb2ff148287da9265b0334f9e2609aac16e8ad503") + ~expected: + "ffffffffffffffffffffffffffffffff3022cfeeffffffffffffffffffffff7f" + ; test + ~scalar: + (`Hex + "55d55f11bb8da1ea318bca7266f0376662441ea87270aa2077f1b770c4854a48") + ~point: + (`Hex + "04000000000000000000000000000000000000000000000000000000000000000066485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4") + ~expected: + "48e82c9b82c88cb9fc2a5cff9e7c41bc4255ff6bd3814538c9b130877c07e4cf" + ] + +let to_ok_or_error = function + | Ok _ -> Ok () + | Error _ as e -> e + +let point_validation = + let test ~name ~x ~y ~expected = + let scalar = + scalar_of_hex + (`Hex + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + in + let point = + Cstruct.concat [Cstruct.of_hex "04"; Hex.to_cstruct x; Hex.to_cstruct y] + in + ( name + , `Quick + , fun () -> + Fiat_p256.key_exchange scalar point + |> to_ok_or_error + |> Alcotest.check Testable.ok_or_error __LOC__ expected ) + in + let zero = `Hex (String.make 64 '0') in + let sb = + `Hex "66485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4" + in + [ test ~name:"Ok" + ~x: + (`Hex + "62d5bd3372af75fe85a040715d0f502428e07046868b0bfdfa61d731afe44f26") + ~y: + (`Hex + "ac333a93a9e70a81cd5a95b5bf8d13990eb741c8c38872b4a07d275a014e30cf") + ~expected:(Ok ()) + ; test ~name:"P=0" + ~x: + (`Hex + "0000000000000000000000000000000000000000000000000000000000000000") + ~y: + (`Hex + "0000000000000000000000000000000000000000000000000000000000000000") + ~expected:(Error `Not_on_curve) + ; test ~name:"(0, sqrt(b))" ~x:zero ~y:sb ~expected:(Ok ()) + ; test ~name:"out of range" + ~x: + (`Hex + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF") + ~y:sb + ~expected:(Error `Invalid_range) ] + +let scalar_validation = + let test_scalar_validation ~name ~scalar ~expected = + let safe = + Cstruct.of_hex + "0000000000000000000000000000000000000000000000000000000000000001" + in + let ncalls = ref 0 in + let return_value = ref (Some (Hex.to_cstruct scalar)) in + let rng _ = + incr ncalls; + match !return_value with + | None -> safe + | Some rv -> + return_value := None; + rv + in + ( name + , `Quick + , fun () -> + let _, _ = Fiat_p256.gen_key ~rng in + let got = !ncalls in + Alcotest.check Alcotest.int __LOC__ expected got ) + in + [ test_scalar_validation ~name:"0" + ~scalar: + (`Hex + "0000000000000000000000000000000000000000000000000000000000000000") + ~expected:2 + ; test_scalar_validation ~name:"1" + ~scalar: + (`Hex + "0000000000000000000000000000000000000000000000000000000000000001") + ~expected:1 + ; test_scalar_validation ~name:"n-1" + ~scalar: + (`Hex + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550") + ~expected:1 + ; test_scalar_validation ~name:"n" + ~scalar: + (`Hex + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551") + ~expected:2 ] + +let () = + Alcotest.run "Fiat_p256" + [ ("Key exchange", key_exchange) + ; ("Low level scalar mult", scalar_mult) + ; ("Point validation", point_validation) + ; ("Scalar validation when generating", scalar_validation) ] diff --git a/test/unit/test_p256.mli b/test/unit/test_p256.mli new file mode 100644 index 0000000..e69de29 diff --git a/test_wycheproof/dune b/test/wycheproof/dune similarity index 100% rename from test_wycheproof/dune rename to test/wycheproof/dune diff --git a/test_wycheproof/ecdh_secp256r1_test.json b/test/wycheproof/ecdh_secp256r1_test.json similarity index 100% rename from test_wycheproof/ecdh_secp256r1_test.json rename to test/wycheproof/ecdh_secp256r1_test.json diff --git a/test_wycheproof/test.ml b/test/wycheproof/test.ml similarity index 100% rename from test_wycheproof/test.ml rename to test/wycheproof/test.ml diff --git a/test_wycheproof/test.mli b/test/wycheproof/test.mli similarity index 100% rename from test_wycheproof/test.mli rename to test/wycheproof/test.mli