Branch data Line data Source code
# 1 : : /*********************************************************************
# 2 : : * Copyright (c) 2016 Pieter Wuille *
# 3 : : * Distributed under the MIT software license, see the accompanying *
# 4 : : * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
# 5 : : **********************************************************************/
# 6 : :
# 7 : : /* Constant time, unoptimized, concise, plain C, AES implementation
# 8 : : * Based On:
# 9 : : * Emilia Kasper and Peter Schwabe, Faster and Timing-Attack Resistant AES-GCM
# 10 : : * http://www.iacr.org/archive/ches2009/57470001/57470001.pdf
# 11 : : * But using 8 16-bit integers representing a single AES state rather than 8 128-bit
# 12 : : * integers representing 8 AES states.
# 13 : : */
# 14 : :
# 15 : : #include "ctaes.h"
# 16 : :
# 17 : : /* Slice variable slice_i contains the i'th bit of the 16 state variables in this order:
# 18 : : * 0 1 2 3
# 19 : : * 4 5 6 7
# 20 : : * 8 9 10 11
# 21 : : * 12 13 14 15
# 22 : : */
# 23 : :
# 24 : : /** Convert a byte to sliced form, storing it corresponding to given row and column in s */
# 25 : 926352 : static void LoadByte(AES_state* s, unsigned char byte, int r, int c) {
# 26 : 926352 : int i;
# 27 [ + + ]: 8337168 : for (i = 0; i < 8; i++) {
# 28 : 7410816 : s->slice[i] |= (byte & 1) << (r * 4 + c);
# 29 : 7410816 : byte >>= 1;
# 30 : 7410816 : }
# 31 : 926352 : }
# 32 : :
# 33 : : /** Load 16 bytes of data into 8 sliced integers */
# 34 : 31059 : static void LoadBytes(AES_state *s, const unsigned char* data16) {
# 35 : 31059 : int c;
# 36 [ + + ]: 155295 : for (c = 0; c < 4; c++) {
# 37 : 124236 : int r;
# 38 [ + + ]: 621180 : for (r = 0; r < 4; r++) {
# 39 : 496944 : LoadByte(s, *(data16++), r, c);
# 40 : 496944 : }
# 41 : 124236 : }
# 42 : 31059 : }
# 43 : :
# 44 : : /** Convert 8 sliced integers into 16 bytes of data */
# 45 : 31059 : static void SaveBytes(unsigned char* data16, const AES_state *s) {
# 46 : 31059 : int c;
# 47 [ + + ]: 155295 : for (c = 0; c < 4; c++) {
# 48 : 124236 : int r;
# 49 [ + + ]: 621180 : for (r = 0; r < 4; r++) {
# 50 : 496944 : int b;
# 51 : 496944 : uint8_t v = 0;
# 52 [ + + ]: 4472496 : for (b = 0; b < 8; b++) {
# 53 : 3975552 : v |= ((s->slice[b] >> (r * 4 + c)) & 1) << b;
# 54 : 3975552 : }
# 55 : 496944 : *(data16++) = v;
# 56 : 496944 : }
# 57 : 124236 : }
# 58 : 31059 : }
# 59 : :
# 60 : : /* S-box implementation based on the gate logic from:
# 61 : : * Joan Boyar and Rene Peralta, A depth-16 circuit for the AES S-box.
# 62 : : * https://eprint.iacr.org/2011/332.pdf
# 63 : : */
# 64 : 609273 : static void SubBytes(AES_state *s, int inv) {
# 65 : : /* Load the bit slices */
# 66 : 609273 : uint16_t U0 = s->slice[7], U1 = s->slice[6], U2 = s->slice[5], U3 = s->slice[4];
# 67 : 609273 : uint16_t U4 = s->slice[3], U5 = s->slice[2], U6 = s->slice[1], U7 = s->slice[0];
# 68 : :
# 69 : 609273 : uint16_t T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16;
# 70 : 609273 : uint16_t T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, D;
# 71 : 609273 : uint16_t M1, M6, M11, M13, M15, M20, M21, M22, M23, M25, M37, M38, M39, M40;
# 72 : 609273 : uint16_t M41, M42, M43, M44, M45, M46, M47, M48, M49, M50, M51, M52, M53, M54;
# 73 : 609273 : uint16_t M55, M56, M57, M58, M59, M60, M61, M62, M63;
# 74 : :
# 75 [ + + ]: 609273 : if (inv) {
# 76 : 301826 : uint16_t R5, R13, R17, R18, R19;
# 77 : : /* Undo linear postprocessing */
# 78 : 301826 : T23 = U0 ^ U3;
# 79 : 301826 : T22 = ~(U1 ^ U3);
# 80 : 301826 : T2 = ~(U0 ^ U1);
# 81 : 301826 : T1 = U3 ^ U4;
# 82 : 301826 : T24 = ~(U4 ^ U7);
# 83 : 301826 : R5 = U6 ^ U7;
# 84 : 301826 : T8 = ~(U1 ^ T23);
# 85 : 301826 : T19 = T22 ^ R5;
# 86 : 301826 : T9 = ~(U7 ^ T1);
# 87 : 301826 : T10 = T2 ^ T24;
# 88 : 301826 : T13 = T2 ^ R5;
# 89 : 301826 : T3 = T1 ^ R5;
# 90 : 301826 : T25 = ~(U2 ^ T1);
# 91 : 301826 : R13 = U1 ^ U6;
# 92 : 301826 : T17 = ~(U2 ^ T19);
# 93 : 301826 : T20 = T24 ^ R13;
# 94 : 301826 : T4 = U4 ^ T8;
# 95 : 301826 : R17 = ~(U2 ^ U5);
# 96 : 301826 : R18 = ~(U5 ^ U6);
# 97 : 301826 : R19 = ~(U2 ^ U4);
# 98 : 301826 : D = U0 ^ R17;
# 99 : 301826 : T6 = T22 ^ R17;
# 100 : 301826 : T16 = R13 ^ R19;
# 101 : 301826 : T27 = T1 ^ R18;
# 102 : 301826 : T15 = T10 ^ T27;
# 103 : 301826 : T14 = T10 ^ R18;
# 104 : 301826 : T26 = T3 ^ T16;
# 105 : 307447 : } else {
# 106 : : /* Linear preprocessing. */
# 107 : 307447 : T1 = U0 ^ U3;
# 108 : 307447 : T2 = U0 ^ U5;
# 109 : 307447 : T3 = U0 ^ U6;
# 110 : 307447 : T4 = U3 ^ U5;
# 111 : 307447 : T5 = U4 ^ U6;
# 112 : 307447 : T6 = T1 ^ T5;
# 113 : 307447 : T7 = U1 ^ U2;
# 114 : 307447 : T8 = U7 ^ T6;
# 115 : 307447 : T9 = U7 ^ T7;
# 116 : 307447 : T10 = T6 ^ T7;
# 117 : 307447 : T11 = U1 ^ U5;
# 118 : 307447 : T12 = U2 ^ U5;
# 119 : 307447 : T13 = T3 ^ T4;
# 120 : 307447 : T14 = T6 ^ T11;
# 121 : 307447 : T15 = T5 ^ T11;
# 122 : 307447 : T16 = T5 ^ T12;
# 123 : 307447 : T17 = T9 ^ T16;
# 124 : 307447 : T18 = U3 ^ U7;
# 125 : 307447 : T19 = T7 ^ T18;
# 126 : 307447 : T20 = T1 ^ T19;
# 127 : 307447 : T21 = U6 ^ U7;
# 128 : 307447 : T22 = T7 ^ T21;
# 129 : 307447 : T23 = T2 ^ T22;
# 130 : 307447 : T24 = T2 ^ T10;
# 131 : 307447 : T25 = T20 ^ T17;
# 132 : 307447 : T26 = T3 ^ T16;
# 133 : 307447 : T27 = T1 ^ T12;
# 134 : 307447 : D = U7;
# 135 : 307447 : }
# 136 : :
# 137 : : /* Non-linear transformation (shared between the forward and backward case) */
# 138 : 609273 : M1 = T13 & T6;
# 139 : 609273 : M6 = T3 & T16;
# 140 : 609273 : M11 = T1 & T15;
# 141 : 609273 : M13 = (T4 & T27) ^ M11;
# 142 : 609273 : M15 = (T2 & T10) ^ M11;
# 143 : 609273 : M20 = T14 ^ M1 ^ (T23 & T8) ^ M13;
# 144 : 609273 : M21 = (T19 & D) ^ M1 ^ T24 ^ M15;
# 145 : 609273 : M22 = T26 ^ M6 ^ (T22 & T9) ^ M13;
# 146 : 609273 : M23 = (T20 & T17) ^ M6 ^ M15 ^ T25;
# 147 : 609273 : M25 = M22 & M20;
# 148 : 609273 : M37 = M21 ^ ((M20 ^ M21) & (M23 ^ M25));
# 149 : 609273 : M38 = M20 ^ M25 ^ (M21 | (M20 & M23));
# 150 : 609273 : M39 = M23 ^ ((M22 ^ M23) & (M21 ^ M25));
# 151 : 609273 : M40 = M22 ^ M25 ^ (M23 | (M21 & M22));
# 152 : 609273 : M41 = M38 ^ M40;
# 153 : 609273 : M42 = M37 ^ M39;
# 154 : 609273 : M43 = M37 ^ M38;
# 155 : 609273 : M44 = M39 ^ M40;
# 156 : 609273 : M45 = M42 ^ M41;
# 157 : 609273 : M46 = M44 & T6;
# 158 : 609273 : M47 = M40 & T8;
# 159 : 609273 : M48 = M39 & D;
# 160 : 609273 : M49 = M43 & T16;
# 161 : 609273 : M50 = M38 & T9;
# 162 : 609273 : M51 = M37 & T17;
# 163 : 609273 : M52 = M42 & T15;
# 164 : 609273 : M53 = M45 & T27;
# 165 : 609273 : M54 = M41 & T10;
# 166 : 609273 : M55 = M44 & T13;
# 167 : 609273 : M56 = M40 & T23;
# 168 : 609273 : M57 = M39 & T19;
# 169 : 609273 : M58 = M43 & T3;
# 170 : 609273 : M59 = M38 & T22;
# 171 : 609273 : M60 = M37 & T20;
# 172 : 609273 : M61 = M42 & T1;
# 173 : 609273 : M62 = M45 & T4;
# 174 : 609273 : M63 = M41 & T2;
# 175 : :
# 176 [ + + ]: 609273 : if (inv){
# 177 : : /* Undo linear preprocessing */
# 178 : 301826 : uint16_t P0 = M52 ^ M61;
# 179 : 301826 : uint16_t P1 = M58 ^ M59;
# 180 : 301826 : uint16_t P2 = M54 ^ M62;
# 181 : 301826 : uint16_t P3 = M47 ^ M50;
# 182 : 301826 : uint16_t P4 = M48 ^ M56;
# 183 : 301826 : uint16_t P5 = M46 ^ M51;
# 184 : 301826 : uint16_t P6 = M49 ^ M60;
# 185 : 301826 : uint16_t P7 = P0 ^ P1;
# 186 : 301826 : uint16_t P8 = M50 ^ M53;
# 187 : 301826 : uint16_t P9 = M55 ^ M63;
# 188 : 301826 : uint16_t P10 = M57 ^ P4;
# 189 : 301826 : uint16_t P11 = P0 ^ P3;
# 190 : 301826 : uint16_t P12 = M46 ^ M48;
# 191 : 301826 : uint16_t P13 = M49 ^ M51;
# 192 : 301826 : uint16_t P14 = M49 ^ M62;
# 193 : 301826 : uint16_t P15 = M54 ^ M59;
# 194 : 301826 : uint16_t P16 = M57 ^ M61;
# 195 : 301826 : uint16_t P17 = M58 ^ P2;
# 196 : 301826 : uint16_t P18 = M63 ^ P5;
# 197 : 301826 : uint16_t P19 = P2 ^ P3;
# 198 : 301826 : uint16_t P20 = P4 ^ P6;
# 199 : 301826 : uint16_t P22 = P2 ^ P7;
# 200 : 301826 : uint16_t P23 = P7 ^ P8;
# 201 : 301826 : uint16_t P24 = P5 ^ P7;
# 202 : 301826 : uint16_t P25 = P6 ^ P10;
# 203 : 301826 : uint16_t P26 = P9 ^ P11;
# 204 : 301826 : uint16_t P27 = P10 ^ P18;
# 205 : 301826 : uint16_t P28 = P11 ^ P25;
# 206 : 301826 : uint16_t P29 = P15 ^ P20;
# 207 : 301826 : s->slice[7] = P13 ^ P22;
# 208 : 301826 : s->slice[6] = P26 ^ P29;
# 209 : 301826 : s->slice[5] = P17 ^ P28;
# 210 : 301826 : s->slice[4] = P12 ^ P22;
# 211 : 301826 : s->slice[3] = P23 ^ P27;
# 212 : 301826 : s->slice[2] = P19 ^ P24;
# 213 : 301826 : s->slice[1] = P14 ^ P23;
# 214 : 301826 : s->slice[0] = P9 ^ P16;
# 215 : 307447 : } else {
# 216 : : /* Linear postprocessing */
# 217 : 307447 : uint16_t L0 = M61 ^ M62;
# 218 : 307447 : uint16_t L1 = M50 ^ M56;
# 219 : 307447 : uint16_t L2 = M46 ^ M48;
# 220 : 307447 : uint16_t L3 = M47 ^ M55;
# 221 : 307447 : uint16_t L4 = M54 ^ M58;
# 222 : 307447 : uint16_t L5 = M49 ^ M61;
# 223 : 307447 : uint16_t L6 = M62 ^ L5;
# 224 : 307447 : uint16_t L7 = M46 ^ L3;
# 225 : 307447 : uint16_t L8 = M51 ^ M59;
# 226 : 307447 : uint16_t L9 = M52 ^ M53;
# 227 : 307447 : uint16_t L10 = M53 ^ L4;
# 228 : 307447 : uint16_t L11 = M60 ^ L2;
# 229 : 307447 : uint16_t L12 = M48 ^ M51;
# 230 : 307447 : uint16_t L13 = M50 ^ L0;
# 231 : 307447 : uint16_t L14 = M52 ^ M61;
# 232 : 307447 : uint16_t L15 = M55 ^ L1;
# 233 : 307447 : uint16_t L16 = M56 ^ L0;
# 234 : 307447 : uint16_t L17 = M57 ^ L1;
# 235 : 307447 : uint16_t L18 = M58 ^ L8;
# 236 : 307447 : uint16_t L19 = M63 ^ L4;
# 237 : 307447 : uint16_t L20 = L0 ^ L1;
# 238 : 307447 : uint16_t L21 = L1 ^ L7;
# 239 : 307447 : uint16_t L22 = L3 ^ L12;
# 240 : 307447 : uint16_t L23 = L18 ^ L2;
# 241 : 307447 : uint16_t L24 = L15 ^ L9;
# 242 : 307447 : uint16_t L25 = L6 ^ L10;
# 243 : 307447 : uint16_t L26 = L7 ^ L9;
# 244 : 307447 : uint16_t L27 = L8 ^ L10;
# 245 : 307447 : uint16_t L28 = L11 ^ L14;
# 246 : 307447 : uint16_t L29 = L11 ^ L17;
# 247 : 307447 : s->slice[7] = L6 ^ L24;
# 248 : 307447 : s->slice[6] = ~(L16 ^ L26);
# 249 : 307447 : s->slice[5] = ~(L19 ^ L28);
# 250 : 307447 : s->slice[4] = L6 ^ L21;
# 251 : 307447 : s->slice[3] = L20 ^ L22;
# 252 : 307447 : s->slice[2] = L25 ^ L29;
# 253 : 307447 : s->slice[1] = ~(L13 ^ L27);
# 254 : 307447 : s->slice[0] = ~(L6 ^ L23);
# 255 : 307447 : }
# 256 : 609273 : }
# 257 : :
# 258 : 24350256 : #define BIT_RANGE(from,to) (((1 << ((to) - (from))) - 1) << (from))
# 259 : :
# 260 : 10435824 : #define BIT_RANGE_LEFT(x,from,to,shift) (((x) & BIT_RANGE((from), (to))) << (shift))
# 261 : 10435824 : #define BIT_RANGE_RIGHT(x,from,to,shift) (((x) & BIT_RANGE((from), (to))) >> (shift))
# 262 : :
# 263 : 133000 : static void ShiftRows(AES_state* s) {
# 264 : 133000 : int i;
# 265 [ + + ]: 1197000 : for (i = 0; i < 8; i++) {
# 266 : 1064000 : uint16_t v = s->slice[i];
# 267 : 1064000 : s->slice[i] =
# 268 : 1064000 : (v & BIT_RANGE(0, 4)) |
# 269 : 1064000 : BIT_RANGE_LEFT(v, 4, 5, 3) | BIT_RANGE_RIGHT(v, 5, 8, 1) |
# 270 : 1064000 : BIT_RANGE_LEFT(v, 8, 10, 2) | BIT_RANGE_RIGHT(v, 10, 12, 2) |
# 271 : 1064000 : BIT_RANGE_LEFT(v, 12, 15, 1) | BIT_RANGE_RIGHT(v, 15, 16, 3);
# 272 : 1064000 : }
# 273 : 133000 : }
# 274 : :
# 275 : 301826 : static void InvShiftRows(AES_state* s) {
# 276 : 301826 : int i;
# 277 [ + + ]: 2716434 : for (i = 0; i < 8; i++) {
# 278 : 2414608 : uint16_t v = s->slice[i];
# 279 : 2414608 : s->slice[i] =
# 280 : 2414608 : (v & BIT_RANGE(0, 4)) |
# 281 : 2414608 : BIT_RANGE_LEFT(v, 4, 7, 1) | BIT_RANGE_RIGHT(v, 7, 8, 3) |
# 282 : 2414608 : BIT_RANGE_LEFT(v, 8, 10, 2) | BIT_RANGE_RIGHT(v, 10, 12, 2) |
# 283 : 2414608 : BIT_RANGE_LEFT(v, 12, 13, 3) | BIT_RANGE_RIGHT(v, 13, 16, 1);
# 284 : 2414608 : }
# 285 : 301826 : }
# 286 : :
# 287 : 11932544 : #define ROT(x,b) (((x) >> ((b) * 4)) | ((x) << ((4-(b)) * 4)))
# 288 : :
# 289 : 403767 : static void MixColumns(AES_state* s, int inv) {
# 290 : : /* The MixColumns transform treats the bytes of the columns of the state as
# 291 : : * coefficients of a 3rd degree polynomial over GF(2^8) and multiplies them
# 292 : : * by the fixed polynomial a(x) = {03}x^3 + {01}x^2 + {01}x + {02}, modulo
# 293 : : * x^4 + {01}.
# 294 : : *
# 295 : : * In the inverse transform, we multiply by the inverse of a(x),
# 296 : : * a^-1(x) = {0b}x^3 + {0d}x^2 + {09}x + {0e}. This is equal to
# 297 : : * a(x) * ({04}x^2 + {05}), so we can reuse the forward transform's code
# 298 : : * (found in OpenSSL's bsaes-x86_64.pl, attributed to Jussi Kivilinna)
# 299 : : *
# 300 : : * In the bitsliced representation, a multiplication of every column by x
# 301 : : * mod x^4 + 1 is simply a right rotation.
# 302 : : */
# 303 : :
# 304 : : /* Shared for both directions is a multiplication by a(x), which can be
# 305 : : * rewritten as (x^3 + x^2 + x) + {02}*(x^3 + {01}).
# 306 : : *
# 307 : : * First compute s into the s? variables, (x^3 + {01}) * s into the s?_01
# 308 : : * variables and (x^3 + x^2 + x)*s into the s?_123 variables.
# 309 : : */
# 310 : 403767 : uint16_t s0 = s->slice[0], s1 = s->slice[1], s2 = s->slice[2], s3 = s->slice[3];
# 311 : 403767 : uint16_t s4 = s->slice[4], s5 = s->slice[5], s6 = s->slice[6], s7 = s->slice[7];
# 312 : 403767 : uint16_t s0_01 = s0 ^ ROT(s0, 1), s0_123 = ROT(s0_01, 1) ^ ROT(s0, 3);
# 313 : 403767 : uint16_t s1_01 = s1 ^ ROT(s1, 1), s1_123 = ROT(s1_01, 1) ^ ROT(s1, 3);
# 314 : 403767 : uint16_t s2_01 = s2 ^ ROT(s2, 1), s2_123 = ROT(s2_01, 1) ^ ROT(s2, 3);
# 315 : 403767 : uint16_t s3_01 = s3 ^ ROT(s3, 1), s3_123 = ROT(s3_01, 1) ^ ROT(s3, 3);
# 316 : 403767 : uint16_t s4_01 = s4 ^ ROT(s4, 1), s4_123 = ROT(s4_01, 1) ^ ROT(s4, 3);
# 317 : 403767 : uint16_t s5_01 = s5 ^ ROT(s5, 1), s5_123 = ROT(s5_01, 1) ^ ROT(s5, 3);
# 318 : 403767 : uint16_t s6_01 = s6 ^ ROT(s6, 1), s6_123 = ROT(s6_01, 1) ^ ROT(s6, 3);
# 319 : 403767 : uint16_t s7_01 = s7 ^ ROT(s7, 1), s7_123 = ROT(s7_01, 1) ^ ROT(s7, 3);
# 320 : : /* Now compute s = s?_123 + {02} * s?_01. */
# 321 : 403767 : s->slice[0] = s7_01 ^ s0_123;
# 322 : 403767 : s->slice[1] = s7_01 ^ s0_01 ^ s1_123;
# 323 : 403767 : s->slice[2] = s1_01 ^ s2_123;
# 324 : 403767 : s->slice[3] = s7_01 ^ s2_01 ^ s3_123;
# 325 : 403767 : s->slice[4] = s7_01 ^ s3_01 ^ s4_123;
# 326 : 403767 : s->slice[5] = s4_01 ^ s5_123;
# 327 : 403767 : s->slice[6] = s5_01 ^ s6_123;
# 328 : 403767 : s->slice[7] = s6_01 ^ s7_123;
# 329 [ + + ]: 403767 : if (inv) {
# 330 : : /* In the reverse direction, we further need to multiply by
# 331 : : * {04}x^2 + {05}, which can be written as {04} * (x^2 + {01}) + {01}.
# 332 : : *
# 333 : : * First compute (x^2 + {01}) * s into the t?_02 variables: */
# 334 : 280267 : uint16_t t0_02 = s->slice[0] ^ ROT(s->slice[0], 2);
# 335 : 280267 : uint16_t t1_02 = s->slice[1] ^ ROT(s->slice[1], 2);
# 336 : 280267 : uint16_t t2_02 = s->slice[2] ^ ROT(s->slice[2], 2);
# 337 : 280267 : uint16_t t3_02 = s->slice[3] ^ ROT(s->slice[3], 2);
# 338 : 280267 : uint16_t t4_02 = s->slice[4] ^ ROT(s->slice[4], 2);
# 339 : 280267 : uint16_t t5_02 = s->slice[5] ^ ROT(s->slice[5], 2);
# 340 : 280267 : uint16_t t6_02 = s->slice[6] ^ ROT(s->slice[6], 2);
# 341 : 280267 : uint16_t t7_02 = s->slice[7] ^ ROT(s->slice[7], 2);
# 342 : : /* And then update s += {04} * t?_02 */
# 343 : 280267 : s->slice[0] ^= t6_02;
# 344 : 280267 : s->slice[1] ^= t6_02 ^ t7_02;
# 345 : 280267 : s->slice[2] ^= t0_02 ^ t7_02;
# 346 : 280267 : s->slice[3] ^= t1_02 ^ t6_02;
# 347 : 280267 : s->slice[4] ^= t2_02 ^ t6_02 ^ t7_02;
# 348 : 280267 : s->slice[5] ^= t3_02 ^ t7_02;
# 349 : 280267 : s->slice[6] ^= t4_02;
# 350 : 280267 : s->slice[7] ^= t5_02;
# 351 : 280267 : }
# 352 : 403767 : }
# 353 : :
# 354 : 465885 : static void AddRoundKey(AES_state* s, const AES_state* round) {
# 355 : 465885 : int b;
# 356 [ + + ]: 4192965 : for (b = 0; b < 8; b++) {
# 357 : 3727080 : s->slice[b] ^= round->slice[b];
# 358 : 3727080 : }
# 359 : 465885 : }
# 360 : :
# 361 : : /** column_0(s) = column_c(a) */
# 362 : 13419 : static void GetOneColumn(AES_state* s, const AES_state* a, int c) {
# 363 : 13419 : int b;
# 364 [ + + ]: 120771 : for (b = 0; b < 8; b++) {
# 365 : 107352 : s->slice[b] = (a->slice[b] >> c) & 0x1111;
# 366 : 107352 : }
# 367 : 13419 : }
# 368 : :
# 369 : : /** column_c1(r) |= (column_0(s) ^= column_c2(a)) */
# 370 : 697788 : static void KeySetupColumnMix(AES_state* s, AES_state* r, const AES_state* a, int c1, int c2) {
# 371 : 697788 : int b;
# 372 [ + + ]: 6280092 : for (b = 0; b < 8; b++) {
# 373 : 5582304 : r->slice[b] |= ((s->slice[b] ^= ((a->slice[b] >> c2) & 0x1111)) & 0x1111) << c1;
# 374 : 5582304 : }
# 375 : 697788 : }
# 376 : :
# 377 : : /** Rotate the rows in s one position upwards, and xor in r */
# 378 : 93933 : static void KeySetupTransform(AES_state* s, const AES_state* r) {
# 379 : 93933 : int b;
# 380 [ + + ]: 845397 : for (b = 0; b < 8; b++) {
# 381 : 751464 : s->slice[b] = ((s->slice[b] >> 4) | (s->slice[b] << 12)) ^ r->slice[b];
# 382 : 751464 : }
# 383 : 93933 : }
# 384 : :
# 385 : : /* Multiply the cells in s by x, as polynomials over GF(2) mod x^8 + x^4 + x^3 + x + 1 */
# 386 : 93933 : static void MultX(AES_state* s) {
# 387 : 93933 : uint16_t top = s->slice[7];
# 388 : 93933 : s->slice[7] = s->slice[6];
# 389 : 93933 : s->slice[6] = s->slice[5];
# 390 : 93933 : s->slice[5] = s->slice[4];
# 391 : 93933 : s->slice[4] = s->slice[3] ^ top;
# 392 : 93933 : s->slice[3] = s->slice[2] ^ top;
# 393 : 93933 : s->slice[2] = s->slice[1];
# 394 : 93933 : s->slice[1] = s->slice[0] ^ top;
# 395 : 93933 : s->slice[0] = top;
# 396 : 93933 : }
# 397 : :
# 398 : : /** Expand the cipher key into the key schedule.
# 399 : : *
# 400 : : * state must be a pointer to an array of size nrounds + 1.
# 401 : : * key must be a pointer to 4 * nkeywords bytes.
# 402 : : *
# 403 : : * AES128 uses nkeywords = 4, nrounds = 10
# 404 : : * AES192 uses nkeywords = 6, nrounds = 12
# 405 : : * AES256 uses nkeywords = 8, nrounds = 14
# 406 : : */
# 407 : : static void AES_setup(AES_state* rounds, const uint8_t* key, int nkeywords, int nrounds)
# 408 : 13419 : {
# 409 : 13419 : int i;
# 410 : :
# 411 : : /* The one-byte round constant */
# 412 : 13419 : AES_state rcon = {{1,0,0,0,0,0,0,0}};
# 413 : : /* The number of the word being generated, modulo nkeywords */
# 414 : 13419 : int pos = 0;
# 415 : : /* The column representing the word currently being processed */
# 416 : 13419 : AES_state column;
# 417 : :
# 418 [ + + ]: 214704 : for (i = 0; i < nrounds + 1; i++) {
# 419 : 201285 : int b;
# 420 [ + + ]: 1811565 : for (b = 0; b < 8; b++) {
# 421 : 1610280 : rounds[i].slice[b] = 0;
# 422 : 1610280 : }
# 423 : 201285 : }
# 424 : :
# 425 : : /* The first nkeywords round columns are just taken from the key directly. */
# 426 [ + + ]: 120771 : for (i = 0; i < nkeywords; i++) {
# 427 : 107352 : int r;
# 428 [ + + ]: 536760 : for (r = 0; r < 4; r++) {
# 429 : 429408 : LoadByte(&rounds[i >> 2], *(key++), r, i & 3);
# 430 : 429408 : }
# 431 : 107352 : }
# 432 : :
# 433 : 13419 : GetOneColumn(&column, &rounds[(nkeywords - 1) >> 2], (nkeywords - 1) & 3);
# 434 : :
# 435 [ + + ]: 711207 : for (i = nkeywords; i < 4 * (nrounds + 1); i++) {
# 436 : : /* Transform column */
# 437 [ + + ]: 697788 : if (pos == 0) {
# 438 : 93933 : SubBytes(&column, 0);
# 439 : 93933 : KeySetupTransform(&column, &rcon);
# 440 : 93933 : MultX(&rcon);
# 441 [ + - ][ + + ]: 603855 : } else if (nkeywords > 6 && pos == 4) {
# 442 : 80514 : SubBytes(&column, 0);
# 443 : 80514 : }
# 444 [ + + ]: 697788 : if (++pos == nkeywords) pos = 0;
# 445 : 697788 : KeySetupColumnMix(&column, &rounds[i >> 2], &rounds[(i - nkeywords) >> 2], i & 3, (i - nkeywords) & 3);
# 446 : 697788 : }
# 447 : 13419 : }
# 448 : :
# 449 : 9500 : static void AES_encrypt(const AES_state* rounds, int nrounds, unsigned char* cipher16, const unsigned char* plain16) {
# 450 : 9500 : AES_state s = {{0}};
# 451 : 9500 : int round;
# 452 : :
# 453 : 9500 : LoadBytes(&s, plain16);
# 454 : 9500 : AddRoundKey(&s, rounds++);
# 455 : :
# 456 [ + + ]: 133000 : for (round = 1; round < nrounds; round++) {
# 457 : 123500 : SubBytes(&s, 0);
# 458 : 123500 : ShiftRows(&s);
# 459 : 123500 : MixColumns(&s, 0);
# 460 : 123500 : AddRoundKey(&s, rounds++);
# 461 : 123500 : }
# 462 : :
# 463 : 9500 : SubBytes(&s, 0);
# 464 : 9500 : ShiftRows(&s);
# 465 : 9500 : AddRoundKey(&s, rounds);
# 466 : :
# 467 : 9500 : SaveBytes(cipher16, &s);
# 468 : 9500 : }
# 469 : :
# 470 : 21559 : static void AES_decrypt(const AES_state* rounds, int nrounds, unsigned char* plain16, const unsigned char* cipher16) {
# 471 : : /* Most AES decryption implementations use the alternate scheme
# 472 : : * (the Equivalent Inverse Cipher), which allows for more code reuse between
# 473 : : * the encryption and decryption code, but requires separate setup for both.
# 474 : : */
# 475 : 21559 : AES_state s = {{0}};
# 476 : 21559 : int round;
# 477 : :
# 478 : 21559 : rounds += nrounds;
# 479 : :
# 480 : 21559 : LoadBytes(&s, cipher16);
# 481 : 21559 : AddRoundKey(&s, rounds--);
# 482 : :
# 483 [ + + ]: 301826 : for (round = 1; round < nrounds; round++) {
# 484 : 280267 : InvShiftRows(&s);
# 485 : 280267 : SubBytes(&s, 1);
# 486 : 280267 : AddRoundKey(&s, rounds--);
# 487 : 280267 : MixColumns(&s, 1);
# 488 : 280267 : }
# 489 : :
# 490 : 21559 : InvShiftRows(&s);
# 491 : 21559 : SubBytes(&s, 1);
# 492 : 21559 : AddRoundKey(&s, rounds);
# 493 : :
# 494 : 21559 : SaveBytes(plain16, &s);
# 495 : 21559 : }
# 496 : :
# 497 : 0 : void AES128_init(AES128_ctx* ctx, const unsigned char* key16) {
# 498 : 0 : AES_setup(ctx->rk, key16, 4, 10);
# 499 : 0 : }
# 500 : :
# 501 : 0 : void AES128_encrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) {
# 502 [ # # ]: 0 : while (blocks--) {
# 503 : 0 : AES_encrypt(ctx->rk, 10, cipher16, plain16);
# 504 : 0 : cipher16 += 16;
# 505 : 0 : plain16 += 16;
# 506 : 0 : }
# 507 : 0 : }
# 508 : :
# 509 : 0 : void AES128_decrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) {
# 510 [ # # ]: 0 : while (blocks--) {
# 511 : 0 : AES_decrypt(ctx->rk, 10, plain16, cipher16);
# 512 : 0 : cipher16 += 16;
# 513 : 0 : plain16 += 16;
# 514 : 0 : }
# 515 : 0 : }
# 516 : :
# 517 : 0 : void AES192_init(AES192_ctx* ctx, const unsigned char* key24) {
# 518 : 0 : AES_setup(ctx->rk, key24, 6, 12);
# 519 : 0 : }
# 520 : :
# 521 : 0 : void AES192_encrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) {
# 522 [ # # ]: 0 : while (blocks--) {
# 523 : 0 : AES_encrypt(ctx->rk, 12, cipher16, plain16);
# 524 : 0 : cipher16 += 16;
# 525 : 0 : plain16 += 16;
# 526 : 0 : }
# 527 : :
# 528 : 0 : }
# 529 : :
# 530 : 0 : void AES192_decrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) {
# 531 [ # # ]: 0 : while (blocks--) {
# 532 : 0 : AES_decrypt(ctx->rk, 12, plain16, cipher16);
# 533 : 0 : cipher16 += 16;
# 534 : 0 : plain16 += 16;
# 535 : 0 : }
# 536 : 0 : }
# 537 : :
# 538 : 13419 : void AES256_init(AES256_ctx* ctx, const unsigned char* key32) {
# 539 : 13419 : AES_setup(ctx->rk, key32, 8, 14);
# 540 : 13419 : }
# 541 : :
# 542 : 9500 : void AES256_encrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) {
# 543 [ + + ]: 19000 : while (blocks--) {
# 544 : 9500 : AES_encrypt(ctx->rk, 14, cipher16, plain16);
# 545 : 9500 : cipher16 += 16;
# 546 : 9500 : plain16 += 16;
# 547 : 9500 : }
# 548 : 9500 : }
# 549 : :
# 550 : 21559 : void AES256_decrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) {
# 551 [ + + ]: 43118 : while (blocks--) {
# 552 : 21559 : AES_decrypt(ctx->rk, 14, plain16, cipher16);
# 553 : 21559 : cipher16 += 16;
# 554 : 21559 : plain16 += 16;
# 555 : 21559 : }
# 556 : 21559 : }
|