1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
55 #include "../../lib/freebl/mpi/mpi.h"
60 EC_DecodeParams(const SECItem
*encodedParams
, ECParams
**ecparams
);
62 EC_CopyParams(PRArenaPool
*arena
, ECParams
*dstParams
,
63 const ECParams
*srcParams
);
68 #define BYTE unsigned char
69 #define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001
70 #define RSA_MAX_TEST_MODULUS_BITS 4096
71 #define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS/8
72 #define RSA_MAX_TEST_EXPONENT_BYTES 8
73 #define PQG_TEST_SEED_BYTES 20
76 hex_to_byteval(const char *c2
, unsigned char *byteval
)
82 if (c2
[i
] >= '0' && c2
[i
] <= '9') {
84 *byteval
|= offset
<< 4*(1-i
);
85 } else if (c2
[i
] >= 'a' && c2
[i
] <= 'f') {
87 *byteval
|= (offset
+ 10) << 4*(1-i
);
88 } else if (c2
[i
] >= 'A' && c2
[i
] <= 'F') {
90 *byteval
|= (offset
+ 10) << 4*(1-i
);
99 byteval_to_hex(unsigned char byteval
, char *c2
, char a
)
102 unsigned char offset
;
103 for (i
=0; i
<2; i
++) {
104 offset
= (byteval
>> 4*(1-i
)) & 0x0f;
106 c2
[i
] = '0' + offset
;
108 c2
[i
] = a
+ offset
- 10;
115 to_hex_str(char *str
, const unsigned char *buf
, unsigned int len
)
118 for (i
=0; i
<len
; i
++) {
119 byteval_to_hex(buf
[i
], &str
[2*i
], 'a');
125 to_hex_str_cap(char *str
, const unsigned char *buf
, unsigned int len
)
128 for (i
=0; i
<len
; i
++) {
129 byteval_to_hex(buf
[i
], &str
[2*i
], 'A');
135 * Convert a string of hex digits (str) to an array (buf) of len bytes.
136 * Return PR_TRUE if the hex string can fit in the byte array. Return
137 * PR_FALSE if the hex string is empty or is too long.
140 from_hex_str(unsigned char *buf
, unsigned int len
, const char *str
)
142 unsigned int nxdigit
; /* number of hex digits in str */
143 unsigned int i
; /* index into buf */
144 unsigned int j
; /* index into str */
146 /* count the hex digits */
148 for (nxdigit
= 0; isxdigit(str
[nxdigit
]); nxdigit
++) {
154 if (nxdigit
> 2*len
) {
156 * The input hex string is too long, but we allow it if the
157 * extra digits are leading 0's.
159 for (j
= 0; j
< nxdigit
-2*len
; j
++) {
164 /* skip leading 0's */
165 str
+= nxdigit
-2*len
;
168 for (i
=0, j
=0; i
< len
; i
++) {
169 if (2*i
< 2*len
-nxdigit
) {
170 /* Handle a short input as if we padded it with leading 0's. */
171 if (2*i
+1 < 2*len
-nxdigit
) {
177 hex_to_byteval(tmp
, &buf
[i
]);
181 hex_to_byteval(&str
[j
], &buf
[i
]);
191 const unsigned char *key
,
192 const unsigned char *iv
,
193 unsigned char *output
, unsigned int *outputlen
, unsigned int maxoutputlen
,
194 const unsigned char *input
, unsigned int inputlen
)
196 SECStatus rv
= SECFailure
;
198 unsigned char doublecheck
[8*20]; /* 1 to 20 blocks */
199 unsigned int doublechecklen
= 0;
201 cx
= DES_CreateContext(key
, iv
, mode
, PR_TRUE
);
205 rv
= DES_Encrypt(cx
, output
, outputlen
, maxoutputlen
, input
, inputlen
);
206 if (rv
!= SECSuccess
) {
209 if (*outputlen
!= inputlen
) {
212 DES_DestroyContext(cx
, PR_TRUE
);
216 * Doublecheck our result by decrypting the ciphertext and
217 * compare the output with the input plaintext.
219 cx
= DES_CreateContext(key
, iv
, mode
, PR_FALSE
);
223 rv
= DES_Decrypt(cx
, doublecheck
, &doublechecklen
, sizeof doublecheck
,
225 if (rv
!= SECSuccess
) {
228 if (doublechecklen
!= *outputlen
) {
231 DES_DestroyContext(cx
, PR_TRUE
);
233 if (memcmp(doublecheck
, input
, inputlen
) != 0) {
240 DES_DestroyContext(cx
, PR_TRUE
);
248 const unsigned char *key
,
249 const unsigned char *iv
,
250 unsigned char *output
, unsigned int *outputlen
, unsigned int maxoutputlen
,
251 const unsigned char *input
, unsigned int inputlen
)
253 SECStatus rv
= SECFailure
;
255 unsigned char doublecheck
[8*20]; /* 1 to 20 blocks */
256 unsigned int doublechecklen
= 0;
258 cx
= DES_CreateContext(key
, iv
, mode
, PR_FALSE
);
262 rv
= DES_Decrypt(cx
, output
, outputlen
, maxoutputlen
,
264 if (rv
!= SECSuccess
) {
267 if (*outputlen
!= inputlen
) {
270 DES_DestroyContext(cx
, PR_TRUE
);
274 * Doublecheck our result by encrypting the plaintext and
275 * compare the output with the input ciphertext.
277 cx
= DES_CreateContext(key
, iv
, mode
, PR_TRUE
);
281 rv
= DES_Encrypt(cx
, doublecheck
, &doublechecklen
, sizeof doublecheck
,
283 if (rv
!= SECSuccess
) {
286 if (doublechecklen
!= *outputlen
) {
289 DES_DestroyContext(cx
, PR_TRUE
);
291 if (memcmp(doublecheck
, input
, inputlen
) != 0) {
298 DES_DestroyContext(cx
, PR_TRUE
);
304 * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
305 * Test (MMT) in ECB or CBC mode. The KAT (there are five types)
306 * and MMT have the same structure: given the key and IV (CBC mode
307 * only), encrypt the given plaintext or decrypt the given ciphertext.
308 * So we can handle them the same way.
310 * reqfn is the pathname of the REQUEST file.
312 * The output RESPONSE file is written to stdout.
315 tdea_kat_mmt(char *reqfn
)
317 char buf
[180]; /* holds one line from the input REQUEST file.
318 * needs to be large enough to hold the longest
319 * line "CIPHERTEXT = <180 hex digits>\n".
321 FILE *req
; /* input stream from the REQUEST file */
322 FILE *resp
; /* output stream to the RESPONSE file */
324 int mode
; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
325 int crypt
= DECRYPT
; /* 1 means encrypt, 0 means decrypt */
326 unsigned char key
[24]; /* TDEA 3 key bundle */
327 unsigned int numKeys
= 0;
328 unsigned char iv
[8]; /* for all modes except ECB */
329 unsigned char plaintext
[8*20]; /* 1 to 20 blocks */
330 unsigned int plaintextlen
;
331 unsigned char ciphertext
[8*20]; /* 1 to 20 blocks */
332 unsigned int ciphertextlen
;
335 req
= fopen(reqfn
, "r");
337 while (fgets(buf
, sizeof buf
, req
) != NULL
) {
338 /* a comment or blank line */
339 if (buf
[0] == '#' || buf
[0] == '\n') {
343 /* [ENCRYPT] or [DECRYPT] */
345 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
354 if (strncmp(&buf
[0], "NumKeys", 7) == 0) {
356 while (isspace(buf
[i
]) || buf
[i
] == '=') {
363 /* "COUNT = x" begins a new data set */
364 if (strncmp(buf
, "COUNT", 5) == 0) {
365 /* mode defaults to ECB, if dataset has IV mode will be set CBC */
367 /* zeroize the variables for the test with this data set */
368 memset(key
, 0, sizeof key
);
369 memset(iv
, 0, sizeof iv
);
370 memset(plaintext
, 0, sizeof plaintext
);
372 memset(ciphertext
, 0, sizeof ciphertext
);
378 if (strncmp(buf
, "KEYs", 4) == 0) {
380 while (isspace(buf
[i
]) || buf
[i
] == '=') {
383 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
384 hex_to_byteval(&buf
[i
], &key
[j
]);
393 if (strncmp(buf
, "KEY1", 4) == 0) {
395 while (isspace(buf
[i
]) || buf
[i
] == '=') {
398 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
399 hex_to_byteval(&buf
[i
], &key
[j
]);
405 if (strncmp(buf
, "KEY2", 4) == 0) {
407 while (isspace(buf
[i
]) || buf
[i
] == '=') {
410 for (j
=8; isxdigit(buf
[i
]); i
+=2,j
++) {
411 hex_to_byteval(&buf
[i
], &key
[j
]);
417 if (strncmp(buf
, "KEY3", 4) == 0) {
419 while (isspace(buf
[i
]) || buf
[i
] == '=') {
422 for (j
=16; isxdigit(buf
[i
]); i
+=2,j
++) {
423 hex_to_byteval(&buf
[i
], &key
[j
]);
431 if (strncmp(buf
, "IV", 2) == 0) {
432 mode
= NSS_DES_EDE3_CBC
;
434 while (isspace(buf
[i
]) || buf
[i
] == '=') {
437 for (j
=0; j
<sizeof iv
; i
+=2,j
++) {
438 hex_to_byteval(&buf
[i
], &iv
[j
]);
444 /* PLAINTEXT = ... */
445 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
447 if (crypt
!= ENCRYPT
) {
451 while (isspace(buf
[i
]) || buf
[i
] == '=') {
454 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
455 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
458 rv
= tdea_encrypt_buf(mode
, key
,
459 (mode
== NSS_DES_EDE3
) ? NULL
: iv
,
460 ciphertext
, &ciphertextlen
, sizeof ciphertext
,
461 plaintext
, plaintextlen
);
462 if (rv
!= SECSuccess
) {
467 fputs("CIPHERTEXT = ", resp
);
468 to_hex_str(buf
, ciphertext
, ciphertextlen
);
473 /* CIPHERTEXT = ... */
474 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
476 if (crypt
!= DECRYPT
) {
481 while (isspace(buf
[i
]) || buf
[i
] == '=') {
484 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
485 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
489 rv
= tdea_decrypt_buf(mode
, key
,
490 (mode
== NSS_DES_EDE3
) ? NULL
: iv
,
491 plaintext
, &plaintextlen
, sizeof plaintext
,
492 ciphertext
, ciphertextlen
);
493 if (rv
!= SECSuccess
) {
498 fputs("PLAINTEXT = ", resp
);
499 to_hex_str(buf
, plaintext
, plaintextlen
);
511 * Set the parity bit for the given byte
513 BYTE
odd_parity( BYTE in
)
519 return (BYTE
)(out
^ !(in
& 1));
523 * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j]
524 * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
527 tdea_mct_next_keys(unsigned char *key
,
528 const unsigned char *text_2
, const unsigned char *text_1
,
529 const unsigned char *text
, unsigned int numKeys
)
533 /* key1[i+1] = key1[i] xor PT/CT[j] */
534 for (k
=0; k
<8; k
++) {
538 if (numKeys
== 2 || numKeys
== 3) {
539 /* key2 independent */
540 for (k
=8; k
<16; k
++) {
541 /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
542 key
[k
] ^= text_1
[k
-8];
546 for (k
=8; k
<16; k
++) {
547 /* key2[i+1] = KEY2[i] xor PT/CT[j] */
552 if (numKeys
== 1 || numKeys
== 2) {
554 for (k
=16; k
<24; k
++) {
555 /* key3[i+1] = KEY3[i] xor PT/CT[j] */
559 /* key3 independent */
560 for (k
=16; k
<24; k
++) {
561 /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
562 key
[k
] ^= text_2
[k
-16];
565 /* set the parity bits */
566 for (k
=0; k
<24; k
++) {
567 key
[k
] = odd_parity(key
[k
]);
572 * Perform the Monte Carlo Test
574 * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
575 * crypt = ENCRYPT || DECRYPT
576 * inputtext = plaintext or Cyphertext depending on the value of crypt
577 * inputlength is expected to be size 8 bytes
578 * iv = needs to be set for NSS_DES_EDE3_CBC mode
579 * resp = is the output response file.
582 tdea_mct_test(int mode
, unsigned char* key
, unsigned int numKeys
,
583 unsigned int crypt
, unsigned char* inputtext
,
584 unsigned int inputlength
, unsigned char* iv
, FILE *resp
) {
587 unsigned char outputtext_1
[8]; /* PT/CT[j-1] */
588 unsigned char outputtext_2
[8]; /* PT/CT[j-2] */
589 char buf
[80]; /* holds one line from the input REQUEST file. */
590 unsigned int outputlen
;
591 unsigned char outputtext
[8];
596 if (mode
== NSS_DES_EDE3
&& iv
!= NULL
) {
597 printf("IV must be NULL for NSS_DES_EDE3 mode");
599 } else if (mode
== NSS_DES_EDE3_CBC
&& iv
== NULL
) {
600 printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
605 for (i
=0; i
<400; i
++) {
606 /* if i == 0 CV[0] = IV not necessary */
607 /* record the count and key values and plainText */
608 sprintf(buf
, "COUNT = %d\n", i
);
611 fputs("KEY1 = ", resp
);
612 to_hex_str(buf
, key
, 8);
616 fputs("KEY2 = ", resp
);
617 to_hex_str(buf
, &key
[8], 8);
621 fputs("KEY3 = ", resp
);
622 to_hex_str(buf
, &key
[16], 8);
625 if (mode
== NSS_DES_EDE3_CBC
) {
627 fputs("IV = ", resp
);
628 to_hex_str(buf
, iv
, 8);
632 if (crypt
== ENCRYPT
) {
634 fputs("PLAINTEXT = ", resp
);
637 fputs("CIPHERTEXT = ", resp
);
640 to_hex_str(buf
, inputtext
, inputlength
);
644 /* loop 10,000 times */
645 for (j
=0; j
<10000; j
++) {
648 if (crypt
== ENCRYPT
) {
649 /* inputtext == ciphertext outputtext == plaintext*/
650 rv
= tdea_encrypt_buf(mode
, key
,
651 (mode
== NSS_DES_EDE3
) ? NULL
: iv
,
652 outputtext
, &outputlen
, 8,
655 /* inputtext == plaintext outputtext == ciphertext */
656 rv
= tdea_decrypt_buf(mode
, key
,
657 (mode
== NSS_DES_EDE3
) ? NULL
: iv
,
658 outputtext
, &outputlen
, 8,
662 if (rv
!= SECSuccess
) {
665 if (outputlen
!= inputlength
) {
669 if (mode
== NSS_DES_EDE3_CBC
) {
670 if (crypt
== ENCRYPT
) {
673 memcpy(inputtext
, iv
, 8);
675 /* p[j+1] = C[j-1] */
676 memcpy(inputtext
, outputtext_1
, 8);
679 memcpy(iv
, outputtext
, 8);
682 memcpy(outputtext_1
, outputtext
, 8);
684 } else { /* DECRYPT */
686 memcpy(iv
, inputtext
, 8);
688 memcpy(inputtext
, outputtext
, 8);
691 /* ECB mode PT/CT[j+1] = CT/PT[j] */
692 memcpy(inputtext
, outputtext
, 8);
695 /* Save PT/CT[j-2] and PT/CT[j-1] */
696 if (j
==9997) memcpy(outputtext_2
, outputtext
, 8);
697 if (j
==9998) memcpy(outputtext_1
, outputtext
, 8);
698 /* done at the end of the for(j) loop */
702 if (crypt
== ENCRYPT
) {
704 fputs("CIPHERTEXT = ", resp
);
707 fputs("PLAINTEXT = ", resp
);
709 to_hex_str(buf
, outputtext
, 8);
713 /* Key[i+1] = Key[i] xor ... outputtext_2 == PT/CT[j-2]
714 * outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j]
716 tdea_mct_next_keys(key
, outputtext_2
,
717 outputtext_1
, outputtext
, numKeys
);
719 if (mode
== NSS_DES_EDE3_CBC
) {
720 /* taken care of in the j=9999 iteration */
721 if (crypt
== ENCRYPT
) {
725 /* taken care of in the j=9999 iteration */
730 /* ECB PT/CT[i] = PT/CT[j] */
731 memcpy(inputtext
, outputtext
, 8);
733 /* done at the end of the for(i) loop */
742 * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
743 * by gathering the input from the request file, and then
744 * calling tdea_mct_test.
746 * reqfn is the pathname of the input REQUEST file.
748 * The output RESPONSE file is written to stdout.
751 tdea_mct(int mode
, char *reqfn
)
754 char buf
[80]; /* holds one line from the input REQUEST file. */
755 FILE *req
; /* input stream from the REQUEST file */
756 FILE *resp
; /* output stream to the RESPONSE file */
757 unsigned int crypt
= 0; /* 1 means encrypt, 0 means decrypt */
758 unsigned char key
[24]; /* TDEA 3 key bundle */
759 unsigned int numKeys
= 0;
760 unsigned char plaintext
[8]; /* PT[j] */
761 unsigned char ciphertext
[8]; /* CT[j] */
764 /* zeroize the variables for the test with this data set */
765 memset(key
, 0, sizeof key
);
766 memset(plaintext
, 0, sizeof plaintext
);
767 memset(ciphertext
, 0, sizeof ciphertext
);
768 memset(iv
, 0, sizeof iv
);
770 req
= fopen(reqfn
, "r");
772 while (fgets(buf
, sizeof buf
, req
) != NULL
) {
773 /* a comment or blank line */
774 if (buf
[0] == '#' || buf
[0] == '\n') {
778 /* [ENCRYPT] or [DECRYPT] */
780 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
789 if (strncmp(&buf
[0], "NumKeys", 7) == 0) {
791 while (isspace(buf
[i
]) || buf
[i
] == '=') {
794 numKeys
= atoi(&buf
[i
]);
798 if (strncmp(buf
, "KEY1", 4) == 0) {
800 while (isspace(buf
[i
]) || buf
[i
] == '=') {
803 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
804 hex_to_byteval(&buf
[i
], &key
[j
]);
809 if (strncmp(buf
, "KEY2", 4) == 0) {
811 while (isspace(buf
[i
]) || buf
[i
] == '=') {
814 for (j
=8; isxdigit(buf
[i
]); i
+=2,j
++) {
815 hex_to_byteval(&buf
[i
], &key
[j
]);
820 if (strncmp(buf
, "KEY3", 4) == 0) {
822 while (isspace(buf
[i
]) || buf
[i
] == '=') {
825 for (j
=16; isxdigit(buf
[i
]); i
+=2,j
++) {
826 hex_to_byteval(&buf
[i
], &key
[j
]);
832 if (strncmp(buf
, "IV", 2) == 0) {
834 while (isspace(buf
[i
]) || buf
[i
] == '=') {
837 for (j
=0; j
<sizeof iv
; i
+=2,j
++) {
838 hex_to_byteval(&buf
[i
], &iv
[j
]);
843 /* PLAINTEXT = ... */
844 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
847 if (crypt
!= ENCRYPT
) {
852 while (isspace(buf
[i
]) || buf
[i
] == '=') {
855 for (j
=0; j
<sizeof plaintext
; i
+=2,j
++) {
856 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
859 /* do the Monte Carlo test */
860 if (mode
==NSS_DES_EDE3
) {
861 tdea_mct_test(NSS_DES_EDE3
, key
, numKeys
, crypt
, plaintext
, sizeof plaintext
, NULL
, resp
);
863 tdea_mct_test(NSS_DES_EDE3_CBC
, key
, numKeys
, crypt
, plaintext
, sizeof plaintext
, iv
, resp
);
867 /* CIPHERTEXT = ... */
868 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
870 if (crypt
!= DECRYPT
) {
875 while (isspace(buf
[i
]) || buf
[i
] == '=') {
878 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
879 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
882 /* do the Monte Carlo test */
883 if (mode
==NSS_DES_EDE3
) {
884 tdea_mct_test(NSS_DES_EDE3
, key
, numKeys
, crypt
, ciphertext
, sizeof ciphertext
, NULL
, resp
);
886 tdea_mct_test(NSS_DES_EDE3_CBC
, key
, numKeys
, crypt
, ciphertext
, sizeof ciphertext
, iv
, resp
);
900 const unsigned char *key
, unsigned int keysize
,
901 const unsigned char *iv
,
902 unsigned char *output
, unsigned int *outputlen
, unsigned int maxoutputlen
,
903 const unsigned char *input
, unsigned int inputlen
)
905 SECStatus rv
= SECFailure
;
907 unsigned char doublecheck
[10*16]; /* 1 to 10 blocks */
908 unsigned int doublechecklen
= 0;
910 cx
= AES_CreateContext(key
, iv
, mode
, PR_TRUE
, keysize
, 16);
914 rv
= AES_Encrypt(cx
, output
, outputlen
, maxoutputlen
, input
, inputlen
);
915 if (rv
!= SECSuccess
) {
918 if (*outputlen
!= inputlen
) {
921 AES_DestroyContext(cx
, PR_TRUE
);
925 * Doublecheck our result by decrypting the ciphertext and
926 * compare the output with the input plaintext.
928 cx
= AES_CreateContext(key
, iv
, mode
, PR_FALSE
, keysize
, 16);
932 rv
= AES_Decrypt(cx
, doublecheck
, &doublechecklen
, sizeof doublecheck
,
934 if (rv
!= SECSuccess
) {
937 if (doublechecklen
!= *outputlen
) {
940 AES_DestroyContext(cx
, PR_TRUE
);
942 if (memcmp(doublecheck
, input
, inputlen
) != 0) {
949 AES_DestroyContext(cx
, PR_TRUE
);
957 const unsigned char *key
, unsigned int keysize
,
958 const unsigned char *iv
,
959 unsigned char *output
, unsigned int *outputlen
, unsigned int maxoutputlen
,
960 const unsigned char *input
, unsigned int inputlen
)
962 SECStatus rv
= SECFailure
;
964 unsigned char doublecheck
[10*16]; /* 1 to 10 blocks */
965 unsigned int doublechecklen
= 0;
967 cx
= AES_CreateContext(key
, iv
, mode
, PR_FALSE
, keysize
, 16);
971 rv
= AES_Decrypt(cx
, output
, outputlen
, maxoutputlen
,
973 if (rv
!= SECSuccess
) {
976 if (*outputlen
!= inputlen
) {
979 AES_DestroyContext(cx
, PR_TRUE
);
983 * Doublecheck our result by encrypting the plaintext and
984 * compare the output with the input ciphertext.
986 cx
= AES_CreateContext(key
, iv
, mode
, PR_TRUE
, keysize
, 16);
990 rv
= AES_Encrypt(cx
, doublecheck
, &doublechecklen
, sizeof doublecheck
,
992 if (rv
!= SECSuccess
) {
995 if (doublechecklen
!= *outputlen
) {
998 AES_DestroyContext(cx
, PR_TRUE
);
1000 if (memcmp(doublecheck
, input
, inputlen
) != 0) {
1007 AES_DestroyContext(cx
, PR_TRUE
);
1013 * Perform the AES Known Answer Test (KAT) or Multi-block Message
1014 * Test (MMT) in ECB or CBC mode. The KAT (there are four types)
1015 * and MMT have the same structure: given the key and IV (CBC mode
1016 * only), encrypt the given plaintext or decrypt the given ciphertext.
1017 * So we can handle them the same way.
1019 * reqfn is the pathname of the REQUEST file.
1021 * The output RESPONSE file is written to stdout.
1024 aes_kat_mmt(char *reqfn
)
1026 char buf
[512]; /* holds one line from the input REQUEST file.
1027 * needs to be large enough to hold the longest
1028 * line "CIPHERTEXT = <320 hex digits>\n".
1030 FILE *aesreq
; /* input stream from the REQUEST file */
1031 FILE *aesresp
; /* output stream to the RESPONSE file */
1033 int mode
; /* NSS_AES (ECB) or NSS_AES_CBC */
1034 int encrypt
= 0; /* 1 means encrypt, 0 means decrypt */
1035 unsigned char key
[32]; /* 128, 192, or 256 bits */
1036 unsigned int keysize
;
1037 unsigned char iv
[16]; /* for all modes except ECB */
1038 unsigned char plaintext
[10*16]; /* 1 to 10 blocks */
1039 unsigned int plaintextlen
;
1040 unsigned char ciphertext
[10*16]; /* 1 to 10 blocks */
1041 unsigned int ciphertextlen
;
1044 aesreq
= fopen(reqfn
, "r");
1046 while (fgets(buf
, sizeof buf
, aesreq
) != NULL
) {
1047 /* a comment or blank line */
1048 if (buf
[0] == '#' || buf
[0] == '\n') {
1049 fputs(buf
, aesresp
);
1052 /* [ENCRYPT] or [DECRYPT] */
1053 if (buf
[0] == '[') {
1054 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
1059 fputs(buf
, aesresp
);
1062 /* "COUNT = x" begins a new data set */
1063 if (strncmp(buf
, "COUNT", 5) == 0) {
1065 /* zeroize the variables for the test with this data set */
1066 memset(key
, 0, sizeof key
);
1068 memset(iv
, 0, sizeof iv
);
1069 memset(plaintext
, 0, sizeof plaintext
);
1071 memset(ciphertext
, 0, sizeof ciphertext
);
1073 fputs(buf
, aesresp
);
1077 if (strncmp(buf
, "KEY", 3) == 0) {
1079 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1082 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1083 hex_to_byteval(&buf
[i
], &key
[j
]);
1086 fputs(buf
, aesresp
);
1090 if (strncmp(buf
, "IV", 2) == 0) {
1093 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1096 for (j
=0; j
<sizeof iv
; i
+=2,j
++) {
1097 hex_to_byteval(&buf
[i
], &iv
[j
]);
1099 fputs(buf
, aesresp
);
1102 /* PLAINTEXT = ... */
1103 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
1110 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1113 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1114 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
1118 rv
= aes_encrypt_buf(mode
, key
, keysize
,
1119 (mode
== NSS_AES
) ? NULL
: iv
,
1120 ciphertext
, &ciphertextlen
, sizeof ciphertext
,
1121 plaintext
, plaintextlen
);
1122 if (rv
!= SECSuccess
) {
1126 fputs(buf
, aesresp
);
1127 fputs("CIPHERTEXT = ", aesresp
);
1128 to_hex_str(buf
, ciphertext
, ciphertextlen
);
1129 fputs(buf
, aesresp
);
1130 fputc('\n', aesresp
);
1133 /* CIPHERTEXT = ... */
1134 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
1141 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1144 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1145 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
1149 rv
= aes_decrypt_buf(mode
, key
, keysize
,
1150 (mode
== NSS_AES
) ? NULL
: iv
,
1151 plaintext
, &plaintextlen
, sizeof plaintext
,
1152 ciphertext
, ciphertextlen
);
1153 if (rv
!= SECSuccess
) {
1157 fputs(buf
, aesresp
);
1158 fputs("PLAINTEXT = ", aesresp
);
1159 to_hex_str(buf
, plaintext
, plaintextlen
);
1160 fputs(buf
, aesresp
);
1161 fputc('\n', aesresp
);
1170 * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
1171 * Test (MCT) in ECB and CBC modes.
1174 aes_mct_next_key(unsigned char *key
, unsigned int keysize
,
1175 const unsigned char *ciphertext_1
, const unsigned char *ciphertext
)
1180 case 16: /* 128-bit key */
1181 /* Key[i+1] = Key[i] xor CT[j] */
1182 for (k
=0; k
<16; k
++) {
1183 key
[k
] ^= ciphertext
[k
];
1186 case 24: /* 192-bit key */
1188 * Key[i+1] = Key[i] xor (last 64-bits of
1191 for (k
=0; k
<8; k
++) {
1192 key
[k
] ^= ciphertext_1
[k
+8];
1194 for (k
=8; k
<24; k
++) {
1195 key
[k
] ^= ciphertext
[k
-8];
1198 case 32: /* 256-bit key */
1199 /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
1200 for (k
=0; k
<16; k
++) {
1201 key
[k
] ^= ciphertext_1
[k
];
1203 for (k
=16; k
<32; k
++) {
1204 key
[k
] ^= ciphertext
[k
-16];
1211 * Perform the AES Monte Carlo Test (MCT) in ECB mode. MCT exercises
1212 * our AES code in streaming mode because the plaintext or ciphertext
1213 * is generated block by block as we go, so we can't collect all the
1214 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1217 * reqfn is the pathname of the input REQUEST file.
1219 * The output RESPONSE file is written to stdout.
1222 aes_ecb_mct(char *reqfn
)
1224 char buf
[80]; /* holds one line from the input REQUEST file.
1225 * needs to be large enough to hold the longest
1226 * line "KEY = <64 hex digits>\n".
1228 FILE *aesreq
; /* input stream from the REQUEST file */
1229 FILE *aesresp
; /* output stream to the RESPONSE file */
1231 int encrypt
= 0; /* 1 means encrypt, 0 means decrypt */
1232 unsigned char key
[32]; /* 128, 192, or 256 bits */
1233 unsigned int keysize
;
1234 unsigned char plaintext
[16]; /* PT[j] */
1235 unsigned char plaintext_1
[16]; /* PT[j-1] */
1236 unsigned char ciphertext
[16]; /* CT[j] */
1237 unsigned char ciphertext_1
[16]; /* CT[j-1] */
1238 unsigned char doublecheck
[16];
1239 unsigned int outputlen
;
1240 AESContext
*cx
= NULL
; /* the operation being tested */
1241 AESContext
*cx2
= NULL
; /* the inverse operation done in parallel
1242 * to doublecheck our result.
1246 aesreq
= fopen(reqfn
, "r");
1248 while (fgets(buf
, sizeof buf
, aesreq
) != NULL
) {
1249 /* a comment or blank line */
1250 if (buf
[0] == '#' || buf
[0] == '\n') {
1251 fputs(buf
, aesresp
);
1254 /* [ENCRYPT] or [DECRYPT] */
1255 if (buf
[0] == '[') {
1256 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
1261 fputs(buf
, aesresp
);
1264 /* "COUNT = x" begins a new data set */
1265 if (strncmp(buf
, "COUNT", 5) == 0) {
1266 /* zeroize the variables for the test with this data set */
1267 memset(key
, 0, sizeof key
);
1269 memset(plaintext
, 0, sizeof plaintext
);
1270 memset(ciphertext
, 0, sizeof ciphertext
);
1274 if (strncmp(buf
, "KEY", 3) == 0) {
1277 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1280 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1281 hex_to_byteval(&buf
[i
], &key
[j
]);
1286 /* PLAINTEXT = ... */
1287 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
1294 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1297 for (j
=0; j
<sizeof plaintext
; i
+=2,j
++) {
1298 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
1301 for (i
=0; i
<100; i
++) {
1302 sprintf(buf
, "COUNT = %d\n", i
);
1303 fputs(buf
, aesresp
);
1305 fputs("KEY = ", aesresp
);
1306 to_hex_str(buf
, key
, keysize
);
1307 fputs(buf
, aesresp
);
1308 fputc('\n', aesresp
);
1310 fputs("PLAINTEXT = ", aesresp
);
1311 to_hex_str(buf
, plaintext
, sizeof plaintext
);
1312 fputs(buf
, aesresp
);
1313 fputc('\n', aesresp
);
1315 cx
= AES_CreateContext(key
, NULL
, NSS_AES
,
1316 PR_TRUE
, keysize
, 16);
1321 * doublecheck our result by decrypting the result
1322 * and comparing the output with the plaintext.
1324 cx2
= AES_CreateContext(key
, NULL
, NSS_AES
,
1325 PR_FALSE
, keysize
, 16);
1329 for (j
=0; j
<1000; j
++) {
1331 memcpy(ciphertext_1
, ciphertext
, sizeof ciphertext
);
1333 /* CT[j] = AES(Key[i], PT[j]) */
1335 rv
= AES_Encrypt(cx
,
1336 ciphertext
, &outputlen
, sizeof ciphertext
,
1337 plaintext
, sizeof plaintext
);
1338 if (rv
!= SECSuccess
) {
1341 if (outputlen
!= sizeof plaintext
) {
1345 /* doublecheck our result */
1347 rv
= AES_Decrypt(cx2
,
1348 doublecheck
, &outputlen
, sizeof doublecheck
,
1349 ciphertext
, sizeof ciphertext
);
1350 if (rv
!= SECSuccess
) {
1353 if (outputlen
!= sizeof ciphertext
) {
1356 if (memcmp(doublecheck
, plaintext
, sizeof plaintext
)) {
1360 /* PT[j+1] = CT[j] */
1361 memcpy(plaintext
, ciphertext
, sizeof plaintext
);
1363 AES_DestroyContext(cx
, PR_TRUE
);
1365 AES_DestroyContext(cx2
, PR_TRUE
);
1369 fputs("CIPHERTEXT = ", aesresp
);
1370 to_hex_str(buf
, ciphertext
, sizeof ciphertext
);
1371 fputs(buf
, aesresp
);
1372 fputc('\n', aesresp
);
1374 /* Key[i+1] = Key[i] xor ... */
1375 aes_mct_next_key(key
, keysize
, ciphertext_1
, ciphertext
);
1377 /* done at the end of the for(j) loop */
1379 fputc('\n', aesresp
);
1384 /* CIPHERTEXT = ... */
1385 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
1392 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1395 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1396 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
1399 for (i
=0; i
<100; i
++) {
1400 sprintf(buf
, "COUNT = %d\n", i
);
1401 fputs(buf
, aesresp
);
1403 fputs("KEY = ", aesresp
);
1404 to_hex_str(buf
, key
, keysize
);
1405 fputs(buf
, aesresp
);
1406 fputc('\n', aesresp
);
1408 fputs("CIPHERTEXT = ", aesresp
);
1409 to_hex_str(buf
, ciphertext
, sizeof ciphertext
);
1410 fputs(buf
, aesresp
);
1411 fputc('\n', aesresp
);
1413 cx
= AES_CreateContext(key
, NULL
, NSS_AES
,
1414 PR_FALSE
, keysize
, 16);
1419 * doublecheck our result by encrypting the result
1420 * and comparing the output with the ciphertext.
1422 cx2
= AES_CreateContext(key
, NULL
, NSS_AES
,
1423 PR_TRUE
, keysize
, 16);
1427 for (j
=0; j
<1000; j
++) {
1429 memcpy(plaintext_1
, plaintext
, sizeof plaintext
);
1431 /* PT[j] = AES(Key[i], CT[j]) */
1433 rv
= AES_Decrypt(cx
,
1434 plaintext
, &outputlen
, sizeof plaintext
,
1435 ciphertext
, sizeof ciphertext
);
1436 if (rv
!= SECSuccess
) {
1439 if (outputlen
!= sizeof ciphertext
) {
1443 /* doublecheck our result */
1445 rv
= AES_Encrypt(cx2
,
1446 doublecheck
, &outputlen
, sizeof doublecheck
,
1447 plaintext
, sizeof plaintext
);
1448 if (rv
!= SECSuccess
) {
1451 if (outputlen
!= sizeof plaintext
) {
1454 if (memcmp(doublecheck
, ciphertext
, sizeof ciphertext
)) {
1458 /* CT[j+1] = PT[j] */
1459 memcpy(ciphertext
, plaintext
, sizeof ciphertext
);
1461 AES_DestroyContext(cx
, PR_TRUE
);
1463 AES_DestroyContext(cx2
, PR_TRUE
);
1467 fputs("PLAINTEXT = ", aesresp
);
1468 to_hex_str(buf
, plaintext
, sizeof plaintext
);
1469 fputs(buf
, aesresp
);
1470 fputc('\n', aesresp
);
1472 /* Key[i+1] = Key[i] xor ... */
1473 aes_mct_next_key(key
, keysize
, plaintext_1
, plaintext
);
1475 /* done at the end of the for(j) loop */
1477 fputc('\n', aesresp
);
1485 AES_DestroyContext(cx
, PR_TRUE
);
1488 AES_DestroyContext(cx2
, PR_TRUE
);
1494 * Perform the AES Monte Carlo Test (MCT) in CBC mode. MCT exercises
1495 * our AES code in streaming mode because the plaintext or ciphertext
1496 * is generated block by block as we go, so we can't collect all the
1497 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1500 * reqfn is the pathname of the input REQUEST file.
1502 * The output RESPONSE file is written to stdout.
1505 aes_cbc_mct(char *reqfn
)
1507 char buf
[80]; /* holds one line from the input REQUEST file.
1508 * needs to be large enough to hold the longest
1509 * line "KEY = <64 hex digits>\n".
1511 FILE *aesreq
; /* input stream from the REQUEST file */
1512 FILE *aesresp
; /* output stream to the RESPONSE file */
1514 int encrypt
= 0; /* 1 means encrypt, 0 means decrypt */
1515 unsigned char key
[32]; /* 128, 192, or 256 bits */
1516 unsigned int keysize
;
1517 unsigned char iv
[16];
1518 unsigned char plaintext
[16]; /* PT[j] */
1519 unsigned char plaintext_1
[16]; /* PT[j-1] */
1520 unsigned char ciphertext
[16]; /* CT[j] */
1521 unsigned char ciphertext_1
[16]; /* CT[j-1] */
1522 unsigned char doublecheck
[16];
1523 unsigned int outputlen
;
1524 AESContext
*cx
= NULL
; /* the operation being tested */
1525 AESContext
*cx2
= NULL
; /* the inverse operation done in parallel
1526 * to doublecheck our result.
1530 aesreq
= fopen(reqfn
, "r");
1532 while (fgets(buf
, sizeof buf
, aesreq
) != NULL
) {
1533 /* a comment or blank line */
1534 if (buf
[0] == '#' || buf
[0] == '\n') {
1535 fputs(buf
, aesresp
);
1538 /* [ENCRYPT] or [DECRYPT] */
1539 if (buf
[0] == '[') {
1540 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
1545 fputs(buf
, aesresp
);
1548 /* "COUNT = x" begins a new data set */
1549 if (strncmp(buf
, "COUNT", 5) == 0) {
1550 /* zeroize the variables for the test with this data set */
1551 memset(key
, 0, sizeof key
);
1553 memset(iv
, 0, sizeof iv
);
1554 memset(plaintext
, 0, sizeof plaintext
);
1555 memset(ciphertext
, 0, sizeof ciphertext
);
1559 if (strncmp(buf
, "KEY", 3) == 0) {
1562 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1565 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1566 hex_to_byteval(&buf
[i
], &key
[j
]);
1572 if (strncmp(buf
, "IV", 2) == 0) {
1575 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1578 for (j
=0; j
<sizeof iv
; i
+=2,j
++) {
1579 hex_to_byteval(&buf
[i
], &iv
[j
]);
1583 /* PLAINTEXT = ... */
1584 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
1591 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1594 for (j
=0; j
<sizeof plaintext
; i
+=2,j
++) {
1595 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
1598 for (i
=0; i
<100; i
++) {
1599 sprintf(buf
, "COUNT = %d\n", i
);
1600 fputs(buf
, aesresp
);
1602 fputs("KEY = ", aesresp
);
1603 to_hex_str(buf
, key
, keysize
);
1604 fputs(buf
, aesresp
);
1605 fputc('\n', aesresp
);
1607 fputs("IV = ", aesresp
);
1608 to_hex_str(buf
, iv
, sizeof iv
);
1609 fputs(buf
, aesresp
);
1610 fputc('\n', aesresp
);
1612 fputs("PLAINTEXT = ", aesresp
);
1613 to_hex_str(buf
, plaintext
, sizeof plaintext
);
1614 fputs(buf
, aesresp
);
1615 fputc('\n', aesresp
);
1617 cx
= AES_CreateContext(key
, iv
, NSS_AES_CBC
,
1618 PR_TRUE
, keysize
, 16);
1623 * doublecheck our result by decrypting the result
1624 * and comparing the output with the plaintext.
1626 cx2
= AES_CreateContext(key
, iv
, NSS_AES_CBC
,
1627 PR_FALSE
, keysize
, 16);
1631 /* CT[-1] = IV[i] */
1632 memcpy(ciphertext
, iv
, sizeof ciphertext
);
1633 for (j
=0; j
<1000; j
++) {
1635 memcpy(ciphertext_1
, ciphertext
, sizeof ciphertext
);
1638 * CT[j] = AES(Key[i], IV[i], PT[j])
1639 * PT[j+1] = IV[i] (= CT[j-1])
1641 * CT[j] = AES(Key[i], PT[j])
1645 rv
= AES_Encrypt(cx
,
1646 ciphertext
, &outputlen
, sizeof ciphertext
,
1647 plaintext
, sizeof plaintext
);
1648 if (rv
!= SECSuccess
) {
1651 if (outputlen
!= sizeof plaintext
) {
1655 /* doublecheck our result */
1657 rv
= AES_Decrypt(cx2
,
1658 doublecheck
, &outputlen
, sizeof doublecheck
,
1659 ciphertext
, sizeof ciphertext
);
1660 if (rv
!= SECSuccess
) {
1663 if (outputlen
!= sizeof ciphertext
) {
1666 if (memcmp(doublecheck
, plaintext
, sizeof plaintext
)) {
1670 memcpy(plaintext
, ciphertext_1
, sizeof plaintext
);
1672 AES_DestroyContext(cx
, PR_TRUE
);
1674 AES_DestroyContext(cx2
, PR_TRUE
);
1678 fputs("CIPHERTEXT = ", aesresp
);
1679 to_hex_str(buf
, ciphertext
, sizeof ciphertext
);
1680 fputs(buf
, aesresp
);
1681 fputc('\n', aesresp
);
1683 /* Key[i+1] = Key[i] xor ... */
1684 aes_mct_next_key(key
, keysize
, ciphertext_1
, ciphertext
);
1685 /* IV[i+1] = CT[j] */
1686 memcpy(iv
, ciphertext
, sizeof iv
);
1687 /* PT[0] = CT[j-1] */
1688 /* done at the end of the for(j) loop */
1690 fputc('\n', aesresp
);
1695 /* CIPHERTEXT = ... */
1696 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
1703 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1706 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1707 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
1710 for (i
=0; i
<100; i
++) {
1711 sprintf(buf
, "COUNT = %d\n", i
);
1712 fputs(buf
, aesresp
);
1714 fputs("KEY = ", aesresp
);
1715 to_hex_str(buf
, key
, keysize
);
1716 fputs(buf
, aesresp
);
1717 fputc('\n', aesresp
);
1719 fputs("IV = ", aesresp
);
1720 to_hex_str(buf
, iv
, sizeof iv
);
1721 fputs(buf
, aesresp
);
1722 fputc('\n', aesresp
);
1724 fputs("CIPHERTEXT = ", aesresp
);
1725 to_hex_str(buf
, ciphertext
, sizeof ciphertext
);
1726 fputs(buf
, aesresp
);
1727 fputc('\n', aesresp
);
1729 cx
= AES_CreateContext(key
, iv
, NSS_AES_CBC
,
1730 PR_FALSE
, keysize
, 16);
1735 * doublecheck our result by encrypting the result
1736 * and comparing the output with the ciphertext.
1738 cx2
= AES_CreateContext(key
, iv
, NSS_AES_CBC
,
1739 PR_TRUE
, keysize
, 16);
1743 /* PT[-1] = IV[i] */
1744 memcpy(plaintext
, iv
, sizeof plaintext
);
1745 for (j
=0; j
<1000; j
++) {
1747 memcpy(plaintext_1
, plaintext
, sizeof plaintext
);
1750 * PT[j] = AES(Key[i], IV[i], CT[j])
1751 * CT[j+1] = IV[i] (= PT[j-1])
1753 * PT[j] = AES(Key[i], CT[j])
1757 rv
= AES_Decrypt(cx
,
1758 plaintext
, &outputlen
, sizeof plaintext
,
1759 ciphertext
, sizeof ciphertext
);
1760 if (rv
!= SECSuccess
) {
1763 if (outputlen
!= sizeof ciphertext
) {
1767 /* doublecheck our result */
1769 rv
= AES_Encrypt(cx2
,
1770 doublecheck
, &outputlen
, sizeof doublecheck
,
1771 plaintext
, sizeof plaintext
);
1772 if (rv
!= SECSuccess
) {
1775 if (outputlen
!= sizeof plaintext
) {
1778 if (memcmp(doublecheck
, ciphertext
, sizeof ciphertext
)) {
1782 memcpy(ciphertext
, plaintext_1
, sizeof ciphertext
);
1784 AES_DestroyContext(cx
, PR_TRUE
);
1786 AES_DestroyContext(cx2
, PR_TRUE
);
1790 fputs("PLAINTEXT = ", aesresp
);
1791 to_hex_str(buf
, plaintext
, sizeof plaintext
);
1792 fputs(buf
, aesresp
);
1793 fputc('\n', aesresp
);
1795 /* Key[i+1] = Key[i] xor ... */
1796 aes_mct_next_key(key
, keysize
, plaintext_1
, plaintext
);
1797 /* IV[i+1] = PT[j] */
1798 memcpy(iv
, plaintext
, sizeof iv
);
1799 /* CT[0] = PT[j-1] */
1800 /* done at the end of the for(j) loop */
1802 fputc('\n', aesresp
);
1810 AES_DestroyContext(cx
, PR_TRUE
);
1813 AES_DestroyContext(cx2
, PR_TRUE
);
1818 void write_compact_string(FILE *out
, unsigned char *hash
, unsigned int len
)
1821 int j
, count
= 0, last
= -1, z
= 0;
1822 long start
= ftell(out
);
1823 for (i
=0; i
<len
; i
++) {
1824 for (j
=7; j
>=0; j
--) {
1826 last
= (hash
[i
] & (1 << j
)) ? 1 : 0;
1827 fprintf(out
, "%d ", last
);
1829 } else if (hash
[i
] & (1 << j
)) {
1834 fprintf(out
, "%d ", count
);
1843 fprintf(out
, "%d ", count
);
1850 fprintf(out
, "^\n");
1851 fseek(out
, start
, SEEK_SET
);
1852 fprintf(out
, "%d ", z
);
1853 fseek(out
, 0, SEEK_END
);
1856 int get_next_line(FILE *req
, char *key
, char *val
, FILE *rsp
)
1859 char *writeto
= key
;
1862 while ((c
= fgetc(req
)) != EOF
) {
1864 fprintf(rsp
, "%c", c
);
1865 if (c
== '\n') return ignore
;
1866 } else if (c
== '\n') {
1868 } else if (c
== '#') {
1870 fprintf(rsp
, "%c", c
);
1871 } else if (c
== '=') {
1875 } else if (c
== ' ' || c
== '[' || c
== ']') {
1882 return (c
== EOF
) ? -1 : ignore
;
1885 #ifdef NSS_ENABLE_ECC
1886 typedef struct curveNameTagPairStr
{
1888 SECOidTag curveOidTag
;
1891 #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
1892 /* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */
1894 static CurveNameTagPair nameTagPair
[] =
1896 { "sect163k1", SEC_OID_SECG_EC_SECT163K1
},
1897 { "nistk163", SEC_OID_SECG_EC_SECT163K1
},
1898 { "sect163r1", SEC_OID_SECG_EC_SECT163R1
},
1899 { "sect163r2", SEC_OID_SECG_EC_SECT163R2
},
1900 { "nistb163", SEC_OID_SECG_EC_SECT163R2
},
1901 { "sect193r1", SEC_OID_SECG_EC_SECT193R1
},
1902 { "sect193r2", SEC_OID_SECG_EC_SECT193R2
},
1903 { "sect233k1", SEC_OID_SECG_EC_SECT233K1
},
1904 { "nistk233", SEC_OID_SECG_EC_SECT233K1
},
1905 { "sect233r1", SEC_OID_SECG_EC_SECT233R1
},
1906 { "nistb233", SEC_OID_SECG_EC_SECT233R1
},
1907 { "sect239k1", SEC_OID_SECG_EC_SECT239K1
},
1908 { "sect283k1", SEC_OID_SECG_EC_SECT283K1
},
1909 { "nistk283", SEC_OID_SECG_EC_SECT283K1
},
1910 { "sect283r1", SEC_OID_SECG_EC_SECT283R1
},
1911 { "nistb283", SEC_OID_SECG_EC_SECT283R1
},
1912 { "sect409k1", SEC_OID_SECG_EC_SECT409K1
},
1913 { "nistk409", SEC_OID_SECG_EC_SECT409K1
},
1914 { "sect409r1", SEC_OID_SECG_EC_SECT409R1
},
1915 { "nistb409", SEC_OID_SECG_EC_SECT409R1
},
1916 { "sect571k1", SEC_OID_SECG_EC_SECT571K1
},
1917 { "nistk571", SEC_OID_SECG_EC_SECT571K1
},
1918 { "sect571r1", SEC_OID_SECG_EC_SECT571R1
},
1919 { "nistb571", SEC_OID_SECG_EC_SECT571R1
},
1920 { "secp160k1", SEC_OID_SECG_EC_SECP160K1
},
1921 { "secp160r1", SEC_OID_SECG_EC_SECP160R1
},
1922 { "secp160r2", SEC_OID_SECG_EC_SECP160R2
},
1923 { "secp192k1", SEC_OID_SECG_EC_SECP192K1
},
1924 { "secp192r1", SEC_OID_SECG_EC_SECP192R1
},
1925 { "nistp192", SEC_OID_SECG_EC_SECP192R1
},
1926 { "secp224k1", SEC_OID_SECG_EC_SECP224K1
},
1927 { "secp224r1", SEC_OID_SECG_EC_SECP224R1
},
1928 { "nistp224", SEC_OID_SECG_EC_SECP224R1
},
1929 { "secp256k1", SEC_OID_SECG_EC_SECP256K1
},
1930 { "secp256r1", SEC_OID_SECG_EC_SECP256R1
},
1931 { "nistp256", SEC_OID_SECG_EC_SECP256R1
},
1932 { "secp384r1", SEC_OID_SECG_EC_SECP384R1
},
1933 { "nistp384", SEC_OID_SECG_EC_SECP384R1
},
1934 { "secp521r1", SEC_OID_SECG_EC_SECP521R1
},
1935 { "nistp521", SEC_OID_SECG_EC_SECP521R1
},
1937 { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1
},
1938 { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2
},
1939 { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3
},
1940 { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1
},
1941 { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2
},
1942 { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3
},
1944 { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1
},
1945 { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2
},
1946 { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3
},
1947 { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1
},
1948 { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1
},
1949 { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2
},
1950 { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3
},
1951 { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4
},
1952 { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5
},
1953 { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1
},
1954 { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1
},
1955 { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2
},
1956 { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3
},
1957 { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4
},
1958 { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5
},
1959 { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1
},
1960 { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1
},
1961 { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1
},
1962 { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1
},
1963 { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1
},
1965 { "secp112r1", SEC_OID_SECG_EC_SECP112R1
},
1966 { "secp112r2", SEC_OID_SECG_EC_SECP112R2
},
1967 { "secp128r1", SEC_OID_SECG_EC_SECP128R1
},
1968 { "secp128r2", SEC_OID_SECG_EC_SECP128R2
},
1970 { "sect113r1", SEC_OID_SECG_EC_SECT113R1
},
1971 { "sect113r2", SEC_OID_SECG_EC_SECT113R2
},
1972 { "sect131r1", SEC_OID_SECG_EC_SECT131R1
},
1973 { "sect131r2", SEC_OID_SECG_EC_SECT131R2
},
1976 static SECKEYECParams
*
1977 getECParams(const char *curve
)
1979 SECKEYECParams
*ecparams
;
1980 SECOidData
*oidData
= NULL
;
1981 SECOidTag curveOidTag
= SEC_OID_UNKNOWN
; /* default */
1984 if (curve
!= NULL
) {
1985 numCurves
= sizeof(nameTagPair
)/sizeof(CurveNameTagPair
);
1986 for (i
= 0; ((i
< numCurves
) && (curveOidTag
== SEC_OID_UNKNOWN
));
1988 if (PL_strcmp(curve
, nameTagPair
[i
].curveName
) == 0)
1989 curveOidTag
= nameTagPair
[i
].curveOidTag
;
1993 /* Return NULL if curve name is not recognized */
1994 if ((curveOidTag
== SEC_OID_UNKNOWN
) ||
1995 (oidData
= SECOID_FindOIDByTag(curveOidTag
)) == NULL
) {
1996 fprintf(stderr
, "Unrecognized elliptic curve %s\n", curve
);
2000 ecparams
= SECITEM_AllocItem(NULL
, NULL
, (2 + oidData
->oid
.len
));
2003 * ecparams->data needs to contain the ASN encoding of an object ID (OID)
2004 * representing the named curve. The actual OID is in
2005 * oidData->oid.data so we simply prepend 0x06 and OID length
2007 ecparams
->data
[0] = SEC_ASN1_OBJECT_ID
;
2008 ecparams
->data
[1] = oidData
->oid
.len
;
2009 memcpy(ecparams
->data
+ 2, oidData
->oid
.data
, oidData
->oid
.len
);
2015 * Perform the ECDSA Key Pair Generation Test.
2017 * reqfn is the pathname of the REQUEST file.
2019 * The output RESPONSE file is written to stdout.
2022 ecdsa_keypair_test(char *reqfn
)
2024 char buf
[256]; /* holds one line from the input REQUEST file
2025 * or to the output RESPONSE file.
2026 * needs to be large enough to hold the longest
2027 * line "Qx = <144 hex digits>\n".
2029 FILE *ecdsareq
; /* input stream from the REQUEST file */
2030 FILE *ecdsaresp
; /* output stream to the RESPONSE file */
2031 char curve
[16]; /* "nistxddd" */
2037 ecdsareq
= fopen(reqfn
, "r");
2039 strcpy(curve
, "nist");
2040 while (fgets(buf
, sizeof buf
, ecdsareq
) != NULL
) {
2041 /* a comment or blank line */
2042 if (buf
[0] == '#' || buf
[0] == '\n') {
2043 fputs(buf
, ecdsaresp
);
2047 if (buf
[0] == '[') {
2050 SECKEYECParams
*encodedparams
;
2054 *dst
++ = tolower(*src
);
2055 src
+= 2; /* skip the hyphen */
2060 encodedparams
= getECParams(curve
);
2061 if (encodedparams
== NULL
) {
2064 if (EC_DecodeParams(encodedparams
, &ecparams
) != SECSuccess
) {
2067 SECITEM_FreeItem(encodedparams
, PR_TRUE
);
2068 fputs(buf
, ecdsaresp
);
2072 if (buf
[0] == 'N') {
2073 if (sscanf(buf
, "N = %d", &N
) != 1) {
2076 for (i
= 0; i
< N
; i
++) {
2077 ECPrivateKey
*ecpriv
;
2079 if (EC_NewKey(ecparams
, &ecpriv
) != SECSuccess
) {
2082 fputs("d = ", ecdsaresp
);
2083 to_hex_str(buf
, ecpriv
->privateValue
.data
,
2084 ecpriv
->privateValue
.len
);
2085 fputs(buf
, ecdsaresp
);
2086 fputc('\n', ecdsaresp
);
2087 if (EC_ValidatePublicKey(ecparams
, &ecpriv
->publicValue
)
2091 len
= ecpriv
->publicValue
.len
;
2096 if (ecpriv
->publicValue
.data
[0]
2097 != EC_POINT_FORM_UNCOMPRESSED
) {
2100 fputs("Qx = ", ecdsaresp
);
2101 to_hex_str(buf
, &ecpriv
->publicValue
.data
[1], len
);
2102 fputs(buf
, ecdsaresp
);
2103 fputc('\n', ecdsaresp
);
2104 fputs("Qy = ", ecdsaresp
);
2105 to_hex_str(buf
, &ecpriv
->publicValue
.data
[1+len
], len
);
2106 fputs(buf
, ecdsaresp
);
2107 fputc('\n', ecdsaresp
);
2108 fputc('\n', ecdsaresp
);
2109 PORT_FreeArena(ecpriv
->ecParams
.arena
, PR_TRUE
);
2111 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2120 * Perform the ECDSA Public Key Validation Test.
2122 * reqfn is the pathname of the REQUEST file.
2124 * The output RESPONSE file is written to stdout.
2127 ecdsa_pkv_test(char *reqfn
)
2129 char buf
[256]; /* holds one line from the input REQUEST file.
2130 * needs to be large enough to hold the longest
2131 * line "Qx = <144 hex digits>\n".
2133 FILE *ecdsareq
; /* input stream from the REQUEST file */
2134 FILE *ecdsaresp
; /* output stream to the RESPONSE file */
2135 char curve
[16]; /* "nistxddd" */
2136 ECParams
*ecparams
= NULL
;
2140 PRBool keyvalid
= PR_TRUE
;
2142 ecdsareq
= fopen(reqfn
, "r");
2144 strcpy(curve
, "nist");
2146 while (fgets(buf
, sizeof buf
, ecdsareq
) != NULL
) {
2147 /* a comment or blank line */
2148 if (buf
[0] == '#' || buf
[0] == '\n') {
2149 fputs(buf
, ecdsaresp
);
2153 if (buf
[0] == '[') {
2156 SECKEYECParams
*encodedparams
;
2160 *dst
++ = tolower(*src
);
2161 src
+= 2; /* skip the hyphen */
2166 if (ecparams
!= NULL
) {
2167 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2170 encodedparams
= getECParams(curve
);
2171 if (encodedparams
== NULL
) {
2174 if (EC_DecodeParams(encodedparams
, &ecparams
) != SECSuccess
) {
2177 SECITEM_FreeItem(encodedparams
, PR_TRUE
);
2178 len
= (ecparams
->fieldID
.size
+ 7) >> 3;
2179 if (pubkey
.data
!= NULL
) {
2180 PORT_Free(pubkey
.data
);
2183 SECITEM_AllocItem(NULL
, &pubkey
, 2*len
+1);
2184 if (pubkey
.data
== NULL
) {
2187 pubkey
.data
[0] = EC_POINT_FORM_UNCOMPRESSED
;
2188 fputs(buf
, ecdsaresp
);
2192 if (strncmp(buf
, "Qx", 2) == 0) {
2193 fputs(buf
, ecdsaresp
);
2195 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2198 keyvalid
= from_hex_str(&pubkey
.data
[1], len
, &buf
[i
]);
2202 if (strncmp(buf
, "Qy", 2) == 0) {
2203 fputs(buf
, ecdsaresp
);
2205 fputs("Result = F\n", ecdsaresp
);
2209 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2212 keyvalid
= from_hex_str(&pubkey
.data
[1+len
], len
, &buf
[i
]);
2214 fputs("Result = F\n", ecdsaresp
);
2217 if (EC_ValidatePublicKey(ecparams
, &pubkey
) == SECSuccess
) {
2218 fputs("Result = P\n", ecdsaresp
);
2219 } else if (PORT_GetError() == SEC_ERROR_BAD_KEY
) {
2220 fputs("Result = F\n", ecdsaresp
);
2228 if (ecparams
!= NULL
) {
2229 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2231 if (pubkey
.data
!= NULL
) {
2232 PORT_Free(pubkey
.data
);
2238 * Perform the ECDSA Signature Generation Test.
2240 * reqfn is the pathname of the REQUEST file.
2242 * The output RESPONSE file is written to stdout.
2245 ecdsa_siggen_test(char *reqfn
)
2247 char buf
[1024]; /* holds one line from the input REQUEST file
2248 * or to the output RESPONSE file.
2249 * needs to be large enough to hold the longest
2250 * line "Msg = <256 hex digits>\n".
2252 FILE *ecdsareq
; /* input stream from the REQUEST file */
2253 FILE *ecdsaresp
; /* output stream to the RESPONSE file */
2254 char curve
[16]; /* "nistxddd" */
2255 ECParams
*ecparams
= NULL
;
2258 unsigned char msg
[512]; /* message to be signed (<= 128 bytes) */
2259 unsigned int msglen
;
2260 unsigned char sha1
[20]; /* SHA-1 hash (160 bits) */
2261 unsigned char sig
[2*MAX_ECKEY_LEN
];
2262 SECItem signature
, digest
;
2264 ecdsareq
= fopen(reqfn
, "r");
2266 strcpy(curve
, "nist");
2267 while (fgets(buf
, sizeof buf
, ecdsareq
) != NULL
) {
2268 /* a comment or blank line */
2269 if (buf
[0] == '#' || buf
[0] == '\n') {
2270 fputs(buf
, ecdsaresp
);
2274 if (buf
[0] == '[') {
2277 SECKEYECParams
*encodedparams
;
2281 *dst
++ = tolower(*src
);
2282 src
+= 2; /* skip the hyphen */
2287 if (ecparams
!= NULL
) {
2288 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2291 encodedparams
= getECParams(curve
);
2292 if (encodedparams
== NULL
) {
2295 if (EC_DecodeParams(encodedparams
, &ecparams
) != SECSuccess
) {
2298 SECITEM_FreeItem(encodedparams
, PR_TRUE
);
2299 fputs(buf
, ecdsaresp
);
2303 if (strncmp(buf
, "Msg", 3) == 0) {
2304 ECPrivateKey
*ecpriv
;
2307 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2310 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
2311 hex_to_byteval(&buf
[i
], &msg
[j
]);
2314 if (SHA1_HashBuf(sha1
, msg
, msglen
) != SECSuccess
) {
2317 fputs(buf
, ecdsaresp
);
2319 if (EC_NewKey(ecparams
, &ecpriv
) != SECSuccess
) {
2322 if (EC_ValidatePublicKey(ecparams
, &ecpriv
->publicValue
)
2326 len
= ecpriv
->publicValue
.len
;
2331 if (ecpriv
->publicValue
.data
[0] != EC_POINT_FORM_UNCOMPRESSED
) {
2334 fputs("Qx = ", ecdsaresp
);
2335 to_hex_str(buf
, &ecpriv
->publicValue
.data
[1], len
);
2336 fputs(buf
, ecdsaresp
);
2337 fputc('\n', ecdsaresp
);
2338 fputs("Qy = ", ecdsaresp
);
2339 to_hex_str(buf
, &ecpriv
->publicValue
.data
[1+len
], len
);
2340 fputs(buf
, ecdsaresp
);
2341 fputc('\n', ecdsaresp
);
2343 digest
.type
= siBuffer
;
2345 digest
.len
= sizeof sha1
;
2346 signature
.type
= siBuffer
;
2347 signature
.data
= sig
;
2348 signature
.len
= sizeof sig
;
2349 if (ECDSA_SignDigest(ecpriv
, &signature
, &digest
) != SECSuccess
) {
2352 len
= signature
.len
;
2357 fputs("R = ", ecdsaresp
);
2358 to_hex_str(buf
, &signature
.data
[0], len
);
2359 fputs(buf
, ecdsaresp
);
2360 fputc('\n', ecdsaresp
);
2361 fputs("S = ", ecdsaresp
);
2362 to_hex_str(buf
, &signature
.data
[len
], len
);
2363 fputs(buf
, ecdsaresp
);
2364 fputc('\n', ecdsaresp
);
2366 PORT_FreeArena(ecpriv
->ecParams
.arena
, PR_TRUE
);
2371 if (ecparams
!= NULL
) {
2372 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2378 * Perform the ECDSA Signature Verification Test.
2380 * reqfn is the pathname of the REQUEST file.
2382 * The output RESPONSE file is written to stdout.
2385 ecdsa_sigver_test(char *reqfn
)
2387 char buf
[1024]; /* holds one line from the input REQUEST file.
2388 * needs to be large enough to hold the longest
2389 * line "Msg = <256 hex digits>\n".
2391 FILE *ecdsareq
; /* input stream from the REQUEST file */
2392 FILE *ecdsaresp
; /* output stream to the RESPONSE file */
2393 char curve
[16]; /* "nistxddd" */
2396 unsigned int flen
; /* length in bytes of the field size */
2397 unsigned int olen
; /* length in bytes of the base point order */
2398 unsigned char msg
[512]; /* message that was signed (<= 128 bytes) */
2399 unsigned int msglen
;
2400 unsigned char sha1
[20]; /* SHA-1 hash (160 bits) */
2401 unsigned char sig
[2*MAX_ECKEY_LEN
];
2402 SECItem signature
, digest
;
2403 PRBool keyvalid
= PR_TRUE
;
2404 PRBool sigvalid
= PR_TRUE
;
2406 ecdsareq
= fopen(reqfn
, "r");
2408 ecpub
.ecParams
.arena
= NULL
;
2409 strcpy(curve
, "nist");
2410 while (fgets(buf
, sizeof buf
, ecdsareq
) != NULL
) {
2411 /* a comment or blank line */
2412 if (buf
[0] == '#' || buf
[0] == '\n') {
2413 fputs(buf
, ecdsaresp
);
2417 if (buf
[0] == '[') {
2420 SECKEYECParams
*encodedparams
;
2425 *dst
++ = tolower(*src
);
2426 src
+= 2; /* skip the hyphen */
2431 encodedparams
= getECParams(curve
);
2432 if (encodedparams
== NULL
) {
2435 if (EC_DecodeParams(encodedparams
, &ecparams
) != SECSuccess
) {
2438 SECITEM_FreeItem(encodedparams
, PR_TRUE
);
2439 if (ecpub
.ecParams
.arena
!= NULL
) {
2440 PORT_FreeArena(ecpub
.ecParams
.arena
, PR_FALSE
);
2442 ecpub
.ecParams
.arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2443 if (ecpub
.ecParams
.arena
== NULL
) {
2446 if (EC_CopyParams(ecpub
.ecParams
.arena
, &ecpub
.ecParams
, ecparams
)
2450 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2451 flen
= (ecpub
.ecParams
.fieldID
.size
+ 7) >> 3;
2452 olen
= ecpub
.ecParams
.order
.len
;
2453 if (2*olen
> sizeof sig
) {
2456 ecpub
.publicValue
.type
= siBuffer
;
2457 ecpub
.publicValue
.data
= NULL
;
2458 ecpub
.publicValue
.len
= 0;
2459 SECITEM_AllocItem(ecpub
.ecParams
.arena
,
2460 &ecpub
.publicValue
, 2*flen
+1);
2461 if (ecpub
.publicValue
.data
== NULL
) {
2464 ecpub
.publicValue
.data
[0] = EC_POINT_FORM_UNCOMPRESSED
;
2465 fputs(buf
, ecdsaresp
);
2469 if (strncmp(buf
, "Msg", 3) == 0) {
2471 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2474 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
2475 hex_to_byteval(&buf
[i
], &msg
[j
]);
2478 if (SHA1_HashBuf(sha1
, msg
, msglen
) != SECSuccess
) {
2481 fputs(buf
, ecdsaresp
);
2483 digest
.type
= siBuffer
;
2485 digest
.len
= sizeof sha1
;
2490 if (strncmp(buf
, "Qx", 2) == 0) {
2491 fputs(buf
, ecdsaresp
);
2493 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2496 keyvalid
= from_hex_str(&ecpub
.publicValue
.data
[1], flen
,
2501 if (strncmp(buf
, "Qy", 2) == 0) {
2502 fputs(buf
, ecdsaresp
);
2507 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2510 keyvalid
= from_hex_str(&ecpub
.publicValue
.data
[1+flen
], flen
,
2515 if (EC_ValidatePublicKey(&ecpub
.ecParams
, &ecpub
.publicValue
)
2517 if (PORT_GetError() == SEC_ERROR_BAD_KEY
) {
2518 keyvalid
= PR_FALSE
;
2526 if (buf
[0] == 'R') {
2527 fputs(buf
, ecdsaresp
);
2529 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2532 sigvalid
= from_hex_str(sig
, olen
, &buf
[i
]);
2536 if (buf
[0] == 'S') {
2537 fputs(buf
, ecdsaresp
);
2539 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2543 sigvalid
= from_hex_str(&sig
[olen
], olen
, &buf
[i
]);
2545 signature
.type
= siBuffer
;
2546 signature
.data
= sig
;
2547 signature
.len
= 2*olen
;
2549 if (!keyvalid
|| !sigvalid
) {
2550 fputs("Result = F\n", ecdsaresp
);
2551 } else if (ECDSA_VerifyDigest(&ecpub
, &signature
, &digest
)
2553 fputs("Result = P\n", ecdsaresp
);
2555 fputs("Result = F\n", ecdsaresp
);
2561 if (ecpub
.ecParams
.arena
!= NULL
) {
2562 PORT_FreeArena(ecpub
.ecParams
.arena
, PR_FALSE
);
2566 #endif /* NSS_ENABLE_ECC */
2569 * Perform the RNG Variable Seed Test (VST) for the RNG algorithm
2570 * "DSA - Generation of X", used both as specified and as a generic
2571 * purpose RNG. The presence of "Q = ..." in the REQUEST file
2572 * indicates we are using the algorithm as specified.
2574 * reqfn is the pathname of the REQUEST file.
2576 * The output RESPONSE file is written to stdout.
2579 rng_vst(char *reqfn
)
2581 char buf
[256]; /* holds one line from the input REQUEST file.
2582 * needs to be large enough to hold the longest
2583 * line "XSeed = <128 hex digits>\n".
2585 FILE *rngreq
; /* input stream from the REQUEST file */
2586 FILE *rngresp
; /* output stream to the RESPONSE file */
2588 unsigned char Q
[DSA_SUBPRIME_LEN
];
2589 PRBool hasQ
= PR_FALSE
;
2590 unsigned int b
; /* 160 <= b <= 512, b is a multiple of 8 */
2591 unsigned char XKey
[512/8];
2592 unsigned char XSeed
[512/8];
2593 unsigned char GENX
[2*SHA1_LENGTH
];
2594 unsigned char DSAX
[DSA_SUBPRIME_LEN
];
2597 rngreq
= fopen(reqfn
, "r");
2599 while (fgets(buf
, sizeof buf
, rngreq
) != NULL
) {
2600 /* a comment or blank line */
2601 if (buf
[0] == '#' || buf
[0] == '\n') {
2602 fputs(buf
, rngresp
);
2605 /* [Xchange - SHA1] */
2606 if (buf
[0] == '[') {
2607 fputs(buf
, rngresp
);
2611 if (buf
[0] == 'Q') {
2613 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2616 for (j
=0; j
<sizeof Q
; i
+=2,j
++) {
2617 hex_to_byteval(&buf
[i
], &Q
[j
]);
2619 fputs(buf
, rngresp
);
2623 /* "COUNT = x" begins a new data set */
2624 if (strncmp(buf
, "COUNT", 5) == 0) {
2625 /* zeroize the variables for the test with this data set */
2627 memset(XKey
, 0, sizeof XKey
);
2628 memset(XSeed
, 0, sizeof XSeed
);
2629 fputs(buf
, rngresp
);
2633 if (buf
[0] == 'b') {
2635 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2639 if (b
< 160 || b
> 512 || b
%8 != 0) {
2642 fputs(buf
, rngresp
);
2646 if (strncmp(buf
, "XKey", 4) == 0) {
2648 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2651 for (j
=0; j
<b
/8; i
+=2,j
++) {
2652 hex_to_byteval(&buf
[i
], &XKey
[j
]);
2654 fputs(buf
, rngresp
);
2658 if (strncmp(buf
, "XSeed", 5) == 0) {
2660 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2663 for (j
=0; j
<b
/8; i
+=2,j
++) {
2664 hex_to_byteval(&buf
[i
], &XSeed
[j
]);
2666 fputs(buf
, rngresp
);
2668 rv
= FIPS186Change_GenerateX(XKey
, XSeed
, GENX
);
2669 if (rv
!= SECSuccess
) {
2672 fputs("X = ", rngresp
);
2674 rv
= FIPS186Change_ReduceModQForDSA(GENX
, Q
, DSAX
);
2675 if (rv
!= SECSuccess
) {
2678 to_hex_str(buf
, DSAX
, sizeof DSAX
);
2680 to_hex_str(buf
, GENX
, sizeof GENX
);
2682 fputs(buf
, rngresp
);
2683 fputc('\n', rngresp
);
2692 * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm
2693 * "DSA - Generation of X", used both as specified and as a generic
2694 * purpose RNG. The presence of "Q = ..." in the REQUEST file
2695 * indicates we are using the algorithm as specified.
2697 * reqfn is the pathname of the REQUEST file.
2699 * The output RESPONSE file is written to stdout.
2702 rng_mct(char *reqfn
)
2704 char buf
[256]; /* holds one line from the input REQUEST file.
2705 * needs to be large enough to hold the longest
2706 * line "XSeed = <128 hex digits>\n".
2708 FILE *rngreq
; /* input stream from the REQUEST file */
2709 FILE *rngresp
; /* output stream to the RESPONSE file */
2711 unsigned char Q
[DSA_SUBPRIME_LEN
];
2712 PRBool hasQ
= PR_FALSE
;
2713 unsigned int b
; /* 160 <= b <= 512, b is a multiple of 8 */
2714 unsigned char XKey
[512/8];
2715 unsigned char XSeed
[512/8];
2716 unsigned char GENX
[2*SHA1_LENGTH
];
2717 unsigned char DSAX
[DSA_SUBPRIME_LEN
];
2720 rngreq
= fopen(reqfn
, "r");
2722 while (fgets(buf
, sizeof buf
, rngreq
) != NULL
) {
2723 /* a comment or blank line */
2724 if (buf
[0] == '#' || buf
[0] == '\n') {
2725 fputs(buf
, rngresp
);
2728 /* [Xchange - SHA1] */
2729 if (buf
[0] == '[') {
2730 fputs(buf
, rngresp
);
2734 if (buf
[0] == 'Q') {
2736 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2739 for (j
=0; j
<sizeof Q
; i
+=2,j
++) {
2740 hex_to_byteval(&buf
[i
], &Q
[j
]);
2742 fputs(buf
, rngresp
);
2746 /* "COUNT = x" begins a new data set */
2747 if (strncmp(buf
, "COUNT", 5) == 0) {
2748 /* zeroize the variables for the test with this data set */
2750 memset(XKey
, 0, sizeof XKey
);
2751 memset(XSeed
, 0, sizeof XSeed
);
2752 fputs(buf
, rngresp
);
2756 if (buf
[0] == 'b') {
2758 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2762 if (b
< 160 || b
> 512 || b
%8 != 0) {
2765 fputs(buf
, rngresp
);
2769 if (strncmp(buf
, "XKey", 4) == 0) {
2771 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2774 for (j
=0; j
<b
/8; i
+=2,j
++) {
2775 hex_to_byteval(&buf
[i
], &XKey
[j
]);
2777 fputs(buf
, rngresp
);
2781 if (strncmp(buf
, "XSeed", 5) == 0) {
2784 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2787 for (j
=0; j
<b
/8; i
+=2,j
++) {
2788 hex_to_byteval(&buf
[i
], &XSeed
[j
]);
2790 fputs(buf
, rngresp
);
2792 for (k
= 0; k
< 10000; k
++) {
2793 rv
= FIPS186Change_GenerateX(XKey
, XSeed
, GENX
);
2794 if (rv
!= SECSuccess
) {
2798 fputs("X = ", rngresp
);
2800 rv
= FIPS186Change_ReduceModQForDSA(GENX
, Q
, DSAX
);
2801 if (rv
!= SECSuccess
) {
2804 to_hex_str(buf
, DSAX
, sizeof DSAX
);
2806 to_hex_str(buf
, GENX
, sizeof GENX
);
2808 fputs(buf
, rngresp
);
2809 fputc('\n', rngresp
);
2818 * Calculate the SHA Message Digest
2820 * MD = Message digest
2821 * MDLen = length of Message Digest and SHA_Type
2822 * msg = message to digest
2823 * msgLen = length of message to digest
2825 SECStatus
sha_calcMD(unsigned char *MD
, unsigned int MDLen
, unsigned char *msg
, unsigned int msgLen
)
2827 SECStatus sha_status
= SECFailure
;
2829 if (MDLen
== SHA1_LENGTH
) {
2830 sha_status
= SHA1_HashBuf(MD
, msg
, msgLen
);
2831 } else if (MDLen
== SHA256_LENGTH
) {
2832 sha_status
= SHA256_HashBuf(MD
, msg
, msgLen
);
2833 } else if (MDLen
== SHA384_LENGTH
) {
2834 sha_status
= SHA384_HashBuf(MD
, msg
, msgLen
);
2835 } else if (MDLen
== SHA512_LENGTH
) {
2836 sha_status
= SHA512_HashBuf(MD
, msg
, msgLen
);
2843 * Perform the SHA Monte Carlo Test
2845 * MDLen = length of Message Digest and SHA_Type
2846 * seed = input seed value
2847 * resp = is the output response file.
2849 SECStatus
sha_mct_test(unsigned int MDLen
, unsigned char *seed
, FILE *resp
)
2852 unsigned int msgLen
= MDLen
*3;
2853 unsigned char MD_i3
[HASH_LENGTH_MAX
]; /* MD[i-3] */
2854 unsigned char MD_i2
[HASH_LENGTH_MAX
]; /* MD[i-2] */
2855 unsigned char MD_i1
[HASH_LENGTH_MAX
]; /* MD[i-1] */
2856 unsigned char MD_i
[HASH_LENGTH_MAX
]; /* MD[i] */
2857 unsigned char msg
[HASH_LENGTH_MAX
*3];
2858 char buf
[HASH_LENGTH_MAX
*2 + 1]; /* MAX buf MD_i as a hex string */
2860 for (j
=0; j
<100; j
++) {
2861 /* MD_0 = MD_1 = MD_2 = seed */
2862 memcpy(MD_i3
, seed
, MDLen
);
2863 memcpy(MD_i2
, seed
, MDLen
);
2864 memcpy(MD_i1
, seed
, MDLen
);
2866 for (i
=3; i
< 1003; i
++) {
2867 /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */
2868 memcpy(msg
, MD_i3
, MDLen
);
2869 memcpy(&msg
[MDLen
], MD_i2
, MDLen
);
2870 memcpy(&msg
[MDLen
*2], MD_i1
,MDLen
);
2872 /* MDi = SHA(Msg) */
2873 if (sha_calcMD(MD_i
, MDLen
,
2874 msg
, msgLen
) != SECSuccess
) {
2878 /* save MD[i-3] MD[i-2] MD[i-1] */
2879 memcpy(MD_i3
, MD_i2
, MDLen
);
2880 memcpy(MD_i2
, MD_i1
, MDLen
);
2881 memcpy(MD_i1
, MD_i
, MDLen
);
2886 memcpy(seed
, MD_i
, MDLen
);
2888 sprintf(buf
, "COUNT = %d\n", j
);
2892 fputs("MD = ", resp
);
2893 to_hex_str(buf
, MD_i
, MDLen
);
2902 * Perform the SHA Tests.
2904 * reqfn is the pathname of the input REQUEST file.
2906 * The output RESPONSE file is written to stdout.
2908 void sha_test(char *reqfn
)
2911 unsigned int MDlen
; /* the length of the Message Digest in Bytes */
2912 unsigned int msgLen
; /* the length of the input Message in Bytes */
2913 unsigned char *msg
= NULL
; /* holds the message to digest.*/
2914 size_t bufSize
= 25608; /*MAX buffer size */
2915 char *buf
= NULL
; /* holds one line from the input REQUEST file.*/
2916 unsigned char seed
[HASH_LENGTH_MAX
]; /* max size of seed 64 bytes */
2917 unsigned char MD
[HASH_LENGTH_MAX
]; /* message digest */
2919 FILE *req
= NULL
; /* input stream from the REQUEST file */
2920 FILE *resp
; /* output stream to the RESPONSE file */
2922 buf
= PORT_ZAlloc(bufSize
);
2927 /* zeroize the variables for the test with this data set */
2928 memset(seed
, 0, sizeof seed
);
2930 req
= fopen(reqfn
, "r");
2932 while (fgets(buf
, bufSize
, req
) != NULL
) {
2934 /* a comment or blank line */
2935 if (buf
[0] == '#' || buf
[0] == '\n') {
2939 /* [L = Length of the Message Digest and sha_type */
2940 if (buf
[0] == '[') {
2941 if (strncmp(&buf
[1], "L ", 1) == 0) {
2943 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2946 MDlen
= atoi(&buf
[i
]);
2951 /* Len = Length of the Input Message Length ... */
2952 if (strncmp(buf
, "Len", 3) == 0) {
2954 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2958 PORT_ZFree(msg
,msgLen
);
2961 msgLen
= atoi(&buf
[i
]); /* in bits */
2962 if (msgLen
%8 != 0) {
2963 fprintf(stderr
, "SHA tests are incorrectly configured for "
2964 "BIT oriented implementations\n");
2967 msgLen
= msgLen
/8; /* convert to bytes */
2969 msg
= PORT_ZAlloc(msgLen
);
2970 if (msg
== NULL
&& msgLen
!= 0) {
2976 if (strncmp(buf
, "Msg", 3) == 0) {
2978 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2981 for (j
=0; j
< msgLen
; i
+=2,j
++) {
2982 hex_to_byteval(&buf
[i
], &msg
[j
]);
2985 /* calculate the Message Digest */
2986 memset(MD
, 0, sizeof MD
);
2987 if (sha_calcMD(MD
, MDlen
,
2988 msg
, msgLen
) != SECSuccess
) {
2992 fputs("MD = ", resp
);
2993 to_hex_str(buf
, MD
, MDlen
);
3000 if (strncmp(buf
, "Seed", 4) == 0) {
3002 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3005 for (j
=0; j
<sizeof seed
; i
+=2,j
++) {
3006 hex_to_byteval(&buf
[i
], &seed
[j
]);
3012 /* do the Monte Carlo test */
3013 if (sha_mct_test(MDlen
, seed
, resp
) != SECSuccess
) {
3025 PORT_ZFree(buf
, bufSize
);
3028 PORT_ZFree(msg
, msgLen
);
3032 /****************************************************/
3033 /* HMAC SHA-X calc */
3034 /* hmac_computed - the computed HMAC */
3035 /* hmac_length - the length of the computed HMAC */
3036 /* secret_key - secret key to HMAC */
3037 /* secret_key_length - length of secret key, */
3038 /* message - message to HMAC */
3039 /* message_length - length ofthe message */
3040 /****************************************************/
3042 hmac_calc(unsigned char *hmac_computed
,
3043 const unsigned int hmac_length
,
3044 const unsigned char *secret_key
,
3045 const unsigned int secret_key_length
,
3046 const unsigned char *message
,
3047 const unsigned int message_length
,
3048 const HASH_HashType hashAlg
)
3050 SECStatus hmac_status
= SECFailure
;
3051 HMACContext
*cx
= NULL
;
3052 SECHashObject
*hashObj
= NULL
;
3053 unsigned int bytes_hashed
= 0;
3055 hashObj
= (SECHashObject
*) HASH_GetRawHashObject(hashAlg
);
3058 return( SECFailure
);
3060 cx
= HMAC_Create(hashObj
, secret_key
,
3062 PR_TRUE
); /* PR_TRUE for in FIPS mode */
3065 return( SECFailure
);
3068 HMAC_Update(cx
, message
, message_length
);
3069 hmac_status
= HMAC_Finish(cx
, hmac_computed
, &bytes_hashed
,
3072 HMAC_Destroy(cx
, PR_TRUE
);
3074 return( hmac_status
);
3078 * Perform the HMAC Tests.
3080 * reqfn is the pathname of the input REQUEST file.
3082 * The output RESPONSE file is written to stdout.
3084 void hmac_test(char *reqfn
)
3087 size_t bufSize
= 288; /* MAX buffer size */
3088 char *buf
= NULL
; /* holds one line from the input REQUEST file.*/
3089 unsigned int keyLen
; /* Key Length */
3090 unsigned char key
[140]; /* key MAX size = 140 */
3091 unsigned int msgLen
= 128; /* the length of the input */
3092 /* Message is always 128 Bytes */
3093 unsigned char *msg
= NULL
; /* holds the message to digest.*/
3094 unsigned int HMACLen
; /* the length of the HMAC Bytes */
3095 unsigned char HMAC
[HASH_LENGTH_MAX
]; /* computed HMAC */
3096 HASH_HashType hash_alg
; /* HMAC type */
3098 FILE *req
= NULL
; /* input stream from the REQUEST file */
3099 FILE *resp
; /* output stream to the RESPONSE file */
3101 buf
= PORT_ZAlloc(bufSize
);
3105 msg
= PORT_ZAlloc(msgLen
);
3106 memset(msg
, 0, msgLen
);
3111 req
= fopen(reqfn
, "r");
3113 while (fgets(buf
, bufSize
, req
) != NULL
) {
3115 /* a comment or blank line */
3116 if (buf
[0] == '#' || buf
[0] == '\n') {
3120 /* [L = Length of the MAC and HASH_type */
3121 if (buf
[0] == '[') {
3122 if (strncmp(&buf
[1], "L ", 1) == 0) {
3124 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3127 /* HMACLen will get reused for Tlen */
3128 HMACLen
= atoi(&buf
[i
]);
3129 /* set the HASH algorithm for HMAC */
3130 if (HMACLen
== SHA1_LENGTH
) {
3131 hash_alg
= HASH_AlgSHA1
;
3132 } else if (HMACLen
== SHA256_LENGTH
) {
3133 hash_alg
= HASH_AlgSHA256
;
3134 } else if (HMACLen
== SHA384_LENGTH
) {
3135 hash_alg
= HASH_AlgSHA384
;
3136 } else if (HMACLen
== SHA512_LENGTH
) {
3137 hash_alg
= HASH_AlgSHA512
;
3145 /* Count = test iteration number*/
3146 if (strncmp(buf
, "Count ", 5) == 0) {
3147 /* count can just be put into resp file */
3149 /* zeroize the variables for the test with this data set */
3152 memset(key
, 0, sizeof key
);
3153 memset(msg
, 0, sizeof msg
);
3154 memset(HMAC
, 0, sizeof HMAC
);
3157 /* KLen = Length of the Input Secret Key ... */
3158 if (strncmp(buf
, "Klen", 4) == 0) {
3160 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3163 keyLen
= atoi(&buf
[i
]); /* in bytes */
3167 /* key = the secret key for the key to MAC */
3168 if (strncmp(buf
, "Key", 3) == 0) {
3170 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3173 for (j
=0; j
< keyLen
; i
+=2,j
++) {
3174 hex_to_byteval(&buf
[i
], &key
[j
]);
3178 /* TLen = Length of the calculated HMAC */
3179 if (strncmp(buf
, "Tlen", 4) == 0) {
3181 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3184 HMACLen
= atoi(&buf
[i
]); /* in bytes */
3188 /* MSG = to HMAC always 128 bytes for these tests */
3189 if (strncmp(buf
, "Msg", 3) == 0) {
3191 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3194 for (j
=0; j
< msgLen
; i
+=2,j
++) {
3195 hex_to_byteval(&buf
[i
], &msg
[j
]);
3198 /* calculate the HMAC and output */
3199 if (hmac_calc(HMAC
, HMACLen
, key
, keyLen
,
3200 msg
, msgLen
, hash_alg
) != SECSuccess
) {
3203 fputs("MAC = ", resp
);
3204 to_hex_str(buf
, HMAC
, HMACLen
);
3215 PORT_ZFree(buf
, bufSize
);
3218 PORT_ZFree(msg
, msgLen
);
3223 * Perform the DSA Key Pair Generation Test.
3225 * reqfn is the pathname of the REQUEST file.
3227 * The output RESPONSE file is written to stdout.
3230 dsa_keypair_test(char *reqfn
)
3232 char buf
[260]; /* holds one line from the input REQUEST file
3233 * or to the output RESPONSE file.
3234 * 257 to hold (128 public key (x2 for HEX) + 1'\n'
3236 FILE *dsareq
; /* input stream from the REQUEST file */
3237 FILE *dsaresp
; /* output stream to the RESPONSE file */
3238 int N
; /* number of time to generate key pair */
3241 PQGParams
*pqg
= NULL
;
3242 PQGVerify
*vfy
= NULL
;
3243 int keySizeIndex
; /* index for valid key sizes */
3245 dsareq
= fopen(reqfn
, "r");
3247 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
3248 /* a comment or blank line */
3249 if (buf
[0] == '#' || buf
[0] == '\n') {
3250 fputs(buf
, dsaresp
);
3255 if (buf
[0] == '[') {
3257 PQG_DestroyParams(pqg
);
3261 PQG_DestroyVerify(vfy
);
3265 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
3268 fputs(buf
, dsaresp
);
3269 fputc('\n', dsaresp
);
3271 /*****************************************************************
3272 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
3273 * that points to a valid key size.
3275 keySizeIndex
= PQG_PBITS_TO_INDEX(modulus
);
3276 if(keySizeIndex
== -1 || modulus
<512 || modulus
>1024) {
3278 "DSA key size must be a multiple of 64 between 512 "
3279 "and 1024, inclusive");
3283 /* Generate the parameters P, Q, and G */
3284 if (PQG_ParamGenSeedLen(keySizeIndex
, PQG_TEST_SEED_BYTES
,
3285 &pqg
, &vfy
) != SECSuccess
) {
3286 fprintf(dsaresp
, "ERROR: Unable to generate PQG parameters");
3290 /* output P, Q, and G */
3291 to_hex_str(buf
, pqg
->prime
.data
, pqg
->prime
.len
);
3292 fprintf(dsaresp
, "P = %s\n", buf
);
3293 to_hex_str(buf
, pqg
->subPrime
.data
, pqg
->subPrime
.len
);
3294 fprintf(dsaresp
, "Q = %s\n", buf
);
3295 to_hex_str(buf
, pqg
->base
.data
, pqg
->base
.len
);
3296 fprintf(dsaresp
, "G = %s\n\n", buf
);
3300 if (buf
[0] == 'N') {
3302 if (sscanf(buf
, "N = %d", &N
) != 1) {
3305 /* Generate a DSA key, and output the key pair for N times */
3306 for (i
= 0; i
< N
; i
++) {
3307 DSAPrivateKey
*dsakey
= NULL
;
3308 if (DSA_NewKey(pqg
, &dsakey
) != SECSuccess
) {
3309 fprintf(dsaresp
, "ERROR: Unable to generate DSA key");
3312 to_hex_str(buf
, dsakey
->privateValue
.data
,
3313 dsakey
->privateValue
.len
);
3314 fprintf(dsaresp
, "X = %s\n", buf
);
3315 to_hex_str(buf
, dsakey
->publicValue
.data
,
3316 dsakey
->publicValue
.len
);
3317 fprintf(dsaresp
, "Y = %s\n\n", buf
);
3318 PORT_FreeArena(dsakey
->params
.arena
, PR_TRUE
);
3330 * Perform the DSA Domain Parameter Validation Test.
3332 * reqfn is the pathname of the REQUEST file.
3334 * The output RESPONSE file is written to stdout.
3337 dsa_pqgver_test(char *reqfn
)
3339 char buf
[263]; /* holds one line from the input REQUEST file
3340 * or to the output RESPONSE file.
3341 * 260 to hold (128 public key (x2 for HEX) + P = ...
3343 FILE *dsareq
; /* input stream from the REQUEST file */
3344 FILE *dsaresp
; /* output stream to the RESPONSE file */
3349 unsigned int pghSize
; /* size for p, g, and h */
3351 dsareq
= fopen(reqfn
, "r");
3353 memset(&pqg
, 0, sizeof(pqg
));
3354 memset(&vfy
, 0, sizeof(vfy
));
3356 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
3357 /* a comment or blank line */
3358 if (buf
[0] == '#' || buf
[0] == '\n') {
3359 fputs(buf
, dsaresp
);
3364 if (buf
[0] == '[') {
3366 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
3370 if (pqg
.prime
.data
) { /* P */
3371 SECITEM_ZfreeItem(&pqg
.prime
, PR_FALSE
);
3373 if (pqg
.subPrime
.data
) { /* Q */
3374 SECITEM_ZfreeItem(&pqg
.subPrime
, PR_FALSE
);
3376 if (pqg
.base
.data
) { /* G */
3377 SECITEM_ZfreeItem(&pqg
.base
, PR_FALSE
);
3379 if (vfy
.seed
.data
) { /* seed */
3380 SECITEM_ZfreeItem(&vfy
.seed
, PR_FALSE
);
3382 if (vfy
.h
.data
) { /* H */
3383 SECITEM_ZfreeItem(&vfy
.h
, PR_FALSE
);
3386 fputs(buf
, dsaresp
);
3388 /*calculate the size of p, g, and h then allocate items */
3389 pghSize
= modulus
/8;
3390 SECITEM_AllocItem(NULL
, &pqg
.prime
, pghSize
);
3391 SECITEM_AllocItem(NULL
, &pqg
.base
, pghSize
);
3392 SECITEM_AllocItem(NULL
, &vfy
.h
, pghSize
);
3393 pqg
.prime
.len
= pqg
.base
.len
= vfy
.h
.len
= pghSize
;
3394 /* seed and q are always 20 bytes */
3395 SECITEM_AllocItem(NULL
, &vfy
.seed
, 20);
3396 SECITEM_AllocItem(NULL
, &pqg
.subPrime
, 20);
3397 vfy
.seed
.len
= pqg
.subPrime
.len
= 20;
3403 if (buf
[0] == 'P') {
3405 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3408 for (j
=0; j
< pqg
.prime
.len
; i
+=2,j
++) {
3409 hex_to_byteval(&buf
[i
], &pqg
.prime
.data
[j
]);
3412 fputs(buf
, dsaresp
);
3417 if (buf
[0] == 'Q') {
3419 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3422 for (j
=0; j
< pqg
.subPrime
.len
; i
+=2,j
++) {
3423 hex_to_byteval(&buf
[i
], &pqg
.subPrime
.data
[j
]);
3426 fputs(buf
, dsaresp
);
3431 if (buf
[0] == 'G') {
3433 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3436 for (j
=0; j
< pqg
.base
.len
; i
+=2,j
++) {
3437 hex_to_byteval(&buf
[i
], &pqg
.base
.data
[j
]);
3440 fputs(buf
, dsaresp
);
3445 if (strncmp(buf
, "Seed", 4) == 0) {
3447 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3450 for (j
=0; j
< vfy
.seed
.len
; i
+=2,j
++) {
3451 hex_to_byteval(&buf
[i
], &vfy
.seed
.data
[j
]);
3454 fputs(buf
, dsaresp
);
3459 if (buf
[0] == 'c') {
3461 if (sscanf(buf
, "c = %u", &vfy
.counter
) != 1) {
3465 fputs(buf
, dsaresp
);
3470 if (buf
[0] == 'H') {
3471 SECStatus rv
, result
= SECFailure
;
3474 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3477 for (j
=0; j
< vfy
.h
.len
; i
+=2,j
++) {
3478 hex_to_byteval(&buf
[i
], &vfy
.h
.data
[j
]);
3480 fputs(buf
, dsaresp
);
3482 /* Verify the Parameters */
3483 rv
= PQG_VerifyParams(&pqg
, &vfy
, &result
);
3484 if (rv
!= SECSuccess
) {
3487 if (result
== SECSuccess
) {
3488 fprintf(dsaresp
, "Result = P\n");
3490 fprintf(dsaresp
, "Result = F\n");
3497 if (pqg
.prime
.data
) { /* P */
3498 SECITEM_ZfreeItem(&pqg
.prime
, PR_FALSE
);
3500 if (pqg
.subPrime
.data
) { /* Q */
3501 SECITEM_ZfreeItem(&pqg
.subPrime
, PR_FALSE
);
3503 if (pqg
.base
.data
) { /* G */
3504 SECITEM_ZfreeItem(&pqg
.base
, PR_FALSE
);
3506 if (vfy
.seed
.data
) { /* seed */
3507 SECITEM_ZfreeItem(&vfy
.seed
, PR_FALSE
);
3509 if (vfy
.h
.data
) { /* H */
3510 SECITEM_ZfreeItem(&vfy
.h
, PR_FALSE
);
3516 * Perform the DSA Public Key Validation Test.
3518 * reqfn is the pathname of the REQUEST file.
3520 * The output RESPONSE file is written to stdout.
3523 dsa_pqggen_test(char *reqfn
)
3525 char buf
[263]; /* holds one line from the input REQUEST file
3526 * or to the output RESPONSE file.
3527 * 263 to hold seed = (128 public key (x2 for HEX)
3529 FILE *dsareq
; /* input stream from the REQUEST file */
3530 FILE *dsaresp
; /* output stream to the RESPONSE file */
3531 int N
; /* number of times to generate parameters */
3535 PQGParams
*pqg
= NULL
;
3536 PQGVerify
*vfy
= NULL
;
3537 unsigned int keySizeIndex
;
3539 dsareq
= fopen(reqfn
, "r");
3541 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
3542 /* a comment or blank line */
3543 if (buf
[0] == '#' || buf
[0] == '\n') {
3544 fputs(buf
, dsaresp
);
3549 if (buf
[0] == '[') {
3551 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
3555 fputs(buf
, dsaresp
);
3556 fputc('\n', dsaresp
);
3558 /****************************************************************
3559 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
3560 * that points to a valid key size.
3562 keySizeIndex
= PQG_PBITS_TO_INDEX(modulus
);
3563 if(keySizeIndex
== -1 || modulus
<512 || modulus
>1024) {
3565 "DSA key size must be a multiple of 64 between 512 "
3566 "and 1024, inclusive");
3573 if (buf
[0] == 'N') {
3575 if (sscanf(buf
, "N = %d", &N
) != 1) {
3578 for (i
= 0; i
< N
; i
++) {
3579 if (PQG_ParamGenSeedLen(keySizeIndex
, PQG_TEST_SEED_BYTES
,
3580 &pqg
, &vfy
) != SECSuccess
) {
3582 "ERROR: Unable to generate PQG parameters");
3585 to_hex_str(buf
, pqg
->prime
.data
, pqg
->prime
.len
);
3586 fprintf(dsaresp
, "P = %s\n", buf
);
3587 to_hex_str(buf
, pqg
->subPrime
.data
, pqg
->subPrime
.len
);
3588 fprintf(dsaresp
, "Q = %s\n", buf
);
3589 to_hex_str(buf
, pqg
->base
.data
, pqg
->base
.len
);
3590 fprintf(dsaresp
, "G = %s\n", buf
);
3591 to_hex_str(buf
, vfy
->seed
.data
, vfy
->seed
.len
);
3592 fprintf(dsaresp
, "Seed = %s\n", buf
);
3593 fprintf(dsaresp
, "c = %d\n", vfy
->counter
);
3594 to_hex_str(buf
, vfy
->h
.data
, vfy
->h
.len
);
3595 fputs("H = ", dsaresp
);
3596 for (j
=vfy
->h
.len
; j
<pqg
->prime
.len
; j
++) {
3597 fprintf(dsaresp
, "00");
3599 fprintf(dsaresp
, "%s\n", buf
);
3600 fputc('\n', dsaresp
);
3602 PQG_DestroyParams(pqg
);
3606 PQG_DestroyVerify(vfy
);
3618 PQG_DestroyParams(pqg
);
3621 PQG_DestroyVerify(vfy
);
3626 * Perform the DSA Signature Generation Test.
3628 * reqfn is the pathname of the REQUEST file.
3630 * The output RESPONSE file is written to stdout.
3633 dsa_siggen_test(char *reqfn
)
3635 char buf
[263]; /* holds one line from the input REQUEST file
3636 * or to the output RESPONSE file.
3637 * max for Msg = ....
3639 FILE *dsareq
; /* input stream from the REQUEST file */
3640 FILE *dsaresp
; /* output stream to the RESPONSE file */
3643 PQGParams
*pqg
= NULL
;
3644 PQGVerify
*vfy
= NULL
;
3645 DSAPrivateKey
*dsakey
= NULL
;
3646 int keySizeIndex
; /* index for valid key sizes */
3647 unsigned char sha1
[20]; /* SHA-1 hash (160 bits) */
3648 unsigned char sig
[DSA_SIGNATURE_LEN
];
3649 SECItem digest
, signature
;
3651 dsareq
= fopen(reqfn
, "r");
3654 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
3655 /* a comment or blank line */
3656 if (buf
[0] == '#' || buf
[0] == '\n') {
3657 fputs(buf
, dsaresp
);
3662 if (buf
[0] == '[') {
3664 PQG_DestroyParams(pqg
);
3668 PQG_DestroyVerify(vfy
);
3671 if (dsakey
!= NULL
) {
3672 PORT_FreeArena(dsakey
->params
.arena
, PR_TRUE
);
3676 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
3679 fputs(buf
, dsaresp
);
3680 fputc('\n', dsaresp
);
3682 /****************************************************************
3683 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
3684 * that points to a valid key size.
3686 keySizeIndex
= PQG_PBITS_TO_INDEX(modulus
);
3687 if(keySizeIndex
== -1 || modulus
<512 || modulus
>1024) {
3689 "DSA key size must be a multiple of 64 between 512 "
3690 "and 1024, inclusive");
3694 /* Generate PQG and output PQG */
3695 if (PQG_ParamGenSeedLen(keySizeIndex
, PQG_TEST_SEED_BYTES
,
3696 &pqg
, &vfy
) != SECSuccess
) {
3697 fprintf(dsaresp
, "ERROR: Unable to generate PQG parameters");
3700 to_hex_str(buf
, pqg
->prime
.data
, pqg
->prime
.len
);
3701 fprintf(dsaresp
, "P = %s\n", buf
);
3702 to_hex_str(buf
, pqg
->subPrime
.data
, pqg
->subPrime
.len
);
3703 fprintf(dsaresp
, "Q = %s\n", buf
);
3704 to_hex_str(buf
, pqg
->base
.data
, pqg
->base
.len
);
3705 fprintf(dsaresp
, "G = %s\n", buf
);
3707 /* create DSA Key */
3708 if (DSA_NewKey(pqg
, &dsakey
) != SECSuccess
) {
3709 fprintf(dsaresp
, "ERROR: Unable to generate DSA key");
3716 if (strncmp(buf
, "Msg", 3) == 0) {
3717 unsigned char msg
[128]; /* MAX msg 128 */
3718 unsigned int len
= 0;
3720 memset(sha1
, 0, sizeof sha1
);
3721 memset(sig
, 0, sizeof sig
);
3724 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3727 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
3728 hex_to_byteval(&buf
[i
], &msg
[j
]);
3730 if (SHA1_HashBuf(sha1
, msg
, j
) != SECSuccess
) {
3731 fprintf(dsaresp
, "ERROR: Unable to generate SHA1 digest");
3735 digest
.type
= siBuffer
;
3737 digest
.len
= sizeof sha1
;
3738 signature
.type
= siBuffer
;
3739 signature
.data
= sig
;
3740 signature
.len
= sizeof sig
;
3742 if (DSA_SignDigest(dsakey
, &signature
, &digest
) != SECSuccess
) {
3743 fprintf(dsaresp
, "ERROR: Unable to generate DSA signature");
3746 len
= signature
.len
;
3752 /* output the orginal Msg, and generated Y, R, and S */
3753 fputs(buf
, dsaresp
);
3754 fputc('\n', dsaresp
);
3755 to_hex_str(buf
, dsakey
->publicValue
.data
,
3756 dsakey
->publicValue
.len
);
3757 fprintf(dsaresp
, "Y = %s\n", buf
);
3758 to_hex_str(buf
, &signature
.data
[0], len
);
3759 fprintf(dsaresp
, "R = %s\n", buf
);
3760 to_hex_str(buf
, &signature
.data
[len
], len
);
3761 fprintf(dsaresp
, "S = %s\n", buf
);
3769 PQG_DestroyParams(pqg
);
3773 PQG_DestroyVerify(vfy
);
3777 PORT_FreeArena(dsakey
->params
.arena
, PR_TRUE
);
3783 * Perform the DSA Signature Verification Test.
3785 * reqfn is the pathname of the REQUEST file.
3787 * The output RESPONSE file is written to stdout.
3790 dsa_sigver_test(char *reqfn
)
3792 char buf
[263]; /* holds one line from the input REQUEST file
3793 * or to the output RESPONSE file.
3794 * max for Msg = ....
3796 FILE *dsareq
; /* input stream from the REQUEST file */
3797 FILE *dsaresp
; /* output stream to the RESPONSE file */
3800 SECItem digest
, signature
;
3801 DSAPublicKey pubkey
;
3802 unsigned int pgySize
; /* size for p, g, and y */
3803 unsigned char sha1
[20]; /* SHA-1 hash (160 bits) */
3804 unsigned char sig
[DSA_SIGNATURE_LEN
];
3806 dsareq
= fopen(reqfn
, "r");
3808 memset(&pubkey
, 0, sizeof(pubkey
));
3810 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
3811 /* a comment or blank line */
3812 if (buf
[0] == '#' || buf
[0] == '\n') {
3813 fputs(buf
, dsaresp
);
3818 if (buf
[0] == '[') {
3820 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
3824 if (pubkey
.params
.prime
.data
) { /* P */
3825 SECITEM_ZfreeItem(&pubkey
.params
.prime
, PR_FALSE
);
3827 if (pubkey
.params
.subPrime
.data
) { /* Q */
3828 SECITEM_ZfreeItem(&pubkey
.params
.subPrime
, PR_FALSE
);
3830 if (pubkey
.params
.base
.data
) { /* G */
3831 SECITEM_ZfreeItem(&pubkey
.params
.base
, PR_FALSE
);
3833 if (pubkey
.publicValue
.data
) { /* Y */
3834 SECITEM_ZfreeItem(&pubkey
.publicValue
, PR_FALSE
);
3836 fputs(buf
, dsaresp
);
3838 /* calculate the size of p, g, and y then allocate items */
3839 pgySize
= modulus
/8;
3840 SECITEM_AllocItem(NULL
, &pubkey
.params
.prime
, pgySize
);
3841 SECITEM_AllocItem(NULL
, &pubkey
.params
.base
, pgySize
);
3842 SECITEM_AllocItem(NULL
, &pubkey
.publicValue
, pgySize
);
3843 pubkey
.params
.prime
.len
= pubkey
.params
.base
.len
= pgySize
;
3844 pubkey
.publicValue
.len
= pgySize
;
3846 /* q always 20 bytes */
3847 SECITEM_AllocItem(NULL
, &pubkey
.params
.subPrime
, 20);
3848 pubkey
.params
.subPrime
.len
= 20;
3853 if (buf
[0] == 'P') {
3855 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3858 memset(pubkey
.params
.prime
.data
, 0, pubkey
.params
.prime
.len
);
3859 for (j
=0; j
< pubkey
.params
.prime
.len
; i
+=2,j
++) {
3860 hex_to_byteval(&buf
[i
], &pubkey
.params
.prime
.data
[j
]);
3863 fputs(buf
, dsaresp
);
3868 if (buf
[0] == 'Q') {
3870 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3873 memset(pubkey
.params
.subPrime
.data
, 0, pubkey
.params
.subPrime
.len
);
3874 for (j
=0; j
< pubkey
.params
.subPrime
.len
; i
+=2,j
++) {
3875 hex_to_byteval(&buf
[i
], &pubkey
.params
.subPrime
.data
[j
]);
3878 fputs(buf
, dsaresp
);
3883 if (buf
[0] == 'G') {
3885 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3888 memset(pubkey
.params
.base
.data
, 0, pubkey
.params
.base
.len
);
3889 for (j
=0; j
< pubkey
.params
.base
.len
; i
+=2,j
++) {
3890 hex_to_byteval(&buf
[i
], &pubkey
.params
.base
.data
[j
]);
3893 fputs(buf
, dsaresp
);
3898 if (strncmp(buf
, "Msg", 3) == 0) {
3899 unsigned char msg
[128]; /* MAX msg 128 */
3900 memset(sha1
, 0, sizeof sha1
);
3903 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3906 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
3907 hex_to_byteval(&buf
[i
], &msg
[j
]);
3909 if (SHA1_HashBuf(sha1
, msg
, j
) != SECSuccess
) {
3910 fprintf(dsaresp
, "ERROR: Unable to generate SHA1 digest");
3914 fputs(buf
, dsaresp
);
3919 if (buf
[0] == 'Y') {
3921 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3924 memset(pubkey
.publicValue
.data
, 0, pubkey
.params
.subPrime
.len
);
3925 for (j
=0; j
< pubkey
.publicValue
.len
; i
+=2,j
++) {
3926 hex_to_byteval(&buf
[i
], &pubkey
.publicValue
.data
[j
]);
3929 fputs(buf
, dsaresp
);
3934 if (buf
[0] == 'R') {
3935 memset(sig
, 0, sizeof sig
);
3937 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3940 for (j
=0; j
< DSA_SUBPRIME_LEN
; i
+=2,j
++) {
3941 hex_to_byteval(&buf
[i
], &sig
[j
]);
3944 fputs(buf
, dsaresp
);
3949 if (buf
[0] == 'S') {
3951 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3954 for (j
=DSA_SUBPRIME_LEN
; j
< DSA_SIGNATURE_LEN
; i
+=2,j
++) {
3955 hex_to_byteval(&buf
[i
], &sig
[j
]);
3957 fputs(buf
, dsaresp
);
3959 digest
.type
= siBuffer
;
3961 digest
.len
= sizeof sha1
;
3962 signature
.type
= siBuffer
;
3963 signature
.data
= sig
;
3964 signature
.len
= sizeof sig
;
3966 if (DSA_VerifyDigest(&pubkey
, &signature
, &digest
) == SECSuccess
) {
3967 fprintf(dsaresp
, "Result = P\n");
3969 fprintf(dsaresp
, "Result = F\n");
3976 if (pubkey
.params
.prime
.data
) { /* P */
3977 SECITEM_ZfreeItem(&pubkey
.params
.prime
, PR_FALSE
);
3979 if (pubkey
.params
.subPrime
.data
) { /* Q */
3980 SECITEM_ZfreeItem(&pubkey
.params
.subPrime
, PR_FALSE
);
3982 if (pubkey
.params
.base
.data
) { /* G */
3983 SECITEM_ZfreeItem(&pubkey
.params
.base
, PR_FALSE
);
3985 if (pubkey
.publicValue
.data
) { /* Y */
3986 SECITEM_ZfreeItem(&pubkey
.publicValue
, PR_FALSE
);
3991 * Perform the RSA Signature Generation Test.
3993 * reqfn is the pathname of the REQUEST file.
3995 * The output RESPONSE file is written to stdout.
3998 rsa_siggen_test(char *reqfn
)
4000 char buf
[2*RSA_MAX_TEST_MODULUS_BYTES
+1];
4001 /* buf holds one line from the input REQUEST file
4002 * or to the output RESPONSE file.
4003 * 2x for HEX output + 1 for \n
4005 FILE *rsareq
; /* input stream from the REQUEST file */
4006 FILE *rsaresp
; /* output stream to the RESPONSE file */
4008 unsigned char sha
[HASH_LENGTH_MAX
]; /* SHA digest */
4009 unsigned int shaLength
= 0; /* length of SHA */
4010 HASH_HashType shaAlg
= HASH_AlgNULL
; /* type of SHA Alg */
4011 SECOidTag shaOid
= SEC_OID_UNKNOWN
;
4012 int modulus
; /* the Modulus size */
4013 int publicExponent
= DEFAULT_RSA_PUBLIC_EXPONENT
;
4014 SECItem pe
= {0, 0, 0 };
4015 unsigned char pubEx
[4];
4018 RSAPrivateKey
*rsaBlapiPrivKey
= NULL
; /* holds RSA private and
4020 RSAPublicKey
*rsaBlapiPublicKey
= NULL
; /* hold RSA public key */
4022 rsareq
= fopen(reqfn
, "r");
4025 /* calculate the exponent */
4026 for (i
=0; i
< 4; i
++) {
4027 if (peCount
|| (publicExponent
&
4028 ((unsigned long)0xff000000L
>> (i
*8)))) {
4030 (unsigned char)((publicExponent
>> (3-i
)*8) & 0xff);
4035 pe
.data
= &pubEx
[0];
4038 while (fgets(buf
, sizeof buf
, rsareq
) != NULL
) {
4039 /* a comment or blank line */
4040 if (buf
[0] == '#' || buf
[0] == '\n') {
4041 fputs(buf
, rsaresp
);
4046 if (buf
[0] == '[') {
4048 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
4051 if (modulus
> RSA_MAX_TEST_MODULUS_BITS
) {
4052 fprintf(rsaresp
,"ERROR: modulus greater than test maximum\n");
4056 fputs(buf
, rsaresp
);
4058 if (rsaBlapiPrivKey
!= NULL
) {
4059 PORT_FreeArena(rsaBlapiPrivKey
->arena
, PR_TRUE
);
4060 rsaBlapiPrivKey
= NULL
;
4061 rsaBlapiPublicKey
= NULL
;
4064 rsaBlapiPrivKey
= RSA_NewKey(modulus
, &pe
);
4065 if (rsaBlapiPrivKey
== NULL
) {
4066 fprintf(rsaresp
, "Error unable to create RSA key\n");
4070 to_hex_str(buf
, rsaBlapiPrivKey
->modulus
.data
,
4071 rsaBlapiPrivKey
->modulus
.len
);
4072 fprintf(rsaresp
, "\nn = %s\n\n", buf
);
4073 to_hex_str(buf
, rsaBlapiPrivKey
->publicExponent
.data
,
4074 rsaBlapiPrivKey
->publicExponent
.len
);
4075 fprintf(rsaresp
, "e = %s\n", buf
);
4076 /* convert private key to public key. Memory
4077 * is freed with private key's arena */
4078 rsaBlapiPublicKey
= (RSAPublicKey
*)PORT_ArenaAlloc(
4079 rsaBlapiPrivKey
->arena
,
4080 sizeof(RSAPublicKey
));
4082 rsaBlapiPublicKey
->modulus
.len
= rsaBlapiPrivKey
->modulus
.len
;
4083 rsaBlapiPublicKey
->modulus
.data
= rsaBlapiPrivKey
->modulus
.data
;
4084 rsaBlapiPublicKey
->publicExponent
.len
=
4085 rsaBlapiPrivKey
->publicExponent
.len
;
4086 rsaBlapiPublicKey
->publicExponent
.data
=
4087 rsaBlapiPrivKey
->publicExponent
.data
;
4092 if (strncmp(buf
, "SHAAlg", 6) == 0) {
4094 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4097 /* set the SHA Algorithm */
4098 if (strncmp(&buf
[i
], "SHA1", 4) == 0) {
4099 shaAlg
= HASH_AlgSHA1
;
4100 } else if (strncmp(&buf
[i
], "SHA256", 6) == 0) {
4101 shaAlg
= HASH_AlgSHA256
;
4102 } else if (strncmp(&buf
[i
], "SHA384", 6)== 0) {
4103 shaAlg
= HASH_AlgSHA384
;
4104 } else if (strncmp(&buf
[i
], "SHA512", 6) == 0) {
4105 shaAlg
= HASH_AlgSHA512
;
4107 fprintf(rsaresp
, "ERROR: Unable to find SHAAlg type");
4110 fputs(buf
, rsaresp
);
4115 if (strncmp(buf
, "Msg", 3) == 0) {
4117 unsigned char msg
[128]; /* MAX msg 128 */
4118 unsigned int rsa_bytes_signed
;
4119 unsigned char rsa_computed_signature
[RSA_MAX_TEST_MODULUS_BYTES
];
4120 SECStatus rv
= SECFailure
;
4121 NSSLOWKEYPublicKey
* rsa_public_key
;
4122 NSSLOWKEYPrivateKey
* rsa_private_key
;
4123 NSSLOWKEYPrivateKey low_RSA_private_key
= { NULL
,
4125 NSSLOWKEYPublicKey low_RSA_public_key
= { NULL
,
4128 low_RSA_private_key
.u
.rsa
= *rsaBlapiPrivKey
;
4129 low_RSA_public_key
.u
.rsa
= *rsaBlapiPublicKey
;
4131 rsa_private_key
= &low_RSA_private_key
;
4132 rsa_public_key
= &low_RSA_public_key
;
4134 memset(sha
, 0, sizeof sha
);
4135 memset(msg
, 0, sizeof msg
);
4136 rsa_bytes_signed
= 0;
4137 memset(rsa_computed_signature
, 0, sizeof rsa_computed_signature
);
4140 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4143 for (j
=0; isxdigit(buf
[i
]) && j
< sizeof(msg
); i
+=2,j
++) {
4144 hex_to_byteval(&buf
[i
], &msg
[j
]);
4147 if (shaAlg
== HASH_AlgSHA1
) {
4148 if (SHA1_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4149 fprintf(rsaresp
, "ERROR: Unable to generate SHA1");
4152 shaLength
= SHA1_LENGTH
;
4153 shaOid
= SEC_OID_SHA1
;
4154 } else if (shaAlg
== HASH_AlgSHA256
) {
4155 if (SHA256_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4156 fprintf(rsaresp
, "ERROR: Unable to generate SHA256");
4159 shaLength
= SHA256_LENGTH
;
4160 shaOid
= SEC_OID_SHA256
;
4161 } else if (shaAlg
== HASH_AlgSHA384
) {
4162 if (SHA384_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4163 fprintf(rsaresp
, "ERROR: Unable to generate SHA384");
4166 shaLength
= SHA384_LENGTH
;
4167 shaOid
= SEC_OID_SHA384
;
4168 } else if (shaAlg
== HASH_AlgSHA512
) {
4169 if (SHA512_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4170 fprintf(rsaresp
, "ERROR: Unable to generate SHA512");
4173 shaLength
= SHA512_LENGTH
;
4174 shaOid
= SEC_OID_SHA512
;
4176 fprintf(rsaresp
, "ERROR: SHAAlg not defined.");
4180 /* Perform RSA signature with the RSA private key. */
4181 rv
= RSA_HashSign( shaOid
,
4183 rsa_computed_signature
,
4185 nsslowkey_PrivateModulusLen(rsa_private_key
),
4189 if( rv
!= SECSuccess
) {
4190 fprintf(rsaresp
, "ERROR: RSA_HashSign failed");
4194 /* Output the signature */
4195 fputs(buf
, rsaresp
);
4196 to_hex_str(buf
, rsa_computed_signature
, rsa_bytes_signed
);
4197 fprintf(rsaresp
, "S = %s\n", buf
);
4199 /* Perform RSA verification with the RSA public key. */
4200 rv
= RSA_HashCheckSign( shaOid
,
4202 rsa_computed_signature
,
4206 if( rv
!= SECSuccess
) {
4207 fprintf(rsaresp
, "ERROR: RSA_HashCheckSign failed");
4216 if (rsaBlapiPrivKey
!= NULL
) {
4217 /* frees private and public key */
4218 PORT_FreeArena(rsaBlapiPrivKey
->arena
, PR_TRUE
);
4219 rsaBlapiPrivKey
= NULL
;
4220 rsaBlapiPublicKey
= NULL
;
4225 * Perform the RSA Signature Verification Test.
4227 * reqfn is the pathname of the REQUEST file.
4229 * The output RESPONSE file is written to stdout.
4232 rsa_sigver_test(char *reqfn
)
4234 char buf
[2*RSA_MAX_TEST_MODULUS_BYTES
+7];
4235 /* buf holds one line from the input REQUEST file
4236 * or to the output RESPONSE file.
4237 * s = 2x for HEX output + 1 for \n
4239 FILE *rsareq
; /* input stream from the REQUEST file */
4240 FILE *rsaresp
; /* output stream to the RESPONSE file */
4242 unsigned char sha
[HASH_LENGTH_MAX
]; /* SHA digest */
4243 unsigned int shaLength
= 0; /* actual length of the digest */
4244 HASH_HashType shaAlg
= HASH_AlgNULL
;
4245 SECOidTag shaOid
= SEC_OID_UNKNOWN
;
4246 int modulus
= 0; /* the Modulus size */
4247 unsigned char signature
[513]; /* largest signature size + '\n' */
4248 unsigned int signatureLength
= 0; /* actual length of the signature */
4249 PRBool keyvalid
= PR_TRUE
;
4251 RSAPublicKey rsaBlapiPublicKey
; /* hold RSA public key */
4253 rsareq
= fopen(reqfn
, "r");
4255 memset(&rsaBlapiPublicKey
, 0, sizeof(RSAPublicKey
));
4257 while (fgets(buf
, sizeof buf
, rsareq
) != NULL
) {
4258 /* a comment or blank line */
4259 if (buf
[0] == '#' || buf
[0] == '\n') {
4260 fputs(buf
, rsaresp
);
4265 if (buf
[0] == '[') {
4266 unsigned int flen
; /* length in bytes of the field size */
4268 if (rsaBlapiPublicKey
.modulus
.data
) { /* n */
4269 SECITEM_ZfreeItem(&rsaBlapiPublicKey
.modulus
, PR_FALSE
);
4271 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
4275 if (modulus
> RSA_MAX_TEST_MODULUS_BITS
) {
4276 fprintf(rsaresp
,"ERROR: modulus greater than test maximum\n");
4280 fputs(buf
, rsaresp
);
4282 signatureLength
= flen
= modulus
/8;
4284 SECITEM_AllocItem(NULL
, &rsaBlapiPublicKey
.modulus
, flen
);
4285 if (rsaBlapiPublicKey
.modulus
.data
== NULL
) {
4291 /* n = ... modulus */
4292 if (buf
[0] == 'n') {
4294 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4297 keyvalid
= from_hex_str(&rsaBlapiPublicKey
.modulus
.data
[0],
4298 rsaBlapiPublicKey
.modulus
.len
,
4302 fprintf(rsaresp
, "ERROR: rsa_sigver n not valid.\n");
4305 fputs(buf
, rsaresp
);
4310 if (strncmp(buf
, "SHAAlg", 6) == 0) {
4312 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4315 /* set the SHA Algorithm */
4316 if (strncmp(&buf
[i
], "SHA1", 4) == 0) {
4317 shaAlg
= HASH_AlgSHA1
;
4318 } else if (strncmp(&buf
[i
], "SHA256", 6) == 0) {
4319 shaAlg
= HASH_AlgSHA256
;
4320 } else if (strncmp(&buf
[i
], "SHA384", 6) == 0) {
4321 shaAlg
= HASH_AlgSHA384
;
4322 } else if (strncmp(&buf
[i
], "SHA512", 6) == 0) {
4323 shaAlg
= HASH_AlgSHA512
;
4325 fprintf(rsaresp
, "ERROR: Unable to find SHAAlg type");
4328 fputs(buf
, rsaresp
);
4332 /* e = ... public Key */
4333 if (buf
[0] == 'e') {
4334 unsigned char data
[RSA_MAX_TEST_EXPONENT_BYTES
];
4337 memset(data
, 0, sizeof data
);
4339 if (rsaBlapiPublicKey
.publicExponent
.data
) { /* e */
4340 SECITEM_ZfreeItem(&rsaBlapiPublicKey
.publicExponent
, PR_FALSE
);
4344 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4347 /* skip leading zero's */
4348 while (isxdigit(buf
[i
])) {
4349 hex_to_byteval(&buf
[i
], &t
);
4355 /* get the exponent */
4356 for (j
=0; isxdigit(buf
[i
]) && j
< sizeof data
; i
+=2,j
++) {
4357 hex_to_byteval(&buf
[i
], &data
[j
]);
4360 if (j
== 0) { j
= 1; } /* to handle 1 byte length exponents */
4362 SECITEM_AllocItem(NULL
, &rsaBlapiPublicKey
.publicExponent
, j
);
4363 if (rsaBlapiPublicKey
.publicExponent
.data
== NULL
) {
4367 for (i
=0; i
< j
; i
++) {
4368 rsaBlapiPublicKey
.publicExponent
.data
[i
] = data
[i
];
4371 fputs(buf
, rsaresp
);
4376 if (strncmp(buf
, "Msg", 3) == 0) {
4377 unsigned char msg
[128]; /* MAX msg 128 */
4379 memset(sha
, 0, sizeof sha
);
4380 memset(msg
, 0, sizeof msg
);
4383 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4387 for (j
=0; isxdigit(buf
[i
]) && j
< sizeof msg
; i
+=2,j
++) {
4388 hex_to_byteval(&buf
[i
], &msg
[j
]);
4391 if (shaAlg
== HASH_AlgSHA1
) {
4392 if (SHA1_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4393 fprintf(rsaresp
, "ERROR: Unable to generate SHA1");
4396 shaLength
= SHA1_LENGTH
;
4397 shaOid
= SEC_OID_SHA1
;
4398 } else if (shaAlg
== HASH_AlgSHA256
) {
4399 if (SHA256_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4400 fprintf(rsaresp
, "ERROR: Unable to generate SHA256");
4403 shaLength
= SHA256_LENGTH
;
4404 shaOid
= SEC_OID_SHA256
;
4405 } else if (shaAlg
== HASH_AlgSHA384
) {
4406 if (SHA384_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4407 fprintf(rsaresp
, "ERROR: Unable to generate SHA384");
4410 shaLength
= SHA384_LENGTH
;
4411 shaOid
= SEC_OID_SHA384
;
4412 } else if (shaAlg
== HASH_AlgSHA512
) {
4413 if (SHA512_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4414 fprintf(rsaresp
, "ERROR: Unable to generate SHA512");
4417 shaLength
= SHA512_LENGTH
;
4418 shaOid
= SEC_OID_SHA512
;
4420 fprintf(rsaresp
, "ERROR: SHAAlg not defined.");
4424 fputs(buf
, rsaresp
);
4430 if (buf
[0] == 'S') {
4431 SECStatus rv
= SECFailure
;
4432 NSSLOWKEYPublicKey
* rsa_public_key
;
4433 NSSLOWKEYPublicKey low_RSA_public_key
= { NULL
,
4436 /* convert to a low RSA public key */
4437 low_RSA_public_key
.u
.rsa
= rsaBlapiPublicKey
;
4438 rsa_public_key
= &low_RSA_public_key
;
4440 memset(signature
, 0, sizeof(signature
));
4442 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4446 for (j
=0; isxdigit(buf
[i
]) && j
< sizeof signature
; i
+=2,j
++) {
4447 hex_to_byteval(&buf
[i
], &signature
[j
]);
4450 signatureLength
= j
;
4451 fputs(buf
, rsaresp
);
4453 /* Perform RSA verification with the RSA public key. */
4454 rv
= RSA_HashCheckSign( shaOid
,
4460 if( rv
== SECSuccess
) {
4461 fputs("Result = P\n", rsaresp
);
4463 fputs("Result = F\n", rsaresp
);
4470 if (rsaBlapiPublicKey
.modulus
.data
) { /* n */
4471 SECITEM_ZfreeItem(&rsaBlapiPublicKey
.modulus
, PR_FALSE
);
4473 if (rsaBlapiPublicKey
.publicExponent
.data
) { /* e */
4474 SECITEM_ZfreeItem(&rsaBlapiPublicKey
.publicExponent
, PR_FALSE
);
4478 int main(int argc
, char **argv
)
4480 if (argc
< 2) exit (-1);
4481 NSS_NoDB_Init(NULL
);
4485 if (strcmp(argv
[1], "tdea") == 0) {
4486 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
4487 if (strcmp(argv
[2], "kat") == 0) {
4488 /* Known Answer Test (KAT) */
4489 tdea_kat_mmt(argv
[4]);
4490 } else if (strcmp(argv
[2], "mmt") == 0) {
4491 /* Multi-block Message Test (MMT) */
4492 tdea_kat_mmt(argv
[4]);
4493 } else if (strcmp(argv
[2], "mct") == 0) {
4494 /* Monte Carlo Test (MCT) */
4495 if (strcmp(argv
[3], "ecb") == 0) {
4497 tdea_mct(NSS_DES_EDE3
, argv
[4]);
4498 } else if (strcmp(argv
[3], "cbc") == 0) {
4500 tdea_mct(NSS_DES_EDE3_CBC
, argv
[4]);
4506 } else if (strcmp(argv
[1], "aes") == 0) {
4507 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
4508 if ( strcmp(argv
[2], "kat") == 0) {
4509 /* Known Answer Test (KAT) */
4510 aes_kat_mmt(argv
[4]);
4511 } else if (strcmp(argv
[2], "mmt") == 0) {
4512 /* Multi-block Message Test (MMT) */
4513 aes_kat_mmt(argv
[4]);
4514 } else if (strcmp(argv
[2], "mct") == 0) {
4515 /* Monte Carlo Test (MCT) */
4516 if ( strcmp(argv
[3], "ecb") == 0) {
4518 aes_ecb_mct(argv
[4]);
4519 } else if (strcmp(argv
[3], "cbc") == 0) {
4521 aes_cbc_mct(argv
[4]);
4527 } else if (strcmp(argv
[1], "sha") == 0) {
4532 } else if (strcmp(argv
[1], "rsa") == 0) {
4533 /* argv[2]=siggen|sigver */
4534 /* argv[3]=<test name>.req */
4535 if (strcmp(argv
[2], "siggen") == 0) {
4536 /* Signature Generation Test */
4537 rsa_siggen_test(argv
[3]);
4538 } else if (strcmp(argv
[2], "sigver") == 0) {
4539 /* Signature Verification Test */
4540 rsa_sigver_test(argv
[3]);
4545 } else if (strcmp(argv
[1], "hmac") == 0) {
4550 } else if (strcmp(argv
[1], "dsa") == 0) {
4551 /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */
4552 /* argv[3]=<test name>.req */
4553 if (strcmp(argv
[2], "keypair") == 0) {
4554 /* Key Pair Generation Test */
4555 dsa_keypair_test(argv
[3]);
4556 } else if (strcmp(argv
[2], "pqggen") == 0) {
4557 /* Domain Parameter Generation Test */
4558 dsa_pqggen_test(argv
[3]);
4559 } else if (strcmp(argv
[2], "pqgver") == 0) {
4560 /* Domain Parameter Validation Test */
4561 dsa_pqgver_test(argv
[3]);
4562 } else if (strcmp(argv
[2], "siggen") == 0) {
4563 /* Signature Generation Test */
4564 dsa_siggen_test(argv
[3]);
4565 } else if (strcmp(argv
[2], "sigver") == 0) {
4566 /* Signature Verification Test */
4567 dsa_sigver_test(argv
[3]);
4569 #ifdef NSS_ENABLE_ECC
4573 } else if (strcmp(argv
[1], "ecdsa") == 0) {
4574 /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */
4575 if ( strcmp(argv
[2], "keypair") == 0) {
4576 /* Key Pair Generation Test */
4577 ecdsa_keypair_test(argv
[3]);
4578 } else if (strcmp(argv
[2], "pkv") == 0) {
4579 /* Public Key Validation Test */
4580 ecdsa_pkv_test(argv
[3]);
4581 } else if (strcmp(argv
[2], "siggen") == 0) {
4582 /* Signature Generation Test */
4583 ecdsa_siggen_test(argv
[3]);
4584 } else if (strcmp(argv
[2], "sigver") == 0) {
4585 /* Signature Verification Test */
4586 ecdsa_sigver_test(argv
[3]);
4588 #endif /* NSS_ENABLE_ECC */
4592 } else if (strcmp(argv
[1], "rng") == 0) {
4593 /* argv[2]=vst|mct argv[3]=<test name>.req */
4594 if ( strcmp(argv
[2], "vst") == 0) {
4595 /* Variable Seed Test */
4597 } else if (strcmp(argv
[2], "mct") == 0) {
4598 /* Monte Carlo Test */