upstream: https://github.com/mirage/mirage-crypto
at main 717 lines 23 kB view raw
1open Uncommon 2 3module Block = struct 4 module type Core = sig 5 type ekey 6 type dkey 7 8 val of_secret : string -> ekey * dkey 9 val e_of_secret : string -> ekey 10 val d_of_secret : string -> dkey 11 val key : int array 12 val block : int 13 14 (* XXX currently unsafe point *) 15 val encrypt : 16 key:ekey -> blocks:int -> string -> int -> bytes -> int -> unit 17 18 val decrypt : 19 key:dkey -> blocks:int -> string -> int -> bytes -> int -> unit 20 end 21 22 module type ECB = sig 23 type key 24 25 val of_secret : string -> key 26 val key_sizes : int array 27 val block_size : int 28 val encrypt : key:key -> string -> string 29 val decrypt : key:key -> string -> string 30 31 val encrypt_into : 32 key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit 33 34 val decrypt_into : 35 key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit 36 37 val unsafe_encrypt_into : 38 key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit 39 40 val unsafe_decrypt_into : 41 key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit 42 end 43 44 module type CBC = sig 45 type key 46 47 val of_secret : string -> key 48 val key_sizes : int array 49 val block_size : int 50 val encrypt : key:key -> iv:string -> string -> string 51 val decrypt : key:key -> iv:string -> string -> string 52 val next_iv : ?off:int -> string -> iv:string -> string 53 54 val encrypt_into : 55 key:key -> 56 iv:string -> 57 string -> 58 src_off:int -> 59 bytes -> 60 dst_off:int -> 61 int -> 62 unit 63 64 val decrypt_into : 65 key:key -> 66 iv:string -> 67 string -> 68 src_off:int -> 69 bytes -> 70 dst_off:int -> 71 int -> 72 unit 73 74 val unsafe_encrypt_into : 75 key:key -> 76 iv:string -> 77 string -> 78 src_off:int -> 79 bytes -> 80 dst_off:int -> 81 int -> 82 unit 83 84 val unsafe_decrypt_into : 85 key:key -> 86 iv:string -> 87 string -> 88 src_off:int -> 89 bytes -> 90 dst_off:int -> 91 int -> 92 unit 93 94 val unsafe_encrypt_into_inplace : 95 key:key -> iv:string -> bytes -> dst_off:int -> int -> unit 96 end 97 98 module type CTR = sig 99 type key 100 101 val of_secret : string -> key 102 val key_sizes : int array 103 val block_size : int 104 105 type ctr 106 107 val add_ctr : ctr -> int64 -> ctr 108 val next_ctr : ?off:int -> string -> ctr:ctr -> ctr 109 val ctr_of_octets : string -> ctr 110 val stream : key:key -> ctr:ctr -> int -> string 111 val encrypt : key:key -> ctr:ctr -> string -> string 112 val decrypt : key:key -> ctr:ctr -> string -> string 113 val stream_into : key:key -> ctr:ctr -> bytes -> off:int -> int -> unit 114 115 val encrypt_into : 116 key:key -> 117 ctr:ctr -> 118 string -> 119 src_off:int -> 120 bytes -> 121 dst_off:int -> 122 int -> 123 unit 124 125 val decrypt_into : 126 key:key -> 127 ctr:ctr -> 128 string -> 129 src_off:int -> 130 bytes -> 131 dst_off:int -> 132 int -> 133 unit 134 135 val unsafe_stream_into : 136 key:key -> ctr:ctr -> bytes -> off:int -> int -> unit 137 138 val unsafe_encrypt_into : 139 key:key -> 140 ctr:ctr -> 141 string -> 142 src_off:int -> 143 bytes -> 144 dst_off:int -> 145 int -> 146 unit 147 148 val unsafe_decrypt_into : 149 key:key -> 150 ctr:ctr -> 151 string -> 152 src_off:int -> 153 bytes -> 154 dst_off:int -> 155 int -> 156 unit 157 end 158 159 module type GCM = sig 160 include Aead.AEAD 161 162 val key_sizes : int array 163 val block_size : int 164 end 165 166 module type CCM16 = sig 167 include Aead.AEAD 168 169 val key_sizes : int array 170 val block_size : int 171 end 172end 173 174module Counters = struct 175 module type S = sig 176 type ctr 177 178 val size : int 179 val add : ctr -> int64 -> ctr 180 val of_octets : string -> ctr 181 val unsafe_count_into : ctr -> bytes -> off:int -> blocks:int -> unit 182 end 183 184 module C64be = struct 185 type ctr = int64 186 187 let size = 8 188 let of_octets cs = String.get_int64_be cs 0 189 let add = Int64.add 190 191 let unsafe_count_into t buf ~off ~blocks = 192 let ctr = Bytes.create 8 in 193 Bytes.set_int64_be ctr 0 t; 194 Native.count8be ~ctr buf ~off ~blocks 195 end 196 197 module C128be = struct 198 type ctr = int64 * int64 199 200 let size = 16 201 202 let of_octets cs = 203 let buf = Bytes.unsafe_of_string cs in 204 Bytes.(get_int64_be buf 0, get_int64_be buf 8) 205 206 let add (w1, w0) n = 207 let w0' = Int64.add w0 n in 208 let flip = if Int64.logxor w0 w0' < 0L then w0' > w0 else w0' < w0 in 209 ((if flip then Int64.succ w1 else w1), w0') 210 211 let unsafe_count_into (w1, w0) buf ~off ~blocks = 212 let ctr = Bytes.create 16 in 213 Bytes.set_int64_be ctr 0 w1; 214 Bytes.set_int64_be ctr 8 w0; 215 Native.count16be ~ctr buf ~off ~blocks 216 end 217 218 module C128be32 = struct 219 include C128be 220 221 let add (w1, w0) n = 222 let hi = 0xffffffff00000000L and lo = 0x00000000ffffffffL in 223 (w1, Int64.(logor (logand hi w0) (add n w0 |> logand lo))) 224 225 let unsafe_count_into (w1, w0) buf ~off ~blocks = 226 let ctr = Bytes.create 16 in 227 Bytes.set_int64_be ctr 0 w1; 228 Bytes.set_int64_be ctr 8 w0; 229 Native.count16be4 ~ctr buf ~off ~blocks 230 end 231end 232 233let check_offset ~tag ~buf ~off ~len actual_len = 234 if off < 0 then invalid_arg "%s: %s off %u < 0" tag buf off; 235 if actual_len - off < len then 236 invalid_arg "%s: %s length %u - off %u < len %u" tag buf actual_len off len 237[@@inline] 238 239module Modes = struct 240 module ECB_of (Core : Block.Core) : Block.ECB = struct 241 type key = Core.ekey * Core.dkey 242 243 let key_sizes, block_size = Core.(key, block) 244 let of_secret = Core.of_secret 245 246 let unsafe_ecb xform key src src_off dst dst_off len = 247 xform ~key ~blocks:(len / block_size) src src_off dst dst_off 248 249 let ecb xform key src src_off dst dst_off len = 250 if len mod block_size <> 0 then 251 invalid_arg "ECB: length %u not of block size" len; 252 check_offset ~tag:"ECB" ~buf:"src" ~off:src_off ~len (String.length src); 253 check_offset ~tag:"ECB" ~buf:"dst" ~off:dst_off ~len (Bytes.length dst); 254 unsafe_ecb xform key src src_off dst dst_off len 255 256 let encrypt_into ~key:(key, _) src ~src_off dst ~dst_off len = 257 ecb Core.encrypt key src src_off dst dst_off len 258 259 let unsafe_encrypt_into ~key:(key, _) src ~src_off dst ~dst_off len = 260 unsafe_ecb Core.encrypt key src src_off dst dst_off len 261 262 let decrypt_into ~key:(_, key) src ~src_off dst ~dst_off len = 263 ecb Core.decrypt key src src_off dst dst_off len 264 265 let unsafe_decrypt_into ~key:(_, key) src ~src_off dst ~dst_off len = 266 unsafe_ecb Core.decrypt key src src_off dst dst_off len 267 268 let encrypt ~key src = 269 let len = String.length src in 270 let dst = Bytes.create len in 271 encrypt_into ~key src ~src_off:0 dst ~dst_off:0 len; 272 Bytes.unsafe_to_string dst 273 274 let decrypt ~key src = 275 let len = String.length src in 276 let dst = Bytes.create len in 277 decrypt_into ~key src ~src_off:0 dst ~dst_off:0 len; 278 Bytes.unsafe_to_string dst 279 end 280 281 module CBC_of (Core : Block.Core) : Block.CBC = struct 282 type key = Core.ekey * Core.dkey 283 284 let key_sizes, block_size = Core.(key, block) 285 let block = block_size 286 let of_secret = Core.of_secret 287 288 let check_block_size ~iv len = 289 if String.length iv <> block then 290 invalid_arg "CBC: IV length %u not of block size" (String.length iv); 291 if len mod block <> 0 then 292 invalid_arg "CBC: argument length %u not of block size" len 293 [@@inline] 294 295 let next_iv ?(off = 0) cs ~iv = 296 check_block_size ~iv (String.length cs - off); 297 if String.length cs > off then 298 String.sub cs (String.length cs - block_size) block_size 299 else iv 300 301 let unsafe_encrypt_into_inplace ~key:(key, _) ~iv dst ~dst_off len = 302 let rec loop iv iv_i dst_i = function 303 | 0 -> () 304 | b -> 305 Native.xor_into_bytes iv iv_i dst dst_i block; 306 Core.encrypt ~key ~blocks:1 307 (Bytes.unsafe_to_string dst) 308 dst_i dst dst_i; 309 (loop [@tailcall]) 310 (Bytes.unsafe_to_string dst) 311 dst_i (dst_i + block) (b - 1) 312 in 313 loop iv 0 dst_off (len / block) 314 315 let unsafe_encrypt_into ~key ~iv src ~src_off dst ~dst_off len = 316 Bytes.unsafe_blit_string src src_off dst dst_off len; 317 unsafe_encrypt_into_inplace ~key ~iv dst ~dst_off len 318 319 let encrypt_into ~key ~iv src ~src_off dst ~dst_off len = 320 check_block_size ~iv len; 321 check_offset ~tag:"CBC" ~buf:"src" ~off:src_off ~len (String.length src); 322 check_offset ~tag:"CBC" ~buf:"dst" ~off:dst_off ~len (Bytes.length dst); 323 unsafe_encrypt_into ~key ~iv src ~src_off dst ~dst_off len 324 325 let encrypt ~key ~iv src = 326 let dst = Bytes.create (String.length src) in 327 encrypt_into ~key ~iv src ~src_off:0 dst ~dst_off:0 (String.length src); 328 Bytes.unsafe_to_string dst 329 330 let unsafe_decrypt_into ~key:(_, key) ~iv src ~src_off dst ~dst_off len = 331 let b = len / block in 332 if b > 0 then begin 333 Core.decrypt ~key ~blocks:b src src_off dst dst_off; 334 Native.xor_into_bytes iv 0 dst dst_off block; 335 Native.xor_into_bytes src src_off dst (dst_off + block) ((b - 1) * block) 336 end 337 338 let decrypt_into ~key ~iv src ~src_off dst ~dst_off len = 339 check_block_size ~iv len; 340 check_offset ~tag:"CBC" ~buf:"src" ~off:src_off ~len (String.length src); 341 check_offset ~tag:"CBC" ~buf:"dst" ~off:dst_off ~len (Bytes.length dst); 342 unsafe_decrypt_into ~key ~iv src ~src_off dst ~dst_off len 343 344 let decrypt ~key ~iv src = 345 let len = String.length src in 346 let msg = Bytes.create len in 347 decrypt_into ~key ~iv src ~src_off:0 msg ~dst_off:0 len; 348 Bytes.unsafe_to_string msg 349 end 350 351 module CTR_of (Core : Block.Core) (Ctr : Counters.S) : 352 Block.CTR with type key = Core.ekey and type ctr = Ctr.ctr = struct 353 (* FIXME: CTR has more room for speedups. Like stitching. *) 354 355 assert (Core.block = Ctr.size);; 356 357 type key = Core.ekey 358 type ctr = Ctr.ctr 359 360 let key_sizes, block_size = Core.(key, block) 361 let of_secret = Core.e_of_secret 362 363 let unsafe_stream_into ~key ~ctr buf ~off len = 364 let blocks = imax 0 len / block_size in 365 Ctr.unsafe_count_into ctr buf ~off ~blocks; 366 Core.encrypt ~key ~blocks (Bytes.unsafe_to_string buf) off buf off; 367 let slack = imax 0 len mod block_size in 368 if slack <> 0 then begin 369 let buf' = Bytes.create block_size in 370 let ctr = Ctr.add ctr (Int64.of_int blocks) in 371 Ctr.unsafe_count_into ctr buf' ~off:0 ~blocks:1; 372 Core.encrypt ~key ~blocks:1 (Bytes.unsafe_to_string buf') 0 buf' 0; 373 Bytes.unsafe_blit buf' 0 buf (off + (blocks * block_size)) slack 374 end 375 376 let stream_into ~key ~ctr buf ~off len = 377 check_offset ~tag:"CTR" ~buf:"buf" ~off ~len (Bytes.length buf); 378 unsafe_stream_into ~key ~ctr buf ~off len 379 380 let stream ~key ~ctr n = 381 let buf = Bytes.create n in 382 unsafe_stream_into ~key ~ctr buf ~off:0 n; 383 Bytes.unsafe_to_string buf 384 385 let unsafe_encrypt_into ~key ~ctr src ~src_off dst ~dst_off len = 386 unsafe_stream_into ~key ~ctr dst ~off:dst_off len; 387 Uncommon.unsafe_xor_into src ~src_off dst ~dst_off len 388 389 let encrypt_into ~key ~ctr src ~src_off dst ~dst_off len = 390 check_offset ~tag:"CTR" ~buf:"src" ~off:src_off ~len (String.length src); 391 check_offset ~tag:"CTR" ~buf:"dst" ~off:dst_off ~len (Bytes.length dst); 392 unsafe_encrypt_into ~key ~ctr src ~src_off dst ~dst_off len 393 394 let encrypt ~key ~ctr src = 395 let len = String.length src in 396 let dst = Bytes.create len in 397 encrypt_into ~key ~ctr src ~src_off:0 dst ~dst_off:0 len; 398 Bytes.unsafe_to_string dst 399 400 let decrypt = encrypt 401 let decrypt_into = encrypt_into 402 let unsafe_decrypt_into = unsafe_encrypt_into 403 let add_ctr = Ctr.add 404 405 let next_ctr ?(off = 0) msg ~ctr = 406 add_ctr ctr (Int64.of_int @@ ((String.length msg - off) // block_size)) 407 408 let ctr_of_octets = Ctr.of_octets 409 end 410 411 module GHASH : sig 412 type key 413 414 val derive : string -> key 415 val digesti : key:key -> string Uncommon.iter -> string 416 417 val digesti_off_len : 418 key:key -> (string * int * int) Uncommon.iter -> string 419 420 val tagsize : int 421 end = struct 422 type key = string 423 424 let keysize = Native.GHASH.keysize () 425 let tagsize = 16 426 427 let derive cs = 428 assert (String.length cs >= tagsize); 429 let k = Bytes.create keysize in 430 Native.GHASH.keyinit cs k; 431 Bytes.unsafe_to_string k 432 433 let digesti_off_len ~key i = 434 let res = Bytes.make tagsize '\x00' in 435 i (fun (cs, off, len) -> Native.GHASH.ghash key res cs off len); 436 Bytes.unsafe_to_string res 437 438 let digesti ~key i = 439 let res = Bytes.make tagsize '\x00' in 440 i (fun cs -> Native.GHASH.ghash key res cs 0 (String.length cs)); 441 Bytes.unsafe_to_string res 442 end 443 444 module GCM_of (C : Block.Core) : Block.GCM = struct 445 assert (C.block = 16);; 446 447 module CTR = CTR_of (C) (Counters.C128be32) 448 449 type key = { key : C.ekey; hkey : GHASH.key } 450 451 let tag_size = GHASH.tagsize 452 let key_sizes, block_size = C.(key, block) 453 let z128 = String.make block_size '\x00' 454 455 let of_secret cs = 456 let h = Bytes.create block_size in 457 let key = C.e_of_secret cs in 458 C.encrypt ~key ~blocks:1 z128 0 h 0; 459 { key; hkey = GHASH.derive (Bytes.unsafe_to_string h) } 460 461 let bits64 cs = Int64.of_int (String.length cs * 8) 462 463 let pack64s a b = 464 let cs = Bytes.create 16 in 465 Bytes.set_int64_be cs 0 a; 466 Bytes.set_int64_be cs 8 b; 467 Bytes.unsafe_to_string cs 468 469 let counter ~hkey nonce = 470 match String.length nonce with 471 | 0 -> invalid_arg "GCM: invalid nonce of length 0" 472 | 12 -> 473 let w1, w2 = 474 (String.get_int64_be nonce 0, String.get_int32_be nonce 8) 475 in 476 (w1, Int64.(shift_left (of_int32 w2) 32 |> add 1L)) 477 | _ -> 478 CTR.ctr_of_octets @@ GHASH.digesti ~key:hkey 479 @@ iter2 nonce (pack64s 0L (bits64 nonce)) 480 481 let unsafe_tag_into ~key ~hkey ~ctr ?(adata = "") cdata ~off ~len dst 482 ~tag_off = 483 CTR.unsafe_encrypt_into ~key ~ctr 484 (GHASH.digesti_off_len ~key:hkey 485 (iter3 486 (adata, 0, String.length adata) 487 (cdata, off, len) 488 (pack64s (bits64 adata) (Int64.of_int (len * 8)), 0, 16))) 489 ~src_off:0 dst ~dst_off:tag_off tag_size 490 491 let unsafe_authenticate_encrypt_into ~key:{ key; hkey } ~nonce ?adata src 492 ~src_off dst ~dst_off ~tag_off len = 493 let ctr = counter ~hkey nonce in 494 CTR.( 495 unsafe_encrypt_into ~key ~ctr:(add_ctr ctr 1L) src ~src_off dst ~dst_off 496 len); 497 unsafe_tag_into ~key ~hkey ~ctr ?adata 498 (Bytes.unsafe_to_string dst) 499 ~off:dst_off ~len dst ~tag_off 500 501 let authenticate_encrypt_into ~key ~nonce ?adata src ~src_off dst ~dst_off 502 ~tag_off len = 503 check_offset ~tag:"GCM" ~buf:"src" ~off:src_off ~len (String.length src); 504 check_offset ~tag:"GCM" ~buf:"dst" ~off:dst_off ~len (Bytes.length dst); 505 check_offset ~tag:"GCM" ~buf:"dst tag" ~off:tag_off ~len:tag_size 506 (Bytes.length dst); 507 unsafe_authenticate_encrypt_into ~key ~nonce ?adata src ~src_off dst 508 ~dst_off ~tag_off len 509 510 let authenticate_encrypt ~key ~nonce ?adata data = 511 let l = String.length data in 512 let dst = Bytes.create (l + tag_size) in 513 unsafe_authenticate_encrypt_into ~key ~nonce ?adata data ~src_off:0 dst 514 ~dst_off:0 ~tag_off:l l; 515 Bytes.unsafe_to_string dst 516 517 let authenticate_encrypt_tag ~key ~nonce ?adata data = 518 let r = authenticate_encrypt ~key ~nonce ?adata data in 519 ( String.sub r 0 (String.length data), 520 String.sub r (String.length data) tag_size ) 521 522 let unsafe_authenticate_decrypt_into ~key:{ key; hkey } ~nonce ?adata src 523 ~src_off ~tag_off dst ~dst_off len = 524 let ctr = counter ~hkey nonce in 525 CTR.( 526 unsafe_encrypt_into ~key ~ctr:(add_ctr ctr 1L) src ~src_off dst ~dst_off 527 len); 528 let ctag = Bytes.create tag_size in 529 unsafe_tag_into ~key ~hkey ~ctr ?adata src ~off:src_off ~len ctag 530 ~tag_off:0; 531 Eqaf.equal (String.sub src tag_off tag_size) (Bytes.unsafe_to_string ctag) 532 533 let authenticate_decrypt_into ~key ~nonce ?adata src ~src_off ~tag_off dst 534 ~dst_off len = 535 check_offset ~tag:"GCM" ~buf:"src" ~off:src_off ~len (String.length src); 536 check_offset ~tag:"GCM" ~buf:"src tag" ~off:tag_off ~len:tag_size 537 (String.length src); 538 check_offset ~tag:"GCM" ~buf:"dst" ~off:dst_off ~len (Bytes.length dst); 539 unsafe_authenticate_decrypt_into ~key ~nonce ?adata src ~src_off ~tag_off 540 dst ~dst_off len 541 542 let authenticate_decrypt ~key ~nonce ?adata cdata = 543 if String.length cdata < tag_size then None 544 else 545 let l = String.length cdata - tag_size in 546 let data = Bytes.create l in 547 if 548 unsafe_authenticate_decrypt_into ~key ~nonce ?adata cdata ~src_off:0 549 ~tag_off:l data ~dst_off:0 l 550 then Some (Bytes.unsafe_to_string data) 551 else None 552 553 let authenticate_decrypt_tag ~key ~nonce ?adata ~tag:tag_data cipher = 554 let cdata = cipher ^ tag_data in 555 authenticate_decrypt ~key ~nonce ?adata cdata 556 end 557 558 module CCM16_of (C : Block.Core) : Block.CCM16 = struct 559 assert (C.block = 16);; 560 561 let tag_size = C.block 562 563 type key = C.ekey 564 565 let of_secret sec = C.e_of_secret sec 566 let key_sizes, block_size = C.(key, block) 567 568 let cipher ~key src ~src_off dst ~dst_off = 569 C.encrypt ~key ~blocks:1 src src_off dst dst_off 570 571 let unsafe_authenticate_encrypt_into ~key ~nonce ?(adata = "") src ~src_off 572 dst ~dst_off ~tag_off len = 573 Ccm.unsafe_generation_encryption_into ~cipher ~key ~nonce ~adata src 574 ~src_off dst ~dst_off ~tag_off len 575 576 let valid_nonce nonce = 577 let nsize = String.length nonce in 578 if nsize < 7 || nsize > 13 then 579 invalid_arg "CCM: nonce length not between 7 and 13: %u" nsize 580 581 let authenticate_encrypt_into ~key ~nonce ?adata src ~src_off dst ~dst_off 582 ~tag_off len = 583 check_offset ~tag:"CCM" ~buf:"src" ~off:src_off ~len (String.length src); 584 check_offset ~tag:"CCM" ~buf:"dst" ~off:dst_off ~len (Bytes.length dst); 585 check_offset ~tag:"CCM" ~buf:"dst tag" ~off:tag_off ~len:tag_size 586 (Bytes.length dst); 587 valid_nonce nonce; 588 unsafe_authenticate_encrypt_into ~key ~nonce ?adata src ~src_off dst 589 ~dst_off ~tag_off len 590 591 let authenticate_encrypt ~key ~nonce ?adata cs = 592 valid_nonce nonce; 593 let l = String.length cs in 594 let dst = Bytes.create (l + tag_size) in 595 unsafe_authenticate_encrypt_into ~key ~nonce ?adata cs ~src_off:0 dst 596 ~dst_off:0 ~tag_off:l l; 597 Bytes.unsafe_to_string dst 598 599 let authenticate_encrypt_tag ~key ~nonce ?adata cs = 600 let res = authenticate_encrypt ~key ~nonce ?adata cs in 601 ( String.sub res 0 (String.length cs), 602 String.sub res (String.length cs) tag_size ) 603 604 let unsafe_authenticate_decrypt_into ~key ~nonce ?(adata = "") src ~src_off 605 ~tag_off dst ~dst_off len = 606 Ccm.unsafe_decryption_verification_into ~cipher ~key ~nonce ~adata src 607 ~src_off ~tag_off dst ~dst_off len 608 609 let authenticate_decrypt_into ~key ~nonce ?adata src ~src_off ~tag_off dst 610 ~dst_off len = 611 check_offset ~tag:"CCM" ~buf:"src" ~off:src_off ~len (String.length src); 612 check_offset ~tag:"CCM" ~buf:"src tag" ~off:tag_off ~len:tag_size 613 (String.length src); 614 check_offset ~tag:"CCM" ~buf:"dst" ~off:dst_off ~len (Bytes.length dst); 615 valid_nonce nonce; 616 unsafe_authenticate_decrypt_into ~key ~nonce ?adata src ~src_off ~tag_off 617 dst ~dst_off len 618 619 let authenticate_decrypt ~key ~nonce ?adata data = 620 if String.length data < tag_size then None 621 else 622 let dlen = String.length data - tag_size in 623 let dst = Bytes.create dlen in 624 if 625 authenticate_decrypt_into ~key ~nonce ?adata data ~src_off:0 626 ~tag_off:dlen dst ~dst_off:0 dlen 627 then Some (Bytes.unsafe_to_string dst) 628 else None 629 630 let authenticate_decrypt_tag ~key ~nonce ?adata ~tag cs = 631 authenticate_decrypt ~key ~nonce ?adata (cs ^ tag) 632 end 633end 634 635module AES = struct 636 module Core : Block.Core = struct 637 let key = [| 16; 24; 32 |] 638 let block = 16 639 640 type ekey = string * int 641 type dkey = string * int 642 643 let of_secret_with init key = 644 let rounds = 645 match String.length key with 646 | 16 | 24 | 32 -> (String.length key / 4) + 6 647 | _ -> invalid_arg "AES.of_secret: key length %u" (String.length key) 648 in 649 let rk = Bytes.create (Native.AES.rk_s rounds) in 650 init key rk rounds; 651 (Bytes.unsafe_to_string rk, rounds) 652 653 let derive_d ?e buf rk rs = Native.AES.derive_d buf rk rs e 654 let e_of_secret = of_secret_with Native.AES.derive_e 655 let d_of_secret = of_secret_with (derive_d ?e:None) 656 657 let of_secret secret = 658 let ((e, _) as ekey) = e_of_secret secret in 659 (ekey, of_secret_with (derive_d ~e) secret) 660 661 (* XXX arg order ocaml<->c slows down *) 662 (* XXX bounds checks *) 663 664 let encrypt ~key:(e, rounds) ~blocks src off1 dst off2 = 665 Native.AES.enc src off1 dst off2 e rounds blocks 666 667 let decrypt ~key:(d, rounds) ~blocks src off1 dst off2 = 668 Native.AES.dec src off1 dst off2 d rounds blocks 669 end 670 671 module ECB = Modes.ECB_of (Core) 672 module CBC = Modes.CBC_of (Core) 673 module CTR = Modes.CTR_of (Core) (Counters.C128be) 674 module GCM = Modes.GCM_of (Core) 675 module CCM16 = Modes.CCM16_of (Core) 676end 677 678module DES = struct 679 module Core : Block.Core = struct 680 let key = [| 24 |] 681 let block = 8 682 683 type ekey = string 684 type dkey = string 685 686 let k_s = Native.DES.k_s () 687 688 let gen_of_secret ~direction key = 689 if String.length key <> 24 then 690 invalid_arg "DES.of_secret: key length %u" (String.length key); 691 let key = Bytes.of_string key in 692 let keybuf = Bytes.create k_s in 693 Native.DES.des3key key direction keybuf; 694 Bytes.unsafe_to_string keybuf 695 696 let e_of_secret = gen_of_secret ~direction:0 697 let d_of_secret = gen_of_secret ~direction:1 698 let of_secret secret = (e_of_secret secret, d_of_secret secret) 699 700 let encrypt ~key ~blocks src off1 dst off2 = 701 Native.DES.ddes src off1 dst off2 blocks key 702 703 let decrypt = encrypt 704 end 705 706 module ECB = Modes.ECB_of (Core) 707 module CBC = Modes.CBC_of (Core) 708 module CTR = Modes.CTR_of (Core) (Counters.C64be) 709end 710 711let accelerated = 712 let flags = 713 (match Native.misc_mode () with 1 -> [ `XOR ] | _ -> []) 714 @ (match Native.AES.mode () with 1 -> [ `AES ] | _ -> []) 715 @ match Native.GHASH.mode () with 1 -> [ `GHASH ] | _ -> [] 716 in 717 flags