summaryrefslogtreecommitdiff
path: root/lib/softoken/fipstest.c
blob: 01d66427c4d28a3a92ed5271750be492b6b010ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
/*
 * PKCS #11 FIPS Power-Up Self Test.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef NSS_FIPS_DISABLED
#include "seccomon.h"
#include "blapi.h"
#include "softoken.h"
#include "lowkeyi.h"
#include "secoid.h"
#include "secerr.h"
#include "pkcs11i.h"
#include "lowpbe.h"

/*
 * different platforms have different ways of calling and initial entry point
 * when the dll/.so is loaded. Most platforms support either a posix pragma
 * or the GCC attribute. Some platforms suppor a pre-defined name, and some
 * platforms have a link line way of invoking this function.
 */

/* The pragma */
#if defined(USE_INIT_PRAGMA)
#pragma init(sftk_startup_tests)
#endif

/* GCC Attribute */
#if defined(__GNUC__) && !defined(NSS_NO_INIT_SUPPORT)
#define INIT_FUNCTION __attribute__((constructor))
#else
#define INIT_FUNCTION
#endif

static void INIT_FUNCTION sftk_startup_tests(void);

/* Windows pre-defined entry */
#if defined(XP_WIN) && !defined(NSS_NO_INIT_SUPPORT)
#include <windows.h>

BOOL WINAPI
DllMain(
    HINSTANCE hinstDLL, // handle to DLL module
    DWORD fdwReason,    // reason for calling function
    LPVOID lpReserved)  // reserved
{
    // Perform actions based on the reason for calling.
    switch (fdwReason) {
        case DLL_PROCESS_ATTACH:
            // Initialize once for each new process.
            // Return FALSE to fail DLL load.
            sftk_startup_tests();
            break;

        case DLL_THREAD_ATTACH:
            // Do thread-specific initialization.
            break;

        case DLL_THREAD_DETACH:
            // Do thread-specific cleanup.
            break;

        case DLL_PROCESS_DETACH:
            // Perform any necessary cleanup.
            break;
    }
    return TRUE; // Successful DLL_PROCESS_ATTACH.
}
#endif

/* FIPS preprocessor directives for RSA.                         */
#define FIPS_RSA_TYPE siBuffer
#define FIPS_RSA_PUBLIC_EXPONENT_LENGTH 3    /*   24-bits */
#define FIPS_RSA_PRIVATE_VERSION_LENGTH 1    /*    8-bits */
#define FIPS_RSA_MESSAGE_LENGTH 256          /* 2048-bits */
#define FIPS_RSA_COEFFICIENT_LENGTH 128      /* 1024-bits */
#define FIPS_RSA_PRIME0_LENGTH 128           /* 1024-bits */
#define FIPS_RSA_PRIME1_LENGTH 128           /* 1024-bits */
#define FIPS_RSA_EXPONENT0_LENGTH 128        /* 1024-bits */
#define FIPS_RSA_EXPONENT1_LENGTH 128        /* 1024-bits */
#define FIPS_RSA_PRIVATE_EXPONENT_LENGTH 256 /* 2048-bits */
#define FIPS_RSA_ENCRYPT_LENGTH 256          /* 2048-bits */
#define FIPS_RSA_DECRYPT_LENGTH 256          /* 2048-bits */
#define FIPS_RSA_SIGNATURE_LENGTH 256        /* 2048-bits */
#define FIPS_RSA_MODULUS_LENGTH 256          /* 2048-bits */

/*
* Test the softoken RSA_HashSign and RSH_HashCheckSign.
*/
static SECStatus
sftk_fips_RSA_PowerUpSigSelfTest(HASH_HashType shaAlg,
                                 NSSLOWKEYPublicKey *rsa_public_key,
                                 NSSLOWKEYPrivateKey *rsa_private_key,
                                 const unsigned char *rsa_known_msg,
                                 const unsigned int rsa_kmsg_length,
                                 const unsigned char *rsa_known_signature)
{
    SECOidTag shaOid;                   /* SHA OID */
    unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
    unsigned int shaLength = 0;         /* length of SHA */
    unsigned int rsa_bytes_signed;
    unsigned char rsa_computed_signature[FIPS_RSA_SIGNATURE_LENGTH];
    SECStatus rv;

    if (shaAlg == HASH_AlgSHA1) {
        if (SHA1_HashBuf(sha, rsa_known_msg, rsa_kmsg_length) != SECSuccess) {
            goto loser;
        }
        shaLength = SHA1_LENGTH;
        shaOid = SEC_OID_SHA1;
    } else if (shaAlg == HASH_AlgSHA256) {
        if (SHA256_HashBuf(sha, rsa_known_msg, rsa_kmsg_length) != SECSuccess) {
            goto loser;
        }
        shaLength = SHA256_LENGTH;
        shaOid = SEC_OID_SHA256;
    } else if (shaAlg == HASH_AlgSHA384) {
        if (SHA384_HashBuf(sha, rsa_known_msg, rsa_kmsg_length) != SECSuccess) {
            goto loser;
        }
        shaLength = SHA384_LENGTH;
        shaOid = SEC_OID_SHA384;
    } else if (shaAlg == HASH_AlgSHA512) {
        if (SHA512_HashBuf(sha, rsa_known_msg, rsa_kmsg_length) != SECSuccess) {
            goto loser;
        }
        shaLength = SHA512_LENGTH;
        shaOid = SEC_OID_SHA512;
    } else {
        goto loser;
    }

    /*************************************************/
    /* RSA Single-Round Known Answer Signature Test. */
    /*************************************************/

    /* Perform RSA signature with the RSA private key. */
    rv = RSA_HashSign(shaOid,
                      rsa_private_key,
                      rsa_computed_signature,
                      &rsa_bytes_signed,
                      FIPS_RSA_SIGNATURE_LENGTH,
                      sha,
                      shaLength);

    if ((rv != SECSuccess) ||
        (rsa_bytes_signed != FIPS_RSA_SIGNATURE_LENGTH) ||
        (PORT_Memcmp(rsa_computed_signature, rsa_known_signature,
                     FIPS_RSA_SIGNATURE_LENGTH) != 0)) {
        goto loser;
    }

    /****************************************************/
    /* RSA Single-Round Known Answer Verification Test. */
    /****************************************************/

    /* Perform RSA verification with the RSA public key. */
    rv = RSA_HashCheckSign(shaOid,
                           rsa_public_key,
                           rsa_computed_signature,
                           rsa_bytes_signed,
                           sha,
                           shaLength);

    if (rv != SECSuccess) {
        goto loser;
    }
    return (SECSuccess);

loser:

    return (SECFailure);
}

static SECStatus
sftk_fips_RSA_PowerUpSelfTest(void)
{
    /* RSA Known Modulus used in both Public/Private Key Values (2048-bits). */
    static const PRUint8 rsa_modulus[FIPS_RSA_MODULUS_LENGTH] = {
        0xb8, 0x15, 0x00, 0x33, 0xda, 0x0c, 0x9d, 0xa5,
        0x14, 0x8c, 0xde, 0x1f, 0x23, 0x07, 0x54, 0xe2,
        0xc6, 0xb9, 0x51, 0x04, 0xc9, 0x65, 0x24, 0x6e,
        0x0a, 0x46, 0x34, 0x5c, 0x37, 0x86, 0x6b, 0x88,
        0x24, 0x27, 0xac, 0xa5, 0x02, 0x79, 0xfb, 0xed,
        0x75, 0xc5, 0x3f, 0x6e, 0xdf, 0x05, 0x5f, 0x0f,
        0x20, 0x70, 0xa0, 0x5b, 0x85, 0xdb, 0xac, 0xb9,
        0x5f, 0x02, 0xc2, 0x64, 0x1e, 0x84, 0x5b, 0x3e,
        0xad, 0xbf, 0xf6, 0x2e, 0x51, 0xd6, 0xad, 0xf7,
        0xa7, 0x86, 0x75, 0x86, 0xec, 0xa7, 0xe1, 0xf7,
        0x08, 0xbf, 0xdc, 0x56, 0xb1, 0x3b, 0xca, 0xd8,
        0xfc, 0x51, 0xdf, 0x9a, 0x2a, 0x37, 0x06, 0xf2,
        0xd1, 0x6b, 0x9a, 0x5e, 0x2a, 0xe5, 0x20, 0x57,
        0x35, 0x9f, 0x1f, 0x98, 0xcf, 0x40, 0xc7, 0xd6,
        0x98, 0xdb, 0xde, 0xf5, 0x64, 0x53, 0xf7, 0x9d,
        0x45, 0xf3, 0xd6, 0x78, 0xb9, 0xe3, 0xa3, 0x20,
        0xcd, 0x79, 0x43, 0x35, 0xef, 0xd7, 0xfb, 0xb9,
        0x80, 0x88, 0x27, 0x2f, 0x63, 0xa8, 0x67, 0x3d,
        0x4a, 0xfa, 0x06, 0xc6, 0xd2, 0x86, 0x0b, 0xa7,
        0x28, 0xfd, 0xe0, 0x1e, 0x93, 0x4b, 0x17, 0x2e,
        0xb0, 0x11, 0x6f, 0xc6, 0x2b, 0x98, 0x0f, 0x15,
        0xe3, 0x87, 0x16, 0x7a, 0x7c, 0x67, 0x3e, 0x12,
        0x2b, 0xf8, 0xbe, 0x48, 0xc1, 0x97, 0x47, 0xf4,
        0x1f, 0x81, 0x80, 0x12, 0x28, 0xe4, 0x7b, 0x1e,
        0xb7, 0x00, 0xa4, 0xde, 0xaa, 0xfb, 0x0f, 0x77,
        0x84, 0xa3, 0xd6, 0xb2, 0x03, 0x48, 0xdd, 0x53,
        0x8b, 0x46, 0x41, 0x28, 0x52, 0xc4, 0x53, 0xf0,
        0x1c, 0x95, 0xd9, 0x36, 0xe0, 0x0f, 0x26, 0x46,
        0x9c, 0x61, 0x0e, 0x80, 0xca, 0x86, 0xaf, 0x39,
        0x95, 0xe5, 0x60, 0x43, 0x61, 0x3e, 0x2b, 0xb4,
        0xe8, 0xbd, 0x8d, 0x77, 0x62, 0xf5, 0x32, 0x43,
        0x2f, 0x4b, 0x65, 0x82, 0x14, 0xdd, 0x29, 0x5b
    };

    /* RSA Known Public Key Values (24-bits). */
    static const PRUint8 rsa_public_exponent[FIPS_RSA_PUBLIC_EXPONENT_LENGTH] = { 0x01, 0x00, 0x01 };
    /* RSA Known Private Key Values (version                 is    8-bits), */
    /*                              (private exponent        is 2048-bits), */
    /*                              (private prime0          is 1024-bits), */
    /*                              (private prime1          is 1024-bits), */
    /*                              (private prime exponent0 is 1024-bits), */
    /*                              (private prime exponent1 is 1024-bits), */
    /*                          and (private coefficient     is 1024-bits). */
    static const PRUint8 rsa_version[] = { 0x00 };

    static const PRUint8 rsa_private_exponent[FIPS_RSA_PRIVATE_EXPONENT_LENGTH] = {
        0x29, 0x08, 0x05, 0x53, 0x89, 0x76, 0xe6, 0x6c,
        0xb5, 0x77, 0xf0, 0xca, 0xdf, 0xf3, 0xf2, 0x67,
        0xda, 0x03, 0xd4, 0x9b, 0x4c, 0x88, 0xce, 0xe5,
        0xf8, 0x44, 0x4d, 0xc7, 0x80, 0x58, 0xe5, 0xff,
        0x22, 0x8f, 0xf5, 0x5b, 0x92, 0x81, 0xbe, 0x35,
        0xdf, 0xda, 0x67, 0x99, 0x3e, 0xfc, 0xe3, 0x83,
        0x6b, 0xa7, 0xaf, 0x16, 0xb7, 0x6f, 0x8f, 0xc0,
        0x81, 0xfd, 0x0b, 0x77, 0x65, 0x95, 0xfb, 0x00,
        0xad, 0x99, 0xec, 0x35, 0xc6, 0xe8, 0x23, 0x3e,
        0xe0, 0x88, 0x88, 0x09, 0xdb, 0x16, 0x50, 0xb7,
        0xcf, 0xab, 0x74, 0x61, 0x9e, 0x7f, 0xc5, 0x67,
        0x38, 0x56, 0xc7, 0x90, 0x85, 0x78, 0x5e, 0x84,
        0x21, 0x49, 0xea, 0xce, 0xb2, 0xa0, 0xff, 0xe4,
        0x70, 0x7f, 0x57, 0x7b, 0xa8, 0x36, 0xb8, 0x54,
        0x8d, 0x1d, 0xf5, 0x44, 0x9d, 0x68, 0x59, 0xf9,
        0x24, 0x6e, 0x85, 0x8f, 0xc3, 0x5f, 0x8a, 0x2c,
        0x94, 0xb7, 0xbc, 0x0e, 0xa5, 0xef, 0x93, 0x06,
        0x38, 0xcd, 0x07, 0x0c, 0xae, 0xb8, 0x44, 0x1a,
        0xd8, 0xe7, 0xf5, 0x9a, 0x1e, 0x9c, 0x18, 0xc7,
        0x6a, 0xc2, 0x7f, 0x28, 0x01, 0x4f, 0xb4, 0xb8,
        0x90, 0x97, 0x5a, 0x43, 0x38, 0xad, 0xe8, 0x95,
        0x68, 0x83, 0x1a, 0x1b, 0x10, 0x07, 0xe6, 0x02,
        0x52, 0x1f, 0xbf, 0x76, 0x6b, 0x46, 0xd6, 0xfb,
        0xc3, 0xbe, 0xb5, 0xac, 0x52, 0x53, 0x01, 0x1c,
        0xf3, 0xc5, 0xeb, 0x64, 0xf2, 0x1e, 0xc4, 0x38,
        0xe9, 0xaa, 0xd9, 0xc3, 0x72, 0x51, 0xa5, 0x44,
        0x58, 0x69, 0x0b, 0x1b, 0x98, 0x7f, 0xf2, 0x23,
        0xff, 0xeb, 0xf0, 0x75, 0x24, 0xcf, 0xc5, 0x1e,
        0xb8, 0x6a, 0xc5, 0x2f, 0x4f, 0x23, 0x50, 0x7d,
        0x15, 0x9d, 0x19, 0x7a, 0x0b, 0x82, 0xe0, 0x21,
        0x5b, 0x5f, 0x9d, 0x50, 0x2b, 0x83, 0xe4, 0x48,
        0xcc, 0x39, 0xe5, 0xfb, 0x13, 0x7b, 0x6f, 0x81
    };

    static const PRUint8 rsa_prime0[FIPS_RSA_PRIME0_LENGTH] = {
        0xe4, 0xbf, 0x21, 0x62, 0x9b, 0xa9, 0x77, 0x40,
        0x8d, 0x2a, 0xce, 0xa1, 0x67, 0x5a, 0x4c, 0x96,
        0x45, 0x98, 0x67, 0xbd, 0x75, 0x22, 0x33, 0x6f,
        0xe6, 0xcb, 0x77, 0xde, 0x9e, 0x97, 0x7d, 0x96,
        0x8c, 0x5e, 0x5d, 0x34, 0xfb, 0x27, 0xfc, 0x6d,
        0x74, 0xdb, 0x9d, 0x2e, 0x6d, 0xf6, 0xea, 0xfc,
        0xce, 0x9e, 0xda, 0xa7, 0x25, 0xa2, 0xf4, 0x58,
        0x6d, 0x0a, 0x3f, 0x01, 0xc2, 0xb4, 0xab, 0x38,
        0xc1, 0x14, 0x85, 0xb6, 0xfa, 0x94, 0xc3, 0x85,
        0xf9, 0x3c, 0x2e, 0x96, 0x56, 0x01, 0xe7, 0xd6,
        0x14, 0x71, 0x4f, 0xfb, 0x4c, 0x85, 0x52, 0xc4,
        0x61, 0x1e, 0xa5, 0x1e, 0x96, 0x13, 0x0d, 0x8f,
        0x66, 0xae, 0xa0, 0xcd, 0x7d, 0x25, 0x66, 0x19,
        0x15, 0xc2, 0xcf, 0xc3, 0x12, 0x3c, 0xe8, 0xa4,
        0x52, 0x4c, 0xcb, 0x28, 0x3c, 0xc4, 0xbf, 0x95,
        0x33, 0xe3, 0x81, 0xea, 0x0c, 0x6c, 0xa2, 0x05
    };
    static const PRUint8 rsa_prime1[FIPS_RSA_PRIME1_LENGTH] = {
        0xce, 0x03, 0x94, 0xf4, 0xa9, 0x2c, 0x1e, 0x06,
        0xe7, 0x40, 0x30, 0x01, 0xf7, 0xbb, 0x68, 0x8c,
        0x27, 0xd2, 0x15, 0xe3, 0x28, 0x49, 0x5b, 0xa8,
        0xc1, 0x9a, 0x42, 0x7e, 0x31, 0xf9, 0x08, 0x34,
        0x81, 0xa2, 0x0f, 0x04, 0x61, 0x34, 0xe3, 0x36,
        0x92, 0xb1, 0x09, 0x2b, 0xe9, 0xef, 0x84, 0x88,
        0xbe, 0x9c, 0x98, 0x60, 0xa6, 0x60, 0x84, 0xe9,
        0x75, 0x6f, 0xcc, 0x81, 0xd1, 0x96, 0xef, 0xdd,
        0x2e, 0xca, 0xc4, 0xf5, 0x42, 0xfb, 0x13, 0x2b,
        0x57, 0xbf, 0x14, 0x5e, 0xc2, 0x7f, 0x77, 0x35,
        0x29, 0xc4, 0xe5, 0xe0, 0xf9, 0x6d, 0x15, 0x4a,
        0x42, 0x56, 0x1c, 0x3e, 0x0c, 0xc5, 0xce, 0x70,
        0x08, 0x63, 0x1e, 0x73, 0xdb, 0x7e, 0x74, 0x05,
        0x32, 0x01, 0xc6, 0x36, 0x32, 0x75, 0x6b, 0xed,
        0x9d, 0xfe, 0x7c, 0x7e, 0xa9, 0x57, 0xb4, 0xe9,
        0x22, 0xe4, 0xe7, 0xfe, 0x36, 0x07, 0x9b, 0xdf
    };
    static const PRUint8 rsa_exponent0[FIPS_RSA_EXPONENT0_LENGTH] = {
        0x04, 0x5a, 0x3a, 0xa9, 0x64, 0xaa, 0xd9, 0xd1,
        0x09, 0x9e, 0x99, 0xe5, 0xea, 0x50, 0x86, 0x8a,
        0x89, 0x72, 0x77, 0xee, 0xdb, 0xee, 0xb5, 0xa9,
        0xd8, 0x6b, 0x60, 0xb1, 0x84, 0xb4, 0xff, 0x37,
        0xc1, 0x1d, 0xfe, 0x8a, 0x06, 0x89, 0x61, 0x3d,
        0x37, 0xef, 0x01, 0xd3, 0xa3, 0x56, 0x02, 0x6c,
        0xa3, 0x05, 0xd4, 0xc5, 0x3f, 0x6b, 0x15, 0x59,
        0x25, 0x61, 0xff, 0x86, 0xea, 0x0c, 0x84, 0x01,
        0x85, 0x72, 0xfd, 0x84, 0x58, 0xca, 0x41, 0xda,
        0x27, 0xbe, 0xe4, 0x68, 0x09, 0xe4, 0xe9, 0x63,
        0x62, 0x6a, 0x31, 0x8a, 0x67, 0x8f, 0x55, 0xde,
        0xd4, 0xb6, 0x3f, 0x90, 0x10, 0x6c, 0xf6, 0x62,
        0x17, 0x23, 0x15, 0x7e, 0x33, 0x76, 0x65, 0xb5,
        0xee, 0x7b, 0x11, 0x76, 0xf5, 0xbe, 0xe0, 0xf2,
        0x57, 0x7a, 0x8c, 0x97, 0x0c, 0x68, 0xf5, 0xf8,
        0x41, 0xcf, 0x7f, 0x66, 0x53, 0xac, 0x31, 0x7d
    };
    static const PRUint8 rsa_exponent1[FIPS_RSA_EXPONENT1_LENGTH] = {
        0x93, 0x54, 0x14, 0x6e, 0x73, 0x9d, 0x4d, 0x4b,
        0xfa, 0x8c, 0xf8, 0xc8, 0x2f, 0x76, 0x22, 0xea,
        0x38, 0x80, 0x11, 0x8f, 0x05, 0xfc, 0x90, 0x44,
        0x3b, 0x50, 0x2a, 0x45, 0x3d, 0x4f, 0xaf, 0x02,
        0x7d, 0xc2, 0x7b, 0xa2, 0xd2, 0x31, 0x94, 0x5c,
        0x2e, 0xc3, 0xd4, 0x9f, 0x47, 0x09, 0x37, 0x6a,
        0xe3, 0x85, 0xf1, 0xa3, 0x0c, 0xd8, 0xf1, 0xb4,
        0x53, 0x7b, 0xc4, 0x71, 0x02, 0x86, 0x42, 0xbb,
        0x96, 0xff, 0x03, 0xa3, 0xb2, 0x67, 0x03, 0xea,
        0x77, 0x31, 0xfb, 0x4b, 0x59, 0x24, 0xf7, 0x07,
        0x59, 0xfb, 0xa9, 0xba, 0x1e, 0x26, 0x58, 0x97,
        0x66, 0xa1, 0x56, 0x49, 0x39, 0xb1, 0x2c, 0x55,
        0x0a, 0x6a, 0x78, 0x18, 0xba, 0xdb, 0xcf, 0xf4,
        0xf7, 0x32, 0x35, 0xa2, 0x04, 0xab, 0xdc, 0xa7,
        0x6d, 0xd9, 0xd5, 0x06, 0x6f, 0xec, 0x7d, 0x40,
        0x4c, 0xe8, 0x0e, 0xd0, 0xc9, 0xaa, 0xdf, 0x59
    };
    static const PRUint8 rsa_coefficient[FIPS_RSA_COEFFICIENT_LENGTH] = {
        0x17, 0xd7, 0xf5, 0x0a, 0xf0, 0x68, 0x97, 0x96,
        0xc4, 0x29, 0x18, 0x77, 0x9a, 0x1f, 0xe3, 0xf3,
        0x12, 0x13, 0x0f, 0x7e, 0x7b, 0xb9, 0xc1, 0x91,
        0xf9, 0xc7, 0x08, 0x56, 0x5c, 0xa4, 0xbc, 0x83,
        0x71, 0xf9, 0x78, 0xd9, 0x2b, 0xec, 0xfe, 0x6b,
        0xdc, 0x2f, 0x63, 0xc9, 0xcd, 0x50, 0x14, 0x5b,
        0xd3, 0x6e, 0x85, 0x4d, 0x0c, 0xa2, 0x0b, 0xa0,
        0x09, 0xb6, 0xca, 0x34, 0x9c, 0xc2, 0xc1, 0x4a,
        0xb0, 0xbc, 0x45, 0x93, 0xa5, 0x7e, 0x99, 0xb5,
        0xbd, 0xe4, 0x69, 0x29, 0x08, 0x28, 0xd2, 0xcd,
        0xab, 0x24, 0x78, 0x48, 0x41, 0x26, 0x0b, 0x37,
        0xa3, 0x43, 0xd1, 0x95, 0x1a, 0xd6, 0xee, 0x22,
        0x1c, 0x00, 0x0b, 0xc2, 0xb7, 0xa4, 0xa3, 0x21,
        0xa9, 0xcd, 0xe4, 0x69, 0xd3, 0x45, 0x02, 0xb1,
        0xb7, 0x3a, 0xbf, 0x51, 0x35, 0x1b, 0x78, 0xc2,
        0xcf, 0x0c, 0x0d, 0x60, 0x09, 0xa9, 0x44, 0x02
    };

    /* RSA Known Plaintext Message (1024-bits). */
    static const PRUint8 rsa_known_plaintext_msg[FIPS_RSA_MESSAGE_LENGTH] = {
        "Known plaintext message utilized"
        "for RSA Encryption &  Decryption"
        "blocks SHA256, SHA384  and      "
        "SHA512 RSA Signature KAT tests. "
        "Known plaintext message utilized"
        "for RSA Encryption &  Decryption"
        "blocks SHA256, SHA384  and      "
        "SHA512 RSA Signature KAT  tests."
    };

    /* RSA Known Signed Hash (2048-bits). */
    static const PRUint8 rsa_known_sha256_signature[] = {
        0x8c, 0x2d, 0x2e, 0xfb, 0x37, 0xb5, 0x6f, 0x38,
        0x9f, 0x06, 0x5a, 0xf3, 0x8c, 0xa0, 0xd0, 0x7a,
        0xde, 0xcf, 0xf9, 0x14, 0x95, 0x59, 0xd3, 0x5f,
        0x51, 0x5d, 0x5d, 0xad, 0xd8, 0x71, 0x33, 0x50,
        0x1d, 0x03, 0x3b, 0x3a, 0x32, 0x00, 0xb4, 0xde,
        0x7f, 0xe4, 0xb1, 0xe5, 0x6b, 0x83, 0xf4, 0x80,
        0x10, 0x3b, 0xb8, 0x8a, 0xdb, 0xe8, 0x0a, 0x42,
        0x9e, 0x8d, 0xd7, 0xbe, 0xed, 0xde, 0x5a, 0x3d,
        0xc6, 0xdb, 0xfe, 0x49, 0x6a, 0xe9, 0x1e, 0x75,
        0x66, 0xf1, 0x3f, 0x9e, 0x3f, 0xff, 0x05, 0x65,
        0xde, 0xca, 0x62, 0x62, 0xf3, 0xec, 0x53, 0x09,
        0xa0, 0x37, 0xd5, 0x66, 0x62, 0x72, 0x14, 0xb6,
        0x51, 0x32, 0x67, 0x50, 0xc1, 0xe1, 0x2f, 0x9e,
        0x98, 0x4e, 0x53, 0x96, 0x55, 0x4b, 0xc4, 0x92,
        0xc3, 0xb4, 0x80, 0xf0, 0x35, 0xc9, 0x00, 0x4b,
        0x5c, 0x85, 0x92, 0xb1, 0xe8, 0x6e, 0xa5, 0x51,
        0x38, 0x9f, 0xc9, 0x11, 0xb6, 0x14, 0xdf, 0x34,
        0x64, 0x40, 0x82, 0x82, 0xde, 0x16, 0x69, 0x93,
        0x89, 0x4e, 0x5c, 0x32, 0xf2, 0x0a, 0x4e, 0x9e,
        0xbd, 0x63, 0x99, 0x4f, 0xf3, 0x15, 0x90, 0xc2,
        0xfe, 0x6f, 0xb7, 0xf4, 0xad, 0xd4, 0x8e, 0x0b,
        0xd2, 0xf5, 0x22, 0xd2, 0x71, 0x65, 0x13, 0xf7,
        0x82, 0x7b, 0x75, 0xb6, 0xc1, 0xb4, 0x45, 0xbd,
        0x8f, 0x95, 0xcf, 0x5b, 0x95, 0x32, 0xef, 0x18,
        0x5f, 0xd3, 0xdf, 0x7e, 0x22, 0xdd, 0x25, 0xeb,
        0xe1, 0xbf, 0x3b, 0x9a, 0x55, 0x75, 0x4f, 0x3c,
        0x38, 0x67, 0x57, 0x04, 0x04, 0x57, 0x27, 0xf6,
        0x34, 0x0e, 0x57, 0x8a, 0x7c, 0xff, 0x7d, 0xca,
        0x8c, 0x06, 0xf8, 0x9d, 0xdb, 0xe4, 0xd8, 0x19,
        0xdd, 0x4d, 0xfd, 0x8f, 0xa0, 0x06, 0x53, 0xe8,
        0x33, 0x00, 0x70, 0x3f, 0x6b, 0xc3, 0xbd, 0x9a,
        0x78, 0xb5, 0xa9, 0xef, 0x6d, 0xda, 0x67, 0x92
    };

    /* RSA Known Signed Hash (2048-bits). */
    static const PRUint8 rsa_known_sha384_signature[] = {
        0x20, 0x2d, 0x21, 0x3a, 0xaa, 0x1e, 0x05, 0x15,
        0x5c, 0xca, 0x84, 0x86, 0xc0, 0x15, 0x81, 0xdf,
        0xd4, 0x06, 0x9f, 0xe0, 0xc1, 0xed, 0xef, 0x0f,
        0xfe, 0xb3, 0xc3, 0xbb, 0x28, 0xa5, 0x56, 0xbf,
        0xe3, 0x11, 0x5c, 0xc2, 0xc0, 0x0b, 0xfa, 0xfa,
        0x3d, 0xd3, 0x06, 0x20, 0xe2, 0xc9, 0xe4, 0x66,
        0x28, 0xb7, 0xc0, 0x3b, 0x3c, 0x96, 0xc6, 0x49,
        0x3b, 0xcf, 0x86, 0x49, 0x31, 0xaf, 0x5b, 0xa3,
        0xec, 0x63, 0x10, 0xdf, 0xda, 0x2f, 0x68, 0xac,
        0x7b, 0x3a, 0x49, 0xfa, 0xe6, 0x0d, 0xfe, 0x37,
        0x17, 0x56, 0x8e, 0x5c, 0x48, 0x97, 0x43, 0xf7,
        0xa0, 0xbc, 0xe3, 0x4b, 0x42, 0xde, 0x58, 0x1d,
        0xd9, 0x5d, 0xb3, 0x08, 0x35, 0xbd, 0xa4, 0xe1,
        0x80, 0xc3, 0x64, 0xab, 0x21, 0x97, 0xad, 0xfb,
        0x71, 0xee, 0xa3, 0x3d, 0x9c, 0xaa, 0xfa, 0x16,
        0x60, 0x46, 0x32, 0xda, 0x44, 0x2e, 0x10, 0x92,
        0x20, 0xd8, 0x98, 0x80, 0x84, 0x75, 0x5b, 0x70,
        0x91, 0x00, 0x33, 0x19, 0x69, 0xc9, 0x2a, 0xec,
        0x3d, 0xe5, 0x5f, 0x0f, 0x9a, 0xa7, 0x97, 0x1f,
        0x79, 0xc3, 0x1d, 0x65, 0x74, 0x62, 0xc5, 0xa1,
        0x23, 0x65, 0x4b, 0x84, 0xa1, 0x03, 0x98, 0xf3,
        0xf1, 0x02, 0x24, 0xca, 0xe5, 0xd4, 0xc8, 0xa2,
        0x30, 0xad, 0x72, 0x7d, 0x29, 0x60, 0x1a, 0x8e,
        0x6f, 0x23, 0xa4, 0xda, 0x68, 0xa4, 0x45, 0x9c,
        0x39, 0x70, 0x44, 0x18, 0x4b, 0x73, 0xfe, 0xf8,
        0x33, 0x53, 0x1d, 0x7e, 0x93, 0x93, 0xac, 0xc7,
        0x1e, 0x6e, 0x6b, 0xfd, 0x9e, 0xba, 0xa6, 0x71,
        0x70, 0x47, 0x6a, 0xd6, 0x82, 0x32, 0xa2, 0x6e,
        0x20, 0x72, 0xb0, 0xba, 0xec, 0x91, 0xbb, 0x6b,
        0xcc, 0x84, 0x0a, 0x33, 0x2b, 0x8a, 0x8d, 0xeb,
        0x71, 0xcd, 0xca, 0x67, 0x1b, 0xad, 0x10, 0xd4,
        0xce, 0x4f, 0xc0, 0x29, 0xec, 0xfa, 0xed, 0xfa
    };

    /* RSA Known Signed Hash (2048-bits). */
    static const PRUint8 rsa_known_sha512_signature[] = {
        0x35, 0x0e, 0x74, 0x9d, 0xeb, 0xc7, 0x67, 0x31,
        0x9f, 0xff, 0x0b, 0xbb, 0x5e, 0x66, 0xb4, 0x2f,
        0xbf, 0x72, 0x60, 0x4f, 0xe9, 0xbd, 0xec, 0xc8,
        0x17, 0x79, 0x5f, 0x39, 0x83, 0xb4, 0x54, 0x2e,
        0x01, 0xb9, 0xd3, 0x20, 0x47, 0xcb, 0xd4, 0x42,
        0xf2, 0x6e, 0x36, 0xc1, 0x97, 0xad, 0xef, 0x8e,
        0xe6, 0x51, 0xee, 0x5e, 0x9e, 0x88, 0xb4, 0x9d,
        0xda, 0x3e, 0x77, 0x4b, 0xe8, 0xae, 0x48, 0x53,
        0x2c, 0xc4, 0xd3, 0x25, 0x6b, 0x23, 0xb7, 0x54,
        0x3c, 0x95, 0x8f, 0xfb, 0x6f, 0x6d, 0xc5, 0x56,
        0x39, 0x69, 0x28, 0x0e, 0x74, 0x9b, 0x31, 0xe8,
        0x76, 0x77, 0x2b, 0xc1, 0x44, 0x89, 0x81, 0x93,
        0xfc, 0xf6, 0xec, 0x5f, 0x8f, 0x89, 0xfc, 0x1d,
        0xa4, 0x53, 0x58, 0x8c, 0xe9, 0xc0, 0xc0, 0x26,
        0xe6, 0xdf, 0x6d, 0x27, 0xb1, 0x8e, 0x3e, 0xb6,
        0x47, 0xe1, 0x02, 0x96, 0xc2, 0x5f, 0x7f, 0x3d,
        0xc5, 0x6c, 0x2f, 0xea, 0xaa, 0x5e, 0x39, 0xfc,
        0x77, 0xca, 0x00, 0x02, 0x5c, 0x64, 0x7c, 0xce,
        0x7d, 0x63, 0x82, 0x05, 0xed, 0xf7, 0x5b, 0x55,
        0x58, 0xc0, 0xeb, 0x76, 0xd7, 0x95, 0x55, 0x37,
        0x85, 0x7d, 0x17, 0xad, 0xd2, 0x11, 0xfd, 0x97,
        0x48, 0xb5, 0xc2, 0x5e, 0xc7, 0x62, 0xc0, 0xe0,
        0x68, 0xa8, 0x61, 0x14, 0x41, 0xca, 0x25, 0x3a,
        0xec, 0x48, 0x54, 0x22, 0x83, 0x2b, 0x69, 0x54,
        0xfd, 0xc8, 0x99, 0x9a, 0xee, 0x37, 0x03, 0xa3,
        0x8f, 0x0f, 0x32, 0xb0, 0xaa, 0x74, 0x39, 0x04,
        0x7c, 0xd9, 0xc2, 0x8f, 0xbe, 0xf2, 0xc4, 0xbe,
        0xdd, 0x7a, 0x7a, 0x7f, 0x72, 0xd3, 0x80, 0x59,
        0x18, 0xa0, 0xa1, 0x2d, 0x6f, 0xa3, 0xa9, 0x48,
        0xed, 0x20, 0xa6, 0xea, 0xaa, 0x10, 0x83, 0x98,
        0x0c, 0x13, 0x69, 0x6e, 0xcd, 0x31, 0x6b, 0xd0,
        0x66, 0xa6, 0x5e, 0x30, 0x0c, 0x82, 0xd5, 0x81
    };

    static const RSAPublicKey bl_public_key = {
        NULL,
        { FIPS_RSA_TYPE, (unsigned char *)rsa_modulus,
          FIPS_RSA_MODULUS_LENGTH },
        { FIPS_RSA_TYPE, (unsigned char *)rsa_public_exponent,
          FIPS_RSA_PUBLIC_EXPONENT_LENGTH }
    };
    static const RSAPrivateKey bl_private_key = {
        NULL,
        { FIPS_RSA_TYPE, (unsigned char *)rsa_version,
          FIPS_RSA_PRIVATE_VERSION_LENGTH },
        { FIPS_RSA_TYPE, (unsigned char *)rsa_modulus,
          FIPS_RSA_MODULUS_LENGTH },
        { FIPS_RSA_TYPE, (unsigned char *)rsa_public_exponent,
          FIPS_RSA_PUBLIC_EXPONENT_LENGTH },
        { FIPS_RSA_TYPE, (unsigned char *)rsa_private_exponent,
          FIPS_RSA_PRIVATE_EXPONENT_LENGTH },
        { FIPS_RSA_TYPE, (unsigned char *)rsa_prime0,
          FIPS_RSA_PRIME0_LENGTH },
        { FIPS_RSA_TYPE, (unsigned char *)rsa_prime1,
          FIPS_RSA_PRIME1_LENGTH },
        { FIPS_RSA_TYPE, (unsigned char *)rsa_exponent0,
          FIPS_RSA_EXPONENT0_LENGTH },
        { FIPS_RSA_TYPE, (unsigned char *)rsa_exponent1,
          FIPS_RSA_EXPONENT1_LENGTH },
        { FIPS_RSA_TYPE, (unsigned char *)rsa_coefficient,
          FIPS_RSA_COEFFICIENT_LENGTH }
    };

/* RSA variables. */
#ifdef CREATE_TEMP_ARENAS
    PLArenaPool *rsa_public_arena;
    PLArenaPool *rsa_private_arena;
#endif
    NSSLOWKEYPublicKey *rsa_public_key;
    NSSLOWKEYPrivateKey *rsa_private_key;
    SECStatus rsa_status;

    NSSLOWKEYPublicKey low_public_key = { NULL, NSSLOWKEYRSAKey };
    NSSLOWKEYPrivateKey low_private_key = { NULL, NSSLOWKEYRSAKey };

    /****************************************/
    /* Compose RSA Public/Private Key Pair. */
    /****************************************/

    low_public_key.u.rsa = bl_public_key;
    low_private_key.u.rsa = bl_private_key;

    rsa_public_key = &low_public_key;
    rsa_private_key = &low_private_key;

#ifdef CREATE_TEMP_ARENAS
    /* Create some space for the RSA public key. */
    rsa_public_arena = PORT_NewArena(NSS_SOFTOKEN_DEFAULT_CHUNKSIZE);

    if (rsa_public_arena == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return (SECFailure);
    }

    /* Create some space for the RSA private key. */
    rsa_private_arena = PORT_NewArena(NSS_SOFTOKEN_DEFAULT_CHUNKSIZE);

    if (rsa_private_arena == NULL) {
        PORT_FreeArena(rsa_public_arena, PR_TRUE);
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return (SECFailure);
    }

    rsa_public_key->arena = rsa_public_arena;
    rsa_private_key->arena = rsa_private_arena;
#endif

    /**************************************************/
    /* RSA Hash tests                                 */
    /**************************************************/

    rsa_status = sftk_fips_RSA_PowerUpSigSelfTest(HASH_AlgSHA256,
                                                  rsa_public_key, rsa_private_key,
                                                  rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
                                                  rsa_known_sha256_signature);
    if (rsa_status != SECSuccess)
        goto rsa_loser;

    rsa_status = sftk_fips_RSA_PowerUpSigSelfTest(HASH_AlgSHA384,
                                                  rsa_public_key, rsa_private_key,
                                                  rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
                                                  rsa_known_sha384_signature);
    if (rsa_status != SECSuccess)
        goto rsa_loser;

    rsa_status = sftk_fips_RSA_PowerUpSigSelfTest(HASH_AlgSHA512,
                                                  rsa_public_key, rsa_private_key,
                                                  rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
                                                  rsa_known_sha512_signature);
    if (rsa_status != SECSuccess)
        goto rsa_loser;

    /* Dispose of all RSA key material. */
    nsslowkey_DestroyPublicKey(rsa_public_key);
    nsslowkey_DestroyPrivateKey(rsa_private_key);

    return (SECSuccess);

rsa_loser:

    nsslowkey_DestroyPublicKey(rsa_public_key);
    nsslowkey_DestroyPrivateKey(rsa_private_key);

    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
    return (SECFailure);
}

static SECStatus
sftk_fips_HKDF_PowerUpSelfTest(void)
{
    SECStatus status;
    static const unsigned char base_key[] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
        0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
        0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
        0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
    };
    static const unsigned char known_hkdf_sha256_key[] = {
        0xdd, 0xdb, 0xeb, 0xe5, 0x6d, 0xd2, 0x96, 0xa4,
        0x07, 0xc5, 0x7d, 0xda, 0x31, 0x56, 0x8d, 0xa5,
        0x41, 0x3e, 0x90, 0xd4, 0xe6, 0x98, 0xeb, 0xf8,
        0x5a, 0x49, 0x7f, 0x38, 0xef, 0x01, 0x8a, 0xe5,
        0xda, 0x36, 0xe5, 0xcf, 0x21, 0xe3, 0x9f, 0xc3,
        0x32, 0xb3, 0x1e, 0xf6, 0xc5, 0x10, 0x4c, 0x86,
        0x53, 0x5e, 0x6f, 0xe0, 0x63, 0x6e, 0x43, 0x33,
        0x61, 0x35, 0xf4, 0x17, 0x10, 0x77, 0x75, 0x2a
    };
/* current NIST IG's say we only need to test one instance
 * of kdfs, keep these others around in case the guidance
 * changes */
#ifdef NSS_FULL_POST
    static const unsigned char known_hkdf_sha384_key[] = {
        0x35, 0x64, 0xc4, 0xa1, 0xcc, 0xc1, 0xdc, 0xe4,
        0xe2, 0xca, 0x51, 0xae, 0xe8, 0x92, 0x88, 0x30,
        0x8b, 0xb0, 0x2b, 0xac, 0x00, 0x15, 0xac, 0x15,
        0x97, 0xc9, 0xf4, 0x6b, 0xf6, 0x3f, 0x97, 0xea,
        0x48, 0x55, 0x38, 0x25, 0x06, 0x5d, 0x91, 0x64,
        0xbd, 0x09, 0xf3, 0x44, 0xbc, 0x82, 0xbe, 0xdb,
        0x5c, 0xd7, 0xf2, 0x24, 0xa5, 0x55, 0x8d, 0xa9,
        0xa8, 0x85, 0xde, 0x8c, 0x33, 0xe0, 0x4d, 0xc3
    };
    static const unsigned char known_hkdf_sha512_key[] = {
        0x63, 0x4e, 0xbc, 0x42, 0xb3, 0x56, 0x74, 0x7d,
        0x1b, 0x55, 0xf0, 0x34, 0x54, 0xcb, 0x6d, 0x58,
        0x39, 0x96, 0x10, 0xda, 0x03, 0x20, 0x8f, 0x77,
        0x0d, 0xb4, 0xf7, 0xf6, 0x67, 0x0d, 0x5b, 0x6b,
        0xd0, 0x30, 0xc4, 0xdd, 0x67, 0x61, 0x5d, 0x9a,
        0xf5, 0x18, 0x6e, 0x1b, 0x60, 0x97, 0xc2, 0x4d,
        0x23, 0x43, 0x69, 0xe6, 0x3b, 0xa5, 0xdf, 0xe9,
        0x7c, 0xf1, 0x87, 0x48, 0x6f, 0xb9, 0xd3, 0x02
    };
#endif
    unsigned char outBytes[64] = { 0 };

    CK_HKDF_PARAMS hkdf_params;

    hkdf_params.bExpand = CK_TRUE;
    hkdf_params.bExtract = CK_TRUE;
    hkdf_params.ulSaltType = CKF_HKDF_SALT_DATA;
    hkdf_params.pSalt = (CK_BYTE_PTR)base_key;
    hkdf_params.ulSaltLen = sizeof(base_key);
    hkdf_params.pInfo = (CK_BYTE_PTR)base_key;
    hkdf_params.ulInfoLen = sizeof(base_key);

    /**************************************************/
    /* HKDF tests                                     */
    /**************************************************/

    hkdf_params.prfHashMechanism = CKM_SHA256_HMAC;
    status = sftk_HKDF(&hkdf_params, CK_INVALID_HANDLE, NULL,
                       base_key, 32, NULL, outBytes, sizeof(outBytes),
                       PR_TRUE, PR_TRUE);
    if ((status != SECSuccess) ||
        PORT_Memcmp(outBytes, known_hkdf_sha256_key, sizeof(outBytes)) != 0) {
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
        return (SECFailure);
    }

#ifdef NSS_FULL_POST
    hkdf_params.prfHashMechanism = CKM_SHA384_HMAC;
    status = sftk_HKDF(&hkdf_params, CK_INVALID_HANDLE, NULL,
                       base_key, 48, NULL, outBytes, sizeof(outBytes),
                       PR_TRUE, PR_TRUE);
    if ((status != SECSuccess) ||
        PORT_Memcmp(outBytes, known_hkdf_sha384_key, sizeof(outBytes)) != 0) {
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
        return (SECFailure);
    }

    hkdf_params.prfHashMechanism = CKM_SHA512_HMAC;
    status = sftk_HKDF(&hkdf_params, CK_INVALID_HANDLE, NULL,
                       base_key, 64, NULL, outBytes, sizeof(outBytes),
                       PR_TRUE, PR_TRUE);
    if ((status != SECSuccess) ||
        PORT_Memcmp(outBytes, known_hkdf_sha512_key, sizeof(outBytes)) != 0) {
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
        return (SECFailure);
    }
#endif

    return (SECSuccess);
}

static PRBool sftk_self_tests_ran = PR_FALSE;
static PRBool sftk_self_tests_success = PR_FALSE;

/*
 * This function is called at dll load time, the code tha makes this
 * happen is platform specific on defined above.
 */
static void
sftk_startup_tests(void)
{
    SECStatus rv;
    const char *libraryName = SOFTOKEN_LIB_NAME;

    PORT_Assert(!sftk_self_tests_ran);
    PORT_Assert(!sftk_self_tests_success);
    sftk_self_tests_ran = PR_TRUE;
    sftk_self_tests_success = PR_FALSE; /* just in case */

    /* need to initiallize the oid library before the RSA tests */
    rv = SECOID_Init();
    if (rv != SECSuccess) {
        return;
    }
    /* make sure freebl is initialized, or our RSA check
     * may fail. This is normally done at freebl load time, but it's
     * possible we may have shut freebl down without unloading it. */
    rv = BL_Init();
    if (rv != SECSuccess) {
        return;
    }

    rv = RNG_RNGInit();
    if (rv != SECSuccess) {
        return;
    }
    /* check the RSA combined functions in softoken */
    rv = sftk_fips_RSA_PowerUpSelfTest();
    if (rv != SECSuccess) {
        return;
    }
    if (!BLAPI_SHVerify(libraryName,
                        (PRFuncPtr)&sftk_fips_RSA_PowerUpSelfTest)) {
        /* something is wrong with the library, fail without enabling
         * the token */
        return;
    }
    rv = sftk_fips_IKE_PowerUpSelfTests();
    if (rv != SECSuccess) {
        return;
    }

    rv = sftk_fips_SP800_108_PowerUpSelfTests();
    if (rv != SECSuccess) {
        return;
    }

    rv = sftk_fips_HKDF_PowerUpSelfTest();
    if (rv != SECSuccess) {
        return;
    }

    rv = sftk_fips_pbkdf_PowerUpSelfTests();
    if (rv != SECSuccess) {
        return;
    }

    sftk_self_tests_success = PR_TRUE;
}

/*
 * this is called from nsc_Common_Initizialize entry points that gates access
 * to * all other pkcs11 functions. This prevents softoken operation if our
 * power on selftest failed.
 */
CK_RV
sftk_FIPSEntryOK()
{
#ifdef NSS_NO_INIT_SUPPORT
    /* this should only be set on platforms that can't handle one of the INIT
     * schemes.  This code allows those platforms to continue to function,
     * though they don't meet the strict NIST requirements. If NSS_NO_INIT_SUPPORT
     * is not set, and init support has not been properly enabled, softken
     * will always fail because of the test below
     */
    if (!sftk_self_tests_ran) {
        sftk_startup_tests();
    }
#endif
    if (!sftk_self_tests_success) {
        return CKR_DEVICE_ERROR;
    }
    return CKR_OK;
}
#else
#include "pkcs11t.h"
CK_RV
sftk_FIPSEntryOK()
{
    return CKR_DEVICE_ERROR;
}
#endif /* NSS_FIPS_DISABLED */