1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
22 #include "../../lib/freebl/mpi/mpi.h"
25 #ifndef NSS_DISABLE_ECC
27 EC_DecodeParams(const SECItem
*encodedParams
, ECParams
**ecparams
);
29 EC_CopyParams(PLArenaPool
*arena
, ECParams
*dstParams
,
30 const ECParams
*srcParams
);
35 #define BYTE unsigned char
36 #define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001
37 #define RSA_MAX_TEST_MODULUS_BITS 4096
38 #define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS/8
39 #define RSA_MAX_TEST_EXPONENT_BYTES 8
40 #define PQG_TEST_SEED_BYTES 20
43 hex_to_byteval(const char *c2
, unsigned char *byteval
)
49 if (c2
[i
] >= '0' && c2
[i
] <= '9') {
51 *byteval
|= offset
<< 4*(1-i
);
52 } else if (c2
[i
] >= 'a' && c2
[i
] <= 'f') {
54 *byteval
|= (offset
+ 10) << 4*(1-i
);
55 } else if (c2
[i
] >= 'A' && c2
[i
] <= 'F') {
57 *byteval
|= (offset
+ 10) << 4*(1-i
);
66 byteval_to_hex(unsigned char byteval
, char *c2
, char a
)
71 offset
= (byteval
>> 4*(1-i
)) & 0x0f;
75 c2
[i
] = a
+ offset
- 10;
82 to_hex_str(char *str
, const unsigned char *buf
, unsigned int len
)
85 for (i
=0; i
<len
; i
++) {
86 byteval_to_hex(buf
[i
], &str
[2*i
], 'a');
92 to_hex_str_cap(char *str
, const unsigned char *buf
, unsigned int len
)
95 for (i
=0; i
<len
; i
++) {
96 byteval_to_hex(buf
[i
], &str
[2*i
], 'A');
102 * Convert a string of hex digits (str) to an array (buf) of len bytes.
103 * Return PR_TRUE if the hex string can fit in the byte array. Return
104 * PR_FALSE if the hex string is empty or is too long.
107 from_hex_str(unsigned char *buf
, unsigned int len
, const char *str
)
109 unsigned int nxdigit
; /* number of hex digits in str */
110 unsigned int i
; /* index into buf */
111 unsigned int j
; /* index into str */
113 /* count the hex digits */
115 for (nxdigit
= 0; isxdigit(str
[nxdigit
]); nxdigit
++) {
121 if (nxdigit
> 2*len
) {
123 * The input hex string is too long, but we allow it if the
124 * extra digits are leading 0's.
126 for (j
= 0; j
< nxdigit
-2*len
; j
++) {
131 /* skip leading 0's */
132 str
+= nxdigit
-2*len
;
135 for (i
=0, j
=0; i
< len
; i
++) {
136 if (2*i
< 2*len
-nxdigit
) {
137 /* Handle a short input as if we padded it with leading 0's. */
138 if (2*i
+1 < 2*len
-nxdigit
) {
144 hex_to_byteval(tmp
, &buf
[i
]);
148 hex_to_byteval(&str
[j
], &buf
[i
]);
158 const unsigned char *key
,
159 const unsigned char *iv
,
160 unsigned char *output
, unsigned int *outputlen
, unsigned int maxoutputlen
,
161 const unsigned char *input
, unsigned int inputlen
)
163 SECStatus rv
= SECFailure
;
165 unsigned char doublecheck
[8*20]; /* 1 to 20 blocks */
166 unsigned int doublechecklen
= 0;
168 cx
= DES_CreateContext(key
, iv
, mode
, PR_TRUE
);
172 rv
= DES_Encrypt(cx
, output
, outputlen
, maxoutputlen
, input
, inputlen
);
173 if (rv
!= SECSuccess
) {
176 if (*outputlen
!= inputlen
) {
179 DES_DestroyContext(cx
, PR_TRUE
);
183 * Doublecheck our result by decrypting the ciphertext and
184 * compare the output with the input plaintext.
186 cx
= DES_CreateContext(key
, iv
, mode
, PR_FALSE
);
190 rv
= DES_Decrypt(cx
, doublecheck
, &doublechecklen
, sizeof doublecheck
,
192 if (rv
!= SECSuccess
) {
195 if (doublechecklen
!= *outputlen
) {
198 DES_DestroyContext(cx
, PR_TRUE
);
200 if (memcmp(doublecheck
, input
, inputlen
) != 0) {
207 DES_DestroyContext(cx
, PR_TRUE
);
215 const unsigned char *key
,
216 const unsigned char *iv
,
217 unsigned char *output
, unsigned int *outputlen
, unsigned int maxoutputlen
,
218 const unsigned char *input
, unsigned int inputlen
)
220 SECStatus rv
= SECFailure
;
222 unsigned char doublecheck
[8*20]; /* 1 to 20 blocks */
223 unsigned int doublechecklen
= 0;
225 cx
= DES_CreateContext(key
, iv
, mode
, PR_FALSE
);
229 rv
= DES_Decrypt(cx
, output
, outputlen
, maxoutputlen
,
231 if (rv
!= SECSuccess
) {
234 if (*outputlen
!= inputlen
) {
237 DES_DestroyContext(cx
, PR_TRUE
);
241 * Doublecheck our result by encrypting the plaintext and
242 * compare the output with the input ciphertext.
244 cx
= DES_CreateContext(key
, iv
, mode
, PR_TRUE
);
248 rv
= DES_Encrypt(cx
, doublecheck
, &doublechecklen
, sizeof doublecheck
,
250 if (rv
!= SECSuccess
) {
253 if (doublechecklen
!= *outputlen
) {
256 DES_DestroyContext(cx
, PR_TRUE
);
258 if (memcmp(doublecheck
, input
, inputlen
) != 0) {
265 DES_DestroyContext(cx
, PR_TRUE
);
271 * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
272 * Test (MMT) in ECB or CBC mode. The KAT (there are five types)
273 * and MMT have the same structure: given the key and IV (CBC mode
274 * only), encrypt the given plaintext or decrypt the given ciphertext.
275 * So we can handle them the same way.
277 * reqfn is the pathname of the REQUEST file.
279 * The output RESPONSE file is written to stdout.
282 tdea_kat_mmt(char *reqfn
)
284 char buf
[180]; /* holds one line from the input REQUEST file.
285 * needs to be large enough to hold the longest
286 * line "CIPHERTEXT = <180 hex digits>\n".
288 FILE *req
; /* input stream from the REQUEST file */
289 FILE *resp
; /* output stream to the RESPONSE file */
291 int mode
; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
292 int crypt
= DECRYPT
; /* 1 means encrypt, 0 means decrypt */
293 unsigned char key
[24]; /* TDEA 3 key bundle */
294 unsigned int numKeys
= 0;
295 unsigned char iv
[8]; /* for all modes except ECB */
296 unsigned char plaintext
[8*20]; /* 1 to 20 blocks */
297 unsigned int plaintextlen
;
298 unsigned char ciphertext
[8*20]; /* 1 to 20 blocks */
299 unsigned int ciphertextlen
;
302 req
= fopen(reqfn
, "r");
304 while (fgets(buf
, sizeof buf
, req
) != NULL
) {
305 /* a comment or blank line */
306 if (buf
[0] == '#' || buf
[0] == '\n') {
310 /* [ENCRYPT] or [DECRYPT] */
312 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
321 if (strncmp(&buf
[0], "NumKeys", 7) == 0) {
323 while (isspace(buf
[i
]) || buf
[i
] == '=') {
330 /* "COUNT = x" begins a new data set */
331 if (strncmp(buf
, "COUNT", 5) == 0) {
332 /* mode defaults to ECB, if dataset has IV mode will be set CBC */
334 /* zeroize the variables for the test with this data set */
335 memset(key
, 0, sizeof key
);
336 memset(iv
, 0, sizeof iv
);
337 memset(plaintext
, 0, sizeof plaintext
);
339 memset(ciphertext
, 0, sizeof ciphertext
);
345 if (strncmp(buf
, "KEYs", 4) == 0) {
347 while (isspace(buf
[i
]) || buf
[i
] == '=') {
350 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
351 hex_to_byteval(&buf
[i
], &key
[j
]);
360 if (strncmp(buf
, "KEY1", 4) == 0) {
362 while (isspace(buf
[i
]) || buf
[i
] == '=') {
365 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
366 hex_to_byteval(&buf
[i
], &key
[j
]);
372 if (strncmp(buf
, "KEY2", 4) == 0) {
374 while (isspace(buf
[i
]) || buf
[i
] == '=') {
377 for (j
=8; isxdigit(buf
[i
]); i
+=2,j
++) {
378 hex_to_byteval(&buf
[i
], &key
[j
]);
384 if (strncmp(buf
, "KEY3", 4) == 0) {
386 while (isspace(buf
[i
]) || buf
[i
] == '=') {
389 for (j
=16; isxdigit(buf
[i
]); i
+=2,j
++) {
390 hex_to_byteval(&buf
[i
], &key
[j
]);
398 if (strncmp(buf
, "IV", 2) == 0) {
399 mode
= NSS_DES_EDE3_CBC
;
401 while (isspace(buf
[i
]) || buf
[i
] == '=') {
404 for (j
=0; j
<sizeof iv
; i
+=2,j
++) {
405 hex_to_byteval(&buf
[i
], &iv
[j
]);
411 /* PLAINTEXT = ... */
412 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
414 if (crypt
!= ENCRYPT
) {
418 while (isspace(buf
[i
]) || buf
[i
] == '=') {
421 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
422 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
425 rv
= tdea_encrypt_buf(mode
, key
,
426 (mode
== NSS_DES_EDE3
) ? NULL
: iv
,
427 ciphertext
, &ciphertextlen
, sizeof ciphertext
,
428 plaintext
, plaintextlen
);
429 if (rv
!= SECSuccess
) {
434 fputs("CIPHERTEXT = ", resp
);
435 to_hex_str(buf
, ciphertext
, ciphertextlen
);
440 /* CIPHERTEXT = ... */
441 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
443 if (crypt
!= DECRYPT
) {
448 while (isspace(buf
[i
]) || buf
[i
] == '=') {
451 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
452 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
456 rv
= tdea_decrypt_buf(mode
, key
,
457 (mode
== NSS_DES_EDE3
) ? NULL
: iv
,
458 plaintext
, &plaintextlen
, sizeof plaintext
,
459 ciphertext
, ciphertextlen
);
460 if (rv
!= SECSuccess
) {
465 fputs("PLAINTEXT = ", resp
);
466 to_hex_str(buf
, plaintext
, plaintextlen
);
478 * Set the parity bit for the given byte
480 BYTE
odd_parity( BYTE in
)
486 return (BYTE
)(out
^ !(in
& 1));
490 * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j]
491 * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
494 tdea_mct_next_keys(unsigned char *key
,
495 const unsigned char *text_2
, const unsigned char *text_1
,
496 const unsigned char *text
, unsigned int numKeys
)
500 /* key1[i+1] = key1[i] xor PT/CT[j] */
501 for (k
=0; k
<8; k
++) {
505 if (numKeys
== 2 || numKeys
== 3) {
506 /* key2 independent */
507 for (k
=8; k
<16; k
++) {
508 /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
509 key
[k
] ^= text_1
[k
-8];
513 for (k
=8; k
<16; k
++) {
514 /* key2[i+1] = KEY2[i] xor PT/CT[j] */
519 if (numKeys
== 1 || numKeys
== 2) {
521 for (k
=16; k
<24; k
++) {
522 /* key3[i+1] = KEY3[i] xor PT/CT[j] */
526 /* key3 independent */
527 for (k
=16; k
<24; k
++) {
528 /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
529 key
[k
] ^= text_2
[k
-16];
532 /* set the parity bits */
533 for (k
=0; k
<24; k
++) {
534 key
[k
] = odd_parity(key
[k
]);
539 * Perform the Monte Carlo Test
541 * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
542 * crypt = ENCRYPT || DECRYPT
543 * inputtext = plaintext or Cyphertext depending on the value of crypt
544 * inputlength is expected to be size 8 bytes
545 * iv = needs to be set for NSS_DES_EDE3_CBC mode
546 * resp = is the output response file.
549 tdea_mct_test(int mode
, unsigned char* key
, unsigned int numKeys
,
550 unsigned int crypt
, unsigned char* inputtext
,
551 unsigned int inputlength
, unsigned char* iv
, FILE *resp
) {
554 unsigned char outputtext_1
[8]; /* PT/CT[j-1] */
555 unsigned char outputtext_2
[8]; /* PT/CT[j-2] */
556 char buf
[80]; /* holds one line from the input REQUEST file. */
557 unsigned int outputlen
;
558 unsigned char outputtext
[8];
563 if (mode
== NSS_DES_EDE3
&& iv
!= NULL
) {
564 printf("IV must be NULL for NSS_DES_EDE3 mode");
566 } else if (mode
== NSS_DES_EDE3_CBC
&& iv
== NULL
) {
567 printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
572 for (i
=0; i
<400; i
++) {
573 /* if i == 0 CV[0] = IV not necessary */
574 /* record the count and key values and plainText */
575 sprintf(buf
, "COUNT = %d\n", i
);
578 fputs("KEY1 = ", resp
);
579 to_hex_str(buf
, key
, 8);
583 fputs("KEY2 = ", resp
);
584 to_hex_str(buf
, &key
[8], 8);
588 fputs("KEY3 = ", resp
);
589 to_hex_str(buf
, &key
[16], 8);
592 if (mode
== NSS_DES_EDE3_CBC
) {
594 fputs("IV = ", resp
);
595 to_hex_str(buf
, iv
, 8);
599 if (crypt
== ENCRYPT
) {
601 fputs("PLAINTEXT = ", resp
);
604 fputs("CIPHERTEXT = ", resp
);
607 to_hex_str(buf
, inputtext
, inputlength
);
611 /* loop 10,000 times */
612 for (j
=0; j
<10000; j
++) {
615 if (crypt
== ENCRYPT
) {
616 /* inputtext == ciphertext outputtext == plaintext*/
617 rv
= tdea_encrypt_buf(mode
, key
,
618 (mode
== NSS_DES_EDE3
) ? NULL
: iv
,
619 outputtext
, &outputlen
, 8,
622 /* inputtext == plaintext outputtext == ciphertext */
623 rv
= tdea_decrypt_buf(mode
, key
,
624 (mode
== NSS_DES_EDE3
) ? NULL
: iv
,
625 outputtext
, &outputlen
, 8,
629 if (rv
!= SECSuccess
) {
632 if (outputlen
!= inputlength
) {
636 if (mode
== NSS_DES_EDE3_CBC
) {
637 if (crypt
== ENCRYPT
) {
640 memcpy(inputtext
, iv
, 8);
642 /* p[j+1] = C[j-1] */
643 memcpy(inputtext
, outputtext_1
, 8);
646 memcpy(iv
, outputtext
, 8);
649 memcpy(outputtext_1
, outputtext
, 8);
651 } else { /* DECRYPT */
653 memcpy(iv
, inputtext
, 8);
655 memcpy(inputtext
, outputtext
, 8);
658 /* ECB mode PT/CT[j+1] = CT/PT[j] */
659 memcpy(inputtext
, outputtext
, 8);
662 /* Save PT/CT[j-2] and PT/CT[j-1] */
663 if (j
==9997) memcpy(outputtext_2
, outputtext
, 8);
664 if (j
==9998) memcpy(outputtext_1
, outputtext
, 8);
665 /* done at the end of the for(j) loop */
669 if (crypt
== ENCRYPT
) {
671 fputs("CIPHERTEXT = ", resp
);
674 fputs("PLAINTEXT = ", resp
);
676 to_hex_str(buf
, outputtext
, 8);
680 /* Key[i+1] = Key[i] xor ... outputtext_2 == PT/CT[j-2]
681 * outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j]
683 tdea_mct_next_keys(key
, outputtext_2
,
684 outputtext_1
, outputtext
, numKeys
);
686 if (mode
== NSS_DES_EDE3_CBC
) {
687 /* taken care of in the j=9999 iteration */
688 if (crypt
== ENCRYPT
) {
692 /* taken care of in the j=9999 iteration */
697 /* ECB PT/CT[i] = PT/CT[j] */
698 memcpy(inputtext
, outputtext
, 8);
700 /* done at the end of the for(i) loop */
709 * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
710 * by gathering the input from the request file, and then
711 * calling tdea_mct_test.
713 * reqfn is the pathname of the input REQUEST file.
715 * The output RESPONSE file is written to stdout.
718 tdea_mct(int mode
, char *reqfn
)
721 char buf
[80]; /* holds one line from the input REQUEST file. */
722 FILE *req
; /* input stream from the REQUEST file */
723 FILE *resp
; /* output stream to the RESPONSE file */
724 unsigned int crypt
= 0; /* 1 means encrypt, 0 means decrypt */
725 unsigned char key
[24]; /* TDEA 3 key bundle */
726 unsigned int numKeys
= 0;
727 unsigned char plaintext
[8]; /* PT[j] */
728 unsigned char ciphertext
[8]; /* CT[j] */
731 /* zeroize the variables for the test with this data set */
732 memset(key
, 0, sizeof key
);
733 memset(plaintext
, 0, sizeof plaintext
);
734 memset(ciphertext
, 0, sizeof ciphertext
);
735 memset(iv
, 0, sizeof iv
);
737 req
= fopen(reqfn
, "r");
739 while (fgets(buf
, sizeof buf
, req
) != NULL
) {
740 /* a comment or blank line */
741 if (buf
[0] == '#' || buf
[0] == '\n') {
745 /* [ENCRYPT] or [DECRYPT] */
747 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
756 if (strncmp(&buf
[0], "NumKeys", 7) == 0) {
758 while (isspace(buf
[i
]) || buf
[i
] == '=') {
761 numKeys
= atoi(&buf
[i
]);
765 if (strncmp(buf
, "KEY1", 4) == 0) {
767 while (isspace(buf
[i
]) || buf
[i
] == '=') {
770 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
771 hex_to_byteval(&buf
[i
], &key
[j
]);
776 if (strncmp(buf
, "KEY2", 4) == 0) {
778 while (isspace(buf
[i
]) || buf
[i
] == '=') {
781 for (j
=8; isxdigit(buf
[i
]); i
+=2,j
++) {
782 hex_to_byteval(&buf
[i
], &key
[j
]);
787 if (strncmp(buf
, "KEY3", 4) == 0) {
789 while (isspace(buf
[i
]) || buf
[i
] == '=') {
792 for (j
=16; isxdigit(buf
[i
]); i
+=2,j
++) {
793 hex_to_byteval(&buf
[i
], &key
[j
]);
799 if (strncmp(buf
, "IV", 2) == 0) {
801 while (isspace(buf
[i
]) || buf
[i
] == '=') {
804 for (j
=0; j
<sizeof iv
; i
+=2,j
++) {
805 hex_to_byteval(&buf
[i
], &iv
[j
]);
810 /* PLAINTEXT = ... */
811 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
814 if (crypt
!= ENCRYPT
) {
819 while (isspace(buf
[i
]) || buf
[i
] == '=') {
822 for (j
=0; j
<sizeof plaintext
; i
+=2,j
++) {
823 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
826 /* do the Monte Carlo test */
827 if (mode
==NSS_DES_EDE3
) {
828 tdea_mct_test(NSS_DES_EDE3
, key
, numKeys
, crypt
, plaintext
, sizeof plaintext
, NULL
, resp
);
830 tdea_mct_test(NSS_DES_EDE3_CBC
, key
, numKeys
, crypt
, plaintext
, sizeof plaintext
, iv
, resp
);
834 /* CIPHERTEXT = ... */
835 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
837 if (crypt
!= DECRYPT
) {
842 while (isspace(buf
[i
]) || buf
[i
] == '=') {
845 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
846 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
849 /* do the Monte Carlo test */
850 if (mode
==NSS_DES_EDE3
) {
851 tdea_mct_test(NSS_DES_EDE3
, key
, numKeys
, crypt
, ciphertext
, sizeof ciphertext
, NULL
, resp
);
853 tdea_mct_test(NSS_DES_EDE3_CBC
, key
, numKeys
, crypt
, ciphertext
, sizeof ciphertext
, iv
, resp
);
867 const unsigned char *key
, unsigned int keysize
,
868 const unsigned char *iv
,
869 unsigned char *output
, unsigned int *outputlen
, unsigned int maxoutputlen
,
870 const unsigned char *input
, unsigned int inputlen
)
872 SECStatus rv
= SECFailure
;
874 unsigned char doublecheck
[10*16]; /* 1 to 10 blocks */
875 unsigned int doublechecklen
= 0;
877 cx
= AES_CreateContext(key
, iv
, mode
, PR_TRUE
, keysize
, 16);
881 rv
= AES_Encrypt(cx
, output
, outputlen
, maxoutputlen
, input
, inputlen
);
882 if (rv
!= SECSuccess
) {
885 if (*outputlen
!= inputlen
) {
888 AES_DestroyContext(cx
, PR_TRUE
);
892 * Doublecheck our result by decrypting the ciphertext and
893 * compare the output with the input plaintext.
895 cx
= AES_CreateContext(key
, iv
, mode
, PR_FALSE
, keysize
, 16);
899 rv
= AES_Decrypt(cx
, doublecheck
, &doublechecklen
, sizeof doublecheck
,
901 if (rv
!= SECSuccess
) {
904 if (doublechecklen
!= *outputlen
) {
907 AES_DestroyContext(cx
, PR_TRUE
);
909 if (memcmp(doublecheck
, input
, inputlen
) != 0) {
916 AES_DestroyContext(cx
, PR_TRUE
);
924 const unsigned char *key
, unsigned int keysize
,
925 const unsigned char *iv
,
926 unsigned char *output
, unsigned int *outputlen
, unsigned int maxoutputlen
,
927 const unsigned char *input
, unsigned int inputlen
)
929 SECStatus rv
= SECFailure
;
931 unsigned char doublecheck
[10*16]; /* 1 to 10 blocks */
932 unsigned int doublechecklen
= 0;
934 cx
= AES_CreateContext(key
, iv
, mode
, PR_FALSE
, keysize
, 16);
938 rv
= AES_Decrypt(cx
, output
, outputlen
, maxoutputlen
,
940 if (rv
!= SECSuccess
) {
943 if (*outputlen
!= inputlen
) {
946 AES_DestroyContext(cx
, PR_TRUE
);
950 * Doublecheck our result by encrypting the plaintext and
951 * compare the output with the input ciphertext.
953 cx
= AES_CreateContext(key
, iv
, mode
, PR_TRUE
, keysize
, 16);
957 rv
= AES_Encrypt(cx
, doublecheck
, &doublechecklen
, sizeof doublecheck
,
959 if (rv
!= SECSuccess
) {
962 if (doublechecklen
!= *outputlen
) {
965 AES_DestroyContext(cx
, PR_TRUE
);
967 if (memcmp(doublecheck
, input
, inputlen
) != 0) {
974 AES_DestroyContext(cx
, PR_TRUE
);
980 * Perform the AES Known Answer Test (KAT) or Multi-block Message
981 * Test (MMT) in ECB or CBC mode. The KAT (there are four types)
982 * and MMT have the same structure: given the key and IV (CBC mode
983 * only), encrypt the given plaintext or decrypt the given ciphertext.
984 * So we can handle them the same way.
986 * reqfn is the pathname of the REQUEST file.
988 * The output RESPONSE file is written to stdout.
991 aes_kat_mmt(char *reqfn
)
993 char buf
[512]; /* holds one line from the input REQUEST file.
994 * needs to be large enough to hold the longest
995 * line "CIPHERTEXT = <320 hex digits>\n".
997 FILE *aesreq
; /* input stream from the REQUEST file */
998 FILE *aesresp
; /* output stream to the RESPONSE file */
1000 int mode
; /* NSS_AES (ECB) or NSS_AES_CBC */
1001 int encrypt
= 0; /* 1 means encrypt, 0 means decrypt */
1002 unsigned char key
[32]; /* 128, 192, or 256 bits */
1003 unsigned int keysize
;
1004 unsigned char iv
[16]; /* for all modes except ECB */
1005 unsigned char plaintext
[10*16]; /* 1 to 10 blocks */
1006 unsigned int plaintextlen
;
1007 unsigned char ciphertext
[10*16]; /* 1 to 10 blocks */
1008 unsigned int ciphertextlen
;
1011 aesreq
= fopen(reqfn
, "r");
1013 while (fgets(buf
, sizeof buf
, aesreq
) != NULL
) {
1014 /* a comment or blank line */
1015 if (buf
[0] == '#' || buf
[0] == '\n') {
1016 fputs(buf
, aesresp
);
1019 /* [ENCRYPT] or [DECRYPT] */
1020 if (buf
[0] == '[') {
1021 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
1026 fputs(buf
, aesresp
);
1029 /* "COUNT = x" begins a new data set */
1030 if (strncmp(buf
, "COUNT", 5) == 0) {
1032 /* zeroize the variables for the test with this data set */
1033 memset(key
, 0, sizeof key
);
1035 memset(iv
, 0, sizeof iv
);
1036 memset(plaintext
, 0, sizeof plaintext
);
1038 memset(ciphertext
, 0, sizeof ciphertext
);
1040 fputs(buf
, aesresp
);
1044 if (strncmp(buf
, "KEY", 3) == 0) {
1046 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1049 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1050 hex_to_byteval(&buf
[i
], &key
[j
]);
1053 fputs(buf
, aesresp
);
1057 if (strncmp(buf
, "IV", 2) == 0) {
1060 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1063 for (j
=0; j
<sizeof iv
; i
+=2,j
++) {
1064 hex_to_byteval(&buf
[i
], &iv
[j
]);
1066 fputs(buf
, aesresp
);
1069 /* PLAINTEXT = ... */
1070 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
1077 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1080 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1081 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
1085 rv
= aes_encrypt_buf(mode
, key
, keysize
,
1086 (mode
== NSS_AES
) ? NULL
: iv
,
1087 ciphertext
, &ciphertextlen
, sizeof ciphertext
,
1088 plaintext
, plaintextlen
);
1089 if (rv
!= SECSuccess
) {
1093 fputs(buf
, aesresp
);
1094 fputs("CIPHERTEXT = ", aesresp
);
1095 to_hex_str(buf
, ciphertext
, ciphertextlen
);
1096 fputs(buf
, aesresp
);
1097 fputc('\n', aesresp
);
1100 /* CIPHERTEXT = ... */
1101 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
1108 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1111 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1112 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
1116 rv
= aes_decrypt_buf(mode
, key
, keysize
,
1117 (mode
== NSS_AES
) ? NULL
: iv
,
1118 plaintext
, &plaintextlen
, sizeof plaintext
,
1119 ciphertext
, ciphertextlen
);
1120 if (rv
!= SECSuccess
) {
1124 fputs(buf
, aesresp
);
1125 fputs("PLAINTEXT = ", aesresp
);
1126 to_hex_str(buf
, plaintext
, plaintextlen
);
1127 fputs(buf
, aesresp
);
1128 fputc('\n', aesresp
);
1137 * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
1138 * Test (MCT) in ECB and CBC modes.
1141 aes_mct_next_key(unsigned char *key
, unsigned int keysize
,
1142 const unsigned char *ciphertext_1
, const unsigned char *ciphertext
)
1147 case 16: /* 128-bit key */
1148 /* Key[i+1] = Key[i] xor CT[j] */
1149 for (k
=0; k
<16; k
++) {
1150 key
[k
] ^= ciphertext
[k
];
1153 case 24: /* 192-bit key */
1155 * Key[i+1] = Key[i] xor (last 64-bits of
1158 for (k
=0; k
<8; k
++) {
1159 key
[k
] ^= ciphertext_1
[k
+8];
1161 for (k
=8; k
<24; k
++) {
1162 key
[k
] ^= ciphertext
[k
-8];
1165 case 32: /* 256-bit key */
1166 /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
1167 for (k
=0; k
<16; k
++) {
1168 key
[k
] ^= ciphertext_1
[k
];
1170 for (k
=16; k
<32; k
++) {
1171 key
[k
] ^= ciphertext
[k
-16];
1178 * Perform the AES Monte Carlo Test (MCT) in ECB mode. MCT exercises
1179 * our AES code in streaming mode because the plaintext or ciphertext
1180 * is generated block by block as we go, so we can't collect all the
1181 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1184 * reqfn is the pathname of the input REQUEST file.
1186 * The output RESPONSE file is written to stdout.
1189 aes_ecb_mct(char *reqfn
)
1191 char buf
[80]; /* holds one line from the input REQUEST file.
1192 * needs to be large enough to hold the longest
1193 * line "KEY = <64 hex digits>\n".
1195 FILE *aesreq
; /* input stream from the REQUEST file */
1196 FILE *aesresp
; /* output stream to the RESPONSE file */
1198 int encrypt
= 0; /* 1 means encrypt, 0 means decrypt */
1199 unsigned char key
[32]; /* 128, 192, or 256 bits */
1200 unsigned int keysize
;
1201 unsigned char plaintext
[16]; /* PT[j] */
1202 unsigned char plaintext_1
[16]; /* PT[j-1] */
1203 unsigned char ciphertext
[16]; /* CT[j] */
1204 unsigned char ciphertext_1
[16]; /* CT[j-1] */
1205 unsigned char doublecheck
[16];
1206 unsigned int outputlen
;
1207 AESContext
*cx
= NULL
; /* the operation being tested */
1208 AESContext
*cx2
= NULL
; /* the inverse operation done in parallel
1209 * to doublecheck our result.
1213 aesreq
= fopen(reqfn
, "r");
1215 while (fgets(buf
, sizeof buf
, aesreq
) != NULL
) {
1216 /* a comment or blank line */
1217 if (buf
[0] == '#' || buf
[0] == '\n') {
1218 fputs(buf
, aesresp
);
1221 /* [ENCRYPT] or [DECRYPT] */
1222 if (buf
[0] == '[') {
1223 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
1228 fputs(buf
, aesresp
);
1231 /* "COUNT = x" begins a new data set */
1232 if (strncmp(buf
, "COUNT", 5) == 0) {
1233 /* zeroize the variables for the test with this data set */
1234 memset(key
, 0, sizeof key
);
1236 memset(plaintext
, 0, sizeof plaintext
);
1237 memset(ciphertext
, 0, sizeof ciphertext
);
1241 if (strncmp(buf
, "KEY", 3) == 0) {
1244 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1247 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1248 hex_to_byteval(&buf
[i
], &key
[j
]);
1253 /* PLAINTEXT = ... */
1254 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
1261 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1264 for (j
=0; j
<sizeof plaintext
; i
+=2,j
++) {
1265 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
1268 for (i
=0; i
<100; i
++) {
1269 sprintf(buf
, "COUNT = %d\n", i
);
1270 fputs(buf
, aesresp
);
1272 fputs("KEY = ", aesresp
);
1273 to_hex_str(buf
, key
, keysize
);
1274 fputs(buf
, aesresp
);
1275 fputc('\n', aesresp
);
1277 fputs("PLAINTEXT = ", aesresp
);
1278 to_hex_str(buf
, plaintext
, sizeof plaintext
);
1279 fputs(buf
, aesresp
);
1280 fputc('\n', aesresp
);
1282 cx
= AES_CreateContext(key
, NULL
, NSS_AES
,
1283 PR_TRUE
, keysize
, 16);
1288 * doublecheck our result by decrypting the result
1289 * and comparing the output with the plaintext.
1291 cx2
= AES_CreateContext(key
, NULL
, NSS_AES
,
1292 PR_FALSE
, keysize
, 16);
1296 for (j
=0; j
<1000; j
++) {
1298 memcpy(ciphertext_1
, ciphertext
, sizeof ciphertext
);
1300 /* CT[j] = AES(Key[i], PT[j]) */
1302 rv
= AES_Encrypt(cx
,
1303 ciphertext
, &outputlen
, sizeof ciphertext
,
1304 plaintext
, sizeof plaintext
);
1305 if (rv
!= SECSuccess
) {
1308 if (outputlen
!= sizeof plaintext
) {
1312 /* doublecheck our result */
1314 rv
= AES_Decrypt(cx2
,
1315 doublecheck
, &outputlen
, sizeof doublecheck
,
1316 ciphertext
, sizeof ciphertext
);
1317 if (rv
!= SECSuccess
) {
1320 if (outputlen
!= sizeof ciphertext
) {
1323 if (memcmp(doublecheck
, plaintext
, sizeof plaintext
)) {
1327 /* PT[j+1] = CT[j] */
1328 memcpy(plaintext
, ciphertext
, sizeof plaintext
);
1330 AES_DestroyContext(cx
, PR_TRUE
);
1332 AES_DestroyContext(cx2
, PR_TRUE
);
1336 fputs("CIPHERTEXT = ", aesresp
);
1337 to_hex_str(buf
, ciphertext
, sizeof ciphertext
);
1338 fputs(buf
, aesresp
);
1339 fputc('\n', aesresp
);
1341 /* Key[i+1] = Key[i] xor ... */
1342 aes_mct_next_key(key
, keysize
, ciphertext_1
, ciphertext
);
1344 /* done at the end of the for(j) loop */
1346 fputc('\n', aesresp
);
1351 /* CIPHERTEXT = ... */
1352 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
1359 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1362 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1363 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
1366 for (i
=0; i
<100; i
++) {
1367 sprintf(buf
, "COUNT = %d\n", i
);
1368 fputs(buf
, aesresp
);
1370 fputs("KEY = ", aesresp
);
1371 to_hex_str(buf
, key
, keysize
);
1372 fputs(buf
, aesresp
);
1373 fputc('\n', aesresp
);
1375 fputs("CIPHERTEXT = ", aesresp
);
1376 to_hex_str(buf
, ciphertext
, sizeof ciphertext
);
1377 fputs(buf
, aesresp
);
1378 fputc('\n', aesresp
);
1380 cx
= AES_CreateContext(key
, NULL
, NSS_AES
,
1381 PR_FALSE
, keysize
, 16);
1386 * doublecheck our result by encrypting the result
1387 * and comparing the output with the ciphertext.
1389 cx2
= AES_CreateContext(key
, NULL
, NSS_AES
,
1390 PR_TRUE
, keysize
, 16);
1394 for (j
=0; j
<1000; j
++) {
1396 memcpy(plaintext_1
, plaintext
, sizeof plaintext
);
1398 /* PT[j] = AES(Key[i], CT[j]) */
1400 rv
= AES_Decrypt(cx
,
1401 plaintext
, &outputlen
, sizeof plaintext
,
1402 ciphertext
, sizeof ciphertext
);
1403 if (rv
!= SECSuccess
) {
1406 if (outputlen
!= sizeof ciphertext
) {
1410 /* doublecheck our result */
1412 rv
= AES_Encrypt(cx2
,
1413 doublecheck
, &outputlen
, sizeof doublecheck
,
1414 plaintext
, sizeof plaintext
);
1415 if (rv
!= SECSuccess
) {
1418 if (outputlen
!= sizeof plaintext
) {
1421 if (memcmp(doublecheck
, ciphertext
, sizeof ciphertext
)) {
1425 /* CT[j+1] = PT[j] */
1426 memcpy(ciphertext
, plaintext
, sizeof ciphertext
);
1428 AES_DestroyContext(cx
, PR_TRUE
);
1430 AES_DestroyContext(cx2
, PR_TRUE
);
1434 fputs("PLAINTEXT = ", aesresp
);
1435 to_hex_str(buf
, plaintext
, sizeof plaintext
);
1436 fputs(buf
, aesresp
);
1437 fputc('\n', aesresp
);
1439 /* Key[i+1] = Key[i] xor ... */
1440 aes_mct_next_key(key
, keysize
, plaintext_1
, plaintext
);
1442 /* done at the end of the for(j) loop */
1444 fputc('\n', aesresp
);
1452 AES_DestroyContext(cx
, PR_TRUE
);
1455 AES_DestroyContext(cx2
, PR_TRUE
);
1461 * Perform the AES Monte Carlo Test (MCT) in CBC mode. MCT exercises
1462 * our AES code in streaming mode because the plaintext or ciphertext
1463 * is generated block by block as we go, so we can't collect all the
1464 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1467 * reqfn is the pathname of the input REQUEST file.
1469 * The output RESPONSE file is written to stdout.
1472 aes_cbc_mct(char *reqfn
)
1474 char buf
[80]; /* holds one line from the input REQUEST file.
1475 * needs to be large enough to hold the longest
1476 * line "KEY = <64 hex digits>\n".
1478 FILE *aesreq
; /* input stream from the REQUEST file */
1479 FILE *aesresp
; /* output stream to the RESPONSE file */
1481 int encrypt
= 0; /* 1 means encrypt, 0 means decrypt */
1482 unsigned char key
[32]; /* 128, 192, or 256 bits */
1483 unsigned int keysize
;
1484 unsigned char iv
[16];
1485 unsigned char plaintext
[16]; /* PT[j] */
1486 unsigned char plaintext_1
[16]; /* PT[j-1] */
1487 unsigned char ciphertext
[16]; /* CT[j] */
1488 unsigned char ciphertext_1
[16]; /* CT[j-1] */
1489 unsigned char doublecheck
[16];
1490 unsigned int outputlen
;
1491 AESContext
*cx
= NULL
; /* the operation being tested */
1492 AESContext
*cx2
= NULL
; /* the inverse operation done in parallel
1493 * to doublecheck our result.
1497 aesreq
= fopen(reqfn
, "r");
1499 while (fgets(buf
, sizeof buf
, aesreq
) != NULL
) {
1500 /* a comment or blank line */
1501 if (buf
[0] == '#' || buf
[0] == '\n') {
1502 fputs(buf
, aesresp
);
1505 /* [ENCRYPT] or [DECRYPT] */
1506 if (buf
[0] == '[') {
1507 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
1512 fputs(buf
, aesresp
);
1515 /* "COUNT = x" begins a new data set */
1516 if (strncmp(buf
, "COUNT", 5) == 0) {
1517 /* zeroize the variables for the test with this data set */
1518 memset(key
, 0, sizeof key
);
1520 memset(iv
, 0, sizeof iv
);
1521 memset(plaintext
, 0, sizeof plaintext
);
1522 memset(ciphertext
, 0, sizeof ciphertext
);
1526 if (strncmp(buf
, "KEY", 3) == 0) {
1529 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1532 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1533 hex_to_byteval(&buf
[i
], &key
[j
]);
1539 if (strncmp(buf
, "IV", 2) == 0) {
1542 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1545 for (j
=0; j
<sizeof iv
; i
+=2,j
++) {
1546 hex_to_byteval(&buf
[i
], &iv
[j
]);
1550 /* PLAINTEXT = ... */
1551 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
1558 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1561 for (j
=0; j
<sizeof plaintext
; i
+=2,j
++) {
1562 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
1565 for (i
=0; i
<100; i
++) {
1566 sprintf(buf
, "COUNT = %d\n", i
);
1567 fputs(buf
, aesresp
);
1569 fputs("KEY = ", aesresp
);
1570 to_hex_str(buf
, key
, keysize
);
1571 fputs(buf
, aesresp
);
1572 fputc('\n', aesresp
);
1574 fputs("IV = ", aesresp
);
1575 to_hex_str(buf
, iv
, sizeof iv
);
1576 fputs(buf
, aesresp
);
1577 fputc('\n', aesresp
);
1579 fputs("PLAINTEXT = ", aesresp
);
1580 to_hex_str(buf
, plaintext
, sizeof plaintext
);
1581 fputs(buf
, aesresp
);
1582 fputc('\n', aesresp
);
1584 cx
= AES_CreateContext(key
, iv
, NSS_AES_CBC
,
1585 PR_TRUE
, keysize
, 16);
1590 * doublecheck our result by decrypting the result
1591 * and comparing the output with the plaintext.
1593 cx2
= AES_CreateContext(key
, iv
, NSS_AES_CBC
,
1594 PR_FALSE
, keysize
, 16);
1598 /* CT[-1] = IV[i] */
1599 memcpy(ciphertext
, iv
, sizeof ciphertext
);
1600 for (j
=0; j
<1000; j
++) {
1602 memcpy(ciphertext_1
, ciphertext
, sizeof ciphertext
);
1605 * CT[j] = AES(Key[i], IV[i], PT[j])
1606 * PT[j+1] = IV[i] (= CT[j-1])
1608 * CT[j] = AES(Key[i], PT[j])
1612 rv
= AES_Encrypt(cx
,
1613 ciphertext
, &outputlen
, sizeof ciphertext
,
1614 plaintext
, sizeof plaintext
);
1615 if (rv
!= SECSuccess
) {
1618 if (outputlen
!= sizeof plaintext
) {
1622 /* doublecheck our result */
1624 rv
= AES_Decrypt(cx2
,
1625 doublecheck
, &outputlen
, sizeof doublecheck
,
1626 ciphertext
, sizeof ciphertext
);
1627 if (rv
!= SECSuccess
) {
1630 if (outputlen
!= sizeof ciphertext
) {
1633 if (memcmp(doublecheck
, plaintext
, sizeof plaintext
)) {
1637 memcpy(plaintext
, ciphertext_1
, sizeof plaintext
);
1639 AES_DestroyContext(cx
, PR_TRUE
);
1641 AES_DestroyContext(cx2
, PR_TRUE
);
1645 fputs("CIPHERTEXT = ", aesresp
);
1646 to_hex_str(buf
, ciphertext
, sizeof ciphertext
);
1647 fputs(buf
, aesresp
);
1648 fputc('\n', aesresp
);
1650 /* Key[i+1] = Key[i] xor ... */
1651 aes_mct_next_key(key
, keysize
, ciphertext_1
, ciphertext
);
1652 /* IV[i+1] = CT[j] */
1653 memcpy(iv
, ciphertext
, sizeof iv
);
1654 /* PT[0] = CT[j-1] */
1655 /* done at the end of the for(j) loop */
1657 fputc('\n', aesresp
);
1662 /* CIPHERTEXT = ... */
1663 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
1670 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1673 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1674 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
1677 for (i
=0; i
<100; i
++) {
1678 sprintf(buf
, "COUNT = %d\n", i
);
1679 fputs(buf
, aesresp
);
1681 fputs("KEY = ", aesresp
);
1682 to_hex_str(buf
, key
, keysize
);
1683 fputs(buf
, aesresp
);
1684 fputc('\n', aesresp
);
1686 fputs("IV = ", aesresp
);
1687 to_hex_str(buf
, iv
, sizeof iv
);
1688 fputs(buf
, aesresp
);
1689 fputc('\n', aesresp
);
1691 fputs("CIPHERTEXT = ", aesresp
);
1692 to_hex_str(buf
, ciphertext
, sizeof ciphertext
);
1693 fputs(buf
, aesresp
);
1694 fputc('\n', aesresp
);
1696 cx
= AES_CreateContext(key
, iv
, NSS_AES_CBC
,
1697 PR_FALSE
, keysize
, 16);
1702 * doublecheck our result by encrypting the result
1703 * and comparing the output with the ciphertext.
1705 cx2
= AES_CreateContext(key
, iv
, NSS_AES_CBC
,
1706 PR_TRUE
, keysize
, 16);
1710 /* PT[-1] = IV[i] */
1711 memcpy(plaintext
, iv
, sizeof plaintext
);
1712 for (j
=0; j
<1000; j
++) {
1714 memcpy(plaintext_1
, plaintext
, sizeof plaintext
);
1717 * PT[j] = AES(Key[i], IV[i], CT[j])
1718 * CT[j+1] = IV[i] (= PT[j-1])
1720 * PT[j] = AES(Key[i], CT[j])
1724 rv
= AES_Decrypt(cx
,
1725 plaintext
, &outputlen
, sizeof plaintext
,
1726 ciphertext
, sizeof ciphertext
);
1727 if (rv
!= SECSuccess
) {
1730 if (outputlen
!= sizeof ciphertext
) {
1734 /* doublecheck our result */
1736 rv
= AES_Encrypt(cx2
,
1737 doublecheck
, &outputlen
, sizeof doublecheck
,
1738 plaintext
, sizeof plaintext
);
1739 if (rv
!= SECSuccess
) {
1742 if (outputlen
!= sizeof plaintext
) {
1745 if (memcmp(doublecheck
, ciphertext
, sizeof ciphertext
)) {
1749 memcpy(ciphertext
, plaintext_1
, sizeof ciphertext
);
1751 AES_DestroyContext(cx
, PR_TRUE
);
1753 AES_DestroyContext(cx2
, PR_TRUE
);
1757 fputs("PLAINTEXT = ", aesresp
);
1758 to_hex_str(buf
, plaintext
, sizeof plaintext
);
1759 fputs(buf
, aesresp
);
1760 fputc('\n', aesresp
);
1762 /* Key[i+1] = Key[i] xor ... */
1763 aes_mct_next_key(key
, keysize
, plaintext_1
, plaintext
);
1764 /* IV[i+1] = PT[j] */
1765 memcpy(iv
, plaintext
, sizeof iv
);
1766 /* CT[0] = PT[j-1] */
1767 /* done at the end of the for(j) loop */
1769 fputc('\n', aesresp
);
1777 AES_DestroyContext(cx
, PR_TRUE
);
1780 AES_DestroyContext(cx2
, PR_TRUE
);
1785 void write_compact_string(FILE *out
, unsigned char *hash
, unsigned int len
)
1788 int j
, count
= 0, last
= -1, z
= 0;
1789 long start
= ftell(out
);
1790 for (i
=0; i
<len
; i
++) {
1791 for (j
=7; j
>=0; j
--) {
1793 last
= (hash
[i
] & (1 << j
)) ? 1 : 0;
1794 fprintf(out
, "%d ", last
);
1796 } else if (hash
[i
] & (1 << j
)) {
1801 fprintf(out
, "%d ", count
);
1810 fprintf(out
, "%d ", count
);
1817 fprintf(out
, "^\n");
1818 fseek(out
, start
, SEEK_SET
);
1819 fprintf(out
, "%d ", z
);
1820 fseek(out
, 0, SEEK_END
);
1823 int get_next_line(FILE *req
, char *key
, char *val
, FILE *rsp
)
1826 char *writeto
= key
;
1829 while ((c
= fgetc(req
)) != EOF
) {
1831 fprintf(rsp
, "%c", c
);
1832 if (c
== '\n') return ignore
;
1833 } else if (c
== '\n') {
1835 } else if (c
== '#') {
1837 fprintf(rsp
, "%c", c
);
1838 } else if (c
== '=') {
1842 } else if (c
== ' ' || c
== '[' || c
== ']') {
1849 return (c
== EOF
) ? -1 : ignore
;
1852 #ifndef NSS_DISABLE_ECC
1853 typedef struct curveNameTagPairStr
{
1855 SECOidTag curveOidTag
;
1858 #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
1859 /* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */
1861 static CurveNameTagPair nameTagPair
[] =
1863 { "sect163k1", SEC_OID_SECG_EC_SECT163K1
},
1864 { "nistk163", SEC_OID_SECG_EC_SECT163K1
},
1865 { "sect163r1", SEC_OID_SECG_EC_SECT163R1
},
1866 { "sect163r2", SEC_OID_SECG_EC_SECT163R2
},
1867 { "nistb163", SEC_OID_SECG_EC_SECT163R2
},
1868 { "sect193r1", SEC_OID_SECG_EC_SECT193R1
},
1869 { "sect193r2", SEC_OID_SECG_EC_SECT193R2
},
1870 { "sect233k1", SEC_OID_SECG_EC_SECT233K1
},
1871 { "nistk233", SEC_OID_SECG_EC_SECT233K1
},
1872 { "sect233r1", SEC_OID_SECG_EC_SECT233R1
},
1873 { "nistb233", SEC_OID_SECG_EC_SECT233R1
},
1874 { "sect239k1", SEC_OID_SECG_EC_SECT239K1
},
1875 { "sect283k1", SEC_OID_SECG_EC_SECT283K1
},
1876 { "nistk283", SEC_OID_SECG_EC_SECT283K1
},
1877 { "sect283r1", SEC_OID_SECG_EC_SECT283R1
},
1878 { "nistb283", SEC_OID_SECG_EC_SECT283R1
},
1879 { "sect409k1", SEC_OID_SECG_EC_SECT409K1
},
1880 { "nistk409", SEC_OID_SECG_EC_SECT409K1
},
1881 { "sect409r1", SEC_OID_SECG_EC_SECT409R1
},
1882 { "nistb409", SEC_OID_SECG_EC_SECT409R1
},
1883 { "sect571k1", SEC_OID_SECG_EC_SECT571K1
},
1884 { "nistk571", SEC_OID_SECG_EC_SECT571K1
},
1885 { "sect571r1", SEC_OID_SECG_EC_SECT571R1
},
1886 { "nistb571", SEC_OID_SECG_EC_SECT571R1
},
1887 { "secp160k1", SEC_OID_SECG_EC_SECP160K1
},
1888 { "secp160r1", SEC_OID_SECG_EC_SECP160R1
},
1889 { "secp160r2", SEC_OID_SECG_EC_SECP160R2
},
1890 { "secp192k1", SEC_OID_SECG_EC_SECP192K1
},
1891 { "secp192r1", SEC_OID_SECG_EC_SECP192R1
},
1892 { "nistp192", SEC_OID_SECG_EC_SECP192R1
},
1893 { "secp224k1", SEC_OID_SECG_EC_SECP224K1
},
1894 { "secp224r1", SEC_OID_SECG_EC_SECP224R1
},
1895 { "nistp224", SEC_OID_SECG_EC_SECP224R1
},
1896 { "secp256k1", SEC_OID_SECG_EC_SECP256K1
},
1897 { "secp256r1", SEC_OID_SECG_EC_SECP256R1
},
1898 { "nistp256", SEC_OID_SECG_EC_SECP256R1
},
1899 { "secp384r1", SEC_OID_SECG_EC_SECP384R1
},
1900 { "nistp384", SEC_OID_SECG_EC_SECP384R1
},
1901 { "secp521r1", SEC_OID_SECG_EC_SECP521R1
},
1902 { "nistp521", SEC_OID_SECG_EC_SECP521R1
},
1904 { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1
},
1905 { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2
},
1906 { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3
},
1907 { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1
},
1908 { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2
},
1909 { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3
},
1911 { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1
},
1912 { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2
},
1913 { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3
},
1914 { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1
},
1915 { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1
},
1916 { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2
},
1917 { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3
},
1918 { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4
},
1919 { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5
},
1920 { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1
},
1921 { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1
},
1922 { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2
},
1923 { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3
},
1924 { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4
},
1925 { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5
},
1926 { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1
},
1927 { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1
},
1928 { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1
},
1929 { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1
},
1930 { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1
},
1932 { "secp112r1", SEC_OID_SECG_EC_SECP112R1
},
1933 { "secp112r2", SEC_OID_SECG_EC_SECP112R2
},
1934 { "secp128r1", SEC_OID_SECG_EC_SECP128R1
},
1935 { "secp128r2", SEC_OID_SECG_EC_SECP128R2
},
1937 { "sect113r1", SEC_OID_SECG_EC_SECT113R1
},
1938 { "sect113r2", SEC_OID_SECG_EC_SECT113R2
},
1939 { "sect131r1", SEC_OID_SECG_EC_SECT131R1
},
1940 { "sect131r2", SEC_OID_SECG_EC_SECT131R2
},
1944 getECParams(const char *curve
)
1947 SECOidData
*oidData
= NULL
;
1948 SECOidTag curveOidTag
= SEC_OID_UNKNOWN
; /* default */
1951 if (curve
!= NULL
) {
1952 numCurves
= sizeof(nameTagPair
)/sizeof(CurveNameTagPair
);
1953 for (i
= 0; ((i
< numCurves
) && (curveOidTag
== SEC_OID_UNKNOWN
));
1955 if (PL_strcmp(curve
, nameTagPair
[i
].curveName
) == 0)
1956 curveOidTag
= nameTagPair
[i
].curveOidTag
;
1960 /* Return NULL if curve name is not recognized */
1961 if ((curveOidTag
== SEC_OID_UNKNOWN
) ||
1962 (oidData
= SECOID_FindOIDByTag(curveOidTag
)) == NULL
) {
1963 fprintf(stderr
, "Unrecognized elliptic curve %s\n", curve
);
1967 ecparams
= SECITEM_AllocItem(NULL
, NULL
, (2 + oidData
->oid
.len
));
1970 * ecparams->data needs to contain the ASN encoding of an object ID (OID)
1971 * representing the named curve. The actual OID is in
1972 * oidData->oid.data so we simply prepend 0x06 and OID length
1974 ecparams
->data
[0] = SEC_ASN1_OBJECT_ID
;
1975 ecparams
->data
[1] = oidData
->oid
.len
;
1976 memcpy(ecparams
->data
+ 2, oidData
->oid
.data
, oidData
->oid
.len
);
1982 * Perform the ECDSA Key Pair Generation Test.
1984 * reqfn is the pathname of the REQUEST file.
1986 * The output RESPONSE file is written to stdout.
1989 ecdsa_keypair_test(char *reqfn
)
1991 char buf
[256]; /* holds one line from the input REQUEST file
1992 * or to the output RESPONSE file.
1993 * needs to be large enough to hold the longest
1994 * line "Qx = <144 hex digits>\n".
1996 FILE *ecdsareq
; /* input stream from the REQUEST file */
1997 FILE *ecdsaresp
; /* output stream to the RESPONSE file */
1998 char curve
[16]; /* "nistxddd" */
2004 ecdsareq
= fopen(reqfn
, "r");
2006 strcpy(curve
, "nist");
2007 while (fgets(buf
, sizeof buf
, ecdsareq
) != NULL
) {
2008 /* a comment or blank line */
2009 if (buf
[0] == '#' || buf
[0] == '\n') {
2010 fputs(buf
, ecdsaresp
);
2014 if (buf
[0] == '[') {
2017 SECItem
*encodedparams
;
2021 *dst
++ = tolower(*src
);
2022 src
+= 2; /* skip the hyphen */
2027 encodedparams
= getECParams(curve
);
2028 if (encodedparams
== NULL
) {
2031 if (EC_DecodeParams(encodedparams
, &ecparams
) != SECSuccess
) {
2034 SECITEM_FreeItem(encodedparams
, PR_TRUE
);
2035 fputs(buf
, ecdsaresp
);
2039 if (buf
[0] == 'N') {
2040 if (sscanf(buf
, "N = %d", &N
) != 1) {
2043 for (i
= 0; i
< N
; i
++) {
2044 ECPrivateKey
*ecpriv
;
2046 if (EC_NewKey(ecparams
, &ecpriv
) != SECSuccess
) {
2049 fputs("d = ", ecdsaresp
);
2050 to_hex_str(buf
, ecpriv
->privateValue
.data
,
2051 ecpriv
->privateValue
.len
);
2052 fputs(buf
, ecdsaresp
);
2053 fputc('\n', ecdsaresp
);
2054 if (EC_ValidatePublicKey(ecparams
, &ecpriv
->publicValue
)
2058 len
= ecpriv
->publicValue
.len
;
2063 if (ecpriv
->publicValue
.data
[0]
2064 != EC_POINT_FORM_UNCOMPRESSED
) {
2067 fputs("Qx = ", ecdsaresp
);
2068 to_hex_str(buf
, &ecpriv
->publicValue
.data
[1], len
);
2069 fputs(buf
, ecdsaresp
);
2070 fputc('\n', ecdsaresp
);
2071 fputs("Qy = ", ecdsaresp
);
2072 to_hex_str(buf
, &ecpriv
->publicValue
.data
[1+len
], len
);
2073 fputs(buf
, ecdsaresp
);
2074 fputc('\n', ecdsaresp
);
2075 fputc('\n', ecdsaresp
);
2076 PORT_FreeArena(ecpriv
->ecParams
.arena
, PR_TRUE
);
2078 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2087 * Perform the ECDSA Public Key Validation Test.
2089 * reqfn is the pathname of the REQUEST file.
2091 * The output RESPONSE file is written to stdout.
2094 ecdsa_pkv_test(char *reqfn
)
2096 char buf
[256]; /* holds one line from the input REQUEST file.
2097 * needs to be large enough to hold the longest
2098 * line "Qx = <144 hex digits>\n".
2100 FILE *ecdsareq
; /* input stream from the REQUEST file */
2101 FILE *ecdsaresp
; /* output stream to the RESPONSE file */
2102 char curve
[16]; /* "nistxddd" */
2103 ECParams
*ecparams
= NULL
;
2107 PRBool keyvalid
= PR_TRUE
;
2109 ecdsareq
= fopen(reqfn
, "r");
2111 strcpy(curve
, "nist");
2113 while (fgets(buf
, sizeof buf
, ecdsareq
) != NULL
) {
2114 /* a comment or blank line */
2115 if (buf
[0] == '#' || buf
[0] == '\n') {
2116 fputs(buf
, ecdsaresp
);
2120 if (buf
[0] == '[') {
2123 SECItem
*encodedparams
;
2127 *dst
++ = tolower(*src
);
2128 src
+= 2; /* skip the hyphen */
2133 if (ecparams
!= NULL
) {
2134 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2137 encodedparams
= getECParams(curve
);
2138 if (encodedparams
== NULL
) {
2141 if (EC_DecodeParams(encodedparams
, &ecparams
) != SECSuccess
) {
2144 SECITEM_FreeItem(encodedparams
, PR_TRUE
);
2145 len
= (ecparams
->fieldID
.size
+ 7) >> 3;
2146 if (pubkey
.data
!= NULL
) {
2147 PORT_Free(pubkey
.data
);
2150 SECITEM_AllocItem(NULL
, &pubkey
, 2*len
+1);
2151 if (pubkey
.data
== NULL
) {
2154 pubkey
.data
[0] = EC_POINT_FORM_UNCOMPRESSED
;
2155 fputs(buf
, ecdsaresp
);
2159 if (strncmp(buf
, "Qx", 2) == 0) {
2160 fputs(buf
, ecdsaresp
);
2162 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2165 keyvalid
= from_hex_str(&pubkey
.data
[1], len
, &buf
[i
]);
2169 if (strncmp(buf
, "Qy", 2) == 0) {
2170 fputs(buf
, ecdsaresp
);
2172 fputs("Result = F\n", ecdsaresp
);
2176 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2179 keyvalid
= from_hex_str(&pubkey
.data
[1+len
], len
, &buf
[i
]);
2181 fputs("Result = F\n", ecdsaresp
);
2184 if (EC_ValidatePublicKey(ecparams
, &pubkey
) == SECSuccess
) {
2185 fputs("Result = P\n", ecdsaresp
);
2186 } else if (PORT_GetError() == SEC_ERROR_BAD_KEY
) {
2187 fputs("Result = F\n", ecdsaresp
);
2195 if (ecparams
!= NULL
) {
2196 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2198 if (pubkey
.data
!= NULL
) {
2199 PORT_Free(pubkey
.data
);
2205 * Perform the ECDSA Signature Generation Test.
2207 * reqfn is the pathname of the REQUEST file.
2209 * The output RESPONSE file is written to stdout.
2212 ecdsa_siggen_test(char *reqfn
)
2214 char buf
[1024]; /* holds one line from the input REQUEST file
2215 * or to the output RESPONSE file.
2216 * needs to be large enough to hold the longest
2217 * line "Msg = <256 hex digits>\n".
2219 FILE *ecdsareq
; /* input stream from the REQUEST file */
2220 FILE *ecdsaresp
; /* output stream to the RESPONSE file */
2221 char curve
[16]; /* "nistxddd" */
2222 ECParams
*ecparams
= NULL
;
2225 unsigned char msg
[512]; /* message to be signed (<= 128 bytes) */
2226 unsigned int msglen
;
2227 unsigned char sha1
[20]; /* SHA-1 hash (160 bits) */
2228 unsigned char sig
[2*MAX_ECKEY_LEN
];
2229 SECItem signature
, digest
;
2231 ecdsareq
= fopen(reqfn
, "r");
2233 strcpy(curve
, "nist");
2234 while (fgets(buf
, sizeof buf
, ecdsareq
) != NULL
) {
2235 /* a comment or blank line */
2236 if (buf
[0] == '#' || buf
[0] == '\n') {
2237 fputs(buf
, ecdsaresp
);
2241 if (buf
[0] == '[') {
2244 SECItem
*encodedparams
;
2248 *dst
++ = tolower(*src
);
2249 src
+= 2; /* skip the hyphen */
2254 if (ecparams
!= NULL
) {
2255 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2258 encodedparams
= getECParams(curve
);
2259 if (encodedparams
== NULL
) {
2262 if (EC_DecodeParams(encodedparams
, &ecparams
) != SECSuccess
) {
2265 SECITEM_FreeItem(encodedparams
, PR_TRUE
);
2266 fputs(buf
, ecdsaresp
);
2270 if (strncmp(buf
, "Msg", 3) == 0) {
2271 ECPrivateKey
*ecpriv
;
2274 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2277 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
2278 hex_to_byteval(&buf
[i
], &msg
[j
]);
2281 if (SHA1_HashBuf(sha1
, msg
, msglen
) != SECSuccess
) {
2284 fputs(buf
, ecdsaresp
);
2286 if (EC_NewKey(ecparams
, &ecpriv
) != SECSuccess
) {
2289 if (EC_ValidatePublicKey(ecparams
, &ecpriv
->publicValue
)
2293 len
= ecpriv
->publicValue
.len
;
2298 if (ecpriv
->publicValue
.data
[0] != EC_POINT_FORM_UNCOMPRESSED
) {
2301 fputs("Qx = ", ecdsaresp
);
2302 to_hex_str(buf
, &ecpriv
->publicValue
.data
[1], len
);
2303 fputs(buf
, ecdsaresp
);
2304 fputc('\n', ecdsaresp
);
2305 fputs("Qy = ", ecdsaresp
);
2306 to_hex_str(buf
, &ecpriv
->publicValue
.data
[1+len
], len
);
2307 fputs(buf
, ecdsaresp
);
2308 fputc('\n', ecdsaresp
);
2310 digest
.type
= siBuffer
;
2312 digest
.len
= sizeof sha1
;
2313 signature
.type
= siBuffer
;
2314 signature
.data
= sig
;
2315 signature
.len
= sizeof sig
;
2316 if (ECDSA_SignDigest(ecpriv
, &signature
, &digest
) != SECSuccess
) {
2319 len
= signature
.len
;
2324 fputs("R = ", ecdsaresp
);
2325 to_hex_str(buf
, &signature
.data
[0], len
);
2326 fputs(buf
, ecdsaresp
);
2327 fputc('\n', ecdsaresp
);
2328 fputs("S = ", ecdsaresp
);
2329 to_hex_str(buf
, &signature
.data
[len
], len
);
2330 fputs(buf
, ecdsaresp
);
2331 fputc('\n', ecdsaresp
);
2333 PORT_FreeArena(ecpriv
->ecParams
.arena
, PR_TRUE
);
2338 if (ecparams
!= NULL
) {
2339 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2345 * Perform the ECDSA Signature Verification Test.
2347 * reqfn is the pathname of the REQUEST file.
2349 * The output RESPONSE file is written to stdout.
2352 ecdsa_sigver_test(char *reqfn
)
2354 char buf
[1024]; /* holds one line from the input REQUEST file.
2355 * needs to be large enough to hold the longest
2356 * line "Msg = <256 hex digits>\n".
2358 FILE *ecdsareq
; /* input stream from the REQUEST file */
2359 FILE *ecdsaresp
; /* output stream to the RESPONSE file */
2360 char curve
[16]; /* "nistxddd" */
2363 unsigned int flen
; /* length in bytes of the field size */
2364 unsigned int olen
; /* length in bytes of the base point order */
2365 unsigned char msg
[512]; /* message that was signed (<= 128 bytes) */
2366 unsigned int msglen
;
2367 unsigned char sha1
[20]; /* SHA-1 hash (160 bits) */
2368 unsigned char sig
[2*MAX_ECKEY_LEN
];
2369 SECItem signature
, digest
;
2370 PRBool keyvalid
= PR_TRUE
;
2371 PRBool sigvalid
= PR_TRUE
;
2373 ecdsareq
= fopen(reqfn
, "r");
2375 ecpub
.ecParams
.arena
= NULL
;
2376 strcpy(curve
, "nist");
2377 while (fgets(buf
, sizeof buf
, ecdsareq
) != NULL
) {
2378 /* a comment or blank line */
2379 if (buf
[0] == '#' || buf
[0] == '\n') {
2380 fputs(buf
, ecdsaresp
);
2384 if (buf
[0] == '[') {
2387 SECItem
*encodedparams
;
2392 *dst
++ = tolower(*src
);
2393 src
+= 2; /* skip the hyphen */
2398 encodedparams
= getECParams(curve
);
2399 if (encodedparams
== NULL
) {
2402 if (EC_DecodeParams(encodedparams
, &ecparams
) != SECSuccess
) {
2405 SECITEM_FreeItem(encodedparams
, PR_TRUE
);
2406 if (ecpub
.ecParams
.arena
!= NULL
) {
2407 PORT_FreeArena(ecpub
.ecParams
.arena
, PR_FALSE
);
2409 ecpub
.ecParams
.arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2410 if (ecpub
.ecParams
.arena
== NULL
) {
2413 if (EC_CopyParams(ecpub
.ecParams
.arena
, &ecpub
.ecParams
, ecparams
)
2417 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2418 flen
= (ecpub
.ecParams
.fieldID
.size
+ 7) >> 3;
2419 olen
= ecpub
.ecParams
.order
.len
;
2420 if (2*olen
> sizeof sig
) {
2423 ecpub
.publicValue
.type
= siBuffer
;
2424 ecpub
.publicValue
.data
= NULL
;
2425 ecpub
.publicValue
.len
= 0;
2426 SECITEM_AllocItem(ecpub
.ecParams
.arena
,
2427 &ecpub
.publicValue
, 2*flen
+1);
2428 if (ecpub
.publicValue
.data
== NULL
) {
2431 ecpub
.publicValue
.data
[0] = EC_POINT_FORM_UNCOMPRESSED
;
2432 fputs(buf
, ecdsaresp
);
2436 if (strncmp(buf
, "Msg", 3) == 0) {
2438 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2441 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
2442 hex_to_byteval(&buf
[i
], &msg
[j
]);
2445 if (SHA1_HashBuf(sha1
, msg
, msglen
) != SECSuccess
) {
2448 fputs(buf
, ecdsaresp
);
2450 digest
.type
= siBuffer
;
2452 digest
.len
= sizeof sha1
;
2457 if (strncmp(buf
, "Qx", 2) == 0) {
2458 fputs(buf
, ecdsaresp
);
2460 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2463 keyvalid
= from_hex_str(&ecpub
.publicValue
.data
[1], flen
,
2468 if (strncmp(buf
, "Qy", 2) == 0) {
2469 fputs(buf
, ecdsaresp
);
2474 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2477 keyvalid
= from_hex_str(&ecpub
.publicValue
.data
[1+flen
], flen
,
2482 if (EC_ValidatePublicKey(&ecpub
.ecParams
, &ecpub
.publicValue
)
2484 if (PORT_GetError() == SEC_ERROR_BAD_KEY
) {
2485 keyvalid
= PR_FALSE
;
2493 if (buf
[0] == 'R') {
2494 fputs(buf
, ecdsaresp
);
2496 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2499 sigvalid
= from_hex_str(sig
, olen
, &buf
[i
]);
2503 if (buf
[0] == 'S') {
2504 fputs(buf
, ecdsaresp
);
2506 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2510 sigvalid
= from_hex_str(&sig
[olen
], olen
, &buf
[i
]);
2512 signature
.type
= siBuffer
;
2513 signature
.data
= sig
;
2514 signature
.len
= 2*olen
;
2516 if (!keyvalid
|| !sigvalid
) {
2517 fputs("Result = F\n", ecdsaresp
);
2518 } else if (ECDSA_VerifyDigest(&ecpub
, &signature
, &digest
)
2520 fputs("Result = P\n", ecdsaresp
);
2522 fputs("Result = F\n", ecdsaresp
);
2528 if (ecpub
.ecParams
.arena
!= NULL
) {
2529 PORT_FreeArena(ecpub
.ecParams
.arena
, PR_FALSE
);
2533 #endif /* NSS_DISABLE_ECC */
2537 * Read a value from the test and allocate the result.
2539 static unsigned char *
2540 alloc_value(char *buf
, int *len
)
2542 unsigned char * value
;
2545 if (strncmp(buf
, "<None>", 6) == 0) {
2550 /* find the length of the number */
2551 for (count
= 0; isxdigit(buf
[count
]); count
++);
2558 value
= PORT_Alloc(*len
);
2564 for (i
=0; i
<*len
; buf
+=2 , i
++) {
2565 hex_to_byteval(buf
, &value
[i
]);
2573 isblankline(char *b
)
2575 while (isspace(*b
)) b
++;
2576 if ((*b
== '\n') || (*b
== 0)) {
2582 static int debug
= 0;
2585 * Perform the Hash_DRBG (CAVS) for the RNG algorithm
2587 * reqfn is the pathname of the REQUEST file.
2589 * The output RESPONSE file is written to stdout.
2594 char buf
[2000]; /* test case has some very long lines, returned bits
2595 * as high as 800 bytes (6400 bits). That 1600 byte
2598 FILE *rngreq
; /* input stream from the REQUEST file */
2599 FILE *rngresp
; /* output stream to the RESPONSE file */
2602 PRBool predictionResistance
= PR_FALSE
;
2603 unsigned char *nonce
= NULL
;
2605 unsigned char *personalizationString
= NULL
;
2606 int personalizationStringLen
= 0;
2607 unsigned char *additionalInput
= NULL
;
2608 int additionalInputLen
= 0;
2609 unsigned char *entropyInput
= NULL
;
2610 int entropyInputLen
= 0;
2611 unsigned char predictedreturn_bytes
[SHA256_LENGTH
];
2612 unsigned char return_bytes
[SHA256_LENGTH
];
2613 int return_bytes_len
= SHA256_LENGTH
;
2614 enum { NONE
, INSTANTIATE
, GENERATE
, RESEED
, RESULT
} command
=
2616 PRBool genResult
= PR_FALSE
;
2619 rngreq
= fopen(reqfn
, "r");
2621 while (fgets(buf
, sizeof buf
, rngreq
) != NULL
) {
2625 fputs("# PRNGTEST_Instantiate(",rngresp
);
2626 to_hex_str(buf2
,entropyInput
, entropyInputLen
);
2627 fputs(buf2
,rngresp
);
2628 fprintf(rngresp
,",%d,",entropyInputLen
);
2629 to_hex_str(buf2
,nonce
, nonceLen
);
2630 fputs(buf2
,rngresp
);
2631 fprintf(rngresp
,",%d,",nonceLen
);
2632 to_hex_str(buf2
,personalizationString
,
2633 personalizationStringLen
);
2634 fputs(buf2
,rngresp
);
2635 fprintf(rngresp
,",%d)\n", personalizationStringLen
);
2637 rv
= PRNGTEST_Instantiate(entropyInput
, entropyInputLen
,
2639 personalizationString
,
2640 personalizationStringLen
);
2641 if (rv
!= SECSuccess
) {
2648 memset(return_bytes
, 0, return_bytes_len
);
2650 fputs("# PRNGTEST_Generate(returnbytes",rngresp
);
2651 fprintf(rngresp
,",%d,", return_bytes_len
);
2652 to_hex_str(buf2
,additionalInput
, additionalInputLen
);
2653 fputs(buf2
,rngresp
);
2654 fprintf(rngresp
,",%d)\n",additionalInputLen
);
2656 rv
= PRNGTEST_Generate((PRUint8
*) return_bytes
,
2658 (PRUint8
*) additionalInput
,
2659 additionalInputLen
);
2660 if (rv
!= SECSuccess
) {
2664 if (command
== RESULT
) {
2665 fputs("ReturnedBits = ", rngresp
);
2666 to_hex_str(buf2
, return_bytes
, return_bytes_len
);
2667 fputs(buf2
, rngresp
);
2668 fputc('\n', rngresp
);
2670 fputs("# PRNGTEST_Uninstantiate()\n",rngresp
);
2672 rv
= PRNGTEST_Uninstantiate();
2673 if (rv
!= SECSuccess
) {
2677 fputs("#ReturnedBits = ", rngresp
);
2678 to_hex_str(buf2
, return_bytes
, return_bytes_len
);
2679 fputs(buf2
, rngresp
);
2680 fputc('\n', rngresp
);
2683 memset(additionalInput
, 0, additionalInputLen
);
2687 if (entropyInput
|| additionalInput
) {
2689 fputs("# PRNGTEST_Reseed(",rngresp
);
2690 fprintf(rngresp
,",%d,", return_bytes_len
);
2691 to_hex_str(buf2
,entropyInput
, entropyInputLen
);
2692 fputs(buf2
,rngresp
);
2693 fprintf(rngresp
,",%d,", entropyInputLen
);
2694 to_hex_str(buf2
,additionalInput
, additionalInputLen
);
2695 fputs(buf2
,rngresp
);
2696 fprintf(rngresp
,",%d)\n",additionalInputLen
);
2698 rv
= PRNGTEST_Reseed(entropyInput
, entropyInputLen
,
2699 additionalInput
, additionalInputLen
);
2700 if (rv
!= SECSuccess
) {
2704 memset(entropyInput
, 0, entropyInputLen
);
2705 memset(additionalInput
, 0, additionalInputLen
);
2713 /* a comment or blank line */
2714 if (buf
[0] == '#' || buf
[0] == '\n' || buf
[0] == '\r' ) {
2715 fputs(buf
, rngresp
);
2719 /* [Hash - SHA256] */
2720 if (strncmp(buf
, "[SHA-256]", 9) == 0) {
2721 fputs(buf
, rngresp
);
2725 if (strncmp(buf
, "[PredictionResistance", 21) == 0) {
2727 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2730 if (strncmp(buf
, "False", 5) == 0) {
2731 predictionResistance
= PR_FALSE
;
2733 predictionResistance
= PR_TRUE
;
2736 fputs(buf
, rngresp
);
2740 if (strncmp(buf
, "[EntropyInputLen", 16) == 0) {
2742 PORT_ZFree(entropyInput
, entropyInputLen
);
2743 entropyInput
= NULL
;
2744 entropyInputLen
= 0;
2746 if (sscanf(buf
, "[EntropyInputLen = %d]", &entropyInputLen
) != 1) {
2749 entropyInputLen
= entropyInputLen
/8;
2750 if (entropyInputLen
> 0) {
2751 entropyInput
= PORT_Alloc(entropyInputLen
);
2753 fputs(buf
, rngresp
);
2757 if (strncmp(buf
, "[NonceLen", 9) == 0) {
2759 PORT_ZFree(nonce
, nonceLen
);
2764 if (sscanf(buf
, "[NonceLen = %d]", &nonceLen
) != 1) {
2767 nonceLen
= nonceLen
/8;
2769 nonce
= PORT_Alloc(nonceLen
);
2771 fputs(buf
, rngresp
);
2775 if (strncmp(buf
, "[PersonalizationStringLen", 16) == 0) {
2776 if (personalizationString
) {
2777 PORT_ZFree(personalizationString
, personalizationStringLen
);
2778 personalizationString
= NULL
;
2779 personalizationStringLen
= 0;
2782 if (sscanf(buf
, "[PersonalizationStringLen = %d]", &personalizationStringLen
) != 1) {
2785 personalizationStringLen
= personalizationStringLen
/ 8;
2786 if (personalizationStringLen
> 0) {
2787 personalizationString
= PORT_Alloc(personalizationStringLen
);
2789 fputs(buf
, rngresp
);
2794 if (strncmp(buf
, "[AdditionalInputLen", 16) == 0) {
2795 if (additionalInput
) {
2796 PORT_ZFree(additionalInput
, additionalInputLen
);
2797 additionalInput
= NULL
;
2798 additionalInputLen
= 0;
2801 if (sscanf(buf
, "[AdditionalInputLen = %d]", &additionalInputLen
) != 1) {
2804 additionalInputLen
= additionalInputLen
/8;
2805 if (additionalInputLen
> 0) {
2806 additionalInput
= PORT_Alloc(additionalInputLen
);
2808 fputs(buf
, rngresp
);
2812 if (strncmp(buf
, "COUNT", 5) == 0) {
2813 /* zeroize the variables for the test with this data set */
2815 memset(entropyInput
, 0, entropyInputLen
);
2818 memset(nonce
, 0, nonceLen
);
2820 if (personalizationString
) {
2821 memset(personalizationString
, 0, personalizationStringLen
);
2823 if (additionalInput
) {
2824 memset(additionalInput
, 0, additionalInputLen
);
2826 genResult
= PR_FALSE
;
2828 fputs(buf
, rngresp
);
2832 /* EntropyInputReseed = ... */
2833 if (strncmp(buf
, "EntropyInputReseed", 18) == 0) {
2835 memset(entropyInput
, 0, entropyInputLen
);
2837 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2841 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) { /*j<entropyInputLen*/
2842 hex_to_byteval(&buf
[i
], &entropyInput
[j
]);
2845 fputs(buf
, rngresp
);
2849 /* AttionalInputReseed = ... */
2850 if (strncmp(buf
, "AdditionalInputReseed", 21) == 0) {
2851 if (additionalInput
) {
2852 memset(additionalInput
, 0, additionalInputLen
);
2854 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2857 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) { /*j<additionalInputLen*/
2858 hex_to_byteval(&buf
[i
], &additionalInput
[j
]);
2862 fputs(buf
, rngresp
);
2866 /* Entropy input = ... */
2867 if (strncmp(buf
, "EntropyInput", 12) == 0) {
2869 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2872 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) { /*j<entropyInputLen*/
2873 hex_to_byteval(&buf
[i
], &entropyInput
[j
]);
2875 fputs(buf
, rngresp
);
2880 if (strncmp(buf
, "Nonce", 5) == 0) {
2882 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2885 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) { /*j<nonceLen*/
2886 hex_to_byteval(&buf
[i
], &nonce
[j
]);
2888 fputs(buf
, rngresp
);
2892 /* Personalization string = ... */
2893 if (strncmp(buf
, "PersonalizationString", 21) == 0) {
2894 if (personalizationString
) {
2896 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2899 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) { /*j<personalizationStringLen*/
2900 hex_to_byteval(&buf
[i
], &personalizationString
[j
]);
2903 fputs(buf
, rngresp
);
2904 command
= INSTANTIATE
;
2908 /* Additional input = ... */
2909 if (strncmp(buf
, "AdditionalInput", 15) == 0) {
2910 if (additionalInput
) {
2912 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2915 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) { /*j<additionalInputLen*/
2916 hex_to_byteval(&buf
[i
], &additionalInput
[j
]);
2923 genResult
= PR_TRUE
; /* next time generate result */
2925 fputs(buf
, rngresp
);
2929 /* Returned bits = ... */
2930 if (strncmp(buf
, "ReturnedBits", 12) == 0) {
2932 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2935 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) { /*j<additionalInputLen*/
2936 hex_to_byteval(&buf
[i
], &predictedreturn_bytes
[j
]);
2939 if (memcmp(return_bytes
,
2940 predictedreturn_bytes
, return_bytes_len
) != 0) {
2942 fprintf(rngresp
, "# Generate failed:\n");
2943 fputs( "# predicted=", rngresp
);
2944 to_hex_str(buf
, predictedreturn_bytes
,
2946 fputs(buf
, rngresp
);
2947 fputs("\n# actual = ", rngresp
);
2948 fputs(buf2
, rngresp
);
2949 fputc('\n', rngresp
);
2952 fprintf(stderr
, "Generate failed:\n");
2953 fputs( " predicted=", stderr
);
2954 to_hex_str(buf
, predictedreturn_bytes
,
2957 fputs("\n actual = ", stderr
);
2958 fputs(buf2
, stderr
);
2959 fputc('\n', stderr
);
2962 memset(predictedreturn_bytes
, 0 , sizeof predictedreturn_bytes
);
2972 * Perform the RNG Variable Seed Test (VST) for the RNG algorithm
2973 * "DSA - Generation of X", used both as specified and as a generic
2974 * purpose RNG. The presence of "Q = ..." in the REQUEST file
2975 * indicates we are using the algorithm as specified.
2977 * reqfn is the pathname of the REQUEST file.
2979 * The output RESPONSE file is written to stdout.
2982 rng_vst(char *reqfn
)
2984 char buf
[256]; /* holds one line from the input REQUEST file.
2985 * needs to be large enough to hold the longest
2986 * line "XSeed = <128 hex digits>\n".
2988 FILE *rngreq
; /* input stream from the REQUEST file */
2989 FILE *rngresp
; /* output stream to the RESPONSE file */
2991 unsigned char Q
[DSA1_SUBPRIME_LEN
];
2992 PRBool hasQ
= PR_FALSE
;
2993 unsigned int b
; /* 160 <= b <= 512, b is a multiple of 8 */
2994 unsigned char XKey
[512/8];
2995 unsigned char XSeed
[512/8];
2996 unsigned char GENX
[DSA1_SIGNATURE_LEN
];
2997 unsigned char DSAX
[DSA1_SUBPRIME_LEN
];
3000 rngreq
= fopen(reqfn
, "r");
3002 while (fgets(buf
, sizeof buf
, rngreq
) != NULL
) {
3003 /* a comment or blank line */
3004 if (buf
[0] == '#' || buf
[0] == '\n') {
3005 fputs(buf
, rngresp
);
3008 /* [Xchange - SHA1] */
3009 if (buf
[0] == '[') {
3010 fputs(buf
, rngresp
);
3014 if (buf
[0] == 'Q') {
3016 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3019 for (j
=0; j
<sizeof Q
; i
+=2,j
++) {
3020 hex_to_byteval(&buf
[i
], &Q
[j
]);
3022 fputs(buf
, rngresp
);
3026 /* "COUNT = x" begins a new data set */
3027 if (strncmp(buf
, "COUNT", 5) == 0) {
3028 /* zeroize the variables for the test with this data set */
3030 memset(XKey
, 0, sizeof XKey
);
3031 memset(XSeed
, 0, sizeof XSeed
);
3032 fputs(buf
, rngresp
);
3036 if (buf
[0] == 'b') {
3038 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3042 if (b
< 160 || b
> 512 || b
%8 != 0) {
3045 fputs(buf
, rngresp
);
3049 if (strncmp(buf
, "XKey", 4) == 0) {
3051 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3054 for (j
=0; j
<b
/8; i
+=2,j
++) {
3055 hex_to_byteval(&buf
[i
], &XKey
[j
]);
3057 fputs(buf
, rngresp
);
3061 if (strncmp(buf
, "XSeed", 5) == 0) {
3063 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3066 for (j
=0; j
<b
/8; i
+=2,j
++) {
3067 hex_to_byteval(&buf
[i
], &XSeed
[j
]);
3069 fputs(buf
, rngresp
);
3071 rv
= FIPS186Change_GenerateX(XKey
, XSeed
, GENX
);
3072 if (rv
!= SECSuccess
) {
3075 fputs("X = ", rngresp
);
3077 rv
= FIPS186Change_ReduceModQForDSA(GENX
, Q
, DSAX
);
3078 if (rv
!= SECSuccess
) {
3081 to_hex_str(buf
, DSAX
, sizeof DSAX
);
3083 to_hex_str(buf
, GENX
, sizeof GENX
);
3085 fputs(buf
, rngresp
);
3086 fputc('\n', rngresp
);
3095 * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm
3096 * "DSA - Generation of X", used both as specified and as a generic
3097 * purpose RNG. The presence of "Q = ..." in the REQUEST file
3098 * indicates we are using the algorithm as specified.
3100 * reqfn is the pathname of the REQUEST file.
3102 * The output RESPONSE file is written to stdout.
3105 rng_mct(char *reqfn
)
3107 char buf
[256]; /* holds one line from the input REQUEST file.
3108 * needs to be large enough to hold the longest
3109 * line "XSeed = <128 hex digits>\n".
3111 FILE *rngreq
; /* input stream from the REQUEST file */
3112 FILE *rngresp
; /* output stream to the RESPONSE file */
3114 unsigned char Q
[DSA1_SUBPRIME_LEN
];
3115 PRBool hasQ
= PR_FALSE
;
3116 unsigned int b
; /* 160 <= b <= 512, b is a multiple of 8 */
3117 unsigned char XKey
[512/8];
3118 unsigned char XSeed
[512/8];
3119 unsigned char GENX
[2*SHA1_LENGTH
];
3120 unsigned char DSAX
[DSA1_SUBPRIME_LEN
];
3123 rngreq
= fopen(reqfn
, "r");
3125 while (fgets(buf
, sizeof buf
, rngreq
) != NULL
) {
3126 /* a comment or blank line */
3127 if (buf
[0] == '#' || buf
[0] == '\n') {
3128 fputs(buf
, rngresp
);
3131 /* [Xchange - SHA1] */
3132 if (buf
[0] == '[') {
3133 fputs(buf
, rngresp
);
3137 if (buf
[0] == 'Q') {
3139 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3142 for (j
=0; j
<sizeof Q
; i
+=2,j
++) {
3143 hex_to_byteval(&buf
[i
], &Q
[j
]);
3145 fputs(buf
, rngresp
);
3149 /* "COUNT = x" begins a new data set */
3150 if (strncmp(buf
, "COUNT", 5) == 0) {
3151 /* zeroize the variables for the test with this data set */
3153 memset(XKey
, 0, sizeof XKey
);
3154 memset(XSeed
, 0, sizeof XSeed
);
3155 fputs(buf
, rngresp
);
3159 if (buf
[0] == 'b') {
3161 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3165 if (b
< 160 || b
> 512 || b
%8 != 0) {
3168 fputs(buf
, rngresp
);
3172 if (strncmp(buf
, "XKey", 4) == 0) {
3174 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3177 for (j
=0; j
<b
/8; i
+=2,j
++) {
3178 hex_to_byteval(&buf
[i
], &XKey
[j
]);
3180 fputs(buf
, rngresp
);
3184 if (strncmp(buf
, "XSeed", 5) == 0) {
3187 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3190 for (j
=0; j
<b
/8; i
+=2,j
++) {
3191 hex_to_byteval(&buf
[i
], &XSeed
[j
]);
3193 fputs(buf
, rngresp
);
3195 for (k
= 0; k
< 10000; k
++) {
3196 rv
= FIPS186Change_GenerateX(XKey
, XSeed
, GENX
);
3197 if (rv
!= SECSuccess
) {
3201 fputs("X = ", rngresp
);
3203 rv
= FIPS186Change_ReduceModQForDSA(GENX
, Q
, DSAX
);
3204 if (rv
!= SECSuccess
) {
3207 to_hex_str(buf
, DSAX
, sizeof DSAX
);
3209 to_hex_str(buf
, GENX
, sizeof GENX
);
3211 fputs(buf
, rngresp
);
3212 fputc('\n', rngresp
);
3221 * HASH_ functions are available to full NSS apps and internally inside
3222 * freebl, but not exported to users of freebl. Create short stubs to
3223 * replace the functionality for fipstest.
3226 fips_hashBuf(HASH_HashType type
, unsigned char *hashBuf
,
3227 unsigned char *msg
, int len
)
3229 SECStatus rv
= SECFailure
;
3233 rv
= SHA1_HashBuf(hashBuf
, msg
, len
);
3235 case HASH_AlgSHA224
:
3236 rv
= SHA224_HashBuf(hashBuf
, msg
, len
);
3238 case HASH_AlgSHA256
:
3239 rv
= SHA256_HashBuf(hashBuf
, msg
, len
);
3241 case HASH_AlgSHA384
:
3242 rv
= SHA384_HashBuf(hashBuf
, msg
, len
);
3244 case HASH_AlgSHA512
:
3245 rv
= SHA512_HashBuf(hashBuf
, msg
, len
);
3254 fips_hashLen(HASH_HashType type
)
3262 case HASH_AlgSHA224
:
3263 len
= SHA224_LENGTH
;
3265 case HASH_AlgSHA256
:
3266 len
= SHA256_LENGTH
;
3268 case HASH_AlgSHA384
:
3269 len
= SHA384_LENGTH
;
3271 case HASH_AlgSHA512
:
3272 len
= SHA512_LENGTH
;
3281 fips_hashOid(HASH_HashType type
)
3283 SECOidTag oid
= SEC_OID_UNKNOWN
;
3289 case HASH_AlgSHA224
:
3290 oid
= SEC_OID_SHA224
;
3292 case HASH_AlgSHA256
:
3293 oid
= SEC_OID_SHA256
;
3295 case HASH_AlgSHA384
:
3296 oid
= SEC_OID_SHA384
;
3298 case HASH_AlgSHA512
:
3299 oid
= SEC_OID_SHA512
;
3308 sha_get_hashType(int hashbits
)
3310 HASH_HashType hashType
= HASH_AlgNULL
;
3314 case (SHA1_LENGTH
*PR_BITS_PER_BYTE
):
3315 hashType
= HASH_AlgSHA1
;
3317 case (SHA224_LENGTH
*PR_BITS_PER_BYTE
):
3318 hashType
= HASH_AlgSHA224
;
3320 case (SHA256_LENGTH
*PR_BITS_PER_BYTE
):
3321 hashType
= HASH_AlgSHA256
;
3323 case (SHA384_LENGTH
*PR_BITS_PER_BYTE
):
3324 hashType
= HASH_AlgSHA384
;
3326 case (SHA512_LENGTH
*PR_BITS_PER_BYTE
):
3327 hashType
= HASH_AlgSHA512
;
3336 * Calculate the SHA Message Digest
3338 * MD = Message digest
3339 * MDLen = length of Message Digest and SHA_Type
3340 * msg = message to digest
3341 * msgLen = length of message to digest
3343 SECStatus
sha_calcMD(unsigned char *MD
, unsigned int MDLen
, unsigned char *msg
, unsigned int msgLen
)
3345 HASH_HashType hashType
= sha_get_hashType(MDLen
*PR_BITS_PER_BYTE
);
3347 return fips_hashBuf(hashType
, MD
, msg
, msgLen
);
3351 * Perform the SHA Monte Carlo Test
3353 * MDLen = length of Message Digest and SHA_Type
3354 * seed = input seed value
3355 * resp = is the output response file.
3357 SECStatus
sha_mct_test(unsigned int MDLen
, unsigned char *seed
, FILE *resp
)
3360 unsigned int msgLen
= MDLen
*3;
3361 unsigned char MD_i3
[HASH_LENGTH_MAX
]; /* MD[i-3] */
3362 unsigned char MD_i2
[HASH_LENGTH_MAX
]; /* MD[i-2] */
3363 unsigned char MD_i1
[HASH_LENGTH_MAX
]; /* MD[i-1] */
3364 unsigned char MD_i
[HASH_LENGTH_MAX
]; /* MD[i] */
3365 unsigned char msg
[HASH_LENGTH_MAX
*3];
3366 char buf
[HASH_LENGTH_MAX
*2 + 1]; /* MAX buf MD_i as a hex string */
3368 for (j
=0; j
<100; j
++) {
3369 /* MD_0 = MD_1 = MD_2 = seed */
3370 memcpy(MD_i3
, seed
, MDLen
);
3371 memcpy(MD_i2
, seed
, MDLen
);
3372 memcpy(MD_i1
, seed
, MDLen
);
3374 for (i
=3; i
< 1003; i
++) {
3375 /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */
3376 memcpy(msg
, MD_i3
, MDLen
);
3377 memcpy(&msg
[MDLen
], MD_i2
, MDLen
);
3378 memcpy(&msg
[MDLen
*2], MD_i1
,MDLen
);
3380 /* MDi = SHA(Msg) */
3381 if (sha_calcMD(MD_i
, MDLen
,
3382 msg
, msgLen
) != SECSuccess
) {
3386 /* save MD[i-3] MD[i-2] MD[i-1] */
3387 memcpy(MD_i3
, MD_i2
, MDLen
);
3388 memcpy(MD_i2
, MD_i1
, MDLen
);
3389 memcpy(MD_i1
, MD_i
, MDLen
);
3394 memcpy(seed
, MD_i
, MDLen
);
3396 sprintf(buf
, "COUNT = %d\n", j
);
3400 fputs("MD = ", resp
);
3401 to_hex_str(buf
, MD_i
, MDLen
);
3410 * Perform the SHA Tests.
3412 * reqfn is the pathname of the input REQUEST file.
3414 * The output RESPONSE file is written to stdout.
3416 void sha_test(char *reqfn
)
3419 unsigned int MDlen
; /* the length of the Message Digest in Bytes */
3420 unsigned int msgLen
; /* the length of the input Message in Bytes */
3421 unsigned char *msg
= NULL
; /* holds the message to digest.*/
3422 size_t bufSize
= 25608; /*MAX buffer size */
3423 char *buf
= NULL
; /* holds one line from the input REQUEST file.*/
3424 unsigned char seed
[HASH_LENGTH_MAX
]; /* max size of seed 64 bytes */
3425 unsigned char MD
[HASH_LENGTH_MAX
]; /* message digest */
3427 FILE *req
= NULL
; /* input stream from the REQUEST file */
3428 FILE *resp
; /* output stream to the RESPONSE file */
3430 buf
= PORT_ZAlloc(bufSize
);
3435 /* zeroize the variables for the test with this data set */
3436 memset(seed
, 0, sizeof seed
);
3438 req
= fopen(reqfn
, "r");
3440 while (fgets(buf
, bufSize
, req
) != NULL
) {
3442 /* a comment or blank line */
3443 if (buf
[0] == '#' || buf
[0] == '\n') {
3447 /* [L = Length of the Message Digest and sha_type */
3448 if (buf
[0] == '[') {
3449 if (strncmp(&buf
[1], "L ", 1) == 0) {
3451 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3454 MDlen
= atoi(&buf
[i
]);
3459 /* Len = Length of the Input Message Length ... */
3460 if (strncmp(buf
, "Len", 3) == 0) {
3462 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3466 PORT_ZFree(msg
,msgLen
);
3469 msgLen
= atoi(&buf
[i
]); /* in bits */
3470 if (msgLen
%8 != 0) {
3471 fprintf(stderr
, "SHA tests are incorrectly configured for "
3472 "BIT oriented implementations\n");
3475 msgLen
= msgLen
/8; /* convert to bytes */
3477 msg
= PORT_ZAlloc(msgLen
);
3478 if (msg
== NULL
&& msgLen
!= 0) {
3484 if (strncmp(buf
, "Msg", 3) == 0) {
3486 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3489 for (j
=0; j
< msgLen
; i
+=2,j
++) {
3490 hex_to_byteval(&buf
[i
], &msg
[j
]);
3493 /* calculate the Message Digest */
3494 memset(MD
, 0, sizeof MD
);
3495 if (sha_calcMD(MD
, MDlen
,
3496 msg
, msgLen
) != SECSuccess
) {
3500 fputs("MD = ", resp
);
3501 to_hex_str(buf
, MD
, MDlen
);
3508 if (strncmp(buf
, "Seed", 4) == 0) {
3510 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3513 for (j
=0; j
<sizeof seed
; i
+=2,j
++) {
3514 hex_to_byteval(&buf
[i
], &seed
[j
]);
3520 /* do the Monte Carlo test */
3521 if (sha_mct_test(MDlen
, seed
, resp
) != SECSuccess
) {
3533 PORT_ZFree(buf
, bufSize
);
3536 PORT_ZFree(msg
, msgLen
);
3540 /****************************************************/
3541 /* HMAC SHA-X calc */
3542 /* hmac_computed - the computed HMAC */
3543 /* hmac_length - the length of the computed HMAC */
3544 /* secret_key - secret key to HMAC */
3545 /* secret_key_length - length of secret key, */
3546 /* message - message to HMAC */
3547 /* message_length - length ofthe message */
3548 /****************************************************/
3550 hmac_calc(unsigned char *hmac_computed
,
3551 const unsigned int hmac_length
,
3552 const unsigned char *secret_key
,
3553 const unsigned int secret_key_length
,
3554 const unsigned char *message
,
3555 const unsigned int message_length
,
3556 const HASH_HashType hashAlg
)
3558 SECStatus hmac_status
= SECFailure
;
3559 HMACContext
*cx
= NULL
;
3560 SECHashObject
*hashObj
= NULL
;
3561 unsigned int bytes_hashed
= 0;
3563 hashObj
= (SECHashObject
*) HASH_GetRawHashObject(hashAlg
);
3566 return( SECFailure
);
3568 cx
= HMAC_Create(hashObj
, secret_key
,
3570 PR_TRUE
); /* PR_TRUE for in FIPS mode */
3573 return( SECFailure
);
3576 HMAC_Update(cx
, message
, message_length
);
3577 hmac_status
= HMAC_Finish(cx
, hmac_computed
, &bytes_hashed
,
3580 HMAC_Destroy(cx
, PR_TRUE
);
3582 return( hmac_status
);
3586 * Perform the HMAC Tests.
3588 * reqfn is the pathname of the input REQUEST file.
3590 * The output RESPONSE file is written to stdout.
3592 void hmac_test(char *reqfn
)
3595 size_t bufSize
= 400; /* MAX buffer size */
3596 char *buf
= NULL
; /* holds one line from the input REQUEST file.*/
3597 unsigned int keyLen
; /* Key Length */
3598 unsigned char key
[200]; /* key MAX size = 184 */
3599 unsigned int msgLen
= 128; /* the length of the input */
3600 /* Message is always 128 Bytes */
3601 unsigned char *msg
= NULL
; /* holds the message to digest.*/
3602 unsigned int HMACLen
; /* the length of the HMAC Bytes */
3603 unsigned int TLen
; /* the length of the requested */
3604 /* truncated HMAC Bytes */
3605 unsigned char HMAC
[HASH_LENGTH_MAX
]; /* computed HMAC */
3606 unsigned char expectedHMAC
[HASH_LENGTH_MAX
]; /* for .fax files that have */
3607 /* supplied known answer */
3608 HASH_HashType hash_alg
; /* HMAC type */
3611 FILE *req
= NULL
; /* input stream from the REQUEST file */
3612 FILE *resp
; /* output stream to the RESPONSE file */
3614 buf
= PORT_ZAlloc(bufSize
);
3618 msg
= PORT_ZAlloc(msgLen
);
3623 req
= fopen(reqfn
, "r");
3625 while (fgets(buf
, bufSize
, req
) != NULL
) {
3626 if (strncmp(buf
, "Mac", 3) == 0) {
3628 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3631 memset(expectedHMAC
, 0, HASH_LENGTH_MAX
);
3632 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
3633 hex_to_byteval(&buf
[i
], &expectedHMAC
[j
]);
3635 if (memcmp(HMAC
, expectedHMAC
, TLen
) != 0) {
3636 fprintf(stderr
, "Generate failed:\n");
3637 fputs( " expected=", stderr
);
3638 to_hex_str(buf
, expectedHMAC
,
3641 fputs("\n generated=", stderr
);
3642 to_hex_str(buf
, HMAC
,
3645 fputc('\n', stderr
);
3649 /* a comment or blank line */
3650 if (buf
[0] == '#' || buf
[0] == '\n') {
3654 /* [L = Length of the MAC and HASH_type */
3655 if (buf
[0] == '[') {
3656 if (strncmp(&buf
[1], "L ", 1) == 0) {
3658 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3661 /* HMACLen will get reused for Tlen */
3662 HMACLen
= atoi(&buf
[i
]);
3663 hash_alg
= sha_get_hashType(HMACLen
*PR_BITS_PER_BYTE
);
3664 if (hash_alg
== HASH_AlgNULL
) {
3671 /* Count = test iteration number*/
3672 if (strncmp(buf
, "Count ", 5) == 0) {
3673 /* count can just be put into resp file */
3675 /* zeroize the variables for the test with this data set */
3678 memset(key
, 0, sizeof key
);
3679 memset(msg
, 0, msgLen
);
3680 memset(HMAC
, 0, sizeof HMAC
);
3683 /* KLen = Length of the Input Secret Key ... */
3684 if (strncmp(buf
, "Klen", 4) == 0) {
3686 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3689 keyLen
= atoi(&buf
[i
]); /* in bytes */
3693 /* key = the secret key for the key to MAC */
3694 if (strncmp(buf
, "Key", 3) == 0) {
3696 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3699 for (j
=0; j
< keyLen
; i
+=2,j
++) {
3700 hex_to_byteval(&buf
[i
], &key
[j
]);
3704 /* TLen = Length of the calculated HMAC */
3705 if (strncmp(buf
, "Tlen", 4) == 0) {
3707 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3710 TLen
= atoi(&buf
[i
]); /* in bytes */
3714 /* MSG = to HMAC always 128 bytes for these tests */
3715 if (strncmp(buf
, "Msg", 3) == 0) {
3717 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3720 for (j
=0; j
< msgLen
; i
+=2,j
++) {
3721 hex_to_byteval(&buf
[i
], &msg
[j
]);
3724 /* calculate the HMAC and output */
3725 if (hmac_calc(HMAC
, HMACLen
, key
, keyLen
,
3726 msg
, msgLen
, hash_alg
) != SECSuccess
) {
3729 fputs("MAC = ", resp
);
3730 to_hex_str(buf
, HMAC
, TLen
);
3741 PORT_ZFree(buf
, bufSize
);
3744 PORT_ZFree(msg
, msgLen
);
3749 * Perform the DSA Key Pair Generation Test.
3751 * reqfn is the pathname of the REQUEST file.
3753 * The output RESPONSE file is written to stdout.
3756 dsa_keypair_test(char *reqfn
)
3758 char buf
[800]; /* holds one line from the input REQUEST file
3759 * or to the output RESPONSE file.
3760 * 800 to hold (384 public key (x2 for HEX) + 1'\n'
3762 FILE *dsareq
; /* input stream from the REQUEST file */
3763 FILE *dsaresp
; /* output stream to the RESPONSE file */
3768 PQGParams
*pqg
= NULL
;
3769 PQGVerify
*vfy
= NULL
;
3770 PRBool use_dsa1
= PR_FALSE
;
3771 int keySizeIndex
; /* index for valid key sizes */
3773 dsareq
= fopen(reqfn
, "r");
3775 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
3776 /* a comment or blank line */
3777 if (buf
[0] == '#' || buf
[0] == '\n') {
3778 fputs(buf
, dsaresp
);
3783 if (buf
[0] == '[') {
3785 PQG_DestroyParams(pqg
);
3789 PQG_DestroyVerify(vfy
);
3793 if (sscanf(buf
, "[mod = L=%d, N=%d]", &L
, &N
) != 2) {
3795 if (sscanf(buf
, "[mod = %d]", &L
) != 1) {
3799 fputs(buf
, dsaresp
);
3800 fputc('\n', dsaresp
);
3803 /*************************************************************
3804 * PQG_ParamGenSeedLen doesn't take a key size, it takes an
3805 * index that points to a valid key size.
3807 keySizeIndex
= PQG_PBITS_TO_INDEX(L
);
3808 if(keySizeIndex
== -1 || L
<512 || L
>1024) {
3810 "DSA key size must be a multiple of 64 between 512 "
3811 "and 1024, inclusive");
3815 /* Generate the parameters P, Q, and G */
3816 if (PQG_ParamGenSeedLen(keySizeIndex
, PQG_TEST_SEED_BYTES
,
3817 &pqg
, &vfy
) != SECSuccess
) {
3819 "ERROR: Unable to generate PQG parameters");
3823 if (PQG_ParamGenV2(L
, N
, N
, &pqg
, &vfy
) != SECSuccess
) {
3825 "ERROR: Unable to generate PQG parameters");
3830 /* output P, Q, and G */
3831 to_hex_str(buf
, pqg
->prime
.data
, pqg
->prime
.len
);
3832 fprintf(dsaresp
, "P = %s\n", buf
);
3833 to_hex_str(buf
, pqg
->subPrime
.data
, pqg
->subPrime
.len
);
3834 fprintf(dsaresp
, "Q = %s\n", buf
);
3835 to_hex_str(buf
, pqg
->base
.data
, pqg
->base
.len
);
3836 fprintf(dsaresp
, "G = %s\n\n", buf
);
3840 if (buf
[0] == 'N') {
3842 if (sscanf(buf
, "N = %d", &count
) != 1) {
3845 /* Generate a DSA key, and output the key pair for N times */
3846 for (i
= 0; i
< count
; i
++) {
3847 DSAPrivateKey
*dsakey
= NULL
;
3848 if (DSA_NewKey(pqg
, &dsakey
) != SECSuccess
) {
3849 fprintf(dsaresp
, "ERROR: Unable to generate DSA key");
3852 to_hex_str(buf
, dsakey
->privateValue
.data
,
3853 dsakey
->privateValue
.len
);
3854 fprintf(dsaresp
, "X = %s\n", buf
);
3855 to_hex_str(buf
, dsakey
->publicValue
.data
,
3856 dsakey
->publicValue
.len
);
3857 fprintf(dsaresp
, "Y = %s\n\n", buf
);
3858 PORT_FreeArena(dsakey
->params
.arena
, PR_TRUE
);
3870 * pqg generation type
3873 FIPS186_1
,/* Generate/Verify P,Q & G according to FIPS 186-1 */
3874 A_1_1_2
, /* Generate Probable P & Q */
3875 A_1_1_3
, /* Verify Probable P & Q */
3876 A_1_2_2
, /* Verify Provable P & Q */
3877 A_2_1
, /* Generate Unverifiable G */
3878 A_2_2
, /* Assure Unverifiable G */
3879 A_2_3
, /* Generate Verifiable G */
3880 A_2_4
/* Verify Verifiable G */
3884 * Perform the DSA Domain Parameter Validation Test.
3886 * reqfn is the pathname of the REQUEST file.
3888 * The output RESPONSE file is written to stdout.
3891 dsa_pqgver_test(char *reqfn
)
3893 char buf
[800]; /* holds one line from the input REQUEST file
3894 * or to the output RESPONSE file.
3895 * 800 to hold (384 public key (x2 for HEX) + P = ...
3897 FILE *dsareq
; /* input stream from the REQUEST file */
3898 FILE *dsaresp
; /* output stream to the RESPONSE file */
3904 unsigned int pghSize
; /* size for p, g, and h */
3905 dsa_pqg_type type
= FIPS186_1
;
3907 dsareq
= fopen(reqfn
, "r");
3909 memset(&pqg
, 0, sizeof(pqg
));
3910 memset(&vfy
, 0, sizeof(vfy
));
3912 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
3913 /* a comment or blank line */
3914 if (buf
[0] == '#' || buf
[0] == '\n') {
3915 fputs(buf
, dsaresp
);
3920 if (buf
[0] == '[' && buf
[1] == 'A') {
3922 if (strncmp(&buf
[1],"A.1.1.3",7) == 0) {
3924 } else if (strncmp(&buf
[1],"A.2.2",5) == 0) {
3926 } else if (strncmp(&buf
[1],"A.2.4",5) == 0) {
3928 } else if (strncmp(&buf
[1],"A.1.2.2",7) == 0) {
3930 /* validate our output from PQGGEN */
3931 } else if (strncmp(&buf
[1],"A.1.1.2",7) == 0) {
3932 type
= A_2_4
; /* validate PQ and G together */
3934 fprintf(stderr
, "Unknown dsa ver test %s\n", &buf
[1]);
3938 fputs(buf
, dsaresp
);
3944 if (buf
[0] == '[') {
3946 if (type
== FIPS186_1
) {
3948 if (sscanf(buf
, "[mod = %d]", &L
) != 1) {
3951 } else if (sscanf(buf
, "[mod = L=%d, N=%d", &L
, &N
) != 2) {
3955 if (pqg
.prime
.data
) { /* P */
3956 SECITEM_ZfreeItem(&pqg
.prime
, PR_FALSE
);
3958 if (pqg
.subPrime
.data
) { /* Q */
3959 SECITEM_ZfreeItem(&pqg
.subPrime
, PR_FALSE
);
3961 if (pqg
.base
.data
) { /* G */
3962 SECITEM_ZfreeItem(&pqg
.base
, PR_FALSE
);
3964 if (vfy
.seed
.data
) { /* seed */
3965 SECITEM_ZfreeItem(&vfy
.seed
, PR_FALSE
);
3967 if (vfy
.h
.data
) { /* H */
3968 SECITEM_ZfreeItem(&vfy
.h
, PR_FALSE
);
3971 fputs(buf
, dsaresp
);
3973 /*calculate the size of p, g, and h then allocate items */
3976 pqg
.base
.data
= vfy
.h
.data
= NULL
;
3977 vfy
.seed
.len
= pqg
.base
.len
= vfy
.h
.len
= 0;
3978 SECITEM_AllocItem(NULL
, &pqg
.prime
, pghSize
);
3979 SECITEM_AllocItem(NULL
, &vfy
.seed
, pghSize
*3);
3980 if (type
== A_2_2
) {
3981 SECITEM_AllocItem(NULL
, &vfy
.h
, pghSize
);
3982 vfy
.h
.len
= pghSize
;
3983 } else if (type
== A_2_4
) {
3984 SECITEM_AllocItem(NULL
, &vfy
.h
, 1);
3987 pqg
.prime
.len
= pghSize
;
3988 /* q is always N bits */
3989 SECITEM_AllocItem(NULL
, &pqg
.subPrime
, N
/8);
3990 pqg
.subPrime
.len
= N
/8;
3996 if (buf
[0] == 'P') {
3998 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4001 for (j
=0; j
< pqg
.prime
.len
; i
+=2,j
++) {
4002 hex_to_byteval(&buf
[i
], &pqg
.prime
.data
[j
]);
4005 fputs(buf
, dsaresp
);
4010 if (buf
[0] == 'Q') {
4012 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4015 for (j
=0; j
< pqg
.subPrime
.len
; i
+=2,j
++) {
4016 hex_to_byteval(&buf
[i
], &pqg
.subPrime
.data
[j
]);
4019 fputs(buf
, dsaresp
);
4024 if (buf
[0] == 'G') {
4026 if (pqg
.base
.data
) {
4027 SECITEM_ZfreeItem(&pqg
.base
, PR_FALSE
);
4029 SECITEM_AllocItem(NULL
, &pqg
.base
, pghSize
);
4030 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4033 for (j
=0; j
< pqg
.base
.len
; i
+=2,j
++) {
4034 hex_to_byteval(&buf
[i
], &pqg
.base
.data
[j
]);
4037 fputs(buf
, dsaresp
);
4041 /* Seed = ... or domain_parameter_seed = ... */
4042 if (strncmp(buf
, "Seed", 4) == 0) {
4044 } else if (strncmp(buf
, "domain_parameter_seed", 21) == 0) {
4046 } else if (strncmp(buf
,"firstseed",9) == 0) {
4052 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4055 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
4056 hex_to_byteval(&buf
[i
], &vfy
.seed
.data
[j
]);
4060 fputs(buf
, dsaresp
);
4061 if (type
== A_2_4
) {
4064 /* Verify the Parameters */
4065 SECStatus rv
= PQG_VerifyParams(&pqg
, &vfy
, &result
);
4066 if (rv
!= SECSuccess
) {
4069 if (result
== SECSuccess
) {
4070 fprintf(dsaresp
, "Result = P\n");
4072 fprintf(dsaresp
, "Result = F\n");
4077 if ((strncmp(buf
,"pseed",5) == 0) ||
4078 (strncmp(buf
,"qseed",5) == 0))
4081 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4084 for (j
=vfy
.seed
.len
; isxdigit(buf
[i
]); i
+=2,j
++) {
4085 hex_to_byteval(&buf
[i
], &vfy
.seed
.data
[j
]);
4088 fputs(buf
, dsaresp
);
4092 if (strncmp(buf
, "index", 4) == 0) {
4094 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4097 hex_to_byteval(&buf
[i
], &vfy
.h
.data
[0]);
4099 fputs(buf
, dsaresp
);
4102 /* c = ... or counter=*/
4103 if (buf
[0] == 'c') {
4104 if (strncmp(buf
,"counter", 7) == 0) {
4105 if (sscanf(buf
, "counter = %u", &vfy
.counter
) != 1) {
4109 if (sscanf(buf
, "c = %u", &vfy
.counter
) != 1) {
4114 fputs(buf
, dsaresp
);
4115 if (type
== A_1_1_3
) {
4117 /* only verify P and Q, we have everything now. do it */
4118 SECStatus rv
= PQG_VerifyParams(&pqg
, &vfy
, &result
);
4119 if (rv
!= SECSuccess
) {
4122 if (result
== SECSuccess
) {
4123 fprintf(dsaresp
, "Result = P\n");
4125 fprintf(dsaresp
, "Result = F\n");
4127 fprintf(dsaresp
, "\n");
4131 if (strncmp(buf
,"pgen_counter", 12) == 0) {
4132 if (sscanf(buf
, "pgen_counter = %u", &vfy
.counter
) != 1) {
4135 fputs(buf
, dsaresp
);
4138 if (strncmp(buf
,"qgen_counter", 12) == 0) {
4139 fputs(buf
, dsaresp
);
4140 if (type
== A_1_2_2
) {
4142 /* only verify P and Q, we have everything now. do it */
4143 SECStatus rv
= PQG_VerifyParams(&pqg
, &vfy
, &result
);
4144 if (rv
!= SECSuccess
) {
4147 if (result
== SECSuccess
) {
4148 fprintf(dsaresp
, "Result = P\n");
4150 fprintf(dsaresp
, "Result = F\n");
4152 fprintf(dsaresp
, "\n");
4157 if (buf
[0] == 'H') {
4158 SECStatus rv
, result
= SECFailure
;
4161 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4164 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
4165 hex_to_byteval(&buf
[i
], &vfy
.h
.data
[j
]);
4168 fputs(buf
, dsaresp
);
4170 /* this should be a byte value. Remove the leading zeros. If
4171 * it doesn't reduce to a byte, PQG_VerifyParams will catch it
4172 if (type == A_2_2) {
4173 data_save = vfy.h.data;
4174 while(vfy.h.data[0] && (vfy.h.len > 1)) {
4180 /* Verify the Parameters */
4181 rv
= PQG_VerifyParams(&pqg
, &vfy
, &result
);
4182 if (rv
!= SECSuccess
) {
4185 if (result
== SECSuccess
) {
4186 fprintf(dsaresp
, "Result = P\n");
4188 fprintf(dsaresp
, "Result = F\n");
4190 fprintf(dsaresp
, "\n");
4196 if (pqg
.prime
.data
) { /* P */
4197 SECITEM_ZfreeItem(&pqg
.prime
, PR_FALSE
);
4199 if (pqg
.subPrime
.data
) { /* Q */
4200 SECITEM_ZfreeItem(&pqg
.subPrime
, PR_FALSE
);
4202 if (pqg
.base
.data
) { /* G */
4203 SECITEM_ZfreeItem(&pqg
.base
, PR_FALSE
);
4205 if (vfy
.seed
.data
) { /* seed */
4206 SECITEM_ZfreeItem(&vfy
.seed
, PR_FALSE
);
4208 if (vfy
.h
.data
) { /* H */
4209 SECITEM_ZfreeItem(&vfy
.h
, PR_FALSE
);
4215 * Perform the DSA Public Key Validation Test.
4217 * reqfn is the pathname of the REQUEST file.
4219 * The output RESPONSE file is written to stdout.
4222 dsa_pqggen_test(char *reqfn
)
4224 char buf
[800]; /* holds one line from the input REQUEST file
4225 * or to the output RESPONSE file.
4226 * 800 to hold seed = (384 public key (x2 for HEX)
4228 FILE *dsareq
; /* input stream from the REQUEST file */
4229 FILE *dsaresp
; /* output stream to the RESPONSE file */
4230 int count
; /* number of times to generate parameters */
4235 PQGParams
*pqg
= NULL
;
4236 PQGVerify
*vfy
= NULL
;
4237 unsigned int keySizeIndex
;
4238 dsa_pqg_type type
= FIPS186_1
;
4240 dsareq
= fopen(reqfn
, "r");
4242 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
4243 /* a comment or blank line */
4244 if (buf
[0] == '#' || buf
[0] == '\n') {
4245 fputs(buf
, dsaresp
);
4250 if (buf
[0] == '[' && buf
[1] == 'A') {
4251 if (strncmp(&buf
[1],"A.1.1.2",7) == 0) {
4253 } else if (strncmp(&buf
[1],"A.2.1",5) == 0) {
4254 fprintf(stderr
, "NSS only Generates G with P&Q\n");
4256 } else if (strncmp(&buf
[1],"A.2.3",5) == 0) {
4257 fprintf(stderr
, "NSS only Generates G with P&Q\n");
4259 } else if (strncmp(&buf
[1],"A.1.2.1",7) == 0) {
4260 fprintf(stderr
, "NSS does not support Shawe-Taylor Primes\n");
4263 fprintf(stderr
, "Unknown dsa ver test %s\n", &buf
[1]);
4266 fputs(buf
, dsaresp
);
4271 if (buf
[0] == '[') {
4273 if (type
== FIPS186_1
) {
4275 if (sscanf(buf
, "[mod = %d]", &L
) != 1) {
4278 } else if (sscanf(buf
, "[mod = L=%d, N=%d", &L
, &N
) != 2) {
4282 fputs(buf
, dsaresp
);
4283 fputc('\n', dsaresp
);
4285 if (type
== FIPS186_1
) {
4286 /************************************************************
4287 * PQG_ParamGenSeedLen doesn't take a key size, it takes an
4288 * index that points to a valid key size.
4290 keySizeIndex
= PQG_PBITS_TO_INDEX(L
);
4291 if(keySizeIndex
== -1 || L
<512 || L
>1024) {
4293 "DSA key size must be a multiple of 64 between 512 "
4294 "and 1024, inclusive");
4301 if (buf
[0] == 'N') {
4302 if (sscanf(buf
, "N = %d", &count
) != 1) {
4305 for (i
= 0; i
< count
; i
++) {
4308 if (type
== FIPS186_1
) {
4309 rv
= PQG_ParamGenSeedLen(keySizeIndex
, PQG_TEST_SEED_BYTES
,
4312 rv
= PQG_ParamGenV2(L
, N
, N
, &pqg
, &vfy
);
4314 if (rv
!= SECSuccess
) {
4316 "ERROR: Unable to generate PQG parameters");
4319 to_hex_str(buf
, pqg
->prime
.data
, pqg
->prime
.len
);
4320 fprintf(dsaresp
, "P = %s\n", buf
);
4321 to_hex_str(buf
, pqg
->subPrime
.data
, pqg
->subPrime
.len
);
4322 fprintf(dsaresp
, "Q = %s\n", buf
);
4323 to_hex_str(buf
, pqg
->base
.data
, pqg
->base
.len
);
4324 fprintf(dsaresp
, "G = %s\n", buf
);
4325 if (type
== FIPS186_1
) {
4326 to_hex_str(buf
, vfy
->seed
.data
, vfy
->seed
.len
);
4327 fprintf(dsaresp
, "Seed = %s\n", buf
);
4328 fprintf(dsaresp
, "c = %d\n", vfy
->counter
);
4329 to_hex_str(buf
, vfy
->h
.data
, vfy
->h
.len
);
4330 fputs("H = ", dsaresp
);
4331 for (j
=vfy
->h
.len
; j
< pqg
->prime
.len
; j
++) {
4332 fprintf(dsaresp
, "00");
4334 fprintf(dsaresp
, "%s\n", buf
);
4336 fprintf(dsaresp
, "counter = %d\n", vfy
->counter
);
4337 fprintf(dsaresp
, "index = %02x\n", vfy
->h
.data
[0]);
4338 to_hex_str(buf
, vfy
->seed
.data
, vfy
->seed
.len
);
4339 fprintf(dsaresp
, "domain_parameter_seed = %s\n", buf
);
4341 fputc('\n', dsaresp
);
4343 PQG_DestroyParams(pqg
);
4347 PQG_DestroyVerify(vfy
);
4359 PQG_DestroyParams(pqg
);
4362 PQG_DestroyVerify(vfy
);
4368 * Perform the DSA Signature Generation Test.
4370 * reqfn is the pathname of the REQUEST file.
4372 * The output RESPONSE file is written to stdout.
4375 dsa_siggen_test(char *reqfn
)
4377 char buf
[800]; /* holds one line from the input REQUEST file
4378 * or to the output RESPONSE file.
4379 * max for Msg = ....
4381 FILE *dsareq
; /* input stream from the REQUEST file */
4382 FILE *dsaresp
; /* output stream to the RESPONSE file */
4387 PRBool use_dsa1
= PR_FALSE
;
4388 PQGParams
*pqg
= NULL
;
4389 PQGVerify
*vfy
= NULL
;
4390 DSAPrivateKey
*dsakey
= NULL
;
4391 int keySizeIndex
; /* index for valid key sizes */
4392 unsigned char hashBuf
[HASH_LENGTH_MAX
]; /* SHA-x hash (160-512 bits) */
4393 unsigned char sig
[DSA_MAX_SIGNATURE_LEN
];
4394 SECItem digest
, signature
;
4395 HASH_HashType hashType
= HASH_AlgNULL
;
4398 dsareq
= fopen(reqfn
, "r");
4401 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
4402 /* a comment or blank line */
4403 if (buf
[0] == '#' || buf
[0] == '\n') {
4404 fputs(buf
, dsaresp
);
4409 if (buf
[0] == '[') {
4411 PQG_DestroyParams(pqg
);
4415 PQG_DestroyVerify(vfy
);
4418 if (dsakey
!= NULL
) {
4419 PORT_FreeArena(dsakey
->params
.arena
, PR_TRUE
);
4423 if (sscanf(buf
, "[mod = L=%d, N=%d, SHA-%d]", &L
, & N
,
4427 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
4431 fputs(buf
, dsaresp
);
4432 fputc('\n', dsaresp
);
4434 /****************************************************************
4435 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
4436 * that points to a valid key size.
4439 keySizeIndex
= PQG_PBITS_TO_INDEX(modulus
);
4440 if(keySizeIndex
== -1 || modulus
<512 || modulus
>1024) {
4442 "DSA key size must be a multiple of 64 between 512 "
4443 "and 1024, inclusive");
4446 /* Generate PQG and output PQG */
4447 if (PQG_ParamGenSeedLen(keySizeIndex
, PQG_TEST_SEED_BYTES
,
4448 &pqg
, &vfy
) != SECSuccess
) {
4450 "ERROR: Unable to generate PQG parameters");
4454 if (PQG_ParamGenV2(L
, N
, N
, &pqg
, &vfy
) != SECSuccess
) {
4456 "ERROR: Unable to generate PQG parameters");
4460 to_hex_str(buf
, pqg
->prime
.data
, pqg
->prime
.len
);
4461 fprintf(dsaresp
, "P = %s\n", buf
);
4462 to_hex_str(buf
, pqg
->subPrime
.data
, pqg
->subPrime
.len
);
4463 fprintf(dsaresp
, "Q = %s\n", buf
);
4464 to_hex_str(buf
, pqg
->base
.data
, pqg
->base
.len
);
4465 fprintf(dsaresp
, "G = %s\n", buf
);
4467 /* create DSA Key */
4468 if (DSA_NewKey(pqg
, &dsakey
) != SECSuccess
) {
4469 fprintf(dsaresp
, "ERROR: Unable to generate DSA key");
4473 hashType
= sha_get_hashType(hashNum
);
4474 if (hashType
== HASH_AlgNULL
) {
4475 fprintf(dsaresp
, "ERROR: invalid hash (SHA-%d)",hashNum
);
4482 if (strncmp(buf
, "Msg", 3) == 0) {
4483 unsigned char msg
[128]; /* MAX msg 128 */
4484 unsigned int len
= 0;
4486 if (hashType
== HASH_AlgNULL
) {
4487 fprintf(dsaresp
, "ERROR: Hash Alg not set");
4491 memset(hashBuf
, 0, sizeof hashBuf
);
4492 memset(sig
, 0, sizeof sig
);
4495 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4498 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
4499 hex_to_byteval(&buf
[i
], &msg
[j
]);
4501 if (fips_hashBuf(hashType
, hashBuf
, msg
, j
) != SECSuccess
) {
4502 fprintf(dsaresp
, "ERROR: Unable to generate SHA% digest",
4508 digest
.type
= siBuffer
;
4509 digest
.data
= hashBuf
;
4510 digest
.len
= fips_hashLen(hashType
);
4511 signature
.type
= siBuffer
;
4512 signature
.data
= sig
;
4513 signature
.len
= sizeof sig
;
4515 if (DSA_SignDigest(dsakey
, &signature
, &digest
) != SECSuccess
) {
4516 fprintf(dsaresp
, "ERROR: Unable to generate DSA signature");
4519 len
= signature
.len
;
4525 /* output the orginal Msg, and generated Y, R, and S */
4526 fputs(buf
, dsaresp
);
4527 to_hex_str(buf
, dsakey
->publicValue
.data
,
4528 dsakey
->publicValue
.len
);
4529 fprintf(dsaresp
, "Y = %s\n", buf
);
4530 to_hex_str(buf
, &signature
.data
[0], len
);
4531 fprintf(dsaresp
, "R = %s\n", buf
);
4532 to_hex_str(buf
, &signature
.data
[len
], len
);
4533 fprintf(dsaresp
, "S = %s\n", buf
);
4534 fputc('\n', dsaresp
);
4542 PQG_DestroyParams(pqg
);
4546 PQG_DestroyVerify(vfy
);
4550 PORT_FreeArena(dsakey
->params
.arena
, PR_TRUE
);
4556 * Perform the DSA Signature Verification Test.
4558 * reqfn is the pathname of the REQUEST file.
4560 * The output RESPONSE file is written to stdout.
4563 dsa_sigver_test(char *reqfn
)
4565 char buf
[800]; /* holds one line from the input REQUEST file
4566 * or to the output RESPONSE file.
4567 * max for Msg = ....
4569 FILE *dsareq
; /* input stream from the REQUEST file */
4570 FILE *dsaresp
; /* output stream to the RESPONSE file */
4574 SECItem digest
, signature
;
4575 DSAPublicKey pubkey
;
4576 unsigned int pgySize
; /* size for p, g, and y */
4577 unsigned char hashBuf
[HASH_LENGTH_MAX
]; /* SHA-x hash (160-512 bits) */
4578 unsigned char sig
[DSA_MAX_SIGNATURE_LEN
];
4579 HASH_HashType hashType
= HASH_AlgNULL
;
4582 dsareq
= fopen(reqfn
, "r");
4584 memset(&pubkey
, 0, sizeof(pubkey
));
4586 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
4587 /* a comment or blank line */
4588 if (buf
[0] == '#' || buf
[0] == '\n') {
4589 fputs(buf
, dsaresp
);
4594 if (buf
[0] == '[') {
4596 if (sscanf(buf
, "[mod = L=%d, N=%d, SHA-%d]", &L
, & N
,
4600 if (sscanf(buf
, "[mod = %d]", &L
) != 1) {
4605 if (pubkey
.params
.prime
.data
) { /* P */
4606 SECITEM_ZfreeItem(&pubkey
.params
.prime
, PR_FALSE
);
4608 if (pubkey
.params
.subPrime
.data
) { /* Q */
4609 SECITEM_ZfreeItem(&pubkey
.params
.subPrime
, PR_FALSE
);
4611 if (pubkey
.params
.base
.data
) { /* G */
4612 SECITEM_ZfreeItem(&pubkey
.params
.base
, PR_FALSE
);
4614 if (pubkey
.publicValue
.data
) { /* Y */
4615 SECITEM_ZfreeItem(&pubkey
.publicValue
, PR_FALSE
);
4617 fputs(buf
, dsaresp
);
4619 /* calculate the size of p, g, and y then allocate items */
4621 SECITEM_AllocItem(NULL
, &pubkey
.params
.prime
, pgySize
);
4622 SECITEM_AllocItem(NULL
, &pubkey
.params
.base
, pgySize
);
4623 SECITEM_AllocItem(NULL
, &pubkey
.publicValue
, pgySize
);
4624 pubkey
.params
.prime
.len
= pubkey
.params
.base
.len
= pgySize
;
4625 pubkey
.publicValue
.len
= pgySize
;
4627 /* q always N/8 bytes */
4628 SECITEM_AllocItem(NULL
, &pubkey
.params
.subPrime
, N
/8);
4629 pubkey
.params
.subPrime
.len
= N
/8;
4631 hashType
= sha_get_hashType(hashNum
);
4632 if (hashType
== HASH_AlgNULL
) {
4633 fprintf(dsaresp
, "ERROR: invalid hash (SHA-%d)",hashNum
);
4640 if (buf
[0] == 'P') {
4642 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4645 memset(pubkey
.params
.prime
.data
, 0, pubkey
.params
.prime
.len
);
4646 for (j
=0; j
< pubkey
.params
.prime
.len
; i
+=2,j
++) {
4647 hex_to_byteval(&buf
[i
], &pubkey
.params
.prime
.data
[j
]);
4650 fputs(buf
, dsaresp
);
4655 if (buf
[0] == 'Q') {
4657 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4660 memset(pubkey
.params
.subPrime
.data
, 0, pubkey
.params
.subPrime
.len
);
4661 for (j
=0; j
< pubkey
.params
.subPrime
.len
; i
+=2,j
++) {
4662 hex_to_byteval(&buf
[i
], &pubkey
.params
.subPrime
.data
[j
]);
4665 fputs(buf
, dsaresp
);
4670 if (buf
[0] == 'G') {
4672 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4675 memset(pubkey
.params
.base
.data
, 0, pubkey
.params
.base
.len
);
4676 for (j
=0; j
< pubkey
.params
.base
.len
; i
+=2,j
++) {
4677 hex_to_byteval(&buf
[i
], &pubkey
.params
.base
.data
[j
]);
4680 fputs(buf
, dsaresp
);
4685 if (strncmp(buf
, "Msg", 3) == 0) {
4686 unsigned char msg
[128]; /* MAX msg 128 */
4687 memset(hashBuf
, 0, sizeof hashBuf
);
4689 if (hashType
== HASH_AlgNULL
) {
4690 fprintf(dsaresp
, "ERROR: Hash Alg not set");
4695 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4698 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
4699 hex_to_byteval(&buf
[i
], &msg
[j
]);
4701 if (fips_hashBuf(hashType
, hashBuf
, msg
, j
) != SECSuccess
) {
4702 fprintf(dsaresp
, "ERROR: Unable to generate SHA-%d digest",
4707 fputs(buf
, dsaresp
);
4712 if (buf
[0] == 'Y') {
4714 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4717 memset(pubkey
.publicValue
.data
, 0, pubkey
.params
.subPrime
.len
);
4718 for (j
=0; j
< pubkey
.publicValue
.len
; i
+=2,j
++) {
4719 hex_to_byteval(&buf
[i
], &pubkey
.publicValue
.data
[j
]);
4722 fputs(buf
, dsaresp
);
4727 if (buf
[0] == 'R') {
4728 memset(sig
, 0, sizeof sig
);
4730 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4733 for (j
=0; j
< pubkey
.params
.subPrime
.len
; i
+=2,j
++) {
4734 hex_to_byteval(&buf
[i
], &sig
[j
]);
4737 fputs(buf
, dsaresp
);
4742 if (buf
[0] == 'S') {
4743 if (hashType
== HASH_AlgNULL
) {
4744 fprintf(dsaresp
, "ERROR: Hash Alg not set");
4749 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4752 for (j
=pubkey
.params
.subPrime
.len
;
4753 j
< pubkey
.params
.subPrime
.len
*2; i
+=2,j
++) {
4754 hex_to_byteval(&buf
[i
], &sig
[j
]);
4756 fputs(buf
, dsaresp
);
4758 digest
.type
= siBuffer
;
4759 digest
.data
= hashBuf
;
4760 digest
.len
= fips_hashLen(hashType
);
4761 signature
.type
= siBuffer
;
4762 signature
.data
= sig
;
4763 signature
.len
= pubkey
.params
.subPrime
.len
*2;
4765 if (DSA_VerifyDigest(&pubkey
, &signature
, &digest
) == SECSuccess
) {
4766 fprintf(dsaresp
, "Result = P\n");
4768 fprintf(dsaresp
, "Result = F\n");
4770 fprintf(dsaresp
, "\n");
4776 if (pubkey
.params
.prime
.data
) { /* P */
4777 SECITEM_ZfreeItem(&pubkey
.params
.prime
, PR_FALSE
);
4779 if (pubkey
.params
.subPrime
.data
) { /* Q */
4780 SECITEM_ZfreeItem(&pubkey
.params
.subPrime
, PR_FALSE
);
4782 if (pubkey
.params
.base
.data
) { /* G */
4783 SECITEM_ZfreeItem(&pubkey
.params
.base
, PR_FALSE
);
4785 if (pubkey
.publicValue
.data
) { /* Y */
4786 SECITEM_ZfreeItem(&pubkey
.publicValue
, PR_FALSE
);
4791 * Perform the RSA Signature Generation Test.
4793 * reqfn is the pathname of the REQUEST file.
4795 * The output RESPONSE file is written to stdout.
4798 rsa_siggen_test(char *reqfn
)
4800 char buf
[2*RSA_MAX_TEST_MODULUS_BYTES
+1];
4801 /* buf holds one line from the input REQUEST file
4802 * or to the output RESPONSE file.
4803 * 2x for HEX output + 1 for \n
4805 FILE *rsareq
; /* input stream from the REQUEST file */
4806 FILE *rsaresp
; /* output stream to the RESPONSE file */
4808 unsigned char sha
[HASH_LENGTH_MAX
]; /* SHA digest */
4809 unsigned int shaLength
= 0; /* length of SHA */
4810 HASH_HashType shaAlg
= HASH_AlgNULL
; /* type of SHA Alg */
4811 SECOidTag shaOid
= SEC_OID_UNKNOWN
;
4812 int modulus
; /* the Modulus size */
4813 int publicExponent
= DEFAULT_RSA_PUBLIC_EXPONENT
;
4814 SECItem pe
= {0, 0, 0 };
4815 unsigned char pubEx
[4];
4818 RSAPrivateKey
*rsaBlapiPrivKey
= NULL
; /* holds RSA private and
4820 RSAPublicKey
*rsaBlapiPublicKey
= NULL
; /* hold RSA public key */
4822 rsareq
= fopen(reqfn
, "r");
4825 /* calculate the exponent */
4826 for (i
=0; i
< 4; i
++) {
4827 if (peCount
|| (publicExponent
&
4828 ((unsigned long)0xff000000L
>> (i
*8)))) {
4830 (unsigned char)((publicExponent
>> (3-i
)*8) & 0xff);
4835 pe
.data
= &pubEx
[0];
4838 while (fgets(buf
, sizeof buf
, rsareq
) != NULL
) {
4839 /* a comment or blank line */
4840 if (buf
[0] == '#' || buf
[0] == '\n') {
4841 fputs(buf
, rsaresp
);
4846 if (buf
[0] == '[') {
4848 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
4851 if (modulus
> RSA_MAX_TEST_MODULUS_BITS
) {
4852 fprintf(rsaresp
,"ERROR: modulus greater than test maximum\n");
4856 fputs(buf
, rsaresp
);
4858 if (rsaBlapiPrivKey
!= NULL
) {
4859 PORT_FreeArena(rsaBlapiPrivKey
->arena
, PR_TRUE
);
4860 rsaBlapiPrivKey
= NULL
;
4861 rsaBlapiPublicKey
= NULL
;
4864 rsaBlapiPrivKey
= RSA_NewKey(modulus
, &pe
);
4865 if (rsaBlapiPrivKey
== NULL
) {
4866 fprintf(rsaresp
, "Error unable to create RSA key\n");
4870 to_hex_str(buf
, rsaBlapiPrivKey
->modulus
.data
,
4871 rsaBlapiPrivKey
->modulus
.len
);
4872 fprintf(rsaresp
, "\nn = %s\n\n", buf
);
4873 to_hex_str(buf
, rsaBlapiPrivKey
->publicExponent
.data
,
4874 rsaBlapiPrivKey
->publicExponent
.len
);
4875 fprintf(rsaresp
, "e = %s\n", buf
);
4876 /* convert private key to public key. Memory
4877 * is freed with private key's arena */
4878 rsaBlapiPublicKey
= (RSAPublicKey
*)PORT_ArenaAlloc(
4879 rsaBlapiPrivKey
->arena
,
4880 sizeof(RSAPublicKey
));
4882 rsaBlapiPublicKey
->modulus
.len
= rsaBlapiPrivKey
->modulus
.len
;
4883 rsaBlapiPublicKey
->modulus
.data
= rsaBlapiPrivKey
->modulus
.data
;
4884 rsaBlapiPublicKey
->publicExponent
.len
=
4885 rsaBlapiPrivKey
->publicExponent
.len
;
4886 rsaBlapiPublicKey
->publicExponent
.data
=
4887 rsaBlapiPrivKey
->publicExponent
.data
;
4892 if (strncmp(buf
, "SHAAlg", 6) == 0) {
4894 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4897 /* set the SHA Algorithm */
4898 if (strncmp(&buf
[i
], "SHA1", 4) == 0) {
4899 shaAlg
= HASH_AlgSHA1
;
4900 } else if (strncmp(&buf
[i
], "SHA224", 6) == 0) {
4901 shaAlg
= HASH_AlgSHA224
;
4902 } else if (strncmp(&buf
[i
], "SHA256", 6) == 0) {
4903 shaAlg
= HASH_AlgSHA256
;
4904 } else if (strncmp(&buf
[i
], "SHA384", 6)== 0) {
4905 shaAlg
= HASH_AlgSHA384
;
4906 } else if (strncmp(&buf
[i
], "SHA512", 6) == 0) {
4907 shaAlg
= HASH_AlgSHA512
;
4909 fprintf(rsaresp
, "ERROR: Unable to find SHAAlg type");
4912 fputs(buf
, rsaresp
);
4917 if (strncmp(buf
, "Msg", 3) == 0) {
4919 unsigned char msg
[128]; /* MAX msg 128 */
4920 unsigned int rsa_bytes_signed
;
4921 unsigned char rsa_computed_signature
[RSA_MAX_TEST_MODULUS_BYTES
];
4922 SECStatus rv
= SECFailure
;
4923 NSSLOWKEYPublicKey
* rsa_public_key
;
4924 NSSLOWKEYPrivateKey
* rsa_private_key
;
4925 NSSLOWKEYPrivateKey low_RSA_private_key
= { NULL
,
4927 NSSLOWKEYPublicKey low_RSA_public_key
= { NULL
,
4930 low_RSA_private_key
.u
.rsa
= *rsaBlapiPrivKey
;
4931 low_RSA_public_key
.u
.rsa
= *rsaBlapiPublicKey
;
4933 rsa_private_key
= &low_RSA_private_key
;
4934 rsa_public_key
= &low_RSA_public_key
;
4936 memset(sha
, 0, sizeof sha
);
4937 memset(msg
, 0, sizeof msg
);
4938 rsa_bytes_signed
= 0;
4939 memset(rsa_computed_signature
, 0, sizeof rsa_computed_signature
);
4942 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4945 for (j
=0; isxdigit(buf
[i
]) && j
< sizeof(msg
); i
+=2,j
++) {
4946 hex_to_byteval(&buf
[i
], &msg
[j
]);
4948 shaLength
= fips_hashLen(shaAlg
);
4949 if (fips_hashBuf(shaAlg
,sha
,msg
,j
) != SECSuccess
) {
4950 if (shaLength
== 0) {
4951 fprintf(rsaresp
, "ERROR: SHAAlg not defined.");
4953 fprintf(rsaresp
, "ERROR: Unable to generate SHA%x",
4954 shaLength
== 160 ? 1 : shaLength
);
4957 shaOid
= fips_hashOid(shaAlg
);
4959 /* Perform RSA signature with the RSA private key. */
4960 rv
= RSA_HashSign( shaOid
,
4962 rsa_computed_signature
,
4964 nsslowkey_PrivateModulusLen(rsa_private_key
),
4968 if( rv
!= SECSuccess
) {
4969 fprintf(rsaresp
, "ERROR: RSA_HashSign failed");
4973 /* Output the signature */
4974 fputs(buf
, rsaresp
);
4975 to_hex_str(buf
, rsa_computed_signature
, rsa_bytes_signed
);
4976 fprintf(rsaresp
, "S = %s\n", buf
);
4978 /* Perform RSA verification with the RSA public key. */
4979 rv
= RSA_HashCheckSign( shaOid
,
4981 rsa_computed_signature
,
4985 if( rv
!= SECSuccess
) {
4986 fprintf(rsaresp
, "ERROR: RSA_HashCheckSign failed");
4995 if (rsaBlapiPrivKey
!= NULL
) {
4996 /* frees private and public key */
4997 PORT_FreeArena(rsaBlapiPrivKey
->arena
, PR_TRUE
);
4998 rsaBlapiPrivKey
= NULL
;
4999 rsaBlapiPublicKey
= NULL
;
5004 * Perform the RSA Signature Verification Test.
5006 * reqfn is the pathname of the REQUEST file.
5008 * The output RESPONSE file is written to stdout.
5011 rsa_sigver_test(char *reqfn
)
5013 char buf
[2*RSA_MAX_TEST_MODULUS_BYTES
+7];
5014 /* buf holds one line from the input REQUEST file
5015 * or to the output RESPONSE file.
5016 * s = 2x for HEX output + 1 for \n
5018 FILE *rsareq
; /* input stream from the REQUEST file */
5019 FILE *rsaresp
; /* output stream to the RESPONSE file */
5021 unsigned char sha
[HASH_LENGTH_MAX
]; /* SHA digest */
5022 unsigned int shaLength
= 0; /* actual length of the digest */
5023 HASH_HashType shaAlg
= HASH_AlgNULL
;
5024 SECOidTag shaOid
= SEC_OID_UNKNOWN
;
5025 int modulus
= 0; /* the Modulus size */
5026 unsigned char signature
[513]; /* largest signature size + '\n' */
5027 unsigned int signatureLength
= 0; /* actual length of the signature */
5028 PRBool keyvalid
= PR_TRUE
;
5030 RSAPublicKey rsaBlapiPublicKey
; /* hold RSA public key */
5032 rsareq
= fopen(reqfn
, "r");
5034 memset(&rsaBlapiPublicKey
, 0, sizeof(RSAPublicKey
));
5036 while (fgets(buf
, sizeof buf
, rsareq
) != NULL
) {
5037 /* a comment or blank line */
5038 if (buf
[0] == '#' || buf
[0] == '\n') {
5039 fputs(buf
, rsaresp
);
5044 if (buf
[0] == '[') {
5045 unsigned int flen
; /* length in bytes of the field size */
5047 if (rsaBlapiPublicKey
.modulus
.data
) { /* n */
5048 SECITEM_ZfreeItem(&rsaBlapiPublicKey
.modulus
, PR_FALSE
);
5050 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
5054 if (modulus
> RSA_MAX_TEST_MODULUS_BITS
) {
5055 fprintf(rsaresp
,"ERROR: modulus greater than test maximum\n");
5059 fputs(buf
, rsaresp
);
5061 signatureLength
= flen
= modulus
/8;
5063 SECITEM_AllocItem(NULL
, &rsaBlapiPublicKey
.modulus
, flen
);
5064 if (rsaBlapiPublicKey
.modulus
.data
== NULL
) {
5070 /* n = ... modulus */
5071 if (buf
[0] == 'n') {
5073 while (isspace(buf
[i
]) || buf
[i
] == '=') {
5076 keyvalid
= from_hex_str(&rsaBlapiPublicKey
.modulus
.data
[0],
5077 rsaBlapiPublicKey
.modulus
.len
,
5081 fprintf(rsaresp
, "ERROR: rsa_sigver n not valid.\n");
5084 fputs(buf
, rsaresp
);
5089 if (strncmp(buf
, "SHAAlg", 6) == 0) {
5091 while (isspace(buf
[i
]) || buf
[i
] == '=') {
5094 /* set the SHA Algorithm */
5095 if (strncmp(&buf
[i
], "SHA1", 4) == 0) {
5096 shaAlg
= HASH_AlgSHA1
;
5097 } else if (strncmp(&buf
[i
], "SHA224", 6) == 0) {
5098 shaAlg
= HASH_AlgSHA224
;
5099 } else if (strncmp(&buf
[i
], "SHA256", 6) == 0) {
5100 shaAlg
= HASH_AlgSHA256
;
5101 } else if (strncmp(&buf
[i
], "SHA384", 6) == 0) {
5102 shaAlg
= HASH_AlgSHA384
;
5103 } else if (strncmp(&buf
[i
], "SHA512", 6) == 0) {
5104 shaAlg
= HASH_AlgSHA512
;
5106 fprintf(rsaresp
, "ERROR: Unable to find SHAAlg type");
5109 fputs(buf
, rsaresp
);
5113 /* e = ... public Key */
5114 if (buf
[0] == 'e') {
5115 unsigned char data
[RSA_MAX_TEST_EXPONENT_BYTES
];
5118 memset(data
, 0, sizeof data
);
5120 if (rsaBlapiPublicKey
.publicExponent
.data
) { /* e */
5121 SECITEM_ZfreeItem(&rsaBlapiPublicKey
.publicExponent
, PR_FALSE
);
5125 while (isspace(buf
[i
]) || buf
[i
] == '=') {
5128 /* skip leading zero's */
5129 while (isxdigit(buf
[i
])) {
5130 hex_to_byteval(&buf
[i
], &t
);
5136 /* get the exponent */
5137 for (j
=0; isxdigit(buf
[i
]) && j
< sizeof data
; i
+=2,j
++) {
5138 hex_to_byteval(&buf
[i
], &data
[j
]);
5141 if (j
== 0) { j
= 1; } /* to handle 1 byte length exponents */
5143 SECITEM_AllocItem(NULL
, &rsaBlapiPublicKey
.publicExponent
, j
);
5144 if (rsaBlapiPublicKey
.publicExponent
.data
== NULL
) {
5148 for (i
=0; i
< j
; i
++) {
5149 rsaBlapiPublicKey
.publicExponent
.data
[i
] = data
[i
];
5152 fputs(buf
, rsaresp
);
5157 if (strncmp(buf
, "Msg", 3) == 0) {
5158 unsigned char msg
[128]; /* MAX msg 128 */
5160 memset(sha
, 0, sizeof sha
);
5161 memset(msg
, 0, sizeof msg
);
5164 while (isspace(buf
[i
]) || buf
[i
] == '=') {
5168 for (j
=0; isxdigit(buf
[i
]) && j
< sizeof msg
; i
+=2,j
++) {
5169 hex_to_byteval(&buf
[i
], &msg
[j
]);
5172 shaLength
= fips_hashLen(shaAlg
);
5173 if (fips_hashBuf(shaAlg
,sha
,msg
,j
) != SECSuccess
) {
5174 if (shaLength
== 0) {
5175 fprintf(rsaresp
, "ERROR: SHAAlg not defined.");
5177 fprintf(rsaresp
, "ERROR: Unable to generate SHA%x",
5178 shaLength
== 160 ? 1 : shaLength
);
5182 fputs(buf
, rsaresp
);
5188 if (buf
[0] == 'S') {
5189 SECStatus rv
= SECFailure
;
5190 NSSLOWKEYPublicKey
* rsa_public_key
;
5191 NSSLOWKEYPublicKey low_RSA_public_key
= { NULL
,
5194 /* convert to a low RSA public key */
5195 low_RSA_public_key
.u
.rsa
= rsaBlapiPublicKey
;
5196 rsa_public_key
= &low_RSA_public_key
;
5198 memset(signature
, 0, sizeof(signature
));
5200 while (isspace(buf
[i
]) || buf
[i
] == '=') {
5204 for (j
=0; isxdigit(buf
[i
]) && j
< sizeof signature
; i
+=2,j
++) {
5205 hex_to_byteval(&buf
[i
], &signature
[j
]);
5208 signatureLength
= j
;
5209 fputs(buf
, rsaresp
);
5211 /* Perform RSA verification with the RSA public key. */
5212 rv
= RSA_HashCheckSign( shaOid
,
5218 if( rv
== SECSuccess
) {
5219 fputs("Result = P\n", rsaresp
);
5221 fputs("Result = F\n", rsaresp
);
5228 if (rsaBlapiPublicKey
.modulus
.data
) { /* n */
5229 SECITEM_ZfreeItem(&rsaBlapiPublicKey
.modulus
, PR_FALSE
);
5231 if (rsaBlapiPublicKey
.publicExponent
.data
) { /* e */
5232 SECITEM_ZfreeItem(&rsaBlapiPublicKey
.publicExponent
, PR_FALSE
);
5236 int main(int argc
, char **argv
)
5238 if (argc
< 2) exit (-1);
5246 if (strcmp(argv
[1], "tdea") == 0) {
5247 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
5248 if (strcmp(argv
[2], "kat") == 0) {
5249 /* Known Answer Test (KAT) */
5250 tdea_kat_mmt(argv
[4]);
5251 } else if (strcmp(argv
[2], "mmt") == 0) {
5252 /* Multi-block Message Test (MMT) */
5253 tdea_kat_mmt(argv
[4]);
5254 } else if (strcmp(argv
[2], "mct") == 0) {
5255 /* Monte Carlo Test (MCT) */
5256 if (strcmp(argv
[3], "ecb") == 0) {
5258 tdea_mct(NSS_DES_EDE3
, argv
[4]);
5259 } else if (strcmp(argv
[3], "cbc") == 0) {
5261 tdea_mct(NSS_DES_EDE3_CBC
, argv
[4]);
5267 } else if (strcmp(argv
[1], "aes") == 0) {
5268 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
5269 if ( strcmp(argv
[2], "kat") == 0) {
5270 /* Known Answer Test (KAT) */
5271 aes_kat_mmt(argv
[4]);
5272 } else if (strcmp(argv
[2], "mmt") == 0) {
5273 /* Multi-block Message Test (MMT) */
5274 aes_kat_mmt(argv
[4]);
5275 } else if (strcmp(argv
[2], "mct") == 0) {
5276 /* Monte Carlo Test (MCT) */
5277 if ( strcmp(argv
[3], "ecb") == 0) {
5279 aes_ecb_mct(argv
[4]);
5280 } else if (strcmp(argv
[3], "cbc") == 0) {
5282 aes_cbc_mct(argv
[4]);
5288 } else if (strcmp(argv
[1], "sha") == 0) {
5293 } else if (strcmp(argv
[1], "rsa") == 0) {
5294 /* argv[2]=siggen|sigver */
5295 /* argv[3]=<test name>.req */
5296 if (strcmp(argv
[2], "siggen") == 0) {
5297 /* Signature Generation Test */
5298 rsa_siggen_test(argv
[3]);
5299 } else if (strcmp(argv
[2], "sigver") == 0) {
5300 /* Signature Verification Test */
5301 rsa_sigver_test(argv
[3]);
5306 } else if (strcmp(argv
[1], "hmac") == 0) {
5311 } else if (strcmp(argv
[1], "dsa") == 0) {
5312 /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */
5313 /* argv[3]=<test name>.req */
5314 if (strcmp(argv
[2], "keypair") == 0) {
5315 /* Key Pair Generation Test */
5316 dsa_keypair_test(argv
[3]);
5317 } else if (strcmp(argv
[2], "pqggen") == 0) {
5318 /* Domain Parameter Generation Test */
5319 dsa_pqggen_test(argv
[3]);
5320 } else if (strcmp(argv
[2], "pqgver") == 0) {
5321 /* Domain Parameter Validation Test */
5322 dsa_pqgver_test(argv
[3]);
5323 } else if (strcmp(argv
[2], "siggen") == 0) {
5324 /* Signature Generation Test */
5325 dsa_siggen_test(argv
[3]);
5326 } else if (strcmp(argv
[2], "sigver") == 0) {
5327 /* Signature Verification Test */
5328 dsa_sigver_test(argv
[3]);
5330 #ifndef NSS_DISABLE_ECC
5334 } else if (strcmp(argv
[1], "ecdsa") == 0) {
5335 /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */
5336 if ( strcmp(argv
[2], "keypair") == 0) {
5337 /* Key Pair Generation Test */
5338 ecdsa_keypair_test(argv
[3]);
5339 } else if (strcmp(argv
[2], "pkv") == 0) {
5340 /* Public Key Validation Test */
5341 ecdsa_pkv_test(argv
[3]);
5342 } else if (strcmp(argv
[2], "siggen") == 0) {
5343 /* Signature Generation Test */
5344 ecdsa_siggen_test(argv
[3]);
5345 } else if (strcmp(argv
[2], "sigver") == 0) {
5346 /* Signature Verification Test */
5347 ecdsa_sigver_test(argv
[3]);
5349 #endif /* NSS_DISABLE_ECC */
5353 } else if (strcmp(argv
[1], "rng") == 0) {
5354 /* argv[2]=vst|mct argv[3]=<test name>.req */
5355 if ( strcmp(argv
[2], "vst") == 0) {
5356 /* Variable Seed Test */
5358 } else if (strcmp(argv
[2], "mct") == 0) {
5359 /* Monte Carlo Test */
5362 } else if (strcmp(argv
[1], "drbg") == 0) {
5363 /* Variable Seed Test */
5365 } else if (strcmp(argv
[1], "ddrbg") == 0) {