1 /*
2  *   Digital Signature Standard (DSS)
3  *
4  *   Elliptic Curve variation GF(2^m) - See Dr. Dobbs Journal, April 1997
5  *
6  *   This program asks for the name of a <file>, computes its message digest,
7  *   signs it, and outputs the signature to a file <file>.ecs. It is assumed
8  *   that curve parameters are available from a file common2.ecs, as well as
9  *   the private key of the signer previously generated by the ecsgen2 program
10  *
11  *   The curve is y^2+xy = x^3+Ax^2+B over GF(2^m) using a trinomial or
12  *   pentanomial basis (t^m+t^a+1 or t^m+t^a+t^b+t^c+1), These parameters
13  *   can be generated using the findbase.cpp example program, or taken from tables
14  *   provided, for example in IEEE-P1363 Annex A
15  *
16  *   The file common2.ecs is presumed to exist and contain
17  *   {m,A,B,q,x,y,a,b,c} where A and B are parameters of the equation
18  *   above, (x,y) is an initial point on the curve, {m,a,b,c} are the field
19  *   parameters, (b is zero for a trinomial) and q is the order of the
20  *   (x,y) point, itself a large prime. The number of points on the curve is
21  *   cf.q where cf is the "co-factor", normally 2 or 4.
22  *
23  *   This program is written for static mode.
24  *   For a 163-bit modulus p, MR_STATIC could be defined as 6 in mirdef.h
25  *   for a 32-bit processor, or 11 for a 16-bit processor (11*16 > 163).
26  *   The system parameters can be found in the file common2.ecs
27  *   Assumes MR_GENERIC_MT is defined in mirdef.h
28  */
29 
30 #include <stdio.h>
31 #include "miracl.h"
32 #include <stdlib.h>
33 #include <string.h>
34 
strip(char * name)35 void strip(char *name)
36 { /* strip off filename extension */
37     int i;
38     for (i=0;name[i]!='\0';i++)
39     {
40         if (name[i]!='.') continue;
41         name[i]='\0';
42         break;
43     }
44 }
45 
hashing(miracl * mip,FILE * fp,big hash)46 static void hashing(miracl *mip,FILE *fp,big hash)
47 { /* compute hash function */
48     char h[20];
49     int i,ch;
50     sha sh;
51     shs_init(&sh);
52     while ((ch=fgetc(fp))!=EOF) shs_process(&sh,ch);
53     shs_hash(&sh,h);
54     bytes_to_big(mip,20,h,hash);
55 }
56 
main()57 int main()
58 {
59     FILE *fp;
60     int m,a,b,c;
61     char ifname[50],ofname[50];
62     big a2,a6,q,x,y,d,r,s,k,hash;
63     epoint *g;
64     long seed;
65     miracl instance;
66     miracl *mip=&instance;
67     char mem[MR_BIG_RESERVE(10)];           /* reserve space on the stack for 10 bigs */
68     char mem1[MR_ECP_RESERVE(1)];           /* and one elliptic curve points         */
69     memset(mem,0,MR_BIG_RESERVE(10));
70     memset(mem1,0,MR_ECP_RESERVE(1));
71 
72 /* get public data */
73     fp=fopen("common2.ecs","rt");
74     if (fp==NULL)
75     {
76         printf("file common2.ecs does not exist\n");
77         return 0;
78     }
79     fscanf(fp,"%d\n",&m);
80 
81     mip=mirsys(mip,MR_ROUNDUP(abs(m),4),16);
82     a2=mirvar_mem(mip,mem,0);
83     a6=mirvar_mem(mip,mem,1);
84     q=mirvar_mem(mip,mem,2);
85     x=mirvar_mem(mip,mem,3);
86     y=mirvar_mem(mip,mem,4);
87     d=mirvar_mem(mip,mem,5);
88     r=mirvar_mem(mip,mem,6);
89     s=mirvar_mem(mip,mem,7);
90     k=mirvar_mem(mip,mem,8);
91     hash=mirvar_mem(mip,mem,9);
92 
93     innum(mip,a2,fp);     /* curve parameters */
94     innum(mip,a6,fp);     /* curve parameters */
95     innum(mip,q,fp);     /* order of (x,y) */
96     innum(mip,x,fp);     /* (x,y) point on curve of order q */
97     innum(mip,y,fp);
98 
99     fscanf(fp,"%d\n",&a);
100     fscanf(fp,"%d\n",&b);
101     fscanf(fp,"%d\n",&c);
102     fclose(fp);
103 
104 /* randomise */
105     printf("Enter 9 digit random number seed  = ");
106     scanf("%ld",&seed);
107     getchar();
108     irand(mip,seed);
109 
110     ecurve2_init(mip,m,a,b,c,a2,a6,FALSE,MR_PROJECTIVE);  /* initialise curve */
111 
112     g=epoint_init_mem(mip,mem1,0);
113     epoint2_set(mip,x,y,0,g); /* set point of order q */
114 
115 /* calculate r - this can be done offline,
116    and hence amortized to almost nothing   */
117     bigrand(mip,q,k);
118     ecurve2_mult(mip,k,g,g);      /* see ebrick2.c for method to speed this up */
119     epoint2_get(mip,g,r,r);
120     divide(mip,r,q,q);
121 
122 /* get private key of signer */
123     fp=fopen("private.ecs","rt");
124     if (fp==NULL)
125     {
126         printf("file private.ecs does not exist\n");
127         return 0;
128     }
129     innum(mip,d,fp);
130     fclose(fp);
131 
132 /* calculate message digest */
133     printf("file to be signed = ");
134     gets(ifname);
135     strcpy(ofname,ifname);
136     strip(ofname);
137     strcat(ofname,".ecs");
138     if ((fp=fopen(ifname,"rb"))==NULL)
139     {
140         printf("Unable to open file %s\n",ifname);
141         return 0;
142     }
143     hashing(mip,fp,hash);
144     fclose(fp);
145 
146 /* calculate s */
147     xgcd(mip,k,q,k,k,k);
148 
149     mad(mip,d,r,hash,q,q,s);
150     mad(mip,s,k,k,q,q,s);
151     fp=fopen(ofname,"wt");
152     otnum(mip,r,fp);
153     otnum(mip,s,fp);
154     fclose(fp);
155 /* clear all memory used */
156     memset(mem,0,MR_BIG_RESERVE(10));
157     memset(mem1,0,MR_ECP_RESERVE(1));
158 
159     return 0;
160 }
161 
162