nss: import at 3.0.1 beta 1
[mozilla-nss.git] / security / nss / cmd / fipstest / fipstest.c
blobd191fe391fa5d9499ec972e63781a0798bfa84e7
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <ctype.h>
41 #include "secitem.h"
42 #include "blapi.h"
43 #include "nss.h"
44 #include "secerr.h"
45 #include "secder.h"
46 #include "secdig.h"
47 #include "keythi.h"
48 #include "ec.h"
49 #include "hasht.h"
50 #include "lowkeyi.h"
51 #include "softoken.h"
53 #if 0
54 #include "../../lib/freebl/mpi/mpi.h"
55 #endif
57 #ifdef NSS_ENABLE_ECC
58 extern SECStatus
59 EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
60 extern SECStatus
61 EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
62 const ECParams *srcParams);
63 #endif
65 #define ENCRYPT 1
66 #define DECRYPT 0
67 #define BYTE unsigned char
68 #define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001
69 #define RSA_MAX_TEST_MODULUS_BITS 4096
70 #define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS/8
71 #define RSA_MAX_TEST_EXPONENT_BYTES 8
72 #define PQG_TEST_SEED_BYTES 20
74 SECStatus
75 hex_to_byteval(const char *c2, unsigned char *byteval)
77 int i;
78 unsigned char offset;
79 *byteval = 0;
80 for (i=0; i<2; i++) {
81 if (c2[i] >= '0' && c2[i] <= '9') {
82 offset = c2[i] - '0';
83 *byteval |= offset << 4*(1-i);
84 } else if (c2[i] >= 'a' && c2[i] <= 'f') {
85 offset = c2[i] - 'a';
86 *byteval |= (offset + 10) << 4*(1-i);
87 } else if (c2[i] >= 'A' && c2[i] <= 'F') {
88 offset = c2[i] - 'A';
89 *byteval |= (offset + 10) << 4*(1-i);
90 } else {
91 return SECFailure;
94 return SECSuccess;
97 SECStatus
98 byteval_to_hex(unsigned char byteval, char *c2, char a)
100 int i;
101 unsigned char offset;
102 for (i=0; i<2; i++) {
103 offset = (byteval >> 4*(1-i)) & 0x0f;
104 if (offset < 10) {
105 c2[i] = '0' + offset;
106 } else {
107 c2[i] = a + offset - 10;
110 return SECSuccess;
113 void
114 to_hex_str(char *str, const unsigned char *buf, unsigned int len)
116 unsigned int i;
117 for (i=0; i<len; i++) {
118 byteval_to_hex(buf[i], &str[2*i], 'a');
120 str[2*len] = '\0';
123 void
124 to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len)
126 unsigned int i;
127 for (i=0; i<len; i++) {
128 byteval_to_hex(buf[i], &str[2*i], 'A');
130 str[2*len] = '\0';
134 * Convert a string of hex digits (str) to an array (buf) of len bytes.
135 * Return PR_TRUE if the hex string can fit in the byte array. Return
136 * PR_FALSE if the hex string is empty or is too long.
138 PRBool
139 from_hex_str(unsigned char *buf, unsigned int len, const char *str)
141 unsigned int nxdigit; /* number of hex digits in str */
142 unsigned int i; /* index into buf */
143 unsigned int j; /* index into str */
145 /* count the hex digits */
146 nxdigit = 0;
147 for (nxdigit = 0; isxdigit(str[nxdigit]); nxdigit++) {
148 /* empty body */
150 if (nxdigit == 0) {
151 return PR_FALSE;
153 if (nxdigit > 2*len) {
155 * The input hex string is too long, but we allow it if the
156 * extra digits are leading 0's.
158 for (j = 0; j < nxdigit-2*len; j++) {
159 if (str[j] != '0') {
160 return PR_FALSE;
163 /* skip leading 0's */
164 str += nxdigit-2*len;
165 nxdigit = 2*len;
167 for (i=0, j=0; i< len; i++) {
168 if (2*i < 2*len-nxdigit) {
169 /* Handle a short input as if we padded it with leading 0's. */
170 if (2*i+1 < 2*len-nxdigit) {
171 buf[i] = 0;
172 } else {
173 char tmp[2];
174 tmp[0] = '0';
175 tmp[1] = str[j];
176 hex_to_byteval(tmp, &buf[i]);
177 j++;
179 } else {
180 hex_to_byteval(&str[j], &buf[i]);
181 j += 2;
184 return PR_TRUE;
187 SECStatus
188 tdea_encrypt_buf(
189 int mode,
190 const unsigned char *key,
191 const unsigned char *iv,
192 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
193 const unsigned char *input, unsigned int inputlen)
195 SECStatus rv = SECFailure;
196 DESContext *cx;
197 unsigned char doublecheck[8*20]; /* 1 to 20 blocks */
198 unsigned int doublechecklen = 0;
200 cx = DES_CreateContext(key, iv, mode, PR_TRUE);
201 if (cx == NULL) {
202 goto loser;
204 rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
205 if (rv != SECSuccess) {
206 goto loser;
208 if (*outputlen != inputlen) {
209 goto loser;
211 DES_DestroyContext(cx, PR_TRUE);
212 cx = NULL;
215 * Doublecheck our result by decrypting the ciphertext and
216 * compare the output with the input plaintext.
218 cx = DES_CreateContext(key, iv, mode, PR_FALSE);
219 if (cx == NULL) {
220 goto loser;
222 rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
223 output, *outputlen);
224 if (rv != SECSuccess) {
225 goto loser;
227 if (doublechecklen != *outputlen) {
228 goto loser;
230 DES_DestroyContext(cx, PR_TRUE);
231 cx = NULL;
232 if (memcmp(doublecheck, input, inputlen) != 0) {
233 goto loser;
235 rv = SECSuccess;
237 loser:
238 if (cx != NULL) {
239 DES_DestroyContext(cx, PR_TRUE);
241 return rv;
244 SECStatus
245 tdea_decrypt_buf(
246 int mode,
247 const unsigned char *key,
248 const unsigned char *iv,
249 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
250 const unsigned char *input, unsigned int inputlen)
252 SECStatus rv = SECFailure;
253 DESContext *cx;
254 unsigned char doublecheck[8*20]; /* 1 to 20 blocks */
255 unsigned int doublechecklen = 0;
257 cx = DES_CreateContext(key, iv, mode, PR_FALSE);
258 if (cx == NULL) {
259 goto loser;
261 rv = DES_Decrypt(cx, output, outputlen, maxoutputlen,
262 input, inputlen);
263 if (rv != SECSuccess) {
264 goto loser;
266 if (*outputlen != inputlen) {
267 goto loser;
269 DES_DestroyContext(cx, PR_TRUE);
270 cx = NULL;
273 * Doublecheck our result by encrypting the plaintext and
274 * compare the output with the input ciphertext.
276 cx = DES_CreateContext(key, iv, mode, PR_TRUE);
277 if (cx == NULL) {
278 goto loser;
280 rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
281 output, *outputlen);
282 if (rv != SECSuccess) {
283 goto loser;
285 if (doublechecklen != *outputlen) {
286 goto loser;
288 DES_DestroyContext(cx, PR_TRUE);
289 cx = NULL;
290 if (memcmp(doublecheck, input, inputlen) != 0) {
291 goto loser;
293 rv = SECSuccess;
295 loser:
296 if (cx != NULL) {
297 DES_DestroyContext(cx, PR_TRUE);
299 return rv;
303 * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
304 * Test (MMT) in ECB or CBC mode. The KAT (there are five types)
305 * and MMT have the same structure: given the key and IV (CBC mode
306 * only), encrypt the given plaintext or decrypt the given ciphertext.
307 * So we can handle them the same way.
309 * reqfn is the pathname of the REQUEST file.
311 * The output RESPONSE file is written to stdout.
313 void
314 tdea_kat_mmt(char *reqfn)
316 char buf[180]; /* holds one line from the input REQUEST file.
317 * needs to be large enough to hold the longest
318 * line "CIPHERTEXT = <180 hex digits>\n".
320 FILE *req; /* input stream from the REQUEST file */
321 FILE *resp; /* output stream to the RESPONSE file */
322 int i, j;
323 int mode; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
324 int crypt = DECRYPT; /* 1 means encrypt, 0 means decrypt */
325 unsigned char key[24]; /* TDEA 3 key bundle */
326 unsigned int numKeys = 0;
327 unsigned char iv[8]; /* for all modes except ECB */
328 unsigned char plaintext[8*20]; /* 1 to 20 blocks */
329 unsigned int plaintextlen;
330 unsigned char ciphertext[8*20]; /* 1 to 20 blocks */
331 unsigned int ciphertextlen;
332 SECStatus rv;
334 req = fopen(reqfn, "r");
335 resp = stdout;
336 while (fgets(buf, sizeof buf, req) != NULL) {
337 /* a comment or blank line */
338 if (buf[0] == '#' || buf[0] == '\n') {
339 fputs(buf, resp);
340 continue;
342 /* [ENCRYPT] or [DECRYPT] */
343 if (buf[0] == '[') {
344 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
345 crypt = ENCRYPT;
346 } else {
347 crypt = DECRYPT;
349 fputs(buf, resp);
350 continue;
352 /* NumKeys */
353 if (strncmp(&buf[0], "NumKeys", 7) == 0) {
354 i = 7;
355 while (isspace(buf[i]) || buf[i] == '=') {
356 i++;
358 numKeys = buf[i];
359 fputs(buf, resp);
360 continue;
362 /* "COUNT = x" begins a new data set */
363 if (strncmp(buf, "COUNT", 5) == 0) {
364 /* mode defaults to ECB, if dataset has IV mode will be set CBC */
365 mode = NSS_DES_EDE3;
366 /* zeroize the variables for the test with this data set */
367 memset(key, 0, sizeof key);
368 memset(iv, 0, sizeof iv);
369 memset(plaintext, 0, sizeof plaintext);
370 plaintextlen = 0;
371 memset(ciphertext, 0, sizeof ciphertext);
372 ciphertextlen = 0;
373 fputs(buf, resp);
374 continue;
376 if (numKeys == 0) {
377 if (strncmp(buf, "KEYs", 4) == 0) {
378 i = 4;
379 while (isspace(buf[i]) || buf[i] == '=') {
380 i++;
382 for (j=0; isxdigit(buf[i]); i+=2,j++) {
383 hex_to_byteval(&buf[i], &key[j]);
384 key[j+8] = key[j];
385 key[j+16] = key[j];
387 fputs(buf, resp);
388 continue;
390 } else {
391 /* KEY1 = ... */
392 if (strncmp(buf, "KEY1", 4) == 0) {
393 i = 4;
394 while (isspace(buf[i]) || buf[i] == '=') {
395 i++;
397 for (j=0; isxdigit(buf[i]); i+=2,j++) {
398 hex_to_byteval(&buf[i], &key[j]);
400 fputs(buf, resp);
401 continue;
403 /* KEY2 = ... */
404 if (strncmp(buf, "KEY2", 4) == 0) {
405 i = 4;
406 while (isspace(buf[i]) || buf[i] == '=') {
407 i++;
409 for (j=8; isxdigit(buf[i]); i+=2,j++) {
410 hex_to_byteval(&buf[i], &key[j]);
412 fputs(buf, resp);
413 continue;
415 /* KEY3 = ... */
416 if (strncmp(buf, "KEY3", 4) == 0) {
417 i = 4;
418 while (isspace(buf[i]) || buf[i] == '=') {
419 i++;
421 for (j=16; isxdigit(buf[i]); i+=2,j++) {
422 hex_to_byteval(&buf[i], &key[j]);
424 fputs(buf, resp);
425 continue;
429 /* IV = ... */
430 if (strncmp(buf, "IV", 2) == 0) {
431 mode = NSS_DES_EDE3_CBC;
432 i = 2;
433 while (isspace(buf[i]) || buf[i] == '=') {
434 i++;
436 for (j=0; j<sizeof iv; i+=2,j++) {
437 hex_to_byteval(&buf[i], &iv[j]);
439 fputs(buf, resp);
440 continue;
443 /* PLAINTEXT = ... */
444 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
445 /* sanity check */
446 if (crypt != ENCRYPT) {
447 goto loser;
449 i = 9;
450 while (isspace(buf[i]) || buf[i] == '=') {
451 i++;
453 for (j=0; isxdigit(buf[i]); i+=2,j++) {
454 hex_to_byteval(&buf[i], &plaintext[j]);
456 plaintextlen = j;
457 rv = tdea_encrypt_buf(mode, key,
458 (mode == NSS_DES_EDE3) ? NULL : iv,
459 ciphertext, &ciphertextlen, sizeof ciphertext,
460 plaintext, plaintextlen);
461 if (rv != SECSuccess) {
462 goto loser;
465 fputs(buf, resp);
466 fputs("CIPHERTEXT = ", resp);
467 to_hex_str(buf, ciphertext, ciphertextlen);
468 fputs(buf, resp);
469 fputc('\n', resp);
470 continue;
472 /* CIPHERTEXT = ... */
473 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
474 /* sanity check */
475 if (crypt != DECRYPT) {
476 goto loser;
479 i = 10;
480 while (isspace(buf[i]) || buf[i] == '=') {
481 i++;
483 for (j=0; isxdigit(buf[i]); i+=2,j++) {
484 hex_to_byteval(&buf[i], &ciphertext[j]);
486 ciphertextlen = j;
488 rv = tdea_decrypt_buf(mode, key,
489 (mode == NSS_DES_EDE3) ? NULL : iv,
490 plaintext, &plaintextlen, sizeof plaintext,
491 ciphertext, ciphertextlen);
492 if (rv != SECSuccess) {
493 goto loser;
496 fputs(buf, resp);
497 fputs("PLAINTEXT = ", resp);
498 to_hex_str(buf, plaintext, plaintextlen);
499 fputs(buf, resp);
500 fputc('\n', resp);
501 continue;
505 loser:
506 fclose(req);
510 * Set the parity bit for the given byte
512 BYTE odd_parity( BYTE in)
514 BYTE out = in;
515 in ^= in >> 4;
516 in ^= in >> 2;
517 in ^= in >> 1;
518 return (BYTE)(out ^ !(in & 1));
522 * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j]
523 * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
525 void
526 tdea_mct_next_keys(unsigned char *key,
527 const unsigned char *text_2, const unsigned char *text_1,
528 const unsigned char *text, unsigned int numKeys)
530 int k;
532 /* key1[i+1] = key1[i] xor PT/CT[j] */
533 for (k=0; k<8; k++) {
534 key[k] ^= text[k];
536 /* key2 */
537 if (numKeys == 2 || numKeys == 3) {
538 /* key2 independent */
539 for (k=8; k<16; k++) {
540 /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
541 key[k] ^= text_1[k-8];
543 } else {
544 /* key2 == key 1 */
545 for (k=8; k<16; k++) {
546 /* key2[i+1] = KEY2[i] xor PT/CT[j] */
547 key[k] = key[k-8];
550 /* key3 */
551 if (numKeys == 1 || numKeys == 2) {
552 /* key3 == key 1 */
553 for (k=16; k<24; k++) {
554 /* key3[i+1] = KEY3[i] xor PT/CT[j] */
555 key[k] = key[k-16];
557 } else {
558 /* key3 independent */
559 for (k=16; k<24; k++) {
560 /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
561 key[k] ^= text_2[k-16];
564 /* set the parity bits */
565 for (k=0; k<24; k++) {
566 key[k] = odd_parity(key[k]);
571 * Perform the Monte Carlo Test
573 * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
574 * crypt = ENCRYPT || DECRYPT
575 * inputtext = plaintext or Cyphertext depending on the value of crypt
576 * inputlength is expected to be size 8 bytes
577 * iv = needs to be set for NSS_DES_EDE3_CBC mode
578 * resp = is the output response file.
580 void
581 tdea_mct_test(int mode, unsigned char* key, unsigned int numKeys,
582 unsigned int crypt, unsigned char* inputtext,
583 unsigned int inputlength, unsigned char* iv, FILE *resp) {
585 int i, j;
586 unsigned char outputtext_1[8]; /* PT/CT[j-1] */
587 unsigned char outputtext_2[8]; /* PT/CT[j-2] */
588 char buf[80]; /* holds one line from the input REQUEST file. */
589 unsigned int outputlen;
590 unsigned char outputtext[8];
593 SECStatus rv;
595 if (mode == NSS_DES_EDE3 && iv != NULL) {
596 printf("IV must be NULL for NSS_DES_EDE3 mode");
597 goto loser;
598 } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) {
599 printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
600 goto loser;
603 /* loop 400 times */
604 for (i=0; i<400; i++) {
605 /* if i == 0 CV[0] = IV not necessary */
606 /* record the count and key values and plainText */
607 sprintf(buf, "COUNT = %d\n", i);
608 fputs(buf, resp);
609 /* Output KEY1[i] */
610 fputs("KEY1 = ", resp);
611 to_hex_str(buf, key, 8);
612 fputs(buf, resp);
613 fputc('\n', resp);
614 /* Output KEY2[i] */
615 fputs("KEY2 = ", resp);
616 to_hex_str(buf, &key[8], 8);
617 fputs(buf, resp);
618 fputc('\n', resp);
619 /* Output KEY3[i] */
620 fputs("KEY3 = ", resp);
621 to_hex_str(buf, &key[16], 8);
622 fputs(buf, resp);
623 fputc('\n', resp);
624 if (mode == NSS_DES_EDE3_CBC) {
625 /* Output CV[i] */
626 fputs("IV = ", resp);
627 to_hex_str(buf, iv, 8);
628 fputs(buf, resp);
629 fputc('\n', resp);
631 if (crypt == ENCRYPT) {
632 /* Output PT[0] */
633 fputs("PLAINTEXT = ", resp);
634 } else {
635 /* Output CT[0] */
636 fputs("CIPHERTEXT = ", resp);
639 to_hex_str(buf, inputtext, inputlength);
640 fputs(buf, resp);
641 fputc('\n', resp);
643 /* loop 10,000 times */
644 for (j=0; j<10000; j++) {
646 outputlen = 0;
647 if (crypt == ENCRYPT) {
648 /* inputtext == ciphertext outputtext == plaintext*/
649 rv = tdea_encrypt_buf(mode, key,
650 (mode == NSS_DES_EDE3) ? NULL : iv,
651 outputtext, &outputlen, 8,
652 inputtext, 8);
653 } else {
654 /* inputtext == plaintext outputtext == ciphertext */
655 rv = tdea_decrypt_buf(mode, key,
656 (mode == NSS_DES_EDE3) ? NULL : iv,
657 outputtext, &outputlen, 8,
658 inputtext, 8);
661 if (rv != SECSuccess) {
662 goto loser;
664 if (outputlen != inputlength) {
665 goto loser;
668 if (mode == NSS_DES_EDE3_CBC) {
669 if (crypt == ENCRYPT) {
670 if (j == 0) {
671 /*P[j+1] = CV[0] */
672 memcpy(inputtext, iv, 8);
673 } else {
674 /* p[j+1] = C[j-1] */
675 memcpy(inputtext, outputtext_1, 8);
677 /* CV[j+1] = C[j] */
678 memcpy(iv, outputtext, 8);
679 if (j != 9999) {
680 /* save C[j-1] */
681 memcpy(outputtext_1, outputtext, 8);
683 } else { /* DECRYPT */
684 /* CV[j+1] = C[j] */
685 memcpy(iv, inputtext, 8);
686 /* C[j+1] = P[j] */
687 memcpy(inputtext, outputtext, 8);
689 } else {
690 /* ECB mode PT/CT[j+1] = CT/PT[j] */
691 memcpy(inputtext, outputtext, 8);
694 /* Save PT/CT[j-2] and PT/CT[j-1] */
695 if (j==9997) memcpy(outputtext_2, outputtext, 8);
696 if (j==9998) memcpy(outputtext_1, outputtext, 8);
697 /* done at the end of the for(j) loop */
701 if (crypt == ENCRYPT) {
702 /* Output CT[j] */
703 fputs("CIPHERTEXT = ", resp);
704 } else {
705 /* Output PT[j] */
706 fputs("PLAINTEXT = ", resp);
708 to_hex_str(buf, outputtext, 8);
709 fputs(buf, resp);
710 fputc('\n', resp);
712 /* Key[i+1] = Key[i] xor ... outputtext_2 == PT/CT[j-2]
713 * outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j]
715 tdea_mct_next_keys(key, outputtext_2,
716 outputtext_1, outputtext, numKeys);
718 if (mode == NSS_DES_EDE3_CBC) {
719 /* taken care of in the j=9999 iteration */
720 if (crypt == ENCRYPT) {
721 /* P[i] = C[j-1] */
722 /* CV[i] = C[j] */
723 } else {
724 /* taken care of in the j=9999 iteration */
725 /* CV[i] = C[j] */
726 /* C[i] = P[j] */
728 } else {
729 /* ECB PT/CT[i] = PT/CT[j] */
730 memcpy(inputtext, outputtext, 8);
732 /* done at the end of the for(i) loop */
733 fputc('\n', resp);
736 loser:
737 return;
741 * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
742 * by gathering the input from the request file, and then
743 * calling tdea_mct_test.
745 * reqfn is the pathname of the input REQUEST file.
747 * The output RESPONSE file is written to stdout.
749 void
750 tdea_mct(int mode, char *reqfn)
752 int i, j;
753 char buf[80]; /* holds one line from the input REQUEST file. */
754 FILE *req; /* input stream from the REQUEST file */
755 FILE *resp; /* output stream to the RESPONSE file */
756 unsigned int crypt = 0; /* 1 means encrypt, 0 means decrypt */
757 unsigned char key[24]; /* TDEA 3 key bundle */
758 unsigned int numKeys = 0;
759 unsigned char plaintext[8]; /* PT[j] */
760 unsigned char ciphertext[8]; /* CT[j] */
761 unsigned char iv[8];
763 /* zeroize the variables for the test with this data set */
764 memset(key, 0, sizeof key);
765 memset(plaintext, 0, sizeof plaintext);
766 memset(ciphertext, 0, sizeof ciphertext);
767 memset(iv, 0, sizeof iv);
769 req = fopen(reqfn, "r");
770 resp = stdout;
771 while (fgets(buf, sizeof buf, req) != NULL) {
772 /* a comment or blank line */
773 if (buf[0] == '#' || buf[0] == '\n') {
774 fputs(buf, resp);
775 continue;
777 /* [ENCRYPT] or [DECRYPT] */
778 if (buf[0] == '[') {
779 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
780 crypt = ENCRYPT;
781 } else {
782 crypt = DECRYPT;
784 fputs(buf, resp);
785 continue;
787 /* NumKeys */
788 if (strncmp(&buf[0], "NumKeys", 7) == 0) {
789 i = 7;
790 while (isspace(buf[i]) || buf[i] == '=') {
791 i++;
793 numKeys = atoi(&buf[i]);
794 continue;
796 /* KEY1 = ... */
797 if (strncmp(buf, "KEY1", 4) == 0) {
798 i = 4;
799 while (isspace(buf[i]) || buf[i] == '=') {
800 i++;
802 for (j=0; isxdigit(buf[i]); i+=2,j++) {
803 hex_to_byteval(&buf[i], &key[j]);
805 continue;
807 /* KEY2 = ... */
808 if (strncmp(buf, "KEY2", 4) == 0) {
809 i = 4;
810 while (isspace(buf[i]) || buf[i] == '=') {
811 i++;
813 for (j=8; isxdigit(buf[i]); i+=2,j++) {
814 hex_to_byteval(&buf[i], &key[j]);
816 continue;
818 /* KEY3 = ... */
819 if (strncmp(buf, "KEY3", 4) == 0) {
820 i = 4;
821 while (isspace(buf[i]) || buf[i] == '=') {
822 i++;
824 for (j=16; isxdigit(buf[i]); i+=2,j++) {
825 hex_to_byteval(&buf[i], &key[j]);
827 continue;
830 /* IV = ... */
831 if (strncmp(buf, "IV", 2) == 0) {
832 i = 2;
833 while (isspace(buf[i]) || buf[i] == '=') {
834 i++;
836 for (j=0; j<sizeof iv; i+=2,j++) {
837 hex_to_byteval(&buf[i], &iv[j]);
839 continue;
842 /* PLAINTEXT = ... */
843 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
845 /* sanity check */
846 if (crypt != ENCRYPT) {
847 goto loser;
849 /* PT[0] = PT */
850 i = 9;
851 while (isspace(buf[i]) || buf[i] == '=') {
852 i++;
854 for (j=0; j<sizeof plaintext; i+=2,j++) {
855 hex_to_byteval(&buf[i], &plaintext[j]);
858 /* do the Monte Carlo test */
859 if (mode==NSS_DES_EDE3) {
860 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp);
861 } else {
862 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp);
864 continue;
866 /* CIPHERTEXT = ... */
867 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
868 /* sanity check */
869 if (crypt != DECRYPT) {
870 goto loser;
872 /* CT[0] = CT */
873 i = 10;
874 while (isspace(buf[i]) || buf[i] == '=') {
875 i++;
877 for (j=0; isxdigit(buf[i]); i+=2,j++) {
878 hex_to_byteval(&buf[i], &ciphertext[j]);
881 /* do the Monte Carlo test */
882 if (mode==NSS_DES_EDE3) {
883 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp);
884 } else {
885 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp);
887 continue;
891 loser:
892 fclose(req);
896 SECStatus
897 aes_encrypt_buf(
898 int mode,
899 const unsigned char *key, unsigned int keysize,
900 const unsigned char *iv,
901 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
902 const unsigned char *input, unsigned int inputlen)
904 SECStatus rv = SECFailure;
905 AESContext *cx;
906 unsigned char doublecheck[10*16]; /* 1 to 10 blocks */
907 unsigned int doublechecklen = 0;
909 cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
910 if (cx == NULL) {
911 goto loser;
913 rv = AES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
914 if (rv != SECSuccess) {
915 goto loser;
917 if (*outputlen != inputlen) {
918 goto loser;
920 AES_DestroyContext(cx, PR_TRUE);
921 cx = NULL;
924 * Doublecheck our result by decrypting the ciphertext and
925 * compare the output with the input plaintext.
927 cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
928 if (cx == NULL) {
929 goto loser;
931 rv = AES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
932 output, *outputlen);
933 if (rv != SECSuccess) {
934 goto loser;
936 if (doublechecklen != *outputlen) {
937 goto loser;
939 AES_DestroyContext(cx, PR_TRUE);
940 cx = NULL;
941 if (memcmp(doublecheck, input, inputlen) != 0) {
942 goto loser;
944 rv = SECSuccess;
946 loser:
947 if (cx != NULL) {
948 AES_DestroyContext(cx, PR_TRUE);
950 return rv;
953 SECStatus
954 aes_decrypt_buf(
955 int mode,
956 const unsigned char *key, unsigned int keysize,
957 const unsigned char *iv,
958 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
959 const unsigned char *input, unsigned int inputlen)
961 SECStatus rv = SECFailure;
962 AESContext *cx;
963 unsigned char doublecheck[10*16]; /* 1 to 10 blocks */
964 unsigned int doublechecklen = 0;
966 cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
967 if (cx == NULL) {
968 goto loser;
970 rv = AES_Decrypt(cx, output, outputlen, maxoutputlen,
971 input, inputlen);
972 if (rv != SECSuccess) {
973 goto loser;
975 if (*outputlen != inputlen) {
976 goto loser;
978 AES_DestroyContext(cx, PR_TRUE);
979 cx = NULL;
982 * Doublecheck our result by encrypting the plaintext and
983 * compare the output with the input ciphertext.
985 cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
986 if (cx == NULL) {
987 goto loser;
989 rv = AES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
990 output, *outputlen);
991 if (rv != SECSuccess) {
992 goto loser;
994 if (doublechecklen != *outputlen) {
995 goto loser;
997 AES_DestroyContext(cx, PR_TRUE);
998 cx = NULL;
999 if (memcmp(doublecheck, input, inputlen) != 0) {
1000 goto loser;
1002 rv = SECSuccess;
1004 loser:
1005 if (cx != NULL) {
1006 AES_DestroyContext(cx, PR_TRUE);
1008 return rv;
1012 * Perform the AES Known Answer Test (KAT) or Multi-block Message
1013 * Test (MMT) in ECB or CBC mode. The KAT (there are four types)
1014 * and MMT have the same structure: given the key and IV (CBC mode
1015 * only), encrypt the given plaintext or decrypt the given ciphertext.
1016 * So we can handle them the same way.
1018 * reqfn is the pathname of the REQUEST file.
1020 * The output RESPONSE file is written to stdout.
1022 void
1023 aes_kat_mmt(char *reqfn)
1025 char buf[512]; /* holds one line from the input REQUEST file.
1026 * needs to be large enough to hold the longest
1027 * line "CIPHERTEXT = <320 hex digits>\n".
1029 FILE *aesreq; /* input stream from the REQUEST file */
1030 FILE *aesresp; /* output stream to the RESPONSE file */
1031 int i, j;
1032 int mode; /* NSS_AES (ECB) or NSS_AES_CBC */
1033 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
1034 unsigned char key[32]; /* 128, 192, or 256 bits */
1035 unsigned int keysize;
1036 unsigned char iv[16]; /* for all modes except ECB */
1037 unsigned char plaintext[10*16]; /* 1 to 10 blocks */
1038 unsigned int plaintextlen;
1039 unsigned char ciphertext[10*16]; /* 1 to 10 blocks */
1040 unsigned int ciphertextlen;
1041 SECStatus rv;
1043 aesreq = fopen(reqfn, "r");
1044 aesresp = stdout;
1045 while (fgets(buf, sizeof buf, aesreq) != NULL) {
1046 /* a comment or blank line */
1047 if (buf[0] == '#' || buf[0] == '\n') {
1048 fputs(buf, aesresp);
1049 continue;
1051 /* [ENCRYPT] or [DECRYPT] */
1052 if (buf[0] == '[') {
1053 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1054 encrypt = 1;
1055 } else {
1056 encrypt = 0;
1058 fputs(buf, aesresp);
1059 continue;
1061 /* "COUNT = x" begins a new data set */
1062 if (strncmp(buf, "COUNT", 5) == 0) {
1063 mode = NSS_AES;
1064 /* zeroize the variables for the test with this data set */
1065 memset(key, 0, sizeof key);
1066 keysize = 0;
1067 memset(iv, 0, sizeof iv);
1068 memset(plaintext, 0, sizeof plaintext);
1069 plaintextlen = 0;
1070 memset(ciphertext, 0, sizeof ciphertext);
1071 ciphertextlen = 0;
1072 fputs(buf, aesresp);
1073 continue;
1075 /* KEY = ... */
1076 if (strncmp(buf, "KEY", 3) == 0) {
1077 i = 3;
1078 while (isspace(buf[i]) || buf[i] == '=') {
1079 i++;
1081 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1082 hex_to_byteval(&buf[i], &key[j]);
1084 keysize = j;
1085 fputs(buf, aesresp);
1086 continue;
1088 /* IV = ... */
1089 if (strncmp(buf, "IV", 2) == 0) {
1090 mode = NSS_AES_CBC;
1091 i = 2;
1092 while (isspace(buf[i]) || buf[i] == '=') {
1093 i++;
1095 for (j=0; j<sizeof iv; i+=2,j++) {
1096 hex_to_byteval(&buf[i], &iv[j]);
1098 fputs(buf, aesresp);
1099 continue;
1101 /* PLAINTEXT = ... */
1102 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1103 /* sanity check */
1104 if (!encrypt) {
1105 goto loser;
1108 i = 9;
1109 while (isspace(buf[i]) || buf[i] == '=') {
1110 i++;
1112 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1113 hex_to_byteval(&buf[i], &plaintext[j]);
1115 plaintextlen = j;
1117 rv = aes_encrypt_buf(mode, key, keysize,
1118 (mode == NSS_AES) ? NULL : iv,
1119 ciphertext, &ciphertextlen, sizeof ciphertext,
1120 plaintext, plaintextlen);
1121 if (rv != SECSuccess) {
1122 goto loser;
1125 fputs(buf, aesresp);
1126 fputs("CIPHERTEXT = ", aesresp);
1127 to_hex_str(buf, ciphertext, ciphertextlen);
1128 fputs(buf, aesresp);
1129 fputc('\n', aesresp);
1130 continue;
1132 /* CIPHERTEXT = ... */
1133 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1134 /* sanity check */
1135 if (encrypt) {
1136 goto loser;
1139 i = 10;
1140 while (isspace(buf[i]) || buf[i] == '=') {
1141 i++;
1143 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1144 hex_to_byteval(&buf[i], &ciphertext[j]);
1146 ciphertextlen = j;
1148 rv = aes_decrypt_buf(mode, key, keysize,
1149 (mode == NSS_AES) ? NULL : iv,
1150 plaintext, &plaintextlen, sizeof plaintext,
1151 ciphertext, ciphertextlen);
1152 if (rv != SECSuccess) {
1153 goto loser;
1156 fputs(buf, aesresp);
1157 fputs("PLAINTEXT = ", aesresp);
1158 to_hex_str(buf, plaintext, plaintextlen);
1159 fputs(buf, aesresp);
1160 fputc('\n', aesresp);
1161 continue;
1164 loser:
1165 fclose(aesreq);
1169 * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
1170 * Test (MCT) in ECB and CBC modes.
1172 void
1173 aes_mct_next_key(unsigned char *key, unsigned int keysize,
1174 const unsigned char *ciphertext_1, const unsigned char *ciphertext)
1176 int k;
1178 switch (keysize) {
1179 case 16: /* 128-bit key */
1180 /* Key[i+1] = Key[i] xor CT[j] */
1181 for (k=0; k<16; k++) {
1182 key[k] ^= ciphertext[k];
1184 break;
1185 case 24: /* 192-bit key */
1187 * Key[i+1] = Key[i] xor (last 64-bits of
1188 * CT[j-1] || CT[j])
1190 for (k=0; k<8; k++) {
1191 key[k] ^= ciphertext_1[k+8];
1193 for (k=8; k<24; k++) {
1194 key[k] ^= ciphertext[k-8];
1196 break;
1197 case 32: /* 256-bit key */
1198 /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
1199 for (k=0; k<16; k++) {
1200 key[k] ^= ciphertext_1[k];
1202 for (k=16; k<32; k++) {
1203 key[k] ^= ciphertext[k-16];
1205 break;
1210 * Perform the AES Monte Carlo Test (MCT) in ECB mode. MCT exercises
1211 * our AES code in streaming mode because the plaintext or ciphertext
1212 * is generated block by block as we go, so we can't collect all the
1213 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1214 * one shot.
1216 * reqfn is the pathname of the input REQUEST file.
1218 * The output RESPONSE file is written to stdout.
1220 void
1221 aes_ecb_mct(char *reqfn)
1223 char buf[80]; /* holds one line from the input REQUEST file.
1224 * needs to be large enough to hold the longest
1225 * line "KEY = <64 hex digits>\n".
1227 FILE *aesreq; /* input stream from the REQUEST file */
1228 FILE *aesresp; /* output stream to the RESPONSE file */
1229 int i, j;
1230 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
1231 unsigned char key[32]; /* 128, 192, or 256 bits */
1232 unsigned int keysize;
1233 unsigned char plaintext[16]; /* PT[j] */
1234 unsigned char plaintext_1[16]; /* PT[j-1] */
1235 unsigned char ciphertext[16]; /* CT[j] */
1236 unsigned char ciphertext_1[16]; /* CT[j-1] */
1237 unsigned char doublecheck[16];
1238 unsigned int outputlen;
1239 AESContext *cx = NULL; /* the operation being tested */
1240 AESContext *cx2 = NULL; /* the inverse operation done in parallel
1241 * to doublecheck our result.
1243 SECStatus rv;
1245 aesreq = fopen(reqfn, "r");
1246 aesresp = stdout;
1247 while (fgets(buf, sizeof buf, aesreq) != NULL) {
1248 /* a comment or blank line */
1249 if (buf[0] == '#' || buf[0] == '\n') {
1250 fputs(buf, aesresp);
1251 continue;
1253 /* [ENCRYPT] or [DECRYPT] */
1254 if (buf[0] == '[') {
1255 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1256 encrypt = 1;
1257 } else {
1258 encrypt = 0;
1260 fputs(buf, aesresp);
1261 continue;
1263 /* "COUNT = x" begins a new data set */
1264 if (strncmp(buf, "COUNT", 5) == 0) {
1265 /* zeroize the variables for the test with this data set */
1266 memset(key, 0, sizeof key);
1267 keysize = 0;
1268 memset(plaintext, 0, sizeof plaintext);
1269 memset(ciphertext, 0, sizeof ciphertext);
1270 continue;
1272 /* KEY = ... */
1273 if (strncmp(buf, "KEY", 3) == 0) {
1274 /* Key[0] = Key */
1275 i = 3;
1276 while (isspace(buf[i]) || buf[i] == '=') {
1277 i++;
1279 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1280 hex_to_byteval(&buf[i], &key[j]);
1282 keysize = j;
1283 continue;
1285 /* PLAINTEXT = ... */
1286 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1287 /* sanity check */
1288 if (!encrypt) {
1289 goto loser;
1291 /* PT[0] = PT */
1292 i = 9;
1293 while (isspace(buf[i]) || buf[i] == '=') {
1294 i++;
1296 for (j=0; j<sizeof plaintext; i+=2,j++) {
1297 hex_to_byteval(&buf[i], &plaintext[j]);
1300 for (i=0; i<100; i++) {
1301 sprintf(buf, "COUNT = %d\n", i);
1302 fputs(buf, aesresp);
1303 /* Output Key[i] */
1304 fputs("KEY = ", aesresp);
1305 to_hex_str(buf, key, keysize);
1306 fputs(buf, aesresp);
1307 fputc('\n', aesresp);
1308 /* Output PT[0] */
1309 fputs("PLAINTEXT = ", aesresp);
1310 to_hex_str(buf, plaintext, sizeof plaintext);
1311 fputs(buf, aesresp);
1312 fputc('\n', aesresp);
1314 cx = AES_CreateContext(key, NULL, NSS_AES,
1315 PR_TRUE, keysize, 16);
1316 if (cx == NULL) {
1317 goto loser;
1320 * doublecheck our result by decrypting the result
1321 * and comparing the output with the plaintext.
1323 cx2 = AES_CreateContext(key, NULL, NSS_AES,
1324 PR_FALSE, keysize, 16);
1325 if (cx2 == NULL) {
1326 goto loser;
1328 for (j=0; j<1000; j++) {
1329 /* Save CT[j-1] */
1330 memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
1332 /* CT[j] = AES(Key[i], PT[j]) */
1333 outputlen = 0;
1334 rv = AES_Encrypt(cx,
1335 ciphertext, &outputlen, sizeof ciphertext,
1336 plaintext, sizeof plaintext);
1337 if (rv != SECSuccess) {
1338 goto loser;
1340 if (outputlen != sizeof plaintext) {
1341 goto loser;
1344 /* doublecheck our result */
1345 outputlen = 0;
1346 rv = AES_Decrypt(cx2,
1347 doublecheck, &outputlen, sizeof doublecheck,
1348 ciphertext, sizeof ciphertext);
1349 if (rv != SECSuccess) {
1350 goto loser;
1352 if (outputlen != sizeof ciphertext) {
1353 goto loser;
1355 if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
1356 goto loser;
1359 /* PT[j+1] = CT[j] */
1360 memcpy(plaintext, ciphertext, sizeof plaintext);
1362 AES_DestroyContext(cx, PR_TRUE);
1363 cx = NULL;
1364 AES_DestroyContext(cx2, PR_TRUE);
1365 cx2 = NULL;
1367 /* Output CT[j] */
1368 fputs("CIPHERTEXT = ", aesresp);
1369 to_hex_str(buf, ciphertext, sizeof ciphertext);
1370 fputs(buf, aesresp);
1371 fputc('\n', aesresp);
1373 /* Key[i+1] = Key[i] xor ... */
1374 aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
1375 /* PT[0] = CT[j] */
1376 /* done at the end of the for(j) loop */
1378 fputc('\n', aesresp);
1381 continue;
1383 /* CIPHERTEXT = ... */
1384 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1385 /* sanity check */
1386 if (encrypt) {
1387 goto loser;
1389 /* CT[0] = CT */
1390 i = 10;
1391 while (isspace(buf[i]) || buf[i] == '=') {
1392 i++;
1394 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1395 hex_to_byteval(&buf[i], &ciphertext[j]);
1398 for (i=0; i<100; i++) {
1399 sprintf(buf, "COUNT = %d\n", i);
1400 fputs(buf, aesresp);
1401 /* Output Key[i] */
1402 fputs("KEY = ", aesresp);
1403 to_hex_str(buf, key, keysize);
1404 fputs(buf, aesresp);
1405 fputc('\n', aesresp);
1406 /* Output CT[0] */
1407 fputs("CIPHERTEXT = ", aesresp);
1408 to_hex_str(buf, ciphertext, sizeof ciphertext);
1409 fputs(buf, aesresp);
1410 fputc('\n', aesresp);
1412 cx = AES_CreateContext(key, NULL, NSS_AES,
1413 PR_FALSE, keysize, 16);
1414 if (cx == NULL) {
1415 goto loser;
1418 * doublecheck our result by encrypting the result
1419 * and comparing the output with the ciphertext.
1421 cx2 = AES_CreateContext(key, NULL, NSS_AES,
1422 PR_TRUE, keysize, 16);
1423 if (cx2 == NULL) {
1424 goto loser;
1426 for (j=0; j<1000; j++) {
1427 /* Save PT[j-1] */
1428 memcpy(plaintext_1, plaintext, sizeof plaintext);
1430 /* PT[j] = AES(Key[i], CT[j]) */
1431 outputlen = 0;
1432 rv = AES_Decrypt(cx,
1433 plaintext, &outputlen, sizeof plaintext,
1434 ciphertext, sizeof ciphertext);
1435 if (rv != SECSuccess) {
1436 goto loser;
1438 if (outputlen != sizeof ciphertext) {
1439 goto loser;
1442 /* doublecheck our result */
1443 outputlen = 0;
1444 rv = AES_Encrypt(cx2,
1445 doublecheck, &outputlen, sizeof doublecheck,
1446 plaintext, sizeof plaintext);
1447 if (rv != SECSuccess) {
1448 goto loser;
1450 if (outputlen != sizeof plaintext) {
1451 goto loser;
1453 if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
1454 goto loser;
1457 /* CT[j+1] = PT[j] */
1458 memcpy(ciphertext, plaintext, sizeof ciphertext);
1460 AES_DestroyContext(cx, PR_TRUE);
1461 cx = NULL;
1462 AES_DestroyContext(cx2, PR_TRUE);
1463 cx2 = NULL;
1465 /* Output PT[j] */
1466 fputs("PLAINTEXT = ", aesresp);
1467 to_hex_str(buf, plaintext, sizeof plaintext);
1468 fputs(buf, aesresp);
1469 fputc('\n', aesresp);
1471 /* Key[i+1] = Key[i] xor ... */
1472 aes_mct_next_key(key, keysize, plaintext_1, plaintext);
1473 /* CT[0] = PT[j] */
1474 /* done at the end of the for(j) loop */
1476 fputc('\n', aesresp);
1479 continue;
1482 loser:
1483 if (cx != NULL) {
1484 AES_DestroyContext(cx, PR_TRUE);
1486 if (cx2 != NULL) {
1487 AES_DestroyContext(cx2, PR_TRUE);
1489 fclose(aesreq);
1493 * Perform the AES Monte Carlo Test (MCT) in CBC mode. MCT exercises
1494 * our AES code in streaming mode because the plaintext or ciphertext
1495 * is generated block by block as we go, so we can't collect all the
1496 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1497 * one shot.
1499 * reqfn is the pathname of the input REQUEST file.
1501 * The output RESPONSE file is written to stdout.
1503 void
1504 aes_cbc_mct(char *reqfn)
1506 char buf[80]; /* holds one line from the input REQUEST file.
1507 * needs to be large enough to hold the longest
1508 * line "KEY = <64 hex digits>\n".
1510 FILE *aesreq; /* input stream from the REQUEST file */
1511 FILE *aesresp; /* output stream to the RESPONSE file */
1512 int i, j;
1513 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
1514 unsigned char key[32]; /* 128, 192, or 256 bits */
1515 unsigned int keysize;
1516 unsigned char iv[16];
1517 unsigned char plaintext[16]; /* PT[j] */
1518 unsigned char plaintext_1[16]; /* PT[j-1] */
1519 unsigned char ciphertext[16]; /* CT[j] */
1520 unsigned char ciphertext_1[16]; /* CT[j-1] */
1521 unsigned char doublecheck[16];
1522 unsigned int outputlen;
1523 AESContext *cx = NULL; /* the operation being tested */
1524 AESContext *cx2 = NULL; /* the inverse operation done in parallel
1525 * to doublecheck our result.
1527 SECStatus rv;
1529 aesreq = fopen(reqfn, "r");
1530 aesresp = stdout;
1531 while (fgets(buf, sizeof buf, aesreq) != NULL) {
1532 /* a comment or blank line */
1533 if (buf[0] == '#' || buf[0] == '\n') {
1534 fputs(buf, aesresp);
1535 continue;
1537 /* [ENCRYPT] or [DECRYPT] */
1538 if (buf[0] == '[') {
1539 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1540 encrypt = 1;
1541 } else {
1542 encrypt = 0;
1544 fputs(buf, aesresp);
1545 continue;
1547 /* "COUNT = x" begins a new data set */
1548 if (strncmp(buf, "COUNT", 5) == 0) {
1549 /* zeroize the variables for the test with this data set */
1550 memset(key, 0, sizeof key);
1551 keysize = 0;
1552 memset(iv, 0, sizeof iv);
1553 memset(plaintext, 0, sizeof plaintext);
1554 memset(ciphertext, 0, sizeof ciphertext);
1555 continue;
1557 /* KEY = ... */
1558 if (strncmp(buf, "KEY", 3) == 0) {
1559 /* Key[0] = Key */
1560 i = 3;
1561 while (isspace(buf[i]) || buf[i] == '=') {
1562 i++;
1564 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1565 hex_to_byteval(&buf[i], &key[j]);
1567 keysize = j;
1568 continue;
1570 /* IV = ... */
1571 if (strncmp(buf, "IV", 2) == 0) {
1572 /* IV[0] = IV */
1573 i = 2;
1574 while (isspace(buf[i]) || buf[i] == '=') {
1575 i++;
1577 for (j=0; j<sizeof iv; i+=2,j++) {
1578 hex_to_byteval(&buf[i], &iv[j]);
1580 continue;
1582 /* PLAINTEXT = ... */
1583 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1584 /* sanity check */
1585 if (!encrypt) {
1586 goto loser;
1588 /* PT[0] = PT */
1589 i = 9;
1590 while (isspace(buf[i]) || buf[i] == '=') {
1591 i++;
1593 for (j=0; j<sizeof plaintext; i+=2,j++) {
1594 hex_to_byteval(&buf[i], &plaintext[j]);
1597 for (i=0; i<100; i++) {
1598 sprintf(buf, "COUNT = %d\n", i);
1599 fputs(buf, aesresp);
1600 /* Output Key[i] */
1601 fputs("KEY = ", aesresp);
1602 to_hex_str(buf, key, keysize);
1603 fputs(buf, aesresp);
1604 fputc('\n', aesresp);
1605 /* Output IV[i] */
1606 fputs("IV = ", aesresp);
1607 to_hex_str(buf, iv, sizeof iv);
1608 fputs(buf, aesresp);
1609 fputc('\n', aesresp);
1610 /* Output PT[0] */
1611 fputs("PLAINTEXT = ", aesresp);
1612 to_hex_str(buf, plaintext, sizeof plaintext);
1613 fputs(buf, aesresp);
1614 fputc('\n', aesresp);
1616 cx = AES_CreateContext(key, iv, NSS_AES_CBC,
1617 PR_TRUE, keysize, 16);
1618 if (cx == NULL) {
1619 goto loser;
1622 * doublecheck our result by decrypting the result
1623 * and comparing the output with the plaintext.
1625 cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
1626 PR_FALSE, keysize, 16);
1627 if (cx2 == NULL) {
1628 goto loser;
1630 /* CT[-1] = IV[i] */
1631 memcpy(ciphertext, iv, sizeof ciphertext);
1632 for (j=0; j<1000; j++) {
1633 /* Save CT[j-1] */
1634 memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
1636 * If ( j=0 )
1637 * CT[j] = AES(Key[i], IV[i], PT[j])
1638 * PT[j+1] = IV[i] (= CT[j-1])
1639 * Else
1640 * CT[j] = AES(Key[i], PT[j])
1641 * PT[j+1] = CT[j-1]
1643 outputlen = 0;
1644 rv = AES_Encrypt(cx,
1645 ciphertext, &outputlen, sizeof ciphertext,
1646 plaintext, sizeof plaintext);
1647 if (rv != SECSuccess) {
1648 goto loser;
1650 if (outputlen != sizeof plaintext) {
1651 goto loser;
1654 /* doublecheck our result */
1655 outputlen = 0;
1656 rv = AES_Decrypt(cx2,
1657 doublecheck, &outputlen, sizeof doublecheck,
1658 ciphertext, sizeof ciphertext);
1659 if (rv != SECSuccess) {
1660 goto loser;
1662 if (outputlen != sizeof ciphertext) {
1663 goto loser;
1665 if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
1666 goto loser;
1669 memcpy(plaintext, ciphertext_1, sizeof plaintext);
1671 AES_DestroyContext(cx, PR_TRUE);
1672 cx = NULL;
1673 AES_DestroyContext(cx2, PR_TRUE);
1674 cx2 = NULL;
1676 /* Output CT[j] */
1677 fputs("CIPHERTEXT = ", aesresp);
1678 to_hex_str(buf, ciphertext, sizeof ciphertext);
1679 fputs(buf, aesresp);
1680 fputc('\n', aesresp);
1682 /* Key[i+1] = Key[i] xor ... */
1683 aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
1684 /* IV[i+1] = CT[j] */
1685 memcpy(iv, ciphertext, sizeof iv);
1686 /* PT[0] = CT[j-1] */
1687 /* done at the end of the for(j) loop */
1689 fputc('\n', aesresp);
1692 continue;
1694 /* CIPHERTEXT = ... */
1695 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1696 /* sanity check */
1697 if (encrypt) {
1698 goto loser;
1700 /* CT[0] = CT */
1701 i = 10;
1702 while (isspace(buf[i]) || buf[i] == '=') {
1703 i++;
1705 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1706 hex_to_byteval(&buf[i], &ciphertext[j]);
1709 for (i=0; i<100; i++) {
1710 sprintf(buf, "COUNT = %d\n", i);
1711 fputs(buf, aesresp);
1712 /* Output Key[i] */
1713 fputs("KEY = ", aesresp);
1714 to_hex_str(buf, key, keysize);
1715 fputs(buf, aesresp);
1716 fputc('\n', aesresp);
1717 /* Output IV[i] */
1718 fputs("IV = ", aesresp);
1719 to_hex_str(buf, iv, sizeof iv);
1720 fputs(buf, aesresp);
1721 fputc('\n', aesresp);
1722 /* Output CT[0] */
1723 fputs("CIPHERTEXT = ", aesresp);
1724 to_hex_str(buf, ciphertext, sizeof ciphertext);
1725 fputs(buf, aesresp);
1726 fputc('\n', aesresp);
1728 cx = AES_CreateContext(key, iv, NSS_AES_CBC,
1729 PR_FALSE, keysize, 16);
1730 if (cx == NULL) {
1731 goto loser;
1734 * doublecheck our result by encrypting the result
1735 * and comparing the output with the ciphertext.
1737 cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
1738 PR_TRUE, keysize, 16);
1739 if (cx2 == NULL) {
1740 goto loser;
1742 /* PT[-1] = IV[i] */
1743 memcpy(plaintext, iv, sizeof plaintext);
1744 for (j=0; j<1000; j++) {
1745 /* Save PT[j-1] */
1746 memcpy(plaintext_1, plaintext, sizeof plaintext);
1748 * If ( j=0 )
1749 * PT[j] = AES(Key[i], IV[i], CT[j])
1750 * CT[j+1] = IV[i] (= PT[j-1])
1751 * Else
1752 * PT[j] = AES(Key[i], CT[j])
1753 * CT[j+1] = PT[j-1]
1755 outputlen = 0;
1756 rv = AES_Decrypt(cx,
1757 plaintext, &outputlen, sizeof plaintext,
1758 ciphertext, sizeof ciphertext);
1759 if (rv != SECSuccess) {
1760 goto loser;
1762 if (outputlen != sizeof ciphertext) {
1763 goto loser;
1766 /* doublecheck our result */
1767 outputlen = 0;
1768 rv = AES_Encrypt(cx2,
1769 doublecheck, &outputlen, sizeof doublecheck,
1770 plaintext, sizeof plaintext);
1771 if (rv != SECSuccess) {
1772 goto loser;
1774 if (outputlen != sizeof plaintext) {
1775 goto loser;
1777 if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
1778 goto loser;
1781 memcpy(ciphertext, plaintext_1, sizeof ciphertext);
1783 AES_DestroyContext(cx, PR_TRUE);
1784 cx = NULL;
1785 AES_DestroyContext(cx2, PR_TRUE);
1786 cx2 = NULL;
1788 /* Output PT[j] */
1789 fputs("PLAINTEXT = ", aesresp);
1790 to_hex_str(buf, plaintext, sizeof plaintext);
1791 fputs(buf, aesresp);
1792 fputc('\n', aesresp);
1794 /* Key[i+1] = Key[i] xor ... */
1795 aes_mct_next_key(key, keysize, plaintext_1, plaintext);
1796 /* IV[i+1] = PT[j] */
1797 memcpy(iv, plaintext, sizeof iv);
1798 /* CT[0] = PT[j-1] */
1799 /* done at the end of the for(j) loop */
1801 fputc('\n', aesresp);
1804 continue;
1807 loser:
1808 if (cx != NULL) {
1809 AES_DestroyContext(cx, PR_TRUE);
1811 if (cx2 != NULL) {
1812 AES_DestroyContext(cx2, PR_TRUE);
1814 fclose(aesreq);
1817 void write_compact_string(FILE *out, unsigned char *hash, unsigned int len)
1819 unsigned int i;
1820 int j, count = 0, last = -1, z = 0;
1821 long start = ftell(out);
1822 for (i=0; i<len; i++) {
1823 for (j=7; j>=0; j--) {
1824 if (last < 0) {
1825 last = (hash[i] & (1 << j)) ? 1 : 0;
1826 fprintf(out, "%d ", last);
1827 count = 1;
1828 } else if (hash[i] & (1 << j)) {
1829 if (last) {
1830 count++;
1831 } else {
1832 last = 0;
1833 fprintf(out, "%d ", count);
1834 count = 1;
1835 z++;
1837 } else {
1838 if (!last) {
1839 count++;
1840 } else {
1841 last = 1;
1842 fprintf(out, "%d ", count);
1843 count = 1;
1844 z++;
1849 fprintf(out, "^\n");
1850 fseek(out, start, SEEK_SET);
1851 fprintf(out, "%d ", z);
1852 fseek(out, 0, SEEK_END);
1855 int get_next_line(FILE *req, char *key, char *val, FILE *rsp)
1857 int ignore = 0;
1858 char *writeto = key;
1859 int w = 0;
1860 int c;
1861 while ((c = fgetc(req)) != EOF) {
1862 if (ignore) {
1863 fprintf(rsp, "%c", c);
1864 if (c == '\n') return ignore;
1865 } else if (c == '\n') {
1866 break;
1867 } else if (c == '#') {
1868 ignore = 1;
1869 fprintf(rsp, "%c", c);
1870 } else if (c == '=') {
1871 writeto[w] = '\0';
1872 w = 0;
1873 writeto = val;
1874 } else if (c == ' ' || c == '[' || c == ']') {
1875 continue;
1876 } else {
1877 writeto[w++] = c;
1880 writeto[w] = '\0';
1881 return (c == EOF) ? -1 : ignore;
1884 #ifdef NSS_ENABLE_ECC
1885 typedef struct curveNameTagPairStr {
1886 char *curveName;
1887 SECOidTag curveOidTag;
1888 } CurveNameTagPair;
1890 #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
1891 /* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */
1893 static CurveNameTagPair nameTagPair[] =
1895 { "sect163k1", SEC_OID_SECG_EC_SECT163K1},
1896 { "nistk163", SEC_OID_SECG_EC_SECT163K1},
1897 { "sect163r1", SEC_OID_SECG_EC_SECT163R1},
1898 { "sect163r2", SEC_OID_SECG_EC_SECT163R2},
1899 { "nistb163", SEC_OID_SECG_EC_SECT163R2},
1900 { "sect193r1", SEC_OID_SECG_EC_SECT193R1},
1901 { "sect193r2", SEC_OID_SECG_EC_SECT193R2},
1902 { "sect233k1", SEC_OID_SECG_EC_SECT233K1},
1903 { "nistk233", SEC_OID_SECG_EC_SECT233K1},
1904 { "sect233r1", SEC_OID_SECG_EC_SECT233R1},
1905 { "nistb233", SEC_OID_SECG_EC_SECT233R1},
1906 { "sect239k1", SEC_OID_SECG_EC_SECT239K1},
1907 { "sect283k1", SEC_OID_SECG_EC_SECT283K1},
1908 { "nistk283", SEC_OID_SECG_EC_SECT283K1},
1909 { "sect283r1", SEC_OID_SECG_EC_SECT283R1},
1910 { "nistb283", SEC_OID_SECG_EC_SECT283R1},
1911 { "sect409k1", SEC_OID_SECG_EC_SECT409K1},
1912 { "nistk409", SEC_OID_SECG_EC_SECT409K1},
1913 { "sect409r1", SEC_OID_SECG_EC_SECT409R1},
1914 { "nistb409", SEC_OID_SECG_EC_SECT409R1},
1915 { "sect571k1", SEC_OID_SECG_EC_SECT571K1},
1916 { "nistk571", SEC_OID_SECG_EC_SECT571K1},
1917 { "sect571r1", SEC_OID_SECG_EC_SECT571R1},
1918 { "nistb571", SEC_OID_SECG_EC_SECT571R1},
1919 { "secp160k1", SEC_OID_SECG_EC_SECP160K1},
1920 { "secp160r1", SEC_OID_SECG_EC_SECP160R1},
1921 { "secp160r2", SEC_OID_SECG_EC_SECP160R2},
1922 { "secp192k1", SEC_OID_SECG_EC_SECP192K1},
1923 { "secp192r1", SEC_OID_SECG_EC_SECP192R1},
1924 { "nistp192", SEC_OID_SECG_EC_SECP192R1},
1925 { "secp224k1", SEC_OID_SECG_EC_SECP224K1},
1926 { "secp224r1", SEC_OID_SECG_EC_SECP224R1},
1927 { "nistp224", SEC_OID_SECG_EC_SECP224R1},
1928 { "secp256k1", SEC_OID_SECG_EC_SECP256K1},
1929 { "secp256r1", SEC_OID_SECG_EC_SECP256R1},
1930 { "nistp256", SEC_OID_SECG_EC_SECP256R1},
1931 { "secp384r1", SEC_OID_SECG_EC_SECP384R1},
1932 { "nistp384", SEC_OID_SECG_EC_SECP384R1},
1933 { "secp521r1", SEC_OID_SECG_EC_SECP521R1},
1934 { "nistp521", SEC_OID_SECG_EC_SECP521R1},
1936 { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
1937 { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
1938 { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
1939 { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
1940 { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
1941 { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
1943 { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
1944 { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
1945 { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
1946 { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
1947 { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
1948 { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
1949 { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
1950 { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
1951 { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
1952 { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
1953 { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
1954 { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
1955 { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
1956 { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
1957 { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
1958 { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
1959 { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
1960 { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
1961 { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
1962 { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
1964 { "secp112r1", SEC_OID_SECG_EC_SECP112R1},
1965 { "secp112r2", SEC_OID_SECG_EC_SECP112R2},
1966 { "secp128r1", SEC_OID_SECG_EC_SECP128R1},
1967 { "secp128r2", SEC_OID_SECG_EC_SECP128R2},
1969 { "sect113r1", SEC_OID_SECG_EC_SECT113R1},
1970 { "sect113r2", SEC_OID_SECG_EC_SECT113R2},
1971 { "sect131r1", SEC_OID_SECG_EC_SECT131R1},
1972 { "sect131r2", SEC_OID_SECG_EC_SECT131R2},
1975 static SECKEYECParams *
1976 getECParams(const char *curve)
1978 SECKEYECParams *ecparams;
1979 SECOidData *oidData = NULL;
1980 SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
1981 int i, numCurves;
1983 if (curve != NULL) {
1984 numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair);
1985 for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN));
1986 i++) {
1987 if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
1988 curveOidTag = nameTagPair[i].curveOidTag;
1992 /* Return NULL if curve name is not recognized */
1993 if ((curveOidTag == SEC_OID_UNKNOWN) ||
1994 (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
1995 fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
1996 return NULL;
1999 ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
2002 * ecparams->data needs to contain the ASN encoding of an object ID (OID)
2003 * representing the named curve. The actual OID is in
2004 * oidData->oid.data so we simply prepend 0x06 and OID length
2006 ecparams->data[0] = SEC_ASN1_OBJECT_ID;
2007 ecparams->data[1] = oidData->oid.len;
2008 memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
2010 return ecparams;
2014 * Perform the ECDSA Key Pair Generation Test.
2016 * reqfn is the pathname of the REQUEST file.
2018 * The output RESPONSE file is written to stdout.
2020 void
2021 ecdsa_keypair_test(char *reqfn)
2023 char buf[256]; /* holds one line from the input REQUEST file
2024 * or to the output RESPONSE file.
2025 * needs to be large enough to hold the longest
2026 * line "Qx = <144 hex digits>\n".
2028 FILE *ecdsareq; /* input stream from the REQUEST file */
2029 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2030 char curve[16]; /* "nistxddd" */
2031 ECParams *ecparams;
2032 int N;
2033 int i;
2034 unsigned int len;
2036 ecdsareq = fopen(reqfn, "r");
2037 ecdsaresp = stdout;
2038 strcpy(curve, "nist");
2039 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2040 /* a comment or blank line */
2041 if (buf[0] == '#' || buf[0] == '\n') {
2042 fputs(buf, ecdsaresp);
2043 continue;
2045 /* [X-ddd] */
2046 if (buf[0] == '[') {
2047 const char *src;
2048 char *dst;
2049 SECKEYECParams *encodedparams;
2051 src = &buf[1];
2052 dst = &curve[4];
2053 *dst++ = tolower(*src);
2054 src += 2; /* skip the hyphen */
2055 *dst++ = *src++;
2056 *dst++ = *src++;
2057 *dst++ = *src++;
2058 *dst = '\0';
2059 encodedparams = getECParams(curve);
2060 if (encodedparams == NULL) {
2061 goto loser;
2063 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2064 goto loser;
2066 SECITEM_FreeItem(encodedparams, PR_TRUE);
2067 fputs(buf, ecdsaresp);
2068 continue;
2070 /* N = x */
2071 if (buf[0] == 'N') {
2072 if (sscanf(buf, "N = %d", &N) != 1) {
2073 goto loser;
2075 for (i = 0; i < N; i++) {
2076 ECPrivateKey *ecpriv;
2078 if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
2079 goto loser;
2081 fputs("d = ", ecdsaresp);
2082 to_hex_str(buf, ecpriv->privateValue.data,
2083 ecpriv->privateValue.len);
2084 fputs(buf, ecdsaresp);
2085 fputc('\n', ecdsaresp);
2086 if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
2087 != SECSuccess) {
2088 goto loser;
2090 len = ecpriv->publicValue.len;
2091 if (len%2 == 0) {
2092 goto loser;
2094 len = (len-1)/2;
2095 if (ecpriv->publicValue.data[0]
2096 != EC_POINT_FORM_UNCOMPRESSED) {
2097 goto loser;
2099 fputs("Qx = ", ecdsaresp);
2100 to_hex_str(buf, &ecpriv->publicValue.data[1], len);
2101 fputs(buf, ecdsaresp);
2102 fputc('\n', ecdsaresp);
2103 fputs("Qy = ", ecdsaresp);
2104 to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
2105 fputs(buf, ecdsaresp);
2106 fputc('\n', ecdsaresp);
2107 fputc('\n', ecdsaresp);
2108 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
2110 PORT_FreeArena(ecparams->arena, PR_FALSE);
2111 continue;
2114 loser:
2115 fclose(ecdsareq);
2119 * Perform the ECDSA Public Key Validation Test.
2121 * reqfn is the pathname of the REQUEST file.
2123 * The output RESPONSE file is written to stdout.
2125 void
2126 ecdsa_pkv_test(char *reqfn)
2128 char buf[256]; /* holds one line from the input REQUEST file.
2129 * needs to be large enough to hold the longest
2130 * line "Qx = <144 hex digits>\n".
2132 FILE *ecdsareq; /* input stream from the REQUEST file */
2133 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2134 char curve[16]; /* "nistxddd" */
2135 ECParams *ecparams = NULL;
2136 SECItem pubkey;
2137 unsigned int i;
2138 unsigned int len;
2139 PRBool keyvalid = PR_TRUE;
2141 ecdsareq = fopen(reqfn, "r");
2142 ecdsaresp = stdout;
2143 strcpy(curve, "nist");
2144 pubkey.data = NULL;
2145 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2146 /* a comment or blank line */
2147 if (buf[0] == '#' || buf[0] == '\n') {
2148 fputs(buf, ecdsaresp);
2149 continue;
2151 /* [X-ddd] */
2152 if (buf[0] == '[') {
2153 const char *src;
2154 char *dst;
2155 SECKEYECParams *encodedparams;
2157 src = &buf[1];
2158 dst = &curve[4];
2159 *dst++ = tolower(*src);
2160 src += 2; /* skip the hyphen */
2161 *dst++ = *src++;
2162 *dst++ = *src++;
2163 *dst++ = *src++;
2164 *dst = '\0';
2165 if (ecparams != NULL) {
2166 PORT_FreeArena(ecparams->arena, PR_FALSE);
2167 ecparams = NULL;
2169 encodedparams = getECParams(curve);
2170 if (encodedparams == NULL) {
2171 goto loser;
2173 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2174 goto loser;
2176 SECITEM_FreeItem(encodedparams, PR_TRUE);
2177 len = (ecparams->fieldID.size + 7) >> 3;
2178 if (pubkey.data != NULL) {
2179 PORT_Free(pubkey.data);
2180 pubkey.data = NULL;
2182 SECITEM_AllocItem(NULL, &pubkey, 2*len+1);
2183 if (pubkey.data == NULL) {
2184 goto loser;
2186 pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
2187 fputs(buf, ecdsaresp);
2188 continue;
2190 /* Qx = ... */
2191 if (strncmp(buf, "Qx", 2) == 0) {
2192 fputs(buf, ecdsaresp);
2193 i = 2;
2194 while (isspace(buf[i]) || buf[i] == '=') {
2195 i++;
2197 keyvalid = from_hex_str(&pubkey.data[1], len, &buf[i]);
2198 continue;
2200 /* Qy = ... */
2201 if (strncmp(buf, "Qy", 2) == 0) {
2202 fputs(buf, ecdsaresp);
2203 if (!keyvalid) {
2204 fputs("Result = F\n", ecdsaresp);
2205 continue;
2207 i = 2;
2208 while (isspace(buf[i]) || buf[i] == '=') {
2209 i++;
2211 keyvalid = from_hex_str(&pubkey.data[1+len], len, &buf[i]);
2212 if (!keyvalid) {
2213 fputs("Result = F\n", ecdsaresp);
2214 continue;
2216 if (EC_ValidatePublicKey(ecparams, &pubkey) == SECSuccess) {
2217 fputs("Result = P\n", ecdsaresp);
2218 } else if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
2219 fputs("Result = F\n", ecdsaresp);
2220 } else {
2221 goto loser;
2223 continue;
2226 loser:
2227 if (ecparams != NULL) {
2228 PORT_FreeArena(ecparams->arena, PR_FALSE);
2230 if (pubkey.data != NULL) {
2231 PORT_Free(pubkey.data);
2233 fclose(ecdsareq);
2237 * Perform the ECDSA Signature Generation Test.
2239 * reqfn is the pathname of the REQUEST file.
2241 * The output RESPONSE file is written to stdout.
2243 void
2244 ecdsa_siggen_test(char *reqfn)
2246 char buf[1024]; /* holds one line from the input REQUEST file
2247 * or to the output RESPONSE file.
2248 * needs to be large enough to hold the longest
2249 * line "Msg = <256 hex digits>\n".
2251 FILE *ecdsareq; /* input stream from the REQUEST file */
2252 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2253 char curve[16]; /* "nistxddd" */
2254 ECParams *ecparams = NULL;
2255 int i, j;
2256 unsigned int len;
2257 unsigned char msg[512]; /* message to be signed (<= 128 bytes) */
2258 unsigned int msglen;
2259 unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
2260 unsigned char sig[2*MAX_ECKEY_LEN];
2261 SECItem signature, digest;
2263 ecdsareq = fopen(reqfn, "r");
2264 ecdsaresp = stdout;
2265 strcpy(curve, "nist");
2266 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2267 /* a comment or blank line */
2268 if (buf[0] == '#' || buf[0] == '\n') {
2269 fputs(buf, ecdsaresp);
2270 continue;
2272 /* [X-ddd] */
2273 if (buf[0] == '[') {
2274 const char *src;
2275 char *dst;
2276 SECKEYECParams *encodedparams;
2278 src = &buf[1];
2279 dst = &curve[4];
2280 *dst++ = tolower(*src);
2281 src += 2; /* skip the hyphen */
2282 *dst++ = *src++;
2283 *dst++ = *src++;
2284 *dst++ = *src++;
2285 *dst = '\0';
2286 if (ecparams != NULL) {
2287 PORT_FreeArena(ecparams->arena, PR_FALSE);
2288 ecparams = NULL;
2290 encodedparams = getECParams(curve);
2291 if (encodedparams == NULL) {
2292 goto loser;
2294 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2295 goto loser;
2297 SECITEM_FreeItem(encodedparams, PR_TRUE);
2298 fputs(buf, ecdsaresp);
2299 continue;
2301 /* Msg = ... */
2302 if (strncmp(buf, "Msg", 3) == 0) {
2303 ECPrivateKey *ecpriv;
2305 i = 3;
2306 while (isspace(buf[i]) || buf[i] == '=') {
2307 i++;
2309 for (j=0; isxdigit(buf[i]); i+=2,j++) {
2310 hex_to_byteval(&buf[i], &msg[j]);
2312 msglen = j;
2313 if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
2314 goto loser;
2316 fputs(buf, ecdsaresp);
2318 if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
2319 goto loser;
2321 if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
2322 != SECSuccess) {
2323 goto loser;
2325 len = ecpriv->publicValue.len;
2326 if (len%2 == 0) {
2327 goto loser;
2329 len = (len-1)/2;
2330 if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
2331 goto loser;
2333 fputs("Qx = ", ecdsaresp);
2334 to_hex_str(buf, &ecpriv->publicValue.data[1], len);
2335 fputs(buf, ecdsaresp);
2336 fputc('\n', ecdsaresp);
2337 fputs("Qy = ", ecdsaresp);
2338 to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
2339 fputs(buf, ecdsaresp);
2340 fputc('\n', ecdsaresp);
2342 digest.type = siBuffer;
2343 digest.data = sha1;
2344 digest.len = sizeof sha1;
2345 signature.type = siBuffer;
2346 signature.data = sig;
2347 signature.len = sizeof sig;
2348 if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) {
2349 goto loser;
2351 len = signature.len;
2352 if (len%2 != 0) {
2353 goto loser;
2355 len = len/2;
2356 fputs("R = ", ecdsaresp);
2357 to_hex_str(buf, &signature.data[0], len);
2358 fputs(buf, ecdsaresp);
2359 fputc('\n', ecdsaresp);
2360 fputs("S = ", ecdsaresp);
2361 to_hex_str(buf, &signature.data[len], len);
2362 fputs(buf, ecdsaresp);
2363 fputc('\n', ecdsaresp);
2365 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
2366 continue;
2369 loser:
2370 if (ecparams != NULL) {
2371 PORT_FreeArena(ecparams->arena, PR_FALSE);
2373 fclose(ecdsareq);
2377 * Perform the ECDSA Signature Verification Test.
2379 * reqfn is the pathname of the REQUEST file.
2381 * The output RESPONSE file is written to stdout.
2383 void
2384 ecdsa_sigver_test(char *reqfn)
2386 char buf[1024]; /* holds one line from the input REQUEST file.
2387 * needs to be large enough to hold the longest
2388 * line "Msg = <256 hex digits>\n".
2390 FILE *ecdsareq; /* input stream from the REQUEST file */
2391 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2392 char curve[16]; /* "nistxddd" */
2393 ECPublicKey ecpub;
2394 unsigned int i, j;
2395 unsigned int flen; /* length in bytes of the field size */
2396 unsigned int olen; /* length in bytes of the base point order */
2397 unsigned char msg[512]; /* message that was signed (<= 128 bytes) */
2398 unsigned int msglen;
2399 unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
2400 unsigned char sig[2*MAX_ECKEY_LEN];
2401 SECItem signature, digest;
2402 PRBool keyvalid = PR_TRUE;
2403 PRBool sigvalid = PR_TRUE;
2405 ecdsareq = fopen(reqfn, "r");
2406 ecdsaresp = stdout;
2407 ecpub.ecParams.arena = NULL;
2408 strcpy(curve, "nist");
2409 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2410 /* a comment or blank line */
2411 if (buf[0] == '#' || buf[0] == '\n') {
2412 fputs(buf, ecdsaresp);
2413 continue;
2415 /* [X-ddd] */
2416 if (buf[0] == '[') {
2417 const char *src;
2418 char *dst;
2419 SECKEYECParams *encodedparams;
2420 ECParams *ecparams;
2422 src = &buf[1];
2423 dst = &curve[4];
2424 *dst++ = tolower(*src);
2425 src += 2; /* skip the hyphen */
2426 *dst++ = *src++;
2427 *dst++ = *src++;
2428 *dst++ = *src++;
2429 *dst = '\0';
2430 encodedparams = getECParams(curve);
2431 if (encodedparams == NULL) {
2432 goto loser;
2434 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2435 goto loser;
2437 SECITEM_FreeItem(encodedparams, PR_TRUE);
2438 if (ecpub.ecParams.arena != NULL) {
2439 PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
2441 ecpub.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2442 if (ecpub.ecParams.arena == NULL) {
2443 goto loser;
2445 if (EC_CopyParams(ecpub.ecParams.arena, &ecpub.ecParams, ecparams)
2446 != SECSuccess) {
2447 goto loser;
2449 PORT_FreeArena(ecparams->arena, PR_FALSE);
2450 flen = (ecpub.ecParams.fieldID.size + 7) >> 3;
2451 olen = ecpub.ecParams.order.len;
2452 if (2*olen > sizeof sig) {
2453 goto loser;
2455 ecpub.publicValue.type = siBuffer;
2456 ecpub.publicValue.data = NULL;
2457 ecpub.publicValue.len = 0;
2458 SECITEM_AllocItem(ecpub.ecParams.arena,
2459 &ecpub.publicValue, 2*flen+1);
2460 if (ecpub.publicValue.data == NULL) {
2461 goto loser;
2463 ecpub.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED;
2464 fputs(buf, ecdsaresp);
2465 continue;
2467 /* Msg = ... */
2468 if (strncmp(buf, "Msg", 3) == 0) {
2469 i = 3;
2470 while (isspace(buf[i]) || buf[i] == '=') {
2471 i++;
2473 for (j=0; isxdigit(buf[i]); i+=2,j++) {
2474 hex_to_byteval(&buf[i], &msg[j]);
2476 msglen = j;
2477 if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
2478 goto loser;
2480 fputs(buf, ecdsaresp);
2482 digest.type = siBuffer;
2483 digest.data = sha1;
2484 digest.len = sizeof sha1;
2486 continue;
2488 /* Qx = ... */
2489 if (strncmp(buf, "Qx", 2) == 0) {
2490 fputs(buf, ecdsaresp);
2491 i = 2;
2492 while (isspace(buf[i]) || buf[i] == '=') {
2493 i++;
2495 keyvalid = from_hex_str(&ecpub.publicValue.data[1], flen,
2496 &buf[i]);
2497 continue;
2499 /* Qy = ... */
2500 if (strncmp(buf, "Qy", 2) == 0) {
2501 fputs(buf, ecdsaresp);
2502 if (!keyvalid) {
2503 continue;
2505 i = 2;
2506 while (isspace(buf[i]) || buf[i] == '=') {
2507 i++;
2509 keyvalid = from_hex_str(&ecpub.publicValue.data[1+flen], flen,
2510 &buf[i]);
2511 if (!keyvalid) {
2512 continue;
2514 if (EC_ValidatePublicKey(&ecpub.ecParams, &ecpub.publicValue)
2515 != SECSuccess) {
2516 if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
2517 keyvalid = PR_FALSE;
2518 } else {
2519 goto loser;
2522 continue;
2524 /* R = ... */
2525 if (buf[0] == 'R') {
2526 fputs(buf, ecdsaresp);
2527 i = 1;
2528 while (isspace(buf[i]) || buf[i] == '=') {
2529 i++;
2531 sigvalid = from_hex_str(sig, olen, &buf[i]);
2532 continue;
2534 /* S = ... */
2535 if (buf[0] == 'S') {
2536 fputs(buf, ecdsaresp);
2537 i = 1;
2538 while (isspace(buf[i]) || buf[i] == '=') {
2539 i++;
2541 if (sigvalid) {
2542 sigvalid = from_hex_str(&sig[olen], olen, &buf[i]);
2544 signature.type = siBuffer;
2545 signature.data = sig;
2546 signature.len = 2*olen;
2548 if (!keyvalid || !sigvalid) {
2549 fputs("Result = F\n", ecdsaresp);
2550 } else if (ECDSA_VerifyDigest(&ecpub, &signature, &digest)
2551 == SECSuccess) {
2552 fputs("Result = P\n", ecdsaresp);
2553 } else {
2554 fputs("Result = F\n", ecdsaresp);
2556 continue;
2559 loser:
2560 if (ecpub.ecParams.arena != NULL) {
2561 PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
2563 fclose(ecdsareq);
2565 #endif /* NSS_ENABLE_ECC */
2568 * Perform the RNG Variable Seed Test (VST) for the RNG algorithm
2569 * "DSA - Generation of X", used both as specified and as a generic
2570 * purpose RNG. The presence of "Q = ..." in the REQUEST file
2571 * indicates we are using the algorithm as specified.
2573 * reqfn is the pathname of the REQUEST file.
2575 * The output RESPONSE file is written to stdout.
2577 void
2578 rng_vst(char *reqfn)
2580 char buf[256]; /* holds one line from the input REQUEST file.
2581 * needs to be large enough to hold the longest
2582 * line "XSeed = <128 hex digits>\n".
2584 FILE *rngreq; /* input stream from the REQUEST file */
2585 FILE *rngresp; /* output stream to the RESPONSE file */
2586 unsigned int i, j;
2587 unsigned char Q[DSA_SUBPRIME_LEN];
2588 PRBool hasQ = PR_FALSE;
2589 unsigned int b; /* 160 <= b <= 512, b is a multiple of 8 */
2590 unsigned char XKey[512/8];
2591 unsigned char XSeed[512/8];
2592 unsigned char GENX[2*SHA1_LENGTH];
2593 unsigned char DSAX[DSA_SUBPRIME_LEN];
2594 SECStatus rv;
2596 rngreq = fopen(reqfn, "r");
2597 rngresp = stdout;
2598 while (fgets(buf, sizeof buf, rngreq) != NULL) {
2599 /* a comment or blank line */
2600 if (buf[0] == '#' || buf[0] == '\n') {
2601 fputs(buf, rngresp);
2602 continue;
2604 /* [Xchange - SHA1] */
2605 if (buf[0] == '[') {
2606 fputs(buf, rngresp);
2607 continue;
2609 /* Q = ... */
2610 if (buf[0] == 'Q') {
2611 i = 1;
2612 while (isspace(buf[i]) || buf[i] == '=') {
2613 i++;
2615 for (j=0; j<sizeof Q; i+=2,j++) {
2616 hex_to_byteval(&buf[i], &Q[j]);
2618 fputs(buf, rngresp);
2619 hasQ = PR_TRUE;
2620 continue;
2622 /* "COUNT = x" begins a new data set */
2623 if (strncmp(buf, "COUNT", 5) == 0) {
2624 /* zeroize the variables for the test with this data set */
2625 b = 0;
2626 memset(XKey, 0, sizeof XKey);
2627 memset(XSeed, 0, sizeof XSeed);
2628 fputs(buf, rngresp);
2629 continue;
2631 /* b = ... */
2632 if (buf[0] == 'b') {
2633 i = 1;
2634 while (isspace(buf[i]) || buf[i] == '=') {
2635 i++;
2637 b = atoi(&buf[i]);
2638 if (b < 160 || b > 512 || b%8 != 0) {
2639 goto loser;
2641 fputs(buf, rngresp);
2642 continue;
2644 /* XKey = ... */
2645 if (strncmp(buf, "XKey", 4) == 0) {
2646 i = 4;
2647 while (isspace(buf[i]) || buf[i] == '=') {
2648 i++;
2650 for (j=0; j<b/8; i+=2,j++) {
2651 hex_to_byteval(&buf[i], &XKey[j]);
2653 fputs(buf, rngresp);
2654 continue;
2656 /* XSeed = ... */
2657 if (strncmp(buf, "XSeed", 5) == 0) {
2658 i = 5;
2659 while (isspace(buf[i]) || buf[i] == '=') {
2660 i++;
2662 for (j=0; j<b/8; i+=2,j++) {
2663 hex_to_byteval(&buf[i], &XSeed[j]);
2665 fputs(buf, rngresp);
2667 rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
2668 if (rv != SECSuccess) {
2669 goto loser;
2671 fputs("X = ", rngresp);
2672 if (hasQ) {
2673 rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
2674 if (rv != SECSuccess) {
2675 goto loser;
2677 to_hex_str(buf, DSAX, sizeof DSAX);
2678 } else {
2679 to_hex_str(buf, GENX, sizeof GENX);
2681 fputs(buf, rngresp);
2682 fputc('\n', rngresp);
2683 continue;
2686 loser:
2687 fclose(rngreq);
2691 * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm
2692 * "DSA - Generation of X", used both as specified and as a generic
2693 * purpose RNG. The presence of "Q = ..." in the REQUEST file
2694 * indicates we are using the algorithm as specified.
2696 * reqfn is the pathname of the REQUEST file.
2698 * The output RESPONSE file is written to stdout.
2700 void
2701 rng_mct(char *reqfn)
2703 char buf[256]; /* holds one line from the input REQUEST file.
2704 * needs to be large enough to hold the longest
2705 * line "XSeed = <128 hex digits>\n".
2707 FILE *rngreq; /* input stream from the REQUEST file */
2708 FILE *rngresp; /* output stream to the RESPONSE file */
2709 unsigned int i, j;
2710 unsigned char Q[DSA_SUBPRIME_LEN];
2711 PRBool hasQ = PR_FALSE;
2712 unsigned int b; /* 160 <= b <= 512, b is a multiple of 8 */
2713 unsigned char XKey[512/8];
2714 unsigned char XSeed[512/8];
2715 unsigned char GENX[2*SHA1_LENGTH];
2716 unsigned char DSAX[DSA_SUBPRIME_LEN];
2717 SECStatus rv;
2719 rngreq = fopen(reqfn, "r");
2720 rngresp = stdout;
2721 while (fgets(buf, sizeof buf, rngreq) != NULL) {
2722 /* a comment or blank line */
2723 if (buf[0] == '#' || buf[0] == '\n') {
2724 fputs(buf, rngresp);
2725 continue;
2727 /* [Xchange - SHA1] */
2728 if (buf[0] == '[') {
2729 fputs(buf, rngresp);
2730 continue;
2732 /* Q = ... */
2733 if (buf[0] == 'Q') {
2734 i = 1;
2735 while (isspace(buf[i]) || buf[i] == '=') {
2736 i++;
2738 for (j=0; j<sizeof Q; i+=2,j++) {
2739 hex_to_byteval(&buf[i], &Q[j]);
2741 fputs(buf, rngresp);
2742 hasQ = PR_TRUE;
2743 continue;
2745 /* "COUNT = x" begins a new data set */
2746 if (strncmp(buf, "COUNT", 5) == 0) {
2747 /* zeroize the variables for the test with this data set */
2748 b = 0;
2749 memset(XKey, 0, sizeof XKey);
2750 memset(XSeed, 0, sizeof XSeed);
2751 fputs(buf, rngresp);
2752 continue;
2754 /* b = ... */
2755 if (buf[0] == 'b') {
2756 i = 1;
2757 while (isspace(buf[i]) || buf[i] == '=') {
2758 i++;
2760 b = atoi(&buf[i]);
2761 if (b < 160 || b > 512 || b%8 != 0) {
2762 goto loser;
2764 fputs(buf, rngresp);
2765 continue;
2767 /* XKey = ... */
2768 if (strncmp(buf, "XKey", 4) == 0) {
2769 i = 4;
2770 while (isspace(buf[i]) || buf[i] == '=') {
2771 i++;
2773 for (j=0; j<b/8; i+=2,j++) {
2774 hex_to_byteval(&buf[i], &XKey[j]);
2776 fputs(buf, rngresp);
2777 continue;
2779 /* XSeed = ... */
2780 if (strncmp(buf, "XSeed", 5) == 0) {
2781 unsigned int k;
2782 i = 5;
2783 while (isspace(buf[i]) || buf[i] == '=') {
2784 i++;
2786 for (j=0; j<b/8; i+=2,j++) {
2787 hex_to_byteval(&buf[i], &XSeed[j]);
2789 fputs(buf, rngresp);
2791 for (k = 0; k < 10000; k++) {
2792 rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
2793 if (rv != SECSuccess) {
2794 goto loser;
2797 fputs("X = ", rngresp);
2798 if (hasQ) {
2799 rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
2800 if (rv != SECSuccess) {
2801 goto loser;
2803 to_hex_str(buf, DSAX, sizeof DSAX);
2804 } else {
2805 to_hex_str(buf, GENX, sizeof GENX);
2807 fputs(buf, rngresp);
2808 fputc('\n', rngresp);
2809 continue;
2812 loser:
2813 fclose(rngreq);
2817 * Calculate the SHA Message Digest
2819 * MD = Message digest
2820 * MDLen = length of Message Digest and SHA_Type
2821 * msg = message to digest
2822 * msgLen = length of message to digest
2824 SECStatus sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen)
2826 SECStatus sha_status = SECFailure;
2828 if (MDLen == SHA1_LENGTH) {
2829 sha_status = SHA1_HashBuf(MD, msg, msgLen);
2830 } else if (MDLen == SHA256_LENGTH) {
2831 sha_status = SHA256_HashBuf(MD, msg, msgLen);
2832 } else if (MDLen == SHA384_LENGTH) {
2833 sha_status = SHA384_HashBuf(MD, msg, msgLen);
2834 } else if (MDLen == SHA512_LENGTH) {
2835 sha_status = SHA512_HashBuf(MD, msg, msgLen);
2838 return sha_status;
2842 * Perform the SHA Monte Carlo Test
2844 * MDLen = length of Message Digest and SHA_Type
2845 * seed = input seed value
2846 * resp = is the output response file.
2848 SECStatus sha_mct_test(unsigned int MDLen, unsigned char *seed, FILE *resp)
2850 int i, j;
2851 unsigned int msgLen = MDLen*3;
2852 unsigned char MD_i3[HASH_LENGTH_MAX]; /* MD[i-3] */
2853 unsigned char MD_i2[HASH_LENGTH_MAX]; /* MD[i-2] */
2854 unsigned char MD_i1[HASH_LENGTH_MAX]; /* MD[i-1] */
2855 unsigned char MD_i[HASH_LENGTH_MAX]; /* MD[i] */
2856 unsigned char msg[HASH_LENGTH_MAX*3];
2857 char buf[HASH_LENGTH_MAX*2 + 1]; /* MAX buf MD_i as a hex string */
2859 for (j=0; j<100; j++) {
2860 /* MD_0 = MD_1 = MD_2 = seed */
2861 memcpy(MD_i3, seed, MDLen);
2862 memcpy(MD_i2, seed, MDLen);
2863 memcpy(MD_i1, seed, MDLen);
2865 for (i=3; i < 1003; i++) {
2866 /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */
2867 memcpy(msg, MD_i3, MDLen);
2868 memcpy(&msg[MDLen], MD_i2, MDLen);
2869 memcpy(&msg[MDLen*2], MD_i1,MDLen);
2871 /* MDi = SHA(Msg) */
2872 if (sha_calcMD(MD_i, MDLen,
2873 msg, msgLen) != SECSuccess) {
2874 return SECFailure;
2877 /* save MD[i-3] MD[i-2] MD[i-1] */
2878 memcpy(MD_i3, MD_i2, MDLen);
2879 memcpy(MD_i2, MD_i1, MDLen);
2880 memcpy(MD_i1, MD_i, MDLen);
2884 /* seed = MD_i */
2885 memcpy(seed, MD_i, MDLen);
2887 sprintf(buf, "COUNT = %d\n", j);
2888 fputs(buf, resp);
2890 /* output MD_i */
2891 fputs("MD = ", resp);
2892 to_hex_str(buf, MD_i, MDLen);
2893 fputs(buf, resp);
2894 fputc('\n', resp);
2897 return SECSuccess;
2901 * Perform the SHA Tests.
2903 * reqfn is the pathname of the input REQUEST file.
2905 * The output RESPONSE file is written to stdout.
2907 void sha_test(char *reqfn)
2909 unsigned int i, j;
2910 unsigned int MDlen; /* the length of the Message Digest in Bytes */
2911 unsigned int msgLen; /* the length of the input Message in Bytes */
2912 unsigned char *msg = NULL; /* holds the message to digest.*/
2913 size_t bufSize = 25608; /*MAX buffer size */
2914 char *buf = NULL; /* holds one line from the input REQUEST file.*/
2915 unsigned char seed[HASH_LENGTH_MAX]; /* max size of seed 64 bytes */
2916 unsigned char MD[HASH_LENGTH_MAX]; /* message digest */
2918 FILE *req = NULL; /* input stream from the REQUEST file */
2919 FILE *resp; /* output stream to the RESPONSE file */
2921 buf = PORT_ZAlloc(bufSize);
2922 if (buf == NULL) {
2923 goto loser;
2926 /* zeroize the variables for the test with this data set */
2927 memset(seed, 0, sizeof seed);
2929 req = fopen(reqfn, "r");
2930 resp = stdout;
2931 while (fgets(buf, bufSize, req) != NULL) {
2933 /* a comment or blank line */
2934 if (buf[0] == '#' || buf[0] == '\n') {
2935 fputs(buf, resp);
2936 continue;
2938 /* [L = Length of the Message Digest and sha_type */
2939 if (buf[0] == '[') {
2940 if (strncmp(&buf[1], "L ", 1) == 0) {
2941 i = 2;
2942 while (isspace(buf[i]) || buf[i] == '=') {
2943 i++;
2945 MDlen = atoi(&buf[i]);
2946 fputs(buf, resp);
2947 continue;
2950 /* Len = Length of the Input Message Length ... */
2951 if (strncmp(buf, "Len", 3) == 0) {
2952 i = 3;
2953 while (isspace(buf[i]) || buf[i] == '=') {
2954 i++;
2956 if (msg) {
2957 PORT_ZFree(msg,msgLen);
2958 msg = NULL;
2960 msgLen = atoi(&buf[i]); /* in bits */
2961 if (msgLen%8 != 0) {
2962 fprintf(stderr, "SHA tests are incorrectly configured for "
2963 "BIT oriented implementations\n");
2964 goto loser;
2966 msgLen = msgLen/8; /* convert to bytes */
2967 fputs(buf, resp);
2968 msg = PORT_ZAlloc(msgLen);
2969 if (msg == NULL && msgLen != 0) {
2970 goto loser;
2972 continue;
2974 /* MSG = ... */
2975 if (strncmp(buf, "Msg", 3) == 0) {
2976 i = 3;
2977 while (isspace(buf[i]) || buf[i] == '=') {
2978 i++;
2980 for (j=0; j< msgLen; i+=2,j++) {
2981 hex_to_byteval(&buf[i], &msg[j]);
2983 fputs(buf, resp);
2984 /* calculate the Message Digest */
2985 memset(MD, 0, sizeof MD);
2986 if (sha_calcMD(MD, MDlen,
2987 msg, msgLen) != SECSuccess) {
2988 goto loser;
2991 fputs("MD = ", resp);
2992 to_hex_str(buf, MD, MDlen);
2993 fputs(buf, resp);
2994 fputc('\n', resp);
2996 continue;
2998 /* Seed = ... */
2999 if (strncmp(buf, "Seed", 4) == 0) {
3000 i = 4;
3001 while (isspace(buf[i]) || buf[i] == '=') {
3002 i++;
3004 for (j=0; j<sizeof seed; i+=2,j++) {
3005 hex_to_byteval(&buf[i], &seed[j]);
3008 fputs(buf, resp);
3009 fputc('\n', resp);
3011 /* do the Monte Carlo test */
3012 if (sha_mct_test(MDlen, seed, resp) != SECSuccess) {
3013 goto loser;
3016 continue;
3019 loser:
3020 if (req) {
3021 fclose(req);
3023 if (buf) {
3024 PORT_ZFree(buf, bufSize);
3026 if (msg) {
3027 PORT_ZFree(msg, msgLen);
3031 /****************************************************/
3032 /* HMAC SHA-X calc */
3033 /* hmac_computed - the computed HMAC */
3034 /* hmac_length - the length of the computed HMAC */
3035 /* secret_key - secret key to HMAC */
3036 /* secret_key_length - length of secret key, */
3037 /* message - message to HMAC */
3038 /* message_length - length ofthe message */
3039 /****************************************************/
3040 static SECStatus
3041 hmac_calc(unsigned char *hmac_computed,
3042 const unsigned int hmac_length,
3043 const unsigned char *secret_key,
3044 const unsigned int secret_key_length,
3045 const unsigned char *message,
3046 const unsigned int message_length,
3047 const HASH_HashType hashAlg )
3049 SECStatus hmac_status = SECFailure;
3050 HMACContext *cx = NULL;
3051 SECHashObject *hashObj = NULL;
3052 unsigned int bytes_hashed = 0;
3054 hashObj = (SECHashObject *) HASH_GetRawHashObject(hashAlg);
3056 if (!hashObj)
3057 return( SECFailure );
3059 cx = HMAC_Create(hashObj, secret_key,
3060 secret_key_length,
3061 PR_TRUE); /* PR_TRUE for in FIPS mode */
3063 if (cx == NULL)
3064 return( SECFailure );
3066 HMAC_Begin(cx);
3067 HMAC_Update(cx, message, message_length);
3068 hmac_status = HMAC_Finish(cx, hmac_computed, &bytes_hashed,
3069 hmac_length);
3071 HMAC_Destroy(cx, PR_TRUE);
3073 return( hmac_status );
3077 * Perform the HMAC Tests.
3079 * reqfn is the pathname of the input REQUEST file.
3081 * The output RESPONSE file is written to stdout.
3083 void hmac_test(char *reqfn)
3085 unsigned int i, j;
3086 size_t bufSize = 288; /* MAX buffer size */
3087 char *buf = NULL; /* holds one line from the input REQUEST file.*/
3088 unsigned int keyLen; /* Key Length */
3089 unsigned char key[140]; /* key MAX size = 140 */
3090 unsigned int msgLen = 128; /* the length of the input */
3091 /* Message is always 128 Bytes */
3092 unsigned char *msg = NULL; /* holds the message to digest.*/
3093 unsigned int HMACLen; /* the length of the HMAC Bytes */
3094 unsigned char HMAC[HASH_LENGTH_MAX]; /* computed HMAC */
3095 HASH_HashType hash_alg; /* HMAC type */
3097 FILE *req = NULL; /* input stream from the REQUEST file */
3098 FILE *resp; /* output stream to the RESPONSE file */
3100 buf = PORT_ZAlloc(bufSize);
3101 if (buf == NULL) {
3102 goto loser;
3104 msg = PORT_ZAlloc(msgLen);
3105 memset(msg, 0, msgLen);
3106 if (msg == NULL) {
3107 goto loser;
3110 req = fopen(reqfn, "r");
3111 resp = stdout;
3112 while (fgets(buf, bufSize, req) != NULL) {
3114 /* a comment or blank line */
3115 if (buf[0] == '#' || buf[0] == '\n') {
3116 fputs(buf, resp);
3117 continue;
3119 /* [L = Length of the MAC and HASH_type */
3120 if (buf[0] == '[') {
3121 if (strncmp(&buf[1], "L ", 1) == 0) {
3122 i = 2;
3123 while (isspace(buf[i]) || buf[i] == '=') {
3124 i++;
3126 /* HMACLen will get reused for Tlen */
3127 HMACLen = atoi(&buf[i]);
3128 /* set the HASH algorithm for HMAC */
3129 if (HMACLen == SHA1_LENGTH) {
3130 hash_alg = HASH_AlgSHA1;
3131 } else if (HMACLen == SHA256_LENGTH) {
3132 hash_alg = HASH_AlgSHA256;
3133 } else if (HMACLen == SHA384_LENGTH) {
3134 hash_alg = HASH_AlgSHA384;
3135 } else if (HMACLen == SHA512_LENGTH) {
3136 hash_alg = HASH_AlgSHA512;
3137 } else {
3138 goto loser;
3140 fputs(buf, resp);
3141 continue;
3144 /* Count = test iteration number*/
3145 if (strncmp(buf, "Count ", 5) == 0) {
3146 /* count can just be put into resp file */
3147 fputs(buf, resp);
3148 /* zeroize the variables for the test with this data set */
3149 keyLen = 0;
3150 HMACLen = 0;
3151 memset(key, 0, sizeof key);
3152 memset(msg, 0, sizeof msg);
3153 memset(HMAC, 0, sizeof HMAC);
3154 continue;
3156 /* KLen = Length of the Input Secret Key ... */
3157 if (strncmp(buf, "Klen", 4) == 0) {
3158 i = 4;
3159 while (isspace(buf[i]) || buf[i] == '=') {
3160 i++;
3162 keyLen = atoi(&buf[i]); /* in bytes */
3163 fputs(buf, resp);
3164 continue;
3166 /* key = the secret key for the key to MAC */
3167 if (strncmp(buf, "Key", 3) == 0) {
3168 i = 3;
3169 while (isspace(buf[i]) || buf[i] == '=') {
3170 i++;
3172 for (j=0; j< keyLen; i+=2,j++) {
3173 hex_to_byteval(&buf[i], &key[j]);
3175 fputs(buf, resp);
3177 /* TLen = Length of the calculated HMAC */
3178 if (strncmp(buf, "Tlen", 4) == 0) {
3179 i = 4;
3180 while (isspace(buf[i]) || buf[i] == '=') {
3181 i++;
3183 HMACLen = atoi(&buf[i]); /* in bytes */
3184 fputs(buf, resp);
3185 continue;
3187 /* MSG = to HMAC always 128 bytes for these tests */
3188 if (strncmp(buf, "Msg", 3) == 0) {
3189 i = 3;
3190 while (isspace(buf[i]) || buf[i] == '=') {
3191 i++;
3193 for (j=0; j< msgLen; i+=2,j++) {
3194 hex_to_byteval(&buf[i], &msg[j]);
3196 fputs(buf, resp);
3197 /* calculate the HMAC and output */
3198 if (hmac_calc(HMAC, HMACLen, key, keyLen,
3199 msg, msgLen, hash_alg) != SECSuccess) {
3200 goto loser;
3202 fputs("MAC = ", resp);
3203 to_hex_str(buf, HMAC, HMACLen);
3204 fputs(buf, resp);
3205 fputc('\n', resp);
3206 continue;
3209 loser:
3210 if (req) {
3211 fclose(req);
3213 if (buf) {
3214 PORT_ZFree(buf, bufSize);
3216 if (msg) {
3217 PORT_ZFree(msg, msgLen);
3222 * Perform the DSA Key Pair Generation Test.
3224 * reqfn is the pathname of the REQUEST file.
3226 * The output RESPONSE file is written to stdout.
3228 void
3229 dsa_keypair_test(char *reqfn)
3231 char buf[260]; /* holds one line from the input REQUEST file
3232 * or to the output RESPONSE file.
3233 * 257 to hold (128 public key (x2 for HEX) + 1'\n'
3235 FILE *dsareq; /* input stream from the REQUEST file */
3236 FILE *dsaresp; /* output stream to the RESPONSE file */
3237 int N; /* number of time to generate key pair */
3238 int modulus;
3239 int i;
3240 PQGParams *pqg = NULL;
3241 PQGVerify *vfy = NULL;
3242 int keySizeIndex; /* index for valid key sizes */
3244 dsareq = fopen(reqfn, "r");
3245 dsaresp = stdout;
3246 while (fgets(buf, sizeof buf, dsareq) != NULL) {
3247 /* a comment or blank line */
3248 if (buf[0] == '#' || buf[0] == '\n') {
3249 fputs(buf, dsaresp);
3250 continue;
3253 /* [Mod = x] */
3254 if (buf[0] == '[') {
3255 if(pqg!=NULL) {
3256 PQG_DestroyParams(pqg);
3257 pqg = NULL;
3259 if(vfy!=NULL) {
3260 PQG_DestroyVerify(vfy);
3261 vfy = NULL;
3264 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
3265 goto loser;
3267 fputs(buf, dsaresp);
3268 fputc('\n', dsaresp);
3270 /*****************************************************************
3271 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
3272 * that points to a valid key size.
3274 keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
3275 if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
3276 fprintf(dsaresp,
3277 "DSA key size must be a multiple of 64 between 512 "
3278 "and 1024, inclusive");
3279 goto loser;
3282 /* Generate the parameters P, Q, and G */
3283 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
3284 &pqg, &vfy) != SECSuccess) {
3285 fprintf(dsaresp, "ERROR: Unable to generate PQG parameters");
3286 goto loser;
3289 /* output P, Q, and G */
3290 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
3291 fprintf(dsaresp, "P = %s\n", buf);
3292 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
3293 fprintf(dsaresp, "Q = %s\n", buf);
3294 to_hex_str(buf, pqg->base.data, pqg->base.len);
3295 fprintf(dsaresp, "G = %s\n\n", buf);
3296 continue;
3298 /* N = ...*/
3299 if (buf[0] == 'N') {
3301 if (sscanf(buf, "N = %d", &N) != 1) {
3302 goto loser;
3304 /* Generate a DSA key, and output the key pair for N times */
3305 for (i = 0; i < N; i++) {
3306 DSAPrivateKey *dsakey = NULL;
3307 if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
3308 fprintf(dsaresp, "ERROR: Unable to generate DSA key");
3309 goto loser;
3311 to_hex_str(buf, dsakey->privateValue.data,
3312 dsakey->privateValue.len);
3313 fprintf(dsaresp, "X = %s\n", buf);
3314 to_hex_str(buf, dsakey->publicValue.data,
3315 dsakey->publicValue.len);
3316 fprintf(dsaresp, "Y = %s\n\n", buf);
3317 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
3318 dsakey = NULL;
3320 continue;
3324 loser:
3325 fclose(dsareq);
3329 * Perform the DSA Domain Parameter Validation Test.
3331 * reqfn is the pathname of the REQUEST file.
3333 * The output RESPONSE file is written to stdout.
3335 void
3336 dsa_pqgver_test(char *reqfn)
3338 char buf[263]; /* holds one line from the input REQUEST file
3339 * or to the output RESPONSE file.
3340 * 260 to hold (128 public key (x2 for HEX) + P = ...
3342 FILE *dsareq; /* input stream from the REQUEST file */
3343 FILE *dsaresp; /* output stream to the RESPONSE file */
3344 int modulus;
3345 unsigned int i, j;
3346 PQGParams pqg;
3347 PQGVerify vfy;
3348 unsigned int pghSize; /* size for p, g, and h */
3350 dsareq = fopen(reqfn, "r");
3351 dsaresp = stdout;
3352 memset(&pqg, 0, sizeof(pqg));
3353 memset(&vfy, 0, sizeof(vfy));
3355 while (fgets(buf, sizeof buf, dsareq) != NULL) {
3356 /* a comment or blank line */
3357 if (buf[0] == '#' || buf[0] == '\n') {
3358 fputs(buf, dsaresp);
3359 continue;
3362 /* [Mod = x] */
3363 if (buf[0] == '[') {
3365 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
3366 goto loser;
3369 if (pqg.prime.data) { /* P */
3370 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
3372 if (pqg.subPrime.data) { /* Q */
3373 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
3375 if (pqg.base.data) { /* G */
3376 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
3378 if (vfy.seed.data) { /* seed */
3379 SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
3381 if (vfy.h.data) { /* H */
3382 SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
3385 fputs(buf, dsaresp);
3387 /*calculate the size of p, g, and h then allocate items */
3388 pghSize = modulus/8;
3389 SECITEM_AllocItem(NULL, &pqg.prime, pghSize);
3390 SECITEM_AllocItem(NULL, &pqg.base, pghSize);
3391 SECITEM_AllocItem(NULL, &vfy.h, pghSize);
3392 pqg.prime.len = pqg.base.len = vfy.h.len = pghSize;
3393 /* seed and q are always 20 bytes */
3394 SECITEM_AllocItem(NULL, &vfy.seed, 20);
3395 SECITEM_AllocItem(NULL, &pqg.subPrime, 20);
3396 vfy.seed.len = pqg.subPrime.len = 20;
3397 vfy.counter = 0;
3399 continue;
3401 /* P = ... */
3402 if (buf[0] == 'P') {
3403 i = 1;
3404 while (isspace(buf[i]) || buf[i] == '=') {
3405 i++;
3407 for (j=0; j< pqg.prime.len; i+=2,j++) {
3408 hex_to_byteval(&buf[i], &pqg.prime.data[j]);
3411 fputs(buf, dsaresp);
3412 continue;
3415 /* Q = ... */
3416 if (buf[0] == 'Q') {
3417 i = 1;
3418 while (isspace(buf[i]) || buf[i] == '=') {
3419 i++;
3421 for (j=0; j< pqg.subPrime.len; i+=2,j++) {
3422 hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
3425 fputs(buf, dsaresp);
3426 continue;
3429 /* G = ... */
3430 if (buf[0] == 'G') {
3431 i = 1;
3432 while (isspace(buf[i]) || buf[i] == '=') {
3433 i++;
3435 for (j=0; j< pqg.base.len; i+=2,j++) {
3436 hex_to_byteval(&buf[i], &pqg.base.data[j]);
3439 fputs(buf, dsaresp);
3440 continue;
3443 /* Seed = ... */
3444 if (strncmp(buf, "Seed", 4) == 0) {
3445 i = 4;
3446 while (isspace(buf[i]) || buf[i] == '=') {
3447 i++;
3449 for (j=0; j< vfy.seed.len; i+=2,j++) {
3450 hex_to_byteval(&buf[i], &vfy.seed.data[j]);
3453 fputs(buf, dsaresp);
3454 continue;
3457 /* c = ... */
3458 if (buf[0] == 'c') {
3460 if (sscanf(buf, "c = %u", &vfy.counter) != 1) {
3461 goto loser;
3464 fputs(buf, dsaresp);
3465 continue;
3468 /* H = ... */
3469 if (buf[0] == 'H') {
3470 SECStatus rv, result = SECFailure;
3472 i = 1;
3473 while (isspace(buf[i]) || buf[i] == '=') {
3474 i++;
3476 for (j=0; j< vfy.h.len; i+=2,j++) {
3477 hex_to_byteval(&buf[i], &vfy.h.data[j]);
3479 fputs(buf, dsaresp);
3481 /* Verify the Parameters */
3482 rv = PQG_VerifyParams(&pqg, &vfy, &result);
3483 if (rv != SECSuccess) {
3484 goto loser;
3486 if (result == SECSuccess) {
3487 fprintf(dsaresp, "Result = P\n");
3488 } else {
3489 fprintf(dsaresp, "Result = F\n");
3491 continue;
3494 loser:
3495 fclose(dsareq);
3496 if (pqg.prime.data) { /* P */
3497 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
3499 if (pqg.subPrime.data) { /* Q */
3500 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
3502 if (pqg.base.data) { /* G */
3503 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
3505 if (vfy.seed.data) { /* seed */
3506 SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
3508 if (vfy.h.data) { /* H */
3509 SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
3515 * Perform the DSA Public Key Validation Test.
3517 * reqfn is the pathname of the REQUEST file.
3519 * The output RESPONSE file is written to stdout.
3521 void
3522 dsa_pqggen_test(char *reqfn)
3524 char buf[263]; /* holds one line from the input REQUEST file
3525 * or to the output RESPONSE file.
3526 * 263 to hold seed = (128 public key (x2 for HEX)
3528 FILE *dsareq; /* input stream from the REQUEST file */
3529 FILE *dsaresp; /* output stream to the RESPONSE file */
3530 int N; /* number of times to generate parameters */
3531 int modulus;
3532 int i;
3533 unsigned int j;
3534 PQGParams *pqg = NULL;
3535 PQGVerify *vfy = NULL;
3536 unsigned int keySizeIndex;
3538 dsareq = fopen(reqfn, "r");
3539 dsaresp = stdout;
3540 while (fgets(buf, sizeof buf, dsareq) != NULL) {
3541 /* a comment or blank line */
3542 if (buf[0] == '#' || buf[0] == '\n') {
3543 fputs(buf, dsaresp);
3544 continue;
3547 /* [Mod = ... ] */
3548 if (buf[0] == '[') {
3550 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
3551 goto loser;
3554 fputs(buf, dsaresp);
3555 fputc('\n', dsaresp);
3557 /****************************************************************
3558 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
3559 * that points to a valid key size.
3561 keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
3562 if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
3563 fprintf(dsaresp,
3564 "DSA key size must be a multiple of 64 between 512 "
3565 "and 1024, inclusive");
3566 goto loser;
3569 continue;
3571 /* N = ... */
3572 if (buf[0] == 'N') {
3574 if (sscanf(buf, "N = %d", &N) != 1) {
3575 goto loser;
3577 for (i = 0; i < N; i++) {
3578 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
3579 &pqg, &vfy) != SECSuccess) {
3580 fprintf(dsaresp,
3581 "ERROR: Unable to generate PQG parameters");
3582 goto loser;
3584 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
3585 fprintf(dsaresp, "P = %s\n", buf);
3586 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
3587 fprintf(dsaresp, "Q = %s\n", buf);
3588 to_hex_str(buf, pqg->base.data, pqg->base.len);
3589 fprintf(dsaresp, "G = %s\n", buf);
3590 to_hex_str(buf, vfy->seed.data, vfy->seed.len);
3591 fprintf(dsaresp, "Seed = %s\n", buf);
3592 fprintf(dsaresp, "c = %d\n", vfy->counter);
3593 to_hex_str(buf, vfy->h.data, vfy->h.len);
3594 fputs("H = ", dsaresp);
3595 for (j=vfy->h.len; j<pqg->prime.len; j++) {
3596 fprintf(dsaresp, "00");
3598 fprintf(dsaresp, "%s\n", buf);
3599 fputc('\n', dsaresp);
3600 if(pqg!=NULL) {
3601 PQG_DestroyParams(pqg);
3602 pqg = NULL;
3604 if(vfy!=NULL) {
3605 PQG_DestroyVerify(vfy);
3606 vfy = NULL;
3610 continue;
3614 loser:
3615 fclose(dsareq);
3616 if(pqg!=NULL) {
3617 PQG_DestroyParams(pqg);
3619 if(vfy!=NULL) {
3620 PQG_DestroyVerify(vfy);
3625 * Perform the DSA Signature Generation Test.
3627 * reqfn is the pathname of the REQUEST file.
3629 * The output RESPONSE file is written to stdout.
3631 void
3632 dsa_siggen_test(char *reqfn)
3634 char buf[263]; /* holds one line from the input REQUEST file
3635 * or to the output RESPONSE file.
3636 * max for Msg = ....
3638 FILE *dsareq; /* input stream from the REQUEST file */
3639 FILE *dsaresp; /* output stream to the RESPONSE file */
3640 int modulus;
3641 int i, j;
3642 PQGParams *pqg = NULL;
3643 PQGVerify *vfy = NULL;
3644 DSAPrivateKey *dsakey = NULL;
3645 int keySizeIndex; /* index for valid key sizes */
3646 unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
3647 unsigned char sig[DSA_SIGNATURE_LEN];
3648 SECItem digest, signature;
3650 dsareq = fopen(reqfn, "r");
3651 dsaresp = stdout;
3653 while (fgets(buf, sizeof buf, dsareq) != NULL) {
3654 /* a comment or blank line */
3655 if (buf[0] == '#' || buf[0] == '\n') {
3656 fputs(buf, dsaresp);
3657 continue;
3660 /* [Mod = x] */
3661 if (buf[0] == '[') {
3662 if(pqg!=NULL) {
3663 PQG_DestroyParams(pqg);
3664 pqg = NULL;
3666 if(vfy!=NULL) {
3667 PQG_DestroyVerify(vfy);
3668 vfy = NULL;
3670 if (dsakey != NULL) {
3671 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
3672 dsakey = NULL;
3675 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
3676 goto loser;
3678 fputs(buf, dsaresp);
3679 fputc('\n', dsaresp);
3681 /****************************************************************
3682 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
3683 * that points to a valid key size.
3685 keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
3686 if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
3687 fprintf(dsaresp,
3688 "DSA key size must be a multiple of 64 between 512 "
3689 "and 1024, inclusive");
3690 goto loser;
3693 /* Generate PQG and output PQG */
3694 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
3695 &pqg, &vfy) != SECSuccess) {
3696 fprintf(dsaresp, "ERROR: Unable to generate PQG parameters");
3697 goto loser;
3699 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
3700 fprintf(dsaresp, "P = %s\n", buf);
3701 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
3702 fprintf(dsaresp, "Q = %s\n", buf);
3703 to_hex_str(buf, pqg->base.data, pqg->base.len);
3704 fprintf(dsaresp, "G = %s\n", buf);
3706 /* create DSA Key */
3707 if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
3708 fprintf(dsaresp, "ERROR: Unable to generate DSA key");
3709 goto loser;
3711 continue;
3714 /* Msg = ... */
3715 if (strncmp(buf, "Msg", 3) == 0) {
3716 unsigned char msg[128]; /* MAX msg 128 */
3717 unsigned int len = 0;
3719 memset(sha1, 0, sizeof sha1);
3720 memset(sig, 0, sizeof sig);
3722 i = 3;
3723 while (isspace(buf[i]) || buf[i] == '=') {
3724 i++;
3726 for (j=0; isxdigit(buf[i]); i+=2,j++) {
3727 hex_to_byteval(&buf[i], &msg[j]);
3729 if (SHA1_HashBuf(sha1, msg, j) != SECSuccess) {
3730 fprintf(dsaresp, "ERROR: Unable to generate SHA1 digest");
3731 goto loser;
3734 digest.type = siBuffer;
3735 digest.data = sha1;
3736 digest.len = sizeof sha1;
3737 signature.type = siBuffer;
3738 signature.data = sig;
3739 signature.len = sizeof sig;
3741 if (DSA_SignDigest(dsakey, &signature, &digest) != SECSuccess) {
3742 fprintf(dsaresp, "ERROR: Unable to generate DSA signature");
3743 goto loser;
3745 len = signature.len;
3746 if (len%2 != 0) {
3747 goto loser;
3749 len = len/2;
3751 /* output the orginal Msg, and generated Y, R, and S */
3752 fputs(buf, dsaresp);
3753 fputc('\n', dsaresp);
3754 to_hex_str(buf, dsakey->publicValue.data,
3755 dsakey->publicValue.len);
3756 fprintf(dsaresp, "Y = %s\n", buf);
3757 to_hex_str(buf, &signature.data[0], len);
3758 fprintf(dsaresp, "R = %s\n", buf);
3759 to_hex_str(buf, &signature.data[len], len);
3760 fprintf(dsaresp, "S = %s\n", buf);
3761 continue;
3765 loser:
3766 fclose(dsareq);
3767 if(pqg != NULL) {
3768 PQG_DestroyParams(pqg);
3769 pqg = NULL;
3771 if(vfy != NULL) {
3772 PQG_DestroyVerify(vfy);
3773 vfy = NULL;
3775 if (dsaKey) {
3776 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
3777 dsakey = NULL;
3782 * Perform the DSA Signature Verification Test.
3784 * reqfn is the pathname of the REQUEST file.
3786 * The output RESPONSE file is written to stdout.
3788 void
3789 dsa_sigver_test(char *reqfn)
3791 char buf[263]; /* holds one line from the input REQUEST file
3792 * or to the output RESPONSE file.
3793 * max for Msg = ....
3795 FILE *dsareq; /* input stream from the REQUEST file */
3796 FILE *dsaresp; /* output stream to the RESPONSE file */
3797 int modulus;
3798 unsigned int i, j;
3799 SECItem digest, signature;
3800 DSAPublicKey pubkey;
3801 unsigned int pgySize; /* size for p, g, and y */
3802 unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
3803 unsigned char sig[DSA_SIGNATURE_LEN];
3805 dsareq = fopen(reqfn, "r");
3806 dsaresp = stdout;
3807 memset(&pubkey, 0, sizeof(pubkey));
3809 while (fgets(buf, sizeof buf, dsareq) != NULL) {
3810 /* a comment or blank line */
3811 if (buf[0] == '#' || buf[0] == '\n') {
3812 fputs(buf, dsaresp);
3813 continue;
3816 /* [Mod = x] */
3817 if (buf[0] == '[') {
3819 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
3820 goto loser;
3823 if (pubkey.params.prime.data) { /* P */
3824 SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
3826 if (pubkey.params.subPrime.data) { /* Q */
3827 SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
3829 if (pubkey.params.base.data) { /* G */
3830 SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
3832 if (pubkey.publicValue.data) { /* Y */
3833 SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
3835 fputs(buf, dsaresp);
3837 /* calculate the size of p, g, and y then allocate items */
3838 pgySize = modulus/8;
3839 SECITEM_AllocItem(NULL, &pubkey.params.prime, pgySize);
3840 SECITEM_AllocItem(NULL, &pubkey.params.base, pgySize);
3841 SECITEM_AllocItem(NULL, &pubkey.publicValue, pgySize);
3842 pubkey.params.prime.len = pubkey.params.base.len = pgySize;
3843 pubkey.publicValue.len = pgySize;
3845 /* q always 20 bytes */
3846 SECITEM_AllocItem(NULL, &pubkey.params.subPrime, 20);
3847 pubkey.params.subPrime.len = 20;
3849 continue;
3851 /* P = ... */
3852 if (buf[0] == 'P') {
3853 i = 1;
3854 while (isspace(buf[i]) || buf[i] == '=') {
3855 i++;
3857 memset(pubkey.params.prime.data, 0, pubkey.params.prime.len);
3858 for (j=0; j< pubkey.params.prime.len; i+=2,j++) {
3859 hex_to_byteval(&buf[i], &pubkey.params.prime.data[j]);
3862 fputs(buf, dsaresp);
3863 continue;
3866 /* Q = ... */
3867 if (buf[0] == 'Q') {
3868 i = 1;
3869 while (isspace(buf[i]) || buf[i] == '=') {
3870 i++;
3872 memset(pubkey.params.subPrime.data, 0, pubkey.params.subPrime.len);
3873 for (j=0; j< pubkey.params.subPrime.len; i+=2,j++) {
3874 hex_to_byteval(&buf[i], &pubkey.params.subPrime.data[j]);
3877 fputs(buf, dsaresp);
3878 continue;
3881 /* G = ... */
3882 if (buf[0] == 'G') {
3883 i = 1;
3884 while (isspace(buf[i]) || buf[i] == '=') {
3885 i++;
3887 memset(pubkey.params.base.data, 0, pubkey.params.base.len);
3888 for (j=0; j< pubkey.params.base.len; i+=2,j++) {
3889 hex_to_byteval(&buf[i], &pubkey.params.base.data[j]);
3892 fputs(buf, dsaresp);
3893 continue;
3896 /* Msg = ... */
3897 if (strncmp(buf, "Msg", 3) == 0) {
3898 unsigned char msg[128]; /* MAX msg 128 */
3899 memset(sha1, 0, sizeof sha1);
3901 i = 3;
3902 while (isspace(buf[i]) || buf[i] == '=') {
3903 i++;
3905 for (j=0; isxdigit(buf[i]); i+=2,j++) {
3906 hex_to_byteval(&buf[i], &msg[j]);
3908 if (SHA1_HashBuf(sha1, msg, j) != SECSuccess) {
3909 fprintf(dsaresp, "ERROR: Unable to generate SHA1 digest");
3910 goto loser;
3913 fputs(buf, dsaresp);
3914 continue;
3917 /* Y = ... */
3918 if (buf[0] == 'Y') {
3919 i = 1;
3920 while (isspace(buf[i]) || buf[i] == '=') {
3921 i++;
3923 memset(pubkey.publicValue.data, 0, pubkey.params.subPrime.len);
3924 for (j=0; j< pubkey.publicValue.len; i+=2,j++) {
3925 hex_to_byteval(&buf[i], &pubkey.publicValue.data[j]);
3928 fputs(buf, dsaresp);
3929 continue;
3932 /* R = ... */
3933 if (buf[0] == 'R') {
3934 memset(sig, 0, sizeof sig);
3935 i = 1;
3936 while (isspace(buf[i]) || buf[i] == '=') {
3937 i++;
3939 for (j=0; j< DSA_SUBPRIME_LEN; i+=2,j++) {
3940 hex_to_byteval(&buf[i], &sig[j]);
3943 fputs(buf, dsaresp);
3944 continue;
3947 /* S = ... */
3948 if (buf[0] == 'S') {
3949 i = 1;
3950 while (isspace(buf[i]) || buf[i] == '=') {
3951 i++;
3953 for (j=DSA_SUBPRIME_LEN; j< DSA_SIGNATURE_LEN; i+=2,j++) {
3954 hex_to_byteval(&buf[i], &sig[j]);
3956 fputs(buf, dsaresp);
3958 digest.type = siBuffer;
3959 digest.data = sha1;
3960 digest.len = sizeof sha1;
3961 signature.type = siBuffer;
3962 signature.data = sig;
3963 signature.len = sizeof sig;
3965 if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) {
3966 fprintf(dsaresp, "Result = P\n");
3967 } else {
3968 fprintf(dsaresp, "Result = F\n");
3970 continue;
3973 loser:
3974 fclose(dsareq);
3975 if (pubkey.params.prime.data) { /* P */
3976 SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
3978 if (pubkey.params.subPrime.data) { /* Q */
3979 SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
3981 if (pubkey.params.base.data) { /* G */
3982 SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
3984 if (pubkey.publicValue.data) { /* Y */
3985 SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
3990 * Perform the RSA Signature Generation Test.
3992 * reqfn is the pathname of the REQUEST file.
3994 * The output RESPONSE file is written to stdout.
3996 void
3997 rsa_siggen_test(char *reqfn)
3999 char buf[2*RSA_MAX_TEST_MODULUS_BYTES+1];
4000 /* buf holds one line from the input REQUEST file
4001 * or to the output RESPONSE file.
4002 * 2x for HEX output + 1 for \n
4004 FILE *rsareq; /* input stream from the REQUEST file */
4005 FILE *rsaresp; /* output stream to the RESPONSE file */
4006 int i, j;
4007 unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
4008 unsigned int shaLength = 0; /* length of SHA */
4009 HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
4010 SECOidTag shaOid = SEC_OID_UNKNOWN;
4011 int modulus; /* the Modulus size */
4012 int publicExponent = DEFAULT_RSA_PUBLIC_EXPONENT;
4013 SECItem pe = {0, 0, 0 };
4014 unsigned char pubEx[4];
4015 int peCount = 0;
4017 RSAPrivateKey *rsaBlapiPrivKey = NULL; /* holds RSA private and
4018 * public keys */
4019 RSAPublicKey *rsaBlapiPublicKey = NULL; /* hold RSA public key */
4021 rsareq = fopen(reqfn, "r");
4022 rsaresp = stdout;
4024 /* calculate the exponent */
4025 for (i=0; i < 4; i++) {
4026 if (peCount || (publicExponent &
4027 ((unsigned long)0xff000000L >> (i*8)))) {
4028 pubEx[peCount] =
4029 (unsigned char)((publicExponent >> (3-i)*8) & 0xff);
4030 peCount++;
4033 pe.len = peCount;
4034 pe.data = &pubEx[0];
4035 pe.type = siBuffer;
4037 while (fgets(buf, sizeof buf, rsareq) != NULL) {
4038 /* a comment or blank line */
4039 if (buf[0] == '#' || buf[0] == '\n') {
4040 fputs(buf, rsaresp);
4041 continue;
4044 /* [mod = ...] */
4045 if (buf[0] == '[') {
4047 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
4048 goto loser;
4050 if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
4051 fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
4052 goto loser;
4055 fputs(buf, rsaresp);
4057 if (rsaBlapiPrivKey != NULL) {
4058 PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
4059 rsaBlapiPrivKey = NULL;
4060 rsaBlapiPublicKey = NULL;
4063 rsaBlapiPrivKey = RSA_NewKey(modulus, &pe);
4064 if (rsaBlapiPrivKey == NULL) {
4065 fprintf(rsaresp, "Error unable to create RSA key\n");
4066 goto loser;
4069 to_hex_str(buf, rsaBlapiPrivKey->modulus.data,
4070 rsaBlapiPrivKey->modulus.len);
4071 fprintf(rsaresp, "\nn = %s\n\n", buf);
4072 to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data,
4073 rsaBlapiPrivKey->publicExponent.len);
4074 fprintf(rsaresp, "e = %s\n", buf);
4075 /* convert private key to public key. Memory
4076 * is freed with private key's arena */
4077 rsaBlapiPublicKey = (RSAPublicKey *)PORT_ArenaAlloc(
4078 rsaBlapiPrivKey->arena,
4079 sizeof(RSAPublicKey));
4081 rsaBlapiPublicKey->modulus.len = rsaBlapiPrivKey->modulus.len;
4082 rsaBlapiPublicKey->modulus.data = rsaBlapiPrivKey->modulus.data;
4083 rsaBlapiPublicKey->publicExponent.len =
4084 rsaBlapiPrivKey->publicExponent.len;
4085 rsaBlapiPublicKey->publicExponent.data =
4086 rsaBlapiPrivKey->publicExponent.data;
4087 continue;
4090 /* SHAAlg = ... */
4091 if (strncmp(buf, "SHAAlg", 6) == 0) {
4092 i = 6;
4093 while (isspace(buf[i]) || buf[i] == '=') {
4094 i++;
4096 /* set the SHA Algorithm */
4097 if (strncmp(&buf[i], "SHA1", 4) == 0) {
4098 shaAlg = HASH_AlgSHA1;
4099 } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
4100 shaAlg = HASH_AlgSHA256;
4101 } else if (strncmp(&buf[i], "SHA384", 6)== 0) {
4102 shaAlg = HASH_AlgSHA384;
4103 } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
4104 shaAlg = HASH_AlgSHA512;
4105 } else {
4106 fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
4107 goto loser;
4109 fputs(buf, rsaresp);
4110 continue;
4113 /* Msg = ... */
4114 if (strncmp(buf, "Msg", 3) == 0) {
4116 unsigned char msg[128]; /* MAX msg 128 */
4117 unsigned int rsa_bytes_signed;
4118 unsigned char rsa_computed_signature[RSA_MAX_TEST_MODULUS_BYTES];
4119 SECStatus rv = SECFailure;
4120 NSSLOWKEYPublicKey * rsa_public_key;
4121 NSSLOWKEYPrivateKey * rsa_private_key;
4122 NSSLOWKEYPrivateKey low_RSA_private_key = { NULL,
4123 NSSLOWKEYRSAKey, };
4124 NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
4125 NSSLOWKEYRSAKey, };
4127 low_RSA_private_key.u.rsa = *rsaBlapiPrivKey;
4128 low_RSA_public_key.u.rsa = *rsaBlapiPublicKey;
4130 rsa_private_key = &low_RSA_private_key;
4131 rsa_public_key = &low_RSA_public_key;
4133 memset(sha, 0, sizeof sha);
4134 memset(msg, 0, sizeof msg);
4135 rsa_bytes_signed = 0;
4136 memset(rsa_computed_signature, 0, sizeof rsa_computed_signature);
4138 i = 3;
4139 while (isspace(buf[i]) || buf[i] == '=') {
4140 i++;
4142 for (j=0; isxdigit(buf[i]) && j < sizeof(msg); i+=2,j++) {
4143 hex_to_byteval(&buf[i], &msg[j]);
4146 if (shaAlg == HASH_AlgSHA1) {
4147 if (SHA1_HashBuf(sha, msg, j) != SECSuccess) {
4148 fprintf(rsaresp, "ERROR: Unable to generate SHA1");
4149 goto loser;
4151 shaLength = SHA1_LENGTH;
4152 shaOid = SEC_OID_SHA1;
4153 } else if (shaAlg == HASH_AlgSHA256) {
4154 if (SHA256_HashBuf(sha, msg, j) != SECSuccess) {
4155 fprintf(rsaresp, "ERROR: Unable to generate SHA256");
4156 goto loser;
4158 shaLength = SHA256_LENGTH;
4159 shaOid = SEC_OID_SHA256;
4160 } else if (shaAlg == HASH_AlgSHA384) {
4161 if (SHA384_HashBuf(sha, msg, j) != SECSuccess) {
4162 fprintf(rsaresp, "ERROR: Unable to generate SHA384");
4163 goto loser;
4165 shaLength = SHA384_LENGTH;
4166 shaOid = SEC_OID_SHA384;
4167 } else if (shaAlg == HASH_AlgSHA512) {
4168 if (SHA512_HashBuf(sha, msg, j) != SECSuccess) {
4169 fprintf(rsaresp, "ERROR: Unable to generate SHA512");
4170 goto loser;
4172 shaLength = SHA512_LENGTH;
4173 shaOid = SEC_OID_SHA512;
4174 } else {
4175 fprintf(rsaresp, "ERROR: SHAAlg not defined.");
4176 goto loser;
4179 /* Perform RSA signature with the RSA private key. */
4180 rv = RSA_HashSign( shaOid,
4181 rsa_private_key,
4182 rsa_computed_signature,
4183 &rsa_bytes_signed,
4184 nsslowkey_PrivateModulusLen(rsa_private_key),
4185 sha,
4186 shaLength);
4188 if( rv != SECSuccess ) {
4189 fprintf(rsaresp, "ERROR: RSA_HashSign failed");
4190 goto loser;
4193 /* Output the signature */
4194 fputs(buf, rsaresp);
4195 to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed);
4196 fprintf(rsaresp, "S = %s\n", buf);
4198 /* Perform RSA verification with the RSA public key. */
4199 rv = RSA_HashCheckSign( shaOid,
4200 rsa_public_key,
4201 rsa_computed_signature,
4202 rsa_bytes_signed,
4203 sha,
4204 shaLength);
4205 if( rv != SECSuccess ) {
4206 fprintf(rsaresp, "ERROR: RSA_HashCheckSign failed");
4207 goto loser;
4209 continue;
4212 loser:
4213 fclose(rsareq);
4215 if (rsaBlapiPrivKey != NULL) {
4216 /* frees private and public key */
4217 PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
4218 rsaBlapiPrivKey = NULL;
4219 rsaBlapiPublicKey = NULL;
4224 * Perform the RSA Signature Verification Test.
4226 * reqfn is the pathname of the REQUEST file.
4228 * The output RESPONSE file is written to stdout.
4230 void
4231 rsa_sigver_test(char *reqfn)
4233 char buf[2*RSA_MAX_TEST_MODULUS_BYTES+7];
4234 /* buf holds one line from the input REQUEST file
4235 * or to the output RESPONSE file.
4236 * s = 2x for HEX output + 1 for \n
4238 FILE *rsareq; /* input stream from the REQUEST file */
4239 FILE *rsaresp; /* output stream to the RESPONSE file */
4240 int i, j;
4241 unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
4242 unsigned int shaLength = 0; /* actual length of the digest */
4243 HASH_HashType shaAlg = HASH_AlgNULL;
4244 SECOidTag shaOid = SEC_OID_UNKNOWN;
4245 int modulus = 0; /* the Modulus size */
4246 unsigned char signature[513]; /* largest signature size + '\n' */
4247 unsigned int signatureLength = 0; /* actual length of the signature */
4248 PRBool keyvalid = PR_TRUE;
4250 RSAPublicKey rsaBlapiPublicKey; /* hold RSA public key */
4252 rsareq = fopen(reqfn, "r");
4253 rsaresp = stdout;
4254 memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey));
4256 while (fgets(buf, sizeof buf, rsareq) != NULL) {
4257 /* a comment or blank line */
4258 if (buf[0] == '#' || buf[0] == '\n') {
4259 fputs(buf, rsaresp);
4260 continue;
4263 /* [Mod = ...] */
4264 if (buf[0] == '[') {
4265 unsigned int flen; /* length in bytes of the field size */
4267 if (rsaBlapiPublicKey.modulus.data) { /* n */
4268 SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
4270 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
4271 goto loser;
4274 if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
4275 fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
4276 goto loser;
4279 fputs(buf, rsaresp);
4281 signatureLength = flen = modulus/8;
4283 SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.modulus, flen);
4284 if (rsaBlapiPublicKey.modulus.data == NULL) {
4285 goto loser;
4287 continue;
4290 /* n = ... modulus */
4291 if (buf[0] == 'n') {
4292 i = 1;
4293 while (isspace(buf[i]) || buf[i] == '=') {
4294 i++;
4296 keyvalid = from_hex_str(&rsaBlapiPublicKey.modulus.data[0],
4297 rsaBlapiPublicKey.modulus.len,
4298 &buf[i]);
4300 if (!keyvalid) {
4301 fprintf(rsaresp, "ERROR: rsa_sigver n not valid.\n");
4302 goto loser;
4304 fputs(buf, rsaresp);
4305 continue;
4308 /* SHAAlg = ... */
4309 if (strncmp(buf, "SHAAlg", 6) == 0) {
4310 i = 6;
4311 while (isspace(buf[i]) || buf[i] == '=') {
4312 i++;
4314 /* set the SHA Algorithm */
4315 if (strncmp(&buf[i], "SHA1", 4) == 0) {
4316 shaAlg = HASH_AlgSHA1;
4317 } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
4318 shaAlg = HASH_AlgSHA256;
4319 } else if (strncmp(&buf[i], "SHA384", 6) == 0) {
4320 shaAlg = HASH_AlgSHA384;
4321 } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
4322 shaAlg = HASH_AlgSHA512;
4323 } else {
4324 fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
4325 goto loser;
4327 fputs(buf, rsaresp);
4328 continue;
4331 /* e = ... public Key */
4332 if (buf[0] == 'e') {
4333 unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES];
4334 unsigned char t;
4336 memset(data, 0, sizeof data);
4338 if (rsaBlapiPublicKey.publicExponent.data) { /* e */
4339 SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
4342 i = 1;
4343 while (isspace(buf[i]) || buf[i] == '=') {
4344 i++;
4346 /* skip leading zero's */
4347 while (isxdigit(buf[i])) {
4348 hex_to_byteval(&buf[i], &t);
4349 if (t == 0) {
4350 i+=2;
4351 } else break;
4354 /* get the exponent */
4355 for (j=0; isxdigit(buf[i]) && j < sizeof data; i+=2,j++) {
4356 hex_to_byteval(&buf[i], &data[j]);
4359 if (j == 0) { j = 1; } /* to handle 1 byte length exponents */
4361 SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.publicExponent, j);
4362 if (rsaBlapiPublicKey.publicExponent.data == NULL) {
4363 goto loser;
4366 for (i=0; i < j; i++) {
4367 rsaBlapiPublicKey.publicExponent.data[i] = data[i];
4370 fputs(buf, rsaresp);
4371 continue;
4374 /* Msg = ... */
4375 if (strncmp(buf, "Msg", 3) == 0) {
4376 unsigned char msg[128]; /* MAX msg 128 */
4378 memset(sha, 0, sizeof sha);
4379 memset(msg, 0, sizeof msg);
4381 i = 3;
4382 while (isspace(buf[i]) || buf[i] == '=') {
4383 i++;
4386 for (j=0; isxdigit(buf[i]) && j < sizeof msg; i+=2,j++) {
4387 hex_to_byteval(&buf[i], &msg[j]);
4390 if (shaAlg == HASH_AlgSHA1) {
4391 if (SHA1_HashBuf(sha, msg, j) != SECSuccess) {
4392 fprintf(rsaresp, "ERROR: Unable to generate SHA1");
4393 goto loser;
4395 shaLength = SHA1_LENGTH;
4396 shaOid = SEC_OID_SHA1;
4397 } else if (shaAlg == HASH_AlgSHA256) {
4398 if (SHA256_HashBuf(sha, msg, j) != SECSuccess) {
4399 fprintf(rsaresp, "ERROR: Unable to generate SHA256");
4400 goto loser;
4402 shaLength = SHA256_LENGTH;
4403 shaOid = SEC_OID_SHA256;
4404 } else if (shaAlg == HASH_AlgSHA384) {
4405 if (SHA384_HashBuf(sha, msg, j) != SECSuccess) {
4406 fprintf(rsaresp, "ERROR: Unable to generate SHA384");
4407 goto loser;
4409 shaLength = SHA384_LENGTH;
4410 shaOid = SEC_OID_SHA384;
4411 } else if (shaAlg == HASH_AlgSHA512) {
4412 if (SHA512_HashBuf(sha, msg, j) != SECSuccess) {
4413 fprintf(rsaresp, "ERROR: Unable to generate SHA512");
4414 goto loser;
4416 shaLength = SHA512_LENGTH;
4417 shaOid = SEC_OID_SHA512;
4418 } else {
4419 fprintf(rsaresp, "ERROR: SHAAlg not defined.");
4420 goto loser;
4423 fputs(buf, rsaresp);
4424 continue;
4428 /* S = ... */
4429 if (buf[0] == 'S') {
4430 SECStatus rv = SECFailure;
4431 NSSLOWKEYPublicKey * rsa_public_key;
4432 NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
4433 NSSLOWKEYRSAKey, };
4435 /* convert to a low RSA public key */
4436 low_RSA_public_key.u.rsa = rsaBlapiPublicKey;
4437 rsa_public_key = &low_RSA_public_key;
4439 memset(signature, 0, sizeof(signature));
4440 i = 1;
4441 while (isspace(buf[i]) || buf[i] == '=') {
4442 i++;
4445 for (j=0; isxdigit(buf[i]) && j < sizeof signature; i+=2,j++) {
4446 hex_to_byteval(&buf[i], &signature[j]);
4449 signatureLength = j;
4450 fputs(buf, rsaresp);
4452 /* Perform RSA verification with the RSA public key. */
4453 rv = RSA_HashCheckSign( shaOid,
4454 rsa_public_key,
4455 signature,
4456 signatureLength,
4457 sha,
4458 shaLength);
4459 if( rv == SECSuccess ) {
4460 fputs("Result = P\n", rsaresp);
4461 } else {
4462 fputs("Result = F\n", rsaresp);
4464 continue;
4467 loser:
4468 fclose(rsareq);
4469 if (rsaBlapiPublicKey.modulus.data) { /* n */
4470 SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
4472 if (rsaBlapiPublicKey.publicExponent.data) { /* e */
4473 SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
4477 int main(int argc, char **argv)
4479 if (argc < 2) exit (-1);
4480 NSS_NoDB_Init(NULL);
4481 /*************/
4482 /* TDEA */
4483 /*************/
4484 if (strcmp(argv[1], "tdea") == 0) {
4485 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
4486 if (strcmp(argv[2], "kat") == 0) {
4487 /* Known Answer Test (KAT) */
4488 tdea_kat_mmt(argv[4]);
4489 } else if (strcmp(argv[2], "mmt") == 0) {
4490 /* Multi-block Message Test (MMT) */
4491 tdea_kat_mmt(argv[4]);
4492 } else if (strcmp(argv[2], "mct") == 0) {
4493 /* Monte Carlo Test (MCT) */
4494 if (strcmp(argv[3], "ecb") == 0) {
4495 /* ECB mode */
4496 tdea_mct(NSS_DES_EDE3, argv[4]);
4497 } else if (strcmp(argv[3], "cbc") == 0) {
4498 /* CBC mode */
4499 tdea_mct(NSS_DES_EDE3_CBC, argv[4]);
4502 /*************/
4503 /* AES */
4504 /*************/
4505 } else if (strcmp(argv[1], "aes") == 0) {
4506 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
4507 if ( strcmp(argv[2], "kat") == 0) {
4508 /* Known Answer Test (KAT) */
4509 aes_kat_mmt(argv[4]);
4510 } else if (strcmp(argv[2], "mmt") == 0) {
4511 /* Multi-block Message Test (MMT) */
4512 aes_kat_mmt(argv[4]);
4513 } else if (strcmp(argv[2], "mct") == 0) {
4514 /* Monte Carlo Test (MCT) */
4515 if ( strcmp(argv[3], "ecb") == 0) {
4516 /* ECB mode */
4517 aes_ecb_mct(argv[4]);
4518 } else if (strcmp(argv[3], "cbc") == 0) {
4519 /* CBC mode */
4520 aes_cbc_mct(argv[4]);
4523 /*************/
4524 /* SHA */
4525 /*************/
4526 } else if (strcmp(argv[1], "sha") == 0) {
4527 sha_test(argv[2]);
4528 /*************/
4529 /* RSA */
4530 /*************/
4531 } else if (strcmp(argv[1], "rsa") == 0) {
4532 /* argv[2]=siggen|sigver */
4533 /* argv[3]=<test name>.req */
4534 if (strcmp(argv[2], "siggen") == 0) {
4535 /* Signature Generation Test */
4536 rsa_siggen_test(argv[3]);
4537 } else if (strcmp(argv[2], "sigver") == 0) {
4538 /* Signature Verification Test */
4539 rsa_sigver_test(argv[3]);
4541 /*************/
4542 /* HMAC */
4543 /*************/
4544 } else if (strcmp(argv[1], "hmac") == 0) {
4545 hmac_test(argv[2]);
4546 /*************/
4547 /* DSA */
4548 /*************/
4549 } else if (strcmp(argv[1], "dsa") == 0) {
4550 /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */
4551 /* argv[3]=<test name>.req */
4552 if (strcmp(argv[2], "keypair") == 0) {
4553 /* Key Pair Generation Test */
4554 dsa_keypair_test(argv[3]);
4555 } else if (strcmp(argv[2], "pqggen") == 0) {
4556 /* Domain Parameter Generation Test */
4557 dsa_pqggen_test(argv[3]);
4558 } else if (strcmp(argv[2], "pqgver") == 0) {
4559 /* Domain Parameter Validation Test */
4560 dsa_pqgver_test(argv[3]);
4561 } else if (strcmp(argv[2], "siggen") == 0) {
4562 /* Signature Generation Test */
4563 dsa_siggen_test(argv[3]);
4564 } else if (strcmp(argv[2], "sigver") == 0) {
4565 /* Signature Verification Test */
4566 dsa_sigver_test(argv[3]);
4568 #ifdef NSS_ENABLE_ECC
4569 /*************/
4570 /* ECDSA */
4571 /*************/
4572 } else if (strcmp(argv[1], "ecdsa") == 0) {
4573 /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */
4574 if ( strcmp(argv[2], "keypair") == 0) {
4575 /* Key Pair Generation Test */
4576 ecdsa_keypair_test(argv[3]);
4577 } else if (strcmp(argv[2], "pkv") == 0) {
4578 /* Public Key Validation Test */
4579 ecdsa_pkv_test(argv[3]);
4580 } else if (strcmp(argv[2], "siggen") == 0) {
4581 /* Signature Generation Test */
4582 ecdsa_siggen_test(argv[3]);
4583 } else if (strcmp(argv[2], "sigver") == 0) {
4584 /* Signature Verification Test */
4585 ecdsa_sigver_test(argv[3]);
4587 #endif /* NSS_ENABLE_ECC */
4588 /*************/
4589 /* RNG */
4590 /*************/
4591 } else if (strcmp(argv[1], "rng") == 0) {
4592 /* argv[2]=vst|mct argv[3]=<test name>.req */
4593 if ( strcmp(argv[2], "vst") == 0) {
4594 /* Variable Seed Test */
4595 rng_vst(argv[3]);
4596 } else if (strcmp(argv[2], "mct") == 0) {
4597 /* Monte Carlo Test */
4598 rng_mct(argv[3]);
4601 return 0;