|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include <stdio.h> |
|
6 #include <stdlib.h> |
|
7 #include <string.h> |
|
8 #include <malloc.h> |
|
9 #include <time.h> |
|
10 #include "mpi.h" |
|
11 #include "mpi-priv.h" |
|
12 |
|
13 /* #define OLD_WAY 1 */ |
|
14 |
|
15 /* This key is the 1024-bit test key used for speed testing of RSA private |
|
16 ** key ops. |
|
17 */ |
|
18 |
|
19 #define CONST const |
|
20 |
|
21 static CONST unsigned char default_n[128] = { |
|
22 0xc2,0xae,0x96,0x89,0xaf,0xce,0xd0,0x7b,0x3b,0x35,0xfd,0x0f,0xb1,0xf4,0x7a,0xd1, |
|
23 0x3c,0x7d,0xb5,0x86,0xf2,0x68,0x36,0xc9,0x97,0xe6,0x82,0x94,0x86,0xaa,0x05,0x39, |
|
24 0xec,0x11,0x51,0xcc,0x5c,0xa1,0x59,0xba,0x29,0x18,0xf3,0x28,0xf1,0x9d,0xe3,0xae, |
|
25 0x96,0x5d,0x6d,0x87,0x73,0xf6,0xf6,0x1f,0xd0,0x2d,0xfb,0x2f,0x7a,0x13,0x7f,0xc8, |
|
26 0x0c,0x7a,0xe9,0x85,0xfb,0xce,0x74,0x86,0xf8,0xef,0x2f,0x85,0x37,0x73,0x0f,0x62, |
|
27 0x4e,0x93,0x17,0xb7,0x7e,0x84,0x9a,0x94,0x11,0x05,0xca,0x0d,0x31,0x4b,0x2a,0xc8, |
|
28 0xdf,0xfe,0xe9,0x0c,0x13,0xc7,0xf2,0xad,0x19,0x64,0x28,0x3c,0xb5,0x6a,0xc8,0x4b, |
|
29 0x79,0xea,0x7c,0xce,0x75,0x92,0x45,0x3e,0xa3,0x9d,0x64,0x6f,0x04,0x69,0x19,0x17 |
|
30 }; |
|
31 |
|
32 static CONST unsigned char default_d[128] = { |
|
33 0x13,0xcb,0xbc,0xf2,0xf3,0x35,0x8c,0x6d,0x7b,0x6f,0xd9,0xf3,0xa6,0x9c,0xbd,0x80, |
|
34 0x59,0x2e,0x4f,0x2f,0x11,0xa7,0x17,0x2b,0x18,0x8f,0x0f,0xe8,0x1a,0x69,0x5f,0x6e, |
|
35 0xac,0x5a,0x76,0x7e,0xd9,0x4c,0x6e,0xdb,0x47,0x22,0x8a,0x57,0x37,0x7a,0x5e,0x94, |
|
36 0x7a,0x25,0xb5,0xe5,0x78,0x1d,0x3c,0x99,0xaf,0x89,0x7d,0x69,0x2e,0x78,0x9d,0x1d, |
|
37 0x84,0xc8,0xc1,0xd7,0x1a,0xb2,0x6d,0x2d,0x8a,0xd9,0xab,0x6b,0xce,0xae,0xb0,0xa0, |
|
38 0x58,0x55,0xad,0x5c,0x40,0x8a,0xd6,0x96,0x08,0x8a,0xe8,0x63,0xe6,0x3d,0x6c,0x20, |
|
39 0x49,0xc7,0xaf,0x0f,0x25,0x73,0xd3,0x69,0x43,0x3b,0xf2,0x32,0xf8,0x3d,0x5e,0xee, |
|
40 0x7a,0xca,0xd6,0x94,0x55,0xe5,0xbd,0x25,0x34,0x8d,0x63,0x40,0xb5,0x8a,0xc3,0x01 |
|
41 }; |
|
42 |
|
43 |
|
44 #define DEFAULT_ITERS 50 |
|
45 |
|
46 typedef clock_t timetype; |
|
47 #define gettime(x) *(x) = clock() |
|
48 #define subtime(a, b) a -= b |
|
49 #define msec(x) ((clock_t)((double)x * 1000.0 / CLOCKS_PER_SEC)) |
|
50 #define sec(x) (x / CLOCKS_PER_SEC) |
|
51 |
|
52 struct TimingContextStr { |
|
53 timetype start; |
|
54 timetype end; |
|
55 timetype interval; |
|
56 |
|
57 int minutes; |
|
58 int seconds; |
|
59 int millisecs; |
|
60 }; |
|
61 |
|
62 typedef struct TimingContextStr TimingContext; |
|
63 |
|
64 TimingContext *CreateTimingContext(void) |
|
65 { |
|
66 return (TimingContext *)malloc(sizeof(TimingContext)); |
|
67 } |
|
68 |
|
69 void DestroyTimingContext(TimingContext *ctx) |
|
70 { |
|
71 free(ctx); |
|
72 } |
|
73 |
|
74 void TimingBegin(TimingContext *ctx) |
|
75 { |
|
76 gettime(&ctx->start); |
|
77 } |
|
78 |
|
79 static void timingUpdate(TimingContext *ctx) |
|
80 { |
|
81 |
|
82 ctx->millisecs = msec(ctx->interval) % 1000; |
|
83 ctx->seconds = sec(ctx->interval); |
|
84 ctx->minutes = ctx->seconds / 60; |
|
85 ctx->seconds %= 60; |
|
86 |
|
87 } |
|
88 |
|
89 void TimingEnd(TimingContext *ctx) |
|
90 { |
|
91 gettime(&ctx->end); |
|
92 ctx->interval = ctx->end; |
|
93 subtime(ctx->interval, ctx->start); |
|
94 timingUpdate(ctx); |
|
95 } |
|
96 |
|
97 char *TimingGenerateString(TimingContext *ctx) |
|
98 { |
|
99 static char sBuf[4096]; |
|
100 |
|
101 sprintf(sBuf, "%d minutes, %d.%03d seconds", ctx->minutes, |
|
102 ctx->seconds, ctx->millisecs); |
|
103 return sBuf; |
|
104 } |
|
105 |
|
106 static void |
|
107 dumpBytes( unsigned char * b, int l) |
|
108 { |
|
109 int i; |
|
110 if (l <= 0) |
|
111 return; |
|
112 for (i = 0; i < l; ++i) { |
|
113 if (i % 16 == 0) |
|
114 printf("\t"); |
|
115 printf(" %02x", b[i]); |
|
116 if (i % 16 == 15) |
|
117 printf("\n"); |
|
118 } |
|
119 if ((i % 16) != 0) |
|
120 printf("\n"); |
|
121 printf("\n"); |
|
122 } |
|
123 |
|
124 static mp_err |
|
125 testNewFuncs(const unsigned char * modulusBytes, int modulus_len) |
|
126 { |
|
127 mp_err mperr = MP_OKAY; |
|
128 mp_int modulus; |
|
129 unsigned char buf[512]; |
|
130 |
|
131 mperr = mp_init(&modulus); |
|
132 mperr = mp_read_unsigned_octets(&modulus, modulusBytes, modulus_len ); |
|
133 mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len); |
|
134 mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len+1); |
|
135 mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len+4); |
|
136 mperr = mp_to_unsigned_octets(&modulus, buf, modulus_len); |
|
137 mperr = mp_to_signed_octets(&modulus, buf, modulus_len + 1); |
|
138 mp_clear(&modulus); |
|
139 return mperr; |
|
140 } |
|
141 |
|
142 int |
|
143 testModExp( const unsigned char * modulusBytes, |
|
144 const unsigned int expo, |
|
145 const unsigned char * input, |
|
146 unsigned char * output, |
|
147 int modulus_len) |
|
148 { |
|
149 mp_err mperr = MP_OKAY; |
|
150 mp_int modulus; |
|
151 mp_int base; |
|
152 mp_int exponent; |
|
153 mp_int result; |
|
154 |
|
155 mperr = mp_init(&modulus); |
|
156 mperr += mp_init(&base); |
|
157 mperr += mp_init(&exponent); |
|
158 mperr += mp_init(&result); |
|
159 /* we initialize all mp_ints unconditionally, even if some fail. |
|
160 ** This guarantees that the DIGITS pointer is valid (even if null). |
|
161 ** So, mp_clear will do the right thing below. |
|
162 */ |
|
163 if (mperr == MP_OKAY) { |
|
164 mperr = mp_read_unsigned_octets(&modulus, |
|
165 modulusBytes + (sizeof default_n - modulus_len), modulus_len ); |
|
166 mperr += mp_read_unsigned_octets(&base, input, modulus_len ); |
|
167 mp_set(&exponent, expo); |
|
168 if (mperr == MP_OKAY) { |
|
169 #if OLD_WAY |
|
170 mperr = s_mp_exptmod(&base, &exponent, &modulus, &result); |
|
171 #else |
|
172 mperr = mp_exptmod(&base, &exponent, &modulus, &result); |
|
173 #endif |
|
174 if (mperr == MP_OKAY) { |
|
175 mperr = mp_to_fixlen_octets(&result, output, modulus_len); |
|
176 } |
|
177 } |
|
178 } |
|
179 mp_clear(&base); |
|
180 mp_clear(&result); |
|
181 |
|
182 mp_clear(&modulus); |
|
183 mp_clear(&exponent); |
|
184 |
|
185 return (int)mperr; |
|
186 } |
|
187 |
|
188 int |
|
189 doModExp( const unsigned char * modulusBytes, |
|
190 const unsigned char * exponentBytes, |
|
191 const unsigned char * input, |
|
192 unsigned char * output, |
|
193 int modulus_len) |
|
194 { |
|
195 mp_err mperr = MP_OKAY; |
|
196 mp_int modulus; |
|
197 mp_int base; |
|
198 mp_int exponent; |
|
199 mp_int result; |
|
200 |
|
201 mperr = mp_init(&modulus); |
|
202 mperr += mp_init(&base); |
|
203 mperr += mp_init(&exponent); |
|
204 mperr += mp_init(&result); |
|
205 /* we initialize all mp_ints unconditionally, even if some fail. |
|
206 ** This guarantees that the DIGITS pointer is valid (even if null). |
|
207 ** So, mp_clear will do the right thing below. |
|
208 */ |
|
209 if (mperr == MP_OKAY) { |
|
210 mperr = mp_read_unsigned_octets(&modulus, |
|
211 modulusBytes + (sizeof default_n - modulus_len), modulus_len ); |
|
212 mperr += mp_read_unsigned_octets(&exponent, exponentBytes, modulus_len ); |
|
213 mperr += mp_read_unsigned_octets(&base, input, modulus_len ); |
|
214 if (mperr == MP_OKAY) { |
|
215 #if OLD_WAY |
|
216 mperr = s_mp_exptmod(&base, &exponent, &modulus, &result); |
|
217 #else |
|
218 mperr = mp_exptmod(&base, &exponent, &modulus, &result); |
|
219 #endif |
|
220 if (mperr == MP_OKAY) { |
|
221 mperr = mp_to_fixlen_octets(&result, output, modulus_len); |
|
222 } |
|
223 } |
|
224 } |
|
225 mp_clear(&base); |
|
226 mp_clear(&result); |
|
227 |
|
228 mp_clear(&modulus); |
|
229 mp_clear(&exponent); |
|
230 |
|
231 return (int)mperr; |
|
232 } |
|
233 |
|
234 int |
|
235 main(int argc, char **argv) |
|
236 { |
|
237 TimingContext * timeCtx; |
|
238 char * progName; |
|
239 long iters = DEFAULT_ITERS; |
|
240 unsigned int modulus_len; |
|
241 int i; |
|
242 int rv; |
|
243 unsigned char buf [1024]; |
|
244 unsigned char buf2[1024]; |
|
245 |
|
246 progName = strrchr(argv[0], '/'); |
|
247 if (!progName) |
|
248 progName = strrchr(argv[0], '\\'); |
|
249 progName = progName ? progName+1 : argv[0]; |
|
250 |
|
251 if (argc >= 2) { |
|
252 iters = atol(argv[1]); |
|
253 } |
|
254 |
|
255 if (argc >= 3) { |
|
256 modulus_len = atol(argv[2]); |
|
257 } else |
|
258 modulus_len = sizeof default_n; |
|
259 |
|
260 /* no library init function !? */ |
|
261 |
|
262 memset(buf, 0x41, sizeof buf); |
|
263 |
|
264 if (iters < 2) { |
|
265 testNewFuncs( default_n, modulus_len); |
|
266 testNewFuncs( default_n+1, modulus_len - 1); |
|
267 testNewFuncs( default_n+2, modulus_len - 2); |
|
268 testNewFuncs( default_n+3, modulus_len - 3); |
|
269 |
|
270 printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies); |
|
271 rv = testModExp(default_n, 0, buf, buf2, modulus_len); |
|
272 dumpBytes((unsigned char *)buf2, modulus_len); |
|
273 |
|
274 printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies); |
|
275 rv = testModExp(default_n, 1, buf, buf2, modulus_len); |
|
276 dumpBytes((unsigned char *)buf2, modulus_len); |
|
277 |
|
278 printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies); |
|
279 rv = testModExp(default_n, 2, buf, buf2, modulus_len); |
|
280 dumpBytes((unsigned char *)buf2, modulus_len); |
|
281 |
|
282 printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies); |
|
283 rv = testModExp(default_n, 3, buf, buf2, modulus_len); |
|
284 dumpBytes((unsigned char *)buf2, modulus_len); |
|
285 } |
|
286 printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies); |
|
287 rv = doModExp(default_n, default_d, buf, buf2, modulus_len); |
|
288 if (rv != 0) { |
|
289 fprintf(stderr, "Error in modexp operation:\n"); |
|
290 exit(1); |
|
291 } |
|
292 dumpBytes((unsigned char *)buf2, modulus_len); |
|
293 printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies); |
|
294 |
|
295 timeCtx = CreateTimingContext(); |
|
296 TimingBegin(timeCtx); |
|
297 i = iters; |
|
298 while (i--) { |
|
299 rv = doModExp(default_n, default_d, buf, buf2, modulus_len); |
|
300 if (rv != 0) { |
|
301 fprintf(stderr, "Error in modexp operation\n"); |
|
302 exit(1); |
|
303 } |
|
304 } |
|
305 TimingEnd(timeCtx); |
|
306 printf("%ld iterations in %s\n", iters, TimingGenerateString(timeCtx)); |
|
307 printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies); |
|
308 |
|
309 return 0; |
|
310 } |