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 <ctype.h>
8
9 #include "secitem.h"
10 #include "blapi.h"
11 #include "nssutil.h"
12 #include "secerr.h"
13 #include "secder.h"
14 #include "secdig.h"
15 #include "secoid.h"
16 #include "ec.h"
17 #include "hasht.h"
18 #include "lowkeyi.h"
19 #include "softoken.h"
20 #include "pkcs11t.h"
21 #define __PASTE(x, y) x##y
22 #undef CK_PKCS11_FUNCTION_INFO
23 #undef CK_NEED_ARG_LIST
24 #define CK_EXTERN extern
25 #define CK_PKCS11_FUNCTION_INFO(func) \
26 CK_RV __PASTE(NS, func)
27 #define CK_NEED_ARG_LIST 1
28 #include "pkcs11f.h"
29 #undef CK_PKCS11_FUNCTION_INFO
30 #undef CK_NEED_ARG_LIST
31 #undef __PASTE
32 #define SSL3_RANDOM_LENGTH 32
33
34 #if 0
35 #include "../../lib/freebl/mpi/mpi.h"
36 #endif
37 #define MATCH_OPENSSL 1
38 /*#define MATCH_NIST 1 */
39 #ifdef MATCH_NIST
40 #define VERBOSE_REASON 1
41 #endif
42
43 extern SECStatus
44 EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
45 extern SECStatus
46 EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
47 const ECParams *srcParams);
48
49 #define ENCRYPT 1
50 #define DECRYPT 0
51 #define BYTE unsigned char
52 #define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001
53 #define RSA_MAX_TEST_MODULUS_BITS 4096
54 #define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS / 8
55 #define RSA_MAX_TEST_EXPONENT_BYTES 8
56 #define PQG_TEST_SEED_BYTES 20
57
58 SECStatus
hex_to_byteval(const char * c2,unsigned char * byteval)59 hex_to_byteval(const char *c2, unsigned char *byteval)
60 {
61 int i;
62 unsigned char offset;
63 *byteval = 0;
64 for (i = 0; i < 2; i++) {
65 if (c2[i] >= '0' && c2[i] <= '9') {
66 offset = c2[i] - '0';
67 *byteval |= offset << 4 * (1 - i);
68 } else if (c2[i] >= 'a' && c2[i] <= 'f') {
69 offset = c2[i] - 'a';
70 *byteval |= (offset + 10) << 4 * (1 - i);
71 } else if (c2[i] >= 'A' && c2[i] <= 'F') {
72 offset = c2[i] - 'A';
73 *byteval |= (offset + 10) << 4 * (1 - i);
74 } else {
75 return SECFailure;
76 }
77 }
78 return SECSuccess;
79 }
80
81 SECStatus
byteval_to_hex(unsigned char byteval,char * c2,char a)82 byteval_to_hex(unsigned char byteval, char *c2, char a)
83 {
84 int i;
85 unsigned char offset;
86 for (i = 0; i < 2; i++) {
87 offset = (byteval >> 4 * (1 - i)) & 0x0f;
88 if (offset < 10) {
89 c2[i] = '0' + offset;
90 } else {
91 c2[i] = a + offset - 10;
92 }
93 }
94 return SECSuccess;
95 }
96
97 void
to_hex_str(char * str,const unsigned char * buf,unsigned int len)98 to_hex_str(char *str, const unsigned char *buf, unsigned int len)
99 {
100 unsigned int i;
101 for (i = 0; i < len; i++) {
102 byteval_to_hex(buf[i], &str[2 * i], 'a');
103 }
104 str[2 * len] = '\0';
105 }
106
107 void
to_hex_str_cap(char * str,const unsigned char * buf,unsigned int len)108 to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len)
109 {
110 unsigned int i;
111 for (i = 0; i < len; i++) {
112 byteval_to_hex(buf[i], &str[2 * i], 'A');
113 }
114 str[2 * len] = '\0';
115 }
116
117 /*
118 * Convert a string of hex digits (str) to an array (buf) of len bytes.
119 * Return PR_TRUE if the hex string can fit in the byte array. Return
120 * PR_FALSE if the hex string is empty or is too long.
121 */
122 PRBool
from_hex_str(unsigned char * buf,unsigned int len,const char * str)123 from_hex_str(unsigned char *buf, unsigned int len, const char *str)
124 {
125 unsigned int nxdigit; /* number of hex digits in str */
126 unsigned int i; /* index into buf */
127 unsigned int j; /* index into str */
128
129 /* count the hex digits */
130 nxdigit = 0;
131 for (nxdigit = 0; isxdigit(str[nxdigit]); nxdigit++) {
132 /* empty body */
133 }
134 if (nxdigit == 0) {
135 return PR_FALSE;
136 }
137 if (nxdigit > 2 * len) {
138 /*
139 * The input hex string is too long, but we allow it if the
140 * extra digits are leading 0's.
141 */
142 for (j = 0; j < nxdigit - 2 * len; j++) {
143 if (str[j] != '0') {
144 return PR_FALSE;
145 }
146 }
147 /* skip leading 0's */
148 str += nxdigit - 2 * len;
149 nxdigit = 2 * len;
150 }
151 for (i = 0, j = 0; i < len; i++) {
152 if (2 * i < 2 * len - nxdigit) {
153 /* Handle a short input as if we padded it with leading 0's. */
154 if (2 * i + 1 < 2 * len - nxdigit) {
155 buf[i] = 0;
156 } else {
157 char tmp[2];
158 tmp[0] = '0';
159 tmp[1] = str[j];
160 hex_to_byteval(tmp, &buf[i]);
161 j++;
162 }
163 } else {
164 hex_to_byteval(&str[j], &buf[i]);
165 j += 2;
166 }
167 }
168 return PR_TRUE;
169 }
170
171 SECStatus
tdea_encrypt_buf(int mode,const unsigned char * key,const unsigned char * iv,unsigned char * output,unsigned int * outputlen,unsigned int maxoutputlen,const unsigned char * input,unsigned int inputlen)172 tdea_encrypt_buf(
173 int mode,
174 const unsigned char *key,
175 const unsigned char *iv,
176 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
177 const unsigned char *input, unsigned int inputlen)
178 {
179 SECStatus rv = SECFailure;
180 DESContext *cx;
181 unsigned char doublecheck[8 * 20]; /* 1 to 20 blocks */
182 unsigned int doublechecklen = 0;
183
184 cx = DES_CreateContext(key, iv, mode, PR_TRUE);
185 if (cx == NULL) {
186 goto loser;
187 }
188 rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
189 if (rv != SECSuccess) {
190 goto loser;
191 }
192 if (*outputlen != inputlen) {
193 goto loser;
194 }
195 DES_DestroyContext(cx, PR_TRUE);
196 cx = NULL;
197
198 /*
199 * Doublecheck our result by decrypting the ciphertext and
200 * compare the output with the input plaintext.
201 */
202 cx = DES_CreateContext(key, iv, mode, PR_FALSE);
203 if (cx == NULL) {
204 goto loser;
205 }
206 rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
207 output, *outputlen);
208 if (rv != SECSuccess) {
209 goto loser;
210 }
211 if (doublechecklen != *outputlen) {
212 goto loser;
213 }
214 DES_DestroyContext(cx, PR_TRUE);
215 cx = NULL;
216 if (memcmp(doublecheck, input, inputlen) != 0) {
217 goto loser;
218 }
219 rv = SECSuccess;
220
221 loser:
222 if (cx != NULL) {
223 DES_DestroyContext(cx, PR_TRUE);
224 }
225 return rv;
226 }
227
228 SECStatus
tdea_decrypt_buf(int mode,const unsigned char * key,const unsigned char * iv,unsigned char * output,unsigned int * outputlen,unsigned int maxoutputlen,const unsigned char * input,unsigned int inputlen)229 tdea_decrypt_buf(
230 int mode,
231 const unsigned char *key,
232 const unsigned char *iv,
233 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
234 const unsigned char *input, unsigned int inputlen)
235 {
236 SECStatus rv = SECFailure;
237 DESContext *cx;
238 unsigned char doublecheck[8 * 20]; /* 1 to 20 blocks */
239 unsigned int doublechecklen = 0;
240
241 cx = DES_CreateContext(key, iv, mode, PR_FALSE);
242 if (cx == NULL) {
243 goto loser;
244 }
245 rv = DES_Decrypt(cx, output, outputlen, maxoutputlen,
246 input, inputlen);
247 if (rv != SECSuccess) {
248 goto loser;
249 }
250 if (*outputlen != inputlen) {
251 goto loser;
252 }
253 DES_DestroyContext(cx, PR_TRUE);
254 cx = NULL;
255
256 /*
257 * Doublecheck our result by encrypting the plaintext and
258 * compare the output with the input ciphertext.
259 */
260 cx = DES_CreateContext(key, iv, mode, PR_TRUE);
261 if (cx == NULL) {
262 goto loser;
263 }
264 rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
265 output, *outputlen);
266 if (rv != SECSuccess) {
267 goto loser;
268 }
269 if (doublechecklen != *outputlen) {
270 goto loser;
271 }
272 DES_DestroyContext(cx, PR_TRUE);
273 cx = NULL;
274 if (memcmp(doublecheck, input, inputlen) != 0) {
275 goto loser;
276 }
277 rv = SECSuccess;
278
279 loser:
280 if (cx != NULL) {
281 DES_DestroyContext(cx, PR_TRUE);
282 }
283 return rv;
284 }
285
286 /*
287 * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
288 * Test (MMT) in ECB or CBC mode. The KAT (there are five types)
289 * and MMT have the same structure: given the key and IV (CBC mode
290 * only), encrypt the given plaintext or decrypt the given ciphertext.
291 * So we can handle them the same way.
292 *
293 * reqfn is the pathname of the REQUEST file.
294 *
295 * The output RESPONSE file is written to stdout.
296 */
297 void
tdea_kat_mmt(char * reqfn)298 tdea_kat_mmt(char *reqfn)
299 {
300 char buf[180]; /* holds one line from the input REQUEST file.
301 * needs to be large enough to hold the longest
302 * line "CIPHERTEXT = <180 hex digits>\n".
303 */
304 FILE *req; /* input stream from the REQUEST file */
305 FILE *resp; /* output stream to the RESPONSE file */
306 int i, j;
307 int mode = NSS_DES_EDE3; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
308 int crypt = DECRYPT; /* 1 means encrypt, 0 means decrypt */
309 unsigned char key[24]; /* TDEA 3 key bundle */
310 unsigned int numKeys = 0;
311 unsigned char iv[8]; /* for all modes except ECB */
312 unsigned char plaintext[8 * 20]; /* 1 to 20 blocks */
313 unsigned int plaintextlen;
314 unsigned char ciphertext[8 * 20]; /* 1 to 20 blocks */
315 unsigned int ciphertextlen;
316 SECStatus rv;
317
318 req = fopen(reqfn, "r");
319 resp = stdout;
320 while (fgets(buf, sizeof buf, req) != NULL) {
321 /* a comment or blank line */
322 if (buf[0] == '#' || buf[0] == '\n') {
323 fputs(buf, resp);
324 continue;
325 }
326 /* [ENCRYPT] or [DECRYPT] */
327 if (buf[0] == '[') {
328 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
329 crypt = ENCRYPT;
330 } else {
331 crypt = DECRYPT;
332 }
333 fputs(buf, resp);
334 continue;
335 }
336 /* NumKeys */
337 if (strncmp(&buf[0], "NumKeys", 7) == 0) {
338 i = 7;
339 while (isspace(buf[i]) || buf[i] == '=') {
340 i++;
341 }
342 numKeys = buf[i];
343 fputs(buf, resp);
344 continue;
345 }
346 /* "COUNT = x" begins a new data set */
347 if (strncmp(buf, "COUNT", 5) == 0) {
348 /* mode defaults to ECB, if dataset has IV mode will be set CBC */
349 mode = NSS_DES_EDE3;
350 /* zeroize the variables for the test with this data set */
351 memset(key, 0, sizeof key);
352 memset(iv, 0, sizeof iv);
353 memset(plaintext, 0, sizeof plaintext);
354 plaintextlen = 0;
355 memset(ciphertext, 0, sizeof ciphertext);
356 ciphertextlen = 0;
357 fputs(buf, resp);
358 continue;
359 }
360 if (numKeys == 0) {
361 if (strncmp(buf, "KEYs", 4) == 0) {
362 i = 4;
363 while (isspace(buf[i]) || buf[i] == '=') {
364 i++;
365 }
366 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
367 hex_to_byteval(&buf[i], &key[j]);
368 key[j + 8] = key[j];
369 key[j + 16] = key[j];
370 }
371 fputs(buf, resp);
372 continue;
373 }
374 } else {
375 /* KEY1 = ... */
376 if (strncmp(buf, "KEY1", 4) == 0) {
377 i = 4;
378 while (isspace(buf[i]) || buf[i] == '=') {
379 i++;
380 }
381 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
382 hex_to_byteval(&buf[i], &key[j]);
383 }
384 fputs(buf, resp);
385 continue;
386 }
387 /* KEY2 = ... */
388 if (strncmp(buf, "KEY2", 4) == 0) {
389 i = 4;
390 while (isspace(buf[i]) || buf[i] == '=') {
391 i++;
392 }
393 for (j = 8; isxdigit(buf[i]); i += 2, j++) {
394 hex_to_byteval(&buf[i], &key[j]);
395 }
396 fputs(buf, resp);
397 continue;
398 }
399 /* KEY3 = ... */
400 if (strncmp(buf, "KEY3", 4) == 0) {
401 i = 4;
402 while (isspace(buf[i]) || buf[i] == '=') {
403 i++;
404 }
405 for (j = 16; isxdigit(buf[i]); i += 2, j++) {
406 hex_to_byteval(&buf[i], &key[j]);
407 }
408 fputs(buf, resp);
409 continue;
410 }
411 }
412
413 /* IV = ... */
414 if (strncmp(buf, "IV", 2) == 0) {
415 mode = NSS_DES_EDE3_CBC;
416 i = 2;
417 while (isspace(buf[i]) || buf[i] == '=') {
418 i++;
419 }
420 for (j = 0; j < sizeof iv; i += 2, j++) {
421 hex_to_byteval(&buf[i], &iv[j]);
422 }
423 fputs(buf, resp);
424 continue;
425 }
426
427 /* PLAINTEXT = ... */
428 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
429 /* sanity check */
430 if (crypt != ENCRYPT) {
431 goto loser;
432 }
433 i = 9;
434 while (isspace(buf[i]) || buf[i] == '=') {
435 i++;
436 }
437 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
438 hex_to_byteval(&buf[i], &plaintext[j]);
439 }
440 plaintextlen = j;
441 rv = tdea_encrypt_buf(mode, key,
442 (mode == NSS_DES_EDE3) ? NULL : iv,
443 ciphertext, &ciphertextlen, sizeof ciphertext,
444 plaintext, plaintextlen);
445 if (rv != SECSuccess) {
446 goto loser;
447 }
448
449 fputs(buf, resp);
450 fputs("CIPHERTEXT = ", resp);
451 to_hex_str(buf, ciphertext, ciphertextlen);
452 fputs(buf, resp);
453 fputc('\n', resp);
454 continue;
455 }
456 /* CIPHERTEXT = ... */
457 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
458 /* sanity check */
459 if (crypt != DECRYPT) {
460 goto loser;
461 }
462
463 i = 10;
464 while (isspace(buf[i]) || buf[i] == '=') {
465 i++;
466 }
467 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
468 hex_to_byteval(&buf[i], &ciphertext[j]);
469 }
470 ciphertextlen = j;
471
472 rv = tdea_decrypt_buf(mode, key,
473 (mode == NSS_DES_EDE3) ? NULL : iv,
474 plaintext, &plaintextlen, sizeof plaintext,
475 ciphertext, ciphertextlen);
476 if (rv != SECSuccess) {
477 goto loser;
478 }
479
480 fputs(buf, resp);
481 fputs("PLAINTEXT = ", resp);
482 to_hex_str(buf, plaintext, plaintextlen);
483 fputs(buf, resp);
484 fputc('\n', resp);
485 continue;
486 }
487 }
488
489 loser:
490 fclose(req);
491 }
492
493 /*
494 * Set the parity bit for the given byte
495 */
496 BYTE
odd_parity(BYTE in)497 odd_parity(BYTE in)
498 {
499 BYTE out = in;
500 in ^= in >> 4;
501 in ^= in >> 2;
502 in ^= in >> 1;
503 return (BYTE)(out ^ !(in & 1));
504 }
505
506 /*
507 * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j]
508 * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
509 */
510 void
tdea_mct_next_keys(unsigned char * key,const unsigned char * text_2,const unsigned char * text_1,const unsigned char * text,unsigned int numKeys)511 tdea_mct_next_keys(unsigned char *key,
512 const unsigned char *text_2, const unsigned char *text_1,
513 const unsigned char *text, unsigned int numKeys)
514 {
515 int k;
516
517 /* key1[i+1] = key1[i] xor PT/CT[j] */
518 for (k = 0; k < 8; k++) {
519 key[k] ^= text[k];
520 }
521 /* key2 */
522 if (numKeys == 2 || numKeys == 3) {
523 /* key2 independent */
524 for (k = 8; k < 16; k++) {
525 /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
526 key[k] ^= text_1[k - 8];
527 }
528 } else {
529 /* key2 == key 1 */
530 for (k = 8; k < 16; k++) {
531 /* key2[i+1] = KEY2[i] xor PT/CT[j] */
532 key[k] = key[k - 8];
533 }
534 }
535 /* key3 */
536 if (numKeys == 1 || numKeys == 2) {
537 /* key3 == key 1 */
538 for (k = 16; k < 24; k++) {
539 /* key3[i+1] = KEY3[i] xor PT/CT[j] */
540 key[k] = key[k - 16];
541 }
542 } else {
543 /* key3 independent */
544 for (k = 16; k < 24; k++) {
545 /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
546 key[k] ^= text_2[k - 16];
547 }
548 }
549 /* set the parity bits */
550 for (k = 0; k < 24; k++) {
551 key[k] = odd_parity(key[k]);
552 }
553 }
554
555 /*
556 * Perform the Monte Carlo Test
557 *
558 * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
559 * crypt = ENCRYPT || DECRYPT
560 * inputtext = plaintext or Cyphertext depending on the value of crypt
561 * inputlength is expected to be size 8 bytes
562 * iv = needs to be set for NSS_DES_EDE3_CBC mode
563 * resp = is the output response file.
564 */
565 void
tdea_mct_test(int mode,unsigned char * key,unsigned int numKeys,unsigned int crypt,unsigned char * inputtext,unsigned int inputlength,unsigned char * iv,FILE * resp)566 tdea_mct_test(int mode, unsigned char *key, unsigned int numKeys,
567 unsigned int crypt, unsigned char *inputtext,
568 unsigned int inputlength, unsigned char *iv, FILE *resp)
569 {
570
571 int i, j;
572 unsigned char outputtext_1[8]; /* PT/CT[j-1] */
573 unsigned char outputtext_2[8]; /* PT/CT[j-2] */
574 char buf[80]; /* holds one line from the input REQUEST file. */
575 unsigned int outputlen;
576 unsigned char outputtext[8];
577
578 SECStatus rv;
579
580 if (mode == NSS_DES_EDE3 && iv != NULL) {
581 printf("IV must be NULL for NSS_DES_EDE3 mode");
582 goto loser;
583 } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) {
584 printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
585 goto loser;
586 }
587
588 /* loop 400 times */
589 for (i = 0; i < 400; i++) {
590 /* if i == 0 CV[0] = IV not necessary */
591 /* record the count and key values and plainText */
592 sprintf(buf, "COUNT = %d\n", i);
593 fputs(buf, resp);
594 /* Output KEY1[i] */
595 fputs("KEY1 = ", resp);
596 to_hex_str(buf, key, 8);
597 fputs(buf, resp);
598 fputc('\n', resp);
599 /* Output KEY2[i] */
600 fputs("KEY2 = ", resp);
601 to_hex_str(buf, &key[8], 8);
602 fputs(buf, resp);
603 fputc('\n', resp);
604 /* Output KEY3[i] */
605 fputs("KEY3 = ", resp);
606 to_hex_str(buf, &key[16], 8);
607 fputs(buf, resp);
608 fputc('\n', resp);
609 if (mode == NSS_DES_EDE3_CBC) {
610 /* Output CV[i] */
611 fputs("IV = ", resp);
612 to_hex_str(buf, iv, 8);
613 fputs(buf, resp);
614 fputc('\n', resp);
615 }
616 if (crypt == ENCRYPT) {
617 /* Output PT[0] */
618 fputs("PLAINTEXT = ", resp);
619 } else {
620 /* Output CT[0] */
621 fputs("CIPHERTEXT = ", resp);
622 }
623
624 to_hex_str(buf, inputtext, inputlength);
625 fputs(buf, resp);
626 fputc('\n', resp);
627
628 /* loop 10,000 times */
629 for (j = 0; j < 10000; j++) {
630
631 outputlen = 0;
632 if (crypt == ENCRYPT) {
633 /* inputtext == ciphertext outputtext == plaintext*/
634 rv = tdea_encrypt_buf(mode, key,
635 (mode ==
636 NSS_DES_EDE3)
637 ? NULL
638 : iv,
639 outputtext, &outputlen, 8,
640 inputtext, 8);
641 } else {
642 /* inputtext == plaintext outputtext == ciphertext */
643 rv = tdea_decrypt_buf(mode, key,
644 (mode ==
645 NSS_DES_EDE3)
646 ? NULL
647 : iv,
648 outputtext, &outputlen, 8,
649 inputtext, 8);
650 }
651
652 if (rv != SECSuccess) {
653 goto loser;
654 }
655 if (outputlen != inputlength) {
656 goto loser;
657 }
658
659 if (mode == NSS_DES_EDE3_CBC) {
660 if (crypt == ENCRYPT) {
661 if (j == 0) {
662 /*P[j+1] = CV[0] */
663 memcpy(inputtext, iv, 8);
664 } else {
665 /* p[j+1] = C[j-1] */
666 memcpy(inputtext, outputtext_1, 8);
667 }
668 /* CV[j+1] = C[j] */
669 memcpy(iv, outputtext, 8);
670 if (j != 9999) {
671 /* save C[j-1] */
672 memcpy(outputtext_1, outputtext, 8);
673 }
674 } else { /* DECRYPT */
675 /* CV[j+1] = C[j] */
676 memcpy(iv, inputtext, 8);
677 /* C[j+1] = P[j] */
678 memcpy(inputtext, outputtext, 8);
679 }
680 } else {
681 /* ECB mode PT/CT[j+1] = CT/PT[j] */
682 memcpy(inputtext, outputtext, 8);
683 }
684
685 /* Save PT/CT[j-2] and PT/CT[j-1] */
686 if (j == 9997)
687 memcpy(outputtext_2, outputtext, 8);
688 if (j == 9998)
689 memcpy(outputtext_1, outputtext, 8);
690 /* done at the end of the for(j) loop */
691 }
692
693 if (crypt == ENCRYPT) {
694 /* Output CT[j] */
695 fputs("CIPHERTEXT = ", resp);
696 } else {
697 /* Output PT[j] */
698 fputs("PLAINTEXT = ", resp);
699 }
700 to_hex_str(buf, outputtext, 8);
701 fputs(buf, resp);
702 fputc('\n', resp);
703
704 /* Key[i+1] = Key[i] xor ... outputtext_2 == PT/CT[j-2]
705 * outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j]
706 */
707 tdea_mct_next_keys(key, outputtext_2,
708 outputtext_1, outputtext, numKeys);
709
710 if (mode == NSS_DES_EDE3_CBC) {
711 /* taken care of in the j=9999 iteration */
712 if (crypt == ENCRYPT) {
713 /* P[i] = C[j-1] */
714 /* CV[i] = C[j] */
715 } else {
716 /* taken care of in the j=9999 iteration */
717 /* CV[i] = C[j] */
718 /* C[i] = P[j] */
719 }
720 } else {
721 /* ECB PT/CT[i] = PT/CT[j] */
722 memcpy(inputtext, outputtext, 8);
723 }
724 /* done at the end of the for(i) loop */
725 fputc('\n', resp);
726 }
727
728 loser:
729 return;
730 }
731
732 /*
733 * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
734 * by gathering the input from the request file, and then
735 * calling tdea_mct_test.
736 *
737 * reqfn is the pathname of the input REQUEST file.
738 *
739 * The output RESPONSE file is written to stdout.
740 */
741 void
tdea_mct(int mode,char * reqfn)742 tdea_mct(int mode, char *reqfn)
743 {
744 int i, j;
745 char buf[80]; /* holds one line from the input REQUEST file. */
746 FILE *req; /* input stream from the REQUEST file */
747 FILE *resp; /* output stream to the RESPONSE file */
748 unsigned int crypt = 0; /* 1 means encrypt, 0 means decrypt */
749 unsigned char key[24]; /* TDEA 3 key bundle */
750 unsigned int numKeys = 0;
751 unsigned char plaintext[8]; /* PT[j] */
752 unsigned char ciphertext[8]; /* CT[j] */
753 unsigned char iv[8];
754
755 /* zeroize the variables for the test with this data set */
756 memset(key, 0, sizeof key);
757 memset(plaintext, 0, sizeof plaintext);
758 memset(ciphertext, 0, sizeof ciphertext);
759 memset(iv, 0, sizeof iv);
760
761 req = fopen(reqfn, "r");
762 resp = stdout;
763 while (fgets(buf, sizeof buf, req) != NULL) {
764 /* a comment or blank line */
765 if (buf[0] == '#' || buf[0] == '\n') {
766 fputs(buf, resp);
767 continue;
768 }
769 /* [ENCRYPT] or [DECRYPT] */
770 if (buf[0] == '[') {
771 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
772 crypt = ENCRYPT;
773 } else {
774 crypt = DECRYPT;
775 }
776 fputs(buf, resp);
777 continue;
778 }
779 /* NumKeys */
780 if (strncmp(&buf[0], "NumKeys", 7) == 0) {
781 i = 7;
782 while (isspace(buf[i]) || buf[i] == '=') {
783 i++;
784 }
785 numKeys = atoi(&buf[i]);
786 continue;
787 }
788 /* KEY1 = ... */
789 if (strncmp(buf, "KEY1", 4) == 0) {
790 i = 4;
791 while (isspace(buf[i]) || buf[i] == '=') {
792 i++;
793 }
794 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
795 hex_to_byteval(&buf[i], &key[j]);
796 }
797 continue;
798 }
799 /* KEY2 = ... */
800 if (strncmp(buf, "KEY2", 4) == 0) {
801 i = 4;
802 while (isspace(buf[i]) || buf[i] == '=') {
803 i++;
804 }
805 for (j = 8; isxdigit(buf[i]); i += 2, j++) {
806 hex_to_byteval(&buf[i], &key[j]);
807 }
808 continue;
809 }
810 /* KEY3 = ... */
811 if (strncmp(buf, "KEY3", 4) == 0) {
812 i = 4;
813 while (isspace(buf[i]) || buf[i] == '=') {
814 i++;
815 }
816 for (j = 16; isxdigit(buf[i]); i += 2, j++) {
817 hex_to_byteval(&buf[i], &key[j]);
818 }
819 continue;
820 }
821
822 /* IV = ... */
823 if (strncmp(buf, "IV", 2) == 0) {
824 i = 2;
825 while (isspace(buf[i]) || buf[i] == '=') {
826 i++;
827 }
828 for (j = 0; j < sizeof iv; i += 2, j++) {
829 hex_to_byteval(&buf[i], &iv[j]);
830 }
831 continue;
832 }
833
834 /* PLAINTEXT = ... */
835 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
836
837 /* sanity check */
838 if (crypt != ENCRYPT) {
839 goto loser;
840 }
841 /* PT[0] = PT */
842 i = 9;
843 while (isspace(buf[i]) || buf[i] == '=') {
844 i++;
845 }
846 for (j = 0; j < sizeof plaintext; i += 2, j++) {
847 hex_to_byteval(&buf[i], &plaintext[j]);
848 }
849
850 /* do the Monte Carlo test */
851 if (mode == NSS_DES_EDE3) {
852 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp);
853 } else {
854 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp);
855 }
856 continue;
857 }
858 /* CIPHERTEXT = ... */
859 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
860 /* sanity check */
861 if (crypt != DECRYPT) {
862 goto loser;
863 }
864 /* CT[0] = CT */
865 i = 10;
866 while (isspace(buf[i]) || buf[i] == '=') {
867 i++;
868 }
869 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
870 hex_to_byteval(&buf[i], &ciphertext[j]);
871 }
872
873 /* do the Monte Carlo test */
874 if (mode == NSS_DES_EDE3) {
875 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp);
876 } else {
877 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp);
878 }
879 continue;
880 }
881 }
882
883 loser:
884 fclose(req);
885 }
886
887 SECStatus
aes_encrypt_buf(int mode,const unsigned char * key,unsigned int keysize,const unsigned char * iv,unsigned char * output,unsigned int * outputlen,unsigned int maxoutputlen,const unsigned char * input,unsigned int inputlen)888 aes_encrypt_buf(
889 int mode,
890 const unsigned char *key, unsigned int keysize,
891 const unsigned char *iv,
892 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
893 const unsigned char *input, unsigned int inputlen)
894 {
895 SECStatus rv = SECFailure;
896 AESContext *cx;
897 unsigned char doublecheck[10 * 16]; /* 1 to 10 blocks */
898 unsigned int doublechecklen = 0;
899
900 cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
901 if (cx == NULL) {
902 goto loser;
903 }
904 rv = AES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
905 if (rv != SECSuccess) {
906 goto loser;
907 }
908 if (*outputlen != inputlen) {
909 goto loser;
910 }
911 AES_DestroyContext(cx, PR_TRUE);
912 cx = NULL;
913
914 /*
915 * Doublecheck our result by decrypting the ciphertext and
916 * compare the output with the input plaintext.
917 */
918 cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
919 if (cx == NULL) {
920 goto loser;
921 }
922 rv = AES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
923 output, *outputlen);
924 if (rv != SECSuccess) {
925 goto loser;
926 }
927 if (doublechecklen != *outputlen) {
928 goto loser;
929 }
930 AES_DestroyContext(cx, PR_TRUE);
931 cx = NULL;
932 if (memcmp(doublecheck, input, inputlen) != 0) {
933 goto loser;
934 }
935 rv = SECSuccess;
936
937 loser:
938 if (cx != NULL) {
939 AES_DestroyContext(cx, PR_TRUE);
940 }
941 return rv;
942 }
943
944 SECStatus
aes_decrypt_buf(int mode,const unsigned char * key,unsigned int keysize,const unsigned char * iv,unsigned char * output,unsigned int * outputlen,unsigned int maxoutputlen,const unsigned char * input,unsigned int inputlen)945 aes_decrypt_buf(
946 int mode,
947 const unsigned char *key, unsigned int keysize,
948 const unsigned char *iv,
949 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
950 const unsigned char *input, unsigned int inputlen)
951 {
952 SECStatus rv = SECFailure;
953 AESContext *cx;
954 unsigned char doublecheck[10 * 16]; /* 1 to 10 blocks */
955 unsigned int doublechecklen = 0;
956
957 cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
958 if (cx == NULL) {
959 goto loser;
960 }
961 rv = AES_Decrypt(cx, output, outputlen, maxoutputlen,
962 input, inputlen);
963 if (rv != SECSuccess) {
964 goto loser;
965 }
966 if (*outputlen != inputlen) {
967 goto loser;
968 }
969 AES_DestroyContext(cx, PR_TRUE);
970 cx = NULL;
971
972 /*
973 * Doublecheck our result by encrypting the plaintext and
974 * compare the output with the input ciphertext.
975 */
976 cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
977 if (cx == NULL) {
978 goto loser;
979 }
980 rv = AES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
981 output, *outputlen);
982 if (rv != SECSuccess) {
983 goto loser;
984 }
985 if (doublechecklen != *outputlen) {
986 goto loser;
987 }
988 AES_DestroyContext(cx, PR_TRUE);
989 cx = NULL;
990 if (memcmp(doublecheck, input, inputlen) != 0) {
991 goto loser;
992 }
993 rv = SECSuccess;
994
995 loser:
996 if (cx != NULL) {
997 AES_DestroyContext(cx, PR_TRUE);
998 }
999 return rv;
1000 }
1001 /*
1002 * Perform the AES GCM tests.
1003 *
1004 * reqfn is the pathname of the REQUEST file.
1005 *
1006 * The output RESPONSE file is written to stdout.
1007 */
1008 void
aes_gcm(char * reqfn,int encrypt)1009 aes_gcm(char *reqfn, int encrypt)
1010 {
1011 char buf[512]; /* holds one line from the input REQUEST file.
1012 * needs to be large enough to hold the longest
1013 * line "CIPHERTEXT = <320 hex digits>\n".
1014 */
1015 FILE *aesreq; /* input stream from the REQUEST file */
1016 FILE *aesresp; /* output stream to the RESPONSE file */
1017 int i, j;
1018 unsigned char key[32]; /* 128, 192, or 256 bits */
1019 unsigned int keysize = 0;
1020 unsigned char iv[128]; /* handle large gcm IV's */
1021 unsigned char plaintext[10 * 16]; /* 1 to 10 blocks */
1022 unsigned int plaintextlen;
1023 unsigned char ciphertext[11 * 16]; /* 1 to 10 blocks + tag */
1024 unsigned int ciphertextlen;
1025 unsigned char aad[11 * 16]; /* 1 to 10 blocks + tag */
1026 unsigned int aadlen = 0;
1027 unsigned int tagbits;
1028 unsigned int taglen = 0;
1029 unsigned int ivlen;
1030 CK_NSS_GCM_PARAMS params;
1031 SECStatus rv;
1032
1033 aesreq = fopen(reqfn, "r");
1034 aesresp = stdout;
1035 while (fgets(buf, sizeof buf, aesreq) != NULL) {
1036 /* a comment or blank line */
1037 if (buf[0] == '#' || buf[0] == '\n') {
1038 fputs(buf, aesresp);
1039 continue;
1040 }
1041 /* [ENCRYPT] or [DECRYPT] */
1042 if (buf[0] == '[') {
1043 if (strncmp(buf, "[Taglen", 7) == 0) {
1044 if (sscanf(buf, "[Taglen = %d]", &tagbits) != 1) {
1045 goto loser;
1046 }
1047 taglen = tagbits / 8;
1048 }
1049 if (strncmp(buf, "[IVlen", 6) == 0) {
1050 if (sscanf(buf, "[IVlen = %d]", &ivlen) != 1) {
1051 goto loser;
1052 }
1053 ivlen = ivlen / 8;
1054 }
1055 fputs(buf, aesresp);
1056 continue;
1057 }
1058 /* "COUNT = x" begins a new data set */
1059 if (strncmp(buf, "Count", 5) == 0) {
1060 /* zeroize the variables for the test with this data set */
1061 memset(key, 0, sizeof key);
1062 keysize = 0;
1063 memset(iv, 0, sizeof iv);
1064 memset(plaintext, 0, sizeof plaintext);
1065 plaintextlen = 0;
1066 memset(ciphertext, 0, sizeof ciphertext);
1067 ciphertextlen = 0;
1068 fputs(buf, aesresp);
1069 continue;
1070 }
1071 /* KEY = ... */
1072 if (strncmp(buf, "Key", 3) == 0) {
1073 i = 3;
1074 while (isspace(buf[i]) || buf[i] == '=') {
1075 i++;
1076 }
1077 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1078 hex_to_byteval(&buf[i], &key[j]);
1079 }
1080 keysize = j;
1081 fputs(buf, aesresp);
1082 continue;
1083 }
1084 /* IV = ... */
1085 if (strncmp(buf, "IV", 2) == 0) {
1086 i = 2;
1087 while (isspace(buf[i]) || buf[i] == '=') {
1088 i++;
1089 }
1090 for (j = 0; j < sizeof iv; i += 2, j++) {
1091 hex_to_byteval(&buf[i], &iv[j]);
1092 }
1093 fputs(buf, aesresp);
1094 continue;
1095 }
1096 /* PLAINTEXT = ... */
1097 if (strncmp(buf, "PT", 2) == 0) {
1098 /* sanity check */
1099 if (!encrypt) {
1100 goto loser;
1101 }
1102
1103 i = 2;
1104 while (isspace(buf[i]) || buf[i] == '=') {
1105 i++;
1106 }
1107 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1108 hex_to_byteval(&buf[i], &plaintext[j]);
1109 }
1110 plaintextlen = j;
1111 fputs(buf, aesresp);
1112 continue;
1113 }
1114 /* CIPHERTEXT = ... */
1115 if (strncmp(buf, "CT", 2) == 0) {
1116 /* sanity check */
1117 if (encrypt) {
1118 goto loser;
1119 }
1120
1121 i = 2;
1122 while (isspace(buf[i]) || buf[i] == '=') {
1123 i++;
1124 }
1125 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1126 hex_to_byteval(&buf[i], &ciphertext[j]);
1127 }
1128 ciphertextlen = j;
1129 fputs(buf, aesresp);
1130 continue;
1131 }
1132 if (strncmp(buf, "AAD", 3) == 0) {
1133 i = 3;
1134 while (isspace(buf[i]) || buf[i] == '=') {
1135 i++;
1136 }
1137 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1138 hex_to_byteval(&buf[i], &aad[j]);
1139 }
1140 aadlen = j;
1141 fputs(buf, aesresp);
1142 if (encrypt) {
1143 if (encrypt == 2) {
1144 rv = RNG_GenerateGlobalRandomBytes(iv, ivlen);
1145 if (rv != SECSuccess) {
1146 goto loser;
1147 }
1148 }
1149 params.pIv = iv;
1150 params.ulIvLen = ivlen;
1151 params.pAAD = aad;
1152 params.ulAADLen = aadlen;
1153 params.ulTagBits = tagbits;
1154 rv = aes_encrypt_buf(NSS_AES_GCM, key, keysize,
1155 (unsigned char *)¶ms,
1156 ciphertext, &ciphertextlen, sizeof ciphertext,
1157 plaintext, plaintextlen);
1158 if (rv != SECSuccess) {
1159 goto loser;
1160 }
1161
1162 if (encrypt == 2) {
1163 fputs("IV = ", aesresp);
1164 to_hex_str(buf, iv, ivlen);
1165 fputs(buf, aesresp);
1166 fputc('\n', aesresp);
1167 }
1168 fputs("CT = ", aesresp);
1169 j = ciphertextlen - taglen;
1170 to_hex_str(buf, ciphertext, j);
1171 fputs(buf, aesresp);
1172 fputs("\nTag = ", aesresp);
1173 to_hex_str(buf, ciphertext + j, taglen);
1174 fputs(buf, aesresp);
1175 fputc('\n', aesresp);
1176 }
1177 continue;
1178 }
1179 if (strncmp(buf, "Tag", 3) == 0) {
1180 /* sanity check */
1181 if (encrypt) {
1182 goto loser;
1183 }
1184
1185 i = 3;
1186 while (isspace(buf[i]) || buf[i] == '=') {
1187 i++;
1188 }
1189 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1190 hex_to_byteval(&buf[i], &ciphertext[j + ciphertextlen]);
1191 }
1192 ciphertextlen += j;
1193 params.pIv = iv;
1194 params.ulIvLen = ivlen;
1195 params.pAAD = aad;
1196 params.ulAADLen = aadlen;
1197 params.ulTagBits = tagbits;
1198 rv = aes_decrypt_buf(NSS_AES_GCM, key, keysize,
1199 (unsigned char *)¶ms,
1200 plaintext, &plaintextlen, sizeof plaintext,
1201 ciphertext, ciphertextlen);
1202 fputs(buf, aesresp);
1203 if (rv != SECSuccess) {
1204 fprintf(aesresp, "FAIL\n");
1205 } else {
1206 fputs("PT = ", aesresp);
1207 to_hex_str(buf, plaintext, plaintextlen);
1208 fputs(buf, aesresp);
1209 fputc('\n', aesresp);
1210 }
1211 continue;
1212 }
1213 }
1214 loser:
1215 fclose(aesreq);
1216 }
1217
1218 /*
1219 * Perform the AES Known Answer Test (KAT) or Multi-block Message
1220 * Test (MMT) in ECB or CBC mode. The KAT (there are four types)
1221 * and MMT have the same structure: given the key and IV (CBC mode
1222 * only), encrypt the given plaintext or decrypt the given ciphertext.
1223 * So we can handle them the same way.
1224 *
1225 * reqfn is the pathname of the REQUEST file.
1226 *
1227 * The output RESPONSE file is written to stdout.
1228 */
1229 void
aes_kat_mmt(char * reqfn)1230 aes_kat_mmt(char *reqfn)
1231 {
1232 char buf[512]; /* holds one line from the input REQUEST file.
1233 * needs to be large enough to hold the longest
1234 * line "CIPHERTEXT = <320 hex digits>\n".
1235 */
1236 FILE *aesreq; /* input stream from the REQUEST file */
1237 FILE *aesresp; /* output stream to the RESPONSE file */
1238 int i, j;
1239 int mode = NSS_AES; /* NSS_AES (ECB) or NSS_AES_CBC */
1240 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
1241 unsigned char key[32]; /* 128, 192, or 256 bits */
1242 unsigned int keysize = 0;
1243 unsigned char iv[16]; /* for all modes except ECB */
1244 unsigned char plaintext[10 * 16]; /* 1 to 10 blocks */
1245 unsigned int plaintextlen;
1246 unsigned char ciphertext[10 * 16]; /* 1 to 10 blocks */
1247 unsigned int ciphertextlen;
1248 SECStatus rv;
1249
1250 aesreq = fopen(reqfn, "r");
1251 aesresp = stdout;
1252 while (fgets(buf, sizeof buf, aesreq) != NULL) {
1253 /* a comment or blank line */
1254 if (buf[0] == '#' || buf[0] == '\n') {
1255 fputs(buf, aesresp);
1256 continue;
1257 }
1258 /* [ENCRYPT] or [DECRYPT] */
1259 if (buf[0] == '[') {
1260 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1261 encrypt = 1;
1262 } else {
1263 encrypt = 0;
1264 }
1265 fputs(buf, aesresp);
1266 continue;
1267 }
1268 /* "COUNT = x" begins a new data set */
1269 if (strncmp(buf, "COUNT", 5) == 0) {
1270 mode = NSS_AES;
1271 /* zeroize the variables for the test with this data set */
1272 memset(key, 0, sizeof key);
1273 keysize = 0;
1274 memset(iv, 0, sizeof iv);
1275 memset(plaintext, 0, sizeof plaintext);
1276 plaintextlen = 0;
1277 memset(ciphertext, 0, sizeof ciphertext);
1278 ciphertextlen = 0;
1279 fputs(buf, aesresp);
1280 continue;
1281 }
1282 /* KEY = ... */
1283 if (strncmp(buf, "KEY", 3) == 0) {
1284 i = 3;
1285 while (isspace(buf[i]) || buf[i] == '=') {
1286 i++;
1287 }
1288 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1289 hex_to_byteval(&buf[i], &key[j]);
1290 }
1291 keysize = j;
1292 fputs(buf, aesresp);
1293 continue;
1294 }
1295 /* IV = ... */
1296 if (strncmp(buf, "IV", 2) == 0) {
1297 mode = NSS_AES_CBC;
1298 i = 2;
1299 while (isspace(buf[i]) || buf[i] == '=') {
1300 i++;
1301 }
1302 for (j = 0; j < sizeof iv; i += 2, j++) {
1303 hex_to_byteval(&buf[i], &iv[j]);
1304 }
1305 fputs(buf, aesresp);
1306 continue;
1307 }
1308 /* PLAINTEXT = ... */
1309 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1310 /* sanity check */
1311 if (!encrypt) {
1312 goto loser;
1313 }
1314
1315 i = 9;
1316 while (isspace(buf[i]) || buf[i] == '=') {
1317 i++;
1318 }
1319 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1320 hex_to_byteval(&buf[i], &plaintext[j]);
1321 }
1322 plaintextlen = j;
1323
1324 rv = aes_encrypt_buf(mode, key, keysize,
1325 (mode ==
1326 NSS_AES)
1327 ? NULL
1328 : iv,
1329 ciphertext, &ciphertextlen, sizeof ciphertext,
1330 plaintext, plaintextlen);
1331 if (rv != SECSuccess) {
1332 goto loser;
1333 }
1334
1335 fputs(buf, aesresp);
1336 fputs("CIPHERTEXT = ", aesresp);
1337 to_hex_str(buf, ciphertext, ciphertextlen);
1338 fputs(buf, aesresp);
1339 fputc('\n', aesresp);
1340 continue;
1341 }
1342 /* CIPHERTEXT = ... */
1343 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1344 /* sanity check */
1345 if (encrypt) {
1346 goto loser;
1347 }
1348
1349 i = 10;
1350 while (isspace(buf[i]) || buf[i] == '=') {
1351 i++;
1352 }
1353 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1354 hex_to_byteval(&buf[i], &ciphertext[j]);
1355 }
1356 ciphertextlen = j;
1357
1358 rv = aes_decrypt_buf(mode, key, keysize,
1359 (mode ==
1360 NSS_AES)
1361 ? NULL
1362 : iv,
1363 plaintext, &plaintextlen, sizeof plaintext,
1364 ciphertext, ciphertextlen);
1365 if (rv != SECSuccess) {
1366 goto loser;
1367 }
1368
1369 fputs(buf, aesresp);
1370 fputs("PLAINTEXT = ", aesresp);
1371 to_hex_str(buf, plaintext, plaintextlen);
1372 fputs(buf, aesresp);
1373 fputc('\n', aesresp);
1374 continue;
1375 }
1376 }
1377 loser:
1378 fclose(aesreq);
1379 }
1380
1381 /*
1382 * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
1383 * Test (MCT) in ECB and CBC modes.
1384 */
1385 void
aes_mct_next_key(unsigned char * key,unsigned int keysize,const unsigned char * ciphertext_1,const unsigned char * ciphertext)1386 aes_mct_next_key(unsigned char *key, unsigned int keysize,
1387 const unsigned char *ciphertext_1, const unsigned char *ciphertext)
1388 {
1389 int k;
1390
1391 switch (keysize) {
1392 case 16: /* 128-bit key */
1393 /* Key[i+1] = Key[i] xor CT[j] */
1394 for (k = 0; k < 16; k++) {
1395 key[k] ^= ciphertext[k];
1396 }
1397 break;
1398 case 24: /* 192-bit key */
1399 /*
1400 * Key[i+1] = Key[i] xor (last 64-bits of
1401 * CT[j-1] || CT[j])
1402 */
1403 for (k = 0; k < 8; k++) {
1404 key[k] ^= ciphertext_1[k + 8];
1405 }
1406 for (k = 8; k < 24; k++) {
1407 key[k] ^= ciphertext[k - 8];
1408 }
1409 break;
1410 case 32: /* 256-bit key */
1411 /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
1412 for (k = 0; k < 16; k++) {
1413 key[k] ^= ciphertext_1[k];
1414 }
1415 for (k = 16; k < 32; k++) {
1416 key[k] ^= ciphertext[k - 16];
1417 }
1418 break;
1419 }
1420 }
1421
1422 /*
1423 * Perform the AES Monte Carlo Test (MCT) in ECB mode. MCT exercises
1424 * our AES code in streaming mode because the plaintext or ciphertext
1425 * is generated block by block as we go, so we can't collect all the
1426 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1427 * one shot.
1428 *
1429 * reqfn is the pathname of the input REQUEST file.
1430 *
1431 * The output RESPONSE file is written to stdout.
1432 */
1433 void
aes_ecb_mct(char * reqfn)1434 aes_ecb_mct(char *reqfn)
1435 {
1436 char buf[80]; /* holds one line from the input REQUEST file.
1437 * needs to be large enough to hold the longest
1438 * line "KEY = <64 hex digits>\n".
1439 */
1440 FILE *aesreq; /* input stream from the REQUEST file */
1441 FILE *aesresp; /* output stream to the RESPONSE file */
1442 int i, j;
1443 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
1444 unsigned char key[32]; /* 128, 192, or 256 bits */
1445 unsigned int keysize = 0;
1446 unsigned char plaintext[16]; /* PT[j] */
1447 unsigned char plaintext_1[16]; /* PT[j-1] */
1448 unsigned char ciphertext[16]; /* CT[j] */
1449 unsigned char ciphertext_1[16]; /* CT[j-1] */
1450 unsigned char doublecheck[16];
1451 unsigned int outputlen;
1452 AESContext *cx = NULL; /* the operation being tested */
1453 AESContext *cx2 = NULL; /* the inverse operation done in parallel
1454 * to doublecheck our result.
1455 */
1456 SECStatus rv;
1457
1458 aesreq = fopen(reqfn, "r");
1459 aesresp = stdout;
1460 while (fgets(buf, sizeof buf, aesreq) != NULL) {
1461 /* a comment or blank line */
1462 if (buf[0] == '#' || buf[0] == '\n') {
1463 fputs(buf, aesresp);
1464 continue;
1465 }
1466 /* [ENCRYPT] or [DECRYPT] */
1467 if (buf[0] == '[') {
1468 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1469 encrypt = 1;
1470 } else {
1471 encrypt = 0;
1472 }
1473 fputs(buf, aesresp);
1474 continue;
1475 }
1476 /* "COUNT = x" begins a new data set */
1477 if (strncmp(buf, "COUNT", 5) == 0) {
1478 /* zeroize the variables for the test with this data set */
1479 memset(key, 0, sizeof key);
1480 keysize = 0;
1481 memset(plaintext, 0, sizeof plaintext);
1482 memset(ciphertext, 0, sizeof ciphertext);
1483 continue;
1484 }
1485 /* KEY = ... */
1486 if (strncmp(buf, "KEY", 3) == 0) {
1487 /* Key[0] = Key */
1488 i = 3;
1489 while (isspace(buf[i]) || buf[i] == '=') {
1490 i++;
1491 }
1492 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1493 hex_to_byteval(&buf[i], &key[j]);
1494 }
1495 keysize = j;
1496 continue;
1497 }
1498 /* PLAINTEXT = ... */
1499 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1500 /* sanity check */
1501 if (!encrypt) {
1502 goto loser;
1503 }
1504 /* PT[0] = PT */
1505 i = 9;
1506 while (isspace(buf[i]) || buf[i] == '=') {
1507 i++;
1508 }
1509 for (j = 0; j < sizeof plaintext; i += 2, j++) {
1510 hex_to_byteval(&buf[i], &plaintext[j]);
1511 }
1512
1513 for (i = 0; i < 100; i++) {
1514 sprintf(buf, "COUNT = %d\n", i);
1515 fputs(buf, aesresp);
1516 /* Output Key[i] */
1517 fputs("KEY = ", aesresp);
1518 to_hex_str(buf, key, keysize);
1519 fputs(buf, aesresp);
1520 fputc('\n', aesresp);
1521 /* Output PT[0] */
1522 fputs("PLAINTEXT = ", aesresp);
1523 to_hex_str(buf, plaintext, sizeof plaintext);
1524 fputs(buf, aesresp);
1525 fputc('\n', aesresp);
1526
1527 cx = AES_CreateContext(key, NULL, NSS_AES,
1528 PR_TRUE, keysize, 16);
1529 if (cx == NULL) {
1530 goto loser;
1531 }
1532 /*
1533 * doublecheck our result by decrypting the result
1534 * and comparing the output with the plaintext.
1535 */
1536 cx2 = AES_CreateContext(key, NULL, NSS_AES,
1537 PR_FALSE, keysize, 16);
1538 if (cx2 == NULL) {
1539 goto loser;
1540 }
1541 for (j = 0; j < 1000; j++) {
1542 /* Save CT[j-1] */
1543 memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
1544
1545 /* CT[j] = AES(Key[i], PT[j]) */
1546 outputlen = 0;
1547 rv = AES_Encrypt(cx,
1548 ciphertext, &outputlen, sizeof ciphertext,
1549 plaintext, sizeof plaintext);
1550 if (rv != SECSuccess) {
1551 goto loser;
1552 }
1553 if (outputlen != sizeof plaintext) {
1554 goto loser;
1555 }
1556
1557 /* doublecheck our result */
1558 outputlen = 0;
1559 rv = AES_Decrypt(cx2,
1560 doublecheck, &outputlen, sizeof doublecheck,
1561 ciphertext, sizeof ciphertext);
1562 if (rv != SECSuccess) {
1563 goto loser;
1564 }
1565 if (outputlen != sizeof ciphertext) {
1566 goto loser;
1567 }
1568 if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
1569 goto loser;
1570 }
1571
1572 /* PT[j+1] = CT[j] */
1573 memcpy(plaintext, ciphertext, sizeof plaintext);
1574 }
1575 AES_DestroyContext(cx, PR_TRUE);
1576 cx = NULL;
1577 AES_DestroyContext(cx2, PR_TRUE);
1578 cx2 = NULL;
1579
1580 /* Output CT[j] */
1581 fputs("CIPHERTEXT = ", aesresp);
1582 to_hex_str(buf, ciphertext, sizeof ciphertext);
1583 fputs(buf, aesresp);
1584 fputc('\n', aesresp);
1585
1586 /* Key[i+1] = Key[i] xor ... */
1587 aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
1588 /* PT[0] = CT[j] */
1589 /* done at the end of the for(j) loop */
1590
1591 fputc('\n', aesresp);
1592 }
1593
1594 continue;
1595 }
1596 /* CIPHERTEXT = ... */
1597 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1598 /* sanity check */
1599 if (encrypt) {
1600 goto loser;
1601 }
1602 /* CT[0] = CT */
1603 i = 10;
1604 while (isspace(buf[i]) || buf[i] == '=') {
1605 i++;
1606 }
1607 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1608 hex_to_byteval(&buf[i], &ciphertext[j]);
1609 }
1610
1611 for (i = 0; i < 100; i++) {
1612 sprintf(buf, "COUNT = %d\n", i);
1613 fputs(buf, aesresp);
1614 /* Output Key[i] */
1615 fputs("KEY = ", aesresp);
1616 to_hex_str(buf, key, keysize);
1617 fputs(buf, aesresp);
1618 fputc('\n', aesresp);
1619 /* Output CT[0] */
1620 fputs("CIPHERTEXT = ", aesresp);
1621 to_hex_str(buf, ciphertext, sizeof ciphertext);
1622 fputs(buf, aesresp);
1623 fputc('\n', aesresp);
1624
1625 cx = AES_CreateContext(key, NULL, NSS_AES,
1626 PR_FALSE, keysize, 16);
1627 if (cx == NULL) {
1628 goto loser;
1629 }
1630 /*
1631 * doublecheck our result by encrypting the result
1632 * and comparing the output with the ciphertext.
1633 */
1634 cx2 = AES_CreateContext(key, NULL, NSS_AES,
1635 PR_TRUE, keysize, 16);
1636 if (cx2 == NULL) {
1637 goto loser;
1638 }
1639 for (j = 0; j < 1000; j++) {
1640 /* Save PT[j-1] */
1641 memcpy(plaintext_1, plaintext, sizeof plaintext);
1642
1643 /* PT[j] = AES(Key[i], CT[j]) */
1644 outputlen = 0;
1645 rv = AES_Decrypt(cx,
1646 plaintext, &outputlen, sizeof plaintext,
1647 ciphertext, sizeof ciphertext);
1648 if (rv != SECSuccess) {
1649 goto loser;
1650 }
1651 if (outputlen != sizeof ciphertext) {
1652 goto loser;
1653 }
1654
1655 /* doublecheck our result */
1656 outputlen = 0;
1657 rv = AES_Encrypt(cx2,
1658 doublecheck, &outputlen, sizeof doublecheck,
1659 plaintext, sizeof plaintext);
1660 if (rv != SECSuccess) {
1661 goto loser;
1662 }
1663 if (outputlen != sizeof plaintext) {
1664 goto loser;
1665 }
1666 if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
1667 goto loser;
1668 }
1669
1670 /* CT[j+1] = PT[j] */
1671 memcpy(ciphertext, plaintext, sizeof ciphertext);
1672 }
1673 AES_DestroyContext(cx, PR_TRUE);
1674 cx = NULL;
1675 AES_DestroyContext(cx2, PR_TRUE);
1676 cx2 = NULL;
1677
1678 /* Output PT[j] */
1679 fputs("PLAINTEXT = ", aesresp);
1680 to_hex_str(buf, plaintext, sizeof plaintext);
1681 fputs(buf, aesresp);
1682 fputc('\n', aesresp);
1683
1684 /* Key[i+1] = Key[i] xor ... */
1685 aes_mct_next_key(key, keysize, plaintext_1, plaintext);
1686 /* CT[0] = PT[j] */
1687 /* done at the end of the for(j) loop */
1688
1689 fputc('\n', aesresp);
1690 }
1691
1692 continue;
1693 }
1694 }
1695 loser:
1696 if (cx != NULL) {
1697 AES_DestroyContext(cx, PR_TRUE);
1698 }
1699 if (cx2 != NULL) {
1700 AES_DestroyContext(cx2, PR_TRUE);
1701 }
1702 fclose(aesreq);
1703 }
1704
1705 /*
1706 * Perform the AES Monte Carlo Test (MCT) in CBC mode. MCT exercises
1707 * our AES code in streaming mode because the plaintext or ciphertext
1708 * is generated block by block as we go, so we can't collect all the
1709 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1710 * one shot.
1711 *
1712 * reqfn is the pathname of the input REQUEST file.
1713 *
1714 * The output RESPONSE file is written to stdout.
1715 */
1716 void
aes_cbc_mct(char * reqfn)1717 aes_cbc_mct(char *reqfn)
1718 {
1719 char buf[80]; /* holds one line from the input REQUEST file.
1720 * needs to be large enough to hold the longest
1721 * line "KEY = <64 hex digits>\n".
1722 */
1723 FILE *aesreq; /* input stream from the REQUEST file */
1724 FILE *aesresp; /* output stream to the RESPONSE file */
1725 int i, j;
1726 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
1727 unsigned char key[32]; /* 128, 192, or 256 bits */
1728 unsigned int keysize = 0;
1729 unsigned char iv[16];
1730 unsigned char plaintext[16]; /* PT[j] */
1731 unsigned char plaintext_1[16]; /* PT[j-1] */
1732 unsigned char ciphertext[16]; /* CT[j] */
1733 unsigned char ciphertext_1[16]; /* CT[j-1] */
1734 unsigned char doublecheck[16];
1735 unsigned int outputlen;
1736 AESContext *cx = NULL; /* the operation being tested */
1737 AESContext *cx2 = NULL; /* the inverse operation done in parallel
1738 * to doublecheck our result.
1739 */
1740 SECStatus rv;
1741
1742 aesreq = fopen(reqfn, "r");
1743 aesresp = stdout;
1744 while (fgets(buf, sizeof buf, aesreq) != NULL) {
1745 /* a comment or blank line */
1746 if (buf[0] == '#' || buf[0] == '\n') {
1747 fputs(buf, aesresp);
1748 continue;
1749 }
1750 /* [ENCRYPT] or [DECRYPT] */
1751 if (buf[0] == '[') {
1752 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1753 encrypt = 1;
1754 } else {
1755 encrypt = 0;
1756 }
1757 fputs(buf, aesresp);
1758 continue;
1759 }
1760 /* "COUNT = x" begins a new data set */
1761 if (strncmp(buf, "COUNT", 5) == 0) {
1762 /* zeroize the variables for the test with this data set */
1763 memset(key, 0, sizeof key);
1764 keysize = 0;
1765 memset(iv, 0, sizeof iv);
1766 memset(plaintext, 0, sizeof plaintext);
1767 memset(ciphertext, 0, sizeof ciphertext);
1768 continue;
1769 }
1770 /* KEY = ... */
1771 if (strncmp(buf, "KEY", 3) == 0) {
1772 /* Key[0] = Key */
1773 i = 3;
1774 while (isspace(buf[i]) || buf[i] == '=') {
1775 i++;
1776 }
1777 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1778 hex_to_byteval(&buf[i], &key[j]);
1779 }
1780 keysize = j;
1781 continue;
1782 }
1783 /* IV = ... */
1784 if (strncmp(buf, "IV", 2) == 0) {
1785 /* IV[0] = IV */
1786 i = 2;
1787 while (isspace(buf[i]) || buf[i] == '=') {
1788 i++;
1789 }
1790 for (j = 0; j < sizeof iv; i += 2, j++) {
1791 hex_to_byteval(&buf[i], &iv[j]);
1792 }
1793 continue;
1794 }
1795 /* PLAINTEXT = ... */
1796 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1797 /* sanity check */
1798 if (!encrypt) {
1799 goto loser;
1800 }
1801 /* PT[0] = PT */
1802 i = 9;
1803 while (isspace(buf[i]) || buf[i] == '=') {
1804 i++;
1805 }
1806 for (j = 0; j < sizeof plaintext; i += 2, j++) {
1807 hex_to_byteval(&buf[i], &plaintext[j]);
1808 }
1809
1810 for (i = 0; i < 100; i++) {
1811 sprintf(buf, "COUNT = %d\n", i);
1812 fputs(buf, aesresp);
1813 /* Output Key[i] */
1814 fputs("KEY = ", aesresp);
1815 to_hex_str(buf, key, keysize);
1816 fputs(buf, aesresp);
1817 fputc('\n', aesresp);
1818 /* Output IV[i] */
1819 fputs("IV = ", aesresp);
1820 to_hex_str(buf, iv, sizeof iv);
1821 fputs(buf, aesresp);
1822 fputc('\n', aesresp);
1823 /* Output PT[0] */
1824 fputs("PLAINTEXT = ", aesresp);
1825 to_hex_str(buf, plaintext, sizeof plaintext);
1826 fputs(buf, aesresp);
1827 fputc('\n', aesresp);
1828
1829 cx = AES_CreateContext(key, iv, NSS_AES_CBC,
1830 PR_TRUE, keysize, 16);
1831 if (cx == NULL) {
1832 goto loser;
1833 }
1834 /*
1835 * doublecheck our result by decrypting the result
1836 * and comparing the output with the plaintext.
1837 */
1838 cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
1839 PR_FALSE, keysize, 16);
1840 if (cx2 == NULL) {
1841 goto loser;
1842 }
1843 /* CT[-1] = IV[i] */
1844 memcpy(ciphertext, iv, sizeof ciphertext);
1845 for (j = 0; j < 1000; j++) {
1846 /* Save CT[j-1] */
1847 memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
1848 /*
1849 * If ( j=0 )
1850 * CT[j] = AES(Key[i], IV[i], PT[j])
1851 * PT[j+1] = IV[i] (= CT[j-1])
1852 * Else
1853 * CT[j] = AES(Key[i], PT[j])
1854 * PT[j+1] = CT[j-1]
1855 */
1856 outputlen = 0;
1857 rv = AES_Encrypt(cx,
1858 ciphertext, &outputlen, sizeof ciphertext,
1859 plaintext, sizeof plaintext);
1860 if (rv != SECSuccess) {
1861 goto loser;
1862 }
1863 if (outputlen != sizeof plaintext) {
1864 goto loser;
1865 }
1866
1867 /* doublecheck our result */
1868 outputlen = 0;
1869 rv = AES_Decrypt(cx2,
1870 doublecheck, &outputlen, sizeof doublecheck,
1871 ciphertext, sizeof ciphertext);
1872 if (rv != SECSuccess) {
1873 goto loser;
1874 }
1875 if (outputlen != sizeof ciphertext) {
1876 goto loser;
1877 }
1878 if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
1879 goto loser;
1880 }
1881
1882 memcpy(plaintext, ciphertext_1, sizeof plaintext);
1883 }
1884 AES_DestroyContext(cx, PR_TRUE);
1885 cx = NULL;
1886 AES_DestroyContext(cx2, PR_TRUE);
1887 cx2 = NULL;
1888
1889 /* Output CT[j] */
1890 fputs("CIPHERTEXT = ", aesresp);
1891 to_hex_str(buf, ciphertext, sizeof ciphertext);
1892 fputs(buf, aesresp);
1893 fputc('\n', aesresp);
1894
1895 /* Key[i+1] = Key[i] xor ... */
1896 aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
1897 /* IV[i+1] = CT[j] */
1898 memcpy(iv, ciphertext, sizeof iv);
1899 /* PT[0] = CT[j-1] */
1900 /* done at the end of the for(j) loop */
1901
1902 fputc('\n', aesresp);
1903 }
1904
1905 continue;
1906 }
1907 /* CIPHERTEXT = ... */
1908 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1909 /* sanity check */
1910 if (encrypt) {
1911 goto loser;
1912 }
1913 /* CT[0] = CT */
1914 i = 10;
1915 while (isspace(buf[i]) || buf[i] == '=') {
1916 i++;
1917 }
1918 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1919 hex_to_byteval(&buf[i], &ciphertext[j]);
1920 }
1921
1922 for (i = 0; i < 100; i++) {
1923 sprintf(buf, "COUNT = %d\n", i);
1924 fputs(buf, aesresp);
1925 /* Output Key[i] */
1926 fputs("KEY = ", aesresp);
1927 to_hex_str(buf, key, keysize);
1928 fputs(buf, aesresp);
1929 fputc('\n', aesresp);
1930 /* Output IV[i] */
1931 fputs("IV = ", aesresp);
1932 to_hex_str(buf, iv, sizeof iv);
1933 fputs(buf, aesresp);
1934 fputc('\n', aesresp);
1935 /* Output CT[0] */
1936 fputs("CIPHERTEXT = ", aesresp);
1937 to_hex_str(buf, ciphertext, sizeof ciphertext);
1938 fputs(buf, aesresp);
1939 fputc('\n', aesresp);
1940
1941 cx = AES_CreateContext(key, iv, NSS_AES_CBC,
1942 PR_FALSE, keysize, 16);
1943 if (cx == NULL) {
1944 goto loser;
1945 }
1946 /*
1947 * doublecheck our result by encrypting the result
1948 * and comparing the output with the ciphertext.
1949 */
1950 cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
1951 PR_TRUE, keysize, 16);
1952 if (cx2 == NULL) {
1953 goto loser;
1954 }
1955 /* PT[-1] = IV[i] */
1956 memcpy(plaintext, iv, sizeof plaintext);
1957 for (j = 0; j < 1000; j++) {
1958 /* Save PT[j-1] */
1959 memcpy(plaintext_1, plaintext, sizeof plaintext);
1960 /*
1961 * If ( j=0 )
1962 * PT[j] = AES(Key[i], IV[i], CT[j])
1963 * CT[j+1] = IV[i] (= PT[j-1])
1964 * Else
1965 * PT[j] = AES(Key[i], CT[j])
1966 * CT[j+1] = PT[j-1]
1967 */
1968 outputlen = 0;
1969 rv = AES_Decrypt(cx,
1970 plaintext, &outputlen, sizeof plaintext,
1971 ciphertext, sizeof ciphertext);
1972 if (rv != SECSuccess) {
1973 goto loser;
1974 }
1975 if (outputlen != sizeof ciphertext) {
1976 goto loser;
1977 }
1978
1979 /* doublecheck our result */
1980 outputlen = 0;
1981 rv = AES_Encrypt(cx2,
1982 doublecheck, &outputlen, sizeof doublecheck,
1983 plaintext, sizeof plaintext);
1984 if (rv != SECSuccess) {
1985 goto loser;
1986 }
1987 if (outputlen != sizeof plaintext) {
1988 goto loser;
1989 }
1990 if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
1991 goto loser;
1992 }
1993
1994 memcpy(ciphertext, plaintext_1, sizeof ciphertext);
1995 }
1996 AES_DestroyContext(cx, PR_TRUE);
1997 cx = NULL;
1998 AES_DestroyContext(cx2, PR_TRUE);
1999 cx2 = NULL;
2000
2001 /* Output PT[j] */
2002 fputs("PLAINTEXT = ", aesresp);
2003 to_hex_str(buf, plaintext, sizeof plaintext);
2004 fputs(buf, aesresp);
2005 fputc('\n', aesresp);
2006
2007 /* Key[i+1] = Key[i] xor ... */
2008 aes_mct_next_key(key, keysize, plaintext_1, plaintext);
2009 /* IV[i+1] = PT[j] */
2010 memcpy(iv, plaintext, sizeof iv);
2011 /* CT[0] = PT[j-1] */
2012 /* done at the end of the for(j) loop */
2013
2014 fputc('\n', aesresp);
2015 }
2016
2017 continue;
2018 }
2019 }
2020 loser:
2021 if (cx != NULL) {
2022 AES_DestroyContext(cx, PR_TRUE);
2023 }
2024 if (cx2 != NULL) {
2025 AES_DestroyContext(cx2, PR_TRUE);
2026 }
2027 fclose(aesreq);
2028 }
2029
2030 void
write_compact_string(FILE * out,unsigned char * hash,unsigned int len)2031 write_compact_string(FILE *out, unsigned char *hash, unsigned int len)
2032 {
2033 unsigned int i;
2034 int j, count = 0, last = -1, z = 0;
2035 long start = ftell(out);
2036 for (i = 0; i < len; i++) {
2037 for (j = 7; j >= 0; j--) {
2038 if (last < 0) {
2039 last = (hash[i] & (1 << j)) ? 1 : 0;
2040 fprintf(out, "%d ", last);
2041 count = 1;
2042 } else if (hash[i] & (1 << j)) {
2043 if (last) {
2044 count++;
2045 } else {
2046 last = 0;
2047 fprintf(out, "%d ", count);
2048 count = 1;
2049 z++;
2050 }
2051 } else {
2052 if (!last) {
2053 count++;
2054 } else {
2055 last = 1;
2056 fprintf(out, "%d ", count);
2057 count = 1;
2058 z++;
2059 }
2060 }
2061 }
2062 }
2063 fprintf(out, "^\n");
2064 fseek(out, start, SEEK_SET);
2065 fprintf(out, "%d ", z);
2066 fseek(out, 0, SEEK_END);
2067 }
2068
2069 int
get_next_line(FILE * req,char * key,char * val,FILE * rsp)2070 get_next_line(FILE *req, char *key, char *val, FILE *rsp)
2071 {
2072 int ignore = 0;
2073 char *writeto = key;
2074 int w = 0;
2075 int c;
2076 while ((c = fgetc(req)) != EOF) {
2077 if (ignore) {
2078 fprintf(rsp, "%c", c);
2079 if (c == '\n')
2080 return ignore;
2081 } else if (c == '\n') {
2082 break;
2083 } else if (c == '#') {
2084 ignore = 1;
2085 fprintf(rsp, "%c", c);
2086 } else if (c == '=') {
2087 writeto[w] = '\0';
2088 w = 0;
2089 writeto = val;
2090 } else if (c == ' ' || c == '[' || c == ']') {
2091 continue;
2092 } else {
2093 writeto[w++] = c;
2094 }
2095 }
2096 writeto[w] = '\0';
2097 return (c == EOF) ? -1 : ignore;
2098 }
2099
2100 typedef struct curveNameTagPairStr {
2101 char *curveName;
2102 SECOidTag curveOidTag;
2103 } CurveNameTagPair;
2104
2105 #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
2106 /* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */
2107
2108 static CurveNameTagPair nameTagPair[] =
2109 {
2110 { "sect163k1", SEC_OID_SECG_EC_SECT163K1 },
2111 { "nistk163", SEC_OID_SECG_EC_SECT163K1 },
2112 { "sect163r1", SEC_OID_SECG_EC_SECT163R1 },
2113 { "sect163r2", SEC_OID_SECG_EC_SECT163R2 },
2114 { "nistb163", SEC_OID_SECG_EC_SECT163R2 },
2115 { "sect193r1", SEC_OID_SECG_EC_SECT193R1 },
2116 { "sect193r2", SEC_OID_SECG_EC_SECT193R2 },
2117 { "sect233k1", SEC_OID_SECG_EC_SECT233K1 },
2118 { "nistk233", SEC_OID_SECG_EC_SECT233K1 },
2119 { "sect233r1", SEC_OID_SECG_EC_SECT233R1 },
2120 { "nistb233", SEC_OID_SECG_EC_SECT233R1 },
2121 { "sect239k1", SEC_OID_SECG_EC_SECT239K1 },
2122 { "sect283k1", SEC_OID_SECG_EC_SECT283K1 },
2123 { "nistk283", SEC_OID_SECG_EC_SECT283K1 },
2124 { "sect283r1", SEC_OID_SECG_EC_SECT283R1 },
2125 { "nistb283", SEC_OID_SECG_EC_SECT283R1 },
2126 { "sect409k1", SEC_OID_SECG_EC_SECT409K1 },
2127 { "nistk409", SEC_OID_SECG_EC_SECT409K1 },
2128 { "sect409r1", SEC_OID_SECG_EC_SECT409R1 },
2129 { "nistb409", SEC_OID_SECG_EC_SECT409R1 },
2130 { "sect571k1", SEC_OID_SECG_EC_SECT571K1 },
2131 { "nistk571", SEC_OID_SECG_EC_SECT571K1 },
2132 { "sect571r1", SEC_OID_SECG_EC_SECT571R1 },
2133 { "nistb571", SEC_OID_SECG_EC_SECT571R1 },
2134 { "secp160k1", SEC_OID_SECG_EC_SECP160K1 },
2135 { "secp160r1", SEC_OID_SECG_EC_SECP160R1 },
2136 { "secp160r2", SEC_OID_SECG_EC_SECP160R2 },
2137 { "secp192k1", SEC_OID_SECG_EC_SECP192K1 },
2138 { "secp192r1", SEC_OID_SECG_EC_SECP192R1 },
2139 { "nistp192", SEC_OID_SECG_EC_SECP192R1 },
2140 { "secp224k1", SEC_OID_SECG_EC_SECP224K1 },
2141 { "secp224r1", SEC_OID_SECG_EC_SECP224R1 },
2142 { "nistp224", SEC_OID_SECG_EC_SECP224R1 },
2143 { "secp256k1", SEC_OID_SECG_EC_SECP256K1 },
2144 { "secp256r1", SEC_OID_SECG_EC_SECP256R1 },
2145 { "nistp256", SEC_OID_SECG_EC_SECP256R1 },
2146 { "secp384r1", SEC_OID_SECG_EC_SECP384R1 },
2147 { "nistp384", SEC_OID_SECG_EC_SECP384R1 },
2148 { "secp521r1", SEC_OID_SECG_EC_SECP521R1 },
2149 { "nistp521", SEC_OID_SECG_EC_SECP521R1 },
2150
2151 { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
2152 { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
2153 { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
2154 { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
2155 { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
2156 { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
2157
2158 { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
2159 { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
2160 { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
2161 { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
2162 { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
2163 { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
2164 { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
2165 { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
2166 { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
2167 { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
2168 { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
2169 { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
2170 { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
2171 { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
2172 { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
2173 { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
2174 { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
2175 { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
2176 { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
2177 { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
2178
2179 { "secp112r1", SEC_OID_SECG_EC_SECP112R1 },
2180 { "secp112r2", SEC_OID_SECG_EC_SECP112R2 },
2181 { "secp128r1", SEC_OID_SECG_EC_SECP128R1 },
2182 { "secp128r2", SEC_OID_SECG_EC_SECP128R2 },
2183
2184 { "sect113r1", SEC_OID_SECG_EC_SECT113R1 },
2185 { "sect113r2", SEC_OID_SECG_EC_SECT113R2 },
2186 { "sect131r1", SEC_OID_SECG_EC_SECT131R1 },
2187 { "sect131r2", SEC_OID_SECG_EC_SECT131R2 },
2188 };
2189
2190 static SECItem *
getECParams(const char * curve)2191 getECParams(const char *curve)
2192 {
2193 SECItem *ecparams;
2194 SECOidData *oidData = NULL;
2195 SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
2196 int i, numCurves;
2197
2198 if (curve != NULL) {
2199 numCurves = sizeof(nameTagPair) / sizeof(CurveNameTagPair);
2200 for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN));
2201 i++) {
2202 if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
2203 curveOidTag = nameTagPair[i].curveOidTag;
2204 }
2205 }
2206
2207 /* Return NULL if curve name is not recognized */
2208 if ((curveOidTag == SEC_OID_UNKNOWN) ||
2209 (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
2210 fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
2211 return NULL;
2212 }
2213
2214 ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
2215
2216 /*
2217 * ecparams->data needs to contain the ASN encoding of an object ID (OID)
2218 * representing the named curve. The actual OID is in
2219 * oidData->oid.data so we simply prepend 0x06 and OID length
2220 */
2221 ecparams->data[0] = SEC_ASN1_OBJECT_ID;
2222 ecparams->data[1] = oidData->oid.len;
2223 memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
2224
2225 return ecparams;
2226 }
2227
2228 /*
2229 * HASH_ functions are available to full NSS apps and internally inside
2230 * freebl, but not exported to users of freebl. Create short stubs to
2231 * replace the functionality for fipstest.
2232 */
2233 SECStatus
fips_hashBuf(HASH_HashType type,unsigned char * hashBuf,unsigned char * msg,int len)2234 fips_hashBuf(HASH_HashType type, unsigned char *hashBuf,
2235 unsigned char *msg, int len)
2236 {
2237 SECStatus rv = SECFailure;
2238
2239 switch (type) {
2240 case HASH_AlgSHA1:
2241 rv = SHA1_HashBuf(hashBuf, msg, len);
2242 break;
2243 case HASH_AlgSHA224:
2244 rv = SHA224_HashBuf(hashBuf, msg, len);
2245 break;
2246 case HASH_AlgSHA256:
2247 rv = SHA256_HashBuf(hashBuf, msg, len);
2248 break;
2249 case HASH_AlgSHA384:
2250 rv = SHA384_HashBuf(hashBuf, msg, len);
2251 break;
2252 case HASH_AlgSHA512:
2253 rv = SHA512_HashBuf(hashBuf, msg, len);
2254 break;
2255 default:
2256 break;
2257 }
2258 return rv;
2259 }
2260
2261 int
fips_hashLen(HASH_HashType type)2262 fips_hashLen(HASH_HashType type)
2263 {
2264 int len = 0;
2265
2266 switch (type) {
2267 case HASH_AlgSHA1:
2268 len = SHA1_LENGTH;
2269 break;
2270 case HASH_AlgSHA224:
2271 len = SHA224_LENGTH;
2272 break;
2273 case HASH_AlgSHA256:
2274 len = SHA256_LENGTH;
2275 break;
2276 case HASH_AlgSHA384:
2277 len = SHA384_LENGTH;
2278 break;
2279 case HASH_AlgSHA512:
2280 len = SHA512_LENGTH;
2281 break;
2282 default:
2283 break;
2284 }
2285 return len;
2286 }
2287
2288 SECOidTag
fips_hashOid(HASH_HashType type)2289 fips_hashOid(HASH_HashType type)
2290 {
2291 SECOidTag oid = SEC_OID_UNKNOWN;
2292
2293 switch (type) {
2294 case HASH_AlgSHA1:
2295 oid = SEC_OID_SHA1;
2296 break;
2297 case HASH_AlgSHA224:
2298 oid = SEC_OID_SHA224;
2299 break;
2300 case HASH_AlgSHA256:
2301 oid = SEC_OID_SHA256;
2302 break;
2303 case HASH_AlgSHA384:
2304 oid = SEC_OID_SHA384;
2305 break;
2306 case HASH_AlgSHA512:
2307 oid = SEC_OID_SHA512;
2308 break;
2309 default:
2310 break;
2311 }
2312 return oid;
2313 }
2314
2315 HASH_HashType
sha_get_hashType(int hashbits)2316 sha_get_hashType(int hashbits)
2317 {
2318 HASH_HashType hashType = HASH_AlgNULL;
2319
2320 switch (hashbits) {
2321 case 1:
2322 case (SHA1_LENGTH * PR_BITS_PER_BYTE):
2323 hashType = HASH_AlgSHA1;
2324 break;
2325 case (SHA224_LENGTH * PR_BITS_PER_BYTE):
2326 hashType = HASH_AlgSHA224;
2327 break;
2328 case (SHA256_LENGTH * PR_BITS_PER_BYTE):
2329 hashType = HASH_AlgSHA256;
2330 break;
2331 case (SHA384_LENGTH * PR_BITS_PER_BYTE):
2332 hashType = HASH_AlgSHA384;
2333 break;
2334 case (SHA512_LENGTH * PR_BITS_PER_BYTE):
2335 hashType = HASH_AlgSHA512;
2336 break;
2337 default:
2338 break;
2339 }
2340 return hashType;
2341 }
2342
2343 HASH_HashType
hash_string_to_hashType(const char * src)2344 hash_string_to_hashType(const char *src)
2345 {
2346 HASH_HashType shaAlg = HASH_AlgNULL;
2347 if (strncmp(src, "SHA-1", 5) == 0) {
2348 shaAlg = HASH_AlgSHA1;
2349 } else if (strncmp(src, "SHA-224", 7) == 0) {
2350 shaAlg = HASH_AlgSHA224;
2351 } else if (strncmp(src, "SHA-256", 7) == 0) {
2352 shaAlg = HASH_AlgSHA256;
2353 } else if (strncmp(src, "SHA-384", 7) == 0) {
2354 shaAlg = HASH_AlgSHA384;
2355 } else if (strncmp(src, "SHA-512", 7) == 0) {
2356 shaAlg = HASH_AlgSHA512;
2357 } else if (strncmp(src, "SHA1", 4) == 0) {
2358 shaAlg = HASH_AlgSHA1;
2359 } else if (strncmp(src, "SHA224", 6) == 0) {
2360 shaAlg = HASH_AlgSHA224;
2361 } else if (strncmp(src, "SHA256", 6) == 0) {
2362 shaAlg = HASH_AlgSHA256;
2363 } else if (strncmp(src, "SHA384", 6) == 0) {
2364 shaAlg = HASH_AlgSHA384;
2365 } else if (strncmp(src, "SHA512", 6) == 0) {
2366 shaAlg = HASH_AlgSHA512;
2367 }
2368 return shaAlg;
2369 }
2370
2371 /*
2372 * Perform the ECDSA Key Pair Generation Test.
2373 *
2374 * reqfn is the pathname of the REQUEST file.
2375 *
2376 * The output RESPONSE file is written to stdout.
2377 */
2378 void
ecdsa_keypair_test(char * reqfn)2379 ecdsa_keypair_test(char *reqfn)
2380 {
2381 char buf[256]; /* holds one line from the input REQUEST file
2382 * or to the output RESPONSE file.
2383 * needs to be large enough to hold the longest
2384 * line "Qx = <144 hex digits>\n".
2385 */
2386 FILE *ecdsareq; /* input stream from the REQUEST file */
2387 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2388 char curve[16]; /* "nistxddd" */
2389 ECParams *ecparams = NULL;
2390 int N;
2391 int i;
2392 unsigned int len;
2393
2394 ecdsareq = fopen(reqfn, "r");
2395 ecdsaresp = stdout;
2396 strcpy(curve, "nist");
2397 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2398 /* a comment or blank line */
2399 if (buf[0] == '#' || buf[0] == '\n') {
2400 fputs(buf, ecdsaresp);
2401 continue;
2402 }
2403 /* [X-ddd] */
2404 if (buf[0] == '[') {
2405 const char *src;
2406 char *dst;
2407 SECItem *encodedparams;
2408
2409 if (buf[1] == 'B') {
2410 fputs(buf, ecdsaresp);
2411 continue;
2412 }
2413 if (ecparams) {
2414 PORT_FreeArena(ecparams->arena, PR_FALSE);
2415 ecparams = NULL;
2416 }
2417
2418 src = &buf[1];
2419 dst = &curve[4];
2420 *dst++ = tolower(*src);
2421 src += 2; /* skip the hyphen */
2422 *dst++ = *src++;
2423 *dst++ = *src++;
2424 *dst++ = *src++;
2425 *dst = '\0';
2426 encodedparams = getECParams(curve);
2427 if (encodedparams == NULL) {
2428 fprintf(stderr, "Unknown curve %s.", curve);
2429 goto loser;
2430 }
2431 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2432 fprintf(stderr, "Curve %s not supported.\n", curve);
2433 goto loser;
2434 }
2435 SECITEM_FreeItem(encodedparams, PR_TRUE);
2436 fputs(buf, ecdsaresp);
2437 continue;
2438 }
2439 /* N = x */
2440 if (buf[0] == 'N') {
2441 if (sscanf(buf, "N = %d", &N) != 1) {
2442 goto loser;
2443 }
2444 for (i = 0; i < N; i++) {
2445 ECPrivateKey *ecpriv;
2446
2447 if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
2448 goto loser;
2449 }
2450 fputs("d = ", ecdsaresp);
2451 to_hex_str(buf, ecpriv->privateValue.data,
2452 ecpriv->privateValue.len);
2453 fputs(buf, ecdsaresp);
2454 fputc('\n', ecdsaresp);
2455 if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue) !=
2456 SECSuccess) {
2457 goto loser;
2458 }
2459 len = ecpriv->publicValue.len;
2460 if (len % 2 == 0) {
2461 goto loser;
2462 }
2463 len = (len - 1) / 2;
2464 if (ecpriv->publicValue.data[0] !=
2465 EC_POINT_FORM_UNCOMPRESSED) {
2466 goto loser;
2467 }
2468 fputs("Qx = ", ecdsaresp);
2469 to_hex_str(buf, &ecpriv->publicValue.data[1], len);
2470 fputs(buf, ecdsaresp);
2471 fputc('\n', ecdsaresp);
2472 fputs("Qy = ", ecdsaresp);
2473 to_hex_str(buf, &ecpriv->publicValue.data[1 + len], len);
2474 fputs(buf, ecdsaresp);
2475 fputc('\n', ecdsaresp);
2476 fputc('\n', ecdsaresp);
2477 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
2478 }
2479 continue;
2480 }
2481 }
2482 loser:
2483 if (ecparams) {
2484 PORT_FreeArena(ecparams->arena, PR_FALSE);
2485 ecparams = NULL;
2486 }
2487 fclose(ecdsareq);
2488 }
2489
2490 /*
2491 * Perform the ECDSA Public Key Validation Test.
2492 *
2493 * reqfn is the pathname of the REQUEST file.
2494 *
2495 * The output RESPONSE file is written to stdout.
2496 */
2497 void
ecdsa_pkv_test(char * reqfn)2498 ecdsa_pkv_test(char *reqfn)
2499 {
2500 char buf[256]; /* holds one line from the input REQUEST file.
2501 * needs to be large enough to hold the longest
2502 * line "Qx = <144 hex digits>\n".
2503 */
2504 FILE *ecdsareq; /* input stream from the REQUEST file */
2505 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2506 char curve[16]; /* "nistxddd" */
2507 ECParams *ecparams = NULL;
2508 SECItem pubkey;
2509 unsigned int i;
2510 unsigned int len = 0;
2511 PRBool keyvalid = PR_TRUE;
2512
2513 ecdsareq = fopen(reqfn, "r");
2514 ecdsaresp = stdout;
2515 strcpy(curve, "nist");
2516 pubkey.data = NULL;
2517 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2518 /* a comment or blank line */
2519 if (buf[0] == '#' || buf[0] == '\n') {
2520 fputs(buf, ecdsaresp);
2521 continue;
2522 }
2523 /* [X-ddd] */
2524 if (buf[0] == '[') {
2525 const char *src;
2526 char *dst;
2527 SECItem *encodedparams;
2528
2529 src = &buf[1];
2530 dst = &curve[4];
2531 *dst++ = tolower(*src);
2532 src += 2; /* skip the hyphen */
2533 *dst++ = *src++;
2534 *dst++ = *src++;
2535 *dst++ = *src++;
2536 *dst = '\0';
2537 if (ecparams != NULL) {
2538 PORT_FreeArena(ecparams->arena, PR_FALSE);
2539 ecparams = NULL;
2540 }
2541 encodedparams = getECParams(curve);
2542 if (encodedparams == NULL) {
2543 fprintf(stderr, "Unknown curve %s.", curve);
2544 goto loser;
2545 }
2546 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2547 fprintf(stderr, "Curve %s not supported.\n", curve);
2548 goto loser;
2549 }
2550 SECITEM_FreeItem(encodedparams, PR_TRUE);
2551 len = (ecparams->fieldID.size + 7) >> 3;
2552 if (pubkey.data != NULL) {
2553 PORT_Free(pubkey.data);
2554 pubkey.data = NULL;
2555 }
2556 SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(ecparams));
2557 if (pubkey.data == NULL) {
2558 goto loser;
2559 }
2560 pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
2561 fputs(buf, ecdsaresp);
2562 continue;
2563 }
2564 /* Qx = ... */
2565 if (strncmp(buf, "Qx", 2) == 0) {
2566 fputs(buf, ecdsaresp);
2567 i = 2;
2568 while (isspace(buf[i]) || buf[i] == '=') {
2569 i++;
2570 }
2571 keyvalid = from_hex_str(&pubkey.data[1], len, &buf[i]);
2572 continue;
2573 }
2574 /* Qy = ... */
2575 if (strncmp(buf, "Qy", 2) == 0) {
2576 fputs(buf, ecdsaresp);
2577 if (!keyvalid) {
2578 fputs("Result = F\n", ecdsaresp);
2579 continue;
2580 }
2581 i = 2;
2582 while (isspace(buf[i]) || buf[i] == '=') {
2583 i++;
2584 }
2585 keyvalid = from_hex_str(&pubkey.data[1 + len], len, &buf[i]);
2586 if (!keyvalid) {
2587 fputs("Result = F\n", ecdsaresp);
2588 continue;
2589 }
2590 if (EC_ValidatePublicKey(ecparams, &pubkey) == SECSuccess) {
2591 fputs("Result = P\n", ecdsaresp);
2592 } else if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
2593 fputs("Result = F\n", ecdsaresp);
2594 } else {
2595 goto loser;
2596 }
2597 continue;
2598 }
2599 }
2600 loser:
2601 if (ecparams != NULL) {
2602 PORT_FreeArena(ecparams->arena, PR_FALSE);
2603 }
2604 if (pubkey.data != NULL) {
2605 PORT_Free(pubkey.data);
2606 }
2607 fclose(ecdsareq);
2608 }
2609
2610 /*
2611 * Perform the ECDSA Signature Generation Test.
2612 *
2613 * reqfn is the pathname of the REQUEST file.
2614 *
2615 * The output RESPONSE file is written to stdout.
2616 */
2617 void
ecdsa_siggen_test(char * reqfn)2618 ecdsa_siggen_test(char *reqfn)
2619 {
2620 char buf[1024]; /* holds one line from the input REQUEST file
2621 * or to the output RESPONSE file.
2622 * needs to be large enough to hold the longest
2623 * line "Msg = <256 hex digits>\n".
2624 */
2625 FILE *ecdsareq; /* input stream from the REQUEST file */
2626 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2627 char curve[16]; /* "nistxddd" */
2628 ECParams *ecparams = NULL;
2629 int i, j;
2630 unsigned int len;
2631 unsigned char msg[512]; /* message to be signed (<= 128 bytes) */
2632 unsigned int msglen;
2633 unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
2634 unsigned int shaLength = 0; /* length of SHA */
2635 HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
2636 unsigned char sig[2 * MAX_ECKEY_LEN];
2637 SECItem signature, digest;
2638
2639 ecdsareq = fopen(reqfn, "r");
2640 ecdsaresp = stdout;
2641 strcpy(curve, "nist");
2642 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2643 /* a comment or blank line */
2644 if (buf[0] == '#' || buf[0] == '\n') {
2645 fputs(buf, ecdsaresp);
2646 continue;
2647 }
2648 /* [X-ddd] */
2649 if (buf[0] == '[') {
2650 const char *src;
2651 char *dst;
2652 SECItem *encodedparams;
2653
2654 src = &buf[1];
2655 dst = &curve[4];
2656 *dst++ = tolower(*src);
2657 src += 2; /* skip the hyphen */
2658 *dst++ = *src++;
2659 *dst++ = *src++;
2660 *dst++ = *src++;
2661 *dst = '\0';
2662 src++; /* skip the comma */
2663 /* set the SHA Algorithm */
2664 shaAlg = hash_string_to_hashType(src);
2665 if (shaAlg == HASH_AlgNULL) {
2666 fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type");
2667 goto loser;
2668 }
2669 if (ecparams != NULL) {
2670 PORT_FreeArena(ecparams->arena, PR_FALSE);
2671 ecparams = NULL;
2672 }
2673 encodedparams = getECParams(curve);
2674 if (encodedparams == NULL) {
2675 fprintf(stderr, "Unknown curve %s.", curve);
2676 goto loser;
2677 }
2678 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2679 fprintf(stderr, "Curve %s not supported.\n", curve);
2680 goto loser;
2681 }
2682 SECITEM_FreeItem(encodedparams, PR_TRUE);
2683 fputs(buf, ecdsaresp);
2684 continue;
2685 }
2686 /* Msg = ... */
2687 if (strncmp(buf, "Msg", 3) == 0) {
2688 ECPrivateKey *ecpriv;
2689
2690 i = 3;
2691 while (isspace(buf[i]) || buf[i] == '=') {
2692 i++;
2693 }
2694 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
2695 hex_to_byteval(&buf[i], &msg[j]);
2696 }
2697 msglen = j;
2698 shaLength = fips_hashLen(shaAlg);
2699 if (fips_hashBuf(shaAlg, sha, msg, msglen) != SECSuccess) {
2700 if (shaLength == 0) {
2701 fprintf(ecdsaresp, "ERROR: SHAAlg not defined.");
2702 }
2703 fprintf(ecdsaresp, "ERROR: Unable to generate SHA%x",
2704 shaLength == 160 ? 1 : shaLength);
2705 goto loser;
2706 }
2707 fputs(buf, ecdsaresp);
2708
2709 if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
2710 goto loser;
2711 }
2712 if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue) !=
2713 SECSuccess) {
2714 goto loser;
2715 }
2716 len = ecpriv->publicValue.len;
2717 if (len % 2 == 0) {
2718 goto loser;
2719 }
2720 len = (len - 1) / 2;
2721 if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
2722 goto loser;
2723 }
2724 fputs("Qx = ", ecdsaresp);
2725 to_hex_str(buf, &ecpriv->publicValue.data[1], len);
2726 fputs(buf, ecdsaresp);
2727 fputc('\n', ecdsaresp);
2728 fputs("Qy = ", ecdsaresp);
2729 to_hex_str(buf, &ecpriv->publicValue.data[1 + len], len);
2730 fputs(buf, ecdsaresp);
2731 fputc('\n', ecdsaresp);
2732
2733 digest.type = siBuffer;
2734 digest.data = sha;
2735 digest.len = shaLength;
2736 signature.type = siBuffer;
2737 signature.data = sig;
2738 signature.len = sizeof sig;
2739 if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) {
2740 goto loser;
2741 }
2742 len = signature.len;
2743 if (len % 2 != 0) {
2744 goto loser;
2745 }
2746 len = len / 2;
2747 fputs("R = ", ecdsaresp);
2748 to_hex_str(buf, &signature.data[0], len);
2749 fputs(buf, ecdsaresp);
2750 fputc('\n', ecdsaresp);
2751 fputs("S = ", ecdsaresp);
2752 to_hex_str(buf, &signature.data[len], len);
2753 fputs(buf, ecdsaresp);
2754 fputc('\n', ecdsaresp);
2755
2756 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
2757 continue;
2758 }
2759 }
2760 loser:
2761 if (ecparams != NULL) {
2762 PORT_FreeArena(ecparams->arena, PR_FALSE);
2763 }
2764 fclose(ecdsareq);
2765 }
2766
2767 /*
2768 * Perform the ECDSA Signature Verification Test.
2769 *
2770 * reqfn is the pathname of the REQUEST file.
2771 *
2772 * The output RESPONSE file is written to stdout.
2773 */
2774 void
ecdsa_sigver_test(char * reqfn)2775 ecdsa_sigver_test(char *reqfn)
2776 {
2777 char buf[1024]; /* holds one line from the input REQUEST file.
2778 * needs to be large enough to hold the longest
2779 * line "Msg = <256 hex digits>\n".
2780 */
2781 FILE *ecdsareq; /* input stream from the REQUEST file */
2782 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2783 char curve[16]; /* "nistxddd" */
2784 ECPublicKey ecpub;
2785 unsigned int i, j;
2786 unsigned int flen = 0; /* length in bytes of the field size */
2787 unsigned int olen = 0; /* length in bytes of the base point order */
2788 unsigned char msg[512]; /* message that was signed (<= 128 bytes) */
2789 unsigned int msglen = 0;
2790 unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
2791 unsigned int shaLength = 0; /* length of SHA */
2792 HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
2793 unsigned char sig[2 * MAX_ECKEY_LEN];
2794 SECItem signature, digest;
2795 PRBool keyvalid = PR_TRUE;
2796 PRBool sigvalid = PR_TRUE;
2797
2798 ecdsareq = fopen(reqfn, "r");
2799 ecdsaresp = stdout;
2800 ecpub.ecParams.arena = NULL;
2801 strcpy(curve, "nist");
2802 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2803 /* a comment or blank line */
2804 if (buf[0] == '#' || buf[0] == '\n') {
2805 fputs(buf, ecdsaresp);
2806 continue;
2807 }
2808 /* [X-ddd] */
2809 if (buf[0] == '[') {
2810 const char *src;
2811 char *dst;
2812 SECItem *encodedparams;
2813 ECParams *ecparams;
2814
2815 src = &buf[1];
2816 dst = &curve[4];
2817 *dst++ = tolower(*src);
2818 src += 2; /* skip the hyphen */
2819 *dst++ = *src++;
2820 *dst++ = *src++;
2821 *dst++ = *src++;
2822 *dst = '\0';
2823 src++; /* skip the comma */
2824 /* set the SHA Algorithm */
2825 shaAlg = hash_string_to_hashType(src);
2826 if (shaAlg == HASH_AlgNULL) {
2827 fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type");
2828 goto loser;
2829 }
2830 encodedparams = getECParams(curve);
2831 if (encodedparams == NULL) {
2832 fprintf(stderr, "Unknown curve %s.", curve);
2833 goto loser;
2834 }
2835 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2836 fprintf(stderr, "Curve %s not supported.\n", curve);
2837 goto loser;
2838 }
2839 SECITEM_FreeItem(encodedparams, PR_TRUE);
2840 if (ecpub.ecParams.arena != NULL) {
2841 PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
2842 }
2843 ecpub.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2844 if (ecpub.ecParams.arena == NULL) {
2845 goto loser;
2846 }
2847 if (EC_CopyParams(ecpub.ecParams.arena, &ecpub.ecParams, ecparams) !=
2848 SECSuccess) {
2849 goto loser;
2850 }
2851 PORT_FreeArena(ecparams->arena, PR_FALSE);
2852 flen = (ecpub.ecParams.fieldID.size + 7) >> 3;
2853 olen = ecpub.ecParams.order.len;
2854 if (2 * olen > sizeof sig) {
2855 goto loser;
2856 }
2857 ecpub.publicValue.type = siBuffer;
2858 ecpub.publicValue.data = NULL;
2859 ecpub.publicValue.len = 0;
2860 SECITEM_AllocItem(ecpub.ecParams.arena,
2861 &ecpub.publicValue, 2 * flen + 1);
2862 if (ecpub.publicValue.data == NULL) {
2863 goto loser;
2864 }
2865 ecpub.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED;
2866 fputs(buf, ecdsaresp);
2867 continue;
2868 }
2869 /* Msg = ... */
2870 if (strncmp(buf, "Msg", 3) == 0) {
2871 i = 3;
2872 while (isspace(buf[i]) || buf[i] == '=') {
2873 i++;
2874 }
2875 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
2876 hex_to_byteval(&buf[i], &msg[j]);
2877 }
2878 msglen = j;
2879 shaLength = fips_hashLen(shaAlg);
2880 if (fips_hashBuf(shaAlg, sha, msg, msglen) != SECSuccess) {
2881 if (shaLength == 0) {
2882 fprintf(ecdsaresp, "ERROR: SHAAlg not defined.");
2883 }
2884 fprintf(ecdsaresp, "ERROR: Unable to generate SHA%x",
2885 shaLength == 160 ? 1 : shaLength);
2886 goto loser;
2887 }
2888 fputs(buf, ecdsaresp);
2889
2890 digest.type = siBuffer;
2891 digest.data = sha;
2892 digest.len = shaLength;
2893
2894 continue;
2895 }
2896 /* Qx = ... */
2897 if (strncmp(buf, "Qx", 2) == 0) {
2898 fputs(buf, ecdsaresp);
2899 i = 2;
2900 while (isspace(buf[i]) || buf[i] == '=') {
2901 i++;
2902 }
2903 keyvalid = from_hex_str(&ecpub.publicValue.data[1], flen,
2904 &buf[i]);
2905 continue;
2906 }
2907 /* Qy = ... */
2908 if (strncmp(buf, "Qy", 2) == 0) {
2909 fputs(buf, ecdsaresp);
2910 if (!keyvalid) {
2911 continue;
2912 }
2913 i = 2;
2914 while (isspace(buf[i]) || buf[i] == '=') {
2915 i++;
2916 }
2917 keyvalid = from_hex_str(&ecpub.publicValue.data[1 + flen], flen,
2918 &buf[i]);
2919 if (!keyvalid) {
2920 continue;
2921 }
2922 if (EC_ValidatePublicKey(&ecpub.ecParams, &ecpub.publicValue) !=
2923 SECSuccess) {
2924 if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
2925 keyvalid = PR_FALSE;
2926 } else {
2927 goto loser;
2928 }
2929 }
2930 continue;
2931 }
2932 /* R = ... */
2933 if (buf[0] == 'R') {
2934 fputs(buf, ecdsaresp);
2935 i = 1;
2936 while (isspace(buf[i]) || buf[i] == '=') {
2937 i++;
2938 }
2939 sigvalid = from_hex_str(sig, olen, &buf[i]);
2940 continue;
2941 }
2942 /* S = ... */
2943 if (buf[0] == 'S') {
2944 fputs(buf, ecdsaresp);
2945 i = 1;
2946 while (isspace(buf[i]) || buf[i] == '=') {
2947 i++;
2948 }
2949 if (sigvalid) {
2950 sigvalid = from_hex_str(&sig[olen], olen, &buf[i]);
2951 }
2952 signature.type = siBuffer;
2953 signature.data = sig;
2954 signature.len = 2 * olen;
2955
2956 if (!keyvalid || !sigvalid) {
2957 fputs("Result = F\n", ecdsaresp);
2958 } else if (ECDSA_VerifyDigest(&ecpub, &signature, &digest) ==
2959 SECSuccess) {
2960 fputs("Result = P\n", ecdsaresp);
2961 } else {
2962 fputs("Result = F\n", ecdsaresp);
2963 }
2964 continue;
2965 }
2966 }
2967 loser:
2968 if (ecpub.ecParams.arena != NULL) {
2969 PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
2970 }
2971 fclose(ecdsareq);
2972 }
2973
2974 /*
2975 * Perform the ECDH Functional Test.
2976 *
2977 * reqfn is the pathname of the REQUEST file.
2978 *
2979 * The output RESPONSE file is written to stdout.
2980 */
2981 #define MAX_ECC_PARAMS 256
2982 void
ecdh_functional(char * reqfn,PRBool response)2983 ecdh_functional(char *reqfn, PRBool response)
2984 {
2985 char buf[256]; /* holds one line from the input REQUEST file.
2986 * needs to be large enough to hold the longest
2987 * line "Qx = <144 hex digits>\n".
2988 */
2989 FILE *ecdhreq; /* input stream from the REQUEST file */
2990 FILE *ecdhresp; /* output stream to the RESPONSE file */
2991 char curve[16]; /* "nistxddd" */
2992 unsigned char hashBuf[HASH_LENGTH_MAX];
2993 ECParams *ecparams[MAX_ECC_PARAMS] = { NULL };
2994 ECPrivateKey *ecpriv = NULL;
2995 ECParams *current_ecparams = NULL;
2996 SECItem pubkey;
2997 SECItem ZZ;
2998 unsigned int i;
2999 unsigned int len = 0;
3000 unsigned int uit_len = 0;
3001 int current_curve = -1;
3002 HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
3003
3004 ecdhreq = fopen(reqfn, "r");
3005 ecdhresp = stdout;
3006 strcpy(curve, "nist");
3007 pubkey.data = NULL;
3008 while (fgets(buf, sizeof buf, ecdhreq) != NULL) {
3009 /* a comment or blank line */
3010 if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
3011 fputs(buf, ecdhresp);
3012 continue;
3013 }
3014 if (buf[0] == '[') {
3015 /* [Ex] */
3016 if (buf[1] == 'E' && buf[3] == ']') {
3017 current_curve = buf[2] - 'A';
3018 fputs(buf, ecdhresp);
3019 continue;
3020 }
3021 /* [Curve selected: x-nnn */
3022 if (strncmp(buf, "[Curve ", 7) == 0) {
3023 const char *src;
3024 char *dst;
3025 SECItem *encodedparams;
3026
3027 if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) {
3028 fprintf(stderr, "No curve type defined\n");
3029 goto loser;
3030 }
3031
3032 src = &buf[1];
3033 /* skip passed the colon */
3034 while (*src && *src != ':')
3035 src++;
3036 if (*src != ':') {
3037 fprintf(stderr,
3038 "No colon in curve selected statement\n%s", buf);
3039 goto loser;
3040 }
3041 src++;
3042 /* skip to the first non-space */
3043 while (*src && *src == ' ')
3044 src++;
3045 dst = &curve[4];
3046 *dst++ = tolower(*src);
3047 src += 2; /* skip the hyphen */
3048 *dst++ = *src++;
3049 *dst++ = *src++;
3050 *dst++ = *src++;
3051 *dst = '\0';
3052 if (ecparams[current_curve] != NULL) {
3053 PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE);
3054 ecparams[current_curve] = NULL;
3055 }
3056 encodedparams = getECParams(curve);
3057 if (encodedparams == NULL) {
3058 fprintf(stderr, "Unknown curve %s.", curve);
3059 goto loser;
3060 }
3061 if (EC_DecodeParams(encodedparams, &ecparams[current_curve]) != SECSuccess) {
3062 fprintf(stderr, "Curve %s not supported.\n", curve);
3063 goto loser;
3064 }
3065 SECITEM_FreeItem(encodedparams, PR_TRUE);
3066 fputs(buf, ecdhresp);
3067 continue;
3068 }
3069 /* [Ex - SHAxxx] */
3070 if (buf[1] == 'E' && buf[3] == ' ') {
3071 const char *src;
3072 current_curve = buf[2] - 'A';
3073 if ((current_curve < 0) || (current_curve > 256)) {
3074 fprintf(stderr, "bad curve type defined (%c)\n", buf[2]);
3075 goto loser;
3076 }
3077 current_ecparams = ecparams[current_curve];
3078 if (current_ecparams == NULL) {
3079 fprintf(stderr, "no curve defined for type %c defined\n",
3080 buf[2]);
3081 goto loser;
3082 }
3083 /* skip passed the colon */
3084 src = &buf[1];
3085 while (*src && *src != '-')
3086 src++;
3087 if (*src != '-') {
3088 fprintf(stderr,
3089 "No data in curve selected statement\n%s", buf);
3090 goto loser;
3091 }
3092 src++;
3093 /* skip to the first non-space */
3094 while (*src && *src == ' ')
3095 src++;
3096 hash = hash_string_to_hashType(src);
3097 if (hash == HASH_AlgNULL) {
3098 fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type");
3099 goto loser;
3100 }
3101 fputs(buf, ecdhresp);
3102 continue;
3103 }
3104 fputs(buf, ecdhresp);
3105 continue;
3106 }
3107 /* COUNT = ... */
3108 if (strncmp(buf, "COUNT", 5) == 0) {
3109 fputs(buf, ecdhresp);
3110 if (current_ecparams == NULL) {
3111 fprintf(stderr, "no curve defined for type %c defined\n",
3112 buf[2]);
3113 goto loser;
3114 }
3115 len = (current_ecparams->fieldID.size + 7) >> 3;
3116 if (pubkey.data != NULL) {
3117 PORT_Free(pubkey.data);
3118 pubkey.data = NULL;
3119 }
3120 SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams));
3121 if (pubkey.data == NULL) {
3122 goto loser;
3123 }
3124 pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
3125 continue;
3126 }
3127 /* QeCAVSx = ... */
3128 if (strncmp(buf, "QeCAVSx", 7) == 0) {
3129 fputs(buf, ecdhresp);
3130 i = 7;
3131 while (isspace(buf[i]) || buf[i] == '=') {
3132 i++;
3133 }
3134 from_hex_str(&pubkey.data[1], len, &buf[i]);
3135 continue;
3136 }
3137 /* QeCAVSy = ... */
3138 if (strncmp(buf, "QeCAVSy", 7) == 0) {
3139 fputs(buf, ecdhresp);
3140 i = 7;
3141 while (isspace(buf[i]) || buf[i] == '=') {
3142 i++;
3143 }
3144 from_hex_str(&pubkey.data[1 + len], len, &buf[i]);
3145 if (current_ecparams == NULL) {
3146 fprintf(stderr, "no curve defined\n");
3147 goto loser;
3148 }
3149 /* validate CAVS public key */
3150 if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) {
3151 fprintf(stderr, "BAD key detected\n");
3152 goto loser;
3153 }
3154
3155 /* generate ECC key pair */
3156 if (EC_NewKey(current_ecparams, &ecpriv) != SECSuccess) {
3157 fprintf(stderr, "Failed to generate new key\n");
3158 goto loser;
3159 }
3160 /* validate UIT generated public key */
3161 if (EC_ValidatePublicKey(current_ecparams, &ecpriv->publicValue) !=
3162 SECSuccess) {
3163 fprintf(stderr, "generate key did not validate\n");
3164 goto loser;
3165 }
3166 /* output UIT public key */
3167 uit_len = ecpriv->publicValue.len;
3168 if (uit_len % 2 == 0) {
3169 fprintf(stderr, "generate key had invalid public value len\n");
3170 goto loser;
3171 }
3172 uit_len = (uit_len - 1) / 2;
3173 if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
3174 fprintf(stderr, "generate key was compressed\n");
3175 goto loser;
3176 }
3177 fputs("deIUT = ", ecdhresp);
3178 to_hex_str(buf, ecpriv->privateValue.data, ecpriv->privateValue.len);
3179 fputs(buf, ecdhresp);
3180 fputc('\n', ecdhresp);
3181 fputs("QeIUTx = ", ecdhresp);
3182 to_hex_str(buf, &ecpriv->publicValue.data[1], uit_len);
3183 fputs(buf, ecdhresp);
3184 fputc('\n', ecdhresp);
3185 fputs("QeIUTy = ", ecdhresp);
3186 to_hex_str(buf, &ecpriv->publicValue.data[1 + uit_len], uit_len);
3187 fputs(buf, ecdhresp);
3188 fputc('\n', ecdhresp);
3189 /* ECDH */
3190 if (ECDH_Derive(&pubkey, current_ecparams, &ecpriv->privateValue,
3191 PR_FALSE, &ZZ) != SECSuccess) {
3192 fprintf(stderr, "Derive failed\n");
3193 goto loser;
3194 }
3195 /* output hash of ZZ */
3196 if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
3197 fprintf(stderr, "hash of derived key failed\n");
3198 goto loser;
3199 }
3200 SECITEM_FreeItem(&ZZ, PR_FALSE);
3201 fputs("HashZZ = ", ecdhresp);
3202 to_hex_str(buf, hashBuf, fips_hashLen(hash));
3203 fputs(buf, ecdhresp);
3204 fputc('\n', ecdhresp);
3205 fputc('\n', ecdhresp);
3206 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
3207 ecpriv = NULL;
3208 continue;
3209 }
3210 }
3211 loser:
3212 if (ecpriv != NULL) {
3213 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
3214 }
3215 for (i = 0; i < MAX_ECC_PARAMS; i++) {
3216 if (ecparams[i] != NULL) {
3217 PORT_FreeArena(ecparams[i]->arena, PR_FALSE);
3218 ecparams[i] = NULL;
3219 }
3220 }
3221 if (pubkey.data != NULL) {
3222 PORT_Free(pubkey.data);
3223 }
3224 fclose(ecdhreq);
3225 }
3226
3227 /*
3228 * Perform the ECDH Validity Test.
3229 *
3230 * reqfn is the pathname of the REQUEST file.
3231 *
3232 * The output RESPONSE file is written to stdout.
3233 */
3234 void
ecdh_verify(char * reqfn,PRBool response)3235 ecdh_verify(char *reqfn, PRBool response)
3236 {
3237 char buf[256]; /* holds one line from the input REQUEST file.
3238 * needs to be large enough to hold the longest
3239 * line "Qx = <144 hex digits>\n".
3240 */
3241 FILE *ecdhreq; /* input stream from the REQUEST file */
3242 FILE *ecdhresp; /* output stream to the RESPONSE file */
3243 char curve[16]; /* "nistxddd" */
3244 unsigned char hashBuf[HASH_LENGTH_MAX];
3245 unsigned char cavsHashBuf[HASH_LENGTH_MAX];
3246 unsigned char private_data[MAX_ECKEY_LEN];
3247 ECParams *ecparams[MAX_ECC_PARAMS] = { NULL };
3248 ECParams *current_ecparams = NULL;
3249 SECItem pubkey;
3250 SECItem ZZ;
3251 SECItem private_value;
3252 unsigned int i;
3253 unsigned int len = 0;
3254 int current_curve = -1;
3255 HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
3256
3257 ecdhreq = fopen(reqfn, "r");
3258 ecdhresp = stdout;
3259 strcpy(curve, "nist");
3260 pubkey.data = NULL;
3261 while (fgets(buf, sizeof buf, ecdhreq) != NULL) {
3262 /* a comment or blank line */
3263 if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
3264 fputs(buf, ecdhresp);
3265 continue;
3266 }
3267 if (buf[0] == '[') {
3268 /* [Ex] */
3269 if (buf[1] == 'E' && buf[3] == ']') {
3270 current_curve = buf[2] - 'A';
3271 fputs(buf, ecdhresp);
3272 continue;
3273 }
3274 /* [Curve selected: x-nnn */
3275 if (strncmp(buf, "[Curve ", 7) == 0) {
3276 const char *src;
3277 char *dst;
3278 SECItem *encodedparams;
3279
3280 if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) {
3281 fprintf(stderr, "No curve type defined\n");
3282 goto loser;
3283 }
3284
3285 src = &buf[1];
3286 /* skip passed the colon */
3287 while (*src && *src != ':')
3288 src++;
3289 if (*src != ':') {
3290 fprintf(stderr,
3291 "No colon in curve selected statement\n%s", buf);
3292 goto loser;
3293 }
3294 src++;
3295 /* skip to the first non-space */
3296 while (*src && *src == ' ')
3297 src++;
3298 dst = &curve[4];
3299 *dst++ = tolower(*src);
3300 src += 2; /* skip the hyphen */
3301 *dst++ = *src++;
3302 *dst++ = *src++;
3303 *dst++ = *src++;
3304 *dst = '\0';
3305 if (ecparams[current_curve] != NULL) {
3306 PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE);
3307 ecparams[current_curve] = NULL;
3308 }
3309 encodedparams = getECParams(curve);
3310 if (encodedparams == NULL) {
3311 fprintf(stderr, "Unknown curve %s.\n", curve);
3312 goto loser;
3313 }
3314 if (EC_DecodeParams(encodedparams, &ecparams[current_curve]) != SECSuccess) {
3315 fprintf(stderr, "Curve %s not supported.\n", curve);
3316 goto loser;
3317 }
3318 SECITEM_FreeItem(encodedparams, PR_TRUE);
3319 fputs(buf, ecdhresp);
3320 continue;
3321 }
3322 /* [Ex - SHAxxx] */
3323 if (buf[1] == 'E' && buf[3] == ' ') {
3324 const char *src;
3325 current_curve = buf[2] - 'A';
3326 if ((current_curve < 0) || (current_curve > 256)) {
3327 fprintf(stderr, "bad curve type defined (%c)\n", buf[2]);
3328 goto loser;
3329 }
3330 current_ecparams = ecparams[current_curve];
3331 if (current_ecparams == NULL) {
3332 fprintf(stderr, "no curve defined for type %c defined\n",
3333 buf[2]);
3334 goto loser;
3335 }
3336 /* skip passed the colon */
3337 src = &buf[1];
3338 while (*src && *src != '-')
3339 src++;
3340 if (*src != '-') {
3341 fprintf(stderr,
3342 "No data in curve selected statement\n%s", buf);
3343 goto loser;
3344 }
3345 src++;
3346 /* skip to the first non-space */
3347 while (*src && *src == ' ')
3348 src++;
3349 hash = hash_string_to_hashType(src);
3350 if (hash == HASH_AlgNULL) {
3351 fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type");
3352 goto loser;
3353 }
3354 fputs(buf, ecdhresp);
3355 continue;
3356 }
3357 fputs(buf, ecdhresp);
3358 continue;
3359 }
3360 /* COUNT = ... */
3361 if (strncmp(buf, "COUNT", 5) == 0) {
3362 fputs(buf, ecdhresp);
3363 if (current_ecparams == NULL) {
3364 fprintf(stderr, "no curve defined for type %c defined\n",
3365 buf[2]);
3366 goto loser;
3367 }
3368 len = (current_ecparams->fieldID.size + 7) >> 3;
3369 if (pubkey.data != NULL) {
3370 PORT_Free(pubkey.data);
3371 pubkey.data = NULL;
3372 }
3373 SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams));
3374 if (pubkey.data == NULL) {
3375 goto loser;
3376 }
3377 pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
3378 continue;
3379 }
3380 /* QeCAVSx = ... */
3381 if (strncmp(buf, "QeCAVSx", 7) == 0) {
3382 fputs(buf, ecdhresp);
3383 i = 7;
3384 while (isspace(buf[i]) || buf[i] == '=') {
3385 i++;
3386 }
3387 from_hex_str(&pubkey.data[1], len, &buf[i]);
3388 continue;
3389 }
3390 /* QeCAVSy = ... */
3391 if (strncmp(buf, "QeCAVSy", 7) == 0) {
3392 fputs(buf, ecdhresp);
3393 i = 7;
3394 while (isspace(buf[i]) || buf[i] == '=') {
3395 i++;
3396 }
3397 from_hex_str(&pubkey.data[1 + len], len, &buf[i]);
3398 continue;
3399 }
3400 if (strncmp(buf, "deIUT", 5) == 0) {
3401 fputs(buf, ecdhresp);
3402 i = 5;
3403 while (isspace(buf[i]) || buf[i] == '=') {
3404 i++;
3405 }
3406 from_hex_str(private_data, len, &buf[i]);
3407 private_value.data = private_data;
3408 private_value.len = len;
3409 continue;
3410 }
3411 if (strncmp(buf, "QeIUTx", 6) == 0) {
3412 fputs(buf, ecdhresp);
3413 continue;
3414 }
3415 if (strncmp(buf, "QeIUTy", 6) == 0) {
3416 fputs(buf, ecdhresp);
3417 continue;
3418 }
3419 if ((strncmp(buf, "CAVSHashZZ", 10) == 0) ||
3420 (strncmp(buf, "HashZZ", 6) == 0)) {
3421 fputs(buf, ecdhresp);
3422 i = (buf[0] == 'C') ? 10 : 6;
3423 while (isspace(buf[i]) || buf[i] == '=') {
3424 i++;
3425 }
3426 from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]);
3427 if (current_ecparams == NULL) {
3428 fprintf(stderr, "no curve defined for type defined\n");
3429 goto loser;
3430 }
3431 /* validate CAVS public key */
3432 if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) {
3433 #ifdef VERBOSE_REASON
3434 fprintf(ecdhresp, "Result = F # key didn't validate\n");
3435 #else
3436 fprintf(ecdhresp, "Result = F\n");
3437 #endif
3438 continue;
3439 }
3440
3441 /* ECDH */
3442 if (ECDH_Derive(&pubkey, current_ecparams, &private_value,
3443 PR_FALSE, &ZZ) != SECSuccess) {
3444 #ifdef VERBOSE_REASON
3445 fprintf(ecdhresp, "Result = F # derive failure\n");
3446 #else
3447 fprintf(ecdhresp, "Result = F\n");
3448 #endif
3449 continue;
3450 }
3451 /* output ZZ */
3452 #ifndef MATCH_OPENSSL
3453 fputs("Z = ", ecdhresp);
3454 to_hex_str(buf, ZZ.data, ZZ.len);
3455 fputs(buf, ecdhresp);
3456 fputc('\n', ecdhresp);
3457 #endif
3458
3459 if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
3460 fprintf(stderr, "hash of derived key failed\n");
3461 goto loser;
3462 }
3463 SECITEM_FreeItem(&ZZ, PR_FALSE);
3464 #ifndef MATCH_NIST
3465 fputs("IUTHashZZ = ", ecdhresp);
3466 to_hex_str(buf, hashBuf, fips_hashLen(hash));
3467 fputs(buf, ecdhresp);
3468 fputc('\n', ecdhresp);
3469 #endif
3470 if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) {
3471 #ifdef VERBOSE_REASON
3472 fprintf(ecdhresp, "Result = F # hash doesn't match\n");
3473 #else
3474 fprintf(ecdhresp, "Result = F\n");
3475 #endif
3476 } else {
3477 fprintf(ecdhresp, "Result = P\n");
3478 }
3479 #ifndef MATCH_OPENSSL
3480 fputc('\n', ecdhresp);
3481 #endif
3482 continue;
3483 }
3484 }
3485 loser:
3486 for (i = 0; i < MAX_ECC_PARAMS; i++) {
3487 if (ecparams[i] != NULL) {
3488 PORT_FreeArena(ecparams[i]->arena, PR_FALSE);
3489 ecparams[i] = NULL;
3490 }
3491 }
3492 if (pubkey.data != NULL) {
3493 PORT_Free(pubkey.data);
3494 }
3495 fclose(ecdhreq);
3496 }
3497
3498 /*
3499 * Perform the DH Functional Test.
3500 *
3501 * reqfn is the pathname of the REQUEST file.
3502 *
3503 * The output RESPONSE file is written to stdout.
3504 */
3505 #define MAX_ECC_PARAMS 256
3506 void
dh_functional(char * reqfn,PRBool response)3507 dh_functional(char *reqfn, PRBool response)
3508 {
3509 char buf[1024]; /* holds one line from the input REQUEST file.
3510 * needs to be large enough to hold the longest
3511 * line "YephCAVS = <512 hex digits>\n".
3512 */
3513 FILE *dhreq; /* input stream from the REQUEST file */
3514 FILE *dhresp; /* output stream to the RESPONSE file */
3515 unsigned char hashBuf[HASH_LENGTH_MAX];
3516 DSAPrivateKey *dsapriv = NULL;
3517 PQGParams pqg = { 0 };
3518 unsigned char pubkeydata[DSA_MAX_P_BITS / 8];
3519 SECItem pubkey;
3520 SECItem ZZ;
3521 unsigned int i, j;
3522 unsigned int pgySize;
3523 HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
3524
3525 dhreq = fopen(reqfn, "r");
3526 dhresp = stdout;
3527 while (fgets(buf, sizeof buf, dhreq) != NULL) {
3528 /* a comment or blank line */
3529 if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
3530 fputs(buf, dhresp);
3531 continue;
3532 }
3533 if (buf[0] == '[') {
3534 /* [Fx - SHAxxx] */
3535 if (buf[1] == 'F' && buf[3] == ' ') {
3536 const char *src;
3537 /* skip passed the colon */
3538 src = &buf[1];
3539 while (*src && *src != '-')
3540 src++;
3541 if (*src != '-') {
3542 fprintf(stderr, "No hash specified\n%s", buf);
3543 goto loser;
3544 }
3545 src++;
3546 /* skip to the first non-space */
3547 while (*src && *src == ' ')
3548 src++;
3549 hash = hash_string_to_hashType(src);
3550 if (hash == HASH_AlgNULL) {
3551 fprintf(dhresp, "ERROR: Unable to find SHAAlg type");
3552 goto loser;
3553 }
3554 /* clear the PQG parameters */
3555 if (pqg.prime.data) { /* P */
3556 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
3557 }
3558 if (pqg.subPrime.data) { /* Q */
3559 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
3560 }
3561 if (pqg.base.data) { /* G */
3562 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
3563 }
3564 pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */
3565 SECITEM_AllocItem(NULL, &pqg.prime, pgySize);
3566 SECITEM_AllocItem(NULL, &pqg.base, pgySize);
3567 pqg.prime.len = pqg.base.len = pgySize;
3568
3569 /* set q to the max allows */
3570 SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS / 8);
3571 pqg.subPrime.len = DSA_MAX_Q_BITS / 8;
3572 fputs(buf, dhresp);
3573 continue;
3574 }
3575 fputs(buf, dhresp);
3576 continue;
3577 }
3578 if (buf[0] == 'P') {
3579 i = 1;
3580 while (isspace(buf[i]) || buf[i] == '=') {
3581 i++;
3582 }
3583 for (j = 0; j < pqg.prime.len; i += 2, j++) {
3584 if (!isxdigit(buf[i])) {
3585 pqg.prime.len = j;
3586 break;
3587 }
3588 hex_to_byteval(&buf[i], &pqg.prime.data[j]);
3589 }
3590
3591 fputs(buf, dhresp);
3592 continue;
3593 }
3594
3595 /* Q = ... */
3596 if (buf[0] == 'Q') {
3597 i = 1;
3598 while (isspace(buf[i]) || buf[i] == '=') {
3599 i++;
3600 }
3601 for (j = 0; j < pqg.subPrime.len; i += 2, j++) {
3602 if (!isxdigit(buf[i])) {
3603 pqg.subPrime.len = j;
3604 break;
3605 }
3606 hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
3607 }
3608
3609 fputs(buf, dhresp);
3610 continue;
3611 }
3612
3613 /* G = ... */
3614 if (buf[0] == 'G') {
3615 i = 1;
3616 while (isspace(buf[i]) || buf[i] == '=') {
3617 i++;
3618 }
3619 for (j = 0; j < pqg.base.len; i += 2, j++) {
3620 if (!isxdigit(buf[i])) {
3621 pqg.base.len = j;
3622 break;
3623 }
3624 hex_to_byteval(&buf[i], &pqg.base.data[j]);
3625 }
3626
3627 fputs(buf, dhresp);
3628 continue;
3629 }
3630
3631 /* COUNT = ... */
3632 if (strncmp(buf, "COUNT", 5) == 0) {
3633 fputs(buf, dhresp);
3634 continue;
3635 }
3636
3637 /* YephemCAVS = ... */
3638 if (strncmp(buf, "YephemCAVS", 10) == 0) {
3639 fputs(buf, dhresp);
3640 i = 10;
3641 while (isspace(buf[i]) || buf[i] == '=') {
3642 i++;
3643 }
3644 from_hex_str(pubkeydata, pqg.prime.len, &buf[i]);
3645 pubkey.data = pubkeydata;
3646 pubkey.len = pqg.prime.len;
3647
3648 /* generate FCC key pair, nist uses pqg rather then pg,
3649 * so use DSA to generate the key */
3650 if (DSA_NewKey(&pqg, &dsapriv) != SECSuccess) {
3651 fprintf(stderr, "Failed to generate new key\n");
3652 goto loser;
3653 }
3654 fputs("XephemIUT = ", dhresp);
3655 to_hex_str(buf, dsapriv->privateValue.data, dsapriv->privateValue.len);
3656 fputs(buf, dhresp);
3657 fputc('\n', dhresp);
3658 fputs("YephemIUT = ", dhresp);
3659 to_hex_str(buf, dsapriv->publicValue.data, dsapriv->publicValue.len);
3660 fputs(buf, dhresp);
3661 fputc('\n', dhresp);
3662 /* DH */
3663 if (DH_Derive(&pubkey, &pqg.prime, &dsapriv->privateValue,
3664 &ZZ, pqg.prime.len) != SECSuccess) {
3665 fprintf(stderr, "Derive failed\n");
3666 goto loser;
3667 }
3668 /* output hash of ZZ */
3669 if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
3670 fprintf(stderr, "hash of derived key failed\n");
3671 goto loser;
3672 }
3673 SECITEM_FreeItem(&ZZ, PR_FALSE);
3674 fputs("HashZZ = ", dhresp);
3675 to_hex_str(buf, hashBuf, fips_hashLen(hash));
3676 fputs(buf, dhresp);
3677 fputc('\n', dhresp);
3678 fputc('\n', dhresp);
3679 PORT_FreeArena(dsapriv->params.arena, PR_TRUE);
3680 dsapriv = NULL;
3681 continue;
3682 }
3683 }
3684 loser:
3685 if (dsapriv != NULL) {
3686 PORT_FreeArena(dsapriv->params.arena, PR_TRUE);
3687 }
3688 fclose(dhreq);
3689 }
3690
3691 /*
3692 * Perform the DH Validity Test.
3693 *
3694 * reqfn is the pathname of the REQUEST file.
3695 *
3696 * The output RESPONSE file is written to stdout.
3697 */
3698 void
dh_verify(char * reqfn,PRBool response)3699 dh_verify(char *reqfn, PRBool response)
3700 {
3701 char buf[1024]; /* holds one line from the input REQUEST file.
3702 * needs to be large enough to hold the longest
3703 * line "YephCAVS = <512 hex digits>\n".
3704 */
3705 FILE *dhreq; /* input stream from the REQUEST file */
3706 FILE *dhresp; /* output stream to the RESPONSE file */
3707 unsigned char hashBuf[HASH_LENGTH_MAX];
3708 unsigned char cavsHashBuf[HASH_LENGTH_MAX];
3709 PQGParams pqg = { 0 };
3710 unsigned char pubkeydata[DSA_MAX_P_BITS / 8];
3711 unsigned char privkeydata[DSA_MAX_P_BITS / 8];
3712 SECItem pubkey;
3713 SECItem privkey;
3714 SECItem ZZ;
3715 unsigned int i, j;
3716 unsigned int pgySize;
3717 HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
3718
3719 dhreq = fopen(reqfn, "r");
3720 dhresp = stdout;
3721 while (fgets(buf, sizeof buf, dhreq) != NULL) {
3722 /* a comment or blank line */
3723 if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
3724 fputs(buf, dhresp);
3725 continue;
3726 }
3727 if (buf[0] == '[') {
3728 /* [Fx - SHAxxx] */
3729 if (buf[1] == 'F' && buf[3] == ' ') {
3730 const char *src;
3731 /* skip passed the colon */
3732 src = &buf[1];
3733 while (*src && *src != '-')
3734 src++;
3735 if (*src != '-') {
3736 fprintf(stderr, "No hash specified\n%s", buf);
3737 goto loser;
3738 }
3739 src++;
3740 /* skip to the first non-space */
3741 while (*src && *src == ' ')
3742 src++;
3743 hash = hash_string_to_hashType(src);
3744 if (hash == HASH_AlgNULL) {
3745 fprintf(dhresp, "ERROR: Unable to find SHAAlg type");
3746 goto loser;
3747 }
3748 /* clear the PQG parameters */
3749 if (pqg.prime.data) { /* P */
3750 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
3751 }
3752 if (pqg.subPrime.data) { /* Q */
3753 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
3754 }
3755 if (pqg.base.data) { /* G */
3756 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
3757 }
3758 pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */
3759 SECITEM_AllocItem(NULL, &pqg.prime, pgySize);
3760 SECITEM_AllocItem(NULL, &pqg.base, pgySize);
3761 pqg.prime.len = pqg.base.len = pgySize;
3762
3763 /* set q to the max allows */
3764 SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS / 8);
3765 pqg.subPrime.len = DSA_MAX_Q_BITS / 8;
3766 fputs(buf, dhresp);
3767 continue;
3768 }
3769 fputs(buf, dhresp);
3770 continue;
3771 }
3772 if (buf[0] == 'P') {
3773 i = 1;
3774 while (isspace(buf[i]) || buf[i] == '=') {
3775 i++;
3776 }
3777 for (j = 0; j < pqg.prime.len; i += 2, j++) {
3778 if (!isxdigit(buf[i])) {
3779 pqg.prime.len = j;
3780 break;
3781 }
3782 hex_to_byteval(&buf[i], &pqg.prime.data[j]);
3783 }
3784
3785 fputs(buf, dhresp);
3786 continue;
3787 }
3788
3789 /* Q = ... */
3790 if (buf[0] == 'Q') {
3791 i = 1;
3792 while (isspace(buf[i]) || buf[i] == '=') {
3793 i++;
3794 }
3795 for (j = 0; j < pqg.subPrime.len; i += 2, j++) {
3796 if (!isxdigit(buf[i])) {
3797 pqg.subPrime.len = j;
3798 break;
3799 }
3800 hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
3801 }
3802
3803 fputs(buf, dhresp);
3804 continue;
3805 }
3806
3807 /* G = ... */
3808 if (buf[0] == 'G') {
3809 i = 1;
3810 while (isspace(buf[i]) || buf[i] == '=') {
3811 i++;
3812 }
3813 for (j = 0; j < pqg.base.len; i += 2, j++) {
3814 if (!isxdigit(buf[i])) {
3815 pqg.base.len = j;
3816 break;
3817 }
3818 hex_to_byteval(&buf[i], &pqg.base.data[j]);
3819 }
3820
3821 fputs(buf, dhresp);
3822 continue;
3823 }
3824
3825 /* COUNT = ... */
3826 if (strncmp(buf, "COUNT", 5) == 0) {
3827 fputs(buf, dhresp);
3828 continue;
3829 }
3830
3831 /* YephemCAVS = ... */
3832 if (strncmp(buf, "YephemCAVS", 10) == 0) {
3833 fputs(buf, dhresp);
3834 i = 10;
3835 while (isspace(buf[i]) || buf[i] == '=') {
3836 i++;
3837 }
3838 from_hex_str(pubkeydata, pqg.prime.len, &buf[i]);
3839 pubkey.data = pubkeydata;
3840 pubkey.len = pqg.prime.len;
3841 continue;
3842 }
3843 /* XephemUIT = ... */
3844 if (strncmp(buf, "XephemIUT", 9) == 0) {
3845 fputs(buf, dhresp);
3846 i = 9;
3847 while (isspace(buf[i]) || buf[i] == '=') {
3848 i++;
3849 }
3850 from_hex_str(privkeydata, pqg.subPrime.len, &buf[i]);
3851 privkey.data = privkeydata;
3852 privkey.len = pqg.subPrime.len;
3853 continue;
3854 }
3855 /* YephemUIT = ... */
3856 if (strncmp(buf, "YephemIUT", 9) == 0) {
3857 fputs(buf, dhresp);
3858 continue;
3859 }
3860 /* CAVSHashZZ = ... */
3861 if ((strncmp(buf, "CAVSHashZZ", 10) == 0) ||
3862 (strncmp(buf, "HashZZ", 6) == 0)) {
3863 fputs(buf, dhresp);
3864 i = buf[0] == 'C' ? 10 : 6;
3865 while (isspace(buf[i]) || buf[i] == '=') {
3866 i++;
3867 }
3868 from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]);
3869 /* do the DH operation*/
3870 if (DH_Derive(&pubkey, &pqg.prime, &privkey,
3871 &ZZ, pqg.prime.len) != SECSuccess) {
3872 fprintf(stderr, "Derive failed\n");
3873 goto loser;
3874 }
3875 /* output ZZ */
3876 #ifndef MATCH_OPENSSL
3877 fputs("Z = ", dhresp);
3878 to_hex_str(buf, ZZ.data, ZZ.len);
3879 fputs(buf, dhresp);
3880 fputc('\n', dhresp);
3881 #endif
3882 if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
3883 fprintf(stderr, "hash of derived key failed\n");
3884 goto loser;
3885 }
3886 SECITEM_FreeItem(&ZZ, PR_FALSE);
3887 #ifndef MATCH_NIST
3888 fputs("IUTHashZZ = ", dhresp);
3889 to_hex_str(buf, hashBuf, fips_hashLen(hash));
3890 fputs(buf, dhresp);
3891 fputc('\n', dhresp);
3892 #endif
3893 if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) {
3894 fprintf(dhresp, "Result = F\n");
3895 } else {
3896 fprintf(dhresp, "Result = P\n");
3897 }
3898 #ifndef MATCH_OPENSSL
3899 fputc('\n', dhresp);
3900 #endif
3901 continue;
3902 }
3903 }
3904 loser:
3905 fclose(dhreq);
3906 }
3907
3908 PRBool
isblankline(char * b)3909 isblankline(char *b)
3910 {
3911 while (isspace(*b))
3912 b++;
3913 if ((*b == '\n') || (*b == 0)) {
3914 return PR_TRUE;
3915 }
3916 return PR_FALSE;
3917 }
3918
3919 static int debug = 0;
3920
3921 /*
3922 * Perform the Hash_DRBG (CAVS) for the RNG algorithm
3923 *
3924 * reqfn is the pathname of the REQUEST file.
3925 *
3926 * The output RESPONSE file is written to stdout.
3927 */
3928 void
drbg(char * reqfn)3929 drbg(char *reqfn)
3930 {
3931 char buf[2000]; /* test case has some very long lines, returned bits
3932 * as high as 800 bytes (6400 bits). That 1600 byte
3933 * plus a tag */
3934 char buf2[2000];
3935 FILE *rngreq; /* input stream from the REQUEST file */
3936 FILE *rngresp; /* output stream to the RESPONSE file */
3937
3938 unsigned int i, j;
3939 #ifdef HANDLE_PREDICTION_RESISTANCE
3940 PRBool predictionResistance = PR_FALSE;
3941 #endif
3942 unsigned char *nonce = NULL;
3943 int nonceLen = 0;
3944 unsigned char *personalizationString = NULL;
3945 int personalizationStringLen = 0;
3946 unsigned char *additionalInput = NULL;
3947 int additionalInputLen = 0;
3948 unsigned char *entropyInput = NULL;
3949 int entropyInputLen = 0;
3950 unsigned char *predictedreturn_bytes = NULL;
3951 unsigned char *return_bytes = NULL;
3952 int return_bytes_len = 0;
3953 enum { NONE,
3954 INSTANTIATE,
3955 GENERATE,
3956 RESEED,
3957 RESULT } command =
3958 NONE;
3959 PRBool genResult = PR_FALSE;
3960 SECStatus rv;
3961
3962 rngreq = fopen(reqfn, "r");
3963 rngresp = stdout;
3964 while (fgets(buf, sizeof buf, rngreq) != NULL) {
3965 switch (command) {
3966 case INSTANTIATE:
3967 if (debug) {
3968 fputs("# PRNGTEST_Instantiate(", rngresp);
3969 to_hex_str(buf2, entropyInput, entropyInputLen);
3970 fputs(buf2, rngresp);
3971 fprintf(rngresp, ",%d,", entropyInputLen);
3972 to_hex_str(buf2, nonce, nonceLen);
3973 fputs(buf2, rngresp);
3974 fprintf(rngresp, ",%d,", nonceLen);
3975 to_hex_str(buf2, personalizationString,
3976 personalizationStringLen);
3977 fputs(buf2, rngresp);
3978 fprintf(rngresp, ",%d)\n", personalizationStringLen);
3979 }
3980 rv = PRNGTEST_Instantiate(entropyInput, entropyInputLen,
3981 nonce, nonceLen,
3982 personalizationString,
3983 personalizationStringLen);
3984 if (rv != SECSuccess) {
3985 goto loser;
3986 }
3987 break;
3988
3989 case GENERATE:
3990 case RESULT:
3991 memset(return_bytes, 0, return_bytes_len);
3992 if (debug) {
3993 fputs("# PRNGTEST_Generate(returnbytes", rngresp);
3994 fprintf(rngresp, ",%d,", return_bytes_len);
3995 to_hex_str(buf2, additionalInput, additionalInputLen);
3996 fputs(buf2, rngresp);
3997 fprintf(rngresp, ",%d)\n", additionalInputLen);
3998 }
3999 rv = PRNGTEST_Generate((PRUint8 *)return_bytes,
4000 return_bytes_len,
4001 (PRUint8 *)additionalInput,
4002 additionalInputLen);
4003 if (rv != SECSuccess) {
4004 goto loser;
4005 }
4006
4007 if (command == RESULT) {
4008 fputs("ReturnedBits = ", rngresp);
4009 to_hex_str(buf2, return_bytes, return_bytes_len);
4010 fputs(buf2, rngresp);
4011 fputc('\n', rngresp);
4012 if (debug) {
4013 fputs("# PRNGTEST_Uninstantiate()\n", rngresp);
4014 }
4015 rv = PRNGTEST_Uninstantiate();
4016 if (rv != SECSuccess) {
4017 goto loser;
4018 }
4019 } else if (debug) {
4020 fputs("#ReturnedBits = ", rngresp);
4021 to_hex_str(buf2, return_bytes, return_bytes_len);
4022 fputs(buf2, rngresp);
4023 fputc('\n', rngresp);
4024 }
4025
4026 memset(additionalInput, 0, additionalInputLen);
4027 break;
4028
4029 case RESEED:
4030 if (entropyInput || additionalInput) {
4031 if (debug) {
4032 fputs("# PRNGTEST_Reseed(", rngresp);
4033 fprintf(rngresp, ",%d,", return_bytes_len);
4034 to_hex_str(buf2, entropyInput, entropyInputLen);
4035 fputs(buf2, rngresp);
4036 fprintf(rngresp, ",%d,", entropyInputLen);
4037 to_hex_str(buf2, additionalInput, additionalInputLen);
4038 fputs(buf2, rngresp);
4039 fprintf(rngresp, ",%d)\n", additionalInputLen);
4040 }
4041 rv = PRNGTEST_Reseed(entropyInput, entropyInputLen,
4042 additionalInput, additionalInputLen);
4043 if (rv != SECSuccess) {
4044 goto loser;
4045 }
4046 }
4047 memset(entropyInput, 0, entropyInputLen);
4048 memset(additionalInput, 0, additionalInputLen);
4049 break;
4050 case NONE:
4051 break;
4052 }
4053 command = NONE;
4054
4055 /* a comment or blank line */
4056 if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
4057 fputs(buf, rngresp);
4058 continue;
4059 }
4060
4061 /* [Hash - SHA256] */
4062 if (strncmp(buf, "[SHA-256]", 9) == 0) {
4063 fputs(buf, rngresp);
4064 continue;
4065 }
4066
4067 if (strncmp(buf, "[PredictionResistance", 21) == 0) {
4068 #ifdef HANDLE_PREDICTION_RESISTANCE
4069 i = 21;
4070 while (isspace(buf[i]) || buf[i] == '=') {
4071 i++;
4072 }
4073 if (strncmp(buf, "False", 5) == 0) {
4074 predictionResistance = PR_FALSE;
4075 } else {
4076 predictionResistance = PR_TRUE;
4077 }
4078 #endif
4079
4080 fputs(buf, rngresp);
4081 continue;
4082 }
4083
4084 if (strncmp(buf, "[ReturnedBitsLen", 16) == 0) {
4085 if (return_bytes) {
4086 PORT_ZFree(return_bytes, return_bytes_len);
4087 return_bytes = NULL;
4088 }
4089 if (predictedreturn_bytes) {
4090 PORT_ZFree(predictedreturn_bytes, return_bytes_len);
4091 predictedreturn_bytes = NULL;
4092 }
4093 return_bytes_len = 0;
4094 if (sscanf(buf, "[ReturnedBitsLen = %d]", &return_bytes_len) != 1) {
4095 goto loser;
4096 }
4097 return_bytes_len = return_bytes_len / 8;
4098 if (return_bytes_len > 0) {
4099 return_bytes = PORT_Alloc(return_bytes_len);
4100 predictedreturn_bytes = PORT_Alloc(return_bytes_len);
4101 }
4102 fputs(buf, rngresp);
4103 continue;
4104 }
4105
4106 if (strncmp(buf, "[EntropyInputLen", 16) == 0) {
4107 if (entropyInput) {
4108 PORT_ZFree(entropyInput, entropyInputLen);
4109 entropyInput = NULL;
4110 entropyInputLen = 0;
4111 }
4112 if (sscanf(buf, "[EntropyInputLen = %d]", &entropyInputLen) != 1) {
4113 goto loser;
4114 }
4115 entropyInputLen = entropyInputLen / 8;
4116 if (entropyInputLen > 0) {
4117 entropyInput = PORT_Alloc(entropyInputLen);
4118 }
4119 fputs(buf, rngresp);
4120 continue;
4121 }
4122
4123 if (strncmp(buf, "[NonceLen", 9) == 0) {
4124 if (nonce) {
4125 PORT_ZFree(nonce, nonceLen);
4126 nonce = NULL;
4127 nonceLen = 0;
4128 }
4129
4130 if (sscanf(buf, "[NonceLen = %d]", &nonceLen) != 1) {
4131 goto loser;
4132 }
4133 nonceLen = nonceLen / 8;
4134 if (nonceLen > 0) {
4135 nonce = PORT_Alloc(nonceLen);
4136 }
4137 fputs(buf, rngresp);
4138 continue;
4139 }
4140
4141 if (strncmp(buf, "[PersonalizationStringLen", 16) == 0) {
4142 if (personalizationString) {
4143 PORT_ZFree(personalizationString, personalizationStringLen);
4144 personalizationString = NULL;
4145 personalizationStringLen = 0;
4146 }
4147
4148 if (sscanf(buf, "[PersonalizationStringLen = %d]", &personalizationStringLen) != 1) {
4149 goto loser;
4150 }
4151 personalizationStringLen = personalizationStringLen / 8;
4152 if (personalizationStringLen > 0) {
4153 personalizationString = PORT_Alloc(personalizationStringLen);
4154 }
4155 fputs(buf, rngresp);
4156
4157 continue;
4158 }
4159
4160 if (strncmp(buf, "[AdditionalInputLen", 16) == 0) {
4161 if (additionalInput) {
4162 PORT_ZFree(additionalInput, additionalInputLen);
4163 additionalInput = NULL;
4164 additionalInputLen = 0;
4165 }
4166
4167 if (sscanf(buf, "[AdditionalInputLen = %d]", &additionalInputLen) != 1) {
4168 goto loser;
4169 }
4170 additionalInputLen = additionalInputLen / 8;
4171 if (additionalInputLen > 0) {
4172 additionalInput = PORT_Alloc(additionalInputLen);
4173 }
4174 fputs(buf, rngresp);
4175 continue;
4176 }
4177
4178 if (strncmp(buf, "COUNT", 5) == 0) {
4179 /* zeroize the variables for the test with this data set */
4180 if (entropyInput) {
4181 memset(entropyInput, 0, entropyInputLen);
4182 }
4183 if (nonce) {
4184 memset(nonce, 0, nonceLen);
4185 }
4186 if (personalizationString) {
4187 memset(personalizationString, 0, personalizationStringLen);
4188 }
4189 if (additionalInput) {
4190 memset(additionalInput, 0, additionalInputLen);
4191 }
4192 genResult = PR_FALSE;
4193
4194 fputs(buf, rngresp);
4195 continue;
4196 }
4197
4198 /* EntropyInputReseed = ... */
4199 if (strncmp(buf, "EntropyInputReseed", 18) == 0) {
4200 if (entropyInput) {
4201 memset(entropyInput, 0, entropyInputLen);
4202 i = 18;
4203 while (isspace(buf[i]) || buf[i] == '=') {
4204 i++;
4205 }
4206
4207 for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<entropyInputLen*/
4208 hex_to_byteval(&buf[i], &entropyInput[j]);
4209 }
4210 }
4211 fputs(buf, rngresp);
4212 continue;
4213 }
4214
4215 /* AttionalInputReseed = ... */
4216 if (strncmp(buf, "AdditionalInputReseed", 21) == 0) {
4217 if (additionalInput) {
4218 memset(additionalInput, 0, additionalInputLen);
4219 i = 21;
4220 while (isspace(buf[i]) || buf[i] == '=') {
4221 i++;
4222 }
4223 for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<additionalInputLen*/
4224 hex_to_byteval(&buf[i], &additionalInput[j]);
4225 }
4226 }
4227 command = RESEED;
4228 fputs(buf, rngresp);
4229 continue;
4230 }
4231
4232 /* Entropy input = ... */
4233 if (strncmp(buf, "EntropyInput", 12) == 0) {
4234 i = 12;
4235 while (isspace(buf[i]) || buf[i] == '=') {
4236 i++;
4237 }
4238 for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<entropyInputLen*/
4239 hex_to_byteval(&buf[i], &entropyInput[j]);
4240 }
4241 fputs(buf, rngresp);
4242 continue;
4243 }
4244
4245 /* nouce = ... */
4246 if (strncmp(buf, "Nonce", 5) == 0) {
4247 i = 5;
4248 while (isspace(buf[i]) || buf[i] == '=') {
4249 i++;
4250 }
4251 for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<nonceLen*/
4252 hex_to_byteval(&buf[i], &nonce[j]);
4253 }
4254 fputs(buf, rngresp);
4255 continue;
4256 }
4257
4258 /* Personalization string = ... */
4259 if (strncmp(buf, "PersonalizationString", 21) == 0) {
4260 if (personalizationString) {
4261 i = 21;
4262 while (isspace(buf[i]) || buf[i] == '=') {
4263 i++;
4264 }
4265 for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<personalizationStringLen*/
4266 hex_to_byteval(&buf[i], &personalizationString[j]);
4267 }
4268 }
4269 fputs(buf, rngresp);
4270 command = INSTANTIATE;
4271 continue;
4272 }
4273
4274 /* Additional input = ... */
4275 if (strncmp(buf, "AdditionalInput", 15) == 0) {
4276 if (additionalInput) {
4277 i = 15;
4278 while (isspace(buf[i]) || buf[i] == '=') {
4279 i++;
4280 }
4281 for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<additionalInputLen*/
4282 hex_to_byteval(&buf[i], &additionalInput[j]);
4283 }
4284 }
4285 if (genResult) {
4286 command = RESULT;
4287 } else {
4288 command = GENERATE;
4289 genResult = PR_TRUE; /* next time generate result */
4290 }
4291 fputs(buf, rngresp);
4292 continue;
4293 }
4294
4295 /* Returned bits = ... */
4296 if (strncmp(buf, "ReturnedBits", 12) == 0) {
4297 i = 12;
4298 while (isspace(buf[i]) || buf[i] == '=') {
4299 i++;
4300 }
4301 for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<additionalInputLen*/
4302 hex_to_byteval(&buf[i], &predictedreturn_bytes[j]);
4303 }
4304
4305 if (memcmp(return_bytes,
4306 predictedreturn_bytes, return_bytes_len) != 0) {
4307 if (debug) {
4308 fprintf(rngresp, "# Generate failed:\n");
4309 fputs("# predicted=", rngresp);
4310 to_hex_str(buf, predictedreturn_bytes,
4311 return_bytes_len);
4312 fputs(buf, rngresp);
4313 fputs("\n# actual = ", rngresp);
4314 fputs(buf2, rngresp);
4315 fputc('\n', rngresp);
4316
4317 } else {
4318 fprintf(stderr, "Generate failed:\n");
4319 fputs(" predicted=", stderr);
4320 to_hex_str(buf, predictedreturn_bytes,
4321 return_bytes_len);
4322 fputs(buf, stderr);
4323 fputs("\n actual = ", stderr);
4324 fputs(buf2, stderr);
4325 fputc('\n', stderr);
4326 }
4327 }
4328 memset(predictedreturn_bytes, 0, return_bytes_len);
4329
4330 continue;
4331 }
4332 }
4333 loser:
4334 if (predictedreturn_bytes) {
4335 PORT_Free(predictedreturn_bytes);
4336 }
4337 if (return_bytes) {
4338 PORT_Free(return_bytes);
4339 }
4340 if (additionalInput) {
4341 PORT_Free(additionalInput);
4342 }
4343 if (personalizationString) {
4344 PORT_Free(personalizationString);
4345 }
4346 if (nonce) {
4347 PORT_Free(nonce);
4348 }
4349 if (entropyInput) {
4350 PORT_Free(entropyInput);
4351 }
4352 fclose(rngreq);
4353 }
4354
4355 /*
4356 * Perform the RNG Variable Seed Test (VST) for the RNG algorithm
4357 * "DSA - Generation of X", used both as specified and as a generic
4358 * purpose RNG. The presence of "Q = ..." in the REQUEST file
4359 * indicates we are using the algorithm as specified.
4360 *
4361 * reqfn is the pathname of the REQUEST file.
4362 *
4363 * The output RESPONSE file is written to stdout.
4364 */
4365 void
rng_vst(char * reqfn)4366 rng_vst(char *reqfn)
4367 {
4368 char buf[256]; /* holds one line from the input REQUEST file.
4369 * needs to be large enough to hold the longest
4370 * line "XSeed = <128 hex digits>\n".
4371 */
4372 FILE *rngreq; /* input stream from the REQUEST file */
4373 FILE *rngresp; /* output stream to the RESPONSE file */
4374 unsigned int i, j;
4375 unsigned char Q[DSA1_SUBPRIME_LEN];
4376 PRBool hasQ = PR_FALSE;
4377 unsigned int b = 0; /* 160 <= b <= 512, b is a multiple of 8 */
4378 unsigned char XKey[512 / 8];
4379 unsigned char XSeed[512 / 8];
4380 unsigned char GENX[DSA1_SIGNATURE_LEN];
4381 unsigned char DSAX[DSA1_SUBPRIME_LEN];
4382 SECStatus rv;
4383
4384 rngreq = fopen(reqfn, "r");
4385 rngresp = stdout;
4386 while (fgets(buf, sizeof buf, rngreq) != NULL) {
4387 /* a comment or blank line */
4388 if (buf[0] == '#' || buf[0] == '\n') {
4389 fputs(buf, rngresp);
4390 continue;
4391 }
4392 /* [Xchange - SHA1] */
4393 if (buf[0] == '[') {
4394 fputs(buf, rngresp);
4395 continue;
4396 }
4397 /* Q = ... */
4398 if (buf[0] == 'Q') {
4399 i = 1;
4400 while (isspace(buf[i]) || buf[i] == '=') {
4401 i++;
4402 }
4403 for (j = 0; j < sizeof Q; i += 2, j++) {
4404 hex_to_byteval(&buf[i], &Q[j]);
4405 }
4406 fputs(buf, rngresp);
4407 hasQ = PR_TRUE;
4408 continue;
4409 }
4410 /* "COUNT = x" begins a new data set */
4411 if (strncmp(buf, "COUNT", 5) == 0) {
4412 /* zeroize the variables for the test with this data set */
4413 b = 0;
4414 memset(XKey, 0, sizeof XKey);
4415 memset(XSeed, 0, sizeof XSeed);
4416 fputs(buf, rngresp);
4417 continue;
4418 }
4419 /* b = ... */
4420 if (buf[0] == 'b') {
4421 i = 1;
4422 while (isspace(buf[i]) || buf[i] == '=') {
4423 i++;
4424 }
4425 b = atoi(&buf[i]);
4426 if (b < 160 || b > 512 || b % 8 != 0) {
4427 goto loser;
4428 }
4429 fputs(buf, rngresp);
4430 continue;
4431 }
4432 /* XKey = ... */
4433 if (strncmp(buf, "XKey", 4) == 0) {
4434 i = 4;
4435 while (isspace(buf[i]) || buf[i] == '=') {
4436 i++;
4437 }
4438 for (j = 0; j < b / 8; i += 2, j++) {
4439 hex_to_byteval(&buf[i], &XKey[j]);
4440 }
4441 fputs(buf, rngresp);
4442 continue;
4443 }
4444 /* XSeed = ... */
4445 if (strncmp(buf, "XSeed", 5) == 0) {
4446 i = 5;
4447 while (isspace(buf[i]) || buf[i] == '=') {
4448 i++;
4449 }
4450 for (j = 0; j < b / 8; i += 2, j++) {
4451 hex_to_byteval(&buf[i], &XSeed[j]);
4452 }
4453 fputs(buf, rngresp);
4454
4455 rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
4456 if (rv != SECSuccess) {
4457 goto loser;
4458 }
4459 fputs("X = ", rngresp);
4460 if (hasQ) {
4461 rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
4462 if (rv != SECSuccess) {
4463 goto loser;
4464 }
4465 to_hex_str(buf, DSAX, sizeof DSAX);
4466 } else {
4467 to_hex_str(buf, GENX, sizeof GENX);
4468 }
4469 fputs(buf, rngresp);
4470 fputc('\n', rngresp);
4471 continue;
4472 }
4473 }
4474 loser:
4475 fclose(rngreq);
4476 }
4477
4478 /*
4479 * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm
4480 * "DSA - Generation of X", used both as specified and as a generic
4481 * purpose RNG. The presence of "Q = ..." in the REQUEST file
4482 * indicates we are using the algorithm as specified.
4483 *
4484 * reqfn is the pathname of the REQUEST file.
4485 *
4486 * The output RESPONSE file is written to stdout.
4487 */
4488 void
rng_mct(char * reqfn)4489 rng_mct(char *reqfn)
4490 {
4491 char buf[256]; /* holds one line from the input REQUEST file.
4492 * needs to be large enough to hold the longest
4493 * line "XSeed = <128 hex digits>\n".
4494 */
4495 FILE *rngreq; /* input stream from the REQUEST file */
4496 FILE *rngresp; /* output stream to the RESPONSE file */
4497 unsigned int i, j;
4498 unsigned char Q[DSA1_SUBPRIME_LEN];
4499 PRBool hasQ = PR_FALSE;
4500 unsigned int b = 0; /* 160 <= b <= 512, b is a multiple of 8 */
4501 unsigned char XKey[512 / 8];
4502 unsigned char XSeed[512 / 8];
4503 unsigned char GENX[2 * SHA1_LENGTH];
4504 unsigned char DSAX[DSA1_SUBPRIME_LEN];
4505 SECStatus rv;
4506
4507 rngreq = fopen(reqfn, "r");
4508 rngresp = stdout;
4509 while (fgets(buf, sizeof buf, rngreq) != NULL) {
4510 /* a comment or blank line */
4511 if (buf[0] == '#' || buf[0] == '\n') {
4512 fputs(buf, rngresp);
4513 continue;
4514 }
4515 /* [Xchange - SHA1] */
4516 if (buf[0] == '[') {
4517 fputs(buf, rngresp);
4518 continue;
4519 }
4520 /* Q = ... */
4521 if (buf[0] == 'Q') {
4522 i = 1;
4523 while (isspace(buf[i]) || buf[i] == '=') {
4524 i++;
4525 }
4526 for (j = 0; j < sizeof Q; i += 2, j++) {
4527 hex_to_byteval(&buf[i], &Q[j]);
4528 }
4529 fputs(buf, rngresp);
4530 hasQ = PR_TRUE;
4531 continue;
4532 }
4533 /* "COUNT = x" begins a new data set */
4534 if (strncmp(buf, "COUNT", 5) == 0) {
4535 /* zeroize the variables for the test with this data set */
4536 b = 0;
4537 memset(XKey, 0, sizeof XKey);
4538 memset(XSeed, 0, sizeof XSeed);
4539 fputs(buf, rngresp);
4540 continue;
4541 }
4542 /* b = ... */
4543 if (buf[0] == 'b') {
4544 i = 1;
4545 while (isspace(buf[i]) || buf[i] == '=') {
4546 i++;
4547 }
4548 b = atoi(&buf[i]);
4549 if (b < 160 || b > 512 || b % 8 != 0) {
4550 goto loser;
4551 }
4552 fputs(buf, rngresp);
4553 continue;
4554 }
4555 /* XKey = ... */
4556 if (strncmp(buf, "XKey", 4) == 0) {
4557 i = 4;
4558 while (isspace(buf[i]) || buf[i] == '=') {
4559 i++;
4560 }
4561 for (j = 0; j < b / 8; i += 2, j++) {
4562 hex_to_byteval(&buf[i], &XKey[j]);
4563 }
4564 fputs(buf, rngresp);
4565 continue;
4566 }
4567 /* XSeed = ... */
4568 if (strncmp(buf, "XSeed", 5) == 0) {
4569 unsigned int k;
4570 i = 5;
4571 while (isspace(buf[i]) || buf[i] == '=') {
4572 i++;
4573 }
4574 for (j = 0; j < b / 8; i += 2, j++) {
4575 hex_to_byteval(&buf[i], &XSeed[j]);
4576 }
4577 fputs(buf, rngresp);
4578
4579 for (k = 0; k < 10000; k++) {
4580 rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
4581 if (rv != SECSuccess) {
4582 goto loser;
4583 }
4584 }
4585 fputs("X = ", rngresp);
4586 if (hasQ) {
4587 rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
4588 if (rv != SECSuccess) {
4589 goto loser;
4590 }
4591 to_hex_str(buf, DSAX, sizeof DSAX);
4592 } else {
4593 to_hex_str(buf, GENX, sizeof GENX);
4594 }
4595 fputs(buf, rngresp);
4596 fputc('\n', rngresp);
4597 continue;
4598 }
4599 }
4600 loser:
4601 fclose(rngreq);
4602 }
4603
4604 /*
4605 * Calculate the SHA Message Digest
4606 *
4607 * MD = Message digest
4608 * MDLen = length of Message Digest and SHA_Type
4609 * msg = message to digest
4610 * msgLen = length of message to digest
4611 */
4612 SECStatus
sha_calcMD(unsigned char * MD,unsigned int MDLen,unsigned char * msg,unsigned int msgLen)4613 sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen)
4614 {
4615 HASH_HashType hashType = sha_get_hashType(MDLen * PR_BITS_PER_BYTE);
4616
4617 return fips_hashBuf(hashType, MD, msg, msgLen);
4618 }
4619
4620 /*
4621 * Perform the SHA Monte Carlo Test
4622 *
4623 * MDLen = length of Message Digest and SHA_Type
4624 * seed = input seed value
4625 * resp = is the output response file.
4626 */
4627 SECStatus
sha_mct_test(unsigned int MDLen,unsigned char * seed,FILE * resp)4628 sha_mct_test(unsigned int MDLen, unsigned char *seed, FILE *resp)
4629 {
4630 int i, j;
4631 unsigned int msgLen = MDLen * 3;
4632 unsigned char MD_i3[HASH_LENGTH_MAX]; /* MD[i-3] */
4633 unsigned char MD_i2[HASH_LENGTH_MAX]; /* MD[i-2] */
4634 unsigned char MD_i1[HASH_LENGTH_MAX]; /* MD[i-1] */
4635 unsigned char MD_i[HASH_LENGTH_MAX]; /* MD[i] */
4636 unsigned char msg[HASH_LENGTH_MAX * 3];
4637 char buf[HASH_LENGTH_MAX * 2 + 1]; /* MAX buf MD_i as a hex string */
4638
4639 for (j = 0; j < 100; j++) {
4640 /* MD_0 = MD_1 = MD_2 = seed */
4641 memcpy(MD_i3, seed, MDLen);
4642 memcpy(MD_i2, seed, MDLen);
4643 memcpy(MD_i1, seed, MDLen);
4644
4645 for (i = 3; i < 1003; i++) {
4646 /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */
4647 memcpy(msg, MD_i3, MDLen);
4648 memcpy(&msg[MDLen], MD_i2, MDLen);
4649 memcpy(&msg[MDLen * 2], MD_i1, MDLen);
4650
4651 /* MDi = SHA(Msg) */
4652 if (sha_calcMD(MD_i, MDLen,
4653 msg, msgLen) != SECSuccess) {
4654 return SECFailure;
4655 }
4656
4657 /* save MD[i-3] MD[i-2] MD[i-1] */
4658 memcpy(MD_i3, MD_i2, MDLen);
4659 memcpy(MD_i2, MD_i1, MDLen);
4660 memcpy(MD_i1, MD_i, MDLen);
4661 }
4662
4663 /* seed = MD_i */
4664 memcpy(seed, MD_i, MDLen);
4665
4666 sprintf(buf, "COUNT = %d\n", j);
4667 fputs(buf, resp);
4668
4669 /* output MD_i */
4670 fputs("MD = ", resp);
4671 to_hex_str(buf, MD_i, MDLen);
4672 fputs(buf, resp);
4673 fputc('\n', resp);
4674 }
4675
4676 return SECSuccess;
4677 }
4678
4679 /*
4680 * Perform the SHA Tests.
4681 *
4682 * reqfn is the pathname of the input REQUEST file.
4683 *
4684 * The output RESPONSE file is written to stdout.
4685 */
4686 void
sha_test(char * reqfn)4687 sha_test(char *reqfn)
4688 {
4689 unsigned int i, j;
4690 unsigned int MDlen = 0; /* the length of the Message Digest in Bytes */
4691 unsigned int msgLen = 0; /* the length of the input Message in Bytes */
4692 unsigned char *msg = NULL; /* holds the message to digest.*/
4693 size_t bufSize = 256 * 128; /*MAX buffer size */
4694 char *buf = NULL; /* holds one line from the input REQUEST file.*/
4695 unsigned char seed[HASH_LENGTH_MAX]; /* max size of seed 64 bytes */
4696 unsigned char MD[HASH_LENGTH_MAX]; /* message digest */
4697
4698 FILE *req = NULL; /* input stream from the REQUEST file */
4699 FILE *resp; /* output stream to the RESPONSE file */
4700
4701 buf = PORT_ZAlloc(bufSize);
4702 if (buf == NULL) {
4703 goto loser;
4704 }
4705
4706 /* zeroize the variables for the test with this data set */
4707 memset(seed, 0, sizeof seed);
4708
4709 req = fopen(reqfn, "r");
4710 resp = stdout;
4711 while (fgets(buf, bufSize, req) != NULL) {
4712
4713 /* a comment or blank line */
4714 if (buf[0] == '#' || buf[0] == '\n') {
4715 fputs(buf, resp);
4716 continue;
4717 }
4718 /* [L = Length of the Message Digest and sha_type */
4719 if (buf[0] == '[') {
4720 if (strncmp(&buf[1], "L ", 1) == 0) {
4721 i = 2;
4722 while (isspace(buf[i]) || buf[i] == '=') {
4723 i++;
4724 }
4725 MDlen = atoi(&buf[i]);
4726 fputs(buf, resp);
4727 continue;
4728 }
4729 }
4730 /* Len = Length of the Input Message Length ... */
4731 if (strncmp(buf, "Len", 3) == 0) {
4732 i = 3;
4733 while (isspace(buf[i]) || buf[i] == '=') {
4734 i++;
4735 }
4736 if (msg) {
4737 PORT_ZFree(msg, msgLen);
4738 msg = NULL;
4739 }
4740 msgLen = atoi(&buf[i]); /* in bits */
4741 if (msgLen % 8 != 0) {
4742 fprintf(stderr, "SHA tests are incorrectly configured for "
4743 "BIT oriented implementations\n");
4744 goto loser;
4745 }
4746 msgLen = msgLen / 8; /* convert to bytes */
4747 fputs(buf, resp);
4748 msg = PORT_ZAlloc(msgLen);
4749 if (msg == NULL && msgLen != 0) {
4750 goto loser;
4751 }
4752 continue;
4753 }
4754 /* MSG = ... */
4755 if (strncmp(buf, "Msg", 3) == 0) {
4756 i = 3;
4757 while (isspace(buf[i]) || buf[i] == '=') {
4758 i++;
4759 }
4760 for (j = 0; j < msgLen; i += 2, j++) {
4761 hex_to_byteval(&buf[i], &msg[j]);
4762 }
4763 fputs(buf, resp);
4764 /* calculate the Message Digest */
4765 memset(MD, 0, sizeof MD);
4766 if (sha_calcMD(MD, MDlen,
4767 msg, msgLen) != SECSuccess) {
4768 goto loser;
4769 }
4770
4771 fputs("MD = ", resp);
4772 to_hex_str(buf, MD, MDlen);
4773 fputs(buf, resp);
4774 fputc('\n', resp);
4775
4776 continue;
4777 }
4778 /* Seed = ... */
4779 if (strncmp(buf, "Seed", 4) == 0) {
4780 i = 4;
4781 while (isspace(buf[i]) || buf[i] == '=') {
4782 i++;
4783 }
4784 for (j = 0; j < sizeof seed; i += 2, j++) {
4785 hex_to_byteval(&buf[i], &seed[j]);
4786 }
4787
4788 fputs(buf, resp);
4789 fputc('\n', resp);
4790
4791 /* do the Monte Carlo test */
4792 if (sha_mct_test(MDlen, seed, resp) != SECSuccess) {
4793 goto loser;
4794 }
4795
4796 continue;
4797 }
4798 }
4799 loser:
4800 if (req) {
4801 fclose(req);
4802 }
4803 if (buf) {
4804 PORT_ZFree(buf, bufSize);
4805 }
4806 if (msg) {
4807 PORT_ZFree(msg, msgLen);
4808 }
4809 }
4810
4811 /****************************************************/
4812 /* HMAC SHA-X calc */
4813 /* hmac_computed - the computed HMAC */
4814 /* hmac_length - the length of the computed HMAC */
4815 /* secret_key - secret key to HMAC */
4816 /* secret_key_length - length of secret key, */
4817 /* message - message to HMAC */
4818 /* message_length - length ofthe message */
4819 /****************************************************/
4820 static SECStatus
hmac_calc(unsigned char * hmac_computed,const unsigned int hmac_length,const unsigned char * secret_key,const unsigned int secret_key_length,const unsigned char * message,const unsigned int message_length,const HASH_HashType hashAlg)4821 hmac_calc(unsigned char *hmac_computed,
4822 const unsigned int hmac_length,
4823 const unsigned char *secret_key,
4824 const unsigned int secret_key_length,
4825 const unsigned char *message,
4826 const unsigned int message_length,
4827 const HASH_HashType hashAlg)
4828 {
4829 SECStatus hmac_status = SECFailure;
4830 HMACContext *cx = NULL;
4831 SECHashObject *hashObj = NULL;
4832 unsigned int bytes_hashed = 0;
4833
4834 hashObj = (SECHashObject *)HASH_GetRawHashObject(hashAlg);
4835
4836 if (!hashObj)
4837 return (SECFailure);
4838
4839 cx = HMAC_Create(hashObj, secret_key,
4840 secret_key_length,
4841 PR_TRUE); /* PR_TRUE for in FIPS mode */
4842
4843 if (cx == NULL)
4844 return (SECFailure);
4845
4846 HMAC_Begin(cx);
4847 HMAC_Update(cx, message, message_length);
4848 hmac_status = HMAC_Finish(cx, hmac_computed, &bytes_hashed,
4849 hmac_length);
4850
4851 HMAC_Destroy(cx, PR_TRUE);
4852
4853 return (hmac_status);
4854 }
4855
4856 /*
4857 * Perform the HMAC Tests.
4858 *
4859 * reqfn is the pathname of the input REQUEST file.
4860 *
4861 * The output RESPONSE file is written to stdout.
4862 */
4863 void
hmac_test(char * reqfn)4864 hmac_test(char *reqfn)
4865 {
4866 unsigned int i, j;
4867 size_t bufSize = 400; /* MAX buffer size */
4868 char *buf = NULL; /* holds one line from the input REQUEST file.*/
4869 unsigned int keyLen = 0; /* Key Length */
4870 unsigned char key[200]; /* key MAX size = 184 */
4871 unsigned int msgLen = 128; /* the length of the input */
4872 /* Message is always 128 Bytes */
4873 unsigned char *msg = NULL; /* holds the message to digest.*/
4874 unsigned int HMACLen = 0; /* the length of the HMAC Bytes */
4875 unsigned int TLen = 0; /* the length of the requested */
4876 /* truncated HMAC Bytes */
4877 unsigned char HMAC[HASH_LENGTH_MAX]; /* computed HMAC */
4878 unsigned char expectedHMAC[HASH_LENGTH_MAX]; /* for .fax files that have */
4879 /* supplied known answer */
4880 HASH_HashType hash_alg = HASH_AlgNULL; /* HMAC type */
4881
4882 FILE *req = NULL; /* input stream from the REQUEST file */
4883 FILE *resp; /* output stream to the RESPONSE file */
4884
4885 buf = PORT_ZAlloc(bufSize);
4886 if (buf == NULL) {
4887 goto loser;
4888 }
4889 msg = PORT_ZAlloc(msgLen);
4890 if (msg == NULL) {
4891 goto loser;
4892 }
4893
4894 req = fopen(reqfn, "r");
4895 resp = stdout;
4896 while (fgets(buf, bufSize, req) != NULL) {
4897 if (strncmp(buf, "Mac", 3) == 0) {
4898 i = 3;
4899 while (isspace(buf[i]) || buf[i] == '=') {
4900 i++;
4901 }
4902 memset(expectedHMAC, 0, HASH_LENGTH_MAX);
4903 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
4904 hex_to_byteval(&buf[i], &expectedHMAC[j]);
4905 }
4906 if (memcmp(HMAC, expectedHMAC, TLen) != 0) {
4907 fprintf(stderr, "Generate failed:\n");
4908 fputs(" expected=", stderr);
4909 to_hex_str(buf, expectedHMAC,
4910 TLen);
4911 fputs(buf, stderr);
4912 fputs("\n generated=", stderr);
4913 to_hex_str(buf, HMAC,
4914 TLen);
4915 fputs(buf, stderr);
4916 fputc('\n', stderr);
4917 }
4918 }
4919
4920 /* a comment or blank line */
4921 if (buf[0] == '#' || buf[0] == '\n') {
4922 fputs(buf, resp);
4923 continue;
4924 }
4925 /* [L = Length of the MAC and HASH_type */
4926 if (buf[0] == '[') {
4927 if (strncmp(&buf[1], "L ", 1) == 0) {
4928 i = 2;
4929 while (isspace(buf[i]) || buf[i] == '=') {
4930 i++;
4931 }
4932 /* HMACLen will get reused for Tlen */
4933 HMACLen = atoi(&buf[i]);
4934 hash_alg = sha_get_hashType(HMACLen * PR_BITS_PER_BYTE);
4935 if (hash_alg == HASH_AlgNULL) {
4936 goto loser;
4937 }
4938 fputs(buf, resp);
4939 continue;
4940 }
4941 }
4942 /* Count = test iteration number*/
4943 if (strncmp(buf, "Count ", 5) == 0) {
4944 /* count can just be put into resp file */
4945 fputs(buf, resp);
4946 /* zeroize the variables for the test with this data set */
4947 keyLen = 0;
4948 TLen = 0;
4949 memset(key, 0, sizeof key);
4950 memset(msg, 0, msgLen);
4951 memset(HMAC, 0, sizeof HMAC);
4952 continue;
4953 }
4954 /* KLen = Length of the Input Secret Key ... */
4955 if (strncmp(buf, "Klen", 4) == 0) {
4956 i = 4;
4957 while (isspace(buf[i]) || buf[i] == '=') {
4958 i++;
4959 }
4960 keyLen = atoi(&buf[i]); /* in bytes */
4961 fputs(buf, resp);
4962 continue;
4963 }
4964 /* key = the secret key for the key to MAC */
4965 if (strncmp(buf, "Key", 3) == 0) {
4966 i = 3;
4967 while (isspace(buf[i]) || buf[i] == '=') {
4968 i++;
4969 }
4970 for (j = 0; j < keyLen; i += 2, j++) {
4971 hex_to_byteval(&buf[i], &key[j]);
4972 }
4973 fputs(buf, resp);
4974 }
4975 /* TLen = Length of the calculated HMAC */
4976 if (strncmp(buf, "Tlen", 4) == 0) {
4977 i = 4;
4978 while (isspace(buf[i]) || buf[i] == '=') {
4979 i++;
4980 }
4981 TLen = atoi(&buf[i]); /* in bytes */
4982 fputs(buf, resp);
4983 continue;
4984 }
4985 /* MSG = to HMAC always 128 bytes for these tests */
4986 if (strncmp(buf, "Msg", 3) == 0) {
4987 i = 3;
4988 while (isspace(buf[i]) || buf[i] == '=') {
4989 i++;
4990 }
4991 for (j = 0; j < msgLen; i += 2, j++) {
4992 hex_to_byteval(&buf[i], &msg[j]);
4993 }
4994 fputs(buf, resp);
4995 /* calculate the HMAC and output */
4996 if (hmac_calc(HMAC, HMACLen, key, keyLen,
4997 msg, msgLen, hash_alg) != SECSuccess) {
4998 goto loser;
4999 }
5000 fputs("Mac = ", resp);
5001 to_hex_str(buf, HMAC, TLen);
5002 fputs(buf, resp);
5003 fputc('\n', resp);
5004 continue;
5005 }
5006 }
5007 loser:
5008 if (req) {
5009 fclose(req);
5010 }
5011 if (buf) {
5012 PORT_ZFree(buf, bufSize);
5013 }
5014 if (msg) {
5015 PORT_ZFree(msg, msgLen);
5016 }
5017 }
5018
5019 /*
5020 * Perform the DSA Key Pair Generation Test.
5021 *
5022 * reqfn is the pathname of the REQUEST file.
5023 *
5024 * The output RESPONSE file is written to stdout.
5025 */
5026 void
dsa_keypair_test(char * reqfn)5027 dsa_keypair_test(char *reqfn)
5028 {
5029 char buf[800]; /* holds one line from the input REQUEST file
5030 * or to the output RESPONSE file.
5031 * 800 to hold (384 public key (x2 for HEX) + 1'\n'
5032 */
5033 FILE *dsareq; /* input stream from the REQUEST file */
5034 FILE *dsaresp; /* output stream to the RESPONSE file */
5035 int count;
5036 int N;
5037 int L;
5038 int i;
5039 PQGParams *pqg = NULL;
5040 PQGVerify *vfy = NULL;
5041 PRBool use_dsa1 = PR_FALSE;
5042 int keySizeIndex; /* index for valid key sizes */
5043
5044 dsareq = fopen(reqfn, "r");
5045 dsaresp = stdout;
5046 while (fgets(buf, sizeof buf, dsareq) != NULL) {
5047 /* a comment or blank line */
5048 if (buf[0] == '#' || buf[0] == '\n') {
5049 fputs(buf, dsaresp);
5050 continue;
5051 }
5052
5053 /* [Mod = x] */
5054 if (buf[0] == '[') {
5055 if (pqg != NULL) {
5056 PQG_DestroyParams(pqg);
5057 pqg = NULL;
5058 }
5059 if (vfy != NULL) {
5060 PQG_DestroyVerify(vfy);
5061 vfy = NULL;
5062 }
5063
5064 if (sscanf(buf, "[mod = L=%d, N=%d]", &L, &N) != 2) {
5065 use_dsa1 = PR_TRUE;
5066 if (sscanf(buf, "[mod = %d]", &L) != 1) {
5067 goto loser;
5068 }
5069 }
5070 fputs(buf, dsaresp);
5071 fputc('\n', dsaresp);
5072
5073 if (use_dsa1) {
5074 /*************************************************************
5075 * PQG_ParamGenSeedLen doesn't take a key size, it takes an
5076 * index that points to a valid key size.
5077 */
5078 keySizeIndex = PQG_PBITS_TO_INDEX(L);
5079 if (keySizeIndex == -1 || L < 512 || L > 1024) {
5080 fprintf(dsaresp,
5081 "DSA key size must be a multiple of 64 between 512 "
5082 "and 1024, inclusive");
5083 goto loser;
5084 }
5085
5086 /* Generate the parameters P, Q, and G */
5087 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
5088 &pqg, &vfy) !=
5089 SECSuccess) {
5090 fprintf(dsaresp,
5091 "ERROR: Unable to generate PQG parameters");
5092 goto loser;
5093 }
5094 } else {
5095 if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
5096 fprintf(dsaresp,
5097 "ERROR: Unable to generate PQG parameters");
5098 goto loser;
5099 }
5100 }
5101
5102 /* output P, Q, and G */
5103 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
5104 fprintf(dsaresp, "P = %s\n", buf);
5105 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
5106 fprintf(dsaresp, "Q = %s\n", buf);
5107 to_hex_str(buf, pqg->base.data, pqg->base.len);
5108 fprintf(dsaresp, "G = %s\n\n", buf);
5109 continue;
5110 }
5111 /* N = ...*/
5112 if (buf[0] == 'N') {
5113
5114 if (sscanf(buf, "N = %d", &count) != 1) {
5115 goto loser;
5116 }
5117 /* Generate a DSA key, and output the key pair for N times */
5118 for (i = 0; i < count; i++) {
5119 DSAPrivateKey *dsakey = NULL;
5120 if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
5121 fprintf(dsaresp, "ERROR: Unable to generate DSA key");
5122 goto loser;
5123 }
5124 to_hex_str(buf, dsakey->privateValue.data,
5125 dsakey->privateValue.len);
5126 fprintf(dsaresp, "X = %s\n", buf);
5127 to_hex_str(buf, dsakey->publicValue.data,
5128 dsakey->publicValue.len);
5129 fprintf(dsaresp, "Y = %s\n\n", buf);
5130 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
5131 dsakey = NULL;
5132 }
5133 continue;
5134 }
5135 }
5136 loser:
5137 fclose(dsareq);
5138 }
5139
5140 /*
5141 * pqg generation type
5142 */
5143 typedef enum {
5144 FIPS186_1, /* Generate/Verify P,Q & G according to FIPS 186-1 */
5145 A_1_2_1, /* Generate Provable P & Q */
5146 A_1_1_3, /* Verify Probable P & Q */
5147 A_1_2_2, /* Verify Provable P & Q */
5148 A_2_1, /* Generate Unverifiable G */
5149 A_2_2, /* Assure Unverifiable G */
5150 A_2_3, /* Generate Verifiable G */
5151 A_2_4 /* Verify Verifiable G */
5152 } dsa_pqg_type;
5153
5154 /*
5155 * Perform the DSA Domain Parameter Validation Test.
5156 *
5157 * reqfn is the pathname of the REQUEST file.
5158 *
5159 * The output RESPONSE file is written to stdout.
5160 */
5161 void
dsa_pqgver_test(char * reqfn)5162 dsa_pqgver_test(char *reqfn)
5163 {
5164 char buf[800]; /* holds one line from the input REQUEST file
5165 * or to the output RESPONSE file.
5166 * 800 to hold (384 public key (x2 for HEX) + P = ...
5167 */
5168 FILE *dsareq; /* input stream from the REQUEST file */
5169 FILE *dsaresp; /* output stream to the RESPONSE file */
5170 int N;
5171 int L;
5172 unsigned int i, j;
5173 PQGParams pqg;
5174 PQGVerify vfy;
5175 unsigned int pghSize = 0; /* size for p, g, and h */
5176 dsa_pqg_type type = FIPS186_1;
5177
5178 dsareq = fopen(reqfn, "r");
5179 dsaresp = stdout;
5180 memset(&pqg, 0, sizeof(pqg));
5181 memset(&vfy, 0, sizeof(vfy));
5182
5183 while (fgets(buf, sizeof buf, dsareq) != NULL) {
5184 /* a comment or blank line */
5185 if (buf[0] == '#' || buf[0] == '\n') {
5186 fputs(buf, dsaresp);
5187 continue;
5188 }
5189
5190 /* [A.xxxxx ] */
5191 if (buf[0] == '[' && buf[1] == 'A') {
5192
5193 if (strncmp(&buf[1], "A.1.1.3", 7) == 0) {
5194 type = A_1_1_3;
5195 } else if (strncmp(&buf[1], "A.2.2", 5) == 0) {
5196 type = A_2_2;
5197 } else if (strncmp(&buf[1], "A.2.4", 5) == 0) {
5198 type = A_2_4;
5199 } else if (strncmp(&buf[1], "A.1.2.2", 7) == 0) {
5200 type = A_1_2_2;
5201 /* validate our output from PQGGEN */
5202 } else if (strncmp(&buf[1], "A.1.1.2", 7) == 0) {
5203 type = A_2_4; /* validate PQ and G together */
5204 } else {
5205 fprintf(stderr, "Unknown dsa ver test %s\n", &buf[1]);
5206 exit(1);
5207 }
5208
5209 fputs(buf, dsaresp);
5210 continue;
5211 }
5212
5213 /* [Mod = x] */
5214 if (buf[0] == '[') {
5215
5216 if (type == FIPS186_1) {
5217 N = 160;
5218 if (sscanf(buf, "[mod = %d]", &L) != 1) {
5219 goto loser;
5220 }
5221 } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
5222 goto loser;
5223 }
5224
5225 if (pqg.prime.data) { /* P */
5226 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
5227 }
5228 if (pqg.subPrime.data) { /* Q */
5229 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
5230 }
5231 if (pqg.base.data) { /* G */
5232 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
5233 }
5234 if (vfy.seed.data) { /* seed */
5235 SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
5236 }
5237 if (vfy.h.data) { /* H */
5238 SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
5239 }
5240
5241 fputs(buf, dsaresp);
5242
5243 /*calculate the size of p, g, and h then allocate items */
5244 pghSize = L / 8;
5245
5246 pqg.base.data = vfy.h.data = NULL;
5247 vfy.seed.len = pqg.base.len = vfy.h.len = 0;
5248 SECITEM_AllocItem(NULL, &pqg.prime, pghSize);
5249 SECITEM_AllocItem(NULL, &vfy.seed, pghSize * 3);
5250 if (type == A_2_2) {
5251 SECITEM_AllocItem(NULL, &vfy.h, pghSize);
5252 vfy.h.len = pghSize;
5253 } else if (type == A_2_4) {
5254 SECITEM_AllocItem(NULL, &vfy.h, 1);
5255 vfy.h.len = 1;
5256 }
5257 pqg.prime.len = pghSize;
5258 /* q is always N bits */
5259 SECITEM_AllocItem(NULL, &pqg.subPrime, N / 8);
5260 pqg.subPrime.len = N / 8;
5261 vfy.counter = -1;
5262
5263 continue;
5264 }
5265 /* P = ... */
5266 if (buf[0] == 'P') {
5267 i = 1;
5268 while (isspace(buf[i]) || buf[i] == '=') {
5269 i++;
5270 }
5271 for (j = 0; j < pqg.prime.len; i += 2, j++) {
5272 hex_to_byteval(&buf[i], &pqg.prime.data[j]);
5273 }
5274
5275 fputs(buf, dsaresp);
5276 continue;
5277 }
5278
5279 /* Q = ... */
5280 if (buf[0] == 'Q') {
5281 i = 1;
5282 while (isspace(buf[i]) || buf[i] == '=') {
5283 i++;
5284 }
5285 for (j = 0; j < pqg.subPrime.len; i += 2, j++) {
5286 hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
5287 }
5288
5289 fputs(buf, dsaresp);
5290 continue;
5291 }
5292
5293 /* G = ... */
5294 if (buf[0] == 'G') {
5295 i = 1;
5296 if (pqg.base.data) {
5297 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
5298 }
5299 SECITEM_AllocItem(NULL, &pqg.base, pghSize);
5300 while (isspace(buf[i]) || buf[i] == '=') {
5301 i++;
5302 }
5303 for (j = 0; j < pqg.base.len; i += 2, j++) {
5304 hex_to_byteval(&buf[i], &pqg.base.data[j]);
5305 }
5306
5307 fputs(buf, dsaresp);
5308 continue;
5309 }
5310
5311 /* Seed = ... or domain_parameter_seed = ... */
5312 if (strncmp(buf, "Seed", 4) == 0) {
5313 i = 4;
5314 } else if (strncmp(buf, "domain_parameter_seed", 21) == 0) {
5315 i = 21;
5316 } else if (strncmp(buf, "firstseed", 9) == 0) {
5317 i = 9;
5318 } else {
5319 i = 0;
5320 }
5321 if (i) {
5322 while (isspace(buf[i]) || buf[i] == '=') {
5323 i++;
5324 }
5325 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
5326 hex_to_byteval(&buf[i], &vfy.seed.data[j]);
5327 }
5328 vfy.seed.len = j;
5329
5330 fputs(buf, dsaresp);
5331 if (type == A_2_4) {
5332 SECStatus result;
5333
5334 /* Verify the Parameters */
5335 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
5336 if (rv != SECSuccess) {
5337 goto loser;
5338 }
5339 if (result == SECSuccess) {
5340 fprintf(dsaresp, "Result = P\n");
5341 } else {
5342 fprintf(dsaresp, "Result = F\n");
5343 }
5344 }
5345 continue;
5346 }
5347 if ((strncmp(buf, "pseed", 5) == 0) ||
5348 (strncmp(buf, "qseed", 5) == 0)) {
5349 i = 5;
5350 while (isspace(buf[i]) || buf[i] == '=') {
5351 i++;
5352 }
5353 for (j = vfy.seed.len; isxdigit(buf[i]); i += 2, j++) {
5354 hex_to_byteval(&buf[i], &vfy.seed.data[j]);
5355 }
5356 vfy.seed.len = j;
5357 fputs(buf, dsaresp);
5358
5359 continue;
5360 }
5361 if (strncmp(buf, "index", 4) == 0) {
5362 i = 5;
5363 while (isspace(buf[i]) || buf[i] == '=') {
5364 i++;
5365 }
5366 hex_to_byteval(&buf[i], &vfy.h.data[0]);
5367 vfy.h.len = 1;
5368 fputs(buf, dsaresp);
5369 }
5370
5371 /* c = ... or counter=*/
5372 if (buf[0] == 'c') {
5373 if (strncmp(buf, "counter", 7) == 0) {
5374 if (sscanf(buf, "counter = %u", &vfy.counter) != 1) {
5375 goto loser;
5376 }
5377 } else {
5378 if (sscanf(buf, "c = %u", &vfy.counter) != 1) {
5379 goto loser;
5380 }
5381 }
5382
5383 fputs(buf, dsaresp);
5384 if (type == A_1_1_3) {
5385 SECStatus result;
5386 /* only verify P and Q, we have everything now. do it */
5387 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
5388 if (rv != SECSuccess) {
5389 goto loser;
5390 }
5391 if (result == SECSuccess) {
5392 fprintf(dsaresp, "Result = P\n");
5393 } else {
5394 fprintf(dsaresp, "Result = F\n");
5395 }
5396 fprintf(dsaresp, "\n");
5397 }
5398 continue;
5399 }
5400 if (strncmp(buf, "pgen_counter", 12) == 0) {
5401 if (sscanf(buf, "pgen_counter = %u", &vfy.counter) != 1) {
5402 goto loser;
5403 }
5404 fputs(buf, dsaresp);
5405 continue;
5406 }
5407 if (strncmp(buf, "qgen_counter", 12) == 0) {
5408 fputs(buf, dsaresp);
5409 if (type == A_1_2_2) {
5410 SECStatus result;
5411 /* only verify P and Q, we have everything now. do it */
5412 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
5413 if (rv != SECSuccess) {
5414 goto loser;
5415 }
5416 if (result == SECSuccess) {
5417 fprintf(dsaresp, "Result = P\n");
5418 } else {
5419 fprintf(dsaresp, "Result = F\n");
5420 }
5421 fprintf(dsaresp, "\n");
5422 }
5423 continue;
5424 }
5425 /* H = ... */
5426 if (buf[0] == 'H') {
5427 SECStatus rv, result = SECFailure;
5428
5429 i = 1;
5430 while (isspace(buf[i]) || buf[i] == '=') {
5431 i++;
5432 }
5433 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
5434 hex_to_byteval(&buf[i], &vfy.h.data[j]);
5435 }
5436 vfy.h.len = j;
5437 fputs(buf, dsaresp);
5438
5439 /* this should be a byte value. Remove the leading zeros. If
5440 * it doesn't reduce to a byte, PQG_VerifyParams will catch it
5441 if (type == A_2_2) {
5442 data_save = vfy.h.data;
5443 while(vfy.h.data[0] && (vfy.h.len > 1)) {
5444 vfy.h.data++;
5445 vfy.h.len--;
5446 }
5447 } */
5448
5449 /* Verify the Parameters */
5450 rv = PQG_VerifyParams(&pqg, &vfy, &result);
5451 if (rv != SECSuccess) {
5452 goto loser;
5453 }
5454 if (result == SECSuccess) {
5455 fprintf(dsaresp, "Result = P\n");
5456 } else {
5457 fprintf(dsaresp, "Result = F\n");
5458 }
5459 fprintf(dsaresp, "\n");
5460 continue;
5461 }
5462 }
5463 loser:
5464 fclose(dsareq);
5465 if (pqg.prime.data) { /* P */
5466 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
5467 }
5468 if (pqg.subPrime.data) { /* Q */
5469 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
5470 }
5471 if (pqg.base.data) { /* G */
5472 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
5473 }
5474 if (vfy.seed.data) { /* seed */
5475 SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
5476 }
5477 if (vfy.h.data) { /* H */
5478 SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
5479 }
5480 }
5481
5482 /*
5483 * Perform the DSA Public Key Validation Test.
5484 *
5485 * reqfn is the pathname of the REQUEST file.
5486 *
5487 * The output RESPONSE file is written to stdout.
5488 */
5489 void
dsa_pqggen_test(char * reqfn)5490 dsa_pqggen_test(char *reqfn)
5491 {
5492 char buf[800]; /* holds one line from the input REQUEST file
5493 * or to the output RESPONSE file.
5494 * 800 to hold seed = (384 public key (x2 for HEX)
5495 */
5496 FILE *dsareq; /* input stream from the REQUEST file */
5497 FILE *dsaresp; /* output stream to the RESPONSE file */
5498 int count; /* number of times to generate parameters */
5499 int N;
5500 int L;
5501 int i;
5502 unsigned int j;
5503 int output_g = 1;
5504 PQGParams *pqg = NULL;
5505 PQGVerify *vfy = NULL;
5506 unsigned int keySizeIndex = 0;
5507 dsa_pqg_type type = FIPS186_1;
5508
5509 dsareq = fopen(reqfn, "r");
5510 dsaresp = stdout;
5511 while (fgets(buf, sizeof buf, dsareq) != NULL) {
5512 /* a comment or blank line */
5513 if (buf[0] == '#' || buf[0] == '\n') {
5514 fputs(buf, dsaresp);
5515 continue;
5516 }
5517
5518 /* [A.xxxxx ] */
5519 if (buf[0] == '[' && buf[1] == 'A') {
5520 if (strncmp(&buf[1], "A.1.1.2", 7) == 0) {
5521 fprintf(stderr, "NSS does Generate Probablistic Primes\n");
5522 exit(1);
5523 } else if (strncmp(&buf[1], "A.2.1", 5) == 0) {
5524 type = A_1_2_1;
5525 output_g = 1;
5526 exit(1);
5527 } else if (strncmp(&buf[1], "A.2.3", 5) == 0) {
5528 fprintf(stderr, "NSS only Generates G with P&Q\n");
5529 exit(1);
5530 } else if (strncmp(&buf[1], "A.1.2.1", 7) == 0) {
5531 type = A_1_2_1;
5532 output_g = 0;
5533 } else {
5534 fprintf(stderr, "Unknown dsa pqggen test %s\n", &buf[1]);
5535 exit(1);
5536 }
5537 fputs(buf, dsaresp);
5538 continue;
5539 }
5540
5541 /* [Mod = ... ] */
5542 if (buf[0] == '[') {
5543
5544 if (type == FIPS186_1) {
5545 N = 160;
5546 if (sscanf(buf, "[mod = %d]", &L) != 1) {
5547 goto loser;
5548 }
5549 } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
5550 goto loser;
5551 }
5552
5553 fputs(buf, dsaresp);
5554 fputc('\n', dsaresp);
5555
5556 if (type == FIPS186_1) {
5557 /************************************************************
5558 * PQG_ParamGenSeedLen doesn't take a key size, it takes an
5559 * index that points to a valid key size.
5560 */
5561 keySizeIndex = PQG_PBITS_TO_INDEX(L);
5562 if (keySizeIndex == -1 || L < 512 || L > 1024) {
5563 fprintf(dsaresp,
5564 "DSA key size must be a multiple of 64 between 512 "
5565 "and 1024, inclusive");
5566 goto loser;
5567 }
5568 }
5569 continue;
5570 }
5571 /* N = ... */
5572 if (buf[0] == 'N') {
5573 if (strncmp(buf, "Num", 3) == 0) {
5574 if (sscanf(buf, "Num = %d", &count) != 1) {
5575 goto loser;
5576 }
5577 } else if (sscanf(buf, "N = %d", &count) != 1) {
5578 goto loser;
5579 }
5580 for (i = 0; i < count; i++) {
5581 SECStatus rv;
5582
5583 if (type == FIPS186_1) {
5584 rv = PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
5585 &pqg, &vfy);
5586 } else {
5587 rv = PQG_ParamGenV2(L, N, N, &pqg, &vfy);
5588 }
5589 if (rv != SECSuccess) {
5590 fprintf(dsaresp,
5591 "ERROR: Unable to generate PQG parameters");
5592 goto loser;
5593 }
5594 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
5595 fprintf(dsaresp, "P = %s\n", buf);
5596 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
5597 fprintf(dsaresp, "Q = %s\n", buf);
5598 if (output_g) {
5599 to_hex_str(buf, pqg->base.data, pqg->base.len);
5600 fprintf(dsaresp, "G = %s\n", buf);
5601 }
5602 if (type == FIPS186_1) {
5603 to_hex_str(buf, vfy->seed.data, vfy->seed.len);
5604 fprintf(dsaresp, "Seed = %s\n", buf);
5605 fprintf(dsaresp, "c = %d\n", vfy->counter);
5606 to_hex_str(buf, vfy->h.data, vfy->h.len);
5607 fputs("H = ", dsaresp);
5608 for (j = vfy->h.len; j < pqg->prime.len; j++) {
5609 fprintf(dsaresp, "00");
5610 }
5611 fprintf(dsaresp, "%s\n", buf);
5612 } else {
5613 unsigned int seedlen = vfy->seed.len / 2;
5614 unsigned int pgen_counter = vfy->counter >> 16;
5615 unsigned int qgen_counter = vfy->counter & 0xffff;
5616 /*fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]); */
5617 to_hex_str(buf, vfy->seed.data, seedlen);
5618 fprintf(dsaresp, "pseed = %s\n", buf);
5619 to_hex_str(buf, vfy->seed.data + seedlen, seedlen);
5620 fprintf(dsaresp, "qseed = %s\n", buf);
5621 fprintf(dsaresp, "pgen_counter = %d\n", pgen_counter);
5622 fprintf(dsaresp, "qgen_counter = %d\n", qgen_counter);
5623 if (output_g) {
5624 to_hex_str(buf, vfy->seed.data, vfy->seed.len);
5625 fprintf(dsaresp, "domain_parameter_seed = %s\n", buf);
5626 fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]);
5627 }
5628 }
5629 fputc('\n', dsaresp);
5630 if (pqg != NULL) {
5631 PQG_DestroyParams(pqg);
5632 pqg = NULL;
5633 }
5634 if (vfy != NULL) {
5635 PQG_DestroyVerify(vfy);
5636 vfy = NULL;
5637 }
5638 }
5639
5640 continue;
5641 }
5642 }
5643 loser:
5644 fclose(dsareq);
5645 if (pqg != NULL) {
5646 PQG_DestroyParams(pqg);
5647 }
5648 if (vfy != NULL) {
5649 PQG_DestroyVerify(vfy);
5650 }
5651 }
5652
5653 /*
5654 * Perform the DSA Signature Generation Test.
5655 *
5656 * reqfn is the pathname of the REQUEST file.
5657 *
5658 * The output RESPONSE file is written to stdout.
5659 */
5660 void
dsa_siggen_test(char * reqfn)5661 dsa_siggen_test(char *reqfn)
5662 {
5663 char buf[800]; /* holds one line from the input REQUEST file
5664 * or to the output RESPONSE file.
5665 * max for Msg = ....
5666 */
5667 FILE *dsareq; /* input stream from the REQUEST file */
5668 FILE *dsaresp; /* output stream to the RESPONSE file */
5669 int modulus;
5670 int L;
5671 int N;
5672 int i, j;
5673 PRBool use_dsa1 = PR_FALSE;
5674 PQGParams *pqg = NULL;
5675 PQGVerify *vfy = NULL;
5676 DSAPrivateKey *dsakey = NULL;
5677 int keySizeIndex; /* index for valid key sizes */
5678 unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */
5679 unsigned char sig[DSA_MAX_SIGNATURE_LEN];
5680 SECItem digest, signature;
5681 HASH_HashType hashType = HASH_AlgNULL;
5682 int hashNum = 0;
5683
5684 dsareq = fopen(reqfn, "r");
5685 dsaresp = stdout;
5686
5687 while (fgets(buf, sizeof buf, dsareq) != NULL) {
5688 /* a comment or blank line */
5689 if (buf[0] == '#' || buf[0] == '\n') {
5690 fputs(buf, dsaresp);
5691 continue;
5692 }
5693
5694 /* [Mod = x] */
5695 if (buf[0] == '[') {
5696 if (pqg != NULL) {
5697 PQG_DestroyParams(pqg);
5698 pqg = NULL;
5699 }
5700 if (vfy != NULL) {
5701 PQG_DestroyVerify(vfy);
5702 vfy = NULL;
5703 }
5704 if (dsakey != NULL) {
5705 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
5706 dsakey = NULL;
5707 }
5708
5709 if (sscanf(buf, "[mod = L=%d, N=%d, SHA-%d]", &L, &N,
5710 &hashNum) != 3) {
5711 use_dsa1 = PR_TRUE;
5712 hashNum = 1;
5713 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
5714 goto loser;
5715 }
5716 }
5717 fputs(buf, dsaresp);
5718 fputc('\n', dsaresp);
5719
5720 /****************************************************************
5721 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
5722 * that points to a valid key size.
5723 */
5724 if (use_dsa1) {
5725 keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
5726 if (keySizeIndex == -1 || modulus < 512 || modulus > 1024) {
5727 fprintf(dsaresp,
5728 "DSA key size must be a multiple of 64 between 512 "
5729 "and 1024, inclusive");
5730 goto loser;
5731 }
5732 /* Generate PQG and output PQG */
5733 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
5734 &pqg, &vfy) !=
5735 SECSuccess) {
5736 fprintf(dsaresp,
5737 "ERROR: Unable to generate PQG parameters");
5738 goto loser;
5739 }
5740 } else {
5741 if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
5742 fprintf(dsaresp,
5743 "ERROR: Unable to generate PQG parameters");
5744 goto loser;
5745 }
5746 }
5747 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
5748 fprintf(dsaresp, "P = %s\n", buf);
5749 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
5750 fprintf(dsaresp, "Q = %s\n", buf);
5751 to_hex_str(buf, pqg->base.data, pqg->base.len);
5752 fprintf(dsaresp, "G = %s\n", buf);
5753
5754 /* create DSA Key */
5755 if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
5756 fprintf(dsaresp, "ERROR: Unable to generate DSA key");
5757 goto loser;
5758 }
5759
5760 hashType = sha_get_hashType(hashNum);
5761 if (hashType == HASH_AlgNULL) {
5762 fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)", hashNum);
5763 goto loser;
5764 }
5765 continue;
5766 }
5767
5768 /* Msg = ... */
5769 if (strncmp(buf, "Msg", 3) == 0) {
5770 unsigned char msg[128]; /* MAX msg 128 */
5771 unsigned int len = 0;
5772
5773 if (hashType == HASH_AlgNULL) {
5774 fprintf(dsaresp, "ERROR: Hash Alg not set");
5775 goto loser;
5776 }
5777
5778 memset(hashBuf, 0, sizeof hashBuf);
5779 memset(sig, 0, sizeof sig);
5780
5781 i = 3;
5782 while (isspace(buf[i]) || buf[i] == '=') {
5783 i++;
5784 }
5785 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
5786 hex_to_byteval(&buf[i], &msg[j]);
5787 }
5788 if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) {
5789 fprintf(dsaresp, "ERROR: Unable to generate SHA% digest",
5790 hashNum);
5791 goto loser;
5792 }
5793
5794 digest.type = siBuffer;
5795 digest.data = hashBuf;
5796 digest.len = fips_hashLen(hashType);
5797 signature.type = siBuffer;
5798 signature.data = sig;
5799 signature.len = sizeof sig;
5800
5801 if (DSA_SignDigest(dsakey, &signature, &digest) != SECSuccess) {
5802 fprintf(dsaresp, "ERROR: Unable to generate DSA signature");
5803 goto loser;
5804 }
5805 len = signature.len;
5806 if (len % 2 != 0) {
5807 goto loser;
5808 }
5809 len = len / 2;
5810
5811 /* output the orginal Msg, and generated Y, R, and S */
5812 fputs(buf, dsaresp);
5813 to_hex_str(buf, dsakey->publicValue.data,
5814 dsakey->publicValue.len);
5815 fprintf(dsaresp, "Y = %s\n", buf);
5816 to_hex_str(buf, &signature.data[0], len);
5817 fprintf(dsaresp, "R = %s\n", buf);
5818 to_hex_str(buf, &signature.data[len], len);
5819 fprintf(dsaresp, "S = %s\n", buf);
5820 fputc('\n', dsaresp);
5821 continue;
5822 }
5823 }
5824 loser:
5825 fclose(dsareq);
5826 if (pqg != NULL) {
5827 PQG_DestroyParams(pqg);
5828 pqg = NULL;
5829 }
5830 if (vfy != NULL) {
5831 PQG_DestroyVerify(vfy);
5832 vfy = NULL;
5833 }
5834 if (dsakey) {
5835 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
5836 dsakey = NULL;
5837 }
5838 }
5839
5840 /*
5841 * Perform the DSA Signature Verification Test.
5842 *
5843 * reqfn is the pathname of the REQUEST file.
5844 *
5845 * The output RESPONSE file is written to stdout.
5846 */
5847 void
dsa_sigver_test(char * reqfn)5848 dsa_sigver_test(char *reqfn)
5849 {
5850 char buf[800]; /* holds one line from the input REQUEST file
5851 * or to the output RESPONSE file.
5852 * max for Msg = ....
5853 */
5854 FILE *dsareq; /* input stream from the REQUEST file */
5855 FILE *dsaresp; /* output stream to the RESPONSE file */
5856 int L;
5857 int N;
5858 unsigned int i, j;
5859 SECItem digest, signature;
5860 DSAPublicKey pubkey;
5861 unsigned int pgySize; /* size for p, g, and y */
5862 unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */
5863 unsigned char sig[DSA_MAX_SIGNATURE_LEN];
5864 HASH_HashType hashType = HASH_AlgNULL;
5865 int hashNum = 0;
5866
5867 dsareq = fopen(reqfn, "r");
5868 dsaresp = stdout;
5869 memset(&pubkey, 0, sizeof(pubkey));
5870
5871 while (fgets(buf, sizeof buf, dsareq) != NULL) {
5872 /* a comment or blank line */
5873 if (buf[0] == '#' || buf[0] == '\n') {
5874 fputs(buf, dsaresp);
5875 continue;
5876 }
5877
5878 /* [Mod = x] */
5879 if (buf[0] == '[') {
5880
5881 if (sscanf(buf, "[mod = L=%d, N=%d, SHA-%d]", &L, &N,
5882 &hashNum) != 3) {
5883 N = 160;
5884 hashNum = 1;
5885 if (sscanf(buf, "[mod = %d]", &L) != 1) {
5886 goto loser;
5887 }
5888 }
5889
5890 if (pubkey.params.prime.data) { /* P */
5891 SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
5892 }
5893 if (pubkey.params.subPrime.data) { /* Q */
5894 SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
5895 }
5896 if (pubkey.params.base.data) { /* G */
5897 SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
5898 }
5899 if (pubkey.publicValue.data) { /* Y */
5900 SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
5901 }
5902 fputs(buf, dsaresp);
5903
5904 /* calculate the size of p, g, and y then allocate items */
5905 pgySize = L / 8;
5906 SECITEM_AllocItem(NULL, &pubkey.params.prime, pgySize);
5907 SECITEM_AllocItem(NULL, &pubkey.params.base, pgySize);
5908 SECITEM_AllocItem(NULL, &pubkey.publicValue, pgySize);
5909 pubkey.params.prime.len = pubkey.params.base.len = pgySize;
5910 pubkey.publicValue.len = pgySize;
5911
5912 /* q always N/8 bytes */
5913 SECITEM_AllocItem(NULL, &pubkey.params.subPrime, N / 8);
5914 pubkey.params.subPrime.len = N / 8;
5915
5916 hashType = sha_get_hashType(hashNum);
5917 if (hashType == HASH_AlgNULL) {
5918 fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)", hashNum);
5919 goto loser;
5920 }
5921
5922 continue;
5923 }
5924 /* P = ... */
5925 if (buf[0] == 'P') {
5926 i = 1;
5927 while (isspace(buf[i]) || buf[i] == '=') {
5928 i++;
5929 }
5930 memset(pubkey.params.prime.data, 0, pubkey.params.prime.len);
5931 for (j = 0; j < pubkey.params.prime.len; i += 2, j++) {
5932 hex_to_byteval(&buf[i], &pubkey.params.prime.data[j]);
5933 }
5934
5935 fputs(buf, dsaresp);
5936 continue;
5937 }
5938
5939 /* Q = ... */
5940 if (buf[0] == 'Q') {
5941 i = 1;
5942 while (isspace(buf[i]) || buf[i] == '=') {
5943 i++;
5944 }
5945 memset(pubkey.params.subPrime.data, 0, pubkey.params.subPrime.len);
5946 for (j = 0; j < pubkey.params.subPrime.len; i += 2, j++) {
5947 hex_to_byteval(&buf[i], &pubkey.params.subPrime.data[j]);
5948 }
5949
5950 fputs(buf, dsaresp);
5951 continue;
5952 }
5953
5954 /* G = ... */
5955 if (buf[0] == 'G') {
5956 i = 1;
5957 while (isspace(buf[i]) || buf[i] == '=') {
5958 i++;
5959 }
5960 memset(pubkey.params.base.data, 0, pubkey.params.base.len);
5961 for (j = 0; j < pubkey.params.base.len; i += 2, j++) {
5962 hex_to_byteval(&buf[i], &pubkey.params.base.data[j]);
5963 }
5964
5965 fputs(buf, dsaresp);
5966 continue;
5967 }
5968
5969 /* Msg = ... */
5970 if (strncmp(buf, "Msg", 3) == 0) {
5971 unsigned char msg[128]; /* MAX msg 128 */
5972 memset(hashBuf, 0, sizeof hashBuf);
5973
5974 if (hashType == HASH_AlgNULL) {
5975 fprintf(dsaresp, "ERROR: Hash Alg not set");
5976 goto loser;
5977 }
5978
5979 i = 3;
5980 while (isspace(buf[i]) || buf[i] == '=') {
5981 i++;
5982 }
5983 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
5984 hex_to_byteval(&buf[i], &msg[j]);
5985 }
5986 if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) {
5987 fprintf(dsaresp, "ERROR: Unable to generate SHA-%d digest",
5988 hashNum);
5989 goto loser;
5990 }
5991
5992 fputs(buf, dsaresp);
5993 continue;
5994 }
5995
5996 /* Y = ... */
5997 if (buf[0] == 'Y') {
5998 i = 1;
5999 while (isspace(buf[i]) || buf[i] == '=') {
6000 i++;
6001 }
6002 memset(pubkey.publicValue.data, 0, pubkey.params.subPrime.len);
6003 for (j = 0; j < pubkey.publicValue.len; i += 2, j++) {
6004 hex_to_byteval(&buf[i], &pubkey.publicValue.data[j]);
6005 }
6006
6007 fputs(buf, dsaresp);
6008 continue;
6009 }
6010
6011 /* R = ... */
6012 if (buf[0] == 'R') {
6013 memset(sig, 0, sizeof sig);
6014 i = 1;
6015 while (isspace(buf[i]) || buf[i] == '=') {
6016 i++;
6017 }
6018 for (j = 0; j < pubkey.params.subPrime.len; i += 2, j++) {
6019 hex_to_byteval(&buf[i], &sig[j]);
6020 }
6021
6022 fputs(buf, dsaresp);
6023 continue;
6024 }
6025
6026 /* S = ... */
6027 if (buf[0] == 'S') {
6028 if (hashType == HASH_AlgNULL) {
6029 fprintf(dsaresp, "ERROR: Hash Alg not set");
6030 goto loser;
6031 }
6032
6033 i = 1;
6034 while (isspace(buf[i]) || buf[i] == '=') {
6035 i++;
6036 }
6037 for (j = pubkey.params.subPrime.len;
6038 j < pubkey.params.subPrime.len * 2; i += 2, j++) {
6039 hex_to_byteval(&buf[i], &sig[j]);
6040 }
6041 fputs(buf, dsaresp);
6042
6043 digest.type = siBuffer;
6044 digest.data = hashBuf;
6045 digest.len = fips_hashLen(hashType);
6046 signature.type = siBuffer;
6047 signature.data = sig;
6048 signature.len = pubkey.params.subPrime.len * 2;
6049
6050 if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) {
6051 fprintf(dsaresp, "Result = P\n");
6052 } else {
6053 fprintf(dsaresp, "Result = F\n");
6054 }
6055 fprintf(dsaresp, "\n");
6056 continue;
6057 }
6058 }
6059 loser:
6060 fclose(dsareq);
6061 if (pubkey.params.prime.data) { /* P */
6062 SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
6063 }
6064 if (pubkey.params.subPrime.data) { /* Q */
6065 SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
6066 }
6067 if (pubkey.params.base.data) { /* G */
6068 SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
6069 }
6070 if (pubkey.publicValue.data) { /* Y */
6071 SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
6072 }
6073 }
6074
6075 static void
pad(unsigned char * buf,int pad_len,unsigned char * src,int src_len)6076 pad(unsigned char *buf, int pad_len, unsigned char *src, int src_len)
6077 {
6078 int offset = 0;
6079 /* this shouldn't happen, fail right away rather than produce bad output */
6080 if (pad_len < src_len) {
6081 fprintf(stderr, "data bigger than expected! %d > %d\n", src_len, pad_len);
6082 exit(1);
6083 }
6084
6085 offset = pad_len - src_len;
6086 memset(buf, 0, offset);
6087 memcpy(buf + offset, src, src_len);
6088 return;
6089 }
6090
6091 /*
6092 * Perform the DSA Key Pair Generation Test.
6093 *
6094 * reqfn is the pathname of the REQUEST file.
6095 *
6096 * The output RESPONSE file is written to stdout.
6097 */
6098 void
rsa_keypair_test(char * reqfn)6099 rsa_keypair_test(char *reqfn)
6100 {
6101 char buf[800]; /* holds one line from the input REQUEST file
6102 * or to the output RESPONSE file.
6103 * 800 to hold (384 public key (x2 for HEX) + 1'\n'
6104 */
6105 unsigned char buf2[400]; /* can't need more then 1/2 buf length */
6106 FILE *rsareq; /* input stream from the REQUEST file */
6107 FILE *rsaresp; /* output stream to the RESPONSE file */
6108 int count;
6109 int i;
6110 int keySize = 1; /* key size in bits*/
6111 int len = 0; /* key size in bytes */
6112 int len2 = 0; /* key size in bytes/2 (prime size) */
6113 SECItem e;
6114 unsigned char default_e[] = { 0x1, 0x0, 0x1 };
6115
6116 e.data = default_e;
6117 e.len = sizeof(default_e);
6118
6119 rsareq = fopen(reqfn, "r");
6120 rsaresp = stdout;
6121 while (fgets(buf, sizeof buf, rsareq) != NULL) {
6122 /* a comment or blank line */
6123 if (buf[0] == '#' || buf[0] == '\n') {
6124 fputs(buf, rsaresp);
6125 continue;
6126 }
6127
6128 /* [Mod = x] */
6129 if (buf[0] == '[') {
6130 if (buf[1] == 'm') {
6131 if (sscanf(buf, "[mod = %d]", &keySize) != 1) {
6132 goto loser;
6133 }
6134 len = keySize / 8;
6135 len2 = keySize / 16;
6136 }
6137 fputs(buf, rsaresp);
6138 continue;
6139 }
6140 /* N = ...*/
6141 if (buf[0] == 'N') {
6142
6143 if (sscanf(buf, "N = %d", &count) != 1) {
6144 goto loser;
6145 }
6146
6147 /* Generate a DSA key, and output the key pair for N times */
6148 for (i = 0; i < count; i++) {
6149 RSAPrivateKey *rsakey = NULL;
6150 if ((rsakey = RSA_NewKey(keySize, &e)) == NULL) {
6151 fprintf(rsaresp, "ERROR: Unable to generate RSA key");
6152 goto loser;
6153 }
6154 pad(buf2, len, rsakey->publicExponent.data,
6155 rsakey->publicExponent.len);
6156 to_hex_str(buf, buf2, len);
6157 fprintf(rsaresp, "e = %s\n", buf);
6158 pad(buf2, len2, rsakey->prime1.data,
6159 rsakey->prime1.len);
6160 to_hex_str(buf, buf2, len2);
6161 fprintf(rsaresp, "p = %s\n", buf);
6162 pad(buf2, len2, rsakey->prime2.data,
6163 rsakey->prime2.len);
6164 to_hex_str(buf, buf2, len2);
6165 fprintf(rsaresp, "q = %s\n", buf);
6166 pad(buf2, len, rsakey->modulus.data,
6167 rsakey->modulus.len);
6168 to_hex_str(buf, buf2, len);
6169 fprintf(rsaresp, "n = %s\n", buf);
6170 pad(buf2, len, rsakey->privateExponent.data,
6171 rsakey->privateExponent.len);
6172 to_hex_str(buf, buf2, len);
6173 fprintf(rsaresp, "d = %s\n", buf);
6174 fprintf(rsaresp, "\n");
6175 PORT_FreeArena(rsakey->arena, PR_TRUE);
6176 rsakey = NULL;
6177 }
6178 continue;
6179 }
6180 }
6181 loser:
6182 fclose(rsareq);
6183 }
6184
6185 /*
6186 * Perform the RSA Signature Generation Test.
6187 *
6188 * reqfn is the pathname of the REQUEST file.
6189 *
6190 * The output RESPONSE file is written to stdout.
6191 */
6192 void
rsa_siggen_test(char * reqfn)6193 rsa_siggen_test(char *reqfn)
6194 {
6195 char buf[2 * RSA_MAX_TEST_MODULUS_BYTES + 1];
6196 /* buf holds one line from the input REQUEST file
6197 * or to the output RESPONSE file.
6198 * 2x for HEX output + 1 for \n
6199 */
6200 FILE *rsareq; /* input stream from the REQUEST file */
6201 FILE *rsaresp; /* output stream to the RESPONSE file */
6202 int i, j;
6203 unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
6204 unsigned int shaLength = 0; /* length of SHA */
6205 HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
6206 SECOidTag shaOid = SEC_OID_UNKNOWN;
6207 int modulus; /* the Modulus size */
6208 int publicExponent = DEFAULT_RSA_PUBLIC_EXPONENT;
6209 SECItem pe = { 0, 0, 0 };
6210 unsigned char pubEx[4];
6211 int peCount = 0;
6212
6213 RSAPrivateKey *rsaBlapiPrivKey = NULL; /* holds RSA private and
6214 * public keys */
6215 RSAPublicKey *rsaBlapiPublicKey = NULL; /* hold RSA public key */
6216
6217 rsareq = fopen(reqfn, "r");
6218 rsaresp = stdout;
6219
6220 /* calculate the exponent */
6221 for (i = 0; i < 4; i++) {
6222 if (peCount || (publicExponent &
6223 ((unsigned long)0xff000000L >> (i *
6224 8)))) {
6225 pubEx[peCount] =
6226 (unsigned char)((publicExponent >> (3 - i) * 8) & 0xff);
6227 peCount++;
6228 }
6229 }
6230 pe.len = peCount;
6231 pe.data = &pubEx[0];
6232 pe.type = siBuffer;
6233
6234 while (fgets(buf, sizeof buf, rsareq) != NULL) {
6235 /* a comment or blank line */
6236 if (buf[0] == '#' || buf[0] == '\n') {
6237 fputs(buf, rsaresp);
6238 continue;
6239 }
6240
6241 /* [mod = ...] */
6242 if (buf[0] == '[') {
6243
6244 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
6245 goto loser;
6246 }
6247 if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
6248 fprintf(rsaresp, "ERROR: modulus greater than test maximum\n");
6249 goto loser;
6250 }
6251
6252 fputs(buf, rsaresp);
6253
6254 if (rsaBlapiPrivKey != NULL) {
6255 PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
6256 rsaBlapiPrivKey = NULL;
6257 rsaBlapiPublicKey = NULL;
6258 }
6259
6260 rsaBlapiPrivKey = RSA_NewKey(modulus, &pe);
6261 if (rsaBlapiPrivKey == NULL) {
6262 fprintf(rsaresp, "Error unable to create RSA key\n");
6263 goto loser;
6264 }
6265
6266 to_hex_str(buf, rsaBlapiPrivKey->modulus.data,
6267 rsaBlapiPrivKey->modulus.len);
6268 fprintf(rsaresp, "\nn = %s\n\n", buf);
6269 to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data,
6270 rsaBlapiPrivKey->publicExponent.len);
6271 fprintf(rsaresp, "e = %s\n", buf);
6272 /* convert private key to public key. Memory
6273 * is freed with private key's arena */
6274 rsaBlapiPublicKey = (RSAPublicKey *)PORT_ArenaAlloc(
6275 rsaBlapiPrivKey->arena,
6276 sizeof(RSAPublicKey));
6277
6278 rsaBlapiPublicKey->modulus.len = rsaBlapiPrivKey->modulus.len;
6279 rsaBlapiPublicKey->modulus.data = rsaBlapiPrivKey->modulus.data;
6280 rsaBlapiPublicKey->publicExponent.len =
6281 rsaBlapiPrivKey->publicExponent.len;
6282 rsaBlapiPublicKey->publicExponent.data =
6283 rsaBlapiPrivKey->publicExponent.data;
6284 continue;
6285 }
6286
6287 /* SHAAlg = ... */
6288 if (strncmp(buf, "SHAAlg", 6) == 0) {
6289 i = 6;
6290 while (isspace(buf[i]) || buf[i] == '=') {
6291 i++;
6292 }
6293 /* set the SHA Algorithm */
6294 shaAlg = hash_string_to_hashType(&buf[i]);
6295 if (shaAlg == HASH_AlgNULL) {
6296 fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
6297 goto loser;
6298 }
6299 fputs(buf, rsaresp);
6300 continue;
6301 }
6302 /* Msg = ... */
6303 if (strncmp(buf, "Msg", 3) == 0) {
6304
6305 unsigned char msg[128]; /* MAX msg 128 */
6306 unsigned int rsa_bytes_signed;
6307 unsigned char rsa_computed_signature[RSA_MAX_TEST_MODULUS_BYTES];
6308 SECStatus rv = SECFailure;
6309 NSSLOWKEYPublicKey *rsa_public_key;
6310 NSSLOWKEYPrivateKey *rsa_private_key;
6311 NSSLOWKEYPrivateKey low_RSA_private_key = { NULL,
6312 NSSLOWKEYRSAKey };
6313 NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
6314 NSSLOWKEYRSAKey };
6315
6316 low_RSA_private_key.u.rsa = *rsaBlapiPrivKey;
6317 low_RSA_public_key.u.rsa = *rsaBlapiPublicKey;
6318
6319 rsa_private_key = &low_RSA_private_key;
6320 rsa_public_key = &low_RSA_public_key;
6321
6322 memset(sha, 0, sizeof sha);
6323 memset(msg, 0, sizeof msg);
6324 rsa_bytes_signed = 0;
6325 memset(rsa_computed_signature, 0, sizeof rsa_computed_signature);
6326
6327 i = 3;
6328 while (isspace(buf[i]) || buf[i] == '=') {
6329 i++;
6330 }
6331 for (j = 0; isxdigit(buf[i]) && j < sizeof(msg); i += 2, j++) {
6332 hex_to_byteval(&buf[i], &msg[j]);
6333 }
6334 shaLength = fips_hashLen(shaAlg);
6335 if (fips_hashBuf(shaAlg, sha, msg, j) != SECSuccess) {
6336 if (shaLength == 0) {
6337 fprintf(rsaresp, "ERROR: SHAAlg not defined.");
6338 }
6339 fprintf(rsaresp, "ERROR: Unable to generate SHA%x",
6340 shaLength == 160 ? 1 : shaLength);
6341 goto loser;
6342 }
6343 shaOid = fips_hashOid(shaAlg);
6344
6345 /* Perform RSA signature with the RSA private key. */
6346 rv = RSA_HashSign(shaOid,
6347 rsa_private_key,
6348 rsa_computed_signature,
6349 &rsa_bytes_signed,
6350 nsslowkey_PrivateModulusLen(rsa_private_key),
6351 sha,
6352 shaLength);
6353
6354 if (rv != SECSuccess) {
6355 fprintf(rsaresp, "ERROR: RSA_HashSign failed");
6356 goto loser;
6357 }
6358
6359 /* Output the signature */
6360 fputs(buf, rsaresp);
6361 to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed);
6362 fprintf(rsaresp, "S = %s\n", buf);
6363
6364 /* Perform RSA verification with the RSA public key. */
6365 rv = RSA_HashCheckSign(shaOid,
6366 rsa_public_key,
6367 rsa_computed_signature,
6368 rsa_bytes_signed,
6369 sha,
6370 shaLength);
6371 if (rv != SECSuccess) {
6372 fprintf(rsaresp, "ERROR: RSA_HashCheckSign failed");
6373 goto loser;
6374 }
6375 continue;
6376 }
6377 }
6378 loser:
6379 fclose(rsareq);
6380
6381 if (rsaBlapiPrivKey != NULL) {
6382 /* frees private and public key */
6383 PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
6384 rsaBlapiPrivKey = NULL;
6385 rsaBlapiPublicKey = NULL;
6386 }
6387 }
6388 /*
6389 * Perform the RSA Signature Verification Test.
6390 *
6391 * reqfn is the pathname of the REQUEST file.
6392 *
6393 * The output RESPONSE file is written to stdout.
6394 */
6395 void
rsa_sigver_test(char * reqfn)6396 rsa_sigver_test(char *reqfn)
6397 {
6398 char buf[2 * RSA_MAX_TEST_MODULUS_BYTES + 7];
6399 /* buf holds one line from the input REQUEST file
6400 * or to the output RESPONSE file.
6401 * s = 2x for HEX output + 1 for \n
6402 */
6403 FILE *rsareq; /* input stream from the REQUEST file */
6404 FILE *rsaresp; /* output stream to the RESPONSE file */
6405 int i, j;
6406 unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
6407 unsigned int shaLength = 0; /* actual length of the digest */
6408 HASH_HashType shaAlg = HASH_AlgNULL;
6409 SECOidTag shaOid = SEC_OID_UNKNOWN;
6410 int modulus = 0; /* the Modulus size */
6411 unsigned char signature[513]; /* largest signature size + '\n' */
6412 unsigned int signatureLength = 0; /* actual length of the signature */
6413 PRBool keyvalid = PR_TRUE;
6414
6415 RSAPublicKey rsaBlapiPublicKey; /* hold RSA public key */
6416
6417 rsareq = fopen(reqfn, "r");
6418 rsaresp = stdout;
6419 memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey));
6420
6421 while (fgets(buf, sizeof buf, rsareq) != NULL) {
6422 /* a comment or blank line */
6423 if (buf[0] == '#' || buf[0] == '\n') {
6424 fputs(buf, rsaresp);
6425 continue;
6426 }
6427
6428 /* [Mod = ...] */
6429 if (buf[0] == '[') {
6430 unsigned int flen; /* length in bytes of the field size */
6431
6432 if (rsaBlapiPublicKey.modulus.data) { /* n */
6433 SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
6434 }
6435 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
6436 goto loser;
6437 }
6438
6439 if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
6440 fprintf(rsaresp, "ERROR: modulus greater than test maximum\n");
6441 goto loser;
6442 }
6443
6444 fputs(buf, rsaresp);
6445
6446 signatureLength = flen = modulus / 8;
6447
6448 SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.modulus, flen);
6449 if (rsaBlapiPublicKey.modulus.data == NULL) {
6450 goto loser;
6451 }
6452 continue;
6453 }
6454
6455 /* n = ... modulus */
6456 if (buf[0] == 'n') {
6457 i = 1;
6458 while (isspace(buf[i]) || buf[i] == '=') {
6459 i++;
6460 }
6461 keyvalid = from_hex_str(&rsaBlapiPublicKey.modulus.data[0],
6462 rsaBlapiPublicKey.modulus.len,
6463 &buf[i]);
6464
6465 if (!keyvalid) {
6466 fprintf(rsaresp, "ERROR: rsa_sigver n not valid.\n");
6467 goto loser;
6468 }
6469 fputs(buf, rsaresp);
6470 continue;
6471 }
6472
6473 /* SHAAlg = ... */
6474 if (strncmp(buf, "SHAAlg", 6) == 0) {
6475 i = 6;
6476 while (isspace(buf[i]) || buf[i] == '=') {
6477 i++;
6478 }
6479 /* set the SHA Algorithm */
6480 shaAlg = hash_string_to_hashType(&buf[i]);
6481 if (shaAlg == HASH_AlgNULL) {
6482 fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
6483 goto loser;
6484 }
6485 fputs(buf, rsaresp);
6486 continue;
6487 }
6488
6489 /* e = ... public Key */
6490 if (buf[0] == 'e') {
6491 unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES];
6492 unsigned char t;
6493
6494 memset(data, 0, sizeof data);
6495
6496 if (rsaBlapiPublicKey.publicExponent.data) { /* e */
6497 SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
6498 }
6499
6500 i = 1;
6501 while (isspace(buf[i]) || buf[i] == '=') {
6502 i++;
6503 }
6504 /* skip leading zero's */
6505 while (isxdigit(buf[i])) {
6506 hex_to_byteval(&buf[i], &t);
6507 if (t == 0) {
6508 i += 2;
6509 } else
6510 break;
6511 }
6512
6513 /* get the exponent */
6514 for (j = 0; isxdigit(buf[i]) && j < sizeof data; i += 2, j++) {
6515 hex_to_byteval(&buf[i], &data[j]);
6516 }
6517
6518 if (j == 0) {
6519 j = 1;
6520 } /* to handle 1 byte length exponents */
6521
6522 SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.publicExponent, j);
6523 if (rsaBlapiPublicKey.publicExponent.data == NULL) {
6524 goto loser;
6525 }
6526
6527 for (i = 0; i < j; i++) {
6528 rsaBlapiPublicKey.publicExponent.data[i] = data[i];
6529 }
6530
6531 fputs(buf, rsaresp);
6532 continue;
6533 }
6534
6535 /* Msg = ... */
6536 if (strncmp(buf, "Msg", 3) == 0) {
6537 unsigned char msg[128]; /* MAX msg 128 */
6538
6539 memset(sha, 0, sizeof sha);
6540 memset(msg, 0, sizeof msg);
6541
6542 i = 3;
6543 while (isspace(buf[i]) || buf[i] == '=') {
6544 i++;
6545 }
6546
6547 for (j = 0; isxdigit(buf[i]) && j < sizeof msg; i += 2, j++) {
6548 hex_to_byteval(&buf[i], &msg[j]);
6549 }
6550
6551 shaLength = fips_hashLen(shaAlg);
6552 if (fips_hashBuf(shaAlg, sha, msg, j) != SECSuccess) {
6553 if (shaLength == 0) {
6554 fprintf(rsaresp, "ERROR: SHAAlg not defined.");
6555 }
6556 fprintf(rsaresp, "ERROR: Unable to generate SHA%x",
6557 shaLength == 160 ? 1 : shaLength);
6558 goto loser;
6559 }
6560
6561 fputs(buf, rsaresp);
6562 continue;
6563 }
6564
6565 /* S = ... */
6566 if (buf[0] == 'S') {
6567 SECStatus rv = SECFailure;
6568 NSSLOWKEYPublicKey *rsa_public_key;
6569 NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
6570 NSSLOWKEYRSAKey };
6571
6572 /* convert to a low RSA public key */
6573 low_RSA_public_key.u.rsa = rsaBlapiPublicKey;
6574 rsa_public_key = &low_RSA_public_key;
6575
6576 memset(signature, 0, sizeof(signature));
6577 i = 1;
6578 while (isspace(buf[i]) || buf[i] == '=') {
6579 i++;
6580 }
6581
6582 for (j = 0; isxdigit(buf[i]) && j < sizeof signature; i += 2, j++) {
6583 hex_to_byteval(&buf[i], &signature[j]);
6584 }
6585
6586 signatureLength = j;
6587 fputs(buf, rsaresp);
6588
6589 shaOid = fips_hashOid(shaAlg);
6590
6591 /* Perform RSA verification with the RSA public key. */
6592 rv = RSA_HashCheckSign(shaOid,
6593 rsa_public_key,
6594 signature,
6595 signatureLength,
6596 sha,
6597 shaLength);
6598 if (rv == SECSuccess) {
6599 fputs("Result = P\n", rsaresp);
6600 } else {
6601 fputs("Result = F\n", rsaresp);
6602 }
6603 continue;
6604 }
6605 }
6606 loser:
6607 fclose(rsareq);
6608 if (rsaBlapiPublicKey.modulus.data) { /* n */
6609 SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
6610 }
6611 if (rsaBlapiPublicKey.publicExponent.data) { /* e */
6612 SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
6613 }
6614 }
6615
6616 void
tls(char * reqfn)6617 tls(char *reqfn)
6618 {
6619 char buf[256]; /* holds one line from the input REQUEST file.
6620 * needs to be large enough to hold the longest
6621 * line "XSeed = <128 hex digits>\n".
6622 */
6623 unsigned char *pms = NULL;
6624 int pms_len;
6625 unsigned char *master_secret = NULL;
6626 unsigned char *key_block = NULL;
6627 int key_block_len;
6628 unsigned char serverHello_random[SSL3_RANDOM_LENGTH];
6629 unsigned char clientHello_random[SSL3_RANDOM_LENGTH];
6630 unsigned char server_random[SSL3_RANDOM_LENGTH];
6631 unsigned char client_random[SSL3_RANDOM_LENGTH];
6632 FILE *tlsreq = NULL; /* input stream from the REQUEST file */
6633 FILE *tlsresp; /* output stream to the RESPONSE file */
6634 unsigned int i, j;
6635 CK_SLOT_ID slotList[10];
6636 CK_SLOT_ID slotID;
6637 CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
6638 CK_ULONG count;
6639 static const CK_C_INITIALIZE_ARGS pk11args = {
6640 NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
6641 (void *)"flags=readOnly,noCertDB,noModDB", NULL
6642 };
6643 static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
6644 static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
6645 static CK_BBOOL ck_true = CK_TRUE;
6646 static CK_ULONG one = 1;
6647 CK_ATTRIBUTE create_template[] = {
6648 { CKA_VALUE, NULL, 0 },
6649 { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
6650 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
6651 { CKA_DERIVE, &ck_true, sizeof(ck_true) },
6652 };
6653 CK_ULONG create_template_count =
6654 sizeof(create_template) / sizeof(create_template[0]);
6655 CK_ATTRIBUTE derive_template[] = {
6656 { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
6657 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
6658 { CKA_DERIVE, &ck_true, sizeof(ck_true) },
6659 { CKA_VALUE_LEN, &one, sizeof(one) },
6660 };
6661 CK_ULONG derive_template_count =
6662 sizeof(derive_template) / sizeof(derive_template[0]);
6663 CK_ATTRIBUTE master_template =
6664 { CKA_VALUE, NULL, 0 };
6665 CK_ATTRIBUTE kb1_template =
6666 { CKA_VALUE, NULL, 0 };
6667 CK_ATTRIBUTE kb2_template =
6668 { CKA_VALUE, NULL, 0 };
6669
6670 CK_MECHANISM master_mech = { CKM_TLS_MASTER_KEY_DERIVE, NULL, 0 };
6671 CK_MECHANISM key_block_mech = { CKM_TLS_KEY_AND_MAC_DERIVE, NULL, 0 };
6672 CK_TLS12_MASTER_KEY_DERIVE_PARAMS master_params;
6673 CK_TLS12_KEY_MAT_PARAMS key_block_params;
6674 CK_SSL3_KEY_MAT_OUT key_material;
6675 CK_RV crv;
6676
6677 /* set up PKCS #11 parameters */
6678 master_params.prfHashMechanism = CKM_SHA256;
6679 master_params.pVersion = NULL;
6680 master_params.RandomInfo.pClientRandom = clientHello_random;
6681 master_params.RandomInfo.ulClientRandomLen = sizeof(clientHello_random);
6682 master_params.RandomInfo.pServerRandom = serverHello_random;
6683 master_params.RandomInfo.ulServerRandomLen = sizeof(serverHello_random);
6684 master_mech.pParameter = (void *)&master_params;
6685 master_mech.ulParameterLen = sizeof(master_params);
6686 key_block_params.prfHashMechanism = CKM_SHA256;
6687 key_block_params.ulMacSizeInBits = 0;
6688 key_block_params.ulKeySizeInBits = 0;
6689 key_block_params.ulIVSizeInBits = 0;
6690 key_block_params.bIsExport = PR_FALSE; /* ignored anyway for TLS mech */
6691 key_block_params.RandomInfo.pClientRandom = client_random;
6692 key_block_params.RandomInfo.ulClientRandomLen = sizeof(client_random);
6693 key_block_params.RandomInfo.pServerRandom = server_random;
6694 key_block_params.RandomInfo.ulServerRandomLen = sizeof(server_random);
6695 key_block_params.pReturnedKeyMaterial = &key_material;
6696 key_block_mech.pParameter = (void *)&key_block_params;
6697 key_block_mech.ulParameterLen = sizeof(key_block_params);
6698
6699 crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
6700 if (crv != CKR_OK) {
6701 fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
6702 goto loser;
6703 }
6704 count = slotListCount;
6705 crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
6706 if (crv != CKR_OK) {
6707 fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
6708 goto loser;
6709 }
6710 if ((count > slotListCount) || count < 1) {
6711 fprintf(stderr,
6712 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
6713 (int)count, (int)slotListCount);
6714 goto loser;
6715 }
6716 slotID = slotList[0];
6717 tlsreq = fopen(reqfn, "r");
6718 tlsresp = stdout;
6719 while (fgets(buf, sizeof buf, tlsreq) != NULL) {
6720 /* a comment or blank line */
6721 if (buf[0] == '#' || buf[0] == '\n') {
6722 fputs(buf, tlsresp);
6723 continue;
6724 }
6725 /* [Xchange - SHA1] */
6726 if (buf[0] == '[') {
6727 if (strncmp(buf, "[TLS", 4) == 0) {
6728 if (buf[7] == '0') {
6729 /* CK_SSL3_MASTER_KEY_DERIVE_PARAMS is a subset of
6730 * CK_TLS12_MASTER_KEY_DERIVE_PARAMS and
6731 * CK_SSL3_KEY_MAT_PARAMS is a subset of
6732 * CK_TLS12_KEY_MAT_PARAMS. The latter params have
6733 * an extra prfHashMechanism field at the end. */
6734 master_mech.mechanism = CKM_TLS_MASTER_KEY_DERIVE;
6735 key_block_mech.mechanism = CKM_TLS_KEY_AND_MAC_DERIVE;
6736 master_mech.ulParameterLen = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
6737 key_block_mech.ulParameterLen = sizeof(CK_SSL3_KEY_MAT_PARAMS);
6738 } else if (buf[7] == '2') {
6739 if (strncmp(&buf[10], "SHA-1", 5) == 0) {
6740 master_params.prfHashMechanism = CKM_SHA_1;
6741 key_block_params.prfHashMechanism = CKM_SHA_1;
6742 } else if (strncmp(&buf[10], "SHA-224", 7) == 0) {
6743 master_params.prfHashMechanism = CKM_SHA224;
6744 key_block_params.prfHashMechanism = CKM_SHA224;
6745 } else if (strncmp(&buf[10], "SHA-256", 7) == 0) {
6746 master_params.prfHashMechanism = CKM_SHA256;
6747 key_block_params.prfHashMechanism = CKM_SHA256;
6748 } else if (strncmp(&buf[10], "SHA-384", 7) == 0) {
6749 master_params.prfHashMechanism = CKM_SHA384;
6750 key_block_params.prfHashMechanism = CKM_SHA384;
6751 } else if (strncmp(&buf[10], "SHA-512", 7) == 0) {
6752 master_params.prfHashMechanism = CKM_SHA512;
6753 key_block_params.prfHashMechanism = CKM_SHA512;
6754 } else {
6755 fprintf(tlsresp, "ERROR: Unable to find prf Hash type");
6756 goto loser;
6757 }
6758 master_mech.mechanism = CKM_TLS12_MASTER_KEY_DERIVE;
6759 key_block_mech.mechanism = CKM_TLS12_KEY_AND_MAC_DERIVE;
6760 master_mech.ulParameterLen = sizeof(master_params);
6761 key_block_mech.ulParameterLen = sizeof(key_block_params);
6762 } else {
6763 fprintf(stderr, "Unknown TLS type %x\n",
6764 (unsigned int)buf[0]);
6765 goto loser;
6766 }
6767 }
6768 if (strncmp(buf, "[pre-master", 11) == 0) {
6769 if (sscanf(buf, "[pre-master secret length = %d]",
6770 &pms_len) != 1) {
6771 goto loser;
6772 }
6773 pms_len = pms_len / 8;
6774 pms = malloc(pms_len);
6775 master_secret = malloc(pms_len);
6776 create_template[0].pValue = pms;
6777 create_template[0].ulValueLen = pms_len;
6778 master_template.pValue = master_secret;
6779 master_template.ulValueLen = pms_len;
6780 }
6781 if (strncmp(buf, "[key", 4) == 0) {
6782 if (sscanf(buf, "[key block length = %d]", &key_block_len) != 1) {
6783 goto loser;
6784 }
6785 key_block_params.ulKeySizeInBits = 8;
6786 key_block_params.ulIVSizeInBits = key_block_len / 2 - 8;
6787 key_block_len = key_block_len / 8;
6788 key_block = malloc(key_block_len);
6789 kb1_template.pValue = &key_block[0];
6790 kb1_template.ulValueLen = 1;
6791 kb2_template.pValue = &key_block[1];
6792 kb2_template.ulValueLen = 1;
6793 key_material.pIVClient = &key_block[2];
6794 key_material.pIVServer = &key_block[2 + key_block_len / 2 - 1];
6795 }
6796 fputs(buf, tlsresp);
6797 continue;
6798 }
6799 /* "COUNT = x" begins a new data set */
6800 if (strncmp(buf, "COUNT", 5) == 0) {
6801 /* zeroize the variables for the test with this data set */
6802 memset(pms, 0, pms_len);
6803 memset(master_secret, 0, pms_len);
6804 memset(key_block, 0, key_block_len);
6805 fputs(buf, tlsresp);
6806 continue;
6807 }
6808 /* pre_master_secret = ... */
6809 if (strncmp(buf, "pre_master_secret", 17) == 0) {
6810 i = 17;
6811 while (isspace(buf[i]) || buf[i] == '=') {
6812 i++;
6813 }
6814 for (j = 0; j < pms_len; i += 2, j++) {
6815 hex_to_byteval(&buf[i], &pms[j]);
6816 }
6817 fputs(buf, tlsresp);
6818 continue;
6819 }
6820 /* serverHello_random = ... */
6821 if (strncmp(buf, "serverHello_random", 18) == 0) {
6822 i = 18;
6823 while (isspace(buf[i]) || buf[i] == '=') {
6824 i++;
6825 }
6826 for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
6827 hex_to_byteval(&buf[i], &serverHello_random[j]);
6828 }
6829 fputs(buf, tlsresp);
6830 continue;
6831 }
6832 /* clientHello_random = ... */
6833 if (strncmp(buf, "clientHello_random", 18) == 0) {
6834 i = 18;
6835 while (isspace(buf[i]) || buf[i] == '=') {
6836 i++;
6837 }
6838 for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
6839 hex_to_byteval(&buf[i], &clientHello_random[j]);
6840 }
6841 fputs(buf, tlsresp);
6842 continue;
6843 }
6844 /* server_random = ... */
6845 if (strncmp(buf, "server_random", 13) == 0) {
6846 i = 13;
6847 while (isspace(buf[i]) || buf[i] == '=') {
6848 i++;
6849 }
6850 for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
6851 hex_to_byteval(&buf[i], &server_random[j]);
6852 }
6853 fputs(buf, tlsresp);
6854 continue;
6855 }
6856 /* client_random = ... */
6857 if (strncmp(buf, "client_random", 13) == 0) {
6858 CK_SESSION_HANDLE session;
6859 CK_OBJECT_HANDLE pms_handle;
6860 CK_OBJECT_HANDLE master_handle;
6861 CK_OBJECT_HANDLE fake_handle;
6862 i = 13;
6863 while (isspace(buf[i]) || buf[i] == '=') {
6864 i++;
6865 }
6866 for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
6867 hex_to_byteval(&buf[i], &client_random[j]);
6868 }
6869 fputs(buf, tlsresp);
6870 crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
6871 if (crv != CKR_OK) {
6872 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
6873 (unsigned int)crv);
6874 goto loser;
6875 }
6876 crv = NSC_CreateObject(session, create_template,
6877 create_template_count, &pms_handle);
6878 if (crv != CKR_OK) {
6879 fprintf(stderr, "NSC_CreateObject failed crv=0x%x\n",
6880 (unsigned int)crv);
6881 goto loser;
6882 }
6883 crv = NSC_DeriveKey(session, &master_mech, pms_handle,
6884 derive_template, derive_template_count - 1,
6885 &master_handle);
6886 if (crv != CKR_OK) {
6887 fprintf(stderr, "NSC_DeriveKey(master) failed crv=0x%x\n",
6888 (unsigned int)crv);
6889 goto loser;
6890 }
6891 crv = NSC_GetAttributeValue(session, master_handle,
6892 &master_template, 1);
6893 if (crv != CKR_OK) {
6894 fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n",
6895 (unsigned int)crv);
6896 goto loser;
6897 }
6898 fputs("master_secret = ", tlsresp);
6899 to_hex_str(buf, master_secret, pms_len);
6900 fputs(buf, tlsresp);
6901 fputc('\n', tlsresp);
6902 crv = NSC_DeriveKey(session, &key_block_mech, master_handle,
6903 derive_template, derive_template_count, &fake_handle);
6904 if (crv != CKR_OK) {
6905 fprintf(stderr,
6906 "NSC_DeriveKey(keyblock) failed crv=0x%x\n",
6907 (unsigned int)crv);
6908 goto loser;
6909 }
6910 crv = NSC_GetAttributeValue(session, key_material.hClientKey,
6911 &kb1_template, 1);
6912 if (crv != CKR_OK) {
6913 fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n",
6914 (unsigned int)crv);
6915 goto loser;
6916 }
6917 crv = NSC_GetAttributeValue(session, key_material.hServerKey,
6918 &kb2_template, 1);
6919 if (crv != CKR_OK) {
6920 fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n",
6921 (unsigned int)crv);
6922 goto loser;
6923 }
6924 fputs("key_block = ", tlsresp);
6925 to_hex_str(buf, key_block, key_block_len);
6926 fputs(buf, tlsresp);
6927 fputc('\n', tlsresp);
6928 crv = NSC_CloseSession(session);
6929 continue;
6930 }
6931 }
6932 loser:
6933 NSC_Finalize(NULL);
6934 if (pms)
6935 free(pms);
6936 if (master_secret)
6937 free(master_secret);
6938 if (key_block)
6939 free(key_block);
6940 if (tlsreq)
6941 fclose(tlsreq);
6942 }
6943
6944 void
ikev1(char * reqfn)6945 ikev1(char *reqfn)
6946 {
6947 char buf[4096]; /* holds one line from the input REQUEST file.
6948 * needs to be large enough to hold the longest
6949 * line "g^xy = <2048 hex digits>\n".
6950 */
6951 unsigned char *gxy = NULL;
6952 int gxy_len;
6953 unsigned char *Ni = NULL;
6954 int Ni_len;
6955 unsigned char *Nr = NULL;
6956 int Nr_len;
6957 unsigned char CKYi[8];
6958 int CKYi_len;
6959 unsigned char CKYr[8];
6960 int CKYr_len;
6961 unsigned int i, j;
6962 FILE *ikereq = NULL; /* input stream from the REQUEST file */
6963 FILE *ikeresp; /* output stream to the RESPONSE file */
6964
6965 CK_SLOT_ID slotList[10];
6966 CK_SLOT_ID slotID;
6967 CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
6968 CK_ULONG count;
6969 static const CK_C_INITIALIZE_ARGS pk11args = {
6970 NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
6971 (void *)"flags=readOnly,noCertDB,noModDB", NULL
6972 };
6973 static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
6974 static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
6975 static CK_BBOOL ck_true = CK_TRUE;
6976 static CK_ULONG keyLen = 1;
6977 CK_ATTRIBUTE gxy_template[] = {
6978 { CKA_VALUE, NULL, 0 }, /* must be first */
6979 { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
6980 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
6981 { CKA_DERIVE, &ck_true, sizeof(ck_true) },
6982 };
6983 CK_ULONG gxy_template_count =
6984 sizeof(gxy_template) / sizeof(gxy_template[0]);
6985 CK_ATTRIBUTE derive_template[] = {
6986 { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
6987 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
6988 { CKA_DERIVE, &ck_true, sizeof(ck_true) },
6989 { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) }, /* must be last */
6990 };
6991 CK_ULONG derive_template_count =
6992 sizeof(derive_template) / sizeof(derive_template[0]);
6993 CK_ATTRIBUTE skeyid_template =
6994 { CKA_VALUE, NULL, 0 };
6995 CK_ATTRIBUTE skeyid_d_template =
6996 { CKA_VALUE, NULL, 0 };
6997 CK_ATTRIBUTE skeyid_a_template =
6998 { CKA_VALUE, NULL, 0 };
6999 CK_ATTRIBUTE skeyid_e_template =
7000 { CKA_VALUE, NULL, 0 };
7001 unsigned char skeyid_secret[HASH_LENGTH_MAX];
7002 unsigned char skeyid_d_secret[HASH_LENGTH_MAX];
7003 unsigned char skeyid_a_secret[HASH_LENGTH_MAX];
7004 unsigned char skeyid_e_secret[HASH_LENGTH_MAX];
7005
7006 CK_MECHANISM ike_mech = { CKM_NSS_IKE_PRF_DERIVE, NULL, 0 };
7007 CK_MECHANISM ike1_mech = { CKM_NSS_IKE1_PRF_DERIVE, NULL, 0 };
7008 CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf;
7009 CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf;
7010 CK_RV crv;
7011
7012 /* set up PKCS #11 parameters */
7013 ike_prf.bDataAsKey = PR_TRUE;
7014 ike_prf.bRekey = PR_FALSE;
7015 ike_prf.hNewKey = CK_INVALID_HANDLE;
7016 CKYi_len = sizeof(CKYi);
7017 CKYr_len = sizeof(CKYr);
7018 ike1_prf.pCKYi = CKYi;
7019 ike1_prf.ulCKYiLen = CKYi_len;
7020 ike1_prf.pCKYr = CKYr;
7021 ike1_prf.ulCKYrLen = CKYr_len;
7022 ike_mech.pParameter = &ike_prf;
7023 ike_mech.ulParameterLen = sizeof(ike_prf);
7024 ike1_mech.pParameter = &ike1_prf;
7025 ike1_mech.ulParameterLen = sizeof(ike1_prf);
7026 skeyid_template.pValue = skeyid_secret;
7027 skeyid_template.ulValueLen = HASH_LENGTH_MAX;
7028 skeyid_d_template.pValue = skeyid_d_secret;
7029 skeyid_d_template.ulValueLen = HASH_LENGTH_MAX;
7030 skeyid_a_template.pValue = skeyid_a_secret;
7031 skeyid_a_template.ulValueLen = HASH_LENGTH_MAX;
7032 skeyid_e_template.pValue = skeyid_e_secret;
7033 skeyid_e_template.ulValueLen = HASH_LENGTH_MAX;
7034
7035 crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
7036 if (crv != CKR_OK) {
7037 fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
7038 goto loser;
7039 }
7040 count = slotListCount;
7041 crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
7042 if (crv != CKR_OK) {
7043 fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
7044 goto loser;
7045 }
7046 if ((count > slotListCount) || count < 1) {
7047 fprintf(stderr,
7048 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
7049 (int)count, (int)slotListCount);
7050 goto loser;
7051 }
7052 slotID = slotList[0];
7053 ikereq = fopen(reqfn, "r");
7054 ikeresp = stdout;
7055 while (fgets(buf, sizeof buf, ikereq) != NULL) {
7056 /* a comment or blank line */
7057 if (buf[0] == '#' || buf[0] == '\n') {
7058 fputs(buf, ikeresp);
7059 continue;
7060 }
7061 /* [.....] */
7062 if (buf[0] == '[') {
7063 if (strncmp(buf, "[SHA-1]", 7) == 0) {
7064 ike_prf.prfMechanism = CKM_SHA_1_HMAC;
7065 ike1_prf.prfMechanism = CKM_SHA_1_HMAC;
7066 }
7067 if (strncmp(buf, "[SHA-224]", 9) == 0) {
7068 ike_prf.prfMechanism = CKM_SHA224_HMAC;
7069 ike1_prf.prfMechanism = CKM_SHA224_HMAC;
7070 }
7071 if (strncmp(buf, "[SHA-256]", 9) == 0) {
7072 ike_prf.prfMechanism = CKM_SHA256_HMAC;
7073 ike1_prf.prfMechanism = CKM_SHA256_HMAC;
7074 }
7075 if (strncmp(buf, "[SHA-384]", 9) == 0) {
7076 ike_prf.prfMechanism = CKM_SHA384_HMAC;
7077 ike1_prf.prfMechanism = CKM_SHA384_HMAC;
7078 }
7079 if (strncmp(buf, "[SHA-512]", 9) == 0) {
7080 ike_prf.prfMechanism = CKM_SHA512_HMAC;
7081 ike1_prf.prfMechanism = CKM_SHA512_HMAC;
7082 }
7083 if (strncmp(buf, "[AES-XCBC", 9) == 0) {
7084 ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
7085 ike1_prf.prfMechanism = CKM_AES_XCBC_MAC;
7086 }
7087 if (strncmp(buf, "[g^xy", 5) == 0) {
7088 if (sscanf(buf, "[g^xy length = %d]",
7089 &gxy_len) != 1) {
7090 goto loser;
7091 }
7092 gxy_len = gxy_len / 8;
7093 if (gxy)
7094 free(gxy);
7095 gxy = malloc(gxy_len);
7096 gxy_template[0].pValue = gxy;
7097 gxy_template[0].ulValueLen = gxy_len;
7098 }
7099 if (strncmp(buf, "[Ni", 3) == 0) {
7100 if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
7101 goto loser;
7102 }
7103 Ni_len = Ni_len / 8;
7104 if (Ni)
7105 free(Ni);
7106 Ni = malloc(Ni_len);
7107 ike_prf.pNi = Ni;
7108 ike_prf.ulNiLen = Ni_len;
7109 }
7110 if (strncmp(buf, "[Nr", 3) == 0) {
7111 if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
7112 goto loser;
7113 }
7114 Nr_len = Nr_len / 8;
7115 if (Nr)
7116 free(Nr);
7117 Nr = malloc(Nr_len);
7118 ike_prf.pNr = Nr;
7119 ike_prf.ulNrLen = Nr_len;
7120 }
7121 fputs(buf, ikeresp);
7122 continue;
7123 }
7124 /* "COUNT = x" begins a new data set */
7125 if (strncmp(buf, "COUNT", 5) == 0) {
7126 /* zeroize the variables for the test with this data set */
7127 memset(gxy, 0, gxy_len);
7128 memset(Ni, 0, Ni_len);
7129 memset(Nr, 0, Nr_len);
7130 memset(CKYi, 0, CKYi_len);
7131 memset(CKYr, 0, CKYr_len);
7132 fputs(buf, ikeresp);
7133 continue;
7134 }
7135 /* Ni = ... */
7136 if (strncmp(buf, "Ni", 2) == 0) {
7137 i = 2;
7138 while (isspace(buf[i]) || buf[i] == '=') {
7139 i++;
7140 }
7141 for (j = 0; j < Ni_len; i += 2, j++) {
7142 hex_to_byteval(&buf[i], &Ni[j]);
7143 }
7144 fputs(buf, ikeresp);
7145 continue;
7146 }
7147 /* Nr = ... */
7148 if (strncmp(buf, "Nr", 2) == 0) {
7149 i = 2;
7150 while (isspace(buf[i]) || buf[i] == '=') {
7151 i++;
7152 }
7153 for (j = 0; j < Nr_len; i += 2, j++) {
7154 hex_to_byteval(&buf[i], &Nr[j]);
7155 }
7156 fputs(buf, ikeresp);
7157 continue;
7158 }
7159 /* CKYi = ... */
7160 if (strncmp(buf, "CKY_I", 5) == 0) {
7161 i = 5;
7162 while (isspace(buf[i]) || buf[i] == '=') {
7163 i++;
7164 }
7165 for (j = 0; j < CKYi_len; i += 2, j++) {
7166 hex_to_byteval(&buf[i], &CKYi[j]);
7167 }
7168 fputs(buf, ikeresp);
7169 continue;
7170 }
7171 /* CKYr = ... */
7172 if (strncmp(buf, "CKY_R", 5) == 0) {
7173 i = 5;
7174 while (isspace(buf[i]) || buf[i] == '=') {
7175 i++;
7176 }
7177 for (j = 0; j < CKYr_len; i += 2, j++) {
7178 hex_to_byteval(&buf[i], &CKYr[j]);
7179 }
7180 fputs(buf, ikeresp);
7181 continue;
7182 }
7183 /* g^xy = ... */
7184 if (strncmp(buf, "g^xy", 4) == 0) {
7185 CK_SESSION_HANDLE session;
7186 CK_OBJECT_HANDLE gxy_handle;
7187 CK_OBJECT_HANDLE skeyid_handle;
7188 CK_OBJECT_HANDLE skeyid_d_handle;
7189 CK_OBJECT_HANDLE skeyid_a_handle;
7190 CK_OBJECT_HANDLE skeyid_e_handle;
7191 i = 4;
7192 while (isspace(buf[i]) || buf[i] == '=') {
7193 i++;
7194 }
7195 for (j = 0; j < gxy_len; i += 2, j++) {
7196 hex_to_byteval(&buf[i], &gxy[j]);
7197 }
7198 fputs(buf, ikeresp);
7199 crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
7200 if (crv != CKR_OK) {
7201 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
7202 (unsigned int)crv);
7203 goto loser;
7204 }
7205 crv = NSC_CreateObject(session, gxy_template,
7206 gxy_template_count, &gxy_handle);
7207 if (crv != CKR_OK) {
7208 fprintf(stderr, "NSC_CreateObject failed crv=0x%x\n",
7209 (unsigned int)crv);
7210 goto loser;
7211 }
7212 /* get the skeyid key */
7213 crv = NSC_DeriveKey(session, &ike_mech, gxy_handle,
7214 derive_template, derive_template_count - 1,
7215 &skeyid_handle);
7216 if (crv != CKR_OK) {
7217 fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
7218 (unsigned int)crv);
7219 goto loser;
7220 }
7221 skeyid_template.ulValueLen = HASH_LENGTH_MAX;
7222 crv = NSC_GetAttributeValue(session, skeyid_handle,
7223 &skeyid_template, 1);
7224 if (crv != CKR_OK) {
7225 fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
7226 (unsigned int)crv);
7227 goto loser;
7228 }
7229 /* use the length of the skeyid to set the target length of all the
7230 * other keys */
7231 keyLen = skeyid_template.ulValueLen;
7232 ike1_prf.hKeygxy = gxy_handle;
7233 ike1_prf.bHasPrevKey = PR_FALSE;
7234 ike1_prf.keyNumber = 0;
7235 crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
7236 derive_template, derive_template_count,
7237 &skeyid_d_handle);
7238 if (crv != CKR_OK) {
7239 fprintf(stderr, "NSC_DeriveKey(skeyid_d) failed crv=0x%x\n",
7240 (unsigned int)crv);
7241 goto loser;
7242 }
7243
7244 ike1_prf.hKeygxy = gxy_handle;
7245 ike1_prf.bHasPrevKey = CK_TRUE;
7246 ike1_prf.hPrevKey = skeyid_d_handle;
7247 ike1_prf.keyNumber = 1;
7248 crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
7249 derive_template, derive_template_count,
7250 &skeyid_a_handle);
7251 if (crv != CKR_OK) {
7252 fprintf(stderr, "NSC_DeriveKey(skeyid_a) failed crv=0x%x\n",
7253 (unsigned int)crv);
7254 goto loser;
7255 }
7256 ike1_prf.hKeygxy = gxy_handle;
7257 ike1_prf.bHasPrevKey = CK_TRUE;
7258 ike1_prf.hPrevKey = skeyid_a_handle;
7259 ike1_prf.keyNumber = 2;
7260 crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
7261 derive_template, derive_template_count,
7262 &skeyid_e_handle);
7263 if (crv != CKR_OK) {
7264 fprintf(stderr, "NSC_DeriveKey(skeyid_e) failed crv=0x%x\n",
7265 (unsigned int)crv);
7266 goto loser;
7267 }
7268 fputs("SKEYID = ", ikeresp);
7269 to_hex_str(buf, skeyid_secret, keyLen);
7270 fputs(buf, ikeresp);
7271 fputc('\n', ikeresp);
7272
7273 skeyid_d_template.ulValueLen = keyLen;
7274 crv = NSC_GetAttributeValue(session, skeyid_d_handle,
7275 &skeyid_d_template, 1);
7276 if (crv != CKR_OK) {
7277 fprintf(stderr, "NSC_GetAttribute(skeyid_d) failed crv=0x%x\n",
7278 (unsigned int)crv);
7279 goto loser;
7280 }
7281 fputs("SKEYID_d = ", ikeresp);
7282 to_hex_str(buf, skeyid_d_secret, skeyid_d_template.ulValueLen);
7283 fputs(buf, ikeresp);
7284 fputc('\n', ikeresp);
7285
7286 skeyid_a_template.ulValueLen = keyLen;
7287 crv = NSC_GetAttributeValue(session, skeyid_a_handle,
7288 &skeyid_a_template, 1);
7289 if (crv != CKR_OK) {
7290 fprintf(stderr, "NSC_GetAttribute(skeyid_a) failed crv=0x%x\n",
7291 (unsigned int)crv);
7292 goto loser;
7293 }
7294 fputs("SKEYID_a = ", ikeresp);
7295 to_hex_str(buf, skeyid_a_secret, skeyid_a_template.ulValueLen);
7296 fputs(buf, ikeresp);
7297 fputc('\n', ikeresp);
7298
7299 skeyid_e_template.ulValueLen = keyLen;
7300 crv = NSC_GetAttributeValue(session, skeyid_e_handle,
7301 &skeyid_e_template, 1);
7302 if (crv != CKR_OK) {
7303 fprintf(stderr, "NSC_GetAttribute(skeyid_e) failed crv=0x%x\n",
7304 (unsigned int)crv);
7305 goto loser;
7306 }
7307 fputs("SKEYID_e = ", ikeresp);
7308 to_hex_str(buf, skeyid_e_secret, skeyid_e_template.ulValueLen);
7309 fputs(buf, ikeresp);
7310 fputc('\n', ikeresp);
7311
7312 crv = NSC_CloseSession(session);
7313 continue;
7314 }
7315 }
7316 loser:
7317 NSC_Finalize(NULL);
7318 if (gxy)
7319 free(gxy);
7320 if (Ni)
7321 free(Ni);
7322 if (Nr)
7323 free(Nr);
7324 if (ikereq)
7325 fclose(ikereq);
7326 }
7327
7328 void
ikev1_psk(char * reqfn)7329 ikev1_psk(char *reqfn)
7330 {
7331 char buf[4096]; /* holds one line from the input REQUEST file.
7332 * needs to be large enough to hold the longest
7333 * line "g^xy = <2048 hex digits>\n".
7334 */
7335 unsigned char *gxy = NULL;
7336 int gxy_len;
7337 unsigned char *Ni = NULL;
7338 int Ni_len;
7339 unsigned char *Nr = NULL;
7340 int Nr_len;
7341 unsigned char CKYi[8];
7342 int CKYi_len;
7343 unsigned char CKYr[8];
7344 int CKYr_len;
7345 unsigned char *psk = NULL;
7346 int psk_len;
7347 unsigned int i, j;
7348 FILE *ikereq = NULL; /* input stream from the REQUEST file */
7349 FILE *ikeresp; /* output stream to the RESPONSE file */
7350
7351 CK_SLOT_ID slotList[10];
7352 CK_SLOT_ID slotID;
7353 CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
7354 CK_ULONG count;
7355 static const CK_C_INITIALIZE_ARGS pk11args = {
7356 NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
7357 (void *)"flags=readOnly,noCertDB,noModDB", NULL
7358 };
7359 static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
7360 static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
7361 static CK_BBOOL ck_true = CK_TRUE;
7362 static CK_ULONG keyLen = 1;
7363 CK_ATTRIBUTE gxy_template[] = {
7364 { CKA_VALUE, NULL, 0 }, /* must be first */
7365 { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
7366 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
7367 { CKA_DERIVE, &ck_true, sizeof(ck_true) },
7368 };
7369 CK_ULONG gxy_template_count =
7370 sizeof(gxy_template) / sizeof(gxy_template[0]);
7371 CK_ATTRIBUTE psk_template[] = {
7372 { CKA_VALUE, NULL, 0 }, /* must be first */
7373 { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
7374 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
7375 { CKA_DERIVE, &ck_true, sizeof(ck_true) },
7376 };
7377 CK_ULONG psk_template_count =
7378 sizeof(psk_template) / sizeof(psk_template[0]);
7379 CK_ATTRIBUTE derive_template[] = {
7380 { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
7381 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
7382 { CKA_DERIVE, &ck_true, sizeof(ck_true) },
7383 { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) }, /* must be last */
7384 };
7385 CK_ULONG derive_template_count =
7386 sizeof(derive_template) / sizeof(derive_template[0]);
7387 CK_ATTRIBUTE skeyid_template =
7388 { CKA_VALUE, NULL, 0 };
7389 CK_ATTRIBUTE skeyid_d_template =
7390 { CKA_VALUE, NULL, 0 };
7391 CK_ATTRIBUTE skeyid_a_template =
7392 { CKA_VALUE, NULL, 0 };
7393 CK_ATTRIBUTE skeyid_e_template =
7394 { CKA_VALUE, NULL, 0 };
7395 unsigned char skeyid_secret[HASH_LENGTH_MAX];
7396 unsigned char skeyid_d_secret[HASH_LENGTH_MAX];
7397 unsigned char skeyid_a_secret[HASH_LENGTH_MAX];
7398 unsigned char skeyid_e_secret[HASH_LENGTH_MAX];
7399
7400 CK_MECHANISM ike_mech = { CKM_NSS_IKE_PRF_DERIVE, NULL, 0 };
7401 CK_MECHANISM ike1_mech = { CKM_NSS_IKE1_PRF_DERIVE, NULL, 0 };
7402 CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf;
7403 CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf;
7404 CK_RV crv;
7405
7406 /* set up PKCS #11 parameters */
7407 ike_prf.bDataAsKey = PR_FALSE;
7408 ike_prf.bRekey = PR_FALSE;
7409 ike_prf.hNewKey = CK_INVALID_HANDLE;
7410 CKYi_len = 8;
7411 CKYr_len = 8;
7412 ike1_prf.pCKYi = CKYi;
7413 ike1_prf.ulCKYiLen = CKYi_len;
7414 ike1_prf.pCKYr = CKYr;
7415 ike1_prf.ulCKYrLen = CKYr_len;
7416 ike_mech.pParameter = &ike_prf;
7417 ike_mech.ulParameterLen = sizeof(ike_prf);
7418 ike1_mech.pParameter = &ike1_prf;
7419 ike1_mech.ulParameterLen = sizeof(ike1_prf);
7420 skeyid_template.pValue = skeyid_secret;
7421 skeyid_template.ulValueLen = HASH_LENGTH_MAX;
7422 skeyid_d_template.pValue = skeyid_d_secret;
7423 skeyid_d_template.ulValueLen = HASH_LENGTH_MAX;
7424 skeyid_a_template.pValue = skeyid_a_secret;
7425 skeyid_a_template.ulValueLen = HASH_LENGTH_MAX;
7426 skeyid_e_template.pValue = skeyid_e_secret;
7427 skeyid_e_template.ulValueLen = HASH_LENGTH_MAX;
7428
7429 crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
7430 if (crv != CKR_OK) {
7431 fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
7432 goto loser;
7433 }
7434 count = slotListCount;
7435 crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
7436 if (crv != CKR_OK) {
7437 fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
7438 goto loser;
7439 }
7440 if ((count > slotListCount) || count < 1) {
7441 fprintf(stderr,
7442 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
7443 (int)count, (int)slotListCount);
7444 goto loser;
7445 }
7446 slotID = slotList[0];
7447 ikereq = fopen(reqfn, "r");
7448 ikeresp = stdout;
7449 while (fgets(buf, sizeof buf, ikereq) != NULL) {
7450 /* a comment or blank line */
7451 if (buf[0] == '#' || buf[0] == '\n') {
7452 fputs(buf, ikeresp);
7453 continue;
7454 }
7455 /* [.....] */
7456 if (buf[0] == '[') {
7457 if (strncmp(buf, "[SHA-1]", 7) == 0) {
7458 ike_prf.prfMechanism = CKM_SHA_1_HMAC;
7459 ike1_prf.prfMechanism = CKM_SHA_1_HMAC;
7460 }
7461 if (strncmp(buf, "[SHA-224]", 9) == 0) {
7462 ike_prf.prfMechanism = CKM_SHA224_HMAC;
7463 ike1_prf.prfMechanism = CKM_SHA224_HMAC;
7464 }
7465 if (strncmp(buf, "[SHA-256]", 9) == 0) {
7466 ike_prf.prfMechanism = CKM_SHA256_HMAC;
7467 ike1_prf.prfMechanism = CKM_SHA256_HMAC;
7468 }
7469 if (strncmp(buf, "[SHA-384]", 9) == 0) {
7470 ike_prf.prfMechanism = CKM_SHA384_HMAC;
7471 ike1_prf.prfMechanism = CKM_SHA384_HMAC;
7472 }
7473 if (strncmp(buf, "[SHA-512]", 9) == 0) {
7474 ike_prf.prfMechanism = CKM_SHA512_HMAC;
7475 ike1_prf.prfMechanism = CKM_SHA512_HMAC;
7476 }
7477 if (strncmp(buf, "[AES-XCBC", 9) == 0) {
7478 ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
7479 ike1_prf.prfMechanism = CKM_AES_XCBC_MAC;
7480 }
7481 if (strncmp(buf, "[g^xy", 5) == 0) {
7482 if (sscanf(buf, "[g^xy length = %d]",
7483 &gxy_len) != 1) {
7484 goto loser;
7485 }
7486 gxy_len = gxy_len / 8;
7487 if (gxy)
7488 free(gxy);
7489 gxy = malloc(gxy_len);
7490 gxy_template[0].pValue = gxy;
7491 gxy_template[0].ulValueLen = gxy_len;
7492 }
7493 if (strncmp(buf, "[pre-shared-key", 15) == 0) {
7494 if (sscanf(buf, "[pre-shared-key length = %d]",
7495 &psk_len) != 1) {
7496 goto loser;
7497 }
7498 psk_len = psk_len / 8;
7499 if (psk)
7500 free(psk);
7501 psk = malloc(psk_len);
7502 psk_template[0].pValue = psk;
7503 psk_template[0].ulValueLen = psk_len;
7504 }
7505 if (strncmp(buf, "[Ni", 3) == 0) {
7506 if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
7507 goto loser;
7508 }
7509 Ni_len = Ni_len / 8;
7510 if (Ni)
7511 free(Ni);
7512 Ni = malloc(Ni_len);
7513 ike_prf.pNi = Ni;
7514 ike_prf.ulNiLen = Ni_len;
7515 }
7516 if (strncmp(buf, "[Nr", 3) == 0) {
7517 if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
7518 goto loser;
7519 }
7520 Nr_len = Nr_len / 8;
7521 if (Nr)
7522 free(Nr);
7523 Nr = malloc(Nr_len);
7524 ike_prf.pNr = Nr;
7525 ike_prf.ulNrLen = Nr_len;
7526 }
7527 fputs(buf, ikeresp);
7528 continue;
7529 }
7530 /* "COUNT = x" begins a new data set */
7531 if (strncmp(buf, "COUNT", 5) == 0) {
7532 /* zeroize the variables for the test with this data set */
7533 memset(gxy, 0, gxy_len);
7534 memset(Ni, 0, Ni_len);
7535 memset(Nr, 0, Nr_len);
7536 memset(CKYi, 0, CKYi_len);
7537 memset(CKYr, 0, CKYr_len);
7538 fputs(buf, ikeresp);
7539 continue;
7540 }
7541 /* Ni = ... */
7542 if (strncmp(buf, "Ni", 2) == 0) {
7543 i = 2;
7544 while (isspace(buf[i]) || buf[i] == '=') {
7545 i++;
7546 }
7547 for (j = 0; j < Ni_len; i += 2, j++) {
7548 hex_to_byteval(&buf[i], &Ni[j]);
7549 }
7550 fputs(buf, ikeresp);
7551 continue;
7552 }
7553 /* Nr = ... */
7554 if (strncmp(buf, "Nr", 2) == 0) {
7555 i = 2;
7556 while (isspace(buf[i]) || buf[i] == '=') {
7557 i++;
7558 }
7559 for (j = 0; j < Nr_len; i += 2, j++) {
7560 hex_to_byteval(&buf[i], &Nr[j]);
7561 }
7562 fputs(buf, ikeresp);
7563 continue;
7564 }
7565 /* CKYi = ... */
7566 if (strncmp(buf, "CKY_I", 5) == 0) {
7567 i = 5;
7568 while (isspace(buf[i]) || buf[i] == '=') {
7569 i++;
7570 }
7571 for (j = 0; j < CKYi_len; i += 2, j++) {
7572 hex_to_byteval(&buf[i], &CKYi[j]);
7573 }
7574 fputs(buf, ikeresp);
7575 continue;
7576 }
7577 /* CKYr = ... */
7578 if (strncmp(buf, "CKY_R", 5) == 0) {
7579 i = 5;
7580 while (isspace(buf[i]) || buf[i] == '=') {
7581 i++;
7582 }
7583 for (j = 0; j < CKYr_len; i += 2, j++) {
7584 hex_to_byteval(&buf[i], &CKYr[j]);
7585 }
7586 fputs(buf, ikeresp);
7587 continue;
7588 }
7589 /* g^xy = ... */
7590 if (strncmp(buf, "g^xy", 4) == 0) {
7591 i = 4;
7592 while (isspace(buf[i]) || buf[i] == '=') {
7593 i++;
7594 }
7595 for (j = 0; j < gxy_len; i += 2, j++) {
7596 hex_to_byteval(&buf[i], &gxy[j]);
7597 }
7598 fputs(buf, ikeresp);
7599 continue;
7600 }
7601 /* pre-shared-key = ... */
7602 if (strncmp(buf, "pre-shared-key", 14) == 0) {
7603 CK_SESSION_HANDLE session;
7604 CK_OBJECT_HANDLE gxy_handle;
7605 CK_OBJECT_HANDLE psk_handle;
7606 CK_OBJECT_HANDLE skeyid_handle;
7607 CK_OBJECT_HANDLE skeyid_d_handle;
7608 CK_OBJECT_HANDLE skeyid_a_handle;
7609 CK_OBJECT_HANDLE skeyid_e_handle;
7610 i = 14;
7611 while (isspace(buf[i]) || buf[i] == '=') {
7612 i++;
7613 }
7614 for (j = 0; j < psk_len; i += 2, j++) {
7615 hex_to_byteval(&buf[i], &psk[j]);
7616 }
7617 fputs(buf, ikeresp);
7618 crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
7619 if (crv != CKR_OK) {
7620 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
7621 (unsigned int)crv);
7622 goto loser;
7623 }
7624 crv = NSC_CreateObject(session, psk_template,
7625 psk_template_count, &psk_handle);
7626 if (crv != CKR_OK) {
7627 fprintf(stderr, "NSC_CreateObject(psk) failed crv=0x%x\n",
7628 (unsigned int)crv);
7629 goto loser;
7630 }
7631 crv = NSC_CreateObject(session, gxy_template,
7632 gxy_template_count, &gxy_handle);
7633 if (crv != CKR_OK) {
7634 fprintf(stderr, "NSC_CreateObject(gxy) failed crv=0x%x\n",
7635 (unsigned int)crv);
7636 goto loser;
7637 }
7638 /* get the skeyid key */
7639 crv = NSC_DeriveKey(session, &ike_mech, psk_handle,
7640 derive_template, derive_template_count - 1,
7641 &skeyid_handle);
7642 if (crv != CKR_OK) {
7643 fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
7644 (unsigned int)crv);
7645 goto loser;
7646 }
7647 skeyid_template.ulValueLen = HASH_LENGTH_MAX;
7648 crv = NSC_GetAttributeValue(session, skeyid_handle,
7649 &skeyid_template, 1);
7650 if (crv != CKR_OK) {
7651 fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
7652 (unsigned int)crv);
7653 goto loser;
7654 }
7655 /* use the length of the skeyid to set the target length of all the
7656 * other keys */
7657 keyLen = skeyid_template.ulValueLen;
7658 ike1_prf.hKeygxy = gxy_handle;
7659 ike1_prf.bHasPrevKey = PR_FALSE;
7660 ike1_prf.keyNumber = 0;
7661 crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
7662 derive_template, derive_template_count,
7663 &skeyid_d_handle);
7664 if (crv != CKR_OK) {
7665 fprintf(stderr, "NSC_DeriveKey(skeyid_d) failed crv=0x%x\n",
7666 (unsigned int)crv);
7667 goto loser;
7668 }
7669
7670 ike1_prf.hKeygxy = gxy_handle;
7671 ike1_prf.bHasPrevKey = CK_TRUE;
7672 ike1_prf.hPrevKey = skeyid_d_handle;
7673 ike1_prf.keyNumber = 1;
7674 crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
7675 derive_template, derive_template_count,
7676 &skeyid_a_handle);
7677 if (crv != CKR_OK) {
7678 fprintf(stderr, "NSC_DeriveKey(skeyid_a) failed crv=0x%x\n",
7679 (unsigned int)crv);
7680 goto loser;
7681 }
7682 ike1_prf.hKeygxy = gxy_handle;
7683 ike1_prf.bHasPrevKey = CK_TRUE;
7684 ike1_prf.hPrevKey = skeyid_a_handle;
7685 ike1_prf.keyNumber = 2;
7686 crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
7687 derive_template, derive_template_count,
7688 &skeyid_e_handle);
7689 if (crv != CKR_OK) {
7690 fprintf(stderr, "NSC_DeriveKey(skeyid_e) failed crv=0x%x\n",
7691 (unsigned int)crv);
7692 goto loser;
7693 }
7694 fputs("SKEYID = ", ikeresp);
7695 to_hex_str(buf, skeyid_secret, keyLen);
7696 fputs(buf, ikeresp);
7697 fputc('\n', ikeresp);
7698
7699 skeyid_d_template.ulValueLen = keyLen;
7700 crv = NSC_GetAttributeValue(session, skeyid_d_handle,
7701 &skeyid_d_template, 1);
7702 if (crv != CKR_OK) {
7703 fprintf(stderr, "NSC_GetAttribute(skeyid_d) failed crv=0x%x\n",
7704 (unsigned int)crv);
7705 goto loser;
7706 }
7707 fputs("SKEYID_d = ", ikeresp);
7708 to_hex_str(buf, skeyid_d_secret, skeyid_d_template.ulValueLen);
7709 fputs(buf, ikeresp);
7710 fputc('\n', ikeresp);
7711
7712 skeyid_a_template.ulValueLen = keyLen;
7713 crv = NSC_GetAttributeValue(session, skeyid_a_handle,
7714 &skeyid_a_template, 1);
7715 if (crv != CKR_OK) {
7716 fprintf(stderr, "NSC_GetAttribute(skeyid_a) failed crv=0x%x\n",
7717 (unsigned int)crv);
7718 goto loser;
7719 }
7720 fputs("SKEYID_a = ", ikeresp);
7721 to_hex_str(buf, skeyid_a_secret, skeyid_a_template.ulValueLen);
7722 fputs(buf, ikeresp);
7723 fputc('\n', ikeresp);
7724
7725 skeyid_e_template.ulValueLen = keyLen;
7726 crv = NSC_GetAttributeValue(session, skeyid_e_handle,
7727 &skeyid_e_template, 1);
7728 if (crv != CKR_OK) {
7729 fprintf(stderr, "NSC_GetAttribute(skeyid_e) failed crv=0x%x\n",
7730 (unsigned int)crv);
7731 goto loser;
7732 }
7733 fputs("SKEYID_e = ", ikeresp);
7734 to_hex_str(buf, skeyid_e_secret, skeyid_e_template.ulValueLen);
7735 fputs(buf, ikeresp);
7736 fputc('\n', ikeresp);
7737
7738 crv = NSC_CloseSession(session);
7739 continue;
7740 }
7741 }
7742 loser:
7743 NSC_Finalize(NULL);
7744 if (psk)
7745 free(psk);
7746 if (gxy)
7747 free(gxy);
7748 if (Ni)
7749 free(Ni);
7750 if (Nr)
7751 free(Nr);
7752 if (ikereq)
7753 fclose(ikereq);
7754 }
7755
7756 void
ikev2(char * reqfn)7757 ikev2(char *reqfn)
7758 {
7759 char buf[4096]; /* holds one line from the input REQUEST file.
7760 * needs to be large enough to hold the longest
7761 * line "g^xy = <2048 hex digits>\n".
7762 */
7763 unsigned char *gir = NULL;
7764 unsigned char *gir_new = NULL;
7765 int gir_len;
7766 unsigned char *Ni = NULL;
7767 int Ni_len;
7768 unsigned char *Nr = NULL;
7769 int Nr_len;
7770 unsigned char *SPIi = NULL;
7771 int SPIi_len = 8;
7772 unsigned char *SPIr = NULL;
7773 int SPIr_len = 8;
7774 unsigned char *DKM = NULL;
7775 int DKM_len;
7776 unsigned char *DKM_child = NULL;
7777 int DKM_child_len;
7778 unsigned char *seed_data = NULL;
7779 int seed_data_len = 0;
7780 unsigned int i, j;
7781 FILE *ikereq = NULL; /* input stream from the REQUEST file */
7782 FILE *ikeresp; /* output stream to the RESPONSE file */
7783
7784 CK_SLOT_ID slotList[10];
7785 CK_SLOT_ID slotID;
7786 CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
7787 CK_ULONG count;
7788 static const CK_C_INITIALIZE_ARGS pk11args = {
7789 NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
7790 (void *)"flags=readOnly,noCertDB,noModDB", NULL
7791 };
7792 static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
7793 static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
7794 static CK_BBOOL ck_true = CK_TRUE;
7795 static CK_ULONG keyLen = 1;
7796 CK_ATTRIBUTE gir_template[] = {
7797 { CKA_VALUE, NULL, 0 },
7798 { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
7799 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
7800 { CKA_DERIVE, &ck_true, sizeof(ck_true) },
7801 };
7802 CK_ULONG gir_template_count =
7803 sizeof(gir_template) / sizeof(gir_template[0]);
7804 CK_ATTRIBUTE gir_new_template[] = {
7805 { CKA_VALUE, NULL, 0 },
7806 { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
7807 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
7808 { CKA_DERIVE, &ck_true, sizeof(ck_true) },
7809 };
7810 CK_ULONG gir_new_template_count =
7811 sizeof(gir_new_template) / sizeof(gir_new_template[0]);
7812 CK_ATTRIBUTE derive_template[] = {
7813 { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
7814 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
7815 { CKA_DERIVE, &ck_true, sizeof(ck_true) },
7816 { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) },
7817 };
7818 CK_ULONG derive_template_count =
7819 sizeof(derive_template) / sizeof(derive_template[0]);
7820 CK_ATTRIBUTE skeyseed_template =
7821 { CKA_VALUE, NULL, 0 };
7822 CK_ATTRIBUTE dkm_template =
7823 { CKA_VALUE, NULL, 0 };
7824 CK_ATTRIBUTE dkm_child_template =
7825 { CKA_VALUE, NULL, 0 };
7826 unsigned char skeyseed_secret[HASH_LENGTH_MAX];
7827
7828 CK_MECHANISM ike_mech = { CKM_NSS_IKE_PRF_DERIVE, NULL, 0 };
7829 CK_MECHANISM ike2_mech = { CKM_NSS_IKE_PRF_PLUS_DERIVE, NULL, 0 };
7830 CK_MECHANISM subset_mech = { CKM_EXTRACT_KEY_FROM_KEY, NULL, 0 };
7831 CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf;
7832 CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS ike2_prf;
7833 CK_EXTRACT_PARAMS subset_params;
7834 CK_RV crv;
7835
7836 /* set up PKCS #11 parameters */
7837 ike_mech.pParameter = &ike_prf;
7838 ike_mech.ulParameterLen = sizeof(ike_prf);
7839 ike2_mech.pParameter = &ike2_prf;
7840 ike2_mech.ulParameterLen = sizeof(ike2_prf);
7841 subset_mech.pParameter = &subset_params;
7842 subset_mech.ulParameterLen = sizeof(subset_params);
7843 subset_params = 0;
7844 skeyseed_template.pValue = skeyseed_secret;
7845 skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
7846
7847 crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
7848 if (crv != CKR_OK) {
7849 fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
7850 goto loser;
7851 }
7852 count = slotListCount;
7853 crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
7854 if (crv != CKR_OK) {
7855 fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
7856 goto loser;
7857 }
7858 if ((count > slotListCount) || count < 1) {
7859 fprintf(stderr,
7860 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
7861 (int)count, (int)slotListCount);
7862 goto loser;
7863 }
7864 slotID = slotList[0];
7865 ikereq = fopen(reqfn, "r");
7866 ikeresp = stdout;
7867 while (fgets(buf, sizeof buf, ikereq) != NULL) {
7868 /* a comment or blank line */
7869 if (buf[0] == '#' || buf[0] == '\n') {
7870 fputs(buf, ikeresp);
7871 continue;
7872 }
7873 /* [.....] */
7874 if (buf[0] == '[') {
7875 if (strncmp(buf, "[SHA-1]", 7) == 0) {
7876 ike_prf.prfMechanism = CKM_SHA_1_HMAC;
7877 ike2_prf.prfMechanism = CKM_SHA_1_HMAC;
7878 }
7879 if (strncmp(buf, "[SHA-224]", 9) == 0) {
7880 ike_prf.prfMechanism = CKM_SHA224_HMAC;
7881 ike2_prf.prfMechanism = CKM_SHA224_HMAC;
7882 }
7883 if (strncmp(buf, "[SHA-256]", 9) == 0) {
7884 ike_prf.prfMechanism = CKM_SHA256_HMAC;
7885 ike2_prf.prfMechanism = CKM_SHA256_HMAC;
7886 }
7887 if (strncmp(buf, "[SHA-384]", 9) == 0) {
7888 ike_prf.prfMechanism = CKM_SHA384_HMAC;
7889 ike2_prf.prfMechanism = CKM_SHA384_HMAC;
7890 }
7891 if (strncmp(buf, "[SHA-512]", 9) == 0) {
7892 ike_prf.prfMechanism = CKM_SHA512_HMAC;
7893 ike2_prf.prfMechanism = CKM_SHA512_HMAC;
7894 }
7895 if (strncmp(buf, "[AES-XCBC", 9) == 0) {
7896 ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
7897 ike2_prf.prfMechanism = CKM_AES_XCBC_MAC;
7898 }
7899 if (strncmp(buf, "[g^ir", 5) == 0) {
7900 if (sscanf(buf, "[g^ir length = %d]",
7901 &gir_len) != 1) {
7902 goto loser;
7903 }
7904 gir_len = gir_len / 8;
7905 if (gir)
7906 free(gir);
7907 if (gir_new)
7908 free(gir_new);
7909 gir = malloc(gir_len);
7910 gir_new = malloc(gir_len);
7911 gir_template[0].pValue = gir;
7912 gir_template[0].ulValueLen = gir_len;
7913 gir_new_template[0].pValue = gir_new;
7914 gir_new_template[0].ulValueLen = gir_len;
7915 }
7916 if (strncmp(buf, "[Ni", 3) == 0) {
7917 if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
7918 goto loser;
7919 }
7920 Ni_len = Ni_len / 8;
7921 }
7922 if (strncmp(buf, "[Nr", 3) == 0) {
7923 if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
7924 goto loser;
7925 }
7926 Nr_len = Nr_len / 8;
7927 }
7928 if (strncmp(buf, "[DKM", 4) == 0) {
7929 if (sscanf(buf, "[DKM length = %d]",
7930 &DKM_len) != 1) {
7931 goto loser;
7932 }
7933 DKM_len = DKM_len / 8;
7934 if (DKM)
7935 free(DKM);
7936 DKM = malloc(DKM_len);
7937 dkm_template.pValue = DKM;
7938 dkm_template.ulValueLen = DKM_len;
7939 }
7940 if (strncmp(buf, "[Child SA DKM", 13) == 0) {
7941 if (sscanf(buf, "[Child SA DKM length = %d]",
7942 &DKM_child_len) != 1) {
7943 goto loser;
7944 }
7945 DKM_child_len = DKM_child_len / 8;
7946 if (DKM_child)
7947 free(DKM_child);
7948 DKM_child = malloc(DKM_child_len);
7949 dkm_child_template.pValue = DKM_child;
7950 dkm_child_template.ulValueLen = DKM_child_len;
7951 }
7952 fputs(buf, ikeresp);
7953 continue;
7954 }
7955 /* "COUNT = x" begins a new data set */
7956 if (strncmp(buf, "COUNT", 5) == 0) {
7957 /* zeroize the variables for the test with this data set */
7958 int new_seed_len = Ni_len + Nr_len + SPIi_len + SPIr_len;
7959 if (seed_data_len != new_seed_len) {
7960 if (seed_data)
7961 free(seed_data);
7962 seed_data_len = new_seed_len;
7963 seed_data = malloc(seed_data_len);
7964 Ni = seed_data;
7965 Nr = &seed_data[Ni_len];
7966 SPIi = &seed_data[Ni_len + Nr_len];
7967 SPIr = &seed_data[new_seed_len - SPIr_len];
7968 ike_prf.pNi = Ni;
7969 ike_prf.ulNiLen = Ni_len;
7970 ike_prf.pNr = Nr;
7971 ike_prf.ulNrLen = Nr_len;
7972 ike2_prf.pSeedData = seed_data;
7973 }
7974 memset(gir, 0, gir_len);
7975 memset(gir_new, 0, gir_len);
7976 memset(seed_data, 0, seed_data_len);
7977 fputs(buf, ikeresp);
7978 continue;
7979 }
7980 /* Ni = ... */
7981 if (strncmp(buf, "Ni", 2) == 0) {
7982 i = 2;
7983 while (isspace(buf[i]) || buf[i] == '=') {
7984 i++;
7985 }
7986 for (j = 0; j < Ni_len; i += 2, j++) {
7987 hex_to_byteval(&buf[i], &Ni[j]);
7988 }
7989 fputs(buf, ikeresp);
7990 continue;
7991 }
7992 /* Nr = ... */
7993 if (strncmp(buf, "Nr", 2) == 0) {
7994 i = 2;
7995 while (isspace(buf[i]) || buf[i] == '=') {
7996 i++;
7997 }
7998 for (j = 0; j < Nr_len; i += 2, j++) {
7999 hex_to_byteval(&buf[i], &Nr[j]);
8000 }
8001 fputs(buf, ikeresp);
8002 continue;
8003 }
8004 /* g^ir (new) = ... */
8005 if (strncmp(buf, "g^ir (new)", 10) == 0) {
8006 i = 10;
8007 while (isspace(buf[i]) || buf[i] == '=') {
8008 i++;
8009 }
8010 for (j = 0; j < gir_len; i += 2, j++) {
8011 hex_to_byteval(&buf[i], &gir_new[j]);
8012 }
8013 fputs(buf, ikeresp);
8014 continue;
8015 }
8016 /* g^ir = ... */
8017 if (strncmp(buf, "g^ir", 4) == 0) {
8018 i = 4;
8019 while (isspace(buf[i]) || buf[i] == '=') {
8020 i++;
8021 }
8022 for (j = 0; j < gir_len; i += 2, j++) {
8023 hex_to_byteval(&buf[i], &gir[j]);
8024 }
8025 fputs(buf, ikeresp);
8026 continue;
8027 }
8028 /* SPIi = ... */
8029 if (strncmp(buf, "SPIi", 4) == 0) {
8030 i = 4;
8031 while (isspace(buf[i]) || buf[i] == '=') {
8032 i++;
8033 }
8034 for (j = 0; j < SPIi_len; i += 2, j++) {
8035 hex_to_byteval(&buf[i], &SPIi[j]);
8036 }
8037 fputs(buf, ikeresp);
8038 continue;
8039 }
8040 /* SPIr = ... */
8041 if (strncmp(buf, "SPIr", 4) == 0) {
8042 CK_SESSION_HANDLE session;
8043 CK_OBJECT_HANDLE gir_handle;
8044 CK_OBJECT_HANDLE gir_new_handle;
8045 CK_OBJECT_HANDLE skeyseed_handle;
8046 CK_OBJECT_HANDLE sk_d_handle;
8047 CK_OBJECT_HANDLE skeyseed_new_handle;
8048 CK_OBJECT_HANDLE dkm_handle;
8049 CK_OBJECT_HANDLE dkm_child_handle;
8050 i = 4;
8051 while (isspace(buf[i]) || buf[i] == '=') {
8052 i++;
8053 }
8054 for (j = 0; j < SPIr_len; i += 2, j++) {
8055 hex_to_byteval(&buf[i], &SPIr[j]);
8056 }
8057 fputs(buf, ikeresp);
8058 crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
8059 if (crv != CKR_OK) {
8060 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
8061 (unsigned int)crv);
8062 goto loser;
8063 }
8064 crv = NSC_CreateObject(session, gir_template,
8065 gir_template_count, &gir_handle);
8066 if (crv != CKR_OK) {
8067 fprintf(stderr, "NSC_CreateObject (g^ir) failed crv=0x%x\n",
8068 (unsigned int)crv);
8069 goto loser;
8070 }
8071 crv = NSC_CreateObject(session, gir_new_template,
8072 gir_new_template_count, &gir_new_handle);
8073 if (crv != CKR_OK) {
8074 fprintf(stderr, "NSC_CreateObject (g^ir new) failed crv=0x%x\n",
8075 (unsigned int)crv);
8076 goto loser;
8077 }
8078 /* get the SKEYSEED key */
8079 ike_prf.bDataAsKey = CK_TRUE;
8080 ike_prf.bRekey = CK_FALSE;
8081 ike_prf.hNewKey = CK_INVALID_HANDLE;
8082 crv = NSC_DeriveKey(session, &ike_mech, gir_handle,
8083 derive_template, derive_template_count - 1,
8084 &skeyseed_handle);
8085 if (crv != CKR_OK) {
8086 fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
8087 (unsigned int)crv);
8088 goto loser;
8089 }
8090 skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
8091 crv = NSC_GetAttributeValue(session, skeyseed_handle,
8092 &skeyseed_template, 1);
8093 if (crv != CKR_OK) {
8094 fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
8095 (unsigned int)crv);
8096 goto loser;
8097 }
8098 fputs("SKEYSEED = ", ikeresp);
8099 to_hex_str(buf, skeyseed_secret, skeyseed_template.ulValueLen);
8100 fputs(buf, ikeresp);
8101 fputc('\n', ikeresp);
8102
8103 /* get DKM */
8104 keyLen = DKM_len;
8105 ike2_prf.bHasSeedKey = CK_FALSE;
8106 ike2_prf.hSeedKey = CK_INVALID_HANDLE;
8107 ike2_prf.ulSeedDataLen = seed_data_len;
8108 crv = NSC_DeriveKey(session, &ike2_mech, skeyseed_handle,
8109 derive_template, derive_template_count,
8110 &dkm_handle);
8111 if (crv != CKR_OK) {
8112 fprintf(stderr, "NSC_DeriveKey(DKM) failed crv=0x%x\n",
8113 (unsigned int)crv);
8114 goto loser;
8115 }
8116 crv = NSC_GetAttributeValue(session, dkm_handle,
8117 &dkm_template, 1);
8118 if (crv != CKR_OK) {
8119 fprintf(stderr, "NSC_GetAttribute(DKM) failed crv=0x%x\n",
8120 (unsigned int)crv);
8121 goto loser;
8122 }
8123 fputs("DKM = ", ikeresp);
8124 to_hex_str(buf, DKM, DKM_len);
8125 fputs(buf, ikeresp);
8126 fputc('\n', ikeresp);
8127
8128 /* get the sk_d from the DKM */
8129 keyLen = skeyseed_template.ulValueLen;
8130 crv = NSC_DeriveKey(session, &subset_mech, dkm_handle,
8131 derive_template, derive_template_count,
8132 &sk_d_handle);
8133 if (crv != CKR_OK) {
8134 fprintf(stderr, "NSC_DeriveKey(sk_d) failed crv=0x%x\n",
8135 (unsigned int)crv);
8136 goto loser;
8137 }
8138
8139 /* get DKM child */
8140 keyLen = DKM_child_len;
8141 ike2_prf.bHasSeedKey = CK_FALSE;
8142 ike2_prf.hSeedKey = CK_INVALID_HANDLE;
8143 ike2_prf.ulSeedDataLen = Ni_len + Nr_len;
8144 crv = NSC_DeriveKey(session, &ike2_mech, sk_d_handle,
8145 derive_template, derive_template_count,
8146 &dkm_child_handle);
8147 if (crv != CKR_OK) {
8148 fprintf(stderr, "NSC_DeriveKey(DKM Child SA) failed crv=0x%x\n",
8149 (unsigned int)crv);
8150 goto loser;
8151 }
8152 crv = NSC_GetAttributeValue(session, dkm_child_handle,
8153 &dkm_child_template, 1);
8154 if (crv != CKR_OK) {
8155 fprintf(stderr, "NSC_GetAttribute(DKM Child SA) failed crv=0x%x\n",
8156 (unsigned int)crv);
8157 goto loser;
8158 }
8159 fputs("DKM(Child SA) = ", ikeresp);
8160 to_hex_str(buf, DKM_child, DKM_child_len);
8161 fputs(buf, ikeresp);
8162 fputc('\n', ikeresp);
8163
8164 /* get DKM child D-H*/
8165 keyLen = DKM_child_len;
8166 ike2_prf.bHasSeedKey = CK_TRUE;
8167 ike2_prf.hSeedKey = gir_new_handle;
8168 ike2_prf.ulSeedDataLen = Ni_len + Nr_len;
8169 crv = NSC_DeriveKey(session, &ike2_mech, sk_d_handle,
8170 derive_template, derive_template_count,
8171 &dkm_child_handle);
8172 if (crv != CKR_OK) {
8173 fprintf(stderr, "NSC_DeriveKey(DKM Child SA D-H) failed crv=0x%x\n",
8174 (unsigned int)crv);
8175 goto loser;
8176 }
8177 crv = NSC_GetAttributeValue(session, dkm_child_handle,
8178 &dkm_child_template, 1);
8179 if (crv != CKR_OK) {
8180 fprintf(stderr, "NSC_GetAttribute(DKM Child SA D-H) failed crv=0x%x\n",
8181 (unsigned int)crv);
8182 goto loser;
8183 }
8184 fputs("DKM(Child SA D-H) = ", ikeresp);
8185 to_hex_str(buf, DKM_child, DKM_child_len);
8186 fputs(buf, ikeresp);
8187 fputc('\n', ikeresp);
8188
8189 /* get SKEYSEED(rekey) */
8190 ike_prf.bDataAsKey = CK_FALSE;
8191 ike_prf.bRekey = CK_TRUE;
8192 ike_prf.hNewKey = gir_new_handle;
8193 crv = NSC_DeriveKey(session, &ike_mech, sk_d_handle,
8194 derive_template, derive_template_count - 1,
8195 &skeyseed_new_handle);
8196 if (crv != CKR_OK) {
8197 fprintf(stderr, "NSC_DeriveKey(skeyid rekey) failed crv=0x%x\n",
8198 (unsigned int)crv);
8199 goto loser;
8200 }
8201 skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
8202 crv = NSC_GetAttributeValue(session, skeyseed_new_handle,
8203 &skeyseed_template, 1);
8204 if (crv != CKR_OK) {
8205 fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
8206 (unsigned int)crv);
8207 goto loser;
8208 }
8209 fputs("SKEYSEED(rekey) = ", ikeresp);
8210 to_hex_str(buf, skeyseed_secret, skeyseed_template.ulValueLen);
8211 fputs(buf, ikeresp);
8212 fputc('\n', ikeresp);
8213
8214 crv = NSC_CloseSession(session);
8215 continue;
8216 }
8217 }
8218 loser:
8219 NSC_Finalize(NULL);
8220 if (gir)
8221 free(gir);
8222 if (gir_new)
8223 free(gir_new);
8224 if (seed_data)
8225 free(seed_data);
8226 if (DKM)
8227 free(DKM);
8228 if (DKM_child)
8229 free(DKM_child);
8230 if (ikereq)
8231 fclose(ikereq);
8232 }
8233
8234 void
kbkdf(char * path)8235 kbkdf(char *path)
8236 {
8237 /* == Parser data == */
8238 char buf[610]; /* holds one line from the input REQUEST file. Needs to
8239 * be large enough to hold the longest line:
8240 * "KO = <600 hex digits>\n". */
8241 CK_ULONG L;
8242 unsigned char KI[64];
8243 unsigned int KI_len = 64;
8244 unsigned char KO[300];
8245 unsigned int KO_len = 300;
8246 /* This is used only with feedback mode. */
8247 unsigned char IV[64];
8248 unsigned int IV_len = 64;
8249 /* These are only used in counter mode with counter location as
8250 * MIDDLE_FIXED. */
8251 unsigned char BeforeFixedInputData[50];
8252 unsigned int BeforeFixedInputData_len = 50;
8253 unsigned char AfterFixedInputData[10];
8254 unsigned int AfterFixedInputData_len = 10;
8255 /* These are used with every KDF type. */
8256 unsigned char FixedInputData[60];
8257 unsigned int FixedInputData_len = 60;
8258
8259 /* Counter locations:
8260 *
8261 * 0: not used
8262 * 1: beginning
8263 * 2: middle
8264 * 3: end */
8265 int ctr_location = 0;
8266 CK_ULONG counter_bitlen = 0;
8267
8268 size_t buf_offset;
8269 size_t offset;
8270
8271 FILE *kbkdf_req = NULL;
8272 FILE *kbkdf_resp = NULL;
8273
8274 /* == PKCS#11 data == */
8275 CK_RV crv;
8276
8277 CK_SLOT_ID slotList[10];
8278 CK_SLOT_ID slotID;
8279 CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
8280 CK_ULONG slotCount = 0;
8281
8282 CK_MECHANISM kdf = { 0 };
8283
8284 CK_MECHANISM_TYPE prf_mech = 0;
8285 CK_BBOOL ck_true = CK_TRUE;
8286
8287 /* We never need more than 3 data parameters. */
8288 CK_PRF_DATA_PARAM dataParams[3];
8289 CK_ULONG dataParams_len = 3;
8290
8291 CK_SP800_108_COUNTER_FORMAT iterator = { CK_FALSE, 0 };
8292
8293 CK_SP800_108_KDF_PARAMS kdfParams = { 0 };
8294 CK_SP800_108_FEEDBACK_KDF_PARAMS feedbackParams = { 0 };
8295
8296 CK_OBJECT_CLASS ck_secret_key = CKO_SECRET_KEY;
8297 CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
8298
8299 CK_ATTRIBUTE prf_template[] = {
8300 { CKA_VALUE, &KI, sizeof(KI) },
8301 { CKA_CLASS, &ck_secret_key, sizeof(ck_secret_key) },
8302 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
8303 { CKA_DERIVE, &ck_true, sizeof(ck_true) }
8304 };
8305 CK_ULONG prf_template_count = sizeof(prf_template) / sizeof(prf_template[0]);
8306
8307 CK_ATTRIBUTE derive_template[] = {
8308 { CKA_CLASS, &ck_secret_key, sizeof(ck_secret_key) },
8309 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
8310 { CKA_DERIVE, &ck_true, sizeof(ck_true) },
8311 { CKA_VALUE_LEN, &L, sizeof(L) }
8312 };
8313 CK_ULONG derive_template_count = sizeof(derive_template) / sizeof(derive_template[0]);
8314
8315 CK_ATTRIBUTE output_key = { CKA_VALUE, KO, KO_len };
8316
8317 const CK_C_INITIALIZE_ARGS pk11args = {
8318 NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
8319 (void *)"flags=readOnly,noCertDB,noModDB", NULL
8320 };
8321
8322 /* == Start up PKCS#11 == */
8323 crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
8324 if (crv != CKR_OK) {
8325 fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
8326 goto done;
8327 }
8328
8329 slotCount = slotListCount;
8330 crv = NSC_GetSlotList(PR_TRUE, slotList, &slotCount);
8331 if (crv != CKR_OK) {
8332 fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
8333 goto done;
8334 }
8335 if ((slotCount > slotListCount) || slotCount < 1) {
8336 fprintf(stderr,
8337 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
8338 (int)slotCount, (int)slotListCount);
8339 goto done;
8340 }
8341 slotID = slotList[0];
8342
8343 /* == Start parsing the file == */
8344 kbkdf_req = fopen(path, "r");
8345 kbkdf_resp = stdout;
8346
8347 while (fgets(buf, sizeof buf, kbkdf_req) != NULL) {
8348 /* If we have a comment, check if it tells us the type of KDF to use.
8349 * This differs per-file, so we have to parse it. */
8350 if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
8351 if (strncmp(buf, "# KDF Mode Supported: Counter Mode", 34) == 0) {
8352 kdf.mechanism = CKM_SP800_108_COUNTER_KDF;
8353 }
8354 if (strncmp(buf, "# KDF Mode Supported: Feedback Mode", 35) == 0) {
8355 kdf.mechanism = CKM_SP800_108_FEEDBACK_KDF;
8356 }
8357 if (strncmp(buf, "# KDF Mode Supported: DblPipeline Mode", 38) == 0) {
8358 kdf.mechanism = CKM_SP800_108_DOUBLE_PIPELINE_KDF;
8359 }
8360
8361 fputs(buf, kbkdf_resp);
8362 continue;
8363 }
8364
8365 /* [....] - context directive */
8366 if (buf[0] == '[') {
8367 /* PRF begins each new section. */
8368 if (strncmp(buf, "[PRF=CMAC_AES128]", 17) == 0) {
8369 prf_mech = CKM_AES_CMAC;
8370 KI_len = 16;
8371 } else if (strncmp(buf, "[PRF=CMAC_AES192]", 17) == 0) {
8372 prf_mech = CKM_AES_CMAC;
8373 KI_len = 24;
8374 } else if (strncmp(buf, "[PRF=CMAC_AES256]", 17) == 0) {
8375 prf_mech = CKM_AES_CMAC;
8376 KI_len = 32;
8377 } else if (strncmp(buf, "[PRF=HMAC_SHA1]", 15) == 0) {
8378 prf_mech = CKM_SHA_1_HMAC;
8379 KI_len = 20;
8380 } else if (strncmp(buf, "[PRF=HMAC_SHA224]", 17) == 0) {
8381 prf_mech = CKM_SHA224_HMAC;
8382 KI_len = 28;
8383 } else if (strncmp(buf, "[PRF=HMAC_SHA256]", 17) == 0) {
8384 prf_mech = CKM_SHA256_HMAC;
8385 KI_len = 32;
8386 } else if (strncmp(buf, "[PRF=HMAC_SHA384]", 17) == 0) {
8387 prf_mech = CKM_SHA384_HMAC;
8388 KI_len = 48;
8389 } else if (strncmp(buf, "[PRF=HMAC_SHA512]", 17) == 0) {
8390 prf_mech = CKM_SHA512_HMAC;
8391 KI_len = 64;
8392 } else if (strncmp(buf, "[PRF=", 5) == 0) {
8393 fprintf(stderr, "Invalid or unsupported PRF mechanism: %s\n", buf);
8394 goto done;
8395 }
8396
8397 /* Then comes counter, if present. */
8398 if (strncmp(buf, "[CTRLOCATION=BEFORE_FIXED]", 26) == 0 ||
8399 strncmp(buf, "[CTRLOCATION=BEFORE_ITER]", 24) == 0) {
8400 ctr_location = 1;
8401 }
8402 if (strncmp(buf, "[CTRLOCATION=MIDDLE_FIXED]", 26) == 0 ||
8403 strncmp(buf, "[CTRLOCATION=AFTER_ITER]", 24) == 0) {
8404 ctr_location = 2;
8405 }
8406 if (strncmp(buf, "[CTRLOCATION=AFTER_FIXED]", 25) == 0) {
8407 ctr_location = 3;
8408 }
8409
8410 /* If counter is present, then we need to know its size. */
8411 if (strncmp(buf, "[RLEN=", 6) == 0) {
8412 if (sscanf(buf, "[RLEN=%lu_BITS]", &counter_bitlen) != 1) {
8413 goto done;
8414 }
8415 }
8416
8417 fputs(buf, kbkdf_resp);
8418 continue;
8419 }
8420
8421 /* Each test contains a counter, an output length L, an input key KI,
8422 * maybe an initialization vector IV, one of a couple of fixed data
8423 * buffers, and finally the output key KO. */
8424
8425 /* First comes COUNT. */
8426 if (strncmp(buf, "COUNT=", 6) == 0) {
8427 /* Clear all out data fields on each test. */
8428 memset(KI, 0, sizeof KI);
8429 memset(KO, 0, sizeof KO);
8430 memset(IV, 0, sizeof IV);
8431 memset(BeforeFixedInputData, 0, sizeof BeforeFixedInputData);
8432 memset(AfterFixedInputData, 0, sizeof AfterFixedInputData);
8433 memset(FixedInputData, 0, sizeof FixedInputData);
8434
8435 /* Then reset lengths except KI: it was determined by PRF
8436 * selection above. */
8437 KO_len = 0;
8438 IV_len = 0;
8439 BeforeFixedInputData_len = 0;
8440 AfterFixedInputData_len = 0;
8441 FixedInputData_len = 0;
8442
8443 fputs(buf, kbkdf_resp);
8444 continue;
8445 }
8446
8447 /* Then comes L. */
8448 if (strncmp(buf, "L = ", 4) == 0) {
8449 if (sscanf(buf, "L = %lu", &L) != 1) {
8450 goto done;
8451 }
8452
8453 if ((L % 8) != 0) {
8454 fprintf(stderr, "Assumption that L was length in bits incorrect: %lu - %s", L, buf);
8455 fprintf(stderr, "Note that NSS only supports byte-aligned outputs and not bit-aligned outputs.\n");
8456 goto done;
8457 }
8458
8459 L = L / 8;
8460
8461 fputs(buf, kbkdf_resp);
8462 continue;
8463 }
8464
8465 /* Then comes KI. */
8466 if (strncmp(buf, "KI = ", 5) == 0) {
8467 buf_offset = 5;
8468
8469 for (offset = 0; offset < KI_len; offset++, buf_offset += 2) {
8470 hex_to_byteval(buf + buf_offset, KI + offset);
8471 }
8472
8473 fputs(buf, kbkdf_resp);
8474 continue;
8475 }
8476
8477 /* Then comes IVlen and IV, if present. */
8478 if (strncmp(buf, "IVlen = ", 8) == 0) {
8479 if (sscanf(buf, "IVlen = %u", &IV_len) != 1) {
8480 goto done;
8481 }
8482
8483 if ((IV_len % 8) != 0) {
8484 fprintf(stderr, "Assumption that IV_len was length in bits incorrect: %u - %s. ", IV_len, buf);
8485 fprintf(stderr, "Note that NSS only supports byte-aligned inputs and not bit-aligned inputs.\n");
8486 goto done;
8487 }
8488
8489 /* Need the IV length in bytes, not bits. */
8490 IV_len = IV_len / 8;
8491
8492 fputs(buf, kbkdf_resp);
8493 continue;
8494 }
8495 if (strncmp(buf, "IV = ", 5) == 0) {
8496 buf_offset = 5;
8497
8498 for (offset = 0; offset < IV_len; offset++, buf_offset += 2) {
8499 hex_to_byteval(buf + buf_offset, IV + offset);
8500 }
8501
8502 fputs(buf, kbkdf_resp);
8503 continue;
8504 }
8505
8506 /* We might have DataBeforeCtr and DataAfterCtr if present. */
8507 if (strncmp(buf, "DataBeforeCtrLen = ", 19) == 0) {
8508 if (sscanf(buf, "DataBeforeCtrLen = %u", &BeforeFixedInputData_len) != 1) {
8509 goto done;
8510 }
8511
8512 fputs(buf, kbkdf_resp);
8513 continue;
8514 }
8515 if (strncmp(buf, "DataBeforeCtrData = ", 20) == 0) {
8516 buf_offset = 20;
8517
8518 for (offset = 0; offset < BeforeFixedInputData_len; offset++, buf_offset += 2) {
8519 hex_to_byteval(buf + buf_offset, BeforeFixedInputData + offset);
8520 }
8521
8522 fputs(buf, kbkdf_resp);
8523 continue;
8524 }
8525 if (strncmp(buf, "DataAfterCtrLen = ", 18) == 0) {
8526 if (sscanf(buf, "DataAfterCtrLen = %u", &AfterFixedInputData_len) != 1) {
8527 goto done;
8528 }
8529
8530 fputs(buf, kbkdf_resp);
8531 continue;
8532 }
8533 if (strncmp(buf, "DataAfterCtrData = ", 19) == 0) {
8534 buf_offset = 19;
8535
8536 for (offset = 0; offset < AfterFixedInputData_len; offset++, buf_offset += 2) {
8537 hex_to_byteval(buf + buf_offset, AfterFixedInputData + offset);
8538 }
8539
8540 fputs(buf, kbkdf_resp);
8541 continue;
8542 }
8543
8544 /* Otherwise, we might have FixedInputData, if present. */
8545 if (strncmp(buf, "FixedInputDataByteLen = ", 24) == 0) {
8546 if (sscanf(buf, "FixedInputDataByteLen = %u", &FixedInputData_len) != 1) {
8547 goto done;
8548 }
8549
8550 fputs(buf, kbkdf_resp);
8551 continue;
8552 }
8553 if (strncmp(buf, "FixedInputData = ", 17) == 0) {
8554 buf_offset = 17;
8555
8556 for (offset = 0; offset < FixedInputData_len; offset++, buf_offset += 2) {
8557 hex_to_byteval(buf + buf_offset, FixedInputData + offset);
8558 }
8559
8560 fputs(buf, kbkdf_resp);
8561 continue;
8562 }
8563
8564 /* Finally, run the KBKDF calculation when KO is passed. */
8565 if (strncmp(buf, "KO = ", 5) == 0) {
8566 CK_SESSION_HANDLE session;
8567 CK_OBJECT_HANDLE prf_key;
8568 CK_OBJECT_HANDLE derived_key;
8569
8570 /* Open the session. */
8571 crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
8572 if (crv != CKR_OK) {
8573 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n", (unsigned int)crv);
8574 goto done;
8575 }
8576
8577 /* Create the PRF key object. */
8578 prf_template[0].ulValueLen = KI_len;
8579 crv = NSC_CreateObject(session, prf_template, prf_template_count, &prf_key);
8580 if (crv != CKR_OK) {
8581 fprintf(stderr, "NSC_CreateObject (prf_key) failed crv=0x%x\n", (unsigned int)crv);
8582 goto done;
8583 }
8584
8585 /* Set up the KDF parameters. */
8586 if (kdf.mechanism == CKM_SP800_108_COUNTER_KDF) {
8587 /* Counter operates in one of three ways: counter before fixed
8588 * input data, counter between fixed input data, and counter
8589 * after fixed input data. In all cases, we have an iterator.
8590 */
8591 iterator.ulWidthInBits = counter_bitlen;
8592
8593 if (ctr_location == 0 || ctr_location > 3) {
8594 fprintf(stderr, "Expected ctr_location != 0 for Counter Mode KDF but got 0.\n");
8595 goto done;
8596 } else if (ctr_location == 1) {
8597 /* Counter before */
8598 dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
8599 dataParams[0].pValue = &iterator;
8600 dataParams[0].ulValueLen = sizeof(iterator);
8601
8602 dataParams[1].type = CK_SP800_108_BYTE_ARRAY;
8603 dataParams[1].pValue = FixedInputData;
8604 dataParams[1].ulValueLen = FixedInputData_len;
8605
8606 dataParams_len = 2;
8607 } else if (ctr_location == 2) {
8608 /* Counter between */
8609 dataParams[0].type = CK_SP800_108_BYTE_ARRAY;
8610 dataParams[0].pValue = BeforeFixedInputData;
8611 dataParams[0].ulValueLen = BeforeFixedInputData_len;
8612
8613 dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE;
8614 dataParams[1].pValue = &iterator;
8615 dataParams[1].ulValueLen = sizeof(iterator);
8616
8617 dataParams[2].type = CK_SP800_108_BYTE_ARRAY;
8618 dataParams[2].pValue = AfterFixedInputData;
8619 dataParams[2].ulValueLen = AfterFixedInputData_len;
8620
8621 dataParams_len = 3;
8622 } else {
8623 /* Counter after */
8624 dataParams[0].type = CK_SP800_108_BYTE_ARRAY;
8625 dataParams[0].pValue = FixedInputData;
8626 dataParams[0].ulValueLen = FixedInputData_len;
8627
8628 dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE;
8629 dataParams[1].pValue = &iterator;
8630 dataParams[1].ulValueLen = sizeof(iterator);
8631
8632 dataParams_len = 2;
8633 }
8634 } else if (kdf.mechanism == CKM_SP800_108_FEEDBACK_KDF || kdf.mechanism == CKM_SP800_108_DOUBLE_PIPELINE_KDF) {
8635 /* When counter_bitlen != 0, we have an optional counter. */
8636 if (counter_bitlen != 0) {
8637 iterator.ulWidthInBits = counter_bitlen;
8638
8639 if (ctr_location == 0 || ctr_location > 3) {
8640 fprintf(stderr, "Expected ctr_location != 0 for Counter Mode KDF but got 0.\n");
8641 goto done;
8642 } else if (ctr_location == 1) {
8643 /* Counter before */
8644 dataParams[0].type = CK_SP800_108_OPTIONAL_COUNTER;
8645 dataParams[0].pValue = &iterator;
8646 dataParams[0].ulValueLen = sizeof(iterator);
8647
8648 dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE;
8649 dataParams[1].pValue = NULL;
8650 dataParams[1].ulValueLen = 0;
8651
8652 dataParams[2].type = CK_SP800_108_BYTE_ARRAY;
8653 dataParams[2].pValue = FixedInputData;
8654 dataParams[2].ulValueLen = FixedInputData_len;
8655
8656 dataParams_len = 3;
8657 } else if (ctr_location == 2) {
8658 /* Counter between */
8659 dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
8660 dataParams[0].pValue = NULL;
8661 dataParams[0].ulValueLen = 0;
8662
8663 dataParams[1].type = CK_SP800_108_OPTIONAL_COUNTER;
8664 dataParams[1].pValue = &iterator;
8665 dataParams[1].ulValueLen = sizeof(iterator);
8666
8667 dataParams[2].type = CK_SP800_108_BYTE_ARRAY;
8668 dataParams[2].pValue = FixedInputData;
8669 dataParams[2].ulValueLen = FixedInputData_len;
8670
8671 dataParams_len = 3;
8672 } else {
8673 /* Counter after */
8674 dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
8675 dataParams[0].pValue = NULL;
8676 dataParams[0].ulValueLen = 0;
8677
8678 dataParams[1].type = CK_SP800_108_BYTE_ARRAY;
8679 dataParams[1].pValue = FixedInputData;
8680 dataParams[1].ulValueLen = FixedInputData_len;
8681
8682 dataParams[2].type = CK_SP800_108_OPTIONAL_COUNTER;
8683 dataParams[2].pValue = &iterator;
8684 dataParams[2].ulValueLen = sizeof(iterator);
8685
8686 dataParams_len = 3;
8687 }
8688 } else {
8689 dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
8690 dataParams[0].pValue = NULL;
8691 dataParams[0].ulValueLen = 0;
8692
8693 dataParams[1].type = CK_SP800_108_BYTE_ARRAY;
8694 dataParams[1].pValue = FixedInputData;
8695 dataParams[1].ulValueLen = FixedInputData_len;
8696
8697 dataParams_len = 2;
8698 }
8699 }
8700
8701 if (kdf.mechanism != CKM_SP800_108_FEEDBACK_KDF) {
8702 kdfParams.prfType = prf_mech;
8703 kdfParams.ulNumberOfDataParams = dataParams_len;
8704 kdfParams.pDataParams = dataParams;
8705
8706 kdf.pParameter = &kdfParams;
8707 kdf.ulParameterLen = sizeof(kdfParams);
8708 } else {
8709 feedbackParams.prfType = prf_mech;
8710 feedbackParams.ulNumberOfDataParams = dataParams_len;
8711 feedbackParams.pDataParams = dataParams;
8712 feedbackParams.ulIVLen = IV_len;
8713 if (IV_len == 0) {
8714 feedbackParams.pIV = NULL;
8715 } else {
8716 feedbackParams.pIV = IV;
8717 }
8718
8719 kdf.pParameter = &feedbackParams;
8720 kdf.ulParameterLen = sizeof(feedbackParams);
8721 }
8722
8723 crv = NSC_DeriveKey(session, &kdf, prf_key, derive_template, derive_template_count, &derived_key);
8724 if (crv != CKR_OK) {
8725 fprintf(stderr, "NSC_DeriveKey(derived_key) failed crv=0x%x\n", (unsigned int)crv);
8726 goto done;
8727 }
8728
8729 crv = NSC_GetAttributeValue(session, derived_key, &output_key, 1);
8730 if (crv != CKR_OK) {
8731 fprintf(stderr, "NSC_GetAttribute(derived_value) failed crv=0x%x\n", (unsigned int)crv);
8732 goto done;
8733 }
8734
8735 fputs("KO = ", kbkdf_resp);
8736 to_hex_str(buf, KO, output_key.ulValueLen);
8737 fputs(buf, kbkdf_resp);
8738 fputs("\r\n", kbkdf_resp);
8739
8740 continue;
8741 }
8742 }
8743
8744 done:
8745 if (kbkdf_req != NULL) {
8746 fclose(kbkdf_req);
8747 }
8748 if (kbkdf_resp != stdout && kbkdf_resp != NULL) {
8749 fclose(kbkdf_resp);
8750 }
8751
8752 return;
8753 }
8754
8755 int
main(int argc,char ** argv)8756 main(int argc, char **argv)
8757 {
8758 if (argc < 2)
8759 exit(-1);
8760
8761 RNG_RNGInit();
8762 SECOID_Init();
8763
8764 /*************/
8765 /* TDEA */
8766 /*************/
8767 if (strcmp(argv[1], "tdea") == 0) {
8768 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
8769 if (strcmp(argv[2], "kat") == 0) {
8770 /* Known Answer Test (KAT) */
8771 tdea_kat_mmt(argv[4]);
8772 } else if (strcmp(argv[2], "mmt") == 0) {
8773 /* Multi-block Message Test (MMT) */
8774 tdea_kat_mmt(argv[4]);
8775 } else if (strcmp(argv[2], "mct") == 0) {
8776 /* Monte Carlo Test (MCT) */
8777 if (strcmp(argv[3], "ecb") == 0) {
8778 /* ECB mode */
8779 tdea_mct(NSS_DES_EDE3, argv[4]);
8780 } else if (strcmp(argv[3], "cbc") == 0) {
8781 /* CBC mode */
8782 tdea_mct(NSS_DES_EDE3_CBC, argv[4]);
8783 }
8784 }
8785 /*************/
8786 /* AES */
8787 /*************/
8788 } else if (strcmp(argv[1], "aes") == 0) {
8789 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
8790 if (strcmp(argv[2], "kat") == 0) {
8791 /* Known Answer Test (KAT) */
8792 aes_kat_mmt(argv[4]);
8793 } else if (strcmp(argv[2], "mmt") == 0) {
8794 /* Multi-block Message Test (MMT) */
8795 aes_kat_mmt(argv[4]);
8796 } else if (strcmp(argv[2], "gcm") == 0) {
8797 if (strcmp(argv[3], "decrypt") == 0) {
8798 aes_gcm(argv[4], 0);
8799 } else if (strcmp(argv[3], "encrypt_extiv") == 0) {
8800 aes_gcm(argv[4], 1);
8801 } else if (strcmp(argv[3], "encrypt_intiv") == 0) {
8802 aes_gcm(argv[4], 2);
8803 }
8804 } else if (strcmp(argv[2], "mct") == 0) {
8805 /* Monte Carlo Test (MCT) */
8806 if (strcmp(argv[3], "ecb") == 0) {
8807 /* ECB mode */
8808 aes_ecb_mct(argv[4]);
8809 } else if (strcmp(argv[3], "cbc") == 0) {
8810 /* CBC mode */
8811 aes_cbc_mct(argv[4]);
8812 }
8813 }
8814 /*************/
8815 /* SHA */
8816 /*************/
8817 } else if (strcmp(argv[1], "sha") == 0) {
8818 sha_test(argv[2]);
8819 /*************/
8820 /* RSA */
8821 /*************/
8822 } else if (strcmp(argv[1], "rsa") == 0) {
8823 /* argv[2]=siggen|sigver */
8824 /* argv[3]=<test name>.req */
8825 if (strcmp(argv[2], "siggen") == 0) {
8826 /* Signature Generation Test */
8827 rsa_siggen_test(argv[3]);
8828 } else if (strcmp(argv[2], "sigver") == 0) {
8829 /* Signature Verification Test */
8830 rsa_sigver_test(argv[3]);
8831 } else if (strcmp(argv[2], "keypair") == 0) {
8832 /* Key Pair Generation Test */
8833 rsa_keypair_test(argv[3]);
8834 }
8835 /*************/
8836 /* HMAC */
8837 /*************/
8838 } else if (strcmp(argv[1], "hmac") == 0) {
8839 hmac_test(argv[2]);
8840 /*************/
8841 /* DSA */
8842 /*************/
8843 } else if (strcmp(argv[1], "dsa") == 0) {
8844 /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */
8845 /* argv[3]=<test name>.req */
8846 if (strcmp(argv[2], "keypair") == 0) {
8847 /* Key Pair Generation Test */
8848 dsa_keypair_test(argv[3]);
8849 } else if (strcmp(argv[2], "pqggen") == 0) {
8850 /* Domain Parameter Generation Test */
8851 dsa_pqggen_test(argv[3]);
8852 } else if (strcmp(argv[2], "pqgver") == 0) {
8853 /* Domain Parameter Validation Test */
8854 dsa_pqgver_test(argv[3]);
8855 } else if (strcmp(argv[2], "siggen") == 0) {
8856 /* Signature Generation Test */
8857 dsa_siggen_test(argv[3]);
8858 } else if (strcmp(argv[2], "sigver") == 0) {
8859 /* Signature Verification Test */
8860 dsa_sigver_test(argv[3]);
8861 }
8862 /*************/
8863 /* ECDSA */
8864 /*************/
8865 } else if (strcmp(argv[1], "ecdsa") == 0) {
8866 /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */
8867 if (strcmp(argv[2], "keypair") == 0) {
8868 /* Key Pair Generation Test */
8869 ecdsa_keypair_test(argv[3]);
8870 } else if (strcmp(argv[2], "pkv") == 0) {
8871 /* Public Key Validation Test */
8872 ecdsa_pkv_test(argv[3]);
8873 } else if (strcmp(argv[2], "siggen") == 0) {
8874 /* Signature Generation Test */
8875 ecdsa_siggen_test(argv[3]);
8876 } else if (strcmp(argv[2], "sigver") == 0) {
8877 /* Signature Verification Test */
8878 ecdsa_sigver_test(argv[3]);
8879 }
8880 /*************/
8881 /* ECDH */
8882 /*************/
8883 } else if (strcmp(argv[1], "ecdh") == 0) {
8884 /* argv[2]={init|resp}-{func|verify} argv[3]=<test name>.req */
8885 if (strcmp(argv[2], "init-func") == 0) {
8886 ecdh_functional(argv[3], 0);
8887 } else if (strcmp(argv[2], "resp-func") == 0) {
8888 ecdh_functional(argv[3], 1);
8889 } else if (strcmp(argv[2], "init-verify") == 0) {
8890 ecdh_verify(argv[3], 0);
8891 } else if (strcmp(argv[2], "resp-verify") == 0) {
8892 ecdh_verify(argv[3], 1);
8893 }
8894 /*************/
8895 /* DH */
8896 /*************/
8897 } else if (strcmp(argv[1], "dh") == 0) {
8898 /* argv[2]={init|resp}-{func|verify} argv[3]=<test name>.req */
8899 if (strcmp(argv[2], "init-func") == 0) {
8900 dh_functional(argv[3], 0);
8901 } else if (strcmp(argv[2], "resp-func") == 0) {
8902 dh_functional(argv[3], 1);
8903 } else if (strcmp(argv[2], "init-verify") == 0) {
8904 dh_verify(argv[3], 0);
8905 } else if (strcmp(argv[2], "resp-verify") == 0) {
8906 dh_verify(argv[3], 1);
8907 }
8908 /*************/
8909 /* RNG */
8910 /*************/
8911 } else if (strcmp(argv[1], "rng") == 0) {
8912 /* argv[2]=vst|mct argv[3]=<test name>.req */
8913 if (strcmp(argv[2], "vst") == 0) {
8914 /* Variable Seed Test */
8915 rng_vst(argv[3]);
8916 } else if (strcmp(argv[2], "mct") == 0) {
8917 /* Monte Carlo Test */
8918 rng_mct(argv[3]);
8919 }
8920 } else if (strcmp(argv[1], "drbg") == 0) {
8921 /* Variable Seed Test */
8922 drbg(argv[2]);
8923 } else if (strcmp(argv[1], "ddrbg") == 0) {
8924 debug = 1;
8925 drbg(argv[2]);
8926 } else if (strcmp(argv[1], "tls") == 0) {
8927 tls(argv[2]);
8928 } else if (strcmp(argv[1], "ikev1") == 0) {
8929 ikev1(argv[2]);
8930 } else if (strcmp(argv[1], "ikev1-psk") == 0) {
8931 ikev1_psk(argv[2]);
8932 } else if (strcmp(argv[1], "ikev2") == 0) {
8933 ikev2(argv[2]);
8934 } else if (strcmp(argv[1], "kbkdf") == 0) {
8935 kbkdf(argv[2]);
8936 }
8937 return 0;
8938 }
8939