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

Configure Feed

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

crypto: vendor BearSSL constant-time fallbacks for non-x86 AES/GHASH

Replace the non-constant-time table-driven AES (aes_generic.c) and
GHASH (ghash_generic.c) fallback paths with BearSSL's aes_ct64 and
ghash_ctmul64 implementations (Thomas Pornin, MIT license).

This closes the cache-timing side channel on non-x86 hosts (ARM64,
RISC-V, 32-bit) that was flagged upstream as mirage/mirage-crypto#36
in March 2020 but never fixed. The x86 AES-NI and PCLMUL paths
(hand-tuned mirage-crypto code with 8-way GHASH aggregation) are
kept unchanged — the diff with upstream mirage-crypto is now just
the header rename.

Includes scripts/import.ml which vendors a minimal subset of BearSSL
and auto-generates bearssl/inner.h from the upstream source tree.
Each vendored file is stamped with the BearSSL commit hash.

+1348 -68
+280
scripts/import.ml
··· 1 + (* import.ml -- vendor BearSSL source files into ocaml-crypto/src/c/bearssl/. 2 + 3 + Usage: ocaml scripts/import.ml /path/to/bearssl 4 + 5 + We only vendor BearSSL's *constant-time* fallbacks (aes_ct64, 6 + ghash_ctmul64). The x86 AES-NI / PCLMUL paths are provided by the 7 + hand-tuned mirage-crypto code in ../aes_aesni.c / ../ghash_pclmul.c, 8 + which is faster (8-way GHASH aggregation, precomputed powers of H). 9 + 10 + - Copies a fixed set of .c files verbatim from BearSSL. 11 + - Extracts the function declarations and inline helpers we need 12 + from BearSSL's src/inner.h, generating a minimal inner.h. 13 + - Fails loudly if BearSSL has changed in a way that breaks extraction. 14 + 15 + This avoids vendoring all of BearSSL while keeping the C surface 16 + small and auditable. Re-run after upgrading BearSSL to refresh. 17 + *) 18 + 19 + let usage () = 20 + prerr_endline "Usage: ocaml import.ml /path/to/bearssl"; 21 + exit 1 22 + 23 + let bearssl = 24 + if Array.length Sys.argv <> 2 then usage (); 25 + Sys.argv.(1) 26 + 27 + (* Output directory: ocaml-crypto/src/c/bearssl/, relative to this script *) 28 + let dir = 29 + let script_dir = Filename.dirname Sys.argv.(0) in 30 + Filename.concat script_dir "../src/c/bearssl" 31 + 32 + let inner_src = Filename.concat bearssl "src/inner.h" 33 + 34 + let () = 35 + if not (Sys.file_exists inner_src) then begin 36 + Printf.eprintf "error: %s not found\n" inner_src; 37 + Printf.eprintf "Is %s a BearSSL source tree?\n" bearssl; 38 + exit 1 39 + end 40 + 41 + (* Capture the upstream commit hash so the generated header records 42 + exactly which BearSSL revision was vendored. Falls back to 43 + "unknown" if BearSSL is not a git checkout. *) 44 + let bearssl_revision = 45 + let tmp = Filename.temp_file "bearssl-rev" "" in 46 + let cmd = 47 + Printf.sprintf "git -C %s rev-parse HEAD > %s 2>/dev/null" 48 + (Filename.quote bearssl) (Filename.quote tmp) 49 + in 50 + let _ = Sys.command cmd in 51 + let ic = open_in tmp in 52 + let line = try input_line ic with End_of_file -> "unknown" in 53 + close_in ic; 54 + Sys.remove tmp; 55 + line 56 + 57 + (* --- Copy .c files verbatim, with a vendoring stamp prepended --- *) 58 + 59 + let copy_with_stamp ~rel_src src dst = 60 + let ic = open_in src in 61 + let oc = open_out dst in 62 + Printf.fprintf oc 63 + "/* Vendored from BearSSL %s\n\ 64 + \ * Source: %s\n\ 65 + \ * Imported by: ../scripts/import.ml -- do not edit by hand.\n\ 66 + \ */\n" 67 + bearssl_revision rel_src; 68 + (try 69 + while true do 70 + output_char oc (input_char ic) 71 + done 72 + with End_of_file -> ()); 73 + close_in ic; 74 + close_out oc 75 + 76 + let files_to_copy = 77 + [ 78 + (* Constant-time bitsliced AES (used by ../aes_generic.c on hosts 79 + without AES-NI -- includes ARM64, RISC-V, 32-bit, etc.) *) 80 + ("src/symcipher/aes_ct64.c", "aes_ct64.c"); 81 + ("src/symcipher/aes_ct64_enc.c", "aes_ct64_enc.c"); 82 + ("src/symcipher/aes_ct64_dec.c", "aes_ct64_dec.c"); 83 + (* Constant-time GHASH (used by ../ghash_generic.c on 64-bit 84 + hosts without PCLMUL. 32-bit hosts use ../ghash_ctmul.c, which 85 + is a verbatim copy of BearSSL's ghash_ctmul.c.) *) 86 + ("src/hash/ghash_ctmul64.c", "ghash_ctmul64.c"); 87 + (* Byte-encoding range helpers used by aes_ct64.c *) 88 + ("src/codec/dec32le.c", "dec32le.c"); 89 + ("src/codec/enc32le.c", "enc32le.c"); 90 + ] 91 + 92 + let () = 93 + List.iter 94 + (fun (rel_src, dst) -> 95 + let s = Filename.concat bearssl rel_src in 96 + let d = Filename.concat dir dst in 97 + if not (Sys.file_exists s) then begin 98 + Printf.eprintf "error: %s not found in BearSSL\n" s; 99 + exit 1 100 + end; 101 + copy_with_stamp ~rel_src s d) 102 + files_to_copy 103 + 104 + (* --- Extract from BearSSL's inner.h --- *) 105 + 106 + let read_lines path = 107 + let ic = open_in path in 108 + let lines = ref [] in 109 + (try 110 + while true do 111 + lines := input_line ic :: !lines 112 + done 113 + with End_of_file -> ()); 114 + close_in ic; 115 + Array.of_list (List.rev !lines) 116 + 117 + let inner_lines = read_lines inner_src 118 + let hash_lines = read_lines (Filename.concat bearssl "inc/bearssl_hash.h") 119 + 120 + let starts_with s p = 121 + String.length s >= String.length p && String.sub s 0 (String.length p) = p 122 + 123 + let contains s sub = 124 + let ls = String.length s and lsub = String.length sub in 125 + if lsub = 0 then true 126 + else if lsub > ls then false 127 + else 128 + let rec aux i = 129 + if i + lsub > ls then false 130 + else if String.sub s i lsub = sub then true 131 + else aux (i + 1) 132 + in 133 + aux 0 134 + 135 + (* Extract an inline function: from "static inline TYPE" through the 136 + matching "}". The function name appears on the line after 137 + "static inline TYPE". *) 138 + let extract_inline lines name = 139 + let n = Array.length lines in 140 + let rec find i = 141 + if i + 1 >= n then failwith ("inline function not found: " ^ name) 142 + else if 143 + starts_with lines.(i) "static inline" 144 + && starts_with lines.(i + 1) (name ^ "(") 145 + then i 146 + else find (i + 1) 147 + in 148 + let start = find 0 in 149 + let buf = Buffer.create 256 in 150 + let rec emit i in_body = 151 + if i >= n then failwith ("unterminated function: " ^ name); 152 + Buffer.add_string buf lines.(i); 153 + Buffer.add_char buf '\n'; 154 + if in_body && lines.(i) = "}" then () 155 + else if lines.(i) = "{" then emit (i + 1) true 156 + else emit (i + 1) in_body 157 + in 158 + emit start false; 159 + Buffer.contents buf 160 + 161 + (* Extract a single-line declaration starting with the given prefix *) 162 + let extract_decl lines prefix = 163 + let n = Array.length lines in 164 + let rec find i = 165 + if i >= n then failwith ("declaration not found: " ^ prefix) 166 + else if starts_with lines.(i) prefix && contains lines.(i) ";" then 167 + lines.(i) 168 + else find (i + 1) 169 + in 170 + find 0 171 + 172 + (* Check whether a line looks like a C comment line *) 173 + let is_comment_line s = 174 + let s = String.trim s in 175 + String.length s > 0 && (s.[0] = '*' || s.[0] = '/') 176 + 177 + (* Extract a multi-line declaration: from a line containing `marker` 178 + to the next line containing `;`. Skip comment lines. *) 179 + let extract_multiline_decl lines marker = 180 + let n = Array.length lines in 181 + let rec find i = 182 + if i >= n then failwith ("multi-line decl not found: " ^ marker) 183 + else if contains lines.(i) marker && not (is_comment_line lines.(i)) then i 184 + else find (i + 1) 185 + in 186 + let start = find 0 in 187 + let buf = Buffer.create 256 in 188 + let rec emit i = 189 + if i >= n then failwith ("unterminated decl: " ^ marker); 190 + Buffer.add_string buf lines.(i); 191 + Buffer.add_char buf '\n'; 192 + if contains lines.(i) ";" then () else emit (i + 1) 193 + in 194 + emit start; 195 + Buffer.contents buf 196 + 197 + (* --- Generate inner.h --- *) 198 + 199 + let oc = open_out (Filename.concat dir "inner.h") 200 + let p s = output_string oc s 201 + 202 + let pl s = 203 + output_string oc s; 204 + output_char oc '\n' 205 + 206 + let pf fmt = Printf.fprintf oc fmt 207 + 208 + let () = 209 + (* Header *) 210 + pl "/*"; 211 + pl " * Minimal subset of BearSSL inner.h for ocaml-crypto."; 212 + pl " * AUTO-GENERATED by ../scripts/import.ml -- do not edit by hand."; 213 + pl " *"; 214 + pf " * Vendored from BearSSL %s\n" bearssl_revision; 215 + pl " *"; 216 + pl " * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>"; 217 + pl " * MIT license (see individual .c files for full text)."; 218 + pl " */"; 219 + pl "#ifndef INNER_H__"; 220 + pl "#define INNER_H__"; 221 + pl "#include <string.h>"; 222 + pl "#include <stdint.h>"; 223 + pl ""; 224 + 225 + (* Byte encoding helpers. 226 + These contain #if BR_LE_UNALIGNED branches; we don't define 227 + BR_LE_UNALIGNED, so the portable #else branch is selected at 228 + compile time. *) 229 + pl "/* Byte encoding helpers (extracted from BearSSL src/inner.h)."; 230 + pl " * BR_LE_UNALIGNED / BR_BE_UNALIGNED are not defined, so the"; 231 + pl " * portable #else branches are selected. */"; 232 + List.iter 233 + (fun name -> 234 + p (extract_inline inner_lines name); 235 + pl "") 236 + [ 237 + "br_enc32le"; 238 + "br_enc32be"; 239 + "br_dec32le"; 240 + "br_dec32be"; 241 + "br_enc64be"; 242 + "br_dec64be"; 243 + ]; 244 + 245 + (* Range function declarations *) 246 + pl "/* Range function declarations */"; 247 + pl (extract_decl inner_lines "void br_range_dec32le"); 248 + pl (extract_decl inner_lines "void br_range_enc32le"); 249 + pl ""; 250 + 251 + (* aes_ct64 API *) 252 + pl "/* aes_ct64 API (extracted from BearSSL src/inner.h) */"; 253 + pl (extract_decl inner_lines "void br_aes_ct64_ortho"); 254 + pl (extract_decl inner_lines "void br_aes_ct64_interleave_in"); 255 + pl (extract_decl inner_lines "void br_aes_ct64_interleave_out"); 256 + pl (extract_decl inner_lines "void br_aes_ct64_bitslice_Sbox"); 257 + pl (extract_decl inner_lines "void br_aes_ct64_bitslice_invSbox"); 258 + p (extract_multiline_decl inner_lines "br_aes_ct64_bitslice_encrypt("); 259 + p (extract_multiline_decl inner_lines "br_aes_ct64_bitslice_decrypt("); 260 + p (extract_multiline_decl inner_lines "br_aes_ct64_keysched("); 261 + p (extract_multiline_decl inner_lines "br_aes_ct64_skey_expand("); 262 + pl ""; 263 + 264 + (* GHASH constant-time fallbacks. We don't vendor BearSSL's full 265 + bearssl_hash.h (44 KB), so we extract just the two declarations 266 + our ghash_generic.c / ghash_ctmul.c need. *) 267 + pl "/* GHASH constant-time fallbacks (extracted from BearSSL"; 268 + pl " * inc/bearssl_hash.h, used by ../ghash_generic.c on 64-bit and"; 269 + pl " * ../ghash_ctmul.c on 32-bit / MSVC). */"; 270 + pl (extract_decl hash_lines "void br_ghash_ctmul("); 271 + pl (extract_decl hash_lines "void br_ghash_ctmul64("); 272 + pl ""; 273 + pl "#endif /* INNER_H__ */"; 274 + 275 + close_out oc 276 + 277 + let () = 278 + Printf.printf "Imported BearSSL files into %s:\n" dir; 279 + List.iter (fun (_, dst) -> Printf.printf " %s\n" dst) files_to_copy; 280 + Printf.printf " inner.h (generated)\n"
-31
src/c/aes_aesni.c
··· 362 362 363 363 #endif /* __mc_ACCELERATE__ */ 364 364 365 - /* ------------------------------------------------------------------ */ 366 - /* Dispatch */ 367 - /* */ 368 - /* On x86: AES-NI accelerated path above. */ 369 - /* On ARM64 and other platforms: uses BearSSL aes_ct64 via */ 370 - /* mc_aes_*_generic (constant-time, no hardware intrinsics). */ 371 - /* ARM64 AES-CE acceleration: TODO (needs audited implementation). */ 372 - /* ------------------------------------------------------------------ */ 373 - 374 365 CAMLprim value 375 366 mc_aes_rk_size (value rounds) { 376 367 value s; 377 - #if defined(__mc_ACCELERATE__) 378 368 _mc_switch_accel(aesni, 379 369 s = mc_aes_rk_size_generic(rounds), 380 370 s = Val_int (_mc_aesni_rk_size (Int_val (rounds)))) 381 - #else 382 - s = mc_aes_rk_size_generic(rounds); 383 - #endif 384 371 return s; 385 372 } 386 373 387 374 CAMLprim value 388 375 mc_aes_derive_e_key (value key, value rk, value rounds) { 389 - #if defined(__mc_ACCELERATE__) 390 376 _mc_switch_accel(aesni, 391 377 mc_aes_derive_e_key_generic(key, rk, rounds), 392 378 _mc_aesni_derive_e_key (_st_uint8 (key), 393 379 _bp_uint8 (rk), 394 380 Int_val (rounds))) 395 - #else 396 - mc_aes_derive_e_key_generic(key, rk, rounds); 397 - #endif 398 381 return Val_unit; 399 382 } 400 383 401 384 CAMLprim value 402 385 mc_aes_derive_d_key (value key, value kr, value rounds, value rk) { 403 - #if defined(__mc_ACCELERATE__) 404 386 _mc_switch_accel(aesni, 405 387 mc_aes_derive_d_key_generic(key, kr, rounds, rk), 406 388 _mc_aesni_derive_d_key (_st_uint8 (key), 407 389 _bp_uint8 (kr), 408 390 Int_val (rounds), 409 391 Is_block(rk) ? _bp_uint8(Field(rk, 0)) : 0)) 410 - #else 411 - mc_aes_derive_d_key_generic(key, kr, rounds, rk); 412 - #endif 413 392 return Val_unit; 414 393 } 415 394 416 395 CAMLprim value 417 396 mc_aes_enc (value src, value off1, value dst, value off2, value rk, value rounds, value blocks) { 418 - #if defined(__mc_ACCELERATE__) 419 397 _mc_switch_accel(aesni, 420 398 mc_aes_enc_generic(src, off1, dst, off2, rk, rounds, blocks), 421 399 _mc_aesni_enc_blocks ( _st_uint8_off (src, off1), ··· 423 401 _st_uint8 (rk), 424 402 Int_val (rounds), 425 403 Int_val (blocks) )) 426 - #else 427 - mc_aes_enc_generic(src, off1, dst, off2, rk, rounds, blocks); 428 - #endif 429 404 return Val_unit; 430 405 } 431 406 432 407 CAMLprim value 433 408 mc_aes_dec (value src, value off1, value dst, value off2, value rk, value rounds, value blocks) { 434 - #if defined(__mc_ACCELERATE__) 435 409 _mc_switch_accel(aesni, 436 410 mc_aes_dec_generic(src, off1, dst, off2, rk, rounds, blocks), 437 411 _mc_aesni_dec_blocks ( _st_uint8_off (src, off1), ··· 439 413 _st_uint8 (rk), 440 414 Int_val (rounds), 441 415 Int_val (blocks) )) 442 - #else 443 - mc_aes_dec_generic(src, off1, dst, off2, rk, rounds, blocks); 444 - #endif 445 416 return Val_unit; 446 417 } 447 418 448 419 CAMLprim value mc_aes_mode (__unit ()) { 449 420 value enabled = 0; 450 - #if defined(__mc_ACCELERATE__) 451 421 _mc_switch_accel(aesni, 452 422 enabled = 0, 453 423 enabled = 1) 454 - #endif 455 424 return Val_int (enabled); 456 425 } 457 426
+402
src/c/bearssl/aes_ct64.c
··· 1 + /* Vendored from BearSSL 7bea48e5e850ab4cafbe68d3765cdaba13a86d6f 2 + * Source: src/symcipher/aes_ct64.c 3 + * Imported by: ../scripts/import.ml -- do not edit by hand. 4 + */ 5 + /* 6 + * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> 7 + * 8 + * Permission is hereby granted, free of charge, to any person obtaining 9 + * a copy of this software and associated documentation files (the 10 + * "Software"), to deal in the Software without restriction, including 11 + * without limitation the rights to use, copy, modify, merge, publish, 12 + * distribute, sublicense, and/or sell copies of the Software, and to 13 + * permit persons to whom the Software is furnished to do so, subject to 14 + * the following conditions: 15 + * 16 + * The above copyright notice and this permission notice shall be 17 + * included in all copies or substantial portions of the Software. 18 + * 19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 + * SOFTWARE. 27 + */ 28 + 29 + #include "inner.h" 30 + 31 + /* see inner.h */ 32 + void 33 + br_aes_ct64_bitslice_Sbox(uint64_t *q) 34 + { 35 + /* 36 + * This S-box implementation is a straightforward translation of 37 + * the circuit described by Boyar and Peralta in "A new 38 + * combinational logic minimization technique with applications 39 + * to cryptology" (https://eprint.iacr.org/2009/191.pdf). 40 + * 41 + * Note that variables x* (input) and s* (output) are numbered 42 + * in "reverse" order (x0 is the high bit, x7 is the low bit). 43 + */ 44 + 45 + uint64_t x0, x1, x2, x3, x4, x5, x6, x7; 46 + uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; 47 + uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; 48 + uint64_t y20, y21; 49 + uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; 50 + uint64_t z10, z11, z12, z13, z14, z15, z16, z17; 51 + uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; 52 + uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; 53 + uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; 54 + uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; 55 + uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; 56 + uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; 57 + uint64_t t60, t61, t62, t63, t64, t65, t66, t67; 58 + uint64_t s0, s1, s2, s3, s4, s5, s6, s7; 59 + 60 + x0 = q[7]; 61 + x1 = q[6]; 62 + x2 = q[5]; 63 + x3 = q[4]; 64 + x4 = q[3]; 65 + x5 = q[2]; 66 + x6 = q[1]; 67 + x7 = q[0]; 68 + 69 + /* 70 + * Top linear transformation. 71 + */ 72 + y14 = x3 ^ x5; 73 + y13 = x0 ^ x6; 74 + y9 = x0 ^ x3; 75 + y8 = x0 ^ x5; 76 + t0 = x1 ^ x2; 77 + y1 = t0 ^ x7; 78 + y4 = y1 ^ x3; 79 + y12 = y13 ^ y14; 80 + y2 = y1 ^ x0; 81 + y5 = y1 ^ x6; 82 + y3 = y5 ^ y8; 83 + t1 = x4 ^ y12; 84 + y15 = t1 ^ x5; 85 + y20 = t1 ^ x1; 86 + y6 = y15 ^ x7; 87 + y10 = y15 ^ t0; 88 + y11 = y20 ^ y9; 89 + y7 = x7 ^ y11; 90 + y17 = y10 ^ y11; 91 + y19 = y10 ^ y8; 92 + y16 = t0 ^ y11; 93 + y21 = y13 ^ y16; 94 + y18 = x0 ^ y16; 95 + 96 + /* 97 + * Non-linear section. 98 + */ 99 + t2 = y12 & y15; 100 + t3 = y3 & y6; 101 + t4 = t3 ^ t2; 102 + t5 = y4 & x7; 103 + t6 = t5 ^ t2; 104 + t7 = y13 & y16; 105 + t8 = y5 & y1; 106 + t9 = t8 ^ t7; 107 + t10 = y2 & y7; 108 + t11 = t10 ^ t7; 109 + t12 = y9 & y11; 110 + t13 = y14 & y17; 111 + t14 = t13 ^ t12; 112 + t15 = y8 & y10; 113 + t16 = t15 ^ t12; 114 + t17 = t4 ^ t14; 115 + t18 = t6 ^ t16; 116 + t19 = t9 ^ t14; 117 + t20 = t11 ^ t16; 118 + t21 = t17 ^ y20; 119 + t22 = t18 ^ y19; 120 + t23 = t19 ^ y21; 121 + t24 = t20 ^ y18; 122 + 123 + t25 = t21 ^ t22; 124 + t26 = t21 & t23; 125 + t27 = t24 ^ t26; 126 + t28 = t25 & t27; 127 + t29 = t28 ^ t22; 128 + t30 = t23 ^ t24; 129 + t31 = t22 ^ t26; 130 + t32 = t31 & t30; 131 + t33 = t32 ^ t24; 132 + t34 = t23 ^ t33; 133 + t35 = t27 ^ t33; 134 + t36 = t24 & t35; 135 + t37 = t36 ^ t34; 136 + t38 = t27 ^ t36; 137 + t39 = t29 & t38; 138 + t40 = t25 ^ t39; 139 + 140 + t41 = t40 ^ t37; 141 + t42 = t29 ^ t33; 142 + t43 = t29 ^ t40; 143 + t44 = t33 ^ t37; 144 + t45 = t42 ^ t41; 145 + z0 = t44 & y15; 146 + z1 = t37 & y6; 147 + z2 = t33 & x7; 148 + z3 = t43 & y16; 149 + z4 = t40 & y1; 150 + z5 = t29 & y7; 151 + z6 = t42 & y11; 152 + z7 = t45 & y17; 153 + z8 = t41 & y10; 154 + z9 = t44 & y12; 155 + z10 = t37 & y3; 156 + z11 = t33 & y4; 157 + z12 = t43 & y13; 158 + z13 = t40 & y5; 159 + z14 = t29 & y2; 160 + z15 = t42 & y9; 161 + z16 = t45 & y14; 162 + z17 = t41 & y8; 163 + 164 + /* 165 + * Bottom linear transformation. 166 + */ 167 + t46 = z15 ^ z16; 168 + t47 = z10 ^ z11; 169 + t48 = z5 ^ z13; 170 + t49 = z9 ^ z10; 171 + t50 = z2 ^ z12; 172 + t51 = z2 ^ z5; 173 + t52 = z7 ^ z8; 174 + t53 = z0 ^ z3; 175 + t54 = z6 ^ z7; 176 + t55 = z16 ^ z17; 177 + t56 = z12 ^ t48; 178 + t57 = t50 ^ t53; 179 + t58 = z4 ^ t46; 180 + t59 = z3 ^ t54; 181 + t60 = t46 ^ t57; 182 + t61 = z14 ^ t57; 183 + t62 = t52 ^ t58; 184 + t63 = t49 ^ t58; 185 + t64 = z4 ^ t59; 186 + t65 = t61 ^ t62; 187 + t66 = z1 ^ t63; 188 + s0 = t59 ^ t63; 189 + s6 = t56 ^ ~t62; 190 + s7 = t48 ^ ~t60; 191 + t67 = t64 ^ t65; 192 + s3 = t53 ^ t66; 193 + s4 = t51 ^ t66; 194 + s5 = t47 ^ t65; 195 + s1 = t64 ^ ~s3; 196 + s2 = t55 ^ ~t67; 197 + 198 + q[7] = s0; 199 + q[6] = s1; 200 + q[5] = s2; 201 + q[4] = s3; 202 + q[3] = s4; 203 + q[2] = s5; 204 + q[1] = s6; 205 + q[0] = s7; 206 + } 207 + 208 + /* see inner.h */ 209 + void 210 + br_aes_ct64_ortho(uint64_t *q) 211 + { 212 + #define SWAPN(cl, ch, s, x, y) do { \ 213 + uint64_t a, b; \ 214 + a = (x); \ 215 + b = (y); \ 216 + (x) = (a & (uint64_t)cl) | ((b & (uint64_t)cl) << (s)); \ 217 + (y) = ((a & (uint64_t)ch) >> (s)) | (b & (uint64_t)ch); \ 218 + } while (0) 219 + 220 + #define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) 221 + #define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) 222 + #define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) 223 + 224 + SWAP2(q[0], q[1]); 225 + SWAP2(q[2], q[3]); 226 + SWAP2(q[4], q[5]); 227 + SWAP2(q[6], q[7]); 228 + 229 + SWAP4(q[0], q[2]); 230 + SWAP4(q[1], q[3]); 231 + SWAP4(q[4], q[6]); 232 + SWAP4(q[5], q[7]); 233 + 234 + SWAP8(q[0], q[4]); 235 + SWAP8(q[1], q[5]); 236 + SWAP8(q[2], q[6]); 237 + SWAP8(q[3], q[7]); 238 + } 239 + 240 + /* see inner.h */ 241 + void 242 + br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) 243 + { 244 + uint64_t x0, x1, x2, x3; 245 + 246 + x0 = w[0]; 247 + x1 = w[1]; 248 + x2 = w[2]; 249 + x3 = w[3]; 250 + x0 |= (x0 << 16); 251 + x1 |= (x1 << 16); 252 + x2 |= (x2 << 16); 253 + x3 |= (x3 << 16); 254 + x0 &= (uint64_t)0x0000FFFF0000FFFF; 255 + x1 &= (uint64_t)0x0000FFFF0000FFFF; 256 + x2 &= (uint64_t)0x0000FFFF0000FFFF; 257 + x3 &= (uint64_t)0x0000FFFF0000FFFF; 258 + x0 |= (x0 << 8); 259 + x1 |= (x1 << 8); 260 + x2 |= (x2 << 8); 261 + x3 |= (x3 << 8); 262 + x0 &= (uint64_t)0x00FF00FF00FF00FF; 263 + x1 &= (uint64_t)0x00FF00FF00FF00FF; 264 + x2 &= (uint64_t)0x00FF00FF00FF00FF; 265 + x3 &= (uint64_t)0x00FF00FF00FF00FF; 266 + *q0 = x0 | (x2 << 8); 267 + *q1 = x1 | (x3 << 8); 268 + } 269 + 270 + /* see inner.h */ 271 + void 272 + br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) 273 + { 274 + uint64_t x0, x1, x2, x3; 275 + 276 + x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; 277 + x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; 278 + x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; 279 + x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; 280 + x0 |= (x0 >> 8); 281 + x1 |= (x1 >> 8); 282 + x2 |= (x2 >> 8); 283 + x3 |= (x3 >> 8); 284 + x0 &= (uint64_t)0x0000FFFF0000FFFF; 285 + x1 &= (uint64_t)0x0000FFFF0000FFFF; 286 + x2 &= (uint64_t)0x0000FFFF0000FFFF; 287 + x3 &= (uint64_t)0x0000FFFF0000FFFF; 288 + w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); 289 + w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); 290 + w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); 291 + w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); 292 + } 293 + 294 + static const unsigned char Rcon[] = { 295 + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 296 + }; 297 + 298 + static uint32_t 299 + sub_word(uint32_t x) 300 + { 301 + uint64_t q[8]; 302 + 303 + memset(q, 0, sizeof q); 304 + q[0] = x; 305 + br_aes_ct64_ortho(q); 306 + br_aes_ct64_bitslice_Sbox(q); 307 + br_aes_ct64_ortho(q); 308 + return (uint32_t)q[0]; 309 + } 310 + 311 + /* see inner.h */ 312 + unsigned 313 + br_aes_ct64_keysched(uint64_t *comp_skey, const void *key, size_t key_len) 314 + { 315 + unsigned num_rounds; 316 + int i, j, k, nk, nkf; 317 + uint32_t tmp; 318 + uint32_t skey[60]; 319 + 320 + switch (key_len) { 321 + case 16: 322 + num_rounds = 10; 323 + break; 324 + case 24: 325 + num_rounds = 12; 326 + break; 327 + case 32: 328 + num_rounds = 14; 329 + break; 330 + default: 331 + /* abort(); */ 332 + return 0; 333 + } 334 + nk = (int)(key_len >> 2); 335 + nkf = (int)((num_rounds + 1) << 2); 336 + br_range_dec32le(skey, (key_len >> 2), key); 337 + tmp = skey[(key_len >> 2) - 1]; 338 + for (i = nk, j = 0, k = 0; i < nkf; i ++) { 339 + if (j == 0) { 340 + tmp = (tmp << 24) | (tmp >> 8); 341 + tmp = sub_word(tmp) ^ Rcon[k]; 342 + } else if (nk > 6 && j == 4) { 343 + tmp = sub_word(tmp); 344 + } 345 + tmp ^= skey[i - nk]; 346 + skey[i] = tmp; 347 + if (++ j == nk) { 348 + j = 0; 349 + k ++; 350 + } 351 + } 352 + 353 + for (i = 0, j = 0; i < nkf; i += 4, j += 2) { 354 + uint64_t q[8]; 355 + 356 + br_aes_ct64_interleave_in(&q[0], &q[4], skey + i); 357 + q[1] = q[0]; 358 + q[2] = q[0]; 359 + q[3] = q[0]; 360 + q[5] = q[4]; 361 + q[6] = q[4]; 362 + q[7] = q[4]; 363 + br_aes_ct64_ortho(q); 364 + comp_skey[j + 0] = 365 + (q[0] & (uint64_t)0x1111111111111111) 366 + | (q[1] & (uint64_t)0x2222222222222222) 367 + | (q[2] & (uint64_t)0x4444444444444444) 368 + | (q[3] & (uint64_t)0x8888888888888888); 369 + comp_skey[j + 1] = 370 + (q[4] & (uint64_t)0x1111111111111111) 371 + | (q[5] & (uint64_t)0x2222222222222222) 372 + | (q[6] & (uint64_t)0x4444444444444444) 373 + | (q[7] & (uint64_t)0x8888888888888888); 374 + } 375 + return num_rounds; 376 + } 377 + 378 + /* see inner.h */ 379 + void 380 + br_aes_ct64_skey_expand(uint64_t *skey, 381 + unsigned num_rounds, const uint64_t *comp_skey) 382 + { 383 + unsigned u, v, n; 384 + 385 + n = (num_rounds + 1) << 1; 386 + for (u = 0, v = 0; u < n; u ++, v += 4) { 387 + uint64_t x0, x1, x2, x3; 388 + 389 + x0 = x1 = x2 = x3 = comp_skey[u]; 390 + x0 &= (uint64_t)0x1111111111111111; 391 + x1 &= (uint64_t)0x2222222222222222; 392 + x2 &= (uint64_t)0x4444444444444444; 393 + x3 &= (uint64_t)0x8888888888888888; 394 + x1 >>= 1; 395 + x2 >>= 2; 396 + x3 >>= 3; 397 + skey[v + 0] = (x0 << 4) - x0; 398 + skey[v + 1] = (x1 << 4) - x1; 399 + skey[v + 2] = (x2 << 4) - x2; 400 + skey[v + 3] = (x3 << 4) - x3; 401 + } 402 + }
+163
src/c/bearssl/aes_ct64_dec.c
··· 1 + /* Vendored from BearSSL 7bea48e5e850ab4cafbe68d3765cdaba13a86d6f 2 + * Source: src/symcipher/aes_ct64_dec.c 3 + * Imported by: ../scripts/import.ml -- do not edit by hand. 4 + */ 5 + /* 6 + * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> 7 + * 8 + * Permission is hereby granted, free of charge, to any person obtaining 9 + * a copy of this software and associated documentation files (the 10 + * "Software"), to deal in the Software without restriction, including 11 + * without limitation the rights to use, copy, modify, merge, publish, 12 + * distribute, sublicense, and/or sell copies of the Software, and to 13 + * permit persons to whom the Software is furnished to do so, subject to 14 + * the following conditions: 15 + * 16 + * The above copyright notice and this permission notice shall be 17 + * included in all copies or substantial portions of the Software. 18 + * 19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 + * SOFTWARE. 27 + */ 28 + 29 + #include "inner.h" 30 + 31 + /* see inner.h */ 32 + void 33 + br_aes_ct64_bitslice_invSbox(uint64_t *q) 34 + { 35 + /* 36 + * See br_aes_ct_bitslice_invSbox(). This is the natural extension 37 + * to 64-bit registers. 38 + */ 39 + uint64_t q0, q1, q2, q3, q4, q5, q6, q7; 40 + 41 + q0 = ~q[0]; 42 + q1 = ~q[1]; 43 + q2 = q[2]; 44 + q3 = q[3]; 45 + q4 = q[4]; 46 + q5 = ~q[5]; 47 + q6 = ~q[6]; 48 + q7 = q[7]; 49 + q[7] = q1 ^ q4 ^ q6; 50 + q[6] = q0 ^ q3 ^ q5; 51 + q[5] = q7 ^ q2 ^ q4; 52 + q[4] = q6 ^ q1 ^ q3; 53 + q[3] = q5 ^ q0 ^ q2; 54 + q[2] = q4 ^ q7 ^ q1; 55 + q[1] = q3 ^ q6 ^ q0; 56 + q[0] = q2 ^ q5 ^ q7; 57 + 58 + br_aes_ct64_bitslice_Sbox(q); 59 + 60 + q0 = ~q[0]; 61 + q1 = ~q[1]; 62 + q2 = q[2]; 63 + q3 = q[3]; 64 + q4 = q[4]; 65 + q5 = ~q[5]; 66 + q6 = ~q[6]; 67 + q7 = q[7]; 68 + q[7] = q1 ^ q4 ^ q6; 69 + q[6] = q0 ^ q3 ^ q5; 70 + q[5] = q7 ^ q2 ^ q4; 71 + q[4] = q6 ^ q1 ^ q3; 72 + q[3] = q5 ^ q0 ^ q2; 73 + q[2] = q4 ^ q7 ^ q1; 74 + q[1] = q3 ^ q6 ^ q0; 75 + q[0] = q2 ^ q5 ^ q7; 76 + } 77 + 78 + static void 79 + add_round_key(uint64_t *q, const uint64_t *sk) 80 + { 81 + int i; 82 + 83 + for (i = 0; i < 8; i ++) { 84 + q[i] ^= sk[i]; 85 + } 86 + } 87 + 88 + static void 89 + inv_shift_rows(uint64_t *q) 90 + { 91 + int i; 92 + 93 + for (i = 0; i < 8; i ++) { 94 + uint64_t x; 95 + 96 + x = q[i]; 97 + q[i] = (x & (uint64_t)0x000000000000FFFF) 98 + | ((x & (uint64_t)0x000000000FFF0000) << 4) 99 + | ((x & (uint64_t)0x00000000F0000000) >> 12) 100 + | ((x & (uint64_t)0x000000FF00000000) << 8) 101 + | ((x & (uint64_t)0x0000FF0000000000) >> 8) 102 + | ((x & (uint64_t)0x000F000000000000) << 12) 103 + | ((x & (uint64_t)0xFFF0000000000000) >> 4); 104 + } 105 + } 106 + 107 + static inline uint64_t 108 + rotr32(uint64_t x) 109 + { 110 + return (x << 32) | (x >> 32); 111 + } 112 + 113 + static void 114 + inv_mix_columns(uint64_t *q) 115 + { 116 + uint64_t q0, q1, q2, q3, q4, q5, q6, q7; 117 + uint64_t r0, r1, r2, r3, r4, r5, r6, r7; 118 + 119 + q0 = q[0]; 120 + q1 = q[1]; 121 + q2 = q[2]; 122 + q3 = q[3]; 123 + q4 = q[4]; 124 + q5 = q[5]; 125 + q6 = q[6]; 126 + q7 = q[7]; 127 + r0 = (q0 >> 16) | (q0 << 48); 128 + r1 = (q1 >> 16) | (q1 << 48); 129 + r2 = (q2 >> 16) | (q2 << 48); 130 + r3 = (q3 >> 16) | (q3 << 48); 131 + r4 = (q4 >> 16) | (q4 << 48); 132 + r5 = (q5 >> 16) | (q5 << 48); 133 + r6 = (q6 >> 16) | (q6 << 48); 134 + r7 = (q7 >> 16) | (q7 << 48); 135 + 136 + q[0] = q5 ^ q6 ^ q7 ^ r0 ^ r5 ^ r7 ^ rotr32(q0 ^ q5 ^ q6 ^ r0 ^ r5); 137 + q[1] = q0 ^ q5 ^ r0 ^ r1 ^ r5 ^ r6 ^ r7 ^ rotr32(q1 ^ q5 ^ q7 ^ r1 ^ r5 ^ r6); 138 + q[2] = q0 ^ q1 ^ q6 ^ r1 ^ r2 ^ r6 ^ r7 ^ rotr32(q0 ^ q2 ^ q6 ^ r2 ^ r6 ^ r7); 139 + q[3] = q0 ^ q1 ^ q2 ^ q5 ^ q6 ^ r0 ^ r2 ^ r3 ^ r5 ^ rotr32(q0 ^ q1 ^ q3 ^ q5 ^ q6 ^ q7 ^ r0 ^ r3 ^ r5 ^ r7); 140 + q[4] = q1 ^ q2 ^ q3 ^ q5 ^ r1 ^ r3 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr32(q1 ^ q2 ^ q4 ^ q5 ^ q7 ^ r1 ^ r4 ^ r5 ^ r6); 141 + q[5] = q2 ^ q3 ^ q4 ^ q6 ^ r2 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr32(q2 ^ q3 ^ q5 ^ q6 ^ r2 ^ r5 ^ r6 ^ r7); 142 + q[6] = q3 ^ q4 ^ q5 ^ q7 ^ r3 ^ r5 ^ r6 ^ r7 ^ rotr32(q3 ^ q4 ^ q6 ^ q7 ^ r3 ^ r6 ^ r7); 143 + q[7] = q4 ^ q5 ^ q6 ^ r4 ^ r6 ^ r7 ^ rotr32(q4 ^ q5 ^ q7 ^ r4 ^ r7); 144 + } 145 + 146 + /* see inner.h */ 147 + void 148 + br_aes_ct64_bitslice_decrypt(unsigned num_rounds, 149 + const uint64_t *skey, uint64_t *q) 150 + { 151 + unsigned u; 152 + 153 + add_round_key(q, skey + (num_rounds << 3)); 154 + for (u = num_rounds - 1; u > 0; u --) { 155 + inv_shift_rows(q); 156 + br_aes_ct64_bitslice_invSbox(q); 157 + add_round_key(q, skey + (u << 3)); 158 + inv_mix_columns(q); 159 + } 160 + inv_shift_rows(q); 161 + br_aes_ct64_bitslice_invSbox(q); 162 + add_round_key(q, skey); 163 + }
+119
src/c/bearssl/aes_ct64_enc.c
··· 1 + /* Vendored from BearSSL 7bea48e5e850ab4cafbe68d3765cdaba13a86d6f 2 + * Source: src/symcipher/aes_ct64_enc.c 3 + * Imported by: ../scripts/import.ml -- do not edit by hand. 4 + */ 5 + /* 6 + * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> 7 + * 8 + * Permission is hereby granted, free of charge, to any person obtaining 9 + * a copy of this software and associated documentation files (the 10 + * "Software"), to deal in the Software without restriction, including 11 + * without limitation the rights to use, copy, modify, merge, publish, 12 + * distribute, sublicense, and/or sell copies of the Software, and to 13 + * permit persons to whom the Software is furnished to do so, subject to 14 + * the following conditions: 15 + * 16 + * The above copyright notice and this permission notice shall be 17 + * included in all copies or substantial portions of the Software. 18 + * 19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 + * SOFTWARE. 27 + */ 28 + 29 + #include "inner.h" 30 + 31 + static inline void 32 + add_round_key(uint64_t *q, const uint64_t *sk) 33 + { 34 + q[0] ^= sk[0]; 35 + q[1] ^= sk[1]; 36 + q[2] ^= sk[2]; 37 + q[3] ^= sk[3]; 38 + q[4] ^= sk[4]; 39 + q[5] ^= sk[5]; 40 + q[6] ^= sk[6]; 41 + q[7] ^= sk[7]; 42 + } 43 + 44 + static inline void 45 + shift_rows(uint64_t *q) 46 + { 47 + int i; 48 + 49 + for (i = 0; i < 8; i ++) { 50 + uint64_t x; 51 + 52 + x = q[i]; 53 + q[i] = (x & (uint64_t)0x000000000000FFFF) 54 + | ((x & (uint64_t)0x00000000FFF00000) >> 4) 55 + | ((x & (uint64_t)0x00000000000F0000) << 12) 56 + | ((x & (uint64_t)0x0000FF0000000000) >> 8) 57 + | ((x & (uint64_t)0x000000FF00000000) << 8) 58 + | ((x & (uint64_t)0xF000000000000000) >> 12) 59 + | ((x & (uint64_t)0x0FFF000000000000) << 4); 60 + } 61 + } 62 + 63 + static inline uint64_t 64 + rotr32(uint64_t x) 65 + { 66 + return (x << 32) | (x >> 32); 67 + } 68 + 69 + static inline void 70 + mix_columns(uint64_t *q) 71 + { 72 + uint64_t q0, q1, q2, q3, q4, q5, q6, q7; 73 + uint64_t r0, r1, r2, r3, r4, r5, r6, r7; 74 + 75 + q0 = q[0]; 76 + q1 = q[1]; 77 + q2 = q[2]; 78 + q3 = q[3]; 79 + q4 = q[4]; 80 + q5 = q[5]; 81 + q6 = q[6]; 82 + q7 = q[7]; 83 + r0 = (q0 >> 16) | (q0 << 48); 84 + r1 = (q1 >> 16) | (q1 << 48); 85 + r2 = (q2 >> 16) | (q2 << 48); 86 + r3 = (q3 >> 16) | (q3 << 48); 87 + r4 = (q4 >> 16) | (q4 << 48); 88 + r5 = (q5 >> 16) | (q5 << 48); 89 + r6 = (q6 >> 16) | (q6 << 48); 90 + r7 = (q7 >> 16) | (q7 << 48); 91 + 92 + q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); 93 + q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); 94 + q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); 95 + q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); 96 + q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); 97 + q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); 98 + q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); 99 + q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); 100 + } 101 + 102 + /* see inner.h */ 103 + void 104 + br_aes_ct64_bitslice_encrypt(unsigned num_rounds, 105 + const uint64_t *skey, uint64_t *q) 106 + { 107 + unsigned u; 108 + 109 + add_round_key(q, skey); 110 + for (u = 1; u < num_rounds; u ++) { 111 + br_aes_ct64_bitslice_Sbox(q); 112 + shift_rows(q); 113 + mix_columns(q); 114 + add_round_key(q, skey + (u << 3)); 115 + } 116 + br_aes_ct64_bitslice_Sbox(q); 117 + shift_rows(q); 118 + add_round_key(q, skey + (num_rounds << 3)); 119 + }
+42
src/c/bearssl/dec32le.c
··· 1 + /* Vendored from BearSSL 7bea48e5e850ab4cafbe68d3765cdaba13a86d6f 2 + * Source: src/codec/dec32le.c 3 + * Imported by: ../scripts/import.ml -- do not edit by hand. 4 + */ 5 + /* 6 + * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> 7 + * 8 + * Permission is hereby granted, free of charge, to any person obtaining 9 + * a copy of this software and associated documentation files (the 10 + * "Software"), to deal in the Software without restriction, including 11 + * without limitation the rights to use, copy, modify, merge, publish, 12 + * distribute, sublicense, and/or sell copies of the Software, and to 13 + * permit persons to whom the Software is furnished to do so, subject to 14 + * the following conditions: 15 + * 16 + * The above copyright notice and this permission notice shall be 17 + * included in all copies or substantial portions of the Software. 18 + * 19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 + * SOFTWARE. 27 + */ 28 + 29 + #include "inner.h" 30 + 31 + /* see inner.h */ 32 + void 33 + br_range_dec32le(uint32_t *v, size_t num, const void *src) 34 + { 35 + const unsigned char *buf; 36 + 37 + buf = src; 38 + while (num -- > 0) { 39 + *v ++ = br_dec32le(buf); 40 + buf += 4; 41 + } 42 + }
+42
src/c/bearssl/enc32le.c
··· 1 + /* Vendored from BearSSL 7bea48e5e850ab4cafbe68d3765cdaba13a86d6f 2 + * Source: src/codec/enc32le.c 3 + * Imported by: ../scripts/import.ml -- do not edit by hand. 4 + */ 5 + /* 6 + * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> 7 + * 8 + * Permission is hereby granted, free of charge, to any person obtaining 9 + * a copy of this software and associated documentation files (the 10 + * "Software"), to deal in the Software without restriction, including 11 + * without limitation the rights to use, copy, modify, merge, publish, 12 + * distribute, sublicense, and/or sell copies of the Software, and to 13 + * permit persons to whom the Software is furnished to do so, subject to 14 + * the following conditions: 15 + * 16 + * The above copyright notice and this permission notice shall be 17 + * included in all copies or substantial portions of the Software. 18 + * 19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 + * SOFTWARE. 27 + */ 28 + 29 + #include "inner.h" 30 + 31 + /* see inner.h */ 32 + void 33 + br_range_enc32le(void *dst, const uint32_t *v, size_t num) 34 + { 35 + unsigned char *buf; 36 + 37 + buf = dst; 38 + while (num -- > 0) { 39 + br_enc32le(buf, *v ++); 40 + buf += 4; 41 + } 42 + }
+158
src/c/bearssl/ghash_ctmul64.c
··· 1 + /* Vendored from BearSSL 7bea48e5e850ab4cafbe68d3765cdaba13a86d6f 2 + * Source: src/hash/ghash_ctmul64.c 3 + * Imported by: ../scripts/import.ml -- do not edit by hand. 4 + */ 5 + /* 6 + * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> 7 + * 8 + * Permission is hereby granted, free of charge, to any person obtaining 9 + * a copy of this software and associated documentation files (the 10 + * "Software"), to deal in the Software without restriction, including 11 + * without limitation the rights to use, copy, modify, merge, publish, 12 + * distribute, sublicense, and/or sell copies of the Software, and to 13 + * permit persons to whom the Software is furnished to do so, subject to 14 + * the following conditions: 15 + * 16 + * The above copyright notice and this permission notice shall be 17 + * included in all copies or substantial portions of the Software. 18 + * 19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 + * SOFTWARE. 27 + */ 28 + 29 + #include "inner.h" 30 + 31 + /* 32 + * This is the 64-bit variant of br_ghash_ctmul32(), with 64-bit operands 33 + * and bit reversal of 64-bit words. 34 + */ 35 + 36 + static inline uint64_t 37 + bmul64(uint64_t x, uint64_t y) 38 + { 39 + uint64_t x0, x1, x2, x3; 40 + uint64_t y0, y1, y2, y3; 41 + uint64_t z0, z1, z2, z3; 42 + 43 + x0 = x & (uint64_t)0x1111111111111111; 44 + x1 = x & (uint64_t)0x2222222222222222; 45 + x2 = x & (uint64_t)0x4444444444444444; 46 + x3 = x & (uint64_t)0x8888888888888888; 47 + y0 = y & (uint64_t)0x1111111111111111; 48 + y1 = y & (uint64_t)0x2222222222222222; 49 + y2 = y & (uint64_t)0x4444444444444444; 50 + y3 = y & (uint64_t)0x8888888888888888; 51 + z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1); 52 + z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2); 53 + z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3); 54 + z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0); 55 + z0 &= (uint64_t)0x1111111111111111; 56 + z1 &= (uint64_t)0x2222222222222222; 57 + z2 &= (uint64_t)0x4444444444444444; 58 + z3 &= (uint64_t)0x8888888888888888; 59 + return z0 | z1 | z2 | z3; 60 + } 61 + 62 + static uint64_t 63 + rev64(uint64_t x) 64 + { 65 + #define RMS(m, s) do { \ 66 + x = ((x & (uint64_t)(m)) << (s)) \ 67 + | ((x >> (s)) & (uint64_t)(m)); \ 68 + } while (0) 69 + 70 + RMS(0x5555555555555555, 1); 71 + RMS(0x3333333333333333, 2); 72 + RMS(0x0F0F0F0F0F0F0F0F, 4); 73 + RMS(0x00FF00FF00FF00FF, 8); 74 + RMS(0x0000FFFF0000FFFF, 16); 75 + return (x << 32) | (x >> 32); 76 + 77 + #undef RMS 78 + } 79 + 80 + /* see bearssl_ghash.h */ 81 + void 82 + br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len) 83 + { 84 + const unsigned char *buf, *hb; 85 + unsigned char *yb; 86 + uint64_t y0, y1; 87 + uint64_t h0, h1, h2, h0r, h1r, h2r; 88 + 89 + buf = data; 90 + yb = y; 91 + hb = h; 92 + y1 = br_dec64be(yb); 93 + y0 = br_dec64be(yb + 8); 94 + h1 = br_dec64be(hb); 95 + h0 = br_dec64be(hb + 8); 96 + h0r = rev64(h0); 97 + h1r = rev64(h1); 98 + h2 = h0 ^ h1; 99 + h2r = h0r ^ h1r; 100 + while (len > 0) { 101 + const unsigned char *src; 102 + unsigned char tmp[16]; 103 + uint64_t y0r, y1r, y2, y2r; 104 + uint64_t z0, z1, z2, z0h, z1h, z2h; 105 + uint64_t v0, v1, v2, v3; 106 + 107 + if (len >= 16) { 108 + src = buf; 109 + buf += 16; 110 + len -= 16; 111 + } else { 112 + memcpy(tmp, buf, len); 113 + memset(tmp + len, 0, (sizeof tmp) - len); 114 + src = tmp; 115 + len = 0; 116 + } 117 + y1 ^= br_dec64be(src); 118 + y0 ^= br_dec64be(src + 8); 119 + 120 + y0r = rev64(y0); 121 + y1r = rev64(y1); 122 + y2 = y0 ^ y1; 123 + y2r = y0r ^ y1r; 124 + 125 + z0 = bmul64(y0, h0); 126 + z1 = bmul64(y1, h1); 127 + z2 = bmul64(y2, h2); 128 + z0h = bmul64(y0r, h0r); 129 + z1h = bmul64(y1r, h1r); 130 + z2h = bmul64(y2r, h2r); 131 + z2 ^= z0 ^ z1; 132 + z2h ^= z0h ^ z1h; 133 + z0h = rev64(z0h) >> 1; 134 + z1h = rev64(z1h) >> 1; 135 + z2h = rev64(z2h) >> 1; 136 + 137 + v0 = z0; 138 + v1 = z0h ^ z2; 139 + v2 = z1 ^ z2h; 140 + v3 = z1h; 141 + 142 + v3 = (v3 << 1) | (v2 >> 63); 143 + v2 = (v2 << 1) | (v1 >> 63); 144 + v1 = (v1 << 1) | (v0 >> 63); 145 + v0 = (v0 << 1); 146 + 147 + v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7); 148 + v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57); 149 + v3 ^= v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7); 150 + v2 ^= (v1 << 63) ^ (v1 << 62) ^ (v1 << 57); 151 + 152 + y0 = v2; 153 + y1 = v3; 154 + } 155 + 156 + br_enc64be(yb, y1); 157 + br_enc64be(yb + 8, y0); 158 + }
+135
src/c/bearssl/inner.h
··· 1 + /* 2 + * Minimal subset of BearSSL inner.h for ocaml-crypto. 3 + * AUTO-GENERATED by ../scripts/import.ml -- do not edit by hand. 4 + * 5 + * Vendored from BearSSL 7bea48e5e850ab4cafbe68d3765cdaba13a86d6f 6 + * 7 + * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> 8 + * MIT license (see individual .c files for full text). 9 + */ 10 + #ifndef INNER_H__ 11 + #define INNER_H__ 12 + #include <string.h> 13 + #include <stdint.h> 14 + 15 + /* Byte encoding helpers (extracted from BearSSL src/inner.h). 16 + * BR_LE_UNALIGNED / BR_BE_UNALIGNED are not defined, so the 17 + * portable #else branches are selected. */ 18 + static inline void 19 + br_enc32le(void *dst, uint32_t x) 20 + { 21 + #if BR_LE_UNALIGNED 22 + ((br_union_u32 *)dst)->u = x; 23 + #else 24 + unsigned char *buf; 25 + 26 + buf = dst; 27 + buf[0] = (unsigned char)x; 28 + buf[1] = (unsigned char)(x >> 8); 29 + buf[2] = (unsigned char)(x >> 16); 30 + buf[3] = (unsigned char)(x >> 24); 31 + #endif 32 + } 33 + 34 + static inline void 35 + br_enc32be(void *dst, uint32_t x) 36 + { 37 + #if BR_BE_UNALIGNED 38 + ((br_union_u32 *)dst)->u = x; 39 + #else 40 + unsigned char *buf; 41 + 42 + buf = dst; 43 + buf[0] = (unsigned char)(x >> 24); 44 + buf[1] = (unsigned char)(x >> 16); 45 + buf[2] = (unsigned char)(x >> 8); 46 + buf[3] = (unsigned char)x; 47 + #endif 48 + } 49 + 50 + static inline uint32_t 51 + br_dec32le(const void *src) 52 + { 53 + #if BR_LE_UNALIGNED 54 + return ((const br_union_u32 *)src)->u; 55 + #else 56 + const unsigned char *buf; 57 + 58 + buf = src; 59 + return (uint32_t)buf[0] 60 + | ((uint32_t)buf[1] << 8) 61 + | ((uint32_t)buf[2] << 16) 62 + | ((uint32_t)buf[3] << 24); 63 + #endif 64 + } 65 + 66 + static inline uint32_t 67 + br_dec32be(const void *src) 68 + { 69 + #if BR_BE_UNALIGNED 70 + return ((const br_union_u32 *)src)->u; 71 + #else 72 + const unsigned char *buf; 73 + 74 + buf = src; 75 + return ((uint32_t)buf[0] << 24) 76 + | ((uint32_t)buf[1] << 16) 77 + | ((uint32_t)buf[2] << 8) 78 + | (uint32_t)buf[3]; 79 + #endif 80 + } 81 + 82 + static inline void 83 + br_enc64be(void *dst, uint64_t x) 84 + { 85 + #if BR_BE_UNALIGNED 86 + ((br_union_u64 *)dst)->u = x; 87 + #else 88 + unsigned char *buf; 89 + 90 + buf = dst; 91 + br_enc32be(buf, (uint32_t)(x >> 32)); 92 + br_enc32be(buf + 4, (uint32_t)x); 93 + #endif 94 + } 95 + 96 + static inline uint64_t 97 + br_dec64be(const void *src) 98 + { 99 + #if BR_BE_UNALIGNED 100 + return ((const br_union_u64 *)src)->u; 101 + #else 102 + const unsigned char *buf; 103 + 104 + buf = src; 105 + return ((uint64_t)br_dec32be(buf) << 32) 106 + | (uint64_t)br_dec32be(buf + 4); 107 + #endif 108 + } 109 + 110 + /* Range function declarations */ 111 + void br_range_dec32le(uint32_t *v, size_t num, const void *src); 112 + void br_range_enc32le(void *dst, const uint32_t *v, size_t num); 113 + 114 + /* aes_ct64 API (extracted from BearSSL src/inner.h) */ 115 + void br_aes_ct64_ortho(uint64_t *q); 116 + void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w); 117 + void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1); 118 + void br_aes_ct64_bitslice_Sbox(uint64_t *q); 119 + void br_aes_ct64_bitslice_invSbox(uint64_t *q); 120 + void br_aes_ct64_bitslice_encrypt(unsigned num_rounds, 121 + const uint64_t *skey, uint64_t *q); 122 + void br_aes_ct64_bitslice_decrypt(unsigned num_rounds, 123 + const uint64_t *skey, uint64_t *q); 124 + unsigned br_aes_ct64_keysched(uint64_t *comp_skey, 125 + const void *key, size_t key_len); 126 + void br_aes_ct64_skey_expand(uint64_t *skey, 127 + unsigned num_rounds, const uint64_t *comp_skey); 128 + 129 + /* GHASH constant-time fallbacks (extracted from BearSSL 130 + * inc/bearssl_hash.h, used by ../ghash_generic.c on 64-bit and 131 + * ../ghash_ctmul.c on 32-bit / MSVC). */ 132 + void br_ghash_ctmul(void *y, const void *h, const void *data, size_t len); 133 + void br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len); 134 + 135 + #endif /* INNER_H__ */
+3 -9
src/c/crypto.h
··· 45 45 46 46 #endif /* __mc_detect_features__ */ 47 47 48 - #if defined(__mc_ACCELERATE__) 49 - 50 - #define _mc_switch_accel(FEATURE, GENERIC_CALL, ACCELERATED_CALL) \ 51 - if (!(mc_detected_cpu_features.FEATURE)) { GENERIC_CALL; } \ 52 - else { ACCELERATED_CALL; } 53 - 54 - #elif defined(__mc_ARM64CE__) 48 + #ifdef __mc_ACCELERATE__ 55 49 56 50 #define _mc_switch_accel(FEATURE, GENERIC_CALL, ACCELERATED_CALL) \ 57 51 if (!(mc_detected_cpu_features.FEATURE)) { GENERIC_CALL; } \ 58 52 else { ACCELERATED_CALL; } 59 53 60 - #else 54 + #else /* __mc_ACCELERATE__ */ 61 55 62 56 #define _mc_switch_accel(_FEATURE, GENERIC_CALL, _ACCELERATED_CALL) \ 63 57 GENERIC_CALL; 64 58 65 - #endif 59 + #endif /* __mc_ACCELERATE__ */ 66 60 67 61 #if defined (__x86_64__) || defined (__aarch64__) || defined (__powerpc64__) || defined (__ppc64__) || (64 == __riscv_xlen) || defined (__s390x__) || (defined (__mips__) && _MIPS_SIM==_ABI64) || defined (__loongarch_lp64) || (1 == _WIN64) 68 62 #define ARCH_64BIT
+4 -5
src/c/dune
··· 26 26 (flags 27 27 (:standard) 28 28 (:include ../cflags.sexp))) 29 + ; BearSSL constant-time fallbacks (aes_ct64, ghash_ctmul64) used by 30 + ; aes_generic.c and ghash_generic.c on hosts without AES-NI / PCLMUL. 31 + ; Compiled with standard flags -- no x86 intrinsics required. 29 32 (foreign_stubs 30 33 (language c) 31 - (names 32 - aes_ct64 aes_ct64_enc aes_ct64_dec 33 - aes_x86ni aes_x86ni_cbcenc aes_x86ni_cbcdec aes_x86ni_ctr 34 - ghash_ctmul64 ghash_pclmul_bearssl 35 - dec32le enc32le) 34 + (names aes_ct64 aes_ct64_enc aes_ct64_dec ghash_ctmul64 dec32le enc32le) 36 35 (flags 37 36 (:standard) 38 37 (:include ../cflags.sexp)
-23
src/c/ghash_pclmul.c
··· 188 188 189 189 #endif /* __mc_ACCELERATE__ */ 190 190 191 - /* ------------------------------------------------------------------ */ 192 - /* Dispatch */ 193 - /* */ 194 - /* On x86: PCLMULQDQ accelerated path above. */ 195 - /* On ARM64 and other platforms: uses BearSSL ghash_ctmul64 via */ 196 - /* mc_ghash_generic (constant-time, no hardware intrinsics). */ 197 - /* ARM64 PMULL acceleration: TODO (needs audited implementation). */ 198 - /* ------------------------------------------------------------------ */ 199 - 200 191 CAMLprim value mc_ghash_key_size (__unit ()) { 201 192 value s; 202 - #if defined(__mc_ACCELERATE__) 203 193 _mc_switch_accel(pclmul, 204 194 s = mc_ghash_key_size_generic(Val_unit), 205 195 s = Val_int (__keys * 16)) 206 - #else 207 - s = mc_ghash_key_size_generic(Val_unit); 208 - #endif 209 196 return s; 210 197 } 211 198 212 199 CAMLprim value mc_ghash_init_key (value key, value m) { 213 - #if defined(__mc_ACCELERATE__) 214 200 _mc_switch_accel(pclmul, 215 201 mc_ghash_init_key_generic(key, m), 216 202 __derive ((__m128i *) _st_uint8 (key), (__m128i *) Bp_val (m))) 217 - #else 218 - mc_ghash_init_key_generic(key, m); 219 - #endif 220 203 return Val_unit; 221 204 } 222 205 223 206 CAMLprim value 224 207 mc_ghash (value k, value hash, value src, value off, value len) { 225 - #if defined(__mc_ACCELERATE__) 226 208 _mc_switch_accel(pclmul, 227 209 mc_ghash_generic(k, hash, src, off, len), 228 210 __ghash ( (__m128i *) Bp_val (k), (__m128i *) Bp_val (hash), 229 211 (__m128i *) _st_uint8_off (src, off), Int_val (len) )) 230 - #else 231 - mc_ghash_generic(k, hash, src, off, len); 232 - #endif 233 212 return Val_unit; 234 213 } 235 214 236 215 CAMLprim value mc_ghash_mode (__unit ()) { 237 216 value enabled = 0; 238 - #if defined(__mc_ACCELERATE__) 239 217 _mc_switch_accel(pclmul, 240 218 enabled = 0, 241 219 enabled = 1) 242 - #endif 243 220 return Val_int (enabled); 244 221 }