Bumping manifests a=b2g-bump
[gecko.git] / security / nss / cmd / fipstest / fipstest.c
blobcdd6b1aa5459754041e1e60710bdaa64f28ec674
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/. */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <ctype.h>
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"
21 #if 0
22 #include "../../lib/freebl/mpi/mpi.h"
23 #endif
25 #ifndef NSS_DISABLE_ECC
26 extern SECStatus
27 EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
28 extern SECStatus
29 EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
30 const ECParams *srcParams);
31 #endif
33 #define ENCRYPT 1
34 #define DECRYPT 0
35 #define BYTE unsigned char
36 #define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001
37 #define RSA_MAX_TEST_MODULUS_BITS 4096
38 #define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS/8
39 #define RSA_MAX_TEST_EXPONENT_BYTES 8
40 #define PQG_TEST_SEED_BYTES 20
42 SECStatus
43 hex_to_byteval(const char *c2, unsigned char *byteval)
45 int i;
46 unsigned char offset;
47 *byteval = 0;
48 for (i=0; i<2; i++) {
49 if (c2[i] >= '0' && c2[i] <= '9') {
50 offset = c2[i] - '0';
51 *byteval |= offset << 4*(1-i);
52 } else if (c2[i] >= 'a' && c2[i] <= 'f') {
53 offset = c2[i] - 'a';
54 *byteval |= (offset + 10) << 4*(1-i);
55 } else if (c2[i] >= 'A' && c2[i] <= 'F') {
56 offset = c2[i] - 'A';
57 *byteval |= (offset + 10) << 4*(1-i);
58 } else {
59 return SECFailure;
62 return SECSuccess;
65 SECStatus
66 byteval_to_hex(unsigned char byteval, char *c2, char a)
68 int i;
69 unsigned char offset;
70 for (i=0; i<2; i++) {
71 offset = (byteval >> 4*(1-i)) & 0x0f;
72 if (offset < 10) {
73 c2[i] = '0' + offset;
74 } else {
75 c2[i] = a + offset - 10;
78 return SECSuccess;
81 void
82 to_hex_str(char *str, const unsigned char *buf, unsigned int len)
84 unsigned int i;
85 for (i=0; i<len; i++) {
86 byteval_to_hex(buf[i], &str[2*i], 'a');
88 str[2*len] = '\0';
91 void
92 to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len)
94 unsigned int i;
95 for (i=0; i<len; i++) {
96 byteval_to_hex(buf[i], &str[2*i], 'A');
98 str[2*len] = '\0';
102 * Convert a string of hex digits (str) to an array (buf) of len bytes.
103 * Return PR_TRUE if the hex string can fit in the byte array. Return
104 * PR_FALSE if the hex string is empty or is too long.
106 PRBool
107 from_hex_str(unsigned char *buf, unsigned int len, const char *str)
109 unsigned int nxdigit; /* number of hex digits in str */
110 unsigned int i; /* index into buf */
111 unsigned int j; /* index into str */
113 /* count the hex digits */
114 nxdigit = 0;
115 for (nxdigit = 0; isxdigit(str[nxdigit]); nxdigit++) {
116 /* empty body */
118 if (nxdigit == 0) {
119 return PR_FALSE;
121 if (nxdigit > 2*len) {
123 * The input hex string is too long, but we allow it if the
124 * extra digits are leading 0's.
126 for (j = 0; j < nxdigit-2*len; j++) {
127 if (str[j] != '0') {
128 return PR_FALSE;
131 /* skip leading 0's */
132 str += nxdigit-2*len;
133 nxdigit = 2*len;
135 for (i=0, j=0; i< len; i++) {
136 if (2*i < 2*len-nxdigit) {
137 /* Handle a short input as if we padded it with leading 0's. */
138 if (2*i+1 < 2*len-nxdigit) {
139 buf[i] = 0;
140 } else {
141 char tmp[2];
142 tmp[0] = '0';
143 tmp[1] = str[j];
144 hex_to_byteval(tmp, &buf[i]);
145 j++;
147 } else {
148 hex_to_byteval(&str[j], &buf[i]);
149 j += 2;
152 return PR_TRUE;
155 SECStatus
156 tdea_encrypt_buf(
157 int mode,
158 const unsigned char *key,
159 const unsigned char *iv,
160 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
161 const unsigned char *input, unsigned int inputlen)
163 SECStatus rv = SECFailure;
164 DESContext *cx;
165 unsigned char doublecheck[8*20]; /* 1 to 20 blocks */
166 unsigned int doublechecklen = 0;
168 cx = DES_CreateContext(key, iv, mode, PR_TRUE);
169 if (cx == NULL) {
170 goto loser;
172 rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
173 if (rv != SECSuccess) {
174 goto loser;
176 if (*outputlen != inputlen) {
177 goto loser;
179 DES_DestroyContext(cx, PR_TRUE);
180 cx = NULL;
183 * Doublecheck our result by decrypting the ciphertext and
184 * compare the output with the input plaintext.
186 cx = DES_CreateContext(key, iv, mode, PR_FALSE);
187 if (cx == NULL) {
188 goto loser;
190 rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
191 output, *outputlen);
192 if (rv != SECSuccess) {
193 goto loser;
195 if (doublechecklen != *outputlen) {
196 goto loser;
198 DES_DestroyContext(cx, PR_TRUE);
199 cx = NULL;
200 if (memcmp(doublecheck, input, inputlen) != 0) {
201 goto loser;
203 rv = SECSuccess;
205 loser:
206 if (cx != NULL) {
207 DES_DestroyContext(cx, PR_TRUE);
209 return rv;
212 SECStatus
213 tdea_decrypt_buf(
214 int mode,
215 const unsigned char *key,
216 const unsigned char *iv,
217 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
218 const unsigned char *input, unsigned int inputlen)
220 SECStatus rv = SECFailure;
221 DESContext *cx;
222 unsigned char doublecheck[8*20]; /* 1 to 20 blocks */
223 unsigned int doublechecklen = 0;
225 cx = DES_CreateContext(key, iv, mode, PR_FALSE);
226 if (cx == NULL) {
227 goto loser;
229 rv = DES_Decrypt(cx, output, outputlen, maxoutputlen,
230 input, inputlen);
231 if (rv != SECSuccess) {
232 goto loser;
234 if (*outputlen != inputlen) {
235 goto loser;
237 DES_DestroyContext(cx, PR_TRUE);
238 cx = NULL;
241 * Doublecheck our result by encrypting the plaintext and
242 * compare the output with the input ciphertext.
244 cx = DES_CreateContext(key, iv, mode, PR_TRUE);
245 if (cx == NULL) {
246 goto loser;
248 rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
249 output, *outputlen);
250 if (rv != SECSuccess) {
251 goto loser;
253 if (doublechecklen != *outputlen) {
254 goto loser;
256 DES_DestroyContext(cx, PR_TRUE);
257 cx = NULL;
258 if (memcmp(doublecheck, input, inputlen) != 0) {
259 goto loser;
261 rv = SECSuccess;
263 loser:
264 if (cx != NULL) {
265 DES_DestroyContext(cx, PR_TRUE);
267 return rv;
271 * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
272 * Test (MMT) in ECB or CBC mode. The KAT (there are five types)
273 * and MMT have the same structure: given the key and IV (CBC mode
274 * only), encrypt the given plaintext or decrypt the given ciphertext.
275 * So we can handle them the same way.
277 * reqfn is the pathname of the REQUEST file.
279 * The output RESPONSE file is written to stdout.
281 void
282 tdea_kat_mmt(char *reqfn)
284 char buf[180]; /* holds one line from the input REQUEST file.
285 * needs to be large enough to hold the longest
286 * line "CIPHERTEXT = <180 hex digits>\n".
288 FILE *req; /* input stream from the REQUEST file */
289 FILE *resp; /* output stream to the RESPONSE file */
290 int i, j;
291 int mode; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
292 int crypt = DECRYPT; /* 1 means encrypt, 0 means decrypt */
293 unsigned char key[24]; /* TDEA 3 key bundle */
294 unsigned int numKeys = 0;
295 unsigned char iv[8]; /* for all modes except ECB */
296 unsigned char plaintext[8*20]; /* 1 to 20 blocks */
297 unsigned int plaintextlen;
298 unsigned char ciphertext[8*20]; /* 1 to 20 blocks */
299 unsigned int ciphertextlen;
300 SECStatus rv;
302 req = fopen(reqfn, "r");
303 resp = stdout;
304 while (fgets(buf, sizeof buf, req) != NULL) {
305 /* a comment or blank line */
306 if (buf[0] == '#' || buf[0] == '\n') {
307 fputs(buf, resp);
308 continue;
310 /* [ENCRYPT] or [DECRYPT] */
311 if (buf[0] == '[') {
312 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
313 crypt = ENCRYPT;
314 } else {
315 crypt = DECRYPT;
317 fputs(buf, resp);
318 continue;
320 /* NumKeys */
321 if (strncmp(&buf[0], "NumKeys", 7) == 0) {
322 i = 7;
323 while (isspace(buf[i]) || buf[i] == '=') {
324 i++;
326 numKeys = buf[i];
327 fputs(buf, resp);
328 continue;
330 /* "COUNT = x" begins a new data set */
331 if (strncmp(buf, "COUNT", 5) == 0) {
332 /* mode defaults to ECB, if dataset has IV mode will be set CBC */
333 mode = NSS_DES_EDE3;
334 /* zeroize the variables for the test with this data set */
335 memset(key, 0, sizeof key);
336 memset(iv, 0, sizeof iv);
337 memset(plaintext, 0, sizeof plaintext);
338 plaintextlen = 0;
339 memset(ciphertext, 0, sizeof ciphertext);
340 ciphertextlen = 0;
341 fputs(buf, resp);
342 continue;
344 if (numKeys == 0) {
345 if (strncmp(buf, "KEYs", 4) == 0) {
346 i = 4;
347 while (isspace(buf[i]) || buf[i] == '=') {
348 i++;
350 for (j=0; isxdigit(buf[i]); i+=2,j++) {
351 hex_to_byteval(&buf[i], &key[j]);
352 key[j+8] = key[j];
353 key[j+16] = key[j];
355 fputs(buf, resp);
356 continue;
358 } else {
359 /* KEY1 = ... */
360 if (strncmp(buf, "KEY1", 4) == 0) {
361 i = 4;
362 while (isspace(buf[i]) || buf[i] == '=') {
363 i++;
365 for (j=0; isxdigit(buf[i]); i+=2,j++) {
366 hex_to_byteval(&buf[i], &key[j]);
368 fputs(buf, resp);
369 continue;
371 /* KEY2 = ... */
372 if (strncmp(buf, "KEY2", 4) == 0) {
373 i = 4;
374 while (isspace(buf[i]) || buf[i] == '=') {
375 i++;
377 for (j=8; isxdigit(buf[i]); i+=2,j++) {
378 hex_to_byteval(&buf[i], &key[j]);
380 fputs(buf, resp);
381 continue;
383 /* KEY3 = ... */
384 if (strncmp(buf, "KEY3", 4) == 0) {
385 i = 4;
386 while (isspace(buf[i]) || buf[i] == '=') {
387 i++;
389 for (j=16; isxdigit(buf[i]); i+=2,j++) {
390 hex_to_byteval(&buf[i], &key[j]);
392 fputs(buf, resp);
393 continue;
397 /* IV = ... */
398 if (strncmp(buf, "IV", 2) == 0) {
399 mode = NSS_DES_EDE3_CBC;
400 i = 2;
401 while (isspace(buf[i]) || buf[i] == '=') {
402 i++;
404 for (j=0; j<sizeof iv; i+=2,j++) {
405 hex_to_byteval(&buf[i], &iv[j]);
407 fputs(buf, resp);
408 continue;
411 /* PLAINTEXT = ... */
412 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
413 /* sanity check */
414 if (crypt != ENCRYPT) {
415 goto loser;
417 i = 9;
418 while (isspace(buf[i]) || buf[i] == '=') {
419 i++;
421 for (j=0; isxdigit(buf[i]); i+=2,j++) {
422 hex_to_byteval(&buf[i], &plaintext[j]);
424 plaintextlen = j;
425 rv = tdea_encrypt_buf(mode, key,
426 (mode == NSS_DES_EDE3) ? NULL : iv,
427 ciphertext, &ciphertextlen, sizeof ciphertext,
428 plaintext, plaintextlen);
429 if (rv != SECSuccess) {
430 goto loser;
433 fputs(buf, resp);
434 fputs("CIPHERTEXT = ", resp);
435 to_hex_str(buf, ciphertext, ciphertextlen);
436 fputs(buf, resp);
437 fputc('\n', resp);
438 continue;
440 /* CIPHERTEXT = ... */
441 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
442 /* sanity check */
443 if (crypt != DECRYPT) {
444 goto loser;
447 i = 10;
448 while (isspace(buf[i]) || buf[i] == '=') {
449 i++;
451 for (j=0; isxdigit(buf[i]); i+=2,j++) {
452 hex_to_byteval(&buf[i], &ciphertext[j]);
454 ciphertextlen = j;
456 rv = tdea_decrypt_buf(mode, key,
457 (mode == NSS_DES_EDE3) ? NULL : iv,
458 plaintext, &plaintextlen, sizeof plaintext,
459 ciphertext, ciphertextlen);
460 if (rv != SECSuccess) {
461 goto loser;
464 fputs(buf, resp);
465 fputs("PLAINTEXT = ", resp);
466 to_hex_str(buf, plaintext, plaintextlen);
467 fputs(buf, resp);
468 fputc('\n', resp);
469 continue;
473 loser:
474 fclose(req);
478 * Set the parity bit for the given byte
480 BYTE odd_parity( BYTE in)
482 BYTE out = in;
483 in ^= in >> 4;
484 in ^= in >> 2;
485 in ^= in >> 1;
486 return (BYTE)(out ^ !(in & 1));
490 * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j]
491 * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
493 void
494 tdea_mct_next_keys(unsigned char *key,
495 const unsigned char *text_2, const unsigned char *text_1,
496 const unsigned char *text, unsigned int numKeys)
498 int k;
500 /* key1[i+1] = key1[i] xor PT/CT[j] */
501 for (k=0; k<8; k++) {
502 key[k] ^= text[k];
504 /* key2 */
505 if (numKeys == 2 || numKeys == 3) {
506 /* key2 independent */
507 for (k=8; k<16; k++) {
508 /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
509 key[k] ^= text_1[k-8];
511 } else {
512 /* key2 == key 1 */
513 for (k=8; k<16; k++) {
514 /* key2[i+1] = KEY2[i] xor PT/CT[j] */
515 key[k] = key[k-8];
518 /* key3 */
519 if (numKeys == 1 || numKeys == 2) {
520 /* key3 == key 1 */
521 for (k=16; k<24; k++) {
522 /* key3[i+1] = KEY3[i] xor PT/CT[j] */
523 key[k] = key[k-16];
525 } else {
526 /* key3 independent */
527 for (k=16; k<24; k++) {
528 /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
529 key[k] ^= text_2[k-16];
532 /* set the parity bits */
533 for (k=0; k<24; k++) {
534 key[k] = odd_parity(key[k]);
539 * Perform the Monte Carlo Test
541 * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
542 * crypt = ENCRYPT || DECRYPT
543 * inputtext = plaintext or Cyphertext depending on the value of crypt
544 * inputlength is expected to be size 8 bytes
545 * iv = needs to be set for NSS_DES_EDE3_CBC mode
546 * resp = is the output response file.
548 void
549 tdea_mct_test(int mode, unsigned char* key, unsigned int numKeys,
550 unsigned int crypt, unsigned char* inputtext,
551 unsigned int inputlength, unsigned char* iv, FILE *resp) {
553 int i, j;
554 unsigned char outputtext_1[8]; /* PT/CT[j-1] */
555 unsigned char outputtext_2[8]; /* PT/CT[j-2] */
556 char buf[80]; /* holds one line from the input REQUEST file. */
557 unsigned int outputlen;
558 unsigned char outputtext[8];
561 SECStatus rv;
563 if (mode == NSS_DES_EDE3 && iv != NULL) {
564 printf("IV must be NULL for NSS_DES_EDE3 mode");
565 goto loser;
566 } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) {
567 printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
568 goto loser;
571 /* loop 400 times */
572 for (i=0; i<400; i++) {
573 /* if i == 0 CV[0] = IV not necessary */
574 /* record the count and key values and plainText */
575 sprintf(buf, "COUNT = %d\n", i);
576 fputs(buf, resp);
577 /* Output KEY1[i] */
578 fputs("KEY1 = ", resp);
579 to_hex_str(buf, key, 8);
580 fputs(buf, resp);
581 fputc('\n', resp);
582 /* Output KEY2[i] */
583 fputs("KEY2 = ", resp);
584 to_hex_str(buf, &key[8], 8);
585 fputs(buf, resp);
586 fputc('\n', resp);
587 /* Output KEY3[i] */
588 fputs("KEY3 = ", resp);
589 to_hex_str(buf, &key[16], 8);
590 fputs(buf, resp);
591 fputc('\n', resp);
592 if (mode == NSS_DES_EDE3_CBC) {
593 /* Output CV[i] */
594 fputs("IV = ", resp);
595 to_hex_str(buf, iv, 8);
596 fputs(buf, resp);
597 fputc('\n', resp);
599 if (crypt == ENCRYPT) {
600 /* Output PT[0] */
601 fputs("PLAINTEXT = ", resp);
602 } else {
603 /* Output CT[0] */
604 fputs("CIPHERTEXT = ", resp);
607 to_hex_str(buf, inputtext, inputlength);
608 fputs(buf, resp);
609 fputc('\n', resp);
611 /* loop 10,000 times */
612 for (j=0; j<10000; j++) {
614 outputlen = 0;
615 if (crypt == ENCRYPT) {
616 /* inputtext == ciphertext outputtext == plaintext*/
617 rv = tdea_encrypt_buf(mode, key,
618 (mode == NSS_DES_EDE3) ? NULL : iv,
619 outputtext, &outputlen, 8,
620 inputtext, 8);
621 } else {
622 /* inputtext == plaintext outputtext == ciphertext */
623 rv = tdea_decrypt_buf(mode, key,
624 (mode == NSS_DES_EDE3) ? NULL : iv,
625 outputtext, &outputlen, 8,
626 inputtext, 8);
629 if (rv != SECSuccess) {
630 goto loser;
632 if (outputlen != inputlength) {
633 goto loser;
636 if (mode == NSS_DES_EDE3_CBC) {
637 if (crypt == ENCRYPT) {
638 if (j == 0) {
639 /*P[j+1] = CV[0] */
640 memcpy(inputtext, iv, 8);
641 } else {
642 /* p[j+1] = C[j-1] */
643 memcpy(inputtext, outputtext_1, 8);
645 /* CV[j+1] = C[j] */
646 memcpy(iv, outputtext, 8);
647 if (j != 9999) {
648 /* save C[j-1] */
649 memcpy(outputtext_1, outputtext, 8);
651 } else { /* DECRYPT */
652 /* CV[j+1] = C[j] */
653 memcpy(iv, inputtext, 8);
654 /* C[j+1] = P[j] */
655 memcpy(inputtext, outputtext, 8);
657 } else {
658 /* ECB mode PT/CT[j+1] = CT/PT[j] */
659 memcpy(inputtext, outputtext, 8);
662 /* Save PT/CT[j-2] and PT/CT[j-1] */
663 if (j==9997) memcpy(outputtext_2, outputtext, 8);
664 if (j==9998) memcpy(outputtext_1, outputtext, 8);
665 /* done at the end of the for(j) loop */
669 if (crypt == ENCRYPT) {
670 /* Output CT[j] */
671 fputs("CIPHERTEXT = ", resp);
672 } else {
673 /* Output PT[j] */
674 fputs("PLAINTEXT = ", resp);
676 to_hex_str(buf, outputtext, 8);
677 fputs(buf, resp);
678 fputc('\n', resp);
680 /* Key[i+1] = Key[i] xor ... outputtext_2 == PT/CT[j-2]
681 * outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j]
683 tdea_mct_next_keys(key, outputtext_2,
684 outputtext_1, outputtext, numKeys);
686 if (mode == NSS_DES_EDE3_CBC) {
687 /* taken care of in the j=9999 iteration */
688 if (crypt == ENCRYPT) {
689 /* P[i] = C[j-1] */
690 /* CV[i] = C[j] */
691 } else {
692 /* taken care of in the j=9999 iteration */
693 /* CV[i] = C[j] */
694 /* C[i] = P[j] */
696 } else {
697 /* ECB PT/CT[i] = PT/CT[j] */
698 memcpy(inputtext, outputtext, 8);
700 /* done at the end of the for(i) loop */
701 fputc('\n', resp);
704 loser:
705 return;
709 * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
710 * by gathering the input from the request file, and then
711 * calling tdea_mct_test.
713 * reqfn is the pathname of the input REQUEST file.
715 * The output RESPONSE file is written to stdout.
717 void
718 tdea_mct(int mode, char *reqfn)
720 int i, j;
721 char buf[80]; /* holds one line from the input REQUEST file. */
722 FILE *req; /* input stream from the REQUEST file */
723 FILE *resp; /* output stream to the RESPONSE file */
724 unsigned int crypt = 0; /* 1 means encrypt, 0 means decrypt */
725 unsigned char key[24]; /* TDEA 3 key bundle */
726 unsigned int numKeys = 0;
727 unsigned char plaintext[8]; /* PT[j] */
728 unsigned char ciphertext[8]; /* CT[j] */
729 unsigned char iv[8];
731 /* zeroize the variables for the test with this data set */
732 memset(key, 0, sizeof key);
733 memset(plaintext, 0, sizeof plaintext);
734 memset(ciphertext, 0, sizeof ciphertext);
735 memset(iv, 0, sizeof iv);
737 req = fopen(reqfn, "r");
738 resp = stdout;
739 while (fgets(buf, sizeof buf, req) != NULL) {
740 /* a comment or blank line */
741 if (buf[0] == '#' || buf[0] == '\n') {
742 fputs(buf, resp);
743 continue;
745 /* [ENCRYPT] or [DECRYPT] */
746 if (buf[0] == '[') {
747 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
748 crypt = ENCRYPT;
749 } else {
750 crypt = DECRYPT;
752 fputs(buf, resp);
753 continue;
755 /* NumKeys */
756 if (strncmp(&buf[0], "NumKeys", 7) == 0) {
757 i = 7;
758 while (isspace(buf[i]) || buf[i] == '=') {
759 i++;
761 numKeys = atoi(&buf[i]);
762 continue;
764 /* KEY1 = ... */
765 if (strncmp(buf, "KEY1", 4) == 0) {
766 i = 4;
767 while (isspace(buf[i]) || buf[i] == '=') {
768 i++;
770 for (j=0; isxdigit(buf[i]); i+=2,j++) {
771 hex_to_byteval(&buf[i], &key[j]);
773 continue;
775 /* KEY2 = ... */
776 if (strncmp(buf, "KEY2", 4) == 0) {
777 i = 4;
778 while (isspace(buf[i]) || buf[i] == '=') {
779 i++;
781 for (j=8; isxdigit(buf[i]); i+=2,j++) {
782 hex_to_byteval(&buf[i], &key[j]);
784 continue;
786 /* KEY3 = ... */
787 if (strncmp(buf, "KEY3", 4) == 0) {
788 i = 4;
789 while (isspace(buf[i]) || buf[i] == '=') {
790 i++;
792 for (j=16; isxdigit(buf[i]); i+=2,j++) {
793 hex_to_byteval(&buf[i], &key[j]);
795 continue;
798 /* IV = ... */
799 if (strncmp(buf, "IV", 2) == 0) {
800 i = 2;
801 while (isspace(buf[i]) || buf[i] == '=') {
802 i++;
804 for (j=0; j<sizeof iv; i+=2,j++) {
805 hex_to_byteval(&buf[i], &iv[j]);
807 continue;
810 /* PLAINTEXT = ... */
811 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
813 /* sanity check */
814 if (crypt != ENCRYPT) {
815 goto loser;
817 /* PT[0] = PT */
818 i = 9;
819 while (isspace(buf[i]) || buf[i] == '=') {
820 i++;
822 for (j=0; j<sizeof plaintext; i+=2,j++) {
823 hex_to_byteval(&buf[i], &plaintext[j]);
826 /* do the Monte Carlo test */
827 if (mode==NSS_DES_EDE3) {
828 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp);
829 } else {
830 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp);
832 continue;
834 /* CIPHERTEXT = ... */
835 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
836 /* sanity check */
837 if (crypt != DECRYPT) {
838 goto loser;
840 /* CT[0] = CT */
841 i = 10;
842 while (isspace(buf[i]) || buf[i] == '=') {
843 i++;
845 for (j=0; isxdigit(buf[i]); i+=2,j++) {
846 hex_to_byteval(&buf[i], &ciphertext[j]);
849 /* do the Monte Carlo test */
850 if (mode==NSS_DES_EDE3) {
851 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp);
852 } else {
853 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp);
855 continue;
859 loser:
860 fclose(req);
864 SECStatus
865 aes_encrypt_buf(
866 int mode,
867 const unsigned char *key, unsigned int keysize,
868 const unsigned char *iv,
869 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
870 const unsigned char *input, unsigned int inputlen)
872 SECStatus rv = SECFailure;
873 AESContext *cx;
874 unsigned char doublecheck[10*16]; /* 1 to 10 blocks */
875 unsigned int doublechecklen = 0;
877 cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
878 if (cx == NULL) {
879 goto loser;
881 rv = AES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
882 if (rv != SECSuccess) {
883 goto loser;
885 if (*outputlen != inputlen) {
886 goto loser;
888 AES_DestroyContext(cx, PR_TRUE);
889 cx = NULL;
892 * Doublecheck our result by decrypting the ciphertext and
893 * compare the output with the input plaintext.
895 cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
896 if (cx == NULL) {
897 goto loser;
899 rv = AES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
900 output, *outputlen);
901 if (rv != SECSuccess) {
902 goto loser;
904 if (doublechecklen != *outputlen) {
905 goto loser;
907 AES_DestroyContext(cx, PR_TRUE);
908 cx = NULL;
909 if (memcmp(doublecheck, input, inputlen) != 0) {
910 goto loser;
912 rv = SECSuccess;
914 loser:
915 if (cx != NULL) {
916 AES_DestroyContext(cx, PR_TRUE);
918 return rv;
921 SECStatus
922 aes_decrypt_buf(
923 int mode,
924 const unsigned char *key, unsigned int keysize,
925 const unsigned char *iv,
926 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
927 const unsigned char *input, unsigned int inputlen)
929 SECStatus rv = SECFailure;
930 AESContext *cx;
931 unsigned char doublecheck[10*16]; /* 1 to 10 blocks */
932 unsigned int doublechecklen = 0;
934 cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
935 if (cx == NULL) {
936 goto loser;
938 rv = AES_Decrypt(cx, output, outputlen, maxoutputlen,
939 input, inputlen);
940 if (rv != SECSuccess) {
941 goto loser;
943 if (*outputlen != inputlen) {
944 goto loser;
946 AES_DestroyContext(cx, PR_TRUE);
947 cx = NULL;
950 * Doublecheck our result by encrypting the plaintext and
951 * compare the output with the input ciphertext.
953 cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
954 if (cx == NULL) {
955 goto loser;
957 rv = AES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
958 output, *outputlen);
959 if (rv != SECSuccess) {
960 goto loser;
962 if (doublechecklen != *outputlen) {
963 goto loser;
965 AES_DestroyContext(cx, PR_TRUE);
966 cx = NULL;
967 if (memcmp(doublecheck, input, inputlen) != 0) {
968 goto loser;
970 rv = SECSuccess;
972 loser:
973 if (cx != NULL) {
974 AES_DestroyContext(cx, PR_TRUE);
976 return rv;
980 * Perform the AES Known Answer Test (KAT) or Multi-block Message
981 * Test (MMT) in ECB or CBC mode. The KAT (there are four types)
982 * and MMT have the same structure: given the key and IV (CBC mode
983 * only), encrypt the given plaintext or decrypt the given ciphertext.
984 * So we can handle them the same way.
986 * reqfn is the pathname of the REQUEST file.
988 * The output RESPONSE file is written to stdout.
990 void
991 aes_kat_mmt(char *reqfn)
993 char buf[512]; /* holds one line from the input REQUEST file.
994 * needs to be large enough to hold the longest
995 * line "CIPHERTEXT = <320 hex digits>\n".
997 FILE *aesreq; /* input stream from the REQUEST file */
998 FILE *aesresp; /* output stream to the RESPONSE file */
999 int i, j;
1000 int mode; /* NSS_AES (ECB) or NSS_AES_CBC */
1001 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
1002 unsigned char key[32]; /* 128, 192, or 256 bits */
1003 unsigned int keysize;
1004 unsigned char iv[16]; /* for all modes except ECB */
1005 unsigned char plaintext[10*16]; /* 1 to 10 blocks */
1006 unsigned int plaintextlen;
1007 unsigned char ciphertext[10*16]; /* 1 to 10 blocks */
1008 unsigned int ciphertextlen;
1009 SECStatus rv;
1011 aesreq = fopen(reqfn, "r");
1012 aesresp = stdout;
1013 while (fgets(buf, sizeof buf, aesreq) != NULL) {
1014 /* a comment or blank line */
1015 if (buf[0] == '#' || buf[0] == '\n') {
1016 fputs(buf, aesresp);
1017 continue;
1019 /* [ENCRYPT] or [DECRYPT] */
1020 if (buf[0] == '[') {
1021 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1022 encrypt = 1;
1023 } else {
1024 encrypt = 0;
1026 fputs(buf, aesresp);
1027 continue;
1029 /* "COUNT = x" begins a new data set */
1030 if (strncmp(buf, "COUNT", 5) == 0) {
1031 mode = NSS_AES;
1032 /* zeroize the variables for the test with this data set */
1033 memset(key, 0, sizeof key);
1034 keysize = 0;
1035 memset(iv, 0, sizeof iv);
1036 memset(plaintext, 0, sizeof plaintext);
1037 plaintextlen = 0;
1038 memset(ciphertext, 0, sizeof ciphertext);
1039 ciphertextlen = 0;
1040 fputs(buf, aesresp);
1041 continue;
1043 /* KEY = ... */
1044 if (strncmp(buf, "KEY", 3) == 0) {
1045 i = 3;
1046 while (isspace(buf[i]) || buf[i] == '=') {
1047 i++;
1049 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1050 hex_to_byteval(&buf[i], &key[j]);
1052 keysize = j;
1053 fputs(buf, aesresp);
1054 continue;
1056 /* IV = ... */
1057 if (strncmp(buf, "IV", 2) == 0) {
1058 mode = NSS_AES_CBC;
1059 i = 2;
1060 while (isspace(buf[i]) || buf[i] == '=') {
1061 i++;
1063 for (j=0; j<sizeof iv; i+=2,j++) {
1064 hex_to_byteval(&buf[i], &iv[j]);
1066 fputs(buf, aesresp);
1067 continue;
1069 /* PLAINTEXT = ... */
1070 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1071 /* sanity check */
1072 if (!encrypt) {
1073 goto loser;
1076 i = 9;
1077 while (isspace(buf[i]) || buf[i] == '=') {
1078 i++;
1080 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1081 hex_to_byteval(&buf[i], &plaintext[j]);
1083 plaintextlen = j;
1085 rv = aes_encrypt_buf(mode, key, keysize,
1086 (mode == NSS_AES) ? NULL : iv,
1087 ciphertext, &ciphertextlen, sizeof ciphertext,
1088 plaintext, plaintextlen);
1089 if (rv != SECSuccess) {
1090 goto loser;
1093 fputs(buf, aesresp);
1094 fputs("CIPHERTEXT = ", aesresp);
1095 to_hex_str(buf, ciphertext, ciphertextlen);
1096 fputs(buf, aesresp);
1097 fputc('\n', aesresp);
1098 continue;
1100 /* CIPHERTEXT = ... */
1101 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1102 /* sanity check */
1103 if (encrypt) {
1104 goto loser;
1107 i = 10;
1108 while (isspace(buf[i]) || buf[i] == '=') {
1109 i++;
1111 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1112 hex_to_byteval(&buf[i], &ciphertext[j]);
1114 ciphertextlen = j;
1116 rv = aes_decrypt_buf(mode, key, keysize,
1117 (mode == NSS_AES) ? NULL : iv,
1118 plaintext, &plaintextlen, sizeof plaintext,
1119 ciphertext, ciphertextlen);
1120 if (rv != SECSuccess) {
1121 goto loser;
1124 fputs(buf, aesresp);
1125 fputs("PLAINTEXT = ", aesresp);
1126 to_hex_str(buf, plaintext, plaintextlen);
1127 fputs(buf, aesresp);
1128 fputc('\n', aesresp);
1129 continue;
1132 loser:
1133 fclose(aesreq);
1137 * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
1138 * Test (MCT) in ECB and CBC modes.
1140 void
1141 aes_mct_next_key(unsigned char *key, unsigned int keysize,
1142 const unsigned char *ciphertext_1, const unsigned char *ciphertext)
1144 int k;
1146 switch (keysize) {
1147 case 16: /* 128-bit key */
1148 /* Key[i+1] = Key[i] xor CT[j] */
1149 for (k=0; k<16; k++) {
1150 key[k] ^= ciphertext[k];
1152 break;
1153 case 24: /* 192-bit key */
1155 * Key[i+1] = Key[i] xor (last 64-bits of
1156 * CT[j-1] || CT[j])
1158 for (k=0; k<8; k++) {
1159 key[k] ^= ciphertext_1[k+8];
1161 for (k=8; k<24; k++) {
1162 key[k] ^= ciphertext[k-8];
1164 break;
1165 case 32: /* 256-bit key */
1166 /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
1167 for (k=0; k<16; k++) {
1168 key[k] ^= ciphertext_1[k];
1170 for (k=16; k<32; k++) {
1171 key[k] ^= ciphertext[k-16];
1173 break;
1178 * Perform the AES Monte Carlo Test (MCT) in ECB mode. MCT exercises
1179 * our AES code in streaming mode because the plaintext or ciphertext
1180 * is generated block by block as we go, so we can't collect all the
1181 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1182 * one shot.
1184 * reqfn is the pathname of the input REQUEST file.
1186 * The output RESPONSE file is written to stdout.
1188 void
1189 aes_ecb_mct(char *reqfn)
1191 char buf[80]; /* holds one line from the input REQUEST file.
1192 * needs to be large enough to hold the longest
1193 * line "KEY = <64 hex digits>\n".
1195 FILE *aesreq; /* input stream from the REQUEST file */
1196 FILE *aesresp; /* output stream to the RESPONSE file */
1197 int i, j;
1198 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
1199 unsigned char key[32]; /* 128, 192, or 256 bits */
1200 unsigned int keysize;
1201 unsigned char plaintext[16]; /* PT[j] */
1202 unsigned char plaintext_1[16]; /* PT[j-1] */
1203 unsigned char ciphertext[16]; /* CT[j] */
1204 unsigned char ciphertext_1[16]; /* CT[j-1] */
1205 unsigned char doublecheck[16];
1206 unsigned int outputlen;
1207 AESContext *cx = NULL; /* the operation being tested */
1208 AESContext *cx2 = NULL; /* the inverse operation done in parallel
1209 * to doublecheck our result.
1211 SECStatus rv;
1213 aesreq = fopen(reqfn, "r");
1214 aesresp = stdout;
1215 while (fgets(buf, sizeof buf, aesreq) != NULL) {
1216 /* a comment or blank line */
1217 if (buf[0] == '#' || buf[0] == '\n') {
1218 fputs(buf, aesresp);
1219 continue;
1221 /* [ENCRYPT] or [DECRYPT] */
1222 if (buf[0] == '[') {
1223 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1224 encrypt = 1;
1225 } else {
1226 encrypt = 0;
1228 fputs(buf, aesresp);
1229 continue;
1231 /* "COUNT = x" begins a new data set */
1232 if (strncmp(buf, "COUNT", 5) == 0) {
1233 /* zeroize the variables for the test with this data set */
1234 memset(key, 0, sizeof key);
1235 keysize = 0;
1236 memset(plaintext, 0, sizeof plaintext);
1237 memset(ciphertext, 0, sizeof ciphertext);
1238 continue;
1240 /* KEY = ... */
1241 if (strncmp(buf, "KEY", 3) == 0) {
1242 /* Key[0] = Key */
1243 i = 3;
1244 while (isspace(buf[i]) || buf[i] == '=') {
1245 i++;
1247 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1248 hex_to_byteval(&buf[i], &key[j]);
1250 keysize = j;
1251 continue;
1253 /* PLAINTEXT = ... */
1254 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1255 /* sanity check */
1256 if (!encrypt) {
1257 goto loser;
1259 /* PT[0] = PT */
1260 i = 9;
1261 while (isspace(buf[i]) || buf[i] == '=') {
1262 i++;
1264 for (j=0; j<sizeof plaintext; i+=2,j++) {
1265 hex_to_byteval(&buf[i], &plaintext[j]);
1268 for (i=0; i<100; i++) {
1269 sprintf(buf, "COUNT = %d\n", i);
1270 fputs(buf, aesresp);
1271 /* Output Key[i] */
1272 fputs("KEY = ", aesresp);
1273 to_hex_str(buf, key, keysize);
1274 fputs(buf, aesresp);
1275 fputc('\n', aesresp);
1276 /* Output PT[0] */
1277 fputs("PLAINTEXT = ", aesresp);
1278 to_hex_str(buf, plaintext, sizeof plaintext);
1279 fputs(buf, aesresp);
1280 fputc('\n', aesresp);
1282 cx = AES_CreateContext(key, NULL, NSS_AES,
1283 PR_TRUE, keysize, 16);
1284 if (cx == NULL) {
1285 goto loser;
1288 * doublecheck our result by decrypting the result
1289 * and comparing the output with the plaintext.
1291 cx2 = AES_CreateContext(key, NULL, NSS_AES,
1292 PR_FALSE, keysize, 16);
1293 if (cx2 == NULL) {
1294 goto loser;
1296 for (j=0; j<1000; j++) {
1297 /* Save CT[j-1] */
1298 memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
1300 /* CT[j] = AES(Key[i], PT[j]) */
1301 outputlen = 0;
1302 rv = AES_Encrypt(cx,
1303 ciphertext, &outputlen, sizeof ciphertext,
1304 plaintext, sizeof plaintext);
1305 if (rv != SECSuccess) {
1306 goto loser;
1308 if (outputlen != sizeof plaintext) {
1309 goto loser;
1312 /* doublecheck our result */
1313 outputlen = 0;
1314 rv = AES_Decrypt(cx2,
1315 doublecheck, &outputlen, sizeof doublecheck,
1316 ciphertext, sizeof ciphertext);
1317 if (rv != SECSuccess) {
1318 goto loser;
1320 if (outputlen != sizeof ciphertext) {
1321 goto loser;
1323 if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
1324 goto loser;
1327 /* PT[j+1] = CT[j] */
1328 memcpy(plaintext, ciphertext, sizeof plaintext);
1330 AES_DestroyContext(cx, PR_TRUE);
1331 cx = NULL;
1332 AES_DestroyContext(cx2, PR_TRUE);
1333 cx2 = NULL;
1335 /* Output CT[j] */
1336 fputs("CIPHERTEXT = ", aesresp);
1337 to_hex_str(buf, ciphertext, sizeof ciphertext);
1338 fputs(buf, aesresp);
1339 fputc('\n', aesresp);
1341 /* Key[i+1] = Key[i] xor ... */
1342 aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
1343 /* PT[0] = CT[j] */
1344 /* done at the end of the for(j) loop */
1346 fputc('\n', aesresp);
1349 continue;
1351 /* CIPHERTEXT = ... */
1352 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1353 /* sanity check */
1354 if (encrypt) {
1355 goto loser;
1357 /* CT[0] = CT */
1358 i = 10;
1359 while (isspace(buf[i]) || buf[i] == '=') {
1360 i++;
1362 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1363 hex_to_byteval(&buf[i], &ciphertext[j]);
1366 for (i=0; i<100; i++) {
1367 sprintf(buf, "COUNT = %d\n", i);
1368 fputs(buf, aesresp);
1369 /* Output Key[i] */
1370 fputs("KEY = ", aesresp);
1371 to_hex_str(buf, key, keysize);
1372 fputs(buf, aesresp);
1373 fputc('\n', aesresp);
1374 /* Output CT[0] */
1375 fputs("CIPHERTEXT = ", aesresp);
1376 to_hex_str(buf, ciphertext, sizeof ciphertext);
1377 fputs(buf, aesresp);
1378 fputc('\n', aesresp);
1380 cx = AES_CreateContext(key, NULL, NSS_AES,
1381 PR_FALSE, keysize, 16);
1382 if (cx == NULL) {
1383 goto loser;
1386 * doublecheck our result by encrypting the result
1387 * and comparing the output with the ciphertext.
1389 cx2 = AES_CreateContext(key, NULL, NSS_AES,
1390 PR_TRUE, keysize, 16);
1391 if (cx2 == NULL) {
1392 goto loser;
1394 for (j=0; j<1000; j++) {
1395 /* Save PT[j-1] */
1396 memcpy(plaintext_1, plaintext, sizeof plaintext);
1398 /* PT[j] = AES(Key[i], CT[j]) */
1399 outputlen = 0;
1400 rv = AES_Decrypt(cx,
1401 plaintext, &outputlen, sizeof plaintext,
1402 ciphertext, sizeof ciphertext);
1403 if (rv != SECSuccess) {
1404 goto loser;
1406 if (outputlen != sizeof ciphertext) {
1407 goto loser;
1410 /* doublecheck our result */
1411 outputlen = 0;
1412 rv = AES_Encrypt(cx2,
1413 doublecheck, &outputlen, sizeof doublecheck,
1414 plaintext, sizeof plaintext);
1415 if (rv != SECSuccess) {
1416 goto loser;
1418 if (outputlen != sizeof plaintext) {
1419 goto loser;
1421 if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
1422 goto loser;
1425 /* CT[j+1] = PT[j] */
1426 memcpy(ciphertext, plaintext, sizeof ciphertext);
1428 AES_DestroyContext(cx, PR_TRUE);
1429 cx = NULL;
1430 AES_DestroyContext(cx2, PR_TRUE);
1431 cx2 = NULL;
1433 /* Output PT[j] */
1434 fputs("PLAINTEXT = ", aesresp);
1435 to_hex_str(buf, plaintext, sizeof plaintext);
1436 fputs(buf, aesresp);
1437 fputc('\n', aesresp);
1439 /* Key[i+1] = Key[i] xor ... */
1440 aes_mct_next_key(key, keysize, plaintext_1, plaintext);
1441 /* CT[0] = PT[j] */
1442 /* done at the end of the for(j) loop */
1444 fputc('\n', aesresp);
1447 continue;
1450 loser:
1451 if (cx != NULL) {
1452 AES_DestroyContext(cx, PR_TRUE);
1454 if (cx2 != NULL) {
1455 AES_DestroyContext(cx2, PR_TRUE);
1457 fclose(aesreq);
1461 * Perform the AES Monte Carlo Test (MCT) in CBC mode. MCT exercises
1462 * our AES code in streaming mode because the plaintext or ciphertext
1463 * is generated block by block as we go, so we can't collect all the
1464 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1465 * one shot.
1467 * reqfn is the pathname of the input REQUEST file.
1469 * The output RESPONSE file is written to stdout.
1471 void
1472 aes_cbc_mct(char *reqfn)
1474 char buf[80]; /* holds one line from the input REQUEST file.
1475 * needs to be large enough to hold the longest
1476 * line "KEY = <64 hex digits>\n".
1478 FILE *aesreq; /* input stream from the REQUEST file */
1479 FILE *aesresp; /* output stream to the RESPONSE file */
1480 int i, j;
1481 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
1482 unsigned char key[32]; /* 128, 192, or 256 bits */
1483 unsigned int keysize;
1484 unsigned char iv[16];
1485 unsigned char plaintext[16]; /* PT[j] */
1486 unsigned char plaintext_1[16]; /* PT[j-1] */
1487 unsigned char ciphertext[16]; /* CT[j] */
1488 unsigned char ciphertext_1[16]; /* CT[j-1] */
1489 unsigned char doublecheck[16];
1490 unsigned int outputlen;
1491 AESContext *cx = NULL; /* the operation being tested */
1492 AESContext *cx2 = NULL; /* the inverse operation done in parallel
1493 * to doublecheck our result.
1495 SECStatus rv;
1497 aesreq = fopen(reqfn, "r");
1498 aesresp = stdout;
1499 while (fgets(buf, sizeof buf, aesreq) != NULL) {
1500 /* a comment or blank line */
1501 if (buf[0] == '#' || buf[0] == '\n') {
1502 fputs(buf, aesresp);
1503 continue;
1505 /* [ENCRYPT] or [DECRYPT] */
1506 if (buf[0] == '[') {
1507 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1508 encrypt = 1;
1509 } else {
1510 encrypt = 0;
1512 fputs(buf, aesresp);
1513 continue;
1515 /* "COUNT = x" begins a new data set */
1516 if (strncmp(buf, "COUNT", 5) == 0) {
1517 /* zeroize the variables for the test with this data set */
1518 memset(key, 0, sizeof key);
1519 keysize = 0;
1520 memset(iv, 0, sizeof iv);
1521 memset(plaintext, 0, sizeof plaintext);
1522 memset(ciphertext, 0, sizeof ciphertext);
1523 continue;
1525 /* KEY = ... */
1526 if (strncmp(buf, "KEY", 3) == 0) {
1527 /* Key[0] = Key */
1528 i = 3;
1529 while (isspace(buf[i]) || buf[i] == '=') {
1530 i++;
1532 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1533 hex_to_byteval(&buf[i], &key[j]);
1535 keysize = j;
1536 continue;
1538 /* IV = ... */
1539 if (strncmp(buf, "IV", 2) == 0) {
1540 /* IV[0] = IV */
1541 i = 2;
1542 while (isspace(buf[i]) || buf[i] == '=') {
1543 i++;
1545 for (j=0; j<sizeof iv; i+=2,j++) {
1546 hex_to_byteval(&buf[i], &iv[j]);
1548 continue;
1550 /* PLAINTEXT = ... */
1551 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1552 /* sanity check */
1553 if (!encrypt) {
1554 goto loser;
1556 /* PT[0] = PT */
1557 i = 9;
1558 while (isspace(buf[i]) || buf[i] == '=') {
1559 i++;
1561 for (j=0; j<sizeof plaintext; i+=2,j++) {
1562 hex_to_byteval(&buf[i], &plaintext[j]);
1565 for (i=0; i<100; i++) {
1566 sprintf(buf, "COUNT = %d\n", i);
1567 fputs(buf, aesresp);
1568 /* Output Key[i] */
1569 fputs("KEY = ", aesresp);
1570 to_hex_str(buf, key, keysize);
1571 fputs(buf, aesresp);
1572 fputc('\n', aesresp);
1573 /* Output IV[i] */
1574 fputs("IV = ", aesresp);
1575 to_hex_str(buf, iv, sizeof iv);
1576 fputs(buf, aesresp);
1577 fputc('\n', aesresp);
1578 /* Output PT[0] */
1579 fputs("PLAINTEXT = ", aesresp);
1580 to_hex_str(buf, plaintext, sizeof plaintext);
1581 fputs(buf, aesresp);
1582 fputc('\n', aesresp);
1584 cx = AES_CreateContext(key, iv, NSS_AES_CBC,
1585 PR_TRUE, keysize, 16);
1586 if (cx == NULL) {
1587 goto loser;
1590 * doublecheck our result by decrypting the result
1591 * and comparing the output with the plaintext.
1593 cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
1594 PR_FALSE, keysize, 16);
1595 if (cx2 == NULL) {
1596 goto loser;
1598 /* CT[-1] = IV[i] */
1599 memcpy(ciphertext, iv, sizeof ciphertext);
1600 for (j=0; j<1000; j++) {
1601 /* Save CT[j-1] */
1602 memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
1604 * If ( j=0 )
1605 * CT[j] = AES(Key[i], IV[i], PT[j])
1606 * PT[j+1] = IV[i] (= CT[j-1])
1607 * Else
1608 * CT[j] = AES(Key[i], PT[j])
1609 * PT[j+1] = CT[j-1]
1611 outputlen = 0;
1612 rv = AES_Encrypt(cx,
1613 ciphertext, &outputlen, sizeof ciphertext,
1614 plaintext, sizeof plaintext);
1615 if (rv != SECSuccess) {
1616 goto loser;
1618 if (outputlen != sizeof plaintext) {
1619 goto loser;
1622 /* doublecheck our result */
1623 outputlen = 0;
1624 rv = AES_Decrypt(cx2,
1625 doublecheck, &outputlen, sizeof doublecheck,
1626 ciphertext, sizeof ciphertext);
1627 if (rv != SECSuccess) {
1628 goto loser;
1630 if (outputlen != sizeof ciphertext) {
1631 goto loser;
1633 if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
1634 goto loser;
1637 memcpy(plaintext, ciphertext_1, sizeof plaintext);
1639 AES_DestroyContext(cx, PR_TRUE);
1640 cx = NULL;
1641 AES_DestroyContext(cx2, PR_TRUE);
1642 cx2 = NULL;
1644 /* Output CT[j] */
1645 fputs("CIPHERTEXT = ", aesresp);
1646 to_hex_str(buf, ciphertext, sizeof ciphertext);
1647 fputs(buf, aesresp);
1648 fputc('\n', aesresp);
1650 /* Key[i+1] = Key[i] xor ... */
1651 aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
1652 /* IV[i+1] = CT[j] */
1653 memcpy(iv, ciphertext, sizeof iv);
1654 /* PT[0] = CT[j-1] */
1655 /* done at the end of the for(j) loop */
1657 fputc('\n', aesresp);
1660 continue;
1662 /* CIPHERTEXT = ... */
1663 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1664 /* sanity check */
1665 if (encrypt) {
1666 goto loser;
1668 /* CT[0] = CT */
1669 i = 10;
1670 while (isspace(buf[i]) || buf[i] == '=') {
1671 i++;
1673 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1674 hex_to_byteval(&buf[i], &ciphertext[j]);
1677 for (i=0; i<100; i++) {
1678 sprintf(buf, "COUNT = %d\n", i);
1679 fputs(buf, aesresp);
1680 /* Output Key[i] */
1681 fputs("KEY = ", aesresp);
1682 to_hex_str(buf, key, keysize);
1683 fputs(buf, aesresp);
1684 fputc('\n', aesresp);
1685 /* Output IV[i] */
1686 fputs("IV = ", aesresp);
1687 to_hex_str(buf, iv, sizeof iv);
1688 fputs(buf, aesresp);
1689 fputc('\n', aesresp);
1690 /* Output CT[0] */
1691 fputs("CIPHERTEXT = ", aesresp);
1692 to_hex_str(buf, ciphertext, sizeof ciphertext);
1693 fputs(buf, aesresp);
1694 fputc('\n', aesresp);
1696 cx = AES_CreateContext(key, iv, NSS_AES_CBC,
1697 PR_FALSE, keysize, 16);
1698 if (cx == NULL) {
1699 goto loser;
1702 * doublecheck our result by encrypting the result
1703 * and comparing the output with the ciphertext.
1705 cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
1706 PR_TRUE, keysize, 16);
1707 if (cx2 == NULL) {
1708 goto loser;
1710 /* PT[-1] = IV[i] */
1711 memcpy(plaintext, iv, sizeof plaintext);
1712 for (j=0; j<1000; j++) {
1713 /* Save PT[j-1] */
1714 memcpy(plaintext_1, plaintext, sizeof plaintext);
1716 * If ( j=0 )
1717 * PT[j] = AES(Key[i], IV[i], CT[j])
1718 * CT[j+1] = IV[i] (= PT[j-1])
1719 * Else
1720 * PT[j] = AES(Key[i], CT[j])
1721 * CT[j+1] = PT[j-1]
1723 outputlen = 0;
1724 rv = AES_Decrypt(cx,
1725 plaintext, &outputlen, sizeof plaintext,
1726 ciphertext, sizeof ciphertext);
1727 if (rv != SECSuccess) {
1728 goto loser;
1730 if (outputlen != sizeof ciphertext) {
1731 goto loser;
1734 /* doublecheck our result */
1735 outputlen = 0;
1736 rv = AES_Encrypt(cx2,
1737 doublecheck, &outputlen, sizeof doublecheck,
1738 plaintext, sizeof plaintext);
1739 if (rv != SECSuccess) {
1740 goto loser;
1742 if (outputlen != sizeof plaintext) {
1743 goto loser;
1745 if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
1746 goto loser;
1749 memcpy(ciphertext, plaintext_1, sizeof ciphertext);
1751 AES_DestroyContext(cx, PR_TRUE);
1752 cx = NULL;
1753 AES_DestroyContext(cx2, PR_TRUE);
1754 cx2 = NULL;
1756 /* Output PT[j] */
1757 fputs("PLAINTEXT = ", aesresp);
1758 to_hex_str(buf, plaintext, sizeof plaintext);
1759 fputs(buf, aesresp);
1760 fputc('\n', aesresp);
1762 /* Key[i+1] = Key[i] xor ... */
1763 aes_mct_next_key(key, keysize, plaintext_1, plaintext);
1764 /* IV[i+1] = PT[j] */
1765 memcpy(iv, plaintext, sizeof iv);
1766 /* CT[0] = PT[j-1] */
1767 /* done at the end of the for(j) loop */
1769 fputc('\n', aesresp);
1772 continue;
1775 loser:
1776 if (cx != NULL) {
1777 AES_DestroyContext(cx, PR_TRUE);
1779 if (cx2 != NULL) {
1780 AES_DestroyContext(cx2, PR_TRUE);
1782 fclose(aesreq);
1785 void write_compact_string(FILE *out, unsigned char *hash, unsigned int len)
1787 unsigned int i;
1788 int j, count = 0, last = -1, z = 0;
1789 long start = ftell(out);
1790 for (i=0; i<len; i++) {
1791 for (j=7; j>=0; j--) {
1792 if (last < 0) {
1793 last = (hash[i] & (1 << j)) ? 1 : 0;
1794 fprintf(out, "%d ", last);
1795 count = 1;
1796 } else if (hash[i] & (1 << j)) {
1797 if (last) {
1798 count++;
1799 } else {
1800 last = 0;
1801 fprintf(out, "%d ", count);
1802 count = 1;
1803 z++;
1805 } else {
1806 if (!last) {
1807 count++;
1808 } else {
1809 last = 1;
1810 fprintf(out, "%d ", count);
1811 count = 1;
1812 z++;
1817 fprintf(out, "^\n");
1818 fseek(out, start, SEEK_SET);
1819 fprintf(out, "%d ", z);
1820 fseek(out, 0, SEEK_END);
1823 int get_next_line(FILE *req, char *key, char *val, FILE *rsp)
1825 int ignore = 0;
1826 char *writeto = key;
1827 int w = 0;
1828 int c;
1829 while ((c = fgetc(req)) != EOF) {
1830 if (ignore) {
1831 fprintf(rsp, "%c", c);
1832 if (c == '\n') return ignore;
1833 } else if (c == '\n') {
1834 break;
1835 } else if (c == '#') {
1836 ignore = 1;
1837 fprintf(rsp, "%c", c);
1838 } else if (c == '=') {
1839 writeto[w] = '\0';
1840 w = 0;
1841 writeto = val;
1842 } else if (c == ' ' || c == '[' || c == ']') {
1843 continue;
1844 } else {
1845 writeto[w++] = c;
1848 writeto[w] = '\0';
1849 return (c == EOF) ? -1 : ignore;
1852 #ifndef NSS_DISABLE_ECC
1853 typedef struct curveNameTagPairStr {
1854 char *curveName;
1855 SECOidTag curveOidTag;
1856 } CurveNameTagPair;
1858 #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
1859 /* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */
1861 static CurveNameTagPair nameTagPair[] =
1863 { "sect163k1", SEC_OID_SECG_EC_SECT163K1},
1864 { "nistk163", SEC_OID_SECG_EC_SECT163K1},
1865 { "sect163r1", SEC_OID_SECG_EC_SECT163R1},
1866 { "sect163r2", SEC_OID_SECG_EC_SECT163R2},
1867 { "nistb163", SEC_OID_SECG_EC_SECT163R2},
1868 { "sect193r1", SEC_OID_SECG_EC_SECT193R1},
1869 { "sect193r2", SEC_OID_SECG_EC_SECT193R2},
1870 { "sect233k1", SEC_OID_SECG_EC_SECT233K1},
1871 { "nistk233", SEC_OID_SECG_EC_SECT233K1},
1872 { "sect233r1", SEC_OID_SECG_EC_SECT233R1},
1873 { "nistb233", SEC_OID_SECG_EC_SECT233R1},
1874 { "sect239k1", SEC_OID_SECG_EC_SECT239K1},
1875 { "sect283k1", SEC_OID_SECG_EC_SECT283K1},
1876 { "nistk283", SEC_OID_SECG_EC_SECT283K1},
1877 { "sect283r1", SEC_OID_SECG_EC_SECT283R1},
1878 { "nistb283", SEC_OID_SECG_EC_SECT283R1},
1879 { "sect409k1", SEC_OID_SECG_EC_SECT409K1},
1880 { "nistk409", SEC_OID_SECG_EC_SECT409K1},
1881 { "sect409r1", SEC_OID_SECG_EC_SECT409R1},
1882 { "nistb409", SEC_OID_SECG_EC_SECT409R1},
1883 { "sect571k1", SEC_OID_SECG_EC_SECT571K1},
1884 { "nistk571", SEC_OID_SECG_EC_SECT571K1},
1885 { "sect571r1", SEC_OID_SECG_EC_SECT571R1},
1886 { "nistb571", SEC_OID_SECG_EC_SECT571R1},
1887 { "secp160k1", SEC_OID_SECG_EC_SECP160K1},
1888 { "secp160r1", SEC_OID_SECG_EC_SECP160R1},
1889 { "secp160r2", SEC_OID_SECG_EC_SECP160R2},
1890 { "secp192k1", SEC_OID_SECG_EC_SECP192K1},
1891 { "secp192r1", SEC_OID_SECG_EC_SECP192R1},
1892 { "nistp192", SEC_OID_SECG_EC_SECP192R1},
1893 { "secp224k1", SEC_OID_SECG_EC_SECP224K1},
1894 { "secp224r1", SEC_OID_SECG_EC_SECP224R1},
1895 { "nistp224", SEC_OID_SECG_EC_SECP224R1},
1896 { "secp256k1", SEC_OID_SECG_EC_SECP256K1},
1897 { "secp256r1", SEC_OID_SECG_EC_SECP256R1},
1898 { "nistp256", SEC_OID_SECG_EC_SECP256R1},
1899 { "secp384r1", SEC_OID_SECG_EC_SECP384R1},
1900 { "nistp384", SEC_OID_SECG_EC_SECP384R1},
1901 { "secp521r1", SEC_OID_SECG_EC_SECP521R1},
1902 { "nistp521", SEC_OID_SECG_EC_SECP521R1},
1904 { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
1905 { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
1906 { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
1907 { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
1908 { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
1909 { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
1911 { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
1912 { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
1913 { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
1914 { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
1915 { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
1916 { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
1917 { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
1918 { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
1919 { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
1920 { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
1921 { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
1922 { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
1923 { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
1924 { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
1925 { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
1926 { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
1927 { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
1928 { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
1929 { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
1930 { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
1932 { "secp112r1", SEC_OID_SECG_EC_SECP112R1},
1933 { "secp112r2", SEC_OID_SECG_EC_SECP112R2},
1934 { "secp128r1", SEC_OID_SECG_EC_SECP128R1},
1935 { "secp128r2", SEC_OID_SECG_EC_SECP128R2},
1937 { "sect113r1", SEC_OID_SECG_EC_SECT113R1},
1938 { "sect113r2", SEC_OID_SECG_EC_SECT113R2},
1939 { "sect131r1", SEC_OID_SECG_EC_SECT131R1},
1940 { "sect131r2", SEC_OID_SECG_EC_SECT131R2},
1943 static SECItem *
1944 getECParams(const char *curve)
1946 SECItem *ecparams;
1947 SECOidData *oidData = NULL;
1948 SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
1949 int i, numCurves;
1951 if (curve != NULL) {
1952 numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair);
1953 for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN));
1954 i++) {
1955 if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
1956 curveOidTag = nameTagPair[i].curveOidTag;
1960 /* Return NULL if curve name is not recognized */
1961 if ((curveOidTag == SEC_OID_UNKNOWN) ||
1962 (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
1963 fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
1964 return NULL;
1967 ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
1970 * ecparams->data needs to contain the ASN encoding of an object ID (OID)
1971 * representing the named curve. The actual OID is in
1972 * oidData->oid.data so we simply prepend 0x06 and OID length
1974 ecparams->data[0] = SEC_ASN1_OBJECT_ID;
1975 ecparams->data[1] = oidData->oid.len;
1976 memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
1978 return ecparams;
1982 * Perform the ECDSA Key Pair Generation Test.
1984 * reqfn is the pathname of the REQUEST file.
1986 * The output RESPONSE file is written to stdout.
1988 void
1989 ecdsa_keypair_test(char *reqfn)
1991 char buf[256]; /* holds one line from the input REQUEST file
1992 * or to the output RESPONSE file.
1993 * needs to be large enough to hold the longest
1994 * line "Qx = <144 hex digits>\n".
1996 FILE *ecdsareq; /* input stream from the REQUEST file */
1997 FILE *ecdsaresp; /* output stream to the RESPONSE file */
1998 char curve[16]; /* "nistxddd" */
1999 ECParams *ecparams;
2000 int N;
2001 int i;
2002 unsigned int len;
2004 ecdsareq = fopen(reqfn, "r");
2005 ecdsaresp = stdout;
2006 strcpy(curve, "nist");
2007 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2008 /* a comment or blank line */
2009 if (buf[0] == '#' || buf[0] == '\n') {
2010 fputs(buf, ecdsaresp);
2011 continue;
2013 /* [X-ddd] */
2014 if (buf[0] == '[') {
2015 const char *src;
2016 char *dst;
2017 SECItem *encodedparams;
2019 src = &buf[1];
2020 dst = &curve[4];
2021 *dst++ = tolower(*src);
2022 src += 2; /* skip the hyphen */
2023 *dst++ = *src++;
2024 *dst++ = *src++;
2025 *dst++ = *src++;
2026 *dst = '\0';
2027 encodedparams = getECParams(curve);
2028 if (encodedparams == NULL) {
2029 goto loser;
2031 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2032 goto loser;
2034 SECITEM_FreeItem(encodedparams, PR_TRUE);
2035 fputs(buf, ecdsaresp);
2036 continue;
2038 /* N = x */
2039 if (buf[0] == 'N') {
2040 if (sscanf(buf, "N = %d", &N) != 1) {
2041 goto loser;
2043 for (i = 0; i < N; i++) {
2044 ECPrivateKey *ecpriv;
2046 if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
2047 goto loser;
2049 fputs("d = ", ecdsaresp);
2050 to_hex_str(buf, ecpriv->privateValue.data,
2051 ecpriv->privateValue.len);
2052 fputs(buf, ecdsaresp);
2053 fputc('\n', ecdsaresp);
2054 if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
2055 != SECSuccess) {
2056 goto loser;
2058 len = ecpriv->publicValue.len;
2059 if (len%2 == 0) {
2060 goto loser;
2062 len = (len-1)/2;
2063 if (ecpriv->publicValue.data[0]
2064 != EC_POINT_FORM_UNCOMPRESSED) {
2065 goto loser;
2067 fputs("Qx = ", ecdsaresp);
2068 to_hex_str(buf, &ecpriv->publicValue.data[1], len);
2069 fputs(buf, ecdsaresp);
2070 fputc('\n', ecdsaresp);
2071 fputs("Qy = ", ecdsaresp);
2072 to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
2073 fputs(buf, ecdsaresp);
2074 fputc('\n', ecdsaresp);
2075 fputc('\n', ecdsaresp);
2076 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
2078 PORT_FreeArena(ecparams->arena, PR_FALSE);
2079 continue;
2082 loser:
2083 fclose(ecdsareq);
2087 * Perform the ECDSA Public Key Validation Test.
2089 * reqfn is the pathname of the REQUEST file.
2091 * The output RESPONSE file is written to stdout.
2093 void
2094 ecdsa_pkv_test(char *reqfn)
2096 char buf[256]; /* holds one line from the input REQUEST file.
2097 * needs to be large enough to hold the longest
2098 * line "Qx = <144 hex digits>\n".
2100 FILE *ecdsareq; /* input stream from the REQUEST file */
2101 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2102 char curve[16]; /* "nistxddd" */
2103 ECParams *ecparams = NULL;
2104 SECItem pubkey;
2105 unsigned int i;
2106 unsigned int len;
2107 PRBool keyvalid = PR_TRUE;
2109 ecdsareq = fopen(reqfn, "r");
2110 ecdsaresp = stdout;
2111 strcpy(curve, "nist");
2112 pubkey.data = NULL;
2113 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2114 /* a comment or blank line */
2115 if (buf[0] == '#' || buf[0] == '\n') {
2116 fputs(buf, ecdsaresp);
2117 continue;
2119 /* [X-ddd] */
2120 if (buf[0] == '[') {
2121 const char *src;
2122 char *dst;
2123 SECItem *encodedparams;
2125 src = &buf[1];
2126 dst = &curve[4];
2127 *dst++ = tolower(*src);
2128 src += 2; /* skip the hyphen */
2129 *dst++ = *src++;
2130 *dst++ = *src++;
2131 *dst++ = *src++;
2132 *dst = '\0';
2133 if (ecparams != NULL) {
2134 PORT_FreeArena(ecparams->arena, PR_FALSE);
2135 ecparams = NULL;
2137 encodedparams = getECParams(curve);
2138 if (encodedparams == NULL) {
2139 goto loser;
2141 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2142 goto loser;
2144 SECITEM_FreeItem(encodedparams, PR_TRUE);
2145 len = (ecparams->fieldID.size + 7) >> 3;
2146 if (pubkey.data != NULL) {
2147 PORT_Free(pubkey.data);
2148 pubkey.data = NULL;
2150 SECITEM_AllocItem(NULL, &pubkey, 2*len+1);
2151 if (pubkey.data == NULL) {
2152 goto loser;
2154 pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
2155 fputs(buf, ecdsaresp);
2156 continue;
2158 /* Qx = ... */
2159 if (strncmp(buf, "Qx", 2) == 0) {
2160 fputs(buf, ecdsaresp);
2161 i = 2;
2162 while (isspace(buf[i]) || buf[i] == '=') {
2163 i++;
2165 keyvalid = from_hex_str(&pubkey.data[1], len, &buf[i]);
2166 continue;
2168 /* Qy = ... */
2169 if (strncmp(buf, "Qy", 2) == 0) {
2170 fputs(buf, ecdsaresp);
2171 if (!keyvalid) {
2172 fputs("Result = F\n", ecdsaresp);
2173 continue;
2175 i = 2;
2176 while (isspace(buf[i]) || buf[i] == '=') {
2177 i++;
2179 keyvalid = from_hex_str(&pubkey.data[1+len], len, &buf[i]);
2180 if (!keyvalid) {
2181 fputs("Result = F\n", ecdsaresp);
2182 continue;
2184 if (EC_ValidatePublicKey(ecparams, &pubkey) == SECSuccess) {
2185 fputs("Result = P\n", ecdsaresp);
2186 } else if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
2187 fputs("Result = F\n", ecdsaresp);
2188 } else {
2189 goto loser;
2191 continue;
2194 loser:
2195 if (ecparams != NULL) {
2196 PORT_FreeArena(ecparams->arena, PR_FALSE);
2198 if (pubkey.data != NULL) {
2199 PORT_Free(pubkey.data);
2201 fclose(ecdsareq);
2205 * Perform the ECDSA Signature Generation Test.
2207 * reqfn is the pathname of the REQUEST file.
2209 * The output RESPONSE file is written to stdout.
2211 void
2212 ecdsa_siggen_test(char *reqfn)
2214 char buf[1024]; /* holds one line from the input REQUEST file
2215 * or to the output RESPONSE file.
2216 * needs to be large enough to hold the longest
2217 * line "Msg = <256 hex digits>\n".
2219 FILE *ecdsareq; /* input stream from the REQUEST file */
2220 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2221 char curve[16]; /* "nistxddd" */
2222 ECParams *ecparams = NULL;
2223 int i, j;
2224 unsigned int len;
2225 unsigned char msg[512]; /* message to be signed (<= 128 bytes) */
2226 unsigned int msglen;
2227 unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
2228 unsigned char sig[2*MAX_ECKEY_LEN];
2229 SECItem signature, digest;
2231 ecdsareq = fopen(reqfn, "r");
2232 ecdsaresp = stdout;
2233 strcpy(curve, "nist");
2234 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2235 /* a comment or blank line */
2236 if (buf[0] == '#' || buf[0] == '\n') {
2237 fputs(buf, ecdsaresp);
2238 continue;
2240 /* [X-ddd] */
2241 if (buf[0] == '[') {
2242 const char *src;
2243 char *dst;
2244 SECItem *encodedparams;
2246 src = &buf[1];
2247 dst = &curve[4];
2248 *dst++ = tolower(*src);
2249 src += 2; /* skip the hyphen */
2250 *dst++ = *src++;
2251 *dst++ = *src++;
2252 *dst++ = *src++;
2253 *dst = '\0';
2254 if (ecparams != NULL) {
2255 PORT_FreeArena(ecparams->arena, PR_FALSE);
2256 ecparams = NULL;
2258 encodedparams = getECParams(curve);
2259 if (encodedparams == NULL) {
2260 goto loser;
2262 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2263 goto loser;
2265 SECITEM_FreeItem(encodedparams, PR_TRUE);
2266 fputs(buf, ecdsaresp);
2267 continue;
2269 /* Msg = ... */
2270 if (strncmp(buf, "Msg", 3) == 0) {
2271 ECPrivateKey *ecpriv;
2273 i = 3;
2274 while (isspace(buf[i]) || buf[i] == '=') {
2275 i++;
2277 for (j=0; isxdigit(buf[i]); i+=2,j++) {
2278 hex_to_byteval(&buf[i], &msg[j]);
2280 msglen = j;
2281 if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
2282 goto loser;
2284 fputs(buf, ecdsaresp);
2286 if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
2287 goto loser;
2289 if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
2290 != SECSuccess) {
2291 goto loser;
2293 len = ecpriv->publicValue.len;
2294 if (len%2 == 0) {
2295 goto loser;
2297 len = (len-1)/2;
2298 if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
2299 goto loser;
2301 fputs("Qx = ", ecdsaresp);
2302 to_hex_str(buf, &ecpriv->publicValue.data[1], len);
2303 fputs(buf, ecdsaresp);
2304 fputc('\n', ecdsaresp);
2305 fputs("Qy = ", ecdsaresp);
2306 to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
2307 fputs(buf, ecdsaresp);
2308 fputc('\n', ecdsaresp);
2310 digest.type = siBuffer;
2311 digest.data = sha1;
2312 digest.len = sizeof sha1;
2313 signature.type = siBuffer;
2314 signature.data = sig;
2315 signature.len = sizeof sig;
2316 if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) {
2317 goto loser;
2319 len = signature.len;
2320 if (len%2 != 0) {
2321 goto loser;
2323 len = len/2;
2324 fputs("R = ", ecdsaresp);
2325 to_hex_str(buf, &signature.data[0], len);
2326 fputs(buf, ecdsaresp);
2327 fputc('\n', ecdsaresp);
2328 fputs("S = ", ecdsaresp);
2329 to_hex_str(buf, &signature.data[len], len);
2330 fputs(buf, ecdsaresp);
2331 fputc('\n', ecdsaresp);
2333 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
2334 continue;
2337 loser:
2338 if (ecparams != NULL) {
2339 PORT_FreeArena(ecparams->arena, PR_FALSE);
2341 fclose(ecdsareq);
2345 * Perform the ECDSA Signature Verification Test.
2347 * reqfn is the pathname of the REQUEST file.
2349 * The output RESPONSE file is written to stdout.
2351 void
2352 ecdsa_sigver_test(char *reqfn)
2354 char buf[1024]; /* holds one line from the input REQUEST file.
2355 * needs to be large enough to hold the longest
2356 * line "Msg = <256 hex digits>\n".
2358 FILE *ecdsareq; /* input stream from the REQUEST file */
2359 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2360 char curve[16]; /* "nistxddd" */
2361 ECPublicKey ecpub;
2362 unsigned int i, j;
2363 unsigned int flen; /* length in bytes of the field size */
2364 unsigned int olen; /* length in bytes of the base point order */
2365 unsigned char msg[512]; /* message that was signed (<= 128 bytes) */
2366 unsigned int msglen;
2367 unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
2368 unsigned char sig[2*MAX_ECKEY_LEN];
2369 SECItem signature, digest;
2370 PRBool keyvalid = PR_TRUE;
2371 PRBool sigvalid = PR_TRUE;
2373 ecdsareq = fopen(reqfn, "r");
2374 ecdsaresp = stdout;
2375 ecpub.ecParams.arena = NULL;
2376 strcpy(curve, "nist");
2377 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2378 /* a comment or blank line */
2379 if (buf[0] == '#' || buf[0] == '\n') {
2380 fputs(buf, ecdsaresp);
2381 continue;
2383 /* [X-ddd] */
2384 if (buf[0] == '[') {
2385 const char *src;
2386 char *dst;
2387 SECItem *encodedparams;
2388 ECParams *ecparams;
2390 src = &buf[1];
2391 dst = &curve[4];
2392 *dst++ = tolower(*src);
2393 src += 2; /* skip the hyphen */
2394 *dst++ = *src++;
2395 *dst++ = *src++;
2396 *dst++ = *src++;
2397 *dst = '\0';
2398 encodedparams = getECParams(curve);
2399 if (encodedparams == NULL) {
2400 goto loser;
2402 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2403 goto loser;
2405 SECITEM_FreeItem(encodedparams, PR_TRUE);
2406 if (ecpub.ecParams.arena != NULL) {
2407 PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
2409 ecpub.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2410 if (ecpub.ecParams.arena == NULL) {
2411 goto loser;
2413 if (EC_CopyParams(ecpub.ecParams.arena, &ecpub.ecParams, ecparams)
2414 != SECSuccess) {
2415 goto loser;
2417 PORT_FreeArena(ecparams->arena, PR_FALSE);
2418 flen = (ecpub.ecParams.fieldID.size + 7) >> 3;
2419 olen = ecpub.ecParams.order.len;
2420 if (2*olen > sizeof sig) {
2421 goto loser;
2423 ecpub.publicValue.type = siBuffer;
2424 ecpub.publicValue.data = NULL;
2425 ecpub.publicValue.len = 0;
2426 SECITEM_AllocItem(ecpub.ecParams.arena,
2427 &ecpub.publicValue, 2*flen+1);
2428 if (ecpub.publicValue.data == NULL) {
2429 goto loser;
2431 ecpub.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED;
2432 fputs(buf, ecdsaresp);
2433 continue;
2435 /* Msg = ... */
2436 if (strncmp(buf, "Msg", 3) == 0) {
2437 i = 3;
2438 while (isspace(buf[i]) || buf[i] == '=') {
2439 i++;
2441 for (j=0; isxdigit(buf[i]); i+=2,j++) {
2442 hex_to_byteval(&buf[i], &msg[j]);
2444 msglen = j;
2445 if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
2446 goto loser;
2448 fputs(buf, ecdsaresp);
2450 digest.type = siBuffer;
2451 digest.data = sha1;
2452 digest.len = sizeof sha1;
2454 continue;
2456 /* Qx = ... */
2457 if (strncmp(buf, "Qx", 2) == 0) {
2458 fputs(buf, ecdsaresp);
2459 i = 2;
2460 while (isspace(buf[i]) || buf[i] == '=') {
2461 i++;
2463 keyvalid = from_hex_str(&ecpub.publicValue.data[1], flen,
2464 &buf[i]);
2465 continue;
2467 /* Qy = ... */
2468 if (strncmp(buf, "Qy", 2) == 0) {
2469 fputs(buf, ecdsaresp);
2470 if (!keyvalid) {
2471 continue;
2473 i = 2;
2474 while (isspace(buf[i]) || buf[i] == '=') {
2475 i++;
2477 keyvalid = from_hex_str(&ecpub.publicValue.data[1+flen], flen,
2478 &buf[i]);
2479 if (!keyvalid) {
2480 continue;
2482 if (EC_ValidatePublicKey(&ecpub.ecParams, &ecpub.publicValue)
2483 != SECSuccess) {
2484 if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
2485 keyvalid = PR_FALSE;
2486 } else {
2487 goto loser;
2490 continue;
2492 /* R = ... */
2493 if (buf[0] == 'R') {
2494 fputs(buf, ecdsaresp);
2495 i = 1;
2496 while (isspace(buf[i]) || buf[i] == '=') {
2497 i++;
2499 sigvalid = from_hex_str(sig, olen, &buf[i]);
2500 continue;
2502 /* S = ... */
2503 if (buf[0] == 'S') {
2504 fputs(buf, ecdsaresp);
2505 i = 1;
2506 while (isspace(buf[i]) || buf[i] == '=') {
2507 i++;
2509 if (sigvalid) {
2510 sigvalid = from_hex_str(&sig[olen], olen, &buf[i]);
2512 signature.type = siBuffer;
2513 signature.data = sig;
2514 signature.len = 2*olen;
2516 if (!keyvalid || !sigvalid) {
2517 fputs("Result = F\n", ecdsaresp);
2518 } else if (ECDSA_VerifyDigest(&ecpub, &signature, &digest)
2519 == SECSuccess) {
2520 fputs("Result = P\n", ecdsaresp);
2521 } else {
2522 fputs("Result = F\n", ecdsaresp);
2524 continue;
2527 loser:
2528 if (ecpub.ecParams.arena != NULL) {
2529 PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
2531 fclose(ecdsareq);
2533 #endif /* NSS_DISABLE_ECC */
2537 * Read a value from the test and allocate the result.
2539 static unsigned char *
2540 alloc_value(char *buf, int *len)
2542 unsigned char * value;
2543 int i, count;
2545 if (strncmp(buf, "<None>", 6) == 0) {
2546 *len = 0;
2547 return NULL;
2550 /* find the length of the number */
2551 for (count = 0; isxdigit(buf[count]); count++);
2552 *len = count/2;
2554 if (*len == 0) {
2555 return NULL;
2558 value = PORT_Alloc(*len);
2559 if (!value) {
2560 *len = 0;
2561 return NULL;
2564 for (i=0; i<*len; buf+=2 , i++) {
2565 hex_to_byteval(buf, &value[i]);
2569 return value;
2572 PRBool
2573 isblankline(char *b)
2575 while (isspace(*b)) b++;
2576 if ((*b == '\n') || (*b == 0)) {
2577 return PR_TRUE;
2579 return PR_FALSE;
2582 static int debug = 0;
2585 * Perform the Hash_DRBG (CAVS) for the RNG algorithm
2587 * reqfn is the pathname of the REQUEST file.
2589 * The output RESPONSE file is written to stdout.
2591 void
2592 drbg(char *reqfn)
2594 char buf[2000]; /* test case has some very long lines, returned bits
2595 * as high as 800 bytes (6400 bits). That 1600 byte
2596 * plus a tag */
2597 char buf2[2000];
2598 FILE *rngreq; /* input stream from the REQUEST file */
2599 FILE *rngresp; /* output stream to the RESPONSE file */
2601 unsigned int i, j;
2602 PRBool predictionResistance = PR_FALSE;
2603 unsigned char *nonce = NULL;
2604 int nonceLen = 0;
2605 unsigned char *personalizationString = NULL;
2606 int personalizationStringLen = 0;
2607 unsigned char *additionalInput = NULL;
2608 int additionalInputLen = 0;
2609 unsigned char *entropyInput = NULL;
2610 int entropyInputLen = 0;
2611 unsigned char predictedreturn_bytes[SHA256_LENGTH];
2612 unsigned char return_bytes[SHA256_LENGTH];
2613 int return_bytes_len = SHA256_LENGTH;
2614 enum { NONE, INSTANTIATE, GENERATE, RESEED, RESULT } command =
2615 NONE;
2616 PRBool genResult = PR_FALSE;
2617 SECStatus rv;
2619 rngreq = fopen(reqfn, "r");
2620 rngresp = stdout;
2621 while (fgets(buf, sizeof buf, rngreq) != NULL) {
2622 switch (command) {
2623 case INSTANTIATE:
2624 if (debug) {
2625 fputs("# PRNGTEST_Instantiate(",rngresp);
2626 to_hex_str(buf2,entropyInput, entropyInputLen);
2627 fputs(buf2,rngresp);
2628 fprintf(rngresp,",%d,",entropyInputLen);
2629 to_hex_str(buf2,nonce, nonceLen);
2630 fputs(buf2,rngresp);
2631 fprintf(rngresp,",%d,",nonceLen);
2632 to_hex_str(buf2,personalizationString,
2633 personalizationStringLen);
2634 fputs(buf2,rngresp);
2635 fprintf(rngresp,",%d)\n", personalizationStringLen);
2637 rv = PRNGTEST_Instantiate(entropyInput, entropyInputLen,
2638 nonce, nonceLen,
2639 personalizationString,
2640 personalizationStringLen);
2641 if (rv != SECSuccess) {
2642 goto loser;
2644 break;
2646 case GENERATE:
2647 case RESULT:
2648 memset(return_bytes, 0, return_bytes_len);
2649 if (debug) {
2650 fputs("# PRNGTEST_Generate(returnbytes",rngresp);
2651 fprintf(rngresp,",%d,", return_bytes_len);
2652 to_hex_str(buf2,additionalInput, additionalInputLen);
2653 fputs(buf2,rngresp);
2654 fprintf(rngresp,",%d)\n",additionalInputLen);
2656 rv = PRNGTEST_Generate((PRUint8 *) return_bytes,
2657 return_bytes_len,
2658 (PRUint8 *) additionalInput,
2659 additionalInputLen);
2660 if (rv != SECSuccess) {
2661 goto loser;
2664 if (command == RESULT) {
2665 fputs("ReturnedBits = ", rngresp);
2666 to_hex_str(buf2, return_bytes, return_bytes_len);
2667 fputs(buf2, rngresp);
2668 fputc('\n', rngresp);
2669 if (debug) {
2670 fputs("# PRNGTEST_Uninstantiate()\n",rngresp);
2672 rv = PRNGTEST_Uninstantiate();
2673 if (rv != SECSuccess) {
2674 goto loser;
2676 } else if (debug) {
2677 fputs("#ReturnedBits = ", rngresp);
2678 to_hex_str(buf2, return_bytes, return_bytes_len);
2679 fputs(buf2, rngresp);
2680 fputc('\n', rngresp);
2683 memset(additionalInput, 0, additionalInputLen);
2684 break;
2686 case RESEED:
2687 if (entropyInput || additionalInput) {
2688 if (debug) {
2689 fputs("# PRNGTEST_Reseed(",rngresp);
2690 fprintf(rngresp,",%d,", return_bytes_len);
2691 to_hex_str(buf2,entropyInput, entropyInputLen);
2692 fputs(buf2,rngresp);
2693 fprintf(rngresp,",%d,", entropyInputLen);
2694 to_hex_str(buf2,additionalInput, additionalInputLen);
2695 fputs(buf2,rngresp);
2696 fprintf(rngresp,",%d)\n",additionalInputLen);
2698 rv = PRNGTEST_Reseed(entropyInput, entropyInputLen,
2699 additionalInput, additionalInputLen);
2700 if (rv != SECSuccess) {
2701 goto loser;
2704 memset(entropyInput, 0, entropyInputLen);
2705 memset(additionalInput, 0, additionalInputLen);
2706 break;
2707 case NONE:
2708 break;
2711 command = NONE;
2713 /* a comment or blank line */
2714 if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r' ) {
2715 fputs(buf, rngresp);
2716 continue;
2719 /* [Hash - SHA256] */
2720 if (strncmp(buf, "[SHA-256]", 9) == 0) {
2721 fputs(buf, rngresp);
2722 continue;
2725 if (strncmp(buf, "[PredictionResistance", 21) == 0) {
2726 i = 21;
2727 while (isspace(buf[i]) || buf[i] == '=') {
2728 i++;
2730 if (strncmp(buf, "False", 5) == 0) {
2731 predictionResistance = PR_FALSE;
2732 } else {
2733 predictionResistance = PR_TRUE;
2736 fputs(buf, rngresp);
2737 continue;
2740 if (strncmp(buf, "[EntropyInputLen", 16) == 0) {
2741 if (entropyInput) {
2742 PORT_ZFree(entropyInput, entropyInputLen);
2743 entropyInput = NULL;
2744 entropyInputLen = 0;
2746 if (sscanf(buf, "[EntropyInputLen = %d]", &entropyInputLen) != 1) {
2747 goto loser;
2749 entropyInputLen = entropyInputLen/8;
2750 if (entropyInputLen > 0) {
2751 entropyInput = PORT_Alloc(entropyInputLen);
2753 fputs(buf, rngresp);
2754 continue;
2757 if (strncmp(buf, "[NonceLen", 9) == 0) {
2758 if (nonce) {
2759 PORT_ZFree(nonce, nonceLen);
2760 nonce = NULL;
2761 nonceLen = 0;
2764 if (sscanf(buf, "[NonceLen = %d]", &nonceLen) != 1) {
2765 goto loser;
2767 nonceLen = nonceLen/8;
2768 if (nonceLen > 0) {
2769 nonce = PORT_Alloc(nonceLen);
2771 fputs(buf, rngresp);
2772 continue;
2775 if (strncmp(buf, "[PersonalizationStringLen", 16) == 0) {
2776 if (personalizationString) {
2777 PORT_ZFree(personalizationString, personalizationStringLen);
2778 personalizationString = NULL;
2779 personalizationStringLen = 0;
2782 if (sscanf(buf, "[PersonalizationStringLen = %d]", &personalizationStringLen) != 1) {
2783 goto loser;
2785 personalizationStringLen = personalizationStringLen / 8;
2786 if (personalizationStringLen > 0) {
2787 personalizationString = PORT_Alloc(personalizationStringLen);
2789 fputs(buf, rngresp);
2791 continue;
2794 if (strncmp(buf, "[AdditionalInputLen", 16) == 0) {
2795 if (additionalInput) {
2796 PORT_ZFree(additionalInput, additionalInputLen);
2797 additionalInput = NULL;
2798 additionalInputLen = 0;
2801 if (sscanf(buf, "[AdditionalInputLen = %d]", &additionalInputLen) != 1) {
2802 goto loser;
2804 additionalInputLen = additionalInputLen/8;
2805 if (additionalInputLen > 0) {
2806 additionalInput = PORT_Alloc(additionalInputLen);
2808 fputs(buf, rngresp);
2809 continue;
2812 if (strncmp(buf, "COUNT", 5) == 0) {
2813 /* zeroize the variables for the test with this data set */
2814 if (entropyInput) {
2815 memset(entropyInput, 0, entropyInputLen);
2817 if (nonce) {
2818 memset(nonce, 0, nonceLen);
2820 if (personalizationString) {
2821 memset(personalizationString, 0, personalizationStringLen);
2823 if (additionalInput) {
2824 memset(additionalInput, 0, additionalInputLen);
2826 genResult = PR_FALSE;
2828 fputs(buf, rngresp);
2829 continue;
2832 /* EntropyInputReseed = ... */
2833 if (strncmp(buf, "EntropyInputReseed", 18) == 0) {
2834 if (entropyInput) {
2835 memset(entropyInput, 0, entropyInputLen);
2836 i = 18;
2837 while (isspace(buf[i]) || buf[i] == '=') {
2838 i++;
2841 for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<entropyInputLen*/
2842 hex_to_byteval(&buf[i], &entropyInput[j]);
2845 fputs(buf, rngresp);
2846 continue;
2849 /* AttionalInputReseed = ... */
2850 if (strncmp(buf, "AdditionalInputReseed", 21) == 0) {
2851 if (additionalInput) {
2852 memset(additionalInput, 0, additionalInputLen);
2853 i = 21;
2854 while (isspace(buf[i]) || buf[i] == '=') {
2855 i++;
2857 for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<additionalInputLen*/
2858 hex_to_byteval(&buf[i], &additionalInput[j]);
2861 command = RESEED;
2862 fputs(buf, rngresp);
2863 continue;
2866 /* Entropy input = ... */
2867 if (strncmp(buf, "EntropyInput", 12) == 0) {
2868 i = 12;
2869 while (isspace(buf[i]) || buf[i] == '=') {
2870 i++;
2872 for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<entropyInputLen*/
2873 hex_to_byteval(&buf[i], &entropyInput[j]);
2875 fputs(buf, rngresp);
2876 continue;
2879 /* nouce = ... */
2880 if (strncmp(buf, "Nonce", 5) == 0) {
2881 i = 5;
2882 while (isspace(buf[i]) || buf[i] == '=') {
2883 i++;
2885 for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<nonceLen*/
2886 hex_to_byteval(&buf[i], &nonce[j]);
2888 fputs(buf, rngresp);
2889 continue;
2892 /* Personalization string = ... */
2893 if (strncmp(buf, "PersonalizationString", 21) == 0) {
2894 if (personalizationString) {
2895 i = 21;
2896 while (isspace(buf[i]) || buf[i] == '=') {
2897 i++;
2899 for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<personalizationStringLen*/
2900 hex_to_byteval(&buf[i], &personalizationString[j]);
2903 fputs(buf, rngresp);
2904 command = INSTANTIATE;
2905 continue;
2908 /* Additional input = ... */
2909 if (strncmp(buf, "AdditionalInput", 15) == 0) {
2910 if (additionalInput) {
2911 i = 15;
2912 while (isspace(buf[i]) || buf[i] == '=') {
2913 i++;
2915 for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<additionalInputLen*/
2916 hex_to_byteval(&buf[i], &additionalInput[j]);
2919 if (genResult) {
2920 command = RESULT;
2921 } else {
2922 command = GENERATE;
2923 genResult = PR_TRUE; /* next time generate result */
2925 fputs(buf, rngresp);
2926 continue;
2929 /* Returned bits = ... */
2930 if (strncmp(buf, "ReturnedBits", 12) == 0) {
2931 i = 12;
2932 while (isspace(buf[i]) || buf[i] == '=') {
2933 i++;
2935 for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<additionalInputLen*/
2936 hex_to_byteval(&buf[i], &predictedreturn_bytes[j]);
2939 if (memcmp(return_bytes,
2940 predictedreturn_bytes, return_bytes_len) != 0) {
2941 if (debug) {
2942 fprintf(rngresp, "# Generate failed:\n");
2943 fputs( "# predicted=", rngresp);
2944 to_hex_str(buf, predictedreturn_bytes,
2945 return_bytes_len);
2946 fputs(buf, rngresp);
2947 fputs("\n# actual = ", rngresp);
2948 fputs(buf2, rngresp);
2949 fputc('\n', rngresp);
2951 } else {
2952 fprintf(stderr, "Generate failed:\n");
2953 fputs( " predicted=", stderr);
2954 to_hex_str(buf, predictedreturn_bytes,
2955 return_bytes_len);
2956 fputs(buf, stderr);
2957 fputs("\n actual = ", stderr);
2958 fputs(buf2, stderr);
2959 fputc('\n', stderr);
2962 memset(predictedreturn_bytes, 0 , sizeof predictedreturn_bytes);
2964 continue;
2967 loser:
2968 fclose(rngreq);
2972 * Perform the RNG Variable Seed Test (VST) for the RNG algorithm
2973 * "DSA - Generation of X", used both as specified and as a generic
2974 * purpose RNG. The presence of "Q = ..." in the REQUEST file
2975 * indicates we are using the algorithm as specified.
2977 * reqfn is the pathname of the REQUEST file.
2979 * The output RESPONSE file is written to stdout.
2981 void
2982 rng_vst(char *reqfn)
2984 char buf[256]; /* holds one line from the input REQUEST file.
2985 * needs to be large enough to hold the longest
2986 * line "XSeed = <128 hex digits>\n".
2988 FILE *rngreq; /* input stream from the REQUEST file */
2989 FILE *rngresp; /* output stream to the RESPONSE file */
2990 unsigned int i, j;
2991 unsigned char Q[DSA1_SUBPRIME_LEN];
2992 PRBool hasQ = PR_FALSE;
2993 unsigned int b; /* 160 <= b <= 512, b is a multiple of 8 */
2994 unsigned char XKey[512/8];
2995 unsigned char XSeed[512/8];
2996 unsigned char GENX[DSA1_SIGNATURE_LEN];
2997 unsigned char DSAX[DSA1_SUBPRIME_LEN];
2998 SECStatus rv;
3000 rngreq = fopen(reqfn, "r");
3001 rngresp = stdout;
3002 while (fgets(buf, sizeof buf, rngreq) != NULL) {
3003 /* a comment or blank line */
3004 if (buf[0] == '#' || buf[0] == '\n') {
3005 fputs(buf, rngresp);
3006 continue;
3008 /* [Xchange - SHA1] */
3009 if (buf[0] == '[') {
3010 fputs(buf, rngresp);
3011 continue;
3013 /* Q = ... */
3014 if (buf[0] == 'Q') {
3015 i = 1;
3016 while (isspace(buf[i]) || buf[i] == '=') {
3017 i++;
3019 for (j=0; j<sizeof Q; i+=2,j++) {
3020 hex_to_byteval(&buf[i], &Q[j]);
3022 fputs(buf, rngresp);
3023 hasQ = PR_TRUE;
3024 continue;
3026 /* "COUNT = x" begins a new data set */
3027 if (strncmp(buf, "COUNT", 5) == 0) {
3028 /* zeroize the variables for the test with this data set */
3029 b = 0;
3030 memset(XKey, 0, sizeof XKey);
3031 memset(XSeed, 0, sizeof XSeed);
3032 fputs(buf, rngresp);
3033 continue;
3035 /* b = ... */
3036 if (buf[0] == 'b') {
3037 i = 1;
3038 while (isspace(buf[i]) || buf[i] == '=') {
3039 i++;
3041 b = atoi(&buf[i]);
3042 if (b < 160 || b > 512 || b%8 != 0) {
3043 goto loser;
3045 fputs(buf, rngresp);
3046 continue;
3048 /* XKey = ... */
3049 if (strncmp(buf, "XKey", 4) == 0) {
3050 i = 4;
3051 while (isspace(buf[i]) || buf[i] == '=') {
3052 i++;
3054 for (j=0; j<b/8; i+=2,j++) {
3055 hex_to_byteval(&buf[i], &XKey[j]);
3057 fputs(buf, rngresp);
3058 continue;
3060 /* XSeed = ... */
3061 if (strncmp(buf, "XSeed", 5) == 0) {
3062 i = 5;
3063 while (isspace(buf[i]) || buf[i] == '=') {
3064 i++;
3066 for (j=0; j<b/8; i+=2,j++) {
3067 hex_to_byteval(&buf[i], &XSeed[j]);
3069 fputs(buf, rngresp);
3071 rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
3072 if (rv != SECSuccess) {
3073 goto loser;
3075 fputs("X = ", rngresp);
3076 if (hasQ) {
3077 rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
3078 if (rv != SECSuccess) {
3079 goto loser;
3081 to_hex_str(buf, DSAX, sizeof DSAX);
3082 } else {
3083 to_hex_str(buf, GENX, sizeof GENX);
3085 fputs(buf, rngresp);
3086 fputc('\n', rngresp);
3087 continue;
3090 loser:
3091 fclose(rngreq);
3095 * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm
3096 * "DSA - Generation of X", used both as specified and as a generic
3097 * purpose RNG. The presence of "Q = ..." in the REQUEST file
3098 * indicates we are using the algorithm as specified.
3100 * reqfn is the pathname of the REQUEST file.
3102 * The output RESPONSE file is written to stdout.
3104 void
3105 rng_mct(char *reqfn)
3107 char buf[256]; /* holds one line from the input REQUEST file.
3108 * needs to be large enough to hold the longest
3109 * line "XSeed = <128 hex digits>\n".
3111 FILE *rngreq; /* input stream from the REQUEST file */
3112 FILE *rngresp; /* output stream to the RESPONSE file */
3113 unsigned int i, j;
3114 unsigned char Q[DSA1_SUBPRIME_LEN];
3115 PRBool hasQ = PR_FALSE;
3116 unsigned int b; /* 160 <= b <= 512, b is a multiple of 8 */
3117 unsigned char XKey[512/8];
3118 unsigned char XSeed[512/8];
3119 unsigned char GENX[2*SHA1_LENGTH];
3120 unsigned char DSAX[DSA1_SUBPRIME_LEN];
3121 SECStatus rv;
3123 rngreq = fopen(reqfn, "r");
3124 rngresp = stdout;
3125 while (fgets(buf, sizeof buf, rngreq) != NULL) {
3126 /* a comment or blank line */
3127 if (buf[0] == '#' || buf[0] == '\n') {
3128 fputs(buf, rngresp);
3129 continue;
3131 /* [Xchange - SHA1] */
3132 if (buf[0] == '[') {
3133 fputs(buf, rngresp);
3134 continue;
3136 /* Q = ... */
3137 if (buf[0] == 'Q') {
3138 i = 1;
3139 while (isspace(buf[i]) || buf[i] == '=') {
3140 i++;
3142 for (j=0; j<sizeof Q; i+=2,j++) {
3143 hex_to_byteval(&buf[i], &Q[j]);
3145 fputs(buf, rngresp);
3146 hasQ = PR_TRUE;
3147 continue;
3149 /* "COUNT = x" begins a new data set */
3150 if (strncmp(buf, "COUNT", 5) == 0) {
3151 /* zeroize the variables for the test with this data set */
3152 b = 0;
3153 memset(XKey, 0, sizeof XKey);
3154 memset(XSeed, 0, sizeof XSeed);
3155 fputs(buf, rngresp);
3156 continue;
3158 /* b = ... */
3159 if (buf[0] == 'b') {
3160 i = 1;
3161 while (isspace(buf[i]) || buf[i] == '=') {
3162 i++;
3164 b = atoi(&buf[i]);
3165 if (b < 160 || b > 512 || b%8 != 0) {
3166 goto loser;
3168 fputs(buf, rngresp);
3169 continue;
3171 /* XKey = ... */
3172 if (strncmp(buf, "XKey", 4) == 0) {
3173 i = 4;
3174 while (isspace(buf[i]) || buf[i] == '=') {
3175 i++;
3177 for (j=0; j<b/8; i+=2,j++) {
3178 hex_to_byteval(&buf[i], &XKey[j]);
3180 fputs(buf, rngresp);
3181 continue;
3183 /* XSeed = ... */
3184 if (strncmp(buf, "XSeed", 5) == 0) {
3185 unsigned int k;
3186 i = 5;
3187 while (isspace(buf[i]) || buf[i] == '=') {
3188 i++;
3190 for (j=0; j<b/8; i+=2,j++) {
3191 hex_to_byteval(&buf[i], &XSeed[j]);
3193 fputs(buf, rngresp);
3195 for (k = 0; k < 10000; k++) {
3196 rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
3197 if (rv != SECSuccess) {
3198 goto loser;
3201 fputs("X = ", rngresp);
3202 if (hasQ) {
3203 rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
3204 if (rv != SECSuccess) {
3205 goto loser;
3207 to_hex_str(buf, DSAX, sizeof DSAX);
3208 } else {
3209 to_hex_str(buf, GENX, sizeof GENX);
3211 fputs(buf, rngresp);
3212 fputc('\n', rngresp);
3213 continue;
3216 loser:
3217 fclose(rngreq);
3221 * HASH_ functions are available to full NSS apps and internally inside
3222 * freebl, but not exported to users of freebl. Create short stubs to
3223 * replace the functionality for fipstest.
3225 SECStatus
3226 fips_hashBuf(HASH_HashType type, unsigned char *hashBuf,
3227 unsigned char *msg, int len)
3229 SECStatus rv = SECFailure;
3231 switch (type) {
3232 case HASH_AlgSHA1:
3233 rv = SHA1_HashBuf(hashBuf, msg, len);
3234 break;
3235 case HASH_AlgSHA224:
3236 rv = SHA224_HashBuf(hashBuf, msg, len);
3237 break;
3238 case HASH_AlgSHA256:
3239 rv = SHA256_HashBuf(hashBuf, msg, len);
3240 break;
3241 case HASH_AlgSHA384:
3242 rv = SHA384_HashBuf(hashBuf, msg, len);
3243 break;
3244 case HASH_AlgSHA512:
3245 rv = SHA512_HashBuf(hashBuf, msg, len);
3246 break;
3247 default:
3248 break;
3250 return rv;
3254 fips_hashLen(HASH_HashType type)
3256 int len = 0;
3258 switch (type) {
3259 case HASH_AlgSHA1:
3260 len = SHA1_LENGTH;
3261 break;
3262 case HASH_AlgSHA224:
3263 len = SHA224_LENGTH;
3264 break;
3265 case HASH_AlgSHA256:
3266 len = SHA256_LENGTH;
3267 break;
3268 case HASH_AlgSHA384:
3269 len = SHA384_LENGTH;
3270 break;
3271 case HASH_AlgSHA512:
3272 len = SHA512_LENGTH;
3273 break;
3274 default:
3275 break;
3277 return len;
3280 SECOidTag
3281 fips_hashOid(HASH_HashType type)
3283 SECOidTag oid = SEC_OID_UNKNOWN;
3285 switch (type) {
3286 case HASH_AlgSHA1:
3287 oid = SEC_OID_SHA1;
3288 break;
3289 case HASH_AlgSHA224:
3290 oid = SEC_OID_SHA224;
3291 break;
3292 case HASH_AlgSHA256:
3293 oid = SEC_OID_SHA256;
3294 break;
3295 case HASH_AlgSHA384:
3296 oid = SEC_OID_SHA384;
3297 break;
3298 case HASH_AlgSHA512:
3299 oid = SEC_OID_SHA512;
3300 break;
3301 default:
3302 break;
3304 return oid;
3307 HASH_HashType
3308 sha_get_hashType(int hashbits)
3310 HASH_HashType hashType = HASH_AlgNULL;
3312 switch (hashbits) {
3313 case 1:
3314 case (SHA1_LENGTH*PR_BITS_PER_BYTE):
3315 hashType = HASH_AlgSHA1;
3316 break;
3317 case (SHA224_LENGTH*PR_BITS_PER_BYTE):
3318 hashType = HASH_AlgSHA224;
3319 break;
3320 case (SHA256_LENGTH*PR_BITS_PER_BYTE):
3321 hashType = HASH_AlgSHA256;
3322 break;
3323 case (SHA384_LENGTH*PR_BITS_PER_BYTE):
3324 hashType = HASH_AlgSHA384;
3325 break;
3326 case (SHA512_LENGTH*PR_BITS_PER_BYTE):
3327 hashType = HASH_AlgSHA512;
3328 break;
3329 default:
3330 break;
3332 return hashType;
3336 * Calculate the SHA Message Digest
3338 * MD = Message digest
3339 * MDLen = length of Message Digest and SHA_Type
3340 * msg = message to digest
3341 * msgLen = length of message to digest
3343 SECStatus sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen)
3345 HASH_HashType hashType = sha_get_hashType(MDLen*PR_BITS_PER_BYTE);
3347 return fips_hashBuf(hashType, MD, msg, msgLen);
3351 * Perform the SHA Monte Carlo Test
3353 * MDLen = length of Message Digest and SHA_Type
3354 * seed = input seed value
3355 * resp = is the output response file.
3357 SECStatus sha_mct_test(unsigned int MDLen, unsigned char *seed, FILE *resp)
3359 int i, j;
3360 unsigned int msgLen = MDLen*3;
3361 unsigned char MD_i3[HASH_LENGTH_MAX]; /* MD[i-3] */
3362 unsigned char MD_i2[HASH_LENGTH_MAX]; /* MD[i-2] */
3363 unsigned char MD_i1[HASH_LENGTH_MAX]; /* MD[i-1] */
3364 unsigned char MD_i[HASH_LENGTH_MAX]; /* MD[i] */
3365 unsigned char msg[HASH_LENGTH_MAX*3];
3366 char buf[HASH_LENGTH_MAX*2 + 1]; /* MAX buf MD_i as a hex string */
3368 for (j=0; j<100; j++) {
3369 /* MD_0 = MD_1 = MD_2 = seed */
3370 memcpy(MD_i3, seed, MDLen);
3371 memcpy(MD_i2, seed, MDLen);
3372 memcpy(MD_i1, seed, MDLen);
3374 for (i=3; i < 1003; i++) {
3375 /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */
3376 memcpy(msg, MD_i3, MDLen);
3377 memcpy(&msg[MDLen], MD_i2, MDLen);
3378 memcpy(&msg[MDLen*2], MD_i1,MDLen);
3380 /* MDi = SHA(Msg) */
3381 if (sha_calcMD(MD_i, MDLen,
3382 msg, msgLen) != SECSuccess) {
3383 return SECFailure;
3386 /* save MD[i-3] MD[i-2] MD[i-1] */
3387 memcpy(MD_i3, MD_i2, MDLen);
3388 memcpy(MD_i2, MD_i1, MDLen);
3389 memcpy(MD_i1, MD_i, MDLen);
3393 /* seed = MD_i */
3394 memcpy(seed, MD_i, MDLen);
3396 sprintf(buf, "COUNT = %d\n", j);
3397 fputs(buf, resp);
3399 /* output MD_i */
3400 fputs("MD = ", resp);
3401 to_hex_str(buf, MD_i, MDLen);
3402 fputs(buf, resp);
3403 fputc('\n', resp);
3406 return SECSuccess;
3410 * Perform the SHA Tests.
3412 * reqfn is the pathname of the input REQUEST file.
3414 * The output RESPONSE file is written to stdout.
3416 void sha_test(char *reqfn)
3418 unsigned int i, j;
3419 unsigned int MDlen; /* the length of the Message Digest in Bytes */
3420 unsigned int msgLen; /* the length of the input Message in Bytes */
3421 unsigned char *msg = NULL; /* holds the message to digest.*/
3422 size_t bufSize = 25608; /*MAX buffer size */
3423 char *buf = NULL; /* holds one line from the input REQUEST file.*/
3424 unsigned char seed[HASH_LENGTH_MAX]; /* max size of seed 64 bytes */
3425 unsigned char MD[HASH_LENGTH_MAX]; /* message digest */
3427 FILE *req = NULL; /* input stream from the REQUEST file */
3428 FILE *resp; /* output stream to the RESPONSE file */
3430 buf = PORT_ZAlloc(bufSize);
3431 if (buf == NULL) {
3432 goto loser;
3435 /* zeroize the variables for the test with this data set */
3436 memset(seed, 0, sizeof seed);
3438 req = fopen(reqfn, "r");
3439 resp = stdout;
3440 while (fgets(buf, bufSize, req) != NULL) {
3442 /* a comment or blank line */
3443 if (buf[0] == '#' || buf[0] == '\n') {
3444 fputs(buf, resp);
3445 continue;
3447 /* [L = Length of the Message Digest and sha_type */
3448 if (buf[0] == '[') {
3449 if (strncmp(&buf[1], "L ", 1) == 0) {
3450 i = 2;
3451 while (isspace(buf[i]) || buf[i] == '=') {
3452 i++;
3454 MDlen = atoi(&buf[i]);
3455 fputs(buf, resp);
3456 continue;
3459 /* Len = Length of the Input Message Length ... */
3460 if (strncmp(buf, "Len", 3) == 0) {
3461 i = 3;
3462 while (isspace(buf[i]) || buf[i] == '=') {
3463 i++;
3465 if (msg) {
3466 PORT_ZFree(msg,msgLen);
3467 msg = NULL;
3469 msgLen = atoi(&buf[i]); /* in bits */
3470 if (msgLen%8 != 0) {
3471 fprintf(stderr, "SHA tests are incorrectly configured for "
3472 "BIT oriented implementations\n");
3473 goto loser;
3475 msgLen = msgLen/8; /* convert to bytes */
3476 fputs(buf, resp);
3477 msg = PORT_ZAlloc(msgLen);
3478 if (msg == NULL && msgLen != 0) {
3479 goto loser;
3481 continue;
3483 /* MSG = ... */
3484 if (strncmp(buf, "Msg", 3) == 0) {
3485 i = 3;
3486 while (isspace(buf[i]) || buf[i] == '=') {
3487 i++;
3489 for (j=0; j< msgLen; i+=2,j++) {
3490 hex_to_byteval(&buf[i], &msg[j]);
3492 fputs(buf, resp);
3493 /* calculate the Message Digest */
3494 memset(MD, 0, sizeof MD);
3495 if (sha_calcMD(MD, MDlen,
3496 msg, msgLen) != SECSuccess) {
3497 goto loser;
3500 fputs("MD = ", resp);
3501 to_hex_str(buf, MD, MDlen);
3502 fputs(buf, resp);
3503 fputc('\n', resp);
3505 continue;
3507 /* Seed = ... */
3508 if (strncmp(buf, "Seed", 4) == 0) {
3509 i = 4;
3510 while (isspace(buf[i]) || buf[i] == '=') {
3511 i++;
3513 for (j=0; j<sizeof seed; i+=2,j++) {
3514 hex_to_byteval(&buf[i], &seed[j]);
3517 fputs(buf, resp);
3518 fputc('\n', resp);
3520 /* do the Monte Carlo test */
3521 if (sha_mct_test(MDlen, seed, resp) != SECSuccess) {
3522 goto loser;
3525 continue;
3528 loser:
3529 if (req) {
3530 fclose(req);
3532 if (buf) {
3533 PORT_ZFree(buf, bufSize);
3535 if (msg) {
3536 PORT_ZFree(msg, msgLen);
3540 /****************************************************/
3541 /* HMAC SHA-X calc */
3542 /* hmac_computed - the computed HMAC */
3543 /* hmac_length - the length of the computed HMAC */
3544 /* secret_key - secret key to HMAC */
3545 /* secret_key_length - length of secret key, */
3546 /* message - message to HMAC */
3547 /* message_length - length ofthe message */
3548 /****************************************************/
3549 static SECStatus
3550 hmac_calc(unsigned char *hmac_computed,
3551 const unsigned int hmac_length,
3552 const unsigned char *secret_key,
3553 const unsigned int secret_key_length,
3554 const unsigned char *message,
3555 const unsigned int message_length,
3556 const HASH_HashType hashAlg )
3558 SECStatus hmac_status = SECFailure;
3559 HMACContext *cx = NULL;
3560 SECHashObject *hashObj = NULL;
3561 unsigned int bytes_hashed = 0;
3563 hashObj = (SECHashObject *) HASH_GetRawHashObject(hashAlg);
3565 if (!hashObj)
3566 return( SECFailure );
3568 cx = HMAC_Create(hashObj, secret_key,
3569 secret_key_length,
3570 PR_TRUE); /* PR_TRUE for in FIPS mode */
3572 if (cx == NULL)
3573 return( SECFailure );
3575 HMAC_Begin(cx);
3576 HMAC_Update(cx, message, message_length);
3577 hmac_status = HMAC_Finish(cx, hmac_computed, &bytes_hashed,
3578 hmac_length);
3580 HMAC_Destroy(cx, PR_TRUE);
3582 return( hmac_status );
3586 * Perform the HMAC Tests.
3588 * reqfn is the pathname of the input REQUEST file.
3590 * The output RESPONSE file is written to stdout.
3592 void hmac_test(char *reqfn)
3594 unsigned int i, j;
3595 size_t bufSize = 400; /* MAX buffer size */
3596 char *buf = NULL; /* holds one line from the input REQUEST file.*/
3597 unsigned int keyLen; /* Key Length */
3598 unsigned char key[200]; /* key MAX size = 184 */
3599 unsigned int msgLen = 128; /* the length of the input */
3600 /* Message is always 128 Bytes */
3601 unsigned char *msg = NULL; /* holds the message to digest.*/
3602 unsigned int HMACLen; /* the length of the HMAC Bytes */
3603 unsigned int TLen; /* the length of the requested */
3604 /* truncated HMAC Bytes */
3605 unsigned char HMAC[HASH_LENGTH_MAX]; /* computed HMAC */
3606 unsigned char expectedHMAC[HASH_LENGTH_MAX]; /* for .fax files that have */
3607 /* supplied known answer */
3608 HASH_HashType hash_alg; /* HMAC type */
3611 FILE *req = NULL; /* input stream from the REQUEST file */
3612 FILE *resp; /* output stream to the RESPONSE file */
3614 buf = PORT_ZAlloc(bufSize);
3615 if (buf == NULL) {
3616 goto loser;
3618 msg = PORT_ZAlloc(msgLen);
3619 if (msg == NULL) {
3620 goto loser;
3623 req = fopen(reqfn, "r");
3624 resp = stdout;
3625 while (fgets(buf, bufSize, req) != NULL) {
3626 if (strncmp(buf, "Mac", 3) == 0) {
3627 i = 3;
3628 while (isspace(buf[i]) || buf[i] == '=') {
3629 i++;
3631 memset(expectedHMAC, 0, HASH_LENGTH_MAX);
3632 for (j=0; isxdigit(buf[i]); i+=2,j++) {
3633 hex_to_byteval(&buf[i], &expectedHMAC[j]);
3635 if (memcmp(HMAC, expectedHMAC, TLen) != 0) {
3636 fprintf(stderr, "Generate failed:\n");
3637 fputs( " expected=", stderr);
3638 to_hex_str(buf, expectedHMAC,
3639 TLen);
3640 fputs(buf, stderr);
3641 fputs("\n generated=", stderr);
3642 to_hex_str(buf, HMAC,
3643 TLen);
3644 fputs(buf, stderr);
3645 fputc('\n', stderr);
3649 /* a comment or blank line */
3650 if (buf[0] == '#' || buf[0] == '\n') {
3651 fputs(buf, resp);
3652 continue;
3654 /* [L = Length of the MAC and HASH_type */
3655 if (buf[0] == '[') {
3656 if (strncmp(&buf[1], "L ", 1) == 0) {
3657 i = 2;
3658 while (isspace(buf[i]) || buf[i] == '=') {
3659 i++;
3661 /* HMACLen will get reused for Tlen */
3662 HMACLen = atoi(&buf[i]);
3663 hash_alg = sha_get_hashType(HMACLen*PR_BITS_PER_BYTE);
3664 if (hash_alg == HASH_AlgNULL) {
3665 goto loser;
3667 fputs(buf, resp);
3668 continue;
3671 /* Count = test iteration number*/
3672 if (strncmp(buf, "Count ", 5) == 0) {
3673 /* count can just be put into resp file */
3674 fputs(buf, resp);
3675 /* zeroize the variables for the test with this data set */
3676 keyLen = 0;
3677 TLen = 0;
3678 memset(key, 0, sizeof key);
3679 memset(msg, 0, msgLen);
3680 memset(HMAC, 0, sizeof HMAC);
3681 continue;
3683 /* KLen = Length of the Input Secret Key ... */
3684 if (strncmp(buf, "Klen", 4) == 0) {
3685 i = 4;
3686 while (isspace(buf[i]) || buf[i] == '=') {
3687 i++;
3689 keyLen = atoi(&buf[i]); /* in bytes */
3690 fputs(buf, resp);
3691 continue;
3693 /* key = the secret key for the key to MAC */
3694 if (strncmp(buf, "Key", 3) == 0) {
3695 i = 3;
3696 while (isspace(buf[i]) || buf[i] == '=') {
3697 i++;
3699 for (j=0; j< keyLen; i+=2,j++) {
3700 hex_to_byteval(&buf[i], &key[j]);
3702 fputs(buf, resp);
3704 /* TLen = Length of the calculated HMAC */
3705 if (strncmp(buf, "Tlen", 4) == 0) {
3706 i = 4;
3707 while (isspace(buf[i]) || buf[i] == '=') {
3708 i++;
3710 TLen = atoi(&buf[i]); /* in bytes */
3711 fputs(buf, resp);
3712 continue;
3714 /* MSG = to HMAC always 128 bytes for these tests */
3715 if (strncmp(buf, "Msg", 3) == 0) {
3716 i = 3;
3717 while (isspace(buf[i]) || buf[i] == '=') {
3718 i++;
3720 for (j=0; j< msgLen; i+=2,j++) {
3721 hex_to_byteval(&buf[i], &msg[j]);
3723 fputs(buf, resp);
3724 /* calculate the HMAC and output */
3725 if (hmac_calc(HMAC, HMACLen, key, keyLen,
3726 msg, msgLen, hash_alg) != SECSuccess) {
3727 goto loser;
3729 fputs("MAC = ", resp);
3730 to_hex_str(buf, HMAC, TLen);
3731 fputs(buf, resp);
3732 fputc('\n', resp);
3733 continue;
3736 loser:
3737 if (req) {
3738 fclose(req);
3740 if (buf) {
3741 PORT_ZFree(buf, bufSize);
3743 if (msg) {
3744 PORT_ZFree(msg, msgLen);
3749 * Perform the DSA Key Pair Generation Test.
3751 * reqfn is the pathname of the REQUEST file.
3753 * The output RESPONSE file is written to stdout.
3755 void
3756 dsa_keypair_test(char *reqfn)
3758 char buf[800]; /* holds one line from the input REQUEST file
3759 * or to the output RESPONSE file.
3760 * 800 to hold (384 public key (x2 for HEX) + 1'\n'
3762 FILE *dsareq; /* input stream from the REQUEST file */
3763 FILE *dsaresp; /* output stream to the RESPONSE file */
3764 int count;
3765 int N;
3766 int L;
3767 int i;
3768 PQGParams *pqg = NULL;
3769 PQGVerify *vfy = NULL;
3770 PRBool use_dsa1 = PR_FALSE;
3771 int keySizeIndex; /* index for valid key sizes */
3773 dsareq = fopen(reqfn, "r");
3774 dsaresp = stdout;
3775 while (fgets(buf, sizeof buf, dsareq) != NULL) {
3776 /* a comment or blank line */
3777 if (buf[0] == '#' || buf[0] == '\n') {
3778 fputs(buf, dsaresp);
3779 continue;
3782 /* [Mod = x] */
3783 if (buf[0] == '[') {
3784 if(pqg!=NULL) {
3785 PQG_DestroyParams(pqg);
3786 pqg = NULL;
3788 if(vfy!=NULL) {
3789 PQG_DestroyVerify(vfy);
3790 vfy = NULL;
3793 if (sscanf(buf, "[mod = L=%d, N=%d]", &L, &N) != 2) {
3794 use_dsa1 = PR_TRUE;
3795 if (sscanf(buf, "[mod = %d]", &L) != 1) {
3796 goto loser;
3799 fputs(buf, dsaresp);
3800 fputc('\n', dsaresp);
3802 if (use_dsa1) {
3803 /*************************************************************
3804 * PQG_ParamGenSeedLen doesn't take a key size, it takes an
3805 * index that points to a valid key size.
3807 keySizeIndex = PQG_PBITS_TO_INDEX(L);
3808 if(keySizeIndex == -1 || L<512 || L>1024) {
3809 fprintf(dsaresp,
3810 "DSA key size must be a multiple of 64 between 512 "
3811 "and 1024, inclusive");
3812 goto loser;
3815 /* Generate the parameters P, Q, and G */
3816 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
3817 &pqg, &vfy) != SECSuccess) {
3818 fprintf(dsaresp,
3819 "ERROR: Unable to generate PQG parameters");
3820 goto loser;
3822 } else {
3823 if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
3824 fprintf(dsaresp,
3825 "ERROR: Unable to generate PQG parameters");
3826 goto loser;
3830 /* output P, Q, and G */
3831 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
3832 fprintf(dsaresp, "P = %s\n", buf);
3833 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
3834 fprintf(dsaresp, "Q = %s\n", buf);
3835 to_hex_str(buf, pqg->base.data, pqg->base.len);
3836 fprintf(dsaresp, "G = %s\n\n", buf);
3837 continue;
3839 /* N = ...*/
3840 if (buf[0] == 'N') {
3842 if (sscanf(buf, "N = %d", &count) != 1) {
3843 goto loser;
3845 /* Generate a DSA key, and output the key pair for N times */
3846 for (i = 0; i < count; i++) {
3847 DSAPrivateKey *dsakey = NULL;
3848 if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
3849 fprintf(dsaresp, "ERROR: Unable to generate DSA key");
3850 goto loser;
3852 to_hex_str(buf, dsakey->privateValue.data,
3853 dsakey->privateValue.len);
3854 fprintf(dsaresp, "X = %s\n", buf);
3855 to_hex_str(buf, dsakey->publicValue.data,
3856 dsakey->publicValue.len);
3857 fprintf(dsaresp, "Y = %s\n\n", buf);
3858 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
3859 dsakey = NULL;
3861 continue;
3865 loser:
3866 fclose(dsareq);
3870 * pqg generation type
3872 typedef enum {
3873 FIPS186_1,/* Generate/Verify P,Q & G according to FIPS 186-1 */
3874 A_1_1_2, /* Generate Probable P & Q */
3875 A_1_1_3, /* Verify Probable P & Q */
3876 A_1_2_2, /* Verify Provable P & Q */
3877 A_2_1, /* Generate Unverifiable G */
3878 A_2_2, /* Assure Unverifiable G */
3879 A_2_3, /* Generate Verifiable G */
3880 A_2_4 /* Verify Verifiable G */
3881 } dsa_pqg_type;
3884 * Perform the DSA Domain Parameter Validation Test.
3886 * reqfn is the pathname of the REQUEST file.
3888 * The output RESPONSE file is written to stdout.
3890 void
3891 dsa_pqgver_test(char *reqfn)
3893 char buf[800]; /* holds one line from the input REQUEST file
3894 * or to the output RESPONSE file.
3895 * 800 to hold (384 public key (x2 for HEX) + P = ...
3897 FILE *dsareq; /* input stream from the REQUEST file */
3898 FILE *dsaresp; /* output stream to the RESPONSE file */
3899 int N;
3900 int L;
3901 unsigned int i, j;
3902 PQGParams pqg;
3903 PQGVerify vfy;
3904 unsigned int pghSize; /* size for p, g, and h */
3905 dsa_pqg_type type = FIPS186_1;
3907 dsareq = fopen(reqfn, "r");
3908 dsaresp = stdout;
3909 memset(&pqg, 0, sizeof(pqg));
3910 memset(&vfy, 0, sizeof(vfy));
3912 while (fgets(buf, sizeof buf, dsareq) != NULL) {
3913 /* a comment or blank line */
3914 if (buf[0] == '#' || buf[0] == '\n') {
3915 fputs(buf, dsaresp);
3916 continue;
3919 /* [A.xxxxx ] */
3920 if (buf[0] == '[' && buf[1] == 'A') {
3922 if (strncmp(&buf[1],"A.1.1.3",7) == 0) {
3923 type = A_1_1_3;
3924 } else if (strncmp(&buf[1],"A.2.2",5) == 0) {
3925 type = A_2_2;
3926 } else if (strncmp(&buf[1],"A.2.4",5) == 0) {
3927 type = A_2_4;
3928 } else if (strncmp(&buf[1],"A.1.2.2",7) == 0) {
3929 type = A_1_2_2;
3930 /* validate our output from PQGGEN */
3931 } else if (strncmp(&buf[1],"A.1.1.2",7) == 0) {
3932 type = A_2_4; /* validate PQ and G together */
3933 } else {
3934 fprintf(stderr, "Unknown dsa ver test %s\n", &buf[1]);
3935 exit(1);
3938 fputs(buf, dsaresp);
3939 continue;
3943 /* [Mod = x] */
3944 if (buf[0] == '[') {
3946 if (type == FIPS186_1) {
3947 N=160;
3948 if (sscanf(buf, "[mod = %d]", &L) != 1) {
3949 goto loser;
3951 } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
3952 goto loser;
3955 if (pqg.prime.data) { /* P */
3956 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
3958 if (pqg.subPrime.data) { /* Q */
3959 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
3961 if (pqg.base.data) { /* G */
3962 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
3964 if (vfy.seed.data) { /* seed */
3965 SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
3967 if (vfy.h.data) { /* H */
3968 SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
3971 fputs(buf, dsaresp);
3973 /*calculate the size of p, g, and h then allocate items */
3974 pghSize = L/8;
3976 pqg.base.data = vfy.h.data = NULL;
3977 vfy.seed.len = pqg.base.len = vfy.h.len = 0;
3978 SECITEM_AllocItem(NULL, &pqg.prime, pghSize);
3979 SECITEM_AllocItem(NULL, &vfy.seed, pghSize*3);
3980 if (type == A_2_2) {
3981 SECITEM_AllocItem(NULL, &vfy.h, pghSize);
3982 vfy.h.len = pghSize;
3983 } else if (type == A_2_4) {
3984 SECITEM_AllocItem(NULL, &vfy.h, 1);
3985 vfy.h.len = 1;
3987 pqg.prime.len = pghSize;
3988 /* q is always N bits */
3989 SECITEM_AllocItem(NULL, &pqg.subPrime, N/8);
3990 pqg.subPrime.len = N/8;
3991 vfy.counter = -1;
3993 continue;
3995 /* P = ... */
3996 if (buf[0] == 'P') {
3997 i = 1;
3998 while (isspace(buf[i]) || buf[i] == '=') {
3999 i++;
4001 for (j=0; j< pqg.prime.len; i+=2,j++) {
4002 hex_to_byteval(&buf[i], &pqg.prime.data[j]);
4005 fputs(buf, dsaresp);
4006 continue;
4009 /* Q = ... */
4010 if (buf[0] == 'Q') {
4011 i = 1;
4012 while (isspace(buf[i]) || buf[i] == '=') {
4013 i++;
4015 for (j=0; j< pqg.subPrime.len; i+=2,j++) {
4016 hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
4019 fputs(buf, dsaresp);
4020 continue;
4023 /* G = ... */
4024 if (buf[0] == 'G') {
4025 i = 1;
4026 if (pqg.base.data) {
4027 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
4029 SECITEM_AllocItem(NULL, &pqg.base, pghSize);
4030 while (isspace(buf[i]) || buf[i] == '=') {
4031 i++;
4033 for (j=0; j< pqg.base.len; i+=2,j++) {
4034 hex_to_byteval(&buf[i], &pqg.base.data[j]);
4037 fputs(buf, dsaresp);
4038 continue;
4041 /* Seed = ... or domain_parameter_seed = ... */
4042 if (strncmp(buf, "Seed", 4) == 0) {
4043 i = 4;
4044 } else if (strncmp(buf, "domain_parameter_seed", 21) == 0) {
4045 i = 21;
4046 } else if (strncmp(buf,"firstseed",9) == 0) {
4047 i = 9;
4048 } else {
4049 i = 0;
4051 if (i) {
4052 while (isspace(buf[i]) || buf[i] == '=') {
4053 i++;
4055 for (j=0; isxdigit(buf[i]); i+=2,j++) {
4056 hex_to_byteval(&buf[i], &vfy.seed.data[j]);
4058 vfy.seed.len = j;
4060 fputs(buf, dsaresp);
4061 if (type == A_2_4) {
4062 SECStatus result;
4064 /* Verify the Parameters */
4065 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
4066 if (rv != SECSuccess) {
4067 goto loser;
4069 if (result == SECSuccess) {
4070 fprintf(dsaresp, "Result = P\n");
4071 } else {
4072 fprintf(dsaresp, "Result = F\n");
4075 continue;
4077 if ((strncmp(buf,"pseed",5) == 0) ||
4078 (strncmp(buf,"qseed",5) == 0))
4080 i = 5;
4081 while (isspace(buf[i]) || buf[i] == '=') {
4082 i++;
4084 for (j=vfy.seed.len; isxdigit(buf[i]); i+=2,j++) {
4085 hex_to_byteval(&buf[i], &vfy.seed.data[j]);
4087 vfy.seed.len = j;
4088 fputs(buf, dsaresp);
4090 continue;
4092 if (strncmp(buf, "index", 4) == 0) {
4093 i=5;
4094 while (isspace(buf[i]) || buf[i] == '=') {
4095 i++;
4097 hex_to_byteval(&buf[i], &vfy.h.data[0]);
4098 vfy.h.len = 1;
4099 fputs(buf, dsaresp);
4102 /* c = ... or counter=*/
4103 if (buf[0] == 'c') {
4104 if (strncmp(buf,"counter", 7) == 0) {
4105 if (sscanf(buf, "counter = %u", &vfy.counter) != 1) {
4106 goto loser;
4108 } else {
4109 if (sscanf(buf, "c = %u", &vfy.counter) != 1) {
4110 goto loser;
4114 fputs(buf, dsaresp);
4115 if (type == A_1_1_3) {
4116 SECStatus result;
4117 /* only verify P and Q, we have everything now. do it */
4118 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
4119 if (rv != SECSuccess) {
4120 goto loser;
4122 if (result == SECSuccess) {
4123 fprintf(dsaresp, "Result = P\n");
4124 } else {
4125 fprintf(dsaresp, "Result = F\n");
4127 fprintf(dsaresp, "\n");
4129 continue;
4131 if (strncmp(buf,"pgen_counter", 12) == 0) {
4132 if (sscanf(buf, "pgen_counter = %u", &vfy.counter) != 1) {
4133 goto loser;
4135 fputs(buf, dsaresp);
4136 continue;
4138 if (strncmp(buf,"qgen_counter", 12) == 0) {
4139 fputs(buf, dsaresp);
4140 if (type == A_1_2_2) {
4141 SECStatus result;
4142 /* only verify P and Q, we have everything now. do it */
4143 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
4144 if (rv != SECSuccess) {
4145 goto loser;
4147 if (result == SECSuccess) {
4148 fprintf(dsaresp, "Result = P\n");
4149 } else {
4150 fprintf(dsaresp, "Result = F\n");
4152 fprintf(dsaresp, "\n");
4154 continue;
4156 /* H = ... */
4157 if (buf[0] == 'H') {
4158 SECStatus rv, result = SECFailure;
4160 i = 1;
4161 while (isspace(buf[i]) || buf[i] == '=') {
4162 i++;
4164 for (j=0; isxdigit(buf[i]); i+=2,j++) {
4165 hex_to_byteval(&buf[i], &vfy.h.data[j]);
4167 vfy.h.len = j;
4168 fputs(buf, dsaresp);
4170 /* this should be a byte value. Remove the leading zeros. If
4171 * it doesn't reduce to a byte, PQG_VerifyParams will catch it
4172 if (type == A_2_2) {
4173 data_save = vfy.h.data;
4174 while(vfy.h.data[0] && (vfy.h.len > 1)) {
4175 vfy.h.data++;
4176 vfy.h.len--;
4178 } */
4180 /* Verify the Parameters */
4181 rv = PQG_VerifyParams(&pqg, &vfy, &result);
4182 if (rv != SECSuccess) {
4183 goto loser;
4185 if (result == SECSuccess) {
4186 fprintf(dsaresp, "Result = P\n");
4187 } else {
4188 fprintf(dsaresp, "Result = F\n");
4190 fprintf(dsaresp, "\n");
4191 continue;
4194 loser:
4195 fclose(dsareq);
4196 if (pqg.prime.data) { /* P */
4197 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
4199 if (pqg.subPrime.data) { /* Q */
4200 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
4202 if (pqg.base.data) { /* G */
4203 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
4205 if (vfy.seed.data) { /* seed */
4206 SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
4208 if (vfy.h.data) { /* H */
4209 SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
4215 * Perform the DSA Public Key Validation Test.
4217 * reqfn is the pathname of the REQUEST file.
4219 * The output RESPONSE file is written to stdout.
4221 void
4222 dsa_pqggen_test(char *reqfn)
4224 char buf[800]; /* holds one line from the input REQUEST file
4225 * or to the output RESPONSE file.
4226 * 800 to hold seed = (384 public key (x2 for HEX)
4228 FILE *dsareq; /* input stream from the REQUEST file */
4229 FILE *dsaresp; /* output stream to the RESPONSE file */
4230 int count; /* number of times to generate parameters */
4231 int N;
4232 int L;
4233 int i;
4234 unsigned int j;
4235 PQGParams *pqg = NULL;
4236 PQGVerify *vfy = NULL;
4237 unsigned int keySizeIndex;
4238 dsa_pqg_type type = FIPS186_1;
4240 dsareq = fopen(reqfn, "r");
4241 dsaresp = stdout;
4242 while (fgets(buf, sizeof buf, dsareq) != NULL) {
4243 /* a comment or blank line */
4244 if (buf[0] == '#' || buf[0] == '\n') {
4245 fputs(buf, dsaresp);
4246 continue;
4249 /* [A.xxxxx ] */
4250 if (buf[0] == '[' && buf[1] == 'A') {
4251 if (strncmp(&buf[1],"A.1.1.2",7) == 0) {
4252 type = A_1_1_2;
4253 } else if (strncmp(&buf[1],"A.2.1",5) == 0) {
4254 fprintf(stderr, "NSS only Generates G with P&Q\n");
4255 exit(1);
4256 } else if (strncmp(&buf[1],"A.2.3",5) == 0) {
4257 fprintf(stderr, "NSS only Generates G with P&Q\n");
4258 exit(1);
4259 } else if (strncmp(&buf[1],"A.1.2.1",7) == 0) {
4260 fprintf(stderr, "NSS does not support Shawe-Taylor Primes\n");
4261 exit(1);
4262 } else {
4263 fprintf(stderr, "Unknown dsa ver test %s\n", &buf[1]);
4264 exit(1);
4266 fputs(buf, dsaresp);
4267 continue;
4270 /* [Mod = ... ] */
4271 if (buf[0] == '[') {
4273 if (type == FIPS186_1) {
4274 N=160;
4275 if (sscanf(buf, "[mod = %d]", &L) != 1) {
4276 goto loser;
4278 } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
4279 goto loser;
4282 fputs(buf, dsaresp);
4283 fputc('\n', dsaresp);
4285 if (type == FIPS186_1) {
4286 /************************************************************
4287 * PQG_ParamGenSeedLen doesn't take a key size, it takes an
4288 * index that points to a valid key size.
4290 keySizeIndex = PQG_PBITS_TO_INDEX(L);
4291 if(keySizeIndex == -1 || L<512 || L>1024) {
4292 fprintf(dsaresp,
4293 "DSA key size must be a multiple of 64 between 512 "
4294 "and 1024, inclusive");
4295 goto loser;
4298 continue;
4300 /* N = ... */
4301 if (buf[0] == 'N') {
4302 if (sscanf(buf, "N = %d", &count) != 1) {
4303 goto loser;
4305 for (i = 0; i < count; i++) {
4306 SECStatus rv;
4308 if (type == FIPS186_1) {
4309 rv = PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
4310 &pqg, &vfy);
4311 } else {
4312 rv = PQG_ParamGenV2(L, N, N, &pqg, &vfy);
4314 if (rv != SECSuccess) {
4315 fprintf(dsaresp,
4316 "ERROR: Unable to generate PQG parameters");
4317 goto loser;
4319 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
4320 fprintf(dsaresp, "P = %s\n", buf);
4321 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
4322 fprintf(dsaresp, "Q = %s\n", buf);
4323 to_hex_str(buf, pqg->base.data, pqg->base.len);
4324 fprintf(dsaresp, "G = %s\n", buf);
4325 if (type == FIPS186_1) {
4326 to_hex_str(buf, vfy->seed.data, vfy->seed.len);
4327 fprintf(dsaresp, "Seed = %s\n", buf);
4328 fprintf(dsaresp, "c = %d\n", vfy->counter);
4329 to_hex_str(buf, vfy->h.data, vfy->h.len);
4330 fputs("H = ", dsaresp);
4331 for (j=vfy->h.len; j< pqg->prime.len; j++) {
4332 fprintf(dsaresp, "00");
4334 fprintf(dsaresp, "%s\n", buf);
4335 } else {
4336 fprintf(dsaresp, "counter = %d\n", vfy->counter);
4337 fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]);
4338 to_hex_str(buf, vfy->seed.data, vfy->seed.len);
4339 fprintf(dsaresp, "domain_parameter_seed = %s\n", buf);
4341 fputc('\n', dsaresp);
4342 if(pqg!=NULL) {
4343 PQG_DestroyParams(pqg);
4344 pqg = NULL;
4346 if(vfy!=NULL) {
4347 PQG_DestroyVerify(vfy);
4348 vfy = NULL;
4352 continue;
4356 loser:
4357 fclose(dsareq);
4358 if(pqg!=NULL) {
4359 PQG_DestroyParams(pqg);
4361 if(vfy!=NULL) {
4362 PQG_DestroyVerify(vfy);
4368 * Perform the DSA Signature Generation Test.
4370 * reqfn is the pathname of the REQUEST file.
4372 * The output RESPONSE file is written to stdout.
4374 void
4375 dsa_siggen_test(char *reqfn)
4377 char buf[800]; /* holds one line from the input REQUEST file
4378 * or to the output RESPONSE file.
4379 * max for Msg = ....
4381 FILE *dsareq; /* input stream from the REQUEST file */
4382 FILE *dsaresp; /* output stream to the RESPONSE file */
4383 int modulus;
4384 int L;
4385 int N;
4386 int i, j;
4387 PRBool use_dsa1 = PR_FALSE;
4388 PQGParams *pqg = NULL;
4389 PQGVerify *vfy = NULL;
4390 DSAPrivateKey *dsakey = NULL;
4391 int keySizeIndex; /* index for valid key sizes */
4392 unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */
4393 unsigned char sig[DSA_MAX_SIGNATURE_LEN];
4394 SECItem digest, signature;
4395 HASH_HashType hashType = HASH_AlgNULL;
4396 int hashNum = 0;
4398 dsareq = fopen(reqfn, "r");
4399 dsaresp = stdout;
4401 while (fgets(buf, sizeof buf, dsareq) != NULL) {
4402 /* a comment or blank line */
4403 if (buf[0] == '#' || buf[0] == '\n') {
4404 fputs(buf, dsaresp);
4405 continue;
4408 /* [Mod = x] */
4409 if (buf[0] == '[') {
4410 if(pqg!=NULL) {
4411 PQG_DestroyParams(pqg);
4412 pqg = NULL;
4414 if(vfy!=NULL) {
4415 PQG_DestroyVerify(vfy);
4416 vfy = NULL;
4418 if (dsakey != NULL) {
4419 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
4420 dsakey = NULL;
4423 if (sscanf(buf, "[mod = L=%d, N=%d, SHA-%d]", &L, & N,
4424 &hashNum) != 3) {
4425 use_dsa1 = PR_TRUE;
4426 hashNum = 1;
4427 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
4428 goto loser;
4431 fputs(buf, dsaresp);
4432 fputc('\n', dsaresp);
4434 /****************************************************************
4435 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
4436 * that points to a valid key size.
4438 if (use_dsa1) {
4439 keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
4440 if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
4441 fprintf(dsaresp,
4442 "DSA key size must be a multiple of 64 between 512 "
4443 "and 1024, inclusive");
4444 goto loser;
4446 /* Generate PQG and output PQG */
4447 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
4448 &pqg, &vfy) != SECSuccess) {
4449 fprintf(dsaresp,
4450 "ERROR: Unable to generate PQG parameters");
4451 goto loser;
4453 } else {
4454 if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
4455 fprintf(dsaresp,
4456 "ERROR: Unable to generate PQG parameters");
4457 goto loser;
4460 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
4461 fprintf(dsaresp, "P = %s\n", buf);
4462 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
4463 fprintf(dsaresp, "Q = %s\n", buf);
4464 to_hex_str(buf, pqg->base.data, pqg->base.len);
4465 fprintf(dsaresp, "G = %s\n", buf);
4467 /* create DSA Key */
4468 if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
4469 fprintf(dsaresp, "ERROR: Unable to generate DSA key");
4470 goto loser;
4473 hashType = sha_get_hashType(hashNum);
4474 if (hashType == HASH_AlgNULL) {
4475 fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)",hashNum);
4476 goto loser;
4478 continue;
4481 /* Msg = ... */
4482 if (strncmp(buf, "Msg", 3) == 0) {
4483 unsigned char msg[128]; /* MAX msg 128 */
4484 unsigned int len = 0;
4486 if (hashType == HASH_AlgNULL) {
4487 fprintf(dsaresp, "ERROR: Hash Alg not set");
4488 goto loser;
4491 memset(hashBuf, 0, sizeof hashBuf);
4492 memset(sig, 0, sizeof sig);
4494 i = 3;
4495 while (isspace(buf[i]) || buf[i] == '=') {
4496 i++;
4498 for (j=0; isxdigit(buf[i]); i+=2,j++) {
4499 hex_to_byteval(&buf[i], &msg[j]);
4501 if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) {
4502 fprintf(dsaresp, "ERROR: Unable to generate SHA% digest",
4503 hashNum);
4504 goto loser;
4508 digest.type = siBuffer;
4509 digest.data = hashBuf;
4510 digest.len = fips_hashLen(hashType);
4511 signature.type = siBuffer;
4512 signature.data = sig;
4513 signature.len = sizeof sig;
4515 if (DSA_SignDigest(dsakey, &signature, &digest) != SECSuccess) {
4516 fprintf(dsaresp, "ERROR: Unable to generate DSA signature");
4517 goto loser;
4519 len = signature.len;
4520 if (len%2 != 0) {
4521 goto loser;
4523 len = len/2;
4525 /* output the orginal Msg, and generated Y, R, and S */
4526 fputs(buf, dsaresp);
4527 to_hex_str(buf, dsakey->publicValue.data,
4528 dsakey->publicValue.len);
4529 fprintf(dsaresp, "Y = %s\n", buf);
4530 to_hex_str(buf, &signature.data[0], len);
4531 fprintf(dsaresp, "R = %s\n", buf);
4532 to_hex_str(buf, &signature.data[len], len);
4533 fprintf(dsaresp, "S = %s\n", buf);
4534 fputc('\n', dsaresp);
4535 continue;
4539 loser:
4540 fclose(dsareq);
4541 if(pqg != NULL) {
4542 PQG_DestroyParams(pqg);
4543 pqg = NULL;
4545 if(vfy != NULL) {
4546 PQG_DestroyVerify(vfy);
4547 vfy = NULL;
4549 if (dsakey) {
4550 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
4551 dsakey = NULL;
4556 * Perform the DSA Signature Verification Test.
4558 * reqfn is the pathname of the REQUEST file.
4560 * The output RESPONSE file is written to stdout.
4562 void
4563 dsa_sigver_test(char *reqfn)
4565 char buf[800]; /* holds one line from the input REQUEST file
4566 * or to the output RESPONSE file.
4567 * max for Msg = ....
4569 FILE *dsareq; /* input stream from the REQUEST file */
4570 FILE *dsaresp; /* output stream to the RESPONSE file */
4571 int L;
4572 int N;
4573 unsigned int i, j;
4574 SECItem digest, signature;
4575 DSAPublicKey pubkey;
4576 unsigned int pgySize; /* size for p, g, and y */
4577 unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */
4578 unsigned char sig[DSA_MAX_SIGNATURE_LEN];
4579 HASH_HashType hashType = HASH_AlgNULL;
4580 int hashNum = 0;
4582 dsareq = fopen(reqfn, "r");
4583 dsaresp = stdout;
4584 memset(&pubkey, 0, sizeof(pubkey));
4586 while (fgets(buf, sizeof buf, dsareq) != NULL) {
4587 /* a comment or blank line */
4588 if (buf[0] == '#' || buf[0] == '\n') {
4589 fputs(buf, dsaresp);
4590 continue;
4593 /* [Mod = x] */
4594 if (buf[0] == '[') {
4596 if (sscanf(buf, "[mod = L=%d, N=%d, SHA-%d]", &L, & N,
4597 &hashNum) != 3) {
4598 N=160;
4599 hashNum = 1;
4600 if (sscanf(buf, "[mod = %d]", &L) != 1) {
4601 goto loser;
4605 if (pubkey.params.prime.data) { /* P */
4606 SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
4608 if (pubkey.params.subPrime.data) { /* Q */
4609 SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
4611 if (pubkey.params.base.data) { /* G */
4612 SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
4614 if (pubkey.publicValue.data) { /* Y */
4615 SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
4617 fputs(buf, dsaresp);
4619 /* calculate the size of p, g, and y then allocate items */
4620 pgySize = L/8;
4621 SECITEM_AllocItem(NULL, &pubkey.params.prime, pgySize);
4622 SECITEM_AllocItem(NULL, &pubkey.params.base, pgySize);
4623 SECITEM_AllocItem(NULL, &pubkey.publicValue, pgySize);
4624 pubkey.params.prime.len = pubkey.params.base.len = pgySize;
4625 pubkey.publicValue.len = pgySize;
4627 /* q always N/8 bytes */
4628 SECITEM_AllocItem(NULL, &pubkey.params.subPrime, N/8);
4629 pubkey.params.subPrime.len = N/8;
4631 hashType = sha_get_hashType(hashNum);
4632 if (hashType == HASH_AlgNULL) {
4633 fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)",hashNum);
4634 goto loser;
4637 continue;
4639 /* P = ... */
4640 if (buf[0] == 'P') {
4641 i = 1;
4642 while (isspace(buf[i]) || buf[i] == '=') {
4643 i++;
4645 memset(pubkey.params.prime.data, 0, pubkey.params.prime.len);
4646 for (j=0; j< pubkey.params.prime.len; i+=2,j++) {
4647 hex_to_byteval(&buf[i], &pubkey.params.prime.data[j]);
4650 fputs(buf, dsaresp);
4651 continue;
4654 /* Q = ... */
4655 if (buf[0] == 'Q') {
4656 i = 1;
4657 while (isspace(buf[i]) || buf[i] == '=') {
4658 i++;
4660 memset(pubkey.params.subPrime.data, 0, pubkey.params.subPrime.len);
4661 for (j=0; j< pubkey.params.subPrime.len; i+=2,j++) {
4662 hex_to_byteval(&buf[i], &pubkey.params.subPrime.data[j]);
4665 fputs(buf, dsaresp);
4666 continue;
4669 /* G = ... */
4670 if (buf[0] == 'G') {
4671 i = 1;
4672 while (isspace(buf[i]) || buf[i] == '=') {
4673 i++;
4675 memset(pubkey.params.base.data, 0, pubkey.params.base.len);
4676 for (j=0; j< pubkey.params.base.len; i+=2,j++) {
4677 hex_to_byteval(&buf[i], &pubkey.params.base.data[j]);
4680 fputs(buf, dsaresp);
4681 continue;
4684 /* Msg = ... */
4685 if (strncmp(buf, "Msg", 3) == 0) {
4686 unsigned char msg[128]; /* MAX msg 128 */
4687 memset(hashBuf, 0, sizeof hashBuf);
4689 if (hashType == HASH_AlgNULL) {
4690 fprintf(dsaresp, "ERROR: Hash Alg not set");
4691 goto loser;
4694 i = 3;
4695 while (isspace(buf[i]) || buf[i] == '=') {
4696 i++;
4698 for (j=0; isxdigit(buf[i]); i+=2,j++) {
4699 hex_to_byteval(&buf[i], &msg[j]);
4701 if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) {
4702 fprintf(dsaresp, "ERROR: Unable to generate SHA-%d digest",
4703 hashNum);
4704 goto loser;
4707 fputs(buf, dsaresp);
4708 continue;
4711 /* Y = ... */
4712 if (buf[0] == 'Y') {
4713 i = 1;
4714 while (isspace(buf[i]) || buf[i] == '=') {
4715 i++;
4717 memset(pubkey.publicValue.data, 0, pubkey.params.subPrime.len);
4718 for (j=0; j< pubkey.publicValue.len; i+=2,j++) {
4719 hex_to_byteval(&buf[i], &pubkey.publicValue.data[j]);
4722 fputs(buf, dsaresp);
4723 continue;
4726 /* R = ... */
4727 if (buf[0] == 'R') {
4728 memset(sig, 0, sizeof sig);
4729 i = 1;
4730 while (isspace(buf[i]) || buf[i] == '=') {
4731 i++;
4733 for (j=0; j< pubkey.params.subPrime.len; i+=2,j++) {
4734 hex_to_byteval(&buf[i], &sig[j]);
4737 fputs(buf, dsaresp);
4738 continue;
4741 /* S = ... */
4742 if (buf[0] == 'S') {
4743 if (hashType == HASH_AlgNULL) {
4744 fprintf(dsaresp, "ERROR: Hash Alg not set");
4745 goto loser;
4748 i = 1;
4749 while (isspace(buf[i]) || buf[i] == '=') {
4750 i++;
4752 for (j=pubkey.params.subPrime.len;
4753 j< pubkey.params.subPrime.len*2; i+=2,j++) {
4754 hex_to_byteval(&buf[i], &sig[j]);
4756 fputs(buf, dsaresp);
4758 digest.type = siBuffer;
4759 digest.data = hashBuf;
4760 digest.len = fips_hashLen(hashType);
4761 signature.type = siBuffer;
4762 signature.data = sig;
4763 signature.len = pubkey.params.subPrime.len*2;
4765 if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) {
4766 fprintf(dsaresp, "Result = P\n");
4767 } else {
4768 fprintf(dsaresp, "Result = F\n");
4770 fprintf(dsaresp, "\n");
4771 continue;
4774 loser:
4775 fclose(dsareq);
4776 if (pubkey.params.prime.data) { /* P */
4777 SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
4779 if (pubkey.params.subPrime.data) { /* Q */
4780 SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
4782 if (pubkey.params.base.data) { /* G */
4783 SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
4785 if (pubkey.publicValue.data) { /* Y */
4786 SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
4791 * Perform the RSA Signature Generation Test.
4793 * reqfn is the pathname of the REQUEST file.
4795 * The output RESPONSE file is written to stdout.
4797 void
4798 rsa_siggen_test(char *reqfn)
4800 char buf[2*RSA_MAX_TEST_MODULUS_BYTES+1];
4801 /* buf holds one line from the input REQUEST file
4802 * or to the output RESPONSE file.
4803 * 2x for HEX output + 1 for \n
4805 FILE *rsareq; /* input stream from the REQUEST file */
4806 FILE *rsaresp; /* output stream to the RESPONSE file */
4807 int i, j;
4808 unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
4809 unsigned int shaLength = 0; /* length of SHA */
4810 HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
4811 SECOidTag shaOid = SEC_OID_UNKNOWN;
4812 int modulus; /* the Modulus size */
4813 int publicExponent = DEFAULT_RSA_PUBLIC_EXPONENT;
4814 SECItem pe = {0, 0, 0 };
4815 unsigned char pubEx[4];
4816 int peCount = 0;
4818 RSAPrivateKey *rsaBlapiPrivKey = NULL; /* holds RSA private and
4819 * public keys */
4820 RSAPublicKey *rsaBlapiPublicKey = NULL; /* hold RSA public key */
4822 rsareq = fopen(reqfn, "r");
4823 rsaresp = stdout;
4825 /* calculate the exponent */
4826 for (i=0; i < 4; i++) {
4827 if (peCount || (publicExponent &
4828 ((unsigned long)0xff000000L >> (i*8)))) {
4829 pubEx[peCount] =
4830 (unsigned char)((publicExponent >> (3-i)*8) & 0xff);
4831 peCount++;
4834 pe.len = peCount;
4835 pe.data = &pubEx[0];
4836 pe.type = siBuffer;
4838 while (fgets(buf, sizeof buf, rsareq) != NULL) {
4839 /* a comment or blank line */
4840 if (buf[0] == '#' || buf[0] == '\n') {
4841 fputs(buf, rsaresp);
4842 continue;
4845 /* [mod = ...] */
4846 if (buf[0] == '[') {
4848 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
4849 goto loser;
4851 if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
4852 fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
4853 goto loser;
4856 fputs(buf, rsaresp);
4858 if (rsaBlapiPrivKey != NULL) {
4859 PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
4860 rsaBlapiPrivKey = NULL;
4861 rsaBlapiPublicKey = NULL;
4864 rsaBlapiPrivKey = RSA_NewKey(modulus, &pe);
4865 if (rsaBlapiPrivKey == NULL) {
4866 fprintf(rsaresp, "Error unable to create RSA key\n");
4867 goto loser;
4870 to_hex_str(buf, rsaBlapiPrivKey->modulus.data,
4871 rsaBlapiPrivKey->modulus.len);
4872 fprintf(rsaresp, "\nn = %s\n\n", buf);
4873 to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data,
4874 rsaBlapiPrivKey->publicExponent.len);
4875 fprintf(rsaresp, "e = %s\n", buf);
4876 /* convert private key to public key. Memory
4877 * is freed with private key's arena */
4878 rsaBlapiPublicKey = (RSAPublicKey *)PORT_ArenaAlloc(
4879 rsaBlapiPrivKey->arena,
4880 sizeof(RSAPublicKey));
4882 rsaBlapiPublicKey->modulus.len = rsaBlapiPrivKey->modulus.len;
4883 rsaBlapiPublicKey->modulus.data = rsaBlapiPrivKey->modulus.data;
4884 rsaBlapiPublicKey->publicExponent.len =
4885 rsaBlapiPrivKey->publicExponent.len;
4886 rsaBlapiPublicKey->publicExponent.data =
4887 rsaBlapiPrivKey->publicExponent.data;
4888 continue;
4891 /* SHAAlg = ... */
4892 if (strncmp(buf, "SHAAlg", 6) == 0) {
4893 i = 6;
4894 while (isspace(buf[i]) || buf[i] == '=') {
4895 i++;
4897 /* set the SHA Algorithm */
4898 if (strncmp(&buf[i], "SHA1", 4) == 0) {
4899 shaAlg = HASH_AlgSHA1;
4900 } else if (strncmp(&buf[i], "SHA224", 6) == 0) {
4901 shaAlg = HASH_AlgSHA224;
4902 } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
4903 shaAlg = HASH_AlgSHA256;
4904 } else if (strncmp(&buf[i], "SHA384", 6)== 0) {
4905 shaAlg = HASH_AlgSHA384;
4906 } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
4907 shaAlg = HASH_AlgSHA512;
4908 } else {
4909 fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
4910 goto loser;
4912 fputs(buf, rsaresp);
4913 continue;
4916 /* Msg = ... */
4917 if (strncmp(buf, "Msg", 3) == 0) {
4919 unsigned char msg[128]; /* MAX msg 128 */
4920 unsigned int rsa_bytes_signed;
4921 unsigned char rsa_computed_signature[RSA_MAX_TEST_MODULUS_BYTES];
4922 SECStatus rv = SECFailure;
4923 NSSLOWKEYPublicKey * rsa_public_key;
4924 NSSLOWKEYPrivateKey * rsa_private_key;
4925 NSSLOWKEYPrivateKey low_RSA_private_key = { NULL,
4926 NSSLOWKEYRSAKey, };
4927 NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
4928 NSSLOWKEYRSAKey, };
4930 low_RSA_private_key.u.rsa = *rsaBlapiPrivKey;
4931 low_RSA_public_key.u.rsa = *rsaBlapiPublicKey;
4933 rsa_private_key = &low_RSA_private_key;
4934 rsa_public_key = &low_RSA_public_key;
4936 memset(sha, 0, sizeof sha);
4937 memset(msg, 0, sizeof msg);
4938 rsa_bytes_signed = 0;
4939 memset(rsa_computed_signature, 0, sizeof rsa_computed_signature);
4941 i = 3;
4942 while (isspace(buf[i]) || buf[i] == '=') {
4943 i++;
4945 for (j=0; isxdigit(buf[i]) && j < sizeof(msg); i+=2,j++) {
4946 hex_to_byteval(&buf[i], &msg[j]);
4948 shaLength = fips_hashLen(shaAlg);
4949 if (fips_hashBuf(shaAlg,sha,msg,j) != SECSuccess) {
4950 if (shaLength == 0) {
4951 fprintf(rsaresp, "ERROR: SHAAlg not defined.");
4953 fprintf(rsaresp, "ERROR: Unable to generate SHA%x",
4954 shaLength == 160 ? 1 : shaLength);
4955 goto loser;
4957 shaOid = fips_hashOid(shaAlg);
4959 /* Perform RSA signature with the RSA private key. */
4960 rv = RSA_HashSign( shaOid,
4961 rsa_private_key,
4962 rsa_computed_signature,
4963 &rsa_bytes_signed,
4964 nsslowkey_PrivateModulusLen(rsa_private_key),
4965 sha,
4966 shaLength);
4968 if( rv != SECSuccess ) {
4969 fprintf(rsaresp, "ERROR: RSA_HashSign failed");
4970 goto loser;
4973 /* Output the signature */
4974 fputs(buf, rsaresp);
4975 to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed);
4976 fprintf(rsaresp, "S = %s\n", buf);
4978 /* Perform RSA verification with the RSA public key. */
4979 rv = RSA_HashCheckSign( shaOid,
4980 rsa_public_key,
4981 rsa_computed_signature,
4982 rsa_bytes_signed,
4983 sha,
4984 shaLength);
4985 if( rv != SECSuccess ) {
4986 fprintf(rsaresp, "ERROR: RSA_HashCheckSign failed");
4987 goto loser;
4989 continue;
4992 loser:
4993 fclose(rsareq);
4995 if (rsaBlapiPrivKey != NULL) {
4996 /* frees private and public key */
4997 PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
4998 rsaBlapiPrivKey = NULL;
4999 rsaBlapiPublicKey = NULL;
5004 * Perform the RSA Signature Verification Test.
5006 * reqfn is the pathname of the REQUEST file.
5008 * The output RESPONSE file is written to stdout.
5010 void
5011 rsa_sigver_test(char *reqfn)
5013 char buf[2*RSA_MAX_TEST_MODULUS_BYTES+7];
5014 /* buf holds one line from the input REQUEST file
5015 * or to the output RESPONSE file.
5016 * s = 2x for HEX output + 1 for \n
5018 FILE *rsareq; /* input stream from the REQUEST file */
5019 FILE *rsaresp; /* output stream to the RESPONSE file */
5020 int i, j;
5021 unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
5022 unsigned int shaLength = 0; /* actual length of the digest */
5023 HASH_HashType shaAlg = HASH_AlgNULL;
5024 SECOidTag shaOid = SEC_OID_UNKNOWN;
5025 int modulus = 0; /* the Modulus size */
5026 unsigned char signature[513]; /* largest signature size + '\n' */
5027 unsigned int signatureLength = 0; /* actual length of the signature */
5028 PRBool keyvalid = PR_TRUE;
5030 RSAPublicKey rsaBlapiPublicKey; /* hold RSA public key */
5032 rsareq = fopen(reqfn, "r");
5033 rsaresp = stdout;
5034 memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey));
5036 while (fgets(buf, sizeof buf, rsareq) != NULL) {
5037 /* a comment or blank line */
5038 if (buf[0] == '#' || buf[0] == '\n') {
5039 fputs(buf, rsaresp);
5040 continue;
5043 /* [Mod = ...] */
5044 if (buf[0] == '[') {
5045 unsigned int flen; /* length in bytes of the field size */
5047 if (rsaBlapiPublicKey.modulus.data) { /* n */
5048 SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
5050 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
5051 goto loser;
5054 if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
5055 fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
5056 goto loser;
5059 fputs(buf, rsaresp);
5061 signatureLength = flen = modulus/8;
5063 SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.modulus, flen);
5064 if (rsaBlapiPublicKey.modulus.data == NULL) {
5065 goto loser;
5067 continue;
5070 /* n = ... modulus */
5071 if (buf[0] == 'n') {
5072 i = 1;
5073 while (isspace(buf[i]) || buf[i] == '=') {
5074 i++;
5076 keyvalid = from_hex_str(&rsaBlapiPublicKey.modulus.data[0],
5077 rsaBlapiPublicKey.modulus.len,
5078 &buf[i]);
5080 if (!keyvalid) {
5081 fprintf(rsaresp, "ERROR: rsa_sigver n not valid.\n");
5082 goto loser;
5084 fputs(buf, rsaresp);
5085 continue;
5088 /* SHAAlg = ... */
5089 if (strncmp(buf, "SHAAlg", 6) == 0) {
5090 i = 6;
5091 while (isspace(buf[i]) || buf[i] == '=') {
5092 i++;
5094 /* set the SHA Algorithm */
5095 if (strncmp(&buf[i], "SHA1", 4) == 0) {
5096 shaAlg = HASH_AlgSHA1;
5097 } else if (strncmp(&buf[i], "SHA224", 6) == 0) {
5098 shaAlg = HASH_AlgSHA224;
5099 } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
5100 shaAlg = HASH_AlgSHA256;
5101 } else if (strncmp(&buf[i], "SHA384", 6) == 0) {
5102 shaAlg = HASH_AlgSHA384;
5103 } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
5104 shaAlg = HASH_AlgSHA512;
5105 } else {
5106 fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
5107 goto loser;
5109 fputs(buf, rsaresp);
5110 continue;
5113 /* e = ... public Key */
5114 if (buf[0] == 'e') {
5115 unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES];
5116 unsigned char t;
5118 memset(data, 0, sizeof data);
5120 if (rsaBlapiPublicKey.publicExponent.data) { /* e */
5121 SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
5124 i = 1;
5125 while (isspace(buf[i]) || buf[i] == '=') {
5126 i++;
5128 /* skip leading zero's */
5129 while (isxdigit(buf[i])) {
5130 hex_to_byteval(&buf[i], &t);
5131 if (t == 0) {
5132 i+=2;
5133 } else break;
5136 /* get the exponent */
5137 for (j=0; isxdigit(buf[i]) && j < sizeof data; i+=2,j++) {
5138 hex_to_byteval(&buf[i], &data[j]);
5141 if (j == 0) { j = 1; } /* to handle 1 byte length exponents */
5143 SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.publicExponent, j);
5144 if (rsaBlapiPublicKey.publicExponent.data == NULL) {
5145 goto loser;
5148 for (i=0; i < j; i++) {
5149 rsaBlapiPublicKey.publicExponent.data[i] = data[i];
5152 fputs(buf, rsaresp);
5153 continue;
5156 /* Msg = ... */
5157 if (strncmp(buf, "Msg", 3) == 0) {
5158 unsigned char msg[128]; /* MAX msg 128 */
5160 memset(sha, 0, sizeof sha);
5161 memset(msg, 0, sizeof msg);
5163 i = 3;
5164 while (isspace(buf[i]) || buf[i] == '=') {
5165 i++;
5168 for (j=0; isxdigit(buf[i]) && j < sizeof msg; i+=2,j++) {
5169 hex_to_byteval(&buf[i], &msg[j]);
5172 shaLength = fips_hashLen(shaAlg);
5173 if (fips_hashBuf(shaAlg,sha,msg,j) != SECSuccess) {
5174 if (shaLength == 0) {
5175 fprintf(rsaresp, "ERROR: SHAAlg not defined.");
5177 fprintf(rsaresp, "ERROR: Unable to generate SHA%x",
5178 shaLength == 160 ? 1 : shaLength);
5179 goto loser;
5182 fputs(buf, rsaresp);
5183 continue;
5187 /* S = ... */
5188 if (buf[0] == 'S') {
5189 SECStatus rv = SECFailure;
5190 NSSLOWKEYPublicKey * rsa_public_key;
5191 NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
5192 NSSLOWKEYRSAKey, };
5194 /* convert to a low RSA public key */
5195 low_RSA_public_key.u.rsa = rsaBlapiPublicKey;
5196 rsa_public_key = &low_RSA_public_key;
5198 memset(signature, 0, sizeof(signature));
5199 i = 1;
5200 while (isspace(buf[i]) || buf[i] == '=') {
5201 i++;
5204 for (j=0; isxdigit(buf[i]) && j < sizeof signature; i+=2,j++) {
5205 hex_to_byteval(&buf[i], &signature[j]);
5208 signatureLength = j;
5209 fputs(buf, rsaresp);
5211 /* Perform RSA verification with the RSA public key. */
5212 rv = RSA_HashCheckSign( shaOid,
5213 rsa_public_key,
5214 signature,
5215 signatureLength,
5216 sha,
5217 shaLength);
5218 if( rv == SECSuccess ) {
5219 fputs("Result = P\n", rsaresp);
5220 } else {
5221 fputs("Result = F\n", rsaresp);
5223 continue;
5226 loser:
5227 fclose(rsareq);
5228 if (rsaBlapiPublicKey.modulus.data) { /* n */
5229 SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
5231 if (rsaBlapiPublicKey.publicExponent.data) { /* e */
5232 SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
5236 int main(int argc, char **argv)
5238 if (argc < 2) exit (-1);
5240 RNG_RNGInit();
5241 SECOID_Init();
5243 /*************/
5244 /* TDEA */
5245 /*************/
5246 if (strcmp(argv[1], "tdea") == 0) {
5247 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
5248 if (strcmp(argv[2], "kat") == 0) {
5249 /* Known Answer Test (KAT) */
5250 tdea_kat_mmt(argv[4]);
5251 } else if (strcmp(argv[2], "mmt") == 0) {
5252 /* Multi-block Message Test (MMT) */
5253 tdea_kat_mmt(argv[4]);
5254 } else if (strcmp(argv[2], "mct") == 0) {
5255 /* Monte Carlo Test (MCT) */
5256 if (strcmp(argv[3], "ecb") == 0) {
5257 /* ECB mode */
5258 tdea_mct(NSS_DES_EDE3, argv[4]);
5259 } else if (strcmp(argv[3], "cbc") == 0) {
5260 /* CBC mode */
5261 tdea_mct(NSS_DES_EDE3_CBC, argv[4]);
5264 /*************/
5265 /* AES */
5266 /*************/
5267 } else if (strcmp(argv[1], "aes") == 0) {
5268 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
5269 if ( strcmp(argv[2], "kat") == 0) {
5270 /* Known Answer Test (KAT) */
5271 aes_kat_mmt(argv[4]);
5272 } else if (strcmp(argv[2], "mmt") == 0) {
5273 /* Multi-block Message Test (MMT) */
5274 aes_kat_mmt(argv[4]);
5275 } else if (strcmp(argv[2], "mct") == 0) {
5276 /* Monte Carlo Test (MCT) */
5277 if ( strcmp(argv[3], "ecb") == 0) {
5278 /* ECB mode */
5279 aes_ecb_mct(argv[4]);
5280 } else if (strcmp(argv[3], "cbc") == 0) {
5281 /* CBC mode */
5282 aes_cbc_mct(argv[4]);
5285 /*************/
5286 /* SHA */
5287 /*************/
5288 } else if (strcmp(argv[1], "sha") == 0) {
5289 sha_test(argv[2]);
5290 /*************/
5291 /* RSA */
5292 /*************/
5293 } else if (strcmp(argv[1], "rsa") == 0) {
5294 /* argv[2]=siggen|sigver */
5295 /* argv[3]=<test name>.req */
5296 if (strcmp(argv[2], "siggen") == 0) {
5297 /* Signature Generation Test */
5298 rsa_siggen_test(argv[3]);
5299 } else if (strcmp(argv[2], "sigver") == 0) {
5300 /* Signature Verification Test */
5301 rsa_sigver_test(argv[3]);
5303 /*************/
5304 /* HMAC */
5305 /*************/
5306 } else if (strcmp(argv[1], "hmac") == 0) {
5307 hmac_test(argv[2]);
5308 /*************/
5309 /* DSA */
5310 /*************/
5311 } else if (strcmp(argv[1], "dsa") == 0) {
5312 /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */
5313 /* argv[3]=<test name>.req */
5314 if (strcmp(argv[2], "keypair") == 0) {
5315 /* Key Pair Generation Test */
5316 dsa_keypair_test(argv[3]);
5317 } else if (strcmp(argv[2], "pqggen") == 0) {
5318 /* Domain Parameter Generation Test */
5319 dsa_pqggen_test(argv[3]);
5320 } else if (strcmp(argv[2], "pqgver") == 0) {
5321 /* Domain Parameter Validation Test */
5322 dsa_pqgver_test(argv[3]);
5323 } else if (strcmp(argv[2], "siggen") == 0) {
5324 /* Signature Generation Test */
5325 dsa_siggen_test(argv[3]);
5326 } else if (strcmp(argv[2], "sigver") == 0) {
5327 /* Signature Verification Test */
5328 dsa_sigver_test(argv[3]);
5330 #ifndef NSS_DISABLE_ECC
5331 /*************/
5332 /* ECDSA */
5333 /*************/
5334 } else if (strcmp(argv[1], "ecdsa") == 0) {
5335 /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */
5336 if ( strcmp(argv[2], "keypair") == 0) {
5337 /* Key Pair Generation Test */
5338 ecdsa_keypair_test(argv[3]);
5339 } else if (strcmp(argv[2], "pkv") == 0) {
5340 /* Public Key Validation Test */
5341 ecdsa_pkv_test(argv[3]);
5342 } else if (strcmp(argv[2], "siggen") == 0) {
5343 /* Signature Generation Test */
5344 ecdsa_siggen_test(argv[3]);
5345 } else if (strcmp(argv[2], "sigver") == 0) {
5346 /* Signature Verification Test */
5347 ecdsa_sigver_test(argv[3]);
5349 #endif /* NSS_DISABLE_ECC */
5350 /*************/
5351 /* RNG */
5352 /*************/
5353 } else if (strcmp(argv[1], "rng") == 0) {
5354 /* argv[2]=vst|mct argv[3]=<test name>.req */
5355 if ( strcmp(argv[2], "vst") == 0) {
5356 /* Variable Seed Test */
5357 rng_vst(argv[3]);
5358 } else if (strcmp(argv[2], "mct") == 0) {
5359 /* Monte Carlo Test */
5360 rng_mct(argv[3]);
5362 } else if (strcmp(argv[1], "drbg") == 0) {
5363 /* Variable Seed Test */
5364 drbg(argv[2]);
5365 } else if (strcmp(argv[1], "ddrbg") == 0) {
5366 debug = 1;
5367 drbg(argv[2]);
5369 return 0;