From 928ee9d3a03b3aa2c9a37ef558884526b4de2adc Mon Sep 17 00:00:00 2001 From: Vincent Bernardoff Date: Mon, 2 Jul 2018 10:43:28 +0200 Subject: [PATCH] Hacl: add HMAC_SHA512 --- vendors/ocaml-hacl/src/hacl.ml | 82 ++++++++++++++++++++++++--------- vendors/ocaml-hacl/src/hacl.mli | 13 +++++- vendors/ocaml-hacl/test/test.ml | 17 ++++++- 3 files changed, 86 insertions(+), 26 deletions(-) diff --git a/vendors/ocaml-hacl/src/hacl.ml b/vendors/ocaml-hacl/src/hacl.ml index 22a7a557d..61f2a789f 100644 --- a/vendors/ocaml-hacl/src/hacl.ml +++ b/vendors/ocaml-hacl/src/hacl.ml @@ -117,41 +117,77 @@ module Hash = struct Bigstring.t -> Bigstring.t -> Bigstring.t -> unit = "ml_Hacl_HMAC_SHA2_256_hmac" [@@noalloc] - let write_hmac ~key ~msg buf = - if Bigstring.length buf < 32 then - invalid_arg (Printf.sprintf "Hash.write_hmac_sha156: invalid len \ - %d" 32) ; + let write ~key ~msg buf = + let buflen = Bigstring.length buf in + if buflen < 32 then + invalid_arg (Printf.sprintf "Hash.SHA256.HMAC.write: invalid \ + len (%d), expected %d" buflen bytes) ; hmac buf key msg - let hmac ~key ~msg = + let digest ~key ~msg = let buf = Bigstring.create 32 in - write_hmac ~key ~msg buf ; + write ~key ~msg buf ; buf end end - module SHA512 = Make(struct - (* state -> unit *) - external init : Bigstring.t -> unit = - "ml_Hacl_SHA2_512_init" [@@noalloc] + module SHA512 = struct + module H = Make(struct + (* state -> unit *) + external init : Bigstring.t -> unit = + "ml_Hacl_SHA2_512_init" [@@noalloc] - (* state -> data -> unit *) - external update : Bigstring.t -> Bigstring.t -> unit = - "ml_Hacl_SHA2_512_update" [@@noalloc] + (* state -> data -> unit *) + external update : Bigstring.t -> Bigstring.t -> unit = + "ml_Hacl_SHA2_512_update" [@@noalloc] - (* state -> data -> datalen -> unit *) - external update_last : Bigstring.t -> Bigstring.t -> int -> unit = - "ml_Hacl_SHA2_512_update_last" [@@noalloc] + (* state -> data -> datalen -> unit *) + external update_last : Bigstring.t -> Bigstring.t -> int -> unit = + "ml_Hacl_SHA2_512_update_last" [@@noalloc] - (* state -> hash *) - external finish : Bigstring.t -> Bigstring.t -> unit = - "ml_Hacl_SHA2_512_finish" [@@noalloc] + (* state -> hash *) + external finish : Bigstring.t -> Bigstring.t -> unit = + "ml_Hacl_SHA2_512_finish" [@@noalloc] - let bytes = 64 - let blockbytes = 128 - let statebytes = 169 * 8 - end) + let bytes = 64 + let blockbytes = 128 + let statebytes = 169 * 8 + end) + include H + module HMAC = struct + let derive_key k = + let buf = Bigstring.create blockbytes in + Bigstring.fill buf '\x00' ; + let keylen = Bigstring.length k in + let k, keylen = + if keylen > blockbytes then H.digest k, bytes else k, keylen in + Bigstring.blit k 0 buf 0 keylen ; + buf + + let xor_ipad = + Bigstring.map ~f:(fun c -> Char.(chr ((code c) lxor 0x36))) + let xor_opad = + Bigstring.map ~f:(fun c -> Char.(chr ((code c) lxor 0x5c))) + + let digest ~key ~msg = + let key = derive_key key in + let preimage = + Bigstring.concat "" [ + xor_opad key ; + digest (Bigstring.concat "" [xor_ipad key ; msg]) + ] in + digest preimage + + let write ~key ~msg buf = + let buflen = Bigstring.length buf in + if buflen < bytes then + invalid_arg (Printf.sprintf "Hash.SHA512.HMAC.write: invalid \ + len (%d), expected %d" buflen bytes) ; + let d = digest ~key ~msg in + Bigstring.blit d 0 buf 0 bytes + end + end end module Nonce = struct diff --git a/vendors/ocaml-hacl/src/hacl.mli b/vendors/ocaml-hacl/src/hacl.mli index ca9fba02b..7559c3013 100644 --- a/vendors/ocaml-hacl/src/hacl.mli +++ b/vendors/ocaml-hacl/src/hacl.mli @@ -46,11 +46,11 @@ module Hash : sig val digest : Bigstring.t -> Bigstring.t module HMAC : sig - val write_hmac : + val write : key:Bigstring.t -> msg:Bigstring.t -> Bigstring.t -> unit (** @raise [Invalid_argument] if argument is less than 32 bytes long *) - val hmac : + val digest : key:Bigstring.t -> msg:Bigstring.t -> Bigstring.t end end @@ -71,6 +71,15 @@ module Hash : sig (** Direct Interface *) val digest : Bigstring.t -> Bigstring.t + + module HMAC : sig + val write : + key:Bigstring.t -> msg:Bigstring.t -> Bigstring.t -> unit + (** @raise [Invalid_argument] if argument is less than 32 bytes long *) + + val digest : + key:Bigstring.t -> msg:Bigstring.t -> Bigstring.t + end end end diff --git a/vendors/ocaml-hacl/test/test.ml b/vendors/ocaml-hacl/test/test.ml index 693cf882c..e60f860bb 100644 --- a/vendors/ocaml-hacl/test/test.ml +++ b/vendors/ocaml-hacl/test/test.ml @@ -84,11 +84,26 @@ let hmac_sha256 () = let key = Bigstring.of_string "key" in let msg = Bigstring.of_string "The quick brown fox jumps over the lazy dog" in let resp = of_hex "f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8" in - let digest = Hash.HMAC_SHA256.hmac ~key ~msg in + let digest = Hash.SHA256.HMAC.digest ~key ~msg in Alcotest.(check bigstring "hmac_sha256" resp digest) +let hmac_sha512 () = + let vectors = [ + Bigstring.of_string "key", + Bigstring.of_string "The quick brown fox jumps over the lazy dog", + of_hex "b42af09057bac1e2d41708e48a902e09b5ff7f12ab428a4fe86653c73dd248fb82f948a549f7b791a5b41915ee4d1ec3935357e4e2317250d0372afa2ebeeb3a" ; + Bigstring.empty, + Bigstring.empty, + of_hex "b936cee86c9f87aa5d3c6f2e84cb5a4239a5fe50480a6ec66b70ab5b1f4ac6730c6c515421b327ec1d69402e53dfb49ad7381eb067b338fd7b0cb22247225d47" ; + ] in + List.iter begin fun (key, msg, resp) -> + let digest = Hash.SHA512.HMAC.digest ~key ~msg in + Alcotest.(check bigstring "hmac_sha512" resp digest) + end vectors + let hash = [ "hmac_sha256", `Quick, hmac_sha256 ; + "hmac_sha512", `Quick, hmac_sha512 ; "sha256", `Quick, sha256 ; "sha256_seq", `Quick, sha256_seq ;