| ... | ... | @@ -94,7 +94,18 @@ pub const Ghash = struct { |
| 94 | 94 | } |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | | fn bmul(x: u64, y: u64) u64 { |
| 97 | inline fn clmul_pclmul(x: u64, y: u64) u64 { |
| 98 | const Vector = std.meta.Vector; |
| 99 | const product = asm ( |
| 100 | \\ vpclmulqdq $0x00, %[x], %[y], %[out] |
| 101 | : [out] "=x" (-> Vector(2, u64)) |
| 102 | : [x] "x" (@bitCast(Vector(2, u64), @as(u128, x))), |
| 103 | [y] "x" (@bitCast(Vector(2, u64), @as(u128, y))) |
| 104 | ); |
| 105 | return product[0]; |
| 106 | } |
| 107 | |
| 108 | fn clmul_soft(x: u64, y: u64) u64 { |
| 98 | 109 | const x0 = x & 0x1111111111111111; |
| 99 | 110 | const x1 = x & 0x2222222222222222; |
| 100 | 111 | const x2 = x & 0x4444444444444444; |
| ... | ... | @@ -111,10 +122,13 @@ pub const Ghash = struct { |
| 111 | 122 | z1 &= 0x2222222222222222; |
| 112 | 123 | z2 &= 0x4444444444444444; |
| 113 | 124 | z3 &= 0x8888888888888888; |
| 114 | | |
| 115 | 125 | return z0 | z1 | z2 | z3; |
| 116 | 126 | } |
| 117 | 127 | |
| 128 | const has_pclmul = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .pclmul); |
| 129 | const has_avx = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .avx); |
| 130 | const clmul = if (std.Target.current.cpu.arch == .x86_64 and has_pclmul and has_avx) clmul_pclmul else clmul_soft; |
| 131 | |
| 118 | 132 | fn blocks(st: *Ghash, msg: []const u8) void { |
| 119 | 133 | assert(msg.len % 16 == 0); // GHASH blocks() expects full blocks |
| 120 | 134 | var y1 = st.y1; |
| ... | ... | @@ -134,12 +148,12 @@ pub const Ghash = struct { |
| 134 | 148 | const y2 = y0 ^ y1; |
| 135 | 149 | const y2r = y0r ^ y1r; |
| 136 | 150 | |
| 137 | | var z0 = bmul(y0, st.hh0); |
| 138 | | var z1 = bmul(y1, st.hh1); |
| 139 | | var z2 = bmul(y2, st.hh2) ^ z0 ^ z1; |
| 140 | | var z0h = bmul(y0r, st.hh0r); |
| 141 | | var z1h = bmul(y1r, st.hh1r); |
| 142 | | var z2h = bmul(y2r, st.hh2r) ^ z0h ^ z1h; |
| 151 | var z0 = clmul(y0, st.hh0); |
| 152 | var z1 = clmul(y1, st.hh1); |
| 153 | var z2 = clmul(y2, st.hh2) ^ z0 ^ z1; |
| 154 | var z0h = clmul(y0r, st.hh0r); |
| 155 | var z1h = clmul(y1r, st.hh1r); |
| 156 | var z2h = clmul(y2r, st.hh2r) ^ z0h ^ z1h; |
| 143 | 157 | |
| 144 | 158 | // B1 * H unreduced |
| 145 | 159 | const sy1 = mem.readIntBig(u64, msg[i..][16..24]); |
| ... | ... | @@ -150,12 +164,12 @@ pub const Ghash = struct { |
| 150 | 164 | const sy2 = sy0 ^ sy1; |
| 151 | 165 | const sy2r = sy0r ^ sy1r; |
| 152 | 166 | |
| 153 | | const sz0 = bmul(sy0, st.h0); |
| 154 | | const sz1 = bmul(sy1, st.h1); |
| 155 | | const sz2 = bmul(sy2, st.h2) ^ sz0 ^ sz1; |
| 156 | | const sz0h = bmul(sy0r, st.h0r); |
| 157 | | const sz1h = bmul(sy1r, st.h1r); |
| 158 | | const sz2h = bmul(sy2r, st.h2r) ^ sz0h ^ sz1h; |
| 167 | const sz0 = clmul(sy0, st.h0); |
| 168 | const sz1 = clmul(sy1, st.h1); |
| 169 | const sz2 = clmul(sy2, st.h2) ^ sz0 ^ sz1; |
| 170 | const sz0h = clmul(sy0r, st.h0r); |
| 171 | const sz1h = clmul(sy1r, st.h1r); |
| 172 | const sz2h = clmul(sy2r, st.h2r) ^ sz0h ^ sz1h; |
| 159 | 173 | |
| 160 | 174 | // ((B0 * H^2) + B1 * H) (mod M) |
| 161 | 175 | z0 ^= sz0; |
| ... | ... | @@ -195,12 +209,12 @@ pub const Ghash = struct { |
| 195 | 209 | const y2 = y0 ^ y1; |
| 196 | 210 | const y2r = y0r ^ y1r; |
| 197 | 211 | |
| 198 | | const z0 = bmul(y0, st.h0); |
| 199 | | const z1 = bmul(y1, st.h1); |
| 200 | | var z2 = bmul(y2, st.h2) ^ z0 ^ z1; |
| 201 | | var z0h = bmul(y0r, st.h0r); |
| 202 | | var z1h = bmul(y1r, st.h1r); |
| 203 | | var z2h = bmul(y2r, st.h2r) ^ z0h ^ z1h; |
| 212 | const z0 = clmul(y0, st.h0); |
| 213 | const z1 = clmul(y1, st.h1); |
| 214 | var z2 = clmul(y2, st.h2) ^ z0 ^ z1; |
| 215 | var z0h = clmul(y0r, st.h0r); |
| 216 | var z1h = clmul(y1r, st.h1r); |
| 217 | var z2h = clmul(y2r, st.h2r) ^ z0h ^ z1h; |
| 204 | 218 | z0h = @bitReverse(u64, z0h) >> 1; |
| 205 | 219 | z1h = @bitReverse(u64, z1h) >> 1; |
| 206 | 220 | z2h = @bitReverse(u64, z2h) >> 1; |