/** * Multiply to elements of GF(2**128) using the reducing polynomial * (x^128 + x^7 + x^2 + x + 1). */ static void gcm_mult(uint8_t out[16], const uint8_t x[16], const uint8_t y[16]) { uint64_t z[2], v[2]; int i; /** z, v = 0, y **/ z[0] = z[1] = 0; v[0] = be_to_word(&y[0]); v[1] = be_to_word(&y[8]); for (i=0; i<16; i++) { uint8_t j; for (j=0x80; j>0; j>>=1) { uint64_t c; /** z ^= (x>>i&1)*v **/ if (x[i] & j) { z[0] ^= v[0]; z[1] ^= v[1]; } /** v = (v&1)*0xE1000000000000000000000000000000L ^ (v>>1) **/ c = v[1]&1 ? 0xE100000000000000 : 0; v[1] = v[1]>>1 | (v[0] << 63); v[0] = v[0]>>1 ^ c; } } word_to_be(out, z[0]); word_to_be(out+8, z[1]); }
/** * Multiply two elements of GF(2**128) using the reducing polynomial * (x^128 + x^7 + x^2 + x + 1). * * \param out The 16 byte buffer that will receive the result * \param key_tables One factor, expanded into a V table * \param x The other factor (16 bytes) */ static void gcm_mult2(uint8_t out[16], const t_v_tables *key_tables, const uint8_t x[16]) { int i, bit_scan_128; uint64_t z[2]; z[0] = z[1] = 0; bit_scan_128 = 0; for (i=0; i<16; i++) { uint8_t xi; int j; xi = x[i]; for (j=0; j<8; j++) { int bit; bit = xi>>7 & 1; /** Constant time */ z[0] ^= (*key_tables)[bit_scan_128][bit][0]; z[1] ^= (*key_tables)[bit_scan_128][bit][1]; xi <<= 1; bit_scan_128++; } } word_to_be(out, z[0]); word_to_be(out+8, z[1]); }
/** * Multiply two elements of GF(2**128) using the reducing polynomial * (x^128 + x^7 + x^2 + x + 1). * * The first element has been expanded into H tables. */ static void gcm_mult2(uint8_t out[16], const t_key_tables *key_tables, const uint8_t x[16]) { int i; uint64_t z[2]; z[0] = z[1] = 0; for (i=0; i<16; i++) { z[0] ^= (*key_tables)[i][x[i]][0]; z[1] ^= (*key_tables)[i][x[i]][1]; } word_to_be(out, z[0]); word_to_be(out+8, z[1]); }