package secret

  1. Overview
  2. Docs
Zeroized secret memory outside the OCaml heap

Install

dune-project
 Dependency

Authors

Maintainers

Sources

v0.1.2.tar.gz
md5=2ef809fd4e37a3498f15a8aa28c99484
sha512=db8110e36515895b26b43a5bbdef19c38639236237c52f3585b40ee1bb5a14db9fbf0b00f4ea5bb4634f03df85be3bb43362197e80c1b1de6c2ed5e84eaf0f7b

doc/src/secret.unix/secret_unix.ml.html

Source file secret_unix.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
external read_c : Unix.file_descr -> Secret.t -> int -> int -> int
  = "secret_unix_read"

external write_c : Unix.file_descr -> Secret.t -> int -> int -> int
  = "secret_unix_write"

let decode = function -1 -> raise Secret.Destroyed | r -> r
let read fd t ~off ~len = decode (read_c fd t off len)
let write fd t ~off ~len = decode (write_c fd t off len)

let read_exactly fd t ~off ~len =
  let rec go off len =
    if len > 0 then begin
      let n = read fd t ~off ~len in
      if n = 0 then raise End_of_file;
      go (off + n) (len - n)
    end
  in
  go off len

let read_fd ?hardened fd n =
  if n < 0 then invalid_arg "Secret_unix.read_fd";
  let t = Secret.create ?hardened n in
  let keep = ref false in
  let rec go off =
    if off < n then
      let r = read fd t ~off ~len:(n - off) in
      if r = 0 then off else go (off + r)
    else off
  in
  Fun.protect
    ~finally:(fun () -> if not !keep then Secret.destroy t)
    (fun () ->
      let got = go 0 in
      if got = n then begin
        keep := true;
        t
      end
      else Secret.sub t ~off:0 ~len:got)

let read_file ?hardened ?max path =
  let fd = Unix.openfile path [ Unix.O_RDONLY; Unix.O_CLOEXEC ] 0 in
  match
    let n =
      match max with
      | Some m -> m
      | None -> (
          let st = Unix.fstat fd in
          match st.Unix.st_kind with
          | Unix.S_REG -> st.Unix.st_size
          | _ -> 1 lsl 20)
    in
    read_fd ?hardened fd n
  with
  | t -> (
      match Unix.close fd with
      | () -> t
      | exception e ->
          Secret.destroy t;
          raise e)
  | exception e ->
      (try Unix.close fd with _ -> ());
      raise e

let write_all fd t =
  let n = Secret.length t in
  let rec go off =
    if off < n then
      let w = write fd t ~off ~len:(n - off) in
      if w = 0 then raise (Unix.Unix_error (Unix.EIO, "write", ""))
      else go (off + w)
  in
  go 0