~tdelaet/cimple/old-codebase

« back to all changes in this revision

Viewing changes to dependencies/PyECC/seccure/ecc.c

  • Committer: Thomas Delaet
  • Date: 2010-01-07 14:14:32 UTC
  • Revision ID: thomas@cole-20100107141432-yhker27v3pmn62uo
first phase of rewrite with focus on storage

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  seccure  -  Copyright 2009 B. Poettering
3
 
 *
4
 
 *  Maintained by R. Tyler Ballance <tyler@slide.com>
5
 
 *
6
 
 * This library is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU Lesser General Public
8
 
 * License as published by the Free Software Foundation; either
9
 
 * version 2.1 of the License, or (at your option) any later version.
10
 
 *
11
 
 * This library is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
 * Lesser General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this library; if not, write to the Free Software
18
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
 
 */
20
 
 
21
 
/* 
22
 
 *   SECCURE Elliptic Curve Crypto Utility for Reliable Encryption
23
 
 *
24
 
 * Current homepage: http://slideinc.github.com/pyecc
25
 
 * Original homepage: http://point-at-infinity.org/seccure/
26
 
 *
27
 
 *
28
 
 * seccure implements a selection of asymmetric algorithms based on  
29
 
 * elliptic curve cryptography (ECC). See the manpage or the project's  
30
 
 * homepage for further details.
31
 
 *
32
 
 * This code links against the GNU gcrypt library "libgcrypt" (which
33
 
 * is part of the GnuPG project). Use the included Makefile to build
34
 
 * the binary.
35
 
 * 
36
 
 * Report bugs to: http://github.com/rtyler/PyECC/issues
37
 
 */
38
 
 
39
 
 
40
 
#include <assert.h>
41
 
#include <gcrypt.h>
42
 
 
43
 
#include "ecc.h"
44
 
#include "numtheory.h"
45
 
 
46
 
/******************************************************************************/
47
 
 
48
 
/* Chapter 3.1.2 in the "Guide to Elliptic Curve Cryptography"                */
49
 
 
50
 
struct affine_point point_new(void)
51
 
{
52
 
  struct affine_point r;
53
 
  r.x = gcry_mpi_snew(0);
54
 
  r.y = gcry_mpi_snew(0);
55
 
  return r;
56
 
}
57
 
 
58
 
void point_release(struct affine_point *p)
59
 
{
60
 
  gcry_mpi_release(p->x);
61
 
  gcry_mpi_release(p->y);
62
 
  p->x = NULL;
63
 
  p->y = NULL;
64
 
}
65
 
 
66
 
void point_set(struct affine_point *p1, const struct affine_point *p2)
67
 
{
68
 
  gcry_mpi_set(p1->x, p2->x);
69
 
  gcry_mpi_set(p1->y, p2->y);
70
 
}
71
 
 
72
 
void point_load_zero(struct affine_point *p)
73
 
{
74
 
  gcry_mpi_set_ui(p->x, 0);
75
 
  gcry_mpi_set_ui(p->y, 0);
76
 
}
77
 
 
78
 
int point_is_zero(const struct affine_point *p)
79
 
{
80
 
  return ! gcry_mpi_cmp_ui(p->x, 0) && ! gcry_mpi_cmp_ui(p->y, 0);
81
 
}
82
 
 
83
 
int point_on_curve(const struct affine_point *p, const struct domain_params *dp)
84
 
{
85
 
  int res;
86
 
  if (! (res = point_is_zero(p))) {
87
 
    gcry_mpi_t h1, h2;
88
 
    h1 = gcry_mpi_snew(0);
89
 
    h2 = gcry_mpi_snew(0);
90
 
    gcry_mpi_mulm(h1, p->x, p->x, dp->m);
91
 
    gcry_mpi_addm(h1, h1, dp->a, dp->m);
92
 
    gcry_mpi_mulm(h1, h1, p->x, dp->m);
93
 
    gcry_mpi_addm(h1, h1, dp->b, dp->m);
94
 
    gcry_mpi_mulm(h2, p->y, p->y, dp->m);
95
 
    res = ! gcry_mpi_cmp(h1, h2);
96
 
    gcry_mpi_release(h1);
97
 
    gcry_mpi_release(h2);
98
 
  }
99
 
  return res;
100
 
}
101
 
 
102
 
int point_compress(const struct affine_point *p)
103
 
{
104
 
  return gcry_mpi_test_bit(p->y, 0);
105
 
}
106
 
 
107
 
int point_decompress(struct affine_point *p, const gcry_mpi_t x, int yflag, 
108
 
                     const struct domain_params *dp)
109
 
{
110
 
  gcry_mpi_t h, y;
111
 
  int res, rc;
112
 
  h = gcry_mpi_snew(0);
113
 
  y = gcry_mpi_snew(0);
114
 
  gcry_mpi_mulm(h, x, x, dp->m);
115
 
  gcry_mpi_addm(h, h, dp->a, dp->m);
116
 
  gcry_mpi_mulm(h, h, x, dp->m);
117
 
  gcry_mpi_addm(h, h, dp->b, dp->m);
118
 
  if ((res = mod_root(y, h, dp->m)))
119
 
    if ((res = (gcry_mpi_cmp_ui(y, 0) || ! yflag))) {
120
 
      p->x = gcry_mpi_snew(0);
121
 
      p->y = gcry_mpi_snew(0);
122
 
      gcry_mpi_set(p->x, x);
123
 
      if (gcry_mpi_test_bit(y, 0) == yflag)
124
 
        gcry_mpi_set(p->y, y);
125
 
      else
126
 
        gcry_mpi_sub(p->y, dp->m, y);
127
 
    rc = point_on_curve(p, dp);
128
 
    assert(rc);
129
 
    }
130
 
  gcry_mpi_release(h);
131
 
  gcry_mpi_release(y);
132
 
  return res;
133
 
}
134
 
 
135
 
void point_double(struct affine_point *p, const struct domain_params *dp)
136
 
{
137
 
  if (gcry_mpi_cmp_ui(p->y, 0)) {
138
 
    gcry_mpi_t t1, t2;
139
 
    t1 = gcry_mpi_snew(0);
140
 
    t2 = gcry_mpi_snew(0);
141
 
    gcry_mpi_mulm(t2, p->x, p->x, dp->m);
142
 
    gcry_mpi_addm(t1, t2, t2, dp->m);
143
 
    gcry_mpi_addm(t1, t1, t2, dp->m);
144
 
    gcry_mpi_addm(t1, t1, dp->a, dp->m);
145
 
    gcry_mpi_addm(t2, p->y, p->y, dp->m);
146
 
    gcry_mpi_invm(t2, t2, dp->m);
147
 
    gcry_mpi_mulm(t1, t1, t2, dp->m);
148
 
    gcry_mpi_mulm(t2, t1, t1, dp->m);
149
 
    gcry_mpi_subm(t2, t2, p->x, dp->m);
150
 
    gcry_mpi_subm(t2, t2, p->x, dp->m);
151
 
    gcry_mpi_subm(p->x, p->x, t2, dp->m);
152
 
    gcry_mpi_mulm(t1, t1, p->x, dp->m);
153
 
    gcry_mpi_subm(p->y, t1, p->y, dp->m);
154
 
    gcry_mpi_set(p->x, t2);
155
 
    gcry_mpi_release(t1);
156
 
    gcry_mpi_release(t2);
157
 
  }
158
 
  else
159
 
    gcry_mpi_set_ui(p->x, 0);
160
 
}
161
 
 
162
 
void point_add(struct affine_point *p1, const struct affine_point *p2,
163
 
               const struct domain_params *dp)
164
 
{
165
 
  if (! point_is_zero(p2)) {
166
 
    if (! point_is_zero(p1)) {
167
 
      if (! gcry_mpi_cmp(p1->x, p2->x)) {
168
 
        if (! gcry_mpi_cmp(p1->y, p2->y))
169
 
          point_double(p1, dp);
170
 
        else
171
 
          point_load_zero(p1);
172
 
      }
173
 
      else {
174
 
        gcry_mpi_t t;
175
 
        t = gcry_mpi_snew(0);
176
 
        gcry_mpi_subm(t, p1->y, p2->y, dp->m);
177
 
        gcry_mpi_subm(p1->y, p1->x, p2->x, dp->m);
178
 
        gcry_mpi_invm(p1->y, p1->y, dp->m);
179
 
        gcry_mpi_mulm(p1->y, t, p1->y, dp->m);
180
 
        gcry_mpi_mulm(t, p1->y, p1->y, dp->m);
181
 
        gcry_mpi_addm(p1->x, p1->x, p2->x, dp->m);
182
 
        gcry_mpi_subm(p1->x, t, p1->x, dp->m);
183
 
        gcry_mpi_subm(t, p2->x, p1->x, dp->m);
184
 
        gcry_mpi_mulm(p1->y, p1->y, t, dp->m);
185
 
        gcry_mpi_subm(p1->y, p1->y, p2->y, dp->m);
186
 
        gcry_mpi_release(t);
187
 
      }
188
 
    }
189
 
    else
190
 
      point_set(p1, p2);
191
 
  }
192
 
}
193
 
 
194
 
/******************************************************************************/
195
 
 
196
 
/* Chapter 3.2.2 in the "Guide to Elliptic Curve Cryptography"                */
197
 
 
198
 
struct jacobian_point jacobian_new(void)
199
 
{
200
 
  struct jacobian_point r;
201
 
  r.x = gcry_mpi_snew(0);
202
 
  r.y = gcry_mpi_snew(0);
203
 
  r.z = gcry_mpi_snew(0);
204
 
  return r;
205
 
}
206
 
 
207
 
void jacobian_release(struct jacobian_point *p)
208
 
{
209
 
  gcry_mpi_release(p->x);
210
 
  gcry_mpi_release(p->y);
211
 
  gcry_mpi_release(p->z);
212
 
}
213
 
 
214
 
void jacobian_load_affine(struct jacobian_point *p1,
215
 
                          const struct affine_point *p2)
216
 
{
217
 
  if (! point_is_zero(p2)) {
218
 
    gcry_mpi_set(p1->x, p2->x);
219
 
    gcry_mpi_set(p1->y, p2->y);
220
 
    gcry_mpi_set_ui(p1->z, 1);
221
 
  }
222
 
  else
223
 
    gcry_mpi_set_ui(p1->z, 0);
224
 
}
225
 
 
226
 
void jacobian_load_zero(struct jacobian_point *p)
227
 
{
228
 
  gcry_mpi_set_ui(p->z, 0);
229
 
}
230
 
 
231
 
int jacobian_is_zero(const struct jacobian_point *p)
232
 
{
233
 
  return ! gcry_mpi_cmp_ui(p->z, 0);
234
 
}
235
 
 
236
 
void jacobian_double(struct jacobian_point *p, const struct domain_params *dp)
237
 
{
238
 
  if (gcry_mpi_cmp_ui(p->z, 0)) {
239
 
    if (gcry_mpi_cmp_ui(p->y, 0)) {
240
 
      gcry_mpi_t t1, t2;
241
 
      t1 = gcry_mpi_snew(0);
242
 
      t2 = gcry_mpi_snew(0);
243
 
      gcry_mpi_mulm(t1, p->x, p->x, dp->m);
244
 
      gcry_mpi_addm(t2, t1, t1, dp->m);
245
 
      gcry_mpi_addm(t2, t2, t1, dp->m);
246
 
      gcry_mpi_mulm(t1, p->z, p->z, dp->m);
247
 
      gcry_mpi_mulm(t1, t1, t1, dp->m);
248
 
      gcry_mpi_mulm(t1, t1, dp->a, dp->m);
249
 
      gcry_mpi_addm(t1, t1, t2, dp->m);
250
 
      gcry_mpi_mulm(p->z, p->z, p->y, dp->m);
251
 
      gcry_mpi_addm(p->z, p->z, p->z, dp->m);
252
 
      gcry_mpi_mulm(p->y, p->y, p->y, dp->m);
253
 
      gcry_mpi_addm(p->y, p->y, p->y, dp->m);
254
 
      gcry_mpi_mulm(t2, p->x, p->y, dp->m);
255
 
      gcry_mpi_addm(t2, t2, t2, dp->m);
256
 
      gcry_mpi_mulm(p->x, t1, t1, dp->m);
257
 
      gcry_mpi_subm(p->x, p->x, t2, dp->m);
258
 
      gcry_mpi_subm(p->x, p->x, t2, dp->m);
259
 
      gcry_mpi_subm(t2, t2, p->x, dp->m);
260
 
      gcry_mpi_mulm(t1, t1, t2, dp->m);
261
 
      gcry_mpi_mulm(t2, p->y, p->y, dp->m);
262
 
      gcry_mpi_addm(t2, t2, t2, dp->m);
263
 
      gcry_mpi_subm(p->y, t1, t2, dp->m);
264
 
      gcry_mpi_release(t1);
265
 
      gcry_mpi_release(t2);
266
 
    }
267
 
    else
268
 
      gcry_mpi_set_ui(p->z, 0);
269
 
  }
270
 
}
271
 
 
272
 
void jacobian_affine_point_add(struct jacobian_point *p1, 
273
 
                               const struct affine_point *p2,
274
 
                               const struct domain_params *dp)
275
 
{
276
 
  if (! point_is_zero(p2)) {
277
 
    if (gcry_mpi_cmp_ui(p1->z, 0)) {
278
 
      gcry_mpi_t t1, t2, t3;
279
 
      t1 = gcry_mpi_snew(0);
280
 
      t2 = gcry_mpi_snew(0);
281
 
      gcry_mpi_mulm(t1, p1->z, p1->z, dp->m);
282
 
      gcry_mpi_mulm(t2, t1, p2->x, dp->m);
283
 
      gcry_mpi_mulm(t1, t1, p1->z, dp->m);
284
 
      gcry_mpi_mulm(t1, t1, p2->y, dp->m);
285
 
      if (! gcry_mpi_cmp(p1->x, t2)) {
286
 
        if (! gcry_mpi_cmp(p1->y, t1))
287
 
          jacobian_double(p1, dp);
288
 
        else
289
 
          jacobian_load_zero(p1);
290
 
      }
291
 
      else {
292
 
        t3 = gcry_mpi_snew(0);
293
 
        gcry_mpi_subm(p1->x, p1->x, t2, dp->m);
294
 
        gcry_mpi_subm(p1->y, p1->y, t1, dp->m);
295
 
        gcry_mpi_mulm(p1->z, p1->z, p1->x, dp->m);
296
 
        gcry_mpi_mulm(t3, p1->x, p1->x, dp->m);
297
 
        gcry_mpi_mulm(t2, t2, t3, dp->m);
298
 
        gcry_mpi_mulm(t3, t3, p1->x, dp->m);
299
 
        gcry_mpi_mulm(t1, t1, t3, dp->m);
300
 
        gcry_mpi_mulm(p1->x, p1->y, p1->y, dp->m);
301
 
        gcry_mpi_subm(p1->x, p1->x, t3, dp->m);
302
 
        gcry_mpi_subm(p1->x, p1->x, t2, dp->m);
303
 
        gcry_mpi_subm(p1->x, p1->x, t2, dp->m);
304
 
        gcry_mpi_subm(t2, t2, p1->x, dp->m);
305
 
        gcry_mpi_mulm(p1->y, p1->y, t2, dp->m);
306
 
        gcry_mpi_subm(p1->y, p1->y, t1, dp->m);
307
 
        gcry_mpi_release(t3);
308
 
      }
309
 
      gcry_mpi_release(t1);
310
 
      gcry_mpi_release(t2);
311
 
    }
312
 
    else
313
 
      jacobian_load_affine(p1, p2);
314
 
  }
315
 
}
316
 
 
317
 
struct affine_point jacobian_to_affine(const struct jacobian_point *p,
318
 
                                       const struct domain_params *dp)
319
 
{
320
 
  struct affine_point r = point_new();
321
 
  if (gcry_mpi_cmp_ui(p->z, 0)) {
322
 
    gcry_mpi_t h;
323
 
    h = gcry_mpi_snew(0);
324
 
    gcry_mpi_invm(h, p->z, dp->m);
325
 
    gcry_mpi_mulm(r.y, h, h, dp->m);
326
 
    gcry_mpi_mulm(r.x, p->x, r.y, dp->m);
327
 
    gcry_mpi_mulm(r.y, r.y, h, dp->m);
328
 
    gcry_mpi_mulm(r.y, r.y, p->y, dp->m);
329
 
    gcry_mpi_release(h);
330
 
  }
331
 
  return r;
332
 
}
333
 
 
334
 
/******************************************************************************/
335
 
 
336
 
/* Algorithm 3.27 in the "Guide to Elliptic Curve Cryptography"               */
337
 
 
338
 
#if 0
339
 
 
340
 
struct affine_point pointmul(const struct affine_point *p,
341
 
                             const gcry_mpi_t exp, 
342
 
                             const struct domain_params *dp)
343
 
{
344
 
  struct affine_point r = point_new();
345
 
  int n = gcry_mpi_get_nbits(exp);
346
 
  while (n) {
347
 
    point_double(&r, dp);
348
 
    if (gcry_mpi_test_bit(exp, --n))
349
 
      point_add(&r, p, dp);
350
 
  }
351
 
  assert(point_on_curve(&r, dp));
352
 
  return r;
353
 
}
354
 
 
355
 
#else
356
 
 
357
 
struct affine_point pointmul(const struct affine_point *p,
358
 
                             const gcry_mpi_t exp, 
359
 
                             const struct domain_params *dp)
360
 
{
361
 
  struct jacobian_point r = jacobian_new();
362
 
  struct affine_point R;
363
 
  int n = gcry_mpi_get_nbits(exp);
364
 
  int rc = 0;
365
 
  while (n) {
366
 
    jacobian_double(&r, dp);
367
 
    if (gcry_mpi_test_bit(exp, --n))
368
 
      jacobian_affine_point_add(&r, p, dp);
369
 
  }
370
 
  R = jacobian_to_affine(&r, dp);
371
 
  jacobian_release(&r);
372
 
  rc = point_on_curve(&R, dp);
373
 
  assert(rc);
374
 
  return R;
375
 
}
376
 
 
377
 
#endif
378
 
 
379
 
/******************************************************************************/
380
 
 
381
 
/* Algorithm 4.26 in the "Guide to Elliptic Curve Cryptography"               */
382
 
int embedded_key_validation(const struct affine_point *p,
383
 
                            const struct domain_params *dp)
384
 
{
385
 
  if (gcry_mpi_cmp_ui(p->x, 0) < 0 || gcry_mpi_cmp(p->x, dp->m) >= 0 ||
386
 
      gcry_mpi_cmp_ui(p->y, 0) < 0 || gcry_mpi_cmp(p->y, dp->m) >= 0)
387
 
    return 0;
388
 
  return ! point_is_zero(p) && point_on_curve(p, dp);
389
 
}
390
 
 
391
 
/* Algorithm 4.25 in the "Guide to Elliptic Curve Cryptography"               */
392
 
int full_key_validation(const struct affine_point *p,
393
 
                        const struct domain_params *dp)
394
 
{
395
 
  if (! embedded_key_validation(p, dp))
396
 
    return 0;
397
 
  if (dp->cofactor != 1) {
398
 
    struct affine_point bp;
399
 
    int res;
400
 
    bp = pointmul(p, dp->order, dp);
401
 
    res = point_is_zero(&bp);
402
 
    point_release(&bp);
403
 
    return res;
404
 
  }
405
 
  else
406
 
    return 1;
407
 
}