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 ***** */
54 #include "../../lib/freebl/mpi/mpi.h"
59 EC_DecodeParams(const SECItem
*encodedParams
, ECParams
**ecparams
);
61 EC_CopyParams(PRArenaPool
*arena
, ECParams
*dstParams
,
62 const ECParams
*srcParams
);
67 #define BYTE unsigned char
68 #define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001
69 #define RSA_MAX_TEST_MODULUS_BITS 4096
70 #define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS/8
71 #define RSA_MAX_TEST_EXPONENT_BYTES 8
72 #define PQG_TEST_SEED_BYTES 20
75 hex_to_byteval(const char *c2
, unsigned char *byteval
)
81 if (c2
[i
] >= '0' && c2
[i
] <= '9') {
83 *byteval
|= offset
<< 4*(1-i
);
84 } else if (c2
[i
] >= 'a' && c2
[i
] <= 'f') {
86 *byteval
|= (offset
+ 10) << 4*(1-i
);
87 } else if (c2
[i
] >= 'A' && c2
[i
] <= 'F') {
89 *byteval
|= (offset
+ 10) << 4*(1-i
);
98 byteval_to_hex(unsigned char byteval
, char *c2
, char a
)
101 unsigned char offset
;
102 for (i
=0; i
<2; i
++) {
103 offset
= (byteval
>> 4*(1-i
)) & 0x0f;
105 c2
[i
] = '0' + offset
;
107 c2
[i
] = a
+ offset
- 10;
114 to_hex_str(char *str
, const unsigned char *buf
, unsigned int len
)
117 for (i
=0; i
<len
; i
++) {
118 byteval_to_hex(buf
[i
], &str
[2*i
], 'a');
124 to_hex_str_cap(char *str
, const unsigned char *buf
, unsigned int len
)
127 for (i
=0; i
<len
; i
++) {
128 byteval_to_hex(buf
[i
], &str
[2*i
], 'A');
134 * Convert a string of hex digits (str) to an array (buf) of len bytes.
135 * Return PR_TRUE if the hex string can fit in the byte array. Return
136 * PR_FALSE if the hex string is empty or is too long.
139 from_hex_str(unsigned char *buf
, unsigned int len
, const char *str
)
141 unsigned int nxdigit
; /* number of hex digits in str */
142 unsigned int i
; /* index into buf */
143 unsigned int j
; /* index into str */
145 /* count the hex digits */
147 for (nxdigit
= 0; isxdigit(str
[nxdigit
]); nxdigit
++) {
153 if (nxdigit
> 2*len
) {
155 * The input hex string is too long, but we allow it if the
156 * extra digits are leading 0's.
158 for (j
= 0; j
< nxdigit
-2*len
; j
++) {
163 /* skip leading 0's */
164 str
+= nxdigit
-2*len
;
167 for (i
=0, j
=0; i
< len
; i
++) {
168 if (2*i
< 2*len
-nxdigit
) {
169 /* Handle a short input as if we padded it with leading 0's. */
170 if (2*i
+1 < 2*len
-nxdigit
) {
176 hex_to_byteval(tmp
, &buf
[i
]);
180 hex_to_byteval(&str
[j
], &buf
[i
]);
190 const unsigned char *key
,
191 const unsigned char *iv
,
192 unsigned char *output
, unsigned int *outputlen
, unsigned int maxoutputlen
,
193 const unsigned char *input
, unsigned int inputlen
)
195 SECStatus rv
= SECFailure
;
197 unsigned char doublecheck
[8*20]; /* 1 to 20 blocks */
198 unsigned int doublechecklen
= 0;
200 cx
= DES_CreateContext(key
, iv
, mode
, PR_TRUE
);
204 rv
= DES_Encrypt(cx
, output
, outputlen
, maxoutputlen
, input
, inputlen
);
205 if (rv
!= SECSuccess
) {
208 if (*outputlen
!= inputlen
) {
211 DES_DestroyContext(cx
, PR_TRUE
);
215 * Doublecheck our result by decrypting the ciphertext and
216 * compare the output with the input plaintext.
218 cx
= DES_CreateContext(key
, iv
, mode
, PR_FALSE
);
222 rv
= DES_Decrypt(cx
, doublecheck
, &doublechecklen
, sizeof doublecheck
,
224 if (rv
!= SECSuccess
) {
227 if (doublechecklen
!= *outputlen
) {
230 DES_DestroyContext(cx
, PR_TRUE
);
232 if (memcmp(doublecheck
, input
, inputlen
) != 0) {
239 DES_DestroyContext(cx
, PR_TRUE
);
247 const unsigned char *key
,
248 const unsigned char *iv
,
249 unsigned char *output
, unsigned int *outputlen
, unsigned int maxoutputlen
,
250 const unsigned char *input
, unsigned int inputlen
)
252 SECStatus rv
= SECFailure
;
254 unsigned char doublecheck
[8*20]; /* 1 to 20 blocks */
255 unsigned int doublechecklen
= 0;
257 cx
= DES_CreateContext(key
, iv
, mode
, PR_FALSE
);
261 rv
= DES_Decrypt(cx
, output
, outputlen
, maxoutputlen
,
263 if (rv
!= SECSuccess
) {
266 if (*outputlen
!= inputlen
) {
269 DES_DestroyContext(cx
, PR_TRUE
);
273 * Doublecheck our result by encrypting the plaintext and
274 * compare the output with the input ciphertext.
276 cx
= DES_CreateContext(key
, iv
, mode
, PR_TRUE
);
280 rv
= DES_Encrypt(cx
, doublecheck
, &doublechecklen
, sizeof doublecheck
,
282 if (rv
!= SECSuccess
) {
285 if (doublechecklen
!= *outputlen
) {
288 DES_DestroyContext(cx
, PR_TRUE
);
290 if (memcmp(doublecheck
, input
, inputlen
) != 0) {
297 DES_DestroyContext(cx
, PR_TRUE
);
303 * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
304 * Test (MMT) in ECB or CBC mode. The KAT (there are five types)
305 * and MMT have the same structure: given the key and IV (CBC mode
306 * only), encrypt the given plaintext or decrypt the given ciphertext.
307 * So we can handle them the same way.
309 * reqfn is the pathname of the REQUEST file.
311 * The output RESPONSE file is written to stdout.
314 tdea_kat_mmt(char *reqfn
)
316 char buf
[180]; /* holds one line from the input REQUEST file.
317 * needs to be large enough to hold the longest
318 * line "CIPHERTEXT = <180 hex digits>\n".
320 FILE *req
; /* input stream from the REQUEST file */
321 FILE *resp
; /* output stream to the RESPONSE file */
323 int mode
; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
324 int crypt
= DECRYPT
; /* 1 means encrypt, 0 means decrypt */
325 unsigned char key
[24]; /* TDEA 3 key bundle */
326 unsigned int numKeys
= 0;
327 unsigned char iv
[8]; /* for all modes except ECB */
328 unsigned char plaintext
[8*20]; /* 1 to 20 blocks */
329 unsigned int plaintextlen
;
330 unsigned char ciphertext
[8*20]; /* 1 to 20 blocks */
331 unsigned int ciphertextlen
;
334 req
= fopen(reqfn
, "r");
336 while (fgets(buf
, sizeof buf
, req
) != NULL
) {
337 /* a comment or blank line */
338 if (buf
[0] == '#' || buf
[0] == '\n') {
342 /* [ENCRYPT] or [DECRYPT] */
344 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
353 if (strncmp(&buf
[0], "NumKeys", 7) == 0) {
355 while (isspace(buf
[i
]) || buf
[i
] == '=') {
362 /* "COUNT = x" begins a new data set */
363 if (strncmp(buf
, "COUNT", 5) == 0) {
364 /* mode defaults to ECB, if dataset has IV mode will be set CBC */
366 /* zeroize the variables for the test with this data set */
367 memset(key
, 0, sizeof key
);
368 memset(iv
, 0, sizeof iv
);
369 memset(plaintext
, 0, sizeof plaintext
);
371 memset(ciphertext
, 0, sizeof ciphertext
);
377 if (strncmp(buf
, "KEYs", 4) == 0) {
379 while (isspace(buf
[i
]) || buf
[i
] == '=') {
382 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
383 hex_to_byteval(&buf
[i
], &key
[j
]);
392 if (strncmp(buf
, "KEY1", 4) == 0) {
394 while (isspace(buf
[i
]) || buf
[i
] == '=') {
397 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
398 hex_to_byteval(&buf
[i
], &key
[j
]);
404 if (strncmp(buf
, "KEY2", 4) == 0) {
406 while (isspace(buf
[i
]) || buf
[i
] == '=') {
409 for (j
=8; isxdigit(buf
[i
]); i
+=2,j
++) {
410 hex_to_byteval(&buf
[i
], &key
[j
]);
416 if (strncmp(buf
, "KEY3", 4) == 0) {
418 while (isspace(buf
[i
]) || buf
[i
] == '=') {
421 for (j
=16; isxdigit(buf
[i
]); i
+=2,j
++) {
422 hex_to_byteval(&buf
[i
], &key
[j
]);
430 if (strncmp(buf
, "IV", 2) == 0) {
431 mode
= NSS_DES_EDE3_CBC
;
433 while (isspace(buf
[i
]) || buf
[i
] == '=') {
436 for (j
=0; j
<sizeof iv
; i
+=2,j
++) {
437 hex_to_byteval(&buf
[i
], &iv
[j
]);
443 /* PLAINTEXT = ... */
444 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
446 if (crypt
!= ENCRYPT
) {
450 while (isspace(buf
[i
]) || buf
[i
] == '=') {
453 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
454 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
457 rv
= tdea_encrypt_buf(mode
, key
,
458 (mode
== NSS_DES_EDE3
) ? NULL
: iv
,
459 ciphertext
, &ciphertextlen
, sizeof ciphertext
,
460 plaintext
, plaintextlen
);
461 if (rv
!= SECSuccess
) {
466 fputs("CIPHERTEXT = ", resp
);
467 to_hex_str(buf
, ciphertext
, ciphertextlen
);
472 /* CIPHERTEXT = ... */
473 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
475 if (crypt
!= DECRYPT
) {
480 while (isspace(buf
[i
]) || buf
[i
] == '=') {
483 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
484 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
488 rv
= tdea_decrypt_buf(mode
, key
,
489 (mode
== NSS_DES_EDE3
) ? NULL
: iv
,
490 plaintext
, &plaintextlen
, sizeof plaintext
,
491 ciphertext
, ciphertextlen
);
492 if (rv
!= SECSuccess
) {
497 fputs("PLAINTEXT = ", resp
);
498 to_hex_str(buf
, plaintext
, plaintextlen
);
510 * Set the parity bit for the given byte
512 BYTE
odd_parity( BYTE in
)
518 return (BYTE
)(out
^ !(in
& 1));
522 * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j]
523 * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
526 tdea_mct_next_keys(unsigned char *key
,
527 const unsigned char *text_2
, const unsigned char *text_1
,
528 const unsigned char *text
, unsigned int numKeys
)
532 /* key1[i+1] = key1[i] xor PT/CT[j] */
533 for (k
=0; k
<8; k
++) {
537 if (numKeys
== 2 || numKeys
== 3) {
538 /* key2 independent */
539 for (k
=8; k
<16; k
++) {
540 /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
541 key
[k
] ^= text_1
[k
-8];
545 for (k
=8; k
<16; k
++) {
546 /* key2[i+1] = KEY2[i] xor PT/CT[j] */
551 if (numKeys
== 1 || numKeys
== 2) {
553 for (k
=16; k
<24; k
++) {
554 /* key3[i+1] = KEY3[i] xor PT/CT[j] */
558 /* key3 independent */
559 for (k
=16; k
<24; k
++) {
560 /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
561 key
[k
] ^= text_2
[k
-16];
564 /* set the parity bits */
565 for (k
=0; k
<24; k
++) {
566 key
[k
] = odd_parity(key
[k
]);
571 * Perform the Monte Carlo Test
573 * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
574 * crypt = ENCRYPT || DECRYPT
575 * inputtext = plaintext or Cyphertext depending on the value of crypt
576 * inputlength is expected to be size 8 bytes
577 * iv = needs to be set for NSS_DES_EDE3_CBC mode
578 * resp = is the output response file.
581 tdea_mct_test(int mode
, unsigned char* key
, unsigned int numKeys
,
582 unsigned int crypt
, unsigned char* inputtext
,
583 unsigned int inputlength
, unsigned char* iv
, FILE *resp
) {
586 unsigned char outputtext_1
[8]; /* PT/CT[j-1] */
587 unsigned char outputtext_2
[8]; /* PT/CT[j-2] */
588 char buf
[80]; /* holds one line from the input REQUEST file. */
589 unsigned int outputlen
;
590 unsigned char outputtext
[8];
595 if (mode
== NSS_DES_EDE3
&& iv
!= NULL
) {
596 printf("IV must be NULL for NSS_DES_EDE3 mode");
598 } else if (mode
== NSS_DES_EDE3_CBC
&& iv
== NULL
) {
599 printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
604 for (i
=0; i
<400; i
++) {
605 /* if i == 0 CV[0] = IV not necessary */
606 /* record the count and key values and plainText */
607 sprintf(buf
, "COUNT = %d\n", i
);
610 fputs("KEY1 = ", resp
);
611 to_hex_str(buf
, key
, 8);
615 fputs("KEY2 = ", resp
);
616 to_hex_str(buf
, &key
[8], 8);
620 fputs("KEY3 = ", resp
);
621 to_hex_str(buf
, &key
[16], 8);
624 if (mode
== NSS_DES_EDE3_CBC
) {
626 fputs("IV = ", resp
);
627 to_hex_str(buf
, iv
, 8);
631 if (crypt
== ENCRYPT
) {
633 fputs("PLAINTEXT = ", resp
);
636 fputs("CIPHERTEXT = ", resp
);
639 to_hex_str(buf
, inputtext
, inputlength
);
643 /* loop 10,000 times */
644 for (j
=0; j
<10000; j
++) {
647 if (crypt
== ENCRYPT
) {
648 /* inputtext == ciphertext outputtext == plaintext*/
649 rv
= tdea_encrypt_buf(mode
, key
,
650 (mode
== NSS_DES_EDE3
) ? NULL
: iv
,
651 outputtext
, &outputlen
, 8,
654 /* inputtext == plaintext outputtext == ciphertext */
655 rv
= tdea_decrypt_buf(mode
, key
,
656 (mode
== NSS_DES_EDE3
) ? NULL
: iv
,
657 outputtext
, &outputlen
, 8,
661 if (rv
!= SECSuccess
) {
664 if (outputlen
!= inputlength
) {
668 if (mode
== NSS_DES_EDE3_CBC
) {
669 if (crypt
== ENCRYPT
) {
672 memcpy(inputtext
, iv
, 8);
674 /* p[j+1] = C[j-1] */
675 memcpy(inputtext
, outputtext_1
, 8);
678 memcpy(iv
, outputtext
, 8);
681 memcpy(outputtext_1
, outputtext
, 8);
683 } else { /* DECRYPT */
685 memcpy(iv
, inputtext
, 8);
687 memcpy(inputtext
, outputtext
, 8);
690 /* ECB mode PT/CT[j+1] = CT/PT[j] */
691 memcpy(inputtext
, outputtext
, 8);
694 /* Save PT/CT[j-2] and PT/CT[j-1] */
695 if (j
==9997) memcpy(outputtext_2
, outputtext
, 8);
696 if (j
==9998) memcpy(outputtext_1
, outputtext
, 8);
697 /* done at the end of the for(j) loop */
701 if (crypt
== ENCRYPT
) {
703 fputs("CIPHERTEXT = ", resp
);
706 fputs("PLAINTEXT = ", resp
);
708 to_hex_str(buf
, outputtext
, 8);
712 /* Key[i+1] = Key[i] xor ... outputtext_2 == PT/CT[j-2]
713 * outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j]
715 tdea_mct_next_keys(key
, outputtext_2
,
716 outputtext_1
, outputtext
, numKeys
);
718 if (mode
== NSS_DES_EDE3_CBC
) {
719 /* taken care of in the j=9999 iteration */
720 if (crypt
== ENCRYPT
) {
724 /* taken care of in the j=9999 iteration */
729 /* ECB PT/CT[i] = PT/CT[j] */
730 memcpy(inputtext
, outputtext
, 8);
732 /* done at the end of the for(i) loop */
741 * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
742 * by gathering the input from the request file, and then
743 * calling tdea_mct_test.
745 * reqfn is the pathname of the input REQUEST file.
747 * The output RESPONSE file is written to stdout.
750 tdea_mct(int mode
, char *reqfn
)
753 char buf
[80]; /* holds one line from the input REQUEST file. */
754 FILE *req
; /* input stream from the REQUEST file */
755 FILE *resp
; /* output stream to the RESPONSE file */
756 unsigned int crypt
= 0; /* 1 means encrypt, 0 means decrypt */
757 unsigned char key
[24]; /* TDEA 3 key bundle */
758 unsigned int numKeys
= 0;
759 unsigned char plaintext
[8]; /* PT[j] */
760 unsigned char ciphertext
[8]; /* CT[j] */
763 /* zeroize the variables for the test with this data set */
764 memset(key
, 0, sizeof key
);
765 memset(plaintext
, 0, sizeof plaintext
);
766 memset(ciphertext
, 0, sizeof ciphertext
);
767 memset(iv
, 0, sizeof iv
);
769 req
= fopen(reqfn
, "r");
771 while (fgets(buf
, sizeof buf
, req
) != NULL
) {
772 /* a comment or blank line */
773 if (buf
[0] == '#' || buf
[0] == '\n') {
777 /* [ENCRYPT] or [DECRYPT] */
779 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
788 if (strncmp(&buf
[0], "NumKeys", 7) == 0) {
790 while (isspace(buf
[i
]) || buf
[i
] == '=') {
793 numKeys
= atoi(&buf
[i
]);
797 if (strncmp(buf
, "KEY1", 4) == 0) {
799 while (isspace(buf
[i
]) || buf
[i
] == '=') {
802 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
803 hex_to_byteval(&buf
[i
], &key
[j
]);
808 if (strncmp(buf
, "KEY2", 4) == 0) {
810 while (isspace(buf
[i
]) || buf
[i
] == '=') {
813 for (j
=8; isxdigit(buf
[i
]); i
+=2,j
++) {
814 hex_to_byteval(&buf
[i
], &key
[j
]);
819 if (strncmp(buf
, "KEY3", 4) == 0) {
821 while (isspace(buf
[i
]) || buf
[i
] == '=') {
824 for (j
=16; isxdigit(buf
[i
]); i
+=2,j
++) {
825 hex_to_byteval(&buf
[i
], &key
[j
]);
831 if (strncmp(buf
, "IV", 2) == 0) {
833 while (isspace(buf
[i
]) || buf
[i
] == '=') {
836 for (j
=0; j
<sizeof iv
; i
+=2,j
++) {
837 hex_to_byteval(&buf
[i
], &iv
[j
]);
842 /* PLAINTEXT = ... */
843 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
846 if (crypt
!= ENCRYPT
) {
851 while (isspace(buf
[i
]) || buf
[i
] == '=') {
854 for (j
=0; j
<sizeof plaintext
; i
+=2,j
++) {
855 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
858 /* do the Monte Carlo test */
859 if (mode
==NSS_DES_EDE3
) {
860 tdea_mct_test(NSS_DES_EDE3
, key
, numKeys
, crypt
, plaintext
, sizeof plaintext
, NULL
, resp
);
862 tdea_mct_test(NSS_DES_EDE3_CBC
, key
, numKeys
, crypt
, plaintext
, sizeof plaintext
, iv
, resp
);
866 /* CIPHERTEXT = ... */
867 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
869 if (crypt
!= DECRYPT
) {
874 while (isspace(buf
[i
]) || buf
[i
] == '=') {
877 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
878 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
881 /* do the Monte Carlo test */
882 if (mode
==NSS_DES_EDE3
) {
883 tdea_mct_test(NSS_DES_EDE3
, key
, numKeys
, crypt
, ciphertext
, sizeof ciphertext
, NULL
, resp
);
885 tdea_mct_test(NSS_DES_EDE3_CBC
, key
, numKeys
, crypt
, ciphertext
, sizeof ciphertext
, iv
, resp
);
899 const unsigned char *key
, unsigned int keysize
,
900 const unsigned char *iv
,
901 unsigned char *output
, unsigned int *outputlen
, unsigned int maxoutputlen
,
902 const unsigned char *input
, unsigned int inputlen
)
904 SECStatus rv
= SECFailure
;
906 unsigned char doublecheck
[10*16]; /* 1 to 10 blocks */
907 unsigned int doublechecklen
= 0;
909 cx
= AES_CreateContext(key
, iv
, mode
, PR_TRUE
, keysize
, 16);
913 rv
= AES_Encrypt(cx
, output
, outputlen
, maxoutputlen
, input
, inputlen
);
914 if (rv
!= SECSuccess
) {
917 if (*outputlen
!= inputlen
) {
920 AES_DestroyContext(cx
, PR_TRUE
);
924 * Doublecheck our result by decrypting the ciphertext and
925 * compare the output with the input plaintext.
927 cx
= AES_CreateContext(key
, iv
, mode
, PR_FALSE
, keysize
, 16);
931 rv
= AES_Decrypt(cx
, doublecheck
, &doublechecklen
, sizeof doublecheck
,
933 if (rv
!= SECSuccess
) {
936 if (doublechecklen
!= *outputlen
) {
939 AES_DestroyContext(cx
, PR_TRUE
);
941 if (memcmp(doublecheck
, input
, inputlen
) != 0) {
948 AES_DestroyContext(cx
, PR_TRUE
);
956 const unsigned char *key
, unsigned int keysize
,
957 const unsigned char *iv
,
958 unsigned char *output
, unsigned int *outputlen
, unsigned int maxoutputlen
,
959 const unsigned char *input
, unsigned int inputlen
)
961 SECStatus rv
= SECFailure
;
963 unsigned char doublecheck
[10*16]; /* 1 to 10 blocks */
964 unsigned int doublechecklen
= 0;
966 cx
= AES_CreateContext(key
, iv
, mode
, PR_FALSE
, keysize
, 16);
970 rv
= AES_Decrypt(cx
, output
, outputlen
, maxoutputlen
,
972 if (rv
!= SECSuccess
) {
975 if (*outputlen
!= inputlen
) {
978 AES_DestroyContext(cx
, PR_TRUE
);
982 * Doublecheck our result by encrypting the plaintext and
983 * compare the output with the input ciphertext.
985 cx
= AES_CreateContext(key
, iv
, mode
, PR_TRUE
, keysize
, 16);
989 rv
= AES_Encrypt(cx
, doublecheck
, &doublechecklen
, sizeof doublecheck
,
991 if (rv
!= SECSuccess
) {
994 if (doublechecklen
!= *outputlen
) {
997 AES_DestroyContext(cx
, PR_TRUE
);
999 if (memcmp(doublecheck
, input
, inputlen
) != 0) {
1006 AES_DestroyContext(cx
, PR_TRUE
);
1012 * Perform the AES Known Answer Test (KAT) or Multi-block Message
1013 * Test (MMT) in ECB or CBC mode. The KAT (there are four types)
1014 * and MMT have the same structure: given the key and IV (CBC mode
1015 * only), encrypt the given plaintext or decrypt the given ciphertext.
1016 * So we can handle them the same way.
1018 * reqfn is the pathname of the REQUEST file.
1020 * The output RESPONSE file is written to stdout.
1023 aes_kat_mmt(char *reqfn
)
1025 char buf
[512]; /* holds one line from the input REQUEST file.
1026 * needs to be large enough to hold the longest
1027 * line "CIPHERTEXT = <320 hex digits>\n".
1029 FILE *aesreq
; /* input stream from the REQUEST file */
1030 FILE *aesresp
; /* output stream to the RESPONSE file */
1032 int mode
; /* NSS_AES (ECB) or NSS_AES_CBC */
1033 int encrypt
= 0; /* 1 means encrypt, 0 means decrypt */
1034 unsigned char key
[32]; /* 128, 192, or 256 bits */
1035 unsigned int keysize
;
1036 unsigned char iv
[16]; /* for all modes except ECB */
1037 unsigned char plaintext
[10*16]; /* 1 to 10 blocks */
1038 unsigned int plaintextlen
;
1039 unsigned char ciphertext
[10*16]; /* 1 to 10 blocks */
1040 unsigned int ciphertextlen
;
1043 aesreq
= fopen(reqfn
, "r");
1045 while (fgets(buf
, sizeof buf
, aesreq
) != NULL
) {
1046 /* a comment or blank line */
1047 if (buf
[0] == '#' || buf
[0] == '\n') {
1048 fputs(buf
, aesresp
);
1051 /* [ENCRYPT] or [DECRYPT] */
1052 if (buf
[0] == '[') {
1053 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
1058 fputs(buf
, aesresp
);
1061 /* "COUNT = x" begins a new data set */
1062 if (strncmp(buf
, "COUNT", 5) == 0) {
1064 /* zeroize the variables for the test with this data set */
1065 memset(key
, 0, sizeof key
);
1067 memset(iv
, 0, sizeof iv
);
1068 memset(plaintext
, 0, sizeof plaintext
);
1070 memset(ciphertext
, 0, sizeof ciphertext
);
1072 fputs(buf
, aesresp
);
1076 if (strncmp(buf
, "KEY", 3) == 0) {
1078 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1081 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1082 hex_to_byteval(&buf
[i
], &key
[j
]);
1085 fputs(buf
, aesresp
);
1089 if (strncmp(buf
, "IV", 2) == 0) {
1092 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1095 for (j
=0; j
<sizeof iv
; i
+=2,j
++) {
1096 hex_to_byteval(&buf
[i
], &iv
[j
]);
1098 fputs(buf
, aesresp
);
1101 /* PLAINTEXT = ... */
1102 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
1109 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1112 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1113 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
1117 rv
= aes_encrypt_buf(mode
, key
, keysize
,
1118 (mode
== NSS_AES
) ? NULL
: iv
,
1119 ciphertext
, &ciphertextlen
, sizeof ciphertext
,
1120 plaintext
, plaintextlen
);
1121 if (rv
!= SECSuccess
) {
1125 fputs(buf
, aesresp
);
1126 fputs("CIPHERTEXT = ", aesresp
);
1127 to_hex_str(buf
, ciphertext
, ciphertextlen
);
1128 fputs(buf
, aesresp
);
1129 fputc('\n', aesresp
);
1132 /* CIPHERTEXT = ... */
1133 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
1140 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1143 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1144 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
1148 rv
= aes_decrypt_buf(mode
, key
, keysize
,
1149 (mode
== NSS_AES
) ? NULL
: iv
,
1150 plaintext
, &plaintextlen
, sizeof plaintext
,
1151 ciphertext
, ciphertextlen
);
1152 if (rv
!= SECSuccess
) {
1156 fputs(buf
, aesresp
);
1157 fputs("PLAINTEXT = ", aesresp
);
1158 to_hex_str(buf
, plaintext
, plaintextlen
);
1159 fputs(buf
, aesresp
);
1160 fputc('\n', aesresp
);
1169 * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
1170 * Test (MCT) in ECB and CBC modes.
1173 aes_mct_next_key(unsigned char *key
, unsigned int keysize
,
1174 const unsigned char *ciphertext_1
, const unsigned char *ciphertext
)
1179 case 16: /* 128-bit key */
1180 /* Key[i+1] = Key[i] xor CT[j] */
1181 for (k
=0; k
<16; k
++) {
1182 key
[k
] ^= ciphertext
[k
];
1185 case 24: /* 192-bit key */
1187 * Key[i+1] = Key[i] xor (last 64-bits of
1190 for (k
=0; k
<8; k
++) {
1191 key
[k
] ^= ciphertext_1
[k
+8];
1193 for (k
=8; k
<24; k
++) {
1194 key
[k
] ^= ciphertext
[k
-8];
1197 case 32: /* 256-bit key */
1198 /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
1199 for (k
=0; k
<16; k
++) {
1200 key
[k
] ^= ciphertext_1
[k
];
1202 for (k
=16; k
<32; k
++) {
1203 key
[k
] ^= ciphertext
[k
-16];
1210 * Perform the AES Monte Carlo Test (MCT) in ECB mode. MCT exercises
1211 * our AES code in streaming mode because the plaintext or ciphertext
1212 * is generated block by block as we go, so we can't collect all the
1213 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1216 * reqfn is the pathname of the input REQUEST file.
1218 * The output RESPONSE file is written to stdout.
1221 aes_ecb_mct(char *reqfn
)
1223 char buf
[80]; /* holds one line from the input REQUEST file.
1224 * needs to be large enough to hold the longest
1225 * line "KEY = <64 hex digits>\n".
1227 FILE *aesreq
; /* input stream from the REQUEST file */
1228 FILE *aesresp
; /* output stream to the RESPONSE file */
1230 int encrypt
= 0; /* 1 means encrypt, 0 means decrypt */
1231 unsigned char key
[32]; /* 128, 192, or 256 bits */
1232 unsigned int keysize
;
1233 unsigned char plaintext
[16]; /* PT[j] */
1234 unsigned char plaintext_1
[16]; /* PT[j-1] */
1235 unsigned char ciphertext
[16]; /* CT[j] */
1236 unsigned char ciphertext_1
[16]; /* CT[j-1] */
1237 unsigned char doublecheck
[16];
1238 unsigned int outputlen
;
1239 AESContext
*cx
= NULL
; /* the operation being tested */
1240 AESContext
*cx2
= NULL
; /* the inverse operation done in parallel
1241 * to doublecheck our result.
1245 aesreq
= fopen(reqfn
, "r");
1247 while (fgets(buf
, sizeof buf
, aesreq
) != NULL
) {
1248 /* a comment or blank line */
1249 if (buf
[0] == '#' || buf
[0] == '\n') {
1250 fputs(buf
, aesresp
);
1253 /* [ENCRYPT] or [DECRYPT] */
1254 if (buf
[0] == '[') {
1255 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
1260 fputs(buf
, aesresp
);
1263 /* "COUNT = x" begins a new data set */
1264 if (strncmp(buf
, "COUNT", 5) == 0) {
1265 /* zeroize the variables for the test with this data set */
1266 memset(key
, 0, sizeof key
);
1268 memset(plaintext
, 0, sizeof plaintext
);
1269 memset(ciphertext
, 0, sizeof ciphertext
);
1273 if (strncmp(buf
, "KEY", 3) == 0) {
1276 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1279 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1280 hex_to_byteval(&buf
[i
], &key
[j
]);
1285 /* PLAINTEXT = ... */
1286 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
1293 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1296 for (j
=0; j
<sizeof plaintext
; i
+=2,j
++) {
1297 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
1300 for (i
=0; i
<100; i
++) {
1301 sprintf(buf
, "COUNT = %d\n", i
);
1302 fputs(buf
, aesresp
);
1304 fputs("KEY = ", aesresp
);
1305 to_hex_str(buf
, key
, keysize
);
1306 fputs(buf
, aesresp
);
1307 fputc('\n', aesresp
);
1309 fputs("PLAINTEXT = ", aesresp
);
1310 to_hex_str(buf
, plaintext
, sizeof plaintext
);
1311 fputs(buf
, aesresp
);
1312 fputc('\n', aesresp
);
1314 cx
= AES_CreateContext(key
, NULL
, NSS_AES
,
1315 PR_TRUE
, keysize
, 16);
1320 * doublecheck our result by decrypting the result
1321 * and comparing the output with the plaintext.
1323 cx2
= AES_CreateContext(key
, NULL
, NSS_AES
,
1324 PR_FALSE
, keysize
, 16);
1328 for (j
=0; j
<1000; j
++) {
1330 memcpy(ciphertext_1
, ciphertext
, sizeof ciphertext
);
1332 /* CT[j] = AES(Key[i], PT[j]) */
1334 rv
= AES_Encrypt(cx
,
1335 ciphertext
, &outputlen
, sizeof ciphertext
,
1336 plaintext
, sizeof plaintext
);
1337 if (rv
!= SECSuccess
) {
1340 if (outputlen
!= sizeof plaintext
) {
1344 /* doublecheck our result */
1346 rv
= AES_Decrypt(cx2
,
1347 doublecheck
, &outputlen
, sizeof doublecheck
,
1348 ciphertext
, sizeof ciphertext
);
1349 if (rv
!= SECSuccess
) {
1352 if (outputlen
!= sizeof ciphertext
) {
1355 if (memcmp(doublecheck
, plaintext
, sizeof plaintext
)) {
1359 /* PT[j+1] = CT[j] */
1360 memcpy(plaintext
, ciphertext
, sizeof plaintext
);
1362 AES_DestroyContext(cx
, PR_TRUE
);
1364 AES_DestroyContext(cx2
, PR_TRUE
);
1368 fputs("CIPHERTEXT = ", aesresp
);
1369 to_hex_str(buf
, ciphertext
, sizeof ciphertext
);
1370 fputs(buf
, aesresp
);
1371 fputc('\n', aesresp
);
1373 /* Key[i+1] = Key[i] xor ... */
1374 aes_mct_next_key(key
, keysize
, ciphertext_1
, ciphertext
);
1376 /* done at the end of the for(j) loop */
1378 fputc('\n', aesresp
);
1383 /* CIPHERTEXT = ... */
1384 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
1391 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1394 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1395 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
1398 for (i
=0; i
<100; i
++) {
1399 sprintf(buf
, "COUNT = %d\n", i
);
1400 fputs(buf
, aesresp
);
1402 fputs("KEY = ", aesresp
);
1403 to_hex_str(buf
, key
, keysize
);
1404 fputs(buf
, aesresp
);
1405 fputc('\n', aesresp
);
1407 fputs("CIPHERTEXT = ", aesresp
);
1408 to_hex_str(buf
, ciphertext
, sizeof ciphertext
);
1409 fputs(buf
, aesresp
);
1410 fputc('\n', aesresp
);
1412 cx
= AES_CreateContext(key
, NULL
, NSS_AES
,
1413 PR_FALSE
, keysize
, 16);
1418 * doublecheck our result by encrypting the result
1419 * and comparing the output with the ciphertext.
1421 cx2
= AES_CreateContext(key
, NULL
, NSS_AES
,
1422 PR_TRUE
, keysize
, 16);
1426 for (j
=0; j
<1000; j
++) {
1428 memcpy(plaintext_1
, plaintext
, sizeof plaintext
);
1430 /* PT[j] = AES(Key[i], CT[j]) */
1432 rv
= AES_Decrypt(cx
,
1433 plaintext
, &outputlen
, sizeof plaintext
,
1434 ciphertext
, sizeof ciphertext
);
1435 if (rv
!= SECSuccess
) {
1438 if (outputlen
!= sizeof ciphertext
) {
1442 /* doublecheck our result */
1444 rv
= AES_Encrypt(cx2
,
1445 doublecheck
, &outputlen
, sizeof doublecheck
,
1446 plaintext
, sizeof plaintext
);
1447 if (rv
!= SECSuccess
) {
1450 if (outputlen
!= sizeof plaintext
) {
1453 if (memcmp(doublecheck
, ciphertext
, sizeof ciphertext
)) {
1457 /* CT[j+1] = PT[j] */
1458 memcpy(ciphertext
, plaintext
, sizeof ciphertext
);
1460 AES_DestroyContext(cx
, PR_TRUE
);
1462 AES_DestroyContext(cx2
, PR_TRUE
);
1466 fputs("PLAINTEXT = ", aesresp
);
1467 to_hex_str(buf
, plaintext
, sizeof plaintext
);
1468 fputs(buf
, aesresp
);
1469 fputc('\n', aesresp
);
1471 /* Key[i+1] = Key[i] xor ... */
1472 aes_mct_next_key(key
, keysize
, plaintext_1
, plaintext
);
1474 /* done at the end of the for(j) loop */
1476 fputc('\n', aesresp
);
1484 AES_DestroyContext(cx
, PR_TRUE
);
1487 AES_DestroyContext(cx2
, PR_TRUE
);
1493 * Perform the AES Monte Carlo Test (MCT) in CBC mode. MCT exercises
1494 * our AES code in streaming mode because the plaintext or ciphertext
1495 * is generated block by block as we go, so we can't collect all the
1496 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1499 * reqfn is the pathname of the input REQUEST file.
1501 * The output RESPONSE file is written to stdout.
1504 aes_cbc_mct(char *reqfn
)
1506 char buf
[80]; /* holds one line from the input REQUEST file.
1507 * needs to be large enough to hold the longest
1508 * line "KEY = <64 hex digits>\n".
1510 FILE *aesreq
; /* input stream from the REQUEST file */
1511 FILE *aesresp
; /* output stream to the RESPONSE file */
1513 int encrypt
= 0; /* 1 means encrypt, 0 means decrypt */
1514 unsigned char key
[32]; /* 128, 192, or 256 bits */
1515 unsigned int keysize
;
1516 unsigned char iv
[16];
1517 unsigned char plaintext
[16]; /* PT[j] */
1518 unsigned char plaintext_1
[16]; /* PT[j-1] */
1519 unsigned char ciphertext
[16]; /* CT[j] */
1520 unsigned char ciphertext_1
[16]; /* CT[j-1] */
1521 unsigned char doublecheck
[16];
1522 unsigned int outputlen
;
1523 AESContext
*cx
= NULL
; /* the operation being tested */
1524 AESContext
*cx2
= NULL
; /* the inverse operation done in parallel
1525 * to doublecheck our result.
1529 aesreq
= fopen(reqfn
, "r");
1531 while (fgets(buf
, sizeof buf
, aesreq
) != NULL
) {
1532 /* a comment or blank line */
1533 if (buf
[0] == '#' || buf
[0] == '\n') {
1534 fputs(buf
, aesresp
);
1537 /* [ENCRYPT] or [DECRYPT] */
1538 if (buf
[0] == '[') {
1539 if (strncmp(&buf
[1], "ENCRYPT", 7) == 0) {
1544 fputs(buf
, aesresp
);
1547 /* "COUNT = x" begins a new data set */
1548 if (strncmp(buf
, "COUNT", 5) == 0) {
1549 /* zeroize the variables for the test with this data set */
1550 memset(key
, 0, sizeof key
);
1552 memset(iv
, 0, sizeof iv
);
1553 memset(plaintext
, 0, sizeof plaintext
);
1554 memset(ciphertext
, 0, sizeof ciphertext
);
1558 if (strncmp(buf
, "KEY", 3) == 0) {
1561 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1564 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1565 hex_to_byteval(&buf
[i
], &key
[j
]);
1571 if (strncmp(buf
, "IV", 2) == 0) {
1574 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1577 for (j
=0; j
<sizeof iv
; i
+=2,j
++) {
1578 hex_to_byteval(&buf
[i
], &iv
[j
]);
1582 /* PLAINTEXT = ... */
1583 if (strncmp(buf
, "PLAINTEXT", 9) == 0) {
1590 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1593 for (j
=0; j
<sizeof plaintext
; i
+=2,j
++) {
1594 hex_to_byteval(&buf
[i
], &plaintext
[j
]);
1597 for (i
=0; i
<100; i
++) {
1598 sprintf(buf
, "COUNT = %d\n", i
);
1599 fputs(buf
, aesresp
);
1601 fputs("KEY = ", aesresp
);
1602 to_hex_str(buf
, key
, keysize
);
1603 fputs(buf
, aesresp
);
1604 fputc('\n', aesresp
);
1606 fputs("IV = ", aesresp
);
1607 to_hex_str(buf
, iv
, sizeof iv
);
1608 fputs(buf
, aesresp
);
1609 fputc('\n', aesresp
);
1611 fputs("PLAINTEXT = ", aesresp
);
1612 to_hex_str(buf
, plaintext
, sizeof plaintext
);
1613 fputs(buf
, aesresp
);
1614 fputc('\n', aesresp
);
1616 cx
= AES_CreateContext(key
, iv
, NSS_AES_CBC
,
1617 PR_TRUE
, keysize
, 16);
1622 * doublecheck our result by decrypting the result
1623 * and comparing the output with the plaintext.
1625 cx2
= AES_CreateContext(key
, iv
, NSS_AES_CBC
,
1626 PR_FALSE
, keysize
, 16);
1630 /* CT[-1] = IV[i] */
1631 memcpy(ciphertext
, iv
, sizeof ciphertext
);
1632 for (j
=0; j
<1000; j
++) {
1634 memcpy(ciphertext_1
, ciphertext
, sizeof ciphertext
);
1637 * CT[j] = AES(Key[i], IV[i], PT[j])
1638 * PT[j+1] = IV[i] (= CT[j-1])
1640 * CT[j] = AES(Key[i], PT[j])
1644 rv
= AES_Encrypt(cx
,
1645 ciphertext
, &outputlen
, sizeof ciphertext
,
1646 plaintext
, sizeof plaintext
);
1647 if (rv
!= SECSuccess
) {
1650 if (outputlen
!= sizeof plaintext
) {
1654 /* doublecheck our result */
1656 rv
= AES_Decrypt(cx2
,
1657 doublecheck
, &outputlen
, sizeof doublecheck
,
1658 ciphertext
, sizeof ciphertext
);
1659 if (rv
!= SECSuccess
) {
1662 if (outputlen
!= sizeof ciphertext
) {
1665 if (memcmp(doublecheck
, plaintext
, sizeof plaintext
)) {
1669 memcpy(plaintext
, ciphertext_1
, sizeof plaintext
);
1671 AES_DestroyContext(cx
, PR_TRUE
);
1673 AES_DestroyContext(cx2
, PR_TRUE
);
1677 fputs("CIPHERTEXT = ", aesresp
);
1678 to_hex_str(buf
, ciphertext
, sizeof ciphertext
);
1679 fputs(buf
, aesresp
);
1680 fputc('\n', aesresp
);
1682 /* Key[i+1] = Key[i] xor ... */
1683 aes_mct_next_key(key
, keysize
, ciphertext_1
, ciphertext
);
1684 /* IV[i+1] = CT[j] */
1685 memcpy(iv
, ciphertext
, sizeof iv
);
1686 /* PT[0] = CT[j-1] */
1687 /* done at the end of the for(j) loop */
1689 fputc('\n', aesresp
);
1694 /* CIPHERTEXT = ... */
1695 if (strncmp(buf
, "CIPHERTEXT", 10) == 0) {
1702 while (isspace(buf
[i
]) || buf
[i
] == '=') {
1705 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
1706 hex_to_byteval(&buf
[i
], &ciphertext
[j
]);
1709 for (i
=0; i
<100; i
++) {
1710 sprintf(buf
, "COUNT = %d\n", i
);
1711 fputs(buf
, aesresp
);
1713 fputs("KEY = ", aesresp
);
1714 to_hex_str(buf
, key
, keysize
);
1715 fputs(buf
, aesresp
);
1716 fputc('\n', aesresp
);
1718 fputs("IV = ", aesresp
);
1719 to_hex_str(buf
, iv
, sizeof iv
);
1720 fputs(buf
, aesresp
);
1721 fputc('\n', aesresp
);
1723 fputs("CIPHERTEXT = ", aesresp
);
1724 to_hex_str(buf
, ciphertext
, sizeof ciphertext
);
1725 fputs(buf
, aesresp
);
1726 fputc('\n', aesresp
);
1728 cx
= AES_CreateContext(key
, iv
, NSS_AES_CBC
,
1729 PR_FALSE
, keysize
, 16);
1734 * doublecheck our result by encrypting the result
1735 * and comparing the output with the ciphertext.
1737 cx2
= AES_CreateContext(key
, iv
, NSS_AES_CBC
,
1738 PR_TRUE
, keysize
, 16);
1742 /* PT[-1] = IV[i] */
1743 memcpy(plaintext
, iv
, sizeof plaintext
);
1744 for (j
=0; j
<1000; j
++) {
1746 memcpy(plaintext_1
, plaintext
, sizeof plaintext
);
1749 * PT[j] = AES(Key[i], IV[i], CT[j])
1750 * CT[j+1] = IV[i] (= PT[j-1])
1752 * PT[j] = AES(Key[i], CT[j])
1756 rv
= AES_Decrypt(cx
,
1757 plaintext
, &outputlen
, sizeof plaintext
,
1758 ciphertext
, sizeof ciphertext
);
1759 if (rv
!= SECSuccess
) {
1762 if (outputlen
!= sizeof ciphertext
) {
1766 /* doublecheck our result */
1768 rv
= AES_Encrypt(cx2
,
1769 doublecheck
, &outputlen
, sizeof doublecheck
,
1770 plaintext
, sizeof plaintext
);
1771 if (rv
!= SECSuccess
) {
1774 if (outputlen
!= sizeof plaintext
) {
1777 if (memcmp(doublecheck
, ciphertext
, sizeof ciphertext
)) {
1781 memcpy(ciphertext
, plaintext_1
, sizeof ciphertext
);
1783 AES_DestroyContext(cx
, PR_TRUE
);
1785 AES_DestroyContext(cx2
, PR_TRUE
);
1789 fputs("PLAINTEXT = ", aesresp
);
1790 to_hex_str(buf
, plaintext
, sizeof plaintext
);
1791 fputs(buf
, aesresp
);
1792 fputc('\n', aesresp
);
1794 /* Key[i+1] = Key[i] xor ... */
1795 aes_mct_next_key(key
, keysize
, plaintext_1
, plaintext
);
1796 /* IV[i+1] = PT[j] */
1797 memcpy(iv
, plaintext
, sizeof iv
);
1798 /* CT[0] = PT[j-1] */
1799 /* done at the end of the for(j) loop */
1801 fputc('\n', aesresp
);
1809 AES_DestroyContext(cx
, PR_TRUE
);
1812 AES_DestroyContext(cx2
, PR_TRUE
);
1817 void write_compact_string(FILE *out
, unsigned char *hash
, unsigned int len
)
1820 int j
, count
= 0, last
= -1, z
= 0;
1821 long start
= ftell(out
);
1822 for (i
=0; i
<len
; i
++) {
1823 for (j
=7; j
>=0; j
--) {
1825 last
= (hash
[i
] & (1 << j
)) ? 1 : 0;
1826 fprintf(out
, "%d ", last
);
1828 } else if (hash
[i
] & (1 << j
)) {
1833 fprintf(out
, "%d ", count
);
1842 fprintf(out
, "%d ", count
);
1849 fprintf(out
, "^\n");
1850 fseek(out
, start
, SEEK_SET
);
1851 fprintf(out
, "%d ", z
);
1852 fseek(out
, 0, SEEK_END
);
1855 int get_next_line(FILE *req
, char *key
, char *val
, FILE *rsp
)
1858 char *writeto
= key
;
1861 while ((c
= fgetc(req
)) != EOF
) {
1863 fprintf(rsp
, "%c", c
);
1864 if (c
== '\n') return ignore
;
1865 } else if (c
== '\n') {
1867 } else if (c
== '#') {
1869 fprintf(rsp
, "%c", c
);
1870 } else if (c
== '=') {
1874 } else if (c
== ' ' || c
== '[' || c
== ']') {
1881 return (c
== EOF
) ? -1 : ignore
;
1884 #ifdef NSS_ENABLE_ECC
1885 typedef struct curveNameTagPairStr
{
1887 SECOidTag curveOidTag
;
1890 #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
1891 /* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */
1893 static CurveNameTagPair nameTagPair
[] =
1895 { "sect163k1", SEC_OID_SECG_EC_SECT163K1
},
1896 { "nistk163", SEC_OID_SECG_EC_SECT163K1
},
1897 { "sect163r1", SEC_OID_SECG_EC_SECT163R1
},
1898 { "sect163r2", SEC_OID_SECG_EC_SECT163R2
},
1899 { "nistb163", SEC_OID_SECG_EC_SECT163R2
},
1900 { "sect193r1", SEC_OID_SECG_EC_SECT193R1
},
1901 { "sect193r2", SEC_OID_SECG_EC_SECT193R2
},
1902 { "sect233k1", SEC_OID_SECG_EC_SECT233K1
},
1903 { "nistk233", SEC_OID_SECG_EC_SECT233K1
},
1904 { "sect233r1", SEC_OID_SECG_EC_SECT233R1
},
1905 { "nistb233", SEC_OID_SECG_EC_SECT233R1
},
1906 { "sect239k1", SEC_OID_SECG_EC_SECT239K1
},
1907 { "sect283k1", SEC_OID_SECG_EC_SECT283K1
},
1908 { "nistk283", SEC_OID_SECG_EC_SECT283K1
},
1909 { "sect283r1", SEC_OID_SECG_EC_SECT283R1
},
1910 { "nistb283", SEC_OID_SECG_EC_SECT283R1
},
1911 { "sect409k1", SEC_OID_SECG_EC_SECT409K1
},
1912 { "nistk409", SEC_OID_SECG_EC_SECT409K1
},
1913 { "sect409r1", SEC_OID_SECG_EC_SECT409R1
},
1914 { "nistb409", SEC_OID_SECG_EC_SECT409R1
},
1915 { "sect571k1", SEC_OID_SECG_EC_SECT571K1
},
1916 { "nistk571", SEC_OID_SECG_EC_SECT571K1
},
1917 { "sect571r1", SEC_OID_SECG_EC_SECT571R1
},
1918 { "nistb571", SEC_OID_SECG_EC_SECT571R1
},
1919 { "secp160k1", SEC_OID_SECG_EC_SECP160K1
},
1920 { "secp160r1", SEC_OID_SECG_EC_SECP160R1
},
1921 { "secp160r2", SEC_OID_SECG_EC_SECP160R2
},
1922 { "secp192k1", SEC_OID_SECG_EC_SECP192K1
},
1923 { "secp192r1", SEC_OID_SECG_EC_SECP192R1
},
1924 { "nistp192", SEC_OID_SECG_EC_SECP192R1
},
1925 { "secp224k1", SEC_OID_SECG_EC_SECP224K1
},
1926 { "secp224r1", SEC_OID_SECG_EC_SECP224R1
},
1927 { "nistp224", SEC_OID_SECG_EC_SECP224R1
},
1928 { "secp256k1", SEC_OID_SECG_EC_SECP256K1
},
1929 { "secp256r1", SEC_OID_SECG_EC_SECP256R1
},
1930 { "nistp256", SEC_OID_SECG_EC_SECP256R1
},
1931 { "secp384r1", SEC_OID_SECG_EC_SECP384R1
},
1932 { "nistp384", SEC_OID_SECG_EC_SECP384R1
},
1933 { "secp521r1", SEC_OID_SECG_EC_SECP521R1
},
1934 { "nistp521", SEC_OID_SECG_EC_SECP521R1
},
1936 { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1
},
1937 { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2
},
1938 { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3
},
1939 { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1
},
1940 { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2
},
1941 { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3
},
1943 { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1
},
1944 { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2
},
1945 { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3
},
1946 { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1
},
1947 { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1
},
1948 { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2
},
1949 { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3
},
1950 { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4
},
1951 { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5
},
1952 { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1
},
1953 { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1
},
1954 { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2
},
1955 { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3
},
1956 { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4
},
1957 { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5
},
1958 { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1
},
1959 { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1
},
1960 { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1
},
1961 { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1
},
1962 { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1
},
1964 { "secp112r1", SEC_OID_SECG_EC_SECP112R1
},
1965 { "secp112r2", SEC_OID_SECG_EC_SECP112R2
},
1966 { "secp128r1", SEC_OID_SECG_EC_SECP128R1
},
1967 { "secp128r2", SEC_OID_SECG_EC_SECP128R2
},
1969 { "sect113r1", SEC_OID_SECG_EC_SECT113R1
},
1970 { "sect113r2", SEC_OID_SECG_EC_SECT113R2
},
1971 { "sect131r1", SEC_OID_SECG_EC_SECT131R1
},
1972 { "sect131r2", SEC_OID_SECG_EC_SECT131R2
},
1975 static SECKEYECParams
*
1976 getECParams(const char *curve
)
1978 SECKEYECParams
*ecparams
;
1979 SECOidData
*oidData
= NULL
;
1980 SECOidTag curveOidTag
= SEC_OID_UNKNOWN
; /* default */
1983 if (curve
!= NULL
) {
1984 numCurves
= sizeof(nameTagPair
)/sizeof(CurveNameTagPair
);
1985 for (i
= 0; ((i
< numCurves
) && (curveOidTag
== SEC_OID_UNKNOWN
));
1987 if (PL_strcmp(curve
, nameTagPair
[i
].curveName
) == 0)
1988 curveOidTag
= nameTagPair
[i
].curveOidTag
;
1992 /* Return NULL if curve name is not recognized */
1993 if ((curveOidTag
== SEC_OID_UNKNOWN
) ||
1994 (oidData
= SECOID_FindOIDByTag(curveOidTag
)) == NULL
) {
1995 fprintf(stderr
, "Unrecognized elliptic curve %s\n", curve
);
1999 ecparams
= SECITEM_AllocItem(NULL
, NULL
, (2 + oidData
->oid
.len
));
2002 * ecparams->data needs to contain the ASN encoding of an object ID (OID)
2003 * representing the named curve. The actual OID is in
2004 * oidData->oid.data so we simply prepend 0x06 and OID length
2006 ecparams
->data
[0] = SEC_ASN1_OBJECT_ID
;
2007 ecparams
->data
[1] = oidData
->oid
.len
;
2008 memcpy(ecparams
->data
+ 2, oidData
->oid
.data
, oidData
->oid
.len
);
2014 * Perform the ECDSA Key Pair Generation Test.
2016 * reqfn is the pathname of the REQUEST file.
2018 * The output RESPONSE file is written to stdout.
2021 ecdsa_keypair_test(char *reqfn
)
2023 char buf
[256]; /* holds one line from the input REQUEST file
2024 * or to the output RESPONSE file.
2025 * needs to be large enough to hold the longest
2026 * line "Qx = <144 hex digits>\n".
2028 FILE *ecdsareq
; /* input stream from the REQUEST file */
2029 FILE *ecdsaresp
; /* output stream to the RESPONSE file */
2030 char curve
[16]; /* "nistxddd" */
2036 ecdsareq
= fopen(reqfn
, "r");
2038 strcpy(curve
, "nist");
2039 while (fgets(buf
, sizeof buf
, ecdsareq
) != NULL
) {
2040 /* a comment or blank line */
2041 if (buf
[0] == '#' || buf
[0] == '\n') {
2042 fputs(buf
, ecdsaresp
);
2046 if (buf
[0] == '[') {
2049 SECKEYECParams
*encodedparams
;
2053 *dst
++ = tolower(*src
);
2054 src
+= 2; /* skip the hyphen */
2059 encodedparams
= getECParams(curve
);
2060 if (encodedparams
== NULL
) {
2063 if (EC_DecodeParams(encodedparams
, &ecparams
) != SECSuccess
) {
2066 SECITEM_FreeItem(encodedparams
, PR_TRUE
);
2067 fputs(buf
, ecdsaresp
);
2071 if (buf
[0] == 'N') {
2072 if (sscanf(buf
, "N = %d", &N
) != 1) {
2075 for (i
= 0; i
< N
; i
++) {
2076 ECPrivateKey
*ecpriv
;
2078 if (EC_NewKey(ecparams
, &ecpriv
) != SECSuccess
) {
2081 fputs("d = ", ecdsaresp
);
2082 to_hex_str(buf
, ecpriv
->privateValue
.data
,
2083 ecpriv
->privateValue
.len
);
2084 fputs(buf
, ecdsaresp
);
2085 fputc('\n', ecdsaresp
);
2086 if (EC_ValidatePublicKey(ecparams
, &ecpriv
->publicValue
)
2090 len
= ecpriv
->publicValue
.len
;
2095 if (ecpriv
->publicValue
.data
[0]
2096 != EC_POINT_FORM_UNCOMPRESSED
) {
2099 fputs("Qx = ", ecdsaresp
);
2100 to_hex_str(buf
, &ecpriv
->publicValue
.data
[1], len
);
2101 fputs(buf
, ecdsaresp
);
2102 fputc('\n', ecdsaresp
);
2103 fputs("Qy = ", ecdsaresp
);
2104 to_hex_str(buf
, &ecpriv
->publicValue
.data
[1+len
], len
);
2105 fputs(buf
, ecdsaresp
);
2106 fputc('\n', ecdsaresp
);
2107 fputc('\n', ecdsaresp
);
2108 PORT_FreeArena(ecpriv
->ecParams
.arena
, PR_TRUE
);
2110 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2119 * Perform the ECDSA Public Key Validation Test.
2121 * reqfn is the pathname of the REQUEST file.
2123 * The output RESPONSE file is written to stdout.
2126 ecdsa_pkv_test(char *reqfn
)
2128 char buf
[256]; /* holds one line from the input REQUEST file.
2129 * needs to be large enough to hold the longest
2130 * line "Qx = <144 hex digits>\n".
2132 FILE *ecdsareq
; /* input stream from the REQUEST file */
2133 FILE *ecdsaresp
; /* output stream to the RESPONSE file */
2134 char curve
[16]; /* "nistxddd" */
2135 ECParams
*ecparams
= NULL
;
2139 PRBool keyvalid
= PR_TRUE
;
2141 ecdsareq
= fopen(reqfn
, "r");
2143 strcpy(curve
, "nist");
2145 while (fgets(buf
, sizeof buf
, ecdsareq
) != NULL
) {
2146 /* a comment or blank line */
2147 if (buf
[0] == '#' || buf
[0] == '\n') {
2148 fputs(buf
, ecdsaresp
);
2152 if (buf
[0] == '[') {
2155 SECKEYECParams
*encodedparams
;
2159 *dst
++ = tolower(*src
);
2160 src
+= 2; /* skip the hyphen */
2165 if (ecparams
!= NULL
) {
2166 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2169 encodedparams
= getECParams(curve
);
2170 if (encodedparams
== NULL
) {
2173 if (EC_DecodeParams(encodedparams
, &ecparams
) != SECSuccess
) {
2176 SECITEM_FreeItem(encodedparams
, PR_TRUE
);
2177 len
= (ecparams
->fieldID
.size
+ 7) >> 3;
2178 if (pubkey
.data
!= NULL
) {
2179 PORT_Free(pubkey
.data
);
2182 SECITEM_AllocItem(NULL
, &pubkey
, 2*len
+1);
2183 if (pubkey
.data
== NULL
) {
2186 pubkey
.data
[0] = EC_POINT_FORM_UNCOMPRESSED
;
2187 fputs(buf
, ecdsaresp
);
2191 if (strncmp(buf
, "Qx", 2) == 0) {
2192 fputs(buf
, ecdsaresp
);
2194 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2197 keyvalid
= from_hex_str(&pubkey
.data
[1], len
, &buf
[i
]);
2201 if (strncmp(buf
, "Qy", 2) == 0) {
2202 fputs(buf
, ecdsaresp
);
2204 fputs("Result = F\n", ecdsaresp
);
2208 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2211 keyvalid
= from_hex_str(&pubkey
.data
[1+len
], len
, &buf
[i
]);
2213 fputs("Result = F\n", ecdsaresp
);
2216 if (EC_ValidatePublicKey(ecparams
, &pubkey
) == SECSuccess
) {
2217 fputs("Result = P\n", ecdsaresp
);
2218 } else if (PORT_GetError() == SEC_ERROR_BAD_KEY
) {
2219 fputs("Result = F\n", ecdsaresp
);
2227 if (ecparams
!= NULL
) {
2228 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2230 if (pubkey
.data
!= NULL
) {
2231 PORT_Free(pubkey
.data
);
2237 * Perform the ECDSA Signature Generation Test.
2239 * reqfn is the pathname of the REQUEST file.
2241 * The output RESPONSE file is written to stdout.
2244 ecdsa_siggen_test(char *reqfn
)
2246 char buf
[1024]; /* holds one line from the input REQUEST file
2247 * or to the output RESPONSE file.
2248 * needs to be large enough to hold the longest
2249 * line "Msg = <256 hex digits>\n".
2251 FILE *ecdsareq
; /* input stream from the REQUEST file */
2252 FILE *ecdsaresp
; /* output stream to the RESPONSE file */
2253 char curve
[16]; /* "nistxddd" */
2254 ECParams
*ecparams
= NULL
;
2257 unsigned char msg
[512]; /* message to be signed (<= 128 bytes) */
2258 unsigned int msglen
;
2259 unsigned char sha1
[20]; /* SHA-1 hash (160 bits) */
2260 unsigned char sig
[2*MAX_ECKEY_LEN
];
2261 SECItem signature
, digest
;
2263 ecdsareq
= fopen(reqfn
, "r");
2265 strcpy(curve
, "nist");
2266 while (fgets(buf
, sizeof buf
, ecdsareq
) != NULL
) {
2267 /* a comment or blank line */
2268 if (buf
[0] == '#' || buf
[0] == '\n') {
2269 fputs(buf
, ecdsaresp
);
2273 if (buf
[0] == '[') {
2276 SECKEYECParams
*encodedparams
;
2280 *dst
++ = tolower(*src
);
2281 src
+= 2; /* skip the hyphen */
2286 if (ecparams
!= NULL
) {
2287 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2290 encodedparams
= getECParams(curve
);
2291 if (encodedparams
== NULL
) {
2294 if (EC_DecodeParams(encodedparams
, &ecparams
) != SECSuccess
) {
2297 SECITEM_FreeItem(encodedparams
, PR_TRUE
);
2298 fputs(buf
, ecdsaresp
);
2302 if (strncmp(buf
, "Msg", 3) == 0) {
2303 ECPrivateKey
*ecpriv
;
2306 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2309 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
2310 hex_to_byteval(&buf
[i
], &msg
[j
]);
2313 if (SHA1_HashBuf(sha1
, msg
, msglen
) != SECSuccess
) {
2316 fputs(buf
, ecdsaresp
);
2318 if (EC_NewKey(ecparams
, &ecpriv
) != SECSuccess
) {
2321 if (EC_ValidatePublicKey(ecparams
, &ecpriv
->publicValue
)
2325 len
= ecpriv
->publicValue
.len
;
2330 if (ecpriv
->publicValue
.data
[0] != EC_POINT_FORM_UNCOMPRESSED
) {
2333 fputs("Qx = ", ecdsaresp
);
2334 to_hex_str(buf
, &ecpriv
->publicValue
.data
[1], len
);
2335 fputs(buf
, ecdsaresp
);
2336 fputc('\n', ecdsaresp
);
2337 fputs("Qy = ", ecdsaresp
);
2338 to_hex_str(buf
, &ecpriv
->publicValue
.data
[1+len
], len
);
2339 fputs(buf
, ecdsaresp
);
2340 fputc('\n', ecdsaresp
);
2342 digest
.type
= siBuffer
;
2344 digest
.len
= sizeof sha1
;
2345 signature
.type
= siBuffer
;
2346 signature
.data
= sig
;
2347 signature
.len
= sizeof sig
;
2348 if (ECDSA_SignDigest(ecpriv
, &signature
, &digest
) != SECSuccess
) {
2351 len
= signature
.len
;
2356 fputs("R = ", ecdsaresp
);
2357 to_hex_str(buf
, &signature
.data
[0], len
);
2358 fputs(buf
, ecdsaresp
);
2359 fputc('\n', ecdsaresp
);
2360 fputs("S = ", ecdsaresp
);
2361 to_hex_str(buf
, &signature
.data
[len
], len
);
2362 fputs(buf
, ecdsaresp
);
2363 fputc('\n', ecdsaresp
);
2365 PORT_FreeArena(ecpriv
->ecParams
.arena
, PR_TRUE
);
2370 if (ecparams
!= NULL
) {
2371 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2377 * Perform the ECDSA Signature Verification Test.
2379 * reqfn is the pathname of the REQUEST file.
2381 * The output RESPONSE file is written to stdout.
2384 ecdsa_sigver_test(char *reqfn
)
2386 char buf
[1024]; /* holds one line from the input REQUEST file.
2387 * needs to be large enough to hold the longest
2388 * line "Msg = <256 hex digits>\n".
2390 FILE *ecdsareq
; /* input stream from the REQUEST file */
2391 FILE *ecdsaresp
; /* output stream to the RESPONSE file */
2392 char curve
[16]; /* "nistxddd" */
2395 unsigned int flen
; /* length in bytes of the field size */
2396 unsigned int olen
; /* length in bytes of the base point order */
2397 unsigned char msg
[512]; /* message that was signed (<= 128 bytes) */
2398 unsigned int msglen
;
2399 unsigned char sha1
[20]; /* SHA-1 hash (160 bits) */
2400 unsigned char sig
[2*MAX_ECKEY_LEN
];
2401 SECItem signature
, digest
;
2402 PRBool keyvalid
= PR_TRUE
;
2403 PRBool sigvalid
= PR_TRUE
;
2405 ecdsareq
= fopen(reqfn
, "r");
2407 ecpub
.ecParams
.arena
= NULL
;
2408 strcpy(curve
, "nist");
2409 while (fgets(buf
, sizeof buf
, ecdsareq
) != NULL
) {
2410 /* a comment or blank line */
2411 if (buf
[0] == '#' || buf
[0] == '\n') {
2412 fputs(buf
, ecdsaresp
);
2416 if (buf
[0] == '[') {
2419 SECKEYECParams
*encodedparams
;
2424 *dst
++ = tolower(*src
);
2425 src
+= 2; /* skip the hyphen */
2430 encodedparams
= getECParams(curve
);
2431 if (encodedparams
== NULL
) {
2434 if (EC_DecodeParams(encodedparams
, &ecparams
) != SECSuccess
) {
2437 SECITEM_FreeItem(encodedparams
, PR_TRUE
);
2438 if (ecpub
.ecParams
.arena
!= NULL
) {
2439 PORT_FreeArena(ecpub
.ecParams
.arena
, PR_FALSE
);
2441 ecpub
.ecParams
.arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2442 if (ecpub
.ecParams
.arena
== NULL
) {
2445 if (EC_CopyParams(ecpub
.ecParams
.arena
, &ecpub
.ecParams
, ecparams
)
2449 PORT_FreeArena(ecparams
->arena
, PR_FALSE
);
2450 flen
= (ecpub
.ecParams
.fieldID
.size
+ 7) >> 3;
2451 olen
= ecpub
.ecParams
.order
.len
;
2452 if (2*olen
> sizeof sig
) {
2455 ecpub
.publicValue
.type
= siBuffer
;
2456 ecpub
.publicValue
.data
= NULL
;
2457 ecpub
.publicValue
.len
= 0;
2458 SECITEM_AllocItem(ecpub
.ecParams
.arena
,
2459 &ecpub
.publicValue
, 2*flen
+1);
2460 if (ecpub
.publicValue
.data
== NULL
) {
2463 ecpub
.publicValue
.data
[0] = EC_POINT_FORM_UNCOMPRESSED
;
2464 fputs(buf
, ecdsaresp
);
2468 if (strncmp(buf
, "Msg", 3) == 0) {
2470 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2473 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
2474 hex_to_byteval(&buf
[i
], &msg
[j
]);
2477 if (SHA1_HashBuf(sha1
, msg
, msglen
) != SECSuccess
) {
2480 fputs(buf
, ecdsaresp
);
2482 digest
.type
= siBuffer
;
2484 digest
.len
= sizeof sha1
;
2489 if (strncmp(buf
, "Qx", 2) == 0) {
2490 fputs(buf
, ecdsaresp
);
2492 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2495 keyvalid
= from_hex_str(&ecpub
.publicValue
.data
[1], flen
,
2500 if (strncmp(buf
, "Qy", 2) == 0) {
2501 fputs(buf
, ecdsaresp
);
2506 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2509 keyvalid
= from_hex_str(&ecpub
.publicValue
.data
[1+flen
], flen
,
2514 if (EC_ValidatePublicKey(&ecpub
.ecParams
, &ecpub
.publicValue
)
2516 if (PORT_GetError() == SEC_ERROR_BAD_KEY
) {
2517 keyvalid
= PR_FALSE
;
2525 if (buf
[0] == 'R') {
2526 fputs(buf
, ecdsaresp
);
2528 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2531 sigvalid
= from_hex_str(sig
, olen
, &buf
[i
]);
2535 if (buf
[0] == 'S') {
2536 fputs(buf
, ecdsaresp
);
2538 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2542 sigvalid
= from_hex_str(&sig
[olen
], olen
, &buf
[i
]);
2544 signature
.type
= siBuffer
;
2545 signature
.data
= sig
;
2546 signature
.len
= 2*olen
;
2548 if (!keyvalid
|| !sigvalid
) {
2549 fputs("Result = F\n", ecdsaresp
);
2550 } else if (ECDSA_VerifyDigest(&ecpub
, &signature
, &digest
)
2552 fputs("Result = P\n", ecdsaresp
);
2554 fputs("Result = F\n", ecdsaresp
);
2560 if (ecpub
.ecParams
.arena
!= NULL
) {
2561 PORT_FreeArena(ecpub
.ecParams
.arena
, PR_FALSE
);
2565 #endif /* NSS_ENABLE_ECC */
2568 * Perform the RNG Variable Seed Test (VST) for the RNG algorithm
2569 * "DSA - Generation of X", used both as specified and as a generic
2570 * purpose RNG. The presence of "Q = ..." in the REQUEST file
2571 * indicates we are using the algorithm as specified.
2573 * reqfn is the pathname of the REQUEST file.
2575 * The output RESPONSE file is written to stdout.
2578 rng_vst(char *reqfn
)
2580 char buf
[256]; /* holds one line from the input REQUEST file.
2581 * needs to be large enough to hold the longest
2582 * line "XSeed = <128 hex digits>\n".
2584 FILE *rngreq
; /* input stream from the REQUEST file */
2585 FILE *rngresp
; /* output stream to the RESPONSE file */
2587 unsigned char Q
[DSA_SUBPRIME_LEN
];
2588 PRBool hasQ
= PR_FALSE
;
2589 unsigned int b
; /* 160 <= b <= 512, b is a multiple of 8 */
2590 unsigned char XKey
[512/8];
2591 unsigned char XSeed
[512/8];
2592 unsigned char GENX
[2*SHA1_LENGTH
];
2593 unsigned char DSAX
[DSA_SUBPRIME_LEN
];
2596 rngreq
= fopen(reqfn
, "r");
2598 while (fgets(buf
, sizeof buf
, rngreq
) != NULL
) {
2599 /* a comment or blank line */
2600 if (buf
[0] == '#' || buf
[0] == '\n') {
2601 fputs(buf
, rngresp
);
2604 /* [Xchange - SHA1] */
2605 if (buf
[0] == '[') {
2606 fputs(buf
, rngresp
);
2610 if (buf
[0] == 'Q') {
2612 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2615 for (j
=0; j
<sizeof Q
; i
+=2,j
++) {
2616 hex_to_byteval(&buf
[i
], &Q
[j
]);
2618 fputs(buf
, rngresp
);
2622 /* "COUNT = x" begins a new data set */
2623 if (strncmp(buf
, "COUNT", 5) == 0) {
2624 /* zeroize the variables for the test with this data set */
2626 memset(XKey
, 0, sizeof XKey
);
2627 memset(XSeed
, 0, sizeof XSeed
);
2628 fputs(buf
, rngresp
);
2632 if (buf
[0] == 'b') {
2634 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2638 if (b
< 160 || b
> 512 || b
%8 != 0) {
2641 fputs(buf
, rngresp
);
2645 if (strncmp(buf
, "XKey", 4) == 0) {
2647 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2650 for (j
=0; j
<b
/8; i
+=2,j
++) {
2651 hex_to_byteval(&buf
[i
], &XKey
[j
]);
2653 fputs(buf
, rngresp
);
2657 if (strncmp(buf
, "XSeed", 5) == 0) {
2659 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2662 for (j
=0; j
<b
/8; i
+=2,j
++) {
2663 hex_to_byteval(&buf
[i
], &XSeed
[j
]);
2665 fputs(buf
, rngresp
);
2667 rv
= FIPS186Change_GenerateX(XKey
, XSeed
, GENX
);
2668 if (rv
!= SECSuccess
) {
2671 fputs("X = ", rngresp
);
2673 rv
= FIPS186Change_ReduceModQForDSA(GENX
, Q
, DSAX
);
2674 if (rv
!= SECSuccess
) {
2677 to_hex_str(buf
, DSAX
, sizeof DSAX
);
2679 to_hex_str(buf
, GENX
, sizeof GENX
);
2681 fputs(buf
, rngresp
);
2682 fputc('\n', rngresp
);
2691 * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm
2692 * "DSA - Generation of X", used both as specified and as a generic
2693 * purpose RNG. The presence of "Q = ..." in the REQUEST file
2694 * indicates we are using the algorithm as specified.
2696 * reqfn is the pathname of the REQUEST file.
2698 * The output RESPONSE file is written to stdout.
2701 rng_mct(char *reqfn
)
2703 char buf
[256]; /* holds one line from the input REQUEST file.
2704 * needs to be large enough to hold the longest
2705 * line "XSeed = <128 hex digits>\n".
2707 FILE *rngreq
; /* input stream from the REQUEST file */
2708 FILE *rngresp
; /* output stream to the RESPONSE file */
2710 unsigned char Q
[DSA_SUBPRIME_LEN
];
2711 PRBool hasQ
= PR_FALSE
;
2712 unsigned int b
; /* 160 <= b <= 512, b is a multiple of 8 */
2713 unsigned char XKey
[512/8];
2714 unsigned char XSeed
[512/8];
2715 unsigned char GENX
[2*SHA1_LENGTH
];
2716 unsigned char DSAX
[DSA_SUBPRIME_LEN
];
2719 rngreq
= fopen(reqfn
, "r");
2721 while (fgets(buf
, sizeof buf
, rngreq
) != NULL
) {
2722 /* a comment or blank line */
2723 if (buf
[0] == '#' || buf
[0] == '\n') {
2724 fputs(buf
, rngresp
);
2727 /* [Xchange - SHA1] */
2728 if (buf
[0] == '[') {
2729 fputs(buf
, rngresp
);
2733 if (buf
[0] == 'Q') {
2735 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2738 for (j
=0; j
<sizeof Q
; i
+=2,j
++) {
2739 hex_to_byteval(&buf
[i
], &Q
[j
]);
2741 fputs(buf
, rngresp
);
2745 /* "COUNT = x" begins a new data set */
2746 if (strncmp(buf
, "COUNT", 5) == 0) {
2747 /* zeroize the variables for the test with this data set */
2749 memset(XKey
, 0, sizeof XKey
);
2750 memset(XSeed
, 0, sizeof XSeed
);
2751 fputs(buf
, rngresp
);
2755 if (buf
[0] == 'b') {
2757 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2761 if (b
< 160 || b
> 512 || b
%8 != 0) {
2764 fputs(buf
, rngresp
);
2768 if (strncmp(buf
, "XKey", 4) == 0) {
2770 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2773 for (j
=0; j
<b
/8; i
+=2,j
++) {
2774 hex_to_byteval(&buf
[i
], &XKey
[j
]);
2776 fputs(buf
, rngresp
);
2780 if (strncmp(buf
, "XSeed", 5) == 0) {
2783 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2786 for (j
=0; j
<b
/8; i
+=2,j
++) {
2787 hex_to_byteval(&buf
[i
], &XSeed
[j
]);
2789 fputs(buf
, rngresp
);
2791 for (k
= 0; k
< 10000; k
++) {
2792 rv
= FIPS186Change_GenerateX(XKey
, XSeed
, GENX
);
2793 if (rv
!= SECSuccess
) {
2797 fputs("X = ", rngresp
);
2799 rv
= FIPS186Change_ReduceModQForDSA(GENX
, Q
, DSAX
);
2800 if (rv
!= SECSuccess
) {
2803 to_hex_str(buf
, DSAX
, sizeof DSAX
);
2805 to_hex_str(buf
, GENX
, sizeof GENX
);
2807 fputs(buf
, rngresp
);
2808 fputc('\n', rngresp
);
2817 * Calculate the SHA Message Digest
2819 * MD = Message digest
2820 * MDLen = length of Message Digest and SHA_Type
2821 * msg = message to digest
2822 * msgLen = length of message to digest
2824 SECStatus
sha_calcMD(unsigned char *MD
, unsigned int MDLen
, unsigned char *msg
, unsigned int msgLen
)
2826 SECStatus sha_status
= SECFailure
;
2828 if (MDLen
== SHA1_LENGTH
) {
2829 sha_status
= SHA1_HashBuf(MD
, msg
, msgLen
);
2830 } else if (MDLen
== SHA256_LENGTH
) {
2831 sha_status
= SHA256_HashBuf(MD
, msg
, msgLen
);
2832 } else if (MDLen
== SHA384_LENGTH
) {
2833 sha_status
= SHA384_HashBuf(MD
, msg
, msgLen
);
2834 } else if (MDLen
== SHA512_LENGTH
) {
2835 sha_status
= SHA512_HashBuf(MD
, msg
, msgLen
);
2842 * Perform the SHA Monte Carlo Test
2844 * MDLen = length of Message Digest and SHA_Type
2845 * seed = input seed value
2846 * resp = is the output response file.
2848 SECStatus
sha_mct_test(unsigned int MDLen
, unsigned char *seed
, FILE *resp
)
2851 unsigned int msgLen
= MDLen
*3;
2852 unsigned char MD_i3
[HASH_LENGTH_MAX
]; /* MD[i-3] */
2853 unsigned char MD_i2
[HASH_LENGTH_MAX
]; /* MD[i-2] */
2854 unsigned char MD_i1
[HASH_LENGTH_MAX
]; /* MD[i-1] */
2855 unsigned char MD_i
[HASH_LENGTH_MAX
]; /* MD[i] */
2856 unsigned char msg
[HASH_LENGTH_MAX
*3];
2857 char buf
[HASH_LENGTH_MAX
*2 + 1]; /* MAX buf MD_i as a hex string */
2859 for (j
=0; j
<100; j
++) {
2860 /* MD_0 = MD_1 = MD_2 = seed */
2861 memcpy(MD_i3
, seed
, MDLen
);
2862 memcpy(MD_i2
, seed
, MDLen
);
2863 memcpy(MD_i1
, seed
, MDLen
);
2865 for (i
=3; i
< 1003; i
++) {
2866 /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */
2867 memcpy(msg
, MD_i3
, MDLen
);
2868 memcpy(&msg
[MDLen
], MD_i2
, MDLen
);
2869 memcpy(&msg
[MDLen
*2], MD_i1
,MDLen
);
2871 /* MDi = SHA(Msg) */
2872 if (sha_calcMD(MD_i
, MDLen
,
2873 msg
, msgLen
) != SECSuccess
) {
2877 /* save MD[i-3] MD[i-2] MD[i-1] */
2878 memcpy(MD_i3
, MD_i2
, MDLen
);
2879 memcpy(MD_i2
, MD_i1
, MDLen
);
2880 memcpy(MD_i1
, MD_i
, MDLen
);
2885 memcpy(seed
, MD_i
, MDLen
);
2887 sprintf(buf
, "COUNT = %d\n", j
);
2891 fputs("MD = ", resp
);
2892 to_hex_str(buf
, MD_i
, MDLen
);
2901 * Perform the SHA Tests.
2903 * reqfn is the pathname of the input REQUEST file.
2905 * The output RESPONSE file is written to stdout.
2907 void sha_test(char *reqfn
)
2910 unsigned int MDlen
; /* the length of the Message Digest in Bytes */
2911 unsigned int msgLen
; /* the length of the input Message in Bytes */
2912 unsigned char *msg
= NULL
; /* holds the message to digest.*/
2913 size_t bufSize
= 25608; /*MAX buffer size */
2914 char *buf
= NULL
; /* holds one line from the input REQUEST file.*/
2915 unsigned char seed
[HASH_LENGTH_MAX
]; /* max size of seed 64 bytes */
2916 unsigned char MD
[HASH_LENGTH_MAX
]; /* message digest */
2918 FILE *req
= NULL
; /* input stream from the REQUEST file */
2919 FILE *resp
; /* output stream to the RESPONSE file */
2921 buf
= PORT_ZAlloc(bufSize
);
2926 /* zeroize the variables for the test with this data set */
2927 memset(seed
, 0, sizeof seed
);
2929 req
= fopen(reqfn
, "r");
2931 while (fgets(buf
, bufSize
, req
) != NULL
) {
2933 /* a comment or blank line */
2934 if (buf
[0] == '#' || buf
[0] == '\n') {
2938 /* [L = Length of the Message Digest and sha_type */
2939 if (buf
[0] == '[') {
2940 if (strncmp(&buf
[1], "L ", 1) == 0) {
2942 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2945 MDlen
= atoi(&buf
[i
]);
2950 /* Len = Length of the Input Message Length ... */
2951 if (strncmp(buf
, "Len", 3) == 0) {
2953 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2957 PORT_ZFree(msg
,msgLen
);
2960 msgLen
= atoi(&buf
[i
]); /* in bits */
2961 if (msgLen
%8 != 0) {
2962 fprintf(stderr
, "SHA tests are incorrectly configured for "
2963 "BIT oriented implementations\n");
2966 msgLen
= msgLen
/8; /* convert to bytes */
2968 msg
= PORT_ZAlloc(msgLen
);
2969 if (msg
== NULL
&& msgLen
!= 0) {
2975 if (strncmp(buf
, "Msg", 3) == 0) {
2977 while (isspace(buf
[i
]) || buf
[i
] == '=') {
2980 for (j
=0; j
< msgLen
; i
+=2,j
++) {
2981 hex_to_byteval(&buf
[i
], &msg
[j
]);
2984 /* calculate the Message Digest */
2985 memset(MD
, 0, sizeof MD
);
2986 if (sha_calcMD(MD
, MDlen
,
2987 msg
, msgLen
) != SECSuccess
) {
2991 fputs("MD = ", resp
);
2992 to_hex_str(buf
, MD
, MDlen
);
2999 if (strncmp(buf
, "Seed", 4) == 0) {
3001 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3004 for (j
=0; j
<sizeof seed
; i
+=2,j
++) {
3005 hex_to_byteval(&buf
[i
], &seed
[j
]);
3011 /* do the Monte Carlo test */
3012 if (sha_mct_test(MDlen
, seed
, resp
) != SECSuccess
) {
3024 PORT_ZFree(buf
, bufSize
);
3027 PORT_ZFree(msg
, msgLen
);
3031 /****************************************************/
3032 /* HMAC SHA-X calc */
3033 /* hmac_computed - the computed HMAC */
3034 /* hmac_length - the length of the computed HMAC */
3035 /* secret_key - secret key to HMAC */
3036 /* secret_key_length - length of secret key, */
3037 /* message - message to HMAC */
3038 /* message_length - length ofthe message */
3039 /****************************************************/
3041 hmac_calc(unsigned char *hmac_computed
,
3042 const unsigned int hmac_length
,
3043 const unsigned char *secret_key
,
3044 const unsigned int secret_key_length
,
3045 const unsigned char *message
,
3046 const unsigned int message_length
,
3047 const HASH_HashType hashAlg
)
3049 SECStatus hmac_status
= SECFailure
;
3050 HMACContext
*cx
= NULL
;
3051 SECHashObject
*hashObj
= NULL
;
3052 unsigned int bytes_hashed
= 0;
3054 hashObj
= (SECHashObject
*) HASH_GetRawHashObject(hashAlg
);
3057 return( SECFailure
);
3059 cx
= HMAC_Create(hashObj
, secret_key
,
3061 PR_TRUE
); /* PR_TRUE for in FIPS mode */
3064 return( SECFailure
);
3067 HMAC_Update(cx
, message
, message_length
);
3068 hmac_status
= HMAC_Finish(cx
, hmac_computed
, &bytes_hashed
,
3071 HMAC_Destroy(cx
, PR_TRUE
);
3073 return( hmac_status
);
3077 * Perform the HMAC Tests.
3079 * reqfn is the pathname of the input REQUEST file.
3081 * The output RESPONSE file is written to stdout.
3083 void hmac_test(char *reqfn
)
3086 size_t bufSize
= 288; /* MAX buffer size */
3087 char *buf
= NULL
; /* holds one line from the input REQUEST file.*/
3088 unsigned int keyLen
; /* Key Length */
3089 unsigned char key
[140]; /* key MAX size = 140 */
3090 unsigned int msgLen
= 128; /* the length of the input */
3091 /* Message is always 128 Bytes */
3092 unsigned char *msg
= NULL
; /* holds the message to digest.*/
3093 unsigned int HMACLen
; /* the length of the HMAC Bytes */
3094 unsigned char HMAC
[HASH_LENGTH_MAX
]; /* computed HMAC */
3095 HASH_HashType hash_alg
; /* HMAC type */
3097 FILE *req
= NULL
; /* input stream from the REQUEST file */
3098 FILE *resp
; /* output stream to the RESPONSE file */
3100 buf
= PORT_ZAlloc(bufSize
);
3104 msg
= PORT_ZAlloc(msgLen
);
3105 memset(msg
, 0, msgLen
);
3110 req
= fopen(reqfn
, "r");
3112 while (fgets(buf
, bufSize
, req
) != NULL
) {
3114 /* a comment or blank line */
3115 if (buf
[0] == '#' || buf
[0] == '\n') {
3119 /* [L = Length of the MAC and HASH_type */
3120 if (buf
[0] == '[') {
3121 if (strncmp(&buf
[1], "L ", 1) == 0) {
3123 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3126 /* HMACLen will get reused for Tlen */
3127 HMACLen
= atoi(&buf
[i
]);
3128 /* set the HASH algorithm for HMAC */
3129 if (HMACLen
== SHA1_LENGTH
) {
3130 hash_alg
= HASH_AlgSHA1
;
3131 } else if (HMACLen
== SHA256_LENGTH
) {
3132 hash_alg
= HASH_AlgSHA256
;
3133 } else if (HMACLen
== SHA384_LENGTH
) {
3134 hash_alg
= HASH_AlgSHA384
;
3135 } else if (HMACLen
== SHA512_LENGTH
) {
3136 hash_alg
= HASH_AlgSHA512
;
3144 /* Count = test iteration number*/
3145 if (strncmp(buf
, "Count ", 5) == 0) {
3146 /* count can just be put into resp file */
3148 /* zeroize the variables for the test with this data set */
3151 memset(key
, 0, sizeof key
);
3152 memset(msg
, 0, sizeof msg
);
3153 memset(HMAC
, 0, sizeof HMAC
);
3156 /* KLen = Length of the Input Secret Key ... */
3157 if (strncmp(buf
, "Klen", 4) == 0) {
3159 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3162 keyLen
= atoi(&buf
[i
]); /* in bytes */
3166 /* key = the secret key for the key to MAC */
3167 if (strncmp(buf
, "Key", 3) == 0) {
3169 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3172 for (j
=0; j
< keyLen
; i
+=2,j
++) {
3173 hex_to_byteval(&buf
[i
], &key
[j
]);
3177 /* TLen = Length of the calculated HMAC */
3178 if (strncmp(buf
, "Tlen", 4) == 0) {
3180 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3183 HMACLen
= atoi(&buf
[i
]); /* in bytes */
3187 /* MSG = to HMAC always 128 bytes for these tests */
3188 if (strncmp(buf
, "Msg", 3) == 0) {
3190 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3193 for (j
=0; j
< msgLen
; i
+=2,j
++) {
3194 hex_to_byteval(&buf
[i
], &msg
[j
]);
3197 /* calculate the HMAC and output */
3198 if (hmac_calc(HMAC
, HMACLen
, key
, keyLen
,
3199 msg
, msgLen
, hash_alg
) != SECSuccess
) {
3202 fputs("MAC = ", resp
);
3203 to_hex_str(buf
, HMAC
, HMACLen
);
3214 PORT_ZFree(buf
, bufSize
);
3217 PORT_ZFree(msg
, msgLen
);
3222 * Perform the DSA Key Pair Generation Test.
3224 * reqfn is the pathname of the REQUEST file.
3226 * The output RESPONSE file is written to stdout.
3229 dsa_keypair_test(char *reqfn
)
3231 char buf
[260]; /* holds one line from the input REQUEST file
3232 * or to the output RESPONSE file.
3233 * 257 to hold (128 public key (x2 for HEX) + 1'\n'
3235 FILE *dsareq
; /* input stream from the REQUEST file */
3236 FILE *dsaresp
; /* output stream to the RESPONSE file */
3237 int N
; /* number of time to generate key pair */
3240 PQGParams
*pqg
= NULL
;
3241 PQGVerify
*vfy
= NULL
;
3242 int keySizeIndex
; /* index for valid key sizes */
3244 dsareq
= fopen(reqfn
, "r");
3246 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
3247 /* a comment or blank line */
3248 if (buf
[0] == '#' || buf
[0] == '\n') {
3249 fputs(buf
, dsaresp
);
3254 if (buf
[0] == '[') {
3256 PQG_DestroyParams(pqg
);
3260 PQG_DestroyVerify(vfy
);
3264 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
3267 fputs(buf
, dsaresp
);
3268 fputc('\n', dsaresp
);
3270 /*****************************************************************
3271 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
3272 * that points to a valid key size.
3274 keySizeIndex
= PQG_PBITS_TO_INDEX(modulus
);
3275 if(keySizeIndex
== -1 || modulus
<512 || modulus
>1024) {
3277 "DSA key size must be a multiple of 64 between 512 "
3278 "and 1024, inclusive");
3282 /* Generate the parameters P, Q, and G */
3283 if (PQG_ParamGenSeedLen(keySizeIndex
, PQG_TEST_SEED_BYTES
,
3284 &pqg
, &vfy
) != SECSuccess
) {
3285 fprintf(dsaresp
, "ERROR: Unable to generate PQG parameters");
3289 /* output P, Q, and G */
3290 to_hex_str(buf
, pqg
->prime
.data
, pqg
->prime
.len
);
3291 fprintf(dsaresp
, "P = %s\n", buf
);
3292 to_hex_str(buf
, pqg
->subPrime
.data
, pqg
->subPrime
.len
);
3293 fprintf(dsaresp
, "Q = %s\n", buf
);
3294 to_hex_str(buf
, pqg
->base
.data
, pqg
->base
.len
);
3295 fprintf(dsaresp
, "G = %s\n\n", buf
);
3299 if (buf
[0] == 'N') {
3301 if (sscanf(buf
, "N = %d", &N
) != 1) {
3304 /* Generate a DSA key, and output the key pair for N times */
3305 for (i
= 0; i
< N
; i
++) {
3306 DSAPrivateKey
*dsakey
= NULL
;
3307 if (DSA_NewKey(pqg
, &dsakey
) != SECSuccess
) {
3308 fprintf(dsaresp
, "ERROR: Unable to generate DSA key");
3311 to_hex_str(buf
, dsakey
->privateValue
.data
,
3312 dsakey
->privateValue
.len
);
3313 fprintf(dsaresp
, "X = %s\n", buf
);
3314 to_hex_str(buf
, dsakey
->publicValue
.data
,
3315 dsakey
->publicValue
.len
);
3316 fprintf(dsaresp
, "Y = %s\n\n", buf
);
3317 PORT_FreeArena(dsakey
->params
.arena
, PR_TRUE
);
3329 * Perform the DSA Domain Parameter Validation Test.
3331 * reqfn is the pathname of the REQUEST file.
3333 * The output RESPONSE file is written to stdout.
3336 dsa_pqgver_test(char *reqfn
)
3338 char buf
[263]; /* holds one line from the input REQUEST file
3339 * or to the output RESPONSE file.
3340 * 260 to hold (128 public key (x2 for HEX) + P = ...
3342 FILE *dsareq
; /* input stream from the REQUEST file */
3343 FILE *dsaresp
; /* output stream to the RESPONSE file */
3348 unsigned int pghSize
; /* size for p, g, and h */
3350 dsareq
= fopen(reqfn
, "r");
3352 memset(&pqg
, 0, sizeof(pqg
));
3353 memset(&vfy
, 0, sizeof(vfy
));
3355 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
3356 /* a comment or blank line */
3357 if (buf
[0] == '#' || buf
[0] == '\n') {
3358 fputs(buf
, dsaresp
);
3363 if (buf
[0] == '[') {
3365 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
3369 if (pqg
.prime
.data
) { /* P */
3370 SECITEM_ZfreeItem(&pqg
.prime
, PR_FALSE
);
3372 if (pqg
.subPrime
.data
) { /* Q */
3373 SECITEM_ZfreeItem(&pqg
.subPrime
, PR_FALSE
);
3375 if (pqg
.base
.data
) { /* G */
3376 SECITEM_ZfreeItem(&pqg
.base
, PR_FALSE
);
3378 if (vfy
.seed
.data
) { /* seed */
3379 SECITEM_ZfreeItem(&vfy
.seed
, PR_FALSE
);
3381 if (vfy
.h
.data
) { /* H */
3382 SECITEM_ZfreeItem(&vfy
.h
, PR_FALSE
);
3385 fputs(buf
, dsaresp
);
3387 /*calculate the size of p, g, and h then allocate items */
3388 pghSize
= modulus
/8;
3389 SECITEM_AllocItem(NULL
, &pqg
.prime
, pghSize
);
3390 SECITEM_AllocItem(NULL
, &pqg
.base
, pghSize
);
3391 SECITEM_AllocItem(NULL
, &vfy
.h
, pghSize
);
3392 pqg
.prime
.len
= pqg
.base
.len
= vfy
.h
.len
= pghSize
;
3393 /* seed and q are always 20 bytes */
3394 SECITEM_AllocItem(NULL
, &vfy
.seed
, 20);
3395 SECITEM_AllocItem(NULL
, &pqg
.subPrime
, 20);
3396 vfy
.seed
.len
= pqg
.subPrime
.len
= 20;
3402 if (buf
[0] == 'P') {
3404 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3407 for (j
=0; j
< pqg
.prime
.len
; i
+=2,j
++) {
3408 hex_to_byteval(&buf
[i
], &pqg
.prime
.data
[j
]);
3411 fputs(buf
, dsaresp
);
3416 if (buf
[0] == 'Q') {
3418 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3421 for (j
=0; j
< pqg
.subPrime
.len
; i
+=2,j
++) {
3422 hex_to_byteval(&buf
[i
], &pqg
.subPrime
.data
[j
]);
3425 fputs(buf
, dsaresp
);
3430 if (buf
[0] == 'G') {
3432 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3435 for (j
=0; j
< pqg
.base
.len
; i
+=2,j
++) {
3436 hex_to_byteval(&buf
[i
], &pqg
.base
.data
[j
]);
3439 fputs(buf
, dsaresp
);
3444 if (strncmp(buf
, "Seed", 4) == 0) {
3446 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3449 for (j
=0; j
< vfy
.seed
.len
; i
+=2,j
++) {
3450 hex_to_byteval(&buf
[i
], &vfy
.seed
.data
[j
]);
3453 fputs(buf
, dsaresp
);
3458 if (buf
[0] == 'c') {
3460 if (sscanf(buf
, "c = %u", &vfy
.counter
) != 1) {
3464 fputs(buf
, dsaresp
);
3469 if (buf
[0] == 'H') {
3470 SECStatus rv
, result
= SECFailure
;
3473 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3476 for (j
=0; j
< vfy
.h
.len
; i
+=2,j
++) {
3477 hex_to_byteval(&buf
[i
], &vfy
.h
.data
[j
]);
3479 fputs(buf
, dsaresp
);
3481 /* Verify the Parameters */
3482 rv
= PQG_VerifyParams(&pqg
, &vfy
, &result
);
3483 if (rv
!= SECSuccess
) {
3486 if (result
== SECSuccess
) {
3487 fprintf(dsaresp
, "Result = P\n");
3489 fprintf(dsaresp
, "Result = F\n");
3496 if (pqg
.prime
.data
) { /* P */
3497 SECITEM_ZfreeItem(&pqg
.prime
, PR_FALSE
);
3499 if (pqg
.subPrime
.data
) { /* Q */
3500 SECITEM_ZfreeItem(&pqg
.subPrime
, PR_FALSE
);
3502 if (pqg
.base
.data
) { /* G */
3503 SECITEM_ZfreeItem(&pqg
.base
, PR_FALSE
);
3505 if (vfy
.seed
.data
) { /* seed */
3506 SECITEM_ZfreeItem(&vfy
.seed
, PR_FALSE
);
3508 if (vfy
.h
.data
) { /* H */
3509 SECITEM_ZfreeItem(&vfy
.h
, PR_FALSE
);
3515 * Perform the DSA Public Key Validation Test.
3517 * reqfn is the pathname of the REQUEST file.
3519 * The output RESPONSE file is written to stdout.
3522 dsa_pqggen_test(char *reqfn
)
3524 char buf
[263]; /* holds one line from the input REQUEST file
3525 * or to the output RESPONSE file.
3526 * 263 to hold seed = (128 public key (x2 for HEX)
3528 FILE *dsareq
; /* input stream from the REQUEST file */
3529 FILE *dsaresp
; /* output stream to the RESPONSE file */
3530 int N
; /* number of times to generate parameters */
3534 PQGParams
*pqg
= NULL
;
3535 PQGVerify
*vfy
= NULL
;
3536 unsigned int keySizeIndex
;
3538 dsareq
= fopen(reqfn
, "r");
3540 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
3541 /* a comment or blank line */
3542 if (buf
[0] == '#' || buf
[0] == '\n') {
3543 fputs(buf
, dsaresp
);
3548 if (buf
[0] == '[') {
3550 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
3554 fputs(buf
, dsaresp
);
3555 fputc('\n', dsaresp
);
3557 /****************************************************************
3558 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
3559 * that points to a valid key size.
3561 keySizeIndex
= PQG_PBITS_TO_INDEX(modulus
);
3562 if(keySizeIndex
== -1 || modulus
<512 || modulus
>1024) {
3564 "DSA key size must be a multiple of 64 between 512 "
3565 "and 1024, inclusive");
3572 if (buf
[0] == 'N') {
3574 if (sscanf(buf
, "N = %d", &N
) != 1) {
3577 for (i
= 0; i
< N
; i
++) {
3578 if (PQG_ParamGenSeedLen(keySizeIndex
, PQG_TEST_SEED_BYTES
,
3579 &pqg
, &vfy
) != SECSuccess
) {
3581 "ERROR: Unable to generate PQG parameters");
3584 to_hex_str(buf
, pqg
->prime
.data
, pqg
->prime
.len
);
3585 fprintf(dsaresp
, "P = %s\n", buf
);
3586 to_hex_str(buf
, pqg
->subPrime
.data
, pqg
->subPrime
.len
);
3587 fprintf(dsaresp
, "Q = %s\n", buf
);
3588 to_hex_str(buf
, pqg
->base
.data
, pqg
->base
.len
);
3589 fprintf(dsaresp
, "G = %s\n", buf
);
3590 to_hex_str(buf
, vfy
->seed
.data
, vfy
->seed
.len
);
3591 fprintf(dsaresp
, "Seed = %s\n", buf
);
3592 fprintf(dsaresp
, "c = %d\n", vfy
->counter
);
3593 to_hex_str(buf
, vfy
->h
.data
, vfy
->h
.len
);
3594 fputs("H = ", dsaresp
);
3595 for (j
=vfy
->h
.len
; j
<pqg
->prime
.len
; j
++) {
3596 fprintf(dsaresp
, "00");
3598 fprintf(dsaresp
, "%s\n", buf
);
3599 fputc('\n', dsaresp
);
3601 PQG_DestroyParams(pqg
);
3605 PQG_DestroyVerify(vfy
);
3617 PQG_DestroyParams(pqg
);
3620 PQG_DestroyVerify(vfy
);
3625 * Perform the DSA Signature Generation Test.
3627 * reqfn is the pathname of the REQUEST file.
3629 * The output RESPONSE file is written to stdout.
3632 dsa_siggen_test(char *reqfn
)
3634 char buf
[263]; /* holds one line from the input REQUEST file
3635 * or to the output RESPONSE file.
3636 * max for Msg = ....
3638 FILE *dsareq
; /* input stream from the REQUEST file */
3639 FILE *dsaresp
; /* output stream to the RESPONSE file */
3642 PQGParams
*pqg
= NULL
;
3643 PQGVerify
*vfy
= NULL
;
3644 DSAPrivateKey
*dsakey
= NULL
;
3645 int keySizeIndex
; /* index for valid key sizes */
3646 unsigned char sha1
[20]; /* SHA-1 hash (160 bits) */
3647 unsigned char sig
[DSA_SIGNATURE_LEN
];
3648 SECItem digest
, signature
;
3650 dsareq
= fopen(reqfn
, "r");
3653 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
3654 /* a comment or blank line */
3655 if (buf
[0] == '#' || buf
[0] == '\n') {
3656 fputs(buf
, dsaresp
);
3661 if (buf
[0] == '[') {
3663 PQG_DestroyParams(pqg
);
3667 PQG_DestroyVerify(vfy
);
3670 if (dsakey
!= NULL
) {
3671 PORT_FreeArena(dsakey
->params
.arena
, PR_TRUE
);
3675 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
3678 fputs(buf
, dsaresp
);
3679 fputc('\n', dsaresp
);
3681 /****************************************************************
3682 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
3683 * that points to a valid key size.
3685 keySizeIndex
= PQG_PBITS_TO_INDEX(modulus
);
3686 if(keySizeIndex
== -1 || modulus
<512 || modulus
>1024) {
3688 "DSA key size must be a multiple of 64 between 512 "
3689 "and 1024, inclusive");
3693 /* Generate PQG and output PQG */
3694 if (PQG_ParamGenSeedLen(keySizeIndex
, PQG_TEST_SEED_BYTES
,
3695 &pqg
, &vfy
) != SECSuccess
) {
3696 fprintf(dsaresp
, "ERROR: Unable to generate PQG parameters");
3699 to_hex_str(buf
, pqg
->prime
.data
, pqg
->prime
.len
);
3700 fprintf(dsaresp
, "P = %s\n", buf
);
3701 to_hex_str(buf
, pqg
->subPrime
.data
, pqg
->subPrime
.len
);
3702 fprintf(dsaresp
, "Q = %s\n", buf
);
3703 to_hex_str(buf
, pqg
->base
.data
, pqg
->base
.len
);
3704 fprintf(dsaresp
, "G = %s\n", buf
);
3706 /* create DSA Key */
3707 if (DSA_NewKey(pqg
, &dsakey
) != SECSuccess
) {
3708 fprintf(dsaresp
, "ERROR: Unable to generate DSA key");
3715 if (strncmp(buf
, "Msg", 3) == 0) {
3716 unsigned char msg
[128]; /* MAX msg 128 */
3717 unsigned int len
= 0;
3719 memset(sha1
, 0, sizeof sha1
);
3720 memset(sig
, 0, sizeof sig
);
3723 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3726 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
3727 hex_to_byteval(&buf
[i
], &msg
[j
]);
3729 if (SHA1_HashBuf(sha1
, msg
, j
) != SECSuccess
) {
3730 fprintf(dsaresp
, "ERROR: Unable to generate SHA1 digest");
3734 digest
.type
= siBuffer
;
3736 digest
.len
= sizeof sha1
;
3737 signature
.type
= siBuffer
;
3738 signature
.data
= sig
;
3739 signature
.len
= sizeof sig
;
3741 if (DSA_SignDigest(dsakey
, &signature
, &digest
) != SECSuccess
) {
3742 fprintf(dsaresp
, "ERROR: Unable to generate DSA signature");
3745 len
= signature
.len
;
3751 /* output the orginal Msg, and generated Y, R, and S */
3752 fputs(buf
, dsaresp
);
3753 fputc('\n', dsaresp
);
3754 to_hex_str(buf
, dsakey
->publicValue
.data
,
3755 dsakey
->publicValue
.len
);
3756 fprintf(dsaresp
, "Y = %s\n", buf
);
3757 to_hex_str(buf
, &signature
.data
[0], len
);
3758 fprintf(dsaresp
, "R = %s\n", buf
);
3759 to_hex_str(buf
, &signature
.data
[len
], len
);
3760 fprintf(dsaresp
, "S = %s\n", buf
);
3768 PQG_DestroyParams(pqg
);
3772 PQG_DestroyVerify(vfy
);
3776 PORT_FreeArena(dsakey
->params
.arena
, PR_TRUE
);
3782 * Perform the DSA Signature Verification Test.
3784 * reqfn is the pathname of the REQUEST file.
3786 * The output RESPONSE file is written to stdout.
3789 dsa_sigver_test(char *reqfn
)
3791 char buf
[263]; /* holds one line from the input REQUEST file
3792 * or to the output RESPONSE file.
3793 * max for Msg = ....
3795 FILE *dsareq
; /* input stream from the REQUEST file */
3796 FILE *dsaresp
; /* output stream to the RESPONSE file */
3799 SECItem digest
, signature
;
3800 DSAPublicKey pubkey
;
3801 unsigned int pgySize
; /* size for p, g, and y */
3802 unsigned char sha1
[20]; /* SHA-1 hash (160 bits) */
3803 unsigned char sig
[DSA_SIGNATURE_LEN
];
3805 dsareq
= fopen(reqfn
, "r");
3807 memset(&pubkey
, 0, sizeof(pubkey
));
3809 while (fgets(buf
, sizeof buf
, dsareq
) != NULL
) {
3810 /* a comment or blank line */
3811 if (buf
[0] == '#' || buf
[0] == '\n') {
3812 fputs(buf
, dsaresp
);
3817 if (buf
[0] == '[') {
3819 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
3823 if (pubkey
.params
.prime
.data
) { /* P */
3824 SECITEM_ZfreeItem(&pubkey
.params
.prime
, PR_FALSE
);
3826 if (pubkey
.params
.subPrime
.data
) { /* Q */
3827 SECITEM_ZfreeItem(&pubkey
.params
.subPrime
, PR_FALSE
);
3829 if (pubkey
.params
.base
.data
) { /* G */
3830 SECITEM_ZfreeItem(&pubkey
.params
.base
, PR_FALSE
);
3832 if (pubkey
.publicValue
.data
) { /* Y */
3833 SECITEM_ZfreeItem(&pubkey
.publicValue
, PR_FALSE
);
3835 fputs(buf
, dsaresp
);
3837 /* calculate the size of p, g, and y then allocate items */
3838 pgySize
= modulus
/8;
3839 SECITEM_AllocItem(NULL
, &pubkey
.params
.prime
, pgySize
);
3840 SECITEM_AllocItem(NULL
, &pubkey
.params
.base
, pgySize
);
3841 SECITEM_AllocItem(NULL
, &pubkey
.publicValue
, pgySize
);
3842 pubkey
.params
.prime
.len
= pubkey
.params
.base
.len
= pgySize
;
3843 pubkey
.publicValue
.len
= pgySize
;
3845 /* q always 20 bytes */
3846 SECITEM_AllocItem(NULL
, &pubkey
.params
.subPrime
, 20);
3847 pubkey
.params
.subPrime
.len
= 20;
3852 if (buf
[0] == 'P') {
3854 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3857 memset(pubkey
.params
.prime
.data
, 0, pubkey
.params
.prime
.len
);
3858 for (j
=0; j
< pubkey
.params
.prime
.len
; i
+=2,j
++) {
3859 hex_to_byteval(&buf
[i
], &pubkey
.params
.prime
.data
[j
]);
3862 fputs(buf
, dsaresp
);
3867 if (buf
[0] == 'Q') {
3869 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3872 memset(pubkey
.params
.subPrime
.data
, 0, pubkey
.params
.subPrime
.len
);
3873 for (j
=0; j
< pubkey
.params
.subPrime
.len
; i
+=2,j
++) {
3874 hex_to_byteval(&buf
[i
], &pubkey
.params
.subPrime
.data
[j
]);
3877 fputs(buf
, dsaresp
);
3882 if (buf
[0] == 'G') {
3884 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3887 memset(pubkey
.params
.base
.data
, 0, pubkey
.params
.base
.len
);
3888 for (j
=0; j
< pubkey
.params
.base
.len
; i
+=2,j
++) {
3889 hex_to_byteval(&buf
[i
], &pubkey
.params
.base
.data
[j
]);
3892 fputs(buf
, dsaresp
);
3897 if (strncmp(buf
, "Msg", 3) == 0) {
3898 unsigned char msg
[128]; /* MAX msg 128 */
3899 memset(sha1
, 0, sizeof sha1
);
3902 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3905 for (j
=0; isxdigit(buf
[i
]); i
+=2,j
++) {
3906 hex_to_byteval(&buf
[i
], &msg
[j
]);
3908 if (SHA1_HashBuf(sha1
, msg
, j
) != SECSuccess
) {
3909 fprintf(dsaresp
, "ERROR: Unable to generate SHA1 digest");
3913 fputs(buf
, dsaresp
);
3918 if (buf
[0] == 'Y') {
3920 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3923 memset(pubkey
.publicValue
.data
, 0, pubkey
.params
.subPrime
.len
);
3924 for (j
=0; j
< pubkey
.publicValue
.len
; i
+=2,j
++) {
3925 hex_to_byteval(&buf
[i
], &pubkey
.publicValue
.data
[j
]);
3928 fputs(buf
, dsaresp
);
3933 if (buf
[0] == 'R') {
3934 memset(sig
, 0, sizeof sig
);
3936 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3939 for (j
=0; j
< DSA_SUBPRIME_LEN
; i
+=2,j
++) {
3940 hex_to_byteval(&buf
[i
], &sig
[j
]);
3943 fputs(buf
, dsaresp
);
3948 if (buf
[0] == 'S') {
3950 while (isspace(buf
[i
]) || buf
[i
] == '=') {
3953 for (j
=DSA_SUBPRIME_LEN
; j
< DSA_SIGNATURE_LEN
; i
+=2,j
++) {
3954 hex_to_byteval(&buf
[i
], &sig
[j
]);
3956 fputs(buf
, dsaresp
);
3958 digest
.type
= siBuffer
;
3960 digest
.len
= sizeof sha1
;
3961 signature
.type
= siBuffer
;
3962 signature
.data
= sig
;
3963 signature
.len
= sizeof sig
;
3965 if (DSA_VerifyDigest(&pubkey
, &signature
, &digest
) == SECSuccess
) {
3966 fprintf(dsaresp
, "Result = P\n");
3968 fprintf(dsaresp
, "Result = F\n");
3975 if (pubkey
.params
.prime
.data
) { /* P */
3976 SECITEM_ZfreeItem(&pubkey
.params
.prime
, PR_FALSE
);
3978 if (pubkey
.params
.subPrime
.data
) { /* Q */
3979 SECITEM_ZfreeItem(&pubkey
.params
.subPrime
, PR_FALSE
);
3981 if (pubkey
.params
.base
.data
) { /* G */
3982 SECITEM_ZfreeItem(&pubkey
.params
.base
, PR_FALSE
);
3984 if (pubkey
.publicValue
.data
) { /* Y */
3985 SECITEM_ZfreeItem(&pubkey
.publicValue
, PR_FALSE
);
3990 * Perform the RSA Signature Generation Test.
3992 * reqfn is the pathname of the REQUEST file.
3994 * The output RESPONSE file is written to stdout.
3997 rsa_siggen_test(char *reqfn
)
3999 char buf
[2*RSA_MAX_TEST_MODULUS_BYTES
+1];
4000 /* buf holds one line from the input REQUEST file
4001 * or to the output RESPONSE file.
4002 * 2x for HEX output + 1 for \n
4004 FILE *rsareq
; /* input stream from the REQUEST file */
4005 FILE *rsaresp
; /* output stream to the RESPONSE file */
4007 unsigned char sha
[HASH_LENGTH_MAX
]; /* SHA digest */
4008 unsigned int shaLength
= 0; /* length of SHA */
4009 HASH_HashType shaAlg
= HASH_AlgNULL
; /* type of SHA Alg */
4010 SECOidTag shaOid
= SEC_OID_UNKNOWN
;
4011 int modulus
; /* the Modulus size */
4012 int publicExponent
= DEFAULT_RSA_PUBLIC_EXPONENT
;
4013 SECItem pe
= {0, 0, 0 };
4014 unsigned char pubEx
[4];
4017 RSAPrivateKey
*rsaBlapiPrivKey
= NULL
; /* holds RSA private and
4019 RSAPublicKey
*rsaBlapiPublicKey
= NULL
; /* hold RSA public key */
4021 rsareq
= fopen(reqfn
, "r");
4024 /* calculate the exponent */
4025 for (i
=0; i
< 4; i
++) {
4026 if (peCount
|| (publicExponent
&
4027 ((unsigned long)0xff000000L
>> (i
*8)))) {
4029 (unsigned char)((publicExponent
>> (3-i
)*8) & 0xff);
4034 pe
.data
= &pubEx
[0];
4037 while (fgets(buf
, sizeof buf
, rsareq
) != NULL
) {
4038 /* a comment or blank line */
4039 if (buf
[0] == '#' || buf
[0] == '\n') {
4040 fputs(buf
, rsaresp
);
4045 if (buf
[0] == '[') {
4047 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
4050 if (modulus
> RSA_MAX_TEST_MODULUS_BITS
) {
4051 fprintf(rsaresp
,"ERROR: modulus greater than test maximum\n");
4055 fputs(buf
, rsaresp
);
4057 if (rsaBlapiPrivKey
!= NULL
) {
4058 PORT_FreeArena(rsaBlapiPrivKey
->arena
, PR_TRUE
);
4059 rsaBlapiPrivKey
= NULL
;
4060 rsaBlapiPublicKey
= NULL
;
4063 rsaBlapiPrivKey
= RSA_NewKey(modulus
, &pe
);
4064 if (rsaBlapiPrivKey
== NULL
) {
4065 fprintf(rsaresp
, "Error unable to create RSA key\n");
4069 to_hex_str(buf
, rsaBlapiPrivKey
->modulus
.data
,
4070 rsaBlapiPrivKey
->modulus
.len
);
4071 fprintf(rsaresp
, "\nn = %s\n\n", buf
);
4072 to_hex_str(buf
, rsaBlapiPrivKey
->publicExponent
.data
,
4073 rsaBlapiPrivKey
->publicExponent
.len
);
4074 fprintf(rsaresp
, "e = %s\n", buf
);
4075 /* convert private key to public key. Memory
4076 * is freed with private key's arena */
4077 rsaBlapiPublicKey
= (RSAPublicKey
*)PORT_ArenaAlloc(
4078 rsaBlapiPrivKey
->arena
,
4079 sizeof(RSAPublicKey
));
4081 rsaBlapiPublicKey
->modulus
.len
= rsaBlapiPrivKey
->modulus
.len
;
4082 rsaBlapiPublicKey
->modulus
.data
= rsaBlapiPrivKey
->modulus
.data
;
4083 rsaBlapiPublicKey
->publicExponent
.len
=
4084 rsaBlapiPrivKey
->publicExponent
.len
;
4085 rsaBlapiPublicKey
->publicExponent
.data
=
4086 rsaBlapiPrivKey
->publicExponent
.data
;
4091 if (strncmp(buf
, "SHAAlg", 6) == 0) {
4093 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4096 /* set the SHA Algorithm */
4097 if (strncmp(&buf
[i
], "SHA1", 4) == 0) {
4098 shaAlg
= HASH_AlgSHA1
;
4099 } else if (strncmp(&buf
[i
], "SHA256", 6) == 0) {
4100 shaAlg
= HASH_AlgSHA256
;
4101 } else if (strncmp(&buf
[i
], "SHA384", 6)== 0) {
4102 shaAlg
= HASH_AlgSHA384
;
4103 } else if (strncmp(&buf
[i
], "SHA512", 6) == 0) {
4104 shaAlg
= HASH_AlgSHA512
;
4106 fprintf(rsaresp
, "ERROR: Unable to find SHAAlg type");
4109 fputs(buf
, rsaresp
);
4114 if (strncmp(buf
, "Msg", 3) == 0) {
4116 unsigned char msg
[128]; /* MAX msg 128 */
4117 unsigned int rsa_bytes_signed
;
4118 unsigned char rsa_computed_signature
[RSA_MAX_TEST_MODULUS_BYTES
];
4119 SECStatus rv
= SECFailure
;
4120 NSSLOWKEYPublicKey
* rsa_public_key
;
4121 NSSLOWKEYPrivateKey
* rsa_private_key
;
4122 NSSLOWKEYPrivateKey low_RSA_private_key
= { NULL
,
4124 NSSLOWKEYPublicKey low_RSA_public_key
= { NULL
,
4127 low_RSA_private_key
.u
.rsa
= *rsaBlapiPrivKey
;
4128 low_RSA_public_key
.u
.rsa
= *rsaBlapiPublicKey
;
4130 rsa_private_key
= &low_RSA_private_key
;
4131 rsa_public_key
= &low_RSA_public_key
;
4133 memset(sha
, 0, sizeof sha
);
4134 memset(msg
, 0, sizeof msg
);
4135 rsa_bytes_signed
= 0;
4136 memset(rsa_computed_signature
, 0, sizeof rsa_computed_signature
);
4139 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4142 for (j
=0; isxdigit(buf
[i
]) && j
< sizeof(msg
); i
+=2,j
++) {
4143 hex_to_byteval(&buf
[i
], &msg
[j
]);
4146 if (shaAlg
== HASH_AlgSHA1
) {
4147 if (SHA1_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4148 fprintf(rsaresp
, "ERROR: Unable to generate SHA1");
4151 shaLength
= SHA1_LENGTH
;
4152 shaOid
= SEC_OID_SHA1
;
4153 } else if (shaAlg
== HASH_AlgSHA256
) {
4154 if (SHA256_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4155 fprintf(rsaresp
, "ERROR: Unable to generate SHA256");
4158 shaLength
= SHA256_LENGTH
;
4159 shaOid
= SEC_OID_SHA256
;
4160 } else if (shaAlg
== HASH_AlgSHA384
) {
4161 if (SHA384_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4162 fprintf(rsaresp
, "ERROR: Unable to generate SHA384");
4165 shaLength
= SHA384_LENGTH
;
4166 shaOid
= SEC_OID_SHA384
;
4167 } else if (shaAlg
== HASH_AlgSHA512
) {
4168 if (SHA512_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4169 fprintf(rsaresp
, "ERROR: Unable to generate SHA512");
4172 shaLength
= SHA512_LENGTH
;
4173 shaOid
= SEC_OID_SHA512
;
4175 fprintf(rsaresp
, "ERROR: SHAAlg not defined.");
4179 /* Perform RSA signature with the RSA private key. */
4180 rv
= RSA_HashSign( shaOid
,
4182 rsa_computed_signature
,
4184 nsslowkey_PrivateModulusLen(rsa_private_key
),
4188 if( rv
!= SECSuccess
) {
4189 fprintf(rsaresp
, "ERROR: RSA_HashSign failed");
4193 /* Output the signature */
4194 fputs(buf
, rsaresp
);
4195 to_hex_str(buf
, rsa_computed_signature
, rsa_bytes_signed
);
4196 fprintf(rsaresp
, "S = %s\n", buf
);
4198 /* Perform RSA verification with the RSA public key. */
4199 rv
= RSA_HashCheckSign( shaOid
,
4201 rsa_computed_signature
,
4205 if( rv
!= SECSuccess
) {
4206 fprintf(rsaresp
, "ERROR: RSA_HashCheckSign failed");
4215 if (rsaBlapiPrivKey
!= NULL
) {
4216 /* frees private and public key */
4217 PORT_FreeArena(rsaBlapiPrivKey
->arena
, PR_TRUE
);
4218 rsaBlapiPrivKey
= NULL
;
4219 rsaBlapiPublicKey
= NULL
;
4224 * Perform the RSA Signature Verification Test.
4226 * reqfn is the pathname of the REQUEST file.
4228 * The output RESPONSE file is written to stdout.
4231 rsa_sigver_test(char *reqfn
)
4233 char buf
[2*RSA_MAX_TEST_MODULUS_BYTES
+7];
4234 /* buf holds one line from the input REQUEST file
4235 * or to the output RESPONSE file.
4236 * s = 2x for HEX output + 1 for \n
4238 FILE *rsareq
; /* input stream from the REQUEST file */
4239 FILE *rsaresp
; /* output stream to the RESPONSE file */
4241 unsigned char sha
[HASH_LENGTH_MAX
]; /* SHA digest */
4242 unsigned int shaLength
= 0; /* actual length of the digest */
4243 HASH_HashType shaAlg
= HASH_AlgNULL
;
4244 SECOidTag shaOid
= SEC_OID_UNKNOWN
;
4245 int modulus
= 0; /* the Modulus size */
4246 unsigned char signature
[513]; /* largest signature size + '\n' */
4247 unsigned int signatureLength
= 0; /* actual length of the signature */
4248 PRBool keyvalid
= PR_TRUE
;
4250 RSAPublicKey rsaBlapiPublicKey
; /* hold RSA public key */
4252 rsareq
= fopen(reqfn
, "r");
4254 memset(&rsaBlapiPublicKey
, 0, sizeof(RSAPublicKey
));
4256 while (fgets(buf
, sizeof buf
, rsareq
) != NULL
) {
4257 /* a comment or blank line */
4258 if (buf
[0] == '#' || buf
[0] == '\n') {
4259 fputs(buf
, rsaresp
);
4264 if (buf
[0] == '[') {
4265 unsigned int flen
; /* length in bytes of the field size */
4267 if (rsaBlapiPublicKey
.modulus
.data
) { /* n */
4268 SECITEM_ZfreeItem(&rsaBlapiPublicKey
.modulus
, PR_FALSE
);
4270 if (sscanf(buf
, "[mod = %d]", &modulus
) != 1) {
4274 if (modulus
> RSA_MAX_TEST_MODULUS_BITS
) {
4275 fprintf(rsaresp
,"ERROR: modulus greater than test maximum\n");
4279 fputs(buf
, rsaresp
);
4281 signatureLength
= flen
= modulus
/8;
4283 SECITEM_AllocItem(NULL
, &rsaBlapiPublicKey
.modulus
, flen
);
4284 if (rsaBlapiPublicKey
.modulus
.data
== NULL
) {
4290 /* n = ... modulus */
4291 if (buf
[0] == 'n') {
4293 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4296 keyvalid
= from_hex_str(&rsaBlapiPublicKey
.modulus
.data
[0],
4297 rsaBlapiPublicKey
.modulus
.len
,
4301 fprintf(rsaresp
, "ERROR: rsa_sigver n not valid.\n");
4304 fputs(buf
, rsaresp
);
4309 if (strncmp(buf
, "SHAAlg", 6) == 0) {
4311 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4314 /* set the SHA Algorithm */
4315 if (strncmp(&buf
[i
], "SHA1", 4) == 0) {
4316 shaAlg
= HASH_AlgSHA1
;
4317 } else if (strncmp(&buf
[i
], "SHA256", 6) == 0) {
4318 shaAlg
= HASH_AlgSHA256
;
4319 } else if (strncmp(&buf
[i
], "SHA384", 6) == 0) {
4320 shaAlg
= HASH_AlgSHA384
;
4321 } else if (strncmp(&buf
[i
], "SHA512", 6) == 0) {
4322 shaAlg
= HASH_AlgSHA512
;
4324 fprintf(rsaresp
, "ERROR: Unable to find SHAAlg type");
4327 fputs(buf
, rsaresp
);
4331 /* e = ... public Key */
4332 if (buf
[0] == 'e') {
4333 unsigned char data
[RSA_MAX_TEST_EXPONENT_BYTES
];
4336 memset(data
, 0, sizeof data
);
4338 if (rsaBlapiPublicKey
.publicExponent
.data
) { /* e */
4339 SECITEM_ZfreeItem(&rsaBlapiPublicKey
.publicExponent
, PR_FALSE
);
4343 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4346 /* skip leading zero's */
4347 while (isxdigit(buf
[i
])) {
4348 hex_to_byteval(&buf
[i
], &t
);
4354 /* get the exponent */
4355 for (j
=0; isxdigit(buf
[i
]) && j
< sizeof data
; i
+=2,j
++) {
4356 hex_to_byteval(&buf
[i
], &data
[j
]);
4359 if (j
== 0) { j
= 1; } /* to handle 1 byte length exponents */
4361 SECITEM_AllocItem(NULL
, &rsaBlapiPublicKey
.publicExponent
, j
);
4362 if (rsaBlapiPublicKey
.publicExponent
.data
== NULL
) {
4366 for (i
=0; i
< j
; i
++) {
4367 rsaBlapiPublicKey
.publicExponent
.data
[i
] = data
[i
];
4370 fputs(buf
, rsaresp
);
4375 if (strncmp(buf
, "Msg", 3) == 0) {
4376 unsigned char msg
[128]; /* MAX msg 128 */
4378 memset(sha
, 0, sizeof sha
);
4379 memset(msg
, 0, sizeof msg
);
4382 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4386 for (j
=0; isxdigit(buf
[i
]) && j
< sizeof msg
; i
+=2,j
++) {
4387 hex_to_byteval(&buf
[i
], &msg
[j
]);
4390 if (shaAlg
== HASH_AlgSHA1
) {
4391 if (SHA1_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4392 fprintf(rsaresp
, "ERROR: Unable to generate SHA1");
4395 shaLength
= SHA1_LENGTH
;
4396 shaOid
= SEC_OID_SHA1
;
4397 } else if (shaAlg
== HASH_AlgSHA256
) {
4398 if (SHA256_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4399 fprintf(rsaresp
, "ERROR: Unable to generate SHA256");
4402 shaLength
= SHA256_LENGTH
;
4403 shaOid
= SEC_OID_SHA256
;
4404 } else if (shaAlg
== HASH_AlgSHA384
) {
4405 if (SHA384_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4406 fprintf(rsaresp
, "ERROR: Unable to generate SHA384");
4409 shaLength
= SHA384_LENGTH
;
4410 shaOid
= SEC_OID_SHA384
;
4411 } else if (shaAlg
== HASH_AlgSHA512
) {
4412 if (SHA512_HashBuf(sha
, msg
, j
) != SECSuccess
) {
4413 fprintf(rsaresp
, "ERROR: Unable to generate SHA512");
4416 shaLength
= SHA512_LENGTH
;
4417 shaOid
= SEC_OID_SHA512
;
4419 fprintf(rsaresp
, "ERROR: SHAAlg not defined.");
4423 fputs(buf
, rsaresp
);
4429 if (buf
[0] == 'S') {
4430 SECStatus rv
= SECFailure
;
4431 NSSLOWKEYPublicKey
* rsa_public_key
;
4432 NSSLOWKEYPublicKey low_RSA_public_key
= { NULL
,
4435 /* convert to a low RSA public key */
4436 low_RSA_public_key
.u
.rsa
= rsaBlapiPublicKey
;
4437 rsa_public_key
= &low_RSA_public_key
;
4439 memset(signature
, 0, sizeof(signature
));
4441 while (isspace(buf
[i
]) || buf
[i
] == '=') {
4445 for (j
=0; isxdigit(buf
[i
]) && j
< sizeof signature
; i
+=2,j
++) {
4446 hex_to_byteval(&buf
[i
], &signature
[j
]);
4449 signatureLength
= j
;
4450 fputs(buf
, rsaresp
);
4452 /* Perform RSA verification with the RSA public key. */
4453 rv
= RSA_HashCheckSign( shaOid
,
4459 if( rv
== SECSuccess
) {
4460 fputs("Result = P\n", rsaresp
);
4462 fputs("Result = F\n", rsaresp
);
4469 if (rsaBlapiPublicKey
.modulus
.data
) { /* n */
4470 SECITEM_ZfreeItem(&rsaBlapiPublicKey
.modulus
, PR_FALSE
);
4472 if (rsaBlapiPublicKey
.publicExponent
.data
) { /* e */
4473 SECITEM_ZfreeItem(&rsaBlapiPublicKey
.publicExponent
, PR_FALSE
);
4477 int main(int argc
, char **argv
)
4479 if (argc
< 2) exit (-1);
4480 NSS_NoDB_Init(NULL
);
4484 if (strcmp(argv
[1], "tdea") == 0) {
4485 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
4486 if (strcmp(argv
[2], "kat") == 0) {
4487 /* Known Answer Test (KAT) */
4488 tdea_kat_mmt(argv
[4]);
4489 } else if (strcmp(argv
[2], "mmt") == 0) {
4490 /* Multi-block Message Test (MMT) */
4491 tdea_kat_mmt(argv
[4]);
4492 } else if (strcmp(argv
[2], "mct") == 0) {
4493 /* Monte Carlo Test (MCT) */
4494 if (strcmp(argv
[3], "ecb") == 0) {
4496 tdea_mct(NSS_DES_EDE3
, argv
[4]);
4497 } else if (strcmp(argv
[3], "cbc") == 0) {
4499 tdea_mct(NSS_DES_EDE3_CBC
, argv
[4]);
4505 } else if (strcmp(argv
[1], "aes") == 0) {
4506 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
4507 if ( strcmp(argv
[2], "kat") == 0) {
4508 /* Known Answer Test (KAT) */
4509 aes_kat_mmt(argv
[4]);
4510 } else if (strcmp(argv
[2], "mmt") == 0) {
4511 /* Multi-block Message Test (MMT) */
4512 aes_kat_mmt(argv
[4]);
4513 } else if (strcmp(argv
[2], "mct") == 0) {
4514 /* Monte Carlo Test (MCT) */
4515 if ( strcmp(argv
[3], "ecb") == 0) {
4517 aes_ecb_mct(argv
[4]);
4518 } else if (strcmp(argv
[3], "cbc") == 0) {
4520 aes_cbc_mct(argv
[4]);
4526 } else if (strcmp(argv
[1], "sha") == 0) {
4531 } else if (strcmp(argv
[1], "rsa") == 0) {
4532 /* argv[2]=siggen|sigver */
4533 /* argv[3]=<test name>.req */
4534 if (strcmp(argv
[2], "siggen") == 0) {
4535 /* Signature Generation Test */
4536 rsa_siggen_test(argv
[3]);
4537 } else if (strcmp(argv
[2], "sigver") == 0) {
4538 /* Signature Verification Test */
4539 rsa_sigver_test(argv
[3]);
4544 } else if (strcmp(argv
[1], "hmac") == 0) {
4549 } else if (strcmp(argv
[1], "dsa") == 0) {
4550 /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */
4551 /* argv[3]=<test name>.req */
4552 if (strcmp(argv
[2], "keypair") == 0) {
4553 /* Key Pair Generation Test */
4554 dsa_keypair_test(argv
[3]);
4555 } else if (strcmp(argv
[2], "pqggen") == 0) {
4556 /* Domain Parameter Generation Test */
4557 dsa_pqggen_test(argv
[3]);
4558 } else if (strcmp(argv
[2], "pqgver") == 0) {
4559 /* Domain Parameter Validation Test */
4560 dsa_pqgver_test(argv
[3]);
4561 } else if (strcmp(argv
[2], "siggen") == 0) {
4562 /* Signature Generation Test */
4563 dsa_siggen_test(argv
[3]);
4564 } else if (strcmp(argv
[2], "sigver") == 0) {
4565 /* Signature Verification Test */
4566 dsa_sigver_test(argv
[3]);
4568 #ifdef NSS_ENABLE_ECC
4572 } else if (strcmp(argv
[1], "ecdsa") == 0) {
4573 /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */
4574 if ( strcmp(argv
[2], "keypair") == 0) {
4575 /* Key Pair Generation Test */
4576 ecdsa_keypair_test(argv
[3]);
4577 } else if (strcmp(argv
[2], "pkv") == 0) {
4578 /* Public Key Validation Test */
4579 ecdsa_pkv_test(argv
[3]);
4580 } else if (strcmp(argv
[2], "siggen") == 0) {
4581 /* Signature Generation Test */
4582 ecdsa_siggen_test(argv
[3]);
4583 } else if (strcmp(argv
[2], "sigver") == 0) {
4584 /* Signature Verification Test */
4585 ecdsa_sigver_test(argv
[3]);
4587 #endif /* NSS_ENABLE_ECC */
4591 } else if (strcmp(argv
[1], "rng") == 0) {
4592 /* argv[2]=vst|mct argv[3]=<test name>.req */
4593 if ( strcmp(argv
[2], "vst") == 0) {
4594 /* Variable Seed Test */
4596 } else if (strcmp(argv
[2], "mct") == 0) {
4597 /* Monte Carlo Test */