upstream: https://github.com/mirage/mirage-crypto
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Chacha20-Poly1305: use string instead of cstruct (#203)

* Chacha20-Poly1305: use string instead of cstruct
Performance improvement from 8MB/s to 20MB/s (with 16 byte blocks, on my laptop)

Co-Authored-By: Reynir Björnsson <reynir@reynir.dk>

authored by

Hannes Mehnert
Reynir Björnsson
and committed by
GitHub
0a74d9ea ec3e5ba7

+145 -137
+1 -1
.github/workflows/test.yml
··· 9 9 strategy: 10 10 fail-fast: false 11 11 matrix: 12 - ocaml-version: ["4.14.1", "4.13.1", "4.12.1", "4.11.2", "4.10.2", "4.09.1", "4.08.1"] 12 + ocaml-version: ["4.14.1", "4.13.1", "4.12.1", "4.11.2", "4.10.2", "4.09.1"] 13 13 operating-system: [macos-latest, ubuntu-latest] 14 14 15 15 runs-on: ${{ matrix.operating-system }}
+1 -1
.github/workflows/windows.yml
··· 9 9 strategy: 10 10 fail-fast: false 11 11 matrix: 12 - ocaml-version: ["4.14.0", "4.13.1", "4.12.1", "4.11.2", "4.10.2", "4.09.1", "4.08.1"] 12 + ocaml-version: ["4.14.0", "4.13.1", "4.12.1", "4.11.2", "4.10.2", "4.09.1"] 13 13 operating-system: [windows-latest] 14 14 15 15 runs-on: ${{ matrix.operating-system }}
+1 -1
mirage-crypto.opam
··· 13 13 ["dune" "runtest" "-p" name "-j" jobs] {with-test} ] 14 14 15 15 depends: [ 16 - "ocaml" {>= "4.08.0"} 16 + "ocaml" {>= "4.09.0"} 17 17 "dune" {>= "2.7"} 18 18 "dune-configurator" {>= "2.0.0"} 19 19 "ounit2" {with-test}
+43 -37
src/chacha20.ml
··· 4 4 5 5 let block = 64 6 6 7 - type key = Cstruct.t 7 + type key = string 8 8 9 - let of_secret a = a 9 + let of_secret a = Cstruct.to_string a 10 10 11 11 let chacha20_block state idx key_stream = 12 - Native.Chacha.round 10 state.Cstruct.buffer 0 key_stream.Cstruct.buffer idx 12 + Native.Chacha.round 10 state key_stream idx 13 13 14 14 let init ctr ~key ~nonce = 15 15 let ctr_off = 48 in 16 - let set_ctr32 b v = Cstruct.LE.set_uint32 b ctr_off v 17 - and set_ctr64 b v = Cstruct.LE.set_uint64 b ctr_off v 16 + let set_ctr32 b v = Bytes.set_int32_le b ctr_off v 17 + and set_ctr64 b v = Bytes.set_int64_le b ctr_off v 18 18 in 19 - let inc32 b = set_ctr32 b (Int32.add (Cstruct.LE.get_uint32 b ctr_off) 1l) 20 - and inc64 b = set_ctr64 b (Int64.add (Cstruct.LE.get_uint64 b ctr_off) 1L) 19 + let inc32 b = set_ctr32 b (Int32.add (Bytes.get_int32_le b ctr_off) 1l) 20 + and inc64 b = set_ctr64 b (Int64.add (Bytes.get_int64_le b ctr_off) 1L) 21 21 in 22 22 let s, key, init_ctr, nonce_off, inc = 23 - match Cstruct.length key, Cstruct.length nonce, Int64.shift_right ctr 32 = 0L with 23 + match String.length key, String.length nonce, Int64.shift_right ctr 32 = 0L with 24 24 | 32, 12, true -> 25 25 let ctr = Int64.to_int32 ctr in 26 26 "expand 32-byte k", key, (fun b -> set_ctr32 b ctr), 52, inc32 ··· 29 29 | 32, 8, _ -> 30 30 "expand 32-byte k", key, (fun b -> set_ctr64 b ctr), 56, inc64 31 31 | 16, 8, _ -> 32 - let k = Cstruct.append key key in 32 + let k = key ^ key in 33 33 "expand 16-byte k", k, (fun b -> set_ctr64 b ctr), 56, inc64 34 34 | _ -> invalid_arg "Valid parameters are nonce 12 bytes and key 32 bytes \ 35 35 (counter 32 bit), or nonce 8 byte and key 16 or 32 \ 36 36 bytes (counter 64 bit)." 37 37 in 38 - let state = Cstruct.create block in 39 - Cstruct.blit_from_string s 0 state 0 16 ; 40 - Cstruct.blit key 0 state 16 32 ; 38 + let state = Bytes.create block in 39 + Bytes.unsafe_blit_string s 0 state 0 16 ; 40 + Bytes.unsafe_blit_string key 0 state 16 32 ; 41 41 init_ctr state ; 42 - Cstruct.blit nonce 0 state nonce_off (Cstruct.length nonce) ; 42 + Bytes.unsafe_blit_string nonce 0 state nonce_off (String.length nonce) ; 43 43 state, inc 44 44 45 45 let crypt ~key ~nonce ?(ctr = 0L) data = 46 46 let state, inc = init ctr ~key ~nonce in 47 - let l = Cstruct.length data in 47 + let l = String.length data in 48 48 let block_count = l // block in 49 - let len = block * block_count in 50 49 let last_len = 51 50 let last = l mod block in 52 51 if last = 0 then block else last 53 52 in 54 - let key_stream = Cstruct.create_unsafe len in 53 + let res = Bytes.create l in 55 54 let rec loop i = function 56 55 | 0 -> () 57 56 | 1 -> 58 - chacha20_block state i key_stream ; 59 - Native.xor_into data.buffer (data.off + i) key_stream.buffer i last_len 57 + if last_len = block then begin 58 + chacha20_block state i res ; 59 + Native.xor_into_bytes data i res i block 60 + end else begin 61 + let buf = Bytes.create block in 62 + chacha20_block state 0 buf ; 63 + Native.xor_into_bytes data i buf 0 last_len ; 64 + Bytes.unsafe_blit buf 0 res i last_len 65 + end 60 66 | n -> 61 - chacha20_block state i key_stream ; 62 - Native.xor_into data.buffer (data.off + i) key_stream.buffer i block ; 67 + chacha20_block state i res ; 68 + Native.xor_into_bytes data i res i block ; 63 69 inc state; 64 70 loop (i + block) (n - 1) 65 71 in 66 72 loop 0 block_count ; 67 - Cstruct.sub key_stream 0 l 73 + Bytes.unsafe_to_string res 68 74 69 75 module P = Poly1305.It 70 76 71 77 let generate_poly1305_key ~key ~nonce = 72 - crypt ~key ~nonce (Cstruct.create 32) 78 + crypt ~key ~nonce (String.make 32 '\000') 73 79 74 80 let mac ~key ~adata ciphertext = 75 81 let pad16 b = 76 - let len = Cstruct.length b mod 16 in 77 - if len = 0 then Cstruct.empty else Cstruct.create (16 - len) 82 + let len = String.length b mod 16 in 83 + if len = 0 then "" else String.make (16 - len) '\000' 78 84 and len = 79 - let data = Cstruct.create 16 in 80 - Cstruct.LE.set_uint64 data 0 (Int64.of_int (Cstruct.length adata)); 81 - Cstruct.LE.set_uint64 data 8 (Int64.of_int (Cstruct.length ciphertext)); 82 - data 85 + let data = Bytes.create 16 in 86 + Bytes.set_int64_le data 0 (Int64.of_int (String.length adata)); 87 + Bytes.set_int64_le data 8 (Int64.of_int (String.length ciphertext)); 88 + Bytes.unsafe_to_string data 83 89 in 84 - let ctx = P.empty ~key in 85 - let ctx = P.feed ctx adata in 86 - let ctx = P.feed ctx (pad16 adata) in 87 - let ctx = P.feed ctx ciphertext in 88 - let ctx = P.feed ctx (pad16 ciphertext) in 89 - let ctx = P.feed ctx len in 90 - P.get ctx 90 + P.macl ~key [ adata ; pad16 adata ; ciphertext ; pad16 ciphertext ; len ] 91 91 92 92 let authenticate_encrypt_tag ~key ~nonce ?(adata = Cstruct.empty) data = 93 + let adata = Cstruct.to_string adata in 94 + let nonce = Cstruct.to_string nonce in 95 + let data = Cstruct.to_string data in 93 96 let poly1305_key = generate_poly1305_key ~key ~nonce in 94 97 let ciphertext = crypt ~key ~nonce ~ctr:1L data in 95 98 let mac = mac ~key:poly1305_key ~adata ciphertext in 96 - ciphertext, mac 99 + Cstruct.of_string ciphertext, Cstruct.of_string mac 97 100 98 101 let authenticate_encrypt ~key ~nonce ?adata data = 99 102 let cdata, ctag = authenticate_encrypt_tag ~key ~nonce ?adata data in 100 103 Cstruct.append cdata ctag 101 104 102 105 let authenticate_decrypt_tag ~key ~nonce ?(adata = Cstruct.empty) ~tag data = 106 + let adata = Cstruct.to_string adata in 107 + let nonce = Cstruct.to_string nonce in 108 + let data = Cstruct.to_string data in 103 109 let poly1305_key = generate_poly1305_key ~key ~nonce in 104 110 let ctag = mac ~key:poly1305_key ~adata data in 105 111 let plain = crypt ~key ~nonce ~ctr:1L data in 106 - if Eqaf_cstruct.equal tag ctag then Some plain else None 112 + if Eqaf_cstruct.equal tag (Cstruct.of_string ctag) then Some (Cstruct.of_string plain) else None 107 113 108 114 let authenticate_decrypt ~key ~nonce ?adata data = 109 115 if Cstruct.length data < P.mac_size then
+10 -7
src/mirage_crypto.mli
··· 204 204 205 205 (** The poly1305 message authentication code *) 206 206 module Poly1305 : sig 207 - type mac = Cstruct.t 207 + type mac = string 208 208 209 209 type 'a iter = ('a -> unit) -> unit 210 210 ··· 214 214 val mac_size : int 215 215 (** [mac_size] is the size of the output. *) 216 216 217 - val empty : key:Cstruct.t -> t 217 + val empty : key:string -> t 218 218 (** [empty] is the empty context with the given [key]. 219 219 220 220 @raise Invalid_argument if key is not 32 bytes. *) 221 221 222 - val feed : t -> Cstruct.t -> t 222 + val feed : t -> string -> t 223 223 (** [feed t msg] adds the information in [msg] to [t]. *) 224 224 225 - val feedi : t -> Cstruct.t iter -> t 225 + val feedi : t -> string iter -> t 226 226 (** [feedi t iter] feeds iter into [t]. *) 227 227 228 228 val get : t -> mac 229 229 (** [get t] is the mac corresponding to [t]. *) 230 230 231 - val mac : key:Cstruct.t -> Cstruct.t -> mac 231 + val mac : key:string -> string -> mac 232 232 (** [mac ~key msg] is the all-in-one mac computation: 233 233 [get (feed (empty ~key) msg)]. *) 234 234 235 - val maci : key:Cstruct.t -> Cstruct.t iter -> mac 235 + val maci : key:string -> string iter -> mac 236 236 (** [maci ~key iter] is the all-in-one mac computation: 237 237 [get (feedi (empty ~key) iter)]. *) 238 + 239 + val macl : key:string -> string list -> mac 240 + (** [macl ~key datas] computes the [mac] of [datas]. *) 238 241 end 239 242 240 243 (** {1 Symmetric-key cryptography} *) ··· 506 509 module Chacha20 : sig 507 510 include AEAD 508 511 509 - val crypt : key:key -> nonce:Cstruct.t -> ?ctr:int64 -> Cstruct.t -> Cstruct.t 512 + val crypt : key:key -> nonce:string -> ?ctr:int64 -> string -> string 510 513 (** [crypt ~key ~nonce ~ctr data] generates a ChaCha20 key stream using 511 514 the [key], and [nonce]. The [ctr] defaults to 0. The generated key 512 515 stream is of the same length as [data], and the output is the XOR
+6 -4
src/native.ml
··· 31 31 end 32 32 33 33 module Chacha = struct 34 - external round : int -> buffer -> off -> buffer -> off -> unit = "mc_chacha_round" [@@noalloc] 34 + external round : int -> bytes -> bytes -> off -> unit = "mc_chacha_round" [@@noalloc] 35 35 end 36 36 37 37 module Poly1305 = struct 38 - external init : ctx -> buffer -> off -> unit = "mc_poly1305_init" [@@noalloc] 39 - external update : ctx -> buffer -> off -> size -> unit = "mc_poly1305_update" [@@noalloc] 40 - external finalize : ctx -> buffer -> off -> unit = "mc_poly1305_finalize" [@@noalloc] 38 + external init : ctx -> string -> unit = "mc_poly1305_init" [@@noalloc] 39 + external update : ctx -> string -> size -> unit = "mc_poly1305_update" [@@noalloc] 40 + external finalize : ctx -> bytes -> unit = "mc_poly1305_finalize" [@@noalloc] 41 41 external ctx_size : unit -> int = "mc_poly1305_ctx_size" [@@noalloc] 42 42 external mac_size : unit -> int = "mc_poly1305_mac_size" [@@noalloc] 43 43 end ··· 94 94 (* XXX TODO 95 95 * Unsolved: bounds-checked XORs are slowing things down considerably... *) 96 96 external xor_into : buffer -> off -> buffer -> off -> size -> unit = "mc_xor_into" [@@noalloc] 97 + 98 + external xor_into_bytes : string -> off -> bytes -> off -> size -> unit = "mc_xor_into_bytes" [@@noalloc] 97 99 98 100 external count8be : bytes -> buffer -> off -> blocks:size -> unit = "mc_count_8_be" [@@noalloc] 99 101 external count16be : bytes -> buffer -> off -> blocks:size -> unit = "mc_count_16_be" [@@noalloc]
+4 -4
src/native/bitfn.h
··· 99 99 return (word >> shift) | (word << (64 - shift)); 100 100 } 101 101 102 - static inline void array_swap32(uint32_t *d, uint32_t *s, uint32_t nb) 102 + static inline void array_swap32(uint32_t *d, const uint32_t *s, uint32_t nb) 103 103 { 104 104 while (nb--) 105 105 *d++ = bitfn_swap32(*s++); 106 106 } 107 107 108 - static inline void array_swap64(uint64_t *d, uint64_t *s, uint32_t nb) 108 + static inline void array_swap64(uint64_t *d, const uint64_t *s, uint32_t nb) 109 109 { 110 110 while (nb--) 111 111 *d++ = bitfn_swap64(*s++); 112 112 } 113 113 114 - static inline void array_copy32(uint32_t *d, uint32_t *s, uint32_t nb) 114 + static inline void array_copy32(uint32_t *d, const uint32_t *s, uint32_t nb) 115 115 { 116 116 while (nb--) *d++ = *s++; 117 117 } 118 118 119 - static inline void array_copy64(uint64_t *d, uint64_t *s, uint32_t nb) 119 + static inline void array_copy64(uint64_t *d, const uint64_t *s, uint32_t nb) 120 120 { 121 121 while (nb--) *d++ = *s++; 122 122 }
+10 -26
src/native/chacha.c
··· 2 2 3 3 #include "mirage_crypto.h" 4 4 5 - extern void mc_chacha_core_generic(int count, uint8_t *src, uint8_t *dst); 5 + extern void mc_chacha_core_generic(int count, const uint32_t *src, uint32_t *dst); 6 6 7 7 #ifdef __mc_ACCELERATE__ 8 8 ··· 13 13 x[c] += x[d]; x[b] = rol32(x[b] ^ x[c], 7); 14 14 } 15 15 16 - static inline uint32_t mc_get_u32_le(uint8_t *input, int offset) { 17 - return input[offset] 18 - | (input[offset + 1] << 8) 19 - | (input[offset + 2] << 16) 20 - | (input[offset + 3] << 24); 21 - } 22 - 23 - static inline void mc_set_u32_le(uint8_t *input, int offset, uint32_t value) { 24 - input[offset] = (uint8_t) value; 25 - input[offset + 1] = (uint8_t) (value >> 8); 26 - input[offset + 2] = (uint8_t) (value >> 16); 27 - input[offset + 3] = (uint8_t) (value >> 24); 28 - } 29 - 30 - static void mc_chacha_core(int count, uint8_t *src, uint8_t *dst) { 16 + static void mc_chacha_core(int count, const uint32_t *src, uint32_t *dst) { 31 17 uint32_t x[16]; 32 - for (int i = 0; i < 16; i++) { 33 - x[i] = mc_get_u32_le(src, i * 4); 34 - } 18 + cpu_to_le32_array(x, src, 16); 35 19 for (int i = 0; i < count; i++) { 36 20 mc_chacha_quarterround(x, 0, 4, 8, 12); 37 21 mc_chacha_quarterround(x, 1, 5, 9, 13); ··· 45 29 } 46 30 for (int i = 0; i < 16; i++) { 47 31 uint32_t xi = x[i]; 48 - uint32_t hj = mc_get_u32_le(src, i * 4); 49 - mc_set_u32_le(dst, i * 4, xi + hj); 32 + uint32_t hj = cpu_to_le32(src[i]); 33 + dst[i] = le32_to_cpu(xi + hj); 50 34 } 51 35 } 52 36 53 37 CAMLprim value 54 - mc_chacha_round(value count, value src, value off1, value dst, value off2) 38 + mc_chacha_round(value count, value src, value dst, value off) 55 39 { 56 40 _mc_switch_accel(ssse3, 57 - mc_chacha_core_generic(Int_val(count), _ba_uint8_off(src, off1), _ba_uint8_off(dst, off2)), 58 - mc_chacha_core(Int_val(count), _ba_uint8_off(src, off1), _ba_uint8_off(dst, off2))); 41 + mc_chacha_core_generic(Int_val(count), (const uint32_t *)(String_val(src)), (uint32_t *)(Bytes_val(dst) + Long_val(off))), 42 + mc_chacha_core(Int_val(count), (const uint32_t *)(String_val(src)), (uint32_t *)(Bytes_val(dst) + Long_val(off)))); 59 43 return Val_unit; 60 44 } 61 45 62 46 #else //#ifdef __mc_ACCELERATE__ 63 47 64 48 CAMLprim value 65 - mc_chacha_round(value count, value src, value off1, value dst, value off2) 49 + mc_chacha_round(value count, value src, value dst, value off) 66 50 { 67 - mc_chacha_core_generic(Int_val(count), _ba_uint8_off(src, off1), _ba_uint8_off(dst, off2)); 51 + mc_chacha_core_generic(Int_val(count), (const uint32_t *)(String_val(src)), (uint32_t *)(Bytes_val(dst) + Long_val(off))); 68 52 return Val_unit; 69 53 } 70 54
+4 -20
src/native/chacha_generic.c
··· 9 9 x[c] += x[d]; x[b] = rol32(x[b] ^ x[c], 7); 10 10 } 11 11 12 - static inline uint32_t mc_get_u32_le(uint8_t *input, int offset) { 13 - return input[offset] 14 - | (input[offset + 1] << 8) 15 - | (input[offset + 2] << 16) 16 - | (input[offset + 3] << 24); 17 - } 18 - 19 - static inline void mc_set_u32_le(uint8_t *input, int offset, uint32_t value) { 20 - input[offset] = (uint8_t) value; 21 - input[offset + 1] = (uint8_t) (value >> 8); 22 - input[offset + 2] = (uint8_t) (value >> 16); 23 - input[offset + 3] = (uint8_t) (value >> 24); 24 - } 25 - 26 - void mc_chacha_core_generic(int count, uint8_t *src, uint8_t *dst) { 12 + void mc_chacha_core_generic(int count, const uint32_t *src, uint32_t *dst) { 27 13 uint32_t x[16]; 28 - for (int i = 0; i < 16; i++) { 29 - x[i] = mc_get_u32_le(src, i * 4); 30 - } 14 + cpu_to_le32_array(x, src, 16); 31 15 for (int i = 0; i < count; i++) { 32 16 mc_chacha_quarterround(x, 0, 4, 8, 12); 33 17 mc_chacha_quarterround(x, 1, 5, 9, 13); ··· 41 25 } 42 26 for (int i = 0; i < 16; i++) { 43 27 uint32_t xi = x[i]; 44 - uint32_t hj = mc_get_u32_le(src, i * 4); 45 - mc_set_u32_le(dst, i * 4, xi + hj); 28 + uint32_t hj = cpu_to_le32(src[i]); 29 + dst[i] = le32_to_cpu(xi + hj); 46 30 } 47 31 } 48 32
+3
src/native/mirage_crypto.h
··· 116 116 mc_xor_into_generic (value b1, value off1, value b2, value off2, value n); 117 117 118 118 CAMLprim value 119 + mc_xor_into_bytes_generic (value b1, value off1, value b2, value off2, value n); 120 + 121 + CAMLprim value 119 122 mc_count_16_be_4_generic (value ctr, value dst, value off, value blocks); 120 123 121 124 #endif /* H__MIRAGE_CRYPTO */
+7 -1
src/native/misc.c
··· 1 1 #include "mirage_crypto.h" 2 2 3 - static inline void xor_into (uint8_t *src, uint8_t *dst, size_t n) { 3 + static inline void xor_into (const uint8_t *src, uint8_t *dst, size_t n) { 4 4 /* see issue #70 #81 for alignment considerations (memcpy used below) */ 5 5 #ifdef ARCH_64BIT 6 6 uint64_t s; ··· 56 56 CAMLprim value 57 57 mc_xor_into_generic (value b1, value off1, value b2, value off2, value n) { 58 58 xor_into (_ba_uint8_off (b1, off1), _ba_uint8_off (b2, off2), Int_val (n)); 59 + return Val_unit; 60 + } 61 + 62 + CAMLprim value 63 + mc_xor_into_bytes_generic (value b1, value off1, value b2, value off2, value n) { 64 + xor_into (_st_uint8 (b1) + Long_val(off1), Bytes_val (b2) + Long_val(off2), Int_val (n)); 59 65 return Val_unit; 60 66 } 61 67
+9 -1
src/native/misc_sse.c
··· 2 2 3 3 #ifdef __mc_ACCELERATE__ 4 4 5 - static inline void xor_into (uint8_t *src, uint8_t *dst, size_t n) { 5 + static inline void xor_into (const uint8_t *src, uint8_t *dst, size_t n) { 6 6 /* see issue #70 #81 for alignment considerations (memcpy used below) */ 7 7 #ifdef ARCH_64BIT 8 8 __m128i r; ··· 44 44 _mc_switch_accel(ssse3, 45 45 mc_xor_into_generic(b1, off1, b2, off2, n), 46 46 xor_into (_ba_uint8_off (b1, off1), _ba_uint8_off (b2, off2), Int_val (n))) 47 + return Val_unit; 48 + } 49 + 50 + CAMLprim value 51 + mc_xor_into_bytes (value b1, value off1, value b2, value off2, value n) { 52 + _mc_switch_accel(ssse3, 53 + mc_xor_into_bytes_generic(b1, off1, b2, off2, n), 54 + xor_into (_st_uint8 (b1) + Long_val(off1), Bytes_val (b2) + Long_val(off2), Int_val (n))) 47 55 return Val_unit; 48 56 } 49 57
+6 -6
src/native/poly1305-donna.c
··· 54 54 } 55 55 56 56 //stubs for OCaml 57 - CAMLprim value mc_poly1305_init (value ctx, value key, value off) { 58 - poly1305_init ((poly1305_context *) Bytes_val(ctx), _ba_uint8_off(key, off)); 57 + CAMLprim value mc_poly1305_init (value ctx, value key) { 58 + poly1305_init ((poly1305_context *) Bytes_val(ctx), _st_uint8(key)); 59 59 return Val_unit; 60 60 } 61 61 62 - CAMLprim value mc_poly1305_update (value ctx, value buf, value off, value len) { 63 - poly1305_update ((poly1305_context *) Bytes_val(ctx), _ba_uint8_off(buf, off), Int_val(len)); 62 + CAMLprim value mc_poly1305_update (value ctx, value buf, value len) { 63 + poly1305_update ((poly1305_context *) Bytes_val(ctx), _st_uint8(buf), Int_val(len)); 64 64 return Val_unit; 65 65 } 66 66 67 - CAMLprim value mc_poly1305_finalize (value ctx, value mac, value off) { 68 - poly1305_finish ((poly1305_context *) Bytes_val(ctx), _ba_uint8_off(mac, off)); 67 + CAMLprim value mc_poly1305_finalize (value ctx, value mac) { 68 + poly1305_finish ((poly1305_context *) Bytes_val(ctx), Bytes_val(mac)); 69 69 return Val_unit; 70 70 } 71 71
+22 -16
src/poly1305.ml
··· 1 1 module type S = sig 2 - type mac = Cstruct.t 2 + type mac = string 3 3 type 'a iter = 'a Uncommon.iter 4 4 5 5 type t 6 6 val mac_size : int 7 7 8 - val empty : key:Cstruct.t -> t 9 - val feed : t -> Cstruct.t -> t 10 - val feedi : t -> Cstruct.t iter -> t 11 - val get : t -> Cstruct.t 8 + val empty : key:string -> t 9 + val feed : t -> string -> t 10 + val feedi : t -> string iter -> t 11 + val get : t -> string 12 12 13 - val mac : key:Cstruct.t -> Cstruct.t -> mac 14 - val maci : key:Cstruct.t -> Cstruct.t iter -> mac 13 + val mac : key:string -> string -> mac 14 + val maci : key:string -> string iter -> mac 15 + val macl : key:string -> string list -> mac 15 16 end 16 17 17 18 module It : S = struct 18 - type mac = Cstruct.t 19 + type mac = string 19 20 type 'a iter = 'a Uncommon.iter 20 21 21 22 module P = Native.Poly1305 ··· 25 26 26 27 let dup = Bytes.copy 27 28 28 - let empty ~key:{ Cstruct.buffer ; off ; len } = 29 + let empty ~key = 29 30 let ctx = Bytes.create (P.ctx_size ()) in 30 - if len <> 32 then invalid_arg "Poly1305 key must be 32 bytes" ; 31 - P.init ctx buffer off ; 31 + if String.length key <> 32 then invalid_arg "Poly1305 key must be 32 bytes" ; 32 + P.init ctx key ; 32 33 ctx 33 34 34 - let update ctx { Cstruct.buffer ; off ; len } = 35 - P.update ctx buffer off len 35 + let update ctx data = 36 + P.update ctx data (String.length data) 36 37 37 38 let feed ctx cs = 38 39 let t = dup ctx in ··· 45 46 t 46 47 47 48 let final ctx = 48 - let res = Cstruct.create mac_size in 49 - P.finalize ctx res.buffer res.off; 50 - res 49 + let res = Bytes.create mac_size in 50 + P.finalize ctx res; 51 + Bytes.unsafe_to_string res 51 52 52 53 let get ctx = final (dup ctx) 53 54 54 55 let mac ~key data = feed (empty ~key) data |> final 55 56 56 57 let maci ~key iter = feedi (empty ~key) iter |> final 58 + 59 + let macl ~key datas = 60 + let ctx = empty ~key in 61 + List.iter (update ctx) datas; 62 + final ctx 57 63 end
+12 -12
tests/test_cipher.ml
··· 440 440 441 441 442 442 let chacha20_cases = 443 - let case msg ?ctr ~key ~nonce ?(input = Cstruct.create 128) output = 443 + let case msg ?ctr ~key ~nonce ?(input = String.make 128 '\000') output = 444 444 let key = Chacha20.of_secret (vx key) 445 - and nonce = vx nonce 446 - and output = vx output 445 + and nonce = vx_str nonce 446 + and output = vx_str output 447 447 in 448 - assert_cs_equal ~msg (Chacha20.crypt ~key ~nonce ?ctr input) output 448 + assert_str_equal ~msg (Chacha20.crypt ~key ~nonce ?ctr input) output 449 449 in 450 - let rfc8439_input = Cstruct.of_string "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it." in 450 + let rfc8439_input = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it." in 451 451 let rfc8439_test_2_4_2 _ = 452 452 let key = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" 453 453 and nonce = "000000000000004a00000000" ··· 478 478 1a e1 0b 59 4f 09 e2 6a 7e 90 2e cb d0 60 06 91|} 479 479 in 480 480 assert_cs_equal ~msg:"Chacha20/Poly1305 RFC 8439 2.8.2 encrypt" 481 - (Chacha20.authenticate_encrypt ~key ~nonce ~adata rfc8439_input) 481 + (Chacha20.authenticate_encrypt ~key ~nonce ~adata (Cstruct.of_string rfc8439_input)) 482 482 output; 483 483 assert_cs_equal ~msg:"Chacha20/Poly1305 RFC 8439 2.8.2 decrypt" 484 484 (match Chacha20.authenticate_decrypt ~key ~nonce ~adata output with 485 485 | Some cs -> cs | None -> assert_failure "Chacha20/poly1305 decryption broken") 486 - rfc8439_input; 487 - let input = Cstruct.(shift (append (create 16) rfc8439_input) 16) in 486 + (Cstruct.of_string rfc8439_input); 487 + let input = Cstruct.(shift (append (create 16) (Cstruct.of_string rfc8439_input)) 16) in 488 488 assert_cs_equal ~msg:"Chacha20/Poly1305 RFC 8439 2.8.2 encrypt 2" 489 489 (Chacha20.authenticate_encrypt ~key ~nonce ~adata input) 490 490 output; ··· 693 693 ] 694 694 695 695 let poly1305_rfc8439_2_5_2 _ = 696 - let key = vx "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b" 697 - and data = Cstruct.of_string "Cryptographic Forum Research Group" 698 - and output = vx "a8061dc1305136c6c22b8baf0c0127a9" 696 + let key = vx_str "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b" 697 + and data = "Cryptographic Forum Research Group" 698 + and output = vx_str "a8061dc1305136c6c22b8baf0c0127a9" 699 699 in 700 - assert_cs_equal ~msg:"poly 1305 RFC8439 Section 2.5.2" 700 + assert_str_equal ~msg:"poly 1305 RFC8439 Section 2.5.2" 701 701 (Poly1305.mac ~key data) output 702 702 703 703 let empty_cases _ =
+6
tests/test_common.ml
··· 27 27 assert_equal ~cmp:Cstruct.equal ?msg 28 28 ~pp_diff:(pp_diff Cstruct.hexdump_pp) 29 29 30 + let assert_str_equal ?msg = 31 + assert_equal ~cmp:String.equal ?msg 32 + ~pp_diff:(fun ppf (a, b) -> pp_diff Cstruct.hexdump_pp ppf (Cstruct.of_string a, Cstruct.of_string b)) 33 + 30 34 let iter_list xs f = List.iter f xs 31 35 32 36 let cases_of f = ··· 35 39 let any _ = true 36 40 37 41 let vx = Cstruct.of_hex 42 + 43 + let vx_str data = Cstruct.to_string (Cstruct.of_hex data) 38 44 39 45 let f1_eq ?msg f (a, b) _ = 40 46 assert_cs_equal ?msg (f (vx a)) (vx b)