diff --git a/vendors/ocaml-pbkdf/pbkdf.opam b/vendors/ocaml-pbkdf/pbkdf.opam index 00a393c96..e6b0a2c9d 100644 --- a/vendors/ocaml-pbkdf/pbkdf.opam +++ b/vendors/ocaml-pbkdf/pbkdf.opam @@ -12,6 +12,9 @@ build: [ "dune" "build" "-j" jobs "-p" name "@install" ] build-test: [ "dune" "runtest" "-p" name "-j" jobs ] depends: [ "dune" {build & = "1.0.1"} - "nocrypto" {>= "0.5.4"} + "hacl" + "bigstring" {>= "0.2"} + "ocplib-endian" {>= "1.0"} "alcotest" {test & >= "0.8.1"} + "hex" {test & >= "1.2.0"} ] diff --git a/vendors/ocaml-pbkdf/src/dune b/vendors/ocaml-pbkdf/src/dune index ebbcebd21..59945d957 100644 --- a/vendors/ocaml-pbkdf/src/dune +++ b/vendors/ocaml-pbkdf/src/dune @@ -2,4 +2,4 @@ (name pbkdf) (public_name pbkdf) (synopsis "") - (libraries nocrypto)) + (libraries bigstring hacl)) diff --git a/vendors/ocaml-pbkdf/src/pbkdf.ml b/vendors/ocaml-pbkdf/src/pbkdf.ml index 9e8e6d89e..bb8bf63d0 100644 --- a/vendors/ocaml-pbkdf/src/pbkdf.ml +++ b/vendors/ocaml-pbkdf/src/pbkdf.ml @@ -1,56 +1,49 @@ -open Nocrypto -open Uncommon +let xorbuf a b = + let alen = Bigstring.length a in + if Bigstring.length b <> alen then + invalid_arg "xor: both buffers must be of same size" ; + for i = 0 to alen - 1 do + Bigstring.(set a i Char.(chr (code (get a i) lxor code (get b i)))) + done ; + a + +let cdiv x y = + (* This is lifted from Nocrypto.Uncommon.(//) + (formerly known as [cdiv]). It is part of the documented, publically + exposed _internal_ utility library not for public consumption, hence + the API break that prompted this copy-pasted function. *) + if y < 1 then raise Division_by_zero else + if x > 0 then 1 + ((x - 1) / y) else 0 [@@inline] module type S = sig - val pbkdf1 : password:Cstruct.t -> salt:Cstruct.t -> count:int -> dk_len:int -> Cstruct.t - val pbkdf2 : password:Cstruct.t -> salt:Cstruct.t -> count:int -> dk_len:int32 -> Cstruct.t + val pbkdf2 : password:Bigstring.t -> salt:Bigstring.t -> count:int -> dk_len:int32 -> Bigstring.t end -module Make (H: Hash.S) : S = struct - let pbkdf1 ~password ~salt ~count ~dk_len = - if Cstruct.len salt <> 8 then invalid_arg "salt should be 8 bytes" - else if count <= 0 then invalid_arg "count must be a positive integer" - else if dk_len <= 0 then invalid_arg "derived key length must be a positive integer" - else if dk_len > H.digest_size then invalid_arg "derived key too long" - else - let rec loop t = function - 0 -> t - | i -> loop (H.digest t) (i - 1) - in - Cstruct.sub (loop (Cstruct.append password salt) count) 0 dk_len - +module Make (H: Hacl.Hash.S) : S = struct let pbkdf2 ~password ~salt ~count ~dk_len = - if count <= 0 then invalid_arg "count must be a positive integer" - else if dk_len <= 0l then invalid_arg "derived key length must be a positive integer" - else - let h_len = H.digest_size - and dk_len = Int32.to_int dk_len in - let l = cdiv dk_len h_len in - let r = dk_len - (l - 1) * h_len in - let block i = - let rec f u xor = function - 0 -> xor - | j -> let u = H.hmac ~key:password u in - f u (Cs.xor xor u) (j - 1) - in - let int_i = Cstruct.create 4 in - Cstruct.BE.set_uint32 int_i 0 (Int32.of_int i); - let u_1 = H.hmac ~key:password (Cstruct.append salt int_i) in - f u_1 u_1 (count - 1) + if count <= 0 then invalid_arg "count must be a positive integer" ; + if dk_len <= 0l then invalid_arg "derived key length must be a positive integer" ; + let h_len = H.bytes + and dk_len = Int32.to_int dk_len in + let l = cdiv dk_len h_len in + let r = dk_len - (l - 1) * h_len in + let block i = + let rec f u xor = function + 0 -> xor + | j -> let u = H.HMAC.digest ~key:password ~msg:u in + f u (xorbuf xor u) (j - 1) in - let rec loop blocks = function - 0 -> blocks - | i -> loop ((block i)::blocks) (i - 1) - in - Cstruct.concat (loop [Cstruct.sub (block l) 0 r] (l - 1)) + let int_i = Bigstring.create 4 in + EndianBigstring.BigEndian.set_int32 int_i 0 (Int32.of_int i); + let u_1 = H.HMAC.digest ~key:password ~msg:(Bigstring.concat "" [salt; int_i]) in + f u_1 u_1 (count - 1) + in + let rec loop blocks = function + 0 -> blocks + | i -> loop ((block i)::blocks) (i - 1) + in + Bigstring.concat "" (loop [Bigstring.sub (block l) 0 r] (l - 1)) end -let pbkdf1 ~hash ~password ~salt ~count ~dk_len = - let module H = (val (Hash.module_of hash)) in - let module PBKDF = Make (H) in - PBKDF.pbkdf1 ~password ~salt ~count ~dk_len - -let pbkdf2 ~prf ~password ~salt ~count ~dk_len = - let module H = (val (Hash.module_of prf)) in - let module PBKDF = Make (H) in - PBKDF.pbkdf2 ~password ~salt ~count ~dk_len +module SHA256 = Make(Hacl.Hash.SHA256) +module SHA512 = Make(Hacl.Hash.SHA512) diff --git a/vendors/ocaml-pbkdf/src/pbkdf.mli b/vendors/ocaml-pbkdf/src/pbkdf.mli index c06680985..5e3f057d3 100644 --- a/vendors/ocaml-pbkdf/src/pbkdf.mli +++ b/vendors/ocaml-pbkdf/src/pbkdf.mli @@ -2,22 +2,13 @@ key derivation functions (PBKDF1 and PBKDF2), which are abstracted over a specific hash/pseudorandom function. *) module type S = sig - (** [pbkdf1 password salt count dk_len] is [dk], the derived key of [dk_len] octets. - The [salt] must be eight octets, [count] the iteration count. - @raise Invalid_argument when either [salt] is not eight octets long or either - [count] or [dk_len] are not valid. *) - val pbkdf1 : password:Cstruct.t -> salt:Cstruct.t -> count:int -> dk_len:int -> Cstruct.t - (** [pbkdf2 password salt count dk_len] is [dk], the derived key of [dk_len] octets. @raise Invalid_argument when either [count] or [dk_len] are not valid *) - val pbkdf2 : password:Cstruct.t -> salt:Cstruct.t -> count:int -> dk_len:int32 -> Cstruct.t + val pbkdf2 : password:Bigstring.t -> salt:Bigstring.t -> count:int -> dk_len:int32 -> Bigstring.t end (** Given a Hash/pseudorandom function, get the PBKDF *) -module Make (H: Nocrypto.Hash.S) : S +module Make (H: Hacl.Hash.S) : S -(** convenience [pbkdf1 hash password salt count dk_len] where the [hash] has to be provided explicitly *) -val pbkdf1 : hash:[`MD5 | `SHA1] -> password:Cstruct.t -> salt:Cstruct.t -> count:int -> dk_len:int -> Cstruct.t - -(** convenience [pbkdf2 prf password salt count dk_len] where the [prf] has to be provided explicitly *) -val pbkdf2 : prf:Nocrypto.Hash.hash -> password:Cstruct.t -> salt:Cstruct.t -> count:int -> dk_len:int32 -> Cstruct.t +module SHA256 : S +module SHA512 : S diff --git a/vendors/ocaml-pbkdf/test/pbkdf_tests.ml b/vendors/ocaml-pbkdf/test/pbkdf_tests.ml index 65e38aa09..3b3a1d9a2 100644 --- a/vendors/ocaml-pbkdf/test/pbkdf_tests.ml +++ b/vendors/ocaml-pbkdf/test/pbkdf_tests.ml @@ -1,300 +1,50 @@ -(* PBKDF1 *) -let test_pbkdf1 ~hash ~password ~salt ~count ~dk_len ~dk = - let open Nocrypto.Uncommon.Cs in - let salt = of_hex salt - and dk = of_hex dk - and password = Cstruct.of_string password in - (fun () -> - let edk = Pbkdf.pbkdf1 ~hash ~password ~salt ~count ~dk_len in - let sedk = Cstruct.to_string edk - and sdk = Cstruct.to_string dk - in - Alcotest.check Alcotest.string "PBKDF1 test" sedk sdk) - -let test_pbkdf1_invalid_arg ~hash ~password ~salt ~count ~dk_len ~msg = - let open Nocrypto.Uncommon.Cs in - let salt = of_hex salt - and password = Cstruct.of_string password in - (fun () -> - Alcotest.check_raises - msg - (Invalid_argument msg) - (fun () -> ignore (Pbkdf.pbkdf1 ~hash ~password ~salt ~count ~dk_len))) - -(* Taken from http://www.di-mgt.com.au/cryptoKDFs.html *) -let pbkdf1_test1 = - test_pbkdf1 - ~hash:`SHA1 - ~password:"password" - ~salt:"78578e5a5d63cb06" - ~count:1000 - ~dk_len:16 - ~dk:"dc19847e05c64d2faf10ebfb4a3d2a20" - -let pbkdf1_test2 = - test_pbkdf1_invalid_arg - ~hash:`SHA1 - ~password:"password" - ~salt:"78578e5a5d63cb" - ~count:1000 - ~dk_len:16 - ~msg:"salt should be 8 bytes" - -let pbkdf1_test3 = - test_pbkdf1_invalid_arg - ~hash:`SHA1 - ~password:"password" - ~salt:"78578e5a5d63cb0600" - ~count:1000 - ~dk_len:16 - ~msg:"salt should be 8 bytes" - -let pbkdf1_test4 = - test_pbkdf1_invalid_arg - ~hash:`SHA1 - ~password:"password" - ~salt:"78578e5a5d63cb06" - ~count:(-1) - ~dk_len:16 - ~msg:"count must be a positive integer" - -let pbkdf1_test5 = - test_pbkdf1_invalid_arg - ~hash:`SHA1 - ~password:"password" - ~salt:"78578e5a5d63cb06" - ~count:0 - ~dk_len:16 - ~msg:"count must be a positive integer" - -let pbkdf1_test6 = - test_pbkdf1_invalid_arg - ~hash:`SHA1 - ~password:"password" - ~salt:"78578e5a5d63cb06" - ~count:1000 - ~dk_len:24 - ~msg:"derived key too long" - -let pbkdf1_test7 = - test_pbkdf1_invalid_arg - ~hash:`SHA1 - ~password:"password" - ~salt:"78578e5a5d63cb06" - ~count:1000 - ~dk_len:0 - ~msg:"derived key length must be a positive integer" - -let pbkdf1_tests = [ - "Test Case 1", `Quick, pbkdf1_test1; - "Test Case 2", `Quick, pbkdf1_test2; - "Test Case 3", `Quick, pbkdf1_test3; - "Test Case 4", `Quick, pbkdf1_test4; - "Test Case 5", `Quick, pbkdf1_test5; - "Test Case 6", `Quick, pbkdf1_test6; - "Test Case 7", `Quick, pbkdf1_test7; -] - - (* PBKDF2 *) -let test_pbkdf2 ~prf ~password ~salt ~count ~dk_len ~dk = - let open Nocrypto.Uncommon.Cs in - let salt = of_hex salt - and dk = of_hex dk - and password = Cstruct.of_string password - in +let test_pbkdf2 (module A : Hacl.Hash.S) ~password ~salt ~count ~dk_len ~dk = + let module P = Pbkdf.Make(A) in + let salt = Cstruct.to_bigarray (Hex.to_cstruct (`Hex salt)) in + let dk = Cstruct.to_bigarray (Hex.to_cstruct (`Hex dk)) in + let password = Bigstring.of_string password in (fun () -> - let edk = Pbkdf.pbkdf2 ~prf ~password ~salt ~count ~dk_len in - let sedk = Cstruct.to_string edk - and sdk = Cstruct.to_string dk - in + let edk = P.pbkdf2 ~password ~salt ~count ~dk_len in + let sedk = Bigstring.to_string edk in + let sdk = Bigstring.to_string dk in Alcotest.check Alcotest.string "PBKDF2 test" sedk sdk) -let test_pbkdf2_invalid_arg ~prf ~password ~salt ~count ~dk_len ~msg () = - let salt = Nocrypto.Uncommon.Cs.of_hex salt - and password = Cstruct.of_string password - in - Alcotest.check_raises - msg - (Invalid_argument msg) - (fun () -> ignore (Pbkdf.pbkdf2 ~prf ~password ~salt ~count ~dk_len)) +(* let test_pbkdf2_invalid_arg ~prf ~password ~salt ~count ~dk_len ~msg () = + * let salt = Nocrypto.Uncommon.Cs.of_hex salt + * and password = Cstruct.of_string password + * in + * Alcotest.check_raises + * msg + * (Invalid_argument msg) + * (fun () -> ignore (Pbkdf.pbkdf2 ~prf ~password ~salt ~count ~dk_len)) *) (* Taken from https://github.com/randombit/botan/blob/master/src/tests/data/pbkdf/pbkdf2.vec *) -let pbkdf2_test1 = - test_pbkdf2 - ~prf:`SHA1 - ~password:"" - ~salt:"0001020304050607" - ~count:10000 - ~dk_len:32l - ~dk:"59b2b1143b4cb1059ec58d9722fb1c72471e0d85c6f7543ba5228526375b0127" - -let pbkdf2_test2 = - test_pbkdf2 - ~prf:`SHA1 - ~password:"jyueqgxrscgglpxdykcf" - ~salt:"9b56e55328a4c97a250738f8dba1b992e8a1b508" - ~count:10000 - ~dk_len:14l - ~dk:"df6d9d72872404bf73e708cf3b7d" - -let pbkdf2_test3 = - test_pbkdf2 - ~prf:`SHA1 - ~password:"aqrqsznzvvzgtksammgo" - ~salt:"57487813cdd2220dfc485d932a2979ee8769ea8b" - ~count:101 - ~dk_len:40l - ~dk:"fa13f40af1ade2a30f2fffd66fc8a659ef95e6388c1682fc0fe4d15a70109517a32942e39c371440" - -let pbkdf2_test4 = - test_pbkdf2 - ~prf:`SHA1 - ~password:"ltexmfeyylmlbrsyikaw" - ~salt:"ed1f39a0a7f3889aaf7e60743b3bc1cc2c738e60" - ~count:1000 - ~dk_len:10l - ~dk:"027afadd48f4be8dcc4f" - -let pbkdf2_test5 = - test_pbkdf2 - ~prf:`SHA1 - ~password:"cxgnyrcgrvllylolsjpo" - ~salt:"94ac88200743fb0f6ac51be62166cbef08d94c15" - ~count:1 - ~dk_len:32l - ~dk:"7c0d009fc91b48cb6d19bafbfccff3e2ccabfe725eaa234e56bde1d551c132f2" - -let pbkdf2_test6 = - test_pbkdf2 - ~prf:`SHA1 - ~password:"xqyfhrxehiedlhewnvbj" - ~salt:"24a1a50b17d63ee8394b69fc70887f4f94883d68" - ~count:5 - ~dk_len:32l - ~dk:"4661301d3517ca4443a6a607b32b2a63f69996299df75db75f1e0b98dd0eb7d8" - -let pbkdf2_test7 = - test_pbkdf2 - ~prf:`SHA1 - ~password:"andaqkpjwabvcfnpnjkl" - ~salt:"9316c80801623cc2734af74bec42cf4dbaa3f6d5" - ~count:100 - ~dk_len:30l - ~dk:"82fb44a521448d5aac94b5158ead1e4dcd7363081a747b9f7626752bda2d" - -let pbkdf2_test8 = - test_pbkdf2 - ~prf:`SHA1 - ~password:"hsavvyvocloyuztlsniu" - ~salt:"612cc61df3cf2bdb36e10c4d8c9d73192bddee05" - ~count:100 - ~dk_len:30l - ~dk:"f8ec2b0ac817896ac8189d787c6424ed24a6d881436687a4629802c0ecce" - -let pbkdf2_test9 = - test_pbkdf2 - ~prf:`SHA1 - ~password:"eaimrbzpcopbusaqtkmw" - ~salt:"45248f9d0cebcb86a18243e76c972a1f3b36772a" - ~count:100 - ~dk_len:34l - ~dk:"c9a0b2622f13916036e29e7462e206e8ba5b50ce9212752eb8ea2a4aa7b40a4cc1bf" - -let pbkdf2_test10 = - test_pbkdf2 - ~prf:`SHA1 - ~password:"gwrxpqxumsdsmbmhfhmfdcvlcvngzkig" - ~salt:"a39b76c6eec8374a11493ad08c246a3e40dfae5064f4ee3489c273646178" - ~count:1000 - ~dk_len:64l - ~dk:"4c9db7ba24955225d5b845f65ef24ef1b0c6e86f2e39c8ddaa4b8abd26082d1f350381fadeaeb560dc447afc68a6b47e6ea1e7412f6cf7b2d82342fccd11d3b4" let pbkdf2_test11 = test_pbkdf2 - ~prf:`SHA256 + (module Hacl.Hash.SHA256) ~password:"xyz" ~salt:"0001020304050607" ~count: 10000 ~dk_len:48l ~dk:"defd2987fa26a4672f4d16d98398432ad95e896bf619f6a6b8d4ed1faf98e8b531b39ffb66966d0e115a6cd8e70b72d0" -let pbkdf2_test12 = - test_pbkdf2 - ~prf:`SHA384 - ~password:"xyz" - ~salt:"0001020304050607" - ~count:10000 - ~dk_len:48l - ~dk:"47a3ae920b24edaa2bb53155808554b13fab58df62b81f043d9812e9f2881164df20bbffa54e5ee2489fa183b6718a74" - let pbkdf2_test13 = test_pbkdf2 - ~prf:`SHA512 + (module Hacl.Hash.SHA512) ~password:"xyz" ~salt:"0001020304050607" ~count:10000 ~dk_len:48l ~dk:"daf8a734327745eb63d19054dbd4018a682cef11086a1bfb63fdbc16158c2f8b0742802f36aef1b1df92accbea5d31a5" -let pbkdf2_test14 = - test_pbkdf2_invalid_arg - ~prf:`SHA1 - ~password:"password" - ~salt:"0001020304050607" - ~count:(-1) - ~dk_len:48l - ~msg:"count must be a positive integer" - -let pbkdf2_test15 = - test_pbkdf2_invalid_arg - ~prf:`SHA1 - ~password:"password" - ~salt:"0001020304050607" - ~count:0 - ~dk_len:48l - ~msg:"count must be a positive integer" - -let pbkdf2_test16 = - test_pbkdf2_invalid_arg - ~prf:`SHA1 - ~password:"password" - ~salt:"0001020304050607" - ~count:1000 - ~dk_len:(-1l) - ~msg:"derived key length must be a positive integer" - -let pbkdf2_test17 = - test_pbkdf2_invalid_arg - ~prf:`SHA1 - ~password:"password" - ~salt:"0001020304050607" - ~count:1000 - ~dk_len:0l - ~msg:"derived key length must be a positive integer" - let pbkdf2_tests = [ - "Test Case 1", `Quick, pbkdf2_test1; - "Test Case 2", `Quick, pbkdf2_test2; - "Test Case 3", `Quick, pbkdf2_test3; - "Test Case 4", `Quick, pbkdf2_test4; - "Test Case 5", `Quick, pbkdf2_test5; - "Test Case 6", `Quick, pbkdf2_test6; - "Test Case 7", `Quick, pbkdf2_test7; - "Test Case 8", `Quick, pbkdf2_test8; - "Test Case 9", `Quick, pbkdf2_test9; - "Test Case 10", `Quick, pbkdf2_test10; "Test Case 11", `Quick, pbkdf2_test11; - "Test Case 12", `Quick, pbkdf2_test12; "Test Case 13", `Quick, pbkdf2_test13; - "Test Case 14", `Quick, pbkdf2_test14; - "Test Case 15", `Quick, pbkdf2_test15; - "Test Case 16", `Quick, pbkdf2_test16; - "Test Case 17", `Quick, pbkdf2_test17; ] let () = Alcotest.run "PBKDF Tests" [ - "PBKDF1 tests", pbkdf1_tests; "PBKDF2 tests", pbkdf2_tests; ]