Skip to content

Commit

Permalink
aead into, WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
hannesm committed Feb 25, 2024
1 parent 28f8cde commit 3a812fe
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 23 deletions.
2 changes: 2 additions & 0 deletions src/aead.ml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ module type AEAD = sig
?adata:Cstruct.t -> Cstruct.t -> Cstruct.t * Cstruct.t
val authenticate_decrypt_tag : key:key -> nonce:Cstruct.t -> ?adata:Cstruct.t ->
tag:Cstruct.t -> Cstruct.t -> Cstruct.t option
val authenticate_encrypt_into : tag_first:bool -> key:key -> nonce:Cstruct.t ->
?adata:Cstruct.t -> dst:Cstruct.t -> Cstruct.t -> unit
end
30 changes: 19 additions & 11 deletions src/ccm.ml
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,8 @@ let prepare_header nonce adata plen tlen =

type mode = Encrypt | Decrypt

let crypto_core ~cipher ~mode ~key ~nonce ~maclen ~adata data =
let datalen = Cstruct.length data in
let cbcheader = prepare_header nonce adata datalen maclen in
let target = Cstruct.create datalen in
let crypto_core_into ~cipher ~mode ~key ~nonce ~maclen ~adata ~target ~tag_target data =
let cbcheader = prepare_header nonce adata (Cstruct.length data) maclen in

let blkprefix, blkpreflen, preflen = gen_ctr_prefix nonce in
let ctrblock i block =
Expand All @@ -104,7 +102,7 @@ let crypto_core ~cipher ~mode ~key ~nonce ~maclen ~adata data =
doit (Cstruct.sub block 0 block_size)
(Cstruct.shift block block_size)
in
doit (Cstruct.create block_size) cbcheader
doit tag_target cbcheader
in

let rec loop iv ctr src target =
Expand All @@ -114,15 +112,14 @@ let crypto_core ~cipher ~mode ~key ~nonce ~maclen ~adata data =
| Decrypt -> target
in
match Cstruct.length src with
| 0 -> iv
| 0 -> ()
| x when x < block_size ->
let ctrbl = pad_block target in
ctrblock ctr ctrbl ;
Cstruct.blit ctrbl 0 target 0 x ;
Cs.xor_into src target x ;
let cbblock = pad_block cbcblock in
cbc cbblock iv ;
iv
cbc cbblock iv
| _ ->
ctrblock ctr target ;
Cs.xor_into src target block_size ;
Expand All @@ -132,9 +129,15 @@ let crypto_core ~cipher ~mode ~key ~nonce ~maclen ~adata data =
(Cstruct.shift src block_size)
(Cstruct.shift target block_size)
in
let last = loop cbcprep 1 data target in
let t = Cstruct.sub last 0 maclen in
(target, t)
loop cbcprep 1 data target

let crypto_core ~cipher ~mode ~key ~nonce ~maclen ~adata data =
assert (maclen = block_size);
let datalen = Cstruct.length data in
let target = Cstruct.create datalen in
let tag_target = Cstruct.create maclen in
crypto_core_into ~cipher ~mode ~key ~nonce ~maclen ~adata ~target ~tag_target data;
target, tag_target

let crypto_t t nonce cipher key =
let ctr = gen_ctr nonce 0 in
Expand All @@ -146,6 +149,11 @@ let valid_nonce nonce =
if nsize < 7 || nsize > 13 then
invalid_arg "CCM: nonce length not between 7 and 13: %d" nsize

let generation_encryption_into ~cipher ~key ~nonce ~maclen ~adata ~target ~tag_target data =
valid_nonce nonce;
crypto_core_into ~cipher ~mode:Encrypt ~key ~nonce ~maclen ~adata ~target ~tag_target data;
crypto_t tag_target nonce cipher key

let generation_encryption ~cipher ~key ~nonce ~maclen ~adata data =
valid_nonce nonce;
let cdata, t = crypto_core ~cipher ~mode:Encrypt ~key ~nonce ~maclen ~adata data in
Expand Down
46 changes: 34 additions & 12 deletions src/chacha20.ml
Original file line number Diff line number Diff line change
Expand Up @@ -42,36 +42,38 @@ let init ctr ~key ~nonce =
Cstruct.blit nonce 0 state nonce_off (Cstruct.length nonce) ;
state, inc

let crypt ~key ~nonce ?(ctr = 0L) data =
let crypt_into ~key ~nonce ?(ctr = 0L) ~dst data =
let state, inc = init ctr ~key ~nonce in
let l = Cstruct.length data in
let block_count = l // block in
let len = block * block_count in
let last_len =
let last = l mod block in
if last = 0 then block else last
in
let key_stream = Cstruct.create_unsafe len in
let rec loop i = function
| 0 -> ()
| 1 ->
chacha20_block state i key_stream ;
Native.xor_into data.buffer (data.off + i) key_stream.buffer i last_len
chacha20_block state i dst ;
Native.xor_into data.buffer (data.off + i) dst.buffer i last_len
| n ->
chacha20_block state i key_stream ;
Native.xor_into data.buffer (data.off + i) key_stream.buffer i block ;
chacha20_block state i dst ;
Native.xor_into data.buffer (data.off + i) dst.buffer i block ;
inc state;
loop (i + block) (n - 1)
in
loop 0 block_count ;
Cstruct.sub key_stream 0 l
loop 0 block_count

let crypt ~key ~nonce ?ctr data =
let dst = Cstruct.create_unsafe (Cstruct.length data) in
crypt_into ~key ~nonce ?ctr ~dst data;
dst

module P = Poly1305.It

let generate_poly1305_key ~key ~nonce =
crypt ~key ~nonce (Cstruct.create 32)

let mac ~key ~adata ciphertext =
let mac_raw ~key ~adata ciphertext =
let pad16 b =
let len = Cstruct.length b mod 16 in
if len = 0 then Cstruct.empty else Cstruct.create (16 - len)
Expand All @@ -87,6 +89,14 @@ let mac ~key ~adata ciphertext =
let ctx = P.feed ctx ciphertext in
let ctx = P.feed ctx (pad16 ciphertext) in
let ctx = P.feed ctx len in
ctx

let mac_into ~dst ~key ~adata ciphertext =
let ctx = mac_raw ~key ~adata ciphertext in
P.get_into ~dst ctx

let mac ~key ~adata ciphertext =
let ctx = mac_raw ~key ~adata ciphertext in
P.get ctx

let authenticate_encrypt_tag ~key ~nonce ?(adata = Cstruct.empty) data =
Expand All @@ -99,6 +109,20 @@ let authenticate_encrypt ~key ~nonce ?adata data =
let cdata, ctag = authenticate_encrypt_tag ~key ~nonce ?adata data in
Cstruct.append cdata ctag

let tag_size = P.mac_size

let authenticate_encrypt_into ~tag_first ~key ~nonce ?(adata = Cstruct.empty) ~dst data =
let buf, tag =
if tag_first then
let tag, buf = Cstruct.split dst tag_size in
buf, tag
else
Cstruct.split dst (Cstruct.length dst - tag_size)
in
crypt_into ~key ~nonce ~ctr:1L ~dst:buf data;
let poly1305_key = generate_poly1305_key ~key ~nonce in
mac_into ~dst:tag ~key:poly1305_key ~adata buf

let authenticate_decrypt_tag ~key ~nonce ?(adata = Cstruct.empty) ~tag data =
let poly1305_key = generate_poly1305_key ~key ~nonce in
let ctag = mac ~key:poly1305_key ~adata data in
Expand All @@ -111,5 +135,3 @@ let authenticate_decrypt ~key ~nonce ?adata data =
else
let cipher, tag = Cstruct.split data (Cstruct.length data - P.mac_size) in
authenticate_decrypt_tag ~key ~nonce ?adata ~tag cipher

let tag_size = P.mac_size
37 changes: 37 additions & 0 deletions src/cipher_block.ml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ module S = struct
val encrypt : key:key -> ctr:ctr -> Cstruct.t -> Cstruct.t
val decrypt : key:key -> ctr:ctr -> Cstruct.t -> Cstruct.t

val encrypt_into : key:key -> ctr:ctr -> dst:Cstruct.t -> Cstruct.t -> unit

val add_ctr : ctr -> int64 -> ctr
val next_ctr : ctr:ctr -> Cstruct.t -> ctr
val ctr_of_cstruct : Cstruct.t -> ctr
Expand Down Expand Up @@ -221,6 +223,12 @@ module Modes = struct

let decrypt = encrypt

let encrypt_into ~key ~ctr ~dst src =
let blocks = src.len // block_size in
Ctr.unsafe_count_into ctr ~blocks dst.buffer dst.off ;
Core.encrypt ~key ~blocks dst.buffer dst.off dst.buffer dst.off ;
Native.xor_into src.buffer src.off dst.buffer dst.off src.len

let add_ctr = Ctr.add
let next_ctr ~ctr msg = add_ctr ctr (Int64.of_int @@ msg.len // block_size)
let ctr_of_cstruct = Ctr.of_cstruct
Expand Down Expand Up @@ -279,6 +287,11 @@ module Modes = struct
GHASH.digesti ~key:hkey @@
iter3 adata cdata (pack64s (bits64 adata) (bits64 cdata))

let tag_into ~key ~hkey ~ctr ?(adata=Cstruct.empty) ~dst cdata =
CTR.encrypt_into ~key ~ctr ~dst @@
GHASH.digesti ~key:hkey @@
iter3 adata cdata (pack64s (bits64 adata) (bits64 cdata))

let authenticate_encrypt_tag ~key:{ key; hkey } ~nonce ?adata data =
let ctr = counter ~hkey nonce in
let cdata = CTR.(encrypt ~key ~ctr:(add_ctr ctr 1L) data) in
Expand All @@ -303,6 +316,19 @@ module Modes = struct
Cstruct.split cdata (Cstruct.length cdata - tag_size)
in
authenticate_decrypt_tag ~key ~nonce ?adata ~tag cipher

let authenticate_encrypt_into ~tag_first ~key:{ key ; hkey } ~nonce ?adata ~dst data =
let ctr = counter ~hkey nonce in
let ts = tag_size in
let buf, tag =
if tag_first then
let tag, buf = split dst ts in
buf, tag
else
split dst (dst.len - ts)
in
CTR.(encrypt_into ~key ~ctr:(add_ctr ctr 1L) ~dst:buf data);
tag_into ~key ~hkey ~ctr ?adata ~dst:tag buf;
end

module CCM16_of (C : S.Core) : S.CCM16 = struct
Expand Down Expand Up @@ -338,6 +364,17 @@ module Modes = struct
else
let data, tag = Cstruct.split data (Cstruct.length data - tag_size) in
authenticate_decrypt_tag ~key ~nonce ?adata ~tag data

let authenticate_encrypt_into ~tag_first ~key ~nonce ?(adata = Cstruct.empty) ~dst cs =
let buf, tag =
if tag_first then
let tag, buf = Cstruct.split dst tag_size in
buf, tag
else
Cstruct.split dst (dst.len - tag_size)
in
Ccm.generation_encryption_into ~cipher ~key ~nonce ~maclen:tag_size ~adata ~target:buf ~tag_target:tag cs

end
end

Expand Down
12 changes: 12 additions & 0 deletions src/mirage_crypto.mli
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,16 @@ module type AEAD = sig
returned.
@raise Invalid_argument if [nonce] is not of the right size. *)

val authenticate_encrypt_into : tag_first:bool -> key:key -> nonce:Cstruct.t ->
?adata:Cstruct.t -> dst:Cstruct.t -> Cstruct.t -> unit
(** [authenticat_encrypt_into ~tag_first ~key ~nonce ~adata ~dst src]
encrypts and authenticates [src] using [key], [nonce], and [adata]. The
resulting ciphertext is blit into [dst]. If [tag_first] is true, the
authentication tag is put first, otherwise it is put last.
@raise Invalid_argument if [nonce] is not of the right size, or [dst] too
small, *)
end

(** Block ciphers.
Expand Down Expand Up @@ -434,6 +444,8 @@ module Cipher_block : sig
val decrypt : key:key -> ctr:ctr -> Cstruct.t -> Cstruct.t
(** [decrypt] is [encrypt]. *)

val encrypt_into : key:key -> ctr:ctr -> dst:Cstruct.t -> Cstruct.t -> unit

val add_ctr : ctr -> int64 -> ctr
(** [add_ctr ctr n] adds [n] to [ctr]. *)

Expand Down
6 changes: 6 additions & 0 deletions src/poly1305.ml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module type S = sig
val feed : t -> Cstruct.t -> t
val feedi : t -> Cstruct.t iter -> t
val get : t -> Cstruct.t
val get_into : dst:Cstruct.t -> t -> unit

val mac : key:Cstruct.t -> Cstruct.t -> mac
val maci : key:Cstruct.t -> Cstruct.t iter -> mac
Expand Down Expand Up @@ -49,6 +50,11 @@ module It : S = struct
P.finalize ctx res.buffer res.off;
res

let final_into ~dst ctx =
P.finalize ctx dst.Cstruct.buffer dst.off

let get_into ~dst ctx = final_into ~dst (dup ctx)

let get ctx = final (dup ctx)

let mac ~key data = feed (empty ~key) data |> final
Expand Down

0 comments on commit 3a812fe

Please sign in to comment.