Skip to content

Commit 8df7584

Browse files
committed
Mirage_crypto.Block.ECB with {de,en}crypt_into
Also provide unsafe_{en,de}crypt_into for further performance.
1 parent 41eb1fd commit 8df7584

File tree

3 files changed

+114
-11
lines changed

3 files changed

+114
-11
lines changed

bench/speed.ml

+16-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ let throughput title f =
4545
Printf.printf " % 5d: %04f MB/s (%d iters in %.03f s)\n%!"
4646
size (bw /. mb) iters time
4747

48+
let throughput_into title f =
49+
Printf.printf "\n* [%s]\n%!" title ;
50+
sizes |> List.iter @@ fun size ->
51+
Gc.full_major () ;
52+
let dst = Bytes.create size in
53+
let (iters, time, bw) = burn (f dst) size in
54+
Printf.printf " % 5d: %04f MB/s (%d iters in %.03f s)\n%!"
55+
size (bw /. mb) iters time
56+
4857
let count_period = 10.
4958

5059
let count f n =
@@ -353,7 +362,13 @@ let benchmarks = [
353362

354363
bm "aes-128-ecb" (fun name ->
355364
let key = AES.ECB.of_secret (Mirage_crypto_rng.generate 16) in
356-
throughput name (fun cs -> AES.ECB.encrypt ~key cs)) ;
365+
throughput_into name
366+
(fun dst cs -> AES.ECB.encrypt_into ~key cs ~src_off:0 dst ~dst_off:0 (String.length cs))) ;
367+
368+
bm "aes-128-ecb-unsafe" (fun name ->
369+
let key = AES.ECB.of_secret (Mirage_crypto_rng.generate 16) in
370+
throughput_into name
371+
(fun dst cs -> AES.ECB.unsafe_encrypt_into ~key cs ~src_off:0 dst ~dst_off:0 (String.length cs))) ;
357372

358373
bm "aes-128-cbc-e" (fun name ->
359374
let key = AES.CBC.of_secret (Mirage_crypto_rng.generate 16)

src/cipher_block.ml

+40-10
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ module Block = struct
2828
val block_size : int
2929
val encrypt : key:key -> string -> string
3030
val decrypt : key:key -> string -> string
31+
val encrypt_into : key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit
32+
val decrypt_into : key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit
33+
val unsafe_encrypt_into : key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit
34+
val unsafe_decrypt_into : key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit
3135
end
3236

3337
module type CBC = sig
@@ -135,17 +139,43 @@ module Modes = struct
135139

136140
let of_secret = Core.of_secret
137141

138-
let (encrypt, decrypt) =
139-
let ecb xform key src =
140-
let n = String.length src in
141-
if n mod block_size <> 0 then invalid_arg "ECB: length %u" n;
142-
let dst = Bytes.create n in
143-
xform ~key ~blocks:(n / block_size) src 0 dst 0 ;
144-
Bytes.unsafe_to_string dst
145-
in
146-
(fun ~key:(key, _) src -> ecb Core.encrypt key src),
147-
(fun ~key:(_, key) src -> ecb Core.decrypt key src)
142+
let unsafe_ecb xform key src src_off dst dst_off len =
143+
xform ~key ~blocks:(len / block_size) src src_off dst dst_off
144+
145+
let ecb xform key src src_off dst dst_off len =
146+
if len mod block_size <> 0 then
147+
invalid_arg "ECB: length %u not of block size" len;
148+
if String.length src - src_off < len then
149+
invalid_arg "ECB: source length %u - src_off %u < len %u"
150+
(String.length src) src_off len;
151+
if Bytes.length dst - dst_off < len then
152+
invalid_arg "ECB: dst length %u - dst_off %u < len %u"
153+
(Bytes.length dst) dst_off len;
154+
unsafe_ecb xform key src src_off dst dst_off len
155+
156+
let encrypt_into ~key:(key, _) src ~src_off dst ~dst_off len =
157+
ecb Core.encrypt key src src_off dst dst_off len
158+
159+
let unsafe_encrypt_into ~key:(key, _) src ~src_off dst ~dst_off len =
160+
unsafe_ecb Core.encrypt key src src_off dst dst_off len
161+
162+
let decrypt_into ~key:(_, key) src ~src_off dst ~dst_off len =
163+
ecb Core.decrypt key src src_off dst dst_off len
148164

165+
let unsafe_decrypt_into ~key:(_, key) src ~src_off dst ~dst_off len =
166+
ecb Core.decrypt key src src_off dst dst_off len
167+
168+
let encrypt ~key src =
169+
let len = String.length src in
170+
let dst = Bytes.create len in
171+
encrypt_into ~key src ~src_off:0 dst ~dst_off:0 len;
172+
Bytes.unsafe_to_string dst
173+
174+
let decrypt ~key src =
175+
let len = String.length src in
176+
let dst = Bytes.create len in
177+
decrypt_into ~key src ~src_off:0 dst ~dst_off:0 len;
178+
Bytes.unsafe_to_string dst
149179
end
150180

151181
module CBC_of (Core : Block.Core) : Block.CBC = struct

src/mirage_crypto.mli

+58
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,70 @@ module Block : sig
158158
module type ECB = sig
159159

160160
type key
161+
161162
val of_secret : string -> key
163+
(** Construct the encryption key corresponding to [secret].
164+
165+
@raise Invalid_argument if the length of [secret] is not in
166+
{{!key_sizes}[key_sizes]}. *)
162167

163168
val key_sizes : int array
169+
(** Key sizes allowed with this cipher. *)
170+
164171
val block_size : int
172+
(** The size of a single block. *)
173+
165174
val encrypt : key:key -> string -> string
175+
(** [encrypt ~key src] encrypts [src] into a freshly allocated buffer of the
176+
same size using [key].
177+
178+
@raise Invalid_argument if the length of [src] is not a multiple of
179+
{!block_size}. *)
180+
166181
val decrypt : key:key -> string -> string
182+
(** [decrypt ~key src] decrypts [src] into a freshly allocated buffer of the
183+
same size using [key].
184+
185+
@raise Invalid_argument if the length of [src] is not a multiple of
186+
{!block_size}. *)
187+
188+
val encrypt_into : key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit
189+
(** [encrypt_into ~key src ~src_off dst dst_off len] encrypts [len] octets
190+
from [src] starting at [src_off] into [dst] starting at [dst_off].
191+
192+
@raise Invalid_argument if [len] is not a multiple of {!block_size}.
193+
@raise Invalid_argument if [String.length src - src_off < len].
194+
@raise Invalid_argument if [Bytes.length dst - dst_off < len]. *)
195+
196+
val decrypt_into : key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit
197+
(** [decrypt_into ~key src ~src_off dst dst_off len] decrypts [len] octets
198+
from [src] starting at [src_off] into [dst] starting at [dst_off].
199+
200+
@raise Invalid_argument if [len] is not a multiple of {!block_size}.
201+
@raise Invalid_argument if [String.length src - src_off < len].
202+
@raise Invalid_argument if [Bytes.length dst - dst_off < len]. *)
203+
204+
(**/**)
205+
val unsafe_encrypt_into : key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit
206+
(** [unsafe_encrypt_into ~key src ~src_off dst dst_off len] encrypts [len]
207+
octets from [src] starting at [src_off] into [dst] starting at
208+
[dst_off]. Since buffer lengths and block sizes are not checked, this
209+
may cause memory issues if an invariant is violated:
210+
{ul
211+
{- [len] must be a multiple of {!block_size},}
212+
{- [String.length src - src_off >= len],}
213+
{- [Bytes.length dst - dst_off >= len].}} *)
214+
215+
val unsafe_decrypt_into : key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit
216+
(** [unsafe_decrypt_into ~key src ~src_off dst dst_off len] decrypts [len]
217+
octets from [src] starting at [src_off] into [dst] starting at
218+
[dst_off]. Since buffer lengths and block sizes are not checked, this
219+
may cause memory issues if an invariant is violated:
220+
{ul
221+
{- [len] must be a multiple of {!block_size},}
222+
{- [String.length src - src_off >= len],}
223+
{- [Bytes.length dst - dst_off >= len].}} *)
224+
(**/**)
167225
end
168226

169227
(** {e Cipher-block chaining} mode. *)

0 commit comments

Comments
 (0)