1
+ pragma circom 2.1.9;
2
+
3
+ include "vclmul_emulator.circom";
4
+ include "helper_functions.circom";
5
+
6
+ // GFMULInt multiplies two 128-bit numbers in GF(2^128) and returns the result.
7
+ //
8
+ // Inputs:
9
+ // - `a` the first 128-bit number, encoded as a polynomial over GF(2^128)
10
+ // - `b` the second 128-bit number, encoded as a polynomial over GF(2^128)
11
+ //
12
+ // Outputs:
13
+ // - `res` the result of the multiplication
14
+ //
15
+ // Computes:
16
+ // res = a * b mod p
17
+ // where p = x^128 + x^7 + x^2 + x + 1
18
+ template GFMULInt()
19
+ {
20
+ signal input a[2][64];
21
+ signal input b[2][64];
22
+ signal output res[2][64];
23
+
24
+
25
+ // TODO(TK 2024-08-10): note about magic nuhmebr
26
+ var tmp[5][2][64];
27
+
28
+ // XMMMask is x^128 + x^7 + x^2 + x + 1
29
+ // GHASH is big endian, polyval is little endian
30
+ // bitwise: 11100001 .... 00000001
31
+ //
32
+ // 0x87 = 0b1000_0111 => encode x^7 + x^2 + x + 1
33
+ var XMMMASK[2] = [0x87, 0x0];
34
+
35
+ var i, j, k;
36
+
37
+ log("GFMULInt");
38
+ log(a[0][0]);
39
+ // log(b);
40
+ // log("res", res);
41
+
42
+ component num2bits_1[2];
43
+ var XMMMASK_bits[2][64];
44
+ for(i=0; i<2; i++)
45
+ {
46
+ num2bits_1[i] = Num2Bits(64);
47
+ num2bits_1[i].in <== XMMMASK[i];
48
+ for(j=0; j<8; j++)
49
+ {
50
+ for(k=0; k<8; k++) XMMMASK_bits[i][j*8+k] = num2bits_1[i].out[j*8+7-k];
51
+ }
52
+ }
53
+
54
+ component vclmul_emulator_1[4];
55
+
56
+ for(i=0; i<4; i++)
57
+ {
58
+ vclmul_emulator_1[i] = VCLMULEmulator(i);
59
+ for(j=0; j<2; j++)
60
+ {
61
+ for(k=0; k<64; k++)
62
+ {
63
+ vclmul_emulator_1[i].src1[j][k] <== a[j][k];
64
+ vclmul_emulator_1[i].src2[j][k] <== b[j][k];
65
+ }
66
+ }
67
+
68
+ tmp[i+1] = vclmul_emulator_1[i].destination;
69
+ }
70
+
71
+ component xor_1[2][64];
72
+ for(i=0; i<2; i++)
73
+ {
74
+ for(j=0; j<64; j++)
75
+ {
76
+ xor_1[i][j] = XOR();
77
+ xor_1[i][j].a <== tmp[2][i][j];
78
+ xor_1[i][j].b <== tmp[3][i][j];
79
+
80
+ tmp[2][i][j] = xor_1[i][j].out;
81
+ }
82
+ }
83
+
84
+ for(i=0; i<64; i++) tmp[3][0][i] = 0;
85
+
86
+ for(i=0; i<64; i++) tmp[3][1][i] = tmp[2][0][i];
87
+
88
+ for(i=0; i<64; i++) tmp[2][0][i] = tmp[2][1][i];
89
+
90
+ for(i=0; i<64; i++) tmp[2][1][i] = 0;
91
+
92
+ component xor_2[2][64];
93
+ for(i=0; i<2; i++)
94
+ {
95
+ for(j=0; j<64; j++)
96
+ {
97
+ xor_2[i][j] = XOR();
98
+ xor_2[i][j].a <== tmp[1][i][j];
99
+ xor_2[i][j].b <== tmp[3][i][j];
100
+
101
+ tmp[1][i][j] = xor_2[i][j].out;
102
+ }
103
+ }
104
+
105
+ component xor_3[2][64];
106
+ for(i=0; i<2; i++)
107
+ {
108
+ for(j=0; j<64; j++)
109
+ {
110
+ xor_3[i][j] = XOR();
111
+ xor_3[i][j].a <== tmp[4][i][j];
112
+ xor_3[i][j].b <== tmp[2][i][j];
113
+
114
+ tmp[4][i][j] = xor_3[i][j].out;
115
+ }
116
+ }
117
+
118
+ component vclmul_emulator_2 = VCLMULEmulator(1);
119
+ for(i=0; i<2; i++)
120
+ {
121
+ for(j=0; j<64; j++)
122
+ {
123
+ vclmul_emulator_2.src1[i][j] <== XMMMASK_bits[i][j];
124
+ vclmul_emulator_2.src2[i][j] <== tmp[1][i][j];
125
+ }
126
+ }
127
+
128
+ tmp[2] = vclmul_emulator_2.destination;
129
+
130
+ for(i=0; i<64; i++)
131
+ {
132
+ tmp[3][0][i] = tmp[1][1][i];
133
+ tmp[3][1][i] = tmp[1][0][i];
134
+ }
135
+
136
+ component xor_4[2][64];
137
+ for(i=0; i<2; i++)
138
+ {
139
+ for(j=0; j<64; j++)
140
+ {
141
+ xor_4[i][j] = XOR();
142
+ xor_4[i][j].a <== tmp[2][i][j];
143
+ xor_4[i][j].b <== tmp[3][i][j];
144
+
145
+ tmp[1][i][j] = xor_4[i][j].out;
146
+ }
147
+ }
148
+
149
+ component vclmul_emulator_3 = VCLMULEmulator(1);
150
+ for(i=0; i<2; i++)
151
+ {
152
+ for(j=0; j<64; j++)
153
+ {
154
+ vclmul_emulator_3.src1[i][j] <== XMMMASK_bits[i][j];
155
+ vclmul_emulator_3.src2[i][j] <== tmp[1][i][j];
156
+ }
157
+ }
158
+
159
+ tmp[2] = vclmul_emulator_3.destination;
160
+
161
+ for(i=0; i<64; i++)
162
+ {
163
+ tmp[3][0][i] = tmp[1][1][i];
164
+ tmp[3][1][i] = tmp[1][0][i];
165
+ }
166
+
167
+ component xor_5[2][64];
168
+ for(i=0; i<2; i++)
169
+ {
170
+ for(j=0; j<64; j++)
171
+ {
172
+ xor_5[i][j] = XOR();
173
+ xor_5[i][j].a <== tmp[2][i][j];
174
+ xor_5[i][j].b <== tmp[3][i][j];
175
+
176
+ tmp[1][i][j] = xor_5[i][j].out;
177
+ }
178
+ }
179
+
180
+ component xor_6[2][64];
181
+ for(i=0; i<2; i++)
182
+ {
183
+ for(j=0; j<64; j++)
184
+ {
185
+ xor_6[i][j] = XOR();
186
+ xor_6[i][j].a <== tmp[1][i][j];
187
+ xor_6[i][j].b <== tmp[4][i][j];
188
+
189
+ res[i][j] <== xor_6[i][j].out;
190
+ }
191
+ }
192
+ }
0 commit comments