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

Configure Feed

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

Merge pull request #72 from hannesm/chacha

Add Chacha20 cipher, and poly1305 mac

authored by

Hannes Mehnert and committed by
GitHub
a67e3359 5ce3fa48

+1053 -3
+1 -1
freestanding/dune
··· 7 7 (libraries ocaml-freestanding) 8 8 (c_flags (:standard) (:include ../src/cflags.sexp) (:include cflags-freestanding.sexp)) 9 9 (c_names detect_cpu_features misc misc_sse hash_stubs md5 sha1 sha256 sha512 10 - aes_generic aes_aesni des_generic 10 + aes_generic aes_aesni des_generic chacha poly1305-donna 11 11 ghash_pclmul ghash_generic ghash_ctmul 12 12 entropy_cpu_stubs) 13 13 )
+95
src/chacha20.ml
··· 1 + (* Based on https://github.com/abeaumont/ocaml-chacha.git *) 2 + 3 + open Uncommon 4 + 5 + let block = 64 6 + 7 + let chacha20_block state idx key_stream = 8 + Native.Chacha.round 10 state.Cstruct.buffer 0 key_stream.Cstruct.buffer idx 9 + 10 + let init ctr ~key ~nonce = 11 + let ctr_off = 48 in 12 + let set_ctr32 b v = Cstruct.LE.set_uint32 b ctr_off v 13 + and set_ctr64 b v = Cstruct.LE.set_uint64 b ctr_off v 14 + in 15 + let inc32 b = set_ctr32 b (Int32.add (Cstruct.LE.get_uint32 b ctr_off) 1l) 16 + and inc64 b = set_ctr64 b (Int64.add (Cstruct.LE.get_uint64 b ctr_off) 1L) 17 + in 18 + let s, key, init_ctr, nonce_off, inc = 19 + match Cstruct.len key, Cstruct.len nonce, Int64.shift_right ctr 32 = 0L with 20 + | 32, 12, true -> 21 + let ctr = Int64.to_int32 ctr in 22 + "expand 32-byte k", key, (fun b -> set_ctr32 b ctr), 52, inc32 23 + | 32, 12, false -> 24 + invalid_arg "Counter too big for IETF mode (32 bit counter)" 25 + | 32, 8, _ -> 26 + "expand 32-byte k", key, (fun b -> set_ctr64 b ctr), 56, inc64 27 + | 16, 8, _ -> 28 + let k = Cstruct.append key key in 29 + "expand 16-byte k", k, (fun b -> set_ctr64 b ctr), 56, inc64 30 + | _ -> invalid_arg "Valid parameters are nonce 12 bytes and key 32 bytes \ 31 + (counter 32 bit), or nonce 8 byte and key 16 or 32 \ 32 + bytes (counter 64 bit)." 33 + in 34 + let state = Cstruct.create block in 35 + Cstruct.blit_from_string s 0 state 0 16 ; 36 + Cstruct.blit key 0 state 16 32 ; 37 + init_ctr state ; 38 + Cstruct.blit nonce 0 state nonce_off (Cstruct.len nonce) ; 39 + state, inc 40 + 41 + let crypt ~key ~nonce ?(ctr = 0L) data = 42 + let state, inc = init ctr ~key ~nonce in 43 + let l = Cstruct.len data in 44 + let block_count = l // block in 45 + let len = block * block_count in 46 + let key_stream = Cstruct.create_unsafe len in 47 + let rec loop i = function 48 + | 0 -> () 49 + | n -> 50 + chacha20_block state i key_stream ; 51 + Native.xor_into data.buffer (data.off + i) key_stream.buffer i block ; 52 + inc state; 53 + loop (i + block) (n - 1) 54 + in 55 + loop 0 block_count ; 56 + Cstruct.sub key_stream 0 l 57 + 58 + module P = Poly1305.It 59 + 60 + let generate_poly1305_key ~key ~nonce = 61 + crypt ~key ~nonce (Cstruct.create 32) 62 + 63 + let mac ~key ~adata ciphertext = 64 + let pad16 b = 65 + let len = Cstruct.len b mod 16 in 66 + if len = 0 then Cstruct.empty else Cstruct.create (16 - len) 67 + and len = 68 + let data = Cstruct.create 16 in 69 + Cstruct.LE.set_uint64 data 0 (Int64.of_int (Cstruct.len adata)); 70 + Cstruct.LE.set_uint64 data 8 (Int64.of_int (Cstruct.len ciphertext)); 71 + data 72 + in 73 + let ctx = P.empty ~key in 74 + let ctx = P.feed ctx adata in 75 + let ctx = P.feed ctx (pad16 adata) in 76 + let ctx = P.feed ctx ciphertext in 77 + let ctx = P.feed ctx (pad16 ciphertext) in 78 + let ctx = P.feed ctx len in 79 + P.get ctx 80 + 81 + let aead_poly1305_encrypt ~key ~nonce ?(adata = Cstruct.empty) data = 82 + let poly1305_key = generate_poly1305_key ~key ~nonce in 83 + let ciphertext = crypt ~key ~nonce ~ctr:1L data in 84 + let mac = mac ~key:poly1305_key ~adata ciphertext in 85 + Cstruct.append ciphertext mac 86 + 87 + let aead_poly1305_decrypt ~key ~nonce ?(adata = Cstruct.empty) data = 88 + if Cstruct.len data < P.mac_size then 89 + None 90 + else 91 + let cipher, tag = Cstruct.split data (Cstruct.len data - P.mac_size) in 92 + let poly1305_key = generate_poly1305_key ~key ~nonce in 93 + let ctag = mac ~key:poly1305_key ~adata cipher in 94 + let plain = crypt ~key ~nonce ~ctr:1L cipher in 95 + if Cstruct.equal tag ctag then Some plain else None
+2 -1
src/dune
··· 2 2 (name mirage_crypto) 3 3 (public_name mirage-crypto) 4 4 (libraries cstruct) 5 - (private_modules ccm cipher_block cipher_stream hash native uncommon) 5 + (private_modules chacha20 ccm cipher_block cipher_stream hash native poly1305 uncommon) 6 6 (c_names detect_cpu_features 7 7 misc misc_sse 8 8 md5 sha1 sha256 sha512 hash_stubs 9 9 aes_generic aes_aesni 10 10 ghash_generic ghash_pclmul ghash_ctmul 11 11 des_generic 12 + chacha poly1305-donna 12 13 entropy_cpu_stubs) 13 14 (c_flags (:standard) (:include cflags.sexp))) 14 15
+2
src/mirage_crypto.ml
··· 1 1 module Uncommon = Uncommon 2 2 module Hash = Hash 3 + module Poly1305 = Poly1305.It 3 4 module Cipher_block = Cipher_block 5 + module Chacha20 = Chacha20 4 6 module Cipher_stream = Cipher_stream
+65
src/mirage_crypto.mli
··· 187 187 (** [digest_size algorithm] is the size of the [algorithm] in bytes. *) 188 188 end 189 189 190 + (** The poly1305 message authentication code *) 191 + module Poly1305 : sig 192 + type mac = Cstruct.t 193 + 194 + type 'a iter = ('a -> unit) -> unit 195 + 196 + type t 197 + (** Represents a running mac computation, suitable for appending inputs. *) 198 + 199 + val mac_size : int 200 + (** [mac_size] is the size of the output. *) 201 + 202 + val empty : key:Cstruct.t -> t 203 + (** [empty] is the empty context with the given [key]. 204 + 205 + @raise Invalid_argument if key is not 32 bytes. *) 206 + 207 + val feed : t -> Cstruct.t -> t 208 + (** [feed t msg] adds the information in [msg] to [t]. *) 209 + 210 + val feedi : t -> Cstruct.t iter -> t 211 + (** [feedi t iter] feeds iter into [t]. *) 212 + 213 + val get : t -> mac 214 + (** [get t] is the mac corresponding to [t]. *) 215 + 216 + val mac : key:Cstruct.t -> Cstruct.t -> mac 217 + (** [mac ~key msg] is the all-in-one mac computation: 218 + [get (feed (empty ~key) msg)]. *) 219 + 220 + val maci : key:Cstruct.t -> Cstruct.t iter -> mac 221 + (** [maci ~key iter] is the all-in-one mac computation: 222 + [get (feedi (empty ~key) iter)]. *) 223 + end 190 224 191 225 (** {1 Symmetric-key cryptography} *) 192 226 ··· 437 471 this build of the library. *) 438 472 end 439 473 474 + (** The ChaCha20 cipher proposed by D.J. Bernstein. *) 475 + module Chacha20 : sig 476 + val crypt : key:Cstruct.t -> nonce:Cstruct.t -> ?ctr:int64 -> Cstruct.t -> Cstruct.t 477 + (** [crypt ~key ~nonce ~ctr data] generates a ChaCha20 key stream using 478 + the [key], and [nonce]. The [ctr] defaults to 0. The generated key 479 + stream is of the same length as [data], and the output is the XOR 480 + of the key stream and [data]. This implements, depending on the size 481 + of the [nonce] (8 or 12 bytes) both the original specification (where 482 + the counter is 8 byte, same as the nonce) and the IETF RFC 8439 483 + specification (where nonce is 12 bytes, and counter 4 bytes). 484 + 485 + @raise Invalid_argument if invalid parameters are provided. Valid 486 + parameters are: [key] must be 32 bytes and [nonce] 12 bytes for the 487 + IETF mode (and counter fit into 32 bits), or [key] must be either 16 488 + bytes or 32 bytes and [nonce] 8 bytes. 489 + *) 490 + 491 + val aead_poly1305_encrypt : key:Cstruct.t -> nonce:Cstruct.t -> 492 + ?adata:Cstruct.t -> Cstruct.t -> Cstruct.t 493 + (** [aead_poly1305_encrypt ~key ~nonce ~adata data] encrypts [data] 494 + with ChaCha20 using [key] and [nonce]. Additionally, an authentication 495 + tag using {!Poly1305} is appended to the output. This conforms to 496 + RFC 8439 Section 2.8. *) 497 + 498 + val aead_poly1305_decrypt : key:Cstruct.t -> nonce:Cstruct.t -> 499 + ?adata:Cstruct.t -> Cstruct.t -> Cstruct.t option 500 + (** [aead_poly1305_decrypt ~key ~nonce ~adata data] decrypts [data] with 501 + ChaCha20 using [key] and [nonce]. Also, the authentication tag is split 502 + off the end of [data] and verified using {!Poly1305}. This conforms to 503 + RFC 8439 Section 2.8. *) 504 + end 440 505 441 506 (** Streaming ciphers. *) 442 507 module Cipher_stream : sig
+12
src/native.ml
··· 30 30 external k_s : unit -> int = "mc_des_key_size" [@@noalloc] 31 31 end 32 32 33 + module Chacha = struct 34 + external round : int -> buffer -> off -> buffer -> off -> unit = "mc_chacha_round" [@@noalloc] 35 + end 36 + 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] 41 + external ctx_size : unit -> int = "mc_poly1305_ctx_size" [@@noalloc] 42 + external mac_size : unit -> int = "mc_poly1305_mac_size" [@@noalloc] 43 + end 44 + 33 45 module MD5 = struct 34 46 external init : ctx -> unit = "mc_md5_init" [@@noalloc] 35 47 external update : ctx -> buffer -> off -> size -> unit = "mc_md5_update" [@@noalloc]
+55
src/native/chacha.c
··· 1 + /* Based on https://github.com/abeaumont/ocaml-chacha.git */ 2 + 3 + #include "mirage_crypto.h" 4 + 5 + static inline void mc_chacha_quarterround(uint32_t *x, int a, int b, int c, int d) { 6 + x[a] += x[b]; x[d] = rol32(x[d] ^ x[a], 16); 7 + x[c] += x[d]; x[b] = rol32(x[b] ^ x[c], 12); 8 + x[a] += x[b]; x[d] = rol32(x[d] ^ x[a], 8); 9 + x[c] += x[d]; x[b] = rol32(x[b] ^ x[c], 7); 10 + } 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 + static void mc_chacha_core(int count, uint8_t *src, uint8_t *dst) { 27 + uint32_t x[16]; 28 + for (int i = 0; i < 16; i++) { 29 + x[i] = mc_get_u32_le(src, i * 4); 30 + } 31 + for (int i = 0; i < count; i++) { 32 + mc_chacha_quarterround(x, 0, 4, 8, 12); 33 + mc_chacha_quarterround(x, 1, 5, 9, 13); 34 + mc_chacha_quarterround(x, 2, 6, 10, 14); 35 + mc_chacha_quarterround(x, 3, 7, 11, 15); 36 + 37 + mc_chacha_quarterround(x, 0, 5, 10, 15); 38 + mc_chacha_quarterround(x, 1, 6, 11, 12); 39 + mc_chacha_quarterround(x, 2, 7, 8, 13); 40 + mc_chacha_quarterround(x, 3, 4, 9, 14); 41 + } 42 + for (int i = 0; i < 16; i++) { 43 + 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); 46 + } 47 + } 48 + 49 + CAMLprim value 50 + mc_chacha_round(value count, value src, value off1, value dst, value off2) 51 + { 52 + mc_chacha_core(Int_val(count), _ba_uint8_off(src, off1), _ba_uint8_off(dst, off2)); 53 + return Val_unit; 54 + } 55 +
+221
src/native/poly1305-donna-32.h
··· 1 + // from https://github.com/floodyberry/poly1305-donna.git 2 + 3 + /* 4 + poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication and 64 bit addition 5 + */ 6 + 7 + #if defined(_MSC_VER) 8 + #define POLY1305_NOINLINE __declspec(noinline) 9 + #elif defined(__GNUC__) 10 + #define POLY1305_NOINLINE __attribute__((noinline)) 11 + #else 12 + #define POLY1305_NOINLINE 13 + #endif 14 + 15 + #define poly1305_block_size 16 16 + 17 + /* 17 + sizeof(size_t) + 14*sizeof(unsigned long) */ 18 + typedef struct poly1305_state_internal_t { 19 + unsigned long r[5]; 20 + unsigned long h[5]; 21 + unsigned long pad[4]; 22 + size_t leftover; 23 + unsigned char buffer[poly1305_block_size]; 24 + unsigned char final; 25 + } poly1305_state_internal_t; 26 + 27 + /* interpret four 8 bit unsigned integers as a 32 bit unsigned integer in little endian */ 28 + static unsigned long 29 + U8TO32(const unsigned char *p) { 30 + return 31 + (((unsigned long)(p[0] & 0xff) ) | 32 + ((unsigned long)(p[1] & 0xff) << 8) | 33 + ((unsigned long)(p[2] & 0xff) << 16) | 34 + ((unsigned long)(p[3] & 0xff) << 24)); 35 + } 36 + 37 + /* store a 32 bit unsigned integer as four 8 bit unsigned integers in little endian */ 38 + static void 39 + U32TO8(unsigned char *p, unsigned long v) { 40 + p[0] = (v ) & 0xff; 41 + p[1] = (v >> 8) & 0xff; 42 + p[2] = (v >> 16) & 0xff; 43 + p[3] = (v >> 24) & 0xff; 44 + } 45 + 46 + void 47 + poly1305_init(poly1305_context *ctx, const unsigned char key[32]) { 48 + poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; 49 + 50 + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ 51 + st->r[0] = (U8TO32(&key[ 0]) ) & 0x3ffffff; 52 + st->r[1] = (U8TO32(&key[ 3]) >> 2) & 0x3ffff03; 53 + st->r[2] = (U8TO32(&key[ 6]) >> 4) & 0x3ffc0ff; 54 + st->r[3] = (U8TO32(&key[ 9]) >> 6) & 0x3f03fff; 55 + st->r[4] = (U8TO32(&key[12]) >> 8) & 0x00fffff; 56 + 57 + /* h = 0 */ 58 + st->h[0] = 0; 59 + st->h[1] = 0; 60 + st->h[2] = 0; 61 + st->h[3] = 0; 62 + st->h[4] = 0; 63 + 64 + /* save pad for later */ 65 + st->pad[0] = U8TO32(&key[16]); 66 + st->pad[1] = U8TO32(&key[20]); 67 + st->pad[2] = U8TO32(&key[24]); 68 + st->pad[3] = U8TO32(&key[28]); 69 + 70 + st->leftover = 0; 71 + st->final = 0; 72 + } 73 + 74 + static void 75 + poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes) { 76 + const unsigned long hibit = (st->final) ? 0 : (1UL << 24); /* 1 << 128 */ 77 + unsigned long r0,r1,r2,r3,r4; 78 + unsigned long s1,s2,s3,s4; 79 + unsigned long h0,h1,h2,h3,h4; 80 + unsigned long long d0,d1,d2,d3,d4; 81 + unsigned long c; 82 + 83 + r0 = st->r[0]; 84 + r1 = st->r[1]; 85 + r2 = st->r[2]; 86 + r3 = st->r[3]; 87 + r4 = st->r[4]; 88 + 89 + s1 = r1 * 5; 90 + s2 = r2 * 5; 91 + s3 = r3 * 5; 92 + s4 = r4 * 5; 93 + 94 + h0 = st->h[0]; 95 + h1 = st->h[1]; 96 + h2 = st->h[2]; 97 + h3 = st->h[3]; 98 + h4 = st->h[4]; 99 + 100 + while (bytes >= poly1305_block_size) { 101 + /* h += m[i] */ 102 + h0 += (U8TO32(m+ 0) ) & 0x3ffffff; 103 + h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff; 104 + h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff; 105 + h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff; 106 + h4 += (U8TO32(m+12) >> 8) | hibit; 107 + 108 + /* h *= r */ 109 + d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4) + ((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2) + ((unsigned long long)h4 * s1); 110 + d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0) + ((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3) + ((unsigned long long)h4 * s2); 111 + d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1) + ((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4) + ((unsigned long long)h4 * s3); 112 + d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2) + ((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0) + ((unsigned long long)h4 * s4); 113 + d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) + ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) + ((unsigned long long)h4 * r0); 114 + 115 + /* (partial) h %= p */ 116 + c = (unsigned long)(d0 >> 26); h0 = (unsigned long)d0 & 0x3ffffff; 117 + d1 += c; c = (unsigned long)(d1 >> 26); h1 = (unsigned long)d1 & 0x3ffffff; 118 + d2 += c; c = (unsigned long)(d2 >> 26); h2 = (unsigned long)d2 & 0x3ffffff; 119 + d3 += c; c = (unsigned long)(d3 >> 26); h3 = (unsigned long)d3 & 0x3ffffff; 120 + d4 += c; c = (unsigned long)(d4 >> 26); h4 = (unsigned long)d4 & 0x3ffffff; 121 + h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; 122 + h1 += c; 123 + 124 + m += poly1305_block_size; 125 + bytes -= poly1305_block_size; 126 + } 127 + 128 + st->h[0] = h0; 129 + st->h[1] = h1; 130 + st->h[2] = h2; 131 + st->h[3] = h3; 132 + st->h[4] = h4; 133 + } 134 + 135 + POLY1305_NOINLINE void 136 + poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) { 137 + poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; 138 + unsigned long h0,h1,h2,h3,h4,c; 139 + unsigned long g0,g1,g2,g3,g4; 140 + unsigned long long f; 141 + unsigned long mask; 142 + 143 + /* process the remaining block */ 144 + if (st->leftover) { 145 + size_t i = st->leftover; 146 + st->buffer[i++] = 1; 147 + for (; i < poly1305_block_size; i++) 148 + st->buffer[i] = 0; 149 + st->final = 1; 150 + poly1305_blocks(st, st->buffer, poly1305_block_size); 151 + } 152 + 153 + /* fully carry h */ 154 + h0 = st->h[0]; 155 + h1 = st->h[1]; 156 + h2 = st->h[2]; 157 + h3 = st->h[3]; 158 + h4 = st->h[4]; 159 + 160 + c = h1 >> 26; h1 = h1 & 0x3ffffff; 161 + h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; 162 + h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; 163 + h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; 164 + h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; 165 + h1 += c; 166 + 167 + /* compute h + -p */ 168 + g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; 169 + g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; 170 + g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; 171 + g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; 172 + g4 = h4 + c - (1UL << 26); 173 + 174 + /* select h if h < p, or h + -p if h >= p */ 175 + mask = (g4 >> ((sizeof(unsigned long) * 8) - 1)) - 1; 176 + g0 &= mask; 177 + g1 &= mask; 178 + g2 &= mask; 179 + g3 &= mask; 180 + g4 &= mask; 181 + mask = ~mask; 182 + h0 = (h0 & mask) | g0; 183 + h1 = (h1 & mask) | g1; 184 + h2 = (h2 & mask) | g2; 185 + h3 = (h3 & mask) | g3; 186 + h4 = (h4 & mask) | g4; 187 + 188 + /* h = h % (2^128) */ 189 + h0 = ((h0 ) | (h1 << 26)) & 0xffffffff; 190 + h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; 191 + h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; 192 + h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; 193 + 194 + /* mac = (h + pad) % (2^128) */ 195 + f = (unsigned long long)h0 + st->pad[0] ; h0 = (unsigned long)f; 196 + f = (unsigned long long)h1 + st->pad[1] + (f >> 32); h1 = (unsigned long)f; 197 + f = (unsigned long long)h2 + st->pad[2] + (f >> 32); h2 = (unsigned long)f; 198 + f = (unsigned long long)h3 + st->pad[3] + (f >> 32); h3 = (unsigned long)f; 199 + 200 + U32TO8(mac + 0, h0); 201 + U32TO8(mac + 4, h1); 202 + U32TO8(mac + 8, h2); 203 + U32TO8(mac + 12, h3); 204 + 205 + /* zero out the state */ 206 + st->h[0] = 0; 207 + st->h[1] = 0; 208 + st->h[2] = 0; 209 + st->h[3] = 0; 210 + st->h[4] = 0; 211 + st->r[0] = 0; 212 + st->r[1] = 0; 213 + st->r[2] = 0; 214 + st->r[3] = 0; 215 + st->r[4] = 0; 216 + st->pad[0] = 0; 217 + st->pad[1] = 0; 218 + st->pad[2] = 0; 219 + st->pad[3] = 0; 220 + } 221 +
+204
src/native/poly1305-donna-64.h
··· 1 + // from https://github.com/floodyberry/poly1305-donna.git 2 + 3 + /* 4 + poly1305 implementation using 64 bit * 64 bit = 128 bit multiplication and 128 bit addition 5 + */ 6 + 7 + #define uint128_t __uint128_t 8 + #define MUL(out, x, y) out = ((uint128_t)x * y) 9 + #define ADD(out, in) out += in 10 + #define ADDLO(out, in) out += in 11 + #define SHR(in, shift) (unsigned long long)(in >> (shift)) 12 + #define LO(in) (unsigned long long)(in) 13 + 14 + #define POLY1305_NOINLINE __attribute__((noinline)) 15 + 16 + #define poly1305_block_size 16 17 + 18 + /* 17 + sizeof(size_t) + 8*sizeof(unsigned long long) */ 19 + typedef struct poly1305_state_internal_t { 20 + unsigned long long r[3]; 21 + unsigned long long h[3]; 22 + unsigned long long pad[2]; 23 + size_t leftover; 24 + unsigned char buffer[poly1305_block_size]; 25 + unsigned char final; 26 + } poly1305_state_internal_t; 27 + 28 + /* interpret eight 8 bit unsigned integers as a 64 bit unsigned integer in little endian */ 29 + static unsigned long long 30 + U8TO64(const unsigned char *p) { 31 + return 32 + (((unsigned long long)(p[0] & 0xff) ) | 33 + ((unsigned long long)(p[1] & 0xff) << 8) | 34 + ((unsigned long long)(p[2] & 0xff) << 16) | 35 + ((unsigned long long)(p[3] & 0xff) << 24) | 36 + ((unsigned long long)(p[4] & 0xff) << 32) | 37 + ((unsigned long long)(p[5] & 0xff) << 40) | 38 + ((unsigned long long)(p[6] & 0xff) << 48) | 39 + ((unsigned long long)(p[7] & 0xff) << 56)); 40 + } 41 + 42 + /* store a 64 bit unsigned integer as eight 8 bit unsigned integers in little endian */ 43 + static void 44 + U64TO8(unsigned char *p, unsigned long long v) { 45 + p[0] = (v ) & 0xff; 46 + p[1] = (v >> 8) & 0xff; 47 + p[2] = (v >> 16) & 0xff; 48 + p[3] = (v >> 24) & 0xff; 49 + p[4] = (v >> 32) & 0xff; 50 + p[5] = (v >> 40) & 0xff; 51 + p[6] = (v >> 48) & 0xff; 52 + p[7] = (v >> 56) & 0xff; 53 + } 54 + 55 + void 56 + poly1305_init(poly1305_context *ctx, const unsigned char key[32]) { 57 + poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; 58 + unsigned long long t0,t1; 59 + 60 + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ 61 + t0 = U8TO64(&key[0]); 62 + t1 = U8TO64(&key[8]); 63 + 64 + st->r[0] = ( t0 ) & 0xffc0fffffff; 65 + st->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff; 66 + st->r[2] = ((t1 >> 24) ) & 0x00ffffffc0f; 67 + 68 + /* h = 0 */ 69 + st->h[0] = 0; 70 + st->h[1] = 0; 71 + st->h[2] = 0; 72 + 73 + /* save pad for later */ 74 + st->pad[0] = U8TO64(&key[16]); 75 + st->pad[1] = U8TO64(&key[24]); 76 + 77 + st->leftover = 0; 78 + st->final = 0; 79 + } 80 + 81 + static void 82 + poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes) { 83 + const unsigned long long hibit = (st->final) ? 0 : ((unsigned long long)1 << 40); /* 1 << 128 */ 84 + unsigned long long r0,r1,r2; 85 + unsigned long long s1,s2; 86 + unsigned long long h0,h1,h2; 87 + unsigned long long c; 88 + uint128_t d0,d1,d2,d; 89 + 90 + r0 = st->r[0]; 91 + r1 = st->r[1]; 92 + r2 = st->r[2]; 93 + 94 + h0 = st->h[0]; 95 + h1 = st->h[1]; 96 + h2 = st->h[2]; 97 + 98 + s1 = r1 * (5 << 2); 99 + s2 = r2 * (5 << 2); 100 + 101 + while (bytes >= poly1305_block_size) { 102 + unsigned long long t0,t1; 103 + 104 + /* h += m[i] */ 105 + t0 = U8TO64(&m[0]); 106 + t1 = U8TO64(&m[8]); 107 + 108 + h0 += (( t0 ) & 0xfffffffffff); 109 + h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff); 110 + h2 += (((t1 >> 24) ) & 0x3ffffffffff) | hibit; 111 + 112 + /* h *= r */ 113 + MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d); 114 + MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d); 115 + MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d); 116 + 117 + /* (partial) h %= p */ 118 + c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff; 119 + ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff; 120 + ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff; 121 + h0 += c * 5; c = (h0 >> 44); h0 = h0 & 0xfffffffffff; 122 + h1 += c; 123 + 124 + m += poly1305_block_size; 125 + bytes -= poly1305_block_size; 126 + } 127 + 128 + st->h[0] = h0; 129 + st->h[1] = h1; 130 + st->h[2] = h2; 131 + } 132 + 133 + 134 + POLY1305_NOINLINE void 135 + poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) { 136 + poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; 137 + unsigned long long h0,h1,h2,c; 138 + unsigned long long g0,g1,g2; 139 + unsigned long long t0,t1; 140 + 141 + /* process the remaining block */ 142 + if (st->leftover) { 143 + size_t i = st->leftover; 144 + st->buffer[i] = 1; 145 + for (i = i + 1; i < poly1305_block_size; i++) 146 + st->buffer[i] = 0; 147 + st->final = 1; 148 + poly1305_blocks(st, st->buffer, poly1305_block_size); 149 + } 150 + 151 + /* fully carry h */ 152 + h0 = st->h[0]; 153 + h1 = st->h[1]; 154 + h2 = st->h[2]; 155 + 156 + c = (h1 >> 44); h1 &= 0xfffffffffff; 157 + h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff; 158 + h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff; 159 + h1 += c; c = (h1 >> 44); h1 &= 0xfffffffffff; 160 + h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff; 161 + h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff; 162 + h1 += c; 163 + 164 + /* compute h + -p */ 165 + g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff; 166 + g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff; 167 + g2 = h2 + c - ((unsigned long long)1 << 42); 168 + 169 + /* select h if h < p, or h + -p if h >= p */ 170 + c = (g2 >> ((sizeof(unsigned long long) * 8) - 1)) - 1; 171 + g0 &= c; 172 + g1 &= c; 173 + g2 &= c; 174 + c = ~c; 175 + h0 = (h0 & c) | g0; 176 + h1 = (h1 & c) | g1; 177 + h2 = (h2 & c) | g2; 178 + 179 + /* h = (h + pad) */ 180 + t0 = st->pad[0]; 181 + t1 = st->pad[1]; 182 + 183 + h0 += (( t0 ) & 0xfffffffffff) ; c = (h0 >> 44); h0 &= 0xfffffffffff; 184 + h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; c = (h1 >> 44); h1 &= 0xfffffffffff; 185 + h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c; h2 &= 0x3ffffffffff; 186 + 187 + /* mac = h % (2^128) */ 188 + h0 = ((h0 ) | (h1 << 44)); 189 + h1 = ((h1 >> 20) | (h2 << 24)); 190 + 191 + U64TO8(&mac[0], h0); 192 + U64TO8(&mac[8], h1); 193 + 194 + /* zero out the state */ 195 + st->h[0] = 0; 196 + st->h[1] = 0; 197 + st->h[2] = 0; 198 + st->r[0] = 0; 199 + st->r[1] = 0; 200 + st->r[2] = 0; 201 + st->pad[0] = 0; 202 + st->pad[1] = 0; 203 + } 204 +
+75
src/native/poly1305-donna.c
··· 1 + // from https://github.com/floodyberry/poly1305-donna.git 2 + 3 + #include "mirage_crypto.h" 4 + 5 + typedef struct poly1305_context { 6 + size_t aligner; 7 + unsigned char opaque[136]; 8 + } poly1305_context; 9 + 10 + #if defined (__x86_64__) || defined (__aarch64__) 11 + #include "poly1305-donna-64.h" 12 + #else 13 + #include "poly1305-donna-32.h" 14 + #endif 15 + 16 + void 17 + poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes) { 18 + poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; 19 + size_t i; 20 + 21 + /* handle leftover */ 22 + if (st->leftover) { 23 + size_t want = (poly1305_block_size - st->leftover); 24 + if (want > bytes) 25 + want = bytes; 26 + for (i = 0; i < want; i++) 27 + st->buffer[st->leftover + i] = m[i]; 28 + bytes -= want; 29 + m += want; 30 + st->leftover += want; 31 + if (st->leftover < poly1305_block_size) 32 + return; 33 + poly1305_blocks(st, st->buffer, poly1305_block_size); 34 + st->leftover = 0; 35 + } 36 + 37 + /* process full blocks */ 38 + if (bytes >= poly1305_block_size) { 39 + size_t want = (bytes & ~(poly1305_block_size - 1)); 40 + poly1305_blocks(st, m, want); 41 + m += want; 42 + bytes -= want; 43 + } 44 + 45 + /* store leftover */ 46 + if (bytes) { 47 + for (i = 0; i < bytes; i++) 48 + st->buffer[st->leftover + i] = m[i]; 49 + st->leftover += bytes; 50 + } 51 + } 52 + 53 + //stubs for OCaml 54 + CAMLprim value mc_poly1305_init (value ctx, value key, value off) { 55 + poly1305_init ((poly1305_context *) Bytes_val(ctx), _ba_uint8_off(key, off)); 56 + return Val_unit; 57 + } 58 + 59 + CAMLprim value mc_poly1305_update (value ctx, value buf, value off, value len) { 60 + poly1305_update ((poly1305_context *) Bytes_val(ctx), _ba_uint8_off(buf, off), Int_val(len)); 61 + return Val_unit; 62 + } 63 + 64 + CAMLprim value mc_poly1305_finalize (value ctx, value mac, value off) { 65 + poly1305_finish ((poly1305_context *) Bytes_val(ctx), _ba_uint8_off(mac, off)); 66 + return Val_unit; 67 + } 68 + 69 + CAMLprim value mc_poly1305_ctx_size (__unit ()) { 70 + return Val_int(sizeof(poly1305_context)); 71 + } 72 + 73 + CAMLprim value mc_poly1305_mac_size (__unit ()) { 74 + return Val_int(16); 75 + }
+57
src/poly1305.ml
··· 1 + module type S = sig 2 + type mac = Cstruct.t 3 + type 'a iter = 'a Uncommon.iter 4 + 5 + type t 6 + val mac_size : int 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 12 + 13 + val mac : key:Cstruct.t -> Cstruct.t -> mac 14 + val maci : key:Cstruct.t -> Cstruct.t iter -> mac 15 + end 16 + 17 + module It : S = struct 18 + type mac = Cstruct.t 19 + type 'a iter = 'a Uncommon.iter 20 + 21 + module P = Native.Poly1305 22 + let mac_size = P.mac_size () 23 + 24 + type t = Native.ctx 25 + 26 + let dup = Bytes.copy 27 + 28 + let empty ~key:{ Cstruct.buffer ; off ; len } = 29 + 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 ; 32 + ctx 33 + 34 + let update ctx { Cstruct.buffer ; off ; len } = 35 + P.update ctx buffer off len 36 + 37 + let feed ctx cs = 38 + let t = dup ctx in 39 + update t cs ; 40 + t 41 + 42 + let feedi ctx iter = 43 + let t = dup ctx in 44 + iter (update t) ; 45 + t 46 + 47 + let final ctx = 48 + let res = Cstruct.create mac_size in 49 + P.finalize ctx res.buffer res.off; 50 + res 51 + 52 + let get ctx = final (dup ctx) 53 + 54 + let mac ~key data = feed (empty ~key) data |> final 55 + 56 + let maci ~key iter = feedi (empty ~key) iter |> final 57 + end
+263
tests/test_cipher.ml
··· 413 413 ] 414 414 415 415 416 + let chacha20_cases = 417 + let case msg ?ctr ~key ~nonce ?(input = Cstruct.create 128) output = 418 + let key = vx key 419 + and nonce = vx nonce 420 + and output = vx output 421 + in 422 + assert_cs_equal ~msg (Chacha20.crypt ~key ~nonce ?ctr input) output 423 + in 424 + 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 425 + let rfc8439_test_2_4_2 _ = 426 + let key = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" 427 + and nonce = "000000000000004a00000000" 428 + and output = 429 + {|6e 2e 35 9a 25 68 f9 80 41 ba 07 28 dd 0d 69 81 430 + e9 7e 7a ec 1d 43 60 c2 0a 27 af cc fd 9f ae 0b 431 + f9 1b 65 c5 52 47 33 ab 8f 59 3d ab cd 62 b3 57 432 + 16 39 d6 24 e6 51 52 ab 8f 53 0c 35 9f 08 61 d8 433 + 07 ca 0d bf 50 0d 6a 61 56 a3 8e 08 8a 22 b6 5e 434 + 52 bc 51 4d 16 cc f8 06 81 8c e9 1a b7 79 37 36 435 + 5a f9 0b bf 74 a3 5b e6 b4 0b 8e ed f2 78 5e 42 436 + 87 4d|} 437 + in 438 + case "Chacha20 RFC 8439 2.4.2" ~ctr:1L ~key ~nonce ~input:rfc8439_input output 439 + and rfc8439_test_2_8_2 _ = 440 + let key = vx "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" 441 + and adata = vx "50515253c0c1c2c3c4c5c6c7" 442 + and nonce = vx "0700000040 41424344454647" 443 + and output = vx {| 444 + d3 1a 8d 34 64 8e 60 db 7b 86 af bc 53 ef 7e c2 445 + a4 ad ed 51 29 6e 08 fe a9 e2 b5 a7 36 ee 62 d6 446 + 3d be a4 5e 8c a9 67 12 82 fa fb 69 da 92 72 8b 447 + 1a 71 de 0a 9e 06 0b 29 05 d6 a5 b6 7e cd 3b 36 448 + 92 dd bd 7f 2d 77 8b 8c 98 03 ae e3 28 09 1b 58 449 + fa b3 24 e4 fa d6 75 94 55 85 80 8b 48 31 d7 bc 450 + 3f f4 de f0 8e 4b 7a 9d e5 76 d2 65 86 ce c6 4b 451 + 61 16 452 + 1a e1 0b 59 4f 09 e2 6a 7e 90 2e cb d0 60 06 91|} 453 + in 454 + assert_cs_equal ~msg:"Chacha20/Poly1305 RFC 8439 2.8.2 encrypt" 455 + (Chacha20.aead_poly1305_encrypt ~key ~nonce ~adata rfc8439_input) 456 + output; 457 + assert_cs_equal ~msg:"Chacha20/Poly1305 RFC 8439 2.8.2 decrypt" 458 + (match Chacha20.aead_poly1305_decrypt ~key ~nonce ~adata output with 459 + | Some cs -> cs | None -> assert false) 460 + rfc8439_input; 461 + let input = Cstruct.(shift (append (create 16) rfc8439_input) 16) in 462 + assert_cs_equal ~msg:"Chacha20/Poly1305 RFC 8439 2.8.2 encrypt 2" 463 + (Chacha20.aead_poly1305_encrypt ~key ~nonce ~adata input) 464 + output; 465 + in 466 + (* from https://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-01 *) 467 + let case ~key ~nonce ~output0 ~output1 _ = 468 + case "chacha20 crypt" ~key ~nonce (output0 ^ output1) 469 + in 470 + List.map test_case 471 + [ 472 + rfc8439_test_2_4_2 ; 473 + 474 + rfc8439_test_2_8_2 ; 475 + 476 + case 477 + ~key:(String.make 64 '0') 478 + ~nonce:(String.make 16 '0') 479 + ~output0:("76b8e0ada0f13d90405d6ae55386bd28" ^ 480 + "bdd219b8a08ded1aa836efcc8b770dc7" ^ 481 + "da41597c5157488d7724e03fb8d84a37" ^ 482 + "6a43b8f41518a11cc387b669b2ee6586") 483 + ~output1:("9f07e7be5551387a98ba977c732d080d" ^ 484 + "cb0f29a048e3656912c6533e32ee7aed" ^ 485 + "29b721769ce64e43d57133b074d839d5" ^ 486 + "31ed1f28510afb45ace10a1f4b794d6f") ; 487 + 488 + case 489 + ~key:("01" ^ String.make 62 '0') 490 + ~nonce:(String.make 16 '0') 491 + ~output0:("c5d30a7ce1ec119378c84f487d775a85" ^ 492 + "42f13ece238a9455e8229e888de85bbd" ^ 493 + "29eb63d0a17a5b999b52da22be4023eb" ^ 494 + "07620a54f6fa6ad8737b71eb0464dac0") 495 + ~output1:("10f656e6d1fd55053e50c4875c9930a3" ^ 496 + "3f6d0263bd14dfd6ab8c70521c19338b" ^ 497 + "2308b95cf8d0bb7d202d2102780ea352" ^ 498 + "8f1cb48560f76b20f382b942500fceac") ; 499 + 500 + case 501 + ~key:(String.make 64 '0') 502 + ~nonce:("01" ^ String.make 14 '0') 503 + ~output0:("ef3fdfd6c61578fbf5cf35bd3dd33b80" ^ 504 + "09631634d21e42ac33960bd138e50d32" ^ 505 + "111e4caf237ee53ca8ad6426194a8854" ^ 506 + "5ddc497a0b466e7d6bbdb0041b2f586b") 507 + ~output1:("5305e5e44aff19b235936144675efbe4" ^ 508 + "409eb7e8e5f1430f5f5836aeb49bb532" ^ 509 + "8b017c4b9dc11f8a03863fa803dc71d5" ^ 510 + "726b2b6b31aa32708afe5af1d6b69058") ; 511 + 512 + case 513 + ~key:(String.make 64 'f') 514 + ~nonce:(String.make 16 'f') 515 + ~output0:("d9bf3f6bce6ed0b54254557767fb5744" ^ 516 + "3dd4778911b606055c39cc25e674b836" ^ 517 + "3feabc57fde54f790c52c8ae43240b79" ^ 518 + "d49042b777bfd6cb80e931270b7f50eb") 519 + ~output1:("5bac2acd86a836c5dc98c116c1217ec3" ^ 520 + "1d3a63a9451319f097f3b4d6dab07787" ^ 521 + "19477d24d24b403a12241d7cca064f79" ^ 522 + "0f1d51ccaff6b1667d4bbca1958c4306") ; 523 + 524 + case 525 + ~key:(String.make 64 '5') 526 + ~nonce:(String.make 16 '5') 527 + ~output0:("bea9411aa453c5434a5ae8c92862f564" ^ 528 + "396855a9ea6e22d6d3b50ae1b3663311" ^ 529 + "a4a3606c671d605ce16c3aece8e61ea1" ^ 530 + "45c59775017bee2fa6f88afc758069f7") 531 + ~output1:("e0b8f676e644216f4d2a3422d7fa36c6" ^ 532 + "c4931aca950e9da42788e6d0b6d1cd83" ^ 533 + "8ef652e97b145b14871eae6c6804c700" ^ 534 + "4db5ac2fce4c68c726d004b10fcaba86") ; 535 + 536 + case 537 + ~key:(String.make 64 'a') 538 + ~nonce:(String.make 16 'a') 539 + ~output0:("9aa2a9f656efde5aa7591c5fed4b35ae" ^ 540 + "a2895dec7cb4543b9e9f21f5e7bcbcf3" ^ 541 + "c43c748a970888f8248393a09d43e0b7" ^ 542 + "e164bc4d0b0fb240a2d72115c4808906") 543 + ~output1:("72184489440545d021d97ef6b693dfe5" ^ 544 + "b2c132d47e6f041c9063651f96b623e6" ^ 545 + "2a11999a23b6f7c461b2153026ad5e86" ^ 546 + "6a2e597ed07b8401dec63a0934c6b2a9") ; 547 + 548 + case 549 + ~key:"00112233445566778899aabbccddeeffffeeddccbbaa99887766554433221100" 550 + ~nonce:"0f1e2d3c4b5a6978" 551 + ~output0:("9fadf409c00811d00431d67efbd88fba" ^ 552 + "59218d5d6708b1d685863fabbb0e961e" ^ 553 + "ea480fd6fb532bfd494b215101505742" ^ 554 + "3ab60a63fe4f55f7a212e2167ccab931") 555 + ~output1:("fbfd29cf7bc1d279eddf25dd316bb884" ^ 556 + "3d6edee0bd1ef121d12fa17cbc2c574c" ^ 557 + "ccab5e275167b08bd686f8a09df87ec3" ^ 558 + "ffb35361b94ebfa13fec0e4889d18da5") ; 559 + 560 + case 561 + ~key:"c46ec1b18ce8a878725a37e780dfb7351f68ed2e194c79fbc6aebee1a667975d" 562 + ~nonce:"1ada31d5cf688221" 563 + ~output0:("f63a89b75c2271f9368816542ba52f06" ^ 564 + "ed49241792302b00b5e8f80ae9a473af" ^ 565 + "c25b218f519af0fdd406362e8d69de7f" ^ 566 + "54c604a6e00f353f110f771bdca8ab92") 567 + ~output1:("e5fbc34e60a1d9a9db17345b0a402736" ^ 568 + "853bf910b060bdf1f897b6290f01d138" ^ 569 + "ae2c4c90225ba9ea14d518f55929dea0" ^ 570 + "98ca7a6ccfe61227053c84e49a4a3332") ; 571 + 572 + case 573 + ~key:(String.make 32 '0') 574 + ~nonce:(String.make 16 '0') 575 + ~output0:("89670952608364fd00b2f90936f031c8" ^ 576 + "e756e15dba04b8493d00429259b20f46" ^ 577 + "cc04f111246b6c2ce066be3bfb32d9aa" ^ 578 + "0fddfbc12123d4b9e44f34dca05a103f") 579 + ~output1:("6cd135c2878c832b5896b134f6142a9d" ^ 580 + "4d8d0d8f1026d20a0a81512cbce6e975" ^ 581 + "8a7143d021978022a384141a80cea306" ^ 582 + "2f41f67a752e66ad3411984c787e30ad") ; 583 + 584 + case 585 + ~key:("01" ^ String.make 30 '0') 586 + ~nonce:(String.make 16 '0') 587 + ~output0:("ae56060d04f5b597897ff2af1388dbce" ^ 588 + "ff5a2a4920335dc17a3cb1b1b10fbe70" ^ 589 + "ece8f4864d8c7cdf0076453a8291c7db" ^ 590 + "eb3aa9c9d10e8ca36be4449376ed7c42") 591 + ~output1:("fc3d471c34a36fbbf616bc0a0e7c5230" ^ 592 + "30d944f43ec3e78dd6a12466547cb4f7" ^ 593 + "b3cebd0a5005e762e562d1375b7ac445" ^ 594 + "93a991b85d1a60fba2035dfaa2a642d5") ; 595 + 596 + case 597 + ~key:(String.make 32 '0') 598 + ~nonce:("01" ^ String.make 14 '0') 599 + ~output0:("1663879eb3f2c9949e2388caa343d361" ^ 600 + "bb132771245ae6d027ca9cb010dc1fa7" ^ 601 + "178dc41f8278bc1f64b3f12769a24097" ^ 602 + "f40d63a86366bdb36ac08abe60c07fe8") 603 + ~output1:("b057375c89144408cc744624f69f7f4c" ^ 604 + "cbd93366c92fc4dfcada65f1b959d8c6" ^ 605 + "4dfc50de711fb46416c2553cc60f21bb" ^ 606 + "fd006491cb17888b4fb3521c4fdd8745") ; 607 + 608 + case 609 + ~key:(String.make 32 'f') 610 + ~nonce:(String.make 16 'f') 611 + ~output0:("992947c3966126a0e660a3e95db048de" ^ 612 + "091fb9e0185b1e41e41015bb7ee50150" ^ 613 + "399e4760b262f9d53f26d8dd19e56f5c" ^ 614 + "506ae0c3619fa67fb0c408106d0203ee") 615 + ~output1:("40ea3cfa61fa32a2fda8d1238a2135d9" ^ 616 + "d4178775240f99007064a6a7f0c731b6" ^ 617 + "7c227c52ef796b6bed9f9059ba0614bc" ^ 618 + "f6dd6e38917f3b150e576375be50ed67") ; 619 + 620 + case 621 + ~key:(String.make 32 '5') 622 + ~nonce:(String.make 16 '5') 623 + ~output0:("357d7d94f966778f5815a2051dcb0413" ^ 624 + "3b26b0ead9f57dd09927837bc3067e4b" ^ 625 + "6bf299ad81f7f50c8da83c7810bfc17b" ^ 626 + "b6f4813ab6c326957045fd3fd5e19915") 627 + ~output1:("ec744a6b9bf8cbdcb36d8b6a5499c68a" ^ 628 + "08ef7be6cc1e93f2f5bcd2cad4e47c18" ^ 629 + "a3e5d94b5666382c6d130d822dd56aac" ^ 630 + "b0f8195278e7b292495f09868ddf12cc") ; 631 + 632 + case 633 + ~key:(String.make 32 'a') 634 + ~nonce:(String.make 16 'a') 635 + ~output0:("fc79acbd58526103862776aab20f3b7d" ^ 636 + "8d3149b2fab65766299316b6e5b16684" ^ 637 + "de5de548c1b7d083efd9e3052319e0c6" ^ 638 + "254141da04a6586df800f64d46b01c87") 639 + ~output1:("1f05bc67e07628ebe6f6865a2177e0b6" ^ 640 + "6a558aa7cc1e8ff1a98d27f7071f8335" ^ 641 + "efce4537bb0ef7b573b32f32765f2900" ^ 642 + "7da53bba62e7a44d006f41eb28fe15d6") ; 643 + 644 + case 645 + ~key:"00112233445566778899aabbccddeeff" 646 + ~nonce:"0f1e2d3c4b5a6978" 647 + ~output0:("d1abf630467eb4f67f1cfb47cd626aae" ^ 648 + "8afedbbe4ff8fc5fe9cfae307e74ed45" ^ 649 + "1f1404425ad2b54569d5f18148939971" ^ 650 + "abb8fafc88ce4ac7fe1c3d1f7a1eb7ca") 651 + ~output1:("e76ca87b61a9713541497760dd9ae059" ^ 652 + "350cad0dcedfaa80a883119a1a6f987f" ^ 653 + "d1ce91fd8ee0828034b411200a9745a2" ^ 654 + "85554475d12afc04887fef3516d12a2c") ; 655 + 656 + case 657 + ~key:"c46ec1b18ce8a878725a37e780dfb735" 658 + ~nonce:"1ada31d5cf688221" 659 + ~output0:("826abdd84460e2e9349f0ef4af5b179b" ^ 660 + "426e4b2d109a9c5bb44000ae51bea90a" ^ 661 + "496beeef62a76850ff3f0402c4ddc99f" ^ 662 + "6db07f151c1c0dfac2e56565d6289625") 663 + ~output1:("5b23132e7b469c7bfb88fa95d44ca5ae" ^ 664 + "3e45e848a4108e98bad7a9eb15512784" ^ 665 + "a6a9e6e591dce674120acaf9040ff50f" ^ 666 + "f3ac30ccfb5e14204f5e4268b90a8804") 667 + ] 668 + 669 + let poly1305_rfc8439_2_5_2 _ = 670 + let key = vx "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b" 671 + and data = Cstruct.of_string "Cryptographic Forum Research Group" 672 + and output = vx "a8061dc1305136c6c22b8baf0c0127a9" 673 + in 674 + assert_cs_equal ~msg:"poly 1305 RFC8439 Section 2.5.2" 675 + (Poly1305.mac ~key data) output 676 + 416 677 let suite = [ 417 678 "AES-ECB" >::: [ "SP 300-38A" >::: aes_ecb_cases ] ; 418 679 "AES-CBC" >::: [ "SP 300-38A" >::: aes_cbc_cases ] ; ··· 421 682 "AES-CCM" >::: ccm_cases ; 422 683 "AES-CCM-REGRESSION" >::: ccm_regressions ; 423 684 "AES-GCM-REGRESSION" >::: gcm_regressions ; 685 + "Chacha20" >::: chacha20_cases ; 686 + "poly1305" >:: poly1305_rfc8439_2_5_2 ; 424 687 ]
+1 -1
xen/dune
··· 7 7 (libraries mirage-xen-posix) 8 8 (c_flags (:standard) (:include ../src/cflags.sexp) (:include cflags-xen.sexp)) 9 9 (c_names detect_cpu_features misc misc_sse hash_stubs md5 sha1 sha256 sha512 10 - aes_generic aes_aesni des_generic 10 + aes_generic aes_aesni des_generic chacha poly1305-donna 11 11 ghash_pclmul ghash_generic ghash_ctmul 12 12 entropy_cpu_stubs) 13 13 )