| ... | @@ -94,7 +94,18 @@ pub const Ghash = struct { | ... | @@ -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 | const x0 = x & 0x1111111111111111; | 109 | const x0 = x & 0x1111111111111111; |
| 99 | const x1 = x & 0x2222222222222222; | 110 | const x1 = x & 0x2222222222222222; |
| 100 | const x2 = x & 0x4444444444444444; | 111 | const x2 = x & 0x4444444444444444; |
| ... | @@ -111,10 +122,13 @@ pub const Ghash = struct { | ... | @@ -111,10 +122,13 @@ pub const Ghash = struct { |
| 111 | z1 &= 0x2222222222222222; | 122 | z1 &= 0x2222222222222222; |
| 112 | z2 &= 0x4444444444444444; | 123 | z2 &= 0x4444444444444444; |
| 113 | z3 &= 0x8888888888888888; | 124 | z3 &= 0x8888888888888888; |
| 114 | | | |
| 115 | return z0 | z1 | z2 | z3; | 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 | fn blocks(st: *Ghash, msg: []const u8) void { | 132 | fn blocks(st: *Ghash, msg: []const u8) void { |
| 119 | assert(msg.len % 16 == 0); // GHASH blocks() expects full blocks | 133 | assert(msg.len % 16 == 0); // GHASH blocks() expects full blocks |
| 120 | var y1 = st.y1; | 134 | var y1 = st.y1; |
| ... | @@ -134,12 +148,12 @@ pub const Ghash = struct { | ... | @@ -134,12 +148,12 @@ pub const Ghash = struct { |
| 134 | const y2 = y0 ^ y1; | 148 | const y2 = y0 ^ y1; |
| 135 | const y2r = y0r ^ y1r; | 149 | const y2r = y0r ^ y1r; |
| 136 | | 150 | |
| 137 | var z0 = bmul(y0, st.hh0); | 151 | var z0 = clmul(y0, st.hh0); |
| 138 | var z1 = bmul(y1, st.hh1); | 152 | var z1 = clmul(y1, st.hh1); |
| 139 | var z2 = bmul(y2, st.hh2) ^ z0 ^ z1; | 153 | var z2 = clmul(y2, st.hh2) ^ z0 ^ z1; |
| 140 | var z0h = bmul(y0r, st.hh0r); | 154 | var z0h = clmul(y0r, st.hh0r); |
| 141 | var z1h = bmul(y1r, st.hh1r); | 155 | var z1h = clmul(y1r, st.hh1r); |
| 142 | var z2h = bmul(y2r, st.hh2r) ^ z0h ^ z1h; | 156 | var z2h = clmul(y2r, st.hh2r) ^ z0h ^ z1h; |
| 143 | | 157 | |
| 144 | // B1 * H unreduced | 158 | // B1 * H unreduced |
| 145 | const sy1 = mem.readIntBig(u64, msg[i..][16..24]); | 159 | const sy1 = mem.readIntBig(u64, msg[i..][16..24]); |
| ... | @@ -150,12 +164,12 @@ pub const Ghash = struct { | ... | @@ -150,12 +164,12 @@ pub const Ghash = struct { |
| 150 | const sy2 = sy0 ^ sy1; | 164 | const sy2 = sy0 ^ sy1; |
| 151 | const sy2r = sy0r ^ sy1r; | 165 | const sy2r = sy0r ^ sy1r; |
| 152 | | 166 | |
| 153 | const sz0 = bmul(sy0, st.h0); | 167 | const sz0 = clmul(sy0, st.h0); |
| 154 | const sz1 = bmul(sy1, st.h1); | 168 | const sz1 = clmul(sy1, st.h1); |
| 155 | const sz2 = bmul(sy2, st.h2) ^ sz0 ^ sz1; | 169 | const sz2 = clmul(sy2, st.h2) ^ sz0 ^ sz1; |
| 156 | const sz0h = bmul(sy0r, st.h0r); | 170 | const sz0h = clmul(sy0r, st.h0r); |
| 157 | const sz1h = bmul(sy1r, st.h1r); | 171 | const sz1h = clmul(sy1r, st.h1r); |
| 158 | const sz2h = bmul(sy2r, st.h2r) ^ sz0h ^ sz1h; | 172 | const sz2h = clmul(sy2r, st.h2r) ^ sz0h ^ sz1h; |
| 159 | | 173 | |
| 160 | // ((B0 * H^2) + B1 * H) (mod M) | 174 | // ((B0 * H^2) + B1 * H) (mod M) |
| 161 | z0 ^= sz0; | 175 | z0 ^= sz0; |
| ... | @@ -195,12 +209,12 @@ pub const Ghash = struct { | ... | @@ -195,12 +209,12 @@ pub const Ghash = struct { |
| 195 | const y2 = y0 ^ y1; | 209 | const y2 = y0 ^ y1; |
| 196 | const y2r = y0r ^ y1r; | 210 | const y2r = y0r ^ y1r; |
| 197 | | 211 | |
| 198 | const z0 = bmul(y0, st.h0); | 212 | const z0 = clmul(y0, st.h0); |
| 199 | const z1 = bmul(y1, st.h1); | 213 | const z1 = clmul(y1, st.h1); |
| 200 | var z2 = bmul(y2, st.h2) ^ z0 ^ z1; | 214 | var z2 = clmul(y2, st.h2) ^ z0 ^ z1; |
| 201 | var z0h = bmul(y0r, st.h0r); | 215 | var z0h = clmul(y0r, st.h0r); |
| 202 | var z1h = bmul(y1r, st.h1r); | 216 | var z1h = clmul(y1r, st.h1r); |
| 203 | var z2h = bmul(y2r, st.h2r) ^ z0h ^ z1h; | 217 | var z2h = clmul(y2r, st.h2r) ^ z0h ^ z1h; |
| 204 | z0h = @bitReverse(u64, z0h) >> 1; | 218 | z0h = @bitReverse(u64, z0h) >> 1; |
| 205 | z1h = @bitReverse(u64, z1h) >> 1; | 219 | z1h = @bitReverse(u64, z1h) >> 1; |
| 206 | z2h = @bitReverse(u64, z2h) >> 1; | 220 | z2h = @bitReverse(u64, z2h) >> 1; |