package cryptodbm
Encrypted layer over the dbm library: access to serverless, key-value databases with symmetric encryption.
Install
Dune Dependency
Authors
Maintainers
Sources
v0.84.2.tar.gz
sha256=388a4a8bf17c9ad0825907251720ba40291a19afb643f64066a29e813be50a7e
md5=7c33f55fca768501d06e2ef0eb583f80
doc/src/cryptodbm.internals/subtable.ml.html
Source file subtable.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 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
open Types open Kinds type 'a sub = { (* Status *) mutable status : full Operations.handler status ; (* Handler. None for empty (phony) subtables. *) handler : 'a Operations.handler option ; (* Subtable name *) name: string ; (* Subtable number *) subt: int ; (* Subtable salt *) sub_salt: string ; (* Key kind for user keys. *) user_key_kind: key_kind ; (* Key kind for builtin keys. *) builtin_key_kind: key_kind ; (* Maximal padding for user data. *) max_extra_data: int ; (* Passphrase used to sign the subtable. Empty means no subtable signature. *) subsignwd: Cipher.passwd ; } (* Fails *) let error err sub = raiserror (err (Subtable (sub.name, sub.subt))) let get_number sub = sub.subt let get_name sub = sub.name let phony_kind = Kinds.(mk_key Table_Builtin Uncrypted) (* Mimics an empty subtable. *) let empty name subt = { status = Read ; handler = None ; name ; subt ; sub_salt = "" ; user_key_kind = phony_kind ; builtin_key_kind = phony_kind ; max_extra_data = 0 ; subsignwd = Cipher.empty_passwd ; } (* Extract the table password. *) let get_table_passwds sub = assert (sub.handler <> None) ; match sub.builtin_key_kind.key_how with | Uncrypted -> (Cipher.empty_passwd, Cipher.empty_passwd) | Encrypted (pw, sw, _) -> (pw, sw) (* Salts the given key kind. * sub_pw is just a string, we transform it into a (strong) password. *) let get_salted_key_how ~iterations salt max_extra_key = function | Uncrypted -> Uncrypted | Encrypted (tab_pw, "") -> Encrypted (tab_pw, Cipher.empty_passwd, max_extra_key) | Encrypted (tab_pw, sub_pw) -> Encrypted (tab_pw, Cipher.mk_passwd ~iterations (Config.add_salt salt sub_pw), max_extra_key) let get_semi_uncrypted = function | Uncrypted -> Uncrypted | Encrypted (tab_pw, _) -> if tab_pw == Cipher.empty_passwd then Uncrypted else Encrypted (tab_pw, Cipher.empty_passwd, 0) (* Sign if necessary. *) let sign sub = match sub.status with | Full handler -> if sub.subsignwd != Cipher.empty_passwd then begin let (passwd, _) = get_table_passwds sub in Signature.sign_subtable handler ~subtable_salt:sub.sub_salt ~passwd sub.builtin_key_kind ~subt:sub.subt ~signwd:sub.subsignwd end | Read -> () | Closed -> error is_closed sub let close sub = sign sub ; (* Check if it closed. *) sub.status <- Closed ; (* The handler controls the full database file. We don't close it here. *) () (* Like operations.get, but with a different error if the binding is not found. *) let builtin_get loc ~bad_passwd handler kind ~key = try Operations.get handler kind ~key with | Error (Unbound (_, Any) | Bad_password Any) -> if bad_passwd then raiserror (Bad_password loc) else raiserror (Corrupted (loc, "Missing builtin binding for key: " ^ key)) let compute_and_check_signature subtable = if subtable.subsignwd == Cipher.empty_passwd then () else match subtable.handler with | None -> assert false (* The signwd was empty. Cannot get here. *) | Some handler -> (* Compute signature *) let (table_passwd, _) = get_table_passwds subtable in let signature = Signature.subtable_signature handler ~subtable_salt:subtable.sub_salt ~passwd:table_passwd ~subt:subtable.subt ~signwd:subtable.subsignwd in let read_signature = try Signature.read_subtable_signature handler subtable.builtin_key_kind ~subt:subtable.subt with Error (Unbound (_, Any)) -> error no_signature subtable in if Signature.equal signature read_signature then () else error bad_signature subtable let open_aux handler status ~name ~subt ~iterations ~how ~signwd ~check_signature = (* Key kind to get the subtable salt. *) let salt_key_kind = mk_key (Subtable_Builtin subt) (get_semi_uncrypted how) in (* Read subtable salt and max_extra_key *) let loc = Subtable (name, subt) in let sub_salt = builtin_get loc ~bad_passwd:false handler salt_key_kind ~key:Config.salt_key and max_extra_key = let sval = builtin_get loc ~bad_passwd:false handler salt_key_kind ~key:Config.max_extra_key_key in try int_of_string sval with Failure _ -> raiserror (Corrupted (loc, Printf.sprintf "Max_key_pad is not bound to a number as expected. Found: %s" sval)) and max_extra_data = if status = Read then 0 else let sval = builtin_get loc ~bad_passwd:false handler salt_key_kind ~key:Config.max_extra_data_key in try int_of_string sval with Failure _ -> raiserror (Corrupted (loc, Printf.sprintf "Max_data_pad is not bound to a number as expected. Found: %s" sval)) in (* Signword *) let signwd = if signwd = "" then Cipher.empty_passwd else Cipher.mk_passwd ~iterations (Config.add_salt sub_salt signwd) in let how = get_salted_key_how ~iterations sub_salt max_extra_key how in let builtin_key_kind = mk_key (Subtable_Builtin subt) how and user_key_kind = mk_key (Subtable_User subt) how in let subtable = { status ; handler = Some handler ; name ; subt ; sub_salt ; max_extra_data ; user_key_kind ; builtin_key_kind ; subsignwd = signwd } in (* Check test binding. *) let data = builtin_get loc ~bad_passwd:true handler builtin_key_kind ~key:Config.test_key in if data <> Config.test_data then raiserror (Corrupted (loc, Printf.sprintf "Corrupted test binding: found %s instead of %s." data Config.test_data)) ; (* Check signature *) if check_signature then compute_and_check_signature subtable ; subtable let open_read handler ~name ~subt ~iterations ~how ~signwd = open_aux (Operations.cast handler) Read ~name ~subt ~iterations ~how ~signwd ~check_signature:true let open_append handler ~name ~subt ~iterations ~how ~signwd ~check_signature = open_aux handler (Full handler) ~name ~subt ~iterations ~how ~signwd ~check_signature let open_full handler ~name ~subt ~iterations ~how ~signwd ~max_extra_key ~max_extra_data = if subt > Kinds.max_subtable then raiserror Subtable_overflow ; (* Key kind to write the subtable salt. *) let salt_key_kind = mk_key (Subtable_Builtin subt) (get_semi_uncrypted how) in (* Create salt *) let sub_salt = Utils.random_string Utils.gen Config.salt_size in (* Write salt and max_extras to the database. *) Operations.add ~may_overwrite:false handler salt_key_kind ~max_extra_data:0 ~key:Config.salt_key ~data:sub_salt ; Operations.add ~may_overwrite:false handler salt_key_kind ~max_extra_data:0 ~key:Config.max_extra_key_key ~data:(string_of_int max_extra_key) ; Operations.add ~may_overwrite:false handler salt_key_kind ~max_extra_data:0 ~key:Config.max_extra_data_key ~data:(string_of_int max_extra_data) ; (* Signword *) let signwd = if signwd = "" then Cipher.empty_passwd else Cipher.mk_passwd ~iterations (Config.add_salt sub_salt signwd) in let how = get_salted_key_how ~iterations sub_salt max_extra_key how in let builtin_key_kind = mk_key (Subtable_Builtin subt) how and user_key_kind = mk_key (Subtable_User subt) how in let subtable = { status = Full handler ; handler = Some handler ; name ; subt ; sub_salt ; max_extra_data ; builtin_key_kind ; user_key_kind ; subsignwd = signwd } in (* Write test binding *) Operations.add ~may_overwrite:false handler builtin_key_kind ~max_extra_data ~key:Config.test_key ~data:Config.test_data ; subtable let check_writeable sub = match sub.status with | Closed -> error is_closed sub | Read -> assert false | Full _ -> () let add ?may_overwrite sub ~key ~data = check_writeable sub ; match sub.handler with | None -> assert false | Some handler -> try Operations.add ?may_overwrite handler sub.user_key_kind ~max_extra_data:sub.max_extra_data ~key ~data with Error (Overwrite (key, Any)) -> raiserror (Overwrite (key, Subtable (sub.name, sub.subt))) let find sub key = if sub.status = Closed then error is_closed sub ; match sub.handler with | None -> raiserror (Unbound (key, Subtable (sub.name, sub.subt))) | Some handler -> try Operations.get handler sub.user_key_kind ~key with Error (Unbound (key, Any)) -> raiserror (Unbound (key, Subtable (sub.name, sub.subt))) let delete sub key = check_writeable sub ; match sub.handler with | None -> assert false | Some handler -> try Operations.remove handler sub.user_key_kind ~key with Error (Unbound (_, Any)) -> raiserror (Unbound (key, Subtable (sub.name, sub.subt))) let is_bound sub key = try let _ = find sub key in true with Error (Unbound _) -> false let iterkey sub f = if sub.status = Closed then error is_closed sub ; match sub.handler with | None -> () | Some handler -> let (table_passwd, subpass) = get_table_passwds sub in Operations.iter_subtable handler table_passwd ~subt:sub.subt ~subpass begin fun loc key -> match loc with | Kinds.Subtable_User _ -> f key | _ -> () end let iter sub f = iterkey sub (fun key -> f key (try find sub key with _ -> assert false)) let fold sub acu f = let acu = ref acu in iter sub (fun key data -> acu := f key data !acu) ; !acu let clear sub = check_writeable sub ; let (table_passwd, _) = get_table_passwds sub in let all_keys = ref (Setp.empty Pervasives.compare) in (* We cannot iterate over and remove the elements at the same time. *) match sub.handler with | None -> assert false (* Empty subtable is not in full mode. *) | Some handler -> Operations.iter_subtable_encrypted handler table_passwd ~subt:sub.subt begin fun loc encoded_key -> match loc with | Kinds.Table_Builtin | Kinds.Subtable_Builtin _ -> () | Subtable_User n -> assert (n = sub.subt) ; all_keys := Setp.add encoded_key !all_keys ; end ; Setp.iter (Operations.remove_encrypted handler) !all_keys ; () let remove_signature sub = match sub.handler with | None -> assert false (* Empty subtable not in full move. *) | Some handler -> Signature.remove_subtable_signature handler sub.builtin_key_kind ~subt:sub.subt
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>