New code from Sergi Blanch i Torne.
[libgcrypt.git] / cipher / ecc.c
1 /* ecc.c  -  ECElGamal Public Key encryption & ECDSA signature algorithm
2  *      Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 /* This code is a based on the 
22  * Patch 0.1.6 for the gnupg 1.4.x branch
23  * as retrieved on 2007-03-21 from
24  * http://www.calcurco.cat/eccGnuPG/src/gnupg-1.4.6-ecc0.2.0beta1.diff.bz2
25  *
26  * Written by 
27  *  Sergi Blanch i Torne <d4372211 at alumnes.eup.udl.es>, 
28  *  Ramiro Moreno Chiral <ramiro at eup.udl.es>
29  * Maintainers
30  *  Sergi Blanch i Torne
31  *  Ramiro Moreno Chiral
32  *  Mikael Mylnikov (mmr)
33  */
34
35 /*
36  * This module are under development, it would not have to be used 
37  * in a production environments. It can have bugs!
38  * 
39  * Made work:
40  *  alex: found a bug over the passphrase.
41  *  mmr: signature bug found and solved (afine conversion).
42  *  mmr: found too many mistakes in the mathematical background transcription.
43  *  mmr: improve the mathematical performance.
44  *  mmr: solve ECElGamal IFP weakness.
45  *  more polite gen_k() and its calls.
46  *  mmr: extend the check_secret_key()
47  * In process:
48  *  genBigPoint(): Randomize the point generation.
49  *  improve te memory uses.
50  *  Separation between sign & encrypt keys to facility the subkeys creation.
51  *  read & reread the code in a bug search!
52  * To do:
53  *  2-isogeny: randomize the elliptic curves.
54  *  E(F_{2^m})
55  */
56
57 #include <config.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include "types.h"
62 #include "util.h"
63 #include "mpi.h"
64 #include "cipher.h"
65 #include "ecc.h"
66
67 //ECC over F_p; E(F_p)
68 //T=(p,a,b,G,n,h)
69 //         p:    big odd number
70 //         a,b:  curve generators
71 //         G:    Subgroup generator point
72 //         n:    big int, in G order
73 //         h:    cofactor
74 // y^2=x^3+ax+b --> (Y^2)Z=X^3+aX(Z^2)+b(Z^3)
75
76 //
77 //         Q=[d]G, 1<=d<=n-1
78
79 typedef struct {
80         MPI x_;
81         MPI y_;
82         MPI z_;
83 } point; //Point representation in projective coordinates.
84
85 typedef struct {
86         MPI p_;
87         MPI a_,b_;
88         //MPI Gx,Gy,Gz;
89         point G;
90         MPI n_;
91         //MPI h_; =1                    //!! We will need to change this value in 2-isogeny
92 } ellipticCurve;//doubtful name         //!!
93
94 typedef struct {
95         ellipticCurve E;
96         point Q;        /*Q=[d]G*/
97 } ECC_public_key;//Q
98
99 typedef struct {
100         ellipticCurve E;
101         point Q;        /*Q=[d]G*/
102         MPI d;
103 } ECC_secret_key;//d
104
105
106 static MPI gen_k( MPI p, int secure );
107
108 static void generateCurve(unsigned nbits, ellipticCurve *ECC_curve);//choice a curve of the rank
109
110 static void generateKey(ECC_secret_key *sk, unsigned nbits , MPI **factors );//Generate de cryptosystem setup.
111 static void testKeys( ECC_secret_key *sk, unsigned nbits );//verify correct skey
112 static int check_secret_key( ECC_secret_key *sk );//check the validity of the value
113 static void doEncrypt(MPI input, ECC_public_key *pkey, point *R, MPI c);
114 static MPI decrypt(MPI output, ECC_secret_key *skey, point R, MPI c);
115 static void sign(MPI input, ECC_secret_key *skey, MPI *r, MPI *s);
116 static int verify(MPI input, ECC_public_key *pkey, MPI r, MPI s);
117
118 static int genBigPoint(MPI *prime, ellipticCurve *base, point *G, unsigned nbits);//return -1 if it isn't possible
119 static point genPoint(MPI prime, ellipticCurve base);//random point over an Elliptic curve
120 static MPI existSquareRoot(MPI integer, MPI modulus);//return true or false
121 static void Lucas(MPI n, MPI p_, MPI q_, MPI k, MPI V_n, MPI Q_0);
122
123 static int PointAtInfinity(point Query);//return true(1), false(0), or error(-1) for an invalid point
124
125 static void escalarMult(MPI escalar, point *P, point *R, ellipticCurve *base);//return R=escalarP
126 static void sumPoints(point *P0, point *P1, point *P2, ellipticCurve *base);//P2=P0+P1
127 static void duplicatePoint(point *P, point *R, ellipticCurve *base);//R=2P
128 static void invertPoint(point *P, ellipticCurve *base);//P=-P
129
130 static point point_copy(point P);
131 static void point_free(point *P);
132 static int point_affine(point *P, MPI x, MPI y, ellipticCurve *base);//turn an projective coordinate to affine, return 0 (1 if error).
133 static ellipticCurve curve_copy(ellipticCurve E);
134 static void curve_free(ellipticCurve *E);
135 static MPI gen_bit();
136 static MPI gen_y_2(MPI x, ellipticCurve *base);
137
138 //Function for IFP ECElGamal Weakness.
139 static void sha256_hashing(MPI input, MPI *output);//Compute a hash
140 static void aes256_encrypting(MPI key, MPI input, MPI *output);//Encrypt simmetricaly
141 static void aes256_decrypting(MPI key, MPI input, MPI *output);//Decrypt simmetricaly
142
143 static void (*progress_cb) ( void *, int );
144 static void *progress_cb_data;
145
146 static void
147 progress( int c )
148 {
149     if ( progress_cb )
150         progress_cb ( progress_cb_data, c );
151     else
152         fputc( c, stderr );
153 }
154
155 /****************
156  * At the begging was the same than elgamal.c
157  * but mmr improve it.
158  * Generate a random secret scalar k with an order of p
159  * Moreover it do NOT use Wiener's table.
160  */
161 static MPI
162 gen_k( MPI p, int secure ){
163
164     MPI k = mpi_alloc_secure( 0 );
165     unsigned int nbits = mpi_get_nbits(p);
166     unsigned int nbytes;
167
168     nbytes = (nbits+7)/8;
169     if( DBG_CIPHER )
170         log_debug("choosing a random k of %u bits\n", nbits);
171     char *c = get_random_bits( nbits, secure, 1 );
172     mpi_set_buffer( k, c, nbytes, 0 );
173     xfree(c);
174     mpi_fdiv_r(k,k, p);//simple module: k=k (mod p)
175     if( DBG_CIPHER )
176         progress('\n');
177
178     return k;
179 }
180
181 /****************
182  * Generate de cryptosystem setup.
183  * At this time it fix the values to the ones which NIST recomend.
184  * The subgroup generator point is in another function: 'genBigPoint'.
185  */
186 static void
187 generateCurve(unsigned nbits, ellipticCurve *ECC_curve){
188
189         ellipticCurve E;
190         //point *G;
191
192         if( nbits == 192 ){//NIST P-192
193                 E.p_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
194                 if (mpi_fromstr(E.p_,\
195                         "0xfffffffffffffffffffffffffffffffeffffffffffffffff"))
196                         log_fatal("ECC operation: Curve assigments failed(p)\n");
197                 else    ECC_curve->p_ = mpi_copy(E.p_);
198                 E.a_ =mpi_alloc((2/(BYTES_PER_MPI_LIMB*8))+1);
199                 if (mpi_fromstr(E.a_,\
200                         "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"))//"-0x3"))
201                         log_fatal("ECC operation: Curve assigments failed(a)\n");
202                 else    ECC_curve->a_ = mpi_copy(E.a_);
203                 E.b_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
204                 if (mpi_fromstr(E.b_,\
205                         "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"))
206                         log_fatal("ECC operation: Curve assigments failed(b)\n");
207                 else    ECC_curve->b_ = mpi_copy(E.b_);
208                 E.n_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
209                 if (mpi_fromstr(E.n_,\
210                         "0xffffffffffffffffffffffff99def836146bc9b1b4d22831"))
211                         log_fatal("ECC operation: Curve assigments failed(n)\n");
212                 else    ECC_curve->n_ = mpi_copy(E.n_);
213         }
214         else if( nbits == 224 ){//NIST P-224
215                 E.p_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
216                 if (mpi_fromstr(E.p_,\
217                         "0xffffffffffffffffffffffffffffffff000000000000000000000001"))
218                         log_fatal("ECC operation: Curve assigments failed(p)\n");
219                 else    ECC_curve->p_ = mpi_copy(E.p_);
220                 E.a_ =mpi_alloc((2/(BYTES_PER_MPI_LIMB*8))+1);
221                 if (mpi_fromstr(E.a_,\
222                         "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"))//"-0x3"))
223                         log_fatal("ECC operation: Curve assigments failed(a)\n");
224                 else    ECC_curve->a_ = mpi_copy(E.a_);
225                 E.b_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
226                 if (mpi_fromstr(E.b_,\
227                         "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4"))
228                         log_fatal("ECC operation: Curve assigments failed(b)\n");
229                 else    ECC_curve->b_ = mpi_copy(E.b_);
230                 E.n_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
231                 if (mpi_fromstr(E.n_,\
232                         "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d"))
233                         log_fatal("ECC operation: Curve assigments failed(n)\n");
234                 else    ECC_curve->n_ = mpi_copy(E.n_);
235         }
236         else if( nbits == 256 ){//NIST P-256
237                 E.p_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
238                 if (mpi_fromstr(E.p_,\
239                         "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff"))
240                         log_fatal("ECC operation: Curve assigments failed(p)\n");
241                 else    ECC_curve->p_ = mpi_copy(E.p_);
242                 E.a_ =mpi_alloc((2/(BYTES_PER_MPI_LIMB*8))+1);
243                 if (mpi_fromstr(E.a_,\
244                         "0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"))//"-0x3"))
245                         log_fatal("ECC operation: Curve assigments failed(a)\n");
246                 else    ECC_curve->a_ = mpi_copy(E.a_);
247                 E.b_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
248                 if (mpi_fromstr(E.b_,\
249                         "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b"))
250                         log_fatal("ECC operation: Curve assigments failed(b)\n");
251                 else    ECC_curve->b_ = mpi_copy(E.b_);
252                 E.n_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
253                 if (mpi_fromstr(E.n_,\
254                         "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"))
255                         log_fatal("ECC operation: Curve assigments failed(n)\n");
256                 else    ECC_curve->n_ = mpi_copy(E.n_);
257         }
258         else if( nbits == 384 ){//NIST P-384
259                 E.p_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
260                 if (mpi_fromstr(E.p_,\
261                         "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff"))
262                         log_fatal("ECC operation: Curve assigments failed(p)\n");
263                 else    ECC_curve->p_ = mpi_copy(E.p_);
264                 E.a_ =mpi_alloc((2/(BYTES_PER_MPI_LIMB*8))+1);
265                 if (mpi_fromstr(E.a_,\
266                         "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC"))//"-0x3"))
267                         log_fatal("ECC operation: Curve assigments failed(a)\n");
268                 else    ECC_curve->a_ = mpi_copy(E.a_);
269                 E.b_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
270                 if (mpi_fromstr(E.b_,\
271                         "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef"))
272                         log_fatal("ECC operation: Curve assigments failed(b)\n");
273                 else    ECC_curve->b_ = mpi_copy(E.b_);
274                 E.n_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
275                 if (mpi_fromstr(E.n_,\
276                         "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973"))
277                         log_fatal("ECC operation: Curve assigments failed(n)\n");
278                 else    ECC_curve->n_ = mpi_copy(E.n_);
279         }
280         else if( nbits == 521 ){//NIST P-521
281                 E.p_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
282                 if (mpi_fromstr(E.p_,\
283                         "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
284                         log_fatal("ECC operation: Curve assigments failed(p)\n");
285                 else    ECC_curve->p_ = mpi_copy(E.p_);
286                 E.a_ =mpi_alloc((2/(BYTES_PER_MPI_LIMB*8))+1);
287                 if (mpi_fromstr(E.a_,\
288                         "0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC"))//"-0x3"))
289                         log_fatal("ECC operation: Curve assigments failed(a)\n");
290                 else    ECC_curve->a_ = mpi_copy(E.a_);
291                 E.b_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
292                 if (mpi_fromstr(E.b_,\
293                         "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00"))
294                         log_fatal("ECC operation: Curve assigments failed(b)\n");
295                 else    ECC_curve->b_ = mpi_copy(E.b_);
296                 E.n_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
297                 if (mpi_fromstr(E.n_,\
298                         "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409"))
299                         log_fatal("ECC operation: Curve assigments failed(n)\n");
300                 else    ECC_curve->n_ = mpi_copy(E.n_);
301         }
302         else{
303                 log_fatal("ECC operation: Curve generation failed\n");
304         }
305         if( DBG_CIPHER ){
306                 progress('\n');
307                 log_mpidump("generation  p= ", ECC_curve->p_ );
308                 log_mpidump("generation  a= ", ECC_curve->a_ );
309                 log_mpidump("generation  b= ", ECC_curve->b_ );
310                 log_mpidump("generation  n= ", ECC_curve->n_ );
311         }
312         if ( genBigPoint(&ECC_curve->n_, ECC_curve, &ECC_curve->G, nbits) == -1){
313                 log_fatal("ECC operation: Point generation failed\n");
314         }
315         if( DBG_CIPHER ) {
316                 log_mpidump("generation  Gx= ", ECC_curve->G.x_ );
317                 log_mpidump("generation  Gy= ", ECC_curve->G.y_ );
318                 log_mpidump("generation  Gz= ", ECC_curve->G.z_ );
319                 log_info("Setup generated\n");
320                 progress('\n');
321         }
322 }
323
324 /****************
325  * Fisrt obtain the setup.
326  * Over the finite field randomize an scalar secret value, and calculat de public point.
327  * 
328  *        !! What about the **ret_factors !!  //!!
329  */
330 static void
331 generateKey(ECC_secret_key *sk, unsigned nbits , MPI **ret_factors ){
332
333         ellipticCurve E;
334         MPI d;
335         point Q,G;
336
337         generateCurve(nbits,&E);
338
339         d = mpi_alloc_secure(nbits/BITS_PER_MPI_LIMB);
340         if( DBG_CIPHER )
341                 log_debug("choosing a random x of size %u\n", nbits );
342         d = gen_k(E.n_,2);//generate_secret_prime(nbits);
343         G = point_copy(E.G);
344
345         escalarMult(d,&E.G,&Q,&E);
346
347         /* copy the stuff to the key structures */
348         sk->E.p_ = mpi_copy(E.p_);
349         sk->E.a_ = mpi_copy(E.a_);
350         sk->E.b_ = mpi_copy(E.b_);
351         sk->E.G = point_copy(E.G);
352         sk->E.n_ = mpi_copy(E.n_);
353         sk->Q = point_copy(Q);
354         sk->d = mpi_copy(d);
355
356         /* now we can test our keys (this should never fail!) */
357         testKeys( sk, nbits - 64 );
358
359         point_free(&Q);
360         mpi_free(d);
361         curve_free(&E);
362 }
363
364 /****************
365  * To verify correct skey it use a random information.
366  * First, encrypt and decrypt this dummy value, 
367  * test if the information is recuperated.
368  * Second, test with the sign and verify functions.
369  */
370 static void
371 testKeys( ECC_secret_key *sk, unsigned nbits ){
372
373         ECC_public_key pk;
374         MPI test = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
375         point R_;
376         MPI c = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
377         MPI out = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
378         MPI r = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
379         MPI s = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
380
381         if( DBG_CIPHER )log_info("Testing key.\n");
382
383         pk.E = curve_copy(sk->E);
384         pk.E.G = point_copy(sk->E.G);
385         pk.Q = point_copy(sk->Q);
386
387         /*mpi_set_bytes( test, nbits, get_random_byte, 0 );*/
388         {       char *p = get_random_bits( nbits, 0, 0 );
389                 mpi_set_buffer( test, p, (nbits+7)/8, 0 );
390                 xfree(p);
391         }
392
393         doEncrypt(test,&pk,&R_,c);
394
395         out = decrypt(out,sk,R_,c);
396
397         if( mpi_cmp( test, out ) )//test!=out
398                 log_fatal("ECELG operation: encrypt, decrypt failed\n");
399         if( DBG_CIPHER )log_info("ECELG operation: encrypt, decrypt ok.\n");
400
401         sign(test,sk,&r,&s);
402
403         if( !verify(test,&pk,r,s) ){
404                 log_fatal("ECDSA operation: sign, verify failed\n");}
405
406         if( DBG_CIPHER )log_info("ECDSA operation: sign, verify ok.\n");
407
408         mpi_free(s);
409         mpi_free(r);
410         mpi_free(out);
411         mpi_free(c);
412         point_free(&R_);
413         mpi_free(test);
414 }
415
416 /****************
417  * To check the validity of the value, recalculate the correspondence
418  * between the public value and de secret one.
419  */
420 static int
421 check_secret_key( ECC_secret_key *sk ){
422
423         point Q;
424         MPI y_2,y2 = mpi_alloc(0);
425
426         //?primarity test of 'p'
427         // (...) //!!
428         //G in E(F_p)
429         y_2 = gen_y_2(sk->E.G.x_,&sk->E);// y^2=x^3+a*x+b
430         mpi_mulm(y2,sk->E.G.y_,sk->E.G.y_,sk->E.p_);// y^2=y*y
431         if (mpi_cmp(y_2,y2)){
432                 if( DBG_CIPHER )log_info("Bad check: Point 'G' does not belong to curve 'E'!\n");
433                 return (1);
434         }
435         //G != PaI
436         if (PointAtInfinity(sk->E.G)){
437                 if( DBG_CIPHER )log_info("Bad check: 'G' cannot be Point at Infinity!\n");
438                 return (1);
439         }
440         //?primarity test of 'n'
441         // (...) //!!
442         //?(p-sqrt(p)) < n < (p+sqrt(p))
443         //?n!=p
444         //?(n^k) mod p !=1 for k=1 to 31 (from GOST) or k=1 to 50 (from MIRACL)
445         //Q=[n]G over E = PaI
446         escalarMult(sk->E.n_,&sk->E.G,&Q,&sk->E);
447         if (!PointAtInfinity(Q)){
448                 if( DBG_CIPHER )log_info("Bad check: 'E' is not curve of order 'n'!\n");
449                 return (1);
450         }
451         //pubkey cannot be PaI
452         if (PointAtInfinity(sk->Q)){
453                 if( DBG_CIPHER )log_info("Bad check: Q can not be a Point at Infinity!\n");
454                 return (1);
455         }
456         //pubkey = [d]G over E
457         escalarMult(sk->d,&sk->E.G,&Q,&sk->E);
458         if ((Q.x_ == sk->Q.x_) && (Q.y_ == sk->Q.y_) && (Q.z_ == sk->Q.z_)){
459                 if( DBG_CIPHER )log_info("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
460                 return (1);
461         }
462         point_free(&Q);
463         return (0);
464 }
465
466 /****************
467  * Encrypt a number and obtain and struct (R,c)
468  */
469 static void
470 doEncrypt(MPI input, ECC_public_key *pkey, point *R, MPI c){
471
472         MPI k,p,x,y;
473         point P,Q,G;
474         ellipticCurve E;
475
476         k = mpi_alloc(0);
477         p = mpi_copy(pkey->E.p_);
478         x = mpi_alloc(0);
479         y = mpi_alloc(0);
480         Q = point_copy(pkey->Q);
481         G = point_copy(pkey->E.G);
482         E = curve_copy(pkey->E);
483
484         k = gen_k( p, 1);//2nd parametre: how much security?
485         escalarMult(k,&Q,&P,&E);//P=[k]Q=[k]([d]G)
486         escalarMult(k,&G,R,&E);//R=[k]G
487         //IFP weakness//mpi_mul(c,input,Q.x_);//c=input*Q_x
488         //MMR Use affine conversion befor extract x-coordinate
489         if (point_affine(&P,x,y,&E)){//Q cannot turn to affine coordinate
490                 if( DBG_CIPHER ){log_info("Encrypting: Cannot turn to affine.\n");}
491         }
492         //MMR According to the standard P1363 we can not use x-coordinate directly.
493         // It is necessary to add hash-operation later. 
494         // As the maximal length of a key for the symmetric cipher is 256 bit it is possible to take hash-function SHA256.
495         sha256_hashing(x,&x);
496         aes256_encrypting(x,input,&c);
497
498         if( DBG_CIPHER ){log_debug("doEncrypt: end.\n");}
499 }
500
501 /****************
502  * Undo the ciphertext
503  */
504 static MPI
505 decrypt(MPI output, ECC_secret_key *skey, point R, MPI c){
506
507         MPI p,inv,x,y;
508         point P,Q;
509         ellipticCurve E;
510
511         p = mpi_copy(skey->E.p_);
512         inv = mpi_alloc(0);
513         x = mpi_alloc(0);
514         y = mpi_alloc(0);
515         Q = point_copy(skey->Q);
516         E = curve_copy(skey->E);
517
518         escalarMult(skey->d,&R,&P,&E);//P=[d]R
519         //That is like: mpi_fdiv_q(output,c,Q.x_);
520         //IFP weakness//mpi_invm(inv,Q.x_,p);//inv=Q{_x}^-1 (mod p)
521         //IFP weakness//mpi_mulm(output,c,inv,p);//output=c*inv (mod p)
522         //MMR Use affine conversion befor extract x-coordinate
523         if (point_affine(&P,x,y,&E)){//Q cannot turn to affine coordinate
524                 if( DBG_CIPHER ){log_info("Encrypting: Cannot turn to affine.\n");}
525         }
526         sha256_hashing(x,&x);
527         aes256_decrypting(x,c,&output);
528
529         if( DBG_CIPHER ){log_debug("decrypt: end.\n");}
530         return (output);
531 }
532
533 /****************
534  * Return the signature struct (r,s) from the message hash.
535  */
536 static void
537 sign(MPI input, ECC_secret_key *skey, MPI *r, MPI *s){
538
539         MPI k,i,dr,sum,k_1,x,y;
540         point G,I;
541         ellipticCurve E;
542
543         k = mpi_alloc(0); i = mpi_alloc(0); dr = mpi_alloc(0); sum = mpi_alloc(0); k_1 = mpi_alloc(0);
544         x = mpi_alloc(0); y = mpi_alloc(0);
545         G = point_copy(skey->E.G);
546         E = curve_copy(skey->E);
547         *r = mpi_alloc(0);
548         *s = mpi_alloc(0);
549
550         while (!mpi_cmp_ui(*s,0)){//s==0
551                 while (!mpi_cmp_ui(*r,0)){//r==0
552                         k = gen_k( E.p_, 1 );
553                         escalarMult(k,&G,&I,&E);//I=[k]G
554                         if (point_affine(&I,x,y,&E)){//I cannot turn to affine coordinate
555                               if( DBG_CIPHER ){log_info("Sign: Cannot turn to affine. Cannot complete sign.\n");}
556                         }
557                         i = mpi_copy(x);//i=I_x
558                         mpi_fdiv_r(*r,i,E.n_);//simple module: r=i (mod n)
559                 }
560                 mpi_mulm(dr,skey->d,*r,E.n_);//dr=d*r (mod n)
561                 mpi_addm(sum,input,dr,E.n_);//sum=hash+(d*r) (mod n)
562                 mpi_invm(k_1,k,E.n_);//k_1=k^(-1) (mod n)
563                 mpi_mulm(*s,k_1,sum,E.n_);// s=k^(-1)*(hash+(d*r)) (mod n)
564         }
565         if( DBG_CIPHER ){log_debug("Sign: end\n");}
566         mpi_free(y);
567         mpi_free(x);
568         mpi_free(k_1);
569         mpi_free(sum);
570         mpi_free(dr);
571         mpi_free(i);
572         mpi_free(k);
573 }
574
575 /****************
576  * Check if the struct (r,s) is for the hash value that it have.
577  */
578 static int
579 verify(MPI input, ECC_public_key *pkey, MPI r, MPI s){
580
581         MPI r_,s_,h,h1,h2,i,x,y;
582         point Q,Q1,Q2,G;
583         ellipticCurve E;
584
585         r_ = mpi_alloc(0); s_ = mpi_alloc(0); h = mpi_alloc(0); h1 = mpi_alloc(0); h2 = mpi_alloc(0); x = mpi_alloc(0); y = mpi_alloc(0);
586         G = point_copy(pkey->E.G);
587         E = curve_copy(pkey->E);
588         
589         mpi_fdiv_r(r_,r,pkey->E.n_);//simple module
590         mpi_fdiv_r(s_,s,pkey->E.n_);//simple module
591
592         //check if the input parameters are valid.
593         if ( mpi_cmp(r_,r) || mpi_cmp(s_,s)) {//r_!=r || s_!=s
594                 if( DBG_CIPHER ){log_info("Verification: No valid values.\n");}
595                 return 0; //not valid values.
596         }
597
598         mpi_invm(h,s,E.n_);//h=s^(-1) (mod n)
599         mpi_mulm(h1,input,h,E.n_);//h1=hash*s^(-1) (mod n)
600         escalarMult(h1,&G,&Q1,&E);//Q1=[hash*s^(-1)]G
601         mpi_mulm(h2,r,h,E.n_);//h2=r*s^(-1) (mod n)
602         escalarMult(h2,&pkey->Q,&Q2,&E);//Q2=[r*s^(-1)]Q
603         sumPoints(&Q1,&Q2,&Q,&E);//Q=([hash*s^(-1)]G)+([r*s^(-1)]Q)
604
605         if (PointAtInfinity(Q)){
606                 if( DBG_CIPHER ){log_info("Verification: Rejected.\n");}
607                 return 0;//rejected
608         }
609         if (point_affine(&Q,x,y,&E)){//Q cannot turn to affine coordinate
610                 if( DBG_CIPHER ){log_info("Verification: Cannot turn to affine. Rejected.\n");}
611                 return 0;//rejected
612         }
613         i = mpi_copy(x);//Give the x_coordinate
614         mpi_fdiv_r(i,i,E.n_);//simple module
615
616         if (!mpi_cmp(i,r)){//i==r => Return 0 (distance between them).
617                 if( DBG_CIPHER ){log_info("Verification: Accepted.\n");}
618                 return 1;//accepted
619         }
620         if( DBG_CIPHER ){log_info("Verification: Not verified.\n");}
621         return 0;
622 }
623
624 /****************
625  * A point of order 'n' is needed to generate a ciclic subgroup.
626  * Over this ciclic subgroup it's defined the ECDLP.
627  * Now it use a fix values from NIST FIPS PUB 186-2.
628  */
629 static int
630 genBigPoint(MPI *prime, ellipticCurve *base, point *G, unsigned nbits){
631   ///*estandard nist
632         if( nbits == 192 ){//NIST P-192
633                 G->x_ = mpi_alloc(mpi_get_nlimbs(base->n_));
634                 if (mpi_fromstr(G->x_,\
635                         "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012"))
636                         log_fatal("Generator operation: Point assigments failed(x)\n");
637                 G->y_ = mpi_alloc(mpi_get_nlimbs(base->n_));
638                 if (mpi_fromstr(G->y_,\
639                         "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"))
640                         log_fatal("Generator operation: Point assigments failed(y)\n");
641                 G->z_ = mpi_alloc_set_ui(1);
642         }
643         else if( nbits == 224 ){//NIST P-224
644                 G->x_ = mpi_alloc(mpi_get_nlimbs(base->n_));
645                 if (mpi_fromstr(G->x_,\
646                         "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"))
647                         log_fatal("Generator operation: Point assigments failed(x)\n");
648                 G->y_ = mpi_alloc(mpi_get_nlimbs(base->n_));
649                 if (mpi_fromstr(G->y_,\
650                         "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"))
651                         log_fatal("Generator operation: Point assigments failed(y)\n");
652                 G->z_ = mpi_alloc_set_ui(1);
653         }
654         else if( nbits == 256 ){//NIST P-256
655                 G->x_ = mpi_alloc(mpi_get_nlimbs(base->n_));
656                 if (mpi_fromstr(G->x_,\
657                         "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296"))
658                         log_fatal("Generator operation: Point assigments failed(x)\n");
659                 G->y_ = mpi_alloc(mpi_get_nlimbs(base->n_));
660                 if (mpi_fromstr(G->y_,\
661                         "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"))
662                         log_fatal("Generator operation: Point assigments failed(y)\n");
663                 G->z_ = mpi_alloc_set_ui(1);
664         }
665         else if( nbits == 384 ){//NIST P-384
666                 G->x_ = mpi_alloc(mpi_get_nlimbs(base->n_));
667                 if (mpi_fromstr(G->x_,\
668                         "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7"))
669                         log_fatal("Generator operation: Point assigments failed(x)\n");
670                 G->y_ = mpi_alloc(mpi_get_nlimbs(base->n_));
671                 if (mpi_fromstr(G->y_,\
672                         "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f"))
673                         log_fatal("Generator operation: Point assigments failed(y)\n");
674                 G->z_ = mpi_alloc_set_ui(1);
675         }
676         else if( nbits == 521 ){//NIST P-521
677                 G->x_ = mpi_alloc(mpi_get_nlimbs(base->n_));
678                 if (mpi_fromstr(G->x_,\
679                         "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66"))
680                         log_fatal("Generator operation: Point assigments failed(x)\n");
681                 G->y_ = mpi_alloc(mpi_get_nlimbs(base->n_));
682                 if (mpi_fromstr(G->y_,\
683                         "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"))
684                         log_fatal("Generator operation: Point assigments failed(y)\n");
685                 G->z_ = mpi_alloc_set_ui(1);
686         }
687   //end Estandard nist
688   /*Randomize G
689         unsigned int i=0;
690         MPI one;
691         point Big, P;
692
693         one = mpi_alloc_set_ui(1);
694         G->x_ = mpi_alloc(mpi_get_nlimbs(*prime));
695         G->y_ = mpi_alloc(mpi_get_nlimbs(*prime));
696         G->z_ = mpi_alloc(mpi_get_nlimbs(*prime));
697
698         if( DBG_MPI )log_info("Generating a Big point.\n");
699         do{
700                 do{
701                         *P = genPoint(*prime,*base);
702                 }while(PointAtInfinity(*P));//A random point in the curve that it's not PaI
703                 escalarMult(base.h,&P,&G,&base);//cofactor (1 o 2), could be improved
704         }while(PointAtInfinity(G));
705         if( DBG_MPI )log_info("Big point generated.\n");
706         if( DBG_MPI ){
707                 log_mpidump("Gx=",G->x_);log_mpidump("Gy=",G->y_);log_mpidump("Gz=",G->z_);
708         }
709         return 0;
710   *///end aleatoritzar G
711         return 0;
712 }
713
714 /****************
715  * Generate a random point over an Elliptic curve 
716  * is the first step to find a random ciclic subgroup
717  * generator.
718  *
719  *        !! At this moment it isn't used !!  //!!
720  */
721 static point
722 genPoint(MPI prime, ellipticCurve base){
723
724         unsigned int i=0;
725         MPI x,y_2,y;
726         MPI one, one_neg,bit;
727         point P;
728
729         x = mpi_alloc(mpi_get_nlimbs(base.p_));
730         y_2 = mpi_alloc(mpi_get_nlimbs(base.p_));
731         y = mpi_alloc(mpi_get_nlimbs(base.p_));
732         one = mpi_alloc_set_ui(1);
733         one_neg = mpi_alloc(mpi_get_nlimbs(one));
734         mpi_invm(one_neg,one,base.p_);
735
736         if( DBG_MPI )log_info("Generating a normal point.\n");
737         do{
738                 x = gen_k(base.p_,1);//generate_public_prime(mpi_get_nlimbs(base.n_)*BITS_PER_MPI_LIMB);
739                 do{
740                         y_2 = gen_y_2(x,&base);//x^3+ax+b (mod p)
741                         mpi_add_ui(x, x, 1);
742                         i++;
743                 }while( !mpi_cmp_ui(y_2,0) && i<0xf);//Try to find a valid value until 16 iterations.
744                 i=0;
745                 y = existSquareRoot(y_2,base.p_);
746         }while( !mpi_cmp_ui(y,0));//Repeat until a valid coordinate is found.
747         bit = gen_bit();//generate one bit
748         if (mpi_cmp_ui(bit,1)){//choose the y coordinate
749                 mpi_invm(y, y, base.p_);//mpi_powm(y, y, one_neg,base.p_);
750         }
751         if( DBG_MPI )log_info("Normal point generated.\n");
752
753         P.x_ = mpi_copy(x);
754         P.y_ = mpi_copy(y);
755         P.z_ = mpi_copy(one);
756
757         mpi_free(bit);
758         mpi_free(one_neg);
759         mpi_free(one);
760         mpi_free(y);
761         mpi_free(y_2);
762         mpi_free(x);
763
764         return(P);
765 }
766
767 /****************
768  * Find, if it exist, the square root of one integer module a big prime.
769  * Return the square root or 0 if it is not found.
770  */
771 static MPI
772 existSquareRoot(MPI integer, MPI modulus){
773
774         unsigned long int i=0;
775         MPI one,two,three,four,five,eight;
776         MPI k,r,z,k1;
777         MPI t1,t2,t3,t4;
778
779         one = mpi_alloc_set_ui(1);
780         two = mpi_alloc_set_ui(2);
781         three = mpi_alloc_set_ui(3);
782         four = mpi_alloc_set_ui(4);
783         five = mpi_alloc_set_ui(5);
784         eight = mpi_alloc_set_ui(8);
785         k = mpi_alloc(mpi_get_nlimbs(modulus));
786         r = mpi_alloc(mpi_get_nlimbs(modulus));
787         z = mpi_alloc(mpi_get_nlimbs(modulus));
788         k1 = mpi_alloc(mpi_get_nlimbs(modulus));
789         t1 = mpi_alloc(mpi_get_nlimbs(modulus));
790         t2 = mpi_alloc(mpi_get_nlimbs(modulus));
791         t3 = mpi_alloc(mpi_get_nlimbs(modulus));
792         t4 = mpi_alloc(mpi_get_nlimbs(modulus));
793
794         if( DBG_MPI )log_mpidump("?exist Square Root of ",integer);
795
796         mpi_fdiv_qr(k,r,modulus,four);
797         if (mpi_cmp(r,three)){//p=3 (mod 4)
798                 mpi_addm(k1,k,one,modulus);
799                 mpi_powm(z,integer,k1,modulus);
800                 if( DBG_MPI ){log_mpidump("z=",z);}
801                 return z;//value found
802         }
803         mpi_fdiv_qr(k,r,modulus,eight);
804         if (mpi_cmp(r,five)){//p=5 (mod 8)
805                 mpi_mulm(t1,two,integer,modulus);
806                 mpi_powm(t2,t1,k,modulus);
807                 mpi_powm(t2,t2,two,modulus);
808                 mpi_mulm(t2,t1,t2,modulus);
809                 mpi_mulm(t3,integer,t1,modulus);
810                 mpi_subm(t4,t2,one,modulus);
811                 mpi_mulm(z,t3,t4,modulus);
812                 if( DBG_MPI ){log_mpidump("z=",z);}
813                 return z;//value found
814         }
815         if (mpi_cmp(r,one)){//p=1 (mod 8)
816                 while(i<0xFF){//while not find z after 256 iterations*/
817                         if( DBG_MPI )log_info("Square root bucle.\n");
818                         t1 = mpi_copy(integer);
819                         t2 = gen_k(modulus,0);
820                         mpi_add_ui(t3,modulus,1);//t3=p+1
821                         mpi_rshift(t3,t3,1);//t3=t3/2
822                         Lucas(t1,t2,t3,modulus,t4,t3);//t4=V_k
823                         mpi_rshift(z,t4,1);//z=V/2
824                         mpi_sub_ui(t3,modulus,1);//t3=p-1
825                         mpi_rshift(t4,t3,2);//t4=t3/2
826                         Lucas(t1,t2,t4,modulus,t4,t1);//t1=Q_0
827                         mpi_powm(t2,z,two,modulus);//t2=z^2
828                         if (mpi_cmp(t1,integer)){
829                                 if( DBG_MPI ){log_mpidump("z=",z);}
830                                 return z;//value found
831                         }
832                         if (t4>mpi_alloc_set_ui(1) && t4<t3){
833                                 if( DBG_MPI )log_info("Rejected.\n");
834                                 return (0);             //NULL
835                         }
836                         if( DBG_MPI )log_info("Another loop.\n");
837                 }
838         }
839         if( DBG_MPI )log_info("iterations limit.\n");
840         return (0);//because this algorithm not always finish.
841 }
842
843 /****************
844  * Formal definition:
845  * V_0=2;V_1=p
846  * V_k=(p*V_(k-1))-(q*V_(k-2)) for k>=2
847  */
848 static void
849 Lucas(MPI n, MPI p_, MPI q_, MPI k, MPI V_n, MPI Q_0){
850
851         MPI v0,v1,q0,q1;
852         MPI t1,t2;
853         unsigned int r,i;
854
855         v0 = mpi_alloc_set_ui(2);
856         v1 = mpi_copy(p_);
857         q0 = mpi_alloc_set_ui(1);
858         q1 = mpi_alloc_set_ui(1);
859         t1 = mpi_alloc_set_ui(0);
860         t2 = mpi_alloc_set_ui(0);
861
862         if( DBG_MPI ){log_info("Generating lucas sequence.\n");log_mpidump("k=",k);}
863
864         r = mpi_get_nbits(k)-1;
865         i = 0;
866         while (mpi_test_bit(k,i) != 1){        //search the first bit with value '1'
867                 i++;
868         }
869         while (i<r){
870                 if( DBG_MPI ){
871                         log_info("Lucas sequence bucle.\n");
872                         log_mpidump("i=",mpi_alloc_set_ui(i));
873                         log_mpidump("r=",mpi_alloc_set_ui(r));
874                 }
875                 mpi_mulm(q0,q0,q1,n);
876                 if (mpi_test_bit(k,i) == 1){
877                         mpi_mulm(q1,q0,q_,n);
878                         mpi_mul(t1,v0,v1);
879                         mpi_mul(t2,p_,q0);
880                         mpi_subm(v0,t1,t2,n);
881                         mpi_powm(t1,v1,mpi_alloc_set_ui(2),n);
882                         mpi_mul(t2,mpi_alloc_set_ui(2),q1);
883                         mpi_subm(v1,t1,t2,n);
884                 }
885                 else{
886                         q1 = mpi_copy(q0);
887                         mpi_mul(t1,v0,v1);
888                         mpi_mul(t2,p_,q0);
889                         mpi_subm(v1,t1,t2,n);
890                         mpi_powm(t1,v0,mpi_alloc_set_ui(2),n);
891                         mpi_mul(t2,mpi_alloc_set_ui(2),q0);
892                         mpi_subm(v0,t1,t2,n);
893                 }
894                 i++;
895         }
896         V_n = mpi_copy(v0);
897         Q_0 = mpi_copy(q0);
898         if( DBG_MPI ){
899                 log_info("Lucas sequence generated.\n");
900                 log_mpidump("V_n=",V_n);
901                 log_mpidump("Q_0=",Q_0);
902         }
903 }
904
905 /****************
906  * The point at infinity is needed to make 
907  * a group structure to the elliptic curve.
908  * Know if one point is it, is needed so 
909  * much times in this code.
910  */
911 static int
912 PointAtInfinity(point Query){
913
914         if( DBG_MPI ){log_info("?is a Point at Infinity.\n");}
915
916         if (!mpi_cmp_ui(Query.z_,0)){//Z=0
917                if (/*mpi_cmp_ui(Query.x_,0) && */mpi_cmp_ui(Query.y_,0)){//X & Y!=0 & Z=0
918                         if( DBG_MPI )log_info("True:It is a Point at Infinite.\n");
919                         return (1); //true
920                 }
921                 if( DBG_MPI )log_info("Error:It isn't an elliptic curve valid point.\n");
922                 return (-1); //
923         }
924         if( DBG_MPI ){log_info("False:It isn't a Point at Infinity.\n");}
925         return (0); //it is a valid curve point, but it isn't the point at infinity
926 }
927
928 /****************
929  * The modular power used without EC, 
930  * is this function over EC.
931  */
932 static void
933 escalarMult(MPI escalar, point *P, point *R, ellipticCurve *base){
934
935         MPI one,two,three;
936         MPI p;
937         MPI xx,yy,zz,x1,y1,z1,z2,z3,k,h;//it could use less memory!!!!
938         unsigned int i,loops;
939         point P1,P2,P1_;
940
941         x1 = mpi_alloc(mpi_get_nlimbs(P->x_));
942         y1 = mpi_alloc(mpi_get_nlimbs(P->y_));
943         z2 = mpi_alloc(mpi_get_nlimbs(P->z_));
944         z3 = mpi_alloc(mpi_get_nlimbs(P->z_));
945         h = mpi_alloc(mpi_get_nlimbs(P->z_));
946
947         if( DBG_MPI )log_info("Calculating an scalar Multiple.\n");
948
949         one = mpi_alloc_set_ui(1);
950         two = mpi_alloc_set_ui(2);
951         three = mpi_alloc_set_ui(3);
952         p = mpi_copy(base->p_);
953
954         if ( !mpi_cmp_ui(escalar,0) || mpi_cmp_ui(P->z_,0)){//n=0 | Z=0 => [1:1:0]
955                 R->x_ = mpi_copy(one);
956                 R->y_ = mpi_copy(one);
957                 R->z_ = mpi_alloc(0);
958         }
959         xx = mpi_copy(P->x_);
960         zz = mpi_copy(P->z_);
961         z1 = mpi_copy(one);
962         if (mpi_is_neg(escalar)){//(-n)P=n(-P)
963                 escalar->sign = 0;//+n
964                 k = mpi_copy(escalar);
965                 yy = mpi_copy(P->y_);//-P
966                 mpi_invm(yy,yy,p);
967         }
968         else {
969                 k = mpi_copy(escalar);
970                 yy = mpi_copy(P->y_);
971         }
972         if (!mpi_cmp(zz,one)){//zz==1
973                 x1 = mpi_copy(xx);
974                 y1 = mpi_copy(yy);
975         }
976         else {
977                 mpi_mulm(z2,zz,zz,p);//z^2
978                 mpi_mulm(z3,zz,z2,p);//z^3
979                 mpi_invm(z2,z2,p);//1/Z^2
980                 mpi_mulm(x1,xx,z2,p);//xx/z^2
981                 mpi_invm(z3,z3,p);//1/z^3
982                 mpi_mulm(y1,yy,z3,p);//yy/z^3
983         }
984         mpi_mul(h,three,k);//h=3k
985         loops = mpi_get_nbits(h);
986         i=loops-2; // i = l-1 = loops-2
987         R->x_ = mpi_copy(xx);
988         R->y_ = mpi_copy(yy);
989         R->z_ = mpi_copy(zz);
990         P1.x_ = mpi_copy(x1);
991         P1.y_ = mpi_copy(y1);
992         P1.z_ = mpi_copy(z1);
993         while(i>0){ // A.10.9. step 11  i from l-1 downto 1
994                 duplicatePoint(R,R,base);
995                 if ( mpi_test_bit(h,i) == 1 && mpi_test_bit(k,i) == 0){//h_i=1 & k_i=0
996                         P2 = point_copy(*R);
997                         sumPoints(&P2,&P1,R,base);//R=P2+P1 over the base elliptic curve
998                 }
999                 if ( mpi_test_bit(h,i) == 0 && mpi_test_bit(k,i) == 1){//h_i=0 & k_i=1
1000                         P2 = point_copy(*R);
1001                         P1_ = point_copy(P1);
1002                         invertPoint(&P1_,base);
1003                         sumPoints(&P2,&P1_,R,base);//R=P2+P1_ over the base elliptic curve
1004                 }
1005                 i--;
1006         }
1007         if( DBG_MPI )log_info("Scalar Multiple calculated.\n");
1008
1009         point_free(&P1);
1010         point_free(&P2);
1011         point_free(&P1_);
1012         mpi_free(h);
1013         mpi_free(k);
1014         mpi_free(z3);
1015         mpi_free(z2);
1016         mpi_free(z1);
1017         mpi_free(y1);
1018         mpi_free(x1);
1019         mpi_free(zz);
1020         mpi_free(yy);
1021         mpi_free(xx);
1022         mpi_free(p);
1023         mpi_free(three);
1024         mpi_free(two);
1025         mpi_free(one);
1026 }
1027
1028 /****************
1029  * Point addition is the group operation.
1030  */
1031 static void
1032 sumPoints(point *P0, point *P1, point *P2, ellipticCurve *base){
1033
1034         MPI one,two;
1035         MPI p;
1036         MPI t1,t2,t3,t4,t5,t6,t7;
1037
1038         one = mpi_alloc_set_ui(1);
1039         two = mpi_alloc_set_ui(2);
1040         p = mpi_copy(base->p_);
1041         t1 = mpi_alloc(mpi_get_nlimbs(p));
1042         t2 = mpi_alloc(mpi_get_nlimbs(p));
1043         t3 = mpi_alloc(mpi_get_nlimbs(p));
1044         t4 = mpi_alloc(mpi_get_nlimbs(p));
1045         t5 = mpi_alloc(mpi_get_nlimbs(p));
1046         t6 = mpi_alloc(mpi_get_nlimbs(p));
1047         t7 = mpi_alloc(mpi_get_nlimbs(p));
1048
1049         if( DBG_MPI )log_info("Add two points.\n");
1050
1051         if ((!mpi_cmp(P1->x_,P0->x_)) && (!mpi_cmp(P1->y_,P0->y_)) && (!mpi_cmp(P1->z_,P0->z_))){// P1=P0
1052                 duplicatePoint(P0,P2,base);
1053         }
1054         else if (PointAtInfinity(*P0)){//(!mpi_cmp_ui(P0->y_,0) || !mpi_cmp_ui(P0->z_,0)){// P2=0+P1=P1
1055                 P2->x_ = mpi_copy(P1->x_);
1056                 P2->y_ = mpi_copy(P1->y_);
1057                 P2->z_ = mpi_copy(P1->z_);
1058         }
1059         else if (PointAtInfinity(*P1)){//(!mpi_cmp_ui(P1->y_,0) || !mpi_cmp_ui(P1->z_,0)){// P2=P0+0=P0
1060                 P2->x_ = mpi_copy(P0->x_);
1061                 P2->y_ = mpi_copy(P0->y_);
1062                 P2->z_ = mpi_copy(P0->z_);
1063         }
1064         else {
1065                 t1 = mpi_copy(P0->x_);//t1=x0
1066                 t2 = mpi_copy(P0->y_);//t2=y0
1067                 t3 = mpi_copy(P0->z_);//t3=z0
1068                 t4 = mpi_copy(P1->x_);//t4=x1
1069                 t5 = mpi_copy(P1->y_);//t5=y2
1070                 if (mpi_cmp(P1->z_,one)){//z1!=1
1071                         t6 = mpi_copy(P1->z_);//t6=z1
1072                         mpi_powm(t7, t6,two,p);//t7=t6^2 mod p
1073                         mpi_mulm(t1,t1,t7,p);//t1=t1*t7 mod p
1074                         mpi_mulm(t7,t6,t7,p);//t7=t6*t7 mod p
1075                         mpi_mulm(t2,t2,t7,p);//t2=t2*t7 mod p
1076                 }
1077                 mpi_powm(t7,t3,two,p);//t7=t3^2 mod p
1078                 mpi_mulm(t4,t4,t7,p);//t4=t4*t7 mod p
1079                 mpi_mulm(t7,t3,t7,p);//t7=t3*t7 mod p
1080                 mpi_mulm(t5,t5,t7,p);//t5=t5*t7 mod p
1081                 mpi_subm(t4,t1,t4,p);//t4=t1-t4 mod p
1082                 mpi_subm(t5,t2,t5,p);//t5=t2-t5 mod p
1083                 if (!mpi_cmp_ui(t4,0)){//t4==0
1084                         if (!mpi_cmp_ui(t5,0)){//return (0:0:0), it have an special mean.
1085                                 if( DBG_MPI )log_info("Point Addition: [0:0:0]!\n");
1086                                 P2->x_ = mpi_copy(mpi_alloc_set_ui(0));
1087                                 P2->y_ = mpi_copy(mpi_alloc_set_ui(0));
1088                                 P2->z_ = mpi_copy(mpi_alloc_set_ui(0));
1089                         }
1090                         else {//return (1:1:0)
1091                                 if( DBG_MPI )log_info("Point Addition: [1:1:0]!\n");
1092                                 P2->x_ = mpi_copy(one);
1093                                 P2->y_ = mpi_copy(one);
1094                                 P2->z_ = mpi_copy(mpi_alloc_set_ui(0));
1095                         }
1096                 }
1097                 else{
1098                         mpi_mulm(t1,two,t1,p);
1099                         mpi_subm(t1,t1,t4,p);//t1=2*t1-t4 mod p
1100                         mpi_mulm(t2,two,t2,p);
1101                         mpi_subm(t2,t2,t5,p);//t2=2*t2-t5 mod p
1102                         if (mpi_cmp(P1->z_,one)){//z1!=1
1103                           mpi_mulm(t3,t3,t6,p);//t3=t3*t6
1104                         }
1105                         mpi_mulm(t3,t3,t4,p);//t3=t3*t4 mod p
1106                         mpi_powm(t7,t4,two,p);//t7=t4^2 mod p
1107                         mpi_mulm(t4,t4,t7,p);//t4=t4*t7 mod p
1108                         mpi_mulm(t7,t1,t7,p);//t7=t1*t7 mod p
1109                         mpi_powm(t1,t5,two,p);//t1=t5^2 mod p
1110                         mpi_subm(t1,t1,t7,p);//t1=t1-t7 mod p
1111                         mpi_mulm(t6,two,t1,p);
1112                         mpi_subm(t7,t7,t6,p);//t7=t7-2*t1 mod p
1113                         mpi_mulm(t5,t5,t7,p);//t5=t5*t7 mod p
1114                         mpi_mulm(t4,t2,t4,p);//t4=t2*t4 mod p
1115                         mpi_subm(t2,t5,t4,p);//t2=t5-t4 mod p
1116                         mpi_invm(t6,two,p);
1117                         mpi_mulm(t2,t2,t6,p);//t2 = t2/2
1118
1119                         P2->x_ = mpi_copy(t1);
1120                         P2->y_ = mpi_copy(t2);
1121                         P2->z_ = mpi_copy(t3);
1122                 }
1123         }
1124         mpi_free(t7);
1125         mpi_free(t6);
1126         mpi_free(t5);
1127         mpi_free(t4);
1128         mpi_free(t3);
1129         mpi_free(t2);
1130         mpi_free(t1);
1131         mpi_free(p);
1132         mpi_free(two);
1133         mpi_free(one);
1134 }
1135
1136 /****************
1137  * Scalar multiplication of one point, with the integer fixed to 2.
1138  */
1139 static void
1140 duplicatePoint(point *P, point *R, ellipticCurve *base){
1141
1142         MPI one,two,three,four,eight;
1143         MPI p,p_3,a;
1144         MPI t1,t2,t3,t4,t5,t6,t7;
1145         MPI aux;
1146
1147         one = mpi_alloc_set_ui(1);
1148         two = mpi_alloc_set_ui(2);
1149         three = mpi_alloc_set_ui(3);
1150         four = mpi_alloc_set_ui(4);
1151         eight = mpi_alloc_set_ui(8);
1152         p = mpi_copy(base->p_);
1153         p_3 = mpi_alloc(mpi_get_nlimbs(p));
1154         mpi_sub_ui(p_3,p,3);
1155         a = mpi_copy(base->a_);
1156         t1 = mpi_alloc(mpi_get_nlimbs(p));
1157         t2 = mpi_alloc(mpi_get_nlimbs(p));
1158         t3 = mpi_alloc(mpi_get_nlimbs(p));
1159         t4 = mpi_alloc(mpi_get_nlimbs(p));
1160         t5 = mpi_alloc(mpi_get_nlimbs(p));
1161         t6 = mpi_alloc(mpi_get_nlimbs(p));
1162         t7 = mpi_alloc(mpi_get_nlimbs(p));
1163         aux= mpi_alloc(mpi_get_nlimbs(p));
1164
1165         if( DBG_MPI ){log_info("Duplicate a point.\n");}
1166
1167         t1 = mpi_copy(P->x_);//t1=x1
1168         t2 = mpi_copy(P->y_);//t2=y1
1169         t3 = mpi_copy(P->z_);//t3=z1
1170
1171         if (!mpi_cmp_ui(t2,0) || !mpi_cmp_ui(t3,0)){//t2==0 | t3==0 => [1:1:0]
1172                 if( DBG_MPI ){log_info("t2==0 | t3==0\n");}
1173                 R->x_ = mpi_copy(one);
1174                 R->y_ = mpi_copy(one);
1175                 R->z_ = mpi_copy(mpi_alloc_set_ui(0));
1176         }
1177         else{
1178                 mpi_fdiv_r(a,a,p);//a mod p
1179                 if (!mpi_cmp(a,p_3)){//a==p-3
1180                         mpi_powm(t4,t3,two,p);//t4=t3^2 mod p
1181                         mpi_subm(t5,t1,t4,p);//t5=t1-t4 mod p
1182                         mpi_addm(t4,t1,t4,p);//t4=t1+t4 mod p
1183                         mpi_mulm(t5,t4,t5,p);//t5=t4*t5 mod p
1184                         mpi_mulm(t4,three,t5,p);//t4=3*t5 mod p
1185                 }
1186                 else{
1187                         t4 = mpi_copy(a);//t4=a
1188                         mpi_powm(t5,t3,two,p);//t5=t3^2 mod p
1189                         mpi_powm(t5,t5,two,p);//t5=t5^2 mod p
1190                         mpi_mulm(t5,t4,t5,p);//t5=t4*t5 mod p
1191                         mpi_powm(t4,t1,two,p);//t4=t1^2 mod p
1192                         mpi_mulm(t4,three,t4,p);//t4=3*t4 mod p
1193                         mpi_addm(t4,t4,t5,p);//t4=t4+t5 mod p
1194                 }
1195                 if( DBG_MPI ){log_info("t2!=0 & t3!=0\n");}
1196                 mpi_mulm(t3,t2,t3,p);//t3=t2*t3 mod p
1197                 mpi_mulm(t3,two,t3,p);//t3=2*t3 mod p 
1198                 mpi_powm(aux,t2,two,p);//t2=t2^2 mod p
1199                 t2 = mpi_copy(aux);
1200                 mpi_mulm(t5,t1,t2,p);//t5=t1*t2 mod p
1201                 mpi_mulm(t5,four,t5,p);//t5=4*t5 mod p
1202                 mpi_powm(t1,t4,two,p);//t1=t4^2 mod p
1203                 mpi_mulm(aux,two,t5,p);
1204                 mpi_subm(t1,t1,aux,p);//t1=t1-2*t5 mod p
1205                 mpi_powm(aux,t2,two,p);//t2=t2^2 mod p
1206                 t2 = mpi_copy(aux);
1207                 mpi_mulm(t2,eight,t2,p);//t2=8*t2 mod p
1208                 mpi_subm(t5,t5,t1,p);//t5=t5-t1 mod p
1209                 mpi_mulm(t5,t4,t5,p);//t5=t4*t5 mod p
1210                 mpi_subm(t2,t5,t2,p);//t2=t5-t2 mod p
1211
1212                 R->x_ = mpi_copy(t1);
1213                 R->y_ = mpi_copy(t2);
1214                 R->z_ = mpi_copy(t3);
1215         }
1216         if( DBG_MPI ){log_info("Duplicated point.\n");}
1217
1218         mpi_free(aux);
1219         mpi_free(t7);
1220         mpi_free(t6);
1221         mpi_free(t5);
1222         mpi_free(t4);
1223         mpi_free(t3);
1224         mpi_free(t2);
1225         mpi_free(t1);
1226         mpi_free(p);
1227         mpi_free(p_3);
1228         mpi_free(a);
1229         mpi_free(eight);
1230         mpi_free(four);
1231         mpi_free(three);
1232         mpi_free(two);
1233         mpi_free(one);
1234
1235 }
1236
1237 /****************
1238  * The point inversion over F_p
1239  * is a simple modular inversion
1240  * of the Y coordinate.
1241  */
1242 static void
1243 invertPoint(point *P, ellipticCurve *base){
1244
1245         mpi_subm(P->y_,base->p_,P->y_,base->p_);//y=p-y mod p
1246 }
1247
1248 /****************
1249  * Auxiliar function to made easy a struct copy.
1250  */
1251 static point
1252 point_copy(point P){
1253         point R;
1254
1255         R.x_ = mpi_copy(P.x_);
1256         R.y_ = mpi_copy(P.y_);
1257         R.z_ = mpi_copy(P.z_);
1258
1259         return R;
1260 }
1261
1262 /****************
1263  * Made easy the free memory for a point struct.
1264  */
1265 static void
1266 point_free(point *P){
1267
1268         mpi_free(P->x_);
1269         mpi_free(P->y_);
1270         mpi_free(P->z_);
1271 }
1272
1273 /****************
1274  * Turn a projective coordinate to affine, return 0 (or 1 in error case).
1275  * Needed to verify a signature.
1276  *
1277  * y_coordinate it is never used, we could do without it. //!!
1278  */
1279 static int 
1280 point_affine(point *P, MPI x, MPI y, ellipticCurve *base){
1281
1282         //MPI z;
1283         MPI z1,z2,z3;
1284
1285         z1 = mpi_alloc(0);
1286         z2 = mpi_alloc(0);
1287         z3 = mpi_alloc(0);
1288
1289         if (PointAtInfinity(*P)){
1290                 if( DBG_CIPHER )log_info("Affine: Point at Infinity does NOT exist in the affine plane!\n");
1291                 return 1;
1292         }
1293
1294         mpi_invm(z1,P->z_,base->p_);    //      z1 =Z^{-1} (mod p)
1295         mpi_mulm(z2,z1,z1,base->p_);    //      z2 =Z^(-2) (mod p)
1296         mpi_mulm(z3,z2,z1,base->p_);    //      z3 =Z^(-3) (mod p)
1297         mpi_mulm(x,P->x_,z2,base->p_);
1298         mpi_mulm(y,P->y_,z3,base->p_);
1299
1300         mpi_free(z1);
1301         mpi_free(z2);
1302         mpi_free(z3);
1303         return 0;
1304 }
1305
1306 /****************
1307  * Auxiliar function to made easy a struct copy.
1308  */
1309 static ellipticCurve
1310 curve_copy(ellipticCurve E){
1311
1312         ellipticCurve R;
1313
1314         R.p_ = mpi_copy(E.p_);
1315         R.a_ = mpi_copy(E.a_);
1316         R.b_ = mpi_copy(E.b_);
1317         R.G = point_copy(E.G);
1318         R.n_ = mpi_copy(E.n_);
1319
1320         return R;
1321 }
1322
1323 /****************
1324  * Made easy the free memory for a setup struct.
1325  */
1326 static void
1327 curve_free(ellipticCurve *E){
1328         mpi_free(E->p_);
1329         mpi_free(E->a_);
1330         mpi_free(E->b_);
1331         point_free(&E->G);
1332         mpi_free(E->n_);
1333 }
1334
1335 /****************
1336  * Boolean generator to choose between to coordinates.
1337  */
1338 static MPI
1339 gen_bit(){
1340
1341         MPI aux = mpi_alloc_set_ui(0);
1342
1343         //Get one random bit, with less security level, and translate it to an MPI.
1344         mpi_set_buffer( aux, get_random_bits( 1, 0, 1 ), 1, 0 );//gen_k(...)
1345
1346         return aux;//b;
1347 }
1348
1349 /****************
1350  * Solve the right side of the equation that define a curve.
1351  */
1352 static MPI
1353 gen_y_2(MPI x, ellipticCurve *base){
1354
1355         MPI three;
1356         MPI x_3,ax,axb,y;
1357         MPI a,b,p;
1358
1359         three = mpi_alloc_set_ui(3);
1360         a = mpi_copy(base->a_);
1361         b = mpi_copy(base->b_),
1362         p = mpi_copy(base->p_);
1363         x_3 = mpi_alloc(mpi_get_nlimbs(p));
1364         ax = mpi_alloc(mpi_get_nlimbs(p));
1365         axb = mpi_alloc(mpi_get_nlimbs(p));
1366         y = mpi_alloc(mpi_get_nlimbs(p));
1367
1368         if( DBG_MPI )log_info("solving an elliptic equation.\n");
1369
1370         mpi_powm(x_3,x,three,p);//x_3=x^3 mod p
1371         mpi_mulm(ax,a,x,p);//ax=a*x mod p
1372         mpi_addm(axb,ax,b,p);//axb=ax+b mod p
1373         mpi_addm(y,x_3,axb,p);//y=x^3+ax+b mod p
1374
1375         if( DBG_MPI )log_info("solved.\n");
1376
1377         return y;//the quadratic value of the coordinate if it exist.
1378 }
1379
1380 //Function to solve an IFP ECElGamal weakness:
1381 // sha256_hashing()
1382 // aes256_encrypting()
1383 // aes356_decrypting()
1384
1385 /****************
1386  * Compute 256 bit hash value from input MPI.
1387  * Use SHA256 Algorithm.
1388  */
1389 static void 
1390 sha256_hashing(MPI input, MPI *output){ // 
1391
1392         int sign;
1393         byte *hash_inp_buf; 
1394         byte hash_out_buf[32]; 
1395         MD_HANDLE hash = md_open(8,1);//algo SHA256 in secure mode
1396
1397         unsigned int nbytes;
1398
1399         hash_inp_buf = mpi_get_secure_buffer( input, &nbytes, &sign );//convert MPI input to string
1400
1401         md_write( hash, hash_inp_buf, nbytes );//hashing input string
1402         wipememory( hash_inp_buf, sizeof hash_inp_buf ); // burn temp value 
1403         xfree(hash_inp_buf);
1404
1405         md_digest(hash, 8, hash_out_buf, 32);
1406         mpi_set_buffer( *output, hash_out_buf, 32, 0 );// convert 256 bit digest to MPI
1407
1408         wipememory( hash_out_buf, sizeof hash_out_buf ); // burn temp value 
1409         md_close(hash);// destroy and free hash state.
1410
1411 }
1412
1413 /****************
1414  * Encrypt input MPI.
1415  * Use AES256 algorithm.
1416  */
1417
1418 static void 
1419 aes256_encrypting(MPI key, MPI input, MPI *output){ // 
1420
1421         int sign;
1422         byte *key_buf; 
1423         byte *cipher_buf; 
1424
1425         unsigned int keylength;
1426         unsigned int nbytes;
1427
1428
1429         CIPHER_HANDLE cipher = cipher_open(9,CIPHER_MODE_CFB,1);//algo AES256 CFB mode in secure memory
1430         cipher_setiv( cipher, NULL, 0 ); // Zero IV
1431
1432         key_buf = mpi_get_secure_buffer( key, &keylength, &sign );//convert MPI key to string
1433         cipher_setkey( cipher, key_buf, keylength );
1434         wipememory( key_buf, sizeof key_buf ); // burn temp value 
1435         xfree(key_buf);
1436
1437         cipher_buf = mpi_get_secure_buffer( input, &nbytes, &sign );//convert MPI input to string
1438
1439         cipher_encrypt( cipher, cipher_buf+1, cipher_buf+1, nbytes-1);//
1440         cipher_close(cipher);// destroy and free cipher state.
1441
1442         mpi_set_buffer( *output, cipher_buf, nbytes, 0 );// convert encrypted string to MPI
1443         wipememory( cipher_buf, sizeof cipher_buf ); // burn temp value 
1444         xfree(cipher_buf);
1445 }
1446
1447 /****************
1448  * Decrypt input MPI.
1449  * Use AES256 algorithm.
1450  */
1451
1452 static void 
1453 aes256_decrypting(MPI key, MPI input, MPI *output){ // 
1454
1455         int sign;
1456         byte *key_buf; 
1457         byte *cipher_buf; 
1458
1459         unsigned int keylength;
1460         unsigned int nbytes;
1461
1462
1463         CIPHER_HANDLE cipher = cipher_open(9,CIPHER_MODE_CFB,1);//algo AES256 CFB mode in secure memory
1464         cipher_setiv( cipher, NULL, 0 ); // Zero IV
1465
1466         key_buf = mpi_get_secure_buffer( key, &keylength, &sign );//convert MPI input to string
1467         cipher_setkey( cipher, key_buf, keylength );
1468         wipememory( key_buf, sizeof key_buf ); // burn temp value 
1469         xfree(key_buf);
1470
1471         cipher_buf = mpi_get_secure_buffer( input, &nbytes, &sign );//convert MPI input to string;
1472
1473         cipher_decrypt( cipher, cipher_buf+1, cipher_buf+1, nbytes-1 );//
1474         cipher_close(cipher);// destroy and free cipher state.
1475
1476         mpi_set_buffer( *output, cipher_buf, nbytes, 0 );// convert encrypted string to MPI
1477         wipememory( cipher_buf, sizeof cipher_buf ); // burn temp value 
1478         xfree(cipher_buf);
1479 }
1480 //End of IFP ECElGamal weakness functions.
1481
1482 /*********************************************
1483  **************  interface  ******************
1484  *********************************************/
1485 int
1486 ecc_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
1487 {
1488
1489         ECC_secret_key sk;
1490
1491         if( !is_ECC(algo) )
1492                 return G10ERR_PUBKEY_ALGO;
1493
1494         generateKey( &sk, nbits, retfactors );
1495
1496         skey[0] = sk.E.p_;
1497         skey[1] = sk.E.a_;
1498         skey[2] = sk.E.b_;
1499         skey[3] = sk.E.G.x_;
1500         skey[4] = sk.E.G.y_;
1501         skey[5] = sk.E.G.z_;
1502         skey[6] = sk.E.n_;
1503         skey[7] = sk.Q.x_;
1504         skey[8] = sk.Q.y_;
1505         skey[9] = sk.Q.z_;
1506         skey[10] = sk.d;
1507
1508         if( DBG_CIPHER ) {
1509                 progress('\n');
1510
1511                 log_mpidump("[ecc]  p= ", skey[0]);
1512                 log_mpidump("[ecc]  a= ", skey[1]);
1513                 log_mpidump("[ecc]  b= ", skey[2]);
1514                 log_mpidump("[ecc]  Gx= ", skey[3]);
1515                 log_mpidump("[ecc]  Gy= ", skey[4]);
1516                 log_mpidump("[ecc]  Gz= ", skey[5]);
1517                 log_mpidump("[ecc]  n= ", skey[6]);
1518                 log_mpidump("[ecc]  Qx= ", skey[7]);
1519                 log_mpidump("[ecc]  Qy= ", skey[8]);
1520                 log_mpidump("[ecc]  Qz= ", skey[9]);
1521                 log_mpidump("[ecc]  d= ", skey[10]);
1522         }
1523
1524         if( DBG_CIPHER ){log_info("ECC key Generated.\n");}
1525         return 0;
1526 }
1527
1528
1529 int
1530 ecc_check_secret_key( int algo, MPI *skey )
1531 {
1532         ECC_secret_key sk;
1533
1534         if( !is_ECC(algo) )
1535                 return G10ERR_PUBKEY_ALGO;
1536         if(!skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5] || !skey[6] || !skey[7] || !skey[8] || !skey[9] || !skey[10])
1537                 return G10ERR_BAD_MPI;
1538
1539         if( DBG_CIPHER ){log_info("ECC check secret key.\n");}
1540         sk.E.p_ = skey[0];
1541         sk.E.a_ = skey[1];
1542         sk.E.b_ = skey[2];
1543         sk.E.G.x_ = skey[3];
1544         sk.E.G.y_ = skey[4];
1545         sk.E.G.z_ = skey[5];
1546         sk.E.n_ = skey[6];
1547         sk.Q.x_ = skey[7];
1548         sk.Q.y_ = skey[8];
1549         sk.Q.z_ = skey[9];
1550         sk.d = skey[10];
1551
1552         if( check_secret_key(&sk)){
1553                 if( DBG_CIPHER )log_info("Bad check: Bad secret key.\n");
1554                 return G10ERR_BAD_SECKEY;
1555         }
1556         return 0;
1557 }
1558
1559
1560
1561 int
1562 ecc_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
1563 {
1564         ECC_public_key pk;
1565         point R;
1566
1567         if( algo != PUBKEY_ALGO_ECC && algo != PUBKEY_ALGO_ECC_E )
1568                 return G10ERR_PUBKEY_ALGO;
1569         if( !data || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4] || !pkey[5] || !pkey[6] || !pkey[7] || !pkey[8] || !pkey[9])
1570                 return G10ERR_BAD_MPI;
1571
1572         if( DBG_CIPHER ){log_info("ECC encrypt.\n");}
1573         pk.E.p_ = pkey[0];
1574         pk.E.a_ = pkey[1];
1575         pk.E.b_ = pkey[2];
1576         pk.E.G.x_ = pkey[3];
1577         pk.E.G.y_ = pkey[4];
1578         pk.E.G.z_ = pkey[5];
1579         pk.E.n_ = pkey[6];
1580         pk.Q.x_ = pkey[7];
1581         pk.Q.y_ = pkey[8];
1582         pk.Q.z_ = pkey[9];
1583
1584         R.x_ = resarr[0] = mpi_alloc( mpi_get_nlimbs( pk.Q.x_ ) );
1585         R.y_ = resarr[1] = mpi_alloc( mpi_get_nlimbs( pk.Q.y_ ) );
1586         R.z_ = resarr[2] = mpi_alloc( mpi_get_nlimbs( pk.Q.z_ ) );
1587         resarr[3] = mpi_alloc( mpi_get_nlimbs( pk.E.p_ ) );
1588
1589         doEncrypt(data, &pk, &R, resarr[3]);
1590
1591         resarr[0] = mpi_copy(R.x_);
1592         resarr[1] = mpi_copy(R.y_);
1593         resarr[2] = mpi_copy(R.z_);
1594         return 0;
1595 }
1596
1597 int
1598 ecc_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
1599 {
1600         ECC_secret_key sk;
1601         point R;
1602
1603         if( algo != PUBKEY_ALGO_ECC && algo != PUBKEY_ALGO_ECC_E )
1604                 return G10ERR_PUBKEY_ALGO;
1605         if( !data[0] || !data[1] || !data[2] || !data[3] || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5] || !skey[6] || !skey[7] || !skey[8] || !skey[9] || !skey[10])
1606                 return G10ERR_BAD_MPI;
1607
1608         if( DBG_CIPHER ){log_info("ECC decrypt.\n");}
1609         R.x_ = data[0];
1610         R.y_ = data[1];
1611         R.z_ = data[2];
1612         sk.E.p_ = skey[0];
1613         sk.E.a_ = skey[1];
1614         sk.E.b_ = skey[2];
1615         sk.E.G.x_ = skey[3];
1616         sk.E.G.y_ = skey[4];
1617         sk.E.G.z_ = skey[5];
1618         sk.E.n_ = skey[6];
1619         sk.Q.x_ = skey[7];
1620         sk.Q.y_ = skey[8];
1621         sk.Q.z_ = skey[9];
1622         sk.d = skey[10];
1623
1624         *result = mpi_alloc_secure( mpi_get_nlimbs( sk.E.p_ ) );
1625         *result = decrypt( *result, &sk, R, data[3]);
1626         return 0;
1627 }
1628
1629 int
1630 ecc_sign( int algo, MPI *resarr, MPI data, MPI *skey )
1631 {
1632         ECC_secret_key sk;
1633
1634         if( algo != PUBKEY_ALGO_ECC && algo != PUBKEY_ALGO_ECC_S )
1635                 return G10ERR_PUBKEY_ALGO;
1636         if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5] || !skey[6] || !skey[7] || !skey[8] || !skey[9] || !skey[10])
1637                 return G10ERR_BAD_MPI;
1638
1639         sk.E.p_ = skey[0];
1640         sk.E.a_ = skey[1];
1641         sk.E.b_ = skey[2];
1642         sk.E.G.x_ = skey[3];
1643         sk.E.G.y_ = skey[4];
1644         sk.E.G.z_ = skey[5];
1645         sk.E.n_ = skey[6];
1646         sk.Q.x_ = skey[7];
1647         sk.Q.y_ = skey[8];
1648         sk.Q.z_ = skey[9];
1649         sk.d = skey[10];
1650
1651         resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.E.p_ ) );
1652         resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.E.p_ ) );
1653         sign( data, &sk, &resarr[0], &resarr[1]);
1654         return 0;
1655 }
1656
1657 int
1658 ecc_verify( int algo, MPI hash, MPI *data, MPI *pkey )
1659 {
1660         ECC_public_key pk;
1661
1662         if( algo != PUBKEY_ALGO_ECC && algo != PUBKEY_ALGO_ECC_S )
1663                 return G10ERR_PUBKEY_ALGO;
1664         if( !data[0] || !data[1] || !hash || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4] || !pkey[5] || !pkey[6] || !pkey[7] || !pkey[8] || !pkey[9])
1665                 return G10ERR_BAD_MPI;
1666
1667         if( DBG_CIPHER ){log_info("ECC verify.\n");}
1668         pk.E.p_ = pkey[0];
1669         pk.E.a_ = pkey[1];
1670         pk.E.b_ = pkey[2];
1671         pk.E.G.x_ = pkey[3];
1672         pk.E.G.y_ = pkey[4];
1673         pk.E.G.z_ = pkey[5];
1674         pk.E.n_ = pkey[6];
1675         pk.Q.x_ = pkey[7];
1676         pk.Q.y_ = pkey[8];
1677         pk.Q.z_ = pkey[9];
1678
1679         if( !verify( hash, &pk, data[0], data[1]) )
1680                 return G10ERR_BAD_SIGN;
1681         return 0;
1682 }
1683
1684
1685
1686 unsigned int
1687 ecc_get_nbits( int algo, MPI *pkey )
1688 {
1689         if ( !is_ECC(algo) ){
1690                 return 0;
1691         }
1692         if( DBG_CIPHER ){log_info("ECC get nbits.\n");}
1693
1694         if( DBG_CIPHER ) {
1695                 progress('\n');
1696
1697                 log_mpidump("[ecc]  p= ", pkey[0]);
1698                 log_mpidump("[ecc]  a= ", pkey[1]);
1699                 log_mpidump("[ecc]  b= ", pkey[2]);
1700                 log_mpidump("[ecc]  Gx= ", pkey[3]);
1701                 log_mpidump("[ecc]  Gy= ", pkey[4]);
1702                 log_mpidump("[ecc]  Gz= ", pkey[5]);
1703                 log_mpidump("[ecc]  n= ", pkey[6]);
1704                 log_mpidump("[ecc]  Qx= ", pkey[7]);
1705                 log_mpidump("[ecc]  Qy= ", pkey[8]);
1706                 log_mpidump("[ecc]  Qz= ", pkey[9]);
1707         }
1708
1709         return mpi_get_nbits( pkey[0] );
1710 }
1711
1712 const char *
1713 ecc_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig, int *use )
1714 {
1715     *npkey = 10;
1716     *nskey = 11;
1717     *nenc = 4;
1718     *nsig = 2;
1719
1720     if( DBG_CIPHER ){log_info("ECC get info.\n");}
1721     switch( algo ) {
1722       case PUBKEY_ALGO_ECC:
1723         *use = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC;
1724         return "ECC";
1725       case PUBKEY_ALGO_ECC_S:
1726         *use = PUBKEY_USAGE_SIG;
1727         return "ECDSA";
1728       case PUBKEY_ALGO_ECC_E:
1729         *use = PUBKEY_USAGE_ENC;
1730         return "ECELG";
1731       default: *use = 0; return NULL;
1732     }
1733 }