Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / cmd / fipstest / fipstest.c
blob149bde1a310e1c7daebd66e5f7e032de3c046d83
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"
52 #include "pqgutil.h"
54 #if 0
55 #include "../../lib/freebl/mpi/mpi.h"
56 #endif
58 #ifdef NSS_ENABLE_ECC
59 extern SECStatus
60 EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
61 extern SECStatus
62 EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
63 const ECParams *srcParams);
64 #endif
66 #define ENCRYPT 1
67 #define DECRYPT 0
68 #define BYTE unsigned char
69 #define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001
70 #define RSA_MAX_TEST_MODULUS_BITS 4096
71 #define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS/8
72 #define RSA_MAX_TEST_EXPONENT_BYTES 8
73 #define PQG_TEST_SEED_BYTES 20
75 SECStatus
76 hex_to_byteval(const char *c2, unsigned char *byteval)
78 int i;
79 unsigned char offset;
80 *byteval = 0;
81 for (i=0; i<2; i++) {
82 if (c2[i] >= '0' && c2[i] <= '9') {
83 offset = c2[i] - '0';
84 *byteval |= offset << 4*(1-i);
85 } else if (c2[i] >= 'a' && c2[i] <= 'f') {
86 offset = c2[i] - 'a';
87 *byteval |= (offset + 10) << 4*(1-i);
88 } else if (c2[i] >= 'A' && c2[i] <= 'F') {
89 offset = c2[i] - 'A';
90 *byteval |= (offset + 10) << 4*(1-i);
91 } else {
92 return SECFailure;
95 return SECSuccess;
98 SECStatus
99 byteval_to_hex(unsigned char byteval, char *c2, char a)
101 int i;
102 unsigned char offset;
103 for (i=0; i<2; i++) {
104 offset = (byteval >> 4*(1-i)) & 0x0f;
105 if (offset < 10) {
106 c2[i] = '0' + offset;
107 } else {
108 c2[i] = a + offset - 10;
111 return SECSuccess;
114 void
115 to_hex_str(char *str, const unsigned char *buf, unsigned int len)
117 unsigned int i;
118 for (i=0; i<len; i++) {
119 byteval_to_hex(buf[i], &str[2*i], 'a');
121 str[2*len] = '\0';
124 void
125 to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len)
127 unsigned int i;
128 for (i=0; i<len; i++) {
129 byteval_to_hex(buf[i], &str[2*i], 'A');
131 str[2*len] = '\0';
135 * Convert a string of hex digits (str) to an array (buf) of len bytes.
136 * Return PR_TRUE if the hex string can fit in the byte array. Return
137 * PR_FALSE if the hex string is empty or is too long.
139 PRBool
140 from_hex_str(unsigned char *buf, unsigned int len, const char *str)
142 unsigned int nxdigit; /* number of hex digits in str */
143 unsigned int i; /* index into buf */
144 unsigned int j; /* index into str */
146 /* count the hex digits */
147 nxdigit = 0;
148 for (nxdigit = 0; isxdigit(str[nxdigit]); nxdigit++) {
149 /* empty body */
151 if (nxdigit == 0) {
152 return PR_FALSE;
154 if (nxdigit > 2*len) {
156 * The input hex string is too long, but we allow it if the
157 * extra digits are leading 0's.
159 for (j = 0; j < nxdigit-2*len; j++) {
160 if (str[j] != '0') {
161 return PR_FALSE;
164 /* skip leading 0's */
165 str += nxdigit-2*len;
166 nxdigit = 2*len;
168 for (i=0, j=0; i< len; i++) {
169 if (2*i < 2*len-nxdigit) {
170 /* Handle a short input as if we padded it with leading 0's. */
171 if (2*i+1 < 2*len-nxdigit) {
172 buf[i] = 0;
173 } else {
174 char tmp[2];
175 tmp[0] = '0';
176 tmp[1] = str[j];
177 hex_to_byteval(tmp, &buf[i]);
178 j++;
180 } else {
181 hex_to_byteval(&str[j], &buf[i]);
182 j += 2;
185 return PR_TRUE;
188 SECStatus
189 tdea_encrypt_buf(
190 int mode,
191 const unsigned char *key,
192 const unsigned char *iv,
193 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
194 const unsigned char *input, unsigned int inputlen)
196 SECStatus rv = SECFailure;
197 DESContext *cx;
198 unsigned char doublecheck[8*20]; /* 1 to 20 blocks */
199 unsigned int doublechecklen = 0;
201 cx = DES_CreateContext(key, iv, mode, PR_TRUE);
202 if (cx == NULL) {
203 goto loser;
205 rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
206 if (rv != SECSuccess) {
207 goto loser;
209 if (*outputlen != inputlen) {
210 goto loser;
212 DES_DestroyContext(cx, PR_TRUE);
213 cx = NULL;
216 * Doublecheck our result by decrypting the ciphertext and
217 * compare the output with the input plaintext.
219 cx = DES_CreateContext(key, iv, mode, PR_FALSE);
220 if (cx == NULL) {
221 goto loser;
223 rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
224 output, *outputlen);
225 if (rv != SECSuccess) {
226 goto loser;
228 if (doublechecklen != *outputlen) {
229 goto loser;
231 DES_DestroyContext(cx, PR_TRUE);
232 cx = NULL;
233 if (memcmp(doublecheck, input, inputlen) != 0) {
234 goto loser;
236 rv = SECSuccess;
238 loser:
239 if (cx != NULL) {
240 DES_DestroyContext(cx, PR_TRUE);
242 return rv;
245 SECStatus
246 tdea_decrypt_buf(
247 int mode,
248 const unsigned char *key,
249 const unsigned char *iv,
250 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
251 const unsigned char *input, unsigned int inputlen)
253 SECStatus rv = SECFailure;
254 DESContext *cx;
255 unsigned char doublecheck[8*20]; /* 1 to 20 blocks */
256 unsigned int doublechecklen = 0;
258 cx = DES_CreateContext(key, iv, mode, PR_FALSE);
259 if (cx == NULL) {
260 goto loser;
262 rv = DES_Decrypt(cx, output, outputlen, maxoutputlen,
263 input, inputlen);
264 if (rv != SECSuccess) {
265 goto loser;
267 if (*outputlen != inputlen) {
268 goto loser;
270 DES_DestroyContext(cx, PR_TRUE);
271 cx = NULL;
274 * Doublecheck our result by encrypting the plaintext and
275 * compare the output with the input ciphertext.
277 cx = DES_CreateContext(key, iv, mode, PR_TRUE);
278 if (cx == NULL) {
279 goto loser;
281 rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
282 output, *outputlen);
283 if (rv != SECSuccess) {
284 goto loser;
286 if (doublechecklen != *outputlen) {
287 goto loser;
289 DES_DestroyContext(cx, PR_TRUE);
290 cx = NULL;
291 if (memcmp(doublecheck, input, inputlen) != 0) {
292 goto loser;
294 rv = SECSuccess;
296 loser:
297 if (cx != NULL) {
298 DES_DestroyContext(cx, PR_TRUE);
300 return rv;
304 * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
305 * Test (MMT) in ECB or CBC mode. The KAT (there are five types)
306 * and MMT have the same structure: given the key and IV (CBC mode
307 * only), encrypt the given plaintext or decrypt the given ciphertext.
308 * So we can handle them the same way.
310 * reqfn is the pathname of the REQUEST file.
312 * The output RESPONSE file is written to stdout.
314 void
315 tdea_kat_mmt(char *reqfn)
317 char buf[180]; /* holds one line from the input REQUEST file.
318 * needs to be large enough to hold the longest
319 * line "CIPHERTEXT = <180 hex digits>\n".
321 FILE *req; /* input stream from the REQUEST file */
322 FILE *resp; /* output stream to the RESPONSE file */
323 int i, j;
324 int mode; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
325 int crypt = DECRYPT; /* 1 means encrypt, 0 means decrypt */
326 unsigned char key[24]; /* TDEA 3 key bundle */
327 unsigned int numKeys = 0;
328 unsigned char iv[8]; /* for all modes except ECB */
329 unsigned char plaintext[8*20]; /* 1 to 20 blocks */
330 unsigned int plaintextlen;
331 unsigned char ciphertext[8*20]; /* 1 to 20 blocks */
332 unsigned int ciphertextlen;
333 SECStatus rv;
335 req = fopen(reqfn, "r");
336 resp = stdout;
337 while (fgets(buf, sizeof buf, req) != NULL) {
338 /* a comment or blank line */
339 if (buf[0] == '#' || buf[0] == '\n') {
340 fputs(buf, resp);
341 continue;
343 /* [ENCRYPT] or [DECRYPT] */
344 if (buf[0] == '[') {
345 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
346 crypt = ENCRYPT;
347 } else {
348 crypt = DECRYPT;
350 fputs(buf, resp);
351 continue;
353 /* NumKeys */
354 if (strncmp(&buf[0], "NumKeys", 7) == 0) {
355 i = 7;
356 while (isspace(buf[i]) || buf[i] == '=') {
357 i++;
359 numKeys = buf[i];
360 fputs(buf, resp);
361 continue;
363 /* "COUNT = x" begins a new data set */
364 if (strncmp(buf, "COUNT", 5) == 0) {
365 /* mode defaults to ECB, if dataset has IV mode will be set CBC */
366 mode = NSS_DES_EDE3;
367 /* zeroize the variables for the test with this data set */
368 memset(key, 0, sizeof key);
369 memset(iv, 0, sizeof iv);
370 memset(plaintext, 0, sizeof plaintext);
371 plaintextlen = 0;
372 memset(ciphertext, 0, sizeof ciphertext);
373 ciphertextlen = 0;
374 fputs(buf, resp);
375 continue;
377 if (numKeys == 0) {
378 if (strncmp(buf, "KEYs", 4) == 0) {
379 i = 4;
380 while (isspace(buf[i]) || buf[i] == '=') {
381 i++;
383 for (j=0; isxdigit(buf[i]); i+=2,j++) {
384 hex_to_byteval(&buf[i], &key[j]);
385 key[j+8] = key[j];
386 key[j+16] = key[j];
388 fputs(buf, resp);
389 continue;
391 } else {
392 /* KEY1 = ... */
393 if (strncmp(buf, "KEY1", 4) == 0) {
394 i = 4;
395 while (isspace(buf[i]) || buf[i] == '=') {
396 i++;
398 for (j=0; isxdigit(buf[i]); i+=2,j++) {
399 hex_to_byteval(&buf[i], &key[j]);
401 fputs(buf, resp);
402 continue;
404 /* KEY2 = ... */
405 if (strncmp(buf, "KEY2", 4) == 0) {
406 i = 4;
407 while (isspace(buf[i]) || buf[i] == '=') {
408 i++;
410 for (j=8; isxdigit(buf[i]); i+=2,j++) {
411 hex_to_byteval(&buf[i], &key[j]);
413 fputs(buf, resp);
414 continue;
416 /* KEY3 = ... */
417 if (strncmp(buf, "KEY3", 4) == 0) {
418 i = 4;
419 while (isspace(buf[i]) || buf[i] == '=') {
420 i++;
422 for (j=16; isxdigit(buf[i]); i+=2,j++) {
423 hex_to_byteval(&buf[i], &key[j]);
425 fputs(buf, resp);
426 continue;
430 /* IV = ... */
431 if (strncmp(buf, "IV", 2) == 0) {
432 mode = NSS_DES_EDE3_CBC;
433 i = 2;
434 while (isspace(buf[i]) || buf[i] == '=') {
435 i++;
437 for (j=0; j<sizeof iv; i+=2,j++) {
438 hex_to_byteval(&buf[i], &iv[j]);
440 fputs(buf, resp);
441 continue;
444 /* PLAINTEXT = ... */
445 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
446 /* sanity check */
447 if (crypt != ENCRYPT) {
448 goto loser;
450 i = 9;
451 while (isspace(buf[i]) || buf[i] == '=') {
452 i++;
454 for (j=0; isxdigit(buf[i]); i+=2,j++) {
455 hex_to_byteval(&buf[i], &plaintext[j]);
457 plaintextlen = j;
458 rv = tdea_encrypt_buf(mode, key,
459 (mode == NSS_DES_EDE3) ? NULL : iv,
460 ciphertext, &ciphertextlen, sizeof ciphertext,
461 plaintext, plaintextlen);
462 if (rv != SECSuccess) {
463 goto loser;
466 fputs(buf, resp);
467 fputs("CIPHERTEXT = ", resp);
468 to_hex_str(buf, ciphertext, ciphertextlen);
469 fputs(buf, resp);
470 fputc('\n', resp);
471 continue;
473 /* CIPHERTEXT = ... */
474 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
475 /* sanity check */
476 if (crypt != DECRYPT) {
477 goto loser;
480 i = 10;
481 while (isspace(buf[i]) || buf[i] == '=') {
482 i++;
484 for (j=0; isxdigit(buf[i]); i+=2,j++) {
485 hex_to_byteval(&buf[i], &ciphertext[j]);
487 ciphertextlen = j;
489 rv = tdea_decrypt_buf(mode, key,
490 (mode == NSS_DES_EDE3) ? NULL : iv,
491 plaintext, &plaintextlen, sizeof plaintext,
492 ciphertext, ciphertextlen);
493 if (rv != SECSuccess) {
494 goto loser;
497 fputs(buf, resp);
498 fputs("PLAINTEXT = ", resp);
499 to_hex_str(buf, plaintext, plaintextlen);
500 fputs(buf, resp);
501 fputc('\n', resp);
502 continue;
506 loser:
507 fclose(req);
511 * Set the parity bit for the given byte
513 BYTE odd_parity( BYTE in)
515 BYTE out = in;
516 in ^= in >> 4;
517 in ^= in >> 2;
518 in ^= in >> 1;
519 return (BYTE)(out ^ !(in & 1));
523 * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j]
524 * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
526 void
527 tdea_mct_next_keys(unsigned char *key,
528 const unsigned char *text_2, const unsigned char *text_1,
529 const unsigned char *text, unsigned int numKeys)
531 int k;
533 /* key1[i+1] = key1[i] xor PT/CT[j] */
534 for (k=0; k<8; k++) {
535 key[k] ^= text[k];
537 /* key2 */
538 if (numKeys == 2 || numKeys == 3) {
539 /* key2 independent */
540 for (k=8; k<16; k++) {
541 /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
542 key[k] ^= text_1[k-8];
544 } else {
545 /* key2 == key 1 */
546 for (k=8; k<16; k++) {
547 /* key2[i+1] = KEY2[i] xor PT/CT[j] */
548 key[k] = key[k-8];
551 /* key3 */
552 if (numKeys == 1 || numKeys == 2) {
553 /* key3 == key 1 */
554 for (k=16; k<24; k++) {
555 /* key3[i+1] = KEY3[i] xor PT/CT[j] */
556 key[k] = key[k-16];
558 } else {
559 /* key3 independent */
560 for (k=16; k<24; k++) {
561 /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
562 key[k] ^= text_2[k-16];
565 /* set the parity bits */
566 for (k=0; k<24; k++) {
567 key[k] = odd_parity(key[k]);
572 * Perform the Monte Carlo Test
574 * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
575 * crypt = ENCRYPT || DECRYPT
576 * inputtext = plaintext or Cyphertext depending on the value of crypt
577 * inputlength is expected to be size 8 bytes
578 * iv = needs to be set for NSS_DES_EDE3_CBC mode
579 * resp = is the output response file.
581 void
582 tdea_mct_test(int mode, unsigned char* key, unsigned int numKeys,
583 unsigned int crypt, unsigned char* inputtext,
584 unsigned int inputlength, unsigned char* iv, FILE *resp) {
586 int i, j;
587 unsigned char outputtext_1[8]; /* PT/CT[j-1] */
588 unsigned char outputtext_2[8]; /* PT/CT[j-2] */
589 char buf[80]; /* holds one line from the input REQUEST file. */
590 unsigned int outputlen;
591 unsigned char outputtext[8];
594 SECStatus rv;
596 if (mode == NSS_DES_EDE3 && iv != NULL) {
597 printf("IV must be NULL for NSS_DES_EDE3 mode");
598 goto loser;
599 } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) {
600 printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
601 goto loser;
604 /* loop 400 times */
605 for (i=0; i<400; i++) {
606 /* if i == 0 CV[0] = IV not necessary */
607 /* record the count and key values and plainText */
608 sprintf(buf, "COUNT = %d\n", i);
609 fputs(buf, resp);
610 /* Output KEY1[i] */
611 fputs("KEY1 = ", resp);
612 to_hex_str(buf, key, 8);
613 fputs(buf, resp);
614 fputc('\n', resp);
615 /* Output KEY2[i] */
616 fputs("KEY2 = ", resp);
617 to_hex_str(buf, &key[8], 8);
618 fputs(buf, resp);
619 fputc('\n', resp);
620 /* Output KEY3[i] */
621 fputs("KEY3 = ", resp);
622 to_hex_str(buf, &key[16], 8);
623 fputs(buf, resp);
624 fputc('\n', resp);
625 if (mode == NSS_DES_EDE3_CBC) {
626 /* Output CV[i] */
627 fputs("IV = ", resp);
628 to_hex_str(buf, iv, 8);
629 fputs(buf, resp);
630 fputc('\n', resp);
632 if (crypt == ENCRYPT) {
633 /* Output PT[0] */
634 fputs("PLAINTEXT = ", resp);
635 } else {
636 /* Output CT[0] */
637 fputs("CIPHERTEXT = ", resp);
640 to_hex_str(buf, inputtext, inputlength);
641 fputs(buf, resp);
642 fputc('\n', resp);
644 /* loop 10,000 times */
645 for (j=0; j<10000; j++) {
647 outputlen = 0;
648 if (crypt == ENCRYPT) {
649 /* inputtext == ciphertext outputtext == plaintext*/
650 rv = tdea_encrypt_buf(mode, key,
651 (mode == NSS_DES_EDE3) ? NULL : iv,
652 outputtext, &outputlen, 8,
653 inputtext, 8);
654 } else {
655 /* inputtext == plaintext outputtext == ciphertext */
656 rv = tdea_decrypt_buf(mode, key,
657 (mode == NSS_DES_EDE3) ? NULL : iv,
658 outputtext, &outputlen, 8,
659 inputtext, 8);
662 if (rv != SECSuccess) {
663 goto loser;
665 if (outputlen != inputlength) {
666 goto loser;
669 if (mode == NSS_DES_EDE3_CBC) {
670 if (crypt == ENCRYPT) {
671 if (j == 0) {
672 /*P[j+1] = CV[0] */
673 memcpy(inputtext, iv, 8);
674 } else {
675 /* p[j+1] = C[j-1] */
676 memcpy(inputtext, outputtext_1, 8);
678 /* CV[j+1] = C[j] */
679 memcpy(iv, outputtext, 8);
680 if (j != 9999) {
681 /* save C[j-1] */
682 memcpy(outputtext_1, outputtext, 8);
684 } else { /* DECRYPT */
685 /* CV[j+1] = C[j] */
686 memcpy(iv, inputtext, 8);
687 /* C[j+1] = P[j] */
688 memcpy(inputtext, outputtext, 8);
690 } else {
691 /* ECB mode PT/CT[j+1] = CT/PT[j] */
692 memcpy(inputtext, outputtext, 8);
695 /* Save PT/CT[j-2] and PT/CT[j-1] */
696 if (j==9997) memcpy(outputtext_2, outputtext, 8);
697 if (j==9998) memcpy(outputtext_1, outputtext, 8);
698 /* done at the end of the for(j) loop */
702 if (crypt == ENCRYPT) {
703 /* Output CT[j] */
704 fputs("CIPHERTEXT = ", resp);
705 } else {
706 /* Output PT[j] */
707 fputs("PLAINTEXT = ", resp);
709 to_hex_str(buf, outputtext, 8);
710 fputs(buf, resp);
711 fputc('\n', resp);
713 /* Key[i+1] = Key[i] xor ... outputtext_2 == PT/CT[j-2]
714 * outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j]
716 tdea_mct_next_keys(key, outputtext_2,
717 outputtext_1, outputtext, numKeys);
719 if (mode == NSS_DES_EDE3_CBC) {
720 /* taken care of in the j=9999 iteration */
721 if (crypt == ENCRYPT) {
722 /* P[i] = C[j-1] */
723 /* CV[i] = C[j] */
724 } else {
725 /* taken care of in the j=9999 iteration */
726 /* CV[i] = C[j] */
727 /* C[i] = P[j] */
729 } else {
730 /* ECB PT/CT[i] = PT/CT[j] */
731 memcpy(inputtext, outputtext, 8);
733 /* done at the end of the for(i) loop */
734 fputc('\n', resp);
737 loser:
738 return;
742 * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
743 * by gathering the input from the request file, and then
744 * calling tdea_mct_test.
746 * reqfn is the pathname of the input REQUEST file.
748 * The output RESPONSE file is written to stdout.
750 void
751 tdea_mct(int mode, char *reqfn)
753 int i, j;
754 char buf[80]; /* holds one line from the input REQUEST file. */
755 FILE *req; /* input stream from the REQUEST file */
756 FILE *resp; /* output stream to the RESPONSE file */
757 unsigned int crypt = 0; /* 1 means encrypt, 0 means decrypt */
758 unsigned char key[24]; /* TDEA 3 key bundle */
759 unsigned int numKeys = 0;
760 unsigned char plaintext[8]; /* PT[j] */
761 unsigned char ciphertext[8]; /* CT[j] */
762 unsigned char iv[8];
764 /* zeroize the variables for the test with this data set */
765 memset(key, 0, sizeof key);
766 memset(plaintext, 0, sizeof plaintext);
767 memset(ciphertext, 0, sizeof ciphertext);
768 memset(iv, 0, sizeof iv);
770 req = fopen(reqfn, "r");
771 resp = stdout;
772 while (fgets(buf, sizeof buf, req) != NULL) {
773 /* a comment or blank line */
774 if (buf[0] == '#' || buf[0] == '\n') {
775 fputs(buf, resp);
776 continue;
778 /* [ENCRYPT] or [DECRYPT] */
779 if (buf[0] == '[') {
780 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
781 crypt = ENCRYPT;
782 } else {
783 crypt = DECRYPT;
785 fputs(buf, resp);
786 continue;
788 /* NumKeys */
789 if (strncmp(&buf[0], "NumKeys", 7) == 0) {
790 i = 7;
791 while (isspace(buf[i]) || buf[i] == '=') {
792 i++;
794 numKeys = atoi(&buf[i]);
795 continue;
797 /* KEY1 = ... */
798 if (strncmp(buf, "KEY1", 4) == 0) {
799 i = 4;
800 while (isspace(buf[i]) || buf[i] == '=') {
801 i++;
803 for (j=0; isxdigit(buf[i]); i+=2,j++) {
804 hex_to_byteval(&buf[i], &key[j]);
806 continue;
808 /* KEY2 = ... */
809 if (strncmp(buf, "KEY2", 4) == 0) {
810 i = 4;
811 while (isspace(buf[i]) || buf[i] == '=') {
812 i++;
814 for (j=8; isxdigit(buf[i]); i+=2,j++) {
815 hex_to_byteval(&buf[i], &key[j]);
817 continue;
819 /* KEY3 = ... */
820 if (strncmp(buf, "KEY3", 4) == 0) {
821 i = 4;
822 while (isspace(buf[i]) || buf[i] == '=') {
823 i++;
825 for (j=16; isxdigit(buf[i]); i+=2,j++) {
826 hex_to_byteval(&buf[i], &key[j]);
828 continue;
831 /* IV = ... */
832 if (strncmp(buf, "IV", 2) == 0) {
833 i = 2;
834 while (isspace(buf[i]) || buf[i] == '=') {
835 i++;
837 for (j=0; j<sizeof iv; i+=2,j++) {
838 hex_to_byteval(&buf[i], &iv[j]);
840 continue;
843 /* PLAINTEXT = ... */
844 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
846 /* sanity check */
847 if (crypt != ENCRYPT) {
848 goto loser;
850 /* PT[0] = PT */
851 i = 9;
852 while (isspace(buf[i]) || buf[i] == '=') {
853 i++;
855 for (j=0; j<sizeof plaintext; i+=2,j++) {
856 hex_to_byteval(&buf[i], &plaintext[j]);
859 /* do the Monte Carlo test */
860 if (mode==NSS_DES_EDE3) {
861 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp);
862 } else {
863 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp);
865 continue;
867 /* CIPHERTEXT = ... */
868 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
869 /* sanity check */
870 if (crypt != DECRYPT) {
871 goto loser;
873 /* CT[0] = CT */
874 i = 10;
875 while (isspace(buf[i]) || buf[i] == '=') {
876 i++;
878 for (j=0; isxdigit(buf[i]); i+=2,j++) {
879 hex_to_byteval(&buf[i], &ciphertext[j]);
882 /* do the Monte Carlo test */
883 if (mode==NSS_DES_EDE3) {
884 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp);
885 } else {
886 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp);
888 continue;
892 loser:
893 fclose(req);
897 SECStatus
898 aes_encrypt_buf(
899 int mode,
900 const unsigned char *key, unsigned int keysize,
901 const unsigned char *iv,
902 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
903 const unsigned char *input, unsigned int inputlen)
905 SECStatus rv = SECFailure;
906 AESContext *cx;
907 unsigned char doublecheck[10*16]; /* 1 to 10 blocks */
908 unsigned int doublechecklen = 0;
910 cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
911 if (cx == NULL) {
912 goto loser;
914 rv = AES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
915 if (rv != SECSuccess) {
916 goto loser;
918 if (*outputlen != inputlen) {
919 goto loser;
921 AES_DestroyContext(cx, PR_TRUE);
922 cx = NULL;
925 * Doublecheck our result by decrypting the ciphertext and
926 * compare the output with the input plaintext.
928 cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
929 if (cx == NULL) {
930 goto loser;
932 rv = AES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
933 output, *outputlen);
934 if (rv != SECSuccess) {
935 goto loser;
937 if (doublechecklen != *outputlen) {
938 goto loser;
940 AES_DestroyContext(cx, PR_TRUE);
941 cx = NULL;
942 if (memcmp(doublecheck, input, inputlen) != 0) {
943 goto loser;
945 rv = SECSuccess;
947 loser:
948 if (cx != NULL) {
949 AES_DestroyContext(cx, PR_TRUE);
951 return rv;
954 SECStatus
955 aes_decrypt_buf(
956 int mode,
957 const unsigned char *key, unsigned int keysize,
958 const unsigned char *iv,
959 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
960 const unsigned char *input, unsigned int inputlen)
962 SECStatus rv = SECFailure;
963 AESContext *cx;
964 unsigned char doublecheck[10*16]; /* 1 to 10 blocks */
965 unsigned int doublechecklen = 0;
967 cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
968 if (cx == NULL) {
969 goto loser;
971 rv = AES_Decrypt(cx, output, outputlen, maxoutputlen,
972 input, inputlen);
973 if (rv != SECSuccess) {
974 goto loser;
976 if (*outputlen != inputlen) {
977 goto loser;
979 AES_DestroyContext(cx, PR_TRUE);
980 cx = NULL;
983 * Doublecheck our result by encrypting the plaintext and
984 * compare the output with the input ciphertext.
986 cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
987 if (cx == NULL) {
988 goto loser;
990 rv = AES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
991 output, *outputlen);
992 if (rv != SECSuccess) {
993 goto loser;
995 if (doublechecklen != *outputlen) {
996 goto loser;
998 AES_DestroyContext(cx, PR_TRUE);
999 cx = NULL;
1000 if (memcmp(doublecheck, input, inputlen) != 0) {
1001 goto loser;
1003 rv = SECSuccess;
1005 loser:
1006 if (cx != NULL) {
1007 AES_DestroyContext(cx, PR_TRUE);
1009 return rv;
1013 * Perform the AES Known Answer Test (KAT) or Multi-block Message
1014 * Test (MMT) in ECB or CBC mode. The KAT (there are four types)
1015 * and MMT have the same structure: given the key and IV (CBC mode
1016 * only), encrypt the given plaintext or decrypt the given ciphertext.
1017 * So we can handle them the same way.
1019 * reqfn is the pathname of the REQUEST file.
1021 * The output RESPONSE file is written to stdout.
1023 void
1024 aes_kat_mmt(char *reqfn)
1026 char buf[512]; /* holds one line from the input REQUEST file.
1027 * needs to be large enough to hold the longest
1028 * line "CIPHERTEXT = <320 hex digits>\n".
1030 FILE *aesreq; /* input stream from the REQUEST file */
1031 FILE *aesresp; /* output stream to the RESPONSE file */
1032 int i, j;
1033 int mode; /* NSS_AES (ECB) or NSS_AES_CBC */
1034 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
1035 unsigned char key[32]; /* 128, 192, or 256 bits */
1036 unsigned int keysize;
1037 unsigned char iv[16]; /* for all modes except ECB */
1038 unsigned char plaintext[10*16]; /* 1 to 10 blocks */
1039 unsigned int plaintextlen;
1040 unsigned char ciphertext[10*16]; /* 1 to 10 blocks */
1041 unsigned int ciphertextlen;
1042 SECStatus rv;
1044 aesreq = fopen(reqfn, "r");
1045 aesresp = stdout;
1046 while (fgets(buf, sizeof buf, aesreq) != NULL) {
1047 /* a comment or blank line */
1048 if (buf[0] == '#' || buf[0] == '\n') {
1049 fputs(buf, aesresp);
1050 continue;
1052 /* [ENCRYPT] or [DECRYPT] */
1053 if (buf[0] == '[') {
1054 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1055 encrypt = 1;
1056 } else {
1057 encrypt = 0;
1059 fputs(buf, aesresp);
1060 continue;
1062 /* "COUNT = x" begins a new data set */
1063 if (strncmp(buf, "COUNT", 5) == 0) {
1064 mode = NSS_AES;
1065 /* zeroize the variables for the test with this data set */
1066 memset(key, 0, sizeof key);
1067 keysize = 0;
1068 memset(iv, 0, sizeof iv);
1069 memset(plaintext, 0, sizeof plaintext);
1070 plaintextlen = 0;
1071 memset(ciphertext, 0, sizeof ciphertext);
1072 ciphertextlen = 0;
1073 fputs(buf, aesresp);
1074 continue;
1076 /* KEY = ... */
1077 if (strncmp(buf, "KEY", 3) == 0) {
1078 i = 3;
1079 while (isspace(buf[i]) || buf[i] == '=') {
1080 i++;
1082 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1083 hex_to_byteval(&buf[i], &key[j]);
1085 keysize = j;
1086 fputs(buf, aesresp);
1087 continue;
1089 /* IV = ... */
1090 if (strncmp(buf, "IV", 2) == 0) {
1091 mode = NSS_AES_CBC;
1092 i = 2;
1093 while (isspace(buf[i]) || buf[i] == '=') {
1094 i++;
1096 for (j=0; j<sizeof iv; i+=2,j++) {
1097 hex_to_byteval(&buf[i], &iv[j]);
1099 fputs(buf, aesresp);
1100 continue;
1102 /* PLAINTEXT = ... */
1103 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1104 /* sanity check */
1105 if (!encrypt) {
1106 goto loser;
1109 i = 9;
1110 while (isspace(buf[i]) || buf[i] == '=') {
1111 i++;
1113 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1114 hex_to_byteval(&buf[i], &plaintext[j]);
1116 plaintextlen = j;
1118 rv = aes_encrypt_buf(mode, key, keysize,
1119 (mode == NSS_AES) ? NULL : iv,
1120 ciphertext, &ciphertextlen, sizeof ciphertext,
1121 plaintext, plaintextlen);
1122 if (rv != SECSuccess) {
1123 goto loser;
1126 fputs(buf, aesresp);
1127 fputs("CIPHERTEXT = ", aesresp);
1128 to_hex_str(buf, ciphertext, ciphertextlen);
1129 fputs(buf, aesresp);
1130 fputc('\n', aesresp);
1131 continue;
1133 /* CIPHERTEXT = ... */
1134 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1135 /* sanity check */
1136 if (encrypt) {
1137 goto loser;
1140 i = 10;
1141 while (isspace(buf[i]) || buf[i] == '=') {
1142 i++;
1144 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1145 hex_to_byteval(&buf[i], &ciphertext[j]);
1147 ciphertextlen = j;
1149 rv = aes_decrypt_buf(mode, key, keysize,
1150 (mode == NSS_AES) ? NULL : iv,
1151 plaintext, &plaintextlen, sizeof plaintext,
1152 ciphertext, ciphertextlen);
1153 if (rv != SECSuccess) {
1154 goto loser;
1157 fputs(buf, aesresp);
1158 fputs("PLAINTEXT = ", aesresp);
1159 to_hex_str(buf, plaintext, plaintextlen);
1160 fputs(buf, aesresp);
1161 fputc('\n', aesresp);
1162 continue;
1165 loser:
1166 fclose(aesreq);
1170 * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
1171 * Test (MCT) in ECB and CBC modes.
1173 void
1174 aes_mct_next_key(unsigned char *key, unsigned int keysize,
1175 const unsigned char *ciphertext_1, const unsigned char *ciphertext)
1177 int k;
1179 switch (keysize) {
1180 case 16: /* 128-bit key */
1181 /* Key[i+1] = Key[i] xor CT[j] */
1182 for (k=0; k<16; k++) {
1183 key[k] ^= ciphertext[k];
1185 break;
1186 case 24: /* 192-bit key */
1188 * Key[i+1] = Key[i] xor (last 64-bits of
1189 * CT[j-1] || CT[j])
1191 for (k=0; k<8; k++) {
1192 key[k] ^= ciphertext_1[k+8];
1194 for (k=8; k<24; k++) {
1195 key[k] ^= ciphertext[k-8];
1197 break;
1198 case 32: /* 256-bit key */
1199 /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
1200 for (k=0; k<16; k++) {
1201 key[k] ^= ciphertext_1[k];
1203 for (k=16; k<32; k++) {
1204 key[k] ^= ciphertext[k-16];
1206 break;
1211 * Perform the AES Monte Carlo Test (MCT) in ECB mode. MCT exercises
1212 * our AES code in streaming mode because the plaintext or ciphertext
1213 * is generated block by block as we go, so we can't collect all the
1214 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1215 * one shot.
1217 * reqfn is the pathname of the input REQUEST file.
1219 * The output RESPONSE file is written to stdout.
1221 void
1222 aes_ecb_mct(char *reqfn)
1224 char buf[80]; /* holds one line from the input REQUEST file.
1225 * needs to be large enough to hold the longest
1226 * line "KEY = <64 hex digits>\n".
1228 FILE *aesreq; /* input stream from the REQUEST file */
1229 FILE *aesresp; /* output stream to the RESPONSE file */
1230 int i, j;
1231 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
1232 unsigned char key[32]; /* 128, 192, or 256 bits */
1233 unsigned int keysize;
1234 unsigned char plaintext[16]; /* PT[j] */
1235 unsigned char plaintext_1[16]; /* PT[j-1] */
1236 unsigned char ciphertext[16]; /* CT[j] */
1237 unsigned char ciphertext_1[16]; /* CT[j-1] */
1238 unsigned char doublecheck[16];
1239 unsigned int outputlen;
1240 AESContext *cx = NULL; /* the operation being tested */
1241 AESContext *cx2 = NULL; /* the inverse operation done in parallel
1242 * to doublecheck our result.
1244 SECStatus rv;
1246 aesreq = fopen(reqfn, "r");
1247 aesresp = stdout;
1248 while (fgets(buf, sizeof buf, aesreq) != NULL) {
1249 /* a comment or blank line */
1250 if (buf[0] == '#' || buf[0] == '\n') {
1251 fputs(buf, aesresp);
1252 continue;
1254 /* [ENCRYPT] or [DECRYPT] */
1255 if (buf[0] == '[') {
1256 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1257 encrypt = 1;
1258 } else {
1259 encrypt = 0;
1261 fputs(buf, aesresp);
1262 continue;
1264 /* "COUNT = x" begins a new data set */
1265 if (strncmp(buf, "COUNT", 5) == 0) {
1266 /* zeroize the variables for the test with this data set */
1267 memset(key, 0, sizeof key);
1268 keysize = 0;
1269 memset(plaintext, 0, sizeof plaintext);
1270 memset(ciphertext, 0, sizeof ciphertext);
1271 continue;
1273 /* KEY = ... */
1274 if (strncmp(buf, "KEY", 3) == 0) {
1275 /* Key[0] = Key */
1276 i = 3;
1277 while (isspace(buf[i]) || buf[i] == '=') {
1278 i++;
1280 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1281 hex_to_byteval(&buf[i], &key[j]);
1283 keysize = j;
1284 continue;
1286 /* PLAINTEXT = ... */
1287 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1288 /* sanity check */
1289 if (!encrypt) {
1290 goto loser;
1292 /* PT[0] = PT */
1293 i = 9;
1294 while (isspace(buf[i]) || buf[i] == '=') {
1295 i++;
1297 for (j=0; j<sizeof plaintext; i+=2,j++) {
1298 hex_to_byteval(&buf[i], &plaintext[j]);
1301 for (i=0; i<100; i++) {
1302 sprintf(buf, "COUNT = %d\n", i);
1303 fputs(buf, aesresp);
1304 /* Output Key[i] */
1305 fputs("KEY = ", aesresp);
1306 to_hex_str(buf, key, keysize);
1307 fputs(buf, aesresp);
1308 fputc('\n', aesresp);
1309 /* Output PT[0] */
1310 fputs("PLAINTEXT = ", aesresp);
1311 to_hex_str(buf, plaintext, sizeof plaintext);
1312 fputs(buf, aesresp);
1313 fputc('\n', aesresp);
1315 cx = AES_CreateContext(key, NULL, NSS_AES,
1316 PR_TRUE, keysize, 16);
1317 if (cx == NULL) {
1318 goto loser;
1321 * doublecheck our result by decrypting the result
1322 * and comparing the output with the plaintext.
1324 cx2 = AES_CreateContext(key, NULL, NSS_AES,
1325 PR_FALSE, keysize, 16);
1326 if (cx2 == NULL) {
1327 goto loser;
1329 for (j=0; j<1000; j++) {
1330 /* Save CT[j-1] */
1331 memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
1333 /* CT[j] = AES(Key[i], PT[j]) */
1334 outputlen = 0;
1335 rv = AES_Encrypt(cx,
1336 ciphertext, &outputlen, sizeof ciphertext,
1337 plaintext, sizeof plaintext);
1338 if (rv != SECSuccess) {
1339 goto loser;
1341 if (outputlen != sizeof plaintext) {
1342 goto loser;
1345 /* doublecheck our result */
1346 outputlen = 0;
1347 rv = AES_Decrypt(cx2,
1348 doublecheck, &outputlen, sizeof doublecheck,
1349 ciphertext, sizeof ciphertext);
1350 if (rv != SECSuccess) {
1351 goto loser;
1353 if (outputlen != sizeof ciphertext) {
1354 goto loser;
1356 if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
1357 goto loser;
1360 /* PT[j+1] = CT[j] */
1361 memcpy(plaintext, ciphertext, sizeof plaintext);
1363 AES_DestroyContext(cx, PR_TRUE);
1364 cx = NULL;
1365 AES_DestroyContext(cx2, PR_TRUE);
1366 cx2 = NULL;
1368 /* Output CT[j] */
1369 fputs("CIPHERTEXT = ", aesresp);
1370 to_hex_str(buf, ciphertext, sizeof ciphertext);
1371 fputs(buf, aesresp);
1372 fputc('\n', aesresp);
1374 /* Key[i+1] = Key[i] xor ... */
1375 aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
1376 /* PT[0] = CT[j] */
1377 /* done at the end of the for(j) loop */
1379 fputc('\n', aesresp);
1382 continue;
1384 /* CIPHERTEXT = ... */
1385 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1386 /* sanity check */
1387 if (encrypt) {
1388 goto loser;
1390 /* CT[0] = CT */
1391 i = 10;
1392 while (isspace(buf[i]) || buf[i] == '=') {
1393 i++;
1395 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1396 hex_to_byteval(&buf[i], &ciphertext[j]);
1399 for (i=0; i<100; i++) {
1400 sprintf(buf, "COUNT = %d\n", i);
1401 fputs(buf, aesresp);
1402 /* Output Key[i] */
1403 fputs("KEY = ", aesresp);
1404 to_hex_str(buf, key, keysize);
1405 fputs(buf, aesresp);
1406 fputc('\n', aesresp);
1407 /* Output CT[0] */
1408 fputs("CIPHERTEXT = ", aesresp);
1409 to_hex_str(buf, ciphertext, sizeof ciphertext);
1410 fputs(buf, aesresp);
1411 fputc('\n', aesresp);
1413 cx = AES_CreateContext(key, NULL, NSS_AES,
1414 PR_FALSE, keysize, 16);
1415 if (cx == NULL) {
1416 goto loser;
1419 * doublecheck our result by encrypting the result
1420 * and comparing the output with the ciphertext.
1422 cx2 = AES_CreateContext(key, NULL, NSS_AES,
1423 PR_TRUE, keysize, 16);
1424 if (cx2 == NULL) {
1425 goto loser;
1427 for (j=0; j<1000; j++) {
1428 /* Save PT[j-1] */
1429 memcpy(plaintext_1, plaintext, sizeof plaintext);
1431 /* PT[j] = AES(Key[i], CT[j]) */
1432 outputlen = 0;
1433 rv = AES_Decrypt(cx,
1434 plaintext, &outputlen, sizeof plaintext,
1435 ciphertext, sizeof ciphertext);
1436 if (rv != SECSuccess) {
1437 goto loser;
1439 if (outputlen != sizeof ciphertext) {
1440 goto loser;
1443 /* doublecheck our result */
1444 outputlen = 0;
1445 rv = AES_Encrypt(cx2,
1446 doublecheck, &outputlen, sizeof doublecheck,
1447 plaintext, sizeof plaintext);
1448 if (rv != SECSuccess) {
1449 goto loser;
1451 if (outputlen != sizeof plaintext) {
1452 goto loser;
1454 if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
1455 goto loser;
1458 /* CT[j+1] = PT[j] */
1459 memcpy(ciphertext, plaintext, sizeof ciphertext);
1461 AES_DestroyContext(cx, PR_TRUE);
1462 cx = NULL;
1463 AES_DestroyContext(cx2, PR_TRUE);
1464 cx2 = NULL;
1466 /* Output PT[j] */
1467 fputs("PLAINTEXT = ", aesresp);
1468 to_hex_str(buf, plaintext, sizeof plaintext);
1469 fputs(buf, aesresp);
1470 fputc('\n', aesresp);
1472 /* Key[i+1] = Key[i] xor ... */
1473 aes_mct_next_key(key, keysize, plaintext_1, plaintext);
1474 /* CT[0] = PT[j] */
1475 /* done at the end of the for(j) loop */
1477 fputc('\n', aesresp);
1480 continue;
1483 loser:
1484 if (cx != NULL) {
1485 AES_DestroyContext(cx, PR_TRUE);
1487 if (cx2 != NULL) {
1488 AES_DestroyContext(cx2, PR_TRUE);
1490 fclose(aesreq);
1494 * Perform the AES Monte Carlo Test (MCT) in CBC mode. MCT exercises
1495 * our AES code in streaming mode because the plaintext or ciphertext
1496 * is generated block by block as we go, so we can't collect all the
1497 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1498 * one shot.
1500 * reqfn is the pathname of the input REQUEST file.
1502 * The output RESPONSE file is written to stdout.
1504 void
1505 aes_cbc_mct(char *reqfn)
1507 char buf[80]; /* holds one line from the input REQUEST file.
1508 * needs to be large enough to hold the longest
1509 * line "KEY = <64 hex digits>\n".
1511 FILE *aesreq; /* input stream from the REQUEST file */
1512 FILE *aesresp; /* output stream to the RESPONSE file */
1513 int i, j;
1514 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
1515 unsigned char key[32]; /* 128, 192, or 256 bits */
1516 unsigned int keysize;
1517 unsigned char iv[16];
1518 unsigned char plaintext[16]; /* PT[j] */
1519 unsigned char plaintext_1[16]; /* PT[j-1] */
1520 unsigned char ciphertext[16]; /* CT[j] */
1521 unsigned char ciphertext_1[16]; /* CT[j-1] */
1522 unsigned char doublecheck[16];
1523 unsigned int outputlen;
1524 AESContext *cx = NULL; /* the operation being tested */
1525 AESContext *cx2 = NULL; /* the inverse operation done in parallel
1526 * to doublecheck our result.
1528 SECStatus rv;
1530 aesreq = fopen(reqfn, "r");
1531 aesresp = stdout;
1532 while (fgets(buf, sizeof buf, aesreq) != NULL) {
1533 /* a comment or blank line */
1534 if (buf[0] == '#' || buf[0] == '\n') {
1535 fputs(buf, aesresp);
1536 continue;
1538 /* [ENCRYPT] or [DECRYPT] */
1539 if (buf[0] == '[') {
1540 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1541 encrypt = 1;
1542 } else {
1543 encrypt = 0;
1545 fputs(buf, aesresp);
1546 continue;
1548 /* "COUNT = x" begins a new data set */
1549 if (strncmp(buf, "COUNT", 5) == 0) {
1550 /* zeroize the variables for the test with this data set */
1551 memset(key, 0, sizeof key);
1552 keysize = 0;
1553 memset(iv, 0, sizeof iv);
1554 memset(plaintext, 0, sizeof plaintext);
1555 memset(ciphertext, 0, sizeof ciphertext);
1556 continue;
1558 /* KEY = ... */
1559 if (strncmp(buf, "KEY", 3) == 0) {
1560 /* Key[0] = Key */
1561 i = 3;
1562 while (isspace(buf[i]) || buf[i] == '=') {
1563 i++;
1565 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1566 hex_to_byteval(&buf[i], &key[j]);
1568 keysize = j;
1569 continue;
1571 /* IV = ... */
1572 if (strncmp(buf, "IV", 2) == 0) {
1573 /* IV[0] = IV */
1574 i = 2;
1575 while (isspace(buf[i]) || buf[i] == '=') {
1576 i++;
1578 for (j=0; j<sizeof iv; i+=2,j++) {
1579 hex_to_byteval(&buf[i], &iv[j]);
1581 continue;
1583 /* PLAINTEXT = ... */
1584 if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1585 /* sanity check */
1586 if (!encrypt) {
1587 goto loser;
1589 /* PT[0] = PT */
1590 i = 9;
1591 while (isspace(buf[i]) || buf[i] == '=') {
1592 i++;
1594 for (j=0; j<sizeof plaintext; i+=2,j++) {
1595 hex_to_byteval(&buf[i], &plaintext[j]);
1598 for (i=0; i<100; i++) {
1599 sprintf(buf, "COUNT = %d\n", i);
1600 fputs(buf, aesresp);
1601 /* Output Key[i] */
1602 fputs("KEY = ", aesresp);
1603 to_hex_str(buf, key, keysize);
1604 fputs(buf, aesresp);
1605 fputc('\n', aesresp);
1606 /* Output IV[i] */
1607 fputs("IV = ", aesresp);
1608 to_hex_str(buf, iv, sizeof iv);
1609 fputs(buf, aesresp);
1610 fputc('\n', aesresp);
1611 /* Output PT[0] */
1612 fputs("PLAINTEXT = ", aesresp);
1613 to_hex_str(buf, plaintext, sizeof plaintext);
1614 fputs(buf, aesresp);
1615 fputc('\n', aesresp);
1617 cx = AES_CreateContext(key, iv, NSS_AES_CBC,
1618 PR_TRUE, keysize, 16);
1619 if (cx == NULL) {
1620 goto loser;
1623 * doublecheck our result by decrypting the result
1624 * and comparing the output with the plaintext.
1626 cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
1627 PR_FALSE, keysize, 16);
1628 if (cx2 == NULL) {
1629 goto loser;
1631 /* CT[-1] = IV[i] */
1632 memcpy(ciphertext, iv, sizeof ciphertext);
1633 for (j=0; j<1000; j++) {
1634 /* Save CT[j-1] */
1635 memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
1637 * If ( j=0 )
1638 * CT[j] = AES(Key[i], IV[i], PT[j])
1639 * PT[j+1] = IV[i] (= CT[j-1])
1640 * Else
1641 * CT[j] = AES(Key[i], PT[j])
1642 * PT[j+1] = CT[j-1]
1644 outputlen = 0;
1645 rv = AES_Encrypt(cx,
1646 ciphertext, &outputlen, sizeof ciphertext,
1647 plaintext, sizeof plaintext);
1648 if (rv != SECSuccess) {
1649 goto loser;
1651 if (outputlen != sizeof plaintext) {
1652 goto loser;
1655 /* doublecheck our result */
1656 outputlen = 0;
1657 rv = AES_Decrypt(cx2,
1658 doublecheck, &outputlen, sizeof doublecheck,
1659 ciphertext, sizeof ciphertext);
1660 if (rv != SECSuccess) {
1661 goto loser;
1663 if (outputlen != sizeof ciphertext) {
1664 goto loser;
1666 if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
1667 goto loser;
1670 memcpy(plaintext, ciphertext_1, sizeof plaintext);
1672 AES_DestroyContext(cx, PR_TRUE);
1673 cx = NULL;
1674 AES_DestroyContext(cx2, PR_TRUE);
1675 cx2 = NULL;
1677 /* Output CT[j] */
1678 fputs("CIPHERTEXT = ", aesresp);
1679 to_hex_str(buf, ciphertext, sizeof ciphertext);
1680 fputs(buf, aesresp);
1681 fputc('\n', aesresp);
1683 /* Key[i+1] = Key[i] xor ... */
1684 aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
1685 /* IV[i+1] = CT[j] */
1686 memcpy(iv, ciphertext, sizeof iv);
1687 /* PT[0] = CT[j-1] */
1688 /* done at the end of the for(j) loop */
1690 fputc('\n', aesresp);
1693 continue;
1695 /* CIPHERTEXT = ... */
1696 if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1697 /* sanity check */
1698 if (encrypt) {
1699 goto loser;
1701 /* CT[0] = CT */
1702 i = 10;
1703 while (isspace(buf[i]) || buf[i] == '=') {
1704 i++;
1706 for (j=0; isxdigit(buf[i]); i+=2,j++) {
1707 hex_to_byteval(&buf[i], &ciphertext[j]);
1710 for (i=0; i<100; i++) {
1711 sprintf(buf, "COUNT = %d\n", i);
1712 fputs(buf, aesresp);
1713 /* Output Key[i] */
1714 fputs("KEY = ", aesresp);
1715 to_hex_str(buf, key, keysize);
1716 fputs(buf, aesresp);
1717 fputc('\n', aesresp);
1718 /* Output IV[i] */
1719 fputs("IV = ", aesresp);
1720 to_hex_str(buf, iv, sizeof iv);
1721 fputs(buf, aesresp);
1722 fputc('\n', aesresp);
1723 /* Output CT[0] */
1724 fputs("CIPHERTEXT = ", aesresp);
1725 to_hex_str(buf, ciphertext, sizeof ciphertext);
1726 fputs(buf, aesresp);
1727 fputc('\n', aesresp);
1729 cx = AES_CreateContext(key, iv, NSS_AES_CBC,
1730 PR_FALSE, keysize, 16);
1731 if (cx == NULL) {
1732 goto loser;
1735 * doublecheck our result by encrypting the result
1736 * and comparing the output with the ciphertext.
1738 cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
1739 PR_TRUE, keysize, 16);
1740 if (cx2 == NULL) {
1741 goto loser;
1743 /* PT[-1] = IV[i] */
1744 memcpy(plaintext, iv, sizeof plaintext);
1745 for (j=0; j<1000; j++) {
1746 /* Save PT[j-1] */
1747 memcpy(plaintext_1, plaintext, sizeof plaintext);
1749 * If ( j=0 )
1750 * PT[j] = AES(Key[i], IV[i], CT[j])
1751 * CT[j+1] = IV[i] (= PT[j-1])
1752 * Else
1753 * PT[j] = AES(Key[i], CT[j])
1754 * CT[j+1] = PT[j-1]
1756 outputlen = 0;
1757 rv = AES_Decrypt(cx,
1758 plaintext, &outputlen, sizeof plaintext,
1759 ciphertext, sizeof ciphertext);
1760 if (rv != SECSuccess) {
1761 goto loser;
1763 if (outputlen != sizeof ciphertext) {
1764 goto loser;
1767 /* doublecheck our result */
1768 outputlen = 0;
1769 rv = AES_Encrypt(cx2,
1770 doublecheck, &outputlen, sizeof doublecheck,
1771 plaintext, sizeof plaintext);
1772 if (rv != SECSuccess) {
1773 goto loser;
1775 if (outputlen != sizeof plaintext) {
1776 goto loser;
1778 if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
1779 goto loser;
1782 memcpy(ciphertext, plaintext_1, sizeof ciphertext);
1784 AES_DestroyContext(cx, PR_TRUE);
1785 cx = NULL;
1786 AES_DestroyContext(cx2, PR_TRUE);
1787 cx2 = NULL;
1789 /* Output PT[j] */
1790 fputs("PLAINTEXT = ", aesresp);
1791 to_hex_str(buf, plaintext, sizeof plaintext);
1792 fputs(buf, aesresp);
1793 fputc('\n', aesresp);
1795 /* Key[i+1] = Key[i] xor ... */
1796 aes_mct_next_key(key, keysize, plaintext_1, plaintext);
1797 /* IV[i+1] = PT[j] */
1798 memcpy(iv, plaintext, sizeof iv);
1799 /* CT[0] = PT[j-1] */
1800 /* done at the end of the for(j) loop */
1802 fputc('\n', aesresp);
1805 continue;
1808 loser:
1809 if (cx != NULL) {
1810 AES_DestroyContext(cx, PR_TRUE);
1812 if (cx2 != NULL) {
1813 AES_DestroyContext(cx2, PR_TRUE);
1815 fclose(aesreq);
1818 void write_compact_string(FILE *out, unsigned char *hash, unsigned int len)
1820 unsigned int i;
1821 int j, count = 0, last = -1, z = 0;
1822 long start = ftell(out);
1823 for (i=0; i<len; i++) {
1824 for (j=7; j>=0; j--) {
1825 if (last < 0) {
1826 last = (hash[i] & (1 << j)) ? 1 : 0;
1827 fprintf(out, "%d ", last);
1828 count = 1;
1829 } else if (hash[i] & (1 << j)) {
1830 if (last) {
1831 count++;
1832 } else {
1833 last = 0;
1834 fprintf(out, "%d ", count);
1835 count = 1;
1836 z++;
1838 } else {
1839 if (!last) {
1840 count++;
1841 } else {
1842 last = 1;
1843 fprintf(out, "%d ", count);
1844 count = 1;
1845 z++;
1850 fprintf(out, "^\n");
1851 fseek(out, start, SEEK_SET);
1852 fprintf(out, "%d ", z);
1853 fseek(out, 0, SEEK_END);
1856 int get_next_line(FILE *req, char *key, char *val, FILE *rsp)
1858 int ignore = 0;
1859 char *writeto = key;
1860 int w = 0;
1861 int c;
1862 while ((c = fgetc(req)) != EOF) {
1863 if (ignore) {
1864 fprintf(rsp, "%c", c);
1865 if (c == '\n') return ignore;
1866 } else if (c == '\n') {
1867 break;
1868 } else if (c == '#') {
1869 ignore = 1;
1870 fprintf(rsp, "%c", c);
1871 } else if (c == '=') {
1872 writeto[w] = '\0';
1873 w = 0;
1874 writeto = val;
1875 } else if (c == ' ' || c == '[' || c == ']') {
1876 continue;
1877 } else {
1878 writeto[w++] = c;
1881 writeto[w] = '\0';
1882 return (c == EOF) ? -1 : ignore;
1885 #ifdef NSS_ENABLE_ECC
1886 typedef struct curveNameTagPairStr {
1887 char *curveName;
1888 SECOidTag curveOidTag;
1889 } CurveNameTagPair;
1891 #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
1892 /* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */
1894 static CurveNameTagPair nameTagPair[] =
1896 { "sect163k1", SEC_OID_SECG_EC_SECT163K1},
1897 { "nistk163", SEC_OID_SECG_EC_SECT163K1},
1898 { "sect163r1", SEC_OID_SECG_EC_SECT163R1},
1899 { "sect163r2", SEC_OID_SECG_EC_SECT163R2},
1900 { "nistb163", SEC_OID_SECG_EC_SECT163R2},
1901 { "sect193r1", SEC_OID_SECG_EC_SECT193R1},
1902 { "sect193r2", SEC_OID_SECG_EC_SECT193R2},
1903 { "sect233k1", SEC_OID_SECG_EC_SECT233K1},
1904 { "nistk233", SEC_OID_SECG_EC_SECT233K1},
1905 { "sect233r1", SEC_OID_SECG_EC_SECT233R1},
1906 { "nistb233", SEC_OID_SECG_EC_SECT233R1},
1907 { "sect239k1", SEC_OID_SECG_EC_SECT239K1},
1908 { "sect283k1", SEC_OID_SECG_EC_SECT283K1},
1909 { "nistk283", SEC_OID_SECG_EC_SECT283K1},
1910 { "sect283r1", SEC_OID_SECG_EC_SECT283R1},
1911 { "nistb283", SEC_OID_SECG_EC_SECT283R1},
1912 { "sect409k1", SEC_OID_SECG_EC_SECT409K1},
1913 { "nistk409", SEC_OID_SECG_EC_SECT409K1},
1914 { "sect409r1", SEC_OID_SECG_EC_SECT409R1},
1915 { "nistb409", SEC_OID_SECG_EC_SECT409R1},
1916 { "sect571k1", SEC_OID_SECG_EC_SECT571K1},
1917 { "nistk571", SEC_OID_SECG_EC_SECT571K1},
1918 { "sect571r1", SEC_OID_SECG_EC_SECT571R1},
1919 { "nistb571", SEC_OID_SECG_EC_SECT571R1},
1920 { "secp160k1", SEC_OID_SECG_EC_SECP160K1},
1921 { "secp160r1", SEC_OID_SECG_EC_SECP160R1},
1922 { "secp160r2", SEC_OID_SECG_EC_SECP160R2},
1923 { "secp192k1", SEC_OID_SECG_EC_SECP192K1},
1924 { "secp192r1", SEC_OID_SECG_EC_SECP192R1},
1925 { "nistp192", SEC_OID_SECG_EC_SECP192R1},
1926 { "secp224k1", SEC_OID_SECG_EC_SECP224K1},
1927 { "secp224r1", SEC_OID_SECG_EC_SECP224R1},
1928 { "nistp224", SEC_OID_SECG_EC_SECP224R1},
1929 { "secp256k1", SEC_OID_SECG_EC_SECP256K1},
1930 { "secp256r1", SEC_OID_SECG_EC_SECP256R1},
1931 { "nistp256", SEC_OID_SECG_EC_SECP256R1},
1932 { "secp384r1", SEC_OID_SECG_EC_SECP384R1},
1933 { "nistp384", SEC_OID_SECG_EC_SECP384R1},
1934 { "secp521r1", SEC_OID_SECG_EC_SECP521R1},
1935 { "nistp521", SEC_OID_SECG_EC_SECP521R1},
1937 { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
1938 { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
1939 { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
1940 { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
1941 { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
1942 { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
1944 { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
1945 { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
1946 { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
1947 { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
1948 { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
1949 { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
1950 { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
1951 { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
1952 { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
1953 { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
1954 { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
1955 { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
1956 { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
1957 { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
1958 { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
1959 { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
1960 { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
1961 { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
1962 { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
1963 { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
1965 { "secp112r1", SEC_OID_SECG_EC_SECP112R1},
1966 { "secp112r2", SEC_OID_SECG_EC_SECP112R2},
1967 { "secp128r1", SEC_OID_SECG_EC_SECP128R1},
1968 { "secp128r2", SEC_OID_SECG_EC_SECP128R2},
1970 { "sect113r1", SEC_OID_SECG_EC_SECT113R1},
1971 { "sect113r2", SEC_OID_SECG_EC_SECT113R2},
1972 { "sect131r1", SEC_OID_SECG_EC_SECT131R1},
1973 { "sect131r2", SEC_OID_SECG_EC_SECT131R2},
1976 static SECKEYECParams *
1977 getECParams(const char *curve)
1979 SECKEYECParams *ecparams;
1980 SECOidData *oidData = NULL;
1981 SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
1982 int i, numCurves;
1984 if (curve != NULL) {
1985 numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair);
1986 for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN));
1987 i++) {
1988 if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
1989 curveOidTag = nameTagPair[i].curveOidTag;
1993 /* Return NULL if curve name is not recognized */
1994 if ((curveOidTag == SEC_OID_UNKNOWN) ||
1995 (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
1996 fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
1997 return NULL;
2000 ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
2003 * ecparams->data needs to contain the ASN encoding of an object ID (OID)
2004 * representing the named curve. The actual OID is in
2005 * oidData->oid.data so we simply prepend 0x06 and OID length
2007 ecparams->data[0] = SEC_ASN1_OBJECT_ID;
2008 ecparams->data[1] = oidData->oid.len;
2009 memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
2011 return ecparams;
2015 * Perform the ECDSA Key Pair Generation Test.
2017 * reqfn is the pathname of the REQUEST file.
2019 * The output RESPONSE file is written to stdout.
2021 void
2022 ecdsa_keypair_test(char *reqfn)
2024 char buf[256]; /* holds one line from the input REQUEST file
2025 * or to the output RESPONSE file.
2026 * needs to be large enough to hold the longest
2027 * line "Qx = <144 hex digits>\n".
2029 FILE *ecdsareq; /* input stream from the REQUEST file */
2030 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2031 char curve[16]; /* "nistxddd" */
2032 ECParams *ecparams;
2033 int N;
2034 int i;
2035 unsigned int len;
2037 ecdsareq = fopen(reqfn, "r");
2038 ecdsaresp = stdout;
2039 strcpy(curve, "nist");
2040 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2041 /* a comment or blank line */
2042 if (buf[0] == '#' || buf[0] == '\n') {
2043 fputs(buf, ecdsaresp);
2044 continue;
2046 /* [X-ddd] */
2047 if (buf[0] == '[') {
2048 const char *src;
2049 char *dst;
2050 SECKEYECParams *encodedparams;
2052 src = &buf[1];
2053 dst = &curve[4];
2054 *dst++ = tolower(*src);
2055 src += 2; /* skip the hyphen */
2056 *dst++ = *src++;
2057 *dst++ = *src++;
2058 *dst++ = *src++;
2059 *dst = '\0';
2060 encodedparams = getECParams(curve);
2061 if (encodedparams == NULL) {
2062 goto loser;
2064 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2065 goto loser;
2067 SECITEM_FreeItem(encodedparams, PR_TRUE);
2068 fputs(buf, ecdsaresp);
2069 continue;
2071 /* N = x */
2072 if (buf[0] == 'N') {
2073 if (sscanf(buf, "N = %d", &N) != 1) {
2074 goto loser;
2076 for (i = 0; i < N; i++) {
2077 ECPrivateKey *ecpriv;
2079 if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
2080 goto loser;
2082 fputs("d = ", ecdsaresp);
2083 to_hex_str(buf, ecpriv->privateValue.data,
2084 ecpriv->privateValue.len);
2085 fputs(buf, ecdsaresp);
2086 fputc('\n', ecdsaresp);
2087 if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
2088 != SECSuccess) {
2089 goto loser;
2091 len = ecpriv->publicValue.len;
2092 if (len%2 == 0) {
2093 goto loser;
2095 len = (len-1)/2;
2096 if (ecpriv->publicValue.data[0]
2097 != EC_POINT_FORM_UNCOMPRESSED) {
2098 goto loser;
2100 fputs("Qx = ", ecdsaresp);
2101 to_hex_str(buf, &ecpriv->publicValue.data[1], len);
2102 fputs(buf, ecdsaresp);
2103 fputc('\n', ecdsaresp);
2104 fputs("Qy = ", ecdsaresp);
2105 to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
2106 fputs(buf, ecdsaresp);
2107 fputc('\n', ecdsaresp);
2108 fputc('\n', ecdsaresp);
2109 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
2111 PORT_FreeArena(ecparams->arena, PR_FALSE);
2112 continue;
2115 loser:
2116 fclose(ecdsareq);
2120 * Perform the ECDSA Public Key Validation Test.
2122 * reqfn is the pathname of the REQUEST file.
2124 * The output RESPONSE file is written to stdout.
2126 void
2127 ecdsa_pkv_test(char *reqfn)
2129 char buf[256]; /* holds one line from the input REQUEST file.
2130 * needs to be large enough to hold the longest
2131 * line "Qx = <144 hex digits>\n".
2133 FILE *ecdsareq; /* input stream from the REQUEST file */
2134 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2135 char curve[16]; /* "nistxddd" */
2136 ECParams *ecparams = NULL;
2137 SECItem pubkey;
2138 unsigned int i;
2139 unsigned int len;
2140 PRBool keyvalid = PR_TRUE;
2142 ecdsareq = fopen(reqfn, "r");
2143 ecdsaresp = stdout;
2144 strcpy(curve, "nist");
2145 pubkey.data = NULL;
2146 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2147 /* a comment or blank line */
2148 if (buf[0] == '#' || buf[0] == '\n') {
2149 fputs(buf, ecdsaresp);
2150 continue;
2152 /* [X-ddd] */
2153 if (buf[0] == '[') {
2154 const char *src;
2155 char *dst;
2156 SECKEYECParams *encodedparams;
2158 src = &buf[1];
2159 dst = &curve[4];
2160 *dst++ = tolower(*src);
2161 src += 2; /* skip the hyphen */
2162 *dst++ = *src++;
2163 *dst++ = *src++;
2164 *dst++ = *src++;
2165 *dst = '\0';
2166 if (ecparams != NULL) {
2167 PORT_FreeArena(ecparams->arena, PR_FALSE);
2168 ecparams = NULL;
2170 encodedparams = getECParams(curve);
2171 if (encodedparams == NULL) {
2172 goto loser;
2174 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2175 goto loser;
2177 SECITEM_FreeItem(encodedparams, PR_TRUE);
2178 len = (ecparams->fieldID.size + 7) >> 3;
2179 if (pubkey.data != NULL) {
2180 PORT_Free(pubkey.data);
2181 pubkey.data = NULL;
2183 SECITEM_AllocItem(NULL, &pubkey, 2*len+1);
2184 if (pubkey.data == NULL) {
2185 goto loser;
2187 pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
2188 fputs(buf, ecdsaresp);
2189 continue;
2191 /* Qx = ... */
2192 if (strncmp(buf, "Qx", 2) == 0) {
2193 fputs(buf, ecdsaresp);
2194 i = 2;
2195 while (isspace(buf[i]) || buf[i] == '=') {
2196 i++;
2198 keyvalid = from_hex_str(&pubkey.data[1], len, &buf[i]);
2199 continue;
2201 /* Qy = ... */
2202 if (strncmp(buf, "Qy", 2) == 0) {
2203 fputs(buf, ecdsaresp);
2204 if (!keyvalid) {
2205 fputs("Result = F\n", ecdsaresp);
2206 continue;
2208 i = 2;
2209 while (isspace(buf[i]) || buf[i] == '=') {
2210 i++;
2212 keyvalid = from_hex_str(&pubkey.data[1+len], len, &buf[i]);
2213 if (!keyvalid) {
2214 fputs("Result = F\n", ecdsaresp);
2215 continue;
2217 if (EC_ValidatePublicKey(ecparams, &pubkey) == SECSuccess) {
2218 fputs("Result = P\n", ecdsaresp);
2219 } else if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
2220 fputs("Result = F\n", ecdsaresp);
2221 } else {
2222 goto loser;
2224 continue;
2227 loser:
2228 if (ecparams != NULL) {
2229 PORT_FreeArena(ecparams->arena, PR_FALSE);
2231 if (pubkey.data != NULL) {
2232 PORT_Free(pubkey.data);
2234 fclose(ecdsareq);
2238 * Perform the ECDSA Signature Generation Test.
2240 * reqfn is the pathname of the REQUEST file.
2242 * The output RESPONSE file is written to stdout.
2244 void
2245 ecdsa_siggen_test(char *reqfn)
2247 char buf[1024]; /* holds one line from the input REQUEST file
2248 * or to the output RESPONSE file.
2249 * needs to be large enough to hold the longest
2250 * line "Msg = <256 hex digits>\n".
2252 FILE *ecdsareq; /* input stream from the REQUEST file */
2253 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2254 char curve[16]; /* "nistxddd" */
2255 ECParams *ecparams = NULL;
2256 int i, j;
2257 unsigned int len;
2258 unsigned char msg[512]; /* message to be signed (<= 128 bytes) */
2259 unsigned int msglen;
2260 unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
2261 unsigned char sig[2*MAX_ECKEY_LEN];
2262 SECItem signature, digest;
2264 ecdsareq = fopen(reqfn, "r");
2265 ecdsaresp = stdout;
2266 strcpy(curve, "nist");
2267 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2268 /* a comment or blank line */
2269 if (buf[0] == '#' || buf[0] == '\n') {
2270 fputs(buf, ecdsaresp);
2271 continue;
2273 /* [X-ddd] */
2274 if (buf[0] == '[') {
2275 const char *src;
2276 char *dst;
2277 SECKEYECParams *encodedparams;
2279 src = &buf[1];
2280 dst = &curve[4];
2281 *dst++ = tolower(*src);
2282 src += 2; /* skip the hyphen */
2283 *dst++ = *src++;
2284 *dst++ = *src++;
2285 *dst++ = *src++;
2286 *dst = '\0';
2287 if (ecparams != NULL) {
2288 PORT_FreeArena(ecparams->arena, PR_FALSE);
2289 ecparams = NULL;
2291 encodedparams = getECParams(curve);
2292 if (encodedparams == NULL) {
2293 goto loser;
2295 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2296 goto loser;
2298 SECITEM_FreeItem(encodedparams, PR_TRUE);
2299 fputs(buf, ecdsaresp);
2300 continue;
2302 /* Msg = ... */
2303 if (strncmp(buf, "Msg", 3) == 0) {
2304 ECPrivateKey *ecpriv;
2306 i = 3;
2307 while (isspace(buf[i]) || buf[i] == '=') {
2308 i++;
2310 for (j=0; isxdigit(buf[i]); i+=2,j++) {
2311 hex_to_byteval(&buf[i], &msg[j]);
2313 msglen = j;
2314 if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
2315 goto loser;
2317 fputs(buf, ecdsaresp);
2319 if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
2320 goto loser;
2322 if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
2323 != SECSuccess) {
2324 goto loser;
2326 len = ecpriv->publicValue.len;
2327 if (len%2 == 0) {
2328 goto loser;
2330 len = (len-1)/2;
2331 if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
2332 goto loser;
2334 fputs("Qx = ", ecdsaresp);
2335 to_hex_str(buf, &ecpriv->publicValue.data[1], len);
2336 fputs(buf, ecdsaresp);
2337 fputc('\n', ecdsaresp);
2338 fputs("Qy = ", ecdsaresp);
2339 to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
2340 fputs(buf, ecdsaresp);
2341 fputc('\n', ecdsaresp);
2343 digest.type = siBuffer;
2344 digest.data = sha1;
2345 digest.len = sizeof sha1;
2346 signature.type = siBuffer;
2347 signature.data = sig;
2348 signature.len = sizeof sig;
2349 if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) {
2350 goto loser;
2352 len = signature.len;
2353 if (len%2 != 0) {
2354 goto loser;
2356 len = len/2;
2357 fputs("R = ", ecdsaresp);
2358 to_hex_str(buf, &signature.data[0], len);
2359 fputs(buf, ecdsaresp);
2360 fputc('\n', ecdsaresp);
2361 fputs("S = ", ecdsaresp);
2362 to_hex_str(buf, &signature.data[len], len);
2363 fputs(buf, ecdsaresp);
2364 fputc('\n', ecdsaresp);
2366 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
2367 continue;
2370 loser:
2371 if (ecparams != NULL) {
2372 PORT_FreeArena(ecparams->arena, PR_FALSE);
2374 fclose(ecdsareq);
2378 * Perform the ECDSA Signature Verification Test.
2380 * reqfn is the pathname of the REQUEST file.
2382 * The output RESPONSE file is written to stdout.
2384 void
2385 ecdsa_sigver_test(char *reqfn)
2387 char buf[1024]; /* holds one line from the input REQUEST file.
2388 * needs to be large enough to hold the longest
2389 * line "Msg = <256 hex digits>\n".
2391 FILE *ecdsareq; /* input stream from the REQUEST file */
2392 FILE *ecdsaresp; /* output stream to the RESPONSE file */
2393 char curve[16]; /* "nistxddd" */
2394 ECPublicKey ecpub;
2395 unsigned int i, j;
2396 unsigned int flen; /* length in bytes of the field size */
2397 unsigned int olen; /* length in bytes of the base point order */
2398 unsigned char msg[512]; /* message that was signed (<= 128 bytes) */
2399 unsigned int msglen;
2400 unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
2401 unsigned char sig[2*MAX_ECKEY_LEN];
2402 SECItem signature, digest;
2403 PRBool keyvalid = PR_TRUE;
2404 PRBool sigvalid = PR_TRUE;
2406 ecdsareq = fopen(reqfn, "r");
2407 ecdsaresp = stdout;
2408 ecpub.ecParams.arena = NULL;
2409 strcpy(curve, "nist");
2410 while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2411 /* a comment or blank line */
2412 if (buf[0] == '#' || buf[0] == '\n') {
2413 fputs(buf, ecdsaresp);
2414 continue;
2416 /* [X-ddd] */
2417 if (buf[0] == '[') {
2418 const char *src;
2419 char *dst;
2420 SECKEYECParams *encodedparams;
2421 ECParams *ecparams;
2423 src = &buf[1];
2424 dst = &curve[4];
2425 *dst++ = tolower(*src);
2426 src += 2; /* skip the hyphen */
2427 *dst++ = *src++;
2428 *dst++ = *src++;
2429 *dst++ = *src++;
2430 *dst = '\0';
2431 encodedparams = getECParams(curve);
2432 if (encodedparams == NULL) {
2433 goto loser;
2435 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2436 goto loser;
2438 SECITEM_FreeItem(encodedparams, PR_TRUE);
2439 if (ecpub.ecParams.arena != NULL) {
2440 PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
2442 ecpub.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2443 if (ecpub.ecParams.arena == NULL) {
2444 goto loser;
2446 if (EC_CopyParams(ecpub.ecParams.arena, &ecpub.ecParams, ecparams)
2447 != SECSuccess) {
2448 goto loser;
2450 PORT_FreeArena(ecparams->arena, PR_FALSE);
2451 flen = (ecpub.ecParams.fieldID.size + 7) >> 3;
2452 olen = ecpub.ecParams.order.len;
2453 if (2*olen > sizeof sig) {
2454 goto loser;
2456 ecpub.publicValue.type = siBuffer;
2457 ecpub.publicValue.data = NULL;
2458 ecpub.publicValue.len = 0;
2459 SECITEM_AllocItem(ecpub.ecParams.arena,
2460 &ecpub.publicValue, 2*flen+1);
2461 if (ecpub.publicValue.data == NULL) {
2462 goto loser;
2464 ecpub.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED;
2465 fputs(buf, ecdsaresp);
2466 continue;
2468 /* Msg = ... */
2469 if (strncmp(buf, "Msg", 3) == 0) {
2470 i = 3;
2471 while (isspace(buf[i]) || buf[i] == '=') {
2472 i++;
2474 for (j=0; isxdigit(buf[i]); i+=2,j++) {
2475 hex_to_byteval(&buf[i], &msg[j]);
2477 msglen = j;
2478 if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
2479 goto loser;
2481 fputs(buf, ecdsaresp);
2483 digest.type = siBuffer;
2484 digest.data = sha1;
2485 digest.len = sizeof sha1;
2487 continue;
2489 /* Qx = ... */
2490 if (strncmp(buf, "Qx", 2) == 0) {
2491 fputs(buf, ecdsaresp);
2492 i = 2;
2493 while (isspace(buf[i]) || buf[i] == '=') {
2494 i++;
2496 keyvalid = from_hex_str(&ecpub.publicValue.data[1], flen,
2497 &buf[i]);
2498 continue;
2500 /* Qy = ... */
2501 if (strncmp(buf, "Qy", 2) == 0) {
2502 fputs(buf, ecdsaresp);
2503 if (!keyvalid) {
2504 continue;
2506 i = 2;
2507 while (isspace(buf[i]) || buf[i] == '=') {
2508 i++;
2510 keyvalid = from_hex_str(&ecpub.publicValue.data[1+flen], flen,
2511 &buf[i]);
2512 if (!keyvalid) {
2513 continue;
2515 if (EC_ValidatePublicKey(&ecpub.ecParams, &ecpub.publicValue)
2516 != SECSuccess) {
2517 if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
2518 keyvalid = PR_FALSE;
2519 } else {
2520 goto loser;
2523 continue;
2525 /* R = ... */
2526 if (buf[0] == 'R') {
2527 fputs(buf, ecdsaresp);
2528 i = 1;
2529 while (isspace(buf[i]) || buf[i] == '=') {
2530 i++;
2532 sigvalid = from_hex_str(sig, olen, &buf[i]);
2533 continue;
2535 /* S = ... */
2536 if (buf[0] == 'S') {
2537 fputs(buf, ecdsaresp);
2538 i = 1;
2539 while (isspace(buf[i]) || buf[i] == '=') {
2540 i++;
2542 if (sigvalid) {
2543 sigvalid = from_hex_str(&sig[olen], olen, &buf[i]);
2545 signature.type = siBuffer;
2546 signature.data = sig;
2547 signature.len = 2*olen;
2549 if (!keyvalid || !sigvalid) {
2550 fputs("Result = F\n", ecdsaresp);
2551 } else if (ECDSA_VerifyDigest(&ecpub, &signature, &digest)
2552 == SECSuccess) {
2553 fputs("Result = P\n", ecdsaresp);
2554 } else {
2555 fputs("Result = F\n", ecdsaresp);
2557 continue;
2560 loser:
2561 if (ecpub.ecParams.arena != NULL) {
2562 PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
2564 fclose(ecdsareq);
2566 #endif /* NSS_ENABLE_ECC */
2569 * Perform the RNG Variable Seed Test (VST) for the RNG algorithm
2570 * "DSA - Generation of X", used both as specified and as a generic
2571 * purpose RNG. The presence of "Q = ..." in the REQUEST file
2572 * indicates we are using the algorithm as specified.
2574 * reqfn is the pathname of the REQUEST file.
2576 * The output RESPONSE file is written to stdout.
2578 void
2579 rng_vst(char *reqfn)
2581 char buf[256]; /* holds one line from the input REQUEST file.
2582 * needs to be large enough to hold the longest
2583 * line "XSeed = <128 hex digits>\n".
2585 FILE *rngreq; /* input stream from the REQUEST file */
2586 FILE *rngresp; /* output stream to the RESPONSE file */
2587 unsigned int i, j;
2588 unsigned char Q[DSA_SUBPRIME_LEN];
2589 PRBool hasQ = PR_FALSE;
2590 unsigned int b; /* 160 <= b <= 512, b is a multiple of 8 */
2591 unsigned char XKey[512/8];
2592 unsigned char XSeed[512/8];
2593 unsigned char GENX[2*SHA1_LENGTH];
2594 unsigned char DSAX[DSA_SUBPRIME_LEN];
2595 SECStatus rv;
2597 rngreq = fopen(reqfn, "r");
2598 rngresp = stdout;
2599 while (fgets(buf, sizeof buf, rngreq) != NULL) {
2600 /* a comment or blank line */
2601 if (buf[0] == '#' || buf[0] == '\n') {
2602 fputs(buf, rngresp);
2603 continue;
2605 /* [Xchange - SHA1] */
2606 if (buf[0] == '[') {
2607 fputs(buf, rngresp);
2608 continue;
2610 /* Q = ... */
2611 if (buf[0] == 'Q') {
2612 i = 1;
2613 while (isspace(buf[i]) || buf[i] == '=') {
2614 i++;
2616 for (j=0; j<sizeof Q; i+=2,j++) {
2617 hex_to_byteval(&buf[i], &Q[j]);
2619 fputs(buf, rngresp);
2620 hasQ = PR_TRUE;
2621 continue;
2623 /* "COUNT = x" begins a new data set */
2624 if (strncmp(buf, "COUNT", 5) == 0) {
2625 /* zeroize the variables for the test with this data set */
2626 b = 0;
2627 memset(XKey, 0, sizeof XKey);
2628 memset(XSeed, 0, sizeof XSeed);
2629 fputs(buf, rngresp);
2630 continue;
2632 /* b = ... */
2633 if (buf[0] == 'b') {
2634 i = 1;
2635 while (isspace(buf[i]) || buf[i] == '=') {
2636 i++;
2638 b = atoi(&buf[i]);
2639 if (b < 160 || b > 512 || b%8 != 0) {
2640 goto loser;
2642 fputs(buf, rngresp);
2643 continue;
2645 /* XKey = ... */
2646 if (strncmp(buf, "XKey", 4) == 0) {
2647 i = 4;
2648 while (isspace(buf[i]) || buf[i] == '=') {
2649 i++;
2651 for (j=0; j<b/8; i+=2,j++) {
2652 hex_to_byteval(&buf[i], &XKey[j]);
2654 fputs(buf, rngresp);
2655 continue;
2657 /* XSeed = ... */
2658 if (strncmp(buf, "XSeed", 5) == 0) {
2659 i = 5;
2660 while (isspace(buf[i]) || buf[i] == '=') {
2661 i++;
2663 for (j=0; j<b/8; i+=2,j++) {
2664 hex_to_byteval(&buf[i], &XSeed[j]);
2666 fputs(buf, rngresp);
2668 rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
2669 if (rv != SECSuccess) {
2670 goto loser;
2672 fputs("X = ", rngresp);
2673 if (hasQ) {
2674 rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
2675 if (rv != SECSuccess) {
2676 goto loser;
2678 to_hex_str(buf, DSAX, sizeof DSAX);
2679 } else {
2680 to_hex_str(buf, GENX, sizeof GENX);
2682 fputs(buf, rngresp);
2683 fputc('\n', rngresp);
2684 continue;
2687 loser:
2688 fclose(rngreq);
2692 * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm
2693 * "DSA - Generation of X", used both as specified and as a generic
2694 * purpose RNG. The presence of "Q = ..." in the REQUEST file
2695 * indicates we are using the algorithm as specified.
2697 * reqfn is the pathname of the REQUEST file.
2699 * The output RESPONSE file is written to stdout.
2701 void
2702 rng_mct(char *reqfn)
2704 char buf[256]; /* holds one line from the input REQUEST file.
2705 * needs to be large enough to hold the longest
2706 * line "XSeed = <128 hex digits>\n".
2708 FILE *rngreq; /* input stream from the REQUEST file */
2709 FILE *rngresp; /* output stream to the RESPONSE file */
2710 unsigned int i, j;
2711 unsigned char Q[DSA_SUBPRIME_LEN];
2712 PRBool hasQ = PR_FALSE;
2713 unsigned int b; /* 160 <= b <= 512, b is a multiple of 8 */
2714 unsigned char XKey[512/8];
2715 unsigned char XSeed[512/8];
2716 unsigned char GENX[2*SHA1_LENGTH];
2717 unsigned char DSAX[DSA_SUBPRIME_LEN];
2718 SECStatus rv;
2720 rngreq = fopen(reqfn, "r");
2721 rngresp = stdout;
2722 while (fgets(buf, sizeof buf, rngreq) != NULL) {
2723 /* a comment or blank line */
2724 if (buf[0] == '#' || buf[0] == '\n') {
2725 fputs(buf, rngresp);
2726 continue;
2728 /* [Xchange - SHA1] */
2729 if (buf[0] == '[') {
2730 fputs(buf, rngresp);
2731 continue;
2733 /* Q = ... */
2734 if (buf[0] == 'Q') {
2735 i = 1;
2736 while (isspace(buf[i]) || buf[i] == '=') {
2737 i++;
2739 for (j=0; j<sizeof Q; i+=2,j++) {
2740 hex_to_byteval(&buf[i], &Q[j]);
2742 fputs(buf, rngresp);
2743 hasQ = PR_TRUE;
2744 continue;
2746 /* "COUNT = x" begins a new data set */
2747 if (strncmp(buf, "COUNT", 5) == 0) {
2748 /* zeroize the variables for the test with this data set */
2749 b = 0;
2750 memset(XKey, 0, sizeof XKey);
2751 memset(XSeed, 0, sizeof XSeed);
2752 fputs(buf, rngresp);
2753 continue;
2755 /* b = ... */
2756 if (buf[0] == 'b') {
2757 i = 1;
2758 while (isspace(buf[i]) || buf[i] == '=') {
2759 i++;
2761 b = atoi(&buf[i]);
2762 if (b < 160 || b > 512 || b%8 != 0) {
2763 goto loser;
2765 fputs(buf, rngresp);
2766 continue;
2768 /* XKey = ... */
2769 if (strncmp(buf, "XKey", 4) == 0) {
2770 i = 4;
2771 while (isspace(buf[i]) || buf[i] == '=') {
2772 i++;
2774 for (j=0; j<b/8; i+=2,j++) {
2775 hex_to_byteval(&buf[i], &XKey[j]);
2777 fputs(buf, rngresp);
2778 continue;
2780 /* XSeed = ... */
2781 if (strncmp(buf, "XSeed", 5) == 0) {
2782 unsigned int k;
2783 i = 5;
2784 while (isspace(buf[i]) || buf[i] == '=') {
2785 i++;
2787 for (j=0; j<b/8; i+=2,j++) {
2788 hex_to_byteval(&buf[i], &XSeed[j]);
2790 fputs(buf, rngresp);
2792 for (k = 0; k < 10000; k++) {
2793 rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
2794 if (rv != SECSuccess) {
2795 goto loser;
2798 fputs("X = ", rngresp);
2799 if (hasQ) {
2800 rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
2801 if (rv != SECSuccess) {
2802 goto loser;
2804 to_hex_str(buf, DSAX, sizeof DSAX);
2805 } else {
2806 to_hex_str(buf, GENX, sizeof GENX);
2808 fputs(buf, rngresp);
2809 fputc('\n', rngresp);
2810 continue;
2813 loser:
2814 fclose(rngreq);
2818 * Calculate the SHA Message Digest
2820 * MD = Message digest
2821 * MDLen = length of Message Digest and SHA_Type
2822 * msg = message to digest
2823 * msgLen = length of message to digest
2825 SECStatus sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen)
2827 SECStatus sha_status = SECFailure;
2829 if (MDLen == SHA1_LENGTH) {
2830 sha_status = SHA1_HashBuf(MD, msg, msgLen);
2831 } else if (MDLen == SHA256_LENGTH) {
2832 sha_status = SHA256_HashBuf(MD, msg, msgLen);
2833 } else if (MDLen == SHA384_LENGTH) {
2834 sha_status = SHA384_HashBuf(MD, msg, msgLen);
2835 } else if (MDLen == SHA512_LENGTH) {
2836 sha_status = SHA512_HashBuf(MD, msg, msgLen);
2839 return sha_status;
2843 * Perform the SHA Monte Carlo Test
2845 * MDLen = length of Message Digest and SHA_Type
2846 * seed = input seed value
2847 * resp = is the output response file.
2849 SECStatus sha_mct_test(unsigned int MDLen, unsigned char *seed, FILE *resp)
2851 int i, j;
2852 unsigned int msgLen = MDLen*3;
2853 unsigned char MD_i3[HASH_LENGTH_MAX]; /* MD[i-3] */
2854 unsigned char MD_i2[HASH_LENGTH_MAX]; /* MD[i-2] */
2855 unsigned char MD_i1[HASH_LENGTH_MAX]; /* MD[i-1] */
2856 unsigned char MD_i[HASH_LENGTH_MAX]; /* MD[i] */
2857 unsigned char msg[HASH_LENGTH_MAX*3];
2858 char buf[HASH_LENGTH_MAX*2 + 1]; /* MAX buf MD_i as a hex string */
2860 for (j=0; j<100; j++) {
2861 /* MD_0 = MD_1 = MD_2 = seed */
2862 memcpy(MD_i3, seed, MDLen);
2863 memcpy(MD_i2, seed, MDLen);
2864 memcpy(MD_i1, seed, MDLen);
2866 for (i=3; i < 1003; i++) {
2867 /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */
2868 memcpy(msg, MD_i3, MDLen);
2869 memcpy(&msg[MDLen], MD_i2, MDLen);
2870 memcpy(&msg[MDLen*2], MD_i1,MDLen);
2872 /* MDi = SHA(Msg) */
2873 if (sha_calcMD(MD_i, MDLen,
2874 msg, msgLen) != SECSuccess) {
2875 return SECFailure;
2878 /* save MD[i-3] MD[i-2] MD[i-1] */
2879 memcpy(MD_i3, MD_i2, MDLen);
2880 memcpy(MD_i2, MD_i1, MDLen);
2881 memcpy(MD_i1, MD_i, MDLen);
2885 /* seed = MD_i */
2886 memcpy(seed, MD_i, MDLen);
2888 sprintf(buf, "COUNT = %d\n", j);
2889 fputs(buf, resp);
2891 /* output MD_i */
2892 fputs("MD = ", resp);
2893 to_hex_str(buf, MD_i, MDLen);
2894 fputs(buf, resp);
2895 fputc('\n', resp);
2898 return SECSuccess;
2902 * Perform the SHA Tests.
2904 * reqfn is the pathname of the input REQUEST file.
2906 * The output RESPONSE file is written to stdout.
2908 void sha_test(char *reqfn)
2910 unsigned int i, j;
2911 unsigned int MDlen; /* the length of the Message Digest in Bytes */
2912 unsigned int msgLen; /* the length of the input Message in Bytes */
2913 unsigned char *msg = NULL; /* holds the message to digest.*/
2914 size_t bufSize = 25608; /*MAX buffer size */
2915 char *buf = NULL; /* holds one line from the input REQUEST file.*/
2916 unsigned char seed[HASH_LENGTH_MAX]; /* max size of seed 64 bytes */
2917 unsigned char MD[HASH_LENGTH_MAX]; /* message digest */
2919 FILE *req = NULL; /* input stream from the REQUEST file */
2920 FILE *resp; /* output stream to the RESPONSE file */
2922 buf = PORT_ZAlloc(bufSize);
2923 if (buf == NULL) {
2924 goto loser;
2927 /* zeroize the variables for the test with this data set */
2928 memset(seed, 0, sizeof seed);
2930 req = fopen(reqfn, "r");
2931 resp = stdout;
2932 while (fgets(buf, bufSize, req) != NULL) {
2934 /* a comment or blank line */
2935 if (buf[0] == '#' || buf[0] == '\n') {
2936 fputs(buf, resp);
2937 continue;
2939 /* [L = Length of the Message Digest and sha_type */
2940 if (buf[0] == '[') {
2941 if (strncmp(&buf[1], "L ", 1) == 0) {
2942 i = 2;
2943 while (isspace(buf[i]) || buf[i] == '=') {
2944 i++;
2946 MDlen = atoi(&buf[i]);
2947 fputs(buf, resp);
2948 continue;
2951 /* Len = Length of the Input Message Length ... */
2952 if (strncmp(buf, "Len", 3) == 0) {
2953 i = 3;
2954 while (isspace(buf[i]) || buf[i] == '=') {
2955 i++;
2957 if (msg) {
2958 PORT_ZFree(msg,msgLen);
2959 msg = NULL;
2961 msgLen = atoi(&buf[i]); /* in bits */
2962 if (msgLen%8 != 0) {
2963 fprintf(stderr, "SHA tests are incorrectly configured for "
2964 "BIT oriented implementations\n");
2965 goto loser;
2967 msgLen = msgLen/8; /* convert to bytes */
2968 fputs(buf, resp);
2969 msg = PORT_ZAlloc(msgLen);
2970 if (msg == NULL && msgLen != 0) {
2971 goto loser;
2973 continue;
2975 /* MSG = ... */
2976 if (strncmp(buf, "Msg", 3) == 0) {
2977 i = 3;
2978 while (isspace(buf[i]) || buf[i] == '=') {
2979 i++;
2981 for (j=0; j< msgLen; i+=2,j++) {
2982 hex_to_byteval(&buf[i], &msg[j]);
2984 fputs(buf, resp);
2985 /* calculate the Message Digest */
2986 memset(MD, 0, sizeof MD);
2987 if (sha_calcMD(MD, MDlen,
2988 msg, msgLen) != SECSuccess) {
2989 goto loser;
2992 fputs("MD = ", resp);
2993 to_hex_str(buf, MD, MDlen);
2994 fputs(buf, resp);
2995 fputc('\n', resp);
2997 continue;
2999 /* Seed = ... */
3000 if (strncmp(buf, "Seed", 4) == 0) {
3001 i = 4;
3002 while (isspace(buf[i]) || buf[i] == '=') {
3003 i++;
3005 for (j=0; j<sizeof seed; i+=2,j++) {
3006 hex_to_byteval(&buf[i], &seed[j]);
3009 fputs(buf, resp);
3010 fputc('\n', resp);
3012 /* do the Monte Carlo test */
3013 if (sha_mct_test(MDlen, seed, resp) != SECSuccess) {
3014 goto loser;
3017 continue;
3020 loser:
3021 if (req) {
3022 fclose(req);
3024 if (buf) {
3025 PORT_ZFree(buf, bufSize);
3027 if (msg) {
3028 PORT_ZFree(msg, msgLen);
3032 /****************************************************/
3033 /* HMAC SHA-X calc */
3034 /* hmac_computed - the computed HMAC */
3035 /* hmac_length - the length of the computed HMAC */
3036 /* secret_key - secret key to HMAC */
3037 /* secret_key_length - length of secret key, */
3038 /* message - message to HMAC */
3039 /* message_length - length ofthe message */
3040 /****************************************************/
3041 static SECStatus
3042 hmac_calc(unsigned char *hmac_computed,
3043 const unsigned int hmac_length,
3044 const unsigned char *secret_key,
3045 const unsigned int secret_key_length,
3046 const unsigned char *message,
3047 const unsigned int message_length,
3048 const HASH_HashType hashAlg )
3050 SECStatus hmac_status = SECFailure;
3051 HMACContext *cx = NULL;
3052 SECHashObject *hashObj = NULL;
3053 unsigned int bytes_hashed = 0;
3055 hashObj = (SECHashObject *) HASH_GetRawHashObject(hashAlg);
3057 if (!hashObj)
3058 return( SECFailure );
3060 cx = HMAC_Create(hashObj, secret_key,
3061 secret_key_length,
3062 PR_TRUE); /* PR_TRUE for in FIPS mode */
3064 if (cx == NULL)
3065 return( SECFailure );
3067 HMAC_Begin(cx);
3068 HMAC_Update(cx, message, message_length);
3069 hmac_status = HMAC_Finish(cx, hmac_computed, &bytes_hashed,
3070 hmac_length);
3072 HMAC_Destroy(cx, PR_TRUE);
3074 return( hmac_status );
3078 * Perform the HMAC Tests.
3080 * reqfn is the pathname of the input REQUEST file.
3082 * The output RESPONSE file is written to stdout.
3084 void hmac_test(char *reqfn)
3086 unsigned int i, j;
3087 size_t bufSize = 288; /* MAX buffer size */
3088 char *buf = NULL; /* holds one line from the input REQUEST file.*/
3089 unsigned int keyLen; /* Key Length */
3090 unsigned char key[140]; /* key MAX size = 140 */
3091 unsigned int msgLen = 128; /* the length of the input */
3092 /* Message is always 128 Bytes */
3093 unsigned char *msg = NULL; /* holds the message to digest.*/
3094 unsigned int HMACLen; /* the length of the HMAC Bytes */
3095 unsigned char HMAC[HASH_LENGTH_MAX]; /* computed HMAC */
3096 HASH_HashType hash_alg; /* HMAC type */
3098 FILE *req = NULL; /* input stream from the REQUEST file */
3099 FILE *resp; /* output stream to the RESPONSE file */
3101 buf = PORT_ZAlloc(bufSize);
3102 if (buf == NULL) {
3103 goto loser;
3105 msg = PORT_ZAlloc(msgLen);
3106 memset(msg, 0, msgLen);
3107 if (msg == NULL) {
3108 goto loser;
3111 req = fopen(reqfn, "r");
3112 resp = stdout;
3113 while (fgets(buf, bufSize, req) != NULL) {
3115 /* a comment or blank line */
3116 if (buf[0] == '#' || buf[0] == '\n') {
3117 fputs(buf, resp);
3118 continue;
3120 /* [L = Length of the MAC and HASH_type */
3121 if (buf[0] == '[') {
3122 if (strncmp(&buf[1], "L ", 1) == 0) {
3123 i = 2;
3124 while (isspace(buf[i]) || buf[i] == '=') {
3125 i++;
3127 /* HMACLen will get reused for Tlen */
3128 HMACLen = atoi(&buf[i]);
3129 /* set the HASH algorithm for HMAC */
3130 if (HMACLen == SHA1_LENGTH) {
3131 hash_alg = HASH_AlgSHA1;
3132 } else if (HMACLen == SHA256_LENGTH) {
3133 hash_alg = HASH_AlgSHA256;
3134 } else if (HMACLen == SHA384_LENGTH) {
3135 hash_alg = HASH_AlgSHA384;
3136 } else if (HMACLen == SHA512_LENGTH) {
3137 hash_alg = HASH_AlgSHA512;
3138 } else {
3139 goto loser;
3141 fputs(buf, resp);
3142 continue;
3145 /* Count = test iteration number*/
3146 if (strncmp(buf, "Count ", 5) == 0) {
3147 /* count can just be put into resp file */
3148 fputs(buf, resp);
3149 /* zeroize the variables for the test with this data set */
3150 keyLen = 0;
3151 HMACLen = 0;
3152 memset(key, 0, sizeof key);
3153 memset(msg, 0, sizeof msg);
3154 memset(HMAC, 0, sizeof HMAC);
3155 continue;
3157 /* KLen = Length of the Input Secret Key ... */
3158 if (strncmp(buf, "Klen", 4) == 0) {
3159 i = 4;
3160 while (isspace(buf[i]) || buf[i] == '=') {
3161 i++;
3163 keyLen = atoi(&buf[i]); /* in bytes */
3164 fputs(buf, resp);
3165 continue;
3167 /* key = the secret key for the key to MAC */
3168 if (strncmp(buf, "Key", 3) == 0) {
3169 i = 3;
3170 while (isspace(buf[i]) || buf[i] == '=') {
3171 i++;
3173 for (j=0; j< keyLen; i+=2,j++) {
3174 hex_to_byteval(&buf[i], &key[j]);
3176 fputs(buf, resp);
3178 /* TLen = Length of the calculated HMAC */
3179 if (strncmp(buf, "Tlen", 4) == 0) {
3180 i = 4;
3181 while (isspace(buf[i]) || buf[i] == '=') {
3182 i++;
3184 HMACLen = atoi(&buf[i]); /* in bytes */
3185 fputs(buf, resp);
3186 continue;
3188 /* MSG = to HMAC always 128 bytes for these tests */
3189 if (strncmp(buf, "Msg", 3) == 0) {
3190 i = 3;
3191 while (isspace(buf[i]) || buf[i] == '=') {
3192 i++;
3194 for (j=0; j< msgLen; i+=2,j++) {
3195 hex_to_byteval(&buf[i], &msg[j]);
3197 fputs(buf, resp);
3198 /* calculate the HMAC and output */
3199 if (hmac_calc(HMAC, HMACLen, key, keyLen,
3200 msg, msgLen, hash_alg) != SECSuccess) {
3201 goto loser;
3203 fputs("MAC = ", resp);
3204 to_hex_str(buf, HMAC, HMACLen);
3205 fputs(buf, resp);
3206 fputc('\n', resp);
3207 continue;
3210 loser:
3211 if (req) {
3212 fclose(req);
3214 if (buf) {
3215 PORT_ZFree(buf, bufSize);
3217 if (msg) {
3218 PORT_ZFree(msg, msgLen);
3223 * Perform the DSA Key Pair Generation Test.
3225 * reqfn is the pathname of the REQUEST file.
3227 * The output RESPONSE file is written to stdout.
3229 void
3230 dsa_keypair_test(char *reqfn)
3232 char buf[260]; /* holds one line from the input REQUEST file
3233 * or to the output RESPONSE file.
3234 * 257 to hold (128 public key (x2 for HEX) + 1'\n'
3236 FILE *dsareq; /* input stream from the REQUEST file */
3237 FILE *dsaresp; /* output stream to the RESPONSE file */
3238 int N; /* number of time to generate key pair */
3239 int modulus;
3240 int i;
3241 PQGParams *pqg = NULL;
3242 PQGVerify *vfy = NULL;
3243 int keySizeIndex; /* index for valid key sizes */
3245 dsareq = fopen(reqfn, "r");
3246 dsaresp = stdout;
3247 while (fgets(buf, sizeof buf, dsareq) != NULL) {
3248 /* a comment or blank line */
3249 if (buf[0] == '#' || buf[0] == '\n') {
3250 fputs(buf, dsaresp);
3251 continue;
3254 /* [Mod = x] */
3255 if (buf[0] == '[') {
3256 if(pqg!=NULL) {
3257 PQG_DestroyParams(pqg);
3258 pqg = NULL;
3260 if(vfy!=NULL) {
3261 PQG_DestroyVerify(vfy);
3262 vfy = NULL;
3265 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
3266 goto loser;
3268 fputs(buf, dsaresp);
3269 fputc('\n', dsaresp);
3271 /*****************************************************************
3272 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
3273 * that points to a valid key size.
3275 keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
3276 if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
3277 fprintf(dsaresp,
3278 "DSA key size must be a multiple of 64 between 512 "
3279 "and 1024, inclusive");
3280 goto loser;
3283 /* Generate the parameters P, Q, and G */
3284 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
3285 &pqg, &vfy) != SECSuccess) {
3286 fprintf(dsaresp, "ERROR: Unable to generate PQG parameters");
3287 goto loser;
3290 /* output P, Q, and G */
3291 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
3292 fprintf(dsaresp, "P = %s\n", buf);
3293 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
3294 fprintf(dsaresp, "Q = %s\n", buf);
3295 to_hex_str(buf, pqg->base.data, pqg->base.len);
3296 fprintf(dsaresp, "G = %s\n\n", buf);
3297 continue;
3299 /* N = ...*/
3300 if (buf[0] == 'N') {
3302 if (sscanf(buf, "N = %d", &N) != 1) {
3303 goto loser;
3305 /* Generate a DSA key, and output the key pair for N times */
3306 for (i = 0; i < N; i++) {
3307 DSAPrivateKey *dsakey = NULL;
3308 if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
3309 fprintf(dsaresp, "ERROR: Unable to generate DSA key");
3310 goto loser;
3312 to_hex_str(buf, dsakey->privateValue.data,
3313 dsakey->privateValue.len);
3314 fprintf(dsaresp, "X = %s\n", buf);
3315 to_hex_str(buf, dsakey->publicValue.data,
3316 dsakey->publicValue.len);
3317 fprintf(dsaresp, "Y = %s\n\n", buf);
3318 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
3319 dsakey = NULL;
3321 continue;
3325 loser:
3326 fclose(dsareq);
3330 * Perform the DSA Domain Parameter Validation Test.
3332 * reqfn is the pathname of the REQUEST file.
3334 * The output RESPONSE file is written to stdout.
3336 void
3337 dsa_pqgver_test(char *reqfn)
3339 char buf[263]; /* holds one line from the input REQUEST file
3340 * or to the output RESPONSE file.
3341 * 260 to hold (128 public key (x2 for HEX) + P = ...
3343 FILE *dsareq; /* input stream from the REQUEST file */
3344 FILE *dsaresp; /* output stream to the RESPONSE file */
3345 int modulus;
3346 unsigned int i, j;
3347 PQGParams pqg;
3348 PQGVerify vfy;
3349 unsigned int pghSize; /* size for p, g, and h */
3351 dsareq = fopen(reqfn, "r");
3352 dsaresp = stdout;
3353 memset(&pqg, 0, sizeof(pqg));
3354 memset(&vfy, 0, sizeof(vfy));
3356 while (fgets(buf, sizeof buf, dsareq) != NULL) {
3357 /* a comment or blank line */
3358 if (buf[0] == '#' || buf[0] == '\n') {
3359 fputs(buf, dsaresp);
3360 continue;
3363 /* [Mod = x] */
3364 if (buf[0] == '[') {
3366 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
3367 goto loser;
3370 if (pqg.prime.data) { /* P */
3371 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
3373 if (pqg.subPrime.data) { /* Q */
3374 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
3376 if (pqg.base.data) { /* G */
3377 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
3379 if (vfy.seed.data) { /* seed */
3380 SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
3382 if (vfy.h.data) { /* H */
3383 SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
3386 fputs(buf, dsaresp);
3388 /*calculate the size of p, g, and h then allocate items */
3389 pghSize = modulus/8;
3390 SECITEM_AllocItem(NULL, &pqg.prime, pghSize);
3391 SECITEM_AllocItem(NULL, &pqg.base, pghSize);
3392 SECITEM_AllocItem(NULL, &vfy.h, pghSize);
3393 pqg.prime.len = pqg.base.len = vfy.h.len = pghSize;
3394 /* seed and q are always 20 bytes */
3395 SECITEM_AllocItem(NULL, &vfy.seed, 20);
3396 SECITEM_AllocItem(NULL, &pqg.subPrime, 20);
3397 vfy.seed.len = pqg.subPrime.len = 20;
3398 vfy.counter = 0;
3400 continue;
3402 /* P = ... */
3403 if (buf[0] == 'P') {
3404 i = 1;
3405 while (isspace(buf[i]) || buf[i] == '=') {
3406 i++;
3408 for (j=0; j< pqg.prime.len; i+=2,j++) {
3409 hex_to_byteval(&buf[i], &pqg.prime.data[j]);
3412 fputs(buf, dsaresp);
3413 continue;
3416 /* Q = ... */
3417 if (buf[0] == 'Q') {
3418 i = 1;
3419 while (isspace(buf[i]) || buf[i] == '=') {
3420 i++;
3422 for (j=0; j< pqg.subPrime.len; i+=2,j++) {
3423 hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
3426 fputs(buf, dsaresp);
3427 continue;
3430 /* G = ... */
3431 if (buf[0] == 'G') {
3432 i = 1;
3433 while (isspace(buf[i]) || buf[i] == '=') {
3434 i++;
3436 for (j=0; j< pqg.base.len; i+=2,j++) {
3437 hex_to_byteval(&buf[i], &pqg.base.data[j]);
3440 fputs(buf, dsaresp);
3441 continue;
3444 /* Seed = ... */
3445 if (strncmp(buf, "Seed", 4) == 0) {
3446 i = 4;
3447 while (isspace(buf[i]) || buf[i] == '=') {
3448 i++;
3450 for (j=0; j< vfy.seed.len; i+=2,j++) {
3451 hex_to_byteval(&buf[i], &vfy.seed.data[j]);
3454 fputs(buf, dsaresp);
3455 continue;
3458 /* c = ... */
3459 if (buf[0] == 'c') {
3461 if (sscanf(buf, "c = %u", &vfy.counter) != 1) {
3462 goto loser;
3465 fputs(buf, dsaresp);
3466 continue;
3469 /* H = ... */
3470 if (buf[0] == 'H') {
3471 SECStatus rv, result = SECFailure;
3473 i = 1;
3474 while (isspace(buf[i]) || buf[i] == '=') {
3475 i++;
3477 for (j=0; j< vfy.h.len; i+=2,j++) {
3478 hex_to_byteval(&buf[i], &vfy.h.data[j]);
3480 fputs(buf, dsaresp);
3482 /* Verify the Parameters */
3483 rv = PQG_VerifyParams(&pqg, &vfy, &result);
3484 if (rv != SECSuccess) {
3485 goto loser;
3487 if (result == SECSuccess) {
3488 fprintf(dsaresp, "Result = P\n");
3489 } else {
3490 fprintf(dsaresp, "Result = F\n");
3492 continue;
3495 loser:
3496 fclose(dsareq);
3497 if (pqg.prime.data) { /* P */
3498 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
3500 if (pqg.subPrime.data) { /* Q */
3501 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
3503 if (pqg.base.data) { /* G */
3504 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
3506 if (vfy.seed.data) { /* seed */
3507 SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
3509 if (vfy.h.data) { /* H */
3510 SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
3516 * Perform the DSA Public Key Validation Test.
3518 * reqfn is the pathname of the REQUEST file.
3520 * The output RESPONSE file is written to stdout.
3522 void
3523 dsa_pqggen_test(char *reqfn)
3525 char buf[263]; /* holds one line from the input REQUEST file
3526 * or to the output RESPONSE file.
3527 * 263 to hold seed = (128 public key (x2 for HEX)
3529 FILE *dsareq; /* input stream from the REQUEST file */
3530 FILE *dsaresp; /* output stream to the RESPONSE file */
3531 int N; /* number of times to generate parameters */
3532 int modulus;
3533 int i;
3534 unsigned int j;
3535 PQGParams *pqg = NULL;
3536 PQGVerify *vfy = NULL;
3537 unsigned int keySizeIndex;
3539 dsareq = fopen(reqfn, "r");
3540 dsaresp = stdout;
3541 while (fgets(buf, sizeof buf, dsareq) != NULL) {
3542 /* a comment or blank line */
3543 if (buf[0] == '#' || buf[0] == '\n') {
3544 fputs(buf, dsaresp);
3545 continue;
3548 /* [Mod = ... ] */
3549 if (buf[0] == '[') {
3551 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
3552 goto loser;
3555 fputs(buf, dsaresp);
3556 fputc('\n', dsaresp);
3558 /****************************************************************
3559 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
3560 * that points to a valid key size.
3562 keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
3563 if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
3564 fprintf(dsaresp,
3565 "DSA key size must be a multiple of 64 between 512 "
3566 "and 1024, inclusive");
3567 goto loser;
3570 continue;
3572 /* N = ... */
3573 if (buf[0] == 'N') {
3575 if (sscanf(buf, "N = %d", &N) != 1) {
3576 goto loser;
3578 for (i = 0; i < N; i++) {
3579 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
3580 &pqg, &vfy) != SECSuccess) {
3581 fprintf(dsaresp,
3582 "ERROR: Unable to generate PQG parameters");
3583 goto loser;
3585 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
3586 fprintf(dsaresp, "P = %s\n", buf);
3587 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
3588 fprintf(dsaresp, "Q = %s\n", buf);
3589 to_hex_str(buf, pqg->base.data, pqg->base.len);
3590 fprintf(dsaresp, "G = %s\n", buf);
3591 to_hex_str(buf, vfy->seed.data, vfy->seed.len);
3592 fprintf(dsaresp, "Seed = %s\n", buf);
3593 fprintf(dsaresp, "c = %d\n", vfy->counter);
3594 to_hex_str(buf, vfy->h.data, vfy->h.len);
3595 fputs("H = ", dsaresp);
3596 for (j=vfy->h.len; j<pqg->prime.len; j++) {
3597 fprintf(dsaresp, "00");
3599 fprintf(dsaresp, "%s\n", buf);
3600 fputc('\n', dsaresp);
3601 if(pqg!=NULL) {
3602 PQG_DestroyParams(pqg);
3603 pqg = NULL;
3605 if(vfy!=NULL) {
3606 PQG_DestroyVerify(vfy);
3607 vfy = NULL;
3611 continue;
3615 loser:
3616 fclose(dsareq);
3617 if(pqg!=NULL) {
3618 PQG_DestroyParams(pqg);
3620 if(vfy!=NULL) {
3621 PQG_DestroyVerify(vfy);
3626 * Perform the DSA Signature Generation Test.
3628 * reqfn is the pathname of the REQUEST file.
3630 * The output RESPONSE file is written to stdout.
3632 void
3633 dsa_siggen_test(char *reqfn)
3635 char buf[263]; /* holds one line from the input REQUEST file
3636 * or to the output RESPONSE file.
3637 * max for Msg = ....
3639 FILE *dsareq; /* input stream from the REQUEST file */
3640 FILE *dsaresp; /* output stream to the RESPONSE file */
3641 int modulus;
3642 int i, j;
3643 PQGParams *pqg = NULL;
3644 PQGVerify *vfy = NULL;
3645 DSAPrivateKey *dsakey = NULL;
3646 int keySizeIndex; /* index for valid key sizes */
3647 unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
3648 unsigned char sig[DSA_SIGNATURE_LEN];
3649 SECItem digest, signature;
3651 dsareq = fopen(reqfn, "r");
3652 dsaresp = stdout;
3654 while (fgets(buf, sizeof buf, dsareq) != NULL) {
3655 /* a comment or blank line */
3656 if (buf[0] == '#' || buf[0] == '\n') {
3657 fputs(buf, dsaresp);
3658 continue;
3661 /* [Mod = x] */
3662 if (buf[0] == '[') {
3663 if(pqg!=NULL) {
3664 PQG_DestroyParams(pqg);
3665 pqg = NULL;
3667 if(vfy!=NULL) {
3668 PQG_DestroyVerify(vfy);
3669 vfy = NULL;
3671 if (dsakey != NULL) {
3672 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
3673 dsakey = NULL;
3676 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
3677 goto loser;
3679 fputs(buf, dsaresp);
3680 fputc('\n', dsaresp);
3682 /****************************************************************
3683 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
3684 * that points to a valid key size.
3686 keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
3687 if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
3688 fprintf(dsaresp,
3689 "DSA key size must be a multiple of 64 between 512 "
3690 "and 1024, inclusive");
3691 goto loser;
3694 /* Generate PQG and output PQG */
3695 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
3696 &pqg, &vfy) != SECSuccess) {
3697 fprintf(dsaresp, "ERROR: Unable to generate PQG parameters");
3698 goto loser;
3700 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
3701 fprintf(dsaresp, "P = %s\n", buf);
3702 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
3703 fprintf(dsaresp, "Q = %s\n", buf);
3704 to_hex_str(buf, pqg->base.data, pqg->base.len);
3705 fprintf(dsaresp, "G = %s\n", buf);
3707 /* create DSA Key */
3708 if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
3709 fprintf(dsaresp, "ERROR: Unable to generate DSA key");
3710 goto loser;
3712 continue;
3715 /* Msg = ... */
3716 if (strncmp(buf, "Msg", 3) == 0) {
3717 unsigned char msg[128]; /* MAX msg 128 */
3718 unsigned int len = 0;
3720 memset(sha1, 0, sizeof sha1);
3721 memset(sig, 0, sizeof sig);
3723 i = 3;
3724 while (isspace(buf[i]) || buf[i] == '=') {
3725 i++;
3727 for (j=0; isxdigit(buf[i]); i+=2,j++) {
3728 hex_to_byteval(&buf[i], &msg[j]);
3730 if (SHA1_HashBuf(sha1, msg, j) != SECSuccess) {
3731 fprintf(dsaresp, "ERROR: Unable to generate SHA1 digest");
3732 goto loser;
3735 digest.type = siBuffer;
3736 digest.data = sha1;
3737 digest.len = sizeof sha1;
3738 signature.type = siBuffer;
3739 signature.data = sig;
3740 signature.len = sizeof sig;
3742 if (DSA_SignDigest(dsakey, &signature, &digest) != SECSuccess) {
3743 fprintf(dsaresp, "ERROR: Unable to generate DSA signature");
3744 goto loser;
3746 len = signature.len;
3747 if (len%2 != 0) {
3748 goto loser;
3750 len = len/2;
3752 /* output the orginal Msg, and generated Y, R, and S */
3753 fputs(buf, dsaresp);
3754 fputc('\n', dsaresp);
3755 to_hex_str(buf, dsakey->publicValue.data,
3756 dsakey->publicValue.len);
3757 fprintf(dsaresp, "Y = %s\n", buf);
3758 to_hex_str(buf, &signature.data[0], len);
3759 fprintf(dsaresp, "R = %s\n", buf);
3760 to_hex_str(buf, &signature.data[len], len);
3761 fprintf(dsaresp, "S = %s\n", buf);
3762 continue;
3766 loser:
3767 fclose(dsareq);
3768 if(pqg != NULL) {
3769 PQG_DestroyParams(pqg);
3770 pqg = NULL;
3772 if(vfy != NULL) {
3773 PQG_DestroyVerify(vfy);
3774 vfy = NULL;
3776 if (dsaKey) {
3777 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
3778 dsakey = NULL;
3783 * Perform the DSA Signature Verification Test.
3785 * reqfn is the pathname of the REQUEST file.
3787 * The output RESPONSE file is written to stdout.
3789 void
3790 dsa_sigver_test(char *reqfn)
3792 char buf[263]; /* holds one line from the input REQUEST file
3793 * or to the output RESPONSE file.
3794 * max for Msg = ....
3796 FILE *dsareq; /* input stream from the REQUEST file */
3797 FILE *dsaresp; /* output stream to the RESPONSE file */
3798 int modulus;
3799 unsigned int i, j;
3800 SECItem digest, signature;
3801 DSAPublicKey pubkey;
3802 unsigned int pgySize; /* size for p, g, and y */
3803 unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
3804 unsigned char sig[DSA_SIGNATURE_LEN];
3806 dsareq = fopen(reqfn, "r");
3807 dsaresp = stdout;
3808 memset(&pubkey, 0, sizeof(pubkey));
3810 while (fgets(buf, sizeof buf, dsareq) != NULL) {
3811 /* a comment or blank line */
3812 if (buf[0] == '#' || buf[0] == '\n') {
3813 fputs(buf, dsaresp);
3814 continue;
3817 /* [Mod = x] */
3818 if (buf[0] == '[') {
3820 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
3821 goto loser;
3824 if (pubkey.params.prime.data) { /* P */
3825 SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
3827 if (pubkey.params.subPrime.data) { /* Q */
3828 SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
3830 if (pubkey.params.base.data) { /* G */
3831 SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
3833 if (pubkey.publicValue.data) { /* Y */
3834 SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
3836 fputs(buf, dsaresp);
3838 /* calculate the size of p, g, and y then allocate items */
3839 pgySize = modulus/8;
3840 SECITEM_AllocItem(NULL, &pubkey.params.prime, pgySize);
3841 SECITEM_AllocItem(NULL, &pubkey.params.base, pgySize);
3842 SECITEM_AllocItem(NULL, &pubkey.publicValue, pgySize);
3843 pubkey.params.prime.len = pubkey.params.base.len = pgySize;
3844 pubkey.publicValue.len = pgySize;
3846 /* q always 20 bytes */
3847 SECITEM_AllocItem(NULL, &pubkey.params.subPrime, 20);
3848 pubkey.params.subPrime.len = 20;
3850 continue;
3852 /* P = ... */
3853 if (buf[0] == 'P') {
3854 i = 1;
3855 while (isspace(buf[i]) || buf[i] == '=') {
3856 i++;
3858 memset(pubkey.params.prime.data, 0, pubkey.params.prime.len);
3859 for (j=0; j< pubkey.params.prime.len; i+=2,j++) {
3860 hex_to_byteval(&buf[i], &pubkey.params.prime.data[j]);
3863 fputs(buf, dsaresp);
3864 continue;
3867 /* Q = ... */
3868 if (buf[0] == 'Q') {
3869 i = 1;
3870 while (isspace(buf[i]) || buf[i] == '=') {
3871 i++;
3873 memset(pubkey.params.subPrime.data, 0, pubkey.params.subPrime.len);
3874 for (j=0; j< pubkey.params.subPrime.len; i+=2,j++) {
3875 hex_to_byteval(&buf[i], &pubkey.params.subPrime.data[j]);
3878 fputs(buf, dsaresp);
3879 continue;
3882 /* G = ... */
3883 if (buf[0] == 'G') {
3884 i = 1;
3885 while (isspace(buf[i]) || buf[i] == '=') {
3886 i++;
3888 memset(pubkey.params.base.data, 0, pubkey.params.base.len);
3889 for (j=0; j< pubkey.params.base.len; i+=2,j++) {
3890 hex_to_byteval(&buf[i], &pubkey.params.base.data[j]);
3893 fputs(buf, dsaresp);
3894 continue;
3897 /* Msg = ... */
3898 if (strncmp(buf, "Msg", 3) == 0) {
3899 unsigned char msg[128]; /* MAX msg 128 */
3900 memset(sha1, 0, sizeof sha1);
3902 i = 3;
3903 while (isspace(buf[i]) || buf[i] == '=') {
3904 i++;
3906 for (j=0; isxdigit(buf[i]); i+=2,j++) {
3907 hex_to_byteval(&buf[i], &msg[j]);
3909 if (SHA1_HashBuf(sha1, msg, j) != SECSuccess) {
3910 fprintf(dsaresp, "ERROR: Unable to generate SHA1 digest");
3911 goto loser;
3914 fputs(buf, dsaresp);
3915 continue;
3918 /* Y = ... */
3919 if (buf[0] == 'Y') {
3920 i = 1;
3921 while (isspace(buf[i]) || buf[i] == '=') {
3922 i++;
3924 memset(pubkey.publicValue.data, 0, pubkey.params.subPrime.len);
3925 for (j=0; j< pubkey.publicValue.len; i+=2,j++) {
3926 hex_to_byteval(&buf[i], &pubkey.publicValue.data[j]);
3929 fputs(buf, dsaresp);
3930 continue;
3933 /* R = ... */
3934 if (buf[0] == 'R') {
3935 memset(sig, 0, sizeof sig);
3936 i = 1;
3937 while (isspace(buf[i]) || buf[i] == '=') {
3938 i++;
3940 for (j=0; j< DSA_SUBPRIME_LEN; i+=2,j++) {
3941 hex_to_byteval(&buf[i], &sig[j]);
3944 fputs(buf, dsaresp);
3945 continue;
3948 /* S = ... */
3949 if (buf[0] == 'S') {
3950 i = 1;
3951 while (isspace(buf[i]) || buf[i] == '=') {
3952 i++;
3954 for (j=DSA_SUBPRIME_LEN; j< DSA_SIGNATURE_LEN; i+=2,j++) {
3955 hex_to_byteval(&buf[i], &sig[j]);
3957 fputs(buf, dsaresp);
3959 digest.type = siBuffer;
3960 digest.data = sha1;
3961 digest.len = sizeof sha1;
3962 signature.type = siBuffer;
3963 signature.data = sig;
3964 signature.len = sizeof sig;
3966 if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) {
3967 fprintf(dsaresp, "Result = P\n");
3968 } else {
3969 fprintf(dsaresp, "Result = F\n");
3971 continue;
3974 loser:
3975 fclose(dsareq);
3976 if (pubkey.params.prime.data) { /* P */
3977 SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
3979 if (pubkey.params.subPrime.data) { /* Q */
3980 SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
3982 if (pubkey.params.base.data) { /* G */
3983 SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
3985 if (pubkey.publicValue.data) { /* Y */
3986 SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
3991 * Perform the RSA Signature Generation Test.
3993 * reqfn is the pathname of the REQUEST file.
3995 * The output RESPONSE file is written to stdout.
3997 void
3998 rsa_siggen_test(char *reqfn)
4000 char buf[2*RSA_MAX_TEST_MODULUS_BYTES+1];
4001 /* buf holds one line from the input REQUEST file
4002 * or to the output RESPONSE file.
4003 * 2x for HEX output + 1 for \n
4005 FILE *rsareq; /* input stream from the REQUEST file */
4006 FILE *rsaresp; /* output stream to the RESPONSE file */
4007 int i, j;
4008 unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
4009 unsigned int shaLength = 0; /* length of SHA */
4010 HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
4011 SECOidTag shaOid = SEC_OID_UNKNOWN;
4012 int modulus; /* the Modulus size */
4013 int publicExponent = DEFAULT_RSA_PUBLIC_EXPONENT;
4014 SECItem pe = {0, 0, 0 };
4015 unsigned char pubEx[4];
4016 int peCount = 0;
4018 RSAPrivateKey *rsaBlapiPrivKey = NULL; /* holds RSA private and
4019 * public keys */
4020 RSAPublicKey *rsaBlapiPublicKey = NULL; /* hold RSA public key */
4022 rsareq = fopen(reqfn, "r");
4023 rsaresp = stdout;
4025 /* calculate the exponent */
4026 for (i=0; i < 4; i++) {
4027 if (peCount || (publicExponent &
4028 ((unsigned long)0xff000000L >> (i*8)))) {
4029 pubEx[peCount] =
4030 (unsigned char)((publicExponent >> (3-i)*8) & 0xff);
4031 peCount++;
4034 pe.len = peCount;
4035 pe.data = &pubEx[0];
4036 pe.type = siBuffer;
4038 while (fgets(buf, sizeof buf, rsareq) != NULL) {
4039 /* a comment or blank line */
4040 if (buf[0] == '#' || buf[0] == '\n') {
4041 fputs(buf, rsaresp);
4042 continue;
4045 /* [mod = ...] */
4046 if (buf[0] == '[') {
4048 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
4049 goto loser;
4051 if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
4052 fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
4053 goto loser;
4056 fputs(buf, rsaresp);
4058 if (rsaBlapiPrivKey != NULL) {
4059 PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
4060 rsaBlapiPrivKey = NULL;
4061 rsaBlapiPublicKey = NULL;
4064 rsaBlapiPrivKey = RSA_NewKey(modulus, &pe);
4065 if (rsaBlapiPrivKey == NULL) {
4066 fprintf(rsaresp, "Error unable to create RSA key\n");
4067 goto loser;
4070 to_hex_str(buf, rsaBlapiPrivKey->modulus.data,
4071 rsaBlapiPrivKey->modulus.len);
4072 fprintf(rsaresp, "\nn = %s\n\n", buf);
4073 to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data,
4074 rsaBlapiPrivKey->publicExponent.len);
4075 fprintf(rsaresp, "e = %s\n", buf);
4076 /* convert private key to public key. Memory
4077 * is freed with private key's arena */
4078 rsaBlapiPublicKey = (RSAPublicKey *)PORT_ArenaAlloc(
4079 rsaBlapiPrivKey->arena,
4080 sizeof(RSAPublicKey));
4082 rsaBlapiPublicKey->modulus.len = rsaBlapiPrivKey->modulus.len;
4083 rsaBlapiPublicKey->modulus.data = rsaBlapiPrivKey->modulus.data;
4084 rsaBlapiPublicKey->publicExponent.len =
4085 rsaBlapiPrivKey->publicExponent.len;
4086 rsaBlapiPublicKey->publicExponent.data =
4087 rsaBlapiPrivKey->publicExponent.data;
4088 continue;
4091 /* SHAAlg = ... */
4092 if (strncmp(buf, "SHAAlg", 6) == 0) {
4093 i = 6;
4094 while (isspace(buf[i]) || buf[i] == '=') {
4095 i++;
4097 /* set the SHA Algorithm */
4098 if (strncmp(&buf[i], "SHA1", 4) == 0) {
4099 shaAlg = HASH_AlgSHA1;
4100 } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
4101 shaAlg = HASH_AlgSHA256;
4102 } else if (strncmp(&buf[i], "SHA384", 6)== 0) {
4103 shaAlg = HASH_AlgSHA384;
4104 } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
4105 shaAlg = HASH_AlgSHA512;
4106 } else {
4107 fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
4108 goto loser;
4110 fputs(buf, rsaresp);
4111 continue;
4114 /* Msg = ... */
4115 if (strncmp(buf, "Msg", 3) == 0) {
4117 unsigned char msg[128]; /* MAX msg 128 */
4118 unsigned int rsa_bytes_signed;
4119 unsigned char rsa_computed_signature[RSA_MAX_TEST_MODULUS_BYTES];
4120 SECStatus rv = SECFailure;
4121 NSSLOWKEYPublicKey * rsa_public_key;
4122 NSSLOWKEYPrivateKey * rsa_private_key;
4123 NSSLOWKEYPrivateKey low_RSA_private_key = { NULL,
4124 NSSLOWKEYRSAKey, };
4125 NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
4126 NSSLOWKEYRSAKey, };
4128 low_RSA_private_key.u.rsa = *rsaBlapiPrivKey;
4129 low_RSA_public_key.u.rsa = *rsaBlapiPublicKey;
4131 rsa_private_key = &low_RSA_private_key;
4132 rsa_public_key = &low_RSA_public_key;
4134 memset(sha, 0, sizeof sha);
4135 memset(msg, 0, sizeof msg);
4136 rsa_bytes_signed = 0;
4137 memset(rsa_computed_signature, 0, sizeof rsa_computed_signature);
4139 i = 3;
4140 while (isspace(buf[i]) || buf[i] == '=') {
4141 i++;
4143 for (j=0; isxdigit(buf[i]) && j < sizeof(msg); i+=2,j++) {
4144 hex_to_byteval(&buf[i], &msg[j]);
4147 if (shaAlg == HASH_AlgSHA1) {
4148 if (SHA1_HashBuf(sha, msg, j) != SECSuccess) {
4149 fprintf(rsaresp, "ERROR: Unable to generate SHA1");
4150 goto loser;
4152 shaLength = SHA1_LENGTH;
4153 shaOid = SEC_OID_SHA1;
4154 } else if (shaAlg == HASH_AlgSHA256) {
4155 if (SHA256_HashBuf(sha, msg, j) != SECSuccess) {
4156 fprintf(rsaresp, "ERROR: Unable to generate SHA256");
4157 goto loser;
4159 shaLength = SHA256_LENGTH;
4160 shaOid = SEC_OID_SHA256;
4161 } else if (shaAlg == HASH_AlgSHA384) {
4162 if (SHA384_HashBuf(sha, msg, j) != SECSuccess) {
4163 fprintf(rsaresp, "ERROR: Unable to generate SHA384");
4164 goto loser;
4166 shaLength = SHA384_LENGTH;
4167 shaOid = SEC_OID_SHA384;
4168 } else if (shaAlg == HASH_AlgSHA512) {
4169 if (SHA512_HashBuf(sha, msg, j) != SECSuccess) {
4170 fprintf(rsaresp, "ERROR: Unable to generate SHA512");
4171 goto loser;
4173 shaLength = SHA512_LENGTH;
4174 shaOid = SEC_OID_SHA512;
4175 } else {
4176 fprintf(rsaresp, "ERROR: SHAAlg not defined.");
4177 goto loser;
4180 /* Perform RSA signature with the RSA private key. */
4181 rv = RSA_HashSign( shaOid,
4182 rsa_private_key,
4183 rsa_computed_signature,
4184 &rsa_bytes_signed,
4185 nsslowkey_PrivateModulusLen(rsa_private_key),
4186 sha,
4187 shaLength);
4189 if( rv != SECSuccess ) {
4190 fprintf(rsaresp, "ERROR: RSA_HashSign failed");
4191 goto loser;
4194 /* Output the signature */
4195 fputs(buf, rsaresp);
4196 to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed);
4197 fprintf(rsaresp, "S = %s\n", buf);
4199 /* Perform RSA verification with the RSA public key. */
4200 rv = RSA_HashCheckSign( shaOid,
4201 rsa_public_key,
4202 rsa_computed_signature,
4203 rsa_bytes_signed,
4204 sha,
4205 shaLength);
4206 if( rv != SECSuccess ) {
4207 fprintf(rsaresp, "ERROR: RSA_HashCheckSign failed");
4208 goto loser;
4210 continue;
4213 loser:
4214 fclose(rsareq);
4216 if (rsaBlapiPrivKey != NULL) {
4217 /* frees private and public key */
4218 PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
4219 rsaBlapiPrivKey = NULL;
4220 rsaBlapiPublicKey = NULL;
4225 * Perform the RSA Signature Verification Test.
4227 * reqfn is the pathname of the REQUEST file.
4229 * The output RESPONSE file is written to stdout.
4231 void
4232 rsa_sigver_test(char *reqfn)
4234 char buf[2*RSA_MAX_TEST_MODULUS_BYTES+7];
4235 /* buf holds one line from the input REQUEST file
4236 * or to the output RESPONSE file.
4237 * s = 2x for HEX output + 1 for \n
4239 FILE *rsareq; /* input stream from the REQUEST file */
4240 FILE *rsaresp; /* output stream to the RESPONSE file */
4241 int i, j;
4242 unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
4243 unsigned int shaLength = 0; /* actual length of the digest */
4244 HASH_HashType shaAlg = HASH_AlgNULL;
4245 SECOidTag shaOid = SEC_OID_UNKNOWN;
4246 int modulus = 0; /* the Modulus size */
4247 unsigned char signature[513]; /* largest signature size + '\n' */
4248 unsigned int signatureLength = 0; /* actual length of the signature */
4249 PRBool keyvalid = PR_TRUE;
4251 RSAPublicKey rsaBlapiPublicKey; /* hold RSA public key */
4253 rsareq = fopen(reqfn, "r");
4254 rsaresp = stdout;
4255 memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey));
4257 while (fgets(buf, sizeof buf, rsareq) != NULL) {
4258 /* a comment or blank line */
4259 if (buf[0] == '#' || buf[0] == '\n') {
4260 fputs(buf, rsaresp);
4261 continue;
4264 /* [Mod = ...] */
4265 if (buf[0] == '[') {
4266 unsigned int flen; /* length in bytes of the field size */
4268 if (rsaBlapiPublicKey.modulus.data) { /* n */
4269 SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
4271 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
4272 goto loser;
4275 if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
4276 fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
4277 goto loser;
4280 fputs(buf, rsaresp);
4282 signatureLength = flen = modulus/8;
4284 SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.modulus, flen);
4285 if (rsaBlapiPublicKey.modulus.data == NULL) {
4286 goto loser;
4288 continue;
4291 /* n = ... modulus */
4292 if (buf[0] == 'n') {
4293 i = 1;
4294 while (isspace(buf[i]) || buf[i] == '=') {
4295 i++;
4297 keyvalid = from_hex_str(&rsaBlapiPublicKey.modulus.data[0],
4298 rsaBlapiPublicKey.modulus.len,
4299 &buf[i]);
4301 if (!keyvalid) {
4302 fprintf(rsaresp, "ERROR: rsa_sigver n not valid.\n");
4303 goto loser;
4305 fputs(buf, rsaresp);
4306 continue;
4309 /* SHAAlg = ... */
4310 if (strncmp(buf, "SHAAlg", 6) == 0) {
4311 i = 6;
4312 while (isspace(buf[i]) || buf[i] == '=') {
4313 i++;
4315 /* set the SHA Algorithm */
4316 if (strncmp(&buf[i], "SHA1", 4) == 0) {
4317 shaAlg = HASH_AlgSHA1;
4318 } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
4319 shaAlg = HASH_AlgSHA256;
4320 } else if (strncmp(&buf[i], "SHA384", 6) == 0) {
4321 shaAlg = HASH_AlgSHA384;
4322 } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
4323 shaAlg = HASH_AlgSHA512;
4324 } else {
4325 fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
4326 goto loser;
4328 fputs(buf, rsaresp);
4329 continue;
4332 /* e = ... public Key */
4333 if (buf[0] == 'e') {
4334 unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES];
4335 unsigned char t;
4337 memset(data, 0, sizeof data);
4339 if (rsaBlapiPublicKey.publicExponent.data) { /* e */
4340 SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
4343 i = 1;
4344 while (isspace(buf[i]) || buf[i] == '=') {
4345 i++;
4347 /* skip leading zero's */
4348 while (isxdigit(buf[i])) {
4349 hex_to_byteval(&buf[i], &t);
4350 if (t == 0) {
4351 i+=2;
4352 } else break;
4355 /* get the exponent */
4356 for (j=0; isxdigit(buf[i]) && j < sizeof data; i+=2,j++) {
4357 hex_to_byteval(&buf[i], &data[j]);
4360 if (j == 0) { j = 1; } /* to handle 1 byte length exponents */
4362 SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.publicExponent, j);
4363 if (rsaBlapiPublicKey.publicExponent.data == NULL) {
4364 goto loser;
4367 for (i=0; i < j; i++) {
4368 rsaBlapiPublicKey.publicExponent.data[i] = data[i];
4371 fputs(buf, rsaresp);
4372 continue;
4375 /* Msg = ... */
4376 if (strncmp(buf, "Msg", 3) == 0) {
4377 unsigned char msg[128]; /* MAX msg 128 */
4379 memset(sha, 0, sizeof sha);
4380 memset(msg, 0, sizeof msg);
4382 i = 3;
4383 while (isspace(buf[i]) || buf[i] == '=') {
4384 i++;
4387 for (j=0; isxdigit(buf[i]) && j < sizeof msg; i+=2,j++) {
4388 hex_to_byteval(&buf[i], &msg[j]);
4391 if (shaAlg == HASH_AlgSHA1) {
4392 if (SHA1_HashBuf(sha, msg, j) != SECSuccess) {
4393 fprintf(rsaresp, "ERROR: Unable to generate SHA1");
4394 goto loser;
4396 shaLength = SHA1_LENGTH;
4397 shaOid = SEC_OID_SHA1;
4398 } else if (shaAlg == HASH_AlgSHA256) {
4399 if (SHA256_HashBuf(sha, msg, j) != SECSuccess) {
4400 fprintf(rsaresp, "ERROR: Unable to generate SHA256");
4401 goto loser;
4403 shaLength = SHA256_LENGTH;
4404 shaOid = SEC_OID_SHA256;
4405 } else if (shaAlg == HASH_AlgSHA384) {
4406 if (SHA384_HashBuf(sha, msg, j) != SECSuccess) {
4407 fprintf(rsaresp, "ERROR: Unable to generate SHA384");
4408 goto loser;
4410 shaLength = SHA384_LENGTH;
4411 shaOid = SEC_OID_SHA384;
4412 } else if (shaAlg == HASH_AlgSHA512) {
4413 if (SHA512_HashBuf(sha, msg, j) != SECSuccess) {
4414 fprintf(rsaresp, "ERROR: Unable to generate SHA512");
4415 goto loser;
4417 shaLength = SHA512_LENGTH;
4418 shaOid = SEC_OID_SHA512;
4419 } else {
4420 fprintf(rsaresp, "ERROR: SHAAlg not defined.");
4421 goto loser;
4424 fputs(buf, rsaresp);
4425 continue;
4429 /* S = ... */
4430 if (buf[0] == 'S') {
4431 SECStatus rv = SECFailure;
4432 NSSLOWKEYPublicKey * rsa_public_key;
4433 NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
4434 NSSLOWKEYRSAKey, };
4436 /* convert to a low RSA public key */
4437 low_RSA_public_key.u.rsa = rsaBlapiPublicKey;
4438 rsa_public_key = &low_RSA_public_key;
4440 memset(signature, 0, sizeof(signature));
4441 i = 1;
4442 while (isspace(buf[i]) || buf[i] == '=') {
4443 i++;
4446 for (j=0; isxdigit(buf[i]) && j < sizeof signature; i+=2,j++) {
4447 hex_to_byteval(&buf[i], &signature[j]);
4450 signatureLength = j;
4451 fputs(buf, rsaresp);
4453 /* Perform RSA verification with the RSA public key. */
4454 rv = RSA_HashCheckSign( shaOid,
4455 rsa_public_key,
4456 signature,
4457 signatureLength,
4458 sha,
4459 shaLength);
4460 if( rv == SECSuccess ) {
4461 fputs("Result = P\n", rsaresp);
4462 } else {
4463 fputs("Result = F\n", rsaresp);
4465 continue;
4468 loser:
4469 fclose(rsareq);
4470 if (rsaBlapiPublicKey.modulus.data) { /* n */
4471 SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
4473 if (rsaBlapiPublicKey.publicExponent.data) { /* e */
4474 SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
4478 int main(int argc, char **argv)
4480 if (argc < 2) exit (-1);
4481 NSS_NoDB_Init(NULL);
4482 /*************/
4483 /* TDEA */
4484 /*************/
4485 if (strcmp(argv[1], "tdea") == 0) {
4486 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
4487 if (strcmp(argv[2], "kat") == 0) {
4488 /* Known Answer Test (KAT) */
4489 tdea_kat_mmt(argv[4]);
4490 } else if (strcmp(argv[2], "mmt") == 0) {
4491 /* Multi-block Message Test (MMT) */
4492 tdea_kat_mmt(argv[4]);
4493 } else if (strcmp(argv[2], "mct") == 0) {
4494 /* Monte Carlo Test (MCT) */
4495 if (strcmp(argv[3], "ecb") == 0) {
4496 /* ECB mode */
4497 tdea_mct(NSS_DES_EDE3, argv[4]);
4498 } else if (strcmp(argv[3], "cbc") == 0) {
4499 /* CBC mode */
4500 tdea_mct(NSS_DES_EDE3_CBC, argv[4]);
4503 /*************/
4504 /* AES */
4505 /*************/
4506 } else if (strcmp(argv[1], "aes") == 0) {
4507 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
4508 if ( strcmp(argv[2], "kat") == 0) {
4509 /* Known Answer Test (KAT) */
4510 aes_kat_mmt(argv[4]);
4511 } else if (strcmp(argv[2], "mmt") == 0) {
4512 /* Multi-block Message Test (MMT) */
4513 aes_kat_mmt(argv[4]);
4514 } else if (strcmp(argv[2], "mct") == 0) {
4515 /* Monte Carlo Test (MCT) */
4516 if ( strcmp(argv[3], "ecb") == 0) {
4517 /* ECB mode */
4518 aes_ecb_mct(argv[4]);
4519 } else if (strcmp(argv[3], "cbc") == 0) {
4520 /* CBC mode */
4521 aes_cbc_mct(argv[4]);
4524 /*************/
4525 /* SHA */
4526 /*************/
4527 } else if (strcmp(argv[1], "sha") == 0) {
4528 sha_test(argv[2]);
4529 /*************/
4530 /* RSA */
4531 /*************/
4532 } else if (strcmp(argv[1], "rsa") == 0) {
4533 /* argv[2]=siggen|sigver */
4534 /* argv[3]=<test name>.req */
4535 if (strcmp(argv[2], "siggen") == 0) {
4536 /* Signature Generation Test */
4537 rsa_siggen_test(argv[3]);
4538 } else if (strcmp(argv[2], "sigver") == 0) {
4539 /* Signature Verification Test */
4540 rsa_sigver_test(argv[3]);
4542 /*************/
4543 /* HMAC */
4544 /*************/
4545 } else if (strcmp(argv[1], "hmac") == 0) {
4546 hmac_test(argv[2]);
4547 /*************/
4548 /* DSA */
4549 /*************/
4550 } else if (strcmp(argv[1], "dsa") == 0) {
4551 /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */
4552 /* argv[3]=<test name>.req */
4553 if (strcmp(argv[2], "keypair") == 0) {
4554 /* Key Pair Generation Test */
4555 dsa_keypair_test(argv[3]);
4556 } else if (strcmp(argv[2], "pqggen") == 0) {
4557 /* Domain Parameter Generation Test */
4558 dsa_pqggen_test(argv[3]);
4559 } else if (strcmp(argv[2], "pqgver") == 0) {
4560 /* Domain Parameter Validation Test */
4561 dsa_pqgver_test(argv[3]);
4562 } else if (strcmp(argv[2], "siggen") == 0) {
4563 /* Signature Generation Test */
4564 dsa_siggen_test(argv[3]);
4565 } else if (strcmp(argv[2], "sigver") == 0) {
4566 /* Signature Verification Test */
4567 dsa_sigver_test(argv[3]);
4569 #ifdef NSS_ENABLE_ECC
4570 /*************/
4571 /* ECDSA */
4572 /*************/
4573 } else if (strcmp(argv[1], "ecdsa") == 0) {
4574 /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */
4575 if ( strcmp(argv[2], "keypair") == 0) {
4576 /* Key Pair Generation Test */
4577 ecdsa_keypair_test(argv[3]);
4578 } else if (strcmp(argv[2], "pkv") == 0) {
4579 /* Public Key Validation Test */
4580 ecdsa_pkv_test(argv[3]);
4581 } else if (strcmp(argv[2], "siggen") == 0) {
4582 /* Signature Generation Test */
4583 ecdsa_siggen_test(argv[3]);
4584 } else if (strcmp(argv[2], "sigver") == 0) {
4585 /* Signature Verification Test */
4586 ecdsa_sigver_test(argv[3]);
4588 #endif /* NSS_ENABLE_ECC */
4589 /*************/
4590 /* RNG */
4591 /*************/
4592 } else if (strcmp(argv[1], "rng") == 0) {
4593 /* argv[2]=vst|mct argv[3]=<test name>.req */
4594 if ( strcmp(argv[2], "vst") == 0) {
4595 /* Variable Seed Test */
4596 rng_vst(argv[3]);
4597 } else if (strcmp(argv[2], "mct") == 0) {
4598 /* Monte Carlo Test */
4599 rng_mct(argv[3]);
4602 return 0;