1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <ctype.h>
8 
9 #include "secitem.h"
10 #include "blapi.h"
11 #include "nssutil.h"
12 #include "secerr.h"
13 #include "secder.h"
14 #include "secdig.h"
15 #include "secoid.h"
16 #include "ec.h"
17 #include "hasht.h"
18 #include "lowkeyi.h"
19 #include "softoken.h"
20 #include "pkcs11t.h"
21 #define __PASTE(x, y) x##y
22 #undef CK_PKCS11_FUNCTION_INFO
23 #undef CK_NEED_ARG_LIST
24 #define CK_EXTERN extern
25 #define CK_PKCS11_FUNCTION_INFO(func) \
26     CK_RV __PASTE(NS, func)
27 #define CK_NEED_ARG_LIST 1
28 #include "pkcs11f.h"
29 #undef CK_PKCS11_FUNCTION_INFO
30 #undef CK_NEED_ARG_LIST
31 #undef __PASTE
32 #define SSL3_RANDOM_LENGTH 32
33 
34 #if 0
35 #include "../../lib/freebl/mpi/mpi.h"
36 #endif
37 #define MATCH_OPENSSL 1
38 /*#define MATCH_NIST 1 */
39 #ifdef MATCH_NIST
40 #define VERBOSE_REASON 1
41 #endif
42 
43 extern SECStatus
44 EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
45 extern SECStatus
46 EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
47               const ECParams *srcParams);
48 
49 #define ENCRYPT 1
50 #define DECRYPT 0
51 #define BYTE unsigned char
52 #define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001
53 #define RSA_MAX_TEST_MODULUS_BITS 4096
54 #define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS / 8
55 #define RSA_MAX_TEST_EXPONENT_BYTES 8
56 #define PQG_TEST_SEED_BYTES 20
57 
58 SECStatus
hex_to_byteval(const char * c2,unsigned char * byteval)59 hex_to_byteval(const char *c2, unsigned char *byteval)
60 {
61     int i;
62     unsigned char offset;
63     *byteval = 0;
64     for (i = 0; i < 2; i++) {
65         if (c2[i] >= '0' && c2[i] <= '9') {
66             offset = c2[i] - '0';
67             *byteval |= offset << 4 * (1 - i);
68         } else if (c2[i] >= 'a' && c2[i] <= 'f') {
69             offset = c2[i] - 'a';
70             *byteval |= (offset + 10) << 4 * (1 - i);
71         } else if (c2[i] >= 'A' && c2[i] <= 'F') {
72             offset = c2[i] - 'A';
73             *byteval |= (offset + 10) << 4 * (1 - i);
74         } else {
75             return SECFailure;
76         }
77     }
78     return SECSuccess;
79 }
80 
81 SECStatus
byteval_to_hex(unsigned char byteval,char * c2,char a)82 byteval_to_hex(unsigned char byteval, char *c2, char a)
83 {
84     int i;
85     unsigned char offset;
86     for (i = 0; i < 2; i++) {
87         offset = (byteval >> 4 * (1 - i)) & 0x0f;
88         if (offset < 10) {
89             c2[i] = '0' + offset;
90         } else {
91             c2[i] = a + offset - 10;
92         }
93     }
94     return SECSuccess;
95 }
96 
97 void
to_hex_str(char * str,const unsigned char * buf,unsigned int len)98 to_hex_str(char *str, const unsigned char *buf, unsigned int len)
99 {
100     unsigned int i;
101     for (i = 0; i < len; i++) {
102         byteval_to_hex(buf[i], &str[2 * i], 'a');
103     }
104     str[2 * len] = '\0';
105 }
106 
107 void
to_hex_str_cap(char * str,const unsigned char * buf,unsigned int len)108 to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len)
109 {
110     unsigned int i;
111     for (i = 0; i < len; i++) {
112         byteval_to_hex(buf[i], &str[2 * i], 'A');
113     }
114     str[2 * len] = '\0';
115 }
116 
117 /*
118  * Convert a string of hex digits (str) to an array (buf) of len bytes.
119  * Return PR_TRUE if the hex string can fit in the byte array.  Return
120  * PR_FALSE if the hex string is empty or is too long.
121  */
122 PRBool
from_hex_str(unsigned char * buf,unsigned int len,const char * str)123 from_hex_str(unsigned char *buf, unsigned int len, const char *str)
124 {
125     unsigned int nxdigit; /* number of hex digits in str */
126     unsigned int i;       /* index into buf */
127     unsigned int j;       /* index into str */
128 
129     /* count the hex digits */
130     nxdigit = 0;
131     for (nxdigit = 0; isxdigit(str[nxdigit]); nxdigit++) {
132         /* empty body */
133     }
134     if (nxdigit == 0) {
135         return PR_FALSE;
136     }
137     if (nxdigit > 2 * len) {
138         /*
139          * The input hex string is too long, but we allow it if the
140          * extra digits are leading 0's.
141          */
142         for (j = 0; j < nxdigit - 2 * len; j++) {
143             if (str[j] != '0') {
144                 return PR_FALSE;
145             }
146         }
147         /* skip leading 0's */
148         str += nxdigit - 2 * len;
149         nxdigit = 2 * len;
150     }
151     for (i = 0, j = 0; i < len; i++) {
152         if (2 * i < 2 * len - nxdigit) {
153             /* Handle a short input as if we padded it with leading 0's. */
154             if (2 * i + 1 < 2 * len - nxdigit) {
155                 buf[i] = 0;
156             } else {
157                 char tmp[2];
158                 tmp[0] = '0';
159                 tmp[1] = str[j];
160                 hex_to_byteval(tmp, &buf[i]);
161                 j++;
162             }
163         } else {
164             hex_to_byteval(&str[j], &buf[i]);
165             j += 2;
166         }
167     }
168     return PR_TRUE;
169 }
170 
171 SECStatus
tdea_encrypt_buf(int mode,const unsigned char * key,const unsigned char * iv,unsigned char * output,unsigned int * outputlen,unsigned int maxoutputlen,const unsigned char * input,unsigned int inputlen)172 tdea_encrypt_buf(
173     int mode,
174     const unsigned char *key,
175     const unsigned char *iv,
176     unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
177     const unsigned char *input, unsigned int inputlen)
178 {
179     SECStatus rv = SECFailure;
180     DESContext *cx;
181     unsigned char doublecheck[8 * 20]; /* 1 to 20 blocks */
182     unsigned int doublechecklen = 0;
183 
184     cx = DES_CreateContext(key, iv, mode, PR_TRUE);
185     if (cx == NULL) {
186         goto loser;
187     }
188     rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
189     if (rv != SECSuccess) {
190         goto loser;
191     }
192     if (*outputlen != inputlen) {
193         goto loser;
194     }
195     DES_DestroyContext(cx, PR_TRUE);
196     cx = NULL;
197 
198     /*
199      * Doublecheck our result by decrypting the ciphertext and
200      * compare the output with the input plaintext.
201      */
202     cx = DES_CreateContext(key, iv, mode, PR_FALSE);
203     if (cx == NULL) {
204         goto loser;
205     }
206     rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
207                      output, *outputlen);
208     if (rv != SECSuccess) {
209         goto loser;
210     }
211     if (doublechecklen != *outputlen) {
212         goto loser;
213     }
214     DES_DestroyContext(cx, PR_TRUE);
215     cx = NULL;
216     if (memcmp(doublecheck, input, inputlen) != 0) {
217         goto loser;
218     }
219     rv = SECSuccess;
220 
221 loser:
222     if (cx != NULL) {
223         DES_DestroyContext(cx, PR_TRUE);
224     }
225     return rv;
226 }
227 
228 SECStatus
tdea_decrypt_buf(int mode,const unsigned char * key,const unsigned char * iv,unsigned char * output,unsigned int * outputlen,unsigned int maxoutputlen,const unsigned char * input,unsigned int inputlen)229 tdea_decrypt_buf(
230     int mode,
231     const unsigned char *key,
232     const unsigned char *iv,
233     unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
234     const unsigned char *input, unsigned int inputlen)
235 {
236     SECStatus rv = SECFailure;
237     DESContext *cx;
238     unsigned char doublecheck[8 * 20]; /* 1 to 20 blocks */
239     unsigned int doublechecklen = 0;
240 
241     cx = DES_CreateContext(key, iv, mode, PR_FALSE);
242     if (cx == NULL) {
243         goto loser;
244     }
245     rv = DES_Decrypt(cx, output, outputlen, maxoutputlen,
246                      input, inputlen);
247     if (rv != SECSuccess) {
248         goto loser;
249     }
250     if (*outputlen != inputlen) {
251         goto loser;
252     }
253     DES_DestroyContext(cx, PR_TRUE);
254     cx = NULL;
255 
256     /*
257      * Doublecheck our result by encrypting the plaintext and
258      * compare the output with the input ciphertext.
259      */
260     cx = DES_CreateContext(key, iv, mode, PR_TRUE);
261     if (cx == NULL) {
262         goto loser;
263     }
264     rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
265                      output, *outputlen);
266     if (rv != SECSuccess) {
267         goto loser;
268     }
269     if (doublechecklen != *outputlen) {
270         goto loser;
271     }
272     DES_DestroyContext(cx, PR_TRUE);
273     cx = NULL;
274     if (memcmp(doublecheck, input, inputlen) != 0) {
275         goto loser;
276     }
277     rv = SECSuccess;
278 
279 loser:
280     if (cx != NULL) {
281         DES_DestroyContext(cx, PR_TRUE);
282     }
283     return rv;
284 }
285 
286 /*
287  * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
288  * Test (MMT) in ECB or CBC mode.  The KAT (there are five types)
289  * and MMT have the same structure: given the key and IV (CBC mode
290  * only), encrypt the given plaintext or decrypt the given ciphertext.
291  * So we can handle them the same way.
292  *
293  * reqfn is the pathname of the REQUEST file.
294  *
295  * The output RESPONSE file is written to stdout.
296  */
297 void
tdea_kat_mmt(char * reqfn)298 tdea_kat_mmt(char *reqfn)
299 {
300     char buf[180]; /* holds one line from the input REQUEST file.
301                          * needs to be large enough to hold the longest
302                          * line "CIPHERTEXT = <180 hex digits>\n".
303                          */
304     FILE *req;     /* input stream from the REQUEST file */
305     FILE *resp;    /* output stream to the RESPONSE file */
306     int i, j;
307     int mode = NSS_DES_EDE3; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
308     int crypt = DECRYPT;     /* 1 means encrypt, 0 means decrypt */
309     unsigned char key[24];   /* TDEA 3 key bundle */
310     unsigned int numKeys = 0;
311     unsigned char iv[8];             /* for all modes except ECB */
312     unsigned char plaintext[8 * 20]; /* 1 to 20 blocks */
313     unsigned int plaintextlen;
314     unsigned char ciphertext[8 * 20]; /* 1 to 20 blocks */
315     unsigned int ciphertextlen;
316     SECStatus rv;
317 
318     req = fopen(reqfn, "r");
319     resp = stdout;
320     while (fgets(buf, sizeof buf, req) != NULL) {
321         /* a comment or blank line */
322         if (buf[0] == '#' || buf[0] == '\n') {
323             fputs(buf, resp);
324             continue;
325         }
326         /* [ENCRYPT] or [DECRYPT] */
327         if (buf[0] == '[') {
328             if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
329                 crypt = ENCRYPT;
330             } else {
331                 crypt = DECRYPT;
332             }
333             fputs(buf, resp);
334             continue;
335         }
336         /* NumKeys */
337         if (strncmp(&buf[0], "NumKeys", 7) == 0) {
338             i = 7;
339             while (isspace(buf[i]) || buf[i] == '=') {
340                 i++;
341             }
342             numKeys = buf[i];
343             fputs(buf, resp);
344             continue;
345         }
346         /* "COUNT = x" begins a new data set */
347         if (strncmp(buf, "COUNT", 5) == 0) {
348             /* mode defaults to ECB, if dataset has IV mode will be set CBC */
349             mode = NSS_DES_EDE3;
350             /* zeroize the variables for the test with this data set */
351             memset(key, 0, sizeof key);
352             memset(iv, 0, sizeof iv);
353             memset(plaintext, 0, sizeof plaintext);
354             plaintextlen = 0;
355             memset(ciphertext, 0, sizeof ciphertext);
356             ciphertextlen = 0;
357             fputs(buf, resp);
358             continue;
359         }
360         if (numKeys == 0) {
361             if (strncmp(buf, "KEYs", 4) == 0) {
362                 i = 4;
363                 while (isspace(buf[i]) || buf[i] == '=') {
364                     i++;
365                 }
366                 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
367                     hex_to_byteval(&buf[i], &key[j]);
368                     key[j + 8] = key[j];
369                     key[j + 16] = key[j];
370                 }
371                 fputs(buf, resp);
372                 continue;
373             }
374         } else {
375             /* KEY1 = ... */
376             if (strncmp(buf, "KEY1", 4) == 0) {
377                 i = 4;
378                 while (isspace(buf[i]) || buf[i] == '=') {
379                     i++;
380                 }
381                 for (j = 0; isxdigit(buf[i]); i += 2, j++) {
382                     hex_to_byteval(&buf[i], &key[j]);
383                 }
384                 fputs(buf, resp);
385                 continue;
386             }
387             /* KEY2 = ... */
388             if (strncmp(buf, "KEY2", 4) == 0) {
389                 i = 4;
390                 while (isspace(buf[i]) || buf[i] == '=') {
391                     i++;
392                 }
393                 for (j = 8; isxdigit(buf[i]); i += 2, j++) {
394                     hex_to_byteval(&buf[i], &key[j]);
395                 }
396                 fputs(buf, resp);
397                 continue;
398             }
399             /* KEY3 = ... */
400             if (strncmp(buf, "KEY3", 4) == 0) {
401                 i = 4;
402                 while (isspace(buf[i]) || buf[i] == '=') {
403                     i++;
404                 }
405                 for (j = 16; isxdigit(buf[i]); i += 2, j++) {
406                     hex_to_byteval(&buf[i], &key[j]);
407                 }
408                 fputs(buf, resp);
409                 continue;
410             }
411         }
412 
413         /* IV = ... */
414         if (strncmp(buf, "IV", 2) == 0) {
415             mode = NSS_DES_EDE3_CBC;
416             i = 2;
417             while (isspace(buf[i]) || buf[i] == '=') {
418                 i++;
419             }
420             for (j = 0; j < sizeof iv; i += 2, j++) {
421                 hex_to_byteval(&buf[i], &iv[j]);
422             }
423             fputs(buf, resp);
424             continue;
425         }
426 
427         /* PLAINTEXT = ... */
428         if (strncmp(buf, "PLAINTEXT", 9) == 0) {
429             /* sanity check */
430             if (crypt != ENCRYPT) {
431                 goto loser;
432             }
433             i = 9;
434             while (isspace(buf[i]) || buf[i] == '=') {
435                 i++;
436             }
437             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
438                 hex_to_byteval(&buf[i], &plaintext[j]);
439             }
440             plaintextlen = j;
441             rv = tdea_encrypt_buf(mode, key,
442                                   (mode == NSS_DES_EDE3) ? NULL : iv,
443                                   ciphertext, &ciphertextlen, sizeof ciphertext,
444                                   plaintext, plaintextlen);
445             if (rv != SECSuccess) {
446                 goto loser;
447             }
448 
449             fputs(buf, resp);
450             fputs("CIPHERTEXT = ", resp);
451             to_hex_str(buf, ciphertext, ciphertextlen);
452             fputs(buf, resp);
453             fputc('\n', resp);
454             continue;
455         }
456         /* CIPHERTEXT = ... */
457         if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
458             /* sanity check */
459             if (crypt != DECRYPT) {
460                 goto loser;
461             }
462 
463             i = 10;
464             while (isspace(buf[i]) || buf[i] == '=') {
465                 i++;
466             }
467             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
468                 hex_to_byteval(&buf[i], &ciphertext[j]);
469             }
470             ciphertextlen = j;
471 
472             rv = tdea_decrypt_buf(mode, key,
473                                   (mode == NSS_DES_EDE3) ? NULL : iv,
474                                   plaintext, &plaintextlen, sizeof plaintext,
475                                   ciphertext, ciphertextlen);
476             if (rv != SECSuccess) {
477                 goto loser;
478             }
479 
480             fputs(buf, resp);
481             fputs("PLAINTEXT = ", resp);
482             to_hex_str(buf, plaintext, plaintextlen);
483             fputs(buf, resp);
484             fputc('\n', resp);
485             continue;
486         }
487     }
488 
489 loser:
490     fclose(req);
491 }
492 
493 /*
494 * Set the parity bit for the given byte
495 */
496 BYTE
odd_parity(BYTE in)497 odd_parity(BYTE in)
498 {
499     BYTE out = in;
500     in ^= in >> 4;
501     in ^= in >> 2;
502     in ^= in >> 1;
503     return (BYTE)(out ^ !(in & 1));
504 }
505 
506 /*
507  * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j]
508  * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
509  */
510 void
tdea_mct_next_keys(unsigned char * key,const unsigned char * text_2,const unsigned char * text_1,const unsigned char * text,unsigned int numKeys)511 tdea_mct_next_keys(unsigned char *key,
512                    const unsigned char *text_2, const unsigned char *text_1,
513                    const unsigned char *text, unsigned int numKeys)
514 {
515     int k;
516 
517     /* key1[i+1] = key1[i] xor PT/CT[j] */
518     for (k = 0; k < 8; k++) {
519         key[k] ^= text[k];
520     }
521     /* key2 */
522     if (numKeys == 2 || numKeys == 3) {
523         /* key2 independent */
524         for (k = 8; k < 16; k++) {
525             /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
526             key[k] ^= text_1[k - 8];
527         }
528     } else {
529         /* key2 == key 1 */
530         for (k = 8; k < 16; k++) {
531             /* key2[i+1] = KEY2[i] xor PT/CT[j] */
532             key[k] = key[k - 8];
533         }
534     }
535     /* key3 */
536     if (numKeys == 1 || numKeys == 2) {
537         /* key3 == key 1 */
538         for (k = 16; k < 24; k++) {
539             /* key3[i+1] = KEY3[i] xor PT/CT[j] */
540             key[k] = key[k - 16];
541         }
542     } else {
543         /* key3 independent */
544         for (k = 16; k < 24; k++) {
545             /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
546             key[k] ^= text_2[k - 16];
547         }
548     }
549     /* set the parity bits */
550     for (k = 0; k < 24; k++) {
551         key[k] = odd_parity(key[k]);
552     }
553 }
554 
555 /*
556  * Perform the Monte Carlo Test
557  *
558  * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
559  * crypt = ENCRYPT || DECRYPT
560  * inputtext = plaintext or Cyphertext depending on the value of crypt
561  * inputlength is expected to be size 8 bytes
562  * iv = needs to be set for NSS_DES_EDE3_CBC mode
563  * resp = is the output response file.
564  */
565 void
tdea_mct_test(int mode,unsigned char * key,unsigned int numKeys,unsigned int crypt,unsigned char * inputtext,unsigned int inputlength,unsigned char * iv,FILE * resp)566 tdea_mct_test(int mode, unsigned char *key, unsigned int numKeys,
567               unsigned int crypt, unsigned char *inputtext,
568               unsigned int inputlength, unsigned char *iv, FILE *resp)
569 {
570 
571     int i, j;
572     unsigned char outputtext_1[8]; /* PT/CT[j-1] */
573     unsigned char outputtext_2[8]; /* PT/CT[j-2] */
574     char buf[80];                  /* holds one line from the input REQUEST file. */
575     unsigned int outputlen;
576     unsigned char outputtext[8];
577 
578     SECStatus rv;
579 
580     if (mode == NSS_DES_EDE3 && iv != NULL) {
581         printf("IV must be NULL for NSS_DES_EDE3 mode");
582         goto loser;
583     } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) {
584         printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
585         goto loser;
586     }
587 
588     /* loop 400 times */
589     for (i = 0; i < 400; i++) {
590         /* if i == 0 CV[0] = IV  not necessary */
591         /* record the count and key values and plainText */
592         sprintf(buf, "COUNT = %d\n", i);
593         fputs(buf, resp);
594         /* Output KEY1[i] */
595         fputs("KEY1 = ", resp);
596         to_hex_str(buf, key, 8);
597         fputs(buf, resp);
598         fputc('\n', resp);
599         /* Output KEY2[i] */
600         fputs("KEY2 = ", resp);
601         to_hex_str(buf, &key[8], 8);
602         fputs(buf, resp);
603         fputc('\n', resp);
604         /* Output KEY3[i] */
605         fputs("KEY3 = ", resp);
606         to_hex_str(buf, &key[16], 8);
607         fputs(buf, resp);
608         fputc('\n', resp);
609         if (mode == NSS_DES_EDE3_CBC) {
610             /* Output CV[i] */
611             fputs("IV = ", resp);
612             to_hex_str(buf, iv, 8);
613             fputs(buf, resp);
614             fputc('\n', resp);
615         }
616         if (crypt == ENCRYPT) {
617             /* Output PT[0] */
618             fputs("PLAINTEXT = ", resp);
619         } else {
620             /* Output CT[0] */
621             fputs("CIPHERTEXT = ", resp);
622         }
623 
624         to_hex_str(buf, inputtext, inputlength);
625         fputs(buf, resp);
626         fputc('\n', resp);
627 
628         /* loop 10,000 times */
629         for (j = 0; j < 10000; j++) {
630 
631             outputlen = 0;
632             if (crypt == ENCRYPT) {
633                 /* inputtext == ciphertext outputtext == plaintext*/
634                 rv = tdea_encrypt_buf(mode, key,
635                                       (mode ==
636                                        NSS_DES_EDE3)
637                                           ? NULL
638                                           : iv,
639                                       outputtext, &outputlen, 8,
640                                       inputtext, 8);
641             } else {
642                 /* inputtext == plaintext outputtext == ciphertext */
643                 rv = tdea_decrypt_buf(mode, key,
644                                       (mode ==
645                                        NSS_DES_EDE3)
646                                           ? NULL
647                                           : iv,
648                                       outputtext, &outputlen, 8,
649                                       inputtext, 8);
650             }
651 
652             if (rv != SECSuccess) {
653                 goto loser;
654             }
655             if (outputlen != inputlength) {
656                 goto loser;
657             }
658 
659             if (mode == NSS_DES_EDE3_CBC) {
660                 if (crypt == ENCRYPT) {
661                     if (j == 0) {
662                         /*P[j+1] = CV[0] */
663                         memcpy(inputtext, iv, 8);
664                     } else {
665                         /* p[j+1] = C[j-1] */
666                         memcpy(inputtext, outputtext_1, 8);
667                     }
668                     /* CV[j+1] = C[j] */
669                     memcpy(iv, outputtext, 8);
670                     if (j != 9999) {
671                         /* save C[j-1] */
672                         memcpy(outputtext_1, outputtext, 8);
673                     }
674                 } else { /* DECRYPT */
675                     /* CV[j+1] = C[j] */
676                     memcpy(iv, inputtext, 8);
677                     /* C[j+1] = P[j] */
678                     memcpy(inputtext, outputtext, 8);
679                 }
680             } else {
681                 /* ECB mode PT/CT[j+1] = CT/PT[j] */
682                 memcpy(inputtext, outputtext, 8);
683             }
684 
685             /* Save PT/CT[j-2] and PT/CT[j-1] */
686             if (j == 9997)
687                 memcpy(outputtext_2, outputtext, 8);
688             if (j == 9998)
689                 memcpy(outputtext_1, outputtext, 8);
690             /* done at the end of the for(j) loop */
691         }
692 
693         if (crypt == ENCRYPT) {
694             /* Output CT[j] */
695             fputs("CIPHERTEXT = ", resp);
696         } else {
697             /* Output PT[j] */
698             fputs("PLAINTEXT = ", resp);
699         }
700         to_hex_str(buf, outputtext, 8);
701         fputs(buf, resp);
702         fputc('\n', resp);
703 
704         /* Key[i+1] = Key[i] xor ...  outputtext_2 == PT/CT[j-2]
705          *  outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j]
706          */
707         tdea_mct_next_keys(key, outputtext_2,
708                            outputtext_1, outputtext, numKeys);
709 
710         if (mode == NSS_DES_EDE3_CBC) {
711             /* taken care of in the j=9999 iteration */
712             if (crypt == ENCRYPT) {
713                 /* P[i] = C[j-1] */
714                 /* CV[i] = C[j] */
715             } else {
716                 /* taken care of in the j=9999 iteration */
717                 /* CV[i] = C[j] */
718                 /* C[i] = P[j]  */
719             }
720         } else {
721             /* ECB PT/CT[i] = PT/CT[j]  */
722             memcpy(inputtext, outputtext, 8);
723         }
724         /* done at the end of the for(i) loop */
725         fputc('\n', resp);
726     }
727 
728 loser:
729     return;
730 }
731 
732 /*
733  * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
734  * by gathering the input from the request file, and then
735  * calling tdea_mct_test.
736  *
737  * reqfn is the pathname of the input REQUEST file.
738  *
739  * The output RESPONSE file is written to stdout.
740  */
741 void
tdea_mct(int mode,char * reqfn)742 tdea_mct(int mode, char *reqfn)
743 {
744     int i, j;
745     char buf[80];           /* holds one line from the input REQUEST file. */
746     FILE *req;              /* input stream from the REQUEST file */
747     FILE *resp;             /* output stream to the RESPONSE file */
748     unsigned int crypt = 0; /* 1 means encrypt, 0 means decrypt */
749     unsigned char key[24];  /* TDEA 3 key bundle */
750     unsigned int numKeys = 0;
751     unsigned char plaintext[8];  /* PT[j] */
752     unsigned char ciphertext[8]; /* CT[j] */
753     unsigned char iv[8];
754 
755     /* zeroize the variables for the test with this data set */
756     memset(key, 0, sizeof key);
757     memset(plaintext, 0, sizeof plaintext);
758     memset(ciphertext, 0, sizeof ciphertext);
759     memset(iv, 0, sizeof iv);
760 
761     req = fopen(reqfn, "r");
762     resp = stdout;
763     while (fgets(buf, sizeof buf, req) != NULL) {
764         /* a comment or blank line */
765         if (buf[0] == '#' || buf[0] == '\n') {
766             fputs(buf, resp);
767             continue;
768         }
769         /* [ENCRYPT] or [DECRYPT] */
770         if (buf[0] == '[') {
771             if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
772                 crypt = ENCRYPT;
773             } else {
774                 crypt = DECRYPT;
775             }
776             fputs(buf, resp);
777             continue;
778         }
779         /* NumKeys */
780         if (strncmp(&buf[0], "NumKeys", 7) == 0) {
781             i = 7;
782             while (isspace(buf[i]) || buf[i] == '=') {
783                 i++;
784             }
785             numKeys = atoi(&buf[i]);
786             continue;
787         }
788         /* KEY1 = ... */
789         if (strncmp(buf, "KEY1", 4) == 0) {
790             i = 4;
791             while (isspace(buf[i]) || buf[i] == '=') {
792                 i++;
793             }
794             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
795                 hex_to_byteval(&buf[i], &key[j]);
796             }
797             continue;
798         }
799         /* KEY2 = ... */
800         if (strncmp(buf, "KEY2", 4) == 0) {
801             i = 4;
802             while (isspace(buf[i]) || buf[i] == '=') {
803                 i++;
804             }
805             for (j = 8; isxdigit(buf[i]); i += 2, j++) {
806                 hex_to_byteval(&buf[i], &key[j]);
807             }
808             continue;
809         }
810         /* KEY3 = ... */
811         if (strncmp(buf, "KEY3", 4) == 0) {
812             i = 4;
813             while (isspace(buf[i]) || buf[i] == '=') {
814                 i++;
815             }
816             for (j = 16; isxdigit(buf[i]); i += 2, j++) {
817                 hex_to_byteval(&buf[i], &key[j]);
818             }
819             continue;
820         }
821 
822         /* IV = ... */
823         if (strncmp(buf, "IV", 2) == 0) {
824             i = 2;
825             while (isspace(buf[i]) || buf[i] == '=') {
826                 i++;
827             }
828             for (j = 0; j < sizeof iv; i += 2, j++) {
829                 hex_to_byteval(&buf[i], &iv[j]);
830             }
831             continue;
832         }
833 
834         /* PLAINTEXT = ... */
835         if (strncmp(buf, "PLAINTEXT", 9) == 0) {
836 
837             /* sanity check */
838             if (crypt != ENCRYPT) {
839                 goto loser;
840             }
841             /* PT[0] = PT */
842             i = 9;
843             while (isspace(buf[i]) || buf[i] == '=') {
844                 i++;
845             }
846             for (j = 0; j < sizeof plaintext; i += 2, j++) {
847                 hex_to_byteval(&buf[i], &plaintext[j]);
848             }
849 
850             /* do the Monte Carlo test */
851             if (mode == NSS_DES_EDE3) {
852                 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp);
853             } else {
854                 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp);
855             }
856             continue;
857         }
858         /* CIPHERTEXT = ... */
859         if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
860             /* sanity check */
861             if (crypt != DECRYPT) {
862                 goto loser;
863             }
864             /* CT[0] = CT */
865             i = 10;
866             while (isspace(buf[i]) || buf[i] == '=') {
867                 i++;
868             }
869             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
870                 hex_to_byteval(&buf[i], &ciphertext[j]);
871             }
872 
873             /* do the Monte Carlo test */
874             if (mode == NSS_DES_EDE3) {
875                 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp);
876             } else {
877                 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp);
878             }
879             continue;
880         }
881     }
882 
883 loser:
884     fclose(req);
885 }
886 
887 SECStatus
aes_encrypt_buf(int mode,const unsigned char * key,unsigned int keysize,const unsigned char * iv,unsigned char * output,unsigned int * outputlen,unsigned int maxoutputlen,const unsigned char * input,unsigned int inputlen)888 aes_encrypt_buf(
889     int mode,
890     const unsigned char *key, unsigned int keysize,
891     const unsigned char *iv,
892     unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
893     const unsigned char *input, unsigned int inputlen)
894 {
895     SECStatus rv = SECFailure;
896     AESContext *cx;
897     unsigned char doublecheck[10 * 16]; /* 1 to 10 blocks */
898     unsigned int doublechecklen = 0;
899 
900     cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
901     if (cx == NULL) {
902         goto loser;
903     }
904     rv = AES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
905     if (rv != SECSuccess) {
906         goto loser;
907     }
908     if (*outputlen != inputlen) {
909         goto loser;
910     }
911     AES_DestroyContext(cx, PR_TRUE);
912     cx = NULL;
913 
914     /*
915      * Doublecheck our result by decrypting the ciphertext and
916      * compare the output with the input plaintext.
917      */
918     cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
919     if (cx == NULL) {
920         goto loser;
921     }
922     rv = AES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
923                      output, *outputlen);
924     if (rv != SECSuccess) {
925         goto loser;
926     }
927     if (doublechecklen != *outputlen) {
928         goto loser;
929     }
930     AES_DestroyContext(cx, PR_TRUE);
931     cx = NULL;
932     if (memcmp(doublecheck, input, inputlen) != 0) {
933         goto loser;
934     }
935     rv = SECSuccess;
936 
937 loser:
938     if (cx != NULL) {
939         AES_DestroyContext(cx, PR_TRUE);
940     }
941     return rv;
942 }
943 
944 SECStatus
aes_decrypt_buf(int mode,const unsigned char * key,unsigned int keysize,const unsigned char * iv,unsigned char * output,unsigned int * outputlen,unsigned int maxoutputlen,const unsigned char * input,unsigned int inputlen)945 aes_decrypt_buf(
946     int mode,
947     const unsigned char *key, unsigned int keysize,
948     const unsigned char *iv,
949     unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
950     const unsigned char *input, unsigned int inputlen)
951 {
952     SECStatus rv = SECFailure;
953     AESContext *cx;
954     unsigned char doublecheck[10 * 16]; /* 1 to 10 blocks */
955     unsigned int doublechecklen = 0;
956 
957     cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
958     if (cx == NULL) {
959         goto loser;
960     }
961     rv = AES_Decrypt(cx, output, outputlen, maxoutputlen,
962                      input, inputlen);
963     if (rv != SECSuccess) {
964         goto loser;
965     }
966     if (*outputlen != inputlen) {
967         goto loser;
968     }
969     AES_DestroyContext(cx, PR_TRUE);
970     cx = NULL;
971 
972     /*
973      * Doublecheck our result by encrypting the plaintext and
974      * compare the output with the input ciphertext.
975      */
976     cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
977     if (cx == NULL) {
978         goto loser;
979     }
980     rv = AES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
981                      output, *outputlen);
982     if (rv != SECSuccess) {
983         goto loser;
984     }
985     if (doublechecklen != *outputlen) {
986         goto loser;
987     }
988     AES_DestroyContext(cx, PR_TRUE);
989     cx = NULL;
990     if (memcmp(doublecheck, input, inputlen) != 0) {
991         goto loser;
992     }
993     rv = SECSuccess;
994 
995 loser:
996     if (cx != NULL) {
997         AES_DestroyContext(cx, PR_TRUE);
998     }
999     return rv;
1000 }
1001 /*
1002  * Perform the AES GCM tests.
1003  *
1004  * reqfn is the pathname of the REQUEST file.
1005  *
1006  * The output RESPONSE file is written to stdout.
1007  */
1008 void
aes_gcm(char * reqfn,int encrypt)1009 aes_gcm(char *reqfn, int encrypt)
1010 {
1011     char buf[512]; /* holds one line from the input REQUEST file.
1012                          * needs to be large enough to hold the longest
1013                          * line "CIPHERTEXT = <320 hex digits>\n".
1014                          */
1015     FILE *aesreq;  /* input stream from the REQUEST file */
1016     FILE *aesresp; /* output stream to the RESPONSE file */
1017     int i, j;
1018     unsigned char key[32]; /* 128, 192, or 256 bits */
1019     unsigned int keysize = 0;
1020     unsigned char iv[128];            /* handle large gcm IV's */
1021     unsigned char plaintext[10 * 16]; /* 1 to 10 blocks */
1022     unsigned int plaintextlen;
1023     unsigned char ciphertext[11 * 16]; /* 1 to 10 blocks + tag */
1024     unsigned int ciphertextlen;
1025     unsigned char aad[11 * 16]; /* 1 to 10 blocks + tag */
1026     unsigned int aadlen = 0;
1027     unsigned int tagbits;
1028     unsigned int taglen = 0;
1029     unsigned int ivlen;
1030     CK_NSS_GCM_PARAMS params;
1031     SECStatus rv;
1032 
1033     aesreq = fopen(reqfn, "r");
1034     aesresp = stdout;
1035     while (fgets(buf, sizeof buf, aesreq) != NULL) {
1036         /* a comment or blank line */
1037         if (buf[0] == '#' || buf[0] == '\n') {
1038             fputs(buf, aesresp);
1039             continue;
1040         }
1041         /* [ENCRYPT] or [DECRYPT] */
1042         if (buf[0] == '[') {
1043             if (strncmp(buf, "[Taglen", 7) == 0) {
1044                 if (sscanf(buf, "[Taglen = %d]", &tagbits) != 1) {
1045                     goto loser;
1046                 }
1047                 taglen = tagbits / 8;
1048             }
1049             if (strncmp(buf, "[IVlen", 6) == 0) {
1050                 if (sscanf(buf, "[IVlen = %d]", &ivlen) != 1) {
1051                     goto loser;
1052                 }
1053                 ivlen = ivlen / 8;
1054             }
1055             fputs(buf, aesresp);
1056             continue;
1057         }
1058         /* "COUNT = x" begins a new data set */
1059         if (strncmp(buf, "Count", 5) == 0) {
1060             /* zeroize the variables for the test with this data set */
1061             memset(key, 0, sizeof key);
1062             keysize = 0;
1063             memset(iv, 0, sizeof iv);
1064             memset(plaintext, 0, sizeof plaintext);
1065             plaintextlen = 0;
1066             memset(ciphertext, 0, sizeof ciphertext);
1067             ciphertextlen = 0;
1068             fputs(buf, aesresp);
1069             continue;
1070         }
1071         /* KEY = ... */
1072         if (strncmp(buf, "Key", 3) == 0) {
1073             i = 3;
1074             while (isspace(buf[i]) || buf[i] == '=') {
1075                 i++;
1076             }
1077             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1078                 hex_to_byteval(&buf[i], &key[j]);
1079             }
1080             keysize = j;
1081             fputs(buf, aesresp);
1082             continue;
1083         }
1084         /* IV = ... */
1085         if (strncmp(buf, "IV", 2) == 0) {
1086             i = 2;
1087             while (isspace(buf[i]) || buf[i] == '=') {
1088                 i++;
1089             }
1090             for (j = 0; j < sizeof iv; i += 2, j++) {
1091                 hex_to_byteval(&buf[i], &iv[j]);
1092             }
1093             fputs(buf, aesresp);
1094             continue;
1095         }
1096         /* PLAINTEXT = ... */
1097         if (strncmp(buf, "PT", 2) == 0) {
1098             /* sanity check */
1099             if (!encrypt) {
1100                 goto loser;
1101             }
1102 
1103             i = 2;
1104             while (isspace(buf[i]) || buf[i] == '=') {
1105                 i++;
1106             }
1107             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1108                 hex_to_byteval(&buf[i], &plaintext[j]);
1109             }
1110             plaintextlen = j;
1111             fputs(buf, aesresp);
1112             continue;
1113         }
1114         /* CIPHERTEXT = ... */
1115         if (strncmp(buf, "CT", 2) == 0) {
1116             /* sanity check */
1117             if (encrypt) {
1118                 goto loser;
1119             }
1120 
1121             i = 2;
1122             while (isspace(buf[i]) || buf[i] == '=') {
1123                 i++;
1124             }
1125             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1126                 hex_to_byteval(&buf[i], &ciphertext[j]);
1127             }
1128             ciphertextlen = j;
1129             fputs(buf, aesresp);
1130             continue;
1131         }
1132         if (strncmp(buf, "AAD", 3) == 0) {
1133             i = 3;
1134             while (isspace(buf[i]) || buf[i] == '=') {
1135                 i++;
1136             }
1137             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1138                 hex_to_byteval(&buf[i], &aad[j]);
1139             }
1140             aadlen = j;
1141             fputs(buf, aesresp);
1142             if (encrypt) {
1143                 if (encrypt == 2) {
1144                     rv = RNG_GenerateGlobalRandomBytes(iv, ivlen);
1145                     if (rv != SECSuccess) {
1146                         goto loser;
1147                     }
1148                 }
1149                 params.pIv = iv;
1150                 params.ulIvLen = ivlen;
1151                 params.pAAD = aad;
1152                 params.ulAADLen = aadlen;
1153                 params.ulTagBits = tagbits;
1154                 rv = aes_encrypt_buf(NSS_AES_GCM, key, keysize,
1155                                      (unsigned char *)&params,
1156                                      ciphertext, &ciphertextlen, sizeof ciphertext,
1157                                      plaintext, plaintextlen);
1158                 if (rv != SECSuccess) {
1159                     goto loser;
1160                 }
1161 
1162                 if (encrypt == 2) {
1163                     fputs("IV = ", aesresp);
1164                     to_hex_str(buf, iv, ivlen);
1165                     fputs(buf, aesresp);
1166                     fputc('\n', aesresp);
1167                 }
1168                 fputs("CT = ", aesresp);
1169                 j = ciphertextlen - taglen;
1170                 to_hex_str(buf, ciphertext, j);
1171                 fputs(buf, aesresp);
1172                 fputs("\nTag = ", aesresp);
1173                 to_hex_str(buf, ciphertext + j, taglen);
1174                 fputs(buf, aesresp);
1175                 fputc('\n', aesresp);
1176             }
1177             continue;
1178         }
1179         if (strncmp(buf, "Tag", 3) == 0) {
1180             /* sanity check */
1181             if (encrypt) {
1182                 goto loser;
1183             }
1184 
1185             i = 3;
1186             while (isspace(buf[i]) || buf[i] == '=') {
1187                 i++;
1188             }
1189             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1190                 hex_to_byteval(&buf[i], &ciphertext[j + ciphertextlen]);
1191             }
1192             ciphertextlen += j;
1193             params.pIv = iv;
1194             params.ulIvLen = ivlen;
1195             params.pAAD = aad;
1196             params.ulAADLen = aadlen;
1197             params.ulTagBits = tagbits;
1198             rv = aes_decrypt_buf(NSS_AES_GCM, key, keysize,
1199                                  (unsigned char *)&params,
1200                                  plaintext, &plaintextlen, sizeof plaintext,
1201                                  ciphertext, ciphertextlen);
1202             fputs(buf, aesresp);
1203             if (rv != SECSuccess) {
1204                 fprintf(aesresp, "FAIL\n");
1205             } else {
1206                 fputs("PT = ", aesresp);
1207                 to_hex_str(buf, plaintext, plaintextlen);
1208                 fputs(buf, aesresp);
1209                 fputc('\n', aesresp);
1210             }
1211             continue;
1212         }
1213     }
1214 loser:
1215     fclose(aesreq);
1216 }
1217 
1218 /*
1219  * Perform the AES Known Answer Test (KAT) or Multi-block Message
1220  * Test (MMT) in ECB or CBC mode.  The KAT (there are four types)
1221  * and MMT have the same structure: given the key and IV (CBC mode
1222  * only), encrypt the given plaintext or decrypt the given ciphertext.
1223  * So we can handle them the same way.
1224  *
1225  * reqfn is the pathname of the REQUEST file.
1226  *
1227  * The output RESPONSE file is written to stdout.
1228  */
1229 void
aes_kat_mmt(char * reqfn)1230 aes_kat_mmt(char *reqfn)
1231 {
1232     char buf[512]; /* holds one line from the input REQUEST file.
1233                          * needs to be large enough to hold the longest
1234                          * line "CIPHERTEXT = <320 hex digits>\n".
1235                          */
1236     FILE *aesreq;  /* input stream from the REQUEST file */
1237     FILE *aesresp; /* output stream to the RESPONSE file */
1238     int i, j;
1239     int mode = NSS_AES;    /* NSS_AES (ECB) or NSS_AES_CBC */
1240     int encrypt = 0;       /* 1 means encrypt, 0 means decrypt */
1241     unsigned char key[32]; /* 128, 192, or 256 bits */
1242     unsigned int keysize = 0;
1243     unsigned char iv[16];             /* for all modes except ECB */
1244     unsigned char plaintext[10 * 16]; /* 1 to 10 blocks */
1245     unsigned int plaintextlen;
1246     unsigned char ciphertext[10 * 16]; /* 1 to 10 blocks */
1247     unsigned int ciphertextlen;
1248     SECStatus rv;
1249 
1250     aesreq = fopen(reqfn, "r");
1251     aesresp = stdout;
1252     while (fgets(buf, sizeof buf, aesreq) != NULL) {
1253         /* a comment or blank line */
1254         if (buf[0] == '#' || buf[0] == '\n') {
1255             fputs(buf, aesresp);
1256             continue;
1257         }
1258         /* [ENCRYPT] or [DECRYPT] */
1259         if (buf[0] == '[') {
1260             if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1261                 encrypt = 1;
1262             } else {
1263                 encrypt = 0;
1264             }
1265             fputs(buf, aesresp);
1266             continue;
1267         }
1268         /* "COUNT = x" begins a new data set */
1269         if (strncmp(buf, "COUNT", 5) == 0) {
1270             mode = NSS_AES;
1271             /* zeroize the variables for the test with this data set */
1272             memset(key, 0, sizeof key);
1273             keysize = 0;
1274             memset(iv, 0, sizeof iv);
1275             memset(plaintext, 0, sizeof plaintext);
1276             plaintextlen = 0;
1277             memset(ciphertext, 0, sizeof ciphertext);
1278             ciphertextlen = 0;
1279             fputs(buf, aesresp);
1280             continue;
1281         }
1282         /* KEY = ... */
1283         if (strncmp(buf, "KEY", 3) == 0) {
1284             i = 3;
1285             while (isspace(buf[i]) || buf[i] == '=') {
1286                 i++;
1287             }
1288             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1289                 hex_to_byteval(&buf[i], &key[j]);
1290             }
1291             keysize = j;
1292             fputs(buf, aesresp);
1293             continue;
1294         }
1295         /* IV = ... */
1296         if (strncmp(buf, "IV", 2) == 0) {
1297             mode = NSS_AES_CBC;
1298             i = 2;
1299             while (isspace(buf[i]) || buf[i] == '=') {
1300                 i++;
1301             }
1302             for (j = 0; j < sizeof iv; i += 2, j++) {
1303                 hex_to_byteval(&buf[i], &iv[j]);
1304             }
1305             fputs(buf, aesresp);
1306             continue;
1307         }
1308         /* PLAINTEXT = ... */
1309         if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1310             /* sanity check */
1311             if (!encrypt) {
1312                 goto loser;
1313             }
1314 
1315             i = 9;
1316             while (isspace(buf[i]) || buf[i] == '=') {
1317                 i++;
1318             }
1319             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1320                 hex_to_byteval(&buf[i], &plaintext[j]);
1321             }
1322             plaintextlen = j;
1323 
1324             rv = aes_encrypt_buf(mode, key, keysize,
1325                                  (mode ==
1326                                   NSS_AES)
1327                                      ? NULL
1328                                      : iv,
1329                                  ciphertext, &ciphertextlen, sizeof ciphertext,
1330                                  plaintext, plaintextlen);
1331             if (rv != SECSuccess) {
1332                 goto loser;
1333             }
1334 
1335             fputs(buf, aesresp);
1336             fputs("CIPHERTEXT = ", aesresp);
1337             to_hex_str(buf, ciphertext, ciphertextlen);
1338             fputs(buf, aesresp);
1339             fputc('\n', aesresp);
1340             continue;
1341         }
1342         /* CIPHERTEXT = ... */
1343         if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1344             /* sanity check */
1345             if (encrypt) {
1346                 goto loser;
1347             }
1348 
1349             i = 10;
1350             while (isspace(buf[i]) || buf[i] == '=') {
1351                 i++;
1352             }
1353             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1354                 hex_to_byteval(&buf[i], &ciphertext[j]);
1355             }
1356             ciphertextlen = j;
1357 
1358             rv = aes_decrypt_buf(mode, key, keysize,
1359                                  (mode ==
1360                                   NSS_AES)
1361                                      ? NULL
1362                                      : iv,
1363                                  plaintext, &plaintextlen, sizeof plaintext,
1364                                  ciphertext, ciphertextlen);
1365             if (rv != SECSuccess) {
1366                 goto loser;
1367             }
1368 
1369             fputs(buf, aesresp);
1370             fputs("PLAINTEXT = ", aesresp);
1371             to_hex_str(buf, plaintext, plaintextlen);
1372             fputs(buf, aesresp);
1373             fputc('\n', aesresp);
1374             continue;
1375         }
1376     }
1377 loser:
1378     fclose(aesreq);
1379 }
1380 
1381 /*
1382  * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
1383  * Test (MCT) in ECB and CBC modes.
1384  */
1385 void
aes_mct_next_key(unsigned char * key,unsigned int keysize,const unsigned char * ciphertext_1,const unsigned char * ciphertext)1386 aes_mct_next_key(unsigned char *key, unsigned int keysize,
1387                  const unsigned char *ciphertext_1, const unsigned char *ciphertext)
1388 {
1389     int k;
1390 
1391     switch (keysize) {
1392         case 16: /* 128-bit key */
1393             /* Key[i+1] = Key[i] xor CT[j] */
1394             for (k = 0; k < 16; k++) {
1395                 key[k] ^= ciphertext[k];
1396             }
1397             break;
1398         case 24: /* 192-bit key */
1399             /*
1400          * Key[i+1] = Key[i] xor (last 64-bits of
1401          *            CT[j-1] || CT[j])
1402          */
1403             for (k = 0; k < 8; k++) {
1404                 key[k] ^= ciphertext_1[k + 8];
1405             }
1406             for (k = 8; k < 24; k++) {
1407                 key[k] ^= ciphertext[k - 8];
1408             }
1409             break;
1410         case 32: /* 256-bit key */
1411             /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
1412             for (k = 0; k < 16; k++) {
1413                 key[k] ^= ciphertext_1[k];
1414             }
1415             for (k = 16; k < 32; k++) {
1416                 key[k] ^= ciphertext[k - 16];
1417             }
1418             break;
1419     }
1420 }
1421 
1422 /*
1423  * Perform the AES Monte Carlo Test (MCT) in ECB mode.  MCT exercises
1424  * our AES code in streaming mode because the plaintext or ciphertext
1425  * is generated block by block as we go, so we can't collect all the
1426  * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1427  * one shot.
1428  *
1429  * reqfn is the pathname of the input REQUEST file.
1430  *
1431  * The output RESPONSE file is written to stdout.
1432  */
1433 void
aes_ecb_mct(char * reqfn)1434 aes_ecb_mct(char *reqfn)
1435 {
1436     char buf[80];  /* holds one line from the input REQUEST file.
1437                          * needs to be large enough to hold the longest
1438                          * line "KEY = <64 hex digits>\n".
1439                          */
1440     FILE *aesreq;  /* input stream from the REQUEST file */
1441     FILE *aesresp; /* output stream to the RESPONSE file */
1442     int i, j;
1443     int encrypt = 0;       /* 1 means encrypt, 0 means decrypt */
1444     unsigned char key[32]; /* 128, 192, or 256 bits */
1445     unsigned int keysize = 0;
1446     unsigned char plaintext[16];    /* PT[j] */
1447     unsigned char plaintext_1[16];  /* PT[j-1] */
1448     unsigned char ciphertext[16];   /* CT[j] */
1449     unsigned char ciphertext_1[16]; /* CT[j-1] */
1450     unsigned char doublecheck[16];
1451     unsigned int outputlen;
1452     AESContext *cx = NULL;  /* the operation being tested */
1453     AESContext *cx2 = NULL; /* the inverse operation done in parallel
1454                                  * to doublecheck our result.
1455                                  */
1456     SECStatus rv;
1457 
1458     aesreq = fopen(reqfn, "r");
1459     aesresp = stdout;
1460     while (fgets(buf, sizeof buf, aesreq) != NULL) {
1461         /* a comment or blank line */
1462         if (buf[0] == '#' || buf[0] == '\n') {
1463             fputs(buf, aesresp);
1464             continue;
1465         }
1466         /* [ENCRYPT] or [DECRYPT] */
1467         if (buf[0] == '[') {
1468             if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1469                 encrypt = 1;
1470             } else {
1471                 encrypt = 0;
1472             }
1473             fputs(buf, aesresp);
1474             continue;
1475         }
1476         /* "COUNT = x" begins a new data set */
1477         if (strncmp(buf, "COUNT", 5) == 0) {
1478             /* zeroize the variables for the test with this data set */
1479             memset(key, 0, sizeof key);
1480             keysize = 0;
1481             memset(plaintext, 0, sizeof plaintext);
1482             memset(ciphertext, 0, sizeof ciphertext);
1483             continue;
1484         }
1485         /* KEY = ... */
1486         if (strncmp(buf, "KEY", 3) == 0) {
1487             /* Key[0] = Key */
1488             i = 3;
1489             while (isspace(buf[i]) || buf[i] == '=') {
1490                 i++;
1491             }
1492             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1493                 hex_to_byteval(&buf[i], &key[j]);
1494             }
1495             keysize = j;
1496             continue;
1497         }
1498         /* PLAINTEXT = ... */
1499         if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1500             /* sanity check */
1501             if (!encrypt) {
1502                 goto loser;
1503             }
1504             /* PT[0] = PT */
1505             i = 9;
1506             while (isspace(buf[i]) || buf[i] == '=') {
1507                 i++;
1508             }
1509             for (j = 0; j < sizeof plaintext; i += 2, j++) {
1510                 hex_to_byteval(&buf[i], &plaintext[j]);
1511             }
1512 
1513             for (i = 0; i < 100; i++) {
1514                 sprintf(buf, "COUNT = %d\n", i);
1515                 fputs(buf, aesresp);
1516                 /* Output Key[i] */
1517                 fputs("KEY = ", aesresp);
1518                 to_hex_str(buf, key, keysize);
1519                 fputs(buf, aesresp);
1520                 fputc('\n', aesresp);
1521                 /* Output PT[0] */
1522                 fputs("PLAINTEXT = ", aesresp);
1523                 to_hex_str(buf, plaintext, sizeof plaintext);
1524                 fputs(buf, aesresp);
1525                 fputc('\n', aesresp);
1526 
1527                 cx = AES_CreateContext(key, NULL, NSS_AES,
1528                                        PR_TRUE, keysize, 16);
1529                 if (cx == NULL) {
1530                     goto loser;
1531                 }
1532                 /*
1533                  * doublecheck our result by decrypting the result
1534                  * and comparing the output with the plaintext.
1535                  */
1536                 cx2 = AES_CreateContext(key, NULL, NSS_AES,
1537                                         PR_FALSE, keysize, 16);
1538                 if (cx2 == NULL) {
1539                     goto loser;
1540                 }
1541                 for (j = 0; j < 1000; j++) {
1542                     /* Save CT[j-1] */
1543                     memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
1544 
1545                     /* CT[j] = AES(Key[i], PT[j]) */
1546                     outputlen = 0;
1547                     rv = AES_Encrypt(cx,
1548                                      ciphertext, &outputlen, sizeof ciphertext,
1549                                      plaintext, sizeof plaintext);
1550                     if (rv != SECSuccess) {
1551                         goto loser;
1552                     }
1553                     if (outputlen != sizeof plaintext) {
1554                         goto loser;
1555                     }
1556 
1557                     /* doublecheck our result */
1558                     outputlen = 0;
1559                     rv = AES_Decrypt(cx2,
1560                                      doublecheck, &outputlen, sizeof doublecheck,
1561                                      ciphertext, sizeof ciphertext);
1562                     if (rv != SECSuccess) {
1563                         goto loser;
1564                     }
1565                     if (outputlen != sizeof ciphertext) {
1566                         goto loser;
1567                     }
1568                     if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
1569                         goto loser;
1570                     }
1571 
1572                     /* PT[j+1] = CT[j] */
1573                     memcpy(plaintext, ciphertext, sizeof plaintext);
1574                 }
1575                 AES_DestroyContext(cx, PR_TRUE);
1576                 cx = NULL;
1577                 AES_DestroyContext(cx2, PR_TRUE);
1578                 cx2 = NULL;
1579 
1580                 /* Output CT[j] */
1581                 fputs("CIPHERTEXT = ", aesresp);
1582                 to_hex_str(buf, ciphertext, sizeof ciphertext);
1583                 fputs(buf, aesresp);
1584                 fputc('\n', aesresp);
1585 
1586                 /* Key[i+1] = Key[i] xor ... */
1587                 aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
1588                 /* PT[0] = CT[j] */
1589                 /* done at the end of the for(j) loop */
1590 
1591                 fputc('\n', aesresp);
1592             }
1593 
1594             continue;
1595         }
1596         /* CIPHERTEXT = ... */
1597         if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1598             /* sanity check */
1599             if (encrypt) {
1600                 goto loser;
1601             }
1602             /* CT[0] = CT */
1603             i = 10;
1604             while (isspace(buf[i]) || buf[i] == '=') {
1605                 i++;
1606             }
1607             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1608                 hex_to_byteval(&buf[i], &ciphertext[j]);
1609             }
1610 
1611             for (i = 0; i < 100; i++) {
1612                 sprintf(buf, "COUNT = %d\n", i);
1613                 fputs(buf, aesresp);
1614                 /* Output Key[i] */
1615                 fputs("KEY = ", aesresp);
1616                 to_hex_str(buf, key, keysize);
1617                 fputs(buf, aesresp);
1618                 fputc('\n', aesresp);
1619                 /* Output CT[0] */
1620                 fputs("CIPHERTEXT = ", aesresp);
1621                 to_hex_str(buf, ciphertext, sizeof ciphertext);
1622                 fputs(buf, aesresp);
1623                 fputc('\n', aesresp);
1624 
1625                 cx = AES_CreateContext(key, NULL, NSS_AES,
1626                                        PR_FALSE, keysize, 16);
1627                 if (cx == NULL) {
1628                     goto loser;
1629                 }
1630                 /*
1631                  * doublecheck our result by encrypting the result
1632                  * and comparing the output with the ciphertext.
1633                  */
1634                 cx2 = AES_CreateContext(key, NULL, NSS_AES,
1635                                         PR_TRUE, keysize, 16);
1636                 if (cx2 == NULL) {
1637                     goto loser;
1638                 }
1639                 for (j = 0; j < 1000; j++) {
1640                     /* Save PT[j-1] */
1641                     memcpy(plaintext_1, plaintext, sizeof plaintext);
1642 
1643                     /* PT[j] = AES(Key[i], CT[j]) */
1644                     outputlen = 0;
1645                     rv = AES_Decrypt(cx,
1646                                      plaintext, &outputlen, sizeof plaintext,
1647                                      ciphertext, sizeof ciphertext);
1648                     if (rv != SECSuccess) {
1649                         goto loser;
1650                     }
1651                     if (outputlen != sizeof ciphertext) {
1652                         goto loser;
1653                     }
1654 
1655                     /* doublecheck our result */
1656                     outputlen = 0;
1657                     rv = AES_Encrypt(cx2,
1658                                      doublecheck, &outputlen, sizeof doublecheck,
1659                                      plaintext, sizeof plaintext);
1660                     if (rv != SECSuccess) {
1661                         goto loser;
1662                     }
1663                     if (outputlen != sizeof plaintext) {
1664                         goto loser;
1665                     }
1666                     if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
1667                         goto loser;
1668                     }
1669 
1670                     /* CT[j+1] = PT[j] */
1671                     memcpy(ciphertext, plaintext, sizeof ciphertext);
1672                 }
1673                 AES_DestroyContext(cx, PR_TRUE);
1674                 cx = NULL;
1675                 AES_DestroyContext(cx2, PR_TRUE);
1676                 cx2 = NULL;
1677 
1678                 /* Output PT[j] */
1679                 fputs("PLAINTEXT = ", aesresp);
1680                 to_hex_str(buf, plaintext, sizeof plaintext);
1681                 fputs(buf, aesresp);
1682                 fputc('\n', aesresp);
1683 
1684                 /* Key[i+1] = Key[i] xor ... */
1685                 aes_mct_next_key(key, keysize, plaintext_1, plaintext);
1686                 /* CT[0] = PT[j] */
1687                 /* done at the end of the for(j) loop */
1688 
1689                 fputc('\n', aesresp);
1690             }
1691 
1692             continue;
1693         }
1694     }
1695 loser:
1696     if (cx != NULL) {
1697         AES_DestroyContext(cx, PR_TRUE);
1698     }
1699     if (cx2 != NULL) {
1700         AES_DestroyContext(cx2, PR_TRUE);
1701     }
1702     fclose(aesreq);
1703 }
1704 
1705 /*
1706  * Perform the AES Monte Carlo Test (MCT) in CBC mode.  MCT exercises
1707  * our AES code in streaming mode because the plaintext or ciphertext
1708  * is generated block by block as we go, so we can't collect all the
1709  * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1710  * one shot.
1711  *
1712  * reqfn is the pathname of the input REQUEST file.
1713  *
1714  * The output RESPONSE file is written to stdout.
1715  */
1716 void
aes_cbc_mct(char * reqfn)1717 aes_cbc_mct(char *reqfn)
1718 {
1719     char buf[80];  /* holds one line from the input REQUEST file.
1720                          * needs to be large enough to hold the longest
1721                          * line "KEY = <64 hex digits>\n".
1722                          */
1723     FILE *aesreq;  /* input stream from the REQUEST file */
1724     FILE *aesresp; /* output stream to the RESPONSE file */
1725     int i, j;
1726     int encrypt = 0;       /* 1 means encrypt, 0 means decrypt */
1727     unsigned char key[32]; /* 128, 192, or 256 bits */
1728     unsigned int keysize = 0;
1729     unsigned char iv[16];
1730     unsigned char plaintext[16];    /* PT[j] */
1731     unsigned char plaintext_1[16];  /* PT[j-1] */
1732     unsigned char ciphertext[16];   /* CT[j] */
1733     unsigned char ciphertext_1[16]; /* CT[j-1] */
1734     unsigned char doublecheck[16];
1735     unsigned int outputlen;
1736     AESContext *cx = NULL;  /* the operation being tested */
1737     AESContext *cx2 = NULL; /* the inverse operation done in parallel
1738                                  * to doublecheck our result.
1739                                  */
1740     SECStatus rv;
1741 
1742     aesreq = fopen(reqfn, "r");
1743     aesresp = stdout;
1744     while (fgets(buf, sizeof buf, aesreq) != NULL) {
1745         /* a comment or blank line */
1746         if (buf[0] == '#' || buf[0] == '\n') {
1747             fputs(buf, aesresp);
1748             continue;
1749         }
1750         /* [ENCRYPT] or [DECRYPT] */
1751         if (buf[0] == '[') {
1752             if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1753                 encrypt = 1;
1754             } else {
1755                 encrypt = 0;
1756             }
1757             fputs(buf, aesresp);
1758             continue;
1759         }
1760         /* "COUNT = x" begins a new data set */
1761         if (strncmp(buf, "COUNT", 5) == 0) {
1762             /* zeroize the variables for the test with this data set */
1763             memset(key, 0, sizeof key);
1764             keysize = 0;
1765             memset(iv, 0, sizeof iv);
1766             memset(plaintext, 0, sizeof plaintext);
1767             memset(ciphertext, 0, sizeof ciphertext);
1768             continue;
1769         }
1770         /* KEY = ... */
1771         if (strncmp(buf, "KEY", 3) == 0) {
1772             /* Key[0] = Key */
1773             i = 3;
1774             while (isspace(buf[i]) || buf[i] == '=') {
1775                 i++;
1776             }
1777             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1778                 hex_to_byteval(&buf[i], &key[j]);
1779             }
1780             keysize = j;
1781             continue;
1782         }
1783         /* IV = ... */
1784         if (strncmp(buf, "IV", 2) == 0) {
1785             /* IV[0] = IV */
1786             i = 2;
1787             while (isspace(buf[i]) || buf[i] == '=') {
1788                 i++;
1789             }
1790             for (j = 0; j < sizeof iv; i += 2, j++) {
1791                 hex_to_byteval(&buf[i], &iv[j]);
1792             }
1793             continue;
1794         }
1795         /* PLAINTEXT = ... */
1796         if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1797             /* sanity check */
1798             if (!encrypt) {
1799                 goto loser;
1800             }
1801             /* PT[0] = PT */
1802             i = 9;
1803             while (isspace(buf[i]) || buf[i] == '=') {
1804                 i++;
1805             }
1806             for (j = 0; j < sizeof plaintext; i += 2, j++) {
1807                 hex_to_byteval(&buf[i], &plaintext[j]);
1808             }
1809 
1810             for (i = 0; i < 100; i++) {
1811                 sprintf(buf, "COUNT = %d\n", i);
1812                 fputs(buf, aesresp);
1813                 /* Output Key[i] */
1814                 fputs("KEY = ", aesresp);
1815                 to_hex_str(buf, key, keysize);
1816                 fputs(buf, aesresp);
1817                 fputc('\n', aesresp);
1818                 /* Output IV[i] */
1819                 fputs("IV = ", aesresp);
1820                 to_hex_str(buf, iv, sizeof iv);
1821                 fputs(buf, aesresp);
1822                 fputc('\n', aesresp);
1823                 /* Output PT[0] */
1824                 fputs("PLAINTEXT = ", aesresp);
1825                 to_hex_str(buf, plaintext, sizeof plaintext);
1826                 fputs(buf, aesresp);
1827                 fputc('\n', aesresp);
1828 
1829                 cx = AES_CreateContext(key, iv, NSS_AES_CBC,
1830                                        PR_TRUE, keysize, 16);
1831                 if (cx == NULL) {
1832                     goto loser;
1833                 }
1834                 /*
1835                  * doublecheck our result by decrypting the result
1836                  * and comparing the output with the plaintext.
1837                  */
1838                 cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
1839                                         PR_FALSE, keysize, 16);
1840                 if (cx2 == NULL) {
1841                     goto loser;
1842                 }
1843                 /* CT[-1] = IV[i] */
1844                 memcpy(ciphertext, iv, sizeof ciphertext);
1845                 for (j = 0; j < 1000; j++) {
1846                     /* Save CT[j-1] */
1847                     memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
1848                     /*
1849                      * If ( j=0 )
1850                      *      CT[j] = AES(Key[i], IV[i], PT[j])
1851                      *      PT[j+1] = IV[i] (= CT[j-1])
1852                      * Else
1853                      *      CT[j] = AES(Key[i], PT[j])
1854                      *      PT[j+1] = CT[j-1]
1855                      */
1856                     outputlen = 0;
1857                     rv = AES_Encrypt(cx,
1858                                      ciphertext, &outputlen, sizeof ciphertext,
1859                                      plaintext, sizeof plaintext);
1860                     if (rv != SECSuccess) {
1861                         goto loser;
1862                     }
1863                     if (outputlen != sizeof plaintext) {
1864                         goto loser;
1865                     }
1866 
1867                     /* doublecheck our result */
1868                     outputlen = 0;
1869                     rv = AES_Decrypt(cx2,
1870                                      doublecheck, &outputlen, sizeof doublecheck,
1871                                      ciphertext, sizeof ciphertext);
1872                     if (rv != SECSuccess) {
1873                         goto loser;
1874                     }
1875                     if (outputlen != sizeof ciphertext) {
1876                         goto loser;
1877                     }
1878                     if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
1879                         goto loser;
1880                     }
1881 
1882                     memcpy(plaintext, ciphertext_1, sizeof plaintext);
1883                 }
1884                 AES_DestroyContext(cx, PR_TRUE);
1885                 cx = NULL;
1886                 AES_DestroyContext(cx2, PR_TRUE);
1887                 cx2 = NULL;
1888 
1889                 /* Output CT[j] */
1890                 fputs("CIPHERTEXT = ", aesresp);
1891                 to_hex_str(buf, ciphertext, sizeof ciphertext);
1892                 fputs(buf, aesresp);
1893                 fputc('\n', aesresp);
1894 
1895                 /* Key[i+1] = Key[i] xor ... */
1896                 aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
1897                 /* IV[i+1] = CT[j] */
1898                 memcpy(iv, ciphertext, sizeof iv);
1899                 /* PT[0] = CT[j-1] */
1900                 /* done at the end of the for(j) loop */
1901 
1902                 fputc('\n', aesresp);
1903             }
1904 
1905             continue;
1906         }
1907         /* CIPHERTEXT = ... */
1908         if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1909             /* sanity check */
1910             if (encrypt) {
1911                 goto loser;
1912             }
1913             /* CT[0] = CT */
1914             i = 10;
1915             while (isspace(buf[i]) || buf[i] == '=') {
1916                 i++;
1917             }
1918             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
1919                 hex_to_byteval(&buf[i], &ciphertext[j]);
1920             }
1921 
1922             for (i = 0; i < 100; i++) {
1923                 sprintf(buf, "COUNT = %d\n", i);
1924                 fputs(buf, aesresp);
1925                 /* Output Key[i] */
1926                 fputs("KEY = ", aesresp);
1927                 to_hex_str(buf, key, keysize);
1928                 fputs(buf, aesresp);
1929                 fputc('\n', aesresp);
1930                 /* Output IV[i] */
1931                 fputs("IV = ", aesresp);
1932                 to_hex_str(buf, iv, sizeof iv);
1933                 fputs(buf, aesresp);
1934                 fputc('\n', aesresp);
1935                 /* Output CT[0] */
1936                 fputs("CIPHERTEXT = ", aesresp);
1937                 to_hex_str(buf, ciphertext, sizeof ciphertext);
1938                 fputs(buf, aesresp);
1939                 fputc('\n', aesresp);
1940 
1941                 cx = AES_CreateContext(key, iv, NSS_AES_CBC,
1942                                        PR_FALSE, keysize, 16);
1943                 if (cx == NULL) {
1944                     goto loser;
1945                 }
1946                 /*
1947                  * doublecheck our result by encrypting the result
1948                  * and comparing the output with the ciphertext.
1949                  */
1950                 cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
1951                                         PR_TRUE, keysize, 16);
1952                 if (cx2 == NULL) {
1953                     goto loser;
1954                 }
1955                 /* PT[-1] = IV[i] */
1956                 memcpy(plaintext, iv, sizeof plaintext);
1957                 for (j = 0; j < 1000; j++) {
1958                     /* Save PT[j-1] */
1959                     memcpy(plaintext_1, plaintext, sizeof plaintext);
1960                     /*
1961                      * If ( j=0 )
1962                      *      PT[j] = AES(Key[i], IV[i], CT[j])
1963                      *      CT[j+1] = IV[i] (= PT[j-1])
1964                      * Else
1965                      *      PT[j] = AES(Key[i], CT[j])
1966                      *      CT[j+1] = PT[j-1]
1967                      */
1968                     outputlen = 0;
1969                     rv = AES_Decrypt(cx,
1970                                      plaintext, &outputlen, sizeof plaintext,
1971                                      ciphertext, sizeof ciphertext);
1972                     if (rv != SECSuccess) {
1973                         goto loser;
1974                     }
1975                     if (outputlen != sizeof ciphertext) {
1976                         goto loser;
1977                     }
1978 
1979                     /* doublecheck our result */
1980                     outputlen = 0;
1981                     rv = AES_Encrypt(cx2,
1982                                      doublecheck, &outputlen, sizeof doublecheck,
1983                                      plaintext, sizeof plaintext);
1984                     if (rv != SECSuccess) {
1985                         goto loser;
1986                     }
1987                     if (outputlen != sizeof plaintext) {
1988                         goto loser;
1989                     }
1990                     if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
1991                         goto loser;
1992                     }
1993 
1994                     memcpy(ciphertext, plaintext_1, sizeof ciphertext);
1995                 }
1996                 AES_DestroyContext(cx, PR_TRUE);
1997                 cx = NULL;
1998                 AES_DestroyContext(cx2, PR_TRUE);
1999                 cx2 = NULL;
2000 
2001                 /* Output PT[j] */
2002                 fputs("PLAINTEXT = ", aesresp);
2003                 to_hex_str(buf, plaintext, sizeof plaintext);
2004                 fputs(buf, aesresp);
2005                 fputc('\n', aesresp);
2006 
2007                 /* Key[i+1] = Key[i] xor ... */
2008                 aes_mct_next_key(key, keysize, plaintext_1, plaintext);
2009                 /* IV[i+1] = PT[j] */
2010                 memcpy(iv, plaintext, sizeof iv);
2011                 /* CT[0] = PT[j-1] */
2012                 /* done at the end of the for(j) loop */
2013 
2014                 fputc('\n', aesresp);
2015             }
2016 
2017             continue;
2018         }
2019     }
2020 loser:
2021     if (cx != NULL) {
2022         AES_DestroyContext(cx, PR_TRUE);
2023     }
2024     if (cx2 != NULL) {
2025         AES_DestroyContext(cx2, PR_TRUE);
2026     }
2027     fclose(aesreq);
2028 }
2029 
2030 void
write_compact_string(FILE * out,unsigned char * hash,unsigned int len)2031 write_compact_string(FILE *out, unsigned char *hash, unsigned int len)
2032 {
2033     unsigned int i;
2034     int j, count = 0, last = -1, z = 0;
2035     long start = ftell(out);
2036     for (i = 0; i < len; i++) {
2037         for (j = 7; j >= 0; j--) {
2038             if (last < 0) {
2039                 last = (hash[i] & (1 << j)) ? 1 : 0;
2040                 fprintf(out, "%d ", last);
2041                 count = 1;
2042             } else if (hash[i] & (1 << j)) {
2043                 if (last) {
2044                     count++;
2045                 } else {
2046                     last = 0;
2047                     fprintf(out, "%d ", count);
2048                     count = 1;
2049                     z++;
2050                 }
2051             } else {
2052                 if (!last) {
2053                     count++;
2054                 } else {
2055                     last = 1;
2056                     fprintf(out, "%d ", count);
2057                     count = 1;
2058                     z++;
2059                 }
2060             }
2061         }
2062     }
2063     fprintf(out, "^\n");
2064     fseek(out, start, SEEK_SET);
2065     fprintf(out, "%d ", z);
2066     fseek(out, 0, SEEK_END);
2067 }
2068 
2069 int
get_next_line(FILE * req,char * key,char * val,FILE * rsp)2070 get_next_line(FILE *req, char *key, char *val, FILE *rsp)
2071 {
2072     int ignore = 0;
2073     char *writeto = key;
2074     int w = 0;
2075     int c;
2076     while ((c = fgetc(req)) != EOF) {
2077         if (ignore) {
2078             fprintf(rsp, "%c", c);
2079             if (c == '\n')
2080                 return ignore;
2081         } else if (c == '\n') {
2082             break;
2083         } else if (c == '#') {
2084             ignore = 1;
2085             fprintf(rsp, "%c", c);
2086         } else if (c == '=') {
2087             writeto[w] = '\0';
2088             w = 0;
2089             writeto = val;
2090         } else if (c == ' ' || c == '[' || c == ']') {
2091             continue;
2092         } else {
2093             writeto[w++] = c;
2094         }
2095     }
2096     writeto[w] = '\0';
2097     return (c == EOF) ? -1 : ignore;
2098 }
2099 
2100 typedef struct curveNameTagPairStr {
2101     char *curveName;
2102     SECOidTag curveOidTag;
2103 } CurveNameTagPair;
2104 
2105 #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
2106 /* #define DEFAULT_CURVE_OID_TAG  SEC_OID_SECG_EC_SECP160R1 */
2107 
2108 static CurveNameTagPair nameTagPair[] =
2109     {
2110       { "sect163k1", SEC_OID_SECG_EC_SECT163K1 },
2111       { "nistk163", SEC_OID_SECG_EC_SECT163K1 },
2112       { "sect163r1", SEC_OID_SECG_EC_SECT163R1 },
2113       { "sect163r2", SEC_OID_SECG_EC_SECT163R2 },
2114       { "nistb163", SEC_OID_SECG_EC_SECT163R2 },
2115       { "sect193r1", SEC_OID_SECG_EC_SECT193R1 },
2116       { "sect193r2", SEC_OID_SECG_EC_SECT193R2 },
2117       { "sect233k1", SEC_OID_SECG_EC_SECT233K1 },
2118       { "nistk233", SEC_OID_SECG_EC_SECT233K1 },
2119       { "sect233r1", SEC_OID_SECG_EC_SECT233R1 },
2120       { "nistb233", SEC_OID_SECG_EC_SECT233R1 },
2121       { "sect239k1", SEC_OID_SECG_EC_SECT239K1 },
2122       { "sect283k1", SEC_OID_SECG_EC_SECT283K1 },
2123       { "nistk283", SEC_OID_SECG_EC_SECT283K1 },
2124       { "sect283r1", SEC_OID_SECG_EC_SECT283R1 },
2125       { "nistb283", SEC_OID_SECG_EC_SECT283R1 },
2126       { "sect409k1", SEC_OID_SECG_EC_SECT409K1 },
2127       { "nistk409", SEC_OID_SECG_EC_SECT409K1 },
2128       { "sect409r1", SEC_OID_SECG_EC_SECT409R1 },
2129       { "nistb409", SEC_OID_SECG_EC_SECT409R1 },
2130       { "sect571k1", SEC_OID_SECG_EC_SECT571K1 },
2131       { "nistk571", SEC_OID_SECG_EC_SECT571K1 },
2132       { "sect571r1", SEC_OID_SECG_EC_SECT571R1 },
2133       { "nistb571", SEC_OID_SECG_EC_SECT571R1 },
2134       { "secp160k1", SEC_OID_SECG_EC_SECP160K1 },
2135       { "secp160r1", SEC_OID_SECG_EC_SECP160R1 },
2136       { "secp160r2", SEC_OID_SECG_EC_SECP160R2 },
2137       { "secp192k1", SEC_OID_SECG_EC_SECP192K1 },
2138       { "secp192r1", SEC_OID_SECG_EC_SECP192R1 },
2139       { "nistp192", SEC_OID_SECG_EC_SECP192R1 },
2140       { "secp224k1", SEC_OID_SECG_EC_SECP224K1 },
2141       { "secp224r1", SEC_OID_SECG_EC_SECP224R1 },
2142       { "nistp224", SEC_OID_SECG_EC_SECP224R1 },
2143       { "secp256k1", SEC_OID_SECG_EC_SECP256K1 },
2144       { "secp256r1", SEC_OID_SECG_EC_SECP256R1 },
2145       { "nistp256", SEC_OID_SECG_EC_SECP256R1 },
2146       { "secp384r1", SEC_OID_SECG_EC_SECP384R1 },
2147       { "nistp384", SEC_OID_SECG_EC_SECP384R1 },
2148       { "secp521r1", SEC_OID_SECG_EC_SECP521R1 },
2149       { "nistp521", SEC_OID_SECG_EC_SECP521R1 },
2150 
2151       { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
2152       { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
2153       { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
2154       { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
2155       { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
2156       { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
2157 
2158       { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
2159       { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
2160       { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
2161       { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
2162       { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
2163       { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
2164       { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
2165       { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
2166       { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
2167       { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
2168       { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
2169       { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
2170       { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
2171       { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
2172       { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
2173       { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
2174       { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
2175       { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
2176       { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
2177       { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
2178 
2179       { "secp112r1", SEC_OID_SECG_EC_SECP112R1 },
2180       { "secp112r2", SEC_OID_SECG_EC_SECP112R2 },
2181       { "secp128r1", SEC_OID_SECG_EC_SECP128R1 },
2182       { "secp128r2", SEC_OID_SECG_EC_SECP128R2 },
2183 
2184       { "sect113r1", SEC_OID_SECG_EC_SECT113R1 },
2185       { "sect113r2", SEC_OID_SECG_EC_SECT113R2 },
2186       { "sect131r1", SEC_OID_SECG_EC_SECT131R1 },
2187       { "sect131r2", SEC_OID_SECG_EC_SECT131R2 },
2188     };
2189 
2190 static SECItem *
getECParams(const char * curve)2191 getECParams(const char *curve)
2192 {
2193     SECItem *ecparams;
2194     SECOidData *oidData = NULL;
2195     SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
2196     int i, numCurves;
2197 
2198     if (curve != NULL) {
2199         numCurves = sizeof(nameTagPair) / sizeof(CurveNameTagPair);
2200         for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN));
2201              i++) {
2202             if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
2203                 curveOidTag = nameTagPair[i].curveOidTag;
2204         }
2205     }
2206 
2207     /* Return NULL if curve name is not recognized */
2208     if ((curveOidTag == SEC_OID_UNKNOWN) ||
2209         (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
2210         fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
2211         return NULL;
2212     }
2213 
2214     ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
2215 
2216     /*
2217      * ecparams->data needs to contain the ASN encoding of an object ID (OID)
2218      * representing the named curve. The actual OID is in
2219      * oidData->oid.data so we simply prepend 0x06 and OID length
2220      */
2221     ecparams->data[0] = SEC_ASN1_OBJECT_ID;
2222     ecparams->data[1] = oidData->oid.len;
2223     memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
2224 
2225     return ecparams;
2226 }
2227 
2228 /*
2229  * HASH_ functions are available to full NSS apps and internally inside
2230  * freebl, but not exported to users of freebl. Create short stubs to
2231  * replace the functionality for fipstest.
2232  */
2233 SECStatus
fips_hashBuf(HASH_HashType type,unsigned char * hashBuf,unsigned char * msg,int len)2234 fips_hashBuf(HASH_HashType type, unsigned char *hashBuf,
2235              unsigned char *msg, int len)
2236 {
2237     SECStatus rv = SECFailure;
2238 
2239     switch (type) {
2240         case HASH_AlgSHA1:
2241             rv = SHA1_HashBuf(hashBuf, msg, len);
2242             break;
2243         case HASH_AlgSHA224:
2244             rv = SHA224_HashBuf(hashBuf, msg, len);
2245             break;
2246         case HASH_AlgSHA256:
2247             rv = SHA256_HashBuf(hashBuf, msg, len);
2248             break;
2249         case HASH_AlgSHA384:
2250             rv = SHA384_HashBuf(hashBuf, msg, len);
2251             break;
2252         case HASH_AlgSHA512:
2253             rv = SHA512_HashBuf(hashBuf, msg, len);
2254             break;
2255         default:
2256             break;
2257     }
2258     return rv;
2259 }
2260 
2261 int
fips_hashLen(HASH_HashType type)2262 fips_hashLen(HASH_HashType type)
2263 {
2264     int len = 0;
2265 
2266     switch (type) {
2267         case HASH_AlgSHA1:
2268             len = SHA1_LENGTH;
2269             break;
2270         case HASH_AlgSHA224:
2271             len = SHA224_LENGTH;
2272             break;
2273         case HASH_AlgSHA256:
2274             len = SHA256_LENGTH;
2275             break;
2276         case HASH_AlgSHA384:
2277             len = SHA384_LENGTH;
2278             break;
2279         case HASH_AlgSHA512:
2280             len = SHA512_LENGTH;
2281             break;
2282         default:
2283             break;
2284     }
2285     return len;
2286 }
2287 
2288 SECOidTag
fips_hashOid(HASH_HashType type)2289 fips_hashOid(HASH_HashType type)
2290 {
2291     SECOidTag oid = SEC_OID_UNKNOWN;
2292 
2293     switch (type) {
2294         case HASH_AlgSHA1:
2295             oid = SEC_OID_SHA1;
2296             break;
2297         case HASH_AlgSHA224:
2298             oid = SEC_OID_SHA224;
2299             break;
2300         case HASH_AlgSHA256:
2301             oid = SEC_OID_SHA256;
2302             break;
2303         case HASH_AlgSHA384:
2304             oid = SEC_OID_SHA384;
2305             break;
2306         case HASH_AlgSHA512:
2307             oid = SEC_OID_SHA512;
2308             break;
2309         default:
2310             break;
2311     }
2312     return oid;
2313 }
2314 
2315 HASH_HashType
sha_get_hashType(int hashbits)2316 sha_get_hashType(int hashbits)
2317 {
2318     HASH_HashType hashType = HASH_AlgNULL;
2319 
2320     switch (hashbits) {
2321         case 1:
2322         case (SHA1_LENGTH * PR_BITS_PER_BYTE):
2323             hashType = HASH_AlgSHA1;
2324             break;
2325         case (SHA224_LENGTH * PR_BITS_PER_BYTE):
2326             hashType = HASH_AlgSHA224;
2327             break;
2328         case (SHA256_LENGTH * PR_BITS_PER_BYTE):
2329             hashType = HASH_AlgSHA256;
2330             break;
2331         case (SHA384_LENGTH * PR_BITS_PER_BYTE):
2332             hashType = HASH_AlgSHA384;
2333             break;
2334         case (SHA512_LENGTH * PR_BITS_PER_BYTE):
2335             hashType = HASH_AlgSHA512;
2336             break;
2337         default:
2338             break;
2339     }
2340     return hashType;
2341 }
2342 
2343 HASH_HashType
hash_string_to_hashType(const char * src)2344 hash_string_to_hashType(const char *src)
2345 {
2346     HASH_HashType shaAlg = HASH_AlgNULL;
2347     if (strncmp(src, "SHA-1", 5) == 0) {
2348         shaAlg = HASH_AlgSHA1;
2349     } else if (strncmp(src, "SHA-224", 7) == 0) {
2350         shaAlg = HASH_AlgSHA224;
2351     } else if (strncmp(src, "SHA-256", 7) == 0) {
2352         shaAlg = HASH_AlgSHA256;
2353     } else if (strncmp(src, "SHA-384", 7) == 0) {
2354         shaAlg = HASH_AlgSHA384;
2355     } else if (strncmp(src, "SHA-512", 7) == 0) {
2356         shaAlg = HASH_AlgSHA512;
2357     } else if (strncmp(src, "SHA1", 4) == 0) {
2358         shaAlg = HASH_AlgSHA1;
2359     } else if (strncmp(src, "SHA224", 6) == 0) {
2360         shaAlg = HASH_AlgSHA224;
2361     } else if (strncmp(src, "SHA256", 6) == 0) {
2362         shaAlg = HASH_AlgSHA256;
2363     } else if (strncmp(src, "SHA384", 6) == 0) {
2364         shaAlg = HASH_AlgSHA384;
2365     } else if (strncmp(src, "SHA512", 6) == 0) {
2366         shaAlg = HASH_AlgSHA512;
2367     }
2368     return shaAlg;
2369 }
2370 
2371 /*
2372  * Perform the ECDSA Key Pair Generation Test.
2373  *
2374  * reqfn is the pathname of the REQUEST file.
2375  *
2376  * The output RESPONSE file is written to stdout.
2377  */
2378 void
ecdsa_keypair_test(char * reqfn)2379 ecdsa_keypair_test(char *reqfn)
2380 {
2381     char buf[256];   /* holds one line from the input REQUEST file
2382                          * or to the output RESPONSE file.
2383                          * needs to be large enough to hold the longest
2384                          * line "Qx = <144 hex digits>\n".
2385                          */
2386     FILE *ecdsareq;  /* input stream from the REQUEST file */
2387     FILE *ecdsaresp; /* output stream to the RESPONSE file */
2388     char curve[16];  /* "nistxddd" */
2389     ECParams *ecparams = NULL;
2390     int N;
2391     int i;
2392     unsigned int len;
2393 
2394     ecdsareq = fopen(reqfn, "r");
2395     ecdsaresp = stdout;
2396     strcpy(curve, "nist");
2397     while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2398         /* a comment or blank line */
2399         if (buf[0] == '#' || buf[0] == '\n') {
2400             fputs(buf, ecdsaresp);
2401             continue;
2402         }
2403         /* [X-ddd] */
2404         if (buf[0] == '[') {
2405             const char *src;
2406             char *dst;
2407             SECItem *encodedparams;
2408 
2409             if (buf[1] == 'B') {
2410                 fputs(buf, ecdsaresp);
2411                 continue;
2412             }
2413             if (ecparams) {
2414                 PORT_FreeArena(ecparams->arena, PR_FALSE);
2415                 ecparams = NULL;
2416             }
2417 
2418             src = &buf[1];
2419             dst = &curve[4];
2420             *dst++ = tolower(*src);
2421             src += 2; /* skip the hyphen */
2422             *dst++ = *src++;
2423             *dst++ = *src++;
2424             *dst++ = *src++;
2425             *dst = '\0';
2426             encodedparams = getECParams(curve);
2427             if (encodedparams == NULL) {
2428                 fprintf(stderr, "Unknown curve %s.", curve);
2429                 goto loser;
2430             }
2431             if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2432                 fprintf(stderr, "Curve %s not supported.\n", curve);
2433                 goto loser;
2434             }
2435             SECITEM_FreeItem(encodedparams, PR_TRUE);
2436             fputs(buf, ecdsaresp);
2437             continue;
2438         }
2439         /* N = x */
2440         if (buf[0] == 'N') {
2441             if (sscanf(buf, "N = %d", &N) != 1) {
2442                 goto loser;
2443             }
2444             for (i = 0; i < N; i++) {
2445                 ECPrivateKey *ecpriv;
2446 
2447                 if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
2448                     goto loser;
2449                 }
2450                 fputs("d = ", ecdsaresp);
2451                 to_hex_str(buf, ecpriv->privateValue.data,
2452                            ecpriv->privateValue.len);
2453                 fputs(buf, ecdsaresp);
2454                 fputc('\n', ecdsaresp);
2455                 if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue) !=
2456                     SECSuccess) {
2457                     goto loser;
2458                 }
2459                 len = ecpriv->publicValue.len;
2460                 if (len % 2 == 0) {
2461                     goto loser;
2462                 }
2463                 len = (len - 1) / 2;
2464                 if (ecpriv->publicValue.data[0] !=
2465                     EC_POINT_FORM_UNCOMPRESSED) {
2466                     goto loser;
2467                 }
2468                 fputs("Qx = ", ecdsaresp);
2469                 to_hex_str(buf, &ecpriv->publicValue.data[1], len);
2470                 fputs(buf, ecdsaresp);
2471                 fputc('\n', ecdsaresp);
2472                 fputs("Qy = ", ecdsaresp);
2473                 to_hex_str(buf, &ecpriv->publicValue.data[1 + len], len);
2474                 fputs(buf, ecdsaresp);
2475                 fputc('\n', ecdsaresp);
2476                 fputc('\n', ecdsaresp);
2477                 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
2478             }
2479             continue;
2480         }
2481     }
2482 loser:
2483     if (ecparams) {
2484         PORT_FreeArena(ecparams->arena, PR_FALSE);
2485         ecparams = NULL;
2486     }
2487     fclose(ecdsareq);
2488 }
2489 
2490 /*
2491  * Perform the ECDSA Public Key Validation Test.
2492  *
2493  * reqfn is the pathname of the REQUEST file.
2494  *
2495  * The output RESPONSE file is written to stdout.
2496  */
2497 void
ecdsa_pkv_test(char * reqfn)2498 ecdsa_pkv_test(char *reqfn)
2499 {
2500     char buf[256];   /* holds one line from the input REQUEST file.
2501                          * needs to be large enough to hold the longest
2502                          * line "Qx = <144 hex digits>\n".
2503                          */
2504     FILE *ecdsareq;  /* input stream from the REQUEST file */
2505     FILE *ecdsaresp; /* output stream to the RESPONSE file */
2506     char curve[16];  /* "nistxddd" */
2507     ECParams *ecparams = NULL;
2508     SECItem pubkey;
2509     unsigned int i;
2510     unsigned int len = 0;
2511     PRBool keyvalid = PR_TRUE;
2512 
2513     ecdsareq = fopen(reqfn, "r");
2514     ecdsaresp = stdout;
2515     strcpy(curve, "nist");
2516     pubkey.data = NULL;
2517     while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2518         /* a comment or blank line */
2519         if (buf[0] == '#' || buf[0] == '\n') {
2520             fputs(buf, ecdsaresp);
2521             continue;
2522         }
2523         /* [X-ddd] */
2524         if (buf[0] == '[') {
2525             const char *src;
2526             char *dst;
2527             SECItem *encodedparams;
2528 
2529             src = &buf[1];
2530             dst = &curve[4];
2531             *dst++ = tolower(*src);
2532             src += 2; /* skip the hyphen */
2533             *dst++ = *src++;
2534             *dst++ = *src++;
2535             *dst++ = *src++;
2536             *dst = '\0';
2537             if (ecparams != NULL) {
2538                 PORT_FreeArena(ecparams->arena, PR_FALSE);
2539                 ecparams = NULL;
2540             }
2541             encodedparams = getECParams(curve);
2542             if (encodedparams == NULL) {
2543                 fprintf(stderr, "Unknown curve %s.", curve);
2544                 goto loser;
2545             }
2546             if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2547                 fprintf(stderr, "Curve %s not supported.\n", curve);
2548                 goto loser;
2549             }
2550             SECITEM_FreeItem(encodedparams, PR_TRUE);
2551             len = (ecparams->fieldID.size + 7) >> 3;
2552             if (pubkey.data != NULL) {
2553                 PORT_Free(pubkey.data);
2554                 pubkey.data = NULL;
2555             }
2556             SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(ecparams));
2557             if (pubkey.data == NULL) {
2558                 goto loser;
2559             }
2560             pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
2561             fputs(buf, ecdsaresp);
2562             continue;
2563         }
2564         /* Qx = ... */
2565         if (strncmp(buf, "Qx", 2) == 0) {
2566             fputs(buf, ecdsaresp);
2567             i = 2;
2568             while (isspace(buf[i]) || buf[i] == '=') {
2569                 i++;
2570             }
2571             keyvalid = from_hex_str(&pubkey.data[1], len, &buf[i]);
2572             continue;
2573         }
2574         /* Qy = ... */
2575         if (strncmp(buf, "Qy", 2) == 0) {
2576             fputs(buf, ecdsaresp);
2577             if (!keyvalid) {
2578                 fputs("Result = F\n", ecdsaresp);
2579                 continue;
2580             }
2581             i = 2;
2582             while (isspace(buf[i]) || buf[i] == '=') {
2583                 i++;
2584             }
2585             keyvalid = from_hex_str(&pubkey.data[1 + len], len, &buf[i]);
2586             if (!keyvalid) {
2587                 fputs("Result = F\n", ecdsaresp);
2588                 continue;
2589             }
2590             if (EC_ValidatePublicKey(ecparams, &pubkey) == SECSuccess) {
2591                 fputs("Result = P\n", ecdsaresp);
2592             } else if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
2593                 fputs("Result = F\n", ecdsaresp);
2594             } else {
2595                 goto loser;
2596             }
2597             continue;
2598         }
2599     }
2600 loser:
2601     if (ecparams != NULL) {
2602         PORT_FreeArena(ecparams->arena, PR_FALSE);
2603     }
2604     if (pubkey.data != NULL) {
2605         PORT_Free(pubkey.data);
2606     }
2607     fclose(ecdsareq);
2608 }
2609 
2610 /*
2611  * Perform the ECDSA Signature Generation Test.
2612  *
2613  * reqfn is the pathname of the REQUEST file.
2614  *
2615  * The output RESPONSE file is written to stdout.
2616  */
2617 void
ecdsa_siggen_test(char * reqfn)2618 ecdsa_siggen_test(char *reqfn)
2619 {
2620     char buf[1024];  /* holds one line from the input REQUEST file
2621                          * or to the output RESPONSE file.
2622                          * needs to be large enough to hold the longest
2623                          * line "Msg = <256 hex digits>\n".
2624                          */
2625     FILE *ecdsareq;  /* input stream from the REQUEST file */
2626     FILE *ecdsaresp; /* output stream to the RESPONSE file */
2627     char curve[16];  /* "nistxddd" */
2628     ECParams *ecparams = NULL;
2629     int i, j;
2630     unsigned int len;
2631     unsigned char msg[512]; /* message to be signed (<= 128 bytes) */
2632     unsigned int msglen;
2633     unsigned char sha[HASH_LENGTH_MAX];  /* SHA digest */
2634     unsigned int shaLength = 0;          /* length of SHA */
2635     HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
2636     unsigned char sig[2 * MAX_ECKEY_LEN];
2637     SECItem signature, digest;
2638 
2639     ecdsareq = fopen(reqfn, "r");
2640     ecdsaresp = stdout;
2641     strcpy(curve, "nist");
2642     while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2643         /* a comment or blank line */
2644         if (buf[0] == '#' || buf[0] == '\n') {
2645             fputs(buf, ecdsaresp);
2646             continue;
2647         }
2648         /* [X-ddd] */
2649         if (buf[0] == '[') {
2650             const char *src;
2651             char *dst;
2652             SECItem *encodedparams;
2653 
2654             src = &buf[1];
2655             dst = &curve[4];
2656             *dst++ = tolower(*src);
2657             src += 2; /* skip the hyphen */
2658             *dst++ = *src++;
2659             *dst++ = *src++;
2660             *dst++ = *src++;
2661             *dst = '\0';
2662             src++; /* skip the comma */
2663             /* set the SHA Algorithm */
2664             shaAlg = hash_string_to_hashType(src);
2665             if (shaAlg == HASH_AlgNULL) {
2666                 fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type");
2667                 goto loser;
2668             }
2669             if (ecparams != NULL) {
2670                 PORT_FreeArena(ecparams->arena, PR_FALSE);
2671                 ecparams = NULL;
2672             }
2673             encodedparams = getECParams(curve);
2674             if (encodedparams == NULL) {
2675                 fprintf(stderr, "Unknown curve %s.", curve);
2676                 goto loser;
2677             }
2678             if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2679                 fprintf(stderr, "Curve %s not supported.\n", curve);
2680                 goto loser;
2681             }
2682             SECITEM_FreeItem(encodedparams, PR_TRUE);
2683             fputs(buf, ecdsaresp);
2684             continue;
2685         }
2686         /* Msg = ... */
2687         if (strncmp(buf, "Msg", 3) == 0) {
2688             ECPrivateKey *ecpriv;
2689 
2690             i = 3;
2691             while (isspace(buf[i]) || buf[i] == '=') {
2692                 i++;
2693             }
2694             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
2695                 hex_to_byteval(&buf[i], &msg[j]);
2696             }
2697             msglen = j;
2698             shaLength = fips_hashLen(shaAlg);
2699             if (fips_hashBuf(shaAlg, sha, msg, msglen) != SECSuccess) {
2700                 if (shaLength == 0) {
2701                     fprintf(ecdsaresp, "ERROR: SHAAlg not defined.");
2702                 }
2703                 fprintf(ecdsaresp, "ERROR: Unable to generate SHA%x",
2704                         shaLength == 160 ? 1 : shaLength);
2705                 goto loser;
2706             }
2707             fputs(buf, ecdsaresp);
2708 
2709             if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
2710                 goto loser;
2711             }
2712             if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue) !=
2713                 SECSuccess) {
2714                 goto loser;
2715             }
2716             len = ecpriv->publicValue.len;
2717             if (len % 2 == 0) {
2718                 goto loser;
2719             }
2720             len = (len - 1) / 2;
2721             if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
2722                 goto loser;
2723             }
2724             fputs("Qx = ", ecdsaresp);
2725             to_hex_str(buf, &ecpriv->publicValue.data[1], len);
2726             fputs(buf, ecdsaresp);
2727             fputc('\n', ecdsaresp);
2728             fputs("Qy = ", ecdsaresp);
2729             to_hex_str(buf, &ecpriv->publicValue.data[1 + len], len);
2730             fputs(buf, ecdsaresp);
2731             fputc('\n', ecdsaresp);
2732 
2733             digest.type = siBuffer;
2734             digest.data = sha;
2735             digest.len = shaLength;
2736             signature.type = siBuffer;
2737             signature.data = sig;
2738             signature.len = sizeof sig;
2739             if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) {
2740                 goto loser;
2741             }
2742             len = signature.len;
2743             if (len % 2 != 0) {
2744                 goto loser;
2745             }
2746             len = len / 2;
2747             fputs("R = ", ecdsaresp);
2748             to_hex_str(buf, &signature.data[0], len);
2749             fputs(buf, ecdsaresp);
2750             fputc('\n', ecdsaresp);
2751             fputs("S = ", ecdsaresp);
2752             to_hex_str(buf, &signature.data[len], len);
2753             fputs(buf, ecdsaresp);
2754             fputc('\n', ecdsaresp);
2755 
2756             PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
2757             continue;
2758         }
2759     }
2760 loser:
2761     if (ecparams != NULL) {
2762         PORT_FreeArena(ecparams->arena, PR_FALSE);
2763     }
2764     fclose(ecdsareq);
2765 }
2766 
2767 /*
2768  * Perform the ECDSA Signature Verification Test.
2769  *
2770  * reqfn is the pathname of the REQUEST file.
2771  *
2772  * The output RESPONSE file is written to stdout.
2773  */
2774 void
ecdsa_sigver_test(char * reqfn)2775 ecdsa_sigver_test(char *reqfn)
2776 {
2777     char buf[1024];  /* holds one line from the input REQUEST file.
2778                          * needs to be large enough to hold the longest
2779                          * line "Msg = <256 hex digits>\n".
2780                          */
2781     FILE *ecdsareq;  /* input stream from the REQUEST file */
2782     FILE *ecdsaresp; /* output stream to the RESPONSE file */
2783     char curve[16];  /* "nistxddd" */
2784     ECPublicKey ecpub;
2785     unsigned int i, j;
2786     unsigned int flen = 0;  /* length in bytes of the field size */
2787     unsigned int olen = 0;  /* length in bytes of the base point order */
2788     unsigned char msg[512]; /* message that was signed (<= 128 bytes) */
2789     unsigned int msglen = 0;
2790     unsigned char sha[HASH_LENGTH_MAX];  /* SHA digest */
2791     unsigned int shaLength = 0;          /* length of SHA */
2792     HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
2793     unsigned char sig[2 * MAX_ECKEY_LEN];
2794     SECItem signature, digest;
2795     PRBool keyvalid = PR_TRUE;
2796     PRBool sigvalid = PR_TRUE;
2797 
2798     ecdsareq = fopen(reqfn, "r");
2799     ecdsaresp = stdout;
2800     ecpub.ecParams.arena = NULL;
2801     strcpy(curve, "nist");
2802     while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
2803         /* a comment or blank line */
2804         if (buf[0] == '#' || buf[0] == '\n') {
2805             fputs(buf, ecdsaresp);
2806             continue;
2807         }
2808         /* [X-ddd] */
2809         if (buf[0] == '[') {
2810             const char *src;
2811             char *dst;
2812             SECItem *encodedparams;
2813             ECParams *ecparams;
2814 
2815             src = &buf[1];
2816             dst = &curve[4];
2817             *dst++ = tolower(*src);
2818             src += 2; /* skip the hyphen */
2819             *dst++ = *src++;
2820             *dst++ = *src++;
2821             *dst++ = *src++;
2822             *dst = '\0';
2823             src++; /* skip the comma */
2824             /* set the SHA Algorithm */
2825             shaAlg = hash_string_to_hashType(src);
2826             if (shaAlg == HASH_AlgNULL) {
2827                 fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type");
2828                 goto loser;
2829             }
2830             encodedparams = getECParams(curve);
2831             if (encodedparams == NULL) {
2832                 fprintf(stderr, "Unknown curve %s.", curve);
2833                 goto loser;
2834             }
2835             if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
2836                 fprintf(stderr, "Curve %s not supported.\n", curve);
2837                 goto loser;
2838             }
2839             SECITEM_FreeItem(encodedparams, PR_TRUE);
2840             if (ecpub.ecParams.arena != NULL) {
2841                 PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
2842             }
2843             ecpub.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2844             if (ecpub.ecParams.arena == NULL) {
2845                 goto loser;
2846             }
2847             if (EC_CopyParams(ecpub.ecParams.arena, &ecpub.ecParams, ecparams) !=
2848                 SECSuccess) {
2849                 goto loser;
2850             }
2851             PORT_FreeArena(ecparams->arena, PR_FALSE);
2852             flen = (ecpub.ecParams.fieldID.size + 7) >> 3;
2853             olen = ecpub.ecParams.order.len;
2854             if (2 * olen > sizeof sig) {
2855                 goto loser;
2856             }
2857             ecpub.publicValue.type = siBuffer;
2858             ecpub.publicValue.data = NULL;
2859             ecpub.publicValue.len = 0;
2860             SECITEM_AllocItem(ecpub.ecParams.arena,
2861                               &ecpub.publicValue, 2 * flen + 1);
2862             if (ecpub.publicValue.data == NULL) {
2863                 goto loser;
2864             }
2865             ecpub.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED;
2866             fputs(buf, ecdsaresp);
2867             continue;
2868         }
2869         /* Msg = ... */
2870         if (strncmp(buf, "Msg", 3) == 0) {
2871             i = 3;
2872             while (isspace(buf[i]) || buf[i] == '=') {
2873                 i++;
2874             }
2875             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
2876                 hex_to_byteval(&buf[i], &msg[j]);
2877             }
2878             msglen = j;
2879             shaLength = fips_hashLen(shaAlg);
2880             if (fips_hashBuf(shaAlg, sha, msg, msglen) != SECSuccess) {
2881                 if (shaLength == 0) {
2882                     fprintf(ecdsaresp, "ERROR: SHAAlg not defined.");
2883                 }
2884                 fprintf(ecdsaresp, "ERROR: Unable to generate SHA%x",
2885                         shaLength == 160 ? 1 : shaLength);
2886                 goto loser;
2887             }
2888             fputs(buf, ecdsaresp);
2889 
2890             digest.type = siBuffer;
2891             digest.data = sha;
2892             digest.len = shaLength;
2893 
2894             continue;
2895         }
2896         /* Qx = ... */
2897         if (strncmp(buf, "Qx", 2) == 0) {
2898             fputs(buf, ecdsaresp);
2899             i = 2;
2900             while (isspace(buf[i]) || buf[i] == '=') {
2901                 i++;
2902             }
2903             keyvalid = from_hex_str(&ecpub.publicValue.data[1], flen,
2904                                     &buf[i]);
2905             continue;
2906         }
2907         /* Qy = ... */
2908         if (strncmp(buf, "Qy", 2) == 0) {
2909             fputs(buf, ecdsaresp);
2910             if (!keyvalid) {
2911                 continue;
2912             }
2913             i = 2;
2914             while (isspace(buf[i]) || buf[i] == '=') {
2915                 i++;
2916             }
2917             keyvalid = from_hex_str(&ecpub.publicValue.data[1 + flen], flen,
2918                                     &buf[i]);
2919             if (!keyvalid) {
2920                 continue;
2921             }
2922             if (EC_ValidatePublicKey(&ecpub.ecParams, &ecpub.publicValue) !=
2923                 SECSuccess) {
2924                 if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
2925                     keyvalid = PR_FALSE;
2926                 } else {
2927                     goto loser;
2928                 }
2929             }
2930             continue;
2931         }
2932         /* R = ... */
2933         if (buf[0] == 'R') {
2934             fputs(buf, ecdsaresp);
2935             i = 1;
2936             while (isspace(buf[i]) || buf[i] == '=') {
2937                 i++;
2938             }
2939             sigvalid = from_hex_str(sig, olen, &buf[i]);
2940             continue;
2941         }
2942         /* S = ... */
2943         if (buf[0] == 'S') {
2944             fputs(buf, ecdsaresp);
2945             i = 1;
2946             while (isspace(buf[i]) || buf[i] == '=') {
2947                 i++;
2948             }
2949             if (sigvalid) {
2950                 sigvalid = from_hex_str(&sig[olen], olen, &buf[i]);
2951             }
2952             signature.type = siBuffer;
2953             signature.data = sig;
2954             signature.len = 2 * olen;
2955 
2956             if (!keyvalid || !sigvalid) {
2957                 fputs("Result = F\n", ecdsaresp);
2958             } else if (ECDSA_VerifyDigest(&ecpub, &signature, &digest) ==
2959                        SECSuccess) {
2960                 fputs("Result = P\n", ecdsaresp);
2961             } else {
2962                 fputs("Result = F\n", ecdsaresp);
2963             }
2964             continue;
2965         }
2966     }
2967 loser:
2968     if (ecpub.ecParams.arena != NULL) {
2969         PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
2970     }
2971     fclose(ecdsareq);
2972 }
2973 
2974 /*
2975  * Perform the ECDH Functional Test.
2976  *
2977  * reqfn is the pathname of the REQUEST file.
2978  *
2979  * The output RESPONSE file is written to stdout.
2980  */
2981 #define MAX_ECC_PARAMS 256
2982 void
ecdh_functional(char * reqfn,PRBool response)2983 ecdh_functional(char *reqfn, PRBool response)
2984 {
2985     char buf[256];  /* holds one line from the input REQUEST file.
2986                          * needs to be large enough to hold the longest
2987                          * line "Qx = <144 hex digits>\n".
2988                          */
2989     FILE *ecdhreq;  /* input stream from the REQUEST file */
2990     FILE *ecdhresp; /* output stream to the RESPONSE file */
2991     char curve[16]; /* "nistxddd" */
2992     unsigned char hashBuf[HASH_LENGTH_MAX];
2993     ECParams *ecparams[MAX_ECC_PARAMS] = { NULL };
2994     ECPrivateKey *ecpriv = NULL;
2995     ECParams *current_ecparams = NULL;
2996     SECItem pubkey;
2997     SECItem ZZ;
2998     unsigned int i;
2999     unsigned int len = 0;
3000     unsigned int uit_len = 0;
3001     int current_curve = -1;
3002     HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
3003 
3004     ecdhreq = fopen(reqfn, "r");
3005     ecdhresp = stdout;
3006     strcpy(curve, "nist");
3007     pubkey.data = NULL;
3008     while (fgets(buf, sizeof buf, ecdhreq) != NULL) {
3009         /* a comment or blank line */
3010         if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
3011             fputs(buf, ecdhresp);
3012             continue;
3013         }
3014         if (buf[0] == '[') {
3015             /* [Ex] */
3016             if (buf[1] == 'E' && buf[3] == ']') {
3017                 current_curve = buf[2] - 'A';
3018                 fputs(buf, ecdhresp);
3019                 continue;
3020             }
3021             /* [Curve selected: x-nnn */
3022             if (strncmp(buf, "[Curve ", 7) == 0) {
3023                 const char *src;
3024                 char *dst;
3025                 SECItem *encodedparams;
3026 
3027                 if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) {
3028                     fprintf(stderr, "No curve type defined\n");
3029                     goto loser;
3030                 }
3031 
3032                 src = &buf[1];
3033                 /* skip passed the colon */
3034                 while (*src && *src != ':')
3035                     src++;
3036                 if (*src != ':') {
3037                     fprintf(stderr,
3038                             "No colon in curve selected statement\n%s", buf);
3039                     goto loser;
3040                 }
3041                 src++;
3042                 /* skip to the first non-space */
3043                 while (*src && *src == ' ')
3044                     src++;
3045                 dst = &curve[4];
3046                 *dst++ = tolower(*src);
3047                 src += 2; /* skip the hyphen */
3048                 *dst++ = *src++;
3049                 *dst++ = *src++;
3050                 *dst++ = *src++;
3051                 *dst = '\0';
3052                 if (ecparams[current_curve] != NULL) {
3053                     PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE);
3054                     ecparams[current_curve] = NULL;
3055                 }
3056                 encodedparams = getECParams(curve);
3057                 if (encodedparams == NULL) {
3058                     fprintf(stderr, "Unknown curve %s.", curve);
3059                     goto loser;
3060                 }
3061                 if (EC_DecodeParams(encodedparams, &ecparams[current_curve]) != SECSuccess) {
3062                     fprintf(stderr, "Curve %s not supported.\n", curve);
3063                     goto loser;
3064                 }
3065                 SECITEM_FreeItem(encodedparams, PR_TRUE);
3066                 fputs(buf, ecdhresp);
3067                 continue;
3068             }
3069             /* [Ex - SHAxxx] */
3070             if (buf[1] == 'E' && buf[3] == ' ') {
3071                 const char *src;
3072                 current_curve = buf[2] - 'A';
3073                 if ((current_curve < 0) || (current_curve > 256)) {
3074                     fprintf(stderr, "bad curve type defined (%c)\n", buf[2]);
3075                     goto loser;
3076                 }
3077                 current_ecparams = ecparams[current_curve];
3078                 if (current_ecparams == NULL) {
3079                     fprintf(stderr, "no curve defined for type %c defined\n",
3080                             buf[2]);
3081                     goto loser;
3082                 }
3083                 /* skip passed the colon */
3084                 src = &buf[1];
3085                 while (*src && *src != '-')
3086                     src++;
3087                 if (*src != '-') {
3088                     fprintf(stderr,
3089                             "No data in curve selected statement\n%s", buf);
3090                     goto loser;
3091                 }
3092                 src++;
3093                 /* skip to the first non-space */
3094                 while (*src && *src == ' ')
3095                     src++;
3096                 hash = hash_string_to_hashType(src);
3097                 if (hash == HASH_AlgNULL) {
3098                     fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type");
3099                     goto loser;
3100                 }
3101                 fputs(buf, ecdhresp);
3102                 continue;
3103             }
3104             fputs(buf, ecdhresp);
3105             continue;
3106         }
3107         /* COUNT = ... */
3108         if (strncmp(buf, "COUNT", 5) == 0) {
3109             fputs(buf, ecdhresp);
3110             if (current_ecparams == NULL) {
3111                 fprintf(stderr, "no curve defined for type %c defined\n",
3112                         buf[2]);
3113                 goto loser;
3114             }
3115             len = (current_ecparams->fieldID.size + 7) >> 3;
3116             if (pubkey.data != NULL) {
3117                 PORT_Free(pubkey.data);
3118                 pubkey.data = NULL;
3119             }
3120             SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams));
3121             if (pubkey.data == NULL) {
3122                 goto loser;
3123             }
3124             pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
3125             continue;
3126         }
3127         /* QeCAVSx = ... */
3128         if (strncmp(buf, "QeCAVSx", 7) == 0) {
3129             fputs(buf, ecdhresp);
3130             i = 7;
3131             while (isspace(buf[i]) || buf[i] == '=') {
3132                 i++;
3133             }
3134             from_hex_str(&pubkey.data[1], len, &buf[i]);
3135             continue;
3136         }
3137         /* QeCAVSy = ... */
3138         if (strncmp(buf, "QeCAVSy", 7) == 0) {
3139             fputs(buf, ecdhresp);
3140             i = 7;
3141             while (isspace(buf[i]) || buf[i] == '=') {
3142                 i++;
3143             }
3144             from_hex_str(&pubkey.data[1 + len], len, &buf[i]);
3145             if (current_ecparams == NULL) {
3146                 fprintf(stderr, "no curve defined\n");
3147                 goto loser;
3148             }
3149             /* validate CAVS public key */
3150             if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) {
3151                 fprintf(stderr, "BAD key detected\n");
3152                 goto loser;
3153             }
3154 
3155             /* generate ECC key pair */
3156             if (EC_NewKey(current_ecparams, &ecpriv) != SECSuccess) {
3157                 fprintf(stderr, "Failed to generate new key\n");
3158                 goto loser;
3159             }
3160             /* validate UIT generated public key */
3161             if (EC_ValidatePublicKey(current_ecparams, &ecpriv->publicValue) !=
3162                 SECSuccess) {
3163                 fprintf(stderr, "generate key did not validate\n");
3164                 goto loser;
3165             }
3166             /* output UIT public key */
3167             uit_len = ecpriv->publicValue.len;
3168             if (uit_len % 2 == 0) {
3169                 fprintf(stderr, "generate key had invalid public value len\n");
3170                 goto loser;
3171             }
3172             uit_len = (uit_len - 1) / 2;
3173             if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
3174                 fprintf(stderr, "generate key was compressed\n");
3175                 goto loser;
3176             }
3177             fputs("deIUT = ", ecdhresp);
3178             to_hex_str(buf, ecpriv->privateValue.data, ecpriv->privateValue.len);
3179             fputs(buf, ecdhresp);
3180             fputc('\n', ecdhresp);
3181             fputs("QeIUTx = ", ecdhresp);
3182             to_hex_str(buf, &ecpriv->publicValue.data[1], uit_len);
3183             fputs(buf, ecdhresp);
3184             fputc('\n', ecdhresp);
3185             fputs("QeIUTy = ", ecdhresp);
3186             to_hex_str(buf, &ecpriv->publicValue.data[1 + uit_len], uit_len);
3187             fputs(buf, ecdhresp);
3188             fputc('\n', ecdhresp);
3189             /* ECDH */
3190             if (ECDH_Derive(&pubkey, current_ecparams, &ecpriv->privateValue,
3191                             PR_FALSE, &ZZ) != SECSuccess) {
3192                 fprintf(stderr, "Derive failed\n");
3193                 goto loser;
3194             }
3195             /* output hash of ZZ */
3196             if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
3197                 fprintf(stderr, "hash of derived key failed\n");
3198                 goto loser;
3199             }
3200             SECITEM_FreeItem(&ZZ, PR_FALSE);
3201             fputs("HashZZ = ", ecdhresp);
3202             to_hex_str(buf, hashBuf, fips_hashLen(hash));
3203             fputs(buf, ecdhresp);
3204             fputc('\n', ecdhresp);
3205             fputc('\n', ecdhresp);
3206             PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
3207             ecpriv = NULL;
3208             continue;
3209         }
3210     }
3211 loser:
3212     if (ecpriv != NULL) {
3213         PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
3214     }
3215     for (i = 0; i < MAX_ECC_PARAMS; i++) {
3216         if (ecparams[i] != NULL) {
3217             PORT_FreeArena(ecparams[i]->arena, PR_FALSE);
3218             ecparams[i] = NULL;
3219         }
3220     }
3221     if (pubkey.data != NULL) {
3222         PORT_Free(pubkey.data);
3223     }
3224     fclose(ecdhreq);
3225 }
3226 
3227 /*
3228  * Perform the ECDH Validity Test.
3229  *
3230  * reqfn is the pathname of the REQUEST file.
3231  *
3232  * The output RESPONSE file is written to stdout.
3233  */
3234 void
ecdh_verify(char * reqfn,PRBool response)3235 ecdh_verify(char *reqfn, PRBool response)
3236 {
3237     char buf[256];  /* holds one line from the input REQUEST file.
3238                          * needs to be large enough to hold the longest
3239                          * line "Qx = <144 hex digits>\n".
3240                          */
3241     FILE *ecdhreq;  /* input stream from the REQUEST file */
3242     FILE *ecdhresp; /* output stream to the RESPONSE file */
3243     char curve[16]; /* "nistxddd" */
3244     unsigned char hashBuf[HASH_LENGTH_MAX];
3245     unsigned char cavsHashBuf[HASH_LENGTH_MAX];
3246     unsigned char private_data[MAX_ECKEY_LEN];
3247     ECParams *ecparams[MAX_ECC_PARAMS] = { NULL };
3248     ECParams *current_ecparams = NULL;
3249     SECItem pubkey;
3250     SECItem ZZ;
3251     SECItem private_value;
3252     unsigned int i;
3253     unsigned int len = 0;
3254     int current_curve = -1;
3255     HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
3256 
3257     ecdhreq = fopen(reqfn, "r");
3258     ecdhresp = stdout;
3259     strcpy(curve, "nist");
3260     pubkey.data = NULL;
3261     while (fgets(buf, sizeof buf, ecdhreq) != NULL) {
3262         /* a comment or blank line */
3263         if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
3264             fputs(buf, ecdhresp);
3265             continue;
3266         }
3267         if (buf[0] == '[') {
3268             /* [Ex] */
3269             if (buf[1] == 'E' && buf[3] == ']') {
3270                 current_curve = buf[2] - 'A';
3271                 fputs(buf, ecdhresp);
3272                 continue;
3273             }
3274             /* [Curve selected: x-nnn */
3275             if (strncmp(buf, "[Curve ", 7) == 0) {
3276                 const char *src;
3277                 char *dst;
3278                 SECItem *encodedparams;
3279 
3280                 if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) {
3281                     fprintf(stderr, "No curve type defined\n");
3282                     goto loser;
3283                 }
3284 
3285                 src = &buf[1];
3286                 /* skip passed the colon */
3287                 while (*src && *src != ':')
3288                     src++;
3289                 if (*src != ':') {
3290                     fprintf(stderr,
3291                             "No colon in curve selected statement\n%s", buf);
3292                     goto loser;
3293                 }
3294                 src++;
3295                 /* skip to the first non-space */
3296                 while (*src && *src == ' ')
3297                     src++;
3298                 dst = &curve[4];
3299                 *dst++ = tolower(*src);
3300                 src += 2; /* skip the hyphen */
3301                 *dst++ = *src++;
3302                 *dst++ = *src++;
3303                 *dst++ = *src++;
3304                 *dst = '\0';
3305                 if (ecparams[current_curve] != NULL) {
3306                     PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE);
3307                     ecparams[current_curve] = NULL;
3308                 }
3309                 encodedparams = getECParams(curve);
3310                 if (encodedparams == NULL) {
3311                     fprintf(stderr, "Unknown curve %s.\n", curve);
3312                     goto loser;
3313                 }
3314                 if (EC_DecodeParams(encodedparams, &ecparams[current_curve]) != SECSuccess) {
3315                     fprintf(stderr, "Curve %s not supported.\n", curve);
3316                     goto loser;
3317                 }
3318                 SECITEM_FreeItem(encodedparams, PR_TRUE);
3319                 fputs(buf, ecdhresp);
3320                 continue;
3321             }
3322             /* [Ex - SHAxxx] */
3323             if (buf[1] == 'E' && buf[3] == ' ') {
3324                 const char *src;
3325                 current_curve = buf[2] - 'A';
3326                 if ((current_curve < 0) || (current_curve > 256)) {
3327                     fprintf(stderr, "bad curve type defined (%c)\n", buf[2]);
3328                     goto loser;
3329                 }
3330                 current_ecparams = ecparams[current_curve];
3331                 if (current_ecparams == NULL) {
3332                     fprintf(stderr, "no curve defined for type %c defined\n",
3333                             buf[2]);
3334                     goto loser;
3335                 }
3336                 /* skip passed the colon */
3337                 src = &buf[1];
3338                 while (*src && *src != '-')
3339                     src++;
3340                 if (*src != '-') {
3341                     fprintf(stderr,
3342                             "No data in curve selected statement\n%s", buf);
3343                     goto loser;
3344                 }
3345                 src++;
3346                 /* skip to the first non-space */
3347                 while (*src && *src == ' ')
3348                     src++;
3349                 hash = hash_string_to_hashType(src);
3350                 if (hash == HASH_AlgNULL) {
3351                     fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type");
3352                     goto loser;
3353                 }
3354                 fputs(buf, ecdhresp);
3355                 continue;
3356             }
3357             fputs(buf, ecdhresp);
3358             continue;
3359         }
3360         /* COUNT = ... */
3361         if (strncmp(buf, "COUNT", 5) == 0) {
3362             fputs(buf, ecdhresp);
3363             if (current_ecparams == NULL) {
3364                 fprintf(stderr, "no curve defined for type %c defined\n",
3365                         buf[2]);
3366                 goto loser;
3367             }
3368             len = (current_ecparams->fieldID.size + 7) >> 3;
3369             if (pubkey.data != NULL) {
3370                 PORT_Free(pubkey.data);
3371                 pubkey.data = NULL;
3372             }
3373             SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams));
3374             if (pubkey.data == NULL) {
3375                 goto loser;
3376             }
3377             pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
3378             continue;
3379         }
3380         /* QeCAVSx = ... */
3381         if (strncmp(buf, "QeCAVSx", 7) == 0) {
3382             fputs(buf, ecdhresp);
3383             i = 7;
3384             while (isspace(buf[i]) || buf[i] == '=') {
3385                 i++;
3386             }
3387             from_hex_str(&pubkey.data[1], len, &buf[i]);
3388             continue;
3389         }
3390         /* QeCAVSy = ... */
3391         if (strncmp(buf, "QeCAVSy", 7) == 0) {
3392             fputs(buf, ecdhresp);
3393             i = 7;
3394             while (isspace(buf[i]) || buf[i] == '=') {
3395                 i++;
3396             }
3397             from_hex_str(&pubkey.data[1 + len], len, &buf[i]);
3398             continue;
3399         }
3400         if (strncmp(buf, "deIUT", 5) == 0) {
3401             fputs(buf, ecdhresp);
3402             i = 5;
3403             while (isspace(buf[i]) || buf[i] == '=') {
3404                 i++;
3405             }
3406             from_hex_str(private_data, len, &buf[i]);
3407             private_value.data = private_data;
3408             private_value.len = len;
3409             continue;
3410         }
3411         if (strncmp(buf, "QeIUTx", 6) == 0) {
3412             fputs(buf, ecdhresp);
3413             continue;
3414         }
3415         if (strncmp(buf, "QeIUTy", 6) == 0) {
3416             fputs(buf, ecdhresp);
3417             continue;
3418         }
3419         if ((strncmp(buf, "CAVSHashZZ", 10) == 0) ||
3420             (strncmp(buf, "HashZZ", 6) == 0)) {
3421             fputs(buf, ecdhresp);
3422             i = (buf[0] == 'C') ? 10 : 6;
3423             while (isspace(buf[i]) || buf[i] == '=') {
3424                 i++;
3425             }
3426             from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]);
3427             if (current_ecparams == NULL) {
3428                 fprintf(stderr, "no curve defined for type defined\n");
3429                 goto loser;
3430             }
3431             /* validate CAVS public key */
3432             if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) {
3433 #ifdef VERBOSE_REASON
3434                 fprintf(ecdhresp, "Result = F # key didn't validate\n");
3435 #else
3436                 fprintf(ecdhresp, "Result = F\n");
3437 #endif
3438                 continue;
3439             }
3440 
3441             /* ECDH */
3442             if (ECDH_Derive(&pubkey, current_ecparams, &private_value,
3443                             PR_FALSE, &ZZ) != SECSuccess) {
3444 #ifdef VERBOSE_REASON
3445                 fprintf(ecdhresp, "Result = F # derive failure\n");
3446 #else
3447                 fprintf(ecdhresp, "Result = F\n");
3448 #endif
3449                 continue;
3450             }
3451 /* output  ZZ */
3452 #ifndef MATCH_OPENSSL
3453             fputs("Z = ", ecdhresp);
3454             to_hex_str(buf, ZZ.data, ZZ.len);
3455             fputs(buf, ecdhresp);
3456             fputc('\n', ecdhresp);
3457 #endif
3458 
3459             if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
3460                 fprintf(stderr, "hash of derived key failed\n");
3461                 goto loser;
3462             }
3463             SECITEM_FreeItem(&ZZ, PR_FALSE);
3464 #ifndef MATCH_NIST
3465             fputs("IUTHashZZ = ", ecdhresp);
3466             to_hex_str(buf, hashBuf, fips_hashLen(hash));
3467             fputs(buf, ecdhresp);
3468             fputc('\n', ecdhresp);
3469 #endif
3470             if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) {
3471 #ifdef VERBOSE_REASON
3472                 fprintf(ecdhresp, "Result = F # hash doesn't match\n");
3473 #else
3474                 fprintf(ecdhresp, "Result = F\n");
3475 #endif
3476             } else {
3477                 fprintf(ecdhresp, "Result = P\n");
3478             }
3479 #ifndef MATCH_OPENSSL
3480             fputc('\n', ecdhresp);
3481 #endif
3482             continue;
3483         }
3484     }
3485 loser:
3486     for (i = 0; i < MAX_ECC_PARAMS; i++) {
3487         if (ecparams[i] != NULL) {
3488             PORT_FreeArena(ecparams[i]->arena, PR_FALSE);
3489             ecparams[i] = NULL;
3490         }
3491     }
3492     if (pubkey.data != NULL) {
3493         PORT_Free(pubkey.data);
3494     }
3495     fclose(ecdhreq);
3496 }
3497 
3498 /*
3499  * Perform the DH Functional Test.
3500  *
3501  * reqfn is the pathname of the REQUEST file.
3502  *
3503  * The output RESPONSE file is written to stdout.
3504  */
3505 #define MAX_ECC_PARAMS 256
3506 void
dh_functional(char * reqfn,PRBool response)3507 dh_functional(char *reqfn, PRBool response)
3508 {
3509     char buf[1024]; /* holds one line from the input REQUEST file.
3510                          * needs to be large enough to hold the longest
3511                          * line "YephCAVS = <512 hex digits>\n".
3512                          */
3513     FILE *dhreq;    /* input stream from the REQUEST file */
3514     FILE *dhresp;   /* output stream to the RESPONSE file */
3515     unsigned char hashBuf[HASH_LENGTH_MAX];
3516     DSAPrivateKey *dsapriv = NULL;
3517     PQGParams pqg = { 0 };
3518     unsigned char pubkeydata[DSA_MAX_P_BITS / 8];
3519     SECItem pubkey;
3520     SECItem ZZ;
3521     unsigned int i, j;
3522     unsigned int pgySize;
3523     HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
3524 
3525     dhreq = fopen(reqfn, "r");
3526     dhresp = stdout;
3527     while (fgets(buf, sizeof buf, dhreq) != NULL) {
3528         /* a comment or blank line */
3529         if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
3530             fputs(buf, dhresp);
3531             continue;
3532         }
3533         if (buf[0] == '[') {
3534             /* [Fx - SHAxxx] */
3535             if (buf[1] == 'F' && buf[3] == ' ') {
3536                 const char *src;
3537                 /* skip passed the colon */
3538                 src = &buf[1];
3539                 while (*src && *src != '-')
3540                     src++;
3541                 if (*src != '-') {
3542                     fprintf(stderr, "No hash specified\n%s", buf);
3543                     goto loser;
3544                 }
3545                 src++;
3546                 /* skip to the first non-space */
3547                 while (*src && *src == ' ')
3548                     src++;
3549                 hash = hash_string_to_hashType(src);
3550                 if (hash == HASH_AlgNULL) {
3551                     fprintf(dhresp, "ERROR: Unable to find SHAAlg type");
3552                     goto loser;
3553                 }
3554                 /* clear the PQG parameters */
3555                 if (pqg.prime.data) { /* P */
3556                     SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
3557                 }
3558                 if (pqg.subPrime.data) { /* Q */
3559                     SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
3560                 }
3561                 if (pqg.base.data) { /* G */
3562                     SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
3563                 }
3564                 pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */
3565                 SECITEM_AllocItem(NULL, &pqg.prime, pgySize);
3566                 SECITEM_AllocItem(NULL, &pqg.base, pgySize);
3567                 pqg.prime.len = pqg.base.len = pgySize;
3568 
3569                 /* set q to the max allows */
3570                 SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS / 8);
3571                 pqg.subPrime.len = DSA_MAX_Q_BITS / 8;
3572                 fputs(buf, dhresp);
3573                 continue;
3574             }
3575             fputs(buf, dhresp);
3576             continue;
3577         }
3578         if (buf[0] == 'P') {
3579             i = 1;
3580             while (isspace(buf[i]) || buf[i] == '=') {
3581                 i++;
3582             }
3583             for (j = 0; j < pqg.prime.len; i += 2, j++) {
3584                 if (!isxdigit(buf[i])) {
3585                     pqg.prime.len = j;
3586                     break;
3587                 }
3588                 hex_to_byteval(&buf[i], &pqg.prime.data[j]);
3589             }
3590 
3591             fputs(buf, dhresp);
3592             continue;
3593         }
3594 
3595         /* Q = ... */
3596         if (buf[0] == 'Q') {
3597             i = 1;
3598             while (isspace(buf[i]) || buf[i] == '=') {
3599                 i++;
3600             }
3601             for (j = 0; j < pqg.subPrime.len; i += 2, j++) {
3602                 if (!isxdigit(buf[i])) {
3603                     pqg.subPrime.len = j;
3604                     break;
3605                 }
3606                 hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
3607             }
3608 
3609             fputs(buf, dhresp);
3610             continue;
3611         }
3612 
3613         /* G = ... */
3614         if (buf[0] == 'G') {
3615             i = 1;
3616             while (isspace(buf[i]) || buf[i] == '=') {
3617                 i++;
3618             }
3619             for (j = 0; j < pqg.base.len; i += 2, j++) {
3620                 if (!isxdigit(buf[i])) {
3621                     pqg.base.len = j;
3622                     break;
3623                 }
3624                 hex_to_byteval(&buf[i], &pqg.base.data[j]);
3625             }
3626 
3627             fputs(buf, dhresp);
3628             continue;
3629         }
3630 
3631         /* COUNT = ... */
3632         if (strncmp(buf, "COUNT", 5) == 0) {
3633             fputs(buf, dhresp);
3634             continue;
3635         }
3636 
3637         /* YephemCAVS = ... */
3638         if (strncmp(buf, "YephemCAVS", 10) == 0) {
3639             fputs(buf, dhresp);
3640             i = 10;
3641             while (isspace(buf[i]) || buf[i] == '=') {
3642                 i++;
3643             }
3644             from_hex_str(pubkeydata, pqg.prime.len, &buf[i]);
3645             pubkey.data = pubkeydata;
3646             pubkey.len = pqg.prime.len;
3647 
3648             /* generate FCC key pair, nist uses pqg rather then pg,
3649              * so use DSA to generate the key */
3650             if (DSA_NewKey(&pqg, &dsapriv) != SECSuccess) {
3651                 fprintf(stderr, "Failed to generate new key\n");
3652                 goto loser;
3653             }
3654             fputs("XephemIUT = ", dhresp);
3655             to_hex_str(buf, dsapriv->privateValue.data, dsapriv->privateValue.len);
3656             fputs(buf, dhresp);
3657             fputc('\n', dhresp);
3658             fputs("YephemIUT = ", dhresp);
3659             to_hex_str(buf, dsapriv->publicValue.data, dsapriv->publicValue.len);
3660             fputs(buf, dhresp);
3661             fputc('\n', dhresp);
3662             /* DH */
3663             if (DH_Derive(&pubkey, &pqg.prime, &dsapriv->privateValue,
3664                           &ZZ, pqg.prime.len) != SECSuccess) {
3665                 fprintf(stderr, "Derive failed\n");
3666                 goto loser;
3667             }
3668             /* output hash of ZZ */
3669             if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
3670                 fprintf(stderr, "hash of derived key failed\n");
3671                 goto loser;
3672             }
3673             SECITEM_FreeItem(&ZZ, PR_FALSE);
3674             fputs("HashZZ = ", dhresp);
3675             to_hex_str(buf, hashBuf, fips_hashLen(hash));
3676             fputs(buf, dhresp);
3677             fputc('\n', dhresp);
3678             fputc('\n', dhresp);
3679             PORT_FreeArena(dsapriv->params.arena, PR_TRUE);
3680             dsapriv = NULL;
3681             continue;
3682         }
3683     }
3684 loser:
3685     if (dsapriv != NULL) {
3686         PORT_FreeArena(dsapriv->params.arena, PR_TRUE);
3687     }
3688     fclose(dhreq);
3689 }
3690 
3691 /*
3692  * Perform the DH Validity Test.
3693  *
3694  * reqfn is the pathname of the REQUEST file.
3695  *
3696  * The output RESPONSE file is written to stdout.
3697  */
3698 void
dh_verify(char * reqfn,PRBool response)3699 dh_verify(char *reqfn, PRBool response)
3700 {
3701     char buf[1024]; /* holds one line from the input REQUEST file.
3702                          * needs to be large enough to hold the longest
3703                          * line "YephCAVS = <512 hex digits>\n".
3704                          */
3705     FILE *dhreq;    /* input stream from the REQUEST file */
3706     FILE *dhresp;   /* output stream to the RESPONSE file */
3707     unsigned char hashBuf[HASH_LENGTH_MAX];
3708     unsigned char cavsHashBuf[HASH_LENGTH_MAX];
3709     PQGParams pqg = { 0 };
3710     unsigned char pubkeydata[DSA_MAX_P_BITS / 8];
3711     unsigned char privkeydata[DSA_MAX_P_BITS / 8];
3712     SECItem pubkey;
3713     SECItem privkey;
3714     SECItem ZZ;
3715     unsigned int i, j;
3716     unsigned int pgySize;
3717     HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
3718 
3719     dhreq = fopen(reqfn, "r");
3720     dhresp = stdout;
3721     while (fgets(buf, sizeof buf, dhreq) != NULL) {
3722         /* a comment or blank line */
3723         if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
3724             fputs(buf, dhresp);
3725             continue;
3726         }
3727         if (buf[0] == '[') {
3728             /* [Fx - SHAxxx] */
3729             if (buf[1] == 'F' && buf[3] == ' ') {
3730                 const char *src;
3731                 /* skip passed the colon */
3732                 src = &buf[1];
3733                 while (*src && *src != '-')
3734                     src++;
3735                 if (*src != '-') {
3736                     fprintf(stderr, "No hash specified\n%s", buf);
3737                     goto loser;
3738                 }
3739                 src++;
3740                 /* skip to the first non-space */
3741                 while (*src && *src == ' ')
3742                     src++;
3743                 hash = hash_string_to_hashType(src);
3744                 if (hash == HASH_AlgNULL) {
3745                     fprintf(dhresp, "ERROR: Unable to find SHAAlg type");
3746                     goto loser;
3747                 }
3748                 /* clear the PQG parameters */
3749                 if (pqg.prime.data) { /* P */
3750                     SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
3751                 }
3752                 if (pqg.subPrime.data) { /* Q */
3753                     SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
3754                 }
3755                 if (pqg.base.data) { /* G */
3756                     SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
3757                 }
3758                 pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */
3759                 SECITEM_AllocItem(NULL, &pqg.prime, pgySize);
3760                 SECITEM_AllocItem(NULL, &pqg.base, pgySize);
3761                 pqg.prime.len = pqg.base.len = pgySize;
3762 
3763                 /* set q to the max allows */
3764                 SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS / 8);
3765                 pqg.subPrime.len = DSA_MAX_Q_BITS / 8;
3766                 fputs(buf, dhresp);
3767                 continue;
3768             }
3769             fputs(buf, dhresp);
3770             continue;
3771         }
3772         if (buf[0] == 'P') {
3773             i = 1;
3774             while (isspace(buf[i]) || buf[i] == '=') {
3775                 i++;
3776             }
3777             for (j = 0; j < pqg.prime.len; i += 2, j++) {
3778                 if (!isxdigit(buf[i])) {
3779                     pqg.prime.len = j;
3780                     break;
3781                 }
3782                 hex_to_byteval(&buf[i], &pqg.prime.data[j]);
3783             }
3784 
3785             fputs(buf, dhresp);
3786             continue;
3787         }
3788 
3789         /* Q = ... */
3790         if (buf[0] == 'Q') {
3791             i = 1;
3792             while (isspace(buf[i]) || buf[i] == '=') {
3793                 i++;
3794             }
3795             for (j = 0; j < pqg.subPrime.len; i += 2, j++) {
3796                 if (!isxdigit(buf[i])) {
3797                     pqg.subPrime.len = j;
3798                     break;
3799                 }
3800                 hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
3801             }
3802 
3803             fputs(buf, dhresp);
3804             continue;
3805         }
3806 
3807         /* G = ... */
3808         if (buf[0] == 'G') {
3809             i = 1;
3810             while (isspace(buf[i]) || buf[i] == '=') {
3811                 i++;
3812             }
3813             for (j = 0; j < pqg.base.len; i += 2, j++) {
3814                 if (!isxdigit(buf[i])) {
3815                     pqg.base.len = j;
3816                     break;
3817                 }
3818                 hex_to_byteval(&buf[i], &pqg.base.data[j]);
3819             }
3820 
3821             fputs(buf, dhresp);
3822             continue;
3823         }
3824 
3825         /* COUNT = ... */
3826         if (strncmp(buf, "COUNT", 5) == 0) {
3827             fputs(buf, dhresp);
3828             continue;
3829         }
3830 
3831         /* YephemCAVS = ... */
3832         if (strncmp(buf, "YephemCAVS", 10) == 0) {
3833             fputs(buf, dhresp);
3834             i = 10;
3835             while (isspace(buf[i]) || buf[i] == '=') {
3836                 i++;
3837             }
3838             from_hex_str(pubkeydata, pqg.prime.len, &buf[i]);
3839             pubkey.data = pubkeydata;
3840             pubkey.len = pqg.prime.len;
3841             continue;
3842         }
3843         /* XephemUIT = ... */
3844         if (strncmp(buf, "XephemIUT", 9) == 0) {
3845             fputs(buf, dhresp);
3846             i = 9;
3847             while (isspace(buf[i]) || buf[i] == '=') {
3848                 i++;
3849             }
3850             from_hex_str(privkeydata, pqg.subPrime.len, &buf[i]);
3851             privkey.data = privkeydata;
3852             privkey.len = pqg.subPrime.len;
3853             continue;
3854         }
3855         /* YephemUIT = ... */
3856         if (strncmp(buf, "YephemIUT", 9) == 0) {
3857             fputs(buf, dhresp);
3858             continue;
3859         }
3860         /* CAVSHashZZ = ... */
3861         if ((strncmp(buf, "CAVSHashZZ", 10) == 0) ||
3862             (strncmp(buf, "HashZZ", 6) == 0)) {
3863             fputs(buf, dhresp);
3864             i = buf[0] == 'C' ? 10 : 6;
3865             while (isspace(buf[i]) || buf[i] == '=') {
3866                 i++;
3867             }
3868             from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]);
3869             /* do the DH operation*/
3870             if (DH_Derive(&pubkey, &pqg.prime, &privkey,
3871                           &ZZ, pqg.prime.len) != SECSuccess) {
3872                 fprintf(stderr, "Derive failed\n");
3873                 goto loser;
3874             }
3875 /* output  ZZ */
3876 #ifndef MATCH_OPENSSL
3877             fputs("Z = ", dhresp);
3878             to_hex_str(buf, ZZ.data, ZZ.len);
3879             fputs(buf, dhresp);
3880             fputc('\n', dhresp);
3881 #endif
3882             if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
3883                 fprintf(stderr, "hash of derived key failed\n");
3884                 goto loser;
3885             }
3886             SECITEM_FreeItem(&ZZ, PR_FALSE);
3887 #ifndef MATCH_NIST
3888             fputs("IUTHashZZ = ", dhresp);
3889             to_hex_str(buf, hashBuf, fips_hashLen(hash));
3890             fputs(buf, dhresp);
3891             fputc('\n', dhresp);
3892 #endif
3893             if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) {
3894                 fprintf(dhresp, "Result = F\n");
3895             } else {
3896                 fprintf(dhresp, "Result = P\n");
3897             }
3898 #ifndef MATCH_OPENSSL
3899             fputc('\n', dhresp);
3900 #endif
3901             continue;
3902         }
3903     }
3904 loser:
3905     fclose(dhreq);
3906 }
3907 
3908 PRBool
isblankline(char * b)3909 isblankline(char *b)
3910 {
3911     while (isspace(*b))
3912         b++;
3913     if ((*b == '\n') || (*b == 0)) {
3914         return PR_TRUE;
3915     }
3916     return PR_FALSE;
3917 }
3918 
3919 static int debug = 0;
3920 
3921 /*
3922  * Perform the Hash_DRBG (CAVS) for the RNG algorithm
3923  *
3924  * reqfn is the pathname of the REQUEST file.
3925  *
3926  * The output RESPONSE file is written to stdout.
3927  */
3928 void
drbg(char * reqfn)3929 drbg(char *reqfn)
3930 {
3931     char buf[2000]; /* test case has some very long lines, returned bits
3932      * as high as 800 bytes (6400 bits). That 1600 byte
3933      * plus a tag */
3934     char buf2[2000];
3935     FILE *rngreq;  /* input stream from the REQUEST file */
3936     FILE *rngresp; /* output stream to the RESPONSE file */
3937 
3938     unsigned int i, j;
3939 #ifdef HANDLE_PREDICTION_RESISTANCE
3940     PRBool predictionResistance = PR_FALSE;
3941 #endif
3942     unsigned char *nonce = NULL;
3943     int nonceLen = 0;
3944     unsigned char *personalizationString = NULL;
3945     int personalizationStringLen = 0;
3946     unsigned char *additionalInput = NULL;
3947     int additionalInputLen = 0;
3948     unsigned char *entropyInput = NULL;
3949     int entropyInputLen = 0;
3950     unsigned char *predictedreturn_bytes = NULL;
3951     unsigned char *return_bytes = NULL;
3952     int return_bytes_len = 0;
3953     enum { NONE,
3954            INSTANTIATE,
3955            GENERATE,
3956            RESEED,
3957            RESULT } command =
3958         NONE;
3959     PRBool genResult = PR_FALSE;
3960     SECStatus rv;
3961 
3962     rngreq = fopen(reqfn, "r");
3963     rngresp = stdout;
3964     while (fgets(buf, sizeof buf, rngreq) != NULL) {
3965         switch (command) {
3966             case INSTANTIATE:
3967                 if (debug) {
3968                     fputs("# PRNGTEST_Instantiate(", rngresp);
3969                     to_hex_str(buf2, entropyInput, entropyInputLen);
3970                     fputs(buf2, rngresp);
3971                     fprintf(rngresp, ",%d,", entropyInputLen);
3972                     to_hex_str(buf2, nonce, nonceLen);
3973                     fputs(buf2, rngresp);
3974                     fprintf(rngresp, ",%d,", nonceLen);
3975                     to_hex_str(buf2, personalizationString,
3976                                personalizationStringLen);
3977                     fputs(buf2, rngresp);
3978                     fprintf(rngresp, ",%d)\n", personalizationStringLen);
3979                 }
3980                 rv = PRNGTEST_Instantiate(entropyInput, entropyInputLen,
3981                                           nonce, nonceLen,
3982                                           personalizationString,
3983                                           personalizationStringLen);
3984                 if (rv != SECSuccess) {
3985                     goto loser;
3986                 }
3987                 break;
3988 
3989             case GENERATE:
3990             case RESULT:
3991                 memset(return_bytes, 0, return_bytes_len);
3992                 if (debug) {
3993                     fputs("# PRNGTEST_Generate(returnbytes", rngresp);
3994                     fprintf(rngresp, ",%d,", return_bytes_len);
3995                     to_hex_str(buf2, additionalInput, additionalInputLen);
3996                     fputs(buf2, rngresp);
3997                     fprintf(rngresp, ",%d)\n", additionalInputLen);
3998                 }
3999                 rv = PRNGTEST_Generate((PRUint8 *)return_bytes,
4000                                        return_bytes_len,
4001                                        (PRUint8 *)additionalInput,
4002                                        additionalInputLen);
4003                 if (rv != SECSuccess) {
4004                     goto loser;
4005                 }
4006 
4007                 if (command == RESULT) {
4008                     fputs("ReturnedBits = ", rngresp);
4009                     to_hex_str(buf2, return_bytes, return_bytes_len);
4010                     fputs(buf2, rngresp);
4011                     fputc('\n', rngresp);
4012                     if (debug) {
4013                         fputs("# PRNGTEST_Uninstantiate()\n", rngresp);
4014                     }
4015                     rv = PRNGTEST_Uninstantiate();
4016                     if (rv != SECSuccess) {
4017                         goto loser;
4018                     }
4019                 } else if (debug) {
4020                     fputs("#ReturnedBits = ", rngresp);
4021                     to_hex_str(buf2, return_bytes, return_bytes_len);
4022                     fputs(buf2, rngresp);
4023                     fputc('\n', rngresp);
4024                 }
4025 
4026                 memset(additionalInput, 0, additionalInputLen);
4027                 break;
4028 
4029             case RESEED:
4030                 if (entropyInput || additionalInput) {
4031                     if (debug) {
4032                         fputs("# PRNGTEST_Reseed(", rngresp);
4033                         fprintf(rngresp, ",%d,", return_bytes_len);
4034                         to_hex_str(buf2, entropyInput, entropyInputLen);
4035                         fputs(buf2, rngresp);
4036                         fprintf(rngresp, ",%d,", entropyInputLen);
4037                         to_hex_str(buf2, additionalInput, additionalInputLen);
4038                         fputs(buf2, rngresp);
4039                         fprintf(rngresp, ",%d)\n", additionalInputLen);
4040                     }
4041                     rv = PRNGTEST_Reseed(entropyInput, entropyInputLen,
4042                                          additionalInput, additionalInputLen);
4043                     if (rv != SECSuccess) {
4044                         goto loser;
4045                     }
4046                 }
4047                 memset(entropyInput, 0, entropyInputLen);
4048                 memset(additionalInput, 0, additionalInputLen);
4049                 break;
4050             case NONE:
4051                 break;
4052         }
4053         command = NONE;
4054 
4055         /* a comment or blank line */
4056         if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
4057             fputs(buf, rngresp);
4058             continue;
4059         }
4060 
4061         /* [Hash - SHA256] */
4062         if (strncmp(buf, "[SHA-256]", 9) == 0) {
4063             fputs(buf, rngresp);
4064             continue;
4065         }
4066 
4067         if (strncmp(buf, "[PredictionResistance", 21) == 0) {
4068 #ifdef HANDLE_PREDICTION_RESISTANCE
4069             i = 21;
4070             while (isspace(buf[i]) || buf[i] == '=') {
4071                 i++;
4072             }
4073             if (strncmp(buf, "False", 5) == 0) {
4074                 predictionResistance = PR_FALSE;
4075             } else {
4076                 predictionResistance = PR_TRUE;
4077             }
4078 #endif
4079 
4080             fputs(buf, rngresp);
4081             continue;
4082         }
4083 
4084         if (strncmp(buf, "[ReturnedBitsLen", 16) == 0) {
4085             if (return_bytes) {
4086                 PORT_ZFree(return_bytes, return_bytes_len);
4087                 return_bytes = NULL;
4088             }
4089             if (predictedreturn_bytes) {
4090                 PORT_ZFree(predictedreturn_bytes, return_bytes_len);
4091                 predictedreturn_bytes = NULL;
4092             }
4093             return_bytes_len = 0;
4094             if (sscanf(buf, "[ReturnedBitsLen = %d]", &return_bytes_len) != 1) {
4095                 goto loser;
4096             }
4097             return_bytes_len = return_bytes_len / 8;
4098             if (return_bytes_len > 0) {
4099                 return_bytes = PORT_Alloc(return_bytes_len);
4100                 predictedreturn_bytes = PORT_Alloc(return_bytes_len);
4101             }
4102             fputs(buf, rngresp);
4103             continue;
4104         }
4105 
4106         if (strncmp(buf, "[EntropyInputLen", 16) == 0) {
4107             if (entropyInput) {
4108                 PORT_ZFree(entropyInput, entropyInputLen);
4109                 entropyInput = NULL;
4110                 entropyInputLen = 0;
4111             }
4112             if (sscanf(buf, "[EntropyInputLen = %d]", &entropyInputLen) != 1) {
4113                 goto loser;
4114             }
4115             entropyInputLen = entropyInputLen / 8;
4116             if (entropyInputLen > 0) {
4117                 entropyInput = PORT_Alloc(entropyInputLen);
4118             }
4119             fputs(buf, rngresp);
4120             continue;
4121         }
4122 
4123         if (strncmp(buf, "[NonceLen", 9) == 0) {
4124             if (nonce) {
4125                 PORT_ZFree(nonce, nonceLen);
4126                 nonce = NULL;
4127                 nonceLen = 0;
4128             }
4129 
4130             if (sscanf(buf, "[NonceLen = %d]", &nonceLen) != 1) {
4131                 goto loser;
4132             }
4133             nonceLen = nonceLen / 8;
4134             if (nonceLen > 0) {
4135                 nonce = PORT_Alloc(nonceLen);
4136             }
4137             fputs(buf, rngresp);
4138             continue;
4139         }
4140 
4141         if (strncmp(buf, "[PersonalizationStringLen", 16) == 0) {
4142             if (personalizationString) {
4143                 PORT_ZFree(personalizationString, personalizationStringLen);
4144                 personalizationString = NULL;
4145                 personalizationStringLen = 0;
4146             }
4147 
4148             if (sscanf(buf, "[PersonalizationStringLen = %d]", &personalizationStringLen) != 1) {
4149                 goto loser;
4150             }
4151             personalizationStringLen = personalizationStringLen / 8;
4152             if (personalizationStringLen > 0) {
4153                 personalizationString = PORT_Alloc(personalizationStringLen);
4154             }
4155             fputs(buf, rngresp);
4156 
4157             continue;
4158         }
4159 
4160         if (strncmp(buf, "[AdditionalInputLen", 16) == 0) {
4161             if (additionalInput) {
4162                 PORT_ZFree(additionalInput, additionalInputLen);
4163                 additionalInput = NULL;
4164                 additionalInputLen = 0;
4165             }
4166 
4167             if (sscanf(buf, "[AdditionalInputLen = %d]", &additionalInputLen) != 1) {
4168                 goto loser;
4169             }
4170             additionalInputLen = additionalInputLen / 8;
4171             if (additionalInputLen > 0) {
4172                 additionalInput = PORT_Alloc(additionalInputLen);
4173             }
4174             fputs(buf, rngresp);
4175             continue;
4176         }
4177 
4178         if (strncmp(buf, "COUNT", 5) == 0) {
4179             /* zeroize the variables for the test with this data set */
4180             if (entropyInput) {
4181                 memset(entropyInput, 0, entropyInputLen);
4182             }
4183             if (nonce) {
4184                 memset(nonce, 0, nonceLen);
4185             }
4186             if (personalizationString) {
4187                 memset(personalizationString, 0, personalizationStringLen);
4188             }
4189             if (additionalInput) {
4190                 memset(additionalInput, 0, additionalInputLen);
4191             }
4192             genResult = PR_FALSE;
4193 
4194             fputs(buf, rngresp);
4195             continue;
4196         }
4197 
4198         /* EntropyInputReseed = ... */
4199         if (strncmp(buf, "EntropyInputReseed", 18) == 0) {
4200             if (entropyInput) {
4201                 memset(entropyInput, 0, entropyInputLen);
4202                 i = 18;
4203                 while (isspace(buf[i]) || buf[i] == '=') {
4204                     i++;
4205                 }
4206 
4207                 for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<entropyInputLen*/
4208                     hex_to_byteval(&buf[i], &entropyInput[j]);
4209                 }
4210             }
4211             fputs(buf, rngresp);
4212             continue;
4213         }
4214 
4215         /* AttionalInputReseed  = ... */
4216         if (strncmp(buf, "AdditionalInputReseed", 21) == 0) {
4217             if (additionalInput) {
4218                 memset(additionalInput, 0, additionalInputLen);
4219                 i = 21;
4220                 while (isspace(buf[i]) || buf[i] == '=') {
4221                     i++;
4222                 }
4223                 for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<additionalInputLen*/
4224                     hex_to_byteval(&buf[i], &additionalInput[j]);
4225                 }
4226             }
4227             command = RESEED;
4228             fputs(buf, rngresp);
4229             continue;
4230         }
4231 
4232         /* Entropy input = ... */
4233         if (strncmp(buf, "EntropyInput", 12) == 0) {
4234             i = 12;
4235             while (isspace(buf[i]) || buf[i] == '=') {
4236                 i++;
4237             }
4238             for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<entropyInputLen*/
4239                 hex_to_byteval(&buf[i], &entropyInput[j]);
4240             }
4241             fputs(buf, rngresp);
4242             continue;
4243         }
4244 
4245         /* nouce = ... */
4246         if (strncmp(buf, "Nonce", 5) == 0) {
4247             i = 5;
4248             while (isspace(buf[i]) || buf[i] == '=') {
4249                 i++;
4250             }
4251             for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<nonceLen*/
4252                 hex_to_byteval(&buf[i], &nonce[j]);
4253             }
4254             fputs(buf, rngresp);
4255             continue;
4256         }
4257 
4258         /* Personalization string = ... */
4259         if (strncmp(buf, "PersonalizationString", 21) == 0) {
4260             if (personalizationString) {
4261                 i = 21;
4262                 while (isspace(buf[i]) || buf[i] == '=') {
4263                     i++;
4264                 }
4265                 for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<personalizationStringLen*/
4266                     hex_to_byteval(&buf[i], &personalizationString[j]);
4267                 }
4268             }
4269             fputs(buf, rngresp);
4270             command = INSTANTIATE;
4271             continue;
4272         }
4273 
4274         /* Additional input = ... */
4275         if (strncmp(buf, "AdditionalInput", 15) == 0) {
4276             if (additionalInput) {
4277                 i = 15;
4278                 while (isspace(buf[i]) || buf[i] == '=') {
4279                     i++;
4280                 }
4281                 for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<additionalInputLen*/
4282                     hex_to_byteval(&buf[i], &additionalInput[j]);
4283                 }
4284             }
4285             if (genResult) {
4286                 command = RESULT;
4287             } else {
4288                 command = GENERATE;
4289                 genResult = PR_TRUE; /* next time generate result */
4290             }
4291             fputs(buf, rngresp);
4292             continue;
4293         }
4294 
4295         /* Returned bits = ... */
4296         if (strncmp(buf, "ReturnedBits", 12) == 0) {
4297             i = 12;
4298             while (isspace(buf[i]) || buf[i] == '=') {
4299                 i++;
4300             }
4301             for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<additionalInputLen*/
4302                 hex_to_byteval(&buf[i], &predictedreturn_bytes[j]);
4303             }
4304 
4305             if (memcmp(return_bytes,
4306                        predictedreturn_bytes, return_bytes_len) != 0) {
4307                 if (debug) {
4308                     fprintf(rngresp, "# Generate failed:\n");
4309                     fputs("#   predicted=", rngresp);
4310                     to_hex_str(buf, predictedreturn_bytes,
4311                                return_bytes_len);
4312                     fputs(buf, rngresp);
4313                     fputs("\n#   actual  = ", rngresp);
4314                     fputs(buf2, rngresp);
4315                     fputc('\n', rngresp);
4316 
4317                 } else {
4318                     fprintf(stderr, "Generate failed:\n");
4319                     fputs("   predicted=", stderr);
4320                     to_hex_str(buf, predictedreturn_bytes,
4321                                return_bytes_len);
4322                     fputs(buf, stderr);
4323                     fputs("\n   actual  = ", stderr);
4324                     fputs(buf2, stderr);
4325                     fputc('\n', stderr);
4326                 }
4327             }
4328             memset(predictedreturn_bytes, 0, return_bytes_len);
4329 
4330             continue;
4331         }
4332     }
4333 loser:
4334     if (predictedreturn_bytes) {
4335         PORT_Free(predictedreturn_bytes);
4336     }
4337     if (return_bytes) {
4338         PORT_Free(return_bytes);
4339     }
4340     if (additionalInput) {
4341         PORT_Free(additionalInput);
4342     }
4343     if (personalizationString) {
4344         PORT_Free(personalizationString);
4345     }
4346     if (nonce) {
4347         PORT_Free(nonce);
4348     }
4349     if (entropyInput) {
4350         PORT_Free(entropyInput);
4351     }
4352     fclose(rngreq);
4353 }
4354 
4355 /*
4356  * Perform the RNG Variable Seed Test (VST) for the RNG algorithm
4357  * "DSA - Generation of X", used both as specified and as a generic
4358  * purpose RNG.  The presence of "Q = ..." in the REQUEST file
4359  * indicates we are using the algorithm as specified.
4360  *
4361  * reqfn is the pathname of the REQUEST file.
4362  *
4363  * The output RESPONSE file is written to stdout.
4364  */
4365 void
rng_vst(char * reqfn)4366 rng_vst(char *reqfn)
4367 {
4368     char buf[256]; /* holds one line from the input REQUEST file.
4369                          * needs to be large enough to hold the longest
4370                          * line "XSeed = <128 hex digits>\n".
4371                          */
4372     FILE *rngreq;  /* input stream from the REQUEST file */
4373     FILE *rngresp; /* output stream to the RESPONSE file */
4374     unsigned int i, j;
4375     unsigned char Q[DSA1_SUBPRIME_LEN];
4376     PRBool hasQ = PR_FALSE;
4377     unsigned int b = 0; /* 160 <= b <= 512, b is a multiple of 8 */
4378     unsigned char XKey[512 / 8];
4379     unsigned char XSeed[512 / 8];
4380     unsigned char GENX[DSA1_SIGNATURE_LEN];
4381     unsigned char DSAX[DSA1_SUBPRIME_LEN];
4382     SECStatus rv;
4383 
4384     rngreq = fopen(reqfn, "r");
4385     rngresp = stdout;
4386     while (fgets(buf, sizeof buf, rngreq) != NULL) {
4387         /* a comment or blank line */
4388         if (buf[0] == '#' || buf[0] == '\n') {
4389             fputs(buf, rngresp);
4390             continue;
4391         }
4392         /* [Xchange - SHA1] */
4393         if (buf[0] == '[') {
4394             fputs(buf, rngresp);
4395             continue;
4396         }
4397         /* Q = ... */
4398         if (buf[0] == 'Q') {
4399             i = 1;
4400             while (isspace(buf[i]) || buf[i] == '=') {
4401                 i++;
4402             }
4403             for (j = 0; j < sizeof Q; i += 2, j++) {
4404                 hex_to_byteval(&buf[i], &Q[j]);
4405             }
4406             fputs(buf, rngresp);
4407             hasQ = PR_TRUE;
4408             continue;
4409         }
4410         /* "COUNT = x" begins a new data set */
4411         if (strncmp(buf, "COUNT", 5) == 0) {
4412             /* zeroize the variables for the test with this data set */
4413             b = 0;
4414             memset(XKey, 0, sizeof XKey);
4415             memset(XSeed, 0, sizeof XSeed);
4416             fputs(buf, rngresp);
4417             continue;
4418         }
4419         /* b = ... */
4420         if (buf[0] == 'b') {
4421             i = 1;
4422             while (isspace(buf[i]) || buf[i] == '=') {
4423                 i++;
4424             }
4425             b = atoi(&buf[i]);
4426             if (b < 160 || b > 512 || b % 8 != 0) {
4427                 goto loser;
4428             }
4429             fputs(buf, rngresp);
4430             continue;
4431         }
4432         /* XKey = ... */
4433         if (strncmp(buf, "XKey", 4) == 0) {
4434             i = 4;
4435             while (isspace(buf[i]) || buf[i] == '=') {
4436                 i++;
4437             }
4438             for (j = 0; j < b / 8; i += 2, j++) {
4439                 hex_to_byteval(&buf[i], &XKey[j]);
4440             }
4441             fputs(buf, rngresp);
4442             continue;
4443         }
4444         /* XSeed = ... */
4445         if (strncmp(buf, "XSeed", 5) == 0) {
4446             i = 5;
4447             while (isspace(buf[i]) || buf[i] == '=') {
4448                 i++;
4449             }
4450             for (j = 0; j < b / 8; i += 2, j++) {
4451                 hex_to_byteval(&buf[i], &XSeed[j]);
4452             }
4453             fputs(buf, rngresp);
4454 
4455             rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
4456             if (rv != SECSuccess) {
4457                 goto loser;
4458             }
4459             fputs("X = ", rngresp);
4460             if (hasQ) {
4461                 rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
4462                 if (rv != SECSuccess) {
4463                     goto loser;
4464                 }
4465                 to_hex_str(buf, DSAX, sizeof DSAX);
4466             } else {
4467                 to_hex_str(buf, GENX, sizeof GENX);
4468             }
4469             fputs(buf, rngresp);
4470             fputc('\n', rngresp);
4471             continue;
4472         }
4473     }
4474 loser:
4475     fclose(rngreq);
4476 }
4477 
4478 /*
4479  * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm
4480  * "DSA - Generation of X", used both as specified and as a generic
4481  * purpose RNG.  The presence of "Q = ..." in the REQUEST file
4482  * indicates we are using the algorithm as specified.
4483  *
4484  * reqfn is the pathname of the REQUEST file.
4485  *
4486  * The output RESPONSE file is written to stdout.
4487  */
4488 void
rng_mct(char * reqfn)4489 rng_mct(char *reqfn)
4490 {
4491     char buf[256]; /* holds one line from the input REQUEST file.
4492                          * needs to be large enough to hold the longest
4493                          * line "XSeed = <128 hex digits>\n".
4494                          */
4495     FILE *rngreq;  /* input stream from the REQUEST file */
4496     FILE *rngresp; /* output stream to the RESPONSE file */
4497     unsigned int i, j;
4498     unsigned char Q[DSA1_SUBPRIME_LEN];
4499     PRBool hasQ = PR_FALSE;
4500     unsigned int b = 0; /* 160 <= b <= 512, b is a multiple of 8 */
4501     unsigned char XKey[512 / 8];
4502     unsigned char XSeed[512 / 8];
4503     unsigned char GENX[2 * SHA1_LENGTH];
4504     unsigned char DSAX[DSA1_SUBPRIME_LEN];
4505     SECStatus rv;
4506 
4507     rngreq = fopen(reqfn, "r");
4508     rngresp = stdout;
4509     while (fgets(buf, sizeof buf, rngreq) != NULL) {
4510         /* a comment or blank line */
4511         if (buf[0] == '#' || buf[0] == '\n') {
4512             fputs(buf, rngresp);
4513             continue;
4514         }
4515         /* [Xchange - SHA1] */
4516         if (buf[0] == '[') {
4517             fputs(buf, rngresp);
4518             continue;
4519         }
4520         /* Q = ... */
4521         if (buf[0] == 'Q') {
4522             i = 1;
4523             while (isspace(buf[i]) || buf[i] == '=') {
4524                 i++;
4525             }
4526             for (j = 0; j < sizeof Q; i += 2, j++) {
4527                 hex_to_byteval(&buf[i], &Q[j]);
4528             }
4529             fputs(buf, rngresp);
4530             hasQ = PR_TRUE;
4531             continue;
4532         }
4533         /* "COUNT = x" begins a new data set */
4534         if (strncmp(buf, "COUNT", 5) == 0) {
4535             /* zeroize the variables for the test with this data set */
4536             b = 0;
4537             memset(XKey, 0, sizeof XKey);
4538             memset(XSeed, 0, sizeof XSeed);
4539             fputs(buf, rngresp);
4540             continue;
4541         }
4542         /* b = ... */
4543         if (buf[0] == 'b') {
4544             i = 1;
4545             while (isspace(buf[i]) || buf[i] == '=') {
4546                 i++;
4547             }
4548             b = atoi(&buf[i]);
4549             if (b < 160 || b > 512 || b % 8 != 0) {
4550                 goto loser;
4551             }
4552             fputs(buf, rngresp);
4553             continue;
4554         }
4555         /* XKey = ... */
4556         if (strncmp(buf, "XKey", 4) == 0) {
4557             i = 4;
4558             while (isspace(buf[i]) || buf[i] == '=') {
4559                 i++;
4560             }
4561             for (j = 0; j < b / 8; i += 2, j++) {
4562                 hex_to_byteval(&buf[i], &XKey[j]);
4563             }
4564             fputs(buf, rngresp);
4565             continue;
4566         }
4567         /* XSeed = ... */
4568         if (strncmp(buf, "XSeed", 5) == 0) {
4569             unsigned int k;
4570             i = 5;
4571             while (isspace(buf[i]) || buf[i] == '=') {
4572                 i++;
4573             }
4574             for (j = 0; j < b / 8; i += 2, j++) {
4575                 hex_to_byteval(&buf[i], &XSeed[j]);
4576             }
4577             fputs(buf, rngresp);
4578 
4579             for (k = 0; k < 10000; k++) {
4580                 rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
4581                 if (rv != SECSuccess) {
4582                     goto loser;
4583                 }
4584             }
4585             fputs("X = ", rngresp);
4586             if (hasQ) {
4587                 rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
4588                 if (rv != SECSuccess) {
4589                     goto loser;
4590                 }
4591                 to_hex_str(buf, DSAX, sizeof DSAX);
4592             } else {
4593                 to_hex_str(buf, GENX, sizeof GENX);
4594             }
4595             fputs(buf, rngresp);
4596             fputc('\n', rngresp);
4597             continue;
4598         }
4599     }
4600 loser:
4601     fclose(rngreq);
4602 }
4603 
4604 /*
4605  * Calculate the SHA Message Digest
4606  *
4607  * MD = Message digest
4608  * MDLen = length of Message Digest and SHA_Type
4609  * msg = message to digest
4610  * msgLen = length of message to digest
4611  */
4612 SECStatus
sha_calcMD(unsigned char * MD,unsigned int MDLen,unsigned char * msg,unsigned int msgLen)4613 sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen)
4614 {
4615     HASH_HashType hashType = sha_get_hashType(MDLen * PR_BITS_PER_BYTE);
4616 
4617     return fips_hashBuf(hashType, MD, msg, msgLen);
4618 }
4619 
4620 /*
4621  * Perform the SHA Monte Carlo Test
4622  *
4623  * MDLen = length of Message Digest and SHA_Type
4624  * seed = input seed value
4625  * resp = is the output response file.
4626  */
4627 SECStatus
sha_mct_test(unsigned int MDLen,unsigned char * seed,FILE * resp)4628 sha_mct_test(unsigned int MDLen, unsigned char *seed, FILE *resp)
4629 {
4630     int i, j;
4631     unsigned int msgLen = MDLen * 3;
4632     unsigned char MD_i3[HASH_LENGTH_MAX]; /* MD[i-3] */
4633     unsigned char MD_i2[HASH_LENGTH_MAX]; /* MD[i-2] */
4634     unsigned char MD_i1[HASH_LENGTH_MAX]; /* MD[i-1] */
4635     unsigned char MD_i[HASH_LENGTH_MAX];  /* MD[i] */
4636     unsigned char msg[HASH_LENGTH_MAX * 3];
4637     char buf[HASH_LENGTH_MAX * 2 + 1]; /* MAX buf MD_i as a hex string */
4638 
4639     for (j = 0; j < 100; j++) {
4640         /* MD_0 = MD_1 = MD_2 = seed */
4641         memcpy(MD_i3, seed, MDLen);
4642         memcpy(MD_i2, seed, MDLen);
4643         memcpy(MD_i1, seed, MDLen);
4644 
4645         for (i = 3; i < 1003; i++) {
4646             /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */
4647             memcpy(msg, MD_i3, MDLen);
4648             memcpy(&msg[MDLen], MD_i2, MDLen);
4649             memcpy(&msg[MDLen * 2], MD_i1, MDLen);
4650 
4651             /* MDi = SHA(Msg) */
4652             if (sha_calcMD(MD_i, MDLen,
4653                            msg, msgLen) != SECSuccess) {
4654                 return SECFailure;
4655             }
4656 
4657             /* save MD[i-3] MD[i-2]  MD[i-1] */
4658             memcpy(MD_i3, MD_i2, MDLen);
4659             memcpy(MD_i2, MD_i1, MDLen);
4660             memcpy(MD_i1, MD_i, MDLen);
4661         }
4662 
4663         /* seed = MD_i */
4664         memcpy(seed, MD_i, MDLen);
4665 
4666         sprintf(buf, "COUNT = %d\n", j);
4667         fputs(buf, resp);
4668 
4669         /* output MD_i */
4670         fputs("MD = ", resp);
4671         to_hex_str(buf, MD_i, MDLen);
4672         fputs(buf, resp);
4673         fputc('\n', resp);
4674     }
4675 
4676     return SECSuccess;
4677 }
4678 
4679 /*
4680  * Perform the SHA Tests.
4681  *
4682  * reqfn is the pathname of the input REQUEST file.
4683  *
4684  * The output RESPONSE file is written to stdout.
4685  */
4686 void
sha_test(char * reqfn)4687 sha_test(char *reqfn)
4688 {
4689     unsigned int i, j;
4690     unsigned int MDlen = 0;              /* the length of the Message Digest in Bytes  */
4691     unsigned int msgLen = 0;             /* the length of the input Message in Bytes */
4692     unsigned char *msg = NULL;           /* holds the message to digest.*/
4693     size_t bufSize = 256 * 128;          /*MAX buffer size */
4694     char *buf = NULL;                    /* holds one line from the input REQUEST file.*/
4695     unsigned char seed[HASH_LENGTH_MAX]; /* max size of seed 64 bytes */
4696     unsigned char MD[HASH_LENGTH_MAX];   /* message digest */
4697 
4698     FILE *req = NULL; /* input stream from the REQUEST file */
4699     FILE *resp;       /* output stream to the RESPONSE file */
4700 
4701     buf = PORT_ZAlloc(bufSize);
4702     if (buf == NULL) {
4703         goto loser;
4704     }
4705 
4706     /* zeroize the variables for the test with this data set */
4707     memset(seed, 0, sizeof seed);
4708 
4709     req = fopen(reqfn, "r");
4710     resp = stdout;
4711     while (fgets(buf, bufSize, req) != NULL) {
4712 
4713         /* a comment or blank line */
4714         if (buf[0] == '#' || buf[0] == '\n') {
4715             fputs(buf, resp);
4716             continue;
4717         }
4718         /* [L = Length of the Message Digest and sha_type */
4719         if (buf[0] == '[') {
4720             if (strncmp(&buf[1], "L ", 1) == 0) {
4721                 i = 2;
4722                 while (isspace(buf[i]) || buf[i] == '=') {
4723                     i++;
4724                 }
4725                 MDlen = atoi(&buf[i]);
4726                 fputs(buf, resp);
4727                 continue;
4728             }
4729         }
4730         /* Len = Length of the Input Message Length  ... */
4731         if (strncmp(buf, "Len", 3) == 0) {
4732             i = 3;
4733             while (isspace(buf[i]) || buf[i] == '=') {
4734                 i++;
4735             }
4736             if (msg) {
4737                 PORT_ZFree(msg, msgLen);
4738                 msg = NULL;
4739             }
4740             msgLen = atoi(&buf[i]); /* in bits */
4741             if (msgLen % 8 != 0) {
4742                 fprintf(stderr, "SHA tests are incorrectly configured for "
4743                                 "BIT oriented implementations\n");
4744                 goto loser;
4745             }
4746             msgLen = msgLen / 8; /* convert to bytes */
4747             fputs(buf, resp);
4748             msg = PORT_ZAlloc(msgLen);
4749             if (msg == NULL && msgLen != 0) {
4750                 goto loser;
4751             }
4752             continue;
4753         }
4754         /* MSG = ... */
4755         if (strncmp(buf, "Msg", 3) == 0) {
4756             i = 3;
4757             while (isspace(buf[i]) || buf[i] == '=') {
4758                 i++;
4759             }
4760             for (j = 0; j < msgLen; i += 2, j++) {
4761                 hex_to_byteval(&buf[i], &msg[j]);
4762             }
4763             fputs(buf, resp);
4764             /* calculate the Message Digest */
4765             memset(MD, 0, sizeof MD);
4766             if (sha_calcMD(MD, MDlen,
4767                            msg, msgLen) != SECSuccess) {
4768                 goto loser;
4769             }
4770 
4771             fputs("MD = ", resp);
4772             to_hex_str(buf, MD, MDlen);
4773             fputs(buf, resp);
4774             fputc('\n', resp);
4775 
4776             continue;
4777         }
4778         /* Seed = ... */
4779         if (strncmp(buf, "Seed", 4) == 0) {
4780             i = 4;
4781             while (isspace(buf[i]) || buf[i] == '=') {
4782                 i++;
4783             }
4784             for (j = 0; j < sizeof seed; i += 2, j++) {
4785                 hex_to_byteval(&buf[i], &seed[j]);
4786             }
4787 
4788             fputs(buf, resp);
4789             fputc('\n', resp);
4790 
4791             /* do the Monte Carlo test */
4792             if (sha_mct_test(MDlen, seed, resp) != SECSuccess) {
4793                 goto loser;
4794             }
4795 
4796             continue;
4797         }
4798     }
4799 loser:
4800     if (req) {
4801         fclose(req);
4802     }
4803     if (buf) {
4804         PORT_ZFree(buf, bufSize);
4805     }
4806     if (msg) {
4807         PORT_ZFree(msg, msgLen);
4808     }
4809 }
4810 
4811 /****************************************************/
4812 /* HMAC SHA-X calc                                  */
4813 /* hmac_computed - the computed HMAC                */
4814 /* hmac_length - the length of the computed HMAC    */
4815 /* secret_key - secret key to HMAC                  */
4816 /* secret_key_length - length of secret key,        */
4817 /* message - message to HMAC                        */
4818 /* message_length - length ofthe message            */
4819 /****************************************************/
4820 static SECStatus
hmac_calc(unsigned char * hmac_computed,const unsigned int hmac_length,const unsigned char * secret_key,const unsigned int secret_key_length,const unsigned char * message,const unsigned int message_length,const HASH_HashType hashAlg)4821 hmac_calc(unsigned char *hmac_computed,
4822           const unsigned int hmac_length,
4823           const unsigned char *secret_key,
4824           const unsigned int secret_key_length,
4825           const unsigned char *message,
4826           const unsigned int message_length,
4827           const HASH_HashType hashAlg)
4828 {
4829     SECStatus hmac_status = SECFailure;
4830     HMACContext *cx = NULL;
4831     SECHashObject *hashObj = NULL;
4832     unsigned int bytes_hashed = 0;
4833 
4834     hashObj = (SECHashObject *)HASH_GetRawHashObject(hashAlg);
4835 
4836     if (!hashObj)
4837         return (SECFailure);
4838 
4839     cx = HMAC_Create(hashObj, secret_key,
4840                      secret_key_length,
4841                      PR_TRUE); /* PR_TRUE for in FIPS mode */
4842 
4843     if (cx == NULL)
4844         return (SECFailure);
4845 
4846     HMAC_Begin(cx);
4847     HMAC_Update(cx, message, message_length);
4848     hmac_status = HMAC_Finish(cx, hmac_computed, &bytes_hashed,
4849                               hmac_length);
4850 
4851     HMAC_Destroy(cx, PR_TRUE);
4852 
4853     return (hmac_status);
4854 }
4855 
4856 /*
4857  * Perform the HMAC Tests.
4858  *
4859  * reqfn is the pathname of the input REQUEST file.
4860  *
4861  * The output RESPONSE file is written to stdout.
4862  */
4863 void
hmac_test(char * reqfn)4864 hmac_test(char *reqfn)
4865 {
4866     unsigned int i, j;
4867     size_t bufSize = 400;                        /* MAX buffer size */
4868     char *buf = NULL;                            /* holds one line from the input REQUEST file.*/
4869     unsigned int keyLen = 0;                     /* Key Length */
4870     unsigned char key[200];                      /* key MAX size = 184 */
4871     unsigned int msgLen = 128;                   /* the length of the input  */
4872                                                  /*  Message is always 128 Bytes */
4873     unsigned char *msg = NULL;                   /* holds the message to digest.*/
4874     unsigned int HMACLen = 0;                    /* the length of the HMAC Bytes  */
4875     unsigned int TLen = 0;                       /* the length of the requested */
4876                                                  /* truncated HMAC Bytes */
4877     unsigned char HMAC[HASH_LENGTH_MAX];         /* computed HMAC */
4878     unsigned char expectedHMAC[HASH_LENGTH_MAX]; /* for .fax files that have */
4879                                                  /* supplied known answer */
4880     HASH_HashType hash_alg = HASH_AlgNULL;       /* HMAC type */
4881 
4882     FILE *req = NULL; /* input stream from the REQUEST file */
4883     FILE *resp;       /* output stream to the RESPONSE file */
4884 
4885     buf = PORT_ZAlloc(bufSize);
4886     if (buf == NULL) {
4887         goto loser;
4888     }
4889     msg = PORT_ZAlloc(msgLen);
4890     if (msg == NULL) {
4891         goto loser;
4892     }
4893 
4894     req = fopen(reqfn, "r");
4895     resp = stdout;
4896     while (fgets(buf, bufSize, req) != NULL) {
4897         if (strncmp(buf, "Mac", 3) == 0) {
4898             i = 3;
4899             while (isspace(buf[i]) || buf[i] == '=') {
4900                 i++;
4901             }
4902             memset(expectedHMAC, 0, HASH_LENGTH_MAX);
4903             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
4904                 hex_to_byteval(&buf[i], &expectedHMAC[j]);
4905             }
4906             if (memcmp(HMAC, expectedHMAC, TLen) != 0) {
4907                 fprintf(stderr, "Generate failed:\n");
4908                 fputs("   expected=", stderr);
4909                 to_hex_str(buf, expectedHMAC,
4910                            TLen);
4911                 fputs(buf, stderr);
4912                 fputs("\n   generated=", stderr);
4913                 to_hex_str(buf, HMAC,
4914                            TLen);
4915                 fputs(buf, stderr);
4916                 fputc('\n', stderr);
4917             }
4918         }
4919 
4920         /* a comment or blank line */
4921         if (buf[0] == '#' || buf[0] == '\n') {
4922             fputs(buf, resp);
4923             continue;
4924         }
4925         /* [L = Length of the MAC and HASH_type */
4926         if (buf[0] == '[') {
4927             if (strncmp(&buf[1], "L ", 1) == 0) {
4928                 i = 2;
4929                 while (isspace(buf[i]) || buf[i] == '=') {
4930                     i++;
4931                 }
4932                 /* HMACLen will get reused for Tlen */
4933                 HMACLen = atoi(&buf[i]);
4934                 hash_alg = sha_get_hashType(HMACLen * PR_BITS_PER_BYTE);
4935                 if (hash_alg == HASH_AlgNULL) {
4936                     goto loser;
4937                 }
4938                 fputs(buf, resp);
4939                 continue;
4940             }
4941         }
4942         /* Count = test iteration number*/
4943         if (strncmp(buf, "Count ", 5) == 0) {
4944             /* count can just be put into resp file */
4945             fputs(buf, resp);
4946             /* zeroize the variables for the test with this data set */
4947             keyLen = 0;
4948             TLen = 0;
4949             memset(key, 0, sizeof key);
4950             memset(msg, 0, msgLen);
4951             memset(HMAC, 0, sizeof HMAC);
4952             continue;
4953         }
4954         /* KLen = Length of the Input Secret Key ... */
4955         if (strncmp(buf, "Klen", 4) == 0) {
4956             i = 4;
4957             while (isspace(buf[i]) || buf[i] == '=') {
4958                 i++;
4959             }
4960             keyLen = atoi(&buf[i]); /* in bytes */
4961             fputs(buf, resp);
4962             continue;
4963         }
4964         /* key = the secret key for the key to MAC */
4965         if (strncmp(buf, "Key", 3) == 0) {
4966             i = 3;
4967             while (isspace(buf[i]) || buf[i] == '=') {
4968                 i++;
4969             }
4970             for (j = 0; j < keyLen; i += 2, j++) {
4971                 hex_to_byteval(&buf[i], &key[j]);
4972             }
4973             fputs(buf, resp);
4974         }
4975         /* TLen = Length of the calculated HMAC */
4976         if (strncmp(buf, "Tlen", 4) == 0) {
4977             i = 4;
4978             while (isspace(buf[i]) || buf[i] == '=') {
4979                 i++;
4980             }
4981             TLen = atoi(&buf[i]); /* in bytes */
4982             fputs(buf, resp);
4983             continue;
4984         }
4985         /* MSG = to HMAC always 128 bytes for these tests */
4986         if (strncmp(buf, "Msg", 3) == 0) {
4987             i = 3;
4988             while (isspace(buf[i]) || buf[i] == '=') {
4989                 i++;
4990             }
4991             for (j = 0; j < msgLen; i += 2, j++) {
4992                 hex_to_byteval(&buf[i], &msg[j]);
4993             }
4994             fputs(buf, resp);
4995             /* calculate the HMAC and output */
4996             if (hmac_calc(HMAC, HMACLen, key, keyLen,
4997                           msg, msgLen, hash_alg) != SECSuccess) {
4998                 goto loser;
4999             }
5000             fputs("Mac = ", resp);
5001             to_hex_str(buf, HMAC, TLen);
5002             fputs(buf, resp);
5003             fputc('\n', resp);
5004             continue;
5005         }
5006     }
5007 loser:
5008     if (req) {
5009         fclose(req);
5010     }
5011     if (buf) {
5012         PORT_ZFree(buf, bufSize);
5013     }
5014     if (msg) {
5015         PORT_ZFree(msg, msgLen);
5016     }
5017 }
5018 
5019 /*
5020  * Perform the DSA Key Pair Generation Test.
5021  *
5022  * reqfn is the pathname of the REQUEST file.
5023  *
5024  * The output RESPONSE file is written to stdout.
5025  */
5026 void
dsa_keypair_test(char * reqfn)5027 dsa_keypair_test(char *reqfn)
5028 {
5029     char buf[800]; /* holds one line from the input REQUEST file
5030                          * or to the output RESPONSE file.
5031                          * 800 to hold (384 public key (x2 for HEX) + 1'\n'
5032                          */
5033     FILE *dsareq;  /* input stream from the REQUEST file */
5034     FILE *dsaresp; /* output stream to the RESPONSE file */
5035     int count;
5036     int N;
5037     int L;
5038     int i;
5039     PQGParams *pqg = NULL;
5040     PQGVerify *vfy = NULL;
5041     PRBool use_dsa1 = PR_FALSE;
5042     int keySizeIndex; /* index for valid key sizes */
5043 
5044     dsareq = fopen(reqfn, "r");
5045     dsaresp = stdout;
5046     while (fgets(buf, sizeof buf, dsareq) != NULL) {
5047         /* a comment or blank line */
5048         if (buf[0] == '#' || buf[0] == '\n') {
5049             fputs(buf, dsaresp);
5050             continue;
5051         }
5052 
5053         /* [Mod = x] */
5054         if (buf[0] == '[') {
5055             if (pqg != NULL) {
5056                 PQG_DestroyParams(pqg);
5057                 pqg = NULL;
5058             }
5059             if (vfy != NULL) {
5060                 PQG_DestroyVerify(vfy);
5061                 vfy = NULL;
5062             }
5063 
5064             if (sscanf(buf, "[mod = L=%d, N=%d]", &L, &N) != 2) {
5065                 use_dsa1 = PR_TRUE;
5066                 if (sscanf(buf, "[mod = %d]", &L) != 1) {
5067                     goto loser;
5068                 }
5069             }
5070             fputs(buf, dsaresp);
5071             fputc('\n', dsaresp);
5072 
5073             if (use_dsa1) {
5074                 /*************************************************************
5075                  * PQG_ParamGenSeedLen doesn't take a key size, it takes an
5076                  * index that points to a valid key size.
5077                  */
5078                 keySizeIndex = PQG_PBITS_TO_INDEX(L);
5079                 if (keySizeIndex == -1 || L < 512 || L > 1024) {
5080                     fprintf(dsaresp,
5081                             "DSA key size must be a multiple of 64 between 512 "
5082                             "and 1024, inclusive");
5083                     goto loser;
5084                 }
5085 
5086                 /* Generate the parameters P, Q, and G */
5087                 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
5088                                         &pqg, &vfy) !=
5089                     SECSuccess) {
5090                     fprintf(dsaresp,
5091                             "ERROR: Unable to generate PQG parameters");
5092                     goto loser;
5093                 }
5094             } else {
5095                 if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
5096                     fprintf(dsaresp,
5097                             "ERROR: Unable to generate PQG parameters");
5098                     goto loser;
5099                 }
5100             }
5101 
5102             /* output P, Q, and G */
5103             to_hex_str(buf, pqg->prime.data, pqg->prime.len);
5104             fprintf(dsaresp, "P = %s\n", buf);
5105             to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
5106             fprintf(dsaresp, "Q = %s\n", buf);
5107             to_hex_str(buf, pqg->base.data, pqg->base.len);
5108             fprintf(dsaresp, "G = %s\n\n", buf);
5109             continue;
5110         }
5111         /* N = ...*/
5112         if (buf[0] == 'N') {
5113 
5114             if (sscanf(buf, "N = %d", &count) != 1) {
5115                 goto loser;
5116             }
5117             /* Generate a DSA key, and output the key pair for N times */
5118             for (i = 0; i < count; i++) {
5119                 DSAPrivateKey *dsakey = NULL;
5120                 if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
5121                     fprintf(dsaresp, "ERROR: Unable to generate DSA key");
5122                     goto loser;
5123                 }
5124                 to_hex_str(buf, dsakey->privateValue.data,
5125                            dsakey->privateValue.len);
5126                 fprintf(dsaresp, "X = %s\n", buf);
5127                 to_hex_str(buf, dsakey->publicValue.data,
5128                            dsakey->publicValue.len);
5129                 fprintf(dsaresp, "Y = %s\n\n", buf);
5130                 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
5131                 dsakey = NULL;
5132             }
5133             continue;
5134         }
5135     }
5136 loser:
5137     fclose(dsareq);
5138 }
5139 
5140 /*
5141  * pqg generation type
5142  */
5143 typedef enum {
5144     FIPS186_1, /* Generate/Verify P,Q & G  according to FIPS 186-1 */
5145     A_1_2_1,   /* Generate Provable P & Q */
5146     A_1_1_3,   /* Verify Probable P & Q */
5147     A_1_2_2,   /* Verify Provable P & Q */
5148     A_2_1,     /* Generate Unverifiable G */
5149     A_2_2,     /* Assure Unverifiable G */
5150     A_2_3,     /* Generate Verifiable G */
5151     A_2_4      /* Verify Verifiable G */
5152 } dsa_pqg_type;
5153 
5154 /*
5155  * Perform the DSA Domain Parameter Validation Test.
5156  *
5157  * reqfn is the pathname of the REQUEST file.
5158  *
5159  * The output RESPONSE file is written to stdout.
5160  */
5161 void
dsa_pqgver_test(char * reqfn)5162 dsa_pqgver_test(char *reqfn)
5163 {
5164     char buf[800]; /* holds one line from the input REQUEST file
5165                          * or to the output RESPONSE file.
5166                          * 800 to hold (384 public key (x2 for HEX) + P = ...
5167                          */
5168     FILE *dsareq;  /* input stream from the REQUEST file */
5169     FILE *dsaresp; /* output stream to the RESPONSE file */
5170     int N;
5171     int L;
5172     unsigned int i, j;
5173     PQGParams pqg;
5174     PQGVerify vfy;
5175     unsigned int pghSize = 0; /* size for p, g, and h */
5176     dsa_pqg_type type = FIPS186_1;
5177 
5178     dsareq = fopen(reqfn, "r");
5179     dsaresp = stdout;
5180     memset(&pqg, 0, sizeof(pqg));
5181     memset(&vfy, 0, sizeof(vfy));
5182 
5183     while (fgets(buf, sizeof buf, dsareq) != NULL) {
5184         /* a comment or blank line */
5185         if (buf[0] == '#' || buf[0] == '\n') {
5186             fputs(buf, dsaresp);
5187             continue;
5188         }
5189 
5190         /* [A.xxxxx ] */
5191         if (buf[0] == '[' && buf[1] == 'A') {
5192 
5193             if (strncmp(&buf[1], "A.1.1.3", 7) == 0) {
5194                 type = A_1_1_3;
5195             } else if (strncmp(&buf[1], "A.2.2", 5) == 0) {
5196                 type = A_2_2;
5197             } else if (strncmp(&buf[1], "A.2.4", 5) == 0) {
5198                 type = A_2_4;
5199             } else if (strncmp(&buf[1], "A.1.2.2", 7) == 0) {
5200                 type = A_1_2_2;
5201                 /* validate our output from PQGGEN */
5202             } else if (strncmp(&buf[1], "A.1.1.2", 7) == 0) {
5203                 type = A_2_4; /* validate PQ and G together */
5204             } else {
5205                 fprintf(stderr, "Unknown dsa ver test %s\n", &buf[1]);
5206                 exit(1);
5207             }
5208 
5209             fputs(buf, dsaresp);
5210             continue;
5211         }
5212 
5213         /* [Mod = x] */
5214         if (buf[0] == '[') {
5215 
5216             if (type == FIPS186_1) {
5217                 N = 160;
5218                 if (sscanf(buf, "[mod = %d]", &L) != 1) {
5219                     goto loser;
5220                 }
5221             } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
5222                 goto loser;
5223             }
5224 
5225             if (pqg.prime.data) { /* P */
5226                 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
5227             }
5228             if (pqg.subPrime.data) { /* Q */
5229                 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
5230             }
5231             if (pqg.base.data) { /* G */
5232                 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
5233             }
5234             if (vfy.seed.data) { /* seed */
5235                 SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
5236             }
5237             if (vfy.h.data) { /* H */
5238                 SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
5239             }
5240 
5241             fputs(buf, dsaresp);
5242 
5243             /*calculate the size of p, g, and h then allocate items  */
5244             pghSize = L / 8;
5245 
5246             pqg.base.data = vfy.h.data = NULL;
5247             vfy.seed.len = pqg.base.len = vfy.h.len = 0;
5248             SECITEM_AllocItem(NULL, &pqg.prime, pghSize);
5249             SECITEM_AllocItem(NULL, &vfy.seed, pghSize * 3);
5250             if (type == A_2_2) {
5251                 SECITEM_AllocItem(NULL, &vfy.h, pghSize);
5252                 vfy.h.len = pghSize;
5253             } else if (type == A_2_4) {
5254                 SECITEM_AllocItem(NULL, &vfy.h, 1);
5255                 vfy.h.len = 1;
5256             }
5257             pqg.prime.len = pghSize;
5258             /* q is always N bits */
5259             SECITEM_AllocItem(NULL, &pqg.subPrime, N / 8);
5260             pqg.subPrime.len = N / 8;
5261             vfy.counter = -1;
5262 
5263             continue;
5264         }
5265         /* P = ... */
5266         if (buf[0] == 'P') {
5267             i = 1;
5268             while (isspace(buf[i]) || buf[i] == '=') {
5269                 i++;
5270             }
5271             for (j = 0; j < pqg.prime.len; i += 2, j++) {
5272                 hex_to_byteval(&buf[i], &pqg.prime.data[j]);
5273             }
5274 
5275             fputs(buf, dsaresp);
5276             continue;
5277         }
5278 
5279         /* Q = ... */
5280         if (buf[0] == 'Q') {
5281             i = 1;
5282             while (isspace(buf[i]) || buf[i] == '=') {
5283                 i++;
5284             }
5285             for (j = 0; j < pqg.subPrime.len; i += 2, j++) {
5286                 hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
5287             }
5288 
5289             fputs(buf, dsaresp);
5290             continue;
5291         }
5292 
5293         /* G = ... */
5294         if (buf[0] == 'G') {
5295             i = 1;
5296             if (pqg.base.data) {
5297                 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
5298             }
5299             SECITEM_AllocItem(NULL, &pqg.base, pghSize);
5300             while (isspace(buf[i]) || buf[i] == '=') {
5301                 i++;
5302             }
5303             for (j = 0; j < pqg.base.len; i += 2, j++) {
5304                 hex_to_byteval(&buf[i], &pqg.base.data[j]);
5305             }
5306 
5307             fputs(buf, dsaresp);
5308             continue;
5309         }
5310 
5311         /* Seed = ...  or domain_parameter_seed = ... */
5312         if (strncmp(buf, "Seed", 4) == 0) {
5313             i = 4;
5314         } else if (strncmp(buf, "domain_parameter_seed", 21) == 0) {
5315             i = 21;
5316         } else if (strncmp(buf, "firstseed", 9) == 0) {
5317             i = 9;
5318         } else {
5319             i = 0;
5320         }
5321         if (i) {
5322             while (isspace(buf[i]) || buf[i] == '=') {
5323                 i++;
5324             }
5325             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
5326                 hex_to_byteval(&buf[i], &vfy.seed.data[j]);
5327             }
5328             vfy.seed.len = j;
5329 
5330             fputs(buf, dsaresp);
5331             if (type == A_2_4) {
5332                 SECStatus result;
5333 
5334                 /* Verify the Parameters */
5335                 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
5336                 if (rv != SECSuccess) {
5337                     goto loser;
5338                 }
5339                 if (result == SECSuccess) {
5340                     fprintf(dsaresp, "Result = P\n");
5341                 } else {
5342                     fprintf(dsaresp, "Result = F\n");
5343                 }
5344             }
5345             continue;
5346         }
5347         if ((strncmp(buf, "pseed", 5) == 0) ||
5348             (strncmp(buf, "qseed", 5) == 0)) {
5349             i = 5;
5350             while (isspace(buf[i]) || buf[i] == '=') {
5351                 i++;
5352             }
5353             for (j = vfy.seed.len; isxdigit(buf[i]); i += 2, j++) {
5354                 hex_to_byteval(&buf[i], &vfy.seed.data[j]);
5355             }
5356             vfy.seed.len = j;
5357             fputs(buf, dsaresp);
5358 
5359             continue;
5360         }
5361         if (strncmp(buf, "index", 4) == 0) {
5362             i = 5;
5363             while (isspace(buf[i]) || buf[i] == '=') {
5364                 i++;
5365             }
5366             hex_to_byteval(&buf[i], &vfy.h.data[0]);
5367             vfy.h.len = 1;
5368             fputs(buf, dsaresp);
5369         }
5370 
5371         /* c = ...  or counter=*/
5372         if (buf[0] == 'c') {
5373             if (strncmp(buf, "counter", 7) == 0) {
5374                 if (sscanf(buf, "counter = %u", &vfy.counter) != 1) {
5375                     goto loser;
5376                 }
5377             } else {
5378                 if (sscanf(buf, "c = %u", &vfy.counter) != 1) {
5379                     goto loser;
5380                 }
5381             }
5382 
5383             fputs(buf, dsaresp);
5384             if (type == A_1_1_3) {
5385                 SECStatus result;
5386                 /* only verify P and Q, we have everything now. do it */
5387                 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
5388                 if (rv != SECSuccess) {
5389                     goto loser;
5390                 }
5391                 if (result == SECSuccess) {
5392                     fprintf(dsaresp, "Result = P\n");
5393                 } else {
5394                     fprintf(dsaresp, "Result = F\n");
5395                 }
5396                 fprintf(dsaresp, "\n");
5397             }
5398             continue;
5399         }
5400         if (strncmp(buf, "pgen_counter", 12) == 0) {
5401             if (sscanf(buf, "pgen_counter = %u", &vfy.counter) != 1) {
5402                 goto loser;
5403             }
5404             fputs(buf, dsaresp);
5405             continue;
5406         }
5407         if (strncmp(buf, "qgen_counter", 12) == 0) {
5408             fputs(buf, dsaresp);
5409             if (type == A_1_2_2) {
5410                 SECStatus result;
5411                 /* only verify P and Q, we have everything now. do it */
5412                 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
5413                 if (rv != SECSuccess) {
5414                     goto loser;
5415                 }
5416                 if (result == SECSuccess) {
5417                     fprintf(dsaresp, "Result = P\n");
5418                 } else {
5419                     fprintf(dsaresp, "Result = F\n");
5420                 }
5421                 fprintf(dsaresp, "\n");
5422             }
5423             continue;
5424         }
5425         /* H = ... */
5426         if (buf[0] == 'H') {
5427             SECStatus rv, result = SECFailure;
5428 
5429             i = 1;
5430             while (isspace(buf[i]) || buf[i] == '=') {
5431                 i++;
5432             }
5433             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
5434                 hex_to_byteval(&buf[i], &vfy.h.data[j]);
5435             }
5436             vfy.h.len = j;
5437             fputs(buf, dsaresp);
5438 
5439             /* this should be a byte value. Remove the leading zeros. If
5440              * it doesn't reduce to a byte, PQG_VerifyParams will catch it
5441             if (type == A_2_2) {
5442                 data_save = vfy.h.data;
5443                 while(vfy.h.data[0] && (vfy.h.len > 1)) {
5444                         vfy.h.data++;
5445                         vfy.h.len--;
5446                 }
5447             } */
5448 
5449             /* Verify the Parameters */
5450             rv = PQG_VerifyParams(&pqg, &vfy, &result);
5451             if (rv != SECSuccess) {
5452                 goto loser;
5453             }
5454             if (result == SECSuccess) {
5455                 fprintf(dsaresp, "Result = P\n");
5456             } else {
5457                 fprintf(dsaresp, "Result = F\n");
5458             }
5459             fprintf(dsaresp, "\n");
5460             continue;
5461         }
5462     }
5463 loser:
5464     fclose(dsareq);
5465     if (pqg.prime.data) { /* P */
5466         SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
5467     }
5468     if (pqg.subPrime.data) { /* Q */
5469         SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
5470     }
5471     if (pqg.base.data) { /* G */
5472         SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
5473     }
5474     if (vfy.seed.data) { /* seed */
5475         SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
5476     }
5477     if (vfy.h.data) { /* H */
5478         SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
5479     }
5480 }
5481 
5482 /*
5483  * Perform the DSA Public Key Validation Test.
5484  *
5485  * reqfn is the pathname of the REQUEST file.
5486  *
5487  * The output RESPONSE file is written to stdout.
5488  */
5489 void
dsa_pqggen_test(char * reqfn)5490 dsa_pqggen_test(char *reqfn)
5491 {
5492     char buf[800]; /* holds one line from the input REQUEST file
5493                          * or to the output RESPONSE file.
5494                          * 800 to hold seed = (384 public key (x2 for HEX)
5495                          */
5496     FILE *dsareq;  /* input stream from the REQUEST file */
5497     FILE *dsaresp; /* output stream to the RESPONSE file */
5498     int count;     /* number of times to generate parameters */
5499     int N;
5500     int L;
5501     int i;
5502     unsigned int j;
5503     int output_g = 1;
5504     PQGParams *pqg = NULL;
5505     PQGVerify *vfy = NULL;
5506     unsigned int keySizeIndex = 0;
5507     dsa_pqg_type type = FIPS186_1;
5508 
5509     dsareq = fopen(reqfn, "r");
5510     dsaresp = stdout;
5511     while (fgets(buf, sizeof buf, dsareq) != NULL) {
5512         /* a comment or blank line */
5513         if (buf[0] == '#' || buf[0] == '\n') {
5514             fputs(buf, dsaresp);
5515             continue;
5516         }
5517 
5518         /* [A.xxxxx ] */
5519         if (buf[0] == '[' && buf[1] == 'A') {
5520             if (strncmp(&buf[1], "A.1.1.2", 7) == 0) {
5521                 fprintf(stderr, "NSS does Generate Probablistic Primes\n");
5522                 exit(1);
5523             } else if (strncmp(&buf[1], "A.2.1", 5) == 0) {
5524                 type = A_1_2_1;
5525                 output_g = 1;
5526                 exit(1);
5527             } else if (strncmp(&buf[1], "A.2.3", 5) == 0) {
5528                 fprintf(stderr, "NSS only Generates G with P&Q\n");
5529                 exit(1);
5530             } else if (strncmp(&buf[1], "A.1.2.1", 7) == 0) {
5531                 type = A_1_2_1;
5532                 output_g = 0;
5533             } else {
5534                 fprintf(stderr, "Unknown dsa pqggen test %s\n", &buf[1]);
5535                 exit(1);
5536             }
5537             fputs(buf, dsaresp);
5538             continue;
5539         }
5540 
5541         /* [Mod = ... ] */
5542         if (buf[0] == '[') {
5543 
5544             if (type == FIPS186_1) {
5545                 N = 160;
5546                 if (sscanf(buf, "[mod = %d]", &L) != 1) {
5547                     goto loser;
5548                 }
5549             } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
5550                 goto loser;
5551             }
5552 
5553             fputs(buf, dsaresp);
5554             fputc('\n', dsaresp);
5555 
5556             if (type == FIPS186_1) {
5557                 /************************************************************
5558                  * PQG_ParamGenSeedLen doesn't take a key size, it takes an
5559                  * index that points to a valid key size.
5560                  */
5561                 keySizeIndex = PQG_PBITS_TO_INDEX(L);
5562                 if (keySizeIndex == -1 || L < 512 || L > 1024) {
5563                     fprintf(dsaresp,
5564                             "DSA key size must be a multiple of 64 between 512 "
5565                             "and 1024, inclusive");
5566                     goto loser;
5567                 }
5568             }
5569             continue;
5570         }
5571         /* N = ... */
5572         if (buf[0] == 'N') {
5573             if (strncmp(buf, "Num", 3) == 0) {
5574                 if (sscanf(buf, "Num = %d", &count) != 1) {
5575                     goto loser;
5576                 }
5577             } else if (sscanf(buf, "N = %d", &count) != 1) {
5578                 goto loser;
5579             }
5580             for (i = 0; i < count; i++) {
5581                 SECStatus rv;
5582 
5583                 if (type == FIPS186_1) {
5584                     rv = PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
5585                                              &pqg, &vfy);
5586                 } else {
5587                     rv = PQG_ParamGenV2(L, N, N, &pqg, &vfy);
5588                 }
5589                 if (rv != SECSuccess) {
5590                     fprintf(dsaresp,
5591                             "ERROR: Unable to generate PQG parameters");
5592                     goto loser;
5593                 }
5594                 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
5595                 fprintf(dsaresp, "P = %s\n", buf);
5596                 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
5597                 fprintf(dsaresp, "Q = %s\n", buf);
5598                 if (output_g) {
5599                     to_hex_str(buf, pqg->base.data, pqg->base.len);
5600                     fprintf(dsaresp, "G = %s\n", buf);
5601                 }
5602                 if (type == FIPS186_1) {
5603                     to_hex_str(buf, vfy->seed.data, vfy->seed.len);
5604                     fprintf(dsaresp, "Seed = %s\n", buf);
5605                     fprintf(dsaresp, "c = %d\n", vfy->counter);
5606                     to_hex_str(buf, vfy->h.data, vfy->h.len);
5607                     fputs("H = ", dsaresp);
5608                     for (j = vfy->h.len; j < pqg->prime.len; j++) {
5609                         fprintf(dsaresp, "00");
5610                     }
5611                     fprintf(dsaresp, "%s\n", buf);
5612                 } else {
5613                     unsigned int seedlen = vfy->seed.len / 2;
5614                     unsigned int pgen_counter = vfy->counter >> 16;
5615                     unsigned int qgen_counter = vfy->counter & 0xffff;
5616                     /*fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]); */
5617                     to_hex_str(buf, vfy->seed.data, seedlen);
5618                     fprintf(dsaresp, "pseed = %s\n", buf);
5619                     to_hex_str(buf, vfy->seed.data + seedlen, seedlen);
5620                     fprintf(dsaresp, "qseed = %s\n", buf);
5621                     fprintf(dsaresp, "pgen_counter = %d\n", pgen_counter);
5622                     fprintf(dsaresp, "qgen_counter = %d\n", qgen_counter);
5623                     if (output_g) {
5624                         to_hex_str(buf, vfy->seed.data, vfy->seed.len);
5625                         fprintf(dsaresp, "domain_parameter_seed = %s\n", buf);
5626                         fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]);
5627                     }
5628                 }
5629                 fputc('\n', dsaresp);
5630                 if (pqg != NULL) {
5631                     PQG_DestroyParams(pqg);
5632                     pqg = NULL;
5633                 }
5634                 if (vfy != NULL) {
5635                     PQG_DestroyVerify(vfy);
5636                     vfy = NULL;
5637                 }
5638             }
5639 
5640             continue;
5641         }
5642     }
5643 loser:
5644     fclose(dsareq);
5645     if (pqg != NULL) {
5646         PQG_DestroyParams(pqg);
5647     }
5648     if (vfy != NULL) {
5649         PQG_DestroyVerify(vfy);
5650     }
5651 }
5652 
5653 /*
5654  * Perform the DSA Signature Generation Test.
5655  *
5656  * reqfn is the pathname of the REQUEST file.
5657  *
5658  * The output RESPONSE file is written to stdout.
5659  */
5660 void
dsa_siggen_test(char * reqfn)5661 dsa_siggen_test(char *reqfn)
5662 {
5663     char buf[800]; /* holds one line from the input REQUEST file
5664                          * or to the output RESPONSE file.
5665                          * max for Msg = ....
5666                          */
5667     FILE *dsareq;  /* input stream from the REQUEST file */
5668     FILE *dsaresp; /* output stream to the RESPONSE file */
5669     int modulus;
5670     int L;
5671     int N;
5672     int i, j;
5673     PRBool use_dsa1 = PR_FALSE;
5674     PQGParams *pqg = NULL;
5675     PQGVerify *vfy = NULL;
5676     DSAPrivateKey *dsakey = NULL;
5677     int keySizeIndex;                       /* index for valid key sizes */
5678     unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */
5679     unsigned char sig[DSA_MAX_SIGNATURE_LEN];
5680     SECItem digest, signature;
5681     HASH_HashType hashType = HASH_AlgNULL;
5682     int hashNum = 0;
5683 
5684     dsareq = fopen(reqfn, "r");
5685     dsaresp = stdout;
5686 
5687     while (fgets(buf, sizeof buf, dsareq) != NULL) {
5688         /* a comment or blank line */
5689         if (buf[0] == '#' || buf[0] == '\n') {
5690             fputs(buf, dsaresp);
5691             continue;
5692         }
5693 
5694         /* [Mod = x] */
5695         if (buf[0] == '[') {
5696             if (pqg != NULL) {
5697                 PQG_DestroyParams(pqg);
5698                 pqg = NULL;
5699             }
5700             if (vfy != NULL) {
5701                 PQG_DestroyVerify(vfy);
5702                 vfy = NULL;
5703             }
5704             if (dsakey != NULL) {
5705                 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
5706                 dsakey = NULL;
5707             }
5708 
5709             if (sscanf(buf, "[mod = L=%d,  N=%d, SHA-%d]", &L, &N,
5710                        &hashNum) != 3) {
5711                 use_dsa1 = PR_TRUE;
5712                 hashNum = 1;
5713                 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
5714                     goto loser;
5715                 }
5716             }
5717             fputs(buf, dsaresp);
5718             fputc('\n', dsaresp);
5719 
5720             /****************************************************************
5721             * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
5722             * that points to a valid key size.
5723             */
5724             if (use_dsa1) {
5725                 keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
5726                 if (keySizeIndex == -1 || modulus < 512 || modulus > 1024) {
5727                     fprintf(dsaresp,
5728                             "DSA key size must be a multiple of 64 between 512 "
5729                             "and 1024, inclusive");
5730                     goto loser;
5731                 }
5732                 /* Generate PQG and output PQG */
5733                 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
5734                                         &pqg, &vfy) !=
5735                     SECSuccess) {
5736                     fprintf(dsaresp,
5737                             "ERROR: Unable to generate PQG parameters");
5738                     goto loser;
5739                 }
5740             } else {
5741                 if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
5742                     fprintf(dsaresp,
5743                             "ERROR: Unable to generate PQG parameters");
5744                     goto loser;
5745                 }
5746             }
5747             to_hex_str(buf, pqg->prime.data, pqg->prime.len);
5748             fprintf(dsaresp, "P = %s\n", buf);
5749             to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
5750             fprintf(dsaresp, "Q = %s\n", buf);
5751             to_hex_str(buf, pqg->base.data, pqg->base.len);
5752             fprintf(dsaresp, "G = %s\n", buf);
5753 
5754             /* create DSA Key */
5755             if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
5756                 fprintf(dsaresp, "ERROR: Unable to generate DSA key");
5757                 goto loser;
5758             }
5759 
5760             hashType = sha_get_hashType(hashNum);
5761             if (hashType == HASH_AlgNULL) {
5762                 fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)", hashNum);
5763                 goto loser;
5764             }
5765             continue;
5766         }
5767 
5768         /* Msg = ... */
5769         if (strncmp(buf, "Msg", 3) == 0) {
5770             unsigned char msg[128]; /* MAX msg 128 */
5771             unsigned int len = 0;
5772 
5773             if (hashType == HASH_AlgNULL) {
5774                 fprintf(dsaresp, "ERROR: Hash Alg not set");
5775                 goto loser;
5776             }
5777 
5778             memset(hashBuf, 0, sizeof hashBuf);
5779             memset(sig, 0, sizeof sig);
5780 
5781             i = 3;
5782             while (isspace(buf[i]) || buf[i] == '=') {
5783                 i++;
5784             }
5785             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
5786                 hex_to_byteval(&buf[i], &msg[j]);
5787             }
5788             if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) {
5789                 fprintf(dsaresp, "ERROR: Unable to generate SHA% digest",
5790                         hashNum);
5791                 goto loser;
5792             }
5793 
5794             digest.type = siBuffer;
5795             digest.data = hashBuf;
5796             digest.len = fips_hashLen(hashType);
5797             signature.type = siBuffer;
5798             signature.data = sig;
5799             signature.len = sizeof sig;
5800 
5801             if (DSA_SignDigest(dsakey, &signature, &digest) != SECSuccess) {
5802                 fprintf(dsaresp, "ERROR: Unable to generate DSA signature");
5803                 goto loser;
5804             }
5805             len = signature.len;
5806             if (len % 2 != 0) {
5807                 goto loser;
5808             }
5809             len = len / 2;
5810 
5811             /* output the orginal Msg, and generated Y, R, and S */
5812             fputs(buf, dsaresp);
5813             to_hex_str(buf, dsakey->publicValue.data,
5814                        dsakey->publicValue.len);
5815             fprintf(dsaresp, "Y = %s\n", buf);
5816             to_hex_str(buf, &signature.data[0], len);
5817             fprintf(dsaresp, "R = %s\n", buf);
5818             to_hex_str(buf, &signature.data[len], len);
5819             fprintf(dsaresp, "S = %s\n", buf);
5820             fputc('\n', dsaresp);
5821             continue;
5822         }
5823     }
5824 loser:
5825     fclose(dsareq);
5826     if (pqg != NULL) {
5827         PQG_DestroyParams(pqg);
5828         pqg = NULL;
5829     }
5830     if (vfy != NULL) {
5831         PQG_DestroyVerify(vfy);
5832         vfy = NULL;
5833     }
5834     if (dsakey) {
5835         PORT_FreeArena(dsakey->params.arena, PR_TRUE);
5836         dsakey = NULL;
5837     }
5838 }
5839 
5840 /*
5841  * Perform the DSA Signature Verification Test.
5842  *
5843  * reqfn is the pathname of the REQUEST file.
5844  *
5845  * The output RESPONSE file is written to stdout.
5846  */
5847 void
dsa_sigver_test(char * reqfn)5848 dsa_sigver_test(char *reqfn)
5849 {
5850     char buf[800]; /* holds one line from the input REQUEST file
5851                          * or to the output RESPONSE file.
5852                          * max for Msg = ....
5853                          */
5854     FILE *dsareq;  /* input stream from the REQUEST file */
5855     FILE *dsaresp; /* output stream to the RESPONSE file */
5856     int L;
5857     int N;
5858     unsigned int i, j;
5859     SECItem digest, signature;
5860     DSAPublicKey pubkey;
5861     unsigned int pgySize;                   /* size for p, g, and y */
5862     unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */
5863     unsigned char sig[DSA_MAX_SIGNATURE_LEN];
5864     HASH_HashType hashType = HASH_AlgNULL;
5865     int hashNum = 0;
5866 
5867     dsareq = fopen(reqfn, "r");
5868     dsaresp = stdout;
5869     memset(&pubkey, 0, sizeof(pubkey));
5870 
5871     while (fgets(buf, sizeof buf, dsareq) != NULL) {
5872         /* a comment or blank line */
5873         if (buf[0] == '#' || buf[0] == '\n') {
5874             fputs(buf, dsaresp);
5875             continue;
5876         }
5877 
5878         /* [Mod = x] */
5879         if (buf[0] == '[') {
5880 
5881             if (sscanf(buf, "[mod = L=%d,  N=%d, SHA-%d]", &L, &N,
5882                        &hashNum) != 3) {
5883                 N = 160;
5884                 hashNum = 1;
5885                 if (sscanf(buf, "[mod = %d]", &L) != 1) {
5886                     goto loser;
5887                 }
5888             }
5889 
5890             if (pubkey.params.prime.data) { /* P */
5891                 SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
5892             }
5893             if (pubkey.params.subPrime.data) { /* Q */
5894                 SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
5895             }
5896             if (pubkey.params.base.data) { /* G */
5897                 SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
5898             }
5899             if (pubkey.publicValue.data) { /* Y */
5900                 SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
5901             }
5902             fputs(buf, dsaresp);
5903 
5904             /* calculate the size of p, g, and y then allocate items */
5905             pgySize = L / 8;
5906             SECITEM_AllocItem(NULL, &pubkey.params.prime, pgySize);
5907             SECITEM_AllocItem(NULL, &pubkey.params.base, pgySize);
5908             SECITEM_AllocItem(NULL, &pubkey.publicValue, pgySize);
5909             pubkey.params.prime.len = pubkey.params.base.len = pgySize;
5910             pubkey.publicValue.len = pgySize;
5911 
5912             /* q always N/8 bytes */
5913             SECITEM_AllocItem(NULL, &pubkey.params.subPrime, N / 8);
5914             pubkey.params.subPrime.len = N / 8;
5915 
5916             hashType = sha_get_hashType(hashNum);
5917             if (hashType == HASH_AlgNULL) {
5918                 fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)", hashNum);
5919                 goto loser;
5920             }
5921 
5922             continue;
5923         }
5924         /* P = ... */
5925         if (buf[0] == 'P') {
5926             i = 1;
5927             while (isspace(buf[i]) || buf[i] == '=') {
5928                 i++;
5929             }
5930             memset(pubkey.params.prime.data, 0, pubkey.params.prime.len);
5931             for (j = 0; j < pubkey.params.prime.len; i += 2, j++) {
5932                 hex_to_byteval(&buf[i], &pubkey.params.prime.data[j]);
5933             }
5934 
5935             fputs(buf, dsaresp);
5936             continue;
5937         }
5938 
5939         /* Q = ... */
5940         if (buf[0] == 'Q') {
5941             i = 1;
5942             while (isspace(buf[i]) || buf[i] == '=') {
5943                 i++;
5944             }
5945             memset(pubkey.params.subPrime.data, 0, pubkey.params.subPrime.len);
5946             for (j = 0; j < pubkey.params.subPrime.len; i += 2, j++) {
5947                 hex_to_byteval(&buf[i], &pubkey.params.subPrime.data[j]);
5948             }
5949 
5950             fputs(buf, dsaresp);
5951             continue;
5952         }
5953 
5954         /* G = ... */
5955         if (buf[0] == 'G') {
5956             i = 1;
5957             while (isspace(buf[i]) || buf[i] == '=') {
5958                 i++;
5959             }
5960             memset(pubkey.params.base.data, 0, pubkey.params.base.len);
5961             for (j = 0; j < pubkey.params.base.len; i += 2, j++) {
5962                 hex_to_byteval(&buf[i], &pubkey.params.base.data[j]);
5963             }
5964 
5965             fputs(buf, dsaresp);
5966             continue;
5967         }
5968 
5969         /* Msg = ... */
5970         if (strncmp(buf, "Msg", 3) == 0) {
5971             unsigned char msg[128]; /* MAX msg 128 */
5972             memset(hashBuf, 0, sizeof hashBuf);
5973 
5974             if (hashType == HASH_AlgNULL) {
5975                 fprintf(dsaresp, "ERROR: Hash Alg not set");
5976                 goto loser;
5977             }
5978 
5979             i = 3;
5980             while (isspace(buf[i]) || buf[i] == '=') {
5981                 i++;
5982             }
5983             for (j = 0; isxdigit(buf[i]); i += 2, j++) {
5984                 hex_to_byteval(&buf[i], &msg[j]);
5985             }
5986             if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) {
5987                 fprintf(dsaresp, "ERROR: Unable to generate SHA-%d digest",
5988                         hashNum);
5989                 goto loser;
5990             }
5991 
5992             fputs(buf, dsaresp);
5993             continue;
5994         }
5995 
5996         /* Y = ... */
5997         if (buf[0] == 'Y') {
5998             i = 1;
5999             while (isspace(buf[i]) || buf[i] == '=') {
6000                 i++;
6001             }
6002             memset(pubkey.publicValue.data, 0, pubkey.params.subPrime.len);
6003             for (j = 0; j < pubkey.publicValue.len; i += 2, j++) {
6004                 hex_to_byteval(&buf[i], &pubkey.publicValue.data[j]);
6005             }
6006 
6007             fputs(buf, dsaresp);
6008             continue;
6009         }
6010 
6011         /* R = ... */
6012         if (buf[0] == 'R') {
6013             memset(sig, 0, sizeof sig);
6014             i = 1;
6015             while (isspace(buf[i]) || buf[i] == '=') {
6016                 i++;
6017             }
6018             for (j = 0; j < pubkey.params.subPrime.len; i += 2, j++) {
6019                 hex_to_byteval(&buf[i], &sig[j]);
6020             }
6021 
6022             fputs(buf, dsaresp);
6023             continue;
6024         }
6025 
6026         /* S = ... */
6027         if (buf[0] == 'S') {
6028             if (hashType == HASH_AlgNULL) {
6029                 fprintf(dsaresp, "ERROR: Hash Alg not set");
6030                 goto loser;
6031             }
6032 
6033             i = 1;
6034             while (isspace(buf[i]) || buf[i] == '=') {
6035                 i++;
6036             }
6037             for (j = pubkey.params.subPrime.len;
6038                  j < pubkey.params.subPrime.len * 2; i += 2, j++) {
6039                 hex_to_byteval(&buf[i], &sig[j]);
6040             }
6041             fputs(buf, dsaresp);
6042 
6043             digest.type = siBuffer;
6044             digest.data = hashBuf;
6045             digest.len = fips_hashLen(hashType);
6046             signature.type = siBuffer;
6047             signature.data = sig;
6048             signature.len = pubkey.params.subPrime.len * 2;
6049 
6050             if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) {
6051                 fprintf(dsaresp, "Result = P\n");
6052             } else {
6053                 fprintf(dsaresp, "Result = F\n");
6054             }
6055             fprintf(dsaresp, "\n");
6056             continue;
6057         }
6058     }
6059 loser:
6060     fclose(dsareq);
6061     if (pubkey.params.prime.data) { /* P */
6062         SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
6063     }
6064     if (pubkey.params.subPrime.data) { /* Q */
6065         SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
6066     }
6067     if (pubkey.params.base.data) { /* G */
6068         SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
6069     }
6070     if (pubkey.publicValue.data) { /* Y */
6071         SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
6072     }
6073 }
6074 
6075 static void
pad(unsigned char * buf,int pad_len,unsigned char * src,int src_len)6076 pad(unsigned char *buf, int pad_len, unsigned char *src, int src_len)
6077 {
6078     int offset = 0;
6079     /* this shouldn't happen, fail right away rather than produce bad output */
6080     if (pad_len < src_len) {
6081         fprintf(stderr, "data bigger than expected! %d > %d\n", src_len, pad_len);
6082         exit(1);
6083     }
6084 
6085     offset = pad_len - src_len;
6086     memset(buf, 0, offset);
6087     memcpy(buf + offset, src, src_len);
6088     return;
6089 }
6090 
6091 /*
6092  * Perform the DSA Key Pair Generation Test.
6093  *
6094  * reqfn is the pathname of the REQUEST file.
6095  *
6096  * The output RESPONSE file is written to stdout.
6097  */
6098 void
rsa_keypair_test(char * reqfn)6099 rsa_keypair_test(char *reqfn)
6100 {
6101     char buf[800];           /* holds one line from the input REQUEST file
6102                          * or to the output RESPONSE file.
6103                          * 800 to hold (384 public key (x2 for HEX) + 1'\n'
6104                          */
6105     unsigned char buf2[400]; /* can't need more then 1/2 buf length */
6106     FILE *rsareq;            /* input stream from the REQUEST file */
6107     FILE *rsaresp;           /* output stream to the RESPONSE file */
6108     int count;
6109     int i;
6110     int keySize = 1; /* key size in bits*/
6111     int len = 0;     /* key size in bytes */
6112     int len2 = 0;    /* key size in bytes/2 (prime size) */
6113     SECItem e;
6114     unsigned char default_e[] = { 0x1, 0x0, 0x1 };
6115 
6116     e.data = default_e;
6117     e.len = sizeof(default_e);
6118 
6119     rsareq = fopen(reqfn, "r");
6120     rsaresp = stdout;
6121     while (fgets(buf, sizeof buf, rsareq) != NULL) {
6122         /* a comment or blank line */
6123         if (buf[0] == '#' || buf[0] == '\n') {
6124             fputs(buf, rsaresp);
6125             continue;
6126         }
6127 
6128         /* [Mod = x] */
6129         if (buf[0] == '[') {
6130             if (buf[1] == 'm') {
6131                 if (sscanf(buf, "[mod = %d]", &keySize) != 1) {
6132                     goto loser;
6133                 }
6134                 len = keySize / 8;
6135                 len2 = keySize / 16;
6136             }
6137             fputs(buf, rsaresp);
6138             continue;
6139         }
6140         /* N = ...*/
6141         if (buf[0] == 'N') {
6142 
6143             if (sscanf(buf, "N = %d", &count) != 1) {
6144                 goto loser;
6145             }
6146 
6147             /* Generate a DSA key, and output the key pair for N times */
6148             for (i = 0; i < count; i++) {
6149                 RSAPrivateKey *rsakey = NULL;
6150                 if ((rsakey = RSA_NewKey(keySize, &e)) == NULL) {
6151                     fprintf(rsaresp, "ERROR: Unable to generate RSA key");
6152                     goto loser;
6153                 }
6154                 pad(buf2, len, rsakey->publicExponent.data,
6155                     rsakey->publicExponent.len);
6156                 to_hex_str(buf, buf2, len);
6157                 fprintf(rsaresp, "e = %s\n", buf);
6158                 pad(buf2, len2, rsakey->prime1.data,
6159                     rsakey->prime1.len);
6160                 to_hex_str(buf, buf2, len2);
6161                 fprintf(rsaresp, "p = %s\n", buf);
6162                 pad(buf2, len2, rsakey->prime2.data,
6163                     rsakey->prime2.len);
6164                 to_hex_str(buf, buf2, len2);
6165                 fprintf(rsaresp, "q = %s\n", buf);
6166                 pad(buf2, len, rsakey->modulus.data,
6167                     rsakey->modulus.len);
6168                 to_hex_str(buf, buf2, len);
6169                 fprintf(rsaresp, "n = %s\n", buf);
6170                 pad(buf2, len, rsakey->privateExponent.data,
6171                     rsakey->privateExponent.len);
6172                 to_hex_str(buf, buf2, len);
6173                 fprintf(rsaresp, "d = %s\n", buf);
6174                 fprintf(rsaresp, "\n");
6175                 PORT_FreeArena(rsakey->arena, PR_TRUE);
6176                 rsakey = NULL;
6177             }
6178             continue;
6179         }
6180     }
6181 loser:
6182     fclose(rsareq);
6183 }
6184 
6185 /*
6186  * Perform the RSA Signature Generation Test.
6187  *
6188  * reqfn is the pathname of the REQUEST file.
6189  *
6190  * The output RESPONSE file is written to stdout.
6191  */
6192 void
rsa_siggen_test(char * reqfn)6193 rsa_siggen_test(char *reqfn)
6194 {
6195     char buf[2 * RSA_MAX_TEST_MODULUS_BYTES + 1];
6196     /* buf holds one line from the input REQUEST file
6197                          * or to the output RESPONSE file.
6198                          * 2x for HEX output + 1 for \n
6199                          */
6200     FILE *rsareq;  /* input stream from the REQUEST file */
6201     FILE *rsaresp; /* output stream to the RESPONSE file */
6202     int i, j;
6203     unsigned char sha[HASH_LENGTH_MAX];  /* SHA digest */
6204     unsigned int shaLength = 0;          /* length of SHA */
6205     HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
6206     SECOidTag shaOid = SEC_OID_UNKNOWN;
6207     int modulus; /* the Modulus size */
6208     int publicExponent = DEFAULT_RSA_PUBLIC_EXPONENT;
6209     SECItem pe = { 0, 0, 0 };
6210     unsigned char pubEx[4];
6211     int peCount = 0;
6212 
6213     RSAPrivateKey *rsaBlapiPrivKey = NULL;  /* holds RSA private and
6214                                               * public keys */
6215     RSAPublicKey *rsaBlapiPublicKey = NULL; /* hold RSA public key */
6216 
6217     rsareq = fopen(reqfn, "r");
6218     rsaresp = stdout;
6219 
6220     /* calculate the exponent */
6221     for (i = 0; i < 4; i++) {
6222         if (peCount || (publicExponent &
6223                         ((unsigned long)0xff000000L >> (i *
6224                                                         8)))) {
6225             pubEx[peCount] =
6226                 (unsigned char)((publicExponent >> (3 - i) * 8) & 0xff);
6227             peCount++;
6228         }
6229     }
6230     pe.len = peCount;
6231     pe.data = &pubEx[0];
6232     pe.type = siBuffer;
6233 
6234     while (fgets(buf, sizeof buf, rsareq) != NULL) {
6235         /* a comment or blank line */
6236         if (buf[0] == '#' || buf[0] == '\n') {
6237             fputs(buf, rsaresp);
6238             continue;
6239         }
6240 
6241         /* [mod = ...] */
6242         if (buf[0] == '[') {
6243 
6244             if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
6245                 goto loser;
6246             }
6247             if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
6248                 fprintf(rsaresp, "ERROR: modulus greater than test maximum\n");
6249                 goto loser;
6250             }
6251 
6252             fputs(buf, rsaresp);
6253 
6254             if (rsaBlapiPrivKey != NULL) {
6255                 PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
6256                 rsaBlapiPrivKey = NULL;
6257                 rsaBlapiPublicKey = NULL;
6258             }
6259 
6260             rsaBlapiPrivKey = RSA_NewKey(modulus, &pe);
6261             if (rsaBlapiPrivKey == NULL) {
6262                 fprintf(rsaresp, "Error unable to create RSA key\n");
6263                 goto loser;
6264             }
6265 
6266             to_hex_str(buf, rsaBlapiPrivKey->modulus.data,
6267                        rsaBlapiPrivKey->modulus.len);
6268             fprintf(rsaresp, "\nn = %s\n\n", buf);
6269             to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data,
6270                        rsaBlapiPrivKey->publicExponent.len);
6271             fprintf(rsaresp, "e = %s\n", buf);
6272             /* convert private key to public key.  Memory
6273              * is freed with private key's arena  */
6274             rsaBlapiPublicKey = (RSAPublicKey *)PORT_ArenaAlloc(
6275                 rsaBlapiPrivKey->arena,
6276                 sizeof(RSAPublicKey));
6277 
6278             rsaBlapiPublicKey->modulus.len = rsaBlapiPrivKey->modulus.len;
6279             rsaBlapiPublicKey->modulus.data = rsaBlapiPrivKey->modulus.data;
6280             rsaBlapiPublicKey->publicExponent.len =
6281                 rsaBlapiPrivKey->publicExponent.len;
6282             rsaBlapiPublicKey->publicExponent.data =
6283                 rsaBlapiPrivKey->publicExponent.data;
6284             continue;
6285         }
6286 
6287         /* SHAAlg = ... */
6288         if (strncmp(buf, "SHAAlg", 6) == 0) {
6289             i = 6;
6290             while (isspace(buf[i]) || buf[i] == '=') {
6291                 i++;
6292             }
6293             /* set the SHA Algorithm */
6294             shaAlg = hash_string_to_hashType(&buf[i]);
6295             if (shaAlg == HASH_AlgNULL) {
6296                 fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
6297                 goto loser;
6298             }
6299             fputs(buf, rsaresp);
6300             continue;
6301         }
6302         /* Msg = ... */
6303         if (strncmp(buf, "Msg", 3) == 0) {
6304 
6305             unsigned char msg[128]; /* MAX msg 128 */
6306             unsigned int rsa_bytes_signed;
6307             unsigned char rsa_computed_signature[RSA_MAX_TEST_MODULUS_BYTES];
6308             SECStatus rv = SECFailure;
6309             NSSLOWKEYPublicKey *rsa_public_key;
6310             NSSLOWKEYPrivateKey *rsa_private_key;
6311             NSSLOWKEYPrivateKey low_RSA_private_key = { NULL,
6312                                                         NSSLOWKEYRSAKey };
6313             NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
6314                                                       NSSLOWKEYRSAKey };
6315 
6316             low_RSA_private_key.u.rsa = *rsaBlapiPrivKey;
6317             low_RSA_public_key.u.rsa = *rsaBlapiPublicKey;
6318 
6319             rsa_private_key = &low_RSA_private_key;
6320             rsa_public_key = &low_RSA_public_key;
6321 
6322             memset(sha, 0, sizeof sha);
6323             memset(msg, 0, sizeof msg);
6324             rsa_bytes_signed = 0;
6325             memset(rsa_computed_signature, 0, sizeof rsa_computed_signature);
6326 
6327             i = 3;
6328             while (isspace(buf[i]) || buf[i] == '=') {
6329                 i++;
6330             }
6331             for (j = 0; isxdigit(buf[i]) && j < sizeof(msg); i += 2, j++) {
6332                 hex_to_byteval(&buf[i], &msg[j]);
6333             }
6334             shaLength = fips_hashLen(shaAlg);
6335             if (fips_hashBuf(shaAlg, sha, msg, j) != SECSuccess) {
6336                 if (shaLength == 0) {
6337                     fprintf(rsaresp, "ERROR: SHAAlg not defined.");
6338                 }
6339                 fprintf(rsaresp, "ERROR: Unable to generate SHA%x",
6340                         shaLength == 160 ? 1 : shaLength);
6341                 goto loser;
6342             }
6343             shaOid = fips_hashOid(shaAlg);
6344 
6345             /* Perform RSA signature with the RSA private key. */
6346             rv = RSA_HashSign(shaOid,
6347                               rsa_private_key,
6348                               rsa_computed_signature,
6349                               &rsa_bytes_signed,
6350                               nsslowkey_PrivateModulusLen(rsa_private_key),
6351                               sha,
6352                               shaLength);
6353 
6354             if (rv != SECSuccess) {
6355                 fprintf(rsaresp, "ERROR: RSA_HashSign failed");
6356                 goto loser;
6357             }
6358 
6359             /* Output the signature */
6360             fputs(buf, rsaresp);
6361             to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed);
6362             fprintf(rsaresp, "S = %s\n", buf);
6363 
6364             /* Perform RSA verification with the RSA public key. */
6365             rv = RSA_HashCheckSign(shaOid,
6366                                    rsa_public_key,
6367                                    rsa_computed_signature,
6368                                    rsa_bytes_signed,
6369                                    sha,
6370                                    shaLength);
6371             if (rv != SECSuccess) {
6372                 fprintf(rsaresp, "ERROR: RSA_HashCheckSign failed");
6373                 goto loser;
6374             }
6375             continue;
6376         }
6377     }
6378 loser:
6379     fclose(rsareq);
6380 
6381     if (rsaBlapiPrivKey != NULL) {
6382         /* frees private and public key */
6383         PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
6384         rsaBlapiPrivKey = NULL;
6385         rsaBlapiPublicKey = NULL;
6386     }
6387 }
6388 /*
6389  * Perform the RSA Signature Verification Test.
6390  *
6391  * reqfn is the pathname of the REQUEST file.
6392  *
6393  * The output RESPONSE file is written to stdout.
6394  */
6395 void
rsa_sigver_test(char * reqfn)6396 rsa_sigver_test(char *reqfn)
6397 {
6398     char buf[2 * RSA_MAX_TEST_MODULUS_BYTES + 7];
6399     /* buf holds one line from the input REQUEST file
6400                          * or to the output RESPONSE file.
6401                          * s = 2x for HEX output + 1 for \n
6402                          */
6403     FILE *rsareq;  /* input stream from the REQUEST file */
6404     FILE *rsaresp; /* output stream to the RESPONSE file */
6405     int i, j;
6406     unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
6407     unsigned int shaLength = 0;         /* actual length of the digest */
6408     HASH_HashType shaAlg = HASH_AlgNULL;
6409     SECOidTag shaOid = SEC_OID_UNKNOWN;
6410     int modulus = 0;                  /* the Modulus size */
6411     unsigned char signature[513];     /* largest signature size + '\n' */
6412     unsigned int signatureLength = 0; /* actual length of the signature */
6413     PRBool keyvalid = PR_TRUE;
6414 
6415     RSAPublicKey rsaBlapiPublicKey; /* hold RSA public key */
6416 
6417     rsareq = fopen(reqfn, "r");
6418     rsaresp = stdout;
6419     memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey));
6420 
6421     while (fgets(buf, sizeof buf, rsareq) != NULL) {
6422         /* a comment or blank line */
6423         if (buf[0] == '#' || buf[0] == '\n') {
6424             fputs(buf, rsaresp);
6425             continue;
6426         }
6427 
6428         /* [Mod = ...] */
6429         if (buf[0] == '[') {
6430             unsigned int flen; /* length in bytes of the field size */
6431 
6432             if (rsaBlapiPublicKey.modulus.data) { /* n */
6433                 SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
6434             }
6435             if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
6436                 goto loser;
6437             }
6438 
6439             if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
6440                 fprintf(rsaresp, "ERROR: modulus greater than test maximum\n");
6441                 goto loser;
6442             }
6443 
6444             fputs(buf, rsaresp);
6445 
6446             signatureLength = flen = modulus / 8;
6447 
6448             SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.modulus, flen);
6449             if (rsaBlapiPublicKey.modulus.data == NULL) {
6450                 goto loser;
6451             }
6452             continue;
6453         }
6454 
6455         /* n = ... modulus */
6456         if (buf[0] == 'n') {
6457             i = 1;
6458             while (isspace(buf[i]) || buf[i] == '=') {
6459                 i++;
6460             }
6461             keyvalid = from_hex_str(&rsaBlapiPublicKey.modulus.data[0],
6462                                     rsaBlapiPublicKey.modulus.len,
6463                                     &buf[i]);
6464 
6465             if (!keyvalid) {
6466                 fprintf(rsaresp, "ERROR: rsa_sigver n not valid.\n");
6467                 goto loser;
6468             }
6469             fputs(buf, rsaresp);
6470             continue;
6471         }
6472 
6473         /* SHAAlg = ... */
6474         if (strncmp(buf, "SHAAlg", 6) == 0) {
6475             i = 6;
6476             while (isspace(buf[i]) || buf[i] == '=') {
6477                 i++;
6478             }
6479             /* set the SHA Algorithm */
6480             shaAlg = hash_string_to_hashType(&buf[i]);
6481             if (shaAlg == HASH_AlgNULL) {
6482                 fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
6483                 goto loser;
6484             }
6485             fputs(buf, rsaresp);
6486             continue;
6487         }
6488 
6489         /* e = ... public Key */
6490         if (buf[0] == 'e') {
6491             unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES];
6492             unsigned char t;
6493 
6494             memset(data, 0, sizeof data);
6495 
6496             if (rsaBlapiPublicKey.publicExponent.data) { /* e */
6497                 SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
6498             }
6499 
6500             i = 1;
6501             while (isspace(buf[i]) || buf[i] == '=') {
6502                 i++;
6503             }
6504             /* skip leading zero's */
6505             while (isxdigit(buf[i])) {
6506                 hex_to_byteval(&buf[i], &t);
6507                 if (t == 0) {
6508                     i += 2;
6509                 } else
6510                     break;
6511             }
6512 
6513             /* get the exponent */
6514             for (j = 0; isxdigit(buf[i]) && j < sizeof data; i += 2, j++) {
6515                 hex_to_byteval(&buf[i], &data[j]);
6516             }
6517 
6518             if (j == 0) {
6519                 j = 1;
6520             } /* to handle 1 byte length exponents */
6521 
6522             SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.publicExponent, j);
6523             if (rsaBlapiPublicKey.publicExponent.data == NULL) {
6524                 goto loser;
6525             }
6526 
6527             for (i = 0; i < j; i++) {
6528                 rsaBlapiPublicKey.publicExponent.data[i] = data[i];
6529             }
6530 
6531             fputs(buf, rsaresp);
6532             continue;
6533         }
6534 
6535         /* Msg = ... */
6536         if (strncmp(buf, "Msg", 3) == 0) {
6537             unsigned char msg[128]; /* MAX msg 128 */
6538 
6539             memset(sha, 0, sizeof sha);
6540             memset(msg, 0, sizeof msg);
6541 
6542             i = 3;
6543             while (isspace(buf[i]) || buf[i] == '=') {
6544                 i++;
6545             }
6546 
6547             for (j = 0; isxdigit(buf[i]) && j < sizeof msg; i += 2, j++) {
6548                 hex_to_byteval(&buf[i], &msg[j]);
6549             }
6550 
6551             shaLength = fips_hashLen(shaAlg);
6552             if (fips_hashBuf(shaAlg, sha, msg, j) != SECSuccess) {
6553                 if (shaLength == 0) {
6554                     fprintf(rsaresp, "ERROR: SHAAlg not defined.");
6555                 }
6556                 fprintf(rsaresp, "ERROR: Unable to generate SHA%x",
6557                         shaLength == 160 ? 1 : shaLength);
6558                 goto loser;
6559             }
6560 
6561             fputs(buf, rsaresp);
6562             continue;
6563         }
6564 
6565         /* S = ... */
6566         if (buf[0] == 'S') {
6567             SECStatus rv = SECFailure;
6568             NSSLOWKEYPublicKey *rsa_public_key;
6569             NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
6570                                                       NSSLOWKEYRSAKey };
6571 
6572             /* convert to a low RSA public key */
6573             low_RSA_public_key.u.rsa = rsaBlapiPublicKey;
6574             rsa_public_key = &low_RSA_public_key;
6575 
6576             memset(signature, 0, sizeof(signature));
6577             i = 1;
6578             while (isspace(buf[i]) || buf[i] == '=') {
6579                 i++;
6580             }
6581 
6582             for (j = 0; isxdigit(buf[i]) && j < sizeof signature; i += 2, j++) {
6583                 hex_to_byteval(&buf[i], &signature[j]);
6584             }
6585 
6586             signatureLength = j;
6587             fputs(buf, rsaresp);
6588 
6589             shaOid = fips_hashOid(shaAlg);
6590 
6591             /* Perform RSA verification with the RSA public key. */
6592             rv = RSA_HashCheckSign(shaOid,
6593                                    rsa_public_key,
6594                                    signature,
6595                                    signatureLength,
6596                                    sha,
6597                                    shaLength);
6598             if (rv == SECSuccess) {
6599                 fputs("Result = P\n", rsaresp);
6600             } else {
6601                 fputs("Result = F\n", rsaresp);
6602             }
6603             continue;
6604         }
6605     }
6606 loser:
6607     fclose(rsareq);
6608     if (rsaBlapiPublicKey.modulus.data) { /* n */
6609         SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
6610     }
6611     if (rsaBlapiPublicKey.publicExponent.data) { /* e */
6612         SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
6613     }
6614 }
6615 
6616 void
tls(char * reqfn)6617 tls(char *reqfn)
6618 {
6619     char buf[256]; /* holds one line from the input REQUEST file.
6620                          * needs to be large enough to hold the longest
6621                          * line "XSeed = <128 hex digits>\n".
6622                          */
6623     unsigned char *pms = NULL;
6624     int pms_len;
6625     unsigned char *master_secret = NULL;
6626     unsigned char *key_block = NULL;
6627     int key_block_len;
6628     unsigned char serverHello_random[SSL3_RANDOM_LENGTH];
6629     unsigned char clientHello_random[SSL3_RANDOM_LENGTH];
6630     unsigned char server_random[SSL3_RANDOM_LENGTH];
6631     unsigned char client_random[SSL3_RANDOM_LENGTH];
6632     FILE *tlsreq = NULL; /* input stream from the REQUEST file */
6633     FILE *tlsresp;       /* output stream to the RESPONSE file */
6634     unsigned int i, j;
6635     CK_SLOT_ID slotList[10];
6636     CK_SLOT_ID slotID;
6637     CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
6638     CK_ULONG count;
6639     static const CK_C_INITIALIZE_ARGS pk11args = {
6640         NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
6641         (void *)"flags=readOnly,noCertDB,noModDB", NULL
6642     };
6643     static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
6644     static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
6645     static CK_BBOOL ck_true = CK_TRUE;
6646     static CK_ULONG one = 1;
6647     CK_ATTRIBUTE create_template[] = {
6648         { CKA_VALUE, NULL, 0 },
6649         { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
6650         { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
6651         { CKA_DERIVE, &ck_true, sizeof(ck_true) },
6652     };
6653     CK_ULONG create_template_count =
6654         sizeof(create_template) / sizeof(create_template[0]);
6655     CK_ATTRIBUTE derive_template[] = {
6656         { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
6657         { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
6658         { CKA_DERIVE, &ck_true, sizeof(ck_true) },
6659         { CKA_VALUE_LEN, &one, sizeof(one) },
6660     };
6661     CK_ULONG derive_template_count =
6662         sizeof(derive_template) / sizeof(derive_template[0]);
6663     CK_ATTRIBUTE master_template =
6664         { CKA_VALUE, NULL, 0 };
6665     CK_ATTRIBUTE kb1_template =
6666         { CKA_VALUE, NULL, 0 };
6667     CK_ATTRIBUTE kb2_template =
6668         { CKA_VALUE, NULL, 0 };
6669 
6670     CK_MECHANISM master_mech = { CKM_TLS_MASTER_KEY_DERIVE, NULL, 0 };
6671     CK_MECHANISM key_block_mech = { CKM_TLS_KEY_AND_MAC_DERIVE, NULL, 0 };
6672     CK_TLS12_MASTER_KEY_DERIVE_PARAMS master_params;
6673     CK_TLS12_KEY_MAT_PARAMS key_block_params;
6674     CK_SSL3_KEY_MAT_OUT key_material;
6675     CK_RV crv;
6676 
6677     /* set up PKCS #11 parameters */
6678     master_params.prfHashMechanism = CKM_SHA256;
6679     master_params.pVersion = NULL;
6680     master_params.RandomInfo.pClientRandom = clientHello_random;
6681     master_params.RandomInfo.ulClientRandomLen = sizeof(clientHello_random);
6682     master_params.RandomInfo.pServerRandom = serverHello_random;
6683     master_params.RandomInfo.ulServerRandomLen = sizeof(serverHello_random);
6684     master_mech.pParameter = (void *)&master_params;
6685     master_mech.ulParameterLen = sizeof(master_params);
6686     key_block_params.prfHashMechanism = CKM_SHA256;
6687     key_block_params.ulMacSizeInBits = 0;
6688     key_block_params.ulKeySizeInBits = 0;
6689     key_block_params.ulIVSizeInBits = 0;
6690     key_block_params.bIsExport = PR_FALSE; /* ignored anyway for TLS mech */
6691     key_block_params.RandomInfo.pClientRandom = client_random;
6692     key_block_params.RandomInfo.ulClientRandomLen = sizeof(client_random);
6693     key_block_params.RandomInfo.pServerRandom = server_random;
6694     key_block_params.RandomInfo.ulServerRandomLen = sizeof(server_random);
6695     key_block_params.pReturnedKeyMaterial = &key_material;
6696     key_block_mech.pParameter = (void *)&key_block_params;
6697     key_block_mech.ulParameterLen = sizeof(key_block_params);
6698 
6699     crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
6700     if (crv != CKR_OK) {
6701         fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
6702         goto loser;
6703     }
6704     count = slotListCount;
6705     crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
6706     if (crv != CKR_OK) {
6707         fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
6708         goto loser;
6709     }
6710     if ((count > slotListCount) || count < 1) {
6711         fprintf(stderr,
6712                 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
6713                 (int)count, (int)slotListCount);
6714         goto loser;
6715     }
6716     slotID = slotList[0];
6717     tlsreq = fopen(reqfn, "r");
6718     tlsresp = stdout;
6719     while (fgets(buf, sizeof buf, tlsreq) != NULL) {
6720         /* a comment or blank line */
6721         if (buf[0] == '#' || buf[0] == '\n') {
6722             fputs(buf, tlsresp);
6723             continue;
6724         }
6725         /* [Xchange - SHA1] */
6726         if (buf[0] == '[') {
6727             if (strncmp(buf, "[TLS", 4) == 0) {
6728                 if (buf[7] == '0') {
6729                     /* CK_SSL3_MASTER_KEY_DERIVE_PARAMS is a subset of
6730                      * CK_TLS12_MASTER_KEY_DERIVE_PARAMS and
6731                      * CK_SSL3_KEY_MAT_PARAMS is a subset of
6732                      * CK_TLS12_KEY_MAT_PARAMS. The latter params have
6733                      * an extra prfHashMechanism field at the end. */
6734                     master_mech.mechanism = CKM_TLS_MASTER_KEY_DERIVE;
6735                     key_block_mech.mechanism = CKM_TLS_KEY_AND_MAC_DERIVE;
6736                     master_mech.ulParameterLen = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
6737                     key_block_mech.ulParameterLen = sizeof(CK_SSL3_KEY_MAT_PARAMS);
6738                 } else if (buf[7] == '2') {
6739                     if (strncmp(&buf[10], "SHA-1", 5) == 0) {
6740                         master_params.prfHashMechanism = CKM_SHA_1;
6741                         key_block_params.prfHashMechanism = CKM_SHA_1;
6742                     } else if (strncmp(&buf[10], "SHA-224", 7) == 0) {
6743                         master_params.prfHashMechanism = CKM_SHA224;
6744                         key_block_params.prfHashMechanism = CKM_SHA224;
6745                     } else if (strncmp(&buf[10], "SHA-256", 7) == 0) {
6746                         master_params.prfHashMechanism = CKM_SHA256;
6747                         key_block_params.prfHashMechanism = CKM_SHA256;
6748                     } else if (strncmp(&buf[10], "SHA-384", 7) == 0) {
6749                         master_params.prfHashMechanism = CKM_SHA384;
6750                         key_block_params.prfHashMechanism = CKM_SHA384;
6751                     } else if (strncmp(&buf[10], "SHA-512", 7) == 0) {
6752                         master_params.prfHashMechanism = CKM_SHA512;
6753                         key_block_params.prfHashMechanism = CKM_SHA512;
6754                     } else {
6755                         fprintf(tlsresp, "ERROR: Unable to find prf Hash type");
6756                         goto loser;
6757                     }
6758                     master_mech.mechanism = CKM_TLS12_MASTER_KEY_DERIVE;
6759                     key_block_mech.mechanism = CKM_TLS12_KEY_AND_MAC_DERIVE;
6760                     master_mech.ulParameterLen = sizeof(master_params);
6761                     key_block_mech.ulParameterLen = sizeof(key_block_params);
6762                 } else {
6763                     fprintf(stderr, "Unknown TLS type %x\n",
6764                             (unsigned int)buf[0]);
6765                     goto loser;
6766                 }
6767             }
6768             if (strncmp(buf, "[pre-master", 11) == 0) {
6769                 if (sscanf(buf, "[pre-master secret length = %d]",
6770                            &pms_len) != 1) {
6771                     goto loser;
6772                 }
6773                 pms_len = pms_len / 8;
6774                 pms = malloc(pms_len);
6775                 master_secret = malloc(pms_len);
6776                 create_template[0].pValue = pms;
6777                 create_template[0].ulValueLen = pms_len;
6778                 master_template.pValue = master_secret;
6779                 master_template.ulValueLen = pms_len;
6780             }
6781             if (strncmp(buf, "[key", 4) == 0) {
6782                 if (sscanf(buf, "[key block length = %d]", &key_block_len) != 1) {
6783                     goto loser;
6784                 }
6785                 key_block_params.ulKeySizeInBits = 8;
6786                 key_block_params.ulIVSizeInBits = key_block_len / 2 - 8;
6787                 key_block_len = key_block_len / 8;
6788                 key_block = malloc(key_block_len);
6789                 kb1_template.pValue = &key_block[0];
6790                 kb1_template.ulValueLen = 1;
6791                 kb2_template.pValue = &key_block[1];
6792                 kb2_template.ulValueLen = 1;
6793                 key_material.pIVClient = &key_block[2];
6794                 key_material.pIVServer = &key_block[2 + key_block_len / 2 - 1];
6795             }
6796             fputs(buf, tlsresp);
6797             continue;
6798         }
6799         /* "COUNT = x" begins a new data set */
6800         if (strncmp(buf, "COUNT", 5) == 0) {
6801             /* zeroize the variables for the test with this data set */
6802             memset(pms, 0, pms_len);
6803             memset(master_secret, 0, pms_len);
6804             memset(key_block, 0, key_block_len);
6805             fputs(buf, tlsresp);
6806             continue;
6807         }
6808         /* pre_master_secret = ... */
6809         if (strncmp(buf, "pre_master_secret", 17) == 0) {
6810             i = 17;
6811             while (isspace(buf[i]) || buf[i] == '=') {
6812                 i++;
6813             }
6814             for (j = 0; j < pms_len; i += 2, j++) {
6815                 hex_to_byteval(&buf[i], &pms[j]);
6816             }
6817             fputs(buf, tlsresp);
6818             continue;
6819         }
6820         /* serverHello_random = ... */
6821         if (strncmp(buf, "serverHello_random", 18) == 0) {
6822             i = 18;
6823             while (isspace(buf[i]) || buf[i] == '=') {
6824                 i++;
6825             }
6826             for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
6827                 hex_to_byteval(&buf[i], &serverHello_random[j]);
6828             }
6829             fputs(buf, tlsresp);
6830             continue;
6831         }
6832         /* clientHello_random = ... */
6833         if (strncmp(buf, "clientHello_random", 18) == 0) {
6834             i = 18;
6835             while (isspace(buf[i]) || buf[i] == '=') {
6836                 i++;
6837             }
6838             for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
6839                 hex_to_byteval(&buf[i], &clientHello_random[j]);
6840             }
6841             fputs(buf, tlsresp);
6842             continue;
6843         }
6844         /* server_random = ... */
6845         if (strncmp(buf, "server_random", 13) == 0) {
6846             i = 13;
6847             while (isspace(buf[i]) || buf[i] == '=') {
6848                 i++;
6849             }
6850             for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
6851                 hex_to_byteval(&buf[i], &server_random[j]);
6852             }
6853             fputs(buf, tlsresp);
6854             continue;
6855         }
6856         /* client_random = ... */
6857         if (strncmp(buf, "client_random", 13) == 0) {
6858             CK_SESSION_HANDLE session;
6859             CK_OBJECT_HANDLE pms_handle;
6860             CK_OBJECT_HANDLE master_handle;
6861             CK_OBJECT_HANDLE fake_handle;
6862             i = 13;
6863             while (isspace(buf[i]) || buf[i] == '=') {
6864                 i++;
6865             }
6866             for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
6867                 hex_to_byteval(&buf[i], &client_random[j]);
6868             }
6869             fputs(buf, tlsresp);
6870             crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
6871             if (crv != CKR_OK) {
6872                 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
6873                         (unsigned int)crv);
6874                 goto loser;
6875             }
6876             crv = NSC_CreateObject(session, create_template,
6877                                    create_template_count, &pms_handle);
6878             if (crv != CKR_OK) {
6879                 fprintf(stderr, "NSC_CreateObject failed crv=0x%x\n",
6880                         (unsigned int)crv);
6881                 goto loser;
6882             }
6883             crv = NSC_DeriveKey(session, &master_mech, pms_handle,
6884                                 derive_template, derive_template_count - 1,
6885                                 &master_handle);
6886             if (crv != CKR_OK) {
6887                 fprintf(stderr, "NSC_DeriveKey(master) failed crv=0x%x\n",
6888                         (unsigned int)crv);
6889                 goto loser;
6890             }
6891             crv = NSC_GetAttributeValue(session, master_handle,
6892                                         &master_template, 1);
6893             if (crv != CKR_OK) {
6894                 fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n",
6895                         (unsigned int)crv);
6896                 goto loser;
6897             }
6898             fputs("master_secret = ", tlsresp);
6899             to_hex_str(buf, master_secret, pms_len);
6900             fputs(buf, tlsresp);
6901             fputc('\n', tlsresp);
6902             crv = NSC_DeriveKey(session, &key_block_mech, master_handle,
6903                                 derive_template, derive_template_count, &fake_handle);
6904             if (crv != CKR_OK) {
6905                 fprintf(stderr,
6906                         "NSC_DeriveKey(keyblock) failed crv=0x%x\n",
6907                         (unsigned int)crv);
6908                 goto loser;
6909             }
6910             crv = NSC_GetAttributeValue(session, key_material.hClientKey,
6911                                         &kb1_template, 1);
6912             if (crv != CKR_OK) {
6913                 fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n",
6914                         (unsigned int)crv);
6915                 goto loser;
6916             }
6917             crv = NSC_GetAttributeValue(session, key_material.hServerKey,
6918                                         &kb2_template, 1);
6919             if (crv != CKR_OK) {
6920                 fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n",
6921                         (unsigned int)crv);
6922                 goto loser;
6923             }
6924             fputs("key_block = ", tlsresp);
6925             to_hex_str(buf, key_block, key_block_len);
6926             fputs(buf, tlsresp);
6927             fputc('\n', tlsresp);
6928             crv = NSC_CloseSession(session);
6929             continue;
6930         }
6931     }
6932 loser:
6933     NSC_Finalize(NULL);
6934     if (pms)
6935         free(pms);
6936     if (master_secret)
6937         free(master_secret);
6938     if (key_block)
6939         free(key_block);
6940     if (tlsreq)
6941         fclose(tlsreq);
6942 }
6943 
6944 void
ikev1(char * reqfn)6945 ikev1(char *reqfn)
6946 {
6947     char buf[4096]; /* holds one line from the input REQUEST file.
6948                          * needs to be large enough to hold the longest
6949                          * line "g^xy = <2048 hex digits>\n".
6950                          */
6951     unsigned char *gxy = NULL;
6952     int gxy_len;
6953     unsigned char *Ni = NULL;
6954     int Ni_len;
6955     unsigned char *Nr = NULL;
6956     int Nr_len;
6957     unsigned char CKYi[8];
6958     int CKYi_len;
6959     unsigned char CKYr[8];
6960     int CKYr_len;
6961     unsigned int i, j;
6962     FILE *ikereq = NULL; /* input stream from the REQUEST file */
6963     FILE *ikeresp;       /* output stream to the RESPONSE file */
6964 
6965     CK_SLOT_ID slotList[10];
6966     CK_SLOT_ID slotID;
6967     CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
6968     CK_ULONG count;
6969     static const CK_C_INITIALIZE_ARGS pk11args = {
6970         NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
6971         (void *)"flags=readOnly,noCertDB,noModDB", NULL
6972     };
6973     static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
6974     static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
6975     static CK_BBOOL ck_true = CK_TRUE;
6976     static CK_ULONG keyLen = 1;
6977     CK_ATTRIBUTE gxy_template[] = {
6978         { CKA_VALUE, NULL, 0 }, /* must be first */
6979         { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
6980         { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
6981         { CKA_DERIVE, &ck_true, sizeof(ck_true) },
6982     };
6983     CK_ULONG gxy_template_count =
6984         sizeof(gxy_template) / sizeof(gxy_template[0]);
6985     CK_ATTRIBUTE derive_template[] = {
6986         { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
6987         { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
6988         { CKA_DERIVE, &ck_true, sizeof(ck_true) },
6989         { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) }, /* must be last */
6990     };
6991     CK_ULONG derive_template_count =
6992         sizeof(derive_template) / sizeof(derive_template[0]);
6993     CK_ATTRIBUTE skeyid_template =
6994         { CKA_VALUE, NULL, 0 };
6995     CK_ATTRIBUTE skeyid_d_template =
6996         { CKA_VALUE, NULL, 0 };
6997     CK_ATTRIBUTE skeyid_a_template =
6998         { CKA_VALUE, NULL, 0 };
6999     CK_ATTRIBUTE skeyid_e_template =
7000         { CKA_VALUE, NULL, 0 };
7001     unsigned char skeyid_secret[HASH_LENGTH_MAX];
7002     unsigned char skeyid_d_secret[HASH_LENGTH_MAX];
7003     unsigned char skeyid_a_secret[HASH_LENGTH_MAX];
7004     unsigned char skeyid_e_secret[HASH_LENGTH_MAX];
7005 
7006     CK_MECHANISM ike_mech = { CKM_NSS_IKE_PRF_DERIVE, NULL, 0 };
7007     CK_MECHANISM ike1_mech = { CKM_NSS_IKE1_PRF_DERIVE, NULL, 0 };
7008     CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf;
7009     CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf;
7010     CK_RV crv;
7011 
7012     /* set up PKCS #11 parameters */
7013     ike_prf.bDataAsKey = PR_TRUE;
7014     ike_prf.bRekey = PR_FALSE;
7015     ike_prf.hNewKey = CK_INVALID_HANDLE;
7016     CKYi_len = sizeof(CKYi);
7017     CKYr_len = sizeof(CKYr);
7018     ike1_prf.pCKYi = CKYi;
7019     ike1_prf.ulCKYiLen = CKYi_len;
7020     ike1_prf.pCKYr = CKYr;
7021     ike1_prf.ulCKYrLen = CKYr_len;
7022     ike_mech.pParameter = &ike_prf;
7023     ike_mech.ulParameterLen = sizeof(ike_prf);
7024     ike1_mech.pParameter = &ike1_prf;
7025     ike1_mech.ulParameterLen = sizeof(ike1_prf);
7026     skeyid_template.pValue = skeyid_secret;
7027     skeyid_template.ulValueLen = HASH_LENGTH_MAX;
7028     skeyid_d_template.pValue = skeyid_d_secret;
7029     skeyid_d_template.ulValueLen = HASH_LENGTH_MAX;
7030     skeyid_a_template.pValue = skeyid_a_secret;
7031     skeyid_a_template.ulValueLen = HASH_LENGTH_MAX;
7032     skeyid_e_template.pValue = skeyid_e_secret;
7033     skeyid_e_template.ulValueLen = HASH_LENGTH_MAX;
7034 
7035     crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
7036     if (crv != CKR_OK) {
7037         fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
7038         goto loser;
7039     }
7040     count = slotListCount;
7041     crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
7042     if (crv != CKR_OK) {
7043         fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
7044         goto loser;
7045     }
7046     if ((count > slotListCount) || count < 1) {
7047         fprintf(stderr,
7048                 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
7049                 (int)count, (int)slotListCount);
7050         goto loser;
7051     }
7052     slotID = slotList[0];
7053     ikereq = fopen(reqfn, "r");
7054     ikeresp = stdout;
7055     while (fgets(buf, sizeof buf, ikereq) != NULL) {
7056         /* a comment or blank line */
7057         if (buf[0] == '#' || buf[0] == '\n') {
7058             fputs(buf, ikeresp);
7059             continue;
7060         }
7061         /* [.....] */
7062         if (buf[0] == '[') {
7063             if (strncmp(buf, "[SHA-1]", 7) == 0) {
7064                 ike_prf.prfMechanism = CKM_SHA_1_HMAC;
7065                 ike1_prf.prfMechanism = CKM_SHA_1_HMAC;
7066             }
7067             if (strncmp(buf, "[SHA-224]", 9) == 0) {
7068                 ike_prf.prfMechanism = CKM_SHA224_HMAC;
7069                 ike1_prf.prfMechanism = CKM_SHA224_HMAC;
7070             }
7071             if (strncmp(buf, "[SHA-256]", 9) == 0) {
7072                 ike_prf.prfMechanism = CKM_SHA256_HMAC;
7073                 ike1_prf.prfMechanism = CKM_SHA256_HMAC;
7074             }
7075             if (strncmp(buf, "[SHA-384]", 9) == 0) {
7076                 ike_prf.prfMechanism = CKM_SHA384_HMAC;
7077                 ike1_prf.prfMechanism = CKM_SHA384_HMAC;
7078             }
7079             if (strncmp(buf, "[SHA-512]", 9) == 0) {
7080                 ike_prf.prfMechanism = CKM_SHA512_HMAC;
7081                 ike1_prf.prfMechanism = CKM_SHA512_HMAC;
7082             }
7083             if (strncmp(buf, "[AES-XCBC", 9) == 0) {
7084                 ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
7085                 ike1_prf.prfMechanism = CKM_AES_XCBC_MAC;
7086             }
7087             if (strncmp(buf, "[g^xy", 5) == 0) {
7088                 if (sscanf(buf, "[g^xy length = %d]",
7089                            &gxy_len) != 1) {
7090                     goto loser;
7091                 }
7092                 gxy_len = gxy_len / 8;
7093                 if (gxy)
7094                     free(gxy);
7095                 gxy = malloc(gxy_len);
7096                 gxy_template[0].pValue = gxy;
7097                 gxy_template[0].ulValueLen = gxy_len;
7098             }
7099             if (strncmp(buf, "[Ni", 3) == 0) {
7100                 if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
7101                     goto loser;
7102                 }
7103                 Ni_len = Ni_len / 8;
7104                 if (Ni)
7105                     free(Ni);
7106                 Ni = malloc(Ni_len);
7107                 ike_prf.pNi = Ni;
7108                 ike_prf.ulNiLen = Ni_len;
7109             }
7110             if (strncmp(buf, "[Nr", 3) == 0) {
7111                 if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
7112                     goto loser;
7113                 }
7114                 Nr_len = Nr_len / 8;
7115                 if (Nr)
7116                     free(Nr);
7117                 Nr = malloc(Nr_len);
7118                 ike_prf.pNr = Nr;
7119                 ike_prf.ulNrLen = Nr_len;
7120             }
7121             fputs(buf, ikeresp);
7122             continue;
7123         }
7124         /* "COUNT = x" begins a new data set */
7125         if (strncmp(buf, "COUNT", 5) == 0) {
7126             /* zeroize the variables for the test with this data set */
7127             memset(gxy, 0, gxy_len);
7128             memset(Ni, 0, Ni_len);
7129             memset(Nr, 0, Nr_len);
7130             memset(CKYi, 0, CKYi_len);
7131             memset(CKYr, 0, CKYr_len);
7132             fputs(buf, ikeresp);
7133             continue;
7134         }
7135         /* Ni = ... */
7136         if (strncmp(buf, "Ni", 2) == 0) {
7137             i = 2;
7138             while (isspace(buf[i]) || buf[i] == '=') {
7139                 i++;
7140             }
7141             for (j = 0; j < Ni_len; i += 2, j++) {
7142                 hex_to_byteval(&buf[i], &Ni[j]);
7143             }
7144             fputs(buf, ikeresp);
7145             continue;
7146         }
7147         /* Nr = ... */
7148         if (strncmp(buf, "Nr", 2) == 0) {
7149             i = 2;
7150             while (isspace(buf[i]) || buf[i] == '=') {
7151                 i++;
7152             }
7153             for (j = 0; j < Nr_len; i += 2, j++) {
7154                 hex_to_byteval(&buf[i], &Nr[j]);
7155             }
7156             fputs(buf, ikeresp);
7157             continue;
7158         }
7159         /* CKYi = ... */
7160         if (strncmp(buf, "CKY_I", 5) == 0) {
7161             i = 5;
7162             while (isspace(buf[i]) || buf[i] == '=') {
7163                 i++;
7164             }
7165             for (j = 0; j < CKYi_len; i += 2, j++) {
7166                 hex_to_byteval(&buf[i], &CKYi[j]);
7167             }
7168             fputs(buf, ikeresp);
7169             continue;
7170         }
7171         /* CKYr = ... */
7172         if (strncmp(buf, "CKY_R", 5) == 0) {
7173             i = 5;
7174             while (isspace(buf[i]) || buf[i] == '=') {
7175                 i++;
7176             }
7177             for (j = 0; j < CKYr_len; i += 2, j++) {
7178                 hex_to_byteval(&buf[i], &CKYr[j]);
7179             }
7180             fputs(buf, ikeresp);
7181             continue;
7182         }
7183         /* g^xy = ... */
7184         if (strncmp(buf, "g^xy", 4) == 0) {
7185             CK_SESSION_HANDLE session;
7186             CK_OBJECT_HANDLE gxy_handle;
7187             CK_OBJECT_HANDLE skeyid_handle;
7188             CK_OBJECT_HANDLE skeyid_d_handle;
7189             CK_OBJECT_HANDLE skeyid_a_handle;
7190             CK_OBJECT_HANDLE skeyid_e_handle;
7191             i = 4;
7192             while (isspace(buf[i]) || buf[i] == '=') {
7193                 i++;
7194             }
7195             for (j = 0; j < gxy_len; i += 2, j++) {
7196                 hex_to_byteval(&buf[i], &gxy[j]);
7197             }
7198             fputs(buf, ikeresp);
7199             crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
7200             if (crv != CKR_OK) {
7201                 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
7202                         (unsigned int)crv);
7203                 goto loser;
7204             }
7205             crv = NSC_CreateObject(session, gxy_template,
7206                                    gxy_template_count, &gxy_handle);
7207             if (crv != CKR_OK) {
7208                 fprintf(stderr, "NSC_CreateObject failed crv=0x%x\n",
7209                         (unsigned int)crv);
7210                 goto loser;
7211             }
7212             /* get the skeyid key */
7213             crv = NSC_DeriveKey(session, &ike_mech, gxy_handle,
7214                                 derive_template, derive_template_count - 1,
7215                                 &skeyid_handle);
7216             if (crv != CKR_OK) {
7217                 fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
7218                         (unsigned int)crv);
7219                 goto loser;
7220             }
7221             skeyid_template.ulValueLen = HASH_LENGTH_MAX;
7222             crv = NSC_GetAttributeValue(session, skeyid_handle,
7223                                         &skeyid_template, 1);
7224             if (crv != CKR_OK) {
7225                 fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
7226                         (unsigned int)crv);
7227                 goto loser;
7228             }
7229             /* use the length of the skeyid to set the target length of all the
7230              * other keys */
7231             keyLen = skeyid_template.ulValueLen;
7232             ike1_prf.hKeygxy = gxy_handle;
7233             ike1_prf.bHasPrevKey = PR_FALSE;
7234             ike1_prf.keyNumber = 0;
7235             crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
7236                                 derive_template, derive_template_count,
7237                                 &skeyid_d_handle);
7238             if (crv != CKR_OK) {
7239                 fprintf(stderr, "NSC_DeriveKey(skeyid_d) failed crv=0x%x\n",
7240                         (unsigned int)crv);
7241                 goto loser;
7242             }
7243 
7244             ike1_prf.hKeygxy = gxy_handle;
7245             ike1_prf.bHasPrevKey = CK_TRUE;
7246             ike1_prf.hPrevKey = skeyid_d_handle;
7247             ike1_prf.keyNumber = 1;
7248             crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
7249                                 derive_template, derive_template_count,
7250                                 &skeyid_a_handle);
7251             if (crv != CKR_OK) {
7252                 fprintf(stderr, "NSC_DeriveKey(skeyid_a) failed crv=0x%x\n",
7253                         (unsigned int)crv);
7254                 goto loser;
7255             }
7256             ike1_prf.hKeygxy = gxy_handle;
7257             ike1_prf.bHasPrevKey = CK_TRUE;
7258             ike1_prf.hPrevKey = skeyid_a_handle;
7259             ike1_prf.keyNumber = 2;
7260             crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
7261                                 derive_template, derive_template_count,
7262                                 &skeyid_e_handle);
7263             if (crv != CKR_OK) {
7264                 fprintf(stderr, "NSC_DeriveKey(skeyid_e) failed crv=0x%x\n",
7265                         (unsigned int)crv);
7266                 goto loser;
7267             }
7268             fputs("SKEYID = ", ikeresp);
7269             to_hex_str(buf, skeyid_secret, keyLen);
7270             fputs(buf, ikeresp);
7271             fputc('\n', ikeresp);
7272 
7273             skeyid_d_template.ulValueLen = keyLen;
7274             crv = NSC_GetAttributeValue(session, skeyid_d_handle,
7275                                         &skeyid_d_template, 1);
7276             if (crv != CKR_OK) {
7277                 fprintf(stderr, "NSC_GetAttribute(skeyid_d) failed crv=0x%x\n",
7278                         (unsigned int)crv);
7279                 goto loser;
7280             }
7281             fputs("SKEYID_d = ", ikeresp);
7282             to_hex_str(buf, skeyid_d_secret, skeyid_d_template.ulValueLen);
7283             fputs(buf, ikeresp);
7284             fputc('\n', ikeresp);
7285 
7286             skeyid_a_template.ulValueLen = keyLen;
7287             crv = NSC_GetAttributeValue(session, skeyid_a_handle,
7288                                         &skeyid_a_template, 1);
7289             if (crv != CKR_OK) {
7290                 fprintf(stderr, "NSC_GetAttribute(skeyid_a) failed crv=0x%x\n",
7291                         (unsigned int)crv);
7292                 goto loser;
7293             }
7294             fputs("SKEYID_a = ", ikeresp);
7295             to_hex_str(buf, skeyid_a_secret, skeyid_a_template.ulValueLen);
7296             fputs(buf, ikeresp);
7297             fputc('\n', ikeresp);
7298 
7299             skeyid_e_template.ulValueLen = keyLen;
7300             crv = NSC_GetAttributeValue(session, skeyid_e_handle,
7301                                         &skeyid_e_template, 1);
7302             if (crv != CKR_OK) {
7303                 fprintf(stderr, "NSC_GetAttribute(skeyid_e) failed crv=0x%x\n",
7304                         (unsigned int)crv);
7305                 goto loser;
7306             }
7307             fputs("SKEYID_e = ", ikeresp);
7308             to_hex_str(buf, skeyid_e_secret, skeyid_e_template.ulValueLen);
7309             fputs(buf, ikeresp);
7310             fputc('\n', ikeresp);
7311 
7312             crv = NSC_CloseSession(session);
7313             continue;
7314         }
7315     }
7316 loser:
7317     NSC_Finalize(NULL);
7318     if (gxy)
7319         free(gxy);
7320     if (Ni)
7321         free(Ni);
7322     if (Nr)
7323         free(Nr);
7324     if (ikereq)
7325         fclose(ikereq);
7326 }
7327 
7328 void
ikev1_psk(char * reqfn)7329 ikev1_psk(char *reqfn)
7330 {
7331     char buf[4096]; /* holds one line from the input REQUEST file.
7332                          * needs to be large enough to hold the longest
7333                          * line "g^xy = <2048 hex digits>\n".
7334                          */
7335     unsigned char *gxy = NULL;
7336     int gxy_len;
7337     unsigned char *Ni = NULL;
7338     int Ni_len;
7339     unsigned char *Nr = NULL;
7340     int Nr_len;
7341     unsigned char CKYi[8];
7342     int CKYi_len;
7343     unsigned char CKYr[8];
7344     int CKYr_len;
7345     unsigned char *psk = NULL;
7346     int psk_len;
7347     unsigned int i, j;
7348     FILE *ikereq = NULL; /* input stream from the REQUEST file */
7349     FILE *ikeresp;       /* output stream to the RESPONSE file */
7350 
7351     CK_SLOT_ID slotList[10];
7352     CK_SLOT_ID slotID;
7353     CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
7354     CK_ULONG count;
7355     static const CK_C_INITIALIZE_ARGS pk11args = {
7356         NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
7357         (void *)"flags=readOnly,noCertDB,noModDB", NULL
7358     };
7359     static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
7360     static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
7361     static CK_BBOOL ck_true = CK_TRUE;
7362     static CK_ULONG keyLen = 1;
7363     CK_ATTRIBUTE gxy_template[] = {
7364         { CKA_VALUE, NULL, 0 }, /* must be first */
7365         { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
7366         { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
7367         { CKA_DERIVE, &ck_true, sizeof(ck_true) },
7368     };
7369     CK_ULONG gxy_template_count =
7370         sizeof(gxy_template) / sizeof(gxy_template[0]);
7371     CK_ATTRIBUTE psk_template[] = {
7372         { CKA_VALUE, NULL, 0 }, /* must be first */
7373         { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
7374         { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
7375         { CKA_DERIVE, &ck_true, sizeof(ck_true) },
7376     };
7377     CK_ULONG psk_template_count =
7378         sizeof(psk_template) / sizeof(psk_template[0]);
7379     CK_ATTRIBUTE derive_template[] = {
7380         { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
7381         { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
7382         { CKA_DERIVE, &ck_true, sizeof(ck_true) },
7383         { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) }, /* must be last */
7384     };
7385     CK_ULONG derive_template_count =
7386         sizeof(derive_template) / sizeof(derive_template[0]);
7387     CK_ATTRIBUTE skeyid_template =
7388         { CKA_VALUE, NULL, 0 };
7389     CK_ATTRIBUTE skeyid_d_template =
7390         { CKA_VALUE, NULL, 0 };
7391     CK_ATTRIBUTE skeyid_a_template =
7392         { CKA_VALUE, NULL, 0 };
7393     CK_ATTRIBUTE skeyid_e_template =
7394         { CKA_VALUE, NULL, 0 };
7395     unsigned char skeyid_secret[HASH_LENGTH_MAX];
7396     unsigned char skeyid_d_secret[HASH_LENGTH_MAX];
7397     unsigned char skeyid_a_secret[HASH_LENGTH_MAX];
7398     unsigned char skeyid_e_secret[HASH_LENGTH_MAX];
7399 
7400     CK_MECHANISM ike_mech = { CKM_NSS_IKE_PRF_DERIVE, NULL, 0 };
7401     CK_MECHANISM ike1_mech = { CKM_NSS_IKE1_PRF_DERIVE, NULL, 0 };
7402     CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf;
7403     CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf;
7404     CK_RV crv;
7405 
7406     /* set up PKCS #11 parameters */
7407     ike_prf.bDataAsKey = PR_FALSE;
7408     ike_prf.bRekey = PR_FALSE;
7409     ike_prf.hNewKey = CK_INVALID_HANDLE;
7410     CKYi_len = 8;
7411     CKYr_len = 8;
7412     ike1_prf.pCKYi = CKYi;
7413     ike1_prf.ulCKYiLen = CKYi_len;
7414     ike1_prf.pCKYr = CKYr;
7415     ike1_prf.ulCKYrLen = CKYr_len;
7416     ike_mech.pParameter = &ike_prf;
7417     ike_mech.ulParameterLen = sizeof(ike_prf);
7418     ike1_mech.pParameter = &ike1_prf;
7419     ike1_mech.ulParameterLen = sizeof(ike1_prf);
7420     skeyid_template.pValue = skeyid_secret;
7421     skeyid_template.ulValueLen = HASH_LENGTH_MAX;
7422     skeyid_d_template.pValue = skeyid_d_secret;
7423     skeyid_d_template.ulValueLen = HASH_LENGTH_MAX;
7424     skeyid_a_template.pValue = skeyid_a_secret;
7425     skeyid_a_template.ulValueLen = HASH_LENGTH_MAX;
7426     skeyid_e_template.pValue = skeyid_e_secret;
7427     skeyid_e_template.ulValueLen = HASH_LENGTH_MAX;
7428 
7429     crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
7430     if (crv != CKR_OK) {
7431         fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
7432         goto loser;
7433     }
7434     count = slotListCount;
7435     crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
7436     if (crv != CKR_OK) {
7437         fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
7438         goto loser;
7439     }
7440     if ((count > slotListCount) || count < 1) {
7441         fprintf(stderr,
7442                 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
7443                 (int)count, (int)slotListCount);
7444         goto loser;
7445     }
7446     slotID = slotList[0];
7447     ikereq = fopen(reqfn, "r");
7448     ikeresp = stdout;
7449     while (fgets(buf, sizeof buf, ikereq) != NULL) {
7450         /* a comment or blank line */
7451         if (buf[0] == '#' || buf[0] == '\n') {
7452             fputs(buf, ikeresp);
7453             continue;
7454         }
7455         /* [.....] */
7456         if (buf[0] == '[') {
7457             if (strncmp(buf, "[SHA-1]", 7) == 0) {
7458                 ike_prf.prfMechanism = CKM_SHA_1_HMAC;
7459                 ike1_prf.prfMechanism = CKM_SHA_1_HMAC;
7460             }
7461             if (strncmp(buf, "[SHA-224]", 9) == 0) {
7462                 ike_prf.prfMechanism = CKM_SHA224_HMAC;
7463                 ike1_prf.prfMechanism = CKM_SHA224_HMAC;
7464             }
7465             if (strncmp(buf, "[SHA-256]", 9) == 0) {
7466                 ike_prf.prfMechanism = CKM_SHA256_HMAC;
7467                 ike1_prf.prfMechanism = CKM_SHA256_HMAC;
7468             }
7469             if (strncmp(buf, "[SHA-384]", 9) == 0) {
7470                 ike_prf.prfMechanism = CKM_SHA384_HMAC;
7471                 ike1_prf.prfMechanism = CKM_SHA384_HMAC;
7472             }
7473             if (strncmp(buf, "[SHA-512]", 9) == 0) {
7474                 ike_prf.prfMechanism = CKM_SHA512_HMAC;
7475                 ike1_prf.prfMechanism = CKM_SHA512_HMAC;
7476             }
7477             if (strncmp(buf, "[AES-XCBC", 9) == 0) {
7478                 ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
7479                 ike1_prf.prfMechanism = CKM_AES_XCBC_MAC;
7480             }
7481             if (strncmp(buf, "[g^xy", 5) == 0) {
7482                 if (sscanf(buf, "[g^xy length = %d]",
7483                            &gxy_len) != 1) {
7484                     goto loser;
7485                 }
7486                 gxy_len = gxy_len / 8;
7487                 if (gxy)
7488                     free(gxy);
7489                 gxy = malloc(gxy_len);
7490                 gxy_template[0].pValue = gxy;
7491                 gxy_template[0].ulValueLen = gxy_len;
7492             }
7493             if (strncmp(buf, "[pre-shared-key", 15) == 0) {
7494                 if (sscanf(buf, "[pre-shared-key length = %d]",
7495                            &psk_len) != 1) {
7496                     goto loser;
7497                 }
7498                 psk_len = psk_len / 8;
7499                 if (psk)
7500                     free(psk);
7501                 psk = malloc(psk_len);
7502                 psk_template[0].pValue = psk;
7503                 psk_template[0].ulValueLen = psk_len;
7504             }
7505             if (strncmp(buf, "[Ni", 3) == 0) {
7506                 if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
7507                     goto loser;
7508                 }
7509                 Ni_len = Ni_len / 8;
7510                 if (Ni)
7511                     free(Ni);
7512                 Ni = malloc(Ni_len);
7513                 ike_prf.pNi = Ni;
7514                 ike_prf.ulNiLen = Ni_len;
7515             }
7516             if (strncmp(buf, "[Nr", 3) == 0) {
7517                 if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
7518                     goto loser;
7519                 }
7520                 Nr_len = Nr_len / 8;
7521                 if (Nr)
7522                     free(Nr);
7523                 Nr = malloc(Nr_len);
7524                 ike_prf.pNr = Nr;
7525                 ike_prf.ulNrLen = Nr_len;
7526             }
7527             fputs(buf, ikeresp);
7528             continue;
7529         }
7530         /* "COUNT = x" begins a new data set */
7531         if (strncmp(buf, "COUNT", 5) == 0) {
7532             /* zeroize the variables for the test with this data set */
7533             memset(gxy, 0, gxy_len);
7534             memset(Ni, 0, Ni_len);
7535             memset(Nr, 0, Nr_len);
7536             memset(CKYi, 0, CKYi_len);
7537             memset(CKYr, 0, CKYr_len);
7538             fputs(buf, ikeresp);
7539             continue;
7540         }
7541         /* Ni = ... */
7542         if (strncmp(buf, "Ni", 2) == 0) {
7543             i = 2;
7544             while (isspace(buf[i]) || buf[i] == '=') {
7545                 i++;
7546             }
7547             for (j = 0; j < Ni_len; i += 2, j++) {
7548                 hex_to_byteval(&buf[i], &Ni[j]);
7549             }
7550             fputs(buf, ikeresp);
7551             continue;
7552         }
7553         /* Nr = ... */
7554         if (strncmp(buf, "Nr", 2) == 0) {
7555             i = 2;
7556             while (isspace(buf[i]) || buf[i] == '=') {
7557                 i++;
7558             }
7559             for (j = 0; j < Nr_len; i += 2, j++) {
7560                 hex_to_byteval(&buf[i], &Nr[j]);
7561             }
7562             fputs(buf, ikeresp);
7563             continue;
7564         }
7565         /* CKYi = ... */
7566         if (strncmp(buf, "CKY_I", 5) == 0) {
7567             i = 5;
7568             while (isspace(buf[i]) || buf[i] == '=') {
7569                 i++;
7570             }
7571             for (j = 0; j < CKYi_len; i += 2, j++) {
7572                 hex_to_byteval(&buf[i], &CKYi[j]);
7573             }
7574             fputs(buf, ikeresp);
7575             continue;
7576         }
7577         /* CKYr = ... */
7578         if (strncmp(buf, "CKY_R", 5) == 0) {
7579             i = 5;
7580             while (isspace(buf[i]) || buf[i] == '=') {
7581                 i++;
7582             }
7583             for (j = 0; j < CKYr_len; i += 2, j++) {
7584                 hex_to_byteval(&buf[i], &CKYr[j]);
7585             }
7586             fputs(buf, ikeresp);
7587             continue;
7588         }
7589         /* g^xy = ... */
7590         if (strncmp(buf, "g^xy", 4) == 0) {
7591             i = 4;
7592             while (isspace(buf[i]) || buf[i] == '=') {
7593                 i++;
7594             }
7595             for (j = 0; j < gxy_len; i += 2, j++) {
7596                 hex_to_byteval(&buf[i], &gxy[j]);
7597             }
7598             fputs(buf, ikeresp);
7599             continue;
7600         }
7601         /* pre-shared-key = ... */
7602         if (strncmp(buf, "pre-shared-key", 14) == 0) {
7603             CK_SESSION_HANDLE session;
7604             CK_OBJECT_HANDLE gxy_handle;
7605             CK_OBJECT_HANDLE psk_handle;
7606             CK_OBJECT_HANDLE skeyid_handle;
7607             CK_OBJECT_HANDLE skeyid_d_handle;
7608             CK_OBJECT_HANDLE skeyid_a_handle;
7609             CK_OBJECT_HANDLE skeyid_e_handle;
7610             i = 14;
7611             while (isspace(buf[i]) || buf[i] == '=') {
7612                 i++;
7613             }
7614             for (j = 0; j < psk_len; i += 2, j++) {
7615                 hex_to_byteval(&buf[i], &psk[j]);
7616             }
7617             fputs(buf, ikeresp);
7618             crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
7619             if (crv != CKR_OK) {
7620                 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
7621                         (unsigned int)crv);
7622                 goto loser;
7623             }
7624             crv = NSC_CreateObject(session, psk_template,
7625                                    psk_template_count, &psk_handle);
7626             if (crv != CKR_OK) {
7627                 fprintf(stderr, "NSC_CreateObject(psk) failed crv=0x%x\n",
7628                         (unsigned int)crv);
7629                 goto loser;
7630             }
7631             crv = NSC_CreateObject(session, gxy_template,
7632                                    gxy_template_count, &gxy_handle);
7633             if (crv != CKR_OK) {
7634                 fprintf(stderr, "NSC_CreateObject(gxy) failed crv=0x%x\n",
7635                         (unsigned int)crv);
7636                 goto loser;
7637             }
7638             /* get the skeyid key */
7639             crv = NSC_DeriveKey(session, &ike_mech, psk_handle,
7640                                 derive_template, derive_template_count - 1,
7641                                 &skeyid_handle);
7642             if (crv != CKR_OK) {
7643                 fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
7644                         (unsigned int)crv);
7645                 goto loser;
7646             }
7647             skeyid_template.ulValueLen = HASH_LENGTH_MAX;
7648             crv = NSC_GetAttributeValue(session, skeyid_handle,
7649                                         &skeyid_template, 1);
7650             if (crv != CKR_OK) {
7651                 fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
7652                         (unsigned int)crv);
7653                 goto loser;
7654             }
7655             /* use the length of the skeyid to set the target length of all the
7656              * other keys */
7657             keyLen = skeyid_template.ulValueLen;
7658             ike1_prf.hKeygxy = gxy_handle;
7659             ike1_prf.bHasPrevKey = PR_FALSE;
7660             ike1_prf.keyNumber = 0;
7661             crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
7662                                 derive_template, derive_template_count,
7663                                 &skeyid_d_handle);
7664             if (crv != CKR_OK) {
7665                 fprintf(stderr, "NSC_DeriveKey(skeyid_d) failed crv=0x%x\n",
7666                         (unsigned int)crv);
7667                 goto loser;
7668             }
7669 
7670             ike1_prf.hKeygxy = gxy_handle;
7671             ike1_prf.bHasPrevKey = CK_TRUE;
7672             ike1_prf.hPrevKey = skeyid_d_handle;
7673             ike1_prf.keyNumber = 1;
7674             crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
7675                                 derive_template, derive_template_count,
7676                                 &skeyid_a_handle);
7677             if (crv != CKR_OK) {
7678                 fprintf(stderr, "NSC_DeriveKey(skeyid_a) failed crv=0x%x\n",
7679                         (unsigned int)crv);
7680                 goto loser;
7681             }
7682             ike1_prf.hKeygxy = gxy_handle;
7683             ike1_prf.bHasPrevKey = CK_TRUE;
7684             ike1_prf.hPrevKey = skeyid_a_handle;
7685             ike1_prf.keyNumber = 2;
7686             crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
7687                                 derive_template, derive_template_count,
7688                                 &skeyid_e_handle);
7689             if (crv != CKR_OK) {
7690                 fprintf(stderr, "NSC_DeriveKey(skeyid_e) failed crv=0x%x\n",
7691                         (unsigned int)crv);
7692                 goto loser;
7693             }
7694             fputs("SKEYID = ", ikeresp);
7695             to_hex_str(buf, skeyid_secret, keyLen);
7696             fputs(buf, ikeresp);
7697             fputc('\n', ikeresp);
7698 
7699             skeyid_d_template.ulValueLen = keyLen;
7700             crv = NSC_GetAttributeValue(session, skeyid_d_handle,
7701                                         &skeyid_d_template, 1);
7702             if (crv != CKR_OK) {
7703                 fprintf(stderr, "NSC_GetAttribute(skeyid_d) failed crv=0x%x\n",
7704                         (unsigned int)crv);
7705                 goto loser;
7706             }
7707             fputs("SKEYID_d = ", ikeresp);
7708             to_hex_str(buf, skeyid_d_secret, skeyid_d_template.ulValueLen);
7709             fputs(buf, ikeresp);
7710             fputc('\n', ikeresp);
7711 
7712             skeyid_a_template.ulValueLen = keyLen;
7713             crv = NSC_GetAttributeValue(session, skeyid_a_handle,
7714                                         &skeyid_a_template, 1);
7715             if (crv != CKR_OK) {
7716                 fprintf(stderr, "NSC_GetAttribute(skeyid_a) failed crv=0x%x\n",
7717                         (unsigned int)crv);
7718                 goto loser;
7719             }
7720             fputs("SKEYID_a = ", ikeresp);
7721             to_hex_str(buf, skeyid_a_secret, skeyid_a_template.ulValueLen);
7722             fputs(buf, ikeresp);
7723             fputc('\n', ikeresp);
7724 
7725             skeyid_e_template.ulValueLen = keyLen;
7726             crv = NSC_GetAttributeValue(session, skeyid_e_handle,
7727                                         &skeyid_e_template, 1);
7728             if (crv != CKR_OK) {
7729                 fprintf(stderr, "NSC_GetAttribute(skeyid_e) failed crv=0x%x\n",
7730                         (unsigned int)crv);
7731                 goto loser;
7732             }
7733             fputs("SKEYID_e = ", ikeresp);
7734             to_hex_str(buf, skeyid_e_secret, skeyid_e_template.ulValueLen);
7735             fputs(buf, ikeresp);
7736             fputc('\n', ikeresp);
7737 
7738             crv = NSC_CloseSession(session);
7739             continue;
7740         }
7741     }
7742 loser:
7743     NSC_Finalize(NULL);
7744     if (psk)
7745         free(psk);
7746     if (gxy)
7747         free(gxy);
7748     if (Ni)
7749         free(Ni);
7750     if (Nr)
7751         free(Nr);
7752     if (ikereq)
7753         fclose(ikereq);
7754 }
7755 
7756 void
ikev2(char * reqfn)7757 ikev2(char *reqfn)
7758 {
7759     char buf[4096]; /* holds one line from the input REQUEST file.
7760                          * needs to be large enough to hold the longest
7761                          * line "g^xy = <2048 hex digits>\n".
7762                          */
7763     unsigned char *gir = NULL;
7764     unsigned char *gir_new = NULL;
7765     int gir_len;
7766     unsigned char *Ni = NULL;
7767     int Ni_len;
7768     unsigned char *Nr = NULL;
7769     int Nr_len;
7770     unsigned char *SPIi = NULL;
7771     int SPIi_len = 8;
7772     unsigned char *SPIr = NULL;
7773     int SPIr_len = 8;
7774     unsigned char *DKM = NULL;
7775     int DKM_len;
7776     unsigned char *DKM_child = NULL;
7777     int DKM_child_len;
7778     unsigned char *seed_data = NULL;
7779     int seed_data_len = 0;
7780     unsigned int i, j;
7781     FILE *ikereq = NULL; /* input stream from the REQUEST file */
7782     FILE *ikeresp;       /* output stream to the RESPONSE file */
7783 
7784     CK_SLOT_ID slotList[10];
7785     CK_SLOT_ID slotID;
7786     CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
7787     CK_ULONG count;
7788     static const CK_C_INITIALIZE_ARGS pk11args = {
7789         NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
7790         (void *)"flags=readOnly,noCertDB,noModDB", NULL
7791     };
7792     static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
7793     static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
7794     static CK_BBOOL ck_true = CK_TRUE;
7795     static CK_ULONG keyLen = 1;
7796     CK_ATTRIBUTE gir_template[] = {
7797         { CKA_VALUE, NULL, 0 },
7798         { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
7799         { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
7800         { CKA_DERIVE, &ck_true, sizeof(ck_true) },
7801     };
7802     CK_ULONG gir_template_count =
7803         sizeof(gir_template) / sizeof(gir_template[0]);
7804     CK_ATTRIBUTE gir_new_template[] = {
7805         { CKA_VALUE, NULL, 0 },
7806         { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
7807         { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
7808         { CKA_DERIVE, &ck_true, sizeof(ck_true) },
7809     };
7810     CK_ULONG gir_new_template_count =
7811         sizeof(gir_new_template) / sizeof(gir_new_template[0]);
7812     CK_ATTRIBUTE derive_template[] = {
7813         { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
7814         { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
7815         { CKA_DERIVE, &ck_true, sizeof(ck_true) },
7816         { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) },
7817     };
7818     CK_ULONG derive_template_count =
7819         sizeof(derive_template) / sizeof(derive_template[0]);
7820     CK_ATTRIBUTE skeyseed_template =
7821         { CKA_VALUE, NULL, 0 };
7822     CK_ATTRIBUTE dkm_template =
7823         { CKA_VALUE, NULL, 0 };
7824     CK_ATTRIBUTE dkm_child_template =
7825         { CKA_VALUE, NULL, 0 };
7826     unsigned char skeyseed_secret[HASH_LENGTH_MAX];
7827 
7828     CK_MECHANISM ike_mech = { CKM_NSS_IKE_PRF_DERIVE, NULL, 0 };
7829     CK_MECHANISM ike2_mech = { CKM_NSS_IKE_PRF_PLUS_DERIVE, NULL, 0 };
7830     CK_MECHANISM subset_mech = { CKM_EXTRACT_KEY_FROM_KEY, NULL, 0 };
7831     CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf;
7832     CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS ike2_prf;
7833     CK_EXTRACT_PARAMS subset_params;
7834     CK_RV crv;
7835 
7836     /* set up PKCS #11 parameters */
7837     ike_mech.pParameter = &ike_prf;
7838     ike_mech.ulParameterLen = sizeof(ike_prf);
7839     ike2_mech.pParameter = &ike2_prf;
7840     ike2_mech.ulParameterLen = sizeof(ike2_prf);
7841     subset_mech.pParameter = &subset_params;
7842     subset_mech.ulParameterLen = sizeof(subset_params);
7843     subset_params = 0;
7844     skeyseed_template.pValue = skeyseed_secret;
7845     skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
7846 
7847     crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
7848     if (crv != CKR_OK) {
7849         fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
7850         goto loser;
7851     }
7852     count = slotListCount;
7853     crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
7854     if (crv != CKR_OK) {
7855         fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
7856         goto loser;
7857     }
7858     if ((count > slotListCount) || count < 1) {
7859         fprintf(stderr,
7860                 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
7861                 (int)count, (int)slotListCount);
7862         goto loser;
7863     }
7864     slotID = slotList[0];
7865     ikereq = fopen(reqfn, "r");
7866     ikeresp = stdout;
7867     while (fgets(buf, sizeof buf, ikereq) != NULL) {
7868         /* a comment or blank line */
7869         if (buf[0] == '#' || buf[0] == '\n') {
7870             fputs(buf, ikeresp);
7871             continue;
7872         }
7873         /* [.....] */
7874         if (buf[0] == '[') {
7875             if (strncmp(buf, "[SHA-1]", 7) == 0) {
7876                 ike_prf.prfMechanism = CKM_SHA_1_HMAC;
7877                 ike2_prf.prfMechanism = CKM_SHA_1_HMAC;
7878             }
7879             if (strncmp(buf, "[SHA-224]", 9) == 0) {
7880                 ike_prf.prfMechanism = CKM_SHA224_HMAC;
7881                 ike2_prf.prfMechanism = CKM_SHA224_HMAC;
7882             }
7883             if (strncmp(buf, "[SHA-256]", 9) == 0) {
7884                 ike_prf.prfMechanism = CKM_SHA256_HMAC;
7885                 ike2_prf.prfMechanism = CKM_SHA256_HMAC;
7886             }
7887             if (strncmp(buf, "[SHA-384]", 9) == 0) {
7888                 ike_prf.prfMechanism = CKM_SHA384_HMAC;
7889                 ike2_prf.prfMechanism = CKM_SHA384_HMAC;
7890             }
7891             if (strncmp(buf, "[SHA-512]", 9) == 0) {
7892                 ike_prf.prfMechanism = CKM_SHA512_HMAC;
7893                 ike2_prf.prfMechanism = CKM_SHA512_HMAC;
7894             }
7895             if (strncmp(buf, "[AES-XCBC", 9) == 0) {
7896                 ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
7897                 ike2_prf.prfMechanism = CKM_AES_XCBC_MAC;
7898             }
7899             if (strncmp(buf, "[g^ir", 5) == 0) {
7900                 if (sscanf(buf, "[g^ir length = %d]",
7901                            &gir_len) != 1) {
7902                     goto loser;
7903                 }
7904                 gir_len = gir_len / 8;
7905                 if (gir)
7906                     free(gir);
7907                 if (gir_new)
7908                     free(gir_new);
7909                 gir = malloc(gir_len);
7910                 gir_new = malloc(gir_len);
7911                 gir_template[0].pValue = gir;
7912                 gir_template[0].ulValueLen = gir_len;
7913                 gir_new_template[0].pValue = gir_new;
7914                 gir_new_template[0].ulValueLen = gir_len;
7915             }
7916             if (strncmp(buf, "[Ni", 3) == 0) {
7917                 if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
7918                     goto loser;
7919                 }
7920                 Ni_len = Ni_len / 8;
7921             }
7922             if (strncmp(buf, "[Nr", 3) == 0) {
7923                 if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
7924                     goto loser;
7925                 }
7926                 Nr_len = Nr_len / 8;
7927             }
7928             if (strncmp(buf, "[DKM", 4) == 0) {
7929                 if (sscanf(buf, "[DKM length = %d]",
7930                            &DKM_len) != 1) {
7931                     goto loser;
7932                 }
7933                 DKM_len = DKM_len / 8;
7934                 if (DKM)
7935                     free(DKM);
7936                 DKM = malloc(DKM_len);
7937                 dkm_template.pValue = DKM;
7938                 dkm_template.ulValueLen = DKM_len;
7939             }
7940             if (strncmp(buf, "[Child SA DKM", 13) == 0) {
7941                 if (sscanf(buf, "[Child SA DKM length = %d]",
7942                            &DKM_child_len) != 1) {
7943                     goto loser;
7944                 }
7945                 DKM_child_len = DKM_child_len / 8;
7946                 if (DKM_child)
7947                     free(DKM_child);
7948                 DKM_child = malloc(DKM_child_len);
7949                 dkm_child_template.pValue = DKM_child;
7950                 dkm_child_template.ulValueLen = DKM_child_len;
7951             }
7952             fputs(buf, ikeresp);
7953             continue;
7954         }
7955         /* "COUNT = x" begins a new data set */
7956         if (strncmp(buf, "COUNT", 5) == 0) {
7957             /* zeroize the variables for the test with this data set */
7958             int new_seed_len = Ni_len + Nr_len + SPIi_len + SPIr_len;
7959             if (seed_data_len != new_seed_len) {
7960                 if (seed_data)
7961                     free(seed_data);
7962                 seed_data_len = new_seed_len;
7963                 seed_data = malloc(seed_data_len);
7964                 Ni = seed_data;
7965                 Nr = &seed_data[Ni_len];
7966                 SPIi = &seed_data[Ni_len + Nr_len];
7967                 SPIr = &seed_data[new_seed_len - SPIr_len];
7968                 ike_prf.pNi = Ni;
7969                 ike_prf.ulNiLen = Ni_len;
7970                 ike_prf.pNr = Nr;
7971                 ike_prf.ulNrLen = Nr_len;
7972                 ike2_prf.pSeedData = seed_data;
7973             }
7974             memset(gir, 0, gir_len);
7975             memset(gir_new, 0, gir_len);
7976             memset(seed_data, 0, seed_data_len);
7977             fputs(buf, ikeresp);
7978             continue;
7979         }
7980         /* Ni = ... */
7981         if (strncmp(buf, "Ni", 2) == 0) {
7982             i = 2;
7983             while (isspace(buf[i]) || buf[i] == '=') {
7984                 i++;
7985             }
7986             for (j = 0; j < Ni_len; i += 2, j++) {
7987                 hex_to_byteval(&buf[i], &Ni[j]);
7988             }
7989             fputs(buf, ikeresp);
7990             continue;
7991         }
7992         /* Nr = ... */
7993         if (strncmp(buf, "Nr", 2) == 0) {
7994             i = 2;
7995             while (isspace(buf[i]) || buf[i] == '=') {
7996                 i++;
7997             }
7998             for (j = 0; j < Nr_len; i += 2, j++) {
7999                 hex_to_byteval(&buf[i], &Nr[j]);
8000             }
8001             fputs(buf, ikeresp);
8002             continue;
8003         }
8004         /* g^ir (new) = ... */
8005         if (strncmp(buf, "g^ir (new)", 10) == 0) {
8006             i = 10;
8007             while (isspace(buf[i]) || buf[i] == '=') {
8008                 i++;
8009             }
8010             for (j = 0; j < gir_len; i += 2, j++) {
8011                 hex_to_byteval(&buf[i], &gir_new[j]);
8012             }
8013             fputs(buf, ikeresp);
8014             continue;
8015         }
8016         /* g^ir = ... */
8017         if (strncmp(buf, "g^ir", 4) == 0) {
8018             i = 4;
8019             while (isspace(buf[i]) || buf[i] == '=') {
8020                 i++;
8021             }
8022             for (j = 0; j < gir_len; i += 2, j++) {
8023                 hex_to_byteval(&buf[i], &gir[j]);
8024             }
8025             fputs(buf, ikeresp);
8026             continue;
8027         }
8028         /* SPIi = ... */
8029         if (strncmp(buf, "SPIi", 4) == 0) {
8030             i = 4;
8031             while (isspace(buf[i]) || buf[i] == '=') {
8032                 i++;
8033             }
8034             for (j = 0; j < SPIi_len; i += 2, j++) {
8035                 hex_to_byteval(&buf[i], &SPIi[j]);
8036             }
8037             fputs(buf, ikeresp);
8038             continue;
8039         }
8040         /* SPIr = ... */
8041         if (strncmp(buf, "SPIr", 4) == 0) {
8042             CK_SESSION_HANDLE session;
8043             CK_OBJECT_HANDLE gir_handle;
8044             CK_OBJECT_HANDLE gir_new_handle;
8045             CK_OBJECT_HANDLE skeyseed_handle;
8046             CK_OBJECT_HANDLE sk_d_handle;
8047             CK_OBJECT_HANDLE skeyseed_new_handle;
8048             CK_OBJECT_HANDLE dkm_handle;
8049             CK_OBJECT_HANDLE dkm_child_handle;
8050             i = 4;
8051             while (isspace(buf[i]) || buf[i] == '=') {
8052                 i++;
8053             }
8054             for (j = 0; j < SPIr_len; i += 2, j++) {
8055                 hex_to_byteval(&buf[i], &SPIr[j]);
8056             }
8057             fputs(buf, ikeresp);
8058             crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
8059             if (crv != CKR_OK) {
8060                 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
8061                         (unsigned int)crv);
8062                 goto loser;
8063             }
8064             crv = NSC_CreateObject(session, gir_template,
8065                                    gir_template_count, &gir_handle);
8066             if (crv != CKR_OK) {
8067                 fprintf(stderr, "NSC_CreateObject (g^ir) failed crv=0x%x\n",
8068                         (unsigned int)crv);
8069                 goto loser;
8070             }
8071             crv = NSC_CreateObject(session, gir_new_template,
8072                                    gir_new_template_count, &gir_new_handle);
8073             if (crv != CKR_OK) {
8074                 fprintf(stderr, "NSC_CreateObject (g^ir new) failed crv=0x%x\n",
8075                         (unsigned int)crv);
8076                 goto loser;
8077             }
8078             /* get the SKEYSEED key */
8079             ike_prf.bDataAsKey = CK_TRUE;
8080             ike_prf.bRekey = CK_FALSE;
8081             ike_prf.hNewKey = CK_INVALID_HANDLE;
8082             crv = NSC_DeriveKey(session, &ike_mech, gir_handle,
8083                                 derive_template, derive_template_count - 1,
8084                                 &skeyseed_handle);
8085             if (crv != CKR_OK) {
8086                 fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
8087                         (unsigned int)crv);
8088                 goto loser;
8089             }
8090             skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
8091             crv = NSC_GetAttributeValue(session, skeyseed_handle,
8092                                         &skeyseed_template, 1);
8093             if (crv != CKR_OK) {
8094                 fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
8095                         (unsigned int)crv);
8096                 goto loser;
8097             }
8098             fputs("SKEYSEED = ", ikeresp);
8099             to_hex_str(buf, skeyseed_secret, skeyseed_template.ulValueLen);
8100             fputs(buf, ikeresp);
8101             fputc('\n', ikeresp);
8102 
8103             /* get DKM */
8104             keyLen = DKM_len;
8105             ike2_prf.bHasSeedKey = CK_FALSE;
8106             ike2_prf.hSeedKey = CK_INVALID_HANDLE;
8107             ike2_prf.ulSeedDataLen = seed_data_len;
8108             crv = NSC_DeriveKey(session, &ike2_mech, skeyseed_handle,
8109                                 derive_template, derive_template_count,
8110                                 &dkm_handle);
8111             if (crv != CKR_OK) {
8112                 fprintf(stderr, "NSC_DeriveKey(DKM) failed crv=0x%x\n",
8113                         (unsigned int)crv);
8114                 goto loser;
8115             }
8116             crv = NSC_GetAttributeValue(session, dkm_handle,
8117                                         &dkm_template, 1);
8118             if (crv != CKR_OK) {
8119                 fprintf(stderr, "NSC_GetAttribute(DKM) failed crv=0x%x\n",
8120                         (unsigned int)crv);
8121                 goto loser;
8122             }
8123             fputs("DKM = ", ikeresp);
8124             to_hex_str(buf, DKM, DKM_len);
8125             fputs(buf, ikeresp);
8126             fputc('\n', ikeresp);
8127 
8128             /* get the sk_d from the DKM */
8129             keyLen = skeyseed_template.ulValueLen;
8130             crv = NSC_DeriveKey(session, &subset_mech, dkm_handle,
8131                                 derive_template, derive_template_count,
8132                                 &sk_d_handle);
8133             if (crv != CKR_OK) {
8134                 fprintf(stderr, "NSC_DeriveKey(sk_d) failed crv=0x%x\n",
8135                         (unsigned int)crv);
8136                 goto loser;
8137             }
8138 
8139             /* get DKM child */
8140             keyLen = DKM_child_len;
8141             ike2_prf.bHasSeedKey = CK_FALSE;
8142             ike2_prf.hSeedKey = CK_INVALID_HANDLE;
8143             ike2_prf.ulSeedDataLen = Ni_len + Nr_len;
8144             crv = NSC_DeriveKey(session, &ike2_mech, sk_d_handle,
8145                                 derive_template, derive_template_count,
8146                                 &dkm_child_handle);
8147             if (crv != CKR_OK) {
8148                 fprintf(stderr, "NSC_DeriveKey(DKM Child SA) failed crv=0x%x\n",
8149                         (unsigned int)crv);
8150                 goto loser;
8151             }
8152             crv = NSC_GetAttributeValue(session, dkm_child_handle,
8153                                         &dkm_child_template, 1);
8154             if (crv != CKR_OK) {
8155                 fprintf(stderr, "NSC_GetAttribute(DKM Child SA) failed crv=0x%x\n",
8156                         (unsigned int)crv);
8157                 goto loser;
8158             }
8159             fputs("DKM(Child SA) = ", ikeresp);
8160             to_hex_str(buf, DKM_child, DKM_child_len);
8161             fputs(buf, ikeresp);
8162             fputc('\n', ikeresp);
8163 
8164             /* get DKM child D-H*/
8165             keyLen = DKM_child_len;
8166             ike2_prf.bHasSeedKey = CK_TRUE;
8167             ike2_prf.hSeedKey = gir_new_handle;
8168             ike2_prf.ulSeedDataLen = Ni_len + Nr_len;
8169             crv = NSC_DeriveKey(session, &ike2_mech, sk_d_handle,
8170                                 derive_template, derive_template_count,
8171                                 &dkm_child_handle);
8172             if (crv != CKR_OK) {
8173                 fprintf(stderr, "NSC_DeriveKey(DKM Child SA D-H) failed crv=0x%x\n",
8174                         (unsigned int)crv);
8175                 goto loser;
8176             }
8177             crv = NSC_GetAttributeValue(session, dkm_child_handle,
8178                                         &dkm_child_template, 1);
8179             if (crv != CKR_OK) {
8180                 fprintf(stderr, "NSC_GetAttribute(DKM Child SA D-H) failed crv=0x%x\n",
8181                         (unsigned int)crv);
8182                 goto loser;
8183             }
8184             fputs("DKM(Child SA D-H) = ", ikeresp);
8185             to_hex_str(buf, DKM_child, DKM_child_len);
8186             fputs(buf, ikeresp);
8187             fputc('\n', ikeresp);
8188 
8189             /* get SKEYSEED(rekey) */
8190             ike_prf.bDataAsKey = CK_FALSE;
8191             ike_prf.bRekey = CK_TRUE;
8192             ike_prf.hNewKey = gir_new_handle;
8193             crv = NSC_DeriveKey(session, &ike_mech, sk_d_handle,
8194                                 derive_template, derive_template_count - 1,
8195                                 &skeyseed_new_handle);
8196             if (crv != CKR_OK) {
8197                 fprintf(stderr, "NSC_DeriveKey(skeyid rekey) failed crv=0x%x\n",
8198                         (unsigned int)crv);
8199                 goto loser;
8200             }
8201             skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
8202             crv = NSC_GetAttributeValue(session, skeyseed_new_handle,
8203                                         &skeyseed_template, 1);
8204             if (crv != CKR_OK) {
8205                 fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
8206                         (unsigned int)crv);
8207                 goto loser;
8208             }
8209             fputs("SKEYSEED(rekey) = ", ikeresp);
8210             to_hex_str(buf, skeyseed_secret, skeyseed_template.ulValueLen);
8211             fputs(buf, ikeresp);
8212             fputc('\n', ikeresp);
8213 
8214             crv = NSC_CloseSession(session);
8215             continue;
8216         }
8217     }
8218 loser:
8219     NSC_Finalize(NULL);
8220     if (gir)
8221         free(gir);
8222     if (gir_new)
8223         free(gir_new);
8224     if (seed_data)
8225         free(seed_data);
8226     if (DKM)
8227         free(DKM);
8228     if (DKM_child)
8229         free(DKM_child);
8230     if (ikereq)
8231         fclose(ikereq);
8232 }
8233 
8234 void
kbkdf(char * path)8235 kbkdf(char *path)
8236 {
8237     /* == Parser data == */
8238     char buf[610]; /* holds one line from the input REQUEST file. Needs to
8239                     * be large enough to hold the longest line:
8240                     * "KO = <600 hex digits>\n". */
8241     CK_ULONG L;
8242     unsigned char KI[64];
8243     unsigned int KI_len = 64;
8244     unsigned char KO[300];
8245     unsigned int KO_len = 300;
8246     /* This is used only with feedback mode. */
8247     unsigned char IV[64];
8248     unsigned int IV_len = 64;
8249     /* These are only used in counter mode with counter location as
8250      * MIDDLE_FIXED. */
8251     unsigned char BeforeFixedInputData[50];
8252     unsigned int BeforeFixedInputData_len = 50;
8253     unsigned char AfterFixedInputData[10];
8254     unsigned int AfterFixedInputData_len = 10;
8255     /* These are used with every KDF type. */
8256     unsigned char FixedInputData[60];
8257     unsigned int FixedInputData_len = 60;
8258 
8259     /* Counter locations:
8260      *
8261      * 0: not used
8262      * 1: beginning
8263      * 2: middle
8264      * 3: end */
8265     int ctr_location = 0;
8266     CK_ULONG counter_bitlen = 0;
8267 
8268     size_t buf_offset;
8269     size_t offset;
8270 
8271     FILE *kbkdf_req = NULL;
8272     FILE *kbkdf_resp = NULL;
8273 
8274     /* == PKCS#11 data == */
8275     CK_RV crv;
8276 
8277     CK_SLOT_ID slotList[10];
8278     CK_SLOT_ID slotID;
8279     CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
8280     CK_ULONG slotCount = 0;
8281 
8282     CK_MECHANISM kdf = { 0 };
8283 
8284     CK_MECHANISM_TYPE prf_mech = 0;
8285     CK_BBOOL ck_true = CK_TRUE;
8286 
8287     /* We never need more than 3 data parameters. */
8288     CK_PRF_DATA_PARAM dataParams[3];
8289     CK_ULONG dataParams_len = 3;
8290 
8291     CK_SP800_108_COUNTER_FORMAT iterator = { CK_FALSE, 0 };
8292 
8293     CK_SP800_108_KDF_PARAMS kdfParams = { 0 };
8294     CK_SP800_108_FEEDBACK_KDF_PARAMS feedbackParams = { 0 };
8295 
8296     CK_OBJECT_CLASS ck_secret_key = CKO_SECRET_KEY;
8297     CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
8298 
8299     CK_ATTRIBUTE prf_template[] = {
8300         { CKA_VALUE, &KI, sizeof(KI) },
8301         { CKA_CLASS, &ck_secret_key, sizeof(ck_secret_key) },
8302         { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
8303         { CKA_DERIVE, &ck_true, sizeof(ck_true) }
8304     };
8305     CK_ULONG prf_template_count = sizeof(prf_template) / sizeof(prf_template[0]);
8306 
8307     CK_ATTRIBUTE derive_template[] = {
8308         { CKA_CLASS, &ck_secret_key, sizeof(ck_secret_key) },
8309         { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
8310         { CKA_DERIVE, &ck_true, sizeof(ck_true) },
8311         { CKA_VALUE_LEN, &L, sizeof(L) }
8312     };
8313     CK_ULONG derive_template_count = sizeof(derive_template) / sizeof(derive_template[0]);
8314 
8315     CK_ATTRIBUTE output_key = { CKA_VALUE, KO, KO_len };
8316 
8317     const CK_C_INITIALIZE_ARGS pk11args = {
8318         NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
8319         (void *)"flags=readOnly,noCertDB,noModDB", NULL
8320     };
8321 
8322     /* == Start up PKCS#11 == */
8323     crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
8324     if (crv != CKR_OK) {
8325         fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
8326         goto done;
8327     }
8328 
8329     slotCount = slotListCount;
8330     crv = NSC_GetSlotList(PR_TRUE, slotList, &slotCount);
8331     if (crv != CKR_OK) {
8332         fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
8333         goto done;
8334     }
8335     if ((slotCount > slotListCount) || slotCount < 1) {
8336         fprintf(stderr,
8337                 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
8338                 (int)slotCount, (int)slotListCount);
8339         goto done;
8340     }
8341     slotID = slotList[0];
8342 
8343     /* == Start parsing the file == */
8344     kbkdf_req = fopen(path, "r");
8345     kbkdf_resp = stdout;
8346 
8347     while (fgets(buf, sizeof buf, kbkdf_req) != NULL) {
8348         /* If we have a comment, check if it tells us the type of KDF to use.
8349          * This differs per-file, so we have to parse it. */
8350         if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
8351             if (strncmp(buf, "# KDF Mode Supported: Counter Mode", 34) == 0) {
8352                 kdf.mechanism = CKM_SP800_108_COUNTER_KDF;
8353             }
8354             if (strncmp(buf, "# KDF Mode Supported: Feedback Mode", 35) == 0) {
8355                 kdf.mechanism = CKM_SP800_108_FEEDBACK_KDF;
8356             }
8357             if (strncmp(buf, "# KDF Mode Supported: DblPipeline Mode", 38) == 0) {
8358                 kdf.mechanism = CKM_SP800_108_DOUBLE_PIPELINE_KDF;
8359             }
8360 
8361             fputs(buf, kbkdf_resp);
8362             continue;
8363         }
8364 
8365         /* [....] - context directive */
8366         if (buf[0] == '[') {
8367             /* PRF begins each new section. */
8368             if (strncmp(buf, "[PRF=CMAC_AES128]", 17) == 0) {
8369                 prf_mech = CKM_AES_CMAC;
8370                 KI_len = 16;
8371             } else if (strncmp(buf, "[PRF=CMAC_AES192]", 17) == 0) {
8372                 prf_mech = CKM_AES_CMAC;
8373                 KI_len = 24;
8374             } else if (strncmp(buf, "[PRF=CMAC_AES256]", 17) == 0) {
8375                 prf_mech = CKM_AES_CMAC;
8376                 KI_len = 32;
8377             } else if (strncmp(buf, "[PRF=HMAC_SHA1]", 15) == 0) {
8378                 prf_mech = CKM_SHA_1_HMAC;
8379                 KI_len = 20;
8380             } else if (strncmp(buf, "[PRF=HMAC_SHA224]", 17) == 0) {
8381                 prf_mech = CKM_SHA224_HMAC;
8382                 KI_len = 28;
8383             } else if (strncmp(buf, "[PRF=HMAC_SHA256]", 17) == 0) {
8384                 prf_mech = CKM_SHA256_HMAC;
8385                 KI_len = 32;
8386             } else if (strncmp(buf, "[PRF=HMAC_SHA384]", 17) == 0) {
8387                 prf_mech = CKM_SHA384_HMAC;
8388                 KI_len = 48;
8389             } else if (strncmp(buf, "[PRF=HMAC_SHA512]", 17) == 0) {
8390                 prf_mech = CKM_SHA512_HMAC;
8391                 KI_len = 64;
8392             } else if (strncmp(buf, "[PRF=", 5) == 0) {
8393                 fprintf(stderr, "Invalid or unsupported PRF mechanism: %s\n", buf);
8394                 goto done;
8395             }
8396 
8397             /* Then comes counter, if present. */
8398             if (strncmp(buf, "[CTRLOCATION=BEFORE_FIXED]", 26) == 0 ||
8399                 strncmp(buf, "[CTRLOCATION=BEFORE_ITER]", 24) == 0) {
8400                 ctr_location = 1;
8401             }
8402             if (strncmp(buf, "[CTRLOCATION=MIDDLE_FIXED]", 26) == 0 ||
8403                 strncmp(buf, "[CTRLOCATION=AFTER_ITER]", 24) == 0) {
8404                 ctr_location = 2;
8405             }
8406             if (strncmp(buf, "[CTRLOCATION=AFTER_FIXED]", 25) == 0) {
8407                 ctr_location = 3;
8408             }
8409 
8410             /* If counter is present, then we need to know its size. */
8411             if (strncmp(buf, "[RLEN=", 6) == 0) {
8412                 if (sscanf(buf, "[RLEN=%lu_BITS]", &counter_bitlen) != 1) {
8413                     goto done;
8414                 }
8415             }
8416 
8417             fputs(buf, kbkdf_resp);
8418             continue;
8419         }
8420 
8421         /* Each test contains a counter, an output length L, an input key KI,
8422          * maybe an initialization vector IV, one of a couple of fixed data
8423          * buffers, and finally the output key KO. */
8424 
8425         /* First comes COUNT. */
8426         if (strncmp(buf, "COUNT=", 6) == 0) {
8427             /* Clear all out data fields on each test. */
8428             memset(KI, 0, sizeof KI);
8429             memset(KO, 0, sizeof KO);
8430             memset(IV, 0, sizeof IV);
8431             memset(BeforeFixedInputData, 0, sizeof BeforeFixedInputData);
8432             memset(AfterFixedInputData, 0, sizeof AfterFixedInputData);
8433             memset(FixedInputData, 0, sizeof FixedInputData);
8434 
8435             /* Then reset lengths except KI: it was determined by PRF
8436              * selection above. */
8437             KO_len = 0;
8438             IV_len = 0;
8439             BeforeFixedInputData_len = 0;
8440             AfterFixedInputData_len = 0;
8441             FixedInputData_len = 0;
8442 
8443             fputs(buf, kbkdf_resp);
8444             continue;
8445         }
8446 
8447         /* Then comes L. */
8448         if (strncmp(buf, "L = ", 4) == 0) {
8449             if (sscanf(buf, "L = %lu", &L) != 1) {
8450                 goto done;
8451             }
8452 
8453             if ((L % 8) != 0) {
8454                 fprintf(stderr, "Assumption that L was length in bits incorrect: %lu - %s", L, buf);
8455                 fprintf(stderr, "Note that NSS only supports byte-aligned outputs and not bit-aligned outputs.\n");
8456                 goto done;
8457             }
8458 
8459             L = L / 8;
8460 
8461             fputs(buf, kbkdf_resp);
8462             continue;
8463         }
8464 
8465         /* Then comes KI. */
8466         if (strncmp(buf, "KI = ", 5) == 0) {
8467             buf_offset = 5;
8468 
8469             for (offset = 0; offset < KI_len; offset++, buf_offset += 2) {
8470                 hex_to_byteval(buf + buf_offset, KI + offset);
8471             }
8472 
8473             fputs(buf, kbkdf_resp);
8474             continue;
8475         }
8476 
8477         /* Then comes IVlen and IV, if present. */
8478         if (strncmp(buf, "IVlen = ", 8) == 0) {
8479             if (sscanf(buf, "IVlen = %u", &IV_len) != 1) {
8480                 goto done;
8481             }
8482 
8483             if ((IV_len % 8) != 0) {
8484                 fprintf(stderr, "Assumption that IV_len was length in bits incorrect: %u - %s. ", IV_len, buf);
8485                 fprintf(stderr, "Note that NSS only supports byte-aligned inputs and not bit-aligned inputs.\n");
8486                 goto done;
8487             }
8488 
8489             /* Need the IV length in bytes, not bits. */
8490             IV_len = IV_len / 8;
8491 
8492             fputs(buf, kbkdf_resp);
8493             continue;
8494         }
8495         if (strncmp(buf, "IV = ", 5) == 0) {
8496             buf_offset = 5;
8497 
8498             for (offset = 0; offset < IV_len; offset++, buf_offset += 2) {
8499                 hex_to_byteval(buf + buf_offset, IV + offset);
8500             }
8501 
8502             fputs(buf, kbkdf_resp);
8503             continue;
8504         }
8505 
8506         /* We might have DataBeforeCtr and DataAfterCtr if present. */
8507         if (strncmp(buf, "DataBeforeCtrLen = ", 19) == 0) {
8508             if (sscanf(buf, "DataBeforeCtrLen = %u", &BeforeFixedInputData_len) != 1) {
8509                 goto done;
8510             }
8511 
8512             fputs(buf, kbkdf_resp);
8513             continue;
8514         }
8515         if (strncmp(buf, "DataBeforeCtrData = ", 20) == 0) {
8516             buf_offset = 20;
8517 
8518             for (offset = 0; offset < BeforeFixedInputData_len; offset++, buf_offset += 2) {
8519                 hex_to_byteval(buf + buf_offset, BeforeFixedInputData + offset);
8520             }
8521 
8522             fputs(buf, kbkdf_resp);
8523             continue;
8524         }
8525         if (strncmp(buf, "DataAfterCtrLen = ", 18) == 0) {
8526             if (sscanf(buf, "DataAfterCtrLen = %u", &AfterFixedInputData_len) != 1) {
8527                 goto done;
8528             }
8529 
8530             fputs(buf, kbkdf_resp);
8531             continue;
8532         }
8533         if (strncmp(buf, "DataAfterCtrData = ", 19) == 0) {
8534             buf_offset = 19;
8535 
8536             for (offset = 0; offset < AfterFixedInputData_len; offset++, buf_offset += 2) {
8537                 hex_to_byteval(buf + buf_offset, AfterFixedInputData + offset);
8538             }
8539 
8540             fputs(buf, kbkdf_resp);
8541             continue;
8542         }
8543 
8544         /* Otherwise, we might have FixedInputData, if present. */
8545         if (strncmp(buf, "FixedInputDataByteLen = ", 24) == 0) {
8546             if (sscanf(buf, "FixedInputDataByteLen = %u", &FixedInputData_len) != 1) {
8547                 goto done;
8548             }
8549 
8550             fputs(buf, kbkdf_resp);
8551             continue;
8552         }
8553         if (strncmp(buf, "FixedInputData = ", 17) == 0) {
8554             buf_offset = 17;
8555 
8556             for (offset = 0; offset < FixedInputData_len; offset++, buf_offset += 2) {
8557                 hex_to_byteval(buf + buf_offset, FixedInputData + offset);
8558             }
8559 
8560             fputs(buf, kbkdf_resp);
8561             continue;
8562         }
8563 
8564         /* Finally, run the KBKDF calculation when KO is passed. */
8565         if (strncmp(buf, "KO = ", 5) == 0) {
8566             CK_SESSION_HANDLE session;
8567             CK_OBJECT_HANDLE prf_key;
8568             CK_OBJECT_HANDLE derived_key;
8569 
8570             /* Open the session. */
8571             crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
8572             if (crv != CKR_OK) {
8573                 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n", (unsigned int)crv);
8574                 goto done;
8575             }
8576 
8577             /* Create the PRF key object. */
8578             prf_template[0].ulValueLen = KI_len;
8579             crv = NSC_CreateObject(session, prf_template, prf_template_count, &prf_key);
8580             if (crv != CKR_OK) {
8581                 fprintf(stderr, "NSC_CreateObject (prf_key) failed crv=0x%x\n", (unsigned int)crv);
8582                 goto done;
8583             }
8584 
8585             /* Set up the KDF parameters. */
8586             if (kdf.mechanism == CKM_SP800_108_COUNTER_KDF) {
8587                 /* Counter operates in one of three ways: counter before fixed
8588                  * input data, counter between fixed input data, and counter
8589                  * after fixed input data. In all cases, we have an iterator.
8590                  */
8591                 iterator.ulWidthInBits = counter_bitlen;
8592 
8593                 if (ctr_location == 0 || ctr_location > 3) {
8594                     fprintf(stderr, "Expected ctr_location != 0 for Counter Mode KDF but got 0.\n");
8595                     goto done;
8596                 } else if (ctr_location == 1) {
8597                     /* Counter before */
8598                     dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
8599                     dataParams[0].pValue = &iterator;
8600                     dataParams[0].ulValueLen = sizeof(iterator);
8601 
8602                     dataParams[1].type = CK_SP800_108_BYTE_ARRAY;
8603                     dataParams[1].pValue = FixedInputData;
8604                     dataParams[1].ulValueLen = FixedInputData_len;
8605 
8606                     dataParams_len = 2;
8607                 } else if (ctr_location == 2) {
8608                     /* Counter between */
8609                     dataParams[0].type = CK_SP800_108_BYTE_ARRAY;
8610                     dataParams[0].pValue = BeforeFixedInputData;
8611                     dataParams[0].ulValueLen = BeforeFixedInputData_len;
8612 
8613                     dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE;
8614                     dataParams[1].pValue = &iterator;
8615                     dataParams[1].ulValueLen = sizeof(iterator);
8616 
8617                     dataParams[2].type = CK_SP800_108_BYTE_ARRAY;
8618                     dataParams[2].pValue = AfterFixedInputData;
8619                     dataParams[2].ulValueLen = AfterFixedInputData_len;
8620 
8621                     dataParams_len = 3;
8622                 } else {
8623                     /* Counter after */
8624                     dataParams[0].type = CK_SP800_108_BYTE_ARRAY;
8625                     dataParams[0].pValue = FixedInputData;
8626                     dataParams[0].ulValueLen = FixedInputData_len;
8627 
8628                     dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE;
8629                     dataParams[1].pValue = &iterator;
8630                     dataParams[1].ulValueLen = sizeof(iterator);
8631 
8632                     dataParams_len = 2;
8633                 }
8634             } else if (kdf.mechanism == CKM_SP800_108_FEEDBACK_KDF || kdf.mechanism == CKM_SP800_108_DOUBLE_PIPELINE_KDF) {
8635                 /* When counter_bitlen != 0, we have an optional counter. */
8636                 if (counter_bitlen != 0) {
8637                     iterator.ulWidthInBits = counter_bitlen;
8638 
8639                     if (ctr_location == 0 || ctr_location > 3) {
8640                         fprintf(stderr, "Expected ctr_location != 0 for Counter Mode KDF but got 0.\n");
8641                         goto done;
8642                     } else if (ctr_location == 1) {
8643                         /* Counter before */
8644                         dataParams[0].type = CK_SP800_108_OPTIONAL_COUNTER;
8645                         dataParams[0].pValue = &iterator;
8646                         dataParams[0].ulValueLen = sizeof(iterator);
8647 
8648                         dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE;
8649                         dataParams[1].pValue = NULL;
8650                         dataParams[1].ulValueLen = 0;
8651 
8652                         dataParams[2].type = CK_SP800_108_BYTE_ARRAY;
8653                         dataParams[2].pValue = FixedInputData;
8654                         dataParams[2].ulValueLen = FixedInputData_len;
8655 
8656                         dataParams_len = 3;
8657                     } else if (ctr_location == 2) {
8658                         /* Counter between */
8659                         dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
8660                         dataParams[0].pValue = NULL;
8661                         dataParams[0].ulValueLen = 0;
8662 
8663                         dataParams[1].type = CK_SP800_108_OPTIONAL_COUNTER;
8664                         dataParams[1].pValue = &iterator;
8665                         dataParams[1].ulValueLen = sizeof(iterator);
8666 
8667                         dataParams[2].type = CK_SP800_108_BYTE_ARRAY;
8668                         dataParams[2].pValue = FixedInputData;
8669                         dataParams[2].ulValueLen = FixedInputData_len;
8670 
8671                         dataParams_len = 3;
8672                     } else {
8673                         /* Counter after */
8674                         dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
8675                         dataParams[0].pValue = NULL;
8676                         dataParams[0].ulValueLen = 0;
8677 
8678                         dataParams[1].type = CK_SP800_108_BYTE_ARRAY;
8679                         dataParams[1].pValue = FixedInputData;
8680                         dataParams[1].ulValueLen = FixedInputData_len;
8681 
8682                         dataParams[2].type = CK_SP800_108_OPTIONAL_COUNTER;
8683                         dataParams[2].pValue = &iterator;
8684                         dataParams[2].ulValueLen = sizeof(iterator);
8685 
8686                         dataParams_len = 3;
8687                     }
8688                 } else {
8689                     dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
8690                     dataParams[0].pValue = NULL;
8691                     dataParams[0].ulValueLen = 0;
8692 
8693                     dataParams[1].type = CK_SP800_108_BYTE_ARRAY;
8694                     dataParams[1].pValue = FixedInputData;
8695                     dataParams[1].ulValueLen = FixedInputData_len;
8696 
8697                     dataParams_len = 2;
8698                 }
8699             }
8700 
8701             if (kdf.mechanism != CKM_SP800_108_FEEDBACK_KDF) {
8702                 kdfParams.prfType = prf_mech;
8703                 kdfParams.ulNumberOfDataParams = dataParams_len;
8704                 kdfParams.pDataParams = dataParams;
8705 
8706                 kdf.pParameter = &kdfParams;
8707                 kdf.ulParameterLen = sizeof(kdfParams);
8708             } else {
8709                 feedbackParams.prfType = prf_mech;
8710                 feedbackParams.ulNumberOfDataParams = dataParams_len;
8711                 feedbackParams.pDataParams = dataParams;
8712                 feedbackParams.ulIVLen = IV_len;
8713                 if (IV_len == 0) {
8714                     feedbackParams.pIV = NULL;
8715                 } else {
8716                     feedbackParams.pIV = IV;
8717                 }
8718 
8719                 kdf.pParameter = &feedbackParams;
8720                 kdf.ulParameterLen = sizeof(feedbackParams);
8721             }
8722 
8723             crv = NSC_DeriveKey(session, &kdf, prf_key, derive_template, derive_template_count, &derived_key);
8724             if (crv != CKR_OK) {
8725                 fprintf(stderr, "NSC_DeriveKey(derived_key) failed crv=0x%x\n", (unsigned int)crv);
8726                 goto done;
8727             }
8728 
8729             crv = NSC_GetAttributeValue(session, derived_key, &output_key, 1);
8730             if (crv != CKR_OK) {
8731                 fprintf(stderr, "NSC_GetAttribute(derived_value) failed crv=0x%x\n", (unsigned int)crv);
8732                 goto done;
8733             }
8734 
8735             fputs("KO = ", kbkdf_resp);
8736             to_hex_str(buf, KO, output_key.ulValueLen);
8737             fputs(buf, kbkdf_resp);
8738             fputs("\r\n", kbkdf_resp);
8739 
8740             continue;
8741         }
8742     }
8743 
8744 done:
8745     if (kbkdf_req != NULL) {
8746         fclose(kbkdf_req);
8747     }
8748     if (kbkdf_resp != stdout && kbkdf_resp != NULL) {
8749         fclose(kbkdf_resp);
8750     }
8751 
8752     return;
8753 }
8754 
8755 int
main(int argc,char ** argv)8756 main(int argc, char **argv)
8757 {
8758     if (argc < 2)
8759         exit(-1);
8760 
8761     RNG_RNGInit();
8762     SECOID_Init();
8763 
8764     /*************/
8765     /*   TDEA    */
8766     /*************/
8767     if (strcmp(argv[1], "tdea") == 0) {
8768         /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
8769         if (strcmp(argv[2], "kat") == 0) {
8770             /* Known Answer Test (KAT) */
8771             tdea_kat_mmt(argv[4]);
8772         } else if (strcmp(argv[2], "mmt") == 0) {
8773             /* Multi-block Message Test (MMT) */
8774             tdea_kat_mmt(argv[4]);
8775         } else if (strcmp(argv[2], "mct") == 0) {
8776             /* Monte Carlo Test (MCT) */
8777             if (strcmp(argv[3], "ecb") == 0) {
8778                 /* ECB mode */
8779                 tdea_mct(NSS_DES_EDE3, argv[4]);
8780             } else if (strcmp(argv[3], "cbc") == 0) {
8781                 /* CBC mode */
8782                 tdea_mct(NSS_DES_EDE3_CBC, argv[4]);
8783             }
8784         }
8785         /*************/
8786         /*   AES     */
8787         /*************/
8788     } else if (strcmp(argv[1], "aes") == 0) {
8789         /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
8790         if (strcmp(argv[2], "kat") == 0) {
8791             /* Known Answer Test (KAT) */
8792             aes_kat_mmt(argv[4]);
8793         } else if (strcmp(argv[2], "mmt") == 0) {
8794             /* Multi-block Message Test (MMT) */
8795             aes_kat_mmt(argv[4]);
8796         } else if (strcmp(argv[2], "gcm") == 0) {
8797             if (strcmp(argv[3], "decrypt") == 0) {
8798                 aes_gcm(argv[4], 0);
8799             } else if (strcmp(argv[3], "encrypt_extiv") == 0) {
8800                 aes_gcm(argv[4], 1);
8801             } else if (strcmp(argv[3], "encrypt_intiv") == 0) {
8802                 aes_gcm(argv[4], 2);
8803             }
8804         } else if (strcmp(argv[2], "mct") == 0) {
8805             /* Monte Carlo Test (MCT) */
8806             if (strcmp(argv[3], "ecb") == 0) {
8807                 /* ECB mode */
8808                 aes_ecb_mct(argv[4]);
8809             } else if (strcmp(argv[3], "cbc") == 0) {
8810                 /* CBC mode */
8811                 aes_cbc_mct(argv[4]);
8812             }
8813         }
8814         /*************/
8815         /*   SHA     */
8816         /*************/
8817     } else if (strcmp(argv[1], "sha") == 0) {
8818         sha_test(argv[2]);
8819         /*************/
8820         /*   RSA     */
8821         /*************/
8822     } else if (strcmp(argv[1], "rsa") == 0) {
8823         /* argv[2]=siggen|sigver */
8824         /* argv[3]=<test name>.req */
8825         if (strcmp(argv[2], "siggen") == 0) {
8826             /* Signature Generation Test */
8827             rsa_siggen_test(argv[3]);
8828         } else if (strcmp(argv[2], "sigver") == 0) {
8829             /* Signature Verification Test */
8830             rsa_sigver_test(argv[3]);
8831         } else if (strcmp(argv[2], "keypair") == 0) {
8832             /* Key Pair Generation Test */
8833             rsa_keypair_test(argv[3]);
8834         }
8835         /*************/
8836         /*   HMAC    */
8837         /*************/
8838     } else if (strcmp(argv[1], "hmac") == 0) {
8839         hmac_test(argv[2]);
8840         /*************/
8841         /*   DSA     */
8842         /*************/
8843     } else if (strcmp(argv[1], "dsa") == 0) {
8844         /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */
8845         /* argv[3]=<test name>.req */
8846         if (strcmp(argv[2], "keypair") == 0) {
8847             /* Key Pair Generation Test */
8848             dsa_keypair_test(argv[3]);
8849         } else if (strcmp(argv[2], "pqggen") == 0) {
8850             /* Domain Parameter Generation Test */
8851             dsa_pqggen_test(argv[3]);
8852         } else if (strcmp(argv[2], "pqgver") == 0) {
8853             /* Domain Parameter Validation Test */
8854             dsa_pqgver_test(argv[3]);
8855         } else if (strcmp(argv[2], "siggen") == 0) {
8856             /* Signature Generation Test */
8857             dsa_siggen_test(argv[3]);
8858         } else if (strcmp(argv[2], "sigver") == 0) {
8859             /* Signature Verification Test */
8860             dsa_sigver_test(argv[3]);
8861         }
8862         /*************/
8863         /*   ECDSA   */
8864         /*************/
8865     } else if (strcmp(argv[1], "ecdsa") == 0) {
8866         /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */
8867         if (strcmp(argv[2], "keypair") == 0) {
8868             /* Key Pair Generation Test */
8869             ecdsa_keypair_test(argv[3]);
8870         } else if (strcmp(argv[2], "pkv") == 0) {
8871             /* Public Key Validation Test */
8872             ecdsa_pkv_test(argv[3]);
8873         } else if (strcmp(argv[2], "siggen") == 0) {
8874             /* Signature Generation Test */
8875             ecdsa_siggen_test(argv[3]);
8876         } else if (strcmp(argv[2], "sigver") == 0) {
8877             /* Signature Verification Test */
8878             ecdsa_sigver_test(argv[3]);
8879         }
8880         /*************/
8881         /*   ECDH   */
8882         /*************/
8883     } else if (strcmp(argv[1], "ecdh") == 0) {
8884         /* argv[2]={init|resp}-{func|verify} argv[3]=<test name>.req */
8885         if (strcmp(argv[2], "init-func") == 0) {
8886             ecdh_functional(argv[3], 0);
8887         } else if (strcmp(argv[2], "resp-func") == 0) {
8888             ecdh_functional(argv[3], 1);
8889         } else if (strcmp(argv[2], "init-verify") == 0) {
8890             ecdh_verify(argv[3], 0);
8891         } else if (strcmp(argv[2], "resp-verify") == 0) {
8892             ecdh_verify(argv[3], 1);
8893         }
8894         /*************/
8895         /*   DH   */
8896         /*************/
8897     } else if (strcmp(argv[1], "dh") == 0) {
8898         /* argv[2]={init|resp}-{func|verify} argv[3]=<test name>.req */
8899         if (strcmp(argv[2], "init-func") == 0) {
8900             dh_functional(argv[3], 0);
8901         } else if (strcmp(argv[2], "resp-func") == 0) {
8902             dh_functional(argv[3], 1);
8903         } else if (strcmp(argv[2], "init-verify") == 0) {
8904             dh_verify(argv[3], 0);
8905         } else if (strcmp(argv[2], "resp-verify") == 0) {
8906             dh_verify(argv[3], 1);
8907         }
8908         /*************/
8909         /*   RNG     */
8910         /*************/
8911     } else if (strcmp(argv[1], "rng") == 0) {
8912         /* argv[2]=vst|mct argv[3]=<test name>.req */
8913         if (strcmp(argv[2], "vst") == 0) {
8914             /* Variable Seed Test */
8915             rng_vst(argv[3]);
8916         } else if (strcmp(argv[2], "mct") == 0) {
8917             /* Monte Carlo Test */
8918             rng_mct(argv[3]);
8919         }
8920     } else if (strcmp(argv[1], "drbg") == 0) {
8921         /* Variable Seed Test */
8922         drbg(argv[2]);
8923     } else if (strcmp(argv[1], "ddrbg") == 0) {
8924         debug = 1;
8925         drbg(argv[2]);
8926     } else if (strcmp(argv[1], "tls") == 0) {
8927         tls(argv[2]);
8928     } else if (strcmp(argv[1], "ikev1") == 0) {
8929         ikev1(argv[2]);
8930     } else if (strcmp(argv[1], "ikev1-psk") == 0) {
8931         ikev1_psk(argv[2]);
8932     } else if (strcmp(argv[1], "ikev2") == 0) {
8933         ikev2(argv[2]);
8934     } else if (strcmp(argv[1], "kbkdf") == 0) {
8935         kbkdf(argv[2]);
8936     }
8937     return 0;
8938 }
8939