diff options
author | Jay Threeth | 2011-04-04 11:48:26 -0700 |
---|---|---|
committer | Jay Threeth | 2011-04-04 11:48:26 -0700 |
commit | 3c9cc506f741b980565ff5b3b001cd8b6ee36b12 (patch) | |
tree | cb862c57b3d5f74177cde3bd962a53fc377166f6 /linden/indra/libotr/libotr-3.2.0/src/sm.c | |
parent | build fixes, might build on linux now (diff) | |
download | meta-impy-3c9cc506f741b980565ff5b3b001cd8b6ee36b12.zip meta-impy-3c9cc506f741b980565ff5b3b001cd8b6ee36b12.tar.gz meta-impy-3c9cc506f741b980565ff5b3b001cd8b6ee36b12.tar.bz2 meta-impy-3c9cc506f741b980565ff5b3b001cd8b6ee36b12.tar.xz |
add source to libraries, and cruft for building under windows
Diffstat (limited to 'linden/indra/libotr/libotr-3.2.0/src/sm.c')
-rwxr-xr-x | linden/indra/libotr/libotr-3.2.0/src/sm.c | 929 |
1 files changed, 929 insertions, 0 deletions
diff --git a/linden/indra/libotr/libotr-3.2.0/src/sm.c b/linden/indra/libotr/libotr-3.2.0/src/sm.c new file mode 100755 index 0000000..318b461 --- /dev/null +++ b/linden/indra/libotr/libotr-3.2.0/src/sm.c | |||
@@ -0,0 +1,929 @@ | |||
1 | /* | ||
2 | * Off-the-Record Messaging library | ||
3 | * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov | ||
4 | * <otr@cypherpunks.ca> | ||
5 | * | ||
6 | * This library is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of version 2.1 of the GNU Lesser General | ||
8 | * Public License as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This library is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * Lesser General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Lesser General Public | ||
16 | * License along with this library; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | /* system headers */ | ||
21 | #include <stdlib.h> | ||
22 | #include <stdio.h> | ||
23 | #include <sys/types.h> | ||
24 | |||
25 | /* libgcrypt headers */ | ||
26 | #include <gcrypt.h> | ||
27 | |||
28 | /* libotr headers */ | ||
29 | #include "sm.h" | ||
30 | #include "serial.h" | ||
31 | |||
32 | static const int SM_MSG1_LEN = 6; | ||
33 | static const int SM_MSG2_LEN = 11; | ||
34 | static const int SM_MSG3_LEN = 8; | ||
35 | static const int SM_MSG4_LEN = 3; | ||
36 | |||
37 | /* The modulus p */ | ||
38 | static const char* SM_MODULUS_S = "0x" | ||
39 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" | ||
40 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" | ||
41 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" | ||
42 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" | ||
43 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" | ||
44 | "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" | ||
45 | "83655D23DCA3AD961C62F356208552BB9ED529077096966D" | ||
46 | "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"; | ||
47 | /* The order of the group q = (p-1)/2 */ | ||
48 | static const char* SM_ORDER_S = "0x" | ||
49 | "7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68" | ||
50 | "948127044533E63A0105DF531D89CD9128A5043CC71A026E" | ||
51 | "F7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122" | ||
52 | "F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6" | ||
53 | "F71C35FDAD44CFD2D74F9208BE258FF324943328F6722D9E" | ||
54 | "E1003E5C50B1DF82CC6D241B0E2AE9CD348B1FD47E9267AF" | ||
55 | "C1B2AE91EE51D6CB0E3179AB1042A95DCF6A9483B84B4B36" | ||
56 | "B3861AA7255E4C0278BA36046511B993FFFFFFFFFFFFFFFF"; | ||
57 | static const char *SM_GENERATOR_S = "0x02"; | ||
58 | static const int SM_MOD_LEN_BITS = 1536; | ||
59 | static const int SM_MOD_LEN_BYTES = 192; | ||
60 | |||
61 | static gcry_mpi_t SM_MODULUS = NULL; | ||
62 | static gcry_mpi_t SM_GENERATOR = NULL; | ||
63 | static gcry_mpi_t SM_ORDER = NULL; | ||
64 | static gcry_mpi_t SM_MODULUS_MINUS_2 = NULL; | ||
65 | |||
66 | /* | ||
67 | * Call this once, at plugin load time. It sets up the modulus and | ||
68 | * generator MPIs. | ||
69 | */ | ||
70 | void otrl_sm_init(void) | ||
71 | { | ||
72 | gcry_check_version(NULL); | ||
73 | gcry_mpi_scan(&SM_MODULUS, GCRYMPI_FMT_HEX, SM_MODULUS_S, 0, NULL); | ||
74 | gcry_mpi_scan(&SM_ORDER, GCRYMPI_FMT_HEX, SM_ORDER_S, 0, NULL); | ||
75 | gcry_mpi_scan(&SM_GENERATOR, GCRYMPI_FMT_HEX, SM_GENERATOR_S, | ||
76 | 0, NULL); | ||
77 | SM_MODULUS_MINUS_2 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
78 | gcry_mpi_sub_ui(SM_MODULUS_MINUS_2, SM_MODULUS, 2); | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * Initialize the fields of a SM state. | ||
83 | */ | ||
84 | void otrl_sm_state_new(OtrlSMState *smst) | ||
85 | { | ||
86 | smst->secret = NULL; | ||
87 | smst->x2 = NULL; | ||
88 | smst->x3 = NULL; | ||
89 | smst->g1 = NULL; | ||
90 | smst->g2 = NULL; | ||
91 | smst->g3 = NULL; | ||
92 | smst->g3o = NULL; | ||
93 | smst->p = NULL; | ||
94 | smst->q = NULL; | ||
95 | smst->pab = NULL; | ||
96 | smst->qab = NULL; | ||
97 | smst->nextExpected = OTRL_SMP_EXPECT1; | ||
98 | smst->received_question = 0; | ||
99 | smst->sm_prog_state = OTRL_SMP_PROG_OK; | ||
100 | } | ||
101 | |||
102 | /* | ||
103 | * Initialize the fields of a SM state. Called the first time that | ||
104 | * a user begins an SMP session. | ||
105 | */ | ||
106 | void otrl_sm_state_init(OtrlSMState *smst) | ||
107 | { | ||
108 | otrl_sm_state_free(smst); | ||
109 | smst->secret = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
110 | smst->x2 = NULL; | ||
111 | smst->x3 = NULL; | ||
112 | smst->g1 = gcry_mpi_copy(SM_GENERATOR); | ||
113 | smst->g2 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
114 | smst->g3 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
115 | smst->g3o = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
116 | smst->p = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
117 | smst->q = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
118 | smst->pab = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
119 | smst->qab = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
120 | smst->received_question = 0; | ||
121 | smst->sm_prog_state = OTRL_SMP_PROG_OK; | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * Initialize the fields of a SM message1. | ||
126 | * [0] = g2a, [1] = c2, [2] = d2, [3] = g3a, [4] = c3, [5] = d3 | ||
127 | */ | ||
128 | void otrl_sm_msg1_init(gcry_mpi_t **msg1) | ||
129 | { | ||
130 | gcry_mpi_t *msg = malloc(SM_MSG1_LEN * sizeof(gcry_mpi_t)); | ||
131 | msg[0] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
132 | msg[1] = NULL; | ||
133 | msg[2] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
134 | msg[3] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
135 | msg[4] = NULL; | ||
136 | msg[5] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
137 | |||
138 | *msg1 = msg; | ||
139 | } | ||
140 | |||
141 | /* | ||
142 | * Initialize the fields of a SM message2. | ||
143 | * [0] = g2b, [1] = c2, [2] = d2, [3] = g3b, [4] = c3, [5] = d3 | ||
144 | * [6] = pb, [7] = qb, [8] = cp, [9] = d5, [10] = d6 | ||
145 | */ | ||
146 | void otrl_sm_msg2_init(gcry_mpi_t **msg2) | ||
147 | { | ||
148 | gcry_mpi_t *msg = malloc(SM_MSG2_LEN * sizeof(gcry_mpi_t)); | ||
149 | msg[0] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
150 | msg[1] = NULL; | ||
151 | msg[2] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
152 | msg[3] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
153 | msg[4] = NULL; | ||
154 | msg[5] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
155 | msg[6] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
156 | msg[7] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
157 | msg[8] = NULL; | ||
158 | msg[9] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
159 | msg[10] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
160 | |||
161 | *msg2 = msg; | ||
162 | } | ||
163 | |||
164 | /* | ||
165 | * Initialize the fields of a SM message3. | ||
166 | * [0] = pa, [1] = qa, [2] = cp, [3] = d5, [4] = d6, [5] = ra, | ||
167 | * [6] = cr, [7] = d7 | ||
168 | */ | ||
169 | void otrl_sm_msg3_init(gcry_mpi_t **msg3) | ||
170 | { | ||
171 | gcry_mpi_t *msg = malloc(SM_MSG3_LEN * sizeof(gcry_mpi_t)); | ||
172 | msg[0] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
173 | msg[1] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
174 | msg[2] = NULL; | ||
175 | msg[3] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
176 | msg[4] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
177 | msg[5] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
178 | msg[6] = NULL; | ||
179 | msg[7] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
180 | |||
181 | *msg3 = msg; | ||
182 | } | ||
183 | |||
184 | /* | ||
185 | * Initialize the fields of a SM message4. | ||
186 | * [0] = rb, [1] = cr, [2] = d7 | ||
187 | */ | ||
188 | void otrl_sm_msg4_init(gcry_mpi_t **msg4) | ||
189 | { | ||
190 | gcry_mpi_t *msg = malloc(SM_MSG4_LEN * sizeof(gcry_mpi_t)); | ||
191 | msg[0] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
192 | msg[1] = NULL; | ||
193 | msg[2] = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
194 | |||
195 | *msg4 = msg; | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | * Deallocate the contents of a OtrlSMState (but not the OtrlSMState | ||
200 | * itself) | ||
201 | */ | ||
202 | void otrl_sm_state_free(OtrlSMState *smst) | ||
203 | { | ||
204 | gcry_mpi_release(smst->secret); | ||
205 | gcry_mpi_release(smst->x2); | ||
206 | gcry_mpi_release(smst->x3); | ||
207 | gcry_mpi_release(smst->g1); | ||
208 | gcry_mpi_release(smst->g2); | ||
209 | gcry_mpi_release(smst->g3); | ||
210 | gcry_mpi_release(smst->g3o); | ||
211 | gcry_mpi_release(smst->p); | ||
212 | gcry_mpi_release(smst->q); | ||
213 | gcry_mpi_release(smst->pab); | ||
214 | gcry_mpi_release(smst->qab); | ||
215 | otrl_sm_state_new(smst); | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * Deallocate the contents of a message | ||
220 | */ | ||
221 | void otrl_sm_msg_free(gcry_mpi_t **message, int msglen) | ||
222 | { | ||
223 | gcry_mpi_t *msg = *message; | ||
224 | int i; | ||
225 | for (i=0; i<msglen; i++) { | ||
226 | gcry_mpi_release(msg[i]); | ||
227 | } | ||
228 | free(msg); | ||
229 | *message = NULL; | ||
230 | } | ||
231 | |||
232 | static gcry_mpi_t randomExponent(void) | ||
233 | { | ||
234 | unsigned char *secbuf = NULL; | ||
235 | gcry_mpi_t randexpon = NULL; | ||
236 | |||
237 | /* Generate a random exponent */ | ||
238 | secbuf = gcry_random_bytes_secure(SM_MOD_LEN_BYTES, GCRY_STRONG_RANDOM); | ||
239 | gcry_mpi_scan(&randexpon, GCRYMPI_FMT_USG, secbuf, SM_MOD_LEN_BYTES, NULL); | ||
240 | gcry_free(secbuf); | ||
241 | |||
242 | return randexpon; | ||
243 | } | ||
244 | |||
245 | /* | ||
246 | * Hash one or two mpis. To hash only one mpi, b may be set to NULL. | ||
247 | */ | ||
248 | static gcry_error_t otrl_sm_hash(gcry_mpi_t* hash, int version, | ||
249 | const gcry_mpi_t a, const gcry_mpi_t b) | ||
250 | { | ||
251 | unsigned char* input; | ||
252 | unsigned char output[SM_DIGEST_SIZE]; | ||
253 | size_t sizea; | ||
254 | size_t sizeb; | ||
255 | size_t totalsize; | ||
256 | unsigned char* dataa; | ||
257 | unsigned char* datab; | ||
258 | |||
259 | gcry_mpi_aprint(GCRYMPI_FMT_USG, &dataa, &sizea, a); | ||
260 | totalsize = 1 + 4 + sizea; | ||
261 | if (b) { | ||
262 | gcry_mpi_aprint(GCRYMPI_FMT_USG, &datab, &sizeb, b); | ||
263 | totalsize += 4 + sizeb; | ||
264 | } else { | ||
265 | sizeb = 0; | ||
266 | } | ||
267 | |||
268 | input = malloc(totalsize); | ||
269 | input[0] = (unsigned char)version; | ||
270 | input[1] = (unsigned char)((sizea >> 24) & 0xFF); | ||
271 | input[2] = (unsigned char)((sizea >> 16) & 0xFF); | ||
272 | input[3] = (unsigned char)((sizea >> 8) & 0xFF); | ||
273 | input[4] = (unsigned char)(sizea & 0xFF); | ||
274 | memmove(input + 5, dataa, sizea); | ||
275 | if (b) { | ||
276 | input[5 + sizea] = (unsigned char)((sizeb >> 24) & 0xFF); | ||
277 | input[6 + sizea] = (unsigned char)((sizeb >> 16) & 0xFF); | ||
278 | input[7 + sizea] = (unsigned char)((sizeb >> 8) & 0xFF); | ||
279 | input[8 + sizea] = (unsigned char)(sizeb & 0xFF); | ||
280 | memmove(input + 9 + sizea, datab, sizeb); | ||
281 | } | ||
282 | |||
283 | gcry_md_hash_buffer(SM_HASH_ALGORITHM, output, input, totalsize); | ||
284 | gcry_mpi_scan(hash, GCRYMPI_FMT_USG, output, SM_DIGEST_SIZE, NULL); | ||
285 | free(input); | ||
286 | input = NULL; | ||
287 | |||
288 | /* free memory */ | ||
289 | gcry_free(dataa); | ||
290 | if (b) gcry_free(datab); | ||
291 | |||
292 | return gcry_error(GPG_ERR_NO_ERROR); | ||
293 | } | ||
294 | |||
295 | /* This method should be passed a pointer to an uninitialized buffer, | ||
296 | * and a list of mpis with a list length. When returns, the buffer will | ||
297 | * point to newly-allocated memory (using malloc) containing a | ||
298 | * reversible serialization. */ | ||
299 | static gcry_error_t serialize_mpi_array(unsigned char **buffer, int *buflen, | ||
300 | unsigned int count, gcry_mpi_t *mpis) | ||
301 | { | ||
302 | size_t totalsize = 0, lenp, nextsize; | ||
303 | unsigned int i, j; | ||
304 | size_t *list_sizes = malloc(count * sizeof(size_t)); | ||
305 | unsigned char **tempbuffer = malloc(count * sizeof(unsigned char *)); | ||
306 | unsigned char *bufp; | ||
307 | |||
308 | for (i=0; i<count; i++) { | ||
309 | gcry_mpi_aprint(GCRYMPI_FMT_USG, &(tempbuffer[i]), &(list_sizes[i]), | ||
310 | mpis[i]); | ||
311 | totalsize += list_sizes[i]; | ||
312 | } | ||
313 | |||
314 | *buflen = (count+1)*4 + totalsize; | ||
315 | *buffer = malloc(*buflen * sizeof(char)); | ||
316 | |||
317 | bufp = *buffer; | ||
318 | lenp = totalsize; | ||
319 | |||
320 | write_int(count); | ||
321 | for(i=0; i<count; i++) | ||
322 | { | ||
323 | nextsize = list_sizes[i]; | ||
324 | write_int(nextsize); | ||
325 | |||
326 | for(j=0; j<nextsize; j++) | ||
327 | bufp[j] = tempbuffer[i][j]; | ||
328 | |||
329 | bufp += nextsize; | ||
330 | lenp -= nextsize; | ||
331 | gcry_free(tempbuffer[i]); | ||
332 | } | ||
333 | free(tempbuffer); | ||
334 | free(list_sizes); | ||
335 | |||
336 | return gcry_error(GPG_ERR_NO_ERROR); | ||
337 | } | ||
338 | |||
339 | /* Takes a buffer containing serialized and concatenated mpis | ||
340 | * and converts it to an array of gcry_mpi_t structs. | ||
341 | * The buffer is assumed to consist of a 4-byte int containing the | ||
342 | * number of mpis in the array, followed by {size, data} pairs for | ||
343 | * each mpi. If malformed, method returns GCRY_ERROR_INV_VALUE */ | ||
344 | static gcry_error_t unserialize_mpi_array(gcry_mpi_t **mpis, | ||
345 | unsigned int expcount, const unsigned char *buffer, const int buflen) | ||
346 | { | ||
347 | unsigned int i; | ||
348 | int lenp = buflen; | ||
349 | unsigned int thecount = 0; | ||
350 | const unsigned char* bufp = buffer; | ||
351 | *mpis = NULL; | ||
352 | |||
353 | read_int(thecount); | ||
354 | if (thecount != expcount) goto invval; | ||
355 | |||
356 | *mpis = malloc(thecount * sizeof(gcry_mpi_t)); | ||
357 | |||
358 | for (i=0; i<thecount; i++) { | ||
359 | (*mpis)[i] = NULL; | ||
360 | } | ||
361 | |||
362 | for (i=0; i<thecount; i++) { | ||
363 | read_mpi((*mpis)[i]); | ||
364 | } | ||
365 | |||
366 | return gcry_error(GPG_ERR_NO_ERROR); | ||
367 | |||
368 | invval: | ||
369 | if (*mpis) { | ||
370 | for (i=0; i<thecount; i++) { | ||
371 | gcry_mpi_release((*mpis)[i]); | ||
372 | } | ||
373 | free(*mpis); | ||
374 | *mpis = NULL; | ||
375 | } | ||
376 | return gcry_error(GPG_ERR_INV_VALUE); | ||
377 | } | ||
378 | |||
379 | /* Check that an MPI is in the right range to be a (non-unit) group | ||
380 | * element */ | ||
381 | static int check_group_elem(gcry_mpi_t g) | ||
382 | { | ||
383 | if (gcry_mpi_cmp_ui(g, 2) < 0 || | ||
384 | gcry_mpi_cmp(g, SM_MODULUS_MINUS_2) > 0) { | ||
385 | return 1; | ||
386 | } | ||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | /* Check that an MPI is in the right range to be a (non-zero) exponent */ | ||
391 | static int check_expon(gcry_mpi_t x) | ||
392 | { | ||
393 | if (gcry_mpi_cmp_ui(x, 1) < 0 || | ||
394 | gcry_mpi_cmp(x, SM_ORDER) >= 0) { | ||
395 | return 1; | ||
396 | } | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | /* | ||
401 | * Proof of knowledge of a discrete logarithm | ||
402 | */ | ||
403 | static gcry_error_t otrl_sm_proof_know_log(gcry_mpi_t *c, gcry_mpi_t *d, const gcry_mpi_t g, const gcry_mpi_t x, int version) | ||
404 | { | ||
405 | gcry_mpi_t r = randomExponent(); | ||
406 | gcry_mpi_t temp = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
407 | gcry_mpi_powm(temp, g, r, SM_MODULUS); | ||
408 | otrl_sm_hash(c, version, temp, NULL); | ||
409 | gcry_mpi_mulm(temp, x, *c, SM_ORDER); | ||
410 | gcry_mpi_subm(*d, r, temp, SM_ORDER); | ||
411 | gcry_mpi_release(temp); | ||
412 | gcry_mpi_release(r); | ||
413 | |||
414 | return gcry_error(GPG_ERR_NO_ERROR); | ||
415 | } | ||
416 | |||
417 | /* | ||
418 | * Verify a proof of knowledge of a discrete logarithm. Checks that c = h(g^d x^c) | ||
419 | */ | ||
420 | static int otrl_sm_check_know_log(const gcry_mpi_t c, const gcry_mpi_t d, const gcry_mpi_t g, const gcry_mpi_t x, int version) | ||
421 | { | ||
422 | int comp; | ||
423 | |||
424 | gcry_mpi_t gd = gcry_mpi_new(SM_MOD_LEN_BITS); /* g^d */ | ||
425 | gcry_mpi_t xc = gcry_mpi_new(SM_MOD_LEN_BITS); /* x^c */ | ||
426 | gcry_mpi_t gdxc = gcry_mpi_new(SM_MOD_LEN_BITS); /* (g^d x^c) */ | ||
427 | gcry_mpi_t hgdxc = NULL; /* h(g^d x^c) */ | ||
428 | |||
429 | gcry_mpi_powm(gd, g, d, SM_MODULUS); | ||
430 | gcry_mpi_powm(xc, x, c, SM_MODULUS); | ||
431 | gcry_mpi_mulm(gdxc, gd, xc, SM_MODULUS); | ||
432 | otrl_sm_hash(&hgdxc, version, gdxc, NULL); | ||
433 | |||
434 | comp = gcry_mpi_cmp(hgdxc, c); | ||
435 | gcry_mpi_release(gd); | ||
436 | gcry_mpi_release(xc); | ||
437 | gcry_mpi_release(gdxc); | ||
438 | gcry_mpi_release(hgdxc); | ||
439 | |||
440 | return comp; | ||
441 | } | ||
442 | |||
443 | /* | ||
444 | * Proof of knowledge of coordinates with first components being equal | ||
445 | */ | ||
446 | static gcry_error_t otrl_sm_proof_equal_coords(gcry_mpi_t *c, gcry_mpi_t *d1, gcry_mpi_t *d2, const OtrlSMState *state, const gcry_mpi_t r, int version) | ||
447 | { | ||
448 | gcry_mpi_t r1 = randomExponent(); | ||
449 | gcry_mpi_t r2 = randomExponent(); | ||
450 | gcry_mpi_t temp1 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
451 | gcry_mpi_t temp2 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
452 | |||
453 | /* Compute the value of c, as c = h(g3^r1, g1^r1 g2^r2) */ | ||
454 | gcry_mpi_powm(temp1, state->g1, r1, SM_MODULUS); | ||
455 | gcry_mpi_powm(temp2, state->g2, r2, SM_MODULUS); | ||
456 | gcry_mpi_mulm(temp2, temp1, temp2, SM_MODULUS); | ||
457 | gcry_mpi_powm(temp1, state->g3, r1, SM_MODULUS); | ||
458 | otrl_sm_hash(c, version, temp1, temp2); | ||
459 | |||
460 | /* Compute the d values, as d1 = r1 - r c, d2 = r2 - secret c */ | ||
461 | gcry_mpi_mulm(temp1, r, *c, SM_ORDER); | ||
462 | gcry_mpi_subm(*d1, r1, temp1, SM_ORDER); | ||
463 | |||
464 | gcry_mpi_mulm(temp1, state->secret, *c, SM_ORDER); | ||
465 | gcry_mpi_subm(*d2, r2, temp1, SM_ORDER); | ||
466 | |||
467 | /* All clear */ | ||
468 | gcry_mpi_release(r1); | ||
469 | gcry_mpi_release(r2); | ||
470 | gcry_mpi_release(temp1); | ||
471 | gcry_mpi_release(temp2); | ||
472 | return gcry_error(GPG_ERR_NO_ERROR); | ||
473 | } | ||
474 | |||
475 | /* | ||
476 | * Verify a proof of knowledge of coordinates with first components being equal | ||
477 | */ | ||
478 | static gcry_error_t otrl_sm_check_equal_coords(const gcry_mpi_t c, const gcry_mpi_t d1, const gcry_mpi_t d2, const gcry_mpi_t p, const gcry_mpi_t q, const OtrlSMState *state, int version) | ||
479 | { | ||
480 | int comp; | ||
481 | |||
482 | gcry_mpi_t temp1 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
483 | gcry_mpi_t temp2 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
484 | gcry_mpi_t temp3 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
485 | gcry_mpi_t cprime = NULL; | ||
486 | |||
487 | /* To verify, we test that hash(g3^d1 * p^c, g1^d1 * g2^d2 * q^c) = c | ||
488 | * If indeed c = hash(g3^r1, g1^r1 g2^r2), d1 = r1 - r*c, | ||
489 | * d2 = r2 - secret*c. And if indeed p = g3^r, q = g1^r * g2^secret | ||
490 | * Then we should have that: | ||
491 | * hash(g3^d1 * p^c, g1^d1 * g2^d2 * q^c) | ||
492 | * = hash(g3^(r1 - r*c + r*c), g1^(r1 - r*c + q*c) * | ||
493 | * g2^(r2 - secret*c + secret*c)) | ||
494 | * = hash(g3^r1, g1^r1 g2^r2) | ||
495 | * = c | ||
496 | */ | ||
497 | gcry_mpi_powm(temp2, state->g3, d1, SM_MODULUS); | ||
498 | gcry_mpi_powm(temp3, p, c, SM_MODULUS); | ||
499 | gcry_mpi_mulm(temp1, temp2, temp3, SM_MODULUS); | ||
500 | |||
501 | gcry_mpi_powm(temp2, state->g1, d1, SM_MODULUS); | ||
502 | gcry_mpi_powm(temp3, state->g2, d2, SM_MODULUS); | ||
503 | gcry_mpi_mulm(temp2, temp2, temp3, SM_MODULUS); | ||
504 | gcry_mpi_powm(temp3, q, c, SM_MODULUS); | ||
505 | gcry_mpi_mulm(temp2, temp3, temp2, SM_MODULUS); | ||
506 | |||
507 | otrl_sm_hash(&cprime, version, temp1, temp2); | ||
508 | |||
509 | comp = gcry_mpi_cmp(c, cprime); | ||
510 | gcry_mpi_release(temp1); | ||
511 | gcry_mpi_release(temp2); | ||
512 | gcry_mpi_release(temp3); | ||
513 | gcry_mpi_release(cprime); | ||
514 | |||
515 | return comp; | ||
516 | } | ||
517 | |||
518 | /* | ||
519 | * Proof of knowledge of logs with exponents being equal | ||
520 | */ | ||
521 | static gcry_error_t otrl_sm_proof_equal_logs(gcry_mpi_t *c, gcry_mpi_t *d, OtrlSMState *state, int version) | ||
522 | { | ||
523 | gcry_mpi_t r = randomExponent(); | ||
524 | gcry_mpi_t temp1 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
525 | gcry_mpi_t temp2 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
526 | |||
527 | /* Compute the value of c, as c = h(g1^r, (Qa/Qb)^r) */ | ||
528 | gcry_mpi_powm(temp1, state->g1, r, SM_MODULUS); | ||
529 | gcry_mpi_powm(temp2, state->qab, r, SM_MODULUS); | ||
530 | otrl_sm_hash(c, version, temp1, temp2); | ||
531 | |||
532 | /* Compute the d values, as d = r - x3 c */ | ||
533 | gcry_mpi_mulm(temp1, state->x3, *c, SM_ORDER); | ||
534 | gcry_mpi_subm(*d, r, temp1, SM_ORDER); | ||
535 | |||
536 | /* All clear */ | ||
537 | gcry_mpi_release(r); | ||
538 | gcry_mpi_release(temp1); | ||
539 | gcry_mpi_release(temp2); | ||
540 | return gcry_error(GPG_ERR_NO_ERROR); | ||
541 | } | ||
542 | |||
543 | /* | ||
544 | * Verify a proof of knowledge of logs with exponents being equal | ||
545 | */ | ||
546 | static gcry_error_t otrl_sm_check_equal_logs(const gcry_mpi_t c, const gcry_mpi_t d, const gcry_mpi_t r, const OtrlSMState *state, int version) | ||
547 | { | ||
548 | int comp; | ||
549 | |||
550 | gcry_mpi_t temp1 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
551 | gcry_mpi_t temp2 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
552 | gcry_mpi_t temp3 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
553 | gcry_mpi_t cprime = NULL; | ||
554 | |||
555 | /* Here, we recall the exponents used to create g3. | ||
556 | * If we have previously seen g3o = g1^x where x is unknown | ||
557 | * during the DH exchange to produce g3, then we may proceed with: | ||
558 | * | ||
559 | * To verify, we test that hash(g1^d * g3o^c, qab^d * r^c) = c | ||
560 | * If indeed c = hash(g1^r1, qab^r1), d = r1- x * c | ||
561 | * And if indeed r = qab^x | ||
562 | * Then we should have that: | ||
563 | * hash(g1^d * g3o^c, qab^d r^c) | ||
564 | * = hash(g1^(r1 - x*c + x*c), qab^(r1 - x*c + x*c)) | ||
565 | * = hash(g1^r1, qab^r1) | ||
566 | * = c | ||
567 | */ | ||
568 | gcry_mpi_powm(temp2, state->g1, d, SM_MODULUS); | ||
569 | gcry_mpi_powm(temp3, state->g3o, c, SM_MODULUS); | ||
570 | gcry_mpi_mulm(temp1, temp2, temp3, SM_MODULUS); | ||
571 | |||
572 | gcry_mpi_powm(temp3, state->qab, d, SM_MODULUS); | ||
573 | gcry_mpi_powm(temp2, r, c, SM_MODULUS); | ||
574 | gcry_mpi_mulm(temp2, temp3, temp2, SM_MODULUS); | ||
575 | |||
576 | otrl_sm_hash(&cprime, version, temp1, temp2); | ||
577 | |||
578 | comp = gcry_mpi_cmp(c, cprime); | ||
579 | gcry_mpi_release(temp1); | ||
580 | gcry_mpi_release(temp2); | ||
581 | gcry_mpi_release(temp3); | ||
582 | gcry_mpi_release(cprime); | ||
583 | |||
584 | return comp; | ||
585 | } | ||
586 | |||
587 | /* Create first message in SMP exchange. Input is Alice's secret value | ||
588 | * which this protocol aims to compare to Bob's. Output is a serialized | ||
589 | * mpi array whose elements correspond to the following: | ||
590 | * [0] = g2a, Alice's half of DH exchange to determine g2 | ||
591 | * [1] = c2, [2] = d2, Alice's ZK proof of knowledge of g2a exponent | ||
592 | * [3] = g3a, Alice's half of DH exchange to determine g3 | ||
593 | * [4] = c3, [5] = d3, Alice's ZK proof of knowledge of g3a exponent */ | ||
594 | gcry_error_t otrl_sm_step1(OtrlSMAliceState *astate, | ||
595 | const unsigned char* secret, int secretlen, | ||
596 | unsigned char** output, int* outputlen) | ||
597 | { | ||
598 | /* Initialize the sm state or update the secret */ | ||
599 | gcry_mpi_t secret_mpi = NULL; | ||
600 | gcry_mpi_t *msg1; | ||
601 | |||
602 | *output = NULL; | ||
603 | *outputlen = 0; | ||
604 | |||
605 | gcry_mpi_scan(&secret_mpi, GCRYMPI_FMT_USG, secret, secretlen, NULL); | ||
606 | |||
607 | if (! astate->g1) { | ||
608 | otrl_sm_state_init(astate); | ||
609 | } | ||
610 | gcry_mpi_set(astate->secret, secret_mpi); | ||
611 | gcry_mpi_release(secret_mpi); | ||
612 | astate->received_question = 0; | ||
613 | |||
614 | otrl_sm_msg1_init(&msg1); | ||
615 | |||
616 | astate->x2 = randomExponent(); | ||
617 | astate->x3 = randomExponent(); | ||
618 | |||
619 | gcry_mpi_powm(msg1[0], astate->g1, astate->x2, SM_MODULUS); | ||
620 | otrl_sm_proof_know_log(&(msg1[1]), &(msg1[2]), astate->g1, astate->x2, 1); | ||
621 | |||
622 | gcry_mpi_powm(msg1[3], astate->g1, astate->x3, SM_MODULUS); | ||
623 | otrl_sm_proof_know_log(&(msg1[4]), &(msg1[5]), astate->g1, astate->x3, 2); | ||
624 | |||
625 | serialize_mpi_array(output, outputlen, SM_MSG1_LEN, msg1); | ||
626 | otrl_sm_msg_free(&msg1, SM_MSG1_LEN); | ||
627 | astate->sm_prog_state = OTRL_SMP_PROG_OK; | ||
628 | return gcry_error(GPG_ERR_NO_ERROR); | ||
629 | } | ||
630 | |||
631 | /* Receive the first message in SMP exchange, which was generated by | ||
632 | * otrl_sm_step1. Input is saved until the user inputs their secret | ||
633 | * information. No output. */ | ||
634 | gcry_error_t otrl_sm_step2a(OtrlSMBobState *bstate, const unsigned char* input, const int inputlen, int received_question) | ||
635 | { | ||
636 | gcry_mpi_t *msg1; | ||
637 | gcry_error_t err; | ||
638 | |||
639 | /* Initialize the sm state if needed */ | ||
640 | if (! bstate->g1) { | ||
641 | otrl_sm_state_init(bstate); | ||
642 | } | ||
643 | bstate->received_question = received_question; | ||
644 | bstate->sm_prog_state = OTRL_SMP_PROG_CHEATED; | ||
645 | |||
646 | /* Read from input to find the mpis */ | ||
647 | err = unserialize_mpi_array(&msg1, SM_MSG1_LEN, input, inputlen); | ||
648 | |||
649 | if (err != gcry_error(GPG_ERR_NO_ERROR)) return err; | ||
650 | |||
651 | if (check_group_elem(msg1[0]) || check_expon(msg1[2]) || | ||
652 | check_group_elem(msg1[3]) || check_expon(msg1[5])) { | ||
653 | return gcry_error(GPG_ERR_INV_VALUE); | ||
654 | } | ||
655 | |||
656 | /* Store Alice's g3a value for later in the protocol */ | ||
657 | gcry_mpi_set(bstate->g3o, msg1[3]); | ||
658 | |||
659 | /* Verify Alice's proofs */ | ||
660 | if (otrl_sm_check_know_log(msg1[1], msg1[2], bstate->g1, msg1[0], 1) || | ||
661 | otrl_sm_check_know_log(msg1[4], msg1[5], bstate->g1, msg1[3], 2)) { | ||
662 | return gcry_error(GPG_ERR_INV_VALUE); | ||
663 | } | ||
664 | |||
665 | /* Create Bob's half of the generators g2 and g3 */ | ||
666 | bstate->x2 = randomExponent(); | ||
667 | bstate->x3 = randomExponent(); | ||
668 | |||
669 | /* Combine the two halves from Bob and Alice and determine g2 and g3 */ | ||
670 | gcry_mpi_powm(bstate->g2, msg1[0], bstate->x2, SM_MODULUS); | ||
671 | gcry_mpi_powm(bstate->g3, msg1[3], bstate->x3, SM_MODULUS); | ||
672 | |||
673 | bstate->sm_prog_state = OTRL_SMP_PROG_OK; | ||
674 | return gcry_error(GPG_ERR_NO_ERROR); | ||
675 | } | ||
676 | |||
677 | /* Create second message in SMP exchange. Input is Bob's secret value. | ||
678 | * Information from earlier steps in the exchange is taken from Bob's | ||
679 | * state. Output is a serialized mpi array whose elements correspond | ||
680 | * to the following: | ||
681 | * [0] = g2b, Bob's half of DH exchange to determine g2 | ||
682 | * [1] = c2, [2] = d2, Bob's ZK proof of knowledge of g2b exponent | ||
683 | * [3] = g3b, Bob's half of DH exchange to determine g3 | ||
684 | * [4] = c3, [5] = d3, Bob's ZK proof of knowledge of g3b exponent | ||
685 | * [6] = pb, [7] = qb, Bob's halves of the (Pa/Pb) and (Qa/Qb) values | ||
686 | * [8] = cp, [9] = d5, [10] = d6, Bob's ZK proof that pb, qb formed correctly */ | ||
687 | gcry_error_t otrl_sm_step2b(OtrlSMBobState *bstate, const unsigned char* secret, int secretlen, unsigned char **output, int* outputlen) | ||
688 | { | ||
689 | /* Convert the given secret to the proper form and store it */ | ||
690 | gcry_mpi_t r, qb1, qb2; | ||
691 | gcry_mpi_t *msg2; | ||
692 | gcry_mpi_t secret_mpi = NULL; | ||
693 | |||
694 | *output = NULL; | ||
695 | *outputlen = 0; | ||
696 | |||
697 | gcry_mpi_scan(&secret_mpi, GCRYMPI_FMT_USG, secret, secretlen, NULL); | ||
698 | gcry_mpi_set(bstate->secret, secret_mpi); | ||
699 | gcry_mpi_release(secret_mpi); | ||
700 | |||
701 | otrl_sm_msg2_init(&msg2); | ||
702 | |||
703 | gcry_mpi_powm(msg2[0], bstate->g1, bstate->x2, SM_MODULUS); | ||
704 | otrl_sm_proof_know_log(&(msg2[1]), &(msg2[2]), bstate->g1, bstate->x2, 3); | ||
705 | |||
706 | gcry_mpi_powm(msg2[3], bstate->g1, bstate->x3, SM_MODULUS); | ||
707 | otrl_sm_proof_know_log(&(msg2[4]), &(msg2[5]), bstate->g1, bstate->x3, 4); | ||
708 | |||
709 | /* Calculate P and Q values for Bob */ | ||
710 | r = randomExponent(); | ||
711 | qb1 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
712 | qb2 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
713 | gcry_mpi_powm(bstate->p, bstate->g3, r, SM_MODULUS); | ||
714 | gcry_mpi_set(msg2[6], bstate->p); | ||
715 | gcry_mpi_powm(qb1, bstate->g1, r, SM_MODULUS); | ||
716 | gcry_mpi_powm(qb2, bstate->g2, bstate->secret, SM_MODULUS); | ||
717 | gcry_mpi_mulm(bstate->q, qb1, qb2, SM_MODULUS); | ||
718 | gcry_mpi_set(msg2[7], bstate->q); | ||
719 | |||
720 | otrl_sm_proof_equal_coords(&(msg2[8]), &(msg2[9]), &(msg2[10]), bstate, r, 5); | ||
721 | |||
722 | /* Convert to serialized form */ | ||
723 | serialize_mpi_array(output, outputlen, SM_MSG2_LEN, msg2); | ||
724 | |||
725 | /* Free up memory for unserialized and intermediate values */ | ||
726 | gcry_mpi_release(r); | ||
727 | gcry_mpi_release(qb1); | ||
728 | gcry_mpi_release(qb2); | ||
729 | otrl_sm_msg_free(&msg2, SM_MSG2_LEN); | ||
730 | |||
731 | return gcry_error(GPG_ERR_NO_ERROR); | ||
732 | } | ||
733 | |||
734 | /* Create third message in SMP exchange. Input is a message generated | ||
735 | * by otrl_sm_step2b. Output is a serialized mpi array whose elements | ||
736 | * correspond to the following: | ||
737 | * [0] = pa, [1] = qa, Alice's halves of the (Pa/Pb) and (Qa/Qb) values | ||
738 | * [2] = cp, [3] = d5, [4] = d6, Alice's ZK proof that pa, qa formed correctly | ||
739 | * [5] = ra, calculated as (Qa/Qb)^x3 where x3 is the exponent used in g3a | ||
740 | * [6] = cr, [7] = d7, Alice's ZK proof that ra is formed correctly */ | ||
741 | gcry_error_t otrl_sm_step3(OtrlSMAliceState *astate, const unsigned char* input, const int inputlen, unsigned char **output, int* outputlen) | ||
742 | { | ||
743 | /* Read from input to find the mpis */ | ||
744 | gcry_mpi_t r, qa1, qa2, inv; | ||
745 | gcry_mpi_t *msg2; | ||
746 | gcry_mpi_t *msg3; | ||
747 | gcry_error_t err; | ||
748 | |||
749 | *output = NULL; | ||
750 | *outputlen = 0; | ||
751 | astate->sm_prog_state = OTRL_SMP_PROG_CHEATED; | ||
752 | |||
753 | err = unserialize_mpi_array(&msg2, SM_MSG2_LEN, input, inputlen); | ||
754 | if (err != gcry_error(GPG_ERR_NO_ERROR)) return err; | ||
755 | |||
756 | if (check_group_elem(msg2[0]) || check_group_elem(msg2[3]) || | ||
757 | check_group_elem(msg2[6]) || check_group_elem(msg2[7]) || | ||
758 | check_expon(msg2[2]) || check_expon(msg2[5]) || | ||
759 | check_expon(msg2[9]) || check_expon(msg2[10])) { | ||
760 | return gcry_error(GPG_ERR_INV_VALUE); | ||
761 | } | ||
762 | |||
763 | otrl_sm_msg3_init(&msg3); | ||
764 | |||
765 | /* Store Bob's g3a value for later in the protocol */ | ||
766 | gcry_mpi_set(astate->g3o, msg2[3]); | ||
767 | |||
768 | /* Verify Bob's knowledge of discreet log proofs */ | ||
769 | if (otrl_sm_check_know_log(msg2[1], msg2[2], astate->g1, msg2[0], 3) || | ||
770 | otrl_sm_check_know_log(msg2[4], msg2[5], astate->g1, msg2[3], 4)) { | ||
771 | return gcry_error(GPG_ERR_INV_VALUE); | ||
772 | } | ||
773 | |||
774 | /* Combine the two halves from Bob and Alice and determine g2 and g3 */ | ||
775 | gcry_mpi_powm(astate->g2, msg2[0], astate->x2, SM_MODULUS); | ||
776 | gcry_mpi_powm(astate->g3, msg2[3], astate->x3, SM_MODULUS); | ||
777 | |||
778 | /* Verify Bob's coordinate equality proof */ | ||
779 | if (otrl_sm_check_equal_coords(msg2[8], msg2[9], msg2[10], msg2[6], msg2[7], astate, 5)) | ||
780 | return gcry_error(GPG_ERR_INV_VALUE); | ||
781 | |||
782 | /* Calculate P and Q values for Alice */ | ||
783 | r = randomExponent(); | ||
784 | qa1 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
785 | qa2 = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
786 | gcry_mpi_powm(astate->p, astate->g3, r, SM_MODULUS); | ||
787 | gcry_mpi_set(msg3[0], astate->p); | ||
788 | gcry_mpi_powm(qa1, astate->g1, r, SM_MODULUS); | ||
789 | gcry_mpi_powm(qa2, astate->g2, astate->secret, SM_MODULUS); | ||
790 | gcry_mpi_mulm(astate->q, qa1, qa2, SM_MODULUS); | ||
791 | gcry_mpi_set(msg3[1], astate->q); | ||
792 | |||
793 | otrl_sm_proof_equal_coords(&(msg3[2]), &(msg3[3]), &(msg3[4]), astate, r, 6); | ||
794 | |||
795 | /* Calculate Ra and proof */ | ||
796 | inv = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
797 | gcry_mpi_invm(inv, msg2[6], SM_MODULUS); | ||
798 | gcry_mpi_mulm(astate->pab, astate->p, inv, SM_MODULUS); | ||
799 | gcry_mpi_invm(inv, msg2[7], SM_MODULUS); | ||
800 | gcry_mpi_mulm(astate->qab, astate->q, inv, SM_MODULUS); | ||
801 | gcry_mpi_powm(msg3[5], astate->qab, astate->x3, SM_MODULUS); | ||
802 | otrl_sm_proof_equal_logs(&(msg3[6]), &(msg3[7]), astate, 7); | ||
803 | |||
804 | serialize_mpi_array(output, outputlen, SM_MSG3_LEN, msg3); | ||
805 | otrl_sm_msg_free(&msg2, SM_MSG2_LEN); | ||
806 | otrl_sm_msg_free(&msg3, SM_MSG3_LEN); | ||
807 | |||
808 | gcry_mpi_release(r); | ||
809 | gcry_mpi_release(qa1); | ||
810 | gcry_mpi_release(qa2); | ||
811 | gcry_mpi_release(inv); | ||
812 | |||
813 | astate->sm_prog_state = OTRL_SMP_PROG_OK; | ||
814 | return gcry_error(GPG_ERR_NO_ERROR); | ||
815 | } | ||
816 | |||
817 | /* Create final message in SMP exchange. Input is a message generated | ||
818 | * by otrl_sm_step3. Output is a serialized mpi array whose elements | ||
819 | * correspond to the following: | ||
820 | * [0] = rb, calculated as (Qa/Qb)^x3 where x3 is the exponent used in g3b | ||
821 | * [1] = cr, [2] = d7, Bob's ZK proof that rb is formed correctly | ||
822 | * This method also checks if Alice and Bob's secrets were the same. If | ||
823 | * so, it returns NO_ERROR. If the secrets differ, an INV_VALUE error is | ||
824 | * returned instead. */ | ||
825 | gcry_error_t otrl_sm_step4(OtrlSMBobState *bstate, const unsigned char* input, const int inputlen, unsigned char **output, int* outputlen) | ||
826 | { | ||
827 | /* Read from input to find the mpis */ | ||
828 | int comp; | ||
829 | gcry_mpi_t inv, rab; | ||
830 | gcry_mpi_t *msg3; | ||
831 | gcry_mpi_t *msg4; | ||
832 | gcry_error_t err; | ||
833 | err = unserialize_mpi_array(&msg3, SM_MSG3_LEN, input, inputlen); | ||
834 | |||
835 | *output = NULL; | ||
836 | *outputlen = 0; | ||
837 | bstate->sm_prog_state = OTRL_SMP_PROG_CHEATED; | ||
838 | |||
839 | if (err != gcry_error(GPG_ERR_NO_ERROR)) return err; | ||
840 | |||
841 | otrl_sm_msg4_init(&msg4); | ||
842 | |||
843 | if (check_group_elem(msg3[0]) || check_group_elem(msg3[1]) || | ||
844 | check_group_elem(msg3[5]) || check_expon(msg3[3]) || | ||
845 | check_expon(msg3[4]) || check_expon(msg3[7])) { | ||
846 | return gcry_error(GPG_ERR_INV_VALUE); | ||
847 | } | ||
848 | |||
849 | /* Verify Alice's coordinate equality proof */ | ||
850 | if (otrl_sm_check_equal_coords(msg3[2], msg3[3], msg3[4], msg3[0], msg3[1], bstate, 6)) | ||
851 | return gcry_error(GPG_ERR_INV_VALUE); | ||
852 | |||
853 | /* Find Pa/Pb and Qa/Qb */ | ||
854 | inv = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
855 | gcry_mpi_invm(inv, bstate->p, SM_MODULUS); | ||
856 | gcry_mpi_mulm(bstate->pab, msg3[0], inv, SM_MODULUS); | ||
857 | gcry_mpi_invm(inv, bstate->q, SM_MODULUS); | ||
858 | gcry_mpi_mulm(bstate->qab, msg3[1], inv, SM_MODULUS); | ||
859 | |||
860 | /* Verify Alice's log equality proof */ | ||
861 | if (otrl_sm_check_equal_logs(msg3[6], msg3[7], msg3[5], bstate, 7)) | ||
862 | return gcry_error(GPG_ERR_INV_VALUE); | ||
863 | |||
864 | /* Calculate Rb and proof */ | ||
865 | gcry_mpi_powm(msg4[0], bstate->qab, bstate->x3, SM_MODULUS); | ||
866 | otrl_sm_proof_equal_logs(&(msg4[1]), &(msg4[2]), bstate, 8); | ||
867 | |||
868 | serialize_mpi_array(output, outputlen, SM_MSG4_LEN, msg4); | ||
869 | |||
870 | /* Calculate Rab and verify that secrets match */ | ||
871 | rab = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
872 | gcry_mpi_powm(rab, msg3[5], bstate->x3, SM_MODULUS); | ||
873 | comp = gcry_mpi_cmp(rab, bstate->pab); | ||
874 | |||
875 | /* Clean up everything allocated in this step */ | ||
876 | otrl_sm_msg_free(&msg3, SM_MSG3_LEN); | ||
877 | otrl_sm_msg_free(&msg4, SM_MSG4_LEN); | ||
878 | gcry_mpi_release(rab); | ||
879 | gcry_mpi_release(inv); | ||
880 | |||
881 | bstate->sm_prog_state = comp ? OTRL_SMP_PROG_FAILED : | ||
882 | OTRL_SMP_PROG_SUCCEEDED; | ||
883 | |||
884 | if (comp) | ||
885 | return gcry_error(GPG_ERR_INV_VALUE); | ||
886 | else | ||
887 | return gcry_error(GPG_ERR_NO_ERROR); | ||
888 | } | ||
889 | |||
890 | /* Receives the final SMP message, which was generated in otrl_sm_step. | ||
891 | * This method checks if Alice and Bob's secrets were the same. If | ||
892 | * so, it returns NO_ERROR. If the secrets differ, an INV_VALUE error is | ||
893 | * returned instead. */ | ||
894 | gcry_error_t otrl_sm_step5(OtrlSMAliceState *astate, const unsigned char* input, const int inputlen) | ||
895 | { | ||
896 | /* Read from input to find the mpis */ | ||
897 | int comp; | ||
898 | gcry_mpi_t rab; | ||
899 | gcry_mpi_t *msg4; | ||
900 | gcry_error_t err; | ||
901 | err = unserialize_mpi_array(&msg4, SM_MSG4_LEN, input, inputlen); | ||
902 | astate->sm_prog_state = OTRL_SMP_PROG_CHEATED; | ||
903 | |||
904 | if (err != gcry_error(GPG_ERR_NO_ERROR)) return err; | ||
905 | |||
906 | if (check_group_elem(msg4[0]) || check_expon(msg4[2])) { | ||
907 | return gcry_error(GPG_ERR_INV_VALUE); | ||
908 | } | ||
909 | |||
910 | /* Verify Bob's log equality proof */ | ||
911 | if (otrl_sm_check_equal_logs(msg4[1], msg4[2], msg4[0], astate, 8)) | ||
912 | return gcry_error(GPG_ERR_INV_VALUE); | ||
913 | |||
914 | /* Calculate Rab and verify that secrets match */ | ||
915 | rab = gcry_mpi_new(SM_MOD_LEN_BITS); | ||
916 | gcry_mpi_powm(rab, msg4[0], astate->x3, SM_MODULUS); | ||
917 | |||
918 | comp = gcry_mpi_cmp(rab, astate->pab); | ||
919 | gcry_mpi_release(rab); | ||
920 | otrl_sm_msg_free(&msg4, SM_MSG4_LEN); | ||
921 | |||
922 | astate->sm_prog_state = comp ? OTRL_SMP_PROG_FAILED : | ||
923 | OTRL_SMP_PROG_SUCCEEDED; | ||
924 | |||
925 | if (comp) | ||
926 | return gcry_error(GPG_ERR_INV_VALUE); | ||
927 | else | ||
928 | return gcry_error(GPG_ERR_NO_ERROR); | ||
929 | } | ||