aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/libotr/libotr-3.2.0/src/sm.c
diff options
context:
space:
mode:
authorJay Threeth2011-04-04 11:48:26 -0700
committerJay Threeth2011-04-04 11:48:26 -0700
commit3c9cc506f741b980565ff5b3b001cd8b6ee36b12 (patch)
treecb862c57b3d5f74177cde3bd962a53fc377166f6 /linden/indra/libotr/libotr-3.2.0/src/sm.c
parentbuild fixes, might build on linux now (diff)
downloadmeta-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-xlinden/indra/libotr/libotr-3.2.0/src/sm.c929
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
32static const int SM_MSG1_LEN = 6;
33static const int SM_MSG2_LEN = 11;
34static const int SM_MSG3_LEN = 8;
35static const int SM_MSG4_LEN = 3;
36
37/* The modulus p */
38static 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 */
48static const char* SM_ORDER_S = "0x"
49 "7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68"
50 "948127044533E63A0105DF531D89CD9128A5043CC71A026E"
51 "F7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122"
52 "F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6"
53 "F71C35FDAD44CFD2D74F9208BE258FF324943328F6722D9E"
54 "E1003E5C50B1DF82CC6D241B0E2AE9CD348B1FD47E9267AF"
55 "C1B2AE91EE51D6CB0E3179AB1042A95DCF6A9483B84B4B36"
56 "B3861AA7255E4C0278BA36046511B993FFFFFFFFFFFFFFFF";
57static const char *SM_GENERATOR_S = "0x02";
58static const int SM_MOD_LEN_BITS = 1536;
59static const int SM_MOD_LEN_BYTES = 192;
60
61static gcry_mpi_t SM_MODULUS = NULL;
62static gcry_mpi_t SM_GENERATOR = NULL;
63static gcry_mpi_t SM_ORDER = NULL;
64static 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 */
70void 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 */
84void 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 */
106void 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 */
128void 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 */
146void 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 */
169void 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 */
188void 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 */
202void 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 */
221void 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
232static 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 */
248static 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. */
299static 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 */
344static 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
368invval:
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 */
381static 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 */
391static 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 */
403static 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 */
420static 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 */
446static 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 */
478static 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 */
521static 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 */
546static 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 */
594gcry_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. */
634gcry_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 */
687gcry_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 */
741gcry_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. */
825gcry_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. */
894gcry_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}