diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 00b232619..f35b473e9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -231,157 +231,167 @@ opam:04:tezos-error-monad: variables: package: tezos-error-monad -opam:05:tezos-rpc: +opam:05:blake2: + <<: *opam_definition + variables: + package: blake2 + +opam:06:tezos-rpc: <<: *opam_definition variables: package: tezos-rpc -opam:06:tezos-stdlib-lwt: +opam:07:tezos-stdlib-lwt: <<: *opam_definition variables: package: tezos-stdlib-lwt -opam:07:tezos-crypto: +opam:08:tweetnacl: + <<: *opam_definition + variables: + package: tweetnacl + +opam:09:tezos-crypto: <<: *opam_definition variables: package: tezos-crypto -opam:08:tezos-micheline: +opam:10:tezos-micheline: <<: *opam_definition variables: package: tezos-micheline -opam:09:ocplib-resto-cohttp: +opam:11:ocplib-resto-cohttp: <<: *opam_definition variables: package: ocplib-resto-cohttp -opam:10:tezos-base: +opam:12:tezos-base: <<: *opam_definition variables: package: tezos-base -opam:11:irmin-leveldb: +opam:13:irmin-leveldb: <<: *opam_definition variables: package: irmin-leveldb -opam:12:tezos-protocol-environment-sigs: +opam:14:tezos-protocol-environment-sigs: <<: *opam_definition variables: package: tezos-protocol-environment-sigs -opam:13:tezos-rpc-http: +opam:15:tezos-rpc-http: <<: *opam_definition variables: package: tezos-rpc-http -opam:14:tezos-shell-services: +opam:16:tezos-shell-services: <<: *opam_definition variables: package: tezos-shell-services -opam:15:tezos-storage: +opam:17:tezos-storage: <<: *opam_definition variables: package: tezos-storage -opam:16:tezos-protocol-compiler: +opam:18:tezos-protocol-compiler: <<: *opam_definition variables: package: tezos-protocol-compiler -opam:17:tezos-client-base: +opam:19:tezos-client-base: <<: *opam_definition variables: package: tezos-client-base -opam:18:tezos-protocol-alpha: +opam:20:tezos-protocol-alpha: <<: *opam_definition variables: package: tezos-protocol-alpha -opam:19:tezos-protocol-environment-client: +opam:21:tezos-protocol-environment-client: <<: *opam_definition variables: package: tezos-protocol-environment-client -opam:20:tezos-p2p: - <<: *opam_definition - variables: - package: tezos-p2p - -opam:21:tezos-protocol-updater: - <<: *opam_definition - variables: - package: tezos-protocol-updater - -opam:22:tezos-client-alpha: - <<: *opam_definition - variables: - package: tezos-client-alpha - -opam:23:tezos-protocol-genesis: +opam:22:tezos-protocol-genesis: <<: *opam_definition variables: package: tezos-protocol-genesis -opam:24:tezos-shell: +opam:23:tezos-protocol-updater: <<: *opam_definition variables: - package: tezos-shell + package: tezos-protocol-updater + +opam:24:tezos-p2p: + <<: *opam_definition + variables: + package: tezos-p2p opam:25:ocplib-resto-json: <<: *opam_definition variables: package: ocplib-resto-json -opam:26:tezos-client-genesis: +opam:26:tezos-client-alpha: + <<: *opam_definition + variables: + package: tezos-client-alpha + +opam:27:tezos-client-genesis: <<: *opam_definition variables: package: tezos-client-genesis -opam:27:tezos-embedded-protocol-alpha: +opam:28:tezos-embedded-protocol-alpha: <<: *opam_definition variables: package: tezos-embedded-protocol-alpha -opam:28:tezos-embedded-protocol-demo: +opam:29:tezos-embedded-protocol-demo: <<: *opam_definition variables: package: tezos-embedded-protocol-demo -opam:29:tezos-embedded-protocol-genesis: +opam:30:tezos-embedded-protocol-genesis: <<: *opam_definition variables: package: tezos-embedded-protocol-genesis -opam:30:ocplib-ezresto: +opam:31:tezos-shell: + <<: *opam_definition + variables: + package: tezos-shell + +opam:32:ocplib-ezresto: <<: *opam_definition variables: package: ocplib-ezresto -opam:31:tezos-client: +opam:33:tezos-client: <<: *opam_definition variables: package: tezos-client -opam:32:tezos-node: +opam:34:tezos-node: <<: *opam_definition variables: package: tezos-node -opam:33:tezos-test-helpers: +opam:35:tezos-test-helpers: <<: *opam_definition variables: package: tezos-test-helpers -opam:34:ocplib-ezresto-directory: +opam:36:ocplib-ezresto-directory: <<: *opam_definition variables: package: ocplib-ezresto-directory -opam:35:tezos-protocol-demo: +opam:37:tezos-protocol-demo: <<: *opam_definition variables: package: tezos-protocol-demo diff --git a/scripts/opam-pin.sh b/scripts/opam-pin.sh index 04d0a4873..695c7a1c5 100755 --- a/scripts/opam-pin.sh +++ b/scripts/opam-pin.sh @@ -10,12 +10,12 @@ export OPAMYES=yes ### Temporary HACK ## Should be in sync with `opam-unpin.sh` -opam pin add --no-action --dev-repo sodium opam pin add --no-action --dev-repo ocplib-json-typed ## Unpin package we used to pin... opam pin remove --no-action ocp-ocamlres opam pin remove --no-action ocplib-resto +opam pin remove --no-action sodium ### End of temporary HACK diff --git a/src/bin_attacker/attacker_minimal.ml b/src/bin_attacker/attacker_minimal.ml index d043b3c98..23f539a67 100644 --- a/src/bin_attacker/attacker_minimal.ml +++ b/src/bin_attacker/attacker_minimal.ml @@ -39,11 +39,11 @@ let block_forged ?prev ops = operations = ops } in let open Proto in let generate_proof_of_work_nonce () = - Sodium.Random.Bigbytes.generate + Rand.generate Proto.Tezos_context.Constants.proof_of_work_nonce_size in let generate_seed_nonce () = match Proto.Nonce_storage.of_bytes @@ - Sodium.Random.Bigbytes.generate + Rand.generate Proto.Tezos_context.Constants.nonce_length with | Error _ -> assert false | Ok nonce -> nonce in diff --git a/src/bin_client/main_lib.ml b/src/bin_client/main_lib.ml index bdd18f22b..b9fd088c8 100644 --- a/src/bin_client/main_lib.ml +++ b/src/bin_client/main_lib.ml @@ -44,7 +44,6 @@ let get_commands_for_version ctxt block protocol = (* Main (lwt) entry *) let main ?only_commands () = Random.self_init () ; - Sodium.Random.stir () ; Lwt.catch begin fun () -> let original_args = List.tl (Array.to_list Sys.argv) in begin diff --git a/src/lib_crypto/blake2B.ml b/src/lib_crypto/blake2B.ml index 7d0dd708d..a79943708 100644 --- a/src/lib_crypto/blake2B.ml +++ b/src/lib_crypto/blake2B.ml @@ -7,17 +7,6 @@ (* *) (**************************************************************************) -let () = - let expected_primitive = "blake2b" - and primitive = Sodium.Generichash.primitive in - if primitive <> expected_primitive then begin - Printf.eprintf - "FATAL ERROR: \ - invalid value for Sodium.Generichash.primitive: %S (expected %S)@." - primitive expected_primitive ; - exit 1 - end - (*-- Type specific Hash builder ---------------------------------------------*) module type Name = sig @@ -32,8 +21,8 @@ module type PrefixedName = sig end module Make_minimal (K : Name) = struct - - type t = Sodium.Generichash.hash + open Blake2 + type t = Blake2b.hash include K @@ -46,7 +35,7 @@ module Make_minimal (K : Name) = struct if String.length s <> size then None else - Some (Sodium.Generichash.Bytes.to_hash (Bytes.of_string s)) + Some (Blake2b.Hash (Cstruct.of_string s)) let of_string_exn s = match of_string s with | None -> @@ -55,7 +44,7 @@ module Make_minimal (K : Name) = struct K.name (String.length s) in raise (Invalid_argument msg) | Some h -> h - let to_string s = Bytes.to_string (Sodium.Generichash.Bytes.of_hash s) + let to_string (Blake2b.Hash h) = Cstruct.to_string h let of_hex s = of_string (Hex.to_string (`Hex s)) let of_hex_exn s = of_string_exn (Hex.to_string (`Hex s)) @@ -63,14 +52,14 @@ module Make_minimal (K : Name) = struct let `Hex s = Hex.of_string (to_string s) in s - let compare = Sodium.Generichash.compare + let compare (Blake2b.Hash h1) (Blake2b.Hash h2) = Cstruct.compare h1 h2 let equal x y = compare x y = 0 let of_bytes b = if MBytes.length b <> size then None else - Some (Sodium.Generichash.Bigbytes.to_hash b) + Some (Blake2b.Hash (Cstruct.of_bigarray b)) let of_bytes_exn b = match of_bytes b with | None -> @@ -79,24 +68,20 @@ module Make_minimal (K : Name) = struct K.name (MBytes.length b) in raise (Invalid_argument msg) | Some h -> h - let to_bytes = Sodium.Generichash.Bigbytes.of_hash + let to_bytes (Blake2b.Hash h) = Cstruct.to_bigarray h let read src off = of_bytes_exn @@ MBytes.sub src off size let write dst off h = MBytes.blit (to_bytes h) 0 dst off size let hash_bytes l = - let open Sodium.Generichash in - let state = init ~size () in - List.iter (Bigbytes.update state) l ; - final state + let state = Blake2b.init size in + List.iter (fun b -> Blake2b.update state (Cstruct.of_bigarray b)) l ; + Blake2b.final state let hash_string l = - let open Sodium.Generichash in - let state = init ~size () in - List.iter - (fun s -> Bytes.update state (BytesLabels.unsafe_of_string s)) - l ; - final state + let state = Blake2b.init size in + List.iter (fun s -> Blake2b.update state (Cstruct.of_string s)) l ; + Blake2b.final state let path_length = 6 let to_path key l = @@ -125,11 +110,7 @@ module Make_minimal (K : Name) = struct module Table = struct include Hashtbl.Make(struct type nonrec t = t - let hash s = - Int64.to_int - (EndianString.BigEndian.get_int64 - (Bytes.unsafe_to_string (Sodium.Generichash.Bytes.of_hash s)) - 0) + let hash (Blake2b.Hash h) = Int64.to_int (Cstruct.BE.get_uint64 h 0) let equal = equal end) end diff --git a/src/lib_crypto/crypto_box.ml b/src/lib_crypto/crypto_box.ml index 7af8f81e3..d1ddd2257 100644 --- a/src/lib_crypto/crypto_box.ml +++ b/src/lib_crypto/crypto_box.ml @@ -9,10 +9,12 @@ (** Tezos - X25519/XSalsa20-Poly1305 cryptography *) -type secret_key = Sodium.Box.secret_key -type public_key = Sodium.Box.public_key -type channel_key = Sodium.Box.channel_key -type nonce = Sodium.Box.nonce +open Tweetnacl + +type secret_key = Box.secret Box.key +type public_key = Box.public Box.key +type channel_key = Box.combined Box.key +type nonce = Nonce.t type target = Z.t module Public_key_hash = Blake2B.Make (Base58) (struct @@ -26,23 +28,50 @@ let () = Base58.check_encoded_prefix Public_key_hash.b58check_encoding "id" 30 let hash pk = - Public_key_hash.hash_bytes [Sodium.Box.Bigbytes.of_public_key pk] + Public_key_hash.hash_bytes [Cstruct.to_bigarray (Box.to_cstruct pk)] + +let zerobytes = Box.zerobytes +let boxzerobytes = Box.boxzerobytes let random_keypair () = - let sk, pk = Sodium.Box.random_keypair () in + let pk, sk = Box.keypair () in sk, pk, hash pk -let random_nonce = Sodium.Box.random_nonce -let increment_nonce = Sodium.Box.increment_nonce -let box = Sodium.Box.Bigbytes.box -let box_open sk pk msg nonce = - try Some (Sodium.Box.Bigbytes.box_open sk pk msg nonce) with - | Sodium.Verification_failure -> None +let random_nonce = Nonce.gen +let increment_nonce = Nonce.increment -let precompute = Sodium.Box.precompute -let fast_box = Sodium.Box.Bigbytes.fast_box -let fast_box_open ck msg nonce = - try Some (Sodium.Box.Bigbytes.fast_box_open ck msg nonce) with - | Sodium.Verification_failure -> None +let box sk pk msg nonce = + let msg = Cstruct.of_bigarray msg in + Cstruct.to_bigarray (Box.box ~sk ~pk ~msg ~nonce) + +let box_open sk pk cmsg nonce = + let cmsg = Cstruct.of_bigarray cmsg in + Option.map ~f:Cstruct.to_bigarray (Box.box_open ~sk ~pk ~cmsg ~nonce) + +let box_noalloc sk pk nonce msg = + let msg = Cstruct.of_bigarray msg in + Box.box_noalloc ~sk ~pk ~nonce ~msg + +let box_open_noalloc sk pk nonce cmsg = + let cmsg = Cstruct.of_bigarray cmsg in + Box.box_open_noalloc ~sk ~pk ~nonce ~cmsg + +let precompute sk pk = Box.combine pk sk + +let fast_box k msg nonce = + let msg = Cstruct.of_bigarray msg in + Cstruct.to_bigarray (Box.box_combined ~k ~msg ~nonce) + +let fast_box_open k cmsg nonce = + let cmsg = Cstruct.of_bigarray cmsg in + Option.map ~f:Cstruct.to_bigarray (Box.box_open_combined ~k ~cmsg ~nonce) + +let fast_box_noalloc k nonce msg = + let msg = Cstruct.of_bigarray msg in + Box.box_combined_noalloc ~k ~nonce ~msg + +let fast_box_open_noalloc k nonce cmsg = + let cmsg = Cstruct.of_bigarray cmsg in + Box.box_open_combined_noalloc ~k ~nonce ~cmsg let compare_target hash target = let hash = Z.of_bits (Blake2B.to_string hash) in @@ -71,8 +100,8 @@ let default_target = make_target 24. let check_proof_of_work pk nonce target = let hash = Blake2B.hash_bytes [ - Sodium.Box.Bigbytes.of_public_key pk ; - Sodium.Box.Bigbytes.of_nonce nonce ; + Cstruct.to_bigarray (Box.to_cstruct pk) ; + Cstruct.to_bigarray (Nonce.to_cstruct nonce) ; ] in compare_target hash target @@ -86,26 +115,31 @@ let generate_proof_of_work ?max pk target = if check_proof_of_work pk nonce target then nonce else - loop (increment_nonce nonce) (cpt + 1) in + loop (Nonce.increment nonce) (cpt + 1) in loop (random_nonce ()) 0 +let to_bigarray : type a. a Box.key -> MBytes.t = fun k -> + Cstruct.to_bigarray (Box.to_cstruct k) + +let of_bigarray f s = f (Cstruct.of_bigarray s) + let public_key_encoding = let open Data_encoding in conv - Sodium.Box.Bigbytes.of_public_key - Sodium.Box.Bigbytes.to_public_key - (Fixed.bytes Sodium.Box.public_key_size) + to_bigarray + (of_bigarray Box.pk_of_cstruct_exn) + (Fixed.bytes Box.pkbytes) let secret_key_encoding = let open Data_encoding in conv - Sodium.Box.Bigbytes.of_secret_key - Sodium.Box.Bigbytes.to_secret_key - (Fixed.bytes Sodium.Box.secret_key_size) + to_bigarray + (of_bigarray Box.sk_of_cstruct_exn) + (Fixed.bytes Box.skbytes) let nonce_encoding = let open Data_encoding in conv - Sodium.Box.Bigbytes.of_nonce - Sodium.Box.Bigbytes.to_nonce - (Fixed.bytes Sodium.Box.nonce_size) + (fun nonce -> Cstruct.to_bigarray (Nonce.to_cstruct nonce)) + (of_bigarray Nonce.of_cstruct_exn) + (Fixed.bytes Nonce.bytes) diff --git a/src/lib_crypto/crypto_box.mli b/src/lib_crypto/crypto_box.mli index 4ae9f557e..dd8a24944 100644 --- a/src/lib_crypto/crypto_box.mli +++ b/src/lib_crypto/crypto_box.mli @@ -28,15 +28,27 @@ val public_key_encoding : public_key Data_encoding.t val secret_key_encoding : secret_key Data_encoding.t val hash : public_key -> Public_key_hash.t + +val zerobytes : int +val boxzerobytes : int + val random_keypair : unit -> secret_key * public_key * Public_key_hash.t val box : secret_key -> public_key -> MBytes.t -> nonce -> MBytes.t val box_open : secret_key -> public_key -> MBytes.t -> nonce -> MBytes.t option +val box_noalloc : secret_key -> public_key -> nonce -> MBytes.t -> unit +val box_open_noalloc : secret_key -> public_key -> nonce -> MBytes.t -> bool + val precompute : secret_key -> public_key -> channel_key + val fast_box : channel_key -> MBytes.t -> nonce -> MBytes.t val fast_box_open : channel_key -> MBytes.t -> nonce -> MBytes.t option +val fast_box_noalloc : channel_key -> nonce -> MBytes.t -> unit +val fast_box_open_noalloc : channel_key -> nonce -> MBytes.t -> bool + val check_proof_of_work : public_key -> nonce -> target -> bool val generate_proof_of_work : ?max:int -> public_key -> target -> nonce + diff --git a/src/lib_crypto/ed25519.ml b/src/lib_crypto/ed25519.ml index d717f8cb6..b16f9926a 100644 --- a/src/lib_crypto/ed25519.ml +++ b/src/lib_crypto/ed25519.ml @@ -17,10 +17,18 @@ module Public_key_hash = Blake2B.Make(Base58)(struct let () = Base58.check_encoded_prefix Public_key_hash.b58check_encoding "tz1" 36 +open Tweetnacl + +let of_bigarray1 f x = + f (Cstruct.of_bigarray x) + +let to_bigarray1 f x = + Cstruct.to_bigarray (f x) + module Public_key = struct - type t = Sodium.Sign.public_key - let compare = Sodium.Sign.compare_public_keys + type t = Sign.public Sign.key + let compare a b = Cstruct.compare (Sign.to_cstruct a) (Sign.to_cstruct b) let (=) xs ys = compare xs ys = 0 let (<>) xs ys = compare xs ys <> 0 let (<) xs ys = compare xs ys < 0 @@ -33,16 +41,13 @@ module Public_key = struct type Base58.data += | Public_key of t - let to_string s = Bytes.to_string (Sodium.Sign.Bytes.of_public_key s) - let of_string_exn x = Sodium.Sign.Bytes.to_public_key (Bytes.of_string x) - let of_string x = - try Some (of_string_exn x) - with _ -> None + let to_string s = Cstruct.to_string (Sign.to_cstruct s) + let of_string s = Sign.pk_of_cstruct (Cstruct.of_string s) let b58check_encoding = Base58.register_encoding ~prefix: Base58.Prefix.ed25519_public_key - ~length:Sodium.Sign.public_key_size + ~length:Sign.pkbytes ~to_raw:to_string ~of_raw:of_string ~wrap:(fun x -> Public_key x) @@ -61,13 +66,14 @@ module Public_key = struct let pp ppf t = Format.fprintf ppf "%s" (to_b58check t) let of_hex s = of_string (Hex.to_string s) - let of_hex_exn s = of_string_exn (Hex.to_string s) + let of_hex_exn s = + match of_string (Hex.to_string s) with + | Some x -> x + | None -> invalid_arg "Public_key.of_hex_exn" let to_hex s = Hex.of_string (to_string s) let of_bytes_opt s = - match Sodium.Sign.Bigbytes.to_public_key s with - | exception _ -> None - | pk -> Some pk + Sign.pk_of_cstruct (Cstruct.of_bigarray s) let of_bytes s = match of_bytes_opt s with @@ -81,7 +87,7 @@ module Public_key = struct Pervasives.invalid_arg "Ed25519.Public_key.of_bytes_exn: argument is not a serialized public key" | Some pk -> pk - let to_bytes = Sodium.Sign.Bigbytes.of_public_key + let to_bytes pk = Cstruct.to_bigarray (Sign.to_cstruct pk) let param ?(name="ed25519-public") ?(desc="Ed25519 public key (b58check-encoded)") t = Cli_entries.(param ~name ~desc (parameter (fun _ str -> Lwt.return (of_b58check str))) t) @@ -105,21 +111,21 @@ module Public_key = struct string) ~binary: (conv - Sodium.Sign.Bigbytes.of_public_key - Sodium.Sign.Bigbytes.to_public_key - (Fixed.bytes Sodium.Sign.public_key_size)) + (to_bigarray1 Sign.to_cstruct) + (of_bigarray1 Sign.pk_of_cstruct_exn) + (Fixed.bytes Sign.pkbytes)) let hash v = Public_key_hash.hash_bytes - [ Sodium.Sign.Bigbytes.of_public_key v ] + [ to_bigarray1 Sign.to_cstruct v ] end module Secret_key = struct - type t = Sodium.Sign.secret_key + type t = Sign.secret Sign.key - let to_public_key = Sodium.Sign.secret_key_to_public_key + let to_public_key = Sign.public type Base58.data += | Secret_key of t @@ -127,28 +133,21 @@ module Secret_key = struct let seed_encoding = Base58.register_encoding ~prefix: Base58.Prefix.ed25519_seed - ~length:Sodium.Sign.seed_size - ~to_raw:(fun x -> Sodium.Sign.secret_key_to_seed x |> - Sodium.Sign.Bytes.of_seed |> - Bytes.unsafe_to_string) - ~of_raw:(fun x -> - try Some (Bytes.unsafe_of_string x |> - Sodium.Sign.Bytes.to_seed |> - Sodium.Sign.seed_keypair |> - fst) - with _ -> None) - ~wrap:(fun x -> Secret_key x) + ~length:Sign.seedbytes + ~to_raw:(fun sk -> Cstruct.to_string (Sign.seed sk)) + ~of_raw:(fun buf -> + let seed = Cstruct.of_string buf in + match Sign.keypair ~seed () with + | exception _ -> None + | _pk, sk -> Some sk) + ~wrap:(fun sk -> Secret_key sk) let secret_key_encoding = Base58.register_encoding ~prefix: Base58.Prefix.ed25519_secret_key - ~length:Sodium.Sign.secret_key_size - ~to_raw:(fun x -> Sodium.Sign.Bytes.of_secret_key x |> - Bytes.unsafe_to_string) - ~of_raw:(fun x -> - try Some (Bytes.unsafe_of_string x |> - Sodium.Sign.Bytes.to_secret_key) - with _ -> None) + ~length:Sign.skbytes + ~to_raw:(fun sk -> Cstruct.to_string (Sign.to_cstruct sk)) + ~of_raw:(fun buf -> Sign.sk_of_cstruct (Cstruct.of_string buf)) ~wrap:(fun x -> Secret_key x) let of_b58check_opt s = @@ -169,12 +168,11 @@ module Secret_key = struct let pp ppf t = Format.fprintf ppf "%s" (to_b58check t) let of_bytes_opt s = - match Sodium.Sign.Bigbytes.to_seed s with - | seed -> Some (seed |> Sodium.Sign.seed_keypair |> fst) - | exception _ -> - match Sodium.Sign.Bigbytes.to_secret_key s with - | exception _ -> None - | sk -> Some sk + let s = Cstruct.of_bigarray s in + match Cstruct.len s with + | 32 -> let _pk, sk = Sign.keypair ~seed:s () in Some sk + | 64 -> Sign.sk_of_cstruct s + | _ -> None let of_bytes s = match of_bytes_opt s with @@ -188,8 +186,7 @@ module Secret_key = struct Pervasives.invalid_arg "Ed25519.Secret_key.of_bytes_exn: argument is not a serialized seed" | Some sk -> sk - let to_bytes sk = - Sodium.Sign.(sk |> secret_key_to_seed |> Bigbytes.of_seed) + let to_bytes = to_bigarray1 Sign.seed let param ?(name="ed25519-secret") ?(desc="Ed25519 secret key (b58check-encoded)") t = Cli_entries.(param ~name ~desc (parameter (fun _ str -> Lwt.return (of_b58check str))) t) @@ -213,20 +210,13 @@ module Secret_key = struct "Ed25519 secret key: unexpected prefix.") string) ~binary: - (conv - (fun sk -> Sodium.Sign.secret_key_to_seed sk |> - Sodium.Sign.Bigbytes.of_seed) - (fun bytes -> - if MBytes.length bytes = Sodium.Sign.seed_size - then Sodium.Sign.Bigbytes.to_seed bytes |> - Sodium.Sign.seed_keypair |> fst - else Sodium.Sign.Bigbytes.to_secret_key bytes) + (conv to_bytes (fun buf -> of_bytes_exn buf) (dynamic_size (Variable.bytes))) end let sign key msg = - Sodium.Sign.Bigbytes.(of_signature @@ sign_detached key msg) + Cstruct.(to_bigarray (Sign.detached ~key (of_bigarray msg))) module Signature = struct @@ -238,7 +228,7 @@ module Signature = struct let b58check_encoding = Base58.register_encoding ~prefix: Base58.Prefix.ed25519_signature - ~length:Sodium.Sign.signature_size + ~length:Sign.bytes ~to_raw:MBytes.to_string ~of_raw:(fun s -> Some (MBytes.of_string s)) ~wrap:(fun x -> Signature x) @@ -257,9 +247,7 @@ module Signature = struct let pp ppf t = Format.fprintf ppf "%s" (to_b58check t) let of_bytes_opt s = - match Sodium.Sign.Bigbytes.to_signature s with - | exception _ -> None - | _signature -> Some s + if MBytes.length s = Sign.bytes then Some s else None let of_bytes s = match of_bytes_opt s with @@ -295,13 +283,12 @@ module Signature = struct | None -> Data_encoding.Json.cannot_destruct "Ed25519 signature: unexpected prefix.") string) - ~binary: (Fixed.bytes Sodium.Sign.signature_size) + ~binary: (Fixed.bytes Sign.bytes) let check public_key signature msg = - try - Sodium.Sign.Bigbytes.(verify public_key (to_signature signature) msg) ; - true - with _ -> false + Sign.verify_detached ~key:public_key + ~signature:(Cstruct.of_bigarray signature) + (Cstruct.of_bigarray msg) let append key msg = MBytes.concat msg (sign key msg) @@ -313,32 +300,16 @@ end module Seed = struct - type t = Sodium.Sign.seed + type t = Cstruct.t - let to_hex s = - Sodium.Sign.Bytes.of_seed s - |> Bytes.to_string - |> Hex.of_string - |> (fun (`Hex s) -> s) - - let of_hex s = - Hex.to_string (`Hex s) - |> Bytes.of_string - |> Sodium.Sign.Bytes.to_seed - - let generate () = - (* Seed is 32 bytes long *) - Sodium.Random.Bytes.generate Sodium.Sign.seed_size - |> Sodium.Sign.Bytes.to_seed - - let extract = - Sodium.Sign.secret_key_to_seed + let generate () = Rand.gen 32 + let extract = Sign.seed end let generate_key () = - let secret, pub = Sodium.Sign.random_keypair () in - (Public_key.hash pub, pub, secret) + let pk, sk = Sign.keypair () in + (Public_key.hash pk, pk, sk) let generate_seeded_key seed = - let secret, pub = Sodium.Sign.seed_keypair seed in - (Public_key.hash pub, pub, secret) + let pk, sk = Sign.keypair ~seed () in + (Public_key.hash pk, pk, sk) diff --git a/src/lib_crypto/ed25519.mli b/src/lib_crypto/ed25519.mli index a069dfaad..c935e71ca 100644 --- a/src/lib_crypto/ed25519.mli +++ b/src/lib_crypto/ed25519.mli @@ -102,7 +102,7 @@ module Signature : sig val of_bytes_opt: MBytes.t -> t option val to_bytes: t -> MBytes.t - (** Checks a signature *) + (** Check a signature *) val check: Public_key.t -> t -> MBytes.t -> bool (** Append a signature *) @@ -113,8 +113,6 @@ end module Seed : sig type t - val to_hex : t -> string - val of_hex : string -> t val generate : unit -> t val extract : Secret_key.t -> t end diff --git a/src/lib_crypto/jbuild b/src/lib_crypto/jbuild index d794d6772..1f516309e 100644 --- a/src/lib_crypto/jbuild +++ b/src/lib_crypto/jbuild @@ -15,7 +15,8 @@ tezos-error-monad tezos-rpc nocrypto - sodium + blake2 + tweetnacl zarith)))) (alias diff --git a/src/lib_crypto/rand.ml b/src/lib_crypto/rand.ml new file mode 100644 index 000000000..746bcd086 --- /dev/null +++ b/src/lib_crypto/rand.ml @@ -0,0 +1,23 @@ +(**************************************************************************) +(* *) +(* Copyright (c) 2014 - 2017. *) +(* Dynamic Ledger Solutions, Inc. *) +(* *) +(* All rights reserved. No warranty, explicit or implicit, provided. *) +(* *) +(**************************************************************************) + +let generate len = + Cstruct.to_bigarray (Tweetnacl.Rand.gen len) + +let generate_into ?(pos=0) ?len buf = + let buflen = MBytes.length buf in + let len = match len with + | Some len -> len + | None -> buflen - pos in + if pos < 0 || len < 0 || pos + len > buflen then + invalid_arg (Printf.sprintf "Rand.generate_into: \ + invalid slice (pos=%d len=%d)" pos len) ; + let cs = Cstruct.of_bigarray buf in + let cs = Cstruct.sub cs pos len in + Tweetnacl.Rand.write cs diff --git a/src/lib_crypto/rand.mli b/src/lib_crypto/rand.mli new file mode 100644 index 000000000..fe0a7bd1a --- /dev/null +++ b/src/lib_crypto/rand.mli @@ -0,0 +1,16 @@ +(**************************************************************************) +(* *) +(* Copyright (c) 2014 - 2017. *) +(* Dynamic Ledger Solutions, Inc. *) +(* *) +(* All rights reserved. No warranty, explicit or implicit, provided. *) +(* *) +(**************************************************************************) + +val generate : int -> MBytes.t +(** [generate len] is [len] random bytes. *) + +val generate_into : ?pos:int -> ?len:int -> MBytes.t -> unit +(** [generate_into ?pos ?len buf] writes [len] (default: + [MBytes.length buf]) bytes in [buf] starting at [pos] (default: + [0]). *) diff --git a/src/lib_crypto/tezos-crypto.opam b/src/lib_crypto/tezos-crypto.opam index 8de36b77f..2e43eed30 100644 --- a/src/lib_crypto/tezos-crypto.opam +++ b/src/lib_crypto/tezos-crypto.opam @@ -16,7 +16,8 @@ depends: [ "tezos-error-monad" "tezos-rpc" "nocrypto" - "sodium" + "blake2" + "tweetnacl" "zarith" ] build: [ diff --git a/src/lib_p2p/p2p_socket.ml b/src/lib_p2p/p2p_socket.ml index fb0fdc6bd..bd663e69b 100644 --- a/src/lib_p2p/p2p_socket.ml +++ b/src/lib_p2p/p2p_socket.ml @@ -7,8 +7,6 @@ (* *) (**************************************************************************) -(* TODO encode/encrypt before to push into the writer pipe. *) -(* TODO patch Sodium.Box to avoid allocation of the encrypted buffer.*) (* TODO patch Data_encoding for continuation-based binary writer/reader. *) (* TODO test `close ~wait:true`. *) (* TODO nothing in welcoming message proves that the incoming peer is @@ -33,10 +31,9 @@ type error += Invalid_chunks_size of { value: int ; min: int ; max: int } module Crypto = struct + let bufsize = 1 lsl 16 - 1 let header_length = 2 - let crypto_overhead = 18 (* FIXME import from Sodium.Box. *) - let max_content_length = - 1 lsl (header_length * 8) - crypto_overhead + let max_content_length = bufsize - header_length - Crypto_box.boxzerobytes type data = { channel_key : Crypto_box.channel_key ; @@ -44,48 +41,53 @@ module Crypto = struct mutable remote_nonce : Crypto_box.nonce ; } - let write_chunk fd cryptobox_data buf = - let header_buf = MBytes.create header_length in + let write_chunk fd cryptobox_data msg = + let msglen = MBytes.length msg in + fail_unless + (msglen <= max_content_length) Invalid_message_size >>=? fun () -> + let buf = MBytes.init (msglen + Crypto_box.zerobytes) '\x00' in + MBytes.blit msg 0 buf Crypto_box.zerobytes msglen ; let local_nonce = cryptobox_data.local_nonce in cryptobox_data.local_nonce <- Crypto_box.increment_nonce local_nonce ; - let encrypted_message = - Crypto_box.fast_box cryptobox_data.channel_key buf local_nonce in - let encrypted_len = MBytes.length encrypted_message in - fail_unless - (encrypted_len < 1 lsl (header_length * 8)) - Invalid_message_size >>=? fun () -> - MBytes.set_int16 header_buf 0 encrypted_len ; - P2p_io_scheduler.write fd header_buf >>=? fun () -> - P2p_io_scheduler.write fd encrypted_message >>=? fun () -> - return () + Crypto_box.fast_box_noalloc + cryptobox_data.channel_key local_nonce buf ; + let encrypted_length = msglen + Crypto_box.boxzerobytes in + MBytes.set_int16 buf + (Crypto_box.boxzerobytes - header_length) encrypted_length ; + let payload = MBytes.sub buf (Crypto_box.boxzerobytes - header_length) + (header_length + encrypted_length) in + P2p_io_scheduler.write fd payload let read_chunk fd cryptobox_data = let header_buf = MBytes.create header_length in P2p_io_scheduler.read_full ~len:header_length fd header_buf >>=? fun () -> - let len = MBytes.get_uint16 header_buf 0 in - let buf = MBytes.create len in - P2p_io_scheduler.read_full ~len fd buf >>=? fun () -> + let encrypted_length = MBytes.get_uint16 header_buf 0 in + let buf = MBytes.init (encrypted_length + Crypto_box.boxzerobytes) '\x00' in + P2p_io_scheduler.read_full + ~pos:Crypto_box.boxzerobytes ~len:encrypted_length fd buf >>=? fun () -> let remote_nonce = cryptobox_data.remote_nonce in cryptobox_data.remote_nonce <- Crypto_box.increment_nonce remote_nonce ; match - Crypto_box.fast_box_open cryptobox_data.channel_key buf remote_nonce + Crypto_box.fast_box_open_noalloc + cryptobox_data.channel_key remote_nonce buf with - | None -> + | false -> fail Decipher_error - | Some buf -> - return buf + | true -> + return (MBytes.sub buf Crypto_box.zerobytes + (encrypted_length - Crypto_box.boxzerobytes)) end let check_binary_chunks_size size = - let value = size - Crypto.crypto_overhead - Crypto.header_length in + let value = size - Crypto_box.boxzerobytes - Crypto.header_length in fail_unless (value > 0 && value <= Crypto.max_content_length) (Invalid_chunks_size { value = size ; - min = Crypto.(header_length + crypto_overhead + 1) ; - max = Crypto.(max_content_length + crypto_overhead + header_length) + min = Crypto.(header_length + Crypto_box.boxzerobytes + 1) ; + max = Crypto.bufsize ; }) module Connection_message = struct @@ -392,7 +394,7 @@ module Writer = struct match binary_chunks_size with | None -> Crypto.max_content_length | Some size -> - let size = size - Crypto.crypto_overhead - Crypto.header_length in + let size = size - Crypto_box.boxzerobytes - Crypto.header_length in assert (size > 0) ; assert (size <= Crypto.max_content_length) ; size diff --git a/src/lib_p2p/test/test_p2p_socket.ml b/src/lib_p2p/test/test_p2p_socket.ml index b3b441b9e..8173e8275 100644 --- a/src/lib_p2p/test/test_p2p_socket.ml +++ b/src/lib_p2p/test/test_p2p_socket.ml @@ -26,13 +26,6 @@ let id0 = let versions = P2p_version.[{ name = "TEST" ; minor = 0 ; major = 0 }] -let random_bytes len = - let msg = MBytes.create len in - for i = 0 to len / 8 - 1 do - MBytes.set_int64 msg (i*8) (Random.int64 Int64.max_int) - done ; - msg - let rec listen ?port addr = let tentative_port = match port with @@ -143,7 +136,7 @@ let is_decoding_error = function module Low_level = struct - let simple_msg = random_bytes (1 lsl 4) + let simple_msg = Rand.generate (1 lsl 4) let client _ch sched addr port = let msg = MBytes.create (MBytes.length simple_msg) in @@ -215,8 +208,8 @@ module Simple_message = struct let encoding = Data_encoding.bytes - let simple_msg = random_bytes (1 lsl 4) - let simple_msg2 = random_bytes (1 lsl 4) + let simple_msg = Rand.generate (1 lsl 4) + let simple_msg2 = Rand.generate (1 lsl 4) let server ch sched socket = accept sched socket >>=? fun (_info, auth_fd) -> @@ -246,8 +239,8 @@ module Chunked_message = struct let encoding = Data_encoding.bytes - let simple_msg = random_bytes (1 lsl 8) - let simple_msg2 = random_bytes (1 lsl 8) + let simple_msg = Rand.generate (1 lsl 8) + let simple_msg2 = Rand.generate (1 lsl 8) let server ch sched socket = accept sched socket >>=? fun (_info, auth_fd) -> @@ -279,8 +272,8 @@ module Oversized_message = struct let encoding = Data_encoding.bytes - let simple_msg = random_bytes (1 lsl 17) - let simple_msg2 = random_bytes (1 lsl 17) + let simple_msg = Rand.generate (1 lsl 17) + let simple_msg2 = Rand.generate (1 lsl 17) let server ch sched socket = accept sched socket >>=? fun (_info, auth_fd) -> @@ -310,7 +303,7 @@ module Close_on_read = struct let encoding = Data_encoding.bytes - let simple_msg = random_bytes (1 lsl 4) + let simple_msg = Rand.generate (1 lsl 4) let server ch sched socket = accept sched socket >>=? fun (_info, auth_fd) -> @@ -336,7 +329,7 @@ module Close_on_write = struct let encoding = Data_encoding.bytes - let simple_msg = random_bytes (1 lsl 4) + let simple_msg = Rand.generate (1 lsl 4) let server ch sched socket = accept sched socket >>=? fun (_info, auth_fd) -> diff --git a/src/lib_protocol_compiler/compiler.ml b/src/lib_protocol_compiler/compiler.ml index 7baf72344..9cf1e7177 100644 --- a/src/lib_protocol_compiler/compiler.ml +++ b/src/lib_protocol_compiler/compiler.ml @@ -117,21 +117,23 @@ let debug fmt = else Format.ifprintf Format.err_formatter fmt let hash_file file = - let open Sodium.Generichash in + let open Blake2 in let buflen = 8092 in let buf = BytesLabels.create buflen in let fd = Unix.openfile file [Unix.O_RDONLY] 0o600 in - let state = init ~size:32 () in + let state = Blake2b.init 32 in let loop () = match Unix.read fd buf 0 buflen with | 0 -> () | nb_read -> - Bytes.update state @@ - if nb_read = buflen then buf else BytesLabels.sub buf ~pos:0 ~len:nb_read + Blake2b.update state + (Cstruct.of_bytes + (if nb_read = buflen then buf else BytesLabels.sub buf ~pos:0 ~len:nb_read)) in loop () ; Unix.close fd ; - BytesLabels.unsafe_to_string (Bytes.of_hash (final state)) + let Blake2b.Hash h = Blake2b.final state in + Cstruct.to_string h let mktemp_dir () = Filename.get_temp_dir_name () // diff --git a/src/lib_stdlib/mBytes.ml b/src/lib_stdlib/mBytes.ml index 4663da703..66334ea39 100644 --- a/src/lib_stdlib/mBytes.ml +++ b/src/lib_stdlib/mBytes.ml @@ -21,6 +21,12 @@ let copy ba = let ba' = create (Array1.dim ba) in Array1.blit ba ba'; ba' +let fill = Array1.fill + +let init sz v = + let b = create sz in + fill b v ; + b (** Adapted from ocaml-cstruct. *) diff --git a/src/lib_stdlib/mBytes.mli b/src/lib_stdlib/mBytes.mli index 471be08c3..e38104c00 100644 --- a/src/lib_stdlib/mBytes.mli +++ b/src/lib_stdlib/mBytes.mli @@ -20,9 +20,14 @@ type t = (char, int8_unsigned_elt, c_layout) Array1.t val create: int -> t (** [create n] allocates and returns an array of size [n] **) +val init: int -> char -> t +(** [init n c] allocates and returns an array of size [n] initialized + with [c]. *) + val length: t -> int val copy: t -> t +val fill: t -> char -> unit val sub: t -> int -> int -> t (** [sub src ofs len] extract a sub-array of [src] starting at [ofs] diff --git a/src/lib_stdlib_lwt/jbuild b/src/lib_stdlib_lwt/jbuild index 3cf892372..bb36d8e11 100644 --- a/src/lib_stdlib_lwt/jbuild +++ b/src/lib_stdlib_lwt/jbuild @@ -12,7 +12,8 @@ tezos-data-encoding tezos-error-monad lwt.unix - ipaddr.unix)))) + ipaddr.unix + str)))) (alias ((name runtest_indent) diff --git a/src/proto_alpha/lib_client/client_baking_forge.ml b/src/proto_alpha/lib_client/client_baking_forge.ml index 697b277f6..eb9f09594 100644 --- a/src/proto_alpha/lib_client/client_baking_forge.ml +++ b/src/proto_alpha/lib_client/client_baking_forge.ml @@ -13,11 +13,11 @@ open Tezos_context open Logging.Client.Baking let generate_proof_of_work_nonce () = - Sodium.Random.Bigbytes.generate Constants.proof_of_work_nonce_size + Rand.generate Constants.proof_of_work_nonce_size let generate_seed_nonce () = match Nonce.of_bytes @@ - Sodium.Random.Bigbytes.generate Constants.nonce_length with + Rand.generate Constants.nonce_length with | Error _ -> assert false | Ok nonce -> nonce diff --git a/src/proto_alpha/lib_client/client_proto_rpcs.ml b/src/proto_alpha/lib_client/client_proto_rpcs.ml index 328ec4b7d..036bd50d5 100644 --- a/src/proto_alpha/lib_client/client_proto_rpcs.ml +++ b/src/proto_alpha/lib_client/client_proto_rpcs.ml @@ -263,7 +263,7 @@ module Helpers = struct operations cctxt block ~branch [Seed_nonce_revelation { level ; nonce }] let faucet cctxt block ~branch ~id () = - let nonce = Sodium.Random.Bigbytes.generate 16 in + let nonce = Rand.generate 16 in operations cctxt block ~branch [Faucet { id ; nonce }] end let empty_proof_of_work_nonce = diff --git a/src/proto_alpha/lib_client/test/proto_alpha_helpers.ml b/src/proto_alpha/lib_client/test/proto_alpha_helpers.ml index ca4b2ebee..d8cbf3398 100644 --- a/src/proto_alpha/lib_client/test/proto_alpha_helpers.ml +++ b/src/proto_alpha/lib_client/test/proto_alpha_helpers.ml @@ -409,7 +409,7 @@ module Baking = struct let bake block (contract: Account.t) operations = let seed_nonce = match Nonce.of_bytes @@ - Sodium.Random.Bigbytes.generate Constants.nonce_length with + Rand.generate Constants.nonce_length with | Error _ -> assert false | Ok nonce -> nonce in let seed_nonce_hash = Nonce.hash seed_nonce in diff --git a/src/proto_alpha/lib_protocol/test/helpers/helpers_block.ml b/src/proto_alpha/lib_protocol/test/helpers/helpers_block.ml index 2065f42ad..5882884d9 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/helpers_block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/helpers_block.ml @@ -42,8 +42,8 @@ let get_op_header_res (res : result) : operation_header = { let get_proto_header priority : protocol_header = { priority ; - proof_of_work_nonce = Helpers_sodium.generate_proof_of_work_nonce (); - seed_nonce_hash = Proto_alpha.Tezos_context.Nonce.hash @@ Helpers_sodium.generate_seed_nonce () + proof_of_work_nonce = Helpers_crypto.generate_proof_of_work_nonce (); + seed_nonce_hash = Proto_alpha.Tezos_context.Nonce.hash @@ Helpers_crypto.generate_seed_nonce () } let get_op_header pbh : operation_header = { diff --git a/src/proto_alpha/lib_protocol/test/helpers/helpers_sodium.ml b/src/proto_alpha/lib_protocol/test/helpers/helpers_crypto.ml similarity index 85% rename from src/proto_alpha/lib_protocol/test/helpers/helpers_sodium.ml rename to src/proto_alpha/lib_protocol/test/helpers/helpers_crypto.ml index c5f3cb6f0..978869600 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/helpers_sodium.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/helpers_crypto.ml @@ -10,10 +10,10 @@ open Proto_alpha.Tezos_context let generate_proof_of_work_nonce () = - Sodium.Random.Bigbytes.generate Constants.proof_of_work_nonce_size + Rand.generate Constants.proof_of_work_nonce_size let generate_seed_nonce () = match Nonce.of_bytes @@ - Sodium.Random.Bigbytes.generate Constants.nonce_length with + Rand.generate Constants.nonce_length with | Error _ -> assert false | Ok nonce -> nonce diff --git a/src/proto_alpha/lib_protocol/test/helpers/helpers_sodium.mli b/src/proto_alpha/lib_protocol/test/helpers/helpers_crypto.mli similarity index 100% rename from src/proto_alpha/lib_protocol/test/helpers/helpers_sodium.mli rename to src/proto_alpha/lib_protocol/test/helpers/helpers_crypto.mli diff --git a/src/proto_alpha/lib_protocol/test/helpers/isolate_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/isolate_helpers.ml index ff14fb9e6..a3d9fb2be 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/isolate_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/isolate_helpers.ml @@ -9,7 +9,7 @@ open Proto_alpha -module Sodium = Helpers_sodium +module Crypto = Helpers_crypto module Cast = Helpers_cast module Assert = Helpers_assert module Services = Helpers_services diff --git a/vendors/ocaml-blake2/LICENSE.md b/vendors/ocaml-blake2/LICENSE.md new file mode 100644 index 000000000..52b5f8cd7 --- /dev/null +++ b/vendors/ocaml-blake2/LICENSE.md @@ -0,0 +1,13 @@ +Copyright (c) 2017 Vincent Bernardoff + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vendors/ocaml-blake2/blake2.opam b/vendors/ocaml-blake2/blake2.opam new file mode 100644 index 000000000..aba17f1f1 --- /dev/null +++ b/vendors/ocaml-blake2/blake2.opam @@ -0,0 +1,21 @@ +opam-version: "1.2" +name: "blake2" +version: "dev" +authors: "Vincent Bernardoff " +maintainer: "Vincent Bernardoff " +license: "ISC" +homepage: "https://github.com/vbmithr/ocaml-blake2" +bug-reports: "https://github.com/vbmithr/ocaml-blake2/issues" +dev-repo: "git://github.com/vbmithr/ocaml-blake2" + +available: [ + ocaml-version >= "4.02.0" +] + +build: [ "jbuilder" "build" "-j" jobs "-p" name "@install" ] +build-test: [ "jbuilder" "runtest" "-p" name "-j" jobs ] +depends: [ + "jbuilder" {build & >= "1.0+beta16"} + "cstruct" {>= "3.2.1"} + "alcotest" { test } +] diff --git a/vendors/ocaml-blake2/src/blake2-impl.h b/vendors/ocaml-blake2/src/blake2-impl.h new file mode 100644 index 000000000..5dff7fc7a --- /dev/null +++ b/vendors/ocaml-blake2/src/blake2-impl.h @@ -0,0 +1,160 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves . You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ +#ifndef BLAKE2_IMPL_H +#define BLAKE2_IMPL_H + +#include +#include + +#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) + #if defined(_MSC_VER) + #define BLAKE2_INLINE __inline + #elif defined(__GNUC__) + #define BLAKE2_INLINE __inline__ + #else + #define BLAKE2_INLINE + #endif +#else + #define BLAKE2_INLINE inline +#endif + +static BLAKE2_INLINE uint32_t load32( const void *src ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + uint32_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = ( const uint8_t * )src; + return (( uint32_t )( p[0] ) << 0) | + (( uint32_t )( p[1] ) << 8) | + (( uint32_t )( p[2] ) << 16) | + (( uint32_t )( p[3] ) << 24) ; +#endif +} + +static BLAKE2_INLINE uint64_t load64( const void *src ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + uint64_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = ( const uint8_t * )src; + return (( uint64_t )( p[0] ) << 0) | + (( uint64_t )( p[1] ) << 8) | + (( uint64_t )( p[2] ) << 16) | + (( uint64_t )( p[3] ) << 24) | + (( uint64_t )( p[4] ) << 32) | + (( uint64_t )( p[5] ) << 40) | + (( uint64_t )( p[6] ) << 48) | + (( uint64_t )( p[7] ) << 56) ; +#endif +} + +static BLAKE2_INLINE uint16_t load16( const void *src ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + uint16_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = ( const uint8_t * )src; + return (( uint16_t )( p[0] ) << 0) | + (( uint16_t )( p[1] ) << 8) ; +#endif +} + +static BLAKE2_INLINE void store16( void *dst, uint16_t w ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = ( uint8_t * )dst; + *p++ = ( uint8_t )w; w >>= 8; + *p++ = ( uint8_t )w; +#endif +} + +static BLAKE2_INLINE void store32( void *dst, uint32_t w ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = ( uint8_t * )dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); +#endif +} + +static BLAKE2_INLINE void store64( void *dst, uint64_t w ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = ( uint8_t * )dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); + p[4] = (uint8_t)(w >> 32); + p[5] = (uint8_t)(w >> 40); + p[6] = (uint8_t)(w >> 48); + p[7] = (uint8_t)(w >> 56); +#endif +} + +static BLAKE2_INLINE uint64_t load48( const void *src ) +{ + const uint8_t *p = ( const uint8_t * )src; + return (( uint64_t )( p[0] ) << 0) | + (( uint64_t )( p[1] ) << 8) | + (( uint64_t )( p[2] ) << 16) | + (( uint64_t )( p[3] ) << 24) | + (( uint64_t )( p[4] ) << 32) | + (( uint64_t )( p[5] ) << 40) ; +} + +static BLAKE2_INLINE void store48( void *dst, uint64_t w ) +{ + uint8_t *p = ( uint8_t * )dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); + p[4] = (uint8_t)(w >> 32); + p[5] = (uint8_t)(w >> 40); +} + +static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c ) +{ + return ( w >> c ) | ( w << ( 32 - c ) ); +} + +static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c ) +{ + return ( w >> c ) | ( w << ( 64 - c ) ); +} + +/* prevents compiler optimizing out memset() */ +static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) +{ + static void *(*const volatile memset_v)(void *, int, size_t) = &memset; + memset_v(v, 0, n); +} + +#endif diff --git a/vendors/ocaml-blake2/src/blake2.h b/vendors/ocaml-blake2/src/blake2.h new file mode 100644 index 000000000..ad62f260e --- /dev/null +++ b/vendors/ocaml-blake2/src/blake2.h @@ -0,0 +1,195 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves . You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ +#ifndef BLAKE2_H +#define BLAKE2_H + +#include +#include + +#if defined(_MSC_VER) +#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop)) +#else +#define BLAKE2_PACKED(x) x __attribute__((packed)) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + + enum blake2s_constant + { + BLAKE2S_BLOCKBYTES = 64, + BLAKE2S_OUTBYTES = 32, + BLAKE2S_KEYBYTES = 32, + BLAKE2S_SALTBYTES = 8, + BLAKE2S_PERSONALBYTES = 8 + }; + + enum blake2b_constant + { + BLAKE2B_BLOCKBYTES = 128, + BLAKE2B_OUTBYTES = 64, + BLAKE2B_KEYBYTES = 64, + BLAKE2B_SALTBYTES = 16, + BLAKE2B_PERSONALBYTES = 16 + }; + + typedef struct blake2s_state__ + { + uint32_t h[8]; + uint32_t t[2]; + uint32_t f[2]; + uint8_t buf[BLAKE2S_BLOCKBYTES]; + size_t buflen; + size_t outlen; + uint8_t last_node; + } blake2s_state; + + typedef struct blake2b_state__ + { + uint64_t h[8]; + uint64_t t[2]; + uint64_t f[2]; + uint8_t buf[BLAKE2B_BLOCKBYTES]; + size_t buflen; + size_t outlen; + uint8_t last_node; + } blake2b_state; + + typedef struct blake2sp_state__ + { + blake2s_state S[8][1]; + blake2s_state R[1]; + uint8_t buf[8 * BLAKE2S_BLOCKBYTES]; + size_t buflen; + size_t outlen; + } blake2sp_state; + + typedef struct blake2bp_state__ + { + blake2b_state S[4][1]; + blake2b_state R[1]; + uint8_t buf[4 * BLAKE2B_BLOCKBYTES]; + size_t buflen; + size_t outlen; + } blake2bp_state; + + + BLAKE2_PACKED(struct blake2s_param__ + { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint16_t xof_length; /* 14 */ + uint8_t node_depth; /* 15 */ + uint8_t inner_length; /* 16 */ + /* uint8_t reserved[0]; */ + uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */ + uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */ + }); + + typedef struct blake2s_param__ blake2s_param; + + BLAKE2_PACKED(struct blake2b_param__ + { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint32_t xof_length; /* 16 */ + uint8_t node_depth; /* 17 */ + uint8_t inner_length; /* 18 */ + uint8_t reserved[14]; /* 32 */ + uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ + uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ + }); + + typedef struct blake2b_param__ blake2b_param; + + typedef struct blake2xs_state__ + { + blake2s_state S[1]; + blake2s_param P[1]; + } blake2xs_state; + + typedef struct blake2xb_state__ + { + blake2b_state S[1]; + blake2b_param P[1]; + } blake2xb_state; + + /* Padded structs result in a compile-time error */ + enum { + BLAKE2_DUMMY_1 = 1/(sizeof(blake2s_param) == BLAKE2S_OUTBYTES), + BLAKE2_DUMMY_2 = 1/(sizeof(blake2b_param) == BLAKE2B_OUTBYTES) + }; + + /* Streaming API */ + int blake2s_init( blake2s_state *S, size_t outlen ); + int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen ); + int blake2s_init_param( blake2s_state *S, const blake2s_param *P ); + int blake2s_update( blake2s_state *S, const void *in, size_t inlen ); + int blake2s_final( blake2s_state *S, void *out, size_t outlen ); + + int blake2b_init( blake2b_state *S, size_t outlen ); + int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ); + int blake2b_init_param( blake2b_state *S, const blake2b_param *P ); + int blake2b_update( blake2b_state *S, const void *in, size_t inlen ); + int blake2b_final( blake2b_state *S, void *out, size_t outlen ); + + int blake2sp_init( blake2sp_state *S, size_t outlen ); + int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen ); + int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen ); + int blake2sp_final( blake2sp_state *S, void *out, size_t outlen ); + + int blake2bp_init( blake2bp_state *S, size_t outlen ); + int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen ); + int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen ); + int blake2bp_final( blake2bp_state *S, void *out, size_t outlen ); + + /* Variable output length API */ + int blake2xs_init( blake2xs_state *S, const size_t outlen ); + int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen ); + int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ); + int blake2xs_final(blake2xs_state *S, void *out, size_t outlen); + + int blake2xb_init( blake2xb_state *S, const size_t outlen ); + int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen ); + int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ); + int blake2xb_final(blake2xb_state *S, void *out, size_t outlen); + + /* Simple API */ + int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + + int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + + int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + + /* This is simply an alias for blake2b */ + int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/vendors/ocaml-blake2/src/blake2.ml b/vendors/ocaml-blake2/src/blake2.ml new file mode 100644 index 000000000..239f9f800 --- /dev/null +++ b/vendors/ocaml-blake2/src/blake2.ml @@ -0,0 +1,91 @@ +(*--------------------------------------------------------------------------- + Copyright (c) 2018 Vincent Bernardoff. All rights reserved. + Distributed under the ISC license, see terms at the end of the file. + ---------------------------------------------------------------------------*) + +module Blake2b = struct + type t = Cstruct.t + + external sizeof_state : unit -> int = + "sizeof_blake2b_state" [@@noalloc] + + let bytes = sizeof_state () + + external init : Cstruct.buffer -> int -> int = + "ml_blake2b_init" [@@noalloc] + + external outlen : Cstruct.buffer -> int = + "blake2b_state_outlen" [@@noalloc] + + let outlen t = outlen t.Cstruct.buffer + + external init_key : Cstruct.buffer -> int -> Cstruct.buffer -> int = + "ml_blake2b_init_key" [@@noalloc] + + external update : Cstruct.buffer -> Cstruct.buffer -> int = + "ml_blake2b_update" [@@noalloc] + + external final : Cstruct.buffer -> Cstruct.buffer -> int = + "ml_blake2b_final" [@@noalloc] + + external direct : + Cstruct.buffer -> Cstruct.buffer -> Cstruct.buffer -> int = + "ml_blake2b" [@@noalloc] + + let or_fail ~msg f = + match f () with + | 0 -> () + | _ -> failwith msg + + let init ?key size = + if size < 1 || size > 64 then + invalid_arg "Blake2b.init: size must be between 1 and 64" ; + let t = Cstruct.create_unsafe bytes in + begin match key with + | Some key -> + or_fail ~msg:"Blake2b.init" + (fun () -> init_key t.buffer size key.Cstruct.buffer) + | None -> + or_fail ~msg:"Blake2b.init" + (fun () -> init t.buffer size) + end ; + t + + let update t buf = + or_fail ~msg:"Blake2b.update" + (fun () -> update t.Cstruct.buffer buf.Cstruct.buffer) + + type hash = Hash of Cstruct.t + + let final t = + let len = outlen t in + let buf = Cstruct.create_unsafe len in + or_fail ~msg:"Blake2b.final" + (fun () -> final t.Cstruct.buffer buf.Cstruct.buffer) ; + Hash buf + + let direct ?(key=Cstruct.create_unsafe 0) inbuf len = + if len < 1 || len > 64 then + invalid_arg "Blake2b.direct: size must be between 1 and 64" ; + let outbuf = Cstruct.create len in + or_fail ~msg:"Blake2b.direct" + (fun () -> direct outbuf.Cstruct.buffer + inbuf.Cstruct.buffer key.buffer) ; + Hash outbuf +end + +(*--------------------------------------------------------------------------- + Copyright (c) 2018 Vincent Bernardoff + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + ---------------------------------------------------------------------------*) diff --git a/vendors/ocaml-blake2/src/blake2.mli b/vendors/ocaml-blake2/src/blake2.mli new file mode 100644 index 000000000..d6eede4e5 --- /dev/null +++ b/vendors/ocaml-blake2/src/blake2.mli @@ -0,0 +1,40 @@ +(*--------------------------------------------------------------------------- + Copyright (c) 2018 Vincent Bernardoff. All rights reserved. + Distributed under the ISC license, see terms at the end of the file. + ---------------------------------------------------------------------------*) + +module Blake2b : sig + type t + type hash = Hash of Cstruct.t + + val init : ?key:Cstruct.t -> int -> t + (** [init ?key size] is a blake2b context for hashes of size [size], + using [key] if present. *) + + val update : t -> Cstruct.t -> unit + (** [update t buf] updates [t] with the data in [buf]. *) + + val final : t -> hash + (** [final t] is the blake2b hash of all data updated in [t] so + far. *) + + val direct : ?key:Cstruct.t -> Cstruct.t -> int -> hash + (** [direct ?key outbuf inbuf] writes the blake2b hash of [inbuf] in + [outbuf], using [key] is present. *) +end + +(*--------------------------------------------------------------------------- + Copyright (c) 2018 Vincent Bernardoff + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + ---------------------------------------------------------------------------*) diff --git a/vendors/ocaml-blake2/src/blake2b-ref.c b/vendors/ocaml-blake2/src/blake2b-ref.c new file mode 100644 index 000000000..32fbacb0e --- /dev/null +++ b/vendors/ocaml-blake2/src/blake2b-ref.c @@ -0,0 +1,423 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves . You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ + +#include +#include +#include + +#include "blake2.h" +#include "blake2-impl.h" + +static const uint64_t blake2b_IV[8] = +{ + 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL +}; + +static const uint8_t blake2b_sigma[12][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } +}; + + +static void blake2b_set_lastnode( blake2b_state *S ) +{ + S->f[1] = (uint64_t)-1; +} + +/* Some helper functions, not necessarily useful */ +static int blake2b_is_lastblock( const blake2b_state *S ) +{ + return S->f[0] != 0; +} + +static void blake2b_set_lastblock( blake2b_state *S ) +{ + if( S->last_node ) blake2b_set_lastnode( S ); + + S->f[0] = (uint64_t)-1; +} + +static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc ) +{ + S->t[0] += inc; + S->t[1] += ( S->t[0] < inc ); +} + +static void blake2b_init0( blake2b_state *S ) +{ + size_t i; + memset( S, 0, sizeof( blake2b_state ) ); + + for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i]; +} + +/* init xors IV with input parameter block */ +int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) +{ + const uint8_t *p = ( const uint8_t * )( P ); + size_t i; + + blake2b_init0( S ); + + /* IV XOR ParamBlock */ + for( i = 0; i < 8; ++i ) + S->h[i] ^= load64( p + sizeof( S->h[i] ) * i ); + + S->outlen = P->digest_length; + return 0; +} + + + +int blake2b_init( blake2b_state *S, size_t outlen ) +{ + blake2b_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; + + P->digest_length = (uint8_t)outlen; + P->key_length = 0; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store32( &P->node_offset, 0 ); + store32( &P->xof_length, 0 ); + P->node_depth = 0; + P->inner_length = 0; + memset( P->reserved, 0, sizeof( P->reserved ) ); + memset( P->salt, 0, sizeof( P->salt ) ); + memset( P->personal, 0, sizeof( P->personal ) ); + return blake2b_init_param( S, P ); +} + + +int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ) +{ + blake2b_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; + + if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; + + P->digest_length = (uint8_t)outlen; + P->key_length = (uint8_t)keylen; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store32( &P->node_offset, 0 ); + store32( &P->xof_length, 0 ); + P->node_depth = 0; + P->inner_length = 0; + memset( P->reserved, 0, sizeof( P->reserved ) ); + memset( P->salt, 0, sizeof( P->salt ) ); + memset( P->personal, 0, sizeof( P->personal ) ); + + if( blake2b_init_param( S, P ) < 0 ) return -1; + + { + uint8_t block[BLAKE2B_BLOCKBYTES]; + memset( block, 0, BLAKE2B_BLOCKBYTES ); + memcpy( block, key, keylen ); + blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); + secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */ + } + return 0; +} + +#define G(r,i,a,b,c,d) \ + do { \ + a = a + b + m[blake2b_sigma[r][2*i+0]]; \ + d = rotr64(d ^ a, 32); \ + c = c + d; \ + b = rotr64(b ^ c, 24); \ + a = a + b + m[blake2b_sigma[r][2*i+1]]; \ + d = rotr64(d ^ a, 16); \ + c = c + d; \ + b = rotr64(b ^ c, 63); \ + } while(0) + +#define ROUND(r) \ + do { \ + G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ + G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ + G(r,2,v[ 2],v[ 6],v[10],v[14]); \ + G(r,3,v[ 3],v[ 7],v[11],v[15]); \ + G(r,4,v[ 0],v[ 5],v[10],v[15]); \ + G(r,5,v[ 1],v[ 6],v[11],v[12]); \ + G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ + G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ + } while(0) + +static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] ) +{ + uint64_t m[16]; + uint64_t v[16]; + size_t i; + + for( i = 0; i < 16; ++i ) { + m[i] = load64( block + i * sizeof( m[i] ) ); + } + + for( i = 0; i < 8; ++i ) { + v[i] = S->h[i]; + } + + v[ 8] = blake2b_IV[0]; + v[ 9] = blake2b_IV[1]; + v[10] = blake2b_IV[2]; + v[11] = blake2b_IV[3]; + v[12] = blake2b_IV[4] ^ S->t[0]; + v[13] = blake2b_IV[5] ^ S->t[1]; + v[14] = blake2b_IV[6] ^ S->f[0]; + v[15] = blake2b_IV[7] ^ S->f[1]; + + ROUND( 0 ); + ROUND( 1 ); + ROUND( 2 ); + ROUND( 3 ); + ROUND( 4 ); + ROUND( 5 ); + ROUND( 6 ); + ROUND( 7 ); + ROUND( 8 ); + ROUND( 9 ); + ROUND( 10 ); + ROUND( 11 ); + + for( i = 0; i < 8; ++i ) { + S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; + } +} + +#undef G +#undef ROUND + +int blake2b_update( blake2b_state *S, const void *pin, size_t inlen ) +{ + const unsigned char * in = (const unsigned char *)pin; + if( inlen > 0 ) + { + size_t left = S->buflen; + size_t fill = BLAKE2B_BLOCKBYTES - left; + if( inlen > fill ) + { + S->buflen = 0; + memcpy( S->buf + left, in, fill ); /* Fill buffer */ + blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); + blake2b_compress( S, S->buf ); /* Compress */ + in += fill; inlen -= fill; + while(inlen > BLAKE2B_BLOCKBYTES) { + blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); + blake2b_compress( S, in ); + in += BLAKE2B_BLOCKBYTES; + inlen -= BLAKE2B_BLOCKBYTES; + } + } + memcpy( S->buf + S->buflen, in, inlen ); + S->buflen += inlen; + } + return 0; +} + +int blake2b_final( blake2b_state *S, void *out, size_t outlen ) +{ + uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; + size_t i; + + if( out == NULL || outlen < S->outlen ) + return -1; + + if( blake2b_is_lastblock( S ) ) + return -1; + + blake2b_increment_counter( S, S->buflen ); + blake2b_set_lastblock( S ); + memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */ + blake2b_compress( S, S->buf ); + + for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ + store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); + + memcpy( out, buffer, S->outlen ); + secure_zero_memory(buffer, sizeof(buffer)); + return 0; +} + +/* inlen, at least, should be uint64_t. Others can be size_t. */ +int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) +{ + blake2b_state S[1]; + + /* Verify parameters */ + if ( NULL == in && inlen > 0 ) return -1; + + if ( NULL == out ) return -1; + + if( NULL == key && keylen > 0 ) return -1; + + if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1; + + if( keylen > BLAKE2B_KEYBYTES ) return -1; + + if( keylen > 0 ) + { + if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; + } + else + { + if( blake2b_init( S, outlen ) < 0 ) return -1; + } + + blake2b_update( S, ( const uint8_t * )in, inlen ); + blake2b_final( S, out, outlen ); + return 0; +} + +int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) { + return blake2b(out, outlen, in, inlen, key, keylen); +} + +#if defined(SUPERCOP) +int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen ) +{ + return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 ); +} +#endif + +#if defined(BLAKE2B_SELFTEST) +#include +#include "blake2-kat.h" +int main( void ) +{ + uint8_t key[BLAKE2B_KEYBYTES]; + uint8_t buf[BLAKE2_KAT_LENGTH]; + size_t i, step; + + for( i = 0; i < BLAKE2B_KEYBYTES; ++i ) + key[i] = ( uint8_t )i; + + for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) + buf[i] = ( uint8_t )i; + + /* Test simple API */ + for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) + { + uint8_t hash[BLAKE2B_OUTBYTES]; + blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES ); + + if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) + { + goto fail; + } + } + + /* Test streaming API */ + for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) { + for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) { + uint8_t hash[BLAKE2B_OUTBYTES]; + blake2b_state S; + uint8_t * p = buf; + size_t mlen = i; + int err = 0; + + if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) { + goto fail; + } + + while (mlen >= step) { + if ( (err = blake2b_update(&S, p, step)) < 0 ) { + goto fail; + } + mlen -= step; + p += step; + } + if ( (err = blake2b_update(&S, p, mlen)) < 0) { + goto fail; + } + if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) { + goto fail; + } + + if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) { + goto fail; + } + } + } + + puts( "ok" ); + return 0; +fail: + puts("error"); + return -1; +} +#endif + +#include +#include + +CAMLprim value sizeof_blake2b_state(value unit) { + return Val_int(sizeof(blake2b_state)); +} + +CAMLprim value blake2b_state_outlen(value S) { + blake2b_state *s = Caml_ba_data_val(S); + return Val_int(s->outlen); +} + +CAMLprim value ml_blake2b_init(value S, value outlen) { + return Val_int(blake2b_init(Caml_ba_data_val(S), Int_val(outlen))); +} + +CAMLprim value ml_blake2b_init_key(value S, value outlen, value key) { + return Val_int(blake2b_init_key(Caml_ba_data_val(S), + Int_val(outlen), + Caml_ba_data_val(key), + Caml_ba_array_val(key)->dim[0])); +} + +CAMLprim value ml_blake2b_update(value S, value in) { + return Val_int(blake2b_update(Caml_ba_data_val(S), + Caml_ba_data_val(in), + Caml_ba_array_val(in)->dim[0])); +} + +CAMLprim value ml_blake2b_final(value S, value out) { + return Val_int(blake2b_final(Caml_ba_data_val(S), + Caml_ba_data_val(out), + Caml_ba_array_val(out)->dim[0])); +} + +CAMLprim value ml_blake2b(value out, value in, value key) { + return Val_int(blake2b(Caml_ba_data_val(out), + Caml_ba_array_val(out)->dim[0], + Caml_ba_data_val(in), + Caml_ba_array_val(in)->dim[0], + Caml_ba_data_val(key), + Caml_ba_array_val(key)->dim[0])); +} diff --git a/vendors/ocaml-blake2/src/jbuild b/vendors/ocaml-blake2/src/jbuild new file mode 100644 index 000000000..6ce592cfd --- /dev/null +++ b/vendors/ocaml-blake2/src/jbuild @@ -0,0 +1,7 @@ +(jbuild_version 1) + +(library + ((name blake2) + (public_name blake2) + (libraries (cstruct)) + (c_names (blake2b-ref)))) diff --git a/vendors/ocaml-blake2/test/jbuild b/vendors/ocaml-blake2/test/jbuild new file mode 100644 index 000000000..42fe2a4a7 --- /dev/null +++ b/vendors/ocaml-blake2/test/jbuild @@ -0,0 +1,14 @@ +(jbuild_version 1) + +(executable + ((name test) + (libraries (blake2 alcotest)))) + +(alias + ((name runtest-blake2) + (deps (test.exe)) + (action (run ${<})))) + +(alias + ((name runtest) + (deps ((alias runtest-blake2))))) diff --git a/vendors/ocaml-blake2/test/test.ml b/vendors/ocaml-blake2/test/test.ml new file mode 100644 index 000000000..2670bbe1a --- /dev/null +++ b/vendors/ocaml-blake2/test/test.ml @@ -0,0 +1,59 @@ + +open Blake2 + +type vector = { + data_in : string list ; + data_key : string option ; + data_out : string ; +} + +let vectors = [ + { data_in = [ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" ] ; + data_key = None ; + data_out = "1c077e279de6548523502b6df800ffdab5e2c3e9442eb838f58c295f3b147cef9d701c41c321283f00c71affa0619310399126295b78dd4d1a74572ef9ed5135" ; + } ; + { data_in = [ "000102030405060708090a0b0c0d0e0f101112131415" ; "161718"; "191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" ] ; + data_key = None ; + data_out = "1c077e279de6548523502b6df800ffdab5e2c3e9442eb838f58c295f3b147cef9d701c41c321283f00c71affa0619310399126295b78dd4d1a74572ef9ed5135" ; + } ; + { data_in = [ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3" ] ; + data_key = Some ("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f") ; + data_out = "b39614268fdd8781515e2cfebf89b4d5402bab10c226e6344e6b9ae000fb0d6c79cb2f3ec80e80eaeb1980d2f8698916bd2e9f747236655116649cd3ca23a837" ; + } ; +] + +let test_update { data_in ; data_key ; data_out } = + let key = + match data_key with None -> None | Some s -> Some (Cstruct.of_hex s) in + let data_out = Cstruct.of_hex data_out in + let d = Blake2b.init ?key (Cstruct.len data_out) in + List.iter (fun s -> Blake2b.update d (Cstruct.of_hex s)) data_in ; + let Blake2b.Hash h = Blake2b.final d in + assert Cstruct.(equal data_out h) + +let test_direct { data_in ; data_key ; data_out } = + let key = + match data_key with None -> None | Some s -> Some (Cstruct.of_hex s) in + let data_out = Cstruct.of_hex data_out in + let Blake2b.Hash h = + Blake2b.direct ?key + (Cstruct.of_hex (String.concat "" data_in)) + (Cstruct.len data_out) in + assert Cstruct.(equal data_out h) + +let update_tests = + List.mapi + (fun i v -> string_of_int i, `Quick, fun () -> test_update v) + vectors + +let direct_tests = + List.mapi + (fun i v -> string_of_int i, `Quick, fun () -> test_direct v) + vectors + +let () = + Alcotest.run "blake2b" [ + "update", update_tests ; + "direct", direct_tests ; + ] + diff --git a/vendors/ocaml-tweetnacl/LICENSE.md b/vendors/ocaml-tweetnacl/LICENSE.md new file mode 100644 index 000000000..52b5f8cd7 --- /dev/null +++ b/vendors/ocaml-tweetnacl/LICENSE.md @@ -0,0 +1,13 @@ +Copyright (c) 2017 Vincent Bernardoff + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vendors/ocaml-tweetnacl/src/jbuild b/vendors/ocaml-tweetnacl/src/jbuild new file mode 100644 index 000000000..6aff84f95 --- /dev/null +++ b/vendors/ocaml-tweetnacl/src/jbuild @@ -0,0 +1,7 @@ +(jbuild_version 1) + +(library + ((name tweetnacl) + (public_name tweetnacl) + (libraries (hex cstruct zarith)) + (c_names (tweetnacl_stubs)))) diff --git a/vendors/ocaml-tweetnacl/src/tweetnacl.h b/vendors/ocaml-tweetnacl/src/tweetnacl.h new file mode 100644 index 000000000..9277fbf8f --- /dev/null +++ b/vendors/ocaml-tweetnacl/src/tweetnacl.h @@ -0,0 +1,272 @@ +#ifndef TWEETNACL_H +#define TWEETNACL_H +#define crypto_auth_PRIMITIVE "hmacsha512256" +#define crypto_auth crypto_auth_hmacsha512256 +#define crypto_auth_verify crypto_auth_hmacsha512256_verify +#define crypto_auth_BYTES crypto_auth_hmacsha512256_BYTES +#define crypto_auth_KEYBYTES crypto_auth_hmacsha512256_KEYBYTES +#define crypto_auth_IMPLEMENTATION crypto_auth_hmacsha512256_IMPLEMENTATION +#define crypto_auth_VERSION crypto_auth_hmacsha512256_VERSION +#define crypto_auth_hmacsha512256_tweet_BYTES 32 +#define crypto_auth_hmacsha512256_tweet_KEYBYTES 32 +extern int crypto_auth_hmacsha512256_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_auth_hmacsha512256_tweet_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +#define crypto_auth_hmacsha512256_tweet_VERSION "-" +#define crypto_auth_hmacsha512256 crypto_auth_hmacsha512256_tweet +#define crypto_auth_hmacsha512256_verify crypto_auth_hmacsha512256_tweet_verify +#define crypto_auth_hmacsha512256_BYTES crypto_auth_hmacsha512256_tweet_BYTES +#define crypto_auth_hmacsha512256_KEYBYTES crypto_auth_hmacsha512256_tweet_KEYBYTES +#define crypto_auth_hmacsha512256_VERSION crypto_auth_hmacsha512256_tweet_VERSION +#define crypto_auth_hmacsha512256_IMPLEMENTATION "crypto_auth/hmacsha512256/tweet" +#define crypto_box_PRIMITIVE "curve25519xsalsa20poly1305" +#define crypto_box crypto_box_curve25519xsalsa20poly1305 +#define crypto_box_open crypto_box_curve25519xsalsa20poly1305_open +#define crypto_box_keypair crypto_box_curve25519xsalsa20poly1305_keypair +#define crypto_box_beforenm crypto_box_curve25519xsalsa20poly1305_beforenm +#define crypto_box_afternm crypto_box_curve25519xsalsa20poly1305_afternm +#define crypto_box_open_afternm crypto_box_curve25519xsalsa20poly1305_open_afternm +#define crypto_box_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES +#define crypto_box_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES +#define crypto_box_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES +#define crypto_box_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_NONCEBYTES +#define crypto_box_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_ZEROBYTES +#define crypto_box_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES +#define crypto_box_IMPLEMENTATION crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION +#define crypto_box_VERSION crypto_box_curve25519xsalsa20poly1305_VERSION +#define crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES 24 +#define crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES 16 +extern int crypto_box_curve25519xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_keypair(unsigned char *,unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_beforenm(unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#define crypto_box_curve25519xsalsa20poly1305_tweet_VERSION "-" +#define crypto_box_curve25519xsalsa20poly1305 crypto_box_curve25519xsalsa20poly1305_tweet +#define crypto_box_curve25519xsalsa20poly1305_open crypto_box_curve25519xsalsa20poly1305_tweet_open +#define crypto_box_curve25519xsalsa20poly1305_keypair crypto_box_curve25519xsalsa20poly1305_tweet_keypair +#define crypto_box_curve25519xsalsa20poly1305_beforenm crypto_box_curve25519xsalsa20poly1305_tweet_beforenm +#define crypto_box_curve25519xsalsa20poly1305_afternm crypto_box_curve25519xsalsa20poly1305_tweet_afternm +#define crypto_box_curve25519xsalsa20poly1305_open_afternm crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm +#define crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES +#define crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES +#define crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES +#define crypto_box_curve25519xsalsa20poly1305_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES +#define crypto_box_curve25519xsalsa20poly1305_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES +#define crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES +#define crypto_box_curve25519xsalsa20poly1305_VERSION crypto_box_curve25519xsalsa20poly1305_tweet_VERSION +#define crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION "crypto_box/curve25519xsalsa20poly1305/tweet" +#define crypto_core_PRIMITIVE "salsa20" +#define crypto_core crypto_core_salsa20 +#define crypto_core_OUTPUTBYTES crypto_core_salsa20_OUTPUTBYTES +#define crypto_core_INPUTBYTES crypto_core_salsa20_INPUTBYTES +#define crypto_core_KEYBYTES crypto_core_salsa20_KEYBYTES +#define crypto_core_CONSTBYTES crypto_core_salsa20_CONSTBYTES +#define crypto_core_IMPLEMENTATION crypto_core_salsa20_IMPLEMENTATION +#define crypto_core_VERSION crypto_core_salsa20_VERSION +#define crypto_core_salsa20_tweet_OUTPUTBYTES 64 +#define crypto_core_salsa20_tweet_INPUTBYTES 16 +#define crypto_core_salsa20_tweet_KEYBYTES 32 +#define crypto_core_salsa20_tweet_CONSTBYTES 16 +extern int crypto_core_salsa20_tweet(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); +#define crypto_core_salsa20_tweet_VERSION "-" +#define crypto_core_salsa20 crypto_core_salsa20_tweet +#define crypto_core_salsa20_OUTPUTBYTES crypto_core_salsa20_tweet_OUTPUTBYTES +#define crypto_core_salsa20_INPUTBYTES crypto_core_salsa20_tweet_INPUTBYTES +#define crypto_core_salsa20_KEYBYTES crypto_core_salsa20_tweet_KEYBYTES +#define crypto_core_salsa20_CONSTBYTES crypto_core_salsa20_tweet_CONSTBYTES +#define crypto_core_salsa20_VERSION crypto_core_salsa20_tweet_VERSION +#define crypto_core_salsa20_IMPLEMENTATION "crypto_core/salsa20/tweet" +#define crypto_core_hsalsa20_tweet_OUTPUTBYTES 32 +#define crypto_core_hsalsa20_tweet_INPUTBYTES 16 +#define crypto_core_hsalsa20_tweet_KEYBYTES 32 +#define crypto_core_hsalsa20_tweet_CONSTBYTES 16 +extern int crypto_core_hsalsa20_tweet(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); +#define crypto_core_hsalsa20_tweet_VERSION "-" +#define crypto_core_hsalsa20 crypto_core_hsalsa20_tweet +#define crypto_core_hsalsa20_OUTPUTBYTES crypto_core_hsalsa20_tweet_OUTPUTBYTES +#define crypto_core_hsalsa20_INPUTBYTES crypto_core_hsalsa20_tweet_INPUTBYTES +#define crypto_core_hsalsa20_KEYBYTES crypto_core_hsalsa20_tweet_KEYBYTES +#define crypto_core_hsalsa20_CONSTBYTES crypto_core_hsalsa20_tweet_CONSTBYTES +#define crypto_core_hsalsa20_VERSION crypto_core_hsalsa20_tweet_VERSION +#define crypto_core_hsalsa20_IMPLEMENTATION "crypto_core/hsalsa20/tweet" +#define crypto_hashblocks_PRIMITIVE "sha512" +#define crypto_hashblocks crypto_hashblocks_sha512 +#define crypto_hashblocks_STATEBYTES crypto_hashblocks_sha512_STATEBYTES +#define crypto_hashblocks_BLOCKBYTES crypto_hashblocks_sha512_BLOCKBYTES +#define crypto_hashblocks_IMPLEMENTATION crypto_hashblocks_sha512_IMPLEMENTATION +#define crypto_hashblocks_VERSION crypto_hashblocks_sha512_VERSION +#define crypto_hashblocks_sha512_tweet_STATEBYTES 64 +#define crypto_hashblocks_sha512_tweet_BLOCKBYTES 128 +extern int crypto_hashblocks_sha512_tweet(unsigned char *,const unsigned char *,unsigned long long); +#define crypto_hashblocks_sha512_tweet_VERSION "-" +#define crypto_hashblocks_sha512 crypto_hashblocks_sha512_tweet +#define crypto_hashblocks_sha512_STATEBYTES crypto_hashblocks_sha512_tweet_STATEBYTES +#define crypto_hashblocks_sha512_BLOCKBYTES crypto_hashblocks_sha512_tweet_BLOCKBYTES +#define crypto_hashblocks_sha512_VERSION crypto_hashblocks_sha512_tweet_VERSION +#define crypto_hashblocks_sha512_IMPLEMENTATION "crypto_hashblocks/sha512/tweet" +#define crypto_hashblocks_sha256_tweet_STATEBYTES 32 +#define crypto_hashblocks_sha256_tweet_BLOCKBYTES 64 +extern int crypto_hashblocks_sha256_tweet(unsigned char *,const unsigned char *,unsigned long long); +#define crypto_hashblocks_sha256_tweet_VERSION "-" +#define crypto_hashblocks_sha256 crypto_hashblocks_sha256_tweet +#define crypto_hashblocks_sha256_STATEBYTES crypto_hashblocks_sha256_tweet_STATEBYTES +#define crypto_hashblocks_sha256_BLOCKBYTES crypto_hashblocks_sha256_tweet_BLOCKBYTES +#define crypto_hashblocks_sha256_VERSION crypto_hashblocks_sha256_tweet_VERSION +#define crypto_hashblocks_sha256_IMPLEMENTATION "crypto_hashblocks/sha256/tweet" +#define crypto_hash_PRIMITIVE "sha512" +#define crypto_hash crypto_hash_sha512 +#define crypto_hash_BYTES crypto_hash_sha512_BYTES +#define crypto_hash_IMPLEMENTATION crypto_hash_sha512_IMPLEMENTATION +#define crypto_hash_VERSION crypto_hash_sha512_VERSION +#define crypto_hash_sha512_tweet_BYTES 64 +extern int crypto_hash_sha512_tweet(unsigned char *,const unsigned char *,unsigned long long); +#define crypto_hash_sha512_tweet_VERSION "-" +#define crypto_hash_sha512 crypto_hash_sha512_tweet +#define crypto_hash_sha512_BYTES crypto_hash_sha512_tweet_BYTES +#define crypto_hash_sha512_VERSION crypto_hash_sha512_tweet_VERSION +#define crypto_hash_sha512_IMPLEMENTATION "crypto_hash/sha512/tweet" +#define crypto_hash_sha256_tweet_BYTES 32 +extern int crypto_hash_sha256_tweet(unsigned char *,const unsigned char *,unsigned long long); +#define crypto_hash_sha256_tweet_VERSION "-" +#define crypto_hash_sha256 crypto_hash_sha256_tweet +#define crypto_hash_sha256_BYTES crypto_hash_sha256_tweet_BYTES +#define crypto_hash_sha256_VERSION crypto_hash_sha256_tweet_VERSION +#define crypto_hash_sha256_IMPLEMENTATION "crypto_hash/sha256/tweet" +#define crypto_onetimeauth_PRIMITIVE "poly1305" +#define crypto_onetimeauth crypto_onetimeauth_poly1305 +#define crypto_onetimeauth_verify crypto_onetimeauth_poly1305_verify +#define crypto_onetimeauth_BYTES crypto_onetimeauth_poly1305_BYTES +#define crypto_onetimeauth_KEYBYTES crypto_onetimeauth_poly1305_KEYBYTES +#define crypto_onetimeauth_IMPLEMENTATION crypto_onetimeauth_poly1305_IMPLEMENTATION +#define crypto_onetimeauth_VERSION crypto_onetimeauth_poly1305_VERSION +#define crypto_onetimeauth_poly1305_tweet_BYTES 16 +#define crypto_onetimeauth_poly1305_tweet_KEYBYTES 32 +extern int crypto_onetimeauth_poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_onetimeauth_poly1305_tweet_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +#define crypto_onetimeauth_poly1305_tweet_VERSION "-" +#define crypto_onetimeauth_poly1305 crypto_onetimeauth_poly1305_tweet +#define crypto_onetimeauth_poly1305_verify crypto_onetimeauth_poly1305_tweet_verify +#define crypto_onetimeauth_poly1305_BYTES crypto_onetimeauth_poly1305_tweet_BYTES +#define crypto_onetimeauth_poly1305_KEYBYTES crypto_onetimeauth_poly1305_tweet_KEYBYTES +#define crypto_onetimeauth_poly1305_VERSION crypto_onetimeauth_poly1305_tweet_VERSION +#define crypto_onetimeauth_poly1305_IMPLEMENTATION "crypto_onetimeauth/poly1305/tweet" +#define crypto_scalarmult_PRIMITIVE "curve25519" +#define crypto_scalarmult crypto_scalarmult_curve25519 +#define crypto_scalarmult_base crypto_scalarmult_curve25519_base +#define crypto_scalarmult_BYTES crypto_scalarmult_curve25519_BYTES +#define crypto_scalarmult_SCALARBYTES crypto_scalarmult_curve25519_SCALARBYTES +#define crypto_scalarmult_IMPLEMENTATION crypto_scalarmult_curve25519_IMPLEMENTATION +#define crypto_scalarmult_VERSION crypto_scalarmult_curve25519_VERSION +#define crypto_scalarmult_curve25519_tweet_BYTES 32 +#define crypto_scalarmult_curve25519_tweet_SCALARBYTES 32 +extern int crypto_scalarmult_curve25519_tweet(unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_scalarmult_curve25519_tweet_base(unsigned char *,const unsigned char *); +#define crypto_scalarmult_curve25519_tweet_VERSION "-" +#define crypto_scalarmult_curve25519 crypto_scalarmult_curve25519_tweet +#define crypto_scalarmult_curve25519_base crypto_scalarmult_curve25519_tweet_base +#define crypto_scalarmult_curve25519_BYTES crypto_scalarmult_curve25519_tweet_BYTES +#define crypto_scalarmult_curve25519_SCALARBYTES crypto_scalarmult_curve25519_tweet_SCALARBYTES +#define crypto_scalarmult_curve25519_VERSION crypto_scalarmult_curve25519_tweet_VERSION +#define crypto_scalarmult_curve25519_IMPLEMENTATION "crypto_scalarmult/curve25519/tweet" +#define crypto_secretbox_PRIMITIVE "xsalsa20poly1305" +#define crypto_secretbox crypto_secretbox_xsalsa20poly1305 +#define crypto_secretbox_open crypto_secretbox_xsalsa20poly1305_open +#define crypto_secretbox_KEYBYTES crypto_secretbox_xsalsa20poly1305_KEYBYTES +#define crypto_secretbox_NONCEBYTES crypto_secretbox_xsalsa20poly1305_NONCEBYTES +#define crypto_secretbox_ZEROBYTES crypto_secretbox_xsalsa20poly1305_ZEROBYTES +#define crypto_secretbox_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES +#define crypto_secretbox_IMPLEMENTATION crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION +#define crypto_secretbox_VERSION crypto_secretbox_xsalsa20poly1305_VERSION +#define crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES 32 +#define crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES 24 +#define crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES 32 +#define crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES 16 +extern int crypto_secretbox_xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_secretbox_xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#define crypto_secretbox_xsalsa20poly1305_tweet_VERSION "-" +#define crypto_secretbox_xsalsa20poly1305 crypto_secretbox_xsalsa20poly1305_tweet +#define crypto_secretbox_xsalsa20poly1305_open crypto_secretbox_xsalsa20poly1305_tweet_open +#define crypto_secretbox_xsalsa20poly1305_KEYBYTES crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES +#define crypto_secretbox_xsalsa20poly1305_NONCEBYTES crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES +#define crypto_secretbox_xsalsa20poly1305_ZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES +#define crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES +#define crypto_secretbox_xsalsa20poly1305_VERSION crypto_secretbox_xsalsa20poly1305_tweet_VERSION +#define crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION "crypto_secretbox/xsalsa20poly1305/tweet" +#define crypto_sign_PRIMITIVE "ed25519" +#define crypto_sign crypto_sign_ed25519 +#define crypto_sign_open crypto_sign_ed25519_open +#define crypto_sign_keypair crypto_sign_ed25519_keypair +#define crypto_sign_BYTES crypto_sign_ed25519_BYTES +#define crypto_sign_PUBLICKEYBYTES crypto_sign_ed25519_PUBLICKEYBYTES +#define crypto_sign_SECRETKEYBYTES crypto_sign_ed25519_SECRETKEYBYTES +#define crypto_sign_IMPLEMENTATION crypto_sign_ed25519_IMPLEMENTATION +#define crypto_sign_VERSION crypto_sign_ed25519_VERSION +#define crypto_sign_ed25519_tweet_BYTES 64 +#define crypto_sign_ed25519_tweet_PUBLICKEYBYTES 32 +#define crypto_sign_ed25519_tweet_SECRETKEYBYTES 64 +extern int crypto_sign_ed25519_tweet(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_sign_ed25519_tweet_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_sign_ed25519_tweet_keypair(unsigned char *,unsigned char *); +#define crypto_sign_ed25519_tweet_VERSION "-" +#define crypto_sign_ed25519 crypto_sign_ed25519_tweet +#define crypto_sign_ed25519_open crypto_sign_ed25519_tweet_open +#define crypto_sign_ed25519_keypair crypto_sign_ed25519_tweet_keypair +#define crypto_sign_ed25519_BYTES crypto_sign_ed25519_tweet_BYTES +#define crypto_sign_ed25519_PUBLICKEYBYTES crypto_sign_ed25519_tweet_PUBLICKEYBYTES +#define crypto_sign_ed25519_SECRETKEYBYTES crypto_sign_ed25519_tweet_SECRETKEYBYTES +#define crypto_sign_ed25519_VERSION crypto_sign_ed25519_tweet_VERSION +#define crypto_sign_ed25519_IMPLEMENTATION "crypto_sign/ed25519/tweet" +#define crypto_stream_PRIMITIVE "xsalsa20" +#define crypto_stream crypto_stream_xsalsa20 +#define crypto_stream_xor crypto_stream_xsalsa20_xor +#define crypto_stream_KEYBYTES crypto_stream_xsalsa20_KEYBYTES +#define crypto_stream_NONCEBYTES crypto_stream_xsalsa20_NONCEBYTES +#define crypto_stream_IMPLEMENTATION crypto_stream_xsalsa20_IMPLEMENTATION +#define crypto_stream_VERSION crypto_stream_xsalsa20_VERSION +#define crypto_stream_xsalsa20_tweet_KEYBYTES 32 +#define crypto_stream_xsalsa20_tweet_NONCEBYTES 24 +extern int crypto_stream_xsalsa20_tweet(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_xsalsa20_tweet_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#define crypto_stream_xsalsa20_tweet_VERSION "-" +#define crypto_stream_xsalsa20 crypto_stream_xsalsa20_tweet +#define crypto_stream_xsalsa20_xor crypto_stream_xsalsa20_tweet_xor +#define crypto_stream_xsalsa20_KEYBYTES crypto_stream_xsalsa20_tweet_KEYBYTES +#define crypto_stream_xsalsa20_NONCEBYTES crypto_stream_xsalsa20_tweet_NONCEBYTES +#define crypto_stream_xsalsa20_VERSION crypto_stream_xsalsa20_tweet_VERSION +#define crypto_stream_xsalsa20_IMPLEMENTATION "crypto_stream/xsalsa20/tweet" +#define crypto_stream_salsa20_tweet_KEYBYTES 32 +#define crypto_stream_salsa20_tweet_NONCEBYTES 8 +extern int crypto_stream_salsa20_tweet(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_salsa20_tweet_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#define crypto_stream_salsa20_tweet_VERSION "-" +#define crypto_stream_salsa20 crypto_stream_salsa20_tweet +#define crypto_stream_salsa20_xor crypto_stream_salsa20_tweet_xor +#define crypto_stream_salsa20_KEYBYTES crypto_stream_salsa20_tweet_KEYBYTES +#define crypto_stream_salsa20_NONCEBYTES crypto_stream_salsa20_tweet_NONCEBYTES +#define crypto_stream_salsa20_VERSION crypto_stream_salsa20_tweet_VERSION +#define crypto_stream_salsa20_IMPLEMENTATION "crypto_stream/salsa20/tweet" +#define crypto_verify_PRIMITIVE "16" +#define crypto_verify crypto_verify_16 +#define crypto_verify_BYTES crypto_verify_16_BYTES +#define crypto_verify_IMPLEMENTATION crypto_verify_16_IMPLEMENTATION +#define crypto_verify_VERSION crypto_verify_16_VERSION +#define crypto_verify_16_tweet_BYTES 16 +extern int crypto_verify_16_tweet(const unsigned char *,const unsigned char *); +#define crypto_verify_16_tweet_VERSION "-" +#define crypto_verify_16 crypto_verify_16_tweet +#define crypto_verify_16_BYTES crypto_verify_16_tweet_BYTES +#define crypto_verify_16_VERSION crypto_verify_16_tweet_VERSION +#define crypto_verify_16_IMPLEMENTATION "crypto_verify/16/tweet" +#define crypto_verify_32_tweet_BYTES 32 +extern int crypto_verify_32_tweet(const unsigned char *,const unsigned char *); +#define crypto_verify_32_tweet_VERSION "-" +#define crypto_verify_32 crypto_verify_32_tweet +#define crypto_verify_32_BYTES crypto_verify_32_tweet_BYTES +#define crypto_verify_32_VERSION crypto_verify_32_tweet_VERSION +#define crypto_verify_32_IMPLEMENTATION "crypto_verify/32/tweet" +#endif diff --git a/vendors/ocaml-tweetnacl/src/tweetnacl.ml b/vendors/ocaml-tweetnacl/src/tweetnacl.ml new file mode 100644 index 000000000..ea14c4c6b --- /dev/null +++ b/vendors/ocaml-tweetnacl/src/tweetnacl.ml @@ -0,0 +1,468 @@ +(*--------------------------------------------------------------------------- + Copyright (c) 2017 Vincent Bernardoff. All rights reserved. + Distributed under the ISC license, see terms at the end of the file. + ---------------------------------------------------------------------------*) + +module Rand = struct + external randombytes : Cstruct.buffer -> int -> unit = + "ml_randombytes" [@@noalloc] + + let gen sz = + let cs = Cstruct.create_unsafe sz in + randombytes (Cstruct.to_bigarray cs) sz ; + cs + + let write cs = + Cstruct.(randombytes (to_bigarray cs) (len cs)) +end + +module Hash = struct + let bytes = 64 + + external sha512 : + Cstruct.buffer -> Cstruct.buffer -> int -> unit = + "ml_crypto_hash" [@@noalloc] + + let sha512 msg = + let q = Cstruct.create_unsafe bytes in + sha512 q.buffer msg.Cstruct.buffer (Cstruct.len msg) ; + q +end + +let cs_of_z cs z = + let bits = Z.to_bits z in + Cstruct.blit_from_string bits 0 cs 0 (String.length bits) + +let unopt_invalid_arg1 ~msg f cs = + match f cs with + | Some v -> v + | None -> invalid_arg msg + +module Nonce = struct + type t = Cstruct.t + let bytes = 24 + + let gen () = + Rand.gen bytes + + let rec incr_byte b step byteno = + let res = Cstruct.BE.get_uint16 b byteno + step in + let lo = res land 0xffff in + let hi = res asr 16 in + Cstruct.BE.set_uint16 b byteno lo ; + if hi = 0 || byteno = 0 then () + else incr_byte b hi (byteno - 2) + + let increment ?(step = 1) nonce = + let new_nonce = Cstruct.create_unsafe 24 in + Cstruct.blit nonce 0 new_nonce 0 24 ; + incr_byte new_nonce step 22 ; + new_nonce + + let of_cstruct cs = + try Some (Cstruct.sub cs 0 bytes) with _ -> None + + let of_cstruct_exn = + unopt_invalid_arg1 ~msg:"Box.Nonce.of_cstruct_exn" of_cstruct + + let to_cstruct nonce = nonce +end + +module Secretbox = struct + type key = Cstruct.t + + let keybytes = 32 + let zerobytes = 32 + let boxzerobytes = 16 + + let genkey () = + Rand.gen 32 + + let of_cstruct cs = + if Cstruct.len cs < keybytes then None + else Some (Cstruct.sub cs 0 keybytes) + + let of_cstruct_exn = + unopt_invalid_arg1 ~msg:"Secret_box.of_cstruct_exn" of_cstruct + + external secretbox : + Cstruct.buffer -> Cstruct.buffer -> + Cstruct.buffer -> Cstruct.buffer -> unit = "ml_secretbox" [@@noalloc] + + external secretbox_open : + Cstruct.buffer -> Cstruct.buffer -> + Cstruct.buffer -> Cstruct.buffer -> int = "ml_secretbox_open" [@@noalloc] + + let box ~key ~nonce ~msg = + let msglen = Cstruct.len msg in + let buflen = msglen + zerobytes in + let buf = Cstruct.create buflen in + Cstruct.blit msg 0 buf zerobytes msglen ; + secretbox + buf.buffer buf.buffer nonce.Cstruct.buffer key.Cstruct.buffer ; + Cstruct.sub buf boxzerobytes (buflen - boxzerobytes) + + let box_noalloc ~key ~nonce ~msg = + secretbox + msg.Cstruct.buffer msg.buffer nonce.Cstruct.buffer key.Cstruct.buffer + + let box_open ~key ~nonce ~cmsg = + let msglen = Cstruct.len cmsg - boxzerobytes in + let buf = Cstruct.create (zerobytes + msglen) in + Cstruct.blit cmsg 0 buf boxzerobytes (msglen + boxzerobytes) ; + match secretbox_open buf.buffer buf.buffer + nonce.Cstruct.buffer key.Cstruct.buffer with + | 0 -> Some (Cstruct.sub buf zerobytes msglen) + | _ -> None + + let box_open_noalloc ~key ~nonce ~cmsg = + match secretbox_open cmsg.Cstruct.buffer cmsg.buffer + nonce.Cstruct.buffer key.Cstruct.buffer with + | 0 -> true + | _ -> false +end + +module Box = struct + type secret + type public + type combined + type _ key = + | Sk : Cstruct.t -> secret key + | Pk : Cstruct.t -> public key + | Ck : Cstruct.t -> combined key + + let skbytes = 32 + let pkbytes = 32 + let beforenmbytes = 32 + let zerobytes = 32 + let boxzerobytes = 16 + + let to_cstruct : type a. a key -> Cstruct.t = function + | Pk cs -> cs + | Sk cs -> cs + | Ck cs -> cs + + let blit_to_cstruct : + type a. a key -> ?pos:int -> Cstruct.t -> unit = fun key ?(pos=0) cs -> + match key with + | Pk pk -> Cstruct.blit pk 0 cs pos pkbytes + | Sk sk -> Cstruct.blit sk 0 cs pos skbytes + | Ck ck -> Cstruct.blit ck 0 cs pos beforenmbytes + + let pp : type a. Format.formatter -> a key -> unit = fun ppf -> function + | Pk cs -> Format.fprintf ppf "P %a" Hex.pp (Hex.of_cstruct cs) + | Sk cs -> Format.fprintf ppf "S %a" Hex.pp (Hex.of_cstruct cs) + | Ck cs -> Format.fprintf ppf "C %a" Hex.pp (Hex.of_cstruct cs) + + let show t = Format.asprintf "%a" pp t + + let equal : + type a. a key -> a key -> bool = fun a b -> match a, b with + | Pk a, Pk b -> Cstruct.equal a b + | Sk a, Sk b -> Cstruct.equal a b + | Ck a, Ck b -> Cstruct.equal a b + + let sk_of_cstruct cs = + try Some (Sk (Cstruct.sub cs 0 skbytes)) with _ -> None + let pk_of_cstruct cs = + try Some (Pk (Cstruct.sub cs 0 pkbytes)) with _ -> None + let ck_of_cstruct cs = + try Some (Ck (Cstruct.sub cs 0 beforenmbytes)) with _ -> None + + let sk_of_cstruct_exn = + unopt_invalid_arg1 ~msg:"Box.sk_of_cstruct_exn" sk_of_cstruct + let pk_of_cstruct_exn = + unopt_invalid_arg1 ~msg:"Box.pk_of_cstruct_exn" pk_of_cstruct + let ck_of_cstruct_exn = + unopt_invalid_arg1 ~msg:"Box.ck_of_cstruct_exn" ck_of_cstruct + + external keypair : + Cstruct.buffer -> Cstruct.buffer -> unit = + "ml_crypto_box_keypair" [@@noalloc] + + let keypair () = + let sk = Cstruct.create skbytes in + let pk = Cstruct.create pkbytes in + keypair pk.buffer sk.buffer ; + Pk pk, Sk sk + + external box_stub : + Cstruct.buffer -> Cstruct.buffer -> Cstruct.buffer -> + Cstruct.buffer -> Cstruct.buffer -> unit = + "ml_crypto_box" [@@noalloc] + + let box ~pk:(Pk pk) ~sk:(Sk sk) ~nonce ~msg = + let msglen = Cstruct.len msg in + let buflen = msglen + zerobytes in + let buf = Cstruct.create buflen in + Cstruct.blit msg 0 buf zerobytes msglen ; + box_stub + buf.buffer buf.buffer nonce.Cstruct.buffer pk.buffer sk.buffer ; + Cstruct.sub buf boxzerobytes (buflen - boxzerobytes) + + let box_noalloc ~pk:(Pk pk) ~sk:(Sk sk) ~nonce ~msg = + box_stub + msg.Cstruct.buffer msg.buffer nonce.Cstruct.buffer pk.buffer sk.buffer + + external box_open_stub : + Cstruct.buffer -> Cstruct.buffer -> Cstruct.buffer -> + Cstruct.buffer -> Cstruct.buffer -> int = + "ml_crypto_box_open" [@@noalloc] + + let box_open ~pk:(Pk pk) ~sk:(Sk sk) ~nonce ~cmsg = + let msglen = Cstruct.len cmsg - boxzerobytes in + let buf = Cstruct.create (zerobytes + msglen) in + Cstruct.blit cmsg 0 buf boxzerobytes (msglen + boxzerobytes) ; + match box_open_stub buf.buffer buf.buffer + nonce.Cstruct.buffer pk.buffer sk.buffer with + | 0 -> Some (Cstruct.sub buf zerobytes msglen) + | _ -> None + + let box_open_noalloc ~pk:(Pk pk) ~sk:(Sk sk) ~nonce ~cmsg = + match box_open_stub cmsg.Cstruct.buffer cmsg.buffer + nonce.Cstruct.buffer pk.buffer sk.buffer with + | 0 -> true + | _ -> false + + external box_beforenm : + Cstruct.buffer -> Cstruct.buffer -> Cstruct.buffer -> unit = + "ml_crypto_box_beforenm" [@@noalloc] + + let combine (Pk pk) (Sk sk) = + let combined = Cstruct.create_unsafe beforenmbytes in + box_beforenm combined.buffer pk.buffer sk.buffer ; + Ck combined + + external box_afternm : + Cstruct.buffer -> Cstruct.buffer -> + Cstruct.buffer -> Cstruct.buffer -> unit = + "ml_crypto_box_afternm" [@@noalloc] + + let box_combined ~k:(Ck k) ~nonce ~msg = + let msglen = Cstruct.len msg in + let buflen = msglen + zerobytes in + let buf = Cstruct.create buflen in + Cstruct.blit msg 0 buf zerobytes msglen ; + box_afternm buf.buffer buf.buffer nonce.Cstruct.buffer k.buffer ; + Cstruct.sub buf boxzerobytes (buflen - boxzerobytes) + + let box_combined_noalloc ~k:(Ck k) ~nonce ~msg = + box_afternm msg.Cstruct.buffer msg.buffer nonce.Cstruct.buffer k.buffer + + external box_open_afternm : + Cstruct.buffer -> Cstruct.buffer -> + Cstruct.buffer -> Cstruct.buffer -> int = + "ml_crypto_box_open_afternm" [@@noalloc] + + let box_open_combined ~k:(Ck k) ~nonce ~cmsg = + let msglen = Cstruct.len cmsg - boxzerobytes in + let buflen = msglen + zerobytes in + let buf = Cstruct.create buflen in + Cstruct.blit cmsg 0 buf boxzerobytes (msglen + boxzerobytes) ; + match box_open_afternm buf.buffer buf.buffer + nonce.Cstruct.buffer k.buffer with + | 0 -> Some (Cstruct.sub buf zerobytes msglen) + | _ -> None + + let box_open_combined_noalloc ~k:(Ck k) ~nonce ~cmsg = + match box_open_afternm cmsg.Cstruct.buffer cmsg.buffer + nonce.Cstruct.buffer k.buffer with + | 0 -> true + | _ -> false +end + +module Sign = struct + type secret + type extended + type public + type _ key = + | Sk : Cstruct.t -> secret key + | Ek : Cstruct.t -> extended key + | Pk : Cstruct.t -> public key + + let bytes = 64 + let pkbytes = 32 + let skbytes = 64 + let ekbytes = 64 + let seedbytes = 32 + + let sk_of_cstruct cs = + try Some (Sk (Cstruct.sub cs 0 skbytes)) with _ -> None + let ek_of_cstruct cs = + try Some (Ek (Cstruct.sub cs 0 ekbytes)) with _ -> None + let pk_of_cstruct cs = + try Some (Pk (Cstruct.sub cs 0 pkbytes)) with _ -> None + + let sk_of_cstruct_exn = + unopt_invalid_arg1 ~msg:"Sign.sk_of_cstruct_exn" sk_of_cstruct + let ek_of_cstruct_exn = + unopt_invalid_arg1 ~msg:"Sign.ek_of_cstruct_exn" ek_of_cstruct + let pk_of_cstruct_exn = + unopt_invalid_arg1 ~msg:"Sign.pk_of_cstruct_exn" pk_of_cstruct + + let to_cstruct : type a. a key -> Cstruct.t = function + | Pk cs -> cs + | Sk cs -> cs + | Ek cs -> cs + + let seed (Sk cs) = Cstruct.sub cs 0 seedbytes + + let blit_to_cstruct : + type a. a key -> ?pos:int -> Cstruct.t -> unit = fun key ?(pos=0) cs -> + match key with + | Pk pk -> Cstruct.blit pk 0 cs pos pkbytes + | Sk sk -> Cstruct.blit sk 0 cs pos skbytes + | Ek ek -> Cstruct.blit ek 0 cs pos ekbytes + + let pp : type a. Format.formatter -> a key -> unit = fun ppf -> function + | Pk cs -> Format.fprintf ppf "P %a" Hex.pp (Hex.of_cstruct cs) + | Sk cs -> Format.fprintf ppf "S %a" Hex.pp (Hex.of_cstruct cs) + | Ek cs -> Format.fprintf ppf "E %a" Hex.pp (Hex.of_cstruct cs) + + let show t = Format.asprintf "%a" pp t + + let equal : + type a. a key -> a key -> bool = fun a b -> match a, b with + | Pk a, Pk b -> Cstruct.equal a b + | Sk a, Sk b -> Cstruct.equal a b + | Ek a, Ek b -> Cstruct.equal a b + + external keypair : + Cstruct.buffer -> Cstruct.buffer -> unit = + "ml_crypto_sign_keypair" [@@noalloc] + + external keypair_seed : + Cstruct.buffer -> Cstruct.buffer -> unit = + "ml_crypto_sign_keypair_seed" [@@noalloc] + + let keypair ?seed () = + let pk = Cstruct.create_unsafe pkbytes in + let sk = Cstruct.create_unsafe skbytes in + begin match seed with + | None -> + Cstruct.(keypair (to_bigarray pk) (to_bigarray sk)) + | Some cs -> + if Cstruct.len cs < seedbytes then + invalid_arg "Sign.keypair: seed must be at least 32 bytes long" ; + Cstruct.blit cs 0 sk 0 pkbytes ; + Cstruct.(keypair_seed (to_bigarray pk) (to_bigarray sk)) + end ; + Pk pk, Sk sk + + let extended (Sk sk) = + let cs = Hash.sha512 (Cstruct.sub sk 0 pkbytes) in + Cstruct.(set_uint8 cs 0 (get_uint8 cs 0 land 248)) ; + Cstruct.(set_uint8 cs 31 (get_uint8 cs 31 land 127)) ; + Cstruct.(set_uint8 cs 31 (get_uint8 cs 31 lor 64)) ; + Ek cs + + external sign : + Cstruct.buffer -> Cstruct.buffer -> unit = + "ml_crypto_sign" [@@noalloc] + + external sign_extended : + Cstruct.buffer -> Cstruct.buffer -> unit = + "ml_crypto_sign_extended" [@@noalloc] + + let sign ~key:(Sk sk) msg = + let msglen = Cstruct.len msg in + let cs = Cstruct.create_unsafe (bytes + msglen) in + Cstruct.blit msg 0 cs bytes msglen ; + Cstruct.(sign (to_bigarray cs) (to_bigarray sk)) ; + cs + + let sign_extended ~key:(Ek ek) msg = + let msglen = Cstruct.len msg in + let cs = Cstruct.create_unsafe (bytes + msglen) in + Cstruct.blit msg 0 cs bytes msglen ; + Cstruct.(sign_extended (to_bigarray cs) (to_bigarray ek)) ; + cs + + let detached ~key msg = + Cstruct.sub (sign ~key msg) 0 bytes + + let detached_extended ~key msg = + Cstruct.sub (sign_extended ~key msg) 0 bytes + + external verify : + Cstruct.buffer -> Cstruct.buffer -> Cstruct.buffer -> Cstruct.buffer -> int = + "ml_crypto_sign_open" [@@noalloc] + + let verify ~key:(Pk pk) smsg = + let mlen = Cstruct.create_unsafe 8 in + let msg = Cstruct.(create (len smsg)) in + let ret = Cstruct.(verify + (to_bigarray msg) (to_bigarray mlen) + (to_bigarray smsg) (to_bigarray pk)) in + match ret with + | 0 -> + let len = Cstruct.LE.get_uint64 mlen 0 |> Int64.to_int in + Some (Cstruct.sub msg 0 len) + | _ -> None + + let verify_detached ~key ~signature msg = + let cs = Cstruct.create_unsafe (bytes + Cstruct.len msg) in + Cstruct.blit signature 0 cs 0 bytes ; + Cstruct.blit msg 0 cs bytes (Cstruct.len msg) ; + match verify ~key cs with + | None -> false + | Some _ -> true + + external add : + Cstruct.buffer -> Cstruct.buffer -> unit = + "ml_add" [@@noalloc] + + let add (Pk p) (Pk q) = + let cs = Cstruct.create_unsafe pkbytes in + Cstruct.blit p 0 cs 0 pkbytes ; + Cstruct.(add (to_bigarray cs) (to_bigarray q)) ; + Pk cs + + external mult : + Cstruct.buffer -> Cstruct.buffer -> Cstruct.buffer -> unit = + "ml_scalarmult" [@@noalloc] + + external base : + Cstruct.buffer -> Cstruct.buffer -> unit = + "ml_scalarbase" [@@noalloc] + + let mult (Pk q) s = + let r = Cstruct.create_unsafe pkbytes in + let scalar = Cstruct.create_unsafe pkbytes in + cs_of_z scalar s ; + Cstruct.(mult (to_bigarray r) (to_bigarray q) (to_bigarray scalar)) ; + Pk r + + let base_direct s = + let cs = Cstruct.create_unsafe pkbytes in + Cstruct.(base (to_bigarray cs) (to_bigarray s)) ; + cs + + let base s = + let r = Cstruct.create_unsafe pkbytes in + let scalar = Cstruct.create_unsafe pkbytes in + cs_of_z scalar s ; + Cstruct.(base (to_bigarray r) (to_bigarray scalar)) ; + Pk r + + let public : type a. a key -> public key = function + | Pk _ as pk -> pk + | Sk cs -> Pk (Cstruct.sub cs 32 32) + | Ek cs -> Pk (base_direct (Cstruct.sub cs 0 32)) +end + +(*--------------------------------------------------------------------------- + Copyright (c) 2017 Vincent Bernardoff + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + ---------------------------------------------------------------------------*) diff --git a/vendors/ocaml-tweetnacl/src/tweetnacl.mli b/vendors/ocaml-tweetnacl/src/tweetnacl.mli new file mode 100644 index 000000000..60951fc3e --- /dev/null +++ b/vendors/ocaml-tweetnacl/src/tweetnacl.mli @@ -0,0 +1,158 @@ +(*--------------------------------------------------------------------------- + Copyright (c) 2017 Vincent Bernardoff. All rights reserved. + Distributed under the ISC license, see terms at the end of the file. + ---------------------------------------------------------------------------*) + +module Rand : sig + val gen : int -> Cstruct.t + val write : Cstruct.t -> unit +end + +module Hash : sig + val sha512 : Cstruct.t -> Cstruct.t +end + +module Nonce : sig + type t + val bytes : int + val gen : unit -> t + val increment : ?step:int -> t -> t + val of_cstruct : Cstruct.t -> t option + val of_cstruct_exn : Cstruct.t -> t + val to_cstruct : t -> Cstruct.t +end + +module Secretbox : sig + type key + + val keybytes : int + val zerobytes : int + val boxzerobytes : int + + val genkey : unit -> key + val of_cstruct : Cstruct.t -> key option + val of_cstruct_exn : Cstruct.t -> key + + val box : key:key -> nonce:Nonce.t -> msg:Cstruct.t -> Cstruct.t + val box_open : key:key -> nonce:Nonce.t -> cmsg:Cstruct.t -> Cstruct.t option + + val box_noalloc : key:key -> nonce:Nonce.t -> msg:Cstruct.t -> unit + val box_open_noalloc : key:key -> nonce:Nonce.t -> cmsg:Cstruct.t -> bool +end + +module Box : sig + type secret + type public + type combined + + type _ key + + val skbytes : int + val pkbytes : int + val beforenmbytes : int + val zerobytes : int + val boxzerobytes : int + + val pp : Format.formatter -> _ key -> unit + val show : _ key -> string + val equal : 'a key -> 'a key -> bool + val to_cstruct : _ key -> Cstruct.t + val blit_to_cstruct : _ key -> ?pos:int -> Cstruct.t -> unit + + val sk_of_cstruct : Cstruct.t -> secret key option + val pk_of_cstruct : Cstruct.t -> public key option + val ck_of_cstruct : Cstruct.t -> combined key option + + val sk_of_cstruct_exn : Cstruct.t -> secret key + val pk_of_cstruct_exn : Cstruct.t -> public key + val ck_of_cstruct_exn : Cstruct.t -> combined key + + val keypair : unit -> public key * secret key + + val box : + pk:public key -> sk:secret key -> + nonce:Nonce.t -> msg:Cstruct.t -> Cstruct.t + val box_open : + pk:public key -> sk:secret key -> + nonce:Nonce.t -> cmsg:Cstruct.t -> Cstruct.t option + + val box_noalloc : + pk:public key -> sk:secret key -> + nonce:Nonce.t -> msg:Cstruct.t -> unit + val box_open_noalloc : + pk:public key -> sk:secret key -> + nonce:Nonce.t -> cmsg:Cstruct.t -> bool + + val combine : public key -> secret key -> combined key + val box_combined : + k:combined key -> nonce:Nonce.t -> msg:Cstruct.t -> Cstruct.t + val box_open_combined : + k:combined key -> nonce:Nonce.t -> cmsg:Cstruct.t -> Cstruct.t option + + val box_combined_noalloc : + k:combined key -> nonce:Nonce.t -> msg:Cstruct.t -> unit + val box_open_combined_noalloc : + k:combined key -> nonce:Nonce.t -> cmsg:Cstruct.t -> bool +end + +module Sign : sig + type secret + type extended + type public + type _ key + + val bytes : int + val pkbytes : int + val skbytes : int + val ekbytes : int + val seedbytes : int + + val pp : Format.formatter -> _ key -> unit + val show : _ key -> string + val to_cstruct : _ key -> Cstruct.t + val blit_to_cstruct : _ key -> ?pos:int -> Cstruct.t -> unit + + val sk_of_cstruct : Cstruct.t -> secret key option + val ek_of_cstruct : Cstruct.t -> extended key option + val pk_of_cstruct : Cstruct.t -> public key option + + val sk_of_cstruct_exn : Cstruct.t -> secret key + val ek_of_cstruct_exn : Cstruct.t -> extended key + val pk_of_cstruct_exn : Cstruct.t -> public key + + val keypair : ?seed:Cstruct.t -> unit -> public key * secret key + val equal : 'a key -> 'a key -> bool + + val extended : secret key -> extended key + val seed : secret key -> Cstruct.t + val public : _ key -> public key + + val sign : key:secret key -> Cstruct.t -> Cstruct.t + val sign_extended : key:extended key -> Cstruct.t -> Cstruct.t + + val detached : key:secret key -> Cstruct.t -> Cstruct.t + val detached_extended : key:extended key -> Cstruct.t -> Cstruct.t + + val verify : key:public key -> Cstruct.t -> Cstruct.t option + val verify_detached : key:public key -> signature:Cstruct.t -> Cstruct.t -> bool + + val add : public key -> public key -> public key + val mult : public key -> Z.t -> public key + val base : Z.t -> public key +end + +(*--------------------------------------------------------------------------- + Copyright (c) 2017 Vincent Bernardoff + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + ---------------------------------------------------------------------------*) diff --git a/vendors/ocaml-tweetnacl/src/tweetnacl_stubs.c b/vendors/ocaml-tweetnacl/src/tweetnacl_stubs.c new file mode 100644 index 000000000..197754e31 --- /dev/null +++ b/vendors/ocaml-tweetnacl/src/tweetnacl_stubs.c @@ -0,0 +1,1068 @@ +#include "tweetnacl.h" +#define FOR(i,n) for (i = 0;i < n;++i) +#define sv static void + +typedef unsigned char u8; +typedef unsigned long u32; +typedef unsigned long long u64; +typedef long long i64; +typedef i64 gf[16]; + +#include +#include +#include +#include + +/* it's really stupid that there isn't a syscall for this */ + +static int fd = -1; + +void randombytes(u8 *x,u64 xlen) +{ + int i; + + if (fd == -1) { + for (;;) { + fd = open("/dev/urandom",O_RDONLY); + if (fd != -1) break; + sleep(1); + } + } + + while (xlen > 0) { + if (xlen < 1048576) i = xlen; else i = 1048576; + + i = read(fd,x,i); + if (i < 1) { + sleep(1); + continue; + } + + x += i; + xlen -= i; + } +} + +static const u8 + _0[16], + _9[32] = {9}; +static const gf + gf0, + gf1 = {1}, + _121665 = {0xDB41,1}, + D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203}, + D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406}, + X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169}, + Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666}, + I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83}; + +static u32 L32(u32 x,int c) { return (x << c) | ((x&0xffffffff) >> (32 - c)); } + +static u32 ld32(const u8 *x) +{ + u32 u = x[3]; + u = (u<<8)|x[2]; + u = (u<<8)|x[1]; + return (u<<8)|x[0]; +} + +static u64 dl64(const u8 *x) +{ + u64 i,u=0; + FOR(i,8) u=(u<<8)|x[i]; + return u; +} + +sv st32(u8 *x,u32 u) +{ + int i; + FOR(i,4) { x[i] = u; u >>= 8; } +} + +sv ts64(u8 *x,u64 u) +{ + int i; + for (i = 7;i >= 0;--i) { x[i] = u; u >>= 8; } +} + +static int vn(const u8 *x,const u8 *y,int n) +{ + u32 i,d = 0; + FOR(i,n) d |= x[i]^y[i]; + return (1 & ((d - 1) >> 8)) - 1; +} + +int crypto_verify_16(const u8 *x,const u8 *y) +{ + return vn(x,y,16); +} + +int crypto_verify_32(const u8 *x,const u8 *y) +{ + return vn(x,y,32); +} + +sv core(u8 *out,const u8 *in,const u8 *k,const u8 *c,int h) +{ + u32 w[16],x[16],y[16],t[4]; + int i,j,m; + + FOR(i,4) { + x[5*i] = ld32(c+4*i); + x[1+i] = ld32(k+4*i); + x[6+i] = ld32(in+4*i); + x[11+i] = ld32(k+16+4*i); + } + + FOR(i,16) y[i] = x[i]; + + FOR(i,20) { + FOR(j,4) { + FOR(m,4) t[m] = x[(5*j+4*m)%16]; + t[1] ^= L32(t[0]+t[3], 7); + t[2] ^= L32(t[1]+t[0], 9); + t[3] ^= L32(t[2]+t[1],13); + t[0] ^= L32(t[3]+t[2],18); + FOR(m,4) w[4*j+(j+m)%4] = t[m]; + } + FOR(m,16) x[m] = w[m]; + } + + if (h) { + FOR(i,16) x[i] += y[i]; + FOR(i,4) { + x[5*i] -= ld32(c+4*i); + x[6+i] -= ld32(in+4*i); + } + FOR(i,4) { + st32(out+4*i,x[5*i]); + st32(out+16+4*i,x[6+i]); + } + } else + FOR(i,16) st32(out + 4 * i,x[i] + y[i]); +} + +int crypto_core_salsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c) +{ + core(out,in,k,c,0); + return 0; +} + +int crypto_core_hsalsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c) +{ + core(out,in,k,c,1); + return 0; +} + +static const u8 sigma[16] = "expand 32-byte k"; + +int crypto_stream_salsa20_xor(u8 *c,const u8 *m,u64 b,const u8 *n,const u8 *k) +{ + u8 z[16],x[64]; + u32 u,i; + if (!b) return 0; + FOR(i,16) z[i] = 0; + FOR(i,8) z[i] = n[i]; + while (b >= 64) { + crypto_core_salsa20(x,z,k,sigma); + FOR(i,64) c[i] = (m?m[i]:0) ^ x[i]; + u = 1; + for (i = 8;i < 16;++i) { + u += (u32) z[i]; + z[i] = u; + u >>= 8; + } + b -= 64; + c += 64; + if (m) m += 64; + } + if (b) { + crypto_core_salsa20(x,z,k,sigma); + FOR(i,b) c[i] = (m?m[i]:0) ^ x[i]; + } + return 0; +} + +int crypto_stream_salsa20(u8 *c,u64 d,const u8 *n,const u8 *k) +{ + return crypto_stream_salsa20_xor(c,0,d,n,k); +} + +int crypto_stream(u8 *c,u64 d,const u8 *n,const u8 *k) +{ + u8 s[32]; + crypto_core_hsalsa20(s,n,k,sigma); + return crypto_stream_salsa20(c,d,n+16,s); +} + +int crypto_stream_xor(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k) +{ + u8 s[32]; + crypto_core_hsalsa20(s,n,k,sigma); + return crypto_stream_salsa20_xor(c,m,d,n+16,s); +} + +sv add1305(u32 *h,const u32 *c) +{ + u32 j,u = 0; + FOR(j,17) { + u += h[j] + c[j]; + h[j] = u & 255; + u >>= 8; + } +} + +static const u32 minusp[17] = { + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252 +} ; + +int crypto_onetimeauth(u8 *out,const u8 *m,u64 n,const u8 *k) +{ + u32 s,i,j,u,x[17],r[17],h[17],c[17],g[17]; + + FOR(j,17) r[j]=h[j]=0; + FOR(j,16) r[j]=k[j]; + r[3]&=15; + r[4]&=252; + r[7]&=15; + r[8]&=252; + r[11]&=15; + r[12]&=252; + r[15]&=15; + + while (n > 0) { + FOR(j,17) c[j] = 0; + for (j = 0;(j < 16) && (j < n);++j) c[j] = m[j]; + c[j] = 1; + m += j; n -= j; + add1305(h,c); + FOR(i,17) { + x[i] = 0; + FOR(j,17) x[i] += h[j] * ((j <= i) ? r[i - j] : 320 * r[i + 17 - j]); + } + FOR(i,17) h[i] = x[i]; + u = 0; + FOR(j,16) { + u += h[j]; + h[j] = u & 255; + u >>= 8; + } + u += h[16]; h[16] = u & 3; + u = 5 * (u >> 2); + FOR(j,16) { + u += h[j]; + h[j] = u & 255; + u >>= 8; + } + u += h[16]; h[16] = u; + } + + FOR(j,17) g[j] = h[j]; + add1305(h,minusp); + s = -(h[16] >> 7); + FOR(j,17) h[j] ^= s & (g[j] ^ h[j]); + + FOR(j,16) c[j] = k[j + 16]; + c[16] = 0; + add1305(h,c); + FOR(j,16) out[j] = h[j]; + return 0; +} + +int crypto_onetimeauth_verify(const u8 *h,const u8 *m,u64 n,const u8 *k) +{ + u8 x[16]; + crypto_onetimeauth(x,m,n,k); + return crypto_verify_16(h,x); +} + +int crypto_secretbox(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k) +{ + int i; + if (d < 32) return -1; + crypto_stream_xor(c,m,d,n,k); + crypto_onetimeauth(c + 16,c + 32,d - 32,c); + FOR(i,16) c[i] = 0; + return 0; +} + +int crypto_secretbox_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k) +{ + int i; + u8 x[32]; + if (d < 32) return -1; + crypto_stream(x,32,n,k); + if (crypto_onetimeauth_verify(c + 16,c + 32,d - 32,x) != 0) return -1; + crypto_stream_xor(m,c,d,n,k); + FOR(i,32) m[i] = 0; + return 0; +} + +sv set25519(gf r, const gf a) +{ + int i; + FOR(i,16) r[i]=a[i]; +} + +sv car25519(gf o) +{ + int i; + i64 c; + FOR(i,16) { + o[i]+=(1LL<<16); + c=o[i]>>16; + o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15); + o[i]-=c<<16; + } +} + +sv sel25519(gf p,gf q,int b) +{ + i64 t,i,c=~(b-1); + FOR(i,16) { + t= c&(p[i]^q[i]); + p[i]^=t; + q[i]^=t; + } +} + +sv pack25519(u8 *o,const gf n) +{ + int i,j,b; + gf m,t; + FOR(i,16) t[i]=n[i]; + car25519(t); + car25519(t); + car25519(t); + FOR(j,2) { + m[0]=t[0]-0xffed; + for(i=1;i<15;i++) { + m[i]=t[i]-0xffff-((m[i-1]>>16)&1); + m[i-1]&=0xffff; + } + m[15]=t[15]-0x7fff-((m[14]>>16)&1); + b=(m[15]>>16)&1; + m[14]&=0xffff; + sel25519(t,m,1-b); + } + FOR(i,16) { + o[2*i]=t[i]&0xff; + o[2*i+1]=t[i]>>8; + } +} + +static int neq25519(const gf a, const gf b) +{ + u8 c[32],d[32]; + pack25519(c,a); + pack25519(d,b); + return crypto_verify_32(c,d); +} + +static u8 par25519(const gf a) +{ + u8 d[32]; + pack25519(d,a); + return d[0]&1; +} + +sv unpack25519(gf o, const u8 *n) +{ + int i; + FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8); + o[15]&=0x7fff; +} + +sv A(gf o,const gf a,const gf b) +{ + int i; + FOR(i,16) o[i]=a[i]+b[i]; +} + +sv Z(gf o,const gf a,const gf b) +{ + int i; + FOR(i,16) o[i]=a[i]-b[i]; +} + +sv M(gf o,const gf a,const gf b) +{ + i64 i,j,t[31]; + FOR(i,31) t[i]=0; + FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j]; + FOR(i,15) t[i]+=38*t[i+16]; + FOR(i,16) o[i]=t[i]; + car25519(o); + car25519(o); +} + +sv S(gf o,const gf a) +{ + M(o,a,a); +} + +sv inv25519(gf o,const gf i) +{ + gf c; + int a; + FOR(a,16) c[a]=i[a]; + for(a=253;a>=0;a--) { + S(c,c); + if(a!=2&&a!=4) M(c,c,i); + } + FOR(a,16) o[a]=c[a]; +} + +sv pow2523(gf o,const gf i) +{ + gf c; + int a; + FOR(a,16) c[a]=i[a]; + for(a=250;a>=0;a--) { + S(c,c); + if(a!=1) M(c,c,i); + } + FOR(a,16) o[a]=c[a]; +} + +int crypto_scalarmult(u8 *q,const u8 *n,const u8 *p) +{ + u8 z[32]; + i64 x[80],r,i; + gf a,b,c,d,e,f; + FOR(i,31) z[i]=n[i]; + z[31]=(n[31]&127)|64; + z[0]&=248; + unpack25519(x,p); + FOR(i,16) { + b[i]=x[i]; + d[i]=a[i]=c[i]=0; + } + a[0]=d[0]=1; + for(i=254;i>=0;--i) { + r=(z[i>>3]>>(i&7))&1; + sel25519(a,b,r); + sel25519(c,d,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,_121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + sel25519(a,b,r); + sel25519(c,d,r); + } + FOR(i,16) { + x[i+16]=a[i]; + x[i+32]=c[i]; + x[i+48]=b[i]; + x[i+64]=d[i]; + } + inv25519(x+32,x+32); + M(x+16,x+16,x+32); + pack25519(q,x+16); + return 0; +} + +int crypto_scalarmult_base(u8 *q,const u8 *n) +{ + return crypto_scalarmult(q,n,_9); +} + +int crypto_box_keypair(u8 *y,u8 *x) +{ + randombytes(x,32); + return crypto_scalarmult_base(y,x); +} + +int crypto_box_beforenm(u8 *k,const u8 *y,const u8 *x) +{ + u8 s[32]; + crypto_scalarmult(s,x,y); + return crypto_core_hsalsa20(k,_0,s,sigma); +} + +int crypto_box_afternm(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k) +{ + return crypto_secretbox(c,m,d,n,k); +} + +int crypto_box_open_afternm(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k) +{ + return crypto_secretbox_open(m,c,d,n,k); +} + +int crypto_box(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *y,const u8 *x) +{ + u8 k[32]; + crypto_box_beforenm(k,y,x); + return crypto_box_afternm(c,m,d,n,k); +} + +int crypto_box_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *y,const u8 *x) +{ + u8 k[32]; + crypto_box_beforenm(k,y,x); + return crypto_box_open_afternm(m,c,d,n,k); +} + +static u64 R(u64 x,int c) { return (x >> c) | (x << (64 - c)); } +static u64 Ch(u64 x,u64 y,u64 z) { return (x & y) ^ (~x & z); } +static u64 Maj(u64 x,u64 y,u64 z) { return (x & y) ^ (x & z) ^ (y & z); } +static u64 Sigma0(u64 x) { return R(x,28) ^ R(x,34) ^ R(x,39); } +static u64 Sigma1(u64 x) { return R(x,14) ^ R(x,18) ^ R(x,41); } +static u64 sigma0(u64 x) { return R(x, 1) ^ R(x, 8) ^ (x >> 7); } +static u64 sigma1(u64 x) { return R(x,19) ^ R(x,61) ^ (x >> 6); } + +static const u64 K[80] = +{ + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +}; + +int crypto_hashblocks(u8 *x,const u8 *m,u64 n) +{ + u64 z[8],b[8],a[8],w[16],t; + int i,j; + + FOR(i,8) z[i] = a[i] = dl64(x + 8 * i); + + while (n >= 128) { + FOR(i,16) w[i] = dl64(m + 8 * i); + + FOR(i,80) { + FOR(j,8) b[j] = a[j]; + t = a[7] + Sigma1(a[4]) + Ch(a[4],a[5],a[6]) + K[i] + w[i%16]; + b[7] = t + Sigma0(a[0]) + Maj(a[0],a[1],a[2]); + b[3] += t; + FOR(j,8) a[(j+1)%8] = b[j]; + if (i%16 == 15) + FOR(j,16) + w[j] += w[(j+9)%16] + sigma0(w[(j+1)%16]) + sigma1(w[(j+14)%16]); + } + + FOR(i,8) { a[i] += z[i]; z[i] = a[i]; } + + m += 128; + n -= 128; + } + + FOR(i,8) ts64(x+8*i,z[i]); + + return n; +} + +static const u8 iv[64] = { + 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, + 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, + 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, + 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, + 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, + 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, + 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, + 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 +} ; + +int crypto_hash(u8 *out,const u8 *m,u64 n) +{ + u8 h[64],x[256]; + u64 i,b = n; + + FOR(i,64) h[i] = iv[i]; + + crypto_hashblocks(h,m,n); + m += n; + n &= 127; + m -= n; + + FOR(i,256) x[i] = 0; + FOR(i,n) x[i] = m[i]; + x[n] = 128; + + n = 256-128*(n<112); + x[n-9] = b >> 61; + ts64(x+n-8,b<<3); + crypto_hashblocks(h,x,n); + + FOR(i,64) out[i] = h[i]; + + return 0; +} + +sv add(gf p[4],gf q[4]) +{ + gf a,b,c,d,t,e,f,g,h; + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); +} + +sv cswap(gf p[4],gf q[4],u8 b) +{ + int i; + FOR(i,4) + sel25519(p[i],q[i],b); +} + +sv pack(u8 *r,gf p[4]) +{ + gf tx, ty, zi; + inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + pack25519(r, ty); + r[31] ^= par25519(tx) << 7; +} + +sv scalarmult(gf p[4],gf q[4],const u8 *s) +{ + int i; + set25519(p[0],gf0); + set25519(p[1],gf1); + set25519(p[2],gf1); + set25519(p[3],gf0); + for (i = 255;i >= 0;--i) { + u8 b = (s[i/8]>>(i&7))&1; + cswap(p,q,b); + add(q,p); + add(p,p); + cswap(p,q,b); + } +} + +sv scalarbase(gf p[4],const u8 *s) +{ + gf q[4]; + set25519(q[0],X); + set25519(q[1],Y); + set25519(q[2],gf1); + M(q[3],X,Y); + scalarmult(p,q,s); +} + +int crypto_sign_keypair(u8 *pk, u8 *sk) +{ + u8 d[64]; + gf p[4]; + int i; + + randombytes(sk, 32); + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p,d); + pack(pk,p); + + FOR(i,32) sk[32 + i] = pk[i]; + return 0; +} + +int crypto_sign_keypair_seed(u8 *pk, u8 *sk) +{ + u8 d[64]; + gf p[4]; + int i; + + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p,d); + pack(pk,p); + + FOR(i,32) sk[32 + i] = pk[i]; + return 0; +} + +static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10}; + +sv modL(u8 *r,i64 x[64]) +{ + i64 carry,i,j; + for (i = 63;i >= 32;--i) { + carry = 0; + for (j = i - 32;j < i - 12;++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)]; + carry = (x[j] + 128) >> 8; + x[j] -= carry << 8; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + FOR(j,32) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + FOR(j,32) x[j] -= carry * L[j]; + FOR(i,32) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } +} + +sv reduce(u8 *r) +{ + i64 x[64],i; + FOR(i,64) x[i] = (u64) r[i]; + FOR(i,64) r[i] = 0; + modL(r,x); +} + +int crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 n,const u8 *sk) +{ + u8 d[64],h[64],r[64]; + i64 i,j,x[64]; + gf p[4]; + + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + *smlen = n+64; + FOR(i,n) sm[64 + i] = m[i]; + FOR(i,32) sm[32 + i] = d[32 + i]; + + crypto_hash(r, sm+32, n+32); + reduce(r); + scalarbase(p,r); + pack(sm,p); + + FOR(i,32) sm[i+32] = sk[i+32]; + crypto_hash(h,sm,n + 64); + reduce(h); + + FOR(i,64) x[i] = 0; + FOR(i,32) x[i] = (u64) r[i]; + FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j]; + modL(sm + 32,x); + + return 0; +} + +int crypto_sign_extended(u8 *sm,u64 *smlen,const u8 *m,u64 n,const u8 *d) +{ + u8 pk[32],h[64],r[64]; + i64 i,j,x[64]; + gf p[4]; + + scalarbase(p,d); + pack(pk,p); + + *smlen = n+64; + FOR(i,n) sm[64 + i] = m[i]; + FOR(i,32) sm[32 + i] = d[32 + i]; + + crypto_hash(r, sm+32, n+32); + reduce(r); + scalarbase(p,r); + pack(sm,p); + + FOR(i,32) sm[i+32] = pk[i]; + crypto_hash(h,sm,n + 64); + reduce(h); + + FOR(i,64) x[i] = 0; + FOR(i,32) x[i] = (u64) r[i]; + FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j]; + modL(sm + 32,x); + + return 0; +} + +static int unpackneg(gf r[4],const u8 p[32]) +{ + gf t, chk, num, den, den2, den4, den6; + set25519(r[2],gf1); + unpack25519(r[1],p); + S(num,r[1]); + M(den,num,D); + Z(num,num,r[2]); + A(den,r[2],den); + + S(den2,den); + S(den4,den2); + M(den6,den4,den2); + M(t,den6,num); + M(t,t,den); + + pow2523(t,t); + M(t,t,num); + M(t,t,den); + M(t,t,den); + M(r[0],t,den); + + S(chk,r[0]); + M(chk,chk,den); + if (neq25519(chk, num)) M(r[0],r[0],I); + + S(chk,r[0]); + M(chk,chk,den); + if (neq25519(chk, num)) return -1; + + if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]); + + M(r[3],r[0],r[1]); + return 0; +} + +static int unpack(gf r[4],const u8 p[32]) +{ + gf t, chk, num, den, den2, den4, den6; + set25519(r[2],gf1); + unpack25519(r[1],p); + S(num,r[1]); + M(den,num,D); + Z(num,num,r[2]); + A(den,r[2],den); + + S(den2,den); + S(den4,den2); + M(den6,den4,den2); + M(t,den6,num); + M(t,t,den); + + pow2523(t,t); + M(t,t,num); + M(t,t,den); + M(t,t,den); + M(r[0],t,den); + + S(chk,r[0]); + M(chk,chk,den); + if (neq25519(chk, num)) M(r[0],r[0],I); + + S(chk,r[0]); + M(chk,chk,den); + if (neq25519(chk, num)) return -1; + + if (par25519(r[0]) != (p[31]>>7)) Z(r[0],gf0,r[0]); + + M(r[3],r[0],r[1]); + return 0; +} + +int crypto_sign_open(u8 *m,u64 *mlen,const u8 *sm,u64 n,const u8 *pk) +{ + int i; + u8 t[32],h[64]; + gf p[4],q[4]; + + *mlen = -1; + if (n < 64) return -1; + + if (unpackneg(q,pk)) return -1; + + FOR(i,n) m[i] = sm[i]; + FOR(i,32) m[i+32] = pk[i]; + crypto_hash(h,m,n); + reduce(h); + scalarmult(p,q,h); + + scalarbase(q,sm + 32); + add(p,q); + pack(t,p); + + n -= 64; + if (crypto_verify_32(sm, t)) { + FOR(i,n) m[i] = 0; + return -1; + } + + FOR(i,n) m[i] = sm[i + 64]; + *mlen = n; + return 0; +} + +#include +#include + +CAMLprim value ml_randombytes(value x, value xlen) { + randombytes(Caml_ba_data_val(x), Long_val(xlen)); + return Val_unit; +} + +CAMLprim value ml_secretbox(value c, value m, value n, value k) { + crypto_secretbox(Caml_ba_data_val(c), + Caml_ba_data_val(m), + Caml_ba_array_val(m)->dim[0], + Caml_ba_data_val(n), + Caml_ba_data_val(k)); + return Val_unit; +} + +CAMLprim value ml_secretbox_open(value m, value c, value n, value k) { + return Val_int(crypto_secretbox_open(Caml_ba_data_val(m), + Caml_ba_data_val(c), + Caml_ba_array_val(c)->dim[0], + Caml_ba_data_val(n), + Caml_ba_data_val(k))); +} + +CAMLprim value ml_crypto_hash(value r, value a, value size) { + crypto_hash(Caml_ba_data_val(r), Caml_ba_data_val(a), Long_val(size)); + return Val_unit; +} + +CAMLprim value ml_crypto_box_keypair(value pk, value sk) { + crypto_box_keypair(Caml_ba_data_val(pk), Caml_ba_data_val(sk)); + return Val_unit; +} + +CAMLprim value ml_crypto_box(value c, value m, value n, value pk, value sk) { + crypto_box(Caml_ba_data_val(c), + Caml_ba_data_val(m), + Caml_ba_array_val(m)->dim[0], + Caml_ba_data_val(n), + Caml_ba_data_val(pk), + Caml_ba_data_val(sk)); + return Val_unit; +} + +CAMLprim value ml_crypto_box_open(value m, value c, value n, value pk, value sk) { + return Val_int(crypto_box_open(Caml_ba_data_val(m), + Caml_ba_data_val(c), + Caml_ba_array_val(c)->dim[0], + Caml_ba_data_val(n), + Caml_ba_data_val(pk), + Caml_ba_data_val(sk))); +} + +CAMLprim value ml_crypto_box_beforenm(value k, value pk, value sk) { + crypto_box_beforenm(Caml_ba_data_val(k), + Caml_ba_data_val(pk), + Caml_ba_data_val(sk)); + return Val_unit; +} + +CAMLprim value ml_crypto_box_afternm(value c, value m, value n, value k) { + crypto_box_afternm(Caml_ba_data_val(c), + Caml_ba_data_val(m), + Caml_ba_array_val(m)->dim[0], + Caml_ba_data_val(n), + Caml_ba_data_val(k)); + return Val_unit; +} + +CAMLprim value ml_crypto_box_open_afternm(value m, value c, value n, value k) { + return Val_int(crypto_box_open_afternm(Caml_ba_data_val(m), + Caml_ba_data_val(c), + Caml_ba_array_val(c)->dim[0], + Caml_ba_data_val(n), + Caml_ba_data_val(k))); +} + +CAMLprim value ml_crypto_sign(value sm, value sk) { + unsigned long long smlen; + crypto_sign(Caml_ba_data_val(sm), + &smlen, + (unsigned char*) Caml_ba_data_val(sm) + 64, + Caml_ba_array_val(sm)->dim[0] - 64, + Caml_ba_data_val(sk)); + return Val_unit; +} + +CAMLprim value ml_crypto_sign_extended(value sm, value d) { + unsigned long long smlen; + crypto_sign_extended(Caml_ba_data_val(sm), + &smlen, + (unsigned char*) Caml_ba_data_val(sm) + 64, + Caml_ba_array_val(sm)->dim[0] - 64, + Caml_ba_data_val(d)); + return Val_unit; +} + +CAMLprim value ml_crypto_sign_open(value m, value mlen, value sm, value pk) { + return Val_int(crypto_sign_open(Caml_ba_data_val(m), + Caml_ba_data_val(mlen), + Caml_ba_data_val(sm), + Caml_ba_array_val(sm)->dim[0], + Caml_ba_data_val(pk))); +} + +CAMLprim value ml_crypto_sign_keypair(value pk, value sk) { + crypto_sign_keypair(Caml_ba_data_val(pk), Caml_ba_data_val(sk)); + return Val_unit; +} + +CAMLprim value ml_crypto_sign_keypair_seed(value pk, value sk) { + crypto_sign_keypair_seed(Caml_ba_data_val(pk), Caml_ba_data_val(sk)); + return Val_unit; +} + +CAMLprim value ml_scalarmult(value p, value q, value s) { + gf pp[4], qq[4]; + unpack(qq, Caml_ba_data_val(q)); + scalarmult(pp, qq, Caml_ba_data_val(s)); + pack(Caml_ba_data_val(p), pp); + return Val_unit; +} + +CAMLprim value ml_scalarbase(value p, value s) { + gf pp[4]; + unpack(pp, Caml_ba_data_val(p)); + scalarbase(pp, Caml_ba_data_val(s)); + pack(Caml_ba_data_val(p), pp); + return Val_unit; +} + +CAMLprim value ml_add(value p, value q) { + gf pp[4], qq[4]; + unpack(pp, Caml_ba_data_val(p)); + unpack(qq, Caml_ba_data_val(q)); + add(pp, qq); + pack(Caml_ba_data_val(p), pp); + return Val_unit; +} diff --git a/vendors/ocaml-tweetnacl/test/jbuild b/vendors/ocaml-tweetnacl/test/jbuild new file mode 100644 index 000000000..fcfd10d52 --- /dev/null +++ b/vendors/ocaml-tweetnacl/test/jbuild @@ -0,0 +1,14 @@ +(jbuild_version 1) + +(executable + ((name test) + (libraries (hex tweetnacl alcotest)))) + +(alias + ((name runtest-tweetnacl) + (deps (test.exe)) + (action (run ${<})))) + +(alias + ((name runtest) + (deps ((alias runtest-tweetnacl))))) diff --git a/vendors/ocaml-tweetnacl/test/test.ml b/vendors/ocaml-tweetnacl/test/test.ml new file mode 100644 index 000000000..25ff6d048 --- /dev/null +++ b/vendors/ocaml-tweetnacl/test/test.ml @@ -0,0 +1,190 @@ +open Tweetnacl + +let msg = "Voulez-vous coucher avec moi, ce soir ?" |> Cstruct.of_string +let msglen = Cstruct.len msg + +let sha512 () = + let resp = `Hex "7941f442d956f124d77ee1d1f0ba3db100751090462cdce4aed5fcd240529097bc666bf9c424becde760910df652c7aefec50b02d7f6efe666f79e5242fb755b" in + let digest = Hash.sha512 msg in + assert (resp = (Hex.of_cstruct digest)) + +let keypair () = + let seed = Rand.gen 32 in + let pk, sk = Sign.keypair ~seed () in + let pk', sk' = Sign.keypair ~seed () in + assert (Sign.equal pk pk') ; + assert (Sign.equal sk sk') + +let sign () = + let pk, sk = Sign.keypair () in + let signed_msg = Sign.sign ~key:sk msg in + match Sign.verify ~key:pk signed_msg with + | None -> failwith "Impossible to verify" + | Some verified_msg -> + assert (Hex.of_cstruct msg = + Hex.of_cstruct (Cstruct.sub verified_msg Sign.bytes msglen)) + +let sign_detached () = + let pk, sk = Sign.keypair () in + let signature = Sign.detached ~key:sk msg in + match Sign.verify_detached ~key:pk ~signature msg with + | false -> failwith "Impossible to verify" + | true -> () + +let sign_extended () = + let pk, sk = Sign.keypair () in + let ek = Sign.extended sk in + let signed_msg = Sign.sign_extended ~key:ek msg in + match Sign.verify ~key:pk signed_msg with + | None -> failwith "Impossible to verify" + | Some verified_msg -> + assert (Hex.of_cstruct msg = + Hex.of_cstruct (Cstruct.sub verified_msg Sign.bytes msglen)) + +let sign_extended_detached () = + let pk, sk = Sign.keypair () in + let ek = Sign.extended sk in + let signature = Sign.detached_extended ~key:ek msg in + match Sign.verify_detached ~key:pk ~signature msg with + | false -> failwith "Impossible to verify" + | true -> () + +let public () = + let pk, sk = Sign.keypair () in + let pk' = Sign.to_cstruct pk in + let ek = Sign.extended sk in + let ppk = Sign.(public pk |> to_cstruct) in + let psk = Sign.(public sk |> to_cstruct) in + let pek = Sign.(public ek |> to_cstruct) in + assert (Cstruct.equal pk' ppk) ; + assert (Cstruct.equal pk' psk) ; + assert (Cstruct.equal pk' pek) + +let base () = + let pk, sk = Sign.keypair () in + let ek = Sign.(extended sk |> to_cstruct) in + let z = Z.of_bits Cstruct.(sub ek 0 32 |> to_string) in + let pk' = Sign.base z in + assert (Sign.equal pk pk') + +let comm () = + let pk1, _ = Sign.keypair () in + let pk2, _ = Sign.keypair () in + let pk3 = Sign.add pk1 pk2 in + let pk3' = Sign.add pk2 pk1 in + assert (Sign.equal pk3 pk3') + +let assoc () = + let pk1, _ = Sign.keypair () in + let pk2, _ = Sign.keypair () in + let pk3, _ = Sign.keypair () in + let sum12 = Sign.add pk1 pk2 in + let sum23 = Sign.add pk2 pk3 in + let a = Sign.add sum12 pk3 in + let b = Sign.add pk1 sum23 in + assert (Sign.equal a b) + +let arith () = + let pk, _sk = Sign.keypair () in + let pk2 = Sign.mult pk (Z.of_int 3) in + let pk2' = Sign.(add (add pk pk) pk) in + assert (Sign.equal pk2 pk2') + +let arith2 () = + let a = Sign.base (Z.of_int 3) in + let b = Sign.mult a (Z.of_int 2) in + let b' = Sign.base (Z.of_int 6) in + assert (Sign.equal b b') + +let hash = [ + "sha512", `Quick, sha512 ; +] + +let secretbox () = + let open Secretbox in + let key = genkey () in + let nonce = Nonce.gen () in + let cmsg = box ~key ~nonce ~msg in + assert (Cstruct.len cmsg = msglen + boxzerobytes) ; + begin match box_open ~key ~nonce ~cmsg with + | None -> assert false + | Some msg' -> assert Cstruct.(equal msg msg') + end + +let secretbox_noalloc () = + let open Secretbox in + let buflen = msglen + zerobytes in + let buf = Cstruct.create buflen in + Cstruct.blit msg 0 buf zerobytes msglen ; + let key = genkey () in + let nonce = Nonce.gen () in + box_noalloc ~key ~nonce ~msg:buf ; + let res = box_open_noalloc ~key ~nonce ~cmsg:buf in + assert res ; + assert Cstruct.(equal msg (sub buf zerobytes msglen)) + +let secretbox = [ + "secretbox", `Quick, secretbox ; + "secretbox_noalloc", `Quick, secretbox_noalloc ; +] + +let box () = + let open Box in + let pk, sk = keypair () in + let ck = combine pk sk in + let nonce = Nonce.gen () in + let cmsg = box ~pk ~sk ~nonce ~msg in + assert (Cstruct.len cmsg = msglen + boxzerobytes) ; + begin match box_open ~pk ~sk ~nonce ~cmsg with + | None -> assert false + | Some msg' -> assert Cstruct.(equal msg msg') + end ; + let cmsg = box_combined ~k:ck ~nonce ~msg in + begin match box_open_combined ~k:ck ~nonce ~cmsg with + | None -> assert false + | Some msg' -> assert Cstruct.(equal msg msg') + end + +let box_noalloc () = + let open Box in + let buflen = msglen + zerobytes in + let buf = Cstruct.create buflen in + Cstruct.blit msg 0 buf zerobytes msglen ; + let pk, sk = keypair () in + let ck = combine pk sk in + let nonce = Nonce.gen () in + box_noalloc ~pk ~sk ~nonce ~msg:buf ; + let res = box_open_noalloc ~pk ~sk ~nonce ~cmsg:buf in + assert res ; + assert Cstruct.(equal msg (sub buf zerobytes msglen)) ; + box_combined_noalloc ~k:ck ~nonce ~msg:buf ; + let res = box_open_combined_noalloc ~k:ck ~nonce ~cmsg:buf in + assert res ; + assert Cstruct.(equal msg (sub buf zerobytes msglen)) + +let box = [ + "box", `Quick, box ; + "box_noalloc", `Quick, box_noalloc ; +] + +let sign = [ + "keypair", `Quick, keypair ; + "sign", `Quick, sign ; + "sign_detached", `Quick, sign_detached ; + "sign_extended", `Quick, sign_extended ; + "sign_extended_detached", `Quick, sign_extended_detached ; + "public", `Quick, public ; + "base", `Quick, base ; + "comm", `Quick, comm ; + "assoc", `Quick, assoc ; + "arith", `Quick, arith ; + "arith2", `Quick, arith2 ; +] + +let () = + Alcotest.run "tweetnacl" [ + "hash", hash ; + "secretbox", secretbox ; + "box", box ; + "sign", sign ; + ] diff --git a/vendors/ocaml-tweetnacl/tweetnacl.opam b/vendors/ocaml-tweetnacl/tweetnacl.opam new file mode 100644 index 000000000..d4416f1ce --- /dev/null +++ b/vendors/ocaml-tweetnacl/tweetnacl.opam @@ -0,0 +1,23 @@ +opam-version: "1.2" +name: "tweetnacl" +version: "dev" +authors: "Vincent Bernardoff " +maintainer: "Vincent Bernardoff " +license: "ISC" +homepage: "https://github.com/vbmithr/ocaml-tweetnacl" +bug-reports: "https://github.com/vbmithr/ocaml-tweetnacl/issues" +dev-repo: "git://github.com/vbmithr/ocaml-tweetnacl" + +available: [ + ocaml-version >= "4.02.0" +] + +build: [ "jbuilder" "build" "-j" jobs "-p" name "@install" ] +build-test: [ "jbuilder" "runtest" "-p" name "-j" jobs ] +depends: [ + "jbuilder" {build & >= "1.0+beta16"} + "hex" {>= "1.2.0"} + "cstruct" {>= "3.2.1"} + "zarith" {>= "1.7"} + "alcotest" { "test" } +]