forked from
gazagnaire.org/ocaml-crypto
upstream: https://github.com/mirage/mirage-crypto
1open OUnit2
2open Crypto
3open Test_common
4
5let sample arr =
6 let ix = Randomconv.int ~bound:(Array.length arr) Crypto_rng.generate in
7 arr.(ix)
8
9(* randomized selfies *)
10
11let ecb_selftest (m : (module Block.ECB)) n =
12 let module C = (val m) in
13 "selftest"
14 >:: times ~n @@ fun _ ->
15 let data = Crypto_rng.generate (C.block_size * 8)
16 and key = C.of_secret @@ Crypto_rng.generate (sample C.key_sizes) in
17 let data' =
18 C.(data |> encrypt ~key |> encrypt ~key |> decrypt ~key |> decrypt ~key)
19 in
20 assert_oct_equal ~msg:"ecb mismatch" data data'
21
22let cbc_selftest (m : (module Block.CBC)) n =
23 let module C = (val m) in
24 "selftest"
25 >:: times ~n @@ fun _ ->
26 let data = Crypto_rng.generate (C.block_size * 8)
27 and iv = Crypto_rng.generate C.block_size
28 and key = C.of_secret @@ Crypto_rng.generate (sample C.key_sizes) in
29 assert_oct_equal ~msg:"CBC e->e->d->d" data
30 C.(
31 data |> encrypt ~key ~iv |> encrypt ~key ~iv |> decrypt ~key ~iv
32 |> decrypt ~key ~iv);
33 let d1, d2 =
34 ( String.sub data 0 (C.block_size * 4),
35 String.sub data (C.block_size * 4)
36 (String.length data - (C.block_size * 4)) )
37 in
38 assert_oct_equal ~msg:"CBC chain"
39 C.(encrypt ~key ~iv data)
40 C.(
41 let e1 = encrypt ~key ~iv d1 in
42 e1 ^ encrypt ~key ~iv:(next_iv ~iv e1) d2)
43
44let ctr_selftest (m : (module Block.CTR)) n =
45 let module M = (val m) in
46 let bs = M.block_size in
47 "selftest"
48 >:: times ~n @@ fun _ ->
49 let key = M.of_secret @@ Crypto_rng.generate (sample M.key_sizes)
50 and ctr = Crypto_rng.generate bs |> M.ctr_of_octets
51 and data =
52 Crypto_rng.(
53 generate @@ (bs + Randomconv.int ~bound:(20 * bs) Crypto_rng.generate))
54 in
55 let enc = M.encrypt ~key ~ctr data in
56 let dec = M.decrypt ~key ~ctr enc in
57 assert_oct_equal ~msg:"CTR e->d" data dec;
58 let d1, d2 =
59 let s =
60 bs
61 * Randomconv.int ~bound:(String.length data / bs) Crypto_rng.generate
62 in
63 (String.sub data 0 s, String.sub data s (String.length data - s))
64 in
65 assert_oct_equal ~msg:"CTR chain" enc
66 @@ M.encrypt ~key ~ctr d1
67 ^ M.encrypt ~key ~ctr:(M.next_ctr ~ctr d1) d2
68
69let ctr_offsets (type c) ~zero (m : (module Block.CTR with type ctr = c)) n =
70 let module M = (val m) in
71 "offsets" >:: fun _ ->
72 let key = M.of_secret @@ Crypto_rng.generate M.key_sizes.(0) in
73 for i = 0 to n - 1 do
74 let ctr =
75 match i with
76 | 0 -> M.add_ctr zero (-1L)
77 | _ -> Crypto_rng.generate M.block_size |> M.ctr_of_octets
78 and gap = Randomconv.int ~bound:64 Crypto_rng.generate in
79 let s1 = M.stream ~key ~ctr ((gap + 1) * M.block_size)
80 and s2 =
81 M.stream ~key ~ctr:(M.add_ctr ctr (Int64.of_int gap)) M.block_size
82 in
83 assert_oct_equal ~msg:"shifted stream"
84 String.(sub s1 (gap * M.block_size) M.block_size)
85 s2
86 done
87
88let xor_selftest n =
89 "selftest"
90 >:: times ~n @@ fun _ ->
91 let n = Randomconv.int ~bound:30 Crypto_rng.generate in
92 let x, y, z = Crypto_rng.(generate n, generate n, generate n) in
93
94 let xyz = Uncommon.(xor (xor x y) z)
95 and xyz' = Uncommon.(xor x (xor y z)) in
96 let x1 = Uncommon.(xor xyz (xor y z))
97 and x2 = Uncommon.(xor (xor z y) xyz) in
98
99 assert_oct_equal ~msg:"assoc" xyz xyz';
100 assert_oct_equal ~msg:"invert" x x1;
101 assert_oct_equal ~msg:"commut" x1 x2
102
103let suite =
104 "All"
105 >::: [
106 "XOR" >::: [ xor_selftest 300 ];
107 "3DES-ECB" >::: [ ecb_selftest (module DES.ECB) 100 ];
108 "3DES-CBC" >::: [ cbc_selftest (module DES.CBC) 100 ];
109 "3DES-CTR"
110 >::: [
111 ctr_selftest (module DES.CTR) 100;
112 ctr_offsets (module DES.CTR) 100 ~zero:0L;
113 ];
114 "AES-ECB" >::: [ ecb_selftest (module AES.ECB) 100 ];
115 "AES-CBC" >::: [ cbc_selftest (module AES.CBC) 100 ];
116 "AES-CTR"
117 >::: [
118 ctr_selftest (module AES.CTR) 100;
119 ctr_offsets (module AES.CTR) 100 ~zero:(0L, 0L);
120 ];
121 ]
122
123let () =
124 Crypto_rng_unix.use_default ();
125 run_test_tt_main suite