summaryrefslogtreecommitdiffstats
path: root/security/nss/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/cmd')
-rw-r--r--security/nss/cmd/Makefile44
-rw-r--r--security/nss/cmd/addbuiltin/Makefile48
-rw-r--r--security/nss/cmd/addbuiltin/addbuiltin.c546
-rw-r--r--security/nss/cmd/addbuiltin/addbuiltin.gyp24
-rw-r--r--security/nss/cmd/addbuiltin/manifest.mn20
-rw-r--r--security/nss/cmd/atob/Makefile48
-rw-r--r--security/nss/cmd/atob/atob.c174
-rw-r--r--security/nss/cmd/atob/atob.gyp30
-rw-r--r--security/nss/cmd/atob/manifest.mn22
-rw-r--r--security/nss/cmd/bltest/Makefile54
-rw-r--r--security/nss/cmd/bltest/blapitest.c4235
-rw-r--r--security/nss/cmd/bltest/bltest.gyp35
-rw-r--r--security/nss/cmd/bltest/manifest.mn26
-rw-r--r--security/nss/cmd/bltest/pkcs1_vectors.h789
-rw-r--r--security/nss/cmd/bltest/tests/README56
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext103
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext113
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext124
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext131
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext142
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext152
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext163
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext173
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext184
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext191
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext21
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext202
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext212
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext223
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext233
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext244
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext31
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext41
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext51
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext61
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext71
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext82
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext92
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv01
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv1bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv101
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv111
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv121
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv131
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv141
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv151
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv161
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv171
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv181
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv191
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv2bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv201
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv212
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv221
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv23bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv241
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv3bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv4bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv5bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv6bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv71
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv81
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv91
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key01
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key1bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key101
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key111
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key121
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key131
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key141
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key151
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key16bin0 -> 24 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key171
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key181
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key191
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key2bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key201
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key212
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key221
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key231
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key241
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key3bin0 -> 24 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key4bin0 -> 24 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key5bin0 -> 32 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key6bin0 -> 32 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key7bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key81
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key91
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/mktst.sh11
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext102
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext111
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext121
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext131
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext141
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext151
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext161
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext172
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext18bin0 -> 160 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext19bin0 -> 32 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext21
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext201
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext211
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext22bin0 -> 128 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext23bin0 -> 144 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext24bin0 -> 160 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext31
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext41
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext52
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext61
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext71
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext81
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext92
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test1.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test10.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test11.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test12.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test13.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test14.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test15.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test16.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test17.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test18.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test19.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test2.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test20.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test21.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test22.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test23.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test24.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test3.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test4.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test5.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test6.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test7.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test8.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/test9.txt5
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_0.txt28
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_1.txt28
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_2.txt28
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_tests_source.txt199
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/ciphertext02
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/ciphertext12
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/ciphertext22
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/iv01
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/iv11
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/iv21
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/key01
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/key11
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/key21
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/mktst.sh9
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/plaintext02
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/plaintext12
-rw-r--r--security/nss/cmd/bltest/tests/aes_ctr/plaintext22
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/aes-cts-type-1-vectors.txt47
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/aes_cts_0.txt6
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/aes_cts_1.txt6
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/aes_cts_2.txt6
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/aes_cts_3.txt6
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/aes_cts_4.txt6
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/aes_cts_5.txt6
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/ciphertext21
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/ciphertext31
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/ciphertext41
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/ciphertext52
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/iv0bin0 -> 34 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/iv1bin0 -> 34 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/iv2bin0 -> 34 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/iv3bin0 -> 34 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/iv4bin0 -> 34 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/iv5bin0 -> 34 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/key01
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/key11
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/key21
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/key31
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/key41
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/key51
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/mktst.sh9
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/plaintext21
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/plaintext31
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/plaintext41
-rw-r--r--security/nss/cmd/bltest/tests/aes_cts/plaintext51
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/ciphertext21
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/ciphertext31
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/ciphertext41
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/ciphertext51
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/ciphertext61
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/key01
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/key1bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/key2bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/key3bin0 -> 24 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/key4bin0 -> 24 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/key5bin0 -> 32 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/key6bin0 -> 32 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/mktst.sh10
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/plaintext21
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/plaintext31
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/plaintext41
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/plaintext52
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/plaintext61
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/test1.txt4
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/test2.txt4
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/test3.txt4
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/test4.txt4
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/test5.txt4
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/test6.txt4
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad00
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad10
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad101
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad111
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad120
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad130
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad140
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad151
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad161
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad171
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad20
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad31
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad41
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad51
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad60
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad70
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad80
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/aad91
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext102
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext112
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext121
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext131
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext142
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext152
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext162
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext172
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext22
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext32
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext42
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext52
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext61
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext71
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext82
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/ciphertext92
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/hex.c78
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv0bin0 -> 12 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv1bin0 -> 12 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv101
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv111
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv12bin0 -> 12 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv13bin0 -> 12 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv141
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv151
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv161
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv171
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv21
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv31
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv41
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv51
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv6bin0 -> 12 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv7bin0 -> 12 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv81
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/iv91
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key0bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key1bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key101
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key111
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key12bin0 -> 32 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key13bin0 -> 32 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key141
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key151
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key161
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key171
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key21
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key31
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key41
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key51
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key6bin0 -> 24 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key7bin0 -> 24 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key81
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/key91
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/mktst.sh13
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext00
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext1bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext101
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext111
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext120
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext13bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext141
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext151
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext161
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext171
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext21
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext31
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext41
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext51
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext60
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext7bin0 -> 16 bytes
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext81
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/plaintext91
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test0.txt11
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test1.txt14
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test10.txt28
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test11.txt31
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test12.txt11
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test13.txt14
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test14.txt23
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test15.txt26
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test16.txt28
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test17.txt31
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test2.txt23
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test3.txt26
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test4.txt28
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test5.txt31
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test6.txt11
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test7.txt14
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test8.txt23
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test9.txt26
-rw-r--r--security/nss/cmd/bltest/tests/aes_gcm/test_source.txt439
-rw-r--r--security/nss/cmd/bltest/tests/camellia_cbc/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/camellia_cbc/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/camellia_cbc/ciphertext21
-rw-r--r--security/nss/cmd/bltest/tests/camellia_cbc/iv01
-rw-r--r--security/nss/cmd/bltest/tests/camellia_cbc/key01
-rw-r--r--security/nss/cmd/bltest/tests/camellia_cbc/key11
-rw-r--r--security/nss/cmd/bltest/tests/camellia_cbc/key21
-rw-r--r--security/nss/cmd/bltest/tests/camellia_cbc/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/camellia_cbc/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/camellia_ecb/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/camellia_ecb/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/camellia_ecb/ciphertext21
-rw-r--r--security/nss/cmd/bltest/tests/camellia_ecb/key01
-rw-r--r--security/nss/cmd/bltest/tests/camellia_ecb/key11
-rw-r--r--security/nss/cmd/bltest/tests/camellia_ecb/key21
-rw-r--r--security/nss/cmd/bltest/tests/camellia_ecb/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/camellia_ecb/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/chacha20_poly1305/aad01
-rw-r--r--security/nss/cmd/bltest/tests/chacha20_poly1305/aad1bin0 -> 12 bytes
-rw-r--r--security/nss/cmd/bltest/tests/chacha20_poly1305/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/chacha20_poly1305/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/chacha20_poly1305/iv0bin0 -> 12 bytes
-rw-r--r--security/nss/cmd/bltest/tests/chacha20_poly1305/iv1bin0 -> 12 bytes
-rw-r--r--security/nss/cmd/bltest/tests/chacha20_poly1305/key01
-rw-r--r--security/nss/cmd/bltest/tests/chacha20_poly1305/key11
-rw-r--r--security/nss/cmd/bltest/tests/chacha20_poly1305/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/chacha20_poly1305/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/chacha20_poly1305/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/des3_cbc/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/des3_cbc/iv01
-rw-r--r--security/nss/cmd/bltest/tests/des3_cbc/key01
-rw-r--r--security/nss/cmd/bltest/tests/des3_cbc/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/des3_cbc/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/des3_ecb/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/des3_ecb/key01
-rw-r--r--security/nss/cmd/bltest/tests/des3_ecb/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/des3_ecb/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/des_cbc/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/des_cbc/iv01
-rw-r--r--security/nss/cmd/bltest/tests/des_cbc/key01
-rw-r--r--security/nss/cmd/bltest/tests/des_cbc/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/des_cbc/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/des_ecb/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/des_ecb/key01
-rw-r--r--security/nss/cmd/bltest/tests/des_ecb/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/des_ecb/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext102
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext112
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext122
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext132
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext142
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext152
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext162
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext172
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext182
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext192
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext21
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext202
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext31
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext41
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext51
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext62
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext72
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext82
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext92
-rw-r--r--security/nss/cmd/bltest/tests/dsa/dsa_fips.txt248
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key06
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key110
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key1018
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key1118
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key1218
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key1318
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key1418
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key1518
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key1626
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key1726
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key1826
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key1926
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key210
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key2026
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key310
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key410
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key510
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key618
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key718
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key818
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key918
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed01
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed11
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed101
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed111
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed121
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed131
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed141
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed151
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed161
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed171
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed181
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed191
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed21
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed201
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed31
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed41
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed51
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed61
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed71
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed81
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed91
-rw-r--r--security/nss/cmd/bltest/tests/dsa/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext102
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext111
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext121
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext131
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext141
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext152
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext161
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext171
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext181
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext191
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext21
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext202
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext31
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext41
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext52
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext61
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext71
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext81
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext91
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg04
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg16
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg1012
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg1112
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg1212
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg1312
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg1412
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg1512
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg1617
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg1717
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg1817
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg1917
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg26
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg2017
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg36
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg46
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg56
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg612
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg712
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg812
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg912
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed01
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed11
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed101
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed111
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed121
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed131
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed141
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed151
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed161
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed171
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed181
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed191
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed21
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed201
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed31
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed41
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed51
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed61
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed71
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed81
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed91
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/README4
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext102
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext112
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext122
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext132
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext142
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext152
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext163
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext173
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext183
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext193
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext21
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext203
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext31
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext41
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext51
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext61
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext71
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext82
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext92
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key03
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key14
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key25
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext101
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext111
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext121
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext131
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext141
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext151
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext161
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext171
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext181
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext191
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext21
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext201
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext31
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext41
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext51
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext61
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext71
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext81
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext91
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed01
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed11
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed101
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed111
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed121
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed131
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed141
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed151
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed161
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed171
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed182
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed192
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed21
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed202
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed31
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed41
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed51
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed61
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed71
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed81
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed91
-rw-r--r--security/nss/cmd/bltest/tests/md2/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/md2/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/md2/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/md5/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/md5/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/md5/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/rc2_cbc/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/rc2_cbc/iv01
-rw-r--r--security/nss/cmd/bltest/tests/rc2_cbc/key01
-rw-r--r--security/nss/cmd/bltest/tests/rc2_cbc/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/rc2_cbc/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/rc2_ecb/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/rc2_ecb/key01
-rw-r--r--security/nss/cmd/bltest/tests/rc2_ecb/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/rc2_ecb/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/rc4/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/rc4/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/rc4/key01
-rw-r--r--security/nss/cmd/bltest/tests/rc4/key11
-rw-r--r--security/nss/cmd/bltest/tests/rc4/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/rc4/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/rc4/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/rc5_cbc/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/rc5_cbc/iv01
-rw-r--r--security/nss/cmd/bltest/tests/rc5_cbc/key01
-rw-r--r--security/nss/cmd/bltest/tests/rc5_cbc/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/rc5_cbc/params02
-rw-r--r--security/nss/cmd/bltest/tests/rc5_cbc/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/rc5_ecb/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/rc5_ecb/key01
-rw-r--r--security/nss/cmd/bltest/tests/rc5_ecb/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/rc5_ecb/params02
-rw-r--r--security/nss/cmd/bltest/tests/rc5_ecb/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/rsa/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/rsa/key04
-rw-r--r--security/nss/cmd/bltest/tests/rsa/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/rsa/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext03
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext13
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext104
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext114
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext125
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext135
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext145
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext155
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext165
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext175
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext23
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext33
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext43
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext53
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext64
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext74
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext84
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/ciphertext94
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash01
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash11
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash101
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash111
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash121
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash131
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash141
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash151
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash161
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash171
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash31
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash41
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash51
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash61
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash71
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash81
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/hash91
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key01
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key11
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key101
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key111
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key121
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key131
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key141
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key151
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key161
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key171
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key31
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key41
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key51
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key61
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key71
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key81
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/key91
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash01
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash11
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash101
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash111
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash121
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash131
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash141
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash151
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash161
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash171
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash31
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash41
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash51
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash61
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash71
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash81
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/maskhash91
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext0bin0 -> 28 bytes
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext101
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext111
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext121
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext131
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext142
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext15bin0 -> 36 bytes
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext161
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext171
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext31
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext41
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext51
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext61
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext71
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext81
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/plaintext93
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed01
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed11
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed101
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed111
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed121
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed131
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed141
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed151
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed161
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed171
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed31
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed41
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed51
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed61
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed71
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed81
-rw-r--r--security/nss/cmd/bltest/tests/rsa_oaep/seed91
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext03
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext13
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext104
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext114
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext125
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext135
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext145
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext155
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext165
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext175
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext23
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext33
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext43
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext53
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext64
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext74
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext84
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext94
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash01
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash11
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash101
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash111
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash121
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash131
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash141
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash151
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash161
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash171
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash31
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash41
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash51
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash61
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash71
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash81
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash91
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key01
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key11
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key101
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key111
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key121
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key131
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key141
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key151
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key161
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key171
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key31
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key41
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key51
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key61
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key71
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key81
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key91
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash01
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash11
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash101
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash111
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash121
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash131
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash141
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash151
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash161
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash171
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash31
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash41
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash51
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash61
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash71
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash81
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash91
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext101
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext111
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext121
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext131
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext141
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext151
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext161
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext171
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext31
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext41
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext51
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext61
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext71
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext81
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext91
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed01
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed11
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed101
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed111
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed121
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed131
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed141
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed151
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed161
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed171
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed31
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed41
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed51
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed61
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed71
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed81
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed91
-rw-r--r--security/nss/cmd/bltest/tests/seed_cbc/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/seed_cbc/iv01
-rw-r--r--security/nss/cmd/bltest/tests/seed_cbc/key01
-rw-r--r--security/nss/cmd/bltest/tests/seed_cbc/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/seed_cbc/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/seed_ecb/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/seed_ecb/iv01
-rw-r--r--security/nss/cmd/bltest/tests/seed_ecb/key01
-rw-r--r--security/nss/cmd/bltest/tests/seed_ecb/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/seed_ecb/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha1/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/sha1/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/sha1/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha224/ciphertext02
-rw-r--r--security/nss/cmd/bltest/tests/sha224/ciphertext12
-rw-r--r--security/nss/cmd/bltest/tests/sha224/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/sha224/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha224/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/sha256/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/sha256/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/sha256/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/sha256/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha256/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/sha384/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/sha384/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/sha384/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/sha384/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha384/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/sha512/ciphertext02
-rw-r--r--security/nss/cmd/bltest/tests/sha512/ciphertext12
-rw-r--r--security/nss/cmd/bltest/tests/sha512/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/sha512/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha512/plaintext11
-rw-r--r--security/nss/cmd/btoa/Makefile47
-rw-r--r--security/nss/cmd/btoa/btoa.c203
-rw-r--r--security/nss/cmd/btoa/btoa.gyp30
-rw-r--r--security/nss/cmd/btoa/manifest.mn21
-rw-r--r--security/nss/cmd/certcgi/HOWTO.txt137
-rw-r--r--security/nss/cmd/certcgi/Makefile48
-rw-r--r--security/nss/cmd/certcgi/ca.html19
-rw-r--r--security/nss/cmd/certcgi/ca_form.html357
-rw-r--r--security/nss/cmd/certcgi/certcgi.c2246
-rw-r--r--security/nss/cmd/certcgi/certcgi.gyp33
-rw-r--r--security/nss/cmd/certcgi/index.html789
-rw-r--r--security/nss/cmd/certcgi/main.html76
-rw-r--r--security/nss/cmd/certcgi/manifest.mn22
-rw-r--r--security/nss/cmd/certcgi/nscp_ext_form.html84
-rw-r--r--security/nss/cmd/certcgi/stnd_ext_form.html219
-rw-r--r--security/nss/cmd/certutil/Makefile48
-rw-r--r--security/nss/cmd/certutil/certext.c2218
-rw-r--r--security/nss/cmd/certutil/certutil.c3707
-rw-r--r--security/nss/cmd/certutil/certutil.gyp32
-rw-r--r--security/nss/cmd/certutil/certutil.h57
-rw-r--r--security/nss/cmd/certutil/keystuff.c608
-rw-r--r--security/nss/cmd/certutil/manifest.mn25
-rw-r--r--security/nss/cmd/chktest/Makefile47
-rw-r--r--security/nss/cmd/chktest/chktest.c45
-rw-r--r--security/nss/cmd/chktest/chktest.gyp32
-rw-r--r--security/nss/cmd/chktest/manifest.mn27
-rw-r--r--security/nss/cmd/crlutil/Makefile53
-rw-r--r--security/nss/cmd/crlutil/crlgen.c1542
-rw-r--r--security/nss/cmd/crlutil/crlgen.h178
-rw-r--r--security/nss/cmd/crlutil/crlgen_lex.c1773
-rw-r--r--security/nss/cmd/crlutil/crlgen_lex_fix.sed6
-rw-r--r--security/nss/cmd/crlutil/crlgen_lex_orig.l181
-rw-r--r--security/nss/cmd/crlutil/crlutil.c1153
-rw-r--r--security/nss/cmd/crlutil/crlutil.gyp32
-rw-r--r--security/nss/cmd/crlutil/manifest.mn25
-rw-r--r--security/nss/cmd/crmf-cgi/Makefile53
-rw-r--r--security/nss/cmd/crmf-cgi/config.mk16
-rw-r--r--security/nss/cmd/crmf-cgi/crmfcgi.c1090
-rw-r--r--security/nss/cmd/crmf-cgi/crmfcgi.html136
-rw-r--r--security/nss/cmd/crmf-cgi/manifest.mn33
-rw-r--r--security/nss/cmd/crmftest/Makefile64
-rw-r--r--security/nss/cmd/crmftest/config.mk15
-rw-r--r--security/nss/cmd/crmftest/crmftest.gyp25
-rw-r--r--security/nss/cmd/crmftest/manifest.mn25
-rw-r--r--security/nss/cmd/crmftest/testcrmf.c1654
-rw-r--r--security/nss/cmd/dbck/Makefile47
-rw-r--r--security/nss/cmd/dbck/dbck.c1350
-rw-r--r--security/nss/cmd/dbck/dbrecover.c668
-rw-r--r--security/nss/cmd/dbck/manifest.mn22
-rw-r--r--security/nss/cmd/dbtest/Makefile46
-rw-r--r--security/nss/cmd/dbtest/dbtest.c244
-rw-r--r--security/nss/cmd/dbtest/dbtest.gyp25
-rw-r--r--security/nss/cmd/dbtest/manifest.mn22
-rw-r--r--security/nss/cmd/derdump/Makefile48
-rw-r--r--security/nss/cmd/derdump/derdump.c128
-rw-r--r--security/nss/cmd/derdump/derdump.gyp30
-rw-r--r--security/nss/cmd/derdump/manifest.mn21
-rw-r--r--security/nss/cmd/digest/Makefile48
-rw-r--r--security/nss/cmd/digest/digest.c228
-rw-r--r--security/nss/cmd/digest/digest.gyp30
-rw-r--r--security/nss/cmd/digest/manifest.mn22
-rw-r--r--security/nss/cmd/ecperf/Makefile46
-rw-r--r--security/nss/cmd/ecperf/ecperf.c726
-rw-r--r--security/nss/cmd/ecperf/ecperf.gyp35
-rwxr-xr-xsecurity/nss/cmd/ecperf/manifest.mn18
-rw-r--r--security/nss/cmd/fbectest/Makefile46
-rw-r--r--security/nss/cmd/fbectest/fbectest.c282
-rw-r--r--security/nss/cmd/fbectest/fbectest.gyp34
-rw-r--r--security/nss/cmd/fbectest/manifest.mn18
-rw-r--r--security/nss/cmd/fbectest/testvecs.h818
-rwxr-xr-xsecurity/nss/cmd/fipstest/Makefile49
-rw-r--r--security/nss/cmd/fipstest/aes.sh112
-rw-r--r--security/nss/cmd/fipstest/aesgcm.sh67
-rwxr-xr-xsecurity/nss/cmd/fipstest/dsa.sh71
-rw-r--r--security/nss/cmd/fipstest/ecdsa.sh60
-rw-r--r--security/nss/cmd/fipstest/fipstest.c6137
-rw-r--r--security/nss/cmd/fipstest/fipstest.gyp31
-rwxr-xr-xsecurity/nss/cmd/fipstest/hmac.sh36
-rw-r--r--security/nss/cmd/fipstest/manifest.mn23
-rw-r--r--security/nss/cmd/fipstest/rng.sh34
-rw-r--r--security/nss/cmd/fipstest/rsa.sh50
-rw-r--r--security/nss/cmd/fipstest/runtest.sh17
-rw-r--r--security/nss/cmd/fipstest/sha.sh66
-rw-r--r--security/nss/cmd/fipstest/tdea.sh106
-rw-r--r--security/nss/cmd/fipstest/tls.sh34
-rw-r--r--security/nss/cmd/fipstest/validate.sh7
-rw-r--r--security/nss/cmd/fipstest/validate1.sh30
-rw-r--r--security/nss/cmd/httpserv/Makefile46
-rw-r--r--security/nss/cmd/httpserv/httpserv.c1453
-rw-r--r--security/nss/cmd/httpserv/httpserv.gyp30
-rw-r--r--security/nss/cmd/httpserv/manifest.mn20
-rw-r--r--security/nss/cmd/lib/Makefile49
-rw-r--r--security/nss/cmd/lib/basicutil.c829
-rw-r--r--security/nss/cmd/lib/basicutil.h137
-rw-r--r--security/nss/cmd/lib/berparse.c388
-rw-r--r--security/nss/cmd/lib/config.mk15
-rw-r--r--security/nss/cmd/lib/derprint.c594
-rw-r--r--security/nss/cmd/lib/exports.gyp27
-rw-r--r--security/nss/cmd/lib/ffs.c21
-rw-r--r--security/nss/cmd/lib/lib.gyp36
-rw-r--r--security/nss/cmd/lib/manifest.mn39
-rw-r--r--security/nss/cmd/lib/moreoids.c167
-rw-r--r--security/nss/cmd/lib/pk11table.c1517
-rw-r--r--security/nss/cmd/lib/pk11table.h178
-rw-r--r--security/nss/cmd/lib/pppolicy.c263
-rw-r--r--security/nss/cmd/lib/secpwd.c168
-rw-r--r--security/nss/cmd/lib/secutil.c3877
-rw-r--r--security/nss/cmd/lib/secutil.h432
-rwxr-xr-xsecurity/nss/cmd/libpkix/Makefile46
-rw-r--r--security/nss/cmd/libpkix/config.mk9
-rwxr-xr-xsecurity/nss/cmd/libpkix/manifest.mn11
-rwxr-xr-xsecurity/nss/cmd/libpkix/perf/Makefile46
-rw-r--r--security/nss/cmd/libpkix/perf/libpkix_buildthreads.c337
-rwxr-xr-xsecurity/nss/cmd/libpkix/perf/manifest.mn21
-rw-r--r--security/nss/cmd/libpkix/perf/nss_threads.c158
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/Makefile48
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/certsel/Makefile47
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/certsel/manifest.mn21
-rw-r--r--security/nss/cmd/libpkix/pkix/certsel/test_certselector.c1683
-rw-r--r--security/nss/cmd/libpkix/pkix/certsel/test_comcertselparams.c800
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/checker/Makefile47
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/checker/manifest.mn19
-rw-r--r--security/nss/cmd/libpkix/pkix/checker/test_certchainchecker.c185
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/crlsel/Makefile47
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/crlsel/manifest.mn21
-rw-r--r--security/nss/cmd/libpkix/pkix/crlsel/test_comcrlselparams.c406
-rw-r--r--security/nss/cmd/libpkix/pkix/crlsel/test_crlselector.c168
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/manifest.mn11
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/params/Makefile47
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/params/manifest.mn23
-rw-r--r--security/nss/cmd/libpkix/pkix/params/test_procparams.c478
-rw-r--r--security/nss/cmd/libpkix/pkix/params/test_resourcelimits.c99
-rw-r--r--security/nss/cmd/libpkix/pkix/params/test_trustanchor.c251
-rw-r--r--security/nss/cmd/libpkix/pkix/params/test_valparams.c261
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/results/Makefile47
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/results/manifest.mn23
-rw-r--r--security/nss/cmd/libpkix/pkix/results/test_buildresult.c212
-rw-r--r--security/nss/cmd/libpkix/pkix/results/test_policynode.c612
-rw-r--r--security/nss/cmd/libpkix/pkix/results/test_valresult.c199
-rw-r--r--security/nss/cmd/libpkix/pkix/results/test_verifynode.c112
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/store/Makefile47
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/store/manifest.mn19
-rw-r--r--security/nss/cmd/libpkix/pkix/store/test_store.c194
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/top/Makefile47
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/top/manifest.mn33
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_basicchecker.c238
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_basicconstraintschecker.c145
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_buildchain.c418
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_buildchain_partialchain.c725
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_buildchain_resourcelimits.c438
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_buildchain_uchecker.c327
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_customcrlchecker.c435
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_defaultcrlchecker2stores.c230
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_ocsp.c288
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_policychecker.c535
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_subjaltnamechecker.c261
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_validatechain.c221
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_validatechain_NB.c351
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_validatechain_bc.c233
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/util/Makefile47
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix/util/manifest.mn23
-rw-r--r--security/nss/cmd/libpkix/pkix/util/test_error.c385
-rw-r--r--security/nss/cmd/libpkix/pkix/util/test_list.c765
-rw-r--r--security/nss/cmd/libpkix/pkix/util/test_list2.c120
-rw-r--r--security/nss/cmd/libpkix/pkix/util/test_logger.c314
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix_pl/Makefile48
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix_pl/manifest.mn11
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix_pl/module/Makefile47
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix_pl/module/manifest.mn24
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/module/test_colcertstore.c247
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/module/test_ekuchecker.c275
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/module/test_httpcertstore.c300
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/module/test_pk11certstore.c580
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/module/test_socket.c571
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix_pl/pki/Makefile47
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix_pl/pki/manifest.mn28
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_authorityinfoaccess.c105
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_cert.c2088
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_crl.c302
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_crlentry.c208
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_date.c106
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_generalname.c123
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_nameconstraints.c127
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_subjectinfoaccess.c121
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_x500name.c169
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix_pl/system/Makefile47
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkix_pl/system/manifest.mn38
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/stress_test.c146
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_bigint.c190
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_bytearray.c231
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_hashtable.c380
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_mem.c133
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_monitorlock.c104
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_mutex.c102
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_mutex2.c166
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_mutex3.c104
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_object.c281
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_oid.c212
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_rwlock.c204
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_string.c434
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_string2.c337
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkixlibs.mk27
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkixrules.mk7
-rw-r--r--security/nss/cmd/libpkix/pkixutil/Makefile43
-rw-r--r--security/nss/cmd/libpkix/pkixutil/manifest.mn41
-rw-r--r--security/nss/cmd/libpkix/pkixutil/pkixutil.c299
-rwxr-xr-xsecurity/nss/cmd/libpkix/sample_apps/Makefile46
-rw-r--r--security/nss/cmd/libpkix/sample_apps/build_chain.c242
-rw-r--r--security/nss/cmd/libpkix/sample_apps/dumpcert.c182
-rw-r--r--security/nss/cmd/libpkix/sample_apps/dumpcrl.c186
-rwxr-xr-xsecurity/nss/cmd/libpkix/sample_apps/manifest.mn23
-rw-r--r--security/nss/cmd/libpkix/sample_apps/validate_chain.c220
-rwxr-xr-xsecurity/nss/cmd/libpkix/testutil/Makefile51
-rw-r--r--security/nss/cmd/libpkix/testutil/config.mk15
-rwxr-xr-xsecurity/nss/cmd/libpkix/testutil/manifest.mn26
-rw-r--r--security/nss/cmd/libpkix/testutil/pkixutil.def48
-rw-r--r--security/nss/cmd/libpkix/testutil/testutil.c576
-rw-r--r--security/nss/cmd/libpkix/testutil/testutil.h292
-rw-r--r--security/nss/cmd/libpkix/testutil/testutil_nss.c579
-rw-r--r--security/nss/cmd/libpkix/testutil/testutil_nss.h119
-rw-r--r--security/nss/cmd/listsuites/Makefile47
-rw-r--r--security/nss/cmd/listsuites/listsuites.c62
-rw-r--r--security/nss/cmd/listsuites/listsuites.gyp24
-rw-r--r--security/nss/cmd/listsuites/manifest.mn15
-rw-r--r--security/nss/cmd/lowhashtest/Makefile65
-rw-r--r--security/nss/cmd/lowhashtest/lowhashtest.c445
-rw-r--r--security/nss/cmd/lowhashtest/lowhashtest.gyp32
-rw-r--r--security/nss/cmd/lowhashtest/manifest.mn24
-rw-r--r--security/nss/cmd/makepqg/Makefile49
-rw-r--r--security/nss/cmd/makepqg/makepqg.c349
-rw-r--r--security/nss/cmd/makepqg/makepqg.gyp25
-rw-r--r--security/nss/cmd/makepqg/manifest.mn19
-rw-r--r--security/nss/cmd/makepqg/testit.ksh13
-rw-r--r--security/nss/cmd/manifest.mn108
-rw-r--r--security/nss/cmd/modutil/Makefile54
-rw-r--r--security/nss/cmd/modutil/README7
-rw-r--r--security/nss/cmd/modutil/error.h139
-rw-r--r--security/nss/cmd/modutil/install-ds.c1525
-rw-r--r--security/nss/cmd/modutil/install-ds.h260
-rw-r--r--security/nss/cmd/modutil/install.c959
-rw-r--r--security/nss/cmd/modutil/install.h100
-rw-r--r--security/nss/cmd/modutil/installparse.c434
-rw-r--r--security/nss/cmd/modutil/installparse.h7
-rw-r--r--security/nss/cmd/modutil/installparse.l137
-rw-r--r--security/nss/cmd/modutil/installparse.y104
-rw-r--r--security/nss/cmd/modutil/instsec.c153
-rw-r--r--security/nss/cmd/modutil/lex.Pk11Install_yy.c1607
-rw-r--r--security/nss/cmd/modutil/manifest.mn34
-rw-r--r--security/nss/cmd/modutil/modutil.c970
-rw-r--r--security/nss/cmd/modutil/modutil.gyp44
-rw-r--r--security/nss/cmd/modutil/modutil.h40
-rw-r--r--security/nss/cmd/modutil/pk11.c960
-rw-r--r--security/nss/cmd/modutil/pk11jar.html279
-rw-r--r--security/nss/cmd/modutil/rules.mk26
-rw-r--r--security/nss/cmd/modutil/specification.html322
-rw-r--r--security/nss/cmd/mpitests/mpi-test.c2127
-rw-r--r--security/nss/cmd/mpitests/mpitests.gyp30
-rw-r--r--security/nss/cmd/mpitests/test-info.c157
-rw-r--r--security/nss/cmd/multinit/Makefile47
-rw-r--r--security/nss/cmd/multinit/manifest.mn13
-rw-r--r--security/nss/cmd/multinit/multinit.c881
-rw-r--r--security/nss/cmd/multinit/multinit.gyp24
-rw-r--r--security/nss/cmd/ocspclnt/Makefile45
-rw-r--r--security/nss/cmd/ocspclnt/manifest.mn24
-rw-r--r--security/nss/cmd/ocspclnt/ocspclnt.c1243
-rw-r--r--security/nss/cmd/ocspclnt/ocspclnt.gyp25
-rw-r--r--security/nss/cmd/ocspresp/Makefile47
-rw-r--r--security/nss/cmd/ocspresp/manifest.mn15
-rw-r--r--security/nss/cmd/ocspresp/ocspresp.c251
-rw-r--r--security/nss/cmd/ocspresp/ocspresp.gyp24
-rw-r--r--security/nss/cmd/oidcalc/Makefile48
-rw-r--r--security/nss/cmd/oidcalc/manifest.mn19
-rw-r--r--security/nss/cmd/oidcalc/oidcalc.c86
-rw-r--r--security/nss/cmd/oidcalc/oidcalc.gyp30
-rw-r--r--security/nss/cmd/p7content/Makefile47
-rw-r--r--security/nss/cmd/p7content/manifest.mn15
-rw-r--r--security/nss/cmd/p7content/p7content.c269
-rw-r--r--security/nss/cmd/p7content/p7content.gyp24
-rw-r--r--security/nss/cmd/p7env/Makefile47
-rw-r--r--security/nss/cmd/p7env/manifest.mn15
-rw-r--r--security/nss/cmd/p7env/p7env.c261
-rw-r--r--security/nss/cmd/p7env/p7env.gyp24
-rw-r--r--security/nss/cmd/p7sign/Makefile47
-rw-r--r--security/nss/cmd/p7sign/manifest.mn15
-rw-r--r--security/nss/cmd/p7sign/p7sign.c281
-rw-r--r--security/nss/cmd/p7sign/p7sign.gyp24
-rw-r--r--security/nss/cmd/p7verify/Makefile47
-rw-r--r--security/nss/cmd/p7verify/manifest.mn15
-rw-r--r--security/nss/cmd/p7verify/p7verify.c283
-rw-r--r--security/nss/cmd/p7verify/p7verify.gyp24
-rw-r--r--security/nss/cmd/pk11ectest/Makefile46
-rw-r--r--security/nss/cmd/pk11ectest/manifest.mn16
-rw-r--r--security/nss/cmd/pk11ectest/pk11ectest.c171
-rw-r--r--security/nss/cmd/pk11ectest/pk11ectest.gyp31
-rwxr-xr-xsecurity/nss/cmd/pk11gcmtest/Makefile47
-rw-r--r--security/nss/cmd/pk11gcmtest/manifest.mn20
-rw-r--r--security/nss/cmd/pk11gcmtest/pk11gcmtest.c460
-rw-r--r--security/nss/cmd/pk11gcmtest/pk11gcmtest.gyp24
-rw-r--r--security/nss/cmd/pk11gcmtest/tests/README14
-rw-r--r--security/nss/cmd/pk11gcmtest/tests/gcmDecrypt128.rsp1016
-rw-r--r--security/nss/cmd/pk11gcmtest/tests/gcmDecrypt192.rsp1016
-rw-r--r--security/nss/cmd/pk11gcmtest/tests/gcmDecrypt256.rsp1016
-rw-r--r--security/nss/cmd/pk11gcmtest/tests/gcmEncryptExtIV128.rsp1016
-rw-r--r--security/nss/cmd/pk11gcmtest/tests/gcmEncryptExtIV192.rsp1016
-rw-r--r--security/nss/cmd/pk11gcmtest/tests/gcmEncryptExtIV256.rsp1016
-rwxr-xr-xsecurity/nss/cmd/pk11mode/Makefile65
-rw-r--r--security/nss/cmd/pk11mode/manifest.mn16
-rw-r--r--security/nss/cmd/pk11mode/pk11mode.c5387
-rw-r--r--security/nss/cmd/pk11mode/pk11mode.gyp24
-rw-r--r--security/nss/cmd/pk11util/Makefile48
-rw-r--r--security/nss/cmd/pk11util/manifest.mn23
-rw-r--r--security/nss/cmd/pk11util/pk11util.c2240
-rw-r--r--security/nss/cmd/pk11util/scripts/dosign162
-rw-r--r--security/nss/cmd/pk11util/scripts/hssign48
-rw-r--r--security/nss/cmd/pk11util/scripts/lcert35
-rw-r--r--security/nss/cmd/pk11util/scripts/mechanisms11
-rw-r--r--security/nss/cmd/pk11util/scripts/pLabel16
-rw-r--r--security/nss/cmd/pk11util/scripts/pMechanisms8
-rw-r--r--security/nss/cmd/pk11util/scripts/pcert30
-rw-r--r--security/nss/cmd/pk12util/Makefile48
-rw-r--r--security/nss/cmd/pk12util/manifest.mn23
-rw-r--r--security/nss/cmd/pk12util/pk12util.c1104
-rw-r--r--security/nss/cmd/pk12util/pk12util.gyp30
-rw-r--r--security/nss/cmd/pk12util/pk12util.h40
-rw-r--r--security/nss/cmd/pk1sign/Makefile47
-rw-r--r--security/nss/cmd/pk1sign/manifest.mn15
-rw-r--r--security/nss/cmd/pk1sign/pk1sign.c318
-rw-r--r--security/nss/cmd/pk1sign/pk1sign.gyp24
-rw-r--r--security/nss/cmd/pkix-errcodes/Makefile47
-rw-r--r--security/nss/cmd/pkix-errcodes/manifest.mn15
-rw-r--r--security/nss/cmd/pkix-errcodes/pkix-errcodes.c35
-rw-r--r--security/nss/cmd/pkix-errcodes/pkix-errcodes.gyp24
-rw-r--r--security/nss/cmd/platlibs.gypi78
-rw-r--r--security/nss/cmd/platlibs.mk262
-rw-r--r--security/nss/cmd/platrules.mk19
-rw-r--r--security/nss/cmd/pp/Makefile47
-rw-r--r--security/nss/cmd/pp/manifest.mn19
-rw-r--r--security/nss/cmd/pp/pp.c196
-rw-r--r--security/nss/cmd/pp/pp.gyp30
-rw-r--r--security/nss/cmd/ppcertdata/Makefile48
-rw-r--r--security/nss/cmd/ppcertdata/manifest.mn22
-rw-r--r--security/nss/cmd/ppcertdata/ppcertdata.c99
-rw-r--r--security/nss/cmd/pwdecrypt/Makefile45
-rw-r--r--security/nss/cmd/pwdecrypt/manifest.mn26
-rw-r--r--security/nss/cmd/pwdecrypt/pwdecrypt.c330
-rw-r--r--security/nss/cmd/pwdecrypt/pwdecrypt.gyp25
-rw-r--r--security/nss/cmd/rsaperf/Makefile46
-rw-r--r--security/nss/cmd/rsaperf/defkey.c293
-rw-r--r--security/nss/cmd/rsaperf/manifest.mn24
-rw-r--r--security/nss/cmd/rsaperf/rsaperf.c696
-rw-r--r--security/nss/cmd/rsaperf/rsaperf.gyp36
-rw-r--r--security/nss/cmd/rsapoptst/Makefile54
-rw-r--r--security/nss/cmd/rsapoptst/manifest.mn22
-rw-r--r--security/nss/cmd/rsapoptst/rsapoptst.c535
-rw-r--r--security/nss/cmd/samples/cert15
-rw-r--r--security/nss/cmd/samples/cert0bin0 -> 505 bytes
-rw-r--r--security/nss/cmd/samples/cert1bin0 -> 515 bytes
-rw-r--r--security/nss/cmd/samples/cert2bin0 -> 528 bytes
-rw-r--r--security/nss/cmd/samples/pkcs7.berbin0 -> 1771 bytes
-rw-r--r--security/nss/cmd/samples/pkcs7bday.berbin0 -> 1881 bytes
-rw-r--r--security/nss/cmd/samples/pkcs7cnet.berbin0 -> 3330 bytes
-rw-r--r--security/nss/cmd/samples/pkcs7news.berbin0 -> 255328 bytes
-rw-r--r--security/nss/cmd/samples/x509v3.derbin0 -> 463 bytes
-rw-r--r--security/nss/cmd/samples/x509v3.txt10
-rw-r--r--security/nss/cmd/sdrtest/Makefile45
-rw-r--r--security/nss/cmd/sdrtest/manifest.mn26
-rw-r--r--security/nss/cmd/sdrtest/sdrtest.c427
-rw-r--r--security/nss/cmd/sdrtest/sdrtest.gyp25
-rw-r--r--security/nss/cmd/selfserv/Makefile46
-rw-r--r--security/nss/cmd/selfserv/manifest.mn20
-rw-r--r--security/nss/cmd/selfserv/selfserv.c2781
-rw-r--r--security/nss/cmd/selfserv/selfserv.gyp30
-rw-r--r--security/nss/cmd/shlibsign/Makefile99
-rw-r--r--security/nss/cmd/shlibsign/mangle/Makefile65
-rw-r--r--security/nss/cmd/shlibsign/mangle/mangle.c140
-rw-r--r--security/nss/cmd/shlibsign/mangle/mangle.gyp31
-rw-r--r--security/nss/cmd/shlibsign/mangle/manifest.mn24
-rw-r--r--security/nss/cmd/shlibsign/manifest.mn27
-rw-r--r--security/nss/cmd/shlibsign/shlibsign.c1332
-rw-r--r--security/nss/cmd/shlibsign/shlibsign.gyp30
-rw-r--r--security/nss/cmd/shlibsign/sign.cmd25
-rw-r--r--security/nss/cmd/shlibsign/sign.sh51
-rw-r--r--security/nss/cmd/signtool/Makefile44
-rw-r--r--security/nss/cmd/signtool/README128
-rw-r--r--security/nss/cmd/signtool/certgen.c713
-rw-r--r--security/nss/cmd/signtool/javascript.c1817
-rw-r--r--security/nss/cmd/signtool/list.c215
-rw-r--r--security/nss/cmd/signtool/manifest.mn25
-rw-r--r--security/nss/cmd/signtool/sign.c834
-rw-r--r--security/nss/cmd/signtool/signtool.c1068
-rw-r--r--security/nss/cmd/signtool/signtool.gyp33
-rw-r--r--security/nss/cmd/signtool/signtool.h113
-rw-r--r--security/nss/cmd/signtool/util.c1086
-rw-r--r--security/nss/cmd/signtool/verify.c337
-rw-r--r--security/nss/cmd/signtool/zip.c676
-rw-r--r--security/nss/cmd/signtool/zip.h69
-rw-r--r--security/nss/cmd/signver/Makefile43
-rwxr-xr-xsecurity/nss/cmd/signver/examples/1/form.pl22
-rw-r--r--security/nss/cmd/signver/examples/1/signedForm.html55
-rw-r--r--security/nss/cmd/signver/examples/1/signedForm.nt.html55
-rwxr-xr-xsecurity/nss/cmd/signver/examples/1/signedForm.pl60
-rw-r--r--security/nss/cmd/signver/manifest.mn24
-rw-r--r--security/nss/cmd/signver/pk7print.c872
-rw-r--r--security/nss/cmd/signver/signver.c315
-rw-r--r--security/nss/cmd/signver/signver.gyp26
-rw-r--r--security/nss/cmd/smimetools/Makefile49
-rw-r--r--security/nss/cmd/smimetools/cmsutil.c1628
-rw-r--r--security/nss/cmd/smimetools/manifest.mn17
-rw-r--r--security/nss/cmd/smimetools/rules.mk7
-rwxr-xr-xsecurity/nss/cmd/smimetools/smime547
-rw-r--r--security/nss/cmd/smimetools/smimetools.gyp25
-rw-r--r--security/nss/cmd/ssltap/Makefile51
-rw-r--r--security/nss/cmd/ssltap/manifest.mn23
-rw-r--r--security/nss/cmd/ssltap/ssltap-manual.html170
-rw-r--r--security/nss/cmd/ssltap/ssltap.c2590
-rw-r--r--security/nss/cmd/ssltap/ssltap.gyp25
-rw-r--r--security/nss/cmd/strsclnt/Makefile47
-rw-r--r--security/nss/cmd/strsclnt/manifest.mn19
-rw-r--r--security/nss/cmd/strsclnt/strsclnt.c1553
-rw-r--r--security/nss/cmd/strsclnt/strsclnt.gyp30
-rw-r--r--security/nss/cmd/symkeyutil/Makefile48
-rw-r--r--security/nss/cmd/symkeyutil/manifest.mn23
-rw-r--r--security/nss/cmd/symkeyutil/symkey.man182
-rw-r--r--security/nss/cmd/symkeyutil/symkeyutil.c1102
-rw-r--r--security/nss/cmd/symkeyutil/symkeyutil.gyp30
-rw-r--r--security/nss/cmd/tests/Makefile45
-rw-r--r--security/nss/cmd/tests/baddbdir.c38
-rw-r--r--security/nss/cmd/tests/conflict.c27
-rw-r--r--security/nss/cmd/tests/dertimetest.c102
-rw-r--r--security/nss/cmd/tests/encodeinttest.c62
-rw-r--r--security/nss/cmd/tests/manifest.mn29
-rw-r--r--security/nss/cmd/tests/nonspr10.c90
-rw-r--r--security/nss/cmd/tests/remtest.c136
-rw-r--r--security/nss/cmd/tests/secmodtest.c126
-rw-r--r--security/nss/cmd/tests/tests.gyp91
-rw-r--r--security/nss/cmd/tstclnt/Makefile46
-rw-r--r--security/nss/cmd/tstclnt/manifest.mn23
-rw-r--r--security/nss/cmd/tstclnt/tstclnt.c1900
-rw-r--r--security/nss/cmd/tstclnt/tstclnt.gyp31
-rw-r--r--security/nss/cmd/vfychain/Makefile46
-rw-r--r--security/nss/cmd/vfychain/manifest.mn23
-rw-r--r--security/nss/cmd/vfychain/vfychain.c820
-rw-r--r--security/nss/cmd/vfychain/vfychain.gyp30
-rw-r--r--security/nss/cmd/vfyserv/Makefile46
-rw-r--r--security/nss/cmd/vfyserv/manifest.mn23
-rw-r--r--security/nss/cmd/vfyserv/vfyserv.c572
-rw-r--r--security/nss/cmd/vfyserv/vfyserv.gyp32
-rw-r--r--security/nss/cmd/vfyserv/vfyserv.h138
-rw-r--r--security/nss/cmd/vfyserv/vfyutil.c620
1312 files changed, 138726 insertions, 0 deletions
diff --git a/security/nss/cmd/Makefile b/security/nss/cmd/Makefile
new file mode 100644
index 000000000..86ef29ad4
--- /dev/null
+++ b/security/nss/cmd/Makefile
@@ -0,0 +1,44 @@
+#! gmake
+#
+# 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/.
+
+CORE_DEPTH = ..
+DEPTH = ..
+
+include manifest.mn
+include $(CORE_DEPTH)/coreconf/config.mk
+
+ifdef BUILD_LIBPKIX_TESTS
+DIRS += libpkix
+endif
+
+ifeq ($(NSS_BUILD_WITHOUT_SOFTOKEN),1)
+BLTEST_SRCDIR =
+ECPERF_SRCDIR =
+FREEBL_ECTEST_SRCDIR =
+FIPSTEST_SRCDIR =
+SHLIBSIGN_SRCDIR =
+else
+BLTEST_SRCDIR = bltest
+ECPERF_SRCDIR = ecperf
+FREEBL_ECTEST_SRCDIR = fbectest
+FIPSTEST_SRCDIR = fipstest
+SHLIBSIGN_SRCDIR = shlibsign
+endif
+
+LOWHASHTEST_SRCDIR=
+ifeq ($(FREEBL_LOWHASH),1)
+LOWHASHTEST_SRCDIR = lowhashtest # Add the lowhashtest directory to DIRS.
+endif
+
+INCLUDES += \
+ -I$(DIST)/../public/security \
+ -I./include \
+ $(NULL)
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+symbols::
+ @echo "TARGETS = $(TARGETS)"
diff --git a/security/nss/cmd/addbuiltin/Makefile b/security/nss/cmd/addbuiltin/Makefile
new file mode 100644
index 000000000..74ae20020
--- /dev/null
+++ b/security/nss/cmd/addbuiltin/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/addbuiltin/addbuiltin.c b/security/nss/cmd/addbuiltin/addbuiltin.c
new file mode 100644
index 000000000..9ecad3d64
--- /dev/null
+++ b/security/nss/cmd/addbuiltin/addbuiltin.c
@@ -0,0 +1,546 @@
+/* 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/. */
+
+/*
+ * Tool for converting builtin CA certs.
+ */
+
+#include "nssrenam.h"
+#include "nss.h"
+#include "cert.h"
+#include "certdb.h"
+#include "secutil.h"
+#include "pk11func.h"
+
+#if defined(WIN32)
+#include <fcntl.h>
+#include <io.h>
+#endif
+
+void
+dumpbytes(unsigned char *buf, int len)
+{
+ int i;
+ for (i = 0; i < len; i++) {
+ if ((i != 0) && ((i & 0xf) == 0)) {
+ printf("\n");
+ }
+ printf("\\%03o", buf[i]);
+ }
+ printf("\n");
+}
+
+char *
+getTrustString(unsigned int trust)
+{
+ if (trust & CERTDB_TRUSTED) {
+ if (trust & CERTDB_TRUSTED_CA) {
+ return "CKT_NSS_TRUSTED_DELEGATOR";
+ } else {
+ return "CKT_NSS_TRUSTED";
+ }
+ } else {
+ if (trust & CERTDB_TRUSTED_CA) {
+ return "CKT_NSS_TRUSTED_DELEGATOR";
+ } else if (trust & CERTDB_VALID_CA) {
+ return "CKT_NSS_VALID_DELEGATOR";
+ } else if (trust & CERTDB_TERMINAL_RECORD) {
+ return "CKT_NSS_NOT_TRUSTED";
+ } else {
+ return "CKT_NSS_MUST_VERIFY_TRUST";
+ }
+ }
+ return "CKT_NSS_TRUST_UNKNOWN"; /* not reached */
+}
+
+static const SEC_ASN1Template serialTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(CERTCertificate, serialNumber) },
+ { 0 }
+};
+
+void
+print_crl_info(CERTName *name, SECItem *serial)
+{
+ PRBool saveWrapeState = SECU_GetWrapEnabled();
+ SECU_EnableWrap(PR_FALSE);
+
+ SECU_PrintNameQuotesOptional(stdout, name, "# Issuer", 0, PR_FALSE);
+ printf("\n");
+
+ SECU_PrintInteger(stdout, serial, "# Serial Number", 0);
+
+ SECU_EnableWrap(saveWrapeState);
+}
+
+static SECStatus
+ConvertCRLEntry(SECItem *sdder, PRInt32 crlentry, char *nickname)
+{
+ int rv;
+ PLArenaPool *arena = NULL;
+ CERTSignedCrl *newCrl = NULL;
+ CERTCrlEntry *entry;
+
+ CERTName *name = NULL;
+ SECItem *derName = NULL;
+ SECItem *serial = NULL;
+
+ rv = SEC_ERROR_NO_MEMORY;
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena)
+ return rv;
+
+ newCrl = CERT_DecodeDERCrlWithFlags(arena, sdder, SEC_CRL_TYPE,
+ CRL_DECODE_DEFAULT_OPTIONS);
+ if (!newCrl)
+ return SECFailure;
+
+ name = &newCrl->crl.name;
+ derName = &newCrl->crl.derName;
+
+ if (newCrl->crl.entries != NULL) {
+ PRInt32 iv = 0;
+ while ((entry = newCrl->crl.entries[iv++]) != NULL) {
+ if (crlentry == iv) {
+ serial = &entry->serialNumber;
+ break;
+ }
+ }
+ }
+
+ if (!name || !derName || !serial)
+ return SECFailure;
+
+ printf("\n# Distrust \"%s\"\n", nickname);
+ print_crl_info(name, serial);
+
+ printf("CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST\n");
+ printf("CKA_TOKEN CK_BBOOL CK_TRUE\n");
+ printf("CKA_PRIVATE CK_BBOOL CK_FALSE\n");
+ printf("CKA_MODIFIABLE CK_BBOOL CK_FALSE\n");
+ printf("CKA_LABEL UTF8 \"%s\"\n", nickname);
+
+ printf("CKA_ISSUER MULTILINE_OCTAL\n");
+ dumpbytes(derName->data, derName->len);
+ printf("END\n");
+ printf("CKA_SERIAL_NUMBER MULTILINE_OCTAL\n");
+ printf("\\002\\%03o", serial->len); /* 002: type integer; len >=3 digits */
+ dumpbytes(serial->data, serial->len);
+ printf("END\n");
+
+ printf("CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_NOT_TRUSTED\n");
+ printf("CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_NOT_TRUSTED\n");
+ printf("CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_NOT_TRUSTED\n");
+ printf("CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE\n");
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+void
+print_info(SECItem *sdder, CERTCertificate *c)
+{
+ PRBool saveWrapeState = SECU_GetWrapEnabled();
+ SECU_EnableWrap(PR_FALSE);
+
+ SECU_PrintNameQuotesOptional(stdout, &c->issuer, "# Issuer", 0, PR_FALSE);
+ printf("\n");
+
+ SECU_PrintInteger(stdout, &c->serialNumber, "# Serial Number", 0);
+
+ SECU_PrintNameQuotesOptional(stdout, &c->subject, "# Subject", 0, PR_FALSE);
+ printf("\n");
+
+ SECU_PrintTimeChoice(stdout, &c->validity.notBefore, "# Not Valid Before", 0);
+ SECU_PrintTimeChoice(stdout, &c->validity.notAfter, "# Not Valid After ", 0);
+
+ SECU_PrintFingerprints(stdout, sdder, "# Fingerprint", 0);
+
+ SECU_EnableWrap(saveWrapeState);
+}
+
+static SECStatus
+ConvertCertificate(SECItem *sdder, char *nickname, CERTCertTrust *trust,
+ PRBool excludeCert, PRBool excludeHash)
+{
+ SECStatus rv = SECSuccess;
+ CERTCertificate *cert;
+ unsigned char sha1_hash[SHA1_LENGTH];
+ unsigned char md5_hash[MD5_LENGTH];
+ SECItem *serial = NULL;
+ PRBool step_up = PR_FALSE;
+ const char *trust_info;
+
+ cert = CERT_DecodeDERCertificate(sdder, PR_FALSE, nickname);
+ if (!cert) {
+ return SECFailure;
+ }
+ serial = SEC_ASN1EncodeItem(NULL, NULL, cert, serialTemplate);
+ if (!serial) {
+ return SECFailure;
+ }
+
+ if (!excludeCert) {
+ printf("\n#\n# Certificate \"%s\"\n#\n", nickname);
+ print_info(sdder, cert);
+ printf("CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE\n");
+ printf("CKA_TOKEN CK_BBOOL CK_TRUE\n");
+ printf("CKA_PRIVATE CK_BBOOL CK_FALSE\n");
+ printf("CKA_MODIFIABLE CK_BBOOL CK_FALSE\n");
+ printf("CKA_LABEL UTF8 \"%s\"\n", nickname);
+ printf("CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509\n");
+ printf("CKA_SUBJECT MULTILINE_OCTAL\n");
+ dumpbytes(cert->derSubject.data, cert->derSubject.len);
+ printf("END\n");
+ printf("CKA_ID UTF8 \"0\"\n");
+ printf("CKA_ISSUER MULTILINE_OCTAL\n");
+ dumpbytes(cert->derIssuer.data, cert->derIssuer.len);
+ printf("END\n");
+ printf("CKA_SERIAL_NUMBER MULTILINE_OCTAL\n");
+ dumpbytes(serial->data, serial->len);
+ printf("END\n");
+ printf("CKA_VALUE MULTILINE_OCTAL\n");
+ dumpbytes(sdder->data, sdder->len);
+ printf("END\n");
+ }
+
+ if ((trust->sslFlags | trust->emailFlags | trust->objectSigningFlags) ==
+ CERTDB_TERMINAL_RECORD)
+ trust_info = "Distrust";
+ else
+ trust_info = "Trust for";
+
+ printf("\n# %s \"%s\"\n", trust_info, nickname);
+ print_info(sdder, cert);
+
+ printf("CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST\n");
+ printf("CKA_TOKEN CK_BBOOL CK_TRUE\n");
+ printf("CKA_PRIVATE CK_BBOOL CK_FALSE\n");
+ printf("CKA_MODIFIABLE CK_BBOOL CK_FALSE\n");
+ printf("CKA_LABEL UTF8 \"%s\"\n", nickname);
+
+ if (!excludeHash) {
+ PK11_HashBuf(SEC_OID_SHA1, sha1_hash, sdder->data, sdder->len);
+ printf("CKA_CERT_SHA1_HASH MULTILINE_OCTAL\n");
+ dumpbytes(sha1_hash, SHA1_LENGTH);
+ printf("END\n");
+ PK11_HashBuf(SEC_OID_MD5, md5_hash, sdder->data, sdder->len);
+ printf("CKA_CERT_MD5_HASH MULTILINE_OCTAL\n");
+ dumpbytes(md5_hash, MD5_LENGTH);
+ printf("END\n");
+ }
+
+ printf("CKA_ISSUER MULTILINE_OCTAL\n");
+ dumpbytes(cert->derIssuer.data, cert->derIssuer.len);
+ printf("END\n");
+ printf("CKA_SERIAL_NUMBER MULTILINE_OCTAL\n");
+ dumpbytes(serial->data, serial->len);
+ printf("END\n");
+
+ printf("CKA_TRUST_SERVER_AUTH CK_TRUST %s\n",
+ getTrustString(trust->sslFlags));
+ printf("CKA_TRUST_EMAIL_PROTECTION CK_TRUST %s\n",
+ getTrustString(trust->emailFlags));
+ printf("CKA_TRUST_CODE_SIGNING CK_TRUST %s\n",
+ getTrustString(trust->objectSigningFlags));
+#ifdef notdef
+ printf("CKA_TRUST_CLIENT_AUTH CK_TRUST CKT_NSS_TRUSTED\n");
+ printf("CKA_TRUST_DIGITAL_SIGNATURE CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
+ printf("CKA_TRUST_NON_REPUDIATION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
+ printf("CKA_TRUST_KEY_ENCIPHERMENT CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
+ printf("CKA_TRUST_DATA_ENCIPHERMENT CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
+ printf("CKA_TRUST_KEY_AGREEMENT CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
+ printf("CKA_TRUST_KEY_CERT_SIGN CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
+#endif
+
+ step_up = (trust->sslFlags & CERTDB_GOVT_APPROVED_CA);
+ printf("CKA_TRUST_STEP_UP_APPROVED CK_BBOOL %s\n",
+ step_up ? "CK_TRUE" : "CK_FALSE");
+
+ PORT_Free(sdder->data);
+ return (rv);
+}
+
+void
+printheader()
+{
+ printf("# \n"
+ "# This Source Code Form is subject to the terms of the Mozilla Public\n"
+ "# License, v. 2.0. If a copy of the MPL was not distributed with this\n"
+ "# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n"
+ "#\n"
+ "# certdata.txt\n"
+ "#\n"
+ "# This file contains the object definitions for the certs and other\n"
+ "# information \"built into\" NSS.\n"
+ "#\n"
+ "# Object definitions:\n"
+ "#\n"
+ "# Certificates\n"
+ "#\n"
+ "# -- Attribute -- -- type -- -- value --\n"
+ "# CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE\n"
+ "# CKA_TOKEN CK_BBOOL CK_TRUE\n"
+ "# CKA_PRIVATE CK_BBOOL CK_FALSE\n"
+ "# CKA_MODIFIABLE CK_BBOOL CK_FALSE\n"
+ "# CKA_LABEL UTF8 (varies)\n"
+ "# CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509\n"
+ "# CKA_SUBJECT DER+base64 (varies)\n"
+ "# CKA_ID byte array (varies)\n"
+ "# CKA_ISSUER DER+base64 (varies)\n"
+ "# CKA_SERIAL_NUMBER DER+base64 (varies)\n"
+ "# CKA_VALUE DER+base64 (varies)\n"
+ "# CKA_NSS_EMAIL ASCII7 (unused here)\n"
+ "#\n"
+ "# Trust\n"
+ "#\n"
+ "# -- Attribute -- -- type -- -- value --\n"
+ "# CKA_CLASS CK_OBJECT_CLASS CKO_TRUST\n"
+ "# CKA_TOKEN CK_BBOOL CK_TRUE\n"
+ "# CKA_PRIVATE CK_BBOOL CK_FALSE\n"
+ "# CKA_MODIFIABLE CK_BBOOL CK_FALSE\n"
+ "# CKA_LABEL UTF8 (varies)\n"
+ "# CKA_ISSUER DER+base64 (varies)\n"
+ "# CKA_SERIAL_NUMBER DER+base64 (varies)\n"
+ "# CKA_CERT_HASH binary+base64 (varies)\n"
+ "# CKA_EXPIRES CK_DATE (not used here)\n"
+ "# CKA_TRUST_DIGITAL_SIGNATURE CK_TRUST (varies)\n"
+ "# CKA_TRUST_NON_REPUDIATION CK_TRUST (varies)\n"
+ "# CKA_TRUST_KEY_ENCIPHERMENT CK_TRUST (varies)\n"
+ "# CKA_TRUST_DATA_ENCIPHERMENT CK_TRUST (varies)\n"
+ "# CKA_TRUST_KEY_AGREEMENT CK_TRUST (varies)\n"
+ "# CKA_TRUST_KEY_CERT_SIGN CK_TRUST (varies)\n"
+ "# CKA_TRUST_CRL_SIGN CK_TRUST (varies)\n"
+ "# CKA_TRUST_SERVER_AUTH CK_TRUST (varies)\n"
+ "# CKA_TRUST_CLIENT_AUTH CK_TRUST (varies)\n"
+ "# CKA_TRUST_CODE_SIGNING CK_TRUST (varies)\n"
+ "# CKA_TRUST_EMAIL_PROTECTION CK_TRUST (varies)\n"
+ "# CKA_TRUST_IPSEC_END_SYSTEM CK_TRUST (varies)\n"
+ "# CKA_TRUST_IPSEC_TUNNEL CK_TRUST (varies)\n"
+ "# CKA_TRUST_IPSEC_USER CK_TRUST (varies)\n"
+ "# CKA_TRUST_TIME_STAMPING CK_TRUST (varies)\n"
+ "# (other trust attributes can be defined)\n"
+ "#\n"
+ "\n"
+ "#\n"
+ "# The object to tell NSS that this is a root list and we don't\n"
+ "# have to go looking for others.\n"
+ "#\n"
+ "BEGINDATA\n"
+ "CKA_CLASS CK_OBJECT_CLASS CKO_NSS_BUILTIN_ROOT_LIST\n"
+ "CKA_TOKEN CK_BBOOL CK_TRUE\n"
+ "CKA_PRIVATE CK_BBOOL CK_FALSE\n"
+ "CKA_MODIFIABLE CK_BBOOL CK_FALSE\n"
+ "CKA_LABEL UTF8 \"Mozilla Builtin Roots\"\n");
+}
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr, "%s -t trust -n nickname [-i certfile] [-c] [-h]\n", progName);
+ fprintf(stderr,
+ "\tRead a der-encoded cert from certfile or stdin, and output\n"
+ "\tit to stdout in a format suitable for the builtin root module.\n"
+ "\tExample: %s -n MyCA -t \"C,C,C\" -i myca.der >> certdata.txt\n",
+ progName);
+ fprintf(stderr, "%s -D -n label [-i certfile]\n", progName);
+ fprintf(stderr,
+ "\tRead a der-encoded cert from certfile or stdin, and output\n"
+ "\ta distrust record.\n"
+ "\t(-D is equivalent to -t p,p,p -c -h)\n");
+ fprintf(stderr, "%s -C -e crl-entry-number -n label [-i crlfile]\n", progName);
+ fprintf(stderr,
+ "\tRead a CRL from crlfile or stdin, and output\n"
+ "\ta distrust record (issuer+serial).\n"
+ "\t(-C implies -c -h)\n");
+ fprintf(stderr, "%-15s trust flags (cCTpPuw).\n", "-t trust");
+ fprintf(stderr, "%-15s nickname to assign to builtin cert, or\n",
+ "-n nickname");
+ fprintf(stderr, "%-15s a label for the distrust record.\n", "");
+ fprintf(stderr, "%-15s exclude the certificate (only add a trust record)\n", "-c");
+ fprintf(stderr, "%-15s exclude hash from trust record\n", "-h");
+ fprintf(stderr, "%-15s (useful to distrust any matching issuer/serial)\n", "");
+ fprintf(stderr, "%-15s (not allowed when adding positive trust)\n", "");
+ fprintf(stderr, "%-15s a CRL entry number, as shown by \"crlutil -S\"\n", "-e");
+ fprintf(stderr, "%-15s input file to read (default stdin)\n", "-i file");
+ fprintf(stderr, "%-15s (pipe through atob if the cert is b64-encoded)\n", "");
+ exit(-1);
+}
+
+enum {
+ opt_Input = 0,
+ opt_Nickname,
+ opt_Trust,
+ opt_Distrust,
+ opt_ExcludeCert,
+ opt_ExcludeHash,
+ opt_DistrustCRL,
+ opt_CRLEnry
+};
+
+static secuCommandFlag addbuiltin_options[] =
+ {
+ { /* opt_Input */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Trust */ 't', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Distrust */ 'D', PR_FALSE, 0, PR_FALSE },
+ { /* opt_ExcludeCert */ 'c', PR_FALSE, 0, PR_FALSE },
+ { /* opt_ExcludeHash */ 'h', PR_FALSE, 0, PR_FALSE },
+ { /* opt_DistrustCRL */ 'C', PR_FALSE, 0, PR_FALSE },
+ { /* opt_CRLEnry */ 'e', PR_TRUE, 0, PR_FALSE },
+ };
+
+int
+main(int argc, char **argv)
+{
+ SECStatus rv;
+ char *nickname = NULL;
+ char *trusts = NULL;
+ char *progName;
+ PRFileDesc *infile;
+ CERTCertTrust trust = { 0 };
+ SECItem derItem = { 0 };
+ PRInt32 crlentry = 0;
+ PRInt32 mutuallyExclusiveOpts = 0;
+ PRBool decodeTrust = PR_FALSE;
+
+ secuCommand addbuiltin = { 0 };
+ addbuiltin.numOptions = sizeof(addbuiltin_options) / sizeof(secuCommandFlag);
+ addbuiltin.options = addbuiltin_options;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &addbuiltin);
+
+ if (rv != SECSuccess)
+ Usage(progName);
+
+ if (addbuiltin.options[opt_Trust].activated)
+ ++mutuallyExclusiveOpts;
+ if (addbuiltin.options[opt_Distrust].activated)
+ ++mutuallyExclusiveOpts;
+ if (addbuiltin.options[opt_DistrustCRL].activated)
+ ++mutuallyExclusiveOpts;
+
+ if (mutuallyExclusiveOpts != 1) {
+ fprintf(stderr, "%s: you must specify exactly one of -t or -D or -C\n",
+ progName);
+ Usage(progName);
+ }
+
+ if (addbuiltin.options[opt_DistrustCRL].activated) {
+ if (!addbuiltin.options[opt_CRLEnry].activated) {
+ fprintf(stderr, "%s: you must specify the CRL entry number.\n",
+ progName);
+ Usage(progName);
+ } else {
+ crlentry = atoi(addbuiltin.options[opt_CRLEnry].arg);
+ if (crlentry < 1) {
+ fprintf(stderr, "%s: The CRL entry number must be > 0.\n",
+ progName);
+ Usage(progName);
+ }
+ }
+ }
+
+ if (!addbuiltin.options[opt_Nickname].activated) {
+ fprintf(stderr, "%s: you must specify parameter -n (a nickname or a label).\n",
+ progName);
+ Usage(progName);
+ }
+
+ if (addbuiltin.options[opt_Input].activated) {
+ infile = PR_Open(addbuiltin.options[opt_Input].arg, PR_RDONLY, 00660);
+ if (!infile) {
+ fprintf(stderr, "%s: failed to open input file.\n", progName);
+ exit(1);
+ }
+ } else {
+#if defined(WIN32)
+ /* If we're going to read binary data from stdin, we must put stdin
+ ** into O_BINARY mode or else incoming \r\n's will become \n's,
+ ** and latin-1 characters will be altered.
+ */
+
+ int smrv = _setmode(_fileno(stdin), _O_BINARY);
+ if (smrv == -1) {
+ fprintf(stderr,
+ "%s: Cannot change stdin to binary mode. Use -i option instead.\n",
+ progName);
+ exit(1);
+ }
+#endif
+ infile = PR_STDIN;
+ }
+
+#if defined(WIN32)
+ /* We must put stdout into O_BINARY mode or else the output will include
+ ** carriage returns.
+ */
+ {
+ int smrv = _setmode(_fileno(stdout), _O_BINARY);
+ if (smrv == -1) {
+ fprintf(stderr, "%s: Cannot change stdout to binary mode.\n", progName);
+ exit(1);
+ }
+ }
+#endif
+
+ nickname = strdup(addbuiltin.options[opt_Nickname].arg);
+
+ NSS_NoDB_Init(NULL);
+
+ if (addbuiltin.options[opt_Distrust].activated ||
+ addbuiltin.options[opt_DistrustCRL].activated) {
+ addbuiltin.options[opt_ExcludeCert].activated = PR_TRUE;
+ addbuiltin.options[opt_ExcludeHash].activated = PR_TRUE;
+ }
+
+ if (addbuiltin.options[opt_Distrust].activated) {
+ trusts = strdup("p,p,p");
+ decodeTrust = PR_TRUE;
+ } else if (addbuiltin.options[opt_Trust].activated) {
+ trusts = strdup(addbuiltin.options[opt_Trust].arg);
+ decodeTrust = PR_TRUE;
+ }
+
+ if (decodeTrust) {
+ rv = CERT_DecodeTrustString(&trust, trusts);
+ if (rv) {
+ fprintf(stderr, "%s: incorrectly formatted trust string.\n", progName);
+ Usage(progName);
+ }
+ }
+
+ if (addbuiltin.options[opt_Trust].activated &&
+ addbuiltin.options[opt_ExcludeHash].activated) {
+ if ((trust.sslFlags | trust.emailFlags | trust.objectSigningFlags) !=
+ CERTDB_TERMINAL_RECORD) {
+ fprintf(stderr, "%s: Excluding the hash only allowed with distrust.\n", progName);
+ Usage(progName);
+ }
+ }
+
+ SECU_FileToItem(&derItem, infile);
+
+ /*printheader();*/
+
+ if (addbuiltin.options[opt_DistrustCRL].activated) {
+ rv = ConvertCRLEntry(&derItem, crlentry, nickname);
+ } else {
+ rv = ConvertCertificate(&derItem, nickname, &trust,
+ addbuiltin.options[opt_ExcludeCert].activated,
+ addbuiltin.options[opt_ExcludeHash].activated);
+ if (rv) {
+ fprintf(stderr, "%s: failed to convert certificate.\n", progName);
+ exit(1);
+ }
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return (SECSuccess);
+}
diff --git a/security/nss/cmd/addbuiltin/addbuiltin.gyp b/security/nss/cmd/addbuiltin/addbuiltin.gyp
new file mode 100644
index 000000000..a8d1382e3
--- /dev/null
+++ b/security/nss/cmd/addbuiltin/addbuiltin.gyp
@@ -0,0 +1,24 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'addbuiltin',
+ 'type': 'executable',
+ 'sources': [
+ 'addbuiltin.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/addbuiltin/manifest.mn b/security/nss/cmd/addbuiltin/manifest.mn
new file mode 100644
index 000000000..9c44c089a
--- /dev/null
+++ b/security/nss/cmd/addbuiltin/manifest.mn
@@ -0,0 +1,20 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ addbuiltin.c \
+ $(NULL)
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd
+
+PROGRAM = addbuiltin
+
diff --git a/security/nss/cmd/atob/Makefile b/security/nss/cmd/atob/Makefile
new file mode 100644
index 000000000..2aaef8fe5
--- /dev/null
+++ b/security/nss/cmd/atob/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/atob/atob.c b/security/nss/cmd/atob/atob.c
new file mode 100644
index 000000000..115b0e9a0
--- /dev/null
+++ b/security/nss/cmd/atob/atob.c
@@ -0,0 +1,174 @@
+/* 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/. */
+
+#include "plgetopt.h"
+#include "secutil.h"
+#include "nssb64.h"
+#include <errno.h>
+
+#if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
+#if !defined(WIN32)
+extern int fread(char *, size_t, size_t, FILE *);
+extern int fwrite(char *, size_t, size_t, FILE *);
+extern int fprintf(FILE *, char *, ...);
+#endif
+#endif
+
+#if defined(WIN32)
+#include "fcntl.h"
+#include "io.h"
+#endif
+
+static PRInt32
+output_binary(void *arg, const unsigned char *obuf, PRInt32 size)
+{
+ FILE *outFile = arg;
+ int nb;
+
+ nb = fwrite(obuf, 1, size, outFile);
+ if (nb != size) {
+ PORT_SetError(SEC_ERROR_IO);
+ return -1;
+ }
+
+ return nb;
+}
+
+static PRBool
+isBase64Char(char c)
+{
+ return ((c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') ||
+ (c >= '0' && c <= '9') ||
+ c == '+' || c == '/' ||
+ c == '=');
+}
+
+static SECStatus
+decode_file(FILE *outFile, FILE *inFile)
+{
+ NSSBase64Decoder *cx;
+ SECStatus status = SECFailure;
+ char ibuf[4096];
+ const char *ptr;
+
+ cx = NSSBase64Decoder_Create(output_binary, outFile);
+ if (!cx) {
+ return -1;
+ }
+
+ for (;;) {
+ if (feof(inFile))
+ break;
+ if (!fgets(ibuf, sizeof(ibuf), inFile)) {
+ if (ferror(inFile)) {
+ PORT_SetError(SEC_ERROR_IO);
+ goto loser;
+ }
+ /* eof */
+ break;
+ }
+ for (ptr = ibuf; *ptr; ++ptr) {
+ char c = *ptr;
+ if (c == '\n' || c == '\r') {
+ break; /* found end of line */
+ }
+ if (!isBase64Char(c)) {
+ ptr = ibuf; /* ignore line */
+ break;
+ }
+ }
+ if (ibuf == ptr) {
+ continue; /* skip empty or non-base64 line */
+ }
+
+ status = NSSBase64Decoder_Update(cx, ibuf, ptr - ibuf);
+ if (status != SECSuccess)
+ goto loser;
+ }
+
+ return NSSBase64Decoder_Destroy(cx, PR_FALSE);
+
+loser:
+ (void)NSSBase64Decoder_Destroy(cx, PR_TRUE);
+ return status;
+}
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ SECStatus rv;
+ FILE *inFile, *outFile;
+ PLOptState *optstate;
+ PLOptStatus status;
+
+ inFile = 0;
+ outFile = 0;
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ /* Parse command line arguments */
+ optstate = PL_CreateOptState(argc, argv, "?hi:o:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ case 'h':
+ Usage(progName);
+ break;
+
+ case 'i':
+ inFile = fopen(optstate->value, "r");
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "wb");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+ }
+ }
+ if (!inFile)
+ inFile = stdin;
+ if (!outFile) {
+#if defined(WIN32)
+ int smrv = _setmode(_fileno(stdout), _O_BINARY);
+ if (smrv == -1) {
+ fprintf(stderr,
+ "%s: Cannot change stdout to binary mode. Use -o option instead.\n",
+ progName);
+ return smrv;
+ }
+#endif
+ outFile = stdout;
+ }
+ rv = decode_file(outFile, inFile);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
+ progName, PORT_GetError(), errno);
+ return -1;
+ }
+ return 0;
+}
diff --git a/security/nss/cmd/atob/atob.gyp b/security/nss/cmd/atob/atob.gyp
new file mode 100644
index 000000000..af972c2e9
--- /dev/null
+++ b/security/nss/cmd/atob/atob.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'atob',
+ 'type': 'executable',
+ 'sources': [
+ 'atob.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/atob/manifest.mn b/security/nss/cmd/atob/manifest.mn
new file mode 100644
index 000000000..5d822b96e
--- /dev/null
+++ b/security/nss/cmd/atob/manifest.mn
@@ -0,0 +1,22 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = atob.c
+
+PROGRAM = atob
+
diff --git a/security/nss/cmd/bltest/Makefile b/security/nss/cmd/bltest/Makefile
new file mode 100644
index 000000000..a5e83efdf
--- /dev/null
+++ b/security/nss/cmd/bltest/Makefile
@@ -0,0 +1,54 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+#MKPROG = purify -cache-dir=/u/mcgreer/pcache -best-effort \
+# -always-use-cache-dir $(CC)
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#EXTRA_SHARED_LIBS += \
+# -L/usr/lib \
+# -lposix4 \
+# $(NULL)
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/security/nss/cmd/bltest/blapitest.c b/security/nss/cmd/bltest/blapitest.c
new file mode 100644
index 000000000..ebe73e6be
--- /dev/null
+++ b/security/nss/cmd/bltest/blapitest.c
@@ -0,0 +1,4235 @@
+/* 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/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "blapi.h"
+#include "secrng.h"
+#include "prmem.h"
+#include "prprf.h"
+#include "prtime.h"
+#include "prsystem.h"
+#include "plstr.h"
+#include "nssb64.h"
+#include "basicutil.h"
+#include "plgetopt.h"
+#include "softoken.h"
+#include "nspr.h"
+#include "secport.h"
+#include "secoid.h"
+#include "nssutil.h"
+
+#include "pkcs1_vectors.h"
+
+#ifndef NSS_DISABLE_ECC
+#include "ecl-curve.h"
+SECStatus EC_DecodeParams(const SECItem *encodedParams,
+ ECParams **ecparams);
+SECStatus EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
+ const ECParams *srcParams);
+#endif
+
+char *progName;
+char *testdir = NULL;
+
+#define BLTEST_DEFAULT_CHUNKSIZE 4096
+
+#define WORDSIZE sizeof(unsigned long)
+
+#define CHECKERROR(rv, ln) \
+ if (rv) { \
+ PRErrorCode prerror = PR_GetError(); \
+ PR_fprintf(PR_STDERR, "%s: ERR %d (%s) at line %d.\n", progName, \
+ prerror, PORT_ErrorToString(prerror), ln); \
+ exit(-1); \
+ }
+
+/* Macros for performance timing. */
+#define TIMESTART() \
+ time1 = PR_IntervalNow();
+
+#define TIMEFINISH(time, reps) \
+ time2 = (PRIntervalTime)(PR_IntervalNow() - time1); \
+ time1 = PR_IntervalToMilliseconds(time2); \
+ time = ((double)(time1)) / reps;
+
+#define TIMEMARK(seconds) \
+ time1 = PR_SecondsToInterval(seconds); \
+ { \
+ PRInt64 tmp; \
+ if (time2 == 0) { \
+ time2 = 1; \
+ } \
+ LL_DIV(tmp, time1, time2); \
+ if (tmp < 10) { \
+ if (tmp == 0) { \
+ opsBetweenChecks = 1; \
+ } else { \
+ LL_L2I(opsBetweenChecks, tmp); \
+ } \
+ } else { \
+ opsBetweenChecks = 10; \
+ } \
+ } \
+ time2 = time1; \
+ time1 = PR_IntervalNow();
+
+#define TIMETOFINISH() \
+ PR_IntervalNow() - time1 >= time2
+
+static void
+Usage()
+{
+#define PRINTUSAGE(subject, option, predicate) \
+ fprintf(stderr, "%10s %s\t%s\n", subject, option, predicate);
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "[-DEHSVR]", "List available cipher modes"); /* XXX */
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-E -m mode ", "Encrypt a buffer");
+ PRINTUSAGE("", "", "[-i plaintext] [-o ciphertext] [-k key] [-v iv]");
+ PRINTUSAGE("", "", "[-b bufsize] [-g keysize] [-e exp] [-r rounds]");
+ PRINTUSAGE("", "", "[-w wordsize] [-p repetitions | -5 time_interval]");
+ PRINTUSAGE("", "", "[-4 th_num]");
+ PRINTUSAGE("", "-m", "cipher mode to use");
+ PRINTUSAGE("", "-i", "file which contains input buffer");
+ PRINTUSAGE("", "-o", "file for output buffer");
+ PRINTUSAGE("", "-k", "file which contains key");
+ PRINTUSAGE("", "-v", "file which contains initialization vector");
+ PRINTUSAGE("", "-b", "size of input buffer");
+ PRINTUSAGE("", "-g", "key size (in bytes)");
+ PRINTUSAGE("", "-p", "do performance test");
+ PRINTUSAGE("", "-4", "run test in multithread mode. th_num number of parallel threads");
+ PRINTUSAGE("", "-5", "run test for specified time interval(in seconds)");
+ PRINTUSAGE("", "--aad", "File with contains additional auth data");
+ PRINTUSAGE("(rsa)", "-e", "rsa public exponent");
+ PRINTUSAGE("(rc5)", "-r", "number of rounds");
+ PRINTUSAGE("(rc5)", "-w", "wordsize (32 or 64)");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-D -m mode", "Decrypt a buffer");
+ PRINTUSAGE("", "", "[-i plaintext] [-o ciphertext] [-k key] [-v iv]");
+ PRINTUSAGE("", "", "[-p repetitions | -5 time_interval] [-4 th_num]");
+ PRINTUSAGE("", "-m", "cipher mode to use");
+ PRINTUSAGE("", "-i", "file which contains input buffer");
+ PRINTUSAGE("", "-o", "file for output buffer");
+ PRINTUSAGE("", "-k", "file which contains key");
+ PRINTUSAGE("", "-v", "file which contains initialization vector");
+ PRINTUSAGE("", "-p", "do performance test");
+ PRINTUSAGE("", "-4", "run test in multithread mode. th_num number of parallel threads");
+ PRINTUSAGE("", "-5", "run test for specified time interval(in seconds)");
+ PRINTUSAGE("", "--aad", "File with contains additional auth data");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-H -m mode", "Hash a buffer");
+ PRINTUSAGE("", "", "[-i plaintext] [-o hash]");
+ PRINTUSAGE("", "", "[-b bufsize]");
+ PRINTUSAGE("", "", "[-p repetitions | -5 time_interval] [-4 th_num]");
+ PRINTUSAGE("", "-m", "cipher mode to use");
+ PRINTUSAGE("", "-i", "file which contains input buffer");
+ PRINTUSAGE("", "-o", "file for hash");
+ PRINTUSAGE("", "-b", "size of input buffer");
+ PRINTUSAGE("", "-p", "do performance test");
+ PRINTUSAGE("", "-4", "run test in multithread mode. th_num number of parallel threads");
+ PRINTUSAGE("", "-5", "run test for specified time interval(in seconds)");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-S -m mode", "Sign a buffer");
+ PRINTUSAGE("", "", "[-i plaintext] [-o signature] [-k key]");
+ PRINTUSAGE("", "", "[-b bufsize]");
+#ifndef NSS_DISABLE_ECC
+ PRINTUSAGE("", "", "[-n curvename]");
+#endif
+ PRINTUSAGE("", "", "[-p repetitions | -5 time_interval] [-4 th_num]");
+ PRINTUSAGE("", "-m", "cipher mode to use");
+ PRINTUSAGE("", "-i", "file which contains input buffer");
+ PRINTUSAGE("", "-o", "file for signature");
+ PRINTUSAGE("", "-k", "file which contains key");
+#ifndef NSS_DISABLE_ECC
+ PRINTUSAGE("", "-n", "name of curve for EC key generation; one of:");
+ PRINTUSAGE("", "", " nistp256, nistp384, nistp521");
+#endif
+ PRINTUSAGE("", "-p", "do performance test");
+ PRINTUSAGE("", "-4", "run test in multithread mode. th_num number of parallel threads");
+ PRINTUSAGE("", "-5", "run test for specified time interval(in seconds)");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-V -m mode", "Verify a signed buffer");
+ PRINTUSAGE("", "", "[-i plaintext] [-s signature] [-k key]");
+ PRINTUSAGE("", "", "[-p repetitions | -5 time_interval] [-4 th_num]");
+ PRINTUSAGE("", "-m", "cipher mode to use");
+ PRINTUSAGE("", "-i", "file which contains input buffer");
+ PRINTUSAGE("", "-s", "file which contains signature of input buffer");
+ PRINTUSAGE("", "-k", "file which contains key");
+ PRINTUSAGE("", "-p", "do performance test");
+ PRINTUSAGE("", "-4", "run test in multithread mode. th_num number of parallel threads");
+ PRINTUSAGE("", "-5", "run test for specified time interval(in seconds)");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-N -m mode -b bufsize",
+ "Create a nonce plaintext and key");
+ PRINTUSAGE("", "", "[-g keysize] [-u cxreps]");
+ PRINTUSAGE("", "-g", "key size (in bytes)");
+ PRINTUSAGE("", "-u", "number of repetitions of context creation");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-R [-g keysize] [-e exp]",
+ "Test the RSA populate key function");
+ PRINTUSAGE("", "", "[-r repetitions]");
+ PRINTUSAGE("", "-g", "key size (in bytes)");
+ PRINTUSAGE("", "-e", "rsa public exponent");
+ PRINTUSAGE("", "-r", "repetitions of the test");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-F", "Run the FIPS self-test");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-T [-m mode1,mode2...]", "Run the BLAPI self-test");
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+/* Helper functions for ascii<-->binary conversion/reading/writing */
+
+/* XXX argh */
+struct item_with_arena {
+ SECItem *item;
+ PLArenaPool *arena;
+};
+
+static PRInt32
+get_binary(void *arg, const unsigned char *ibuf, PRInt32 size)
+{
+ struct item_with_arena *it = arg;
+ SECItem *binary = it->item;
+ SECItem *tmp;
+ int index;
+ if (binary->data == NULL) {
+ tmp = SECITEM_AllocItem(it->arena, NULL, size);
+ binary->data = tmp->data;
+ binary->len = tmp->len;
+ index = 0;
+ } else {
+ SECITEM_ReallocItem(NULL, binary, binary->len, binary->len + size);
+ index = binary->len;
+ }
+ PORT_Memcpy(&binary->data[index], ibuf, size);
+ return binary->len;
+}
+
+static SECStatus
+atob(SECItem *ascii, SECItem *binary, PLArenaPool *arena)
+{
+ SECStatus status;
+ NSSBase64Decoder *cx;
+ struct item_with_arena it;
+ int len;
+ binary->data = NULL;
+ binary->len = 0;
+ it.item = binary;
+ it.arena = arena;
+ len = (strncmp((const char *)&ascii->data[ascii->len - 2], "\r\n", 2)) ? ascii->len
+ : ascii->len - 2;
+ cx = NSSBase64Decoder_Create(get_binary, &it);
+ status = NSSBase64Decoder_Update(cx, (const char *)ascii->data, len);
+ status = NSSBase64Decoder_Destroy(cx, PR_FALSE);
+ return status;
+}
+
+static PRInt32
+output_ascii(void *arg, const char *obuf, PRInt32 size)
+{
+ PRFileDesc *outfile = arg;
+ PRInt32 nb = PR_Write(outfile, obuf, size);
+ if (nb != size) {
+ PORT_SetError(SEC_ERROR_IO);
+ return -1;
+ }
+ return nb;
+}
+
+static SECStatus
+btoa_file(SECItem *binary, PRFileDesc *outfile)
+{
+ SECStatus status;
+ NSSBase64Encoder *cx;
+ if (binary->len == 0)
+ return SECSuccess;
+ cx = NSSBase64Encoder_Create(output_ascii, outfile);
+ status = NSSBase64Encoder_Update(cx, binary->data, binary->len);
+ status = NSSBase64Encoder_Destroy(cx, PR_FALSE);
+ status = PR_Write(outfile, "\r\n", 2);
+ return status;
+}
+
+SECStatus
+hex_from_2char(unsigned char *c2, unsigned char *byteval)
+{
+ int i;
+ unsigned char offset;
+ *byteval = 0;
+ for (i = 0; i < 2; i++) {
+ if (c2[i] >= '0' && c2[i] <= '9') {
+ offset = c2[i] - '0';
+ *byteval |= offset << 4 * (1 - i);
+ } else if (c2[i] >= 'a' && c2[i] <= 'f') {
+ offset = c2[i] - 'a';
+ *byteval |= (offset + 10) << 4 * (1 - i);
+ } else if (c2[i] >= 'A' && c2[i] <= 'F') {
+ offset = c2[i] - 'A';
+ *byteval |= (offset + 10) << 4 * (1 - i);
+ } else {
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+}
+
+SECStatus
+char2_from_hex(unsigned char byteval, char *c2)
+{
+ int i;
+ unsigned char offset;
+ for (i = 0; i < 2; i++) {
+ offset = (byteval >> 4 * (1 - i)) & 0x0f;
+ if (offset < 10) {
+ c2[i] = '0' + offset;
+ } else {
+ c2[i] = 'A' + offset - 10;
+ }
+ }
+ return SECSuccess;
+}
+
+void
+serialize_key(SECItem *it, int ni, PRFileDesc *file)
+{
+ unsigned char len[4];
+ int i;
+ NSSBase64Encoder *cx;
+ cx = NSSBase64Encoder_Create(output_ascii, file);
+ for (i = 0; i < ni; i++, it++) {
+ len[0] = (it->len >> 24) & 0xff;
+ len[1] = (it->len >> 16) & 0xff;
+ len[2] = (it->len >> 8) & 0xff;
+ len[3] = (it->len & 0xff);
+ NSSBase64Encoder_Update(cx, len, 4);
+ NSSBase64Encoder_Update(cx, it->data, it->len);
+ }
+ NSSBase64Encoder_Destroy(cx, PR_FALSE);
+ PR_Write(file, "\r\n", 2);
+}
+
+void
+key_from_filedata(PLArenaPool *arena, SECItem *it, int ns, int ni, SECItem *filedata)
+{
+ int fpos = 0;
+ int i, len;
+ unsigned char *buf = filedata->data;
+ for (i = 0; i < ni; i++) {
+ len = (buf[fpos++] & 0xff) << 24;
+ len |= (buf[fpos++] & 0xff) << 16;
+ len |= (buf[fpos++] & 0xff) << 8;
+ len |= (buf[fpos++] & 0xff);
+ if (ns <= i) {
+ if (len > 0) {
+ it->len = len;
+ it->data = PORT_ArenaAlloc(arena, it->len);
+ PORT_Memcpy(it->data, &buf[fpos], it->len);
+ } else {
+ it->len = 0;
+ it->data = NULL;
+ }
+ it++;
+ }
+ fpos += len;
+ }
+}
+
+static RSAPrivateKey *
+rsakey_from_filedata(PLArenaPool *arena, SECItem *filedata)
+{
+ RSAPrivateKey *key;
+ key = (RSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(RSAPrivateKey));
+ key->arena = arena;
+ key_from_filedata(arena, &key->version, 0, 9, filedata);
+ return key;
+}
+
+static PQGParams *
+pqg_from_filedata(PLArenaPool *arena, SECItem *filedata)
+{
+ PQGParams *pqg;
+ pqg = (PQGParams *)PORT_ArenaZAlloc(arena, sizeof(PQGParams));
+ pqg->arena = arena;
+ key_from_filedata(arena, &pqg->prime, 0, 3, filedata);
+ return pqg;
+}
+
+static DSAPrivateKey *
+dsakey_from_filedata(PLArenaPool *arena, SECItem *filedata)
+{
+ DSAPrivateKey *key;
+ key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey));
+ key->params.arena = arena;
+ key_from_filedata(arena, &key->params.prime, 0, 5, filedata);
+ return key;
+}
+
+#ifndef NSS_DISABLE_ECC
+static ECPrivateKey *
+eckey_from_filedata(PLArenaPool *arena, SECItem *filedata)
+{
+ ECPrivateKey *key;
+ SECStatus rv;
+ ECParams *tmpECParams = NULL;
+ key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey));
+ /* read and convert params */
+ key->ecParams.arena = arena;
+ key_from_filedata(arena, &key->ecParams.DEREncoding, 0, 1, filedata);
+ rv = SECOID_Init();
+ CHECKERROR(rv, __LINE__);
+ rv = EC_DecodeParams(&key->ecParams.DEREncoding, &tmpECParams);
+ CHECKERROR(rv, __LINE__);
+ rv = EC_CopyParams(key->ecParams.arena, &key->ecParams, tmpECParams);
+ CHECKERROR(rv, __LINE__);
+ rv = SECOID_Shutdown();
+ CHECKERROR(rv, __LINE__);
+ PORT_FreeArena(tmpECParams->arena, PR_TRUE);
+ /* read key */
+ key_from_filedata(arena, &key->publicValue, 1, 3, filedata);
+ return key;
+}
+
+typedef struct curveNameTagPairStr {
+ char *curveName;
+ SECOidTag curveOidTag;
+} CurveNameTagPair;
+
+static CurveNameTagPair nameTagPair[] =
+ {
+ { "sect163k1", SEC_OID_SECG_EC_SECT163K1 },
+ { "nistk163", SEC_OID_SECG_EC_SECT163K1 },
+ { "sect163r1", SEC_OID_SECG_EC_SECT163R1 },
+ { "sect163r2", SEC_OID_SECG_EC_SECT163R2 },
+ { "nistb163", SEC_OID_SECG_EC_SECT163R2 },
+ { "sect193r1", SEC_OID_SECG_EC_SECT193R1 },
+ { "sect193r2", SEC_OID_SECG_EC_SECT193R2 },
+ { "sect233k1", SEC_OID_SECG_EC_SECT233K1 },
+ { "nistk233", SEC_OID_SECG_EC_SECT233K1 },
+ { "sect233r1", SEC_OID_SECG_EC_SECT233R1 },
+ { "nistb233", SEC_OID_SECG_EC_SECT233R1 },
+ { "sect239k1", SEC_OID_SECG_EC_SECT239K1 },
+ { "sect283k1", SEC_OID_SECG_EC_SECT283K1 },
+ { "nistk283", SEC_OID_SECG_EC_SECT283K1 },
+ { "sect283r1", SEC_OID_SECG_EC_SECT283R1 },
+ { "nistb283", SEC_OID_SECG_EC_SECT283R1 },
+ { "sect409k1", SEC_OID_SECG_EC_SECT409K1 },
+ { "nistk409", SEC_OID_SECG_EC_SECT409K1 },
+ { "sect409r1", SEC_OID_SECG_EC_SECT409R1 },
+ { "nistb409", SEC_OID_SECG_EC_SECT409R1 },
+ { "sect571k1", SEC_OID_SECG_EC_SECT571K1 },
+ { "nistk571", SEC_OID_SECG_EC_SECT571K1 },
+ { "sect571r1", SEC_OID_SECG_EC_SECT571R1 },
+ { "nistb571", SEC_OID_SECG_EC_SECT571R1 },
+ { "secp160k1", SEC_OID_SECG_EC_SECP160K1 },
+ { "secp160r1", SEC_OID_SECG_EC_SECP160R1 },
+ { "secp160r2", SEC_OID_SECG_EC_SECP160R2 },
+ { "secp192k1", SEC_OID_SECG_EC_SECP192K1 },
+ { "secp192r1", SEC_OID_SECG_EC_SECP192R1 },
+ { "nistp192", SEC_OID_SECG_EC_SECP192R1 },
+ { "secp224k1", SEC_OID_SECG_EC_SECP224K1 },
+ { "secp224r1", SEC_OID_SECG_EC_SECP224R1 },
+ { "nistp224", SEC_OID_SECG_EC_SECP224R1 },
+ { "secp256k1", SEC_OID_SECG_EC_SECP256K1 },
+ { "secp256r1", SEC_OID_SECG_EC_SECP256R1 },
+ { "nistp256", SEC_OID_SECG_EC_SECP256R1 },
+ { "secp384r1", SEC_OID_SECG_EC_SECP384R1 },
+ { "nistp384", SEC_OID_SECG_EC_SECP384R1 },
+ { "secp521r1", SEC_OID_SECG_EC_SECP521R1 },
+ { "nistp521", SEC_OID_SECG_EC_SECP521R1 },
+
+ { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
+ { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
+ { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
+ { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
+ { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
+ { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
+
+ { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
+ { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
+ { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
+ { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
+ { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
+ { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
+ { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
+ { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
+ { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
+ { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
+ { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
+ { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
+ { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
+ { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
+ { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
+ { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
+ { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
+ { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
+ { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
+ { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
+
+ { "secp112r1", SEC_OID_SECG_EC_SECP112R1 },
+ { "secp112r2", SEC_OID_SECG_EC_SECP112R2 },
+ { "secp128r1", SEC_OID_SECG_EC_SECP128R1 },
+ { "secp128r2", SEC_OID_SECG_EC_SECP128R2 },
+
+ { "sect113r1", SEC_OID_SECG_EC_SECT113R1 },
+ { "sect113r2", SEC_OID_SECG_EC_SECT113R2 },
+ { "sect131r1", SEC_OID_SECG_EC_SECT131R1 },
+ { "sect131r2", SEC_OID_SECG_EC_SECT131R2 },
+ { "curve25519", SEC_OID_CURVE25519 },
+ };
+
+static SECItem *
+getECParams(const char *curve)
+{
+ SECItem *ecparams;
+ SECOidData *oidData = NULL;
+ SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
+ int i, numCurves;
+
+ if (curve != NULL) {
+ numCurves = sizeof(nameTagPair) / sizeof(CurveNameTagPair);
+ for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN));
+ i++) {
+ if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
+ curveOidTag = nameTagPair[i].curveOidTag;
+ }
+ }
+
+ /* Return NULL if curve name is not recognized */
+ if ((curveOidTag == SEC_OID_UNKNOWN) ||
+ (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
+ fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
+ return NULL;
+ }
+
+ ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
+
+ /*
+ * ecparams->data needs to contain the ASN encoding of an object ID (OID)
+ * representing the named curve. The actual OID is in
+ * oidData->oid.data so we simply prepend 0x06 and OID length
+ */
+ ecparams->data[0] = SEC_ASN1_OBJECT_ID;
+ ecparams->data[1] = oidData->oid.len;
+ memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
+
+ return ecparams;
+}
+#endif /* NSS_DISABLE_ECC */
+
+static void
+dump_pqg(PQGParams *pqg)
+{
+ SECU_PrintInteger(stdout, &pqg->prime, "PRIME:", 0);
+ SECU_PrintInteger(stdout, &pqg->subPrime, "SUBPRIME:", 0);
+ SECU_PrintInteger(stdout, &pqg->base, "BASE:", 0);
+}
+
+static void
+dump_dsakey(DSAPrivateKey *key)
+{
+ dump_pqg(&key->params);
+ SECU_PrintInteger(stdout, &key->publicValue, "PUBLIC VALUE:", 0);
+ SECU_PrintInteger(stdout, &key->privateValue, "PRIVATE VALUE:", 0);
+}
+
+#ifndef NSS_DISABLE_ECC
+static void
+dump_ecp(ECParams *ecp)
+{
+ /* TODO other fields */
+ SECU_PrintInteger(stdout, &ecp->base, "BASE POINT:", 0);
+}
+
+static void
+dump_eckey(ECPrivateKey *key)
+{
+ dump_ecp(&key->ecParams);
+ SECU_PrintInteger(stdout, &key->publicValue, "PUBLIC VALUE:", 0);
+ SECU_PrintInteger(stdout, &key->privateValue, "PRIVATE VALUE:", 0);
+}
+#endif
+
+static void
+dump_rsakey(RSAPrivateKey *key)
+{
+ SECU_PrintInteger(stdout, &key->version, "VERSION:", 0);
+ SECU_PrintInteger(stdout, &key->modulus, "MODULUS:", 0);
+ SECU_PrintInteger(stdout, &key->publicExponent, "PUBLIC EXP:", 0);
+ SECU_PrintInteger(stdout, &key->privateExponent, "PRIVATE EXP:", 0);
+ SECU_PrintInteger(stdout, &key->prime1, "CRT PRIME 1:", 0);
+ SECU_PrintInteger(stdout, &key->prime2, "CRT PRIME 2:", 0);
+ SECU_PrintInteger(stdout, &key->exponent1, "CRT EXP 1:", 0);
+ SECU_PrintInteger(stdout, &key->exponent2, "CRT EXP 2:", 0);
+ SECU_PrintInteger(stdout, &key->coefficient, "CRT COEFFICIENT:", 0);
+}
+
+typedef enum {
+ bltestBase64Encoded, /* Base64 encoded ASCII */
+ bltestBinary, /* straight binary */
+ bltestHexSpaceDelim, /* 0x12 0x34 0xab 0xCD ... */
+ bltestHexStream /* 1234abCD ... */
+} bltestIOMode;
+
+typedef struct
+{
+ SECItem buf;
+ SECItem pBuf;
+ bltestIOMode mode;
+ PRFileDesc *file;
+} bltestIO;
+
+typedef SECStatus (*bltestSymmCipherFn)(void *cx,
+ unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen);
+
+typedef SECStatus (*bltestAEADFn)(void *cx,
+ unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ const unsigned char *nonce,
+ unsigned int nonceLen,
+ const unsigned char *ad,
+ unsigned int adLen);
+
+typedef SECStatus (*bltestPubKeyCipherFn)(void *key,
+ SECItem *output,
+ const SECItem *input);
+
+typedef SECStatus (*bltestHashCipherFn)(unsigned char *dest,
+ const unsigned char *src,
+ PRUint32 src_length);
+
+/* Note: Algorithms are grouped in order to support is_symmkeyCipher /
+ * is_pubkeyCipher / is_hashCipher / is_sigCipher
+ */
+typedef enum {
+ bltestINVALID = -1,
+ bltestDES_ECB, /* Symmetric Key Ciphers */
+ bltestDES_CBC, /* . */
+ bltestDES_EDE_ECB, /* . */
+ bltestDES_EDE_CBC, /* . */
+ bltestRC2_ECB, /* . */
+ bltestRC2_CBC, /* . */
+ bltestRC4, /* . */
+#ifdef NSS_SOFTOKEN_DOES_RC5
+ bltestRC5_ECB, /* . */
+ bltestRC5_CBC, /* . */
+#endif
+ bltestAES_ECB, /* . */
+ bltestAES_CBC, /* . */
+ bltestAES_CTS, /* . */
+ bltestAES_CTR, /* . */
+ bltestAES_GCM, /* . */
+ bltestCAMELLIA_ECB, /* . */
+ bltestCAMELLIA_CBC, /* . */
+ bltestSEED_ECB, /* SEED algorithm */
+ bltestSEED_CBC, /* SEED algorithm */
+ bltestCHACHA20, /* ChaCha20 + Poly1305 */
+ bltestRSA, /* Public Key Ciphers */
+ bltestRSA_OAEP, /* . (Public Key Enc.) */
+ bltestRSA_PSS, /* . (Public Key Sig.) */
+#ifndef NSS_DISABLE_ECC
+ bltestECDSA, /* . (Public Key Sig.) */
+#endif
+ bltestDSA, /* . (Public Key Sig.) */
+ bltestMD2, /* Hash algorithms */
+ bltestMD5, /* . */
+ bltestSHA1, /* . */
+ bltestSHA224, /* . */
+ bltestSHA256, /* . */
+ bltestSHA384, /* . */
+ bltestSHA512, /* . */
+ NUMMODES
+} bltestCipherMode;
+
+static char *mode_strings[] =
+ {
+ "des_ecb",
+ "des_cbc",
+ "des3_ecb",
+ "des3_cbc",
+ "rc2_ecb",
+ "rc2_cbc",
+ "rc4",
+#ifdef NSS_SOFTOKEN_DOES_RC5
+ "rc5_ecb",
+ "rc5_cbc",
+#endif
+ "aes_ecb",
+ "aes_cbc",
+ "aes_cts",
+ "aes_ctr",
+ "aes_gcm",
+ "camellia_ecb",
+ "camellia_cbc",
+ "seed_ecb",
+ "seed_cbc",
+ "chacha20_poly1305",
+ "rsa",
+ "rsa_oaep",
+ "rsa_pss",
+#ifndef NSS_DISABLE_ECC
+ "ecdsa",
+#endif
+ /*"pqg",*/
+ "dsa",
+ "md2",
+ "md5",
+ "sha1",
+ "sha224",
+ "sha256",
+ "sha384",
+ "sha512",
+ };
+
+typedef struct
+{
+ bltestIO key;
+ bltestIO iv;
+} bltestSymmKeyParams;
+
+typedef struct
+{
+ bltestSymmKeyParams sk; /* must be first */
+ bltestIO aad;
+} bltestAuthSymmKeyParams;
+
+typedef struct
+{
+ bltestIO key;
+ bltestIO iv;
+ int rounds;
+ int wordsize;
+} bltestRC5Params;
+
+typedef struct
+{
+ bltestIO key;
+ int keysizeInBits;
+
+ /* OAEP & PSS */
+ HASH_HashType hashAlg;
+ HASH_HashType maskHashAlg;
+ bltestIO seed; /* salt if PSS */
+} bltestRSAParams;
+
+typedef struct
+{
+ bltestIO pqgdata;
+ unsigned int keysize;
+ bltestIO keyseed;
+ bltestIO sigseed;
+ PQGParams *pqg;
+} bltestDSAParams;
+
+#ifndef NSS_DISABLE_ECC
+typedef struct
+{
+ char *curveName;
+ bltestIO sigseed;
+} bltestECDSAParams;
+#endif
+
+typedef struct
+{
+ bltestIO key;
+ void *privKey;
+ void *pubKey;
+ bltestIO sig; /* if doing verify, the signature (which may come
+ * from sigfile. */
+
+ union {
+ bltestRSAParams rsa;
+ bltestDSAParams dsa;
+#ifndef NSS_DISABLE_ECC
+ bltestECDSAParams ecdsa;
+#endif
+ } cipherParams;
+} bltestAsymKeyParams;
+
+typedef struct
+{
+ bltestIO key; /* unused */
+ PRBool restart;
+} bltestHashParams;
+
+typedef union {
+ bltestIO key;
+ bltestSymmKeyParams sk;
+ bltestAuthSymmKeyParams ask;
+ bltestRC5Params rc5;
+ bltestAsymKeyParams asymk;
+ bltestHashParams hash;
+} bltestParams;
+
+typedef struct bltestCipherInfoStr bltestCipherInfo;
+
+struct bltestCipherInfoStr {
+ PLArenaPool *arena;
+ /* link to next in multithreaded test */
+ bltestCipherInfo *next;
+ PRThread *cipherThread;
+
+ /* MonteCarlo test flag*/
+ PRBool mCarlo;
+ /* cipher context */
+ void *cx;
+ /* I/O streams */
+ bltestIO input;
+ bltestIO output;
+ /* Cipher-specific parameters */
+ bltestParams params;
+ /* Cipher mode */
+ bltestCipherMode mode;
+ /* Cipher function (encrypt/decrypt/sign/verify/hash) */
+ union {
+ bltestSymmCipherFn symmkeyCipher;
+ bltestAEADFn aeadCipher;
+ bltestPubKeyCipherFn pubkeyCipher;
+ bltestHashCipherFn hashCipher;
+ } cipher;
+ /* performance testing */
+ int repetitionsToPerfom;
+ int seconds;
+ int repetitions;
+ int cxreps;
+ double cxtime;
+ double optime;
+};
+
+PRBool
+is_symmkeyCipher(bltestCipherMode mode)
+{
+ /* change as needed! */
+ if (mode >= bltestDES_ECB && mode <= bltestSEED_CBC)
+ return PR_TRUE;
+ return PR_FALSE;
+}
+
+PRBool
+is_aeadCipher(bltestCipherMode mode)
+{
+ /* change as needed! */
+ switch (mode) {
+ case bltestCHACHA20:
+ return PR_TRUE;
+ default:
+ return PR_FALSE;
+ }
+}
+
+PRBool
+is_authCipher(bltestCipherMode mode)
+{
+ /* change as needed! */
+ switch (mode) {
+ case bltestAES_GCM:
+ case bltestCHACHA20:
+ return PR_TRUE;
+ default:
+ return PR_FALSE;
+ }
+}
+
+PRBool
+is_singleShotCipher(bltestCipherMode mode)
+{
+ /* change as needed! */
+ switch (mode) {
+ case bltestAES_GCM:
+ case bltestAES_CTS:
+ case bltestCHACHA20:
+ return PR_TRUE;
+ default:
+ return PR_FALSE;
+ }
+}
+
+PRBool
+is_pubkeyCipher(bltestCipherMode mode)
+{
+ /* change as needed! */
+ if (mode >= bltestRSA && mode <= bltestDSA)
+ return PR_TRUE;
+ return PR_FALSE;
+}
+
+PRBool
+is_hashCipher(bltestCipherMode mode)
+{
+ /* change as needed! */
+ if (mode >= bltestMD2 && mode <= bltestSHA512)
+ return PR_TRUE;
+ return PR_FALSE;
+}
+
+PRBool
+is_sigCipher(bltestCipherMode mode)
+{
+ /* change as needed! */
+ if (mode >= bltestRSA_PSS && mode <= bltestDSA)
+ return PR_TRUE;
+ return PR_FALSE;
+}
+
+PRBool
+cipher_requires_IV(bltestCipherMode mode)
+{
+ /* change as needed! */
+ switch (mode) {
+ case bltestDES_CBC:
+ case bltestDES_EDE_CBC:
+ case bltestRC2_CBC:
+#ifdef NSS_SOFTOKEN_DOES_RC5
+ case bltestRC5_CBC:
+#endif
+ case bltestAES_CBC:
+ case bltestAES_CTS:
+ case bltestAES_CTR:
+ case bltestAES_GCM:
+ case bltestCAMELLIA_CBC:
+ case bltestSEED_CBC:
+ case bltestCHACHA20:
+ return PR_TRUE;
+ default:
+ return PR_FALSE;
+ }
+}
+
+SECStatus finishIO(bltestIO *output, PRFileDesc *file);
+
+SECStatus
+setupIO(PLArenaPool *arena, bltestIO *input, PRFileDesc *file,
+ char *str, int numBytes)
+{
+ SECStatus rv = SECSuccess;
+ SECItem fileData;
+ SECItem *in;
+ unsigned char *tok;
+ unsigned int i, j;
+
+ if (file && (numBytes == 0 || file == PR_STDIN)) {
+ /* grabbing data from a file */
+ rv = SECU_FileToItem(&fileData, file);
+ if (rv != SECSuccess)
+ return SECFailure;
+ in = &fileData;
+ } else if (str) {
+ /* grabbing data from command line */
+ fileData.data = (unsigned char *)str;
+ fileData.len = PL_strlen(str);
+ in = &fileData;
+ } else if (file) {
+ /* create nonce */
+ SECITEM_AllocItem(arena, &input->buf, numBytes);
+ RNG_GenerateGlobalRandomBytes(input->buf.data, numBytes);
+ return finishIO(input, file);
+ } else {
+ return SECFailure;
+ }
+
+ switch (input->mode) {
+ case bltestBase64Encoded:
+ if (in->len == 0) {
+ input->buf.data = NULL;
+ input->buf.len = 0;
+ break;
+ }
+ rv = atob(in, &input->buf, arena);
+ break;
+ case bltestBinary:
+ if (in->len == 0) {
+ input->buf.data = NULL;
+ input->buf.len = 0;
+ break;
+ }
+ if (in->data[in->len - 1] == '\n')
+ --in->len;
+ if (in->data[in->len - 1] == '\r')
+ --in->len;
+ SECITEM_CopyItem(arena, &input->buf, in);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ break;
+ case bltestHexSpaceDelim:
+ SECITEM_AllocItem(arena, &input->buf, in->len / 5);
+ for (i = 0, j = 0; i < in->len; i += 5, j++) {
+ tok = &in->data[i];
+ if (tok[0] != '0' || tok[1] != 'x' || tok[4] != ' ')
+ /* bad hex token */
+ break;
+
+ rv = hex_from_2char(&tok[2], input->buf.data + j);
+ if (rv)
+ break;
+ }
+ break;
+ case bltestHexStream:
+ SECITEM_AllocItem(arena, &input->buf, in->len / 2);
+ for (i = 0, j = 0; i < in->len; i += 2, j++) {
+ tok = &in->data[i];
+ rv = hex_from_2char(tok, input->buf.data + j);
+ if (rv)
+ break;
+ }
+ break;
+ }
+
+ if (file)
+ SECITEM_FreeItem(&fileData, PR_FALSE);
+ return rv;
+}
+
+SECStatus
+finishIO(bltestIO *output, PRFileDesc *file)
+{
+ SECStatus rv = SECSuccess;
+ PRInt32 nb;
+ unsigned char byteval;
+ SECItem *it;
+ char hexstr[5];
+ unsigned int i;
+ if (output->pBuf.len > 0) {
+ it = &output->pBuf;
+ } else {
+ it = &output->buf;
+ }
+ switch (output->mode) {
+ case bltestBase64Encoded:
+ rv = btoa_file(it, file);
+ break;
+ case bltestBinary:
+ nb = PR_Write(file, it->data, it->len);
+ rv = (nb == (PRInt32)it->len) ? SECSuccess : SECFailure;
+ break;
+ case bltestHexSpaceDelim:
+ hexstr[0] = '0';
+ hexstr[1] = 'x';
+ hexstr[4] = ' ';
+ for (i = 0; i < it->len; i++) {
+ byteval = it->data[i];
+ rv = char2_from_hex(byteval, hexstr + 2);
+ nb = PR_Write(file, hexstr, 5);
+ if (rv)
+ break;
+ }
+ PR_Write(file, "\n", 1);
+ break;
+ case bltestHexStream:
+ for (i = 0; i < it->len; i++) {
+ byteval = it->data[i];
+ rv = char2_from_hex(byteval, hexstr);
+ if (rv)
+ break;
+ nb = PR_Write(file, hexstr, 2);
+ }
+ PR_Write(file, "\n", 1);
+ break;
+ }
+ return rv;
+}
+
+SECStatus
+bltestCopyIO(PLArenaPool *arena, bltestIO *dest, bltestIO *src)
+{
+ if (SECITEM_CopyItem(arena, &dest->buf, &src->buf) != SECSuccess) {
+ return SECFailure;
+ }
+ if (src->pBuf.len > 0) {
+ dest->pBuf.len = src->pBuf.len;
+ dest->pBuf.data = dest->buf.data + (src->pBuf.data - src->buf.data);
+ }
+ dest->mode = src->mode;
+ dest->file = src->file;
+
+ return SECSuccess;
+}
+
+void
+misalignBuffer(PLArenaPool *arena, bltestIO *io, int off)
+{
+ ptrdiff_t offset = (ptrdiff_t)io->buf.data % WORDSIZE;
+ int length = io->buf.len;
+ if (offset != off) {
+ SECITEM_ReallocItemV2(arena, &io->buf, length + 2 * WORDSIZE);
+ /* offset may have changed? */
+ offset = (ptrdiff_t)io->buf.data % WORDSIZE;
+ if (offset != off) {
+ memmove(io->buf.data + off, io->buf.data, length);
+ io->pBuf.data = io->buf.data + off;
+ io->pBuf.len = length;
+ } else {
+ io->pBuf.data = io->buf.data;
+ io->pBuf.len = length;
+ }
+ } else {
+ io->pBuf.data = io->buf.data;
+ io->pBuf.len = length;
+ }
+}
+
+SECStatus
+des_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return DES_Encrypt((DESContext *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+des_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return DES_Decrypt((DESContext *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+rc2_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return RC2_Encrypt((RC2Context *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+rc2_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return RC2_Decrypt((RC2Context *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+rc4_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return RC4_Encrypt((RC4Context *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+rc4_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return RC4_Decrypt((RC4Context *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+aes_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return AES_Encrypt((AESContext *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+aes_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return AES_Decrypt((AESContext *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+chacha20_poly1305_Encrypt(void *cx, unsigned char *output,
+ unsigned int *outputLen, unsigned int maxOutputLen,
+ const unsigned char *input, unsigned int inputLen,
+ const unsigned char *nonce, unsigned int nonceLen,
+ const unsigned char *ad, unsigned int adLen)
+{
+ return ChaCha20Poly1305_Seal((ChaCha20Poly1305Context *)cx, output,
+ outputLen, maxOutputLen, input, inputLen,
+ nonce, nonceLen, ad, adLen);
+}
+
+SECStatus
+chacha20_poly1305_Decrypt(void *cx, unsigned char *output,
+ unsigned int *outputLen, unsigned int maxOutputLen,
+ const unsigned char *input, unsigned int inputLen,
+ const unsigned char *nonce, unsigned int nonceLen,
+ const unsigned char *ad, unsigned int adLen)
+{
+ return ChaCha20Poly1305_Open((ChaCha20Poly1305Context *)cx, output,
+ outputLen, maxOutputLen, input, inputLen,
+ nonce, nonceLen, ad, adLen);
+}
+
+SECStatus
+camellia_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return Camellia_Encrypt((CamelliaContext *)cx, output, outputLen,
+ maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+camellia_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return Camellia_Decrypt((CamelliaContext *)cx, output, outputLen,
+ maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+seed_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return SEED_Encrypt((SEEDContext *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+seed_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return SEED_Decrypt((SEEDContext *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+rsa_PublicKeyOp(void *cx, SECItem *output, const SECItem *input)
+{
+ bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
+ RSAPublicKey *pubKey = (RSAPublicKey *)params->pubKey;
+ SECStatus rv = RSA_PublicKeyOp(pubKey, output->data, input->data);
+ if (rv == SECSuccess) {
+ output->len = pubKey->modulus.data[0] ? pubKey->modulus.len : pubKey->modulus.len - 1;
+ }
+ return rv;
+}
+
+SECStatus
+rsa_PrivateKeyOp(void *cx, SECItem *output, const SECItem *input)
+{
+ bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
+ RSAPrivateKey *privKey = (RSAPrivateKey *)params->privKey;
+ SECStatus rv = RSA_PrivateKeyOp(privKey, output->data, input->data);
+ if (rv == SECSuccess) {
+ output->len = privKey->modulus.data[0] ? privKey->modulus.len : privKey->modulus.len - 1;
+ }
+ return rv;
+}
+
+SECStatus
+rsa_signDigestPSS(void *cx, SECItem *output, const SECItem *input)
+{
+ bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
+ bltestRSAParams *rsaParams = &params->cipherParams.rsa;
+ return RSA_SignPSS((RSAPrivateKey *)params->privKey,
+ rsaParams->hashAlg,
+ rsaParams->maskHashAlg,
+ rsaParams->seed.buf.data,
+ rsaParams->seed.buf.len,
+ output->data, &output->len, output->len,
+ input->data, input->len);
+}
+
+SECStatus
+rsa_verifyDigestPSS(void *cx, SECItem *output, const SECItem *input)
+{
+ bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
+ bltestRSAParams *rsaParams = &params->cipherParams.rsa;
+ return RSA_CheckSignPSS((RSAPublicKey *)params->pubKey,
+ rsaParams->hashAlg,
+ rsaParams->maskHashAlg,
+ rsaParams->seed.buf.len,
+ output->data, output->len,
+ input->data, input->len);
+}
+
+SECStatus
+rsa_encryptOAEP(void *cx, SECItem *output, const SECItem *input)
+{
+ bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
+ bltestRSAParams *rsaParams = &params->cipherParams.rsa;
+ return RSA_EncryptOAEP((RSAPublicKey *)params->pubKey,
+ rsaParams->hashAlg,
+ rsaParams->maskHashAlg,
+ NULL, 0,
+ rsaParams->seed.buf.data,
+ rsaParams->seed.buf.len,
+ output->data, &output->len, output->len,
+ input->data, input->len);
+}
+
+SECStatus
+rsa_decryptOAEP(void *cx, SECItem *output, const SECItem *input)
+{
+ bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
+ bltestRSAParams *rsaParams = &params->cipherParams.rsa;
+ return RSA_DecryptOAEP((RSAPrivateKey *)params->privKey,
+ rsaParams->hashAlg,
+ rsaParams->maskHashAlg,
+ NULL, 0,
+ output->data, &output->len, output->len,
+ input->data, input->len);
+}
+
+SECStatus
+dsa_signDigest(void *cx, SECItem *output, const SECItem *input)
+{
+ bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
+ if (params->cipherParams.dsa.sigseed.buf.len > 0) {
+ return DSA_SignDigestWithSeed((DSAPrivateKey *)params->privKey,
+ output, input,
+ params->cipherParams.dsa.sigseed.buf.data);
+ }
+ return DSA_SignDigest((DSAPrivateKey *)params->privKey, output, input);
+}
+
+SECStatus
+dsa_verifyDigest(void *cx, SECItem *output, const SECItem *input)
+{
+ bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
+ return DSA_VerifyDigest((DSAPublicKey *)params->pubKey, output, input);
+}
+
+#ifndef NSS_DISABLE_ECC
+SECStatus
+ecdsa_signDigest(void *cx, SECItem *output, const SECItem *input)
+{
+ bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
+ if (params->cipherParams.ecdsa.sigseed.buf.len > 0) {
+ return ECDSA_SignDigestWithSeed(
+ (ECPrivateKey *)params->privKey,
+ output, input,
+ params->cipherParams.ecdsa.sigseed.buf.data,
+ params->cipherParams.ecdsa.sigseed.buf.len);
+ }
+ return ECDSA_SignDigest((ECPrivateKey *)params->privKey, output, input);
+}
+
+SECStatus
+ecdsa_verifyDigest(void *cx, SECItem *output, const SECItem *input)
+{
+ bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
+ return ECDSA_VerifyDigest((ECPublicKey *)params->pubKey, output, input);
+}
+#endif
+
+SECStatus
+bltest_des_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ PRIntervalTime time1, time2;
+ bltestSymmKeyParams *desp = &cipherInfo->params.sk;
+ int minorMode;
+ int i;
+ switch (cipherInfo->mode) {
+ case bltestDES_ECB:
+ minorMode = NSS_DES;
+ break;
+ case bltestDES_CBC:
+ minorMode = NSS_DES_CBC;
+ break;
+ case bltestDES_EDE_ECB:
+ minorMode = NSS_DES_EDE3;
+ break;
+ case bltestDES_EDE_CBC:
+ minorMode = NSS_DES_EDE3_CBC;
+ break;
+ default:
+ return SECFailure;
+ }
+ cipherInfo->cx = (void *)DES_CreateContext(desp->key.buf.data,
+ desp->iv.buf.data,
+ minorMode, encrypt);
+ if (cipherInfo->cxreps > 0) {
+ DESContext **dummycx;
+ dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(DESContext *));
+ TIMESTART();
+ for (i = 0; i < cipherInfo->cxreps; i++) {
+ dummycx[i] = (void *)DES_CreateContext(desp->key.buf.data,
+ desp->iv.buf.data,
+ minorMode, encrypt);
+ }
+ TIMEFINISH(cipherInfo->cxtime, 1.0);
+ for (i = 0; i < cipherInfo->cxreps; i++) {
+ DES_DestroyContext(dummycx[i], PR_TRUE);
+ }
+ PORT_Free(dummycx);
+ }
+ if (encrypt)
+ cipherInfo->cipher.symmkeyCipher = des_Encrypt;
+ else
+ cipherInfo->cipher.symmkeyCipher = des_Decrypt;
+ return SECSuccess;
+}
+
+SECStatus
+bltest_rc2_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ PRIntervalTime time1, time2;
+ bltestSymmKeyParams *rc2p = &cipherInfo->params.sk;
+ int minorMode;
+ int i;
+ switch (cipherInfo->mode) {
+ case bltestRC2_ECB:
+ minorMode = NSS_RC2;
+ break;
+ case bltestRC2_CBC:
+ minorMode = NSS_RC2_CBC;
+ break;
+ default:
+ return SECFailure;
+ }
+ cipherInfo->cx = (void *)RC2_CreateContext(rc2p->key.buf.data,
+ rc2p->key.buf.len,
+ rc2p->iv.buf.data,
+ minorMode,
+ rc2p->key.buf.len);
+ if (cipherInfo->cxreps > 0) {
+ RC2Context **dummycx;
+ dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(RC2Context *));
+ TIMESTART();
+ for (i = 0; i < cipherInfo->cxreps; i++) {
+ dummycx[i] = (void *)RC2_CreateContext(rc2p->key.buf.data,
+ rc2p->key.buf.len,
+ rc2p->iv.buf.data,
+ minorMode,
+ rc2p->key.buf.len);
+ }
+ TIMEFINISH(cipherInfo->cxtime, 1.0);
+ for (i = 0; i < cipherInfo->cxreps; i++) {
+ RC2_DestroyContext(dummycx[i], PR_TRUE);
+ }
+ PORT_Free(dummycx);
+ }
+ if (encrypt)
+ cipherInfo->cipher.symmkeyCipher = rc2_Encrypt;
+ else
+ cipherInfo->cipher.symmkeyCipher = rc2_Decrypt;
+ return SECSuccess;
+}
+
+SECStatus
+bltest_rc4_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ PRIntervalTime time1, time2;
+ int i;
+ bltestSymmKeyParams *rc4p = &cipherInfo->params.sk;
+ cipherInfo->cx = (void *)RC4_CreateContext(rc4p->key.buf.data,
+ rc4p->key.buf.len);
+ if (cipherInfo->cxreps > 0) {
+ RC4Context **dummycx;
+ dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(RC4Context *));
+ TIMESTART();
+ for (i = 0; i < cipherInfo->cxreps; i++) {
+ dummycx[i] = (void *)RC4_CreateContext(rc4p->key.buf.data,
+ rc4p->key.buf.len);
+ }
+ TIMEFINISH(cipherInfo->cxtime, 1.0);
+ for (i = 0; i < cipherInfo->cxreps; i++) {
+ RC4_DestroyContext(dummycx[i], PR_TRUE);
+ }
+ PORT_Free(dummycx);
+ }
+ if (encrypt)
+ cipherInfo->cipher.symmkeyCipher = rc4_Encrypt;
+ else
+ cipherInfo->cipher.symmkeyCipher = rc4_Decrypt;
+ return SECSuccess;
+}
+
+SECStatus
+bltest_rc5_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+#ifdef NSS_SOFTOKEN_DOES_RC5
+ PRIntervalTime time1, time2;
+ bltestRC5Params *rc5p = &cipherInfo->params.rc5;
+ int minorMode;
+ switch (cipherInfo->mode) {
+ case bltestRC5_ECB:
+ minorMode = NSS_RC5;
+ break;
+ case bltestRC5_CBC:
+ minorMode = NSS_RC5_CBC;
+ break;
+ default:
+ return SECFailure;
+ }
+ TIMESTART();
+ cipherInfo->cx = (void *)RC5_CreateContext(&rc5p->key.buf,
+ rc5p->rounds, rc5p->wordsize,
+ rc5p->iv.buf.data, minorMode);
+ TIMEFINISH(cipherInfo->cxtime, 1.0);
+ if (encrypt)
+ cipherInfo->cipher.symmkeyCipher = RC5_Encrypt;
+ else
+ cipherInfo->cipher.symmkeyCipher = RC5_Decrypt;
+ return SECSuccess;
+#else
+ return SECFailure;
+#endif
+}
+
+SECStatus
+bltest_aes_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ bltestSymmKeyParams *aesp = &cipherInfo->params.sk;
+ bltestAuthSymmKeyParams *gcmp = &cipherInfo->params.ask;
+ int minorMode;
+ int i;
+ int keylen = aesp->key.buf.len;
+ unsigned int blocklen = AES_BLOCK_SIZE;
+ PRIntervalTime time1, time2;
+ unsigned char *params;
+ int len;
+ CK_AES_CTR_PARAMS ctrParams;
+ CK_GCM_PARAMS gcmParams;
+
+ params = aesp->iv.buf.data;
+ switch (cipherInfo->mode) {
+ case bltestAES_ECB:
+ minorMode = NSS_AES;
+ break;
+ case bltestAES_CBC:
+ minorMode = NSS_AES_CBC;
+ break;
+ case bltestAES_CTS:
+ minorMode = NSS_AES_CTS;
+ break;
+ case bltestAES_CTR:
+ minorMode = NSS_AES_CTR;
+ ctrParams.ulCounterBits = 32;
+ len = PR_MIN(aesp->iv.buf.len, blocklen);
+ PORT_Memset(ctrParams.cb, 0, blocklen);
+ PORT_Memcpy(ctrParams.cb, aesp->iv.buf.data, len);
+ params = (unsigned char *)&ctrParams;
+ break;
+ case bltestAES_GCM:
+ minorMode = NSS_AES_GCM;
+ gcmParams.pIv = gcmp->sk.iv.buf.data;
+ gcmParams.ulIvLen = gcmp->sk.iv.buf.len;
+ gcmParams.pAAD = gcmp->aad.buf.data;
+ gcmParams.ulAADLen = gcmp->aad.buf.len;
+ gcmParams.ulTagBits = blocklen * 8;
+ params = (unsigned char *)&gcmParams;
+ break;
+ default:
+ return SECFailure;
+ }
+ cipherInfo->cx = (void *)AES_CreateContext(aesp->key.buf.data,
+ params,
+ minorMode, encrypt,
+ keylen, blocklen);
+ if (cipherInfo->cxreps > 0) {
+ AESContext **dummycx;
+ dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(AESContext *));
+ TIMESTART();
+ for (i = 0; i < cipherInfo->cxreps; i++) {
+ dummycx[i] = (void *)AES_CreateContext(aesp->key.buf.data,
+ params,
+ minorMode, encrypt,
+ keylen, blocklen);
+ }
+ TIMEFINISH(cipherInfo->cxtime, 1.0);
+ for (i = 0; i < cipherInfo->cxreps; i++) {
+ AES_DestroyContext(dummycx[i], PR_TRUE);
+ }
+ PORT_Free(dummycx);
+ }
+ if (encrypt)
+ cipherInfo->cipher.symmkeyCipher = aes_Encrypt;
+ else
+ cipherInfo->cipher.symmkeyCipher = aes_Decrypt;
+ return SECSuccess;
+}
+
+SECStatus
+bltest_camellia_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ bltestSymmKeyParams *camelliap = &cipherInfo->params.sk;
+ int minorMode;
+ int i;
+ int keylen = camelliap->key.buf.len;
+ PRIntervalTime time1, time2;
+
+ switch (cipherInfo->mode) {
+ case bltestCAMELLIA_ECB:
+ minorMode = NSS_CAMELLIA;
+ break;
+ case bltestCAMELLIA_CBC:
+ minorMode = NSS_CAMELLIA_CBC;
+ break;
+ default:
+ return SECFailure;
+ }
+ cipherInfo->cx = (void *)Camellia_CreateContext(camelliap->key.buf.data,
+ camelliap->iv.buf.data,
+ minorMode, encrypt,
+ keylen);
+ if (cipherInfo->cxreps > 0) {
+ CamelliaContext **dummycx;
+ dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(CamelliaContext *));
+ TIMESTART();
+ for (i = 0; i < cipherInfo->cxreps; i++) {
+ dummycx[i] = (void *)Camellia_CreateContext(camelliap->key.buf.data,
+ camelliap->iv.buf.data,
+ minorMode, encrypt,
+ keylen);
+ }
+ TIMEFINISH(cipherInfo->cxtime, 1.0);
+ for (i = 0; i < cipherInfo->cxreps; i++) {
+ Camellia_DestroyContext(dummycx[i], PR_TRUE);
+ }
+ PORT_Free(dummycx);
+ }
+ if (encrypt)
+ cipherInfo->cipher.symmkeyCipher = camellia_Encrypt;
+ else
+ cipherInfo->cipher.symmkeyCipher = camellia_Decrypt;
+ return SECSuccess;
+}
+
+SECStatus
+bltest_seed_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ PRIntervalTime time1, time2;
+ bltestSymmKeyParams *seedp = &cipherInfo->params.sk;
+ int minorMode;
+ int i;
+
+ switch (cipherInfo->mode) {
+ case bltestSEED_ECB:
+ minorMode = NSS_SEED;
+ break;
+ case bltestSEED_CBC:
+ minorMode = NSS_SEED_CBC;
+ break;
+ default:
+ return SECFailure;
+ }
+ cipherInfo->cx = (void *)SEED_CreateContext(seedp->key.buf.data,
+ seedp->iv.buf.data,
+ minorMode, encrypt);
+ if (cipherInfo->cxreps > 0) {
+ SEEDContext **dummycx;
+ dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(SEEDContext *));
+ TIMESTART();
+ for (i = 0; i < cipherInfo->cxreps; i++) {
+ dummycx[i] = (void *)SEED_CreateContext(seedp->key.buf.data,
+ seedp->iv.buf.data,
+ minorMode, encrypt);
+ }
+ TIMEFINISH(cipherInfo->cxtime, 1.0);
+ for (i = 0; i < cipherInfo->cxreps; i++) {
+ SEED_DestroyContext(dummycx[i], PR_TRUE);
+ }
+ PORT_Free(dummycx);
+ }
+ if (encrypt)
+ cipherInfo->cipher.symmkeyCipher = seed_Encrypt;
+ else
+ cipherInfo->cipher.symmkeyCipher = seed_Decrypt;
+
+ return SECSuccess;
+}
+
+SECStatus
+bltest_chacha20_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ const unsigned int tagLen = 16;
+ const bltestSymmKeyParams *sk = &cipherInfo->params.sk;
+ cipherInfo->cx = ChaCha20Poly1305_CreateContext(sk->key.buf.data,
+ sk->key.buf.len, tagLen);
+
+ if (encrypt)
+ cipherInfo->cipher.aeadCipher = chacha20_poly1305_Encrypt;
+ else
+ cipherInfo->cipher.aeadCipher = chacha20_poly1305_Decrypt;
+ return SECSuccess;
+}
+
+SECStatus
+bltest_rsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ int i;
+ RSAPrivateKey **dummyKey;
+ RSAPrivateKey *privKey;
+ RSAPublicKey *pubKey;
+ PRIntervalTime time1, time2;
+
+ bltestAsymKeyParams *asymk = &cipherInfo->params.asymk;
+ bltestRSAParams *rsap = &asymk->cipherParams.rsa;
+
+ /* RSA key gen was done during parameter setup */
+ cipherInfo->cx = asymk;
+ privKey = (RSAPrivateKey *)asymk->privKey;
+
+ /* For performance testing */
+ if (cipherInfo->cxreps > 0) {
+ /* Create space for n private key objects */
+ dummyKey = (RSAPrivateKey **)PORT_Alloc(cipherInfo->cxreps *
+ sizeof(RSAPrivateKey *));
+ /* Time n keygens, storing in the array */
+ TIMESTART();
+ for (i = 0; i < cipherInfo->cxreps; i++)
+ dummyKey[i] = RSA_NewKey(rsap->keysizeInBits,
+ &privKey->publicExponent);
+ TIMEFINISH(cipherInfo->cxtime, cipherInfo->cxreps);
+ /* Free the n key objects */
+ for (i = 0; i < cipherInfo->cxreps; i++)
+ PORT_FreeArena(dummyKey[i]->arena, PR_TRUE);
+ PORT_Free(dummyKey);
+ }
+
+ if ((encrypt && !is_sigCipher(cipherInfo->mode)) ||
+ (!encrypt && is_sigCipher(cipherInfo->mode))) {
+ /* Have to convert private key to public key. Memory
+ * is freed with private key's arena */
+ pubKey = (RSAPublicKey *)PORT_ArenaAlloc(privKey->arena,
+ sizeof(RSAPublicKey));
+ pubKey->modulus.len = privKey->modulus.len;
+ pubKey->modulus.data = privKey->modulus.data;
+ pubKey->publicExponent.len = privKey->publicExponent.len;
+ pubKey->publicExponent.data = privKey->publicExponent.data;
+ asymk->pubKey = (void *)pubKey;
+ }
+ switch (cipherInfo->mode) {
+ case bltestRSA:
+ cipherInfo->cipher.pubkeyCipher = encrypt ? rsa_PublicKeyOp
+ : rsa_PrivateKeyOp;
+ break;
+ case bltestRSA_PSS:
+ cipherInfo->cipher.pubkeyCipher = encrypt ? rsa_signDigestPSS
+ : rsa_verifyDigestPSS;
+ break;
+ case bltestRSA_OAEP:
+ cipherInfo->cipher.pubkeyCipher = encrypt ? rsa_encryptOAEP
+ : rsa_decryptOAEP;
+ break;
+ default:
+ break;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+blapi_pqg_param_gen(unsigned int keysize, PQGParams **pqg, PQGVerify **vfy)
+{
+ if (keysize < 1024) {
+ int j = PQG_PBITS_TO_INDEX(keysize);
+ return PQG_ParamGen(j, pqg, vfy);
+ }
+ return PQG_ParamGenV2(keysize, 0, 0, pqg, vfy);
+}
+
+SECStatus
+bltest_pqg_init(bltestDSAParams *dsap)
+{
+ SECStatus rv, res;
+ PQGVerify *vfy = NULL;
+ rv = blapi_pqg_param_gen(dsap->keysize, &dsap->pqg, &vfy);
+ CHECKERROR(rv, __LINE__);
+ rv = PQG_VerifyParams(dsap->pqg, vfy, &res);
+ CHECKERROR(res, __LINE__);
+ CHECKERROR(rv, __LINE__);
+ return rv;
+}
+
+SECStatus
+bltest_dsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ int i;
+ DSAPrivateKey **dummyKey;
+ PQGParams *dummypqg;
+ PRIntervalTime time1, time2;
+ bltestAsymKeyParams *asymk = &cipherInfo->params.asymk;
+ bltestDSAParams *dsap = &asymk->cipherParams.dsa;
+ PQGVerify *ignore = NULL;
+ cipherInfo->cx = asymk;
+ /* For performance testing */
+ if (cipherInfo->cxreps > 0) {
+ /* Create space for n private key objects */
+ dummyKey = (DSAPrivateKey **)PORT_ZAlloc(cipherInfo->cxreps *
+ sizeof(DSAPrivateKey *));
+ /* Time n keygens, storing in the array */
+ TIMESTART();
+ for (i = 0; i < cipherInfo->cxreps; i++) {
+ dummypqg = NULL;
+ blapi_pqg_param_gen(dsap->keysize, &dummypqg, &ignore);
+ DSA_NewKey(dummypqg, &dummyKey[i]);
+ }
+ TIMEFINISH(cipherInfo->cxtime, cipherInfo->cxreps);
+ /* Free the n key objects */
+ for (i = 0; i < cipherInfo->cxreps; i++)
+ PORT_FreeArena(dummyKey[i]->params.arena, PR_TRUE);
+ PORT_Free(dummyKey);
+ }
+ if (!dsap->pqg && dsap->pqgdata.buf.len > 0) {
+ dsap->pqg = pqg_from_filedata(cipherInfo->arena, &dsap->pqgdata.buf);
+ }
+ if (!asymk->privKey && asymk->key.buf.len > 0) {
+ asymk->privKey = dsakey_from_filedata(cipherInfo->arena, &asymk->key.buf);
+ }
+ if (encrypt) {
+ cipherInfo->cipher.pubkeyCipher = dsa_signDigest;
+ } else {
+ /* Have to convert private key to public key. Memory
+ * is freed with private key's arena */
+ DSAPublicKey *pubkey;
+ DSAPrivateKey *key = (DSAPrivateKey *)asymk->privKey;
+ pubkey = (DSAPublicKey *)PORT_ArenaZAlloc(key->params.arena,
+ sizeof(DSAPublicKey));
+ pubkey->params.prime.len = key->params.prime.len;
+ pubkey->params.prime.data = key->params.prime.data;
+ pubkey->params.subPrime.len = key->params.subPrime.len;
+ pubkey->params.subPrime.data = key->params.subPrime.data;
+ pubkey->params.base.len = key->params.base.len;
+ pubkey->params.base.data = key->params.base.data;
+ pubkey->publicValue.len = key->publicValue.len;
+ pubkey->publicValue.data = key->publicValue.data;
+ asymk->pubKey = pubkey;
+ cipherInfo->cipher.pubkeyCipher = dsa_verifyDigest;
+ }
+ return SECSuccess;
+}
+
+#ifndef NSS_DISABLE_ECC
+SECStatus
+bltest_ecdsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ int i;
+ ECPrivateKey **dummyKey;
+ PRIntervalTime time1, time2;
+ bltestAsymKeyParams *asymk = &cipherInfo->params.asymk;
+ cipherInfo->cx = asymk;
+ /* For performance testing */
+ if (cipherInfo->cxreps > 0) {
+ /* Create space for n private key objects */
+ dummyKey = (ECPrivateKey **)PORT_ZAlloc(cipherInfo->cxreps *
+ sizeof(ECPrivateKey *));
+ /* Time n keygens, storing in the array */
+ TIMESTART();
+ for (i = 0; i < cipherInfo->cxreps; i++) {
+ EC_NewKey(&((ECPrivateKey *)asymk->privKey)->ecParams, &dummyKey[i]);
+ }
+ TIMEFINISH(cipherInfo->cxtime, cipherInfo->cxreps);
+ /* Free the n key objects */
+ for (i = 0; i < cipherInfo->cxreps; i++)
+ PORT_FreeArena(dummyKey[i]->ecParams.arena, PR_TRUE);
+ PORT_Free(dummyKey);
+ }
+ if (!asymk->privKey && asymk->key.buf.len > 0) {
+ asymk->privKey = eckey_from_filedata(cipherInfo->arena, &asymk->key.buf);
+ }
+ if (encrypt) {
+ cipherInfo->cipher.pubkeyCipher = ecdsa_signDigest;
+ } else {
+ /* Have to convert private key to public key. Memory
+ * is freed with private key's arena */
+ ECPublicKey *pubkey;
+ ECPrivateKey *key = (ECPrivateKey *)asymk->privKey;
+ pubkey = (ECPublicKey *)PORT_ArenaZAlloc(key->ecParams.arena,
+ sizeof(ECPublicKey));
+ pubkey->ecParams.type = key->ecParams.type;
+ pubkey->ecParams.fieldID.size = key->ecParams.fieldID.size;
+ pubkey->ecParams.fieldID.type = key->ecParams.fieldID.type;
+ pubkey->ecParams.fieldID.u.prime.len = key->ecParams.fieldID.u.prime.len;
+ pubkey->ecParams.fieldID.u.prime.data = key->ecParams.fieldID.u.prime.data;
+ pubkey->ecParams.fieldID.k1 = key->ecParams.fieldID.k1;
+ pubkey->ecParams.fieldID.k2 = key->ecParams.fieldID.k2;
+ pubkey->ecParams.fieldID.k3 = key->ecParams.fieldID.k3;
+ pubkey->ecParams.curve.a.len = key->ecParams.curve.a.len;
+ pubkey->ecParams.curve.a.data = key->ecParams.curve.a.data;
+ pubkey->ecParams.curve.b.len = key->ecParams.curve.b.len;
+ pubkey->ecParams.curve.b.data = key->ecParams.curve.b.data;
+ pubkey->ecParams.curve.seed.len = key->ecParams.curve.seed.len;
+ pubkey->ecParams.curve.seed.data = key->ecParams.curve.seed.data;
+ pubkey->ecParams.base.len = key->ecParams.base.len;
+ pubkey->ecParams.base.data = key->ecParams.base.data;
+ pubkey->ecParams.order.len = key->ecParams.order.len;
+ pubkey->ecParams.order.data = key->ecParams.order.data;
+ pubkey->ecParams.cofactor = key->ecParams.cofactor;
+ pubkey->ecParams.DEREncoding.len = key->ecParams.DEREncoding.len;
+ pubkey->ecParams.DEREncoding.data = key->ecParams.DEREncoding.data;
+ pubkey->ecParams.name = key->ecParams.name;
+ pubkey->publicValue.len = key->publicValue.len;
+ pubkey->publicValue.data = key->publicValue.data;
+ asymk->pubKey = pubkey;
+ cipherInfo->cipher.pubkeyCipher = ecdsa_verifyDigest;
+ }
+ return SECSuccess;
+}
+#endif
+
+/* XXX unfortunately, this is not defined in blapi.h */
+SECStatus
+md2_HashBuf(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
+{
+ unsigned int len;
+ MD2Context *cx = MD2_NewContext();
+ if (cx == NULL)
+ return SECFailure;
+ MD2_Begin(cx);
+ MD2_Update(cx, src, src_length);
+ MD2_End(cx, dest, &len, MD2_LENGTH);
+ MD2_DestroyContext(cx, PR_TRUE);
+ return SECSuccess;
+}
+
+SECStatus
+md2_restart(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
+{
+ MD2Context *cx, *cx_cpy;
+ unsigned char *cxbytes;
+ unsigned int len;
+ unsigned int i, quarter;
+ SECStatus rv = SECSuccess;
+ cx = MD2_NewContext();
+ MD2_Begin(cx);
+ /* divide message by 4, restarting 3 times */
+ quarter = (src_length + 3) / 4;
+ for (i = 0; i < 4 && src_length > 0; i++) {
+ MD2_Update(cx, src + i * quarter, PR_MIN(quarter, src_length));
+ len = MD2_FlattenSize(cx);
+ cxbytes = PORT_Alloc(len);
+ MD2_Flatten(cx, cxbytes);
+ cx_cpy = MD2_Resurrect(cxbytes, NULL);
+ if (!cx_cpy) {
+ PR_fprintf(PR_STDERR, "%s: MD2_Resurrect failed!\n", progName);
+ goto finish;
+ }
+ rv = PORT_Memcmp(cx, cx_cpy, len);
+ if (rv) {
+ MD2_DestroyContext(cx_cpy, PR_TRUE);
+ PR_fprintf(PR_STDERR, "%s: MD2_restart failed!\n", progName);
+ goto finish;
+ }
+ MD2_DestroyContext(cx_cpy, PR_TRUE);
+ PORT_Free(cxbytes);
+ src_length -= quarter;
+ }
+ MD2_End(cx, dest, &len, MD2_LENGTH);
+finish:
+ MD2_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+SECStatus
+md5_restart(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
+{
+ SECStatus rv = SECSuccess;
+ MD5Context *cx, *cx_cpy;
+ unsigned char *cxbytes;
+ unsigned int len;
+ unsigned int i, quarter;
+ cx = MD5_NewContext();
+ MD5_Begin(cx);
+ /* divide message by 4, restarting 3 times */
+ quarter = (src_length + 3) / 4;
+ for (i = 0; i < 4 && src_length > 0; i++) {
+ MD5_Update(cx, src + i * quarter, PR_MIN(quarter, src_length));
+ len = MD5_FlattenSize(cx);
+ cxbytes = PORT_Alloc(len);
+ MD5_Flatten(cx, cxbytes);
+ cx_cpy = MD5_Resurrect(cxbytes, NULL);
+ if (!cx_cpy) {
+ PR_fprintf(PR_STDERR, "%s: MD5_Resurrect failed!\n", progName);
+ rv = SECFailure;
+ goto finish;
+ }
+ rv = PORT_Memcmp(cx, cx_cpy, len);
+ if (rv) {
+ MD5_DestroyContext(cx_cpy, PR_TRUE);
+ PR_fprintf(PR_STDERR, "%s: MD5_restart failed!\n", progName);
+ goto finish;
+ }
+ MD5_DestroyContext(cx_cpy, PR_TRUE);
+ PORT_Free(cxbytes);
+ src_length -= quarter;
+ }
+ MD5_End(cx, dest, &len, MD5_LENGTH);
+finish:
+ MD5_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+SECStatus
+sha1_restart(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
+{
+ SECStatus rv = SECSuccess;
+ SHA1Context *cx, *cx_cpy;
+ unsigned char *cxbytes;
+ unsigned int len;
+ unsigned int i, quarter;
+ cx = SHA1_NewContext();
+ SHA1_Begin(cx);
+ /* divide message by 4, restarting 3 times */
+ quarter = (src_length + 3) / 4;
+ for (i = 0; i < 4 && src_length > 0; i++) {
+ SHA1_Update(cx, src + i * quarter, PR_MIN(quarter, src_length));
+ len = SHA1_FlattenSize(cx);
+ cxbytes = PORT_Alloc(len);
+ SHA1_Flatten(cx, cxbytes);
+ cx_cpy = SHA1_Resurrect(cxbytes, NULL);
+ if (!cx_cpy) {
+ PR_fprintf(PR_STDERR, "%s: SHA1_Resurrect failed!\n", progName);
+ rv = SECFailure;
+ goto finish;
+ }
+ rv = PORT_Memcmp(cx, cx_cpy, len);
+ if (rv) {
+ SHA1_DestroyContext(cx_cpy, PR_TRUE);
+ PR_fprintf(PR_STDERR, "%s: SHA1_restart failed!\n", progName);
+ goto finish;
+ }
+ SHA1_DestroyContext(cx_cpy, PR_TRUE);
+ PORT_Free(cxbytes);
+ src_length -= quarter;
+ }
+ SHA1_End(cx, dest, &len, MD5_LENGTH);
+finish:
+ SHA1_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+SECStatus
+SHA224_restart(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
+{
+ SECStatus rv = SECSuccess;
+ SHA224Context *cx, *cx_cpy;
+ unsigned char *cxbytes;
+ unsigned int len;
+ unsigned int i, quarter;
+ cx = SHA224_NewContext();
+ SHA224_Begin(cx);
+ /* divide message by 4, restarting 3 times */
+ quarter = (src_length + 3) / 4;
+ for (i = 0; i < 4 && src_length > 0; i++) {
+ SHA224_Update(cx, src + i * quarter, PR_MIN(quarter, src_length));
+ len = SHA224_FlattenSize(cx);
+ cxbytes = PORT_Alloc(len);
+ SHA224_Flatten(cx, cxbytes);
+ cx_cpy = SHA224_Resurrect(cxbytes, NULL);
+ if (!cx_cpy) {
+ PR_fprintf(PR_STDERR, "%s: SHA224_Resurrect failed!\n", progName);
+ rv = SECFailure;
+ goto finish;
+ }
+ rv = PORT_Memcmp(cx, cx_cpy, len);
+ if (rv) {
+ SHA224_DestroyContext(cx_cpy, PR_TRUE);
+ PR_fprintf(PR_STDERR, "%s: SHA224_restart failed!\n", progName);
+ goto finish;
+ }
+
+ SHA224_DestroyContext(cx_cpy, PR_TRUE);
+ PORT_Free(cxbytes);
+ src_length -= quarter;
+ }
+ SHA224_End(cx, dest, &len, MD5_LENGTH);
+finish:
+ SHA224_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+SECStatus
+SHA256_restart(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
+{
+ SECStatus rv = SECSuccess;
+ SHA256Context *cx, *cx_cpy;
+ unsigned char *cxbytes;
+ unsigned int len;
+ unsigned int i, quarter;
+ cx = SHA256_NewContext();
+ SHA256_Begin(cx);
+ /* divide message by 4, restarting 3 times */
+ quarter = (src_length + 3) / 4;
+ for (i = 0; i < 4 && src_length > 0; i++) {
+ SHA256_Update(cx, src + i * quarter, PR_MIN(quarter, src_length));
+ len = SHA256_FlattenSize(cx);
+ cxbytes = PORT_Alloc(len);
+ SHA256_Flatten(cx, cxbytes);
+ cx_cpy = SHA256_Resurrect(cxbytes, NULL);
+ if (!cx_cpy) {
+ PR_fprintf(PR_STDERR, "%s: SHA256_Resurrect failed!\n", progName);
+ rv = SECFailure;
+ goto finish;
+ }
+ rv = PORT_Memcmp(cx, cx_cpy, len);
+ if (rv) {
+ SHA256_DestroyContext(cx_cpy, PR_TRUE);
+ PR_fprintf(PR_STDERR, "%s: SHA256_restart failed!\n", progName);
+ goto finish;
+ }
+ SHA256_DestroyContext(cx_cpy, PR_TRUE);
+ PORT_Free(cxbytes);
+ src_length -= quarter;
+ }
+ SHA256_End(cx, dest, &len, MD5_LENGTH);
+finish:
+ SHA256_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+SECStatus
+SHA384_restart(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
+{
+ SECStatus rv = SECSuccess;
+ SHA384Context *cx, *cx_cpy;
+ unsigned char *cxbytes;
+ unsigned int len;
+ unsigned int i, quarter;
+ cx = SHA384_NewContext();
+ SHA384_Begin(cx);
+ /* divide message by 4, restarting 3 times */
+ quarter = (src_length + 3) / 4;
+ for (i = 0; i < 4 && src_length > 0; i++) {
+ SHA384_Update(cx, src + i * quarter, PR_MIN(quarter, src_length));
+ len = SHA384_FlattenSize(cx);
+ cxbytes = PORT_Alloc(len);
+ SHA384_Flatten(cx, cxbytes);
+ cx_cpy = SHA384_Resurrect(cxbytes, NULL);
+ if (!cx_cpy) {
+ PR_fprintf(PR_STDERR, "%s: SHA384_Resurrect failed!\n", progName);
+ rv = SECFailure;
+ goto finish;
+ }
+ rv = PORT_Memcmp(cx, cx_cpy, len);
+ if (rv) {
+ SHA384_DestroyContext(cx_cpy, PR_TRUE);
+ PR_fprintf(PR_STDERR, "%s: SHA384_restart failed!\n", progName);
+ goto finish;
+ }
+ SHA384_DestroyContext(cx_cpy, PR_TRUE);
+ PORT_Free(cxbytes);
+ src_length -= quarter;
+ }
+ SHA384_End(cx, dest, &len, MD5_LENGTH);
+finish:
+ SHA384_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+SECStatus
+SHA512_restart(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
+{
+ SECStatus rv = SECSuccess;
+ SHA512Context *cx, *cx_cpy;
+ unsigned char *cxbytes;
+ unsigned int len;
+ unsigned int i, quarter;
+ cx = SHA512_NewContext();
+ SHA512_Begin(cx);
+ /* divide message by 4, restarting 3 times */
+ quarter = (src_length + 3) / 4;
+ for (i = 0; i < 4 && src_length > 0; i++) {
+ SHA512_Update(cx, src + i * quarter, PR_MIN(quarter, src_length));
+ len = SHA512_FlattenSize(cx);
+ cxbytes = PORT_Alloc(len);
+ SHA512_Flatten(cx, cxbytes);
+ cx_cpy = SHA512_Resurrect(cxbytes, NULL);
+ if (!cx_cpy) {
+ PR_fprintf(PR_STDERR, "%s: SHA512_Resurrect failed!\n", progName);
+ rv = SECFailure;
+ goto finish;
+ }
+ rv = PORT_Memcmp(cx, cx_cpy, len);
+ if (rv) {
+ SHA512_DestroyContext(cx_cpy, PR_TRUE);
+ PR_fprintf(PR_STDERR, "%s: SHA512_restart failed!\n", progName);
+ goto finish;
+ }
+ SHA512_DestroyContext(cx_cpy, PR_TRUE);
+ PORT_Free(cxbytes);
+ src_length -= quarter;
+ }
+ SHA512_End(cx, dest, &len, MD5_LENGTH);
+finish:
+ SHA512_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+SECStatus
+pubkeyInitKey(bltestCipherInfo *cipherInfo, PRFileDesc *file,
+#ifndef NSS_DISABLE_ECC
+ int keysize, int exponent, char *curveName)
+#else
+ int keysize, int exponent)
+#endif
+{
+ int i;
+ SECStatus rv = SECSuccess;
+ bltestAsymKeyParams *asymk = &cipherInfo->params.asymk;
+ bltestRSAParams *rsap;
+ RSAPrivateKey **rsaKey = NULL;
+ bltestDSAParams *dsap;
+ DSAPrivateKey **dsaKey = NULL;
+#ifndef NSS_DISABLE_ECC
+ SECItem *tmpECParamsDER;
+ ECParams *tmpECParams = NULL;
+ SECItem ecSerialize[3];
+ ECPrivateKey **ecKey = NULL;
+#endif
+ switch (cipherInfo->mode) {
+ case bltestRSA:
+ case bltestRSA_PSS:
+ case bltestRSA_OAEP:
+ rsap = &asymk->cipherParams.rsa;
+ rsaKey = (RSAPrivateKey **)&asymk->privKey;
+ if (keysize > 0) {
+ SECItem expitem = { 0, 0, 0 };
+ SECITEM_AllocItem(cipherInfo->arena, &expitem, sizeof(int));
+ for (i = 1; i <= sizeof(int); i++)
+ expitem.data[i - 1] = exponent >> (8 * (sizeof(int) - i));
+ *rsaKey = RSA_NewKey(keysize * 8, &expitem);
+ serialize_key(&(*rsaKey)->version, 9, file);
+ rsap->keysizeInBits = keysize * 8;
+ } else {
+ setupIO(cipherInfo->arena, &asymk->key, file, NULL, 0);
+ *rsaKey = rsakey_from_filedata(cipherInfo->arena, &asymk->key.buf);
+ rsap->keysizeInBits = (*rsaKey)->modulus.len * 8;
+ }
+ break;
+ case bltestDSA:
+ dsap = &asymk->cipherParams.dsa;
+ dsaKey = (DSAPrivateKey **)&asymk->privKey;
+ if (keysize > 0) {
+ dsap->keysize = keysize * 8;
+ if (!dsap->pqg)
+ bltest_pqg_init(dsap);
+ rv = DSA_NewKey(dsap->pqg, dsaKey);
+ CHECKERROR(rv, __LINE__);
+ serialize_key(&(*dsaKey)->params.prime, 5, file);
+ } else {
+ setupIO(cipherInfo->arena, &asymk->key, file, NULL, 0);
+ *dsaKey = dsakey_from_filedata(cipherInfo->arena, &asymk->key.buf);
+ dsap->keysize = (*dsaKey)->params.prime.len * 8;
+ }
+ break;
+#ifndef NSS_DISABLE_ECC
+ case bltestECDSA:
+ ecKey = (ECPrivateKey **)&asymk->privKey;
+ if (curveName != NULL) {
+ tmpECParamsDER = getECParams(curveName);
+ rv = SECOID_Init();
+ CHECKERROR(rv, __LINE__);
+ rv = EC_DecodeParams(tmpECParamsDER, &tmpECParams) == SECFailure;
+ CHECKERROR(rv, __LINE__);
+ rv = EC_NewKey(tmpECParams, ecKey);
+ CHECKERROR(rv, __LINE__);
+ ecSerialize[0].type = tmpECParamsDER->type;
+ ecSerialize[0].data = tmpECParamsDER->data;
+ ecSerialize[0].len = tmpECParamsDER->len;
+ ecSerialize[1].type = (*ecKey)->publicValue.type;
+ ecSerialize[1].data = (*ecKey)->publicValue.data;
+ ecSerialize[1].len = (*ecKey)->publicValue.len;
+ ecSerialize[2].type = (*ecKey)->privateValue.type;
+ ecSerialize[2].data = (*ecKey)->privateValue.data;
+ ecSerialize[2].len = (*ecKey)->privateValue.len;
+ serialize_key(&(ecSerialize[0]), 3, file);
+ SECITEM_FreeItem(tmpECParamsDER, PR_TRUE);
+ PORT_FreeArena(tmpECParams->arena, PR_TRUE);
+ rv = SECOID_Shutdown();
+ CHECKERROR(rv, __LINE__);
+ } else {
+ setupIO(cipherInfo->arena, &asymk->key, file, NULL, 0);
+ *ecKey = eckey_from_filedata(cipherInfo->arena, &asymk->key.buf);
+ }
+ break;
+#endif
+ default:
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+cipherInit(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ PRBool restart;
+ int outlen;
+ switch (cipherInfo->mode) {
+ case bltestDES_ECB:
+ case bltestDES_CBC:
+ case bltestDES_EDE_ECB:
+ case bltestDES_EDE_CBC:
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ cipherInfo->input.pBuf.len);
+ return bltest_des_init(cipherInfo, encrypt);
+ break;
+ case bltestRC2_ECB:
+ case bltestRC2_CBC:
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ cipherInfo->input.pBuf.len);
+ return bltest_rc2_init(cipherInfo, encrypt);
+ break;
+ case bltestRC4:
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ cipherInfo->input.pBuf.len);
+ return bltest_rc4_init(cipherInfo, encrypt);
+ break;
+#ifdef NSS_SOFTOKEN_DOES_RC5
+ case bltestRC5_ECB:
+ case bltestRC5_CBC:
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ cipherInfo->input.pBuf.len);
+#endif
+ return bltest_rc5_init(cipherInfo, encrypt);
+ break;
+ case bltestAES_ECB:
+ case bltestAES_CBC:
+ case bltestAES_CTS:
+ case bltestAES_CTR:
+ case bltestAES_GCM:
+ outlen = cipherInfo->input.pBuf.len;
+ if (cipherInfo->mode == bltestAES_GCM && encrypt) {
+ outlen += 16;
+ }
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, outlen);
+ return bltest_aes_init(cipherInfo, encrypt);
+ break;
+ case bltestCAMELLIA_ECB:
+ case bltestCAMELLIA_CBC:
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ cipherInfo->input.pBuf.len);
+ return bltest_camellia_init(cipherInfo, encrypt);
+ break;
+ case bltestSEED_ECB:
+ case bltestSEED_CBC:
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ cipherInfo->input.pBuf.len);
+ return bltest_seed_init(cipherInfo, encrypt);
+ break;
+ case bltestCHACHA20:
+ outlen = cipherInfo->input.pBuf.len + (encrypt ? 16 : 0);
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, outlen);
+ return bltest_chacha20_init(cipherInfo, encrypt);
+ break;
+ case bltestRSA:
+ case bltestRSA_OAEP:
+ case bltestRSA_PSS:
+ if (encrypt || cipherInfo->mode != bltestRSA_PSS) {
+ /* Don't allocate a buffer for PSS in verify mode, as no actual
+ * output is produced. */
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ RSA_MAX_MODULUS_BITS / 8);
+ }
+ return bltest_rsa_init(cipherInfo, encrypt);
+ break;
+ case bltestDSA:
+ if (encrypt) {
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ DSA_MAX_SIGNATURE_LEN);
+ }
+ return bltest_dsa_init(cipherInfo, encrypt);
+ break;
+#ifndef NSS_DISABLE_ECC
+ case bltestECDSA:
+ if (encrypt) {
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ 2 * MAX_ECKEY_LEN);
+ }
+ return bltest_ecdsa_init(cipherInfo, encrypt);
+ break;
+#endif
+ case bltestMD2:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ MD2_LENGTH);
+ cipherInfo->cipher.hashCipher = (restart) ? md2_restart : md2_HashBuf;
+ return SECSuccess;
+ break;
+ case bltestMD5:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ MD5_LENGTH);
+ cipherInfo->cipher.hashCipher = (restart) ? md5_restart : MD5_HashBuf;
+ return SECSuccess;
+ break;
+ case bltestSHA1:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ SHA1_LENGTH);
+ cipherInfo->cipher.hashCipher = (restart) ? sha1_restart : SHA1_HashBuf;
+ return SECSuccess;
+ break;
+ case bltestSHA224:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ SHA224_LENGTH);
+ cipherInfo->cipher.hashCipher = (restart) ? SHA224_restart
+ : SHA224_HashBuf;
+ return SECSuccess;
+ break;
+ case bltestSHA256:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ SHA256_LENGTH);
+ cipherInfo->cipher.hashCipher = (restart) ? SHA256_restart
+ : SHA256_HashBuf;
+ return SECSuccess;
+ break;
+ case bltestSHA384:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ SHA384_LENGTH);
+ cipherInfo->cipher.hashCipher = (restart) ? SHA384_restart
+ : SHA384_HashBuf;
+ return SECSuccess;
+ break;
+ case bltestSHA512:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ SHA512_LENGTH);
+ cipherInfo->cipher.hashCipher = (restart) ? SHA512_restart
+ : SHA512_HashBuf;
+ return SECSuccess;
+ break;
+ default:
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+cipherDoOp(bltestCipherInfo *cipherInfo)
+{
+ PRIntervalTime time1, time2;
+ SECStatus rv = SECSuccess;
+ int i;
+ unsigned int len;
+ unsigned int maxLen = cipherInfo->output.pBuf.len;
+ unsigned char *dummyOut;
+ dummyOut = PORT_Alloc(maxLen);
+ if (is_symmkeyCipher(cipherInfo->mode)) {
+ const unsigned char *input = cipherInfo->input.pBuf.data;
+ unsigned int inputLen = is_singleShotCipher(cipherInfo->mode) ? cipherInfo->input.pBuf.len
+ : PR_MIN(cipherInfo->input.pBuf.len, 16);
+ unsigned char *output = cipherInfo->output.pBuf.data;
+ unsigned int outputLen = maxLen;
+ unsigned int totalOutputLen = 0;
+ TIMESTART();
+ rv = (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx,
+ output, &len, outputLen,
+ input, inputLen);
+ CHECKERROR(rv, __LINE__);
+ totalOutputLen += len;
+ if (cipherInfo->input.pBuf.len > inputLen) {
+ input += inputLen;
+ inputLen = cipherInfo->input.pBuf.len - inputLen;
+ output += len;
+ outputLen -= len;
+ rv = (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx,
+ output, &len, outputLen,
+ input, inputLen);
+ CHECKERROR(rv, __LINE__);
+ totalOutputLen += len;
+ }
+ cipherInfo->output.pBuf.len = totalOutputLen;
+ TIMEFINISH(cipherInfo->optime, 1.0);
+ cipherInfo->repetitions = 0;
+ if (cipherInfo->repetitionsToPerfom != 0) {
+ TIMESTART();
+ for (i = 0; i < cipherInfo->repetitionsToPerfom; i++,
+ cipherInfo->repetitions++) {
+ (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx, dummyOut,
+ &len, maxLen,
+ cipherInfo->input.pBuf.data,
+ cipherInfo->input.pBuf.len);
+
+ CHECKERROR(rv, __LINE__);
+ }
+ } else {
+ int opsBetweenChecks = 0;
+ TIMEMARK(cipherInfo->seconds);
+ while (!(TIMETOFINISH())) {
+ int j = 0;
+ for (; j < opsBetweenChecks; j++) {
+ (*cipherInfo->cipher.symmkeyCipher)(
+ cipherInfo->cx, dummyOut, &len, maxLen,
+ cipherInfo->input.pBuf.data,
+ cipherInfo->input.pBuf.len);
+ }
+ cipherInfo->repetitions += j;
+ }
+ }
+ TIMEFINISH(cipherInfo->optime, 1.0);
+ } else if (is_aeadCipher(cipherInfo->mode)) {
+ const unsigned char *input = cipherInfo->input.pBuf.data;
+ unsigned int inputLen = cipherInfo->input.pBuf.len;
+ unsigned char *output = cipherInfo->output.pBuf.data;
+ unsigned int outputLen;
+ bltestSymmKeyParams *sk = &cipherInfo->params.sk;
+ bltestAuthSymmKeyParams *ask = &cipherInfo->params.ask;
+
+ TIMESTART();
+ rv = (*cipherInfo->cipher.aeadCipher)(
+ cipherInfo->cx,
+ output, &outputLen, maxLen,
+ input, inputLen,
+ sk->iv.buf.data, sk->iv.buf.len,
+ ask->aad.buf.data, ask->aad.buf.len);
+ CHECKERROR(rv, __LINE__);
+ cipherInfo->output.pBuf.len = outputLen;
+ TIMEFINISH(cipherInfo->optime, 1.0);
+
+ cipherInfo->repetitions = 0;
+ if (cipherInfo->repetitionsToPerfom != 0) {
+ TIMESTART();
+ for (i = 0; i < cipherInfo->repetitionsToPerfom; i++,
+ cipherInfo->repetitions++) {
+ rv = (*cipherInfo->cipher.aeadCipher)(
+ cipherInfo->cx,
+ output, &outputLen, maxLen,
+ input, inputLen,
+ sk->iv.buf.data, sk->iv.buf.len,
+ ask->aad.buf.data, ask->aad.buf.len);
+ CHECKERROR(rv, __LINE__);
+ }
+ } else {
+ int opsBetweenChecks = 0;
+ TIMEMARK(cipherInfo->seconds);
+ while (!(TIMETOFINISH())) {
+ int j = 0;
+ for (; j < opsBetweenChecks; j++) {
+ (*cipherInfo->cipher.aeadCipher)(
+ cipherInfo->cx,
+ output, &outputLen, maxLen,
+ input, inputLen,
+ sk->iv.buf.data, sk->iv.buf.len,
+ ask->aad.buf.data, ask->aad.buf.len);
+ }
+ cipherInfo->repetitions += j;
+ }
+ }
+ TIMEFINISH(cipherInfo->optime, 1.0);
+ } else if (is_pubkeyCipher(cipherInfo->mode)) {
+ TIMESTART();
+ rv = (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx,
+ &cipherInfo->output.pBuf,
+ &cipherInfo->input.pBuf);
+ TIMEFINISH(cipherInfo->optime, 1.0);
+ CHECKERROR(rv, __LINE__);
+ cipherInfo->repetitions = 0;
+ if (cipherInfo->repetitionsToPerfom != 0) {
+ TIMESTART();
+ for (i = 0; i < cipherInfo->repetitionsToPerfom;
+ i++, cipherInfo->repetitions++) {
+ SECItem dummy;
+ dummy.data = dummyOut;
+ dummy.len = maxLen;
+ (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx, &dummy,
+ &cipherInfo->input.pBuf);
+ CHECKERROR(rv, __LINE__);
+ }
+ } else {
+ int opsBetweenChecks = 0;
+ TIMEMARK(cipherInfo->seconds);
+ while (!(TIMETOFINISH())) {
+ int j = 0;
+ for (; j < opsBetweenChecks; j++) {
+ SECItem dummy;
+ dummy.data = dummyOut;
+ dummy.len = maxLen;
+ (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx, &dummy,
+ &cipherInfo->input.pBuf);
+ CHECKERROR(rv, __LINE__);
+ }
+ cipherInfo->repetitions += j;
+ }
+ }
+ TIMEFINISH(cipherInfo->optime, 1.0);
+ } else if (is_hashCipher(cipherInfo->mode)) {
+ TIMESTART();
+ rv = (*cipherInfo->cipher.hashCipher)(cipherInfo->output.pBuf.data,
+ cipherInfo->input.pBuf.data,
+ cipherInfo->input.pBuf.len);
+ TIMEFINISH(cipherInfo->optime, 1.0);
+ CHECKERROR(rv, __LINE__);
+ cipherInfo->repetitions = 0;
+ if (cipherInfo->repetitionsToPerfom != 0) {
+ TIMESTART();
+ for (i = 0; i < cipherInfo->repetitionsToPerfom;
+ i++, cipherInfo->repetitions++) {
+ (*cipherInfo->cipher.hashCipher)(dummyOut,
+ cipherInfo->input.pBuf.data,
+ cipherInfo->input.pBuf.len);
+ CHECKERROR(rv, __LINE__);
+ }
+ } else {
+ int opsBetweenChecks = 0;
+ TIMEMARK(cipherInfo->seconds);
+ while (!(TIMETOFINISH())) {
+ int j = 0;
+ for (; j < opsBetweenChecks; j++) {
+ bltestIO *input = &cipherInfo->input;
+ (*cipherInfo->cipher.hashCipher)(dummyOut,
+ input->pBuf.data,
+ input->pBuf.len);
+ CHECKERROR(rv, __LINE__);
+ }
+ cipherInfo->repetitions += j;
+ }
+ }
+ TIMEFINISH(cipherInfo->optime, 1.0);
+ }
+ PORT_Free(dummyOut);
+ return rv;
+}
+
+SECStatus
+cipherFinish(bltestCipherInfo *cipherInfo)
+{
+ SECStatus rv = SECSuccess;
+
+ switch (cipherInfo->mode) {
+ case bltestDES_ECB:
+ case bltestDES_CBC:
+ case bltestDES_EDE_ECB:
+ case bltestDES_EDE_CBC:
+ DES_DestroyContext((DESContext *)cipherInfo->cx, PR_TRUE);
+ break;
+ case bltestAES_GCM:
+ case bltestAES_ECB:
+ case bltestAES_CBC:
+ case bltestAES_CTS:
+ case bltestAES_CTR:
+ AES_DestroyContext((AESContext *)cipherInfo->cx, PR_TRUE);
+ break;
+ case bltestCAMELLIA_ECB:
+ case bltestCAMELLIA_CBC:
+ Camellia_DestroyContext((CamelliaContext *)cipherInfo->cx, PR_TRUE);
+ break;
+ case bltestSEED_ECB:
+ case bltestSEED_CBC:
+ SEED_DestroyContext((SEEDContext *)cipherInfo->cx, PR_TRUE);
+ break;
+ case bltestCHACHA20:
+ ChaCha20Poly1305_DestroyContext((ChaCha20Poly1305Context *)
+ cipherInfo->cx,
+ PR_TRUE);
+ break;
+ case bltestRC2_ECB:
+ case bltestRC2_CBC:
+ RC2_DestroyContext((RC2Context *)cipherInfo->cx, PR_TRUE);
+ break;
+ case bltestRC4:
+ RC4_DestroyContext((RC4Context *)cipherInfo->cx, PR_TRUE);
+ break;
+#ifdef NSS_SOFTOKEN_DOES_RC5
+ case bltestRC5_ECB:
+ case bltestRC5_CBC:
+ RC5_DestroyContext((RC5Context *)cipherInfo->cx, PR_TRUE);
+ break;
+#endif
+ case bltestRSA: /* keys are alloc'ed within cipherInfo's arena, */
+ case bltestRSA_PSS: /* will be freed with it. */
+ case bltestRSA_OAEP:
+ case bltestDSA:
+#ifndef NSS_DISABLE_ECC
+ case bltestECDSA:
+#endif
+ case bltestMD2: /* hash contexts are ephemeral */
+ case bltestMD5:
+ case bltestSHA1:
+ case bltestSHA224:
+ case bltestSHA256:
+ case bltestSHA384:
+ case bltestSHA512:
+ return SECSuccess;
+ break;
+ default:
+ return SECFailure;
+ }
+ return rv;
+}
+
+void
+print_exponent(SECItem *exp)
+{
+ int i;
+ int e = 0;
+ if (exp->len <= 4) {
+ for (i = exp->len; i >= 0; --i)
+ e |= exp->data[exp->len - i] << 8 * (i - 1);
+ fprintf(stdout, "%12d", e);
+ } else {
+ e = 8 * exp->len;
+ fprintf(stdout, "~2**%-8d", e);
+ }
+}
+
+static void
+splitToReportUnit(PRInt64 res, int *resArr, int *del, int size)
+{
+ PRInt64 remaining = res, tmp = 0;
+ PRInt64 Ldel;
+ int i = -1;
+
+ while (remaining > 0 && ++i < size) {
+ LL_I2L(Ldel, del[i]);
+ LL_MOD(tmp, remaining, Ldel);
+ LL_L2I(resArr[i], tmp);
+ LL_DIV(remaining, remaining, Ldel);
+ }
+}
+
+static char *
+getHighUnitBytes(PRInt64 res)
+{
+ int spl[] = { 0, 0, 0, 0 };
+ int del[] = { 1024, 1024, 1024, 1024 };
+ char *marks[] = { "b", "Kb", "Mb", "Gb" };
+ int i = 3;
+
+ splitToReportUnit(res, spl, del, 4);
+
+ for (; i > 0; i--) {
+ if (spl[i] != 0) {
+ break;
+ }
+ }
+
+ return PR_smprintf("%d%s", spl[i], marks[i]);
+}
+
+static void
+printPR_smpString(const char *sformat, char *reportStr,
+ const char *nformat, PRInt64 rNum)
+{
+ if (reportStr) {
+ fprintf(stdout, sformat, reportStr);
+ PR_smprintf_free(reportStr);
+ } else {
+ fprintf(stdout, nformat, rNum);
+ }
+}
+
+static char *
+getHighUnitOps(PRInt64 res)
+{
+ int spl[] = { 0, 0, 0, 0 };
+ int del[] = { 1000, 1000, 1000, 1000 };
+ char *marks[] = { "", "T", "M", "B" };
+ int i = 3;
+
+ splitToReportUnit(res, spl, del, 4);
+
+ for (; i > 0; i--) {
+ if (spl[i] != 0) {
+ break;
+ }
+ }
+
+ return PR_smprintf("%d%s", spl[i], marks[i]);
+}
+
+void
+dump_performance_info(bltestCipherInfo *infoList, double totalTimeInt,
+ PRBool encrypt, PRBool cxonly)
+{
+ bltestCipherInfo *info = infoList;
+
+ PRInt64 totalIn = 0;
+ PRBool td = PR_TRUE;
+
+ int repetitions = 0;
+ int cxreps = 0;
+ double cxtime = 0;
+ double optime = 0;
+ while (info != NULL) {
+ repetitions += info->repetitions;
+ cxreps += info->cxreps;
+ cxtime += info->cxtime;
+ optime += info->optime;
+ totalIn += (PRInt64)info->input.buf.len * (PRInt64)info->repetitions;
+
+ info = info->next;
+ }
+ info = infoList;
+
+ fprintf(stdout, "#%9s", "mode");
+ fprintf(stdout, "%12s", "in");
+print_td:
+ switch (info->mode) {
+ case bltestDES_ECB:
+ case bltestDES_CBC:
+ case bltestDES_EDE_ECB:
+ case bltestDES_EDE_CBC:
+ case bltestAES_ECB:
+ case bltestAES_CBC:
+ case bltestAES_CTS:
+ case bltestAES_CTR:
+ case bltestAES_GCM:
+ case bltestCAMELLIA_ECB:
+ case bltestCAMELLIA_CBC:
+ case bltestSEED_ECB:
+ case bltestSEED_CBC:
+ case bltestRC2_ECB:
+ case bltestRC2_CBC:
+ case bltestRC4:
+ if (td)
+ fprintf(stdout, "%8s", "symmkey");
+ else
+ fprintf(stdout, "%8d", 8 * info->params.sk.key.buf.len);
+ break;
+#ifdef NSS_SOFTOKEN_DOES_RC5
+ case bltestRC5_ECB:
+ case bltestRC5_CBC:
+ if (info->params.sk.key.buf.len > 0)
+ printf("symmetric key(bytes)=%d,", info->params.sk.key.buf.len);
+ if (info->rounds > 0)
+ printf("rounds=%d,", info->params.rc5.rounds);
+ if (info->wordsize > 0)
+ printf("wordsize(bytes)=%d,", info->params.rc5.wordsize);
+ break;
+#endif
+ case bltestRSA:
+ case bltestRSA_PSS:
+ case bltestRSA_OAEP:
+ if (td) {
+ fprintf(stdout, "%8s", "rsa_mod");
+ fprintf(stdout, "%12s", "rsa_pe");
+ } else {
+ bltestAsymKeyParams *asymk = &info->params.asymk;
+ fprintf(stdout, "%8d", asymk->cipherParams.rsa.keysizeInBits);
+ print_exponent(
+ &((RSAPrivateKey *)asymk->privKey)->publicExponent);
+ }
+ break;
+ case bltestDSA:
+ if (td) {
+ fprintf(stdout, "%8s", "pqg_mod");
+ } else {
+ fprintf(stdout, "%8d", info->params.asymk.cipherParams.dsa.keysize);
+ }
+ break;
+#ifndef NSS_DISABLE_ECC
+ case bltestECDSA:
+ if (td) {
+ fprintf(stdout, "%12s", "ec_curve");
+ } else {
+ ECPrivateKey *key = (ECPrivateKey *)info->params.asymk.privKey;
+ ECCurveName curveName = key->ecParams.name;
+ fprintf(stdout, "%12s",
+ ecCurve_map[curveName] ? ecCurve_map[curveName]->text : "Unsupported curve");
+ }
+ break;
+#endif
+ case bltestMD2:
+ case bltestMD5:
+ case bltestSHA1:
+ case bltestSHA256:
+ case bltestSHA384:
+ case bltestSHA512:
+ default:
+ break;
+ }
+ if (!td) {
+ PRInt64 totalThroughPut;
+
+ printPR_smpString("%8s", getHighUnitOps(repetitions),
+ "%8d", repetitions);
+
+ printPR_smpString("%8s", getHighUnitOps(cxreps), "%8d", cxreps);
+
+ fprintf(stdout, "%12.3f", cxtime);
+ fprintf(stdout, "%12.3f", optime);
+ fprintf(stdout, "%12.03f", totalTimeInt / 1000);
+
+ totalThroughPut = (PRInt64)(totalIn / totalTimeInt * 1000);
+ printPR_smpString("%12s", getHighUnitBytes(totalThroughPut),
+ "%12d", totalThroughPut);
+
+ fprintf(stdout, "\n");
+ return;
+ }
+
+ fprintf(stdout, "%8s", "opreps");
+ fprintf(stdout, "%8s", "cxreps");
+ fprintf(stdout, "%12s", "context");
+ fprintf(stdout, "%12s", "op");
+ fprintf(stdout, "%12s", "time(sec)");
+ fprintf(stdout, "%12s", "thrgput");
+ fprintf(stdout, "\n");
+ fprintf(stdout, "%8s", mode_strings[info->mode]);
+ fprintf(stdout, "_%c", (cxonly) ? 'c' : (encrypt) ? 'e' : 'd');
+ printPR_smpString("%12s", getHighUnitBytes(totalIn), "%12d", totalIn);
+
+ td = !td;
+ goto print_td;
+}
+
+void
+printmodes()
+{
+ bltestCipherMode mode;
+ int nummodes = sizeof(mode_strings) / sizeof(char *);
+ fprintf(stderr, "%s: Available modes (specify with -m):\n", progName);
+ for (mode = 0; mode < nummodes; mode++)
+ fprintf(stderr, "%s\n", mode_strings[mode]);
+}
+
+bltestCipherMode
+get_mode(const char *modestring)
+{
+ bltestCipherMode mode;
+ int nummodes = sizeof(mode_strings) / sizeof(char *);
+ for (mode = 0; mode < nummodes; mode++)
+ if (PL_strcmp(modestring, mode_strings[mode]) == 0)
+ return mode;
+ fprintf(stderr, "%s: invalid mode: %s\n", progName, modestring);
+ return bltestINVALID;
+}
+
+void
+load_file_data(PLArenaPool *arena, bltestIO *data,
+ char *fn, bltestIOMode ioMode)
+{
+ PRFileDesc *file;
+ data->mode = ioMode;
+ data->file = NULL; /* don't use -- not saving anything */
+ data->pBuf.data = NULL;
+ data->pBuf.len = 0;
+ file = PR_Open(fn, PR_RDONLY, 00660);
+ if (file) {
+ setupIO(arena, data, file, NULL, 0);
+ PR_Close(file);
+ }
+}
+
+HASH_HashType
+mode_str_to_hash_alg(const SECItem *modeStr)
+{
+ bltestCipherMode mode;
+ char *tempModeStr = NULL;
+ if (!modeStr || modeStr->len == 0)
+ return HASH_AlgNULL;
+ tempModeStr = PORT_Alloc(modeStr->len + 1);
+ if (!tempModeStr)
+ return HASH_AlgNULL;
+ memcpy(tempModeStr, modeStr->data, modeStr->len);
+ tempModeStr[modeStr->len] = '\0';
+ mode = get_mode(tempModeStr);
+ PORT_Free(tempModeStr);
+ switch (mode) {
+ case bltestMD2:
+ return HASH_AlgMD2;
+ case bltestMD5:
+ return HASH_AlgMD5;
+ case bltestSHA1:
+ return HASH_AlgSHA1;
+ case bltestSHA224:
+ return HASH_AlgSHA224;
+ case bltestSHA256:
+ return HASH_AlgSHA256;
+ case bltestSHA384:
+ return HASH_AlgSHA384;
+ case bltestSHA512:
+ return HASH_AlgSHA512;
+ default:
+ return HASH_AlgNULL;
+ }
+}
+
+void
+get_params(PLArenaPool *arena, bltestParams *params,
+ bltestCipherMode mode, int j)
+{
+ char filename[256];
+ char *modestr = mode_strings[mode];
+ bltestIO tempIO;
+
+#ifdef NSS_SOFTOKEN_DOES_RC5
+ FILE *file;
+ char *mark, *param, *val;
+ int index = 0;
+#endif
+ switch (mode) {
+ case bltestAES_GCM:
+ case bltestCHACHA20:
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "aad", j);
+ load_file_data(arena, &params->ask.aad, filename, bltestBinary);
+ case bltestDES_CBC:
+ case bltestDES_EDE_CBC:
+ case bltestRC2_CBC:
+ case bltestAES_CBC:
+ case bltestAES_CTS:
+ case bltestAES_CTR:
+ case bltestCAMELLIA_CBC:
+ case bltestSEED_CBC:
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "iv", j);
+ load_file_data(arena, &params->sk.iv, filename, bltestBinary);
+ case bltestDES_ECB:
+ case bltestDES_EDE_ECB:
+ case bltestRC2_ECB:
+ case bltestRC4:
+ case bltestAES_ECB:
+ case bltestCAMELLIA_ECB:
+ case bltestSEED_ECB:
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
+ load_file_data(arena, &params->sk.key, filename, bltestBinary);
+ break;
+#ifdef NSS_SOFTOKEN_DOES_RC5
+ case bltestRC5_ECB:
+ case bltestRC5_CBC:
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "iv", j);
+ load_file_data(arena, &params->sk.iv, filename, bltestBinary);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
+ load_file_data(arena, &params->sk.key, filename, bltestBinary);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr,
+ "params", j);
+ file = fopen(filename, "r");
+ if (!file)
+ return;
+ param = malloc(100);
+ len = fread(param, 1, 100, file);
+ while (index < len) {
+ mark = PL_strchr(param, '=');
+ *mark = '\0';
+ val = mark + 1;
+ mark = PL_strchr(val, '\n');
+ *mark = '\0';
+ if (PL_strcmp(param, "rounds") == 0) {
+ params->rc5.rounds = atoi(val);
+ } else if (PL_strcmp(param, "wordsize") == 0) {
+ params->rc5.wordsize = atoi(val);
+ }
+ index += PL_strlen(param) + PL_strlen(val) + 2;
+ param = mark + 1;
+ }
+ break;
+#endif
+ case bltestRSA_PSS:
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext", j);
+ load_file_data(arena, &params->asymk.sig, filename, bltestBase64Encoded);
+ /* fall through */
+ case bltestRSA_OAEP:
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "seed", j);
+ load_file_data(arena, &params->asymk.cipherParams.rsa.seed,
+ filename, bltestBase64Encoded);
+
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "hash", j);
+ load_file_data(arena, &tempIO, filename, bltestBinary);
+ params->asymk.cipherParams.rsa.hashAlg =
+ mode_str_to_hash_alg(&tempIO.buf);
+
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "maskhash", j);
+ load_file_data(arena, &tempIO, filename, bltestBinary);
+ params->asymk.cipherParams.rsa.maskHashAlg =
+ mode_str_to_hash_alg(&tempIO.buf);
+ /* fall through */
+ case bltestRSA:
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
+ load_file_data(arena, &params->asymk.key, filename,
+ bltestBase64Encoded);
+ params->asymk.privKey =
+ (void *)rsakey_from_filedata(arena, &params->asymk.key.buf);
+ break;
+ case bltestDSA:
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
+ load_file_data(arena, &params->asymk.key, filename, bltestBase64Encoded);
+ params->asymk.privKey =
+ (void *)dsakey_from_filedata(arena, &params->asymk.key.buf);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "pqg", j);
+ load_file_data(arena, &params->asymk.cipherParams.dsa.pqgdata, filename,
+ bltestBase64Encoded);
+ params->asymk.cipherParams.dsa.pqg =
+ pqg_from_filedata(arena, &params->asymk.cipherParams.dsa.pqgdata.buf);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "keyseed", j);
+ load_file_data(arena, &params->asymk.cipherParams.dsa.keyseed, filename,
+ bltestBase64Encoded);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "sigseed", j);
+ load_file_data(arena, &params->asymk.cipherParams.dsa.sigseed, filename,
+ bltestBase64Encoded);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext", j);
+ load_file_data(arena, &params->asymk.sig, filename, bltestBase64Encoded);
+ break;
+#ifndef NSS_DISABLE_ECC
+ case bltestECDSA:
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
+ load_file_data(arena, &params->asymk.key, filename, bltestBase64Encoded);
+ params->asymk.privKey =
+ (void *)eckey_from_filedata(arena, &params->asymk.key.buf);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "sigseed", j);
+ load_file_data(arena, &params->asymk.cipherParams.ecdsa.sigseed,
+ filename, bltestBase64Encoded);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext", j);
+ load_file_data(arena, &params->asymk.sig, filename, bltestBase64Encoded);
+ break;
+#endif
+ case bltestMD2:
+ case bltestMD5:
+ case bltestSHA1:
+ case bltestSHA224:
+ case bltestSHA256:
+ case bltestSHA384:
+ case bltestSHA512:
+ /*params->hash.restart = PR_TRUE;*/
+ params->hash.restart = PR_FALSE;
+ break;
+ default:
+ break;
+ }
+}
+
+SECStatus
+verify_self_test(bltestIO *result, bltestIO *cmp, bltestCipherMode mode,
+ PRBool forward, SECStatus sigstatus)
+{
+ PRBool equal;
+ char *modestr = mode_strings[mode];
+ equal = SECITEM_ItemsAreEqual(&result->pBuf, &cmp->buf);
+ if (is_sigCipher(mode)) {
+ if (forward) {
+ if (equal) {
+ printf("Signature self-test for %s passed.\n", modestr);
+ } else {
+ printf("Signature self-test for %s failed!\n", modestr);
+ }
+ return equal ? SECSuccess : SECFailure;
+ } else {
+ if (sigstatus == SECSuccess) {
+ printf("Verification self-test for %s passed.\n", modestr);
+ } else {
+ printf("Verification self-test for %s failed!\n", modestr);
+ }
+ return sigstatus;
+ }
+ } else if (is_hashCipher(mode)) {
+ if (equal) {
+ printf("Hash self-test for %s passed.\n", modestr);
+ } else {
+ printf("Hash self-test for %s failed!\n", modestr);
+ }
+ } else {
+ if (forward) {
+ if (equal) {
+ printf("Encryption self-test for %s passed.\n", modestr);
+ } else {
+ printf("Encryption self-test for %s failed!\n", modestr);
+ }
+ } else {
+ if (equal) {
+ printf("Decryption self-test for %s passed.\n", modestr);
+ } else {
+ printf("Decryption self-test for %s failed!\n", modestr);
+ }
+ }
+ }
+ return equal ? SECSuccess : SECFailure;
+}
+
+static SECStatus
+ReadFileToItem(PLArenaPool *arena, SECItem *dst, const char *filename)
+{
+ SECItem tmp = { siBuffer, NULL, 0 };
+ PRFileDesc *file;
+ SECStatus rv;
+
+ file = PR_Open(filename, PR_RDONLY, 00660);
+ if (!file) {
+ return SECFailure;
+ }
+ rv = SECU_FileToItem(&tmp, file);
+ rv |= SECITEM_CopyItem(arena, dst, &tmp);
+ SECITEM_FreeItem(&tmp, PR_FALSE);
+ PR_Close(file);
+ return rv;
+}
+
+static SECStatus
+blapi_selftest(bltestCipherMode *modes, int numModes, int inoff, int outoff,
+ PRBool encrypt, PRBool decrypt)
+{
+ bltestCipherInfo cipherInfo;
+ bltestIO pt, ct;
+ bltestCipherMode mode;
+ bltestParams *params;
+ unsigned int i, j, nummodes, numtests;
+ char *modestr;
+ char filename[256];
+ PLArenaPool *arena;
+ SECItem item;
+ SECStatus rv = SECSuccess, srv;
+
+ PORT_Memset(&cipherInfo, 0, sizeof(cipherInfo));
+ arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
+ cipherInfo.arena = arena;
+
+ nummodes = (numModes == 0) ? NUMMODES : numModes;
+ for (i = 0; i < nummodes; i++) {
+ if (numModes > 0)
+ mode = modes[i];
+ else
+ mode = i;
+ if (mode == bltestINVALID) {
+ fprintf(stderr, "%s: Skipping invalid mode.\n", progName);
+ continue;
+ }
+ modestr = mode_strings[mode];
+ cipherInfo.mode = mode;
+ params = &cipherInfo.params;
+ /* get the number of tests in the directory */
+ sprintf(filename, "%s/tests/%s/%s", testdir, modestr, "numtests");
+ if (ReadFileToItem(arena, &item, filename) != SECSuccess) {
+ fprintf(stderr, "%s: Cannot read file %s.\n", progName, filename);
+ rv = SECFailure;
+ continue;
+ }
+ /* loop over the tests in the directory */
+ numtests = 0;
+ for (j = 0; j < item.len; j++) {
+ if (!isdigit(item.data[j])) {
+ break;
+ }
+ numtests *= 10;
+ numtests += (int)(item.data[j] - '0');
+ }
+ for (j = 0; j < numtests; j++) {
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr,
+ "plaintext", j);
+ load_file_data(arena, &pt, filename,
+ is_sigCipher(mode) ? bltestBase64Encoded
+ : bltestBinary);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr,
+ "ciphertext", j);
+ load_file_data(arena, &ct, filename, bltestBase64Encoded);
+
+ get_params(arena, params, mode, j);
+ /* Forward Operation (Encrypt/Sign/Hash)
+ ** Align the input buffer (plaintext) according to request
+ ** then perform operation and compare to ciphertext
+ */
+ if (encrypt) {
+ rv |= bltestCopyIO(arena, &cipherInfo.input, &pt);
+ misalignBuffer(arena, &cipherInfo.input, inoff);
+ memset(&cipherInfo.output.buf, 0, sizeof cipherInfo.output.buf);
+ rv |= cipherInit(&cipherInfo, PR_TRUE);
+ misalignBuffer(arena, &cipherInfo.output, outoff);
+ rv |= cipherDoOp(&cipherInfo);
+ rv |= cipherFinish(&cipherInfo);
+ rv |= verify_self_test(&cipherInfo.output,
+ &ct, mode, PR_TRUE, SECSuccess);
+ /* If testing hash, only one op to test */
+ if (is_hashCipher(mode))
+ continue;
+ if (is_sigCipher(mode)) {
+ /* Verify operations support detached signature files. For
+ ** consistency between tests that run Sign/Verify back to
+ ** back (eg: self-tests) and tests that are only running
+ ** verify operations, copy the output into the sig buf,
+ ** and then copy the sig buf back out when verifying. For
+ ** self-tests, this is unnecessary copying, but for
+ ** verify-only operations, this ensures that the output
+ ** buffer is properly configured
+ */
+ rv |= bltestCopyIO(arena, &params->asymk.sig, &cipherInfo.output);
+ }
+ }
+ if (!decrypt)
+ continue;
+ /* Reverse Operation (Decrypt/Verify)
+ ** Align the input buffer (ciphertext) according to request
+ ** then perform operation and compare to plaintext
+ */
+ if (is_sigCipher(mode)) {
+ rv |= bltestCopyIO(arena, &cipherInfo.input, &pt);
+ rv |= bltestCopyIO(arena, &cipherInfo.output, &params->asymk.sig);
+ } else {
+ rv |= bltestCopyIO(arena, &cipherInfo.input, &ct);
+ memset(&cipherInfo.output.buf, 0, sizeof cipherInfo.output.buf);
+ }
+ misalignBuffer(arena, &cipherInfo.input, inoff);
+ rv |= cipherInit(&cipherInfo, PR_FALSE);
+ misalignBuffer(arena, &cipherInfo.output, outoff);
+ srv = SECSuccess;
+ srv |= cipherDoOp(&cipherInfo);
+ rv |= cipherFinish(&cipherInfo);
+ rv |= verify_self_test(&cipherInfo.output,
+ &pt, mode, PR_FALSE, srv);
+ }
+ }
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+SECStatus
+dump_file(bltestCipherMode mode, char *filename)
+{
+ bltestIO keydata;
+ PLArenaPool *arena = NULL;
+ arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ return SECFailure;
+ }
+ if (mode == bltestRSA || mode == bltestRSA_PSS || mode == bltestRSA_OAEP) {
+ RSAPrivateKey *key;
+ load_file_data(arena, &keydata, filename, bltestBase64Encoded);
+ key = rsakey_from_filedata(arena, &keydata.buf);
+ dump_rsakey(key);
+ } else if (mode == bltestDSA) {
+#if 0
+ PQGParams *pqg;
+ get_file_data(filename, &item, PR_TRUE);
+ pqg = pqg_from_filedata(&item);
+ dump_pqg(pqg);
+#endif
+ DSAPrivateKey *key;
+ load_file_data(arena, &keydata, filename, bltestBase64Encoded);
+ key = dsakey_from_filedata(arena, &keydata.buf);
+ dump_dsakey(key);
+#ifndef NSS_DISABLE_ECC
+ } else if (mode == bltestECDSA) {
+ ECPrivateKey *key;
+ load_file_data(arena, &keydata, filename, bltestBase64Encoded);
+ key = eckey_from_filedata(arena, &keydata.buf);
+ dump_eckey(key);
+#endif
+ }
+ PORT_FreeArena(arena, PR_FALSE);
+ return SECFailure;
+}
+
+void
+ThreadExecTest(void *data)
+{
+ bltestCipherInfo *cipherInfo = (bltestCipherInfo *)data;
+
+ if (cipherInfo->mCarlo == PR_TRUE) {
+ int mciter;
+ for (mciter = 0; mciter < 10000; mciter++) {
+ cipherDoOp(cipherInfo);
+ memcpy(cipherInfo->input.buf.data,
+ cipherInfo->output.buf.data,
+ cipherInfo->input.buf.len);
+ }
+ } else {
+ cipherDoOp(cipherInfo);
+ }
+ cipherFinish(cipherInfo);
+}
+
+static void
+rsaPrivKeyReset(RSAPrivateKey *tstKey)
+{
+ PLArenaPool *arena;
+
+ tstKey->version.data = NULL;
+ tstKey->version.len = 0;
+ tstKey->modulus.data = NULL;
+ tstKey->modulus.len = 0;
+ tstKey->publicExponent.data = NULL;
+ tstKey->publicExponent.len = 0;
+ tstKey->privateExponent.data = NULL;
+ tstKey->privateExponent.len = 0;
+ tstKey->prime1.data = NULL;
+ tstKey->prime1.len = 0;
+ tstKey->prime2.data = NULL;
+ tstKey->prime2.len = 0;
+ tstKey->exponent1.data = NULL;
+ tstKey->exponent1.len = 0;
+ tstKey->exponent2.data = NULL;
+ tstKey->exponent2.len = 0;
+ tstKey->coefficient.data = NULL;
+ tstKey->coefficient.len = 0;
+
+ arena = tstKey->arena;
+ tstKey->arena = NULL;
+ if (arena) {
+ PORT_FreeArena(arena, PR_TRUE);
+ }
+}
+
+#define RSA_TEST_EQUAL(comp) \
+ if (!SECITEM_ItemsAreEqual(&(src->comp), &(dest->comp))) { \
+ fprintf(stderr, "key->" #comp " not equal"); \
+ if (src->comp.len != dest->comp.len) { \
+ fprintf(stderr, "src_len = %d, dest_len = %d", \
+ src->comp.len, dest->comp.len); \
+ } \
+ fprintf(stderr, "\n"); \
+ areEqual = PR_FALSE; \
+ }
+
+static PRBool
+rsaPrivKeysAreEqual(RSAPrivateKey *src, RSAPrivateKey *dest)
+{
+ PRBool areEqual = PR_TRUE;
+ RSA_TEST_EQUAL(modulus)
+ RSA_TEST_EQUAL(publicExponent)
+ RSA_TEST_EQUAL(privateExponent)
+ RSA_TEST_EQUAL(prime1)
+ RSA_TEST_EQUAL(prime2)
+ RSA_TEST_EQUAL(exponent1)
+ RSA_TEST_EQUAL(exponent2)
+ RSA_TEST_EQUAL(coefficient)
+ if (!areEqual) {
+ fprintf(stderr, "original key:\n");
+ dump_rsakey(src);
+ fprintf(stderr, "recreated key:\n");
+ dump_rsakey(dest);
+ }
+ return areEqual;
+}
+
+static int
+doRSAPopulateTestKV()
+{
+ RSAPrivateKey tstKey = { 0 };
+ SECStatus rv;
+ int failed = 0;
+ int i;
+
+ tstKey.arena = NULL;
+
+ /* Test public exponent, private exponent, modulus cases from
+ * pkcs1v15sign-vectors.txt. Some are valid PKCS#1 keys but not valid RSA
+ * ones (de = 1 mod lcm(p − 1, q − 1))
+ */
+ for (i = 0; i < PR_ARRAY_SIZE(PKCS1_VECTORS); ++i) {
+ struct pkcs1_test_vector *v = &PKCS1_VECTORS[i];
+
+ rsaPrivKeyReset(&tstKey);
+ tstKey.privateExponent.data = v->d;
+ tstKey.privateExponent.len = v->d_len;
+ tstKey.publicExponent.data = v->e;
+ tstKey.publicExponent.len = v->e_len;
+ tstKey.modulus.data = v->n;
+ tstKey.modulus.len = v->n_len;
+
+ rv = RSA_PopulatePrivateKey(&tstKey);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "RSA Populate failed: pkcs1v15sign-vector %d\n", i);
+ failed = 1;
+ } else if (memcmp(v->q, tstKey.prime1.data, v->q_len) ||
+ tstKey.prime1.len != v->q_len) {
+ fprintf(stderr, "RSA Populate key mismatch: pkcs1v15sign-vector %d q\n", i);
+ failed = 1;
+ } else if (memcmp(v->p, tstKey.prime2.data, v->p_len) ||
+ tstKey.prime1.len != v->p_len) {
+ fprintf(stderr, "RSA Populate key mismatch: pkcs1v15sign-vector %d p\n", i);
+ failed = 1;
+ } else {
+ fprintf(stderr, "RSA Populate success: pkcs1v15sign-vector %d p\n", i);
+ }
+ }
+
+ PORT_FreeArena(tstKey.arena, PR_TRUE);
+ return failed;
+}
+
+/*
+ * Test the RSA populate command to see that it can really build
+ * keys from its components.
+ */
+static int
+doRSAPopulateTest(unsigned int keySize, unsigned long exponent)
+{
+ RSAPrivateKey *srcKey;
+ RSAPrivateKey tstKey = { 0 };
+ SECItem expitem = { 0, 0, 0 };
+ SECStatus rv;
+ unsigned char pubExp[32];
+ int expLen = 0;
+ int failed = 0;
+ int i;
+
+ for (i = 0; i < sizeof(unsigned long); i++) {
+ int shift = (sizeof(unsigned long) - i - 1) * 8;
+ if (expLen || (exponent && ((unsigned long)0xffL << shift))) {
+ pubExp[expLen] = (unsigned char)((exponent >> shift) & 0xff);
+ expLen++;
+ }
+ }
+
+ expitem.data = pubExp;
+ expitem.len = expLen;
+
+ srcKey = RSA_NewKey(keySize, &expitem);
+ if (srcKey == NULL) {
+ fprintf(stderr, "RSA Key Gen failed");
+ return -1;
+ }
+
+ /* test the basic case - most common, public exponent, modulus, prime */
+ tstKey.arena = NULL;
+ rsaPrivKeyReset(&tstKey);
+
+ tstKey.publicExponent = srcKey->publicExponent;
+ tstKey.modulus = srcKey->modulus;
+ tstKey.prime1 = srcKey->prime1;
+
+ rv = RSA_PopulatePrivateKey(&tstKey);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "RSA Populate failed: pubExp mod p\n");
+ failed = 1;
+ } else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
+ fprintf(stderr, "RSA Populate key mismatch: pubExp mod p\n");
+ failed = 1;
+ }
+
+ /* test the basic2 case, public exponent, modulus, prime2 */
+ rsaPrivKeyReset(&tstKey);
+
+ tstKey.publicExponent = srcKey->publicExponent;
+ tstKey.modulus = srcKey->modulus;
+ tstKey.prime1 = srcKey->prime2; /* test with q in the prime1 position */
+
+ rv = RSA_PopulatePrivateKey(&tstKey);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "RSA Populate failed: pubExp mod q\n");
+ failed = 1;
+ } else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
+ fprintf(stderr, "RSA Populate key mismatch: pubExp mod q\n");
+ failed = 1;
+ }
+
+ /* test the medium case, private exponent, prime1, prime2 */
+ rsaPrivKeyReset(&tstKey);
+
+ tstKey.privateExponent = srcKey->privateExponent;
+ tstKey.prime1 = srcKey->prime2; /* purposefully swap them to make */
+ tstKey.prime2 = srcKey->prime1; /* sure populated swaps them back */
+
+ rv = RSA_PopulatePrivateKey(&tstKey);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "RSA Populate failed: privExp p q\n");
+ failed = 1;
+ } else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
+ fprintf(stderr, "RSA Populate key mismatch: privExp p q\n");
+ failed = 1;
+ }
+
+ /* test the advanced case, public exponent, private exponent, prime2 */
+ rsaPrivKeyReset(&tstKey);
+
+ tstKey.privateExponent = srcKey->privateExponent;
+ tstKey.publicExponent = srcKey->publicExponent;
+ tstKey.prime2 = srcKey->prime2; /* use q in the prime2 position */
+
+ rv = RSA_PopulatePrivateKey(&tstKey);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "RSA Populate failed: pubExp privExp q\n");
+ fprintf(stderr, " - not fatal\n");
+ /* it's possible that we can't uniquely determine the original key
+ * from just the exponents and prime. Populate returns an error rather
+ * than return the wrong key. */
+ } else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
+ /* if we returned a key, it *must* be correct */
+ fprintf(stderr, "RSA Populate key mismatch: pubExp privExp q\n");
+ rv = RSA_PrivateKeyCheck(&tstKey);
+ failed = 1;
+ }
+
+ /* test the advanced case2, public exponent, private exponent, modulus */
+ rsaPrivKeyReset(&tstKey);
+
+ tstKey.privateExponent = srcKey->privateExponent;
+ tstKey.publicExponent = srcKey->publicExponent;
+ tstKey.modulus = srcKey->modulus;
+
+ rv = RSA_PopulatePrivateKey(&tstKey);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "RSA Populate failed: pubExp privExp mod\n");
+ failed = 1;
+ } else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
+ fprintf(stderr, "RSA Populate key mismatch: pubExp privExp mod\n");
+ failed = 1;
+ }
+
+ PORT_FreeArena(srcKey->arena, PR_TRUE);
+ return failed ? -1 : 0;
+}
+
+/* bltest commands */
+enum {
+ cmd_Decrypt = 0,
+ cmd_Encrypt,
+ cmd_FIPS,
+ cmd_Hash,
+ cmd_Nonce,
+ cmd_Dump,
+ cmd_RSAPopulate,
+ cmd_RSAPopulateKV,
+ cmd_Sign,
+ cmd_SelfTest,
+ cmd_Verify
+};
+
+/* bltest options */
+enum {
+ opt_B64 = 0,
+ opt_BufSize,
+ opt_Restart,
+ opt_SelfTestDir,
+ opt_Exponent,
+ opt_SigFile,
+ opt_KeySize,
+ opt_Hex,
+ opt_Input,
+ opt_PQGFile,
+ opt_Key,
+ opt_HexWSpc,
+ opt_Mode,
+#ifndef NSS_DISABLE_ECC
+ opt_CurveName,
+#endif
+ opt_Output,
+ opt_Repetitions,
+ opt_ZeroBuf,
+ opt_Rounds,
+ opt_Seed,
+ opt_SigSeedFile,
+ opt_CXReps,
+ opt_IV,
+ opt_WordSize,
+ opt_UseSeed,
+ opt_UseSigSeed,
+ opt_SeedFile,
+ opt_AAD,
+ opt_InputOffset,
+ opt_OutputOffset,
+ opt_MonteCarlo,
+ opt_ThreadNum,
+ opt_SecondsToRun,
+ opt_CmdLine
+};
+
+static secuCommandFlag bltest_commands[] =
+ {
+ { /* cmd_Decrypt */ 'D', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Encrypt */ 'E', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_FIPS */ 'F', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Hash */ 'H', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Nonce */ 'N', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Dump */ 'P', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_RSAPopulate */ 'R', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_RSAPopulateKV */ 'K', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Sign */ 'S', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_SelfTest */ 'T', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Verify */ 'V', PR_FALSE, 0, PR_FALSE }
+ };
+
+static secuCommandFlag bltest_options[] =
+ {
+ { /* opt_B64 */ 'a', PR_FALSE, 0, PR_FALSE },
+ { /* opt_BufSize */ 'b', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Restart */ 'c', PR_FALSE, 0, PR_FALSE },
+ { /* opt_SelfTestDir */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Exponent */ 'e', PR_TRUE, 0, PR_FALSE },
+ { /* opt_SigFile */ 'f', PR_TRUE, 0, PR_FALSE },
+ { /* opt_KeySize */ 'g', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Hex */ 'h', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Input */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_PQGFile */ 'j', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Key */ 'k', PR_TRUE, 0, PR_FALSE },
+ { /* opt_HexWSpc */ 'l', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Mode */ 'm', PR_TRUE, 0, PR_FALSE },
+#ifndef NSS_DISABLE_ECC
+ { /* opt_CurveName */ 'n', PR_TRUE, 0, PR_FALSE },
+#endif
+ { /* opt_Output */ 'o', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Repetitions */ 'p', PR_TRUE, 0, PR_FALSE },
+ { /* opt_ZeroBuf */ 'q', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Rounds */ 'r', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Seed */ 's', PR_TRUE, 0, PR_FALSE },
+ { /* opt_SigSeedFile */ 't', PR_TRUE, 0, PR_FALSE },
+ { /* opt_CXReps */ 'u', PR_TRUE, 0, PR_FALSE },
+ { /* opt_IV */ 'v', PR_TRUE, 0, PR_FALSE },
+ { /* opt_WordSize */ 'w', PR_TRUE, 0, PR_FALSE },
+ { /* opt_UseSeed */ 'x', PR_FALSE, 0, PR_FALSE },
+ { /* opt_UseSigSeed */ 'y', PR_FALSE, 0, PR_FALSE },
+ { /* opt_SeedFile */ 'z', PR_FALSE, 0, PR_FALSE },
+ { /* opt_AAD */ 0, PR_TRUE, 0, PR_FALSE, "aad" },
+ { /* opt_InputOffset */ '1', PR_TRUE, 0, PR_FALSE },
+ { /* opt_OutputOffset */ '2', PR_TRUE, 0, PR_FALSE },
+ { /* opt_MonteCarlo */ '3', PR_FALSE, 0, PR_FALSE },
+ { /* opt_ThreadNum */ '4', PR_TRUE, 0, PR_FALSE },
+ { /* opt_SecondsToRun */ '5', PR_TRUE, 0, PR_FALSE },
+ { /* opt_CmdLine */ '-', PR_FALSE, 0, PR_FALSE }
+ };
+
+int
+main(int argc, char **argv)
+{
+ SECStatus rv = SECFailure;
+
+ double totalTime = 0.0;
+ PRIntervalTime time1, time2;
+ PRFileDesc *outfile = NULL;
+ bltestCipherInfo *cipherInfoListHead, *cipherInfo = NULL;
+ bltestIOMode ioMode;
+ int bufsize, exponent, curThrdNum;
+#ifndef NSS_DISABLE_ECC
+ char *curveName = NULL;
+#endif
+ int i, commandsEntered;
+ int inoff, outoff;
+ int threads = 1;
+
+ secuCommand bltest;
+ bltest.numCommands = sizeof(bltest_commands) / sizeof(secuCommandFlag);
+ bltest.numOptions = sizeof(bltest_options) / sizeof(secuCommandFlag);
+ bltest.commands = bltest_commands;
+ bltest.options = bltest_options;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName + 1 : argv[0];
+
+ rv = NSS_InitializePRErrorTable();
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+ rv = RNG_RNGInit();
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+ rv = BL_Init();
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+ RNG_SystemInfoForRNG();
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &bltest);
+ if (rv == SECFailure) {
+ fprintf(stderr, "%s: command line parsing error!\n", progName);
+ goto print_usage;
+ }
+ rv = SECFailure;
+
+ cipherInfo = PORT_ZNew(bltestCipherInfo);
+ cipherInfoListHead = cipherInfo;
+
+ /* Check the number of commands entered on the command line. */
+ commandsEntered = 0;
+ for (i = 0; i < bltest.numCommands; i++)
+ if (bltest.commands[i].activated)
+ commandsEntered++;
+
+ if (commandsEntered > 1 &&
+ !(commandsEntered == 2 && bltest.commands[cmd_SelfTest].activated)) {
+ fprintf(stderr, "%s: one command at a time!\n", progName);
+ goto print_usage;
+ }
+
+ if (commandsEntered == 0) {
+ fprintf(stderr, "%s: you must enter a command!\n", progName);
+ goto print_usage;
+ }
+
+ if (bltest.commands[cmd_Sign].activated)
+ bltest.commands[cmd_Encrypt].activated = PR_TRUE;
+ if (bltest.commands[cmd_Verify].activated)
+ bltest.commands[cmd_Decrypt].activated = PR_TRUE;
+ if (bltest.commands[cmd_Hash].activated)
+ bltest.commands[cmd_Encrypt].activated = PR_TRUE;
+
+ inoff = outoff = 0;
+ if (bltest.options[opt_InputOffset].activated)
+ inoff = PORT_Atoi(bltest.options[opt_InputOffset].arg);
+ if (bltest.options[opt_OutputOffset].activated)
+ outoff = PORT_Atoi(bltest.options[opt_OutputOffset].arg);
+
+ testdir = (bltest.options[opt_SelfTestDir].activated) ? strdup(bltest.options[opt_SelfTestDir].arg)
+ : ".";
+
+ /*
+ * Handle three simple cases first
+ */
+
+ /* test the RSA_PopulatePrivateKey function with known vectors */
+ if (bltest.commands[cmd_RSAPopulateKV].activated) {
+ PORT_Free(cipherInfo);
+ return doRSAPopulateTestKV();
+ }
+
+ /* test the RSA_PopulatePrivateKey function */
+ if (bltest.commands[cmd_RSAPopulate].activated) {
+ unsigned int keySize = 1024;
+ unsigned long exponent = 65537;
+ int rounds = 1;
+ int ret = -1;
+
+ if (bltest.options[opt_KeySize].activated) {
+ keySize = PORT_Atoi(bltest.options[opt_KeySize].arg);
+ }
+ if (bltest.options[opt_Rounds].activated) {
+ rounds = PORT_Atoi(bltest.options[opt_Rounds].arg);
+ }
+ if (bltest.options[opt_Exponent].activated) {
+ exponent = PORT_Atoi(bltest.options[opt_Exponent].arg);
+ }
+
+ for (i = 0; i < rounds; i++) {
+ printf("Running RSA Populate test round %d\n", i);
+ ret = doRSAPopulateTest(keySize, exponent);
+ if (ret != 0) {
+ break;
+ }
+ }
+ if (ret != 0) {
+ fprintf(stderr, "RSA Populate test round %d: FAILED\n", i);
+ }
+ PORT_Free(cipherInfo);
+ return ret;
+ }
+
+ /* Do BLAPI self-test */
+ if (bltest.commands[cmd_SelfTest].activated) {
+ PRBool encrypt = PR_TRUE, decrypt = PR_TRUE;
+ /* user may specified a set of ciphers to test. parse them. */
+ bltestCipherMode modesToTest[NUMMODES];
+ int numModesToTest = 0;
+ char *tok, *str;
+ str = bltest.options[opt_Mode].arg;
+ while (str) {
+ tok = strchr(str, ',');
+ if (tok)
+ *tok = '\0';
+ modesToTest[numModesToTest++] = get_mode(str);
+ if (tok) {
+ *tok = ',';
+ str = tok + 1;
+ } else {
+ break;
+ }
+ }
+ if (bltest.commands[cmd_Decrypt].activated &&
+ !bltest.commands[cmd_Encrypt].activated)
+ encrypt = PR_FALSE;
+ if (bltest.commands[cmd_Encrypt].activated &&
+ !bltest.commands[cmd_Decrypt].activated)
+ decrypt = PR_FALSE;
+ rv = blapi_selftest(modesToTest, numModesToTest, inoff, outoff,
+ encrypt, decrypt);
+ PORT_Free(cipherInfo);
+ return rv == SECSuccess ? 0 : 1;
+ }
+
+ /* Do FIPS self-test */
+ if (bltest.commands[cmd_FIPS].activated) {
+ CK_RV ckrv = sftk_FIPSEntryOK();
+ fprintf(stdout, "CK_RV: %ld.\n", ckrv);
+ PORT_Free(cipherInfo);
+ if (ckrv == CKR_OK)
+ return SECSuccess;
+ return SECFailure;
+ }
+
+ /*
+ * Check command line arguments for Encrypt/Decrypt/Hash/Sign/Verify
+ */
+
+ if ((bltest.commands[cmd_Decrypt].activated ||
+ bltest.commands[cmd_Verify].activated) &&
+ bltest.options[opt_BufSize].activated) {
+ fprintf(stderr, "%s: Cannot use a nonce as input to decrypt/verify.\n",
+ progName);
+ goto print_usage;
+ }
+
+ if (bltest.options[opt_Mode].activated) {
+ cipherInfo->mode = get_mode(bltest.options[opt_Mode].arg);
+ if (cipherInfo->mode == bltestINVALID) {
+ goto print_usage;
+ }
+ } else {
+ fprintf(stderr, "%s: You must specify a cipher mode with -m.\n",
+ progName);
+ goto print_usage;
+ }
+
+ if (bltest.options[opt_Repetitions].activated &&
+ bltest.options[opt_SecondsToRun].activated) {
+ fprintf(stderr, "%s: Operation time should be defined in either "
+ "repetitions(-p) or seconds(-5) not both",
+ progName);
+ goto print_usage;
+ }
+
+ if (bltest.options[opt_Repetitions].activated) {
+ cipherInfo->repetitionsToPerfom =
+ PORT_Atoi(bltest.options[opt_Repetitions].arg);
+ } else {
+ cipherInfo->repetitionsToPerfom = 0;
+ }
+
+ if (bltest.options[opt_SecondsToRun].activated) {
+ cipherInfo->seconds = PORT_Atoi(bltest.options[opt_SecondsToRun].arg);
+ } else {
+ cipherInfo->seconds = 0;
+ }
+
+ if (bltest.options[opt_CXReps].activated) {
+ cipherInfo->cxreps = PORT_Atoi(bltest.options[opt_CXReps].arg);
+ } else {
+ cipherInfo->cxreps = 0;
+ }
+
+ if (bltest.options[opt_ThreadNum].activated) {
+ threads = PORT_Atoi(bltest.options[opt_ThreadNum].arg);
+ if (threads <= 0) {
+ threads = 1;
+ }
+ }
+
+ /* Dump a file (rsakey, dsakey, etc.) */
+ if (bltest.commands[cmd_Dump].activated) {
+ rv = dump_file(cipherInfo->mode, bltest.options[opt_Input].arg);
+ PORT_Free(cipherInfo);
+ return rv;
+ }
+
+ /* default input mode is binary */
+ ioMode = (bltest.options[opt_B64].activated)
+ ? bltestBase64Encoded
+ : (bltest.options[opt_Hex].activated)
+ ? bltestHexStream
+ : (bltest.options[opt_HexWSpc].activated) ? bltestHexSpaceDelim
+ : bltestBinary;
+
+ if (bltest.options[opt_Exponent].activated)
+ exponent = PORT_Atoi(bltest.options[opt_Exponent].arg);
+ else
+ exponent = 65537;
+
+#ifndef NSS_DISABLE_ECC
+ if (bltest.options[opt_CurveName].activated)
+ curveName = PORT_Strdup(bltest.options[opt_CurveName].arg);
+ else
+ curveName = NULL;
+#endif
+
+ if (bltest.commands[cmd_Verify].activated &&
+ !bltest.options[opt_SigFile].activated) {
+ fprintf(stderr, "%s: You must specify a signature file with -f.\n",
+ progName);
+
+ print_usage:
+ if (cipherInfo) {
+ PORT_Free(cipherInfo);
+ }
+ Usage();
+ }
+
+ if (bltest.options[opt_MonteCarlo].activated) {
+ cipherInfo->mCarlo = PR_TRUE;
+ } else {
+ cipherInfo->mCarlo = PR_FALSE;
+ }
+
+ for (curThrdNum = 0; curThrdNum < threads; curThrdNum++) {
+ int keysize = 0;
+ PRFileDesc *file = NULL, *infile;
+ bltestParams *params;
+ char *instr = NULL;
+ PLArenaPool *arena;
+
+ if (curThrdNum > 0) {
+ bltestCipherInfo *newCInfo = PORT_ZNew(bltestCipherInfo);
+ if (!newCInfo) {
+ fprintf(stderr, "%s: Can not allocate memory.\n", progName);
+ goto exit_point;
+ }
+ newCInfo->mode = cipherInfo->mode;
+ newCInfo->mCarlo = cipherInfo->mCarlo;
+ newCInfo->repetitionsToPerfom =
+ cipherInfo->repetitionsToPerfom;
+ newCInfo->seconds = cipherInfo->seconds;
+ newCInfo->cxreps = cipherInfo->cxreps;
+ cipherInfo->next = newCInfo;
+ cipherInfo = newCInfo;
+ }
+ arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ fprintf(stderr, "%s: Can not allocate memory.\n", progName);
+ goto exit_point;
+ }
+ cipherInfo->arena = arena;
+ params = &cipherInfo->params;
+
+ /* Set up an encryption key. */
+ keysize = 0;
+ file = NULL;
+ if (is_symmkeyCipher(cipherInfo->mode) ||
+ is_aeadCipher(cipherInfo->mode)) {
+ char *keystr = NULL; /* if key is on command line */
+ if (bltest.options[opt_Key].activated) {
+ if (bltest.options[opt_CmdLine].activated) {
+ keystr = bltest.options[opt_Key].arg;
+ } else {
+ file = PR_Open(bltest.options[opt_Key].arg,
+ PR_RDONLY, 00660);
+ }
+ } else {
+ if (bltest.options[opt_KeySize].activated)
+ keysize = PORT_Atoi(bltest.options[opt_KeySize].arg);
+ else
+ keysize = 8; /* use 64-bit default (DES) */
+ /* save the random key for reference */
+ file = PR_Open("tmp.key", PR_WRONLY | PR_CREATE_FILE, 00660);
+ }
+ params->key.mode = ioMode;
+ setupIO(cipherInfo->arena, &params->key, file, keystr, keysize);
+ if (file)
+ PR_Close(file);
+ } else if (is_pubkeyCipher(cipherInfo->mode)) {
+ if (bltest.options[opt_Key].activated) {
+ file = PR_Open(bltest.options[opt_Key].arg, PR_RDONLY, 00660);
+ } else {
+ if (bltest.options[opt_KeySize].activated)
+ keysize = PORT_Atoi(bltest.options[opt_KeySize].arg);
+ else
+ keysize = 64; /* use 512-bit default */
+ file = PR_Open("tmp.key", PR_WRONLY | PR_CREATE_FILE, 00660);
+ }
+ params->key.mode = bltestBase64Encoded;
+#ifndef NSS_DISABLE_ECC
+ pubkeyInitKey(cipherInfo, file, keysize, exponent, curveName);
+#else
+ pubkeyInitKey(cipherInfo, file, keysize, exponent);
+#endif
+ PR_Close(file);
+ }
+
+ /* set up an initialization vector. */
+ if (cipher_requires_IV(cipherInfo->mode)) {
+ char *ivstr = NULL;
+ bltestSymmKeyParams *skp;
+ file = NULL;
+#ifdef NSS_SOFTOKEN_DOES_RC5
+ if (cipherInfo->mode == bltestRC5_CBC)
+ skp = (bltestSymmKeyParams *)&params->rc5;
+ else
+#endif
+ skp = &params->sk;
+ if (bltest.options[opt_IV].activated) {
+ if (bltest.options[opt_CmdLine].activated) {
+ ivstr = bltest.options[opt_IV].arg;
+ } else {
+ file = PR_Open(bltest.options[opt_IV].arg,
+ PR_RDONLY, 00660);
+ }
+ } else {
+ /* save the random iv for reference */
+ file = PR_Open("tmp.iv", PR_WRONLY | PR_CREATE_FILE, 00660);
+ }
+ memset(&skp->iv, 0, sizeof skp->iv);
+ skp->iv.mode = ioMode;
+ setupIO(cipherInfo->arena, &skp->iv, file, ivstr, keysize);
+ if (file) {
+ PR_Close(file);
+ }
+ }
+
+ /* set up an initialization vector. */
+ if (is_authCipher(cipherInfo->mode)) {
+ char *aadstr = NULL;
+ bltestAuthSymmKeyParams *askp;
+ file = NULL;
+ askp = &params->ask;
+ if (bltest.options[opt_AAD].activated) {
+ if (bltest.options[opt_CmdLine].activated) {
+ aadstr = bltest.options[opt_AAD].arg;
+ } else {
+ file = PR_Open(bltest.options[opt_AAD].arg,
+ PR_RDONLY, 00660);
+ }
+ } else {
+ file = NULL;
+ }
+ memset(&askp->aad, 0, sizeof askp->aad);
+ askp->aad.mode = ioMode;
+ setupIO(cipherInfo->arena, &askp->aad, file, aadstr, 0);
+ if (file) {
+ PR_Close(file);
+ }
+ }
+
+ if (bltest.commands[cmd_Verify].activated) {
+ file = PR_Open(bltest.options[opt_SigFile].arg, PR_RDONLY, 00660);
+ if (is_sigCipher(cipherInfo->mode)) {
+ memset(&params->asymk.sig, 0, sizeof(bltestIO));
+ params->asymk.sig.mode = ioMode;
+ setupIO(cipherInfo->arena, &params->asymk.sig, file, NULL, 0);
+ }
+ if (file) {
+ PR_Close(file);
+ }
+ }
+
+ if (bltest.options[opt_PQGFile].activated) {
+ file = PR_Open(bltest.options[opt_PQGFile].arg, PR_RDONLY, 00660);
+ params->asymk.cipherParams.dsa.pqgdata.mode = bltestBase64Encoded;
+ setupIO(cipherInfo->arena, &params->asymk.cipherParams.dsa.pqgdata,
+ file, NULL, 0);
+ if (file) {
+ PR_Close(file);
+ }
+ }
+
+ /* Set up the input buffer */
+ if (bltest.options[opt_Input].activated) {
+ if (bltest.options[opt_CmdLine].activated) {
+ instr = bltest.options[opt_Input].arg;
+ infile = NULL;
+ } else {
+ /* form file name from testdir and input arg. */
+ char *filename = bltest.options[opt_Input].arg;
+ if (bltest.options[opt_SelfTestDir].activated &&
+ testdir && filename && filename[0] != '/') {
+ filename = PR_smprintf("%s/tests/%s/%s", testdir,
+ mode_strings[cipherInfo->mode],
+ filename);
+ if (!filename) {
+ fprintf(stderr, "%s: Can not allocate memory.\n",
+ progName);
+ goto exit_point;
+ }
+ infile = PR_Open(filename, PR_RDONLY, 00660);
+ PR_smprintf_free(filename);
+ } else {
+ infile = PR_Open(filename, PR_RDONLY, 00660);
+ }
+ }
+ } else if (bltest.options[opt_BufSize].activated) {
+ /* save the random plaintext for reference */
+ char *tmpFName = PR_smprintf("tmp.in.%d", curThrdNum);
+ if (!tmpFName) {
+ fprintf(stderr, "%s: Can not allocate memory.\n", progName);
+ goto exit_point;
+ }
+ infile = PR_Open(tmpFName, PR_WRONLY | PR_CREATE_FILE, 00660);
+ PR_smprintf_free(tmpFName);
+ } else {
+ infile = PR_STDIN;
+ }
+ if (!infile) {
+ fprintf(stderr, "%s: Failed to open input file.\n", progName);
+ goto exit_point;
+ }
+ cipherInfo->input.mode = ioMode;
+
+ /* Set up the output stream */
+ if (bltest.options[opt_Output].activated) {
+ /* form file name from testdir and input arg. */
+ char *filename = bltest.options[opt_Output].arg;
+ if (bltest.options[opt_SelfTestDir].activated &&
+ testdir && filename && filename[0] != '/') {
+ filename = PR_smprintf("%s/tests/%s/%s", testdir,
+ mode_strings[cipherInfo->mode],
+ filename);
+ if (!filename) {
+ fprintf(stderr, "%s: Can not allocate memory.\n", progName);
+ goto exit_point;
+ }
+ outfile = PR_Open(filename, PR_WRONLY | PR_CREATE_FILE, 00660);
+ PR_smprintf_free(filename);
+ } else {
+ outfile = PR_Open(filename, PR_WRONLY | PR_CREATE_FILE, 00660);
+ }
+ } else {
+ outfile = PR_STDOUT;
+ }
+ if (!outfile) {
+ fprintf(stderr, "%s: Failed to open output file.\n", progName);
+ rv = SECFailure;
+ goto exit_point;
+ }
+ cipherInfo->output.mode = ioMode;
+ if (bltest.options[opt_SelfTestDir].activated && ioMode == bltestBinary)
+ cipherInfo->output.mode = bltestBase64Encoded;
+
+ if (is_hashCipher(cipherInfo->mode))
+ cipherInfo->params.hash.restart =
+ bltest.options[opt_Restart].activated;
+
+ bufsize = 0;
+ if (bltest.options[opt_BufSize].activated)
+ bufsize = PORT_Atoi(bltest.options[opt_BufSize].arg);
+
+ /*infile = NULL;*/
+ setupIO(cipherInfo->arena, &cipherInfo->input, infile, instr, bufsize);
+ if (infile && infile != PR_STDIN)
+ PR_Close(infile);
+ misalignBuffer(cipherInfo->arena, &cipherInfo->input, inoff);
+
+ cipherInit(cipherInfo, bltest.commands[cmd_Encrypt].activated);
+ misalignBuffer(cipherInfo->arena, &cipherInfo->output, outoff);
+ }
+
+ if (!bltest.commands[cmd_Nonce].activated) {
+ TIMESTART();
+ cipherInfo = cipherInfoListHead;
+ while (cipherInfo != NULL) {
+ cipherInfo->cipherThread =
+ PR_CreateThread(PR_USER_THREAD,
+ ThreadExecTest,
+ cipherInfo,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ cipherInfo = cipherInfo->next;
+ }
+
+ cipherInfo = cipherInfoListHead;
+ while (cipherInfo != NULL) {
+ PR_JoinThread(cipherInfo->cipherThread);
+ finishIO(&cipherInfo->output, outfile);
+ cipherInfo = cipherInfo->next;
+ }
+ TIMEFINISH(totalTime, 1);
+ }
+
+ cipherInfo = cipherInfoListHead;
+ if (cipherInfo->repetitions > 0 || cipherInfo->cxreps > 0 ||
+ threads > 1)
+ dump_performance_info(cipherInfoListHead, totalTime,
+ bltest.commands[cmd_Encrypt].activated,
+ (cipherInfo->repetitions == 0));
+
+ rv = SECSuccess;
+
+exit_point:
+ if (outfile && outfile != PR_STDOUT)
+ PR_Close(outfile);
+ cipherInfo = cipherInfoListHead;
+ while (cipherInfo != NULL) {
+ bltestCipherInfo *tmpInfo = cipherInfo;
+
+ if (cipherInfo->arena)
+ PORT_FreeArena(cipherInfo->arena, PR_TRUE);
+ cipherInfo = cipherInfo->next;
+ PORT_Free(tmpInfo);
+ }
+
+ /*NSS_Shutdown();*/
+
+ return SECSuccess;
+}
diff --git a/security/nss/cmd/bltest/bltest.gyp b/security/nss/cmd/bltest/bltest.gyp
new file mode 100644
index 000000000..7139c3181
--- /dev/null
+++ b/security/nss/cmd/bltest/bltest.gyp
@@ -0,0 +1,35 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'bltest',
+ 'type': 'executable',
+ 'sources': [
+ 'blapitest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports',
+ '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'include_dirs': [
+ '../../nss/lib/softoken'
+ ],
+ 'defines': [
+ 'NSS_USE_STATIC_LIBS'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss',
+ 'use_static_libs': 1
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/bltest/manifest.mn b/security/nss/cmd/bltest/manifest.mn
new file mode 100644
index 000000000..6e9946c34
--- /dev/null
+++ b/security/nss/cmd/bltest/manifest.mn
@@ -0,0 +1,26 @@
+#
+# 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/.
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+REQUIRES = seccmd dbm softoken
+
+INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken
+
+PROGRAM = bltest
+
+ USE_STATIC_LIBS = 1
+
+EXPORTS = \
+ $(NULL)
+
+PRIVATE_EXPORTS = \
+ $(NULL)
+
+CSRCS = \
+ blapitest.c \
+ $(NULL)
+
diff --git a/security/nss/cmd/bltest/pkcs1_vectors.h b/security/nss/cmd/bltest/pkcs1_vectors.h
new file mode 100644
index 000000000..06729675e
--- /dev/null
+++ b/security/nss/cmd/bltest/pkcs1_vectors.h
@@ -0,0 +1,789 @@
+/* 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/. */
+
+/* Vectors from pkcs1v15sign-vectors.txt */
+
+struct pkcs1_test_vector {
+ unsigned char *n;
+ unsigned long n_len;
+ unsigned char *e;
+ unsigned long e_len;
+ unsigned char *d;
+ unsigned long d_len;
+ unsigned char *p;
+ unsigned long p_len;
+ unsigned char *q;
+ unsigned long q_len;
+};
+
+struct pkcs1_test_vector PKCS1_VECTORS[15] = {
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+ 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+ 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+ 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+ 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+ 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+ 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+ 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+ 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+ 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+ 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ },
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+ 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+ 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+ 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+ 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+ 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+ 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+ 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+ 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+ 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+ 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ },
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+ 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+ 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+ 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+ 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+ 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+ 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+ 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+ 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+ 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+ 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ },
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+ 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+ 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+ 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+ 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+ 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+ 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+ 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+ 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+ 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+ 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ },
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+ 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+ 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+ 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+ 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+ 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+ 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+ 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+ 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+ 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+ 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ },
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+ 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+ 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+ 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+ 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+ 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+ 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+ 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+ 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+ 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+ 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ },
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88,
+ 0x5f, 0x2a, 0x4b, 0xbe, 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac,
+
+ 0x3c, 0x56, 0x8c, 0x8f, 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02,
+
+ 0x66, 0xc8, 0xc6, 0xa3, 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1,
+ 0x12, 0x31, 0x88, 0x44, 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f,
+ 0xee, 0x89, 0x6a, 0x10, 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7,
+ 0x34, 0xe4, 0x47, 0x27, 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53,
+ 0x26, 0x83, 0x10, 0x9c, 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c,
+ 0x31, 0xb4, 0xbd, 0x2f, 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52,
+ 0xce, 0xe3, 0x4f, 0x9e, 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22,
+ 0xad, 0x79, 0xc6, 0xdc, 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3,
+ 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ },
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+ 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+ 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+ 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+ 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+ 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+ 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+ 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+ 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+ 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+ 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ },
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+ 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+ 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+ 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+ 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+ 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+ 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+ 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+ 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+ 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+ 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ },
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+ 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+ 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+ 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+ 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+ 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+ 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+ 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+ 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+ 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+ 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ },
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+ 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+ 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+ 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+ 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+ 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+ 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+ 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+ 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+ 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+ 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ },
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+ 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+ 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+ 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+ 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+ 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+ 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+ 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+ 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+ 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+ 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ },
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+ 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+ 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+ 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+ 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+ 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+ 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+ 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+ 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+ 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+ 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ },
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+ 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+ 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+ 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+ 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+ 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+ 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+ 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+ 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+ 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+ 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ },
+ {
+ (unsigned char[]){
+ 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+ 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+ 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+ 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+ 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+ 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+ 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+ 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+ 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+ 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+ 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+ 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+ 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+ 128,
+ (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+ (unsigned char[]){
+ 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+ 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+ 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+ 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+ 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+ 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+ 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+ 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+ 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+ 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+ 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+ 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+ 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+ 128,
+ (unsigned char[]){
+ 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+ 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+ 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+ 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+ 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+ 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+ 0x9a, 0x67, 0x99, 0xfd },
+ 64,
+ (unsigned char[]){
+ 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+ 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+ 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+ 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+ 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+ 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+ 0xda, 0x8e, 0x64, 0x43 },
+ 64,
+ }
+};
diff --git a/security/nss/cmd/bltest/tests/README b/security/nss/cmd/bltest/tests/README
new file mode 100644
index 000000000..6d1302b46
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/README
@@ -0,0 +1,56 @@
+This directory contains a set of tests for each cipher supported by
+BLAPI. Each subdirectory contains known plaintext and ciphertext pairs
+(and keys and/or iv's if needed). The tests can be run as a full set
+with:
+ bltest -T
+or as subsets, for example:
+ bltest -T -m des_ecb,md2,rsa
+
+In each subdirectory, the plaintext, key, and iv are ascii, and treated
+as such. The ciphertext is base64-encoded to avoid the hassle of binary
+files.
+
+To add a test, incremement the value in the numtests file. Create a
+plaintext, key, and iv file, such that the name of the file is
+incrememted one from the last set of tests. For example, if you are
+adding the second test, put your data in files named plaintext1, key1,
+and iv1 (ignoring key and iv if they are not needed, of course). Make
+sure your key and iv are the correct number of bytes for your cipher (a
+trailing \n is okay, but any other trailing bytes will be used!). Once
+you have your input data, create output data by running bltest on a
+trusted implementation. For example, for a new DES ECB test, run
+ bltest -E -m des_ecb -i plaintext1 -k key1 -o ciphertext1 -a in the
+tests/des_ecb directory. Then run
+ bltest -T des_ecb from the cmd/bltest directory in the tree of the
+implementation you want to test.
+
+Note that the -a option above is important, it tells bltest to expect
+the input to be straight ASCII, and not base64 encoded binary!
+
+Special cases:
+
+RC5:
+RC5 can take additional parameters, the number of rounds to perform and
+the wordsize to use. The number of rounds is between is between 0 and
+255, and the wordsize is either is either 16, 32, or 64 bits (at this
+time only 32-bit is supported). These parameters are specified in a
+paramsN file, where N is an index as above. The format of the file is
+"rounds=R\nwordsize=W\n".
+
+public key modes (RSA and DSA):
+Asymmetric key ciphers use keys with special properties, so creating a
+key file with "Mozilla!" in it will not get you very far! To create a
+public key, run bltest with the plaintext you want to encrypt, using a
+trusted implementation. bltest will generate a key and store it in
+"tmp.key", rename that file to keyN. For example:
+ bltest -E -m rsa -i plaintext0 -o ciphertext0 -e 65537 -g 32 -a
+ mv tmp.key key0
+
+RSA-OAEP/RSA-PSS:
+RSA-OAEP and RSA-PSS have a number of additional parameters to feed in.
+- "seedN": The seed or salt to use when encrypting/signing
+- "hashN" / "maskhashN" - The base digest algorithm and the digest algorithm
+ to use with MGF1, respectively. This should be an ASCII string specifying
+ one of the hash algorithms recognized by bltest (eg: "sha1", "sha256")
+
+[note: specifying a keysize (-g) when using RSA is important!]
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext0 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext0
new file mode 100644
index 000000000..4da9e529b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext0
@@ -0,0 +1 @@
+oJLgOzZ1GiWt3DGo2sPKaOnyGuRz5sZwmDyn4dvAqd8=
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext1 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext1
new file mode 100644
index 000000000..1126bbf38
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext1
@@ -0,0 +1 @@
+AzZ2PpZtkllaVnzJzlN/Xg==
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext10 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext10
new file mode 100644
index 000000000..c3d443ffe
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext10
@@ -0,0 +1,3 @@
+eykx9YVfcXFF4A8VKp9HlDWbH/yz5V9ZTjMJi1HCOmx0oGwdlP3tf9KuQsfbesrv
+WETLM67dxoUlhe0AIKZpnSy1OAnO/RaRSM5CKSr6sGNEOXgwbFgsGLnODaPQhM5N
+PEgs/Y/PGoUITon7iLQKCE1elyRm0HZmEm+3YfhAePI=
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext11 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext11
new file mode 100644
index 000000000..ae00d8b01
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext11
@@ -0,0 +1,3 @@
+sJUS8+/57Q2FiQmDpz2tu3w2eNUlgb5kqKj8WG9JDyUhKXpHigWYBA69D1UJ+vsJ
+afnZ5gDq7zOxuT7tmWh7Fn+JpQZarEOc5G87jSLTCGXmTkXvjNMLaYQ1OoRKEcjN
+YNug6IZrPuMNJLP6imQ7MoNT4GAQ+oJzyP1U7woraTDlUgquXNWQL5uGozWSykNl
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext12 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext12
new file mode 100644
index 000000000..605a1bab0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext12
@@ -0,0 +1,4 @@
+a+ihKABFWjIFOIU+DLoxvS2A6gyFFkpMXCYa5IVBfZPv/i68DQoLUdbqGGM9IQz2
+PAxN28J2B/LoHtkRMZHvhtVvO5m+bEFaQVApn7hGznFgtAtjuvEXnRknWi6DaYN2
+0ouSVIxo4G5tmU4sFQHtKXAU5wLN7+4vZWRHcGAJYU2AHeHKr3P4t/pWzxupS2MZ
+M7vld2JDgIUPEXQ1oDVbKw==
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext13 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext13
new file mode 100644
index 000000000..2abf3695c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext13
@@ -0,0 +1 @@
+UdRHefkNQKgASCdsA1y0nKKke8ubnPcnC5FEeTeH1T8=
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext14 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext14
new file mode 100644
index 000000000..f16428a98
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext14
@@ -0,0 +1,2 @@
+1fVYl2C/nHYiKP3iNt4fot0trUSNs/qb4MQZbv1Go1yE3RrHfZ21jJWRjLMXpkMK
+CNL7ao6LDxybcsejRNw0nw==
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext15 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext15
new file mode 100644
index 000000000..ed1cecd99
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext15
@@ -0,0 +1,2 @@
+dTlZdL0ys2ZWVKbI45a4iuNLEjV1hyp6tofY52tG35EailkM0B0vXDML46Zibp3T
+ql4Q7RTo/4KYEbb+1Q8/UzykOFocvKePXEdE5Q8vg1kWXCSF0TJOdsPq52oMysYp
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext16 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext16
new file mode 100644
index 000000000..8fa895224
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext16
@@ -0,0 +1,3 @@
+gVjiFCDyW1nWrpQ/ocvyHwLpefQZ2rASanIbfu9Vvumtl/XM/30jkFe7wZqMN4FC
+92cvHV5+F9e+vLAHDoNVys5mYBcaU7YYFq6CSm72nORwtv/TtbtLQ4h02R0nhU07
+byWGDTholY3jMH1isTOb3duKMYwM4PM8F8rw6fYECCA=
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext17 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext17
new file mode 100644
index 000000000..8ca864c9e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext17
@@ -0,0 +1,3 @@
+km2ySMwbog8MV2MafIrvCU95GTe5BZSeNGAkDov6b6SDEVobMQtuQ2nK68UmKIg3
+ex3apYAOpJaivf8PmhAx5xKcmiDjViHn8Li6yg2HAw8q58qFk8hZlnegb9SyYAnq
+0I/srCTKqc8srTtHDIInQVp7Hg8uqz+tltcKIJyLsmxidnfiUxuUNcpuPERNGVtf
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext18 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext18
new file mode 100644
index 000000000..9b4274091
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext18
@@ -0,0 +1,4 @@
+yCzyxHbeqMtqbmB6QNLwORvoLqnshKU3poIPmvuZe3Y5fQBUJPqmp03E6MeqSokA
+aQ+JS20dyoBnU5PSJDrax2LxWTAeNX6YtyR2IxDNWnuv4cKgMNukb9k6n9uJzBMs
+qcF9xyAx7Ggi7lqdmdvKZseEwBsIhcu2LinZeAGSfsQVpdIVFY0yX57miUN60bdo
+StM8DZJzlFGsh/Of+MMbhA==
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext19 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext19
new file mode 100644
index 000000000..39bf9377e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext19
@@ -0,0 +1 @@
+L6Dfciqf07ZMsY+ys9tV/yJnQidXKJQT+PZXUHQSpkw=
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext2 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext2
new file mode 100644
index 000000000..ec069abd4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext2
@@ -0,0 +1 @@
+qaFjG/SZaVTrwJOVeyNFiQ==
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext20 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext20
new file mode 100644
index 000000000..d74f0e041
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext20
@@ -0,0 +1,2 @@
+BdXHdylCGwi3N+QRGfpEONH1cMx3Kk1sPff/7aA4TvhCiM43/ExMfRElpJmwUTZM
+OJ/WOb3aZH2qO9rasutVlA==
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext21 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext21
new file mode 100644
index 000000000..9f3b9ead7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext21
@@ -0,0 +1,2 @@
+rD1tuv4uD3QGMv2eggv2BEzVsVUcu5zAPAslw5zLfzO4Oqz8pAoyZfK7/4eRU0SK
+ysuI/Ps7t7EP5GOmjAEJ8Cg4Lj5VexrfAu1kira7iV3wIF0m67+ppf2M69jkvuPc
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext22 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext22
new file mode 100644
index 000000000..b9b5b5ce3
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext22
@@ -0,0 +1,3 @@
+kLe5YwojePU/UBq3vv8DkVUAgHG8hDjniZMs/T6xKZGVRl5mM4SUY/20Q3Unji/b
+ExCCHmSSz4D/Fct3JQn7Qm867uJ71JOIgv0q5rW9nZH6SkOxe7Q5675ZwEIxAWOo
+Kl/lOIeW7uNaGBoScfAL4puFLY+nWbrQH/RnjwEFlM0=
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext23 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext23
new file mode 100644
index 000000000..e7710c1f0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext23
@@ -0,0 +1,3 @@
+AlSyNGO8q+xaOV63TI+w6xN6B7xvXp9h7AsFfeMFcU+PopQiHJGhWcMVk5uB4wDu
+kCGS7F8VJUQo2HcveTJOxDKYyiHACzcCc+5eXtkOQ++h4FpdFxIJ/jT58pI326Km
+cmZQ/TsTIXR9EgiGPGw8az4th5q18leC8Iuo8qu+Y+C+20oifoGvs2u2ZFUINW00
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext24 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext24
new file mode 100644
index 000000000..d5234aa64
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext24
@@ -0,0 +1,4 @@
+/Fhz5Q3o+vTGuEunB7CFTp25qy6ffXB/u6M4xoQ6GPxvrOuvZj0mKW+zKbTSbxhJ
+THngnneWR/m6+odIljDXn0MBYQwjAMGdvzFIt8rIxPSUQQJ1TzMukrb3xedbxhee
+uHegeNRxkAkCF0TBTxP9KlWiucRNGAAGhahFpPYyx8VqdzBu+maiTQXQiNzXwT/i
+T8RHJ1ll255NN/vJMERIzQ==
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext3 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext3
new file mode 100644
index 000000000..82c4cd202
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext3
@@ -0,0 +1 @@
+J1z8BBPYzLcFE8OFmx0Pcg==
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext4 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext4
new file mode 100644
index 000000000..81714bd4d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext4
@@ -0,0 +1 @@
+ybgTX/G1rcQT39BTshvZbQ==
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext5 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext5
new file mode 100644
index 000000000..ce9672a51
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext5
@@ -0,0 +1 @@
+XJ2ETtRvmIUIXl1qT5TH1w==
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext6 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext6
new file mode 100644
index 000000000..fc53a4f55
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext6
@@ -0,0 +1 @@
+qf91vXz2YT03Mcd8O20MBA==
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext7 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext7
new file mode 100644
index 000000000..1d6d84bb0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext7
@@ -0,0 +1 @@
+xNxh2XJZZ6MCAQSpc48jhoUnzoOaqxdS/YvblagsTQA=
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext8 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext8
new file mode 100644
index 000000000..7191a647a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext8
@@ -0,0 +1,2 @@
+Gblgl3LGPzOGCL9utSyhC+ZQl/icHgkFxCQB/Ud5GuLFRAstRzEWyni9n/L7YBXP
+0xZSTq59y5Wuc46+roSkZw==
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext9 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext9
new file mode 100644
index 000000000..232a69114
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext9
@@ -0,0 +1,2 @@
+O4YRv8SXPFzY6YKwc7MxhM0mEQFZFy5EmI61/1ZhoeFvrWclj8v+5VRpJnoS3DdI
+k7TjUz029WNMMJVYNZbxNaqM0RONyJi8VlHuNakuv4mrautTZmU7xgpw4AdPwR7+
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv0 b/security/nss/cmd/bltest/tests/aes_cbc/iv0
new file mode 100644
index 000000000..4e65bc034
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv0
@@ -0,0 +1 @@
+qwertyuiopasdfgh
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv1 b/security/nss/cmd/bltest/tests/aes_cbc/iv1
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv1
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv10 b/security/nss/cmd/bltest/tests/aes_cbc/iv10
new file mode 100644
index 000000000..58d7a2da9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv10
@@ -0,0 +1 @@
+žù4”n\Ю—½XS,´“ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv11 b/security/nss/cmd/bltest/tests/aes_cbc/iv11
new file mode 100644
index 000000000..6847886b9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv11
@@ -0,0 +1 @@
+$_&[vëëÂíÊÄ¢ø \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv12 b/security/nss/cmd/bltest/tests/aes_cbc/iv12
new file mode 100644
index 000000000..15040cd21
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv12
@@ -0,0 +1 @@
+»ë/«´H¯„—–$J× \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv13 b/security/nss/cmd/bltest/tests/aes_cbc/iv13
new file mode 100644
index 000000000..1bef08adf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv13
@@ -0,0 +1 @@
+óÖf~My`÷P[£ƒë \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv14 b/security/nss/cmd/bltest/tests/aes_cbc/iv14
new file mode 100644
index 000000000..099828fdf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv14
@@ -0,0 +1 @@
+‹YÉ œRœ¨9ŸÀÎ<8 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv15 b/security/nss/cmd/bltest/tests/aes_cbc/iv15
new file mode 100644
index 000000000..d7a44d9d6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv15
@@ -0,0 +1 @@
+6긃¯ï“lÃc(FÍ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv16 b/security/nss/cmd/bltest/tests/aes_cbc/iv16
new file mode 100644
index 000000000..678bb8d67
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv16
@@ -0,0 +1 @@
+ãțЗëÝöOHÛm¿â \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv17 b/security/nss/cmd/bltest/tests/aes_cbc/iv17
new file mode 100644
index 000000000..7ff21ab69
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv17
@@ -0,0 +1 @@
+’¤(3ñE ¤½Æè< \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv18 b/security/nss/cmd/bltest/tests/aes_cbc/iv18
new file mode 100644
index 000000000..244b5022e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv18
@@ -0,0 +1 @@
+$@€8,Êà{›¶cUÁ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv19 b/security/nss/cmd/bltest/tests/aes_cbc/iv19
new file mode 100644
index 000000000..919e16574
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv19
@@ -0,0 +1 @@
+ýê¡4È×7EquýWÓü \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv2 b/security/nss/cmd/bltest/tests/aes_cbc/iv2
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv2
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv20 b/security/nss/cmd/bltest/tests/aes_cbc/iv20
new file mode 100644
index 000000000..c49bf8f70
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv20
@@ -0,0 +1 @@
+ÀÍ+ëÌ»lI’ ÕH*ÇVè \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv21 b/security/nss/cmd/bltest/tests/aes_cbc/iv21
new file mode 100644
index 000000000..6452e3d63
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv21
@@ -0,0 +1,2 @@
+³Ë—¨
+S™¸ÂE ;“• \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv22 b/security/nss/cmd/bltest/tests/aes_cbc/iv22
new file mode 100644
index 000000000..42b7bd3af
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv22
@@ -0,0 +1 @@
+LïüYcÔY`&u>–I \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv23 b/security/nss/cmd/bltest/tests/aes_cbc/iv23
new file mode 100644
index 000000000..99b22495c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv23
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv24 b/security/nss/cmd/bltest/tests/aes_cbc/iv24
new file mode 100644
index 000000000..0104daff2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv24
@@ -0,0 +1 @@
+ÖÕ¸ÏëӶ꡵?~á \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv3 b/security/nss/cmd/bltest/tests/aes_cbc/iv3
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv3
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv4 b/security/nss/cmd/bltest/tests/aes_cbc/iv4
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv4
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv5 b/security/nss/cmd/bltest/tests/aes_cbc/iv5
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv5
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv6 b/security/nss/cmd/bltest/tests/aes_cbc/iv6
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv6
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv7 b/security/nss/cmd/bltest/tests/aes_cbc/iv7
new file mode 100644
index 000000000..524d1b984
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv7
@@ -0,0 +1 @@
+ªÑX<Ùeã»/ 40Ðe» \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv8 b/security/nss/cmd/bltest/tests/aes_cbc/iv8
new file mode 100644
index 000000000..f58e954f9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv8
@@ -0,0 +1 @@
+È ]‹± `iŸ|—J  \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv9 b/security/nss/cmd/bltest/tests/aes_cbc/iv9
new file mode 100644
index 000000000..d6c478267
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv9
@@ -0,0 +1 @@
+eµî60¾Ö¸BÙ¹z \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key0 b/security/nss/cmd/bltest/tests/aes_cbc/key0
new file mode 100644
index 000000000..13911cc29
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key0
@@ -0,0 +1 @@
+fedcba9876543210
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key1 b/security/nss/cmd/bltest/tests/aes_cbc/key1
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key1
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key10 b/security/nss/cmd/bltest/tests/aes_cbc/key10
new file mode 100644
index 000000000..3cdff7a85
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key10
@@ -0,0 +1 @@
+Ä‘Ê1ùEŽ)©%ìUx \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key11 b/security/nss/cmd/bltest/tests/aes_cbc/key11
new file mode 100644
index 000000000..4a1304010
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key11
@@ -0,0 +1 @@
+öè}q°Mn°jhÜjqô˜ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key12 b/security/nss/cmd/bltest/tests/aes_cbc/key12
new file mode 100644
index 000000000..0a0103deb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key12
@@ -0,0 +1 @@
+,A7QÃ'0W £6xk \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key13 b/security/nss/cmd/bltest/tests/aes_cbc/key13
new file mode 100644
index 000000000..87ae208d6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key13
@@ -0,0 +1 @@
+ê³±œX¨sᘃ«ƒ»øQû.k! \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key14 b/security/nss/cmd/bltest/tests/aes_cbc/key14
new file mode 100644
index 000000000..de4da4d4e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key14
@@ -0,0 +1 @@
+{±{M÷…i~¬Ï–˜âËuæy|é5Ë \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key15 b/security/nss/cmd/bltest/tests/aes_cbc/key15
new file mode 100644
index 000000000..b13351f01
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key15
@@ -0,0 +1 @@
+ãþÌuðZ ³ƒßÓ‰£Ó<ɸT³²TÀô \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key16 b/security/nss/cmd/bltest/tests/aes_cbc/key16
new file mode 100644
index 000000000..71afcb384
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key16
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key17 b/security/nss/cmd/bltest/tests/aes_cbc/key17
new file mode 100644
index 000000000..291b89b1b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key17
@@ -0,0 +1 @@
+¼¦ú<gý)N•fþ‹ÖOEô(õ¼Ž—3§ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key18 b/security/nss/cmd/bltest/tests/aes_cbc/key18
new file mode 100644
index 000000000..9c28957d7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key18
@@ -0,0 +1 @@
+*ÕæJªUWíÁk,jMK^î \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key19 b/security/nss/cmd/bltest/tests/aes_cbc/key19
new file mode 100644
index 000000000..f0ca40820
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key19
@@ -0,0 +1 @@
+ÜâlkLû(eÚNìÒÏþlßC3Û›_w´`g›Ô® \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key2 b/security/nss/cmd/bltest/tests/aes_cbc/key2
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key2
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key20 b/security/nss/cmd/bltest/tests/aes_cbc/key20
new file mode 100644
index 000000000..ce2858764
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key20
@@ -0,0 +1 @@
+“ÿcq¯j[Ž¬ßZ=K¯Ñ¯µs¾zÞž†‚æcå \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key21 b/security/nss/cmd/bltest/tests/aes_cbc/key21
new file mode 100644
index 000000000..1b1a9bc44
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key21
@@ -0,0 +1,2 @@
+s¸úð 3¬™…\öùéä…i
+Y¤†MÏHÒ‚ú®* \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key22 b/security/nss/cmd/bltest/tests/aes_cbc/key22
new file mode 100644
index 000000000..4b23daa1b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key22
@@ -0,0 +1 @@
+E‹g¿!- ó¥Î9 eX-Îûóª"”Ÿƒ8«R& \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key23 b/security/nss/cmd/bltest/tests/aes_cbc/key23
new file mode 100644
index 000000000..cc1b48fe4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key23
@@ -0,0 +1 @@
+ÒA-°„]„ås+‹½d)WG;û™Ê‹ÿpç’ ÁÛì‰ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key24 b/security/nss/cmd/bltest/tests/aes_cbc/key24
new file mode 100644
index 000000000..cf579fcfe
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key24
@@ -0,0 +1 @@
+H¾Y~c,w#$ÈÓúœZžÍì] ;þÃvÅS+ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key3 b/security/nss/cmd/bltest/tests/aes_cbc/key3
new file mode 100644
index 000000000..4ac5fc6cf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key3
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key4 b/security/nss/cmd/bltest/tests/aes_cbc/key4
new file mode 100644
index 000000000..4ac5fc6cf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key4
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key5 b/security/nss/cmd/bltest/tests/aes_cbc/key5
new file mode 100644
index 000000000..4e4e49357
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key5
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key6 b/security/nss/cmd/bltest/tests/aes_cbc/key6
new file mode 100644
index 000000000..4e4e49357
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key6
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key7 b/security/nss/cmd/bltest/tests/aes_cbc/key7
new file mode 100644
index 000000000..c1e46cee5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key7
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key8 b/security/nss/cmd/bltest/tests/aes_cbc/key8
new file mode 100644
index 000000000..804b8d421
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key8
@@ -0,0 +1 @@
+·óÉWnÝ ¶>¬+š9 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key9 b/security/nss/cmd/bltest/tests/aes_cbc/key9
new file mode 100644
index 000000000..193a2a14d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key9
@@ -0,0 +1 @@
+»ç·ºOñ®|4þ‹F^ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/mktst.sh b/security/nss/cmd/bltest/tests/aes_cbc/mktst.sh
new file mode 100644
index 000000000..443167efb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/mktst.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+do
+ file="test$i.txt"
+ grep "KEY = " $file | sed -e 's;KEY = ;;' | hex > key$i
+ grep "IV = " $file | sed -e 's;IV = ;;' | hex > iv$i
+ grep "PLAINTEXT = " $file | sed -e 's;PLAINTEXT = ;;' | hex > plaintext$i
+ grep "CIPHERTEXT = " $file | sed -e 's;CIPHERTEXT = ;;' | hex > ciphertext$i.bin
+ btoa < ciphertext$i.bin > ciphertext$i
+ rm ciphertext$i.bin
+done
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/numtests b/security/nss/cmd/bltest/tests/aes_cbc/numtests
new file mode 100644
index 000000000..7273c0fa8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/numtests
@@ -0,0 +1 @@
+25
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext0 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext0
new file mode 100644
index 000000000..cc6718945
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext0
@@ -0,0 +1 @@
+0123456789abcdef0123456789abcdef
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext1 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext1
new file mode 100644
index 000000000..8bac1b756
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext1
@@ -0,0 +1 @@
+óDì<Æ'ºÍ]Ãûòsæ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext10 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext10
new file mode 100644
index 000000000..779400be5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext10
@@ -0,0 +1,2 @@
+Ëjx~ ìVù¡e•¯3l¦´…Ùé@“ÆQRdŸˆ.‡My¬^{Ò§Lå®.èTöSž
+”ykÔÉüÛÇšËïMvÑŠ÷â¤üGÝfßlM¾PäfTšG¶6¼Ç³¦$•µk¶{mE_ëÙ¿ï켦Çó5ÏΛEË \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext11 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext11
new file mode 100644
index 000000000..c226c29df
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext11
@@ -0,0 +1 @@
+ø+ï<s¦÷ø ²…rmi¶¿UîÂZ…; àD_&¹»;£цnMØòåøì´ämt§§Œ Íü{ÌžG›§ Êº”8#ŠÐÀQÕÙãÝÎnkKÔ«ÏžŽØ®ß¡Ï–;“ g¹}wm·n~‘?tHã‚DPŸ ¯6½‚áS6Ó\ŸÔä‰?Û„O‡) \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext12 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext12
new file mode 100644
index 000000000..357fd2ccd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext12
@@ -0,0 +1 @@
+@Ù0ù S4Ùo♜?‚ ?jW¨ÄuÉESÑÑi:Üa€Ið§i¢îÖ¦ËÀ>ÅÌͼìLå`ÏÒ"W 2mM甎TÖÐ×þ×Rû#ñªD”û°0éÞÔç~7Ày-‚€@Ã%±¥ïÑ_ÈBä@ÊCt¿8óÃü>ã's; Šî¼ÐUw/Ü`?{,¦Ÿöb6+à¡q»Üê]? \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext13 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext13
new file mode 100644
index 000000000..88c5250f6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext13
@@ -0,0 +1 @@
+NLÌÑh#!…mðiãñÆú9:Ÿ°-YÛtÁ@³¬Ä \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext14 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext14
new file mode 100644
index 000000000..c42aec2ae
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext14
@@ -0,0 +1 @@
+Û7…¨‰´½8wTÚ"/L-+þ yà[Éû©A¾ê0ñ#ž¬ðFìÃhé†ü¦·ÅŽIyÒ–½y†ïõO \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext15 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext15
new file mode 100644
index 000000000..12662556e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext15
@@ -0,0 +1 @@
+“/_:X Õ:kêªd1:4ˆôë°õµ~ø8áW–#;Öæ€wS‹.Qïp<IVC.ŠŽæ£NB²jؽ®l*ù¦Ç™o;`ÒgAñÉôà=JR° eJ3óMÎ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext16 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext16
new file mode 100644
index 000000000..6348620c8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext16
@@ -0,0 +1 @@
+Á£vƒû(”gÝ,‰ïº»Òî$ÏÑDYmí&‚Çš/qz2¿j$ºÝ2¤îc|s·¤¦%†5e‘ûŸúE½ü<±"bA³ÞÎØ™j¥¨Óèpà¤KÀWÔ†# Ö"©?©Ú) ªíõÙèvÉF ”_øìÈ?'7žÕ\ôÅy' \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext17 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext17
new file mode 100644
index 000000000..6343a1aac
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext17
@@ -0,0 +1,2 @@
+[ì¼1ؾ­m6®JXcÑJCkUÒž¦ºªArqqm³£;.PkE †ßæƒJÂÞ0¼A%NÅ@Ä}B7Çy/ÜבMŠò±ufBÕŒu©/kÅ=2j饷á±
+—VWF’“M™9ü9ž ?~ߎ~d‚êÝ1 @pè—´ŒkÊ+@E“P€é3w5ŒB ôÞÞ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext18 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext18
new file mode 100644
index 000000000..4858130f6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext18
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext19 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext19
new file mode 100644
index 000000000..0d6ad5e8c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext19
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext2 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext2
new file mode 100644
index 000000000..b2153e2ad
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext2
@@ -0,0 +1 @@
+—˜Äd ­uÇÃ"}¹Nr \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext20 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext20
new file mode 100644
index 000000000..6873047fc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext20
@@ -0,0 +1 @@
+‹7ùô»%•kæ1 sÈÜXê—ÿI¶C{4É¿ð–©OíÖ‚5&«ÂzŽ anî%J´V}ÖŽŒÍL8¬V;cœ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext21 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext21
new file mode 100644
index 000000000..22bfbac6e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext21
@@ -0,0 +1 @@
+:Þ¦ànBÄðA‘òw^ö7Œ°ˆ$^ÜOdHâ2[`Ð4[Ÿœxße–ì"·¹çn<v³-]g'?ƒþzoÃÝ<I‘púW³¾¬a´ð©á?„F@ÄPšÓzß°® \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext22 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext22
new file mode 100644
index 000000000..a36a7f9da
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext22
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext23 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext23
new file mode 100644
index 000000000..5201604a5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext23
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext24 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext24
new file mode 100644
index 000000000..42c59ead8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext24
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext3 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext3
new file mode 100644
index 000000000..b565f3abc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext3
@@ -0,0 +1 @@
+zjô·ù‚)Þxmu¶9 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext4 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext4
new file mode 100644
index 000000000..9ef1cbb5f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext4
@@ -0,0 +1 @@
+œ-ˆBåôWd‚Óš#šñ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext5 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext5
new file mode 100644
index 000000000..767e9f430
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext5
@@ -0,0 +1,2 @@
+G0ø
+Æ%þ„ð&Æ ýT} \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext6 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext6
new file mode 100644
index 000000000..e8537b6e6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext6
@@ -0,0 +1 @@
+ $¯6<äf_(%×´tœ˜ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext7 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext7
new file mode 100644
index 000000000..b3b728441
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext7
@@ -0,0 +1 @@
+‹%Ç¿±ø½ÔÏÉöÿÅÝÇ&¡—ðå÷ ÷092y¾‘ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext8 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext8
new file mode 100644
index 000000000..32b083320
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext8
@@ -0,0 +1 @@
+šÁ™TγTÓ"`÷7?Ó6$ ýän¿í.yZn½ÄiÞÀ A‡r+„Ú¼²,è¡FWÚ  \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext9 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext9
new file mode 100644
index 000000000..ba4b4551f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext9
@@ -0,0 +1,2 @@
+*­ ,CV‹­tGFÓÚÀT4m&þݼš½‘‘@´yKâ© 
+QšQ¥µ@ôí'5H ²CN™©» `þSv7%¶(ÕsšQ·î:ï¯Å´Á¿Ddgç¿_xó÷Êñ‡ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test1.txt b/security/nss/cmd/bltest/tests/aes_cbc/test1.txt
new file mode 100644
index 000000000..1d4638023
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test1.txt
@@ -0,0 +1,5 @@
+COUNT = 0
+KEY = 00000000000000000000000000000000
+IV = 00000000000000000000000000000000
+PLAINTEXT = f34481ec3cc627bacd5dc3fb08f273e6
+CIPHERTEXT = 0336763e966d92595a567cc9ce537f5e
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test10.txt b/security/nss/cmd/bltest/tests/aes_cbc/test10.txt
new file mode 100644
index 000000000..e220c9016
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test10.txt
@@ -0,0 +1,5 @@
+COUNT = 7
+KEY = c491ca31f91708458e29a925ec558d78
+IV = 9ef934946e5cd0ae97bd58532cb49381
+PLAINTEXT = cb6a787e0dec56f9a165957f81af336ca6b40785d9e94093c6190e5152649f882e874d79ac5e167bd2a74ce5ae088d2ee854f6539e0a94796b1e1bd4c9fcdbc79acbef4d01eeb89776d18af71ae2a4fc47dd66df6c4dbe1d1850e466549a47b636bcc7c2b3a62495b56bb67b6d455f1eebd9bfefecbca6c7f335cfce9b45cb9d
+CIPHERTEXT = 7b2931f5855f717145e00f152a9f4794359b1ffcb3e55f594e33098b51c23a6c74a06c1d94fded7fd2ae42c7db7acaef5844cb33aeddc6852585ed0020a6699d2cb53809cefd169148ce42292afab063443978306c582c18b9ce0da3d084ce4d3c482cfd8fcf1a85084e89fb88b40a084d5e972466d07666126fb761f84078f2
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test11.txt b/security/nss/cmd/bltest/tests/aes_cbc/test11.txt
new file mode 100644
index 000000000..4eb4383bc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test11.txt
@@ -0,0 +1,5 @@
+COUNT = 8
+KEY = f6e87d71b0104d6eb06a68dc6a71f498
+IV = 1c245f26195b76ebebc2edcac412a2f8
+PLAINTEXT = f82bef3c73a6f7f80db285726d691db6bf55eec25a859d3ba0e0445f26b9bb3b16a3161ed1866e4dd8f2e5f8ecb4e46d74a7a78c20cdfc7bcc9e479ba7a0caba9438238ad0c01651d5d98de37f03ddce6e6b4bd4ab03cf9e8ed818aedfa1cf963b932067b97d776dce1087196e7e913f7448e38244509f0caf36bd8217e15336d35c149fd4e41707893fdb84014f8729
+CIPHERTEXT = b09512f3eff9ed0d85890983a73dadbb7c3678d52581be64a8a8fc586f490f2521297a478a0598040ebd0f5509fafb0969f9d9e600eaef33b1b93eed99687b167f89a5065aac439ce46f3b8d22d30865e64e45ef8cd30b6984353a844a11c8cd60dba0e8866b3ee30d24b3fa8a643b328353e06010fa8273c8fd54ef0a2b6930e5520aae5cd5902f9b86a33592ca4365
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test12.txt b/security/nss/cmd/bltest/tests/aes_cbc/test12.txt
new file mode 100644
index 000000000..1b2c7aab5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test12.txt
@@ -0,0 +1,5 @@
+COUNT = 9
+KEY = 2c14413751c31e2730570ba3361c786b
+IV = 1dbbeb2f19abb448af849796244a19d7
+PLAINTEXT = 40d930f9a05334d9816fe204999c3f82a03f6a0457a8c475c94553d1d116693adc618049f0a769a2eed6a6cb14c0143ec5cccdbc8dec4ce560cfd206225709326d4de7948e54d603d01b12d7fed752fb23f1aa4494fbb00130e9ded4e77e37c079042d828040c325b1a5efd15fc842e44014ca4374bf38f3c3fc3ee327733b0c8aee1abcd055772f18dc04603f7b2c1ea69ff662361f2be0a171bbdcea1e5d3f
+CIPHERTEXT = 6be8a12800455a320538853e0cba31bd2d80ea0c85164a4c5c261ae485417d93effe2ebc0d0a0b51d6ea18633d210cf63c0c4ddbc27607f2e81ed9113191ef86d56f3b99be6c415a4150299fb846ce7160b40b63baf1179d19275a2e83698376d28b92548c68e06e6d994e2c1501ed297014e702cdefee2f656447706009614d801de1caaf73f8b7fa56cf1ba94b631933bbe577624380850f117435a0355b2b
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test13.txt b/security/nss/cmd/bltest/tests/aes_cbc/test13.txt
new file mode 100644
index 000000000..344157f6c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test13.txt
@@ -0,0 +1,5 @@
+COUNT = 1
+KEY = eab3b19c581aa873e1981c83ab8d83bbf8025111fb2e6b21
+IV = f3d6667e8d4d791e60f7505ba383eb05
+PLAINTEXT = 9d4e4cccd1682321856df069e3f1c6fa391a083a9fb02d59db74c14081b3acc4
+CIPHERTEXT = 51d44779f90d40a80048276c035cb49ca2a47bcb9b9cf7270b9144793787d53f
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test14.txt b/security/nss/cmd/bltest/tests/aes_cbc/test14.txt
new file mode 100644
index 000000000..c548ceba4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test14.txt
@@ -0,0 +1,5 @@
+COUNT = 3
+KEY = 067bb17b4df785697eaccf961f98e212cb75e6797ce935cb
+IV = 8b59c9209c529ca8391c9fc0ce033c38
+PLAINTEXT = db3785a889b4bd387754da222f0e4c2d2bfe0d79e05bc910fba941beea30f1239eacf0068f4619ec01c368e986fca6b7c58e490579d29611bd10087986eff54f
+CIPHERTEXT = d5f5589760bf9c762228fde236de1fa2dd2dad448db3fa9be0c4196efd46a35c84dd1ac77d9db58c95918cb317a6430a08d2fb6a8e8b0f1c9b72c7a344dc349f
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test15.txt b/security/nss/cmd/bltest/tests/aes_cbc/test15.txt
new file mode 100644
index 000000000..71e0f1c0a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test15.txt
@@ -0,0 +1,5 @@
+COUNT = 5
+KEY = e3fecc75f0075a09b383dfd389a3d33cc9b854b3b254c0f4
+IV = 36eab883afef936cc38f63284619cd19
+PLAINTEXT = 931b2f5f3a5820d53a6beaaa6431083a3488f4eb03b0f5b57ef838e1579623103bd6e6800377538b2e51ef708f3c4956432e8a8ee6a34e190642b26ad8bdae6c2af9a6c7996f3b6004d2671e41f1c9f40ee03d1c4a52b0a0654a331f15f34dce
+CIPHERTEXT = 75395974bd32b3665654a6c8e396b88ae34b123575872a7ab687d8e76b46df911a8a590cd01d2f5c330be3a6626e9dd3aa5e10ed14e8ff829811b6fed50f3f533ca4385a1cbca78f5c4744e50f2f8359165c2485d1324e76c3eae76a0ccac629
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test16.txt b/security/nss/cmd/bltest/tests/aes_cbc/test16.txt
new file mode 100644
index 000000000..60e6e583d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test16.txt
@@ -0,0 +1,5 @@
+COUNT = 7
+KEY = fb09cf9e00dbf883689d079c920077c0073c31890b55bab5
+IV = e3c89bd097c3abddf64f4881db6dbfe2
+PLAINTEXT = c1a37683fb289467dd1b2c89efba16bbd2ee24cf18d19d44596ded2682c79a2f711c7a32bf6a24badd32a4ee637c73b7a41da6258635650f91fb9ffa45bdfc3cb122136241b3deced8996aa51ea8d3e81c9d70e006a44bc0571ed48623a0d622a93fa9da290baaedf5d9e876c94620945ff8ecc83f27379ed55cf490c5790f27
+CIPHERTEXT = 8158e21420f25b59d6ae943fa1cbf21f02e979f419dab0126a721b7eef55bee9ad97f5ccff7d239057bbc19a8c378142f7672f1d5e7e17d7bebcb0070e8355cace6660171a53b61816ae824a6ef69ce470b6ffd3b5bb4b438874d91d27854d3b6f25860d3868958de3307d62b1339bdddb8a318c0ce0f33c17caf0e9f6040820
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test17.txt b/security/nss/cmd/bltest/tests/aes_cbc/test17.txt
new file mode 100644
index 000000000..262b055c9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test17.txt
@@ -0,0 +1,5 @@
+COUNT = 8
+KEY = bca6fa3c67fd294e958f66fe8bd64f45f428f5bc8e9733a7
+IV = 92a47f2833f1450d1da41717bdc6e83c
+PLAINTEXT = 5becbc31d8bead6d36ae014a5863d14a431e6b55d29ea6baaa417271716db3a33b2e506b452086dfe690834ac2de30bc41254ec5401ec47d064237c7792fdcd7914d8af20eb114756642d519021a8c75a92f6bc53d326ae9a5b7e1b10a9756574692934d9939fc399e0c203f7edf8e7e6482eadd31a0400770e897b48c6bca2b404593045080e93377358c42a0f4dede
+CIPHERTEXT = 926db248cc1ba20f0c57631a7c8aef094f791937b905949e3460240e8bfa6fa483115a1b310b6e4369caebc5262888377b1ddaa5800ea496a2bdff0f9a1031e7129c9a20e35621e7f0b8baca0d87030f2ae7ca8593c8599677a06fd4b26009ead08fecac24caa9cf2cad3b470c8227415a7b1e0f2eab3fad96d70a209c8bb26c627677e2531b9435ca6e3c444d195b5f
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test18.txt b/security/nss/cmd/bltest/tests/aes_cbc/test18.txt
new file mode 100644
index 000000000..50a2966a2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test18.txt
@@ -0,0 +1,5 @@
+COUNT = 9
+KEY = 162ad50ee64a0702aa551f571dedc16b2c1b6a1e4d4b5eee
+IV = 24408038161a2ccae07b029bb66355c1
+PLAINTEXT = be8abf00901363987a82cc77d0ec91697ba3857f9e4f84bd79406c138d02698f003276d0449120bef4578d78fecabe8e070e11710b3f0a2744bd52434ec70015884c181ebdfd51c604a71c52e4c0e110bc408cd462b248a80b8a8ac06bb952ac1d7faed144807f1a731b7febcaf7835762defe92eccfc7a9944e1c702cffe6bc86733ed321423121085ac02df8962bcbc1937092eebf0e90a8b20e3dd8c244ae
+CIPHERTEXT = c82cf2c476dea8cb6a6e607a40d2f0391be82ea9ec84a537a6820f9afb997b76397d005424faa6a74dc4e8c7aa4a8900690f894b6d1dca80675393d2243adac762f159301e357e98b724762310cd5a7bafe1c2a030dba46fd93a9fdb89cc132ca9c17dc72031ec6822ee5a9d99dbca66c784c01b0885cbb62e29d97801927ec415a5d215158d325f9ee689437ad1b7684ad33c0d92739451ac87f39ff8c31b84
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test19.txt b/security/nss/cmd/bltest/tests/aes_cbc/test19.txt
new file mode 100644
index 000000000..a38ed0104
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test19.txt
@@ -0,0 +1,5 @@
+COUNT = 1
+KEY = dce26c6b4cfb286510da4eecd2cffe6cdf430f33db9b5f77b460679bd49d13ae
+IV = fdeaa134c8d7379d457175fd1a57d3fc
+PLAINTEXT = 50e9eee1ac528009e8cbcd356975881f957254b13f91d7c6662d10312052eb00
+CIPHERTEXT = 2fa0df722a9fd3b64cb18fb2b3db55ff2267422757289413f8f657507412a64c
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test2.txt b/security/nss/cmd/bltest/tests/aes_cbc/test2.txt
new file mode 100644
index 000000000..d9b681bb8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test2.txt
@@ -0,0 +1,5 @@
+COUNT = 1
+KEY = 00000000000000000000000000000000
+IV = 00000000000000000000000000000000
+PLAINTEXT = 9798c4640bad75c7c3227db910174e72
+CIPHERTEXT = a9a1631bf4996954ebc093957b234589
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test20.txt b/security/nss/cmd/bltest/tests/aes_cbc/test20.txt
new file mode 100644
index 000000000..a0586e1e8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test20.txt
@@ -0,0 +1,5 @@
+COUNT = 3
+KEY = 0493ff637108af6a5b8e90ac1fdf035a3d4bafd1afb573be7ade9e8682e663e5
+IV = c0cd2bebccbb6c49920bd5482ac756e8
+PLAINTEXT = 8b37f9148df4bb25956be6310c73c8dc58ea9714ff49b643107b34c9bff096a94fedd6823526abc27a8e0b16616eee254ab4567dd68e8ccd4c38ac563b13639c
+CIPHERTEXT = 05d5c77729421b08b737e41119fa4438d1f570cc772a4d6c3df7ffeda0384ef84288ce37fc4c4c7d1125a499b051364c389fd639bdda647daa3bdadab2eb5594
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test21.txt b/security/nss/cmd/bltest/tests/aes_cbc/test21.txt
new file mode 100644
index 000000000..06abcde6c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test21.txt
@@ -0,0 +1,5 @@
+COUNT = 5
+KEY = 73b8faf00b3302ac99855cf6f9e9e48518690a5906a4869d4dcf48d282faae2a
+IV = b3cb97a80a539912b8c21f450d3b9395
+PLAINTEXT = 3adea6e06e42c4f041021491f2775ef6378cb08824165edc4f6448e232175b60d0345b9f9c78df6596ec9d22b7b9e76e8f3c76b32d5d67273f1d83fe7a6fc3dd3c49139170fa5701b3beac61b490f0a9e13f844640c4500f9ad3087adfb0ae10
+CIPHERTEXT = ac3d6dbafe2e0f740632fd9e820bf6044cd5b1551cbb9cc03c0b25c39ccb7f33b83aacfca40a3265f2bbff879153448acacb88fcfb3bb7b10fe463a68c0109f028382e3e557b1adf02ed648ab6bb895df0205d26ebbfa9a5fd8cebd8e4bee3dc
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test22.txt b/security/nss/cmd/bltest/tests/aes_cbc/test22.txt
new file mode 100644
index 000000000..991068f55
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test22.txt
@@ -0,0 +1,5 @@
+COUNT = 7
+KEY = 458b67bf212d20f3a57fce392065582dcefbf381aa22949f8338ab9052260e1d
+IV = 4c12effc5963d40459602675153e9649
+PLAINTEXT = 256fd73ce35ae3ea9c25dd2a9454493e96d8633fe633b56176dce8785ce5dbbb84dbf2c8a2eeb1e96b51899605e4f13bbc11b93bf6f39b3469be14858b5b720d4a522d36feed7a329c9b1e852c9280c47db8039c17c4921571a07d1864128330e09c308ddea1694e95c84500f1a61e614197e86a30ecc28df64ccb3ccf5437aa
+CIPHERTEXT = 90b7b9630a2378f53f501ab7beff039155008071bc8438e789932cfd3eb1299195465e6633849463fdb44375278e2fdb1310821e6492cf80ff15cb772509fb426f3aeee27bd4938882fd2ae6b5bd9d91fa4a43b17bb439ebbe59c042310163a82a5fe5388796eee35a181a1271f00be29b852d8fa759bad01ff4678f010594cd
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test23.txt b/security/nss/cmd/bltest/tests/aes_cbc/test23.txt
new file mode 100644
index 000000000..aa6b7d0cf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test23.txt
@@ -0,0 +1,5 @@
+COUNT = 8
+KEY = d2412db0845d84e5732b8bbd642957473b81fb99ca8bff70e7920d16c1dbec89
+IV = 51c619fcf0b23f0c7925f400a6cacb6d
+PLAINTEXT = 026006c4a71a180c9929824d9d095b8faaa86fc4fa25ecac61d85ff6de92dfa8702688c02a282c1b8af4449707f22d75e91991015db22374c95f8f195d5bb0afeb03040ff8965e0e1339dba5653e174f8aa5a1b39fe3ac839ce307a4e44b4f8f1b0063f738ec18acdbff2ebfe07383e734558723e741f0a1836dafdf9de82210a9248bc113b3c1bc8b4e252ca01bd803
+CIPHERTEXT = 0254b23463bcabec5a395eb74c8fb0eb137a07bc6f5e9f61ec0b057de305714f8fa294221c91a159c315939b81e300ee902192ec5f15254428d8772f79324ec43298ca21c00b370273ee5e5ed90e43efa1e05a5d171209fe34f9f29237dba2a6726650fd3b1321747d1208863c6c3c6b3e2d879ab5f25782f08ba8f2abbe63e0bedb4a227e81afb36bb6645508356d34
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test24.txt b/security/nss/cmd/bltest/tests/aes_cbc/test24.txt
new file mode 100644
index 000000000..231fcd17b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test24.txt
@@ -0,0 +1,5 @@
+COUNT = 9
+KEY = 48be597e632c16772324c8d3fa1d9c5a9ecd010f14ec5d110d3bfec376c5532b
+IV = d6d581b8cf04ebd3b6eaa1b53f047ee1
+PLAINTEXT = 0c63d413d3864570e70bb6618bf8a4b9585586688c32bba0a5ecc1362fada74ada32c52acfd1aa7444ba567b4e7daaecf7cc1cb29182af164ae5232b002868695635599807a9a7f07a1f137e97b1e1c9dabc89b6a5e4afa9db5855edaa575056a8f4f8242216242bb0c256310d9d329826ac353d715fa39f80cec144d6424558f9f70b98c920096e0f2c855d594885a00625880e9dfb734163cecef72cf030b8
+CIPHERTEXT = fc5873e50de8faf4c6b84ba707b0854e9db9ab2e9f7d707fbba338c6843a18fc6facebaf663d26296fb329b4d26f18494c79e09e779647f9bafa87489630d79f4301610c2300c19dbf3148b7cac8c4f4944102754f332e92b6f7c5e75bc6179eb877a078d4719009021744c14f13fd2a55a2b9c44d18000685a845a4f632c7c56a77306efa66a24d05d088dcd7c13fe24fc447275965db9e4d37fbc9304448cd
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test3.txt b/security/nss/cmd/bltest/tests/aes_cbc/test3.txt
new file mode 100644
index 000000000..bdbc91b1e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test3.txt
@@ -0,0 +1,5 @@
+COUNT = 0
+KEY = 000000000000000000000000000000000000000000000000
+IV = 00000000000000000000000000000000
+PLAINTEXT = 1b077a6af4b7f98229de786d7516b639
+CIPHERTEXT = 275cfc0413d8ccb70513c3859b1d0f72
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test4.txt b/security/nss/cmd/bltest/tests/aes_cbc/test4.txt
new file mode 100644
index 000000000..764b0953f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test4.txt
@@ -0,0 +1,5 @@
+COUNT = 1
+KEY = 000000000000000000000000000000000000000000000000
+IV = 00000000000000000000000000000000
+PLAINTEXT = 9c2d8842e5f48f57648205d39a239af1
+CIPHERTEXT = c9b8135ff1b5adc413dfd053b21bd96d
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test5.txt b/security/nss/cmd/bltest/tests/aes_cbc/test5.txt
new file mode 100644
index 000000000..8a58240f1
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test5.txt
@@ -0,0 +1,5 @@
+COUNT = 0
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+IV = 00000000000000000000000000000000
+PLAINTEXT = 014730f80ac625fe84f026c60bfd547d
+CIPHERTEXT = 5c9d844ed46f9885085e5d6a4f94c7d7
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test6.txt b/security/nss/cmd/bltest/tests/aes_cbc/test6.txt
new file mode 100644
index 000000000..aa9748941
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test6.txt
@@ -0,0 +1,5 @@
+COUNT = 1
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+IV = 00000000000000000000000000000000
+PLAINTEXT = 0b24af36193ce4665f2825d7b4749c98
+CIPHERTEXT = a9ff75bd7cf6613d3731c77c3b6d0c04
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test7.txt b/security/nss/cmd/bltest/tests/aes_cbc/test7.txt
new file mode 100644
index 000000000..734c8c2c9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test7.txt
@@ -0,0 +1,5 @@
+COUNT = 1
+KEY = 0700d603a1c514e46b6191ba430a3a0c
+IV = aad1583cd91365e3bb2f0c3430d065bb
+PLAINTEXT = 068b25c7bfb1f8bdd4cfc908f69dffc5ddc726a197f0e5f720f730393279be91
+CIPHERTEXT = c4dc61d9725967a3020104a9738f23868527ce839aab1752fd8bdb95a82c4d00
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test8.txt b/security/nss/cmd/bltest/tests/aes_cbc/test8.txt
new file mode 100644
index 000000000..ed628c9a5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test8.txt
@@ -0,0 +1,5 @@
+COUNT = 3
+KEY = b7f3c9576e12dd0db63e8f8fac2b9a39
+IV = c80f095d8bb1a060699f7c19974a1aa0
+PLAINTEXT = 9ac19954ce1319b354d3220460f71c1e373f1cd336240881160cfde46ebfed2e791e8d5a1a136ebd1dc469dec00c4187722b841cdabcb22c1be8a14657da200e
+CIPHERTEXT = 19b9609772c63f338608bf6eb52ca10be65097f89c1e0905c42401fd47791ae2c5440b2d473116ca78bd9ff2fb6015cfd316524eae7dcb95ae738ebeae84a467
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/test9.txt b/security/nss/cmd/bltest/tests/aes_cbc/test9.txt
new file mode 100644
index 000000000..16bc6d6b6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/test9.txt
@@ -0,0 +1,5 @@
+COUNT = 5
+KEY = bbe7b7ba07124ff1ae7c3416fe8b465e
+IV = 7f65b5ee3630bed6b84202d97fb97a1e
+PLAINTEXT = 2aad0c2c4306568bad7447460fd3dac054346d26feddbc9abd9110914011b4794be2a9a00a519a51a5b5124014f4ed2735480db21b434e99a911bb0b60fe0253763725b628d5739a5117b7ee3aefafc5b4c1bf446467e7bf5f78f31ff7caf187
+CIPHERTEXT = 3b8611bfc4973c5cd8e982b073b33184cd26110159172e44988eb5ff5661a1e16fad67258fcbfee55469267a12dc374893b4e3533d36f5634c3095583596f135aa8cd1138dc898bc5651ee35a92ebf89ab6aeb5366653bc60a70e0074fc11efe
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_0.txt b/security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_0.txt
new file mode 100644
index 000000000..1e2a367d4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_0.txt
@@ -0,0 +1,28 @@
+Test="F.5.1 CTR-AES128.Encrypt"
+Type=Encrypt
+Key=2b7e151628aed2a6abf7158809cf4f3c
+Init. Counter=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Block #1={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Output Block=ec8cdf7398607cb0f2d21675ea9ea1e4
+Plaintext=6bc1bee22e409f96e93d7e117393172a
+Ciphertext=874d6191b620e3261bef6864990db6ce
+}
+Block #2={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff00
+Output Block=362b7c3c6773516318a077d7fc5073ae
+Plaintext=ae2d8a571e03ac9c9eb76fac45af8e51
+Ciphertext=9806f66b7970fdff8617187bb9fffdff
+}
+Block #3={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff01
+Output Block=6a2cc3787889374fbeb4c81b17ba6c44
+Plaintext=30c81c46a35ce411e5fbc1191a0a52ef
+Ciphertext=5ae4df3edbd5d35e5b4f09020db03eab
+}
+Block #4={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff02
+Output Block=e89c399ff0f198c6d40a31db156cabfe
+Plaintext=f69f2445df4f9b17ad2b417be66c3710
+Ciphertext=1e031dda2fbe03d1792170a0f3009cee
+}
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_1.txt b/security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_1.txt
new file mode 100644
index 000000000..d42fc1955
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_1.txt
@@ -0,0 +1,28 @@
+Test="F.5.3 CTR-AES192.Encrypt"
+Type=Encrypt
+Key=8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b
+Init. Counter=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Block #1={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Output Block=717d2dc639128334a6167a488ded7921
+Plaintext=6bc1bee22e409f96e93d7e117393172a
+Ciphertext=1abc932417521ca24f2b0459fe7e6e0b
+}
+Block #2={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff00
+Output Block=a72eb3bb14a556734b7bad6ab16100c5
+Plaintext=ae2d8a571e03ac9c9eb76fac45af8e51
+Ciphertext=090339ec0aa6faefd5ccc2c6f4ce8e94
+}
+Block #3={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff01
+Output Block=2efeae2d72b722613446dc7f4c2af918
+Plaintext=30c81c46a35ce411e5fbc1191a0a52ef
+Ciphertext=1e36b26bd1ebc670d1bd1d665620abf7
+}
+Block #4={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff02
+Output Block=b9e783b30dd7924ff7bc9b97beaa8740
+Plaintext=f69f2445df4f9b17ad2b417be66c3710
+Ciphertext=4f78a7f6d29809585a97daec58c6b050
+}
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_2.txt b/security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_2.txt
new file mode 100644
index 000000000..7db800909
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_2.txt
@@ -0,0 +1,28 @@
+Test="F.5.5 CTR-AES256.Encrypt"
+Type=Encrypt
+Key=603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4
+Init. Counter=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Block #1={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Output Block=0bdf7df1591716335e9a8b15c860c502
+Plaintext=6bc1bee22e409f96e93d7e117393172a
+Ciphertext=601ec313775789a5b7a7f504bbf3d228
+}
+Block #2={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff00
+Output Block=5a6e699d536119065433863c8f657b94
+Plaintext=ae2d8a571e03ac9c9eb76fac45af8e51
+Ciphertext=f443e3ca4d62b59aca84e990cacaf5c5
+}
+Block #3={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff01
+Output Block=1bc12c9c01610d5d0d8bd6a3378eca62
+Plaintext=30c81c46a35ce411e5fbc1191a0a52ef
+Ciphertext=2b0930daa23de94ce87017ba2d84988d
+}
+Block #4={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff02
+Output Block=2956e1c8693536b1bee99c73a31576b6
+Plaintext=f69f2445df4f9b17ad2b417be66c3710
+Ciphertext=dfc9c58db67aada613c2dd08457941a6
+}
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_tests_source.txt b/security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_tests_source.txt
new file mode 100644
index 000000000..bef853b6e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/aes_ctr_tests_source.txt
@@ -0,0 +1,199 @@
+#
+# From NIST Special Publication 800-38A; 2001 Edition ;
+# "Recommendation for Block Cipher Modes of Operation: Methods and Techniques"
+# Morris Dworkin
+# Appendix F Example Vectors for Modes of Operation of the AES
+#
+# In this appendix, three examples are provided for each of the modes in this recommendation with
+# the AES algorithm [2] as the underlying block cipher: one example is given for each of the
+# allowed key sizes (128, 192, and 256 bits). Some intermediate results are presented. For the five
+# confidentiality modes, examples are provided for both encryption and decryption. Examples are
+# provided for 1-bit, 8-bit, and 128 bit CFB. The plaintext for all but two of these examples is
+# equivalent to the following string of hexadecimal characters, formatted into four 128 bit blocks:
+#
+# 6bc1bee22e409f96e93d7e117393172a
+# ae2d8a571e03ac9c9eb76fac45af8e51
+# 30c81c46a35ce411e5fbc1191a0a52ef
+# f69f2445df4f9b17ad2b417be66c3710.
+#
+# For the example of 1-bit CFB, the plaintext is the first 16 bits in the above string; for the example
+# of 8-bit CFB, the plaintext is the first 18 octets in the above string. All strings are presented in
+# hexadecimal notation, except in the example of 1-bit CFB, where the plaintext and ciphertext
+# segments are single bits.
+#
+#
+# F.5 CTR Example Vectors
+
+Test="F.5.1 CTR-AES128.Encrypt"
+Type=Encrypt
+Key=2b7e151628aed2a6abf7158809cf4f3c
+Init. Counter=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Block #1={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Output Block=ec8cdf7398607cb0f2d21675ea9ea1e4
+Plaintext=6bc1bee22e409f96e93d7e117393172a
+Ciphertext=874d6191b620e3261bef6864990db6ce
+}
+Block #2={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff00
+Output Block=362b7c3c6773516318a077d7fc5073ae
+Plaintext=ae2d8a571e03ac9c9eb76fac45af8e51
+Ciphertext=9806f66b7970fdff8617187bb9fffdff
+}
+Block #3={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff01
+Output Block=6a2cc3787889374fbeb4c81b17ba6c44
+Plaintext=30c81c46a35ce411e5fbc1191a0a52ef
+Ciphertext=5ae4df3edbd5d35e5b4f09020db03eab
+}
+Block #4={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff02
+Output Block=e89c399ff0f198c6d40a31db156cabfe
+Plaintext=f69f2445df4f9b17ad2b417be66c3710
+Ciphertext=1e031dda2fbe03d1792170a0f3009cee
+}
+
+Test="F.5.2 CTR-AES128.Decrypt"
+Type=Decrypt
+Key=2b7e151628aed2a6abf7158809cf4f3c
+Init. Counter=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Block #1={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Output Block=ec8cdf7398607cb0f2d21675ea9ea1e4
+Ciphertext=874d6191b620e3261bef6864990db6ce
+Plaintext=6bc1bee22e409f96e93d7e117393172a
+Block #2={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff00
+Output Block=362b7c3c6773516318a077d7fc5073ae
+Ciphertext=9806f66b7970fdff8617187bb9fffdff
+Plaintext=ae2d8a571e03ac9c9eb76fac45af8e51
+}
+Block #3={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff01
+Output Block=6a2cc3787889374fbeb4c81b17ba6c44
+Ciphertext=5ae4df3edbd5d35e5b4f09020db03eab
+Plaintext=30c81c46a35ce411e5fbc1191a0a52ef
+}
+Block #4={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff02
+Output Block=e89c399ff0f198c6d40a31db156cabfe
+Ciphertext=1e031dda2fbe03d1792170a0f3009cee
+Plaintext=f69f2445df4f9b17ad2b417be66c3710
+}
+
+Test="F.5.3 CTR-AES192.Encrypt"
+Type=Encrypt
+Key=8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b
+Init. Counter=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Block #1={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Output Block=717d2dc639128334a6167a488ded7921
+Plaintext=6bc1bee22e409f96e93d7e117393172a
+Ciphertext=1abc932417521ca24f2b0459fe7e6e0b
+}
+Block #2={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff00
+Output Block=a72eb3bb14a556734b7bad6ab16100c5
+Plaintext=ae2d8a571e03ac9c9eb76fac45af8e51
+Ciphertext=090339ec0aa6faefd5ccc2c6f4ce8e94
+}
+Block #3={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff01
+Output Block=2efeae2d72b722613446dc7f4c2af918
+Plaintext=30c81c46a35ce411e5fbc1191a0a52ef
+Ciphertext=1e36b26bd1ebc670d1bd1d665620abf7
+}
+Block #4={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff02
+Output Block=b9e783b30dd7924ff7bc9b97beaa8740
+Plaintext=f69f2445df4f9b17ad2b417be66c3710
+Ciphertext=4f78a7f6d29809585a97daec58c6b050
+}
+
+Test="F.5.4 CTR-AES192.Decrypt"
+Type="Decrypt"
+Key=8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b
+Init. Counter=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Block #1={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Output Block=717d2dc639128334a6167a488ded7921
+Ciphertext=1abc932417521ca24f2b0459fe7e6e0b
+Plaintext=6bc1bee22e409f96e93d7e117393172a
+}
+Block #2={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff00
+Output Block=a72eb3bb14a556734b7bad6ab16100c5
+Ciphertext=090339ec0aa6faefd5ccc2c6f4ce8e94
+Plaintext=ae2d8a571e03ac9c9eb76fac45af8e51
+}
+Block #3
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff01
+Output Block=2efeae2d72b722613446dc7f4c2af918
+Ciphertext=1e36b26bd1ebc670d1bd1d665620abf7
+Plaintext=30c81c46a35ce411e5fbc1191a0a52ef
+}
+Block #4
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff02
+Output Block=b9e783b30dd7924ff7bc9b97beaa8740
+Ciphertext=4f78a7f6d29809585a97daec58c6b050
+Plaintext=f69f2445df4f9b17ad2b417be66c3710
+}
+
+Test="F.5.5 CTR-AES256.Encrypt"
+Type=Encrypt
+Key=603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4
+Init. Counter=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Block #1={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Output Block=0bdf7df1591716335e9a8b15c860c502
+Plaintext=6bc1bee22e409f96e93d7e117393172a
+Ciphertext=601ec313775789a5b7a7f504bbf3d228
+}
+Block #2={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff00
+Output Block=5a6e699d536119065433863c8f657b94
+Plaintext=ae2d8a571e03ac9c9eb76fac45af8e51
+Ciphertext=f443e3ca4d62b59aca84e990cacaf5c5
+}
+Block #3={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff01
+Output Block=1bc12c9c01610d5d0d8bd6a3378eca62
+Plaintext=30c81c46a35ce411e5fbc1191a0a52ef
+Ciphertext=2b0930daa23de94ce87017ba2d84988d
+}
+Block #4={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff02
+Output Block=2956e1c8693536b1bee99c73a31576b6
+Plaintext=f69f2445df4f9b17ad2b417be66c3710
+Ciphertext=dfc9c58db67aada613c2dd08457941a6
+}
+
+Test="F.5.6 CTR-AES256.Decrypt"
+Type=Decrypt
+Key=603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4
+Init. Counter=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Block #1={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+OutputBlock=0bdf7df1591716335e9a8b15c860c502
+Ciphertext=601ec313775789a5b7a7f504bbf3d228
+Plaintext=6bc1bee22e409f96e93d7e117393172a
+}
+Block #2={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff00
+OutputBlock=5a6e699d536119065433863c8f657b94
+Ciphertext=f443e3ca4d62b59aca84e990cacaf5c5
+Plaintext=ae2d8a571e03ac9c9eb76fac45af8e51
+}
+Block #3={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff01
+OutputBlock=1bc12c9c01610d5d0d8bd6a3378eca62
+Ciphertext=2b0930daa23de94ce87017ba2d84988d
+Plaintext=30c81c46a35ce411e5fbc1191a0a52ef
+}
+Block #4={
+Input Block=f0f1f2f3f4f5f6f7f8f9fafbfcfdff02
+OutputBlock=2956e1c8693536b1bee99c73a31576b6
+Ciphertext=dfc9c58db67aada613c2dd08457941a6
+Plaintext=f69f2445df4f9b17ad2b417be66c3710
+}
+
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/ciphertext0 b/security/nss/cmd/bltest/tests/aes_ctr/ciphertext0
new file mode 100644
index 000000000..a3a4ab21d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/ciphertext0
@@ -0,0 +1,2 @@
+h01hkbYg4yYb72hkmQ22zpgG9mt5cP3/hhcYe7n//f9a5N8+29XTXltPCQINsD6r
+HgMd2i++A9F5IXCg8wCc7g==
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/ciphertext1 b/security/nss/cmd/bltest/tests/aes_ctr/ciphertext1
new file mode 100644
index 000000000..60ed7007a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/ciphertext1
@@ -0,0 +1,2 @@
+GryTJBdSHKJPKwRZ/n5uCwkDOewKpvrv1czCxvTOjpQeNrJr0evGcNG9HWZWIKv3
+T3in9tKYCVhal9rsWMawUA==
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/ciphertext2 b/security/nss/cmd/bltest/tests/aes_ctr/ciphertext2
new file mode 100644
index 000000000..4c6462f6f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/ciphertext2
@@ -0,0 +1,2 @@
+YB7DE3dXiaW3p/UEu/PSKPRD48pNYrWayoTpkMrK9cUrCTDaoj3pTOhwF7othJiN
+38nFjbZ6raYTwt0IRXlBpg==
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/iv0 b/security/nss/cmd/bltest/tests/aes_ctr/iv0
new file mode 100644
index 000000000..10ae5e187
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/iv0
@@ -0,0 +1 @@
+ðñòóôõö÷øùúûüýþÿ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/iv1 b/security/nss/cmd/bltest/tests/aes_ctr/iv1
new file mode 100644
index 000000000..10ae5e187
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/iv1
@@ -0,0 +1 @@
+ðñòóôõö÷øùúûüýþÿ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/iv2 b/security/nss/cmd/bltest/tests/aes_ctr/iv2
new file mode 100644
index 000000000..10ae5e187
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/iv2
@@ -0,0 +1 @@
+ðñòóôõö÷øùúûüýþÿ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/key0 b/security/nss/cmd/bltest/tests/aes_ctr/key0
new file mode 100644
index 000000000..efb781943
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/key0
@@ -0,0 +1 @@
++~(®Ò¦«÷ˆ ÏO< \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/key1 b/security/nss/cmd/bltest/tests/aes_ctr/key1
new file mode 100644
index 000000000..06b40e45d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/key1
@@ -0,0 +1 @@
+Žs°÷ÚdRÈó+€yåbøêÒR,k{ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/key2 b/security/nss/cmd/bltest/tests/aes_ctr/key2
new file mode 100644
index 000000000..cf22d1a2d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/key2
@@ -0,0 +1 @@
+`=ëÊq¾+s®ð…}w5,;a×-˜£ ßô \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/mktst.sh b/security/nss/cmd/bltest/tests/aes_ctr/mktst.sh
new file mode 100644
index 000000000..b6f2f6f3d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/mktst.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+for i in 0 1 2
+do
+ file="aes_ctr_$i.txt"
+ grep Key $file | sed -e 's;Key=;;' | hex > key$i
+ grep "Init. Counter" $file | sed -e 's;Init. Counter=;;' | hex > iv$i
+ grep "Ciphertext" $file | sed -e 's;Ciphertext=;;' | hex | btoa > ciphertext$i
+ grep "Plaintext" $file | sed -e 's;Plaintext=;;' | hex > plaintext$i
+done
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/numtests b/security/nss/cmd/bltest/tests/aes_ctr/numtests
new file mode 100644
index 000000000..00750edc0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/numtests
@@ -0,0 +1 @@
+3
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/plaintext0 b/security/nss/cmd/bltest/tests/aes_ctr/plaintext0
new file mode 100644
index 000000000..8ad770497
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/plaintext0
@@ -0,0 +1,2 @@
+kÁ¾â.@Ÿ–é=~s“*®-ŠW¬œž·o¬E¯ŽQ0ÈF£\äåûÁ
+RïöŸ$EßO›­+A{æl7 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/plaintext1 b/security/nss/cmd/bltest/tests/aes_ctr/plaintext1
new file mode 100644
index 000000000..8ad770497
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/plaintext1
@@ -0,0 +1,2 @@
+kÁ¾â.@Ÿ–é=~s“*®-ŠW¬œž·o¬E¯ŽQ0ÈF£\äåûÁ
+RïöŸ$EßO›­+A{æl7 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ctr/plaintext2 b/security/nss/cmd/bltest/tests/aes_ctr/plaintext2
new file mode 100644
index 000000000..8ad770497
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ctr/plaintext2
@@ -0,0 +1,2 @@
+kÁ¾â.@Ÿ–é=~s“*®-ŠW¬œž·o¬E¯ŽQ0ÈF£\äåûÁ
+RïöŸ$EßO›­+A{æl7 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cts/aes-cts-type-1-vectors.txt b/security/nss/cmd/bltest/tests/aes_cts/aes-cts-type-1-vectors.txt
new file mode 100644
index 000000000..b10758676
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/aes-cts-type-1-vectors.txt
@@ -0,0 +1,47 @@
+# Raeburn Standards Track [Page 12]
+#
+# RFC 3962 AES Encryption for Kerberos 5 February 2005
+#
+# Some test vectors for CBC with ciphertext stealing, using an initial
+# vector of all-zero.
+#
+# Original Test vectors were for AES CTS-3 (Kerberos). These test vectors have been modified for AES CTS-1 (NIST)
+#
+
+Key: 63 68 69 63 6b 65 6e 20 74 65 72 69 79 61 6b 69
+IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Input: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 20
+Output: 97 c6 35 35 68 f2 bf 8c b4 d8 a5 80 36 2d a7 ff 7f
+Next IV: c6 35 35 68 f2 bf 8c b4 d8 a5 80 36 2d a7 ff 7f
+
+Key: 63 68 69 63 6b 65 6e 20 74 65 72 69 79 61 6b 69
+IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Input: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20
+Output: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 fc 00 78 3e 0e fd b2 c1 d4 45 d4 c8 ef f7 ed 22
+Next IV: fc 00 78 3e 0e fd b2 c1 d4 45 d4 c8 ef f7 ed 22
+
+Key: 63 68 69 63 6b 65 6e 20 74 65 72 69 79 61 6b 69
+IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Input: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20 43
+Output: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 84 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 a8
+Next IV: 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 a8
+
+Key: 63 68 69 63 6b 65 6e 20 74 65 72 69 79 61 6b 69
+IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Input: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20 43 68 69 63 6b 65 6e 2c 20 70 6c 65 61 73 65 2c
+Output: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 84 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 b3 ff fd 94 0c 16 a1 8c 1b 55 49 d2 f8 38 02 9e
+Next IV: b3 ff fd 94 0c 16 a1 8c 1b 55 49 d2 f8 38 02 9e
+
+Key: 63 68 69 63 6b 65 6e 20 74 65 72 69 79 61 6b 69
+IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Input: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20 43 68 69 63 6b 65 6e 2c 20 70 6c 65 61 73 65 2c 20
+Output: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 84 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 a8 9d ad 8b bb 96 c4 cd c0 3b c1 03 e1 a1 94 bb d8
+Next IV: 9d ad 8b bb 96 c4 cd c0 3b c1 03 e1 a1 94 bb d8
+
+Key: 63 68 69 63 6b 65 6e 20 74 65 72 69 79 61 6b 69
+IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Input: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20 43 68 69 63 6b 65 6e 2c 20 70 6c 65 61 73 65 2c 20 61 6e 64 20 77 6f 6e 74 6f 6e 20 73 6f 75 70 2e
+Output: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 84 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 a8 9d ad 8b bb 96 c4 cd c0 3b c1 03 e1 a1 94 bb d8 48 07 ef e8 36 ee 89 a5 26 73 0d bc 2f 7b c8 40
+Next IV: 48 07 ef e8 36 ee 89 a5 26 73 0d bc 2f 7b c8 40
+
+
diff --git a/security/nss/cmd/bltest/tests/aes_cts/aes_cts_0.txt b/security/nss/cmd/bltest/tests/aes_cts/aes_cts_0.txt
new file mode 100644
index 000000000..fa28439b3
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/aes_cts_0.txt
@@ -0,0 +1,6 @@
+Key: 63 68 69 63 6b 65 6e 20 74 65 72 69 79 61 6b 69
+IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Input: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 20
+Output: 97 c6 35 35 68 f2 bf 8c b4 d8 a5 80 36 2d a7 ff 7f
+Next IV: c6 35 35 68 f2 bf 8c b4 d8 a5 80 36 2d a7 ff 7f
+
diff --git a/security/nss/cmd/bltest/tests/aes_cts/aes_cts_1.txt b/security/nss/cmd/bltest/tests/aes_cts/aes_cts_1.txt
new file mode 100644
index 000000000..dae97358a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/aes_cts_1.txt
@@ -0,0 +1,6 @@
+Key: 63 68 69 63 6b 65 6e 20 74 65 72 69 79 61 6b 69
+IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Input: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20
+Output: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 fc 00 78 3e 0e fd b2 c1 d4 45 d4 c8 ef f7 ed 22
+Next IV: fc 00 78 3e 0e fd b2 c1 d4 45 d4 c8 ef f7 ed 22
+
diff --git a/security/nss/cmd/bltest/tests/aes_cts/aes_cts_2.txt b/security/nss/cmd/bltest/tests/aes_cts/aes_cts_2.txt
new file mode 100644
index 000000000..df892892e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/aes_cts_2.txt
@@ -0,0 +1,6 @@
+Key: 63 68 69 63 6b 65 6e 20 74 65 72 69 79 61 6b 69
+IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Input: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20 43
+Output: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 84 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 a8
+Next IV: 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 a8
+
diff --git a/security/nss/cmd/bltest/tests/aes_cts/aes_cts_3.txt b/security/nss/cmd/bltest/tests/aes_cts/aes_cts_3.txt
new file mode 100644
index 000000000..11e68e0c8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/aes_cts_3.txt
@@ -0,0 +1,6 @@
+Key: 63 68 69 63 6b 65 6e 20 74 65 72 69 79 61 6b 69
+IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Input: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20 43 68 69 63 6b 65 6e 2c 20 70 6c 65 61 73 65 2c
+Output: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 84 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 b3 ff fd 94 0c 16 a1 8c 1b 55 49 d2 f8 38 02 9e
+Next IV: b3 ff fd 94 0c 16 a1 8c 1b 55 49 d2 f8 38 02 9e
+
diff --git a/security/nss/cmd/bltest/tests/aes_cts/aes_cts_4.txt b/security/nss/cmd/bltest/tests/aes_cts/aes_cts_4.txt
new file mode 100644
index 000000000..b5dc5ae3f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/aes_cts_4.txt
@@ -0,0 +1,6 @@
+Key: 63 68 69 63 6b 65 6e 20 74 65 72 69 79 61 6b 69
+IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Input: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20 43 68 69 63 6b 65 6e 2c 20 70 6c 65 61 73 65 2c 20
+Output: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 84 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 a8 9d ad 8b bb 96 c4 cd c0 3b c1 03 e1 a1 94 bb d8
+Next IV: 9d ad 8b bb 96 c4 cd c0 3b c1 03 e1 a1 94 bb d8
+
diff --git a/security/nss/cmd/bltest/tests/aes_cts/aes_cts_5.txt b/security/nss/cmd/bltest/tests/aes_cts/aes_cts_5.txt
new file mode 100644
index 000000000..db837f927
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/aes_cts_5.txt
@@ -0,0 +1,6 @@
+Key: 63 68 69 63 6b 65 6e 20 74 65 72 69 79 61 6b 69
+IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Input: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20 43 68 69 63 6b 65 6e 2c 20 70 6c 65 61 73 65 2c 20 61 6e 64 20 77 6f 6e 74 6f 6e 20 73 6f 75 70 2e
+Output: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 84 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 a8 9d ad 8b bb 96 c4 cd c0 3b c1 03 e1 a1 94 bb d8 48 07 ef e8 36 ee 89 a5 26 73 0d bc 2f 7b c8 40
+Next IV: 48 07 ef e8 36 ee 89 a5 26 73 0d bc 2f 7b c8 40
+
diff --git a/security/nss/cmd/bltest/tests/aes_cts/ciphertext0 b/security/nss/cmd/bltest/tests/aes_cts/ciphertext0
new file mode 100644
index 000000000..bcfdc10da
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/ciphertext0
@@ -0,0 +1 @@
+l8Y1NWjyv4y02KWANi2n/38=
diff --git a/security/nss/cmd/bltest/tests/aes_cts/ciphertext1 b/security/nss/cmd/bltest/tests/aes_cts/ciphertext1
new file mode 100644
index 000000000..66560807c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/ciphertext1
@@ -0,0 +1 @@
+l2hyaNbszMDAeyXiXs/l/AB4Pg79ssHURdTI7/ftIg==
diff --git a/security/nss/cmd/bltest/tests/aes_cts/ciphertext2 b/security/nss/cmd/bltest/tests/aes_cts/ciphertext2
new file mode 100644
index 000000000..336d705c9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/ciphertext2
@@ -0,0 +1 @@
+l2hyaNbszMDAeyXiXs/lhDkxJSOnhmLVvn/LzJjr9ag=
diff --git a/security/nss/cmd/bltest/tests/aes_cts/ciphertext3 b/security/nss/cmd/bltest/tests/aes_cts/ciphertext3
new file mode 100644
index 000000000..7c53d4002
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/ciphertext3
@@ -0,0 +1 @@
+l2hyaNbszMDAeyXiXs/lhDkxJSOnhmLVvn/LzJjr9bP//ZQMFqGMG1VJ0vg4Ap4=
diff --git a/security/nss/cmd/bltest/tests/aes_cts/ciphertext4 b/security/nss/cmd/bltest/tests/aes_cts/ciphertext4
new file mode 100644
index 000000000..ef31331c8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/ciphertext4
@@ -0,0 +1 @@
+l2hyaNbszMDAeyXiXs/lhDkxJSOnhmLVvn/LzJjr9aidrYu7lsTNwDvBA+GhlLvY
diff --git a/security/nss/cmd/bltest/tests/aes_cts/ciphertext5 b/security/nss/cmd/bltest/tests/aes_cts/ciphertext5
new file mode 100644
index 000000000..0ead14337
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/ciphertext5
@@ -0,0 +1,2 @@
+l2hyaNbszMDAeyXiXs/lhDkxJSOnhmLVvn/LzJjr9aidrYu7lsTNwDvBA+GhlLvY
+SAfv6DbuiaUmcw28L3vIQA==
diff --git a/security/nss/cmd/bltest/tests/aes_cts/iv0 b/security/nss/cmd/bltest/tests/aes_cts/iv0
new file mode 100644
index 000000000..4bdfab833
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/iv0
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cts/iv1 b/security/nss/cmd/bltest/tests/aes_cts/iv1
new file mode 100644
index 000000000..3e8c8e9e6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/iv1
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cts/iv2 b/security/nss/cmd/bltest/tests/aes_cts/iv2
new file mode 100644
index 000000000..b4bbc2e76
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/iv2
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cts/iv3 b/security/nss/cmd/bltest/tests/aes_cts/iv3
new file mode 100644
index 000000000..c065e8362
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/iv3
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cts/iv4 b/security/nss/cmd/bltest/tests/aes_cts/iv4
new file mode 100644
index 000000000..ba11a0ec0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/iv4
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cts/iv5 b/security/nss/cmd/bltest/tests/aes_cts/iv5
new file mode 100644
index 000000000..213a4bd3c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/iv5
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_cts/key0 b/security/nss/cmd/bltest/tests/aes_cts/key0
new file mode 100644
index 000000000..8ec57e84c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/key0
@@ -0,0 +1 @@
+chicken teriyaki \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cts/key1 b/security/nss/cmd/bltest/tests/aes_cts/key1
new file mode 100644
index 000000000..8ec57e84c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/key1
@@ -0,0 +1 @@
+chicken teriyaki \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cts/key2 b/security/nss/cmd/bltest/tests/aes_cts/key2
new file mode 100644
index 000000000..8ec57e84c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/key2
@@ -0,0 +1 @@
+chicken teriyaki \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cts/key3 b/security/nss/cmd/bltest/tests/aes_cts/key3
new file mode 100644
index 000000000..8ec57e84c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/key3
@@ -0,0 +1 @@
+chicken teriyaki \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cts/key4 b/security/nss/cmd/bltest/tests/aes_cts/key4
new file mode 100644
index 000000000..8ec57e84c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/key4
@@ -0,0 +1 @@
+chicken teriyaki \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cts/key5 b/security/nss/cmd/bltest/tests/aes_cts/key5
new file mode 100644
index 000000000..8ec57e84c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/key5
@@ -0,0 +1 @@
+chicken teriyaki \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cts/mktst.sh b/security/nss/cmd/bltest/tests/aes_cts/mktst.sh
new file mode 100644
index 000000000..58b628d8d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/mktst.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+for i in 0 1 2 3 4 5
+do
+ file="aes_cts_$i.txt"
+ grep "Key" $file | sed -e 's;Key:;;' | hex > key$i
+ grep "IV" $file | sed -e 's;IV:;;' | hex > iv$i
+ grep "Input" $file | sed -e 's;Input:;;' | hex > plaintext$i
+ grep "Output" $file | sed -e 's;Output:;;' | hex | btoa > ciphertext$i
+done
diff --git a/security/nss/cmd/bltest/tests/aes_cts/numtests b/security/nss/cmd/bltest/tests/aes_cts/numtests
new file mode 100644
index 000000000..1e8b31496
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/numtests
@@ -0,0 +1 @@
+6
diff --git a/security/nss/cmd/bltest/tests/aes_cts/plaintext0 b/security/nss/cmd/bltest/tests/aes_cts/plaintext0
new file mode 100644
index 000000000..3f35c974a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/plaintext0
@@ -0,0 +1 @@
+I would like the \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cts/plaintext1 b/security/nss/cmd/bltest/tests/aes_cts/plaintext1
new file mode 100644
index 000000000..397544871
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/plaintext1
@@ -0,0 +1 @@
+I would like the General Gau's \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cts/plaintext2 b/security/nss/cmd/bltest/tests/aes_cts/plaintext2
new file mode 100644
index 000000000..d0664ea0d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/plaintext2
@@ -0,0 +1 @@
+I would like the General Gau's C \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cts/plaintext3 b/security/nss/cmd/bltest/tests/aes_cts/plaintext3
new file mode 100644
index 000000000..563970bfa
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/plaintext3
@@ -0,0 +1 @@
+I would like the General Gau's Chicken, please, \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cts/plaintext4 b/security/nss/cmd/bltest/tests/aes_cts/plaintext4
new file mode 100644
index 000000000..b908471e3
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/plaintext4
@@ -0,0 +1 @@
+I would like the General Gau's Chicken, please, \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_cts/plaintext5 b/security/nss/cmd/bltest/tests/aes_cts/plaintext5
new file mode 100644
index 000000000..5e4c06947
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cts/plaintext5
@@ -0,0 +1 @@
+I would like the General Gau's Chicken, please, and wonton soup. \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/ciphertext0 b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext0
new file mode 100644
index 000000000..d6818c1d0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext0
@@ -0,0 +1 @@
+PVuaCIiaKQhblgFCbVMTTg==
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/ciphertext1 b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext1
new file mode 100644
index 000000000..1126bbf38
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext1
@@ -0,0 +1 @@
+AzZ2PpZtkllaVnzJzlN/Xg==
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/ciphertext2 b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext2
new file mode 100644
index 000000000..ec069abd4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext2
@@ -0,0 +1 @@
+qaFjG/SZaVTrwJOVeyNFiQ==
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/ciphertext3 b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext3
new file mode 100644
index 000000000..82c4cd202
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext3
@@ -0,0 +1 @@
+J1z8BBPYzLcFE8OFmx0Pcg==
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/ciphertext4 b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext4
new file mode 100644
index 000000000..81714bd4d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext4
@@ -0,0 +1 @@
+ybgTX/G1rcQT39BTshvZbQ==
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/ciphertext5 b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext5
new file mode 100644
index 000000000..ce9672a51
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext5
@@ -0,0 +1 @@
+XJ2ETtRvmIUIXl1qT5TH1w==
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/ciphertext6 b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext6
new file mode 100644
index 000000000..fc53a4f55
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext6
@@ -0,0 +1 @@
+qf91vXz2YT03Mcd8O20MBA==
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/key0 b/security/nss/cmd/bltest/tests/aes_ecb/key0
new file mode 100644
index 000000000..13911cc29
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/key0
@@ -0,0 +1 @@
+fedcba9876543210
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/key1 b/security/nss/cmd/bltest/tests/aes_ecb/key1
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/key1
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/key2 b/security/nss/cmd/bltest/tests/aes_ecb/key2
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/key2
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/key3 b/security/nss/cmd/bltest/tests/aes_ecb/key3
new file mode 100644
index 000000000..4ac5fc6cf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/key3
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/key4 b/security/nss/cmd/bltest/tests/aes_ecb/key4
new file mode 100644
index 000000000..4ac5fc6cf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/key4
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/key5 b/security/nss/cmd/bltest/tests/aes_ecb/key5
new file mode 100644
index 000000000..4e4e49357
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/key5
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/key6 b/security/nss/cmd/bltest/tests/aes_ecb/key6
new file mode 100644
index 000000000..4e4e49357
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/key6
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/mktst.sh b/security/nss/cmd/bltest/tests/aes_ecb/mktst.sh
new file mode 100644
index 000000000..6d46509f0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/mktst.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+for i in 1 2 3 4 5 6
+do
+ file="test$i.txt"
+ grep "KEY = " $file | sed -e 's;KEY = ;;' | hex > key$i
+ grep "PLAINTEXT = " $file | sed -e 's;PLAINTEXT = ;;' | hex > plaintext$i
+ grep "CIPHERTEXT = " $file | sed -e 's;CIPHERTEXT = ;;' | hex > ciphertext$i.bin
+ btoa < ciphertext$i.bin > ciphertext$i
+ rm ciphertext$i.bin
+done
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/numtests b/security/nss/cmd/bltest/tests/aes_ecb/numtests
new file mode 100644
index 000000000..7f8f011eb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/numtests
@@ -0,0 +1 @@
+7
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/plaintext0 b/security/nss/cmd/bltest/tests/aes_ecb/plaintext0
new file mode 100644
index 000000000..8d6a8d555
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/plaintext0
@@ -0,0 +1 @@
+0123456789abcdef
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/plaintext1 b/security/nss/cmd/bltest/tests/aes_ecb/plaintext1
new file mode 100644
index 000000000..8bac1b756
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/plaintext1
@@ -0,0 +1 @@
+óDì<Æ'ºÍ]Ãûòsæ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/plaintext2 b/security/nss/cmd/bltest/tests/aes_ecb/plaintext2
new file mode 100644
index 000000000..b2153e2ad
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/plaintext2
@@ -0,0 +1 @@
+—˜Äd ­uÇÃ"}¹Nr \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/plaintext3 b/security/nss/cmd/bltest/tests/aes_ecb/plaintext3
new file mode 100644
index 000000000..b565f3abc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/plaintext3
@@ -0,0 +1 @@
+zjô·ù‚)Þxmu¶9 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/plaintext4 b/security/nss/cmd/bltest/tests/aes_ecb/plaintext4
new file mode 100644
index 000000000..9ef1cbb5f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/plaintext4
@@ -0,0 +1 @@
+œ-ˆBåôWd‚Óš#šñ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/plaintext5 b/security/nss/cmd/bltest/tests/aes_ecb/plaintext5
new file mode 100644
index 000000000..767e9f430
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/plaintext5
@@ -0,0 +1,2 @@
+G0ø
+Æ%þ„ð&Æ ýT} \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/plaintext6 b/security/nss/cmd/bltest/tests/aes_ecb/plaintext6
new file mode 100644
index 000000000..e8537b6e6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/plaintext6
@@ -0,0 +1 @@
+ $¯6<äf_(%×´tœ˜ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/test1.txt b/security/nss/cmd/bltest/tests/aes_ecb/test1.txt
new file mode 100644
index 000000000..96a2adb9c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/test1.txt
@@ -0,0 +1,4 @@
+COUNT = 0
+KEY = 00000000000000000000000000000000
+PLAINTEXT = f34481ec3cc627bacd5dc3fb08f273e6
+CIPHERTEXT = 0336763e966d92595a567cc9ce537f5e
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/test2.txt b/security/nss/cmd/bltest/tests/aes_ecb/test2.txt
new file mode 100644
index 000000000..a01daaef3
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/test2.txt
@@ -0,0 +1,4 @@
+COUNT = 1
+KEY = 00000000000000000000000000000000
+PLAINTEXT = 9798c4640bad75c7c3227db910174e72
+CIPHERTEXT = a9a1631bf4996954ebc093957b234589
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/test3.txt b/security/nss/cmd/bltest/tests/aes_ecb/test3.txt
new file mode 100644
index 000000000..803c23c81
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/test3.txt
@@ -0,0 +1,4 @@
+COUNT = 0
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = 1b077a6af4b7f98229de786d7516b639
+CIPHERTEXT = 275cfc0413d8ccb70513c3859b1d0f72
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/test4.txt b/security/nss/cmd/bltest/tests/aes_ecb/test4.txt
new file mode 100644
index 000000000..e567fab64
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/test4.txt
@@ -0,0 +1,4 @@
+COUNT = 1
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = 9c2d8842e5f48f57648205d39a239af1
+CIPHERTEXT = c9b8135ff1b5adc413dfd053b21bd96d
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/test5.txt b/security/nss/cmd/bltest/tests/aes_ecb/test5.txt
new file mode 100644
index 000000000..c96940e2c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/test5.txt
@@ -0,0 +1,4 @@
+COUNT = 0
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 014730f80ac625fe84f026c60bfd547d
+CIPHERTEXT = 5c9d844ed46f9885085e5d6a4f94c7d7
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/test6.txt b/security/nss/cmd/bltest/tests/aes_ecb/test6.txt
new file mode 100644
index 000000000..d8d00582a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/test6.txt
@@ -0,0 +1,4 @@
+COUNT = 1
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 0b24af36193ce4665f2825d7b4749c98
+CIPHERTEXT = a9ff75bd7cf6613d3731c77c3b6d0c04
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad0 b/security/nss/cmd/bltest/tests/aes_gcm/aad0
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad0
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad1 b/security/nss/cmd/bltest/tests/aes_gcm/aad1
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad1
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad10 b/security/nss/cmd/bltest/tests/aes_gcm/aad10
new file mode 100644
index 000000000..87b29d32c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad10
@@ -0,0 +1 @@
+þíúÎÞ­¾ïþíúÎÞ­¾ï«­ÚÒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad11 b/security/nss/cmd/bltest/tests/aes_gcm/aad11
new file mode 100644
index 000000000..87b29d32c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad11
@@ -0,0 +1 @@
+þíúÎÞ­¾ïþíúÎÞ­¾ï«­ÚÒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad12 b/security/nss/cmd/bltest/tests/aes_gcm/aad12
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad12
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad13 b/security/nss/cmd/bltest/tests/aes_gcm/aad13
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad13
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad14 b/security/nss/cmd/bltest/tests/aes_gcm/aad14
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad14
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad15 b/security/nss/cmd/bltest/tests/aes_gcm/aad15
new file mode 100644
index 000000000..87b29d32c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad15
@@ -0,0 +1 @@
+þíúÎÞ­¾ïþíúÎÞ­¾ï«­ÚÒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad16 b/security/nss/cmd/bltest/tests/aes_gcm/aad16
new file mode 100644
index 000000000..87b29d32c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad16
@@ -0,0 +1 @@
+þíúÎÞ­¾ïþíúÎÞ­¾ï«­ÚÒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad17 b/security/nss/cmd/bltest/tests/aes_gcm/aad17
new file mode 100644
index 000000000..87b29d32c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad17
@@ -0,0 +1 @@
+þíúÎÞ­¾ïþíúÎÞ­¾ï«­ÚÒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad2 b/security/nss/cmd/bltest/tests/aes_gcm/aad2
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad2
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad3 b/security/nss/cmd/bltest/tests/aes_gcm/aad3
new file mode 100644
index 000000000..87b29d32c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad3
@@ -0,0 +1 @@
+þíúÎÞ­¾ïþíúÎÞ­¾ï«­ÚÒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad4 b/security/nss/cmd/bltest/tests/aes_gcm/aad4
new file mode 100644
index 000000000..87b29d32c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad4
@@ -0,0 +1 @@
+þíúÎÞ­¾ïþíúÎÞ­¾ï«­ÚÒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad5 b/security/nss/cmd/bltest/tests/aes_gcm/aad5
new file mode 100644
index 000000000..87b29d32c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad5
@@ -0,0 +1 @@
+þíúÎÞ­¾ïþíúÎÞ­¾ï«­ÚÒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad6 b/security/nss/cmd/bltest/tests/aes_gcm/aad6
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad6
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad7 b/security/nss/cmd/bltest/tests/aes_gcm/aad7
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad7
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad8 b/security/nss/cmd/bltest/tests/aes_gcm/aad8
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad8
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/aad9 b/security/nss/cmd/bltest/tests/aes_gcm/aad9
new file mode 100644
index 000000000..87b29d32c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/aad9
@@ -0,0 +1 @@
+þíúÎÞ­¾ïþíúÎÞ­¾ï«­ÚÒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext0 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext0
new file mode 100644
index 000000000..3b352147b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext0
@@ -0,0 +1 @@
+WOL8zvp+MGE2fx1XpOdFWg==
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext1 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext1
new file mode 100644
index 000000000..9913ff1fa
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext1
@@ -0,0 +1 @@
+A4jazmC2o5LzKMK5cbL+eKtuR9Qs7BO99TpnshJXvd8=
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext10 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext10
new file mode 100644
index 000000000..70cb47100
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext10
@@ -0,0 +1,2 @@
+DxD1ma4UoVTtJLNuJTJNuMVmYy7yu7NPg0coD8RQcFf93CnfmkcfdcZlQdTU2tHJ
+6ToZpY6LRz+g8GL3ZdzFf89iOiQJT8ykDTUz+A==
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext11 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext11
new file mode 100644
index 000000000..b9c42364e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext11
@@ -0,0 +1,2 @@
+0n6IaBzjJDxIMBZaj9z5/x3podjmtEfvbve3mChmbkWB55ASrzTd2eLwN1ibKS2z
+5nwDZ0X6Iufptzc73PVm/ykcJbu4Vo/D03am2Q==
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext12 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext12
new file mode 100644
index 000000000..b756f5c56
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext12
@@ -0,0 +1 @@
+Uw+K+8dFNrmpY7TxxMtziw==
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext13 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext13
new file mode 100644
index 000000000..15bc5e17f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext13
@@ -0,0 +1 @@
+zqdAPU1ga24HTsXTuvOdGNDRyKeZmWvwJluYtdSKuRk=
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext14 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext14
new file mode 100644
index 000000000..a982ef2fe
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext14
@@ -0,0 +1,2 @@
+Ui3B8JlWfQf0fzejKoRCfWQ6jNy/5cDJdZiivSVV0aqMsI5IWQ27PaewixBWgog4
+xfYeY5O6egq8yfZiiYAVrbCU2sXZNHG97BpQInDjzGw=
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext15 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext15
new file mode 100644
index 000000000..5f5b95261
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext15
@@ -0,0 +1,2 @@
+Ui3B8JlWfQf0fzejKoRCfWQ6jNy/5cDJdZiivSVV0aqMsI5IWQ27PaewixBWgog4
+xfYeY5O6egq8yfZidvxuzg9OF2jN34hTuy1VGw==
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext16 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext16
new file mode 100644
index 000000000..86d9096bd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext16
@@ -0,0 +1,2 @@
+w3Yt8cp4fTKuR8E78ZhEy68a4U0Ll2r6xS/315u6neD+tYLTOTSk8JVMwjY7xz94
+YqxDDmSr5Jn0fJsfOjN9v0anksReRUkT/i6o8g==
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext17 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext17
new file mode 100644
index 000000000..6be2346bf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext17
@@ -0,0 +1,2 @@
+Wo3vLwyeU/H3XXhTZZ4qIO6ysiqv3mQZoFirT290a/QPwMO3gPJERS2j6/HF2Cze
+okGJlyAO+C5Ern4/pEqCZu4cjrDItdTPWunxmg==
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext2 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext2
new file mode 100644
index 000000000..f5efb3d52
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext2
@@ -0,0 +1,2 @@
+QoMewiF3dCRLciG3hNDUnOOqIS8sAqTgNcF+IymsoS4h1RSyVGaTHH2PalqshKoF
+G6MLOWoKrJc9WOCRRz9ZhU1cKvMnzWSmLPNavSum+rQ=
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext3 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext3
new file mode 100644
index 000000000..80fe95e85
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext3
@@ -0,0 +1,2 @@
+QoMewiF3dCRLciG3hNDUnOOqIS8sAqTgNcF+IymsoS4h1RSyVGaTHH2PalqshKoF
+G6MLOWoKrJc9WOCRW8lPvDIhpduU+ula5xIaRw==
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext4 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext4
new file mode 100644
index 000000000..cbc0194aa
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext4
@@ -0,0 +1,2 @@
+YTU7TCgGk0p3f/UfoipHVWmbKnFPzcb4N2bl+XtsdCNzgGkA5J8ksisJdUTUiWtC
+SYm14eusDwfCP0WYNhLS5547B4VWG+FKrKL8yw==
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext5 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext5
new file mode 100644
index 000000000..77127ff0e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext5
@@ -0,0 +1,2 @@
+jOJJmGJWFbYDoDOsoT+4lL6REqXDohGouiYqPMp+LKcB5Kmk+6Q8kMzcsoHUjHxv
+1ih10qykFwNMNK7lYZzFrv/+C/pGKvQ8FpnQUA==
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext6 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext6
new file mode 100644
index 000000000..dc07bfd3f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext6
@@ -0,0 +1 @@
+zTOyisdz90ugDtHzElckNQ==
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext7 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext7
new file mode 100644
index 000000000..d405c82fe
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext7
@@ -0,0 +1 @@
+mOckfAfw/kEcJn5DhLD2AC/1jYADOSerjvTUWHUU8Ps=
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext8 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext8
new file mode 100644
index 000000000..53738bbef
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext8
@@ -0,0 +1,2 @@
+OYDKCzwA6EHrBvrEhyonV4WeHOqm79mEYoWTtAyh4Zx9dz0AwUTFJaxhnRjISj9H
+GOJEiy/jJNnM2icQrK3iVpkkp8hYcza/sRgCTbhnShQ=
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/ciphertext9 b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext9
new file mode 100644
index 000000000..bde2785bc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/ciphertext9
@@ -0,0 +1,2 @@
+OYDKCzwA6EHrBvrEhyonV4WeHOqm79mEYoWTtAyh4Zx9dz0AwUTFJaxhnRjISj9H
+GOJEiy/jJNnM2icQJRlJjoDxR483ulW9bSdhjA==
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/hex.c b/security/nss/cmd/bltest/tests/aes_gcm/hex.c
new file mode 100644
index 000000000..cdf583da2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/hex.c
@@ -0,0 +1,78 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+tohex(int c)
+{
+ if ((c >= '0') && (c <= '9')) {
+ return c - '0';
+ }
+ if ((c >= 'a') && (c <= 'f')) {
+ return c - 'a' + 10;
+ }
+ if ((c >= 'A') && (c <= 'F')) {
+ return c - 'A' + 10;
+ }
+ return 0;
+}
+
+int
+isspace(int c)
+{
+ if (c <= ' ')
+ return 1;
+ if (c == '\n')
+ return 1;
+ if (c == '\t')
+ return 1;
+ if (c == ':')
+ return 1;
+ if (c == ';')
+ return 1;
+ if (c == ',')
+ return 1;
+ return 0;
+}
+
+void
+verify_nibble(int nibble, int current)
+{
+ if (nibble != 0) {
+ fprintf(stderr, "count mismatch %d (nibbles=0x%x)\n", nibble, current);
+ fflush(stderr);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ int current = 0;
+ int nibble = 0;
+ int skip = 0;
+
+ if (argv[1]) {
+ skip = atoi(argv[1]);
+ }
+
+#define NIBBLE_COUNT 2
+ while ((c = getchar()) != EOF) {
+ if (isspace(c)) {
+ verify_nibble(nibble, current);
+ continue;
+ }
+ if (skip) {
+ skip--;
+ continue;
+ }
+ current = current << 4 | tohex(c);
+ nibble++;
+ if (nibble == NIBBLE_COUNT) {
+ putchar(current);
+ nibble = 0;
+ current = 0;
+ }
+ }
+ return 0;
+}
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv0 b/security/nss/cmd/bltest/tests/aes_gcm/iv0
new file mode 100644
index 000000000..ce58bc9f8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv0
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv1 b/security/nss/cmd/bltest/tests/aes_gcm/iv1
new file mode 100644
index 000000000..ce58bc9f8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv1
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv10 b/security/nss/cmd/bltest/tests/aes_gcm/iv10
new file mode 100644
index 000000000..bad60b08b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv10
@@ -0,0 +1 @@
+Êþº¾úÎÛ­ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv11 b/security/nss/cmd/bltest/tests/aes_gcm/iv11
new file mode 100644
index 000000000..f446641db
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv11
@@ -0,0 +1 @@
+“"]ø„åUœZÿRiªjz•8SO}¡äÃÒ£§(ÃÀÉQV€•9üðâBškRT®Ûõ ÞjW¦7³› \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv12 b/security/nss/cmd/bltest/tests/aes_gcm/iv12
new file mode 100644
index 000000000..ce58bc9f8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv12
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv13 b/security/nss/cmd/bltest/tests/aes_gcm/iv13
new file mode 100644
index 000000000..ce58bc9f8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv13
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv14 b/security/nss/cmd/bltest/tests/aes_gcm/iv14
new file mode 100644
index 000000000..e3728f726
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv14
@@ -0,0 +1 @@
+Êþº¾úÎÛ­ÞÊøˆ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv15 b/security/nss/cmd/bltest/tests/aes_gcm/iv15
new file mode 100644
index 000000000..e3728f726
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv15
@@ -0,0 +1 @@
+Êþº¾úÎÛ­ÞÊøˆ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv16 b/security/nss/cmd/bltest/tests/aes_gcm/iv16
new file mode 100644
index 000000000..bad60b08b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv16
@@ -0,0 +1 @@
+Êþº¾úÎÛ­ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv17 b/security/nss/cmd/bltest/tests/aes_gcm/iv17
new file mode 100644
index 000000000..f446641db
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv17
@@ -0,0 +1 @@
+“"]ø„åUœZÿRiªjz•8SO}¡äÃÒ£§(ÃÀÉQV€•9üðâBškRT®Ûõ ÞjW¦7³› \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv2 b/security/nss/cmd/bltest/tests/aes_gcm/iv2
new file mode 100644
index 000000000..e3728f726
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv2
@@ -0,0 +1 @@
+Êþº¾úÎÛ­ÞÊøˆ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv3 b/security/nss/cmd/bltest/tests/aes_gcm/iv3
new file mode 100644
index 000000000..e3728f726
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv3
@@ -0,0 +1 @@
+Êþº¾úÎÛ­ÞÊøˆ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv4 b/security/nss/cmd/bltest/tests/aes_gcm/iv4
new file mode 100644
index 000000000..bad60b08b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv4
@@ -0,0 +1 @@
+Êþº¾úÎÛ­ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv5 b/security/nss/cmd/bltest/tests/aes_gcm/iv5
new file mode 100644
index 000000000..f446641db
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv5
@@ -0,0 +1 @@
+“"]ø„åUœZÿRiªjz•8SO}¡äÃÒ£§(ÃÀÉQV€•9üðâBškRT®Ûõ ÞjW¦7³› \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv6 b/security/nss/cmd/bltest/tests/aes_gcm/iv6
new file mode 100644
index 000000000..ce58bc9f8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv6
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv7 b/security/nss/cmd/bltest/tests/aes_gcm/iv7
new file mode 100644
index 000000000..ce58bc9f8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv7
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv8 b/security/nss/cmd/bltest/tests/aes_gcm/iv8
new file mode 100644
index 000000000..e3728f726
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv8
@@ -0,0 +1 @@
+Êþº¾úÎÛ­ÞÊøˆ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/iv9 b/security/nss/cmd/bltest/tests/aes_gcm/iv9
new file mode 100644
index 000000000..e3728f726
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/iv9
@@ -0,0 +1 @@
+Êþº¾úÎÛ­ÞÊøˆ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key0 b/security/nss/cmd/bltest/tests/aes_gcm/key0
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key0
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key1 b/security/nss/cmd/bltest/tests/aes_gcm/key1
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key1
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key10 b/security/nss/cmd/bltest/tests/aes_gcm/key10
new file mode 100644
index 000000000..222b4b5a2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key10
@@ -0,0 +1 @@
+þÿé’†esmj”g0ƒþÿé’†es \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key11 b/security/nss/cmd/bltest/tests/aes_gcm/key11
new file mode 100644
index 000000000..222b4b5a2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key11
@@ -0,0 +1 @@
+þÿé’†esmj”g0ƒþÿé’†es \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key12 b/security/nss/cmd/bltest/tests/aes_gcm/key12
new file mode 100644
index 000000000..4e4e49357
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key12
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key13 b/security/nss/cmd/bltest/tests/aes_gcm/key13
new file mode 100644
index 000000000..4e4e49357
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key13
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key14 b/security/nss/cmd/bltest/tests/aes_gcm/key14
new file mode 100644
index 000000000..2163baf5a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key14
@@ -0,0 +1 @@
+þÿé’†esmj”g0ƒþÿé’†esmj”g0ƒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key15 b/security/nss/cmd/bltest/tests/aes_gcm/key15
new file mode 100644
index 000000000..2163baf5a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key15
@@ -0,0 +1 @@
+þÿé’†esmj”g0ƒþÿé’†esmj”g0ƒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key16 b/security/nss/cmd/bltest/tests/aes_gcm/key16
new file mode 100644
index 000000000..2163baf5a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key16
@@ -0,0 +1 @@
+þÿé’†esmj”g0ƒþÿé’†esmj”g0ƒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key17 b/security/nss/cmd/bltest/tests/aes_gcm/key17
new file mode 100644
index 000000000..2163baf5a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key17
@@ -0,0 +1 @@
+þÿé’†esmj”g0ƒþÿé’†esmj”g0ƒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key2 b/security/nss/cmd/bltest/tests/aes_gcm/key2
new file mode 100644
index 000000000..767ebdace
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key2
@@ -0,0 +1 @@
+þÿé’†esmj”g0ƒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key3 b/security/nss/cmd/bltest/tests/aes_gcm/key3
new file mode 100644
index 000000000..767ebdace
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key3
@@ -0,0 +1 @@
+þÿé’†esmj”g0ƒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key4 b/security/nss/cmd/bltest/tests/aes_gcm/key4
new file mode 100644
index 000000000..767ebdace
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key4
@@ -0,0 +1 @@
+þÿé’†esmj”g0ƒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key5 b/security/nss/cmd/bltest/tests/aes_gcm/key5
new file mode 100644
index 000000000..767ebdace
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key5
@@ -0,0 +1 @@
+þÿé’†esmj”g0ƒ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key6 b/security/nss/cmd/bltest/tests/aes_gcm/key6
new file mode 100644
index 000000000..4ac5fc6cf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key6
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key7 b/security/nss/cmd/bltest/tests/aes_gcm/key7
new file mode 100644
index 000000000..4ac5fc6cf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key7
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key8 b/security/nss/cmd/bltest/tests/aes_gcm/key8
new file mode 100644
index 000000000..222b4b5a2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key8
@@ -0,0 +1 @@
+þÿé’†esmj”g0ƒþÿé’†es \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/key9 b/security/nss/cmd/bltest/tests/aes_gcm/key9
new file mode 100644
index 000000000..222b4b5a2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/key9
@@ -0,0 +1 @@
+þÿé’†esmj”g0ƒþÿé’†es \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/mktst.sh b/security/nss/cmd/bltest/tests/aes_gcm/mktst.sh
new file mode 100644
index 000000000..a990f519c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/mktst.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
+do
+ file="test$i.txt"
+ grep K= $file | sed -e 's;K=;;' | hex > key$i
+ grep IV= $file | sed -e 's;IV=;;' | hex > iv$i
+ grep "C=" $file | sed -e 's;C=;;' | hex > ciphertext$i.bin
+ grep "P=" $file | sed -e 's;P=;;' | hex > plaintext$i
+ grep "A=" $file | sed -e 's;A=;;' | hex > aad$i
+ grep "T=" $file | sed -e 's;T=;;' | hex >> ciphertext$i.bin
+ btoa < ciphertext$i.bin > ciphertext$i
+ rm ciphertext$i.bin
+done
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/numtests b/security/nss/cmd/bltest/tests/aes_gcm/numtests
new file mode 100644
index 000000000..3c032078a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/numtests
@@ -0,0 +1 @@
+18
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext0 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext0
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext0
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext1 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext1
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext1
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext10 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext10
new file mode 100644
index 000000000..00505877a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext10
@@ -0,0 +1 @@
+Ù12%ø„å¥Y ůõ&š†§©S4÷Ú.L0=Š1Šr< ••h S/Ï$I¦µ%±jíõª æWºc{9 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext11 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext11
new file mode 100644
index 000000000..00505877a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext11
@@ -0,0 +1 @@
+Ù12%ø„å¥Y ůõ&š†§©S4÷Ú.L0=Š1Šr< ••h S/Ï$I¦µ%±jíõª æWºc{9 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext12 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext12
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext12
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext13 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext13
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext13
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext14 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext14
new file mode 100644
index 000000000..664f6c9de
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext14
@@ -0,0 +1 @@
+Ù12%ø„å¥Y ůõ&š†§©S4÷Ú.L0=Š1Šr< ••h S/Ï$I¦µ%±jíõª æWºc{9¯ÒU \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext15 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext15
new file mode 100644
index 000000000..00505877a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext15
@@ -0,0 +1 @@
+Ù12%ø„å¥Y ůõ&š†§©S4÷Ú.L0=Š1Šr< ••h S/Ï$I¦µ%±jíõª æWºc{9 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext16 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext16
new file mode 100644
index 000000000..00505877a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext16
@@ -0,0 +1 @@
+Ù12%ø„å¥Y ůõ&š†§©S4÷Ú.L0=Š1Šr< ••h S/Ï$I¦µ%±jíõª æWºc{9 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext17 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext17
new file mode 100644
index 000000000..00505877a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext17
@@ -0,0 +1 @@
+Ù12%ø„å¥Y ůõ&š†§©S4÷Ú.L0=Š1Šr< ••h S/Ï$I¦µ%±jíõª æWºc{9 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext2 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext2
new file mode 100644
index 000000000..664f6c9de
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext2
@@ -0,0 +1 @@
+Ù12%ø„å¥Y ůõ&š†§©S4÷Ú.L0=Š1Šr< ••h S/Ï$I¦µ%±jíõª æWºc{9¯ÒU \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext3 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext3
new file mode 100644
index 000000000..00505877a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext3
@@ -0,0 +1 @@
+Ù12%ø„å¥Y ůõ&š†§©S4÷Ú.L0=Š1Šr< ••h S/Ï$I¦µ%±jíõª æWºc{9 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext4 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext4
new file mode 100644
index 000000000..00505877a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext4
@@ -0,0 +1 @@
+Ù12%ø„å¥Y ůõ&š†§©S4÷Ú.L0=Š1Šr< ••h S/Ï$I¦µ%±jíõª æWºc{9 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext5 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext5
new file mode 100644
index 000000000..00505877a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext5
@@ -0,0 +1 @@
+Ù12%ø„å¥Y ůõ&š†§©S4÷Ú.L0=Š1Šr< ••h S/Ï$I¦µ%±jíõª æWºc{9 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext6 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext6
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext6
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext7 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext7
new file mode 100644
index 000000000..01d633b27
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext7
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext8 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext8
new file mode 100644
index 000000000..664f6c9de
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext8
@@ -0,0 +1 @@
+Ù12%ø„å¥Y ůõ&š†§©S4÷Ú.L0=Š1Šr< ••h S/Ï$I¦µ%±jíõª æWºc{9¯ÒU \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/plaintext9 b/security/nss/cmd/bltest/tests/aes_gcm/plaintext9
new file mode 100644
index 000000000..00505877a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/plaintext9
@@ -0,0 +1 @@
+Ù12%ø„å¥Y ůõ&š†§©S4÷Ú.L0=Š1Šr< ••h S/Ï$I¦µ%±jíõª æWºc{9 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test0.txt b/security/nss/cmd/bltest/tests/aes_gcm/test0.txt
new file mode 100644
index 000000000..a8bd4e15f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test0.txt
@@ -0,0 +1,11 @@
+test="Test Case 1"
+K=00000000000000000000000000000000
+P=
+IV=000000000000000000000000
+H=66e94bd4ef8a2c3b884cfa59ca342b2e
+Y0=00000000000000000000000000000001
+E(K,Y0)=58e2fccefa7e3061367f1d57a4e7455a
+len(A)||len(C)=00000000000000000000000000000000
+GHASH(H,A,C)=00000000000000000000000000000000
+C=
+T=58e2fccefa7e3061367f1d57a4e7455a
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test1.txt b/security/nss/cmd/bltest/tests/aes_gcm/test1.txt
new file mode 100644
index 000000000..7bb83ce8b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test1.txt
@@ -0,0 +1,14 @@
+test="Test Case 2"
+K=00000000000000000000000000000000
+P=00000000000000000000000000000000
+IV=000000000000000000000000
+H=66e94bd4ef8a2c3b884cfa59ca342b2e
+Y0=00000000000000000000000000000001
+E(K,Y0)=58e2fccefa7e3061367f1d57a4e7455a
+Y1=00000000000000000000000000000002
+E(K,Y1)=0388dace60b6a392f328c2b971b2fe78
+X1 5e2ec746917062882c85b0685353deb7
+len(A)||len(C)=00000000000000000000000000000080
+GHASH(H,A,C)=f38cbb1ad69223dcc3457ae5b6b0f885
+C=0388dace60b6a392f328c2b971b2fe78
+T=ab6e47d42cec13bdf53a67b21257bddf
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test10.txt b/security/nss/cmd/bltest/tests/aes_gcm/test10.txt
new file mode 100644
index 000000000..2a4a5a99e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test10.txt
@@ -0,0 +1,28 @@
+test="Test Case 11"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=cafebabefacedbad
+H=466923ec9ae682214f2c082badb39249
+N1=9473c07b02544299cf007c42c5778218
+len({})||len(IV)=00000000000000000000000000000040
+Y0=a14378078d27258a6292737e1802ada5
+E(K,Y0)=7bb6d647c902427ce7cf26563a337371
+X1=f3bf7ba3e305aeb05ed0d2e4fe076666
+X2=20a51fa2302e9c01b87c48f2c3d91a56
+Y1=a14378078d27258a6292737e1802ada6
+E(K,Y1)=d621c7bc5690a7b1487dbaab8ac76b22
+Y2=a14378078d27258a6292737e1802ada7
+E(K,Y2)=43c1ca7de78f4495ad0b18324e61fa25
+Y3=a14378078d27258a6292737e1802ada8
+E(K,Y3)=e1e0254a0f2f1626e9aa4ff09d7c64ec
+Y4=a14378078d27258a6292737e1802ada9
+E(K,Y4)=5850f4502486a1681a9319ce7d0afa59
+X3=8bdedafd6ee8e529689de3a269b8240d
+X4=6607feb377b49c9ecdbc696344fe22d8
+X5=8a19570a06500ba9405fcece4a73fb48
+X6=8532826e63ce4a5b89b70fa28f8070fe
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=1e6a133806607858ee80eaf237064089
+C=0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7
+T=65dcc57fcf623a24094fcca40d3533f8
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test11.txt b/security/nss/cmd/bltest/tests/aes_gcm/test11.txt
new file mode 100644
index 000000000..d46e6f91f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test11.txt
@@ -0,0 +1,31 @@
+test="Test Case 12"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+H=466923ec9ae682214f2c082badb39249
+N1=19aef0f04763b0c87903c5a217d5314f
+N2=62120253f79efc978625d1feb03b5b5b
+N3=b6ce2a84e366de900fa78a1653df77fb
+N4=374ecad90487f0bb261ba817447e022c
+len({})||len(IV)=000000000000000000000000000001e0
+Y0=4505cdc367a054c5002820e96aebef27
+E(K,Y0)=5ea3194f9dd012a3b9bc5103d6e0284d
+X1=f3bf7ba3e305aeb05ed0d2e4fe076666
+X2=20a51fa2302e9c01b87c48f2c3d91a56
+Y1=4505cdc367a054c5002820e96aebef28
+E(K,Y1)=0b4fba4de46722d9ed691f9f2029df65
+Y2=4505cdc367a054c5002820e96aebef29
+E(K,Y2)=9b4e088bf380b03540bb87a5a257e437
+Y3=4505cdc367a054c5002820e96aebef2a
+E(K,Y3)=9ddb9c873a5cd48acd3f397cd28f9896
+Y4=4505cdc367a054c5002820e96aebef2b
+E(K,Y4)=5716ee92eff7c4b053d44c0294ea88cd
+X3=f70d61693ea7f53f08c866d6eedb1e4b
+X4=dc40bc9a181b35aed66488071ef282ae
+X5=85ffa424b87b35cac7be9c450f0d7aee
+X6=65233cbe5251f7d246bfc967a8678647
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=82567fb0b4cc371801eadec005968e94
+C=d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b
+T=dcf566ff291c25bbb8568fc3d376a6d9
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test12.txt b/security/nss/cmd/bltest/tests/aes_gcm/test12.txt
new file mode 100644
index 000000000..b9ccfa86a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test12.txt
@@ -0,0 +1,11 @@
+test="Test Case 13"
+K=0000000000000000000000000000000000000000000000000000000000000000
+P=
+IV=000000000000000000000000
+H=dc95c078a2408989ad48a21492842087
+Y0=00000000000000000000000000000001
+E(K,Y0)=530f8afbc74536b9a963b4f1c4cb738b
+len(A)||len(C)=00000000000000000000000000000000
+GHASH(H,A,C)=00000000000000000000000000000000
+C=
+T=530f8afbc74536b9a963b4f1c4cb738b
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test13.txt b/security/nss/cmd/bltest/tests/aes_gcm/test13.txt
new file mode 100644
index 000000000..b589ba413
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test13.txt
@@ -0,0 +1,14 @@
+test="Test Case 14"
+K=0000000000000000000000000000000000000000000000000000000000000000
+P=00000000000000000000000000000000
+IV=000000000000000000000000
+H=dc95c078a2408989ad48a21492842087
+Y0=00000000000000000000000000000001
+E(K,Y0)=530f8afbc74536b9a963b4f1c4cb738b
+Y1=00000000000000000000000000000002
+E(K,Y1)=cea7403d4d606b6e074ec5d3baf39d18
+X1=fd6ab7586e556dba06d69cfe6223b262
+len(A)||len(C)=00000000000000000000000000000080
+GHASH(H,A,C)=83de425c5edc5d498f382c441041ca92
+C=cea7403d4d606b6e074ec5d3baf39d18
+T=d0d1c8a799996bf0265b98b5d48ab919
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test14.txt b/security/nss/cmd/bltest/tests/aes_gcm/test14.txt
new file mode 100644
index 000000000..f650ea7c6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test14.txt
@@ -0,0 +1,23 @@
+test="Test Case 15"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+IV=cafebabefacedbaddecaf888
+H=acbef20579b4b8ebce889bac8732dad7
+Y0=cafebabefacedbaddecaf88800000001
+E(K,Y0)=fd2caa16a5832e76aa132c1453eeda7e
+Y1=cafebabefacedbaddecaf88800000002
+E(K,Y1)=8b1cf3d561d27be251263e66857164e7
+Y2=cafebabefacedbaddecaf88800000003
+E(K,Y2)=e29d258faad137135bd49280af645bd8
+Y3=cafebabefacedbaddecaf88800000004
+E(K,Y3)=908c82ddcc65b26e887f85341f243d1d
+Y4=cafebabefacedbaddecaf88800000005
+E(K,Y4)=749cf39639b79c5d06aa8d5b932fc7f8
+X1=fcbefb78635d598eddaf982310670f35
+X2=29de812309d3116a6eff7ec844484f3e
+X3=45fad9deeda9ea561b8f199c3613845b
+X4=ed95f8e164bf3213febc740f0bd9c6af
+len(A)||len(C)=00000000000000000000000000000200
+GHASH(H,A,C)=4db870d37cb75fcb46097c36230d1612
+C=522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
+T=b094dac5d93471bdec1a502270e3cc6c
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test15.txt b/security/nss/cmd/bltest/tests/aes_gcm/test15.txt
new file mode 100644
index 000000000..f1a49e3fe
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test15.txt
@@ -0,0 +1,26 @@
+test="Test Case 16"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=cafebabefacedbaddecaf888
+H=acbef20579b4b8ebce889bac8732dad7
+Y0=cafebabefacedbaddecaf88800000001
+E(K,Y0)=fd2caa16a5832e76aa132c1453eeda7e
+X1=5165d242c2592c0a6375e2622cf925d2
+X2=8efa30ce83298b85fe71abefc0cdd01d
+Y1=cafebabefacedbaddecaf88800000002
+E(K,Y1)=8b1cf3d561d27be251263e66857164e7
+Y2=cafebabefacedbaddecaf88800000003
+E(K,Y2)=e29d258faad137135bd49280af645bd8
+Y3=cafebabefacedbaddecaf88800000004
+E(K,Y3)=908c82ddcc65b26e887f85341f243d1d
+Y4=cafebabefacedbaddecaf88800000005
+E(K,Y4)=749cf39639b79c5d06aa8d5b932fc7f8
+X3=abe07e0bb62354177480b550f9f6cdcc
+X4=3978e4f141b95f3b4699756b1c3c2082
+X5=8abf3c48901debe76837d8a05c7d6e87
+X6=9249beaf520c48b912fa120bbf391dc8
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=8bd0c4d8aacd391e67cca447e8c38f65
+C=522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662
+T=76fc6ece0f4e1768cddf8853bb2d551b
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test16.txt b/security/nss/cmd/bltest/tests/aes_gcm/test16.txt
new file mode 100644
index 000000000..6918aca77
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test16.txt
@@ -0,0 +1,28 @@
+test="Test Case 17"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=cafebabefacedbad
+H=acbef20579b4b8ebce889bac8732dad7
+N1=90c22e3d2aca34b971e8bd09708fae5c
+len({})||len(IV)=00000000000000000000000000000040
+Y0=0095df49dd90abe3e4d252475748f5d4
+E(K,Y0)=4f903f37fe611d454217fbfa5cd7d791
+X1=5165d242c2592c0a6375e2622cf925d2
+X2=8efa30ce83298b85fe71abefc0cdd01d
+Y1=0095df49dd90abe3e4d252475748f5d5
+E(K,Y1)=1a471fd432fc7bd70b1ec8fe5e6d6251
+Y2=0095df49dd90abe3e4d252475748f5d6
+E(K,Y2)=29bd481e1ea39d20eb63c7ea118b1792
+Y3=0095df49dd90abe3e4d252475748f5d7
+E(K,Y3)=e2898e46ac5cada3ba83cc1272618a5d
+Y4=0095df49dd90abe3e4d252475748f5d8
+E(K,Y4)=d3c6aefbcea602ce4e1fe026065447bf
+X3=55e1ff68f9249e64b95223858e5cb936
+X4=cef1c034383dc96f733aaa4c99bd3e61
+X5=68588d004fd468f5854515039b08165d
+X6=2378943c034697f72a80fce5059bf3f3
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=75a34288b8c68f811c52b2e9a2f97f63
+C=c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f
+T=3a337dbf46a792c45e454913fe2ea8f2
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test17.txt b/security/nss/cmd/bltest/tests/aes_gcm/test17.txt
new file mode 100644
index 000000000..a5c538ea6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test17.txt
@@ -0,0 +1,31 @@
+test="Test Case 18"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+H=acbef20579b4b8ebce889bac8732dad7
+N1=0bfe66e2032f195516379f5fb710f987
+N2=f0631554d11409915feec8f9f5102aba
+N3=749b90dda19a1557fd9e9fd31fed1d14
+N4=7a6a833f260d848793b327cb07d1b190
+len({})||len(IV)=000000000000000000000000000001e0
+Y0=0cd953e2140a5976079f8e2406bc8eb4
+E(K,Y0)=71b54d092bb0c3d9ba94538d4096e691
+X1=5165d242c2592c0a6375e2622cf925d2
+X2=8efa30ce83298b85fe71abefc0cdd01d
+Y1=0cd953e2140a5976079f8e2406bc8eb5
+E(K,Y1)=83bcdd0af41a551452047196ca6b0cba
+Y2=0cd953e2140a5976079f8e2406bc8eb6
+E(K,Y2)=68151b79baea93c38e149b72e545e186
+Y3=0cd953e2140a5976079f8e2406bc8eb7
+E(K,Y3)=13fccf22159a4d16026ce5d58c7e99fb
+Y4=0cd953e2140a5976079f8e2406bc8eb8
+E(K,Y4)=132b64628a031e79fecd050675a64f07
+X3=e963941cfa8c417bdaa3b3d94ab4e905
+X4=2178d7f836e5fa105ce0fdf0fc8f0654
+X5=bac14eeba3216f966b3e7e011475b832
+X6=cc9ae9175729a649936e890bd971a8bf
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=d5ffcf6fc5ac4d69722187421a7f170b
+C=5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f
+T=a44a8266ee1c8eb0c8b5d4cf5ae9f19a
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test2.txt b/security/nss/cmd/bltest/tests/aes_gcm/test2.txt
new file mode 100644
index 000000000..8e69bf678
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test2.txt
@@ -0,0 +1,23 @@
+test="Test Case 3"
+K=feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+IV=cafebabefacedbaddecaf888
+H=b83b533708bf535d0aa6e52980d53b78
+Y0=cafebabefacedbaddecaf88800000001
+E(K,Y0)=3247184b3c4f69a44dbcd22887bbb418
+Y1=cafebabefacedbaddecaf88800000002
+E(K,Y1)=9bb22ce7d9f372c1ee2b28722b25f206
+Y2=cafebabefacedbaddecaf88800000003
+E(K,Y2)=650d887c3936533a1b8d4e1ea39d2b5c
+Y3=cafebabefacedbaddecaf88800000004
+E(K,Y3)=3de91827c10e9a4f5240647ee5221f20
+Y4=cafebabefacedbaddecaf88800000005
+E(K,Y4)=aac9e6ccc0074ac0873b9ba85d908bd0
+X1=59ed3f2bb1a0aaa07c9f56c6a504647b
+X2=b714c9048389afd9f9bc5c1d4378e052
+X3=47400c6577b1ee8d8f40b2721e86ff10
+X4=4796cf49464704b5dd91f159bb1b7f95
+len(A)||len(C)=00000000000000000000000000000200
+GHASH(H,A,C)=7f1b32b81b820d02614f8895ac1d4eac
+C=42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985
+T=4d5c2af327cd64a62cf35abd2ba6fab4
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test3.txt b/security/nss/cmd/bltest/tests/aes_gcm/test3.txt
new file mode 100644
index 000000000..4083eac7a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test3.txt
@@ -0,0 +1,26 @@
+test="Test Case 4"
+K=feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=cafebabefacedbaddecaf888
+H=b83b533708bf535d0aa6e52980d53b78
+Y0=cafebabefacedbaddecaf88800000001
+E(K,Y0)=3247184b3c4f69a44dbcd22887bbb418
+X1=ed56aaf8a72d67049fdb9228edba1322
+X2=cd47221ccef0554ee4bb044c88150352
+Y1=cafebabefacedbaddecaf88800000002
+E(K,Y1)=9bb22ce7d9f372c1ee2b28722b25f206
+Y2=cafebabefacedbaddecaf88800000003
+E(K,Y2)=650d887c3936533a1b8d4e1ea39d2b5c
+Y3=cafebabefacedbaddecaf88800000004
+E(K,Y3)=3de91827c10e9a4f5240647ee5221f20
+Y4=cafebabefacedbaddecaf88800000005
+E(K,Y4)=aac9e6ccc0074ac0873b9ba85d908bd0
+X3=54f5e1b2b5a8f9525c23924751a3ca51
+X4=324f585c6ffc1359ab371565d6c45f93
+X5=ca7dd446af4aa70cc3c0cd5abba6aa1c
+X6=1590df9b2eb6768289e57d56274c8570
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=698e57f70e6ecc7fd9463b7260a9ae5f
+C=42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091
+T=5bc94fbc3221a5db94fae95ae7121a47
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test4.txt b/security/nss/cmd/bltest/tests/aes_gcm/test4.txt
new file mode 100644
index 000000000..ec62258d0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test4.txt
@@ -0,0 +1,28 @@
+test="Test Case 5"
+K=feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=cafebabefacedbad
+H=b83b533708bf535d0aa6e52980d53b78
+N1=6f288b846e5fed9a18376829c86a6a16
+len({})||len(C)=00000000000000000000000000000040
+Y0=c43a83c4c4badec4354ca984db252f7d
+E(K,Y0)=e94ab9535c72bea9e089c93d48e62fb0
+X1=ed56aaf8a72d67049fdb9228edba1322
+X2=cd47221ccef0554ee4bb044c88150352
+Y1=c43a83c4c4badec4354ca984db252f7e
+E(K,Y1)=b8040969d08295afd226fcda0ddf61cf
+Y2=c43a83c4c4badec4354ca984db252f7f
+E(K,Y2)=ef3c83225af93122192ad5c4f15dfe51
+Y3=c43a83c4c4badec4354ca984db252f80
+E(K,Y3)=6fbc659571f72de104c67b609d2fde67
+Y4=c43a83c4c4badec4354ca984db252f81
+E(K,Y4)=f8e3581441a1e950785c3ea1430c6fa6
+X3=9379e2feae14649c86cf2250e3a81916
+X4=65dde904c92a6b3db877c4817b50a5f4
+X5=48c53cf863b49a1b0bbfc48c3baaa89d
+X6=08c873f1c8cec3effc209a07468caab1
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=df586bb4c249b92cb6922877e444d37b
+C=61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598
+T=3612d2e79e3b0785561be14aaca2fccb
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test5.txt b/security/nss/cmd/bltest/tests/aes_gcm/test5.txt
new file mode 100644
index 000000000..709251b45
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test5.txt
@@ -0,0 +1,31 @@
+test="Test Case 6"
+K=feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+H=b83b533708bf535d0aa6e52980d53b78
+N1=004d6599d7fb1634756e1e299d81630f
+N2=88ffe8a3c8033df4b54d732f7f88408e
+N3=24e694cfab657beabba8055aad495e23
+N4=d8349a5eda24943c8fbb2ef5168b20cb
+len({})||len(IV)=000000000000000000000000000001e0
+Y0=3bab75780a31c059f83d2a44752f9864
+7dc63b399f2d98d57ab073b6baa4138e
+X1=ed56aaf8a72d67049fdb9228edba1322
+X2=cd47221ccef0554ee4bb044c88150352
+Y1=3bab75780a31c059f83d2a44752f9865
+E(K,Y1)=55d37bbd9ad21353a6f93a690eca9e0e
+Y2=3bab75780a31c059f83d2a44752f9866
+E(K,Y2)=3836bbf6d696e672946a1a01404fa6d5
+Y3=3bab75780a31c059f83d2a44752f9867
+E(K,Y3)=1dd8a5316ecc35c3e313bca59d2ac94a
+Y4=3bab75780a31c059f83d2a44752f9868
+E(K,Y4)=6742982706a9f154f657d5dc94b746db
+X3=31727669c63c6f078b5d22adbbbca384
+X4=480c00db2679065a7ed2f771a53acacd
+X5=1c1ae3c355e2214466a9923d2ba6ab35
+X6=0694c6f16bb0275a48891d06590344b0
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=1c5afe9760d3932f3c9a878aac3dc3de
+C=8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5
+T=619cc5aefffe0bfa462af43c1699d050
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test6.txt b/security/nss/cmd/bltest/tests/aes_gcm/test6.txt
new file mode 100644
index 000000000..b738e1f05
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test6.txt
@@ -0,0 +1,11 @@
+test="Test Case 7"
+K=000000000000000000000000000000000000000000000000
+P=
+IV=000000000000000000000000
+H=aae06992acbf52a3e8f4a96ec9300bd7
+Y0=00000000000000000000000000000001
+E(K,Y0)=cd33b28ac773f74ba00ed1f312572435
+len(A)||len(C)=00000000000000000000000000000000
+GHASH(H,A,C)=00000000000000000000000000000000
+C=
+T=cd33b28ac773f74ba00ed1f312572435
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test7.txt b/security/nss/cmd/bltest/tests/aes_gcm/test7.txt
new file mode 100644
index 000000000..68bc52138
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test7.txt
@@ -0,0 +1,14 @@
+test="Test Case 8"
+K=000000000000000000000000000000000000000000000000
+P=00000000000000000000000000000000
+IV=000000000000000000000000
+H=aae06992acbf52a3e8f4a96ec9300bd7
+Y0=00000000000000000000000000000001
+E(K,Y0)=cd33b28ac773f74ba00ed1f312572435
+Y1=00000000000000000000000000000002
+E(K,Y1)=98e7247c07f0fe411c267e4384b0f600
+X1=90e87315fb7d4e1b4092ec0cbfda5d7d
+len(A)||len(C)=00000000000000000000000000000080
+GHASH(H,A,C)=e2c63f0ac44ad0e02efa05ab6743d4ce
+C=98e7247c07f0fe411c267e4384b0f600
+T=2ff58d80033927ab8ef4d4587514f0fb
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test8.txt b/security/nss/cmd/bltest/tests/aes_gcm/test8.txt
new file mode 100644
index 000000000..544324035
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test8.txt
@@ -0,0 +1,23 @@
+test="Test Case 9"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+IV=cafebabefacedbaddecaf888
+H=466923ec9ae682214f2c082badb39249
+Y0=cafebabefacedbaddecaf88800000001
+E(K,Y0)=c835aa88aebbc94f5a02e179fdcfc3e4
+Y1=cafebabefacedbaddecaf88800000002
+E(K,Y1)=e0b1f82ec484eea44e5ff30128df01cd
+Y2=cafebabefacedbaddecaf88800000003
+E(K,Y2)=0339b5b9b3db2e5e4cc9a38986906bee
+Y3=cafebabefacedbaddecaf88800000004
+E(K,Y3)=614b3195542ccc7683ae933c81ec8a62
+Y4=cafebabefacedbaddecaf88800000005
+E(K,Y4)=a988a97e85eec28e76b95c29b6023003
+X1=dddca3f91c17821ffac4a6d0fed176f7
+X2=a4e84ac60e2730f4a7e0e1eef708b198
+X3=e67592048dd7153973a0dbbb8804bee2
+X4=503e86628536625fb746ce3cecea433f
+len(A)||len(C)=00000000000000000000000000000200
+GHASH(H,A,C)=51110d40f6c8fff0eb1ae33445a889f0
+C=3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256
+T=9924a7c8587336bfb118024db8674a14
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test9.txt b/security/nss/cmd/bltest/tests/aes_gcm/test9.txt
new file mode 100644
index 000000000..bcd593929
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test9.txt
@@ -0,0 +1,26 @@
+test="Test Case 10"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=cafebabefacedbaddecaf888
+H=466923ec9ae682214f2c082badb39249
+Y0=cafebabefacedbaddecaf88800000001
+E(K,Y0)=c835aa88aebbc94f5a02e179fdcfc3e4
+X1=f3bf7ba3e305aeb05ed0d2e4fe076666
+X2=20a51fa2302e9c01b87c48f2c3d91a56
+Y1=cafebabefacedbaddecaf88800000002
+E(K,Y1)=e0b1f82ec484eea44e5ff30128df01cd
+Y2=cafebabefacedbaddecaf88800000003
+E(K,Y2)=0339b5b9b3db2e5e4cc9a38986906bee
+Y3=cafebabefacedbaddecaf88800000004
+E(K,Y3)=614b3195542ccc7683ae933c81ec8a62
+Y4=cafebabefacedbaddecaf88800000005
+E(K,Y4)=a988a97e85eec28e76b95c29b6023003
+X3=714f9700ddf520f20695f6180c6e669d
+X4=e858680b7b240d2ecf7e06bbad4524e2
+X5=3f4865abd6bb3fb9f5c4a816f0a9b778
+X6=4256f67fe87b4f49422ba11af857c973
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=ed2ce3062e4a8ec06db8b4c490e8a268
+C=3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710
+T=2519498e80f1478f37ba55bd6d27618c
diff --git a/security/nss/cmd/bltest/tests/aes_gcm/test_source.txt b/security/nss/cmd/bltest/tests/aes_gcm/test_source.txt
new file mode 100644
index 000000000..61c78fcc5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_gcm/test_source.txt
@@ -0,0 +1,439 @@
+# AppendixB AES Test Vectors
+# From "The Galois/Counter Mode of Operation (GCM)", David A McGree & John Viega,
+# http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
+#
+# This appendix contains test cases for AES GCM, with AES key sizes of 128, 192, and 256 bits. These
+# cases use the same notation as in Equations 1 and 2, with the exception that Ni is used in place of
+# Xi when GHASH is used to compute Y0 , in order to distinguish that case from the later invocation
+# of GHASH. All values are in hexadecimal, and a zero-length variable is indicated by the absence
+# of any hex digits. Each line consists of 128 bits of data, and variables whose lengths exceed that
+# value are continued on successive lines. The leftmost hex digit corresponds to the leftmost four
+# bits of the variable. For example, the lowest 128 bits of the field polynomial are represented as
+# e100000000000000000000000000000000.
+#
+
+test="Test Case 1"
+K=00000000000000000000000000000000
+P=
+IV=000000000000000000000000
+H=66e94bd4ef8a2c3b884cfa59ca342b2e
+Y0=00000000000000000000000000000001
+E(K,Y0)=58e2fccefa7e3061367f1d57a4e7455a
+len(A)||len(C)=00000000000000000000000000000000
+GHASH(H,A,C)=00000000000000000000000000000000
+C=
+T=58e2fccefa7e3061367f1d57a4e7455a
+
+
+test="Test Case 2"
+K=00000000000000000000000000000000
+P=00000000000000000000000000000000
+IV=000000000000000000000000
+H=66e94bd4ef8a2c3b884cfa59ca342b2e
+Y0=00000000000000000000000000000001
+E(K,Y0)=58e2fccefa7e3061367f1d57a4e7455a
+Y1=00000000000000000000000000000002
+E(K,Y1)=0388dace60b6a392f328c2b971b2fe78
+X1 5e2ec746917062882c85b0685353deb7
+len(A)||len(C)=00000000000000000000000000000080
+GHASH(H,A,C)=f38cbb1ad69223dcc3457ae5b6b0f885
+C=0388dace60b6a392f328c2b971b2fe78
+T=ab6e47d42cec13bdf53a67b21257bddf
+
+test="Test Case 3"
+K=feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+IV=cafebabefacedbaddecaf888
+H=b83b533708bf535d0aa6e52980d53b78
+Y0=cafebabefacedbaddecaf88800000001
+E(K,Y0)=3247184b3c4f69a44dbcd22887bbb418
+Y1=cafebabefacedbaddecaf88800000002
+E(K,Y1)=9bb22ce7d9f372c1ee2b28722b25f206
+Y2=cafebabefacedbaddecaf88800000003
+E(K,Y2)=650d887c3936533a1b8d4e1ea39d2b5c
+Y3=cafebabefacedbaddecaf88800000004
+E(K,Y3)=3de91827c10e9a4f5240647ee5221f20
+Y4=cafebabefacedbaddecaf88800000005
+E(K,Y4)=aac9e6ccc0074ac0873b9ba85d908bd0
+X1=59ed3f2bb1a0aaa07c9f56c6a504647b
+X2=b714c9048389afd9f9bc5c1d4378e052
+X3=47400c6577b1ee8d8f40b2721e86ff10
+X4=4796cf49464704b5dd91f159bb1b7f95
+len(A)||len(C)=00000000000000000000000000000200
+GHASH(H,A,C)=7f1b32b81b820d02614f8895ac1d4eac
+C=42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985
+T=4d5c2af327cd64a62cf35abd2ba6fab4
+
+test="Test Case 4"
+K=feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=cafebabefacedbaddecaf888
+H=b83b533708bf535d0aa6e52980d53b78
+Y0=cafebabefacedbaddecaf88800000001
+E(K,Y0)=3247184b3c4f69a44dbcd22887bbb418
+X1=ed56aaf8a72d67049fdb9228edba1322
+X2=cd47221ccef0554ee4bb044c88150352
+Y1=cafebabefacedbaddecaf88800000002
+E(K,Y1)=9bb22ce7d9f372c1ee2b28722b25f206
+Y2=cafebabefacedbaddecaf88800000003
+E(K,Y2)=650d887c3936533a1b8d4e1ea39d2b5c
+Y3=cafebabefacedbaddecaf88800000004
+E(K,Y3)=3de91827c10e9a4f5240647ee5221f20
+Y4=cafebabefacedbaddecaf88800000005
+E(K,Y4)=aac9e6ccc0074ac0873b9ba85d908bd0
+X3=54f5e1b2b5a8f9525c23924751a3ca51
+X4=324f585c6ffc1359ab371565d6c45f93
+X5=ca7dd446af4aa70cc3c0cd5abba6aa1c
+X6=1590df9b2eb6768289e57d56274c8570
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=698e57f70e6ecc7fd9463b7260a9ae5f
+C=42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091
+T=5bc94fbc3221a5db94fae95ae7121a47
+
+test="Test Case 5"
+K=feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=cafebabefacedbad
+H=b83b533708bf535d0aa6e52980d53b78
+N1=6f288b846e5fed9a18376829c86a6a16
+len({})||len(C)=00000000000000000000000000000040
+Y0=c43a83c4c4badec4354ca984db252f7d
+E(K,Y0)=e94ab9535c72bea9e089c93d48e62fb0
+X1=ed56aaf8a72d67049fdb9228edba1322
+X2=cd47221ccef0554ee4bb044c88150352
+Y1=c43a83c4c4badec4354ca984db252f7e
+E(K,Y1)=b8040969d08295afd226fcda0ddf61cf
+Y2=c43a83c4c4badec4354ca984db252f7f
+E(K,Y2)=ef3c83225af93122192ad5c4f15dfe51
+Y3=c43a83c4c4badec4354ca984db252f80
+E(K,Y3)=6fbc659571f72de104c67b609d2fde67
+Y4=c43a83c4c4badec4354ca984db252f81
+E(K,Y4)=f8e3581441a1e950785c3ea1430c6fa6
+X3=9379e2feae14649c86cf2250e3a81916
+X4=65dde904c92a6b3db877c4817b50a5f4
+X5=48c53cf863b49a1b0bbfc48c3baaa89d
+X6=08c873f1c8cec3effc209a07468caab1
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=df586bb4c249b92cb6922877e444d37b
+C=61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598
+T=3612d2e79e3b0785561be14aaca2fccb
+
+test="Test Case 6"
+K=feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+H=b83b533708bf535d0aa6e52980d53b78
+N1=004d6599d7fb1634756e1e299d81630f
+N2=88ffe8a3c8033df4b54d732f7f88408e
+N3=24e694cfab657beabba8055aad495e23
+N4=d8349a5eda24943c8fbb2ef5168b20cb
+len({})||len(IV)=000000000000000000000000000001e0
+Y0=3bab75780a31c059f83d2a44752f9864
+7dc63b399f2d98d57ab073b6baa4138e
+X1=ed56aaf8a72d67049fdb9228edba1322
+X2=cd47221ccef0554ee4bb044c88150352
+Y1=3bab75780a31c059f83d2a44752f9865
+E(K,Y1)=55d37bbd9ad21353a6f93a690eca9e0e
+Y2=3bab75780a31c059f83d2a44752f9866
+E(K,Y2)=3836bbf6d696e672946a1a01404fa6d5
+Y3=3bab75780a31c059f83d2a44752f9867
+E(K,Y3)=1dd8a5316ecc35c3e313bca59d2ac94a
+Y4=3bab75780a31c059f83d2a44752f9868
+E(K,Y4)=6742982706a9f154f657d5dc94b746db
+X3=31727669c63c6f078b5d22adbbbca384
+X4=480c00db2679065a7ed2f771a53acacd
+X5=1c1ae3c355e2214466a9923d2ba6ab35
+X6=0694c6f16bb0275a48891d06590344b0
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=1c5afe9760d3932f3c9a878aac3dc3de
+C=8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5
+T=619cc5aefffe0bfa462af43c1699d050
+
+test="Test Case 7"
+K=000000000000000000000000000000000000000000000000
+P=
+IV=000000000000000000000000
+H=aae06992acbf52a3e8f4a96ec9300bd7
+Y0=00000000000000000000000000000001
+E(K,Y0)=cd33b28ac773f74ba00ed1f312572435
+len(A)||len(C)=00000000000000000000000000000000
+GHASH(H,A,C)=00000000000000000000000000000000
+C=
+T=cd33b28ac773f74ba00ed1f312572435
+
+test="Test Case 8"
+K=000000000000000000000000000000000000000000000000
+P=00000000000000000000000000000000
+IV=000000000000000000000000
+H=aae06992acbf52a3e8f4a96ec9300bd7
+Y0=00000000000000000000000000000001
+E(K,Y0)=cd33b28ac773f74ba00ed1f312572435
+Y1=00000000000000000000000000000002
+E(K,Y1)=98e7247c07f0fe411c267e4384b0f600
+X1=90e87315fb7d4e1b4092ec0cbfda5d7d
+len(A)||len(C)=00000000000000000000000000000080
+GHASH(H,A,C)=e2c63f0ac44ad0e02efa05ab6743d4ce
+C=98e7247c07f0fe411c267e4384b0f600
+T=2ff58d80033927ab8ef4d4587514f0fb
+
+
+test="Test Case 9"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+IV=cafebabefacedbaddecaf888
+H=466923ec9ae682214f2c082badb39249
+Y0=cafebabefacedbaddecaf88800000001
+E(K,Y0)=c835aa88aebbc94f5a02e179fdcfc3e4
+Y1=cafebabefacedbaddecaf88800000002
+E(K,Y1)=e0b1f82ec484eea44e5ff30128df01cd
+Y2=cafebabefacedbaddecaf88800000003
+E(K,Y2)=0339b5b9b3db2e5e4cc9a38986906bee
+Y3=cafebabefacedbaddecaf88800000004
+E(K,Y3)=614b3195542ccc7683ae933c81ec8a62
+Y4=cafebabefacedbaddecaf88800000005
+E(K,Y4)=a988a97e85eec28e76b95c29b6023003
+X1=dddca3f91c17821ffac4a6d0fed176f7
+X2=a4e84ac60e2730f4a7e0e1eef708b198
+X3=e67592048dd7153973a0dbbb8804bee2
+X4=503e86628536625fb746ce3cecea433f
+len(A)||len(C)=00000000000000000000000000000200
+GHASH(H,A,C)=51110d40f6c8fff0eb1ae33445a889f0
+C=3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256
+T=9924a7c8587336bfb118024db8674a14
+
+test="Test Case 10"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=cafebabefacedbaddecaf888
+H=466923ec9ae682214f2c082badb39249
+Y0=cafebabefacedbaddecaf88800000001
+E(K,Y0)=c835aa88aebbc94f5a02e179fdcfc3e4
+X1=f3bf7ba3e305aeb05ed0d2e4fe076666
+X2=20a51fa2302e9c01b87c48f2c3d91a56
+Y1=cafebabefacedbaddecaf88800000002
+E(K,Y1)=e0b1f82ec484eea44e5ff30128df01cd
+Y2=cafebabefacedbaddecaf88800000003
+E(K,Y2)=0339b5b9b3db2e5e4cc9a38986906bee
+Y3=cafebabefacedbaddecaf88800000004
+E(K,Y3)=614b3195542ccc7683ae933c81ec8a62
+Y4=cafebabefacedbaddecaf88800000005
+E(K,Y4)=a988a97e85eec28e76b95c29b6023003
+X3=714f9700ddf520f20695f6180c6e669d
+X4=e858680b7b240d2ecf7e06bbad4524e2
+X5=3f4865abd6bb3fb9f5c4a816f0a9b778
+X6=4256f67fe87b4f49422ba11af857c973
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=ed2ce3062e4a8ec06db8b4c490e8a268
+C=3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710
+T=2519498e80f1478f37ba55bd6d27618c
+
+test="Test Case 11"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=cafebabefacedbad
+H=466923ec9ae682214f2c082badb39249
+N1=9473c07b02544299cf007c42c5778218
+len({})||len(IV)=00000000000000000000000000000040
+Y0=a14378078d27258a6292737e1802ada5
+E(K,Y0)=7bb6d647c902427ce7cf26563a337371
+X1=f3bf7ba3e305aeb05ed0d2e4fe076666
+X2=20a51fa2302e9c01b87c48f2c3d91a56
+Y1=a14378078d27258a6292737e1802ada6
+E(K,Y1)=d621c7bc5690a7b1487dbaab8ac76b22
+Y2=a14378078d27258a6292737e1802ada7
+E(K,Y2)=43c1ca7de78f4495ad0b18324e61fa25
+Y3=a14378078d27258a6292737e1802ada8
+E(K,Y3)=e1e0254a0f2f1626e9aa4ff09d7c64ec
+Y4=a14378078d27258a6292737e1802ada9
+E(K,Y4)=5850f4502486a1681a9319ce7d0afa59
+X3=8bdedafd6ee8e529689de3a269b8240d
+X4=6607feb377b49c9ecdbc696344fe22d8
+X5=8a19570a06500ba9405fcece4a73fb48
+X6=8532826e63ce4a5b89b70fa28f8070fe
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=1e6a133806607858ee80eaf237064089
+C=0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7
+T=65dcc57fcf623a24094fcca40d3533f8
+
+test="Test Case 12"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+H=466923ec9ae682214f2c082badb39249
+N1=19aef0f04763b0c87903c5a217d5314f
+N2=62120253f79efc978625d1feb03b5b5b
+N3=b6ce2a84e366de900fa78a1653df77fb
+N4=374ecad90487f0bb261ba817447e022c
+len({})||len(IV)=000000000000000000000000000001e0
+Y0=4505cdc367a054c5002820e96aebef27
+E(K,Y0)=5ea3194f9dd012a3b9bc5103d6e0284d
+X1=f3bf7ba3e305aeb05ed0d2e4fe076666
+X2=20a51fa2302e9c01b87c48f2c3d91a56
+Y1=4505cdc367a054c5002820e96aebef28
+E(K,Y1)=0b4fba4de46722d9ed691f9f2029df65
+Y2=4505cdc367a054c5002820e96aebef29
+E(K,Y2)=9b4e088bf380b03540bb87a5a257e437
+Y3=4505cdc367a054c5002820e96aebef2a
+E(K,Y3)=9ddb9c873a5cd48acd3f397cd28f9896
+Y4=4505cdc367a054c5002820e96aebef2b
+E(K,Y4)=5716ee92eff7c4b053d44c0294ea88cd
+X3=f70d61693ea7f53f08c866d6eedb1e4b
+X4=dc40bc9a181b35aed66488071ef282ae
+X5=85ffa424b87b35cac7be9c450f0d7aee
+X6=65233cbe5251f7d246bfc967a8678647
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=82567fb0b4cc371801eadec005968e94
+C=d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b
+T=dcf566ff291c25bbb8568fc3d376a6d9
+
+test="Test Case 13"
+K=0000000000000000000000000000000000000000000000000000000000000000
+P=
+IV=000000000000000000000000
+H=dc95c078a2408989ad48a21492842087
+Y0=00000000000000000000000000000001
+E(K,Y0)=530f8afbc74536b9a963b4f1c4cb738b
+len(A)||len(C)=00000000000000000000000000000000
+GHASH(H,A,C)=00000000000000000000000000000000
+C=
+T=530f8afbc74536b9a963b4f1c4cb738b
+
+
+test="Test Case 14"
+K=0000000000000000000000000000000000000000000000000000000000000000
+P=00000000000000000000000000000000
+IV=000000000000000000000000
+H=dc95c078a2408989ad48a21492842087
+Y0=00000000000000000000000000000001
+E(K,Y0)=530f8afbc74536b9a963b4f1c4cb738b
+Y1=00000000000000000000000000000002
+E(K,Y1)=cea7403d4d606b6e074ec5d3baf39d18
+X1=fd6ab7586e556dba06d69cfe6223b262
+len(A)||len(C)=00000000000000000000000000000080
+GHASH(H,A,C)=83de425c5edc5d498f382c441041ca92
+C=cea7403d4d606b6e074ec5d3baf39d18
+T=d0d1c8a799996bf0265b98b5d48ab919
+
+test="Test Case 15"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+IV=cafebabefacedbaddecaf888
+H=acbef20579b4b8ebce889bac8732dad7
+Y0=cafebabefacedbaddecaf88800000001
+E(K,Y0)=fd2caa16a5832e76aa132c1453eeda7e
+Y1=cafebabefacedbaddecaf88800000002
+E(K,Y1)=8b1cf3d561d27be251263e66857164e7
+Y2=cafebabefacedbaddecaf88800000003
+E(K,Y2)=e29d258faad137135bd49280af645bd8
+Y3=cafebabefacedbaddecaf88800000004
+E(K,Y3)=908c82ddcc65b26e887f85341f243d1d
+Y4=cafebabefacedbaddecaf88800000005
+E(K,Y4)=749cf39639b79c5d06aa8d5b932fc7f8
+X1=fcbefb78635d598eddaf982310670f35
+X2=29de812309d3116a6eff7ec844484f3e
+X3=45fad9deeda9ea561b8f199c3613845b
+X4=ed95f8e164bf3213febc740f0bd9c6af
+len(A)||len(C)=00000000000000000000000000000200
+GHASH(H,A,C)=4db870d37cb75fcb46097c36230d1612
+C=522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
+T=b094dac5d93471bdec1a502270e3cc6c
+
+test="Test Case 16"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=cafebabefacedbaddecaf888
+H=acbef20579b4b8ebce889bac8732dad7
+Y0=cafebabefacedbaddecaf88800000001
+E(K,Y0)=fd2caa16a5832e76aa132c1453eeda7e
+X1=5165d242c2592c0a6375e2622cf925d2
+X2=8efa30ce83298b85fe71abefc0cdd01d
+Y1=cafebabefacedbaddecaf88800000002
+E(K,Y1)=8b1cf3d561d27be251263e66857164e7
+Y2=cafebabefacedbaddecaf88800000003
+E(K,Y2)=e29d258faad137135bd49280af645bd8
+Y3=cafebabefacedbaddecaf88800000004
+E(K,Y3)=908c82ddcc65b26e887f85341f243d1d
+Y4=cafebabefacedbaddecaf88800000005
+E(K,Y4)=749cf39639b79c5d06aa8d5b932fc7f8
+X3=abe07e0bb62354177480b550f9f6cdcc
+X4=3978e4f141b95f3b4699756b1c3c2082
+X5=8abf3c48901debe76837d8a05c7d6e87
+X6=9249beaf520c48b912fa120bbf391dc8
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=8bd0c4d8aacd391e67cca447e8c38f65
+C=522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662
+T=76fc6ece0f4e1768cddf8853bb2d551b
+
+
+test="Test Case 17"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=cafebabefacedbad
+H=acbef20579b4b8ebce889bac8732dad7
+N1=90c22e3d2aca34b971e8bd09708fae5c
+len({})||len(IV)=00000000000000000000000000000040
+Y0=0095df49dd90abe3e4d252475748f5d4
+E(K,Y0)=4f903f37fe611d454217fbfa5cd7d791
+X1=5165d242c2592c0a6375e2622cf925d2
+X2=8efa30ce83298b85fe71abefc0cdd01d
+Y1=0095df49dd90abe3e4d252475748f5d5
+E(K,Y1)=1a471fd432fc7bd70b1ec8fe5e6d6251
+Y2=0095df49dd90abe3e4d252475748f5d6
+E(K,Y2)=29bd481e1ea39d20eb63c7ea118b1792
+Y3=0095df49dd90abe3e4d252475748f5d7
+E(K,Y3)=e2898e46ac5cada3ba83cc1272618a5d
+Y4=0095df49dd90abe3e4d252475748f5d8
+E(K,Y4)=d3c6aefbcea602ce4e1fe026065447bf
+X3=55e1ff68f9249e64b95223858e5cb936
+X4=cef1c034383dc96f733aaa4c99bd3e61
+X5=68588d004fd468f5854515039b08165d
+X6=2378943c034697f72a80fce5059bf3f3
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=75a34288b8c68f811c52b2e9a2f97f63
+C=c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f
+T=3a337dbf46a792c45e454913fe2ea8f2
+
+test="Test Case 18"
+K=feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+P=d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+A=feedfacedeadbeeffeedfacedeadbeefabaddad2
+IV=9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+H=acbef20579b4b8ebce889bac8732dad7
+N1=0bfe66e2032f195516379f5fb710f987
+N2=f0631554d11409915feec8f9f5102aba
+N3=749b90dda19a1557fd9e9fd31fed1d14
+N4=7a6a833f260d848793b327cb07d1b190
+len({})||len(IV)=000000000000000000000000000001e0
+Y0=0cd953e2140a5976079f8e2406bc8eb4
+E(K,Y0)=71b54d092bb0c3d9ba94538d4096e691
+X1=5165d242c2592c0a6375e2622cf925d2
+X2=8efa30ce83298b85fe71abefc0cdd01d
+Y1=0cd953e2140a5976079f8e2406bc8eb5
+E(K,Y1)=83bcdd0af41a551452047196ca6b0cba
+Y2=0cd953e2140a5976079f8e2406bc8eb6
+E(K,Y2)=68151b79baea93c38e149b72e545e186
+Y3=0cd953e2140a5976079f8e2406bc8eb7
+E(K,Y3)=13fccf22159a4d16026ce5d58c7e99fb
+Y4=0cd953e2140a5976079f8e2406bc8eb8
+E(K,Y4)=132b64628a031e79fecd050675a64f07
+X3=e963941cfa8c417bdaa3b3d94ab4e905
+X4=2178d7f836e5fa105ce0fdf0fc8f0654
+X5=bac14eeba3216f966b3e7e011475b832
+X6=cc9ae9175729a649936e890bd971a8bf
+len(A)||len(C)=00000000000000a000000000000001e0
+GHASH(H,A,C)=d5ffcf6fc5ac4d69722187421a7f170b
+C=5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f
+T=a44a8266ee1c8eb0c8b5d4cf5ae9f19a
+
+
+
+
+
diff --git a/security/nss/cmd/bltest/tests/camellia_cbc/ciphertext0 b/security/nss/cmd/bltest/tests/camellia_cbc/ciphertext0
new file mode 100644
index 000000000..e7895954a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_cbc/ciphertext0
@@ -0,0 +1 @@
+taydfPlRJe3wf8Td0xJ9Tw==
diff --git a/security/nss/cmd/bltest/tests/camellia_cbc/ciphertext1 b/security/nss/cmd/bltest/tests/camellia_cbc/ciphertext1
new file mode 100644
index 000000000..7dbd9b036
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_cbc/ciphertext1
@@ -0,0 +1 @@
+yoYCZwKnUMcS4ADHxnwObA==
diff --git a/security/nss/cmd/bltest/tests/camellia_cbc/ciphertext2 b/security/nss/cmd/bltest/tests/camellia_cbc/ciphertext2
new file mode 100644
index 000000000..007a2b0fa
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_cbc/ciphertext2
@@ -0,0 +1 @@
+T+Wn4cs1Sbqrh/XtNd4vzQ==
diff --git a/security/nss/cmd/bltest/tests/camellia_cbc/iv0 b/security/nss/cmd/bltest/tests/camellia_cbc/iv0
new file mode 100644
index 000000000..4e65bc034
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_cbc/iv0
@@ -0,0 +1 @@
+qwertyuiopasdfgh
diff --git a/security/nss/cmd/bltest/tests/camellia_cbc/key0 b/security/nss/cmd/bltest/tests/camellia_cbc/key0
new file mode 100644
index 000000000..13911cc29
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_cbc/key0
@@ -0,0 +1 @@
+fedcba9876543210
diff --git a/security/nss/cmd/bltest/tests/camellia_cbc/key1 b/security/nss/cmd/bltest/tests/camellia_cbc/key1
new file mode 100644
index 000000000..a9cb2f12f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_cbc/key1
@@ -0,0 +1 @@
+fedcba9876543210fedcba98
diff --git a/security/nss/cmd/bltest/tests/camellia_cbc/key2 b/security/nss/cmd/bltest/tests/camellia_cbc/key2
new file mode 100644
index 000000000..ab55fe2ee
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_cbc/key2
@@ -0,0 +1 @@
+fedcba9876543210fedcba9876543210
diff --git a/security/nss/cmd/bltest/tests/camellia_cbc/numtests b/security/nss/cmd/bltest/tests/camellia_cbc/numtests
new file mode 100644
index 000000000..00750edc0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_cbc/numtests
@@ -0,0 +1 @@
+3
diff --git a/security/nss/cmd/bltest/tests/camellia_cbc/plaintext0 b/security/nss/cmd/bltest/tests/camellia_cbc/plaintext0
new file mode 100644
index 000000000..8d6a8d555
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_cbc/plaintext0
@@ -0,0 +1 @@
+0123456789abcdef
diff --git a/security/nss/cmd/bltest/tests/camellia_ecb/ciphertext0 b/security/nss/cmd/bltest/tests/camellia_ecb/ciphertext0
new file mode 100644
index 000000000..084ba780e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_ecb/ciphertext0
@@ -0,0 +1 @@
+6v0CGxSwow3AhsyhunfdbQ==
diff --git a/security/nss/cmd/bltest/tests/camellia_ecb/ciphertext1 b/security/nss/cmd/bltest/tests/camellia_ecb/ciphertext1
new file mode 100644
index 000000000..dbd6e5f42
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_ecb/ciphertext1
@@ -0,0 +1 @@
+Nf1GwJiBtZT+VPJp+gBhPA==
diff --git a/security/nss/cmd/bltest/tests/camellia_ecb/ciphertext2 b/security/nss/cmd/bltest/tests/camellia_ecb/ciphertext2
new file mode 100644
index 000000000..0b278ce2a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_ecb/ciphertext2
@@ -0,0 +1 @@
+ilB/0K3SI86Oecwh7cruGA==
diff --git a/security/nss/cmd/bltest/tests/camellia_ecb/key0 b/security/nss/cmd/bltest/tests/camellia_ecb/key0
new file mode 100644
index 000000000..13911cc29
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_ecb/key0
@@ -0,0 +1 @@
+fedcba9876543210
diff --git a/security/nss/cmd/bltest/tests/camellia_ecb/key1 b/security/nss/cmd/bltest/tests/camellia_ecb/key1
new file mode 100644
index 000000000..a9cb2f12f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_ecb/key1
@@ -0,0 +1 @@
+fedcba9876543210fedcba98
diff --git a/security/nss/cmd/bltest/tests/camellia_ecb/key2 b/security/nss/cmd/bltest/tests/camellia_ecb/key2
new file mode 100644
index 000000000..ab55fe2ee
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_ecb/key2
@@ -0,0 +1 @@
+fedcba9876543210fedcba9876543210
diff --git a/security/nss/cmd/bltest/tests/camellia_ecb/numtests b/security/nss/cmd/bltest/tests/camellia_ecb/numtests
new file mode 100644
index 000000000..00750edc0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_ecb/numtests
@@ -0,0 +1 @@
+3
diff --git a/security/nss/cmd/bltest/tests/camellia_ecb/plaintext0 b/security/nss/cmd/bltest/tests/camellia_ecb/plaintext0
new file mode 100644
index 000000000..8d6a8d555
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/camellia_ecb/plaintext0
@@ -0,0 +1 @@
+0123456789abcdef
diff --git a/security/nss/cmd/bltest/tests/chacha20_poly1305/aad0 b/security/nss/cmd/bltest/tests/chacha20_poly1305/aad0
new file mode 100644
index 000000000..a420ef184
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/chacha20_poly1305/aad0
@@ -0,0 +1 @@
+PQRSÀÁÂÃÄÅÆÇ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/chacha20_poly1305/aad1 b/security/nss/cmd/bltest/tests/chacha20_poly1305/aad1
new file mode 100644
index 000000000..91287a1a2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/chacha20_poly1305/aad1
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/chacha20_poly1305/ciphertext0 b/security/nss/cmd/bltest/tests/chacha20_poly1305/ciphertext0
new file mode 100644
index 000000000..a06f68b5f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/chacha20_poly1305/ciphertext0
@@ -0,0 +1 @@
+0xqNNGSOYNt7hq+8U+9+wqSt7VEpbgj+qeK1pzbuYtY9vqRejKlnEoL6+2naknKLGnHeCp4GCykF1qW2fs07NpLdvX8td4uMmAOu4ygJG1j6syTk+tZ1lFWFgItIMde8P/Te8I5Lep3ldtJlhs7GS2EWGuELWU8J4mp+kC7L0GAGkQ==
diff --git a/security/nss/cmd/bltest/tests/chacha20_poly1305/ciphertext1 b/security/nss/cmd/bltest/tests/chacha20_poly1305/ciphertext1
new file mode 100644
index 000000000..e7f0d0100
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/chacha20_poly1305/ciphertext1
@@ -0,0 +1 @@
+ZKCGFXWGGvRg8GLHm+ZDvV6AXP00XPOJ8QhnCsdsjLJMbPwYdV1D7qCe6U44LSawvbe3PDIbAQDU8Dt/NViUzzMvgw5xC5fOmMioSr0LlIEUrRduAI0zvWD5grH/N8hVl5egbvTw72HBhjJOKzUGODYGkHtqfAKw+fYVe1PIZ+S5Fmx2e4BNRqWbUhbN56TpkEDFpAQzIl7igqGwoGxSPq9FNNf4P6EVWwBHcYy8VGoNBysEs1ZO6htCInP1SCcaC7IxYFP6dpkZVevWMVlDTs67TkZtrloQc6ZydicJehBJ5hfZHTYQlPpo8P93mHEwMFvqui7aBN+Ze3FNbG8sKaatXLQCKwJwm+6tnWeJDLsiOSM2/qGFHzg=
diff --git a/security/nss/cmd/bltest/tests/chacha20_poly1305/iv0 b/security/nss/cmd/bltest/tests/chacha20_poly1305/iv0
new file mode 100644
index 000000000..7e8a17504
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/chacha20_poly1305/iv0
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/chacha20_poly1305/iv1 b/security/nss/cmd/bltest/tests/chacha20_poly1305/iv1
new file mode 100644
index 000000000..7c8b98f50
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/chacha20_poly1305/iv1
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/chacha20_poly1305/key0 b/security/nss/cmd/bltest/tests/chacha20_poly1305/key0
new file mode 100644
index 000000000..503ecb84e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/chacha20_poly1305/key0
@@ -0,0 +1 @@
+€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/chacha20_poly1305/key1 b/security/nss/cmd/bltest/tests/chacha20_poly1305/key1
new file mode 100644
index 000000000..002bf1b45
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/chacha20_poly1305/key1
@@ -0,0 +1 @@
+’@¥ëUÓŠó3ˆ†öµðG9Á@+€ Ê\¼ puÀ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/chacha20_poly1305/numtests b/security/nss/cmd/bltest/tests/chacha20_poly1305/numtests
new file mode 100644
index 000000000..0cfbf0888
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/chacha20_poly1305/numtests
@@ -0,0 +1 @@
+2
diff --git a/security/nss/cmd/bltest/tests/chacha20_poly1305/plaintext0 b/security/nss/cmd/bltest/tests/chacha20_poly1305/plaintext0
new file mode 100644
index 000000000..74c222908
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/chacha20_poly1305/plaintext0
@@ -0,0 +1 @@
+Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it. \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/chacha20_poly1305/plaintext1 b/security/nss/cmd/bltest/tests/chacha20_poly1305/plaintext1
new file mode 100644
index 000000000..029317d8e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/chacha20_poly1305/plaintext1
@@ -0,0 +1 @@
+Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as /“work in progress./†\ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/des3_cbc/ciphertext0 b/security/nss/cmd/bltest/tests/des3_cbc/ciphertext0
new file mode 100644
index 000000000..61dae3192
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_cbc/ciphertext0
@@ -0,0 +1 @@
+KV3MDNGKWOc=
diff --git a/security/nss/cmd/bltest/tests/des3_cbc/iv0 b/security/nss/cmd/bltest/tests/des3_cbc/iv0
new file mode 100644
index 000000000..97b5955f7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_cbc/iv0
@@ -0,0 +1 @@
+12345678
diff --git a/security/nss/cmd/bltest/tests/des3_cbc/key0 b/security/nss/cmd/bltest/tests/des3_cbc/key0
new file mode 100644
index 000000000..588efd111
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_cbc/key0
@@ -0,0 +1 @@
+abcdefghijklmnopqrstuvwx
diff --git a/security/nss/cmd/bltest/tests/des3_cbc/numtests b/security/nss/cmd/bltest/tests/des3_cbc/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_cbc/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/des3_cbc/plaintext0 b/security/nss/cmd/bltest/tests/des3_cbc/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_cbc/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/des3_ecb/ciphertext0 b/security/nss/cmd/bltest/tests/des3_ecb/ciphertext0
new file mode 100644
index 000000000..76dc820d3
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_ecb/ciphertext0
@@ -0,0 +1 @@
+RgckVNh4QcM=
diff --git a/security/nss/cmd/bltest/tests/des3_ecb/key0 b/security/nss/cmd/bltest/tests/des3_ecb/key0
new file mode 100644
index 000000000..588efd111
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_ecb/key0
@@ -0,0 +1 @@
+abcdefghijklmnopqrstuvwx
diff --git a/security/nss/cmd/bltest/tests/des3_ecb/numtests b/security/nss/cmd/bltest/tests/des3_ecb/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_ecb/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/des3_ecb/plaintext0 b/security/nss/cmd/bltest/tests/des3_ecb/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_ecb/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/des_cbc/ciphertext0 b/security/nss/cmd/bltest/tests/des_cbc/ciphertext0
new file mode 100644
index 000000000..67d2ad1aa
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_cbc/ciphertext0
@@ -0,0 +1 @@
+Perdg9FMYQ4=
diff --git a/security/nss/cmd/bltest/tests/des_cbc/iv0 b/security/nss/cmd/bltest/tests/des_cbc/iv0
new file mode 100644
index 000000000..97b5955f7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_cbc/iv0
@@ -0,0 +1 @@
+12345678
diff --git a/security/nss/cmd/bltest/tests/des_cbc/key0 b/security/nss/cmd/bltest/tests/des_cbc/key0
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_cbc/key0
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/des_cbc/numtests b/security/nss/cmd/bltest/tests/des_cbc/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_cbc/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/des_cbc/plaintext0 b/security/nss/cmd/bltest/tests/des_cbc/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_cbc/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/des_ecb/ciphertext0 b/security/nss/cmd/bltest/tests/des_ecb/ciphertext0
new file mode 100644
index 000000000..8be22fa5c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_ecb/ciphertext0
@@ -0,0 +1 @@
+3bNoWzzNiFc=
diff --git a/security/nss/cmd/bltest/tests/des_ecb/key0 b/security/nss/cmd/bltest/tests/des_ecb/key0
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_ecb/key0
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/des_ecb/numtests b/security/nss/cmd/bltest/tests/des_ecb/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_ecb/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/des_ecb/plaintext0 b/security/nss/cmd/bltest/tests/des_ecb/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_ecb/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext0 b/security/nss/cmd/bltest/tests/dsa/ciphertext0
new file mode 100644
index 000000000..8e7150562
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext0
@@ -0,0 +1 @@
+fB0bnKWvjT6X5NIkZ5l/Y/DXZ6QNI6j0iPhR/ZERkfj67xRnTWY1cg==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext1 b/security/nss/cmd/bltest/tests/dsa/ciphertext1
new file mode 100644
index 000000000..4420dc71b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext1
@@ -0,0 +1 @@
+UO0OgQ4/HHy2rGIzIFhEi9iyhMDGre0XIWtGt+S28ql8GtfMPag/3g==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext10 b/security/nss/cmd/bltest/tests/dsa/ciphertext10
new file mode 100644
index 000000000..55e975aa8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext10
@@ -0,0 +1,2 @@
+namWZQDenTtrf0QcpVAjP8RQlEvFB+Ac1KywMC1y8fZoHoZ/fYvq6+ukvFsjKHYE
+pkz+4cFkWVo=
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext11 b/security/nss/cmd/bltest/tests/dsa/ciphertext11
new file mode 100644
index 000000000..62388f146
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext11
@@ -0,0 +1,2 @@
+Nj4BxWTzgKJ9fSOyB68/lh1I/AmVSH9gBSd11ySrPRBJFtkbKScpTkKdU3wG3SRj
+0YRQGMyihz6Qpsg3tEX93g==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext12 b/security/nss/cmd/bltest/tests/dsa/ciphertext12
new file mode 100644
index 000000000..5a933e6c8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext12
@@ -0,0 +1,2 @@
+BZvunnCLfyDD95GmQO3ulk4KpnKJPEhHmXFYF7Oo9tRL1ByEpyTMhuTwGU7A+/N5
+5lTQ1/ah8IvUaBOUIqXDUw==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext13 b/security/nss/cmd/bltest/tests/dsa/ciphertext13
new file mode 100644
index 000000000..4a21643e5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext13
@@ -0,0 +1,2 @@
+YzBV4FXyN8OJmdgcOXhIw4zOgKVbZJ2eeQXCmOKlFEcrv2gxdmDsHksVSRUCewvA
+DuGc/Av3XQGTBQTyzhCosA==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext14 b/security/nss/cmd/bltest/tests/dsa/ciphertext14
new file mode 100644
index 000000000..ca7896ff3
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext14
@@ -0,0 +1,2 @@
+T9jyXAWQMAJzgdQWfDF0tr4AiMFfClc9fr0Flg9aHrJfVoac7nv2T+xdXW6hW7H6
+EWkAOofszBYhuQobiSIm8g==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext15 b/security/nss/cmd/bltest/tests/dsa/ciphertext15
new file mode 100644
index 000000000..65e68f99d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext15
@@ -0,0 +1,2 @@
+akfqV86uzBFtcZD/bG3Zgxq3W0v2yykQg+Qmi0hu0kUBc1X2mKMqvppNSn3afIWV
+DN3DSKuKZ1HnL93AGqXR8A==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext16 b/security/nss/cmd/bltest/tests/dsa/ciphertext16
new file mode 100644
index 000000000..e72ae9e72
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext16
@@ -0,0 +1,2 @@
+IcoUjN9EvkrpOy81O45RLQOtltr6gGI/3kkiqV8DJzJz5It3o6pEMHSDwt2JXLUd
+shEhd8GFxZyx3P8y/aAqTw==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext17 b/security/nss/cmd/bltest/tests/dsa/ciphertext17
new file mode 100644
index 000000000..83417303a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext17
@@ -0,0 +1,2 @@
+LlnV8w9zeB04JVtw3t7rOK54308ALB90fAjercZTAVVhXFWy3wyijGCms4XFj6A2
+34xLL08ZNXML+PTwvtE2EA==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext18 b/security/nss/cmd/bltest/tests/dsa/ciphertext18
new file mode 100644
index 000000000..56e3ad375
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext18
@@ -0,0 +1,2 @@
+U7rmxvM24usxHB6S2V/ESakpRE74HsQnlmCyANWUM95J86dOlT53p5Qa867+707U
+mb4gmXag7bP6Xny5YbDBEg==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext19 b/security/nss/cmd/bltest/tests/dsa/ciphertext19
new file mode 100644
index 000000000..16d0828bf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext19
@@ -0,0 +1,2 @@
+dpVpihR1XbQgboULT18ZxUCwfQfgiqxZHiAIFkbm7tw9rgEVTs/3sZAHqVPxhfBm
+PvfyU38LFeBPs0PJYfNt4g==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext2 b/security/nss/cmd/bltest/tests/dsa/ciphertext2
new file mode 100644
index 000000000..e2442d9f7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext2
@@ -0,0 +1 @@
+r+5xnn+Ei1Q0nMw7T7JgZYM6TY5zTv6ZIlbzEyXnSbwyokoflXs6Gw==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext20 b/security/nss/cmd/bltest/tests/dsa/ciphertext20
new file mode 100644
index 000000000..ead0ebbee
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext20
@@ -0,0 +1,2 @@
+pApskFZUxV/FjpnH0aP+6ixb5kgj1Ahs6BHzNM/cRI1keAUJd+xYWYBFTgovJqAw
+N7khyliKeKTa/36E1JqKbA==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext3 b/security/nss/cmd/bltest/tests/dsa/ciphertext3
new file mode 100644
index 000000000..072c996ef
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext3
@@ -0,0 +1 @@
+dmg6CF1nQurflaYa91+IEnbP0mo7naf5km6qrQvr1IRcZ/zbZNEkUw==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext4 b/security/nss/cmd/bltest/tests/dsa/ciphertext4
new file mode 100644
index 000000000..4a5ebfa0a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext4
@@ -0,0 +1 @@
+d8TZn2KzrX3R/mSY20Wl2nPOe94jhxoAKuUD/auqaoTcyPOHaXN/AQ==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext5 b/security/nss/cmd/bltest/tests/dsa/ciphertext5
new file mode 100644
index 000000000..707fd56d0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext5
@@ -0,0 +1 @@
+pT8fjyC409RyDxSourUiawedmVMR9T9qTla1H2DiDUlXronhYq6mFg==
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext6 b/security/nss/cmd/bltest/tests/dsa/ciphertext6
new file mode 100644
index 000000000..1bba78703
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext6
@@ -0,0 +1,2 @@
+Rd8vQj6UvxVd1OHZ5j8xXqYG3ThSfUz2Moc4yFmz6O+lvAzL9KPLtlFcS5v3hM+s
+3MEB3J+B0x8=
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext7 b/security/nss/cmd/bltest/tests/dsa/ciphertext7
new file mode 100644
index 000000000..d1a66d336
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext7
@@ -0,0 +1,2 @@
+ZRAuj2TssR8GAXsaDA3vPCmJfCd8SpSLH02muSGtCrsnvTwhFmy5au9wwNvV8wec
+qw3VQ9QSW9E=
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext8 b/security/nss/cmd/bltest/tests/dsa/ciphertext8
new file mode 100644
index 000000000..87fa10cf5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext8
@@ -0,0 +1,2 @@
+nF+kaHndr1wU8H37UyBxX2em/sF5461TNC+20cPhfns8TQrI1J9N0PBMFqCU9C2g
+r8xskPXxu8g=
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext9 b/security/nss/cmd/bltest/tests/dsa/ciphertext9
new file mode 100644
index 000000000..dad2c50af
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext9
@@ -0,0 +1,2 @@
+WrQ+3mahVogUbR9M1xZHAsDERXvU/d66wEgpU2xY6Ksn0oUSxGBjyWv1vOuPutIy
+2PWznEdV0LE=
diff --git a/security/nss/cmd/bltest/tests/dsa/dsa_fips.txt b/security/nss/cmd/bltest/tests/dsa/dsa_fips.txt
new file mode 100644
index 000000000..e657c083e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/dsa_fips.txt
@@ -0,0 +1,248 @@
+# CAVS 11.2
+# "SigGen" information for "dsa2_values"
+# Mod sizes selected: L=1024, N=160, SHA-1 L=1024, N=160, SHA-224 L=1024, N=160, SHA-256 L=1024, N=160, SHA-384 L=1024, N=160, SHA-512 L=2048, N=224, SHA-1 L=2048, N=224, SHA-224 L=2048, N=224, SHA-256 L=2048, N=224, SHA-384 L=2048, N=224, SHA-512 L=2048, N=256, SHA-1 L=2048, N=256, SHA-224 L=2048, N=256, SHA-256 L=2048, N=256, SHA-384 L=2048, N=256, SHA-512 L=3072, N=256, SHA-1 L=3072, N=256, SHA-224 L=3072, N=256, SHA-256 L=3072, N=256, SHA-384 L=3072, N=256, SHA-512
+# Generated on Tue Aug 16 11:21:08 2011
+#
+# These sample from NIST were used to generate dsa tests 1-20
+#
+
+[mod = L=1024, N=160, SHA-1]
+
+P = a8f9cd201e5e35d892f85f80e4db2599a5676a3b1d4f190330ed3256b26d0e80a0e49a8fffaaad2a24f472d2573241d4d6d6c7480c80b4c67bb4479c15ada7ea8424d2502fa01472e760241713dab025ae1b02e1703a1435f62ddf4ee4c1b664066eb22f2e3bf28bb70a2a76e4fd5ebe2d1229681b5b06439ac9c7e9d8bde283
+Q = f85f0f83ac4df7ea0cdf8f469bfeeaea14156495
+G = 2b3152ff6c62f14622b8f48e59f8af46883b38e79b8c74deeae9df131f8b856e3ad6c8455dab87cc0da8ac973417ce4f7878557d6cdf40b35b4a0ca3eb310c6a95d68ce284ad4e25ea28591611ee08b8444bd64b25f3f7c572410ddfb39cc728b9c936f85f419129869929cdb909a6a3a99bbe089216368171bd0ba81de4fe33
+Msg = 3b46736d559bd4e0c2c1b2553a33ad3c6cf23cac998d3d0c0e8fa4b19bca06f2f386db2dcff9dca4f40ad8f561ffc308b46c5f31a7735b5fa7e0f9e6cb512e63d7eea05538d66a75cd0d4234b5ccf6c1715ccaaf9cdc0a2228135f716ee9bdee7fc13ec27a03a6d11c5c5b3685f51900b1337153bc6c4e8f52920c33fa37f4e7
+X = c53eae6d45323164c7d07af5715703744a63fc3a
+Y = 313fd9ebca91574e1c2eebe1517c57e0c21b0209872140c5328761bbb2450b33f1b18b409ce9ab7c4cd8fda3391e8e34868357c199e16a6b2eba06d6749def791d79e95d3a4d09b24c392ad89dbf100995ae19c01062056bb14bce005e8731efde175f95b975089bdcdaea562b32786d96f5a31aedf75364008ad4fffebb970b
+K = 98cbcc4969d845e2461b5f66383dd503712bbcfa
+R = 50ed0e810e3f1c7cb6ac62332058448bd8b284c0
+S = c6aded17216b46b7e4b6f2a97c1ad7cc3da83fde
+
+[mod = L=1024, N=160, SHA-224]
+
+P = 8b9b32f5ba38faad5e0d506eb555540d0d7963195558ca308b7466228d92a17b3b14b8e0ab77a9f3b2959a09848aa69f8df92cd9e9edef0adf792ce77bfceccadd9352700ca5faecf181fa0c326db1d6e5d352458011e51bd3248f4e3bd7c820d7e0a81932aca1eba390175e53eada197223674e3900263e90f72d94e7447bff
+Q = bc550e965647fb3a20f245ec8475624abbb26edd
+G = 11333a931fba503487777376859fdc12f7c687b0948ae889d287f1b7a712ad220ae4f1ce379d0dbb5c9abf419621f005fc123c327e5055d1850634c36d397e689e111d598c1c3636b940c84f42f436846e8e7fcad9012ceda398720f32fffd1a45ab6136ce417069207ac140675b8f86dd063915ae6f62b0cec729fbd509ac17
+Msg = fb2128052509488cad0745ed3e6312850dd96ddaf791f1e624e22a6b9beaa65319c325c78ef59cacba0ccfa722259f24f92c17b77a8f6d8e97c93d880d2d8dbbbedcf6acefa06b0e476ca2013d0394bd90d56c10626ef43cea79d1ef0bc7ac452bf9b9acaef70325e055ac006d34024b32204abea4be5faae0a6d46d365ed0d9
+X = 6e2e31bbfc670944d7a7120e39a981520614d8a8
+Y = 7e339f3757450390160e02291559f30bed0b2d758c5ccc2d8d456232bb435ae49de7e7957e3aad9bfdcf6fd5d9b6ee3b521bc2229a8421dc2aa59b9952345a8fc1de49b348003a9b18da642d7f6f56e3bc665131ae9762088a93786f7b4b72a4bcc308c67e2532a3a5bf09652055cc26bf3b18833598cffd7011f2285f794557
+K = 8cb35d255505a4c41421e562d10827266aa68663
+R = afee719e7f848b54349ccc3b4fb26065833a4d8e
+S = 734efe992256f31325e749bc32a24a1f957b3a1b
+
+[mod = L=1024, N=160, SHA-256]
+
+P = cba13e533637c37c0e80d9fcd052c1e41a88ac325c4ebe13b7170088d54eef4881f3d35eae47c210385a8485d2423a64da3ffda63a26f92cf5a304f39260384a9b7759d8ac1adc81d3f8bfc5e6cb10efb4e0f75867f4e848d1a338586dd0648feeb163647ffe7176174370540ee8a8f588da8cc143d939f70b114a7f981b8483
+Q = 95031b8aa71f29d525b773ef8b7c6701ad8a5d99
+G = 45bcaa443d4cd1602d27aaf84126edc73bd773de6ece15e97e7fef46f13072b7adcaf7b0053cf4706944df8c4568f26c997ee7753000fbe477a37766a4e970ff40008eb900b9de4b5f9ae06e06db6106e78711f3a67feca74dd5bddcdf675ae4014ee9489a42917fbee3bb9f2a24df67512c1c35c97bfbf2308eaacd28368c5c
+Msg = 812172f09cbae62517804885754125fc6066e9a902f9db2041eeddd7e8da67e4a2e65d0029c45ecacea6002f9540eb1004c883a8f900fd84a98b5c449ac49c56f3a91d8bed3f08f427935fbe437ce46f75cd666a0707265c61a096698dc2f36b28c65ec7b6e475c8b67ddfb444b2ee6a984e9d6d15233e25e44bd8d7924d129d
+X = 2eac4f4196fedb3e651b3b00040184cfd6da2ab4
+Y = 4cd6178637d0f0de1488515c3b12e203a3c0ca652f2fe30d088dc7278a87affa634a727a721932d671994a958a0f89223c286c3a9b10a96560542e2626b72e0cd28e5133fb57dc238b7fab2de2a49863ecf998751861ae668bf7cad136e6933f57dfdba544e3147ce0e7370fa6e8ff1de690c51b4aeedf0485183889205591e8
+K = 85976c5610a74959531040a5512b347eac587e48
+R = 76683a085d6742eadf95a61af75f881276cfd26a
+S = 3b9da7f9926eaaad0bebd4845c67fcdb64d12453
+
+[mod = L=1024, N=160, SHA-384]
+
+P = f24a4afc72c7e373a3c30962332fe5405c45930963909418c30792aaf135ddea561e94f24726716b75a18828982e4ce44c1fddcb746487b6b77a9a5a17f868ab50cd621b5bc9da470880b287d7398190a42a5ee22ed8d1ff147e2019810c8298ed68e1ca69d41d555f249e649fb1725ddb075c17b37beff467fdd1609243373f
+Q = da065a078ddb56ee5d2ad06cafab20820d2c4755
+G = 47b5591b79043e4e03ca78a0e277c9a21e2a6b543bf4f044104cd9ac93eff8e101bb6031efc8c596d5d2f92e3a3d0f1f74702dd54f77d3cd46c04dee7a5de9f00ad317691fddcefe4a220a2651acae7fcedda92bfcca855db6705e8d864f8192bf6bf860c00f08ad6493ecc1872e0028d5c86d44505db57422515c3825a6f78a
+Msg = b0dbbf4a421ba5c5b0e52f09629801c113258c252f29898c3354706e39ec5824be523d0e2f8cfe022cd61165301274d5d621a59755f50404d8b802371ce616defa962e3636ae934ec34e4bcf77a16c7eff8cf4cc08a0f4849d6ad4307e9f8df83f24ad16ab46d1a61d2d7d4e21681eb2ae281a1a5f9bca8573a3f5281d308a5a
+X = 649820168eb594f59cd9b28b9aefe8cc106a6c4f
+Y = 43a27b740f422cb2dc3eaa232315883a2f6a22927f997d024f5a638b507b17d3b1cbd3ec691cc674470960a0146efdecb95bb5fe249749e3c806cd5cc3e7f7bab845dadbe1f50b3366fb827a942ce6246dda7bd2c13e1b4a926c0c82c884639552d9d46036f9a4bc2a9e51c2d76e3074d1f53a63224c4279e0fa460474d4ffde
+K = 33c7ba88ff69707971b25ac344ae4a566e195f99
+R = 77c4d99f62b3ad7dd1fe6498db45a5da73ce7bde
+S = 23871a002ae503fdabaa6a84dcc8f38769737f01
+
+[mod = L=1024, N=160, SHA-512]
+
+P = 88d968e9602ecbda6d86f7c970a3ffbeb1da962f28c0afb9270ef05bc330ca98c3adf83c072feb05fb2e293b5065bbb0cbcc930c24d8d07869deaecd92a2604c0f5dd35c5b431fda6a222c52c3562bf7571c710209be8b3b858818788725fe8112b7d6bc82e0ff1cbbf5d6fe94690af2b510e41ad8207dc2c02fb9fa5cefaab5
+Q = a665689b9e5b9ce82fd1676006cf4cf67ecc56b7
+G = 267e282857417752113fba3fca7155b5ce89e7c8a33c1a29122e2b720965fc04245267ff87fc67a5730fe5b308013aa3266990fbb398185a87e055b443a868ce0ce13ae6aee330b9d25d3bbb362665c5881daf0c5aa75e9d4a82e8f04c91a9ad294822e33978ab0c13fadc45831f9d37da4efa0fc2c5eb01371fa85b7ddb1f82
+Msg = 3a84a5314e90fd33bb7cd6ca68720c69058da1da1b359046ae8922cac8afc5e025771635fb4735491521a728441b5cb087d60776ee0ecc2174a41985a82cf46d8f8d8b274a0cc439b00971077c745f8cf701cf56bf9914cc57209b555dc87ca8c13da063270c60fc2c988e692b75a7f2a669903b93d2e14e8efb6fb9f8694a78
+X = 07ce8862e64b7f6c7482046dbfc93907123e5214
+Y = 60f5341e48ca7a3bc5decee61211dd2727cd8e2fc7635f3aabea262366e458f5c51c311afda916cb0dcdc5d5a5729f573a532b594743199bcfa7454903e74b33ddfe65896306cec20ebd8427682fa501ee06bc4c5d1425cbe31828ba008b19c9da68136cf71840b205919e783a628a5a57cf91cf569b2854ffef7a096eda96c9
+K = 2f170907ac69726b14f22056dcb37b4df85f7424
+R = a53f1f8f20b8d3d4720f14a8bab5226b079d9953
+S = 11f53f6a4e56b51f60e20d4957ae89e162aea616
+
+[mod = L=2048, N=224, SHA-1]
+
+P = f2d39ed3062b13c916273600a0f2a029e86d7a4b9217b4f1815bf2b24d9710a57ab33f997294b014585b8d0198dfdccbcd75314da5ff85aa344b45adaeaa979b51a312a7bfa94472fb633f1a6f156bb4458867dfd38403f06b851f00fe2d3484077bded71ab7513d04a140220575fb693395480e4c8402b7a46cec2d37a778c305accd1f13e9f62e865315f4b22cc467c8986ec8e4961ddf810566b0c4ee369ac6aa15e43f4744005826f5bde8071a19e30b6909aac4b3d174237270dad02799d09b8a2cc5f22e66894b5422228b2c234f11f5a771c5b89cf465a2acecbbeeaa1725fe8f9b59422be8991052cb556ddf2c8ce8fa9206dbf39feadc194e00f8e5
+Q = 8000000000000000c118f49835e4ef733c4d15800fcf059e884d31b1
+G = e3a93c09da6f560e4d483a382a4c546f2335c36a4c35ac1463c08a3e6dd415df56fdc537f25fd5372be63e4f5300780b782f1acd01c8b4eb33414615fd0ea82573acba7ef83f5a943854151afc2d7dfe121fb8cd03335b065b549c5dcc606be9052483bc284e12ac3c8dba09b426e08402030e70bc1cc2bf8957c4ba0630f3f32ad689389ac47443176063f247d9e2296b3ea5b5bc2335828ea1a080ed35918dee212fd031279d1b894f01afec523833669eac031a420e540ba1320a59c424a3e5849a460a56bcb001647885b1433c4f992971746bfe2977ce7259c550b551a6c35761e4a41af764e8d92132fcc0a59d1684eab90d863f29f41cf7578faa908c
+Msg = edc6fd9b6c6e8a59f283016f7f29ee16deeaa609b5737927162aef34fed985d0bcb550275637ba67831a2d4efccb35296dfe730f4a0b4f4728d1d7d1bb8f4a36238a5c94311fa1134a93a6b4de39c085e9f60ae4e237c0416d58042bb36baa38cba8c896295b745d5376fd8ce42eb6ee5a1b38f87716b265b76e58cfb24a9170
+X = 6132e551cdac88409183bd37ee1452cd247d4834b08814b275be3ff5
+Y = 289ff18c32a56bb0b8839370647683a38a5a7e291410b93207212adc8088d30f93e9e4abc523f3d46936e7d5c90d88742b36afd37563408f15c8c1a4f7ac24bf05f01008ffee70c8825d57c3a9308bad8a095af2b53b2dda3cbed846d95e301eb9b84766415d11f6c33209a0d28571096ab04a79aa0dc465997529686b68e887cd8a205c2dc8195aef0422eba9979f549ac85548e419413643b7244361153ada1480d238cd00dc16527938955548dd5d027ded1029eeeb8ed6c61b4cd59341d8b15466e9da890a989996f4d7691e6072de136af28b5874bf08bd1f8a60cfb1c00888132909f515e04bce81b02951aa41baac68ffdb8c5dc77a1d32d8f2c10dd7
+K = 7197392d32d0af6a7183cc3398556f8f687d86a8ff742be6ad38562f
+R = 45df2f423e94bf155dd4e1d9e63f315ea606dd38527d4cf6328738c8
+S = 59b3e8efa5bc0ccbf4a3cbb6515c4b9bf784cfacdcc101dc9f81d31f
+
+[mod = L=2048, N=224, SHA-224]
+
+P = aa815c9db1c4d3d2773c7d0d4d1da75ecfc4a39e97d5fa191ffec8b1490a290ce335e5ce87ea620a8a17de0bb64714e2ec840bf00e6ebdb4ffb4e324ca07c3c8717309af1410362a772c9add838b2b0cae1e90ab448adabdacd2e5df59c4187a32a23719d6c57e9400885383bf8f066f23b941920d54c35b4f7cc5044f3b40f17046956307b748e840732844d00a9ce6ec5714293b6265147f15c67f4be38b082b55fdeadb6124689fb76f9d25cc28b8eaa98b562d5c1011e0dcf9b39923240d332d89dc9603b7bddd0c70b83caa2905631b1c83cabbae6c0c0c2efe8f58131ed8351bf93e875f6a73a93cbad470141a2687fbacf2d71c8ddee971ad660729ad
+Q = ea347e90be7c2875d1fe1db622b4763837c5e27a6037310348c1aa11
+G = 2042094ccbc8b8723fc928c12fda671b83295e99c743576f44504be1186323319b5002d24f173df909ea241d6ea5289904ee4636204b2fbe94b068fe093f7962579549551d3af219ad8ed19939eff86bcec834de2f2f78596e89e7cb52c524e177098a56c232eb1f563aa84bc6b026deee6ff51cb441e080f2dafaea1ced86427d1c346be55c66803d4b76d133cd445b4c3482fa415023463c9bf30f2f784223e26057d3aa0d7fbb660630c52e49d4a0325c7389e072aa349f13c966e159752fbb71e9336890f93243fa6e72d299365ee5b3fe266ebf1110568fee4425c847b50210bd484b97431a42856adca3e7d1a9c9c675c7e266918320dd5a78a48c48a9
+Msg = e920fc1610718f2b0213d301c0092a51f3c6b0107bbbd8243a9689c044e2d142f202d9d195a5faef4be5acadc9ff6f7d2261e58b517139bcb9489b110423c2e59eb181294ffdae8aad0e624fab974c97f9f5e7dc19d678a9cb3429cf05ec509072856f5adfec6e29bafe8e5ba95593e612843e343111d88a1eaff7dc0a2e277f
+X = 7b489021578e79e7bd3ee7ab456f659f3dc07c88f5c9a39e4f8cee81
+Y = 1ae10c786ad0902c5c685dae5c7121418a377b888b5f2f2bc76623570fd62bcb190b471ad5359c5f062f8819289e956d8aa6f90d1f8cf1ee72d3a1bdfd56c478dc29a19c4569b5a60e3a8f34f60656eac5b25dde5514a5c67b675423204f6ccaf0990617cc7355b9d3ed868978a252020a769ed59a6edaa6efe3377eef45f3f6f3e64179cc7db8b143fb835c5d71bfcfa1e2a9049bccf7fe9ab57546220fe3f4b7521c861739d138507e81a46a6993605441dcb90d6ee4afbc42cabe90a254444968109d7edd9694a023239f1d56175dd1fac115915e24fab563f4fc3f269bed2f300832d112596485a711417aa73bb4ac72a651a1fa5baed3636c720d397008
+K = 37fadd419fcbd2b073a06ae96b9eceb63e29aee9ac5fa2bdb31ab85d
+R = 65102e8f64ecb11f06017b1a0c0def3c29897c277c4a948b1f4da6b9
+S = 21ad0abb27bd3c21166cb96aef70c0dbd5f3079cab0dd543d4125bd1
+
+[mod = L=2048, N=224, SHA-256]
+
+P = a4c7eaab42c4c73b757770916489f17cd50725cd0a4bc4e1cf67f763b8c1de2d6dab9856baafb008f365b18a42e14dc51f350b88eca0209c5aa4fd71a7a96c765f5901c21e720570d7837bec7c76d2e49344731ca39405d0a879b9e0dcd1a8125fd130ec1e783e654b94e3002e6b629e904ab3877867720cbd54b4270a9e15cd028c7cc796f06c272a660951928fdbeb2dca061b41e932257305742ff16e2f429191d5e5f1a6ddf6e78c5d7722cff80a9c0bd5c8d7aeba8c04438992b075e307c1534c49ad380f477f5f7987dc172c161dca38dcaf3fb3846c72c9119a5299adc748951b3dce0d00d4a9013800b2008203b72465bc6a84ae059a30c4522dea57
+Q = ce89fe332b8e4eb3d1e8ddcea5d163a5bc13b63f16993755427aef43
+G = 8c465edf5a180730291e080dfc5385397a5006450dba2efe0129264fbd897bb5579ca0eab19aa278220424724b4f2a6f6ee6328432abf661380646097233505339c5519d357d7112b6eec938b85d5aa75cc2e38092f0a530acb54e50fe82c4d562fb0f3036b80b30334023ebbe6637a0010b00c7db86371168563671e1e0f028aedbd45d2d572621a609982a073e51aae27707afbeef29e2ecee84d7a6d5da382be3a35f42b6c66849202ab19d025b869d08776476d1ab981475ad2ad2f3e6fd07e30696d90a626816df60d6ca7afd7b482f942f83b45cc82933731f87faee320900f2aa3e70b1867e1430e40be67c07f9290299ef067b8b24a7515b3f992c07
+Msg = cec8d2843dee7cb5f9119b75562585e05c5ce2f4e6457e9bcc3c1c781ccd2c0442b6282aea610f7161dcede176e774861f7d2691be6c894ac3ebf80c0fab21e52a3e63ae0b35025762ccd6c9e1fecc7f9fe00aa55c0c3ae33ae88f66187f9598eba9f863171f3f56484625bf39d883427349b8671d9bb7d396180694e5b546ae
+X = 551595eccbb003b0bf8ddda184a59da51e459a0d28205e5592ca4cb1
+Y = 748a40237211a2d9852596e7a891f43d4eb0ee48826c9cfb336bbb68dbe5a5e16b2e1271d4d13de03644bb85ef6be523a4d4d88415bcd596ba8e0a3c4f6439e981ed013d7d9c70336febf7d420cfed02c267457bb3f3e7c82145d2af54830b942ec74a5d503e4226cd25dd75decd3f50f0a858155d7be799410836ddc559ce99e1ae513808fdaeac34843dd7258f16f67f19205f6f139251a4186da8496d5e90d3fecf8ed10be6c25ff5eb33d960c9a8f4c581c8c724ca43b761e9fdb5af66bffb9d2ebb11a6b504a1fbe4f834ecb6ac254cab513e943b9a953a7084b3305c661bfad434f6a835503c9ade7f4a57f5c965ec301ecde938ee31b4deb038af97b3
+K = 6f326546aa174b3d319ef7331ec8dfd363dd78ae583a920165ff7e54
+R = 9c5fa46879ddaf5c14f07dfb5320715f67a6fec179e3ad53342fb6d1
+S = c3e17e7b3c4d0ac8d49f4dd0f04c16a094f42da0afcc6c90f5f1bbc8
+
+[mod = L=2048, N=224, SHA-384]
+
+P = a6bb5333ce343c31c9b2c878ab91eef2fdea35c6db0e716762bfc0d436d87506e865a4d2c8cfbbd626ce8bfe64563ca5686cd8cf081490f02445b289087982495fb69976b10242d6d50fc23b4dbdb0bef78305d9a4d05d9eae65d87a893eaf397e04e39baa85a26c8ffbdef1233287b5f5b6ef6a90f27a69481a932ee47b18d5d27eb107ffb05025e646e8876b5cb567fec1dd35835d42082198531fafbe5ae280c575a1fb0e62e9b3ca37e197ad96d9dde1f33f2cec7d27deae261c83ee8e2002af7eb6e82f6a14796af037577a1032bbc709129caabd8addf870ae2d0595c8fdb37155748f0dea34b44d4f82ed58c2f5b1b8481662ac53473c693410082fbd
+Q = 8c3ee5bd9a2aaf068bd5845bd55ecf27417055307577bbc3770ec68b
+G = 43b5a6b6d0bb962ec9766a377c32cc4124f1311188c2ecf95c0cd4a4fa097225b7618cb1276c474578d3bf564c145199c092a1b14baa929c2f3f0f36e0c2dae91eba08be30992a889f2952e0442c37af484a4ecdc3243ccfcb9e3413cf5cdd6630b09fe17efbfde14d8725493019b7b73d1f782b48ef30bec36e00e02ba336d2254fc202a69612cd9446f91d76b739ffa6d8b86052f8dc5f1145801c56241af5ba9037241bd89e6338b58e01310671c268eb5e33acb57d1f99f16440a675827d4017754d601a17ada2fbedf904554a90b01530da8c93cd14ce293cb2bd3e7937e934b79e310fe4d80c13f92f63381355bd80a1abee1a73fdfb6da24ef28002a3
+Msg = df5d564db83592c1128be5d29b7036880d55e834a291a745ed8dcd438c4da6b1b9f39412b2c5110730db83c1ccdfe9059dd96ec7ea2bbcb34e3eba72ef0a1d4721c7c0221e29279f014d63facc5bc8f18c539b92ff2af89e568225d6b4cf599cb3dff5e3c6ddfac0a27f10f636ec220abb72630bae9a39c18fd3663e4651ccac
+X = 4efa5136eb6aa74e92bbfc913b0bfebb613db7a47221fb7b64f42e6f
+Y = 647979b7960ce7b971ff0e5f6435f42a41b18c9de09a301114a013a7cd01183f176f88838379dcb4efb67daea79def3f042cbcf9cc503b4c2151a2364f7c9437b19643e67e24a36bac4a4cfa293deedf8ec6b154a32aa72985f7d8de235334b546c29def458c55d0c5c0ac5d74e2024ec7d4abc2fda516a2a0b1a4d886ad92c204707828a4fc7794f60ee8a4be1101c9e5518f7e19eebd475f2de6f6ba89c28bd129f13993befe5818440319a79549833196342a31dbaf7d79497dec65ee7dbef70e58f99d0595f6a711409ade3151d45563d53c1cd0a8ab1a18beff6502cbb0c069b114ea7be77898d0f4e549991ba0b368971b1072ece4afc380e9ae329a50
+K = 7e0f1ce21d185ae65c0a00395567ea9cf217462b58b9c89c4e5ff9cf
+R = 5ab43ede66a15688146d1f4cd7164702c0c4457bd4fddebac0482953
+S = 6c58e8ab27d28512c46063c96bf5bceb8fbad232d8f5b39c4755d0b1
+
+[mod = L=2048, N=224, SHA-512]
+
+P = bfebd000b2d6cd4ab38efba35df334df721d6c2f2b3d956679cbad009f3dfbd002952cc899cc2356ec8769bd3d1ba5a73023729888da92ca48a5ee94c97f4f04a2e3acb4f33a2f0fb3783c31f2c70fa7c70f38214a27dadec8b12e67996a9e85ee3bb148803130147392dc5253c04d7063535e6cd646bfb186984e08b58b74a7be5b333bf32b0abfd5665360e9a923a0c528ff1c62c7253458f5678528719d436e50148741f45dc7dd2c6cac71c55231f12a83fefd2ed0a33ede1b8a51f566fcf7890682cdc1931dc207c92bf2ef4e28ab31661eeb77f1601eea941c9591f038d3f00d912857db05e64b2ad569320061c6f863ff3354d842e7e7ea715afef8d1
+Q = aa986df8a064278e9363316a9830bcfa490656faa6d5daa817d87949
+G = 8195ad9a478fd985216ee58368366d2edd13c12b3d62239169fa042d91156408b483122f44ed6236b8308a6cdb52f9af3de88ec89e039afad7da3aa66c1976049a8e0a7d18d567baf99fcefe315cada01548386b10b25e52f52ed78eb4d28082e5e1ffee9480c4fe2cc4aafd1efc9d4fd2cc6d155968931271ef15b3240e7fb043a80c8f628befe09d645077c1029d21e0ac8bf0ba9c27714d1b580ede594aa01b3b76f6e745fc1ec07db37e2fd7e98c6c8c6915228e422c309de9f5db168f50249d1be1ed3298090808e2ebb896bb79b8c4cbf94d4c2064e37e612ba4449d7ac210edde211416d64b051dd8046ab041732665411a7f154d31b3e11a51da7fc0
+Msg = e9f59c6a5cbe8f5b0cf75008d06a076a6739bdddb39b82143cd03939aa4738a287c2a6f31829bbe15f02cc2ee7d7122dbd132825970daddd8a4d851da86e7edc8940cb1188319218b8e0248a103eae34bc68d85f5a32830d7e5dc7718f74db5e4224c0debe1e841e1eea1a88fee0f85d9fb087cbcee55f86037a646e38346d2b
+X = 6a5b4ffc44238d1852fb9b74e4c1661be85984043cfeee023f57cac6
+Y = af6721bf75dec6a1b76ad35ca3750def31117c5b441c15a306835a1db74c003b86ae9099ebfb745b0aa9cb000cf43fb021513b8f197bc865b22bf949b491809ad752ffc1ca8e54bea16dc7f539e4c55fb70a7743dd28f262f60ef0f2fcaac29e8021a7938c18ffe03075d0b7e0a2b4dcabe46ed1953d33e37f113af519ab0bf0b6186c12b5f6488437f5193096e2fd6a6a1835604794c66b42ae5265c1cf1cb53ae84997975e0318a93ce41e3902e4ef54de3c56555bd19491acd53f3e57464e1f460389dbc5fa80648fa5a5a0f2956e9ec3b8dc441b535c641c362eed770da828649bfd146472b0f46a4c064e459f88bff90dede7ec56177a9a71d167948712
+K = 9ced89ea5050982222830efef26e7394f5ab7d837d4549962d285fae
+R = 9da9966500de9d3b6b7f441ca550233fc450944bc507e01cd4acb030
+S = 2d72f1f6681e867f7d8beaebeba4bc5b23287604a64cfee1c164595a
+
+[mod = L=2048, N=256, SHA-1]
+
+P = c1a59d215573949e0b20a974c2edf2e3137ff2463062f75f1d13df12aba1076bb2d013402b60af6c187fb0fa362167c976c2617c726f9077f09e18c11b60f65008825bd6c02a1f57d3eb0ad41cd547de43d87f2525f971d42b306506e7ca03be63b35f4ada172d0a06924440a14250d7822ac2d5aeafed4619e79d4158a7d5eb2d9f023db181a8f094b2c6cb87cb8535416ac19813f07144660c557745f44a01c6b1029092c129b0d27183e82c5a21a80177ee7476eb95c466fb472bd3d2dc286ce25847e93cbfa9ad39cc57035d0c7b64b926a9c7f5a7b2bc5abcbfbdc0b0e3fede3c1e02c44afc8aefc7957da07a0e5fd12339db8667616f62286df80d58ab
+Q = 8000000000000000000000001bd62c65e8b87c89797f8f0cbfa55e4a6810e2c7
+G = aea5878740f1424d3c6ea9c6b4799615d2749298a17e26207f76cef340ddd390e1b1ad6b6c0010ad015a103342ddd452cac024b36e42d9b8ed52fafae7a1d3ce9e4b21f910d1356eb163a3e5a8184c781bf14492afa2e4b0a56d8884fd01a628b9662739c42e5c5795ade2f5f27e6de1d963917ce8806fc40d021cd87aa3aa3a9e4f0c2c4c45d2959b2578b2fb1a2229c37e181059b9d5e7b7862fa82e2377a49ed0f9dca820a5814079dd6610714efaf8b0cc683d8e72e4c884e6f9d4946b3e8d4cbb92adbbe7d4c47cc30be7f8c37ca81883a1aac6860059ff4640a29ccae73de20b12e63b00a88b2ee9ba94b75eb40a656e15d9ec83731c85d0effcb9ef9f
+Msg = de3605dbefde353cbe05e0d6098647b6d041460dfd4c000312be1afe7551fd3b93fed76a9763c34e004564b8f7dcacbd99e85030632c94e9b0a032046523b7aacdf934a2dbbdcfceefe66b4e3d1cb29e994ff3a4648a8edd9d58ed71f12399d90624789c4e0eebb0fbd5080f7d730f875a1f290749334cb405e9fd2ae1b4ed65
+X = 5a42e77248358f06ae980a2c64f6a22bea2bf7b4fc0015745053c432b7132a67
+Y = 880e17c4ae8141750609d8251c0bbd7acf6d0b460ed3688e9a5f990e6c4b5b00875da750e0228a04102a35f57e74b8d2f9b6950f0d1db8d302c5c90a5b8786a82c68ff5b17a57a758496c5f8053e4484a253d9942204d9a1109f4bd2a3ec311a60cf69c685b586d986f565d33dbf5aab7091e31aa4102c4f4b53fbf872d700156465b6c075e7f778471a23502dc0fee41b271c837a1c26691699f3550d060a331099f64837cddec69caebf51bf4ec9f36f2a220fe773cb4d3c02d0446ddd46133532ef1c3c69d432e303502bd05a75279a7809a742ac4a7872b07f1908654049419350e37a95f2ef33361d8d8736d4083dc14c0bb972e14d4c7b97f3ddfccaef
+K = 2cb9c1d617e127a4770d0a946fb947c5100ed0ca59454ea80479f6885ec10534
+R = 363e01c564f380a27d7d23b207af3f961d48fc0995487f60052775d724ab3d10
+S = 4916d91b2927294e429d537c06dd2463d1845018cca2873e90a6c837b445fdde
+
+[mod = L=2048, N=256, SHA-224]
+
+P = d02276ebf3c22ffd666983183a47ae94c9bccbcbf95ddcb491d1f7ce643549199992d37c79e7b032d26ed031b6ba4489f3125826fafb2726a98333ebd9abdde592d8693d9859536d9cc3841a1d24e044d35aced6136256fc6d6b615cf4f4163aa381eb2b4c480825a8eccc56d8ddcf5fe637e38ad9b2974bd2cf68bf271e0d067d2465a8b6b660524f0082598945ada58ea649b9804eb4753408c2c59768c46abb82e3295f3d9ca469f84cc187f572dc4b5a3b39346ec839dfad6f07d6d1f0e215209bb0ecc05c767cf2e7943ac9cfb02eee1e9ef5946e8ce88316b5e15fdcf95a132ef2e4bb0817136528cfa5dd96532f9c3abe5c421620edb6bcbd52234ca9
+Q = 8000000012997e8285e4089708f528070c6d7af8a0bd01409e7a079cdb6fc5bb
+G = 778453049ef262147fed7b59b0ee6764607c51e7b5b5fc6fea7a7a7b1dd6bb283f4a9ae98efd3964b1556758cb15b2a53af8619e74d85898bec77d3b3f382494ae5961a13ffc745da386182291519800f99dd710e00aeb15adee088e2798ee2e46f598526cf0f4667055d1ba009750041dc5cdd2725ff1d97dd340c8518af7671b87d39d67aeced84b66f84e0701efc82a5c9ef954ee576d24c385b14d63037f0d866fd424b4975bdd5485ed740cb932e843f906683f7c7b2c74775d901c361b847b519c0da699638da40bd736b783d2710b2c2cc26ef91271bf4e2c1929f876e902e2057164223bc78d6a2b9f6c0c7a7cb85922f7d6c4287ae23861f8128848
+Msg = 39f2d8d503aae8cd17854456ecfad49a18900d4375412bc689181ed9c2ccafea98dca689a72dc75e5367d3d3abfc2169700d5891cff70f69d9aca093b061b9f5057f94636bc2783115254344fb12e33b167272e198838a8728e7744ea9a2e8248e34d5906e298302472637b879de91c1a6f9f331a5cf98a5af29132990d27416
+X = 6ba81e6cd4367798aaab8b7af1135183a37c42a766dbd68cd2dce78f2670ef0f
+Y = 7bb31e98c7a0437f978a73d5dcfbdfbb09cc2499dfaf1eb5256bccd6358cabb5f67d04a42823463b7e957f2b9213f1fa8e5a98d614484701abb8c7d67641fe6ed06fa4527b493ddab2e74640fde3de70da693f1db2b8e26417040af0eea6cab451a795a52e187d2ee241b93f65c86c6d66f45834cce165ac5eb670d4f0095c23ce9757e3bdc636f991ee0073d90a09202edb35cc3ea1cf9adca1617fa0bffd9c126229a604a1d3bf4931ddf0b9942dfc8a2f8c09fcc97032564a79ae1ebe1e2ce49ff57839e7c43fa60b1603d15a450898aa4e4a1ee8065794126d64f013367096a83686b9f158c33b10f5f3b36cf1f6358b3f34f84b101dc26d3db68bcc95c8
+K = 45030b79a395b1632700cbaffead97998d02bed8e0656876fc0174e4bdb96f79
+R = 059bee9e708b7f20c3f791a640edee964e0aa672893c484799715817b3a8f6d4
+S = 4bd41c84a724cc86e4f0194ec0fbf379e654d0d7f6a1f08bd468139422a5c353
+
+[mod = L=2048, N=256, SHA-256]
+
+P = a8adb6c0b4cf9588012e5deff1a871d383e0e2a85b5e8e03d814fe13a059705e663230a377bf7323a8fa117100200bfd5adf857393b0bbd67906c081e585410e38480ead51684dac3a38f7b64c9eb109f19739a4517cd7d5d6291e8af20a3fbf17336c7bf80ee718ee087e322ee41047dabefbcc34d10b66b644ddb3160a28c0639563d71993a26543eadb7718f317bf5d9577a6156561b082a10029cd44012b18de6844509fe058ba87980792285f2750969fe89c2cd6498db3545638d5379d125dccf64e06c1af33a6190841d223da1513333a7c9d78462abaab31b9f96d5f34445ceb6309f2f6d2c8dde06441e87980d303ef9a1ff007e8be2f0be06cc15f
+Q = e71f8567447f42e75f5ef85ca20fe557ab0343d37ed09edc3f6e68604d6b9dfb
+G = 5ba24de9607b8998e66ce6c4f812a314c6935842f7ab54cd82b19fa104abfb5d84579a623b2574b37d22ccae9b3e415e48f5c0f9bcbdff8071d63b9bb956e547af3a8df99e5d3061979652ff96b765cb3ee493643544c75dbe5bb39834531952a0fb4b0378b3fcbb4c8b5800a5330392a2a04e700bb6ed7e0b85795ea38b1b962741b3f33b9dde2f4ec1354f09e2eb78e95f037a5804b6171659f88715ce1a9b0cc90c27f35ef2f10ff0c7c7a2bb0154d9b8ebe76a3d764aa879af372f4240de8347937e5a90cec9f41ff2f26b8da9a94a225d1a913717d73f10397d2183f1ba3b7b45a68f1ff1893caf69a827802f7b6a48d51da6fbefb64fd9a6c5b75c4561
+Msg = 4e3a28bcf90d1d2e75f075d9fbe55b36c5529b17bc3a9ccaba6935c9e20548255b3dfae0f91db030c12f2c344b3a29c4151c5b209f5e319fdf1c23b190f64f1fe5b330cb7c8fa952f9d90f13aff1cb11d63181da9efc6f7e15bfed4862d1a62c7dcf3ba8bf1ff304b102b1ec3f1497dddf09712cf323f5610a9d10c3d9132659
+X = 446969025446247f84fdea74d02d7dd13672b2deb7c085be11111441955a377b
+Y = 5a55dceddd1134ee5f11ed85deb4d634a3643f5f36dc3a70689256469a0b651ad22880f14ab85719434f9c0e407e60ea420e2a0cd29422c4899c416359dbb1e592456f2b3cce233259c117542fd05f31ea25b015d9121c890b90e0bad033be1368d229985aac7226d1c8c2eab325ef3b2cd59d3b9f7de7dbc94af1a9339eb430ca36c26c46ecfa6c5481711496f624e188ad7540ef5df26f8efacb820bd17a1f618acb50c9bc197d4cb7ccac45d824a3bf795c234b556b06aeb929173453252084003f69fe98045fe74002ba658f93475622f76791d9b2623d1b5fff2cc16844746efd2d30a6a8134bfc4c8cc80a46107901fb973c28fc553130f3286c1489da
+K = 117a529e3fdfc79843a5a4c07539036b865214e014b4928c2a31f47bf62a4fdb
+R = 633055e055f237c38999d81c397848c38cce80a55b649d9e7905c298e2a51447
+S = 2bbf68317660ec1e4b154915027b0bc00ee19cfc0bf75d01930504f2ce10a8b0
+
+[mod = L=2048, N=256, SHA-384]
+
+P = a6167c16fff74e29342b8586aed3cd896f7b1635a2286ff16fdff41a06317ca6b05ca2ba7c060ad6db1561621ccb0c40b86a03619bfff32e204cbd90b79dcb5f86ebb493e3bd1988d8097fa23fa4d78fb3cddcb00c466423d8fa719873c37645fe4eecc57171bbedfe56fa9474c96385b8ba378c79972d7aaae69a2ba64cde8e5654f0f7b74550cd3447e7a472a33b4037db468dde31c348aa25e82b7fc41b837f7fc226a6103966ecd8f9d14c2d3149556d43829f137451b8d20f8520b0ce8e3d705f74d0a57ea872c2bdee9714e0b63906cddfdc28b6777d19325000f8ed5278ec5d912d102109319cba3b6469d4672909b4f0dbeec0bbb634b551ba0cf213
+Q = 8427529044d214c07574f7b359c2e01c23fd97701b328ac8c1385b81c5373895
+G = 6fc232415c31200cf523af3483f8e26ace808d2f1c6a8b863ab042cc7f6b7144b2d39472c3cb4c7681d0732843503d8f858cbe476e6740324aaa295950105978c335069b919ff9a6ff4b410581b80712fe5d3e04ddb4dfd26d5e7fbca2b0c52d8d404343d57b2f9b2a26daa7ece30ceab9e1789f9751aaa9387049965af32650c6ca5b374a5ae70b3f98e053f51857d6bbb17a670e6eaaf89844d641e1e13d5a1b24d053dc6b8fd101c624786951927e426310aba9498a0042b3dc7bbc59d705f80d9b807de415f7e94c5cf9d789992d3bb8336d1d808cb86b56dde09d934bb527033922de14bf307376ab7d22fbcd616f9eda479ab214a17850bdd0802a871c
+Msg = 8c78cffdcf25d8230b835b30512684c9b252115870b603d1b4ba2eb5d35b33f26d96b684126ec34fff67dfe5c8c856acfe3a9ff45ae11d415f30449bcdc3bf9a9fb5a7e48afeaba6d0b0fc9bce0197eb2bf7a840249d4e550c5a25dc1c71370e67933edad2362fae6fad1efba5c08dc1931ca2841b44b78c0c63a1665ffac860
+X = 459eb1588e9f7dd4f286677a7415cb25a1b46e7a7cfadc8a45100383e20da69d
+Y = 5ca7151bca0e457bbc46f59f71d81ab16688dc0eb7e4d17b166c3326c5b12c5bdebb3613224d1a754023c50b83cb5ecc139096cef28933b3b12ca31038e4089383597c59cc27b902be5da62cae7da5f4af90e9410ed1604082e2e38e25eb0b78dfac0aeb2ad3b19dc23539d2bcd755db1cc6c9805a7dd109e1c98667a5b9d52b21c2772121b8d0d2b246e5fd3da80728e85bbf0d7067d1c6baa64394a29e7fcbf80842bd4ab02b35d83f59805a104e0bd69d0079a065f59e3e6f21573a00da990b72ea537fa98caaa0a58800a7e7a0623e263d4fca65ebb8eded46efdfe7db92c9ebd38062d8f12534f015b186186ee2361d62c24e4f22b3e95da0f9062ce04d
+K = 2368037a1c7647c683d7e301ac79b7feebc736effe3ab1644b68308b4b28620d
+R = 4fd8f25c059030027381d4167c3174b6be0088c15f0a573d7ebd05960f5a1eb2
+S = 5f56869cee7bf64fec5d5d6ea15bb1fa1169003a87eccc1621b90a1b892226f2
+
+[mod = L=2048, N=256, SHA-512]
+
+P = f63da3be9a9616196c6556f3ce6fd8b98bdda9137473da46fed970e2b8d147387a81922065d528a7d6433ebc5e35b15c67ea35a5a5bff5b9cef1cd1e6fe31dda52838da3aa89b9b4e8d9d3c0732ccc4f238ce1b416c4ca93f2c6800e5f4ed41c4f7615cec5531b98680b20dc63f73e70d803aacfaece33d45fa0e39d77c8508209528b9046b5917010791234397e412d22bc0b8d67cbd1cd28a32c2460a0bd86aaba0eea80e16e3245643171e34221760c203a56b8207a1009e6c1a2f6cda85f85c4f9e410b9499233c0ee072e465af4fb4fb9282c5c10e8234fd630ea92f0aae6b97a520db34475707b79a4c175265c0356ccbca827e3837df3d6d0576d9079
+Q = 9b7463f8269f0b909abed10991684f36a64ac864e0d6d717c0ef21577a4c3907
+G = 972a75f606e8aa3a91ff08fd131a20f5963251304e3d1431b712fa0803d527fd710fb7eb27e52904971cd43ca977199a24dbeeb4b7bc2ba075d3b72eb6b2c5ad8f0e8b8f48c50b554c7e0711f4c7416330806672498f430292724bf98a8ea48c7f53d7b31d8b7528b1a6f087d2c27c335202835b1e314225b37aef8bfcec7d80920c4a460a3d68344ded75ed9ee867fa2a6945063894f563b68633b8b39f83a1aaaf5a96c7f422687e7c84cf8fb8cc5f4504dff087bcb26a95bbf8583f03b3a0e43a356b2bd7e25cdddf7a015300faecc6793c5ee99b6327cb8456e32d9115339d5a6b712b7f9d0301acb05133e3115e454d3a6dd24a1693c94aab5406504bf7
+Msg = 8ab01510cfa33cfa5bcff003bba39996fa727693abf6ac010bb959b0b59a15306c0c3a1921af2a76717aa55b39fa3723f4c3229ca9acf6b741614bb551cde8a7220ab97d4b453bec1e05a0eaa42e382bbc7b9b84f8237dc8964ee5b66e9b2a4ca61cf675140efef54fb327a665def8d57ab097e8c53c643fcb58209c4215b608
+X = 5f6e545daef6cd1b8d9848dd98758807236ac0b7ff053b32c703eaa3b1147557
+Y = 41197ce2233d7e48c803cd64c78f657923b9e36b871401f8661c21d8ba38c6b9b3239db767b11d1d401e5faecbf7a45860cc5f1a54d60286b7d6e1c99fd5b8c84ed851c5357d41ad60163f224d78c996143fff89dd3a8fe123dae1f621427fd8cce76ed138d68fa248f374ae233249625b93f3dd5937d15e541b7effa4df4fea7d52faced615bfe0348418ff93e69a20a52e55c76cc30f307f84e71e4aabc0825eca3a95b4bd58ebfb0029d23a169e9d80ba7d1c5fd35395e6602e089aa9918f08bae35ae1cac7af33694129e98f0dadadd90eaeb6eed25024390b1a60af794734c397b0f509865b134b2867c115d6f489b6dd7e3c82994b45dce2a23c6bc902
+K = 5fe61afddbdf04449b24295a52a1a037d3f31441a3cec138b7f0102db86ef132
+R = 6a47ea57ceaecc116d7190ff6c6dd9831ab75b4bf6cb291083e4268b486ed245
+S = 017355f698a32abe9a4d4a7dda7c85950cddc348ab8a6751e72fddc01aa5d1f0
+
+[mod = L=3072, N=256, SHA-1]
+
+P = fd5a6c56dd290f7dd84a29de17126eb4e4487b3eff0a44abe5c59792d2e1200b9c3db44d528b9f7d2248032e4ba0f7bfc4fafc706be511db2276c0b7ecffd38da2e1c2f237a75390c1e4d3239cba8e20e55840ecb05df5f01a1b6977ad1906f2cb544ccfb93b901ad0966b1832ad2dab526244a3156c905c01ac51cb73b9dcd9860d56175a425d846485d9b1f44a8a0c2578e6cf61947bc1a1392fdd320b16a9d70455fe436f2d47ded8e8e605f7486eb578ea7fc4ffd13c07f9996af159fd411e9451403278dd1141a8c926b35c96384bbd6bee09c46f44c36b1ffc7197f5e925dbe0544a68e6ab8c18e426a466b392f9c27dd79fefa9ca163cc5a375539a8559f277f657a535d1964c6a5e91683ef5698ebaa01ef818dbf72cb04c3ff092d188866f25cd405108f566b087f73d2d5beb51fac6de84ae5161a66af9602c7e4bfc146f4820bdfc092faeac69133e4a08a5b202a12498a22e57bad54674ed4b510109d52b5f74e70e1f6f82161718cd4cf00cc9f1958acc8bddcdfbd1fbe46cd1
+Q = 800000000000000000000000334a26dd8f49c6811ce81bb1342b06e980f64b75
+G = 99ab030a21a5c9818174872167641c81c1e03c9b274cfbc27bc472542927766de5fa0539b3b73f3f16ac866a9aec8b445ded97fbff08834ed98c77e7fc89e5dc657bef766ff7fbf8e76873e17bee412762d56fe1141760ab4d25bafd4b6ef25b49a3506632d1f8e10770930760ec1325932c5a4baf9e90154264ddf442ec5c41fed95d11525151dbcfb3758149bad81c62b9cff7816b8f953b8b7c022590d1584e921dc955f5328ac72983ed5cf0d04056fe0d531e62f8f6c9ab3c0fcd44e14860b7311d2561c77c1d32f6c69dc8f77968c9d881ad9db5e0c114fda8628bca0335eb7fb9e15e625aabab58fc01194c81bf6fb2ce54077b82250e57c6a7b25deb6ee39d4b686a5c307a7612b2d85ee92512413dea297e44f317be7ceb70a3328af0b401001a418562b8ffe4e9771b4b4a8e0b40c791349d5d4e459fe620a1a2fc72e2f6ca28567d4c2632bbde1b49864c06bb12619f132c1da8f571ef613eac739f66ab3914cb3fa1ab86e05e5082ebaa24ebeea4cf51beefc27df512fe3fee7d
+Msg = ca84af5c9adbc0044db00d7acfb1b493aab0388ffbad47b38cd3e9e3111cfe2cda2a45f751c46862f05bdcec4b698adfd2e1606e484c3be4ac0c379d4fbc7c2cda43e922811d7f6c33040e8e65d5f317684b90e26387cf931fe7c2f515058d753b08137ff2c6b79c910de8283149e6872cb66f7e02e66f2371785129569362f1
+X = 433cfd0532ccfd8cdd1b25920d2bb7396987b766240379035b0e86527ce9c52d
+Y = e7c2ee18c3aa362c0182c6a56c2584628083c73e045beda8d653690c9c2f6544edf9702c57c455273905336a5f5171107a313cd7d0b0f50f8d3342c60219f22a9023394059d05f464c4496d55dab6eb0898527ff4cf5678e7b5bfb5e18d92c4a9d73288cce14530fc4702f6d0397ec39a880c4a72d358730c56633386ede028023c1791f3164d1574e7823c79b8a3ca1343ea166ba6f02b7ff7e9ef2198db107f7cc159f3b6a1c00a78c355c566deb0ac6fde3f633cb9177a1fbc6c1766ca021d5fec470101abb440d2f06982181a8c92b7cdd765336b9a1e1ab70283d6db0a963fb648c37c4e29a74c37577291049ab47cdbc104c04db966681ea8ebb9f00cf4c4a5462117379575fbda4b801979451fa94b19b4e93656705c0f734f3e0914bb96c1e2b8a0fb68faf14296efdf3300ad95bcde8b67cc4b26e6488eef925cfaeac6f0d6567e8b41355f89d1c2b8fe687bfa2df5e287e1305b89b8c388c26196090ac0351abc561aadc797da8ccea4146c3e96095ebce353e0da4c55019052caa
+K = 40f503abd70fd49a76c67a83e08b062b3fd465ad92be433c080e5f295bb9f559
+R = 21ca148cdf44be4ae93b2f353b8e512d03ad96dafa80623fde4922a95f032732
+S = 73e48b77a3aa44307483c2dd895cb51db2112177c185c59cb1dcff32fda02a4f
+
+[mod = L=3072, N=256, SHA-224]
+
+P = f63b3cdd646d8e7ddb57216aa6eec2134d707488a1f29cfa9970645f1227ea5db2e318eea5da1687c7ed90509669345ed6134cff32203ab72aecbfa693d216aeb55d8d28a981f4abff07d1319a799be5dd746f84842817929c305b408598af12045daa2f1ccc8be4d81b513c630f017fec1658aca108a1af6120ec05e3018c4253c9dd35bce062b73d0f2a93d41c481a5c43bb97909682d39a9a60dc3c35e36375dec6ced0d2db3ba0d111bedea701a0e4753624977a9e75b70a74e2b81e38a52ab22da131b35416d3cec9663079746a763476e57598142e39861545daaf8d38a176f26c71f5afebd9c5620da80cf3452b55c37c661b4a1ec0351710b9de4a3cbe0b98b4d9ec89128d97aa7efb19db8ba43cc0be25c200f90e1506cb78ec0c336d7a95613d4204e8ed68d0f0a6c78420105a8d2d438fbd2551a64a1a0b03ffb878742f8c9979cfa87394150281998d51701d5fcfa9696a4989fd25f400955e626b1abe926c0afa69aa6981900effcdd030592f82b2042a47a9a5a8cb0283dc4d
+Q = 80000000ba4634b5fa4da054bd0ca48ae490e57711f381193842429159ba7ca1
+G = 8ad4553c4e49aa24728ab5024417b132d2ca53a55d959458f2f759adb0435beeefa3a2cfcd0038e2420643fc4a4deeb5d9feaa1edf21193b40e14b42982a94f35c58b81147d7189d263c9b12fe63ab9fa5f6f03a2860c186432e3ab04f2ab0f2fb6147bd9bf7ed5d20713b9da21383e2c3a168e7d09d3d8a5a058fd23095b5acfeb864a3306be2425fa1ad32ad6d9382e603b03c68af4af0246397102c4155cba811abf99da7839e77b2eac9970588ca1d0a2361723a164ac9229c2e80dcfa8db4f9e29803effb3168c7fed7a3a6de40dda19a0536af9b5b7afaefb9c70d6ae8df12da658f6236043aea873db29ceb6f07d108f5225687bd0c30e3084e2090b45ae2f92a97b8ecb7a9705c4956b8b31c4a3d61107c84e47adda6c80d5d22dab3d859220f9d5aab13677ae3df168f0c176d176b54506c639853f04ddef2722f39c18e5ce426e14562ad8ff26247af88870efb72c0cce836de8fee67a662378245b502bf1f83099988a093ce7cdc81364c78b1f4a51b800df6137c71d65e6b089a
+Msg = 957973fc3f3fe3f559065be5d4a0c281cf17959018b9a670d2b3706d41d5812e37301005f8b70ebd2fba3c40a3f377a751b6cb9693e3cb00d92888247d07921d3c1e9257ce08733b8926e0df7bdb6e855f1f851075d4e628d110d42b643b54876e5faa3611477ee68371562555269ed62a9271bad50cc4d46038de2dd41920c2
+X = 524a7ea5977f8102b3552930477f5f042401165d4637dcd8b9d13df4f3aae5d0
+Y = 42243539e49db9ea19d98d97f6f2a94b23529812df889eaabcfeda01ce4c759487fb89bc82da75fe1c9134361f86de47d16d8eee80e56ac502178e8ed8129477af8bfbd8262c5edd937e1a86c0f0e7b2afe7bcbddfcb5814ced0b756a76ca178423bb4d578c5da183712d968582640aa0ec7e9fb56bfd960d7a57549747d8fb7ade47cfe816c1e57da6633dacc537de060813964bb5b2757a312f9da3d84e60aff98170051d3d90e380b8bcc1986c58ff9dc91e8827d4f9f5fc4b2b2e743cf9389ff02dec01f5d434b430d162e891c3355f91855339f8df58300e4c993ae4df8c4318b5c4bd05283ca4b46b7d2fb0f6476bf15907f50dd4141aa7acac9daa62eccd3a67357122060b6cece0446a93eb230ad93bc9a4d1b1efeeca1e3fc83c119785035b439509ffb7968b1a448b7bd8315753fdf04a256eca1562a11b096c90a36b353659cbde4420e17e90b94c43c7519c60641ceec056f897b97d6bb1861268e0dc79b7c3b6b7639c255bf06865737459126cb465bc1da4a043a1963da7d63
+K = 29e4d7790e181b4767903fe0eb37757f33f13337c33588c1fdbfba0e655ab621
+R = 2e59d5f30f73781d38255b70dedeeb38ae78df4f002c1f747c08deadc6530155
+S = 615c55b2df0ca28c60a6b385c58fa036df8c4b2f4f1935730bf8f4f0bed13610
+
+[mod = L=3072, N=256, SHA-256]
+
+P = c7b86d7044218e367453d210e76433e4e27a983db1c560bb9755a8fb7d819912c56cfe002ab1ff3f72165b943c0b28ed46039a07de507d7a29f738603decd1270380a41f971f2592661a64ba2f351d9a69e51a888a05156b7fe1563c4b77ee93a44949138438a2ab8bdcfc49b4e78d1cde766e54984760057d76cd740c94a4dd25a46aa77b18e9d707d6738497d4eac364f4792d9766a16a0e234807e96b8c64d404bbdb876e39b5799ef53fe6cb9bab62ef19fdcc2bdd905beda13b9ef7ac35f1f557cb0dc458c019e2bc19a9f5dfc1e4eca9e6d466564124304a31f038605a3e342da01be1c2b545610edd2c1397a3c8396588c6329efeb4e165af5b368a39a88e4888e39f40bb3de4eb1416672f999fead37aef1ca9643ff32cdbc0fcebe628d7e46d281a989d43dd21432151af68be3f6d56acfbdb6c97d87fcb5e6291bf8b4ee1275ae0eb4383cc753903c8d29f4adb6a547e405decdff288c5f6c7aa30dcb12f84d392493a70933317c0f5e6552601fae18f17e6e5bb6bf396d32d8ab9
+Q = 876fa09e1dc62b236ce1c3155ba48b0ccfda29f3ac5a97f7ffa1bd87b68d2a4b
+G = 110afebb12c7f862b6de03d47fdbc3326e0d4d31b12a8ca95b2dee2123bcc667d4f72c1e7209767d2721f95fbd9a4d03236d54174fbfaff2c4ff7deae4738b20d9f37bf0a1134c288b420af0b5792e47a92513c0413f346a4edbab2c45bdca13f5341c2b55b8ba54932b9217b5a859e553f14bb8c120fbb9d99909dff5ea68e14b379964fd3f3861e5ba5cc970c4a180eef54428703961021e7bd68cb637927b8cbee6805fa27285bfee4d1ef70e02c1a18a7cd78bef1dd9cdad45dde9cd690755050fc4662937ee1d6f4db12807ccc95bc435f11b71e7086048b1dab5913c6055012de82e43a4e50cf93feff5dcab814abc224c5e0025bd868c3fc592041bba04747c10af513fc36e4d91c63ee5253422cf4063398d77c52fcb011427cbfcfa67b1b2c2d1aa4a3da72645cb1c767036054e2f31f88665a54461c885fb3219d5ad8748a01158f6c7c0df5a8c908ba8c3e536822428886c7b500bbc15b49df746b9de5a78fe3b4f6991d0110c3cbff458039dc36261cf46af4bc2515368f4abb7
+Msg = cb06e02234263c22b80e832d6dc5a1bee5ea8af3bc2da752441c04027f176158bfe68372bd67f84d489c0d49b07d4025962976be60437be1a2d01d3be0992afa5abe0980e26a9da4ae72f827b423665195cc4eed6fe85c335b32d9c03c945a86e7fa99373f0a30c6eca938b3afb6dff67adb8bece6f8cfec4b6a12ea281e2323
+X = 3470832055dade94e14cd8777171d18e5d06f66aeff4c61471e4eba74ee56164
+Y = 456a105c713566234838bc070b8a751a0b57767cb75e99114a1a46641e11da1fa9f22914d808ad7148612c1ea55d25301781e9ae0c9ae36a69d87ba039ec7cd864c3ad094873e6e56709fd10d966853d611b1cff15d37fdee424506c184d62c7033358be78c2250943b6f6d043d63b317de56e5ad8d1fd97dd355abe96452f8e435485fb3b907b51900aa3f24418df50b4fcdafbf6137548c39373b8bc4ba3dabb4746ebd17b87fcd6a2f197c107b18ec5b465e6e4cb430d9c0ce78da5988441054a370792b730da9aba41a3169af26176f74e6f7c0c9c9b55b62bbe7ce38d4695d48157e660c2acb63f482f55418150e5fee43ace84c540c3ba7662ae80835c1a2d51890ea96ba206427c41ef8c38aa07d2a365e7e58380d8f4782e22ac2101af732ee22758337b253637838e16f50f56d313d07981880d685557f7d79a6db823c61f1bb3dbc5d50421a4843a6f29690e78aa0f0cff304231818b81fc4a243fc00f09a54c466d6a8c73d32a55e1abd5ec8b4e1afa32a79b01df85a81f3f5cfe
+K = 3d7c068a3978b2d8fe9034bcad65ad7c300c4440e4085de280e577eea72c1207
+R = 53bae6c6f336e2eb311c1e92d95fc449a929444ef81ec4279660b200d59433de
+S = 49f3a74e953e77a7941af3aefeef4ed499be209976a0edb3fa5e7cb961b0c112
+
+[mod = L=3072, N=256, SHA-384]
+
+P = a410d23ed9ad9964d3e401cb9317a25213f75712acbc5c12191abf3f1c0e723e2333b49eb1f95b0f9748d952f04a5ae358859d384403ce364aa3f58dd9769909b45048548c55872a6afbb3b15c54882f96c20df1b2df164f0bac849ca17ad2df63abd75c881922e79a5009f00b7d631622e90e7fa4e980618575e1d6bd1a72d5b6a50f4f6a68b793937c4af95fc11541759a1736577d9448b87792dff07232415512e933755e12250d466e9cc8df150727d747e51fea7964158326b1365d580cb190f4518291598221fdf36c6305c8b8a8ed05663dd7b006e945f592abbecae460f77c71b6ec649d3fd5394202ed7bbbd040f7b8fd57cb06a99be254fa25d71a3760734046c2a0db383e02397913ae67ce65870d9f6c6f67a9d00497be1d763b21937cf9cbf9a24ef97bbcaa07916f8894e5b7fb03258821ac46140965b23c5409ca49026efb2bf95bce025c4183a5f659bf6aaeef56d7933bb29697d7d541348c871fa01f869678b2e34506f6dc0a4c132b689a0ed27dc3c8d53702aa584877
+Q = abc67417725cf28fc7640d5de43825f416ebfa80e191c42ee886303338f56045
+G = 867d5fb72f5936d1a14ed3b60499662f3124686ef108c5b3da6663a0e86197ec2cc4c9460193a74ff16028ac9441b0c7d27c2272d483ac7cd794d598416c4ff9099a61679d417d478ce5dd974bf349a14575afe74a88b12dd5f6d1cbd3f91ddd597ed68e79eba402613130c224b94ac28714a1f1c552475a5d29cfcdd8e08a6b1d65661e28ef313514d1408f5abd3e06ebe3a7d814d1ede316bf495273ca1d574f42b482eea30db53466f454b51a175a0b89b3c05dda006e719a2e6371669080d768cc038cdfb8098e9aad9b8d83d4b759f43ac9d22b353ed88a33723550150de0361b7a376f37b45d437f71cb711f2847de671ad1059516a1d45755224a15d37b4aeada3f58c69a136daef0636fe38e3752064afe598433e80089fda24b144a462734bef8f77638845b00e59ce7fa4f1daf487a2cada11eaba72bb23e1df6b66a183edd226c440272dd9b06bec0e57f1a0822d2e00212064b6dba64562085f5a75929afa5fe509e0b78e630aaf12f91e4980c9b0d6f7e059a2ea3e23479d930
+Msg = ed9a64d3109ef8a9292956b946873ca4bd887ce624b81be81b82c69c67aaddf5655f70fe4768114db2834c71787f858e5165da1a7fa961d855ad7e5bc4b7be31b97dbe770798ef7966152b14b86ae35625a28aee5663b9ef3067cbdfbabd87197e5c842d3092eb88dca57c6c8ad4c00a19ddf2e1967b59bd06ccaef933bc28e7
+X = 6d4c934391b7f6fb6e19e3141f8c0018ef5726118a11064358c7d35b37737377
+Y = 1f0a5c75e7985d6e70e4fbfda51a10b925f6accb600d7c6510db90ec367b93bb069bd286e8f979b22ef0702f717a8755c18309c87dae3fe82cc3dc8f4b7aa3d5f3876f4d4b3eb68bfe910c43076d6cd0d39fc88dde78f09480db55234e6c8ca59fe2700efec04feee6b4e8ee2413721858be7190dbe905f456edcab55b2dc2916dc1e8731988d9ef8b619abcf8955aa960ef02b3f02a8dc649369222af50f1338ed28d667f3f10cae2a3c28a3c1d08df639c81ada13c8fd198c6dae3d62a3fe9f04c985c65f610c06cb8faea68edb80de6cf07a8e89c00218185a952b23572e34df07ce5b4261e5de427eb503ee1baf5992db6d438b47434c40c22657bc163e7953fa33eff39dc2734607039aadd6ac27e4367131041f845ffa1a13f556bfba2307a5c78f2ccf11298c762e08871968e48dc3d1569d09965cd09da43cf0309a16af1e20fee7da3dc21b364c4615cd5123fa5f9b23cfc4ffd9cfdcea670623840b062d4648d2eba786ad3f7ae337a4284324ace236f9f7174fbf442b99043002f
+K = 40b5cc685c3d1f59072228af9551683b5b8c8ff65240114ad2dacfccf3928057
+R = 7695698a14755db4206e850b4f5f19c540b07d07e08aac591e20081646e6eedc
+S = 3dae01154ecff7b19007a953f185f0663ef7f2537f0b15e04fb343c961f36de2
+
+[mod = L=3072, N=256, SHA-512]
+
+P = c1d0a6d0b5ed615dee76ac5a60dd35ecb000a202063018b1ba0a06fe7a00f765db1c59a680cecfe3ad41475badb5ad50b6147e2596b88d34656052aca79486ea6f6ec90b23e363f3ab8cdc8b93b62a070e02688ea877843a4685c2ba6db111e9addbd7ca4bce65bb10c9ceb69bf806e2ebd7e54edeb7f996a65c907b50efdf8e575bae462a219c302fef2ae81d73cee75274625b5fc29c6d60c057ed9e7b0d46ad2f57fe01f823230f31422722319ce0abf1f141f326c00fbc2be4cdb8944b6fd050bd300bdb1c5f4da72537e553e01d51239c4d461860f1fb4fd8fa79f5d5263ff62fed7008e2e0a2d36bf7b9062d0d75db226c3464b67ba24101b085f2c670c0f87ae530d98ee60c5472f4aa15fb25041e19106354da06bc2b1d322d40ed97b21fd1cdad3025c69da6ce9c7ddf3dcf1ea4d56577bfdec23071c1f05ee4077b5391e9a404eaffe12d1ea62d06acd6bf19e91a158d2066b4cd20e4c4e52ffb1d5204cd022bc7108f2c799fb468866ef1cb09bce09dfd49e4740ff8140497be61
+Q = bf65441c987b7737385eadec158dd01614da6f15386248e59f3cddbefc8e9dd1
+G = c02ac85375fab80ba2a784b94e4d145b3be0f92090eba17bd12358cf3e03f4379584f8742252f76b1ede3fc37281420e74a963e4c088796ff2bab8db6e9a4530fc67d51f88b905ab43995aab46364cb40c1256f0466f3dbce36203ef228b35e90247e95e5115e831b126b628ee984f349911d30ffb9d613b50a84dfa1f042ba536b82d5101e711c629f9f2096dc834deec63b70f2a2315a6d27323b995aa20d3d0737075186f5049af6f512a0c38a9da06817f4b619b94520edfac85c4a6e2e186225c95a04ec3c3422b8deb284e98d24b31465802008a097c25969e826c2baa59d2cba33d6c1d9f3962330c1fcda7cfb18508fea7d0555e3a169daed353f3ee6f4bb30244319161dff6438a37ca793b24bbb1b1bc2194fc6e6ef60278157899cb03c5dd6fc91a836eb20a25c09945643d95f7bd50d206684d6ffc14d16d82d5f781225bff908392a5793b803f9b70b4dfcb394f9ed81c18e391a09eb3f93a032d81ba670cabfd6f64aa5e3374cb7c2029f45200e4f0bfd820c8bd58dc5eeb34
+Msg = 494180eed0951371bbaf0a850ef13679df49c1f13fe3770b6c13285bf3ad93dc4ab018aab9139d74200808e9c55bf88300324cc697efeaa641d37f3acf72d8c97bff0182a35b940150c98a03ef41a3e1487440c923a988e53ca3ce883a2fb532bb7441c122f1dc2f9d0b0bc07f26ba29a35cdf0da846a9d8eab405cbf8c8e77f
+X = 150b5c51ea6402276bc912322f0404f6d57ff7d32afcaa83b6dfde11abb48181
+Y = 6da54f2b0ddb4dcce2da1edfa16ba84953d8429ce60cd111a5c65edcf7ba5b8d9387ab6881c24880b2afbdb437e9ed7ffb8e96beca7ea80d1d90f24d546112629df5c9e9661742cc872fdb3d409bc77b75b17c7e6cfff86261071c4b5c9f9898be1e9e27349b933c34fb345685f8fc6c12470d124cecf51b5d5adbf5e7a2490f8d67aac53a82ed6a2110686cf631c348bcbc4cf156f3a6980163e2feca72a45f6b3d68c10e5a2283b470b7292674490383f75fa26ccf93c0e1c8d0628ca35f2f3d9b6876505d118988957237a2fc8051cb47b410e8b7a619e73b1350a9f6a260c5f16841e7c4db53d8eaa0b4708d62f95b2a72e2f04ca14647bca6b5e3ee707fcdf758b925eb8d4e6ace4fc7443c9bc5819ff9e555be098aa055066828e21b818fedc3aac517a0ee8f9060bd86e0d4cce212ab6a3a243c5ec0274563353ca7103af085e8f41be524fbb75cda88903907df94bfd69373e288949bd0626d85c1398b3073a139d5c747d24afdae7a3e745437335d0ee993eef36a3041c912f7eb58
+K = b599111b9f78402cefe7bde8bf553b6ca00d5abaf9a158aa42f2607bf78510bc
+R = a40a6c905654c55fc58e99c7d1a3feea2c5be64823d4086ce811f334cfdc448d
+S = 6478050977ec585980454e0a2f26a03037b921ca588a78a4daff7e84d49a8a6c
+
diff --git a/security/nss/cmd/bltest/tests/dsa/key0 b/security/nss/cmd/bltest/tests/dsa/key0
new file mode 100644
index 000000000..e582eeb04
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key0
@@ -0,0 +1,6 @@
+AAAAQI3ypJRJInaqPSV1m7BoacvqwNg6+40M98u4Mk8NeILl0HYvxbchDq/C6a2s
+Mqt6rElpPfv4NyTC7Ac27jHIApEAAAAUx3MhjHN+yO6ZO08t7TD0jtrOkV8AAABA
+Ym0CeDnqChNBMWOlW0y1ACmdVSKVbO/LO/8Q85nOLC5xy53l+iS6v1jlt5Uhklyc
+xC6fb0ZLCIzFcq9T5teIAgAAAEAZExhx11sWEqgZ8p140bDXNG96p3u2KoWb/WxW
+ddqdIS06Nu8Wcu9mC4x8JVzA7HSFj7oz9EwGaZYwp2sDDuMzAAAAFCBwsyI9ujcv
+3hwP/HsuO0mLJgYU
diff --git a/security/nss/cmd/bltest/tests/dsa/key1 b/security/nss/cmd/bltest/tests/dsa/key1
new file mode 100644
index 000000000..8ba3118dd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key1
@@ -0,0 +1,10 @@
+AAAAgKj5zSAeXjXYkvhfgOTbJZmlZ2o7HU8ZAzDtMlaybQ6AoOSaj/+qrSok9HLS
+VzJB1NbWx0gMgLTGe7RHnBWtp+qEJNJQL6AUcudgJBcT2rAlrhsC4XA6FDX2Ld9O
+5MG2ZAZusi8uO/KLtwoqduT9Xr4tEiloG1sGQ5rJx+nYveKDAAAAFPhfD4OsTffq
+DN+PRpv+6uoUFWSVAAAAgCsxUv9sYvFGIrj0jln4r0aIOzjnm4x03urp3xMfi4Vu
+OtbIRV2rh8wNqKyXNBfOT3h4VX1s30CzW0oMo+sxDGqV1ozihK1OJeooWRYR7gi4
+REvWSyXz98VyQQ3fs5zHKLnJNvhfQZEphpkpzbkJpqOpm74IkhY2gXG9C6gd5P4z
+AAAAgDE/2evKkVdOHC7r4VF8V+DCGwIJhyFAxTKHYbuyRQsz8bGLQJzpq3xM2P2j
+OR6ONIaDV8GZ4WprLroG1nSd73kdeeldOk0Jskw5KtidvxAJla4ZwBBiBWuxS84A
+Xocx794XX5W5dQib3NrqVisyeG2W9aMa7fdTZACK1P/+u5cLAAAAFMU+rm1FMjFk
+x9B69XFXA3RKY/w6
diff --git a/security/nss/cmd/bltest/tests/dsa/key10 b/security/nss/cmd/bltest/tests/dsa/key10
new file mode 100644
index 000000000..166f9bd03
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key10
@@ -0,0 +1,18 @@
+AAABAL/r0ACy1s1Ks477o13zNN9yHWwvKz2VZnnLrQCfPfvQApUsyJnMI1bsh2m9
+PRulpzAjcpiI2pLKSKXulMl/TwSi46y08zovD7N4PDHyxw+nxw84IUon2t7IsS5n
+mWqehe47sUiAMTAUc5LcUlPATXBjU15s1ka/sYaYTgi1i3SnvlszO/MrCr/VZlNg
+6akjoMUo/xxixyU0WPVnhShxnUNuUBSHQfRdx90sbKxxxVIx8SqD/v0u0KM+3huK
+UfVm/PeJBoLNwZMdwgfJK/LvTiirMWYe63fxYB7qlByVkfA40/ANkShX2wXmSyrV
+aTIAYcb4Y/8zVNhC5+fqcVr++NEAAAAcqpht+KBkJ46TYzFqmDC8+kkGVvqm1dqo
+F9h5SQAAAQCBla2aR4/ZhSFu5YNoNm0u3RPBKz1iI5Fp+gQtkRVkCLSDEi9E7WI2
+uDCKbNtS+a896I7IngOa+tfaOqZsGXYEmo4KfRjVZ7r5n87+MVytoBVIOGsQsl5S
+9S7XjrTSgILl4f/ulIDE/izEqv0e/J1P0sxtFVlokxJx7xWzJA5/sEOoDI9ii+/g
+nWRQd8ECnSHgrIvwupwncU0bWA7eWUqgGzt29udF/B7AfbN+L9fpjGyMaRUijkIs
+MJ3p9dsWj1AknRvh7TKYCQgI4uu4lrt5uMTL+U1MIGTjfmErpESdesIQ7d4hFBbW
+SwUd2ARqsEFzJmVBGn8VTTGz4RpR2n/AAAABAK9nIb913saht2rTXKN1De8xEXxb
+RBwVowaDWh23TAA7hq6Qmev7dFsKqcsADPQ/sCFRO48Ze8hlsiv5SbSRgJrXUv/B
+yo5UvqFtx/U55MVftwp3Q90o8mL2DvDy/KrCnoAhp5OMGP/gMHXQt+CitNyr5G7R
+lT0z438ROvUZqwvwthhsErX2SIQ39RkwluL9amoYNWBHlMZrQq5SZcHPHLU66EmX
+l14DGKk85B45AuTvVN48VlVb0ZSRrNU/PldGTh9GA4nbxfqAZI+lpaDylW6ew7jc
+RBtTXGQcNi7tdw2oKGSb/RRkcrD0akwGTkWfiL/5De3n7FYXeppx0WeUhxIAAAAc
+altP/EQjjRhS+5t05MFmG+hZhAQ8/u4CP1fKxg==
diff --git a/security/nss/cmd/bltest/tests/dsa/key11 b/security/nss/cmd/bltest/tests/dsa/key11
new file mode 100644
index 000000000..086f49375
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key11
@@ -0,0 +1,18 @@
+AAABAMGlnSFVc5SeCyCpdMLt8uMTf/JGMGL3Xx0T3xKroQdrstATQCtgr2wYf7D6
+NiFnyXbCYXxyb5B38J4YwRtg9lAIglvWwCofV9PrCtQc1UfeQ9h/JSX5cdQrMGUG
+58oDvmOzX0raFy0KBpJEQKFCUNeCKsLVrq/tRhnnnUFYp9XrLZ8CPbGBqPCUssbL
+h8uFNUFqwZgT8HFEZgxVd0X0SgHGsQKQksEpsNJxg+gsWiGoAXfudHbrlcRm+0cr
+09LcKGziWEfpPL+prTnMVwNdDHtkuSapx/WnsrxavL+9wLDj/t48HgLESvyK78eV
+faB6Dl/RIznbhmdhb2IobfgNWKsAAAAggAAAAAAAAAAAAAAAG9YsZei4fIl5f48M
+v6VeSmgQ4scAAAEArqWHh0DxQk08bqnGtHmWFdJ0kpihfiYgf3bO80Dd05Dhsa1r
+bAAQrQFaEDNC3dRSysAks25C2bjtUvr656HTzp5LIfkQ0TVusWOj5agYTHgb8USS
+r6LksKVtiIT9AaYouWYnOcQuXFeVreL18n5t4dljkXzogG/EDQIc2HqjqjqeTwws
+TEXSlZsleLL7GiIpw34YEFm51ee3hi+oLiN3pJ7Q+dyoIKWBQHndZhBxTvr4sMxo
+PY5y5MiE5vnUlGs+jUy7kq2759TEfMML5/jDfKgYg6GqxoYAWf9GQKKcyuc94gsS
+5jsAqIsu6bqUt160CmVuFdnsg3MchdDv/LnvnwAAAQCIDhfEroFBdQYJ2CUcC716
+z20LRg7TaI6aX5kObEtbAIddp1DgIooEECo19X50uNL5tpUPDR240wLFyQpbh4ao
+LGj/WxelenWElsX4BT5EhKJT2ZQiBNmhEJ9L0qPsMRpgz2nGhbWG2Yb1ZdM9v1qr
+cJHjGqQQLE9LU/v4ctcAFWRltsB15/d4RxojUC3A/uQbJxyDehwmaRaZ81UNBgoz
+EJn2SDfN3sacrr9Rv07J828qIg/nc8tNPALQRG3dRhM1Mu8cPGnUMuMDUCvQWnUn
+mngJp0KsSnhysH8ZCGVASUGTUON6lfLvMzYdjYc21Ag9wUwLuXLhTUx7l/Pd/Mrv
+AAAAIFpC53JINY8GrpgKLGT2oivqK/e0/AAVdFBTxDK3Eypn
diff --git a/security/nss/cmd/bltest/tests/dsa/key12 b/security/nss/cmd/bltest/tests/dsa/key12
new file mode 100644
index 000000000..bb2cba1cf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key12
@@ -0,0 +1,18 @@
+AAABANAiduvzwi/9ZmmDGDpHrpTJvMvL+V3ctJHR985kNUkZmZLTfHnnsDLSbtAx
+trpEifMSWCb6+ycmqYMz69mr3eWS2Gk9mFlTbZzDhBodJOBE01rO1hNiVvxta2Fc
+9PQWOqOB6ytMSAglqOzMVtjdz1/mN+OK2bKXS9LPaL8nHg0GfSRlqLa2YFJPAIJZ
+iUWtpY6mSbmATrR1NAjCxZdoxGq7guMpXz2cpGn4TMGH9XLcS1o7OTRuyDnfrW8H
+1tHw4hUgm7DswFx2fPLnlDrJz7Au7h6e9ZRujOiDFrXhX9z5WhMu8uS7CBcTZSjP
+pd2WUy+cOr5cQhYg7ba8vVIjTKkAAAAggAAAABKZfoKF5AiXCPUoBwxtevigvQFA
+nnoHnNtvxbsAAAEAd4RTBJ7yYhR/7XtZsO5nZGB8Uee1tfxv6np6ex3Wuyg/Sprp
+jv05ZLFVZ1jLFbKlOvhhnnTYWJi+x307PzgklK5ZYaE//HRdo4YYIpFRmAD5ndcQ
+4ArrFa3uCI4nmO4uRvWYUmzw9GZwVdG6AJdQBB3FzdJyX/HZfdNAyFGK92cbh9Od
+Z67O2Etm+E4HAe/IKlye+VTuV20kw4WxTWMDfw2Gb9QktJdb3VSF7XQMuTLoQ/kG
+aD98eyx0d12QHDYbhHtRnA2mmWONpAvXNreD0nELLCzCbvkScb9OLBkp+HbpAuIF
+cWQiO8eNaiufbAx6fLhZIvfWxCh64jhh+BKISAAAAQB7sx6Yx6BDf5eKc9Xc+9+7
+Ccwkmd+vHrUla8zWNYyrtfZ9BKQoI0Y7fpV/K5IT8fqOWpjWFEhHAau4x9Z2Qf5u
+0G+kUntJPdqy50ZA/ePecNppPx2yuOJkFwQK8O6myrRRp5WlLhh9LuJBuT9lyGxt
+ZvRYNMzhZaxetnDU8AlcI86XV+O9xjb5ke4Ac9kKCSAu2zXMPqHPmtyhYX+gv/2c
+EmIppgSh079JMd3wuZQt/IovjAn8yXAyVkp5rh6+Hizkn/V4OefEP6YLFgPRWkUI
+mKpOSh7oBleUEm1k8BM2cJaoNoa58VjDOxD187Ns8fY1iz80+EsQHcJtPbaLzJXI
+AAAAIGuoHmzUNneYqquLevETUYOjfEKnZtvWjNLc548mcO8P
diff --git a/security/nss/cmd/bltest/tests/dsa/key13 b/security/nss/cmd/bltest/tests/dsa/key13
new file mode 100644
index 000000000..b3e25c7cc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key13
@@ -0,0 +1,18 @@
+AAABAKittsC0z5WIAS5d7/GocdOD4OKoW16OA9gU/hOgWXBeZjIwo3e/cyOo+hFx
+ACAL/VrfhXOTsLvWeQbAgeWFQQ44SA6tUWhNrDo497ZMnrEJ8Zc5pFF819XWKR6K
+8go/vxczbHv4DucY7gh+Mi7kEEfavvvMNNELZrZE3bMWCijAY5Vj1xmTomVD6tt3
+GPMXv12Vd6YVZWGwgqEAKc1EASsY3mhEUJ/gWLqHmAeSKF8nUJaf6Jws1kmNs1RW
+ONU3nRJdzPZOBsGvM6YZCEHSI9oVEzM6fJ14Riq6qzG5+W1fNERc62MJ8vbSyN3g
+ZEHoeYDTA++aH/AH6L4vC+BswV8AAAAg5x+FZ0R/QudfXvhcog/lV6sDQ9N+0J7c
+P25oYE1rnfsAAAEAW6JN6WB7iZjmbObE+BKjFMaTWEL3q1TNgrGfoQSr+12EV5pi
+OyV0s30izK6bPkFeSPXA+by9/4Bx1jubuVblR686jfmeXTBhl5ZS/5a3Zcs+5JNk
+NUTHXb5bs5g0UxlSoPtLA3iz/LtMi1gApTMDkqKgTnALtu1+C4V5XqOLG5YnQbPz
+O53eL07BNU8J4ut46V8DelgEthcWWfiHFc4amwzJDCfzXvLxD/DHx6K7AVTZuOvn
+aj12Sqh5rzcvQkDeg0eTflqQzsn0H/Lya42pqUoiXRqRNxfXPxA5fSGD8bo7e0Wm
+jx/xiTyvaagngC97akjVHab777ZP2abFt1xFYQAAAQBaVdzt3RE07l8R7YXetNY0
+o2Q/XzbcOnBoklZGmgtlGtIogPFKuFcZQ0+cDkB+YOpCDioM0pQixImcQWNZ27Hl
+kkVvKzzOIzJZwRdUL9BfMeolsBXZEhyJC5DgutAzvhNo0imYWqxyJtHIwuqzJe87
+LNWdO59959vJSvGpM560MMo2wmxG7PpsVIFxFJb2JOGIrXVA713yb476y4IL0Xof
+YYrLUMm8GX1Mt8ysRdgko795XCNLVWsGrrkpFzRTJSCEAD9p/pgEX+dAArplj5NH
+ViL3Z5HZsmI9G1//LMFoRHRu/S0wpqgTS/xMjMgKRhB5AfuXPCj8VTEw8yhsFIna
+AAAAIERpaQJURiR/hP3qdNAtfdE2crLet8CFvhERFEGVWjd7
diff --git a/security/nss/cmd/bltest/tests/dsa/key14 b/security/nss/cmd/bltest/tests/dsa/key14
new file mode 100644
index 000000000..759c602be
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key14
@@ -0,0 +1,18 @@
+AAABAKYWfBb/904pNCuFhq7TzYlvexY1oihv8W/f9BoGMXymsFyiunwGCtbbFWFi
+HMsMQLhqA2Gb//MuIEy9kLedy1+G67ST470ZiNgJf6I/pNePs83csAxGZCPY+nGY
+c8N2Rf5O7MVxcbvt/lb6lHTJY4W4ujeMeZcteqrmmiumTN6OVlTw97dFUM00R+ek
+cqM7QDfbRo3eMcNIqiXoK3/EG4N/f8ImphA5ZuzY+dFMLTFJVW1Dgp8TdFG40g+F
+ILDOjj1wX3TQpX6ocsK97pcU4LY5Bs3f3Ci2d30ZMlAA+O1SeOxdkS0QIQkxnLo7
+ZGnUZykJtPDb7sC7tjS1UboM8hMAAAAghCdSkETSFMB1dPezWcLgHCP9l3AbMorI
+wThbgcU3OJUAAAEAb8IyQVwxIAz1I680g/jias6AjS8caouGOrBCzH9rcUSy05Ry
+w8tMdoHQcyhDUD2PhYy+R25nQDJKqilZUBBZeMM1BpuRn/mm/0tBBYG4BxL+XT4E
+3bTf0m1ef7yisMUtjUBDQ9V7L5sqJtqn7OMM6rnheJ+XUaqpOHBJllrzJlDGyls3
+SlrnCz+Y4FP1GFfWu7F6Zw5uqviYRNZB4eE9Whsk0FPca4/RAcYkeGlRkn5CYxCr
+qUmKAEKz3Hu8WdcF+A2bgH3kFffpTFz514mZLTu4M20dgIy4a1bd4J2TS7UnAzki
+3hS/MHN2q30i+81hb57aR5qyFKF4UL3QgCqHHAAAAQBcpxUbyg5Fe7xG9Z9x2Bqx
+ZojcDrfk0XsWbDMmxbEsW967NhMiTRp1QCPFC4PLXswTkJbO8okzs7EsoxA45AiT
+g1l8WcwnuQK+XaYsrn2l9K+Q6UEO0WBAguLjjiXrC3jfrArrKtOxncI1OdK811Xb
+HMbJgFp90QnhyYZnpbnVKyHCdyEhuNDSskbl/T2oByjoW78NcGfRxrqmQ5Sinn/L
++AhCvUqwKzXYP1mAWhBOC9adAHmgZfWePm8hVzoA2pkLcupTf6mMqqCliACn56Bi
+PiY9T8pl67jt7Ubv3+fbksnr04Bi2PElNPAVsYYYbuI2HWLCTk8is+ldoPkGLOBN
+AAAAIEWesViOn33U8oZnenQVyyWhtG56fPrcikUQA4PiDaad
diff --git a/security/nss/cmd/bltest/tests/dsa/key15 b/security/nss/cmd/bltest/tests/dsa/key15
new file mode 100644
index 000000000..dee9a8a75
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key15
@@ -0,0 +1,18 @@
+AAABAPY9o76alhYZbGVW885v2LmL3akTdHPaRv7ZcOK40Uc4eoGSIGXVKKfWQz68
+XjWxXGfqNaWlv/W5zvHNHm/jHdpSg42jqom5tOjZ08BzLMxPI4zhtBbEypPyxoAO
+X07UHE92Fc7FUxuYaAsg3GP3PnDYA6rPrs4z1F+g4513yFCCCVKLkEa1kXAQeRI0
+OX5BLSK8C41ny9HNKKMsJGCgvYaqug7qgOFuMkVkMXHjQiF2DCA6VrggehAJ5sGi
+9s2oX4XE+eQQuUmSM8DuBy5GWvT7T7koLFwQ6CNP1jDqkvCq5rl6Ug2zRHVwe3mk
+wXUmXANWzLyoJ+ODffPW0FdtkHkAAAAgm3Rj+CafC5CavtEJkWhPNqZKyGTg1tcX
+wO8hV3pMOQcAAAEAlyp19gboqjqR/wj9Exog9ZYyUTBOPRQxtxL6CAPVJ/1xD7fr
+J+UpBJcc1DypdxmaJNvutLe8K6B107cutrLFrY8Oi49IxQtVTH4HEfTHQWMwgGZy
+SY9DApJyS/mKjqSMf1PXsx2LdSixpvCH0sJ8M1ICg1seMUIls3rvi/zsfYCSDEpG
+Cj1oNE3tde2e6Gf6KmlFBjiU9WO2hjO4s5+DoaqvWpbH9CJofnyEz4+4zF9FBN/w
+h7yyapW7+Fg/A7Og5Do1ayvX4lzd33oBUwD67MZ5PF7pm2Mny4RW4y2RFTOdWmtx
+K3+dAwGssFEz4xFeRU06bdJKFpPJSqtUBlBL9wAAAQBBGXziIz1+SMgDzWTHj2V5
+I7nja4cUAfhmHCHYujjGubMjnbdnsR0dQB5frsv3pFhgzF8aVNYChrfW4cmf1bjI
+TthRxTV9Qa1gFj8iTXjJlhQ//4ndOo/hI9rh9iFCf9jM527RONaPokjzdK4jMkli
+W5Pz3Vk30V5UG37/pN9P6n1S+s7WFb/gNIQY/5PmmiClLlXHbMMPMH+E5x5Kq8CC
+Xso6lbS9WOv7ACnSOhaenYC6fRxf01OV5mAuCJqpkY8IuuNa4crHrzNpQSnpjw2t
+rdkOrrbu0lAkOQsaYK95RzTDl7D1CYZbE0soZ8EV1vSJtt1+PIKZS0Xc4qI8a8kC
+AAAAIF9uVF2u9s0bjZhI3Zh1iAcjasC3/wU7MscD6qOxFHVX
diff --git a/security/nss/cmd/bltest/tests/dsa/key16 b/security/nss/cmd/bltest/tests/dsa/key16
new file mode 100644
index 000000000..704d76cb4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key16
@@ -0,0 +1,26 @@
+AAABgP1abFbdKQ992Eop3hcSbrTkSHs+/wpEq+XFl5LS4SALnD20TVKLn30iSAMu
+S6D3v8T6/HBr5RHbInbAt+z/042i4cLyN6dTkMHk0yOcuo4g5VhA7LBd9fAaG2l3
+rRkG8stUTM+5O5Aa0JZrGDKtLatSYkSjFWyQXAGsUctzudzZhg1WF1pCXYRkhdmx
+9EqKDCV45s9hlHvBoTkv3TILFqnXBFX+Q28tR97Y6OYF90hutXjqf8T/0TwH+Zlq
+8Vn9QR6UUUAyeN0RQajJJrNcljhLvWvuCcRvRMNrH/xxl/XpJdvgVEpo5quMGOQm
+pGazkvnCfdef76nKFjzFo3VTmoVZ8nf2V6U10ZZMal6RaD71aY66oB74GNv3LLBM
+P/CS0YiGbyXNQFEI9Wawh/c9LVvrUfrG3oSuUWGmavlgLH5L/BRvSCC9/Akvrqxp
+Ez5KCKWyAqEkmKIuV7rVRnTtS1EBCdUrX3TnDh9vghYXGM1M8AzJ8ZWKzIvdzfvR
+++Rs0QAAACCAAAAAAAAAAAAAAAAzSibdj0nGgRzoG7E0KwbpgPZLdQAAAYCZqwMK
+IaXJgYF0hyFnZByBweA8mydM+8J7xHJUKSd2beX6BTmztz8/FqyGaprsi0Rd7Zf7
+/wiDTtmMd+f8ieXcZXvvdm/3+/jnaHPhe+5BJ2LVb+EUF2CrTSW6/Utu8ltJo1Bm
+MtH44Qdwkwdg7BMlkyxaS6+ekBVCZN30QuxcQf7ZXRFSUVHbz7N1gUm62Bxiuc/3
+gWuPlTuLfAIlkNFYTpIdyVX1MorHKYPtXPDQQFb+DVMeYvj2yas8D81E4UhgtzEd
+JWHHfB0y9sadyPd5aMnYga2dteDBFP2oYovKAzXrf7nhXmJaq6tY/AEZTIG/b7LO
+VAd7giUOV8ansl3rbuOdS2hqXDB6dhKy2F7pJRJBPeopfkTzF75863CjMorwtAEA
+GkGFYrj/5Ol3G0tKjgtAx5E0nV1ORZ/mIKGi/HLi9sooVn1MJjK73htJhkwGuxJh
+nxMsHaj1ce9hPqxzn2arORTLP6GrhuBeUILrqiTr7qTPUb7vwn31Ev4/7n0AAAGA
+58LuGMOqNiwBgsalbCWEYoCDxz4EW+2o1lNpDJwvZUTt+XAsV8RVJzkFM2pfUXEQ
+ejE819Cw9Q+NM0LGAhnyKpAjOUBZ0F9GTESW1V2rbrCJhSf/TPVnjntb+14Y2SxK
+nXMojM4UUw/EcC9tA5fsOaiAxKctNYcwxWYzOG7eAoAjwXkfMWTRV054I8ebijyh
+ND6hZrpvArf/fp7yGY2xB/fMFZ87ahwAp4w1XFZt6wrG/eP2M8uRd6H7xsF2bKAh
+1f7EcBAau0QNLwaYIYGoySt83XZTNrmh4atwKD1tsKlj+2SMN8TimnTDdXcpEEmr
+R828EEwE25ZmgeqOu58Az0xKVGIRc3lXX72kuAGXlFH6lLGbTpNlZwXA9zTz4JFL
+uWweK4oPto+vFClu/fMwCtlbzei2fMSybmSI7vklz66sbw1lZ+i0E1X4nRwrj+aH
+v6LfXih+EwW4m4w4jCYZYJCsA1GrxWGq3Hl9qMzqQUbD6WCV6841Pg2kxVAZBSyq
+AAAAIEM8/QUyzP2M3Rslkg0rtzlph7dmJAN5A1sOhlJ86cUt
diff --git a/security/nss/cmd/bltest/tests/dsa/key17 b/security/nss/cmd/bltest/tests/dsa/key17
new file mode 100644
index 000000000..d5b014496
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key17
@@ -0,0 +1,26 @@
+AAABgPY7PN1kbY5921chaqbuwhNNcHSIofKc+plwZF8SJ+pdsuMY7qXaFofH7ZBQ
+lmk0XtYTTP8yIDq3Kuy/ppPSFq61XY0oqYH0q/8H0TGaeZvl3XRvhIQoF5KcMFtA
+hZivEgRdqi8czIvk2BtRPGMPAX/sFlisoQihr2Eg7AXjAYxCU8ndNbzgYrc9DyqT
+1BxIGlxDu5eQloLTmppg3Dw142N13sbO0NLbO6DREb7epwGg5HU2JJd6nnW3CnTi
+uB44pSqyLaExs1QW087JZjB5dGp2NHbldZgULjmGFUXar404oXbybHH1r+vZxWIN
+qAzzRStVw3xmG0oewDUXELneSjy+C5i02eyJEo2Xqn77GduLpDzAviXCAPkOFQbL
+eOwMM216lWE9QgTo7WjQ8KbHhCAQWo0tQ4+9JVGmShoLA/+4eHQvjJl5z6hzlBUC
+gZmNUXAdX8+paWpJif0l9ACVXmJrGr6SbAr6aappgZAO/83QMFkvgrIEKkeppajL
+AoPcTQAAACCAAAAAukY0tfpNoFS9DKSK5JDldxHzgRk4QkKRWbp8oQAAAYCK1FU8
+TkmqJHKKtQJEF7Ey0spTpV2VlFjy91mtsENb7u+jos/NADjiQgZD/EpN7rXZ/qoe
+3yEZO0DhS0KYKpTzXFi4EUfXGJ0mPJsS/mOrn6X28DooYMGGQy46sE8qsPL7YUe9
+m/ftXSBxO52iE4Piw6Fo59CdPYpaBY/SMJW1rP64ZKMwa+JCX6GtMq1tk4LmA7A8
+aK9K8CRjlxAsQVXLqBGr+Z2ng553surJlwWIyh0KI2FyOhZKySKcLoDc+o20+eKY
+A+/7MWjH/tejpt5A3aGaBTavm1t6+u+5xw1q6N8S2mWPYjYEOuqHPbKc628H0Qj1
+IlaHvQww4whOIJC0WuL5Kpe47LepcFxJVrizHEo9YRB8hOR63abIDV0i2rPYWSIP
+nVqrE2d6498WjwwXbRdrVFBsY5hT8E3e8nIvOcGOXOQm4UVirY/yYkeviIcO+3LA
+zOg23o/uZ6ZiN4JFtQK/H4MJmYigk8583IE2THix9KUbgA32E3xx1l5rCJoAAAGA
+QiQ1OeSdueoZ2Y2X9vKpSyNSmBLfiJ6qvP7aAc5MdZSH+4m8gtp1/hyRNDYfht5H
+0W2O7oDlasUCF46O2BKUd6+L+9gmLF7dk34ahsDw57Kv57y938tYFM7Qt1anbKF4
+Qju01XjF2hg3EtloWCZAqg7H6ftWv9lg16V1SXR9j7et5Hz+gWweV9pmM9rMU33g
+YIE5ZLtbJ1ejEvnaPYTmCv+YFwBR09kOOAuLzBmGxY/53JHogn1Pn1/EsrLnQ8+T
+if8C3sAfXUNLQw0WLokcM1X5GFUzn431gwDkyZOuTfjEMYtcS9BSg8pLRrfS+w9k
+dr8VkH9Q3UFBqnrKydqmLszTpnNXEiBgts7OBEapPrIwrZO8mk0bHv7soeP8g8EZ
+eFA1tDlQn/t5aLGkSLe9gxV1P98EolbsoVYqEbCWyQo2s1NlnL3kQg4X6QuUxDx1
+GcYGQc7sBW+Je5fWuxhhJo4Nx5t8O2t2OcJVvwaGVzdFkSbLRlvB2koEOhlj2n1j
+AAAAIFJKfqWXf4ECs1UpMEd/XwQkARZdRjfc2LnRPfTzquXQ
diff --git a/security/nss/cmd/bltest/tests/dsa/key18 b/security/nss/cmd/bltest/tests/dsa/key18
new file mode 100644
index 000000000..fe841bb26
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key18
@@ -0,0 +1,26 @@
+AAABgMe4bXBEIY42dFPSEOdkM+Tiepg9scVgu5dVqPt9gZkSxWz+ACqx/z9yFluU
+PAso7UYDmgfeUH16Kfc4YD3s0ScDgKQflx8lkmYaZLovNR2aaeUaiIoFFWt/4VY8
+S3fuk6RJSROEOKKri9z8SbTnjRzedm5UmEdgBX12zXQMlKTdJaRqp3sY6dcH1nOE
+l9Tqw2T0eS2XZqFqDiNIB+lrjGTUBLvbh245tXme9T/my5urYu8Z/cwr3ZBb7aE7
+nvesNfH1V8sNxFjAGeK8Gan138Hk7Knm1GZWQSQwSjHwOGBaPjQtoBvhwrVFYQ7d
+LBOXo8g5ZYjGMp7+tOFlr1s2ijmojkiI459Auz3k6xQWZy+Zn+rTeu8cqWQ/8yzb
+wPzr5ijX5G0oGpidQ90hQyFRr2i+P21WrPvbbJfYf8teYpG/i07hJ1rg60ODzHU5
+A8jSn0rbalR+QF3s3/KIxfbHqjDcsS+E05JJOnCTMxfA9eZVJgH64Y8X5uW7a/OW
+0y2KuQAAACCHb6CeHcYrI2zhwxVbpIsMz9op86xal/f/ob2Hto0qSwAAAYARCv67
+Esf4YrbeA9R/28Mybg1NMbEqjKlbLe4hI7zGZ9T3LB5yCXZ9JyH5X72aTQMjbVQX
+T7+v8sT/ferkc4sg2fN78KETTCiLQgrwtXkuR6klE8BBPzRqTturLEW9yhP1NBwr
+Vbi6VJMrkhe1qFnlU/FLuMEg+7nZmQnf9epo4Us3mWT9Pzhh5bpcyXDEoYDu9UQo
+cDlhAh571oy2N5J7jL7mgF+icoW/7k0e9w4CwaGKfNeL7x3Zza1F3enNaQdVBQ/E
+Zik37h1vTbEoB8zJW8Q18Rtx5whgSLHatZE8YFUBLeguQ6TlDPk/7/Xcq4FKvCJM
+XgAlvYaMP8WSBBu6BHR8EK9RP8NuTZHGPuUlNCLPQGM5jXfFL8sBFCfL/PpnsbLC
+0apKPacmRcscdnA2BU4vMfiGZaVEYciF+zIZ1a2HSKARWPbHwN9ajJCLqMPlNoIk
+KIhse1ALvBW0nfdGud5aeP47T2mR0BEMPL/0WAOdw2Jhz0avS8JRU2j0q7cAAAGA
+RWoQXHE1ZiNIOLwHC4p1GgtXdny3XpkRShpGZB4R2h+p8ikU2AitcUhhLB6lXSUw
+F4Hprgya42pp2HugOex82GTDrQlIc+blZwn9ENlmhT1hGxz/FdN/3uQkUGwYTWLH
+AzNYvnjCJQlDtvbQQ9Y7MX3lblrY0f2X3TVavpZFL45DVIX7O5B7UZAKo/JEGN9Q
+tPza+/YTdUjDk3O4vEuj2rtHRuvRe4f81qLxl8EHsY7FtGXm5MtDDZwM542lmIRB
+BUo3B5K3MNqaukGjFpryYXb3Tm98DJybVbYrvnzjjUaV1IFX5mDCrLY/SC9VQYFQ
+5f7kOs6ExUDDunZiroCDXBotUYkOqWuiBkJ8Qe+MOKoH0qNl5+WDgNj0eC4irCEB
+r3Mu4idYM3slNjeDjhb1D1bTE9B5gYgNaFVX99eabbgjxh8bs9vF1QQhpIQ6bylp
+DniqDwz/MEIxgYuB/EokP8APCaVMRm1qjHPTKlXhq9Xsi04a+jKnmwHfhagfP1z+
+AAAAIDRwgyBV2t6U4UzYd3Fx0Y5dBvZq7/TGFHHk66dO5WFk
diff --git a/security/nss/cmd/bltest/tests/dsa/key19 b/security/nss/cmd/bltest/tests/dsa/key19
new file mode 100644
index 000000000..5f769bec2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key19
@@ -0,0 +1,26 @@
+AAABgKQQ0j7ZrZlk0+QBy5MXolIT91cSrLxcEhkavz8cDnI+IzO0nrH5Ww+XSNlS
+8Epa41iFnThEA842SqP1jdl2mQm0UEhUjFWHKmr7s7FcVIgvlsIN8bLfFk8LrISc
+oXrS32Or11yIGSLnmlAJ8At9YxYi6Q5/pOmAYYV14da9GnLVtqUPT2pot5OTfEr5
+X8EVQXWaFzZXfZRIuHeS3/ByMkFVEukzdV4SJQ1GbpzI3xUHJ9dH5R/qeWQVgyax
+Nl1YDLGQ9FGCkVmCIf3zbGMFyLio7QVmPdewBulF9ZKrvsrkYPd8cbbsZJ0/1TlC
+Au17u9BA97j9V8sGqZviVPol1xo3YHNARsKg2zg+Ajl5E65nzmWHDZ9sb2ep0ASX
+vh12OyGTfPnL+aJO+Xu8qgeRb4iU5bf7AyWIIaxGFAllsjxUCcpJAm77K/lbzgJc
+QYOl9lm/aq7vVteTO7KWl9fVQTSMhx+gH4aWeLLjRQb23ApMEytomg7SfcPI1TcC
+qlhIdwAAACCrxnQXclzyj8dkDV3kOCX0Fuv6gOGRxC7ohjAzOPVgRQAAAYCGfV+3
+L1k20aFO07YEmWYvMSRobvEIxbPaZmOg6GGX7CzEyUYBk6dP8WAorJRBsMfSfCJy
+1IOsfNeU1ZhBbE/5CZphZ51BfUeM5d2XS/NJoUV1r+dKiLEt1fbRy9P5Hd1ZftaO
+eeukAmExMMIkuUrChxSh8cVSR1pdKc/N2OCKax1lZh4o7zE1FNFAj1q9Pgbr46fY
+FNHt4xa/SVJzyh1XT0K0gu6jDbU0ZvRUtRoXWguJs8Bd2gBucZouY3FmkIDXaMwD
+jN+4CY6arZuNg9S3WfQ6ydIrNT7YijNyNVAVDeA2G3o3bze0XUN/cctxHyhH3mca
+0QWVFqHUV1UiShXTe0rq2j9YxpoTba7wY2/jjjdSBkr+WYQz6ACJ/aJLFEpGJzS+
++Pd2OIRbAOWc5/pPHa9IeiytoR6rpyuyPh32tmoYPt0ibEQCct2bBr7A5X8aCCLS
+4AISBkttumRWIIX1p1kpr6X+UJ4LeOYwqvEvkeSYDJsNb34Fmi6j4jR52TAAAAGA
+HwpcdeeYXW5w5Pv9pRoQuSX2rMtgDXxlENuQ7DZ7k7sGm9KG6Pl5si7wcC9xeodV
+wYMJyH2uP+gsw9yPS3qj1fOHb01LPraL/pEMQwdtbNDTn8iN3njwlIDbVSNObIyl
+n+JwDv7AT+7mtOjuJBNyGFi+cZDb6QX0Vu3KtVstwpFtwehzGYjZ74thmrz4lVqp
+YO8Cs/AqjcZJNpIir1DxM47SjWZ/PxDK4qPCijwdCN9jnIGtoTyP0ZjG2uPWKj/p
+8EyYXGX2EMBsuPrqaO24DebPB6jonAAhgYWpUrI1cuNN8HzltCYeXeQn61A+4br1
+mS221Di0dDTEDCJle8Fj55U/oz7/OdwnNGBwOardasJ+Q2cTEEH4Rf+hoT9Va/ui
+MHpcePLM8RKYx2LgiHGWjkjcPRVp0JllzQnaQ88DCaFq8eIP7n2j3CGzZMRhXNUS
+P6X5sjz8T/2c/c6mcGI4QLBi1GSNLrp4atP3rjN6QoQySs4jb59xdPv0QrmQQwAv
+AAAAIG1Mk0ORt/b7bhnjFB+MABjvVyYRihEGQ1jH01s3c3N3
diff --git a/security/nss/cmd/bltest/tests/dsa/key2 b/security/nss/cmd/bltest/tests/dsa/key2
new file mode 100644
index 000000000..7df1a9031
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key2
@@ -0,0 +1,10 @@
+AAAAgIubMvW6OPqtXg1QbrVVVA0NeWMZVVjKMIt0ZiKNkqF7OxS44Kt3qfOylZoJ
+hIqmn435LNnp7e8K33ks53v87Mrdk1JwDKX67PGB+gwybbHW5dNSRYAR5RvTJI9O
+O9fIINfgqBkyrKHro5AXXlPq2hlyI2dOOQAmPpD3LZTnRHv/AAAAFLxVDpZWR/s6
+IPJF7IR1Ykq7sm7dAAAAgBEzOpMfulA0h3dzdoWf3BL3xoewlIroidKH8benEq0i
+CuTxzjedDbtcmr9BliHwBfwSPDJ+UFXRhQY0w205fmieER1ZjBw2NrlAyE9C9DaE
+bo5/ytkBLO2jmHIPMv/9GkWrYTbOQXBpIHrBQGdbj4bdBjkVrm9isM7HKfvVCawX
+AAAAgH4znzdXRQOQFg4CKRVZ8wvtCy11jFzMLY1FYjK7Q1rknefnlX46rZv9z2/V
+2bbuO1IbwiKahCHcKqWbmVI0Wo/B3kmzSAA6mxjaZC1/b1bjvGZRMa6XYgiKk3hv
+e0typLzDCMZ+JTKjpb8JZSBVzCa/OxiDNZjP/XAR8ihfeUVXAAAAFG4uMbv8ZwlE
+16cSDjmpgVIGFNio
diff --git a/security/nss/cmd/bltest/tests/dsa/key20 b/security/nss/cmd/bltest/tests/dsa/key20
new file mode 100644
index 000000000..5a5dbfdb1
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key20
@@ -0,0 +1,26 @@
+AAABgMHQptC17WFd7nasWmDdNeywAKICBjAYsboKBv56APdl2xxZpoDOz+OtQUdb
+rbWtULYUfiWWuI00ZWBSrKeUhupvbskLI+Nj86uM3IuTtioHDgJojqh3hDpGhcK6
+bbER6a3b18pLzmW7EMnOtpv4BuLr1+VO3rf5lqZckHtQ79+OV1uuRiohnDAv7yro
+HXPO51J0YltfwpxtYMBX7Z57DUatL1f+AfgjIw8xQiciMZzgq/HxQfMmwA+8K+TN
+uJRLb9BQvTAL2xxfTaclN+VT4B1RI5xNRhhg8ftP2Pp59dUmP/Yv7XAI4uCi02v3
+uQYtDXXbImw0ZLZ7okEBsIXyxnDA+HrlMNmO5gxUcvSqFfslBB4ZEGNU2ga8Kx0y
+LUDtl7If0c2tMCXGnabOnH3fPc8epNVld7/ewjBxwfBe5Ad7U5HppATq/+EtHqYt
+BqzWvxnpGhWNIGa0zSDkxOUv+x1SBM0CK8cQjyx5n7Rohm7xywm84J39SeR0D/gU
+BJe+YQAAACC/ZUQcmHt3NzherewVjdAWFNpvFThiSOWfPN2+/I6d0QAAAYDAKshT
+dfq4C6KnhLlOTRRbO+D5IJDroXvRI1jPPgP0N5WE+HQiUvdrHt4/w3KBQg50qWPk
+wIh5b/K6uNtumkUw/GfVH4i5BatDmVqrRjZMtAwSVvBGbz2842ID7yKLNekCR+le
+URXoMbEmtijumE80mRHTD/udYTtQqE36HwQrpTa4LVEB5xHGKfnyCW3INN7sY7cP
+KiMVptJzI7mVqiDT0HNwdRhvUEmvb1EqDDip2gaBf0thm5RSDt+shcSm4uGGIlyV
+oE7Dw0IrjesoTpjSSzFGWAIAigl8JZaegmwrqlnSy6M9bB2fOWIzDB/Np8+xhQj+
+p9BVXjoWna7TU/Pub0uzAkQxkWHf9kOKN8p5OyS7sbG8IZT8bm72AngVeJnLA8Xd
+b8kag26yCiXAmUVkPZX3vVDSBmhNb/wU0W2C1feBIlv/kIOSpXk7gD+bcLTfyzlP
+ntgcGOORoJ6z+ToDLYG6Zwyr/W9kql4zdMt8ICn0UgDk8L/YIMi9WNxe6zQAAAGA
+baVPKw3bTczi2h7foWuoSVPYQpzmDNERpcZe3Pe6W42Th6togcJIgLKvvbQ36e1/
++46Wvsp+qA0dkPJNVGESYp31yelmF0LMhy/bPUCbx3t1sXx+bP/4YmEHHEtcn5iY
+vh6eJzSbkzw0+zRWhfj8bBJHDRJM7PUbXVrb9eeiSQ+NZ6rFOoLtaiEQaGz2McNI
+vLxM8VbzppgBY+L+ynKkX2s9aMEOWiKDtHC3KSZ0SQOD91+ibM+TwOHI0GKMo18v
+PZtodlBdEYmIlXI3ovyAUctHtBDot6YZ5zsTUKn2omDF8WhB58TbU9jqoLRwjWL5
+Wypy4vBMoUZHvKa14+5wf833WLkl641Oas5Px0Q8m8WBn/nlVb4JiqBVBmgo4huB
+j+3DqsUXoO6PkGC9huDUzOISq2o6JDxewCdFYzU8pxA68IXo9BvlJPu3XNqIkDkH
+35S/1pNz4oiUm9BibYXBOYswc6E51cdH0kr9rno+dFQ3M10O6ZPu82owQckS9+tY
+AAAAIBULXFHqZAIna8kSMi8EBPbVf/fTKvyqg7bf3hGrtIGB
diff --git a/security/nss/cmd/bltest/tests/dsa/key3 b/security/nss/cmd/bltest/tests/dsa/key3
new file mode 100644
index 000000000..50c0a9b31
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key3
@@ -0,0 +1,10 @@
+AAAAgMuhPlM2N8N8DoDZ/NBSweQaiKwyXE6+E7cXAIjVTu9IgfPTXq5HwhA4WoSF
+0kI6ZNo//aY6Jvks9aME85JgOEqbd1nYrBrcgdP4v8XmyxDvtOD3WGf06EjRozhY
+bdBkj+6xY2R//nF2F0NwVA7oqPWI2ozBQ9k59wsRSn+YG4SDAAAAFJUDG4qnHynV
+Jbdz74t8ZwGtil2ZAAAAgEW8qkQ9TNFgLSeq+EEm7cc713Pebs4V6X5/70bxMHK3
+rcr3sAU89HBpRN+MRWjybJl+53UwAPvkd6N3ZqTpcP9AAI65ALneS1+a4G4G22EG
+54cR86Z/7KdN1b3c32da5AFO6UiaQpF/vuO7nyok32dRLBw1yXv78jCOqs0oNoxc
+AAAAgEzWF4Y30PDeFIhRXDsS4gOjwMplLy/jDQiNxyeKh6/6Y0pyenIZMtZxmUqV
+ig+JIjwobDqbEKllYFQuJia3LgzSjlEz+1fcI4t/qy3ipJhj7PmYdRhhrmaL98rR
+NuaTP1ff26VE4xR84Oc3D6bo/x3mkMUbSu7fBIUYOIkgVZHoAAAAFC6sT0GW/ts+
+ZRs7AAQBhM/W2iq0
diff --git a/security/nss/cmd/bltest/tests/dsa/key4 b/security/nss/cmd/bltest/tests/dsa/key4
new file mode 100644
index 000000000..657abc8c4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key4
@@ -0,0 +1,10 @@
+AAAAgPJKSvxyx+Nzo8MJYjMv5UBcRZMJY5CUGMMHkqrxNd3qVh6U8kcmcWt1oYgo
+mC5M5Ewf3ct0ZIe2t3qaWhf4aKtQzWIbW8naRwiAsofXOYGQpCpe4i7Y0f8UfiAZ
+gQyCmO1o4cpp1B1VXySeZJ+xcl3bB1wXs3vv9Gf90WCSQzc/AAAAFNoGWgeN21bu
+XSrQbK+rIIINLEdVAAAAgEe1WRt5BD5OA8p4oOJ3yaIeKmtUO/TwRBBM2ayT7/jh
+AbtgMe/IxZbV0vkuOj0PH3RwLdVPd9PNRsBN7npd6fAK0xdpH93O/koiCiZRrK5/
+zt2pK/zKhV22cF6Nhk+Bkr9r+GDADwitZJPswYcuACjVyG1EUF21dCJRXDglpveK
+AAAAgEOie3QPQiyy3D6qIyMViDovaiKSf5l9Ak9aY4tQexfTscvT7GkcxnRHCWCg
+FG797Llbtf4kl0njyAbNXMPn97q4Rdrb4fULM2b7gnqULOYkbdp70sE+G0qSbAyC
+yIRjlVLZ1GA2+aS8Kp5RwtduMHTR9TpjIkxCeeD6RgR01P/eAAAAFGSYIBaOtZT1
+nNmyi5rv6MwQamxP
diff --git a/security/nss/cmd/bltest/tests/dsa/key5 b/security/nss/cmd/bltest/tests/dsa/key5
new file mode 100644
index 000000000..8d94d7fa7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key5
@@ -0,0 +1,10 @@
+AAAAgIjZaOlgLsvabYb3yXCj/76x2pYvKMCvuScO8FvDMMqYw634PAcv6wX7Lik7
+UGW7sMvMkwwk2NB4ad6uzZKiYEwPXdNcW0Mf2moiLFLDViv3VxxxAgm+izuFiBh4
+hyX+gRK31ryC4P8cu/XW/pRpCvK1EOQa2CB9wsAvufpc76q1AAAAFKZlaJueW5zo
+L9FnYAbPTPZ+zFa3AAAAgCZ+KChXQXdSET+6P8pxVbXOiefIozwaKRIuK3IJZfwE
+JFJn/4f8Z6VzD+WzCAE6oyZpkPuzmBhah+BVtEOoaM4M4TrmruMwudJdO7s2JmXF
+iB2vDFqnXp1KgujwTJGprSlIIuM5eKsME/rcRYMfnTfaTvoPwsXrATcfqFt92x+C
+AAAAgGD1NB5Iyno7xd7O5hIR3ScnzY4vx2NfOqvqJiNm5Fj1xRwxGv2pFssNzcXV
+pXKfVzpTK1lHQxmbz6dFSQPnSzPd/mWJYwbOwg69hCdoL6UB7ga8TF0UJcvjGCi6
+AIsZydpoE2z3GECyBZGeeDpiilpXz5HPVpsoVP/veglu2pbJAAAAFAfOiGLmS39s
+dIIEbb/JOQcSPlIU
diff --git a/security/nss/cmd/bltest/tests/dsa/key6 b/security/nss/cmd/bltest/tests/dsa/key6
new file mode 100644
index 000000000..3408d5cc9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key6
@@ -0,0 +1,18 @@
+AAABAPLTntMGKxPJFic2AKDyoCnobXpLkhe08YFb8rJNlxClerM/mXKUsBRYW40B
+mN/cy811MU2l/4WqNEtFra6ql5tRoxKnv6lEcvtjPxpvFWu0RYhn39OEA/BrhR8A
+/i00hAd73tcat1E9BKFAIgV1+2kzlUgOTIQCt6Rs7C03p3jDBazNHxPp9i6GUxX0
+sizEZ8iYbsjklh3fgQVmsMTuNprGqhXkP0dEAFgm9b3oBxoZ4wtpCarEs9F0I3Jw
+2tAnmdCbiizF8i5miUtUIiKLLCNPEfWnccW4nPRloqzsu+6qFyX+j5tZQivomRBS
+y1Vt3yyM6PqSBtvzn+rcGU4A+OUAAAAcgAAAAAAAAADBGPSYNeTvczxNFYAPzwWe
+iE0xsQAAAQDjqTwJ2m9WDk1IOjgqTFRvIzXDakw1rBRjwIo+bdQV31b9xTfyX9U3
+K+Y+T1MAeAt4LxrNAci06zNBRhX9Dqglc6y6fvg/WpQ4VBUa/C19/hIfuM0DM1sG
+W1ScXcxga+kFJIO8KE4SrDyNugm0JuCEAgMOcLwcwr+JV8S6BjDz8yrWiTiaxHRD
+F2Bj8kfZ4ilrPqW1vCM1go6hoIDtNZGN7iEv0DEnnRuJTwGv7FI4M2aerAMaQg5U
+C6EyClnEJKPlhJpGCla8sAFkeIWxQzxPmSlxdGv+KXfOclnFULVRpsNXYeSkGvdk
+6NkhMvzApZ0WhOq5DYY/KfQc91ePqpCMAAABACif8YwypWuwuIOTcGR2g6OKWn4p
+FBC5MgchKtyAiNMPk+nkq8Uj89RpNufVyQ2IdCs2r9N1Y0CPFcjBpPesJL8F8BAI
+/+5wyIJdV8OpMIutigla8rU7Ldo8vthG2V4wHrm4R2ZBXRH2wzIJoNKFcQlqsEp5
+qg3EZZl1KWhraOiHzYogXC3IGVrvBCLrqZefVJrIVUjkGUE2Q7ckQ2EVOtoUgNI4
+zQDcFlJ5OJVVSN1dAn3tECnu647WxhtM1ZNB2LFUZunaiQqYmZb012keYHLeE2ry
+i1h0vwi9H4pgz7HACIgTKQn1FeBLzoGwKVGqQbqsaP/bjF3Heh0y2PLBDdcAAAAc
+YTLlUc2siECRg7037hRSzSR9SDSwiBSydb4/9Q==
diff --git a/security/nss/cmd/bltest/tests/dsa/key7 b/security/nss/cmd/bltest/tests/dsa/key7
new file mode 100644
index 000000000..e7830fb08
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key7
@@ -0,0 +1,18 @@
+AAABAKqBXJ2xxNPSdzx9DU0dp17PxKOel9X6GR/+yLFJCikM4zXlzofqYgqKF94L
+tkcU4uyEC/AObr20/7TjJMoHw8hxcwmvFBA2Kncsmt2DiysMrh6Qq0SK2r2s0uXf
+WcQYejKiNxnWxX6UAIhTg7+PBm8juUGSDVTDW098xQRPO0DxcEaVYwe3SOhAcyhE
+0Aqc5uxXFCk7YmUUfxXGf0vjiwgrVf3q22EkaJ+3b50lzCi46qmLVi1cEBHg3Pmz
+mSMkDTMtidyWA7e93QxwuDyqKQVjGxyDyruubAwMLv6PWBMe2DUb+T6HX2pzqTy6
+1HAUGiaH+6zy1xyN3ulxrWYHKa0AAAAc6jR+kL58KHXR/h22IrR2ODfF4npgNzED
+SMGqEQAAAQAgQglMy8i4cj/JKMEv2mcbgylemcdDV29EUEvhGGMjMZtQAtJPFz35
+CeokHW6lKJkE7kY2IEsvvpSwaP4JP3liV5VJVR068hmtjtGZOe/4a87INN4vL3hZ
+bonny1LFJOF3CYpWwjLrH1Y6qEvGsCbe7m/1HLRB4IDy2vrqHO2GQn0cNGvlXGaA
+PUt20TPNRFtMNIL6QVAjRjyb8w8veEIj4mBX06oNf7tmBjDFLknUoDJcc4ngcqo0
+nxPJZuFZdS+7cekzaJD5MkP6bnLSmTZe5bP+Jm6/ERBWj+5EJchHtQIQvUhLl0Ma
+QoVq3KPn0anJxnXH4maRgyDdWnikjEipAAABABrhDHhq0JAsXGhdrlxxIUGKN3uI
+i18vK8dmI1cP1ivLGQtHGtU1nF8GL4gZKJ6VbYqm+Q0fjPHuctOhvf1WxHjcKaGc
+RWm1pg46jzT2BlbqxbJd3lUUpcZ7Z1QjIE9syvCZBhfMc1W50+2GiXiiUgIKdp7V
+mm7apu/jN37vRfP28+ZBecx9uLFD+4NcXXG/z6HiqQSbzPf+mrV1RiIP4/S3UhyG
+FznROFB+gaRqaZNgVEHcuQ1u5K+8Qsq+kKJUREloEJ1+3ZaUoCMjnx1WF13R+sEV
+kV4k+rVj9Pw/JpvtLzAIMtESWWSFpxFBeqc7tKxyplGh+luu02Nscg05cAgAAAAc
+e0iQIVeOeee9PuerRW9lnz3AfIj1yaOeT4zugQ==
diff --git a/security/nss/cmd/bltest/tests/dsa/key8 b/security/nss/cmd/bltest/tests/dsa/key8
new file mode 100644
index 000000000..e7e72bd30
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key8
@@ -0,0 +1,18 @@
+AAABAKTH6qtCxMc7dXdwkWSJ8XzVByXNCkvE4c9n92O4wd4tbauYVrqvsAjzZbGK
+QuFNxR81C4jsoCCcWqT9caepbHZfWQHCHnIFcNeDe+x8dtLkk0RzHKOUBdCoebng
+3NGoEl/RMOweeD5lS5TjAC5rYp6QSrOHeGdyDL1UtCcKnhXNAox8x5bwbCcqZglR
+ko/b6y3KBhtB6TIlcwV0L/FuL0KRkdXl8abd9ueMXXciz/gKnAvVyNeuuowEQ4mS
+sHXjB8FTTEmtOA9Hf195h9wXLBYdyjjcrz+zhGxyyRGaUpmtx0iVGz3ODQDUqQE4
+ALIAggO3JGW8aoSuBZowxFIt6lcAAAAczon+MyuOTrPR6N3OpdFjpbwTtj8WmTdV
+QnrvQwAAAQCMRl7fWhgHMCkeCA38U4U5elAGRQ26Lv4BKSZPvYl7tVecoOqxmqJ4
+IgQkcktPKm9u5jKEMqv2YTgGRglyM1BTOcVRnTV9cRK27sk4uF1ap1zC44CS8KUw
+rLVOUP6CxNVi+w8wNrgLMDNAI+u+ZjegAQsAx9uGNxFoVjZx4eDwKK7b1F0tVyYh
+pgmYKgc+Uaridwevvu8p4uzuhNem1do4K+OjX0K2xmhJICqxnQJbhp0Id2R20auY
+FHWtKtLz5v0H4waW2QpiaBbfYNbKev17SC+UL4O0XMgpM3Mfh/ruMgkA8qo+cLGG
+fhQw5AvmfAf5KQKZ7wZ7iySnUVs/mSwHAAABAHSKQCNyEaLZhSWW56iR9D1OsO5I
+gmyc+zNru2jb5aXhay4ScdTRPeA2RLuF72vlI6TU2IQVvNWWuo4KPE9kOemB7QE9
+fZxwM2/r99Qgz+0CwmdFe7Pz58ghRdKvVIMLlC7HSl1QPkImzSXddd7NP1DwqFgV
+XXvnmUEINt3FWc6Z4a5ROAj9rqw0hD3XJY8W9n8ZIF9vE5JRpBhtqEltXpDT/s+O
+0Qvmwl/16zPZYMmo9MWByMckykO3Yen9ta9mv/udLrsRprUEofvk+DTstqwlTKtR
+PpQ7mpU6cISzMFxmG/rUNPaoNVA8mt5/Slf1yWXsMB7N6TjuMbTesDivl7MAAAAc
+VRWV7MuwA7C/jd2hhKWdpR5Fmg0oIF5VkspMsQ==
diff --git a/security/nss/cmd/bltest/tests/dsa/key9 b/security/nss/cmd/bltest/tests/dsa/key9
new file mode 100644
index 000000000..1ab8a0c90
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key9
@@ -0,0 +1,18 @@
+AAABAKa7UzPONDwxybLIeKuR7vL96jXG2w5xZ2K/wNQ22HUG6GWk0sjPu9Ymzov+
+ZFY8pWhs2M8IFJDwJEWyiQh5gklftpl2sQJC1tUPwjtNvbC+94MF2aTQXZ6uZdh6
+iT6vOX4E45uqhaJsj/ve8SMyh7X1tu9qkPJ6aUgaky7kexjV0n6xB/+wUCXmRuiH
+a1y1Z/7B3TWDXUIIIZhTH6++WuKAxXWh+w5i6bPKN+GXrZbZ3eHzPyzsfSferiYc
+g+6OIAKvfrboL2oUeWrwN1d6EDK7xwkSnKq9it34cK4tBZXI/bNxVXSPDeo0tE1P
+gu1YwvWxuEgWYqxTRzxpNBAIL70AAAAcjD7lvZoqrwaL1YRb1V7PJ0FwVTB1d7vD
+dw7GiwAAAQBDtaa20LuWLsl2ajd8MsxBJPExEYjC7PlcDNSk+glyJbdhjLEnbEdF
+eNO/VkwUUZnAkqGxS6qSnC8/DzbgwtrpHroIvjCZKoifKVLgRCw3r0hKTs3DJDzP
+y540E89c3WYwsJ/hfvv94U2HJUkwGbe3PR94K0jvML7DbgDgK6M20iVPwgKmlhLN
+lEb5HXa3Of+m2LhgUvjcXxFFgBxWJBr1upA3JBvYnmM4tY4BMQZxwmjrXjOstX0f
+mfFkQKZ1gn1AF3VNYBoXraL77fkEVUqQsBUw2oyTzRTOKTyyvT55N+k0t54xD+TY
+DBP5L2M4E1W9gKGr7hpz/fttok7ygAKjAAABAGR5ebeWDOe5cf8OX2Q19CpBsYyd
+4JowERSgE6fNARg/F2+Ig4N53LTvtn2up53vPwQsvPnMUDtMIVGiNk98lDexlkPm
+fiSja6xKTPopPe7fjsaxVKMqpymF99jeI1M0tUbCne9FjFXQxcCsXXTiAk7H1KvC
+/aUWoqCxpNiGrZLCBHB4KKT8d5T2DuikvhEByeVRj34Z7r1HXy3m9rqJwovRKfE5
+k77+WBhEAxmnlUmDMZY0KjHbr315SX3sZe59vvcOWPmdBZX2pxFAmt4xUdRVY9U8
+HNCoqxoYvv9lAsuwwGmxFOp753iY0PTlSZkboLNolxsQcuzkr8OA6a4ymlAAAAAc
+TvpRNutqp06Su/yROwv+u2E9t6RyIft7ZPQubw==
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed0 b/security/nss/cmd/bltest/tests/dsa/keyseed0
new file mode 100644
index 000000000..6eea359db
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed0
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed1 b/security/nss/cmd/bltest/tests/dsa/keyseed1
new file mode 100644
index 000000000..6eea359db
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed1
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed10 b/security/nss/cmd/bltest/tests/dsa/keyseed10
new file mode 100644
index 000000000..054c192d9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed10
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed11 b/security/nss/cmd/bltest/tests/dsa/keyseed11
new file mode 100644
index 000000000..cde1798da
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed11
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed12 b/security/nss/cmd/bltest/tests/dsa/keyseed12
new file mode 100644
index 000000000..cde1798da
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed12
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed13 b/security/nss/cmd/bltest/tests/dsa/keyseed13
new file mode 100644
index 000000000..cde1798da
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed13
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed14 b/security/nss/cmd/bltest/tests/dsa/keyseed14
new file mode 100644
index 000000000..cde1798da
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed14
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed15 b/security/nss/cmd/bltest/tests/dsa/keyseed15
new file mode 100644
index 000000000..cde1798da
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed15
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed16 b/security/nss/cmd/bltest/tests/dsa/keyseed16
new file mode 100644
index 000000000..cde1798da
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed16
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed17 b/security/nss/cmd/bltest/tests/dsa/keyseed17
new file mode 100644
index 000000000..cde1798da
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed17
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed18 b/security/nss/cmd/bltest/tests/dsa/keyseed18
new file mode 100644
index 000000000..cde1798da
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed18
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed19 b/security/nss/cmd/bltest/tests/dsa/keyseed19
new file mode 100644
index 000000000..cde1798da
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed19
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed2 b/security/nss/cmd/bltest/tests/dsa/keyseed2
new file mode 100644
index 000000000..6eea359db
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed2
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed20 b/security/nss/cmd/bltest/tests/dsa/keyseed20
new file mode 100644
index 000000000..cde1798da
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed20
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed3 b/security/nss/cmd/bltest/tests/dsa/keyseed3
new file mode 100644
index 000000000..6eea359db
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed3
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed4 b/security/nss/cmd/bltest/tests/dsa/keyseed4
new file mode 100644
index 000000000..6eea359db
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed4
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed5 b/security/nss/cmd/bltest/tests/dsa/keyseed5
new file mode 100644
index 000000000..6eea359db
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed5
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed6 b/security/nss/cmd/bltest/tests/dsa/keyseed6
new file mode 100644
index 000000000..054c192d9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed6
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed7 b/security/nss/cmd/bltest/tests/dsa/keyseed7
new file mode 100644
index 000000000..054c192d9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed7
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed8 b/security/nss/cmd/bltest/tests/dsa/keyseed8
new file mode 100644
index 000000000..054c192d9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed8
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed9 b/security/nss/cmd/bltest/tests/dsa/keyseed9
new file mode 100644
index 000000000..054c192d9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed9
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
diff --git a/security/nss/cmd/bltest/tests/dsa/numtests b/security/nss/cmd/bltest/tests/dsa/numtests
new file mode 100644
index 000000000..aabe6ec39
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/numtests
@@ -0,0 +1 @@
+21
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext0 b/security/nss/cmd/bltest/tests/dsa/plaintext0
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext0
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext1 b/security/nss/cmd/bltest/tests/dsa/plaintext1
new file mode 100644
index 000000000..f7b1badf6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext1
@@ -0,0 +1 @@
+WEKejzcfnh1ppb+WpVTWJ8/VSFw=
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext10 b/security/nss/cmd/bltest/tests/dsa/plaintext10
new file mode 100644
index 000000000..08d653e66
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext10
@@ -0,0 +1,2 @@
+rBhknAaqqqlnKm/advb86OGGUVWFcbz9ihmsNZcQniSGMCNRB1ROUVCb5azZuiZ+
+4ImIYj1aymGnxDoIS+YZng==
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext11 b/security/nss/cmd/bltest/tests/dsa/plaintext11
new file mode 100644
index 000000000..05f0054e5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext11
@@ -0,0 +1 @@
+PlUtQFJV4fg6RHC9IFSw1nSy/dY=
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext12 b/security/nss/cmd/bltest/tests/dsa/plaintext12
new file mode 100644
index 000000000..639a7cce7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext12
@@ -0,0 +1 @@
+tGiqjB9KQERHn6GvDD8iHrgM5nYcmcaGbRp9nQ==
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext13 b/security/nss/cmd/bltest/tests/dsa/plaintext13
new file mode 100644
index 000000000..924d0edc2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext13
@@ -0,0 +1 @@
+CrhLNBzxdeOM06JwSiDHlsHH0AlCJKHkdpQvJw4OTio=
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext14 b/security/nss/cmd/bltest/tests/dsa/plaintext14
new file mode 100644
index 000000000..967d952be
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext14
@@ -0,0 +1 @@
+4II54Zw0xvxpgkZbrlGIWAPGug2Ih8VgwXb+NG3cRkcdkNR5SHsy/jDgrlTYQGn/
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext15 b/security/nss/cmd/bltest/tests/dsa/plaintext15
new file mode 100644
index 000000000..a702f7ed2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext15
@@ -0,0 +1,2 @@
+OfmOLA3KSs6DsKB+owDqX4JKdU9bT3xwUOJzPGkrsyKo3mur8w2dklEbOObDF5zg
+XxEGB/8DFIp8sCqeP2qewg==
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext16 b/security/nss/cmd/bltest/tests/dsa/plaintext16
new file mode 100644
index 000000000..dfa0cdaa5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext16
@@ -0,0 +1 @@
+mbNzEDnv9o8UR+5qjp+UCBlCe70=
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext17 b/security/nss/cmd/bltest/tests/dsa/plaintext17
new file mode 100644
index 000000000..ec01a51bd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext17
@@ -0,0 +1 @@
+INmoiblVarLpT/1EghXog/90qXfqHhqcQlUsmg==
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext18 b/security/nss/cmd/bltest/tests/dsa/plaintext18
new file mode 100644
index 000000000..84a985629
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext18
@@ -0,0 +1 @@
+b5h4y7cMDS2TQtEP6tSlMuxCp3q1hlT3LLt7noMBKrA=
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext19 b/security/nss/cmd/bltest/tests/dsa/plaintext19
new file mode 100644
index 000000000..aa054c5ce
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext19
@@ -0,0 +1 @@
+kYTu+RQoZJZSUNshOvoBQxBj2N7aAyjFYJzs0WWVBdRaLlujVOVu2dlxGwJktm9M
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext2 b/security/nss/cmd/bltest/tests/dsa/plaintext2
new file mode 100644
index 000000000..bf54afc07
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext2
@@ -0,0 +1 @@
+IDdekD+X/lylh+t2yXvLHboeHUZAZUozsUU48g==
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext20 b/security/nss/cmd/bltest/tests/dsa/plaintext20
new file mode 100644
index 000000000..20c8ee2c3
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext20
@@ -0,0 +1,2 @@
+Q6bpLpUVhU3Sjdd4YG4BnAfUf4u6TrwCAzmSB0q66YryvQBzf3fQ3H4fp4GVuYRV
+ftjzEtAhCf9OYBtR4GSnvA==
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext3 b/security/nss/cmd/bltest/tests/dsa/plaintext3
new file mode 100644
index 000000000..a8ec5df96
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext3
@@ -0,0 +1 @@
+Mqqlk48AsWXhRAWNXCGQuvRpPAwqfbTlmnfsFKcKblA=
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext4 b/security/nss/cmd/bltest/tests/dsa/plaintext4
new file mode 100644
index 000000000..46644c0d5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext4
@@ -0,0 +1 @@
+w8+3pOAcqljMh1bLGnWAWlZvlgnJhOJDBC2C0M3mTFrCeylP+FfUSfGfRD2uDS2f
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext5 b/security/nss/cmd/bltest/tests/dsa/plaintext5
new file mode 100644
index 000000000..631d1eb9e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext5
@@ -0,0 +1,2 @@
+PiPosk1QVF3Ck1taH0AunEzHuPxBHnFMTKPWBsxTI9YdZ5XAEzt5QPHQKm7ja20+
+bmsWwSw++jcz8N2DY6WW2g==
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext6 b/security/nss/cmd/bltest/tests/dsa/plaintext6
new file mode 100644
index 000000000..f62997be7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext6
@@ -0,0 +1 @@
+uCkA/iALiJlpG34VqA2JNi5cqJY=
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext7 b/security/nss/cmd/bltest/tests/dsa/plaintext7
new file mode 100644
index 000000000..c0f0aa06a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext7
@@ -0,0 +1 @@
+KfVXa9k+jC0vrKPpgWQNMrHmPXpYTROh7YXBMw==
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext8 b/security/nss/cmd/bltest/tests/dsa/plaintext8
new file mode 100644
index 000000000..9c053cbf8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext8
@@ -0,0 +1 @@
+GC7dULJ04jKDdn7fzRjVyUZm7aDbl31cEJU6STyznuA=
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext9 b/security/nss/cmd/bltest/tests/dsa/plaintext9
new file mode 100644
index 000000000..c0378ae02
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext9
@@ -0,0 +1 @@
+hV6v7+GSeeSI2lL+Nu9CJCNoU2pR8eyGkOsfOxb2lBZ42gDIglCTvg88E4ocTsam
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg0 b/security/nss/cmd/bltest/tests/dsa/pqg0
new file mode 100644
index 000000000..f16326ccc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg0
@@ -0,0 +1,4 @@
+AAAAQI3ypJRJInaqPSV1m7BoacvqwNg6+40M98u4Mk8NeILl0HYvxbchDq/C6a2s
+Mqt6rElpPfv4NyTC7Ac27jHIApEAAAAUx3MhjHN+yO6ZO08t7TD0jtrOkV8AAABA
+Ym0CeDnqChNBMWOlW0y1ACmdVSKVbO/LO/8Q85nOLC5xy53l+iS6v1jlt5Uhklyc
+xC6fb0ZLCIzFcq9T5teIAg==
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg1 b/security/nss/cmd/bltest/tests/dsa/pqg1
new file mode 100644
index 000000000..0c09290dc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg1
@@ -0,0 +1,6 @@
+AAAAgKj5zSAeXjXYkvhfgOTbJZmlZ2o7HU8ZAzDtMlaybQ6AoOSaj/+qrSok9HLS
+VzJB1NbWx0gMgLTGe7RHnBWtp+qEJNJQL6AUcudgJBcT2rAlrhsC4XA6FDX2Ld9O
+5MG2ZAZusi8uO/KLtwoqduT9Xr4tEiloG1sGQ5rJx+nYveKDAAAAFPhfD4OsTffq
+DN+PRpv+6uoUFWSVAAAAgCsxUv9sYvFGIrj0jln4r0aIOzjnm4x03urp3xMfi4Vu
+OtbIRV2rh8wNqKyXNBfOT3h4VX1s30CzW0oMo+sxDGqV1ozihK1OJeooWRYR7gi4
+REvWSyXz98VyQQ3fs5zHKLnJNvhfQZEphpkpzbkJpqOpm74IkhY2gXG9C6gd5P4z
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg10 b/security/nss/cmd/bltest/tests/dsa/pqg10
new file mode 100644
index 000000000..6654a09f3
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg10
@@ -0,0 +1,12 @@
+AAABAL/r0ACy1s1Ks477o13zNN9yHWwvKz2VZnnLrQCfPfvQApUsyJnMI1bsh2m9
+PRulpzAjcpiI2pLKSKXulMl/TwSi46y08zovD7N4PDHyxw+nxw84IUon2t7IsS5n
+mWqehe47sUiAMTAUc5LcUlPATXBjU15s1ka/sYaYTgi1i3SnvlszO/MrCr/VZlNg
+6akjoMUo/xxixyU0WPVnhShxnUNuUBSHQfRdx90sbKxxxVIx8SqD/v0u0KM+3huK
+UfVm/PeJBoLNwZMdwgfJK/LvTiirMWYe63fxYB7qlByVkfA40/ANkShX2wXmSyrV
+aTIAYcb4Y/8zVNhC5+fqcVr++NEAAAAcqpht+KBkJ46TYzFqmDC8+kkGVvqm1dqo
+F9h5SQAAAQCBla2aR4/ZhSFu5YNoNm0u3RPBKz1iI5Fp+gQtkRVkCLSDEi9E7WI2
+uDCKbNtS+a896I7IngOa+tfaOqZsGXYEmo4KfRjVZ7r5n87+MVytoBVIOGsQsl5S
+9S7XjrTSgILl4f/ulIDE/izEqv0e/J1P0sxtFVlokxJx7xWzJA5/sEOoDI9ii+/g
+nWRQd8ECnSHgrIvwupwncU0bWA7eWUqgGzt29udF/B7AfbN+L9fpjGyMaRUijkIs
+MJ3p9dsWj1AknRvh7TKYCQgI4uu4lrt5uMTL+U1MIGTjfmErpESdesIQ7d4hFBbW
+SwUd2ARqsEFzJmVBGn8VTTGz4RpR2n/A
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg11 b/security/nss/cmd/bltest/tests/dsa/pqg11
new file mode 100644
index 000000000..a0a47d453
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg11
@@ -0,0 +1,12 @@
+AAABAMGlnSFVc5SeCyCpdMLt8uMTf/JGMGL3Xx0T3xKroQdrstATQCtgr2wYf7D6
+NiFnyXbCYXxyb5B38J4YwRtg9lAIglvWwCofV9PrCtQc1UfeQ9h/JSX5cdQrMGUG
+58oDvmOzX0raFy0KBpJEQKFCUNeCKsLVrq/tRhnnnUFYp9XrLZ8CPbGBqPCUssbL
+h8uFNUFqwZgT8HFEZgxVd0X0SgHGsQKQksEpsNJxg+gsWiGoAXfudHbrlcRm+0cr
+09LcKGziWEfpPL+prTnMVwNdDHtkuSapx/WnsrxavL+9wLDj/t48HgLESvyK78eV
+faB6Dl/RIznbhmdhb2IobfgNWKsAAAAggAAAAAAAAAAAAAAAG9YsZei4fIl5f48M
+v6VeSmgQ4scAAAEArqWHh0DxQk08bqnGtHmWFdJ0kpihfiYgf3bO80Dd05Dhsa1r
+bAAQrQFaEDNC3dRSysAks25C2bjtUvr656HTzp5LIfkQ0TVusWOj5agYTHgb8USS
+r6LksKVtiIT9AaYouWYnOcQuXFeVreL18n5t4dljkXzogG/EDQIc2HqjqjqeTwws
+TEXSlZsleLL7GiIpw34YEFm51ee3hi+oLiN3pJ7Q+dyoIKWBQHndZhBxTvr4sMxo
+PY5y5MiE5vnUlGs+jUy7kq2759TEfMML5/jDfKgYg6GqxoYAWf9GQKKcyuc94gsS
+5jsAqIsu6bqUt160CmVuFdnsg3MchdDv/Lnvnw==
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg12 b/security/nss/cmd/bltest/tests/dsa/pqg12
new file mode 100644
index 000000000..b62db4b95
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg12
@@ -0,0 +1,12 @@
+AAABANAiduvzwi/9ZmmDGDpHrpTJvMvL+V3ctJHR985kNUkZmZLTfHnnsDLSbtAx
+trpEifMSWCb6+ycmqYMz69mr3eWS2Gk9mFlTbZzDhBodJOBE01rO1hNiVvxta2Fc
+9PQWOqOB6ytMSAglqOzMVtjdz1/mN+OK2bKXS9LPaL8nHg0GfSRlqLa2YFJPAIJZ
+iUWtpY6mSbmATrR1NAjCxZdoxGq7guMpXz2cpGn4TMGH9XLcS1o7OTRuyDnfrW8H
+1tHw4hUgm7DswFx2fPLnlDrJz7Au7h6e9ZRujOiDFrXhX9z5WhMu8uS7CBcTZSjP
+pd2WUy+cOr5cQhYg7ba8vVIjTKkAAAAggAAAABKZfoKF5AiXCPUoBwxtevigvQFA
+nnoHnNtvxbsAAAEAd4RTBJ7yYhR/7XtZsO5nZGB8Uee1tfxv6np6ex3Wuyg/Sprp
+jv05ZLFVZ1jLFbKlOvhhnnTYWJi+x307PzgklK5ZYaE//HRdo4YYIpFRmAD5ndcQ
+4ArrFa3uCI4nmO4uRvWYUmzw9GZwVdG6AJdQBB3FzdJyX/HZfdNAyFGK92cbh9Od
+Z67O2Etm+E4HAe/IKlye+VTuV20kw4WxTWMDfw2Gb9QktJdb3VSF7XQMuTLoQ/kG
+aD98eyx0d12QHDYbhHtRnA2mmWONpAvXNreD0nELLCzCbvkScb9OLBkp+HbpAuIF
+cWQiO8eNaiufbAx6fLhZIvfWxCh64jhh+BKISA==
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg13 b/security/nss/cmd/bltest/tests/dsa/pqg13
new file mode 100644
index 000000000..3f01b91a7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg13
@@ -0,0 +1,12 @@
+AAABAKittsC0z5WIAS5d7/GocdOD4OKoW16OA9gU/hOgWXBeZjIwo3e/cyOo+hFx
+ACAL/VrfhXOTsLvWeQbAgeWFQQ44SA6tUWhNrDo497ZMnrEJ8Zc5pFF819XWKR6K
+8go/vxczbHv4DucY7gh+Mi7kEEfavvvMNNELZrZE3bMWCijAY5Vj1xmTomVD6tt3
+GPMXv12Vd6YVZWGwgqEAKc1EASsY3mhEUJ/gWLqHmAeSKF8nUJaf6Jws1kmNs1RW
+ONU3nRJdzPZOBsGvM6YZCEHSI9oVEzM6fJ14Riq6qzG5+W1fNERc62MJ8vbSyN3g
+ZEHoeYDTA++aH/AH6L4vC+BswV8AAAAg5x+FZ0R/QudfXvhcog/lV6sDQ9N+0J7c
+P25oYE1rnfsAAAEAW6JN6WB7iZjmbObE+BKjFMaTWEL3q1TNgrGfoQSr+12EV5pi
+OyV0s30izK6bPkFeSPXA+by9/4Bx1jubuVblR686jfmeXTBhl5ZS/5a3Zcs+5JNk
+NUTHXb5bs5g0UxlSoPtLA3iz/LtMi1gApTMDkqKgTnALtu1+C4V5XqOLG5YnQbPz
+O53eL07BNU8J4ut46V8DelgEthcWWfiHFc4amwzJDCfzXvLxD/DHx6K7AVTZuOvn
+aj12Sqh5rzcvQkDeg0eTflqQzsn0H/Lya42pqUoiXRqRNxfXPxA5fSGD8bo7e0Wm
+jx/xiTyvaagngC97akjVHab777ZP2abFt1xFYQ==
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg14 b/security/nss/cmd/bltest/tests/dsa/pqg14
new file mode 100644
index 000000000..5b04b1e93
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg14
@@ -0,0 +1,12 @@
+AAABAKYWfBb/904pNCuFhq7TzYlvexY1oihv8W/f9BoGMXymsFyiunwGCtbbFWFi
+HMsMQLhqA2Gb//MuIEy9kLedy1+G67ST470ZiNgJf6I/pNePs83csAxGZCPY+nGY
+c8N2Rf5O7MVxcbvt/lb6lHTJY4W4ujeMeZcteqrmmiumTN6OVlTw97dFUM00R+ek
+cqM7QDfbRo3eMcNIqiXoK3/EG4N/f8ImphA5ZuzY+dFMLTFJVW1Dgp8TdFG40g+F
+ILDOjj1wX3TQpX6ocsK97pcU4LY5Bs3f3Ci2d30ZMlAA+O1SeOxdkS0QIQkxnLo7
+ZGnUZykJtPDb7sC7tjS1UboM8hMAAAAghCdSkETSFMB1dPezWcLgHCP9l3AbMorI
+wThbgcU3OJUAAAEAb8IyQVwxIAz1I680g/jias6AjS8caouGOrBCzH9rcUSy05Ry
+w8tMdoHQcyhDUD2PhYy+R25nQDJKqilZUBBZeMM1BpuRn/mm/0tBBYG4BxL+XT4E
+3bTf0m1ef7yisMUtjUBDQ9V7L5sqJtqn7OMM6rnheJ+XUaqpOHBJllrzJlDGyls3
+SlrnCz+Y4FP1GFfWu7F6Zw5uqviYRNZB4eE9Whsk0FPca4/RAcYkeGlRkn5CYxCr
+qUmKAEKz3Hu8WdcF+A2bgH3kFffpTFz514mZLTu4M20dgIy4a1bd4J2TS7UnAzki
+3hS/MHN2q30i+81hb57aR5qyFKF4UL3QgCqHHA==
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg15 b/security/nss/cmd/bltest/tests/dsa/pqg15
new file mode 100644
index 000000000..ecc45f342
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg15
@@ -0,0 +1,12 @@
+AAABAPY9o76alhYZbGVW885v2LmL3akTdHPaRv7ZcOK40Uc4eoGSIGXVKKfWQz68
+XjWxXGfqNaWlv/W5zvHNHm/jHdpSg42jqom5tOjZ08BzLMxPI4zhtBbEypPyxoAO
+X07UHE92Fc7FUxuYaAsg3GP3PnDYA6rPrs4z1F+g4513yFCCCVKLkEa1kXAQeRI0
+OX5BLSK8C41ny9HNKKMsJGCgvYaqug7qgOFuMkVkMXHjQiF2DCA6VrggehAJ5sGi
+9s2oX4XE+eQQuUmSM8DuBy5GWvT7T7koLFwQ6CNP1jDqkvCq5rl6Ug2zRHVwe3mk
+wXUmXANWzLyoJ+ODffPW0FdtkHkAAAAgm3Rj+CafC5CavtEJkWhPNqZKyGTg1tcX
+wO8hV3pMOQcAAAEAlyp19gboqjqR/wj9Exog9ZYyUTBOPRQxtxL6CAPVJ/1xD7fr
+J+UpBJcc1DypdxmaJNvutLe8K6B107cutrLFrY8Oi49IxQtVTH4HEfTHQWMwgGZy
+SY9DApJyS/mKjqSMf1PXsx2LdSixpvCH0sJ8M1ICg1seMUIls3rvi/zsfYCSDEpG
+Cj1oNE3tde2e6Gf6KmlFBjiU9WO2hjO4s5+DoaqvWpbH9CJofnyEz4+4zF9FBN/w
+h7yyapW7+Fg/A7Og5Do1ayvX4lzd33oBUwD67MZ5PF7pm2Mny4RW4y2RFTOdWmtx
+K3+dAwGssFEz4xFeRU06bdJKFpPJSqtUBlBL9w==
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg16 b/security/nss/cmd/bltest/tests/dsa/pqg16
new file mode 100644
index 000000000..e298647eb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg16
@@ -0,0 +1,17 @@
+AAABgP1abFbdKQ992Eop3hcSbrTkSHs+/wpEq+XFl5LS4SALnD20TVKLn30iSAMu
+S6D3v8T6/HBr5RHbInbAt+z/042i4cLyN6dTkMHk0yOcuo4g5VhA7LBd9fAaG2l3
+rRkG8stUTM+5O5Aa0JZrGDKtLatSYkSjFWyQXAGsUctzudzZhg1WF1pCXYRkhdmx
+9EqKDCV45s9hlHvBoTkv3TILFqnXBFX+Q28tR97Y6OYF90hutXjqf8T/0TwH+Zlq
+8Vn9QR6UUUAyeN0RQajJJrNcljhLvWvuCcRvRMNrH/xxl/XpJdvgVEpo5quMGOQm
+pGazkvnCfdef76nKFjzFo3VTmoVZ8nf2V6U10ZZMal6RaD71aY66oB74GNv3LLBM
+P/CS0YiGbyXNQFEI9Wawh/c9LVvrUfrG3oSuUWGmavlgLH5L/BRvSCC9/Akvrqxp
+Ez5KCKWyAqEkmKIuV7rVRnTtS1EBCdUrX3TnDh9vghYXGM1M8AzJ8ZWKzIvdzfvR
+++Rs0QAAACCAAAAAAAAAAAAAAAAzSibdj0nGgRzoG7E0KwbpgPZLdQAAAYCZqwMK
+IaXJgYF0hyFnZByBweA8mydM+8J7xHJUKSd2beX6BTmztz8/FqyGaprsi0Rd7Zf7
+/wiDTtmMd+f8ieXcZXvvdm/3+/jnaHPhe+5BJ2LVb+EUF2CrTSW6/Utu8ltJo1Bm
+MtH44Qdwkwdg7BMlkyxaS6+ekBVCZN30QuxcQf7ZXRFSUVHbz7N1gUm62Bxiuc/3
+gWuPlTuLfAIlkNFYTpIdyVX1MorHKYPtXPDQQFb+DVMeYvj2yas8D81E4UhgtzEd
+JWHHfB0y9sadyPd5aMnYga2dteDBFP2oYovKAzXrf7nhXmJaq6tY/AEZTIG/b7LO
+VAd7giUOV8ansl3rbuOdS2hqXDB6dhKy2F7pJRJBPeopfkTzF75863CjMorwtAEA
+GkGFYrj/5Ol3G0tKjgtAx5E0nV1ORZ/mIKGi/HLi9sooVn1MJjK73htJhkwGuxJh
+nxMsHaj1ce9hPqxzn2arORTLP6GrhuBeUILrqiTr7qTPUb7vwn31Ev4/7n0=
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg17 b/security/nss/cmd/bltest/tests/dsa/pqg17
new file mode 100644
index 000000000..fa1b638bc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg17
@@ -0,0 +1,17 @@
+AAABgPY7PN1kbY5921chaqbuwhNNcHSIofKc+plwZF8SJ+pdsuMY7qXaFofH7ZBQ
+lmk0XtYTTP8yIDq3Kuy/ppPSFq61XY0oqYH0q/8H0TGaeZvl3XRvhIQoF5KcMFtA
+hZivEgRdqi8czIvk2BtRPGMPAX/sFlisoQihr2Eg7AXjAYxCU8ndNbzgYrc9DyqT
+1BxIGlxDu5eQloLTmppg3Dw142N13sbO0NLbO6DREb7epwGg5HU2JJd6nnW3CnTi
+uB44pSqyLaExs1QW087JZjB5dGp2NHbldZgULjmGFUXar404oXbybHH1r+vZxWIN
+qAzzRStVw3xmG0oewDUXELneSjy+C5i02eyJEo2Xqn77GduLpDzAviXCAPkOFQbL
+eOwMM216lWE9QgTo7WjQ8KbHhCAQWo0tQ4+9JVGmShoLA/+4eHQvjJl5z6hzlBUC
+gZmNUXAdX8+paWpJif0l9ACVXmJrGr6SbAr6aappgZAO/83QMFkvgrIEKkeppajL
+AoPcTQAAACCAAAAAukY0tfpNoFS9DKSK5JDldxHzgRk4QkKRWbp8oQAAAYCK1FU8
+TkmqJHKKtQJEF7Ey0spTpV2VlFjy91mtsENb7u+jos/NADjiQgZD/EpN7rXZ/qoe
+3yEZO0DhS0KYKpTzXFi4EUfXGJ0mPJsS/mOrn6X28DooYMGGQy46sE8qsPL7YUe9
+m/ftXSBxO52iE4Piw6Fo59CdPYpaBY/SMJW1rP64ZKMwa+JCX6GtMq1tk4LmA7A8
+aK9K8CRjlxAsQVXLqBGr+Z2ng553surJlwWIyh0KI2FyOhZKySKcLoDc+o20+eKY
+A+/7MWjH/tejpt5A3aGaBTavm1t6+u+5xw1q6N8S2mWPYjYEOuqHPbKc628H0Qj1
+IlaHvQww4whOIJC0WuL5Kpe47LepcFxJVrizHEo9YRB8hOR63abIDV0i2rPYWSIP
+nVqrE2d6498WjwwXbRdrVFBsY5hT8E3e8nIvOcGOXOQm4UVirY/yYkeviIcO+3LA
+zOg23o/uZ6ZiN4JFtQK/H4MJmYigk8583IE2THix9KUbgA32E3xx1l5rCJo=
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg18 b/security/nss/cmd/bltest/tests/dsa/pqg18
new file mode 100644
index 000000000..cd7ed66ab
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg18
@@ -0,0 +1,17 @@
+AAABgMe4bXBEIY42dFPSEOdkM+Tiepg9scVgu5dVqPt9gZkSxWz+ACqx/z9yFluU
+PAso7UYDmgfeUH16Kfc4YD3s0ScDgKQflx8lkmYaZLovNR2aaeUaiIoFFWt/4VY8
+S3fuk6RJSROEOKKri9z8SbTnjRzedm5UmEdgBX12zXQMlKTdJaRqp3sY6dcH1nOE
+l9Tqw2T0eS2XZqFqDiNIB+lrjGTUBLvbh245tXme9T/my5urYu8Z/cwr3ZBb7aE7
+nvesNfH1V8sNxFjAGeK8Gan138Hk7Knm1GZWQSQwSjHwOGBaPjQtoBvhwrVFYQ7d
+LBOXo8g5ZYjGMp7+tOFlr1s2ijmojkiI459Auz3k6xQWZy+Zn+rTeu8cqWQ/8yzb
+wPzr5ijX5G0oGpidQ90hQyFRr2i+P21WrPvbbJfYf8teYpG/i07hJ1rg60ODzHU5
+A8jSn0rbalR+QF3s3/KIxfbHqjDcsS+E05JJOnCTMxfA9eZVJgH64Y8X5uW7a/OW
+0y2KuQAAACCHb6CeHcYrI2zhwxVbpIsMz9op86xal/f/ob2Hto0qSwAAAYARCv67
+Esf4YrbeA9R/28Mybg1NMbEqjKlbLe4hI7zGZ9T3LB5yCXZ9JyH5X72aTQMjbVQX
+T7+v8sT/ferkc4sg2fN78KETTCiLQgrwtXkuR6klE8BBPzRqTturLEW9yhP1NBwr
+Vbi6VJMrkhe1qFnlU/FLuMEg+7nZmQnf9epo4Us3mWT9Pzhh5bpcyXDEoYDu9UQo
+cDlhAh571oy2N5J7jL7mgF+icoW/7k0e9w4CwaGKfNeL7x3Zza1F3enNaQdVBQ/E
+Zik37h1vTbEoB8zJW8Q18Rtx5whgSLHatZE8YFUBLeguQ6TlDPk/7/Xcq4FKvCJM
+XgAlvYaMP8WSBBu6BHR8EK9RP8NuTZHGPuUlNCLPQGM5jXfFL8sBFCfL/PpnsbLC
+0apKPacmRcscdnA2BU4vMfiGZaVEYciF+zIZ1a2HSKARWPbHwN9ajJCLqMPlNoIk
+KIhse1ALvBW0nfdGud5aeP47T2mR0BEMPL/0WAOdw2Jhz0avS8JRU2j0q7c=
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg19 b/security/nss/cmd/bltest/tests/dsa/pqg19
new file mode 100644
index 000000000..cacd4e4aa
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg19
@@ -0,0 +1,17 @@
+AAABgKQQ0j7ZrZlk0+QBy5MXolIT91cSrLxcEhkavz8cDnI+IzO0nrH5Ww+XSNlS
+8Epa41iFnThEA842SqP1jdl2mQm0UEhUjFWHKmr7s7FcVIgvlsIN8bLfFk8LrISc
+oXrS32Or11yIGSLnmlAJ8At9YxYi6Q5/pOmAYYV14da9GnLVtqUPT2pot5OTfEr5
+X8EVQXWaFzZXfZRIuHeS3/ByMkFVEukzdV4SJQ1GbpzI3xUHJ9dH5R/qeWQVgyax
+Nl1YDLGQ9FGCkVmCIf3zbGMFyLio7QVmPdewBulF9ZKrvsrkYPd8cbbsZJ0/1TlC
+Au17u9BA97j9V8sGqZviVPol1xo3YHNARsKg2zg+Ajl5E65nzmWHDZ9sb2ep0ASX
+vh12OyGTfPnL+aJO+Xu8qgeRb4iU5bf7AyWIIaxGFAllsjxUCcpJAm77K/lbzgJc
+QYOl9lm/aq7vVteTO7KWl9fVQTSMhx+gH4aWeLLjRQb23ApMEytomg7SfcPI1TcC
+qlhIdwAAACCrxnQXclzyj8dkDV3kOCX0Fuv6gOGRxC7ohjAzOPVgRQAAAYCGfV+3
+L1k20aFO07YEmWYvMSRobvEIxbPaZmOg6GGX7CzEyUYBk6dP8WAorJRBsMfSfCJy
+1IOsfNeU1ZhBbE/5CZphZ51BfUeM5d2XS/NJoUV1r+dKiLEt1fbRy9P5Hd1ZftaO
+eeukAmExMMIkuUrChxSh8cVSR1pdKc/N2OCKax1lZh4o7zE1FNFAj1q9Pgbr46fY
+FNHt4xa/SVJzyh1XT0K0gu6jDbU0ZvRUtRoXWguJs8Bd2gBucZouY3FmkIDXaMwD
+jN+4CY6arZuNg9S3WfQ6ydIrNT7YijNyNVAVDeA2G3o3bze0XUN/cctxHyhH3mca
+0QWVFqHUV1UiShXTe0rq2j9YxpoTba7wY2/jjjdSBkr+WYQz6ACJ/aJLFEpGJzS+
++Pd2OIRbAOWc5/pPHa9IeiytoR6rpyuyPh32tmoYPt0ibEQCct2bBr7A5X8aCCLS
+4AISBkttumRWIIX1p1kpr6X+UJ4LeOYwqvEvkeSYDJsNb34Fmi6j4jR52TA=
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg2 b/security/nss/cmd/bltest/tests/dsa/pqg2
new file mode 100644
index 000000000..4bde8eca6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg2
@@ -0,0 +1,6 @@
+AAAAgIubMvW6OPqtXg1QbrVVVA0NeWMZVVjKMIt0ZiKNkqF7OxS44Kt3qfOylZoJ
+hIqmn435LNnp7e8K33ks53v87Mrdk1JwDKX67PGB+gwybbHW5dNSRYAR5RvTJI9O
+O9fIINfgqBkyrKHro5AXXlPq2hlyI2dOOQAmPpD3LZTnRHv/AAAAFLxVDpZWR/s6
+IPJF7IR1Ykq7sm7dAAAAgBEzOpMfulA0h3dzdoWf3BL3xoewlIroidKH8benEq0i
+CuTxzjedDbtcmr9BliHwBfwSPDJ+UFXRhQY0w205fmieER1ZjBw2NrlAyE9C9DaE
+bo5/ytkBLO2jmHIPMv/9GkWrYTbOQXBpIHrBQGdbj4bdBjkVrm9isM7HKfvVCawX
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg20 b/security/nss/cmd/bltest/tests/dsa/pqg20
new file mode 100644
index 000000000..f78284051
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg20
@@ -0,0 +1,17 @@
+AAABgMHQptC17WFd7nasWmDdNeywAKICBjAYsboKBv56APdl2xxZpoDOz+OtQUdb
+rbWtULYUfiWWuI00ZWBSrKeUhupvbskLI+Nj86uM3IuTtioHDgJojqh3hDpGhcK6
+bbER6a3b18pLzmW7EMnOtpv4BuLr1+VO3rf5lqZckHtQ79+OV1uuRiohnDAv7yro
+HXPO51J0YltfwpxtYMBX7Z57DUatL1f+AfgjIw8xQiciMZzgq/HxQfMmwA+8K+TN
+uJRLb9BQvTAL2xxfTaclN+VT4B1RI5xNRhhg8ftP2Pp59dUmP/Yv7XAI4uCi02v3
+uQYtDXXbImw0ZLZ7okEBsIXyxnDA+HrlMNmO5gxUcvSqFfslBB4ZEGNU2ga8Kx0y
+LUDtl7If0c2tMCXGnabOnH3fPc8epNVld7/ewjBxwfBe5Ad7U5HppATq/+EtHqYt
+BqzWvxnpGhWNIGa0zSDkxOUv+x1SBM0CK8cQjyx5n7Rohm7xywm84J39SeR0D/gU
+BJe+YQAAACC/ZUQcmHt3NzherewVjdAWFNpvFThiSOWfPN2+/I6d0QAAAYDAKshT
+dfq4C6KnhLlOTRRbO+D5IJDroXvRI1jPPgP0N5WE+HQiUvdrHt4/w3KBQg50qWPk
+wIh5b/K6uNtumkUw/GfVH4i5BatDmVqrRjZMtAwSVvBGbz2842ID7yKLNekCR+le
+URXoMbEmtijumE80mRHTD/udYTtQqE36HwQrpTa4LVEB5xHGKfnyCW3INN7sY7cP
+KiMVptJzI7mVqiDT0HNwdRhvUEmvb1EqDDip2gaBf0thm5RSDt+shcSm4uGGIlyV
+oE7Dw0IrjesoTpjSSzFGWAIAigl8JZaegmwrqlnSy6M9bB2fOWIzDB/Np8+xhQj+
+p9BVXjoWna7TU/Pub0uzAkQxkWHf9kOKN8p5OyS7sbG8IZT8bm72AngVeJnLA8Xd
+b8kag26yCiXAmUVkPZX3vVDSBmhNb/wU0W2C1feBIlv/kIOSpXk7gD+bcLTfyzlP
+ntgcGOORoJ6z+ToDLYG6Zwyr/W9kql4zdMt8ICn0UgDk8L/YIMi9WNxe6zQ=
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg3 b/security/nss/cmd/bltest/tests/dsa/pqg3
new file mode 100644
index 000000000..1f9216111
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg3
@@ -0,0 +1,6 @@
+AAAAgMuhPlM2N8N8DoDZ/NBSweQaiKwyXE6+E7cXAIjVTu9IgfPTXq5HwhA4WoSF
+0kI6ZNo//aY6Jvks9aME85JgOEqbd1nYrBrcgdP4v8XmyxDvtOD3WGf06EjRozhY
+bdBkj+6xY2R//nF2F0NwVA7oqPWI2ozBQ9k59wsRSn+YG4SDAAAAFJUDG4qnHynV
+Jbdz74t8ZwGtil2ZAAAAgEW8qkQ9TNFgLSeq+EEm7cc713Pebs4V6X5/70bxMHK3
+rcr3sAU89HBpRN+MRWjybJl+53UwAPvkd6N3ZqTpcP9AAI65ALneS1+a4G4G22EG
+54cR86Z/7KdN1b3c32da5AFO6UiaQpF/vuO7nyok32dRLBw1yXv78jCOqs0oNoxc
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg4 b/security/nss/cmd/bltest/tests/dsa/pqg4
new file mode 100644
index 000000000..0446942f2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg4
@@ -0,0 +1,6 @@
+AAAAgPJKSvxyx+Nzo8MJYjMv5UBcRZMJY5CUGMMHkqrxNd3qVh6U8kcmcWt1oYgo
+mC5M5Ewf3ct0ZIe2t3qaWhf4aKtQzWIbW8naRwiAsofXOYGQpCpe4i7Y0f8UfiAZ
+gQyCmO1o4cpp1B1VXySeZJ+xcl3bB1wXs3vv9Gf90WCSQzc/AAAAFNoGWgeN21bu
+XSrQbK+rIIINLEdVAAAAgEe1WRt5BD5OA8p4oOJ3yaIeKmtUO/TwRBBM2ayT7/jh
+AbtgMe/IxZbV0vkuOj0PH3RwLdVPd9PNRsBN7npd6fAK0xdpH93O/koiCiZRrK5/
+zt2pK/zKhV22cF6Nhk+Bkr9r+GDADwitZJPswYcuACjVyG1EUF21dCJRXDglpveK
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg5 b/security/nss/cmd/bltest/tests/dsa/pqg5
new file mode 100644
index 000000000..6a091c535
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg5
@@ -0,0 +1,6 @@
+AAAAgIjZaOlgLsvabYb3yXCj/76x2pYvKMCvuScO8FvDMMqYw634PAcv6wX7Lik7
+UGW7sMvMkwwk2NB4ad6uzZKiYEwPXdNcW0Mf2moiLFLDViv3VxxxAgm+izuFiBh4
+hyX+gRK31ryC4P8cu/XW/pRpCvK1EOQa2CB9wsAvufpc76q1AAAAFKZlaJueW5zo
+L9FnYAbPTPZ+zFa3AAAAgCZ+KChXQXdSET+6P8pxVbXOiefIozwaKRIuK3IJZfwE
+JFJn/4f8Z6VzD+WzCAE6oyZpkPuzmBhah+BVtEOoaM4M4TrmruMwudJdO7s2JmXF
+iB2vDFqnXp1KgujwTJGprSlIIuM5eKsME/rcRYMfnTfaTvoPwsXrATcfqFt92x+C
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg6 b/security/nss/cmd/bltest/tests/dsa/pqg6
new file mode 100644
index 000000000..e1220d7af
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg6
@@ -0,0 +1,12 @@
+AAABAPLTntMGKxPJFic2AKDyoCnobXpLkhe08YFb8rJNlxClerM/mXKUsBRYW40B
+mN/cy811MU2l/4WqNEtFra6ql5tRoxKnv6lEcvtjPxpvFWu0RYhn39OEA/BrhR8A
+/i00hAd73tcat1E9BKFAIgV1+2kzlUgOTIQCt6Rs7C03p3jDBazNHxPp9i6GUxX0
+sizEZ8iYbsjklh3fgQVmsMTuNprGqhXkP0dEAFgm9b3oBxoZ4wtpCarEs9F0I3Jw
+2tAnmdCbiizF8i5miUtUIiKLLCNPEfWnccW4nPRloqzsu+6qFyX+j5tZQivomRBS
+y1Vt3yyM6PqSBtvzn+rcGU4A+OUAAAAcgAAAAAAAAADBGPSYNeTvczxNFYAPzwWe
+iE0xsQAAAQDjqTwJ2m9WDk1IOjgqTFRvIzXDakw1rBRjwIo+bdQV31b9xTfyX9U3
+K+Y+T1MAeAt4LxrNAci06zNBRhX9Dqglc6y6fvg/WpQ4VBUa/C19/hIfuM0DM1sG
+W1ScXcxga+kFJIO8KE4SrDyNugm0JuCEAgMOcLwcwr+JV8S6BjDz8yrWiTiaxHRD
+F2Bj8kfZ4ilrPqW1vCM1go6hoIDtNZGN7iEv0DEnnRuJTwGv7FI4M2aerAMaQg5U
+C6EyClnEJKPlhJpGCla8sAFkeIWxQzxPmSlxdGv+KXfOclnFULVRpsNXYeSkGvdk
+6NkhMvzApZ0WhOq5DYY/KfQc91ePqpCM
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg7 b/security/nss/cmd/bltest/tests/dsa/pqg7
new file mode 100644
index 000000000..f65cc5c3f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg7
@@ -0,0 +1,12 @@
+AAABAKqBXJ2xxNPSdzx9DU0dp17PxKOel9X6GR/+yLFJCikM4zXlzofqYgqKF94L
+tkcU4uyEC/AObr20/7TjJMoHw8hxcwmvFBA2Kncsmt2DiysMrh6Qq0SK2r2s0uXf
+WcQYejKiNxnWxX6UAIhTg7+PBm8juUGSDVTDW098xQRPO0DxcEaVYwe3SOhAcyhE
+0Aqc5uxXFCk7YmUUfxXGf0vjiwgrVf3q22EkaJ+3b50lzCi46qmLVi1cEBHg3Pmz
+mSMkDTMtidyWA7e93QxwuDyqKQVjGxyDyruubAwMLv6PWBMe2DUb+T6HX2pzqTy6
+1HAUGiaH+6zy1xyN3ulxrWYHKa0AAAAc6jR+kL58KHXR/h22IrR2ODfF4npgNzED
+SMGqEQAAAQAgQglMy8i4cj/JKMEv2mcbgylemcdDV29EUEvhGGMjMZtQAtJPFz35
+CeokHW6lKJkE7kY2IEsvvpSwaP4JP3liV5VJVR068hmtjtGZOe/4a87INN4vL3hZ
+bonny1LFJOF3CYpWwjLrH1Y6qEvGsCbe7m/1HLRB4IDy2vrqHO2GQn0cNGvlXGaA
+PUt20TPNRFtMNIL6QVAjRjyb8w8veEIj4mBX06oNf7tmBjDFLknUoDJcc4ngcqo0
+nxPJZuFZdS+7cekzaJD5MkP6bnLSmTZe5bP+Jm6/ERBWj+5EJchHtQIQvUhLl0Ma
+QoVq3KPn0anJxnXH4maRgyDdWnikjEip
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg8 b/security/nss/cmd/bltest/tests/dsa/pqg8
new file mode 100644
index 000000000..93b570050
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg8
@@ -0,0 +1,12 @@
+AAABAKTH6qtCxMc7dXdwkWSJ8XzVByXNCkvE4c9n92O4wd4tbauYVrqvsAjzZbGK
+QuFNxR81C4jsoCCcWqT9caepbHZfWQHCHnIFcNeDe+x8dtLkk0RzHKOUBdCoebng
+3NGoEl/RMOweeD5lS5TjAC5rYp6QSrOHeGdyDL1UtCcKnhXNAox8x5bwbCcqZglR
+ko/b6y3KBhtB6TIlcwV0L/FuL0KRkdXl8abd9ueMXXciz/gKnAvVyNeuuowEQ4mS
+sHXjB8FTTEmtOA9Hf195h9wXLBYdyjjcrz+zhGxyyRGaUpmtx0iVGz3ODQDUqQE4
+ALIAggO3JGW8aoSuBZowxFIt6lcAAAAczon+MyuOTrPR6N3OpdFjpbwTtj8WmTdV
+QnrvQwAAAQCMRl7fWhgHMCkeCA38U4U5elAGRQ26Lv4BKSZPvYl7tVecoOqxmqJ4
+IgQkcktPKm9u5jKEMqv2YTgGRglyM1BTOcVRnTV9cRK27sk4uF1ap1zC44CS8KUw
+rLVOUP6CxNVi+w8wNrgLMDNAI+u+ZjegAQsAx9uGNxFoVjZx4eDwKK7b1F0tVyYh
+pgmYKgc+Uaridwevvu8p4uzuhNem1do4K+OjX0K2xmhJICqxnQJbhp0Id2R20auY
+FHWtKtLz5v0H4waW2QpiaBbfYNbKev17SC+UL4O0XMgpM3Mfh/ruMgkA8qo+cLGG
+fhQw5AvmfAf5KQKZ7wZ7iySnUVs/mSwH
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg9 b/security/nss/cmd/bltest/tests/dsa/pqg9
new file mode 100644
index 000000000..8cec6fa33
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg9
@@ -0,0 +1,12 @@
+AAABAKa7UzPONDwxybLIeKuR7vL96jXG2w5xZ2K/wNQ22HUG6GWk0sjPu9Ymzov+
+ZFY8pWhs2M8IFJDwJEWyiQh5gklftpl2sQJC1tUPwjtNvbC+94MF2aTQXZ6uZdh6
+iT6vOX4E45uqhaJsj/ve8SMyh7X1tu9qkPJ6aUgaky7kexjV0n6xB/+wUCXmRuiH
+a1y1Z/7B3TWDXUIIIZhTH6++WuKAxXWh+w5i6bPKN+GXrZbZ3eHzPyzsfSferiYc
+g+6OIAKvfrboL2oUeWrwN1d6EDK7xwkSnKq9it34cK4tBZXI/bNxVXSPDeo0tE1P
+gu1YwvWxuEgWYqxTRzxpNBAIL70AAAAcjD7lvZoqrwaL1YRb1V7PJ0FwVTB1d7vD
+dw7GiwAAAQBDtaa20LuWLsl2ajd8MsxBJPExEYjC7PlcDNSk+glyJbdhjLEnbEdF
+eNO/VkwUUZnAkqGxS6qSnC8/DzbgwtrpHroIvjCZKoifKVLgRCw3r0hKTs3DJDzP
+y540E89c3WYwsJ/hfvv94U2HJUkwGbe3PR94K0jvML7DbgDgK6M20iVPwgKmlhLN
+lEb5HXa3Of+m2LhgUvjcXxFFgBxWJBr1upA3JBvYnmM4tY4BMQZxwmjrXjOstX0f
+mfFkQKZ1gn1AF3VNYBoXraL77fkEVUqQsBUw2oyTzRTOKTyyvT55N+k0t54xD+TY
+DBP5L2M4E1W9gKGr7hpz/fttok7ygAKj
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed0 b/security/nss/cmd/bltest/tests/dsa/sigseed0
new file mode 100644
index 000000000..05d7fd2d6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed0
@@ -0,0 +1 @@
+aHpm2QZI+ZOGfhIfTd+d2wEgVYQ=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed1 b/security/nss/cmd/bltest/tests/dsa/sigseed1
new file mode 100644
index 000000000..83a7ecfa3
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed1
@@ -0,0 +1 @@
+mMvMSWnYReJGG19mOD3VA3ErvPo=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed10 b/security/nss/cmd/bltest/tests/dsa/sigseed10
new file mode 100644
index 000000000..7ddd4ea0d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed10
@@ -0,0 +1 @@
+nO2J6lBQmCIigw7+8m5zlPWrfYN9RUmWLShfrg==
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed11 b/security/nss/cmd/bltest/tests/dsa/sigseed11
new file mode 100644
index 000000000..a12adcbfc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed11
@@ -0,0 +1 @@
+LLnB1hfhJ6R3DQqUb7lHxRAO0MpZRU6oBHn2iF7BBTQ=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed12 b/security/nss/cmd/bltest/tests/dsa/sigseed12
new file mode 100644
index 000000000..d51eaf388
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed12
@@ -0,0 +1 @@
+RQMLeaOVsWMnAMuv/q2XmY0CvtjgZWh2/AF05L25b3k=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed13 b/security/nss/cmd/bltest/tests/dsa/sigseed13
new file mode 100644
index 000000000..77c773ac7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed13
@@ -0,0 +1 @@
+EXpSnj/fx5hDpaTAdTkDa4ZSFOAUtJKMKjH0e/YqT9s=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed14 b/security/nss/cmd/bltest/tests/dsa/sigseed14
new file mode 100644
index 000000000..8178d4b66
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed14
@@ -0,0 +1 @@
+I2gDehx2R8aD1+MBrHm3/uvHNu/+OrFkS2gwi0soYg0=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed15 b/security/nss/cmd/bltest/tests/dsa/sigseed15
new file mode 100644
index 000000000..8bfb67809
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed15
@@ -0,0 +1 @@
+X+Ya/dvfBESbJClaUqGgN9PzFEGjzsE4t/AQLbhu8TI=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed16 b/security/nss/cmd/bltest/tests/dsa/sigseed16
new file mode 100644
index 000000000..06c4c1bdb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed16
@@ -0,0 +1 @@
+QPUDq9cP1Jp2xnqD4IsGKz/UZa2SvkM8CA5fKVu59Vk=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed17 b/security/nss/cmd/bltest/tests/dsa/sigseed17
new file mode 100644
index 000000000..43148bff9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed17
@@ -0,0 +1 @@
+KeTXeQ4YG0dnkD/g6zd1fzPxMzfDNYjB/b+6DmVatiE=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed18 b/security/nss/cmd/bltest/tests/dsa/sigseed18
new file mode 100644
index 000000000..370f857d6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed18
@@ -0,0 +1 @@
+PXwGijl4stj+kDS8rWWtfDAMREDkCF3igOV37qcsEgc=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed19 b/security/nss/cmd/bltest/tests/dsa/sigseed19
new file mode 100644
index 000000000..edb0bf8a5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed19
@@ -0,0 +1 @@
+QLXMaFw9H1kHIiivlVFoO1uMj/ZSQBFK0trPzPOSgFc=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed2 b/security/nss/cmd/bltest/tests/dsa/sigseed2
new file mode 100644
index 000000000..814709f1b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed2
@@ -0,0 +1 @@
+jLNdJVUFpMQUIeVi0QgnJmqmhmM=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed20 b/security/nss/cmd/bltest/tests/dsa/sigseed20
new file mode 100644
index 000000000..de625fdd2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed20
@@ -0,0 +1 @@
+tZkRG594QCzv573ov1U7bKANWrr5oViqQvJge/eFELw=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed3 b/security/nss/cmd/bltest/tests/dsa/sigseed3
new file mode 100644
index 000000000..d2c733940
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed3
@@ -0,0 +1 @@
+hZdsVhCnSVlTEEClUSs0fqxYfkg=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed4 b/security/nss/cmd/bltest/tests/dsa/sigseed4
new file mode 100644
index 000000000..036d29a8f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed4
@@ -0,0 +1 @@
+M8e6iP9pcHlxslrDRK5KVm4ZX5k=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed5 b/security/nss/cmd/bltest/tests/dsa/sigseed5
new file mode 100644
index 000000000..7d80d6677
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed5
@@ -0,0 +1 @@
+LxcJB6xpcmsU8iBW3LN7TfhfdCQ=
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed6 b/security/nss/cmd/bltest/tests/dsa/sigseed6
new file mode 100644
index 000000000..2f8d8df4e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed6
@@ -0,0 +1 @@
+cZc5LTLQr2pxg8wzmFVvj2h9hqj/dCvmrThWLw==
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed7 b/security/nss/cmd/bltest/tests/dsa/sigseed7
new file mode 100644
index 000000000..eda93236d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed7
@@ -0,0 +1 @@
+N/rdQZ/L0rBzoGrpa57Otj4prumsX6K9sxq4XQ==
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed8 b/security/nss/cmd/bltest/tests/dsa/sigseed8
new file mode 100644
index 000000000..03997e010
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed8
@@ -0,0 +1 @@
+bzJlRqoXSz0xnvczHsjf02PdeK5YOpIBZf9+VA==
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed9 b/security/nss/cmd/bltest/tests/dsa/sigseed9
new file mode 100644
index 000000000..0ce4ead34
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed9
@@ -0,0 +1 @@
+fg8c4h0YWuZcCgA5VWfqnPIXRitYucicTl/5zw==
diff --git a/security/nss/cmd/bltest/tests/ecdsa/README b/security/nss/cmd/bltest/tests/ecdsa/README
new file mode 100644
index 000000000..0a6ece60b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/README
@@ -0,0 +1,4 @@
+0 nistp256
+1 nistp384
+# the following tests are not yet implemented
+2 nistp521
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext0 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext0
new file mode 100644
index 000000000..14d8e0ece
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext0
@@ -0,0 +1 @@
+GoWqve3YezF7HOABQjioFL/3oq32oM9pHsGTQTJE7aFE62nItVqAdg==
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext1 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext1
new file mode 100644
index 000000000..4484aae61
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext1
@@ -0,0 +1 @@
+PM6xHbiwP6Xcb44mg7BHtaJvd8PkxgvHAB1sh2cF0so3naFf0Tj6vQ==
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext10 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext10
new file mode 100644
index 000000000..a956d53a6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext10
@@ -0,0 +1,2 @@
+AF3bbyED08NTrUgKmag9HiuUbaW0skXA/Bp9RPjRAD6M0rp3nvLDKozI940jxPP1
+nWpHF7VcyCVzJeV6
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext11 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext11
new file mode 100644
index 000000000..8cc2c2623
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext11
@@ -0,0 +1,2 @@
+AOLrxy4FWd29ToUjOwLs6GyQ+dYZN6NkZ8oVO6dsAEXt55ePlCWZbOtmk6v9PrNG
+JOsY/MHnGhDeAGRl
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext12 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext12
new file mode 100644
index 000000000..5a05a7863
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext12
@@ -0,0 +1,2 @@
+aQHMte9cFByD9Ff3rZOPOtPI75luPoxemmgjXIgh/9jEeoTdDk8xuAYQUkayCfs+
+DpDaGnOLkfAyZ8GcuaCujg==
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext13 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext13
new file mode 100644
index 000000000..690c00a71
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext13
@@ -0,0 +1,2 @@
+AaeVCRJQPbpTqa1+zLd/8xAbkz3KKTr0dlS4tuGC8hc9j5esAeEv+7IklbA3v5Jz
+jC+nJy4p81iNO5E9H8nfGGckfQSiFzHG
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext14 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext14
new file mode 100644
index 000000000..fe527c625
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext14
@@ -0,0 +1,2 @@
+AgU0N7zJPg/1UxmCWD5Z+DqDqkRKjy4heFgayCyopb/u4XErAZArgsjashAxzMKC
+PSDJasPT90T5Va8sNtjXtSpHWxc2roV9
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext15 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext15
new file mode 100644
index 000000000..d1090942a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext15
@@ -0,0 +1,2 @@
+NXo8is+7lAoOwWGt7+GBbT/UX8LGs8TXEHBI+tX9311pJ4J3pfBYobgN0ZK6ZBtp
+dS6PkrPaQp0S9nrfTOS5uAH95eD1eymRfCbOnjTUKzLuIn53V17vRjdcDtLzrhzX
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext16 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext16
new file mode 100644
index 000000000..d5fe14482
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext16
@@ -0,0 +1,3 @@
+ADhxjBz/ACTy4GJlL0tYZpyNpC4DsXND9lJuU7x9N7g6gkpJyBPw3vBYU1olw6PH
+dnegpgAm4Gh6MCsZB4KBcLwl1wjt4B3p2eqEqDYn5fiie5f4XuRomvI92jR5Sb+I
+nBLCHIppt/Q=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext17 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext17
new file mode 100644
index 000000000..486bf664f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext17
@@ -0,0 +1,3 @@
+AGhHQ6kfdZRgu1svQTXEIewvFVglnUy6ANPumyUbM14AEfRkCUNa1uzvhV1sbWYj
+qT3egQCA9MTjThDNJeDOvvL6hVVOryUv4+C3RtkpQGCtdml+CSsjVTej8h9JbMds
+Dme40b2G6fE=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext18 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext18
new file mode 100644
index 000000000..7eeef3811
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext18
@@ -0,0 +1,3 @@
+AGBuqk48tufy0bKEWpu+xEHsmi+6KCfdwOSRwLDnpVetGe9AWknHDzeTSwe0QxcE
+RsEkUZGDpxfzUlCLSSSU+ErrYY/uyLV2AJTb3prB6A2YNwdmFGeRbDoxeOu7FuQA
+3gxBQhR+TGMuskeM+BdHFmFrwvTTdHCGzjTBa5S8mbgEJTfeik/it28T/9i+duZ8
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext19 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext19
new file mode 100644
index 000000000..ef8e5f381
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext19
@@ -0,0 +1,3 @@
+AaiotJfCiWU1d2LFe+t0CcWHDSF7EOlApWYJ+RNRSq8TbkXJIzi6abbb7BovtRwf
+i/COYwjS7OnkFQ6x5Pdrb7OZ0dTAdDRXAKtXWSKR20Y4fhnx/HUxisFwKrsCEQ3O
+uVtwDG8rh5V8zjBnCEcs5Iy9CsklucibR0PIyglVmW+ZuY42YNebuOC2VUKqHNF7
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext2 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext2
new file mode 100644
index 000000000..a3837a410
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext2
@@ -0,0 +1 @@
+Vli8Hau3xL8oder6ZdM9Y3fMd92jbguiMq6F+9CUjlUQXy5EwAVGeg==
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext20 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext20
new file mode 100644
index 000000000..67c99244a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext20
@@ -0,0 +1,3 @@
+ALAM5hGnex7TvBbSEzDlfv+n5g7aWyRyZsBbl2Y6wW1plSovbq2GcV6w1ZV1Vlot
+70zbqkKyNApvTi3xoD4Ens6pAeLMYDILwaQhnyJZWQv3etbWqUKJZNgfH1IDj03k
+n9hbjYLX3y4bc4CnrhOiv5Ab34s7M8wUYcjC+DbHwhLl/S6N
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext3 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext3
new file mode 100644
index 000000000..e9a480882
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext3
@@ -0,0 +1 @@
+AFohw5TN/dpmqbhp/T4z1Rl1boAUA6r9eEPJbYN0zf+eHZzyvezxqjxU
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext4 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext4
new file mode 100644
index 000000000..57ce239ab
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext4
@@ -0,0 +1 @@
+AtJdCPXn5yQW34jekhsnsNmaMOeeA3KIVl1d2+7pb6QycUAzYccgwSrp
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext5 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext5
new file mode 100644
index 000000000..e476c80bf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext5
@@ -0,0 +1 @@
+AzEg0sOGHwxd0o3cv+o9dsRPOzXMAdpgtI6O0uUmVN2+a5qI5FYQlItz
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext6 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext6
new file mode 100644
index 000000000..bdea7171d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext6
@@ -0,0 +1 @@
+5+HDXH/ieN8Bzxd3dfxKZoqbbhsm7jyeqWdemt6Xy0kx+7zwSYsh9Ng5KRdy6wtA
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext7 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext7
new file mode 100644
index 000000000..3273fd9f7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext7
@@ -0,0 +1 @@
+WcS9umnUASP0X6lHvkWJwPY37ZVvAMLBERHLjL3Vzg6QVjwcS8kDVortTFei3aTx
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext8 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext8
new file mode 100644
index 000000000..636392e43
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext8
@@ -0,0 +1,2 @@
+ItpmPaGAaoe2feXPbh5+EASLGnEzyYbEnwJ+JFNSOQcoY4a/cMV2rn8FYyBsEDiZ
+LPDBU0i2uOg=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext9 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext9
new file mode 100644
index 000000000..0c43fa3d7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext9
@@ -0,0 +1,2 @@
+QjzCVGRUjulOLqeBqC5xpY0GWomOrmQUCtImY0czn98a/jHrdgsSRKiMHukBUxM1
+TIRGjkV2L+A=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key0 b/security/nss/cmd/bltest/tests/ecdsa/key0
new file mode 100644
index 000000000..491fdba1b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key0
@@ -0,0 +1,3 @@
+AAAACgYIKoZIzj0DAQcAAABBBNGB7n4kH15tKA/SMpetaQVqg6WxIuuUuMQT2tDX
+NN5jKZfaxD47NsTjTr3x3D5t1qRBYuL6VtdgIuxBIHGG9dcAAAAgaGjyZBL+LN3a
+7NkGiHJBfqh7XKNH0AnPF3vFWpostIQ=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key1 b/security/nss/cmd/bltest/tests/ecdsa/key1
new file mode 100644
index 000000000..a062f1f67
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key1
@@ -0,0 +1,4 @@
+AAAABwYFK4EEACIAAABhBLWMJG3t4khPYcsl3H492rAqukJ1RqJm27pqpN54rFGG
+r2VDwOfqb9tMninq8IyOh42eaaVOEPXXu4Q/ATWBEfrbTRBjTpzAE2SSPuQma0lM
+q0RSVECCgdBOKIhB0H6VxAAAADA3WPjUaMWCS9E5KbVDrEcf5CV5tCNNWJQkwjsA
+yALMCiXJqRVXwbq42WMuaELMW+g=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key2 b/security/nss/cmd/bltest/tests/ecdsa/key2
new file mode 100644
index 000000000..c4da3486d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key2
@@ -0,0 +1,5 @@
+AAAABwYFK4EEACMAAACFBAHLMSpMFVyG6mXE7SZ5O5Bwv4d8/QiAB3BzpXkyrU1W
+jJ9O9uOYTXM+cFtF5v56+LsI4yGkaAl9+RF6lFPjrhpIswCmBmEqMBgZpjoz38my
+nLHBI9MaFF8AHkRQwD3LJLo4eSZHOVkdIvDYLwicdlgr0zD3Nf76/HB1+0DkBGqE
+MyG22gAAAEIAFah7z179UbqqdH68pzdZsP1ChXjtYZ11rBM0+HP7yLirxH3ahKTt
+DjsY19GEjz4gKsaLfLiQ1/Dp+VKVLcBKpk0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/numtests b/security/nss/cmd/bltest/tests/ecdsa/numtests
new file mode 100644
index 000000000..aabe6ec39
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/numtests
@@ -0,0 +1 @@
+21
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext0 b/security/nss/cmd/bltest/tests/ecdsa/plaintext0
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext0
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext1 b/security/nss/cmd/bltest/tests/ecdsa/plaintext1
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext1
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext10 b/security/nss/cmd/bltest/tests/ecdsa/plaintext10
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext10
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext11 b/security/nss/cmd/bltest/tests/ecdsa/plaintext11
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext11
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext12 b/security/nss/cmd/bltest/tests/ecdsa/plaintext12
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext12
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext13 b/security/nss/cmd/bltest/tests/ecdsa/plaintext13
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext13
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext14 b/security/nss/cmd/bltest/tests/ecdsa/plaintext14
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext14
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext15 b/security/nss/cmd/bltest/tests/ecdsa/plaintext15
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext15
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext16 b/security/nss/cmd/bltest/tests/ecdsa/plaintext16
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext16
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext17 b/security/nss/cmd/bltest/tests/ecdsa/plaintext17
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext17
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext18 b/security/nss/cmd/bltest/tests/ecdsa/plaintext18
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext18
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext19 b/security/nss/cmd/bltest/tests/ecdsa/plaintext19
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext19
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext2 b/security/nss/cmd/bltest/tests/ecdsa/plaintext2
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext2
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext20 b/security/nss/cmd/bltest/tests/ecdsa/plaintext20
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext20
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext3 b/security/nss/cmd/bltest/tests/ecdsa/plaintext3
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext3
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext4 b/security/nss/cmd/bltest/tests/ecdsa/plaintext4
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext4
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext5 b/security/nss/cmd/bltest/tests/ecdsa/plaintext5
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext5
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext6 b/security/nss/cmd/bltest/tests/ecdsa/plaintext6
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext6
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext7 b/security/nss/cmd/bltest/tests/ecdsa/plaintext7
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext7
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext8 b/security/nss/cmd/bltest/tests/ecdsa/plaintext8
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext8
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext9 b/security/nss/cmd/bltest/tests/ecdsa/plaintext9
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext9
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed0 b/security/nss/cmd/bltest/tests/ecdsa/sigseed0
new file mode 100644
index 000000000..05d7fd2d6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed0
@@ -0,0 +1 @@
+aHpm2QZI+ZOGfhIfTd+d2wEgVYQ=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed1 b/security/nss/cmd/bltest/tests/ecdsa/sigseed1
new file mode 100644
index 000000000..05d7fd2d6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed1
@@ -0,0 +1 @@
+aHpm2QZI+ZOGfhIfTd+d2wEgVYQ=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed10 b/security/nss/cmd/bltest/tests/ecdsa/sigseed10
new file mode 100644
index 000000000..6983e5f7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed10
@@ -0,0 +1 @@
+fjIzMWJpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed11 b/security/nss/cmd/bltest/tests/ecdsa/sigseed11
new file mode 100644
index 000000000..6983e5f7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed11
@@ -0,0 +1 @@
+fjIzMWJpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed12 b/security/nss/cmd/bltest/tests/ecdsa/sigseed12
new file mode 100644
index 000000000..92aa40c82
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed12
@@ -0,0 +1 @@
+/jI1NmJpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA4MDk=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed13 b/security/nss/cmd/bltest/tests/ecdsa/sigseed13
new file mode 100644
index 000000000..4ac076584
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed13
@@ -0,0 +1 @@
+ATI4MWJpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA4MDkwYTBi
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed14 b/security/nss/cmd/bltest/tests/ecdsa/sigseed14
new file mode 100644
index 000000000..4ac076584
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed14
@@ -0,0 +1 @@
+ATI4MWJpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA4MDkwYTBi
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed15 b/security/nss/cmd/bltest/tests/ecdsa/sigseed15
new file mode 100644
index 000000000..097523032
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed15
@@ -0,0 +1 @@
+/jM4NGJpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA4MDkwYTBiMGMwZDBlMGYxMDEx
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed16 b/security/nss/cmd/bltest/tests/ecdsa/sigseed16
new file mode 100644
index 000000000..36fbf0951
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed16
@@ -0,0 +1 @@
+fjQwN2JpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA4MDkwYTBiMGMwZDBlMGYxMDExMTIx
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed17 b/security/nss/cmd/bltest/tests/ecdsa/sigseed17
new file mode 100644
index 000000000..36fbf0951
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed17
@@ -0,0 +1 @@
+fjQwN2JpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA4MDkwYTBiMGMwZDBlMGYxMDExMTIx
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed18 b/security/nss/cmd/bltest/tests/ecdsa/sigseed18
new file mode 100644
index 000000000..7be8ce6dd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed18
@@ -0,0 +1,2 @@
+PjU2NmJpdHNPZlRleHQwMDAxMDIwMzA0MDUwNjA3MDgwOTBhMGIwYzBkMGUwZjEwMTExMjEz
+MTQxNTE2MTcxODE5MWExYjE=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed19 b/security/nss/cmd/bltest/tests/ecdsa/sigseed19
new file mode 100644
index 000000000..7be8ce6dd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed19
@@ -0,0 +1,2 @@
+PjU2NmJpdHNPZlRleHQwMDAxMDIwMzA0MDUwNjA3MDgwOTBhMGIwYzBkMGUwZjEwMTExMjEz
+MTQxNTE2MTcxODE5MWExYjE=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed2 b/security/nss/cmd/bltest/tests/ecdsa/sigseed2
new file mode 100644
index 000000000..05d7fd2d6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed2
@@ -0,0 +1 @@
+aHpm2QZI+ZOGfhIfTd+d2wEgVYQ=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed20 b/security/nss/cmd/bltest/tests/ecdsa/sigseed20
new file mode 100644
index 000000000..f0dddb66c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed20
@@ -0,0 +1,2 @@
+/jUyMGJpdHNPZlRleHQwMDAxMDIwMzA0MDUwNjA3MDgwOTBhMGIwYzBkMGUwZjEwMTExMjEz
+MTQxNTE2MTcxODE=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed3 b/security/nss/cmd/bltest/tests/ecdsa/sigseed3
new file mode 100644
index 000000000..05d7fd2d6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed3
@@ -0,0 +1 @@
+aHpm2QZI+ZOGfhIfTd+d2wEgVYQ=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed4 b/security/nss/cmd/bltest/tests/ecdsa/sigseed4
new file mode 100644
index 000000000..05d7fd2d6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed4
@@ -0,0 +1 @@
+aHpm2QZI+ZOGfhIfTd+d2wEgVYQ=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed5 b/security/nss/cmd/bltest/tests/ecdsa/sigseed5
new file mode 100644
index 000000000..05d7fd2d6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed5
@@ -0,0 +1 @@
+aHpm2QZI+ZOGfhIfTd+d2wEgVYQ=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed6 b/security/nss/cmd/bltest/tests/ecdsa/sigseed6
new file mode 100644
index 000000000..a0687196c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed6
@@ -0,0 +1 @@
+/jE5MmJpdHNPZlRleHQwMDAwMDAwMDAw
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed7 b/security/nss/cmd/bltest/tests/ecdsa/sigseed7
new file mode 100644
index 000000000..a0687196c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed7
@@ -0,0 +1 @@
+/jE5MmJpdHNPZlRleHQwMDAwMDAwMDAw
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed8 b/security/nss/cmd/bltest/tests/ecdsa/sigseed8
new file mode 100644
index 000000000..01ae26574
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed8
@@ -0,0 +1 @@
+/jIyNGJpdHNPZlRleHQwMDAwMDAwMDAwMDAwMA==
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed9 b/security/nss/cmd/bltest/tests/ecdsa/sigseed9
new file mode 100644
index 000000000..01ae26574
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed9
@@ -0,0 +1 @@
+/jIyNGJpdHNPZlRleHQwMDAwMDAwMDAwMDAwMA==
diff --git a/security/nss/cmd/bltest/tests/md2/ciphertext0 b/security/nss/cmd/bltest/tests/md2/ciphertext0
new file mode 100644
index 000000000..22e1fc496
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/md2/ciphertext0
@@ -0,0 +1 @@
+CS/UNcrWhB5Knt7Gf8Tz3Q==
diff --git a/security/nss/cmd/bltest/tests/md2/numtests b/security/nss/cmd/bltest/tests/md2/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/md2/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/md2/plaintext0 b/security/nss/cmd/bltest/tests/md2/plaintext0
new file mode 100644
index 000000000..dce2994ba
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/md2/plaintext0
@@ -0,0 +1 @@
+16-bytes to MD2.
diff --git a/security/nss/cmd/bltest/tests/md5/ciphertext0 b/security/nss/cmd/bltest/tests/md5/ciphertext0
new file mode 100644
index 000000000..ea11ee523
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/md5/ciphertext0
@@ -0,0 +1 @@
+XN8lnQuWAiMqmSGfvd8Hdw==
diff --git a/security/nss/cmd/bltest/tests/md5/numtests b/security/nss/cmd/bltest/tests/md5/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/md5/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/md5/plaintext0 b/security/nss/cmd/bltest/tests/md5/plaintext0
new file mode 100644
index 000000000..5ae3875e2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/md5/plaintext0
@@ -0,0 +1 @@
+63-byte input to MD5 can be a bit tricky, but no problems here.
diff --git a/security/nss/cmd/bltest/tests/rc2_cbc/ciphertext0 b/security/nss/cmd/bltest/tests/rc2_cbc/ciphertext0
new file mode 100644
index 000000000..d964ef864
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_cbc/ciphertext0
@@ -0,0 +1 @@
+3ki6eVsWpY8=
diff --git a/security/nss/cmd/bltest/tests/rc2_cbc/iv0 b/security/nss/cmd/bltest/tests/rc2_cbc/iv0
new file mode 100644
index 000000000..97b5955f7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_cbc/iv0
@@ -0,0 +1 @@
+12345678
diff --git a/security/nss/cmd/bltest/tests/rc2_cbc/key0 b/security/nss/cmd/bltest/tests/rc2_cbc/key0
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_cbc/key0
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/rc2_cbc/numtests b/security/nss/cmd/bltest/tests/rc2_cbc/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_cbc/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/rc2_cbc/plaintext0 b/security/nss/cmd/bltest/tests/rc2_cbc/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_cbc/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/rc2_ecb/ciphertext0 b/security/nss/cmd/bltest/tests/rc2_ecb/ciphertext0
new file mode 100644
index 000000000..337d30765
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_ecb/ciphertext0
@@ -0,0 +1 @@
+WT+tc4fANhQ=
diff --git a/security/nss/cmd/bltest/tests/rc2_ecb/key0 b/security/nss/cmd/bltest/tests/rc2_ecb/key0
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_ecb/key0
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/rc2_ecb/numtests b/security/nss/cmd/bltest/tests/rc2_ecb/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_ecb/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/rc2_ecb/plaintext0 b/security/nss/cmd/bltest/tests/rc2_ecb/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_ecb/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/rc4/ciphertext0 b/security/nss/cmd/bltest/tests/rc4/ciphertext0
new file mode 100644
index 000000000..004f13472
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc4/ciphertext0
@@ -0,0 +1 @@
+34sTZJtr20k=
diff --git a/security/nss/cmd/bltest/tests/rc4/ciphertext1 b/security/nss/cmd/bltest/tests/rc4/ciphertext1
new file mode 100644
index 000000000..6050da4c6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc4/ciphertext1
@@ -0,0 +1 @@
+34sTZJtr20nGP6VxS3BIBxxIYm6QGIa1rehFHn51z9M=
diff --git a/security/nss/cmd/bltest/tests/rc4/key0 b/security/nss/cmd/bltest/tests/rc4/key0
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc4/key0
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/rc4/key1 b/security/nss/cmd/bltest/tests/rc4/key1
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc4/key1
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/rc4/numtests b/security/nss/cmd/bltest/tests/rc4/numtests
new file mode 100644
index 000000000..0cfbf0888
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc4/numtests
@@ -0,0 +1 @@
+2
diff --git a/security/nss/cmd/bltest/tests/rc4/plaintext0 b/security/nss/cmd/bltest/tests/rc4/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc4/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/rc4/plaintext1 b/security/nss/cmd/bltest/tests/rc4/plaintext1
new file mode 100644
index 000000000..d41abc7b8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc4/plaintext1
@@ -0,0 +1 @@
+Mozilla!Mozilla!Mozilla!Mozilla!
diff --git a/security/nss/cmd/bltest/tests/rc5_cbc/ciphertext0 b/security/nss/cmd/bltest/tests/rc5_cbc/ciphertext0
new file mode 100644
index 000000000..544713b33
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_cbc/ciphertext0
@@ -0,0 +1 @@
+qsv4Fn2J6d0=
diff --git a/security/nss/cmd/bltest/tests/rc5_cbc/iv0 b/security/nss/cmd/bltest/tests/rc5_cbc/iv0
new file mode 100644
index 000000000..97b5955f7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_cbc/iv0
@@ -0,0 +1 @@
+12345678
diff --git a/security/nss/cmd/bltest/tests/rc5_cbc/key0 b/security/nss/cmd/bltest/tests/rc5_cbc/key0
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_cbc/key0
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/rc5_cbc/numtests b/security/nss/cmd/bltest/tests/rc5_cbc/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_cbc/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/rc5_cbc/params0 b/security/nss/cmd/bltest/tests/rc5_cbc/params0
new file mode 100644
index 000000000..d68e0362d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_cbc/params0
@@ -0,0 +1,2 @@
+rounds=10
+wordsize=4
diff --git a/security/nss/cmd/bltest/tests/rc5_cbc/plaintext0 b/security/nss/cmd/bltest/tests/rc5_cbc/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_cbc/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/rc5_ecb/ciphertext0 b/security/nss/cmd/bltest/tests/rc5_ecb/ciphertext0
new file mode 100644
index 000000000..133777dd0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_ecb/ciphertext0
@@ -0,0 +1 @@
+4ZKK/1v5Ohc=
diff --git a/security/nss/cmd/bltest/tests/rc5_ecb/key0 b/security/nss/cmd/bltest/tests/rc5_ecb/key0
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_ecb/key0
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/rc5_ecb/numtests b/security/nss/cmd/bltest/tests/rc5_ecb/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_ecb/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/rc5_ecb/params0 b/security/nss/cmd/bltest/tests/rc5_ecb/params0
new file mode 100644
index 000000000..d68e0362d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_ecb/params0
@@ -0,0 +1,2 @@
+rounds=10
+wordsize=4
diff --git a/security/nss/cmd/bltest/tests/rc5_ecb/plaintext0 b/security/nss/cmd/bltest/tests/rc5_ecb/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_ecb/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/rsa/ciphertext0 b/security/nss/cmd/bltest/tests/rsa/ciphertext0
new file mode 100644
index 000000000..943ea599a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa/ciphertext0
@@ -0,0 +1 @@
+qPVrXv0y3SC5rY44bIi6GE4Aec8uDpHH7/cCg0FU5as=
diff --git a/security/nss/cmd/bltest/tests/rsa/key0 b/security/nss/cmd/bltest/tests/rsa/key0
new file mode 100644
index 000000000..1352fe986
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa/key0
@@ -0,0 +1,4 @@
+AAAAAAAAACC5lyu2K2ro8YGnvOCKaL1sFX1HEIblIVbuMXsa8oeFSwAAAAERAAAA
+IBXVjKwFG6LvPG4WOIjBBzmxGNpkQwDs3W5qZcXVzqahAAAAEOEOH/WnhZCJyM39
+oNfhf18AAAAQ0xvmxqXXs3L62xxogUl9lQAAABAaeiHgqkvy4wiQtG1Gkv/tAAAA
+EMaw2TNu6SFdKFXAYluQdjEAAAAQi0u+IlgKCt/hatGAsTrfzQ==
diff --git a/security/nss/cmd/bltest/tests/rsa/numtests b/security/nss/cmd/bltest/tests/rsa/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/rsa/plaintext0 b/security/nss/cmd/bltest/tests/rsa/plaintext0
new file mode 100644
index 000000000..d915bc88c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa/plaintext0
@@ -0,0 +1 @@
+512bitsforRSAPublicKeyEncryption
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext0 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext0
new file mode 100644
index 000000000..7037fa2e1
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext0
@@ -0,0 +1,3 @@
+NU/me0oSbV01/jbHd3kaP3uhPe9ITi05CK/3IvrUaPshaW3pXQvpEcLTF0+K/MIBA197bY5pQC3l
+RRYYwhpTX6nXv8W43Z/CQ/jPkn2zEyLW6IHqqRqZYXDmV6BaJmQm2YyIAD+Ed8EicJSg2foejEAk
+MJzh7My1IQA11HrHLoo=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext1 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext1
new file mode 100644
index 000000000..4cece4832
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext1
@@ -0,0 +1,3 @@
+ZA2xrMWOBWj+VAfl+bcB3/jDyR5xbFNvx/zsbLW3HBFlmI1KJ54Vd9cw/Hopky4/AMgVFSNtjY4x
+AXp6Cd9DUtkEzet5qlg63MMeppikwFKD2rqQib5UkfZ8Gk7kjcdLu+ZkOu+EZnm0yzlaNS1e0RWR
+LfaW/+BwKTKUbXFJK0Q=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext10 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext10
new file mode 100644
index 000000000..6007b8d65
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext10
@@ -0,0 +1,4 @@
+Iyr7ySf6CML2onuH1KXLCcB9wm+uc9c6kFWIOfT9ZtKBuH7HNLziN7oWZpjtgpEGp95pQs1s3OeP
+7Y0uTYFCjmZJDQNiZM75KvlB0+NQVf45geFNKcu5pPZ0cwY7rseaEXn1oXycGDLyg4/X1eWbuWWd
+VtzooBnt7xuzrMxpfMbMenePYKBkx/b11SnGIQJi4APeWD6B4xZ7iZcfuMDhXUT//vibU9jWTdeX
+0Vm1bSsI6lMH6hLCQb1Y1O4nih8u
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext11 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext11
new file mode 100644
index 000000000..43b65a670
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext11
@@ -0,0 +1,4 @@
+Q4zH3AimjaJJ5CUF+Fc7pg4sJ3PVspD0z53/cY6EIIHDg+ZwJKDylZTqmHudJeS3OPKFlw0ZWrs6
+jIBU49eda5yagye6WW8SWeJxJmdHZpB9jVgv86hHYVSSmtsebRI1ssy07I9mO6nMZwqSvr2FPI2/
+acZDbQFvYa3YNulHMkUENCB/n9TEPewqEqlY76Ae/iZpiZteYEwlXFX7cWbeVYnjaVl7sJFowG3V
+2xd+BqF0DrLVyC+uym2S/O6ZMbqf
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext12 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext12
new file mode 100644
index 000000000..9d0da8a07
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext12
@@ -0,0 +1,5 @@
+U+pdwIzSYPs7hYVnKH+pFVLDCy/r+6IT8K6HcC0GjRm6sH/ldFI9+0ITnWjDxa/u4L/ky3lpy/OC
+uATW5hOWFE4tDmB0H4mTwwFLWLmxlXqLq80jr4VPTDVvsWYqpyv8x+WGVZ3EKA0WDBJnhacj6+6+
+/3HxFZRECq74fRB5Ood0ojnUoEyH/hRnudr4UgjsbHJVeUqWzCkUL5qL1Bjjwf1nNEsM0IKd87K+
+xgJTGWKTxrNNP3XTLyE91Fxic9UFrfTM7RBXy3WPwmru+kQSVe1OZMGZ7gdefxZkYYL9tGRzm2ir
+Xa/w5j6VUgFoJPBUv008jJCpe7a2VTKE60KfzA==
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext13 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext13
new file mode 100644
index 000000000..3ecd85768
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext13
@@ -0,0 +1,5 @@
+orGkMKnWV+L6HCu17UP/slwFowj+kJPAEDF5X1h0QAEQgorlj7m1gc6d3dPlSa4EoJhUWb3mxiZZ
+TnsF3EJ4sqFGXBNoQIgjyF6W3GbDowmDxjlmT8RWmjf+IeWhlbV3bu0t+NjTYa9obnUCKbvWY/Fh
+hopQYV4MM3vsDKNf7AuxnDbrLgu8wFgvodk6rNsGEGP1nyzh7kNgXl2J7KGD0qzf6fgQEQIq07Q6
+PdQX2slLThHqgbGSlm6WaxgggucZZGB7T4AC82KZhEoR8q4PrqwurnD49PmAiKzc0KxVbp/MxRFS
+GQj60m8ExkIBRQMFd4dYsFOL+LW7FEqCjmKXlQ==
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext14 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext14
new file mode 100644
index 000000000..09d8a8582
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext14
@@ -0,0 +1,5 @@
+mIbD5nZKi5qE6EFI69jDsaqAUDgaePZocUwW2c/Spu3FaXnFNdne47RLhcGL6JKJkjcXEUciFtld
+2pjS7oNHybFN/9/4SqSNJawG99fmU5islnsc6Qkl9n3OBJt/gS2wdCmXp01E/oHb4Oej/q8uXECv
+iI1VDdu+O8IGV6KVQ/j8KRO5vRphsqsiVuxAm719wNF3F+olxD9C7Sffhzi/SvxnZv96/whZVV7i
+g5IPTIpjxKc0DLr93DOezbSwUVAC+WyTK1t5Fnr2mcCtP8z98PROhacCYr8uGP40uFBYmXXoZ/+W
+nUjqvyEicVRs3AWmnstSblKHDINvMHvXmHgO3g==
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext15 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext15
new file mode 100644
index 000000000..bae2acb56
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext15
@@ -0,0 +1,5 @@
+Yxjp+1wNBeUwfhaDQ26QMpOsRkI1iqoiPXFjATq6h+Lf2o5gxoYOKaHpJoYWPqC5F18ynKOxMaHt
+06d3Wai5e61qT49DlvKM9vOcpYES5IFg1uID2qWFbzrKX/7Vd69JlAjj39Iz4+YE2+NKnEyQgt5l
+UnysYzHSncgOBQig+nEi5/Mp9sylz6NNTR2kF4BUV+AIvsVJ5Hj/nhKnY8R30Vu7ePW2m9V4MPws
+TtaG15vHKpXYX4gTTGsK/laozPvIVYKLszm9F5Cc8dcN4zNa4HA5CT5gbWVTZd5lULhyzW3h1EDu
+AxthlF9imtijU7DUCTnpajxFDSqNXu6fZ4CTyA==
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext16 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext16
new file mode 100644
index 000000000..6226b0e7f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext16
@@ -0,0 +1,5 @@
+dSkIcsz9SkUFZg1lH1babaoJyhMB2JBjL2qZLz1WXO5GSv3tQO07W+k1ZxTqWqdlX0oTZsLxfHKP
+byxaXR+OKEKbxOb48s/42o3A4KmAjkX9CeovpAyyts5v//XA4VnRG2jZCoX3uE4QOwnmgmZkgMZX
+UFwJKSWUaKMUeG106rExVzzyNL9X232eZsxnSBkuAC3A3uqTBYXwgx/c2bwz1R957S/8Frz01ZgS
+/OvKo/kGmw5EVobWRMJcz2O0Vu5fpv/pbxnN91H+2erzWVd1Tb9L/qUhaqGETcUHyy0IDnIuuhUD
+CMK1/xGTYg8XZuz0SBuvuUO9KSh38hNspJSroA==
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext17 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext17
new file mode 100644
index 000000000..9095393e0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext17
@@ -0,0 +1,5 @@
+LSB6c0Mqj7TAMFGz9zsophdkCY36NMR6IJlfgRWqaBZnm1V+gtvuWEkIxuaXgtfes029Za8GPVf8
+p2pf0GlJL9YGjZmE0gk1BWWmLlx38jA4wSyxDGY0cJtUfEb2tKcJvYXKEi10Rl75d2LCl2Pgbbx6
+nnOMeL/KAQLcXnnWW5c/KCQMqrLhYaeLV9JiRX7YGV1T48eunaAhiDxtt8JK/dIyLqyXKtPDVMX8
+7x4UbDoCkPtnrfAHBm4AQo0s7BjOWPkyhpje/vSy617HaRj94cGYy7OLevxnYmqa7+xDIr/ZDSVj
+SByaIh94yCcsgtG2KrkU4cafavbvMMpSYNtKRg==
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext2 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext2
new file mode 100644
index 000000000..8eb40cd8c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext2
@@ -0,0 +1,3 @@
+Qjc27QNfYCavJ2w1wLN0GzZeX3bKCRtOjCni8L7+5gNZWqgyLWAtLmJeleuBsvHJck6CLsp224YY
+zwnFNDUDpDYINbWQO8Y344efsF4O8yaF1a7FBnzXzJb+SyZwturDBmsfz1aGtoWJqvt9YpsC2Phi
+XKODNiTUgA+wgbHPlOs=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext3 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext3
new file mode 100644
index 000000000..1e86bb071
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext3
@@ -0,0 +1,3 @@
+RerUylUeZiyYAPGsqCg7BSXmq64wvktKunYvpA/T044iq+/Gl5T267vAXduxEhYkfS9BL9D7qHxu
+Os2IiBNkb9DkjnhSBPnD9z1tgjlWJyLd3Ydx/sSLg6Me5vWSxM/UvIgXTzsToRKq47n3uA4Pxvcl
+W6iA3H2AIeIq1qhfB1U=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext4 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext4
new file mode 100644
index 000000000..3f87612fc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext4
@@ -0,0 +1,3 @@
+NvbjTZSo002qy6M6ITnQCthak0WoYFHnMHFiAFa5IOIZAFhVohOg8jiXzc1zG0UlfHd/6QggK+/d
+C1g4axJE6gz1OaBdXRAynaROEwMP12Dc1kTP7yCU0ZENP0M+HHxt0YvB8t9/ZD1mL7ndN+rZBZGQ
+9PpmyjnoacTrRJy9xDk=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext5 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext5
new file mode 100644
index 000000000..64a5f4fe7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext5
@@ -0,0 +1,3 @@
+Qs7iYXsezqTbP0gpOG+9Ydr78DjhgNg3yWNm3yTAl7SrD6xr31kNghyfEGQuaBrQW414s3jA9Gzi
++tY/dOCtPfBrB11+tfVjb41AO5BZynYbXGK7UqpFAC6nC6rOCN7SQ7nYy9YqaK3iZYMrVlZOQ6b6
+Qu0ZmgmXaXQt8VOeglU=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext6 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext6
new file mode 100644
index 000000000..9af9805c6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext6
@@ -0,0 +1,4 @@
+JnvNEYrKsfyLqByF1zADy4YQ+lXB2X2o1Ip8fwaJak23UaooQlW502rWXzdlPYKfGzf5e4ABlCVF
+svwsVac3bKehvksXYMjgWjPlqiUmuNmOMXCI54NMdVsqWbEmMaGCwF1dQ6sXeSZPhFb1Fc5X399R
+LVST2re3M43Et9eNucCRrDuvU3pp/H9UnZefDv+alP2kFpvU0dGaacmeM8O1VJDVAbObHtrhGP9n
+k6FTJhWE06Xzn25oLj0XyM0SYfpy
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext7 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext7
new file mode 100644
index 000000000..4396ffbaf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext7
@@ -0,0 +1,4 @@
+k6yfBnHsKay7RE7/waV0E1HWD9sOOT+/dUrPDeSXYaFIQd93cum8gnc5ZqFYTE1yuuoAEY+D81zK
+blN8vU2BH1WDspeD2KbZTNMb5w1vUmwQ/wnG+nzgaXlaP80FEf1fy1ZLzIDqnHjzi4ABJTnYpN32
+/oHpzdt/UNu7vMfl2GCXzPTsSRifuL8xi+bVoHFdUWtJrxkSWM0y3IM85utGc8A6Gbus6IzFSJX2
+NswMHsiQltEc4jWiZcoXZCMqaJro
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext8 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext8
new file mode 100644
index 000000000..5d53ef0b0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext8
@@ -0,0 +1,4 @@
+gevdlQVLDIIu+a12k/Woet+0tMTOcN8t+E7UnATaWLpfwgoZ4abot6OQCyJ5bcToae5rQnktFajs
+61bAnGmRToE86o9pMeS47W9CGvKY1ZXJf0eJx8qmEsfvNgmEwhuT7cVAEGi1r0x4qHcbmE1TuOqK
+3y9qfUoLp2x14d2fZY8g3tSkYHHUbXeRtWgD2P6n8LD45Brj8JODpvlYX+d1Pqr/0r+UVjEIvuzC
+B7u1NfX8xwXw3en3CMYvSanJA3HT
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext9 b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext9
new file mode 100644
index 000000000..6e865ff4b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/ciphertext9
@@ -0,0 +1,4 @@
+vMNflM3mbLETZiXWJblEMqNbIvPS+hGmE/8PylvVf4e5AszcHNCuvLBxXuhp0dH+OV9nkwA/XspG
+UFnIhmDURv9fCBhVICJVfjjAimfq2ZEmIlTxBoKXXsVjl3aFN/SXevbV9qrOt/sl3sWTcjAjH9iX
+ivSRGaKfKeQkq4JytHVieS1clPd0uIKdCw2fGoye3fN1dNX6JI7vqcUnH8XsJXnIG91htBD6Yf42
+5CQiHBE63bJ1ZkyAHTTKjGNR5KhY
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash0 b/security/nss/cmd/bltest/tests/rsa_oaep/hash0
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash0
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash1 b/security/nss/cmd/bltest/tests/rsa_oaep/hash1
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash1
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash10 b/security/nss/cmd/bltest/tests/rsa_oaep/hash10
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash10
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash11 b/security/nss/cmd/bltest/tests/rsa_oaep/hash11
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash11
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash12 b/security/nss/cmd/bltest/tests/rsa_oaep/hash12
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash12
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash13 b/security/nss/cmd/bltest/tests/rsa_oaep/hash13
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash13
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash14 b/security/nss/cmd/bltest/tests/rsa_oaep/hash14
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash14
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash15 b/security/nss/cmd/bltest/tests/rsa_oaep/hash15
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash15
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash16 b/security/nss/cmd/bltest/tests/rsa_oaep/hash16
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash16
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash17 b/security/nss/cmd/bltest/tests/rsa_oaep/hash17
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash17
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash2 b/security/nss/cmd/bltest/tests/rsa_oaep/hash2
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash2
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash3 b/security/nss/cmd/bltest/tests/rsa_oaep/hash3
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash3
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash4 b/security/nss/cmd/bltest/tests/rsa_oaep/hash4
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash4
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash5 b/security/nss/cmd/bltest/tests/rsa_oaep/hash5
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash5
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash6 b/security/nss/cmd/bltest/tests/rsa_oaep/hash6
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash6
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash7 b/security/nss/cmd/bltest/tests/rsa_oaep/hash7
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash7
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash8 b/security/nss/cmd/bltest/tests/rsa_oaep/hash8
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash8
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/hash9 b/security/nss/cmd/bltest/tests/rsa_oaep/hash9
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/hash9
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key0 b/security/nss/cmd/bltest/tests/rsa_oaep/key0
new file mode 100644
index 000000000..61684becc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key0
@@ -0,0 +1 @@
+AAAAAQAAAACAqLOyhK+OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx+CwgtaTpef87Wdc9GaFEncsDLxkp0LGxjD1M8jMcvYq6DPEC/JYQumEu3i9v5fAEH1VvbZi9cTg+rmEXLUUjvc5LdOq/5OuHmtme7PUJHYW1PW6ENTP0ibeiNOfFvsAAAADAQABAAAAgFMznP23n8hGamVccxasqFxV/Y9t2Jj9rxGVF+9PUuj9jiWN+T/uGA+g5KspaTzYOxUqVT1KxNGBK4ufpa8Of1X+cwTfQVcJJvMxHxXE1lpzLEgxFu49PS0K81Sa2b98v7eK2IT4TVvrBHJNxzabMd7zfQz1OenPzdPeZTcp6tXRAAAAQNMnN+cmf/4TQbLVwNFQqBtYb7MTK+0vjVJihkqcufMK84vkSFmNQToXLvuALCGs8cEcUgwvJqRx3K0hLqx8o50AAABAzIhT0dVNpjD6wAT0cfKBx7iYLYIkpJDtvrM9Pj1cyTxHZXA9HdeRZC8fEWoN2FK+JBmyr3K/6aAw6GCwKItddwAAAEAOEr8XGOnO9VmbocOIL+gEapCHTu/OjyzMIOTydB+wozo4SK7JyTBfvsvS12gZln1GcazGQx5AN5aNs3h45pXBAAAAQJUpew+Vovpn0AcH1gnf1PwFyJ2vwu9tbqVb7HceozNzTZJR55CC7NqGbv7xPEWeGmMThrfjVMiZ9fESyoXXFYMAAABAT0VsUCSTvcDtKrdWo6btTWc1Kml9QhbpMhKxJ6Y9VBHOb6mNXb79cyY+NygUJ0OBgWbtfdY2h90qjKHS9PvY4Q== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key1 b/security/nss/cmd/bltest/tests/rsa_oaep/key1
new file mode 100644
index 000000000..61684becc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key1
@@ -0,0 +1 @@
+AAAAAQAAAACAqLOyhK+OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx+CwgtaTpef87Wdc9GaFEncsDLxkp0LGxjD1M8jMcvYq6DPEC/JYQumEu3i9v5fAEH1VvbZi9cTg+rmEXLUUjvc5LdOq/5OuHmtme7PUJHYW1PW6ENTP0ibeiNOfFvsAAAADAQABAAAAgFMznP23n8hGamVccxasqFxV/Y9t2Jj9rxGVF+9PUuj9jiWN+T/uGA+g5KspaTzYOxUqVT1KxNGBK4ufpa8Of1X+cwTfQVcJJvMxHxXE1lpzLEgxFu49PS0K81Sa2b98v7eK2IT4TVvrBHJNxzabMd7zfQz1OenPzdPeZTcp6tXRAAAAQNMnN+cmf/4TQbLVwNFQqBtYb7MTK+0vjVJihkqcufMK84vkSFmNQToXLvuALCGs8cEcUgwvJqRx3K0hLqx8o50AAABAzIhT0dVNpjD6wAT0cfKBx7iYLYIkpJDtvrM9Pj1cyTxHZXA9HdeRZC8fEWoN2FK+JBmyr3K/6aAw6GCwKItddwAAAEAOEr8XGOnO9VmbocOIL+gEapCHTu/OjyzMIOTydB+wozo4SK7JyTBfvsvS12gZln1GcazGQx5AN5aNs3h45pXBAAAAQJUpew+Vovpn0AcH1gnf1PwFyJ2vwu9tbqVb7HceozNzTZJR55CC7NqGbv7xPEWeGmMThrfjVMiZ9fESyoXXFYMAAABAT0VsUCSTvcDtKrdWo6btTWc1Kml9QhbpMhKxJ6Y9VBHOb6mNXb79cyY+NygUJ0OBgWbtfdY2h90qjKHS9PvY4Q== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key10 b/security/nss/cmd/bltest/tests/rsa_oaep/key10
new file mode 100644
index 000000000..3c9f8742f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key10
@@ -0,0 +1 @@
+AAAAAQAAAADAzyzUHjTKOnKOpcuK/2TDbSe971Nk4zb9aNMSPFoZaowocBPoU9UVbVjRUZVFIPtPbXsXq7aBd2WQnFdhGWWdkCsZBu2KKxDBVcJNEkUo2rnurjeb6sZuSkEXhty4/QBi68Aw3hIZoEwqjBt90xMeTWtsruLjGl7UGsFQmy7x7iqxg2S+VoypQcJezIT/nWQ7XsGqrhAqINc/R5t4D9bakQdSEtnqwDoGdNiZ66LkMfTES2Fba6IjK9SzO67XPWJdAAAAAwEAAQAAAMAZjBQeI3FakrzPahGaW8ETiUaNKBH1SNcn4XtKsOuYbW8hHvtTtx98y+qH7mnHXuYVAIxTMt61K/OQq9+/431yBTaBWbJjjB3jJuIdIiUfD7WEizvxUAXSp0Mw8K/pFu5izME0TR2DpwnmBnYnOED383dCSl4KTadfAbMf92gZz5y/3SFSQ8ORfAPvOBmTEuVns7967Tq0V/Nx74oUI/RbaMbiguwRG7ooM7mH/Wn62DvBuMYTxeHqFsEe0SXqfsEAAABg/I1sBL7E65qBksp5AMvlNuLotRnezzOyRZeYxpCd9PF2230jGQ/HK4hlpxiviV8bzZFFKYAnQjtgXnCkfPWDkKjD6I/IxI6LMuPaIQ374+iB6lZ0tqNIwh6T+eVepl79AAAAYNIA1F54iqzqYGpAHQRg+H3VwQJ+EtwaDXWG6JOdnPeJtA9RrARClh3n0hzCHgXIMVXB8qqRkzh8/flWy0jRU7onBAb5u7pTfUmH2eL5lC16FMv//qdP7N2pKNI+JZ9e4QAAAGDbFoAveaLw1F81jWn9M+RLgfroKGIuk6VCU+mX0BsHQ3WdoOgStKpObIvqsjKNVDGVWkGKZ/8mqMXIB6XaNU4F7zHMjPdY9GNzKVCwPiZXJvuU451qVyomJEqwjbdXUq0AAABgoKMXz+ffFCP4em3uhFH04rSmflSX8ptPHk6DC5+t2UARZwJvVZblo5yXgX4PXxbifhnsmQLgHX6m+5qjx2Cv7h44G2neasnAdYWgatnEugC/dcitL6iYpHnoCuKU/tKhAAAAYAsh8zXDUzQutEw6okRFeAwtZVuUAXTK44x8ik5kk8C6n9MDdIJnsIO5p6bLYeQts2K4yYlttwZOAq1a5hWH2hW0ZJyQWUkJ/rN9vLZUvrcmjsgB5ai0qjkRvr2IVC8Fvg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key11 b/security/nss/cmd/bltest/tests/rsa_oaep/key11
new file mode 100644
index 000000000..3c9f8742f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key11
@@ -0,0 +1 @@
+AAAAAQAAAADAzyzUHjTKOnKOpcuK/2TDbSe971Nk4zb9aNMSPFoZaowocBPoU9UVbVjRUZVFIPtPbXsXq7aBd2WQnFdhGWWdkCsZBu2KKxDBVcJNEkUo2rnurjeb6sZuSkEXhty4/QBi68Aw3hIZoEwqjBt90xMeTWtsruLjGl7UGsFQmy7x7iqxg2S+VoypQcJezIT/nWQ7XsGqrhAqINc/R5t4D9bakQdSEtnqwDoGdNiZ66LkMfTES2Fba6IjK9SzO67XPWJdAAAAAwEAAQAAAMAZjBQeI3FakrzPahGaW8ETiUaNKBH1SNcn4XtKsOuYbW8hHvtTtx98y+qH7mnHXuYVAIxTMt61K/OQq9+/431yBTaBWbJjjB3jJuIdIiUfD7WEizvxUAXSp0Mw8K/pFu5izME0TR2DpwnmBnYnOED383dCSl4KTadfAbMf92gZz5y/3SFSQ8ORfAPvOBmTEuVns7967Tq0V/Nx74oUI/RbaMbiguwRG7ooM7mH/Wn62DvBuMYTxeHqFsEe0SXqfsEAAABg/I1sBL7E65qBksp5AMvlNuLotRnezzOyRZeYxpCd9PF2230jGQ/HK4hlpxiviV8bzZFFKYAnQjtgXnCkfPWDkKjD6I/IxI6LMuPaIQ374+iB6lZ0tqNIwh6T+eVepl79AAAAYNIA1F54iqzqYGpAHQRg+H3VwQJ+EtwaDXWG6JOdnPeJtA9RrARClh3n0hzCHgXIMVXB8qqRkzh8/flWy0jRU7onBAb5u7pTfUmH2eL5lC16FMv//qdP7N2pKNI+JZ9e4QAAAGDbFoAveaLw1F81jWn9M+RLgfroKGIuk6VCU+mX0BsHQ3WdoOgStKpObIvqsjKNVDGVWkGKZ/8mqMXIB6XaNU4F7zHMjPdY9GNzKVCwPiZXJvuU451qVyomJEqwjbdXUq0AAABgoKMXz+ffFCP4em3uhFH04rSmflSX8ptPHk6DC5+t2UARZwJvVZblo5yXgX4PXxbifhnsmQLgHX6m+5qjx2Cv7h44G2neasnAdYWgatnEugC/dcitL6iYpHnoCuKU/tKhAAAAYAsh8zXDUzQutEw6okRFeAwtZVuUAXTK44x8ik5kk8C6n9MDdIJnsIO5p6bLYeQts2K4yYlttwZOAq1a5hWH2hW0ZJyQWUkJ/rN9vLZUvrcmjsgB5ai0qjkRvr2IVC8Fvg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key12 b/security/nss/cmd/bltest/tests/rsa_oaep/key12
new file mode 100644
index 000000000..a2ad3ff8d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key12
@@ -0,0 +1 @@
+AAAAAQAAAAEArkXtVgHOxrjMBfgDk1xnTdvg11xMCf15UfxrDK7DE6jfOZcMUYv/ul7Wjz8NfyKkAp1BPxrgfk6+nkF3ziPn9UBLVp5O4b3PPB+wPvETgC1PhV65tRNLWnyAha3K5vovoUF+w3Y74XGwxit2Dt4jwSrZK5gIhMZB9aj6wmva1KAzgaIv4bdUiFCUyCUG1AGaU1ooav6ycbubpZLeGNz2AMKu6uVuAvfPefwUzzvcfNhP67v5UMqQMEsiGaeqBjrvosPBmA5WDNZK/neVhbYQdle5V4V+/eYBCYirfeQX/IjY84TE5ucsP5Q+DDHAxKXMNvh52KOsnX1Zhg6q2muDuwAAAAMBAAEAAAEABWsEIW/l81SsdyUKS2sMhSWoXFmwvYDFZFCiLV9DjllqMzqodeKR3UP0jLiLnV/A1Jn5/NHDl/mvwHDNnjmMjRnmHbfHQQprJnXfv100W4BNIBrdUC1c4t/LCRzpmXu+vlcwbzg+TViBA/A29+hdGTTRUqMj5KjbRR1vSlsbDxAswVDgL+7iuI3qStTBusyyTYQHLRTh0kpncfdAjuMFZPuG1Dk6NLzwt4hQHRkzA/E6IoSwAfD2Ser3kyjUrFxDCrRBSSCpRg7Rt7xA7GU+h20Jq8UJrkW1JRkBFqDCYQGEgphQnBw786SD5ydAVOFelwdQNumJ9gkygHtSV3UeeQAAAIDs9a7NHlUV//rL11ooFsbr9JAYzftGOOGF1mpzlrb4CQ+AGMf9lcw0uFfcF/DMZRa7E0arTVgsra17QQM1I4e3AzjQhAR8nZU5tkliBLPdbqRCSZIHvsAflkKH/2M2w5hGWDNoRvVuRoYYgcECM9IXa/FaXpbdx4C8hoqnfTznaQAAAIC8RsRk/GrEyng7DrCKPIQbdy9+my8our1YiuiF4aDGHkhYoPslrCmZkPNb6FFkwlm6EXXN1xknBxNRhJkrbCm3Rt0NLKvhQoNffRSMwWFSS0oJlG1IuChHPxzna2y2iGw0XAPgX0HVG1w6kKPyQHPH10pP4l2c8hx1lg8/w4YxgwAAAIDHNWRXHQD7FdCKPemVelCRXXEm6UQtrPQryC6GLlZz/2oAjtTS43RhffifF6FgtDt/2py2trdCGGCYFffUXKJjwVmqMtJy0Sf69LyMotdzeOiusZsK19o8s94K5zFJgPYrbUsKh10d8DwbrjnM2DPvbNfi2VKL8ITR+WnnlOn2wQAAAIAmWLN/bfnBAwvh22gRf6nYfjnqK2k7fm06L3CUdBPuxhQuGPuN/LasVF18hqCtSPhFcXDw77JrxIEmxT79HRaSAZjcKhEH3CgttqgM0wYjYLo/oT9w5DEv8abNa4/EzZxcPbF8bWpXIS9zrin2GTJ7rVmxU4WFhbpOKLYKYqReSQAAAIBvOFJrOSUIVTTvPkFag27ei4YViix8v+zLC9g0ME/saDuo1PR5xDPUNBbmMmliPOoQB3bYWv9AHT//YQ7mVBHOOxNj1jqXCe7eQmR86lYUk9VFcKh5wYaCzZdxC5YgXsMRF9c7XzYiP63W6LqQ3XwO5h1E4WMlHiDH9m6zBRF8uA== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key13 b/security/nss/cmd/bltest/tests/rsa_oaep/key13
new file mode 100644
index 000000000..a2ad3ff8d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key13
@@ -0,0 +1 @@
+AAAAAQAAAAEArkXtVgHOxrjMBfgDk1xnTdvg11xMCf15UfxrDK7DE6jfOZcMUYv/ul7Wjz8NfyKkAp1BPxrgfk6+nkF3ziPn9UBLVp5O4b3PPB+wPvETgC1PhV65tRNLWnyAha3K5vovoUF+w3Y74XGwxit2Dt4jwSrZK5gIhMZB9aj6wmva1KAzgaIv4bdUiFCUyCUG1AGaU1ooav6ycbubpZLeGNz2AMKu6uVuAvfPefwUzzvcfNhP67v5UMqQMEsiGaeqBjrvosPBmA5WDNZK/neVhbYQdle5V4V+/eYBCYirfeQX/IjY84TE5ucsP5Q+DDHAxKXMNvh52KOsnX1Zhg6q2muDuwAAAAMBAAEAAAEABWsEIW/l81SsdyUKS2sMhSWoXFmwvYDFZFCiLV9DjllqMzqodeKR3UP0jLiLnV/A1Jn5/NHDl/mvwHDNnjmMjRnmHbfHQQprJnXfv100W4BNIBrdUC1c4t/LCRzpmXu+vlcwbzg+TViBA/A29+hdGTTRUqMj5KjbRR1vSlsbDxAswVDgL+7iuI3qStTBusyyTYQHLRTh0kpncfdAjuMFZPuG1Dk6NLzwt4hQHRkzA/E6IoSwAfD2Ser3kyjUrFxDCrRBSSCpRg7Rt7xA7GU+h20Jq8UJrkW1JRkBFqDCYQGEgphQnBw786SD5ydAVOFelwdQNumJ9gkygHtSV3UeeQAAAIDs9a7NHlUV//rL11ooFsbr9JAYzftGOOGF1mpzlrb4CQ+AGMf9lcw0uFfcF/DMZRa7E0arTVgsra17QQM1I4e3AzjQhAR8nZU5tkliBLPdbqRCSZIHvsAflkKH/2M2w5hGWDNoRvVuRoYYgcECM9IXa/FaXpbdx4C8hoqnfTznaQAAAIC8RsRk/GrEyng7DrCKPIQbdy9+my8our1YiuiF4aDGHkhYoPslrCmZkPNb6FFkwlm6EXXN1xknBxNRhJkrbCm3Rt0NLKvhQoNffRSMwWFSS0oJlG1IuChHPxzna2y2iGw0XAPgX0HVG1w6kKPyQHPH10pP4l2c8hx1lg8/w4YxgwAAAIDHNWRXHQD7FdCKPemVelCRXXEm6UQtrPQryC6GLlZz/2oAjtTS43RhffifF6FgtDt/2py2trdCGGCYFffUXKJjwVmqMtJy0Sf69LyMotdzeOiusZsK19o8s94K5zFJgPYrbUsKh10d8DwbrjnM2DPvbNfi2VKL8ITR+WnnlOn2wQAAAIAmWLN/bfnBAwvh22gRf6nYfjnqK2k7fm06L3CUdBPuxhQuGPuN/LasVF18hqCtSPhFcXDw77JrxIEmxT79HRaSAZjcKhEH3CgttqgM0wYjYLo/oT9w5DEv8abNa4/EzZxcPbF8bWpXIS9zrin2GTJ7rVmxU4WFhbpOKLYKYqReSQAAAIBvOFJrOSUIVTTvPkFag27ei4YViix8v+zLC9g0ME/saDuo1PR5xDPUNBbmMmliPOoQB3bYWv9AHT//YQ7mVBHOOxNj1jqXCe7eQmR86lYUk9VFcKh5wYaCzZdxC5YgXsMRF9c7XzYiP63W6LqQ3XwO5h1E4WMlHiDH9m6zBRF8uA== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key14 b/security/nss/cmd/bltest/tests/rsa_oaep/key14
new file mode 100644
index 000000000..a2ad3ff8d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key14
@@ -0,0 +1 @@
+AAAAAQAAAAEArkXtVgHOxrjMBfgDk1xnTdvg11xMCf15UfxrDK7DE6jfOZcMUYv/ul7Wjz8NfyKkAp1BPxrgfk6+nkF3ziPn9UBLVp5O4b3PPB+wPvETgC1PhV65tRNLWnyAha3K5vovoUF+w3Y74XGwxit2Dt4jwSrZK5gIhMZB9aj6wmva1KAzgaIv4bdUiFCUyCUG1AGaU1ooav6ycbubpZLeGNz2AMKu6uVuAvfPefwUzzvcfNhP67v5UMqQMEsiGaeqBjrvosPBmA5WDNZK/neVhbYQdle5V4V+/eYBCYirfeQX/IjY84TE5ucsP5Q+DDHAxKXMNvh52KOsnX1Zhg6q2muDuwAAAAMBAAEAAAEABWsEIW/l81SsdyUKS2sMhSWoXFmwvYDFZFCiLV9DjllqMzqodeKR3UP0jLiLnV/A1Jn5/NHDl/mvwHDNnjmMjRnmHbfHQQprJnXfv100W4BNIBrdUC1c4t/LCRzpmXu+vlcwbzg+TViBA/A29+hdGTTRUqMj5KjbRR1vSlsbDxAswVDgL+7iuI3qStTBusyyTYQHLRTh0kpncfdAjuMFZPuG1Dk6NLzwt4hQHRkzA/E6IoSwAfD2Ser3kyjUrFxDCrRBSSCpRg7Rt7xA7GU+h20Jq8UJrkW1JRkBFqDCYQGEgphQnBw786SD5ydAVOFelwdQNumJ9gkygHtSV3UeeQAAAIDs9a7NHlUV//rL11ooFsbr9JAYzftGOOGF1mpzlrb4CQ+AGMf9lcw0uFfcF/DMZRa7E0arTVgsra17QQM1I4e3AzjQhAR8nZU5tkliBLPdbqRCSZIHvsAflkKH/2M2w5hGWDNoRvVuRoYYgcECM9IXa/FaXpbdx4C8hoqnfTznaQAAAIC8RsRk/GrEyng7DrCKPIQbdy9+my8our1YiuiF4aDGHkhYoPslrCmZkPNb6FFkwlm6EXXN1xknBxNRhJkrbCm3Rt0NLKvhQoNffRSMwWFSS0oJlG1IuChHPxzna2y2iGw0XAPgX0HVG1w6kKPyQHPH10pP4l2c8hx1lg8/w4YxgwAAAIDHNWRXHQD7FdCKPemVelCRXXEm6UQtrPQryC6GLlZz/2oAjtTS43RhffifF6FgtDt/2py2trdCGGCYFffUXKJjwVmqMtJy0Sf69LyMotdzeOiusZsK19o8s94K5zFJgPYrbUsKh10d8DwbrjnM2DPvbNfi2VKL8ITR+WnnlOn2wQAAAIAmWLN/bfnBAwvh22gRf6nYfjnqK2k7fm06L3CUdBPuxhQuGPuN/LasVF18hqCtSPhFcXDw77JrxIEmxT79HRaSAZjcKhEH3CgttqgM0wYjYLo/oT9w5DEv8abNa4/EzZxcPbF8bWpXIS9zrin2GTJ7rVmxU4WFhbpOKLYKYqReSQAAAIBvOFJrOSUIVTTvPkFag27ei4YViix8v+zLC9g0ME/saDuo1PR5xDPUNBbmMmliPOoQB3bYWv9AHT//YQ7mVBHOOxNj1jqXCe7eQmR86lYUk9VFcKh5wYaCzZdxC5YgXsMRF9c7XzYiP63W6LqQ3XwO5h1E4WMlHiDH9m6zBRF8uA== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key15 b/security/nss/cmd/bltest/tests/rsa_oaep/key15
new file mode 100644
index 000000000..a2ad3ff8d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key15
@@ -0,0 +1 @@
+AAAAAQAAAAEArkXtVgHOxrjMBfgDk1xnTdvg11xMCf15UfxrDK7DE6jfOZcMUYv/ul7Wjz8NfyKkAp1BPxrgfk6+nkF3ziPn9UBLVp5O4b3PPB+wPvETgC1PhV65tRNLWnyAha3K5vovoUF+w3Y74XGwxit2Dt4jwSrZK5gIhMZB9aj6wmva1KAzgaIv4bdUiFCUyCUG1AGaU1ooav6ycbubpZLeGNz2AMKu6uVuAvfPefwUzzvcfNhP67v5UMqQMEsiGaeqBjrvosPBmA5WDNZK/neVhbYQdle5V4V+/eYBCYirfeQX/IjY84TE5ucsP5Q+DDHAxKXMNvh52KOsnX1Zhg6q2muDuwAAAAMBAAEAAAEABWsEIW/l81SsdyUKS2sMhSWoXFmwvYDFZFCiLV9DjllqMzqodeKR3UP0jLiLnV/A1Jn5/NHDl/mvwHDNnjmMjRnmHbfHQQprJnXfv100W4BNIBrdUC1c4t/LCRzpmXu+vlcwbzg+TViBA/A29+hdGTTRUqMj5KjbRR1vSlsbDxAswVDgL+7iuI3qStTBusyyTYQHLRTh0kpncfdAjuMFZPuG1Dk6NLzwt4hQHRkzA/E6IoSwAfD2Ser3kyjUrFxDCrRBSSCpRg7Rt7xA7GU+h20Jq8UJrkW1JRkBFqDCYQGEgphQnBw786SD5ydAVOFelwdQNumJ9gkygHtSV3UeeQAAAIDs9a7NHlUV//rL11ooFsbr9JAYzftGOOGF1mpzlrb4CQ+AGMf9lcw0uFfcF/DMZRa7E0arTVgsra17QQM1I4e3AzjQhAR8nZU5tkliBLPdbqRCSZIHvsAflkKH/2M2w5hGWDNoRvVuRoYYgcECM9IXa/FaXpbdx4C8hoqnfTznaQAAAIC8RsRk/GrEyng7DrCKPIQbdy9+my8our1YiuiF4aDGHkhYoPslrCmZkPNb6FFkwlm6EXXN1xknBxNRhJkrbCm3Rt0NLKvhQoNffRSMwWFSS0oJlG1IuChHPxzna2y2iGw0XAPgX0HVG1w6kKPyQHPH10pP4l2c8hx1lg8/w4YxgwAAAIDHNWRXHQD7FdCKPemVelCRXXEm6UQtrPQryC6GLlZz/2oAjtTS43RhffifF6FgtDt/2py2trdCGGCYFffUXKJjwVmqMtJy0Sf69LyMotdzeOiusZsK19o8s94K5zFJgPYrbUsKh10d8DwbrjnM2DPvbNfi2VKL8ITR+WnnlOn2wQAAAIAmWLN/bfnBAwvh22gRf6nYfjnqK2k7fm06L3CUdBPuxhQuGPuN/LasVF18hqCtSPhFcXDw77JrxIEmxT79HRaSAZjcKhEH3CgttqgM0wYjYLo/oT9w5DEv8abNa4/EzZxcPbF8bWpXIS9zrin2GTJ7rVmxU4WFhbpOKLYKYqReSQAAAIBvOFJrOSUIVTTvPkFag27ei4YViix8v+zLC9g0ME/saDuo1PR5xDPUNBbmMmliPOoQB3bYWv9AHT//YQ7mVBHOOxNj1jqXCe7eQmR86lYUk9VFcKh5wYaCzZdxC5YgXsMRF9c7XzYiP63W6LqQ3XwO5h1E4WMlHiDH9m6zBRF8uA== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key16 b/security/nss/cmd/bltest/tests/rsa_oaep/key16
new file mode 100644
index 000000000..a2ad3ff8d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key16
@@ -0,0 +1 @@
+AAAAAQAAAAEArkXtVgHOxrjMBfgDk1xnTdvg11xMCf15UfxrDK7DE6jfOZcMUYv/ul7Wjz8NfyKkAp1BPxrgfk6+nkF3ziPn9UBLVp5O4b3PPB+wPvETgC1PhV65tRNLWnyAha3K5vovoUF+w3Y74XGwxit2Dt4jwSrZK5gIhMZB9aj6wmva1KAzgaIv4bdUiFCUyCUG1AGaU1ooav6ycbubpZLeGNz2AMKu6uVuAvfPefwUzzvcfNhP67v5UMqQMEsiGaeqBjrvosPBmA5WDNZK/neVhbYQdle5V4V+/eYBCYirfeQX/IjY84TE5ucsP5Q+DDHAxKXMNvh52KOsnX1Zhg6q2muDuwAAAAMBAAEAAAEABWsEIW/l81SsdyUKS2sMhSWoXFmwvYDFZFCiLV9DjllqMzqodeKR3UP0jLiLnV/A1Jn5/NHDl/mvwHDNnjmMjRnmHbfHQQprJnXfv100W4BNIBrdUC1c4t/LCRzpmXu+vlcwbzg+TViBA/A29+hdGTTRUqMj5KjbRR1vSlsbDxAswVDgL+7iuI3qStTBusyyTYQHLRTh0kpncfdAjuMFZPuG1Dk6NLzwt4hQHRkzA/E6IoSwAfD2Ser3kyjUrFxDCrRBSSCpRg7Rt7xA7GU+h20Jq8UJrkW1JRkBFqDCYQGEgphQnBw786SD5ydAVOFelwdQNumJ9gkygHtSV3UeeQAAAIDs9a7NHlUV//rL11ooFsbr9JAYzftGOOGF1mpzlrb4CQ+AGMf9lcw0uFfcF/DMZRa7E0arTVgsra17QQM1I4e3AzjQhAR8nZU5tkliBLPdbqRCSZIHvsAflkKH/2M2w5hGWDNoRvVuRoYYgcECM9IXa/FaXpbdx4C8hoqnfTznaQAAAIC8RsRk/GrEyng7DrCKPIQbdy9+my8our1YiuiF4aDGHkhYoPslrCmZkPNb6FFkwlm6EXXN1xknBxNRhJkrbCm3Rt0NLKvhQoNffRSMwWFSS0oJlG1IuChHPxzna2y2iGw0XAPgX0HVG1w6kKPyQHPH10pP4l2c8hx1lg8/w4YxgwAAAIDHNWRXHQD7FdCKPemVelCRXXEm6UQtrPQryC6GLlZz/2oAjtTS43RhffifF6FgtDt/2py2trdCGGCYFffUXKJjwVmqMtJy0Sf69LyMotdzeOiusZsK19o8s94K5zFJgPYrbUsKh10d8DwbrjnM2DPvbNfi2VKL8ITR+WnnlOn2wQAAAIAmWLN/bfnBAwvh22gRf6nYfjnqK2k7fm06L3CUdBPuxhQuGPuN/LasVF18hqCtSPhFcXDw77JrxIEmxT79HRaSAZjcKhEH3CgttqgM0wYjYLo/oT9w5DEv8abNa4/EzZxcPbF8bWpXIS9zrin2GTJ7rVmxU4WFhbpOKLYKYqReSQAAAIBvOFJrOSUIVTTvPkFag27ei4YViix8v+zLC9g0ME/saDuo1PR5xDPUNBbmMmliPOoQB3bYWv9AHT//YQ7mVBHOOxNj1jqXCe7eQmR86lYUk9VFcKh5wYaCzZdxC5YgXsMRF9c7XzYiP63W6LqQ3XwO5h1E4WMlHiDH9m6zBRF8uA== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key17 b/security/nss/cmd/bltest/tests/rsa_oaep/key17
new file mode 100644
index 000000000..a2ad3ff8d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key17
@@ -0,0 +1 @@
+AAAAAQAAAAEArkXtVgHOxrjMBfgDk1xnTdvg11xMCf15UfxrDK7DE6jfOZcMUYv/ul7Wjz8NfyKkAp1BPxrgfk6+nkF3ziPn9UBLVp5O4b3PPB+wPvETgC1PhV65tRNLWnyAha3K5vovoUF+w3Y74XGwxit2Dt4jwSrZK5gIhMZB9aj6wmva1KAzgaIv4bdUiFCUyCUG1AGaU1ooav6ycbubpZLeGNz2AMKu6uVuAvfPefwUzzvcfNhP67v5UMqQMEsiGaeqBjrvosPBmA5WDNZK/neVhbYQdle5V4V+/eYBCYirfeQX/IjY84TE5ucsP5Q+DDHAxKXMNvh52KOsnX1Zhg6q2muDuwAAAAMBAAEAAAEABWsEIW/l81SsdyUKS2sMhSWoXFmwvYDFZFCiLV9DjllqMzqodeKR3UP0jLiLnV/A1Jn5/NHDl/mvwHDNnjmMjRnmHbfHQQprJnXfv100W4BNIBrdUC1c4t/LCRzpmXu+vlcwbzg+TViBA/A29+hdGTTRUqMj5KjbRR1vSlsbDxAswVDgL+7iuI3qStTBusyyTYQHLRTh0kpncfdAjuMFZPuG1Dk6NLzwt4hQHRkzA/E6IoSwAfD2Ser3kyjUrFxDCrRBSSCpRg7Rt7xA7GU+h20Jq8UJrkW1JRkBFqDCYQGEgphQnBw786SD5ydAVOFelwdQNumJ9gkygHtSV3UeeQAAAIDs9a7NHlUV//rL11ooFsbr9JAYzftGOOGF1mpzlrb4CQ+AGMf9lcw0uFfcF/DMZRa7E0arTVgsra17QQM1I4e3AzjQhAR8nZU5tkliBLPdbqRCSZIHvsAflkKH/2M2w5hGWDNoRvVuRoYYgcECM9IXa/FaXpbdx4C8hoqnfTznaQAAAIC8RsRk/GrEyng7DrCKPIQbdy9+my8our1YiuiF4aDGHkhYoPslrCmZkPNb6FFkwlm6EXXN1xknBxNRhJkrbCm3Rt0NLKvhQoNffRSMwWFSS0oJlG1IuChHPxzna2y2iGw0XAPgX0HVG1w6kKPyQHPH10pP4l2c8hx1lg8/w4YxgwAAAIDHNWRXHQD7FdCKPemVelCRXXEm6UQtrPQryC6GLlZz/2oAjtTS43RhffifF6FgtDt/2py2trdCGGCYFffUXKJjwVmqMtJy0Sf69LyMotdzeOiusZsK19o8s94K5zFJgPYrbUsKh10d8DwbrjnM2DPvbNfi2VKL8ITR+WnnlOn2wQAAAIAmWLN/bfnBAwvh22gRf6nYfjnqK2k7fm06L3CUdBPuxhQuGPuN/LasVF18hqCtSPhFcXDw77JrxIEmxT79HRaSAZjcKhEH3CgttqgM0wYjYLo/oT9w5DEv8abNa4/EzZxcPbF8bWpXIS9zrin2GTJ7rVmxU4WFhbpOKLYKYqReSQAAAIBvOFJrOSUIVTTvPkFag27ei4YViix8v+zLC9g0ME/saDuo1PR5xDPUNBbmMmliPOoQB3bYWv9AHT//YQ7mVBHOOxNj1jqXCe7eQmR86lYUk9VFcKh5wYaCzZdxC5YgXsMRF9c7XzYiP63W6LqQ3XwO5h1E4WMlHiDH9m6zBRF8uA== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key2 b/security/nss/cmd/bltest/tests/rsa_oaep/key2
new file mode 100644
index 000000000..61684becc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key2
@@ -0,0 +1 @@
+AAAAAQAAAACAqLOyhK+OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx+CwgtaTpef87Wdc9GaFEncsDLxkp0LGxjD1M8jMcvYq6DPEC/JYQumEu3i9v5fAEH1VvbZi9cTg+rmEXLUUjvc5LdOq/5OuHmtme7PUJHYW1PW6ENTP0ibeiNOfFvsAAAADAQABAAAAgFMznP23n8hGamVccxasqFxV/Y9t2Jj9rxGVF+9PUuj9jiWN+T/uGA+g5KspaTzYOxUqVT1KxNGBK4ufpa8Of1X+cwTfQVcJJvMxHxXE1lpzLEgxFu49PS0K81Sa2b98v7eK2IT4TVvrBHJNxzabMd7zfQz1OenPzdPeZTcp6tXRAAAAQNMnN+cmf/4TQbLVwNFQqBtYb7MTK+0vjVJihkqcufMK84vkSFmNQToXLvuALCGs8cEcUgwvJqRx3K0hLqx8o50AAABAzIhT0dVNpjD6wAT0cfKBx7iYLYIkpJDtvrM9Pj1cyTxHZXA9HdeRZC8fEWoN2FK+JBmyr3K/6aAw6GCwKItddwAAAEAOEr8XGOnO9VmbocOIL+gEapCHTu/OjyzMIOTydB+wozo4SK7JyTBfvsvS12gZln1GcazGQx5AN5aNs3h45pXBAAAAQJUpew+Vovpn0AcH1gnf1PwFyJ2vwu9tbqVb7HceozNzTZJR55CC7NqGbv7xPEWeGmMThrfjVMiZ9fESyoXXFYMAAABAT0VsUCSTvcDtKrdWo6btTWc1Kml9QhbpMhKxJ6Y9VBHOb6mNXb79cyY+NygUJ0OBgWbtfdY2h90qjKHS9PvY4Q== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key3 b/security/nss/cmd/bltest/tests/rsa_oaep/key3
new file mode 100644
index 000000000..61684becc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key3
@@ -0,0 +1 @@
+AAAAAQAAAACAqLOyhK+OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx+CwgtaTpef87Wdc9GaFEncsDLxkp0LGxjD1M8jMcvYq6DPEC/JYQumEu3i9v5fAEH1VvbZi9cTg+rmEXLUUjvc5LdOq/5OuHmtme7PUJHYW1PW6ENTP0ibeiNOfFvsAAAADAQABAAAAgFMznP23n8hGamVccxasqFxV/Y9t2Jj9rxGVF+9PUuj9jiWN+T/uGA+g5KspaTzYOxUqVT1KxNGBK4ufpa8Of1X+cwTfQVcJJvMxHxXE1lpzLEgxFu49PS0K81Sa2b98v7eK2IT4TVvrBHJNxzabMd7zfQz1OenPzdPeZTcp6tXRAAAAQNMnN+cmf/4TQbLVwNFQqBtYb7MTK+0vjVJihkqcufMK84vkSFmNQToXLvuALCGs8cEcUgwvJqRx3K0hLqx8o50AAABAzIhT0dVNpjD6wAT0cfKBx7iYLYIkpJDtvrM9Pj1cyTxHZXA9HdeRZC8fEWoN2FK+JBmyr3K/6aAw6GCwKItddwAAAEAOEr8XGOnO9VmbocOIL+gEapCHTu/OjyzMIOTydB+wozo4SK7JyTBfvsvS12gZln1GcazGQx5AN5aNs3h45pXBAAAAQJUpew+Vovpn0AcH1gnf1PwFyJ2vwu9tbqVb7HceozNzTZJR55CC7NqGbv7xPEWeGmMThrfjVMiZ9fESyoXXFYMAAABAT0VsUCSTvcDtKrdWo6btTWc1Kml9QhbpMhKxJ6Y9VBHOb6mNXb79cyY+NygUJ0OBgWbtfdY2h90qjKHS9PvY4Q== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key4 b/security/nss/cmd/bltest/tests/rsa_oaep/key4
new file mode 100644
index 000000000..61684becc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key4
@@ -0,0 +1 @@
+AAAAAQAAAACAqLOyhK+OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx+CwgtaTpef87Wdc9GaFEncsDLxkp0LGxjD1M8jMcvYq6DPEC/JYQumEu3i9v5fAEH1VvbZi9cTg+rmEXLUUjvc5LdOq/5OuHmtme7PUJHYW1PW6ENTP0ibeiNOfFvsAAAADAQABAAAAgFMznP23n8hGamVccxasqFxV/Y9t2Jj9rxGVF+9PUuj9jiWN+T/uGA+g5KspaTzYOxUqVT1KxNGBK4ufpa8Of1X+cwTfQVcJJvMxHxXE1lpzLEgxFu49PS0K81Sa2b98v7eK2IT4TVvrBHJNxzabMd7zfQz1OenPzdPeZTcp6tXRAAAAQNMnN+cmf/4TQbLVwNFQqBtYb7MTK+0vjVJihkqcufMK84vkSFmNQToXLvuALCGs8cEcUgwvJqRx3K0hLqx8o50AAABAzIhT0dVNpjD6wAT0cfKBx7iYLYIkpJDtvrM9Pj1cyTxHZXA9HdeRZC8fEWoN2FK+JBmyr3K/6aAw6GCwKItddwAAAEAOEr8XGOnO9VmbocOIL+gEapCHTu/OjyzMIOTydB+wozo4SK7JyTBfvsvS12gZln1GcazGQx5AN5aNs3h45pXBAAAAQJUpew+Vovpn0AcH1gnf1PwFyJ2vwu9tbqVb7HceozNzTZJR55CC7NqGbv7xPEWeGmMThrfjVMiZ9fESyoXXFYMAAABAT0VsUCSTvcDtKrdWo6btTWc1Kml9QhbpMhKxJ6Y9VBHOb6mNXb79cyY+NygUJ0OBgWbtfdY2h90qjKHS9PvY4Q== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key5 b/security/nss/cmd/bltest/tests/rsa_oaep/key5
new file mode 100644
index 000000000..61684becc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key5
@@ -0,0 +1 @@
+AAAAAQAAAACAqLOyhK+OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx+CwgtaTpef87Wdc9GaFEncsDLxkp0LGxjD1M8jMcvYq6DPEC/JYQumEu3i9v5fAEH1VvbZi9cTg+rmEXLUUjvc5LdOq/5OuHmtme7PUJHYW1PW6ENTP0ibeiNOfFvsAAAADAQABAAAAgFMznP23n8hGamVccxasqFxV/Y9t2Jj9rxGVF+9PUuj9jiWN+T/uGA+g5KspaTzYOxUqVT1KxNGBK4ufpa8Of1X+cwTfQVcJJvMxHxXE1lpzLEgxFu49PS0K81Sa2b98v7eK2IT4TVvrBHJNxzabMd7zfQz1OenPzdPeZTcp6tXRAAAAQNMnN+cmf/4TQbLVwNFQqBtYb7MTK+0vjVJihkqcufMK84vkSFmNQToXLvuALCGs8cEcUgwvJqRx3K0hLqx8o50AAABAzIhT0dVNpjD6wAT0cfKBx7iYLYIkpJDtvrM9Pj1cyTxHZXA9HdeRZC8fEWoN2FK+JBmyr3K/6aAw6GCwKItddwAAAEAOEr8XGOnO9VmbocOIL+gEapCHTu/OjyzMIOTydB+wozo4SK7JyTBfvsvS12gZln1GcazGQx5AN5aNs3h45pXBAAAAQJUpew+Vovpn0AcH1gnf1PwFyJ2vwu9tbqVb7HceozNzTZJR55CC7NqGbv7xPEWeGmMThrfjVMiZ9fESyoXXFYMAAABAT0VsUCSTvcDtKrdWo6btTWc1Kml9QhbpMhKxJ6Y9VBHOb6mNXb79cyY+NygUJ0OBgWbtfdY2h90qjKHS9PvY4Q== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key6 b/security/nss/cmd/bltest/tests/rsa_oaep/key6
new file mode 100644
index 000000000..3c9f8742f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key6
@@ -0,0 +1 @@
+AAAAAQAAAADAzyzUHjTKOnKOpcuK/2TDbSe971Nk4zb9aNMSPFoZaowocBPoU9UVbVjRUZVFIPtPbXsXq7aBd2WQnFdhGWWdkCsZBu2KKxDBVcJNEkUo2rnurjeb6sZuSkEXhty4/QBi68Aw3hIZoEwqjBt90xMeTWtsruLjGl7UGsFQmy7x7iqxg2S+VoypQcJezIT/nWQ7XsGqrhAqINc/R5t4D9bakQdSEtnqwDoGdNiZ66LkMfTES2Fba6IjK9SzO67XPWJdAAAAAwEAAQAAAMAZjBQeI3FakrzPahGaW8ETiUaNKBH1SNcn4XtKsOuYbW8hHvtTtx98y+qH7mnHXuYVAIxTMt61K/OQq9+/431yBTaBWbJjjB3jJuIdIiUfD7WEizvxUAXSp0Mw8K/pFu5izME0TR2DpwnmBnYnOED383dCSl4KTadfAbMf92gZz5y/3SFSQ8ORfAPvOBmTEuVns7967Tq0V/Nx74oUI/RbaMbiguwRG7ooM7mH/Wn62DvBuMYTxeHqFsEe0SXqfsEAAABg/I1sBL7E65qBksp5AMvlNuLotRnezzOyRZeYxpCd9PF2230jGQ/HK4hlpxiviV8bzZFFKYAnQjtgXnCkfPWDkKjD6I/IxI6LMuPaIQ374+iB6lZ0tqNIwh6T+eVepl79AAAAYNIA1F54iqzqYGpAHQRg+H3VwQJ+EtwaDXWG6JOdnPeJtA9RrARClh3n0hzCHgXIMVXB8qqRkzh8/flWy0jRU7onBAb5u7pTfUmH2eL5lC16FMv//qdP7N2pKNI+JZ9e4QAAAGDbFoAveaLw1F81jWn9M+RLgfroKGIuk6VCU+mX0BsHQ3WdoOgStKpObIvqsjKNVDGVWkGKZ/8mqMXIB6XaNU4F7zHMjPdY9GNzKVCwPiZXJvuU451qVyomJEqwjbdXUq0AAABgoKMXz+ffFCP4em3uhFH04rSmflSX8ptPHk6DC5+t2UARZwJvVZblo5yXgX4PXxbifhnsmQLgHX6m+5qjx2Cv7h44G2neasnAdYWgatnEugC/dcitL6iYpHnoCuKU/tKhAAAAYAsh8zXDUzQutEw6okRFeAwtZVuUAXTK44x8ik5kk8C6n9MDdIJnsIO5p6bLYeQts2K4yYlttwZOAq1a5hWH2hW0ZJyQWUkJ/rN9vLZUvrcmjsgB5ai0qjkRvr2IVC8Fvg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key7 b/security/nss/cmd/bltest/tests/rsa_oaep/key7
new file mode 100644
index 000000000..3c9f8742f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key7
@@ -0,0 +1 @@
+AAAAAQAAAADAzyzUHjTKOnKOpcuK/2TDbSe971Nk4zb9aNMSPFoZaowocBPoU9UVbVjRUZVFIPtPbXsXq7aBd2WQnFdhGWWdkCsZBu2KKxDBVcJNEkUo2rnurjeb6sZuSkEXhty4/QBi68Aw3hIZoEwqjBt90xMeTWtsruLjGl7UGsFQmy7x7iqxg2S+VoypQcJezIT/nWQ7XsGqrhAqINc/R5t4D9bakQdSEtnqwDoGdNiZ66LkMfTES2Fba6IjK9SzO67XPWJdAAAAAwEAAQAAAMAZjBQeI3FakrzPahGaW8ETiUaNKBH1SNcn4XtKsOuYbW8hHvtTtx98y+qH7mnHXuYVAIxTMt61K/OQq9+/431yBTaBWbJjjB3jJuIdIiUfD7WEizvxUAXSp0Mw8K/pFu5izME0TR2DpwnmBnYnOED383dCSl4KTadfAbMf92gZz5y/3SFSQ8ORfAPvOBmTEuVns7967Tq0V/Nx74oUI/RbaMbiguwRG7ooM7mH/Wn62DvBuMYTxeHqFsEe0SXqfsEAAABg/I1sBL7E65qBksp5AMvlNuLotRnezzOyRZeYxpCd9PF2230jGQ/HK4hlpxiviV8bzZFFKYAnQjtgXnCkfPWDkKjD6I/IxI6LMuPaIQ374+iB6lZ0tqNIwh6T+eVepl79AAAAYNIA1F54iqzqYGpAHQRg+H3VwQJ+EtwaDXWG6JOdnPeJtA9RrARClh3n0hzCHgXIMVXB8qqRkzh8/flWy0jRU7onBAb5u7pTfUmH2eL5lC16FMv//qdP7N2pKNI+JZ9e4QAAAGDbFoAveaLw1F81jWn9M+RLgfroKGIuk6VCU+mX0BsHQ3WdoOgStKpObIvqsjKNVDGVWkGKZ/8mqMXIB6XaNU4F7zHMjPdY9GNzKVCwPiZXJvuU451qVyomJEqwjbdXUq0AAABgoKMXz+ffFCP4em3uhFH04rSmflSX8ptPHk6DC5+t2UARZwJvVZblo5yXgX4PXxbifhnsmQLgHX6m+5qjx2Cv7h44G2neasnAdYWgatnEugC/dcitL6iYpHnoCuKU/tKhAAAAYAsh8zXDUzQutEw6okRFeAwtZVuUAXTK44x8ik5kk8C6n9MDdIJnsIO5p6bLYeQts2K4yYlttwZOAq1a5hWH2hW0ZJyQWUkJ/rN9vLZUvrcmjsgB5ai0qjkRvr2IVC8Fvg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key8 b/security/nss/cmd/bltest/tests/rsa_oaep/key8
new file mode 100644
index 000000000..3c9f8742f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key8
@@ -0,0 +1 @@
+AAAAAQAAAADAzyzUHjTKOnKOpcuK/2TDbSe971Nk4zb9aNMSPFoZaowocBPoU9UVbVjRUZVFIPtPbXsXq7aBd2WQnFdhGWWdkCsZBu2KKxDBVcJNEkUo2rnurjeb6sZuSkEXhty4/QBi68Aw3hIZoEwqjBt90xMeTWtsruLjGl7UGsFQmy7x7iqxg2S+VoypQcJezIT/nWQ7XsGqrhAqINc/R5t4D9bakQdSEtnqwDoGdNiZ66LkMfTES2Fba6IjK9SzO67XPWJdAAAAAwEAAQAAAMAZjBQeI3FakrzPahGaW8ETiUaNKBH1SNcn4XtKsOuYbW8hHvtTtx98y+qH7mnHXuYVAIxTMt61K/OQq9+/431yBTaBWbJjjB3jJuIdIiUfD7WEizvxUAXSp0Mw8K/pFu5izME0TR2DpwnmBnYnOED383dCSl4KTadfAbMf92gZz5y/3SFSQ8ORfAPvOBmTEuVns7967Tq0V/Nx74oUI/RbaMbiguwRG7ooM7mH/Wn62DvBuMYTxeHqFsEe0SXqfsEAAABg/I1sBL7E65qBksp5AMvlNuLotRnezzOyRZeYxpCd9PF2230jGQ/HK4hlpxiviV8bzZFFKYAnQjtgXnCkfPWDkKjD6I/IxI6LMuPaIQ374+iB6lZ0tqNIwh6T+eVepl79AAAAYNIA1F54iqzqYGpAHQRg+H3VwQJ+EtwaDXWG6JOdnPeJtA9RrARClh3n0hzCHgXIMVXB8qqRkzh8/flWy0jRU7onBAb5u7pTfUmH2eL5lC16FMv//qdP7N2pKNI+JZ9e4QAAAGDbFoAveaLw1F81jWn9M+RLgfroKGIuk6VCU+mX0BsHQ3WdoOgStKpObIvqsjKNVDGVWkGKZ/8mqMXIB6XaNU4F7zHMjPdY9GNzKVCwPiZXJvuU451qVyomJEqwjbdXUq0AAABgoKMXz+ffFCP4em3uhFH04rSmflSX8ptPHk6DC5+t2UARZwJvVZblo5yXgX4PXxbifhnsmQLgHX6m+5qjx2Cv7h44G2neasnAdYWgatnEugC/dcitL6iYpHnoCuKU/tKhAAAAYAsh8zXDUzQutEw6okRFeAwtZVuUAXTK44x8ik5kk8C6n9MDdIJnsIO5p6bLYeQts2K4yYlttwZOAq1a5hWH2hW0ZJyQWUkJ/rN9vLZUvrcmjsgB5ai0qjkRvr2IVC8Fvg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/key9 b/security/nss/cmd/bltest/tests/rsa_oaep/key9
new file mode 100644
index 000000000..3c9f8742f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/key9
@@ -0,0 +1 @@
+AAAAAQAAAADAzyzUHjTKOnKOpcuK/2TDbSe971Nk4zb9aNMSPFoZaowocBPoU9UVbVjRUZVFIPtPbXsXq7aBd2WQnFdhGWWdkCsZBu2KKxDBVcJNEkUo2rnurjeb6sZuSkEXhty4/QBi68Aw3hIZoEwqjBt90xMeTWtsruLjGl7UGsFQmy7x7iqxg2S+VoypQcJezIT/nWQ7XsGqrhAqINc/R5t4D9bakQdSEtnqwDoGdNiZ66LkMfTES2Fba6IjK9SzO67XPWJdAAAAAwEAAQAAAMAZjBQeI3FakrzPahGaW8ETiUaNKBH1SNcn4XtKsOuYbW8hHvtTtx98y+qH7mnHXuYVAIxTMt61K/OQq9+/431yBTaBWbJjjB3jJuIdIiUfD7WEizvxUAXSp0Mw8K/pFu5izME0TR2DpwnmBnYnOED383dCSl4KTadfAbMf92gZz5y/3SFSQ8ORfAPvOBmTEuVns7967Tq0V/Nx74oUI/RbaMbiguwRG7ooM7mH/Wn62DvBuMYTxeHqFsEe0SXqfsEAAABg/I1sBL7E65qBksp5AMvlNuLotRnezzOyRZeYxpCd9PF2230jGQ/HK4hlpxiviV8bzZFFKYAnQjtgXnCkfPWDkKjD6I/IxI6LMuPaIQ374+iB6lZ0tqNIwh6T+eVepl79AAAAYNIA1F54iqzqYGpAHQRg+H3VwQJ+EtwaDXWG6JOdnPeJtA9RrARClh3n0hzCHgXIMVXB8qqRkzh8/flWy0jRU7onBAb5u7pTfUmH2eL5lC16FMv//qdP7N2pKNI+JZ9e4QAAAGDbFoAveaLw1F81jWn9M+RLgfroKGIuk6VCU+mX0BsHQ3WdoOgStKpObIvqsjKNVDGVWkGKZ/8mqMXIB6XaNU4F7zHMjPdY9GNzKVCwPiZXJvuU451qVyomJEqwjbdXUq0AAABgoKMXz+ffFCP4em3uhFH04rSmflSX8ptPHk6DC5+t2UARZwJvVZblo5yXgX4PXxbifhnsmQLgHX6m+5qjx2Cv7h44G2neasnAdYWgatnEugC/dcitL6iYpHnoCuKU/tKhAAAAYAsh8zXDUzQutEw6okRFeAwtZVuUAXTK44x8ik5kk8C6n9MDdIJnsIO5p6bLYeQts2K4yYlttwZOAq1a5hWH2hW0ZJyQWUkJ/rN9vLZUvrcmjsgB5ai0qjkRvr2IVC8Fvg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash0 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash0
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash0
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash1 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash1
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash1
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash10 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash10
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash10
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash11 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash11
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash11
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash12 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash12
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash12
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash13 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash13
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash13
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash14 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash14
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash14
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash15 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash15
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash15
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash16 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash16
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash16
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash17 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash17
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash17
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash2 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash2
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash2
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash3 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash3
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash3
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash4 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash4
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash4
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash5 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash5
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash5
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash6 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash6
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash6
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash7 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash7
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash7
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash8 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash8
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash8
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/maskhash9 b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash9
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/maskhash9
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/numtests b/security/nss/cmd/bltest/tests/rsa_oaep/numtests
new file mode 100644
index 000000000..3c032078a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/numtests
@@ -0,0 +1 @@
+18
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext0 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext0
new file mode 100644
index 000000000..5961feea3
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext0
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext1 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext1
new file mode 100644
index 000000000..bd17cf9e9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext1
@@ -0,0 +1 @@
+u @GõGèä…e#)ŠÉºâEﯗûåoÕ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext10 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext10
new file mode 100644
index 000000000..d07c85b36
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext10
@@ -0,0 +1 @@
+SæèÇ)ÖùÃÝ1~t°ÛŽLÌ¢_<ƒtnzÆ:cï79絕«¹nUåO{Ô´37û‘ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext11 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext11
new file mode 100644
index 000000000..fcd6baa03
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext11
@@ -0,0 +1 @@
+¶²Ž¢ ¼d \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext12 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext12
new file mode 100644
index 000000000..a154e4132
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext12
@@ -0,0 +1 @@
+‹ºkø*l†Õñun—•hp°‰S°kN²¼”î \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext13 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext13
new file mode 100644
index 000000000..8af8ac61d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext13
@@ -0,0 +1 @@
+æ­;X©òEu7>W \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext14 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext14
new file mode 100644
index 000000000..b302369ad
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext14
@@ -0,0 +1,2 @@
+Q
+,ö†o¢4SÉN£Ÿ¼%cè>”EKA$ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext15 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext15
new file mode 100644
index 000000000..36812091d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext15
Binary files differ
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext16 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext16
new file mode 100644
index 000000000..7449ac677
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext16
@@ -0,0 +1 @@
+§Ýl}ÂKFùÝ_‘­¤Ã³ß”~‡r2© \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext17 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext17
new file mode 100644
index 000000000..f3945c85f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext17
@@ -0,0 +1 @@
+êñ§: F S}æœÙ"‹¼ûšŒ¨ÆÃï¯oä§ôcNÐ |9ìi"׸ê,ë¬ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext2 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext2
new file mode 100644
index 000000000..6c08a2a23
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext2
@@ -0,0 +1 @@
+ÙJàƒ.dEÎB3°mS‚±ÛKªÓtmÉß$ÔãÂEÿY¦B>°áÐ-OæFÏiýŒn—°Q \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext3 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext3
new file mode 100644
index 000000000..efd84ad70
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext3
@@ -0,0 +1 @@
+RæPÙŽ*‹O†…!S¹~Ý1o4jöz… \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext4 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext4
new file mode 100644
index 000000000..17963365b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext4
@@ -0,0 +1 @@
+¨ŸÙåùt¢ŸïûF+Ilùè \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext5 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext5
new file mode 100644
index 000000000..38913e9c7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext5
@@ -0,0 +1 @@
+&RP„Bq \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext6 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext6
new file mode 100644
index 000000000..5d4bf7cb2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext6
@@ -0,0 +1 @@
+÷5ýUº’Y,;R¸ùÄöšª¾øþˆ­Ð•YTFœôì ‰lYí¡bçTœŠ»ͼ!¡.ɶµ¸ý/9ž¶ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext7 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext7
new file mode 100644
index 000000000..d1bf80096
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext7
@@ -0,0 +1 @@
+¹`P¦:«ä-ßá—‰õ@Ltt²mÎ>Ô‚¿–Ì‹ô ÅFY \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext8 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext8
new file mode 100644
index 000000000..bb96c956f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext8
@@ -0,0 +1 @@
+ý2d)ß›‰ µK¸óO$ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/plaintext9 b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext9
new file mode 100644
index 000000000..8a71ad8e7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/plaintext9
@@ -0,0 +1,3 @@
+ñE›_ ’ðr:.VbHMŒ
+ ü)ÚÖ¬Ô;µóïýôá¶>ýþf(Ð×L¡›òÖžJ
+¿†Ò“’ZygrøŽ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed0 b/security/nss/cmd/bltest/tests/rsa_oaep/seed0
new file mode 100644
index 000000000..8b990a2f3
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed0
@@ -0,0 +1 @@
+GLd26iEGnWl3ajPpa61I4d2gpe8=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed1 b/security/nss/cmd/bltest/tests/rsa_oaep/seed1
new file mode 100644
index 000000000..afb497d5b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed1
@@ -0,0 +1 @@
+DMdCzkqbfzL5UbyyUe/ZJf5P418=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed10 b/security/nss/cmd/bltest/tests/rsa_oaep/seed10
new file mode 100644
index 000000000..762ceaf5a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed10
@@ -0,0 +1 @@
+/LxCFALp7KvGCCr6QLpfJlIshA4=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed11 b/security/nss/cmd/bltest/tests/rsa_oaep/seed11
new file mode 100644
index 000000000..5cfd292ad
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed11
@@ -0,0 +1 @@
+I6reDh4Iu5uaeNIwKlL5whsuG6I=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed12 b/security/nss/cmd/bltest/tests/rsa_oaep/seed12
new file mode 100644
index 000000000..516e13d9a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed12
@@ -0,0 +1 @@
+R+GrcRn+5WyV7l6q2G9A0KpjvTM=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed13 b/security/nss/cmd/bltest/tests/rsa_oaep/seed13
new file mode 100644
index 000000000..680ddbd4a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed13
@@ -0,0 +1 @@
+bRf1tMH/rDUdGVv3sJ0J8JpAec8=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed14 b/security/nss/cmd/bltest/tests/rsa_oaep/seed14
new file mode 100644
index 000000000..f41e51c60
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed14
@@ -0,0 +1 @@
+OFOHUU3szHx0DdjN+druSaHL/VQ=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed15 b/security/nss/cmd/bltest/tests/rsa_oaep/seed15
new file mode 100644
index 000000000..9a825c93c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed15
@@ -0,0 +1 @@
+XKymoPdkFhqWhPhdkrbg7zfKi2U=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed16 b/security/nss/cmd/bltest/tests/rsa_oaep/seed16
new file mode 100644
index 000000000..dcf464dc4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed16
@@ -0,0 +1 @@
+lbyp44WYlLPdhp+n7NW7xkAb8+Q=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed17 b/security/nss/cmd/bltest/tests/rsa_oaep/seed17
new file mode 100644
index 000000000..90133c73e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed17
@@ -0,0 +1 @@
+n0fd9C6X7qhWqb28cU6zrCL26zI=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed2 b/security/nss/cmd/bltest/tests/rsa_oaep/seed2
new file mode 100644
index 000000000..0c82aab49
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed2
@@ -0,0 +1 @@
+JRTfRpV1WmeyiOr0kFw27sZv0v0=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed3 b/security/nss/cmd/bltest/tests/rsa_oaep/seed3
new file mode 100644
index 000000000..4cd022ec9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed3
@@ -0,0 +1 @@
+xENaPhoYpotoIENikKN877hds/s=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed4 b/security/nss/cmd/bltest/tests/rsa_oaep/seed4
new file mode 100644
index 000000000..275f90802
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed4
@@ -0,0 +1 @@
+sxjELfO+D4P+qCP1p7R+1eQlo7U=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed5 b/security/nss/cmd/bltest/tests/rsa_oaep/seed5
new file mode 100644
index 000000000..3406494e6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed5
@@ -0,0 +1 @@
+5OwJgsIzbzpnf2o1YXTrDOiHq8I=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed6 b/security/nss/cmd/bltest/tests/rsa_oaep/seed6
new file mode 100644
index 000000000..c7316f9df
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed6
@@ -0,0 +1 @@
+jsll8TSj7Jkx6SocoNyBadXqcFw=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed7 b/security/nss/cmd/bltest/tests/rsa_oaep/seed7
new file mode 100644
index 000000000..a4cbd1640
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed7
@@ -0,0 +1 @@
+7LG4sl+lDNqwjlYEKGf0r1gm0Ww=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed8 b/security/nss/cmd/bltest/tests/rsa_oaep/seed8
new file mode 100644
index 000000000..d4a76a052
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed8
@@ -0,0 +1 @@
+6JuwMsbOYiy9tTvJRmAU6nf3d8A=
diff --git a/security/nss/cmd/bltest/tests/rsa_oaep/seed9 b/security/nss/cmd/bltest/tests/rsa_oaep/seed9
new file mode 100644
index 000000000..8cd39a9c6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_oaep/seed9
@@ -0,0 +1 @@
+YG87mcC5zNdx6qKeoOTIhPMYnMw=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext0 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext0
new file mode 100644
index 000000000..0ed7e8c10
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext0
@@ -0,0 +1,3 @@
+kHQwj7WY6XAbIpQ4jlL5cfqsK2ClFFrxhd9Sh7XtKIflfOf9RNyGNOQHyODkNgvCJvPsIn+dnlRj
+jo0x9QUSFd9uu5wvlXmqd1mKOPkUtbnBvYPE4vnzgqDQqjVC/+5lmEpgG8aeso3rJ9yhLILC1MP2
+bNUA8f8rmU2KTjDLszw=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext1 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext1
new file mode 100644
index 000000000..01aa061c9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext1
@@ -0,0 +1,3 @@
+Pvf0boMb+SsyJ0FCpYX/zvvcp7Mq6Q0Q+w8McpmE8E7ymp3weAd1zkNzm5eDg5DbClUF5j3pJwKN
+nSmyGcosRReDJVilXWlKbSW52rZgA8TMzZB4Ahk75RcNJhR9N7k1kCQb5RwlBV9H72J1LPviFBj6
+/pjCLE1NR3JP21Zp6EM=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext10 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext10
new file mode 100644
index 000000000..f31ec8eef
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext10
@@ -0,0 +1,4 @@
+ghAt+MuR5xeZGaBNJtM11k+8L4csRIM5QyQd6EVIECdM3z219C1CPbFSr3E19wFCDjm0lKZ8v9Gf
+kRnaIzoj2lxkObW6DSvDc+7jUHABN41KQHOFa3/iq6C17pOyf0r+x9TRIJIcg/YGdlsCwZ5Naho7
+lfpMQilRvk9SExB37xcXlynN3721aVDbrO7+eMsWZAoJnqVtJDie7xD4/ssxuj6jsifAqGaYu4nj
+6TY5Bb8id3sqOqUhtltM73bYO95M
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext11 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext11
new file mode 100644
index 000000000..2e67c0376
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext11
@@ -0,0 +1,4 @@
+p/2w0lkWXKLIjQC78QKKhn0zdpnQYRk7F6lkjhTMu6rerKrN7IFedXEpTruKEXryBfoHi0ewcSwZ
+njrQUTXFBMJLgXBRFXQIAkh5kv/VEdSvxrhUSR6z8N1SMTlUL/FcMQHuhVQ1F8ajx5QXxn4t2ap0
+HpopsG3LWTwjNrNnCuOvusfD524hVHPoZuM4yiRN4AtiYk1rlCaCLOrp+MxGCJX0ElAHP9RcWh57
+QlwgSkI6aZFZ9pA+cQs3p7sryASf
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext12 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext12
new file mode 100644
index 000000000..7f3530c21
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext12
@@ -0,0 +1,5 @@
+gsKxYAk7iqPA91IrGfhzVAZsd4R6vyqfzlQtDoTpIMWvtJ/9/azhZWDulKE2lgEUjrrXoOFRzxYz
+F5Glcn0F8h505+uBFEAgaTXXRHZaFeefAVy2bFMsh6agWWHIv610GppmVwIolDk+ciNzl5bAKndF
+XQ9VWw7AHd8lm2IH/Q/VdhTO8aVXO6r/TsAAaZUWWbhfJDAKJRYMqFItxuZyflfQGdfmNim4/l6J
+4lzBW+s6ZHV3VZKZKAubKPebBAkAC+JbvZZAi6O0PMSGGE3RyOYlU/oa9AQPYGY95/XknAQ4jiV/
+HOicldq0ijFdm2axt2KCM4dv8jhSMNBw0H4WZg==
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext13 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext13
new file mode 100644
index 000000000..2d8791535
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext13
@@ -0,0 +1,5 @@
+FK412d0GupL387iXl4rtfNS/X/C1haQL1GzhtCzScDBTu5BE1k6BPY+W2y3XAH0QEY9vj4SWCXrX
+Xh/2kjQbKJKtVaYzocVefwoK1ZoOIDpbgniuxU3YYi4oMdhxdPjK/0PubEZEU0XYSlllm/uS7NTI
+GGaGlfNHBvZoKKiZWWN/K/PjJRwkvbpNS3ZJ2gAiIYsRnITnmmUn7FuKX4YcFZlS4j7AXh5xc0b6
+7+ixaGglvSsmL7JTEGbA3gms3i5CMWkHKLXYXhFaL2uSt5wlq8m9k5n/i8+CWlLqH1bqdt0m9Duq
++hi/qSpQTL01aZ4m0dzFoohzhfPGMjLwbzJEww==
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext14 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext14
new file mode 100644
index 000000000..eaa167e35
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext14
@@ -0,0 +1,5 @@
+bj5Ne2sV0vtGATuJAKpbuzk5zywJVxeYcEICbuYsdMVM/9XX1X77v5UKD1xXT6CdP8HJ9ROwW0/1
+Ddjfft+iAQKFTDXlkhgBGacM5bCFGCqgLZ6iqpDR3wPy2q6IW6L10Fr9rJdHbwa5O1vJShqAqpEW
+xNYV8zOwmIkrJf+s4mb121paO8wQqCTtVarTW3J4NPuMB9oo/PQWpdmyIk8fi0QrNvkeRW/eotfP
+4zZyaN4DB6THTpJBWe0zOT1eBlVTHHcye4mCG97fiAFhx4zUGWtUGfesw/E+Xr8WG258ZyRxbKM7
+hcLiVkAZKsKFllHVC95+uXblHOyCi5i2VjuGuw==
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext15 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext15
new file mode 100644
index 000000000..a7bff41b9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext15
@@ -0,0 +1,5 @@
+NAR/+WxNwNyQstT/WaGjYaR1SyVdLuCvfYv4fJvJ593u3jOTTGPKHA49JiyxRe+TKh8sCpl6pqNP
+jq7nR32CzPCQlaa4rK041O7J+36retAtodEdjlTBgl5Vv1jCojI0uQK+Ek+ekDio9o+kXaty9m4J
+Rb8di6zJBExvBwmMn87FijqrEAyAUXgVXwMKEkxFDlrL2kfQ5PELgKI/gD53TQI7ABXCC5+bvnyR
+KWM41ey0ccr7AyAHtnpgvl9pUEqfAauzy0Z7Jg4rzoYL6Nlb+SwMjhSW7R5ShZOkq7bfRi3eiglo
+3/5GgxFoV6Iy9ev2yFviOHRa0POPdnpf2/SG+w==
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext16 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext16
new file mode 100644
index 000000000..79e7afb61
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext16
@@ -0,0 +1,5 @@
+fgk16hj01sHRfOgusrODbFWzhFic4Z3+dDNjrJlI0fNGt7/d/pLv14rbIfrvyJreQrEPN0AD/hIu
+Z0KaHLjL0fjZAUVkxE0SARb0mQ8abjh3TBlL0bghMoawd7BJnS57P0NKsSKJxVZoTe7XgTGTS7Pd
+ZTcjb3xvPcsJ1Ha+B3IeN+HO7Zsve0Boh71TFXMF4ci0+E1zO8Hhhv4GzFm27bj0vX/+/fT3upz7
+nVcGibWhpBCadGppCJPbN5klWgy5IV0tHNSQWQ6VLoyHhqoAESZSUkcMBB37w+7Hw8v3HCSGnRFc
+DLSpVvVtUwuAq1iaz+/GkHUd3zbo04P4PO3SzA==
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext17 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext17
new file mode 100644
index 000000000..86b2cfd3b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext17
@@ -0,0 +1,5 @@
+bTtbh/Z+plevIfdUQZd9IYD5GyxfaS3oKVVpamhnMNm5d42XB1jMsmBxwiCf+9YSW+LpbqgbZ8ub
+kwgjn9oX97K2Ts2glra5NWQKWhy0KpFVscnvemM6AsWfDW7lm4UsQ7NQKec8lA/wQQ6PEU7tRrvQ
++uFl5CviUopAHDso/YGO8yMtyp9NKg9RZuxZxCOW1sEdvBIVpW+hcWnblXU0PvNPneMqSc3DF0ki
+8inCPhjkXfk1MRnsQxnO3OehfGQIjB9vUr4pY0EAs5GdOPPR7ZTmiR5mpzuPuEn1h031lFnimMe7
+zi7ueCoZWqZv4tBzKyXllfV9PgYbH8PkBjv5jw==
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext2 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext2
new file mode 100644
index 000000000..47f992248
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext2
@@ -0,0 +1,3 @@
+ZmAm+6cb0+fPExV8wsUajkqmhK+XePkYSfNDNdFBwAFUxBl2IfliSmdbWrwi7n1bqv+q4cm6yizD
+c7PzPnjmFDw5WpGqf6ymZOtzOv0U2IJyWdmadVD6ylAe8rBOM8I6pR9LnoKC79tyjMCrCUBakWB8
+Y2mWG8gnDS1POfzmErE=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext3 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext3
new file mode 100644
index 000000000..28306f23a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext3
@@ -0,0 +1,3 @@
+Rgl5OyPp0JNi3CG7R9oLTzp2ImSaR9RkAZua6v5TNZwXjJHNWLpry3i+A0anvGN/S4c9S6s47mYf
+GZY0xUehrYRC4D2gFbE25UP3qwfAwT5CJbjejM4l1PbrhAD4H34YM7fubjNNNwlkynn9uHK011Ij
+te6wgQFZH7Uy0VWm3oc=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext4 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext4
new file mode 100644
index 000000000..a83e4f591
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext4
@@ -0,0 +1,3 @@
+HSqtIhyk0x3fE1CSOQGTmOPRSzLcNNxa9K6uo8CVr3NHnPCkXlYpY1pToBg3dhWxbLmxOz4J1nHr
+ceOHuFRcWWDaWmR3bnaOgrLJNYO/EEw/2yNRK3tOifYz3QBjpTDbRSSwHD84TAkxDjFaedzT1oQC
+Kn8xyGWmZOMWl4t1n60=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext5 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext5
new file mode 100644
index 000000000..b4a3e3c41
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext5
@@ -0,0 +1,3 @@
+KjT2El4fawv5cehPvUHGMr6PLCrOfei2km4x/5Ppr5h/vAblHpvhT1GY+R8/lTvWfaYKnfWXZMPc
+D+COHL7wt1+GjRCtP7p0n+9Z+22sRqDW5QQ2kzFYb1jkYo85qieJglQ7wO61N9xhlYAZs5T7Jz8h
+WFigoBrE1lC5VcZ/TFg=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext6 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext6
new file mode 100644
index 000000000..92a284cac
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext6
@@ -0,0 +1,4 @@
+WGEHImw84BOnyPBNGmopWbtLjiBbpDontQ8SQRG8Ne9YmwOfWTIYfLaW19mjLAw4MApc3aSDS2LS
+6yQK8z950T378JW/WZ4NloaUjBlkdHtn6JyaulzYUBYjb1ZsxYAssT6tUbx8pr7zuU3L27HVcEaX
+cd8OALGooGd3Ry0jFiee2uhkdGaNTh7/+V8d5hxgINoyrpK78WUg/vPPTYj2ESHyS72f6RtZyvEj
+WyqT/4H8QDrd9OveqEk0qc2vjhqe
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext7 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext7
new file mode 100644
index 000000000..55bed19a4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext7
@@ -0,0 +1,4 @@
+gLbWQyVSCfCkVnY4l6ye0lnUWbScKIfliC7LRDTP1m3X4WmTdTgeUc1/VU8sJxcEs5nUK0viVAoO
+ymGVH1Umf3woeMEihC2tsosBvV+MAl9+IoQYpnPAPWvAxzbQopVGvWf3htnWkszqd41x2YwgY7en
+EJIYek01rxCBEdg+g+rkbEaqNCd+BgRFiZA3iPHV587iX7SF6SlJEYgU1vLD7jYUiQFvMn+1vFF+
+tQRwv/oa+l9M6aoM5bjuGb9VAblY
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext8 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext8
new file mode 100644
index 000000000..b6a3018a3
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext8
@@ -0,0 +1,4 @@
+SEQI84mM1fU0g/gIGe+/JwjDTSeosqb66LMi+SQCN/mBgXrKGEbxCE2qbXwHlfblvxr1nDjhhYQ3
+zh9+xBm5jIc2rfbdmgCxgG0r060Kc3deBfUt/vOlmrSwgUPw3wXNGtnQS+zsptqkohKYA+IAy8d3
+h8r0wdBmOmxZh7YFlSAZeCyvLsFCbWj7lO0dS+gWp+0IG3fmqzMLP/wHOCD+zeNyf8vile5hoFCj
+Q2WGN8P9ZZz7Y3Nt4y2fkNPC9j7K
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext9 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext9
new file mode 100644
index 000000000..0da2bcba0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext9
@@ -0,0 +1,4 @@
+hOvrSBvlmEW0ZGi6+0ccARLgKyNdhLXZEcvRkm7lB0rgQkSVyyDoIwi467ZfQZoD+0DnK3iYHYiq
+0UMFNoUXLJeynIt78K5ztbImPEA9oO0vgP90UK94KOuLhvACi9KosXak0ijMzqGDlPI4sJ/3WMwA
+vAQwEVI1V0LygrVOZjqRnnCdjaJK3lUAp7mqUCJuDKUpI+bC2GDsUP9ID6V0d+grBWX0N595x3LV
+wtqAr5+/Ml7Ob8ILAJYWFL7omhg+
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash0 b/security/nss/cmd/bltest/tests/rsa_pss/hash0
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash0
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash1 b/security/nss/cmd/bltest/tests/rsa_pss/hash1
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash1
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash10 b/security/nss/cmd/bltest/tests/rsa_pss/hash10
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash10
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash11 b/security/nss/cmd/bltest/tests/rsa_pss/hash11
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash11
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash12 b/security/nss/cmd/bltest/tests/rsa_pss/hash12
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash12
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash13 b/security/nss/cmd/bltest/tests/rsa_pss/hash13
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash13
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash14 b/security/nss/cmd/bltest/tests/rsa_pss/hash14
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash14
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash15 b/security/nss/cmd/bltest/tests/rsa_pss/hash15
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash15
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash16 b/security/nss/cmd/bltest/tests/rsa_pss/hash16
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash16
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash17 b/security/nss/cmd/bltest/tests/rsa_pss/hash17
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash17
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash2 b/security/nss/cmd/bltest/tests/rsa_pss/hash2
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash2
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash3 b/security/nss/cmd/bltest/tests/rsa_pss/hash3
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash3
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash4 b/security/nss/cmd/bltest/tests/rsa_pss/hash4
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash4
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash5 b/security/nss/cmd/bltest/tests/rsa_pss/hash5
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash5
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash6 b/security/nss/cmd/bltest/tests/rsa_pss/hash6
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash6
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash7 b/security/nss/cmd/bltest/tests/rsa_pss/hash7
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash7
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash8 b/security/nss/cmd/bltest/tests/rsa_pss/hash8
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash8
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash9 b/security/nss/cmd/bltest/tests/rsa_pss/hash9
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash9
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key0 b/security/nss/cmd/bltest/tests/rsa_pss/key0
new file mode 100644
index 000000000..46154801c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key0
@@ -0,0 +1 @@
+AAAAAQAAAACApW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW/+2xYrTA8oOhKoijlN/1JqtykcuzB86r/OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm/4nRnxBazC0/DLNfKSgOE4a29kxO8i4eHyDQzoz/siSb2aITcAAAADAQABAAAAgDOlBCqQsn1PVFHKm7vQtEdxoQGviENArvmIXypLvpLolKckrDxWjI+XhTrQfAJmyMajygkp8ejxEjGIRCn8TZrlX+6JahDOcHw+1+c05Ecno5V0UBpTJoMQnCq6yrooPDG0vS9Tw+4341LO40+eUDvYDAYirXnG3O6INUfGo7MlAAAAQOfolCcgqHdRcnOjVgU+oqG8DJSqctVcboYpay38lnlIwKcsvMyn6ss1cG4Jod9VoVNb2bPMNBYLO23NPtqOZEMAAABAtp3KHPfU1+yB51uQ/MqHSrzeEj/ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ/QAAAEAo+hOThlW+H4oVnLrKWnLqGQwwCJ4ZzSdKVW82xPbhn1VLNMB3eQQnu92N0+3iRIMo84XYGzDo5Dsv/6Anhhl5AAAAQBqLOPOY+nEgSYmNf7ee4Kd2aHkSmc36Ce/A5Qessh7XQwHvW/1IvkVerrbhZ4JVgnWAqOTo4UFR0VEKgqPy5ykAAABAJxVqukEm0kqB86Uoy/sn9WiG+ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key1 b/security/nss/cmd/bltest/tests/rsa_pss/key1
new file mode 100644
index 000000000..46154801c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key1
@@ -0,0 +1 @@
+AAAAAQAAAACApW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW/+2xYrTA8oOhKoijlN/1JqtykcuzB86r/OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm/4nRnxBazC0/DLNfKSgOE4a29kxO8i4eHyDQzoz/siSb2aITcAAAADAQABAAAAgDOlBCqQsn1PVFHKm7vQtEdxoQGviENArvmIXypLvpLolKckrDxWjI+XhTrQfAJmyMajygkp8ejxEjGIRCn8TZrlX+6JahDOcHw+1+c05Ecno5V0UBpTJoMQnCq6yrooPDG0vS9Tw+4341LO40+eUDvYDAYirXnG3O6INUfGo7MlAAAAQOfolCcgqHdRcnOjVgU+oqG8DJSqctVcboYpay38lnlIwKcsvMyn6ss1cG4Jod9VoVNb2bPMNBYLO23NPtqOZEMAAABAtp3KHPfU1+yB51uQ/MqHSrzeEj/ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ/QAAAEAo+hOThlW+H4oVnLrKWnLqGQwwCJ4ZzSdKVW82xPbhn1VLNMB3eQQnu92N0+3iRIMo84XYGzDo5Dsv/6Anhhl5AAAAQBqLOPOY+nEgSYmNf7ee4Kd2aHkSmc36Ce/A5Qessh7XQwHvW/1IvkVerrbhZ4JVgnWAqOTo4UFR0VEKgqPy5ykAAABAJxVqukEm0kqB86Uoy/sn9WiG+ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key10 b/security/nss/cmd/bltest/tests/rsa_pss/key10
new file mode 100644
index 000000000..ef62249f1
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key10
@@ -0,0 +1 @@
+AAAAAQAAAADA5r1pKslmRXkEA/3Q9b64ub+S7RAAf8NlBGQZ3QbAXFtbL0js+YnkziaRCZecu0C0oK0k0iSD0e4xWtTMsVNCaDUmkcUk9t2ObCnSJM8kaXOuyGxb9rFAGoUNG5rRu4y87Eewbw+Mf0XT/I8xkpnFQz3bwrMFO0fe0uzUpMrv1hSDPci7Yi8xftB2uAV/6N4/hEgK1eg+SmGQSk8kj7OXAnNX4dMORjE5gVxv1P1axbgXKkUjDstjGKBPFFXYTlqLAAAAAwEAAQAAAMBqf9hPuF+tBzs0QG23T41hpqvBIZapYd15Vl6dpuUYe84tmAJQ9zWVdTWScNkVkLsOQnxxRgtV1RQQsZG88wn+oTGpLI5wJzj6cZ8eAEH1LkDpHyKfTZah5vFy4VWWtFEKba7CYQXyvrxTMWuHvfITEWZgcOjf7mnVLHGpdsqueccraNKFgNxobZ9RKdIl+Cs9YVUTqIKz25FBa0jOCIiCE+N+65r4ANgcqzKM5CBomQPADHtf0xt1UDptQZaE1ikAAABg+OuX6Y3xJmTu/bdhWWpp3c0Odtrs5u1L9aG1CsCG95KKTS+HJqd+UVt02kGYjyILHMh6ofyBDOmagvLRzoIe3O15TGlB9Cx6GguMTSjHXsYLZSJ59hVKdirtFl1H3uNnAAAAYO1NcdCm4kuTwuX2tLvgX1+wr6BC0gT+M3jTZcLyiLao2tfv5F0VPu9Aysx7gf+TQALRCJlLlKXkcozZyWM3WuSZZb2lXL8O/tjWVTtAJ/LYYgim5rSJwXYSgJLWKeSdPQAAAGArtovd+wxPVshVi/+viS2AQwN4Qef6gc+mGjjF45uQHI7nESKl2iInvWze60gUUsEq09YdXk93agq1Vlkb7+Plnlp/3bg0Xh8vNbn0zuV8MkFMCGrsmT6TU+SA2e7GKJ8AAABgT/iXcJ+tB5dGSUV45w/YVGEw7qtWJ8SbCA8F7krZ8+S3y6nWpd/xE6QcNAkzaDPxkIFtimvELpvsVrdWfQ88nGltthmyRdkB3YVtt8gJLnfpoczNVu5NukLF/bYa7CZpAAAAYHe50RN7UEBKmCcpMW76/H3+ZtNOWhgmANXzCgqFEgUcVg0IHU0KGDXsPSWmD05NaqlIsr89u1sSTLvDSJJVo6lINy9peElnRflD4dtPGDgs6qUF38ZXV7s/hXpY3OUhVg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key11 b/security/nss/cmd/bltest/tests/rsa_pss/key11
new file mode 100644
index 000000000..ef62249f1
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key11
@@ -0,0 +1 @@
+AAAAAQAAAADA5r1pKslmRXkEA/3Q9b64ub+S7RAAf8NlBGQZ3QbAXFtbL0js+YnkziaRCZecu0C0oK0k0iSD0e4xWtTMsVNCaDUmkcUk9t2ObCnSJM8kaXOuyGxb9rFAGoUNG5rRu4y87Eewbw+Mf0XT/I8xkpnFQz3bwrMFO0fe0uzUpMrv1hSDPci7Yi8xftB2uAV/6N4/hEgK1eg+SmGQSk8kj7OXAnNX4dMORjE5gVxv1P1axbgXKkUjDstjGKBPFFXYTlqLAAAAAwEAAQAAAMBqf9hPuF+tBzs0QG23T41hpqvBIZapYd15Vl6dpuUYe84tmAJQ9zWVdTWScNkVkLsOQnxxRgtV1RQQsZG88wn+oTGpLI5wJzj6cZ8eAEH1LkDpHyKfTZah5vFy4VWWtFEKba7CYQXyvrxTMWuHvfITEWZgcOjf7mnVLHGpdsqueccraNKFgNxobZ9RKdIl+Cs9YVUTqIKz25FBa0jOCIiCE+N+65r4ANgcqzKM5CBomQPADHtf0xt1UDptQZaE1ikAAABg+OuX6Y3xJmTu/bdhWWpp3c0Odtrs5u1L9aG1CsCG95KKTS+HJqd+UVt02kGYjyILHMh6ofyBDOmagvLRzoIe3O15TGlB9Cx6GguMTSjHXsYLZSJ59hVKdirtFl1H3uNnAAAAYO1NcdCm4kuTwuX2tLvgX1+wr6BC0gT+M3jTZcLyiLao2tfv5F0VPu9Aysx7gf+TQALRCJlLlKXkcozZyWM3WuSZZb2lXL8O/tjWVTtAJ/LYYgim5rSJwXYSgJLWKeSdPQAAAGArtovd+wxPVshVi/+viS2AQwN4Qef6gc+mGjjF45uQHI7nESKl2iInvWze60gUUsEq09YdXk93agq1Vlkb7+Plnlp/3bg0Xh8vNbn0zuV8MkFMCGrsmT6TU+SA2e7GKJ8AAABgT/iXcJ+tB5dGSUV45w/YVGEw7qtWJ8SbCA8F7krZ8+S3y6nWpd/xE6QcNAkzaDPxkIFtimvELpvsVrdWfQ88nGltthmyRdkB3YVtt8gJLnfpoczNVu5NukLF/bYa7CZpAAAAYHe50RN7UEBKmCcpMW76/H3+ZtNOWhgmANXzCgqFEgUcVg0IHU0KGDXsPSWmD05NaqlIsr89u1sSTLvDSJJVo6lINy9peElnRflD4dtPGDgs6qUF38ZXV7s/hXpY3OUhVg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key12 b/security/nss/cmd/bltest/tests/rsa_pss/key12
new file mode 100644
index 000000000..9f74b3113
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key12
@@ -0,0 +1 @@
+AAAAAQAAAAEApd2GesTLAvkLlFfUjBSncO+ZHFbDnA7GX9Ea+ok3zqV7m+esc7RcABdhW4LWIuMYdTtgJ8D9FXvhL4CQ/uKnrc0O73WfiLpJl8ekLVjJqhLLma4AH+UhwTu1QxRFqNWuT15MfpSKwifTYEBx8g5XfpBfvrFd+vBtHeWuYlPWOmohILMaXaXavJVQYA4g8n03OeJieSX+o8xQnyHf8E5u6kVJxUDWgJ/5MH7t6R//WHM9g4WiN9bTcFoz45GQCZIHDfet8TV89+NwDONmfeg/F7jfF3jbOB3OCctK0FilEQAac4GY7ifPVaE7dUU5kGWC7IsXS9WNXR89dnxhNyGuBQAAAAMBAAEAAAEALS/1Z7P+dOBhkbf97W3hEikMZwaSQw1ZaRhAR9ojTJaT3u0Wc+1ClTnJadNywE1rR+D1uM7ghD5cIoNdvTsFoJl5hK5gWLEbxJB8v2fthPqa4lLfsNDNSeYY4139/lm8o93WbDPOu8d61EGqaV4T4yS1GPAcYPWoXJlK0XnyprX76TQCsRdnvgG/BzRE1rod0rylvQdNSl+uNTGtEwPYSzDYlzGMu7oE4DwuZt5tkfgvluodS7VKWq4QLVlGV/XJeJVTUSspbeop2AIxljV+PjpulY8548I0QDjqYEsx7cbw9/9ucYGlfJKCaiaPhnaOlvh4Vi/HHYXWnkSGEvcEjwAAAIDP1QKD/u65f28I1zy8ezg2+Cu81JlHn15vdv38uLOMT3Hcnoi9am92Nxr9ZdKvGGKzKvs0qV9xuLEyBD/+vjqVK691kkSBSMA/nGmx1o5M5c8yyGuvRv7TAcoatAMGmzL0VrkfcYmKsIHNjEJS71JxkVyXlLjylYUdp1EPmctz6wAAAIDMTpDSobOgZdOy0fWo/OMbVER1Zk6rVh0pcbmft774ROjsHzYLjCrINZaSlx6mo49yP8whH128sXeg/axRZKHU/3+7ToKZhjU8uYNlmhSM3UIMfTG6OCLqkKMr5GwDDowX4foK03hZ4GsKpvo7IW2cvmwOIjOXacCmFZE+XacZzwAAAIAcLR/DL2vEAE/YXf3g+7+aTDj5x8TkHeoaqII0ogHNkvO32lJlg6mK2FuzYPuYO3EeI0SdVh0XeNelFUhry/R7Rsnp4aOh93AA776wmor+R+W4V82pnLFtf/+bcS471gypbZx5c9YW1Gk0qcBQKBwAQ5nO/x233aeHZqipucsIcwAAAIDLOzwEyqWMYL59my3rs+OWQ/T1c5e+CCNqHp6vqnBlNuccOs/gHMZR8jyeBYWP7hO7aor8R99O3JpLowvOy3PQFXhSMn7niQFcLo3ue58FoPMayU62FzFkdAxclRR81fO1riy0qDeH8B2Ksx8nwtDuot2KEauQarogfEPG7hJTMQAAAIAS9rLPE3SnNvrQVhYFD5arS2HRF3x/nVJaKfPRgOd2Z+mdmavwUl0HWGYPN1JlWw8luN+EMdmo/3fBbBKgpRIqnwv3z9WiZqNcFZ+ZEgi5Axb/RE8+C2vQ6TuKeiRI6Vfj3abPzyJmsQYBOsRoCNOziHs7ADRLqslTC0znCPwytg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key13 b/security/nss/cmd/bltest/tests/rsa_pss/key13
new file mode 100644
index 000000000..9f74b3113
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key13
@@ -0,0 +1 @@
+AAAAAQAAAAEApd2GesTLAvkLlFfUjBSncO+ZHFbDnA7GX9Ea+ok3zqV7m+esc7RcABdhW4LWIuMYdTtgJ8D9FXvhL4CQ/uKnrc0O73WfiLpJl8ekLVjJqhLLma4AH+UhwTu1QxRFqNWuT15MfpSKwifTYEBx8g5XfpBfvrFd+vBtHeWuYlPWOmohILMaXaXavJVQYA4g8n03OeJieSX+o8xQnyHf8E5u6kVJxUDWgJ/5MH7t6R//WHM9g4WiN9bTcFoz45GQCZIHDfet8TV89+NwDONmfeg/F7jfF3jbOB3OCctK0FilEQAac4GY7ifPVaE7dUU5kGWC7IsXS9WNXR89dnxhNyGuBQAAAAMBAAEAAAEALS/1Z7P+dOBhkbf97W3hEikMZwaSQw1ZaRhAR9ojTJaT3u0Wc+1ClTnJadNywE1rR+D1uM7ghD5cIoNdvTsFoJl5hK5gWLEbxJB8v2fthPqa4lLfsNDNSeYY4139/lm8o93WbDPOu8d61EGqaV4T4yS1GPAcYPWoXJlK0XnyprX76TQCsRdnvgG/BzRE1rod0rylvQdNSl+uNTGtEwPYSzDYlzGMu7oE4DwuZt5tkfgvluodS7VKWq4QLVlGV/XJeJVTUSspbeop2AIxljV+PjpulY8548I0QDjqYEsx7cbw9/9ucYGlfJKCaiaPhnaOlvh4Vi/HHYXWnkSGEvcEjwAAAIDP1QKD/u65f28I1zy8ezg2+Cu81JlHn15vdv38uLOMT3Hcnoi9am92Nxr9ZdKvGGKzKvs0qV9xuLEyBD/+vjqVK691kkSBSMA/nGmx1o5M5c8yyGuvRv7TAcoatAMGmzL0VrkfcYmKsIHNjEJS71JxkVyXlLjylYUdp1EPmctz6wAAAIDMTpDSobOgZdOy0fWo/OMbVER1Zk6rVh0pcbmft774ROjsHzYLjCrINZaSlx6mo49yP8whH128sXeg/axRZKHU/3+7ToKZhjU8uYNlmhSM3UIMfTG6OCLqkKMr5GwDDowX4foK03hZ4GsKpvo7IW2cvmwOIjOXacCmFZE+XacZzwAAAIAcLR/DL2vEAE/YXf3g+7+aTDj5x8TkHeoaqII0ogHNkvO32lJlg6mK2FuzYPuYO3EeI0SdVh0XeNelFUhry/R7Rsnp4aOh93AA776wmor+R+W4V82pnLFtf/+bcS471gypbZx5c9YW1Gk0qcBQKBwAQ5nO/x233aeHZqipucsIcwAAAIDLOzwEyqWMYL59my3rs+OWQ/T1c5e+CCNqHp6vqnBlNuccOs/gHMZR8jyeBYWP7hO7aor8R99O3JpLowvOy3PQFXhSMn7niQFcLo3ue58FoPMayU62FzFkdAxclRR81fO1riy0qDeH8B2Ksx8nwtDuot2KEauQarogfEPG7hJTMQAAAIAS9rLPE3SnNvrQVhYFD5arS2HRF3x/nVJaKfPRgOd2Z+mdmavwUl0HWGYPN1JlWw8luN+EMdmo/3fBbBKgpRIqnwv3z9WiZqNcFZ+ZEgi5Axb/RE8+C2vQ6TuKeiRI6Vfj3abPzyJmsQYBOsRoCNOziHs7ADRLqslTC0znCPwytg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key14 b/security/nss/cmd/bltest/tests/rsa_pss/key14
new file mode 100644
index 000000000..9f74b3113
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key14
@@ -0,0 +1 @@
+AAAAAQAAAAEApd2GesTLAvkLlFfUjBSncO+ZHFbDnA7GX9Ea+ok3zqV7m+esc7RcABdhW4LWIuMYdTtgJ8D9FXvhL4CQ/uKnrc0O73WfiLpJl8ekLVjJqhLLma4AH+UhwTu1QxRFqNWuT15MfpSKwifTYEBx8g5XfpBfvrFd+vBtHeWuYlPWOmohILMaXaXavJVQYA4g8n03OeJieSX+o8xQnyHf8E5u6kVJxUDWgJ/5MH7t6R//WHM9g4WiN9bTcFoz45GQCZIHDfet8TV89+NwDONmfeg/F7jfF3jbOB3OCctK0FilEQAac4GY7ifPVaE7dUU5kGWC7IsXS9WNXR89dnxhNyGuBQAAAAMBAAEAAAEALS/1Z7P+dOBhkbf97W3hEikMZwaSQw1ZaRhAR9ojTJaT3u0Wc+1ClTnJadNywE1rR+D1uM7ghD5cIoNdvTsFoJl5hK5gWLEbxJB8v2fthPqa4lLfsNDNSeYY4139/lm8o93WbDPOu8d61EGqaV4T4yS1GPAcYPWoXJlK0XnyprX76TQCsRdnvgG/BzRE1rod0rylvQdNSl+uNTGtEwPYSzDYlzGMu7oE4DwuZt5tkfgvluodS7VKWq4QLVlGV/XJeJVTUSspbeop2AIxljV+PjpulY8548I0QDjqYEsx7cbw9/9ucYGlfJKCaiaPhnaOlvh4Vi/HHYXWnkSGEvcEjwAAAIDP1QKD/u65f28I1zy8ezg2+Cu81JlHn15vdv38uLOMT3Hcnoi9am92Nxr9ZdKvGGKzKvs0qV9xuLEyBD/+vjqVK691kkSBSMA/nGmx1o5M5c8yyGuvRv7TAcoatAMGmzL0VrkfcYmKsIHNjEJS71JxkVyXlLjylYUdp1EPmctz6wAAAIDMTpDSobOgZdOy0fWo/OMbVER1Zk6rVh0pcbmft774ROjsHzYLjCrINZaSlx6mo49yP8whH128sXeg/axRZKHU/3+7ToKZhjU8uYNlmhSM3UIMfTG6OCLqkKMr5GwDDowX4foK03hZ4GsKpvo7IW2cvmwOIjOXacCmFZE+XacZzwAAAIAcLR/DL2vEAE/YXf3g+7+aTDj5x8TkHeoaqII0ogHNkvO32lJlg6mK2FuzYPuYO3EeI0SdVh0XeNelFUhry/R7Rsnp4aOh93AA776wmor+R+W4V82pnLFtf/+bcS471gypbZx5c9YW1Gk0qcBQKBwAQ5nO/x233aeHZqipucsIcwAAAIDLOzwEyqWMYL59my3rs+OWQ/T1c5e+CCNqHp6vqnBlNuccOs/gHMZR8jyeBYWP7hO7aor8R99O3JpLowvOy3PQFXhSMn7niQFcLo3ue58FoPMayU62FzFkdAxclRR81fO1riy0qDeH8B2Ksx8nwtDuot2KEauQarogfEPG7hJTMQAAAIAS9rLPE3SnNvrQVhYFD5arS2HRF3x/nVJaKfPRgOd2Z+mdmavwUl0HWGYPN1JlWw8luN+EMdmo/3fBbBKgpRIqnwv3z9WiZqNcFZ+ZEgi5Axb/RE8+C2vQ6TuKeiRI6Vfj3abPzyJmsQYBOsRoCNOziHs7ADRLqslTC0znCPwytg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key15 b/security/nss/cmd/bltest/tests/rsa_pss/key15
new file mode 100644
index 000000000..9f74b3113
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key15
@@ -0,0 +1 @@
+AAAAAQAAAAEApd2GesTLAvkLlFfUjBSncO+ZHFbDnA7GX9Ea+ok3zqV7m+esc7RcABdhW4LWIuMYdTtgJ8D9FXvhL4CQ/uKnrc0O73WfiLpJl8ekLVjJqhLLma4AH+UhwTu1QxRFqNWuT15MfpSKwifTYEBx8g5XfpBfvrFd+vBtHeWuYlPWOmohILMaXaXavJVQYA4g8n03OeJieSX+o8xQnyHf8E5u6kVJxUDWgJ/5MH7t6R//WHM9g4WiN9bTcFoz45GQCZIHDfet8TV89+NwDONmfeg/F7jfF3jbOB3OCctK0FilEQAac4GY7ifPVaE7dUU5kGWC7IsXS9WNXR89dnxhNyGuBQAAAAMBAAEAAAEALS/1Z7P+dOBhkbf97W3hEikMZwaSQw1ZaRhAR9ojTJaT3u0Wc+1ClTnJadNywE1rR+D1uM7ghD5cIoNdvTsFoJl5hK5gWLEbxJB8v2fthPqa4lLfsNDNSeYY4139/lm8o93WbDPOu8d61EGqaV4T4yS1GPAcYPWoXJlK0XnyprX76TQCsRdnvgG/BzRE1rod0rylvQdNSl+uNTGtEwPYSzDYlzGMu7oE4DwuZt5tkfgvluodS7VKWq4QLVlGV/XJeJVTUSspbeop2AIxljV+PjpulY8548I0QDjqYEsx7cbw9/9ucYGlfJKCaiaPhnaOlvh4Vi/HHYXWnkSGEvcEjwAAAIDP1QKD/u65f28I1zy8ezg2+Cu81JlHn15vdv38uLOMT3Hcnoi9am92Nxr9ZdKvGGKzKvs0qV9xuLEyBD/+vjqVK691kkSBSMA/nGmx1o5M5c8yyGuvRv7TAcoatAMGmzL0VrkfcYmKsIHNjEJS71JxkVyXlLjylYUdp1EPmctz6wAAAIDMTpDSobOgZdOy0fWo/OMbVER1Zk6rVh0pcbmft774ROjsHzYLjCrINZaSlx6mo49yP8whH128sXeg/axRZKHU/3+7ToKZhjU8uYNlmhSM3UIMfTG6OCLqkKMr5GwDDowX4foK03hZ4GsKpvo7IW2cvmwOIjOXacCmFZE+XacZzwAAAIAcLR/DL2vEAE/YXf3g+7+aTDj5x8TkHeoaqII0ogHNkvO32lJlg6mK2FuzYPuYO3EeI0SdVh0XeNelFUhry/R7Rsnp4aOh93AA776wmor+R+W4V82pnLFtf/+bcS471gypbZx5c9YW1Gk0qcBQKBwAQ5nO/x233aeHZqipucsIcwAAAIDLOzwEyqWMYL59my3rs+OWQ/T1c5e+CCNqHp6vqnBlNuccOs/gHMZR8jyeBYWP7hO7aor8R99O3JpLowvOy3PQFXhSMn7niQFcLo3ue58FoPMayU62FzFkdAxclRR81fO1riy0qDeH8B2Ksx8nwtDuot2KEauQarogfEPG7hJTMQAAAIAS9rLPE3SnNvrQVhYFD5arS2HRF3x/nVJaKfPRgOd2Z+mdmavwUl0HWGYPN1JlWw8luN+EMdmo/3fBbBKgpRIqnwv3z9WiZqNcFZ+ZEgi5Axb/RE8+C2vQ6TuKeiRI6Vfj3abPzyJmsQYBOsRoCNOziHs7ADRLqslTC0znCPwytg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key16 b/security/nss/cmd/bltest/tests/rsa_pss/key16
new file mode 100644
index 000000000..9f74b3113
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key16
@@ -0,0 +1 @@
+AAAAAQAAAAEApd2GesTLAvkLlFfUjBSncO+ZHFbDnA7GX9Ea+ok3zqV7m+esc7RcABdhW4LWIuMYdTtgJ8D9FXvhL4CQ/uKnrc0O73WfiLpJl8ekLVjJqhLLma4AH+UhwTu1QxRFqNWuT15MfpSKwifTYEBx8g5XfpBfvrFd+vBtHeWuYlPWOmohILMaXaXavJVQYA4g8n03OeJieSX+o8xQnyHf8E5u6kVJxUDWgJ/5MH7t6R//WHM9g4WiN9bTcFoz45GQCZIHDfet8TV89+NwDONmfeg/F7jfF3jbOB3OCctK0FilEQAac4GY7ifPVaE7dUU5kGWC7IsXS9WNXR89dnxhNyGuBQAAAAMBAAEAAAEALS/1Z7P+dOBhkbf97W3hEikMZwaSQw1ZaRhAR9ojTJaT3u0Wc+1ClTnJadNywE1rR+D1uM7ghD5cIoNdvTsFoJl5hK5gWLEbxJB8v2fthPqa4lLfsNDNSeYY4139/lm8o93WbDPOu8d61EGqaV4T4yS1GPAcYPWoXJlK0XnyprX76TQCsRdnvgG/BzRE1rod0rylvQdNSl+uNTGtEwPYSzDYlzGMu7oE4DwuZt5tkfgvluodS7VKWq4QLVlGV/XJeJVTUSspbeop2AIxljV+PjpulY8548I0QDjqYEsx7cbw9/9ucYGlfJKCaiaPhnaOlvh4Vi/HHYXWnkSGEvcEjwAAAIDP1QKD/u65f28I1zy8ezg2+Cu81JlHn15vdv38uLOMT3Hcnoi9am92Nxr9ZdKvGGKzKvs0qV9xuLEyBD/+vjqVK691kkSBSMA/nGmx1o5M5c8yyGuvRv7TAcoatAMGmzL0VrkfcYmKsIHNjEJS71JxkVyXlLjylYUdp1EPmctz6wAAAIDMTpDSobOgZdOy0fWo/OMbVER1Zk6rVh0pcbmft774ROjsHzYLjCrINZaSlx6mo49yP8whH128sXeg/axRZKHU/3+7ToKZhjU8uYNlmhSM3UIMfTG6OCLqkKMr5GwDDowX4foK03hZ4GsKpvo7IW2cvmwOIjOXacCmFZE+XacZzwAAAIAcLR/DL2vEAE/YXf3g+7+aTDj5x8TkHeoaqII0ogHNkvO32lJlg6mK2FuzYPuYO3EeI0SdVh0XeNelFUhry/R7Rsnp4aOh93AA776wmor+R+W4V82pnLFtf/+bcS471gypbZx5c9YW1Gk0qcBQKBwAQ5nO/x233aeHZqipucsIcwAAAIDLOzwEyqWMYL59my3rs+OWQ/T1c5e+CCNqHp6vqnBlNuccOs/gHMZR8jyeBYWP7hO7aor8R99O3JpLowvOy3PQFXhSMn7niQFcLo3ue58FoPMayU62FzFkdAxclRR81fO1riy0qDeH8B2Ksx8nwtDuot2KEauQarogfEPG7hJTMQAAAIAS9rLPE3SnNvrQVhYFD5arS2HRF3x/nVJaKfPRgOd2Z+mdmavwUl0HWGYPN1JlWw8luN+EMdmo/3fBbBKgpRIqnwv3z9WiZqNcFZ+ZEgi5Axb/RE8+C2vQ6TuKeiRI6Vfj3abPzyJmsQYBOsRoCNOziHs7ADRLqslTC0znCPwytg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key17 b/security/nss/cmd/bltest/tests/rsa_pss/key17
new file mode 100644
index 000000000..9f74b3113
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key17
@@ -0,0 +1 @@
+AAAAAQAAAAEApd2GesTLAvkLlFfUjBSncO+ZHFbDnA7GX9Ea+ok3zqV7m+esc7RcABdhW4LWIuMYdTtgJ8D9FXvhL4CQ/uKnrc0O73WfiLpJl8ekLVjJqhLLma4AH+UhwTu1QxRFqNWuT15MfpSKwifTYEBx8g5XfpBfvrFd+vBtHeWuYlPWOmohILMaXaXavJVQYA4g8n03OeJieSX+o8xQnyHf8E5u6kVJxUDWgJ/5MH7t6R//WHM9g4WiN9bTcFoz45GQCZIHDfet8TV89+NwDONmfeg/F7jfF3jbOB3OCctK0FilEQAac4GY7ifPVaE7dUU5kGWC7IsXS9WNXR89dnxhNyGuBQAAAAMBAAEAAAEALS/1Z7P+dOBhkbf97W3hEikMZwaSQw1ZaRhAR9ojTJaT3u0Wc+1ClTnJadNywE1rR+D1uM7ghD5cIoNdvTsFoJl5hK5gWLEbxJB8v2fthPqa4lLfsNDNSeYY4139/lm8o93WbDPOu8d61EGqaV4T4yS1GPAcYPWoXJlK0XnyprX76TQCsRdnvgG/BzRE1rod0rylvQdNSl+uNTGtEwPYSzDYlzGMu7oE4DwuZt5tkfgvluodS7VKWq4QLVlGV/XJeJVTUSspbeop2AIxljV+PjpulY8548I0QDjqYEsx7cbw9/9ucYGlfJKCaiaPhnaOlvh4Vi/HHYXWnkSGEvcEjwAAAIDP1QKD/u65f28I1zy8ezg2+Cu81JlHn15vdv38uLOMT3Hcnoi9am92Nxr9ZdKvGGKzKvs0qV9xuLEyBD/+vjqVK691kkSBSMA/nGmx1o5M5c8yyGuvRv7TAcoatAMGmzL0VrkfcYmKsIHNjEJS71JxkVyXlLjylYUdp1EPmctz6wAAAIDMTpDSobOgZdOy0fWo/OMbVER1Zk6rVh0pcbmft774ROjsHzYLjCrINZaSlx6mo49yP8whH128sXeg/axRZKHU/3+7ToKZhjU8uYNlmhSM3UIMfTG6OCLqkKMr5GwDDowX4foK03hZ4GsKpvo7IW2cvmwOIjOXacCmFZE+XacZzwAAAIAcLR/DL2vEAE/YXf3g+7+aTDj5x8TkHeoaqII0ogHNkvO32lJlg6mK2FuzYPuYO3EeI0SdVh0XeNelFUhry/R7Rsnp4aOh93AA776wmor+R+W4V82pnLFtf/+bcS471gypbZx5c9YW1Gk0qcBQKBwAQ5nO/x233aeHZqipucsIcwAAAIDLOzwEyqWMYL59my3rs+OWQ/T1c5e+CCNqHp6vqnBlNuccOs/gHMZR8jyeBYWP7hO7aor8R99O3JpLowvOy3PQFXhSMn7niQFcLo3ue58FoPMayU62FzFkdAxclRR81fO1riy0qDeH8B2Ksx8nwtDuot2KEauQarogfEPG7hJTMQAAAIAS9rLPE3SnNvrQVhYFD5arS2HRF3x/nVJaKfPRgOd2Z+mdmavwUl0HWGYPN1JlWw8luN+EMdmo/3fBbBKgpRIqnwv3z9WiZqNcFZ+ZEgi5Axb/RE8+C2vQ6TuKeiRI6Vfj3abPzyJmsQYBOsRoCNOziHs7ADRLqslTC0znCPwytg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key2 b/security/nss/cmd/bltest/tests/rsa_pss/key2
new file mode 100644
index 000000000..46154801c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key2
@@ -0,0 +1 @@
+AAAAAQAAAACApW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW/+2xYrTA8oOhKoijlN/1JqtykcuzB86r/OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm/4nRnxBazC0/DLNfKSgOE4a29kxO8i4eHyDQzoz/siSb2aITcAAAADAQABAAAAgDOlBCqQsn1PVFHKm7vQtEdxoQGviENArvmIXypLvpLolKckrDxWjI+XhTrQfAJmyMajygkp8ejxEjGIRCn8TZrlX+6JahDOcHw+1+c05Ecno5V0UBpTJoMQnCq6yrooPDG0vS9Tw+4341LO40+eUDvYDAYirXnG3O6INUfGo7MlAAAAQOfolCcgqHdRcnOjVgU+oqG8DJSqctVcboYpay38lnlIwKcsvMyn6ss1cG4Jod9VoVNb2bPMNBYLO23NPtqOZEMAAABAtp3KHPfU1+yB51uQ/MqHSrzeEj/ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ/QAAAEAo+hOThlW+H4oVnLrKWnLqGQwwCJ4ZzSdKVW82xPbhn1VLNMB3eQQnu92N0+3iRIMo84XYGzDo5Dsv/6Anhhl5AAAAQBqLOPOY+nEgSYmNf7ee4Kd2aHkSmc36Ce/A5Qessh7XQwHvW/1IvkVerrbhZ4JVgnWAqOTo4UFR0VEKgqPy5ykAAABAJxVqukEm0kqB86Uoy/sn9WiG+ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key3 b/security/nss/cmd/bltest/tests/rsa_pss/key3
new file mode 100644
index 000000000..46154801c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key3
@@ -0,0 +1 @@
+AAAAAQAAAACApW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW/+2xYrTA8oOhKoijlN/1JqtykcuzB86r/OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm/4nRnxBazC0/DLNfKSgOE4a29kxO8i4eHyDQzoz/siSb2aITcAAAADAQABAAAAgDOlBCqQsn1PVFHKm7vQtEdxoQGviENArvmIXypLvpLolKckrDxWjI+XhTrQfAJmyMajygkp8ejxEjGIRCn8TZrlX+6JahDOcHw+1+c05Ecno5V0UBpTJoMQnCq6yrooPDG0vS9Tw+4341LO40+eUDvYDAYirXnG3O6INUfGo7MlAAAAQOfolCcgqHdRcnOjVgU+oqG8DJSqctVcboYpay38lnlIwKcsvMyn6ss1cG4Jod9VoVNb2bPMNBYLO23NPtqOZEMAAABAtp3KHPfU1+yB51uQ/MqHSrzeEj/ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ/QAAAEAo+hOThlW+H4oVnLrKWnLqGQwwCJ4ZzSdKVW82xPbhn1VLNMB3eQQnu92N0+3iRIMo84XYGzDo5Dsv/6Anhhl5AAAAQBqLOPOY+nEgSYmNf7ee4Kd2aHkSmc36Ce/A5Qessh7XQwHvW/1IvkVerrbhZ4JVgnWAqOTo4UFR0VEKgqPy5ykAAABAJxVqukEm0kqB86Uoy/sn9WiG+ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key4 b/security/nss/cmd/bltest/tests/rsa_pss/key4
new file mode 100644
index 000000000..46154801c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key4
@@ -0,0 +1 @@
+AAAAAQAAAACApW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW/+2xYrTA8oOhKoijlN/1JqtykcuzB86r/OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm/4nRnxBazC0/DLNfKSgOE4a29kxO8i4eHyDQzoz/siSb2aITcAAAADAQABAAAAgDOlBCqQsn1PVFHKm7vQtEdxoQGviENArvmIXypLvpLolKckrDxWjI+XhTrQfAJmyMajygkp8ejxEjGIRCn8TZrlX+6JahDOcHw+1+c05Ecno5V0UBpTJoMQnCq6yrooPDG0vS9Tw+4341LO40+eUDvYDAYirXnG3O6INUfGo7MlAAAAQOfolCcgqHdRcnOjVgU+oqG8DJSqctVcboYpay38lnlIwKcsvMyn6ss1cG4Jod9VoVNb2bPMNBYLO23NPtqOZEMAAABAtp3KHPfU1+yB51uQ/MqHSrzeEj/ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ/QAAAEAo+hOThlW+H4oVnLrKWnLqGQwwCJ4ZzSdKVW82xPbhn1VLNMB3eQQnu92N0+3iRIMo84XYGzDo5Dsv/6Anhhl5AAAAQBqLOPOY+nEgSYmNf7ee4Kd2aHkSmc36Ce/A5Qessh7XQwHvW/1IvkVerrbhZ4JVgnWAqOTo4UFR0VEKgqPy5ykAAABAJxVqukEm0kqB86Uoy/sn9WiG+ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key5 b/security/nss/cmd/bltest/tests/rsa_pss/key5
new file mode 100644
index 000000000..46154801c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key5
@@ -0,0 +1 @@
+AAAAAQAAAACApW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW/+2xYrTA8oOhKoijlN/1JqtykcuzB86r/OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm/4nRnxBazC0/DLNfKSgOE4a29kxO8i4eHyDQzoz/siSb2aITcAAAADAQABAAAAgDOlBCqQsn1PVFHKm7vQtEdxoQGviENArvmIXypLvpLolKckrDxWjI+XhTrQfAJmyMajygkp8ejxEjGIRCn8TZrlX+6JahDOcHw+1+c05Ecno5V0UBpTJoMQnCq6yrooPDG0vS9Tw+4341LO40+eUDvYDAYirXnG3O6INUfGo7MlAAAAQOfolCcgqHdRcnOjVgU+oqG8DJSqctVcboYpay38lnlIwKcsvMyn6ss1cG4Jod9VoVNb2bPMNBYLO23NPtqOZEMAAABAtp3KHPfU1+yB51uQ/MqHSrzeEj/ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ/QAAAEAo+hOThlW+H4oVnLrKWnLqGQwwCJ4ZzSdKVW82xPbhn1VLNMB3eQQnu92N0+3iRIMo84XYGzDo5Dsv/6Anhhl5AAAAQBqLOPOY+nEgSYmNf7ee4Kd2aHkSmc36Ce/A5Qessh7XQwHvW/1IvkVerrbhZ4JVgnWAqOTo4UFR0VEKgqPy5ykAAABAJxVqukEm0kqB86Uoy/sn9WiG+ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key6 b/security/nss/cmd/bltest/tests/rsa_pss/key6
new file mode 100644
index 000000000..ef62249f1
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key6
@@ -0,0 +1 @@
+AAAAAQAAAADA5r1pKslmRXkEA/3Q9b64ub+S7RAAf8NlBGQZ3QbAXFtbL0js+YnkziaRCZecu0C0oK0k0iSD0e4xWtTMsVNCaDUmkcUk9t2ObCnSJM8kaXOuyGxb9rFAGoUNG5rRu4y87Eewbw+Mf0XT/I8xkpnFQz3bwrMFO0fe0uzUpMrv1hSDPci7Yi8xftB2uAV/6N4/hEgK1eg+SmGQSk8kj7OXAnNX4dMORjE5gVxv1P1axbgXKkUjDstjGKBPFFXYTlqLAAAAAwEAAQAAAMBqf9hPuF+tBzs0QG23T41hpqvBIZapYd15Vl6dpuUYe84tmAJQ9zWVdTWScNkVkLsOQnxxRgtV1RQQsZG88wn+oTGpLI5wJzj6cZ8eAEH1LkDpHyKfTZah5vFy4VWWtFEKba7CYQXyvrxTMWuHvfITEWZgcOjf7mnVLHGpdsqueccraNKFgNxobZ9RKdIl+Cs9YVUTqIKz25FBa0jOCIiCE+N+65r4ANgcqzKM5CBomQPADHtf0xt1UDptQZaE1ikAAABg+OuX6Y3xJmTu/bdhWWpp3c0Odtrs5u1L9aG1CsCG95KKTS+HJqd+UVt02kGYjyILHMh6ofyBDOmagvLRzoIe3O15TGlB9Cx6GguMTSjHXsYLZSJ59hVKdirtFl1H3uNnAAAAYO1NcdCm4kuTwuX2tLvgX1+wr6BC0gT+M3jTZcLyiLao2tfv5F0VPu9Aysx7gf+TQALRCJlLlKXkcozZyWM3WuSZZb2lXL8O/tjWVTtAJ/LYYgim5rSJwXYSgJLWKeSdPQAAAGArtovd+wxPVshVi/+viS2AQwN4Qef6gc+mGjjF45uQHI7nESKl2iInvWze60gUUsEq09YdXk93agq1Vlkb7+Plnlp/3bg0Xh8vNbn0zuV8MkFMCGrsmT6TU+SA2e7GKJ8AAABgT/iXcJ+tB5dGSUV45w/YVGEw7qtWJ8SbCA8F7krZ8+S3y6nWpd/xE6QcNAkzaDPxkIFtimvELpvsVrdWfQ88nGltthmyRdkB3YVtt8gJLnfpoczNVu5NukLF/bYa7CZpAAAAYHe50RN7UEBKmCcpMW76/H3+ZtNOWhgmANXzCgqFEgUcVg0IHU0KGDXsPSWmD05NaqlIsr89u1sSTLvDSJJVo6lINy9peElnRflD4dtPGDgs6qUF38ZXV7s/hXpY3OUhVg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key7 b/security/nss/cmd/bltest/tests/rsa_pss/key7
new file mode 100644
index 000000000..ef62249f1
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key7
@@ -0,0 +1 @@
+AAAAAQAAAADA5r1pKslmRXkEA/3Q9b64ub+S7RAAf8NlBGQZ3QbAXFtbL0js+YnkziaRCZecu0C0oK0k0iSD0e4xWtTMsVNCaDUmkcUk9t2ObCnSJM8kaXOuyGxb9rFAGoUNG5rRu4y87Eewbw+Mf0XT/I8xkpnFQz3bwrMFO0fe0uzUpMrv1hSDPci7Yi8xftB2uAV/6N4/hEgK1eg+SmGQSk8kj7OXAnNX4dMORjE5gVxv1P1axbgXKkUjDstjGKBPFFXYTlqLAAAAAwEAAQAAAMBqf9hPuF+tBzs0QG23T41hpqvBIZapYd15Vl6dpuUYe84tmAJQ9zWVdTWScNkVkLsOQnxxRgtV1RQQsZG88wn+oTGpLI5wJzj6cZ8eAEH1LkDpHyKfTZah5vFy4VWWtFEKba7CYQXyvrxTMWuHvfITEWZgcOjf7mnVLHGpdsqueccraNKFgNxobZ9RKdIl+Cs9YVUTqIKz25FBa0jOCIiCE+N+65r4ANgcqzKM5CBomQPADHtf0xt1UDptQZaE1ikAAABg+OuX6Y3xJmTu/bdhWWpp3c0Odtrs5u1L9aG1CsCG95KKTS+HJqd+UVt02kGYjyILHMh6ofyBDOmagvLRzoIe3O15TGlB9Cx6GguMTSjHXsYLZSJ59hVKdirtFl1H3uNnAAAAYO1NcdCm4kuTwuX2tLvgX1+wr6BC0gT+M3jTZcLyiLao2tfv5F0VPu9Aysx7gf+TQALRCJlLlKXkcozZyWM3WuSZZb2lXL8O/tjWVTtAJ/LYYgim5rSJwXYSgJLWKeSdPQAAAGArtovd+wxPVshVi/+viS2AQwN4Qef6gc+mGjjF45uQHI7nESKl2iInvWze60gUUsEq09YdXk93agq1Vlkb7+Plnlp/3bg0Xh8vNbn0zuV8MkFMCGrsmT6TU+SA2e7GKJ8AAABgT/iXcJ+tB5dGSUV45w/YVGEw7qtWJ8SbCA8F7krZ8+S3y6nWpd/xE6QcNAkzaDPxkIFtimvELpvsVrdWfQ88nGltthmyRdkB3YVtt8gJLnfpoczNVu5NukLF/bYa7CZpAAAAYHe50RN7UEBKmCcpMW76/H3+ZtNOWhgmANXzCgqFEgUcVg0IHU0KGDXsPSWmD05NaqlIsr89u1sSTLvDSJJVo6lINy9peElnRflD4dtPGDgs6qUF38ZXV7s/hXpY3OUhVg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key8 b/security/nss/cmd/bltest/tests/rsa_pss/key8
new file mode 100644
index 000000000..ef62249f1
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key8
@@ -0,0 +1 @@
+AAAAAQAAAADA5r1pKslmRXkEA/3Q9b64ub+S7RAAf8NlBGQZ3QbAXFtbL0js+YnkziaRCZecu0C0oK0k0iSD0e4xWtTMsVNCaDUmkcUk9t2ObCnSJM8kaXOuyGxb9rFAGoUNG5rRu4y87Eewbw+Mf0XT/I8xkpnFQz3bwrMFO0fe0uzUpMrv1hSDPci7Yi8xftB2uAV/6N4/hEgK1eg+SmGQSk8kj7OXAnNX4dMORjE5gVxv1P1axbgXKkUjDstjGKBPFFXYTlqLAAAAAwEAAQAAAMBqf9hPuF+tBzs0QG23T41hpqvBIZapYd15Vl6dpuUYe84tmAJQ9zWVdTWScNkVkLsOQnxxRgtV1RQQsZG88wn+oTGpLI5wJzj6cZ8eAEH1LkDpHyKfTZah5vFy4VWWtFEKba7CYQXyvrxTMWuHvfITEWZgcOjf7mnVLHGpdsqueccraNKFgNxobZ9RKdIl+Cs9YVUTqIKz25FBa0jOCIiCE+N+65r4ANgcqzKM5CBomQPADHtf0xt1UDptQZaE1ikAAABg+OuX6Y3xJmTu/bdhWWpp3c0Odtrs5u1L9aG1CsCG95KKTS+HJqd+UVt02kGYjyILHMh6ofyBDOmagvLRzoIe3O15TGlB9Cx6GguMTSjHXsYLZSJ59hVKdirtFl1H3uNnAAAAYO1NcdCm4kuTwuX2tLvgX1+wr6BC0gT+M3jTZcLyiLao2tfv5F0VPu9Aysx7gf+TQALRCJlLlKXkcozZyWM3WuSZZb2lXL8O/tjWVTtAJ/LYYgim5rSJwXYSgJLWKeSdPQAAAGArtovd+wxPVshVi/+viS2AQwN4Qef6gc+mGjjF45uQHI7nESKl2iInvWze60gUUsEq09YdXk93agq1Vlkb7+Plnlp/3bg0Xh8vNbn0zuV8MkFMCGrsmT6TU+SA2e7GKJ8AAABgT/iXcJ+tB5dGSUV45w/YVGEw7qtWJ8SbCA8F7krZ8+S3y6nWpd/xE6QcNAkzaDPxkIFtimvELpvsVrdWfQ88nGltthmyRdkB3YVtt8gJLnfpoczNVu5NukLF/bYa7CZpAAAAYHe50RN7UEBKmCcpMW76/H3+ZtNOWhgmANXzCgqFEgUcVg0IHU0KGDXsPSWmD05NaqlIsr89u1sSTLvDSJJVo6lINy9peElnRflD4dtPGDgs6qUF38ZXV7s/hXpY3OUhVg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/key9 b/security/nss/cmd/bltest/tests/rsa_pss/key9
new file mode 100644
index 000000000..ef62249f1
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key9
@@ -0,0 +1 @@
+AAAAAQAAAADA5r1pKslmRXkEA/3Q9b64ub+S7RAAf8NlBGQZ3QbAXFtbL0js+YnkziaRCZecu0C0oK0k0iSD0e4xWtTMsVNCaDUmkcUk9t2ObCnSJM8kaXOuyGxb9rFAGoUNG5rRu4y87Eewbw+Mf0XT/I8xkpnFQz3bwrMFO0fe0uzUpMrv1hSDPci7Yi8xftB2uAV/6N4/hEgK1eg+SmGQSk8kj7OXAnNX4dMORjE5gVxv1P1axbgXKkUjDstjGKBPFFXYTlqLAAAAAwEAAQAAAMBqf9hPuF+tBzs0QG23T41hpqvBIZapYd15Vl6dpuUYe84tmAJQ9zWVdTWScNkVkLsOQnxxRgtV1RQQsZG88wn+oTGpLI5wJzj6cZ8eAEH1LkDpHyKfTZah5vFy4VWWtFEKba7CYQXyvrxTMWuHvfITEWZgcOjf7mnVLHGpdsqueccraNKFgNxobZ9RKdIl+Cs9YVUTqIKz25FBa0jOCIiCE+N+65r4ANgcqzKM5CBomQPADHtf0xt1UDptQZaE1ikAAABg+OuX6Y3xJmTu/bdhWWpp3c0Odtrs5u1L9aG1CsCG95KKTS+HJqd+UVt02kGYjyILHMh6ofyBDOmagvLRzoIe3O15TGlB9Cx6GguMTSjHXsYLZSJ59hVKdirtFl1H3uNnAAAAYO1NcdCm4kuTwuX2tLvgX1+wr6BC0gT+M3jTZcLyiLao2tfv5F0VPu9Aysx7gf+TQALRCJlLlKXkcozZyWM3WuSZZb2lXL8O/tjWVTtAJ/LYYgim5rSJwXYSgJLWKeSdPQAAAGArtovd+wxPVshVi/+viS2AQwN4Qef6gc+mGjjF45uQHI7nESKl2iInvWze60gUUsEq09YdXk93agq1Vlkb7+Plnlp/3bg0Xh8vNbn0zuV8MkFMCGrsmT6TU+SA2e7GKJ8AAABgT/iXcJ+tB5dGSUV45w/YVGEw7qtWJ8SbCA8F7krZ8+S3y6nWpd/xE6QcNAkzaDPxkIFtimvELpvsVrdWfQ88nGltthmyRdkB3YVtt8gJLnfpoczNVu5NukLF/bYa7CZpAAAAYHe50RN7UEBKmCcpMW76/H3+ZtNOWhgmANXzCgqFEgUcVg0IHU0KGDXsPSWmD05NaqlIsr89u1sSTLvDSJJVo6lINy9peElnRflD4dtPGDgs6qUF38ZXV7s/hXpY3OUhVg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash0 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash0
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash0
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash1 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash1
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash1
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash10 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash10
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash10
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash11 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash11
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash11
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash12 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash12
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash12
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash13 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash13
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash13
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash14 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash14
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash14
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash15 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash15
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash15
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash16 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash16
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash16
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash17 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash17
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash17
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash2 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash2
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash2
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash3 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash3
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash3
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash4 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash4
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash4
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash5 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash5
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash5
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash6 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash6
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash6
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash7 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash7
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash7
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash8 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash8
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash8
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash9 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash9
new file mode 100644
index 000000000..fcdd09c7d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash9
@@ -0,0 +1 @@
+sha1
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/numtests b/security/nss/cmd/bltest/tests/rsa_pss/numtests
new file mode 100644
index 000000000..3c032078a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/numtests
@@ -0,0 +1 @@
+18
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext0 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext0
new file mode 100644
index 000000000..621838463
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext0
@@ -0,0 +1 @@
+zYtlOMuOjeVmtovQZ1advx7icY4=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext1 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext1
new file mode 100644
index 000000000..e8ce055a6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext1
@@ -0,0 +1 @@
+41vvwXodFguc41+9jrFufuSR0/0=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext10 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext10
new file mode 100644
index 000000000..e7c8e71c7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext10
@@ -0,0 +1 @@
+altL5M02zJff3pmV77+PCXpKmRo=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext11 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext11
new file mode 100644
index 000000000..6af26f173
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext11
@@ -0,0 +1 @@
+ud/R33akYcUeZXbGyO0Kkj0cUOc=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext12 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext12
new file mode 100644
index 000000000..d94dd83f4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext12
@@ -0,0 +1 @@
+lZa7Ywz2qNTqRgBCK566ixNnXdQ=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext13 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext13
new file mode 100644
index 000000000..a7998a4d1
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext13
@@ -0,0 +1 @@
+tQMxk5knf9bByPEDPL8EGZ6iFxY=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext14 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext14
new file mode 100644
index 000000000..b18920b74
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext14
@@ -0,0 +1 @@
+UKrt6FNrLDByCLJ1pnri3xlsdig=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext15 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext15
new file mode 100644
index 000000000..407ec5cc8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext15
@@ -0,0 +1 @@
+qgtyuLNx3dEMiuR0QlzMz4hCopQ=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext16 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext16
new file mode 100644
index 000000000..c10bd8dc8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext16
@@ -0,0 +1 @@
++tOQLJdQYiorxnJiLEgnDMV9Pqg=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext17 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext17
new file mode 100644
index 000000000..cf9856cb5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext17
@@ -0,0 +1 @@
+EiGW3rXRIr2Mb8eB/2kk18aVqt4=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext2 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext2
new file mode 100644
index 000000000..3b390ec8f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext2
@@ -0,0 +1 @@
+BlLsZ7zuMPnSaZEiuRwZq9uon5E=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext3 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext3
new file mode 100644
index 000000000..36da06a98
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext3
@@ -0,0 +1 @@
+OcIcTM7anBrfg5x0ThISpkN1dew=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext4 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext4
new file mode 100644
index 000000000..c8d7ff2ba
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext4
@@ -0,0 +1 @@
+NtrpE7d70XyubnsJRT0kVEzrszw=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext5 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext5
new file mode 100644
index 000000000..fb0a775cf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext5
@@ -0,0 +1 @@
+Re7xkfT3nDH+XS7eflCYmU6SnS0=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext6 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext6
new file mode 100644
index 000000000..05de2c24b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext6
@@ -0,0 +1 @@
+JxWkm4sAEs167oTBFkRubf4/rsA=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext7 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext7
new file mode 100644
index 000000000..b0b066052
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext7
@@ -0,0 +1 @@
+LayVbVOWR0isNk0GWVgnxrTxQ80=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext8 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext8
new file mode 100644
index 000000000..dc97a9c55
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext8
@@ -0,0 +1 @@
+KNmMRszK+9O8BOcvlnpUvT6hIpg=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext9 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext9
new file mode 100644
index 000000000..cd9c0725a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext9
@@ -0,0 +1 @@
+CGbS/1p58l72aM1vMbQt7kIeTA4=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed0 b/security/nss/cmd/bltest/tests/rsa_pss/seed0
new file mode 100644
index 000000000..2e2631533
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed0
@@ -0,0 +1 @@
+3ulZx+BkETYUIP+AGF7Vfz5ndq8=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed1 b/security/nss/cmd/bltest/tests/rsa_pss/seed1
new file mode 100644
index 000000000..26e4788da
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed1
@@ -0,0 +1 @@
+7yhp+kDDRssYPas9e//Jj9Vt9C0=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed10 b/security/nss/cmd/bltest/tests/rsa_pss/seed10
new file mode 100644
index 000000000..8418bb7cc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed10
@@ -0,0 +1 @@
+1okleobv+mghLF4MYZ7KKV+5G2c=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed11 b/security/nss/cmd/bltest/tests/rsa_pss/seed11
new file mode 100644
index 000000000..f58258646
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed11
@@ -0,0 +1 @@
+wl8Tv2fQgWcaBIGh8YINYTu6InY=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed12 b/security/nss/cmd/bltest/tests/rsa_pss/seed12
new file mode 100644
index 000000000..59469f99f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed12
@@ -0,0 +1 @@
+BOIV7m/5NLnacNdzDIc0q/zs3ok=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed13 b/security/nss/cmd/bltest/tests/rsa_pss/seed13
new file mode 100644
index 000000000..402552fe5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed13
@@ -0,0 +1 @@
+iyvdS0D69UXHeN35vBpJy1f5txs=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed14 b/security/nss/cmd/bltest/tests/rsa_pss/seed14
new file mode 100644
index 000000000..d840fd556
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed14
@@ -0,0 +1 @@
+Tpb8GzmPkrRGcQEMDcPv1uIMLXM=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed15 b/security/nss/cmd/bltest/tests/rsa_pss/seed15
new file mode 100644
index 000000000..2edca8b90
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed15
@@ -0,0 +1 @@
+x81pjYS2USjYg146ix6w4By1Qew=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed16 b/security/nss/cmd/bltest/tests/rsa_pss/seed16
new file mode 100644
index 000000000..80e23fbba
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed16
@@ -0,0 +1 @@
+76i/+WISsvSj83GhDVdBUmVfXfs=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed17 b/security/nss/cmd/bltest/tests/rsa_pss/seed17
new file mode 100644
index 000000000..2e7a00d42
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed17
@@ -0,0 +1 @@
+rYsVI3A2RiJLZgtVCIWRfKLR3yg=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed2 b/security/nss/cmd/bltest/tests/rsa_pss/seed2
new file mode 100644
index 000000000..4df6784b4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed2
@@ -0,0 +1 @@
+cQucR0fYANTeh/Eq/c5t8YEHzHc=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed3 b/security/nss/cmd/bltest/tests/rsa_pss/seed3
new file mode 100644
index 000000000..d58108df1
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed3
@@ -0,0 +1 @@
+BW8AmF3hTY71zqnoL4wnvvcgM14=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed4 b/security/nss/cmd/bltest/tests/rsa_pss/seed4
new file mode 100644
index 000000000..7d366c13e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed4
@@ -0,0 +1 @@
+gOcP+GoI3j7GCXKzm0+/3Opnro4=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed5 b/security/nss/cmd/bltest/tests/rsa_pss/seed5
new file mode 100644
index 000000000..a2da928b0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed5
@@ -0,0 +1 @@
+qKtp3YAfAHTCofxgZJg2xhbZloE=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed6 b/security/nss/cmd/bltest/tests/rsa_pss/seed6
new file mode 100644
index 000000000..6dcd0e509
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed6
@@ -0,0 +1 @@
+wKQlMT3411ZL0kNNMRUj1SV+7YA=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed7 b/security/nss/cmd/bltest/tests/rsa_pss/seed7
new file mode 100644
index 000000000..0b6e3f37a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed7
@@ -0,0 +1 @@
+swfEO0hQqNrC8V8y43g574xcDpE=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed8 b/security/nss/cmd/bltest/tests/rsa_pss/seed8
new file mode 100644
index 000000000..b1b34b468
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed8
@@ -0,0 +1 @@
+misAfoCXi7sZLDVOt9qa7fx02/U=
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed9 b/security/nss/cmd/bltest/tests/rsa_pss/seed9
new file mode 100644
index 000000000..d18d81a02
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed9
@@ -0,0 +1 @@
+cPOCvd9NXS3YizvHtzCL5jK4QEU=
diff --git a/security/nss/cmd/bltest/tests/seed_cbc/ciphertext0 b/security/nss/cmd/bltest/tests/seed_cbc/ciphertext0
new file mode 100644
index 000000000..97e970e1b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/seed_cbc/ciphertext0
@@ -0,0 +1 @@
+JVdzim3if1YIcpGABasoCQ==
diff --git a/security/nss/cmd/bltest/tests/seed_cbc/iv0 b/security/nss/cmd/bltest/tests/seed_cbc/iv0
new file mode 100644
index 000000000..2b3b07661
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/seed_cbc/iv0
@@ -0,0 +1 @@
+1234567890123456
diff --git a/security/nss/cmd/bltest/tests/seed_cbc/key0 b/security/nss/cmd/bltest/tests/seed_cbc/key0
new file mode 100644
index 000000000..13911cc29
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/seed_cbc/key0
@@ -0,0 +1 @@
+fedcba9876543210
diff --git a/security/nss/cmd/bltest/tests/seed_cbc/numtests b/security/nss/cmd/bltest/tests/seed_cbc/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/seed_cbc/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/seed_cbc/plaintext0 b/security/nss/cmd/bltest/tests/seed_cbc/plaintext0
new file mode 100644
index 000000000..8d6a8d555
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/seed_cbc/plaintext0
@@ -0,0 +1 @@
+0123456789abcdef
diff --git a/security/nss/cmd/bltest/tests/seed_ecb/ciphertext0 b/security/nss/cmd/bltest/tests/seed_ecb/ciphertext0
new file mode 100644
index 000000000..314ffbd8e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/seed_ecb/ciphertext0
@@ -0,0 +1 @@
+GX8KY3uUhAQnL6XbQhXjEw==
diff --git a/security/nss/cmd/bltest/tests/seed_ecb/iv0 b/security/nss/cmd/bltest/tests/seed_ecb/iv0
new file mode 100644
index 000000000..2b3b07661
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/seed_ecb/iv0
@@ -0,0 +1 @@
+1234567890123456
diff --git a/security/nss/cmd/bltest/tests/seed_ecb/key0 b/security/nss/cmd/bltest/tests/seed_ecb/key0
new file mode 100644
index 000000000..13911cc29
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/seed_ecb/key0
@@ -0,0 +1 @@
+fedcba9876543210
diff --git a/security/nss/cmd/bltest/tests/seed_ecb/numtests b/security/nss/cmd/bltest/tests/seed_ecb/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/seed_ecb/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/seed_ecb/plaintext0 b/security/nss/cmd/bltest/tests/seed_ecb/plaintext0
new file mode 100644
index 000000000..8d6a8d555
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/seed_ecb/plaintext0
@@ -0,0 +1 @@
+0123456789abcdef
diff --git a/security/nss/cmd/bltest/tests/sha1/ciphertext0 b/security/nss/cmd/bltest/tests/sha1/ciphertext0
new file mode 100644
index 000000000..1fe4bd2bd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha1/ciphertext0
@@ -0,0 +1 @@
+cDSMAygXMPIJZC5bntZ4ZhecQ9g=
diff --git a/security/nss/cmd/bltest/tests/sha1/numtests b/security/nss/cmd/bltest/tests/sha1/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha1/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/sha1/plaintext0 b/security/nss/cmd/bltest/tests/sha1/plaintext0
new file mode 100644
index 000000000..863e79c65
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha1/plaintext0
@@ -0,0 +1 @@
+A cage went in search of a bird.
diff --git a/security/nss/cmd/bltest/tests/sha224/ciphertext0 b/security/nss/cmd/bltest/tests/sha224/ciphertext0
new file mode 100644
index 000000000..dfc3d279c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha224/ciphertext0
@@ -0,0 +1,2 @@
+Iwl9IjQF2CKGQqR3vaJVsyqtvOS9oLP342ydpw==
+
diff --git a/security/nss/cmd/bltest/tests/sha224/ciphertext1 b/security/nss/cmd/bltest/tests/sha224/ciphertext1
new file mode 100644
index 000000000..bef4714bb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha224/ciphertext1
@@ -0,0 +1,2 @@
+dTiLFlEndsxdul2h/YkBULDGRVy09YsZUlIlJQ==
+
diff --git a/security/nss/cmd/bltest/tests/sha224/numtests b/security/nss/cmd/bltest/tests/sha224/numtests
new file mode 100644
index 000000000..0cfbf0888
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha224/numtests
@@ -0,0 +1 @@
+2
diff --git a/security/nss/cmd/bltest/tests/sha224/plaintext0 b/security/nss/cmd/bltest/tests/sha224/plaintext0
new file mode 100644
index 000000000..8baef1b4a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha224/plaintext0
@@ -0,0 +1 @@
+abc
diff --git a/security/nss/cmd/bltest/tests/sha224/plaintext1 b/security/nss/cmd/bltest/tests/sha224/plaintext1
new file mode 100644
index 000000000..afb5dce5d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha224/plaintext1
@@ -0,0 +1 @@
+abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq
diff --git a/security/nss/cmd/bltest/tests/sha256/ciphertext0 b/security/nss/cmd/bltest/tests/sha256/ciphertext0
new file mode 100644
index 000000000..07e2ff14f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha256/ciphertext0
@@ -0,0 +1 @@
+ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=
diff --git a/security/nss/cmd/bltest/tests/sha256/ciphertext1 b/security/nss/cmd/bltest/tests/sha256/ciphertext1
new file mode 100644
index 000000000..2ab6e1da5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha256/ciphertext1
@@ -0,0 +1 @@
+JI1qYdIGOLjlwCaTDD5gOaM85Flk/yFn9uzt1BnbBsE=
diff --git a/security/nss/cmd/bltest/tests/sha256/numtests b/security/nss/cmd/bltest/tests/sha256/numtests
new file mode 100644
index 000000000..0cfbf0888
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha256/numtests
@@ -0,0 +1 @@
+2
diff --git a/security/nss/cmd/bltest/tests/sha256/plaintext0 b/security/nss/cmd/bltest/tests/sha256/plaintext0
new file mode 100644
index 000000000..8baef1b4a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha256/plaintext0
@@ -0,0 +1 @@
+abc
diff --git a/security/nss/cmd/bltest/tests/sha256/plaintext1 b/security/nss/cmd/bltest/tests/sha256/plaintext1
new file mode 100644
index 000000000..afb5dce5d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha256/plaintext1
@@ -0,0 +1 @@
+abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq
diff --git a/security/nss/cmd/bltest/tests/sha384/ciphertext0 b/security/nss/cmd/bltest/tests/sha384/ciphertext0
new file mode 100644
index 000000000..c94f91e22
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha384/ciphertext0
@@ -0,0 +1 @@
+ywB1P0WjXou1oD1pmsZQBycsMqsO3tFjGotgWkP/W+2AhgcroefMI1i67KE0yCWn
diff --git a/security/nss/cmd/bltest/tests/sha384/ciphertext1 b/security/nss/cmd/bltest/tests/sha384/ciphertext1
new file mode 100644
index 000000000..833f06d84
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha384/ciphertext1
@@ -0,0 +1 @@
+CTMMM/cRR+g9GS/Hgs0bR1MRGxc7OwXSL6CAhuOw9xL8x8caVX4tuWbD6fqRdGA5
diff --git a/security/nss/cmd/bltest/tests/sha384/numtests b/security/nss/cmd/bltest/tests/sha384/numtests
new file mode 100644
index 000000000..0cfbf0888
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha384/numtests
@@ -0,0 +1 @@
+2
diff --git a/security/nss/cmd/bltest/tests/sha384/plaintext0 b/security/nss/cmd/bltest/tests/sha384/plaintext0
new file mode 100644
index 000000000..8baef1b4a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha384/plaintext0
@@ -0,0 +1 @@
+abc
diff --git a/security/nss/cmd/bltest/tests/sha384/plaintext1 b/security/nss/cmd/bltest/tests/sha384/plaintext1
new file mode 100644
index 000000000..94fcc2b29
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha384/plaintext1
@@ -0,0 +1 @@
+abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu
diff --git a/security/nss/cmd/bltest/tests/sha512/ciphertext0 b/security/nss/cmd/bltest/tests/sha512/ciphertext0
new file mode 100644
index 000000000..8b626e237
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha512/ciphertext0
@@ -0,0 +1,2 @@
+3a81oZNherrMQXNJriBBMRLm+k6JqX6iCp7u5ktV05ohkpkqJ0/BqDa6PCOj/uu9
+RU1EI2Q86A4qmslPpUyknw==
diff --git a/security/nss/cmd/bltest/tests/sha512/ciphertext1 b/security/nss/cmd/bltest/tests/sha512/ciphertext1
new file mode 100644
index 000000000..c02d1752d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha512/ciphertext1
@@ -0,0 +1,2 @@
+jpWbddrjE9qM9PcoFPwUP493ecbrn3+hcpmurbaIkBhQHSieSQD35DMbmd7EtUM6
+x9Mp7rbdJlReluVbh0vpCQ==
diff --git a/security/nss/cmd/bltest/tests/sha512/numtests b/security/nss/cmd/bltest/tests/sha512/numtests
new file mode 100644
index 000000000..0cfbf0888
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha512/numtests
@@ -0,0 +1 @@
+2
diff --git a/security/nss/cmd/bltest/tests/sha512/plaintext0 b/security/nss/cmd/bltest/tests/sha512/plaintext0
new file mode 100644
index 000000000..8baef1b4a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha512/plaintext0
@@ -0,0 +1 @@
+abc
diff --git a/security/nss/cmd/bltest/tests/sha512/plaintext1 b/security/nss/cmd/bltest/tests/sha512/plaintext1
new file mode 100644
index 000000000..94fcc2b29
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha512/plaintext1
@@ -0,0 +1 @@
+abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu
diff --git a/security/nss/cmd/btoa/Makefile b/security/nss/cmd/btoa/Makefile
new file mode 100644
index 000000000..f3b23fdcd
--- /dev/null
+++ b/security/nss/cmd/btoa/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/btoa/btoa.c b/security/nss/cmd/btoa/btoa.c
new file mode 100644
index 000000000..2a5e6d4c6
--- /dev/null
+++ b/security/nss/cmd/btoa/btoa.c
@@ -0,0 +1,203 @@
+/* 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/. */
+
+#include "plgetopt.h"
+#include "secutil.h"
+#include "nssb64.h"
+#include <errno.h>
+
+#if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
+#if !defined(WIN32)
+extern int fread(char *, size_t, size_t, FILE *);
+extern int fwrite(char *, size_t, size_t, FILE *);
+extern int fprintf(FILE *, char *, ...);
+#endif
+#endif
+
+#if defined(WIN32)
+#include "fcntl.h"
+#include "io.h"
+#endif
+
+static PRInt32
+output_ascii(void *arg, const char *obuf, PRInt32 size)
+{
+ FILE *outFile = arg;
+ int nb;
+
+ nb = fwrite(obuf, 1, size, outFile);
+ if (nb != size) {
+ PORT_SetError(SEC_ERROR_IO);
+ return -1;
+ }
+
+ return nb;
+}
+
+static SECStatus
+encode_file(FILE *outFile, FILE *inFile)
+{
+ NSSBase64Encoder *cx;
+ int nb;
+ SECStatus status = SECFailure;
+ unsigned char ibuf[4096];
+
+ cx = NSSBase64Encoder_Create(output_ascii, outFile);
+ if (!cx) {
+ return -1;
+ }
+
+ for (;;) {
+ if (feof(inFile))
+ break;
+ nb = fread(ibuf, 1, sizeof(ibuf), inFile);
+ if (nb != sizeof(ibuf)) {
+ if (nb == 0) {
+ if (ferror(inFile)) {
+ PORT_SetError(SEC_ERROR_IO);
+ goto loser;
+ }
+ /* eof */
+ break;
+ }
+ }
+
+ status = NSSBase64Encoder_Update(cx, ibuf, nb);
+ if (status != SECSuccess)
+ goto loser;
+ }
+
+ status = NSSBase64Encoder_Destroy(cx, PR_FALSE);
+ if (status != SECSuccess)
+ return status;
+
+ /*
+ * Add a trailing CRLF. Note this must be done *after* the call
+ * to Destroy above (because only then are we sure all data has
+ * been written out).
+ */
+ fwrite("\r\n", 1, 2, outFile);
+ return SECSuccess;
+
+loser:
+ (void)NSSBase64Encoder_Destroy(cx, PR_TRUE);
+ return status;
+}
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ fprintf(stderr, "%-20s Wrap output in BEGIN/END lines and the given suffix\n",
+ "-w suffix");
+ fprintf(stderr, "%-20s (use \"c\" as a shortcut for suffix CERTIFICATE)\n",
+ "");
+ exit(-1);
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ SECStatus rv;
+ FILE *inFile, *outFile;
+ PLOptState *optstate;
+ PLOptStatus status;
+ char *suffix = NULL;
+
+ inFile = 0;
+ outFile = 0;
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName + 1 : argv[0];
+
+ /* Parse command line arguments */
+ optstate = PL_CreateOptState(argc, argv, "i:o:w:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ default:
+ Usage(progName);
+ break;
+
+ case 'i':
+ inFile = fopen(optstate->value, "rb");
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "wb");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'w':
+ if (!strcmp(optstate->value, "c"))
+ suffix = strdup("CERTIFICATE");
+ else
+ suffix = strdup(optstate->value);
+ break;
+ }
+ }
+ if (status == PL_OPT_BAD)
+ Usage(progName);
+ if (!inFile) {
+#if defined(WIN32)
+ /* If we're going to read binary data from stdin, we must put stdin
+ ** into O_BINARY mode or else incoming \r\n's will become \n's.
+ */
+
+ int smrv = _setmode(_fileno(stdin), _O_BINARY);
+ if (smrv == -1) {
+ fprintf(stderr,
+ "%s: Cannot change stdin to binary mode. Use -i option instead.\n",
+ progName);
+ return smrv;
+ }
+#endif
+ inFile = stdin;
+ }
+ if (!outFile) {
+#if defined(WIN32)
+ /* We're going to write binary data to stdout. We must put stdout
+ ** into O_BINARY mode or else outgoing \r\n's will become \r\r\n's.
+ */
+
+ int smrv = _setmode(_fileno(stdout), _O_BINARY);
+ if (smrv == -1) {
+ fprintf(stderr,
+ "%s: Cannot change stdout to binary mode. Use -o option instead.\n",
+ progName);
+ return smrv;
+ }
+#endif
+ outFile = stdout;
+ }
+ if (suffix) {
+ fprintf(outFile, "-----BEGIN %s-----\n", suffix);
+ }
+ rv = encode_file(outFile, inFile);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
+ progName, PORT_GetError(), errno);
+ return -1;
+ }
+ if (suffix) {
+ fprintf(outFile, "-----END %s-----\n", suffix);
+ }
+ return 0;
+}
diff --git a/security/nss/cmd/btoa/btoa.gyp b/security/nss/cmd/btoa/btoa.gyp
new file mode 100644
index 000000000..295d5758e
--- /dev/null
+++ b/security/nss/cmd/btoa/btoa.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'btoa',
+ 'type': 'executable',
+ 'sources': [
+ 'btoa.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/btoa/manifest.mn b/security/nss/cmd/btoa/manifest.mn
new file mode 100644
index 000000000..52508a59a
--- /dev/null
+++ b/security/nss/cmd/btoa/manifest.mn
@@ -0,0 +1,21 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# MODULE is implicitly REQUIRED, doesn't need to be listed below.
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = btoa.c
+
+PROGRAM = btoa
+
diff --git a/security/nss/cmd/certcgi/HOWTO.txt b/security/nss/cmd/certcgi/HOWTO.txt
new file mode 100644
index 000000000..54edf8e1a
--- /dev/null
+++ b/security/nss/cmd/certcgi/HOWTO.txt
@@ -0,0 +1,137 @@
+ How to setup your very own Cert-O-Matic Root CA server
+
+ 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/.
+
+ How to setup your very own Cert-O-Matic Root CA server
+
+The program certcgi is part of a small test CA that is used inside
+Netscape by the NSS development team. That CA is affectionately known
+as "Cert-O-Matic" or "Cert-O-Matic II". It presently runs on a server
+named interzone.mcom.com inside Netscape's firewall.
+
+If you wish to setup your own Cert-O-Matic, here are directions.
+
+Disclaimer: This program does not follow good practices for root CAs.
+It should be used only for playing/testing and never for production use.
+Remember, you've been warned!
+
+Cert-O-Matic consists of some html files, shell scripts, one executable
+program that uses NSS and NSPR, the usual set of NSS .db files, and a file
+in which to remember the serial number of the last cert issued. The
+html files and the source to the executable program are in this directory.
+Sample shell scripts are shown below.
+
+The shell scripts and executable program run as CGI "scripts". The
+entire thing runs on an ordinary http web server. It would also run on
+an https web server. The shell scripts and html files must be
+customized for the server on which they run.
+
+The package assumes you have a "document root" directory $DOCROOT, and a
+"cgi-bin" directory $CGIBIN. In this example, the document root is
+assumed to be located in /var/www/htdocs, and the cgi-bin directory in
+/var/www/cgi-bin.
+
+The server is assumed to run all cgi scripts as the user "nobody".
+The names of the cgi scripts run directly by the server all end in .cgi
+because some servers like it that way.
+
+Instructions:
+
+- Create directory $DOCROOT/certomatic
+- Copy the following files from nss/cmd/certcgi to $DOCROOT/certomatic
+ ca.html index.html main.html nscp_ext_form.html stnd_ext_form.html
+- Edit the html files, substituting the name of your own server for the
+ server named in those files.
+- In some web page (e.g. your server's home page), provide an html link to
+ $DOCROOT/certomatic/index.html. This is where users start to get their
+ own certs from certomatic.
+- give these files and directories appropriate permissions.
+
+- Create directories $CGIBIN/certomatic and $CGIBIN/certomatic/bin
+ make sure that $CGIBIN/certomatic is writable by "nobody"
+
+- Create a new set of NSS db files there with the following command:
+
+ certutil -N -d $CGIBIN/certomatic
+
+- when certutil prompts you for the password, enter the word foo
+ because that is compiled into the certcgi program.
+
+- Create the new Root CA cert with this command
+
+ certutil -S -x -d $CGIBIN/certomatic -n "Cert-O-Matic II" \
+ -s "CN=Cert-O-Matic II, O=Cert-O-Matic II" -t TCu,cu,cu -k rsa \
+ -g 1024 -m 10001 -v 60
+
+ (adjust the -g, -m and -v parameters to taste. -s and -x must be as
+shown.)
+
+- dump out the new root CA cert in base64 encoding:
+
+ certutil -d $CGIBIN/certomatic -L -n "Cert-O-Matic II" -a > \
+ $CGIBIN/certomatic/root.cacert
+
+- In $CGIBIN/certomatic/bin add two shell scripts - one to download the
+ root CA cert on demand, and one to run the certcgi program.
+
+download.cgi, the script to install the root CA cert into a browser on
+demand, is this:
+
+#!/bin/sh
+echo "Content-type: application/x-x509-ca-cert"
+echo
+cat $CGIBIN/certomatic/root.cacert
+
+You'll have to put the real path into that cat command because CGIBIN
+won't be defined when this script is run by the server.
+
+certcgi.cgi, the script to run the certcgi program is similar to this:
+
+#!/bin/sh
+cd $CGIBIN/certomatic/bin
+LD_LIBRARY_PATH=$PLATFORM/lib
+export LD_LIBRARY_PATH
+$PLATFORM/bin/certcgi $* 2>&1
+
+Where $PLATFORM/lib is where the NSPR nad NSS DSOs are located, and
+$PLATFORM/bin is where certcgi is located. PLATFORM is not defined when
+the server runs this script, so you'll have to substitute the right value
+in your script. certcgi requires that the working directory be one level
+below the NSS DBs, that is, the DBs are accessed in the directory "..".
+
+You'll want to provide an html link somewhere to the script that downloads
+the root.cacert file. You'll probably want to put that next to the link
+that loads the index.html page. On interzone, this is done with the
+following html:
+
+<a href="/certomatic/index.html">Cert-O-Matic II Root CA server</a>
+<p>
+<a href="/cgi-bin/certomatic/bin/download.cgi">Download and trust Root CA
+certificate</a>
+
+The index.html file in this directory invokes the certcgi.cgi script with
+the form post method, so if you change the name of the certcgi.cgi script,
+you'll also have to change the index.html file in $DOCROOT/certomatic
+
+The 4 files used by the certcgi program (the 3 NSS DBs, and the serial
+number file) are not required to live in $CGIBIN/certomatic, but they are
+required to live in $CWD/.. when certcgi starts.
+
+Known bugs:
+
+1. Because multiple of these CAs exist simultaneously, it would be best if
+they didn't all have to be called "Cert-O-Matic II", but that string is
+presently hard coded into certcgi.c.
+
+2. the html files in this directory contain numerous extraneous <FORM> tags
+which appear to use the post method and have action URLS that are never
+actually used. burp.cgi and echoform.cgi are never actually used. This
+should be cleaned up.
+
+3. The html files use <layer> tags which are supported only in Netscape
+Navigator and Netscape Communication 4.x browsers. The html files do
+not work as intended with Netscape 6.x, Mozilla or Microsoft IE browsers.
+The html files should be fixed to work with all those named browsers.
+
diff --git a/security/nss/cmd/certcgi/Makefile b/security/nss/cmd/certcgi/Makefile
new file mode 100644
index 000000000..c2039d82b
--- /dev/null
+++ b/security/nss/cmd/certcgi/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/certcgi/ca.html b/security/nss/cmd/certcgi/ca.html
new file mode 100644
index 000000000..3f3f08699
--- /dev/null
+++ b/security/nss/cmd/certcgi/ca.html
@@ -0,0 +1,19 @@
+<!-- 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/. -->
+
+<form method="post" name="ca_form" action="mailto:jerdonek@netscape.com">
+<input type="radio" name="caChoiceradio" value="SignWithDefaultkey"
+ onClick="{parent.choice_change(this.form)}">
+ Use the Cert-O-matic certificate to issue the cert</p>
+<input type="radio" name="caChoiceradio" value="SignWithRandomChain"
+ onClick="{parent.choice_change(this.form)}"> Use a
+ <input type="text" size="2" maxsize="2" name="autoCAs"> CA long
+ automatically generated chain ending with the Cert-O-Matic Cert
+ (18 maximum)</p>
+<input type="radio" name="caChoiceradio" value="SignWithSpecifiedChain"
+ onClick="{parent.choice_change(this.form)}"> Use a
+ <input type="text" size="1" maxlength="1" name="manCAs"
+ onChange="{parent.ca_num_change(this.value,this.form)}"> CA long
+ user input chain ending in the Cert-O-Matic Cert.</p>
+</form>
diff --git a/security/nss/cmd/certcgi/ca_form.html b/security/nss/cmd/certcgi/ca_form.html
new file mode 100644
index 000000000..452996b58
--- /dev/null
+++ b/security/nss/cmd/certcgi/ca_form.html
@@ -0,0 +1,357 @@
+<html>
+<!-- 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/. -->
+ <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi">
+ <table border=0 cellspacing=10 cellpadding=0>
+ <tr>
+ <td>
+ Common Name:</td><td> <input type="text" name="name" onChange="{window.top.reset_subject('CN=', value, form)}"></p>
+ </td>
+ <td></td><td></td><td>
+ Mail: </td><td><input type="text" name="email" onChange="var temp;{if (email_type[0].checked) {temp = 'MAIL='} else {temp = 'E='}} ;{window.top.reset_subject(temp, value, form)}"></p>
+ RFC 1274<input type="radio" name="email_type" value="1" onClick="window.top.switch_mail(form)">
+ e-mail<input type="radio" name="email_type" value="2" checked onClick="window.top.switch_mail(form)"></td>
+ <tr>
+ <td>
+ Organization: </td><td> <input type="text" name="org" onChange="{window.top.reset_subject('O=', value, form)}"></p></td>
+ <td></td><td></td><td>
+ Organizational Unit: </td><td><input type="text" name="org_unit" onChange="{window.top.reset_subject('OU=', value, form)}"></p></td>
+ <tr>
+ <td>
+ RFC 1274 UID: </td><td><input type="text" name="uid" onChange="{window.top.reset_subject('UID=', value, form)}"></p></td>
+ <td></td><td></td><td>
+ Locality: </td><td><input type="text" name="loc" onChange="{window.top.reset_subject('L=', value, form)}"></p></td>
+ <tr>
+ <td>
+ State or Province: </td><td><input type="text" name="state" onChange="{window.top.reset_subject('ST=', value, form)}"></p></td>
+ <td></td><td></td><td>
+ Country: </td><td><input type="text" size="2" maxsize="2" name="country" onChange="{window.top.reset_subject('C=', value, form)}"></p></td>
+ </table>
+ <table border=0 cellspacing=10 cellpadding=0>
+ <tr>
+ <td>
+ Serial Number:</p>
+ <DD>
+ <input type="radio" name="serial" value="auto" checked> Auto Generate</P>
+ <DD>
+ <input type="radio" name="serial" value="input">
+ Use this value: <input type="text" name="serial_value" size="8" maxlength="8"></p>
+ </td>
+ <td></td><td></td><td></td><td></td>
+ <td>
+ X.509 version:</p>
+ <DD>
+ <input type="radio" name="ver" value="1" checked> Version 1</p>
+ <DD>
+ <input type="radio" name="ver" value="3"> Version 3</P></td>
+ <td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
+ <td>
+ Key Type:</p>
+ <DD>
+ <input type="radio" name="keyType" value="rsa" checked> RSA</p>
+ <DD>
+ <input type="radio" name="keyType" value="dsa"> DSA</P></td>
+ </table>
+ DN: <input type="text" name="subject" size="70" onChange="{window.top.reset_subjectFields(form)}"></P>
+ <Select name="keysize">
+ <option>1024 (High Grade)
+ <option>768 (Medium Grade)
+ <option>512 (Low Grade)
+ </select>
+ </p>
+ <hr>
+ </p>
+ <table border=1 cellspacing=5 cellpadding=5>
+ <tr>
+ <td>
+ <b>Netscape Certificate Type: </b></p>
+ Activate extension: <input type="checkbox" name="netscape-cert-type"></P>
+ Critical: <input type="checkbox" name="netscape-cert-type-crit">
+ <td>
+ <input type="checkbox" name="netscape-cert-type-ssl-client"> SSL Client</P>
+ <input type="checkbox" name="netscape-cert-type-ssl-server"> SSL Server</P>
+ <input type="checkbox" name="netscape-cert-type-smime"> S/MIME</P>
+ <input type="checkbox" name="netscape-cert-type-object-signing"> Object Signing</P>
+ <input type="checkbox" name="netscape-cert-type-reserved"> Reserved for future use (bit 4)</P>
+ <input type="checkbox" name="netscape-cert-type-ssl-ca"> SSL CA</P>
+ <input type="checkbox" name="netscape-cert-type-smime-ca"> S/MIME CA</P>
+ <input type="checkbox" name="netscape-cert-type-object-signing-ca"> Object Signing CA</P>
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Base URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-base-url"></P>
+ Critical: <input type="checkbox" name="netscape-base-url-crit">
+ <td>
+ <input type="text" name="netscape-base-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Revocation URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-revocation-url"></P>
+ Critical: <input type="checkbox" name="netscape-revocation-url-crit">
+ <td>
+ <input type="text" name="netscape-revocation-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape CA Revocation URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-ca-revocation-url"></P>
+ Critical: <input type="checkbox" name="netscape-ca-revocation-url-crit">
+ <td>
+ <input type="text" name="netscape-ca-revocation-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Certificate Renewal URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-cert-renewal-url"></P>
+ Critical: <input type="checkbox" name="netscape-cert-renewal-url-crit">
+ <td>
+ <input type="text" name="netscape-cert-renewal-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape CA Policy URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-ca-policy-url"></P>
+ Critical: <input type="checkbox" name="netscape-ca-policy-url-crit">
+ <td>
+ <input type="text" name="netscape-ca-policy-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape SSL Server Name:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-ssl-server-name"></P>
+ Critical: <input type="checkbox" name="netscape-ssl-server-name-crit">
+ <td>
+ <input type="text" name="netscape-ssl-server-name-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Comment:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-comment"></P>
+ Critical: <input type="checkbox" name="netscape-comment-crit">
+ <td>
+ <textarea name="netscape-comment-text" rows="5" cols="50"></textarea>
+ </tr>
+ </table>
+ </p>
+ <hr>
+ </p>
+ <table border=1 cellspacing=5 cellpadding=5>
+ <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi">
+ <tr>
+ <td>
+ <b>Key Usage: </b></p>
+ Activate extension: <input type="checkbox" name="keyUsage"></P>
+ Critical: <input type="checkbox" name="keyUsage-crit">
+ <td>
+ <input type="checkbox" name="keyUsage-digitalSignature"> Digital Signature</P>
+ <input type="checkbox" name="keyUsage-nonRepudiation"> Non Repudiation</P>
+ <input type="checkbox" name="keyUsage-keyEncipherment"> Key Encipherment</P>
+ <input type="checkbox" name="keyUsage-dataEncipherment"> Data Encipherment</P>
+ <input type="checkbox" name="keyUsage-keyAgreement"> Key Agreement</P>
+ <input type="checkbox" name="keyUsage-keyCertSign"> Key Certificate Signing</P>
+ <input type="checkbox" name="keyUsage-cRLSign"> CRL Signing</P>
+ </tr>
+ <tr>
+ <td>
+ <b>Extended Key Usage: </b></p>
+ Activate extension: <input type="checkbox" name="extKeyUsage"></P>
+ Critical: <input type="checkbox" name="extKeyUsage-crit">
+ <td>
+ <input type="checkbox" name="extKeyUsage-serverAuth"> Server Auth</P>
+ <input type="checkbox" name="extKeyUsage-clientAuth"> Client Auth</P>
+ <input type="checkbox" name="extKeyUsage-codeSign"> Code Signing</P>
+ <input type="checkbox" name="extKeyUsage-emailProtect"> Email Protection</P>
+ <input type="checkbox" name="extKeyUsage-timeStamp"> Timestamp</P>
+ <input type="checkbox" name="extKeyUsage-ocspResponder"> OCSP Responder</P>
+ <input type="checkbox" name="extKeyUsage-NS-govtApproved"> Step-up</P>
+ <input type="checkbox" name="extKeyUsage-msTrustListSign"> Microsoft Trust List Signing</P>
+ </tr>
+ <tr>
+ <td>
+ <b>Basic Constraints:</b></p>
+ Activate extension: <input type="checkbox" name="basicConstraints"></P>
+ Critical: <input type="checkbox" name="basicConstraints-crit">
+ <td>
+ CA:</p>
+ <dd><input type=radio name="basicConstraints-cA-radio" value="CA"> True</p>
+ <dd><input type=radio name="basicConstraints-cA-radio" value="NotCA"> False</p>
+ <input type="checkbox" name="basicConstraints-pathLengthConstraint">
+ Include Path length: <input type="text" name="basicConstraints-pathLengthConstraint-text" size="2"></p>
+ </tr>
+ <tr>
+ <td>
+ <b>Authority Key Identifier:</b></p>
+ Activate extension: <input type="checkbox" name="authorityKeyIdentifier">
+ <td>
+ <input type="radio" name="authorityKeyIdentifier-radio" value="keyIdentifier"> Key Identider</p>
+ <input type="radio" name="authorityKeyIdentifier-radio" value="authorityCertIssuer"> Issuer Name and Serial number</p>
+ </tr>
+ <tr>
+ <td>
+ <b>Subject Key Identifier:</b></p>
+ Activate extension: <input type="checkbox" name="subjectKeyIdentifier">
+ <td>
+ Key Identifier:
+ <input type="text" name="subjectKeyIdentifier-text"></p>
+ This is an:<p>
+ <dd><dd><input type="radio" name="subjectKeyIdentifier-radio" value="ascii"> ascii text value<p>
+ <dd><dd><input type="radio" name="subjectKeyIdentifier-radio" value="hex"> hex value<p>
+ </tr>
+ <tr>
+ <td>
+ <b>Private Key Usage Period:</b></p>
+ Activate extension: <input type="checkbox" name="privKeyUsagePeriod"></p>
+ Critical: <input type="checkbox" name="privKeyUsagePeriod-crit">
+ <td>
+ Use:</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-radio" value="notBefore"> Not Before</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-radio" value="notAfter"> Not After</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-radio" value="both" > Both</p>
+ <b>Not to be used to sign before:</b></p>
+ <dd><input type="radio" name="privKeyUsagePeriod-notBefore-radio" value="auto"> Set to time of certificate issue</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-notBefore-radio" value="manual"> Use This value</p>
+ <dd><dd>(YYYY/MM/DD HH:MM:SS):
+ <input type="text" name="privKeyUsagePeriod-notBefore-year" size="4" maxlength="4">/
+ <input type="text" name="privKeyUsagePeriod-notBefore-month" size="2" maxlength="2">/
+ <input type="text" name="privKeyUsagePeriod-notBefore-day" size="2" maxlength="2">
+ <input type="text" name="privKeyUsagePeriod-notBefore-hour" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notBefore-minute" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notBefore-second" size="2" maxlength="2"></p>
+ <b>Not to be used to sign after:</b></p>
+ <dd>(YYYY/MM/DD HH:MM:SS):
+ <input type="text" name="privKeyUsagePeriod-notAfter-year" size="4" maxlength="4">/
+ <input type="text" name="privKeyUsagePeriod-notAfter-month" size="2" maxlength="2">/
+ <input type="text" name="privKeyUsagePeriod-notAfter-day" size="2" maxlength="2">
+ <input type="text" name="privKeyUsagePeriod-notAfter-hour" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notAfter-minute" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notAfter-second" size="2" maxlength="2"></p>
+ </tr>
+ <tr>
+ <td>
+ <b>Subject Alternative Name:</b></p>
+ Activate extension: <input type="checkbox" name="SubAltName"></P>
+ Critical: <input type="checkbox" name="SubAltName-crit">
+ <td>
+ <table>
+ <tr>
+ <td>
+ General Names:</p>
+ <select name="SubAltNameSelect" multiple size="10">
+ </select></p></p>
+ <input type="button" name="SubAltName-add" value="Add" onClick="{parent.addSubAltName(this.form)}">
+ <input type="button" name="SubAltName-delete" value="Delete" onClick="parent.deleteSubAltName(this.form)">
+ </td><td>
+ <table><tr><td>
+ Name Type: </td></tr><tr><td>
+ <input type="radio" name="SubAltNameRadio" value="otherName" onClick="parent.setSubAltNameType(form)"> Other Name,
+ OID: <input type="text" name="SubAltNameOtherNameOID" size="6"> </td><td>
+ <input type="radio" name="SubAltNameRadio" value="rfc822Name" onClick="parent.setSubAltNameType(form)"> RFC 822 Name</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="dnsName" onClick="parent.setSubAltNameType(form)"> DNS Name </td><td>
+ <input type="radio" name="SubAltNameRadio" value="x400" onClick="parent.setSubAltNameType(form)"> X400 Address</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="directoryName" onClick="parent.setSubAltNameType(form)"> Directory Name</td><td>
+ <input type="radio" name="SubAltNameRadio" value="ediPartyName" onClick="parent.setSubAltNameType(form)"> EDI Party Name</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="URL" onClick="parent.setSubAltNameType(form)"> Uniform Resource Locator</td><td>
+ <input type="radio" name="SubAltNameRadio" value="ipAddress" onClick="parent.setSubAltNameType(form)"> IP Address</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="regID"onClick="parent.setSubAltNameType(form)"> Registered ID</td><td>
+ <input type="radio" name="SubAltNameRadio" value="nscpNickname" onClick="parent.setSubAltNameType(form)"> Netscape Certificate Nickname</td><td></tr>
+ </table>
+ Name: <input type="text" name="SubAltNameText">
+ Binary Encoded: <input type="checkbox" name="SubAltNameDataType" value="binary" onClick="parent.setSubAltNameType(form)"></p>
+ </tr>
+ </table>
+ </tr>
+
+
+ <tr>
+ <td>
+ <b>Issuer Alternative Name:</b></p>
+ Activate extension: <input type="checkbox" name="IssuerAltName"></P>
+ Critical: <input type="checkbox" name="IssuerAltName-crit">
+ <td>
+ <input type="radio" name="IssuerAltNameSourceRadio" value="auto"> Use the Subject Alternative Name from the Issuers Certificate</p>
+ <input type="radio" name="IssuerAltNameSourceRadio" value="man"> Use this Name:
+ <table>
+ <tr>
+ <td>
+ General Names:</p>
+ <select name="IssuerAltNameSelect" multiple size="10">
+ </select></p></p>
+ <input type="button" name="IssuerAltName-add" value="Add" onClick="{parent.addIssuerAltName(this.form)}">
+ <input type="button" name="IssuerAltName-delete" value="Delete" onClick="parent.deleteIssuerAltName(this.form)">
+ </td><td>
+ <table><tr><td>
+ Name Type: </td></tr><tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="otherName" onClick="parent.setIssuerAltNameType(form)"> Other Name,
+ OID: <input type="text" name="IssuerAltNameOtherNameOID" size="6"> </td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="rfc822Name" onClick="parent.setIssuerAltNameType(form)"> RFC 822 Name</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="dnsName" onClick="parent.setIssuerAltNameType(form)"> DNS Name </td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="x400" onClick="parent.setIssuerAltNameType(form)"> X400 Address</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="directoryName" onClick="parent.setIssuerAltNameType(form)"> Directory Name</td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="ediPartyName" onClick="parent.setIssuerAltNameType(form)"> EDI Party Name</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="URL" onClick="parent.setIssuerAltNameType(form)"> Uniform Resource Locator</td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="ipAddress" onClick="parent.setIssuerAltNameType(form)"> IP Address</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="regID" onClick="parent.setIssuerAltNameType(form)"> Registered ID</td><td></tr>
+ </table>
+ Name: <input type="text" name="IssuerAltNameText">
+ Binary Encoded: <input type="checkbox" name="IssuerAltNameDataType" value="binary" onClick="parent.setIssuerAltNameType(form)"></p>
+ </tr>
+ </table>
+ </tr>
+
+ <tr>
+ <td>
+ <b>Name Constraints:</b></p>
+ Activate extension: <input type="checkbox" name="NameConstraints"></P>
+ <td>
+ <table>
+ <tr>
+ <td>
+ Name Constraints:</p>
+
+
+ <select name="NameConstraintSelect" multiple size="10">
+ </select></p></p>
+ <input type="button" name="NameConstraint-add" value="Add" onClick="{parent.addNameConstraint(this.form)}">
+ <input type="button" name="NameConstraint-delete" value="Delete" onClick="parent.deleteNameConstraint(this.form)">
+ </td><td>
+ <table><tr><td>
+ Name Type: </td></tr><tr><td>
+ <input type="radio" name="NameConstraintRadio" value="otherName" onClick="parent.setNameConstraintNameType(form)"> Other Name,
+ OID: <input type="text" name="NameConstraintOtherNameOID" size="6"> </td><td>
+ <input type="radio" name="NameConstraintRadio" value="rfc822Name" onClick="parent.setNameConstraintNameType(form)"> RFC 822 Name</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="dnsName" onClick="parent.setNameConstraintNameType(form)"> DNS Name </td><td>
+ <input type="radio" name="NameConstraintRadio" value="x400" onClick="parent.setNameConstraintNameType(form)"> X400 Address</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="directoryName" onClick="parent.setNameConstraintNameType(form)"> Directory Name</td><td>
+ <input type="radio" name="NameConstraintRadio" value="ediPartyName" onClick="parent.setNameConstraintNameType(form)"> EDI Party Name</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="URL" onClick="parent.setNameConstraintNameType(form)"> Uniform Resource Locator</td><td>
+ <input type="radio" name="NameConstraintRadio" value="ipAddress" onClick="parent.setNameConstraintNameType(form)"> IP Address</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="regID" onClick="parent.setNameConstraintNameType(form)"> Registered ID</td><td></tr>
+ </table>
+ Name: <input type="text" name="NameConstraintText">
+ Binary Encoded: <input type="checkbox" name="NameConstraintNameDataType" value="binary" onClick="parent.setNameConstraintNameType(form)"></p>
+ Constraint type:<p>
+ <dd><input type="radio" name="NameConstraintTypeRadio" value="permited"> permited<p>
+ <dd><input type="radio" name="NameConstraintTypeRadio" value="excluded"> excluded<p>
+ Minimum: <input type="text" name="NameConstraintMin" size="8" maxlength="8"></p>
+ Maximum: <input type="text" name="NameConstraintMax" size="8" maxlength="8"></p>
+
+
+
+ </tr>
+ </table>
+ </tr>
+ </table>
+ </form>
+
+
+
+
+
+
+
+
+
+
diff --git a/security/nss/cmd/certcgi/certcgi.c b/security/nss/cmd/certcgi/certcgi.c
new file mode 100644
index 000000000..35409e250
--- /dev/null
+++ b/security/nss/cmd/certcgi/certcgi.c
@@ -0,0 +1,2246 @@
+/* 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/. */
+
+/* Cert-O-Matic CGI */
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+
+#include "pk11func.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "secder.h"
+#include "genname.h"
+#include "xconst.h"
+#include "secutil.h"
+#include "pk11pqg.h"
+#include "certxutl.h"
+#include "nss.h"
+
+/* #define TEST 1 */
+/* #define FILEOUT 1 */
+/* #define OFFLINE 1 */
+#define START_FIELDS 100
+#define PREFIX_LEN 6
+#define SERIAL_FILE "../serial"
+#define DB_DIRECTORY ".."
+
+static char *progName;
+
+typedef struct PairStr Pair;
+
+struct PairStr {
+ char *name;
+ char *data;
+};
+
+char prefix[PREFIX_LEN];
+
+const SEC_ASN1Template CERTIA5TypeTemplate[] = {
+ { SEC_ASN1_IA5_STRING }
+};
+
+SECKEYPrivateKey *privkeys[9] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL };
+
+#ifdef notdef
+const SEC_ASN1Template CERT_GeneralNameTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate }
+};
+#endif
+
+static void
+error_out(char *error_string)
+{
+ printf("Content-type: text/plain\n\n");
+ printf("%s", error_string);
+ fflush(stderr);
+ fflush(stdout);
+ exit(1);
+}
+
+static void
+error_allocate(void)
+{
+ error_out("ERROR: Unable to allocate memory");
+}
+
+static char *
+make_copy_string(char *read_pos,
+ int length,
+ char sentinal_value)
+/* copys string from to a new string it creates and
+ returns a pointer to the new string */
+{
+ int remaining = length;
+ char *write_pos;
+ char *new;
+
+ new = write_pos = (char *)PORT_Alloc(length);
+ if (new == NULL) {
+ error_allocate();
+ }
+ while (*read_pos != sentinal_value) {
+ if (remaining == 1) {
+ remaining += length;
+ length = length * 2;
+ new = PORT_Realloc(new, length);
+ if (new == NULL) {
+ error_allocate();
+ }
+ write_pos = new + length - remaining;
+ }
+ *write_pos = *read_pos;
+ ++write_pos;
+ ++read_pos;
+ remaining = remaining - 1;
+ }
+ *write_pos = '\0';
+ return new;
+}
+
+static SECStatus
+clean_input(Pair *data)
+/* converts the non-alphanumeric characters in a form post
+ from hex codes back to characters */
+{
+ int length;
+ int hi_digit;
+ int low_digit;
+ char character;
+ char *begin_pos;
+ char *read_pos;
+ char *write_pos;
+ PRBool name = PR_TRUE;
+
+ begin_pos = data->name;
+ while (begin_pos != NULL) {
+ length = strlen(begin_pos);
+ read_pos = write_pos = begin_pos;
+ while ((read_pos - begin_pos) < length) {
+ if (*read_pos == '+') {
+ *read_pos = ' ';
+ }
+ if (*read_pos == '%') {
+ hi_digit = *(read_pos + 1);
+ low_digit = *(read_pos + 2);
+ read_pos += 3;
+ if (isdigit(hi_digit)) {
+ hi_digit = hi_digit - '0';
+ } else {
+ hi_digit = toupper(hi_digit);
+ if (isxdigit(hi_digit)) {
+ hi_digit = (hi_digit - 'A') + 10;
+ } else {
+ error_out("ERROR: Form data incorrectly formated");
+ }
+ }
+ if (isdigit(low_digit)) {
+ low_digit = low_digit - '0';
+ } else {
+ low_digit = toupper(low_digit);
+ if ((low_digit >= 'A') && (low_digit <= 'F')) {
+ low_digit = (low_digit - 'A') + 10;
+ } else {
+ error_out("ERROR: Form data incorrectly formated");
+ }
+ }
+ character = (hi_digit << 4) | low_digit;
+ if (character != 10) {
+ *write_pos = character;
+ ++write_pos;
+ }
+ } else {
+ *write_pos = *read_pos;
+ ++write_pos;
+ ++read_pos;
+ }
+ }
+ *write_pos = '\0';
+ if (name == PR_TRUE) {
+ begin_pos = data->data;
+ name = PR_FALSE;
+ } else {
+ data++;
+ begin_pos = data->name;
+ name = PR_TRUE;
+ }
+ }
+ return SECSuccess;
+}
+
+static char *
+make_name(char *new_data)
+/* gets the next field name in the input string and returns
+ a pointer to a string containing a copy of it */
+{
+ int length = 20;
+ char *name;
+
+ name = make_copy_string(new_data, length, '=');
+ return name;
+}
+
+static char *
+make_data(char *new_data)
+/* gets the data for the next field in the input string
+ and returns a pointer to a string containing it */
+{
+ int length = 100;
+ char *data;
+ char *read_pos;
+
+ read_pos = new_data;
+ while (*(read_pos - 1) != '=') {
+ ++read_pos;
+ }
+ data = make_copy_string(read_pos, length, '&');
+ return data;
+}
+
+static Pair
+make_pair(char *new_data)
+/* makes a pair name/data pair from the input string */
+{
+ Pair temp;
+
+ temp.name = make_name(new_data);
+ temp.data = make_data(new_data);
+ return temp;
+}
+
+static Pair *
+make_datastruct(char *data, int len)
+/* parses the input from the form post into a data
+ structure of field name/data pairs */
+{
+ Pair *datastruct;
+ Pair *current;
+ char *curr_pos;
+ int fields = START_FIELDS;
+ int remaining = START_FIELDS;
+
+ curr_pos = data;
+ datastruct = current = (Pair *)PORT_Alloc(fields * sizeof(Pair));
+ if (datastruct == NULL) {
+ error_allocate();
+ }
+ while (curr_pos - data < len) {
+ if (remaining == 1) {
+ remaining += fields;
+ fields = fields * 2;
+ datastruct = (Pair *)PORT_Realloc(datastruct, fields *
+ sizeof(Pair));
+ if (datastruct == NULL) {
+ error_allocate();
+ }
+ current = datastruct + (fields - remaining);
+ }
+ *current = make_pair(curr_pos);
+ while (*curr_pos != '&') {
+ ++curr_pos;
+ }
+ ++curr_pos;
+ ++current;
+ remaining = remaining - 1;
+ }
+ current->name = NULL;
+ return datastruct;
+}
+
+static char *
+return_name(Pair *data_struct,
+ int n)
+/* returns a pointer to the name of the nth
+ (starting from 0) item in the data structure */
+{
+ char *name;
+
+ if ((data_struct + n)->name != NULL) {
+ name = (data_struct + n)->name;
+ return name;
+ } else {
+ return NULL;
+ }
+}
+
+static char *
+return_data(Pair *data_struct, int n)
+/* returns a pointer to the data of the nth (starting from 0)
+ itme in the data structure */
+{
+ char *data;
+
+ data = (data_struct + n)->data;
+ return data;
+}
+
+static char *
+add_prefix(char *field_name)
+{
+ extern char prefix[PREFIX_LEN];
+ int i = 0;
+ char *rv;
+ char *write;
+
+ rv = write = PORT_Alloc(PORT_Strlen(prefix) + PORT_Strlen(field_name) + 1);
+ for (i = 0; i < PORT_Strlen(prefix); i++) {
+ *write = prefix[i];
+ write++;
+ }
+ *write = '\0';
+ rv = PORT_Strcat(rv, field_name);
+ return rv;
+}
+
+static char *
+find_field(Pair *data,
+ char *field_name,
+ PRBool add_pre)
+/* returns a pointer to the data of the first pair
+ thats name matches the string it is passed */
+{
+ int i = 0;
+ char *retrieved;
+ int found = 0;
+
+ if (add_pre) {
+ field_name = add_prefix(field_name);
+ }
+ while (return_name(data, i) != NULL) {
+ if (PORT_Strcmp(return_name(data, i), field_name) == 0) {
+ retrieved = return_data(data, i);
+ found = 1;
+ break;
+ }
+ i++;
+ }
+ if (!found) {
+ retrieved = NULL;
+ }
+ return retrieved;
+}
+
+static PRBool
+find_field_bool(Pair *data,
+ char *fieldname,
+ PRBool add_pre)
+{
+ char *rv;
+
+ rv = find_field(data, fieldname, add_pre);
+
+ if ((rv != NULL) && (PORT_Strcmp(rv, "true")) == 0) {
+ return PR_TRUE;
+ } else {
+ return PR_FALSE;
+ }
+}
+
+static CERTCertificateRequest *
+makeCertReq(Pair *form_data,
+ int which_priv_key)
+/* makes and encodes a certrequest */
+{
+
+ PK11SlotInfo *slot;
+ CERTCertificateRequest *certReq = NULL;
+ CERTSubjectPublicKeyInfo *spki;
+ SECKEYPrivateKey *privkey = NULL;
+ SECKEYPublicKey *pubkey = NULL;
+ CERTName *name;
+ char *key;
+ extern SECKEYPrivateKey *privkeys[9];
+ int keySizeInBits;
+ char *challenge = "foo";
+ SECStatus rv = SECSuccess;
+ PQGParams *pqgParams = NULL;
+ PQGVerify *pqgVfy = NULL;
+
+ name = CERT_AsciiToName(find_field(form_data, "subject", PR_TRUE));
+ if (name == NULL) {
+ error_out("ERROR: Unable to create Subject Name");
+ }
+ key = find_field(form_data, "key", PR_TRUE);
+ if (key == NULL) {
+ switch (*find_field(form_data, "keysize", PR_TRUE)) {
+ case '0':
+ keySizeInBits = 2048;
+ break;
+ case '1':
+ keySizeInBits = 1024;
+ break;
+ case '2':
+ keySizeInBits = 512;
+ break;
+ default:
+ error_out("ERROR: Unsupported Key length selected");
+ }
+ if (find_field_bool(form_data, "keyType-dsa", PR_TRUE)) {
+ rv = PK11_PQG_ParamGen(keySizeInBits, &pqgParams, &pqgVfy);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to generate PQG parameters");
+ }
+ slot = PK11_GetBestSlot(CKM_DSA_KEY_PAIR_GEN, NULL);
+ privkey = PK11_GenerateKeyPair(slot, CKM_DSA_KEY_PAIR_GEN,
+ pqgParams, &pubkey, PR_FALSE,
+ PR_TRUE, NULL);
+ } else {
+ privkey = SECKEY_CreateRSAPrivateKey(keySizeInBits, &pubkey, NULL);
+ }
+ privkeys[which_priv_key] = privkey;
+ spki = SECKEY_CreateSubjectPublicKeyInfo(pubkey);
+ } else {
+ spki = SECKEY_ConvertAndDecodePublicKeyAndChallenge(key, challenge,
+ NULL);
+ if (spki == NULL) {
+ error_out("ERROR: Unable to decode Public Key and Challenge String");
+ }
+ }
+ certReq = CERT_CreateCertificateRequest(name, spki, NULL);
+ if (certReq == NULL) {
+ error_out("ERROR: Unable to create Certificate Request");
+ }
+ if (pubkey != NULL) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if (spki != NULL) {
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+ }
+ if (pqgParams != NULL) {
+ PK11_PQG_DestroyParams(pqgParams);
+ }
+ if (pqgVfy != NULL) {
+ PK11_PQG_DestroyVerify(pqgVfy);
+ }
+ return certReq;
+}
+
+static CERTCertificate *
+MakeV1Cert(CERTCertDBHandle *handle,
+ CERTCertificateRequest *req,
+ char *issuerNameStr,
+ PRBool selfsign,
+ int serialNumber,
+ int warpmonths,
+ Pair *data)
+{
+ CERTCertificate *issuerCert = NULL;
+ CERTValidity *validity;
+ CERTCertificate *cert = NULL;
+ PRExplodedTime printableTime;
+ PRTime now,
+ after;
+ if (!selfsign) {
+ issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
+ if (!issuerCert) {
+ error_out("ERROR: Could not find issuer's certificate");
+ return NULL;
+ }
+ }
+ if (find_field_bool(data, "manValidity", PR_TRUE)) {
+ (void)DER_AsciiToTime(&now, find_field(data, "notBefore", PR_TRUE));
+ } else {
+ now = PR_Now();
+ }
+ PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
+ if (warpmonths) {
+ printableTime.tm_month += warpmonths;
+ now = PR_ImplodeTime(&printableTime);
+ PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
+ }
+ if (find_field_bool(data, "manValidity", PR_TRUE)) {
+ (void)DER_AsciiToTime(&after, find_field(data, "notAfter", PR_TRUE));
+ PR_ExplodeTime(after, PR_GMTParameters, &printableTime);
+ } else {
+ printableTime.tm_month += 3;
+ after = PR_ImplodeTime(&printableTime);
+ }
+ /* note that the time is now in micro-second unit */
+ validity = CERT_CreateValidity(now, after);
+
+ if (selfsign) {
+ cert = CERT_CreateCertificate(serialNumber, &(req->subject), validity, req);
+ } else {
+ cert = CERT_CreateCertificate(serialNumber, &(issuerCert->subject), validity, req);
+ }
+
+ CERT_DestroyValidity(validity);
+ if (issuerCert) {
+ CERT_DestroyCertificate(issuerCert);
+ }
+ return (cert);
+}
+
+static int
+get_serial_number(Pair *data)
+{
+ int serial = 0;
+ int error;
+ char *filename = SERIAL_FILE;
+ char *SN;
+ FILE *serialFile;
+
+ if (find_field_bool(data, "serial-auto", PR_TRUE)) {
+ serialFile = fopen(filename, "r");
+ if (serialFile != NULL) {
+ size_t nread = fread(&serial, sizeof(int), 1, serialFile);
+ if (ferror(serialFile) != 0 || nread != 1) {
+ error_out("Error: Unable to read serial number file");
+ }
+ if (serial == -1) {
+ serial = 21;
+ }
+ fclose(serialFile);
+ ++serial;
+ serialFile = fopen(filename, "w");
+ if (serialFile == NULL) {
+ error_out("ERROR: Unable to open serial number file for writing");
+ }
+ fwrite(&serial, sizeof(int), 1, serialFile);
+ if (ferror(serialFile) != 0) {
+ error_out("Error: Unable to write to serial number file");
+ }
+ } else {
+ fclose(serialFile);
+ serialFile = fopen(filename, "w");
+ if (serialFile == NULL) {
+ error_out("ERROR: Unable to open serial number file");
+ }
+ serial = 21;
+ fwrite(&serial, sizeof(int), 1, serialFile);
+ if (ferror(serialFile) != 0) {
+ error_out("Error: Unable to write to serial number file");
+ }
+ error = ferror(serialFile);
+ if (error != 0) {
+ error_out("ERROR: Unable to write to serial file");
+ }
+ }
+ fclose(serialFile);
+ } else {
+ SN = find_field(data, "serial_value", PR_TRUE);
+ while (*SN != '\0') {
+ serial = serial * 16;
+ if ((*SN >= 'A') && (*SN <= 'F')) {
+ serial += *SN - 'A' + 10;
+ } else {
+ if ((*SN >= 'a') && (*SN <= 'f')) {
+ serial += *SN - 'a' + 10;
+ } else {
+ serial += *SN - '0';
+ }
+ }
+ ++SN;
+ }
+ }
+ return serial;
+}
+
+typedef SECStatus (*EXTEN_VALUE_ENCODER)(PLArenaPool *extHandle, void *value, SECItem *encodedValue);
+
+static SECStatus
+EncodeAndAddExtensionValue(
+ PLArenaPool *arena,
+ void *extHandle,
+ void *value,
+ PRBool criticality,
+ int extenType,
+ EXTEN_VALUE_ENCODER EncodeValueFn)
+{
+ SECItem encodedValue;
+ SECStatus rv;
+
+ encodedValue.data = NULL;
+ encodedValue.len = 0;
+ rv = (*EncodeValueFn)(arena, value, &encodedValue);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to encode extension value");
+ }
+ rv = CERT_AddExtension(extHandle, extenType, &encodedValue, criticality, PR_TRUE);
+ return (rv);
+}
+
+static SECStatus
+AddKeyUsage(void *extHandle,
+ Pair *data)
+{
+ SECItem bitStringValue;
+ unsigned char keyUsage = 0x0;
+
+ if (find_field_bool(data, "keyUsage-digitalSignature", PR_TRUE)) {
+ keyUsage |= (0x80 >> 0);
+ }
+ if (find_field_bool(data, "keyUsage-nonRepudiation", PR_TRUE)) {
+ keyUsage |= (0x80 >> 1);
+ }
+ if (find_field_bool(data, "keyUsage-keyEncipherment", PR_TRUE)) {
+ keyUsage |= (0x80 >> 2);
+ }
+ if (find_field_bool(data, "keyUsage-dataEncipherment", PR_TRUE)) {
+ keyUsage |= (0x80 >> 3);
+ }
+ if (find_field_bool(data, "keyUsage-keyAgreement", PR_TRUE)) {
+ keyUsage |= (0x80 >> 4);
+ }
+ if (find_field_bool(data, "keyUsage-keyCertSign", PR_TRUE)) {
+ keyUsage |= (0x80 >> 5);
+ }
+ if (find_field_bool(data, "keyUsage-cRLSign", PR_TRUE)) {
+ keyUsage |= (0x80 >> 6);
+ }
+
+ bitStringValue.data = &keyUsage;
+ bitStringValue.len = 1;
+
+ return (CERT_EncodeAndAddBitStrExtension(extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
+ (find_field_bool(data, "keyUsage-crit", PR_TRUE))));
+}
+
+static CERTOidSequence *
+CreateOidSequence(void)
+{
+ CERTOidSequence *rv = (CERTOidSequence *)NULL;
+ PLArenaPool *arena = (PLArenaPool *)NULL;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ((PLArenaPool *)NULL == arena) {
+ goto loser;
+ }
+
+ rv = (CERTOidSequence *)PORT_ArenaZAlloc(arena, sizeof(CERTOidSequence));
+ if ((CERTOidSequence *)NULL == rv) {
+ goto loser;
+ }
+
+ rv->oids = (SECItem **)PORT_ArenaZAlloc(arena, sizeof(SECItem *));
+ if ((SECItem **)NULL == rv->oids) {
+ goto loser;
+ }
+
+ rv->arena = arena;
+ return rv;
+
+loser:
+ if ((PLArenaPool *)NULL != arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return (CERTOidSequence *)NULL;
+}
+
+static SECStatus
+AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
+{
+ SECItem **oids;
+ PRUint32 count = 0;
+ SECOidData *od;
+
+ od = SECOID_FindOIDByTag(oidTag);
+ if ((SECOidData *)NULL == od) {
+ return SECFailure;
+ }
+
+ for (oids = os->oids; (SECItem *)NULL != *oids; oids++) {
+ count++;
+ }
+
+ /* ArenaZRealloc */
+
+ {
+ PRUint32 i;
+
+ oids = (SECItem **)PORT_ArenaZAlloc(os->arena, sizeof(SECItem *) * (count + 2));
+ if ((SECItem **)NULL == oids) {
+ return SECFailure;
+ }
+
+ for (i = 0; i < count; i++) {
+ oids[i] = os->oids[i];
+ }
+
+ /* ArenaZFree(os->oids); */
+ }
+
+ os->oids = oids;
+ os->oids[count] = &od->oid;
+
+ return SECSuccess;
+}
+
+static SECItem *
+EncodeOidSequence(CERTOidSequence *os)
+{
+ SECItem *rv;
+ extern const SEC_ASN1Template CERT_OidSeqTemplate[];
+
+ rv = (SECItem *)PORT_ArenaZAlloc(os->arena, sizeof(SECItem));
+ if ((SECItem *)NULL == rv) {
+ goto loser;
+ }
+
+ if (!SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate)) {
+ goto loser;
+ }
+
+ return rv;
+
+loser:
+ return (SECItem *)NULL;
+}
+
+static SECStatus
+AddExtKeyUsage(void *extHandle, Pair *data)
+{
+ SECStatus rv;
+ CERTOidSequence *os;
+ SECItem *value;
+ PRBool crit;
+
+ os = CreateOidSequence();
+ if ((CERTOidSequence *)NULL == os) {
+ return SECFailure;
+ }
+
+ if (find_field_bool(data, "extKeyUsage-serverAuth", PR_TRUE)) {
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
+ if (SECSuccess != rv)
+ goto loser;
+ }
+
+ if (find_field_bool(data, "extKeyUsage-msTrustListSign", PR_TRUE)) {
+ rv = AddOidToSequence(os, SEC_OID_MS_EXT_KEY_USAGE_CTL_SIGNING);
+ if (SECSuccess != rv)
+ goto loser;
+ }
+
+ if (find_field_bool(data, "extKeyUsage-clientAuth", PR_TRUE)) {
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
+ if (SECSuccess != rv)
+ goto loser;
+ }
+
+ if (find_field_bool(data, "extKeyUsage-codeSign", PR_TRUE)) {
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
+ if (SECSuccess != rv)
+ goto loser;
+ }
+
+ if (find_field_bool(data, "extKeyUsage-emailProtect", PR_TRUE)) {
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
+ if (SECSuccess != rv)
+ goto loser;
+ }
+
+ if (find_field_bool(data, "extKeyUsage-timeStamp", PR_TRUE)) {
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
+ if (SECSuccess != rv)
+ goto loser;
+ }
+
+ if (find_field_bool(data, "extKeyUsage-ocspResponder", PR_TRUE)) {
+ rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER);
+ if (SECSuccess != rv)
+ goto loser;
+ }
+
+ if (find_field_bool(data, "extKeyUsage-NS-govtApproved", PR_TRUE)) {
+ rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
+ if (SECSuccess != rv)
+ goto loser;
+ }
+
+ value = EncodeOidSequence(os);
+
+ crit = find_field_bool(data, "extKeyUsage-crit", PR_TRUE);
+
+ rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, value,
+ crit, PR_TRUE);
+/*FALLTHROUGH*/
+loser:
+ CERT_DestroyOidSequence(os);
+ return rv;
+}
+
+static SECStatus
+AddSubKeyID(void *extHandle,
+ Pair *data,
+ CERTCertificate *subjectCert)
+{
+ SECItem encodedValue;
+ SECStatus rv;
+ char *read;
+ char *write;
+ char *first;
+ char character;
+ int high_digit = 0,
+ low_digit = 0;
+ int len;
+ PRBool odd = PR_FALSE;
+
+ encodedValue.data = NULL;
+ encodedValue.len = 0;
+ first = read = write = find_field(data, "subjectKeyIdentifier-text",
+ PR_TRUE);
+ len = PORT_Strlen(first);
+ odd = ((len % 2) != 0) ? PR_TRUE : PR_FALSE;
+ if (find_field_bool(data, "subjectKeyIdentifier-radio-hex", PR_TRUE)) {
+ if (odd) {
+ error_out("ERROR: Improperly formated subject key identifier, hex values must be expressed as an octet string");
+ }
+ while (*read != '\0') {
+ if (!isxdigit(*read)) {
+ error_out("ERROR: Improperly formated subject key identifier");
+ }
+ *read = toupper(*read);
+ if ((*read >= 'A') && (*read <= 'F')) {
+ high_digit = *read - 'A' + 10;
+ } else {
+ high_digit = *read - '0';
+ }
+ ++read;
+ if (!isxdigit(*read)) {
+ error_out("ERROR: Improperly formated subject key identifier");
+ }
+ *read = toupper(*read);
+ if ((*read >= 'A') && (*read <= 'F')) {
+ low_digit = *(read) - 'A' + 10;
+ } else {
+ low_digit = *(read) - '0';
+ }
+ character = (high_digit << 4) | low_digit;
+ *write = character;
+ ++write;
+ ++read;
+ }
+ *write = '\0';
+ len = write - first;
+ }
+ subjectCert->subjectKeyID.data = (unsigned char *)find_field(data, "subjectKeyIdentifier-text", PR_TRUE);
+ subjectCert->subjectKeyID.len = len;
+ rv = CERT_EncodeSubjectKeyID(NULL, &subjectCert->subjectKeyID, &encodedValue);
+ if (rv) {
+ return (rv);
+ }
+ return (CERT_AddExtension(extHandle, SEC_OID_X509_SUBJECT_KEY_ID,
+ &encodedValue, PR_FALSE, PR_TRUE));
+}
+
+static SECStatus
+AddAuthKeyID(void *extHandle,
+ Pair *data,
+ char *issuerNameStr,
+ CERTCertDBHandle *handle)
+{
+ CERTAuthKeyID *authKeyID = NULL;
+ PLArenaPool *arena = NULL;
+ SECStatus rv = SECSuccess;
+ CERTCertificate *issuerCert = NULL;
+ CERTGeneralName *genNames;
+ CERTName *directoryName = NULL;
+
+ issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ error_allocate();
+ }
+
+ authKeyID = PORT_ArenaZAlloc(arena, sizeof(CERTAuthKeyID));
+ if (authKeyID == NULL) {
+ error_allocate();
+ }
+ if (find_field_bool(data, "authorityKeyIdentifier-radio-keyIdentifier",
+ PR_TRUE)) {
+ authKeyID->keyID.data = PORT_ArenaAlloc(arena, PORT_Strlen((char *)issuerCert->subjectKeyID.data));
+ if (authKeyID->keyID.data == NULL) {
+ error_allocate();
+ }
+ PORT_Memcpy(authKeyID->keyID.data, issuerCert->subjectKeyID.data,
+ authKeyID->keyID.len =
+ PORT_Strlen((char *)issuerCert->subjectKeyID.data));
+ } else {
+
+ PORT_Assert(arena);
+ genNames = (CERTGeneralName *)PORT_ArenaZAlloc(arena, (sizeof(CERTGeneralName)));
+ if (genNames == NULL) {
+ error_allocate();
+ }
+ genNames->l.next = genNames->l.prev = &(genNames->l);
+ genNames->type = certDirectoryName;
+
+ directoryName = CERT_AsciiToName(issuerCert->subjectName);
+ if (!directoryName) {
+ error_out("ERROR: Unable to create Directory Name");
+ }
+ rv = CERT_CopyName(arena, &genNames->name.directoryName,
+ directoryName);
+ CERT_DestroyName(directoryName);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to copy Directory Name");
+ }
+ authKeyID->authCertIssuer = genNames;
+ if (authKeyID->authCertIssuer == NULL && SECFailure == PORT_GetError()) {
+ error_out("ERROR: Unable to get Issuer General Name for Authority Key ID Extension");
+ }
+ authKeyID->authCertSerialNumber = issuerCert->serialNumber;
+ }
+ rv = EncodeAndAddExtensionValue(arena, extHandle, authKeyID, PR_FALSE,
+ SEC_OID_X509_AUTH_KEY_ID,
+ (EXTEN_VALUE_ENCODER)
+ CERT_EncodeAuthKeyID);
+ if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ return (rv);
+}
+
+static SECStatus
+AddPrivKeyUsagePeriod(void *extHandle,
+ Pair *data,
+ CERTCertificate *cert)
+{
+ char *notBeforeStr;
+ char *notAfterStr;
+ PLArenaPool *arena = NULL;
+ SECStatus rv = SECSuccess;
+ CERTPrivKeyUsagePeriod *pkup;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ error_allocate();
+ }
+ pkup = PORT_ArenaZNew(arena, CERTPrivKeyUsagePeriod);
+ if (pkup == NULL) {
+ error_allocate();
+ }
+ notBeforeStr = (char *)PORT_Alloc(16);
+ if (notBeforeStr == NULL) {
+ error_allocate();
+ }
+ notAfterStr = (char *)PORT_Alloc(16);
+ if (notAfterStr == NULL) {
+ error_allocate();
+ }
+ *notBeforeStr = '\0';
+ *notAfterStr = '\0';
+ pkup->arena = arena;
+ pkup->notBefore.len = 0;
+ pkup->notBefore.data = NULL;
+ pkup->notAfter.len = 0;
+ pkup->notAfter.data = NULL;
+ if (find_field_bool(data, "privKeyUsagePeriod-radio-notBefore", PR_TRUE) ||
+ find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) {
+ pkup->notBefore.len = 15;
+ pkup->notBefore.data = (unsigned char *)notBeforeStr;
+ if (find_field_bool(data, "privKeyUsagePeriod-notBefore-radio-manual",
+ PR_TRUE)) {
+ PORT_Strcat(notBeforeStr, find_field(data,
+ "privKeyUsagePeriod-notBefore-year",
+ PR_TRUE));
+ PORT_Strcat(notBeforeStr, find_field(data,
+ "privKeyUsagePeriod-notBefore-month",
+ PR_TRUE));
+ PORT_Strcat(notBeforeStr, find_field(data,
+ "privKeyUsagePeriod-notBefore-day",
+ PR_TRUE));
+ PORT_Strcat(notBeforeStr, find_field(data,
+ "privKeyUsagePeriod-notBefore-hour",
+ PR_TRUE));
+ PORT_Strcat(notBeforeStr, find_field(data,
+ "privKeyUsagePeriod-notBefore-minute",
+ PR_TRUE));
+ PORT_Strcat(notBeforeStr, find_field(data,
+ "privKeyUsagePeriod-notBefore-second",
+ PR_TRUE));
+ if ((*(notBeforeStr + 14) != '\0') ||
+ (!isdigit(*(notBeforeStr + 13))) ||
+ (*(notBeforeStr + 12) >= '5' && *(notBeforeStr + 12) <= '0') ||
+ (!isdigit(*(notBeforeStr + 11))) ||
+ (*(notBeforeStr + 10) >= '5' && *(notBeforeStr + 10) <= '0') ||
+ (!isdigit(*(notBeforeStr + 9))) ||
+ (*(notBeforeStr + 8) >= '2' && *(notBeforeStr + 8) <= '0') ||
+ (!isdigit(*(notBeforeStr + 7))) ||
+ (*(notBeforeStr + 6) >= '3' && *(notBeforeStr + 6) <= '0') ||
+ (!isdigit(*(notBeforeStr + 5))) ||
+ (*(notBeforeStr + 4) >= '1' && *(notBeforeStr + 4) <= '0') ||
+ (!isdigit(*(notBeforeStr + 3))) ||
+ (!isdigit(*(notBeforeStr + 2))) ||
+ (!isdigit(*(notBeforeStr + 1))) ||
+ (!isdigit(*(notBeforeStr + 0))) ||
+ (*(notBeforeStr + 8) == '2' && *(notBeforeStr + 9) >= '4') ||
+ (*(notBeforeStr + 6) == '3' && *(notBeforeStr + 7) >= '1') ||
+ (*(notBeforeStr + 4) == '1' && *(notBeforeStr + 5) >= '2')) {
+ error_out("ERROR: Improperly formated private key usage period");
+ }
+ *(notBeforeStr + 14) = 'Z';
+ *(notBeforeStr + 15) = '\0';
+ } else {
+ if ((*(cert->validity.notBefore.data) > '5') ||
+ ((*(cert->validity.notBefore.data) == '5') &&
+ (*(cert->validity.notBefore.data + 1) != '0'))) {
+ PORT_Strcat(notBeforeStr, "19");
+ } else {
+ PORT_Strcat(notBeforeStr, "20");
+ }
+ PORT_Strcat(notBeforeStr, (char *)cert->validity.notBefore.data);
+ }
+ }
+ if (find_field_bool(data, "privKeyUsagePeriod-radio-notAfter", PR_TRUE) ||
+ find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) {
+ pkup->notAfter.len = 15;
+ pkup->notAfter.data = (unsigned char *)notAfterStr;
+ PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-year",
+ PR_TRUE));
+ PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-month",
+ PR_TRUE));
+ PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-day",
+ PR_TRUE));
+ PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-hour",
+ PR_TRUE));
+ PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-minute",
+ PR_TRUE));
+ PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-second",
+ PR_TRUE));
+ if ((*(notAfterStr + 14) != '\0') ||
+ (!isdigit(*(notAfterStr + 13))) ||
+ (*(notAfterStr + 12) >= '5' && *(notAfterStr + 12) <= '0') ||
+ (!isdigit(*(notAfterStr + 11))) ||
+ (*(notAfterStr + 10) >= '5' && *(notAfterStr + 10) <= '0') ||
+ (!isdigit(*(notAfterStr + 9))) ||
+ (*(notAfterStr + 8) >= '2' && *(notAfterStr + 8) <= '0') ||
+ (!isdigit(*(notAfterStr + 7))) ||
+ (*(notAfterStr + 6) >= '3' && *(notAfterStr + 6) <= '0') ||
+ (!isdigit(*(notAfterStr + 5))) ||
+ (*(notAfterStr + 4) >= '1' && *(notAfterStr + 4) <= '0') ||
+ (!isdigit(*(notAfterStr + 3))) ||
+ (!isdigit(*(notAfterStr + 2))) ||
+ (!isdigit(*(notAfterStr + 1))) ||
+ (!isdigit(*(notAfterStr + 0))) ||
+ (*(notAfterStr + 8) == '2' && *(notAfterStr + 9) >= '4') ||
+ (*(notAfterStr + 6) == '3' && *(notAfterStr + 7) >= '1') ||
+ (*(notAfterStr + 4) == '1' && *(notAfterStr + 5) >= '2')) {
+ error_out("ERROR: Improperly formated private key usage period");
+ }
+ *(notAfterStr + 14) = 'Z';
+ *(notAfterStr + 15) = '\0';
+ }
+
+ PORT_Assert(arena);
+
+ rv = EncodeAndAddExtensionValue(arena, extHandle, pkup,
+ find_field_bool(data,
+ "privKeyUsagePeriod-crit",
+ PR_TRUE),
+ SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD,
+ (EXTEN_VALUE_ENCODER)
+ CERT_EncodePrivateKeyUsagePeriod);
+ PORT_FreeArena(arena, PR_FALSE);
+ PORT_Free(notBeforeStr);
+ PORT_Free(notAfterStr);
+ return (rv);
+}
+
+static SECStatus
+AddBasicConstraint(void *extHandle,
+ Pair *data)
+{
+ CERTBasicConstraints basicConstraint;
+ SECItem encodedValue;
+ SECStatus rv;
+
+ encodedValue.data = NULL;
+ encodedValue.len = 0;
+ basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
+ basicConstraint.isCA = (find_field_bool(data, "basicConstraints-cA-radio-CA",
+ PR_TRUE));
+ if (find_field_bool(data, "basicConstraints-pathLengthConstraint", PR_TRUE)) {
+ basicConstraint.pathLenConstraint = atoi(find_field(data, "basicConstraints-pathLengthConstraint-text",
+ PR_TRUE));
+ }
+
+ rv = CERT_EncodeBasicConstraintValue(NULL, &basicConstraint,
+ &encodedValue);
+ if (rv)
+ return (rv);
+ rv = CERT_AddExtension(extHandle, SEC_OID_X509_BASIC_CONSTRAINTS,
+ &encodedValue,
+ (find_field_bool(data, "basicConstraints-crit",
+ PR_TRUE)),
+ PR_TRUE);
+
+ PORT_Free(encodedValue.data);
+ return (rv);
+}
+
+static SECStatus
+AddNscpCertType(void *extHandle,
+ Pair *data)
+{
+ SECItem bitStringValue;
+ unsigned char CertType = 0x0;
+
+ if (find_field_bool(data, "netscape-cert-type-ssl-client", PR_TRUE)) {
+ CertType |= (0x80 >> 0);
+ }
+ if (find_field_bool(data, "netscape-cert-type-ssl-server", PR_TRUE)) {
+ CertType |= (0x80 >> 1);
+ }
+ if (find_field_bool(data, "netscape-cert-type-smime", PR_TRUE)) {
+ CertType |= (0x80 >> 2);
+ }
+ if (find_field_bool(data, "netscape-cert-type-object-signing", PR_TRUE)) {
+ CertType |= (0x80 >> 3);
+ }
+ if (find_field_bool(data, "netscape-cert-type-reserved", PR_TRUE)) {
+ CertType |= (0x80 >> 4);
+ }
+ if (find_field_bool(data, "netscape-cert-type-ssl-ca", PR_TRUE)) {
+ CertType |= (0x80 >> 5);
+ }
+ if (find_field_bool(data, "netscape-cert-type-smime-ca", PR_TRUE)) {
+ CertType |= (0x80 >> 6);
+ }
+ if (find_field_bool(data, "netscape-cert-type-object-signing-ca", PR_TRUE)) {
+ CertType |= (0x80 >> 7);
+ }
+
+ bitStringValue.data = &CertType;
+ bitStringValue.len = 1;
+
+ return (CERT_EncodeAndAddBitStrExtension(extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
+ (find_field_bool(data, "netscape-cert-type-crit", PR_TRUE))));
+}
+
+static SECStatus
+add_IA5StringExtension(void *extHandle,
+ char *string,
+ PRBool crit,
+ int idtag)
+{
+ SECItem encodedValue;
+ SECStatus rv;
+
+ encodedValue.data = NULL;
+ encodedValue.len = 0;
+
+ rv = CERT_EncodeIA5TypeExtension(NULL, string, &encodedValue);
+ if (rv) {
+ return (rv);
+ }
+ return (CERT_AddExtension(extHandle, idtag, &encodedValue, crit, PR_TRUE));
+}
+
+static SECItem *
+string_to_oid(char *string)
+{
+ int i;
+ int length = 20;
+ int remaining;
+ int first_value;
+ int second_value;
+ int value;
+ int oidLength;
+ unsigned char *oidString;
+ unsigned char *write;
+ unsigned char *read;
+ unsigned char *temp;
+ SECItem *oid;
+
+ remaining = length;
+ i = 0;
+ while (*string == ' ') {
+ string++;
+ }
+ while (isdigit(*(string + i))) {
+ i++;
+ }
+ if (*(string + i) == '.') {
+ *(string + i) = '\0';
+ } else {
+ error_out("ERROR: Improperly formated OID");
+ }
+ first_value = atoi(string);
+ if (first_value < 0 || first_value > 2) {
+ error_out("ERROR: Improperly formated OID");
+ }
+ string += i + 1;
+ i = 0;
+ while (isdigit(*(string + i))) {
+ i++;
+ }
+ if (*(string + i) == '.') {
+ *(string + i) = '\0';
+ } else {
+ error_out("ERROR: Improperly formated OID");
+ }
+ second_value = atoi(string);
+ if (second_value < 0 || second_value > 39) {
+ error_out("ERROR: Improperly formated OID");
+ }
+ oidString = PORT_ZAlloc(2);
+ *oidString = (first_value * 40) + second_value;
+ *(oidString + 1) = '\0';
+ oidLength = 1;
+ string += i + 1;
+ i = 0;
+ temp = write = PORT_ZAlloc(length);
+ while (*string != '\0') {
+ value = 0;
+ while (isdigit(*(string + i))) {
+ i++;
+ }
+ if (*(string + i) == '\0') {
+ value = atoi(string);
+ string += i;
+ } else {
+ if (*(string + i) == '.') {
+ *(string + i) = '\0';
+ value = atoi(string);
+ string += i + 1;
+ } else {
+ *(string + i) = '\0';
+ i++;
+ value = atoi(string);
+ while (*(string + i) == ' ')
+ i++;
+ if (*(string + i) != '\0') {
+ error_out("ERROR: Improperly formated OID");
+ }
+ }
+ }
+ i = 0;
+ while (value != 0) {
+ if (remaining < 1) {
+ remaining += length;
+ length = length * 2;
+ temp = PORT_Realloc(temp, length);
+ write = temp + length - remaining;
+ }
+ *write = (value & 0x7f) | (0x80);
+ write++;
+ remaining--;
+ value = value >> 7;
+ }
+ *temp = *temp & (0x7f);
+ oidLength += write - temp;
+ oidString = PORT_Realloc(oidString, (oidLength + 1));
+ read = write - 1;
+ write = oidLength + oidString - 1;
+ for (i = 0; i < (length - remaining); i++) {
+ *write = *read;
+ write--;
+ read++;
+ }
+ write = temp;
+ remaining = length;
+ }
+ *(oidString + oidLength) = '\0';
+ oid = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
+ oid->data = oidString;
+ oid->len = oidLength;
+ PORT_Free(temp);
+ return oid;
+}
+
+static SECItem *
+string_to_ipaddress(char *string)
+{
+ int i = 0;
+ int value;
+ int j = 0;
+ SECItem *ipaddress;
+
+ while (*string == ' ') {
+ string++;
+ }
+ ipaddress = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
+ ipaddress->data = PORT_ZAlloc(9);
+ while (*string != '\0' && j < 8) {
+ while (isdigit(*(string + i))) {
+ i++;
+ }
+ if (*(string + i) == '.') {
+ *(string + i) = '\0';
+ value = atoi(string);
+ string = string + i + 1;
+ i = 0;
+ } else {
+ if (*(string + i) == '\0') {
+ value = atoi(string);
+ string = string + i;
+ i = 0;
+ } else {
+ *(string + i) = '\0';
+ while (*(string + i) == ' ') {
+ i++;
+ }
+ if (*(string + i) == '\0') {
+ value = atoi(string);
+ string = string + i;
+ i = 0;
+ } else {
+ error_out("ERROR: Improperly formated IP Address");
+ }
+ }
+ }
+ if (value >= 0 && value < 256) {
+ *(ipaddress->data + j) = value;
+ } else {
+ error_out("ERROR: Improperly formated IP Address");
+ }
+ j++;
+ }
+ *(ipaddress->data + j) = '\0';
+ if (j != 4 && j != 8) {
+ error_out("ERROR: Improperly formated IP Address");
+ }
+ ipaddress->len = j;
+ return ipaddress;
+}
+
+static int
+chr_to_hex(char c)
+{
+ if (isdigit(c)) {
+ return c - '0';
+ }
+ if (isxdigit(c)) {
+ return toupper(c) - 'A' + 10;
+ }
+ return -1;
+}
+
+static SECItem *
+string_to_binary(char *string)
+{
+ SECItem *rv;
+
+ rv = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
+ if (rv == NULL) {
+ error_allocate();
+ }
+ rv->data = (unsigned char *)PORT_ZAlloc((PORT_Strlen(string)) / 3 + 2);
+ rv->len = 0;
+ while (*string && !isxdigit(*string)) {
+ string++;
+ }
+ while (*string) {
+ int high, low;
+ high = chr_to_hex(*string++);
+ low = chr_to_hex(*string++);
+ if (high < 0 || low < 0) {
+ error_out("ERROR: Improperly formated binary encoding");
+ }
+ rv->data[(rv->len)++] = high << 4 | low;
+ if (*string != ':') {
+ break;
+ }
+ ++string;
+ }
+ while (*string == ' ') {
+ ++string;
+ }
+ if (*string) {
+ error_out("ERROR: Junk after binary encoding");
+ }
+
+ return rv;
+}
+
+static SECStatus
+MakeGeneralName(char *name,
+ CERTGeneralName *genName,
+ PLArenaPool *arena)
+{
+ SECItem *oid;
+ SECOidData *oidData;
+ SECItem *ipaddress;
+ SECItem *temp = NULL;
+ int i;
+ int nameType;
+ PRBool binary = PR_FALSE;
+ SECStatus rv = SECSuccess;
+ PRBool nickname = PR_FALSE;
+
+ PORT_Assert(genName);
+ PORT_Assert(arena);
+ nameType = *(name + PORT_Strlen(name) - 1) - '0';
+ if (nameType == 0 && *(name + PORT_Strlen(name) - 2) == '1') {
+ nickname = PR_TRUE;
+ nameType = certOtherName;
+ }
+ if (nameType < 1 || nameType > 9) {
+ error_out("ERROR: Unknown General Name Type");
+ }
+ *(name + PORT_Strlen(name) - 4) = '\0';
+ genName->type = nameType;
+
+ switch (genName->type) {
+ case certURI:
+ case certRFC822Name:
+ case certDNSName: {
+ genName->name.other.data = (unsigned char *)name;
+ genName->name.other.len = PORT_Strlen(name);
+ break;
+ }
+
+ case certIPAddress: {
+ ipaddress = string_to_ipaddress(name);
+ genName->name.other.data = ipaddress->data;
+ genName->name.other.len = ipaddress->len;
+ break;
+ }
+
+ case certRegisterID: {
+ oid = string_to_oid(name);
+ genName->name.other.data = oid->data;
+ genName->name.other.len = oid->len;
+ break;
+ }
+
+ case certEDIPartyName:
+ case certX400Address: {
+
+ genName->name.other.data = PORT_ArenaAlloc(arena,
+ PORT_Strlen(name) + 2);
+ if (genName->name.other.data == NULL) {
+ error_allocate();
+ }
+
+ PORT_Memcpy(genName->name.other.data + 2, name, PORT_Strlen(name));
+ /* This may not be accurate for all cases.
+ For now, use this tag type */
+ genName->name.other.data[0] = (char)(((genName->type - 1) &
+ 0x1f) |
+ 0x80);
+ genName->name.other.data[1] = (char)PORT_Strlen(name);
+ genName->name.other.len = PORT_Strlen(name) + 2;
+ break;
+ }
+
+ case certOtherName: {
+ i = 0;
+ if (!nickname) {
+ while (!isdigit(*(name + PORT_Strlen(name) - i))) {
+ i++;
+ }
+ if (*(name + PORT_Strlen(name) - i) == '1') {
+ binary = PR_TRUE;
+ } else {
+ binary = PR_FALSE;
+ }
+ while (*(name + PORT_Strlen(name) - i) != '-') {
+ i++;
+ }
+ *(name + PORT_Strlen(name) - i - 1) = '\0';
+ i = 0;
+ while (*(name + i) != '-') {
+ i++;
+ }
+ *(name + i - 1) = '\0';
+ oid = string_to_oid(name + i + 2);
+ } else {
+ oidData = SECOID_FindOIDByTag(SEC_OID_NETSCAPE_NICKNAME);
+ oid = &oidData->oid;
+ while (*(name + PORT_Strlen(name) - i) != '-') {
+ i++;
+ }
+ *(name + PORT_Strlen(name) - i) = '\0';
+ }
+ genName->name.OthName.oid.data = oid->data;
+ genName->name.OthName.oid.len = oid->len;
+ if (binary) {
+ temp = string_to_binary(name);
+ genName->name.OthName.name.data = temp->data;
+ genName->name.OthName.name.len = temp->len;
+ } else {
+ temp = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
+ if (temp == NULL) {
+ error_allocate();
+ }
+ temp->data = (unsigned char *)name;
+ temp->len = PORT_Strlen(name);
+ SEC_ASN1EncodeItem(arena, &(genName->name.OthName.name), temp,
+ CERTIA5TypeTemplate);
+ }
+ PORT_Free(temp);
+ break;
+ }
+
+ case certDirectoryName: {
+ CERTName *directoryName = NULL;
+
+ directoryName = CERT_AsciiToName(name);
+ if (!directoryName) {
+ error_out("ERROR: Improperly formated alternative name");
+ break;
+ }
+ rv = CERT_CopyName(arena, &genName->name.directoryName,
+ directoryName);
+ CERT_DestroyName(directoryName);
+
+ break;
+ }
+ }
+ genName->l.next = &(genName->l);
+ genName->l.prev = &(genName->l);
+ return rv;
+}
+
+static CERTGeneralName *
+MakeAltName(Pair *data,
+ char *which,
+ PLArenaPool *arena)
+{
+ CERTGeneralName *SubAltName;
+ CERTGeneralName *current;
+ CERTGeneralName *newname;
+ char *name = NULL;
+ SECStatus rv = SECSuccess;
+ int len;
+
+ len = PORT_Strlen(which);
+ name = find_field(data, which, PR_TRUE);
+ SubAltName = current = (CERTGeneralName *)PORT_ZAlloc(sizeof(CERTGeneralName));
+ if (current == NULL) {
+ error_allocate();
+ }
+ while (name != NULL) {
+
+ rv = MakeGeneralName(name, current, arena);
+
+ if (rv != SECSuccess) {
+ break;
+ }
+ if (*(which + len - 1) < '9') {
+ *(which + len - 1) = *(which + len - 1) + 1;
+ } else {
+ if (isdigit(*(which + len - 2))) {
+ *(which + len - 2) = *(which + len - 2) + 1;
+ *(which + len - 1) = '0';
+ } else {
+ *(which + len - 1) = '1';
+ *(which + len) = '0';
+ *(which + len + 1) = '\0';
+ len++;
+ }
+ }
+ len = PORT_Strlen(which);
+ name = find_field(data, which, PR_TRUE);
+ if (name != NULL) {
+ newname = (CERTGeneralName *)PORT_ZAlloc(sizeof(CERTGeneralName));
+ if (newname == NULL) {
+ error_allocate();
+ }
+ current->l.next = &(newname->l);
+ newname->l.prev = &(current->l);
+ current = newname;
+ newname = NULL;
+ } else {
+ current->l.next = &(SubAltName->l);
+ SubAltName->l.prev = &(current->l);
+ }
+ }
+ if (rv == SECFailure) {
+ return NULL;
+ }
+ return SubAltName;
+}
+
+static CERTNameConstraints *
+MakeNameConstraints(Pair *data,
+ PLArenaPool *arena)
+{
+ CERTNameConstraints *NameConstraints;
+ CERTNameConstraint *current = NULL;
+ CERTNameConstraint *last_permited = NULL;
+ CERTNameConstraint *last_excluded = NULL;
+ char *constraint = NULL;
+ char *which;
+ SECStatus rv = SECSuccess;
+ int len;
+ int i;
+ long max;
+ long min;
+ PRBool permited;
+
+ NameConstraints = (CERTNameConstraints *)PORT_ZAlloc(sizeof(CERTNameConstraints));
+ which = make_copy_string("NameConstraintSelect0", 25, '\0');
+ len = PORT_Strlen(which);
+ constraint = find_field(data, which, PR_TRUE);
+ NameConstraints->permited = NameConstraints->excluded = NULL;
+ while (constraint != NULL) {
+ current = (CERTNameConstraint *)PORT_ZAlloc(sizeof(CERTNameConstraint));
+ if (current == NULL) {
+ error_allocate();
+ }
+ i = 0;
+ while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
+ i++;
+ }
+ *(constraint + PORT_Strlen(constraint) - i - 1) = '\0';
+ max = (long)atoi(constraint + PORT_Strlen(constraint) + 3);
+ if (max > 0) {
+ (void)SEC_ASN1EncodeInteger(arena, &current->max, max);
+ }
+ i = 0;
+ while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
+ i++;
+ }
+ *(constraint + PORT_Strlen(constraint) - i - 1) = '\0';
+ min = (long)atoi(constraint + PORT_Strlen(constraint) + 3);
+ (void)SEC_ASN1EncodeInteger(arena, &current->min, min);
+ while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
+ i++;
+ }
+ *(constraint + PORT_Strlen(constraint) - i - 1) = '\0';
+ if (*(constraint + PORT_Strlen(constraint) + 3) == 'p') {
+ permited = PR_TRUE;
+ } else {
+ permited = PR_FALSE;
+ }
+ rv = MakeGeneralName(constraint, &(current->name), arena);
+
+ if (rv != SECSuccess) {
+ break;
+ }
+ if (*(which + len - 1) < '9') {
+ *(which + len - 1) = *(which + len - 1) + 1;
+ } else {
+ if (isdigit(*(which + len - 2))) {
+ *(which + len - 2) = *(which + len - 2) + 1;
+ *(which + len - 1) = '0';
+ } else {
+ *(which + len - 1) = '1';
+ *(which + len) = '0';
+ *(which + len + 1) = '\0';
+ len++;
+ }
+ }
+ len = PORT_Strlen(which);
+ if (permited) {
+ if (NameConstraints->permited == NULL) {
+ NameConstraints->permited = last_permited = current;
+ }
+ last_permited->l.next = &(current->l);
+ current->l.prev = &(last_permited->l);
+ last_permited = current;
+ } else {
+ if (NameConstraints->excluded == NULL) {
+ NameConstraints->excluded = last_excluded = current;
+ }
+ last_excluded->l.next = &(current->l);
+ current->l.prev = &(last_excluded->l);
+ last_excluded = current;
+ }
+ constraint = find_field(data, which, PR_TRUE);
+ if (constraint != NULL) {
+ current = (CERTNameConstraint *)PORT_ZAlloc(sizeof(CERTNameConstraint));
+ if (current == NULL) {
+ error_allocate();
+ }
+ }
+ }
+ if (NameConstraints->permited != NULL) {
+ last_permited->l.next = &(NameConstraints->permited->l);
+ NameConstraints->permited->l.prev = &(last_permited->l);
+ }
+ if (NameConstraints->excluded != NULL) {
+ last_excluded->l.next = &(NameConstraints->excluded->l);
+ NameConstraints->excluded->l.prev = &(last_excluded->l);
+ }
+ if (which != NULL) {
+ PORT_Free(which);
+ }
+ if (rv == SECFailure) {
+ return NULL;
+ }
+ return NameConstraints;
+}
+
+static SECStatus
+AddAltName(void *extHandle,
+ Pair *data,
+ char *issuerNameStr,
+ CERTCertDBHandle *handle,
+ int type)
+{
+ PRBool autoIssuer = PR_FALSE;
+ PLArenaPool *arena = NULL;
+ CERTGeneralName *genName = NULL;
+ char *which = NULL;
+ char *name = NULL;
+ SECStatus rv = SECSuccess;
+ SECItem *issuersAltName = NULL;
+ CERTCertificate *issuerCert = NULL;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ error_allocate();
+ }
+ if (type == 0) {
+ which = make_copy_string("SubAltNameSelect0", 20, '\0');
+ genName = MakeAltName(data, which, arena);
+ } else {
+ if (autoIssuer) {
+ autoIssuer = find_field_bool(data, "IssuerAltNameSourceRadio-auto",
+ PR_TRUE);
+ issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
+ rv = cert_FindExtension((*issuerCert).extensions,
+ SEC_OID_X509_SUBJECT_ALT_NAME,
+ issuersAltName);
+ if (issuersAltName == NULL) {
+ name = PORT_Alloc(PORT_Strlen((*issuerCert).subjectName) + 4);
+ PORT_Strcpy(name, (*issuerCert).subjectName);
+ PORT_Strcat(name, " - 5");
+ }
+ } else {
+ which = make_copy_string("IssuerAltNameSelect0", 20, '\0');
+ genName = MakeAltName(data, which, arena);
+ }
+ }
+ if (type == 0) {
+ EncodeAndAddExtensionValue(arena, extHandle, genName,
+ find_field_bool(data, "SubAltName-crit",
+ PR_TRUE),
+ SEC_OID_X509_SUBJECT_ALT_NAME,
+ (EXTEN_VALUE_ENCODER)
+ CERT_EncodeAltNameExtension);
+
+ } else {
+ if (autoIssuer && (name == NULL)) {
+ rv = CERT_AddExtension(extHandle, SEC_OID_X509_ISSUER_ALT_NAME, issuersAltName,
+ find_field_bool(data, "IssuerAltName-crit", PR_TRUE), PR_TRUE);
+ } else {
+ EncodeAndAddExtensionValue(arena, extHandle, genName,
+ find_field_bool(data,
+ "IssuerAltName-crit",
+ PR_TRUE),
+ SEC_OID_X509_ISSUER_ALT_NAME,
+ (EXTEN_VALUE_ENCODER)
+ CERT_EncodeAltNameExtension);
+ }
+ }
+ if (which != NULL) {
+ PORT_Free(which);
+ }
+ if (issuerCert != NULL) {
+ CERT_DestroyCertificate(issuerCert);
+ }
+ return rv;
+}
+
+static SECStatus
+AddNameConstraints(void *extHandle,
+ Pair *data)
+{
+ PLArenaPool *arena = NULL;
+ CERTNameConstraints *constraints = NULL;
+ SECStatus rv = SECSuccess;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ error_allocate();
+ }
+ constraints = MakeNameConstraints(data, arena);
+ if (constraints != NULL) {
+ EncodeAndAddExtensionValue(arena, extHandle, constraints, PR_TRUE,
+ SEC_OID_X509_NAME_CONSTRAINTS,
+ (EXTEN_VALUE_ENCODER)
+ CERT_EncodeNameConstraintsExtension);
+ }
+ if (arena != NULL) {
+ PORT_ArenaRelease(arena, NULL);
+ }
+ return rv;
+}
+
+static SECStatus
+add_extensions(CERTCertificate *subjectCert,
+ Pair *data,
+ char *issuerNameStr,
+ CERTCertDBHandle *handle)
+{
+ void *extHandle;
+ SECStatus rv = SECSuccess;
+
+ extHandle = CERT_StartCertExtensions(subjectCert);
+ if (extHandle == NULL) {
+ error_out("ERROR: Unable to get certificates extension handle");
+ }
+ if (find_field_bool(data, "keyUsage", PR_TRUE)) {
+ rv = AddKeyUsage(extHandle, data);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Key Usage extension");
+ }
+ }
+
+ if (find_field_bool(data, "extKeyUsage", PR_TRUE)) {
+ rv = AddExtKeyUsage(extHandle, data);
+ if (SECSuccess != rv) {
+ error_out("ERROR: Unable to add Extended Key Usage extension");
+ }
+ }
+
+ if (find_field_bool(data, "basicConstraints", PR_TRUE)) {
+ rv = AddBasicConstraint(extHandle, data);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Basic Constraint extension");
+ }
+ }
+ if (find_field_bool(data, "subjectKeyIdentifier", PR_TRUE)) {
+ rv = AddSubKeyID(extHandle, data, subjectCert);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Subject Key Identifier Extension");
+ }
+ }
+ if (find_field_bool(data, "authorityKeyIdentifier", PR_TRUE)) {
+ rv = AddAuthKeyID(extHandle, data, issuerNameStr, handle);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Authority Key Identifier extension");
+ }
+ }
+ if (find_field_bool(data, "privKeyUsagePeriod", PR_TRUE)) {
+ rv = AddPrivKeyUsagePeriod(extHandle, data, subjectCert);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Private Key Usage Period extension");
+ }
+ }
+ if (find_field_bool(data, "SubAltName", PR_TRUE)) {
+ rv = AddAltName(extHandle, data, NULL, NULL, 0);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Subject Alternative Name extension");
+ }
+ }
+ if (find_field_bool(data, "IssuerAltName", PR_TRUE)) {
+ rv = AddAltName(extHandle, data, issuerNameStr, handle, 1);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Issuer Alternative Name Extension");
+ }
+ }
+ if (find_field_bool(data, "NameConstraints", PR_TRUE)) {
+ rv = AddNameConstraints(extHandle, data);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Name Constraints Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-cert-type", PR_TRUE)) {
+ rv = AddNscpCertType(extHandle, data);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape Certificate Type Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-base-url", PR_TRUE)) {
+ rv = add_IA5StringExtension(extHandle,
+ find_field(data, "netscape-base-url-text",
+ PR_TRUE),
+ find_field_bool(data,
+ "netscape-base-url-crit",
+ PR_TRUE),
+ SEC_OID_NS_CERT_EXT_BASE_URL);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape Base URL Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-revocation-url", PR_TRUE)) {
+ rv = add_IA5StringExtension(extHandle,
+ find_field(data,
+ "netscape-revocation-url-text",
+ PR_TRUE),
+ find_field_bool(data, "netscape-revocation-url-crit",
+ PR_TRUE),
+ SEC_OID_NS_CERT_EXT_REVOCATION_URL);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape Revocation URL Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-ca-revocation-url", PR_TRUE)) {
+ rv = add_IA5StringExtension(extHandle,
+ find_field(data,
+ "netscape-ca-revocation-url-text",
+ PR_TRUE),
+ find_field_bool(data, "netscape-ca-revocation-url-crit", PR_TRUE),
+ SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape CA Revocation URL Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-cert-renewal-url", PR_TRUE)) {
+ rv = add_IA5StringExtension(extHandle,
+ find_field(data,
+ "netscape-cert-renewal-url-text",
+ PR_TRUE),
+ find_field_bool(data, "netscape-cert-renewal-url-crit",
+ PR_TRUE),
+ SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape Certificate Renewal URL Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-ca-policy-url", PR_TRUE)) {
+ rv = add_IA5StringExtension(extHandle,
+ find_field(data,
+ "netscape-ca-policy-url-text",
+ PR_TRUE),
+ find_field_bool(data, "netscape-ca-policy-url-crit",
+ PR_TRUE),
+ SEC_OID_NS_CERT_EXT_CA_POLICY_URL);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape CA Policy URL Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-ssl-server-name", PR_TRUE)) {
+ rv = add_IA5StringExtension(extHandle,
+ find_field(data,
+ "netscape-ssl-server-name-text",
+ PR_TRUE),
+ find_field_bool(data, "netscape-ssl-server-name-crit",
+ PR_TRUE),
+ SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape SSL Server Name Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-comment", PR_TRUE)) {
+ rv = add_IA5StringExtension(extHandle,
+ find_field(data, "netscape-comment-text",
+ PR_TRUE),
+ find_field_bool(data,
+ "netscape-comment-crit",
+ PR_TRUE),
+ SEC_OID_NS_CERT_EXT_COMMENT);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape Comment Extension");
+ }
+ }
+ CERT_FinishExtensions(extHandle);
+ return (rv);
+}
+
+char *
+return_dbpasswd(PK11SlotInfo *slot, PRBool retry, void *data)
+{
+ char *rv;
+
+ /* don't clobber our poor smart card */
+ if (retry == PR_TRUE) {
+ return NULL;
+ }
+ rv = PORT_Alloc(4);
+ PORT_Strcpy(rv, "foo");
+ return rv;
+}
+
+SECKEYPrivateKey *
+FindPrivateKeyFromNameStr(char *name,
+ CERTCertDBHandle *certHandle)
+{
+ SECKEYPrivateKey *key;
+ CERTCertificate *cert;
+ CERTCertificate *p11Cert;
+
+ /* We don't presently have a PK11 function to find a cert by
+ ** subject name.
+ ** We do have a function to find a cert in the internal slot's
+ ** cert db by subject name, but it doesn't setup the slot info.
+ ** So, this HACK works, but should be replaced as soon as we
+ ** have a function to search for certs accross slots by subject name.
+ */
+ cert = CERT_FindCertByNameString(certHandle, name);
+ if (cert == NULL || cert->nickname == NULL) {
+ error_out("ERROR: Unable to retrieve issuers certificate");
+ }
+ p11Cert = PK11_FindCertFromNickname(cert->nickname, NULL);
+ if (p11Cert == NULL) {
+ error_out("ERROR: Unable to retrieve issuers certificate");
+ }
+ key = PK11_FindKeyByAnyCert(p11Cert, NULL);
+ return key;
+}
+
+static SECItem *
+SignCert(CERTCertificate *cert,
+ char *issuerNameStr,
+ Pair *data,
+ CERTCertDBHandle *handle,
+ int which_key)
+{
+ SECItem der;
+ SECKEYPrivateKey *caPrivateKey = NULL;
+ SECStatus rv;
+ PLArenaPool *arena;
+ SECOidTag algID;
+
+ if (which_key == 0) {
+ caPrivateKey = FindPrivateKeyFromNameStr(issuerNameStr, handle);
+ } else {
+ caPrivateKey = privkeys[which_key - 1];
+ }
+ if (caPrivateKey == NULL) {
+ error_out("ERROR: unable to retrieve issuers key");
+ }
+
+ arena = cert->arena;
+
+ algID = SEC_GetSignatureAlgorithmOidTag(caPrivateKey->keyType,
+ SEC_OID_UNKNOWN);
+ if (algID == SEC_OID_UNKNOWN) {
+ error_out("ERROR: Unknown key type for issuer.");
+ goto done;
+ }
+
+ rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Could not set signature algorithm id.");
+ }
+
+ if (find_field_bool(data, "ver-1", PR_TRUE)) {
+ *(cert->version.data) = 0;
+ cert->version.len = 1;
+ } else {
+ *(cert->version.data) = 2;
+ cert->version.len = 1;
+ }
+ der.data = NULL;
+ der.len = 0;
+ (void)SEC_ASN1EncodeItem(arena, &der, cert, CERT_CertificateTemplate);
+ if (der.data == NULL) {
+ error_out("ERROR: Could not encode certificate.\n");
+ }
+ rv = SEC_DerSignData(arena, &(cert->derCert), der.data, der.len, caPrivateKey,
+ algID);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Could not sign encoded certificate data.\n");
+ }
+done:
+ SECKEY_DestroyPrivateKey(caPrivateKey);
+ return &(cert->derCert);
+}
+
+int
+main(int argc, char **argv)
+{
+ int length = 500;
+ int remaining = 500;
+ int n;
+ int i;
+ int serial;
+ int chainLen;
+ int which_key;
+ char *pos;
+#ifdef OFFLINE
+ char *form_output = "key=MIIBPTCBpzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA7"
+ "SLqjWBL9Wl11Vlg%0AaMqZCvcQOL%2FnvSqYPPRP0XZy9SoAeyWzQnBOiCm2t8H5mK7r2"
+ "jnKdAQOmfhjaJil%0A3hNVu3SekHOXF6Ze7bkWa6%2FSGVcY%2FojkydxFSgY43nd1iyd"
+ "zPQDp8WWLL%2BpVpt%2B%2B%0ATRhFtVXbF0fQI03j9h3BoTgP2lkCAwEAARYDZm9vMA0"
+ "GCSqGSIb3DQEBBAUAA4GB%0AAJ8UfRKJ0GtG%2B%2BufCC6tAfTzKrq3CTBHnom55EyXc"
+ "sAsv6WbDqI%2F0rLAPkn2Xo1r%0AnNhtMxIuj441blMt%2Fa3AGLOy5zmC7Qawt8IytvQ"
+ "ikQ1XTpTBCXevytrmLjCmlURr%0ANJryTM48WaMQHiMiJpbXCqVJC1d%2FpEWBtqvALzZ"
+ "aOOIy&subject=CN%3D%22test%22%26serial-auto%3Dtrue%26serial_value%3D%"
+ "26ver-1%3Dtrue%26ver-3%3Dfalse%26caChoiceradio-SignWithDefaultkey%3Dt"
+ "rue%26caChoiceradio-SignWithRandomChain%3Dfalse%26autoCAs%3D%26caChoi"
+ "ceradio-SignWithSpecifiedChain%3Dfalse%26manCAs%3D%26%24";
+#else
+ char *form_output;
+#endif
+ char *issuerNameStr;
+ char *certName;
+ char *DBdir = DB_DIRECTORY;
+ char *prefixs[10] = { "CA#1-", "CA#2-", "CA#3-",
+ "CA#4-", "CA#5-", "CA#6-",
+ "CA#7-", "CA#8-", "CA#9-", "" };
+ Pair *form_data;
+ CERTCertificate *cert;
+ CERTCertDBHandle *handle;
+ CERTCertificateRequest *certReq = NULL;
+ int warpmonths = 0;
+ SECItem *certDER;
+#ifdef FILEOUT
+ FILE *outfile;
+#endif
+ SECStatus status = SECSuccess;
+ extern char prefix[PREFIX_LEN];
+ SEC_PKCS7ContentInfo *certChain;
+ SECItem *encodedCertChain;
+ PRBool UChain = PR_FALSE;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+#ifdef TEST
+ sleep(20);
+#endif
+ SECU_ConfigDirectory(DBdir);
+
+ PK11_SetPasswordFunc(return_dbpasswd);
+ status = NSS_InitReadWrite(DBdir);
+ if (status != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+ handle = CERT_GetDefaultCertDB();
+
+ prefix[0] = '\0';
+#if !defined(OFFLINE)
+ form_output = (char *)PORT_Alloc(length);
+ if (form_output == NULL) {
+ error_allocate();
+ }
+ pos = form_output;
+ while (feof(stdin) == 0) {
+ if (remaining <= 1) {
+ remaining += length;
+ length = length * 2;
+ form_output = PORT_Realloc(form_output, (length));
+ if (form_output == NULL) {
+ error_allocate();
+ }
+ pos = form_output + length - remaining;
+ }
+ n = fread(pos, 1, (size_t)(remaining - 1), stdin);
+ pos += n;
+ remaining -= n;
+ }
+ *pos = '&';
+ pos++;
+ length = pos - form_output;
+#else
+ length = PORT_Strlen(form_output);
+#endif
+#ifdef FILEOUT
+ printf("Content-type: text/plain\n\n");
+ fwrite(form_output, 1, (size_t)length, stdout);
+ printf("\n");
+#endif
+#ifdef FILEOUT
+ fwrite(form_output, 1, (size_t)length, stdout);
+ printf("\n");
+ fflush(stdout);
+#endif
+ form_data = make_datastruct(form_output, length);
+ status = clean_input(form_data);
+#if !defined(OFFLINE)
+ PORT_Free(form_output);
+#endif
+#ifdef FILEOUT
+ i = 0;
+ while (return_name(form_data, i) != NULL) {
+ printf("%s", return_name(form_data, i));
+ printf("=\n");
+ printf("%s", return_data(form_data, i));
+ printf("\n");
+ i++;
+ }
+ printf("I got that done, woo hoo\n");
+ fflush(stdout);
+#endif
+ issuerNameStr = PORT_Alloc(200);
+ if (find_field_bool(form_data, "caChoiceradio-SignWithSpecifiedChain",
+ PR_FALSE)) {
+ UChain = PR_TRUE;
+ chainLen = atoi(find_field(form_data, "manCAs", PR_FALSE));
+ PORT_Strcpy(prefix, prefixs[0]);
+ issuerNameStr = PORT_Strcpy(issuerNameStr,
+ "CN=Cert-O-Matic II, O=Cert-O-Matic II");
+ if (chainLen == 0) {
+ UChain = PR_FALSE;
+ }
+ } else {
+ if (find_field_bool(form_data, "caChoiceradio-SignWithRandomChain",
+ PR_FALSE)) {
+ PORT_Strcpy(prefix, prefixs[9]);
+ chainLen = atoi(find_field(form_data, "autoCAs", PR_FALSE));
+ if (chainLen < 1 || chainLen > 18) {
+ issuerNameStr = PORT_Strcpy(issuerNameStr,
+ "CN=CA18, O=Cert-O-Matic II");
+ }
+ issuerNameStr = PORT_Strcpy(issuerNameStr, "CN=CA");
+ issuerNameStr = PORT_Strcat(issuerNameStr,
+ find_field(form_data, "autoCAs", PR_FALSE));
+ issuerNameStr = PORT_Strcat(issuerNameStr, ", O=Cert-O-Matic II");
+ } else {
+ issuerNameStr = PORT_Strcpy(issuerNameStr,
+ "CN=Cert-O-Matic II, O=Cert-O-Matic II");
+ }
+ chainLen = 0;
+ }
+
+ i = -1;
+ which_key = 0;
+ do {
+ extern SECStatus cert_GetKeyID(CERTCertificate * cert);
+ i++;
+ if (i != 0 && UChain) {
+ PORT_Strcpy(prefix, prefixs[i]);
+ }
+ /* find_field(form_data,"subject", PR_TRUE); */
+ certReq = makeCertReq(form_data, which_key);
+#ifdef OFFLINE
+ serial = 900;
+#else
+ serial = get_serial_number(form_data);
+#endif
+ cert = MakeV1Cert(handle, certReq, issuerNameStr, PR_FALSE,
+ serial, warpmonths, form_data);
+ if (certReq != NULL) {
+ CERT_DestroyCertificateRequest(certReq);
+ }
+ if (find_field_bool(form_data, "ver-3", PR_TRUE)) {
+ status = add_extensions(cert, form_data, issuerNameStr, handle);
+ if (status != SECSuccess) {
+ error_out("ERROR: Unable to add extensions");
+ }
+ }
+ status = cert_GetKeyID(cert);
+ if (status == SECFailure) {
+ error_out("ERROR: Unable to get Key ID.");
+ }
+ certDER = SignCert(cert, issuerNameStr, form_data, handle, which_key);
+ CERT_NewTempCertificate(handle, certDER, NULL, PR_FALSE, PR_TRUE);
+ issuerNameStr = find_field(form_data, "subject", PR_TRUE);
+ /* SECITEM_FreeItem(certDER, PR_TRUE); */
+ CERT_DestroyCertificate(cert);
+ if (i == (chainLen - 1)) {
+ i = 8;
+ }
+ ++which_key;
+ } while (i < 9 && UChain);
+
+#ifdef FILEOUT
+ outfile = fopen("../certout", "wb");
+#endif
+ certName = find_field(form_data, "subject", PR_FALSE);
+ cert = CERT_FindCertByNameString(handle, certName);
+ certChain = SEC_PKCS7CreateCertsOnly(cert, PR_TRUE, handle);
+ if (certChain == NULL) {
+ error_out("ERROR: No certificates in cert chain");
+ }
+ encodedCertChain = SEC_PKCS7EncodeItem(NULL, NULL, certChain, NULL, NULL,
+ NULL);
+ if (encodedCertChain) {
+#if !defined(FILEOUT)
+ printf("Content-type: application/x-x509-user-cert\r\n");
+ printf("Content-length: %d\r\n\r\n", encodedCertChain->len);
+ fwrite(encodedCertChain->data, 1, encodedCertChain->len, stdout);
+#else
+ fwrite(encodedCertChain->data, 1, encodedCertChain->len, outfile);
+#endif
+
+ } else {
+ error_out("Error: Unable to DER encode certificate");
+ }
+#ifdef FILEOUT
+ printf("\nI got here!\n");
+ fflush(outfile);
+ fclose(outfile);
+#endif
+ fflush(stdout);
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ return 0;
+}
diff --git a/security/nss/cmd/certcgi/certcgi.gyp b/security/nss/cmd/certcgi/certcgi.gyp
new file mode 100644
index 000000000..5ad2893e0
--- /dev/null
+++ b/security/nss/cmd/certcgi/certcgi.gyp
@@ -0,0 +1,33 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'certcgi',
+ 'type': 'executable',
+ 'sources': [
+ 'certcgi.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports',
+ '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20',
+ 'NSS_USE_STATIC_LIBS'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss',
+ 'use_static_libs': 1
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/certcgi/index.html b/security/nss/cmd/certcgi/index.html
new file mode 100644
index 000000000..3ae6a10d4
--- /dev/null
+++ b/security/nss/cmd/certcgi/index.html
@@ -0,0 +1,789 @@
+<HTML> <!-- -*- Mode: Java; tab-width: 8 -*- -->
+<!-- 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/. -->
+<HEAD>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<SCRIPT LANGUAGE="JavaScript1.2">
+
+script_url = 'http://interzone.mcom.com/cgi-bin/certomatic/bin/certcgi.cgi'
+
+ext_page_ver1 =
+ make_page_intro('Version 1 extensions', "#FFFFFF") +
+ '<IFRAME WIDTH="100%" HEIGHT="100%" FRAMEBORDER=0 ID="ext1">' +
+ 'Version 1 X.509 certs do not support extensions' +
+ '</IFRAME>' +
+ '</body></html>';
+
+num_ca = 0;
+
+your_certificate_index_label = 'Your Certificate';
+netscape_extensions_index_label = 'Netscape X.509 Extensions';
+standard_extensions_index_label = 'Standard X.509 Extensions';
+certifying_authorities_index_label = 'Certifying Authorities';
+add_sub_alt_name_index_label = 'Add Subject Alternative Name';
+
+index_list =
+ '0, your_certificate_index_label,' +
+ '0, netscape_extensions_index_label,' +
+ '0, standard_extensions_index_label,' +
+ '0, certifying_authorities_index_label';
+
+add_index_list = '';
+
+ver = 3
+
+max_pages = 13;
+cur_page = 1;
+
+ext_page_array = new Array(max_pages);
+
+index_label = 'Options';
+
+var main_page =
+ make_page_intro('Your Key', "#FFFFFF") +
+ '<IFRAME WIDTH="100%" HEIGHT="100%" FRAMEBORDER=0 ID="main" SRC="main.html">' +
+ '</IFRAME>' +
+ '</body></html>' ;
+
+function setSubAltNameType(form)
+{
+ with(form) {
+ if (SubAltNameRadio[0].checked) {
+ return true;
+ }
+ if (SubAltNameRadio[3].checked || SubAltNameRadio[5].checked) {
+ SubAltNameDataType.checked = true;
+ return true;
+ }
+ if (SubAltNameRadio[1].checked || SubAltNameRadio[2].checked ||
+ SubAltNameRadio[4].checked || SubAltNameRadio[6].checked ||
+ SubAltNameRadio[7].checked || SubAltNameRadio[8].checked) {
+ SubAltNameDataType.checked = false;
+ return true;
+ }
+ }
+ return true;
+}
+
+function setIssuerAltNameType(form)
+{
+ with(form) {
+ if (IssuerAltNameRadio[0].checked) {
+ return true;
+ }
+ if (IssuerAltNameRadio[3].checked || IssuerAltNameRadio[5].checked) {
+ IssuerAltNameDataType.checked = true;
+ return true;
+ }
+ if (IssuerAltNameRadio[1].checked || IssuerAltNameRadio[2].checked ||
+ IssuerAltNameRadio[4].checked || IssuerAltNameRadio[6].checked ||
+ IssuerAltNameRadio[7].checked || IssuerAltNameRadio[8].checked) {
+ IssuerAltNameDataType.checked = false;
+ return true;
+ }
+ }
+ return true;
+}
+
+
+function setNameConstraintNameType(form)
+{
+ with(form) {
+ if (NameConstraintRadio[0].checked) {
+ return true;
+ }
+ if (NameConstraintRadio[3].checked || NameConstraintRadio[5].checked) {
+ NameConstraintNameDataType.checked = true;
+ return true;
+ }
+ if (NameConstraintRadio[1].checked || NameConstraintRadio[2].checked ||
+ NameConstraintRadio[4].checked || NameConstraintRadio[6].checked ||
+ NameConstraintRadio[7].checked || NameConstraintRadio[8].checked) {
+ NameConstraintNameDataType.checked = false;
+ return true;
+ }
+ }
+ return true;
+}
+
+
+function addSubAltName(form)
+{
+ with(form) {
+ var len = SubAltNameSelect.length;
+ var value;
+ var i = 0;
+ while(!(i == (SubAltNameRadio.length - 1)) &
+ !(SubAltNameRadio[i].checked == true)) {
+ i++;
+ }
+ if (i != 0) {
+ value = SubAltNameText.value + " - " + (i + 1);
+ } else {
+ value = SubAltNameText.value + " - " +
+ SubAltNameOtherNameOID.value + " - ";
+ if (SubAltNameDataType.checked) {
+ value += "1 - ";
+ } else {
+ value += "0 - ";
+ }
+ value += (i + 1);
+ if (SubAltNameOtherNameOID.value == "") {
+ alert("Other names must include an OID");
+ return false;
+ }
+ }
+
+ if ((SubAltNameText.value == "") | (SubAltNameRadio[i].checked != true)) {
+ alert("Alternative Names must include values for name and name type.");
+ } else {
+ SubAltNameSelect.options[len] = new Option(value, value);
+ }
+ }
+ return true;
+}
+
+function deleteSubAltName(form)
+{
+ with(form) {
+ while (SubAltNameSelect.selectedIndex >= 0) {
+ SubAltNameSelect[SubAltNameSelect.selectedIndex] = null;
+ }
+ }
+}
+
+function addIssuerAltName(form)
+{
+ with(form)
+ {
+ var len = IssuerAltNameSelect.length;
+ var value;
+ var i = 0;
+
+ while(!(i == (IssuerAltNameRadio.length -1)) &
+ !(IssuerAltNameRadio[i].checked == true)) {
+ i++;
+ }
+ if (i != 0) {
+ value = IssuerAltNameText.value + " - " + (i + 1);
+ } else {
+ value = IssuerAltNameText.value + " - " +
+ IssuerAltNameOtherNameOID.value + " - ";
+ if (IssuerAltNameDataType.checked) {
+ value += "1 - ";
+ } else {
+ value += "0 - ";
+ }
+ value += (i + 1);
+ if (IssuerAltNameOtherNameOID.value == "") {
+ alert("Other names must include an OID");
+ return false;
+ }
+ }
+ if ((IssuerAltNameText.value == "") |
+ (IssuerAltNameRadio[i].checked != true)) {
+ alert("Alternative Names must include values for name and name type.")
+ } else {
+ IssuerAltNameSelect.options[len] = new Option(value, value);
+ }
+ }
+ return true;
+}
+
+function deleteIssuerAltName(form)
+{
+ with(form) {
+ while (IssuerAltNameSelect.selectedIndex >= 0) {
+ IssuerAltNameSelect[IssuerAltNameSelect.selectedIndex] = null;
+ }
+ }
+}
+
+
+
+function addNameConstraint(form)
+{
+ with(form) {
+ var len = NameConstraintSelect.length;
+ var value;
+ var i = 0;
+ var min = NameConstraintMin.value;
+ var max = NameConstraintMax.value;
+
+ while(!(i == (NameConstraintRadio.length - 1) ) &
+ !(NameConstraintRadio[i].checked == true)) {
+ i++;
+ }
+ value = NameConstraintText.value + " - ";
+ if (i == 0) {
+ value += NameConstraintOtherNameOID.value + " - ";
+ if (NameConstraintNameDataType.checked) {
+ value += "1 - ";
+ } else {
+ value += "0 - ";
+ }
+ if (NameConstraintOtherNameOID.value == "") {
+ alert("Other names must include an OID");
+ return false;
+ }
+ }
+ value += (i + 1) + " - ";
+ if (NameConstraintTypeRadio[0].checked == true) {
+ value += "p - ";
+ } else {
+ value += "e - ";
+ }
+ value += min + " - " + max;
+ if ((min == "") | (NameConstraintText.value == "") |
+ (NameConstraintRadio[i].checked != true)) {
+ alert("Name Constraints must include values for minimum, name, and name type.")
+ } else {
+ NameConstraintSelect.options[len] = new Option(value, value);
+ }
+ }
+ return true;
+}
+
+function deleteNameConstraint(form)
+{
+ with(form) {
+ while (NameConstraintSelect.selectedIndex >= 0) {
+ NameConstraintSelect[NameConstraintSelect.selectedIndex] = null;
+ }
+ }
+}
+
+
+function submit_it()
+{
+ save_cur_page(cur_page);
+
+ var ver1 = (ver == 1);
+ var ver3 = (ver == 3);
+ var array_string;
+ var serial = ext_page_array[0][10][0];
+ var serial_number = ext_page_array[0][12][0];
+ var manValidity = ext_page_array[0][19][0];
+ var notBefore = ext_page_array[0][20][0];
+ var notAfter = ext_page_array[0][21][0];
+ var subject = ext_page_array[0][22][0];
+
+ if (subject == "") {
+ alert("The DN field must contain some data");
+ return false;
+ }
+ if (!serial & serial_number == "") {
+ alert("No serial number specified");
+ return false;
+ }
+ if (ext_page_array[0][15][0]) {
+ var keygen = "<keygen name=\"key\" challenge=\"foo\">";
+ } else {
+ switch (ext_page_array[0][17][0]) {
+ case 2:
+ var keygen = "<keygen keytype=\"dsa\" pqg=\"MIGdAkEAjfKklEkidqo9JXWbsGhpy+rA2Dr7jQz3y7gyTw14guXQdi/FtyEOr8Lprawyq3qsSWk9+/g3JMLsBzbuMcgCkQIVAMdzIYxzfsjumTtPLe0w9I7azpFfAkEAYm0CeDnqChNBMWOlW0y1ACmdVSKVbO/LO/8Q85nOLC5xy53l+iS6v1jlt5UhklycxC6fb0ZLCIzFcq9T5teIAg==\" name=\"key\" challenge=\"foo\">";
+ break;
+ case 1:
+ var keygen = "<keygen keytype=\"dsa\" pqg=\"MIHaAmDCboVgX0+6pEeMlbwsasWDVBcJNHPKMzkq9kbCRK2U3k+tE15n+Dc2g3ZjDYr1um51e2iLC34/BwAAAAAAAAAAAAAAAAAAAAAAAAABbBhnlFN5Djmt0Mk8cdEBY5H8iPMCFMhUnFtbpjn3EyfH2DjVg3ALh7FtAmA2zWzhpeCwvOTjYnQorlXiv0WcnSiWmaC79CRYkFt5i+UEfRxwP1eNGJBVB1T+CPW6JGd4WhgsqtSf53pn5DEtv++O7lNfXyOhWhb3KaWHYIx8fuAXtioIWkWmpfEIVZA=\" name=\"key\" challenge=\"foo\">";
+ break;
+ case 0:
+ var keygen = "<keygen keytype=\"dsa\" pqg=\"MIIBHAKBgId8SiiWrcdua5zbsBhPkKfFcnHBG7T/bQla7c6OixGjjmSSuq2fJLvMKa579CaxHxLZzZZXIHmAk9poRgWl2GUUkCJ68XSum8OQzDPXPsofcEdeANjw3mIAAAAAAAAAAAAAAAAAAAAAAAAIE+MkW5hguLIQqWvEVi9dMpbNu6OZAhTIA+y3TgyiwA0D8pt686ofaL1IOQKBgAiZQC6UCXztr2iXxJrAC+51gN5oX/R9Thilln9RGegsWnHrdxUOpcm5vAWp1LU8TOXtujE8kqkm3UxIRhUWQORe9IxLANAXmZJqkw9FEVHkxj6Cy9detwT2MyBzSwS6avsf7aLisgHmI/IHSeapJsQ3NQa3rikb6zRiqIV+TVa6\" name=\"key\" challenge=\"foo\">";
+ break;
+ }
+ }
+ array_string = build_array_string();
+ hiddens = "<input type=\"hidden\" name=\"subject\" value=\'" + subject + "\'> \n" +
+ "<input type=\"hidden\" name=\"serial-auto\" value=\"" + serial + "\"> \n" +
+ "<input type=\"hidden\" name=\"serial_value\" value=\"" + serial_number + "\"> \n" +
+ "<input type=\"hidden\" name=\"ver-1\" value=\"" + ver1 + "\"> \n" +
+ "<input type=\"hidden\" name=\"ver-3\" value=\"" + ver3 + "\"> \n" +
+ "<input type=\"hidden\" name=\"notBefore\" value=\"" + notBefore + "\"> \n" +
+ "<input type=\"hidden\" name=\"notAfter\" value=\"" + notAfter + "\"> \n" +
+ "<input type=\"hidden\" name=\"manValidity\" value=\"" + manValidity + "\"> \n" +
+ array_string;
+
+ var good_submit_page =
+ '<html>' +
+ '<BODY TEXT="#000000" LINK="#000000" VLINK="#000000" ALINK="#FF0000" BGCOLOR="#FFFFFF">' +
+ '<form method="post" action="' + script_url + '">' +
+ 'Select size for your key:' + keygen + '</p>' +
+ '<input type="submit"></p>' +
+ hiddens +
+ '</form>\n' +
+ '</body>\n' +
+ '</html>\n';
+
+ window.frames['right'].document.write(good_submit_page);
+ window.frames['right'].document.close();
+ cur_page = max_pages + 1;
+ make_left_frame(window);
+ return false;
+}
+
+
+
+function build_array_string()
+{
+ var pg;
+ var array_string = '';
+ var pages;
+
+ if ((ext_page_array[3][4][0] > 0) && ext_page_array[3][3][0]) {
+ pages = 4 + parseInt(ext_page_array[3][4][0]);
+ } else {
+ pages = 4;
+ }
+ for (pg = 1; pg < pages; pg++) {
+ if ((pg > 1 || (ver == 3)) && (ext_page_array[pg].length > 1)) {
+ if (pg < 4) {
+ for (i = 0; i < ext_page_array[pg].length; i++) {
+ if (ext_page_array[pg][i][3].indexOf("radio") == -1) {
+ if (ext_page_array[pg][i][3].indexOf("multiple") == -1) {
+ array_string += '<input type=\"hidden\" name=\"' +
+ ext_page_array[pg][i][1] + '\" value=\'' +
+ ext_page_array[pg][i][0] + '\'> \n';
+ } else {
+ for (k = 0; k < ext_page_array[pg][i][0].length; k++) {
+ array_string += '<input type=\"hidden\" name=\"' +
+ ext_page_array[pg][i][1] + k + '\" value=\'' +
+ ext_page_array[pg][i][0][k] + '\'> \n';
+ }
+ }
+ } else {
+ array_string += '<input type=\"hidden\" name=\"' +
+ ext_page_array[pg][i][1] + '-' +
+ ext_page_array[pg][i][2] + '\" value=\'' +
+ ext_page_array[pg][i][0] + '\'> \n';
+ }
+ }
+ } else {
+ for (i = 0; i < ext_page_array[pg].length; i++) {
+ if (ext_page_array[pg][i][3].indexOf("radio") == -1) {
+ if (ext_page_array[pg][i][3].indexOf("multiple") == -1) {
+ array_string += '<input type=\"hidden\" name=\"' +
+ 'CA#' + (pg - 3) + '-' +
+ ext_page_array[pg][i][1] + '\" value=\'' +
+ ext_page_array[pg][i][0] +'\'> \n';
+ } else {
+ for (k = 0; k < ext_page_array[pg][i][0].length; k++) {
+ array_string += '<input type=\"hidden\" name=\"' +
+ 'CA#' + (pg - 3) + '-' +
+ ext_page_array[pg][i][1] + k + '\" value=\'' +
+ ext_page_array[pg][i][0][k] + '\'> \n';
+ }
+ }
+ } else {
+ array_string += '<input type=\"hidden\" name=\"' +
+ 'CA#' + (pg - 3) + '-' +
+ ext_page_array[pg][i][1] + '-' +
+ ext_page_array[pg][i][2] + '\" value=\'' +
+ ext_page_array[pg][i][0] + '\'> \n';
+ }
+ }
+ }
+ }
+ }
+ return array_string;
+}
+
+
+
+function init_ext_page_array()
+{
+ for (i = 0; i < max_pages; i++) {
+ ext_page_array[i] = '';
+ }
+}
+
+function ca_num_change(n,ca_form)
+{
+ with(ca_form) {
+ n = parseInt(n,10);
+ if (caChoiceradio[2].checked) {
+ if (n) {
+ update_left_frame(n);
+ } else {
+ update_left_frame(0);
+ }
+ }
+ }
+}
+
+function choice_change(ca_form)
+{
+ with(ca_form) {
+ if (caChoiceradio[2].checked) {
+ ca_num_change(manCAs.value,ca_form);
+ } else {
+ update_left_frame(0);
+ }
+ }
+}
+
+function update_left_frame(n)
+{
+ var add_string = '';
+ for (var i = 0; i < n; i++) {
+ var j = i + 1;
+ add_string = add_string + ',1, \'CA #' + j + '\'';
+ }
+ top.add_index_list = add_string;
+ num_ca = n;
+ make_left_frame(window);
+}
+
+function set_ver1()
+// redraws the extensions page for version 1 certificates
+{
+ ver = 1
+ if (cur_page == 2 || cur_page == 3) {
+ switch_right_frame(window, cur_page, cur_page);
+ }
+}
+
+
+function set_ver3()
+// redraws the extensions page for version 3 certificates
+{
+ ver = 3
+ if (cur_page == 2) {
+ switch_right_frame(window, 0, 2);
+ } else if (cur_page == 3) {
+ switch_right_frame(window, 0, 3);
+ }
+}
+
+function reset_subject(marker, value, form)
+// Updates the subject field from a subordinate field
+{
+ with(form) {
+ var field_sep = '", ';
+ var begin_index = subject.value.indexOf(marker);
+ if (begin_index != 0 && subject.value[begin_index - 1] != ' ') {
+ begin_index = subject.value.indexOf(marker, begin_index +1);
+ }
+ var end_index = subject.value.indexOf(field_sep, begin_index);
+ if (begin_index > -1) { // is it a delete/change?
+ if (end_index == -1) { // is it the last one (includes only one)?
+ if (value.length > 0) { // do I have to change it?
+ if (begin_index == 0) { // is is the only one?
+ subject.value = marker + '"' + value + '"';
+ } else { // it is the last of many
+ subject.value = subject.value.substring(0,begin_index) +
+ marker + '"' + value + '"';
+ }
+ } else { // must be a delete
+ if (begin_index == 0) { // is it the only one?
+ begin_index += 2;
+ }
+ subject.value = subject.value.substring(0,(begin_index - 2));
+ }
+ } else { // it is the first of many or a middle one
+ if (value.length >0) { // do I have to change it?
+ subject.value =
+ subject.value.substring(0,(begin_index + marker.length + 1)) +
+ value + subject.value.substring(end_index,subject.length);
+ } else { // it is a delete
+ subject.value = subject.value.substring(0,begin_index) +
+ subject.value.substring((end_index + 3),subject.length);
+ }
+ }
+ } else { // It is either an insert or a do nothing
+ if (value.length > 0) { // is it an insert?
+ if (subject.value.length == 0) { // is subject currently empty?
+ subject.value = marker + '"' + value + '"';
+ } else {
+ subject.value = subject.value + ', ' + marker + '"' + value + '"';
+ }
+ }
+ }
+ }
+}
+
+
+
+function reset_subjectFields(form)
+// updates all the subordinate fields from the subject field of a form
+// **** move the strings to global variables, to make maintentance easier ****
+{
+
+ update_subject_Field(form, 'CN=\"', form.name);
+ update_subject_Field(form, 'MAIL=\"', form.email);
+ update_subject_Field(form, 'O=\"', form.org);
+ update_subject_Field(form, 'C=\"', form.country);
+ update_subject_Field(form, ' L=\"', form.loc);
+ update_subject_Field(form, 'ST=\"', form.state);
+ update_subject_Field(form, 'E=\"', form.email);
+ update_subject_Field(form, 'OU=\"', form.org_unit);
+ update_subject_Field(form, 'UID=\"', form.uid);
+}
+
+function update_subject_Field(form, marker, update_field)
+//updates a single subordinate field from the subject field of a form
+// *** need to deal with the two types of e-mail addresses **************
+{
+ with(form) {
+ var field_sep = '", ';
+ var begin_index = subject.value.indexOf(marker) + marker.length;
+ var end_index = subject.value.indexOf(field_sep, begin_index);
+ if (end_index == -1) {
+ end_index = subject.value.indexOf('"',begin_index);
+ }
+ if (begin_index != (-1 + marker.length) ) {
+ update_field.value = subject.value.substring(begin_index, end_index);
+ } else {
+ update_field.value = '';
+ }
+ }
+}
+
+
+function switch_mail(form)
+// **** Do I want to delete the other type of e-mail address ? ************
+{
+ if (form.email_type[0].checked) {
+ var del = 'E=';
+ var ins = 'MAIL=';
+ } else {
+ var del = 'MAIL=';
+ var ins = 'E=';
+ }
+ reset_subject(del, '', form);
+ reset_subject(ins, form.email.value, form);
+}
+
+function make_page_intro(title, bgcolor)
+{
+ var style = '<STYLE TYPE="text/css">BODY{' +
+ 'font-family: Geneva,MS Sans Serif,Arial,Lucida,Helvetica,sans-serif;' +
+ 'font-size: 10pt;' +
+ '}' +
+ 'TD{' +
+ 'font-family: Geneva,MS Sans Serif,Arial,Lucida,Helvetica,sans-serif;' +
+ 'font-size: 10pt;}' +
+ '</STYLE>';
+
+ if (bgcolor == null) { bgcolor = "#C0C0C0"; }
+ return '<HTML><HEAD>' +
+ '<TITLE>' + title + '</TITLE>' +
+ '</HEAD>' +
+ '<BODY TEXT="#000000" LINK="#000000" VLINK="#000000" ALINK="#FF0000" ' +
+ 'BGCOLOR="' + bgcolor + '">';
+}
+
+
+function make_left_frame(window)
+{
+ with (window.frames['index']) {
+ eval ('index_string = make_left_frame_page(cur_page, '
+ + index_list + add_index_list + ' )');
+ fool1 = make_page_intro(index_label, "#FFFFFF") +
+ index_string + '</BODY></HTML>';
+ document.write(fool1);
+ document.close();
+ }
+}
+
+
+function save_cur_page(page_number)
+{
+ var len;
+ var pg = page_number - 1;
+ if (window.frames['right'].document.forms.length != 0) {
+ with (window.frames['right'].document) {
+ if ((page_number != 2 && page_number != 3 && page_number <= max_pages) ||
+ ver == 3) {
+ ext_page_array[pg] = new Array(forms[0].elements.length);
+ for (i = 0; i < forms[0].elements.length; i++) {
+ ext_page_array[pg][i] = new Array(4);
+ switch (forms[0].elements[i].type) {
+ case 'radio':
+ case 'checkbox':
+ ext_page_array[pg][i][0] = forms[0].elements[i].checked;
+ break;
+ case 'select-one':
+ ext_page_array[pg][i][0] = forms[0].elements[i].selectedIndex;
+ break;
+ case 'select-multiple':
+ len = forms[0].elements[i].options.length;
+ ext_page_array[pg][i][0] = new Array(len);
+ for(k = 0; k < len; k++) {
+ ext_page_array[pg][i][0][k] = forms[0].elements[i].options[k].value;
+ }
+ break;
+ default:
+ ext_page_array[pg][i][0] = forms[0].elements[i].value;
+ }
+ ext_page_array[pg][i][1] = forms[0].elements[i].name;
+ ext_page_array[pg][i][2] = forms[0].elements[i].value;
+ ext_page_array[pg][i][3] = forms[0].elements[i].type;
+ }
+ }
+ }
+ }
+}
+
+function reload_form(page_number)
+{
+ var j = page_number - 1;
+ with (window.frames['right'].document) {
+ if (((page_number < 2 || page_number > 3) || ver == 3)
+ && page_number != 0 && (ext_page_array[j].length > 1)) {
+ for (i = 0; i < ext_page_array[j].length; i++) {
+ switch (forms[0].elements[i].type) {
+ case 'radio': case 'checkbox':
+ forms[0].elements[i].checked = ext_page_array[j][i][0];
+ break;
+ case 'select-one':
+ forms[0].elements[i].selectedIndex = ext_page_array[j][i][0];
+ break;
+ case 'select-multiple':
+ for (k = 0; k < ext_page_array[j][i][0].length; k++) {
+ forms[0].elements[i].options[k] =
+ new Option(ext_page_array[j][i][0][k],
+ ext_page_array[j][i][0][k]);
+ }
+ break;
+ default:
+ forms[0].elements[i].value = ext_page_array[j][i][0];
+ }
+ }
+ }
+ }
+}
+
+function switch_right_frame(top_window, old_pane, new_pane)
+{
+ var ext_page_stnd =
+ make_page_intro(standard_extensions_index_label, "#FFFFFF") +
+ '<IFRAME WIDTH="100%" HEIGHT="100%" FRAMEBORDER=0 ID="ext" ' +
+ 'SRC="stnd_ext_form.html">' +
+ '</IFRAME></body></html>';
+
+ var ext_page_nscp =
+ make_page_intro(netscape_extensions_index_label, "#FFFFFF") +
+ '<IFRAME WIDTH="100%" HEIGHT="100%" FRAMEBORDER=0 ID="ext" ' +
+ 'SRC="nscp_ext_form.html">' +
+ '</IFRAME></body></html>';
+
+ var ext_page_ca =
+ make_page_intro(certifying_authorities_index_label, "#FFFFFF") +
+ '<IFRAME WIDTH="100%" HEIGHT="100%" FRAMEBORDER=0 ID="ext" ' +
+ 'SRC="ca.html">' +
+ '</IFRAME></body</html>';
+
+ var ext_page_ca_exp =
+ make_page_intro('Certifying Authority Details', "#FFFFFF") +
+ '<IFRAME WIDTH="100%" HEIGHT="100%" FRAMEBORDER=0 ID="ext" ' +
+ 'SRC="ca_form.html">' +
+ '</IFRAME></body></html>';
+
+
+ if (old_pane > 0 && cur_page <= max_pages) {
+ save_cur_page(old_pane);
+ }
+ cur_page = new_pane;
+ make_left_frame(top_window);
+ if (new_pane == 2 || new_pane == 3) {
+ if (ver == 1) {
+ frames['right'].document.write(ext_page_ver1);
+ frames['right'].document.close();
+ } else if (new_pane == 2) {
+ frames['right'].document.write(ext_page_nscp);
+ frames['right'].document.close();
+ reload_form(new_pane);
+ } else {
+ frames['right'].document.write(ext_page_stnd);
+ frames['right'].document.close();
+ reload_form(new_pane);
+ }
+ } else if (new_pane == 4) {
+ frames['right'].document.write(ext_page_ca);
+ frames['right'].document.close();
+ reload_form(new_pane);
+ } else if (new_pane == 1) {
+ frames['right'].document.write(main_page);
+ frames['right'].document.close();
+ reload_form(new_pane);
+ } else {
+ frames['right'].document.write(ext_page_ca_exp);
+ frames['right'].document.close();
+ reload_form(new_pane);
+ }
+}
+
+function make_left_frame_page(selected)
+{
+ var n_strings = ( make_left_frame_page.arguments.length - 1 ) / 2;
+ var table_background;
+ var command;
+ var indent;
+ var label;
+ var ret_string = "";
+
+ ret_string += '<TABLE CELLSPACING=4>';
+ for ( var i = 1; i <= n_strings; i++ ) {
+ if ( i == selected ) {
+ table_background = 'BGCOLOR=#BBCCBB';
+ } else {
+ table_background = '';
+ }
+
+ indent = make_left_frame_page.arguments[(i*2) - 1];
+ label = make_left_frame_page.arguments[(i*2)];
+
+ if ( indent == 0 ) {
+ ret_string += ('<TR><TD COLSPAN=2 ' + table_background + '>');
+ } else {
+ ret_string += ('<TR><TD>&nbsp;&nbsp;</TD><TD ' + table_background + '>');
+ }
+
+ command = "'parent.switch_right_frame(parent," + selected + "," + i + ")'";
+ ret_string += ('<A HREF="javascript:void setTimeout(' + command + ',0)">');
+ if ( indent == 0 ) { ret_string += "<B>"; }
+ ret_string += label;
+ if ( indent == 0 ) { ret_string += "</B>"; }
+ ret_string += '</A></TD></TR>';
+ }
+ if (selected == (max_pages + 1)) {
+ table_background = 'BGCOLOR=#BBCCBB';
+ } else {
+ table_background = '';
+ }
+ ret_string +=
+ '<TR><TD COLSPAN=2 ' + table_background +
+ '><b><A HREF="javascript:void setTimeout(\'top.submit_it()\', 0)">Finish</A></b>' +
+ '</TD></TR>' +
+ '<input type="submit"></form>' +
+ '</TABLE>';
+ return(ret_string);
+}
+
+
+function make_page(window)
+// Draws the initial page setup
+{
+ selected = cur_page
+ init_ext_page_array()
+
+ with (window.frames['right']) {
+ location="main.html";
+// document.write(main_page);
+// document.close();
+ }
+
+ make_left_frame(window);
+
+}
+</script>
+
+</HEAD>
+<title>Cert-O-Matic</title>
+ <FRAMESET cols="150,*" BORDER=3 ONLOAD="make_page(window)">
+ <FRAME SRC="about:blank" ID="index" NAME="index"
+ MARGINWIDTH=15 MARGINHEIGHT=10 BORDER=3>
+ <FRAME SRC="about:blank" ID="right" NAME="right"
+ MARGINWIDTH=15 MARGINHEIGHT=10 BORDER=3>
+ </FRAMESET>
+</HTML>
diff --git a/security/nss/cmd/certcgi/main.html b/security/nss/cmd/certcgi/main.html
new file mode 100644
index 000000000..05dd9daad
--- /dev/null
+++ b/security/nss/cmd/certcgi/main.html
@@ -0,0 +1,76 @@
+<HTML>
+<!-- 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/. -->
+<HEAD>
+ <TITLE>Main Layer for CertOMatic</TITLE>
+</HEAD>
+
+ <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi">
+ <table border=0 cellspacing=10 cellpadding=0>
+ <tr>
+ <td>
+ Common Name:</td><td> <input type="text" name="name" onChange="{window.top.reset_subject('CN=', value, form)}"></p>
+ </td>
+ <td></td><td></td>
+ <td>
+ Organization: </td><td> <input type="text" name="org" onChange="{window.top.reset_subject('O=', value, form)}"></p></td>
+ <tr>
+ <td>
+ <input type="radio" name="email_type" value="1" onClick="window.top.switch_mail(form)">MAIL=
+
+ <input type="radio" name="email_type" value="2" checked onClick="window.top.switch_mail(form)">E=
+ </td>
+ <td>
+ <input type="text" name="email" onChange="var temp;{if (email_type[0].checked) {temp = 'MAIL='} else {temp = 'E='}} ;{window.top.reset_subject(temp, value, form)}">
+ </td>
+ <td></td><td></td><td>
+ Organizational Unit: </td><td><input type="text" name="org_unit" onChange="{window.top.reset_subject('OU=', value, form)}"></p></td>
+ <tr>
+ <td>
+ UID= </td><td><input type="text" name="uid" onChange="{window.top.reset_subject('UID=', value, form)}"></p></td>
+ <td></td><td></td><td>
+ Locality: </td><td><input type="text" name="loc" onChange="{window.top.reset_subject('L=', value, form)}"></p></td>
+ <tr>
+ <td>
+ State or Province: </td><td><input type="text" name="state" onChange="{window.top.reset_subject('ST=', value, form)}"></p></td>
+ <td></td><td></td><td>
+ Country: </td><td><input type="text" size="2" name="country" onChange="{window.top.reset_subject('C=', value, form)}" maxlength="2"></p></td>
+ <tr>
+ <td COLSPAN=2>
+ Serial Number:
+ <DD><input type="radio" name="serial" value="auto" checked> Auto Generate
+ <DD><input type="radio" name="serial" value="input">
+ Use this hex value:&nbsp; <input type="text" name="serial_value" size="8" maxlength="8"></p>
+ </td>
+ <td></td> <td></td>
+ <td COLSPAN=2>
+ X.509 version:
+ <DD><input type="radio" name="ver" value="1" onClick="if (this.checked) {window.top.set_ver1();}"> Version 1
+ <DD><input type="radio" name="ver" value="3" checked onClick="if (this.checked) {window.top.set_ver3();}"> Version 3</P></td>
+ <tr>
+ <td COLSPAN=2>
+ Key Type:
+ <DD><input type="radio" name="keyType" value="rsa" checked> RSA
+ <DD><input type="radio" name="keyType" value="dsa"> DSA</p>
+ Intermediate CA Key Sizes:
+ <DD><select name="keysize">
+ <option>2048 (Very High Grade)
+ <option>1024 (High Grade)
+ <option>512 (Low Grade)
+ </select>
+ </td>
+ <td></td> <td></td>
+ <td COLSPAN=2>
+ Validity:
+ <DD><input type="radio" name="validity" value="auto" checked>
+ Generate Automatically
+ <DD><input type="radio" name="validity" value="man"> Use these values:
+ <DD>Not Before:&nbsp; <input type="text" size="15" maxlength="17" name="notBefore">
+ <DD>Not After:&nbsp;&nbsp;&nbsp; <input type="text" size="15" maxlength="17" name="notAfter">
+ <DD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ <FONT SIZE=-1><TT>YYMMDDhhmm[ss]{Z|+hhmm|-hhmm} </TT></FONT>
+ </table>
+ DN: <input type="text" name="subject" size="70" onChange="{window.top.reset_subjectFields(form)}"></P>
+ </form>
+</HTML>
diff --git a/security/nss/cmd/certcgi/manifest.mn b/security/nss/cmd/certcgi/manifest.mn
new file mode 100644
index 000000000..9e17cef9d
--- /dev/null
+++ b/security/nss/cmd/certcgi/manifest.mn
@@ -0,0 +1,22 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIREd.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = certcgi.c
+
+PROGRAM = certcgi
+
+USE_STATIC_LIBS = 1
+
diff --git a/security/nss/cmd/certcgi/nscp_ext_form.html b/security/nss/cmd/certcgi/nscp_ext_form.html
new file mode 100644
index 000000000..f2a4a20c3
--- /dev/null
+++ b/security/nss/cmd/certcgi/nscp_ext_form.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<!-- 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/. -->
+
+ <body>
+ <table border=1 cellspacing=5 cellpadding=5>
+ <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi">
+ <tr>
+ <td>
+ <b>Netscape Certificate Type: </b></p>
+ Activate extension: <input type="checkbox" name="netscape-cert-type"></P>
+ Critical: <input type="checkbox" name="netscape-cert-type-crit">
+ <td>
+ <input type="checkbox" name="netscape-cert-type-ssl-client"> SSL Client</P>
+ <input type="checkbox" name="netscape-cert-type-ssl-server"> SSL Server</P>
+ <input type="checkbox" name="netscape-cert-type-smime"> S/MIME</P>
+ <input type="checkbox" name="netscape-cert-type-object-signing"> Object Signing</P>
+ <input type="checkbox" name="netscape-cert-type-reserved"> Reserved for future use (bit 4)</P>
+ <input type="checkbox" name="netscape-cert-type-ssl-ca"> SSL CA</P>
+ <input type="checkbox" name="netscape-cert-type-smime-ca"> S/MIME CA</P>
+ <input type="checkbox" name="netscape-cert-type-object-signing-ca"> Object Signing CA</P>
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Base URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-base-url"></P>
+ Critical: <input type="checkbox" name="netscape-base-url-crit">
+ <td>
+ <input type="text" name="netscape-base-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Revocation URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-revocation-url"></P>
+ Critical: <input type="checkbox" name="netscape-revocation-url-crit">
+ <td>
+ <input type="text" name="netscape-revocation-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape CA Revocation URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-ca-revocation-url"></P>
+ Critical: <input type="checkbox" name="netscape-ca-revocation-url-crit">
+ <td>
+ <input type="text" name="netscape-ca-revocation-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Certificate Renewal URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-cert-renewal-url"></P>
+ Critical: <input type="checkbox" name="netscape-cert-renewal-url-crit">
+ <td>
+ <input type="text" name="netscape-cert-renewal-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape CA Policy URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-ca-policy-url"></P>
+ Critical: <input type="checkbox" name="netscape-ca-policy-url-crit">
+ <td>
+ <input type="text" name="netscape-ca-policy-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape SSL Server Name:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-ssl-server-name"></P>
+ Critical: <input type="checkbox" name="netscape-ssl-server-name-crit">
+ <td>
+ <input type="text" name="netscape-ssl-server-name-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Comment:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-comment"></P>
+ Critical: <input type="checkbox" name="netscape-comment-crit">
+ <td>
+ <textarea name="netscape-comment-text" rows="5" cols="50"></textarea>
+ </tr>
+
+ </table>
+ </body>
+</html>
diff --git a/security/nss/cmd/certcgi/stnd_ext_form.html b/security/nss/cmd/certcgi/stnd_ext_form.html
new file mode 100644
index 000000000..60d4d86a0
--- /dev/null
+++ b/security/nss/cmd/certcgi/stnd_ext_form.html
@@ -0,0 +1,219 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<!-- 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/. -->
+
+ <body>
+ <table border=1 cellspacing=5 cellpadding=5>
+ <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi">
+ <tr>
+ <td>
+ <b>Key Usage: </b></p>
+ Activate extension: <input type="checkbox" name="keyUsage"></P>
+ Critical: <input type="checkbox" name="keyUsage-crit">
+ <td>
+ <input type="checkbox" name="keyUsage-digitalSignature"> Digital Signature</P>
+ <input type="checkbox" name="keyUsage-nonRepudiation"> Non Repudiation</P>
+ <input type="checkbox" name="keyUsage-keyEncipherment"> Key Encipherment</P>
+ <input type="checkbox" name="keyUsage-dataEncipherment"> Data Encipherment</P>
+ <input type="checkbox" name="keyUsage-keyAgreement"> Key Agreement</P>
+ <input type="checkbox" name="keyUsage-keyCertSign"> Key Certificate Signing</P>
+ <input type="checkbox" name="keyUsage-cRLSign"> CRL Signing</P>
+ </tr>
+ <tr>
+ <td>
+ <b>Extended Key Usage: </b></p>
+ Activate extension: <input type="checkbox" name="extKeyUsage"></P>
+ Critical: <input type="checkbox" name="extKeyUsage-crit">
+ <td>
+ <input type="checkbox" name="extKeyUsage-serverAuth"> Server Auth</P>
+ <input type="checkbox" name="extKeyUsage-clientAuth"> Client Auth</P>
+ <input type="checkbox" name="extKeyUsage-codeSign"> Code Signing</P>
+ <input type="checkbox" name="extKeyUsage-emailProtect"> Email Protection</P>
+ <input type="checkbox" name="extKeyUsage-timeStamp"> Timestamp</P>
+ <input type="checkbox" name="extKeyUsage-ocspResponder"> OCSP Responder</P>
+ <input type="checkbox" name="extKeyUsage-NS-govtApproved"> Step-up</P>
+ <input type="checkbox" name="extKeyUsage-msTrustListSign"> Microsoft Trust List Signing</P>
+ </tr>
+ <tr>
+ <td>
+ <b>Basic Constraints:</b></p>
+ Activate extension: <input type="checkbox" name="basicConstraints"></P>
+ Critical: <input type="checkbox" name="basicConstraints-crit">
+ <td>
+ CA:</p>
+ <dd><input type=radio name="basicConstraints-cA-radio" value="CA"> True</p>
+ <dd><input type=radio name="basicConstraints-cA-radio" value="NotCA"> False</p>
+ <input type="checkbox" name="basicConstraints-pathLengthConstraint">
+ Include Path length: <input type="text" name="basicConstraints-pathLengthConstraint-text" size="2"></p>
+ </tr>
+ <tr>
+ <td>
+ <b>Authority Key Identifier:</b></p>
+ Activate extension: <input type="checkbox" name="authorityKeyIdentifier">
+ <td>
+ <input type="radio" name="authorityKeyIdentifier-radio" value="keyIdentifier"> Key Identider</p>
+ <input type="radio" name="authorityKeyIdentifier-radio" value="authorityCertIssuer"> Issuer Name and Serial number</p>
+ </tr>
+ <tr>
+ <td>
+ <b>Subject Key Identifier:</b></p>
+ Activate extension: <input type="checkbox" name="subjectKeyIdentifier">
+ <td>
+ Key Identifier:
+ <input type="text" name="subjectKeyIdentifier-text"></p>
+ This is an:<p>
+ <dd><dd><input type="radio" name="subjectKeyIdentifier-radio" value="ascii"> ascii text value<p>
+ <dd><dd><input type="radio" name="subjectKeyIdentifier-radio" value="hex"> hex value<p>
+ </tr>
+ <tr>
+ <td>
+ <b>Private Key Usage Period:</b></p>
+ Activate extension: <input type="checkbox" name="privKeyUsagePeriod"></p>
+ Critical: <input type="checkbox" name="privKeyUsagePeriod-crit">
+ <td>
+ Use:</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-radio" value="notBefore"> Not Before</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-radio" value="notAfter"> Not After</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-radio" value="both" > Both</p>
+ <b>Not to be used to sign before:</b></p>
+ <dd><input type="radio" name="privKeyUsagePeriod-notBefore-radio" value="auto"> Set to time of certificate issue</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-notBefore-radio" value="manual"> Use This value</p>
+ <dd><dd>(YYYY/MM/DD HH:MM:SS):
+ <input type="text" name="privKeyUsagePeriod-notBefore-year" size="4" maxlength="4">/
+ <input type="text" name="privKeyUsagePeriod-notBefore-month" size="2" maxlength="2">/
+ <input type="text" name="privKeyUsagePeriod-notBefore-day" size="2" maxlength="2">
+ <input type="text" name="privKeyUsagePeriod-notBefore-hour" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notBefore-minute" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notBefore-second" size="2" maxlength="2"></p>
+ <b>Not to be used to sign after:</b></p>
+ <dd>(YYYY/MM/DD HH:MM:SS):
+ <input type="text" name="privKeyUsagePeriod-notAfter-year" size="4" maxlength="4">/
+ <input type="text" name="privKeyUsagePeriod-notAfter-month" size="2" maxlength="2">/
+ <input type="text" name="privKeyUsagePeriod-notAfter-day" size="2" maxlength="2">
+ <input type="text" name="privKeyUsagePeriod-notAfter-hour" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notAfter-minute" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notAfter-second" size="2" maxlength="2"></p>
+ </tr>
+ <tr>
+ <td>
+ <b>Subject Alternative Name:</b></p>
+ Activate extension: <input type="checkbox" name="SubAltName"></P>
+ Critical: <input type="checkbox" name="SubAltName-crit">
+ <td>
+ <table>
+ <tr>
+ <td>
+ General Names:</p>
+ <select name="SubAltNameSelect" multiple size="10">
+ </select></p></p>
+ <input type="button" name="SubAltName-add" value="Add" onClick="{parent.addSubAltName(this.form)}">
+ <input type="button" name="SubAltName-delete" value="Delete" onClick="parent.deleteSubAltName(this.form)">
+ </td><td>
+ <table><tr><td>
+ Name Type: </td></tr><tr><td>
+ <input type="radio" name="SubAltNameRadio" value="otherName" onClick="parent.setSubAltNameType(form)"> Other Name,
+ OID: <input type="text" name="SubAltNameOtherNameOID" size="6"> </td><td>
+ <input type="radio" name="SubAltNameRadio" value="rfc822Name" onClick="parent.setSubAltNameType(form)"> RFC 822 Name</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="dnsName" onClick="parent.setSubAltNameType(form)"> DNS Name </td><td>
+ <input type="radio" name="SubAltNameRadio" value="x400" onClick="parent.setSubAltNameType(form)"> X400 Address</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="directoryName" onClick="parent.setSubAltNameType(form)"> Directory Name</td><td>
+ <input type="radio" name="SubAltNameRadio" value="ediPartyName" onClick="parent.setSubAltNameType(form)"> EDI Party Name</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="URL" onClick="parent.setSubAltNameType(form)"> Uniform Resource Locator</td><td>
+ <input type="radio" name="SubAltNameRadio" value="ipAddress" onClick="parent.setSubAltNameType(form)"> IP Address</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="regID"onClick="parent.setSubAltNameType(form)"> Registered ID</td><td>
+ <input type="radio" name="SubAltNameRadio" value="nscpNickname" onClick="parent.setSubAltNameType(form)"> Netscape Certificate Nickname</td><td></tr>
+ </table>
+ Name: <input type="text" name="SubAltNameText">
+ Binary Encoded: <input type="checkbox" name="SubAltNameDataType" value="binary" onClick="parent.setSubAltNameType(form)"></p>
+ </tr>
+ </table>
+ </tr>
+
+
+ <tr>
+ <td>
+ <b>Issuer Alternative Name:</b></p>
+ Activate extension: <input type="checkbox" name="IssuerAltName"></P>
+ Critical: <input type="checkbox" name="IssuerAltName-crit">
+ <td>
+ <input type="radio" name="IssuerAltNameSourceRadio" value="auto"> Use the Subject Alternative Name from the Issuers Certificate</p>
+ <input type="radio" name="IssuerAltNameSourceRadio" value="man"> Use this Name:
+ <table>
+ <tr>
+ <td>
+ General Names:</p>
+ <select name="IssuerAltNameSelect" multiple size="10">
+ </select></p></p>
+ <input type="button" name="IssuerAltName-add" value="Add" onClick="{parent.addIssuerAltName(this.form)}">
+ <input type="button" name="IssuerAltName-delete" value="Delete" onClick="parent.deleteIssuerAltName(this.form)">
+ </td><td>
+ <table><tr><td>
+ Name Type: </td></tr><tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="otherName" onClick="parent.setIssuerAltNameType(form)"> Other Name,
+ OID: <input type="text" name="IssuerAltNameOtherNameOID" size="6"> </td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="rfc822Name" onClick="parent.setIssuerAltNameType(form)"> RFC 822 Name</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="dnsName" onClick="parent.setIssuerAltNameType(form)"> DNS Name </td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="x400" onClick="parent.setIssuerAltNameType(form)"> X400 Address</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="directoryName" onClick="parent.setIssuerAltNameType(form)"> Directory Name</td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="ediPartyName" onClick="parent.setIssuerAltNameType(form)"> EDI Party Name</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="URL" onClick="parent.setIssuerAltNameType(form)"> Uniform Resource Locator</td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="ipAddress" onClick="parent.setIssuerAltNameType(form)"> IP Address</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="regID" onClick="parent.setIssuerAltNameType(form)"> Registered ID</td><td></tr>
+ </table>
+ Name: <input type="text" name="IssuerAltNameText">
+ Binary Encoded: <input type="checkbox" name="IssuerAltNameDataType" value="binary" onClick="parent.setIssuerAltNameType(form)"></p>
+ </tr>
+ </table>
+ </tr>
+
+ <tr>
+ <td>
+ <b>Name Constraints:</b></p>
+ Activate extension: <input type="checkbox" name="NameConstraints"></P>
+ <td>
+ <table>
+ <tr>
+ <td>
+ Name Constraints:</p>
+ <select name="NameConstraintSelect" multiple size="10">
+ </select></p></p>
+ <input type="button" name="NameConstraint-add" value="Add" onClick="{parent.addNameConstraint(this.form)}">
+ <input type="button" name="NameConstraint-delete" value="Delete" onClick="parent.deleteNameConstraint(this.form)">
+ </td><td>
+ <table><tr><td>
+ Name Type: </td></tr><tr><td>
+ <input type="radio" name="NameConstraintRadio" value="otherName" onClick="parent.setNameConstraintNameType(form)"> Other Name,
+ OID: <input type="text" name="NameConstraintOtherNameOID" size="6"> </td><td>
+ <input type="radio" name="NameConstraintRadio" value="rfc822Name" onClick="parent.setNameConstraintNameType(form)"> RFC 822 Name</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="dnsName" onClick="parent.setNameConstraintNameType(form)"> DNS Name </td><td>
+ <input type="radio" name="NameConstraintRadio" value="x400" onClick="parent.setNameConstraintNameType(form)"> X400 Address</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="directoryName" onClick="parent.setNameConstraintNameType(form)"> Directory Name</td><td>
+ <input type="radio" name="NameConstraintRadio" value="ediPartyName" onClick="parent.setNameConstraintNameType(form)"> EDI Party Name</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="URL" onClick="parent.setNameConstraintNameType(form)"> Uniform Resource Locator</td><td>
+ <input type="radio" name="NameConstraintRadio" value="ipAddress" onClick="parent.setNameConstraintNameType(form)"> IP Address</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="regID" onClick="parent.setNameConstraintNameType(form)"> Registered ID</td><td></tr>
+ </table>
+ Name: <input type="text" name="NameConstraintText">
+ Binary Encoded: <input type="checkbox" name="NameConstraintNameDataType" value="binary" onClick="parent.setNameConstraintNameType(form)"></p>
+ Constraint type:<p>
+ <dd><input type="radio" name="NameConstraintTypeRadio" value="permited"> permited<p>
+ <dd><input type="radio" name="NameConstraintTypeRadio" value="excluded"> excluded<p>
+ Minimum: <input type="text" name="NameConstraintMin" size="8" maxlength="8"></p>
+ Maximum: <input type="text" name="NameConstraintMax" size="8" maxlength="8"></p>
+ </tr>
+ </table>
+ </tr>
+
+ </table>
+ </body>
+</html>
+
+
+
+
+
+
+
+
diff --git a/security/nss/cmd/certutil/Makefile b/security/nss/cmd/certutil/Makefile
new file mode 100644
index 000000000..74ae20020
--- /dev/null
+++ b/security/nss/cmd/certutil/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/certutil/certext.c b/security/nss/cmd/certutil/certext.c
new file mode 100644
index 000000000..b080f06f9
--- /dev/null
+++ b/security/nss/cmd/certutil/certext.c
@@ -0,0 +1,2218 @@
+/* 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/. */
+
+/*
+** certext.c
+**
+** part of certutil for managing certificates extensions
+**
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if defined(WIN32)
+#include "fcntl.h"
+#include "io.h"
+#endif
+
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "cert.h"
+#include "xconst.h"
+#include "prprf.h"
+#include "certutil.h"
+#include "genname.h"
+#include "prnetdb.h"
+
+#define GEN_BREAK(e) \
+ rv = e; \
+ break;
+
+static char *
+Gets_s(char *buff, size_t size)
+{
+ char *str;
+
+ if (buff == NULL || size < 1) {
+ PORT_Assert(0);
+ return NULL;
+ }
+ if ((str = fgets(buff, size, stdin)) != NULL) {
+ int len = PORT_Strlen(str);
+ /*
+ * fgets() automatically converts native text file
+ * line endings to '\n'. As defensive programming
+ * (just in case fgets has a bug or we put stdin in
+ * binary mode by mistake), we handle three native
+ * text file line endings here:
+ * '\n' Unix (including Linux and Mac OS X)
+ * '\r''\n' DOS/Windows & OS/2
+ * '\r' Mac OS Classic
+ * len can not be less then 1, since in case with
+ * empty string it has at least '\n' in the buffer
+ */
+ if (buff[len - 1] == '\n' || buff[len - 1] == '\r') {
+ buff[len - 1] = '\0';
+ if (len > 1 && buff[len - 2] == '\r')
+ buff[len - 2] = '\0';
+ }
+ } else {
+ buff[0] = '\0';
+ }
+ return str;
+}
+
+static SECStatus
+PrintChoicesAndGetAnswer(char *str, char *rBuff, int rSize)
+{
+ fputs(str, stdout);
+ fputs(" > ", stdout);
+ fflush(stdout);
+ if (Gets_s(rBuff, rSize) == NULL) {
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+static CERTGeneralName *
+GetGeneralName(PLArenaPool *arena, CERTGeneralName *useExistingName, PRBool onlyOne)
+{
+ CERTGeneralName *namesList = NULL;
+ CERTGeneralName *current;
+ CERTGeneralName *tail = NULL;
+ SECStatus rv = SECSuccess;
+ int intValue;
+ char buffer[512];
+ void *mark;
+
+ PORT_Assert(arena);
+ mark = PORT_ArenaMark(arena);
+ do {
+ if (PrintChoicesAndGetAnswer(
+ "\nSelect one of the following general name type: \n"
+ "\t2 - rfc822Name\n"
+ "\t3 - dnsName\n"
+ "\t5 - directoryName\n"
+ "\t7 - uniformResourceidentifier\n"
+ "\t8 - ipAddress\n"
+ "\t9 - registerID\n"
+ "\tAny other number to finish\n"
+ "\t\tChoice:",
+ buffer, sizeof(buffer)) == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+ intValue = PORT_Atoi(buffer);
+ /*
+ * Should use ZAlloc instead of Alloc to avoid problem with garbage
+ * initialized pointers in CERT_CopyName
+ */
+ switch (intValue) {
+ case certRFC822Name:
+ case certDNSName:
+ case certDirectoryName:
+ case certURI:
+ case certIPAddress:
+ case certRegisterID:
+ break;
+ default:
+ intValue = 0; /* force a break for anything else */
+ }
+
+ if (intValue == 0)
+ break;
+
+ if (namesList == NULL) {
+ if (useExistingName) {
+ namesList = current = tail = useExistingName;
+ } else {
+ namesList = current = tail =
+ PORT_ArenaZNew(arena, CERTGeneralName);
+ }
+ } else {
+ current = PORT_ArenaZNew(arena, CERTGeneralName);
+ }
+ if (current == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+
+ current->type = intValue;
+ puts("\nEnter data:");
+ fflush(stdout);
+ if (Gets_s(buffer, sizeof(buffer)) == NULL) {
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ GEN_BREAK(SECFailure);
+ }
+ switch (current->type) {
+ case certURI:
+ case certDNSName:
+ case certRFC822Name:
+ current->name.other.data =
+ PORT_ArenaAlloc(arena, strlen(buffer));
+ if (current->name.other.data == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+ PORT_Memcpy(current->name.other.data, buffer,
+ current->name.other.len = strlen(buffer));
+ break;
+
+ case certEDIPartyName:
+ case certIPAddress:
+ case certOtherName:
+ case certRegisterID:
+ case certX400Address: {
+
+ current->name.other.data =
+ PORT_ArenaAlloc(arena, strlen(buffer) + 2);
+ if (current->name.other.data == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+
+ PORT_Memcpy(current->name.other.data + 2, buffer,
+ strlen(buffer));
+ /* This may not be accurate for all cases. For now,
+ * use this tag type */
+ current->name.other.data[0] =
+ (char)(((current->type - 1) & 0x1f) | 0x80);
+ current->name.other.data[1] = (char)strlen(buffer);
+ current->name.other.len = strlen(buffer) + 2;
+ break;
+ }
+
+ case certDirectoryName: {
+ CERTName *directoryName = NULL;
+
+ directoryName = CERT_AsciiToName(buffer);
+ if (!directoryName) {
+ fprintf(stderr, "certutil: improperly formatted name: "
+ "\"%s\"\n",
+ buffer);
+ break;
+ }
+
+ rv = CERT_CopyName(arena, &current->name.directoryName,
+ directoryName);
+ CERT_DestroyName(directoryName);
+
+ break;
+ }
+ }
+ if (rv != SECSuccess)
+ break;
+ current->l.next = &(namesList->l);
+ current->l.prev = &(tail->l);
+ tail->l.next = &(current->l);
+ tail = current;
+
+ } while (!onlyOne);
+
+ if (rv != SECSuccess) {
+ PORT_ArenaRelease(arena, mark);
+ namesList = NULL;
+ }
+ return (namesList);
+}
+
+static CERTGeneralName *
+CreateGeneralName(PLArenaPool *arena)
+{
+ return GetGeneralName(arena, NULL, PR_FALSE);
+}
+
+static SECStatus
+GetString(PLArenaPool *arena, char *prompt, SECItem *value)
+{
+ char buffer[251];
+ char *buffPrt;
+
+ buffer[0] = '\0';
+ value->data = NULL;
+ value->len = 0;
+
+ puts(prompt);
+ buffPrt = Gets_s(buffer, sizeof(buffer));
+ /* returned NULL here treated the same way as empty string */
+ if (buffPrt && strlen(buffer) > 0) {
+ value->data = PORT_ArenaAlloc(arena, strlen(buffer));
+ if (value->data == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return (SECFailure);
+ }
+ PORT_Memcpy(value->data, buffer, value->len = strlen(buffer));
+ }
+ return (SECSuccess);
+}
+
+static PRBool
+GetYesNo(char *prompt)
+{
+ char buf[3];
+ char *buffPrt;
+
+ buf[0] = 'n';
+ puts(prompt);
+ buffPrt = Gets_s(buf, sizeof(buf));
+ return (buffPrt && (buf[0] == 'y' || buf[0] == 'Y')) ? PR_TRUE : PR_FALSE;
+}
+
+/* Parses comma separated values out of the string pointed by nextPos.
+ * Parsed value is compared to an array of possible values(valueArray).
+ * If match is found, a value index is returned, otherwise returns SECFailue.
+ * nextPos is set to the token after found comma separator or to NULL.
+ * NULL in nextPos should be used as indication of the last parsed token.
+ * A special value "critical" can be parsed out from the supplied sting.*/
+
+static SECStatus
+parseNextCmdInput(const char *const *valueArray, int *value, char **nextPos,
+ PRBool *critical)
+{
+ char *thisPos;
+ int keyLen = 0;
+ int arrIndex = 0;
+
+ if (!valueArray || !value || !nextPos || !critical) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ thisPos = *nextPos;
+ while (1) {
+ if ((*nextPos = strchr(thisPos, ',')) == NULL) {
+ keyLen = strlen(thisPos);
+ } else {
+ keyLen = *nextPos - thisPos;
+ *nextPos += 1;
+ }
+ /* if critical keyword is found, go for another loop,
+ * but check, if it is the last keyword of
+ * the string.*/
+ if (!strncmp("critical", thisPos, keyLen)) {
+ *critical = PR_TRUE;
+ if (*nextPos == NULL) {
+ return SECSuccess;
+ }
+ thisPos = *nextPos;
+ continue;
+ }
+ break;
+ }
+ for (arrIndex = 0; valueArray[arrIndex]; arrIndex++) {
+ if (!strncmp(valueArray[arrIndex], thisPos, keyLen)) {
+ *value = arrIndex;
+ return SECSuccess;
+ }
+ }
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+}
+
+static const char *const
+ keyUsageKeyWordArray[] = { "digitalSignature",
+ "nonRepudiation",
+ "keyEncipherment",
+ "dataEncipherment",
+ "keyAgreement",
+ "certSigning",
+ "crlSigning",
+ NULL };
+
+static SECStatus
+AddKeyUsage(void *extHandle, const char *userSuppliedValue)
+{
+ SECItem bitStringValue;
+ unsigned char keyUsage = 0x0;
+ char buffer[5];
+ int value;
+ char *nextPos = (char *)userSuppliedValue;
+ PRBool isCriticalExt = PR_FALSE;
+
+ if (!userSuppliedValue) {
+ while (1) {
+ if (PrintChoicesAndGetAnswer(
+ "\t\t0 - Digital Signature\n"
+ "\t\t1 - Non-repudiation\n"
+ "\t\t2 - Key encipherment\n"
+ "\t\t3 - Data encipherment\n"
+ "\t\t4 - Key agreement\n"
+ "\t\t5 - Cert signing key\n"
+ "\t\t6 - CRL signing key\n"
+ "\t\tOther to finish\n",
+ buffer, sizeof(buffer)) == SECFailure) {
+ return SECFailure;
+ }
+ value = PORT_Atoi(buffer);
+ if (value < 0 || value > 6)
+ break;
+ if (value == 0) {
+ /* Checking that zero value of variable 'value'
+ * corresponds to '0' input made by user */
+ char *chPtr = strchr(buffer, '0');
+ if (chPtr == NULL) {
+ continue;
+ }
+ }
+ keyUsage |= (0x80 >> value);
+ }
+ isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
+ } else {
+ while (1) {
+ if (parseNextCmdInput(keyUsageKeyWordArray, &value, &nextPos,
+ &isCriticalExt) == SECFailure) {
+ return SECFailure;
+ }
+ keyUsage |= (0x80 >> value);
+ if (!nextPos)
+ break;
+ }
+ }
+
+ bitStringValue.data = &keyUsage;
+ bitStringValue.len = 1;
+
+ return (CERT_EncodeAndAddBitStrExtension(extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
+ isCriticalExt));
+}
+
+static CERTOidSequence *
+CreateOidSequence(void)
+{
+ CERTOidSequence *rv = (CERTOidSequence *)NULL;
+ PLArenaPool *arena = (PLArenaPool *)NULL;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ((PLArenaPool *)NULL == arena) {
+ goto loser;
+ }
+
+ rv = (CERTOidSequence *)PORT_ArenaZNew(arena, CERTOidSequence);
+ if ((CERTOidSequence *)NULL == rv) {
+ goto loser;
+ }
+
+ rv->oids = (SECItem **)PORT_ArenaZNew(arena, SECItem *);
+ if ((SECItem **)NULL == rv->oids) {
+ goto loser;
+ }
+
+ rv->arena = arena;
+ return rv;
+
+loser:
+ if ((PLArenaPool *)NULL != arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return (CERTOidSequence *)NULL;
+}
+
+static void
+DestroyOidSequence(CERTOidSequence *os)
+{
+ if (os->arena) {
+ PORT_FreeArena(os->arena, PR_FALSE);
+ }
+}
+
+static SECStatus
+AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
+{
+ SECItem **oids;
+ PRUint32 count = 0;
+ SECOidData *od;
+
+ od = SECOID_FindOIDByTag(oidTag);
+ if ((SECOidData *)NULL == od) {
+ return SECFailure;
+ }
+
+ for (oids = os->oids; (SECItem *)NULL != *oids; oids++) {
+ if (*oids == &od->oid) {
+ /* We already have this oid */
+ return SECSuccess;
+ }
+ count++;
+ }
+
+ /* ArenaZRealloc */
+
+ {
+ PRUint32 i;
+
+ oids = (SECItem **)PORT_ArenaZNewArray(os->arena, SECItem *, count + 2);
+ if ((SECItem **)NULL == oids) {
+ return SECFailure;
+ }
+
+ for (i = 0; i < count; i++) {
+ oids[i] = os->oids[i];
+ }
+
+ /* ArenaZFree(os->oids); */
+ }
+
+ os->oids = oids;
+ os->oids[count] = &od->oid;
+
+ return SECSuccess;
+}
+
+SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
+
+const SEC_ASN1Template CERT_OidSeqTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, offsetof(CERTOidSequence, oids),
+ SEC_ASN1_SUB(SEC_ObjectIDTemplate) }
+};
+
+static SECItem *
+EncodeOidSequence(CERTOidSequence *os)
+{
+ SECItem *rv;
+
+ rv = (SECItem *)PORT_ArenaZNew(os->arena, SECItem);
+ if ((SECItem *)NULL == rv) {
+ goto loser;
+ }
+
+ if (!SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate)) {
+ goto loser;
+ }
+
+ return rv;
+
+loser:
+ return (SECItem *)NULL;
+}
+
+static const char *const
+ extKeyUsageKeyWordArray[] = { "serverAuth",
+ "clientAuth",
+ "codeSigning",
+ "emailProtection",
+ "timeStamp",
+ "ocspResponder",
+ "stepUp",
+ "msTrustListSigning",
+ NULL };
+
+static SECStatus
+AddExtKeyUsage(void *extHandle, const char *userSuppliedValue)
+{
+ char buffer[5];
+ int value;
+ CERTOidSequence *os;
+ SECStatus rv;
+ SECItem *item;
+ PRBool isCriticalExt = PR_FALSE;
+ char *nextPos = (char *)userSuppliedValue;
+
+ os = CreateOidSequence();
+ if ((CERTOidSequence *)NULL == os) {
+ return SECFailure;
+ }
+
+ while (1) {
+ if (!userSuppliedValue) {
+ if (PrintChoicesAndGetAnswer(
+ "\t\t0 - Server Auth\n"
+ "\t\t1 - Client Auth\n"
+ "\t\t2 - Code Signing\n"
+ "\t\t3 - Email Protection\n"
+ "\t\t4 - Timestamp\n"
+ "\t\t5 - OCSP Responder\n"
+ "\t\t6 - Step-up\n"
+ "\t\t7 - Microsoft Trust List Signing\n"
+ "\t\tOther to finish\n",
+ buffer, sizeof(buffer)) == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+ value = PORT_Atoi(buffer);
+
+ if (value == 0) {
+ /* Checking that zero value of variable 'value'
+ * corresponds to '0' input made by user */
+ char *chPtr = strchr(buffer, '0');
+ if (chPtr == NULL) {
+ continue;
+ }
+ }
+ } else {
+ if (parseNextCmdInput(extKeyUsageKeyWordArray, &value, &nextPos,
+ &isCriticalExt) == SECFailure) {
+ return SECFailure;
+ }
+ }
+
+ switch (value) {
+ case 0:
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
+ break;
+ case 1:
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
+ break;
+ case 2:
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
+ break;
+ case 3:
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
+ break;
+ case 4:
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
+ break;
+ case 5:
+ rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER);
+ break;
+ case 6:
+ rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
+ break;
+ case 7:
+ rv = AddOidToSequence(os, SEC_OID_MS_EXT_KEY_USAGE_CTL_SIGNING);
+ break;
+ default:
+ goto endloop;
+ }
+
+ if (userSuppliedValue && !nextPos)
+ break;
+ if (SECSuccess != rv)
+ goto loser;
+ }
+
+endloop:
+ item = EncodeOidSequence(os);
+
+ if (!userSuppliedValue) {
+ isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
+ }
+
+ rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, item,
+ isCriticalExt, PR_TRUE);
+/*FALLTHROUGH*/
+loser:
+ DestroyOidSequence(os);
+ return rv;
+}
+
+static const char *const
+ nsCertTypeKeyWordArray[] = { "sslClient",
+ "sslServer",
+ "smime",
+ "objectSigning",
+ "Not!Used",
+ "sslCA",
+ "smimeCA",
+ "objectSigningCA",
+ NULL };
+
+static SECStatus
+AddNscpCertType(void *extHandle, const char *userSuppliedValue)
+{
+ SECItem bitStringValue;
+ unsigned char keyUsage = 0x0;
+ char buffer[5];
+ int value;
+ char *nextPos = (char *)userSuppliedValue;
+ PRBool isCriticalExt = PR_FALSE;
+
+ if (!userSuppliedValue) {
+ while (1) {
+ if (PrintChoicesAndGetAnswer(
+ "\t\t0 - SSL Client\n"
+ "\t\t1 - SSL Server\n"
+ "\t\t2 - S/MIME\n"
+ "\t\t3 - Object Signing\n"
+ "\t\t4 - Reserved for future use\n"
+ "\t\t5 - SSL CA\n"
+ "\t\t6 - S/MIME CA\n"
+ "\t\t7 - Object Signing CA\n"
+ "\t\tOther to finish\n",
+ buffer, sizeof(buffer)) == SECFailure) {
+ return SECFailure;
+ }
+ value = PORT_Atoi(buffer);
+ if (value < 0 || value > 7)
+ break;
+ if (value == 0) {
+ /* Checking that zero value of variable 'value'
+ * corresponds to '0' input made by user */
+ char *chPtr = strchr(buffer, '0');
+ if (chPtr == NULL) {
+ continue;
+ }
+ }
+ keyUsage |= (0x80 >> value);
+ }
+ isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
+ } else {
+ while (1) {
+ if (parseNextCmdInput(nsCertTypeKeyWordArray, &value, &nextPos,
+ &isCriticalExt) == SECFailure) {
+ return SECFailure;
+ }
+ keyUsage |= (0x80 >> value);
+ if (!nextPos)
+ break;
+ }
+ }
+
+ bitStringValue.data = &keyUsage;
+ bitStringValue.len = 1;
+
+ return (CERT_EncodeAndAddBitStrExtension(extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
+ isCriticalExt));
+}
+
+SECStatus
+GetOidFromString(PLArenaPool *arena, SECItem *to,
+ const char *from, size_t fromLen)
+{
+ SECStatus rv;
+ SECOidTag tag;
+ SECOidData *coid;
+
+ /* try dotted form first */
+ rv = SEC_StringToOID(arena, to, from, fromLen);
+ if (rv == SECSuccess) {
+ return rv;
+ }
+
+ /* Check to see if it matches a name in our oid table.
+ * SECOID_FindOIDByTag returns NULL if tag is out of bounds.
+ */
+ tag = SEC_OID_UNKNOWN;
+ coid = SECOID_FindOIDByTag(tag);
+ for (; coid; coid = SECOID_FindOIDByTag(++tag)) {
+ if (PORT_Strncasecmp(from, coid->desc, fromLen) == 0) {
+ break;
+ }
+ }
+ if (coid == NULL) {
+ /* none found */
+ return SECFailure;
+ }
+ return SECITEM_CopyItem(arena, to, &coid->oid);
+}
+
+static SECStatus
+AddSubjectAltNames(PLArenaPool *arena, CERTGeneralName **existingListp,
+ const char *constNames, CERTGeneralNameType type)
+{
+ CERTGeneralName *nameList = NULL;
+ CERTGeneralName *current = NULL;
+ PRCList *prev = NULL;
+ char *cp, *nextName = NULL;
+ SECStatus rv = SECSuccess;
+ PRBool readTypeFromName = (PRBool)(type == 0);
+ char *names = NULL;
+
+ if (constNames)
+ names = PORT_Strdup(constNames);
+
+ if (names == NULL) {
+ return SECFailure;
+ }
+
+ /*
+ * walk down the comma separated list of names. NOTE: there is
+ * no sanity checks to see if the email address look like
+ * email addresses.
+ *
+ * Each name may optionally be prefixed with a type: string.
+ * If it isn't, the type from the previous name will be used.
+ * If there wasn't a previous name yet, the type given
+ * as a parameter to this function will be used.
+ * If the type value is zero (undefined), we'll fail.
+ */
+ for (cp = names; cp; cp = nextName) {
+ int len;
+ char *oidString;
+ char *nextComma;
+ CERTName *name;
+ PRStatus status;
+ unsigned char *data;
+ PRNetAddr addr;
+
+ nextName = NULL;
+ if (*cp == ',') {
+ cp++;
+ }
+ nextComma = PORT_Strchr(cp, ',');
+ if (nextComma) {
+ *nextComma = 0;
+ nextName = nextComma + 1;
+ }
+ if ((*cp) == 0) {
+ continue;
+ }
+ if (readTypeFromName) {
+ char *save = cp;
+ /* Because we already replaced nextComma with end-of-string,
+ * a found colon belongs to the current name */
+ cp = PORT_Strchr(cp, ':');
+ if (cp) {
+ *cp = 0;
+ cp++;
+ type = CERT_GetGeneralNameTypeFromString(save);
+ if (*cp == 0) {
+ continue;
+ }
+ } else {
+ if (type == 0) {
+ /* no type known yet */
+ rv = SECFailure;
+ break;
+ }
+ cp = save;
+ }
+ }
+
+ current = PORT_ArenaZNew(arena, CERTGeneralName);
+ if (!current) {
+ rv = SECFailure;
+ break;
+ }
+
+ current->type = type;
+ switch (type) {
+ /* string types */
+ case certRFC822Name:
+ case certDNSName:
+ case certURI:
+ current->name.other.data =
+ (unsigned char *)PORT_ArenaStrdup(arena, cp);
+ current->name.other.len = PORT_Strlen(cp);
+ break;
+ /* unformated data types */
+ case certX400Address:
+ case certEDIPartyName:
+ /* turn a string into a data and len */
+ rv = SECFailure; /* punt on these for now */
+ fprintf(stderr, "EDI Party Name and X.400 Address not supported\n");
+ break;
+ case certDirectoryName:
+ /* certDirectoryName */
+ name = CERT_AsciiToName(cp);
+ if (name == NULL) {
+ rv = SECFailure;
+ fprintf(stderr, "Invalid Directory Name (\"%s\")\n", cp);
+ break;
+ }
+ rv = CERT_CopyName(arena, &current->name.directoryName, name);
+ CERT_DestroyName(name);
+ break;
+ /* types that require more processing */
+ case certIPAddress:
+ /* convert the string to an ip address */
+ status = PR_StringToNetAddr(cp, &addr);
+ if (status != PR_SUCCESS) {
+ rv = SECFailure;
+ fprintf(stderr, "Invalid IP Address (\"%s\")\n", cp);
+ break;
+ }
+
+ if (PR_NetAddrFamily(&addr) == PR_AF_INET) {
+ len = sizeof(addr.inet.ip);
+ data = (unsigned char *)&addr.inet.ip;
+ } else if (PR_NetAddrFamily(&addr) == PR_AF_INET6) {
+ len = sizeof(addr.ipv6.ip);
+ data = (unsigned char *)&addr.ipv6.ip;
+ } else {
+ fprintf(stderr, "Invalid IP Family\n");
+ rv = SECFailure;
+ break;
+ }
+ current->name.other.data = PORT_ArenaAlloc(arena, len);
+ if (current->name.other.data == NULL) {
+ rv = SECFailure;
+ break;
+ }
+ current->name.other.len = len;
+ PORT_Memcpy(current->name.other.data, data, len);
+ break;
+ case certRegisterID:
+ rv = GetOidFromString(arena, &current->name.other, cp, strlen(cp));
+ break;
+ case certOtherName:
+ oidString = cp;
+ cp = PORT_Strchr(cp, ';');
+ if (cp == NULL) {
+ rv = SECFailure;
+ fprintf(stderr, "missing name in other name\n");
+ break;
+ }
+ *cp++ = 0;
+ current->name.OthName.name.data =
+ (unsigned char *)PORT_ArenaStrdup(arena, cp);
+ if (current->name.OthName.name.data == NULL) {
+ rv = SECFailure;
+ break;
+ }
+ current->name.OthName.name.len = PORT_Strlen(cp);
+ rv = GetOidFromString(arena, &current->name.OthName.oid,
+ oidString, strlen(oidString));
+ break;
+ default:
+ rv = SECFailure;
+ fprintf(stderr, "Missing or invalid Subject Alternate Name type\n");
+ break;
+ }
+ if (rv == SECFailure) {
+ break;
+ }
+
+ if (prev) {
+ current->l.prev = prev;
+ prev->next = &(current->l);
+ } else {
+ nameList = current;
+ }
+ prev = &(current->l);
+ }
+ PORT_Free(names);
+ /* at this point nameList points to the head of a doubly linked,
+ * but not yet circular, list and current points to its tail. */
+ if (rv == SECSuccess && nameList) {
+ if (*existingListp != NULL) {
+ PRCList *existingprev;
+ /* add nameList to the end of the existing list */
+ existingprev = (*existingListp)->l.prev;
+ (*existingListp)->l.prev = &(current->l);
+ nameList->l.prev = existingprev;
+ existingprev->next = &(nameList->l);
+ current->l.next = &((*existingListp)->l);
+ } else {
+ /* make nameList circular and set it as the new existingList */
+ nameList->l.prev = prev;
+ current->l.next = &(nameList->l);
+ *existingListp = nameList;
+ }
+ }
+ return rv;
+}
+
+static SECStatus
+AddEmailSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
+ const char *emailAddrs)
+{
+ return AddSubjectAltNames(arena, existingListp, emailAddrs,
+ certRFC822Name);
+}
+
+static SECStatus
+AddDNSSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
+ const char *dnsNames)
+{
+ return AddSubjectAltNames(arena, existingListp, dnsNames, certDNSName);
+}
+
+static SECStatus
+AddGeneralSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
+ const char *altNames)
+{
+ return AddSubjectAltNames(arena, existingListp, altNames, 0);
+}
+
+static SECStatus
+AddBasicConstraint(PLArenaPool *arena, void *extHandle)
+{
+ CERTBasicConstraints basicConstraint;
+ SECStatus rv;
+ char buffer[10];
+ PRBool yesNoAns;
+
+ do {
+ basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
+ basicConstraint.isCA = GetYesNo("Is this a CA certificate [y/N]?");
+
+ buffer[0] = '\0';
+ if (PrintChoicesAndGetAnswer("Enter the path length constraint, "
+ "enter to skip [<0 for unlimited path]:",
+ buffer, sizeof(buffer)) == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+ if (PORT_Strlen(buffer) > 0)
+ basicConstraint.pathLenConstraint = PORT_Atoi(buffer);
+
+ yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
+
+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
+ &basicConstraint, yesNoAns, SEC_OID_X509_BASIC_CONSTRAINTS,
+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeBasicConstraintValue);
+ } while (0);
+
+ return (rv);
+}
+
+static SECStatus
+AddNameConstraints(void *extHandle)
+{
+ PLArenaPool *arena = NULL;
+ CERTNameConstraints *constraints = NULL;
+
+ CERTNameConstraint *current = NULL;
+ CERTNameConstraint *last_permited = NULL;
+ CERTNameConstraint *last_excluded = NULL;
+ SECStatus rv = SECSuccess;
+
+ char buffer[512];
+ int intValue = 0;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena) {
+ constraints = PORT_ArenaZNew(arena, CERTNameConstraints);
+ }
+
+ if (!arena || !constraints) {
+ SECU_PrintError(progName, "out of memory");
+ PORT_FreeArena(arena, PR_FALSE);
+ return SECFailure;
+ }
+
+ constraints->permited = constraints->excluded = NULL;
+
+ do {
+ current = PORT_ArenaZNew(arena, CERTNameConstraint);
+ if (!current) {
+ GEN_BREAK(SECFailure);
+ }
+
+ (void)SEC_ASN1EncodeInteger(arena, &current->min, 0);
+
+ if (!GetGeneralName(arena, &current->name, PR_TRUE)) {
+ GEN_BREAK(SECFailure);
+ }
+
+ if (PrintChoicesAndGetAnswer("Type of Name Constraint?\n"
+ "\t1 - permitted\n\t2 - excluded\n\tAny"
+ "other number to finish\n\tChoice",
+ buffer, sizeof(buffer)) !=
+ SECSuccess) {
+ GEN_BREAK(SECFailure);
+ }
+
+ intValue = PORT_Atoi(buffer);
+ switch (intValue) {
+ case 1:
+ if (constraints->permited == NULL) {
+ constraints->permited = last_permited = current;
+ }
+ last_permited->l.next = &(current->l);
+ current->l.prev = &(last_permited->l);
+ last_permited = current;
+ break;
+ case 2:
+ if (constraints->excluded == NULL) {
+ constraints->excluded = last_excluded = current;
+ }
+ last_excluded->l.next = &(current->l);
+ current->l.prev = &(last_excluded->l);
+ last_excluded = current;
+ break;
+ }
+
+ PR_snprintf(buffer, sizeof(buffer), "Add another entry to the"
+ " Name Constraint Extension [y/N]");
+
+ if (GetYesNo(buffer) == 0) {
+ break;
+ }
+
+ } while (1);
+
+ if (rv == SECSuccess) {
+ int oidIdent = SEC_OID_X509_NAME_CONSTRAINTS;
+
+ PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
+
+ if (constraints->permited != NULL) {
+ last_permited->l.next = &(constraints->permited->l);
+ constraints->permited->l.prev = &(last_permited->l);
+ }
+ if (constraints->excluded != NULL) {
+ last_excluded->l.next = &(constraints->excluded->l);
+ constraints->excluded->l.prev = &(last_excluded->l);
+ }
+
+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, constraints,
+ yesNoAns, oidIdent,
+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeNameConstraintsExtension);
+ }
+ if (arena)
+ PORT_FreeArena(arena, PR_FALSE);
+ return (rv);
+}
+
+static SECStatus
+AddAuthKeyID(void *extHandle)
+{
+ CERTAuthKeyID *authKeyID = NULL;
+ PLArenaPool *arena = NULL;
+ SECStatus rv = SECSuccess;
+ PRBool yesNoAns;
+
+ do {
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ SECU_PrintError(progName, "out of memory");
+ GEN_BREAK(SECFailure);
+ }
+
+ if (GetYesNo("Enter value for the authKeyID extension [y/N]?") == 0)
+ break;
+
+ authKeyID = PORT_ArenaZNew(arena, CERTAuthKeyID);
+ if (authKeyID == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+
+ rv = GetString(arena, "Enter value for the key identifier fields,"
+ "enter to omit:",
+ &authKeyID->keyID);
+ if (rv != SECSuccess)
+ break;
+
+ SECU_SECItemHexStringToBinary(&authKeyID->keyID);
+
+ authKeyID->authCertIssuer = CreateGeneralName(arena);
+ if (authKeyID->authCertIssuer == NULL &&
+ SECFailure == PORT_GetError())
+ break;
+
+ rv = GetString(arena, "Enter value for the authCertSerial field, "
+ "enter to omit:",
+ &authKeyID->authCertSerialNumber);
+
+ yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
+
+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
+ authKeyID, yesNoAns, SEC_OID_X509_AUTH_KEY_ID,
+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeAuthKeyID);
+ if (rv)
+ break;
+
+ } while (0);
+ if (arena)
+ PORT_FreeArena(arena, PR_FALSE);
+ return (rv);
+}
+
+static SECStatus
+AddSubjKeyID(void *extHandle)
+{
+ SECItem keyID;
+ PLArenaPool *arena = NULL;
+ SECStatus rv = SECSuccess;
+ PRBool yesNoAns;
+
+ do {
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ SECU_PrintError(progName, "out of memory");
+ GEN_BREAK(SECFailure);
+ }
+ printf("Adding Subject Key ID extension.\n");
+
+ rv = GetString(arena, "Enter value for the key identifier fields,"
+ "enter to omit:",
+ &keyID);
+ if (rv != SECSuccess)
+ break;
+
+ SECU_SECItemHexStringToBinary(&keyID);
+
+ yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
+
+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
+ &keyID, yesNoAns, SEC_OID_X509_SUBJECT_KEY_ID,
+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeSubjectKeyID);
+ if (rv)
+ break;
+
+ } while (0);
+ if (arena)
+ PORT_FreeArena(arena, PR_FALSE);
+ return (rv);
+}
+
+static SECStatus
+AddCrlDistPoint(void *extHandle)
+{
+ PLArenaPool *arena = NULL;
+ CERTCrlDistributionPoints *crlDistPoints = NULL;
+ CRLDistributionPoint *current;
+ SECStatus rv = SECSuccess;
+ int count = 0, intValue;
+ char buffer[512];
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena)
+ return (SECFailure);
+
+ do {
+ current = NULL;
+
+ current = PORT_ArenaZNew(arena, CRLDistributionPoint);
+ if (current == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+
+ /* Get the distributionPointName fields - this field is optional */
+ if (PrintChoicesAndGetAnswer(
+ "Enter the type of the distribution point name:\n"
+ "\t1 - Full Name\n\t2 - Relative Name\n\tAny other "
+ "number to finish\n\t\tChoice: ",
+ buffer, sizeof(buffer)) == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+ intValue = PORT_Atoi(buffer);
+ switch (intValue) {
+ case generalName:
+ current->distPointType = intValue;
+ current->distPoint.fullName = CreateGeneralName(arena);
+ rv = PORT_GetError();
+ break;
+
+ case relativeDistinguishedName: {
+ CERTName *name;
+
+ current->distPointType = intValue;
+ puts("Enter the relative name: ");
+ fflush(stdout);
+ if (Gets_s(buffer, sizeof(buffer)) == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+ /* For simplicity, use CERT_AsciiToName to converse from a string
+ to NAME, but we only interest in the first RDN */
+ name = CERT_AsciiToName(buffer);
+ if (!name) {
+ GEN_BREAK(SECFailure);
+ }
+ rv = CERT_CopyRDN(arena, &current->distPoint.relativeName,
+ name->rdns[0]);
+ CERT_DestroyName(name);
+ break;
+ }
+ }
+ if (rv != SECSuccess)
+ break;
+
+ /* Get the reason flags */
+ if (PrintChoicesAndGetAnswer(
+ "\nSelect one of the following for the reason flags\n"
+ "\t0 - unused\n\t1 - keyCompromise\n"
+ "\t2 - caCompromise\n\t3 - affiliationChanged\n"
+ "\t4 - superseded\n\t5 - cessationOfOperation\n"
+ "\t6 - certificateHold\n"
+ "\tAny other number to finish\t\tChoice: ",
+ buffer, sizeof(buffer)) == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+ intValue = PORT_Atoi(buffer);
+ if (intValue == 0) {
+ /* Checking that zero value of variable 'value'
+ * corresponds to '0' input made by user */
+ char *chPtr = strchr(buffer, '0');
+ if (chPtr == NULL) {
+ intValue = -1;
+ }
+ }
+ if (intValue >= 0 && intValue < 8) {
+ current->reasons.data = PORT_ArenaAlloc(arena, sizeof(char));
+ if (current->reasons.data == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+ *current->reasons.data = (char)(0x80 >> intValue);
+ current->reasons.len = 1;
+ }
+ puts("Enter value for the CRL Issuer name:\n");
+ current->crlIssuer = CreateGeneralName(arena);
+ if (current->crlIssuer == NULL && (rv = PORT_GetError()) == SECFailure)
+ break;
+
+ if (crlDistPoints == NULL) {
+ crlDistPoints = PORT_ArenaZNew(arena, CERTCrlDistributionPoints);
+ if (crlDistPoints == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+ }
+
+ if (crlDistPoints->distPoints) {
+ crlDistPoints->distPoints =
+ PORT_ArenaGrow(arena, crlDistPoints->distPoints,
+ sizeof(*crlDistPoints->distPoints) * count,
+ sizeof(*crlDistPoints->distPoints) * (count + 1));
+ } else {
+ crlDistPoints->distPoints =
+ PORT_ArenaZAlloc(arena, sizeof(*crlDistPoints->distPoints) * (count + 1));
+ }
+ if (crlDistPoints->distPoints == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+
+ crlDistPoints->distPoints[count] = current;
+ ++count;
+ if (GetYesNo("Enter another value for the CRLDistributionPoint "
+ "extension [y/N]?") == 0) {
+ /* Add null to the end to mark end of data */
+ crlDistPoints->distPoints =
+ PORT_ArenaGrow(arena, crlDistPoints->distPoints,
+ sizeof(*crlDistPoints->distPoints) * count,
+ sizeof(*crlDistPoints->distPoints) * (count + 1));
+ crlDistPoints->distPoints[count] = NULL;
+ break;
+ }
+
+ } while (1);
+
+ if (rv == SECSuccess) {
+ PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
+
+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
+ crlDistPoints, yesNoAns, SEC_OID_X509_CRL_DIST_POINTS,
+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeCRLDistributionPoints);
+ }
+ if (arena)
+ PORT_FreeArena(arena, PR_FALSE);
+ return (rv);
+}
+
+static SECStatus
+AddPolicyConstraints(void *extHandle)
+{
+ CERTCertificatePolicyConstraints *policyConstr;
+ PLArenaPool *arena = NULL;
+ SECStatus rv = SECSuccess;
+ SECItem *item, *dummy;
+ char buffer[512];
+ int value;
+ PRBool yesNoAns;
+ PRBool skipExt = PR_TRUE;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ SECU_PrintError(progName, "out of memory");
+ return SECFailure;
+ }
+
+ policyConstr = PORT_ArenaZNew(arena, CERTCertificatePolicyConstraints);
+ if (policyConstr == NULL) {
+ SECU_PrintError(progName, "out of memory");
+ goto loser;
+ }
+
+ if (PrintChoicesAndGetAnswer("for requireExplicitPolicy enter the number "
+ "of certs in path\nbefore explicit policy is required\n"
+ "(press Enter to omit)",
+ buffer, sizeof(buffer)) == SECFailure) {
+ goto loser;
+ }
+
+ if (PORT_Strlen(buffer)) {
+ value = PORT_Atoi(buffer);
+ if (value < 0) {
+ goto loser;
+ }
+ item = &policyConstr->explicitPolicySkipCerts;
+ dummy = SEC_ASN1EncodeInteger(arena, item, value);
+ if (!dummy) {
+ goto loser;
+ }
+ skipExt = PR_FALSE;
+ }
+
+ if (PrintChoicesAndGetAnswer("for inihibitPolicyMapping enter "
+ "the number of certs in path\n"
+ "after which policy mapping is not allowed\n"
+ "(press Enter to omit)",
+ buffer, sizeof(buffer)) == SECFailure) {
+ goto loser;
+ }
+
+ if (PORT_Strlen(buffer)) {
+ value = PORT_Atoi(buffer);
+ if (value < 0) {
+ goto loser;
+ }
+ item = &policyConstr->inhibitMappingSkipCerts;
+ dummy = SEC_ASN1EncodeInteger(arena, item, value);
+ if (!dummy) {
+ goto loser;
+ }
+ skipExt = PR_FALSE;
+ }
+
+ if (!skipExt) {
+ yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
+
+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, policyConstr,
+ yesNoAns, SEC_OID_X509_POLICY_CONSTRAINTS,
+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodePolicyConstraintsExtension);
+ } else {
+ fprintf(stdout, "Policy Constraint extensions must contain "
+ "at least one policy field\n");
+ rv = SECFailure;
+ }
+
+loser:
+ if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ return (rv);
+}
+
+static SECStatus
+AddInhibitAnyPolicy(void *extHandle)
+{
+ CERTCertificateInhibitAny certInhibitAny;
+ PLArenaPool *arena = NULL;
+ SECStatus rv = SECSuccess;
+ SECItem *item, *dummy;
+ char buffer[10];
+ int value;
+ PRBool yesNoAns;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ SECU_PrintError(progName, "out of memory");
+ return SECFailure;
+ }
+
+ if (PrintChoicesAndGetAnswer("Enter the number of certs in the path "
+ "permitted to use anyPolicy.\n"
+ "(press Enter for 0)",
+ buffer, sizeof(buffer)) == SECFailure) {
+ goto loser;
+ }
+
+ item = &certInhibitAny.inhibitAnySkipCerts;
+ value = PORT_Atoi(buffer);
+ if (value < 0) {
+ goto loser;
+ }
+ dummy = SEC_ASN1EncodeInteger(arena, item, value);
+ if (!dummy) {
+ goto loser;
+ }
+
+ yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
+
+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &certInhibitAny,
+ yesNoAns, SEC_OID_X509_INHIBIT_ANY_POLICY,
+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeInhibitAnyExtension);
+loser:
+ if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ return (rv);
+}
+
+static SECStatus
+AddPolicyMappings(void *extHandle)
+{
+ CERTPolicyMap **policyMapArr = NULL;
+ CERTPolicyMap *current;
+ PLArenaPool *arena = NULL;
+ SECStatus rv = SECSuccess;
+ int count = 0;
+ char buffer[512];
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ SECU_PrintError(progName, "out of memory");
+ return SECFailure;
+ }
+
+ do {
+ if (PrintChoicesAndGetAnswer("Enter an Object Identifier (dotted "
+ "decimal format) for Issuer Domain Policy",
+ buffer, sizeof(buffer)) == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+
+ current = PORT_ArenaZNew(arena, CERTPolicyMap);
+ if (current == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+
+ rv = SEC_StringToOID(arena, &current->issuerDomainPolicy, buffer, 0);
+ if (rv == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+
+ if (PrintChoicesAndGetAnswer("Enter an Object Identifier for "
+ "Subject Domain Policy",
+ buffer, sizeof(buffer)) == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+
+ rv = SEC_StringToOID(arena, &current->subjectDomainPolicy, buffer, 0);
+ if (rv == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+
+ if (policyMapArr == NULL) {
+ policyMapArr = PORT_ArenaZNew(arena, CERTPolicyMap *);
+ if (policyMapArr == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+ }
+
+ policyMapArr = PORT_ArenaGrow(arena, policyMapArr,
+ sizeof(current) * count,
+ sizeof(current) * (count + 1));
+ if (policyMapArr == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+
+ policyMapArr[count] = current;
+ ++count;
+
+ if (!GetYesNo("Enter another Policy Mapping [y/N]")) {
+ /* Add null to the end to mark end of data */
+ policyMapArr = PORT_ArenaGrow(arena, policyMapArr,
+ sizeof(current) * count,
+ sizeof(current) * (count + 1));
+ if (policyMapArr == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+ policyMapArr[count] = NULL;
+ break;
+ }
+
+ } while (1);
+
+ if (rv == SECSuccess) {
+ CERTCertificatePolicyMappings mappings;
+ PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
+
+ mappings.arena = arena;
+ mappings.policyMaps = policyMapArr;
+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &mappings,
+ yesNoAns, SEC_OID_X509_POLICY_MAPPINGS,
+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodePolicyMappingExtension);
+ }
+ if (arena)
+ PORT_FreeArena(arena, PR_FALSE);
+ return (rv);
+}
+
+enum PoliciQualifierEnum {
+ cpsPointer = 1,
+ userNotice = 2
+};
+
+static CERTPolicyQualifier **
+RequestPolicyQualifiers(PLArenaPool *arena, SECItem *policyID)
+{
+ CERTPolicyQualifier **policyQualifArr = NULL;
+ CERTPolicyQualifier *current;
+ SECStatus rv = SECSuccess;
+ int count = 0;
+ char buffer[512];
+ void *mark;
+ SECOidData *oid = NULL;
+ int intValue = 0;
+ int inCount = 0;
+
+ PORT_Assert(arena);
+ mark = PORT_ArenaMark(arena);
+ do {
+ current = PORT_ArenaZNew(arena, CERTPolicyQualifier);
+ if (current == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+
+ /* Get the accessMethod fields */
+ SECU_PrintObjectID(stdout, policyID,
+ "Choose the type of qualifier for policy", 0);
+
+ if (PrintChoicesAndGetAnswer(
+ "\t1 - CPS Pointer qualifier\n"
+ "\t2 - User notice qualifier\n"
+ "\tAny other number to finish\n"
+ "\t\tChoice: ",
+ buffer, sizeof(buffer)) == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+ intValue = PORT_Atoi(buffer);
+ switch (intValue) {
+ case cpsPointer: {
+ SECItem input;
+
+ oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CPS_POINTER_QUALIFIER);
+ if (PrintChoicesAndGetAnswer("Enter CPS pointer URI: ",
+ buffer, sizeof(buffer)) == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+ input.len = PORT_Strlen(buffer);
+ input.data = (void *)PORT_ArenaStrdup(arena, buffer);
+ if (input.data == NULL ||
+ SEC_ASN1EncodeItem(arena, &current->qualifierValue, &input,
+ SEC_ASN1_GET(SEC_IA5StringTemplate)) == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+ break;
+ }
+ case userNotice: {
+ SECItem **noticeNumArr;
+ CERTUserNotice *notice = PORT_ArenaZNew(arena, CERTUserNotice);
+ if (!notice) {
+ GEN_BREAK(SECFailure);
+ }
+
+ oid = SECOID_FindOIDByTag(SEC_OID_PKIX_USER_NOTICE_QUALIFIER);
+
+ if (GetYesNo("\t add a User Notice reference? [y/N]")) {
+
+ if (PrintChoicesAndGetAnswer("Enter user organization string: ",
+ buffer, sizeof(buffer)) ==
+ SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+
+ notice->noticeReference.organization.type = siAsciiString;
+ notice->noticeReference.organization.len =
+ PORT_Strlen(buffer);
+ notice->noticeReference.organization.data =
+ (void *)PORT_ArenaStrdup(arena, buffer);
+
+ noticeNumArr = PORT_ArenaZNewArray(arena, SECItem *, 2);
+ if (!noticeNumArr) {
+ GEN_BREAK(SECFailure);
+ }
+
+ do {
+ SECItem *noticeNum;
+
+ noticeNum = PORT_ArenaZNew(arena, SECItem);
+
+ if (PrintChoicesAndGetAnswer(
+ "Enter User Notice reference number "
+ "(or -1 to quit): ",
+ buffer, sizeof(buffer)) == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+
+ intValue = PORT_Atoi(buffer);
+ if (noticeNum == NULL) {
+ if (intValue < 0) {
+ fprintf(stdout, "a noticeReference must have at "
+ "least one reference number\n");
+ GEN_BREAK(SECFailure);
+ }
+ } else {
+ if (intValue >= 0) {
+ noticeNumArr = PORT_ArenaGrow(arena, noticeNumArr,
+ sizeof(current) *
+ inCount,
+ sizeof(current) *
+ (inCount + 1));
+ if (noticeNumArr == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+ } else {
+ break;
+ }
+ }
+ if (!SEC_ASN1EncodeInteger(arena, noticeNum, intValue)) {
+ GEN_BREAK(SECFailure);
+ }
+ noticeNumArr[inCount++] = noticeNum;
+ noticeNumArr[inCount] = NULL;
+
+ } while (1);
+ if (rv == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+ notice->noticeReference.noticeNumbers = noticeNumArr;
+ rv = CERT_EncodeNoticeReference(arena, &notice->noticeReference,
+ &notice->derNoticeReference);
+ if (rv == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+ }
+ if (GetYesNo("\t EnterUser Notice explicit text? [y/N]")) {
+ /* Getting only 200 bytes - RFC limitation */
+ if (PrintChoicesAndGetAnswer(
+ "\t", buffer, 200) == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+ notice->displayText.type = siAsciiString;
+ notice->displayText.len = PORT_Strlen(buffer);
+ notice->displayText.data =
+ (void *)PORT_ArenaStrdup(arena, buffer);
+ if (notice->displayText.data == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+ }
+
+ rv = CERT_EncodeUserNotice(arena, notice, &current->qualifierValue);
+ if (rv == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+
+ break;
+ }
+ }
+ if (rv == SECFailure || oid == NULL ||
+ SECITEM_CopyItem(arena, &current->qualifierID, &oid->oid) ==
+ SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+
+ if (!policyQualifArr) {
+ policyQualifArr = PORT_ArenaZNew(arena, CERTPolicyQualifier *);
+ } else {
+ policyQualifArr = PORT_ArenaGrow(arena, policyQualifArr,
+ sizeof(current) * count,
+ sizeof(current) * (count + 1));
+ }
+ if (policyQualifArr == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+
+ policyQualifArr[count] = current;
+ ++count;
+
+ if (!GetYesNo("Enter another policy qualifier [y/N]")) {
+ /* Add null to the end to mark end of data */
+ policyQualifArr = PORT_ArenaGrow(arena, policyQualifArr,
+ sizeof(current) * count,
+ sizeof(current) * (count + 1));
+ if (policyQualifArr == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+ policyQualifArr[count] = NULL;
+ break;
+ }
+
+ } while (1);
+
+ if (rv != SECSuccess) {
+ PORT_ArenaRelease(arena, mark);
+ policyQualifArr = NULL;
+ }
+ return (policyQualifArr);
+}
+
+static SECStatus
+AddCertPolicies(void *extHandle)
+{
+ CERTPolicyInfo **certPoliciesArr = NULL;
+ CERTPolicyInfo *current;
+ PLArenaPool *arena = NULL;
+ SECStatus rv = SECSuccess;
+ int count = 0;
+ char buffer[512];
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ SECU_PrintError(progName, "out of memory");
+ return SECFailure;
+ }
+
+ do {
+ current = PORT_ArenaZNew(arena, CERTPolicyInfo);
+ if (current == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+
+ if (PrintChoicesAndGetAnswer("Enter a CertPolicy Object Identifier "
+ "(dotted decimal format)\n"
+ "or \"any\" for AnyPolicy:",
+ buffer, sizeof(buffer)) == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+
+ if (strncmp(buffer, "any", 3) == 0) {
+ /* use string version of X509_CERTIFICATE_POLICIES.anyPolicy */
+ strcpy(buffer, "OID.2.5.29.32.0");
+ }
+ rv = SEC_StringToOID(arena, &current->policyID, buffer, 0);
+
+ if (rv == SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+
+ current->policyQualifiers =
+ RequestPolicyQualifiers(arena, &current->policyID);
+
+ if (!certPoliciesArr) {
+ certPoliciesArr = PORT_ArenaZNew(arena, CERTPolicyInfo *);
+ } else {
+ certPoliciesArr = PORT_ArenaGrow(arena, certPoliciesArr,
+ sizeof(current) * count,
+ sizeof(current) * (count + 1));
+ }
+ if (certPoliciesArr == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+
+ certPoliciesArr[count] = current;
+ ++count;
+
+ if (!GetYesNo("Enter another PolicyInformation field [y/N]?")) {
+ /* Add null to the end to mark end of data */
+ certPoliciesArr = PORT_ArenaGrow(arena, certPoliciesArr,
+ sizeof(current) * count,
+ sizeof(current) * (count + 1));
+ if (certPoliciesArr == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+ certPoliciesArr[count] = NULL;
+ break;
+ }
+
+ } while (1);
+
+ if (rv == SECSuccess) {
+ CERTCertificatePolicies policies;
+ PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
+
+ policies.arena = arena;
+ policies.policyInfos = certPoliciesArr;
+
+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &policies,
+ yesNoAns, SEC_OID_X509_CERTIFICATE_POLICIES,
+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeCertPoliciesExtension);
+ }
+ if (arena)
+ PORT_FreeArena(arena, PR_FALSE);
+ return (rv);
+}
+
+enum AuthInfoAccessTypesEnum {
+ caIssuers = 1,
+ ocsp = 2
+};
+
+enum SubjInfoAccessTypesEnum {
+ caRepository = 1,
+ timeStamping = 2
+};
+
+/* Encode and add an AIA or SIA extension */
+static SECStatus
+AddInfoAccess(void *extHandle, PRBool addSIAExt, PRBool isCACert)
+{
+ CERTAuthInfoAccess **infoAccArr = NULL;
+ CERTAuthInfoAccess *current;
+ PLArenaPool *arena = NULL;
+ SECStatus rv = SECSuccess;
+ int count = 0;
+ char buffer[512];
+ SECOidData *oid = NULL;
+ int intValue = 0;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ SECU_PrintError(progName, "out of memory");
+ return SECFailure;
+ }
+
+ do {
+ current = NULL;
+ current = PORT_ArenaZNew(arena, CERTAuthInfoAccess);
+ if (current == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+
+ /* Get the accessMethod fields */
+ if (addSIAExt) {
+ if (isCACert) {
+ puts("Adding \"CA Repository\" access method type for "
+ "Subject Information Access extension:\n");
+ intValue = caRepository;
+ } else {
+ puts("Adding \"Time Stamping Services\" access method type for "
+ "Subject Information Access extension:\n");
+ intValue = timeStamping;
+ }
+ } else {
+ if (PrintChoicesAndGetAnswer("Enter access method type "
+ "for Authority Information Access extension:\n"
+ "\t1 - CA Issuers\n\t2 - OCSP\n\tAny"
+ "other number to finish\n\tChoice",
+ buffer, sizeof(buffer)) !=
+ SECSuccess) {
+ GEN_BREAK(SECFailure);
+ }
+ intValue = PORT_Atoi(buffer);
+ }
+ if (addSIAExt) {
+ switch (intValue) {
+ case caRepository:
+ oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_REPOSITORY);
+ break;
+
+ case timeStamping:
+ oid = SECOID_FindOIDByTag(SEC_OID_PKIX_TIMESTAMPING);
+ break;
+ }
+ } else {
+ switch (intValue) {
+ case caIssuers:
+ oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_ISSUERS);
+ break;
+
+ case ocsp:
+ oid = SECOID_FindOIDByTag(SEC_OID_PKIX_OCSP);
+ break;
+ }
+ }
+ if (oid == NULL ||
+ SECITEM_CopyItem(arena, &current->method, &oid->oid) ==
+ SECFailure) {
+ GEN_BREAK(SECFailure);
+ }
+
+ current->location = CreateGeneralName(arena);
+ if (!current->location) {
+ GEN_BREAK(SECFailure);
+ }
+
+ if (infoAccArr == NULL) {
+ infoAccArr = PORT_ArenaZNew(arena, CERTAuthInfoAccess *);
+ } else {
+ infoAccArr = PORT_ArenaGrow(arena, infoAccArr,
+ sizeof(current) * count,
+ sizeof(current) * (count + 1));
+ }
+ if (infoAccArr == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+
+ infoAccArr[count] = current;
+ ++count;
+
+ PR_snprintf(buffer, sizeof(buffer), "Add another location to the %s"
+ " Information Access extension [y/N]",
+ (addSIAExt) ? "Subject" : "Authority");
+
+ if (GetYesNo(buffer) == 0) {
+ /* Add null to the end to mark end of data */
+ infoAccArr = PORT_ArenaGrow(arena, infoAccArr,
+ sizeof(current) * count,
+ sizeof(current) * (count + 1));
+ if (infoAccArr == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+ infoAccArr[count] = NULL;
+ break;
+ }
+
+ } while (1);
+
+ if (rv == SECSuccess) {
+ int oidIdent = SEC_OID_X509_AUTH_INFO_ACCESS;
+
+ PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
+
+ if (addSIAExt) {
+ oidIdent = SEC_OID_X509_SUBJECT_INFO_ACCESS;
+ }
+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, infoAccArr,
+ yesNoAns, oidIdent,
+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeInfoAccessExtension);
+ }
+ if (arena)
+ PORT_FreeArena(arena, PR_FALSE);
+ return (rv);
+}
+
+/* Example of valid input:
+ * 1.2.3.4:critical:/tmp/abc,5.6.7.8:not-critical:/tmp/xyz
+ */
+static SECStatus
+parseNextGenericExt(const char *nextExtension, const char **oid, int *oidLen,
+ const char **crit, int *critLen,
+ const char **filename, int *filenameLen,
+ const char **next)
+{
+ const char *nextColon;
+ const char *nextComma;
+ const char *iter = nextExtension;
+
+ if (!iter || !*iter)
+ return SECFailure;
+
+ /* Require colons at earlier positions than nextComma (or end of string ) */
+ nextComma = strchr(iter, ',');
+
+ *oid = iter;
+ nextColon = strchr(iter, ':');
+ if (!nextColon || (nextComma && nextColon > nextComma))
+ return SECFailure;
+ *oidLen = (nextColon - *oid);
+
+ if (!*oidLen)
+ return SECFailure;
+
+ iter = nextColon;
+ ++iter;
+
+ *crit = iter;
+ nextColon = strchr(iter, ':');
+ if (!nextColon || (nextComma && nextColon > nextComma))
+ return SECFailure;
+ *critLen = (nextColon - *crit);
+
+ if (!*critLen)
+ return SECFailure;
+
+ iter = nextColon;
+ ++iter;
+
+ *filename = iter;
+ if (nextComma) {
+ *filenameLen = (nextComma - *filename);
+ iter = nextComma;
+ ++iter;
+ *next = iter;
+ } else {
+ *filenameLen = strlen(*filename);
+ *next = NULL;
+ }
+
+ if (!*filenameLen)
+ return SECFailure;
+
+ return SECSuccess;
+}
+
+SECStatus
+AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
+ certutilExtnList extList, const char *extGeneric)
+{
+ PLArenaPool *arena;
+ SECStatus rv = SECSuccess;
+ char *errstring = NULL;
+ const char *nextExtension = NULL;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ return SECFailure;
+ }
+
+ do {
+ /* Add key usage extension */
+ if (extList[ext_keyUsage].activated) {
+ rv = AddKeyUsage(extHandle, extList[ext_keyUsage].arg);
+ if (rv) {
+ errstring = "KeyUsage";
+ break;
+ }
+ }
+
+ /* Add extended key usage extension */
+ if (extList[ext_extKeyUsage].activated) {
+ rv = AddExtKeyUsage(extHandle, extList[ext_extKeyUsage].arg);
+ if (rv) {
+ errstring = "ExtendedKeyUsage";
+ break;
+ }
+ }
+
+ /* Add basic constraint extension */
+ if (extList[ext_basicConstraint].activated) {
+ rv = AddBasicConstraint(arena, extHandle);
+ if (rv) {
+ errstring = "BasicConstraint";
+ break;
+ }
+ }
+
+ /* Add name constraints extension */
+ if (extList[ext_nameConstraints].activated) {
+ rv = AddNameConstraints(extHandle);
+ if (rv) {
+ errstring = "NameConstraints";
+ break;
+ }
+ }
+
+ if (extList[ext_authorityKeyID].activated) {
+ rv = AddAuthKeyID(extHandle);
+ if (rv) {
+ errstring = "AuthorityKeyID";
+ break;
+ }
+ }
+
+ if (extList[ext_subjectKeyID].activated) {
+ rv = AddSubjKeyID(extHandle);
+ if (rv) {
+ errstring = "SubjectKeyID";
+ break;
+ }
+ }
+
+ if (extList[ext_CRLDistPts].activated) {
+ rv = AddCrlDistPoint(extHandle);
+ if (rv) {
+ errstring = "CRLDistPoints";
+ break;
+ }
+ }
+
+ if (extList[ext_NSCertType].activated) {
+ rv = AddNscpCertType(extHandle, extList[ext_NSCertType].arg);
+ if (rv) {
+ errstring = "NSCertType";
+ break;
+ }
+ }
+
+ if (extList[ext_authInfoAcc].activated ||
+ extList[ext_subjInfoAcc].activated) {
+ rv = AddInfoAccess(extHandle, extList[ext_subjInfoAcc].activated,
+ extList[ext_basicConstraint].activated);
+ if (rv) {
+ errstring = "InformationAccess";
+ break;
+ }
+ }
+
+ if (extList[ext_certPolicies].activated) {
+ rv = AddCertPolicies(extHandle);
+ if (rv) {
+ errstring = "Policies";
+ break;
+ }
+ }
+
+ if (extList[ext_policyMappings].activated) {
+ rv = AddPolicyMappings(extHandle);
+ if (rv) {
+ errstring = "PolicyMappings";
+ break;
+ }
+ }
+
+ if (extList[ext_policyConstr].activated) {
+ rv = AddPolicyConstraints(extHandle);
+ if (rv) {
+ errstring = "PolicyConstraints";
+ break;
+ }
+ }
+
+ if (extList[ext_inhibitAnyPolicy].activated) {
+ rv = AddInhibitAnyPolicy(extHandle);
+ if (rv) {
+ errstring = "InhibitAnyPolicy";
+ break;
+ }
+ }
+
+ if (emailAddrs || dnsNames || extList[ext_subjectAltName].activated) {
+ CERTGeneralName *namelist = NULL;
+ SECItem item = { 0, NULL, 0 };
+
+ rv = SECSuccess;
+
+ if (emailAddrs) {
+ rv |= AddEmailSubjectAlt(arena, &namelist, emailAddrs);
+ }
+
+ if (dnsNames) {
+ rv |= AddDNSSubjectAlt(arena, &namelist, dnsNames);
+ }
+
+ if (extList[ext_subjectAltName].activated) {
+ rv |= AddGeneralSubjectAlt(arena, &namelist,
+ extList[ext_subjectAltName].arg);
+ }
+
+ if (rv == SECSuccess) {
+ rv = CERT_EncodeAltNameExtension(arena, namelist, &item);
+ if (rv == SECSuccess) {
+ rv = CERT_AddExtension(extHandle,
+ SEC_OID_X509_SUBJECT_ALT_NAME,
+ &item, PR_FALSE, PR_TRUE);
+ }
+ }
+ if (rv) {
+ errstring = "SubjectAltName";
+ break;
+ }
+ }
+ } while (0);
+
+ PORT_FreeArena(arena, PR_FALSE);
+
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Problem creating %s extension", errstring);
+ }
+
+ nextExtension = extGeneric;
+ while (nextExtension && *nextExtension) {
+ SECItem oid_item, value;
+ PRBool isCritical;
+ const char *oid, *crit, *filename, *next;
+ int oidLen, critLen, filenameLen;
+ PRFileDesc *inFile = NULL;
+ char *zeroTerminatedFilename = NULL;
+
+ rv = parseNextGenericExt(nextExtension, &oid, &oidLen, &crit, &critLen,
+ &filename, &filenameLen, &next);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName,
+ "error parsing generic extension parameter %s",
+ nextExtension);
+ break;
+ }
+ oid_item.data = NULL;
+ oid_item.len = 0;
+ rv = GetOidFromString(NULL, &oid_item, oid, oidLen);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "malformed extension OID %s", nextExtension);
+ break;
+ }
+ if (!strncmp("critical", crit, critLen)) {
+ isCritical = PR_TRUE;
+ } else if (!strncmp("not-critical", crit, critLen)) {
+ isCritical = PR_FALSE;
+ } else {
+ rv = SECFailure;
+ SECU_PrintError(progName, "expected 'critical' or 'not-critical'");
+ break;
+ }
+ zeroTerminatedFilename = PL_strndup(filename, filenameLen);
+ if (!zeroTerminatedFilename) {
+ rv = SECFailure;
+ SECU_PrintError(progName, "out of memory");
+ break;
+ }
+ rv = SECFailure;
+ inFile = PR_Open(zeroTerminatedFilename, PR_RDONLY, 0);
+ if (inFile) {
+ rv = SECU_ReadDERFromFile(&value, inFile, PR_FALSE, PR_FALSE);
+ PR_Close(inFile);
+ inFile = NULL;
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to read file %s",
+ zeroTerminatedFilename);
+ }
+ PL_strfree(zeroTerminatedFilename);
+ if (rv != SECSuccess) {
+ break;
+ }
+ rv = CERT_AddExtensionByOID(extHandle, &oid_item, &value, isCritical,
+ PR_TRUE /*copyData*/);
+ SECITEM_FreeItem(&value, PR_FALSE);
+ SECITEM_FreeItem(&oid_item, PR_FALSE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "failed to add extension %s", nextExtension);
+ break;
+ }
+ nextExtension = next;
+ }
+
+ return rv;
+}
diff --git a/security/nss/cmd/certutil/certutil.c b/security/nss/cmd/certutil/certutil.c
new file mode 100644
index 000000000..24acdbcb4
--- /dev/null
+++ b/security/nss/cmd/certutil/certutil.c
@@ -0,0 +1,3707 @@
+/* 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/. */
+
+/*
+** certutil.c
+**
+** utility for managing certificates and the cert database
+**
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if defined(WIN32)
+#include "fcntl.h"
+#include "io.h"
+#endif
+
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "nss.h"
+#include "certutil.h"
+
+#define MIN_KEY_BITS 512
+/* MAX_KEY_BITS should agree with MAX_RSA_MODULUS in freebl */
+#define MAX_KEY_BITS 8192
+#define DEFAULT_KEY_BITS 2048
+
+#define GEN_BREAK(e) \
+ rv = e; \
+ break;
+
+char *progName;
+
+static CERTCertificateRequest *
+GetCertRequest(const SECItem *reqDER, void *pwarg)
+{
+ CERTCertificateRequest *certReq = NULL;
+ CERTSignedData signedData;
+ PLArenaPool *arena = NULL;
+ SECStatus rv;
+
+ do {
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ GEN_BREAK(SECFailure);
+ }
+
+ certReq = (CERTCertificateRequest *)PORT_ArenaZAlloc(arena, sizeof(CERTCertificateRequest));
+ if (!certReq) {
+ GEN_BREAK(SECFailure);
+ }
+ certReq->arena = arena;
+
+ /* Since cert request is a signed data, must decode to get the inner
+ data
+ */
+ PORT_Memset(&signedData, 0, sizeof(signedData));
+ rv = SEC_ASN1DecodeItem(arena, &signedData,
+ SEC_ASN1_GET(CERT_SignedDataTemplate), reqDER);
+ if (rv) {
+ break;
+ }
+ rv = SEC_ASN1DecodeItem(arena, certReq,
+ SEC_ASN1_GET(CERT_CertificateRequestTemplate), &signedData.data);
+ if (rv) {
+ break;
+ }
+ rv = CERT_VerifySignedDataWithPublicKeyInfo(&signedData,
+ &certReq->subjectPublicKeyInfo, pwarg);
+ } while (0);
+
+ if (rv) {
+ SECU_PrintError(progName, "bad certificate request\n");
+ if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ certReq = NULL;
+ }
+
+ return certReq;
+}
+
+static SECStatus
+AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts,
+ const SECItem *certDER, PRBool emailcert, void *pwdata)
+{
+ CERTCertTrust *trust = NULL;
+ CERTCertificate *cert = NULL;
+ SECStatus rv;
+
+ do {
+ /* Read in an ASCII cert and return a CERTCertificate */
+ cert = CERT_DecodeCertFromPackage((char *)certDER->data, certDER->len);
+ if (!cert) {
+ SECU_PrintError(progName, "could not decode certificate");
+ GEN_BREAK(SECFailure);
+ }
+
+ /* Create a cert trust */
+ trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust));
+ if (!trust) {
+ SECU_PrintError(progName, "unable to allocate cert trust");
+ GEN_BREAK(SECFailure);
+ }
+
+ rv = CERT_DecodeTrustString(trust, trusts);
+ if (rv) {
+ SECU_PrintError(progName, "unable to decode trust string");
+ GEN_BREAK(SECFailure);
+ }
+
+ rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, name, PR_FALSE);
+ if (rv != SECSuccess) {
+ /* sigh, PK11_Import Cert and CERT_ChangeCertTrust should have
+ * been coded to take a password arg. */
+ if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
+ rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName,
+ "could not authenticate to token %s.",
+ PK11_GetTokenName(slot));
+ GEN_BREAK(SECFailure);
+ }
+ rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE,
+ name, PR_FALSE);
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName,
+ "could not add certificate to token or database");
+ GEN_BREAK(SECFailure);
+ }
+ }
+
+ rv = CERT_ChangeCertTrust(handle, cert, trust);
+ if (rv != SECSuccess) {
+ if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
+ rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName,
+ "could not authenticate to token %s.",
+ PK11_GetTokenName(slot));
+ GEN_BREAK(SECFailure);
+ }
+ rv = CERT_ChangeCertTrust(handle, cert, trust);
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName,
+ "could not change trust on certificate");
+ GEN_BREAK(SECFailure);
+ }
+ }
+
+ if (emailcert) {
+ CERT_SaveSMimeProfile(cert, NULL, pwdata);
+ }
+
+ } while (0);
+
+ CERT_DestroyCertificate(cert);
+ PORT_Free(trust);
+
+ return rv;
+}
+
+static SECStatus
+CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
+ SECOidTag hashAlgTag, CERTName *subject, const char *phone, int ascii,
+ const char *emailAddrs, const char *dnsNames,
+ certutilExtnList extnList, const char *extGeneric,
+ PRBool pssCertificate, /*out*/ SECItem *result)
+{
+ CERTSubjectPublicKeyInfo *spki;
+ CERTCertificateRequest *cr;
+ SECItem *encoding;
+ SECOidTag signAlgTag;
+ SECStatus rv;
+ PLArenaPool *arena;
+ void *extHandle;
+ SECItem signedReq = { siBuffer, NULL, 0 };
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ SECU_PrintError(progName, "out of memory");
+ return SECFailure;
+ }
+
+ /* Create info about public key */
+ spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
+ if (!spki) {
+ PORT_FreeArena(arena, PR_FALSE);
+ SECU_PrintError(progName, "unable to create subject public key");
+ return SECFailure;
+ }
+
+ /* Change cert type to RSA-PSS, if desired. */
+ if (pssCertificate) {
+ spki->algorithm.parameters.data = NULL;
+ rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
+ SEC_OID_PKCS1_RSA_PSS_SIGNATURE, 0);
+ if (rv != SECSuccess) {
+ PORT_FreeArena(arena, PR_FALSE);
+ SECU_PrintError(progName, "unable to set algorithm ID");
+ return SECFailure;
+ }
+ }
+
+ /* Generate certificate request */
+ cr = CERT_CreateCertificateRequest(subject, spki, NULL);
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+ if (!cr) {
+ PORT_FreeArena(arena, PR_FALSE);
+ SECU_PrintError(progName, "unable to make certificate request");
+ return SECFailure;
+ }
+
+ extHandle = CERT_StartCertificateRequestAttributes(cr);
+ if (extHandle == NULL) {
+ PORT_FreeArena(arena, PR_FALSE);
+ CERT_DestroyCertificateRequest(cr);
+ return SECFailure;
+ }
+ if (AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric) !=
+ SECSuccess) {
+ PORT_FreeArena(arena, PR_FALSE);
+ CERT_FinishExtensions(extHandle);
+ CERT_DestroyCertificateRequest(cr);
+ return SECFailure;
+ }
+ CERT_FinishExtensions(extHandle);
+ CERT_FinishCertificateRequestAttributes(cr);
+
+ /* Der encode the request */
+ encoding = SEC_ASN1EncodeItem(arena, NULL, cr,
+ SEC_ASN1_GET(CERT_CertificateRequestTemplate));
+ CERT_DestroyCertificateRequest(cr);
+ if (encoding == NULL) {
+ PORT_FreeArena(arena, PR_FALSE);
+ SECU_PrintError(progName, "der encoding of request failed");
+ return SECFailure;
+ }
+
+ /* Sign the request */
+ signAlgTag = SEC_GetSignatureAlgorithmOidTag(keyType, hashAlgTag);
+ if (signAlgTag == SEC_OID_UNKNOWN) {
+ PORT_FreeArena(arena, PR_FALSE);
+ SECU_PrintError(progName, "unknown Key or Hash type");
+ return SECFailure;
+ }
+
+ rv = SEC_DerSignData(arena, &signedReq, encoding->data, encoding->len,
+ privk, signAlgTag);
+ if (rv) {
+ PORT_FreeArena(arena, PR_FALSE);
+ SECU_PrintError(progName, "signing of data failed");
+ return SECFailure;
+ }
+
+ /* Encode request in specified format */
+ if (ascii) {
+ char *obuf;
+ char *header, *name, *email, *org, *state, *country;
+
+ obuf = BTOA_ConvertItemToAscii(&signedReq);
+ if (!obuf) {
+ goto oom;
+ }
+
+ name = CERT_GetCommonName(subject);
+ if (!name) {
+ name = PORT_Strdup("(not specified)");
+ }
+
+ if (!phone)
+ phone = "(not specified)";
+
+ email = CERT_GetCertEmailAddress(subject);
+ if (!email)
+ email = PORT_Strdup("(not specified)");
+
+ org = CERT_GetOrgName(subject);
+ if (!org)
+ org = PORT_Strdup("(not specified)");
+
+ state = CERT_GetStateName(subject);
+ if (!state)
+ state = PORT_Strdup("(not specified)");
+
+ country = CERT_GetCountryName(subject);
+ if (!country)
+ country = PORT_Strdup("(not specified)");
+
+ header = PR_smprintf(
+ "\nCertificate request generated by Netscape certutil\n"
+ "Phone: %s\n\n"
+ "Common Name: %s\n"
+ "Email: %s\n"
+ "Organization: %s\n"
+ "State: %s\n"
+ "Country: %s\n\n"
+ "%s\n",
+ phone, name, email, org, state, country, NS_CERTREQ_HEADER);
+
+ PORT_Free(name);
+ PORT_Free(email);
+ PORT_Free(org);
+ PORT_Free(state);
+ PORT_Free(country);
+
+ if (header) {
+ char *trailer = PR_smprintf("\n%s\n", NS_CERTREQ_TRAILER);
+ if (trailer) {
+ PRUint32 headerLen = PL_strlen(header);
+ PRUint32 obufLen = PL_strlen(obuf);
+ PRUint32 trailerLen = PL_strlen(trailer);
+ SECITEM_AllocItem(NULL, result,
+ headerLen + obufLen + trailerLen);
+ if (result->data) {
+ PORT_Memcpy(result->data, header, headerLen);
+ PORT_Memcpy(result->data + headerLen, obuf, obufLen);
+ PORT_Memcpy(result->data + headerLen + obufLen,
+ trailer, trailerLen);
+ }
+ PR_smprintf_free(trailer);
+ }
+ PR_smprintf_free(header);
+ }
+ PORT_Free(obuf);
+ } else {
+ (void)SECITEM_CopyItem(NULL, result, &signedReq);
+ }
+
+ if (!result->data) {
+ oom:
+ SECU_PrintError(progName, "out of memory");
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ rv = SECFailure;
+ }
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+static SECStatus
+ChangeTrustAttributes(CERTCertDBHandle *handle, PK11SlotInfo *slot,
+ char *name, char *trusts, void *pwdata)
+{
+ SECStatus rv;
+ CERTCertificate *cert;
+ CERTCertTrust *trust;
+
+ cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
+ if (!cert) {
+ SECU_PrintError(progName, "could not find certificate named \"%s\"",
+ name);
+ return SECFailure;
+ }
+
+ trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust));
+ if (!trust) {
+ SECU_PrintError(progName, "unable to allocate cert trust");
+ return SECFailure;
+ }
+
+ /* This function only decodes these characters: pPwcTCu, */
+ rv = CERT_DecodeTrustString(trust, trusts);
+ if (rv) {
+ SECU_PrintError(progName, "unable to decode trust string");
+ return SECFailure;
+ }
+
+ /* CERT_ChangeCertTrust API does not have a way to pass in
+ * a context, so NSS can't prompt for the password if it needs to.
+ * check to see if the failure was token not logged in and
+ * log in if need be. */
+ rv = CERT_ChangeCertTrust(handle, cert, trust);
+ if (rv != SECSuccess) {
+ if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
+ rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "could not authenticate to token %s.",
+ PK11_GetTokenName(slot));
+ return SECFailure;
+ }
+ rv = CERT_ChangeCertTrust(handle, cert, trust);
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to modify trust attributes");
+ return SECFailure;
+ }
+ }
+ CERT_DestroyCertificate(cert);
+ PORT_Free(trust);
+
+ return SECSuccess;
+}
+
+static SECStatus
+DumpChain(CERTCertDBHandle *handle, char *name, PRBool ascii)
+{
+ CERTCertificate *the_cert;
+ CERTCertificateList *chain;
+ int i, j;
+ the_cert = SECU_FindCertByNicknameOrFilename(handle, name,
+ ascii, NULL);
+ if (!the_cert) {
+ SECU_PrintError(progName, "Could not find: %s\n", name);
+ return SECFailure;
+ }
+ chain = CERT_CertChainFromCert(the_cert, 0, PR_TRUE);
+ CERT_DestroyCertificate(the_cert);
+ if (!chain) {
+ SECU_PrintError(progName, "Could not obtain chain for: %s\n", name);
+ return SECFailure;
+ }
+ for (i = chain->len - 1; i >= 0; i--) {
+ CERTCertificate *c;
+ c = CERT_FindCertByDERCert(handle, &chain->certs[i]);
+ for (j = i; j < chain->len - 1; j++) {
+ printf(" ");
+ }
+ if (c) {
+ printf("\"%s\" [%s]\n\n", c->nickname, c->subjectName);
+ CERT_DestroyCertificate(c);
+ } else {
+ printf("(null)\n\n");
+ }
+ }
+ CERT_DestroyCertificateList(chain);
+ return SECSuccess;
+}
+
+static SECStatus
+outputCertOrExtension(CERTCertificate *the_cert, PRBool raw, PRBool ascii,
+ SECItem *extensionOID, PRFileDesc *outfile)
+{
+ SECItem data;
+ PRInt32 numBytes;
+ SECStatus rv = SECFailure;
+ if (extensionOID) {
+ int i;
+ PRBool found = PR_FALSE;
+ for (i = 0; the_cert->extensions[i] != NULL; i++) {
+ CERTCertExtension *extension = the_cert->extensions[i];
+ if (SECITEM_CompareItem(&extension->id, extensionOID) == SECEqual) {
+ found = PR_TRUE;
+ numBytes = PR_Write(outfile, extension->value.data,
+ extension->value.len);
+ rv = SECSuccess;
+ if (numBytes != (PRInt32)extension->value.len) {
+ SECU_PrintSystemError(progName, "error writing extension");
+ rv = SECFailure;
+ }
+ break;
+ }
+ }
+ if (!found) {
+ SECU_PrintSystemError(progName, "extension not found");
+ rv = SECFailure;
+ }
+ } else {
+ data.data = the_cert->derCert.data;
+ data.len = the_cert->derCert.len;
+ if (ascii) {
+ PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER,
+ BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER);
+ rv = SECSuccess;
+ } else if (raw) {
+ numBytes = PR_Write(outfile, data.data, data.len);
+ rv = SECSuccess;
+ if (numBytes != (PRInt32)data.len) {
+ SECU_PrintSystemError(progName, "error writing raw cert");
+ rv = SECFailure;
+ }
+ } else {
+ rv = SEC_PrintCertificateAndTrust(the_cert, "Certificate", NULL);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "problem printing certificate");
+ }
+ }
+ }
+ return rv;
+}
+
+static SECStatus
+listCerts(CERTCertDBHandle *handle, char *name, char *email,
+ PK11SlotInfo *slot, PRBool raw, PRBool ascii,
+ SECItem *extensionOID,
+ PRFileDesc *outfile, void *pwarg)
+{
+ SECStatus rv = SECFailure;
+ CERTCertList *certs;
+ CERTCertListNode *node;
+
+ /* List certs on a non-internal slot. */
+ if (!PK11_IsFriendly(slot) && PK11_NeedLogin(slot)) {
+ SECStatus newrv = PK11_Authenticate(slot, PR_TRUE, pwarg);
+ if (newrv != SECSuccess) {
+ SECU_PrintError(progName, "could not authenticate to token %s.",
+ PK11_GetTokenName(slot));
+ return SECFailure;
+ }
+ }
+ if (name) {
+ CERTCertificate *the_cert =
+ SECU_FindCertByNicknameOrFilename(handle, name, ascii, NULL);
+ if (!the_cert) {
+ SECU_PrintError(progName, "Could not find cert: %s\n", name);
+ return SECFailure;
+ }
+ /* Here, we have one cert with the desired nickname or email
+ * address. Now, we will attempt to get a list of ALL certs
+ * with the same subject name as the cert we have. That list
+ * should contain, at a minimum, the one cert we have already found.
+ * If the list of certs is empty (NULL), the libraries have failed.
+ */
+ certs = CERT_CreateSubjectCertList(NULL, handle, &the_cert->derSubject,
+ PR_Now(), PR_FALSE);
+ CERT_DestroyCertificate(the_cert);
+ if (!certs) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ SECU_PrintError(progName, "problem printing certificates");
+ return SECFailure;
+ }
+ for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node, certs);
+ node = CERT_LIST_NEXT(node)) {
+ rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID,
+ outfile);
+ if (rv != SECSuccess) {
+ break;
+ }
+ }
+ } else if (email) {
+ certs = PK11_FindCertsFromEmailAddress(email, NULL);
+ if (!certs) {
+ SECU_PrintError(progName,
+ "Could not find certificates for email address: %s\n",
+ email);
+ return SECFailure;
+ }
+ for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node, certs);
+ node = CERT_LIST_NEXT(node)) {
+ rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID,
+ outfile);
+ if (rv != SECSuccess) {
+ break;
+ }
+ }
+ } else {
+ certs = PK11_ListCertsInSlot(slot);
+ if (certs) {
+ for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node, certs);
+ node = CERT_LIST_NEXT(node)) {
+ SECU_PrintCertNickname(node, stdout);
+ }
+ rv = SECSuccess;
+ }
+ }
+ if (certs) {
+ CERT_DestroyCertList(certs);
+ }
+ if (rv) {
+ SECU_PrintError(progName, "problem printing certificate nicknames");
+ return SECFailure;
+ }
+
+ return SECSuccess; /* not rv ?? */
+}
+
+static SECStatus
+ListCerts(CERTCertDBHandle *handle, char *nickname, char *email,
+ PK11SlotInfo *slot, PRBool raw, PRBool ascii,
+ SECItem *extensionOID,
+ PRFileDesc *outfile, secuPWData *pwdata)
+{
+ SECStatus rv;
+
+ if (!ascii && !raw && !nickname && !email) {
+ PR_fprintf(outfile, "\n%-60s %-5s\n%-60s %-5s\n\n",
+ "Certificate Nickname", "Trust Attributes", "",
+ "SSL,S/MIME,JAR/XPI");
+ }
+ if (slot == NULL) {
+ CERTCertList *list;
+ CERTCertListNode *node;
+
+ list = PK11_ListCerts(PK11CertListAll, pwdata);
+ for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
+ node = CERT_LIST_NEXT(node)) {
+ SECU_PrintCertNickname(node, stdout);
+ }
+ CERT_DestroyCertList(list);
+ return SECSuccess;
+ }
+ rv = listCerts(handle, nickname, email, slot, raw, ascii,
+ extensionOID, outfile, pwdata);
+ return rv;
+}
+
+static SECStatus
+DeleteCert(CERTCertDBHandle *handle, char *name)
+{
+ SECStatus rv;
+ CERTCertificate *cert;
+
+ cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
+ if (!cert) {
+ SECU_PrintError(progName, "could not find certificate named \"%s\"",
+ name);
+ return SECFailure;
+ }
+
+ rv = SEC_DeletePermCertificate(cert);
+ CERT_DestroyCertificate(cert);
+ if (rv) {
+ SECU_PrintError(progName, "unable to delete certificate");
+ }
+ return rv;
+}
+
+static SECStatus
+RenameCert(CERTCertDBHandle *handle, char *name, char *newName)
+{
+ SECStatus rv;
+ CERTCertificate *cert;
+
+ cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
+ if (!cert) {
+ SECU_PrintError(progName, "could not find certificate named \"%s\"",
+ name);
+ return SECFailure;
+ }
+
+ rv = __PK11_SetCertificateNickname(cert, newName);
+ CERT_DestroyCertificate(cert);
+ if (rv) {
+ SECU_PrintError(progName, "unable to rename certificate");
+ }
+ return rv;
+}
+
+static SECStatus
+ValidateCert(CERTCertDBHandle *handle, char *name, char *date,
+ char *certUsage, PRBool checkSig, PRBool logit,
+ PRBool ascii, secuPWData *pwdata)
+{
+ SECStatus rv;
+ CERTCertificate *cert = NULL;
+ PRTime timeBoundary;
+ SECCertificateUsage usage;
+ CERTVerifyLog reallog;
+ CERTVerifyLog *log = NULL;
+
+ if (!certUsage) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return (SECFailure);
+ }
+
+ switch (*certUsage) {
+ case 'O':
+ usage = certificateUsageStatusResponder;
+ break;
+ case 'L':
+ usage = certificateUsageSSLCA;
+ break;
+ case 'A':
+ usage = certificateUsageAnyCA;
+ break;
+ case 'Y':
+ usage = certificateUsageVerifyCA;
+ break;
+ case 'C':
+ usage = certificateUsageSSLClient;
+ break;
+ case 'V':
+ usage = certificateUsageSSLServer;
+ break;
+ case 'S':
+ usage = certificateUsageEmailSigner;
+ break;
+ case 'R':
+ usage = certificateUsageEmailRecipient;
+ break;
+ case 'J':
+ usage = certificateUsageObjectSigner;
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return (SECFailure);
+ }
+ do {
+ cert = SECU_FindCertByNicknameOrFilename(handle, name, ascii,
+ NULL);
+ if (!cert) {
+ SECU_PrintError(progName, "could not find certificate named \"%s\"",
+ name);
+ GEN_BREAK(SECFailure)
+ }
+
+ if (date != NULL) {
+ rv = DER_AsciiToTime(&timeBoundary, date);
+ if (rv) {
+ SECU_PrintError(progName, "invalid input date");
+ GEN_BREAK(SECFailure)
+ }
+ } else {
+ timeBoundary = PR_Now();
+ }
+
+ if (logit) {
+ log = &reallog;
+
+ log->count = 0;
+ log->head = NULL;
+ log->tail = NULL;
+ log->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (log->arena == NULL) {
+ SECU_PrintError(progName, "out of memory");
+ GEN_BREAK(SECFailure)
+ }
+ }
+
+ rv = CERT_VerifyCertificate(handle, cert, checkSig, usage,
+ timeBoundary, pwdata, log, &usage);
+ if (log) {
+ if (log->head == NULL) {
+ fprintf(stdout, "%s: certificate is valid\n", progName);
+ GEN_BREAK(SECSuccess)
+ } else {
+ char *name;
+ CERTVerifyLogNode *node;
+
+ node = log->head;
+ while (node) {
+ if (node->cert->nickname != NULL) {
+ name = node->cert->nickname;
+ } else {
+ name = node->cert->subjectName;
+ }
+ fprintf(stderr, "%s : %s\n", name,
+ SECU_Strerror(node->error));
+ CERT_DestroyCertificate(node->cert);
+ node = node->next;
+ }
+ }
+ } else {
+ if (rv != SECSuccess) {
+ PRErrorCode perr = PORT_GetError();
+ fprintf(stdout, "%s: certificate is invalid: %s\n",
+ progName, SECU_Strerror(perr));
+ GEN_BREAK(SECFailure)
+ }
+ fprintf(stdout, "%s: certificate is valid\n", progName);
+ GEN_BREAK(SECSuccess)
+ }
+ } while (0);
+
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+
+ return (rv);
+}
+
+static PRBool
+ItemIsPrintableASCII(const SECItem *item)
+{
+ unsigned char *src = item->data;
+ unsigned int len = item->len;
+ while (len-- > 0) {
+ unsigned char uc = *src++;
+ if (uc < 0x20 || uc > 0x7e)
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
+/* Caller ensures that dst is at least item->len*2+1 bytes long */
+static void
+SECItemToHex(const SECItem *item, char *dst)
+{
+ if (dst && item && item->data) {
+ unsigned char *src = item->data;
+ unsigned int len = item->len;
+ for (; len > 0; --len, dst += 2) {
+ sprintf(dst, "%02x", *src++);
+ }
+ *dst = '\0';
+ }
+}
+
+static const char *const keyTypeName[] = {
+ "null", "rsa", "dsa", "fortezza", "dh", "kea", "ec"
+};
+
+#define MAX_CKA_ID_BIN_LEN 20
+#define MAX_CKA_ID_STR_LEN 40
+
+/* print key number, key ID (in hex or ASCII), key label (nickname) */
+static SECStatus
+PrintKey(PRFileDesc *out, const char *nickName, int count,
+ SECKEYPrivateKey *key, void *pwarg)
+{
+ SECItem *ckaID;
+ char ckaIDbuf[MAX_CKA_ID_STR_LEN + 4];
+
+ pwarg = NULL;
+ ckaID = PK11_GetLowLevelKeyIDForPrivateKey(key);
+ if (!ckaID) {
+ strcpy(ckaIDbuf, "(no CKA_ID)");
+ } else if (ItemIsPrintableASCII(ckaID)) {
+ int len = PR_MIN(MAX_CKA_ID_STR_LEN, ckaID->len);
+ ckaIDbuf[0] = '"';
+ memcpy(ckaIDbuf + 1, ckaID->data, len);
+ ckaIDbuf[1 + len] = '"';
+ ckaIDbuf[2 + len] = '\0';
+ } else {
+ /* print ckaid in hex */
+ SECItem idItem = *ckaID;
+ if (idItem.len > MAX_CKA_ID_BIN_LEN)
+ idItem.len = MAX_CKA_ID_BIN_LEN;
+ SECItemToHex(&idItem, ckaIDbuf);
+ }
+
+ PR_fprintf(out, "<%2d> %-8.8s %-42.42s %s\n", count,
+ keyTypeName[key->keyType], ckaIDbuf, nickName);
+ SECITEM_ZfreeItem(ckaID, PR_TRUE);
+
+ return SECSuccess;
+}
+
+/* returns SECSuccess if ANY keys are found, SECFailure otherwise. */
+static SECStatus
+ListKeysInSlot(PK11SlotInfo *slot, const char *nickName, KeyType keyType,
+ void *pwarg)
+{
+ SECKEYPrivateKeyList *list;
+ SECKEYPrivateKeyListNode *node;
+ int count = 0;
+
+ if (PK11_NeedLogin(slot)) {
+ SECStatus rv = PK11_Authenticate(slot, PR_TRUE, pwarg);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "could not authenticate to token %s.",
+ PK11_GetTokenName(slot));
+ return SECFailure;
+ }
+ }
+
+ if (nickName && nickName[0])
+ list = PK11_ListPrivKeysInSlot(slot, (char *)nickName, pwarg);
+ else
+ list = PK11_ListPrivateKeysInSlot(slot);
+ if (list == NULL) {
+ SECU_PrintError(progName, "problem listing keys");
+ return SECFailure;
+ }
+ for (node = PRIVKEY_LIST_HEAD(list);
+ !PRIVKEY_LIST_END(node, list);
+ node = PRIVKEY_LIST_NEXT(node)) {
+ char *keyName;
+ static const char orphan[] = { "(orphan)" };
+
+ if (keyType != nullKey && keyType != node->key->keyType)
+ continue;
+ keyName = PK11_GetPrivateKeyNickname(node->key);
+ if (!keyName || !keyName[0]) {
+ /* Try extra hard to find nicknames for keys that lack them. */
+ CERTCertificate *cert;
+ PORT_Free((void *)keyName);
+ keyName = NULL;
+ cert = PK11_GetCertFromPrivateKey(node->key);
+ if (cert) {
+ if (cert->nickname && cert->nickname[0]) {
+ keyName = PORT_Strdup(cert->nickname);
+ } else if (cert->emailAddr && cert->emailAddr[0]) {
+ keyName = PORT_Strdup(cert->emailAddr);
+ }
+ CERT_DestroyCertificate(cert);
+ }
+ }
+ if (nickName) {
+ if (!keyName || PL_strcmp(keyName, nickName)) {
+ /* PKCS#11 module returned unwanted keys */
+ PORT_Free((void *)keyName);
+ continue;
+ }
+ }
+ if (!keyName)
+ keyName = (char *)orphan;
+
+ PrintKey(PR_STDOUT, keyName, count, node->key, pwarg);
+
+ if (keyName != (char *)orphan)
+ PORT_Free((void *)keyName);
+ count++;
+ }
+ SECKEY_DestroyPrivateKeyList(list);
+
+ if (count == 0) {
+ PR_fprintf(PR_STDOUT, "%s: no keys found\n", progName);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+/* returns SECSuccess if ANY keys are found, SECFailure otherwise. */
+static SECStatus
+ListKeys(PK11SlotInfo *slot, const char *nickName, int index,
+ KeyType keyType, PRBool dopriv, secuPWData *pwdata)
+{
+ SECStatus rv = SECFailure;
+ static const char fmt[] =
+ "%s: Checking token \"%.33s\" in slot \"%.65s\"\n";
+
+ if (slot == NULL) {
+ PK11SlotList *list;
+ PK11SlotListElement *le;
+
+ list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, pwdata);
+ if (list) {
+ for (le = list->head; le; le = le->next) {
+ PR_fprintf(PR_STDOUT, fmt, progName,
+ PK11_GetTokenName(le->slot),
+ PK11_GetSlotName(le->slot));
+ rv &= ListKeysInSlot(le->slot, nickName, keyType, pwdata);
+ }
+ PK11_FreeSlotList(list);
+ }
+ } else {
+ PR_fprintf(PR_STDOUT, fmt, progName, PK11_GetTokenName(slot),
+ PK11_GetSlotName(slot));
+ rv = ListKeysInSlot(slot, nickName, keyType, pwdata);
+ }
+ return rv;
+}
+
+static SECStatus
+DeleteKey(char *nickname, secuPWData *pwdata)
+{
+ SECStatus rv;
+ CERTCertificate *cert;
+ PK11SlotInfo *slot;
+
+ slot = PK11_GetInternalKeySlot();
+ if (PK11_NeedLogin(slot)) {
+ SECStatus rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "could not authenticate to token %s.",
+ PK11_GetTokenName(slot));
+ return SECFailure;
+ }
+ }
+ cert = PK11_FindCertFromNickname(nickname, pwdata);
+ if (!cert) {
+ PK11_FreeSlot(slot);
+ return SECFailure;
+ }
+ rv = PK11_DeleteTokenCertAndKey(cert, pwdata);
+ if (rv != SECSuccess) {
+ SECU_PrintError("problem deleting private key \"%s\"\n", nickname);
+ }
+ CERT_DestroyCertificate(cert);
+ PK11_FreeSlot(slot);
+ return rv;
+}
+
+/*
+ * L i s t M o d u l e s
+ *
+ * Print a list of the PKCS11 modules that are
+ * available. This is useful for smartcard people to
+ * make sure they have the drivers loaded.
+ *
+ */
+static SECStatus
+ListModules(void)
+{
+ PK11SlotList *list;
+ PK11SlotListElement *le;
+
+ /* get them all! */
+ list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL);
+ if (list == NULL)
+ return SECFailure;
+
+ /* look at each slot*/
+ for (le = list->head; le; le = le->next) {
+ printf("\n");
+ printf(" slot: %s\n", PK11_GetSlotName(le->slot));
+ printf(" token: %s\n", PK11_GetTokenName(le->slot));
+ }
+ PK11_FreeSlotList(list);
+
+ return SECSuccess;
+}
+
+static void
+PrintSyntax(char *progName)
+{
+#define FPS fprintf(stderr,
+ FPS "Type %s -H for more detailed descriptions\n", progName);
+ FPS "Usage: %s -N [-d certdir] [-P dbprefix] [-f pwfile] [--empty-password]\n", progName);
+ FPS "Usage: %s -T [-d certdir] [-P dbprefix] [-h token-name]\n"
+ "\t\t [-f pwfile] [-0 SSO-password]\n", progName);
+ FPS "\t%s -A -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n",
+ progName);
+ FPS "\t%s -B -i batch-file\n", progName);
+ FPS "\t%s -C [-c issuer-name | -x] -i cert-request-file -o cert-file\n"
+ "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
+ "\t\t [-f pwfile] [-d certdir] [-P dbprefix] [-Z hashAlg]\n"
+ "\t\t [-1 | --keyUsage [keyUsageKeyword,..]] [-2] [-3] [-4]\n"
+ "\t\t [-5 | --nsCertType [nsCertTypeKeyword,...]]\n"
+ "\t\t [-6 | --extKeyUsage [extKeyUsageKeyword,...]] [-7 emailAddrs]\n"
+ "\t\t [-8 dns-names] [-a]\n",
+ progName);
+ FPS "\t%s -D -n cert-name [-d certdir] [-P dbprefix]\n", progName);
+ FPS "\t%s --rename -n cert-name --new-n new-cert-name\n"
+ "\t\t [-d certdir] [-P dbprefix]\n", progName);
+ FPS "\t%s -E -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n",
+ progName);
+ FPS "\t%s -F -n nickname [-d certdir] [-P dbprefix]\n",
+ progName);
+ FPS "\t%s -G -n key-name [-h token-name] [-k rsa] [-g key-size] [-y exp]\n"
+ "\t\t [-f pwfile] [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
+ FPS "\t%s -G [-h token-name] -k dsa [-q pqgfile -g key-size] [-f pwfile]\n"
+ "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
+#ifndef NSS_DISABLE_ECC
+ FPS "\t%s -G [-h token-name] -k ec -q curve [-f pwfile]\n"
+ "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
+ FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|ec|rsa|all]\n",
+ progName);
+#else
+ FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|rsa|all]\n",
+ progName);
+#endif /* NSS_DISABLE_ECC */
+ FPS "\t\t [-f pwfile] [-X] [-d certdir] [-P dbprefix]\n");
+ FPS "\t%s --upgrade-merge --source-dir upgradeDir --upgrade-id uniqueID\n",
+ progName);
+ FPS "\t\t [--upgrade-token-name tokenName] [-d targetDBDir]\n");
+ FPS "\t\t [-P targetDBPrefix] [--source-prefix upgradeDBPrefix]\n");
+ FPS "\t\t [-f targetPWfile] [-@ upgradePWFile]\n");
+ FPS "\t%s --merge --source-dir sourceDBDir [-d targetDBdir]\n",
+ progName);
+ FPS "\t\t [-P targetDBPrefix] [--source-prefix sourceDBPrefix]\n");
+ FPS "\t\t [-f targetPWfile] [-@ sourcePWFile]\n");
+ FPS "\t%s -L [-n cert-name] [-h token-name] [--email email-address]\n",
+ progName);
+ FPS "\t\t [-X] [-r] [-a] [--dump-ext-val OID] [-d certdir] [-P dbprefix]\n");
+ FPS "\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n",
+ progName);
+ FPS "\t%s -O -n cert-name [-X] [-d certdir] [-a] [-P dbprefix]\n", progName);
+ FPS "\t%s -R -s subj -o cert-request-file [-d certdir] [-P dbprefix] [-p phone] [-a]\n"
+ "\t\t [-7 emailAddrs] [-k key-type-or-id] [-h token-name] [-f pwfile]\n"
+ "\t\t [-g key-size] [-Z hashAlg]\n",
+ progName);
+ FPS "\t%s -V -n cert-name -u usage [-b time] [-e] [-a]\n"
+ "\t\t[-X] [-d certdir] [-P dbprefix]\n",
+ progName);
+ FPS "Usage: %s -W [-d certdir] [-f pwfile] [-@newpwfile]\n",
+ progName);
+ FPS "\t%s -S -n cert-name -s subj [-c issuer-name | -x] -t trustargs\n"
+ "\t\t [-k key-type-or-id] [-q key-params] [-h token-name] [-g key-size]\n"
+ "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
+ "\t\t [-f pwfile] [-d certdir] [-P dbprefix] [-Z hashAlg]\n"
+ "\t\t [-p phone] [-1] [-2] [-3] [-4] [-5] [-6] [-7 emailAddrs]\n"
+ "\t\t [-8 DNS-names]\n"
+ "\t\t [--extAIA] [--extSIA] [--extCP] [--extPM] [--extPC] [--extIA]\n"
+ "\t\t [--extSKID] [--extNC] [--extSAN type:name[,type:name]...]\n"
+ "\t\t [--extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...]\n", progName);
+ FPS "\t%s -U [-X] [-d certdir] [-P dbprefix]\n", progName);
+ exit(1);
+}
+
+enum usage_level {
+ usage_all = 0,
+ usage_selected = 1
+};
+
+static void luCommonDetailsAE();
+
+static void
+luA(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "A"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Add a certificate to the database (create if needed)\n",
+ "-A");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ if (ul == usage_all) {
+ FPS "%-20s\n", " All options under -E apply");
+ } else {
+ luCommonDetailsAE();
+ }
+}
+
+static void
+luB(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "B"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Run a series of certutil commands from a batch file\n", "-B");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s Specify the batch file\n", " -i batch-file");
+}
+
+static void
+luE(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "E"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Add an Email certificate to the database (create if needed)\n",
+ "-E");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ luCommonDetailsAE();
+}
+
+static void
+luCommonDetailsAE()
+{
+ FPS "%-20s Specify the nickname of the certificate to add\n",
+ " -n cert-name");
+ FPS "%-20s Set the certificate trust attributes:\n",
+ " -t trustargs");
+ FPS "%-25s trustargs is of the form x,y,z where x is for SSL, y is for S/MIME,\n", "");
+ FPS "%-25s and z is for code signing. Use ,, for no explicit trust.\n", "");
+ FPS "%-25s p \t prohibited (explicitly distrusted)\n", "");
+ FPS "%-25s P \t trusted peer\n", "");
+ FPS "%-25s c \t valid CA\n", "");
+ FPS "%-25s T \t trusted CA to issue client certs (implies c)\n", "");
+ FPS "%-25s C \t trusted CA to issue server certs (implies c)\n", "");
+ FPS "%-25s u \t user cert\n", "");
+ FPS "%-25s w \t send warning\n", "");
+ FPS "%-25s g \t make step-up cert\n", "");
+ FPS "%-20s Specify the password file\n",
+ " -f pwfile");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s The input certificate is encoded in ASCII (RFC1113)\n",
+ " -a");
+ FPS "%-20s Specify the certificate file (default is stdin)\n",
+ " -i input");
+ FPS "\n");
+}
+
+static void
+luC(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "C"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Create a new binary certificate from a BINARY cert request\n",
+ "-C");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s The nickname of the issuer cert\n",
+ " -c issuer-name");
+ FPS "%-20s The BINARY certificate request file\n",
+ " -i cert-request ");
+ FPS "%-20s Output binary cert to this file (default is stdout)\n",
+ " -o output-cert");
+ FPS "%-20s Self sign\n",
+ " -x");
+ FPS "%-20s Cert serial number\n",
+ " -m serial-number");
+ FPS "%-20s Time Warp\n",
+ " -w warp-months");
+ FPS "%-20s Months valid (default is 3)\n",
+ " -v months-valid");
+ FPS "%-20s Specify the password file\n",
+ " -f pwfile");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s \n"
+ "%-20s Specify the hash algorithm to use. Possible keywords:\n"
+ "%-20s \"MD2\", \"MD4\", \"MD5\", \"SHA1\", \"SHA224\",\n"
+ "%-20s \"SHA256\", \"SHA384\", \"SHA512\"\n",
+ " -Z hashAlg", "", "", "");
+ FPS "%-20s \n"
+ "%-20s Create key usage extension. Possible keywords:\n"
+ "%-20s \"digitalSignature\", \"nonRepudiation\", \"keyEncipherment\",\n"
+ "%-20s \"dataEncipherment\", \"keyAgreement\", \"certSigning\",\n"
+ "%-20s \"crlSigning\", \"critical\"\n",
+ " -1 | --keyUsage keyword,keyword,...", "", "", "", "");
+ FPS "%-20s Create basic constraint extension\n",
+ " -2 ");
+ FPS "%-20s Create authority key ID extension\n",
+ " -3 ");
+ FPS "%-20s Create crl distribution point extension\n",
+ " -4 ");
+ FPS "%-20s \n"
+ "%-20s Create netscape cert type extension. Possible keywords:\n"
+ "%-20s \"sslClient\", \"sslServer\", \"smime\", \"objectSigning\",\n"
+ "%-20s \"sslCA\", \"smimeCA\", \"objectSigningCA\", \"critical\".\n",
+ " -5 | --nsCertType keyword,keyword,... ", "", "", "");
+ FPS "%-20s \n"
+ "%-20s Create extended key usage extension. Possible keywords:\n"
+ "%-20s \"serverAuth\", \"clientAuth\",\"codeSigning\",\n"
+ "%-20s \"emailProtection\", \"timeStamp\",\"ocspResponder\",\n"
+ "%-20s \"stepUp\", \"msTrustListSign\", \"critical\"\n",
+ " -6 | --extKeyUsage keyword,keyword,...", "", "", "", "");
+ FPS "%-20s Create an email subject alt name extension\n",
+ " -7 emailAddrs");
+ FPS "%-20s Create an dns subject alt name extension\n",
+ " -8 dnsNames");
+ FPS "%-20s The input certificate request is encoded in ASCII (RFC1113)\n",
+ " -a");
+ FPS "\n");
+}
+
+static void
+luG(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "G"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Generate a new key pair\n",
+ "-G");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s Name of token in which to generate key (default is internal)\n",
+ " -h token-name");
+#ifndef NSS_DISABLE_ECC
+ FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
+ " -k key-type");
+ FPS "%-20s Key size in bits, (min %d, max %d, default %d) (not for ec)\n",
+ " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
+#else
+ FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n",
+ " -k key-type");
+ FPS "%-20s Key size in bits, (min %d, max %d, default %d)\n",
+ " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
+#endif /* NSS_DISABLE_ECC */
+ FPS "%-20s Set the public exponent value (3, 17, 65537) (rsa only)\n",
+ " -y exp");
+ FPS "%-20s Specify the password file\n",
+ " -f password-file");
+ FPS "%-20s Specify the noise file to be used\n",
+ " -z noisefile");
+ FPS "%-20s read PQG value from pqgfile (dsa only)\n",
+ " -q pqgfile");
+#ifndef NSS_DISABLE_ECC
+ FPS "%-20s Elliptic curve name (ec only)\n",
+ " -q curve-name");
+ FPS "%-20s One of nistp256, nistp384, nistp521, curve25519.\n", "");
+ FPS "%-20s If a custom token is present, the following curves are also supported:\n", "");
+ FPS "%-20s sect163k1, nistk163, sect163r1, sect163r2,\n", "");
+ FPS "%-20s nistb163, sect193r1, sect193r2, sect233k1, nistk233,\n", "");
+ FPS "%-20s sect233r1, nistb233, sect239k1, sect283k1, nistk283,\n", "");
+ FPS "%-20s sect283r1, nistb283, sect409k1, nistk409, sect409r1,\n", "");
+ FPS "%-20s nistb409, sect571k1, nistk571, sect571r1, nistb571,\n", "");
+ FPS "%-20s secp160k1, secp160r1, secp160r2, secp192k1, secp192r1,\n", "");
+ FPS "%-20s nistp192, secp224k1, secp224r1, nistp224, secp256k1,\n", "");
+ FPS "%-20s secp256r1, secp384r1, secp521r1,\n", "");
+ FPS "%-20s prime192v1, prime192v2, prime192v3, \n", "");
+ FPS "%-20s prime239v1, prime239v2, prime239v3, c2pnb163v1, \n", "");
+ FPS "%-20s c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1, \n", "");
+ FPS "%-20s c2tnb191v2, c2tnb191v3, \n", "");
+ FPS "%-20s c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3, \n", "");
+ FPS "%-20s c2pnb272w1, c2pnb304w1, \n", "");
+ FPS "%-20s c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1, \n", "");
+ FPS "%-20s secp112r2, secp128r1, secp128r2, sect113r1, sect113r2\n", "");
+ FPS "%-20s sect131r1, sect131r2\n", "");
+#endif
+ FPS "%-20s Key database directory (default is ~/.netscape)\n",
+ " -d keydir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s\n"
+ "%-20s PKCS #11 key Attributes.\n",
+ " --keyAttrFlags attrflags", "");
+ FPS "%-20s Comma separated list of key attribute attribute flags,\n", "");
+ FPS "%-20s selected from the following list of choices:\n", "");
+ FPS "%-20s {token | session} {public | private} {sensitive | insensitive}\n", "");
+ FPS "%-20s {modifiable | unmodifiable} {extractable | unextractable}\n", "");
+ FPS "%-20s\n",
+ " --keyOpFlagsOn opflags");
+ FPS "%-20s\n"
+ "%-20s PKCS #11 key Operation Flags.\n",
+ " --keyOpFlagsOff opflags", "");
+ FPS "%-20s Comma separated list of one or more of the following:\n", "");
+ FPS "%-20s encrypt, decrypt, sign, sign_recover, verify,\n", "");
+ FPS "%-20s verify_recover, wrap, unwrap, derive\n", "");
+ FPS "\n");
+}
+
+static void
+luD(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "D"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Delete a certificate from the database\n",
+ "-D");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s The nickname of the cert to delete\n",
+ " -n cert-name");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "\n");
+}
+
+static void
+luF(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "F"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Delete a key from the database\n",
+ "-F");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s The nickname of the key to delete\n",
+ " -n cert-name");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "\n");
+}
+
+static void
+luU(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "U"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s List all modules\n", /*, or print out a single named module\n",*/
+ "-U");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s Module database directory (default is '~/.netscape')\n",
+ " -d moddir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s force the database to open R/W\n",
+ " -X");
+ FPS "\n");
+}
+
+static void
+luK(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "K"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s List all private keys\n",
+ "-K");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s Name of token to search (\"all\" for all tokens)\n",
+ " -h token-name ");
+
+ FPS "%-20s Key type (\"all\" (default), \"dsa\","
+#ifndef NSS_DISABLE_ECC
+ " \"ec\","
+#endif
+ " \"rsa\")\n",
+ " -k key-type");
+ FPS "%-20s The nickname of the key or associated certificate\n",
+ " -n name");
+ FPS "%-20s Specify the password file\n",
+ " -f password-file");
+ FPS "%-20s Key database directory (default is ~/.netscape)\n",
+ " -d keydir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s force the database to open R/W\n",
+ " -X");
+ FPS "\n");
+}
+
+static void
+luL(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "L"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s List all certs, or print out a single named cert (or a subset)\n",
+ "-L");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s Name of token to search (\"all\" for all tokens)\n",
+ " -h token-name ");
+ FPS "%-20s Pretty print named cert (list all if unspecified)\n",
+ " -n cert-name");
+ FPS "%-20s \n"
+ "%-20s Pretty print cert with email address (list all if unspecified)\n",
+ " --email email-address", "");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s force the database to open R/W\n",
+ " -X");
+ FPS "%-20s For single cert, print binary DER encoding\n",
+ " -r");
+ FPS "%-20s For single cert, print ASCII encoding (RFC1113)\n",
+ " -a");
+ FPS "%-20s \n"
+ "%-20s For single cert, print binary DER encoding of extension OID\n",
+ " --dump-ext-val OID", "");
+ FPS "\n");
+}
+
+static void
+luM(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "M"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Modify trust attributes of certificate\n",
+ "-M");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s The nickname of the cert to modify\n",
+ " -n cert-name");
+ FPS "%-20s Set the certificate trust attributes (see -A above)\n",
+ " -t trustargs");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "\n");
+}
+
+static void
+luN(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "N"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Create a new certificate database\n",
+ "-N");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s Specify the password file\n",
+ " -f password-file");
+ FPS "%-20s use empty password when creating a new database\n",
+ " --empty-password");
+ FPS "\n");
+}
+
+static void
+luT(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "T"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Reset the Key database or token\n",
+ "-T");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s Token to reset (default is internal)\n",
+ " -h token-name");
+ FPS "%-20s Set token's Site Security Officer password\n",
+ " -0 SSO-password");
+ FPS "\n");
+}
+
+static void
+luO(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "O"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Print the chain of a certificate\n",
+ "-O");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s The nickname of the cert to modify\n",
+ " -n cert-name");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Input the certificate in ASCII (RFC1113); default is binary\n",
+ " -a");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s force the database to open R/W\n",
+ " -X");
+ FPS "\n");
+}
+
+static void
+luR(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "R"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Generate a certificate request (stdout)\n",
+ "-R");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s Specify the subject name (using RFC1485)\n",
+ " -s subject");
+ FPS "%-20s Output the cert request to this file\n",
+ " -o output-req");
+#ifndef NSS_DISABLE_ECC
+ FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
+#else
+ FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n",
+#endif /* NSS_DISABLE_ECC */
+ " -k key-type-or-id");
+ FPS "%-20s or nickname of the cert key to use \n",
+ "");
+ FPS "%-20s Name of token in which to generate key (default is internal)\n",
+ " -h token-name");
+ FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n",
+ " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
+ FPS "%-20s Name of file containing PQG parameters (dsa only)\n",
+ " -q pqgfile");
+#ifndef NSS_DISABLE_ECC
+ FPS "%-20s Elliptic curve name (ec only)\n",
+ " -q curve-name");
+ FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
+ "");
+#endif /* NSS_DISABLE_ECC */
+ FPS "%-20s Specify the password file\n",
+ " -f pwfile");
+ FPS "%-20s Key database directory (default is ~/.netscape)\n",
+ " -d keydir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n",
+ " -p phone");
+ FPS "%-20s \n"
+ "%-20s Specify the hash algorithm to use. Possible keywords:\n"
+ "%-20s \"MD2\", \"MD4\", \"MD5\", \"SHA1\", \"SHA224\",\n"
+ "%-20s \"SHA256\", \"SHA384\", \"SHA512\"\n",
+ " -Z hashAlg", "", "", "");
+ FPS "%-20s Output the cert request in ASCII (RFC1113); default is binary\n",
+ " -a");
+ FPS "%-20s \n",
+ " See -S for available extension options");
+ FPS "%-20s \n",
+ " See -G for available key flag options");
+ FPS "\n");
+}
+
+static void
+luV(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "V"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Validate a certificate\n",
+ "-V");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s The nickname of the cert to Validate\n",
+ " -n cert-name");
+ FPS "%-20s validity time (\"YYMMDDHHMMSS[+HHMM|-HHMM|Z]\")\n",
+ " -b time");
+ FPS "%-20s Check certificate signature \n",
+ " -e ");
+ FPS "%-20s Specify certificate usage:\n", " -u certusage");
+ FPS "%-25s C \t SSL Client\n", "");
+ FPS "%-25s V \t SSL Server\n", "");
+ FPS "%-25s L \t SSL CA\n", "");
+ FPS "%-25s A \t Any CA\n", "");
+ FPS "%-25s Y \t Verify CA\n", "");
+ FPS "%-25s S \t Email signer\n", "");
+ FPS "%-25s R \t Email Recipient\n", "");
+ FPS "%-25s O \t OCSP status responder\n", "");
+ FPS "%-25s J \t Object signer\n", "");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Input the certificate in ASCII (RFC1113); default is binary\n",
+ " -a");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s force the database to open R/W\n",
+ " -X");
+ FPS "\n");
+}
+
+static void
+luW(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "W"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Change the key database password\n",
+ "-W");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s cert and key database directory\n",
+ " -d certdir");
+ FPS "%-20s Specify a file with the current password\n",
+ " -f pwfile");
+ FPS "%-20s Specify a file with the new password in two lines\n",
+ " -@ newpwfile");
+ FPS "\n");
+}
+
+static void
+luRename(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "rename"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Change the database nickname of a certificate\n",
+ "--rename");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s The old nickname of the cert to rename\n",
+ " -n cert-name");
+ FPS "%-20s The new nickname of the cert to rename\n",
+ " --new-n new-name");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "\n");
+}
+
+static void
+luUpgradeMerge(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "upgrade-merge"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Upgrade an old database and merge it into a new one\n",
+ "--upgrade-merge");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s Cert database directory to merge into (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix of the target database\n",
+ " -P dbprefix");
+ FPS "%-20s Specify the password file for the target database\n",
+ " -f pwfile");
+ FPS "%-20s \n%-20s Cert database directory to upgrade from\n",
+ " --source-dir certdir", "");
+ FPS "%-20s \n%-20s Cert & Key database prefix of the upgrade database\n",
+ " --source-prefix dbprefix", "");
+ FPS "%-20s \n%-20s Unique identifier for the upgrade database\n",
+ " --upgrade-id uniqueID", "");
+ FPS "%-20s \n%-20s Name of the token while it is in upgrade state\n",
+ " --upgrade-token-name name", "");
+ FPS "%-20s Specify the password file for the upgrade database\n",
+ " -@ pwfile");
+ FPS "\n");
+}
+
+static void
+luMerge(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "merge"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Merge source database into the target database\n",
+ "--merge");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s Cert database directory of target (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix of the target database\n",
+ " -P dbprefix");
+ FPS "%-20s Specify the password file for the target database\n",
+ " -f pwfile");
+ FPS "%-20s \n%-20s Cert database directory of the source database\n",
+ " --source-dir certdir", "");
+ FPS "%-20s \n%-20s Cert & Key database prefix of the source database\n",
+ " --source-prefix dbprefix", "");
+ FPS "%-20s Specify the password file for the source database\n",
+ " -@ pwfile");
+ FPS "\n");
+}
+
+static void
+luS(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "S"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Make a certificate and add to database\n",
+ "-S");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "%-20s Specify the nickname of the cert\n",
+ " -n key-name");
+ FPS "%-20s Specify the subject name (using RFC1485)\n",
+ " -s subject");
+ FPS "%-20s The nickname of the issuer cert\n",
+ " -c issuer-name");
+ FPS "%-20s Set the certificate trust attributes (see -A above)\n",
+ " -t trustargs");
+#ifndef NSS_DISABLE_ECC
+ FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
+#else
+ FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n",
+#endif /* NSS_DISABLE_ECC */
+ " -k key-type-or-id");
+ FPS "%-20s Name of token in which to generate key (default is internal)\n",
+ " -h token-name");
+ FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n",
+ " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
+ FPS "%-20s Name of file containing PQG parameters (dsa only)\n",
+ " -q pqgfile");
+#ifndef NSS_DISABLE_ECC
+ FPS "%-20s Elliptic curve name (ec only)\n",
+ " -q curve-name");
+ FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
+ "");
+#endif /* NSS_DISABLE_ECC */
+ FPS "%-20s Self sign\n",
+ " -x");
+ FPS "%-20s Cert serial number\n",
+ " -m serial-number");
+ FPS "%-20s Time Warp\n",
+ " -w warp-months");
+ FPS "%-20s Months valid (default is 3)\n",
+ " -v months-valid");
+ FPS "%-20s Specify the password file\n",
+ " -f pwfile");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n",
+ " -p phone");
+ FPS "%-20s \n"
+ "%-20s Specify the hash algorithm to use. Possible keywords:\n"
+ "%-20s \"MD2\", \"MD4\", \"MD5\", \"SHA1\", \"SHA224\",\n"
+ "%-20s \"SHA256\", \"SHA384\", \"SHA512\"\n",
+ " -Z hashAlg", "", "", "");
+ FPS "%-20s Create key usage extension\n",
+ " -1 ");
+ FPS "%-20s Create basic constraint extension\n",
+ " -2 ");
+ FPS "%-20s Create authority key ID extension\n",
+ " -3 ");
+ FPS "%-20s Create crl distribution point extension\n",
+ " -4 ");
+ FPS "%-20s Create netscape cert type extension\n",
+ " -5 ");
+ FPS "%-20s Create extended key usage extension\n",
+ " -6 ");
+ FPS "%-20s Create an email subject alt name extension\n",
+ " -7 emailAddrs ");
+ FPS "%-20s Create a DNS subject alt name extension\n",
+ " -8 DNS-names");
+ FPS "%-20s Create an Authority Information Access extension\n",
+ " --extAIA ");
+ FPS "%-20s Create a Subject Information Access extension\n",
+ " --extSIA ");
+ FPS "%-20s Create a Certificate Policies extension\n",
+ " --extCP ");
+ FPS "%-20s Create a Policy Mappings extension\n",
+ " --extPM ");
+ FPS "%-20s Create a Policy Constraints extension\n",
+ " --extPC ");
+ FPS "%-20s Create an Inhibit Any Policy extension\n",
+ " --extIA ");
+ FPS "%-20s Create a subject key ID extension\n",
+ " --extSKID ");
+ FPS "%-20s \n",
+ " See -G for available key flag options");
+ FPS "%-20s Create a name constraints extension\n",
+ " --extNC ");
+ FPS "%-20s \n"
+ "%-20s Create a Subject Alt Name extension with one or multiple names\n",
+ " --extSAN type:name[,type:name]...", "");
+ FPS "%-20s - type: directory, dn, dns, edi, ediparty, email, ip, ipaddr,\n", "");
+ FPS "%-20s other, registerid, rfc822, uri, x400, x400addr\n", "");
+ FPS "%-20s \n"
+ "%-20s Add one or multiple extensions that certutil cannot encode yet,\n"
+ "%-20s by loading their encodings from external files.\n",
+ " --extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...", "", "");
+ FPS "%-20s - OID (example): 1.2.3.4\n", "");
+ FPS "%-20s - critical-flag: critical or not-critical\n", "");
+ FPS "%-20s - filename: full path to a file containing an encoded extension\n", "");
+ FPS "\n");
+}
+
+static void
+LongUsage(char *progName, enum usage_level ul, const char *command)
+{
+ luA(ul, command);
+ luB(ul, command);
+ luE(ul, command);
+ luC(ul, command);
+ luG(ul, command);
+ luD(ul, command);
+ luRename(ul, command);
+ luF(ul, command);
+ luU(ul, command);
+ luK(ul, command);
+ luL(ul, command);
+ luM(ul, command);
+ luN(ul, command);
+ luT(ul, command);
+ luO(ul, command);
+ luR(ul, command);
+ luV(ul, command);
+ luW(ul, command);
+ luUpgradeMerge(ul, command);
+ luMerge(ul, command);
+ luS(ul, command);
+#undef FPS
+}
+
+static void
+Usage(char *progName)
+{
+ PR_fprintf(PR_STDERR,
+ "%s - Utility to manipulate NSS certificate databases\n\n"
+ "Usage: %s <command> -d <database-directory> <options>\n\n"
+ "Valid commands:\n",
+ progName, progName);
+ LongUsage(progName, usage_selected, NULL);
+ PR_fprintf(PR_STDERR, "\n"
+ "%s -H <command> : Print available options for the given command\n"
+ "%s -H : Print complete help output of all commands and options\n"
+ "%s --syntax : Print a short summary of all commands and options\n",
+ progName, progName, progName);
+ exit(1);
+}
+
+static CERTCertificate *
+MakeV1Cert(CERTCertDBHandle *handle,
+ CERTCertificateRequest *req,
+ char *issuerNickName,
+ PRBool selfsign,
+ unsigned int serialNumber,
+ int warpmonths,
+ int validityMonths)
+{
+ CERTCertificate *issuerCert = NULL;
+ CERTValidity *validity;
+ CERTCertificate *cert = NULL;
+ PRExplodedTime printableTime;
+ PRTime now, after;
+
+ if (!selfsign) {
+ issuerCert = CERT_FindCertByNicknameOrEmailAddr(handle, issuerNickName);
+ if (!issuerCert) {
+ SECU_PrintError(progName, "could not find certificate named \"%s\"",
+ issuerNickName);
+ return NULL;
+ }
+ }
+
+ now = PR_Now();
+ PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
+ if (warpmonths) {
+ printableTime.tm_month += warpmonths;
+ now = PR_ImplodeTime(&printableTime);
+ PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
+ }
+ printableTime.tm_month += validityMonths;
+ after = PR_ImplodeTime(&printableTime);
+
+ /* note that the time is now in micro-second unit */
+ validity = CERT_CreateValidity(now, after);
+ if (validity) {
+ cert = CERT_CreateCertificate(serialNumber,
+ (selfsign ? &req->subject
+ : &issuerCert->subject),
+ validity, req);
+
+ CERT_DestroyValidity(validity);
+ }
+ if (issuerCert) {
+ CERT_DestroyCertificate(issuerCert);
+ }
+
+ return (cert);
+}
+
+static SECStatus
+SignCert(CERTCertDBHandle *handle, CERTCertificate *cert, PRBool selfsign,
+ SECOidTag hashAlgTag,
+ SECKEYPrivateKey *privKey, char *issuerNickName,
+ int certVersion, void *pwarg)
+{
+ SECItem der;
+ SECKEYPrivateKey *caPrivateKey = NULL;
+ SECStatus rv;
+ PLArenaPool *arena;
+ SECOidTag algID;
+ void *dummy;
+
+ if (!selfsign) {
+ CERTCertificate *issuer = PK11_FindCertFromNickname(issuerNickName, pwarg);
+ if ((CERTCertificate *)NULL == issuer) {
+ SECU_PrintError(progName, "unable to find issuer with nickname %s",
+ issuerNickName);
+ return SECFailure;
+ }
+
+ privKey = caPrivateKey = PK11_FindKeyByAnyCert(issuer, pwarg);
+ CERT_DestroyCertificate(issuer);
+ if (caPrivateKey == NULL) {
+ SECU_PrintError(progName, "unable to retrieve key %s", issuerNickName);
+ return SECFailure;
+ }
+ }
+
+ arena = cert->arena;
+
+ algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, hashAlgTag);
+ if (algID == SEC_OID_UNKNOWN) {
+ fprintf(stderr, "Unknown key or hash type for issuer.");
+ rv = SECFailure;
+ goto done;
+ }
+
+ rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "Could not set signature algorithm id.");
+ goto done;
+ }
+
+ switch (certVersion) {
+ case (SEC_CERTIFICATE_VERSION_1):
+ /* The initial version for x509 certificates is version one
+ * and this default value must be an implicit DER encoding. */
+ cert->version.data = NULL;
+ cert->version.len = 0;
+ break;
+ case (SEC_CERTIFICATE_VERSION_2):
+ case (SEC_CERTIFICATE_VERSION_3):
+ case 3: /* unspecified format (would be version 4 certificate). */
+ *(cert->version.data) = certVersion;
+ cert->version.len = 1;
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ der.len = 0;
+ der.data = NULL;
+ dummy = SEC_ASN1EncodeItem(arena, &der, cert,
+ SEC_ASN1_GET(CERT_CertificateTemplate));
+ if (!dummy) {
+ fprintf(stderr, "Could not encode certificate.\n");
+ rv = SECFailure;
+ goto done;
+ }
+
+ rv = SEC_DerSignData(arena, &cert->derCert, der.data, der.len, privKey, algID);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "Could not sign encoded certificate data.\n");
+ /* result allocated out of the arena, it will be freed
+ * when the arena is freed */
+ goto done;
+ }
+done:
+ if (caPrivateKey) {
+ SECKEY_DestroyPrivateKey(caPrivateKey);
+ }
+ return rv;
+}
+
+static SECStatus
+CreateCert(
+ CERTCertDBHandle *handle,
+ PK11SlotInfo *slot,
+ char *issuerNickName,
+ const SECItem *certReqDER,
+ SECKEYPrivateKey **selfsignprivkey,
+ void *pwarg,
+ SECOidTag hashAlgTag,
+ unsigned int serialNumber,
+ int warpmonths,
+ int validityMonths,
+ const char *emailAddrs,
+ const char *dnsNames,
+ PRBool ascii,
+ PRBool selfsign,
+ certutilExtnList extnList,
+ const char *extGeneric,
+ int certVersion,
+ SECItem *certDER)
+{
+ void *extHandle = NULL;
+ CERTCertificate *subjectCert = NULL;
+ CERTCertificateRequest *certReq = NULL;
+ SECStatus rv = SECSuccess;
+ CERTCertExtension **CRexts;
+
+ do {
+ /* Create a certrequest object from the input cert request der */
+ certReq = GetCertRequest(certReqDER, pwarg);
+ if (certReq == NULL) {
+ GEN_BREAK(SECFailure)
+ }
+
+ subjectCert = MakeV1Cert(handle, certReq, issuerNickName, selfsign,
+ serialNumber, warpmonths, validityMonths);
+ if (subjectCert == NULL) {
+ GEN_BREAK(SECFailure)
+ }
+
+ extHandle = CERT_StartCertExtensions(subjectCert);
+ if (extHandle == NULL) {
+ GEN_BREAK(SECFailure)
+ }
+
+ rv = AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric);
+ if (rv != SECSuccess) {
+ GEN_BREAK(SECFailure)
+ }
+
+ if (certReq->attributes != NULL &&
+ certReq->attributes[0] != NULL &&
+ certReq->attributes[0]->attrType.data != NULL &&
+ certReq->attributes[0]->attrType.len > 0 &&
+ SECOID_FindOIDTag(&certReq->attributes[0]->attrType) ==
+ SEC_OID_PKCS9_EXTENSION_REQUEST) {
+ rv = CERT_GetCertificateRequestExtensions(certReq, &CRexts);
+ if (rv != SECSuccess)
+ break;
+ rv = CERT_MergeExtensions(extHandle, CRexts);
+ if (rv != SECSuccess)
+ break;
+ }
+
+ CERT_FinishExtensions(extHandle);
+ extHandle = NULL;
+
+ /* self-signing a cert request, find the private key */
+ if (selfsign && *selfsignprivkey == NULL) {
+ *selfsignprivkey = PK11_FindKeyByDERCert(slot, subjectCert, pwarg);
+ if (!*selfsignprivkey) {
+ fprintf(stderr, "Failed to locate private key.\n");
+ rv = SECFailure;
+ break;
+ }
+ }
+
+ rv = SignCert(handle, subjectCert, selfsign, hashAlgTag,
+ *selfsignprivkey, issuerNickName,
+ certVersion, pwarg);
+ if (rv != SECSuccess)
+ break;
+
+ rv = SECFailure;
+ if (ascii) {
+ char *asciiDER = BTOA_DataToAscii(subjectCert->derCert.data,
+ subjectCert->derCert.len);
+ if (asciiDER) {
+ char *wrapped = PR_smprintf("%s\n%s\n%s\n",
+ NS_CERT_HEADER,
+ asciiDER,
+ NS_CERT_TRAILER);
+ if (wrapped) {
+ PRUint32 wrappedLen = PL_strlen(wrapped);
+ if (SECITEM_AllocItem(NULL, certDER, wrappedLen)) {
+ PORT_Memcpy(certDER->data, wrapped, wrappedLen);
+ rv = SECSuccess;
+ }
+ PR_smprintf_free(wrapped);
+ }
+ PORT_Free(asciiDER);
+ }
+ } else {
+ rv = SECITEM_CopyItem(NULL, certDER, &subjectCert->derCert);
+ }
+ } while (0);
+ if (extHandle) {
+ CERT_FinishExtensions(extHandle);
+ }
+ CERT_DestroyCertificateRequest(certReq);
+ CERT_DestroyCertificate(subjectCert);
+ if (rv != SECSuccess) {
+ PRErrorCode perr = PR_GetError();
+ fprintf(stderr, "%s: unable to create cert (%s)\n", progName,
+ SECU_Strerror(perr));
+ }
+ return (rv);
+}
+
+/*
+ * map a class to a user presentable string
+ */
+static const char *objClassArray[] = {
+ "Data",
+ "Certificate",
+ "Public Key",
+ "Private Key",
+ "Secret Key",
+ "Hardware Feature",
+ "Domain Parameters",
+ "Mechanism"
+};
+
+static const char *objNSSClassArray[] = {
+ "CKO_NSS",
+ "Crl",
+ "SMIME Record",
+ "Trust",
+ "Builtin Root List"
+};
+
+const char *
+getObjectClass(CK_ULONG classType)
+{
+ static char buf[sizeof(CK_ULONG) * 2 + 3];
+
+ if (classType <= CKO_MECHANISM) {
+ return objClassArray[classType];
+ }
+ if (classType >= CKO_NSS && classType <= CKO_NSS_BUILTIN_ROOT_LIST) {
+ return objNSSClassArray[classType - CKO_NSS];
+ }
+ sprintf(buf, "0x%lx", classType);
+ return buf;
+}
+
+typedef struct {
+ char *name;
+ int nameSize;
+ CK_ULONG value;
+} flagArray;
+
+#define NAME_SIZE(x) #x, sizeof(#x) - 1
+
+flagArray opFlagsArray[] =
+ {
+ { NAME_SIZE(encrypt), CKF_ENCRYPT },
+ { NAME_SIZE(decrypt), CKF_DECRYPT },
+ { NAME_SIZE(sign), CKF_SIGN },
+ { NAME_SIZE(sign_recover), CKF_SIGN_RECOVER },
+ { NAME_SIZE(verify), CKF_VERIFY },
+ { NAME_SIZE(verify_recover), CKF_VERIFY_RECOVER },
+ { NAME_SIZE(wrap), CKF_WRAP },
+ { NAME_SIZE(unwrap), CKF_UNWRAP },
+ { NAME_SIZE(derive), CKF_DERIVE },
+ };
+
+int opFlagsCount = sizeof(opFlagsArray) / sizeof(flagArray);
+
+flagArray attrFlagsArray[] =
+ {
+ { NAME_SIZE(token), PK11_ATTR_TOKEN },
+ { NAME_SIZE(session), PK11_ATTR_SESSION },
+ { NAME_SIZE(private), PK11_ATTR_PRIVATE },
+ { NAME_SIZE(public), PK11_ATTR_PUBLIC },
+ { NAME_SIZE(modifiable), PK11_ATTR_MODIFIABLE },
+ { NAME_SIZE(unmodifiable), PK11_ATTR_UNMODIFIABLE },
+ { NAME_SIZE(sensitive), PK11_ATTR_SENSITIVE },
+ { NAME_SIZE(insensitive), PK11_ATTR_INSENSITIVE },
+ { NAME_SIZE(extractable), PK11_ATTR_EXTRACTABLE },
+ { NAME_SIZE(unextractable), PK11_ATTR_UNEXTRACTABLE }
+
+ };
+
+int attrFlagsCount = sizeof(attrFlagsArray) / sizeof(flagArray);
+
+#define MAX_STRING 30
+CK_ULONG
+GetFlags(char *flagsString, flagArray *flagArray, int count)
+{
+ CK_ULONG flagsValue = strtol(flagsString, NULL, 0);
+ int i;
+
+ if ((flagsValue != 0) || (*flagsString == 0)) {
+ return flagsValue;
+ }
+ while (*flagsString) {
+ for (i = 0; i < count; i++) {
+ if (strncmp(flagsString, flagArray[i].name, flagArray[i].nameSize) ==
+ 0) {
+ flagsValue |= flagArray[i].value;
+ flagsString += flagArray[i].nameSize;
+ if (*flagsString != 0) {
+ flagsString++;
+ }
+ break;
+ }
+ }
+ if (i == count) {
+ char name[MAX_STRING];
+ char *tok;
+
+ strncpy(name, flagsString, MAX_STRING);
+ name[MAX_STRING - 1] = 0;
+ tok = strchr(name, ',');
+ if (tok) {
+ *tok = 0;
+ }
+ fprintf(stderr, "Unknown flag (%s)\n", name);
+ tok = strchr(flagsString, ',');
+ if (tok == NULL) {
+ break;
+ }
+ flagsString = tok + 1;
+ }
+ }
+ return flagsValue;
+}
+
+CK_FLAGS
+GetOpFlags(char *flags)
+{
+ return GetFlags(flags, opFlagsArray, opFlagsCount);
+}
+
+PK11AttrFlags
+GetAttrFlags(char *flags)
+{
+ return GetFlags(flags, attrFlagsArray, attrFlagsCount);
+}
+
+char *
+mkNickname(unsigned char *data, int len)
+{
+ char *nick = PORT_Alloc(len + 1);
+ if (!nick) {
+ return nick;
+ }
+ PORT_Memcpy(nick, data, len);
+ nick[len] = 0;
+ return nick;
+}
+
+/*
+ * dump a PK11_MergeTokens error log to the console
+ */
+void
+DumpMergeLog(const char *progname, PK11MergeLog *log)
+{
+ PK11MergeLogNode *node;
+
+ for (node = log->head; node; node = node->next) {
+ SECItem attrItem;
+ char *nickname = NULL;
+ const char *objectClass = NULL;
+ SECStatus rv;
+
+ attrItem.data = NULL;
+ rv = PK11_ReadRawAttribute(PK11_TypeGeneric, node->object,
+ CKA_LABEL, &attrItem);
+ if (rv == SECSuccess) {
+ nickname = mkNickname(attrItem.data, attrItem.len);
+ PORT_Free(attrItem.data);
+ }
+ attrItem.data = NULL;
+ rv = PK11_ReadRawAttribute(PK11_TypeGeneric, node->object,
+ CKA_CLASS, &attrItem);
+ if (rv == SECSuccess) {
+ if (attrItem.len == sizeof(CK_ULONG)) {
+ objectClass = getObjectClass(*(CK_ULONG *)attrItem.data);
+ }
+ PORT_Free(attrItem.data);
+ }
+
+ fprintf(stderr, "%s: Could not merge object %s (type %s): %s\n",
+ progName,
+ nickname ? nickname : "unnamed",
+ objectClass ? objectClass : "unknown",
+ SECU_Strerror(node->error));
+
+ if (nickname) {
+ PORT_Free(nickname);
+ }
+ }
+}
+
+/* Certutil commands */
+enum {
+ cmd_AddCert = 0,
+ cmd_CreateNewCert,
+ cmd_DeleteCert,
+ cmd_AddEmailCert,
+ cmd_DeleteKey,
+ cmd_GenKeyPair,
+ cmd_PrintHelp,
+ cmd_PrintSyntax,
+ cmd_ListKeys,
+ cmd_ListCerts,
+ cmd_ModifyCertTrust,
+ cmd_NewDBs,
+ cmd_DumpChain,
+ cmd_CertReq,
+ cmd_CreateAndAddCert,
+ cmd_TokenReset,
+ cmd_ListModules,
+ cmd_CheckCertValidity,
+ cmd_ChangePassword,
+ cmd_Version,
+ cmd_Batch,
+ cmd_Merge,
+ cmd_UpgradeMerge, /* test only */
+ cmd_Rename,
+ max_cmd
+};
+
+/* Certutil options */
+enum certutilOpts {
+ opt_SSOPass = 0,
+ opt_AddKeyUsageExt,
+ opt_AddBasicConstraintExt,
+ opt_AddAuthorityKeyIDExt,
+ opt_AddCRLDistPtsExt,
+ opt_AddNSCertTypeExt,
+ opt_AddExtKeyUsageExt,
+ opt_ExtendedEmailAddrs,
+ opt_ExtendedDNSNames,
+ opt_ASCIIForIO,
+ opt_ValidityTime,
+ opt_IssuerName,
+ opt_CertDir,
+ opt_VerifySig,
+ opt_PasswordFile,
+ opt_KeySize,
+ opt_TokenName,
+ opt_InputFile,
+ opt_Emailaddress,
+ opt_KeyIndex,
+ opt_KeyType,
+ opt_DetailedInfo,
+ opt_SerialNumber,
+ opt_Nickname,
+ opt_OutputFile,
+ opt_PhoneNumber,
+ opt_DBPrefix,
+ opt_PQGFile,
+ opt_BinaryDER,
+ opt_Subject,
+ opt_Trust,
+ opt_Usage,
+ opt_Validity,
+ opt_OffsetMonths,
+ opt_SelfSign,
+ opt_RW,
+ opt_Exponent,
+ opt_NoiseFile,
+ opt_Hash,
+ opt_NewPasswordFile,
+ opt_AddAuthInfoAccExt,
+ opt_AddSubjInfoAccExt,
+ opt_AddCertPoliciesExt,
+ opt_AddPolicyMapExt,
+ opt_AddPolicyConstrExt,
+ opt_AddInhibAnyExt,
+ opt_AddNameConstraintsExt,
+ opt_AddSubjectKeyIDExt,
+ opt_AddCmdKeyUsageExt,
+ opt_AddCmdNSCertTypeExt,
+ opt_AddCmdExtKeyUsageExt,
+ opt_SourceDir,
+ opt_SourcePrefix,
+ opt_UpgradeID,
+ opt_UpgradeTokenName,
+ opt_KeyOpFlagsOn,
+ opt_KeyOpFlagsOff,
+ opt_KeyAttrFlags,
+ opt_EmptyPassword,
+ opt_CertVersion,
+ opt_AddSubjectAltNameExt,
+ opt_DumpExtensionValue,
+ opt_GenericExtensions,
+ opt_NewNickname,
+ opt_Pss,
+ opt_Help
+};
+
+static const secuCommandFlag commands_init[] =
+ {
+ { /* cmd_AddCert */ 'A', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_CreateNewCert */ 'C', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_DeleteCert */ 'D', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_AddEmailCert */ 'E', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_DeleteKey */ 'F', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_GenKeyPair */ 'G', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_PrintHelp */ 'H', PR_FALSE, 0, PR_FALSE, "help" },
+ { /* cmd_PrintSyntax */ 0, PR_FALSE, 0, PR_FALSE,
+ "syntax" },
+ { /* cmd_ListKeys */ 'K', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ListCerts */ 'L', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ModifyCertTrust */ 'M', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_NewDBs */ 'N', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_DumpChain */ 'O', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_CertReq */ 'R', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_CreateAndAddCert */ 'S', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_TokenReset */ 'T', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ListModules */ 'U', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_CheckCertValidity */ 'V', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ChangePassword */ 'W', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Version */ 'Y', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Batch */ 'B', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Merge */ 0, PR_FALSE, 0, PR_FALSE, "merge" },
+ { /* cmd_UpgradeMerge */ 0, PR_FALSE, 0, PR_FALSE,
+ "upgrade-merge" },
+ { /* cmd_Rename */ 0, PR_FALSE, 0, PR_FALSE,
+ "rename" }
+ };
+#define NUM_COMMANDS ((sizeof commands_init) / (sizeof commands_init[0]))
+
+static const secuCommandFlag options_init[] =
+ {
+ { /* opt_SSOPass */ '0', PR_TRUE, 0, PR_FALSE },
+ { /* opt_AddKeyUsageExt */ '1', PR_FALSE, 0, PR_FALSE },
+ { /* opt_AddBasicConstraintExt*/ '2', PR_FALSE, 0, PR_FALSE },
+ { /* opt_AddAuthorityKeyIDExt*/ '3', PR_FALSE, 0, PR_FALSE },
+ { /* opt_AddCRLDistPtsExt */ '4', PR_FALSE, 0, PR_FALSE },
+ { /* opt_AddNSCertTypeExt */ '5', PR_FALSE, 0, PR_FALSE },
+ { /* opt_AddExtKeyUsageExt */ '6', PR_FALSE, 0, PR_FALSE },
+ { /* opt_ExtendedEmailAddrs */ '7', PR_TRUE, 0, PR_FALSE },
+ { /* opt_ExtendedDNSNames */ '8', PR_TRUE, 0, PR_FALSE },
+ { /* opt_ASCIIForIO */ 'a', PR_FALSE, 0, PR_FALSE },
+ { /* opt_ValidityTime */ 'b', PR_TRUE, 0, PR_FALSE },
+ { /* opt_IssuerName */ 'c', PR_TRUE, 0, PR_FALSE },
+ { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_VerifySig */ 'e', PR_FALSE, 0, PR_FALSE },
+ { /* opt_PasswordFile */ 'f', PR_TRUE, 0, PR_FALSE },
+ { /* opt_KeySize */ 'g', PR_TRUE, 0, PR_FALSE },
+ { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE },
+ { /* opt_InputFile */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Emailaddress */ 0, PR_TRUE, 0, PR_FALSE, "email" },
+ { /* opt_KeyIndex */ 'j', PR_TRUE, 0, PR_FALSE },
+ { /* opt_KeyType */ 'k', PR_TRUE, 0, PR_FALSE },
+ { /* opt_DetailedInfo */ 'l', PR_FALSE, 0, PR_FALSE },
+ { /* opt_SerialNumber */ 'm', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE },
+ { /* opt_OutputFile */ 'o', PR_TRUE, 0, PR_FALSE },
+ { /* opt_PhoneNumber */ 'p', PR_TRUE, 0, PR_FALSE },
+ { /* opt_DBPrefix */ 'P', PR_TRUE, 0, PR_FALSE },
+ { /* opt_PQGFile */ 'q', PR_TRUE, 0, PR_FALSE },
+ { /* opt_BinaryDER */ 'r', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Subject */ 's', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Trust */ 't', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Usage */ 'u', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Validity */ 'v', PR_TRUE, 0, PR_FALSE },
+ { /* opt_OffsetMonths */ 'w', PR_TRUE, 0, PR_FALSE },
+ { /* opt_SelfSign */ 'x', PR_FALSE, 0, PR_FALSE },
+ { /* opt_RW */ 'X', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Exponent */ 'y', PR_TRUE, 0, PR_FALSE },
+ { /* opt_NoiseFile */ 'z', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Hash */ 'Z', PR_TRUE, 0, PR_FALSE },
+ { /* opt_NewPasswordFile */ '@', PR_TRUE, 0, PR_FALSE },
+ { /* opt_AddAuthInfoAccExt */ 0, PR_FALSE, 0, PR_FALSE, "extAIA" },
+ { /* opt_AddSubjInfoAccExt */ 0, PR_FALSE, 0, PR_FALSE, "extSIA" },
+ { /* opt_AddCertPoliciesExt */ 0, PR_FALSE, 0, PR_FALSE, "extCP" },
+ { /* opt_AddPolicyMapExt */ 0, PR_FALSE, 0, PR_FALSE, "extPM" },
+ { /* opt_AddPolicyConstrExt */ 0, PR_FALSE, 0, PR_FALSE, "extPC" },
+ { /* opt_AddInhibAnyExt */ 0, PR_FALSE, 0, PR_FALSE, "extIA" },
+ { /* opt_AddNameConstraintsExt*/ 0, PR_FALSE, 0, PR_FALSE, "extNC" },
+ { /* opt_AddSubjectKeyIDExt */ 0, PR_FALSE, 0, PR_FALSE,
+ "extSKID" },
+ { /* opt_AddCmdKeyUsageExt */ 0, PR_TRUE, 0, PR_FALSE,
+ "keyUsage" },
+ { /* opt_AddCmdNSCertTypeExt */ 0, PR_TRUE, 0, PR_FALSE,
+ "nsCertType" },
+ { /* opt_AddCmdExtKeyUsageExt*/ 0, PR_TRUE, 0, PR_FALSE,
+ "extKeyUsage" },
+
+ { /* opt_SourceDir */ 0, PR_TRUE, 0, PR_FALSE,
+ "source-dir" },
+ { /* opt_SourcePrefix */ 0, PR_TRUE, 0, PR_FALSE,
+ "source-prefix" },
+ { /* opt_UpgradeID */ 0, PR_TRUE, 0, PR_FALSE,
+ "upgrade-id" },
+ { /* opt_UpgradeTokenName */ 0, PR_TRUE, 0, PR_FALSE,
+ "upgrade-token-name" },
+ { /* opt_KeyOpFlagsOn */ 0, PR_TRUE, 0, PR_FALSE,
+ "keyOpFlagsOn" },
+ { /* opt_KeyOpFlagsOff */ 0, PR_TRUE, 0, PR_FALSE,
+ "keyOpFlagsOff" },
+ { /* opt_KeyAttrFlags */ 0, PR_TRUE, 0, PR_FALSE,
+ "keyAttrFlags" },
+ { /* opt_EmptyPassword */ 0, PR_FALSE, 0, PR_FALSE,
+ "empty-password" },
+ { /* opt_CertVersion */ 0, PR_TRUE, 0, PR_FALSE,
+ "certVersion" },
+ { /* opt_AddSubjectAltExt */ 0, PR_TRUE, 0, PR_FALSE, "extSAN" },
+ { /* opt_DumpExtensionValue */ 0, PR_TRUE, 0, PR_FALSE,
+ "dump-ext-val" },
+ { /* opt_GenericExtensions */ 0, PR_TRUE, 0, PR_FALSE,
+ "extGeneric" },
+ { /* opt_NewNickname */ 0, PR_TRUE, 0, PR_FALSE,
+ "new-n" },
+ { /* opt_Pss */ 0, PR_FALSE, 0, PR_FALSE,
+ "pss" },
+ };
+#define NUM_OPTIONS ((sizeof options_init) / (sizeof options_init[0]))
+
+static secuCommandFlag certutil_commands[NUM_COMMANDS];
+static secuCommandFlag certutil_options[NUM_OPTIONS];
+
+static const secuCommand certutil = {
+ NUM_COMMANDS,
+ NUM_OPTIONS,
+ certutil_commands,
+ certutil_options
+};
+
+static certutilExtnList certutil_extns;
+
+static int
+certutil_main(int argc, char **argv, PRBool initialize)
+{
+ CERTCertDBHandle *certHandle;
+ PK11SlotInfo *slot = NULL;
+ CERTName *subject = 0;
+ PRFileDesc *inFile = PR_STDIN;
+ PRFileDesc *outFile = PR_STDOUT;
+ SECItem certReqDER = { siBuffer, NULL, 0 };
+ SECItem certDER = { siBuffer, NULL, 0 };
+ const char *slotname = "internal";
+ const char *certPrefix = "";
+ char *sourceDir = "";
+ const char *srcCertPrefix = "";
+ char *upgradeID = "";
+ char *upgradeTokenName = "";
+ KeyType keytype = rsaKey;
+ char *name = NULL;
+ char *newName = NULL;
+ char *email = NULL;
+ char *keysource = NULL;
+ SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
+ int keysize = DEFAULT_KEY_BITS;
+ int publicExponent = 0x010001;
+ int certVersion = SEC_CERTIFICATE_VERSION_3;
+ unsigned int serialNumber = 0;
+ int warpmonths = 0;
+ int validityMonths = 3;
+ int commandsEntered = 0;
+ char commandToRun = '\0';
+ secuPWData pwdata = { PW_NONE, 0 };
+ secuPWData pwdata2 = { PW_NONE, 0 };
+ PRBool readOnly = PR_FALSE;
+ PRBool initialized = PR_FALSE;
+ CK_FLAGS keyOpFlagsOn = 0;
+ CK_FLAGS keyOpFlagsOff = 0;
+ PK11AttrFlags keyAttrFlags =
+ PK11_ATTR_TOKEN | PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE;
+
+ SECKEYPrivateKey *privkey = NULL;
+ SECKEYPublicKey *pubkey = NULL;
+
+ int i;
+ SECStatus rv;
+
+ progName = PORT_Strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+ memcpy(certutil_commands, commands_init, sizeof commands_init);
+ memcpy(certutil_options, options_init, sizeof options_init);
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &certutil);
+
+ if (rv != SECSuccess)
+ Usage(progName);
+
+ if (certutil.commands[cmd_PrintSyntax].activated) {
+ PrintSyntax(progName);
+ }
+
+ if (certutil.commands[cmd_PrintHelp].activated) {
+ int i;
+ char buf[2];
+ const char *command = NULL;
+ for (i = 0; i < max_cmd; i++) {
+ if (i == cmd_PrintHelp)
+ continue;
+ if (certutil.commands[i].activated) {
+ if (certutil.commands[i].flag) {
+ buf[0] = certutil.commands[i].flag;
+ buf[1] = 0;
+ command = buf;
+ } else {
+ command = certutil.commands[i].longform;
+ }
+ break;
+ }
+ }
+ LongUsage(progName, (command ? usage_selected : usage_all), command);
+ exit(1);
+ }
+
+ if (certutil.options[opt_PasswordFile].arg) {
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = certutil.options[opt_PasswordFile].arg;
+ }
+ if (certutil.options[opt_NewPasswordFile].arg) {
+ pwdata2.source = PW_FROMFILE;
+ pwdata2.data = certutil.options[opt_NewPasswordFile].arg;
+ }
+
+ if (certutil.options[opt_CertDir].activated)
+ SECU_ConfigDirectory(certutil.options[opt_CertDir].arg);
+
+ if (certutil.options[opt_SourceDir].activated)
+ sourceDir = certutil.options[opt_SourceDir].arg;
+
+ if (certutil.options[opt_UpgradeID].activated)
+ upgradeID = certutil.options[opt_UpgradeID].arg;
+
+ if (certutil.options[opt_UpgradeTokenName].activated)
+ upgradeTokenName = certutil.options[opt_UpgradeTokenName].arg;
+
+ if (certutil.options[opt_KeySize].activated) {
+ keysize = PORT_Atoi(certutil.options[opt_KeySize].arg);
+ if ((keysize < MIN_KEY_BITS) || (keysize > MAX_KEY_BITS)) {
+ PR_fprintf(PR_STDERR,
+ "%s -g: Keysize must be between %d and %d.\n",
+ progName, MIN_KEY_BITS, MAX_KEY_BITS);
+ return 255;
+ }
+#ifndef NSS_DISABLE_ECC
+ if (keytype == ecKey) {
+ PR_fprintf(PR_STDERR, "%s -g: Not for ec keys.\n", progName);
+ return 255;
+ }
+#endif /* NSS_DISABLE_ECC */
+ }
+
+ /* -h specify token name */
+ if (certutil.options[opt_TokenName].activated) {
+ if (PL_strcmp(certutil.options[opt_TokenName].arg, "all") == 0)
+ slotname = NULL;
+ else
+ slotname = certutil.options[opt_TokenName].arg;
+ }
+
+ /* -Z hash type */
+ if (certutil.options[opt_Hash].activated) {
+ char *arg = certutil.options[opt_Hash].arg;
+ hashAlgTag = SECU_StringToSignatureAlgTag(arg);
+ if (hashAlgTag == SEC_OID_UNKNOWN) {
+ PR_fprintf(PR_STDERR, "%s -Z: %s is not a recognized type.\n",
+ progName, arg);
+ return 255;
+ }
+ }
+
+ /* -k key type */
+ if (certutil.options[opt_KeyType].activated) {
+ char *arg = certutil.options[opt_KeyType].arg;
+ if (PL_strcmp(arg, "rsa") == 0) {
+ keytype = rsaKey;
+ } else if (PL_strcmp(arg, "dsa") == 0) {
+ keytype = dsaKey;
+#ifndef NSS_DISABLE_ECC
+ } else if (PL_strcmp(arg, "ec") == 0) {
+ keytype = ecKey;
+#endif /* NSS_DISABLE_ECC */
+ } else if (PL_strcmp(arg, "all") == 0) {
+ keytype = nullKey;
+ } else {
+ /* use an existing private/public key pair */
+ keysource = arg;
+ }
+ } else if (certutil.commands[cmd_ListKeys].activated) {
+ keytype = nullKey;
+ }
+
+ if (certutil.options[opt_KeyOpFlagsOn].activated) {
+ keyOpFlagsOn = GetOpFlags(certutil.options[opt_KeyOpFlagsOn].arg);
+ }
+ if (certutil.options[opt_KeyOpFlagsOff].activated) {
+ keyOpFlagsOff = GetOpFlags(certutil.options[opt_KeyOpFlagsOff].arg);
+ keyOpFlagsOn &= ~keyOpFlagsOff; /* make off override on */
+ }
+ if (certutil.options[opt_KeyAttrFlags].activated) {
+ keyAttrFlags = GetAttrFlags(certutil.options[opt_KeyAttrFlags].arg);
+ }
+
+ /* -m serial number */
+ if (certutil.options[opt_SerialNumber].activated) {
+ int sn = PORT_Atoi(certutil.options[opt_SerialNumber].arg);
+ if (sn < 0) {
+ PR_fprintf(PR_STDERR, "%s -m: %s is not a valid serial number.\n",
+ progName, certutil.options[opt_SerialNumber].arg);
+ return 255;
+ }
+ serialNumber = sn;
+ }
+
+ /* -P certdb name prefix */
+ if (certutil.options[opt_DBPrefix].activated) {
+ if (certutil.options[opt_DBPrefix].arg) {
+ certPrefix = certutil.options[opt_DBPrefix].arg;
+ } else {
+ Usage(progName);
+ }
+ }
+
+ /* --source-prefix certdb name prefix */
+ if (certutil.options[opt_SourcePrefix].activated) {
+ if (certutil.options[opt_SourcePrefix].arg) {
+ srcCertPrefix = certutil.options[opt_SourcePrefix].arg;
+ } else {
+ Usage(progName);
+ }
+ }
+
+ /* -q PQG file or curve name */
+ if (certutil.options[opt_PQGFile].activated) {
+#ifndef NSS_DISABLE_ECC
+ if ((keytype != dsaKey) && (keytype != ecKey)) {
+ PR_fprintf(PR_STDERR, "%s -q: specifies a PQG file for DSA keys"
+ " (-k dsa) or a named curve for EC keys (-k ec)\n)",
+ progName);
+#else /* } */
+ if (keytype != dsaKey) {
+ PR_fprintf(PR_STDERR, "%s -q: PQG file is for DSA key (-k dsa).\n)",
+ progName);
+#endif /* NSS_DISABLE_ECC */
+ return 255;
+ }
+ }
+
+ /* -s subject name */
+ if (certutil.options[opt_Subject].activated) {
+ subject = CERT_AsciiToName(certutil.options[opt_Subject].arg);
+ if (!subject) {
+ PR_fprintf(PR_STDERR, "%s -s: improperly formatted name: \"%s\"\n",
+ progName, certutil.options[opt_Subject].arg);
+ return 255;
+ }
+ }
+
+ /* -v validity period */
+ if (certutil.options[opt_Validity].activated) {
+ validityMonths = PORT_Atoi(certutil.options[opt_Validity].arg);
+ if (validityMonths < 0) {
+ PR_fprintf(PR_STDERR, "%s -v: incorrect validity period: \"%s\"\n",
+ progName, certutil.options[opt_Validity].arg);
+ return 255;
+ }
+ }
+
+ /* -w warp months */
+ if (certutil.options[opt_OffsetMonths].activated)
+ warpmonths = PORT_Atoi(certutil.options[opt_OffsetMonths].arg);
+
+ /* -y public exponent (for RSA) */
+ if (certutil.options[opt_Exponent].activated) {
+ publicExponent = PORT_Atoi(certutil.options[opt_Exponent].arg);
+ if ((publicExponent != 3) &&
+ (publicExponent != 17) &&
+ (publicExponent != 65537)) {
+ PR_fprintf(PR_STDERR, "%s -y: incorrect public exponent %d.",
+ progName, publicExponent);
+ PR_fprintf(PR_STDERR, "Must be 3, 17, or 65537.\n");
+ return 255;
+ }
+ }
+
+ /* --certVersion */
+ if (certutil.options[opt_CertVersion].activated) {
+ certVersion = PORT_Atoi(certutil.options[opt_CertVersion].arg);
+ if (certVersion < 1 || certVersion > 4) {
+ PR_fprintf(PR_STDERR, "%s -certVersion: incorrect certificate version %d.",
+ progName, certVersion);
+ PR_fprintf(PR_STDERR, "Must be 1, 2, 3 or 4.\n");
+ return 255;
+ }
+ certVersion = certVersion - 1;
+ }
+
+ /* Check number of commands entered. */
+ commandsEntered = 0;
+ for (i = 0; i < certutil.numCommands; i++) {
+ if (certutil.commands[i].activated) {
+ commandToRun = certutil.commands[i].flag;
+ commandsEntered++;
+ }
+ if (commandsEntered > 1)
+ break;
+ }
+ if (commandsEntered > 1) {
+ PR_fprintf(PR_STDERR, "%s: only one command at a time!\n", progName);
+ PR_fprintf(PR_STDERR, "You entered: ");
+ for (i = 0; i < certutil.numCommands; i++) {
+ if (certutil.commands[i].activated)
+ PR_fprintf(PR_STDERR, " -%c", certutil.commands[i].flag);
+ }
+ PR_fprintf(PR_STDERR, "\n");
+ return 255;
+ }
+ if (commandsEntered == 0) {
+ Usage(progName);
+ }
+
+ if (certutil.commands[cmd_ListCerts].activated ||
+ certutil.commands[cmd_PrintHelp].activated ||
+ certutil.commands[cmd_ListKeys].activated ||
+ certutil.commands[cmd_ListModules].activated ||
+ certutil.commands[cmd_CheckCertValidity].activated ||
+ certutil.commands[cmd_Version].activated) {
+ readOnly = !certutil.options[opt_RW].activated;
+ }
+
+ /* -A, -D, -F, -M, -S, -V, and all require -n */
+ if ((certutil.commands[cmd_AddCert].activated ||
+ certutil.commands[cmd_DeleteCert].activated ||
+ certutil.commands[cmd_DeleteKey].activated ||
+ certutil.commands[cmd_DumpChain].activated ||
+ certutil.commands[cmd_ModifyCertTrust].activated ||
+ certutil.commands[cmd_CreateAndAddCert].activated ||
+ certutil.commands[cmd_CheckCertValidity].activated) &&
+ !certutil.options[opt_Nickname].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: nickname is required for this command (-n).\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ /* -A, -E, -M, -S require trust */
+ if ((certutil.commands[cmd_AddCert].activated ||
+ certutil.commands[cmd_AddEmailCert].activated ||
+ certutil.commands[cmd_ModifyCertTrust].activated ||
+ certutil.commands[cmd_CreateAndAddCert].activated) &&
+ !certutil.options[opt_Trust].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: trust is required for this command (-t).\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ /* if -L is given raw, ascii or dump mode, it must be for only one cert. */
+ if (certutil.commands[cmd_ListCerts].activated &&
+ (certutil.options[opt_ASCIIForIO].activated ||
+ certutil.options[opt_DumpExtensionValue].activated ||
+ certutil.options[opt_BinaryDER].activated) &&
+ !certutil.options[opt_Nickname].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s: nickname is required to dump cert in raw or ascii mode.\n",
+ progName);
+ return 255;
+ }
+
+ /* -L can only be in (raw || ascii). */
+ if (certutil.commands[cmd_ListCerts].activated &&
+ certutil.options[opt_ASCIIForIO].activated &&
+ certutil.options[opt_BinaryDER].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s: cannot specify both -r and -a when dumping cert.\n",
+ progName);
+ return 255;
+ }
+
+ /* If making a cert request, need a subject. */
+ if ((certutil.commands[cmd_CertReq].activated ||
+ certutil.commands[cmd_CreateAndAddCert].activated) &&
+ !(certutil.options[opt_Subject].activated || keysource)) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: subject is required to create a cert request.\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ /* If making a cert, need a serial number. */
+ if ((certutil.commands[cmd_CreateNewCert].activated ||
+ certutil.commands[cmd_CreateAndAddCert].activated) &&
+ !certutil.options[opt_SerialNumber].activated) {
+ /* Make a default serial number from the current time. */
+ PRTime now = PR_Now();
+ LL_USHR(now, now, 19);
+ LL_L2UI(serialNumber, now);
+ }
+
+ /* Validation needs the usage to validate for. */
+ if (certutil.commands[cmd_CheckCertValidity].activated &&
+ !certutil.options[opt_Usage].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s -V: specify a usage to validate the cert for (-u).\n",
+ progName);
+ return 255;
+ }
+
+ /* Rename needs an old and a new nickname */
+ if (certutil.commands[cmd_Rename].activated &&
+ !(certutil.options[opt_Nickname].activated &&
+ certutil.options[opt_NewNickname].activated)) {
+
+ PR_fprintf(PR_STDERR,
+ "%s --rename: specify an old nickname (-n) and\n"
+ " a new nickname (--new-n).\n",
+ progName);
+ return 255;
+ }
+
+ /* Upgrade/Merge needs a source database and a upgrade id. */
+ if (certutil.commands[cmd_UpgradeMerge].activated &&
+ !(certutil.options[opt_SourceDir].activated &&
+ certutil.options[opt_UpgradeID].activated)) {
+
+ PR_fprintf(PR_STDERR,
+ "%s --upgrade-merge: specify an upgrade database directory "
+ "(--source-dir) and\n"
+ " an upgrade ID (--upgrade-id).\n",
+ progName);
+ return 255;
+ }
+
+ /* Merge needs a source database */
+ if (certutil.commands[cmd_Merge].activated &&
+ !certutil.options[opt_SourceDir].activated) {
+
+ PR_fprintf(PR_STDERR,
+ "%s --merge: specify an source database directory "
+ "(--source-dir)\n",
+ progName);
+ return 255;
+ }
+
+ /* To make a cert, need either a issuer or to self-sign it. */
+ if (certutil.commands[cmd_CreateAndAddCert].activated &&
+ !(certutil.options[opt_IssuerName].activated ||
+ certutil.options[opt_SelfSign].activated)) {
+ PR_fprintf(PR_STDERR,
+ "%s -S: must specify issuer (-c) or self-sign (-x).\n",
+ progName);
+ return 255;
+ }
+
+ /* Using slotname == NULL for listing keys and certs on all slots,
+ * but only that. */
+ if (!(certutil.commands[cmd_ListKeys].activated ||
+ certutil.commands[cmd_DumpChain].activated ||
+ certutil.commands[cmd_ListCerts].activated) &&
+ slotname == NULL) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: cannot use \"-h all\" for this command.\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ /* Using keytype == nullKey for list all key types, but only that. */
+ if (!certutil.commands[cmd_ListKeys].activated && keytype == nullKey) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: cannot use \"-k all\" for this command.\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ /* Open the input file. */
+ if (certutil.options[opt_InputFile].activated) {
+ inFile = PR_Open(certutil.options[opt_InputFile].arg, PR_RDONLY, 0);
+ if (!inFile) {
+ PR_fprintf(PR_STDERR,
+ "%s: unable to open \"%s\" for reading (%ld, %ld).\n",
+ progName, certutil.options[opt_InputFile].arg,
+ PR_GetError(), PR_GetOSError());
+ return 255;
+ }
+ }
+
+ /* Open the output file. */
+ if (certutil.options[opt_OutputFile].activated) {
+ outFile = PR_Open(certutil.options[opt_OutputFile].arg,
+ PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 00660);
+ if (!outFile) {
+ PR_fprintf(PR_STDERR,
+ "%s: unable to open \"%s\" for writing (%ld, %ld).\n",
+ progName, certutil.options[opt_OutputFile].arg,
+ PR_GetError(), PR_GetOSError());
+ return 255;
+ }
+ }
+
+ name = SECU_GetOptionArg(&certutil, opt_Nickname);
+ newName = SECU_GetOptionArg(&certutil, opt_NewNickname);
+ email = SECU_GetOptionArg(&certutil, opt_Emailaddress);
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ if (PR_TRUE == initialize) {
+ /* Initialize NSPR and NSS. */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ if (!certutil.commands[cmd_UpgradeMerge].activated) {
+ rv = NSS_Initialize(SECU_ConfigDirectory(NULL),
+ certPrefix, certPrefix,
+ "secmod.db", readOnly ? NSS_INIT_READONLY : 0);
+ } else {
+ rv = NSS_InitWithMerge(SECU_ConfigDirectory(NULL),
+ certPrefix, certPrefix, "secmod.db",
+ sourceDir, srcCertPrefix, srcCertPrefix,
+ upgradeID, upgradeTokenName,
+ readOnly ? NSS_INIT_READONLY : 0);
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ rv = SECFailure;
+ goto shutdown;
+ }
+ initialized = PR_TRUE;
+ SECU_RegisterDynamicOids();
+ }
+ certHandle = CERT_GetDefaultCertDB();
+
+ if (certutil.commands[cmd_Version].activated) {
+ printf("Certificate database content version: command not implemented.\n");
+ }
+
+ if (PL_strcmp(slotname, "internal") == 0)
+ slot = PK11_GetInternalKeySlot();
+ else if (slotname != NULL)
+ slot = PK11_FindSlotByName(slotname);
+
+ if (!slot && (certutil.commands[cmd_NewDBs].activated ||
+ certutil.commands[cmd_ModifyCertTrust].activated ||
+ certutil.commands[cmd_ChangePassword].activated ||
+ certutil.commands[cmd_TokenReset].activated ||
+ certutil.commands[cmd_CreateAndAddCert].activated ||
+ certutil.commands[cmd_AddCert].activated ||
+ certutil.commands[cmd_Merge].activated ||
+ certutil.commands[cmd_UpgradeMerge].activated ||
+ certutil.commands[cmd_AddEmailCert].activated)) {
+
+ SECU_PrintError(progName, "could not find the slot %s", slotname);
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+ /* If creating new database, initialize the password. */
+ if (certutil.commands[cmd_NewDBs].activated) {
+ if (certutil.options[opt_EmptyPassword].activated && (PK11_NeedUserInit(slot)))
+ PK11_InitPin(slot, (char *)NULL, "");
+ else
+ SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg,
+ certutil.options[opt_NewPasswordFile].arg);
+ }
+
+ /* walk through the upgrade merge if necessary.
+ * This option is more to test what some applications will want to do
+ * to do an automatic upgrade. The --merge command is more useful for
+ * the general case where 2 database need to be merged together.
+ */
+ if (certutil.commands[cmd_UpgradeMerge].activated) {
+ if (*upgradeTokenName == 0) {
+ upgradeTokenName = upgradeID;
+ }
+ if (!PK11_IsInternal(slot)) {
+ fprintf(stderr, "Only internal DB's can be upgraded\n");
+ rv = SECSuccess;
+ goto shutdown;
+ }
+ if (!PK11_IsRemovable(slot)) {
+ printf("database already upgraded.\n");
+ rv = SECSuccess;
+ goto shutdown;
+ }
+ if (!PK11_NeedLogin(slot)) {
+ printf("upgrade complete!\n");
+ rv = SECSuccess;
+ goto shutdown;
+ }
+ /* authenticate to the old DB if necessary */
+ if (PORT_Strcmp(PK11_GetTokenName(slot), upgradeTokenName) == 0) {
+ /* if we need a password, supply it. This will be the password
+ * for the old database */
+ rv = PK11_Authenticate(slot, PR_FALSE, &pwdata2);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Could not get password for %s",
+ upgradeTokenName);
+ goto shutdown;
+ }
+ /*
+ * if we succeeded above, but still aren't logged in, that means
+ * we just supplied the password for the old database. We may
+ * need the password for the new database. NSS will automatically
+ * change the token names at this point
+ */
+ if (PK11_IsLoggedIn(slot, &pwdata)) {
+ printf("upgrade complete!\n");
+ rv = SECSuccess;
+ goto shutdown;
+ }
+ }
+
+ /* call PK11_IsPresent to update our cached token information */
+ if (!PK11_IsPresent(slot)) {
+ /* this shouldn't happen. We call isPresent to force a token
+ * info update */
+ fprintf(stderr, "upgrade/merge internal error\n");
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+ /* the token is now set to the state of the source database,
+ * if we need a password for it, PK11_Authenticate will
+ * automatically prompt us */
+ rv = PK11_Authenticate(slot, PR_FALSE, &pwdata);
+ if (rv == SECSuccess) {
+ printf("upgrade complete!\n");
+ } else {
+ SECU_PrintError(progName, "Could not get password for %s",
+ PK11_GetTokenName(slot));
+ }
+ goto shutdown;
+ }
+
+ /*
+ * merge 2 databases.
+ */
+ if (certutil.commands[cmd_Merge].activated) {
+ PK11SlotInfo *sourceSlot = NULL;
+ PK11MergeLog *log;
+ char *modspec = PR_smprintf(
+ "configDir='%s' certPrefix='%s' tokenDescription='%s'",
+ sourceDir, srcCertPrefix,
+ *upgradeTokenName ? upgradeTokenName : "Source Database");
+
+ if (!modspec) {
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+ sourceSlot = SECMOD_OpenUserDB(modspec);
+ PR_smprintf_free(modspec);
+ if (!sourceSlot) {
+ SECU_PrintError(progName, "couldn't open source database");
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+ rv = PK11_Authenticate(slot, PR_FALSE, &pwdata);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Couldn't get password for %s",
+ PK11_GetTokenName(slot));
+ goto merge_fail;
+ }
+
+ rv = PK11_Authenticate(sourceSlot, PR_FALSE, &pwdata2);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Couldn't get password for %s",
+ PK11_GetTokenName(sourceSlot));
+ goto merge_fail;
+ }
+
+ log = PK11_CreateMergeLog();
+ if (!log) {
+ rv = SECFailure;
+ SECU_PrintError(progName, "couldn't create error log");
+ goto merge_fail;
+ }
+
+ rv = PK11_MergeTokens(slot, sourceSlot, log, &pwdata, &pwdata2);
+ if (rv != SECSuccess) {
+ DumpMergeLog(progName, log);
+ }
+ PK11_DestroyMergeLog(log);
+
+ merge_fail:
+ SECMOD_CloseUserDB(sourceSlot);
+ PK11_FreeSlot(sourceSlot);
+ goto shutdown;
+ }
+
+ /* The following 8 options are mutually exclusive with all others. */
+
+ /* List certs (-L) */
+ if (certutil.commands[cmd_ListCerts].activated) {
+ if (certutil.options[opt_DumpExtensionValue].activated) {
+ const char *oid_str;
+ SECItem oid_item;
+ SECStatus srv;
+ oid_item.data = NULL;
+ oid_item.len = 0;
+ oid_str = certutil.options[opt_DumpExtensionValue].arg;
+ srv = GetOidFromString(NULL, &oid_item, oid_str, strlen(oid_str));
+ if (srv != SECSuccess) {
+ SECU_PrintError(progName, "malformed extension OID %s",
+ oid_str);
+ goto shutdown;
+ }
+ rv = ListCerts(certHandle, name, email, slot,
+ PR_TRUE /*binary*/, PR_FALSE /*ascii*/,
+ &oid_item,
+ outFile, &pwdata);
+ SECITEM_FreeItem(&oid_item, PR_FALSE);
+ } else {
+ rv = ListCerts(certHandle, name, email, slot,
+ certutil.options[opt_BinaryDER].activated,
+ certutil.options[opt_ASCIIForIO].activated,
+ NULL, outFile, &pwdata);
+ }
+ goto shutdown;
+ }
+ if (certutil.commands[cmd_DumpChain].activated) {
+ rv = DumpChain(certHandle, name,
+ certutil.options[opt_ASCIIForIO].activated);
+ goto shutdown;
+ }
+ /* XXX needs work */
+ /* List keys (-K) */
+ if (certutil.commands[cmd_ListKeys].activated) {
+ rv = ListKeys(slot, name, 0 /*keyindex*/, keytype, PR_FALSE /*dopriv*/,
+ &pwdata);
+ goto shutdown;
+ }
+ /* List modules (-U) */
+ if (certutil.commands[cmd_ListModules].activated) {
+ rv = ListModules();
+ goto shutdown;
+ }
+ /* Delete cert (-D) */
+ if (certutil.commands[cmd_DeleteCert].activated) {
+ rv = DeleteCert(certHandle, name);
+ goto shutdown;
+ }
+ /* Rename cert (--rename) */
+ if (certutil.commands[cmd_Rename].activated) {
+ rv = RenameCert(certHandle, name, newName);
+ goto shutdown;
+ }
+ /* Delete key (-F) */
+ if (certutil.commands[cmd_DeleteKey].activated) {
+ rv = DeleteKey(name, &pwdata);
+ goto shutdown;
+ }
+ /* Modify trust attribute for cert (-M) */
+ if (certutil.commands[cmd_ModifyCertTrust].activated) {
+ rv = ChangeTrustAttributes(certHandle, slot, name,
+ certutil.options[opt_Trust].arg, &pwdata);
+ goto shutdown;
+ }
+ /* Change key db password (-W) (future - change pw to slot?) */
+ if (certutil.commands[cmd_ChangePassword].activated) {
+ rv = SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg,
+ certutil.options[opt_NewPasswordFile].arg);
+ goto shutdown;
+ }
+ /* Reset the a token */
+ if (certutil.commands[cmd_TokenReset].activated) {
+ char *sso_pass = "";
+
+ if (certutil.options[opt_SSOPass].activated) {
+ sso_pass = certutil.options[opt_SSOPass].arg;
+ }
+ rv = PK11_ResetToken(slot, sso_pass);
+
+ goto shutdown;
+ }
+ /* Check cert validity against current time (-V) */
+ if (certutil.commands[cmd_CheckCertValidity].activated) {
+ /* XXX temporary hack for fips - must log in to get priv key */
+ if (certutil.options[opt_VerifySig].activated) {
+ if (slot && PK11_NeedLogin(slot)) {
+ SECStatus newrv = PK11_Authenticate(slot, PR_TRUE, &pwdata);
+ if (newrv != SECSuccess) {
+ SECU_PrintError(progName, "could not authenticate to token %s.",
+ PK11_GetTokenName(slot));
+ goto shutdown;
+ }
+ }
+ }
+ rv = ValidateCert(certHandle, name,
+ certutil.options[opt_ValidityTime].arg,
+ certutil.options[opt_Usage].arg,
+ certutil.options[opt_VerifySig].activated,
+ certutil.options[opt_DetailedInfo].activated,
+ certutil.options[opt_ASCIIForIO].activated,
+ &pwdata);
+ if (rv != SECSuccess && PR_GetError() == SEC_ERROR_INVALID_ARGS)
+ SECU_PrintError(progName, "validation failed");
+ goto shutdown;
+ }
+
+ /*
+ * Key generation
+ */
+
+ /* These commands may require keygen. */
+ if (certutil.commands[cmd_CertReq].activated ||
+ certutil.commands[cmd_CreateAndAddCert].activated ||
+ certutil.commands[cmd_GenKeyPair].activated) {
+ if (keysource) {
+ CERTCertificate *keycert;
+ keycert = CERT_FindCertByNicknameOrEmailAddr(certHandle, keysource);
+ if (!keycert) {
+ keycert = PK11_FindCertFromNickname(keysource, NULL);
+ if (!keycert) {
+ SECU_PrintError(progName,
+ "%s is neither a key-type nor a nickname", keysource);
+ return SECFailure;
+ }
+ }
+ privkey = PK11_FindKeyByDERCert(slot, keycert, &pwdata);
+ if (privkey)
+ pubkey = CERT_ExtractPublicKey(keycert);
+ if (!pubkey) {
+ SECU_PrintError(progName,
+ "Could not get keys from cert %s", keysource);
+ rv = SECFailure;
+ CERT_DestroyCertificate(keycert);
+ goto shutdown;
+ }
+ keytype = privkey->keyType;
+ /* On CertReq for renewal if no subject has been
+ * specified obtain it from the certificate.
+ */
+ if (certutil.commands[cmd_CertReq].activated && !subject) {
+ subject = CERT_AsciiToName(keycert->subjectName);
+ if (!subject) {
+ SECU_PrintError(progName,
+ "Could not get subject from certificate %s", keysource);
+ CERT_DestroyCertificate(keycert);
+ rv = SECFailure;
+ goto shutdown;
+ }
+ }
+ CERT_DestroyCertificate(keycert);
+ } else {
+ privkey =
+ CERTUTIL_GeneratePrivateKey(keytype, slot, keysize,
+ publicExponent,
+ certutil.options[opt_NoiseFile].arg,
+ &pubkey,
+ certutil.options[opt_PQGFile].arg,
+ keyAttrFlags,
+ keyOpFlagsOn,
+ keyOpFlagsOff,
+ &pwdata);
+ if (privkey == NULL) {
+ SECU_PrintError(progName, "unable to generate key(s)\n");
+ rv = SECFailure;
+ goto shutdown;
+ }
+ }
+ privkey->wincx = &pwdata;
+ PORT_Assert(pubkey != NULL);
+
+ /* If all that was needed was keygen, exit. */
+ if (certutil.commands[cmd_GenKeyPair].activated) {
+ rv = SECSuccess;
+ goto shutdown;
+ }
+ }
+
+ if (certutil.options[opt_Pss].activated) {
+ if (!certutil.commands[cmd_CertReq].activated &&
+ !certutil.commands[cmd_CreateAndAddCert].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: --pss only works with -R or -S.\n",
+ progName, commandToRun);
+ return 255;
+ }
+ if (keytype != rsaKey) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: --pss only works with RSA keys.\n",
+ progName, commandToRun);
+ return 255;
+ }
+ }
+
+ /* If we need a list of extensions convert the flags into list format */
+ if (certutil.commands[cmd_CertReq].activated ||
+ certutil.commands[cmd_CreateAndAddCert].activated ||
+ certutil.commands[cmd_CreateNewCert].activated) {
+ certutil_extns[ext_keyUsage].activated =
+ certutil.options[opt_AddCmdKeyUsageExt].activated;
+ if (!certutil_extns[ext_keyUsage].activated) {
+ certutil_extns[ext_keyUsage].activated =
+ certutil.options[opt_AddKeyUsageExt].activated;
+ } else {
+ certutil_extns[ext_keyUsage].arg =
+ certutil.options[opt_AddCmdKeyUsageExt].arg;
+ }
+ certutil_extns[ext_basicConstraint].activated =
+ certutil.options[opt_AddBasicConstraintExt].activated;
+ certutil_extns[ext_nameConstraints].activated =
+ certutil.options[opt_AddNameConstraintsExt].activated;
+ certutil_extns[ext_authorityKeyID].activated =
+ certutil.options[opt_AddAuthorityKeyIDExt].activated;
+ certutil_extns[ext_subjectKeyID].activated =
+ certutil.options[opt_AddSubjectKeyIDExt].activated;
+ certutil_extns[ext_CRLDistPts].activated =
+ certutil.options[opt_AddCRLDistPtsExt].activated;
+ certutil_extns[ext_NSCertType].activated =
+ certutil.options[opt_AddCmdNSCertTypeExt].activated;
+ if (!certutil_extns[ext_NSCertType].activated) {
+ certutil_extns[ext_NSCertType].activated =
+ certutil.options[opt_AddNSCertTypeExt].activated;
+ } else {
+ certutil_extns[ext_NSCertType].arg =
+ certutil.options[opt_AddCmdNSCertTypeExt].arg;
+ }
+
+ certutil_extns[ext_extKeyUsage].activated =
+ certutil.options[opt_AddCmdExtKeyUsageExt].activated;
+ if (!certutil_extns[ext_extKeyUsage].activated) {
+ certutil_extns[ext_extKeyUsage].activated =
+ certutil.options[opt_AddExtKeyUsageExt].activated;
+ } else {
+ certutil_extns[ext_extKeyUsage].arg =
+ certutil.options[opt_AddCmdExtKeyUsageExt].arg;
+ }
+ certutil_extns[ext_subjectAltName].activated =
+ certutil.options[opt_AddSubjectAltNameExt].activated;
+ if (certutil_extns[ext_subjectAltName].activated) {
+ certutil_extns[ext_subjectAltName].arg =
+ certutil.options[opt_AddSubjectAltNameExt].arg;
+ }
+
+ certutil_extns[ext_authInfoAcc].activated =
+ certutil.options[opt_AddAuthInfoAccExt].activated;
+ certutil_extns[ext_subjInfoAcc].activated =
+ certutil.options[opt_AddSubjInfoAccExt].activated;
+ certutil_extns[ext_certPolicies].activated =
+ certutil.options[opt_AddCertPoliciesExt].activated;
+ certutil_extns[ext_policyMappings].activated =
+ certutil.options[opt_AddPolicyMapExt].activated;
+ certutil_extns[ext_policyConstr].activated =
+ certutil.options[opt_AddPolicyConstrExt].activated;
+ certutil_extns[ext_inhibitAnyPolicy].activated =
+ certutil.options[opt_AddInhibAnyExt].activated;
+ }
+
+ /* -A -C or -E Read inFile */
+ if (certutil.commands[cmd_CreateNewCert].activated ||
+ certutil.commands[cmd_AddCert].activated ||
+ certutil.commands[cmd_AddEmailCert].activated) {
+ PRBool isCreate = certutil.commands[cmd_CreateNewCert].activated;
+ rv = SECU_ReadDERFromFile(isCreate ? &certReqDER : &certDER, inFile,
+ certutil.options[opt_ASCIIForIO].activated,
+ PR_TRUE);
+ if (rv)
+ goto shutdown;
+ }
+
+ /*
+ * Certificate request
+ */
+
+ /* Make a cert request (-R). */
+ if (certutil.commands[cmd_CertReq].activated) {
+ rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
+ certutil.options[opt_PhoneNumber].arg,
+ certutil.options[opt_ASCIIForIO].activated,
+ certutil.options[opt_ExtendedEmailAddrs].arg,
+ certutil.options[opt_ExtendedDNSNames].arg,
+ certutil_extns,
+ (certutil.options[opt_GenericExtensions].activated ? certutil.options[opt_GenericExtensions].arg
+ : NULL),
+ certutil.options[opt_Pss].activated,
+ &certReqDER);
+ if (rv)
+ goto shutdown;
+ privkey->wincx = &pwdata;
+ }
+
+ /*
+ * Certificate creation
+ */
+
+ /* If making and adding a cert, create a cert request file first without
+ * any extensions, then load it with the command line extensions
+ * and output the cert to another file.
+ */
+ if (certutil.commands[cmd_CreateAndAddCert].activated) {
+ static certutilExtnList nullextnlist = { { PR_FALSE, NULL } };
+ rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
+ certutil.options[opt_PhoneNumber].arg,
+ PR_FALSE, /* do not BASE64-encode regardless of -a option */
+ NULL,
+ NULL,
+ nullextnlist,
+ (certutil.options[opt_GenericExtensions].activated ? certutil.options[opt_GenericExtensions].arg
+ : NULL),
+ certutil.options[opt_Pss].activated,
+ &certReqDER);
+ if (rv)
+ goto shutdown;
+ privkey->wincx = &pwdata;
+ }
+
+ /* Create a certificate (-C or -S). */
+ if (certutil.commands[cmd_CreateAndAddCert].activated ||
+ certutil.commands[cmd_CreateNewCert].activated) {
+ rv = CreateCert(certHandle, slot,
+ certutil.options[opt_IssuerName].arg,
+ &certReqDER, &privkey, &pwdata, hashAlgTag,
+ serialNumber, warpmonths, validityMonths,
+ certutil.options[opt_ExtendedEmailAddrs].arg,
+ certutil.options[opt_ExtendedDNSNames].arg,
+ certutil.options[opt_ASCIIForIO].activated &&
+ certutil.commands[cmd_CreateNewCert].activated,
+ certutil.options[opt_SelfSign].activated,
+ certutil_extns,
+ (certutil.options[opt_GenericExtensions].activated ? certutil.options[opt_GenericExtensions].arg
+ : NULL),
+ certVersion,
+ &certDER);
+ if (rv)
+ goto shutdown;
+ }
+
+ /*
+ * Adding a cert to the database (or slot)
+ */
+
+ /* -A -E or -S Add the cert to the DB */
+ if (certutil.commands[cmd_CreateAndAddCert].activated ||
+ certutil.commands[cmd_AddCert].activated ||
+ certutil.commands[cmd_AddEmailCert].activated) {
+ if (strstr(certutil.options[opt_Trust].arg, "u")) {
+ fprintf(stderr, "Notice: Trust flag u is set automatically if the "
+ "private key is present.\n");
+ }
+ rv = AddCert(slot, certHandle, name,
+ certutil.options[opt_Trust].arg,
+ &certDER,
+ certutil.commands[cmd_AddEmailCert].activated, &pwdata);
+ if (rv)
+ goto shutdown;
+ }
+
+ if (certutil.commands[cmd_CertReq].activated ||
+ certutil.commands[cmd_CreateNewCert].activated) {
+ SECItem *item = certutil.commands[cmd_CertReq].activated ? &certReqDER
+ : &certDER;
+ PRInt32 written = PR_Write(outFile, item->data, item->len);
+ if (written < 0 || (PRUint32)written != item->len) {
+ rv = SECFailure;
+ }
+ }
+
+shutdown:
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+ if (privkey) {
+ SECKEY_DestroyPrivateKey(privkey);
+ }
+ if (pubkey) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if (subject) {
+ CERT_DestroyName(subject);
+ }
+ if (name) {
+ PL_strfree(name);
+ }
+ if (newName) {
+ PL_strfree(newName);
+ }
+ if (inFile && inFile != PR_STDIN) {
+ PR_Close(inFile);
+ }
+ if (outFile && outFile != PR_STDOUT) {
+ PR_Close(outFile);
+ }
+ SECITEM_FreeItem(&certReqDER, PR_FALSE);
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ if (pwdata.data && pwdata.source == PW_PLAINTEXT) {
+ /* Allocated by a PL_strdup call in SECU_GetModulePassword. */
+ PL_strfree(pwdata.data);
+ }
+ if (email) {
+ PL_strfree(email);
+ }
+
+ /* Open the batch command file.
+ *
+ * - If -B <command line> option is specified, the contents in the
+ * command file will be interpreted as subsequent certutil
+ * commands to be executed in the current certutil process
+ * context after the current certutil command has been executed.
+ * - Each line in the command file consists of the command
+ * line arguments for certutil.
+ * - The -d <configdir> option will be ignored if specified in the
+ * command file.
+ * - Quoting with double quote characters ("...") is supported
+ * to allow white space in a command line argument. The
+ * double quote character cannot be escaped and quoting cannot
+ * be nested in this version.
+ * - each line in the batch file is limited to 512 characters
+ */
+
+ if ((SECSuccess == rv) && certutil.commands[cmd_Batch].activated) {
+ FILE *batchFile = NULL;
+ char *nextcommand = NULL;
+ PRInt32 cmd_len = 0, buf_size = 0;
+ static const int increment = 512;
+
+ if (!certutil.options[opt_InputFile].activated ||
+ !certutil.options[opt_InputFile].arg) {
+ PR_fprintf(PR_STDERR,
+ "%s: no batch input file specified.\n",
+ progName);
+ return 255;
+ }
+ batchFile = fopen(certutil.options[opt_InputFile].arg, "r");
+ if (!batchFile) {
+ PR_fprintf(PR_STDERR,
+ "%s: unable to open \"%s\" for reading (%ld, %ld).\n",
+ progName, certutil.options[opt_InputFile].arg,
+ PR_GetError(), PR_GetOSError());
+ return 255;
+ }
+ /* read and execute command-lines in a loop */
+ while (SECSuccess == rv) {
+ PRBool invalid = PR_FALSE;
+ int newargc = 2;
+ char *space = NULL;
+ char *nextarg = NULL;
+ char **newargv = NULL;
+ char *crlf;
+
+ if (cmd_len + increment > buf_size) {
+ char *new_buf;
+ buf_size += increment;
+ new_buf = PORT_Realloc(nextcommand, buf_size);
+ if (!new_buf) {
+ PR_fprintf(PR_STDERR, "%s: PORT_Realloc(%ld) failed\n",
+ progName, buf_size);
+ break;
+ }
+ nextcommand = new_buf;
+ nextcommand[cmd_len] = '\0';
+ }
+ if (!fgets(nextcommand + cmd_len, buf_size - cmd_len, batchFile)) {
+ break;
+ }
+ crlf = PORT_Strrchr(nextcommand, '\n');
+ if (crlf) {
+ *crlf = '\0';
+ }
+ cmd_len = strlen(nextcommand);
+ if (cmd_len && nextcommand[cmd_len - 1] == '\\') {
+ nextcommand[--cmd_len] = '\0';
+ continue;
+ }
+
+ /* we now need to split the command into argc / argv format */
+
+ newargv = PORT_Alloc(sizeof(char *) * (newargc + 1));
+ newargv[0] = progName;
+ newargv[1] = nextcommand;
+ nextarg = nextcommand;
+ while ((space = PORT_Strpbrk(nextarg, " \f\n\r\t\v"))) {
+ while (isspace(*space)) {
+ *space = '\0';
+ space++;
+ }
+ if (*space == '\0') {
+ break;
+ } else if (*space != '\"') {
+ nextarg = space;
+ } else {
+ char *closingquote = strchr(space + 1, '\"');
+ if (closingquote) {
+ *closingquote = '\0';
+ space++;
+ nextarg = closingquote + 1;
+ } else {
+ invalid = PR_TRUE;
+ nextarg = space;
+ }
+ }
+ newargc++;
+ newargv = PORT_Realloc(newargv, sizeof(char *) * (newargc + 1));
+ newargv[newargc - 1] = space;
+ }
+ newargv[newargc] = NULL;
+
+ /* invoke next command */
+ if (PR_TRUE == invalid) {
+ PR_fprintf(PR_STDERR, "Missing closing quote in batch command :\n%s\nNot executed.\n",
+ nextcommand);
+ rv = SECFailure;
+ } else {
+ if (0 != certutil_main(newargc, newargv, PR_FALSE))
+ rv = SECFailure;
+ }
+ PORT_Free(newargv);
+ cmd_len = 0;
+ nextcommand[0] = '\0';
+ }
+ PORT_Free(nextcommand);
+ fclose(batchFile);
+ }
+
+ if ((initialized == PR_TRUE) && NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ if (rv == SECSuccess) {
+ return 0;
+ } else {
+ return 255;
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int rv = certutil_main(argc, argv, PR_TRUE);
+ PL_ArenaFinish();
+ PR_Cleanup();
+ return rv;
+}
diff --git a/security/nss/cmd/certutil/certutil.gyp b/security/nss/cmd/certutil/certutil.gyp
new file mode 100644
index 000000000..d8f1b5d4c
--- /dev/null
+++ b/security/nss/cmd/certutil/certutil.gyp
@@ -0,0 +1,32 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'certutil',
+ 'type': 'executable',
+ 'sources': [
+ 'certext.c',
+ 'certutil.c',
+ 'keystuff.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/certutil/certutil.h b/security/nss/cmd/certutil/certutil.h
new file mode 100644
index 000000000..565587264
--- /dev/null
+++ b/security/nss/cmd/certutil/certutil.h
@@ -0,0 +1,57 @@
+/* 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 _CERTUTIL_H
+#define _CERTUTIL_H
+
+extern SECKEYPrivateKey *
+CERTUTIL_GeneratePrivateKey(KeyType keytype,
+ PK11SlotInfo *slot,
+ int rsasize,
+ int publicExponent,
+ char *noise,
+ SECKEYPublicKey **pubkeyp,
+ char *pqgFile,
+ PK11AttrFlags attrFlags,
+ CK_FLAGS opFlagsOn,
+ CK_FLAGS opFlagsOff,
+ secuPWData *pwdata);
+
+extern char *progName;
+
+enum certutilExtns {
+ ext_keyUsage = 0,
+ ext_basicConstraint,
+ ext_authorityKeyID,
+ ext_CRLDistPts,
+ ext_NSCertType,
+ ext_extKeyUsage,
+ ext_authInfoAcc,
+ ext_subjInfoAcc,
+ ext_certPolicies,
+ ext_policyMappings,
+ ext_policyConstr,
+ ext_inhibitAnyPolicy,
+ ext_subjectKeyID,
+ ext_nameConstraints,
+ ext_subjectAltName,
+ ext_End
+};
+
+typedef struct ExtensionEntryStr {
+ PRBool activated;
+ const char *arg;
+} ExtensionEntry;
+
+typedef ExtensionEntry certutilExtnList[ext_End];
+
+extern SECStatus
+AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
+ certutilExtnList extList, const char *extGeneric);
+
+extern SECStatus
+GetOidFromString(PLArenaPool *arena, SECItem *to,
+ const char *from, size_t fromLen);
+
+#endif /* _CERTUTIL_H */
diff --git a/security/nss/cmd/certutil/keystuff.c b/security/nss/cmd/certutil/keystuff.c
new file mode 100644
index 000000000..268ad471a
--- /dev/null
+++ b/security/nss/cmd/certutil/keystuff.c
@@ -0,0 +1,608 @@
+/* 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/. */
+
+#include <stdio.h>
+#include <string.h>
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#include <sys/time.h>
+#include <termios.h>
+#endif
+
+#if defined(XP_WIN) || defined(XP_PC)
+#include <time.h>
+#include <conio.h>
+#endif
+
+#if defined(__sun) && !defined(SVR4)
+extern int fclose(FILE *);
+extern int fprintf(FILE *, char *, ...);
+extern int isatty(int);
+extern char *sys_errlist[];
+#define strerror(errno) sys_errlist[errno]
+#endif
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+
+#include "pk11func.h"
+
+#define NUM_KEYSTROKES 120
+#define RAND_BUF_SIZE 60
+
+#define ERROR_BREAK \
+ rv = SECFailure; \
+ break;
+
+const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, prime) },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, subPrime) },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, base) },
+ { 0 }
+};
+
+/* returns 0 for success, -1 for failure (EOF encountered) */
+static int
+UpdateRNG(void)
+{
+ char randbuf[RAND_BUF_SIZE];
+ int fd, count;
+ int c;
+ int rv = 0;
+#ifdef XP_UNIX
+ cc_t orig_cc_min;
+ cc_t orig_cc_time;
+ tcflag_t orig_lflag;
+ struct termios tio;
+#endif
+ char meter[] = {
+ "\r| |"
+ };
+
+#define FPS fprintf(stderr,
+ FPS "\n");
+ FPS "A random seed must be generated that will be used in the\n");
+ FPS "creation of your key. One of the easiest ways to create a\n");
+ FPS "random seed is to use the timing of keystrokes on a keyboard.\n");
+ FPS "\n");
+ FPS "To begin, type keys on the keyboard until this progress meter\n");
+ FPS "is full. DO NOT USE THE AUTOREPEAT FUNCTION ON YOUR KEYBOARD!\n");
+ FPS "\n");
+ FPS "\n");
+ FPS "Continue typing until the progress meter is full:\n\n");
+ FPS "%s", meter);
+ FPS "\r|");
+
+ /* turn off echo on stdin & return on 1 char instead of NL */
+ fd = fileno(stdin);
+
+#if defined(XP_UNIX)
+ tcgetattr(fd, &tio);
+ orig_lflag = tio.c_lflag;
+ orig_cc_min = tio.c_cc[VMIN];
+ orig_cc_time = tio.c_cc[VTIME];
+ tio.c_lflag &= ~ECHO;
+ tio.c_lflag &= ~ICANON;
+ tio.c_cc[VMIN] = 1;
+ tio.c_cc[VTIME] = 0;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+#endif
+
+ /* Get random noise from keyboard strokes */
+ count = 0;
+ while (count < sizeof randbuf) {
+#if defined(XP_UNIX)
+ c = getc(stdin);
+#else
+ c = getch();
+#endif
+ if (c == EOF) {
+ rv = -1;
+ break;
+ }
+ randbuf[count] = c;
+ if (count == 0 || c != randbuf[count - 1]) {
+ count++;
+ FPS "*");
+ }
+ }
+ PK11_RandomUpdate(randbuf, sizeof randbuf);
+ memset(randbuf, 0, sizeof randbuf);
+
+ FPS "\n\n");
+ FPS "Finished. Press enter to continue: ");
+ while ((c = getc(stdin)) != '\n' && c != EOF)
+ ;
+ if (c == EOF)
+ rv = -1;
+ FPS "\n");
+
+#undef FPS
+
+#if defined(XP_UNIX)
+ /* set back termio the way it was */
+ tio.c_lflag = orig_lflag;
+ tio.c_cc[VMIN] = orig_cc_min;
+ tio.c_cc[VTIME] = orig_cc_time;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+#endif
+ return rv;
+}
+
+static const unsigned char P[] = { 0,
+ 0xc6, 0x2a, 0x47, 0x73, 0xea, 0x78, 0xfa, 0x65,
+ 0x47, 0x69, 0x39, 0x10, 0x08, 0x55, 0x6a, 0xdd,
+ 0xbf, 0x77, 0xe1, 0x9a, 0x69, 0x73, 0xba, 0x66,
+ 0x37, 0x08, 0x93, 0x9e, 0xdb, 0x5d, 0x01, 0x08,
+ 0xb8, 0x3a, 0x73, 0xe9, 0x85, 0x5f, 0xa7, 0x2b,
+ 0x63, 0x7f, 0xd0, 0xc6, 0x4c, 0xdc, 0xfc, 0x8b,
+ 0xa6, 0x03, 0xc9, 0x9c, 0x80, 0x5e, 0xec, 0xc6,
+ 0x21, 0x23, 0xf7, 0x8e, 0xa4, 0x7b, 0x77, 0x83,
+ 0x02, 0x44, 0xf8, 0x05, 0xd7, 0x36, 0x52, 0x13,
+ 0x57, 0x78, 0x97, 0xf3, 0x7b, 0xcf, 0x1f, 0xc9,
+ 0x2a, 0xa4, 0x71, 0x9d, 0xa8, 0xd8, 0x5d, 0xc5,
+ 0x3b, 0x64, 0x3a, 0x72, 0x60, 0x62, 0xb0, 0xb8,
+ 0xf3, 0xb1, 0xe7, 0xb9, 0x76, 0xdf, 0x74, 0xbe,
+ 0x87, 0x6a, 0xd2, 0xf1, 0xa9, 0x44, 0x8b, 0x63,
+ 0x76, 0x4f, 0x5d, 0x21, 0x63, 0xb5, 0x4f, 0x3c,
+ 0x7b, 0x61, 0xb2, 0xf3, 0xea, 0xc5, 0xd8, 0xef,
+ 0x30, 0x50, 0x59, 0x33, 0x61, 0xc0, 0xf3, 0x6e,
+ 0x21, 0xcf, 0x15, 0x35, 0x4a, 0x87, 0x2b, 0xc3,
+ 0xf6, 0x5a, 0x1f, 0x24, 0x22, 0xc5, 0xeb, 0x47,
+ 0x34, 0x4a, 0x1b, 0xb5, 0x2e, 0x71, 0x52, 0x8f,
+ 0x2d, 0x7d, 0xa9, 0x96, 0x8a, 0x7c, 0x61, 0xdb,
+ 0xc0, 0xdc, 0xf1, 0xca, 0x28, 0x69, 0x1c, 0x97,
+ 0xad, 0xea, 0x0d, 0x9e, 0x02, 0xe6, 0xe5, 0x7d,
+ 0xad, 0xe0, 0x42, 0x91, 0x4d, 0xfa, 0xe2, 0x81,
+ 0x16, 0x2b, 0xc2, 0x96, 0x3b, 0x32, 0x8c, 0x20,
+ 0x69, 0x8b, 0x5b, 0x17, 0x3c, 0xf9, 0x13, 0x6c,
+ 0x98, 0x27, 0x1c, 0xca, 0xcf, 0x33, 0xaa, 0x93,
+ 0x21, 0xaf, 0x17, 0x6e, 0x5e, 0x00, 0x37, 0xd9,
+ 0x34, 0x8a, 0x47, 0xd2, 0x1c, 0x67, 0x32, 0x60,
+ 0xb6, 0xc7, 0xb0, 0xfd, 0x32, 0x90, 0x93, 0x32,
+ 0xaa, 0x11, 0xba, 0x23, 0x19, 0x39, 0x6a, 0x42,
+ 0x7c, 0x1f, 0xb7, 0x28, 0xdb, 0x64, 0xad, 0xd9 };
+static const unsigned char Q[] = { 0,
+ 0xe6, 0xa3, 0xc9, 0xc6, 0x51, 0x92, 0x8b, 0xb3,
+ 0x98, 0x8f, 0x97, 0xb8, 0x31, 0x0d, 0x4a, 0x03,
+ 0x1e, 0xba, 0x4e, 0xe6, 0xc8, 0x90, 0x98, 0x1d,
+ 0x3a, 0x95, 0xf4, 0xf1 };
+static const unsigned char G[] = {
+ 0x70, 0x32, 0x58, 0x5d, 0xb3, 0xbf, 0xc3, 0x62,
+ 0x63, 0x0b, 0xf8, 0xa5, 0xe1, 0xed, 0xeb, 0x79,
+ 0xac, 0x18, 0x41, 0x64, 0xb3, 0xda, 0x4c, 0xa7,
+ 0x92, 0x63, 0xb1, 0x33, 0x7c, 0xcb, 0x43, 0xdc,
+ 0x1f, 0x38, 0x63, 0x5e, 0x0e, 0x6d, 0x45, 0xd1,
+ 0xc9, 0x67, 0xf3, 0xcf, 0x3d, 0x2d, 0x16, 0x4e,
+ 0x92, 0x16, 0x06, 0x59, 0x29, 0x89, 0x6f, 0x54,
+ 0xff, 0xc5, 0x71, 0xc8, 0x3a, 0x95, 0x84, 0xb6,
+ 0x7e, 0x7b, 0x1e, 0x8b, 0x47, 0x9d, 0x7a, 0x3a,
+ 0x36, 0x9b, 0x70, 0x2f, 0xd1, 0xbd, 0xef, 0xe8,
+ 0x3a, 0x41, 0xd4, 0xf3, 0x1f, 0x81, 0xc7, 0x1f,
+ 0x96, 0x7c, 0x30, 0xab, 0xf4, 0x7a, 0xac, 0x93,
+ 0xed, 0x6f, 0x67, 0xb0, 0xc9, 0x5b, 0xf3, 0x83,
+ 0x9d, 0xa0, 0xd7, 0xb9, 0x01, 0xed, 0x28, 0xae,
+ 0x1c, 0x6e, 0x2e, 0x48, 0xac, 0x9f, 0x7d, 0xf3,
+ 0x00, 0x48, 0xee, 0x0e, 0xfb, 0x7e, 0x5e, 0xcb,
+ 0xf5, 0x39, 0xd8, 0x92, 0x90, 0x61, 0x2d, 0x1e,
+ 0x3c, 0xd3, 0x55, 0x0d, 0x34, 0xd1, 0x81, 0xc4,
+ 0x89, 0xea, 0x94, 0x2b, 0x56, 0x33, 0x73, 0x58,
+ 0x48, 0xbf, 0x23, 0x72, 0x19, 0x5f, 0x19, 0xac,
+ 0xff, 0x09, 0xc8, 0xcd, 0xab, 0x71, 0xef, 0x9e,
+ 0x20, 0xfd, 0xe3, 0xb8, 0x27, 0x9e, 0x65, 0xb1,
+ 0x85, 0xcd, 0x88, 0xfe, 0xd4, 0xd7, 0x64, 0x4d,
+ 0xe1, 0xe8, 0xa6, 0xe5, 0x96, 0xc8, 0x5d, 0x9c,
+ 0xc6, 0x70, 0x6b, 0xba, 0x77, 0x4e, 0x90, 0x4a,
+ 0xb0, 0x96, 0xc5, 0xa0, 0x9e, 0x2c, 0x01, 0x03,
+ 0xbe, 0xbd, 0x71, 0xba, 0x0a, 0x6f, 0x9f, 0xe5,
+ 0xdb, 0x04, 0x08, 0xf2, 0x9e, 0x0f, 0x1b, 0xac,
+ 0xcd, 0xbb, 0x65, 0x12, 0xcf, 0x77, 0xc9, 0x7d,
+ 0xbe, 0x94, 0x4b, 0x9c, 0x5b, 0xde, 0x0d, 0xfa,
+ 0x57, 0xdd, 0x77, 0x32, 0xf0, 0x5b, 0x34, 0xfd,
+ 0x19, 0x95, 0x33, 0x60, 0x87, 0xe2, 0xa2, 0xf4
+};
+
+/* P, Q, G have been generated using the NSS makepqg utility:
+ * makepqg -l 2048 -g 224 -r
+ * (see also: bug 1170322)
+ *
+ * h: 1 (0x1)
+ * SEED:
+ * d2:0b:c5:63:1b:af:dc:36:b7:7c:b9:3e:36:01:a0:8f:
+ * 0e:be:d0:38:e4:78:d5:3c:7c:9e:a9:9a:d2:0b:c5:63:
+ * 1b:af:dc:36:b7:7c:b9:3e:36:01:a0:8f:0e:be:d0:38:
+ * e4:78:d5:3c:7c:9e:c7:70:d2:0b:c5:63:1b:af:dc:36:
+ * b7:7c:b9:3e:36:01:a0:8f:0e:be:d0:38:e4:78:d5:3c:
+ * 7c:9e:aa:3e
+ * g: 672
+ * counter: 0
+ */
+
+static const SECKEYPQGParams default_pqg_params = {
+ NULL,
+ { 0, (unsigned char *)P, sizeof(P) },
+ { 0, (unsigned char *)Q, sizeof(Q) },
+ { 0, (unsigned char *)G, sizeof(G) }
+};
+
+static SECKEYPQGParams *
+decode_pqg_params(const char *str)
+{
+ char *buf;
+ unsigned int len;
+ PLArenaPool *arena;
+ SECKEYPQGParams *params;
+ SECStatus status;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL)
+ return NULL;
+
+ params = PORT_ArenaZAlloc(arena, sizeof(SECKEYPQGParams));
+ if (params == NULL)
+ goto loser;
+ params->arena = arena;
+
+ buf = (char *)ATOB_AsciiToData(str, &len);
+ if ((buf == NULL) || (len == 0))
+ goto loser;
+
+ status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, buf, len);
+ if (status != SECSuccess)
+ goto loser;
+
+ return params;
+
+loser:
+ if (arena != NULL)
+ PORT_FreeArena(arena, PR_FALSE);
+ return NULL;
+}
+
+void
+CERTUTIL_DestroyParamsPQG(SECKEYPQGParams *params)
+{
+ if (params->arena) {
+ PORT_FreeArena(params->arena, PR_FALSE);
+ }
+}
+
+static int
+pqg_prime_bits(const SECKEYPQGParams *params)
+{
+ int primeBits = 0;
+
+ if (params != NULL) {
+ int i;
+ for (i = 0; params->prime.data[i] == 0; i++) {
+ /* empty */;
+ }
+ primeBits = (params->prime.len - i) * 8;
+ }
+
+ return primeBits;
+}
+
+static char *
+getPQGString(const char *filename)
+{
+ unsigned char *buf = NULL;
+ PRFileDesc *src;
+ PRInt32 numBytes;
+ PRStatus prStatus;
+ PRFileInfo info;
+
+ src = PR_Open(filename, PR_RDONLY, 0);
+ if (!src) {
+ fprintf(stderr, "Failed to open PQG file %s\n", filename);
+ return NULL;
+ }
+
+ prStatus = PR_GetOpenFileInfo(src, &info);
+
+ if (prStatus == PR_SUCCESS) {
+ buf = (unsigned char *)PORT_Alloc(info.size + 1);
+ }
+ if (!buf) {
+ PR_Close(src);
+ fprintf(stderr, "Failed to read PQG file %s\n", filename);
+ return NULL;
+ }
+
+ numBytes = PR_Read(src, buf, info.size);
+ PR_Close(src);
+ if (numBytes != info.size) {
+ PORT_Free(buf);
+ fprintf(stderr, "Failed to read PQG file %s\n", filename);
+ PORT_SetError(SEC_ERROR_IO);
+ return NULL;
+ }
+
+ if (buf[numBytes - 1] == '\n')
+ numBytes--;
+ if (buf[numBytes - 1] == '\r')
+ numBytes--;
+ buf[numBytes] = 0;
+
+ return (char *)buf;
+}
+
+static SECKEYPQGParams *
+getpqgfromfile(int keyBits, const char *pqgFile)
+{
+ char *end, *str, *pqgString;
+ SECKEYPQGParams *params = NULL;
+
+ str = pqgString = getPQGString(pqgFile);
+ if (!str)
+ return NULL;
+
+ do {
+ end = PORT_Strchr(str, ',');
+ if (end)
+ *end = '\0';
+ params = decode_pqg_params(str);
+ if (params) {
+ int primeBits = pqg_prime_bits(params);
+ if (keyBits == primeBits)
+ break;
+ CERTUTIL_DestroyParamsPQG(params);
+ params = NULL;
+ }
+ if (end)
+ str = end + 1;
+ } while (end);
+
+ PORT_Free(pqgString);
+ return params;
+}
+
+static SECStatus
+CERTUTIL_FileForRNG(const char *noise)
+{
+ char buf[2048];
+ PRFileDesc *fd;
+ PRInt32 count;
+
+ fd = PR_Open(noise, PR_RDONLY, 0);
+ if (!fd) {
+ fprintf(stderr, "failed to open noise file.");
+ return SECFailure;
+ }
+
+ do {
+ count = PR_Read(fd, buf, sizeof(buf));
+ if (count > 0) {
+ PK11_RandomUpdate(buf, count);
+ }
+ } while (count > 0);
+
+ PR_Close(fd);
+ return SECSuccess;
+}
+
+#ifndef NSS_DISABLE_ECC
+typedef struct curveNameTagPairStr {
+ char *curveName;
+ SECOidTag curveOidTag;
+} CurveNameTagPair;
+
+static CurveNameTagPair nameTagPair[] =
+ {
+ { "sect163k1", SEC_OID_SECG_EC_SECT163K1 },
+ { "nistk163", SEC_OID_SECG_EC_SECT163K1 },
+ { "sect163r1", SEC_OID_SECG_EC_SECT163R1 },
+ { "sect163r2", SEC_OID_SECG_EC_SECT163R2 },
+ { "nistb163", SEC_OID_SECG_EC_SECT163R2 },
+ { "sect193r1", SEC_OID_SECG_EC_SECT193R1 },
+ { "sect193r2", SEC_OID_SECG_EC_SECT193R2 },
+ { "sect233k1", SEC_OID_SECG_EC_SECT233K1 },
+ { "nistk233", SEC_OID_SECG_EC_SECT233K1 },
+ { "sect233r1", SEC_OID_SECG_EC_SECT233R1 },
+ { "nistb233", SEC_OID_SECG_EC_SECT233R1 },
+ { "sect239k1", SEC_OID_SECG_EC_SECT239K1 },
+ { "sect283k1", SEC_OID_SECG_EC_SECT283K1 },
+ { "nistk283", SEC_OID_SECG_EC_SECT283K1 },
+ { "sect283r1", SEC_OID_SECG_EC_SECT283R1 },
+ { "nistb283", SEC_OID_SECG_EC_SECT283R1 },
+ { "sect409k1", SEC_OID_SECG_EC_SECT409K1 },
+ { "nistk409", SEC_OID_SECG_EC_SECT409K1 },
+ { "sect409r1", SEC_OID_SECG_EC_SECT409R1 },
+ { "nistb409", SEC_OID_SECG_EC_SECT409R1 },
+ { "sect571k1", SEC_OID_SECG_EC_SECT571K1 },
+ { "nistk571", SEC_OID_SECG_EC_SECT571K1 },
+ { "sect571r1", SEC_OID_SECG_EC_SECT571R1 },
+ { "nistb571", SEC_OID_SECG_EC_SECT571R1 },
+ { "secp160k1", SEC_OID_SECG_EC_SECP160K1 },
+ { "secp160r1", SEC_OID_SECG_EC_SECP160R1 },
+ { "secp160r2", SEC_OID_SECG_EC_SECP160R2 },
+ { "secp192k1", SEC_OID_SECG_EC_SECP192K1 },
+ { "secp192r1", SEC_OID_SECG_EC_SECP192R1 },
+ { "nistp192", SEC_OID_SECG_EC_SECP192R1 },
+ { "secp224k1", SEC_OID_SECG_EC_SECP224K1 },
+ { "secp224r1", SEC_OID_SECG_EC_SECP224R1 },
+ { "nistp224", SEC_OID_SECG_EC_SECP224R1 },
+ { "secp256k1", SEC_OID_SECG_EC_SECP256K1 },
+ { "secp256r1", SEC_OID_SECG_EC_SECP256R1 },
+ { "nistp256", SEC_OID_SECG_EC_SECP256R1 },
+ { "secp384r1", SEC_OID_SECG_EC_SECP384R1 },
+ { "nistp384", SEC_OID_SECG_EC_SECP384R1 },
+ { "secp521r1", SEC_OID_SECG_EC_SECP521R1 },
+ { "nistp521", SEC_OID_SECG_EC_SECP521R1 },
+
+ { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
+ { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
+ { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
+ { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
+ { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
+ { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
+
+ { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
+ { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
+ { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
+ { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
+ { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
+ { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
+ { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
+ { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
+ { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
+ { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
+ { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
+ { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
+ { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
+ { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
+ { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
+ { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
+ { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
+ { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
+ { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
+ { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
+
+ { "secp112r1", SEC_OID_SECG_EC_SECP112R1 },
+ { "secp112r2", SEC_OID_SECG_EC_SECP112R2 },
+ { "secp128r1", SEC_OID_SECG_EC_SECP128R1 },
+ { "secp128r2", SEC_OID_SECG_EC_SECP128R2 },
+
+ { "sect113r1", SEC_OID_SECG_EC_SECT113R1 },
+ { "sect113r2", SEC_OID_SECG_EC_SECT113R2 },
+ { "sect131r1", SEC_OID_SECG_EC_SECT131R1 },
+ { "sect131r2", SEC_OID_SECG_EC_SECT131R2 },
+ { "curve25519", SEC_OID_CURVE25519 },
+ };
+
+static SECKEYECParams *
+getECParams(const char *curve)
+{
+ SECKEYECParams *ecparams;
+ SECOidData *oidData = NULL;
+ SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
+ int i, numCurves;
+
+ if (curve != NULL) {
+ numCurves = sizeof(nameTagPair) / sizeof(CurveNameTagPair);
+ for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN));
+ i++) {
+ if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
+ curveOidTag = nameTagPair[i].curveOidTag;
+ }
+ }
+
+ /* Return NULL if curve name is not recognized */
+ if ((curveOidTag == SEC_OID_UNKNOWN) ||
+ (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
+ fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
+ return NULL;
+ }
+
+ ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
+
+ /*
+ * ecparams->data needs to contain the ASN encoding of an object ID (OID)
+ * representing the named curve. The actual OID is in
+ * oidData->oid.data so we simply prepend 0x06 and OID length
+ */
+ ecparams->data[0] = SEC_ASN1_OBJECT_ID;
+ ecparams->data[1] = oidData->oid.len;
+ memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
+
+ return ecparams;
+}
+#endif /* NSS_DISABLE_ECC */
+
+SECKEYPrivateKey *
+CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size,
+ int publicExponent, const char *noise,
+ SECKEYPublicKey **pubkeyp, const char *pqgFile,
+ PK11AttrFlags attrFlags, CK_FLAGS opFlagsOn,
+ CK_FLAGS opFlagsOff, secuPWData *pwdata)
+{
+ CK_MECHANISM_TYPE mechanism;
+ PK11RSAGenParams rsaparams;
+ SECKEYPQGParams *dsaparams = NULL;
+ void *params;
+ SECKEYPrivateKey *privKey = NULL;
+
+ if (slot == NULL)
+ return NULL;
+
+ if (PK11_Authenticate(slot, PR_TRUE, pwdata) != SECSuccess)
+ return NULL;
+
+ /*
+ * Do some random-number initialization.
+ */
+
+ if (noise) {
+ SECStatus rv = CERTUTIL_FileForRNG(noise);
+ if (rv != SECSuccess) {
+ PORT_SetError(PR_END_OF_FILE_ERROR); /* XXX */
+ return NULL;
+ }
+ } else {
+ int rv = UpdateRNG();
+ if (rv) {
+ PORT_SetError(PR_END_OF_FILE_ERROR);
+ return NULL;
+ }
+ }
+
+ switch (keytype) {
+ case rsaKey:
+ rsaparams.keySizeInBits = size;
+ rsaparams.pe = publicExponent;
+ mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
+ params = &rsaparams;
+ break;
+ case dsaKey:
+ mechanism = CKM_DSA_KEY_PAIR_GEN;
+ if (pqgFile) {
+ dsaparams = getpqgfromfile(size, pqgFile);
+ if (dsaparams == NULL)
+ return NULL;
+ params = dsaparams;
+ } else {
+ /* cast away const, and don't set dsaparams */
+ params = (void *)&default_pqg_params;
+ }
+ break;
+#ifndef NSS_DISABLE_ECC
+ case ecKey:
+ mechanism = CKM_EC_KEY_PAIR_GEN;
+ /* For EC keys, PQGFile determines EC parameters */
+ if ((params = (void *)getECParams(pqgFile)) == NULL)
+ return NULL;
+ break;
+#endif /* NSS_DISABLE_ECC */
+ default:
+ return NULL;
+ }
+
+ fprintf(stderr, "\n\n");
+ fprintf(stderr, "Generating key. This may take a few moments...\n\n");
+
+ privKey = PK11_GenerateKeyPairWithOpFlags(slot, mechanism, params, pubkeyp,
+ attrFlags, opFlagsOn, opFlagsOn |
+ opFlagsOff,
+ pwdata /*wincx*/);
+ /* free up the params */
+ switch (keytype) {
+ case dsaKey:
+ if (dsaparams)
+ CERTUTIL_DestroyParamsPQG(dsaparams);
+ break;
+#ifndef NSS_DISABLE_ECC
+ case ecKey:
+ SECITEM_FreeItem((SECItem *)params, PR_TRUE);
+ break;
+#endif
+ default: /* nothing to free */
+ break;
+ }
+ return privKey;
+}
diff --git a/security/nss/cmd/certutil/manifest.mn b/security/nss/cmd/certutil/manifest.mn
new file mode 100644
index 000000000..c0bce4c7e
--- /dev/null
+++ b/security/nss/cmd/certutil/manifest.mn
@@ -0,0 +1,25 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ certext.c \
+ certutil.c \
+ keystuff.c \
+ $(NULL)
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = dbm seccmd
+
+PROGRAM = certutil
+
+#USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/chktest/Makefile b/security/nss/cmd/chktest/Makefile
new file mode 100644
index 000000000..3ffa38747
--- /dev/null
+++ b/security/nss/cmd/chktest/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/security/nss/cmd/chktest/chktest.c b/security/nss/cmd/chktest/chktest.c
new file mode 100644
index 000000000..a33d18457
--- /dev/null
+++ b/security/nss/cmd/chktest/chktest.c
@@ -0,0 +1,45 @@
+/* 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/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "blapi.h"
+#include "secutil.h"
+
+static int
+Usage()
+{
+ fprintf(stderr, "Usage: chktest <full-path-to-shared-library>\n");
+ fprintf(stderr, " Will test for valid chk file.\n");
+ fprintf(stderr, " Will print SUCCESS or FAILURE.\n");
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ SECStatus rv = SECFailure;
+ PRBool good_result = PR_FALSE;
+
+ if (argc != 2)
+ return Usage();
+
+ rv = RNG_RNGInit();
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError("");
+ return -1;
+ }
+ rv = BL_Init();
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError("");
+ return -1;
+ }
+ RNG_SystemInfoForRNG();
+
+ good_result = BLAPI_SHVerifyFile(argv[1]);
+ printf("%s\n",
+ (good_result ? "SUCCESS" : "FAILURE"));
+ return (good_result) ? SECSuccess : SECFailure;
+}
diff --git a/security/nss/cmd/chktest/chktest.gyp b/security/nss/cmd/chktest/chktest.gyp
new file mode 100644
index 000000000..15abbcc93
--- /dev/null
+++ b/security/nss/cmd/chktest/chktest.gyp
@@ -0,0 +1,32 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'chktest',
+ 'type': 'executable',
+ 'sources': [
+ 'chktest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports',
+ '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSS_USE_STATIC_LIBS'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss',
+ 'use_static_libs': 1
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/chktest/manifest.mn b/security/nss/cmd/chktest/manifest.mn
new file mode 100644
index 000000000..50b1ca1eb
--- /dev/null
+++ b/security/nss/cmd/chktest/manifest.mn
@@ -0,0 +1,27 @@
+#
+# 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/.
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+#REQUIRES = seccmd dbm softoken
+REQUIRES = seccmd dbm
+
+#INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken
+
+PROGRAM = chktest
+
+ USE_STATIC_LIBS = 1
+
+EXPORTS = \
+ $(NULL)
+
+PRIVATE_EXPORTS = \
+ $(NULL)
+
+CSRCS = \
+ chktest.c \
+ $(NULL)
+
diff --git a/security/nss/cmd/crlutil/Makefile b/security/nss/cmd/crlutil/Makefile
new file mode 100644
index 000000000..a61ae1c4c
--- /dev/null
+++ b/security/nss/cmd/crlutil/Makefile
@@ -0,0 +1,53 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+#
+# crlgen_lex can be generated on linux by flex or solaris by lex
+#
+crlgen_lex:
+ ${LEX} -t crlgen_lex_orig.l > crlgen_lex_fix.c
+ sed -f crlgen_lex_fix.sed < crlgen_lex_fix.c > crlgen_lex.c
+ rm -f crlgen_lex_fix.c
+
+include ../platrules.mk
diff --git a/security/nss/cmd/crlutil/crlgen.c b/security/nss/cmd/crlutil/crlgen.c
new file mode 100644
index 000000000..1f9dc4b43
--- /dev/null
+++ b/security/nss/cmd/crlutil/crlgen.c
@@ -0,0 +1,1542 @@
+/* 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/. */
+
+/*
+** crlgen.c
+**
+** utility for managing certificates revocation lists generation
+**
+*/
+
+#include <stdio.h>
+#include <math.h>
+
+#include "nspr.h"
+#include "plgetopt.h"
+#include "nss.h"
+#include "secutil.h"
+#include "cert.h"
+#include "certi.h"
+#include "certdb.h"
+#include "pk11func.h"
+#include "crlgen.h"
+
+/* Destroys extHandle and data. data was create on heap.
+ * extHandle creaded by CERT_StartCRLEntryExtensions. entry
+ * was allocated on arena.*/
+static void
+destroyEntryData(CRLGENEntryData *data)
+{
+ if (!data)
+ return;
+ PORT_Assert(data->entry);
+ if (data->extHandle)
+ CERT_FinishExtensions(data->extHandle);
+ PORT_Free(data);
+}
+
+/* Prints error messages along with line number */
+void
+crlgen_PrintError(int line, char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+
+ fprintf(stderr, "crlgen: (line: %d) ", line);
+ vfprintf(stderr, msg, args);
+
+ va_end(args);
+}
+/* Finds CRLGENEntryData in hashtable according PRUint64 value
+ * - certId : cert serial number*/
+static CRLGENEntryData *
+crlgen_FindEntry(CRLGENGeneratorData *crlGenData, SECItem *certId)
+{
+ if (!crlGenData->entryDataHashTable || !certId)
+ return NULL;
+ return (CRLGENEntryData *)
+ PL_HashTableLookup(crlGenData->entryDataHashTable,
+ certId);
+}
+
+/* Removes CRLGENEntryData from hashtable according to certId
+ * - certId : cert serial number*/
+static SECStatus
+crlgen_RmEntry(CRLGENGeneratorData *crlGenData, SECItem *certId)
+{
+ CRLGENEntryData *data = NULL;
+ SECStatus rv = SECSuccess;
+
+ if (!crlGenData->entryDataHashTable) {
+ return SECSuccess;
+ }
+
+ data = crlgen_FindEntry(crlGenData, certId);
+ if (!data) {
+ return SECSuccess;
+ }
+
+ if (!PL_HashTableRemove(crlGenData->entryDataHashTable, certId)) {
+ rv = SECFailure;
+ }
+
+ destroyEntryData(data);
+ return rv;
+}
+
+/* Stores CRLGENEntryData in hashtable according to certId
+ * - certId : cert serial number*/
+static CRLGENEntryData *
+crlgen_PlaceAnEntry(CRLGENGeneratorData *crlGenData,
+ CERTCrlEntry *entry, SECItem *certId)
+{
+ CRLGENEntryData *newData = NULL;
+
+ PORT_Assert(crlGenData && crlGenData->entryDataHashTable &&
+ entry);
+ if (!crlGenData || !crlGenData->entryDataHashTable || !entry) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ newData = PORT_ZNew(CRLGENEntryData);
+ if (!newData) {
+ return NULL;
+ }
+ newData->entry = entry;
+ newData->certId = certId;
+ if (!PL_HashTableAdd(crlGenData->entryDataHashTable,
+ newData->certId, newData)) {
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "Can not add entryData structure\n");
+ return NULL;
+ }
+ return newData;
+}
+
+/* Use this structure to keep pointer when commiting entries extensions */
+struct commitData {
+ int pos;
+ CERTCrlEntry **entries;
+};
+
+/* HT PL_HashTableEnumerateEntries callback. Sorts hashtable entries of the
+ * table he. Returns value through arg parameter*/
+static PRIntn PR_CALLBACK
+crlgen_CommitEntryData(PLHashEntry *he, PRIntn i, void *arg)
+{
+ CRLGENEntryData *data = NULL;
+
+ PORT_Assert(he);
+ if (!he) {
+ return HT_ENUMERATE_NEXT;
+ }
+ data = (CRLGENEntryData *)he->value;
+
+ PORT_Assert(data);
+ PORT_Assert(arg);
+
+ if (data) {
+ struct commitData *dt = (struct commitData *)arg;
+ dt->entries[dt->pos++] = data->entry;
+ destroyEntryData(data);
+ }
+ return HT_ENUMERATE_NEXT;
+}
+
+/* Copy char * datainto allocated in arena SECItem */
+static SECStatus
+crlgen_SetString(PLArenaPool *arena, const char *dataIn, SECItem *value)
+{
+ SECItem item;
+
+ PORT_Assert(arena && dataIn);
+ if (!arena || !dataIn) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ item.data = (void *)dataIn;
+ item.len = PORT_Strlen(dataIn);
+
+ return SECITEM_CopyItem(arena, value, &item);
+}
+
+/* Creates CERTGeneralName from parsed data for the Authority Key Extension */
+static CERTGeneralName *
+crlgen_GetGeneralName(PLArenaPool *arena, CRLGENGeneratorData *crlGenData,
+ const char *data)
+{
+ CERTGeneralName *namesList = NULL;
+ CERTGeneralName *current;
+ CERTGeneralName *tail = NULL;
+ SECStatus rv = SECSuccess;
+ const char *nextChunk = NULL;
+ const char *currData = NULL;
+ int intValue;
+ char buffer[512];
+ void *mark;
+
+ if (!data)
+ return NULL;
+ PORT_Assert(arena);
+ if (!arena) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ mark = PORT_ArenaMark(arena);
+
+ nextChunk = data;
+ currData = data;
+ do {
+ int nameLen = 0;
+ char name[128];
+ const char *sepPrt = NULL;
+ nextChunk = PORT_Strchr(currData, '|');
+ if (!nextChunk)
+ nextChunk = data + strlen(data);
+ sepPrt = PORT_Strchr(currData, ':');
+ if (sepPrt == NULL || sepPrt >= nextChunk) {
+ *buffer = '\0';
+ sepPrt = nextChunk;
+ } else {
+ PORT_Memcpy(buffer, sepPrt + 1,
+ (nextChunk - sepPrt - 1));
+ buffer[nextChunk - sepPrt - 1] = '\0';
+ }
+ nameLen = PR_MIN(sepPrt - currData, sizeof(name) - 1);
+ PORT_Memcpy(name, currData, nameLen);
+ name[nameLen] = '\0';
+ currData = nextChunk + 1;
+
+ if (!PORT_Strcmp(name, "otherName"))
+ intValue = certOtherName;
+ else if (!PORT_Strcmp(name, "rfc822Name"))
+ intValue = certRFC822Name;
+ else if (!PORT_Strcmp(name, "dnsName"))
+ intValue = certDNSName;
+ else if (!PORT_Strcmp(name, "x400Address"))
+ intValue = certX400Address;
+ else if (!PORT_Strcmp(name, "directoryName"))
+ intValue = certDirectoryName;
+ else if (!PORT_Strcmp(name, "ediPartyName"))
+ intValue = certEDIPartyName;
+ else if (!PORT_Strcmp(name, "URI"))
+ intValue = certURI;
+ else if (!PORT_Strcmp(name, "ipAddress"))
+ intValue = certIPAddress;
+ else if (!PORT_Strcmp(name, "registerID"))
+ intValue = certRegisterID;
+ else
+ intValue = -1;
+
+ if (intValue >= certOtherName && intValue <= certRegisterID) {
+ if (namesList == NULL) {
+ namesList = current = tail = PORT_ArenaZNew(arena,
+ CERTGeneralName);
+ } else {
+ current = PORT_ArenaZNew(arena, CERTGeneralName);
+ }
+ if (current == NULL) {
+ rv = SECFailure;
+ break;
+ }
+ } else {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ break;
+ }
+ current->type = intValue;
+ switch (current->type) {
+ case certURI:
+ case certDNSName:
+ case certRFC822Name:
+ current->name.other.data = PORT_ArenaAlloc(arena, strlen(buffer));
+ if (current->name.other.data == NULL) {
+ rv = SECFailure;
+ break;
+ }
+ PORT_Memcpy(current->name.other.data, buffer,
+ current->name.other.len = strlen(buffer));
+ break;
+
+ case certEDIPartyName:
+ case certIPAddress:
+ case certOtherName:
+ case certRegisterID:
+ case certX400Address: {
+
+ current->name.other.data = PORT_ArenaAlloc(arena, strlen(buffer) + 2);
+ if (current->name.other.data == NULL) {
+ rv = SECFailure;
+ break;
+ }
+
+ PORT_Memcpy(current->name.other.data + 2, buffer, strlen(buffer));
+ /* This may not be accurate for all cases.For now, use this tag type */
+ current->name.other.data[0] = (char)(((current->type - 1) & 0x1f) | 0x80);
+ current->name.other.data[1] = (char)strlen(buffer);
+ current->name.other.len = strlen(buffer) + 2;
+ break;
+ }
+
+ case certDirectoryName: {
+ CERTName *directoryName = NULL;
+
+ directoryName = CERT_AsciiToName(buffer);
+ if (!directoryName) {
+ rv = SECFailure;
+ break;
+ }
+
+ rv = CERT_CopyName(arena, &current->name.directoryName, directoryName);
+ CERT_DestroyName(directoryName);
+
+ break;
+ }
+ }
+ if (rv != SECSuccess)
+ break;
+ current->l.next = &(namesList->l);
+ current->l.prev = &(tail->l);
+ tail->l.next = &(current->l);
+ tail = current;
+
+ } while (nextChunk != data + strlen(data));
+
+ if (rv != SECSuccess) {
+ PORT_ArenaRelease(arena, mark);
+ namesList = NULL;
+ }
+ return (namesList);
+}
+
+/* Creates CERTGeneralName from parsed data for the Authority Key Extension */
+static CERTGeneralName *
+crlgen_DistinguishedName(PLArenaPool *arena, CRLGENGeneratorData *crlGenData,
+ const char *data)
+{
+ CERTName *directoryName = NULL;
+ CERTGeneralName *current;
+ SECStatus rv = SECFailure;
+ void *mark;
+
+ if (!data)
+ return NULL;
+ PORT_Assert(arena);
+ if (!arena) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ mark = PORT_ArenaMark(arena);
+
+ current = PORT_ArenaZNew(arena, CERTGeneralName);
+ if (current == NULL) {
+ goto loser;
+ }
+ current->type = certDirectoryName;
+ current->l.next = &current->l;
+ current->l.prev = &current->l;
+
+ directoryName = CERT_AsciiToName((char *)data);
+ if (!directoryName) {
+ goto loser;
+ }
+
+ rv = CERT_CopyName(arena, &current->name.directoryName, directoryName);
+ CERT_DestroyName(directoryName);
+
+loser:
+ if (rv != SECSuccess) {
+ PORT_SetError(rv);
+ PORT_ArenaRelease(arena, mark);
+ current = NULL;
+ }
+ return (current);
+}
+
+/* Adding Authority Key ID extension to extension handle. */
+static SECStatus
+crlgen_AddAuthKeyID(CRLGENGeneratorData *crlGenData,
+ const char **dataArr)
+{
+ void *extHandle = NULL;
+ CERTAuthKeyID *authKeyID = NULL;
+ PLArenaPool *arena = NULL;
+ SECStatus rv = SECSuccess;
+
+ PORT_Assert(dataArr && crlGenData);
+ if (!crlGenData || !dataArr) {
+ return SECFailure;
+ }
+
+ extHandle = crlGenData->crlExtHandle;
+
+ if (!dataArr[0] || !dataArr[1] || !dataArr[2]) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "insufficient number of parameters.\n");
+ return SECFailure;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ return SECFailure;
+ }
+
+ authKeyID = PORT_ArenaZNew(arena, CERTAuthKeyID);
+ if (authKeyID == NULL) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ if (dataArr[3] == NULL) {
+ rv = crlgen_SetString(arena, dataArr[2], &authKeyID->keyID);
+ if (rv != SECSuccess)
+ goto loser;
+ } else {
+ rv = crlgen_SetString(arena, dataArr[3],
+ &authKeyID->authCertSerialNumber);
+ if (rv != SECSuccess)
+ goto loser;
+
+ authKeyID->authCertIssuer =
+ crlgen_DistinguishedName(arena, crlGenData, dataArr[2]);
+ if (authKeyID->authCertIssuer == NULL && SECFailure == PORT_GetError()) {
+ crlgen_PrintError(crlGenData->parsedLineNum, "syntax error.\n");
+ rv = SECFailure;
+ goto loser;
+ }
+ }
+
+ rv =
+ SECU_EncodeAndAddExtensionValue(arena, extHandle, authKeyID,
+ (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
+ SEC_OID_X509_AUTH_KEY_ID,
+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeAuthKeyID);
+loser:
+ if (arena)
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+/* Creates and add Subject Alternative Names extension */
+static SECStatus
+crlgen_AddIssuerAltNames(CRLGENGeneratorData *crlGenData,
+ const char **dataArr)
+{
+ CERTGeneralName *nameList = NULL;
+ PLArenaPool *arena = NULL;
+ void *extHandle = NULL;
+ SECStatus rv = SECSuccess;
+
+ PORT_Assert(dataArr && crlGenData);
+ if (!crlGenData || !dataArr) {
+ return SECFailure;
+ }
+
+ if (!dataArr || !dataArr[0] || !dataArr[1] || !dataArr[2]) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "insufficient number of arguments.\n");
+ return SECFailure;
+ }
+
+ PORT_Assert(dataArr && crlGenData);
+ if (!crlGenData || !dataArr) {
+ return SECFailure;
+ }
+
+ extHandle = crlGenData->crlExtHandle;
+
+ if (!dataArr[0] || !dataArr[1] || !dataArr[2]) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "insufficient number of parameters.\n");
+ return SECFailure;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ return SECFailure;
+ }
+
+ nameList = crlgen_GetGeneralName(arena, crlGenData, dataArr[2]);
+ if (nameList == NULL) {
+ crlgen_PrintError(crlGenData->parsedLineNum, "syntax error.\n");
+ rv = SECFailure;
+ goto loser;
+ }
+
+ rv =
+ SECU_EncodeAndAddExtensionValue(arena, extHandle, nameList,
+ (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
+ SEC_OID_X509_ISSUER_ALT_NAME,
+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeAltNameExtension);
+loser:
+ if (arena)
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+/* Creates and adds CRLNumber extension to extension handle.
+ * Since, this is CRL extension, extension handle is the one
+ * related to CRL extensions */
+static SECStatus
+crlgen_AddCrlNumber(CRLGENGeneratorData *crlGenData, const char **dataArr)
+{
+ PLArenaPool *arena = NULL;
+ SECItem encodedItem;
+ void *dummy;
+ SECStatus rv = SECFailure;
+ int code = 0;
+
+ PORT_Assert(dataArr && crlGenData);
+ if (!crlGenData || !dataArr) {
+ goto loser;
+ }
+
+ if (!dataArr[0] || !dataArr[1] || !dataArr[2]) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "insufficient number of arguments.\n");
+ goto loser;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ goto loser;
+ }
+
+ code = atoi(dataArr[2]);
+ if (code == 0 && *dataArr[2] != '0') {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ goto loser;
+ }
+
+ dummy = SEC_ASN1EncodeInteger(arena, &encodedItem, code);
+ if (!dummy) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ rv = CERT_AddExtension(crlGenData->crlExtHandle, SEC_OID_X509_CRL_NUMBER,
+ &encodedItem,
+ (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
+ PR_TRUE);
+
+loser:
+ if (arena)
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+/* Creates Cert Revocation Reason code extension. Encodes it and
+ * returns as SECItem structure */
+static SECItem *
+crlgen_CreateReasonCode(PLArenaPool *arena, const char **dataArr,
+ int *extCode)
+{
+ SECItem *encodedItem;
+ void *dummy;
+ void *mark = NULL;
+ int code = 0;
+
+ PORT_Assert(arena && dataArr);
+ if (!arena || !dataArr) {
+ goto loser;
+ }
+
+ mark = PORT_ArenaMark(arena);
+
+ encodedItem = PORT_ArenaZNew(arena, SECItem);
+ if (encodedItem == NULL) {
+ goto loser;
+ }
+
+ if (dataArr[2] == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ goto loser;
+ }
+
+ code = atoi(dataArr[2]);
+ /* aACompromise(10) is the last possible of the values
+ * for the Reason Core Extension */
+ if ((code == 0 && *dataArr[2] != '0') || code > 10) {
+
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ goto loser;
+ }
+
+ dummy = SEC_ASN1EncodeInteger(arena, encodedItem, code);
+ if (!dummy) {
+ goto loser;
+ }
+
+ *extCode = SEC_OID_X509_REASON_CODE;
+ return encodedItem;
+
+loser:
+ if (mark) {
+ PORT_ArenaRelease(arena, mark);
+ }
+ return NULL;
+}
+
+/* Creates Cert Invalidity Date extension. Encodes it and
+ * returns as SECItem structure */
+static SECItem *
+crlgen_CreateInvalidityDate(PLArenaPool *arena, const char **dataArr,
+ int *extCode)
+{
+ SECItem *encodedItem;
+ int length = 0;
+ void *mark = NULL;
+
+ PORT_Assert(arena && dataArr);
+ if (!arena || !dataArr) {
+ goto loser;
+ }
+
+ mark = PORT_ArenaMark(arena);
+
+ encodedItem = PORT_ArenaZNew(arena, SECItem);
+ if (encodedItem == NULL) {
+ goto loser;
+ }
+
+ length = PORT_Strlen(dataArr[2]);
+
+ encodedItem->type = siGeneralizedTime;
+ encodedItem->data = PORT_ArenaAlloc(arena, length);
+ if (!encodedItem->data) {
+ goto loser;
+ }
+
+ PORT_Memcpy(encodedItem->data, dataArr[2], (encodedItem->len = length) *
+ sizeof(char));
+
+ *extCode = SEC_OID_X509_INVALID_DATE;
+ return encodedItem;
+
+loser:
+ if (mark) {
+ PORT_ArenaRelease(arena, mark);
+ }
+ return NULL;
+}
+
+/* Creates(by calling extCreator function) and adds extension to a set
+ * of already added certs. Uses values of rangeFrom and rangeTo from
+ * CRLGENCrlGenCtl structure for identifying the inclusive set of certs */
+static SECStatus
+crlgen_AddEntryExtension(CRLGENGeneratorData *crlGenData,
+ const char **dataArr, char *extName,
+ SECItem *(*extCreator)(PLArenaPool *arena,
+ const char **dataArr,
+ int *extCode))
+{
+ PRUint64 i = 0;
+ SECStatus rv = SECFailure;
+ int extCode = 0;
+ PRUint64 lastRange;
+ SECItem *ext = NULL;
+ PLArenaPool *arena = NULL;
+
+ PORT_Assert(crlGenData && dataArr);
+ if (!crlGenData || !dataArr) {
+ goto loser;
+ }
+
+ if (!dataArr[0] || !dataArr[1]) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "insufficient number of arguments.\n");
+ }
+
+ lastRange = crlGenData->rangeTo - crlGenData->rangeFrom + 1;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ goto loser;
+ }
+
+ ext = extCreator(arena, dataArr, &extCode);
+ if (ext == NULL) {
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "got error while creating extension: %s\n",
+ extName);
+ goto loser;
+ }
+
+ for (i = 0; i < lastRange; i++) {
+ CRLGENEntryData *extData = NULL;
+ void *extHandle = NULL;
+ SECItem *certIdItem =
+ SEC_ASN1EncodeInteger(arena, NULL,
+ crlGenData->rangeFrom + i);
+ if (!certIdItem) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ extData = crlgen_FindEntry(crlGenData, certIdItem);
+ if (!extData) {
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "can not add extension: crl entry "
+ "(serial number: %d) is not in the list yet.\n",
+ crlGenData->rangeFrom + i);
+ continue;
+ }
+
+ extHandle = extData->extHandle;
+ if (extHandle == NULL) {
+ extHandle = extData->extHandle =
+ CERT_StartCRLEntryExtensions(&crlGenData->signCrl->crl,
+ (CERTCrlEntry *)extData->entry);
+ }
+ rv = CERT_AddExtension(extHandle, extCode, ext,
+ (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
+ PR_TRUE);
+ if (rv == SECFailure) {
+ goto loser;
+ }
+ }
+
+loser:
+ if (arena)
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+/* Commits all added entries and their's extensions into CRL. */
+SECStatus
+CRLGEN_CommitExtensionsAndEntries(CRLGENGeneratorData *crlGenData)
+{
+ int size = 0;
+ CERTCrl *crl;
+ PLArenaPool *arena;
+ SECStatus rv = SECSuccess;
+ void *mark;
+
+ PORT_Assert(crlGenData && crlGenData->signCrl && crlGenData->signCrl->arena);
+ if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ arena = crlGenData->signCrl->arena;
+ crl = &crlGenData->signCrl->crl;
+
+ mark = PORT_ArenaMark(arena);
+
+ if (crlGenData->crlExtHandle)
+ CERT_FinishExtensions(crlGenData->crlExtHandle);
+
+ size = crlGenData->entryDataHashTable->nentries;
+ crl->entries = NULL;
+ if (size) {
+ crl->entries = PORT_ArenaZNewArray(arena, CERTCrlEntry *, size + 1);
+ if (!crl->entries) {
+ rv = SECFailure;
+ } else {
+ struct commitData dt;
+ dt.entries = crl->entries;
+ dt.pos = 0;
+ PL_HashTableEnumerateEntries(crlGenData->entryDataHashTable,
+ &crlgen_CommitEntryData, &dt);
+ /* Last should be NULL */
+ crl->entries[size] = NULL;
+ }
+ }
+
+ if (rv != SECSuccess)
+ PORT_ArenaRelease(arena, mark);
+ return rv;
+}
+
+/* Initializes extHandle with data from extensions array */
+static SECStatus
+crlgen_InitExtensionHandle(void *extHandle,
+ CERTCertExtension **extensions)
+{
+ CERTCertExtension *extension = NULL;
+
+ if (!extensions)
+ return SECSuccess;
+
+ PORT_Assert(extHandle != NULL);
+ if (!extHandle) {
+ return SECFailure;
+ }
+
+ extension = *extensions;
+ while (extension) {
+ SECOidTag oidTag = SECOID_FindOIDTag(&extension->id);
+ /* shell we skip unknown extensions? */
+ CERT_AddExtension(extHandle, oidTag, &extension->value,
+ (extension->critical.len != 0) ? PR_TRUE : PR_FALSE,
+ PR_FALSE);
+ extension = *(++extensions);
+ }
+ return SECSuccess;
+}
+
+/* Used for initialization of extension handles for crl and certs
+ * extensions from existing CRL data then modifying existing CRL.*/
+SECStatus
+CRLGEN_ExtHandleInit(CRLGENGeneratorData *crlGenData)
+{
+ CERTCrl *crl = NULL;
+ PRUint64 maxSN = 0;
+
+ PORT_Assert(crlGenData && crlGenData->signCrl &&
+ crlGenData->entryDataHashTable);
+ if (!crlGenData || !crlGenData->signCrl ||
+ !crlGenData->entryDataHashTable) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ crl = &crlGenData->signCrl->crl;
+ crlGenData->crlExtHandle = CERT_StartCRLExtensions(crl);
+ crlgen_InitExtensionHandle(crlGenData->crlExtHandle,
+ crl->extensions);
+ crl->extensions = NULL;
+
+ if (crl->entries) {
+ CERTCrlEntry **entry = crl->entries;
+ while (*entry) {
+ PRUint64 sn = DER_GetInteger(&(*entry)->serialNumber);
+ CRLGENEntryData *extData =
+ crlgen_PlaceAnEntry(crlGenData, *entry, &(*entry)->serialNumber);
+ if ((*entry)->extensions) {
+ extData->extHandle =
+ CERT_StartCRLEntryExtensions(&crlGenData->signCrl->crl,
+ (CERTCrlEntry *)extData->entry);
+ if (crlgen_InitExtensionHandle(extData->extHandle,
+ (*entry)->extensions) == SECFailure)
+ return SECFailure;
+ }
+ (*entry)->extensions = NULL;
+ entry++;
+ maxSN = PR_MAX(maxSN, sn);
+ }
+ }
+
+ crlGenData->rangeFrom = crlGenData->rangeTo = maxSN + 1;
+ return SECSuccess;
+}
+
+/*****************************************************************************
+ * Parser trigger functions start here
+ */
+
+/* Sets new internal range value for add/rm certs.*/
+static SECStatus
+crlgen_SetNewRangeField(CRLGENGeneratorData *crlGenData, char *value)
+{
+ long rangeFrom = 0, rangeTo = 0;
+ char *dashPos = NULL;
+
+ PORT_Assert(crlGenData);
+ if (!crlGenData) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (value == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "insufficient number of arguments.\n");
+ return SECFailure;
+ }
+
+ if ((dashPos = strchr(value, '-')) != NULL) {
+ char *rangeToS, *rangeFromS = value;
+ *dashPos = '\0';
+ rangeFrom = atoi(rangeFromS);
+ *dashPos = '-';
+
+ rangeToS = (char *)(dashPos + 1);
+ rangeTo = atol(rangeToS);
+ } else {
+ rangeFrom = atol(value);
+ rangeTo = rangeFrom;
+ }
+
+ if (rangeFrom < 1 || rangeTo < rangeFrom) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "bad cert id range: %s.\n", value);
+ return SECFailure;
+ }
+
+ crlGenData->rangeFrom = rangeFrom;
+ crlGenData->rangeTo = rangeTo;
+
+ return SECSuccess;
+}
+
+/* Changes issuer subject field in CRL. By default this data is taken from
+ * issuer cert subject field.Not yet implemented */
+static SECStatus
+crlgen_SetIssuerField(CRLGENGeneratorData *crlGenData, char *value)
+{
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "Can not change CRL issuer field.\n");
+ return SECFailure;
+}
+
+/* Encode and sets CRL thisUpdate and nextUpdate time fields*/
+static SECStatus
+crlgen_SetTimeField(CRLGENGeneratorData *crlGenData, char *value,
+ PRBool setThisUpdate)
+{
+ CERTSignedCrl *signCrl;
+ PLArenaPool *arena;
+ CERTCrl *crl;
+ int length = 0;
+ SECItem *timeDest = NULL;
+
+ PORT_Assert(crlGenData && crlGenData->signCrl &&
+ crlGenData->signCrl->arena);
+ if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ signCrl = crlGenData->signCrl;
+ arena = signCrl->arena;
+ crl = &signCrl->crl;
+
+ if (value == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "insufficient number of arguments.\n");
+ return SECFailure;
+ }
+ length = PORT_Strlen(value);
+
+ if (setThisUpdate == PR_TRUE) {
+ timeDest = &crl->lastUpdate;
+ } else {
+ timeDest = &crl->nextUpdate;
+ }
+
+ timeDest->type = siGeneralizedTime;
+ timeDest->data = PORT_ArenaAlloc(arena, length);
+ if (!timeDest->data) {
+ return SECFailure;
+ }
+ PORT_Memcpy(timeDest->data, value, length);
+ timeDest->len = length;
+
+ return SECSuccess;
+}
+
+/* Adds new extension into CRL or added cert handles */
+static SECStatus
+crlgen_AddExtension(CRLGENGeneratorData *crlGenData, const char **extData)
+{
+ PORT_Assert(crlGenData && crlGenData->crlExtHandle);
+ if (!crlGenData || !crlGenData->crlExtHandle) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (extData == NULL || *extData == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "insufficient number of arguments.\n");
+ return SECFailure;
+ }
+ if (!PORT_Strcmp(*extData, "authKeyId"))
+ return crlgen_AddAuthKeyID(crlGenData, extData);
+ else if (!PORT_Strcmp(*extData, "issuerAltNames"))
+ return crlgen_AddIssuerAltNames(crlGenData, extData);
+ else if (!PORT_Strcmp(*extData, "crlNumber"))
+ return crlgen_AddCrlNumber(crlGenData, extData);
+ else if (!PORT_Strcmp(*extData, "reasonCode"))
+ return crlgen_AddEntryExtension(crlGenData, extData, "reasonCode",
+ crlgen_CreateReasonCode);
+ else if (!PORT_Strcmp(*extData, "invalidityDate"))
+ return crlgen_AddEntryExtension(crlGenData, extData, "invalidityDate",
+ crlgen_CreateInvalidityDate);
+ else {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "insufficient number of arguments.\n");
+ return SECFailure;
+ }
+}
+
+/* Created CRLGENEntryData for cert with serial number certId and
+ * adds it to entryDataHashTable. certId can be a single cert serial
+ * number or an inclusive rage of certs */
+static SECStatus
+crlgen_AddCert(CRLGENGeneratorData *crlGenData,
+ char *certId, char *revocationDate)
+{
+ CERTSignedCrl *signCrl;
+ SECItem *certIdItem;
+ PLArenaPool *arena;
+ PRUint64 rangeFrom = 0, rangeTo = 0, i = 0;
+ int timeValLength = -1;
+ SECStatus rv = SECFailure;
+ void *mark;
+
+ PORT_Assert(crlGenData && crlGenData->signCrl &&
+ crlGenData->signCrl->arena);
+ if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ signCrl = crlGenData->signCrl;
+ arena = signCrl->arena;
+
+ if (!certId || !revocationDate) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "insufficient number of arguments.\n");
+ return SECFailure;
+ }
+
+ timeValLength = strlen(revocationDate);
+
+ if (crlgen_SetNewRangeField(crlGenData, certId) == SECFailure &&
+ certId) {
+ return SECFailure;
+ }
+ rangeFrom = crlGenData->rangeFrom;
+ rangeTo = crlGenData->rangeTo;
+
+ for (i = 0; i < rangeTo - rangeFrom + 1; i++) {
+ CERTCrlEntry *entry;
+ mark = PORT_ArenaMark(arena);
+ entry = PORT_ArenaZNew(arena, CERTCrlEntry);
+ if (entry == NULL) {
+ goto loser;
+ }
+
+ certIdItem = SEC_ASN1EncodeInteger(arena, &entry->serialNumber,
+ rangeFrom + i);
+ if (!certIdItem) {
+ goto loser;
+ }
+
+ if (crlgen_FindEntry(crlGenData, certIdItem)) {
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "entry already exists. Use \"range\" "
+ "and \"rmcert\" before adding a new one with the "
+ "same serial number %ld\n",
+ rangeFrom + i);
+ goto loser;
+ }
+
+ entry->serialNumber.type = siBuffer;
+
+ entry->revocationDate.type = siGeneralizedTime;
+
+ entry->revocationDate.data =
+ PORT_ArenaAlloc(arena, timeValLength);
+ if (entry->revocationDate.data == NULL) {
+ goto loser;
+ }
+
+ PORT_Memcpy(entry->revocationDate.data, revocationDate,
+ timeValLength * sizeof(char));
+ entry->revocationDate.len = timeValLength;
+
+ entry->extensions = NULL;
+ if (!crlgen_PlaceAnEntry(crlGenData, entry, certIdItem)) {
+ goto loser;
+ }
+ mark = NULL;
+ }
+
+ rv = SECSuccess;
+loser:
+ if (mark) {
+ PORT_ArenaRelease(arena, mark);
+ }
+ return rv;
+}
+
+/* Removes certs from entryDataHashTable which have certId serial number.
+ * certId can have value of a range of certs */
+static SECStatus
+crlgen_RmCert(CRLGENGeneratorData *crlGenData, char *certId)
+{
+ PRUint64 i = 0;
+
+ PORT_Assert(crlGenData && certId);
+ if (!crlGenData || !certId) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (crlgen_SetNewRangeField(crlGenData, certId) == SECFailure &&
+ certId) {
+ return SECFailure;
+ }
+
+ for (i = 0; i < crlGenData->rangeTo - crlGenData->rangeFrom + 1; i++) {
+ SECItem *certIdItem = SEC_ASN1EncodeInteger(NULL, NULL,
+ crlGenData->rangeFrom + i);
+ if (certIdItem) {
+ CRLGENEntryData *extData =
+ crlgen_FindEntry(crlGenData, certIdItem);
+ if (!extData) {
+ printf("Cert with id %s is not in the list\n", certId);
+ } else {
+ crlgen_RmEntry(crlGenData, certIdItem);
+ }
+ SECITEM_FreeItem(certIdItem, PR_TRUE);
+ }
+ }
+
+ return SECSuccess;
+}
+
+/*************************************************************************
+ * Lex Parser Helper functions are used to store parsed information
+ * in context related structures. Context(or state) is identified base on
+ * a type of a instruction parser currently is going through. New context
+ * is identified by first token in a line. It can be addcert context,
+ * addext context, etc. */
+
+/* Updates CRL field depending on current context */
+static SECStatus
+crlgen_updateCrlFn_field(CRLGENGeneratorData *crlGenData, void *str)
+{
+ CRLGENCrlField *fieldStr = (CRLGENCrlField *)str;
+
+ PORT_Assert(crlGenData);
+ if (!crlGenData) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ switch (crlGenData->contextId) {
+ case CRLGEN_ISSUER_CONTEXT:
+ crlgen_SetIssuerField(crlGenData, fieldStr->value);
+ break;
+ case CRLGEN_UPDATE_CONTEXT:
+ return crlgen_SetTimeField(crlGenData, fieldStr->value, PR_TRUE);
+ break;
+ case CRLGEN_NEXT_UPDATE_CONTEXT:
+ return crlgen_SetTimeField(crlGenData, fieldStr->value, PR_FALSE);
+ break;
+ case CRLGEN_CHANGE_RANGE_CONTEXT:
+ return crlgen_SetNewRangeField(crlGenData, fieldStr->value);
+ break;
+ default:
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "syntax error (unknow token type: %d)\n",
+ crlGenData->contextId);
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+/* Sets parsed data for CRL field update into temporary structure */
+static SECStatus
+crlgen_setNextDataFn_field(CRLGENGeneratorData *crlGenData, void *str,
+ void *data, unsigned short dtype)
+{
+ CRLGENCrlField *fieldStr = (CRLGENCrlField *)str;
+
+ PORT_Assert(crlGenData);
+ if (!crlGenData) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ switch (crlGenData->contextId) {
+ case CRLGEN_CHANGE_RANGE_CONTEXT:
+ if (dtype != CRLGEN_TYPE_DIGIT && dtype != CRLGEN_TYPE_DIGIT_RANGE) {
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "range value should have "
+ "numeric or numeric range values.\n");
+ return SECFailure;
+ }
+ break;
+ case CRLGEN_NEXT_UPDATE_CONTEXT:
+ case CRLGEN_UPDATE_CONTEXT:
+ if (dtype != CRLGEN_TYPE_ZDATE) {
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "bad formated date. Should be "
+ "YYYYMMDDHHMMSSZ.\n");
+ return SECFailure;
+ }
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "syntax error (unknow token type: %d).\n",
+ crlGenData->contextId, data);
+ return SECFailure;
+ }
+ fieldStr->value = PORT_Strdup(data);
+ if (!fieldStr->value) {
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+/* Triggers cert entries update depending on current context */
+static SECStatus
+crlgen_updateCrlFn_cert(CRLGENGeneratorData *crlGenData, void *str)
+{
+ CRLGENCertEntry *certStr = (CRLGENCertEntry *)str;
+
+ PORT_Assert(crlGenData);
+ if (!crlGenData) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ switch (crlGenData->contextId) {
+ case CRLGEN_ADD_CERT_CONTEXT:
+ return crlgen_AddCert(crlGenData, certStr->certId,
+ certStr->revocationTime);
+ case CRLGEN_RM_CERT_CONTEXT:
+ return crlgen_RmCert(crlGenData, certStr->certId);
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "syntax error (unknow token type: %d).\n",
+ crlGenData->contextId);
+ return SECFailure;
+ }
+}
+
+/* Sets parsed data for CRL entries update into temporary structure */
+static SECStatus
+crlgen_setNextDataFn_cert(CRLGENGeneratorData *crlGenData, void *str,
+ void *data, unsigned short dtype)
+{
+ CRLGENCertEntry *certStr = (CRLGENCertEntry *)str;
+
+ PORT_Assert(crlGenData);
+ if (!crlGenData) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ switch (dtype) {
+ case CRLGEN_TYPE_DIGIT:
+ case CRLGEN_TYPE_DIGIT_RANGE:
+ certStr->certId = PORT_Strdup(data);
+ if (!certStr->certId) {
+ return SECFailure;
+ }
+ break;
+ case CRLGEN_TYPE_DATE:
+ case CRLGEN_TYPE_ZDATE:
+ certStr->revocationTime = PORT_Strdup(data);
+ if (!certStr->revocationTime) {
+ return SECFailure;
+ }
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "syntax error (unknow token type: %d).\n",
+ crlGenData->contextId);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+/* Triggers cert entries/crl extension update */
+static SECStatus
+crlgen_updateCrlFn_extension(CRLGENGeneratorData *crlGenData, void *str)
+{
+ CRLGENExtensionEntry *extStr = (CRLGENExtensionEntry *)str;
+
+ return crlgen_AddExtension(crlGenData, (const char **)extStr->extData);
+}
+
+/* Defines maximum number of fields extension may have */
+#define MAX_EXT_DATA_LENGTH 10
+
+/* Sets parsed extension data for CRL entries/CRL extensions update
+ * into temporary structure */
+static SECStatus
+crlgen_setNextDataFn_extension(CRLGENGeneratorData *crlGenData, void *str,
+ void *data, unsigned short dtype)
+{
+ CRLGENExtensionEntry *extStr = (CRLGENExtensionEntry *)str;
+
+ PORT_Assert(crlGenData);
+ if (!crlGenData) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (extStr->extData == NULL) {
+ extStr->extData = PORT_ZNewArray(char *, MAX_EXT_DATA_LENGTH);
+ if (!extStr->extData) {
+ return SECFailure;
+ }
+ }
+ if (extStr->nextUpdatedData >= MAX_EXT_DATA_LENGTH) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "number of fields in extension "
+ "exceeded maximum allowed data length: %d.\n",
+ MAX_EXT_DATA_LENGTH);
+ return SECFailure;
+ }
+ extStr->extData[extStr->nextUpdatedData] = PORT_Strdup(data);
+ if (!extStr->extData[extStr->nextUpdatedData]) {
+ return SECFailure;
+ }
+ extStr->nextUpdatedData += 1;
+
+ return SECSuccess;
+}
+
+/****************************************************************************************
+ * Top level functions are triggered directly by parser.
+ */
+
+/*
+ * crl generation script parser recreates a temporary data staructure
+ * for each line it is going through. This function cleans temp structure.
+ */
+void
+crlgen_destroyTempData(CRLGENGeneratorData *crlGenData)
+{
+ if (crlGenData->contextId != CRLGEN_UNKNOWN_CONTEXT) {
+ switch (crlGenData->contextId) {
+ case CRLGEN_ISSUER_CONTEXT:
+ case CRLGEN_UPDATE_CONTEXT:
+ case CRLGEN_NEXT_UPDATE_CONTEXT:
+ case CRLGEN_CHANGE_RANGE_CONTEXT:
+ if (crlGenData->crlField->value)
+ PORT_Free(crlGenData->crlField->value);
+ PORT_Free(crlGenData->crlField);
+ break;
+ case CRLGEN_ADD_CERT_CONTEXT:
+ case CRLGEN_RM_CERT_CONTEXT:
+ if (crlGenData->certEntry->certId)
+ PORT_Free(crlGenData->certEntry->certId);
+ if (crlGenData->certEntry->revocationTime)
+ PORT_Free(crlGenData->certEntry->revocationTime);
+ PORT_Free(crlGenData->certEntry);
+ break;
+ case CRLGEN_ADD_EXTENSION_CONTEXT:
+ if (crlGenData->extensionEntry->extData) {
+ int i = 0;
+ for (; i < crlGenData->extensionEntry->nextUpdatedData; i++)
+ PORT_Free(*(crlGenData->extensionEntry->extData + i));
+ PORT_Free(crlGenData->extensionEntry->extData);
+ }
+ PORT_Free(crlGenData->extensionEntry);
+ break;
+ }
+ crlGenData->contextId = CRLGEN_UNKNOWN_CONTEXT;
+ }
+}
+
+SECStatus
+crlgen_updateCrl(CRLGENGeneratorData *crlGenData)
+{
+ SECStatus rv = SECSuccess;
+
+ PORT_Assert(crlGenData);
+ if (!crlGenData) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ switch (crlGenData->contextId) {
+ case CRLGEN_ISSUER_CONTEXT:
+ case CRLGEN_UPDATE_CONTEXT:
+ case CRLGEN_NEXT_UPDATE_CONTEXT:
+ case CRLGEN_CHANGE_RANGE_CONTEXT:
+ rv = crlGenData->crlField->updateCrlFn(crlGenData, crlGenData->crlField);
+ break;
+ case CRLGEN_RM_CERT_CONTEXT:
+ case CRLGEN_ADD_CERT_CONTEXT:
+ rv = crlGenData->certEntry->updateCrlFn(crlGenData, crlGenData->certEntry);
+ break;
+ case CRLGEN_ADD_EXTENSION_CONTEXT:
+ rv = crlGenData->extensionEntry->updateCrlFn(crlGenData, crlGenData->extensionEntry);
+ break;
+ case CRLGEN_UNKNOWN_CONTEXT:
+ break;
+ default:
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "unknown lang context type code: %d.\n",
+ crlGenData->contextId);
+ PORT_Assert(0);
+ return SECFailure;
+ }
+ /* Clrean structures after crl update */
+ crlgen_destroyTempData(crlGenData);
+
+ crlGenData->parsedLineNum += 1;
+
+ return rv;
+}
+
+SECStatus
+crlgen_setNextData(CRLGENGeneratorData *crlGenData, void *data,
+ unsigned short dtype)
+{
+ SECStatus rv = SECSuccess;
+
+ PORT_Assert(crlGenData);
+ if (!crlGenData) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ switch (crlGenData->contextId) {
+ case CRLGEN_ISSUER_CONTEXT:
+ case CRLGEN_UPDATE_CONTEXT:
+ case CRLGEN_NEXT_UPDATE_CONTEXT:
+ case CRLGEN_CHANGE_RANGE_CONTEXT:
+ rv = crlGenData->crlField->setNextDataFn(crlGenData, crlGenData->crlField,
+ data, dtype);
+ break;
+ case CRLGEN_ADD_CERT_CONTEXT:
+ case CRLGEN_RM_CERT_CONTEXT:
+ rv = crlGenData->certEntry->setNextDataFn(crlGenData, crlGenData->certEntry,
+ data, dtype);
+ break;
+ case CRLGEN_ADD_EXTENSION_CONTEXT:
+ rv =
+ crlGenData->extensionEntry->setNextDataFn(crlGenData, crlGenData->extensionEntry, data, dtype);
+ break;
+ case CRLGEN_UNKNOWN_CONTEXT:
+ break;
+ default:
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "unknown context type: %d.\n",
+ crlGenData->contextId);
+ PORT_Assert(0);
+ return SECFailure;
+ }
+ return rv;
+}
+
+SECStatus
+crlgen_createNewLangStruct(CRLGENGeneratorData *crlGenData,
+ unsigned structType)
+{
+ PORT_Assert(crlGenData &&
+ crlGenData->contextId == CRLGEN_UNKNOWN_CONTEXT);
+ if (!crlGenData ||
+ crlGenData->contextId != CRLGEN_UNKNOWN_CONTEXT) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ switch (structType) {
+ case CRLGEN_ISSUER_CONTEXT:
+ case CRLGEN_UPDATE_CONTEXT:
+ case CRLGEN_NEXT_UPDATE_CONTEXT:
+ case CRLGEN_CHANGE_RANGE_CONTEXT:
+ crlGenData->crlField = PORT_New(CRLGENCrlField);
+ if (!crlGenData->crlField) {
+ return SECFailure;
+ }
+ crlGenData->contextId = structType;
+ crlGenData->crlField->value = NULL;
+ crlGenData->crlField->updateCrlFn = &crlgen_updateCrlFn_field;
+ crlGenData->crlField->setNextDataFn = &crlgen_setNextDataFn_field;
+ break;
+ case CRLGEN_RM_CERT_CONTEXT:
+ case CRLGEN_ADD_CERT_CONTEXT:
+ crlGenData->certEntry = PORT_New(CRLGENCertEntry);
+ if (!crlGenData->certEntry) {
+ return SECFailure;
+ }
+ crlGenData->contextId = structType;
+ crlGenData->certEntry->certId = 0;
+ crlGenData->certEntry->revocationTime = NULL;
+ crlGenData->certEntry->updateCrlFn = &crlgen_updateCrlFn_cert;
+ crlGenData->certEntry->setNextDataFn = &crlgen_setNextDataFn_cert;
+ break;
+ case CRLGEN_ADD_EXTENSION_CONTEXT:
+ crlGenData->extensionEntry = PORT_New(CRLGENExtensionEntry);
+ if (!crlGenData->extensionEntry) {
+ return SECFailure;
+ }
+ crlGenData->contextId = structType;
+ crlGenData->extensionEntry->extData = NULL;
+ crlGenData->extensionEntry->nextUpdatedData = 0;
+ crlGenData->extensionEntry->updateCrlFn =
+ &crlgen_updateCrlFn_extension;
+ crlGenData->extensionEntry->setNextDataFn =
+ &crlgen_setNextDataFn_extension;
+ break;
+ case CRLGEN_UNKNOWN_CONTEXT:
+ break;
+ default:
+ crlgen_PrintError(crlGenData->parsedLineNum,
+ "unknown context type: %d.\n", structType);
+ PORT_Assert(0);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+/* Parser initialization function */
+CRLGENGeneratorData *
+CRLGEN_InitCrlGeneration(CERTSignedCrl *signCrl, PRFileDesc *src)
+{
+ CRLGENGeneratorData *crlGenData = NULL;
+
+ PORT_Assert(signCrl && src);
+ if (!signCrl || !src) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ crlGenData = PORT_ZNew(CRLGENGeneratorData);
+ if (!crlGenData) {
+ return NULL;
+ }
+
+ crlGenData->entryDataHashTable =
+ PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare,
+ PL_CompareValues, NULL, NULL);
+ if (!crlGenData->entryDataHashTable) {
+ PORT_Free(crlGenData);
+ return NULL;
+ }
+
+ crlGenData->src = src;
+ crlGenData->parsedLineNum = 1;
+ crlGenData->contextId = CRLGEN_UNKNOWN_CONTEXT;
+ crlGenData->signCrl = signCrl;
+ crlGenData->rangeFrom = 0;
+ crlGenData->rangeTo = 0;
+ crlGenData->crlExtHandle = NULL;
+
+ PORT_SetError(0);
+
+ return crlGenData;
+}
+
+void
+CRLGEN_FinalizeCrlGeneration(CRLGENGeneratorData *crlGenData)
+{
+ if (!crlGenData)
+ return;
+ if (crlGenData->src)
+ PR_Close(crlGenData->src);
+ PL_HashTableDestroy(crlGenData->entryDataHashTable);
+ PORT_Free(crlGenData);
+}
diff --git a/security/nss/cmd/crlutil/crlgen.h b/security/nss/cmd/crlutil/crlgen.h
new file mode 100644
index 000000000..3ec792108
--- /dev/null
+++ b/security/nss/cmd/crlutil/crlgen.h
@@ -0,0 +1,178 @@
+/* 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 _CRLGEN_H_
+#define _CRLGEN_H_
+
+#include "prio.h"
+#include "prprf.h"
+#include "plhash.h"
+#include "seccomon.h"
+#include "certt.h"
+#include "secoidt.h"
+
+#define CRLGEN_UNKNOWN_CONTEXT 0
+#define CRLGEN_ISSUER_CONTEXT 1
+#define CRLGEN_UPDATE_CONTEXT 2
+#define CRLGEN_NEXT_UPDATE_CONTEXT 3
+#define CRLGEN_ADD_EXTENSION_CONTEXT 4
+#define CRLGEN_ADD_CERT_CONTEXT 6
+#define CRLGEN_CHANGE_RANGE_CONTEXT 7
+#define CRLGEN_RM_CERT_CONTEXT 8
+
+#define CRLGEN_TYPE_DATE 0
+#define CRLGEN_TYPE_ZDATE 1
+#define CRLGEN_TYPE_DIGIT 2
+#define CRLGEN_TYPE_DIGIT_RANGE 3
+#define CRLGEN_TYPE_OID 4
+#define CRLGEN_TYPE_STRING 5
+#define CRLGEN_TYPE_ID 6
+
+typedef struct CRLGENGeneratorDataStr CRLGENGeneratorData;
+typedef struct CRLGENEntryDataStr CRLGENEntryData;
+typedef struct CRLGENExtensionEntryStr CRLGENExtensionEntry;
+typedef struct CRLGENCertEntrySrt CRLGENCertEntry;
+typedef struct CRLGENCrlFieldStr CRLGENCrlField;
+typedef struct CRLGENEntriesSortedDataStr CRLGENEntriesSortedData;
+
+/* Exported functions */
+
+/* Used for initialization of extension handles for crl and certs
+ * extensions from existing CRL data then modifying existing CRL.*/
+extern SECStatus CRLGEN_ExtHandleInit(CRLGENGeneratorData *crlGenData);
+
+/* Commits all added entries and their's extensions into CRL. */
+extern SECStatus CRLGEN_CommitExtensionsAndEntries(CRLGENGeneratorData *crlGenData);
+
+/* Lunches the crl generation script parse */
+extern SECStatus CRLGEN_StartCrlGen(CRLGENGeneratorData *crlGenData);
+
+/* Closes crl generation script file and frees crlGenData */
+extern void CRLGEN_FinalizeCrlGeneration(CRLGENGeneratorData *crlGenData);
+
+/* Parser initialization function. Creates CRLGENGeneratorData structure
+ * for the current thread */
+extern CRLGENGeneratorData *CRLGEN_InitCrlGeneration(CERTSignedCrl *newCrl,
+ PRFileDesc *src);
+
+/* This lock is defined in crlgen_lex.c(derived from crlgen_lex.l).
+ * It controls access to invocation of yylex, allows to parse one
+ * script at a time */
+extern void CRLGEN_InitCrlGenParserLock();
+extern void CRLGEN_DestroyCrlGenParserLock();
+
+/* The following function types are used to define functions for each of
+ * CRLGENExtensionEntryStr, CRLGENCertEntrySrt, CRLGENCrlFieldStr to
+ * provide functionality needed for these structures*/
+typedef SECStatus updateCrlFn_t(CRLGENGeneratorData *crlGenData, void *str);
+typedef SECStatus setNextDataFn_t(CRLGENGeneratorData *crlGenData, void *str,
+ void *data, unsigned short dtype);
+typedef SECStatus createNewLangStructFn_t(CRLGENGeneratorData *crlGenData,
+ void *str, unsigned i);
+
+/* Sets reports failure to parser if anything goes wrong */
+extern void crlgen_setFailure(CRLGENGeneratorData *str, char *);
+
+/* Collects data in to one of the current data structure that corresponds
+ * to the correct context type. This function gets called after each token
+ * is found for a particular line */
+extern SECStatus crlgen_setNextData(CRLGENGeneratorData *str, void *data,
+ unsigned short dtype);
+
+/* initiates crl update with collected data. This function is called at the
+ * end of each line */
+extern SECStatus crlgen_updateCrl(CRLGENGeneratorData *str);
+
+/* Creates new context structure depending on token that was parsed
+ * at the beginning of a line */
+extern SECStatus crlgen_createNewLangStruct(CRLGENGeneratorData *str,
+ unsigned structType);
+
+/* CRLGENExtensionEntry is used to store addext request data for either
+ * CRL extensions or CRL entry extensions. The differentiation between
+ * is based on order and type of extension been added.
+ * - extData : all data in request staring from name of the extension are
+ * in saved here.
+ * - nextUpdatedData: counter of elements added to extData
+ */
+struct CRLGENExtensionEntryStr {
+ char **extData;
+ int nextUpdatedData;
+ updateCrlFn_t *updateCrlFn;
+ setNextDataFn_t *setNextDataFn;
+};
+
+/* CRLGENCeryestEntry is used to store addcert request data
+ * - certId : certificate id or range of certificate with dash as a delimiter
+ * All certs from range will be inclusively added to crl
+ * - revocationTime: revocation time of cert(s)
+ */
+struct CRLGENCertEntrySrt {
+ char *certId;
+ char *revocationTime;
+ updateCrlFn_t *updateCrlFn;
+ setNextDataFn_t *setNextDataFn;
+};
+
+/* CRLGENCrlField is used to store crl fields record like update time, next
+ * update time, etc.
+ * - value: value of the parsed field data*/
+struct CRLGENCrlFieldStr {
+ char *value;
+ updateCrlFn_t *updateCrlFn;
+ setNextDataFn_t *setNextDataFn;
+};
+
+/* Can not create entries extension until completely done with parsing.
+ * Therefore need to keep joined data
+ * - certId : serial number of certificate
+ * - extHandle: head pointer to a list of extensions that belong to
+ * entry
+ * - entry : CERTCrlEntry structure pointer*/
+struct CRLGENEntryDataStr {
+ SECItem *certId;
+ void *extHandle;
+ CERTCrlEntry *entry;
+};
+
+/* Crl generator/parser main structure. Keeps info regarding current state of
+ * parser(context, status), parser helper functions pointers, parsed data and
+ * generated data.
+ * - contextId : current parsing context. Context in this parser environment
+ * defines what type of crl operations parser is going through
+ * in the current line of crl generation script.
+ * setting or new cert or an extension addition, etc.
+ * - createNewLangStructFn: pointer to top level function which creates
+ * data structures according contextId
+ * - setNextDataFn : pointer to top level function which sets new parsed data
+ * in temporary structure
+ * - updateCrlFn : pointer to top level function which triggers actual
+ * crl update functions with gathered data
+ * - union : data union create according to contextId
+ * - rangeFrom, rangeTo : holds last range in which certs was added
+ * - newCrl : pointer to CERTSignedCrl newly created crl
+ * - crlExtHandle : pointer to crl extension handle
+ * - entryDataHashTable: hash of CRLGENEntryData.
+ * key: cert serial number
+ * data: CRLGENEntryData pointer
+ * - parserStatus : current status of parser. Triggers parser to abort when
+ * set to SECFailure
+ * - src : PRFileDesc structure pointer of crl generator config file
+ * - parsedLineNum : currently parsing line. Keeping it to report errors */
+struct CRLGENGeneratorDataStr {
+ unsigned short contextId;
+ CRLGENCrlField *crlField;
+ CRLGENCertEntry *certEntry;
+ CRLGENExtensionEntry *extensionEntry;
+ PRUint64 rangeFrom;
+ PRUint64 rangeTo;
+ CERTSignedCrl *signCrl;
+ void *crlExtHandle;
+ PLHashTable *entryDataHashTable;
+
+ PRFileDesc *src;
+ int parsedLineNum;
+};
+
+#endif /* _CRLGEN_H_ */
diff --git a/security/nss/cmd/crlutil/crlgen_lex.c b/security/nss/cmd/crlutil/crlgen_lex.c
new file mode 100644
index 000000000..fb53ec844
--- /dev/null
+++ b/security/nss/cmd/crlutil/crlgen_lex.c
@@ -0,0 +1,1773 @@
+/* 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/. */
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+#ifdef _WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+#pragma warn - rch
+#pragma warn - use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int)(unsigned char)c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin)
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator). This
+ * avoids problems with code like:
+ *
+ * if ( condition_holds )
+ * yyless( 5 );
+ * else
+ * do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+ do { \
+ /* Undo effects of setting up yytext. */ \
+ *yy_cp = yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } while (0)
+
+#define unput(c) yyunput(c, yytext_ptr)
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+struct yy_buffer_state {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+/* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+};
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *)0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO((FILE * input_file));
+
+void yy_switch_to_buffer YY_PROTO((YY_BUFFER_STATE new_buffer));
+void yy_load_buffer_state YY_PROTO((void));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO((FILE * file, int size));
+void yy_delete_buffer YY_PROTO((YY_BUFFER_STATE b));
+void yy_init_buffer YY_PROTO((YY_BUFFER_STATE b, FILE *file));
+void yy_flush_buffer YY_PROTO((YY_BUFFER_STATE b));
+#define YY_FLUSH_BUFFER yy_flush_buffer(yy_current_buffer)
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO((char *base, yy_size_t size));
+YY_BUFFER_STATE yy_scan_string YY_PROTO((yyconst char *yy_str));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO((yyconst char *bytes, int len));
+
+static void *yy_flex_alloc YY_PROTO((yy_size_t));
+static void *yy_flex_realloc YY_PROTO((void *, yy_size_t));
+static void yy_flex_free YY_PROTO((void *));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if (!yy_current_buffer) \
+ yy_current_buffer = yy_create_buffer(yyin, YY_BUF_SIZE); \
+ yy_current_buffer->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if (!yy_current_buffer) \
+ yy_current_buffer = yy_create_buffer(yyin, YY_BUF_SIZE); \
+ yy_current_buffer->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *)0, *yyout = (FILE *)0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO((void));
+static yy_state_type yy_try_NUL_trans YY_PROTO((yy_state_type current_state));
+static int yy_get_next_buffer YY_PROTO((void));
+static void yy_fatal_error YY_PROTO((yyconst char msg[]));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yytext_ptr = yy_bp; \
+ yytext_ptr -= yy_more_len; \
+ yyleng = (int)(yy_cp - yytext_ptr); \
+ yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 17
+#define YY_END_OF_BUFFER 18
+/* clang-format off */
+static yyconst short int yy_accept[67] =
+ { 0,
+ 0, 0, 18, 16, 14, 15, 16, 11, 12, 2,
+ 10, 9, 9, 9, 9, 9, 13, 14, 15, 11,
+ 12, 0, 12, 2, 9, 9, 9, 9, 9, 13,
+ 3, 4, 2, 9, 9, 9, 9, 2, 9, 9,
+ 9, 9, 2, 2, 9, 9, 8, 9, 2, 5,
+ 9, 6, 2, 9, 2, 9, 2, 9, 2, 7,
+ 2, 2, 2, 2, 1, 0
+ } ;
+
+static yyconst int yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 5, 6, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 7, 8, 1, 9, 9, 10,
+ 11, 12, 12, 12, 13, 13, 13, 14, 1, 1,
+ 15, 1, 1, 1, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 17,
+ 1, 1, 1, 1, 1, 1, 18, 16, 16, 19,
+
+ 20, 16, 21, 16, 22, 16, 16, 16, 16, 23,
+ 16, 24, 16, 25, 26, 27, 28, 16, 16, 29,
+ 16, 16, 1, 14, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst int yy_meta[30] =
+ { 0,
+ 1, 1, 2, 1, 3, 1, 1, 4, 5, 5,
+ 5, 5, 5, 4, 1, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4
+ } ;
+
+static yyconst short int yy_base[72] =
+ { 0,
+ 0, 149, 154, 205, 138, 205, 103, 0, 0, 23,
+ 205, 29, 30, 31, 32, 33, 0, 99, 205, 0,
+ 0, 0, 50, 55, 34, 61, 41, 63, 64, 0,
+ 0, 0, 79, 65, 68, 86, 66, 99, 105, 88,
+ 106, 90, 118, 76, 107, 110, 89, 125, 43, 91,
+ 127, 128, 138, 144, 113, 129, 154, 160, 160, 130,
+ 172, 166, 177, 144, 0, 205, 190, 192, 194, 199,
+ 76
+ } ;
+
+static yyconst short int yy_def[72] =
+ { 0,
+ 66, 1, 66, 66, 66, 66, 66, 67, 68, 68,
+ 66, 69, 69, 69, 69, 69, 70, 66, 66, 67,
+ 68, 71, 68, 10, 69, 69, 69, 69, 69, 70,
+ 71, 23, 10, 69, 69, 69, 69, 10, 69, 69,
+ 69, 69, 10, 38, 69, 69, 69, 69, 38, 69,
+ 69, 69, 38, 69, 38, 69, 38, 69, 38, 69,
+ 38, 38, 38, 38, 68, 0, 66, 66, 66, 66,
+ 66
+ } ;
+
+static yyconst short int yy_nxt[235] =
+ { 0,
+ 4, 5, 6, 7, 8, 4, 4, 9, 10, 10,
+ 10, 10, 10, 9, 11, 12, 12, 12, 12, 12,
+ 12, 13, 14, 12, 15, 12, 12, 16, 12, 22,
+ 23, 24, 24, 24, 24, 24, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 28,
+ 27, 53, 53, 53, 21, 26, 29, 32, 32, 32,
+ 32, 32, 32, 33, 33, 33, 33, 33, 21, 35,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 31, 21, 37, 42, 44, 36, 34, 38, 38, 38,
+ 38, 38, 39, 21, 40, 21, 21, 21, 21, 21,
+
+ 18, 21, 21, 21, 21, 19, 41, 43, 44, 44,
+ 44, 44, 21, 21, 21, 46, 48, 21, 21, 21,
+ 21, 57, 57, 21, 45, 47, 49, 49, 49, 49,
+ 49, 50, 21, 51, 21, 21, 21, 21, 21, 18,
+ 21, 21, 21, 21, 52, 54, 55, 55, 55, 55,
+ 55, 21, 44, 66, 17, 58, 66, 21, 66, 66,
+ 65, 56, 59, 59, 59, 59, 59, 21, 61, 61,
+ 61, 61, 66, 21, 63, 63, 63, 63, 66, 60,
+ 62, 62, 62, 62, 62, 64, 64, 64, 64, 64,
+ 20, 20, 66, 20, 20, 21, 21, 25, 25, 30,
+
+ 66, 30, 30, 30, 3, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66
+ } ;
+
+static yyconst short int yy_chk[235] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 10,
+ 10, 10, 10, 10, 10, 10, 12, 13, 14, 15,
+ 16, 25, 12, 13, 14, 15, 16, 25, 27, 15,
+ 14, 49, 49, 49, 27, 13, 16, 23, 23, 23,
+ 23, 23, 23, 24, 24, 24, 24, 24, 26, 27,
+ 28, 29, 34, 37, 26, 35, 28, 29, 34, 37,
+ 71, 35, 29, 37, 44, 28, 26, 33, 33, 33,
+ 33, 33, 34, 36, 35, 40, 47, 42, 50, 36,
+
+ 18, 40, 47, 42, 50, 7, 36, 38, 38, 38,
+ 38, 38, 39, 41, 45, 40, 42, 46, 39, 41,
+ 45, 55, 55, 46, 39, 41, 43, 43, 43, 43,
+ 43, 45, 48, 46, 51, 52, 56, 60, 48, 5,
+ 51, 52, 56, 60, 48, 51, 53, 53, 53, 53,
+ 53, 54, 64, 3, 2, 56, 0, 54, 0, 0,
+ 64, 54, 57, 57, 57, 57, 57, 58, 59, 59,
+ 59, 59, 0, 58, 62, 62, 62, 62, 0, 58,
+ 61, 61, 61, 61, 61, 63, 63, 63, 63, 63,
+ 67, 67, 0, 67, 67, 68, 68, 69, 69, 70,
+
+ 0, 70, 70, 70, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66
+ } ;
+/* clang-format on */
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+static int yy_more_flag = 0;
+static int yy_more_len = 0;
+#define yymore() (yy_more_flag = 1)
+#define YY_MORE_ADJ yy_more_len
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "crlgen_lex_orig.l"
+#define INITIAL 0
+#line 2 "crlgen_lex_orig.l"
+
+#include "crlgen.h"
+
+static SECStatus parserStatus = SECSuccess;
+static CRLGENGeneratorData *parserData;
+static PRFileDesc *src;
+
+#define YY_INPUT(buf, result, max_size) \
+ if (parserStatus != SECFailure) { \
+ if (((result = PR_Read(src, buf, max_size)) == 0) && \
+ ferror(yyin)) \
+ return SECFailure; \
+ } else { \
+ return SECFailure; \
+ }
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO((void));
+#else
+extern int yywrap YY_PROTO((void));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO((int c, char *buf_ptr));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO((char *, yyconst char *, int));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO((yyconst char *));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO((void));
+#else
+static int input YY_PROTO((void));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO((int new_state));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO((void));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO((void));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines. This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void)fwrite(yytext, yyleng, 1, yyout)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf, result, max_size) \
+ if (yy_current_buffer->yy_is_interactive) { \
+ int c = '*', n; \
+ for (n = 0; n < max_size && \
+ (c = getc(yyin)) != EOF && c != '\n'; \
+ ++n) \
+ buf[n] = (char)c; \
+ if (c == '\n') \
+ buf[n++] = (char)c; \
+ if (c == EOF && ferror(yyin)) \
+ YY_FATAL_ERROR("input in flex scanner failed"); \
+ result = n; \
+ } else if (((result = fread(buf, 1, max_size, yyin)) == 0) && \
+ ferror(yyin)) \
+ YY_FATAL_ERROR("input in flex scanner failed");
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error(msg)
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO((void))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ if (yyleng > 0) \
+ yy_current_buffer->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
+ YY_USER_ACTION
+
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp = NULL, *yy_bp = NULL;
+ register int yy_act;
+
+#line 28 "crlgen_lex_orig.l"
+
+ if (yy_init) {
+ yy_init = 0;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if (!yy_start)
+ yy_start = 1; /* first start state */
+
+ if (!yyin)
+ yyin = stdin;
+
+ if (!yyout)
+ yyout = stdout;
+
+ if (!yy_current_buffer)
+ yy_current_buffer =
+ yy_create_buffer(yyin, YY_BUF_SIZE);
+
+ yy_load_buffer_state();
+ }
+
+ while (1) /* loops until end-of-file is reached */
+ {
+ yy_more_len = 0;
+ if (yy_more_flag) {
+ yy_more_len = yy_c_buf_p - yytext_ptr;
+ yy_more_flag = 0;
+ }
+ yy_cp = yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yy_start;
+ yy_current_state += YY_AT_BOL();
+ yy_match:
+ do {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if (yy_accept[yy_current_state]) {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
+ yy_current_state = (int)yy_def[yy_current_state];
+ if (yy_current_state >= 67)
+ yy_c = yy_meta[(unsigned int)yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int)yy_c];
+ ++yy_cp;
+ } while (yy_base[yy_current_state] != 205);
+
+ yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if (yy_act == 0) { /* have to back up */
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+ do_action: /* This label is used only to access EOF actions. */
+
+ switch (yy_act) { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yy_hold_char;
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ goto yy_find_action;
+
+ case 1:
+ YY_RULE_SETUP
+#line 30 "crlgen_lex_orig.l"
+ {
+ parserStatus =
+ crlgen_setNextData(parserData, yytext, CRLGEN_TYPE_ZDATE);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ }
+ YY_BREAK
+ case 2:
+ YY_RULE_SETUP
+#line 36 "crlgen_lex_orig.l"
+ {
+ parserStatus =
+ crlgen_setNextData(parserData, yytext, CRLGEN_TYPE_DIGIT);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ }
+ YY_BREAK
+ case 3:
+ YY_RULE_SETUP
+#line 42 "crlgen_lex_orig.l"
+ {
+ parserStatus =
+ crlgen_setNextData(parserData, yytext, CRLGEN_TYPE_DIGIT_RANGE);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ }
+ YY_BREAK
+ case 4:
+ YY_RULE_SETUP
+#line 48 "crlgen_lex_orig.l"
+ {
+ parserStatus =
+ crlgen_setNextData(parserData, yytext, CRLGEN_TYPE_OID);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ }
+ YY_BREAK
+ case 5:
+ YY_RULE_SETUP
+#line 54 "crlgen_lex_orig.l"
+ {
+ parserStatus =
+ crlgen_createNewLangStruct(parserData, CRLGEN_ISSUER_CONTEXT);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ }
+ YY_BREAK
+ case 6:
+ YY_RULE_SETUP
+#line 60 "crlgen_lex_orig.l"
+ {
+ parserStatus =
+ crlgen_createNewLangStruct(parserData, CRLGEN_UPDATE_CONTEXT);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ }
+ YY_BREAK
+ case 7:
+ YY_RULE_SETUP
+#line 65 "crlgen_lex_orig.l"
+ {
+ parserStatus =
+ crlgen_createNewLangStruct(parserData, CRLGEN_NEXT_UPDATE_CONTEXT);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ }
+ YY_BREAK
+ case 8:
+ YY_RULE_SETUP
+#line 71 "crlgen_lex_orig.l"
+ {
+ parserStatus =
+ crlgen_createNewLangStruct(parserData, CRLGEN_CHANGE_RANGE_CONTEXT);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ }
+ YY_BREAK
+ case 9:
+ YY_RULE_SETUP
+#line 77 "crlgen_lex_orig.l"
+ {
+ if (strcmp(yytext, "addcert") ==
+ 0) {
+ parserStatus =
+ crlgen_createNewLangStruct(parserData,
+ CRLGEN_ADD_CERT_CONTEXT);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ } else if (strcmp(yytext, "rmcert") ==
+ 0) {
+ parserStatus =
+ crlgen_createNewLangStruct(parserData,
+ CRLGEN_RM_CERT_CONTEXT);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ } else if (strcmp(yytext, "addext") ==
+ 0) {
+ parserStatus =
+ crlgen_createNewLangStruct(parserData,
+ CRLGEN_ADD_EXTENSION_CONTEXT);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ } else {
+ parserStatus =
+ crlgen_setNextData(parserData, yytext, CRLGEN_TYPE_ID);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ }
+ }
+ YY_BREAK
+ case 10:
+ YY_RULE_SETUP
+#line 100 "crlgen_lex_orig.l"
+
+ YY_BREAK
+ case 11:
+ YY_RULE_SETUP
+#line 102 "crlgen_lex_orig.l"
+ {
+ if (yytext[yyleng -
+ 1] ==
+ '\\') {
+ yymore();
+ } else {
+ register int c;
+ c =
+ input();
+ if (c !=
+ '\"') {
+ printf("Error: Line ending \" is missing: %c\n", c);
+ unput(c);
+ } else {
+ parserStatus =
+ crlgen_setNextData(parserData, yytext + 1,
+ CRLGEN_TYPE_STRING);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ }
+ }
+ }
+ YY_BREAK
+ case 12:
+ YY_RULE_SETUP
+#line 120 "crlgen_lex_orig.l"
+ {
+ parserStatus =
+ crlgen_setNextData(parserData, yytext, CRLGEN_TYPE_STRING);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ }
+ YY_BREAK
+ case 13:
+ YY_RULE_SETUP
+#line 128 "crlgen_lex_orig.l"
+ /* eat up one-line comments */ {}
+ YY_BREAK
+ case 14:
+ YY_RULE_SETUP
+#line 130 "crlgen_lex_orig.l"
+ {
+ }
+ YY_BREAK
+ case 15:
+ YY_RULE_SETUP
+#line 132 "crlgen_lex_orig.l"
+ {
+ parserStatus =
+ crlgen_updateCrl(parserData);
+ if (parserStatus !=
+ SECSuccess)
+ return parserStatus;
+ }
+ YY_BREAK
+ case 16:
+ YY_RULE_SETUP
+#line 138 "crlgen_lex_orig.l"
+ {
+ fprintf(stderr, "Syntax error at line %d: unknown token %s\n",
+ parserData->parsedLineNum, yytext);
+ return SECFailure;
+ }
+ YY_BREAK
+ case 17:
+ YY_RULE_SETUP
+#line 144 "crlgen_lex_orig.l"
+ ECHO;
+ YY_BREAK
+ case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER: {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int)(yy_cp - yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if (yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW) {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between yy_current_buffer and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yy_current_buffer->yy_input_file = yyin;
+ yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if (yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars]) { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans(yy_current_state);
+
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+ if (yy_next_state) {
+ /* Consume the NUL. */
+ yy_cp = ++yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else {
+ yy_cp = yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else
+ switch (yy_get_next_buffer()) {
+ case EOB_ACT_END_OF_FILE: {
+ yy_did_buffer_switch_on_eof = 0;
+
+ if (yywrap()) {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else {
+ if (!yy_did_buffer_switch_on_eof)
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p =
+ yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yy_c_buf_p =
+ &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found");
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int
+yy_get_next_buffer()
+{
+ register char *dest = yy_current_buffer->yy_ch_buf;
+ register char *source = yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if (yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1])
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed");
+
+ if (yy_current_buffer->yy_fill_buffer == 0) { /* Don't try to fill the buffer, so this is an EOF. */
+ if (yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1) {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int)(yy_c_buf_p - yytext_ptr) - 1;
+
+ for (i = 0; i < number_to_move; ++i)
+ *(dest++) = *(source++);
+
+ if (yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING)
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+ else {
+ int num_to_read =
+ yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+ while (num_to_read <= 0) { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+ YY_FATAL_ERROR(
+ "input buffer overflow, can't enlarge buffer because scanner uses REJECT");
+#else
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = yy_current_buffer;
+
+ int yy_c_buf_p_offset =
+ (int)(yy_c_buf_p - b->yy_ch_buf);
+
+ if (b->yy_is_our_buffer) {
+ int new_size = b->yy_buf_size * 2;
+
+ if (new_size <= 0)
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yy_flex_realloc((void *)b->yy_ch_buf,
+ b->yy_buf_size + 2);
+ } else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if (!b->yy_ch_buf)
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow");
+
+ yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = yy_current_buffer->yy_buf_size -
+ number_to_move - 1;
+#endif
+ }
+
+ if (num_to_read > YY_READ_BUF_SIZE)
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT((&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read);
+
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ if (yy_n_chars == 0) {
+ if (number_to_move == YY_MORE_ADJ) {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart(yyin);
+ }
+
+ else {
+ ret_val = EOB_ACT_LAST_MATCH;
+ yy_current_buffer->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yy_n_chars += number_to_move;
+ yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type
+yy_get_previous_state()
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = yy_start;
+ yy_current_state += YY_AT_BOL();
+
+ for (yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp) {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if (yy_accept[yy_current_state]) {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
+ yy_current_state = (int)yy_def[yy_current_state];
+ if (yy_current_state >= 67)
+ yy_c = yy_meta[(unsigned int)yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int)yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type
+yy_try_NUL_trans(yy_state_type yy_current_state)
+#else
+static yy_state_type yy_try_NUL_trans(yy_current_state)
+ yy_state_type yy_current_state;
+#endif
+{
+ register int yy_is_jam;
+ register char *yy_cp = yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if (yy_accept[yy_current_state]) {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
+ yy_current_state = (int)yy_def[yy_current_state];
+ if (yy_current_state >= 67)
+ yy_c = yy_meta[(unsigned int)yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int)yy_c];
+ yy_is_jam = (yy_current_state == 66);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void
+yyunput(int c, register char *yy_bp)
+#else
+static void yyunput(c, yy_bp) int c;
+register char *yy_bp;
+#endif
+{
+ register char *yy_cp = yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yy_hold_char;
+
+ if (yy_cp < yy_current_buffer->yy_ch_buf + 2) { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yy_n_chars + 2;
+ register char *dest = &yy_current_buffer->yy_ch_buf[yy_current_buffer->yy_buf_size +
+ 2];
+ register char *source =
+ &yy_current_buffer->yy_ch_buf[number_to_move];
+
+ while (source > yy_current_buffer->yy_ch_buf)
+ *--dest = *--source;
+
+ yy_cp += (int)(dest - source);
+ yy_bp += (int)(dest - source);
+ yy_current_buffer->yy_n_chars =
+ yy_n_chars = yy_current_buffer->yy_buf_size;
+
+ if (yy_cp < yy_current_buffer->yy_ch_buf + 2)
+ YY_FATAL_ERROR("flex scanner push-back overflow");
+ }
+
+ *--yy_cp = (char)c;
+
+ yytext_ptr = yy_bp;
+ yy_hold_char = *yy_cp;
+ yy_c_buf_p = yy_cp;
+}
+#endif /* ifndef YY_NO_UNPUT */
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int
+yyinput()
+#else
+static int
+input()
+#endif
+{
+ int c;
+
+ *yy_c_buf_p = yy_hold_char;
+
+ if (*yy_c_buf_p == YY_END_OF_BUFFER_CHAR) {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if (yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars])
+ /* This was really a NUL. */
+ *yy_c_buf_p = '\0';
+
+ else { /* need more input */
+ int offset = yy_c_buf_p - yytext_ptr;
+ ++yy_c_buf_p;
+
+ switch (yy_get_next_buffer()) {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart(yyin);
+
+ /* fall through */
+
+ case EOB_ACT_END_OF_FILE: {
+ if (yywrap())
+ return EOF;
+
+ if (!yy_did_buffer_switch_on_eof)
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *)yy_c_buf_p; /* cast for 8-bit char's */
+ *yy_c_buf_p = '\0'; /* preserve yytext */
+ yy_hold_char = *++yy_c_buf_p;
+
+ yy_current_buffer->yy_at_bol = (c == '\n');
+
+ return c;
+}
+#endif /* YY_NO_INPUT */
+
+#ifdef YY_USE_PROTOS
+void
+yyrestart(FILE *input_file)
+#else
+void yyrestart(input_file)
+ FILE *input_file;
+#endif
+{
+ if (!yy_current_buffer)
+ yy_current_buffer = yy_create_buffer(yyin, YY_BUF_SIZE);
+
+ yy_init_buffer(yy_current_buffer, input_file);
+ yy_load_buffer_state();
+}
+
+#ifdef YY_USE_PROTOS
+void
+yy_switch_to_buffer(YY_BUFFER_STATE new_buffer)
+#else
+void yy_switch_to_buffer(new_buffer)
+ YY_BUFFER_STATE new_buffer;
+#endif
+{
+ if (yy_current_buffer == new_buffer)
+ return;
+
+ if (yy_current_buffer) {
+ /* Flush out information for old buffer. */
+ *yy_c_buf_p = yy_hold_char;
+ yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ yy_current_buffer = new_buffer;
+ yy_load_buffer_state();
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yy_did_buffer_switch_on_eof = 1;
+}
+
+#ifdef YY_USE_PROTOS
+void
+yy_load_buffer_state(void)
+#else
+void
+yy_load_buffer_state()
+#endif
+{
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+ yyin = yy_current_buffer->yy_input_file;
+ yy_hold_char = *yy_c_buf_p;
+}
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE
+yy_create_buffer(FILE *file, int size)
+#else
+YY_BUFFER_STATE yy_create_buffer(file, size)
+ FILE *file;
+int size;
+#endif
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE)yy_flex_alloc(sizeof(struct yy_buffer_state));
+ if (!b)
+ YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()");
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *)yy_flex_alloc(b->yy_buf_size + 2);
+ if (!b->yy_ch_buf)
+ YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()");
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer(b, file);
+
+ return b;
+}
+
+#ifdef YY_USE_PROTOS
+void
+yy_delete_buffer(YY_BUFFER_STATE b)
+#else
+void yy_delete_buffer(b)
+ YY_BUFFER_STATE b;
+#endif
+{
+ if (!b)
+ return;
+
+ if (b == yy_current_buffer)
+ yy_current_buffer = (YY_BUFFER_STATE)0;
+
+ if (b->yy_is_our_buffer)
+ yy_flex_free((void *)b->yy_ch_buf);
+
+ yy_flex_free((void *)b);
+}
+
+#ifdef YY_USE_PROTOS
+void
+yy_init_buffer(YY_BUFFER_STATE b, FILE *file)
+#else
+void yy_init_buffer(b, file)
+ YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+{
+ yy_flush_buffer(b);
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+ b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+ b->yy_is_interactive = 0;
+#else
+ b->yy_is_interactive = file ? (isatty(fileno(file)) > 0) : 0;
+#endif
+#endif
+}
+
+#ifdef YY_USE_PROTOS
+void
+yy_flush_buffer(YY_BUFFER_STATE b)
+#else
+void yy_flush_buffer(b)
+ YY_BUFFER_STATE b;
+#endif
+
+{
+ if (!b)
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if (b == yy_current_buffer)
+ yy_load_buffer_state();
+}
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE
+yy_scan_buffer(char *base, yy_size_t size)
+#else
+YY_BUFFER_STATE yy_scan_buffer(base, size) char *base;
+yy_size_t size;
+#endif
+{
+ YY_BUFFER_STATE b;
+
+ if (size < 2 ||
+ base[size - 2] != YY_END_OF_BUFFER_CHAR ||
+ base[size - 1] != YY_END_OF_BUFFER_CHAR)
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE)yy_flex_alloc(sizeof(struct yy_buffer_state));
+ if (!b)
+ YY_FATAL_ERROR("out of dynamic memory in yy_scan_buffer()");
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer(b);
+
+ return b;
+}
+#endif
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE
+yy_scan_string(yyconst char *yy_str)
+#else
+YY_BUFFER_STATE yy_scan_string(yy_str)
+ yyconst char *yy_str;
+#endif
+{
+ int len;
+ for (len = 0; yy_str[len]; ++len)
+ ;
+
+ return yy_scan_bytes(yy_str, len);
+}
+#endif
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE
+yy_scan_bytes(yyconst char *bytes, int len)
+#else
+YY_BUFFER_STATE yy_scan_bytes(bytes, len)
+ yyconst char *bytes;
+int len;
+#endif
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = len + 2;
+ buf = (char *)yy_flex_alloc(n);
+ if (!buf)
+ YY_FATAL_ERROR("out of dynamic memory in yy_scan_bytes()");
+
+ for (i = 0; i < len; ++i)
+ buf[i] = bytes[i];
+
+ buf[len] = buf[len + 1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer(buf, n);
+ if (!b)
+ YY_FATAL_ERROR("bad buffer in yy_scan_bytes()");
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+#endif
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void
+yy_push_state(int new_state)
+#else
+static void yy_push_state(new_state) int new_state;
+#endif
+{
+ if (yy_start_stack_ptr >= yy_start_stack_depth) {
+ yy_size_t new_size;
+
+ yy_start_stack_depth += YY_START_STACK_INCR;
+ new_size = yy_start_stack_depth * sizeof(int);
+
+ if (!yy_start_stack)
+ yy_start_stack = (int *)yy_flex_alloc(new_size);
+
+ else
+ yy_start_stack = (int *)yy_flex_realloc(
+ (void *)yy_start_stack, new_size);
+
+ if (!yy_start_stack)
+ YY_FATAL_ERROR(
+ "out of memory expanding start-condition stack");
+ }
+
+ yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+ BEGIN(new_state);
+}
+#endif
+
+#ifndef YY_NO_POP_STATE
+static void
+yy_pop_state()
+{
+ if (--yy_start_stack_ptr < 0)
+ YY_FATAL_ERROR("start-condition stack underflow");
+
+ BEGIN(yy_start_stack[yy_start_stack_ptr]);
+}
+#endif
+
+#ifndef YY_NO_TOP_STATE
+static int
+yy_top_state()
+{
+ return yy_start_stack[yy_start_stack_ptr - 1];
+}
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void
+yy_fatal_error(yyconst char msg[])
+#else
+static void yy_fatal_error(msg) char msg[];
+#endif
+{
+ (void)fprintf(stderr, "%s\n", msg);
+ exit(YY_EXIT_FAILURE);
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do { \
+ /* Undo effects of setting up yytext. */ \
+ yytext[yyleng] = yy_hold_char; \
+ yy_c_buf_p = yytext + n; \
+ yy_hold_char = *yy_c_buf_p; \
+ *yy_c_buf_p = '\0'; \
+ yyleng = n; \
+ } while (0)
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void
+yy_flex_strncpy(char *s1, yyconst char *s2, int n)
+#else
+static void yy_flex_strncpy(s1, s2, n) char *s1;
+yyconst char *s2;
+int n;
+#endif
+{
+ register int i;
+ for (i = 0; i < n; ++i)
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int
+yy_flex_strlen(yyconst char *s)
+#else
+static int yy_flex_strlen(s)
+ yyconst char *s;
+#endif
+{
+ register int n;
+ for (n = 0; s[n]; ++n)
+ ;
+
+ return n;
+}
+#endif
+
+#ifdef YY_USE_PROTOS
+static void *
+yy_flex_alloc(yy_size_t size)
+#else
+static void *yy_flex_alloc(size)
+ yy_size_t size;
+#endif
+{
+ return (void *)malloc(size);
+}
+
+#ifdef YY_USE_PROTOS
+static void *
+yy_flex_realloc(void *ptr, yy_size_t size)
+#else
+static void *yy_flex_realloc(ptr, size) void *ptr;
+yy_size_t size;
+#endif
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *)realloc((char *)ptr, size);
+}
+
+#ifdef YY_USE_PROTOS
+static void
+yy_flex_free(void *ptr)
+#else
+static void yy_flex_free(ptr) void *ptr;
+#endif
+{
+ free(ptr);
+}
+
+#if YY_MAIN
+int
+main()
+{
+ yylex();
+ return 0;
+}
+#endif
+#line 144 "crlgen_lex_orig.l"
+
+#include "prlock.h"
+
+static PRLock *parserInvocationLock;
+
+void
+CRLGEN_InitCrlGenParserLock()
+{
+ parserInvocationLock = PR_NewLock();
+}
+
+void
+CRLGEN_DestroyCrlGenParserLock()
+{
+ PR_DestroyLock(parserInvocationLock);
+}
+
+SECStatus
+CRLGEN_StartCrlGen(CRLGENGeneratorData *parserCtlData)
+{
+ SECStatus rv;
+
+ PR_Lock(parserInvocationLock);
+
+ parserStatus = SECSuccess;
+ parserData = parserCtlData;
+ src = parserCtlData->src;
+
+ rv = yylex();
+
+ PR_Unlock(parserInvocationLock);
+
+ return rv;
+}
+
+int
+yywrap()
+{
+ return 1;
+}
diff --git a/security/nss/cmd/crlutil/crlgen_lex_fix.sed b/security/nss/cmd/crlutil/crlgen_lex_fix.sed
new file mode 100644
index 000000000..603dd2d1b
--- /dev/null
+++ b/security/nss/cmd/crlutil/crlgen_lex_fix.sed
@@ -0,0 +1,6 @@
+/<unistd.h>/ {
+ i #ifdef _WIN32
+ i #include <io.h>
+ i #else
+ a #endif
+}
diff --git a/security/nss/cmd/crlutil/crlgen_lex_orig.l b/security/nss/cmd/crlutil/crlgen_lex_orig.l
new file mode 100644
index 000000000..a412e9892
--- /dev/null
+++ b/security/nss/cmd/crlutil/crlgen_lex_orig.l
@@ -0,0 +1,181 @@
+/* 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/. */
+
+%{
+
+#include "crlgen.h"
+
+static SECStatus parserStatus = SECSuccess;
+static CRLGENGeneratorData *parserData;
+static PRFileDesc *src;
+
+#define YY_INPUT(buf,result,max_size) \
+ if ( parserStatus != SECFailure) { \
+ if (((result = PR_Read(src, buf, max_size)) == 0) && \
+ ferror( yyin )) \
+ return SECFailure; \
+ } else { return SECFailure; }
+
+
+%}
+
+%a 5000
+DIGIT [0-9]+
+DIGIT_RANGE [0-9]+-[0-9]+
+ID [a-zA-Z][a-zA-Z0-9]*
+OID [0-9]+\.[\.0-9]+
+DATE [0-9]{4}[01][0-9][0-3][0-9][0-2][0-9][0-6][0-9][0-6][0-9]
+ZDATE [0-9]{4}[01][0-9][0-3][0-9][0-2][0-9][0-6][0-9][0-6][0-9]Z
+N_SP_STRING [a-zA-Z0-9\:\|\.]+
+
+%%
+
+{ZDATE} {
+parserStatus = crlgen_setNextData(parserData, yytext, CRLGEN_TYPE_ZDATE);
+if (parserStatus != SECSuccess)
+ return parserStatus;
+}
+
+{DIGIT} {
+parserStatus = crlgen_setNextData(parserData, yytext, CRLGEN_TYPE_DIGIT);
+if (parserStatus != SECSuccess)
+ return parserStatus;
+}
+
+{DIGIT_RANGE} {
+parserStatus = crlgen_setNextData(parserData, yytext, CRLGEN_TYPE_DIGIT_RANGE);
+if (parserStatus != SECSuccess)
+ return parserStatus;
+}
+
+{OID} {
+parserStatus = crlgen_setNextData(parserData, yytext, CRLGEN_TYPE_OID);
+if (parserStatus != SECSuccess)
+ return parserStatus;
+}
+
+issuer {
+parserStatus = crlgen_createNewLangStruct(parserData, CRLGEN_ISSUER_CONTEXT);
+if (parserStatus != SECSuccess)
+ return parserStatus;
+}
+
+update {
+parserStatus = crlgen_createNewLangStruct(parserData, CRLGEN_UPDATE_CONTEXT);
+if (parserStatus != SECSuccess)
+ return parserStatus;
+}
+nextupdate {
+parserStatus = crlgen_createNewLangStruct(parserData, CRLGEN_NEXT_UPDATE_CONTEXT);
+if (parserStatus != SECSuccess)
+ return parserStatus;
+}
+
+range {
+parserStatus = crlgen_createNewLangStruct(parserData, CRLGEN_CHANGE_RANGE_CONTEXT);
+if (parserStatus != SECSuccess)
+ return parserStatus;
+}
+
+{ID} {
+if (strcmp(yytext, "addcert") == 0) {
+ parserStatus = crlgen_createNewLangStruct(parserData,
+ CRLGEN_ADD_CERT_CONTEXT);
+ if (parserStatus != SECSuccess)
+ return parserStatus;
+} else if (strcmp(yytext, "rmcert") == 0) {
+ parserStatus = crlgen_createNewLangStruct(parserData,
+ CRLGEN_RM_CERT_CONTEXT);
+ if (parserStatus != SECSuccess)
+ return parserStatus;
+} else if (strcmp(yytext, "addext") == 0) {
+ parserStatus = crlgen_createNewLangStruct(parserData,
+ CRLGEN_ADD_EXTENSION_CONTEXT);
+ if (parserStatus != SECSuccess)
+ return parserStatus;
+} else {
+ parserStatus = crlgen_setNextData(parserData, yytext, CRLGEN_TYPE_ID);
+ if (parserStatus != SECSuccess)
+ return parserStatus;
+}
+}
+
+"="
+
+\"[^\"]* {
+if (yytext[yyleng-1] == '\\') {
+ yymore();
+} else {
+ register int c;
+ c = input();
+ if (c != '\"') {
+ printf( "Error: Line ending \" is missing: %c\n", c);
+ unput(c);
+ } else {
+ parserStatus = crlgen_setNextData(parserData, yytext + 1,
+ CRLGEN_TYPE_STRING);
+ if (parserStatus != SECSuccess)
+ return parserStatus;
+ }
+}
+}
+
+{N_SP_STRING} {
+parserStatus = crlgen_setNextData(parserData, yytext, CRLGEN_TYPE_STRING);
+if (parserStatus != SECSuccess)
+ return parserStatus;
+}
+
+
+
+^#[^\n]* /* eat up one-line comments */ {}
+
+[ \t]+ {}
+
+(\n|\r\n) {
+parserStatus = crlgen_updateCrl(parserData);
+if (parserStatus != SECSuccess)
+ return parserStatus;
+}
+
+. {
+ fprintf(stderr, "Syntax error at line %d: unknown token %s\n",
+ parserData->parsedLineNum, yytext);
+ return SECFailure;
+}
+
+%%
+#include "prlock.h"
+
+static PRLock *parserInvocationLock;
+
+void CRLGEN_InitCrlGenParserLock()
+{
+ parserInvocationLock = PR_NewLock();
+}
+
+void CRLGEN_DestroyCrlGenParserLock()
+{
+ PR_DestroyLock(parserInvocationLock);
+}
+
+
+SECStatus CRLGEN_StartCrlGen(CRLGENGeneratorData *parserCtlData)
+{
+ SECStatus rv;
+
+ PR_Lock(parserInvocationLock);
+
+ parserStatus = SECSuccess;
+ parserData = parserCtlData;
+ src = parserCtlData->src;
+
+ rv = yylex();
+
+ PR_Unlock(parserInvocationLock);
+
+ return rv;
+}
+
+int yywrap() {return 1;}
diff --git a/security/nss/cmd/crlutil/crlutil.c b/security/nss/cmd/crlutil/crlutil.c
new file mode 100644
index 000000000..bdf112b4a
--- /dev/null
+++ b/security/nss/cmd/crlutil/crlutil.c
@@ -0,0 +1,1153 @@
+/* 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/. */
+
+/*
+** certutil.c
+**
+** utility for managing certificates and the cert database
+**
+*/
+/* test only */
+
+#include "nspr.h"
+#include "plgetopt.h"
+#include "secutil.h"
+#include "cert.h"
+#include "certi.h"
+#include "certdb.h"
+#include "nss.h"
+#include "pk11func.h"
+#include "crlgen.h"
+
+#define SEC_CERT_DB_EXISTS 0
+#define SEC_CREATE_CERT_DB 1
+
+static char *progName;
+
+static CERTSignedCrl *
+FindCRL(CERTCertDBHandle *certHandle, char *name, int type)
+{
+ CERTSignedCrl *crl = NULL;
+ CERTCertificate *cert = NULL;
+ SECItem derName;
+
+ derName.data = NULL;
+ derName.len = 0;
+
+ cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, name);
+ if (!cert) {
+ CERTName *certName = NULL;
+ PLArenaPool *arena = NULL;
+ SECStatus rv = SECSuccess;
+
+ certName = CERT_AsciiToName(name);
+ if (certName) {
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena) {
+ SECItem *nameItem =
+ SEC_ASN1EncodeItem(arena, NULL, (void *)certName,
+ SEC_ASN1_GET(CERT_NameTemplate));
+ if (nameItem) {
+ rv = SECITEM_CopyItem(NULL, &derName, nameItem);
+ }
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ CERT_DestroyName(certName);
+ }
+
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "SECITEM_CopyItem failed, out of memory");
+ return ((CERTSignedCrl *)NULL);
+ }
+
+ if (!derName.len || !derName.data) {
+ SECU_PrintError(progName, "could not find certificate named '%s'", name);
+ return ((CERTSignedCrl *)NULL);
+ }
+ } else {
+ SECITEM_CopyItem(NULL, &derName, &cert->derSubject);
+ CERT_DestroyCertificate(cert);
+ }
+
+ crl = SEC_FindCrlByName(certHandle, &derName, type);
+ if (crl == NULL)
+ SECU_PrintError(progName, "could not find %s's CRL", name);
+ if (derName.data) {
+ SECITEM_FreeItem(&derName, PR_FALSE);
+ }
+ return (crl);
+}
+
+static SECStatus
+DisplayCRL(CERTCertDBHandle *certHandle, char *nickName, int crlType)
+{
+ CERTSignedCrl *crl = NULL;
+
+ crl = FindCRL(certHandle, nickName, crlType);
+
+ if (crl) {
+ SECU_PrintCRLInfo(stdout, &crl->crl, "CRL Info:\n", 0);
+ SEC_DestroyCrl(crl);
+ return SECSuccess;
+ }
+ return SECFailure;
+}
+
+static void
+ListCRLNames(CERTCertDBHandle *certHandle, int crlType, PRBool deletecrls)
+{
+ CERTCrlHeadNode *crlList = NULL;
+ CERTCrlNode *crlNode = NULL;
+ CERTName *name = NULL;
+ PLArenaPool *arena = NULL;
+ SECStatus rv;
+
+ do {
+ arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if (arena == NULL) {
+ fprintf(stderr, "%s: fail to allocate memory\n", progName);
+ break;
+ }
+
+ name = PORT_ArenaZAlloc(arena, sizeof(*name));
+ if (name == NULL) {
+ fprintf(stderr, "%s: fail to allocate memory\n", progName);
+ break;
+ }
+ name->arena = arena;
+
+ rv = SEC_LookupCrls(certHandle, &crlList, crlType);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: fail to look up CRLs (%s)\n", progName,
+ SECU_Strerror(PORT_GetError()));
+ break;
+ }
+
+ /* just in case */
+ if (!crlList)
+ break;
+
+ crlNode = crlList->first;
+
+ fprintf(stdout, "\n");
+ fprintf(stdout, "\n%-40s %-5s\n\n", "CRL names", "CRL Type");
+ while (crlNode) {
+ char *asciiname = NULL;
+ CERTCertificate *cert = NULL;
+ if (crlNode->crl && crlNode->crl->crl.derName.data != NULL) {
+ cert = CERT_FindCertByName(certHandle,
+ &crlNode->crl->crl.derName);
+ if (!cert) {
+ SECU_PrintError(progName, "could not find signing "
+ "certificate in database");
+ }
+ }
+ if (cert) {
+ char *certName = NULL;
+ if (cert->nickname && PORT_Strlen(cert->nickname) > 0) {
+ certName = cert->nickname;
+ } else if (cert->emailAddr && PORT_Strlen(cert->emailAddr) > 0) {
+ certName = cert->emailAddr;
+ }
+ if (certName) {
+ asciiname = PORT_Strdup(certName);
+ }
+ CERT_DestroyCertificate(cert);
+ }
+
+ if (!asciiname) {
+ name = &crlNode->crl->crl.name;
+ if (!name) {
+ SECU_PrintError(progName, "fail to get the CRL "
+ "issuer name");
+ continue;
+ }
+ asciiname = CERT_NameToAscii(name);
+ }
+ fprintf(stdout, "%-40s %-5s\n", asciiname, "CRL");
+ if (asciiname) {
+ PORT_Free(asciiname);
+ }
+ if (PR_TRUE == deletecrls) {
+ CERTSignedCrl *acrl = NULL;
+ SECItem *issuer = &crlNode->crl->crl.derName;
+ acrl = SEC_FindCrlByName(certHandle, issuer, crlType);
+ if (acrl) {
+ SEC_DeletePermCRL(acrl);
+ SEC_DestroyCrl(acrl);
+ }
+ }
+ crlNode = crlNode->next;
+ }
+
+ } while (0);
+ if (crlList)
+ PORT_FreeArena(crlList->arena, PR_FALSE);
+ PORT_FreeArena(arena, PR_FALSE);
+}
+
+static SECStatus
+ListCRL(CERTCertDBHandle *certHandle, char *nickName, int crlType)
+{
+ if (nickName == NULL) {
+ ListCRLNames(certHandle, crlType, PR_FALSE);
+ return SECSuccess;
+ }
+
+ return DisplayCRL(certHandle, nickName, crlType);
+}
+
+static SECStatus
+DeleteCRL(CERTCertDBHandle *certHandle, char *name, int type)
+{
+ CERTSignedCrl *crl = NULL;
+ SECStatus rv = SECFailure;
+
+ crl = FindCRL(certHandle, name, type);
+ if (!crl) {
+ SECU_PrintError(progName, "could not find the issuer %s's CRL", name);
+ return SECFailure;
+ }
+ rv = SEC_DeletePermCRL(crl);
+ SEC_DestroyCrl(crl);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "fail to delete the issuer %s's CRL "
+ "from the perm database (reason: %s)",
+ name, SECU_Strerror(PORT_GetError()));
+ return SECFailure;
+ }
+ return (rv);
+}
+
+SECStatus
+ImportCRL(CERTCertDBHandle *certHandle, char *url, int type,
+ PRFileDesc *inFile, PRInt32 importOptions, PRInt32 decodeOptions,
+ secuPWData *pwdata)
+{
+ CERTSignedCrl *crl = NULL;
+ SECItem crlDER;
+ PK11SlotInfo *slot = NULL;
+ int rv;
+#if defined(DEBUG_jp96085)
+ PRIntervalTime starttime, endtime, elapsed;
+ PRUint32 mins, secs, msecs;
+#endif
+
+ crlDER.data = NULL;
+
+ /* Read in the entire file specified with the -f argument */
+ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to read input file");
+ return (SECFailure);
+ }
+
+ decodeOptions |= CRL_DECODE_DONT_COPY_DER;
+
+ slot = PK11_GetInternalKeySlot();
+
+ if (PK11_NeedLogin(slot)) {
+ rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
+ if (rv != SECSuccess)
+ goto loser;
+ }
+
+#if defined(DEBUG_jp96085)
+ starttime = PR_IntervalNow();
+#endif
+ crl = PK11_ImportCRL(slot, &crlDER, url, type,
+ NULL, importOptions, NULL, decodeOptions);
+#if defined(DEBUG_jp96085)
+ endtime = PR_IntervalNow();
+ elapsed = endtime - starttime;
+ mins = PR_IntervalToSeconds(elapsed) / 60;
+ secs = PR_IntervalToSeconds(elapsed) % 60;
+ msecs = PR_IntervalToMilliseconds(elapsed) % 1000;
+ printf("Elapsed : %2d:%2d.%3d\n", mins, secs, msecs);
+#endif
+ if (!crl) {
+ const char *errString;
+
+ rv = SECFailure;
+ errString = SECU_Strerror(PORT_GetError());
+ if (errString && PORT_Strlen(errString) == 0)
+ SECU_PrintError(progName,
+ "CRL is not imported (error: input CRL is not up to date.)");
+ else
+ SECU_PrintError(progName, "unable to import CRL");
+ } else {
+ SEC_DestroyCrl(crl);
+ }
+loser:
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+ SECITEM_FreeItem(&crlDER, PR_FALSE);
+ return (rv);
+}
+
+SECStatus
+DumpCRL(PRFileDesc *inFile)
+{
+ int rv;
+ PLArenaPool *arena = NULL;
+ CERTSignedCrl *newCrl = NULL;
+
+ SECItem crlDER;
+ crlDER.data = NULL;
+
+ /* Read in the entire file specified with the -f argument */
+ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to read input file");
+ return (SECFailure);
+ }
+
+ rv = SEC_ERROR_NO_MEMORY;
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena)
+ return rv;
+
+ newCrl = CERT_DecodeDERCrlWithFlags(arena, &crlDER, SEC_CRL_TYPE,
+ CRL_DECODE_DEFAULT_OPTIONS);
+ if (!newCrl)
+ return SECFailure;
+
+ SECU_PrintCRLInfo(stdout, &newCrl->crl, "CRL file contents", 0);
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+static CERTCertificate *
+FindSigningCert(CERTCertDBHandle *certHandle, CERTSignedCrl *signCrl,
+ char *certNickName)
+{
+ CERTCertificate *cert = NULL, *certTemp = NULL;
+ SECStatus rv = SECFailure;
+ CERTAuthKeyID *authorityKeyID = NULL;
+ SECItem *subject = NULL;
+
+ PORT_Assert(certHandle != NULL);
+ if (!certHandle || (!signCrl && !certNickName)) {
+ SECU_PrintError(progName, "invalid args for function "
+ "FindSigningCert \n");
+ return NULL;
+ }
+
+ if (signCrl) {
+#if 0
+ authorityKeyID = SECU_FindCRLAuthKeyIDExten(tmpArena, scrl);
+#endif
+ subject = &signCrl->crl.derName;
+ } else {
+ certTemp = CERT_FindCertByNickname(certHandle, certNickName);
+ if (!certTemp) {
+ SECU_PrintError(progName, "could not find certificate \"%s\" "
+ "in database",
+ certNickName);
+ goto loser;
+ }
+ subject = &certTemp->derSubject;
+ }
+
+ cert = SECU_FindCrlIssuer(certHandle, subject, authorityKeyID, PR_Now());
+ if (!cert) {
+ SECU_PrintError(progName, "could not find signing certificate "
+ "in database");
+ goto loser;
+ } else {
+ rv = SECSuccess;
+ }
+
+loser:
+ if (certTemp)
+ CERT_DestroyCertificate(certTemp);
+ if (cert && rv != SECSuccess)
+ CERT_DestroyCertificate(cert);
+ return cert;
+}
+
+static CERTSignedCrl *
+CreateModifiedCRLCopy(PLArenaPool *arena, CERTCertDBHandle *certHandle,
+ CERTCertificate **cert, char *certNickName,
+ PRFileDesc *inFile, PRInt32 decodeOptions,
+ PRInt32 importOptions, secuPWData *pwdata)
+{
+ SECItem crlDER = { 0, NULL, 0 };
+ CERTSignedCrl *signCrl = NULL;
+ CERTSignedCrl *modCrl = NULL;
+ PLArenaPool *modArena = NULL;
+ SECStatus rv = SECSuccess;
+
+ if (!arena || !certHandle || !certNickName) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ SECU_PrintError(progName, "CreateModifiedCRLCopy: invalid args\n");
+ return NULL;
+ }
+
+ modArena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if (!modArena) {
+ SECU_PrintError(progName, "fail to allocate memory\n");
+ return NULL;
+ }
+
+ if (inFile != NULL) {
+ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to read input file");
+ PORT_FreeArena(modArena, PR_FALSE);
+ goto loser;
+ }
+
+ decodeOptions |= CRL_DECODE_DONT_COPY_DER;
+
+ modCrl = CERT_DecodeDERCrlWithFlags(modArena, &crlDER, SEC_CRL_TYPE,
+ decodeOptions);
+ if (!modCrl) {
+ SECU_PrintError(progName, "fail to decode CRL");
+ goto loser;
+ }
+
+ if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS)) {
+ /* If caCert is a v2 certificate, make sure that it
+ * can be used for crl signing purpose */
+ *cert = FindSigningCert(certHandle, modCrl, NULL);
+ if (!*cert) {
+ goto loser;
+ }
+
+ rv = CERT_VerifySignedData(&modCrl->signatureWrap, *cert,
+ PR_Now(), pwdata);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "fail to verify signed data\n");
+ goto loser;
+ }
+ }
+ } else {
+ modCrl = FindCRL(certHandle, certNickName, SEC_CRL_TYPE);
+ if (!modCrl) {
+ SECU_PrintError(progName, "fail to find crl %s in database\n",
+ certNickName);
+ goto loser;
+ }
+ }
+
+ signCrl = PORT_ArenaZNew(arena, CERTSignedCrl);
+ if (signCrl == NULL) {
+ SECU_PrintError(progName, "fail to allocate memory\n");
+ goto loser;
+ }
+
+ rv = SECU_CopyCRL(arena, &signCrl->crl, &modCrl->crl);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to dublicate crl for "
+ "modification.");
+ goto loser;
+ }
+
+ /* Make sure the update time is current. It can be modified later
+ * by "update <time>" command from crl generation script */
+ rv = DER_EncodeTimeChoice(arena, &signCrl->crl.lastUpdate, PR_Now());
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "fail to encode current time\n");
+ goto loser;
+ }
+
+ signCrl->arena = arena;
+ signCrl->referenceCount = 1;
+
+loser:
+ if (crlDER.data) {
+ SECITEM_FreeItem(&crlDER, PR_FALSE);
+ }
+ if (modArena && (!modCrl || modCrl->arena != modArena)) {
+ PORT_FreeArena(modArena, PR_FALSE);
+ }
+ if (modCrl)
+ SEC_DestroyCrl(modCrl);
+ if (rv != SECSuccess && signCrl) {
+ SEC_DestroyCrl(signCrl);
+ signCrl = NULL;
+ }
+ return signCrl;
+}
+
+static CERTSignedCrl *
+CreateNewCrl(PLArenaPool *arena, CERTCertDBHandle *certHandle,
+ CERTCertificate *cert)
+{
+ CERTSignedCrl *signCrl = NULL;
+ void *dummy = NULL;
+ SECStatus rv;
+ void *mark = NULL;
+
+ /* if the CERTSignedCrl structure changes, this function will need to be
+ updated as well */
+ if (!cert || !arena) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ SECU_PrintError(progName, "invalid args for function "
+ "CreateNewCrl\n");
+ return NULL;
+ }
+
+ mark = PORT_ArenaMark(arena);
+
+ signCrl = PORT_ArenaZNew(arena, CERTSignedCrl);
+ if (signCrl == NULL) {
+ SECU_PrintError(progName, "fail to allocate memory\n");
+ return NULL;
+ }
+
+ dummy = SEC_ASN1EncodeInteger(arena, &signCrl->crl.version,
+ SEC_CRL_VERSION_2);
+ /* set crl->version */
+ if (!dummy) {
+ SECU_PrintError(progName, "fail to create crl version data "
+ "container\n");
+ goto loser;
+ }
+
+ /* copy SECItem name from cert */
+ rv = SECITEM_CopyItem(arena, &signCrl->crl.derName, &cert->derSubject);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "fail to duplicate der name from "
+ "certificate.\n");
+ goto loser;
+ }
+
+ /* copy CERTName name structure from cert issuer */
+ rv = CERT_CopyName(arena, &signCrl->crl.name, &cert->subject);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "fail to duplicate RD name from "
+ "certificate.\n");
+ goto loser;
+ }
+
+ rv = DER_EncodeTimeChoice(arena, &signCrl->crl.lastUpdate, PR_Now());
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "fail to encode current time\n");
+ goto loser;
+ }
+
+ /* set fields */
+ signCrl->arena = arena;
+ signCrl->dbhandle = certHandle;
+ signCrl->crl.arena = arena;
+
+ PORT_ArenaUnmark(arena, mark);
+
+ return signCrl;
+
+loser:
+ PORT_ArenaRelease(arena, mark);
+ return NULL;
+}
+
+static SECStatus
+UpdateCrl(CERTSignedCrl *signCrl, PRFileDesc *inCrlInitFile)
+{
+ CRLGENGeneratorData *crlGenData = NULL;
+ SECStatus rv;
+
+ if (!signCrl || !inCrlInitFile) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ SECU_PrintError(progName, "invalid args for function "
+ "CreateNewCrl\n");
+ return SECFailure;
+ }
+
+ crlGenData = CRLGEN_InitCrlGeneration(signCrl, inCrlInitFile);
+ if (!crlGenData) {
+ SECU_PrintError(progName, "can not initialize parser structure.\n");
+ return SECFailure;
+ }
+
+ rv = CRLGEN_ExtHandleInit(crlGenData);
+ if (rv == SECFailure) {
+ SECU_PrintError(progName, "can not initialize entries handle.\n");
+ goto loser;
+ }
+
+ rv = CRLGEN_StartCrlGen(crlGenData);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "crl generation failed");
+ goto loser;
+ }
+
+loser:
+ /* CommitExtensionsAndEntries is partially responsible for freeing
+ * up memory that was used for CRL generation. Should be called regardless
+ * of previouse call status, but only after initialization of
+ * crlGenData was done. It will commit all changes that was done before
+ * an error has occurred.
+ */
+ if (SECSuccess != CRLGEN_CommitExtensionsAndEntries(crlGenData)) {
+ SECU_PrintError(progName, "crl generation failed");
+ rv = SECFailure;
+ }
+ CRLGEN_FinalizeCrlGeneration(crlGenData);
+ return rv;
+}
+
+static SECStatus
+SignAndStoreCrl(CERTSignedCrl *signCrl, CERTCertificate *cert,
+ char *outFileName, SECOidTag hashAlgTag, int ascii,
+ char *slotName, char *url, secuPWData *pwdata)
+{
+ PK11SlotInfo *slot = NULL;
+ PRFileDesc *outFile = NULL;
+ SECStatus rv;
+ SignAndEncodeFuncExitStat errCode;
+
+ PORT_Assert(signCrl && (!ascii || outFileName));
+ if (!signCrl || (ascii && !outFileName)) {
+ SECU_PrintError(progName, "invalid args for function "
+ "SignAndStoreCrl\n");
+ return SECFailure;
+ }
+
+ if (!slotName || !PL_strcmp(slotName, "internal"))
+ slot = PK11_GetInternalKeySlot();
+ else
+ slot = PK11_FindSlotByName(slotName);
+ if (!slot) {
+ SECU_PrintError(progName, "can not find requested slot");
+ return SECFailure;
+ }
+
+ if (PK11_NeedLogin(slot)) {
+ rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
+ if (rv != SECSuccess)
+ goto loser;
+ }
+
+ rv = SECU_SignAndEncodeCRL(cert, signCrl, hashAlgTag, &errCode);
+ if (rv != SECSuccess) {
+ char *errMsg = NULL;
+ switch (errCode) {
+ case noKeyFound:
+ errMsg = "No private key found of signing cert";
+ break;
+
+ case noSignatureMatch:
+ errMsg = "Key and Algorithm OId are do not match";
+ break;
+
+ default:
+ case failToEncode:
+ errMsg = "Failed to encode crl structure";
+ break;
+
+ case failToSign:
+ errMsg = "Failed to sign crl structure";
+ break;
+
+ case noMem:
+ errMsg = "Can not allocate memory";
+ break;
+ }
+ SECU_PrintError(progName, "%s\n", errMsg);
+ goto loser;
+ }
+
+ if (outFileName) {
+ outFile = PR_Open(outFileName, PR_WRONLY | PR_CREATE_FILE, PR_IRUSR | PR_IWUSR);
+ if (!outFile) {
+ SECU_PrintError(progName, "unable to open \"%s\" for writing\n",
+ outFileName);
+ goto loser;
+ }
+ }
+
+ rv = SECU_StoreCRL(slot, signCrl->derCrl, outFile, ascii, url);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "fail to save CRL\n");
+ }
+
+loser:
+ if (outFile)
+ PR_Close(outFile);
+ if (slot)
+ PK11_FreeSlot(slot);
+ return rv;
+}
+
+static SECStatus
+GenerateCRL(CERTCertDBHandle *certHandle, char *certNickName,
+ PRFileDesc *inCrlInitFile, PRFileDesc *inFile,
+ char *outFileName, int ascii, char *slotName,
+ PRInt32 importOptions, char *alg, PRBool quiet,
+ PRInt32 decodeOptions, char *url, secuPWData *pwdata,
+ int modifyFlag)
+{
+ CERTCertificate *cert = NULL;
+ CERTSignedCrl *signCrl = NULL;
+ PLArenaPool *arena = NULL;
+ SECStatus rv;
+ SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
+
+ if (alg) {
+ hashAlgTag = SECU_StringToSignatureAlgTag(alg);
+ if (hashAlgTag == SEC_OID_UNKNOWN) {
+ SECU_PrintError(progName, "%s -Z: %s is not a recognized type.\n",
+ progName, alg);
+ return SECFailure;
+ }
+ } else {
+ hashAlgTag = SEC_OID_UNKNOWN;
+ }
+
+ arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if (!arena) {
+ SECU_PrintError(progName, "fail to allocate memory\n");
+ return SECFailure;
+ }
+
+ if (modifyFlag == PR_TRUE) {
+ signCrl = CreateModifiedCRLCopy(arena, certHandle, &cert, certNickName,
+ inFile, decodeOptions, importOptions,
+ pwdata);
+ if (signCrl == NULL) {
+ rv = SECFailure;
+ goto loser;
+ }
+ }
+
+ if (!cert) {
+ cert = FindSigningCert(certHandle, signCrl, certNickName);
+ if (cert == NULL) {
+ rv = SECFailure;
+ goto loser;
+ }
+ }
+
+ if (!signCrl) {
+ if (modifyFlag == PR_TRUE) {
+ if (!outFileName) {
+ int len = strlen(certNickName) + 5;
+ outFileName = PORT_ArenaAlloc(arena, len);
+ PR_snprintf(outFileName, len, "%s.crl", certNickName);
+ }
+ SECU_PrintError(progName, "Will try to generate crl. "
+ "It will be saved in file: %s",
+ outFileName);
+ }
+ signCrl = CreateNewCrl(arena, certHandle, cert);
+ if (!signCrl) {
+ rv = SECFailure;
+ goto loser;
+ }
+ }
+
+ rv = UpdateCrl(signCrl, inCrlInitFile);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ rv = SignAndStoreCrl(signCrl, cert, outFileName, hashAlgTag, ascii,
+ slotName, url, pwdata);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ if (signCrl && !quiet) {
+ SECU_PrintCRLInfo(stdout, &signCrl->crl, "CRL Info:\n", 0);
+ }
+
+loser:
+ if (arena && (!signCrl || !signCrl->arena))
+ PORT_FreeArena(arena, PR_FALSE);
+ if (signCrl)
+ SEC_DestroyCrl(signCrl);
+ if (cert)
+ CERT_DestroyCertificate(cert);
+ return (rv);
+}
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s -L [-n nickname] [-d keydir] [-P dbprefix] [-t crlType]\n"
+ " %s -D -n nickname [-d keydir] [-P dbprefix]\n"
+ " %s -S -i crl\n"
+ " %s -I -i crl -t crlType [-u url] [-d keydir] [-P dbprefix] [-B] "
+ "[-p pwd-file] -w [pwd-string]\n"
+ " %s -E -t crlType [-d keydir] [-P dbprefix]\n"
+ " %s -T\n"
+ " %s -G|-M -c crl-init-file -n nickname [-i crl] [-u url] "
+ "[-d keydir] [-P dbprefix] [-Z alg] ] [-p pwd-file] -w [pwd-string] "
+ "[-a] [-B]\n",
+ progName, progName, progName, progName, progName, progName, progName);
+
+ fprintf(stderr, "%-15s List CRL\n", "-L");
+ fprintf(stderr, "%-20s Specify the nickname of the CA certificate\n",
+ "-n nickname");
+ fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
+ "-d keydir");
+ fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
+ "-P dbprefix");
+
+ fprintf(stderr, "%-15s Delete a CRL from the cert database\n", "-D");
+ fprintf(stderr, "%-20s Specify the nickname for the CA certificate\n",
+ "-n nickname");
+ fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType");
+ fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
+ "-d keydir");
+ fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
+ "-P dbprefix");
+
+ fprintf(stderr, "%-15s Erase all CRLs of specified type from hte cert database\n", "-E");
+ fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType");
+ fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
+ "-d keydir");
+ fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
+ "-P dbprefix");
+
+ fprintf(stderr, "%-15s Show contents of a CRL file (without database)\n", "-S");
+ fprintf(stderr, "%-20s Specify the file which contains the CRL to show\n",
+ "-i crl");
+
+ fprintf(stderr, "%-15s Import a CRL to the cert database\n", "-I");
+ fprintf(stderr, "%-20s Specify the file which contains the CRL to import\n",
+ "-i crl");
+ fprintf(stderr, "%-20s Specify the url.\n", "-u url");
+ fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType");
+ fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
+ "-d keydir");
+ fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
+ "-P dbprefix");
+#ifdef DEBUG
+ fprintf(stderr, "%-15s Test . Only for debugging purposes. See source code\n", "-T");
+#endif
+ fprintf(stderr, "%-20s CRL Types (default is SEC_CRL_TYPE):\n", " ");
+ fprintf(stderr, "%-20s \t 0 - SEC_KRL_TYPE\n", " ");
+ fprintf(stderr, "%-20s \t 1 - SEC_CRL_TYPE\n", " ");
+ fprintf(stderr, "\n%-20s Bypass CA certificate checks.\n", "-B");
+ fprintf(stderr, "\n%-20s Partial decode for faster operation.\n", "-p");
+ fprintf(stderr, "%-20s Repeat the operation.\n", "-r <iterations>");
+ fprintf(stderr, "\n%-15s Create CRL\n", "-G");
+ fprintf(stderr, "%-15s Modify CRL\n", "-M");
+ fprintf(stderr, "%-20s Specify crl initialization file\n",
+ "-c crl-conf-file");
+ fprintf(stderr, "%-20s Specify the nickname of the CA certificate\n",
+ "-n nickname");
+ fprintf(stderr, "%-20s Specify the file which contains the CRL to import\n",
+ "-i crl");
+ fprintf(stderr, "%-20s Specify a CRL output file\n",
+ "-o crl-output-file");
+ fprintf(stderr, "%-20s Specify to use base64 encoded CRL output format\n",
+ "-a");
+ fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
+ "-d keydir");
+ fprintf(stderr, "%-20s Provide path to a default pwd file\n",
+ "-f pwd-file");
+ fprintf(stderr, "%-20s Provide db password in command line\n",
+ "-w pwd-string");
+ fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
+ "-P dbprefix");
+ fprintf(stderr, "%-20s Specify the url.\n", "-u url");
+ fprintf(stderr, "\n%-20s Bypass CA certificate checks.\n", "-B");
+
+ exit(-1);
+}
+
+int
+main(int argc, char **argv)
+{
+ CERTCertDBHandle *certHandle;
+ PRFileDesc *inFile;
+ PRFileDesc *inCrlInitFile = NULL;
+ int generateCRL;
+ int modifyCRL;
+ int listCRL;
+ int importCRL;
+ int showFileCRL;
+ int deleteCRL;
+ int rv;
+ char *nickName;
+ char *url;
+ char *dbPrefix = PORT_Strdup("");
+ char *alg = NULL;
+ char *outFile = NULL;
+ char *slotName = NULL;
+ int ascii = 0;
+ int crlType;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus secstatus;
+ PRInt32 decodeOptions = CRL_DECODE_DEFAULT_OPTIONS;
+ PRInt32 importOptions = CRL_IMPORT_DEFAULT_OPTIONS;
+ PRBool quiet = PR_FALSE;
+ PRBool test = PR_FALSE;
+ PRBool erase = PR_FALSE;
+ PRInt32 i = 0;
+ PRInt32 iterations = 1;
+ PRBool readonly = PR_FALSE;
+
+ secuPWData pwdata = { PW_NONE, 0 };
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ rv = 0;
+ deleteCRL = importCRL = listCRL = generateCRL = modifyCRL = showFileCRL = 0;
+ inFile = NULL;
+ nickName = url = NULL;
+ certHandle = NULL;
+ crlType = SEC_CRL_TYPE;
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv, "sqBCDGILMSTEP:f:d:i:h:n:p:t:u:r:aZ:o:c:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'T':
+ test = PR_TRUE;
+ break;
+
+ case 'E':
+ erase = PR_TRUE;
+ break;
+
+ case 'B':
+ importOptions |= CRL_IMPORT_BYPASS_CHECKS;
+ break;
+
+ case 'G':
+ generateCRL = 1;
+ break;
+
+ case 'M':
+ modifyCRL = 1;
+ break;
+
+ case 'D':
+ deleteCRL = 1;
+ break;
+
+ case 'I':
+ importCRL = 1;
+ break;
+
+ case 'S':
+ showFileCRL = 1;
+ break;
+
+ case 'C':
+ case 'L':
+ listCRL = 1;
+ break;
+
+ case 'P':
+ PORT_Free(dbPrefix);
+ dbPrefix = PORT_Strdup(optstate->value);
+ break;
+
+ case 'Z':
+ alg = PORT_Strdup(optstate->value);
+ break;
+
+ case 'a':
+ ascii = 1;
+ break;
+
+ case 'c':
+ inCrlInitFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!inCrlInitFile) {
+ PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ rv = SECFailure;
+ goto loser;
+ }
+ break;
+
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'f':
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
+
+ case 'h':
+ slotName = PORT_Strdup(optstate->value);
+ break;
+
+ case 'i':
+ inFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!inFile) {
+ PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ rv = SECFailure;
+ goto loser;
+ }
+ break;
+
+ case 'n':
+ nickName = PORT_Strdup(optstate->value);
+ break;
+
+ case 'o':
+ outFile = PORT_Strdup(optstate->value);
+ break;
+
+ case 'p':
+ decodeOptions |= CRL_DECODE_SKIP_ENTRIES;
+ break;
+
+ case 'r': {
+ const char *str = optstate->value;
+ if (str && atoi(str) > 0)
+ iterations = atoi(str);
+ } break;
+
+ case 't': {
+ crlType = atoi(optstate->value);
+ if (crlType != SEC_CRL_TYPE && crlType != SEC_KRL_TYPE) {
+ PR_fprintf(PR_STDERR, "%s: invalid crl type\n", progName);
+ rv = SECFailure;
+ goto loser;
+ }
+ break;
+
+ case 'q':
+ quiet = PR_TRUE;
+ break;
+
+ case 'w':
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
+
+ case 'u':
+ url = PORT_Strdup(optstate->value);
+ break;
+ }
+ }
+ }
+
+ if (deleteCRL && !nickName)
+ Usage(progName);
+ if (importCRL && !inFile)
+ Usage(progName);
+ if (showFileCRL && !inFile)
+ Usage(progName);
+ if ((generateCRL && !nickName) ||
+ (modifyCRL && !inFile && !nickName))
+ Usage(progName);
+ if (!(listCRL || deleteCRL || importCRL || showFileCRL || generateCRL ||
+ modifyCRL || test || erase))
+ Usage(progName);
+
+ if (listCRL || showFileCRL) {
+ readonly = PR_TRUE;
+ }
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ if (showFileCRL) {
+ NSS_NoDB_Init(NULL);
+ } else {
+ secstatus = NSS_Initialize(SECU_ConfigDirectory(NULL), dbPrefix, dbPrefix,
+ "secmod.db", readonly ? NSS_INIT_READONLY : 0);
+ if (secstatus != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ rv = SECFailure;
+ goto loser;
+ }
+ }
+
+ SECU_RegisterDynamicOids();
+
+ certHandle = CERT_GetDefaultCertDB();
+ if (certHandle == NULL) {
+ SECU_PrintError(progName, "unable to open the cert db");
+ rv = SECFailure;
+ goto loser;
+ }
+
+ CRLGEN_InitCrlGenParserLock();
+
+ for (i = 0; i < iterations; i++) {
+ /* Read in the private key info */
+ if (deleteCRL)
+ DeleteCRL(certHandle, nickName, crlType);
+ else if (listCRL) {
+ rv = ListCRL(certHandle, nickName, crlType);
+ } else if (importCRL) {
+ rv = ImportCRL(certHandle, url, crlType, inFile, importOptions,
+ decodeOptions, &pwdata);
+ } else if (showFileCRL) {
+ rv = DumpCRL(inFile);
+ } else if (generateCRL || modifyCRL) {
+ if (!inCrlInitFile)
+ inCrlInitFile = PR_STDIN;
+ rv = GenerateCRL(certHandle, nickName, inCrlInitFile,
+ inFile, outFile, ascii, slotName,
+ importOptions, alg, quiet,
+ decodeOptions, url, &pwdata,
+ modifyCRL);
+ } else if (erase) {
+ /* list and delete all CRLs */
+ ListCRLNames(certHandle, crlType, PR_TRUE);
+ }
+#ifdef DEBUG
+ else if (test) {
+ /* list and delete all CRLs */
+ ListCRLNames(certHandle, crlType, PR_TRUE);
+ /* list CRLs */
+ ListCRLNames(certHandle, crlType, PR_FALSE);
+ /* import CRL as a blob */
+ rv = ImportCRL(certHandle, url, crlType, inFile, importOptions,
+ decodeOptions, &pwdata);
+ /* list CRLs */
+ ListCRLNames(certHandle, crlType, PR_FALSE);
+ }
+#endif
+ }
+
+ CRLGEN_DestroyCrlGenParserLock();
+
+loser:
+ PL_DestroyOptState(optstate);
+
+ if (inFile) {
+ PR_Close(inFile);
+ }
+ if (alg) {
+ PORT_Free(alg);
+ }
+ if (slotName) {
+ PORT_Free(slotName);
+ }
+ if (nickName) {
+ PORT_Free(nickName);
+ }
+ if (outFile) {
+ PORT_Free(outFile);
+ }
+ if (url) {
+ PORT_Free(url);
+ }
+ if (pwdata.data) {
+ PORT_Free(pwdata.data);
+ }
+
+ PORT_Free(dbPrefix);
+
+ if (NSS_Shutdown() != SECSuccess) {
+ rv = SECFailure;
+ }
+
+ return (rv != SECSuccess);
+}
diff --git a/security/nss/cmd/crlutil/crlutil.gyp b/security/nss/cmd/crlutil/crlutil.gyp
new file mode 100644
index 000000000..470449b0c
--- /dev/null
+++ b/security/nss/cmd/crlutil/crlutil.gyp
@@ -0,0 +1,32 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'crlutil',
+ 'type': 'executable',
+ 'sources': [
+ 'crlgen.c',
+ 'crlgen_lex.c',
+ 'crlutil.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/crlutil/manifest.mn b/security/nss/cmd/crlutil/manifest.mn
new file mode 100644
index 000000000..cd0549c6d
--- /dev/null
+++ b/security/nss/cmd/crlutil/manifest.mn
@@ -0,0 +1,25 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = crlgen_lex.c crlgen.c crlutil.c
+
+# this has to be different for NT and UNIX.
+# PROGRAM = ./$(OBJDIR)/crlutil.exe
+PROGRAM = crlutil
+
+#USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/crmf-cgi/Makefile b/security/nss/cmd/crmf-cgi/Makefile
new file mode 100644
index 000000000..f8172689f
--- /dev/null
+++ b/security/nss/cmd/crmf-cgi/Makefile
@@ -0,0 +1,53 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+EXTRA_LIBS += $(DIST)/lib/crmf.lib
+else
+EXTRA_LIBS += $(DIST)/lib/libcrmf.$(LIB_SUFFIX)
+endif
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/crmf-cgi/config.mk b/security/nss/cmd/crmf-cgi/config.mk
new file mode 100644
index 000000000..77fca3696
--- /dev/null
+++ b/security/nss/cmd/crmf-cgi/config.mk
@@ -0,0 +1,16 @@
+#
+# 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/.
+
+
+#
+# Override TARGETS variable so that only static libraries
+# are specifed as dependencies within rules.mk.
+#
+
+TARGETS = $(PROGRAM)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+LIBRARY =
+
diff --git a/security/nss/cmd/crmf-cgi/crmfcgi.c b/security/nss/cmd/crmf-cgi/crmfcgi.c
new file mode 100644
index 000000000..07b81f233
--- /dev/null
+++ b/security/nss/cmd/crmf-cgi/crmfcgi.c
@@ -0,0 +1,1090 @@
+/* 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/. */
+
+#include "seccomon.h"
+#include "nss.h"
+#include "key.h"
+#include "cert.h"
+#include "pk11func.h"
+#include "secmod.h"
+#include "cmmf.h"
+#include "crmf.h"
+#include "base64.h"
+#include "secasn1.h"
+#include "cryptohi.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define DEFAULT_ALLOC_SIZE 200
+#define DEFAULT_CGI_VARS 20
+
+typedef struct CGIVariableStr {
+ char *name;
+ char *value;
+} CGIVariable;
+
+typedef struct CGIVarTableStr {
+ CGIVariable **variables;
+ int numVars;
+ int numAlloc;
+} CGIVarTable;
+
+typedef struct CertResponseInfoStr {
+ CERTCertificate *cert;
+ long certReqID;
+} CertResponseInfo;
+
+typedef struct ChallengeCreationInfoStr {
+ long random;
+ SECKEYPublicKey *pubKey;
+} ChallengeCreationInfo;
+
+char *missingVar = NULL;
+
+/*
+ * Error values.
+ */
+typedef enum {
+ NO_ERROR = 0,
+ NSS_INIT_FAILED,
+ AUTH_FAILED,
+ REQ_CGI_VAR_NOT_PRESENT,
+ CRMF_REQ_NOT_PRESENT,
+ BAD_ASCII_FOR_REQ,
+ CGI_VAR_MISSING,
+ COULD_NOT_FIND_CA,
+ COULD_NOT_DECODE_REQS,
+ OUT_OF_MEMORY,
+ ERROR_RETRIEVING_REQUEST_MSG,
+ ERROR_RETRIEVING_CERT_REQUEST,
+ ERROR_RETRIEVING_SUBJECT_FROM_REQ,
+ ERROR_RETRIEVING_PUBLIC_KEY_FROM_REQ,
+ ERROR_CREATING_NEW_CERTIFICATE,
+ COULD_NOT_START_EXTENSIONS,
+ ERROR_RETRIEVING_EXT_FROM_REQ,
+ ERROR_ADDING_EXT_TO_CERT,
+ ERROR_ENDING_EXTENSIONS,
+ COULD_NOT_FIND_ISSUER_PRIVATE_KEY,
+ UNSUPPORTED_SIGN_OPERATION_FOR_ISSUER,
+ ERROR_SETTING_SIGN_ALG,
+ ERROR_ENCODING_NEW_CERT,
+ ERROR_SIGNING_NEW_CERT,
+ ERROR_CREATING_CERT_REP_CONTENT,
+ ERROR_CREATING_SINGLE_CERT_RESPONSE,
+ ERROR_SETTING_CERT_RESPONSES,
+ ERROR_CREATING_CA_LIST,
+ ERROR_ADDING_ISSUER_TO_CA_LIST,
+ ERROR_ENCODING_CERT_REP_CONTENT,
+ NO_POP_FOR_REQUEST,
+ UNSUPPORTED_POP,
+ ERROR_RETRIEVING_POP_SIGN_KEY,
+ ERROR_RETRIEVING_ALG_ID_FROM_SIGN_KEY,
+ ERROR_RETRIEVING_SIGNATURE_FROM_POP_SIGN_KEY,
+ DO_CHALLENGE_RESPONSE,
+ ERROR_RETRIEVING_PUB_KEY_FROM_NEW_CERT,
+ ERROR_ENCODING_CERT_REQ_FOR_POP,
+ ERROR_VERIFYING_SIGNATURE_POP,
+ ERROR_RETRIEVING_PUB_KEY_FOR_CHALL,
+ ERROR_CREATING_EMPTY_CHAL_CONTENT,
+ ERROR_EXTRACTING_GEN_NAME_FROM_ISSUER,
+ ERROR_SETTING_CHALLENGE,
+ ERROR_ENCODING_CHALL,
+ ERROR_CONVERTING_CHALL_TO_BASE64,
+ ERROR_CONVERTING_RESP_FROM_CHALL_TO_BIN,
+ ERROR_CREATING_KEY_RESP_FROM_DER,
+ ERROR_RETRIEVING_CLIENT_RESPONSE_TO_CHALLENGE,
+ ERROR_RETURNED_CHALL_NOT_VALUE_EXPECTED,
+ ERROR_GETTING_KEY_ENCIPHERMENT,
+ ERROR_NO_POP_FOR_PRIVKEY,
+ ERROR_UNSUPPORTED_POPOPRIVKEY_TYPE
+} ErrorCode;
+
+const char *
+CGITableFindValue(CGIVarTable *varTable, const char *key);
+
+void
+spitOutHeaders(void)
+{
+ printf("Content-type: text/html\n\n");
+}
+
+void
+dumpRequest(CGIVarTable *varTable)
+{
+ int i;
+ CGIVariable *var;
+
+ printf("<table border=1 cellpadding=1 cellspacing=1 width=\"100%%\">\n");
+ printf("<tr><td><b><center>Variable Name<center></b></td>"
+ "<td><b><center>Value</center></b></td></tr>\n");
+ for (i = 0; i < varTable->numVars; i++) {
+ var = varTable->variables[i];
+ printf("<tr><td><pre>%s</pre></td><td><pre>%s</pre></td></tr>\n",
+ var->name, var->value);
+ }
+ printf("</table>\n");
+}
+
+void
+echo_request(CGIVarTable *varTable)
+{
+ spitOutHeaders();
+ printf("<html><head><title>CGI Echo Page</title></head>\n"
+ "<body><h1>Got the following request</h1>\n");
+ dumpRequest(varTable);
+ printf("</body></html>");
+}
+
+void
+processVariable(CGIVariable *var)
+{
+ char *plusSign, *percentSign;
+
+ /*First look for all of the '+' and convert them to spaces */
+ plusSign = var->value;
+ while ((plusSign = strchr(plusSign, '+')) != NULL) {
+ *plusSign = ' ';
+ }
+ percentSign = var->value;
+ while ((percentSign = strchr(percentSign, '%')) != NULL) {
+ char string[3];
+ int value;
+
+ string[0] = percentSign[1];
+ string[1] = percentSign[2];
+ string[2] = '\0';
+
+ sscanf(string, "%x", &value);
+ *percentSign = (char)value;
+ memmove(&percentSign[1], &percentSign[3], 1 + strlen(&percentSign[3]));
+ }
+}
+
+char *
+parseNextVariable(CGIVarTable *varTable, char *form_output)
+{
+ char *ampersand, *equal;
+ CGIVariable *var;
+
+ if (varTable->numVars == varTable->numAlloc) {
+ CGIVariable **newArr = realloc(varTable->variables,
+ (varTable->numAlloc + DEFAULT_CGI_VARS) * sizeof(CGIVariable *));
+ if (newArr == NULL) {
+ return NULL;
+ }
+ varTable->variables = newArr;
+ varTable->numAlloc += DEFAULT_CGI_VARS;
+ }
+ equal = strchr(form_output, '=');
+ if (equal == NULL) {
+ return NULL;
+ }
+ ampersand = strchr(equal, '&');
+ if (ampersand == NULL) {
+ return NULL;
+ }
+ equal[0] = '\0';
+ if (ampersand != NULL) {
+ ampersand[0] = '\0';
+ }
+ var = malloc(sizeof(CGIVariable));
+ var->name = form_output;
+ var->value = &equal[1];
+ varTable->variables[varTable->numVars] = var;
+ varTable->numVars++;
+ processVariable(var);
+ return (ampersand != NULL) ? &ampersand[1] : NULL;
+}
+
+void
+ParseInputVariables(CGIVarTable *varTable, char *form_output)
+{
+ varTable->variables = malloc(sizeof(CGIVariable *) * DEFAULT_CGI_VARS);
+ varTable->numVars = 0;
+ varTable->numAlloc = DEFAULT_CGI_VARS;
+ while (form_output && form_output[0] != '\0') {
+ form_output = parseNextVariable(varTable, form_output);
+ }
+}
+
+const char *
+CGITableFindValue(CGIVarTable *varTable, const char *key)
+{
+ const char *retVal = NULL;
+ int i;
+
+ for (i = 0; i < varTable->numVars; i++) {
+ if (strcmp(varTable->variables[i]->name, key) == 0) {
+ retVal = varTable->variables[i]->value;
+ break;
+ }
+ }
+ return retVal;
+}
+
+char *
+passwordCallback(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ const char *passwd;
+ if (retry) {
+ return NULL;
+ }
+ passwd = CGITableFindValue((CGIVarTable *)arg, "dbPassword");
+ if (passwd == NULL) {
+ return NULL;
+ }
+ return PORT_Strdup(passwd);
+}
+
+ErrorCode
+initNSS(CGIVarTable *varTable)
+{
+ const char *nssDir;
+ PK11SlotInfo *keySlot;
+ SECStatus rv;
+
+ nssDir = CGITableFindValue(varTable, "NSSDirectory");
+ if (nssDir == NULL) {
+ missingVar = "NSSDirectory";
+ return REQ_CGI_VAR_NOT_PRESENT;
+ }
+ rv = NSS_Init(nssDir);
+ if (rv != SECSuccess) {
+ return NSS_INIT_FAILED;
+ }
+ PK11_SetPasswordFunc(passwordCallback);
+ keySlot = PK11_GetInternalKeySlot();
+ rv = PK11_Authenticate(keySlot, PR_FALSE, varTable);
+ PK11_FreeSlot(keySlot);
+ if (rv != SECSuccess) {
+ return AUTH_FAILED;
+ }
+ return NO_ERROR;
+}
+
+void
+dumpErrorMessage(ErrorCode errNum)
+{
+ spitOutHeaders();
+ printf("<html><head><title>Error</title></head><body><h1>Error processing "
+ "data</h1> Received the error %d<p>",
+ errNum);
+ if (errNum == REQ_CGI_VAR_NOT_PRESENT) {
+ printf("The missing variable is %s.", missingVar);
+ }
+ printf("<i>More useful information here in the future.</i></body></html>");
+}
+
+ErrorCode
+initOldCertReq(CERTCertificateRequest *oldCertReq,
+ CERTName *subject, CERTSubjectPublicKeyInfo *spki)
+{
+ PLArenaPool *poolp;
+
+ poolp = oldCertReq->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SEC_ASN1EncodeInteger(poolp, &oldCertReq->version,
+ SEC_CERTIFICATE_VERSION_3);
+ CERT_CopyName(poolp, &oldCertReq->subject, subject);
+ SECKEY_CopySubjectPublicKeyInfo(poolp, &oldCertReq->subjectPublicKeyInfo,
+ spki);
+ oldCertReq->attributes = NULL;
+ return NO_ERROR;
+}
+
+ErrorCode
+addExtensions(CERTCertificate *newCert, CRMFCertRequest *certReq)
+{
+ int numExtensions, i;
+ void *extHandle;
+ ErrorCode rv = NO_ERROR;
+ CRMFCertExtension *ext;
+ SECStatus srv;
+
+ numExtensions = CRMF_CertRequestGetNumberOfExtensions(certReq);
+ if (numExtensions == 0) {
+ /* No extensions to add */
+ return NO_ERROR;
+ }
+ extHandle = CERT_StartCertExtensions(newCert);
+ if (extHandle == NULL) {
+ rv = COULD_NOT_START_EXTENSIONS;
+ goto loser;
+ }
+ for (i = 0; i < numExtensions; i++) {
+ ext = CRMF_CertRequestGetExtensionAtIndex(certReq, i);
+ if (ext == NULL) {
+ rv = ERROR_RETRIEVING_EXT_FROM_REQ;
+ }
+ srv = CERT_AddExtension(extHandle, CRMF_CertExtensionGetOidTag(ext),
+ CRMF_CertExtensionGetValue(ext),
+ CRMF_CertExtensionGetIsCritical(ext), PR_FALSE);
+ if (srv != SECSuccess) {
+ rv = ERROR_ADDING_EXT_TO_CERT;
+ }
+ }
+ srv = CERT_FinishExtensions(extHandle);
+ if (srv != SECSuccess) {
+ rv = ERROR_ENDING_EXTENSIONS;
+ goto loser;
+ }
+ return NO_ERROR;
+loser:
+ return rv;
+}
+
+void
+writeOutItem(const char *filePath, SECItem *der)
+{
+ PRFileDesc *outfile;
+
+ outfile = PR_Open(filePath,
+ PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ PR_Write(outfile, der->data, der->len);
+ PR_Close(outfile);
+}
+
+ErrorCode
+createNewCert(CERTCertificate **issuedCert, CERTCertificateRequest *oldCertReq,
+ CRMFCertReqMsg *currReq, CRMFCertRequest *certReq,
+ CERTCertificate *issuerCert, CGIVarTable *varTable)
+{
+ CERTCertificate *newCert = NULL;
+ CERTValidity *validity;
+ PRExplodedTime printableTime;
+ PRTime now, after;
+ ErrorCode rv = NO_ERROR;
+ SECKEYPrivateKey *issuerPrivKey;
+ SECItem derCert = { 0 };
+ SECOidTag signTag;
+ SECStatus srv;
+ long version;
+
+ now = PR_Now();
+ PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
+ printableTime.tm_month += 9;
+ after = PR_ImplodeTime(&printableTime);
+ validity = CERT_CreateValidity(now, after);
+ newCert = *issuedCert =
+ CERT_CreateCertificate(rand(), &(issuerCert->subject), validity,
+ oldCertReq);
+ if (newCert == NULL) {
+ rv = ERROR_CREATING_NEW_CERTIFICATE;
+ goto loser;
+ }
+ rv = addExtensions(newCert, certReq);
+ if (rv != NO_ERROR) {
+ goto loser;
+ }
+ issuerPrivKey = PK11_FindKeyByAnyCert(issuerCert, varTable);
+ if (issuerPrivKey == NULL) {
+ rv = COULD_NOT_FIND_ISSUER_PRIVATE_KEY;
+ }
+ signTag = SEC_GetSignatureAlgorithmOidTag(issuerPrivatekey->keytype,
+ SEC_OID_UNKNOWN);
+ if (signTag == SEC_OID_UNKNOWN) {
+ rv = UNSUPPORTED_SIGN_OPERATION_FOR_ISSUER;
+ goto loser;
+ }
+ srv = SECOID_SetAlgorithmID(newCert->arena, &newCert->signature,
+ signTag, 0);
+ if (srv != SECSuccess) {
+ rv = ERROR_SETTING_SIGN_ALG;
+ goto loser;
+ }
+ srv = CRMF_CertRequestGetCertTemplateVersion(certReq, &version);
+ if (srv != SECSuccess) {
+ /* No version included in the request */
+ *(newCert->version.data) = SEC_CERTIFICATE_VERSION_3;
+ } else {
+ SECITEM_FreeItem(&newCert->version, PR_FALSE);
+ SEC_ASN1EncodeInteger(newCert->arena, &newCert->version, version);
+ }
+ SEC_ASN1EncodeItem(newCert->arena, &derCert, newCert,
+ CERT_CertificateTemplate);
+ if (derCert.data == NULL) {
+ rv = ERROR_ENCODING_NEW_CERT;
+ goto loser;
+ }
+ srv = SEC_DerSignData(newCert->arena, &(newCert->derCert), derCert.data,
+ derCert.len, issuerPrivKey, signTag);
+ if (srv != SECSuccess) {
+ rv = ERROR_SIGNING_NEW_CERT;
+ goto loser;
+ }
+#ifdef WRITE_OUT_RESPONSE
+ writeOutItem("newcert.der", &newCert->derCert);
+#endif
+ return NO_ERROR;
+loser:
+ *issuedCert = NULL;
+ if (newCert) {
+ CERT_DestroyCertificate(newCert);
+ }
+ return rv;
+}
+
+void
+formatCMMFResponse(char *nickname, char *base64Response)
+{
+ char *currLine, *nextLine;
+
+ printf("var retVal = crypto.importUserCertificates(\"%s\",\n", nickname);
+ currLine = base64Response;
+ while (1) {
+ nextLine = strchr(currLine, '\n');
+ if (nextLine == NULL) {
+ /* print out the last line here. */
+ printf("\"%s\",\n", currLine);
+ break;
+ }
+ nextLine[0] = '\0';
+ printf("\"%s\\n\"+\n", currLine);
+ currLine = nextLine + 1;
+ }
+ printf("true);\n"
+ "if(retVal == '') {\n"
+ "\tdocument.write(\"<h1>New Certificate Successfully Imported.</h1>\");\n"
+ "} else {\n"
+ "\tdocument.write(\"<h2>Unable to import New Certificate</h2>\");\n"
+ "\tdocument.write(\"crypto.importUserCertificates returned <b>\");\n"
+ "\tdocument.write(retVal);\n"
+ "\tdocument.write(\"</b>\");\n"
+ "}\n");
+}
+
+void
+spitOutCMMFResponse(char *nickname, char *base64Response)
+{
+ spitOutHeaders();
+ printf("<html>\n<head>\n<title>CMMF Resonse Page</title>\n</head>\n\n"
+ "<body><h1>CMMF Response Page</h1>\n"
+ "<script language=\"JavaScript\">\n"
+ "<!--\n");
+ formatCMMFResponse(nickname, base64Response);
+ printf("// -->\n"
+ "</script>\n</body>\n</html>");
+}
+
+char *
+getNickname(CERTCertificate *cert)
+{
+ char *nickname;
+
+ if (cert->nickname != NULL) {
+ return cert->nickname;
+ }
+ nickname = CERT_GetCommonName(&cert->subject);
+ if (nickname != NULL) {
+ return nickname;
+ }
+ return CERT_NameToAscii(&cert->subject);
+}
+
+ErrorCode
+createCMMFResponse(CertResponseInfo *issuedCerts, int numCerts,
+ CERTCertificate *issuerCert, char **base64der)
+{
+ CMMFCertRepContent *certRepContent = NULL;
+ ErrorCode rv = NO_ERROR;
+ CMMFCertResponse **responses, *currResponse;
+ CERTCertList *caList;
+ int i;
+ SECStatus srv;
+ PLArenaPool *poolp;
+ SECItem *der;
+
+ certRepContent = CMMF_CreateCertRepContent();
+ if (certRepContent == NULL) {
+ rv = ERROR_CREATING_CERT_REP_CONTENT;
+ goto loser;
+ }
+ responses = PORT_NewArray(CMMFCertResponse *, numCerts);
+ if (responses == NULL) {
+ rv = OUT_OF_MEMORY;
+ goto loser;
+ }
+ for (i = 0; i < numCerts; i++) {
+ responses[i] = currResponse =
+ CMMF_CreateCertResponse(issuedCerts[i].certReqID);
+ if (currResponse == NULL) {
+ rv = ERROR_CREATING_SINGLE_CERT_RESPONSE;
+ goto loser;
+ }
+ CMMF_CertResponseSetPKIStatusInfoStatus(currResponse, cmmfGranted);
+ CMMF_CertResponseSetCertificate(currResponse, issuedCerts[i].cert);
+ }
+ srv = CMMF_CertRepContentSetCertResponses(certRepContent, responses,
+ numCerts);
+ if (srv != SECSuccess) {
+ rv = ERROR_SETTING_CERT_RESPONSES;
+ goto loser;
+ }
+ caList = CERT_NewCertList();
+ if (caList == NULL) {
+ rv = ERROR_CREATING_CA_LIST;
+ goto loser;
+ }
+ srv = CERT_AddCertToListTail(caList, issuerCert);
+ if (srv != SECSuccess) {
+ rv = ERROR_ADDING_ISSUER_TO_CA_LIST;
+ goto loser;
+ }
+ srv = CMMF_CertRepContentSetCAPubs(certRepContent, caList);
+ CERT_DestroyCertList(caList);
+ poolp = PORT_NewArena(1024);
+ der = SEC_ASN1EncodeItem(poolp, NULL, certRepContent,
+ CMMFCertRepContentTemplate);
+ if (der == NULL) {
+ rv = ERROR_ENCODING_CERT_REP_CONTENT;
+ goto loser;
+ }
+#ifdef WRITE_OUT_RESPONSE
+ writeOutItem("CertRepContent.der", der);
+#endif
+ *base64der = BTOA_DataToAscii(der->data, der->len);
+ return NO_ERROR;
+loser:
+ return rv;
+}
+
+ErrorCode
+issueCerts(CertResponseInfo *issuedCerts, int numCerts,
+ CERTCertificate *issuerCert)
+{
+ ErrorCode rv;
+ char *base64Response;
+
+ rv = createCMMFResponse(issuedCerts, numCerts, issuerCert, &base64Response);
+ if (rv != NO_ERROR) {
+ goto loser;
+ }
+ spitOutCMMFResponse(getNickname(issuedCerts[0].cert), base64Response);
+ return NO_ERROR;
+loser:
+ return rv;
+}
+
+ErrorCode
+verifySignature(CGIVarTable *varTable, CRMFCertReqMsg *currReq,
+ CRMFCertRequest *certReq, CERTCertificate *newCert)
+{
+ SECStatus srv;
+ ErrorCode rv = NO_ERROR;
+ CRMFPOPOSigningKey *signKey = NULL;
+ SECAlgorithmID *algID = NULL;
+ SECItem *signature = NULL;
+ SECKEYPublicKey *pubKey = NULL;
+ SECItem *reqDER = NULL;
+
+ srv = CRMF_CertReqMsgGetPOPOSigningKey(currReq, &signKey);
+ if (srv != SECSuccess || signKey == NULL) {
+ rv = ERROR_RETRIEVING_POP_SIGN_KEY;
+ goto loser;
+ }
+ algID = CRMF_POPOSigningKeyGetAlgID(signKey);
+ if (algID == NULL) {
+ rv = ERROR_RETRIEVING_ALG_ID_FROM_SIGN_KEY;
+ goto loser;
+ }
+ signature = CRMF_POPOSigningKeyGetSignature(signKey);
+ if (signature == NULL) {
+ rv = ERROR_RETRIEVING_SIGNATURE_FROM_POP_SIGN_KEY;
+ goto loser;
+ }
+ /* Make the length the number of bytes instead of bits */
+ signature->len = (signature->len + 7) / 8;
+ pubKey = CERT_ExtractPublicKey(newCert);
+ if (pubKey == NULL) {
+ rv = ERROR_RETRIEVING_PUB_KEY_FROM_NEW_CERT;
+ goto loser;
+ }
+ reqDER = SEC_ASN1EncodeItem(NULL, NULL, certReq, CRMFCertRequestTemplate);
+ if (reqDER == NULL) {
+ rv = ERROR_ENCODING_CERT_REQ_FOR_POP;
+ goto loser;
+ }
+ srv = VFY_VerifyDataWithAlgorithmID(reqDER->data, reqDER->len, pubKey,
+ signature, &algID->algorithm, NULL, varTable);
+ if (srv != SECSuccess) {
+ rv = ERROR_VERIFYING_SIGNATURE_POP;
+ goto loser;
+ }
+/* Fall thru in successfull case. */
+loser:
+ if (pubKey != NULL) {
+ SECKEY_DestroyPublicKey(pubKey);
+ }
+ if (reqDER != NULL) {
+ SECITEM_FreeItem(reqDER, PR_TRUE);
+ }
+ if (signature != NULL) {
+ SECITEM_FreeItem(signature, PR_TRUE);
+ }
+ if (algID != NULL) {
+ SECOID_DestroyAlgorithmID(algID, PR_TRUE);
+ }
+ if (signKey != NULL) {
+ CRMF_DestroyPOPOSigningKey(signKey);
+ }
+ return rv;
+}
+
+ErrorCode
+doChallengeResponse(CGIVarTable *varTable, CRMFCertReqMsg *currReq,
+ CRMFCertRequest *certReq, CERTCertificate *newCert,
+ ChallengeCreationInfo *challs, int *numChall)
+{
+ CRMFPOPOPrivKey *privKey = NULL;
+ CRMFPOPOPrivKeyChoice privKeyChoice;
+ SECStatus srv;
+ ErrorCode rv = NO_ERROR;
+
+ srv = CRMF_CertReqMsgGetPOPKeyEncipherment(currReq, &privKey);
+ if (srv != SECSuccess || privKey == NULL) {
+ rv = ERROR_GETTING_KEY_ENCIPHERMENT;
+ goto loser;
+ }
+ privKeyChoice = CRMF_POPOPrivKeyGetChoice(privKey);
+ CRMF_DestroyPOPOPrivKey(privKey);
+ switch (privKeyChoice) {
+ case crmfSubsequentMessage:
+ challs = &challs[*numChall];
+ challs->random = rand();
+ challs->pubKey = CERT_ExtractPublicKey(newCert);
+ if (challs->pubKey == NULL) {
+ rv =
+ ERROR_RETRIEVING_PUB_KEY_FOR_CHALL;
+ goto loser;
+ }
+ (*numChall)++;
+ rv = DO_CHALLENGE_RESPONSE;
+ break;
+ case crmfThisMessage:
+ /* There'd better be a PKIArchiveControl in this message */
+ if (!CRMF_CertRequestIsControlPresent(certReq,
+ crmfPKIArchiveOptionsControl)) {
+ rv =
+ ERROR_NO_POP_FOR_PRIVKEY;
+ goto loser;
+ }
+ break;
+ default:
+ rv = ERROR_UNSUPPORTED_POPOPRIVKEY_TYPE;
+ goto loser;
+ }
+loser:
+ return rv;
+}
+
+ErrorCode
+doProofOfPossession(CGIVarTable *varTable, CRMFCertReqMsg *currReq,
+ CRMFCertRequest *certReq, CERTCertificate *newCert,
+ ChallengeCreationInfo *challs, int *numChall)
+{
+ CRMFPOPChoice popChoice;
+ ErrorCode rv = NO_ERROR;
+
+ popChoice = CRMF_CertReqMsgGetPOPType(currReq);
+ if (popChoice == crmfNoPOPChoice) {
+ rv = NO_POP_FOR_REQUEST;
+ goto loser;
+ }
+ switch (popChoice) {
+ case crmfSignature:
+ rv = verifySignature(varTable, currReq, certReq, newCert);
+ break;
+ case crmfKeyEncipherment:
+ rv = doChallengeResponse(varTable, currReq, certReq, newCert,
+ challs, numChall);
+ break;
+ case crmfRAVerified:
+ case crmfKeyAgreement:
+ default:
+ rv = UNSUPPORTED_POP;
+ goto loser;
+ }
+loser:
+ return rv;
+}
+
+void
+convertB64ToJS(char *base64)
+{
+ int i;
+
+ for (i = 0; base64[i] != '\0'; i++) {
+ if (base64[i] == '\n') {
+ printf("\\n");
+ } else {
+ printf("%c", base64[i]);
+ }
+ }
+}
+
+void
+formatChallenge(char *chall64, char *certRepContentDER,
+ ChallengeCreationInfo *challInfo, int numChalls)
+{
+ printf("function respondToChallenge() {\n"
+ " var chalForm = document.chalForm;\n\n"
+ " chalForm.CertRepContent.value = '");
+ convertB64ToJS(certRepContentDER);
+ printf("';\n"
+ " chalForm.ChallResponse.value = crypto.popChallengeResponse('");
+ convertB64ToJS(chall64);
+ printf("');\n"
+ " chalForm.submit();\n"
+ "}\n");
+}
+
+void
+spitOutChallenge(char *chall64, char *certRepContentDER,
+ ChallengeCreationInfo *challInfo, int numChalls,
+ char *nickname)
+{
+ int i;
+
+ spitOutHeaders();
+ printf("<html>\n"
+ "<head>\n"
+ "<title>Challenge Page</title>\n"
+ "<script language=\"JavaScript\">\n"
+ "<!--\n");
+ /* The JavaScript function actually gets defined within
+ * this function call
+ */
+ formatChallenge(chall64, certRepContentDER, challInfo, numChalls);
+ printf("// -->\n"
+ "</script>\n"
+ "</head>\n"
+ "<body onLoad='respondToChallenge()'>\n"
+ "<h1>Cartman is now responding to the Challenge "
+ "presented by the CGI</h1>\n"
+ "<form action='crmfcgi' method='post' name='chalForm'>\n"
+ "<input type='hidden' name=CertRepContent value=''>\n"
+ "<input type='hidden' name=ChallResponse value=''>\n");
+ for (i = 0; i < numChalls; i++) {
+ printf("<input type='hidden' name='chal%d' value='%d'>\n",
+ i + 1, challInfo[i].random);
+ }
+ printf("<input type='hidden' name='nickname' value='%s'>\n", nickname);
+ printf("</form>\n</body>\n</html>");
+}
+
+ErrorCode
+issueChallenge(CertResponseInfo *issuedCerts, int numCerts,
+ ChallengeCreationInfo *challInfo, int numChalls,
+ CERTCertificate *issuer, CGIVarTable *varTable)
+{
+ ErrorCode rv = NO_ERROR;
+ CMMFPOPODecKeyChallContent *chalContent = NULL;
+ int i;
+ SECStatus srv;
+ PLArenaPool *poolp;
+ CERTGeneralName *genName;
+ SECItem *challDER = NULL;
+ char *chall64, *certRepContentDER;
+
+ rv = createCMMFResponse(issuedCerts, numCerts, issuer,
+ &certRepContentDER);
+ if (rv != NO_ERROR) {
+ goto loser;
+ }
+ chalContent = CMMF_CreatePOPODecKeyChallContent();
+ if (chalContent == NULL) {
+ rv = ERROR_CREATING_EMPTY_CHAL_CONTENT;
+ goto loser;
+ }
+ poolp = PORT_NewArena(1024);
+ if (poolp == NULL) {
+ rv = OUT_OF_MEMORY;
+ goto loser;
+ }
+ genName = CERT_GetCertificateNames(issuer, poolp);
+ if (genName == NULL) {
+ rv = ERROR_EXTRACTING_GEN_NAME_FROM_ISSUER;
+ goto loser;
+ }
+ for (i = 0; i < numChalls; i++) {
+ srv = CMMF_POPODecKeyChallContentSetNextChallenge(chalContent,
+ challInfo[i].random,
+ genName,
+ challInfo[i].pubKey,
+ varTable);
+ SECKEY_DestroyPublicKey(challInfo[i].pubKey);
+ if (srv != SECSuccess) {
+ rv = ERROR_SETTING_CHALLENGE;
+ goto loser;
+ }
+ }
+ challDER = SEC_ASN1EncodeItem(NULL, NULL, chalContent,
+ CMMFPOPODecKeyChallContentTemplate);
+ if (challDER == NULL) {
+ rv = ERROR_ENCODING_CHALL;
+ goto loser;
+ }
+ chall64 = BTOA_DataToAscii(challDER->data, challDER->len);
+ SECITEM_FreeItem(challDER, PR_TRUE);
+ if (chall64 == NULL) {
+ rv = ERROR_CONVERTING_CHALL_TO_BASE64;
+ goto loser;
+ }
+ spitOutChallenge(chall64, certRepContentDER, challInfo, numChalls,
+ getNickname(issuedCerts[0].cert));
+loser:
+ return rv;
+}
+
+ErrorCode
+processRequest(CGIVarTable *varTable)
+{
+ CERTCertDBHandle *certdb;
+ SECKEYKeyDBHandle *keydb;
+ CRMFCertReqMessages *certReqs = NULL;
+ const char *crmfReq;
+ const char *caNickname;
+ CERTCertificate *caCert = NULL;
+ CertResponseInfo *issuedCerts = NULL;
+ CERTSubjectPublicKeyInfo spki = { 0 };
+ ErrorCode rv = NO_ERROR;
+ PRBool doChallengeResponse = PR_FALSE;
+ SECItem der = { 0 };
+ SECStatus srv;
+ CERTCertificateRequest oldCertReq = { 0 };
+ CRMFCertReqMsg **reqMsgs = NULL, *currReq = NULL;
+ CRMFCertRequest **reqs = NULL, *certReq = NULL;
+ CERTName subject = { 0 };
+ int numReqs, i;
+ ChallengeCreationInfo *challInfo = NULL;
+ int numChalls = 0;
+
+ certdb = CERT_GetDefaultCertDB();
+ keydb = SECKEY_GetDefaultKeyDB();
+ crmfReq = CGITableFindValue(varTable, "CRMFRequest");
+ if (crmfReq == NULL) {
+ rv = CGI_VAR_MISSING;
+ missingVar = "CRMFRequest";
+ goto loser;
+ }
+ caNickname = CGITableFindValue(varTable, "CANickname");
+ if (caNickname == NULL) {
+ rv = CGI_VAR_MISSING;
+ missingVar = "CANickname";
+ goto loser;
+ }
+ caCert = CERT_FindCertByNickname(certdb, caNickname);
+ if (caCert == NULL) {
+ rv = COULD_NOT_FIND_CA;
+ goto loser;
+ }
+ srv = ATOB_ConvertAsciiToItem(&der, crmfReq);
+ if (srv != SECSuccess) {
+ rv = BAD_ASCII_FOR_REQ;
+ goto loser;
+ }
+ certReqs = CRMF_CreateCertReqMessagesFromDER(der.data, der.len);
+ SECITEM_FreeItem(&der, PR_FALSE);
+ if (certReqs == NULL) {
+ rv = COULD_NOT_DECODE_REQS;
+ goto loser;
+ }
+ numReqs = CRMF_CertReqMessagesGetNumMessages(certReqs);
+ issuedCerts = PORT_ZNewArray(CertResponseInfo, numReqs);
+ challInfo = PORT_ZNewArray(ChallengeCreationInfo, numReqs);
+ if (issuedCerts == NULL || challInfo == NULL) {
+ rv = OUT_OF_MEMORY;
+ goto loser;
+ }
+ reqMsgs = PORT_ZNewArray(CRMFCertReqMsg *, numReqs);
+ reqs = PORT_ZNewArray(CRMFCertRequest *, numReqs);
+ if (reqMsgs == NULL || reqs == NULL) {
+ rv = OUT_OF_MEMORY;
+ goto loser;
+ }
+ for (i = 0; i < numReqs; i++) {
+ currReq = reqMsgs[i] =
+ CRMF_CertReqMessagesGetCertReqMsgAtIndex(certReqs, i);
+ if (currReq == NULL) {
+ rv = ERROR_RETRIEVING_REQUEST_MSG;
+ goto loser;
+ }
+ certReq = reqs[i] = CRMF_CertReqMsgGetCertRequest(currReq);
+ if (certReq == NULL) {
+ rv = ERROR_RETRIEVING_CERT_REQUEST;
+ goto loser;
+ }
+ srv = CRMF_CertRequestGetCertTemplateSubject(certReq, &subject);
+ if (srv != SECSuccess) {
+ rv = ERROR_RETRIEVING_SUBJECT_FROM_REQ;
+ goto loser;
+ }
+ srv = CRMF_CertRequestGetCertTemplatePublicKey(certReq, &spki);
+ if (srv != SECSuccess) {
+ rv = ERROR_RETRIEVING_PUBLIC_KEY_FROM_REQ;
+ goto loser;
+ }
+ rv = initOldCertReq(&oldCertReq, &subject, &spki);
+ if (rv != NO_ERROR) {
+ goto loser;
+ }
+ rv = createNewCert(&issuedCerts[i].cert, &oldCertReq, currReq, certReq,
+ caCert, varTable);
+ if (rv != NO_ERROR) {
+ goto loser;
+ }
+ rv = doProofOfPossession(varTable, currReq, certReq, issuedCerts[i].cert,
+ challInfo, &numChalls);
+ if (rv != NO_ERROR) {
+ if (rv == DO_CHALLENGE_RESPONSE) {
+ doChallengeResponse = PR_TRUE;
+ } else {
+ goto loser;
+ }
+ }
+ CRMF_CertReqMsgGetID(currReq, &issuedCerts[i].certReqID);
+ CRMF_DestroyCertReqMsg(currReq);
+ CRMF_DestroyCertRequest(certReq);
+ }
+ if (doChallengeResponse) {
+ rv = issueChallenge(issuedCerts, numReqs, challInfo, numChalls, caCert,
+ varTable);
+ } else {
+ rv = issueCerts(issuedCerts, numReqs, caCert);
+ }
+loser:
+ if (certReqs != NULL) {
+ CRMF_DestroyCertReqMessages(certReqs);
+ }
+ return rv;
+}
+
+ErrorCode
+processChallengeResponse(CGIVarTable *varTable, const char *certRepContent)
+{
+ SECItem binDER = { 0 };
+ SECStatus srv;
+ ErrorCode rv = NO_ERROR;
+ const char *clientResponse;
+ const char *formChalValue;
+ const char *nickname;
+ CMMFPOPODecKeyRespContent *respContent = NULL;
+ int numResponses, i;
+ long curResponse, expectedResponse;
+ char cgiChalVar[10];
+#ifdef WRITE_OUT_RESPONSE
+ SECItem certRepBinDER = { 0 };
+
+ ATOB_ConvertAsciiToItem(&certRepBinDER, certRepContent);
+ writeOutItem("challCertRepContent.der", &certRepBinDER);
+ PORT_Free(certRepBinDER.data);
+#endif
+ clientResponse = CGITableFindValue(varTable, "ChallResponse");
+ if (clientResponse == NULL) {
+ rv = REQ_CGI_VAR_NOT_PRESENT;
+ missingVar = "ChallResponse";
+ goto loser;
+ }
+ srv = ATOB_ConvertAsciiToItem(&binDER, clientResponse);
+ if (srv != SECSuccess) {
+ rv = ERROR_CONVERTING_RESP_FROM_CHALL_TO_BIN;
+ goto loser;
+ }
+ respContent = CMMF_CreatePOPODecKeyRespContentFromDER(binDER.data,
+ binDER.len);
+ SECITEM_FreeItem(&binDER, PR_FALSE);
+ binDER.data = NULL;
+ if (respContent == NULL) {
+ rv = ERROR_CREATING_KEY_RESP_FROM_DER;
+ goto loser;
+ }
+ numResponses = CMMF_POPODecKeyRespContentGetNumResponses(respContent);
+ for (i = 0; i < numResponses; i++) {
+ srv = CMMF_POPODecKeyRespContentGetResponse(respContent, i, &curResponse);
+ if (srv != SECSuccess) {
+ rv = ERROR_RETRIEVING_CLIENT_RESPONSE_TO_CHALLENGE;
+ goto loser;
+ }
+ sprintf(cgiChalVar, "chal%d", i + 1);
+ formChalValue = CGITableFindValue(varTable, cgiChalVar);
+ if (formChalValue == NULL) {
+ rv = REQ_CGI_VAR_NOT_PRESENT;
+ missingVar = strdup(cgiChalVar);
+ goto loser;
+ }
+ sscanf(formChalValue, "%ld", &expectedResponse);
+ if (expectedResponse != curResponse) {
+ rv = ERROR_RETURNED_CHALL_NOT_VALUE_EXPECTED;
+ goto loser;
+ }
+ }
+ nickname = CGITableFindValue(varTable, "nickname");
+ if (nickname == NULL) {
+ rv = REQ_CGI_VAR_NOT_PRESENT;
+ missingVar = "nickname";
+ goto loser;
+ }
+ spitOutCMMFResponse(nickname, certRepContent);
+loser:
+ if (respContent != NULL) {
+ CMMF_DestroyPOPODecKeyRespContent(respContent);
+ }
+ return rv;
+}
+
+int
+main()
+{
+ char *form_output = NULL;
+ int form_output_len, form_output_used;
+ CGIVarTable varTable = { 0 };
+ ErrorCode errNum = 0;
+ char *certRepContent;
+
+#ifdef ATTACH_CGI
+ /* Put an ifinite loop in here so I can attach to
+ * the process after the process is spun off
+ */
+ {
+ int stupid = 1;
+ while (stupid)
+ ;
+ }
+#endif
+
+ form_output_used = 0;
+ srand(time(NULL));
+ while (feof(stdin) == 0) {
+ if (form_output == NULL) {
+ form_output = PORT_NewArray(char, DEFAULT_ALLOC_SIZE + 1);
+ form_output_len = DEFAULT_ALLOC_SIZE;
+ } else if ((form_output_used + DEFAULT_ALLOC_SIZE) >= form_output_len) {
+ form_output_len += DEFAULT_ALLOC_SIZE;
+ form_output = PORT_Realloc(form_output, form_output_len + 1);
+ }
+ form_output_used += fread(&form_output[form_output_used], sizeof(char),
+ DEFAULT_ALLOC_SIZE, stdin);
+ }
+ ParseInputVariables(&varTable, form_output);
+ certRepContent = CGITableFindValue(&varTable, "CertRepContent");
+ if (certRepContent == NULL) {
+ errNum = initNSS(&varTable);
+ if (errNum != 0) {
+ goto loser;
+ }
+ errNum = processRequest(&varTable);
+ } else {
+ errNum = processChallengeResponse(&varTable, certRepContent);
+ }
+ if (errNum != NO_ERROR) {
+ goto loser;
+ }
+ goto done;
+loser:
+ dumpErrorMessage(errNum);
+done:
+ free(form_output);
+ return 0;
+}
diff --git a/security/nss/cmd/crmf-cgi/crmfcgi.html b/security/nss/cmd/crmf-cgi/crmfcgi.html
new file mode 100644
index 000000000..537b0f5a9
--- /dev/null
+++ b/security/nss/cmd/crmf-cgi/crmfcgi.html
@@ -0,0 +1,136 @@
+<!-- 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/. -->
+
+<html>
+<head>
+<title>CRMF Test Page for PSM</title>
+<script language=javascript>
+var request;
+//This variable must be set to the first value
+//in the select field "testType" in the form.
+var keyGenType="SigningOnlyRSA";
+
+var requestedDN = "CN=Javi CA Shack ID, O=NSS";
+
+function setTestType() {
+ var testType = document.crmfForm.testType;
+
+ keyGenType = testType.options[testType.selectedIndex].value;
+}
+
+function setRequest() {
+ with (document.crmfForm) {
+ CRMFRequest.value = request.request;
+ submit();
+ }
+}
+
+function generateSignAndEncryptRSARequest() {
+ request = crypto.generateCRMFRequest(requestedDN,
+ null, null, null, "setRequest()",
+ crypto.algorithms.rsa.keyEx.keySizes[0],
+ null, "rsa-dual-use");
+}
+
+function generateSigningOnlyRSARequest() {
+ request = crypto.generateCRMFRequest(requestedDN,null,null,null,"setRequest()",
+ crypto.algorithms.rsa.signing.keySizes[0],
+ null, "rsa-sign");
+}
+
+function generateEncryptionOnlyRSARequest() {
+ request = crypto.generateCRMFRequest(requestedDN, null, null, null, "setRequest()",
+ crypto.algorithms.rsa.keyEx.keySizes[0],
+ null, "rsa-ex");
+}
+
+function generateDualRSAKeys() {
+ request = crypto.generateCRMFRequest(requestedDN, null, null, null, "setRequest()",
+ crypto.algorithms.rsa.keyEx.keySizes[0],
+ null, "rsa-ex",
+ crypto.algorithms.rsa.signing.keySizes[0],
+ null, "rsa-sign");
+}
+
+function generateDSAKey() {
+ request = crypto.generateCRMFRequest(requestedDN, null, null, null, "setRequest()",
+ crypto.algorithms.dsa.keySizes[0],
+ null, "dsa-sign-nonrepudiation");
+}
+
+function processForm(form) {
+ with (form) {
+ if (typeof(crypto.version) == "undefined") {
+ alert('You must be running PSM in order to use this page.');
+ return false;
+ }
+ if (NSSDirectory.value == "") {
+ alert('You must provide a path for NSS to use.');
+ return false;
+ }
+ if (dbPassword.value == "") {
+ alert('You must provide a password for the certificate database.');
+ return false;
+ }
+ if (CANickname.value == "") {
+ alert('You must provide a CA Nickname to use.');
+ return false;
+ }
+ //Now do the correct key generation.
+ if (keyGenType == "SignAndEncryptRSA") {
+ generateSignAndEncryptRSARequest();
+ } else if (keyGenType == "SigningOnlyRSA") {
+ generateSigningOnlyRSARequest();
+ } else if (keyGenType == "EncryptionOnlyRSA") {
+ generateEncryptionOnlyRSARequest();
+ } else if (keyGenType == "DualRSAKeys") {
+ generateDualRSAKeys();
+ } else if (keyGenType == "DSAKeyGen") {
+ generateDSAKey();
+ }
+ }
+ return true;
+}
+</script>
+</head>
+<body>
+<h1><center>CRMF Test page for PSM</center></h1>
+This page is designed to be used in combination with the executable
+produced by ns/security/cmd/crmf-cgi in a CGI environment. In order
+to successfully use this page, modify its action to post to a a server
+where you have installed the crmfcgi executable and you'll be able to
+test the functionality.
+<hr>
+<form name="crmfForm" method=post action="http://www.cgi-site.com/cgi-bin/crmfcgi">
+<h2>Certificate Database information</h2>
+First, enter all the information for the CGI to use for initializing
+NSS. The CGI will use the directory entered below as the directory
+where to look for the certificate and key databases.
+<pre>
+Path for NSS Config: <input size=40 type="text" name="NSSDirectory">
+</pre>
+Enter the password for the certificate database found in the direcotry
+above.
+<pre>
+Database Password: <input type="password" name="dbPassword" size=40>
+</pre>
+Now enter the nickname of the certificate to use for signing the
+certificate issued during this test.
+<pre>
+CA Nickname: <input size=40 type="text" name="CANickname">
+</pre>
+<h2>Now, figure out which type of key generation you want to test:</h2>
+<select name="testType" onChange="setTestType()">`
+<option value="SigningOnlyRSA">Signing Only-RSA
+<option value="EncryptionOnlyRSA">Encryption Only-RSA
+<option value="SignAndEncryptRSA">Sign and Encrypt Single Key -RSA
+<option value="DualRSAKeys">Dual Keys-RSA
+<option value="DSAKeyGen">DSA Key Gen
+</select>
+<input type="hidden" name=CRMFRequest value="">
+<hr>
+<input type="button" value="OK" onclick="processForm(document.crmfForm)">
+</form>
+</body>
+</html>
diff --git a/security/nss/cmd/crmf-cgi/manifest.mn b/security/nss/cmd/crmf-cgi/manifest.mn
new file mode 100644
index 000000000..1212424b6
--- /dev/null
+++ b/security/nss/cmd/crmf-cgi/manifest.mn
@@ -0,0 +1,33 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+MODULE = sectools
+
+EXPORTS = \
+ $(NULL)
+
+CSRCS = \
+ crmfcgi.c \
+ $(NULL)
+
+
+REQUIRES = nss dbm seccmd
+
+ifdef ATTACH_CGI
+DEFINES += -DATTACH_CGI
+endif
+
+ifdef WRITE_OUT_RESPONSE
+DEFINES += -DWRITE_OUT_RESPONSE
+endif
+
+PROGRAM = crmfcgi
+
+USE_STATIC_LIBS = 1
+
+INCLUDES =
+
+DEFINES = -DNSPR20
diff --git a/security/nss/cmd/crmftest/Makefile b/security/nss/cmd/crmftest/Makefile
new file mode 100644
index 000000000..369cdc89f
--- /dev/null
+++ b/security/nss/cmd/crmftest/Makefile
@@ -0,0 +1,64 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+include config.mk
+
+ifeq ($(OS_TARGET)$(OS_RELEASE), AIX4.2)
+OS_LIBS += -lsvld
+endif
+
+ifeq ($(OS_TARGET)$(OS_RELEASE), SunOS5.6)
+OS_LIBS += -ldl -lxnet -lposix4 -lsocket -lnsl
+endif
+
+EXTRA_LIBS += $(DIST)/lib/$(LIB_PREFIX)crmf.$(LIB_SUFFIX)
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+LDDIST = $(DIST)/lib
+
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+EXTRA_LIBS += $(LDDIST)/sectool.lib
+endif
+
+include ../platrules.mk
diff --git a/security/nss/cmd/crmftest/config.mk b/security/nss/cmd/crmftest/config.mk
new file mode 100644
index 000000000..9838ef15c
--- /dev/null
+++ b/security/nss/cmd/crmftest/config.mk
@@ -0,0 +1,15 @@
+#
+# 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/.
+
+#
+# Override TARGETS variable so that only static libraries
+# are specifed as dependencies within rules.mk.
+#
+
+TARGETS = $(PROGRAM)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+LIBRARY =
+
diff --git a/security/nss/cmd/crmftest/crmftest.gyp b/security/nss/cmd/crmftest/crmftest.gyp
new file mode 100644
index 000000000..c14bd195a
--- /dev/null
+++ b/security/nss/cmd/crmftest/crmftest.gyp
@@ -0,0 +1,25 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'crmftest',
+ 'type': 'executable',
+ 'sources': [
+ 'testcrmf.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports',
+ '<(DEPTH)/lib/crmf/crmf.gyp:crmf'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/crmftest/manifest.mn b/security/nss/cmd/crmftest/manifest.mn
new file mode 100644
index 000000000..578729e62
--- /dev/null
+++ b/security/nss/cmd/crmftest/manifest.mn
@@ -0,0 +1,25 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+DEPTH = .
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+EXPORTS = \
+ $(NULL)
+
+CSRCS = \
+ testcrmf.c \
+ $(NULL)
+
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+# REQUIRES = dbm
+
+PROGRAM = crmftest
+
diff --git a/security/nss/cmd/crmftest/testcrmf.c b/security/nss/cmd/crmftest/testcrmf.c
new file mode 100644
index 000000000..fefa6894d
--- /dev/null
+++ b/security/nss/cmd/crmftest/testcrmf.c
@@ -0,0 +1,1654 @@
+/* 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/. */
+
+/*
+ * This program does 5 separate functions. By default, it does them all.
+ * It can be told to do any subset of them.
+ * It does them in this order:
+ *
+ * 1. Generate file of CRMF cert requests.
+ * Generates 2 keys pairs, one for signing, one for encryption.
+ * Can generate RSA or DSA (XXX - DSA is only useful for signing).
+ * Generate a cert request for each of the two public keys.
+ * Generate a single CRMF cert request message that requests both certs.
+ * Leave the generated CRMF request message in file
+ * configdir/CertReqMessages.der
+ *
+ * 2. Decode CRMF Request(s) Message.
+ * Reads in the file configdir/CertReqMessages.der
+ * (either generated by step 1 above, or user supplied).
+ * Decodes it. NOTHING MORE. Drops these decoded results on the floor.
+ * The CMMF response (below) contains a completely unrelated cert. :-(
+ *
+ * 3. CMMF "Stuff".
+ * a) Generates a CMMF response, containing a single cert chain, as if
+ * it was a response to a received CRMF request. But the cert is
+ * simply a user cert from the user's local soft token, whose
+ * nickname is given in the -p option. The CMMF response has no
+ * relationship to the request generated above. The CMMF message
+ * is placed in configdir/CertRepContent.der.
+ * b) Decodes the newly generated CMMF response found in file
+ * configdir/CertRepContent.der and discards the result. 8-/
+ * c) Generate a CMMF Key Escrow message
+ * needs 2 nicknames:
+ * It takes the public and private keys for the cert identified
+ * by -p nickname, and wraps them with a sym key that is in turn
+ * wrapped with the pubkey in the CA cert, whose nickname is
+ * given with the -s option.
+ * Store the message in configdir/KeyRecRepContent.der
+ * d) Decode the CMMF Key Escrow message generated just above.
+ * Get it from file configdir/KeyRecRepContent.der
+ * This is just a decoder test. Results are discarded.
+ *
+ * 4. Key Recovery
+ * This code does not yet compile, and what it was intended to do
+ * has not been fully determined.
+ *
+ * 5. Challenge/Response.
+ * Haven't analyzed this code yet.
+ *
+ *
+ */
+
+/* KNOWN BUGS:
+** 1. generates BOTH signing and encryption cert requests, even for DSA keys.
+**
+** 2. Does not verify the siganture in the "Proof of Posession" in the
+** decoded cert requests. It only checks syntax of the POP.
+** 3. CMMF "Stuff" should be broken up into separate steps, each of
+** which may be optionally selected.
+*/
+
+#include <stdio.h>
+#include "nspr.h"
+#include "nss.h"
+#include "crmf.h"
+#include "secerr.h"
+#include "pk11func.h"
+#include "key.h"
+#include "cmmf.h"
+#include "plgetopt.h"
+#include "secutil.h"
+#include "pk11pqg.h"
+
+#if 0
+#include "pkcs11.h"
+#include "secmod.h"
+#include "secmodi.h"
+#include "pqggen.h"
+#include "secmod.h"
+#include "secmodi.h"
+#include "pkcs11.h"
+#include "secitem.h"
+#include "secasn1.h"
+#include "sechash.h"
+#endif
+
+#define MAX_KEY_LEN 512
+#define PATH_LEN 150
+#define BUFF_SIZE 150
+#define UID_BITS 800
+#define BPB 8
+#define CRMF_FILE "CertReqMessages.der"
+
+PRTime notBefore;
+char *personalCert = NULL;
+char *recoveryEncrypter = NULL;
+char *caCertName = NULL;
+static secuPWData pwdata = { PW_NONE, 0 };
+char *configdir;
+PRBool doingDSA = PR_FALSE;
+
+CERTCertDBHandle *db;
+
+typedef struct {
+ SECKEYPrivateKey *privKey;
+ SECKEYPublicKey *pubKey;
+ CRMFCertRequest *certReq;
+ CRMFCertReqMsg *certReqMsg;
+} TESTKeyPair;
+
+void
+debug_test(SECItem *src, char *filePath)
+{
+ PRFileDesc *fileDesc;
+
+ fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ if (fileDesc == NULL) {
+ printf("Could not cretae file %s.\n", filePath);
+ return;
+ }
+ PR_Write(fileDesc, src->data, src->len);
+}
+
+SECStatus
+get_serial_number(long *dest)
+{
+ SECStatus rv;
+
+ if (dest == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ rv = PK11_GenerateRandom((unsigned char *)dest, sizeof(long));
+ if (rv != SECSuccess) {
+ /* PK11_GenerateRandom calls PORT_SetError */
+ return SECFailure;
+ }
+ /* make serial number positive */
+ if (*dest < 0L)
+ *dest = -*dest;
+ return SECSuccess;
+}
+
+PK11RSAGenParams *
+GetRSAParams(void)
+{
+ PK11RSAGenParams *rsaParams;
+
+ rsaParams = PORT_ZNew(PK11RSAGenParams);
+
+ if (rsaParams == NULL)
+ return NULL;
+
+ rsaParams->keySizeInBits = MAX_KEY_LEN;
+ rsaParams->pe = 0x10001;
+
+ return rsaParams;
+}
+
+PQGParams *
+GetDSAParams(void)
+{
+ PQGParams *params = NULL;
+ PQGVerify *vfy = NULL;
+
+ SECStatus rv;
+
+ rv = PK11_PQG_ParamGen(0, &params, &vfy);
+ if (rv != SECSuccess) {
+ return NULL;
+ }
+ PK11_PQG_DestroyVerify(vfy);
+ return params;
+}
+
+/* Generate a key pair, and then generate a subjectPublicKeyInfo
+** for the public key in that pair. return all 3.
+*/
+CERTSubjectPublicKeyInfo *
+GetSubjectPubKeyInfo(TESTKeyPair *pair)
+{
+ CERTSubjectPublicKeyInfo *spki = NULL;
+ SECKEYPrivateKey *privKey = NULL;
+ SECKEYPublicKey *pubKey = NULL;
+ PK11SlotInfo *keySlot = NULL;
+
+ keySlot = PK11_GetInternalKeySlot();
+ PK11_Authenticate(keySlot, PR_FALSE, &pwdata);
+
+ if (!doingDSA) {
+ PK11RSAGenParams *rsaParams = GetRSAParams();
+ if (rsaParams == NULL) {
+ PK11_FreeSlot(keySlot);
+ return NULL;
+ }
+ privKey = PK11_GenerateKeyPair(keySlot, CKM_RSA_PKCS_KEY_PAIR_GEN,
+ (void *)rsaParams, &pubKey, PR_FALSE,
+ PR_FALSE, &pwdata);
+ } else {
+ PQGParams *dsaParams = GetDSAParams();
+ if (dsaParams == NULL) {
+ PK11_FreeSlot(keySlot);
+ return NULL;
+ }
+ privKey = PK11_GenerateKeyPair(keySlot, CKM_DSA_KEY_PAIR_GEN,
+ (void *)dsaParams, &pubKey, PR_FALSE,
+ PR_FALSE, &pwdata);
+ }
+ PK11_FreeSlot(keySlot);
+ if (privKey == NULL || pubKey == NULL) {
+ if (pubKey) {
+ SECKEY_DestroyPublicKey(pubKey);
+ }
+ if (privKey) {
+ SECKEY_DestroyPrivateKey(privKey);
+ }
+ return NULL;
+ }
+
+ spki = SECKEY_CreateSubjectPublicKeyInfo(pubKey);
+ pair->privKey = privKey;
+ pair->pubKey = pubKey;
+ return spki;
+}
+
+SECStatus
+InitPKCS11(void)
+{
+ PK11SlotInfo *keySlot;
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ keySlot = PK11_GetInternalKeySlot();
+
+ if (PK11_NeedUserInit(keySlot) && PK11_NeedLogin(keySlot)) {
+ if (SECU_ChangePW(keySlot, NULL, NULL) != SECSuccess) {
+ printf("Initializing the PINs failed.\n");
+ return SECFailure;
+ }
+ }
+
+ PK11_FreeSlot(keySlot);
+ return SECSuccess;
+}
+
+void
+WriteItOut(void *arg, const char *buf, unsigned long len)
+{
+ PRFileDesc *fileDesc = (PRFileDesc *)arg;
+
+ PR_Write(fileDesc, (void *)buf, len);
+}
+
+CRMFCertExtCreationInfo *
+GetExtensions(void)
+{
+ unsigned char keyUsage[4] = { 0x03, 0x02, 0x07, KU_DIGITAL_SIGNATURE };
+ /* What are these magic numbers? */
+ SECItem data = { 0, NULL, 0 };
+ CRMFCertExtension *extension;
+ CRMFCertExtCreationInfo *extInfo =
+ PORT_ZNew(CRMFCertExtCreationInfo);
+
+ data.data = keyUsage;
+ data.len = sizeof keyUsage;
+
+ extension =
+ CRMF_CreateCertExtension(SEC_OID_X509_KEY_USAGE, PR_FALSE, &data);
+ if (extension && extInfo) {
+ extInfo->numExtensions = 1;
+ extInfo->extensions = PORT_ZNewArray(CRMFCertExtension *, 1);
+ extInfo->extensions[0] = extension;
+ }
+ return extInfo;
+}
+
+void
+FreeExtInfo(CRMFCertExtCreationInfo *extInfo)
+{
+ int i;
+
+ for (i = 0; i < extInfo->numExtensions; i++) {
+ CRMF_DestroyCertExtension(extInfo->extensions[i]);
+ }
+ PORT_Free(extInfo->extensions);
+ PORT_Free(extInfo);
+}
+
+int
+InjectCertName(CRMFCertRequest *certReq,
+ CRMFCertTemplateField inTemplateField,
+ const char *inNameString)
+{
+ char *nameStr;
+ CERTName *name;
+ int irv = 0;
+
+ nameStr = PORT_Strdup(inNameString);
+ if (!nameStr)
+ return 5;
+ name = CERT_AsciiToName(nameStr);
+ if (name == NULL) {
+ printf("Could not create CERTName structure from %s.\n", nameStr);
+ irv = 5;
+ goto finish;
+ }
+
+ irv = CRMF_CertRequestSetTemplateField(certReq, inTemplateField, (void *)name);
+ if (irv != SECSuccess) {
+ printf("Could not add name to cert template\n");
+ irv = 6;
+ }
+
+finish:
+ PORT_Free(nameStr);
+ if (name)
+ CERT_DestroyName(name);
+ return irv;
+}
+
+int
+CreateCertRequest(TESTKeyPair *pair, long inRequestID)
+{
+ CERTCertificate *caCert;
+ CERTSubjectPublicKeyInfo *spki;
+ CRMFCertExtCreationInfo *extInfo;
+ CRMFCertRequest *certReq;
+ CRMFEncryptedKey *encKey;
+ CRMFPKIArchiveOptions *pkiArchOpt;
+ SECAlgorithmID *algID;
+ long serialNumber;
+ long version = 3;
+ SECStatus rv;
+ CRMFValidityCreationInfo validity;
+ unsigned char UIDbuf[UID_BITS / BPB];
+ SECItem issuerUID = { siBuffer, NULL, 0 };
+ SECItem subjectUID = { siBuffer, NULL, 0 };
+
+ /* len in bits */
+ issuerUID.data = UIDbuf;
+ issuerUID.len = UID_BITS;
+ subjectUID.data = UIDbuf;
+ subjectUID.len = UID_BITS;
+
+ pair->certReq = NULL;
+ certReq = CRMF_CreateCertRequest(inRequestID);
+ if (certReq == NULL) {
+ printf("Could not initialize a certificate request.\n");
+ return 1;
+ }
+
+ /* set to version 3 */
+ rv = CRMF_CertRequestSetTemplateField(certReq, crmfVersion,
+ (void *)(&version));
+ if (rv != SECSuccess) {
+ printf("Could not add the version number to the "
+ "Certificate Request.\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 2;
+ }
+
+ /* set serial number */
+ if (get_serial_number(&serialNumber) != SECSuccess) {
+ printf("Could not generate a serial number for cert request.\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 3;
+ }
+ rv = CRMF_CertRequestSetTemplateField(certReq, crmfSerialNumber,
+ (void *)(&serialNumber));
+ if (rv != SECSuccess) {
+ printf("Could not add serial number to certificate template\n.");
+ CRMF_DestroyCertRequest(certReq);
+ return 4;
+ }
+
+ /* Set issuer name */
+ rv = InjectCertName(certReq, crmfIssuer,
+ "CN=mozilla CA Shack,O=Information Systems");
+ if (rv) {
+ printf("Could not add issuer to cert template\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 5;
+ }
+
+ /* Set Subject Name */
+ rv = InjectCertName(certReq, crmfSubject,
+ "CN=mozilla CA Shack ID,O=Engineering,C=US");
+ if (rv) {
+ printf("Could not add Subject to cert template\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 5;
+ }
+
+ /* Set Algorithm ID */
+ algID = PK11_CreatePBEAlgorithmID(SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC,
+ 1, NULL);
+ if (algID == NULL) {
+ printf("Couldn't create algorithm ID\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 9;
+ }
+ rv = CRMF_CertRequestSetTemplateField(certReq, crmfSigningAlg, (void *)algID);
+ SECOID_DestroyAlgorithmID(algID, PR_TRUE);
+ if (rv != SECSuccess) {
+ printf("Could not add the signing algorithm to the cert template.\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 10;
+ }
+
+ /* Set Validity Dates */
+ validity.notBefore = &notBefore;
+ validity.notAfter = NULL;
+ notBefore = PR_Now();
+ rv = CRMF_CertRequestSetTemplateField(certReq, crmfValidity, (void *)(&validity));
+ if (rv != SECSuccess) {
+ printf("Could not add validity to cert template\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 11;
+ }
+
+ /* Generate a key pair and Add the spki to the request */
+ spki = GetSubjectPubKeyInfo(pair);
+ if (spki == NULL) {
+ printf("Could not create a Subject Public Key Info to add\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 12;
+ }
+ rv = CRMF_CertRequestSetTemplateField(certReq, crmfPublicKey, (void *)spki);
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+ if (rv != SECSuccess) {
+ printf("Could not add the public key to the template\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 13;
+ }
+
+ /* Set the requested isser Unique ID */
+ PK11_GenerateRandom(UIDbuf, sizeof UIDbuf);
+ CRMF_CertRequestSetTemplateField(certReq, crmfIssuerUID, (void *)&issuerUID);
+
+ /* Set the requested Subject Unique ID */
+ PK11_GenerateRandom(UIDbuf, sizeof UIDbuf);
+ CRMF_CertRequestSetTemplateField(certReq, crmfSubjectUID, (void *)&subjectUID);
+
+ /* Add extensions - XXX need to understand these magic numbers */
+ extInfo = GetExtensions();
+ CRMF_CertRequestSetTemplateField(certReq, crmfExtension, (void *)extInfo);
+ FreeExtInfo(extInfo);
+
+ /* get the recipient CA's cert */
+ caCert = CERT_FindCertByNickname(db, caCertName);
+ if (caCert == NULL) {
+ printf("Could not find the certificate for %s\n", caCertName);
+ CRMF_DestroyCertRequest(certReq);
+ return 50;
+ }
+ encKey = CRMF_CreateEncryptedKeyWithEncryptedValue(pair->privKey, caCert);
+ CERT_DestroyCertificate(caCert);
+ if (encKey == NULL) {
+ printf("Could not create Encrypted Key with Encrypted Value.\n");
+ return 14;
+ }
+ pkiArchOpt = CRMF_CreatePKIArchiveOptions(crmfEncryptedPrivateKey, encKey);
+ CRMF_DestroyEncryptedKey(encKey);
+ if (pkiArchOpt == NULL) {
+ printf("Could not create PKIArchiveOptions.\n");
+ return 15;
+ }
+ rv = CRMF_CertRequestSetPKIArchiveOptions(certReq, pkiArchOpt);
+ CRMF_DestroyPKIArchiveOptions(pkiArchOpt);
+ if (rv != SECSuccess) {
+ printf("Could not add the PKIArchiveControl to Cert Request.\n");
+ return 16;
+ }
+ pair->certReq = certReq;
+ return 0;
+}
+
+int
+Encode(CRMFCertReqMsg *inCertReq1, CRMFCertReqMsg *inCertReq2)
+{
+ PRFileDesc *fileDesc;
+ SECStatus rv;
+ int irv = 0;
+ CRMFCertReqMsg *msgArr[3];
+ char filePath[PATH_LEN];
+
+ PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, CRMF_FILE);
+ fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ if (fileDesc == NULL) {
+ printf("Could not open file %s\n", filePath);
+ irv = 14;
+ goto finish;
+ }
+ msgArr[0] = inCertReq1;
+ msgArr[1] = inCertReq2;
+ msgArr[2] = NULL;
+ rv = CRMF_EncodeCertReqMessages(msgArr, WriteItOut, (void *)fileDesc);
+ if (rv != SECSuccess) {
+ printf("An error occurred while encoding.\n");
+ irv = 15;
+ }
+finish:
+ PR_Close(fileDesc);
+ return irv;
+}
+
+int
+AddProofOfPossession(TESTKeyPair *pair,
+ CRMFPOPChoice inPOPChoice)
+{
+
+ switch (inPOPChoice) {
+ case crmfSignature:
+ CRMF_CertReqMsgSetSignaturePOP(pair->certReqMsg, pair->privKey,
+ pair->pubKey, NULL, NULL, &pwdata);
+ break;
+ case crmfRAVerified:
+ CRMF_CertReqMsgSetRAVerifiedPOP(pair->certReqMsg);
+ break;
+ case crmfKeyEncipherment:
+ CRMF_CertReqMsgSetKeyEnciphermentPOP(pair->certReqMsg,
+ crmfSubsequentMessage,
+ crmfChallengeResp, NULL);
+ break;
+ case crmfKeyAgreement: {
+ SECItem pendejo;
+ unsigned char lame[] = { 0xf0, 0x0f, 0xf0, 0x0f, 0xf0 };
+
+ pendejo.data = lame;
+ pendejo.len = 5;
+
+ CRMF_CertReqMsgSetKeyAgreementPOP(pair->certReqMsg, crmfThisMessage,
+ crmfNoSubseqMess, &pendejo);
+ } break;
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+int
+Decode(void)
+{
+ PRFileDesc *fileDesc;
+ CRMFCertReqMsg *certReqMsg;
+ CRMFCertRequest *certReq;
+ CRMFCertReqMessages *certReqMsgs;
+ SECStatus rv;
+ int numMsgs, i;
+ long lame;
+ CRMFGetValidity validity = { NULL, NULL };
+ SECItem item = { siBuffer, NULL, 0 };
+ char filePath[PATH_LEN];
+
+ PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, CRMF_FILE);
+ fileDesc = PR_Open(filePath, PR_RDONLY, 0644);
+ if (fileDesc == NULL) {
+ printf("Could not open file %s\n", filePath);
+ return 214;
+ }
+ rv = SECU_FileToItem(&item, fileDesc);
+ PR_Close(fileDesc);
+ if (rv != SECSuccess) {
+ return 215;
+ }
+
+ certReqMsgs = CRMF_CreateCertReqMessagesFromDER((char *)item.data, item.len);
+ if (certReqMsgs == NULL) {
+ printf("Error decoding CertReqMessages.\n");
+ return 202;
+ }
+ numMsgs = CRMF_CertReqMessagesGetNumMessages(certReqMsgs);
+ if (numMsgs <= 0) {
+ printf("WARNING: The DER contained %d messages.\n", numMsgs);
+ }
+ for (i = 0; i < numMsgs; i++) {
+ SECStatus rv;
+ printf("crmftest: Processing cert request %d\n", i);
+ certReqMsg = CRMF_CertReqMessagesGetCertReqMsgAtIndex(certReqMsgs, i);
+ if (certReqMsg == NULL) {
+ printf("ERROR: Could not access the message at index %d of %s\n",
+ i, filePath);
+ }
+ rv = CRMF_CertReqMsgGetID(certReqMsg, &lame);
+ if (rv) {
+ SECU_PrintError("crmftest", "CRMF_CertReqMsgGetID");
+ }
+ certReq = CRMF_CertReqMsgGetCertRequest(certReqMsg);
+ if (!certReq) {
+ SECU_PrintError("crmftest", "CRMF_CertReqMsgGetCertRequest");
+ }
+ rv = CRMF_CertRequestGetCertTemplateValidity(certReq, &validity);
+ if (rv) {
+ SECU_PrintError("crmftest", "CRMF_CertRequestGetCertTemplateValidity");
+ }
+ if (!validity.notBefore) {
+ /* We encoded a notBefore, so somthing's wrong if it's not here. */
+ printf("ERROR: Validity period notBefore date missing.\n");
+ }
+ /* XXX It's all parsed now. We probably should DO SOMETHING with it.
+ ** But nope. We just throw it all away.
+ ** Maybe this was intended to be no more than a decoder test.
+ */
+ CRMF_DestroyGetValidity(&validity);
+ CRMF_DestroyCertRequest(certReq);
+ CRMF_DestroyCertReqMsg(certReqMsg);
+ }
+ CRMF_DestroyCertReqMessages(certReqMsgs);
+ SECITEM_FreeItem(&item, PR_FALSE);
+ return 0;
+}
+
+int
+GetBitsFromFile(const char *filePath, SECItem *item)
+{
+ PRFileDesc *fileDesc;
+ SECStatus rv;
+
+ fileDesc = PR_Open(filePath, PR_RDONLY, 0644);
+ if (fileDesc == NULL) {
+ printf("Could not open file %s\n", filePath);
+ return 14;
+ }
+
+ rv = SECU_FileToItem(item, fileDesc);
+ PR_Close(fileDesc);
+
+ if (rv != SECSuccess) {
+ item->data = NULL;
+ item->len = 0;
+ return 15;
+ }
+ return 0;
+}
+
+int
+DecodeCMMFCertRepContent(char *derFile)
+{
+ CMMFCertRepContent *certRepContent;
+ int irv = 0;
+ SECItem fileBits = { siBuffer, NULL, 0 };
+
+ GetBitsFromFile(derFile, &fileBits);
+ if (fileBits.data == NULL) {
+ printf("Could not get bits from file %s\n", derFile);
+ return 304;
+ }
+ certRepContent = CMMF_CreateCertRepContentFromDER(db,
+ (char *)fileBits.data, fileBits.len);
+ if (certRepContent == NULL) {
+ printf("Error while decoding %s\n", derFile);
+ irv = 303;
+ } else {
+ /* That was fun. Now, let's throw it away! */
+ CMMF_DestroyCertRepContent(certRepContent);
+ }
+ SECITEM_FreeItem(&fileBits, PR_FALSE);
+ return irv;
+}
+
+int
+EncodeCMMFCertReply(const char *filePath,
+ CERTCertificate *cert,
+ CERTCertList *list)
+{
+ int rv = 0;
+ SECStatus srv;
+ PRFileDesc *fileDesc = NULL;
+ CMMFCertRepContent *certRepContent = NULL;
+ CMMFCertResponse *certResp = NULL;
+ CMMFCertResponse *certResponses[3];
+
+ certResp = CMMF_CreateCertResponse(0xff123);
+ CMMF_CertResponseSetPKIStatusInfoStatus(certResp, cmmfGranted);
+
+ CMMF_CertResponseSetCertificate(certResp, cert);
+
+ certResponses[0] = certResp;
+ certResponses[1] = NULL;
+ certResponses[2] = NULL;
+
+ certRepContent = CMMF_CreateCertRepContent();
+ CMMF_CertRepContentSetCertResponses(certRepContent, certResponses, 1);
+
+ CMMF_CertRepContentSetCAPubs(certRepContent, list);
+
+ fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ if (fileDesc == NULL) {
+ printf("Could not open file %s\n", filePath);
+ rv = 400;
+ goto finish;
+ }
+
+ srv = CMMF_EncodeCertRepContent(certRepContent, WriteItOut,
+ (void *)fileDesc);
+ PR_Close(fileDesc);
+ if (srv != SECSuccess) {
+ printf("CMMF_EncodeCertRepContent failed,\n");
+ rv = 401;
+ }
+finish:
+ if (certRepContent) {
+ CMMF_DestroyCertRepContent(certRepContent);
+ }
+ if (certResp) {
+ CMMF_DestroyCertResponse(certResp);
+ }
+ return rv;
+}
+
+/* Extract the public key from the cert whose nickname is given. */
+int
+extractPubKeyFromNamedCert(const char *nickname, SECKEYPublicKey **pPubKey)
+{
+ CERTCertificate *caCert = NULL;
+ SECKEYPublicKey *caPubKey = NULL;
+ int rv = 0;
+
+ caCert = CERT_FindCertByNickname(db, (char *)nickname);
+ if (caCert == NULL) {
+ printf("Could not get the certifcate for %s\n", caCertName);
+ rv = 411;
+ goto finish;
+ }
+ caPubKey = CERT_ExtractPublicKey(caCert);
+ if (caPubKey == NULL) {
+ printf("Could not extract the public from the "
+ "certificate for \n%s\n",
+ caCertName);
+ rv = 412;
+ }
+finish:
+ *pPubKey = caPubKey;
+ CERT_DestroyCertificate(caCert);
+ caCert = NULL;
+ return rv;
+}
+
+int
+EncodeCMMFRecoveryMessage(const char *filePath,
+ CERTCertificate *cert,
+ CERTCertList *list)
+{
+ SECKEYPublicKey *caPubKey = NULL;
+ SECKEYPrivateKey *privKey = NULL;
+ CMMFKeyRecRepContent *repContent = NULL;
+ PRFileDesc *fileDesc;
+ int rv = 0;
+ SECStatus srv;
+
+ /* Extract the public key from the cert whose nickname is given in
+ ** the -s option.
+ */
+ rv = extractPubKeyFromNamedCert(caCertName, &caPubKey);
+ if (rv)
+ goto finish;
+
+ repContent = CMMF_CreateKeyRecRepContent();
+ if (repContent == NULL) {
+ printf("Could not allocate a CMMFKeyRecRepContent structure\n");
+ rv = 407;
+ goto finish;
+ }
+ srv = CMMF_KeyRecRepContentSetPKIStatusInfoStatus(repContent,
+ cmmfGrantedWithMods);
+ if (srv != SECSuccess) {
+ printf("Error trying to set PKIStatusInfo for "
+ "CMMFKeyRecRepContent.\n");
+ rv = 406;
+ goto finish;
+ }
+ srv = CMMF_KeyRecRepContentSetNewSignCert(repContent, cert);
+ if (srv != SECSuccess) {
+ printf("Error trying to set the new signing certificate for "
+ "key recovery\n");
+ rv = 408;
+ goto finish;
+ }
+ srv = CMMF_KeyRecRepContentSetCACerts(repContent, list);
+ if (srv != SECSuccess) {
+ printf("Errory trying to add the list of CA certs to the "
+ "CMMFKeyRecRepContent structure.\n");
+ rv = 409;
+ goto finish;
+ }
+ privKey = PK11_FindKeyByAnyCert(cert, &pwdata);
+ if (privKey == NULL) {
+ printf("Could not get the private key associated with the\n"
+ "certificate %s\n",
+ personalCert);
+ rv = 410;
+ goto finish;
+ }
+
+ srv = CMMF_KeyRecRepContentSetCertifiedKeyPair(repContent, cert, privKey,
+ caPubKey);
+ if (srv != SECSuccess) {
+ printf("Could not set the Certified Key Pair\n");
+ rv = 413;
+ goto finish;
+ }
+ fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ if (fileDesc == NULL) {
+ printf("Could not open file %s\n", filePath);
+ rv = 414;
+ goto finish;
+ }
+
+ srv = CMMF_EncodeKeyRecRepContent(repContent, WriteItOut,
+ (void *)fileDesc);
+ PR_Close(fileDesc);
+ if (srv != SECSuccess) {
+ printf("CMMF_EncodeKeyRecRepContent failed\n");
+ rv = 415;
+ }
+finish:
+ if (privKey)
+ SECKEY_DestroyPrivateKey(privKey);
+ if (caPubKey)
+ SECKEY_DestroyPublicKey(caPubKey);
+ if (repContent)
+ CMMF_DestroyKeyRecRepContent(repContent);
+ return rv;
+}
+
+int
+decodeCMMFRecoveryMessage(const char *filePath)
+{
+ CMMFKeyRecRepContent *repContent = NULL;
+ int rv = 0;
+ SECItem fileBits = { siBuffer, NULL, 0 };
+
+ GetBitsFromFile(filePath, &fileBits);
+ if (!fileBits.len) {
+ rv = 451;
+ goto finish;
+ }
+ repContent =
+ CMMF_CreateKeyRecRepContentFromDER(db, (const char *)fileBits.data,
+ fileBits.len);
+ if (repContent == NULL) {
+ printf("ERROR: CMMF_CreateKeyRecRepContentFromDER failed on file:\n"
+ "\t%s\n",
+ filePath);
+ rv = 452;
+ }
+finish:
+ if (repContent) {
+ CMMF_DestroyKeyRecRepContent(repContent);
+ }
+ SECITEM_FreeItem(&fileBits, PR_FALSE);
+ return rv;
+}
+
+int
+DoCMMFStuff(void)
+{
+ CERTCertificate *cert = NULL;
+ CERTCertList *list = NULL;
+ int rv = 0;
+ char filePath[PATH_LEN];
+
+ /* Do common setup for the following steps.
+ */
+ PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, "CertRepContent.der");
+
+ cert = CERT_FindCertByNickname(db, personalCert);
+ if (cert == NULL) {
+ printf("Could not find the certificate for %s\n", personalCert);
+ rv = 416;
+ goto finish;
+ }
+ list = CERT_GetCertChainFromCert(cert, PR_Now(), certUsageEmailSigner);
+ if (list == NULL) {
+ printf("Could not find the certificate chain for %s\n", personalCert);
+ rv = 418;
+ goto finish;
+ }
+
+ /* a) Generate the CMMF response message, using a user cert named
+ ** by -p option, rather than a cert generated from the CRMF
+ ** request itself. The CMMF message is placed in
+ ** configdir/CertRepContent.der.
+ */
+ rv = EncodeCMMFCertReply(filePath, cert, list);
+ if (rv != 0) {
+ goto finish;
+ }
+
+ /* b) Decode the CMMF Cert granting message encoded just above,
+ ** found in configdir/CertRepContent.der.
+ ** This only tests the decoding. The decoded content is discarded.
+ */
+ rv = DecodeCMMFCertRepContent(filePath);
+ if (rv != 0) {
+ goto finish;
+ }
+
+ /* c) Generate a CMMF Key Excrow message
+ ** It takes the public and private keys for the cert identified
+ ** by -p nickname, and wraps them with a sym key that is in turn
+ ** wrapped with the pubkey in the CA cert, whose nickname is
+ ** given by the -s option.
+ ** Store the message in configdir/KeyRecRepContent.der
+ */
+ PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir,
+ "KeyRecRepContent.der");
+
+ rv = EncodeCMMFRecoveryMessage(filePath, cert, list);
+ if (rv)
+ goto finish;
+
+ /* d) Decode the CMMF Key Excrow message generated just above.
+ ** Get it from file configdir/KeyRecRepContent.der
+ ** This is just a decoder test. Results are discarded.
+ */
+
+ rv = decodeCMMFRecoveryMessage(filePath);
+
+finish:
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+ if (list) {
+ CERT_DestroyCertList(list);
+ }
+ return rv;
+}
+
+#define KNOWN_MESSAGE_LENGTH 20 /*160 bits*/
+
+int
+DoKeyRecovery(SECKEYPrivateKey *privKey)
+{
+#ifdef DOING_KEY_RECOVERY /* Doesn't compile yet. */
+ SECKEYPublicKey *pubKey;
+ PK11SlotInfo *slot;
+ unsigned char *ciphertext;
+ unsigned char *text_compared;
+ SECKEYPrivateKey *unwrappedPrivKey;
+ SECKEYPrivateKey *caPrivKey;
+ CMMFKeyRecRepContent *keyRecRep;
+ CMMFCertifiedKeyPair *certKeyPair;
+ CERTCertificate *caCert;
+ CERTCertificate *myCert;
+ SECKEYPublicKey *caPubKey;
+ PRFileDesc *fileDesc;
+ CK_ULONG max_bytes_encrypted;
+ CK_ULONG bytes_encrypted;
+ CK_ULONG bytes_compared;
+ CK_ULONG bytes_decrypted;
+ CK_RV crv;
+ CK_OBJECT_HANDLE id;
+ CK_MECHANISM mech = { CKM_INVALID_MECHANISM, NULL, 0 };
+ SECStatus rv;
+ SECItem fileBits;
+ SECItem nickname;
+ unsigned char plaintext[KNOWN_MESSAGE_LENGTH];
+ char filePath[PATH_LEN];
+ static const unsigned char known_message[] = { "Known Crypto Message" };
+
+ /*caCert = CERT_FindCertByNickname(db, caCertName);*/
+ myCert = CERT_FindCertByNickname(db, personalCert);
+ if (myCert == NULL) {
+ printf("Could not find the certificate for %s\n", personalCert);
+ return 700;
+ }
+ caCert = CERT_FindCertByNickname(db, recoveryEncrypter);
+ if (caCert == NULL) {
+ printf("Could not find the certificate for %s\n", recoveryEncrypter);
+ return 701;
+ }
+ caPubKey = CERT_ExtractPublicKey(caCert);
+ pubKey = SECKEY_ConvertToPublicKey(privKey);
+ max_bytes_encrypted = PK11_GetPrivateModulusLen(privKey);
+ slot = PK11_GetBestSlotWithAttributes(mapWrapKeyType(privKey->keyType),
+ CKF_ENCRYPT, 0, NULL);
+ id = PK11_ImportPublicKey(slot, pubKey, PR_FALSE);
+
+ switch (privKey->keyType) {
+ case rsaKey:
+ mech.mechanism = CKM_RSA_PKCS;
+ break;
+ case dsaKey:
+ mech.mechanism = CKM_DSA;
+ break;
+ case dhKey:
+ mech.mechanism = CKM_DH_PKCS_DERIVE;
+ break;
+ default:
+ printf("Bad Key type in key recovery.\n");
+ return 512;
+ }
+ PK11_EnterSlotMonitor(slot);
+ crv = PK11_GETTAB(slot)->C_EncryptInit(slot->session, &mech, id);
+ if (crv != CKR_OK) {
+ PK11_ExitSlotMonitor(slot);
+ PK11_FreeSlot(slot);
+ printf("C_EncryptInit failed in KeyRecovery\n");
+ return 500;
+ }
+ ciphertext = PORT_NewArray(unsigned char, max_bytes_encrypted);
+ if (ciphertext == NULL) {
+ PK11_ExitSlotMonitor(slot);
+ PK11_FreeSlot(slot);
+ printf("Could not allocate memory for ciphertext.\n");
+ return 501;
+ }
+ bytes_encrypted = max_bytes_encrypted;
+ crv = PK11_GETTAB(slot)->C_Encrypt(slot->session,
+ known_message,
+ KNOWN_MESSAGE_LENGTH,
+ ciphertext,
+ &bytes_encrypted);
+ PK11_ExitSlotMonitor(slot);
+ PK11_FreeSlot(slot);
+ if (crv != CKR_OK) {
+ PORT_Free(ciphertext);
+ return 502;
+ }
+ /* Always use the smaller of these two values . . . */
+ bytes_compared = (bytes_encrypted > KNOWN_MESSAGE_LENGTH)
+ ? KNOWN_MESSAGE_LENGTH
+ : bytes_encrypted;
+
+ /* If there was a failure, the plaintext */
+ /* goes at the end, therefore . . . */
+ text_compared = (bytes_encrypted > KNOWN_MESSAGE_LENGTH)
+ ? (ciphertext + bytes_encrypted -
+ KNOWN_MESSAGE_LENGTH)
+ : ciphertext;
+
+ keyRecRep = CMMF_CreateKeyRecRepContent();
+ if (keyRecRep == NULL) {
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ CMMF_DestroyKeyRecRepContent(keyRecRep);
+ printf("Could not allocate a CMMFKeyRecRepContent structre.\n");
+ return 503;
+ }
+ rv = CMMF_KeyRecRepContentSetPKIStatusInfoStatus(keyRecRep,
+ cmmfGranted);
+ if (rv != SECSuccess) {
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ CMMF_DestroyKeyRecRepContent(keyRecRep);
+ printf("Could not set the status for the KeyRecRepContent\n");
+ return 504;
+ }
+ /* The myCert here should correspond to the certificate corresponding
+ * to the private key, but for this test any certificate will do.
+ */
+ rv = CMMF_KeyRecRepContentSetCertifiedKeyPair(keyRecRep, myCert,
+ privKey, caPubKey);
+ if (rv != SECSuccess) {
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ CMMF_DestroyKeyRecRepContent(keyRecRep);
+ printf("Could not set the Certified Key Pair\n");
+ return 505;
+ }
+ PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir,
+ "KeyRecRepContent.der");
+ fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ if (fileDesc == NULL) {
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ CMMF_DestroyKeyRecRepContent(keyRecRep);
+ printf("Could not open file %s\n", filePath);
+ return 506;
+ }
+ rv = CMMF_EncodeKeyRecRepContent(keyRecRep, WriteItOut, fileDesc);
+ CMMF_DestroyKeyRecRepContent(keyRecRep);
+ PR_Close(fileDesc);
+
+ if (rv != SECSuccess) {
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ printf("Error while encoding CMMFKeyRecRepContent\n");
+ return 507;
+ }
+ GetBitsFromFile(filePath, &fileBits);
+ if (fileBits.data == NULL) {
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ printf("Could not get the bits from file %s\n", filePath);
+ return 508;
+ }
+ keyRecRep =
+ CMMF_CreateKeyRecRepContentFromDER(db, (const char *)fileBits.data,
+ fileBits.len);
+ if (keyRecRep == NULL) {
+ printf("Could not decode the KeyRecRepContent in file %s\n",
+ filePath);
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ return 509;
+ }
+ caPrivKey = PK11_FindKeyByAnyCert(caCert, &pwdata);
+ if (CMMF_KeyRecRepContentGetPKIStatusInfoStatus(keyRecRep) !=
+ cmmfGranted) {
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ CMMF_DestroyKeyRecRepContent(keyRecRep);
+ printf("A bad status came back with the "
+ "KeyRecRepContent structure\n");
+ return 510;
+ }
+
+#define NICKNAME "Key Recovery Test Key"
+ nickname.data = (unsigned char *)NICKNAME;
+ nickname.len = PORT_Strlen(NICKNAME);
+
+ certKeyPair = CMMF_KeyRecRepContentGetCertKeyAtIndex(keyRecRep, 0);
+ CMMF_DestroyKeyRecRepContent(keyRecRep);
+ rv = CMMF_CertifiedKeyPairUnwrapPrivKey(certKeyPair,
+ caPrivKey,
+ &nickname,
+ PK11_GetInternalKeySlot(),
+ db,
+ &unwrappedPrivKey, &pwdata);
+ CMMF_DestroyCertifiedKeyPair(certKeyPair);
+ if (rv != SECSuccess) {
+ printf("Unwrapping the private key failed.\n");
+ return 511;
+ }
+ /*Now let's try to decrypt the ciphertext with the "recovered" key*/
+ PK11_EnterSlotMonitor(slot);
+ crv =
+ PK11_GETTAB(slot)->C_DecryptInit(unwrappedPrivKey->pkcs11Slot->session,
+ &mech,
+ unwrappedPrivKey->pkcs11ID);
+ if (crv != CKR_OK) {
+ PK11_ExitSlotMonitor(slot);
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ printf("Decrypting with the recovered key failed.\n");
+ return 513;
+ }
+ bytes_decrypted = KNOWN_MESSAGE_LENGTH;
+ crv = PK11_GETTAB(slot)->C_Decrypt(unwrappedPrivKey->pkcs11Slot->session,
+ ciphertext,
+ bytes_encrypted, plaintext,
+ &bytes_decrypted);
+ SECKEY_DestroyPrivateKey(unwrappedPrivKey);
+ PK11_ExitSlotMonitor(slot);
+ PORT_Free(ciphertext);
+ if (crv != CKR_OK) {
+ PK11_FreeSlot(slot);
+ printf("Decrypting the ciphertext with recovered key failed.\n");
+ return 514;
+ }
+ if ((bytes_decrypted != KNOWN_MESSAGE_LENGTH) ||
+ (PORT_Memcmp(plaintext, known_message, KNOWN_MESSAGE_LENGTH) != 0)) {
+ PK11_FreeSlot(slot);
+ printf("The recovered plaintext does not equal the known message:\n"
+ "\tKnown message: %s\n"
+ "\tRecovered plaintext: %s\n",
+ known_message, plaintext);
+ return 515;
+ }
+#endif
+ return 0;
+}
+
+int
+DoChallengeResponse(SECKEYPrivateKey *privKey,
+ SECKEYPublicKey *pubKey)
+{
+ CMMFPOPODecKeyChallContent *chalContent = NULL;
+ CMMFPOPODecKeyRespContent *respContent = NULL;
+ CERTCertificate *myCert = NULL;
+ CERTGeneralName *myGenName = NULL;
+ PLArenaPool *poolp = NULL;
+ PRFileDesc *fileDesc;
+ SECItem *publicValue;
+ SECItem *keyID;
+ SECKEYPrivateKey *foundPrivKey;
+ long *randomNums;
+ int numChallengesFound = 0;
+ int numChallengesSet = 1;
+ int i;
+ long retrieved;
+ SECStatus rv;
+ SECItem DecKeyChallBits;
+ char filePath[PATH_LEN];
+
+ chalContent = CMMF_CreatePOPODecKeyChallContent();
+ myCert = CERT_FindCertByNickname(db, personalCert);
+ if (myCert == NULL) {
+ printf("Could not find the certificate for %s\n", personalCert);
+ return 900;
+ }
+ poolp = PORT_NewArena(1024);
+ if (poolp == NULL) {
+ printf("Could no allocate a new arena in DoChallengeResponse\n");
+ return 901;
+ }
+ myGenName = CERT_GetCertificateNames(myCert, poolp);
+ if (myGenName == NULL) {
+ printf("Could not get the general names for %s certificate\n",
+ personalCert);
+ return 902;
+ }
+ randomNums = PORT_ArenaNewArray(poolp, long, numChallengesSet);
+ PK11_GenerateRandom((unsigned char *)randomNums,
+ numChallengesSet * sizeof(long));
+ for (i = 0; i < numChallengesSet; i++) {
+ rv = CMMF_POPODecKeyChallContentSetNextChallenge(chalContent,
+ randomNums[i],
+ myGenName,
+ pubKey,
+ &pwdata);
+ if (rv != SECSuccess) {
+ printf("Could not set the challenge in DoChallengeResponse\n");
+ return 903;
+ }
+ }
+ PR_snprintf(filePath, PATH_LEN, "%s/POPODecKeyChallContent.der",
+ configdir);
+ fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ if (fileDesc == NULL) {
+ printf("Could not open file %s\n", filePath);
+ return 904;
+ }
+ rv = CMMF_EncodePOPODecKeyChallContent(chalContent, WriteItOut,
+ (void *)fileDesc);
+ PR_Close(fileDesc);
+ CMMF_DestroyPOPODecKeyChallContent(chalContent);
+ if (rv != SECSuccess) {
+ printf("Could not encode the POPODecKeyChallContent.\n");
+ return 905;
+ }
+ GetBitsFromFile(filePath, &DecKeyChallBits);
+ chalContent = CMMF_CreatePOPODecKeyChallContentFromDER((const char *)DecKeyChallBits.data, DecKeyChallBits.len);
+ SECITEM_FreeItem(&DecKeyChallBits, PR_FALSE);
+ if (chalContent == NULL) {
+ printf("Could not create the POPODecKeyChallContent from DER\n");
+ return 906;
+ }
+ numChallengesFound =
+ CMMF_POPODecKeyChallContentGetNumChallenges(chalContent);
+ if (numChallengesFound != numChallengesSet) {
+ printf("Number of Challenges Found (%d) does not equal the number "
+ "set (%d)\n",
+ numChallengesFound, numChallengesSet);
+ return 907;
+ }
+ for (i = 0; i < numChallengesSet; i++) {
+ publicValue = CMMF_POPODecKeyChallContentGetPublicValue(chalContent, i);
+ if (publicValue == NULL) {
+ printf("Could not get the public value for challenge at index %d\n",
+ i);
+ return 908;
+ }
+ keyID = PK11_MakeIDFromPubKey(publicValue);
+ if (keyID == NULL) {
+ printf("Could not make the keyID from the public value\n");
+ return 909;
+ }
+ foundPrivKey = PK11_FindKeyByKeyID(privKey->pkcs11Slot, keyID, &pwdata);
+ if (foundPrivKey == NULL) {
+ printf("Could not find the private key corresponding to the public"
+ " value.\n");
+ return 910;
+ }
+ rv = CMMF_POPODecKeyChallContDecryptChallenge(chalContent, i,
+ foundPrivKey);
+ if (rv != SECSuccess) {
+ printf("Could not decrypt the challenge at index %d\n", i);
+ return 911;
+ }
+ rv = CMMF_POPODecKeyChallContentGetRandomNumber(chalContent, i,
+ &retrieved);
+ if (rv != SECSuccess) {
+ printf("Could not get the random number from the challenge at "
+ "index %d\n",
+ i);
+ return 912;
+ }
+ if (retrieved != randomNums[i]) {
+ printf("Retrieved the number (%ld), expected (%ld)\n", retrieved,
+ randomNums[i]);
+ return 913;
+ }
+ }
+ CMMF_DestroyPOPODecKeyChallContent(chalContent);
+ PR_snprintf(filePath, PATH_LEN, "%s/POPODecKeyRespContent.der",
+ configdir);
+ fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ if (fileDesc == NULL) {
+ printf("Could not open file %s\n", filePath);
+ return 914;
+ }
+ rv = CMMF_EncodePOPODecKeyRespContent(randomNums, numChallengesSet,
+ WriteItOut, fileDesc);
+ PR_Close(fileDesc);
+ if (rv != 0) {
+ printf("Could not encode the POPODecKeyRespContent\n");
+ return 915;
+ }
+ GetBitsFromFile(filePath, &DecKeyChallBits);
+ respContent =
+ CMMF_CreatePOPODecKeyRespContentFromDER((const char *)DecKeyChallBits.data,
+ DecKeyChallBits.len);
+ if (respContent == NULL) {
+ printf("Could not decode the contents of the file %s\n", filePath);
+ return 916;
+ }
+ numChallengesFound =
+ CMMF_POPODecKeyRespContentGetNumResponses(respContent);
+ if (numChallengesFound != numChallengesSet) {
+ printf("Number of responses found (%d) does not match the number "
+ "of challenges set (%d)\n",
+ numChallengesFound, numChallengesSet);
+ return 917;
+ }
+ for (i = 0; i < numChallengesSet; i++) {
+ rv = CMMF_POPODecKeyRespContentGetResponse(respContent, i, &retrieved);
+ if (rv != SECSuccess) {
+ printf("Could not retrieve the response at index %d\n", i);
+ return 918;
+ }
+ if (retrieved != randomNums[i]) {
+ printf("Retrieved the number (%ld), expected (%ld)\n", retrieved,
+ randomNums[i]);
+ return 919;
+ }
+ }
+ CMMF_DestroyPOPODecKeyRespContent(respContent);
+ return 0;
+}
+
+int
+MakeCertRequest(TESTKeyPair *pair, CRMFPOPChoice inPOPChoice, long inRequestID)
+{
+ int irv;
+
+ /* Generate a key pair and a cert request for it. */
+ irv = CreateCertRequest(pair, inRequestID);
+ if (irv != 0 || pair->certReq == NULL) {
+ goto loser;
+ }
+
+ pair->certReqMsg = CRMF_CreateCertReqMsg();
+ if (!pair->certReqMsg) {
+ irv = 999;
+ goto loser;
+ }
+ /* copy certReq into certReqMsg */
+ CRMF_CertReqMsgSetCertRequest(pair->certReqMsg, pair->certReq);
+ irv = AddProofOfPossession(pair, inPOPChoice);
+loser:
+ return irv;
+}
+
+int
+DestroyPairReqAndMsg(TESTKeyPair *pair)
+{
+ SECStatus rv = SECSuccess;
+ int irv = 0;
+
+ if (pair->certReq) {
+ rv = CRMF_DestroyCertRequest(pair->certReq);
+ pair->certReq = NULL;
+ if (rv != SECSuccess) {
+ printf("Error when destroying cert request.\n");
+ irv = 100;
+ }
+ }
+ if (pair->certReqMsg) {
+ rv = CRMF_DestroyCertReqMsg(pair->certReqMsg);
+ pair->certReqMsg = NULL;
+ if (rv != SECSuccess) {
+ printf("Error when destroying cert request msg.\n");
+ if (!irv)
+ irv = 101;
+ }
+ }
+ return irv;
+}
+
+int
+DestroyPair(TESTKeyPair *pair)
+{
+ int irv = 0;
+
+ if (pair->pubKey) {
+ SECKEY_DestroyPublicKey(pair->pubKey);
+ pair->pubKey = NULL;
+ }
+ if (pair->privKey) {
+ SECKEY_DestroyPrivateKey(pair->privKey);
+ pair->privKey = NULL;
+ }
+ DestroyPairReqAndMsg(pair);
+ return irv;
+}
+
+int
+DoCRMFRequest(TESTKeyPair *signPair, TESTKeyPair *cryptPair)
+{
+ int irv, tirv = 0;
+
+ /* Generate a key pair and a cert request for it. */
+ irv = MakeCertRequest(signPair, crmfSignature, 0x0f020304);
+ if (irv != 0 || signPair->certReq == NULL) {
+ goto loser;
+ }
+
+ if (!doingDSA) {
+ irv = MakeCertRequest(cryptPair, crmfKeyAgreement, 0x0f050607);
+ if (irv != 0 || cryptPair->certReq == NULL) {
+ goto loser;
+ }
+ }
+
+ /* encode the cert request messages into a unified request message.
+ ** leave it in a file with a fixed name. :(
+ */
+ irv = Encode(signPair->certReqMsg, cryptPair->certReqMsg);
+
+loser:
+ if (signPair->certReq) {
+ tirv = DestroyPairReqAndMsg(signPair);
+ if (tirv && !irv)
+ irv = tirv;
+ }
+ if (cryptPair->certReq) {
+ tirv = DestroyPairReqAndMsg(cryptPair);
+ if (tirv && !irv)
+ irv = tirv;
+ }
+ return irv;
+}
+
+void
+Usage(void)
+{
+ printf("Usage:\n"
+ "\tcrmftest -d [Database Directory] -p [Personal Cert]\n"
+ "\t -e [Encrypter] -s [CA Certificate] [-P password]\n\n"
+ "\t [crmf] [dsa] [decode] [cmmf] [recover] [challenge]\n"
+ "\t [-f password_file]\n"
+ "Database Directory\n"
+ "\tThis is the directory where the key3.db, cert7.db, and\n"
+ "\tsecmod.db files are located. This is also the directory\n"
+ "\twhere the program will place CRMF/CMMF der files\n"
+ "Personal Cert\n"
+ "\tThis is the certificate that already exists in the cert\n"
+ "\tdatabase to use while encoding the response. The private\n"
+ "\tkey associated with the certificate must also exist in the\n"
+ "\tkey database.\n"
+ "Encrypter\n"
+ "\tThis is the certificate to use when encrypting the the \n"
+ "\tkey recovery response. The private key for this cert\n"
+ "\tmust also be present in the key database.\n"
+ "CA Certificate\n"
+ "\tThis is the nickname of the certificate to use as the\n"
+ "\tCA when doing all of the encoding.\n");
+}
+
+#define TEST_MAKE_CRMF_REQ 0x0001
+#define TEST_USE_DSA 0x0002
+#define TEST_DECODE_CRMF_REQ 0x0004
+#define TEST_DO_CMMF_STUFF 0x0008
+#define TEST_KEY_RECOVERY 0x0010
+#define TEST_CHALLENGE_RESPONSE 0x0020
+
+SECStatus
+parsePositionalParam(const char *arg, PRUint32 *flags)
+{
+ if (!strcmp(arg, "crmf")) {
+ *flags |= TEST_MAKE_CRMF_REQ;
+ } else if (!strcmp(arg, "dsa")) {
+ *flags |= TEST_MAKE_CRMF_REQ | TEST_USE_DSA;
+ doingDSA = PR_TRUE;
+ } else if (!strcmp(arg, "decode")) {
+ *flags |= TEST_DECODE_CRMF_REQ;
+ } else if (!strcmp(arg, "cmmf")) {
+ *flags |= TEST_DO_CMMF_STUFF;
+ } else if (!strcmp(arg, "recover")) {
+ *flags |= TEST_KEY_RECOVERY;
+ } else if (!strcmp(arg, "challenge")) {
+ *flags |= TEST_CHALLENGE_RESPONSE;
+ } else {
+ printf("unknown positional paremeter: %s\n", arg);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+/* it's not clear, in some cases, whether the desired key is from
+** the sign pair or the crypt pair, so we're guessing in some places.
+** This define serves to remind us of the places where we're guessing.
+*/
+#define WHICH_KEY cryptPair
+
+int
+main(int argc, char **argv)
+{
+ TESTKeyPair signPair, cryptPair;
+ PLOptState *optstate;
+ PLOptStatus status;
+ char *password = NULL;
+ char *pwfile = NULL;
+ int irv = 0;
+ PRUint32 flags = 0;
+ SECStatus rv;
+ PRBool nssInit = PR_FALSE;
+
+ memset(&signPair, 0, sizeof signPair);
+ memset(&cryptPair, 0, sizeof cryptPair);
+ printf("\ncrmftest v1.0\n");
+ optstate = PL_CreateOptState(argc, argv, "d:p:e:s:P:f:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'd':
+ configdir = PORT_Strdup(optstate->value);
+ rv = NSS_Init(configdir);
+ if (rv != SECSuccess) {
+ printf("NSS_Init (-d) failed\n");
+ return 101;
+ }
+ nssInit = PR_TRUE;
+ break;
+ case 'p':
+ personalCert = PORT_Strdup(optstate->value);
+ if (personalCert == NULL) {
+ printf("-p failed\n");
+ return 603;
+ }
+ break;
+ case 'e':
+ recoveryEncrypter = PORT_Strdup(optstate->value);
+ if (recoveryEncrypter == NULL) {
+ printf("-e failed\n");
+ return 602;
+ }
+ break;
+ case 's':
+ caCertName = PORT_Strdup(optstate->value);
+ if (caCertName == NULL) {
+ printf("-s failed\n");
+ return 604;
+ }
+ break;
+ case 'P':
+ password = PORT_Strdup(optstate->value);
+ if (password == NULL) {
+ printf("-P failed\n");
+ return 606;
+ }
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = password;
+ break;
+ case 'f':
+ pwfile = PORT_Strdup(optstate->value);
+ if (pwfile == NULL) {
+ printf("-f failed\n");
+ return 607;
+ }
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = pwfile;
+ break;
+ case 0: /* positional parameter */
+ rv = parsePositionalParam(optstate->value, &flags);
+ if (rv) {
+ printf("bad positional parameter.\n");
+ return 605;
+ }
+ break;
+ default:
+ Usage();
+ return 601;
+ }
+ }
+ PL_DestroyOptState(optstate);
+ if (status == PL_OPT_BAD || !nssInit) {
+ Usage();
+ return 600;
+ }
+ if (!flags)
+ flags = ~TEST_USE_DSA;
+ db = CERT_GetDefaultCertDB();
+ InitPKCS11();
+
+ if (flags & TEST_MAKE_CRMF_REQ) {
+ printf("Generating CRMF request\n");
+ irv = DoCRMFRequest(&signPair, &cryptPair);
+ if (irv)
+ goto loser;
+ }
+
+ if (flags & TEST_DECODE_CRMF_REQ) {
+ printf("Decoding CRMF request\n");
+ irv = Decode();
+ if (irv != 0) {
+ printf("Error while decoding\n");
+ goto loser;
+ }
+ }
+
+ if (flags & TEST_DO_CMMF_STUFF) {
+ printf("Doing CMMF Stuff\n");
+ if ((irv = DoCMMFStuff()) != 0) {
+ printf("CMMF tests failed.\n");
+ goto loser;
+ }
+ }
+
+ if (flags & TEST_KEY_RECOVERY) {
+ /* Requires some other options be set.
+ ** Once we know exactly what hey are, test for them here.
+ */
+ printf("Doing Key Recovery\n");
+ irv = DoKeyRecovery(WHICH_KEY.privKey);
+ if (irv != 0) {
+ printf("Error doing key recovery\n");
+ goto loser;
+ }
+ }
+
+ if (flags & TEST_CHALLENGE_RESPONSE) {
+ printf("Doing Challenge / Response\n");
+ irv = DoChallengeResponse(WHICH_KEY.privKey, WHICH_KEY.pubKey);
+ if (irv != 0) {
+ printf("Error doing challenge-response\n");
+ goto loser;
+ }
+ }
+ printf("Exiting successfully!!!\n\n");
+ irv = 0;
+
+loser:
+ DestroyPair(&signPair);
+ DestroyPair(&cryptPair);
+ rv = NSS_Shutdown();
+ if (rv) {
+ printf("NSS_Shutdown did not shutdown cleanly!\n");
+ }
+ PORT_Free(configdir);
+ if (irv)
+ printf("crmftest returning %d\n", irv);
+ return irv;
+}
diff --git a/security/nss/cmd/dbck/Makefile b/security/nss/cmd/dbck/Makefile
new file mode 100644
index 000000000..ea1d2f49a
--- /dev/null
+++ b/security/nss/cmd/dbck/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+INCLUDES += -I ../../lib/softoken
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/dbck/dbck.c b/security/nss/cmd/dbck/dbck.c
new file mode 100644
index 000000000..6791a0d19
--- /dev/null
+++ b/security/nss/cmd/dbck/dbck.c
@@ -0,0 +1,1350 @@
+/* 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/. */
+
+/*
+** dbck.c
+**
+** utility for fixing corrupt cert databases
+**
+*/
+#include <stdio.h>
+#include <string.h>
+
+#include "secutil.h"
+#include "cdbhdl.h"
+#include "certdb.h"
+#include "cert.h"
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+#include "pcert.h"
+#include "nss.h"
+
+static char *progName;
+
+/* placeholders for pointer error types */
+static void *WrongEntry;
+static void *NoNickname;
+static void *NoSMime;
+
+typedef enum {
+ /* 0*/ NoSubjectForCert = 0,
+ /* 1*/ SubjectHasNoKeyForCert,
+ /* 2*/ NoNicknameOrSMimeForSubject,
+ /* 3*/ WrongNicknameForSubject,
+ /* 4*/ NoNicknameEntry,
+ /* 5*/ WrongSMimeForSubject,
+ /* 6*/ NoSMimeEntry,
+ /* 7*/ NoSubjectForNickname,
+ /* 8*/ NoSubjectForSMime,
+ /* 9*/ NicknameAndSMimeEntries,
+ NUM_ERROR_TYPES
+} dbErrorType;
+
+static char *dbErrorString[NUM_ERROR_TYPES] = {
+ /* 0*/ "<CERT ENTRY>\nDid not find a subject entry for this certificate.",
+ /* 1*/ "<SUBJECT ENTRY>\nSubject has certKey which is not in db.",
+ /* 2*/ "<SUBJECT ENTRY>\nSubject does not have a nickname or email address.",
+ /* 3*/ "<SUBJECT ENTRY>\nUsing this subject's nickname, found a nickname entry for a different subject.",
+ /* 4*/ "<SUBJECT ENTRY>\nDid not find a nickname entry for this subject.",
+ /* 5*/ "<SUBJECT ENTRY>\nUsing this subject's email, found an S/MIME entry for a different subject.",
+ /* 6*/ "<SUBJECT ENTRY>\nDid not find an S/MIME entry for this subject.",
+ /* 7*/ "<NICKNAME ENTRY>\nDid not find a subject entry for this nickname.",
+ /* 8*/ "<S/MIME ENTRY>\nDid not find a subject entry for this S/MIME profile.",
+};
+
+static char *errResult[NUM_ERROR_TYPES] = {
+ "Certificate entries that had no subject entry.",
+ "Subject entries with no corresponding Certificate entries.",
+ "Subject entries that had no nickname or S/MIME entries.",
+ "Redundant nicknames (subjects with the same nickname).",
+ "Subject entries that had no nickname entry.",
+ "Redundant email addresses (subjects with the same email address).",
+ "Subject entries that had no S/MIME entry.",
+ "Nickname entries that had no subject entry.",
+ "S/MIME entries that had no subject entry.",
+ "Subject entries with BOTH nickname and S/MIME entries."
+};
+
+enum {
+ GOBOTH = 0,
+ GORIGHT,
+ GOLEFT
+};
+
+typedef struct
+{
+ PRBool verbose;
+ PRBool dograph;
+ PRFileDesc *out;
+ PRFileDesc *graphfile;
+ int dbErrors[NUM_ERROR_TYPES];
+} dbDebugInfo;
+
+struct certDBEntryListNodeStr {
+ PRCList link;
+ certDBEntry entry;
+ void *appData;
+};
+typedef struct certDBEntryListNodeStr certDBEntryListNode;
+
+/*
+ * A list node for a cert db entry. The index is a unique identifier
+ * to use for creating generic maps of a db. This struct handles
+ * the cert, nickname, and smime db entry types, as all three have a
+ * single handle to a subject entry.
+ * This structure is pointed to by certDBEntryListNode->appData.
+ */
+typedef struct
+{
+ PLArenaPool *arena;
+ int index;
+ certDBEntryListNode *pSubject;
+} certDBEntryMap;
+
+/*
+ * Subject entry is special case, it has bidirectional handles. One
+ * subject entry can point to several certs (using the same DN), and
+ * a nickname and/or smime entry.
+ * This structure is pointed to by certDBEntryListNode->appData.
+ */
+typedef struct
+{
+ PLArenaPool *arena;
+ int index;
+ int numCerts;
+ certDBEntryListNode **pCerts;
+ certDBEntryListNode *pNickname;
+ certDBEntryListNode *pSMime;
+} certDBSubjectEntryMap;
+
+/*
+ * A map of a certdb.
+ */
+typedef struct
+{
+ int numCerts;
+ int numSubjects;
+ int numNicknames;
+ int numSMime;
+ int numRevocation;
+ certDBEntryListNode certs; /* pointer to head of cert list */
+ certDBEntryListNode subjects; /* pointer to head of subject list */
+ certDBEntryListNode nicknames; /* pointer to head of nickname list */
+ certDBEntryListNode smime; /* pointer to head of smime list */
+ certDBEntryListNode revocation; /* pointer to head of revocation list */
+} certDBArray;
+
+/* Cast list to the base element, a certDBEntryListNode. */
+#define LISTNODE_CAST(node) \
+ ((certDBEntryListNode *)(node))
+
+static void
+Usage(char *progName)
+{
+#define FPS fprintf(stderr,
+ FPS "Type %s -H for more detailed descriptions\n", progName);
+ FPS "Usage: %s -D [-d certdir] [-m] [-v [-f dumpfile]]\n",
+ progName);
+#ifdef DORECOVER
+ FPS " %s -R -o newdbname [-d certdir] [-aprsx] [-v [-f dumpfile]]\n",
+ progName);
+#endif
+ exit(-1);
+}
+
+static void
+LongUsage(char *progName)
+{
+ FPS "%-15s Display this help message.\n",
+ "-H");
+ FPS "%-15s Dump analysis. No changes will be made to the database.\n",
+ "-D");
+ FPS "%-15s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-15s Put database graph in ./mailfile (default is stdout).\n",
+ " -m");
+ FPS "%-15s Verbose mode. Dumps the entire contents of your cert8.db.\n",
+ " -v");
+ FPS "%-15s File to dump verbose output into. (default is stdout)\n",
+ " -f dumpfile");
+#ifdef DORECOVER
+ FPS "%-15s Repair the database. The program will look for broken\n",
+ "-R");
+ FPS "%-15s dependencies between subject entries and certificates,\n",
+ "");
+ FPS "%-15s between nickname entries and subjects, and between SMIME\n",
+ "");
+ FPS "%-15s profiles and subjects. Any duplicate entries will be\n",
+ "");
+ FPS "%-15s removed, any missing entries will be created.\n",
+ "");
+ FPS "%-15s File to store new database in (default is new_cert8.db)\n",
+ " -o newdbname");
+ FPS "%-15s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-15s Prompt before removing any certificates.\n",
+ " -p");
+ FPS "%-15s Keep all possible certificates. Only remove certificates\n",
+ " -a");
+ FPS "%-15s which prevent creation of a consistent database. Thus any\n",
+ "");
+ FPS "%-15s expired or redundant entries will be kept.\n",
+ "");
+ FPS "%-15s Keep redundant nickname/email entries. It is possible\n",
+ " -r");
+ FPS "%-15s only one such entry will be usable.\n",
+ "");
+ FPS "%-15s Don't require an S/MIME profile in order to keep an S/MIME\n",
+ " -s");
+ FPS "%-15s cert. An empty profile will be created.\n",
+ "");
+ FPS "%-15s Keep expired certificates.\n",
+ " -x");
+ FPS "%-15s Verbose mode - report all activity while recovering db.\n",
+ " -v");
+ FPS "%-15s File to dump verbose output into.\n",
+ " -f dumpfile");
+ FPS "\n");
+#endif
+ exit(-1);
+#undef FPS
+}
+
+/*******************************************************************
+ *
+ * Functions for dbck.
+ *
+ ******************************************************************/
+
+void
+printHexString(PRFileDesc *out, SECItem *hexval)
+{
+ unsigned int i;
+ for (i = 0; i < hexval->len; i++) {
+ if (i != hexval->len - 1) {
+ PR_fprintf(out, "%02x:", hexval->data[i]);
+ } else {
+ PR_fprintf(out, "%02x", hexval->data[i]);
+ }
+ }
+ PR_fprintf(out, "\n");
+}
+
+SECStatus
+dumpCertificate(CERTCertificate *cert, int num, PRFileDesc *outfile)
+{
+ int userCert = 0;
+ CERTCertTrust *trust = cert->trust;
+ userCert = (SEC_GET_TRUST_FLAGS(trust, trustSSL) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustEmail) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustObjectSigning) & CERTDB_USER);
+ if (num >= 0) {
+ PR_fprintf(outfile, "Certificate: %3d\n", num);
+ } else {
+ PR_fprintf(outfile, "Certificate:\n");
+ }
+ PR_fprintf(outfile, "----------------\n");
+ if (userCert)
+ PR_fprintf(outfile, "(User Cert)\n");
+ PR_fprintf(outfile, "## SUBJECT: %s\n", cert->subjectName);
+ PR_fprintf(outfile, "## ISSUER: %s\n", cert->issuerName);
+ PR_fprintf(outfile, "## SERIAL NUMBER: ");
+ printHexString(outfile, &cert->serialNumber);
+ { /* XXX should be separate function. */
+ PRTime timeBefore, timeAfter;
+ PRExplodedTime beforePrintable, afterPrintable;
+ char *beforestr, *afterstr;
+ DER_DecodeTimeChoice(&timeBefore, &cert->validity.notBefore);
+ DER_DecodeTimeChoice(&timeAfter, &cert->validity.notAfter);
+ PR_ExplodeTime(timeBefore, PR_GMTParameters, &beforePrintable);
+ PR_ExplodeTime(timeAfter, PR_GMTParameters, &afterPrintable);
+ beforestr = PORT_Alloc(100);
+ afterstr = PORT_Alloc(100);
+ PR_FormatTime(beforestr, 100, "%a %b %d %H:%M:%S %Y", &beforePrintable);
+ PR_FormatTime(afterstr, 100, "%a %b %d %H:%M:%S %Y", &afterPrintable);
+ PR_fprintf(outfile, "## VALIDITY: %s to %s\n", beforestr, afterstr);
+ }
+ PR_fprintf(outfile, "\n");
+ return SECSuccess;
+}
+
+SECStatus
+dumpCertEntry(certDBEntryCert *entry, int num, PRFileDesc *outfile)
+{
+#if 0
+ NSSLOWCERTCertificate *cert;
+ /* should we check for existing duplicates? */
+ cert = nsslowcert_DecodeDERCertificate(&entry->cert.derCert,
+ entry->cert.nickname);
+#else
+ CERTCertificate *cert;
+ cert = CERT_DecodeDERCertificate(&entry->derCert, PR_FALSE, NULL);
+#endif
+ if (!cert) {
+ fprintf(stderr, "Failed to decode certificate.\n");
+ return SECFailure;
+ }
+ cert->trust = (CERTCertTrust *)&entry->trust;
+ dumpCertificate(cert, num, outfile);
+ CERT_DestroyCertificate(cert);
+ return SECSuccess;
+}
+
+SECStatus
+dumpSubjectEntry(certDBEntrySubject *entry, int num, PRFileDesc *outfile)
+{
+ char *subjectName = CERT_DerNameToAscii(&entry->derSubject);
+
+ PR_fprintf(outfile, "Subject: %3d\n", num);
+ PR_fprintf(outfile, "------------\n");
+ PR_fprintf(outfile, "## %s\n", subjectName);
+ if (entry->nickname)
+ PR_fprintf(outfile, "## Subject nickname: %s\n", entry->nickname);
+ if (entry->emailAddrs) {
+ unsigned int n;
+ for (n = 0; n < entry->nemailAddrs && entry->emailAddrs[n]; ++n) {
+ char *emailAddr = entry->emailAddrs[n];
+ if (emailAddr[0]) {
+ PR_fprintf(outfile, "## Subject email address: %s\n",
+ emailAddr);
+ }
+ }
+ }
+ PR_fprintf(outfile, "## This subject has %d cert(s).\n", entry->ncerts);
+ PR_fprintf(outfile, "\n");
+ PORT_Free(subjectName);
+ return SECSuccess;
+}
+
+SECStatus
+dumpNicknameEntry(certDBEntryNickname *entry, int num, PRFileDesc *outfile)
+{
+ PR_fprintf(outfile, "Nickname: %3d\n", num);
+ PR_fprintf(outfile, "-------------\n");
+ PR_fprintf(outfile, "## \"%s\"\n\n", entry->nickname);
+ return SECSuccess;
+}
+
+SECStatus
+dumpSMimeEntry(certDBEntrySMime *entry, int num, PRFileDesc *outfile)
+{
+ PR_fprintf(outfile, "S/MIME Profile: %3d\n", num);
+ PR_fprintf(outfile, "-------------------\n");
+ PR_fprintf(outfile, "## \"%s\"\n", entry->emailAddr);
+#ifdef OLDWAY
+ PR_fprintf(outfile, "## OPTIONS: ");
+ printHexString(outfile, &entry->smimeOptions);
+ PR_fprintf(outfile, "## TIMESTAMP: ");
+ printHexString(outfile, &entry->optionsDate);
+#else
+ SECU_PrintAny(stdout, &entry->smimeOptions, "## OPTIONS ", 0);
+ fflush(stdout);
+ if (entry->optionsDate.len && entry->optionsDate.data)
+ PR_fprintf(outfile, "## TIMESTAMP: %.*s\n",
+ entry->optionsDate.len, entry->optionsDate.data);
+#endif
+ PR_fprintf(outfile, "\n");
+ return SECSuccess;
+}
+
+SECStatus
+mapCertEntries(certDBArray *dbArray)
+{
+ certDBEntryCert *certEntry;
+ certDBEntrySubject *subjectEntry;
+ certDBEntryListNode *certNode, *subjNode;
+ certDBSubjectEntryMap *smap;
+ certDBEntryMap *map;
+ PLArenaPool *tmparena;
+ SECItem derSubject;
+ SECItem certKey;
+ PRCList *cElem, *sElem;
+
+ /* Arena for decoded entries */
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (tmparena == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return SECFailure;
+ }
+
+ /* Iterate over cert entries and map them to subject entries.
+ * NOTE: mapSubjectEntries must be called first to alloc memory
+ * for array of subject->cert map.
+ */
+ for (cElem = PR_LIST_HEAD(&dbArray->certs.link);
+ cElem != &dbArray->certs.link; cElem = PR_NEXT_LINK(cElem)) {
+ certNode = LISTNODE_CAST(cElem);
+ certEntry = (certDBEntryCert *)&certNode->entry;
+ map = (certDBEntryMap *)certNode->appData;
+ CERT_NameFromDERCert(&certEntry->derCert, &derSubject);
+ CERT_KeyFromDERCert(tmparena, &certEntry->derCert, &certKey);
+ /* Loop over found subjects for cert's DN. */
+ for (sElem = PR_LIST_HEAD(&dbArray->subjects.link);
+ sElem != &dbArray->subjects.link; sElem = PR_NEXT_LINK(sElem)) {
+ subjNode = LISTNODE_CAST(sElem);
+ subjectEntry = (certDBEntrySubject *)&subjNode->entry;
+ if (SECITEM_ItemsAreEqual(&derSubject, &subjectEntry->derSubject)) {
+ unsigned int i;
+ /* Found matching subject name, create link. */
+ map->pSubject = subjNode;
+ /* Make sure subject entry has cert's key. */
+ for (i = 0; i < subjectEntry->ncerts; i++) {
+ if (SECITEM_ItemsAreEqual(&certKey,
+ &subjectEntry->certKeys[i])) {
+ /* Found matching cert key. */
+ smap = (certDBSubjectEntryMap *)subjNode->appData;
+ smap->pCerts[i] = certNode;
+ break;
+ }
+ }
+ }
+ }
+ }
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return SECSuccess;
+}
+
+SECStatus
+mapSubjectEntries(certDBArray *dbArray)
+{
+ certDBEntrySubject *subjectEntry;
+ certDBEntryListNode *subjNode;
+ certDBSubjectEntryMap *subjMap;
+ PRCList *sElem;
+
+ for (sElem = PR_LIST_HEAD(&dbArray->subjects.link);
+ sElem != &dbArray->subjects.link; sElem = PR_NEXT_LINK(sElem)) {
+ /* Iterate over subject entries and map subjects to nickname
+ * and smime entries. The cert<->subject map will be handled
+ * by a subsequent call to mapCertEntries.
+ */
+ subjNode = LISTNODE_CAST(sElem);
+ subjectEntry = (certDBEntrySubject *)&subjNode->entry;
+ subjMap = (certDBSubjectEntryMap *)subjNode->appData;
+ /* need to alloc memory here for array of matching certs. */
+ subjMap->pCerts = PORT_ArenaAlloc(subjMap->arena,
+ subjectEntry->ncerts * sizeof(int));
+ subjMap->numCerts = subjectEntry->ncerts;
+ subjMap->pNickname = NoNickname;
+ subjMap->pSMime = NoSMime;
+
+ if (subjectEntry->nickname) {
+ /* Subject should have a nickname entry, so create a link. */
+ PRCList *nElem;
+ for (nElem = PR_LIST_HEAD(&dbArray->nicknames.link);
+ nElem != &dbArray->nicknames.link;
+ nElem = PR_NEXT_LINK(nElem)) {
+ certDBEntryListNode *nickNode;
+ certDBEntryNickname *nicknameEntry;
+ /* Look for subject's nickname in nickname entries. */
+ nickNode = LISTNODE_CAST(nElem);
+ nicknameEntry = (certDBEntryNickname *)&nickNode->entry;
+ if (PL_strcmp(subjectEntry->nickname,
+ nicknameEntry->nickname) == 0) {
+ /* Found a nickname entry for subject's nickname. */
+ if (SECITEM_ItemsAreEqual(&subjectEntry->derSubject,
+ &nicknameEntry->subjectName)) {
+ certDBEntryMap *nickMap;
+ nickMap = (certDBEntryMap *)nickNode->appData;
+ /* Nickname and subject match. */
+ subjMap->pNickname = nickNode;
+ nickMap->pSubject = subjNode;
+ } else if (subjMap->pNickname == NoNickname) {
+ /* Nickname entry found is for diff. subject. */
+ subjMap->pNickname = WrongEntry;
+ }
+ }
+ }
+ }
+ if (subjectEntry->emailAddrs) {
+ unsigned int n;
+ for (n = 0; n < subjectEntry->nemailAddrs &&
+ subjectEntry->emailAddrs[n];
+ ++n) {
+ char *emailAddr = subjectEntry->emailAddrs[n];
+ if (emailAddr[0]) {
+ PRCList *mElem;
+ /* Subject should have an smime entry, so create a link. */
+ for (mElem = PR_LIST_HEAD(&dbArray->smime.link);
+ mElem != &dbArray->smime.link;
+ mElem = PR_NEXT_LINK(mElem)) {
+ certDBEntryListNode *smimeNode;
+ certDBEntrySMime *smimeEntry;
+ /* Look for subject's email in S/MIME entries. */
+ smimeNode = LISTNODE_CAST(mElem);
+ smimeEntry = (certDBEntrySMime *)&smimeNode->entry;
+ if (PL_strcmp(emailAddr,
+ smimeEntry->emailAddr) == 0) {
+ /* Found a S/MIME entry for subject's email. */
+ if (SECITEM_ItemsAreEqual(
+ &subjectEntry->derSubject,
+ &smimeEntry->subjectName)) {
+ certDBEntryMap *smimeMap;
+ /* S/MIME entry and subject match. */
+ subjMap->pSMime = smimeNode;
+ smimeMap = (certDBEntryMap *)smimeNode->appData;
+ smimeMap->pSubject = subjNode;
+ } else if (subjMap->pSMime == NoSMime) {
+ /* S/MIME entry found is for diff. subject. */
+ subjMap->pSMime = WrongEntry;
+ }
+ }
+ } /* end for */
+ } /* endif (emailAddr[0]) */
+ } /* end for */
+ } /* endif (subjectEntry->emailAddrs) */
+ }
+ return SECSuccess;
+}
+
+void
+printnode(dbDebugInfo *info, const char *str, int num)
+{
+ if (!info->dograph)
+ return;
+ if (num < 0) {
+ PR_fprintf(info->graphfile, str);
+ } else {
+ PR_fprintf(info->graphfile, str, num);
+ }
+}
+
+PRBool
+map_handle_is_ok(dbDebugInfo *info, void *mapPtr, int indent)
+{
+ if (mapPtr == NULL) {
+ if (indent > 0)
+ printnode(info, " ", -1);
+ if (indent >= 0)
+ printnode(info, "******************* ", -1);
+ return PR_FALSE;
+ } else if (mapPtr == WrongEntry) {
+ if (indent > 0)
+ printnode(info, " ", -1);
+ if (indent >= 0)
+ printnode(info, "??????????????????? ", -1);
+ return PR_FALSE;
+ } else {
+ return PR_TRUE;
+ }
+}
+
+/* these call each other */
+void print_smime_graph(dbDebugInfo *info, certDBEntryMap *smimeMap,
+ int direction);
+void print_nickname_graph(dbDebugInfo *info, certDBEntryMap *nickMap,
+ int direction);
+void print_subject_graph(dbDebugInfo *info, certDBSubjectEntryMap *subjMap,
+ int direction, int optindex, int opttype);
+void print_cert_graph(dbDebugInfo *info, certDBEntryMap *certMap,
+ int direction);
+
+/* Given an smime entry, print its unique identifier. If GOLEFT is
+ * specified, print the cert<-subject<-smime map, else just print
+ * the smime entry.
+ */
+void
+print_smime_graph(dbDebugInfo *info, certDBEntryMap *smimeMap, int direction)
+{
+ certDBSubjectEntryMap *subjMap;
+ certDBEntryListNode *subjNode;
+ if (direction == GOLEFT) {
+ /* Need to output subject and cert first, see print_subject_graph */
+ subjNode = smimeMap->pSubject;
+ if (map_handle_is_ok(info, (void *)subjNode, 1)) {
+ subjMap = (certDBSubjectEntryMap *)subjNode->appData;
+ print_subject_graph(info, subjMap, GOLEFT,
+ smimeMap->index, certDBEntryTypeSMimeProfile);
+ } else {
+ printnode(info, "<---- S/MIME %5d ", smimeMap->index);
+ info->dbErrors[NoSubjectForSMime]++;
+ }
+ } else {
+ printnode(info, "S/MIME %5d ", smimeMap->index);
+ }
+}
+
+/* Given a nickname entry, print its unique identifier. If GOLEFT is
+ * specified, print the cert<-subject<-nickname map, else just print
+ * the nickname entry.
+ */
+void
+print_nickname_graph(dbDebugInfo *info, certDBEntryMap *nickMap, int direction)
+{
+ certDBSubjectEntryMap *subjMap;
+ certDBEntryListNode *subjNode;
+ if (direction == GOLEFT) {
+ /* Need to output subject and cert first, see print_subject_graph */
+ subjNode = nickMap->pSubject;
+ if (map_handle_is_ok(info, (void *)subjNode, 1)) {
+ subjMap = (certDBSubjectEntryMap *)subjNode->appData;
+ print_subject_graph(info, subjMap, GOLEFT,
+ nickMap->index, certDBEntryTypeNickname);
+ } else {
+ printnode(info, "<---- Nickname %5d ", nickMap->index);
+ info->dbErrors[NoSubjectForNickname]++;
+ }
+ } else {
+ printnode(info, "Nickname %5d ", nickMap->index);
+ }
+}
+
+/* Given a subject entry, if going right print the graph of the nickname|smime
+ * that it maps to (by its unique identifier); and if going left
+ * print the list of certs that it points to.
+ */
+void
+print_subject_graph(dbDebugInfo *info, certDBSubjectEntryMap *subjMap,
+ int direction, int optindex, int opttype)
+{
+ certDBEntryMap *map;
+ certDBEntryListNode *node;
+ int i;
+ /* The first line of output always contains the cert id, subject id,
+ * and nickname|smime id. Subsequent lines may contain additional
+ * cert id's for the subject if going left or both directions.
+ * Ex. of printing the graph for a subject entry:
+ * Cert 3 <- Subject 5 -> Nickname 32
+ * Cert 8 /
+ * Cert 9 /
+ * means subject 5 has 3 certs, 3, 8, and 9, and corresponds
+ * to nickname entry 32.
+ * To accomplish the above, it is required to dump the entire first
+ * line left-to-right, regardless of the input direction, and then
+ * finish up any remaining cert entries. Hence the code is uglier
+ * than one may expect.
+ */
+ if (direction == GOLEFT || direction == GOBOTH) {
+ /* In this case, nothing should be output until the first cert is
+ * located and output (cert 3 in the above example).
+ */
+ if (subjMap->numCerts == 0 || subjMap->pCerts == NULL)
+ /* XXX uh-oh */
+ return;
+ /* get the first cert and dump it. */
+ node = subjMap->pCerts[0];
+ if (map_handle_is_ok(info, (void *)node, 0)) {
+ map = (certDBEntryMap *)node->appData;
+ /* going left here stops. */
+ print_cert_graph(info, map, GOLEFT);
+ } else {
+ info->dbErrors[SubjectHasNoKeyForCert]++;
+ }
+ /* Now it is safe to output the subject id. */
+ if (direction == GOLEFT)
+ printnode(info, "Subject %5d <---- ", subjMap->index);
+ else /* direction == GOBOTH */
+ printnode(info, "Subject %5d ----> ", subjMap->index);
+ }
+ if (direction == GORIGHT || direction == GOBOTH) {
+ /* Okay, now output the nickname|smime for this subject. */
+ if (direction != GOBOTH) /* handled above */
+ printnode(info, "Subject %5d ----> ", subjMap->index);
+ if (subjMap->pNickname) {
+ node = subjMap->pNickname;
+ if (map_handle_is_ok(info, (void *)node, 0)) {
+ map = (certDBEntryMap *)node->appData;
+ /* going right here stops. */
+ print_nickname_graph(info, map, GORIGHT);
+ }
+ }
+ if (subjMap->pSMime) {
+ node = subjMap->pSMime;
+ if (map_handle_is_ok(info, (void *)node, 0)) {
+ map = (certDBEntryMap *)node->appData;
+ /* going right here stops. */
+ print_smime_graph(info, map, GORIGHT);
+ }
+ }
+ if (!subjMap->pNickname && !subjMap->pSMime) {
+ printnode(info, "******************* ", -1);
+ info->dbErrors[NoNicknameOrSMimeForSubject]++;
+ }
+ if (subjMap->pNickname && subjMap->pSMime) {
+ info->dbErrors[NicknameAndSMimeEntries]++;
+ }
+ }
+ if (direction != GORIGHT) { /* going right has only one cert */
+ if (opttype == certDBEntryTypeNickname)
+ printnode(info, "Nickname %5d ", optindex);
+ else if (opttype == certDBEntryTypeSMimeProfile)
+ printnode(info, "S/MIME %5d ", optindex);
+ for (i = 1 /* 1st one already done */; i < subjMap->numCerts; i++) {
+ printnode(info, "\n", -1); /* start a new line */
+ node = subjMap->pCerts[i];
+ if (map_handle_is_ok(info, (void *)node, 0)) {
+ map = (certDBEntryMap *)node->appData;
+ /* going left here stops. */
+ print_cert_graph(info, map, GOLEFT);
+ printnode(info, "/", -1);
+ }
+ }
+ }
+}
+
+/* Given a cert entry, print its unique identifer. If GORIGHT is specified,
+ * print the cert->subject->nickname|smime map, else just print
+ * the cert entry.
+ */
+void
+print_cert_graph(dbDebugInfo *info, certDBEntryMap *certMap, int direction)
+{
+ certDBSubjectEntryMap *subjMap;
+ certDBEntryListNode *subjNode;
+ if (direction == GOLEFT) {
+ printnode(info, "Cert %5d <---- ", certMap->index);
+ /* only want cert entry, terminate here. */
+ return;
+ }
+ /* Keep going right then. */
+ printnode(info, "Cert %5d ----> ", certMap->index);
+ subjNode = certMap->pSubject;
+ if (map_handle_is_ok(info, (void *)subjNode, 0)) {
+ subjMap = (certDBSubjectEntryMap *)subjNode->appData;
+ print_subject_graph(info, subjMap, GORIGHT, -1, -1);
+ } else {
+ info->dbErrors[NoSubjectForCert]++;
+ }
+}
+
+SECStatus
+computeDBGraph(certDBArray *dbArray, dbDebugInfo *info)
+{
+ PRCList *cElem, *sElem, *nElem, *mElem;
+ certDBEntryListNode *node;
+ certDBEntryMap *map;
+ certDBSubjectEntryMap *subjMap;
+
+ /* Graph is of this form:
+ *
+ * certs:
+ * cert ---> subject ---> (nickname|smime)
+ *
+ * subjects:
+ * cert <--- subject ---> (nickname|smime)
+ *
+ * nicknames and smime:
+ * cert <--- subject <--- (nickname|smime)
+ */
+
+ /* Print cert graph. */
+ for (cElem = PR_LIST_HEAD(&dbArray->certs.link);
+ cElem != &dbArray->certs.link; cElem = PR_NEXT_LINK(cElem)) {
+ /* Print graph of everything to right of cert entry. */
+ node = LISTNODE_CAST(cElem);
+ map = (certDBEntryMap *)node->appData;
+ print_cert_graph(info, map, GORIGHT);
+ printnode(info, "\n", -1);
+ }
+ printnode(info, "\n", -1);
+
+ /* Print subject graph. */
+ for (sElem = PR_LIST_HEAD(&dbArray->subjects.link);
+ sElem != &dbArray->subjects.link; sElem = PR_NEXT_LINK(sElem)) {
+ /* Print graph of everything to both sides of subject entry. */
+ node = LISTNODE_CAST(sElem);
+ subjMap = (certDBSubjectEntryMap *)node->appData;
+ print_subject_graph(info, subjMap, GOBOTH, -1, -1);
+ printnode(info, "\n", -1);
+ }
+ printnode(info, "\n", -1);
+
+ /* Print nickname graph. */
+ for (nElem = PR_LIST_HEAD(&dbArray->nicknames.link);
+ nElem != &dbArray->nicknames.link; nElem = PR_NEXT_LINK(nElem)) {
+ /* Print graph of everything to left of nickname entry. */
+ node = LISTNODE_CAST(nElem);
+ map = (certDBEntryMap *)node->appData;
+ print_nickname_graph(info, map, GOLEFT);
+ printnode(info, "\n", -1);
+ }
+ printnode(info, "\n", -1);
+
+ /* Print smime graph. */
+ for (mElem = PR_LIST_HEAD(&dbArray->smime.link);
+ mElem != &dbArray->smime.link; mElem = PR_NEXT_LINK(mElem)) {
+ /* Print graph of everything to left of smime entry. */
+ node = LISTNODE_CAST(mElem);
+ if (node == NULL)
+ break;
+ map = (certDBEntryMap *)node->appData;
+ print_smime_graph(info, map, GOLEFT);
+ printnode(info, "\n", -1);
+ }
+ printnode(info, "\n", -1);
+
+ return SECSuccess;
+}
+
+/*
+ * List the entries in the db, showing handles between entry types.
+ */
+void
+verboseOutput(certDBArray *dbArray, dbDebugInfo *info)
+{
+ int i, ref;
+ PRCList *elem;
+ certDBEntryListNode *node;
+ certDBEntryMap *map;
+ certDBSubjectEntryMap *smap;
+ certDBEntrySubject *subjectEntry;
+
+ /* List certs */
+ for (elem = PR_LIST_HEAD(&dbArray->certs.link);
+ elem != &dbArray->certs.link; elem = PR_NEXT_LINK(elem)) {
+ node = LISTNODE_CAST(elem);
+ map = (certDBEntryMap *)node->appData;
+ dumpCertEntry((certDBEntryCert *)&node->entry, map->index, info->out);
+ /* walk the cert handle to it's subject entry */
+ if (map_handle_is_ok(info, map->pSubject, -1)) {
+ smap = (certDBSubjectEntryMap *)map->pSubject->appData;
+ ref = smap->index;
+ PR_fprintf(info->out, "-->(subject %d)\n\n\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING SUBJECT ENTRY)\n\n\n");
+ }
+ }
+ /* List subjects */
+ for (elem = PR_LIST_HEAD(&dbArray->subjects.link);
+ elem != &dbArray->subjects.link; elem = PR_NEXT_LINK(elem)) {
+ int refs = 0;
+ node = LISTNODE_CAST(elem);
+ subjectEntry = (certDBEntrySubject *)&node->entry;
+ smap = (certDBSubjectEntryMap *)node->appData;
+ dumpSubjectEntry(subjectEntry, smap->index, info->out);
+ /* iterate over subject's certs */
+ for (i = 0; i < smap->numCerts; i++) {
+ /* walk each subject handle to it's cert entries */
+ if (map_handle_is_ok(info, smap->pCerts[i], -1)) {
+ ref = ((certDBEntryMap *)smap->pCerts[i]->appData)->index;
+ PR_fprintf(info->out, "-->(%d. certificate %d)\n", i, ref);
+ } else {
+ PR_fprintf(info->out, "-->(%d. MISSING CERT ENTRY)\n", i);
+ }
+ }
+ if (subjectEntry->nickname) {
+ ++refs;
+ /* walk each subject handle to it's nickname entry */
+ if (map_handle_is_ok(info, smap->pNickname, -1)) {
+ ref = ((certDBEntryMap *)smap->pNickname->appData)->index;
+ PR_fprintf(info->out, "-->(nickname %d)\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING NICKNAME ENTRY)\n");
+ }
+ }
+ if (subjectEntry->nemailAddrs &&
+ subjectEntry->emailAddrs &&
+ subjectEntry->emailAddrs[0] &&
+ subjectEntry->emailAddrs[0][0]) {
+ ++refs;
+ /* walk each subject handle to it's smime entry */
+ if (map_handle_is_ok(info, smap->pSMime, -1)) {
+ ref = ((certDBEntryMap *)smap->pSMime->appData)->index;
+ PR_fprintf(info->out, "-->(s/mime %d)\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING S/MIME ENTRY)\n");
+ }
+ }
+ if (!refs) {
+ PR_fprintf(info->out, "-->(NO NICKNAME+S/MIME ENTRY)\n");
+ }
+ PR_fprintf(info->out, "\n\n");
+ }
+ for (elem = PR_LIST_HEAD(&dbArray->nicknames.link);
+ elem != &dbArray->nicknames.link; elem = PR_NEXT_LINK(elem)) {
+ node = LISTNODE_CAST(elem);
+ map = (certDBEntryMap *)node->appData;
+ dumpNicknameEntry((certDBEntryNickname *)&node->entry, map->index,
+ info->out);
+ if (map_handle_is_ok(info, map->pSubject, -1)) {
+ ref = ((certDBEntryMap *)map->pSubject->appData)->index;
+ PR_fprintf(info->out, "-->(subject %d)\n\n\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING SUBJECT ENTRY)\n\n\n");
+ }
+ }
+ for (elem = PR_LIST_HEAD(&dbArray->smime.link);
+ elem != &dbArray->smime.link; elem = PR_NEXT_LINK(elem)) {
+ node = LISTNODE_CAST(elem);
+ map = (certDBEntryMap *)node->appData;
+ dumpSMimeEntry((certDBEntrySMime *)&node->entry, map->index, info->out);
+ if (map_handle_is_ok(info, map->pSubject, -1)) {
+ ref = ((certDBEntryMap *)map->pSubject->appData)->index;
+ PR_fprintf(info->out, "-->(subject %d)\n\n\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING SUBJECT ENTRY)\n\n\n");
+ }
+ }
+ PR_fprintf(info->out, "\n\n");
+}
+
+/* A callback function, intended to be called from nsslowcert_TraverseDBEntries
+ * Builds a PRCList of DB entries of the specified type.
+ */
+SECStatus
+SEC_GetCertDBEntryList(SECItem *dbdata, SECItem *dbkey,
+ certDBEntryType entryType, void *pdata)
+{
+ certDBEntry *entry;
+ certDBEntryListNode *node;
+ PRCList *list = (PRCList *)pdata;
+
+ if (!dbdata || !dbkey || !pdata || !dbdata->data || !dbkey->data) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ entry = nsslowcert_DecodeAnyDBEntry(dbdata, dbkey, entryType, NULL);
+ if (!entry) {
+ return SECSuccess; /* skip it */
+ }
+ node = PORT_ArenaZNew(entry->common.arena, certDBEntryListNode);
+ if (!node) {
+ /* DestroyDBEntry(entry); */
+ PLArenaPool *arena = entry->common.arena;
+ PORT_Memset(&entry->common, 0, sizeof entry->common);
+ PORT_FreeArena(arena, PR_FALSE);
+ return SECFailure;
+ }
+ node->entry = *entry; /* crude but effective. */
+ PR_INIT_CLIST(&node->link);
+ PR_INSERT_BEFORE(&node->link, list);
+ return SECSuccess;
+}
+
+int
+fillDBEntryArray(NSSLOWCERTCertDBHandle *handle, certDBEntryType type,
+ certDBEntryListNode *list)
+{
+ PRCList *elem;
+ certDBEntryListNode *node;
+ certDBEntryMap *mnode;
+ certDBSubjectEntryMap *smnode;
+ PLArenaPool *arena;
+ int count = 0;
+
+ /* Initialize a dummy entry in the list. The list head will be the
+ * next element, so this element is skipped by for loops.
+ */
+ PR_INIT_CLIST((PRCList *)list);
+ /* Collect all of the cert db entries for this type into a list. */
+ nsslowcert_TraverseDBEntries(handle, type, SEC_GetCertDBEntryList, list);
+
+ for (elem = PR_LIST_HEAD(&list->link);
+ elem != &list->link; elem = PR_NEXT_LINK(elem)) {
+ /* Iterate over the entries and ... */
+ node = (certDBEntryListNode *)elem;
+ if (type != certDBEntryTypeSubject) {
+ arena = PORT_NewArena(sizeof(*mnode));
+ mnode = PORT_ArenaZNew(arena, certDBEntryMap);
+ mnode->arena = arena;
+ /* ... assign a unique index number to each node, and ... */
+ mnode->index = count;
+ /* ... set the map pointer for the node. */
+ node->appData = (void *)mnode;
+ } else {
+ /* allocate some room for the cert pointers also */
+ arena = PORT_NewArena(sizeof(*smnode) + 20 * sizeof(void *));
+ smnode = PORT_ArenaZNew(arena, certDBSubjectEntryMap);
+ smnode->arena = arena;
+ smnode->index = count;
+ node->appData = (void *)smnode;
+ }
+ count++;
+ }
+ return count;
+}
+
+void
+freeDBEntryList(PRCList *list)
+{
+ PRCList *next, *elem;
+ certDBEntryListNode *node;
+ certDBEntryMap *map;
+
+ for (elem = PR_LIST_HEAD(list); elem != list;) {
+ next = PR_NEXT_LINK(elem);
+ node = (certDBEntryListNode *)elem;
+ map = (certDBEntryMap *)node->appData;
+ PR_REMOVE_LINK(&node->link);
+ PORT_FreeArena(map->arena, PR_TRUE);
+ PORT_FreeArena(node->entry.common.arena, PR_TRUE);
+ elem = next;
+ }
+}
+
+void
+DBCK_DebugDB(NSSLOWCERTCertDBHandle *handle, PRFileDesc *out,
+ PRFileDesc *mailfile)
+{
+ int i, nCertsFound, nSubjFound, nErr;
+ int nCerts, nSubjects, nSubjCerts, nNicknames, nSMime, nRevocation;
+ PRCList *elem;
+ char c;
+ dbDebugInfo info;
+ certDBArray dbArray;
+
+ PORT_Memset(&dbArray, 0, sizeof(dbArray));
+ PORT_Memset(&info, 0, sizeof(info));
+ info.verbose = (PRBool)(out != NULL);
+ info.dograph = info.verbose;
+ info.out = (out) ? out : PR_STDOUT;
+ info.graphfile = mailfile ? mailfile : PR_STDOUT;
+
+ /* Fill the array structure with cert/subject/nickname/smime entries. */
+ dbArray.numCerts = fillDBEntryArray(handle, certDBEntryTypeCert,
+ &dbArray.certs);
+ dbArray.numSubjects = fillDBEntryArray(handle, certDBEntryTypeSubject,
+ &dbArray.subjects);
+ dbArray.numNicknames = fillDBEntryArray(handle, certDBEntryTypeNickname,
+ &dbArray.nicknames);
+ dbArray.numSMime = fillDBEntryArray(handle, certDBEntryTypeSMimeProfile,
+ &dbArray.smime);
+ dbArray.numRevocation = fillDBEntryArray(handle, certDBEntryTypeRevocation,
+ &dbArray.revocation);
+
+ /* Compute the map between the database entries. */
+ mapSubjectEntries(&dbArray);
+ mapCertEntries(&dbArray);
+ computeDBGraph(&dbArray, &info);
+
+ /* Store the totals for later reference. */
+ nCerts = dbArray.numCerts;
+ nSubjects = dbArray.numSubjects;
+ nNicknames = dbArray.numNicknames;
+ nSMime = dbArray.numSMime;
+ nRevocation = dbArray.numRevocation;
+ nSubjCerts = 0;
+ for (elem = PR_LIST_HEAD(&dbArray.subjects.link);
+ elem != &dbArray.subjects.link; elem = PR_NEXT_LINK(elem)) {
+ certDBSubjectEntryMap *smap;
+ smap = (certDBSubjectEntryMap *)LISTNODE_CAST(elem)->appData;
+ nSubjCerts += smap->numCerts;
+ }
+
+ if (info.verbose) {
+ /* Dump the database contents. */
+ verboseOutput(&dbArray, &info);
+ }
+
+ freeDBEntryList(&dbArray.certs.link);
+ freeDBEntryList(&dbArray.subjects.link);
+ freeDBEntryList(&dbArray.nicknames.link);
+ freeDBEntryList(&dbArray.smime.link);
+ freeDBEntryList(&dbArray.revocation.link);
+
+ PR_fprintf(info.out, "\n");
+ PR_fprintf(info.out, "Database statistics:\n");
+ PR_fprintf(info.out, "N0: Found %4d Certificate entries.\n",
+ nCerts);
+ PR_fprintf(info.out, "N1: Found %4d Subject entries (unique DN's).\n",
+ nSubjects);
+ PR_fprintf(info.out, "N2: Found %4d Cert keys within Subject entries.\n",
+ nSubjCerts);
+ PR_fprintf(info.out, "N3: Found %4d Nickname entries.\n",
+ nNicknames);
+ PR_fprintf(info.out, "N4: Found %4d S/MIME entries.\n",
+ nSMime);
+ PR_fprintf(info.out, "N5: Found %4d CRL entries.\n",
+ nRevocation);
+ PR_fprintf(info.out, "\n");
+
+ nErr = 0;
+ for (i = 0; i < NUM_ERROR_TYPES; i++) {
+ PR_fprintf(info.out, "E%d: Found %4d %s\n",
+ i, info.dbErrors[i], errResult[i]);
+ nErr += info.dbErrors[i];
+ }
+ PR_fprintf(info.out, "--------------\n Found %4d errors in database.\n",
+ nErr);
+
+ PR_fprintf(info.out, "\nCertificates:\n");
+ PR_fprintf(info.out, "N0 == N2 + E%d + E%d\n", NoSubjectForCert,
+ SubjectHasNoKeyForCert);
+ nCertsFound = nSubjCerts +
+ info.dbErrors[NoSubjectForCert] +
+ info.dbErrors[SubjectHasNoKeyForCert];
+ c = (nCertsFound == nCerts) ? '=' : '!';
+ PR_fprintf(info.out, "%d %c= %d + %d + %d\n", nCerts, c, nSubjCerts,
+ info.dbErrors[NoSubjectForCert],
+ info.dbErrors[SubjectHasNoKeyForCert]);
+ PR_fprintf(info.out, "\nSubjects:\n");
+ PR_fprintf(info.out,
+ "N1 == N3 + N4 + E%d + E%d + E%d + E%d + E%d - E%d - E%d - E%d\n",
+ NoNicknameOrSMimeForSubject,
+ WrongNicknameForSubject,
+ NoNicknameEntry,
+ WrongSMimeForSubject,
+ NoSMimeEntry,
+ NoSubjectForNickname,
+ NoSubjectForSMime,
+ NicknameAndSMimeEntries);
+ nSubjFound = nNicknames + nSMime +
+ info.dbErrors[NoNicknameOrSMimeForSubject] +
+ info.dbErrors[WrongNicknameForSubject] +
+ info.dbErrors[NoNicknameEntry] +
+ info.dbErrors[WrongSMimeForSubject] +
+ info.dbErrors[NoSMimeEntry] -
+ info.dbErrors[NoSubjectForNickname] -
+ info.dbErrors[NoSubjectForSMime] -
+ info.dbErrors[NicknameAndSMimeEntries];
+ c = (nSubjFound == nSubjects) ? '=' : '!';
+ PR_fprintf(info.out,
+ "%2d %c= %2d + %2d + %2d + %2d + %2d + %2d + %2d - %2d - %2d - %2d\n",
+ nSubjects, c, nNicknames, nSMime,
+ info.dbErrors[NoNicknameOrSMimeForSubject],
+ info.dbErrors[WrongNicknameForSubject],
+ info.dbErrors[NoNicknameEntry],
+ info.dbErrors[WrongSMimeForSubject],
+ info.dbErrors[NoSMimeEntry],
+ info.dbErrors[NoSubjectForNickname],
+ info.dbErrors[NoSubjectForSMime],
+ info.dbErrors[NicknameAndSMimeEntries]);
+ PR_fprintf(info.out, "\n");
+}
+
+#ifdef DORECOVER
+#include "dbrecover.c"
+#endif /* DORECOVER */
+
+enum {
+ cmd_Debug = 0,
+ cmd_LongUsage,
+ cmd_Recover
+};
+
+enum {
+ opt_KeepAll = 0,
+ opt_CertDir,
+ opt_Dumpfile,
+ opt_InputDB,
+ opt_OutputDB,
+ opt_Mailfile,
+ opt_Prompt,
+ opt_KeepRedundant,
+ opt_KeepNoSMimeProfile,
+ opt_Verbose,
+ opt_KeepExpired
+};
+
+static secuCommandFlag dbck_commands[] =
+ {
+ { /* cmd_Debug, */ 'D', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_LongUsage,*/ 'H', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Recover, */ 'R', PR_FALSE, 0, PR_FALSE }
+ };
+
+static secuCommandFlag dbck_options[] =
+ {
+ { /* opt_KeepAll, */ 'a', PR_FALSE, 0, PR_FALSE },
+ { /* opt_CertDir, */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Dumpfile, */ 'f', PR_TRUE, 0, PR_FALSE },
+ { /* opt_InputDB, */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_OutputDB, */ 'o', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Mailfile, */ 'm', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Prompt, */ 'p', PR_FALSE, 0, PR_FALSE },
+ { /* opt_KeepRedundant, */ 'r', PR_FALSE, 0, PR_FALSE },
+ { /* opt_KeepNoSMimeProfile,*/ 's', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Verbose, */ 'v', PR_FALSE, 0, PR_FALSE },
+ { /* opt_KeepExpired, */ 'x', PR_FALSE, 0, PR_FALSE }
+ };
+
+#define CERT_DB_FMT "%s/cert%s.db"
+
+static char *
+dbck_certdb_name_cb(void *arg, int dbVersion)
+{
+ const char *configdir = (const char *)arg;
+ const char *dbver;
+ char *smpname = NULL;
+ char *dbname = NULL;
+
+ switch (dbVersion) {
+ case 8:
+ dbver = "8";
+ break;
+ case 7:
+ dbver = "7";
+ break;
+ case 6:
+ dbver = "6";
+ break;
+ case 5:
+ dbver = "5";
+ break;
+ case 4:
+ default:
+ dbver = "";
+ break;
+ }
+
+ /* make sure we return something allocated with PORT_ so we have properly
+ * matched frees at the end */
+ smpname = PR_smprintf(CERT_DB_FMT, configdir, dbver);
+ if (smpname) {
+ dbname = PORT_Strdup(smpname);
+ PR_smprintf_free(smpname);
+ }
+ return dbname;
+}
+
+int
+main(int argc, char **argv)
+{
+ NSSLOWCERTCertDBHandle *certHandle;
+
+ PRFileDesc *mailfile = NULL;
+ PRFileDesc *dumpfile = NULL;
+
+ char *pathname = 0;
+ char *fullname = 0;
+ char *newdbname = 0;
+
+ PRBool removeExpired, requireProfile, singleEntry;
+ SECStatus rv;
+ secuCommand dbck;
+
+ dbck.numCommands = sizeof(dbck_commands) / sizeof(secuCommandFlag);
+ dbck.numOptions = sizeof(dbck_options) / sizeof(secuCommandFlag);
+ dbck.commands = dbck_commands;
+ dbck.options = dbck_options;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &dbck);
+
+ if (rv != SECSuccess)
+ Usage(progName);
+
+ if (dbck.commands[cmd_LongUsage].activated)
+ LongUsage(progName);
+
+ if (!dbck.commands[cmd_Debug].activated &&
+ !dbck.commands[cmd_Recover].activated) {
+ PR_fprintf(PR_STDERR, "Please specify -H, -D or -R.\n");
+ Usage(progName);
+ }
+
+ removeExpired = !(dbck.options[opt_KeepAll].activated ||
+ dbck.options[opt_KeepExpired].activated);
+
+ requireProfile = !(dbck.options[opt_KeepAll].activated ||
+ dbck.options[opt_KeepNoSMimeProfile].activated);
+
+ singleEntry = !(dbck.options[opt_KeepAll].activated ||
+ dbck.options[opt_KeepRedundant].activated);
+
+ if (dbck.options[opt_OutputDB].activated) {
+ newdbname = PL_strdup(dbck.options[opt_OutputDB].arg);
+ } else {
+ newdbname = PL_strdup("new_cert8.db");
+ }
+
+ /* Create a generic graph of the database. */
+ if (dbck.options[opt_Mailfile].activated) {
+ mailfile = PR_Open("./mailfile", PR_RDWR | PR_CREATE_FILE, 00660);
+ if (!mailfile) {
+ fprintf(stderr, "Unable to create mailfile.\n");
+ return -1;
+ }
+ }
+
+ /* Dump all debugging info while running. */
+ if (dbck.options[opt_Verbose].activated) {
+ if (dbck.options[opt_Dumpfile].activated) {
+ dumpfile = PR_Open(dbck.options[opt_Dumpfile].arg,
+ PR_RDWR | PR_CREATE_FILE, 00660);
+ if (!dumpfile) {
+ fprintf(stderr, "Unable to create dumpfile.\n");
+ return -1;
+ }
+ } else {
+ dumpfile = PR_STDOUT;
+ }
+ }
+
+ /* Set the cert database directory. */
+ if (dbck.options[opt_CertDir].activated) {
+ SECU_ConfigDirectory(dbck.options[opt_CertDir].arg);
+ }
+
+ pathname = SECU_ConfigDirectory(NULL);
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_NoDB_Init(pathname);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "NSS_NoDB_Init failed\n");
+ return -1;
+ }
+
+ certHandle = PORT_ZNew(NSSLOWCERTCertDBHandle);
+ if (!certHandle) {
+ SECU_PrintError(progName, "unable to get database handle");
+ return -1;
+ }
+ certHandle->ref = 1;
+
+#ifdef NOTYET
+ /* Open the possibly corrupt database. */
+ if (dbck.options[opt_InputDB].activated) {
+ PRFileInfo fileInfo;
+ fullname = PR_smprintf("%s/%s", pathname,
+ dbck.options[opt_InputDB].arg);
+ if (PR_GetFileInfo(fullname, &fileInfo) != PR_SUCCESS) {
+ fprintf(stderr, "Unable to read file \"%s\".\n", fullname);
+ return -1;
+ }
+ rv = CERT_OpenCertDBFilename(certHandle, fullname, PR_TRUE);
+ } else
+#endif
+ {
+/* Use the default. */
+#ifdef NOTYET
+ fullname = SECU_CertDBNameCallback(NULL, CERT_DB_FILE_VERSION);
+ if (PR_GetFileInfo(fullname, &fileInfo) != PR_SUCCESS) {
+ fprintf(stderr, "Unable to read file \"%s\".\n", fullname);
+ return -1;
+ }
+#endif
+ rv = nsslowcert_OpenCertDB(certHandle,
+ PR_TRUE, /* readOnly */
+ NULL, /* rdb appName */
+ "", /* rdb prefix */
+ dbck_certdb_name_cb, /* namecb */
+ pathname, /* configDir */
+ PR_FALSE); /* volatile */
+ }
+
+ if (rv) {
+ SECU_PrintError(progName, "unable to open cert database");
+ return -1;
+ }
+
+ if (dbck.commands[cmd_Debug].activated) {
+ DBCK_DebugDB(certHandle, dumpfile, mailfile);
+ return 0;
+ }
+
+#ifdef DORECOVER
+ if (dbck.commands[cmd_Recover].activated) {
+ DBCK_ReconstructDBFromCerts(certHandle, newdbname,
+ dumpfile, removeExpired,
+ requireProfile, singleEntry,
+ dbck.options[opt_Prompt].activated);
+ return 0;
+ }
+#endif
+
+ if (mailfile)
+ PR_Close(mailfile);
+ if (dumpfile)
+ PR_Close(dumpfile);
+ if (certHandle) {
+ nsslowcert_ClosePermCertDB(certHandle);
+ PORT_Free(certHandle);
+ }
+ return -1;
+}
diff --git a/security/nss/cmd/dbck/dbrecover.c b/security/nss/cmd/dbck/dbrecover.c
new file mode 100644
index 000000000..74d21d85e
--- /dev/null
+++ b/security/nss/cmd/dbck/dbrecover.c
@@ -0,0 +1,668 @@
+/* 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/. */
+
+enum {
+ dbInvalidCert = 0,
+ dbNoSMimeProfile,
+ dbOlderCert,
+ dbBadCertificate,
+ dbCertNotWrittenToDB
+};
+
+typedef struct dbRestoreInfoStr {
+ NSSLOWCERTCertDBHandle *handle;
+ PRBool verbose;
+ PRFileDesc *out;
+ int nCerts;
+ int nOldCerts;
+ int dbErrors[5];
+ PRBool removeType[3];
+ PRBool promptUser[3];
+} dbRestoreInfo;
+
+char *
+IsEmailCert(CERTCertificate *cert)
+{
+ char *email, *tmp1, *tmp2;
+ PRBool isCA;
+ int len;
+
+ if (!cert->subjectName) {
+ return NULL;
+ }
+
+ tmp1 = PORT_Strstr(cert->subjectName, "E=");
+ tmp2 = PORT_Strstr(cert->subjectName, "MAIL=");
+ /* XXX Nelson has cert for KTrilli which does not have either
+ * of above but is email cert (has cert->emailAddr).
+ */
+ if (!tmp1 && !tmp2 && !(cert->emailAddr && cert->emailAddr[0])) {
+ return NULL;
+ }
+
+ /* Server or CA cert, not personal email. */
+ isCA = CERT_IsCACert(cert, NULL);
+ if (isCA)
+ return NULL;
+
+ /* XXX CERT_IsCACert advertises checking the key usage ext.,
+ but doesn't appear to. */
+ /* Check the key usage extension. */
+ if (cert->keyUsagePresent) {
+ /* Must at least be able to sign or encrypt (not neccesarily
+ * both if it is one of a dual cert).
+ */
+ if (!((cert->rawKeyUsage & KU_DIGITAL_SIGNATURE) ||
+ (cert->rawKeyUsage & KU_KEY_ENCIPHERMENT)))
+ return NULL;
+
+ /* CA cert, not personal email. */
+ if (cert->rawKeyUsage & (KU_KEY_CERT_SIGN | KU_CRL_SIGN))
+ return NULL;
+ }
+
+ if (cert->emailAddr && cert->emailAddr[0]) {
+ email = PORT_Strdup(cert->emailAddr);
+ } else {
+ if (tmp1)
+ tmp1 += 2; /* "E=" */
+ else
+ tmp1 = tmp2 + 5; /* "MAIL=" */
+ len = strcspn(tmp1, ", ");
+ email = (char *)PORT_Alloc(len + 1);
+ PORT_Strncpy(email, tmp1, len);
+ email[len] = '\0';
+ }
+
+ return email;
+}
+
+SECStatus
+deleteit(CERTCertificate *cert, void *arg)
+{
+ return SEC_DeletePermCertificate(cert);
+}
+
+/* Different than DeleteCertificate - has the added bonus of removing
+ * all certs with the same DN.
+ */
+SECStatus
+deleteAllEntriesForCert(NSSLOWCERTCertDBHandle *handle, CERTCertificate *cert,
+ PRFileDesc *outfile)
+{
+#if 0
+ certDBEntrySubject *subjectEntry;
+ certDBEntryNickname *nicknameEntry;
+ certDBEntrySMime *smimeEntry;
+ int i;
+#endif
+
+ if (outfile) {
+ PR_fprintf(outfile, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n");
+ PR_fprintf(outfile, "Deleting redundant certificate:\n");
+ dumpCertificate(cert, -1, outfile);
+ }
+
+ CERT_TraverseCertsForSubject(handle, cert->subjectList, deleteit, NULL);
+#if 0
+ CERT_LockDB(handle);
+ subjectEntry = ReadDBSubjectEntry(handle, &cert->derSubject);
+ /* It had better be there, or created a bad db. */
+ PORT_Assert(subjectEntry);
+ for (i=0; i<subjectEntry->ncerts; i++) {
+ DeleteDBCertEntry(handle, &subjectEntry->certKeys[i]);
+ }
+ DeleteDBSubjectEntry(handle, &cert->derSubject);
+ if (subjectEntry->emailAddr && subjectEntry->emailAddr[0]) {
+ smimeEntry = ReadDBSMimeEntry(handle, subjectEntry->emailAddr);
+ if (smimeEntry) {
+ if (SECITEM_ItemsAreEqual(&subjectEntry->derSubject,
+ &smimeEntry->subjectName))
+ /* Only delete it if it's for this subject! */
+ DeleteDBSMimeEntry(handle, subjectEntry->emailAddr);
+ SEC_DestroyDBEntry((certDBEntry*)smimeEntry);
+ }
+ }
+ if (subjectEntry->nickname) {
+ nicknameEntry = ReadDBNicknameEntry(handle, subjectEntry->nickname);
+ if (nicknameEntry) {
+ if (SECITEM_ItemsAreEqual(&subjectEntry->derSubject,
+ &nicknameEntry->subjectName))
+ /* Only delete it if it's for this subject! */
+ DeleteDBNicknameEntry(handle, subjectEntry->nickname);
+ SEC_DestroyDBEntry((certDBEntry*)nicknameEntry);
+ }
+ }
+ SEC_DestroyDBEntry((certDBEntry*)subjectEntry);
+ CERT_UnlockDB(handle);
+#endif
+ return SECSuccess;
+}
+
+void
+getCertsToDelete(char *numlist, int len, int *certNums, int nCerts)
+{
+ int j, num;
+ char *numstr, *numend, *end;
+
+ numstr = numlist;
+ end = numstr + len - 1;
+ while (numstr != end) {
+ numend = strpbrk(numstr, ", \n");
+ *numend = '\0';
+ if (PORT_Strlen(numstr) == 0)
+ return;
+ num = PORT_Atoi(numstr);
+ if (numstr == numlist)
+ certNums[0] = num;
+ for (j = 1; j < nCerts + 1; j++) {
+ if (num == certNums[j]) {
+ certNums[j] = -1;
+ break;
+ }
+ }
+ if (numend == end)
+ break;
+ numstr = strpbrk(numend + 1, "0123456789");
+ }
+}
+
+PRBool
+userSaysDeleteCert(CERTCertificate **certs, int nCerts,
+ int errtype, dbRestoreInfo *info, int *certNums)
+{
+ char response[32];
+ PRInt32 nb;
+ int i;
+ /* User wants to remove cert without prompting. */
+ if (info->promptUser[errtype] == PR_FALSE)
+ return (info->removeType[errtype]);
+ switch (errtype) {
+ case dbInvalidCert:
+ PR_fprintf(PR_STDOUT, "******** Expired ********\n");
+ PR_fprintf(PR_STDOUT, "Cert has expired.\n\n");
+ dumpCertificate(certs[0], -1, PR_STDOUT);
+ PR_fprintf(PR_STDOUT,
+ "Keep it? (y/n - this one, Y/N - all expired certs) [n] ");
+ break;
+ case dbNoSMimeProfile:
+ PR_fprintf(PR_STDOUT, "******** No Profile ********\n");
+ PR_fprintf(PR_STDOUT, "S/MIME cert has no profile.\n\n");
+ dumpCertificate(certs[0], -1, PR_STDOUT);
+ PR_fprintf(PR_STDOUT,
+ "Keep it? (y/n - this one, Y/N - all S/MIME w/o profile) [n] ");
+ break;
+ case dbOlderCert:
+ PR_fprintf(PR_STDOUT, "******* Redundant nickname/email *******\n\n");
+ PR_fprintf(PR_STDOUT, "These certs have the same nickname/email:\n");
+ for (i = 0; i < nCerts; i++)
+ dumpCertificate(certs[i], i, PR_STDOUT);
+ PR_fprintf(PR_STDOUT,
+ "Enter the certs you would like to keep from those listed above.\n");
+ PR_fprintf(PR_STDOUT,
+ "Use a comma-separated list of the cert numbers (ex. 0, 8, 12).\n");
+ PR_fprintf(PR_STDOUT,
+ "The first cert in the list will be the primary cert\n");
+ PR_fprintf(PR_STDOUT,
+ " accessed by the nickname/email handle.\n");
+ PR_fprintf(PR_STDOUT,
+ "List cert numbers to keep here, or hit enter\n");
+ PR_fprintf(PR_STDOUT,
+ " to always keep only the newest cert: ");
+ break;
+ default:
+ }
+ nb = PR_Read(PR_STDIN, response, sizeof(response));
+ PR_fprintf(PR_STDOUT, "\n\n");
+ if (errtype == dbOlderCert) {
+ if (!isdigit(response[0])) {
+ info->promptUser[errtype] = PR_FALSE;
+ info->removeType[errtype] = PR_TRUE;
+ return PR_TRUE;
+ }
+ getCertsToDelete(response, nb, certNums, nCerts);
+ return PR_TRUE;
+ }
+ /* User doesn't want to be prompted for this type anymore. */
+ if (response[0] == 'Y') {
+ info->promptUser[errtype] = PR_FALSE;
+ info->removeType[errtype] = PR_FALSE;
+ return PR_FALSE;
+ } else if (response[0] == 'N') {
+ info->promptUser[errtype] = PR_FALSE;
+ info->removeType[errtype] = PR_TRUE;
+ return PR_TRUE;
+ }
+ return (response[0] != 'y') ? PR_TRUE : PR_FALSE;
+}
+
+SECStatus
+addCertToDB(certDBEntryCert *certEntry, dbRestoreInfo *info,
+ NSSLOWCERTCertDBHandle *oldhandle)
+{
+ SECStatus rv = SECSuccess;
+ PRBool allowOverride;
+ PRBool userCert;
+ SECCertTimeValidity validity;
+ CERTCertificate *oldCert = NULL;
+ CERTCertificate *dbCert = NULL;
+ CERTCertificate *newCert = NULL;
+ CERTCertTrust *trust;
+ certDBEntrySMime *smimeEntry = NULL;
+ char *email = NULL;
+ char *nickname = NULL;
+ int nCertsForSubject = 1;
+
+ oldCert = CERT_DecodeDERCertificate(&certEntry->derCert, PR_FALSE,
+ certEntry->nickname);
+ if (!oldCert) {
+ info->dbErrors[dbBadCertificate]++;
+ SEC_DestroyDBEntry((certDBEntry *)certEntry);
+ return SECSuccess;
+ }
+
+ oldCert->dbEntry = certEntry;
+ oldCert->trust = &certEntry->trust;
+ oldCert->dbhandle = oldhandle;
+
+ trust = oldCert->trust;
+
+ info->nOldCerts++;
+
+ if (info->verbose)
+ PR_fprintf(info->out, "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n");
+
+ if (oldCert->nickname)
+ nickname = PORT_Strdup(oldCert->nickname);
+
+ /* Always keep user certs. Skip ahead. */
+ /* XXX if someone sends themselves a signed message, it is possible
+ for their cert to be imported as an "other" cert, not a user cert.
+ this mucks with smime entries... */
+ userCert = (SEC_GET_TRUST_FLAGS(trust, trustSSL) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustEmail) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustObjectSigning) & CERTDB_USER);
+ if (userCert)
+ goto createcert;
+
+ /* If user chooses so, ignore expired certificates. */
+ allowOverride = (PRBool)((oldCert->keyUsage == certUsageSSLServer) ||
+ (oldCert->keyUsage == certUsageSSLServerWithStepUp));
+ validity = CERT_CheckCertValidTimes(oldCert, PR_Now(), allowOverride);
+ /* If cert expired and user wants to delete it, ignore it. */
+ if ((validity != secCertTimeValid) &&
+ userSaysDeleteCert(&oldCert, 1, dbInvalidCert, info, 0)) {
+ info->dbErrors[dbInvalidCert]++;
+ if (info->verbose) {
+ PR_fprintf(info->out, "Deleting expired certificate:\n");
+ dumpCertificate(oldCert, -1, info->out);
+ }
+ goto cleanup;
+ }
+
+ /* New database will already have default certs, don't attempt
+ to overwrite them. */
+ dbCert = CERT_FindCertByDERCert(info->handle, &oldCert->derCert);
+ if (dbCert) {
+ info->nCerts++;
+ if (info->verbose) {
+ PR_fprintf(info->out, "Added certificate to database:\n");
+ dumpCertificate(oldCert, -1, info->out);
+ }
+ goto cleanup;
+ }
+
+ /* Determine if cert is S/MIME and get its email if so. */
+ email = IsEmailCert(oldCert);
+
+/*
+ XXX Just create empty profiles?
+ if (email) {
+ SECItem *profile = CERT_FindSMimeProfile(oldCert);
+ if (!profile &&
+ userSaysDeleteCert(&oldCert, 1, dbNoSMimeProfile, info, 0)) {
+ info->dbErrors[dbNoSMimeProfile]++;
+ if (info->verbose) {
+ PR_fprintf(info->out,
+ "Deleted cert missing S/MIME profile.\n");
+ dumpCertificate(oldCert, -1, info->out);
+ }
+ goto cleanup;
+ } else {
+ SECITEM_FreeItem(profile);
+ }
+ }
+ */
+
+createcert:
+
+ /* Sometimes happens... */
+ if (!nickname && userCert)
+ nickname = PORT_Strdup(oldCert->subjectName);
+
+ /* Create a new certificate, copy of the old one. */
+ newCert = CERT_NewTempCertificate(info->handle, &oldCert->derCert,
+ nickname, PR_FALSE, PR_TRUE);
+ if (!newCert) {
+ PR_fprintf(PR_STDERR, "Unable to create new certificate.\n");
+ dumpCertificate(oldCert, -1, PR_STDERR);
+ info->dbErrors[dbBadCertificate]++;
+ goto cleanup;
+ }
+
+ /* Add the cert to the new database. */
+ rv = CERT_AddTempCertToPerm(newCert, nickname, oldCert->trust);
+ if (rv) {
+ PR_fprintf(PR_STDERR, "Failed to write temp cert to perm database.\n");
+ dumpCertificate(oldCert, -1, PR_STDERR);
+ info->dbErrors[dbCertNotWrittenToDB]++;
+ goto cleanup;
+ }
+
+ if (info->verbose) {
+ PR_fprintf(info->out, "Added certificate to database:\n");
+ dumpCertificate(oldCert, -1, info->out);
+ }
+
+ /* If the cert is an S/MIME cert, and the first with it's subject,
+ * modify the subject entry to include the email address,
+ * CERT_AddTempCertToPerm does not do email addresses and S/MIME entries.
+ */
+ if (smimeEntry) { /*&& !userCert && nCertsForSubject == 1) { */
+#if 0
+ UpdateSubjectWithEmailAddr(newCert, email);
+#endif
+ SECItem emailProfile, profileTime;
+ rv = CERT_FindFullSMimeProfile(oldCert, &emailProfile, &profileTime);
+ /* calls UpdateSubjectWithEmailAddr */
+ if (rv == SECSuccess)
+ rv = CERT_SaveSMimeProfile(newCert, &emailProfile, &profileTime);
+ }
+
+ info->nCerts++;
+
+cleanup:
+
+ if (nickname)
+ PORT_Free(nickname);
+ if (email)
+ PORT_Free(email);
+ if (oldCert)
+ CERT_DestroyCertificate(oldCert);
+ if (dbCert)
+ CERT_DestroyCertificate(dbCert);
+ if (newCert)
+ CERT_DestroyCertificate(newCert);
+ if (smimeEntry)
+ SEC_DestroyDBEntry((certDBEntry *)smimeEntry);
+ return SECSuccess;
+}
+
+#if 0
+SECStatus
+copyDBEntry(SECItem *data, SECItem *key, certDBEntryType type, void *pdata)
+{
+ SECStatus rv;
+ NSSLOWCERTCertDBHandle *newdb = (NSSLOWCERTCertDBHandle *)pdata;
+ certDBEntryCommon common;
+ SECItem dbkey;
+
+ common.type = type;
+ common.version = CERT_DB_FILE_VERSION;
+ common.flags = data->data[2];
+ common.arena = NULL;
+
+ dbkey.len = key->len + SEC_DB_KEY_HEADER_LEN;
+ dbkey.data = (unsigned char *)PORT_Alloc(dbkey.len*sizeof(unsigned char));
+ PORT_Memcpy(&dbkey.data[SEC_DB_KEY_HEADER_LEN], key->data, key->len);
+ dbkey.data[0] = type;
+
+ rv = WriteDBEntry(newdb, &common, &dbkey, data);
+
+ PORT_Free(dbkey.data);
+ return rv;
+}
+#endif
+
+int
+certIsOlder(CERTCertificate **cert1, CERTCertificate **cert2)
+{
+ return !CERT_IsNewer(*cert1, *cert2);
+}
+
+int
+findNewestSubjectForEmail(NSSLOWCERTCertDBHandle *handle, int subjectNum,
+ certDBArray *dbArray, dbRestoreInfo *info,
+ int *subjectWithSMime, int *smimeForSubject)
+{
+ int newestSubject;
+ int subjectsForEmail[50];
+ int i, j, ns, sNum;
+ certDBEntryListNode *subjects = &dbArray->subjects;
+ certDBEntryListNode *smime = &dbArray->smime;
+ certDBEntrySubject *subjectEntry1, *subjectEntry2;
+ certDBEntrySMime *smimeEntry;
+ CERTCertificate **certs;
+ CERTCertificate *cert;
+ CERTCertTrust *trust;
+ PRBool userCert;
+ int *certNums;
+
+ ns = 0;
+ subjectEntry1 = (certDBEntrySubject *)&subjects.entries[subjectNum];
+ subjectsForEmail[ns++] = subjectNum;
+
+ *subjectWithSMime = -1;
+ *smimeForSubject = -1;
+ newestSubject = subjectNum;
+
+ cert = CERT_FindCertByKey(handle, &subjectEntry1->certKeys[0]);
+ if (cert) {
+ trust = cert->trust;
+ userCert = (SEC_GET_TRUST_FLAGS(trust, trustSSL) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustEmail) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustObjectSigning) & CERTDB_USER);
+ CERT_DestroyCertificate(cert);
+ }
+
+ /*
+ * XXX Should we make sure that subjectEntry1->emailAddr is not
+ * a null pointer or an empty string before going into the next
+ * two for loops, which pass it to PORT_Strcmp?
+ */
+
+ /* Loop over the remaining subjects. */
+ for (i = subjectNum + 1; i < subjects.numEntries; i++) {
+ subjectEntry2 = (certDBEntrySubject *)&subjects.entries[i];
+ if (!subjectEntry2)
+ continue;
+ if (subjectEntry2->emailAddr && subjectEntry2->emailAddr[0] &&
+ PORT_Strcmp(subjectEntry1->emailAddr,
+ subjectEntry2->emailAddr) == 0) {
+ /* Found a subject using the same email address. */
+ subjectsForEmail[ns++] = i;
+ }
+ }
+
+ /* Find the S/MIME entry for this email address. */
+ for (i = 0; i < smime.numEntries; i++) {
+ smimeEntry = (certDBEntrySMime *)&smime.entries[i];
+ if (smimeEntry->common.arena == NULL)
+ continue;
+ if (smimeEntry->emailAddr && smimeEntry->emailAddr[0] &&
+ PORT_Strcmp(subjectEntry1->emailAddr, smimeEntry->emailAddr) == 0) {
+ /* Find which of the subjects uses this S/MIME entry. */
+ for (j = 0; j < ns && *subjectWithSMime < 0; j++) {
+ sNum = subjectsForEmail[j];
+ subjectEntry2 = (certDBEntrySubject *)&subjects.entries[sNum];
+ if (SECITEM_ItemsAreEqual(&smimeEntry->subjectName,
+ &subjectEntry2->derSubject)) {
+ /* Found the subject corresponding to the S/MIME entry. */
+ *subjectWithSMime = sNum;
+ *smimeForSubject = i;
+ }
+ }
+ SEC_DestroyDBEntry((certDBEntry *)smimeEntry);
+ PORT_Memset(smimeEntry, 0, sizeof(certDBEntry));
+ break;
+ }
+ }
+
+ if (ns <= 1)
+ return subjectNum;
+
+ if (userCert)
+ return *subjectWithSMime;
+
+ /* Now find which of the subjects has the newest cert. */
+ certs = (CERTCertificate **)PORT_Alloc(ns * sizeof(CERTCertificate *));
+ certNums = (int *)PORT_Alloc((ns + 1) * sizeof(int));
+ certNums[0] = 0;
+ for (i = 0; i < ns; i++) {
+ sNum = subjectsForEmail[i];
+ subjectEntry1 = (certDBEntrySubject *)&subjects.entries[sNum];
+ certs[i] = CERT_FindCertByKey(handle, &subjectEntry1->certKeys[0]);
+ certNums[i + 1] = i;
+ }
+ /* Sort the array by validity. */
+ qsort(certs, ns, sizeof(CERTCertificate *),
+ (int (*)(const void *, const void *))certIsOlder);
+ newestSubject = -1;
+ for (i = 0; i < ns; i++) {
+ sNum = subjectsForEmail[i];
+ subjectEntry1 = (certDBEntrySubject *)&subjects.entries[sNum];
+ if (SECITEM_ItemsAreEqual(&subjectEntry1->derSubject,
+ &certs[0]->derSubject))
+ newestSubject = sNum;
+ else
+ SEC_DestroyDBEntry((certDBEntry *)subjectEntry1);
+ }
+ if (info && userSaysDeleteCert(certs, ns, dbOlderCert, info, certNums)) {
+ for (i = 1; i < ns + 1; i++) {
+ if (certNums[i] >= 0 && certNums[i] != certNums[0]) {
+ deleteAllEntriesForCert(handle, certs[certNums[i]], info->out);
+ info->dbErrors[dbOlderCert]++;
+ }
+ }
+ }
+ CERT_DestroyCertArray(certs, ns);
+ return newestSubject;
+}
+
+NSSLOWCERTCertDBHandle *
+DBCK_ReconstructDBFromCerts(NSSLOWCERTCertDBHandle *oldhandle, char *newdbname,
+ PRFileDesc *outfile, PRBool removeExpired,
+ PRBool requireProfile, PRBool singleEntry,
+ PRBool promptUser)
+{
+ SECStatus rv;
+ dbRestoreInfo info;
+ certDBEntryContentVersion *oldContentVersion;
+ certDBArray dbArray;
+ int i;
+
+ PORT_Memset(&dbArray, 0, sizeof(dbArray));
+ PORT_Memset(&info, 0, sizeof(info));
+ info.verbose = (outfile) ? PR_TRUE : PR_FALSE;
+ info.out = (outfile) ? outfile : PR_STDOUT;
+ info.removeType[dbInvalidCert] = removeExpired;
+ info.removeType[dbNoSMimeProfile] = requireProfile;
+ info.removeType[dbOlderCert] = singleEntry;
+ info.promptUser[dbInvalidCert] = promptUser;
+ info.promptUser[dbNoSMimeProfile] = promptUser;
+ info.promptUser[dbOlderCert] = promptUser;
+
+ /* Allocate a handle to fill with CERT_OpenCertDB below. */
+ info.handle = PORT_ZNew(NSSLOWCERTCertDBHandle);
+ if (!info.handle) {
+ fprintf(stderr, "unable to get database handle");
+ return NULL;
+ }
+
+ /* Create a certdb with the most recent set of roots. */
+ rv = CERT_OpenCertDBFilename(info.handle, newdbname, PR_FALSE);
+
+ if (rv) {
+ fprintf(stderr, "could not open certificate database");
+ goto loser;
+ }
+
+ /* Create certificate, subject, nickname, and email records.
+ * mcom_db seems to have a sequential access bug. Though reads and writes
+ * should be allowed during traversal, they seem to screw up the sequence.
+ * So, stuff all the cert entries into an array, and loop over the array
+ * doing read/writes in the db.
+ */
+ fillDBEntryArray(oldhandle, certDBEntryTypeCert, &dbArray.certs);
+ for (elem = PR_LIST_HEAD(&dbArray->certs.link);
+ elem != &dbArray->certs.link; elem = PR_NEXT_LINK(elem)) {
+ node = LISTNODE_CAST(elem);
+ addCertToDB((certDBEntryCert *)&node->entry, &info, oldhandle);
+ /* entries get destroyed in addCertToDB */
+ }
+#if 0
+ rv = nsslowcert_TraverseDBEntries(oldhandle, certDBEntryTypeSMimeProfile,
+ copyDBEntry, info.handle);
+#endif
+
+/* Fix up the pointers between (nickname|S/MIME) --> (subject).
+ * Create S/MIME entries for S/MIME certs.
+ * Have the S/MIME entry point to the last-expiring cert using
+ * an email address.
+ */
+#if 0
+ CERT_RedoHandlesForSubjects(info.handle, singleEntry, &info);
+#endif
+
+ freeDBEntryList(&dbArray.certs.link);
+
+/* Copy over the version record. */
+/* XXX Already exists - and _must_ be correct... */
+/*
+ versionEntry = ReadDBVersionEntry(oldhandle);
+ rv = WriteDBVersionEntry(info.handle, versionEntry);
+ */
+
+/* Copy over the content version record. */
+/* XXX Can probably get useful info from old content version?
+ * Was this db created before/after this tool? etc.
+ */
+#if 0
+ oldContentVersion = ReadDBContentVersionEntry(oldhandle);
+ CERT_SetDBContentVersion(oldContentVersion->contentVersion, info.handle);
+#endif
+
+#if 0
+ /* Copy over the CRL & KRL records. */
+ rv = nsslowcert_TraverseDBEntries(oldhandle, certDBEntryTypeRevocation,
+ copyDBEntry, info.handle);
+ /* XXX Only one KRL, just do db->get? */
+ rv = nsslowcert_TraverseDBEntries(oldhandle, certDBEntryTypeKeyRevocation,
+ copyDBEntry, info.handle);
+#endif
+
+ PR_fprintf(info.out, "Database had %d certificates.\n", info.nOldCerts);
+
+ PR_fprintf(info.out, "Reconstructed %d certificates.\n", info.nCerts);
+ PR_fprintf(info.out, "(ax) Rejected %d expired certificates.\n",
+ info.dbErrors[dbInvalidCert]);
+ PR_fprintf(info.out, "(as) Rejected %d S/MIME certificates missing a profile.\n",
+ info.dbErrors[dbNoSMimeProfile]);
+ PR_fprintf(info.out, "(ar) Rejected %d certificates for which a newer certificate was found.\n",
+ info.dbErrors[dbOlderCert]);
+ PR_fprintf(info.out, " Rejected %d corrupt certificates.\n",
+ info.dbErrors[dbBadCertificate]);
+ PR_fprintf(info.out, " Rejected %d certificates which did not write to the DB.\n",
+ info.dbErrors[dbCertNotWrittenToDB]);
+
+ if (rv)
+ goto loser;
+
+ return info.handle;
+
+loser:
+ if (info.handle)
+ PORT_Free(info.handle);
+ return NULL;
+}
diff --git a/security/nss/cmd/dbck/manifest.mn b/security/nss/cmd/dbck/manifest.mn
new file mode 100644
index 000000000..ec8812edb
--- /dev/null
+++ b/security/nss/cmd/dbck/manifest.mn
@@ -0,0 +1,22 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ dbck.c \
+ $(NULL)
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = dbm seccmd
+
+PROGRAM = dbck
+USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/dbtest/Makefile b/security/nss/cmd/dbtest/Makefile
new file mode 100644
index 000000000..a27a3ce97
--- /dev/null
+++ b/security/nss/cmd/dbtest/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#include ../platlibs.mk
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/dbtest/dbtest.c b/security/nss/cmd/dbtest/dbtest.c
new file mode 100644
index 000000000..9a6a034a6
--- /dev/null
+++ b/security/nss/cmd/dbtest/dbtest.c
@@ -0,0 +1,244 @@
+/* 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/. */
+
+/*
+** dbtest.c
+**
+** QA test for cert and key databases, especially to open
+** database readonly (NSS_INIT_READONLY) and force initializations
+** even if the databases cannot be opened (NSS_INIT_FORCEOPEN)
+**
+*/
+#include <stdio.h>
+#include <string.h>
+
+#if defined(WIN32)
+#include "fcntl.h"
+#include "io.h"
+#endif
+
+#include "secutil.h"
+#include "pk11pub.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "certdb.h"
+#include "nss.h"
+#include "../modutil/modutil.h"
+
+#include "plgetopt.h"
+
+static char *progName;
+
+char *dbDir = NULL;
+
+static char *dbName[] = { "secmod.db", "cert8.db", "key3.db" };
+static char *dbprefix = "";
+static char *secmodName = "secmod.db";
+static char *userPassword = "";
+PRBool verbose;
+
+static char *
+getPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ int *success = (int *)arg;
+
+ if (retry) {
+ *success = 0;
+ return NULL;
+ }
+
+ *success = 1;
+ return PORT_Strdup(userPassword);
+}
+
+static void
+Usage(const char *progName)
+{
+ printf("Usage: %s [-r] [-f] [-i] [-d dbdir ] \n",
+ progName);
+ printf("%-20s open database readonly (NSS_INIT_READONLY)\n", "-r");
+ printf("%-20s Continue to force initializations even if the\n", "-f");
+ printf("%-20s databases cannot be opened (NSS_INIT_FORCEOPEN)\n", " ");
+ printf("%-20s Try to initialize the database\n", "-i");
+ printf("%-20s Supply a password with which to initialize the db\n", "-p");
+ printf("%-20s Directory with cert database (default is .\n",
+ "-d certdir");
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ PLOptState *optstate;
+ PLOptStatus optstatus;
+
+ PRUint32 flags = 0;
+ Error ret;
+ SECStatus rv;
+ char *dbString = NULL;
+ PRBool doInitTest = PR_FALSE;
+ int i;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName + 1 : argv[0];
+
+ optstate = PL_CreateOptState(argc, argv, "rfip:d:h");
+
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'h':
+ default:
+ Usage(progName);
+ break;
+
+ case 'r':
+ flags |= NSS_INIT_READONLY;
+ break;
+
+ case 'f':
+ flags |= NSS_INIT_FORCEOPEN;
+ break;
+
+ case 'i':
+ doInitTest = PR_TRUE;
+ break;
+
+ case 'p':
+ userPassword = PORT_Strdup(optstate->value);
+ break;
+
+ case 'd':
+ dbDir = PORT_Strdup(optstate->value);
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+ if (optstatus == PL_OPT_BAD)
+ Usage(progName);
+
+ if (dbDir) {
+ char *tmp = dbDir;
+ dbDir = SECU_ConfigDirectory(tmp);
+ PORT_Free(tmp);
+ } else {
+ /* Look in $SSL_DIR */
+ dbDir = SECU_ConfigDirectory(SECU_DefaultSSLDir());
+ }
+ PR_fprintf(PR_STDERR, "dbdir selected is %s\n\n", dbDir);
+
+ if (dbDir[0] == '\0') {
+ PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
+ ret = DIR_DOESNT_EXIST_ERR;
+ goto loser;
+ }
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+
+ /* get the status of the directory and databases and output message */
+ if (PR_Access(dbDir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
+ } else if (PR_Access(dbDir, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dbDir);
+ } else {
+ if (!(flags & NSS_INIT_READONLY) &&
+ PR_Access(dbDir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dbDir);
+ }
+ if (!doInitTest) {
+ for (i = 0; i < 3; i++) {
+ dbString = PR_smprintf("%s/%s", dbDir, dbName[i]);
+ PR_fprintf(PR_STDOUT, "database checked is %s\n", dbString);
+ if (PR_Access(dbString, PR_ACCESS_EXISTS) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_DOESNT_EXIST_ERR],
+ dbString);
+ } else if (PR_Access(dbString, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR],
+ dbString);
+ } else if (!(flags & NSS_INIT_READONLY) &&
+ PR_Access(dbString, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
+ dbString);
+ }
+ PR_smprintf_free(dbString);
+ }
+ }
+ }
+
+ rv = NSS_Initialize(SECU_ConfigDirectory(dbDir), dbprefix, dbprefix,
+ secmodName, flags);
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ ret = NSS_INITIALIZE_FAILED_ERR;
+ } else {
+ ret = SUCCESS;
+ if (doInitTest) {
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot();
+ SECStatus rv;
+ int passwordSuccess = 0;
+ int type = CKM_DES3_CBC;
+ SECItem keyid = { 0, NULL, 0 };
+ unsigned char keyIdData[] = { 0xff, 0xfe };
+ PK11SymKey *key = NULL;
+
+ keyid.data = keyIdData;
+ keyid.len = sizeof(keyIdData);
+
+ PK11_SetPasswordFunc(getPassword);
+ rv = PK11_InitPin(slot, (char *)NULL, userPassword);
+ if (rv != SECSuccess) {
+ PR_fprintf(PR_STDERR, "Failed to Init DB: %s\n",
+ SECU_Strerror(PORT_GetError()));
+ ret = CHANGEPW_FAILED_ERR;
+ }
+ if (*userPassword && !PK11_IsLoggedIn(slot, &passwordSuccess)) {
+ PR_fprintf(PR_STDERR, "New DB did not log in after init\n");
+ ret = AUTHENTICATION_FAILED_ERR;
+ }
+ /* generate a symetric key */
+ key = PK11_TokenKeyGen(slot, type, NULL, 0, &keyid,
+ PR_TRUE, &passwordSuccess);
+
+ if (!key) {
+ PR_fprintf(PR_STDERR, "Could not generated symetric key: %s\n",
+ SECU_Strerror(PORT_GetError()));
+ exit(UNSPECIFIED_ERR);
+ }
+ PK11_FreeSymKey(key);
+ PK11_Logout(slot);
+
+ PK11_Authenticate(slot, PR_TRUE, &passwordSuccess);
+
+ if (*userPassword && !passwordSuccess) {
+ PR_fprintf(PR_STDERR, "New DB Did not initalize\n");
+ ret = AUTHENTICATION_FAILED_ERR;
+ }
+ key = PK11_FindFixedKey(slot, type, &keyid, &passwordSuccess);
+
+ if (!key) {
+ PR_fprintf(PR_STDERR, "Could not find generated key: %s\n",
+ SECU_Strerror(PORT_GetError()));
+ ret = UNSPECIFIED_ERR;
+ } else {
+ PK11_FreeSymKey(key);
+ }
+ PK11_FreeSlot(slot);
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ PR_fprintf(PR_STDERR, "Could not find generated key: %s\n",
+ SECU_Strerror(PORT_GetError()));
+ exit(1);
+ }
+ }
+
+loser:
+ return ret;
+}
diff --git a/security/nss/cmd/dbtest/dbtest.gyp b/security/nss/cmd/dbtest/dbtest.gyp
new file mode 100644
index 000000000..fb5857328
--- /dev/null
+++ b/security/nss/cmd/dbtest/dbtest.gyp
@@ -0,0 +1,25 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'dbtest',
+ 'type': 'executable',
+ 'sources': [
+ 'dbtest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/dbtest/manifest.mn b/security/nss/cmd/dbtest/manifest.mn
new file mode 100644
index 000000000..8f9ec1f67
--- /dev/null
+++ b/security/nss/cmd/dbtest/manifest.mn
@@ -0,0 +1,22 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+# DIRS =
+
+CSRCS = dbtest.c
+
+PROGRAM = dbtest
+
diff --git a/security/nss/cmd/derdump/Makefile b/security/nss/cmd/derdump/Makefile
new file mode 100644
index 000000000..c2039d82b
--- /dev/null
+++ b/security/nss/cmd/derdump/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/derdump/derdump.c b/security/nss/cmd/derdump/derdump.c
new file mode 100644
index 000000000..d687a8b7a
--- /dev/null
+++ b/security/nss/cmd/derdump/derdump.c
@@ -0,0 +1,128 @@
+/* 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/. */
+
+#include "secutil.h"
+#include "nss.h"
+#include <errno.h>
+
+#if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
+#if !defined(WIN32)
+extern int fprintf(FILE *, char *, ...);
+#endif
+#endif
+#include "plgetopt.h"
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-r] [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s For formatted items, dump raw bytes as well\n",
+ "-r");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ FILE *outFile;
+ PRFileDesc *inFile;
+ SECItem der = { siBuffer, NULL, 0 };
+ SECStatus rv;
+ PRInt16 xp_error;
+ PRBool raw = PR_FALSE;
+ PLOptState *optstate;
+ PLOptStatus status;
+ int retval = -1;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ /* Parse command line arguments */
+ inFile = 0;
+ outFile = 0;
+ optstate = PL_CreateOptState(argc, argv, "i:o:r");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'i':
+ inFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ goto cleanup;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ goto cleanup;
+ }
+ break;
+
+ case 'r':
+ raw = PR_TRUE;
+ break;
+
+ default:
+ Usage(progName);
+ break;
+ }
+ }
+ if (status == PL_OPT_BAD)
+ Usage(progName);
+
+ if (!inFile)
+ inFile = PR_STDIN;
+ if (!outFile)
+ outFile = stdout;
+
+ rv = NSS_NoDB_Init(NULL);
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ goto cleanup;
+ }
+
+ rv = SECU_ReadDERFromFile(&der, inFile, PR_FALSE, PR_FALSE);
+ if (rv == SECSuccess) {
+ rv = DER_PrettyPrint(outFile, &der, raw);
+ if (rv == SECSuccess) {
+ retval = 0;
+ goto cleanup;
+ }
+ }
+
+ xp_error = PORT_GetError();
+ if (xp_error) {
+ SECU_PrintError(progName, "error %d", xp_error);
+ }
+ if (errno) {
+ SECU_PrintSystemError(progName, "errno=%d", errno);
+ }
+ retval = 1;
+
+cleanup:
+ retval |= NSS_Shutdown();
+ if (inFile) {
+ PR_Close(inFile);
+ }
+ if (outFile) {
+ fflush(outFile);
+ fclose(outFile);
+ }
+ PL_DestroyOptState(optstate);
+ if (der.data) {
+ PORT_Free(der.data);
+ }
+
+ return retval;
+}
diff --git a/security/nss/cmd/derdump/derdump.gyp b/security/nss/cmd/derdump/derdump.gyp
new file mode 100644
index 000000000..5637685da
--- /dev/null
+++ b/security/nss/cmd/derdump/derdump.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'derdump',
+ 'type': 'executable',
+ 'sources': [
+ 'derdump.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/derdump/manifest.mn b/security/nss/cmd/derdump/manifest.mn
new file mode 100644
index 000000000..0b550377c
--- /dev/null
+++ b/security/nss/cmd/derdump/manifest.mn
@@ -0,0 +1,21 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = derdump.c
+
+PROGRAM = derdump
diff --git a/security/nss/cmd/digest/Makefile b/security/nss/cmd/digest/Makefile
new file mode 100644
index 000000000..c2039d82b
--- /dev/null
+++ b/security/nss/cmd/digest/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/digest/digest.c b/security/nss/cmd/digest/digest.c
new file mode 100644
index 000000000..8c4c14926
--- /dev/null
+++ b/security/nss/cmd/digest/digest.c
@@ -0,0 +1,228 @@
+/* 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/. */
+
+#include "secutil.h"
+#include "pk11func.h"
+#include "secoid.h"
+
+#if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
+#if !defined(WIN32)
+extern int fread(char *, size_t, size_t, FILE *);
+extern int fwrite(char *, size_t, size_t, FILE *);
+extern int fprintf(FILE *, char *, ...);
+#endif
+#endif
+
+#include "plgetopt.h"
+
+static SECOidData *
+HashTypeToOID(HASH_HashType hashtype)
+{
+ SECOidTag hashtag;
+
+ if (hashtype <= HASH_AlgNULL || hashtype >= HASH_AlgTOTAL)
+ return NULL;
+
+ switch (hashtype) {
+ case HASH_AlgMD2:
+ hashtag = SEC_OID_MD2;
+ break;
+ case HASH_AlgMD5:
+ hashtag = SEC_OID_MD5;
+ break;
+ case HASH_AlgSHA1:
+ hashtag = SEC_OID_SHA1;
+ break;
+ default:
+ fprintf(stderr, "A new hash type has been added to HASH_HashType.\n");
+ fprintf(stderr, "This program needs to be updated!\n");
+ return NULL;
+ }
+
+ return SECOID_FindOIDByTag(hashtag);
+}
+
+static SECOidData *
+HashNameToOID(const char *hashName)
+{
+ HASH_HashType htype;
+ SECOidData *hashOID;
+
+ for (htype = HASH_AlgNULL + 1; htype < HASH_AlgTOTAL; htype++) {
+ hashOID = HashTypeToOID(htype);
+ if (PORT_Strcasecmp(hashName, hashOID->desc) == 0)
+ break;
+ }
+
+ if (htype == HASH_AlgTOTAL)
+ return NULL;
+
+ return hashOID;
+}
+
+static void
+Usage(char *progName)
+{
+ HASH_HashType htype;
+
+ fprintf(stderr,
+ "Usage: %s -t type [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s Specify the digest method (must be one of\n",
+ "-t type");
+ fprintf(stderr, "%-20s ", "");
+ for (htype = HASH_AlgNULL + 1; htype < HASH_AlgTOTAL; htype++) {
+ fprintf(stderr, "%s", HashTypeToOID(htype)->desc);
+ if (htype == (HASH_AlgTOTAL - 2))
+ fprintf(stderr, " or ");
+ else if (htype != (HASH_AlgTOTAL - 1))
+ fprintf(stderr, ", ");
+ }
+ fprintf(stderr, " (case ignored))\n");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+static int
+DigestFile(FILE *outFile, FILE *inFile, SECOidData *hashOID)
+{
+ int nb;
+ unsigned char ibuf[4096], digest[32];
+ PK11Context *hashcx;
+ unsigned int len;
+ SECStatus rv;
+
+ hashcx = PK11_CreateDigestContext(hashOID->offset);
+ if (hashcx == NULL) {
+ return -1;
+ }
+ PK11_DigestBegin(hashcx);
+
+ for (;;) {
+ if (feof(inFile))
+ break;
+ nb = fread(ibuf, 1, sizeof(ibuf), inFile);
+ if (nb != sizeof(ibuf)) {
+ if (nb == 0) {
+ if (ferror(inFile)) {
+ PORT_SetError(SEC_ERROR_IO);
+ PK11_DestroyContext(hashcx, PR_TRUE);
+ return -1;
+ }
+ /* eof */
+ break;
+ }
+ }
+ rv = PK11_DigestOp(hashcx, ibuf, nb);
+ if (rv != SECSuccess) {
+ PK11_DestroyContext(hashcx, PR_TRUE);
+ return -1;
+ }
+ }
+
+ rv = PK11_DigestFinal(hashcx, digest, &len, 32);
+ PK11_DestroyContext(hashcx, PR_TRUE);
+
+ if (rv != SECSuccess)
+ return -1;
+
+ nb = fwrite(digest, 1, len, outFile);
+ if (nb != len) {
+ PORT_SetError(SEC_ERROR_IO);
+ return -1;
+ }
+
+ return 0;
+}
+
+#include "nss.h"
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ FILE *inFile, *outFile;
+ char *hashName;
+ SECOidData *hashOID;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus rv;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ inFile = NULL;
+ outFile = NULL;
+ hashName = NULL;
+
+ rv = NSS_Init("/tmp");
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: NSS_Init failed in directory %s\n",
+ progName, "/tmp");
+ return -1;
+ }
+
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv, "t:i:o:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'i':
+ inFile = fopen(optstate->value, "r");
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 't':
+ hashName = strdup(optstate->value);
+ break;
+ }
+ }
+
+ if (!hashName)
+ Usage(progName);
+
+ if (!inFile)
+ inFile = stdin;
+ if (!outFile)
+ outFile = stdout;
+
+ hashOID = HashNameToOID(hashName);
+ if (hashOID == NULL) {
+ fprintf(stderr, "%s: invalid digest type\n", progName);
+ Usage(progName);
+ }
+
+ if (DigestFile(outFile, inFile, hashOID)) {
+ fprintf(stderr, "%s: problem digesting data (%s)\n",
+ progName, SECU_Strerror(PORT_GetError()));
+ return -1;
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/security/nss/cmd/digest/digest.gyp b/security/nss/cmd/digest/digest.gyp
new file mode 100644
index 000000000..c2e00289f
--- /dev/null
+++ b/security/nss/cmd/digest/digest.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'digest',
+ 'type': 'executable',
+ 'sources': [
+ 'digest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/digest/manifest.mn b/security/nss/cmd/digest/manifest.mn
new file mode 100644
index 000000000..3e764063a
--- /dev/null
+++ b/security/nss/cmd/digest/manifest.mn
@@ -0,0 +1,22 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = digest.c
+
+PROGRAM = digest
+
diff --git a/security/nss/cmd/ecperf/Makefile b/security/nss/cmd/ecperf/Makefile
new file mode 100644
index 000000000..7b74b369c
--- /dev/null
+++ b/security/nss/cmd/ecperf/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/ecperf/ecperf.c b/security/nss/cmd/ecperf/ecperf.c
new file mode 100644
index 000000000..814c0352d
--- /dev/null
+++ b/security/nss/cmd/ecperf/ecperf.c
@@ -0,0 +1,726 @@
+/* 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/. */
+
+#include "blapi.h"
+#include "ec.h"
+#include "ecl-curve.h"
+#include "prprf.h"
+#include "basicutil.h"
+#include "pkcs11.h"
+#include "nspr.h"
+#include "secutil.h"
+#include <stdio.h>
+
+#define __PASTE(x, y) x##y
+
+/*
+ * Get the NSS specific PKCS #11 function names.
+ */
+#undef CK_PKCS11_FUNCTION_INFO
+#undef CK_NEED_ARG_LIST
+
+#define CK_EXTERN extern
+#define CK_PKCS11_FUNCTION_INFO(func) \
+ CK_RV __PASTE(NS, func)
+#define CK_NEED_ARG_LIST 1
+
+#include "pkcs11f.h"
+
+/* mapping between ECCurveName enum and pointers to ECCurveParams */
+static SECOidTag ecCurve_oid_map[] = {
+ SEC_OID_UNKNOWN, /* ECCurve_noName */
+ SEC_OID_ANSIX962_EC_PRIME192V1, /* ECCurve_NIST_P192 */
+ SEC_OID_SECG_EC_SECP224R1, /* ECCurve_NIST_P224 */
+ SEC_OID_ANSIX962_EC_PRIME256V1, /* ECCurve_NIST_P256 */
+ SEC_OID_SECG_EC_SECP384R1, /* ECCurve_NIST_P384 */
+ SEC_OID_SECG_EC_SECP521R1, /* ECCurve_NIST_P521 */
+ SEC_OID_SECG_EC_SECT163K1, /* ECCurve_NIST_K163 */
+ SEC_OID_SECG_EC_SECT163R1, /* ECCurve_NIST_B163 */
+ SEC_OID_SECG_EC_SECT233K1, /* ECCurve_NIST_K233 */
+ SEC_OID_SECG_EC_SECT233R1, /* ECCurve_NIST_B233 */
+ SEC_OID_SECG_EC_SECT283K1, /* ECCurve_NIST_K283 */
+ SEC_OID_SECG_EC_SECT283R1, /* ECCurve_NIST_B283 */
+ SEC_OID_SECG_EC_SECT409K1, /* ECCurve_NIST_K409 */
+ SEC_OID_SECG_EC_SECT409R1, /* ECCurve_NIST_B409 */
+ SEC_OID_SECG_EC_SECT571K1, /* ECCurve_NIST_K571 */
+ SEC_OID_SECG_EC_SECT571R1, /* ECCurve_NIST_B571 */
+ SEC_OID_ANSIX962_EC_PRIME192V2,
+ SEC_OID_ANSIX962_EC_PRIME192V3,
+ SEC_OID_ANSIX962_EC_PRIME239V1,
+ SEC_OID_ANSIX962_EC_PRIME239V2,
+ SEC_OID_ANSIX962_EC_PRIME239V3,
+ SEC_OID_ANSIX962_EC_C2PNB163V1,
+ SEC_OID_ANSIX962_EC_C2PNB163V2,
+ SEC_OID_ANSIX962_EC_C2PNB163V3,
+ SEC_OID_ANSIX962_EC_C2PNB176V1,
+ SEC_OID_ANSIX962_EC_C2TNB191V1,
+ SEC_OID_ANSIX962_EC_C2TNB191V2,
+ SEC_OID_ANSIX962_EC_C2TNB191V3,
+ SEC_OID_ANSIX962_EC_C2PNB208W1,
+ SEC_OID_ANSIX962_EC_C2TNB239V1,
+ SEC_OID_ANSIX962_EC_C2TNB239V2,
+ SEC_OID_ANSIX962_EC_C2TNB239V3,
+ SEC_OID_ANSIX962_EC_C2PNB272W1,
+ SEC_OID_ANSIX962_EC_C2PNB304W1,
+ SEC_OID_ANSIX962_EC_C2TNB359V1,
+ SEC_OID_ANSIX962_EC_C2PNB368W1,
+ SEC_OID_ANSIX962_EC_C2TNB431R1,
+ SEC_OID_SECG_EC_SECP112R1,
+ SEC_OID_SECG_EC_SECP112R2,
+ SEC_OID_SECG_EC_SECP128R1,
+ SEC_OID_SECG_EC_SECP128R2,
+ SEC_OID_SECG_EC_SECP160K1,
+ SEC_OID_SECG_EC_SECP160R1,
+ SEC_OID_SECG_EC_SECP160R2,
+ SEC_OID_SECG_EC_SECP192K1,
+ SEC_OID_SECG_EC_SECP224K1,
+ SEC_OID_SECG_EC_SECP256K1,
+ SEC_OID_SECG_EC_SECT113R1,
+ SEC_OID_SECG_EC_SECT113R2,
+ SEC_OID_SECG_EC_SECT131R1,
+ SEC_OID_SECG_EC_SECT131R2,
+ SEC_OID_SECG_EC_SECT163R1,
+ SEC_OID_SECG_EC_SECT193R1,
+ SEC_OID_SECG_EC_SECT193R2,
+ SEC_OID_SECG_EC_SECT239K1,
+ SEC_OID_UNKNOWN, /* ECCurve_WTLS_1 */
+ SEC_OID_UNKNOWN, /* ECCurve_WTLS_8 */
+ SEC_OID_UNKNOWN, /* ECCurve_WTLS_9 */
+ SEC_OID_CURVE25519,
+ SEC_OID_UNKNOWN /* ECCurve_pastLastCurve */
+};
+
+typedef SECStatus (*op_func)(void *, void *, void *);
+typedef SECStatus (*pk11_op_func)(CK_SESSION_HANDLE, void *, void *, void *);
+
+typedef struct ThreadDataStr {
+ op_func op;
+ void *p1;
+ void *p2;
+ void *p3;
+ int iters;
+ PRLock *lock;
+ int count;
+ SECStatus status;
+ int isSign;
+} ThreadData;
+
+void
+PKCS11Thread(void *data)
+{
+ ThreadData *threadData = (ThreadData *)data;
+ pk11_op_func op = (pk11_op_func)threadData->op;
+ int iters = threadData->iters;
+ unsigned char sigData[256];
+ SECItem sig;
+ CK_SESSION_HANDLE session;
+ CK_RV crv;
+
+ threadData->status = SECSuccess;
+ threadData->count = 0;
+
+ /* get our thread's session */
+ PR_Lock(threadData->lock);
+ crv = NSC_OpenSession(1, CKF_SERIAL_SESSION, NULL, 0, &session);
+ PR_Unlock(threadData->lock);
+ if (crv != CKR_OK) {
+ return;
+ }
+
+ if (threadData->isSign) {
+ sig.data = sigData;
+ sig.len = sizeof(sigData);
+ threadData->p2 = (void *)&sig;
+ }
+
+ while (iters--) {
+ threadData->status = (*op)(session, threadData->p1,
+ threadData->p2, threadData->p3);
+ if (threadData->status != SECSuccess) {
+ break;
+ }
+ threadData->count++;
+ }
+ return;
+}
+
+void
+genericThread(void *data)
+{
+ ThreadData *threadData = (ThreadData *)data;
+ int iters = threadData->iters;
+ unsigned char sigData[256];
+ SECItem sig;
+
+ threadData->status = SECSuccess;
+ threadData->count = 0;
+
+ if (threadData->isSign) {
+ sig.data = sigData;
+ sig.len = sizeof(sigData);
+ threadData->p2 = (void *)&sig;
+ }
+
+ while (iters--) {
+ threadData->status = (*threadData->op)(threadData->p1,
+ threadData->p2, threadData->p3);
+ if (threadData->status != SECSuccess) {
+ break;
+ }
+ threadData->count++;
+ }
+ return;
+}
+
+/* Time iter repetitions of operation op. */
+SECStatus
+M_TimeOperation(void (*threadFunc)(void *),
+ op_func opfunc, char *op, void *param1, void *param2,
+ void *param3, int iters, int numThreads, PRLock *lock,
+ CK_SESSION_HANDLE session, int isSign, double *rate)
+{
+ double dUserTime;
+ int i, total;
+ PRIntervalTime startTime, totalTime;
+ PRThread **threadIDs;
+ ThreadData *threadData;
+ pk11_op_func pk11_op = (pk11_op_func)opfunc;
+ SECStatus rv;
+
+ /* verify operation works before testing performance */
+ if (session) {
+ rv = (*pk11_op)(session, param1, param2, param3);
+ } else {
+ rv = (*opfunc)(param1, param2, param3);
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintError("Error:", op);
+ return rv;
+ }
+
+ /* get Data structures */
+ threadIDs = (PRThread **)PORT_Alloc(numThreads * sizeof(PRThread *));
+ threadData = (ThreadData *)PORT_Alloc(numThreads * sizeof(ThreadData));
+
+ startTime = PR_Now();
+ if (numThreads == 1) {
+ for (i = 0; i < iters; i++) {
+ if (session) {
+ rv = (*pk11_op)(session, param1, param2, param3);
+ } else {
+ rv = (*opfunc)(param1, param2, param3);
+ }
+ if (rv != SECSuccess) {
+ PORT_Free(threadIDs);
+ PORT_Free(threadData);
+ SECU_PrintError("Error:", op);
+ return rv;
+ }
+ }
+ total = iters;
+ } else {
+ for (i = 0; i < numThreads; i++) {
+ threadData[i].op = opfunc;
+ threadData[i].p1 = (void *)param1;
+ threadData[i].p2 = (void *)param2;
+ threadData[i].p3 = (void *)param3;
+ threadData[i].iters = iters;
+ threadData[i].lock = lock;
+ threadData[i].isSign = isSign;
+ threadIDs[i] = PR_CreateThread(PR_USER_THREAD, threadFunc,
+ (void *)&threadData[i], PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ }
+
+ total = 0;
+ for (i = 0; i < numThreads; i++) {
+ PR_JoinThread(threadIDs[i]);
+ /* check the status */
+ total += threadData[i].count;
+ }
+ }
+
+ totalTime = PR_Now() - startTime;
+ /* SecondsToInterval seems to be broken here ... */
+ dUserTime = (double)totalTime / (double)1000000;
+ if (dUserTime) {
+ printf(" %-15s count:%4d sec: %3.2f op/sec: %6.2f\n",
+ op, total, dUserTime, (double)total / dUserTime);
+ if (rate) {
+ *rate = ((double)total) / dUserTime;
+ }
+ }
+ PORT_Free(threadIDs);
+ PORT_Free(threadData);
+
+ return SECSuccess;
+}
+
+/* Test curve using specific field arithmetic. */
+#define ECTEST_NAMED_GFP(name_c, name_v) \
+ if (usefreebl) { \
+ printf("Testing %s using freebl implementation...\n", name_c); \
+ rv = ectest_curve_freebl(name_v, iterations, numThreads, ec_field_GFp); \
+ if (rv != SECSuccess) \
+ goto cleanup; \
+ printf("... okay.\n"); \
+ } \
+ if (usepkcs11) { \
+ printf("Testing %s using pkcs11 implementation...\n", name_c); \
+ rv = ectest_curve_pkcs11(name_v, iterations, numThreads); \
+ if (rv != SECSuccess) \
+ goto cleanup; \
+ printf("... okay.\n"); \
+ }
+
+/* Test curve using specific field arithmetic. */
+#define ECTEST_NAMED_CUSTOM(name_c, name_v) \
+ if (usefreebl) { \
+ printf("Testing %s using freebl implementation...\n", name_c); \
+ rv = ectest_curve_freebl(name_v, iterations, numThreads, ec_field_plain); \
+ if (rv != SECSuccess) \
+ goto cleanup; \
+ printf("... okay.\n"); \
+ } \
+ if (usepkcs11) { \
+ printf("Testing %s using pkcs11 implementation...\n", name_c); \
+ rv = ectest_curve_pkcs11(name_v, iterations, numThreads); \
+ if (rv != SECSuccess) \
+ goto cleanup; \
+ printf("... okay.\n"); \
+ }
+
+#define PK11_SETATTRS(x, id, v, l) \
+ (x)->type = (id); \
+ (x)->pValue = (v); \
+ (x)->ulValueLen = (l);
+
+SECStatus
+PKCS11_Derive(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey,
+ CK_MECHANISM *pMech, int *dummy)
+{
+ CK_RV crv;
+ CK_OBJECT_HANDLE newKey;
+ CK_BBOOL cktrue = CK_TRUE;
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
+ CK_ATTRIBUTE keyTemplate[3];
+ CK_ATTRIBUTE *attrs = keyTemplate;
+
+ PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
+ attrs++;
+ PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
+ attrs++;
+ PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, 1);
+ attrs++;
+
+ crv = NSC_DeriveKey(session, pMech, *hKey, keyTemplate, 3, &newKey);
+ if (crv != CKR_OK) {
+ printf("Derive Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+PKCS11_Sign(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey,
+ SECItem *sig, SECItem *digest)
+{
+ CK_RV crv;
+ CK_MECHANISM mech;
+ CK_ULONG sigLen = sig->len;
+
+ mech.mechanism = CKM_ECDSA;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ crv = NSC_SignInit(session, &mech, *hKey);
+ if (crv != CKR_OK) {
+ printf("Sign Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+ crv = NSC_Sign(session, digest->data, digest->len, sig->data, &sigLen);
+ if (crv != CKR_OK) {
+ printf("Sign Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+ sig->len = (unsigned int)sigLen;
+ return SECSuccess;
+}
+
+SECStatus
+PKCS11_Verify(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey,
+ SECItem *sig, SECItem *digest)
+{
+ CK_RV crv;
+ CK_MECHANISM mech;
+
+ mech.mechanism = CKM_ECDSA;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ crv = NSC_VerifyInit(session, &mech, *hKey);
+ if (crv != CKR_OK) {
+ printf("Verify Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+ crv = NSC_Verify(session, digest->data, digest->len, sig->data, sig->len);
+ if (crv != CKR_OK) {
+ printf("Verify Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+ecName2params(ECCurveName curve, SECKEYECParams *params)
+{
+ SECOidData *oidData = NULL;
+
+ if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve) ||
+ ((oidData = SECOID_FindOIDByTag(ecCurve_oid_map[curve])) == NULL)) {
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
+ return SECFailure;
+ }
+
+ SECITEM_AllocItem(NULL, params, (2 + oidData->oid.len));
+ /*
+ * params->data needs to contain the ASN encoding of an object ID (OID)
+ * representing the named curve. The actual OID is in
+ * oidData->oid.data so we simply prepend 0x06 and OID length
+ */
+ params->data[0] = SEC_ASN1_OBJECT_ID;
+ params->data[1] = oidData->oid.len;
+ memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
+
+ return SECSuccess;
+}
+
+/* Performs basic tests of elliptic curve cryptography over prime fields.
+ * If tests fail, then it prints an error message, aborts, and returns an
+ * error code. Otherwise, returns 0. */
+SECStatus
+ectest_curve_pkcs11(ECCurveName curve, int iterations, int numThreads)
+{
+ CK_OBJECT_HANDLE ecPriv;
+ CK_OBJECT_HANDLE ecPub;
+ CK_SESSION_HANDLE session;
+ SECItem sig;
+ SECItem digest;
+ SECKEYECParams ecParams;
+ CK_MECHANISM mech;
+ CK_ECDH1_DERIVE_PARAMS ecdh_params;
+ unsigned char sigData[256];
+ unsigned char digestData[20];
+ unsigned char pubKeyData[256];
+ PRLock *lock = NULL;
+ double signRate, deriveRate = 0;
+ CK_ATTRIBUTE template;
+ SECStatus rv;
+ CK_RV crv;
+
+ ecParams.data = NULL;
+ ecParams.len = 0;
+ rv = ecName2params(curve, &ecParams);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+
+ crv = NSC_OpenSession(1, CKF_SERIAL_SESSION, NULL, 0, &session);
+ if (crv != CKR_OK) {
+ printf("OpenSession Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+
+ PORT_Memset(digestData, 0xa5, sizeof(digestData));
+ digest.data = digestData;
+ digest.len = sizeof(digestData);
+ sig.data = sigData;
+ sig.len = sizeof(sigData);
+
+ template.type = CKA_EC_PARAMS;
+ template.pValue = ecParams.data;
+ template.ulValueLen = ecParams.len;
+ mech.mechanism = CKM_EC_KEY_PAIR_GEN;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+ crv = NSC_GenerateKeyPair(session, &mech,
+ &template, 1, NULL, 0, &ecPub, &ecPriv);
+ if (crv != CKR_OK) {
+ printf("GenerateKeyPair Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+
+ template.type = CKA_EC_POINT;
+ template.pValue = pubKeyData;
+ template.ulValueLen = sizeof(pubKeyData);
+ crv = NSC_GetAttributeValue(session, ecPub, &template, 1);
+ if (crv != CKR_OK) {
+ printf("GenerateKeyPair Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+
+ ecdh_params.kdf = CKD_NULL;
+ ecdh_params.ulSharedDataLen = 0;
+ ecdh_params.pSharedData = NULL;
+ ecdh_params.ulPublicDataLen = template.ulValueLen;
+ ecdh_params.pPublicData = template.pValue;
+
+ mech.mechanism = CKM_ECDH1_DERIVE;
+ mech.pParameter = (void *)&ecdh_params;
+ mech.ulParameterLen = sizeof(ecdh_params);
+
+ lock = PR_NewLock();
+
+ if (ecCurve_map[curve]->usage & KU_KEY_AGREEMENT) {
+ rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Derive, "ECDH_Derive",
+ &ecPriv, &mech, NULL, iterations, numThreads,
+ lock, session, 0, &deriveRate);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ }
+
+ if (ecCurve_map[curve]->usage & KU_DIGITAL_SIGNATURE) {
+ rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Sign, "ECDSA_Sign",
+ (void *)&ecPriv, &sig, &digest, iterations, numThreads,
+ lock, session, 1, &signRate);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ printf(" ECDHE max rate = %.2f\n", (deriveRate + signRate) / 4.0);
+ /* get a signature */
+ rv = PKCS11_Sign(session, &ecPriv, &sig, &digest);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Verify, "ECDSA_Verify",
+ (void *)&ecPub, &sig, &digest, iterations, numThreads,
+ lock, session, 0, NULL);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if (lock) {
+ PR_DestroyLock(lock);
+ }
+ return rv;
+}
+
+SECStatus
+ECDH_DeriveWrap(ECPrivateKey *priv, ECPublicKey *pub, int *dummy)
+{
+ SECItem secret;
+ unsigned char secretData[256];
+ SECStatus rv;
+
+ secret.data = secretData;
+ secret.len = sizeof(secretData);
+
+ rv = ECDH_Derive(&pub->publicValue, &pub->ecParams,
+ &priv->privateValue, 0, &secret);
+ SECITEM_FreeItem(&secret, PR_FALSE);
+ return rv;
+}
+
+/* Performs basic tests of elliptic curve cryptography over prime fields.
+ * If tests fail, then it prints an error message, aborts, and returns an
+ * error code. Otherwise, returns 0. */
+SECStatus
+ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads,
+ ECFieldType fieldType)
+{
+ ECParams ecParams = { 0 };
+ ECPrivateKey *ecPriv = NULL;
+ ECPublicKey ecPub;
+ SECItem sig;
+ SECItem digest;
+ unsigned char sigData[256];
+ unsigned char digestData[20];
+ double signRate, deriveRate = 0;
+ char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
+ SECStatus rv = SECFailure;
+ PLArenaPool *arena;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ return SECFailure;
+ }
+
+ if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return SECFailure;
+ }
+
+ ecParams.name = curve;
+ ecParams.type = ec_params_named;
+ ecParams.curveOID.data = NULL;
+ ecParams.curveOID.len = 0;
+ ecParams.curve.seed.data = NULL;
+ ecParams.curve.seed.len = 0;
+ ecParams.DEREncoding.data = NULL;
+ ecParams.DEREncoding.len = 0;
+
+ ecParams.fieldID.size = ecCurve_map[curve]->size;
+ ecParams.fieldID.type = fieldType;
+ SECU_HexString2SECItem(arena, &ecParams.fieldID.u.prime, ecCurve_map[curve]->irr);
+ SECU_HexString2SECItem(arena, &ecParams.curve.a, ecCurve_map[curve]->curvea);
+ SECU_HexString2SECItem(arena, &ecParams.curve.b, ecCurve_map[curve]->curveb);
+ genenc[0] = '0';
+ genenc[1] = '4';
+ genenc[2] = '\0';
+ strcat(genenc, ecCurve_map[curve]->genx);
+ strcat(genenc, ecCurve_map[curve]->geny);
+ SECU_HexString2SECItem(arena, &ecParams.base, genenc);
+ SECU_HexString2SECItem(arena, &ecParams.order, ecCurve_map[curve]->order);
+ ecParams.cofactor = ecCurve_map[curve]->cofactor;
+
+ PORT_Memset(digestData, 0xa5, sizeof(digestData));
+ digest.data = digestData;
+ digest.len = sizeof(digestData);
+ sig.data = sigData;
+ sig.len = sizeof(sigData);
+
+ rv = EC_NewKey(&ecParams, &ecPriv);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ ecPub.ecParams = ecParams;
+ ecPub.publicValue = ecPriv->publicValue;
+
+ if (ecCurve_map[curve]->usage & KU_KEY_AGREEMENT) {
+ rv = M_TimeOperation(genericThread, (op_func)ECDH_DeriveWrap, "ECDH_Derive",
+ ecPriv, &ecPub, NULL, iterations, numThreads, 0, 0, 0, &deriveRate);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ }
+
+ if (ecCurve_map[curve]->usage & KU_DIGITAL_SIGNATURE) {
+ rv = M_TimeOperation(genericThread, (op_func)ECDSA_SignDigest, "ECDSA_Sign",
+ ecPriv, &sig, &digest, iterations, numThreads, 0, 0, 1, &signRate);
+ if (rv != SECSuccess)
+ goto cleanup;
+ printf(" ECDHE max rate = %.2f\n", (deriveRate + signRate) / 4.0);
+ rv = ECDSA_SignDigest(ecPriv, &sig, &digest);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ rv = M_TimeOperation(genericThread, (op_func)ECDSA_VerifyDigest, "ECDSA_Verify",
+ &ecPub, &sig, &digest, iterations, numThreads, 0, 0, 0, NULL);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ PORT_FreeArena(arena, PR_FALSE);
+ PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE);
+ return rv;
+}
+
+/* Prints help information. */
+void
+printUsage(char *prog)
+{
+ printf("Usage: %s [-i iterations] [-t threads ] [-ans] [-fp] [-Al]\n"
+ "-a: ansi\n-n: nist\n-s: secp\n-f: usefreebl\n-p: usepkcs11\n-A: all\n",
+ prog);
+}
+
+/* Performs tests of elliptic curve cryptography over prime fields If
+ * tests fail, then it prints an error message, aborts, and returns an
+ * error code. Otherwise, returns 0. */
+int
+main(int argv, char **argc)
+{
+ int ansi = 0;
+ int nist = 0;
+ int secp = 0;
+ int usefreebl = 0;
+ int usepkcs11 = 0;
+ int i;
+ SECStatus rv = SECSuccess;
+ int iterations = 100;
+ int numThreads = 1;
+
+ const CK_C_INITIALIZE_ARGS pk11args = {
+ NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
+ (void *)"flags=readOnly,noCertDB,noModDB", NULL
+ };
+
+ /* read command-line arguments */
+ for (i = 1; i < argv; i++) {
+ if (PL_strcasecmp(argc[i], "-i") == 0) {
+ i++;
+ iterations = atoi(argc[i]);
+ } else if (PL_strcasecmp(argc[i], "-t") == 0) {
+ i++;
+ numThreads = atoi(argc[i]);
+ } else if (PL_strcasecmp(argc[i], "-A") == 0) {
+ ansi = nist = secp = 1;
+ usepkcs11 = usefreebl = 1;
+ } else if (PL_strcasecmp(argc[i], "-a") == 0) {
+ ansi = 1;
+ } else if (PL_strcasecmp(argc[i], "-n") == 0) {
+ nist = 1;
+ } else if (PL_strcasecmp(argc[i], "-s") == 0) {
+ secp = 1;
+ } else if (PL_strcasecmp(argc[i], "-p") == 0) {
+ usepkcs11 = 1;
+ } else if (PL_strcasecmp(argc[i], "-f") == 0) {
+ usefreebl = 1;
+ } else {
+ printUsage(argc[0]);
+ return 0;
+ }
+ }
+
+ if ((ansi | nist | secp) == 0) {
+ nist = 1;
+ }
+ if ((usepkcs11 | usefreebl) == 0) {
+ usefreebl = 1;
+ }
+
+ rv = RNG_RNGInit();
+ if (rv != SECSuccess) {
+ SECU_PrintError("Error:", "RNG_RNGInit");
+ return -1;
+ }
+ RNG_SystemInfoForRNG();
+
+ rv = SECOID_Init();
+ if (rv != SECSuccess) {
+ SECU_PrintError("Error:", "SECOID_Init");
+ goto cleanup;
+ }
+
+ if (usepkcs11) {
+ CK_RV crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
+ return SECFailure;
+ }
+ }
+
+ /* specific arithmetic tests */
+ if (nist) {
+ ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256);
+ ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384);
+ ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521);
+ ECTEST_NAMED_CUSTOM("Curve25519", ECCurve25519);
+ }
+
+cleanup:
+ rv |= SECOID_Shutdown();
+ RNG_RNGShutdown();
+
+ if (rv != SECSuccess) {
+ printf("Error: exiting with error value\n");
+ }
+ return rv;
+}
diff --git a/security/nss/cmd/ecperf/ecperf.gyp b/security/nss/cmd/ecperf/ecperf.gyp
new file mode 100644
index 000000000..c6e99448d
--- /dev/null
+++ b/security/nss/cmd/ecperf/ecperf.gyp
@@ -0,0 +1,35 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'ecperf',
+ 'type': 'executable',
+ 'sources': [
+ 'ecperf.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports',
+ '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'include_dirs': [
+ '<(DEPTH)/lib/softoken',
+ ],
+ 'defines': [
+ 'NSS_USE_STATIC_LIBS'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss',
+ 'use_static_libs': 1
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/ecperf/manifest.mn b/security/nss/cmd/ecperf/manifest.mn
new file mode 100755
index 000000000..96cdc5ac8
--- /dev/null
+++ b/security/nss/cmd/ecperf/manifest.mn
@@ -0,0 +1,18 @@
+#
+# 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/.
+
+DEPTH = ../..
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken
+
+CSRCS = ecperf.c
+
+PROGRAM = ecperf
+
+USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/fbectest/Makefile b/security/nss/cmd/fbectest/Makefile
new file mode 100644
index 000000000..d20daa4b7
--- /dev/null
+++ b/security/nss/cmd/fbectest/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/fbectest/fbectest.c b/security/nss/cmd/fbectest/fbectest.c
new file mode 100644
index 000000000..2336d3fa8
--- /dev/null
+++ b/security/nss/cmd/fbectest/fbectest.c
@@ -0,0 +1,282 @@
+/* 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/. */
+
+#include "blapi.h"
+#include "ec.h"
+#include "ecl-curve.h"
+#include "prprf.h"
+#include "basicutil.h"
+#include "secder.h"
+#include "secitem.h"
+#include "secutil.h"
+#include "nspr.h"
+#include <stdio.h>
+
+typedef struct {
+ ECCurveName curve;
+ int iterations;
+ char *privhex;
+ char *our_pubhex;
+ char *their_pubhex;
+ char *common_key;
+ char *name;
+ ECFieldType fieldType;
+} ECDH_KAT;
+
+typedef struct {
+ ECCurveName curve;
+ char *point;
+ char *name;
+ ECFieldType fieldType;
+} ECDH_BAD;
+
+#include "testvecs.h"
+
+void
+printBuf(const SECItem *item)
+{
+ int i;
+ if (!item || !item->len) {
+ printf("(null)\n");
+ return;
+ }
+
+ for (i = 0; i < item->len; i++) {
+ printf("%02x", item->data[i]);
+ }
+ printf("\n");
+}
+
+/* Initialise test with basic curve populate with only the necessary things */
+SECStatus
+init_params(ECParams *ecParams, ECCurveName curve, PLArenaPool **arena,
+ ECFieldType type)
+{
+ if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) {
+ return SECFailure;
+ }
+ *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!*arena) {
+ return SECFailure;
+ }
+ ecParams->name = curve;
+ ecParams->type = ec_params_named;
+ ecParams->curveOID.data = NULL;
+ ecParams->curveOID.len = 0;
+ ecParams->curve.seed.data = NULL;
+ ecParams->curve.seed.len = 0;
+ ecParams->DEREncoding.data = NULL;
+ ecParams->DEREncoding.len = 0;
+ ecParams->arena = *arena;
+ ecParams->fieldID.size = ecCurve_map[curve]->size;
+ ecParams->fieldID.type = type;
+ ecParams->cofactor = ecCurve_map[curve]->cofactor;
+
+ return SECSuccess;
+}
+
+SECStatus
+ectest_ecdh_kat(ECDH_KAT *kat)
+{
+ ECCurveName curve = kat->curve;
+ ECParams ecParams = { 0 };
+ ECPrivateKey *ecPriv = NULL;
+ SECItem theirKey = { siBuffer, NULL, 0 };
+ SECStatus rv = SECFailure;
+ PLArenaPool *arena = NULL;
+ SECItem seed = { siBuffer, NULL, 0 };
+ SECItem answer = { siBuffer, NULL, 0 };
+ SECItem answer2 = { siBuffer, NULL, 0 };
+ SECItem derived = { siBuffer, NULL, 0 };
+ char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
+ int i;
+
+ rv = init_params(&ecParams, curve, &arena, kat->fieldType);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+
+ SECU_HexString2SECItem(arena, &ecParams.fieldID.u.prime, ecCurve_map[curve]->irr);
+ SECU_HexString2SECItem(arena, &ecParams.curve.a, ecCurve_map[curve]->curvea);
+ SECU_HexString2SECItem(arena, &ecParams.curve.b, ecCurve_map[curve]->curveb);
+ genenc[0] = '0';
+ genenc[1] = '4';
+ genenc[2] = '\0';
+ PORT_Assert(PR_ARRAY_SIZE(genenc) >= PORT_Strlen(ecCurve_map[curve]->genx));
+ PORT_Assert(PR_ARRAY_SIZE(genenc) >= PORT_Strlen(ecCurve_map[curve]->geny));
+ strcat(genenc, ecCurve_map[curve]->genx);
+ strcat(genenc, ecCurve_map[curve]->geny);
+ SECU_HexString2SECItem(arena, &ecParams.base, genenc);
+ SECU_HexString2SECItem(arena, &ecParams.order, ecCurve_map[curve]->order);
+
+ if (kat->our_pubhex) {
+ SECU_HexString2SECItem(arena, &answer, kat->our_pubhex);
+ }
+ SECU_HexString2SECItem(arena, &seed, kat->privhex);
+ rv = EC_NewKeyFromSeed(&ecParams, &ecPriv, seed.data, seed.len);
+ if (rv != SECSuccess) {
+ rv = SECFailure;
+ goto cleanup;
+ }
+ if (kat->our_pubhex) {
+ if (SECITEM_CompareItem(&answer, &ecPriv->publicValue) != SECEqual) {
+ rv = SECFailure;
+ goto cleanup;
+ }
+ }
+
+ SECU_HexString2SECItem(arena, &theirKey, kat->their_pubhex);
+ SECU_HexString2SECItem(arena, &answer2, kat->common_key);
+
+ rv = EC_ValidatePublicKey(&ecParams, &theirKey);
+ if (rv != SECSuccess) {
+ printf("EC_ValidatePublicKey failed\n");
+ goto cleanup;
+ }
+
+ for (i = 0; i < kat->iterations; ++i) {
+ rv = ECDH_Derive(&theirKey, &ecParams, &ecPriv->privateValue, PR_TRUE, &derived);
+ if (rv != SECSuccess) {
+ rv = SECFailure;
+ goto cleanup;
+ }
+ rv = SECITEM_CopyItem(ecParams.arena, &theirKey, &ecPriv->privateValue);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ rv = SECITEM_CopyItem(ecParams.arena, &ecPriv->privateValue, &derived);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ SECITEM_FreeItem(&derived, PR_FALSE);
+ }
+
+ if (SECITEM_CompareItem(&answer2, &ecPriv->privateValue) != SECEqual) {
+ printf("expected: ");
+ printBuf(&answer2);
+ printf("derived: ");
+ printBuf(&ecPriv->privateValue);
+ rv = SECFailure;
+ goto cleanup;
+ }
+
+cleanup:
+ PORT_FreeArena(arena, PR_FALSE);
+ if (ecPriv) {
+ PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE);
+ }
+ if (derived.data) {
+ SECITEM_FreeItem(&derived, PR_FALSE);
+ }
+ return rv;
+}
+
+SECStatus
+ectest_validate_point(ECDH_BAD *bad)
+{
+ ECParams ecParams = { 0 };
+ SECItem point = { siBuffer, NULL, 0 };
+ SECStatus rv = SECFailure;
+ PLArenaPool *arena = NULL;
+
+ rv = init_params(&ecParams, bad->curve, &arena, bad->fieldType);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+
+ SECU_HexString2SECItem(arena, &point, bad->point);
+ rv = EC_ValidatePublicKey(&ecParams, &point);
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+void
+printUsage(char *prog)
+{
+ printf("Usage: %s [-fp] [-nd]\n"
+ "\t-n: NIST curves\n"
+ "\t-d: non-NIST curves\n"
+ "You have to specify at at least one of n or d.\n"
+ "By default no tests are executed.\n",
+ prog);
+}
+
+/* Performs tests of elliptic curve cryptography over prime fields If
+ * tests fail, then it prints an error message, aborts, and returns an
+ * error code. Otherwise, returns 0. */
+int
+main(int argv, char **argc)
+{
+ SECStatus rv = SECSuccess;
+ int numkats = 0;
+ int i = 0;
+ int nist = 0;
+ int nonnist = 0;
+
+ for (i = 1; i < argv; i++) {
+ if (PL_strcasecmp(argc[i], "-n") == 0) {
+ nist = 1;
+ } else if (PL_strcasecmp(argc[i], "-d") == 0) {
+ nonnist = 1;
+ } else {
+ printUsage(argc[0]);
+ return 1;
+ }
+ }
+ if (!nist && !nonnist) {
+ printUsage(argc[0]);
+ return 1;
+ }
+
+ rv = SECOID_Init();
+ if (rv != SECSuccess) {
+ SECU_PrintError("Error:", "SECOID_Init");
+ goto cleanup;
+ }
+
+ /* Test P256, P384, P521 */
+ if (nist) {
+ while (ecdh_testvecs[numkats].curve != ECCurve_pastLastCurve) {
+ numkats++;
+ }
+ printf("1..%d\n", numkats);
+ for (i = 0; ecdh_testvecs[i].curve != ECCurve_pastLastCurve; i++) {
+ if (ectest_ecdh_kat(&ecdh_testvecs[i]) != SECSuccess) {
+ printf("not okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
+ rv = SECFailure;
+ } else {
+ printf("okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
+ }
+ }
+ }
+
+ /* Test KAT for non-NIST curves */
+ if (nonnist) {
+ for (i = 0; nonnist_testvecs[i].curve != ECCurve_pastLastCurve; i++) {
+ if (ectest_ecdh_kat(&nonnist_testvecs[i]) != SECSuccess) {
+ printf("not okay %d - %s\n", i + 1, nonnist_testvecs[i].name);
+ rv = SECFailure;
+ } else {
+ printf("okay %d - %s\n", i + 1, nonnist_testvecs[i].name);
+ }
+ }
+ for (i = 0; nonnist_testvecs_bad_values[i].curve != ECCurve_pastLastCurve; i++) {
+ if (ectest_validate_point(&nonnist_testvecs_bad_values[i]) == SECSuccess) {
+ printf("not okay %d - %s\n", i + 1, nonnist_testvecs_bad_values[i].name);
+ rv = SECFailure;
+ } else {
+ printf("okay %d - %s\n", i + 1, nonnist_testvecs_bad_values[i].name);
+ }
+ }
+ }
+
+cleanup:
+ rv |= SECOID_Shutdown();
+
+ if (rv != SECSuccess) {
+ printf("Error: exiting with error value\n");
+ }
+ return rv;
+}
diff --git a/security/nss/cmd/fbectest/fbectest.gyp b/security/nss/cmd/fbectest/fbectest.gyp
new file mode 100644
index 000000000..07357bc4f
--- /dev/null
+++ b/security/nss/cmd/fbectest/fbectest.gyp
@@ -0,0 +1,34 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'fbectest',
+ 'type': 'executable',
+ 'sources': [
+ 'fbectest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports',
+ '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'include_dirs': [
+ '<(DEPTH)/lib/softoken',
+ ],
+ 'defines': [
+ 'NSS_USE_STATIC_LIBS'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss',
+ 'use_static_libs': 1
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/fbectest/manifest.mn b/security/nss/cmd/fbectest/manifest.mn
new file mode 100644
index 000000000..85d6aa573
--- /dev/null
+++ b/security/nss/cmd/fbectest/manifest.mn
@@ -0,0 +1,18 @@
+#
+# 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/.
+
+DEPTH = ../..
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken
+
+CSRCS = fbectest.c
+
+PROGRAM = fbectest
+
+USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/fbectest/testvecs.h b/security/nss/cmd/fbectest/testvecs.h
new file mode 100644
index 000000000..e66a2bfb8
--- /dev/null
+++ b/security/nss/cmd/fbectest/testvecs.h
@@ -0,0 +1,818 @@
+static ECDH_KAT ecdh_testvecs[] = {
+ { ECCurve_NIST_P256, 1,
+ "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534",
+ "04ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b23028af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141",
+ "04700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac",
+ "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b",
+ "curve: P256 vector: 0", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5",
+ "04119f2f047902782ab0c9e27a54aff5eb9b964829ca99c06b02ddba95b0a3f6d08f52b726664cac366fc98ac7a012b2682cbd962e5acb544671d41b9445704d1d",
+ "04809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7aeb29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3",
+ "057d636096cb80b67a8c038c890e887d1adfa4195e9b3ce241c8a778c59cda67",
+ "curve: P256 vector: 1", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "1accfaf1b97712b85a6f54b148985a1bdc4c9bec0bd258cad4b3d603f49f32c8",
+ "04d9f2b79c172845bfdb560bbb01447ca5ecc0470a09513b6126902c6b4f8d1051f815ef5ec32128d3487834764678702e64e164ff7315185e23aff5facd96d7bc",
+ "04a2339c12d4a03c33546de533268b4ad667debf458b464d77443636440ee7fec3ef48a3ab26e20220bcda2c1851076839dae88eae962869a497bf73cb66faf536",
+ "2d457b78b4614132477618a5b077965ec90730a8c81a1c75d6d4ec68005d67ec",
+ "curve: P256 vector: 2", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "207c43a79bfee03db6f4b944f53d2fb76cc49ef1c9c4d34d51b6c65c4db6932d",
+ "0424277c33f450462dcb3d4801d57b9ced05188f16c28eda873258048cd1607e0dc4789753e2b1f63b32ff014ec42cd6a69fac81dfe6d0d6fd4af372ae27c46f88",
+ "04df3989b9fa55495719b3cf46dccd28b5153f7808191dd518eff0c3cff2b705ed422294ff46003429d739a33206c8752552c8ba54a270defc06e221e0feaf6ac4",
+ "96441259534b80f6aee3d287a6bb17b5094dd4277d9e294f8fe73e48bf2a0024",
+ "curve: P256 vector: 3", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "59137e38152350b195c9718d39673d519838055ad908dd4757152fd8255c09bf",
+ "04a8c5fdce8b62c5ada598f141adb3b26cf254c280b2857a63d2ad783a73115f6b806e1aafec4af80a0d786b3de45375b517a7e5b51ffb2c356537c9e6ef227d4a",
+ "0441192d2813e79561e6a1d6f53c8bc1a433a199c835e141b05a74a97b0faeb9221af98cc45e98a7e041b01cf35f462b7562281351c8ebf3ffa02e33a0722a1328",
+ "19d44c8d63e8e8dd12c22a87b8cd4ece27acdde04dbf47f7f27537a6999a8e62",
+ "curve: P256 vector: 4", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "f5f8e0174610a661277979b58ce5c90fee6c9b3bb346a90a7196255e40b132ef",
+ "047b861dcd2844a5a8363f6b8ef8d493640f55879217189d80326aad9480dfc149c4675b45eeb306405f6c33c38bc69eb2bdec9b75ad5af4706aab84543b9cc63a",
+ "0433e82092a0f1fb38f5649d5867fba28b503172b7035574bf8e5b7100a3052792f2cf6b601e0a05945e335550bf648d782f46186c772c0f20d3cd0d6b8ca14b2f",
+ "664e45d5bba4ac931cd65d52017e4be9b19a515f669bea4703542a2c525cd3d3",
+ "curve: P256 vector: 5", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "3b589af7db03459c23068b64f63f28d3c3c6bc25b5bf76ac05f35482888b5190",
+ "049fb38e2d58ea1baf7622e96720101cae3cde4ba6c1e9fa26d9b1de0899102863d5561b900406edf50802dd7d73e89395f8aed72fba0e1d1b61fe1d22302260f0",
+ "046a9e0c3f916e4e315c91147be571686d90464e8bf981d34a90b6353bca6eeba740f9bead39c2f2bcc2602f75b8a73ec7bdffcbcead159d0174c6c4d3c5357f05",
+ "ca342daa50dc09d61be7c196c85e60a80c5cb04931746820be548cdde055679d",
+ "curve: P256 vector: 6", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "d8bf929a20ea7436b2461b541a11c80e61d826c0a4c9d322b31dd54e7f58b9c8",
+ "0420f07631e4a6512a89ad487c4e9d63039e579cb0d7a556cb9e661cd59c1e7fa46de91846b3eee8a5ec09c2ab1f41e21bd83620ccdd1bdce3ab7ea6e02dd274f5",
+ "04a9c0acade55c2a73ead1a86fb0a9713223c82475791cd0e210b046412ce224bbf6de0afa20e93e078467c053d241903edad734c6b403ba758c2b5ff04c9d4229",
+ "35aa9b52536a461bfde4e85fc756be928c7de97923f0416c7a3ac8f88b3d4489",
+ "curve: P256 vector: 7", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "0f9883ba0ef32ee75ded0d8bda39a5146a29f1f2507b3bd458dbea0b2bb05b4d",
+ "04abb61b423be5d6c26e21c605832c9142dc1dfe5a5fff28726737936e6fbf516d733d2513ef58beab202090586fac91bf0fee31e80ab33473ab23a2d89e58fad6",
+ "0494e94f16a98255fff2b9ac0c9598aac35487b3232d3231bd93b7db7df36f9eb9d8049a43579cfa90b8093a94416cbefbf93386f15b3f6e190b6e3455fedfe69a",
+ "605c16178a9bc875dcbff54d63fe00df699c03e8a888e9e94dfbab90b25f39b4",
+ "curve: P256 vector: 8", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "2beedb04b05c6988f6a67500bb813faf2cae0d580c9253b6339e4a3337bb6c08",
+ "043d63e429cb5fa895a9247129bf4e48e89f35d7b11de8158efeb3e106a2a873950cae9e477ef41e7c8c1064379bb7b554ddcbcae79f9814281f1e50f0403c61f3",
+ "04e099bf2a4d557460b5544430bbf6da11004d127cb5d67f64ab07c94fcdf5274fd9c50dbe70d714edb5e221f4e020610eeb6270517e688ca64fb0e98c7ef8c1c5",
+ "f96e40a1b72840854bb62bc13c40cc2795e373d4e715980b261476835a092e0b",
+ "curve: P256 vector: 9", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "77c15dcf44610e41696bab758943eff1409333e4d5a11bbe72c8f6c395e9f848",
+ "04ad5d13c3db508ddcd38457e5991434a251bed49cf5ddcb59cdee73865f138c9f62cec1e70588aa4fdfc7b9a09daa678081c04e1208b9d662b8a2214bf8e81a21",
+ "04f75a5fe56bda34f3c1396296626ef012dc07e4825838778a645c8248cff0165833bbdf1b1772d8059df568b061f3f1122f28a8d819167c97be448e3dc3fb0c3c",
+ "8388fa79c4babdca02a8e8a34f9e43554976e420a4ad273c81b26e4228e9d3a3",
+ "curve: P256 vector: 10", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "42a83b985011d12303db1a800f2610f74aa71cdf19c67d54ce6c9ed951e9093e",
+ "04ab48caa61ea35f13f8ed07ffa6a13e8db224dfecfae1a7df8b1bb6ebaf0cb97d1274530ca2c385a3218bddfbcbf0b4024c9badd5243bff834ebff24a8618dccb",
+ "042db4540d50230756158abf61d9835712b6486c74312183ccefcaef2797b7674d62f57f314e3f3495dc4e099012f5e0ba71770f9660a1eada54104cdfde77243e",
+ "72877cea33ccc4715038d4bcbdfe0e43f42a9e2c0c3b017fc2370f4b9acbda4a",
+ "curve: P256 vector: 11", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "ceed35507b5c93ead5989119b9ba342cfe38e6e638ba6eea343a55475de2800b",
+ "049a8cd9bd72e71752df91440f77c547509a84df98114e7de4f26cdb39234a625dd07cfc84c8e144fab2839f5189bb1d7c88631d579bbc58012ed9a2327da52f62",
+ "04cd94fc9497e8990750309e9a8534fd114b0a6e54da89c4796101897041d14ecbc3def4b5fe04faee0a11932229fff563637bfdee0e79c6deeaf449f85401c5c4",
+ "e4e7408d85ff0e0e9c838003f28cdbd5247cdce31f32f62494b70e5f1bc36307",
+ "curve: P256 vector: 12", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "43e0e9d95af4dc36483cdd1968d2b7eeb8611fcce77f3a4e7d059ae43e509604",
+ "04f989cf8ee956a82e7ebd9881cdbfb2fd946189b08db53559bc8cfdd48071eb145eff28f1a18a616b04b7d337868679f6dd84f9a7b3d7b6f8af276c19611a541d",
+ "0415b9e467af4d290c417402e040426fe4cf236bae72baa392ed89780dfccdb471cdf4e9170fb904302b8fd93a820ba8cc7ed4efd3a6f2d6b05b80b2ff2aee4e77",
+ "ed56bcf695b734142c24ecb1fc1bb64d08f175eb243a31f37b3d9bb4407f3b96",
+ "curve: P256 vector: 13", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "b2f3600df3368ef8a0bb85ab22f41fc0e5f4fdd54be8167a5c3cd4b08db04903",
+ "0469c627625b36a429c398b45c38677cb35d8beb1cf78a571e40e99fe4eac1cd4e81690112b0a88f20f7136b28d7d47e5fbc2ada3c8edd87589bc19ec9590637bd",
+ "0449c503ba6c4fa605182e186b5e81113f075bc11dcfd51c932fb21e951eee2fa18af706ff0922d87b3f0c5e4e31d8b259aeb260a9269643ed520a13bb25da5924",
+ "bc5c7055089fc9d6c89f83c1ea1ada879d9934b2ea28fcf4e4a7e984b28ad2cf",
+ "curve: P256 vector: 14", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "4002534307f8b62a9bf67ff641ddc60fef593b17c3341239e95bdb3e579bfdc8",
+ "045fe964671315a18aa68a2a6e3dd1fde7e23b8ce7181471cfac43c99e1ae80262d5827be282e62c84de531b963884ba832db5d6b2c3a256f0e604fe7e6b8a7f72",
+ "0419b38de39fdd2f70f7091631a4f75d1993740ba9429162c2a45312401636b29c09aed7232b28e060941741b6828bcdfa2bc49cc844f3773611504f82a390a5ae",
+ "9a4e8e657f6b0e097f47954a63c75d74fcba71a30d83651e3e5a91aa7ccd8343",
+ "curve: P256 vector: 15", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "4dfa12defc60319021b681b3ff84a10a511958c850939ed45635934ba4979147",
+ "04c9b2b8496f1440bd4a2d1e52752fd372835b364885e154a7dac49295f281ec7cfbe6b926a8a4de26ccc83b802b1212400754be25d9f3eeaf008b09870ae76321",
+ "042c91c61f33adfe9311c942fdbff6ba47020feff416b7bb63cec13faf9b0999546cab31b06419e5221fca014fb84ec870622a1b12bab5ae43682aa7ea73ea08d0",
+ "3ca1fc7ad858fb1a6aba232542f3e2a749ffc7203a2374a3f3d3267f1fc97b78",
+ "curve: P256 vector: 16", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "1331f6d874a4ed3bc4a2c6e9c74331d3039796314beee3b7152fcdba5556304e",
+ "0459e1e101521046ad9cf1d082e9d2ec7dd22530cce064991f1e55c5bcf5fcb591482f4f673176c8fdaa0bb6e59b15a3e47454e3a04297d3863c9338d98add1f37",
+ "04a28a2edf58025668f724aaf83a50956b7ac1cfbbff79b08c3bf87dfd2828d767dfa7bfffd4c766b86abeaf5c99b6e50cb9ccc9d9d00b7ffc7804b0491b67bc03",
+ "1aaabe7ee6e4a6fa732291202433a237df1b49bc53866bfbe00db96a0f58224f",
+ "curve: P256 vector: 17", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "dd5e9f70ae740073ca0204df60763fb6036c45709bf4a7bb4e671412fad65da3",
+ "0430b9db2e2e977bcdc98cb87dd736cbd8e78552121925cf16e1933657c2fb23146a45028800b81291bce5c2e1fed7ded650620ebbe6050c6f3a7f0dfb4673ab5c",
+ "04a2ef857a081f9d6eb206a81c4cf78a802bdf598ae380c8886ecd85fdc1ed7644563c4c20419f07bc17d0539fade1855e34839515b892c0f5d26561f97fa04d1a",
+ "430e6a4fba4449d700d2733e557f66a3bf3d50517c1271b1ddae1161b7ac798c",
+ "curve: P256 vector: 18", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "5ae026cfc060d55600717e55b8a12e116d1d0df34af831979057607c2d9c2f76",
+ "0446c9ebd1a4a3c8c0b6d572b5dcfba12467603208a9cb5d2acfbb733c40cf639146c913a27d044185d38b467ace011e04d4d9bbbb8cb9ae25fa92aaf15a595e86",
+ "04ccd8a2d86bc92f2e01bce4d6922cf7fe1626aed044685e95e2eebd464505f01fe9ddd583a9635a667777d5b8a8f31b0f79eba12c75023410b54b8567dddc0f38",
+ "1ce9e6740529499f98d1f1d71329147a33df1d05e4765b539b11cf615d6974d3",
+ "curve: P256 vector: 19", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "b601ac425d5dbf9e1735c5e2d5bdb79ca98b3d5be4a2cfd6f2273f150e064d9d",
+ "047c9e950841d26c8dde8994398b8f5d475a022bc63de7773fcf8d552e01f1ba0acc42b9885c9b3bee0f8d8c57d3a8f6355016c019c4062fa22cff2f209b5cc2e1",
+ "04c188ffc8947f7301fb7b53e36746097c2134bf9cc981ba74b4e9c4361f595e4ebf7d2f2056e72421ef393f0c0f2b0e00130e3cac4abbcc00286168e85ec55051",
+ "4690e3743c07d643f1bc183636ab2a9cb936a60a802113c49bb1b3f2d0661660",
+ "curve: P256 vector: 20", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "fefb1dda1845312b5fce6b81b2be205af2f3a274f5a212f66c0d9fc33d7ae535",
+ "0438b54db85500cb20c61056edd3d88b6a9dc26780a047f213a6e1b900f76596eb6387e4e5781571e4eb8ae62991a33b5dc33301c5bc7e125d53794a39160d8fd0",
+ "04317e1020ff53fccef18bf47bb7f2dd7707fb7b7a7578e04f35b3beed222a0eb609420ce5a19d77c6fe1ee587e6a49fbaf8f280e8df033d75403302e5a27db2ae",
+ "30c2261bd0004e61feda2c16aa5e21ffa8d7e7f7dbf6ec379a43b48e4b36aeb0",
+ "curve: P256 vector: 21", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "334ae0c4693d23935a7e8e043ebbde21e168a7cba3fa507c9be41d7681e049ce",
+ "043f2bf1589abf3047bf3e54ac9a95379bff95f8f55405f64eca36a7eebe8ffca75212a94e66c5ae9a8991872f66a72723d80ec5b2e925745c456f5371943b3a06",
+ "0445fb02b2ceb9d7c79d9c2fa93e9c7967c2fa4df5789f9640b24264b1e524fcb15c6e8ecf1f7d3023893b7b1ca1e4d178972ee2a230757ddc564ffe37f5c5a321",
+ "2adae4a138a239dcd93c243a3803c3e4cf96e37fe14e6a9b717be9599959b11c",
+ "curve: P256 vector: 22", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "2c4bde40214fcc3bfc47d4cf434b629acbe9157f8fd0282540331de7942cf09d",
+ "0429c0807f10cbc42fb45c9989da50681eead716daa7b9e91fd32e062f5eb92ca0ff1d6d1955d7376b2da24fe1163a271659136341bc2eb1195fc706dc62e7f34d",
+ "04a19ef7bff98ada781842fbfc51a47aff39b5935a1c7d9625c8d323d511c92de6e9c184df75c955e02e02e400ffe45f78f339e1afe6d056fb3245f4700ce606ef",
+ "2e277ec30f5ea07d6ce513149b9479b96e07f4b6913b1b5c11305c1444a1bc0b",
+ "curve: P256 vector: 23", ec_field_GFp },
+
+ { ECCurve_NIST_P256, 1,
+ "85a268f9d7772f990c36b42b0a331adc92b5941de0b862d5d89a347cbf8faab0",
+ "049cf4b98581ca1779453cc816ff28b4100af56cf1bf2e5bc312d83b6b1b21d3337a5504fcac5231a0d12d658218284868229c844a04a3450d6c7381abe080bf3b",
+ "04356c5a444c049a52fee0adeb7e5d82ae5aa83030bfff31bbf8ce2096cf161c4b57d128de8b2a57a094d1a001e572173f96e8866ae352bf29cddaf92fc85b2f92",
+ "1e51373bd2c6044c129c436e742a55be2a668a85ae08441b6756445df5493857",
+ "curve: P256 vector: 24", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "3cc3122a68f0d95027ad38c067916ba0eb8c38894d22e1b15618b6818a661774ad463b205da88cf699ab4d43c9cf98a1",
+ "049803807f2f6d2fd966cdd0290bd410c0190352fbec7ff6247de1302df86f25d34fe4a97bef60cff548355c015dbb3e5"
+ "fba26ca69ec2f5b5d9dad20cc9da711383a9dbe34ea3fa5a2af75b46502629ad54dd8b7d73a8abb06a3a3be47d650cc99",
+ "04a7c76b970c3b5fe8b05d2838ae04ab47697b9eaf52e764592efda27fe7513272734466b400091adbf2d68c58e0c5006"
+ "6ac68f19f2e1cb879aed43a9969b91a0839c4c38a49749b661efedf243451915ed0905a32b060992b468c64766fc8437a",
+ "5f9d29dc5e31a163060356213669c8ce132e22f57c9a04f40ba7fcead493b457e5621e766c40a2e3d4d6a04b25e533f1",
+ "curve: P384 vector: 0", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "92860c21bde06165f8e900c687f8ef0a05d14f290b3f07d8b3a8cc6404366e5d5119cd6d03fb12dc58e89f13df9cd783",
+ "04ea4018f5a307c379180bf6a62fd2ceceebeeb7d4df063a66fb838aa35243419791f7e2c9d4803c9319aa0eb03c416b"
+ "6668835a91484f05ef028284df6436fb88ffebabcdd69ab0133e6735a1bcfb37203d10d340a8328a7b68770ca75878a1a6",
+ "0430f43fcf2b6b00de53f624f1543090681839717d53c7c955d1d69efaf0349b7363acb447240101cbb3af6641ce4b88e0"
+ "25e46c0c54f0162a77efcc27b6ea792002ae2ba82714299c860857a68153ab62e525ec0530d81b5aa15897981e858757",
+ "a23742a2c267d7425fda94b93f93bbcc24791ac51cd8fd501a238d40812f4cbfc59aac9520d758cf789c76300c69d2ff",
+ "curve: P384 vector: 1", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "12cf6a223a72352543830f3f18530d5cb37f26880a0b294482c8a8ef8afad09aa78b7dc2f2789a78c66af5d1cc553853",
+ "04fcfcea085e8cf74d0dced1620ba8423694f903a219bbf901b0b59d6ac81baad316a242ba32bde85cb248119b852fab6"
+ "6972e3c68c7ab402c5836f2a16ed451a33120a7750a6039f3ff15388ee622b7065f7122bf6d51aefbc29b37b03404581b",
+ "041aefbfa2c6c8c855a1a216774550b79a24cda37607bb1f7cc906650ee4b3816d68f6a9c75da6e4242cebfb6652f65180"
+ "419d28b723ebadb7658fcebb9ad9b7adea674f1da3dc6b6397b55da0f61a3eddacb4acdb14441cb214b04a0844c02fa3",
+ "3d2e640f350805eed1ff43b40a72b2abed0a518bcebe8f2d15b111b6773223da3c3489121db173d414b5bd5ad7153435",
+ "curve: P384 vector: 2", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "8dd48063a3a058c334b5cc7a4ce07d02e5ee6d8f1f3c51a1600962cbab462690ae3cd974fb39e40b0e843daa0fd32de1",
+ "04e38c9846248123c3421861ea4d32669a7b5c3c08376ad28104399494c84ff5efa3894adb2c6cbe8c3c913ef2eec5bd3"
+ "c9fa84024a1028796df84021f7b6c9d02f0f4bd1a612a03cbf75a0beea43fef8ae84b48c60172aadf09c1ad016d0bf3ce",
+ "048bc089326ec55b9cf59b34f0eb754d93596ca290fcb3444c83d4de3a5607037ec397683f8cef07eab2fe357eae36c44"
+ "9d9d16ce8ac85b3f1e94568521aae534e67139e310ec72693526aa2e927b5b322c95a1a033c229cb6770c957cd3148dd7",
+ "6a42cfc392aba0bfd3d17b7ccf062b91fc09bbf3417612d02a90bdde62ae40c54bb2e56e167d6b70db670097eb8db854",
+ "curve: P384 vector: 3", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "84ece6cc3429309bd5b23e959793ed2b111ec5cb43b6c18085fcaea9efa0685d98a6262ee0d330ee250bc8a67d0e733f",
+ "043222063a2997b302ee60ee1961108ff4c7acf1c0ef1d5fb0d164b84bce71c431705cb9aea9a45f5d73806655a058bee"
+ "3e61fa9e7fbe7cd43abf99596a3d3a039e99fa9dc93b0bdd9cad81966d17eeaf557068afa7c78466bb5b22032d1100fa6",
+ "04eb952e2d9ac0c20c6cc48fb225c2ad154f53c8750b003fd3b4ed8ed1dc0defac61bcdde02a2bcfee7067d75d342ed2b"
+ "0f1828205baece82d1b267d0d7ff2f9c9e15b69a72df47058a97f3891005d1fb38858f5603de840e591dfa4f6e7d489e1",
+ "ce7ba454d4412729a32bb833a2d1fd2ae612d4667c3a900e069214818613447df8c611de66da200db7c375cf913e4405",
+ "curve: P384 vector: 4", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "68fce2121dc3a1e37b10f1dde309f9e2e18fac47cd1770951451c3484cdb77cb136d00e731260597cc2859601c01a25b",
+ "04868be0e694841830e424d913d8e7d86b84ee1021d82b0ecf523f09fe89a76c0c95c49f2dfbcf829c1e39709d55efbb"
+ "3b9195eb183675b40fd92f51f37713317e4a9b4f715c8ab22e0773b1bc71d3a219f05b8116074658ee86b52e36f3897116",
+ "04441d029e244eb7168d647d4df50db5f4e4974ab3fdaf022aff058b3695d0b8c814cc88da6285dc6df1ac55c55388500"
+ "3e8025ac23a41d4b1ea2aa46c50c6e479946b59b6d76497cd9249977e0bfe4a6262622f13d42a3c43d66bdbb30403c345",
+ "ba69f0acdf3e1ca95caaac4ecaf475bbe51b54777efce01ca381f45370e486fe87f9f419b150c61e329a286d1aa265ec",
+ "curve: P384 vector: 5", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "b1764c54897e7aae6de9e7751f2f37de849291f88f0f91093155b858d1cc32a3a87980f706b86cc83f927bdfdbeae0bd",
+ "04c371222feaa6770c6f3ea3e0dac9740def4fcf821378b7f91ff937c21e0470f70f3a31d5c6b2912195f10926942b48ae"
+ "047d6b4d765123563f81116bc665b7b8cc6207830d805fd84da7cb805a65baa7c12fd592d1b5b5e3e65d9672a9ef7662",
+ "043d4e6bf08a73404accc1629873468e4269e82d90d832e58ad72142639b5a056ad8d35c66c60e8149fac0c797bceb7c2"
+ "f9b0308dc7f0e6d29f8c277acbc65a21e5adb83d11e6873bc0a07fda0997f482504602f59e10bc5cb476b83d0a4f75e71",
+ "1a6688ee1d6e59865d8e3ada37781d36bb0c2717eef92e61964d3927cb765c2965ea80f7f63e58c322ba0397faeaf62b",
+ "curve: P384 vector: 6", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "f0f7a96e70d98fd5a30ad6406cf56eb5b72a510e9f192f50e1f84524dbf3d2439f7287bb36f5aa912a79deaab4adea82",
+ "0499c8c41cb1ab5e0854a346e4b08a537c1706a61553387c8d94943ab15196d40dbaa55b8210a77a5d00915f2c4ea69e"
+ "ab5531065bdcf17bfb3cb55a02e41a57c7f694c383ad289f900fbd656c2233a93c92e933e7a26f54cbb56f0ad875c51bb0",
+ "04f5f6bef1d110da03be0017eac760cc34b24d092f736f237bc7054b3865312a813bcb62d297fb10a4f7abf54708fe2d3d"
+ "06fdf8d7dc032f4e10010bf19cbf6159321252ff415fb91920d438f24e67e60c2eb0463204679fa356af44cea9c9ebf5",
+ "d06a568bf2336b90cbac325161be7695eacb2295f599500d787f072612aca313ee5d874f807ddef6c1f023fe2b6e7cd0",
+ "curve: P384 vector: 7", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "9efb87ddc61d43c482ba66e1b143aef678fbd0d1bebc2000941fabe677fe5b706bf78fce36d100b17cc787ead74bbca2",
+ "044c34efee8f0c95565d2065d1bbac2a2dd25ae964320eb6bccedc5f3a9b42a881a1afca1bb6b880584fa27b01c193cd9"
+ "2d8fb01dbf7cd0a3868c26b951f393c3c56c2858cee901f7793ff5d271925d13a41f8e52409f4eba1990f33acb0bac669",
+ "047cdec77e0737ea37c67b89b7137fe38818010f4464438ee4d1d35a0c488cad3fde2f37d00885d36d3b795b9f93d23a6"
+ "728c42ee8d6027c56cf979ba4c229fdb01d234944f8ac433650112c3cf0f02844e888a3569dfef7828a8a884589aa055e",
+ "bb3b1eda9c6560d82ff5bee403339f1e80342338a991344853b56b24f109a4d94b92f654f0425edd4c205903d7586104",
+ "curve: P384 vector: 8", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "d787a57fde22ec656a0a525cf3c738b30d73af61e743ea90893ecb2d7b622add2f94ee25c2171467afb093f3f84d0018",
+ "04171546923b87b2cbbad664f01ce932bf09d6a6118168678446bfa9f0938608cb4667a98f4ec8ac1462285c2508f7486"
+ "2fa41cb4db68ae71f1f8a3e8939dc52c2dec61a83c983beb2a02baf29ec49278088882ed0cf56c74b5c173b552ccf63cf",
+ "048eeea3a319c8df99fbc29cb55f243a720d95509515ee5cc587a5c5ae22fbbd009e626db3e911def0b99a4f7ae304b1b"
+ "a73877dc94db9adddc0d9a4b24e8976c22d73c844370e1ee857f8d1b129a3bd5f63f40caf3bd0533e38a5f5777074ff9e",
+ "1e97b60add7cb35c7403dd884c0a75795b7683fff8b49f9d8672a8206bfdcf0a106b8768f983258c74167422e44e4d14",
+ "curve: P384 vector: 9", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "83d70f7b164d9f4c227c767046b20eb34dfc778f5387e32e834b1e6daec20edb8ca5bb4192093f543b68e6aeb7ce788b",
+ "0457cd770f3bbcbe0c78c770eab0b169bc45e139f86378ffae1c2b16966727c2f2eb724572b8f3eb228d130db4ff862c"
+ "637ec5c8813b685558d83e924f14bc719f6eb7ae0cbb2c474227c5bda88637a4f26c64817929af999592da6f787490332f",
+ "04a721f6a2d4527411834b13d4d3a33c29beb83ab7682465c6cbaf6624aca6ea58c30eb0f29dd842886695400d7254f20f"
+ "14ba6e26355109ad35129366d5e3a640ae798505a7fa55a96a36b5dad33de00474f6670f522214dd7952140ab0a7eb68",
+ "1023478840e54775bfc69293a3cf97f5bc914726455c66538eb5623e218feef7df4befa23e09d77145ad577db32b41f9",
+ "curve: P384 vector: 10", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "8f558e05818b88ed383d5fca962e53413db1a0e4637eda194f761944cbea114ab9d5da175a7d57882550b0e432f395a9",
+ "049a2f57f4867ce753d72b0d95195df6f96c1fae934f602efd7b6a54582f556cfa539d89005ca2edac08ad9b72dd1f60b"
+ "ad9b94ee82da9cc601f346044998ba387aee56404dc6ecc8ab2b590443319d0b2b6176f9d0eac2d44678ed561607d09a9",
+ "04d882a8505c2d5cb9b8851fc676677bb0087681ad53faceba1738286b45827561e7da37b880276c656cfc38b32ade847"
+ "e34b314bdc134575654573cffaf40445da2e6aaf987f7e913cd4c3091523058984a25d8f21da8326192456c6a0fa5f60c",
+ "6ad6b9dc8a6cf0d3691c501cbb967867f6e4bbb764b60dbff8fcff3ed42dbba39d63cf325b4b4078858495ddee75f954",
+ "curve: P384 vector: 11", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "0f5dee0affa7bbf239d5dff32987ebb7cf84fcceed643e1d3c62d0b3352aec23b6e5ac7fa4105c8cb26126ad2d1892cb",
+ "0423346bdfbc9d7c7c736e02bdf607671ff6082fdd27334a8bc75f3b23681ebe614d0597dd614fae58677c835a9f0b273"
+ "b82ba36290d2f94db41479eb45ab4eaf67928a2315138d59eecc9b5285dfddd6714f77557216ea44cc6fc119d8243efaf",
+ "04815c9d773dbf5fb6a1b86799966247f4006a23c92e68c55e9eaa998b17d8832dd4d84d927d831d4f68dac67c6488219f"
+ "e79269948b2611484560fd490feec887cb55ef99a4b524880fa7499d6a07283aae2afa33feab97deca40bc606c4d8764",
+ "cc9e063566d46b357b3fcae21827377331e5e290a36e60cd7c39102b828ae0b918dc5a02216b07fe6f1958d834e42437",
+ "curve: P384 vector: 12", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "037b633b5b8ba857c0fc85656868232e2febf59578718391b81da8541a00bfe53c30ae04151847f27499f8d7abad8cf4",
+ "048878ac8a947f7d5cb2b47aad24fbb8210d86126585399a2871f84aa9c5fde3074ae540c6bf82275ca822d0feb862bc7"
+ "4632f5cd2f900c2711c32f8930728eb647d31edd8d650f9654e7d33e5ed1b475489d08daa30d8cbcba6bfc3b60d9b5a37",
+ "041c0eeda7a2be000c5bdcda0478aed4db733d2a9e341224379123ad847030f29e3b168fa18e89a3c0fba2a6ce1c28fc3"
+ "bec8c1c83c118c4dbea94271869f2d868eb65e8b44e21e6f14b0f4d9b38c068daefa27114255b9a41d084cc4a1ad85456",
+ "deff7f03bd09865baf945e73edff6d5122c03fb561db87dec8662e09bed4340b28a9efe118337bb7d3d4f7f568635ff9",
+ "curve: P384 vector: 13", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "e3d07106bedcc096e7d91630ffd3094df2c7859db8d7edbb2e37b4ac47f429a637d06a67d2fba33838764ef203464991",
+ "04e74a1a2b85f1cbf8dbbdf050cf1aff8acb02fda2fb6591f9d3cfe4e79d0ae938a9c1483e7b75f8db24505d65065cdb1"
+ "81773ee591822f7abaa856a1a60bc0a5203548dbd1cb5025466eff8481bd07614eaa04a16c3db76905913e972a5b6b59d",
+ "04c95c185e256bf997f30b311548ae7f768a38dee43eeeef43083f3077be70e2bf39ac1d4daf360c514c8c6be623443d1"
+ "a3e63a663eaf75d8a765ab2b9a35513d7933fa5e26420a5244550ec6c3b6f033b96db2aca3d6ac6aab052ce929595aea5",
+ "c8b1038f735ad3bb3e4637c3e47eab487637911a6b7950a4e461948329d3923b969e5db663675623611a457fcda35a71",
+ "curve: P384 vector: 14", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "f3f9b0c65a49a506632c8a45b10f66b5316f9eeb06fae218f2da62333f99905117b141c760e8974efc4af10570635791",
+ "04a4ad77aa7d86e5361118a6b921710c820721210712f4c347985fdee58aa4effa1e28be80a17b120b139f96300f89b4"
+ "9b1ddf22e07e03f1560d8f45a480094560dba9fae7f9531130c1b57ebb95982496524f31d3797793396fa823f22bdb4328",
+ "043497238a7e6ad166df2dac039aa4dac8d17aa925e7c7631eb3b56e3aaa1c545fcd54d2e5985807910fb202b1fc191d2a"
+ "a49e5c487dcc7aa40a8f234c979446040d9174e3ad357d404d7765183195aed3f913641b90c81a306ebf0d8913861316",
+ "d337eaa32b9f716b8747b005b97a553c59dab0c51df41a2d49039cdae705aa75c7b9e7bc0b6a0e8c578c902bc4fff23e",
+ "curve: P384 vector: 15", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "59fce7fad7de28bac0230690c95710c720e528f9a4e54d3a6a8cd5fc5c5f21637031ce1c5b4e3d39647d8dcb9b794664",
+ "049c43bf971edf09402876ee742095381f78b1bd3aa39b5132af75dbfe7e98bd78bde10fe2e903c2b6379e1deee175a1b"
+ "0a6c58ecea5a477bb01bd543b339f1cc49f1371a2cda4d46eb4e53e250597942351a99665a122ffea9bde0636c375daf2",
+ "0490a34737d45b1aa65f74e0bd0659bc118f8e4b774b761944ffa6573c6df4f41dec0d11b697abd934d390871d4b453240"
+ "9b590719bb3307c149a7817be355d684893a307764b512eeffe07cb699edb5a6ffbf8d6032e6c79d5e93e94212c2aa4e",
+ "32d292b695a4488e42a7b7922e1ae537d76a3d21a0b2e36875f60e9f6d3e8779c2afb3a413b9dd79ae18e70b47d337c1",
+ "curve: P384 vector: 16", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "3e49fbf950a424c5d80228dc4bc35e9f6c6c0c1d04440998da0a609a877575dbe437d6a5cedaa2ddd2a1a17fd112aded",
+ "045a949594228b1a3d6f599eb3db0d06070fbc551c657b58234ba164ce3fe415fa5f3eb823c08dc29b8c341219c77b6b3"
+ "d2baad447c8c290cfed25edd9031c41d0b76921457327f42db31122b81f337bbf0b1039ec830ce9061a3761953c75e4a8",
+ "04dda546acfc8f903d11e2e3920669636d44b2068aeb66ff07aa266f0030e1535b0ed0203cb8a460ac990f1394faf22f1"
+ "d15bbb2597913035faadf413476f4c70f7279769a40c986f470c427b4ee4962abdf8173bbad81874772925fd32f0b159f",
+ "1220e7e6cad7b25df98e5bbdcc6c0b65ca6c2a50c5ff6c41dca71e475646fd489615979ca92fb4389aeadefde79a24f1",
+ "curve: P384 vector: 17", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "50ccc1f7076e92f4638e85f2db98e0b483e6e2204c92bdd440a6deea04e37a07c6e72791c190ad4e4e86e01efba84269",
+ "04756c07df0ce32c839dac9fb4733c9c28b70113a676a7057c38d223f22a3a9095a8d564653af528e04c7e1824be4a651"
+ "217c2ce6962cbd2a2e066297b39d57dd9bb4680f0191d390f70b4e461419b2972ce68ad46127fdda6c39195774ea86df3",
+ "04788be2336c52f4454d63ee944b1e49bfb619a08371048e6da92e584eae70bde1f171c4df378bd1f3c0ab03048a237802"
+ "4673ebd8db604eaf41711748bab2968a23ca4476ce144e728247f08af752929157b5830f1e26067466bdfa8b65145a33",
+ "793bb9cd22a93cf468faf804a38d12b78cb12189ec679ddd2e9aa21fa9a5a0b049ab16a23574fe04c1c3c02343b91beb",
+ "curve: P384 vector: 18", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "06f132b71f74d87bf99857e1e4350a594e5fe35533b888552ceccbc0d8923c902e36141d7691e28631b8bc9bafe5e064",
+ "042a3cc6b8ff5cde926e7e3a189a1bd029c9b586351af8838f4f201cb8f4b70ef3b0da06d352c80fc26baf8f42b784459"
+ "ebf9985960176da6d23c7452a2954ffcbbcb24249b43019a2a023e0b3dabd461f19ad3e775c364f3f11ad49f3099400d3",
+ "04d09bb822eb99e38060954747c82bb3278cf96bbf36fece3400f4c873838a40c135eb3babb9293bd1001bf3ecdee7bf2"
+ "6d416db6e1b87bbb7427788a3b6c7a7ab2c165b1e366f9608df512037584f213a648d47f16ac326e19aae972f63fd76c9",
+ "012d191cf7404a523678c6fc075de8285b243720a903047708bb33e501e0dbee5bcc40d7c3ef6c6da39ea24d830da1e8",
+ "curve: P384 vector: 19", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "12048ebb4331ec19a1e23f1a2c773b664ccfe90a28bfb846fc12f81dff44b7443c77647164bf1e9e67fd2c07a6766241",
+ "04bc18836bc7a9fdf54b5352f37d7528ab8fa8ec544a8c6180511cbfdd49cce377c39e34c031b5240dc9980503ed2f26"
+ "2c8086cbe338191080f0b7a16c7afc4c7b0326f9ac66f58552ef4bb9d24de3429ed5d3277ed58fcf48f2b5f61326bec6c6",
+ "0413741262ede5861dad71063dfd204b91ea1d3b7c631df68eb949969527d79a1dc59295ef7d2bca6743e8cd77b04d1"
+ "b580baaeadc7e19d74a8a04451a135f1be1b02fe299f9dc00bfdf201e83d995c6950bcc1cb89d6f7b30bf54656b9a4da586",
+ "ad0fd3ddffe8884b9263f3c15fe1f07f2a5a22ffdc7e967085eea45f0cd959f20f18f522763e28bcc925e496a52dda98",
+ "curve: P384 vector: 20", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "34d61a699ca576169fcdc0cc7e44e4e1221db0fe63d16850c8104029f7d48449714b9884328cae189978754ab460b486",
+ "04867f81104ccd6b163a7902b670ef406042cb0cce7dcdc63d1dfc91b2c40e3cdf7595834bf9eceb79849f1636fc8462f"
+ "c9d4bde8e875ec49697d258d1d59465f8431c6f5531e1c59e9f9ebe3cf164a8d9ce10a12f1979283a959bad244dd83863",
+ "049e22cbc18657f516a864b37b783348b66f1aa9626cd631f4fa1bd32ad88cf11db52057c660860d39d11fbf024fabd44"
+ "46b0d53c79681c28116df71e9cee74fd56c8b7f04b39f1198cc72284e98be9562e35926fb4f48a9fbecafe729309e8b6f",
+ "dc4ca392dc15e20185f2c6a8ea5ec31dfc96f56153a47394b3072b13d0015f5d4ae13beb3bed54d65848f9b8383e6c95",
+ "curve: P384 vector: 21", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "dc60fa8736d702135ff16aab992bb88eac397f5972456c72ec447374d0d8ce61153831bfc86ad5a6eb5b60bfb96a862c",
+ "04b69beede85d0f829fec1b893ccb9c3e052ff692e13b974537bc5b0f9feaf7b22e84f03231629b24866bdb4b8cf9089"
+ "1466f85e2bfcaba2843285b0e14ebc07ef7dafff8b424416fee647b59897b619f20eed95a632e6a4206bf7da429c04c560",
+ "042db5da5f940eaa884f4db5ec2139b0469f38e4e6fbbcc52df15c0f7cf7fcb1808c749764b6be85d2fdc5b16f58ad5d"
+ "c022e8b02dcf33e1b5a083849545f84ad5e43f77cb71546dbbac0d11bdb2ee202e9d3872e8d028c08990746c5e1dde9989",
+ "d765b208112d2b9ed5ad10c4046e2e3b0dbf57c469329519e239ac28b25c7d852bf757d5de0ee271cadd021d86cfd347",
+ "curve: P384 vector: 22", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "6fa6a1c704730987aa634b0516a826aba8c6d6411d3a4c89772d7a62610256a2e2f289f5c3440b0ec1e70fa339e251ce",
+ "0453de1fc1328e8de14aecab29ad8a40d6b13768f86f7d298433d20fec791f86f8bc73f358098b256a298bb488de257bf"
+ "4ac28944fd27f17b82946c04c66c41f0053d3692f275da55cd8739a95bd8cd3af2f96e4de959ea8344d8945375905858b",
+ "04329647baa354224eb4414829c5368c82d7893b39804e08cbb2180f459befc4b347a389a70c91a23bd9d30c83be5295d"
+ "3cc8f61923fad2aa8e505d6cfa126b9fabd5af9dce290b75660ef06d1caa73681d06089c33bc4246b3aa30dbcd2435b12",
+ "d3778850aeb58804fbe9dfe6f38b9fa8e20c2ca4e0dec335aafceca0333e3f2490b53c0c1a14a831ba37c4b9d74be0f2",
+ "curve: P384 vector: 23", ec_field_GFp },
+
+ { ECCurve_NIST_P384, 1,
+ "74ad8386c1cb2ca0fcdeb31e0869bb3f48c036afe2ef110ca302bc8b910f621c9fcc54cec32bb89ec7caa84c7b8e54a8",
+ "0427a3e83cfb9d5122e73129d801615857da7cc089cccc9c54ab3032a19e0a0a9f677346e37f08a0b3ed8da6e5dd69106"
+ "38d60e44aa5e0fd30c918456796af37f0e41957901645e5c596c6d989f5859b03a0bd7d1f4e77936fff3c74d204e5388e",
+ "0429d8a36d22200a75b7aea1bb47cdfcb1b7fd66de967041434728ab5d533a060df732130600fe6f75852a871fb2938e3"
+ "9e19b53db528395de897a45108967715eb8cb55c3fcbf23379372c0873a058d57544b102ecce722b2ccabb1a603774fd5",
+ "81e1e71575bb4505498de097350186430a6242fa6c57b85a5f984a23371123d2d1424eefbf804258392bc723e4ef1e35",
+ "curve: P384 vector: 24", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "017eecc07ab4b329068fba65e56a1f8890aa935e57134ae0ffcce802735151f4eac6564f6ee9974c5e6887a1fefee5743"
+ "ae2241bfeb95d5ce31ddcb6f9edb4d6fc47",
+ "0400602f9d0cf9e526b29e22381c203c48a886c2b0673033366314f1ffbcba240ba42f4ef38a76174635f91e6b4ed3427"
+ "5eb01c8467d05ca80315bf1a7bbd945f550a501b7c85f26f5d4b2d7355cf6b02117659943762b6d1db5ab4f1dbc44ce7b2"
+ "946eb6c7de342962893fd387d1b73d7a8672d1f236961170b7eb3579953ee5cdc88cd2d",
+ "0400685a48e86c79f0f0875f7bc18d25eb5fc8c0b07e5da4f4370f3a9490340854334b1e1b87fa395464c60626124a4e70"
+ "d0f785601d37c09870ebf176666877a2046d01ba52c56fc8776d9e8f5db4f0cc27636d0b741bbe05400697942e80b739884"
+ "a83bde99e0f6716939e632bc8986fa18dccd443a348b6c3e522497955a4f3c302f676",
+ "005fc70477c3e63bc3954bd0df3ea0d1f41ee21746ed95fc5e1fdf90930d5e136672d72cc770742d1711c3c3a4c334a0ad9"
+ "759436a4d3c5bf6e74b9578fac148c831",
+ "curve: P521 vector: 0", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "00816f19c1fb10ef94d4a1d81c156ec3d1de08b66761f03f06ee4bb9dcebbbfe1eaa1ed49a6a990838d8ed318c14d74cc"
+ "872f95d05d07ad50f621ceb620cd905cfb8",
+ "0400d45615ed5d37fde699610a62cd43ba76bedd8f85ed31005fe00d6450fbbd101291abd96d4945a8b57bc73b3fe9f46"
+ "71105309ec9b6879d0551d930dac8ba45d25501425332844e592b440c0027972ad1526431c06732df19cd46a242172d4d"
+ "d67c2c8c99dfc22e49949a56cf90c6473635ce82f25b33682fb19bc33bd910ed8ce3a7fa",
+ "0401df277c152108349bc34d539ee0cf06b24f5d3500677b4445453ccc21409453aafb8a72a0be9ebe54d12270aa51b3a"
+ "b7f316aa5e74a951c5e53f74cd95fc29aee7a013d52f33a9f3c14384d1587fa8abe7aed74bc33749ad9c570b471776422c"
+ "7d4505d9b0a96b3bfac041e4c6a6990ae7f700e5b4a6640229112deafa0cd8bb0d089b0",
+ "000b3920ac830ade812c8f96805da2236e002acbbf13596a9ab254d44d0e91b6255ebf1229f366fb5a05c5884ef46032c2"
+ "6d42189273ca4efa4c3db6bd12a6853759",
+ "curve: P521 vector: 1", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "012f2e0c6d9e9d117ceb9723bced02eb3d4eebf5feeaf8ee0113ccd8057b13ddd416e0b74280c2d0ba8ed291c443bc1b14"
+ "1caf8afb3a71f97f57c225c03e1e4d42b0",
+ "0400717fcb3d4a40d103871ede044dc803db508aaa4ae74b70b9fb8d8dfd84bfecfad17871879698c292d2fd5e17b4f9343"
+ "636c531a4fac68a35a93665546b9a87867900f3d96a8637036993ab5d244500fff9d2772112826f6436603d3eb234a44d5c"
+ "4e5c577234679c4f9df725ee5b9118f23d8a58d0cc01096daf70e8dfec0128bdc2e8",
+ "040092db3142564d27a5f0006f819908fba1b85038a5bc2509906a497daac67fd7aee0fc2daba4e4334eeaef0e0019204b4"
+ "71cd88024f82115d8149cc0cf4f7ce1a4d5016bad0623f517b158d9881841d2571efbad63f85cbe2e581960c5d670601a67"
+ "60272675a548996217e4ab2b8ebce31d71fca63fcc3c08e91c1d8edd91cf6fe845f8",
+ "006b380a6e95679277cfee4e8353bf96ef2a1ebdd060749f2f046fe571053740bbcc9a0b55790bc9ab56c3208aa05ddf746"
+ "a10a3ad694daae00d980d944aabc6a08f",
+ "curve: P521 vector: 2", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "00e548a79d8b05f923b9825d11b656f222e8cb98b0f89de1d317184dc5a698f7c71161ee7dc11cd31f4f4f8ae3a981e1a3e7"
+ "8bdebb97d7c204b9261b4ef92e0918e0",
+ "04000ce800217ed243dd10a79ad73df578aa8a3f9194af528cd1094bbfee27a3b5481ad5862c8876c0c3f91294c0ab3aa806"
+ "d9020cbaa2ed72b7fecdc5a09a6dad6f3201543c9ab45b12469232918e21d5a351f9a4b9cbf9efb2afcc402fa9b31650bec2d6"
+ "41a05c440d35331c0893d11fb13151335988b303341301a73dc5f61d574e67d9",
+ "0400fdd40d9e9d974027cb3bae682162eac1328ad61bc4353c45bf5afe76bf607d2894c8cce23695d920f2464fda4773d4693b"
+ "e4b3773584691bdb0329b7f4c86cc2990034ceac6a3fef1c3e1c494bfe8d872b183832219a7e14da414d4e3474573671ec19b03"
+ "3be831b915435905925b44947c592959945b4eb7c951c3b9c8cf52530ba23",
+ "00fbbcd0b8d05331fef6086f22a6cce4d35724ab7a2f49dd8458d0bfd57a0b8b70f246c17c4468c076874b0dff7a0336823b19e"
+ "98bf1cec05e4beffb0591f97713c6",
+ "curve: P521 vector: 3", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "01c8aae94bb10b8ca4f7be577b4fb32bb2381032c4942c24fc2d753e7cc5e47b483389d9f3b956d20ee9001b1eef9f23545f72"
+ "c5602140046839e963313c3decc864",
+ "040106a14e2ee8ff970aa8ab0c79b97a33bba2958e070b75b94736b77bbe3f777324fa52872771aa88a63a9e8490c3378df4dc"
+ "760cd14d62be700779dd1a4377943656002366ce3941e0b284b1aa81215d0d3b9778fce23c8cd1e4ed6fa0abf62156c91d4b3eb"
+ "55999c3471bed275e9e60e5aa9d690d310bfb15c9c5bbd6f5e9eb39682b74",
+ "040098d99dee0816550e84dbfced7e88137fddcf581a725a455021115fe49f8dc3cf233cd9ea0e6f039dc7919da973cdceaca20"
+ "5da39e0bd98c8062536c47f258f44b500cd225c8797371be0c4297d2b457740100c774141d8f214c23b61aa2b6cd4806b9b70722"
+ "aa4965fb622f42b7391e27e5ec21c5679c5b06b59127372997d421adc1e",
+ "0145cfa38f25943516c96a5fd4bfebb2f645d10520117aa51971eff442808a23b4e23c187e639ff928c3725fbd1c0c2ad0d4aeb2"
+ "07bc1a6fb6cb6d467888dc044b3c",
+ "curve: P521 vector: 4", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "009b0af137c9696c75b7e6df7b73156bb2d45f482e5a4217324f478b10ceb76af09724cf86afa316e7f89918d31d54824a5c33"
+ "107a483c15c15b96edc661340b1c0e",
+ "0400748cdbb875d35f4bccb62abe20e82d32e4c14dc2feb5b87da2d0ccb11c9b6d4b7737b6c46f0dfb4d896e2db92fcf53cdbb"
+ "ae2a404c0babd564ad7adeac6273efa301984acab8d8f173323de0bb60274b228871609373bb22a17287e9dec7495873abc09a"
+ "8915b54c8455c8e02f654f602e23a2bbd7a9ebb74f3009bd65ecc650814cc0",
+ "04007ae115adaaf041691ab6b7fb8c921f99d8ed32d283d67084e80b9ad9c40c56cd98389fb0a849d9ecf7268c297b6f934061"
+ "19f40e32b5773ed25a28a9a85c4a758801a28e004e37eeaefe1f4dbb71f1878696141af3a10a9691c4ed93487214643b761fa4b"
+ "0fbeeb247cf6d3fba7a60697536ad03f49b80a9d1cb079673654977c5fa94",
+ "005c5721e96c273319fd60ecc46b5962f698e974b429f28fe6962f4ac656be2eb8674c4aafc037eab48ece612953b1e8d86101"
+ "6b6ad0c79805784c67f73ada96f351",
+ "curve: P521 vector: 5", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "01e48faacee6dec83ffcde944cf6bdf4ce4bae72747888ebafee455b1e91584971efb49127976a52f4142952f7c207ec0265f2b"
+ "718cf3ead96ea4f62c752e4f7acd3",
+ "04010eb1b4d9172bcc23f4f20cc9560fc54928c3f34ea61c00391dc766c76ed9fa608449377d1e4fadd1236025417330b4b91086"
+ "704ace3e4e6484c606e2a943478c860149413864069825ee1d0828da9f4a97713005e9bd1adbc3b38c5b946900721a960fe96ad2c"
+ "1b3a44fe3de9156136d44cb17cbc2415729bb782e16bfe2deb3069e43",
+ "04012588115e6f7f7bdcfdf57f03b169b479758baafdaf569d04135987b2ce6164c02a57685eb5276b5dae6295d3fe90620f38b55"
+ "35c6d2260c173e61eb888ca92020301542c169cf97c2596fe2ddd848a222e367c5f7e6267ebc1bcd9ab5dcf49158f1a48e4af29a89"
+ "7b7e6a82091c2db874d8e7abf0f58064691344154f396dbaed188b6",
+ "01736d9717429b4f412e903febe2f9e0fffd81355d6ce2c06ff3f66a3be15ceec6e65e308347593f00d7f33591da4043c30763d72"
+ "749f72cdceebe825e4b34ecd570",
+ "curve: P521 vector: 6", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "00c29aa223ea8d64b4a1eda27f39d3bc98ea0148dd98c1cbe595f8fd2bfbde119c9e017a50f5d1fc121c08c1cef31b75885955"
+ "6eb3e0e042d8dd6aaac57a05ca61e3",
+ "04001511c848ef60d5419a98d10204db0fe58224124370061bcfa4e9249d50618c56bf3722471b259f38263bb7b280d23caf2a"
+ "1ee8737f9371cdb2732cdc958369930c01d461681ae6d8c49b4c5f4d6016143fb1bd7491573e3ed0e6c48b82e821644f87f82f0"
+ "e5f08fd16f1f98fa17586200ab02ed8c627b35c3f27617ec5fd92f456203f",
+ "040169491d55bd09049fdf4c2a53a660480fee4c03a0538675d1cd09b5bba78dac48543ef118a1173b3fbf8b20e39ce0e6b8"
+ "90a163c50f9645b3d21d1cbb3b60a6fff40083494b2eba76910fed33c761804515011fab50e3b377abd8a8a045d886d2238d2"
+ "c268ac1b6ec88bd71b7ba78e2c33c152e4bf7da5d565e4acbecf5e92c7ad662bb",
+ "018f2ae9476c771726a77780208dedfefa205488996b18fecc50bfd4c132753f5766b2cd744afa9918606de2e016effc63622"
+ "e9029e76dc6e3f0c69f7aeced565c2c",
+ "curve: P521 vector: 7", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "0028692be2bf5c4b48939846fb3d5bce74654bb2646e15f8389e23708a1afadf561511ea0d9957d0b53453819d60fba8f65a1"
+ "8f7b29df021b1bb01cd163293acc3cc",
+ "0401cfdc10c799f5c79cb6930a65fba351748e07567993e5e410ef4cacc4cd8a25784991eb4674e41050f930c7190ac812b92"
+ "45f48a7973b658daf408822fe5b85f6680180d9ddfc9af77b9c4a6f02a834db15e535e0b3845b2cce30388301b51cecbe32763"
+ "07ef439b5c9e6a72dc2d94d879bc395052dbb4a5787d06efb280210fb8be037",
+ "04008415f5bbd0eee387d6c09d0ef8acaf29c66db45d6ba101860ae45d3c60e1e0e3f7247a4626a60fdd404965c3566c79f644"
+ "9e856ce0bf94619f97da8da24bd2cfb600fdd7c59c58c361bc50a7a5d0d36f723b17c4f2ad2b03c24d42dc50f74a8c465a0afc"
+ "4683f10fab84652dfe9e928c2626b5456453e1573ff60be1507467d431fbb2",
+ "0105a346988b92ed8c7a25ce4d79d21bc86cfcc7f99c6cd19dbb4a39f48ab943b79e4f0647348da0b80bd864b85c6b8d92536"
+ "d6aa544dc7537a00c858f8b66319e25",
+ "curve: P521 vector: 8", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "01194d1ee613f5366cbc44b504d21a0cf6715e209cd358f2dd5f3e71cc0d67d0e964168c42a084ebda746f9863a86bacffc81"
+ "9f1edf1b8c727ccfb3047240a57c435",
+ "04016bd15c8a58d366f7f2b2f298cc87b7485e9ee70d11d12448b8377c0a82c7626f67aff7f97be7a3546bf417eeeddf75a93"
+ "c130191c84108042ea2fca17fd3f80d1401560502d04b74fce1743aab477a9d1eac93e5226981fdb97a7478ce4ce566ff72439"
+ "31284fad850b0c2bcae0ddd2d97790160c1a2e77c3ed6c95ecc44b89e2637fc",
+ "0401c721eea805a5cba29f34ba5758775be0cf6160e6c08723f5ab17bf96a1ff2bd9427961a4f34b07fc0b14ca4b2bf6845de"
+ "bd5a869f124ebfa7aa72fe565050b7f1800b6e89eb0e1dcf181236f7c548fd1a8c16b258b52c1a9bfd3fe8f22841b26763265"
+ "f074c4ccf2d634ae97b701956f67a11006c52d97197d92f585f5748bc2672eeb",
+ "004531b3d2c6cd12f21604c8610e6723dbf4daf80b5a459d6ba5814397d1c1f7a21d7c114be964e27376aaebe3a7bc3d6af7"
+ "a7f8c7befb611afe487ff032921f750f",
+ "curve: P521 vector: 9", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "01fd90e3e416e98aa3f2b6afa7f3bf368e451ad9ca5bd54b5b14aee2ed6723dde5181f5085b68169b09fbec721372ccf6b"
+ "284713f9a6356b8d560a8ff78ca3737c88",
+ "0401ebea1b10d3e3b971b7efb69fc878de11c7f472e4e4d384c31b8d6288d8071517acade9b39796c7af5163bcf71aeda7"
+ "77533f382c6cf0a4d9bbb938c85f44b78037016b0e3e19c2996b2cbd1ff64730e7ca90edca1984f9b2951333535e5748baa"
+ "34a99f61ff4d5f812079e0f01e87789f34efdad8098015ee74a4f846dd190d16dc6e1",
+ "0401c35823e440a9363ab98d9fc7a7bc0c0532dc7977a79165599bf1a9cc64c00fb387b42cca365286e8430360bfad3643"
+ "bc31354eda50dc936c329ecdb60905c40fcb00d9e7f433531e44df4f6d514201cbaabb06badd6783e01111726d815531d23"
+ "3c5cdb722893ffbb2027259d594de77438809738120c6f783934f926c3fb69b40c409",
+ "0100c8935969077bae0ba89ef0df8161d975ec5870ac811ae7e65ca5394efba4f0633d41bf79ea5e5b9496bbd7aae000b05"
+ "94baa82ef8f244e6984ae87ae1ed124b7",
+ "curve: P521 vector: 10", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "009012ecfdadc85ced630afea534cdc8e9d1ab8be5f3753dcf5f2b09b40eda66fc6858549bc36e6f8df55998cfa9a0703a"
+ "ecf6c42799c245011064f530c09db98369",
+ "0400234e32be0a907131d2d128a6477e0caceb86f02479745e0fe245cb332de631c078871160482eeef584e274df7fa412c"
+ "ea3e1e91f71ecba8781d9205d48386341ad01cf86455b09b1c005cffba8d76289a3759628c874beea462f51f30bd581e380"
+ "3134307dedbb771b3334ee15be2e242cd79c3407d2f58935456c6941dd9b6d155a46",
+ "0400093057fb862f2ad2e82e581baeb3324e7b32946f2ba845a9beeed87d6995f54918ec6619b9931955d5a89d4d74adf10"
+ "46bb362192f2ef6bd3e3d2d04dd1f87054a00aa3fb2448335f694e3cda4ae0cc71b1b2f2a206fa802d7262f19983c44674f"
+ "e15327acaac1fa40424c395a6556cb8167312527fae5865ecffc14bbdc17da78cdcf",
+ "017f36af19303841d13a389d95ec0b801c7f9a679a823146c75c17bc44256e9ad422a4f8b31f14647b2c7d317b933f7c294"
+ "6c4b8abd1d56d620fab1b5ff1a3adc71f",
+ "curve: P521 vector: 11", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "01b5ff847f8eff20b88cfad42c06e58c3742f2f8f1fdfd64b539ba48c25926926bd5e332b45649c0b184f77255e9d58fe8"
+ "afa1a6d968e2cb1d4637777120c765c128",
+ "0401de3dc9263bc8c4969dc684be0eec54befd9a9f3dba194d8658a789341bf0d78d84da6735227cafaf093519516911975"
+ "73c8c360a11e5285712b8bbdf5ac91b977c00812de58cd095ec2e5a9b247eb3ed41d8bef6aeace194a7a05b65aa5d289fbc9"
+ "b1770ec84bb6be0c2c64cc37c1d54a7f5d71377a9adbe20f26f6f2b544a821ea831",
+ "040083192ed0b1cb31f75817794937f66ad91cf74552cd510cedb9fd641310422af5d09f221cad249ee814d16dd7ac84ded"
+ "9eacdc28340fcfc9c0c06abe30a2fc28cd8002212ed868c9ba0fb2c91e2c39ba93996a3e4ebf45f2852d0928c48930e875c"
+ "c7b428d0e7f3f4d503e5d60c68cb49b13c2480cd486bed9200caddaddfe4ff8e3562",
+ "00062f9fc29ae1a68b2ee0dcf956cbd38c88ae5f645eaa546b00ebe87a7260bf724be20d34b9d02076655c933d056b21e30"
+ "4c24ddb1dedf1dd76de611fc4a2340336",
+ "curve: P521 vector: 12", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "011a6347d4e801c91923488354cc533e7e35fddf81ff0fb7f56bb0726e0c29ee5dcdc5f394ba54cf57269048aab6e055895c"
+ "8da24b8b0639a742314390cc04190ed6",
+ "0400fe30267f33ba5cdefc25cbb3c9320dad9ccb1d7d376644620ca4fadee5626a3cede25ad254624def727a7048f7145f761"
+ "62aa98042f9b123b2076f8e8cf59b3fdf001145dc6631953b6e2945e94301d6cbb098fe4b04f7ee9b09411df104dc82d7d79e"
+ "c46a01ed0f2d3e7db6eb680694bdeb107c1078aec6cabd9ebee3d342fe7e54df",
+ "0401a89b636a93e5d2ba6c2292bf23033a84f06a3ac1220ea71e806afbe097a804cc67e9baa514cfb6c12c9194be30212bf7a"
+ "ae7fdf6d376c212f0554e656463ffab7e0182efcaf70fc412d336602e014da47256a0b606f2addcce8053bf817ac8656bb4e4"
+ "2f14c8cbf2a68f488ab35dcdf64056271dee1f606a440ba4bd4e5a11b8b8e54f",
+ "0128ab09bfec5406799e610f772ba17e892249fa8e0e7b18a04b9197034b250b48294f1867fb9641518f92766066a07a8b917"
+ "b0e76879e1011e51ccbd9f540c54d4f",
+ "curve: P521 vector: 13", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "0022b6d2a22d71dfaa811d2d9f9f31fbed27f2e1f3d239538ddf3e4cc8c39a330266db25b7bc0a9704f17bde7f3592bf5f1f2d"
+ "4b56013aacc3d8d1bc02f00d3146cc",
+ "0400ba38cfbf9fd2518a3f61d43549e7a6a6d28b2be57ffd3e0faceb636b34ed17e044a9f249dae8fc132e937e2d9349cd2ed7"
+ "7bb1049ceb692a2ec5b17ad61502a64c001ec91d3058573fa6c0564a02a1a010160c313bc7c73510dc983e5461682b5be00dbc"
+ "e7e2c682ad73f29ca822cdc111f68fabe33a7b384a648342c3cdb9f050bcdb",
+ "04017200b3f16a68cbaed2bf78ba8cddfb6cffac262bba00fbc25f9dc72a07ce59372904899f364c44cb264c097b647d4412be"
+ "e3e519892d534d9129f8a28f7500fee700baba8d672a4f4a3b63de48b96f56e18df5d68f7d70d5109833f43770d6732e06b39ad"
+ "60d93e5b43db8789f1ec0aba47286a39ea584235acea757dbf13d53b58364",
+ "0101e462e9d9159968f6440e956f11dcf2227ae4aea81667122b6af9239a291eb5d6cf5a4087f358525fcacfa46bb2db01a75a"
+ "f1ba519b2d31da33eda87a9d565748",
+ "curve: P521 vector: 14", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "005bacfff268acf6553c3c583b464ea36a1d35e2b257a5d49eb3419d5a095087c2fb4d15cf5bf5af816d0f3ff7586490ccd3ddc1"
+ "a98b39ce63749c6288ce0dbdac7d",
+ "040036e488da7581472a9d8e628c58d6ad727311b7e6a3f6ae33a8544f34b09280249020be7196916fafd90e2ec54b66b5468d23"
+ "61b99b56fa00d7ac37abb8c6f16653011edb9fb8adb6a43f4f5f5fdc1421c9fe04fc8ba46c9b66334e3af927c8befb4307104f299"
+ "acec4e30f812d9345c9720d19869dbfffd4ca3e7d2713eb5fc3f42615",
+ "04004efd5dbd2f979e3831ce98f82355d6ca14a5757842875882990ab85ab9b7352dd6b9b2f4ea9a1e95c3880d65d1f3602f9ca6"
+ "53dc346fac858658d75626f4d4fb080061cf15dbdaa7f31589c98400373da284506d70c89f074ed262a9e28140796b7236c2eef99"
+ "016085e71552ff488c72b7339fefb7915c38459cb20ab85aec4e45052",
+ "0141d6a4b719ab67eaf04a92c0a41e2dda78f4354fb90bdc35202cc7699b9b04d49616f82255debf7bbec045ae58f982a66905fc"
+ "fae69d689785e38c868eb4a27e7b",
+ "curve: P521 vector: 15", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "008e2c93c5423876223a637cad367c8589da69a2d0fc68612f31923ae50219df2452e7cc92615b67f17b57ffd2f52b19154bb40"
+ "d7715336420fde2e89fee244f59dc",
+ "0400fa3b35118d6c422570f724a26f90b2833b19239174cea081c53133f64db60d6940ea1261299c04c1f4587cdb0c4c39616"
+ "479c1bb0c146799a118032dcf98f899c00069f040229006151fa32b51f679c8816f7c17506b403809dc77cd58a2aec430d94d"
+ "13b6c916de99f355aa45fcfbc6853d686c71be496a067d24bfaea4818fc51f75",
+ "040129891de0cf3cf82e8c2cf1bf90bb296fe00ab08ca45bb7892e0e227a504fdd05d2381a4448b68adff9c4153c87eacb783"
+ "30d8bd52515f9f9a0b58e85f446bb4e10009edd679696d3d1d0ef327f200383253f6413683d9e4fcc87bb35f112c2f110098d"
+ "15e5701d7ceee416291ff5fed85e687f727388b9afe26a4f6feed560b218e6bb",
+ "00345e26e0abb1aac12b75f3a9cf41efe1c336396dffa4a067a4c2cfeb878c68b2b045faa4e5b4e6fa4678f5b603c351903b1"
+ "4bf9a6a70c439257199a640890b61d1",
+ "curve: P521 vector: 16", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "0004d49d39d40d8111bf16d28c5936554326b197353eebbcf47545393bc8d3aaf98f14f5be7074bfb38e6cc97b989754074da"
+ "ddb3045f4e4ce745669fdb3ec0d5fa8",
+ "04012ec226d050ce07c79b3df4d0f0891f9f7adf462e8c98dbc1a2a14f5e53a3f5ad894433587cc429a8be9ea1d84fa33b180"
+ "3690dae04da7218d30026157fc995cf52004837dfbf3426f57b5c793269130abb9a38f618532211931154db4eeb9aede88e57"
+ "290f842ea0f2ea9a5f74c6203a3920fe4e305f6118f676b154e1d75b9cb5eb88",
+ "0401a3c20240e59f5b7a3e17c275d2314ba1741210ad58b71036f8c83cc1f6b0f409dfdd9113e94b67ec39c3291426c23ffc"
+ "c447054670d2908ff8fe67dc2306034c5c01d2825bfd3af8b1e13205780c137fe938f84fde40188e61ea02cead81badfdb425"
+ "c29f7d7fb0324debadc10bbb93de68f62c35069268283f5265865db57a79f7bf7",
+ "006fe9de6fb8e672e7fd150fdc5e617fabb0d43906354ccfd224757c7276f7a1010091b17ed072074f8d10a5ec971eb35a5c"
+ "b7076603b7bc38d432cbc059f80f9488",
+ "curve: P521 vector: 17", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "011a5d1cc79cd2bf73ea106f0e60a5ace220813b53e27b739864334a07c03367efda7a4619fa6eef3a9746492283b3c445610"
+ "a023a9cc49bf4591140384fca5c8bb5",
+ "0400eb07c7332eedb7d3036059d35f7d2288d4377d5f42337ad3964079fb120ccd4c8bd384b585621055217023acd9a94fcb3"
+ "b965bfb394675e788ade41a1de73e620c00491a835de2e6e7deb7e090f4a11f2c460c0b1f3d5e94ee8d751014dc720784fd3b"
+ "54500c86ebaef18429f09e8e876d5d1538968a030d7715dde99f0d8f06e29d59",
+ "04007e2d138f2832e345ae8ff65957e40e5ec7163f016bdf6d24a2243daa631d878a4a16783990c722382130f9e51f0c1bd6"
+ "ff5ac96780e48b68f5dec95f42e6144bb500b0de5c896791f52886b0f09913e26e78dd0b69798fc4df6d95e3ca708ecbcbcce1c1895f"
+ "5561bbabaae372e9e67e6e1a3be60e19b470cdf673ec1fc393d3426e20",
+ "01e4e759ecedce1013baf73e6fcc0b92451d03bdd50489b78871c333114990c9ba6a9b2fc7b1a2d9a1794c1b60d9279af6f"
+ "146f0bbfb0683140403bfa4ccdb524a29",
+ "curve: P521 vector: 18", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "010c908caf1be74c616b625fc8c1f514446a6aec83b5937141d6afbb0a8c7666a7746fa1f7a6664a2123e8cdf6cd8bf836c5"
+ "6d3c0ebdcc980e43a186f938f3a78ae7",
+ "040031890f4c7abec3f723362285d77d2636f876817db3bbc88b01e773597b969ff6f013ea470c854ab4a7739004eb8cbea6"
+ "9b82ddf36acadd406871798ecb2ac3aa7f00d8b429ae3250266b9643c0c765a60dc10155bc2531cf8627296f4978b6640a9e"
+ "600e19d0037d58503fa80799546a814d7478a550aa90e5ebeb052527faaeae5d08",
+ "0400118c36022209b1af8ebad1a12b566fc48744576e1199fe80de1cdf851cdf03e5b9091a8f7e079e83b7f827259b691d0"
+ "c22ee29d6bdf73ec7bbfd746f2cd97a357d00da5ff4904548a342e2e7ba6a1f4ee5f840411a96cf63e6fe622f22c13e614e"
+ "0a847c11a1ab3f1d12cc850c32e095614ca8f7e2721477b486e9ff40372977c3f65c",
+ "0163c9191d651039a5fe985a0eea1eba018a40ab1937fcd2b61220820ee8f2302e9799f6edfc3f5174f369d672d377ea895"
+ "4a8d0c8b851e81a56fda95212a6578f0e",
+ "curve: P521 vector: 19", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "01b37d6b7288de671360425d3e5ac1ccb21815079d8d73431e9b74a6f0e7ae004a357575b11ad66642ce8b775593eba9d98"
+ "bf25c75ef0b4d3a2098bbc641f59a2b77",
+ "0400189a5ee34de7e35aefeaeef9220c18071b4c29a4c3bd9d954458bd3e82a7a34da34cff5579b8101c065b1f2f527cf45"
+ "81501e28ef5671873e65267733d003520af01eb4bc50a7b4d4599d7e3fa773ddb9eb252c9b3422872e544bdf75c7bf60f51"
+ "66ddc11eb08fa7c30822dabaee373ab468eb2d922e484e2a527fff2ebb804b7d9a37",
+ "0401780edff1ca1c03cfbe593edc6c049bcb2860294a92c355489d9afb2e702075ade1c953895a456230a0cde905de4a3f"
+ "38573dbfcccd67ad6e7e93f0b5581e926a5d00a5481962c9162962e7f0ebdec936935d0eaa813e8226d40d7f6119bfd940"
+ "602380c86721e61db1830f51e139f210000bcec0d8edd39e54d73a9a129f95cd5fa979",
+ "015d613e267a36342e0d125cdad643d80d97ed0600afb9e6b9545c9e64a98cc6da7c5aaa3a8da0bdd9dd3b97e9788218a8"
+ "0abafc106ef065c8f1c4e1119ef58d298b",
+ "curve: P521 vector: 20", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "00f2661ac762f60c5fff23be5d969ccd4ec6f98e4e72618d12bdcdb9b4102162333788c0bae59f91cdfc172c7a1681ee44d9"
+ "6ab2135a6e5f3415ebbcd55165b1afb0",
+ "0400a8e25a6902d687b4787cdc94c364ac7cecc5c495483ed363dc0aa95ee2bd739c4c4d46b17006c728b076350d7d7e54c"
+ "6822f52f47162a25109aaaba690cab696ec0168d2f08fe19e4dc9ee7a195b03c9f7fe6676f9f520b6270557504e72ca4394"
+ "a2c6918625e15ac0c51b8f95cd560123653fb8e8ee6db961e2c4c62cc54e92e2a2a9",
+ "04016dacffa183e5303083a334f765de724ec5ec9402026d4797884a9828a0d321a8cfac74ab737fe20a7d6befcfc73b6a3"
+ "5c1c7b01d373e31abc192d48a4241a35803011e5327cac22d305e7156e559176e19bee7e4f2f59e86f1a9d0b6603b6a7df"
+ "1069bde6387feb71587b8ffce5b266e1bae86de29378a34e5c74b6724c4d40a719923",
+ "014d6082a3b5ced1ab8ca265a8106f302146c4acb8c30bb14a4c991e3c82a9731288bdb91e0e85bda313912d06384fc44"
+ "f2153fb13506fa9cf43c9aab5750988c943",
+ "curve: P521 vector: 21", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "00f430ca1261f09681a9282e9e970a9234227b1d5e58d558c3cc6eff44d1bdf53de16ad5ee2b18b92d62fc79586116b0e"
+ "fc15f79340fb7eaf5ce6c44341dcf8dde27",
+ "04006c1d9b5eca87de1fb871a0a32f807c725adccde9b3967453a71347d608f0c030cd09e338cdecbf4a02015bc8a6e8"
+ "d3e2595fe773ffc2fc4e4a55d0b1a2cc00323b01141b2109e7f4981c952aa818a2b9f6f5c41feccdb7a7a45b9b4b6729"
+ "37771b008cae5f934dfe3fed10d383ab1f38769c92ce88d9be5414817ecb073a31ab368ccb",
+ "0400a091421d3703e3b341e9f1e7d58f8cf7bdbd1798d001967b801d1cec27e605c580b2387c1cb464f55ce7ac803341"
+ "02ab03cfb86d88af76c9f4129c01bedd3bbfc4008c9c577a8e6fc446815e9d40baa66025f15dae285f19eb668ee60ae9"
+ "c98e7ecdbf2b2a68e22928059f67db188007161d3ecf397e0883f0c4eb7eaf7827a62205cc",
+ "0020c00747cb8d492fd497e0fec54644bf027d418ab686381f109712a99cabe328b9743d2225836f9ad66e5d7fed1de2"
+ "47e0da92f60d5b31f9e47672e57f710598f4",
+ "curve: P521 vector: 22", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "005dc33aeda03c2eb233014ee468dff753b72f73b00991043ea353828ae69d4cd0fadeda7bb278b535d7c57406ff2e6e"
+ "473a5a4ff98e90f90d6dadd25100e8d85666",
+ "0400c825ba307373cec8dd2498eef82e21fd9862168dbfeb83593980ca9f82875333899fe94f137daf1c4189eb502937"
+ "c3a367ea7951ed8b0f3377fcdf2922021d46a5016b8a2540d5e65493888bc337249e67c0a68774f3e8d81e3b4574a012"
+ "5165f0bd58b8af9de74b35832539f95c3cd9f1b759408560aa6851ae3ac7555347b0d3b13b",
+ "04004f38816681771289ce0cb83a5e29a1ab06fc91f786994b23708ff08a08a0f675b809ae99e9f9967eb1a49f196057"
+ "d69e50d6dedb4dd2d9a81c02bdcc8f7f518460009efb244c8b91087de1eed766500f0e81530752d469256ef79f6b965d"
+ "8a2232a0c2dbc4e8e1d09214bab38485be6e357c4200d073b52f04e4a16fc6f5247187aecb",
+ "00c2bfafcd7fbd3e2fd1c750fdea61e70bd4787a7e68468c574ee99ebc47eedef064e8944a73bcb7913dbab5d93dca6"
+ "60d216c553622362794f7a2acc71022bdb16f",
+ "curve: P521 vector: 23", ec_field_GFp },
+
+ { ECCurve_NIST_P521, 1,
+ "00df14b1f1432a7b0fb053965fd8643afee26b2451ecb6a8a53a655d5fbe16e4c64ce8647225eb11e7fdcb23627471"
+ "dffc5c2523bd2ae89957cba3a57a23933e5a78",
+ "04004e8583bbbb2ecd93f0714c332dff5ab3bc6396e62f3c560229664329baa5138c3bb1c36428abd4e23d17fcb7"
+ "a2cfcc224b2e734c8941f6f121722d7b6b9415457601cf0874f204b0363f020864672fadbf87c8811eb147758b254b"
+ "74b14fae742159f0f671a018212bbf25b8519e126d4cad778cfff50d288fd39ceb0cac635b175ec0",
+ "0401a32099b02c0bd85371f60b0dd20890e6c7af048c8179890fda308b359dbbc2b7a832bb8c6526c4af99a7ea3f0"
+ "b3cb96ae1eb7684132795c478ad6f962e4a6f446d017627357b39e9d7632a1370b3e93c1afb5c851b910eb4ead0c9"
+ "d387df67cde85003e0e427552f1cd09059aad0262e235cce5fba8cedc4fdc1463da76dcd4b6d1a46",
+ "01aaf24e5d47e4080c18c55ea35581cd8da30f1a079565045d2008d51b12d0abb4411cda7a0785b15d149ed301a36"
+ "97062f42da237aa7f07e0af3fd00eb1800d9c41",
+ "curve: P521 vector: 24", ec_field_GFp },
+
+ { ECCurve_pastLastCurve, 0, NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+static ECDH_KAT nonnist_testvecs[] = {
+ { ECCurve25519, 1,
+ "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
+ NULL,
+ "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c",
+ "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552",
+ "curve: 25519 vector: 0", ec_field_plain },
+ { ECCurve25519, 1,
+ "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d",
+ NULL,
+ "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493",
+ "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957",
+ "curve: 25519 vector: 1", ec_field_plain },
+ { ECCurve25519, 1,
+ "0900000000000000000000000000000000000000000000000000000000000000",
+ NULL,
+ "0900000000000000000000000000000000000000000000000000000000000000",
+ "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079",
+ "curve: 25519 vector: 2", ec_field_plain },
+ { ECCurve25519, 1000,
+ "0900000000000000000000000000000000000000000000000000000000000000",
+ NULL,
+ "0900000000000000000000000000000000000000000000000000000000000000",
+ "684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51",
+ "curve: 25519 vector: 1000 iterations", ec_field_plain },
+#ifdef NSS_ENABLE_EXPENSIVE_TESTS
+ /* This test is disabled by default because it takes a very long time
+ * to run. */
+ { ECCurve25519, 1000000,
+ "0900000000000000000000000000000000000000000000000000000000000000",
+ NULL,
+ "0900000000000000000000000000000000000000000000000000000000000000",
+ "7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424",
+ "curve: 25519 vector: 1000000 iterations", ec_field_plain },
+#endif
+ { ECCurve25519, 1,
+ "174a56a75017c029e0861044d3c57c291823cf477ae6e21065cc121578bfa893",
+ NULL,
+ "7bd8396462a5788951caf3d3a28cb0904e4d081e62e6ac2d9da7152eb1310f30",
+ "28c09f6be3666a6ab3bf8f5b03eec14e95505e32726ae887053ce6a2061a9656",
+ "curve: 25519 custom vector 1", ec_field_plain },
+ { ECCurve25519, 1,
+ "577a2a7fcdacd4ccf7d7f81ba93ec83ae4bda32bec00ff7d59c294b69404f688",
+ NULL,
+ "a43b5491cbd9273abf694115f383fabe3bdc5f2baa30d2e00e43b6937a75cc5d",
+ "4aed703c32552576ca0b30a3fab53242e1eea29ddec993219d3c2b3c3e59b735",
+ "curve: 25519 custom vector 1", ec_field_plain },
+
+ { ECCurve_pastLastCurve, 0, NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+static ECDH_BAD nonnist_testvecs_bad_values[] = {
+ { ECCurve25519, "00", "curve: 25519 vector: 0 bad point", ec_field_plain },
+ { ECCurve25519,
+ "0100000000000000000000000000000000000000000000000000000000000000",
+ "curve: 25519 vector: 1 bad point", ec_field_plain },
+ { ECCurve25519,
+ "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b8",
+ "curve: 25519 vector: 2 bad point", ec_field_plain },
+ { ECCurve25519,
+ "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157",
+ "curve: 25519 vector: 3 bad point", ec_field_plain },
+ { ECCurve25519,
+ "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+ "curve: 25519 vector: 4 bad point", ec_field_plain },
+ { ECCurve25519,
+ "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+ "curve: 25519 vector: 5 bad point", ec_field_plain },
+ { ECCurve25519,
+ "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+ "curve: 25519 vector: 6 bad point", ec_field_plain },
+ { ECCurve25519,
+ "cdeb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880",
+ "curve: 25519 vector: 7 bad point", ec_field_plain },
+ { ECCurve25519,
+ "4c9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7",
+ "curve: 25519 vector: 8 bad point", ec_field_plain },
+ { ECCurve25519,
+ "d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "curve: 25519 vector: 9 bad point", ec_field_plain },
+ { ECCurve25519,
+ "daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "curve: 25519 vector: 10 bad point", ec_field_plain },
+ { ECCurve25519,
+ "dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "curve: 25519 vector: 11 bad point", ec_field_plain },
+
+ { ECCurve_pastLastCurve, 0, NULL, 0 }
+};
diff --git a/security/nss/cmd/fipstest/Makefile b/security/nss/cmd/fipstest/Makefile
new file mode 100755
index 000000000..2cf5c0563
--- /dev/null
+++ b/security/nss/cmd/fipstest/Makefile
@@ -0,0 +1,49 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+#MKPROG = purify -cache-dir=/u/mcgreer/pcache -best-effort \
+# -always-use-cache-dir $(CC)
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/security/nss/cmd/fipstest/aes.sh b/security/nss/cmd/fipstest/aes.sh
new file mode 100644
index 000000000..7e25e60d2
--- /dev/null
+++ b/security/nss/cmd/fipstest/aes.sh
@@ -0,0 +1,112 @@
+#!/bin/sh
+#
+# 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/.
+#
+#
+# A Bourne shell script for running the NIST AES Algorithm Validation Suite
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+
+BASEDIR=${1-.}
+TESTDIR=${BASEDIR}/AES
+COMMAND=${2-run}
+REQDIR=${TESTDIR}/req
+RSPDIR=${TESTDIR}/resp
+
+cbc_kat_requests="
+CBCGFSbox128.req
+CBCGFSbox192.req
+CBCGFSbox256.req
+CBCKeySbox128.req
+CBCKeySbox192.req
+CBCKeySbox256.req
+CBCVarKey128.req
+CBCVarKey192.req
+CBCVarKey256.req
+CBCVarTxt128.req
+CBCVarTxt192.req
+CBCVarTxt256.req
+"
+
+cbc_mct_requests="
+CBCMCT128.req
+CBCMCT192.req
+CBCMCT256.req
+"
+
+cbc_mmt_requests="
+CBCMMT128.req
+CBCMMT192.req
+CBCMMT256.req
+"
+
+ecb_kat_requests="
+ECBGFSbox128.req
+ECBGFSbox192.req
+ECBGFSbox256.req
+ECBKeySbox128.req
+ECBKeySbox192.req
+ECBKeySbox256.req
+ECBVarKey128.req
+ECBVarKey192.req
+ECBVarKey256.req
+ECBVarTxt128.req
+ECBVarTxt192.req
+ECBVarTxt256.req
+"
+
+ecb_mct_requests="
+ECBMCT128.req
+ECBMCT192.req
+ECBMCT256.req
+"
+
+ecb_mmt_requests="
+ECBMMT128.req
+ECBMMT192.req
+ECBMMT256.req
+"
+
+if [ ${COMMAND} = "verify" ]; then
+ for request in $cbc_kat_requests $cbc_mct_requests $cbc_mmt_requests $ecb_kat_requests $ecb_mct_requests $ecb_mmt_requests; do
+ sh ./validate1.sh ${TESTDIR} $request
+ done
+ exit 0
+fi
+
+for request in $cbc_kat_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes kat cbc ${REQDIR}/$request > ${RSPDIR}/$response
+done
+for request in $cbc_mct_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes mct cbc ${REQDIR}/$request > ${RSPDIR}/$response
+done
+for request in $cbc_mmt_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes mmt cbc ${REQDIR}/$request > ${RSPDIR}/$response
+done
+for request in $ecb_kat_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes kat ecb ${REQDIR}/$request > ${RSPDIR}/$response
+done
+for request in $ecb_mct_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes mct ecb ${REQDIR}/$request > ${RSPDIR}/$response
+done
+for request in $ecb_mmt_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes mmt ecb ${REQDIR}/$request > ${RSPDIR}/$response
+done
diff --git a/security/nss/cmd/fipstest/aesgcm.sh b/security/nss/cmd/fipstest/aesgcm.sh
new file mode 100644
index 000000000..3b4dcf5e4
--- /dev/null
+++ b/security/nss/cmd/fipstest/aesgcm.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+#
+# 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/.
+#
+# A Bourne shell script for running the NIST AES Algorithm Validation Suite
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+
+BASEDIR=${1-.}
+TESTDIR=${BASEDIR}/AES_GCM
+COMMAND=${2-run}
+REQDIR=${TESTDIR}/req
+RSPDIR=${TESTDIR}/resp
+
+gcm_decrypt_requests="
+gcmDecrypt128.req
+gcmDecrypt192.req
+gcmDecrypt256.req
+"
+
+gcm_encrypt_extiv_requests="
+gcmEncryptExtIV128.req
+gcmEncryptExtIV192.req
+gcmEncryptExtIV256.req
+"
+gcm_encrypt_intiv_requests="
+"
+
+#gcm_encrypt_intiv_requests="
+#gcmEncryptIntIV128.req
+#gcmEncryptIntIV192.req
+#gcmEncryptIntIV256.req
+#"
+
+if [ ${COMMAND} = "verify" ]; then
+ for request in $gcm_decrypt_requests $gcm_encrypt_extiv_requests; do
+ sh ./validate1.sh ${TESTDIR} $request ' ' '-e /Reason:/d'
+ done
+ for request in $gcm_encrypt_intiv_requests; do
+ name=`basename $request .req`
+ echo ">>>>> $name"
+ fipstest aes gcm decrypt ${RSPDIR}/$name.rsp | grep FAIL
+ done
+ exit 0
+fi
+
+for request in $gcm_decrypt_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes gcm decrypt ${REQDIR}/$request > ${RSPDIR}/$response
+done
+for request in $gcm_encrypt_intiv_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes gcm encrypt_intiv ${REQDIR}/$request > ${RSPDIR}/$response
+done
+for request in $gcm_encrypt_extiv_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes gcm encrypt_extiv ${REQDIR}/$request > ${RSPDIR}/$response
+done
diff --git a/security/nss/cmd/fipstest/dsa.sh b/security/nss/cmd/fipstest/dsa.sh
new file mode 100755
index 000000000..da18e1fa3
--- /dev/null
+++ b/security/nss/cmd/fipstest/dsa.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# 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/.
+#
+# A Bourne shell script for running the NIST DSA Validation System
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+BASEDIR=${1-.}
+TESTDIR=${BASEDIR}/DSA2
+COMMAND=${2-run}
+REQDIR=${TESTDIR}/req
+RSPDIR=${TESTDIR}/resp
+
+
+#
+# several of the DSA tests do use known answer tests to verify the result.
+# in those cases, feed generated tests back into the fipstest tool and
+# see if we can verify those value. NOTE: th PQGVer and SigVer tests verify
+# the dsa pqgver and dsa sigver functions, so we know they can detect errors
+# in those PQGGen and SigGen. Only the KeyPair verify is potentially circular.
+#
+if [ ${COMMAND} = "verify" ]; then
+# verify generated keys
+ name=KeyPair
+ echo ">>>>> $name"
+ fipstest dsa keyver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+# verify generated pqg values
+ name=PQGGen
+ echo ">>>>> $name"
+ fipstest dsa pqgver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+# verify PQGVer with known answer
+# sh ./validate1.sh ${TESTDIR} PQGVer.req ' ' '-e /^Result.=.F/s;.(.*);; -e /^Result.=.P/s;.(.*);;'
+# verify signatures
+ name=SigGen
+ echo ">>>>> $name"
+ fipstest dsa sigver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+# verify SigVer with known answer
+ sh ./validate1.sh ${TESTDIR} SigVer.req ' ' '-e /^X.=/d -e /^Result.=.F/s;.(.*);;'
+ exit 0
+fi
+
+request=KeyPair.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest dsa keypair ${REQDIR}/$request > ${RSPDIR}/$response
+
+request=PQGGen.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest dsa pqggen ${REQDIR}/$request > ${RSPDIR}/$response
+
+request=PQGVer1863.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest dsa pqgver ${REQDIR}/$request > ${RSPDIR}/$response
+
+request=SigGen.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest dsa siggen ${REQDIR}/$request > ${RSPDIR}/$response
+
+request=SigVer.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest dsa sigver ${REQDIR}/$request > ${RSPDIR}/$response
diff --git a/security/nss/cmd/fipstest/ecdsa.sh b/security/nss/cmd/fipstest/ecdsa.sh
new file mode 100644
index 000000000..9482160cc
--- /dev/null
+++ b/security/nss/cmd/fipstest/ecdsa.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# 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/.
+#
+# A Bourne shell script for running the NIST ECDSA Validation System
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+BASEDIR=${1-.}
+TESTDIR=${BASEDIR}/ECDSA2
+COMMAND=${2-run}
+REQDIR=${TESTDIR}/req
+RSPDIR=${TESTDIR}/resp
+
+#
+# several of the ECDSA tests do not use known answer tests to verify the result.
+# In those cases, feed generated tests back into the fipstest tool and
+# see if we can verify those value. NOTE: PQGVer and SigVer tests verify
+# the dsa pqgver and dsa sigver functions, so we know they can detect errors
+# in those PQGGen and SigGen. Only the KeyPair verify is potentially circular.
+#
+if [ ${COMMAND} = "verify" ]; then
+# verify generated keys
+ name=KeyPair
+ echo ">>>>> $name"
+ fipstest ecdsa keyver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+ sh ./validate1.sh ${TESTDIR} PKV.req ' ' '-e /^X.=/d -e /^Result.=.F/s;.(.*);; -e /^Result.=.P/s;.(.*);;'
+# verify signatures
+ name=SigGen
+ echo ">>>>> $name"
+ fipstest ecdsa sigver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+# verify SigVer with known answer
+ sh ./validate1.sh ${TESTDIR} SigVer.req ' ' '-e /^X.=/d -e /^Result.=.F/s;.(.*);; -e /^Result.=.P/s;.(.*);;'
+ exit 0
+fi
+
+request=KeyPair.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest ecdsa keypair ${REQDIR}/$request > ${RSPDIR}/$response
+
+request=PKV.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest ecdsa pkv ${REQDIR}/$request > ${RSPDIR}/$response
+
+request=SigGen.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest ecdsa siggen ${REQDIR}/$request > ${RSPDIR}/$response
+
+request=SigVer.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest ecdsa sigver ${REQDIR}/$request > ${RSPDIR}/$response
diff --git a/security/nss/cmd/fipstest/fipstest.c b/security/nss/cmd/fipstest/fipstest.c
new file mode 100644
index 000000000..ab73e42a5
--- /dev/null
+++ b/security/nss/cmd/fipstest/fipstest.c
@@ -0,0 +1,6137 @@
+/* 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/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "secitem.h"
+#include "blapi.h"
+#include "nssutil.h"
+#include "secerr.h"
+#include "secder.h"
+#include "secdig.h"
+#include "secoid.h"
+#include "ec.h"
+#include "hasht.h"
+#include "lowkeyi.h"
+#include "softoken.h"
+#include "pkcs11t.h"
+#define __PASTE(x, y) x##y
+#undef CK_PKCS11_FUNCTION_INFO
+#undef CK_NEED_ARG_LIST
+#define CK_EXTERN extern
+#define CK_PKCS11_FUNCTION_INFO(func) \
+ CK_RV __PASTE(NS, func)
+#define CK_NEED_ARG_LIST 1
+#include "pkcs11f.h"
+#undef CK_PKCS11_FUNCTION_INFO
+#undef CK_NEED_ARG_LIST
+#undef __PASTE
+#define SSL3_RANDOM_LENGTH 32
+
+#if 0
+#include "../../lib/freebl/mpi/mpi.h"
+#endif
+
+#ifndef NSS_DISABLE_ECC
+extern SECStatus
+EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
+extern SECStatus
+EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
+ const ECParams *srcParams);
+#endif
+
+#define ENCRYPT 1
+#define DECRYPT 0
+#define BYTE unsigned char
+#define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001
+#define RSA_MAX_TEST_MODULUS_BITS 4096
+#define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS / 8
+#define RSA_MAX_TEST_EXPONENT_BYTES 8
+#define PQG_TEST_SEED_BYTES 20
+
+SECStatus
+hex_to_byteval(const char *c2, unsigned char *byteval)
+{
+ int i;
+ unsigned char offset;
+ *byteval = 0;
+ for (i = 0; i < 2; i++) {
+ if (c2[i] >= '0' && c2[i] <= '9') {
+ offset = c2[i] - '0';
+ *byteval |= offset << 4 * (1 - i);
+ } else if (c2[i] >= 'a' && c2[i] <= 'f') {
+ offset = c2[i] - 'a';
+ *byteval |= (offset + 10) << 4 * (1 - i);
+ } else if (c2[i] >= 'A' && c2[i] <= 'F') {
+ offset = c2[i] - 'A';
+ *byteval |= (offset + 10) << 4 * (1 - i);
+ } else {
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+}
+
+SECStatus
+byteval_to_hex(unsigned char byteval, char *c2, char a)
+{
+ int i;
+ unsigned char offset;
+ for (i = 0; i < 2; i++) {
+ offset = (byteval >> 4 * (1 - i)) & 0x0f;
+ if (offset < 10) {
+ c2[i] = '0' + offset;
+ } else {
+ c2[i] = a + offset - 10;
+ }
+ }
+ return SECSuccess;
+}
+
+void
+to_hex_str(char *str, const unsigned char *buf, unsigned int len)
+{
+ unsigned int i;
+ for (i = 0; i < len; i++) {
+ byteval_to_hex(buf[i], &str[2 * i], 'a');
+ }
+ str[2 * len] = '\0';
+}
+
+void
+to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len)
+{
+ unsigned int i;
+ for (i = 0; i < len; i++) {
+ byteval_to_hex(buf[i], &str[2 * i], 'A');
+ }
+ str[2 * len] = '\0';
+}
+
+/*
+ * Convert a string of hex digits (str) to an array (buf) of len bytes.
+ * Return PR_TRUE if the hex string can fit in the byte array. Return
+ * PR_FALSE if the hex string is empty or is too long.
+ */
+PRBool
+from_hex_str(unsigned char *buf, unsigned int len, const char *str)
+{
+ unsigned int nxdigit; /* number of hex digits in str */
+ unsigned int i; /* index into buf */
+ unsigned int j; /* index into str */
+
+ /* count the hex digits */
+ nxdigit = 0;
+ for (nxdigit = 0; isxdigit(str[nxdigit]); nxdigit++) {
+ /* empty body */
+ }
+ if (nxdigit == 0) {
+ return PR_FALSE;
+ }
+ if (nxdigit > 2 * len) {
+ /*
+ * The input hex string is too long, but we allow it if the
+ * extra digits are leading 0's.
+ */
+ for (j = 0; j < nxdigit - 2 * len; j++) {
+ if (str[j] != '0') {
+ return PR_FALSE;
+ }
+ }
+ /* skip leading 0's */
+ str += nxdigit - 2 * len;
+ nxdigit = 2 * len;
+ }
+ for (i = 0, j = 0; i < len; i++) {
+ if (2 * i < 2 * len - nxdigit) {
+ /* Handle a short input as if we padded it with leading 0's. */
+ if (2 * i + 1 < 2 * len - nxdigit) {
+ buf[i] = 0;
+ } else {
+ char tmp[2];
+ tmp[0] = '0';
+ tmp[1] = str[j];
+ hex_to_byteval(tmp, &buf[i]);
+ j++;
+ }
+ } else {
+ hex_to_byteval(&str[j], &buf[i]);
+ j += 2;
+ }
+ }
+ return PR_TRUE;
+}
+
+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)
+{
+ SECStatus rv = SECFailure;
+ DESContext *cx;
+ unsigned char doublecheck[8 * 20]; /* 1 to 20 blocks */
+ unsigned int doublechecklen = 0;
+
+ cx = DES_CreateContext(key, iv, mode, PR_TRUE);
+ if (cx == NULL) {
+ goto loser;
+ }
+ rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (*outputlen != inputlen) {
+ goto loser;
+ }
+ DES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+
+ /*
+ * Doublecheck our result by decrypting the ciphertext and
+ * compare the output with the input plaintext.
+ */
+ cx = DES_CreateContext(key, iv, mode, PR_FALSE);
+ if (cx == NULL) {
+ goto loser;
+ }
+ rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
+ output, *outputlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (doublechecklen != *outputlen) {
+ goto loser;
+ }
+ DES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+ if (memcmp(doublecheck, input, inputlen) != 0) {
+ goto loser;
+ }
+ rv = SECSuccess;
+
+loser:
+ if (cx != NULL) {
+ DES_DestroyContext(cx, PR_TRUE);
+ }
+ return rv;
+}
+
+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)
+{
+ SECStatus rv = SECFailure;
+ DESContext *cx;
+ unsigned char doublecheck[8 * 20]; /* 1 to 20 blocks */
+ unsigned int doublechecklen = 0;
+
+ cx = DES_CreateContext(key, iv, mode, PR_FALSE);
+ if (cx == NULL) {
+ goto loser;
+ }
+ rv = DES_Decrypt(cx, output, outputlen, maxoutputlen,
+ input, inputlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (*outputlen != inputlen) {
+ goto loser;
+ }
+ DES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+
+ /*
+ * Doublecheck our result by encrypting the plaintext and
+ * compare the output with the input ciphertext.
+ */
+ cx = DES_CreateContext(key, iv, mode, PR_TRUE);
+ if (cx == NULL) {
+ goto loser;
+ }
+ rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
+ output, *outputlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (doublechecklen != *outputlen) {
+ goto loser;
+ }
+ DES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+ if (memcmp(doublecheck, input, inputlen) != 0) {
+ goto loser;
+ }
+ rv = SECSuccess;
+
+loser:
+ if (cx != NULL) {
+ DES_DestroyContext(cx, PR_TRUE);
+ }
+ return rv;
+}
+
+/*
+ * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
+ * Test (MMT) in ECB or CBC mode. The KAT (there are five types)
+ * and MMT have the same structure: given the key and IV (CBC mode
+ * only), encrypt the given plaintext or decrypt the given ciphertext.
+ * So we can handle them the same way.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+tdea_kat_mmt(char *reqfn)
+{
+ char buf[180]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "CIPHERTEXT = <180 hex digits>\n".
+ */
+ FILE *req; /* input stream from the REQUEST file */
+ FILE *resp; /* output stream to the RESPONSE file */
+ int i, j;
+ int mode = NSS_DES_EDE3; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
+ int crypt = DECRYPT; /* 1 means encrypt, 0 means decrypt */
+ unsigned char key[24]; /* TDEA 3 key bundle */
+ unsigned int numKeys = 0;
+ unsigned char iv[8]; /* for all modes except ECB */
+ unsigned char plaintext[8 * 20]; /* 1 to 20 blocks */
+ unsigned int plaintextlen;
+ unsigned char ciphertext[8 * 20]; /* 1 to 20 blocks */
+ unsigned int ciphertextlen;
+ SECStatus rv;
+
+ req = fopen(reqfn, "r");
+ resp = stdout;
+ while (fgets(buf, sizeof buf, req) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, resp);
+ continue;
+ }
+ /* [ENCRYPT] or [DECRYPT] */
+ if (buf[0] == '[') {
+ if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
+ crypt = ENCRYPT;
+ } else {
+ crypt = DECRYPT;
+ }
+ fputs(buf, resp);
+ continue;
+ }
+ /* NumKeys */
+ if (strncmp(&buf[0], "NumKeys", 7) == 0) {
+ i = 7;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ numKeys = buf[i];
+ fputs(buf, resp);
+ continue;
+ }
+ /* "COUNT = x" begins a new data set */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ /* mode defaults to ECB, if dataset has IV mode will be set CBC */
+ mode = NSS_DES_EDE3;
+ /* zeroize the variables for the test with this data set */
+ memset(key, 0, sizeof key);
+ memset(iv, 0, sizeof iv);
+ memset(plaintext, 0, sizeof plaintext);
+ plaintextlen = 0;
+ memset(ciphertext, 0, sizeof ciphertext);
+ ciphertextlen = 0;
+ fputs(buf, resp);
+ continue;
+ }
+ if (numKeys == 0) {
+ if (strncmp(buf, "KEYs", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ key[j + 8] = key[j];
+ key[j + 16] = key[j];
+ }
+ fputs(buf, resp);
+ continue;
+ }
+ } else {
+ /* KEY1 = ... */
+ if (strncmp(buf, "KEY1", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ fputs(buf, resp);
+ continue;
+ }
+ /* KEY2 = ... */
+ if (strncmp(buf, "KEY2", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 8; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ fputs(buf, resp);
+ continue;
+ }
+ /* KEY3 = ... */
+ if (strncmp(buf, "KEY3", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 16; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ fputs(buf, resp);
+ continue;
+ }
+ }
+
+ /* IV = ... */
+ if (strncmp(buf, "IV", 2) == 0) {
+ mode = NSS_DES_EDE3_CBC;
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < sizeof iv; i += 2, j++) {
+ hex_to_byteval(&buf[i], &iv[j]);
+ }
+ fputs(buf, resp);
+ continue;
+ }
+
+ /* PLAINTEXT = ... */
+ if (strncmp(buf, "PLAINTEXT", 9) == 0) {
+ /* sanity check */
+ if (crypt != ENCRYPT) {
+ goto loser;
+ }
+ i = 9;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &plaintext[j]);
+ }
+ plaintextlen = j;
+ rv = tdea_encrypt_buf(mode, key,
+ (mode == NSS_DES_EDE3) ? NULL : iv,
+ ciphertext, &ciphertextlen, sizeof ciphertext,
+ plaintext, plaintextlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ fputs(buf, resp);
+ fputs("CIPHERTEXT = ", resp);
+ to_hex_str(buf, ciphertext, ciphertextlen);
+ fputs(buf, resp);
+ fputc('\n', resp);
+ continue;
+ }
+ /* CIPHERTEXT = ... */
+ if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
+ /* sanity check */
+ if (crypt != DECRYPT) {
+ goto loser;
+ }
+
+ i = 10;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &ciphertext[j]);
+ }
+ ciphertextlen = j;
+
+ rv = tdea_decrypt_buf(mode, key,
+ (mode == NSS_DES_EDE3) ? NULL : iv,
+ plaintext, &plaintextlen, sizeof plaintext,
+ ciphertext, ciphertextlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ fputs(buf, resp);
+ fputs("PLAINTEXT = ", resp);
+ to_hex_str(buf, plaintext, plaintextlen);
+ fputs(buf, resp);
+ fputc('\n', resp);
+ continue;
+ }
+ }
+
+loser:
+ fclose(req);
+}
+
+/*
+* Set the parity bit for the given byte
+*/
+BYTE
+odd_parity(BYTE in)
+{
+ BYTE out = in;
+ in ^= in >> 4;
+ in ^= in >> 2;
+ in ^= in >> 1;
+ return (BYTE)(out ^ !(in & 1));
+}
+
+/*
+ * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j]
+ * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
+ */
+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)
+{
+ int k;
+
+ /* key1[i+1] = key1[i] xor PT/CT[j] */
+ for (k = 0; k < 8; k++) {
+ key[k] ^= text[k];
+ }
+ /* key2 */
+ if (numKeys == 2 || numKeys == 3) {
+ /* key2 independent */
+ for (k = 8; k < 16; k++) {
+ /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
+ key[k] ^= text_1[k - 8];
+ }
+ } else {
+ /* key2 == key 1 */
+ for (k = 8; k < 16; k++) {
+ /* key2[i+1] = KEY2[i] xor PT/CT[j] */
+ key[k] = key[k - 8];
+ }
+ }
+ /* key3 */
+ if (numKeys == 1 || numKeys == 2) {
+ /* key3 == key 1 */
+ for (k = 16; k < 24; k++) {
+ /* key3[i+1] = KEY3[i] xor PT/CT[j] */
+ key[k] = key[k - 16];
+ }
+ } else {
+ /* key3 independent */
+ for (k = 16; k < 24; k++) {
+ /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
+ key[k] ^= text_2[k - 16];
+ }
+ }
+ /* set the parity bits */
+ for (k = 0; k < 24; k++) {
+ key[k] = odd_parity(key[k]);
+ }
+}
+
+/*
+ * Perform the Monte Carlo Test
+ *
+ * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
+ * crypt = ENCRYPT || DECRYPT
+ * inputtext = plaintext or Cyphertext depending on the value of crypt
+ * inputlength is expected to be size 8 bytes
+ * iv = needs to be set for NSS_DES_EDE3_CBC mode
+ * resp = is the output response file.
+ */
+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)
+{
+
+ int i, j;
+ unsigned char outputtext_1[8]; /* PT/CT[j-1] */
+ unsigned char outputtext_2[8]; /* PT/CT[j-2] */
+ char buf[80]; /* holds one line from the input REQUEST file. */
+ unsigned int outputlen;
+ unsigned char outputtext[8];
+
+ SECStatus rv;
+
+ if (mode == NSS_DES_EDE3 && iv != NULL) {
+ printf("IV must be NULL for NSS_DES_EDE3 mode");
+ goto loser;
+ } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) {
+ printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
+ goto loser;
+ }
+
+ /* loop 400 times */
+ for (i = 0; i < 400; i++) {
+ /* if i == 0 CV[0] = IV not necessary */
+ /* record the count and key values and plainText */
+ sprintf(buf, "COUNT = %d\n", i);
+ fputs(buf, resp);
+ /* Output KEY1[i] */
+ fputs("KEY1 = ", resp);
+ to_hex_str(buf, key, 8);
+ fputs(buf, resp);
+ fputc('\n', resp);
+ /* Output KEY2[i] */
+ fputs("KEY2 = ", resp);
+ to_hex_str(buf, &key[8], 8);
+ fputs(buf, resp);
+ fputc('\n', resp);
+ /* Output KEY3[i] */
+ fputs("KEY3 = ", resp);
+ to_hex_str(buf, &key[16], 8);
+ fputs(buf, resp);
+ fputc('\n', resp);
+ if (mode == NSS_DES_EDE3_CBC) {
+ /* Output CV[i] */
+ fputs("IV = ", resp);
+ to_hex_str(buf, iv, 8);
+ fputs(buf, resp);
+ fputc('\n', resp);
+ }
+ if (crypt == ENCRYPT) {
+ /* Output PT[0] */
+ fputs("PLAINTEXT = ", resp);
+ } else {
+ /* Output CT[0] */
+ fputs("CIPHERTEXT = ", resp);
+ }
+
+ to_hex_str(buf, inputtext, inputlength);
+ fputs(buf, resp);
+ fputc('\n', resp);
+
+ /* loop 10,000 times */
+ for (j = 0; j < 10000; j++) {
+
+ outputlen = 0;
+ if (crypt == ENCRYPT) {
+ /* inputtext == ciphertext outputtext == plaintext*/
+ rv = tdea_encrypt_buf(mode, key,
+ (mode ==
+ NSS_DES_EDE3)
+ ? NULL
+ : iv,
+ outputtext, &outputlen, 8,
+ inputtext, 8);
+ } else {
+ /* inputtext == plaintext outputtext == ciphertext */
+ rv = tdea_decrypt_buf(mode, key,
+ (mode ==
+ NSS_DES_EDE3)
+ ? NULL
+ : iv,
+ outputtext, &outputlen, 8,
+ inputtext, 8);
+ }
+
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (outputlen != inputlength) {
+ goto loser;
+ }
+
+ if (mode == NSS_DES_EDE3_CBC) {
+ if (crypt == ENCRYPT) {
+ if (j == 0) {
+ /*P[j+1] = CV[0] */
+ memcpy(inputtext, iv, 8);
+ } else {
+ /* p[j+1] = C[j-1] */
+ memcpy(inputtext, outputtext_1, 8);
+ }
+ /* CV[j+1] = C[j] */
+ memcpy(iv, outputtext, 8);
+ if (j != 9999) {
+ /* save C[j-1] */
+ memcpy(outputtext_1, outputtext, 8);
+ }
+ } else { /* DECRYPT */
+ /* CV[j+1] = C[j] */
+ memcpy(iv, inputtext, 8);
+ /* C[j+1] = P[j] */
+ memcpy(inputtext, outputtext, 8);
+ }
+ } else {
+ /* ECB mode PT/CT[j+1] = CT/PT[j] */
+ memcpy(inputtext, outputtext, 8);
+ }
+
+ /* Save PT/CT[j-2] and PT/CT[j-1] */
+ if (j == 9997)
+ memcpy(outputtext_2, outputtext, 8);
+ if (j == 9998)
+ memcpy(outputtext_1, outputtext, 8);
+ /* done at the end of the for(j) loop */
+ }
+
+ if (crypt == ENCRYPT) {
+ /* Output CT[j] */
+ fputs("CIPHERTEXT = ", resp);
+ } else {
+ /* Output PT[j] */
+ fputs("PLAINTEXT = ", resp);
+ }
+ to_hex_str(buf, outputtext, 8);
+ fputs(buf, resp);
+ fputc('\n', resp);
+
+ /* Key[i+1] = Key[i] xor ... outputtext_2 == PT/CT[j-2]
+ * outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j]
+ */
+ tdea_mct_next_keys(key, outputtext_2,
+ outputtext_1, outputtext, numKeys);
+
+ if (mode == NSS_DES_EDE3_CBC) {
+ /* taken care of in the j=9999 iteration */
+ if (crypt == ENCRYPT) {
+ /* P[i] = C[j-1] */
+ /* CV[i] = C[j] */
+ } else {
+ /* taken care of in the j=9999 iteration */
+ /* CV[i] = C[j] */
+ /* C[i] = P[j] */
+ }
+ } else {
+ /* ECB PT/CT[i] = PT/CT[j] */
+ memcpy(inputtext, outputtext, 8);
+ }
+ /* done at the end of the for(i) loop */
+ fputc('\n', resp);
+ }
+
+loser:
+ return;
+}
+
+/*
+ * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
+ * by gathering the input from the request file, and then
+ * calling tdea_mct_test.
+ *
+ * reqfn is the pathname of the input REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+tdea_mct(int mode, char *reqfn)
+{
+ int i, j;
+ char buf[80]; /* holds one line from the input REQUEST file. */
+ FILE *req; /* input stream from the REQUEST file */
+ FILE *resp; /* output stream to the RESPONSE file */
+ unsigned int crypt = 0; /* 1 means encrypt, 0 means decrypt */
+ unsigned char key[24]; /* TDEA 3 key bundle */
+ unsigned int numKeys = 0;
+ unsigned char plaintext[8]; /* PT[j] */
+ unsigned char ciphertext[8]; /* CT[j] */
+ unsigned char iv[8];
+
+ /* zeroize the variables for the test with this data set */
+ memset(key, 0, sizeof key);
+ memset(plaintext, 0, sizeof plaintext);
+ memset(ciphertext, 0, sizeof ciphertext);
+ memset(iv, 0, sizeof iv);
+
+ req = fopen(reqfn, "r");
+ resp = stdout;
+ while (fgets(buf, sizeof buf, req) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, resp);
+ continue;
+ }
+ /* [ENCRYPT] or [DECRYPT] */
+ if (buf[0] == '[') {
+ if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
+ crypt = ENCRYPT;
+ } else {
+ crypt = DECRYPT;
+ }
+ fputs(buf, resp);
+ continue;
+ }
+ /* NumKeys */
+ if (strncmp(&buf[0], "NumKeys", 7) == 0) {
+ i = 7;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ numKeys = atoi(&buf[i]);
+ continue;
+ }
+ /* KEY1 = ... */
+ if (strncmp(buf, "KEY1", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ continue;
+ }
+ /* KEY2 = ... */
+ if (strncmp(buf, "KEY2", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 8; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ continue;
+ }
+ /* KEY3 = ... */
+ if (strncmp(buf, "KEY3", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 16; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ continue;
+ }
+
+ /* IV = ... */
+ if (strncmp(buf, "IV", 2) == 0) {
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < sizeof iv; i += 2, j++) {
+ hex_to_byteval(&buf[i], &iv[j]);
+ }
+ continue;
+ }
+
+ /* PLAINTEXT = ... */
+ if (strncmp(buf, "PLAINTEXT", 9) == 0) {
+
+ /* sanity check */
+ if (crypt != ENCRYPT) {
+ goto loser;
+ }
+ /* PT[0] = PT */
+ i = 9;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < sizeof plaintext; i += 2, j++) {
+ hex_to_byteval(&buf[i], &plaintext[j]);
+ }
+
+ /* do the Monte Carlo test */
+ if (mode == NSS_DES_EDE3) {
+ tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp);
+ } else {
+ tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp);
+ }
+ continue;
+ }
+ /* CIPHERTEXT = ... */
+ if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
+ /* sanity check */
+ if (crypt != DECRYPT) {
+ goto loser;
+ }
+ /* CT[0] = CT */
+ i = 10;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &ciphertext[j]);
+ }
+
+ /* do the Monte Carlo test */
+ if (mode == NSS_DES_EDE3) {
+ tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp);
+ } else {
+ tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp);
+ }
+ continue;
+ }
+ }
+
+loser:
+ fclose(req);
+}
+
+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)
+{
+ SECStatus rv = SECFailure;
+ AESContext *cx;
+ unsigned char doublecheck[10 * 16]; /* 1 to 10 blocks */
+ unsigned int doublechecklen = 0;
+
+ cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
+ if (cx == NULL) {
+ goto loser;
+ }
+ rv = AES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (*outputlen != inputlen) {
+ goto loser;
+ }
+ AES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+
+ /*
+ * Doublecheck our result by decrypting the ciphertext and
+ * compare the output with the input plaintext.
+ */
+ cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
+ if (cx == NULL) {
+ goto loser;
+ }
+ rv = AES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
+ output, *outputlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (doublechecklen != *outputlen) {
+ goto loser;
+ }
+ AES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+ if (memcmp(doublecheck, input, inputlen) != 0) {
+ goto loser;
+ }
+ rv = SECSuccess;
+
+loser:
+ if (cx != NULL) {
+ AES_DestroyContext(cx, PR_TRUE);
+ }
+ return rv;
+}
+
+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)
+{
+ SECStatus rv = SECFailure;
+ AESContext *cx;
+ unsigned char doublecheck[10 * 16]; /* 1 to 10 blocks */
+ unsigned int doublechecklen = 0;
+
+ cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
+ if (cx == NULL) {
+ goto loser;
+ }
+ rv = AES_Decrypt(cx, output, outputlen, maxoutputlen,
+ input, inputlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (*outputlen != inputlen) {
+ goto loser;
+ }
+ AES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+
+ /*
+ * Doublecheck our result by encrypting the plaintext and
+ * compare the output with the input ciphertext.
+ */
+ cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
+ if (cx == NULL) {
+ goto loser;
+ }
+ rv = AES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
+ output, *outputlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (doublechecklen != *outputlen) {
+ goto loser;
+ }
+ AES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+ if (memcmp(doublecheck, input, inputlen) != 0) {
+ goto loser;
+ }
+ rv = SECSuccess;
+
+loser:
+ if (cx != NULL) {
+ AES_DestroyContext(cx, PR_TRUE);
+ }
+ return rv;
+}
+/*
+ * Perform the AES GCM tests.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+aes_gcm(char *reqfn, int encrypt)
+{
+ char buf[512]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "CIPHERTEXT = <320 hex digits>\n".
+ */
+ FILE *aesreq; /* input stream from the REQUEST file */
+ FILE *aesresp; /* output stream to the RESPONSE file */
+ int i, j;
+ unsigned char key[32]; /* 128, 192, or 256 bits */
+ unsigned int keysize = 0;
+ unsigned char iv[128]; /* handle large gcm IV's */
+ unsigned char plaintext[10 * 16]; /* 1 to 10 blocks */
+ unsigned int plaintextlen;
+ unsigned char ciphertext[11 * 16]; /* 1 to 10 blocks + tag */
+ unsigned int ciphertextlen;
+ unsigned char aad[11 * 16]; /* 1 to 10 blocks + tag */
+ unsigned int aadlen = 0;
+ unsigned int tagbits;
+ unsigned int taglen = 0;
+ unsigned int ivlen;
+ CK_GCM_PARAMS params;
+ SECStatus rv;
+
+ aesreq = fopen(reqfn, "r");
+ aesresp = stdout;
+ while (fgets(buf, sizeof buf, aesreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* [ENCRYPT] or [DECRYPT] */
+ if (buf[0] == '[') {
+ if (strncmp(buf, "[Taglen", 7) == 0) {
+ if (sscanf(buf, "[Taglen = %d]", &tagbits) != 1) {
+ goto loser;
+ }
+ taglen = tagbits / 8;
+ }
+ if (strncmp(buf, "[IVlen", 6) == 0) {
+ if (sscanf(buf, "[IVlen = %d]", &ivlen) != 1) {
+ goto loser;
+ }
+ ivlen = ivlen / 8;
+ }
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* "COUNT = x" begins a new data set */
+ if (strncmp(buf, "Count", 5) == 0) {
+ /* zeroize the variables for the test with this data set */
+ memset(key, 0, sizeof key);
+ keysize = 0;
+ memset(iv, 0, sizeof iv);
+ memset(plaintext, 0, sizeof plaintext);
+ plaintextlen = 0;
+ memset(ciphertext, 0, sizeof ciphertext);
+ ciphertextlen = 0;
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* KEY = ... */
+ if (strncmp(buf, "Key", 3) == 0) {
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ keysize = j;
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* IV = ... */
+ if (strncmp(buf, "IV", 2) == 0) {
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < sizeof iv; i += 2, j++) {
+ hex_to_byteval(&buf[i], &iv[j]);
+ }
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* PLAINTEXT = ... */
+ if (strncmp(buf, "PT", 2) == 0) {
+ /* sanity check */
+ if (!encrypt) {
+ goto loser;
+ }
+
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &plaintext[j]);
+ }
+ plaintextlen = j;
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* CIPHERTEXT = ... */
+ if (strncmp(buf, "CT", 2) == 0) {
+ /* sanity check */
+ if (encrypt) {
+ goto loser;
+ }
+
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &ciphertext[j]);
+ }
+ ciphertextlen = j;
+ fputs(buf, aesresp);
+ continue;
+ }
+ if (strncmp(buf, "AAD", 3) == 0) {
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &aad[j]);
+ }
+ aadlen = j;
+ fputs(buf, aesresp);
+ if (encrypt) {
+ if (encrypt == 2) {
+ rv = RNG_GenerateGlobalRandomBytes(iv, ivlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+ params.pIv = iv;
+ params.ulIvLen = ivlen;
+ params.pAAD = aad;
+ params.ulAADLen = aadlen;
+ params.ulTagBits = tagbits;
+ rv = aes_encrypt_buf(NSS_AES_GCM, key, keysize,
+ (unsigned char *)&params,
+ ciphertext, &ciphertextlen, sizeof ciphertext,
+ plaintext, plaintextlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ if (encrypt == 2) {
+ fputs("IV = ", aesresp);
+ to_hex_str(buf, iv, ivlen);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+ }
+ fputs("CT = ", aesresp);
+ j = ciphertextlen - taglen;
+ to_hex_str(buf, ciphertext, j);
+ fputs(buf, aesresp);
+ fputs("\nTag = ", aesresp);
+ to_hex_str(buf, ciphertext + j, taglen);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+ }
+ continue;
+ }
+ if (strncmp(buf, "Tag", 3) == 0) {
+ /* sanity check */
+ if (encrypt) {
+ goto loser;
+ }
+
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &ciphertext[j + ciphertextlen]);
+ }
+ ciphertextlen += j;
+ params.pIv = iv;
+ params.ulIvLen = ivlen;
+ params.pAAD = aad;
+ params.ulAADLen = aadlen;
+ params.ulTagBits = tagbits;
+ rv = aes_decrypt_buf(NSS_AES_GCM, key, keysize,
+ (unsigned char *)&params,
+ plaintext, &plaintextlen, sizeof plaintext,
+ ciphertext, ciphertextlen);
+ fputs(buf, aesresp);
+ if (rv != SECSuccess) {
+ fprintf(aesresp, "FAIL\n");
+ } else {
+ fputs("PT = ", aesresp);
+ to_hex_str(buf, plaintext, plaintextlen);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+ }
+ continue;
+ }
+ }
+loser:
+ fclose(aesreq);
+}
+
+/*
+ * Perform the AES Known Answer Test (KAT) or Multi-block Message
+ * Test (MMT) in ECB or CBC mode. The KAT (there are four types)
+ * and MMT have the same structure: given the key and IV (CBC mode
+ * only), encrypt the given plaintext or decrypt the given ciphertext.
+ * So we can handle them the same way.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+aes_kat_mmt(char *reqfn)
+{
+ char buf[512]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "CIPHERTEXT = <320 hex digits>\n".
+ */
+ FILE *aesreq; /* input stream from the REQUEST file */
+ FILE *aesresp; /* output stream to the RESPONSE file */
+ int i, j;
+ int mode = NSS_AES; /* NSS_AES (ECB) or NSS_AES_CBC */
+ int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
+ unsigned char key[32]; /* 128, 192, or 256 bits */
+ unsigned int keysize = 0;
+ unsigned char iv[16]; /* for all modes except ECB */
+ unsigned char plaintext[10 * 16]; /* 1 to 10 blocks */
+ unsigned int plaintextlen;
+ unsigned char ciphertext[10 * 16]; /* 1 to 10 blocks */
+ unsigned int ciphertextlen;
+ SECStatus rv;
+
+ aesreq = fopen(reqfn, "r");
+ aesresp = stdout;
+ while (fgets(buf, sizeof buf, aesreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* [ENCRYPT] or [DECRYPT] */
+ if (buf[0] == '[') {
+ if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
+ encrypt = 1;
+ } else {
+ encrypt = 0;
+ }
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* "COUNT = x" begins a new data set */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ mode = NSS_AES;
+ /* zeroize the variables for the test with this data set */
+ memset(key, 0, sizeof key);
+ keysize = 0;
+ memset(iv, 0, sizeof iv);
+ memset(plaintext, 0, sizeof plaintext);
+ plaintextlen = 0;
+ memset(ciphertext, 0, sizeof ciphertext);
+ ciphertextlen = 0;
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* KEY = ... */
+ if (strncmp(buf, "KEY", 3) == 0) {
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ keysize = j;
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* IV = ... */
+ if (strncmp(buf, "IV", 2) == 0) {
+ mode = NSS_AES_CBC;
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < sizeof iv; i += 2, j++) {
+ hex_to_byteval(&buf[i], &iv[j]);
+ }
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* PLAINTEXT = ... */
+ if (strncmp(buf, "PLAINTEXT", 9) == 0) {
+ /* sanity check */
+ if (!encrypt) {
+ goto loser;
+ }
+
+ i = 9;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &plaintext[j]);
+ }
+ plaintextlen = j;
+
+ rv = aes_encrypt_buf(mode, key, keysize,
+ (mode ==
+ NSS_AES)
+ ? NULL
+ : iv,
+ ciphertext, &ciphertextlen, sizeof ciphertext,
+ plaintext, plaintextlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ fputs(buf, aesresp);
+ fputs("CIPHERTEXT = ", aesresp);
+ to_hex_str(buf, ciphertext, ciphertextlen);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+ continue;
+ }
+ /* CIPHERTEXT = ... */
+ if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
+ /* sanity check */
+ if (encrypt) {
+ goto loser;
+ }
+
+ i = 10;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &ciphertext[j]);
+ }
+ ciphertextlen = j;
+
+ rv = aes_decrypt_buf(mode, key, keysize,
+ (mode ==
+ NSS_AES)
+ ? NULL
+ : iv,
+ plaintext, &plaintextlen, sizeof plaintext,
+ ciphertext, ciphertextlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ fputs(buf, aesresp);
+ fputs("PLAINTEXT = ", aesresp);
+ to_hex_str(buf, plaintext, plaintextlen);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+ continue;
+ }
+ }
+loser:
+ fclose(aesreq);
+}
+
+/*
+ * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
+ * Test (MCT) in ECB and CBC modes.
+ */
+void
+aes_mct_next_key(unsigned char *key, unsigned int keysize,
+ const unsigned char *ciphertext_1, const unsigned char *ciphertext)
+{
+ int k;
+
+ switch (keysize) {
+ case 16: /* 128-bit key */
+ /* Key[i+1] = Key[i] xor CT[j] */
+ for (k = 0; k < 16; k++) {
+ key[k] ^= ciphertext[k];
+ }
+ break;
+ case 24: /* 192-bit key */
+ /*
+ * Key[i+1] = Key[i] xor (last 64-bits of
+ * CT[j-1] || CT[j])
+ */
+ for (k = 0; k < 8; k++) {
+ key[k] ^= ciphertext_1[k + 8];
+ }
+ for (k = 8; k < 24; k++) {
+ key[k] ^= ciphertext[k - 8];
+ }
+ break;
+ case 32: /* 256-bit key */
+ /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
+ for (k = 0; k < 16; k++) {
+ key[k] ^= ciphertext_1[k];
+ }
+ for (k = 16; k < 32; k++) {
+ key[k] ^= ciphertext[k - 16];
+ }
+ break;
+ }
+}
+
+/*
+ * Perform the AES Monte Carlo Test (MCT) in ECB mode. MCT exercises
+ * our AES code in streaming mode because the plaintext or ciphertext
+ * is generated block by block as we go, so we can't collect all the
+ * plaintext or ciphertext in one buffer and encrypt or decrypt it in
+ * one shot.
+ *
+ * reqfn is the pathname of the input REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+aes_ecb_mct(char *reqfn)
+{
+ char buf[80]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "KEY = <64 hex digits>\n".
+ */
+ FILE *aesreq; /* input stream from the REQUEST file */
+ FILE *aesresp; /* output stream to the RESPONSE file */
+ int i, j;
+ int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
+ unsigned char key[32]; /* 128, 192, or 256 bits */
+ unsigned int keysize = 0;
+ unsigned char plaintext[16]; /* PT[j] */
+ unsigned char plaintext_1[16]; /* PT[j-1] */
+ unsigned char ciphertext[16]; /* CT[j] */
+ unsigned char ciphertext_1[16]; /* CT[j-1] */
+ unsigned char doublecheck[16];
+ unsigned int outputlen;
+ AESContext *cx = NULL; /* the operation being tested */
+ AESContext *cx2 = NULL; /* the inverse operation done in parallel
+ * to doublecheck our result.
+ */
+ SECStatus rv;
+
+ aesreq = fopen(reqfn, "r");
+ aesresp = stdout;
+ while (fgets(buf, sizeof buf, aesreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* [ENCRYPT] or [DECRYPT] */
+ if (buf[0] == '[') {
+ if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
+ encrypt = 1;
+ } else {
+ encrypt = 0;
+ }
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* "COUNT = x" begins a new data set */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ /* zeroize the variables for the test with this data set */
+ memset(key, 0, sizeof key);
+ keysize = 0;
+ memset(plaintext, 0, sizeof plaintext);
+ memset(ciphertext, 0, sizeof ciphertext);
+ continue;
+ }
+ /* KEY = ... */
+ if (strncmp(buf, "KEY", 3) == 0) {
+ /* Key[0] = Key */
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ keysize = j;
+ continue;
+ }
+ /* PLAINTEXT = ... */
+ if (strncmp(buf, "PLAINTEXT", 9) == 0) {
+ /* sanity check */
+ if (!encrypt) {
+ goto loser;
+ }
+ /* PT[0] = PT */
+ i = 9;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < sizeof plaintext; i += 2, j++) {
+ hex_to_byteval(&buf[i], &plaintext[j]);
+ }
+
+ for (i = 0; i < 100; i++) {
+ sprintf(buf, "COUNT = %d\n", i);
+ fputs(buf, aesresp);
+ /* Output Key[i] */
+ fputs("KEY = ", aesresp);
+ to_hex_str(buf, key, keysize);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+ /* Output PT[0] */
+ fputs("PLAINTEXT = ", aesresp);
+ to_hex_str(buf, plaintext, sizeof plaintext);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+
+ cx = AES_CreateContext(key, NULL, NSS_AES,
+ PR_TRUE, keysize, 16);
+ if (cx == NULL) {
+ goto loser;
+ }
+ /*
+ * doublecheck our result by decrypting the result
+ * and comparing the output with the plaintext.
+ */
+ cx2 = AES_CreateContext(key, NULL, NSS_AES,
+ PR_FALSE, keysize, 16);
+ if (cx2 == NULL) {
+ goto loser;
+ }
+ for (j = 0; j < 1000; j++) {
+ /* Save CT[j-1] */
+ memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
+
+ /* CT[j] = AES(Key[i], PT[j]) */
+ outputlen = 0;
+ rv = AES_Encrypt(cx,
+ ciphertext, &outputlen, sizeof ciphertext,
+ plaintext, sizeof plaintext);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (outputlen != sizeof plaintext) {
+ goto loser;
+ }
+
+ /* doublecheck our result */
+ outputlen = 0;
+ rv = AES_Decrypt(cx2,
+ doublecheck, &outputlen, sizeof doublecheck,
+ ciphertext, sizeof ciphertext);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (outputlen != sizeof ciphertext) {
+ goto loser;
+ }
+ if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
+ goto loser;
+ }
+
+ /* PT[j+1] = CT[j] */
+ memcpy(plaintext, ciphertext, sizeof plaintext);
+ }
+ AES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+ AES_DestroyContext(cx2, PR_TRUE);
+ cx2 = NULL;
+
+ /* Output CT[j] */
+ fputs("CIPHERTEXT = ", aesresp);
+ to_hex_str(buf, ciphertext, sizeof ciphertext);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+
+ /* Key[i+1] = Key[i] xor ... */
+ aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
+ /* PT[0] = CT[j] */
+ /* done at the end of the for(j) loop */
+
+ fputc('\n', aesresp);
+ }
+
+ continue;
+ }
+ /* CIPHERTEXT = ... */
+ if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
+ /* sanity check */
+ if (encrypt) {
+ goto loser;
+ }
+ /* CT[0] = CT */
+ i = 10;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &ciphertext[j]);
+ }
+
+ for (i = 0; i < 100; i++) {
+ sprintf(buf, "COUNT = %d\n", i);
+ fputs(buf, aesresp);
+ /* Output Key[i] */
+ fputs("KEY = ", aesresp);
+ to_hex_str(buf, key, keysize);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+ /* Output CT[0] */
+ fputs("CIPHERTEXT = ", aesresp);
+ to_hex_str(buf, ciphertext, sizeof ciphertext);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+
+ cx = AES_CreateContext(key, NULL, NSS_AES,
+ PR_FALSE, keysize, 16);
+ if (cx == NULL) {
+ goto loser;
+ }
+ /*
+ * doublecheck our result by encrypting the result
+ * and comparing the output with the ciphertext.
+ */
+ cx2 = AES_CreateContext(key, NULL, NSS_AES,
+ PR_TRUE, keysize, 16);
+ if (cx2 == NULL) {
+ goto loser;
+ }
+ for (j = 0; j < 1000; j++) {
+ /* Save PT[j-1] */
+ memcpy(plaintext_1, plaintext, sizeof plaintext);
+
+ /* PT[j] = AES(Key[i], CT[j]) */
+ outputlen = 0;
+ rv = AES_Decrypt(cx,
+ plaintext, &outputlen, sizeof plaintext,
+ ciphertext, sizeof ciphertext);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (outputlen != sizeof ciphertext) {
+ goto loser;
+ }
+
+ /* doublecheck our result */
+ outputlen = 0;
+ rv = AES_Encrypt(cx2,
+ doublecheck, &outputlen, sizeof doublecheck,
+ plaintext, sizeof plaintext);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (outputlen != sizeof plaintext) {
+ goto loser;
+ }
+ if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
+ goto loser;
+ }
+
+ /* CT[j+1] = PT[j] */
+ memcpy(ciphertext, plaintext, sizeof ciphertext);
+ }
+ AES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+ AES_DestroyContext(cx2, PR_TRUE);
+ cx2 = NULL;
+
+ /* Output PT[j] */
+ fputs("PLAINTEXT = ", aesresp);
+ to_hex_str(buf, plaintext, sizeof plaintext);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+
+ /* Key[i+1] = Key[i] xor ... */
+ aes_mct_next_key(key, keysize, plaintext_1, plaintext);
+ /* CT[0] = PT[j] */
+ /* done at the end of the for(j) loop */
+
+ fputc('\n', aesresp);
+ }
+
+ continue;
+ }
+ }
+loser:
+ if (cx != NULL) {
+ AES_DestroyContext(cx, PR_TRUE);
+ }
+ if (cx2 != NULL) {
+ AES_DestroyContext(cx2, PR_TRUE);
+ }
+ fclose(aesreq);
+}
+
+/*
+ * Perform the AES Monte Carlo Test (MCT) in CBC mode. MCT exercises
+ * our AES code in streaming mode because the plaintext or ciphertext
+ * is generated block by block as we go, so we can't collect all the
+ * plaintext or ciphertext in one buffer and encrypt or decrypt it in
+ * one shot.
+ *
+ * reqfn is the pathname of the input REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+aes_cbc_mct(char *reqfn)
+{
+ char buf[80]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "KEY = <64 hex digits>\n".
+ */
+ FILE *aesreq; /* input stream from the REQUEST file */
+ FILE *aesresp; /* output stream to the RESPONSE file */
+ int i, j;
+ int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
+ unsigned char key[32]; /* 128, 192, or 256 bits */
+ unsigned int keysize = 0;
+ unsigned char iv[16];
+ unsigned char plaintext[16]; /* PT[j] */
+ unsigned char plaintext_1[16]; /* PT[j-1] */
+ unsigned char ciphertext[16]; /* CT[j] */
+ unsigned char ciphertext_1[16]; /* CT[j-1] */
+ unsigned char doublecheck[16];
+ unsigned int outputlen;
+ AESContext *cx = NULL; /* the operation being tested */
+ AESContext *cx2 = NULL; /* the inverse operation done in parallel
+ * to doublecheck our result.
+ */
+ SECStatus rv;
+
+ aesreq = fopen(reqfn, "r");
+ aesresp = stdout;
+ while (fgets(buf, sizeof buf, aesreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* [ENCRYPT] or [DECRYPT] */
+ if (buf[0] == '[') {
+ if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
+ encrypt = 1;
+ } else {
+ encrypt = 0;
+ }
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* "COUNT = x" begins a new data set */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ /* zeroize the variables for the test with this data set */
+ memset(key, 0, sizeof key);
+ keysize = 0;
+ memset(iv, 0, sizeof iv);
+ memset(plaintext, 0, sizeof plaintext);
+ memset(ciphertext, 0, sizeof ciphertext);
+ continue;
+ }
+ /* KEY = ... */
+ if (strncmp(buf, "KEY", 3) == 0) {
+ /* Key[0] = Key */
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ keysize = j;
+ continue;
+ }
+ /* IV = ... */
+ if (strncmp(buf, "IV", 2) == 0) {
+ /* IV[0] = IV */
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < sizeof iv; i += 2, j++) {
+ hex_to_byteval(&buf[i], &iv[j]);
+ }
+ continue;
+ }
+ /* PLAINTEXT = ... */
+ if (strncmp(buf, "PLAINTEXT", 9) == 0) {
+ /* sanity check */
+ if (!encrypt) {
+ goto loser;
+ }
+ /* PT[0] = PT */
+ i = 9;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < sizeof plaintext; i += 2, j++) {
+ hex_to_byteval(&buf[i], &plaintext[j]);
+ }
+
+ for (i = 0; i < 100; i++) {
+ sprintf(buf, "COUNT = %d\n", i);
+ fputs(buf, aesresp);
+ /* Output Key[i] */
+ fputs("KEY = ", aesresp);
+ to_hex_str(buf, key, keysize);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+ /* Output IV[i] */
+ fputs("IV = ", aesresp);
+ to_hex_str(buf, iv, sizeof iv);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+ /* Output PT[0] */
+ fputs("PLAINTEXT = ", aesresp);
+ to_hex_str(buf, plaintext, sizeof plaintext);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+
+ cx = AES_CreateContext(key, iv, NSS_AES_CBC,
+ PR_TRUE, keysize, 16);
+ if (cx == NULL) {
+ goto loser;
+ }
+ /*
+ * doublecheck our result by decrypting the result
+ * and comparing the output with the plaintext.
+ */
+ cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
+ PR_FALSE, keysize, 16);
+ if (cx2 == NULL) {
+ goto loser;
+ }
+ /* CT[-1] = IV[i] */
+ memcpy(ciphertext, iv, sizeof ciphertext);
+ for (j = 0; j < 1000; j++) {
+ /* Save CT[j-1] */
+ memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
+ /*
+ * If ( j=0 )
+ * CT[j] = AES(Key[i], IV[i], PT[j])
+ * PT[j+1] = IV[i] (= CT[j-1])
+ * Else
+ * CT[j] = AES(Key[i], PT[j])
+ * PT[j+1] = CT[j-1]
+ */
+ outputlen = 0;
+ rv = AES_Encrypt(cx,
+ ciphertext, &outputlen, sizeof ciphertext,
+ plaintext, sizeof plaintext);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (outputlen != sizeof plaintext) {
+ goto loser;
+ }
+
+ /* doublecheck our result */
+ outputlen = 0;
+ rv = AES_Decrypt(cx2,
+ doublecheck, &outputlen, sizeof doublecheck,
+ ciphertext, sizeof ciphertext);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (outputlen != sizeof ciphertext) {
+ goto loser;
+ }
+ if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
+ goto loser;
+ }
+
+ memcpy(plaintext, ciphertext_1, sizeof plaintext);
+ }
+ AES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+ AES_DestroyContext(cx2, PR_TRUE);
+ cx2 = NULL;
+
+ /* Output CT[j] */
+ fputs("CIPHERTEXT = ", aesresp);
+ to_hex_str(buf, ciphertext, sizeof ciphertext);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+
+ /* Key[i+1] = Key[i] xor ... */
+ aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
+ /* IV[i+1] = CT[j] */
+ memcpy(iv, ciphertext, sizeof iv);
+ /* PT[0] = CT[j-1] */
+ /* done at the end of the for(j) loop */
+
+ fputc('\n', aesresp);
+ }
+
+ continue;
+ }
+ /* CIPHERTEXT = ... */
+ if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
+ /* sanity check */
+ if (encrypt) {
+ goto loser;
+ }
+ /* CT[0] = CT */
+ i = 10;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &ciphertext[j]);
+ }
+
+ for (i = 0; i < 100; i++) {
+ sprintf(buf, "COUNT = %d\n", i);
+ fputs(buf, aesresp);
+ /* Output Key[i] */
+ fputs("KEY = ", aesresp);
+ to_hex_str(buf, key, keysize);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+ /* Output IV[i] */
+ fputs("IV = ", aesresp);
+ to_hex_str(buf, iv, sizeof iv);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+ /* Output CT[0] */
+ fputs("CIPHERTEXT = ", aesresp);
+ to_hex_str(buf, ciphertext, sizeof ciphertext);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+
+ cx = AES_CreateContext(key, iv, NSS_AES_CBC,
+ PR_FALSE, keysize, 16);
+ if (cx == NULL) {
+ goto loser;
+ }
+ /*
+ * doublecheck our result by encrypting the result
+ * and comparing the output with the ciphertext.
+ */
+ cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
+ PR_TRUE, keysize, 16);
+ if (cx2 == NULL) {
+ goto loser;
+ }
+ /* PT[-1] = IV[i] */
+ memcpy(plaintext, iv, sizeof plaintext);
+ for (j = 0; j < 1000; j++) {
+ /* Save PT[j-1] */
+ memcpy(plaintext_1, plaintext, sizeof plaintext);
+ /*
+ * If ( j=0 )
+ * PT[j] = AES(Key[i], IV[i], CT[j])
+ * CT[j+1] = IV[i] (= PT[j-1])
+ * Else
+ * PT[j] = AES(Key[i], CT[j])
+ * CT[j+1] = PT[j-1]
+ */
+ outputlen = 0;
+ rv = AES_Decrypt(cx,
+ plaintext, &outputlen, sizeof plaintext,
+ ciphertext, sizeof ciphertext);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (outputlen != sizeof ciphertext) {
+ goto loser;
+ }
+
+ /* doublecheck our result */
+ outputlen = 0;
+ rv = AES_Encrypt(cx2,
+ doublecheck, &outputlen, sizeof doublecheck,
+ plaintext, sizeof plaintext);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (outputlen != sizeof plaintext) {
+ goto loser;
+ }
+ if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
+ goto loser;
+ }
+
+ memcpy(ciphertext, plaintext_1, sizeof ciphertext);
+ }
+ AES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+ AES_DestroyContext(cx2, PR_TRUE);
+ cx2 = NULL;
+
+ /* Output PT[j] */
+ fputs("PLAINTEXT = ", aesresp);
+ to_hex_str(buf, plaintext, sizeof plaintext);
+ fputs(buf, aesresp);
+ fputc('\n', aesresp);
+
+ /* Key[i+1] = Key[i] xor ... */
+ aes_mct_next_key(key, keysize, plaintext_1, plaintext);
+ /* IV[i+1] = PT[j] */
+ memcpy(iv, plaintext, sizeof iv);
+ /* CT[0] = PT[j-1] */
+ /* done at the end of the for(j) loop */
+
+ fputc('\n', aesresp);
+ }
+
+ continue;
+ }
+ }
+loser:
+ if (cx != NULL) {
+ AES_DestroyContext(cx, PR_TRUE);
+ }
+ if (cx2 != NULL) {
+ AES_DestroyContext(cx2, PR_TRUE);
+ }
+ fclose(aesreq);
+}
+
+void
+write_compact_string(FILE *out, unsigned char *hash, unsigned int len)
+{
+ unsigned int i;
+ int j, count = 0, last = -1, z = 0;
+ long start = ftell(out);
+ for (i = 0; i < len; i++) {
+ for (j = 7; j >= 0; j--) {
+ if (last < 0) {
+ last = (hash[i] & (1 << j)) ? 1 : 0;
+ fprintf(out, "%d ", last);
+ count = 1;
+ } else if (hash[i] & (1 << j)) {
+ if (last) {
+ count++;
+ } else {
+ last = 0;
+ fprintf(out, "%d ", count);
+ count = 1;
+ z++;
+ }
+ } else {
+ if (!last) {
+ count++;
+ } else {
+ last = 1;
+ fprintf(out, "%d ", count);
+ count = 1;
+ z++;
+ }
+ }
+ }
+ }
+ fprintf(out, "^\n");
+ fseek(out, start, SEEK_SET);
+ fprintf(out, "%d ", z);
+ fseek(out, 0, SEEK_END);
+}
+
+int
+get_next_line(FILE *req, char *key, char *val, FILE *rsp)
+{
+ int ignore = 0;
+ char *writeto = key;
+ int w = 0;
+ int c;
+ while ((c = fgetc(req)) != EOF) {
+ if (ignore) {
+ fprintf(rsp, "%c", c);
+ if (c == '\n')
+ return ignore;
+ } else if (c == '\n') {
+ break;
+ } else if (c == '#') {
+ ignore = 1;
+ fprintf(rsp, "%c", c);
+ } else if (c == '=') {
+ writeto[w] = '\0';
+ w = 0;
+ writeto = val;
+ } else if (c == ' ' || c == '[' || c == ']') {
+ continue;
+ } else {
+ writeto[w++] = c;
+ }
+ }
+ writeto[w] = '\0';
+ return (c == EOF) ? -1 : ignore;
+}
+
+#ifndef NSS_DISABLE_ECC
+typedef struct curveNameTagPairStr {
+ char *curveName;
+ SECOidTag curveOidTag;
+} CurveNameTagPair;
+
+#define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
+/* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */
+
+static CurveNameTagPair nameTagPair[] =
+ {
+ { "sect163k1", SEC_OID_SECG_EC_SECT163K1 },
+ { "nistk163", SEC_OID_SECG_EC_SECT163K1 },
+ { "sect163r1", SEC_OID_SECG_EC_SECT163R1 },
+ { "sect163r2", SEC_OID_SECG_EC_SECT163R2 },
+ { "nistb163", SEC_OID_SECG_EC_SECT163R2 },
+ { "sect193r1", SEC_OID_SECG_EC_SECT193R1 },
+ { "sect193r2", SEC_OID_SECG_EC_SECT193R2 },
+ { "sect233k1", SEC_OID_SECG_EC_SECT233K1 },
+ { "nistk233", SEC_OID_SECG_EC_SECT233K1 },
+ { "sect233r1", SEC_OID_SECG_EC_SECT233R1 },
+ { "nistb233", SEC_OID_SECG_EC_SECT233R1 },
+ { "sect239k1", SEC_OID_SECG_EC_SECT239K1 },
+ { "sect283k1", SEC_OID_SECG_EC_SECT283K1 },
+ { "nistk283", SEC_OID_SECG_EC_SECT283K1 },
+ { "sect283r1", SEC_OID_SECG_EC_SECT283R1 },
+ { "nistb283", SEC_OID_SECG_EC_SECT283R1 },
+ { "sect409k1", SEC_OID_SECG_EC_SECT409K1 },
+ { "nistk409", SEC_OID_SECG_EC_SECT409K1 },
+ { "sect409r1", SEC_OID_SECG_EC_SECT409R1 },
+ { "nistb409", SEC_OID_SECG_EC_SECT409R1 },
+ { "sect571k1", SEC_OID_SECG_EC_SECT571K1 },
+ { "nistk571", SEC_OID_SECG_EC_SECT571K1 },
+ { "sect571r1", SEC_OID_SECG_EC_SECT571R1 },
+ { "nistb571", SEC_OID_SECG_EC_SECT571R1 },
+ { "secp160k1", SEC_OID_SECG_EC_SECP160K1 },
+ { "secp160r1", SEC_OID_SECG_EC_SECP160R1 },
+ { "secp160r2", SEC_OID_SECG_EC_SECP160R2 },
+ { "secp192k1", SEC_OID_SECG_EC_SECP192K1 },
+ { "secp192r1", SEC_OID_SECG_EC_SECP192R1 },
+ { "nistp192", SEC_OID_SECG_EC_SECP192R1 },
+ { "secp224k1", SEC_OID_SECG_EC_SECP224K1 },
+ { "secp224r1", SEC_OID_SECG_EC_SECP224R1 },
+ { "nistp224", SEC_OID_SECG_EC_SECP224R1 },
+ { "secp256k1", SEC_OID_SECG_EC_SECP256K1 },
+ { "secp256r1", SEC_OID_SECG_EC_SECP256R1 },
+ { "nistp256", SEC_OID_SECG_EC_SECP256R1 },
+ { "secp384r1", SEC_OID_SECG_EC_SECP384R1 },
+ { "nistp384", SEC_OID_SECG_EC_SECP384R1 },
+ { "secp521r1", SEC_OID_SECG_EC_SECP521R1 },
+ { "nistp521", SEC_OID_SECG_EC_SECP521R1 },
+
+ { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
+ { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
+ { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
+ { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
+ { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
+ { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
+
+ { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
+ { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
+ { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
+ { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
+ { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
+ { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
+ { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
+ { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
+ { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
+ { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
+ { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
+ { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
+ { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
+ { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
+ { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
+ { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
+ { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
+ { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
+ { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
+ { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
+
+ { "secp112r1", SEC_OID_SECG_EC_SECP112R1 },
+ { "secp112r2", SEC_OID_SECG_EC_SECP112R2 },
+ { "secp128r1", SEC_OID_SECG_EC_SECP128R1 },
+ { "secp128r2", SEC_OID_SECG_EC_SECP128R2 },
+
+ { "sect113r1", SEC_OID_SECG_EC_SECT113R1 },
+ { "sect113r2", SEC_OID_SECG_EC_SECT113R2 },
+ { "sect131r1", SEC_OID_SECG_EC_SECT131R1 },
+ { "sect131r2", SEC_OID_SECG_EC_SECT131R2 },
+ };
+
+static SECItem *
+getECParams(const char *curve)
+{
+ SECItem *ecparams;
+ SECOidData *oidData = NULL;
+ SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
+ int i, numCurves;
+
+ if (curve != NULL) {
+ numCurves = sizeof(nameTagPair) / sizeof(CurveNameTagPair);
+ for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN));
+ i++) {
+ if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
+ curveOidTag = nameTagPair[i].curveOidTag;
+ }
+ }
+
+ /* Return NULL if curve name is not recognized */
+ if ((curveOidTag == SEC_OID_UNKNOWN) ||
+ (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
+ fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
+ return NULL;
+ }
+
+ ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
+
+ /*
+ * ecparams->data needs to contain the ASN encoding of an object ID (OID)
+ * representing the named curve. The actual OID is in
+ * oidData->oid.data so we simply prepend 0x06 and OID length
+ */
+ ecparams->data[0] = SEC_ASN1_OBJECT_ID;
+ ecparams->data[1] = oidData->oid.len;
+ memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
+
+ return ecparams;
+}
+
+/*
+ * HASH_ functions are available to full NSS apps and internally inside
+ * freebl, but not exported to users of freebl. Create short stubs to
+ * replace the functionality for fipstest.
+ */
+SECStatus
+fips_hashBuf(HASH_HashType type, unsigned char *hashBuf,
+ unsigned char *msg, int len)
+{
+ SECStatus rv = SECFailure;
+
+ switch (type) {
+ case HASH_AlgSHA1:
+ rv = SHA1_HashBuf(hashBuf, msg, len);
+ break;
+ case HASH_AlgSHA224:
+ rv = SHA224_HashBuf(hashBuf, msg, len);
+ break;
+ case HASH_AlgSHA256:
+ rv = SHA256_HashBuf(hashBuf, msg, len);
+ break;
+ case HASH_AlgSHA384:
+ rv = SHA384_HashBuf(hashBuf, msg, len);
+ break;
+ case HASH_AlgSHA512:
+ rv = SHA512_HashBuf(hashBuf, msg, len);
+ break;
+ default:
+ break;
+ }
+ return rv;
+}
+
+int
+fips_hashLen(HASH_HashType type)
+{
+ int len = 0;
+
+ switch (type) {
+ case HASH_AlgSHA1:
+ len = SHA1_LENGTH;
+ break;
+ case HASH_AlgSHA224:
+ len = SHA224_LENGTH;
+ break;
+ case HASH_AlgSHA256:
+ len = SHA256_LENGTH;
+ break;
+ case HASH_AlgSHA384:
+ len = SHA384_LENGTH;
+ break;
+ case HASH_AlgSHA512:
+ len = SHA512_LENGTH;
+ break;
+ default:
+ break;
+ }
+ return len;
+}
+
+SECOidTag
+fips_hashOid(HASH_HashType type)
+{
+ SECOidTag oid = SEC_OID_UNKNOWN;
+
+ switch (type) {
+ case HASH_AlgSHA1:
+ oid = SEC_OID_SHA1;
+ break;
+ case HASH_AlgSHA224:
+ oid = SEC_OID_SHA224;
+ break;
+ case HASH_AlgSHA256:
+ oid = SEC_OID_SHA256;
+ break;
+ case HASH_AlgSHA384:
+ oid = SEC_OID_SHA384;
+ break;
+ case HASH_AlgSHA512:
+ oid = SEC_OID_SHA512;
+ break;
+ default:
+ break;
+ }
+ return oid;
+}
+
+HASH_HashType
+sha_get_hashType(int hashbits)
+{
+ HASH_HashType hashType = HASH_AlgNULL;
+
+ switch (hashbits) {
+ case 1:
+ case (SHA1_LENGTH * PR_BITS_PER_BYTE):
+ hashType = HASH_AlgSHA1;
+ break;
+ case (SHA224_LENGTH * PR_BITS_PER_BYTE):
+ hashType = HASH_AlgSHA224;
+ break;
+ case (SHA256_LENGTH * PR_BITS_PER_BYTE):
+ hashType = HASH_AlgSHA256;
+ break;
+ case (SHA384_LENGTH * PR_BITS_PER_BYTE):
+ hashType = HASH_AlgSHA384;
+ break;
+ case (SHA512_LENGTH * PR_BITS_PER_BYTE):
+ hashType = HASH_AlgSHA512;
+ break;
+ default:
+ break;
+ }
+ return hashType;
+}
+
+/*
+ * Perform the ECDSA Key Pair Generation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+ecdsa_keypair_test(char *reqfn)
+{
+ char buf[256]; /* holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * needs to be large enough to hold the longest
+ * line "Qx = <144 hex digits>\n".
+ */
+ FILE *ecdsareq; /* input stream from the REQUEST file */
+ FILE *ecdsaresp; /* output stream to the RESPONSE file */
+ char curve[16]; /* "nistxddd" */
+ ECParams *ecparams = NULL;
+ int N;
+ int i;
+ unsigned int len;
+
+ ecdsareq = fopen(reqfn, "r");
+ ecdsaresp = stdout;
+ strcpy(curve, "nist");
+ while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* [X-ddd] */
+ if (buf[0] == '[') {
+ const char *src;
+ char *dst;
+ SECItem *encodedparams;
+
+ if (buf[1] == 'B') {
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ if (ecparams) {
+ PORT_FreeArena(ecparams->arena, PR_FALSE);
+ ecparams = NULL;
+ }
+
+ src = &buf[1];
+ dst = &curve[4];
+ *dst++ = tolower(*src);
+ src += 2; /* skip the hyphen */
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst = '\0';
+ encodedparams = getECParams(curve);
+ if (encodedparams == NULL) {
+ fprintf(stderr, "Unknown curve %s.", curve);
+ goto loser;
+ }
+ if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
+ fprintf(stderr, "Curve %s not supported.\n", curve);
+ goto loser;
+ }
+ SECITEM_FreeItem(encodedparams, PR_TRUE);
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* N = x */
+ if (buf[0] == 'N') {
+ if (sscanf(buf, "N = %d", &N) != 1) {
+ goto loser;
+ }
+ for (i = 0; i < N; i++) {
+ ECPrivateKey *ecpriv;
+
+ if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
+ goto loser;
+ }
+ fputs("d = ", ecdsaresp);
+ to_hex_str(buf, ecpriv->privateValue.data,
+ ecpriv->privateValue.len);
+ fputs(buf, ecdsaresp);
+ fputc('\n', ecdsaresp);
+ if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue) !=
+ SECSuccess) {
+ goto loser;
+ }
+ len = ecpriv->publicValue.len;
+ if (len % 2 == 0) {
+ goto loser;
+ }
+ len = (len - 1) / 2;
+ if (ecpriv->publicValue.data[0] !=
+ EC_POINT_FORM_UNCOMPRESSED) {
+ goto loser;
+ }
+ fputs("Qx = ", ecdsaresp);
+ to_hex_str(buf, &ecpriv->publicValue.data[1], len);
+ fputs(buf, ecdsaresp);
+ fputc('\n', ecdsaresp);
+ fputs("Qy = ", ecdsaresp);
+ to_hex_str(buf, &ecpriv->publicValue.data[1 + len], len);
+ fputs(buf, ecdsaresp);
+ fputc('\n', ecdsaresp);
+ fputc('\n', ecdsaresp);
+ PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
+ }
+ continue;
+ }
+ }
+loser:
+ if (ecparams) {
+ PORT_FreeArena(ecparams->arena, PR_FALSE);
+ ecparams = NULL;
+ }
+ fclose(ecdsareq);
+}
+
+/*
+ * Perform the ECDSA Public Key Validation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+ecdsa_pkv_test(char *reqfn)
+{
+ char buf[256]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "Qx = <144 hex digits>\n".
+ */
+ FILE *ecdsareq; /* input stream from the REQUEST file */
+ FILE *ecdsaresp; /* output stream to the RESPONSE file */
+ char curve[16]; /* "nistxddd" */
+ ECParams *ecparams = NULL;
+ SECItem pubkey;
+ unsigned int i;
+ unsigned int len = 0;
+ PRBool keyvalid = PR_TRUE;
+
+ ecdsareq = fopen(reqfn, "r");
+ ecdsaresp = stdout;
+ strcpy(curve, "nist");
+ pubkey.data = NULL;
+ while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* [X-ddd] */
+ if (buf[0] == '[') {
+ const char *src;
+ char *dst;
+ SECItem *encodedparams;
+
+ src = &buf[1];
+ dst = &curve[4];
+ *dst++ = tolower(*src);
+ src += 2; /* skip the hyphen */
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst = '\0';
+ if (ecparams != NULL) {
+ PORT_FreeArena(ecparams->arena, PR_FALSE);
+ ecparams = NULL;
+ }
+ encodedparams = getECParams(curve);
+ if (encodedparams == NULL) {
+ fprintf(stderr, "Unknown curve %s.", curve);
+ goto loser;
+ }
+ if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
+ fprintf(stderr, "Curve %s not supported.\n", curve);
+ goto loser;
+ }
+ SECITEM_FreeItem(encodedparams, PR_TRUE);
+ len = (ecparams->fieldID.size + 7) >> 3;
+ if (pubkey.data != NULL) {
+ PORT_Free(pubkey.data);
+ pubkey.data = NULL;
+ }
+ SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(ecparams));
+ if (pubkey.data == NULL) {
+ goto loser;
+ }
+ pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* Qx = ... */
+ if (strncmp(buf, "Qx", 2) == 0) {
+ fputs(buf, ecdsaresp);
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ keyvalid = from_hex_str(&pubkey.data[1], len, &buf[i]);
+ continue;
+ }
+ /* Qy = ... */
+ if (strncmp(buf, "Qy", 2) == 0) {
+ fputs(buf, ecdsaresp);
+ if (!keyvalid) {
+ fputs("Result = F\n", ecdsaresp);
+ continue;
+ }
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ keyvalid = from_hex_str(&pubkey.data[1 + len], len, &buf[i]);
+ if (!keyvalid) {
+ fputs("Result = F\n", ecdsaresp);
+ continue;
+ }
+ if (EC_ValidatePublicKey(ecparams, &pubkey) == SECSuccess) {
+ fputs("Result = P\n", ecdsaresp);
+ } else if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
+ fputs("Result = F\n", ecdsaresp);
+ } else {
+ goto loser;
+ }
+ continue;
+ }
+ }
+loser:
+ if (ecparams != NULL) {
+ PORT_FreeArena(ecparams->arena, PR_FALSE);
+ }
+ if (pubkey.data != NULL) {
+ PORT_Free(pubkey.data);
+ }
+ fclose(ecdsareq);
+}
+
+/*
+ * Perform the ECDSA Signature Generation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+ecdsa_siggen_test(char *reqfn)
+{
+ char buf[1024]; /* holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * needs to be large enough to hold the longest
+ * line "Msg = <256 hex digits>\n".
+ */
+ FILE *ecdsareq; /* input stream from the REQUEST file */
+ FILE *ecdsaresp; /* output stream to the RESPONSE file */
+ char curve[16]; /* "nistxddd" */
+ ECParams *ecparams = NULL;
+ int i, j;
+ unsigned int len;
+ unsigned char msg[512]; /* message to be signed (<= 128 bytes) */
+ unsigned int msglen;
+ unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
+ unsigned int shaLength = 0; /* length of SHA */
+ HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
+ unsigned char sig[2 * MAX_ECKEY_LEN];
+ SECItem signature, digest;
+
+ ecdsareq = fopen(reqfn, "r");
+ ecdsaresp = stdout;
+ strcpy(curve, "nist");
+ while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* [X-ddd] */
+ if (buf[0] == '[') {
+ const char *src;
+ char *dst;
+ SECItem *encodedparams;
+
+ src = &buf[1];
+ dst = &curve[4];
+ *dst++ = tolower(*src);
+ src += 2; /* skip the hyphen */
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst = '\0';
+ src++; /* skip the comma */
+ /* set the SHA Algorithm */
+ if (strncmp(src, "SHA-1", 5) == 0) {
+ shaAlg = HASH_AlgSHA1;
+ } else if (strncmp(src, "SHA-224", 7) == 0) {
+ shaAlg = HASH_AlgSHA224;
+ } else if (strncmp(src, "SHA-256", 7) == 0) {
+ shaAlg = HASH_AlgSHA256;
+ } else if (strncmp(src, "SHA-384", 7) == 0) {
+ shaAlg = HASH_AlgSHA384;
+ } else if (strncmp(src, "SHA-512", 7) == 0) {
+ shaAlg = HASH_AlgSHA512;
+ } else {
+ fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type");
+ goto loser;
+ }
+ if (ecparams != NULL) {
+ PORT_FreeArena(ecparams->arena, PR_FALSE);
+ ecparams = NULL;
+ }
+ encodedparams = getECParams(curve);
+ if (encodedparams == NULL) {
+ fprintf(stderr, "Unknown curve %s.", curve);
+ goto loser;
+ }
+ if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
+ fprintf(stderr, "Curve %s not supported.\n", curve);
+ goto loser;
+ }
+ SECITEM_FreeItem(encodedparams, PR_TRUE);
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* Msg = ... */
+ if (strncmp(buf, "Msg", 3) == 0) {
+ ECPrivateKey *ecpriv;
+
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &msg[j]);
+ }
+ msglen = j;
+ shaLength = fips_hashLen(shaAlg);
+ if (fips_hashBuf(shaAlg, sha, msg, msglen) != SECSuccess) {
+ if (shaLength == 0) {
+ fprintf(ecdsaresp, "ERROR: SHAAlg not defined.");
+ }
+ fprintf(ecdsaresp, "ERROR: Unable to generate SHA%x",
+ shaLength == 160 ? 1 : shaLength);
+ goto loser;
+ }
+ fputs(buf, ecdsaresp);
+
+ if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
+ goto loser;
+ }
+ if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue) !=
+ SECSuccess) {
+ goto loser;
+ }
+ len = ecpriv->publicValue.len;
+ if (len % 2 == 0) {
+ goto loser;
+ }
+ len = (len - 1) / 2;
+ if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
+ goto loser;
+ }
+ fputs("Qx = ", ecdsaresp);
+ to_hex_str(buf, &ecpriv->publicValue.data[1], len);
+ fputs(buf, ecdsaresp);
+ fputc('\n', ecdsaresp);
+ fputs("Qy = ", ecdsaresp);
+ to_hex_str(buf, &ecpriv->publicValue.data[1 + len], len);
+ fputs(buf, ecdsaresp);
+ fputc('\n', ecdsaresp);
+
+ digest.type = siBuffer;
+ digest.data = sha;
+ digest.len = shaLength;
+ signature.type = siBuffer;
+ signature.data = sig;
+ signature.len = sizeof sig;
+ if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) {
+ goto loser;
+ }
+ len = signature.len;
+ if (len % 2 != 0) {
+ goto loser;
+ }
+ len = len / 2;
+ fputs("R = ", ecdsaresp);
+ to_hex_str(buf, &signature.data[0], len);
+ fputs(buf, ecdsaresp);
+ fputc('\n', ecdsaresp);
+ fputs("S = ", ecdsaresp);
+ to_hex_str(buf, &signature.data[len], len);
+ fputs(buf, ecdsaresp);
+ fputc('\n', ecdsaresp);
+
+ PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
+ continue;
+ }
+ }
+loser:
+ if (ecparams != NULL) {
+ PORT_FreeArena(ecparams->arena, PR_FALSE);
+ }
+ fclose(ecdsareq);
+}
+
+/*
+ * Perform the ECDSA Signature Verification Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+ecdsa_sigver_test(char *reqfn)
+{
+ char buf[1024]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "Msg = <256 hex digits>\n".
+ */
+ FILE *ecdsareq; /* input stream from the REQUEST file */
+ FILE *ecdsaresp; /* output stream to the RESPONSE file */
+ char curve[16]; /* "nistxddd" */
+ ECPublicKey ecpub;
+ unsigned int i, j;
+ unsigned int flen = 0; /* length in bytes of the field size */
+ unsigned int olen = 0; /* length in bytes of the base point order */
+ unsigned char msg[512]; /* message that was signed (<= 128 bytes) */
+ unsigned int msglen = 0;
+ unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
+ unsigned int shaLength = 0; /* length of SHA */
+ HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
+ unsigned char sig[2 * MAX_ECKEY_LEN];
+ SECItem signature, digest;
+ PRBool keyvalid = PR_TRUE;
+ PRBool sigvalid = PR_TRUE;
+
+ ecdsareq = fopen(reqfn, "r");
+ ecdsaresp = stdout;
+ ecpub.ecParams.arena = NULL;
+ strcpy(curve, "nist");
+ while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* [X-ddd] */
+ if (buf[0] == '[') {
+ const char *src;
+ char *dst;
+ SECItem *encodedparams;
+ ECParams *ecparams;
+
+ src = &buf[1];
+ dst = &curve[4];
+ *dst++ = tolower(*src);
+ src += 2; /* skip the hyphen */
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst = '\0';
+ src++; /* skip the comma */
+ /* set the SHA Algorithm */
+ if (strncmp(src, "SHA-1", 5) == 0) {
+ shaAlg = HASH_AlgSHA1;
+ } else if (strncmp(src, "SHA-224", 7) == 0) {
+ shaAlg = HASH_AlgSHA224;
+ } else if (strncmp(src, "SHA-256", 7) == 0) {
+ shaAlg = HASH_AlgSHA256;
+ } else if (strncmp(src, "SHA-384", 7) == 0) {
+ shaAlg = HASH_AlgSHA384;
+ } else if (strncmp(src, "SHA-512", 7) == 0) {
+ shaAlg = HASH_AlgSHA512;
+ } else {
+ fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type");
+ goto loser;
+ }
+ encodedparams = getECParams(curve);
+ if (encodedparams == NULL) {
+ fprintf(stderr, "Unknown curve %s.", curve);
+ goto loser;
+ }
+ if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
+ fprintf(stderr, "Curve %s not supported.\n", curve);
+ goto loser;
+ }
+ SECITEM_FreeItem(encodedparams, PR_TRUE);
+ if (ecpub.ecParams.arena != NULL) {
+ PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
+ }
+ ecpub.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (ecpub.ecParams.arena == NULL) {
+ goto loser;
+ }
+ if (EC_CopyParams(ecpub.ecParams.arena, &ecpub.ecParams, ecparams) !=
+ SECSuccess) {
+ goto loser;
+ }
+ PORT_FreeArena(ecparams->arena, PR_FALSE);
+ flen = (ecpub.ecParams.fieldID.size + 7) >> 3;
+ olen = ecpub.ecParams.order.len;
+ if (2 * olen > sizeof sig) {
+ goto loser;
+ }
+ ecpub.publicValue.type = siBuffer;
+ ecpub.publicValue.data = NULL;
+ ecpub.publicValue.len = 0;
+ SECITEM_AllocItem(ecpub.ecParams.arena,
+ &ecpub.publicValue, 2 * flen + 1);
+ if (ecpub.publicValue.data == NULL) {
+ goto loser;
+ }
+ ecpub.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED;
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* Msg = ... */
+ if (strncmp(buf, "Msg", 3) == 0) {
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &msg[j]);
+ }
+ msglen = j;
+ shaLength = fips_hashLen(shaAlg);
+ if (fips_hashBuf(shaAlg, sha, msg, msglen) != SECSuccess) {
+ if (shaLength == 0) {
+ fprintf(ecdsaresp, "ERROR: SHAAlg not defined.");
+ }
+ fprintf(ecdsaresp, "ERROR: Unable to generate SHA%x",
+ shaLength == 160 ? 1 : shaLength);
+ goto loser;
+ }
+ fputs(buf, ecdsaresp);
+
+ digest.type = siBuffer;
+ digest.data = sha;
+ digest.len = shaLength;
+
+ continue;
+ }
+ /* Qx = ... */
+ if (strncmp(buf, "Qx", 2) == 0) {
+ fputs(buf, ecdsaresp);
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ keyvalid = from_hex_str(&ecpub.publicValue.data[1], flen,
+ &buf[i]);
+ continue;
+ }
+ /* Qy = ... */
+ if (strncmp(buf, "Qy", 2) == 0) {
+ fputs(buf, ecdsaresp);
+ if (!keyvalid) {
+ continue;
+ }
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ keyvalid = from_hex_str(&ecpub.publicValue.data[1 + flen], flen,
+ &buf[i]);
+ if (!keyvalid) {
+ continue;
+ }
+ if (EC_ValidatePublicKey(&ecpub.ecParams, &ecpub.publicValue) !=
+ SECSuccess) {
+ if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
+ keyvalid = PR_FALSE;
+ } else {
+ goto loser;
+ }
+ }
+ continue;
+ }
+ /* R = ... */
+ if (buf[0] == 'R') {
+ fputs(buf, ecdsaresp);
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ sigvalid = from_hex_str(sig, olen, &buf[i]);
+ continue;
+ }
+ /* S = ... */
+ if (buf[0] == 'S') {
+ fputs(buf, ecdsaresp);
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ if (sigvalid) {
+ sigvalid = from_hex_str(&sig[olen], olen, &buf[i]);
+ }
+ signature.type = siBuffer;
+ signature.data = sig;
+ signature.len = 2 * olen;
+
+ if (!keyvalid || !sigvalid) {
+ fputs("Result = F\n", ecdsaresp);
+ } else if (ECDSA_VerifyDigest(&ecpub, &signature, &digest) ==
+ SECSuccess) {
+ fputs("Result = P\n", ecdsaresp);
+ } else {
+ fputs("Result = F\n", ecdsaresp);
+ }
+ continue;
+ }
+ }
+loser:
+ if (ecpub.ecParams.arena != NULL) {
+ PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
+ }
+ fclose(ecdsareq);
+}
+#endif /* NSS_DISABLE_ECC */
+
+PRBool
+isblankline(char *b)
+{
+ while (isspace(*b))
+ b++;
+ if ((*b == '\n') || (*b == 0)) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+static int debug = 0;
+
+/*
+ * Perform the Hash_DRBG (CAVS) for the RNG algorithm
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+drbg(char *reqfn)
+{
+ char buf[2000]; /* test case has some very long lines, returned bits
+ * as high as 800 bytes (6400 bits). That 1600 byte
+ * plus a tag */
+ char buf2[2000];
+ FILE *rngreq; /* input stream from the REQUEST file */
+ FILE *rngresp; /* output stream to the RESPONSE file */
+
+ unsigned int i, j;
+#ifdef HANDLE_PREDICTION_RESISTANCE
+ PRBool predictionResistance = PR_FALSE;
+#endif
+ unsigned char *nonce = NULL;
+ int nonceLen = 0;
+ unsigned char *personalizationString = NULL;
+ int personalizationStringLen = 0;
+ unsigned char *additionalInput = NULL;
+ int additionalInputLen = 0;
+ unsigned char *entropyInput = NULL;
+ int entropyInputLen = 0;
+ unsigned char *predictedreturn_bytes = NULL;
+ unsigned char *return_bytes = NULL;
+ int return_bytes_len = 0;
+ enum { NONE,
+ INSTANTIATE,
+ GENERATE,
+ RESEED,
+ RESULT } command =
+ NONE;
+ PRBool genResult = PR_FALSE;
+ SECStatus rv;
+
+ rngreq = fopen(reqfn, "r");
+ rngresp = stdout;
+ while (fgets(buf, sizeof buf, rngreq) != NULL) {
+ switch (command) {
+ case INSTANTIATE:
+ if (debug) {
+ fputs("# PRNGTEST_Instantiate(", rngresp);
+ to_hex_str(buf2, entropyInput, entropyInputLen);
+ fputs(buf2, rngresp);
+ fprintf(rngresp, ",%d,", entropyInputLen);
+ to_hex_str(buf2, nonce, nonceLen);
+ fputs(buf2, rngresp);
+ fprintf(rngresp, ",%d,", nonceLen);
+ to_hex_str(buf2, personalizationString,
+ personalizationStringLen);
+ fputs(buf2, rngresp);
+ fprintf(rngresp, ",%d)\n", personalizationStringLen);
+ }
+ rv = PRNGTEST_Instantiate(entropyInput, entropyInputLen,
+ nonce, nonceLen,
+ personalizationString,
+ personalizationStringLen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ break;
+
+ case GENERATE:
+ case RESULT:
+ memset(return_bytes, 0, return_bytes_len);
+ if (debug) {
+ fputs("# PRNGTEST_Generate(returnbytes", rngresp);
+ fprintf(rngresp, ",%d,", return_bytes_len);
+ to_hex_str(buf2, additionalInput, additionalInputLen);
+ fputs(buf2, rngresp);
+ fprintf(rngresp, ",%d)\n", additionalInputLen);
+ }
+ rv = PRNGTEST_Generate((PRUint8 *)return_bytes,
+ return_bytes_len,
+ (PRUint8 *)additionalInput,
+ additionalInputLen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ if (command == RESULT) {
+ fputs("ReturnedBits = ", rngresp);
+ to_hex_str(buf2, return_bytes, return_bytes_len);
+ fputs(buf2, rngresp);
+ fputc('\n', rngresp);
+ if (debug) {
+ fputs("# PRNGTEST_Uninstantiate()\n", rngresp);
+ }
+ rv = PRNGTEST_Uninstantiate();
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ } else if (debug) {
+ fputs("#ReturnedBits = ", rngresp);
+ to_hex_str(buf2, return_bytes, return_bytes_len);
+ fputs(buf2, rngresp);
+ fputc('\n', rngresp);
+ }
+
+ memset(additionalInput, 0, additionalInputLen);
+ break;
+
+ case RESEED:
+ if (entropyInput || additionalInput) {
+ if (debug) {
+ fputs("# PRNGTEST_Reseed(", rngresp);
+ fprintf(rngresp, ",%d,", return_bytes_len);
+ to_hex_str(buf2, entropyInput, entropyInputLen);
+ fputs(buf2, rngresp);
+ fprintf(rngresp, ",%d,", entropyInputLen);
+ to_hex_str(buf2, additionalInput, additionalInputLen);
+ fputs(buf2, rngresp);
+ fprintf(rngresp, ",%d)\n", additionalInputLen);
+ }
+ rv = PRNGTEST_Reseed(entropyInput, entropyInputLen,
+ additionalInput, additionalInputLen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+ memset(entropyInput, 0, entropyInputLen);
+ memset(additionalInput, 0, additionalInputLen);
+ break;
+ case NONE:
+ break;
+ }
+ command = NONE;
+
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ /* [Hash - SHA256] */
+ if (strncmp(buf, "[SHA-256]", 9) == 0) {
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ if (strncmp(buf, "[PredictionResistance", 21) == 0) {
+#ifdef HANDLE_PREDICTION_RESISTANCE
+ i = 21;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ if (strncmp(buf, "False", 5) == 0) {
+ predictionResistance = PR_FALSE;
+ } else {
+ predictionResistance = PR_TRUE;
+ }
+#endif
+
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ if (strncmp(buf, "[ReturnedBitsLen", 16) == 0) {
+ if (return_bytes) {
+ PORT_ZFree(return_bytes, return_bytes_len);
+ return_bytes = NULL;
+ }
+ if (predictedreturn_bytes) {
+ PORT_ZFree(predictedreturn_bytes, return_bytes_len);
+ predictedreturn_bytes = NULL;
+ }
+ return_bytes_len = 0;
+ if (sscanf(buf, "[ReturnedBitsLen = %d]", &return_bytes_len) != 1) {
+ goto loser;
+ }
+ return_bytes_len = return_bytes_len / 8;
+ if (return_bytes_len > 0) {
+ return_bytes = PORT_Alloc(return_bytes_len);
+ predictedreturn_bytes = PORT_Alloc(return_bytes_len);
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ if (strncmp(buf, "[EntropyInputLen", 16) == 0) {
+ if (entropyInput) {
+ PORT_ZFree(entropyInput, entropyInputLen);
+ entropyInput = NULL;
+ entropyInputLen = 0;
+ }
+ if (sscanf(buf, "[EntropyInputLen = %d]", &entropyInputLen) != 1) {
+ goto loser;
+ }
+ entropyInputLen = entropyInputLen / 8;
+ if (entropyInputLen > 0) {
+ entropyInput = PORT_Alloc(entropyInputLen);
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ if (strncmp(buf, "[NonceLen", 9) == 0) {
+ if (nonce) {
+ PORT_ZFree(nonce, nonceLen);
+ nonce = NULL;
+ nonceLen = 0;
+ }
+
+ if (sscanf(buf, "[NonceLen = %d]", &nonceLen) != 1) {
+ goto loser;
+ }
+ nonceLen = nonceLen / 8;
+ if (nonceLen > 0) {
+ nonce = PORT_Alloc(nonceLen);
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ if (strncmp(buf, "[PersonalizationStringLen", 16) == 0) {
+ if (personalizationString) {
+ PORT_ZFree(personalizationString, personalizationStringLen);
+ personalizationString = NULL;
+ personalizationStringLen = 0;
+ }
+
+ if (sscanf(buf, "[PersonalizationStringLen = %d]", &personalizationStringLen) != 1) {
+ goto loser;
+ }
+ personalizationStringLen = personalizationStringLen / 8;
+ if (personalizationStringLen > 0) {
+ personalizationString = PORT_Alloc(personalizationStringLen);
+ }
+ fputs(buf, rngresp);
+
+ continue;
+ }
+
+ if (strncmp(buf, "[AdditionalInputLen", 16) == 0) {
+ if (additionalInput) {
+ PORT_ZFree(additionalInput, additionalInputLen);
+ additionalInput = NULL;
+ additionalInputLen = 0;
+ }
+
+ if (sscanf(buf, "[AdditionalInputLen = %d]", &additionalInputLen) != 1) {
+ goto loser;
+ }
+ additionalInputLen = additionalInputLen / 8;
+ if (additionalInputLen > 0) {
+ additionalInput = PORT_Alloc(additionalInputLen);
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ /* zeroize the variables for the test with this data set */
+ if (entropyInput) {
+ memset(entropyInput, 0, entropyInputLen);
+ }
+ if (nonce) {
+ memset(nonce, 0, nonceLen);
+ }
+ if (personalizationString) {
+ memset(personalizationString, 0, personalizationStringLen);
+ }
+ if (additionalInput) {
+ memset(additionalInput, 0, additionalInputLen);
+ }
+ genResult = PR_FALSE;
+
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ /* EntropyInputReseed = ... */
+ if (strncmp(buf, "EntropyInputReseed", 18) == 0) {
+ if (entropyInput) {
+ memset(entropyInput, 0, entropyInputLen);
+ i = 18;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<entropyInputLen*/
+ hex_to_byteval(&buf[i], &entropyInput[j]);
+ }
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ /* AttionalInputReseed = ... */
+ if (strncmp(buf, "AdditionalInputReseed", 21) == 0) {
+ if (additionalInput) {
+ memset(additionalInput, 0, additionalInputLen);
+ i = 21;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<additionalInputLen*/
+ hex_to_byteval(&buf[i], &additionalInput[j]);
+ }
+ }
+ command = RESEED;
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ /* Entropy input = ... */
+ if (strncmp(buf, "EntropyInput", 12) == 0) {
+ i = 12;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<entropyInputLen*/
+ hex_to_byteval(&buf[i], &entropyInput[j]);
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ /* nouce = ... */
+ if (strncmp(buf, "Nonce", 5) == 0) {
+ i = 5;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<nonceLen*/
+ hex_to_byteval(&buf[i], &nonce[j]);
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ /* Personalization string = ... */
+ if (strncmp(buf, "PersonalizationString", 21) == 0) {
+ if (personalizationString) {
+ i = 21;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<personalizationStringLen*/
+ hex_to_byteval(&buf[i], &personalizationString[j]);
+ }
+ }
+ fputs(buf, rngresp);
+ command = INSTANTIATE;
+ continue;
+ }
+
+ /* Additional input = ... */
+ if (strncmp(buf, "AdditionalInput", 15) == 0) {
+ if (additionalInput) {
+ i = 15;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<additionalInputLen*/
+ hex_to_byteval(&buf[i], &additionalInput[j]);
+ }
+ }
+ if (genResult) {
+ command = RESULT;
+ } else {
+ command = GENERATE;
+ genResult = PR_TRUE; /* next time generate result */
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ /* Returned bits = ... */
+ if (strncmp(buf, "ReturnedBits", 12) == 0) {
+ i = 12;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) { /*j<additionalInputLen*/
+ hex_to_byteval(&buf[i], &predictedreturn_bytes[j]);
+ }
+
+ if (memcmp(return_bytes,
+ predictedreturn_bytes, return_bytes_len) != 0) {
+ if (debug) {
+ fprintf(rngresp, "# Generate failed:\n");
+ fputs("# predicted=", rngresp);
+ to_hex_str(buf, predictedreturn_bytes,
+ return_bytes_len);
+ fputs(buf, rngresp);
+ fputs("\n# actual = ", rngresp);
+ fputs(buf2, rngresp);
+ fputc('\n', rngresp);
+
+ } else {
+ fprintf(stderr, "Generate failed:\n");
+ fputs(" predicted=", stderr);
+ to_hex_str(buf, predictedreturn_bytes,
+ return_bytes_len);
+ fputs(buf, stderr);
+ fputs("\n actual = ", stderr);
+ fputs(buf2, stderr);
+ fputc('\n', stderr);
+ }
+ }
+ memset(predictedreturn_bytes, 0, return_bytes_len);
+
+ continue;
+ }
+ }
+loser:
+ if (predictedreturn_bytes) {
+ PORT_Free(predictedreturn_bytes);
+ }
+ if (return_bytes) {
+ PORT_Free(return_bytes);
+ }
+ if (additionalInput) {
+ PORT_Free(additionalInput);
+ }
+ if (personalizationString) {
+ PORT_Free(personalizationString);
+ }
+ if (nonce) {
+ PORT_Free(nonce);
+ }
+ if (entropyInput) {
+ PORT_Free(entropyInput);
+ }
+ fclose(rngreq);
+}
+
+/*
+ * Perform the RNG Variable Seed Test (VST) for the RNG algorithm
+ * "DSA - Generation of X", used both as specified and as a generic
+ * purpose RNG. The presence of "Q = ..." in the REQUEST file
+ * indicates we are using the algorithm as specified.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+rng_vst(char *reqfn)
+{
+ char buf[256]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "XSeed = <128 hex digits>\n".
+ */
+ FILE *rngreq; /* input stream from the REQUEST file */
+ FILE *rngresp; /* output stream to the RESPONSE file */
+ unsigned int i, j;
+ unsigned char Q[DSA1_SUBPRIME_LEN];
+ PRBool hasQ = PR_FALSE;
+ unsigned int b = 0; /* 160 <= b <= 512, b is a multiple of 8 */
+ unsigned char XKey[512 / 8];
+ unsigned char XSeed[512 / 8];
+ unsigned char GENX[DSA1_SIGNATURE_LEN];
+ unsigned char DSAX[DSA1_SUBPRIME_LEN];
+ SECStatus rv;
+
+ rngreq = fopen(reqfn, "r");
+ rngresp = stdout;
+ while (fgets(buf, sizeof buf, rngreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* [Xchange - SHA1] */
+ if (buf[0] == '[') {
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* Q = ... */
+ if (buf[0] == 'Q') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < sizeof Q; i += 2, j++) {
+ hex_to_byteval(&buf[i], &Q[j]);
+ }
+ fputs(buf, rngresp);
+ hasQ = PR_TRUE;
+ continue;
+ }
+ /* "COUNT = x" begins a new data set */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ /* zeroize the variables for the test with this data set */
+ b = 0;
+ memset(XKey, 0, sizeof XKey);
+ memset(XSeed, 0, sizeof XSeed);
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* b = ... */
+ if (buf[0] == 'b') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ b = atoi(&buf[i]);
+ if (b < 160 || b > 512 || b % 8 != 0) {
+ goto loser;
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* XKey = ... */
+ if (strncmp(buf, "XKey", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < b / 8; i += 2, j++) {
+ hex_to_byteval(&buf[i], &XKey[j]);
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* XSeed = ... */
+ if (strncmp(buf, "XSeed", 5) == 0) {
+ i = 5;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < b / 8; i += 2, j++) {
+ hex_to_byteval(&buf[i], &XSeed[j]);
+ }
+ fputs(buf, rngresp);
+
+ rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ fputs("X = ", rngresp);
+ if (hasQ) {
+ rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ to_hex_str(buf, DSAX, sizeof DSAX);
+ } else {
+ to_hex_str(buf, GENX, sizeof GENX);
+ }
+ fputs(buf, rngresp);
+ fputc('\n', rngresp);
+ continue;
+ }
+ }
+loser:
+ fclose(rngreq);
+}
+
+/*
+ * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm
+ * "DSA - Generation of X", used both as specified and as a generic
+ * purpose RNG. The presence of "Q = ..." in the REQUEST file
+ * indicates we are using the algorithm as specified.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+rng_mct(char *reqfn)
+{
+ char buf[256]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "XSeed = <128 hex digits>\n".
+ */
+ FILE *rngreq; /* input stream from the REQUEST file */
+ FILE *rngresp; /* output stream to the RESPONSE file */
+ unsigned int i, j;
+ unsigned char Q[DSA1_SUBPRIME_LEN];
+ PRBool hasQ = PR_FALSE;
+ unsigned int b = 0; /* 160 <= b <= 512, b is a multiple of 8 */
+ unsigned char XKey[512 / 8];
+ unsigned char XSeed[512 / 8];
+ unsigned char GENX[2 * SHA1_LENGTH];
+ unsigned char DSAX[DSA1_SUBPRIME_LEN];
+ SECStatus rv;
+
+ rngreq = fopen(reqfn, "r");
+ rngresp = stdout;
+ while (fgets(buf, sizeof buf, rngreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* [Xchange - SHA1] */
+ if (buf[0] == '[') {
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* Q = ... */
+ if (buf[0] == 'Q') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < sizeof Q; i += 2, j++) {
+ hex_to_byteval(&buf[i], &Q[j]);
+ }
+ fputs(buf, rngresp);
+ hasQ = PR_TRUE;
+ continue;
+ }
+ /* "COUNT = x" begins a new data set */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ /* zeroize the variables for the test with this data set */
+ b = 0;
+ memset(XKey, 0, sizeof XKey);
+ memset(XSeed, 0, sizeof XSeed);
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* b = ... */
+ if (buf[0] == 'b') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ b = atoi(&buf[i]);
+ if (b < 160 || b > 512 || b % 8 != 0) {
+ goto loser;
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* XKey = ... */
+ if (strncmp(buf, "XKey", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < b / 8; i += 2, j++) {
+ hex_to_byteval(&buf[i], &XKey[j]);
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* XSeed = ... */
+ if (strncmp(buf, "XSeed", 5) == 0) {
+ unsigned int k;
+ i = 5;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < b / 8; i += 2, j++) {
+ hex_to_byteval(&buf[i], &XSeed[j]);
+ }
+ fputs(buf, rngresp);
+
+ for (k = 0; k < 10000; k++) {
+ rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+ fputs("X = ", rngresp);
+ if (hasQ) {
+ rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ to_hex_str(buf, DSAX, sizeof DSAX);
+ } else {
+ to_hex_str(buf, GENX, sizeof GENX);
+ }
+ fputs(buf, rngresp);
+ fputc('\n', rngresp);
+ continue;
+ }
+ }
+loser:
+ fclose(rngreq);
+}
+
+/*
+ * Calculate the SHA Message Digest
+ *
+ * MD = Message digest
+ * MDLen = length of Message Digest and SHA_Type
+ * msg = message to digest
+ * msgLen = length of message to digest
+ */
+SECStatus
+sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen)
+{
+ HASH_HashType hashType = sha_get_hashType(MDLen * PR_BITS_PER_BYTE);
+
+ return fips_hashBuf(hashType, MD, msg, msgLen);
+}
+
+/*
+ * Perform the SHA Monte Carlo Test
+ *
+ * MDLen = length of Message Digest and SHA_Type
+ * seed = input seed value
+ * resp = is the output response file.
+ */
+SECStatus
+sha_mct_test(unsigned int MDLen, unsigned char *seed, FILE *resp)
+{
+ int i, j;
+ unsigned int msgLen = MDLen * 3;
+ unsigned char MD_i3[HASH_LENGTH_MAX]; /* MD[i-3] */
+ unsigned char MD_i2[HASH_LENGTH_MAX]; /* MD[i-2] */
+ unsigned char MD_i1[HASH_LENGTH_MAX]; /* MD[i-1] */
+ unsigned char MD_i[HASH_LENGTH_MAX]; /* MD[i] */
+ unsigned char msg[HASH_LENGTH_MAX * 3];
+ char buf[HASH_LENGTH_MAX * 2 + 1]; /* MAX buf MD_i as a hex string */
+
+ for (j = 0; j < 100; j++) {
+ /* MD_0 = MD_1 = MD_2 = seed */
+ memcpy(MD_i3, seed, MDLen);
+ memcpy(MD_i2, seed, MDLen);
+ memcpy(MD_i1, seed, MDLen);
+
+ for (i = 3; i < 1003; i++) {
+ /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */
+ memcpy(msg, MD_i3, MDLen);
+ memcpy(&msg[MDLen], MD_i2, MDLen);
+ memcpy(&msg[MDLen * 2], MD_i1, MDLen);
+
+ /* MDi = SHA(Msg) */
+ if (sha_calcMD(MD_i, MDLen,
+ msg, msgLen) != SECSuccess) {
+ return SECFailure;
+ }
+
+ /* save MD[i-3] MD[i-2] MD[i-1] */
+ memcpy(MD_i3, MD_i2, MDLen);
+ memcpy(MD_i2, MD_i1, MDLen);
+ memcpy(MD_i1, MD_i, MDLen);
+ }
+
+ /* seed = MD_i */
+ memcpy(seed, MD_i, MDLen);
+
+ sprintf(buf, "COUNT = %d\n", j);
+ fputs(buf, resp);
+
+ /* output MD_i */
+ fputs("MD = ", resp);
+ to_hex_str(buf, MD_i, MDLen);
+ fputs(buf, resp);
+ fputc('\n', resp);
+ }
+
+ return SECSuccess;
+}
+
+/*
+ * Perform the SHA Tests.
+ *
+ * reqfn is the pathname of the input REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+sha_test(char *reqfn)
+{
+ unsigned int i, j;
+ unsigned int MDlen = 0; /* the length of the Message Digest in Bytes */
+ unsigned int msgLen = 0; /* the length of the input Message in Bytes */
+ unsigned char *msg = NULL; /* holds the message to digest.*/
+ size_t bufSize = 256 * 128; /*MAX buffer size */
+ char *buf = NULL; /* holds one line from the input REQUEST file.*/
+ unsigned char seed[HASH_LENGTH_MAX]; /* max size of seed 64 bytes */
+ unsigned char MD[HASH_LENGTH_MAX]; /* message digest */
+
+ FILE *req = NULL; /* input stream from the REQUEST file */
+ FILE *resp; /* output stream to the RESPONSE file */
+
+ buf = PORT_ZAlloc(bufSize);
+ if (buf == NULL) {
+ goto loser;
+ }
+
+ /* zeroize the variables for the test with this data set */
+ memset(seed, 0, sizeof seed);
+
+ req = fopen(reqfn, "r");
+ resp = stdout;
+ while (fgets(buf, bufSize, req) != NULL) {
+
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, resp);
+ continue;
+ }
+ /* [L = Length of the Message Digest and sha_type */
+ if (buf[0] == '[') {
+ if (strncmp(&buf[1], "L ", 1) == 0) {
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ MDlen = atoi(&buf[i]);
+ fputs(buf, resp);
+ continue;
+ }
+ }
+ /* Len = Length of the Input Message Length ... */
+ if (strncmp(buf, "Len", 3) == 0) {
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ if (msg) {
+ PORT_ZFree(msg, msgLen);
+ msg = NULL;
+ }
+ msgLen = atoi(&buf[i]); /* in bits */
+ if (msgLen % 8 != 0) {
+ fprintf(stderr, "SHA tests are incorrectly configured for "
+ "BIT oriented implementations\n");
+ goto loser;
+ }
+ msgLen = msgLen / 8; /* convert to bytes */
+ fputs(buf, resp);
+ msg = PORT_ZAlloc(msgLen);
+ if (msg == NULL && msgLen != 0) {
+ goto loser;
+ }
+ continue;
+ }
+ /* MSG = ... */
+ if (strncmp(buf, "Msg", 3) == 0) {
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < msgLen; i += 2, j++) {
+ hex_to_byteval(&buf[i], &msg[j]);
+ }
+ fputs(buf, resp);
+ /* calculate the Message Digest */
+ memset(MD, 0, sizeof MD);
+ if (sha_calcMD(MD, MDlen,
+ msg, msgLen) != SECSuccess) {
+ goto loser;
+ }
+
+ fputs("MD = ", resp);
+ to_hex_str(buf, MD, MDlen);
+ fputs(buf, resp);
+ fputc('\n', resp);
+
+ continue;
+ }
+ /* Seed = ... */
+ if (strncmp(buf, "Seed", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < sizeof seed; i += 2, j++) {
+ hex_to_byteval(&buf[i], &seed[j]);
+ }
+
+ fputs(buf, resp);
+ fputc('\n', resp);
+
+ /* do the Monte Carlo test */
+ if (sha_mct_test(MDlen, seed, resp) != SECSuccess) {
+ goto loser;
+ }
+
+ continue;
+ }
+ }
+loser:
+ if (req) {
+ fclose(req);
+ }
+ if (buf) {
+ PORT_ZFree(buf, bufSize);
+ }
+ if (msg) {
+ PORT_ZFree(msg, msgLen);
+ }
+}
+
+/****************************************************/
+/* HMAC SHA-X calc */
+/* hmac_computed - the computed HMAC */
+/* hmac_length - the length of the computed HMAC */
+/* secret_key - secret key to HMAC */
+/* secret_key_length - length of secret key, */
+/* message - message to HMAC */
+/* message_length - length ofthe message */
+/****************************************************/
+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)
+{
+ SECStatus hmac_status = SECFailure;
+ HMACContext *cx = NULL;
+ SECHashObject *hashObj = NULL;
+ unsigned int bytes_hashed = 0;
+
+ hashObj = (SECHashObject *)HASH_GetRawHashObject(hashAlg);
+
+ if (!hashObj)
+ return (SECFailure);
+
+ cx = HMAC_Create(hashObj, secret_key,
+ secret_key_length,
+ PR_TRUE); /* PR_TRUE for in FIPS mode */
+
+ if (cx == NULL)
+ return (SECFailure);
+
+ HMAC_Begin(cx);
+ HMAC_Update(cx, message, message_length);
+ hmac_status = HMAC_Finish(cx, hmac_computed, &bytes_hashed,
+ hmac_length);
+
+ HMAC_Destroy(cx, PR_TRUE);
+
+ return (hmac_status);
+}
+
+/*
+ * Perform the HMAC Tests.
+ *
+ * reqfn is the pathname of the input REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+hmac_test(char *reqfn)
+{
+ unsigned int i, j;
+ size_t bufSize = 400; /* MAX buffer size */
+ char *buf = NULL; /* holds one line from the input REQUEST file.*/
+ unsigned int keyLen = 0; /* Key Length */
+ unsigned char key[200]; /* key MAX size = 184 */
+ unsigned int msgLen = 128; /* the length of the input */
+ /* Message is always 128 Bytes */
+ unsigned char *msg = NULL; /* holds the message to digest.*/
+ unsigned int HMACLen = 0; /* the length of the HMAC Bytes */
+ unsigned int TLen = 0; /* the length of the requested */
+ /* truncated HMAC Bytes */
+ unsigned char HMAC[HASH_LENGTH_MAX]; /* computed HMAC */
+ unsigned char expectedHMAC[HASH_LENGTH_MAX]; /* for .fax files that have */
+ /* supplied known answer */
+ HASH_HashType hash_alg = HASH_AlgNULL; /* HMAC type */
+
+ FILE *req = NULL; /* input stream from the REQUEST file */
+ FILE *resp; /* output stream to the RESPONSE file */
+
+ buf = PORT_ZAlloc(bufSize);
+ if (buf == NULL) {
+ goto loser;
+ }
+ msg = PORT_ZAlloc(msgLen);
+ if (msg == NULL) {
+ goto loser;
+ }
+
+ req = fopen(reqfn, "r");
+ resp = stdout;
+ while (fgets(buf, bufSize, req) != NULL) {
+ if (strncmp(buf, "Mac", 3) == 0) {
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ memset(expectedHMAC, 0, HASH_LENGTH_MAX);
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &expectedHMAC[j]);
+ }
+ if (memcmp(HMAC, expectedHMAC, TLen) != 0) {
+ fprintf(stderr, "Generate failed:\n");
+ fputs(" expected=", stderr);
+ to_hex_str(buf, expectedHMAC,
+ TLen);
+ fputs(buf, stderr);
+ fputs("\n generated=", stderr);
+ to_hex_str(buf, HMAC,
+ TLen);
+ fputs(buf, stderr);
+ fputc('\n', stderr);
+ }
+ }
+
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, resp);
+ continue;
+ }
+ /* [L = Length of the MAC and HASH_type */
+ if (buf[0] == '[') {
+ if (strncmp(&buf[1], "L ", 1) == 0) {
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ /* HMACLen will get reused for Tlen */
+ HMACLen = atoi(&buf[i]);
+ hash_alg = sha_get_hashType(HMACLen * PR_BITS_PER_BYTE);
+ if (hash_alg == HASH_AlgNULL) {
+ goto loser;
+ }
+ fputs(buf, resp);
+ continue;
+ }
+ }
+ /* Count = test iteration number*/
+ if (strncmp(buf, "Count ", 5) == 0) {
+ /* count can just be put into resp file */
+ fputs(buf, resp);
+ /* zeroize the variables for the test with this data set */
+ keyLen = 0;
+ TLen = 0;
+ memset(key, 0, sizeof key);
+ memset(msg, 0, msgLen);
+ memset(HMAC, 0, sizeof HMAC);
+ continue;
+ }
+ /* KLen = Length of the Input Secret Key ... */
+ if (strncmp(buf, "Klen", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ keyLen = atoi(&buf[i]); /* in bytes */
+ fputs(buf, resp);
+ continue;
+ }
+ /* key = the secret key for the key to MAC */
+ if (strncmp(buf, "Key", 3) == 0) {
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < keyLen; i += 2, j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ fputs(buf, resp);
+ }
+ /* TLen = Length of the calculated HMAC */
+ if (strncmp(buf, "Tlen", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ TLen = atoi(&buf[i]); /* in bytes */
+ fputs(buf, resp);
+ continue;
+ }
+ /* MSG = to HMAC always 128 bytes for these tests */
+ if (strncmp(buf, "Msg", 3) == 0) {
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < msgLen; i += 2, j++) {
+ hex_to_byteval(&buf[i], &msg[j]);
+ }
+ fputs(buf, resp);
+ /* calculate the HMAC and output */
+ if (hmac_calc(HMAC, HMACLen, key, keyLen,
+ msg, msgLen, hash_alg) != SECSuccess) {
+ goto loser;
+ }
+ fputs("Mac = ", resp);
+ to_hex_str(buf, HMAC, TLen);
+ fputs(buf, resp);
+ fputc('\n', resp);
+ continue;
+ }
+ }
+loser:
+ if (req) {
+ fclose(req);
+ }
+ if (buf) {
+ PORT_ZFree(buf, bufSize);
+ }
+ if (msg) {
+ PORT_ZFree(msg, msgLen);
+ }
+}
+
+/*
+ * Perform the DSA Key Pair Generation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+dsa_keypair_test(char *reqfn)
+{
+ char buf[800]; /* holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * 800 to hold (384 public key (x2 for HEX) + 1'\n'
+ */
+ FILE *dsareq; /* input stream from the REQUEST file */
+ FILE *dsaresp; /* output stream to the RESPONSE file */
+ int count;
+ int N;
+ int L;
+ int i;
+ PQGParams *pqg = NULL;
+ PQGVerify *vfy = NULL;
+ PRBool use_dsa1 = PR_FALSE;
+ int keySizeIndex; /* index for valid key sizes */
+
+ dsareq = fopen(reqfn, "r");
+ dsaresp = stdout;
+ while (fgets(buf, sizeof buf, dsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* [Mod = x] */
+ if (buf[0] == '[') {
+ if (pqg != NULL) {
+ PQG_DestroyParams(pqg);
+ pqg = NULL;
+ }
+ if (vfy != NULL) {
+ PQG_DestroyVerify(vfy);
+ vfy = NULL;
+ }
+
+ if (sscanf(buf, "[mod = L=%d, N=%d]", &L, &N) != 2) {
+ use_dsa1 = PR_TRUE;
+ if (sscanf(buf, "[mod = %d]", &L) != 1) {
+ goto loser;
+ }
+ }
+ fputs(buf, dsaresp);
+ fputc('\n', dsaresp);
+
+ if (use_dsa1) {
+ /*************************************************************
+ * PQG_ParamGenSeedLen doesn't take a key size, it takes an
+ * index that points to a valid key size.
+ */
+ keySizeIndex = PQG_PBITS_TO_INDEX(L);
+ if (keySizeIndex == -1 || L < 512 || L > 1024) {
+ fprintf(dsaresp,
+ "DSA key size must be a multiple of 64 between 512 "
+ "and 1024, inclusive");
+ goto loser;
+ }
+
+ /* Generate the parameters P, Q, and G */
+ if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
+ &pqg, &vfy) !=
+ SECSuccess) {
+ fprintf(dsaresp,
+ "ERROR: Unable to generate PQG parameters");
+ goto loser;
+ }
+ } else {
+ if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
+ fprintf(dsaresp,
+ "ERROR: Unable to generate PQG parameters");
+ goto loser;
+ }
+ }
+
+ /* output P, Q, and G */
+ to_hex_str(buf, pqg->prime.data, pqg->prime.len);
+ fprintf(dsaresp, "P = %s\n", buf);
+ to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
+ fprintf(dsaresp, "Q = %s\n", buf);
+ to_hex_str(buf, pqg->base.data, pqg->base.len);
+ fprintf(dsaresp, "G = %s\n\n", buf);
+ continue;
+ }
+ /* N = ...*/
+ if (buf[0] == 'N') {
+
+ if (sscanf(buf, "N = %d", &count) != 1) {
+ goto loser;
+ }
+ /* Generate a DSA key, and output the key pair for N times */
+ for (i = 0; i < count; i++) {
+ DSAPrivateKey *dsakey = NULL;
+ if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
+ fprintf(dsaresp, "ERROR: Unable to generate DSA key");
+ goto loser;
+ }
+ to_hex_str(buf, dsakey->privateValue.data,
+ dsakey->privateValue.len);
+ fprintf(dsaresp, "X = %s\n", buf);
+ to_hex_str(buf, dsakey->publicValue.data,
+ dsakey->publicValue.len);
+ fprintf(dsaresp, "Y = %s\n\n", buf);
+ PORT_FreeArena(dsakey->params.arena, PR_TRUE);
+ dsakey = NULL;
+ }
+ continue;
+ }
+ }
+loser:
+ fclose(dsareq);
+}
+
+/*
+ * pqg generation type
+ */
+typedef enum {
+ FIPS186_1, /* Generate/Verify P,Q & G according to FIPS 186-1 */
+ A_1_2_1, /* Generate Provable P & Q */
+ A_1_1_3, /* Verify Probable P & Q */
+ A_1_2_2, /* Verify Provable P & Q */
+ A_2_1, /* Generate Unverifiable G */
+ A_2_2, /* Assure Unverifiable G */
+ A_2_3, /* Generate Verifiable G */
+ A_2_4 /* Verify Verifiable G */
+} dsa_pqg_type;
+
+/*
+ * Perform the DSA Domain Parameter Validation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+dsa_pqgver_test(char *reqfn)
+{
+ char buf[800]; /* holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * 800 to hold (384 public key (x2 for HEX) + P = ...
+ */
+ FILE *dsareq; /* input stream from the REQUEST file */
+ FILE *dsaresp; /* output stream to the RESPONSE file */
+ int N;
+ int L;
+ unsigned int i, j;
+ PQGParams pqg;
+ PQGVerify vfy;
+ unsigned int pghSize = 0; /* size for p, g, and h */
+ dsa_pqg_type type = FIPS186_1;
+
+ dsareq = fopen(reqfn, "r");
+ dsaresp = stdout;
+ memset(&pqg, 0, sizeof(pqg));
+ memset(&vfy, 0, sizeof(vfy));
+
+ while (fgets(buf, sizeof buf, dsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* [A.xxxxx ] */
+ if (buf[0] == '[' && buf[1] == 'A') {
+
+ if (strncmp(&buf[1], "A.1.1.3", 7) == 0) {
+ type = A_1_1_3;
+ } else if (strncmp(&buf[1], "A.2.2", 5) == 0) {
+ type = A_2_2;
+ } else if (strncmp(&buf[1], "A.2.4", 5) == 0) {
+ type = A_2_4;
+ } else if (strncmp(&buf[1], "A.1.2.2", 7) == 0) {
+ type = A_1_2_2;
+ /* validate our output from PQGGEN */
+ } else if (strncmp(&buf[1], "A.1.1.2", 7) == 0) {
+ type = A_2_4; /* validate PQ and G together */
+ } else {
+ fprintf(stderr, "Unknown dsa ver test %s\n", &buf[1]);
+ exit(1);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* [Mod = x] */
+ if (buf[0] == '[') {
+
+ if (type == FIPS186_1) {
+ N = 160;
+ if (sscanf(buf, "[mod = %d]", &L) != 1) {
+ goto loser;
+ }
+ } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
+ goto loser;
+ }
+
+ if (pqg.prime.data) { /* P */
+ SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
+ }
+ if (pqg.subPrime.data) { /* Q */
+ SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
+ }
+ if (pqg.base.data) { /* G */
+ SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
+ }
+ if (vfy.seed.data) { /* seed */
+ SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
+ }
+ if (vfy.h.data) { /* H */
+ SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
+ }
+
+ fputs(buf, dsaresp);
+
+ /*calculate the size of p, g, and h then allocate items */
+ pghSize = L / 8;
+
+ pqg.base.data = vfy.h.data = NULL;
+ vfy.seed.len = pqg.base.len = vfy.h.len = 0;
+ SECITEM_AllocItem(NULL, &pqg.prime, pghSize);
+ SECITEM_AllocItem(NULL, &vfy.seed, pghSize * 3);
+ if (type == A_2_2) {
+ SECITEM_AllocItem(NULL, &vfy.h, pghSize);
+ vfy.h.len = pghSize;
+ } else if (type == A_2_4) {
+ SECITEM_AllocItem(NULL, &vfy.h, 1);
+ vfy.h.len = 1;
+ }
+ pqg.prime.len = pghSize;
+ /* q is always N bits */
+ SECITEM_AllocItem(NULL, &pqg.subPrime, N / 8);
+ pqg.subPrime.len = N / 8;
+ vfy.counter = -1;
+
+ continue;
+ }
+ /* P = ... */
+ if (buf[0] == 'P') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < pqg.prime.len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &pqg.prime.data[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* Q = ... */
+ if (buf[0] == 'Q') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < pqg.subPrime.len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* G = ... */
+ if (buf[0] == 'G') {
+ i = 1;
+ if (pqg.base.data) {
+ SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
+ }
+ SECITEM_AllocItem(NULL, &pqg.base, pghSize);
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < pqg.base.len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &pqg.base.data[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* Seed = ... or domain_parameter_seed = ... */
+ if (strncmp(buf, "Seed", 4) == 0) {
+ i = 4;
+ } else if (strncmp(buf, "domain_parameter_seed", 21) == 0) {
+ i = 21;
+ } else if (strncmp(buf, "firstseed", 9) == 0) {
+ i = 9;
+ } else {
+ i = 0;
+ }
+ if (i) {
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &vfy.seed.data[j]);
+ }
+ vfy.seed.len = j;
+
+ fputs(buf, dsaresp);
+ if (type == A_2_4) {
+ SECStatus result;
+
+ /* Verify the Parameters */
+ SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (result == SECSuccess) {
+ fprintf(dsaresp, "Result = P\n");
+ } else {
+ fprintf(dsaresp, "Result = F\n");
+ }
+ }
+ continue;
+ }
+ if ((strncmp(buf, "pseed", 5) == 0) ||
+ (strncmp(buf, "qseed", 5) == 0)) {
+ i = 5;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = vfy.seed.len; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &vfy.seed.data[j]);
+ }
+ vfy.seed.len = j;
+ fputs(buf, dsaresp);
+
+ continue;
+ }
+ if (strncmp(buf, "index", 4) == 0) {
+ i = 5;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ hex_to_byteval(&buf[i], &vfy.h.data[0]);
+ vfy.h.len = 1;
+ fputs(buf, dsaresp);
+ }
+
+ /* c = ... or counter=*/
+ if (buf[0] == 'c') {
+ if (strncmp(buf, "counter", 7) == 0) {
+ if (sscanf(buf, "counter = %u", &vfy.counter) != 1) {
+ goto loser;
+ }
+ } else {
+ if (sscanf(buf, "c = %u", &vfy.counter) != 1) {
+ goto loser;
+ }
+ }
+
+ fputs(buf, dsaresp);
+ if (type == A_1_1_3) {
+ SECStatus result;
+ /* only verify P and Q, we have everything now. do it */
+ SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (result == SECSuccess) {
+ fprintf(dsaresp, "Result = P\n");
+ } else {
+ fprintf(dsaresp, "Result = F\n");
+ }
+ fprintf(dsaresp, "\n");
+ }
+ continue;
+ }
+ if (strncmp(buf, "pgen_counter", 12) == 0) {
+ if (sscanf(buf, "pgen_counter = %u", &vfy.counter) != 1) {
+ goto loser;
+ }
+ fputs(buf, dsaresp);
+ continue;
+ }
+ if (strncmp(buf, "qgen_counter", 12) == 0) {
+ fputs(buf, dsaresp);
+ if (type == A_1_2_2) {
+ SECStatus result;
+ /* only verify P and Q, we have everything now. do it */
+ SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (result == SECSuccess) {
+ fprintf(dsaresp, "Result = P\n");
+ } else {
+ fprintf(dsaresp, "Result = F\n");
+ }
+ fprintf(dsaresp, "\n");
+ }
+ continue;
+ }
+ /* H = ... */
+ if (buf[0] == 'H') {
+ SECStatus rv, result = SECFailure;
+
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &vfy.h.data[j]);
+ }
+ vfy.h.len = j;
+ fputs(buf, dsaresp);
+
+ /* this should be a byte value. Remove the leading zeros. If
+ * it doesn't reduce to a byte, PQG_VerifyParams will catch it
+ if (type == A_2_2) {
+ data_save = vfy.h.data;
+ while(vfy.h.data[0] && (vfy.h.len > 1)) {
+ vfy.h.data++;
+ vfy.h.len--;
+ }
+ } */
+
+ /* Verify the Parameters */
+ rv = PQG_VerifyParams(&pqg, &vfy, &result);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (result == SECSuccess) {
+ fprintf(dsaresp, "Result = P\n");
+ } else {
+ fprintf(dsaresp, "Result = F\n");
+ }
+ fprintf(dsaresp, "\n");
+ continue;
+ }
+ }
+loser:
+ fclose(dsareq);
+ if (pqg.prime.data) { /* P */
+ SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
+ }
+ if (pqg.subPrime.data) { /* Q */
+ SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
+ }
+ if (pqg.base.data) { /* G */
+ SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
+ }
+ if (vfy.seed.data) { /* seed */
+ SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
+ }
+ if (vfy.h.data) { /* H */
+ SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
+ }
+}
+
+/*
+ * Perform the DSA Public Key Validation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+dsa_pqggen_test(char *reqfn)
+{
+ char buf[800]; /* holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * 800 to hold seed = (384 public key (x2 for HEX)
+ */
+ FILE *dsareq; /* input stream from the REQUEST file */
+ FILE *dsaresp; /* output stream to the RESPONSE file */
+ int count; /* number of times to generate parameters */
+ int N;
+ int L;
+ int i;
+ unsigned int j;
+ int output_g = 1;
+ PQGParams *pqg = NULL;
+ PQGVerify *vfy = NULL;
+ unsigned int keySizeIndex = 0;
+ dsa_pqg_type type = FIPS186_1;
+
+ dsareq = fopen(reqfn, "r");
+ dsaresp = stdout;
+ while (fgets(buf, sizeof buf, dsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* [A.xxxxx ] */
+ if (buf[0] == '[' && buf[1] == 'A') {
+ if (strncmp(&buf[1], "A.1.1.2", 7) == 0) {
+ fprintf(stderr, "NSS does Generate Probablistic Primes\n");
+ exit(1);
+ } else if (strncmp(&buf[1], "A.2.1", 5) == 0) {
+ type = A_1_2_1;
+ output_g = 1;
+ exit(1);
+ } else if (strncmp(&buf[1], "A.2.3", 5) == 0) {
+ fprintf(stderr, "NSS only Generates G with P&Q\n");
+ exit(1);
+ } else if (strncmp(&buf[1], "A.1.2.1", 7) == 0) {
+ type = A_1_2_1;
+ output_g = 0;
+ } else {
+ fprintf(stderr, "Unknown dsa pqggen test %s\n", &buf[1]);
+ exit(1);
+ }
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* [Mod = ... ] */
+ if (buf[0] == '[') {
+
+ if (type == FIPS186_1) {
+ N = 160;
+ if (sscanf(buf, "[mod = %d]", &L) != 1) {
+ goto loser;
+ }
+ } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
+ goto loser;
+ }
+
+ fputs(buf, dsaresp);
+ fputc('\n', dsaresp);
+
+ if (type == FIPS186_1) {
+ /************************************************************
+ * PQG_ParamGenSeedLen doesn't take a key size, it takes an
+ * index that points to a valid key size.
+ */
+ keySizeIndex = PQG_PBITS_TO_INDEX(L);
+ if (keySizeIndex == -1 || L < 512 || L > 1024) {
+ fprintf(dsaresp,
+ "DSA key size must be a multiple of 64 between 512 "
+ "and 1024, inclusive");
+ goto loser;
+ }
+ }
+ continue;
+ }
+ /* N = ... */
+ if (buf[0] == 'N') {
+ if (strncmp(buf, "Num", 3) == 0) {
+ if (sscanf(buf, "Num = %d", &count) != 1) {
+ goto loser;
+ }
+ } else if (sscanf(buf, "N = %d", &count) != 1) {
+ goto loser;
+ }
+ for (i = 0; i < count; i++) {
+ SECStatus rv;
+
+ if (type == FIPS186_1) {
+ rv = PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
+ &pqg, &vfy);
+ } else {
+ rv = PQG_ParamGenV2(L, N, N, &pqg, &vfy);
+ }
+ if (rv != SECSuccess) {
+ fprintf(dsaresp,
+ "ERROR: Unable to generate PQG parameters");
+ goto loser;
+ }
+ to_hex_str(buf, pqg->prime.data, pqg->prime.len);
+ fprintf(dsaresp, "P = %s\n", buf);
+ to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
+ fprintf(dsaresp, "Q = %s\n", buf);
+ if (output_g) {
+ to_hex_str(buf, pqg->base.data, pqg->base.len);
+ fprintf(dsaresp, "G = %s\n", buf);
+ }
+ if (type == FIPS186_1) {
+ to_hex_str(buf, vfy->seed.data, vfy->seed.len);
+ fprintf(dsaresp, "Seed = %s\n", buf);
+ fprintf(dsaresp, "c = %d\n", vfy->counter);
+ to_hex_str(buf, vfy->h.data, vfy->h.len);
+ fputs("H = ", dsaresp);
+ for (j = vfy->h.len; j < pqg->prime.len; j++) {
+ fprintf(dsaresp, "00");
+ }
+ fprintf(dsaresp, "%s\n", buf);
+ } else {
+ unsigned int seedlen = vfy->seed.len / 2;
+ unsigned int pgen_counter = vfy->counter >> 16;
+ unsigned int qgen_counter = vfy->counter & 0xffff;
+ /*fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]); */
+ to_hex_str(buf, vfy->seed.data, seedlen);
+ fprintf(dsaresp, "pseed = %s\n", buf);
+ to_hex_str(buf, vfy->seed.data + seedlen, seedlen);
+ fprintf(dsaresp, "qseed = %s\n", buf);
+ fprintf(dsaresp, "pgen_counter = %d\n", pgen_counter);
+ fprintf(dsaresp, "qgen_counter = %d\n", qgen_counter);
+ if (output_g) {
+ to_hex_str(buf, vfy->seed.data, vfy->seed.len);
+ fprintf(dsaresp, "domain_parameter_seed = %s\n", buf);
+ fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]);
+ }
+ }
+ fputc('\n', dsaresp);
+ if (pqg != NULL) {
+ PQG_DestroyParams(pqg);
+ pqg = NULL;
+ }
+ if (vfy != NULL) {
+ PQG_DestroyVerify(vfy);
+ vfy = NULL;
+ }
+ }
+
+ continue;
+ }
+ }
+loser:
+ fclose(dsareq);
+ if (pqg != NULL) {
+ PQG_DestroyParams(pqg);
+ }
+ if (vfy != NULL) {
+ PQG_DestroyVerify(vfy);
+ }
+}
+
+/*
+ * Perform the DSA Signature Generation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+dsa_siggen_test(char *reqfn)
+{
+ char buf[800]; /* holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * max for Msg = ....
+ */
+ FILE *dsareq; /* input stream from the REQUEST file */
+ FILE *dsaresp; /* output stream to the RESPONSE file */
+ int modulus;
+ int L;
+ int N;
+ int i, j;
+ PRBool use_dsa1 = PR_FALSE;
+ PQGParams *pqg = NULL;
+ PQGVerify *vfy = NULL;
+ DSAPrivateKey *dsakey = NULL;
+ int keySizeIndex; /* index for valid key sizes */
+ unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */
+ unsigned char sig[DSA_MAX_SIGNATURE_LEN];
+ SECItem digest, signature;
+ HASH_HashType hashType = HASH_AlgNULL;
+ int hashNum = 0;
+
+ dsareq = fopen(reqfn, "r");
+ dsaresp = stdout;
+
+ while (fgets(buf, sizeof buf, dsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* [Mod = x] */
+ if (buf[0] == '[') {
+ if (pqg != NULL) {
+ PQG_DestroyParams(pqg);
+ pqg = NULL;
+ }
+ if (vfy != NULL) {
+ PQG_DestroyVerify(vfy);
+ vfy = NULL;
+ }
+ if (dsakey != NULL) {
+ PORT_FreeArena(dsakey->params.arena, PR_TRUE);
+ dsakey = NULL;
+ }
+
+ if (sscanf(buf, "[mod = L=%d, N=%d, SHA-%d]", &L, &N,
+ &hashNum) != 3) {
+ use_dsa1 = PR_TRUE;
+ hashNum = 1;
+ if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
+ goto loser;
+ }
+ }
+ fputs(buf, dsaresp);
+ fputc('\n', dsaresp);
+
+ /****************************************************************
+ * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
+ * that points to a valid key size.
+ */
+ if (use_dsa1) {
+ keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
+ if (keySizeIndex == -1 || modulus < 512 || modulus > 1024) {
+ fprintf(dsaresp,
+ "DSA key size must be a multiple of 64 between 512 "
+ "and 1024, inclusive");
+ goto loser;
+ }
+ /* Generate PQG and output PQG */
+ if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
+ &pqg, &vfy) !=
+ SECSuccess) {
+ fprintf(dsaresp,
+ "ERROR: Unable to generate PQG parameters");
+ goto loser;
+ }
+ } else {
+ if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
+ fprintf(dsaresp,
+ "ERROR: Unable to generate PQG parameters");
+ goto loser;
+ }
+ }
+ to_hex_str(buf, pqg->prime.data, pqg->prime.len);
+ fprintf(dsaresp, "P = %s\n", buf);
+ to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
+ fprintf(dsaresp, "Q = %s\n", buf);
+ to_hex_str(buf, pqg->base.data, pqg->base.len);
+ fprintf(dsaresp, "G = %s\n", buf);
+
+ /* create DSA Key */
+ if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
+ fprintf(dsaresp, "ERROR: Unable to generate DSA key");
+ goto loser;
+ }
+
+ hashType = sha_get_hashType(hashNum);
+ if (hashType == HASH_AlgNULL) {
+ fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)", hashNum);
+ goto loser;
+ }
+ continue;
+ }
+
+ /* Msg = ... */
+ if (strncmp(buf, "Msg", 3) == 0) {
+ unsigned char msg[128]; /* MAX msg 128 */
+ unsigned int len = 0;
+
+ if (hashType == HASH_AlgNULL) {
+ fprintf(dsaresp, "ERROR: Hash Alg not set");
+ goto loser;
+ }
+
+ memset(hashBuf, 0, sizeof hashBuf);
+ memset(sig, 0, sizeof sig);
+
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &msg[j]);
+ }
+ if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) {
+ fprintf(dsaresp, "ERROR: Unable to generate SHA% digest",
+ hashNum);
+ goto loser;
+ }
+
+ digest.type = siBuffer;
+ digest.data = hashBuf;
+ digest.len = fips_hashLen(hashType);
+ signature.type = siBuffer;
+ signature.data = sig;
+ signature.len = sizeof sig;
+
+ if (DSA_SignDigest(dsakey, &signature, &digest) != SECSuccess) {
+ fprintf(dsaresp, "ERROR: Unable to generate DSA signature");
+ goto loser;
+ }
+ len = signature.len;
+ if (len % 2 != 0) {
+ goto loser;
+ }
+ len = len / 2;
+
+ /* output the orginal Msg, and generated Y, R, and S */
+ fputs(buf, dsaresp);
+ to_hex_str(buf, dsakey->publicValue.data,
+ dsakey->publicValue.len);
+ fprintf(dsaresp, "Y = %s\n", buf);
+ to_hex_str(buf, &signature.data[0], len);
+ fprintf(dsaresp, "R = %s\n", buf);
+ to_hex_str(buf, &signature.data[len], len);
+ fprintf(dsaresp, "S = %s\n", buf);
+ fputc('\n', dsaresp);
+ continue;
+ }
+ }
+loser:
+ fclose(dsareq);
+ if (pqg != NULL) {
+ PQG_DestroyParams(pqg);
+ pqg = NULL;
+ }
+ if (vfy != NULL) {
+ PQG_DestroyVerify(vfy);
+ vfy = NULL;
+ }
+ if (dsakey) {
+ PORT_FreeArena(dsakey->params.arena, PR_TRUE);
+ dsakey = NULL;
+ }
+}
+
+/*
+ * Perform the DSA Signature Verification Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+dsa_sigver_test(char *reqfn)
+{
+ char buf[800]; /* holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * max for Msg = ....
+ */
+ FILE *dsareq; /* input stream from the REQUEST file */
+ FILE *dsaresp; /* output stream to the RESPONSE file */
+ int L;
+ int N;
+ unsigned int i, j;
+ SECItem digest, signature;
+ DSAPublicKey pubkey;
+ unsigned int pgySize; /* size for p, g, and y */
+ unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */
+ unsigned char sig[DSA_MAX_SIGNATURE_LEN];
+ HASH_HashType hashType = HASH_AlgNULL;
+ int hashNum = 0;
+
+ dsareq = fopen(reqfn, "r");
+ dsaresp = stdout;
+ memset(&pubkey, 0, sizeof(pubkey));
+
+ while (fgets(buf, sizeof buf, dsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* [Mod = x] */
+ if (buf[0] == '[') {
+
+ if (sscanf(buf, "[mod = L=%d, N=%d, SHA-%d]", &L, &N,
+ &hashNum) != 3) {
+ N = 160;
+ hashNum = 1;
+ if (sscanf(buf, "[mod = %d]", &L) != 1) {
+ goto loser;
+ }
+ }
+
+ if (pubkey.params.prime.data) { /* P */
+ SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
+ }
+ if (pubkey.params.subPrime.data) { /* Q */
+ SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
+ }
+ if (pubkey.params.base.data) { /* G */
+ SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
+ }
+ if (pubkey.publicValue.data) { /* Y */
+ SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
+ }
+ fputs(buf, dsaresp);
+
+ /* calculate the size of p, g, and y then allocate items */
+ pgySize = L / 8;
+ SECITEM_AllocItem(NULL, &pubkey.params.prime, pgySize);
+ SECITEM_AllocItem(NULL, &pubkey.params.base, pgySize);
+ SECITEM_AllocItem(NULL, &pubkey.publicValue, pgySize);
+ pubkey.params.prime.len = pubkey.params.base.len = pgySize;
+ pubkey.publicValue.len = pgySize;
+
+ /* q always N/8 bytes */
+ SECITEM_AllocItem(NULL, &pubkey.params.subPrime, N / 8);
+ pubkey.params.subPrime.len = N / 8;
+
+ hashType = sha_get_hashType(hashNum);
+ if (hashType == HASH_AlgNULL) {
+ fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)", hashNum);
+ goto loser;
+ }
+
+ continue;
+ }
+ /* P = ... */
+ if (buf[0] == 'P') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ memset(pubkey.params.prime.data, 0, pubkey.params.prime.len);
+ for (j = 0; j < pubkey.params.prime.len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &pubkey.params.prime.data[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* Q = ... */
+ if (buf[0] == 'Q') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ memset(pubkey.params.subPrime.data, 0, pubkey.params.subPrime.len);
+ for (j = 0; j < pubkey.params.subPrime.len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &pubkey.params.subPrime.data[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* G = ... */
+ if (buf[0] == 'G') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ memset(pubkey.params.base.data, 0, pubkey.params.base.len);
+ for (j = 0; j < pubkey.params.base.len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &pubkey.params.base.data[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* Msg = ... */
+ if (strncmp(buf, "Msg", 3) == 0) {
+ unsigned char msg[128]; /* MAX msg 128 */
+ memset(hashBuf, 0, sizeof hashBuf);
+
+ if (hashType == HASH_AlgNULL) {
+ fprintf(dsaresp, "ERROR: Hash Alg not set");
+ goto loser;
+ }
+
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &msg[j]);
+ }
+ if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) {
+ fprintf(dsaresp, "ERROR: Unable to generate SHA-%d digest",
+ hashNum);
+ goto loser;
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* Y = ... */
+ if (buf[0] == 'Y') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ memset(pubkey.publicValue.data, 0, pubkey.params.subPrime.len);
+ for (j = 0; j < pubkey.publicValue.len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &pubkey.publicValue.data[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* R = ... */
+ if (buf[0] == 'R') {
+ memset(sig, 0, sizeof sig);
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < pubkey.params.subPrime.len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &sig[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* S = ... */
+ if (buf[0] == 'S') {
+ if (hashType == HASH_AlgNULL) {
+ fprintf(dsaresp, "ERROR: Hash Alg not set");
+ goto loser;
+ }
+
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = pubkey.params.subPrime.len;
+ j < pubkey.params.subPrime.len * 2; i += 2, j++) {
+ hex_to_byteval(&buf[i], &sig[j]);
+ }
+ fputs(buf, dsaresp);
+
+ digest.type = siBuffer;
+ digest.data = hashBuf;
+ digest.len = fips_hashLen(hashType);
+ signature.type = siBuffer;
+ signature.data = sig;
+ signature.len = pubkey.params.subPrime.len * 2;
+
+ if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) {
+ fprintf(dsaresp, "Result = P\n");
+ } else {
+ fprintf(dsaresp, "Result = F\n");
+ }
+ fprintf(dsaresp, "\n");
+ continue;
+ }
+ }
+loser:
+ fclose(dsareq);
+ if (pubkey.params.prime.data) { /* P */
+ SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
+ }
+ if (pubkey.params.subPrime.data) { /* Q */
+ SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
+ }
+ if (pubkey.params.base.data) { /* G */
+ SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
+ }
+ if (pubkey.publicValue.data) { /* Y */
+ SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
+ }
+}
+
+static void
+pad(unsigned char *buf, int pad_len, unsigned char *src, int src_len)
+{
+ int offset = 0;
+ /* this shouldn't happen, fail right away rather than produce bad output */
+ if (pad_len < src_len) {
+ fprintf(stderr, "data bigger than expected! %d > %d\n", src_len, pad_len);
+ exit(1);
+ }
+
+ offset = pad_len - src_len;
+ memset(buf, 0, offset);
+ memcpy(buf + offset, src, src_len);
+ return;
+}
+
+/*
+ * Perform the DSA Key Pair Generation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+rsa_keypair_test(char *reqfn)
+{
+ char buf[800]; /* holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * 800 to hold (384 public key (x2 for HEX) + 1'\n'
+ */
+ unsigned char buf2[400]; /* can't need more then 1/2 buf length */
+ FILE *rsareq; /* input stream from the REQUEST file */
+ FILE *rsaresp; /* output stream to the RESPONSE file */
+ int count;
+ int i;
+ int keySize = 1; /* key size in bits*/
+ int len = 0; /* key size in bytes */
+ int len2 = 0; /* key size in bytes/2 (prime size) */
+ SECItem e;
+ unsigned char default_e[] = { 0x1, 0x0, 0x1 };
+
+ e.data = default_e;
+ e.len = sizeof(default_e);
+
+ rsareq = fopen(reqfn, "r");
+ rsaresp = stdout;
+ while (fgets(buf, sizeof buf, rsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, rsaresp);
+ continue;
+ }
+
+ /* [Mod = x] */
+ if (buf[0] == '[') {
+ if (buf[1] == 'm') {
+ if (sscanf(buf, "[mod = %d]", &keySize) != 1) {
+ goto loser;
+ }
+ len = keySize / 8;
+ len2 = keySize / 16;
+ }
+ fputs(buf, rsaresp);
+ continue;
+ }
+ /* N = ...*/
+ if (buf[0] == 'N') {
+
+ if (sscanf(buf, "N = %d", &count) != 1) {
+ goto loser;
+ }
+
+ /* Generate a DSA key, and output the key pair for N times */
+ for (i = 0; i < count; i++) {
+ RSAPrivateKey *rsakey = NULL;
+ if ((rsakey = RSA_NewKey(keySize, &e)) == NULL) {
+ fprintf(rsaresp, "ERROR: Unable to generate RSA key");
+ goto loser;
+ }
+ pad(buf2, len, rsakey->publicExponent.data,
+ rsakey->publicExponent.len);
+ to_hex_str(buf, buf2, len);
+ fprintf(rsaresp, "e = %s\n", buf);
+ pad(buf2, len2, rsakey->prime1.data,
+ rsakey->prime1.len);
+ to_hex_str(buf, buf2, len2);
+ fprintf(rsaresp, "p = %s\n", buf);
+ pad(buf2, len2, rsakey->prime2.data,
+ rsakey->prime2.len);
+ to_hex_str(buf, buf2, len2);
+ fprintf(rsaresp, "q = %s\n", buf);
+ pad(buf2, len, rsakey->modulus.data,
+ rsakey->modulus.len);
+ to_hex_str(buf, buf2, len);
+ fprintf(rsaresp, "n = %s\n", buf);
+ pad(buf2, len, rsakey->privateExponent.data,
+ rsakey->privateExponent.len);
+ to_hex_str(buf, buf2, len);
+ fprintf(rsaresp, "d = %s\n", buf);
+ fprintf(rsaresp, "\n");
+ PORT_FreeArena(rsakey->arena, PR_TRUE);
+ rsakey = NULL;
+ }
+ continue;
+ }
+ }
+loser:
+ fclose(rsareq);
+}
+
+/*
+ * Perform the RSA Signature Generation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+rsa_siggen_test(char *reqfn)
+{
+ char buf[2 * RSA_MAX_TEST_MODULUS_BYTES + 1];
+ /* buf holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * 2x for HEX output + 1 for \n
+ */
+ FILE *rsareq; /* input stream from the REQUEST file */
+ FILE *rsaresp; /* output stream to the RESPONSE file */
+ int i, j;
+ unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
+ unsigned int shaLength = 0; /* length of SHA */
+ HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
+ SECOidTag shaOid = SEC_OID_UNKNOWN;
+ int modulus; /* the Modulus size */
+ int publicExponent = DEFAULT_RSA_PUBLIC_EXPONENT;
+ SECItem pe = { 0, 0, 0 };
+ unsigned char pubEx[4];
+ int peCount = 0;
+
+ RSAPrivateKey *rsaBlapiPrivKey = NULL; /* holds RSA private and
+ * public keys */
+ RSAPublicKey *rsaBlapiPublicKey = NULL; /* hold RSA public key */
+
+ rsareq = fopen(reqfn, "r");
+ rsaresp = stdout;
+
+ /* calculate the exponent */
+ for (i = 0; i < 4; i++) {
+ if (peCount || (publicExponent &
+ ((unsigned long)0xff000000L >> (i *
+ 8)))) {
+ pubEx[peCount] =
+ (unsigned char)((publicExponent >> (3 - i) * 8) & 0xff);
+ peCount++;
+ }
+ }
+ pe.len = peCount;
+ pe.data = &pubEx[0];
+ pe.type = siBuffer;
+
+ while (fgets(buf, sizeof buf, rsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, rsaresp);
+ continue;
+ }
+
+ /* [mod = ...] */
+ if (buf[0] == '[') {
+
+ if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
+ goto loser;
+ }
+ if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
+ fprintf(rsaresp, "ERROR: modulus greater than test maximum\n");
+ goto loser;
+ }
+
+ fputs(buf, rsaresp);
+
+ if (rsaBlapiPrivKey != NULL) {
+ PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
+ rsaBlapiPrivKey = NULL;
+ rsaBlapiPublicKey = NULL;
+ }
+
+ rsaBlapiPrivKey = RSA_NewKey(modulus, &pe);
+ if (rsaBlapiPrivKey == NULL) {
+ fprintf(rsaresp, "Error unable to create RSA key\n");
+ goto loser;
+ }
+
+ to_hex_str(buf, rsaBlapiPrivKey->modulus.data,
+ rsaBlapiPrivKey->modulus.len);
+ fprintf(rsaresp, "\nn = %s\n\n", buf);
+ to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data,
+ rsaBlapiPrivKey->publicExponent.len);
+ fprintf(rsaresp, "e = %s\n", buf);
+ /* convert private key to public key. Memory
+ * is freed with private key's arena */
+ rsaBlapiPublicKey = (RSAPublicKey *)PORT_ArenaAlloc(
+ rsaBlapiPrivKey->arena,
+ sizeof(RSAPublicKey));
+
+ rsaBlapiPublicKey->modulus.len = rsaBlapiPrivKey->modulus.len;
+ rsaBlapiPublicKey->modulus.data = rsaBlapiPrivKey->modulus.data;
+ rsaBlapiPublicKey->publicExponent.len =
+ rsaBlapiPrivKey->publicExponent.len;
+ rsaBlapiPublicKey->publicExponent.data =
+ rsaBlapiPrivKey->publicExponent.data;
+ continue;
+ }
+
+ /* SHAAlg = ... */
+ if (strncmp(buf, "SHAAlg", 6) == 0) {
+ i = 6;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ /* set the SHA Algorithm */
+ if (strncmp(&buf[i], "SHA1", 4) == 0) {
+ shaAlg = HASH_AlgSHA1;
+ } else if (strncmp(&buf[i], "SHA224", 6) == 0) {
+ shaAlg = HASH_AlgSHA224;
+ } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
+ shaAlg = HASH_AlgSHA256;
+ } else if (strncmp(&buf[i], "SHA384", 6) == 0) {
+ shaAlg = HASH_AlgSHA384;
+ } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
+ shaAlg = HASH_AlgSHA512;
+ } else {
+ fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
+ goto loser;
+ }
+ fputs(buf, rsaresp);
+ continue;
+ }
+ /* Msg = ... */
+ if (strncmp(buf, "Msg", 3) == 0) {
+
+ unsigned char msg[128]; /* MAX msg 128 */
+ unsigned int rsa_bytes_signed;
+ unsigned char rsa_computed_signature[RSA_MAX_TEST_MODULUS_BYTES];
+ SECStatus rv = SECFailure;
+ NSSLOWKEYPublicKey *rsa_public_key;
+ NSSLOWKEYPrivateKey *rsa_private_key;
+ NSSLOWKEYPrivateKey low_RSA_private_key = { NULL,
+ NSSLOWKEYRSAKey };
+ NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
+ NSSLOWKEYRSAKey };
+
+ low_RSA_private_key.u.rsa = *rsaBlapiPrivKey;
+ low_RSA_public_key.u.rsa = *rsaBlapiPublicKey;
+
+ rsa_private_key = &low_RSA_private_key;
+ rsa_public_key = &low_RSA_public_key;
+
+ memset(sha, 0, sizeof sha);
+ memset(msg, 0, sizeof msg);
+ rsa_bytes_signed = 0;
+ memset(rsa_computed_signature, 0, sizeof rsa_computed_signature);
+
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]) && j < sizeof(msg); i += 2, j++) {
+ hex_to_byteval(&buf[i], &msg[j]);
+ }
+ shaLength = fips_hashLen(shaAlg);
+ if (fips_hashBuf(shaAlg, sha, msg, j) != SECSuccess) {
+ if (shaLength == 0) {
+ fprintf(rsaresp, "ERROR: SHAAlg not defined.");
+ }
+ fprintf(rsaresp, "ERROR: Unable to generate SHA%x",
+ shaLength == 160 ? 1 : shaLength);
+ goto loser;
+ }
+ shaOid = fips_hashOid(shaAlg);
+
+ /* Perform RSA signature with the RSA private key. */
+ rv = RSA_HashSign(shaOid,
+ rsa_private_key,
+ rsa_computed_signature,
+ &rsa_bytes_signed,
+ nsslowkey_PrivateModulusLen(rsa_private_key),
+ sha,
+ shaLength);
+
+ if (rv != SECSuccess) {
+ fprintf(rsaresp, "ERROR: RSA_HashSign failed");
+ goto loser;
+ }
+
+ /* Output the signature */
+ fputs(buf, rsaresp);
+ to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed);
+ fprintf(rsaresp, "S = %s\n", buf);
+
+ /* 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) {
+ fprintf(rsaresp, "ERROR: RSA_HashCheckSign failed");
+ goto loser;
+ }
+ continue;
+ }
+ }
+loser:
+ fclose(rsareq);
+
+ if (rsaBlapiPrivKey != NULL) {
+ /* frees private and public key */
+ PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
+ rsaBlapiPrivKey = NULL;
+ rsaBlapiPublicKey = NULL;
+ }
+}
+/*
+ * Perform the RSA Signature Verification Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+rsa_sigver_test(char *reqfn)
+{
+ char buf[2 * RSA_MAX_TEST_MODULUS_BYTES + 7];
+ /* buf holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * s = 2x for HEX output + 1 for \n
+ */
+ FILE *rsareq; /* input stream from the REQUEST file */
+ FILE *rsaresp; /* output stream to the RESPONSE file */
+ int i, j;
+ unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
+ unsigned int shaLength = 0; /* actual length of the digest */
+ HASH_HashType shaAlg = HASH_AlgNULL;
+ SECOidTag shaOid = SEC_OID_UNKNOWN;
+ int modulus = 0; /* the Modulus size */
+ unsigned char signature[513]; /* largest signature size + '\n' */
+ unsigned int signatureLength = 0; /* actual length of the signature */
+ PRBool keyvalid = PR_TRUE;
+
+ RSAPublicKey rsaBlapiPublicKey; /* hold RSA public key */
+
+ rsareq = fopen(reqfn, "r");
+ rsaresp = stdout;
+ memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey));
+
+ while (fgets(buf, sizeof buf, rsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, rsaresp);
+ continue;
+ }
+
+ /* [Mod = ...] */
+ if (buf[0] == '[') {
+ unsigned int flen; /* length in bytes of the field size */
+
+ if (rsaBlapiPublicKey.modulus.data) { /* n */
+ SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
+ }
+ if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
+ goto loser;
+ }
+
+ if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
+ fprintf(rsaresp, "ERROR: modulus greater than test maximum\n");
+ goto loser;
+ }
+
+ fputs(buf, rsaresp);
+
+ signatureLength = flen = modulus / 8;
+
+ SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.modulus, flen);
+ if (rsaBlapiPublicKey.modulus.data == NULL) {
+ goto loser;
+ }
+ continue;
+ }
+
+ /* n = ... modulus */
+ if (buf[0] == 'n') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ keyvalid = from_hex_str(&rsaBlapiPublicKey.modulus.data[0],
+ rsaBlapiPublicKey.modulus.len,
+ &buf[i]);
+
+ if (!keyvalid) {
+ fprintf(rsaresp, "ERROR: rsa_sigver n not valid.\n");
+ goto loser;
+ }
+ fputs(buf, rsaresp);
+ continue;
+ }
+
+ /* SHAAlg = ... */
+ if (strncmp(buf, "SHAAlg", 6) == 0) {
+ i = 6;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ /* set the SHA Algorithm */
+ if (strncmp(&buf[i], "SHA1", 4) == 0) {
+ shaAlg = HASH_AlgSHA1;
+ } else if (strncmp(&buf[i], "SHA224", 6) == 0) {
+ shaAlg = HASH_AlgSHA224;
+ } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
+ shaAlg = HASH_AlgSHA256;
+ } else if (strncmp(&buf[i], "SHA384", 6) == 0) {
+ shaAlg = HASH_AlgSHA384;
+ } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
+ shaAlg = HASH_AlgSHA512;
+ } else {
+ fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
+ goto loser;
+ }
+ fputs(buf, rsaresp);
+ continue;
+ }
+
+ /* e = ... public Key */
+ if (buf[0] == 'e') {
+ unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES];
+ unsigned char t;
+
+ memset(data, 0, sizeof data);
+
+ if (rsaBlapiPublicKey.publicExponent.data) { /* e */
+ SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
+ }
+
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ /* skip leading zero's */
+ while (isxdigit(buf[i])) {
+ hex_to_byteval(&buf[i], &t);
+ if (t == 0) {
+ i += 2;
+ } else
+ break;
+ }
+
+ /* get the exponent */
+ for (j = 0; isxdigit(buf[i]) && j < sizeof data; i += 2, j++) {
+ hex_to_byteval(&buf[i], &data[j]);
+ }
+
+ if (j == 0) {
+ j = 1;
+ } /* to handle 1 byte length exponents */
+
+ SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.publicExponent, j);
+ if (rsaBlapiPublicKey.publicExponent.data == NULL) {
+ goto loser;
+ }
+
+ for (i = 0; i < j; i++) {
+ rsaBlapiPublicKey.publicExponent.data[i] = data[i];
+ }
+
+ fputs(buf, rsaresp);
+ continue;
+ }
+
+ /* Msg = ... */
+ if (strncmp(buf, "Msg", 3) == 0) {
+ unsigned char msg[128]; /* MAX msg 128 */
+
+ memset(sha, 0, sizeof sha);
+ memset(msg, 0, sizeof msg);
+
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+
+ for (j = 0; isxdigit(buf[i]) && j < sizeof msg; i += 2, j++) {
+ hex_to_byteval(&buf[i], &msg[j]);
+ }
+
+ shaLength = fips_hashLen(shaAlg);
+ if (fips_hashBuf(shaAlg, sha, msg, j) != SECSuccess) {
+ if (shaLength == 0) {
+ fprintf(rsaresp, "ERROR: SHAAlg not defined.");
+ }
+ fprintf(rsaresp, "ERROR: Unable to generate SHA%x",
+ shaLength == 160 ? 1 : shaLength);
+ goto loser;
+ }
+
+ fputs(buf, rsaresp);
+ continue;
+ }
+
+ /* S = ... */
+ if (buf[0] == 'S') {
+ SECStatus rv = SECFailure;
+ NSSLOWKEYPublicKey *rsa_public_key;
+ NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
+ NSSLOWKEYRSAKey };
+
+ /* convert to a low RSA public key */
+ low_RSA_public_key.u.rsa = rsaBlapiPublicKey;
+ rsa_public_key = &low_RSA_public_key;
+
+ memset(signature, 0, sizeof(signature));
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+
+ for (j = 0; isxdigit(buf[i]) && j < sizeof signature; i += 2, j++) {
+ hex_to_byteval(&buf[i], &signature[j]);
+ }
+
+ signatureLength = j;
+ fputs(buf, rsaresp);
+
+ shaOid = fips_hashOid(shaAlg);
+
+ /* Perform RSA verification with the RSA public key. */
+ rv = RSA_HashCheckSign(shaOid,
+ rsa_public_key,
+ signature,
+ signatureLength,
+ sha,
+ shaLength);
+ if (rv == SECSuccess) {
+ fputs("Result = P\n", rsaresp);
+ } else {
+ fputs("Result = F\n", rsaresp);
+ }
+ continue;
+ }
+ }
+loser:
+ fclose(rsareq);
+ if (rsaBlapiPublicKey.modulus.data) { /* n */
+ SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
+ }
+ if (rsaBlapiPublicKey.publicExponent.data) { /* e */
+ SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
+ }
+}
+
+void
+tls(char *reqfn)
+{
+ char buf[256]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "XSeed = <128 hex digits>\n".
+ */
+ unsigned char *pms = NULL;
+ int pms_len;
+ unsigned char *master_secret = NULL;
+ unsigned char *key_block = NULL;
+ int key_block_len;
+ unsigned char serverHello_random[SSL3_RANDOM_LENGTH];
+ unsigned char clientHello_random[SSL3_RANDOM_LENGTH];
+ unsigned char server_random[SSL3_RANDOM_LENGTH];
+ unsigned char client_random[SSL3_RANDOM_LENGTH];
+ FILE *tlsreq = NULL; /* input stream from the REQUEST file */
+ FILE *tlsresp; /* output stream to the RESPONSE file */
+ unsigned int i, j;
+ CK_SLOT_ID slotList[10];
+ CK_SLOT_ID slotID;
+ CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
+ CK_ULONG count;
+ static const CK_C_INITIALIZE_ARGS pk11args = {
+ NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
+ (void *)"flags=readOnly,noCertDB,noModDB", NULL
+ };
+ static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
+ static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
+ static CK_BBOOL ck_true = CK_TRUE;
+ static CK_ULONG one = 1;
+ CK_ATTRIBUTE create_template[] = {
+ { CKA_VALUE, NULL, 0 },
+ { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
+ { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
+ { CKA_DERIVE, &ck_true, sizeof(ck_true) },
+ };
+ CK_ULONG create_template_count =
+ sizeof(create_template) / sizeof(create_template[0]);
+ CK_ATTRIBUTE derive_template[] = {
+ { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
+ { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
+ { CKA_DERIVE, &ck_true, sizeof(ck_true) },
+ { CKA_VALUE_LEN, &one, sizeof(one) },
+ };
+ CK_ULONG derive_template_count =
+ sizeof(derive_template) / sizeof(derive_template[0]);
+ CK_ATTRIBUTE master_template =
+ { CKA_VALUE, NULL, 0 };
+ CK_ATTRIBUTE kb1_template =
+ { CKA_VALUE, NULL, 0 };
+ CK_ATTRIBUTE kb2_template =
+ { CKA_VALUE, NULL, 0 };
+
+ CK_MECHANISM master_mech = { CKM_TLS_MASTER_KEY_DERIVE, NULL, 0 };
+ CK_MECHANISM key_block_mech = { CKM_TLS_KEY_AND_MAC_DERIVE, NULL, 0 };
+ CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params;
+ CK_SSL3_KEY_MAT_PARAMS key_block_params;
+ CK_SSL3_KEY_MAT_OUT key_material;
+ CK_RV crv;
+
+ /* set up PKCS #11 parameters */
+ master_params.pVersion = NULL;
+ master_params.RandomInfo.pClientRandom = clientHello_random;
+ master_params.RandomInfo.ulClientRandomLen = sizeof(clientHello_random);
+ master_params.RandomInfo.pServerRandom = serverHello_random;
+ master_params.RandomInfo.ulServerRandomLen = sizeof(serverHello_random);
+ master_mech.pParameter = (void *)&master_params;
+ master_mech.ulParameterLen = sizeof(master_params);
+ key_block_params.ulMacSizeInBits = 0;
+ key_block_params.ulKeySizeInBits = 0;
+ key_block_params.ulIVSizeInBits = 0;
+ key_block_params.bIsExport = PR_FALSE; /* ignored anyway for TLS mech */
+ key_block_params.RandomInfo.pClientRandom = client_random;
+ key_block_params.RandomInfo.ulClientRandomLen = sizeof(client_random);
+ key_block_params.RandomInfo.pServerRandom = server_random;
+ key_block_params.RandomInfo.ulServerRandomLen = sizeof(server_random);
+ key_block_params.pReturnedKeyMaterial = &key_material;
+ key_block_mech.pParameter = (void *)&key_block_params;
+ key_block_mech.ulParameterLen = sizeof(key_block_params);
+
+ crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
+ goto loser;
+ }
+ count = slotListCount;
+ crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
+ goto loser;
+ }
+ if ((count > slotListCount) || count < 1) {
+ fprintf(stderr,
+ "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
+ (int)count, (int)slotListCount);
+ goto loser;
+ }
+ slotID = slotList[0];
+ tlsreq = fopen(reqfn, "r");
+ tlsresp = stdout;
+ while (fgets(buf, sizeof buf, tlsreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, tlsresp);
+ continue;
+ }
+ /* [Xchange - SHA1] */
+ if (buf[0] == '[') {
+ if (strncmp(buf, "[TLS", 4) == 0) {
+ if (buf[7] == '0') {
+ master_mech.mechanism = CKM_TLS_MASTER_KEY_DERIVE;
+ key_block_mech.mechanism = CKM_TLS_KEY_AND_MAC_DERIVE;
+ } else if (buf[7] == '2') {
+ master_mech.mechanism =
+ CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256;
+ key_block_mech.mechanism =
+ CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256;
+ } else {
+ fprintf(stderr, "Unknown TLS type %x\n",
+ (unsigned int)buf[0]);
+ goto loser;
+ }
+ }
+ if (strncmp(buf, "[pre-master", 11) == 0) {
+ if (sscanf(buf, "[pre-master secret length = %d]",
+ &pms_len) != 1) {
+ goto loser;
+ }
+ pms_len = pms_len / 8;
+ pms = malloc(pms_len);
+ master_secret = malloc(pms_len);
+ create_template[0].pValue = pms;
+ create_template[0].ulValueLen = pms_len;
+ master_template.pValue = master_secret;
+ master_template.ulValueLen = pms_len;
+ }
+ if (strncmp(buf, "[key", 4) == 0) {
+ if (sscanf(buf, "[key block length = %d]", &key_block_len) != 1) {
+ goto loser;
+ }
+ key_block_params.ulKeySizeInBits = 8;
+ key_block_params.ulIVSizeInBits = key_block_len / 2 - 8;
+ key_block_len = key_block_len / 8;
+ key_block = malloc(key_block_len);
+ kb1_template.pValue = &key_block[0];
+ kb1_template.ulValueLen = 1;
+ kb2_template.pValue = &key_block[1];
+ kb2_template.ulValueLen = 1;
+ key_material.pIVClient = &key_block[2];
+ key_material.pIVServer = &key_block[2 + key_block_len / 2 - 1];
+ }
+ fputs(buf, tlsresp);
+ continue;
+ }
+ /* "COUNT = x" begins a new data set */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ /* zeroize the variables for the test with this data set */
+ memset(pms, 0, pms_len);
+ memset(master_secret, 0, pms_len);
+ memset(key_block, 0, key_block_len);
+ fputs(buf, tlsresp);
+ continue;
+ }
+ /* pre_master_secret = ... */
+ if (strncmp(buf, "pre_master_secret", 17) == 0) {
+ i = 17;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < pms_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &pms[j]);
+ }
+ fputs(buf, tlsresp);
+ continue;
+ }
+ /* serverHello_random = ... */
+ if (strncmp(buf, "serverHello_random", 18) == 0) {
+ i = 18;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
+ hex_to_byteval(&buf[i], &serverHello_random[j]);
+ }
+ fputs(buf, tlsresp);
+ continue;
+ }
+ /* clientHello_random = ... */
+ if (strncmp(buf, "clientHello_random", 18) == 0) {
+ i = 18;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
+ hex_to_byteval(&buf[i], &clientHello_random[j]);
+ }
+ fputs(buf, tlsresp);
+ continue;
+ }
+ /* server_random = ... */
+ if (strncmp(buf, "server_random", 13) == 0) {
+ i = 13;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
+ hex_to_byteval(&buf[i], &server_random[j]);
+ }
+ fputs(buf, tlsresp);
+ continue;
+ }
+ /* client_random = ... */
+ if (strncmp(buf, "client_random", 13) == 0) {
+ CK_SESSION_HANDLE session;
+ CK_OBJECT_HANDLE pms_handle;
+ CK_OBJECT_HANDLE master_handle;
+ CK_OBJECT_HANDLE fake_handle;
+ i = 13;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
+ hex_to_byteval(&buf[i], &client_random[j]);
+ }
+ fputs(buf, tlsresp);
+ crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ crv = NSC_CreateObject(session, create_template,
+ create_template_count, &pms_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_CreateObject failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ crv = NSC_DeriveKey(session, &master_mech, pms_handle,
+ derive_template, derive_template_count -
+ 1,
+ &master_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(master) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ crv = NSC_GetAttributeValue(session, master_handle,
+ &master_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("master_secret = ", tlsresp);
+ to_hex_str(buf, master_secret, pms_len);
+ fputs(buf, tlsresp);
+ fputc('\n', tlsresp);
+ crv = NSC_DeriveKey(session, &key_block_mech, master_handle,
+ derive_template, derive_template_count, &fake_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr,
+ "NSC_DeriveKey(keyblock) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ crv = NSC_GetAttributeValue(session, key_material.hClientKey,
+ &kb1_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ crv = NSC_GetAttributeValue(session, key_material.hServerKey,
+ &kb2_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("key_block = ", tlsresp);
+ to_hex_str(buf, key_block, key_block_len);
+ fputs(buf, tlsresp);
+ fputc('\n', tlsresp);
+ crv = NSC_CloseSession(session);
+ continue;
+ }
+ }
+loser:
+ NSC_Finalize(NULL);
+ if (pms)
+ free(pms);
+ if (master_secret)
+ free(master_secret);
+ if (key_block)
+ free(key_block);
+ if (tlsreq)
+ fclose(tlsreq);
+}
+
+int
+main(int argc, char **argv)
+{
+ if (argc < 2)
+ exit(-1);
+
+ RNG_RNGInit();
+ SECOID_Init();
+
+ /*************/
+ /* TDEA */
+ /*************/
+ if (strcmp(argv[1], "tdea") == 0) {
+ /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
+ if (strcmp(argv[2], "kat") == 0) {
+ /* Known Answer Test (KAT) */
+ tdea_kat_mmt(argv[4]);
+ } else if (strcmp(argv[2], "mmt") == 0) {
+ /* Multi-block Message Test (MMT) */
+ tdea_kat_mmt(argv[4]);
+ } else if (strcmp(argv[2], "mct") == 0) {
+ /* Monte Carlo Test (MCT) */
+ if (strcmp(argv[3], "ecb") == 0) {
+ /* ECB mode */
+ tdea_mct(NSS_DES_EDE3, argv[4]);
+ } else if (strcmp(argv[3], "cbc") == 0) {
+ /* CBC mode */
+ tdea_mct(NSS_DES_EDE3_CBC, argv[4]);
+ }
+ }
+ /*************/
+ /* AES */
+ /*************/
+ } else if (strcmp(argv[1], "aes") == 0) {
+ /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
+ if (strcmp(argv[2], "kat") == 0) {
+ /* Known Answer Test (KAT) */
+ aes_kat_mmt(argv[4]);
+ } else if (strcmp(argv[2], "mmt") == 0) {
+ /* Multi-block Message Test (MMT) */
+ aes_kat_mmt(argv[4]);
+ } else if (strcmp(argv[2], "gcm") == 0) {
+ if (strcmp(argv[3], "decrypt") == 0) {
+ aes_gcm(argv[4], 0);
+ } else if (strcmp(argv[3], "encrypt_extiv") == 0) {
+ aes_gcm(argv[4], 1);
+ } else if (strcmp(argv[3], "encrypt_intiv") == 0) {
+ aes_gcm(argv[4], 2);
+ }
+ } else if (strcmp(argv[2], "mct") == 0) {
+ /* Monte Carlo Test (MCT) */
+ if (strcmp(argv[3], "ecb") == 0) {
+ /* ECB mode */
+ aes_ecb_mct(argv[4]);
+ } else if (strcmp(argv[3], "cbc") == 0) {
+ /* CBC mode */
+ aes_cbc_mct(argv[4]);
+ }
+ }
+ /*************/
+ /* SHA */
+ /*************/
+ } else if (strcmp(argv[1], "sha") == 0) {
+ sha_test(argv[2]);
+ /*************/
+ /* RSA */
+ /*************/
+ } else if (strcmp(argv[1], "rsa") == 0) {
+ /* argv[2]=siggen|sigver */
+ /* argv[3]=<test name>.req */
+ if (strcmp(argv[2], "siggen") == 0) {
+ /* Signature Generation Test */
+ rsa_siggen_test(argv[3]);
+ } else if (strcmp(argv[2], "sigver") == 0) {
+ /* Signature Verification Test */
+ rsa_sigver_test(argv[3]);
+ } else if (strcmp(argv[2], "keypair") == 0) {
+ /* Key Pair Generation Test */
+ rsa_keypair_test(argv[3]);
+ }
+ /*************/
+ /* HMAC */
+ /*************/
+ } else if (strcmp(argv[1], "hmac") == 0) {
+ hmac_test(argv[2]);
+ /*************/
+ /* DSA */
+ /*************/
+ } else if (strcmp(argv[1], "dsa") == 0) {
+ /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */
+ /* argv[3]=<test name>.req */
+ if (strcmp(argv[2], "keypair") == 0) {
+ /* Key Pair Generation Test */
+ dsa_keypair_test(argv[3]);
+ } else if (strcmp(argv[2], "pqggen") == 0) {
+ /* Domain Parameter Generation Test */
+ dsa_pqggen_test(argv[3]);
+ } else if (strcmp(argv[2], "pqgver") == 0) {
+ /* Domain Parameter Validation Test */
+ dsa_pqgver_test(argv[3]);
+ } else if (strcmp(argv[2], "siggen") == 0) {
+ /* Signature Generation Test */
+ dsa_siggen_test(argv[3]);
+ } else if (strcmp(argv[2], "sigver") == 0) {
+ /* Signature Verification Test */
+ dsa_sigver_test(argv[3]);
+ }
+#ifndef NSS_DISABLE_ECC
+ /*************/
+ /* ECDSA */
+ /*************/
+ } else if (strcmp(argv[1], "ecdsa") == 0) {
+ /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */
+ if (strcmp(argv[2], "keypair") == 0) {
+ /* Key Pair Generation Test */
+ ecdsa_keypair_test(argv[3]);
+ } else if (strcmp(argv[2], "pkv") == 0) {
+ /* Public Key Validation Test */
+ ecdsa_pkv_test(argv[3]);
+ } else if (strcmp(argv[2], "siggen") == 0) {
+ /* Signature Generation Test */
+ ecdsa_siggen_test(argv[3]);
+ } else if (strcmp(argv[2], "sigver") == 0) {
+ /* Signature Verification Test */
+ ecdsa_sigver_test(argv[3]);
+ }
+#endif /* NSS_DISABLE_ECC */
+ /*************/
+ /* RNG */
+ /*************/
+ } else if (strcmp(argv[1], "rng") == 0) {
+ /* argv[2]=vst|mct argv[3]=<test name>.req */
+ if (strcmp(argv[2], "vst") == 0) {
+ /* Variable Seed Test */
+ rng_vst(argv[3]);
+ } else if (strcmp(argv[2], "mct") == 0) {
+ /* Monte Carlo Test */
+ rng_mct(argv[3]);
+ }
+ } else if (strcmp(argv[1], "drbg") == 0) {
+ /* Variable Seed Test */
+ drbg(argv[2]);
+ } else if (strcmp(argv[1], "ddrbg") == 0) {
+ debug = 1;
+ drbg(argv[2]);
+ }
+ return 0;
+}
diff --git a/security/nss/cmd/fipstest/fipstest.gyp b/security/nss/cmd/fipstest/fipstest.gyp
new file mode 100644
index 000000000..41024ca7b
--- /dev/null
+++ b/security/nss/cmd/fipstest/fipstest.gyp
@@ -0,0 +1,31 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'fipstest',
+ 'type': 'executable',
+ 'sources': [
+ 'fipstest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports',
+ '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSS_USE_STATIC_LIBS'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss',
+ 'use_static_libs': 1
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/fipstest/hmac.sh b/security/nss/cmd/fipstest/hmac.sh
new file mode 100755
index 000000000..d29dbc27f
--- /dev/null
+++ b/security/nss/cmd/fipstest/hmac.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# 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/.
+#
+# A Bourne shell script for running the NIST HMAC Algorithm Validation Suite
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+
+BASEDIR=${1-.}
+TESTDIR=${BASEDIR}/HMAC
+COMMAND=${2-run}
+REQDIR=${TESTDIR}/req
+RSPDIR=${TESTDIR}/resp
+
+hmac_requests="
+HMAC.req
+"
+
+if [ ${COMMAND} = "verify" ]; then
+ for request in $hmac_requests; do
+ sh ./validate1.sh ${TESTDIR} $request
+ done
+ exit 0
+fi
+for request in $hmac_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest hmac ${REQDIR}/$request > ${RSPDIR}/$response
+done
+
diff --git a/security/nss/cmd/fipstest/manifest.mn b/security/nss/cmd/fipstest/manifest.mn
new file mode 100644
index 000000000..1cebd7976
--- /dev/null
+++ b/security/nss/cmd/fipstest/manifest.mn
@@ -0,0 +1,23 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+PROGRAM = fipstest
+
+USE_STATIC_LIBS = 1
+
+EXPORTS = \
+ $(NULL)
+
+PRIVATE_EXPORTS = \
+ $(NULL)
+
+CSRCS = \
+ fipstest.c \
+ $(NULL)
+
diff --git a/security/nss/cmd/fipstest/rng.sh b/security/nss/cmd/fipstest/rng.sh
new file mode 100644
index 000000000..1a313b422
--- /dev/null
+++ b/security/nss/cmd/fipstest/rng.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# 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/.
+#
+# A Bourne shell script for running the NIST RNG Validation Suite
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+BASEDIR=${1-.}
+TESTDIR=${BASEDIR}/DRBG800-90A
+COMMAND=${2-run}
+REQDIR=${TESTDIR}/req
+RSPDIR=${TESTDIR}/resp
+
+drbg_requests="
+Hash_DRBG.req
+"
+
+if [ ${COMMAND} = "verify" ]; then
+ for request in $drbg_requests; do
+ sh ./validate1.sh ${TESTDIR} $request
+ done
+ exit 0
+fi
+for request in $drbg_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest drbg ${REQDIR}/$request > ${RSPDIR}/$response
+done
diff --git a/security/nss/cmd/fipstest/rsa.sh b/security/nss/cmd/fipstest/rsa.sh
new file mode 100644
index 000000000..b86a73969
--- /dev/null
+++ b/security/nss/cmd/fipstest/rsa.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# 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/.
+#
+# A Bourne shell script for running the NIST RSA Validation System
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+BASEDIR=${1-.}
+TESTDIR=${BASEDIR}/RSA2
+COMMAND=${2-run}
+REQDIR=${TESTDIR}/req
+RSPDIR=${TESTDIR}/resp
+
+if [ ${COMMAND} = "verify" ]; then
+#verify the signatures. The fax file does not have any known answers, so
+#use our own verify function.
+ name=SigGen15_186-3
+ echo ">>>>> $name"
+ fipstest rsa sigver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+# fipstest rsa sigver ${REQDIR}/SigVer15_186-3.req | grep ^Result.=.F
+#The Fax file has the private exponent and the salt value, remove it
+#also remove the false reason
+ sh ./validate1.sh ${TESTDIR} SigVer15_186-3.req ' ' '-e /^SaltVal/d -e/^d.=/d -e /^p.=/d -e /^q.=/d -e /^EM.with/d -e /^Result.=.F/s;.(.*);;'
+#
+# currently don't have a way to verify the RSA keygen
+#
+ exit 0
+fi
+
+request=SigGen15_186-3.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest rsa siggen ${REQDIR}/$request > ${RSPDIR}/$response
+
+request=SigVer15_186-3.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest rsa sigver ${REQDIR}/$request > ${RSPDIR}/$response
+
+#request=KeyGen_186-3.req
+request=KeyGen_RandomProbablyPrime3_3.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest rsa keypair ${REQDIR}/$request > ${RSPDIR}/$response
diff --git a/security/nss/cmd/fipstest/runtest.sh b/security/nss/cmd/fipstest/runtest.sh
new file mode 100644
index 000000000..99cefed77
--- /dev/null
+++ b/security/nss/cmd/fipstest/runtest.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# 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/.
+#
+TESTDIR=${1-.}
+COMMAND=${2-run}
+TESTS="aes aesgcm dsa ecdsa hmac tls rng rsa sha tdea"
+if [ ${NSS_ENABLE_ECC}x = 1x ]; then
+ TESTS=${TESTS} ecdsa
+fi
+for i in $TESTS
+do
+ echo "********************Running $i tests"
+ sh ./${i}.sh ${TESTDIR} ${COMMAND}
+done
diff --git a/security/nss/cmd/fipstest/sha.sh b/security/nss/cmd/fipstest/sha.sh
new file mode 100644
index 000000000..ccc52d297
--- /dev/null
+++ b/security/nss/cmd/fipstest/sha.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+#
+# 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/.
+#
+# A Bourne shell script for running the NIST SHA Algorithm Validation Suite
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+BASEDIR=${1-.}
+TESTDIR=${BASEDIR}/SHA
+COMMAND=${2-run}
+REQDIR=${TESTDIR}/req
+RSPDIR=${TESTDIR}/resp
+
+sha_ShortMsg_requests="
+SHA1ShortMsg.req
+SHA224ShortMsg.req
+SHA256ShortMsg.req
+SHA384ShortMsg.req
+SHA512ShortMsg.req
+"
+
+sha_LongMsg_requests="
+SHA1LongMsg.req
+SHA224LongMsg.req
+SHA256LongMsg.req
+SHA384LongMsg.req
+SHA512LongMsg.req
+"
+
+sha_Monte_requests="
+SHA1Monte.req
+SHA224Monte.req
+SHA256Monte.req
+SHA384Monte.req
+SHA512Monte.req
+"
+
+if [ ${COMMAND} = "verify" ]; then
+ for request in $sha_ShortMsg_requests $sha_LongMsg_requests $sha_Monte_requests; do
+ sh ./validate1.sh ${TESTDIR} $request
+ done
+ exit 0
+fi
+
+for request in $sha_ShortMsg_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest sha ${REQDIR}/$request > ${RSPDIR}/$response
+done
+for request in $sha_LongMsg_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest sha ${REQDIR}/$request > ${RSPDIR}/$response
+done
+for request in $sha_Monte_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest sha ${REQDIR}/$request > ${RSPDIR}/$response
+done
+
diff --git a/security/nss/cmd/fipstest/tdea.sh b/security/nss/cmd/fipstest/tdea.sh
new file mode 100644
index 000000000..cbddad7d7
--- /dev/null
+++ b/security/nss/cmd/fipstest/tdea.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+#
+# 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/.
+#
+# A Bourne shell script for running the NIST tdea Algorithm Validation Suite
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+
+BASEDIR=${1-.}
+TESTDIR=${BASEDIR}/TDES
+COMMAND=${2-run}
+REQDIR=${TESTDIR}/req
+RSPDIR=${TESTDIR}/resp
+
+#CBC_Known_Answer_tests
+#Initial Permutation KAT
+#Permutation Operation KAT
+#Subsitution Table KAT
+#Variable Key KAT
+#Variable PlainText KAT
+cbc_kat_requests="
+TCBCinvperm.req
+TCBCpermop.req
+TCBCsubtab.req
+TCBCvarkey.req
+TCBCvartext.req
+"
+
+#CBC Monte Carlo KATs
+cbc_monte_requests="
+TCBCMonte1.req
+TCBCMonte2.req
+TCBCMonte3.req
+"
+#Multi-block Message KATs
+cbc_mmt_requests="
+TCBCMMT1.req
+TCBCMMT2.req
+TCBCMMT3.req
+"
+
+ecb_kat_requests="
+TECBinvperm.req
+TECBpermop.req
+TECBsubtab.req
+TECBvarkey.req
+TECBvartext.req
+"
+
+ecb_monte_requests="
+TECBMonte1.req
+TECBMonte2.req
+TECBMonte3.req
+"
+
+ecb_mmt_requests="
+TECBMMT1.req
+TECBMMT2.req
+TECBMMT3.req
+"
+
+
+if [ ${COMMAND} = "verify" ]; then
+ for request in $cbc_kat_requests $cbc_monte_requests $cbc_mmt_requests $ecb_kat_requests $ecb_monte_requests $ecb_mmt_requests
+ do
+ sh ./validate1.sh ${TESTDIR} $request "-e /^NumKeys/d"
+ done
+ exit 0
+fi
+
+for request in $cbc_kat_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest tdea kat cbc ${REQDIR}/$request > ${RSPDIR}/$response
+done
+for request in $cbc_mmt_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest tdea mmt cbc ${REQDIR}/$request > ${RSPDIR}/$response
+done
+for request in $cbc_monte_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest tdea mct cbc ${REQDIR}/$request > ${RSPDIR}/$response
+done
+for request in $ecb_kat_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest tdea kat ecb ${REQDIR}/$request > ${RSPDIR}/$response
+done
+for request in $ecb_mmt_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest tdea mmt ecb ${REQDIR}/$request > ${RSPDIR}/$response
+done
+for request in $ecb_monte_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest tdea mct ecb ${REQDIR}/$request > ${RSPDIR}/$response
+done
diff --git a/security/nss/cmd/fipstest/tls.sh b/security/nss/cmd/fipstest/tls.sh
new file mode 100644
index 000000000..1c2824539
--- /dev/null
+++ b/security/nss/cmd/fipstest/tls.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# 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/.
+#
+# A Bourne shell script for running the NIST RNG Validation Suite
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+BASEDIR=${1-.}
+TESTDIR=${BASEDIR}/KDF135
+COMMAND=${2-run}
+REQDIR=${TESTDIR}/req
+RSPDIR=${TESTDIR}/resp
+
+drbg_requests="
+tls.req
+"
+
+if [ ${COMMAND} = "verify" ]; then
+ for request in $drbg_requests; do
+ sh ./validate1.sh ${TESTDIR} $request
+ done
+ exit 0
+fi
+for request in $drbg_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest tls ${REQDIR}/$request > ${RSPDIR}/$response
+done
diff --git a/security/nss/cmd/fipstest/validate.sh b/security/nss/cmd/fipstest/validate.sh
new file mode 100644
index 000000000..d446dd587
--- /dev/null
+++ b/security/nss/cmd/fipstest/validate.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+#
+# 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/.
+#
+sh ./runtest.sh ${1-.} verify
diff --git a/security/nss/cmd/fipstest/validate1.sh b/security/nss/cmd/fipstest/validate1.sh
new file mode 100644
index 000000000..1440af8fc
--- /dev/null
+++ b/security/nss/cmd/fipstest/validate1.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# 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/.
+#
+# Validate1.sh is a helper shell script that each of the base test shell
+# scripts call to help validate that the generated response (response)
+# matches the known answer response (fax). Sometimes (depending on the
+# individual tests) there are extraneous output in either or both response
+# and fax files. These allow the caller to pass in additional sed commands
+# to clear out those extraneous outputs before we compare the two files.
+# The sed line always clears out Windows line endings, replaces tabs with
+# spaces, and removed comments.
+#
+TESTDIR=${1-.}
+request=${2}
+extraneous_response=${3}
+extraneous_fax=${4}
+name=`basename $request .req`
+echo ">>>>> $name"
+sed -e 's; ;;g' -e 's; ; ;g' -e '/^#/d' $extraneous_response ${TESTDIR}/resp/${name}.rsp > /tmp/y1
+# if we didn't generate any output, flag that as an error
+size=`sum /tmp/y1 | awk '{ print $NF }'`
+if [ $size -eq 0 ]; then
+ echo "${TESTDIR}/resp/${name}.rsp: empty"
+ exit 1;
+fi
+sed -e 's; ;;g' -e 's; ; ;g' -e '/^#/d' $extraneous_fax ${TESTDIR}/fax/${name}.fax > /tmp/y2
+diff -i -w -B /tmp/y1 /tmp/y2
diff --git a/security/nss/cmd/httpserv/Makefile b/security/nss/cmd/httpserv/Makefile
new file mode 100644
index 000000000..7b74b369c
--- /dev/null
+++ b/security/nss/cmd/httpserv/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/httpserv/httpserv.c b/security/nss/cmd/httpserv/httpserv.c
new file mode 100644
index 000000000..7cf28c65a
--- /dev/null
+++ b/security/nss/cmd/httpserv/httpserv.c
@@ -0,0 +1,1453 @@
+/* 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/. */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#if defined(_WINDOWS)
+#include <process.h> /* for getpid() */
+#endif
+
+#include <signal.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "nspr.h"
+#include "prio.h"
+#include "prerror.h"
+#include "prnetdb.h"
+#include "prclist.h"
+#include "plgetopt.h"
+#include "pk11func.h"
+#include "nss.h"
+#include "nssb64.h"
+#include "sechash.h"
+#include "cert.h"
+#include "certdb.h"
+#include "ocsp.h"
+#include "ocspti.h"
+#include "ocspi.h"
+
+#ifndef PORT_Sprintf
+#define PORT_Sprintf sprintf
+#endif
+
+#ifndef PORT_Strstr
+#define PORT_Strstr strstr
+#endif
+
+#ifndef PORT_Malloc
+#define PORT_Malloc PR_Malloc
+#endif
+
+static int handle_connection(PRFileDesc *, PRFileDesc *, int);
+
+/* data and structures for shutdown */
+static int stopping;
+
+static PRBool noDelay;
+static int verbose;
+
+static PRThread *acceptorThread;
+
+static PRLogModuleInfo *lm;
+
+#define PRINTF \
+ if (verbose) \
+ printf
+#define FPRINTF \
+ if (verbose) \
+ fprintf
+#define FLUSH \
+ if (verbose) { \
+ fflush(stdout); \
+ fflush(stderr); \
+ }
+#define VLOG(arg) PR_LOG(lm, PR_LOG_DEBUG, arg)
+
+static void
+Usage(const char *progName)
+{
+ fprintf(stderr,
+
+ "Usage: %s -p port [-Dbv]\n"
+ " [-t threads] [-i pid_file]\n"
+ " [-A nickname -C crl-filename]... [-O method]\n"
+ " [-d dbdir] [-f password_file] [-w password] [-P dbprefix]\n"
+ "-D means disable Nagle delays in TCP\n"
+ "-b means try binding to the port and exit\n"
+ "-v means verbose output\n"
+ "-t threads -- specify the number of threads to use for connections.\n"
+ "-i pid_file file to write the process id of httpserv\n"
+ "Parameters -A, -C and -O are used to provide an OCSP server at /ocsp?\n"
+ "-A a nickname of a CA certificate\n"
+ "-C a CRL filename corresponding to the preceding CA nickname\n"
+ "-O allowed HTTP methods for OCSP requests: get, post, all, random, get-unknown\n"
+ " random means: randomly fail if request method is GET, POST always works\n"
+ " get-unknown means: status unknown for GET, correct status for POST\n"
+ "Multiple pairs of parameters -A and -C are allowed.\n"
+ "If status for a cert from an unknown CA is requested, the cert from the\n"
+ "first -A parameter will be used to sign the unknown status response.\n"
+ "NSS database parameters are used only if OCSP parameters are used.\n",
+ progName);
+}
+
+static const char *
+errWarn(char *funcString)
+{
+ PRErrorCode perr = PR_GetError();
+ const char *errString = SECU_Strerror(perr);
+
+ fprintf(stderr, "httpserv: %s returned error %d:\n%s\n",
+ funcString, perr, errString);
+ return errString;
+}
+
+static void
+errExit(char *funcString)
+{
+ errWarn(funcString);
+ exit(3);
+}
+
+#define MAX_VIRT_SERVER_NAME_ARRAY_INDEX 10
+
+/**************************************************************************
+** Begin thread management routines and data.
+**************************************************************************/
+#define MIN_THREADS 3
+#define DEFAULT_THREADS 8
+#define MAX_THREADS 4096
+#define MAX_PROCS 25
+static int maxThreads = DEFAULT_THREADS;
+
+typedef struct jobStr {
+ PRCList link;
+ PRFileDesc *tcp_sock;
+ PRFileDesc *model_sock;
+ int requestCert;
+} JOB;
+
+static PZLock *qLock; /* this lock protects all data immediately below */
+static PRLock *lastLoadedCrlLock; /* this lock protects lastLoadedCrl variable */
+static PZCondVar *jobQNotEmptyCv;
+static PZCondVar *freeListNotEmptyCv;
+static PZCondVar *threadCountChangeCv;
+static int threadCount;
+static PRCList jobQ;
+static PRCList freeJobs;
+static JOB *jobTable;
+
+SECStatus
+setupJobs(int maxJobs)
+{
+ int i;
+
+ jobTable = (JOB *)PR_Calloc(maxJobs, sizeof(JOB));
+ if (!jobTable)
+ return SECFailure;
+
+ PR_INIT_CLIST(&jobQ);
+ PR_INIT_CLIST(&freeJobs);
+
+ for (i = 0; i < maxJobs; ++i) {
+ JOB *pJob = jobTable + i;
+ PR_APPEND_LINK(&pJob->link, &freeJobs);
+ }
+ return SECSuccess;
+}
+
+typedef int startFn(PRFileDesc *a, PRFileDesc *b, int c);
+
+typedef enum { rs_idle = 0,
+ rs_running = 1,
+ rs_zombie = 2 } runState;
+
+typedef struct perThreadStr {
+ PRFileDesc *a;
+ PRFileDesc *b;
+ int c;
+ int rv;
+ startFn *startFunc;
+ PRThread *prThread;
+ runState state;
+} perThread;
+
+static perThread *threads;
+
+void
+thread_wrapper(void *arg)
+{
+ perThread *slot = (perThread *)arg;
+
+ slot->rv = (*slot->startFunc)(slot->a, slot->b, slot->c);
+
+ /* notify the thread exit handler. */
+ PZ_Lock(qLock);
+ slot->state = rs_zombie;
+ --threadCount;
+ PZ_NotifyAllCondVar(threadCountChangeCv);
+ PZ_Unlock(qLock);
+}
+
+int
+jobLoop(PRFileDesc *a, PRFileDesc *b, int c)
+{
+ PRCList *myLink = 0;
+ JOB *myJob;
+
+ PZ_Lock(qLock);
+ do {
+ myLink = 0;
+ while (PR_CLIST_IS_EMPTY(&jobQ) && !stopping) {
+ PZ_WaitCondVar(jobQNotEmptyCv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ if (!PR_CLIST_IS_EMPTY(&jobQ)) {
+ myLink = PR_LIST_HEAD(&jobQ);
+ PR_REMOVE_AND_INIT_LINK(myLink);
+ }
+ PZ_Unlock(qLock);
+ myJob = (JOB *)myLink;
+ /* myJob will be null when stopping is true and jobQ is empty */
+ if (!myJob)
+ break;
+ handle_connection(myJob->tcp_sock, myJob->model_sock,
+ myJob->requestCert);
+ PZ_Lock(qLock);
+ PR_APPEND_LINK(myLink, &freeJobs);
+ PZ_NotifyCondVar(freeListNotEmptyCv);
+ } while (PR_TRUE);
+ return 0;
+}
+
+SECStatus
+launch_threads(
+ startFn *startFunc,
+ PRFileDesc *a,
+ PRFileDesc *b,
+ int c,
+ PRBool local)
+{
+ int i;
+ SECStatus rv = SECSuccess;
+
+ /* create the thread management serialization structs */
+ qLock = PZ_NewLock(nssILockSelfServ);
+ jobQNotEmptyCv = PZ_NewCondVar(qLock);
+ freeListNotEmptyCv = PZ_NewCondVar(qLock);
+ threadCountChangeCv = PZ_NewCondVar(qLock);
+
+ /* create monitor for crl reload procedure */
+ lastLoadedCrlLock = PR_NewLock();
+
+ /* allocate the array of thread slots */
+ threads = PR_Calloc(maxThreads, sizeof(perThread));
+ if (NULL == threads) {
+ fprintf(stderr, "Oh Drat! Can't allocate the perThread array\n");
+ return SECFailure;
+ }
+ /* 5 is a little extra, intended to keep the jobQ from underflowing.
+ ** That is, from going empty while not stopping and clients are still
+ ** trying to contact us.
+ */
+ rv = setupJobs(maxThreads + 5);
+ if (rv != SECSuccess)
+ return rv;
+
+ PZ_Lock(qLock);
+ for (i = 0; i < maxThreads; ++i) {
+ perThread *slot = threads + i;
+
+ slot->state = rs_running;
+ slot->a = a;
+ slot->b = b;
+ slot->c = c;
+ slot->startFunc = startFunc;
+ slot->prThread = PR_CreateThread(PR_USER_THREAD,
+ thread_wrapper, slot, PR_PRIORITY_NORMAL,
+ (PR_TRUE ==
+ local)
+ ? PR_LOCAL_THREAD
+ : PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD, 0);
+ if (slot->prThread == NULL) {
+ printf("httpserv: Failed to launch thread!\n");
+ slot->state = rs_idle;
+ rv = SECFailure;
+ break;
+ }
+
+ ++threadCount;
+ }
+ PZ_Unlock(qLock);
+
+ return rv;
+}
+
+#define DESTROY_CONDVAR(name) \
+ if (name) { \
+ PZ_DestroyCondVar(name); \
+ name = NULL; \
+ }
+#define DESTROY_LOCK(name) \
+ if (name) { \
+ PZ_DestroyLock(name); \
+ name = NULL; \
+ }
+
+void
+terminateWorkerThreads(void)
+{
+ int i;
+
+ VLOG(("httpserv: server_thread: waiting on stopping"));
+ PZ_Lock(qLock);
+ PZ_NotifyAllCondVar(jobQNotEmptyCv);
+ PZ_Unlock(qLock);
+
+ /* Wait for worker threads to terminate. */
+ for (i = 0; i < maxThreads; ++i) {
+ perThread *slot = threads + i;
+ if (slot->prThread) {
+ PR_JoinThread(slot->prThread);
+ }
+ }
+
+ /* The worker threads empty the jobQ before they terminate. */
+ PZ_Lock(qLock);
+ PORT_Assert(threadCount == 0);
+ PORT_Assert(PR_CLIST_IS_EMPTY(&jobQ));
+ PZ_Unlock(qLock);
+
+ DESTROY_CONDVAR(jobQNotEmptyCv);
+ DESTROY_CONDVAR(freeListNotEmptyCv);
+ DESTROY_CONDVAR(threadCountChangeCv);
+
+ PR_DestroyLock(lastLoadedCrlLock);
+ DESTROY_LOCK(qLock);
+ PR_Free(jobTable);
+ PR_Free(threads);
+}
+
+/**************************************************************************
+** End thread management routines.
+**************************************************************************/
+
+PRBool NoReuse = PR_FALSE;
+PRBool disableLocking = PR_FALSE;
+static secuPWData pwdata = { PW_NONE, 0 };
+
+struct caRevoInfoStr {
+ PRCList link;
+ char *nickname;
+ char *crlFilename;
+ CERTCertificate *cert;
+ CERTOCSPCertID *id;
+ CERTSignedCrl *crl;
+};
+typedef struct caRevoInfoStr caRevoInfo;
+/* Created during app init. No locks necessary,
+ * because later on, only read access will occur. */
+static caRevoInfo *caRevoInfos = NULL;
+
+static enum {
+ ocspGetOnly,
+ ocspPostOnly,
+ ocspGetAndPost,
+ ocspRandomGetFailure,
+ ocspGetUnknown
+} ocspMethodsAllowed = ocspGetAndPost;
+
+static const char stopCmd[] = { "GET /stop " };
+static const char getCmd[] = { "GET " };
+static const char outHeader[] = {
+ "HTTP/1.0 200 OK\r\n"
+ "Server: Generic Web Server\r\n"
+ "Date: Tue, 26 Aug 1997 22:10:05 GMT\r\n"
+ "Content-type: text/plain\r\n"
+ "\r\n"
+};
+static const char outOcspHeader[] = {
+ "HTTP/1.0 200 OK\r\n"
+ "Server: Generic OCSP Server\r\n"
+ "Content-type: application/ocsp-response\r\n"
+ "\r\n"
+};
+static const char outBadRequestHeader[] = {
+ "HTTP/1.0 400 Bad Request\r\n"
+ "Server: Generic OCSP Server\r\n"
+ "\r\n"
+};
+
+void
+stop_server()
+{
+ stopping = 1;
+ PR_Interrupt(acceptorThread);
+ PZ_TraceFlush();
+}
+
+/* Will only work if the original input to url encoding was
+ * a base64 encoded buffer. Will only decode the sequences used
+ * for encoding the special base64 characters, and fail if any
+ * other encoded chars are found.
+ * Will return SECSuccess if input could be processed.
+ * Coversion is done in place.
+ */
+static SECStatus
+urldecode_base64chars_inplace(char *buf)
+{
+ char *walk;
+ size_t remaining_bytes;
+
+ if (!buf || !*buf)
+ return SECFailure;
+
+ walk = buf;
+ remaining_bytes = strlen(buf) + 1; /* include terminator */
+
+ while (*walk) {
+ if (*walk == '%') {
+ if (!PL_strncasecmp(walk, "%2B", 3)) {
+ *walk = '+';
+ } else if (!PL_strncasecmp(walk, "%2F", 3)) {
+ *walk = '/';
+ } else if (!PL_strncasecmp(walk, "%3D", 3)) {
+ *walk = '=';
+ } else {
+ return SECFailure;
+ }
+ remaining_bytes -= 3;
+ ++walk;
+ memmove(walk, walk + 2, remaining_bytes);
+ } else {
+ ++walk;
+ --remaining_bytes;
+ }
+ }
+ return SECSuccess;
+}
+
+int
+handle_connection(
+ PRFileDesc *tcp_sock,
+ PRFileDesc *model_sock,
+ int requestCert)
+{
+ PRFileDesc *ssl_sock = NULL;
+ PRFileDesc *local_file_fd = NULL;
+ char *pBuf; /* unused space at end of buf */
+ const char *errString;
+ PRStatus status;
+ int bufRem; /* unused bytes at end of buf */
+ int bufDat; /* characters received in buf */
+ int newln = 0; /* # of consecutive newlns */
+ int firstTime = 1;
+ int reqLen;
+ int rv;
+ int numIOVs;
+ PRSocketOptionData opt;
+ PRIOVec iovs[16];
+ char msgBuf[160];
+ char buf[10240];
+ char fileName[513];
+ char *getData = NULL; /* inplace conversion */
+ SECItem postData;
+ PRBool isOcspRequest = PR_FALSE;
+ PRBool isPost;
+
+ postData.data = NULL;
+ postData.len = 0;
+
+ pBuf = buf;
+ bufRem = sizeof buf;
+
+ VLOG(("httpserv: handle_connection: starting"));
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ PR_SetSocketOption(tcp_sock, &opt);
+
+ VLOG(("httpserv: handle_connection: starting\n"));
+ ssl_sock = tcp_sock;
+
+ if (noDelay) {
+ opt.option = PR_SockOpt_NoDelay;
+ opt.value.no_delay = PR_TRUE;
+ status = PR_SetSocketOption(ssl_sock, &opt);
+ if (status != PR_SUCCESS) {
+ errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)");
+ if (ssl_sock) {
+ PR_Close(ssl_sock);
+ }
+ return SECFailure;
+ }
+ }
+
+ while (1) {
+ const char *post;
+ const char *foundStr = NULL;
+ const char *tmp = NULL;
+
+ newln = 0;
+ reqLen = 0;
+
+ rv = PR_Read(ssl_sock, pBuf, bufRem - 1);
+ if (rv == 0 ||
+ (rv < 0 && PR_END_OF_FILE_ERROR == PR_GetError())) {
+ if (verbose)
+ errWarn("HDX PR_Read hit EOF");
+ break;
+ }
+ if (rv < 0) {
+ errWarn("HDX PR_Read");
+ goto cleanup;
+ }
+ /* NULL termination */
+ pBuf[rv] = 0;
+ if (firstTime) {
+ firstTime = 0;
+ }
+
+ pBuf += rv;
+ bufRem -= rv;
+ bufDat = pBuf - buf;
+ /* Parse the input, starting at the beginning of the buffer.
+ * Stop when we detect two consecutive \n's (or \r\n's)
+ * as this signifies the end of the GET or POST portion.
+ * The posted data follows.
+ */
+ while (reqLen < bufDat && newln < 2) {
+ int octet = buf[reqLen++];
+ if (octet == '\n') {
+ newln++;
+ } else if (octet != '\r') {
+ newln = 0;
+ }
+ }
+
+ /* came to the end of the buffer, or second newln
+ * If we didn't get an empty line (CRLFCRLF) then keep on reading.
+ */
+ if (newln < 2)
+ continue;
+
+ /* we're at the end of the HTTP request.
+ * If the request is a POST, then there will be one more
+ * line of data.
+ * This parsing is a hack, but ok for SSL test purposes.
+ */
+ post = PORT_Strstr(buf, "POST ");
+ if (!post || *post != 'P')
+ break;
+
+ postData.data = (void *)(buf + reqLen);
+
+ tmp = "content-length: ";
+ foundStr = PL_strcasestr(buf, tmp);
+ if (foundStr) {
+ int expectedPostLen;
+ int havePostLen;
+
+ expectedPostLen = atoi(foundStr + strlen(tmp));
+ havePostLen = bufDat - reqLen;
+ if (havePostLen >= expectedPostLen) {
+ postData.len = expectedPostLen;
+ break;
+ }
+ } else {
+ /* use legacy hack */
+ /* It's a post, so look for the next and final CR/LF. */
+ while (reqLen < bufDat && newln < 3) {
+ int octet = buf[reqLen++];
+ if (octet == '\n') {
+ newln++;
+ }
+ }
+ if (newln == 3)
+ break;
+ }
+ } /* read loop */
+
+ bufDat = pBuf - buf;
+ if (bufDat)
+ do { /* just close if no data */
+ /* Have either (a) a complete get, (b) a complete post, (c) EOF */
+ if (reqLen > 0) {
+ PRBool isGetOrPost = PR_FALSE;
+ unsigned skipChars = 0;
+ isPost = PR_FALSE;
+
+ if (!strncmp(buf, getCmd, sizeof getCmd - 1)) {
+ isGetOrPost = PR_TRUE;
+ skipChars = 4;
+ } else if (!strncmp(buf, "POST ", 5)) {
+ isGetOrPost = PR_TRUE;
+ isPost = PR_TRUE;
+ skipChars = 5;
+ }
+
+ if (isGetOrPost) {
+ char *fnBegin = buf;
+ char *fnEnd;
+ char *fnstart = NULL;
+ PRFileInfo info;
+
+ fnBegin += skipChars;
+
+ fnEnd = strpbrk(fnBegin, " \r\n");
+ if (fnEnd) {
+ int fnLen = fnEnd - fnBegin;
+ if (fnLen < sizeof fileName) {
+ strncpy(fileName, fnBegin, fnLen);
+ fileName[fnLen] = 0; /* null terminate */
+ fnstart = fileName;
+ /* strip initial / because our root is the current directory*/
+ while (*fnstart && *fnstart == '/')
+ ++fnstart;
+ }
+ }
+ if (fnstart) {
+ if (!strncmp(fnstart, "ocsp", 4)) {
+ if (isPost) {
+ if (postData.data) {
+ isOcspRequest = PR_TRUE;
+ }
+ } else {
+ if (!strncmp(fnstart, "ocsp/", 5)) {
+ isOcspRequest = PR_TRUE;
+ getData = fnstart + 5;
+ }
+ }
+ } else {
+ /* try to open the file named.
+ * If successful, then write it to the client.
+ */
+ status = PR_GetFileInfo(fnstart, &info);
+ if (status == PR_SUCCESS &&
+ info.type == PR_FILE_FILE &&
+ info.size >= 0) {
+ local_file_fd = PR_Open(fnstart, PR_RDONLY, 0);
+ }
+ }
+ }
+ }
+ }
+
+ numIOVs = 0;
+
+ iovs[numIOVs].iov_base = (char *)outHeader;
+ iovs[numIOVs].iov_len = (sizeof(outHeader)) - 1;
+ numIOVs++;
+
+ if (isOcspRequest && caRevoInfos) {
+ CERTOCSPRequest *request = NULL;
+ PRBool failThisRequest = PR_FALSE;
+ PLArenaPool *arena = NULL;
+
+ if (ocspMethodsAllowed == ocspGetOnly && postData.len) {
+ failThisRequest = PR_TRUE;
+ } else if (ocspMethodsAllowed == ocspPostOnly && getData) {
+ failThisRequest = PR_TRUE;
+ } else if (ocspMethodsAllowed == ocspRandomGetFailure && getData) {
+ if (!(rand() % 2)) {
+ failThisRequest = PR_TRUE;
+ }
+ }
+
+ if (failThisRequest) {
+ PR_Write(ssl_sock, outBadRequestHeader, strlen(outBadRequestHeader));
+ break;
+ }
+ /* get is base64, post is binary.
+ * If we have base64, convert into the (empty) postData array.
+ */
+ if (getData) {
+ if (urldecode_base64chars_inplace(getData) == SECSuccess) {
+ /* The code below can handle a NULL arena */
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ NSSBase64_DecodeBuffer(arena, &postData, getData, strlen(getData));
+ }
+ }
+ if (postData.len) {
+ request = CERT_DecodeOCSPRequest(&postData);
+ }
+ if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ if (!request || !request->tbsRequest ||
+ !request->tbsRequest->requestList ||
+ !request->tbsRequest->requestList[0]) {
+ PORT_Sprintf(msgBuf, "Cannot decode OCSP request.\r\n");
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ } else {
+ /* TODO: support more than one request entry */
+ CERTOCSPCertID *reqid = request->tbsRequest->requestList[0]->reqCert;
+ const caRevoInfo *revoInfo = NULL;
+ PRBool unknown = PR_FALSE;
+ PRBool revoked = PR_FALSE;
+ PRTime nextUpdate = 0;
+ PRTime revoDate = 0;
+ PRCList *caRevoIter;
+
+ caRevoIter = &caRevoInfos->link;
+ do {
+ CERTOCSPCertID *caid;
+
+ revoInfo = (caRevoInfo *)caRevoIter;
+ caid = revoInfo->id;
+
+ if (SECOID_CompareAlgorithmID(&reqid->hashAlgorithm,
+ &caid->hashAlgorithm) == SECEqual &&
+ SECITEM_CompareItem(&reqid->issuerNameHash,
+ &caid->issuerNameHash) == SECEqual &&
+ SECITEM_CompareItem(&reqid->issuerKeyHash,
+ &caid->issuerKeyHash) == SECEqual) {
+ break;
+ }
+ revoInfo = NULL;
+ caRevoIter = PR_NEXT_LINK(caRevoIter);
+ } while (caRevoIter != &caRevoInfos->link);
+
+ if (!revoInfo) {
+ unknown = PR_TRUE;
+ revoInfo = caRevoInfos;
+ } else {
+ CERTCrl *crl = &revoInfo->crl->crl;
+ CERTCrlEntry *entry = NULL;
+ DER_DecodeTimeChoice(&nextUpdate, &crl->nextUpdate);
+ if (crl->entries) {
+ int iv = 0;
+ /* assign, not compare */
+ while ((entry = crl->entries[iv++])) {
+ if (SECITEM_CompareItem(&reqid->serialNumber,
+ &entry->serialNumber) == SECEqual) {
+ break;
+ }
+ }
+ }
+ if (entry) {
+ /* revoked status response */
+ revoked = PR_TRUE;
+ DER_DecodeTimeChoice(&revoDate, &entry->revocationDate);
+ } else {
+ /* else good status response */
+ if (!isPost && ocspMethodsAllowed == ocspGetUnknown) {
+ unknown = PR_TRUE;
+ nextUpdate = PR_Now() + (PRTime)60 * 60 * 24 * PR_USEC_PER_SEC; /*tomorrow*/
+ revoDate = PR_Now() - (PRTime)60 * 60 * 24 * PR_USEC_PER_SEC; /*yesterday*/
+ }
+ }
+ }
+
+ {
+ PRTime now = PR_Now();
+ PLArenaPool *arena = NULL;
+ CERTOCSPSingleResponse *sr;
+ CERTOCSPSingleResponse **singleResponses;
+ SECItem *ocspResponse;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (unknown) {
+ sr = CERT_CreateOCSPSingleResponseUnknown(arena, reqid, now,
+ &nextUpdate);
+ } else if (revoked) {
+ sr = CERT_CreateOCSPSingleResponseRevoked(arena, reqid, now,
+ &nextUpdate, revoDate, NULL);
+ } else {
+ sr = CERT_CreateOCSPSingleResponseGood(arena, reqid, now,
+ &nextUpdate);
+ }
+
+ /* meaning of value 2: one entry + one end marker */
+ singleResponses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse *, 2);
+ singleResponses[0] = sr;
+ singleResponses[1] = NULL;
+ ocspResponse = CERT_CreateEncodedOCSPSuccessResponse(arena,
+ revoInfo->cert, ocspResponderID_byName, now,
+ singleResponses, &pwdata);
+
+ if (!ocspResponse) {
+ PORT_Sprintf(msgBuf, "Failed to encode response\r\n");
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ } else {
+ PR_Write(ssl_sock, outOcspHeader, strlen(outOcspHeader));
+ PR_Write(ssl_sock, ocspResponse->data, ocspResponse->len);
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ }
+ CERT_DestroyOCSPRequest(request);
+ break;
+ }
+ } else if (local_file_fd) {
+ PRInt32 bytes;
+ int errLen;
+ bytes = PR_TransmitFile(ssl_sock, local_file_fd, outHeader,
+ sizeof outHeader - 1,
+ PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytes >= 0) {
+ bytes -= sizeof outHeader - 1;
+ FPRINTF(stderr,
+ "httpserv: PR_TransmitFile wrote %d bytes from %s\n",
+ bytes, fileName);
+ break;
+ }
+ errString = errWarn("PR_TransmitFile");
+ errLen = PORT_Strlen(errString);
+ errLen = PR_MIN(errLen, sizeof msgBuf - 1);
+ PORT_Memcpy(msgBuf, errString, errLen);
+ msgBuf[errLen] = 0;
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ } else if (reqLen <= 0) { /* hit eof */
+ PORT_Sprintf(msgBuf, "Get or Post incomplete after %d bytes.\r\n",
+ bufDat);
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ } else if (reqLen < bufDat) {
+ PORT_Sprintf(msgBuf, "Discarded %d characters.\r\n",
+ bufDat - reqLen);
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ }
+
+ if (reqLen > 0) {
+ if (verbose > 1)
+ fwrite(buf, 1, reqLen, stdout); /* display it */
+
+ iovs[numIOVs].iov_base = buf;
+ iovs[numIOVs].iov_len = reqLen;
+ numIOVs++;
+ }
+
+ rv = PR_Writev(ssl_sock, iovs, numIOVs, PR_INTERVAL_NO_TIMEOUT);
+ if (rv < 0) {
+ errWarn("PR_Writev");
+ break;
+ }
+
+ } while (0);
+
+cleanup:
+ if (ssl_sock) {
+ PR_Close(ssl_sock);
+ } else if (tcp_sock) {
+ PR_Close(tcp_sock);
+ }
+ if (local_file_fd)
+ PR_Close(local_file_fd);
+ VLOG(("httpserv: handle_connection: exiting\n"));
+
+ /* do a nice shutdown if asked. */
+ if (!strncmp(buf, stopCmd, sizeof stopCmd - 1)) {
+ VLOG(("httpserv: handle_connection: stop command"));
+ stop_server();
+ }
+ VLOG(("httpserv: handle_connection: exiting"));
+ return SECSuccess; /* success */
+}
+
+#ifdef XP_UNIX
+
+void
+sigusr1_handler(int sig)
+{
+ VLOG(("httpserv: sigusr1_handler: stop server"));
+ stop_server();
+}
+
+#endif
+
+SECStatus
+do_accepts(
+ PRFileDesc *listen_sock,
+ PRFileDesc *model_sock,
+ int requestCert)
+{
+ PRNetAddr addr;
+ PRErrorCode perr;
+#ifdef XP_UNIX
+ struct sigaction act;
+#endif
+
+ VLOG(("httpserv: do_accepts: starting"));
+ PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_HIGH);
+
+ acceptorThread = PR_GetCurrentThread();
+#ifdef XP_UNIX
+ /* set up the signal handler */
+ act.sa_handler = sigusr1_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ if (sigaction(SIGUSR1, &act, NULL)) {
+ fprintf(stderr, "Error installing signal handler.\n");
+ exit(1);
+ }
+#endif
+ while (!stopping) {
+ PRFileDesc *tcp_sock;
+ PRCList *myLink;
+
+ FPRINTF(stderr, "\n\n\nhttpserv: About to call accept.\n");
+ tcp_sock = PR_Accept(listen_sock, &addr, PR_INTERVAL_NO_TIMEOUT);
+ if (tcp_sock == NULL) {
+ perr = PR_GetError();
+ if ((perr != PR_CONNECT_RESET_ERROR &&
+ perr != PR_PENDING_INTERRUPT_ERROR) ||
+ verbose) {
+ errWarn("PR_Accept");
+ }
+ if (perr == PR_CONNECT_RESET_ERROR) {
+ FPRINTF(stderr,
+ "Ignoring PR_CONNECT_RESET_ERROR error - continue\n");
+ continue;
+ }
+ stopping = 1;
+ break;
+ }
+
+ VLOG(("httpserv: do_accept: Got connection\n"));
+
+ PZ_Lock(qLock);
+ while (PR_CLIST_IS_EMPTY(&freeJobs) && !stopping) {
+ PZ_WaitCondVar(freeListNotEmptyCv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ if (stopping) {
+ PZ_Unlock(qLock);
+ if (tcp_sock) {
+ PR_Close(tcp_sock);
+ }
+ break;
+ }
+ myLink = PR_LIST_HEAD(&freeJobs);
+ PR_REMOVE_AND_INIT_LINK(myLink);
+ /* could release qLock here and reaquire it 7 lines below, but
+ ** why bother for 4 assignment statements?
+ */
+ {
+ JOB *myJob = (JOB *)myLink;
+ myJob->tcp_sock = tcp_sock;
+ myJob->model_sock = model_sock;
+ myJob->requestCert = requestCert;
+ }
+
+ PR_APPEND_LINK(myLink, &jobQ);
+ PZ_NotifyCondVar(jobQNotEmptyCv);
+ PZ_Unlock(qLock);
+ }
+
+ FPRINTF(stderr, "httpserv: Closing listen socket.\n");
+ VLOG(("httpserv: do_accepts: exiting"));
+ if (listen_sock) {
+ PR_Close(listen_sock);
+ }
+ return SECSuccess;
+}
+
+PRFileDesc *
+getBoundListenSocket(unsigned short port)
+{
+ PRFileDesc *listen_sock;
+ int listenQueueDepth = 5 + (2 * maxThreads);
+ PRStatus prStatus;
+ PRNetAddr addr;
+ PRSocketOptionData opt;
+
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_INADDR_ANY;
+ addr.inet.port = PR_htons(port);
+
+ listen_sock = PR_NewTCPSocket();
+ if (listen_sock == NULL) {
+ errExit("PR_NewTCPSocket");
+ }
+
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ prStatus = PR_SetSocketOption(listen_sock, &opt);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_SetSocketOption(PR_SockOpt_Nonblocking)");
+ }
+
+ opt.option = PR_SockOpt_Reuseaddr;
+ opt.value.reuse_addr = PR_TRUE;
+ prStatus = PR_SetSocketOption(listen_sock, &opt);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_SetSocketOption(PR_SockOpt_Reuseaddr)");
+ }
+
+#ifndef WIN95
+ /* Set PR_SockOpt_Linger because it helps prevent a server bind issue
+ * after clean shutdown . See bug 331413 .
+ * Don't do it in the WIN95 build configuration because clean shutdown is
+ * not implemented, and PR_SockOpt_Linger causes a hang in ssl.sh .
+ * See bug 332348 */
+ opt.option = PR_SockOpt_Linger;
+ opt.value.linger.polarity = PR_TRUE;
+ opt.value.linger.linger = PR_SecondsToInterval(1);
+ prStatus = PR_SetSocketOption(listen_sock, &opt);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_SetSocketOption(PR_SockOpt_Linger)");
+ }
+#endif
+
+ prStatus = PR_Bind(listen_sock, &addr);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_Bind");
+ }
+
+ prStatus = PR_Listen(listen_sock, listenQueueDepth);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_Listen");
+ }
+ return listen_sock;
+}
+
+void
+server_main(
+ PRFileDesc *listen_sock,
+ int requestCert,
+ SECKEYPrivateKey **privKey,
+ CERTCertificate **cert,
+ const char *expectedHostNameVal)
+{
+ PRFileDesc *model_sock = NULL;
+
+ /* Now, do the accepting, here in the main thread. */
+ do_accepts(listen_sock, model_sock, requestCert);
+
+ terminateWorkerThreads();
+
+ if (model_sock) {
+ PR_Close(model_sock);
+ }
+}
+
+int numChildren;
+PRProcess *child[MAX_PROCS];
+
+PRProcess *
+haveAChild(int argc, char **argv, PRProcessAttr *attr)
+{
+ PRProcess *newProcess;
+
+ newProcess = PR_CreateProcess(argv[0], argv, NULL, attr);
+ if (!newProcess) {
+ errWarn("Can't create new process.");
+ } else {
+ child[numChildren++] = newProcess;
+ }
+ return newProcess;
+}
+
+/* slightly adjusted version of ocsp_CreateCertID (not using issuer) */
+static CERTOCSPCertID *
+ocsp_CreateSelfCAID(PLArenaPool *arena, CERTCertificate *cert, PRTime time)
+{
+ CERTOCSPCertID *certID;
+ void *mark = PORT_ArenaMark(arena);
+ SECStatus rv;
+
+ PORT_Assert(arena != NULL);
+
+ certID = PORT_ArenaZNew(arena, CERTOCSPCertID);
+ if (certID == NULL) {
+ goto loser;
+ }
+
+ rv = SECOID_SetAlgorithmID(arena, &certID->hashAlgorithm, SEC_OID_SHA1,
+ NULL);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ if (CERT_GetSubjectNameDigest(arena, cert, SEC_OID_SHA1,
+ &(certID->issuerNameHash)) == NULL) {
+ goto loser;
+ }
+ certID->issuerSHA1NameHash.data = certID->issuerNameHash.data;
+ certID->issuerSHA1NameHash.len = certID->issuerNameHash.len;
+
+ if (CERT_GetSubjectNameDigest(arena, cert, SEC_OID_MD5,
+ &(certID->issuerMD5NameHash)) == NULL) {
+ goto loser;
+ }
+
+ if (CERT_GetSubjectNameDigest(arena, cert, SEC_OID_MD2,
+ &(certID->issuerMD2NameHash)) == NULL) {
+ goto loser;
+ }
+
+ if (CERT_GetSubjectPublicKeyDigest(arena, cert, SEC_OID_SHA1,
+ &certID->issuerKeyHash) == NULL) {
+ goto loser;
+ }
+ certID->issuerSHA1KeyHash.data = certID->issuerKeyHash.data;
+ certID->issuerSHA1KeyHash.len = certID->issuerKeyHash.len;
+ /* cache the other two hash algorithms as well */
+ if (CERT_GetSubjectPublicKeyDigest(arena, cert, SEC_OID_MD5,
+ &certID->issuerMD5KeyHash) == NULL) {
+ goto loser;
+ }
+ if (CERT_GetSubjectPublicKeyDigest(arena, cert, SEC_OID_MD2,
+ &certID->issuerMD2KeyHash) == NULL) {
+ goto loser;
+ }
+
+ PORT_ArenaUnmark(arena, mark);
+ return certID;
+
+loser:
+ PORT_ArenaRelease(arena, mark);
+ return NULL;
+}
+
+/* slightly adjusted version of CERT_CreateOCSPCertID */
+CERTOCSPCertID *
+cert_CreateSelfCAID(CERTCertificate *cert, PRTime time)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTOCSPCertID *certID;
+ PORT_Assert(arena != NULL);
+ if (!arena)
+ return NULL;
+
+ certID = ocsp_CreateSelfCAID(arena, cert, time);
+ if (!certID) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return NULL;
+ }
+ certID->poolp = arena;
+ return certID;
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progName = NULL;
+ const char *dir = ".";
+ char *passwd = NULL;
+ char *pwfile = NULL;
+ const char *pidFile = NULL;
+ char *tmp;
+ PRFileDesc *listen_sock;
+ int optionsFound = 0;
+ unsigned short port = 0;
+ SECStatus rv;
+ PRStatus prStatus;
+ PRBool bindOnly = PR_FALSE;
+ PRBool useLocalThreads = PR_FALSE;
+ PLOptState *optstate;
+ PLOptStatus status;
+ char emptyString[] = { "" };
+ char *certPrefix = emptyString;
+ caRevoInfo *revoInfo = NULL;
+ PRCList *caRevoIter = NULL;
+ PRBool provideOcsp = PR_FALSE;
+
+ tmp = strrchr(argv[0], '/');
+ tmp = tmp ? tmp + 1 : argv[0];
+ progName = strrchr(tmp, '\\');
+ progName = progName ? progName + 1 : tmp;
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ /* please keep this list of options in ASCII collating sequence.
+ ** numbers, then capital letters, then lower case, alphabetical.
+ */
+ optstate = PL_CreateOptState(argc, argv,
+ "A:C:DO:P:bd:f:hi:p:t:vw:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ ++optionsFound;
+ switch (optstate->option) {
+ /* A first, must be followed by C. Any other order is an error.
+ * A creates the object. C completes and moves into list.
+ */
+ case 'A':
+ provideOcsp = PR_TRUE;
+ if (revoInfo) {
+ Usage(progName);
+ exit(0);
+ }
+ revoInfo = PORT_New(caRevoInfo);
+ revoInfo->nickname = PORT_Strdup(optstate->value);
+ break;
+ case 'C':
+ if (!revoInfo) {
+ Usage(progName);
+ exit(0);
+ }
+ revoInfo->crlFilename = PORT_Strdup(optstate->value);
+ if (!caRevoInfos) {
+ PR_INIT_CLIST(&revoInfo->link);
+ caRevoInfos = revoInfo;
+ } else {
+ PR_APPEND_LINK(&revoInfo->link, &caRevoInfos->link);
+ }
+ revoInfo = NULL;
+ break;
+
+ case 'O':
+ if (!PL_strcasecmp(optstate->value, "all")) {
+ ocspMethodsAllowed = ocspGetAndPost;
+ } else if (!PL_strcasecmp(optstate->value, "get")) {
+ ocspMethodsAllowed = ocspGetOnly;
+ } else if (!PL_strcasecmp(optstate->value, "post")) {
+ ocspMethodsAllowed = ocspPostOnly;
+ } else if (!PL_strcasecmp(optstate->value, "random")) {
+ ocspMethodsAllowed = ocspRandomGetFailure;
+ } else if (!PL_strcasecmp(optstate->value, "get-unknown")) {
+ ocspMethodsAllowed = ocspGetUnknown;
+ } else {
+ Usage(progName);
+ exit(0);
+ }
+ break;
+
+ case 'D':
+ noDelay = PR_TRUE;
+ break;
+
+ case 'P':
+ certPrefix = PORT_Strdup(optstate->value);
+ break;
+
+ case 'b':
+ bindOnly = PR_TRUE;
+ break;
+
+ case 'd':
+ dir = optstate->value;
+ break;
+
+ case 'f':
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = pwfile = PORT_Strdup(optstate->value);
+ break;
+
+ case 'h':
+ Usage(progName);
+ exit(0);
+ break;
+
+ case 'i':
+ pidFile = optstate->value;
+ break;
+
+ case 'p':
+ port = PORT_Atoi(optstate->value);
+ break;
+
+ case 't':
+ maxThreads = PORT_Atoi(optstate->value);
+ if (maxThreads > MAX_THREADS)
+ maxThreads = MAX_THREADS;
+ if (maxThreads < MIN_THREADS)
+ maxThreads = MIN_THREADS;
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ case 'w':
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = passwd = PORT_Strdup(optstate->value);
+ break;
+
+ default:
+ case '?':
+ fprintf(stderr, "Unrecognized or bad option specified.\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(4);
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+ if (status == PL_OPT_BAD) {
+ fprintf(stderr, "Unrecognized or bad option specified.\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(5);
+ }
+ if (!optionsFound) {
+ Usage(progName);
+ exit(51);
+ }
+
+ /* The -b (bindOnly) option is only used by the ssl.sh test
+ * script on Linux to determine whether a previous httpserv
+ * process has fully died and freed the port. (Bug 129701)
+ */
+ if (bindOnly) {
+ listen_sock = getBoundListenSocket(port);
+ if (!listen_sock) {
+ exit(1);
+ }
+ if (listen_sock) {
+ PR_Close(listen_sock);
+ }
+ exit(0);
+ }
+
+ if (port == 0) {
+ fprintf(stderr, "Required argument 'port' must be non-zero value\n");
+ exit(7);
+ }
+
+ if (pidFile) {
+ FILE *tmpfile = fopen(pidFile, "w+");
+
+ if (tmpfile) {
+ fprintf(tmpfile, "%d", getpid());
+ fclose(tmpfile);
+ }
+ }
+
+ tmp = PR_GetEnvSecure("TMP");
+ if (!tmp)
+ tmp = PR_GetEnvSecure("TMPDIR");
+ if (!tmp)
+ tmp = PR_GetEnvSecure("TEMP");
+ /* we're an ordinary single process server. */
+ listen_sock = getBoundListenSocket(port);
+ prStatus = PR_SetFDInheritable(listen_sock, PR_FALSE);
+ if (prStatus != PR_SUCCESS)
+ errExit("PR_SetFDInheritable");
+
+ lm = PR_NewLogModule("TestCase");
+
+ /* set our password function */
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ if (provideOcsp) {
+ /* Call the NSS initialization routines */
+ rv = NSS_Initialize(dir, certPrefix, certPrefix, SECMOD_DB, NSS_INIT_READONLY);
+ if (rv != SECSuccess) {
+ fputs("NSS_Init failed.\n", stderr);
+ exit(8);
+ }
+
+ if (caRevoInfos) {
+ caRevoIter = &caRevoInfos->link;
+ do {
+ PRFileDesc *inFile;
+ int rv = SECFailure;
+ SECItem crlDER;
+ crlDER.data = NULL;
+
+ revoInfo = (caRevoInfo *)caRevoIter;
+ revoInfo->cert = CERT_FindCertByNickname(
+ CERT_GetDefaultCertDB(), revoInfo->nickname);
+ if (!revoInfo->cert) {
+ fprintf(stderr, "cannot find cert with nickname %s\n",
+ revoInfo->nickname);
+ exit(1);
+ }
+ inFile = PR_Open(revoInfo->crlFilename, PR_RDONLY, 0);
+ if (inFile) {
+ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
+ PR_Close(inFile);
+ inFile = NULL;
+ }
+ if (rv != SECSuccess) {
+ fprintf(stderr, "unable to read crl file %s\n",
+ revoInfo->crlFilename);
+ exit(1);
+ }
+ revoInfo->crl =
+ CERT_DecodeDERCrlWithFlags(NULL, &crlDER, SEC_CRL_TYPE,
+ CRL_DECODE_DEFAULT_OPTIONS);
+ SECITEM_FreeItem(&crlDER, PR_FALSE);
+ if (!revoInfo->crl) {
+ fprintf(stderr, "unable to decode crl file %s\n",
+ revoInfo->crlFilename);
+ exit(1);
+ }
+ if (CERT_CompareName(&revoInfo->crl->crl.name,
+ &revoInfo->cert->subject) != SECEqual) {
+ fprintf(stderr, "CRL %s doesn't match cert identified by preceding nickname %s\n",
+ revoInfo->crlFilename, revoInfo->nickname);
+ exit(1);
+ }
+ revoInfo->id = cert_CreateSelfCAID(revoInfo->cert, PR_Now());
+ caRevoIter = PR_NEXT_LINK(caRevoIter);
+ } while (caRevoIter != &caRevoInfos->link);
+ }
+ }
+
+ /* allocate the array of thread slots, and launch the worker threads. */
+ rv = launch_threads(&jobLoop, 0, 0, 0, useLocalThreads);
+
+ if (rv == SECSuccess) {
+ server_main(listen_sock, 0, 0, 0,
+ 0);
+ }
+
+ VLOG(("httpserv: server_thread: exiting"));
+
+ if (provideOcsp) {
+ if (caRevoInfos) {
+ PRCList *caRevoIter;
+
+ caRevoIter = &caRevoInfos->link;
+ do {
+ caRevoInfo *revoInfo = (caRevoInfo *)caRevoIter;
+ if (revoInfo->nickname)
+ PORT_Free(revoInfo->nickname);
+ if (revoInfo->crlFilename)
+ PORT_Free(revoInfo->crlFilename);
+ if (revoInfo->cert)
+ CERT_DestroyCertificate(revoInfo->cert);
+ if (revoInfo->id)
+ CERT_DestroyOCSPCertID(revoInfo->id);
+ if (revoInfo->crl)
+ SEC_DestroyCrl(revoInfo->crl);
+
+ caRevoIter = PR_NEXT_LINK(caRevoIter);
+ } while (caRevoIter != &caRevoInfos->link);
+ }
+ if (NSS_Shutdown() != SECSuccess) {
+ SECU_PrintError(progName, "NSS_Shutdown");
+ PR_Cleanup();
+ exit(1);
+ }
+ }
+ if (passwd) {
+ PORT_Free(passwd);
+ }
+ if (pwfile) {
+ PORT_Free(pwfile);
+ }
+ if (certPrefix && certPrefix != emptyString) {
+ PORT_Free(certPrefix);
+ }
+ PR_Cleanup();
+ printf("httpserv: normal termination\n");
+ return 0;
+}
diff --git a/security/nss/cmd/httpserv/httpserv.gyp b/security/nss/cmd/httpserv/httpserv.gyp
new file mode 100644
index 000000000..006706668
--- /dev/null
+++ b/security/nss/cmd/httpserv/httpserv.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'httpserv',
+ 'type': 'executable',
+ 'sources': [
+ 'httpserv.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/httpserv/manifest.mn b/security/nss/cmd/httpserv/manifest.mn
new file mode 100644
index 000000000..e96966110
--- /dev/null
+++ b/security/nss/cmd/httpserv/manifest.mn
@@ -0,0 +1,20 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = httpserv.c
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+PROGRAM = httpserv
+
diff --git a/security/nss/cmd/lib/Makefile b/security/nss/cmd/lib/Makefile
new file mode 100644
index 000000000..0fb6c9058
--- /dev/null
+++ b/security/nss/cmd/lib/Makefile
@@ -0,0 +1,49 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include config.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+export:: private_export
+
+
diff --git a/security/nss/cmd/lib/basicutil.c b/security/nss/cmd/lib/basicutil.c
new file mode 100644
index 000000000..dcd039391
--- /dev/null
+++ b/security/nss/cmd/lib/basicutil.c
@@ -0,0 +1,829 @@
+/* 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/. */
+/*
+** secutil.c - various functions used by security stuff
+**
+*/
+
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+#include "prerror.h"
+#include "prprf.h"
+#include "plgetopt.h"
+#include "prenv.h"
+#include "prnetdb.h"
+
+#include "basicutil.h"
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#endif
+
+#include "secoid.h"
+#include "sslt.h"
+
+extern long DER_GetInteger(const SECItem *src);
+
+static PRBool wrapEnabled = PR_TRUE;
+
+void
+SECU_EnableWrap(PRBool enable)
+{
+ wrapEnabled = enable;
+}
+
+PRBool
+SECU_GetWrapEnabled(void)
+{
+ return wrapEnabled;
+}
+
+void
+SECU_PrintErrMsg(FILE *out, int level, const char *progName, const char *msg,
+ ...)
+{
+ va_list args;
+ PRErrorCode err = PORT_GetError();
+ const char *errString = PORT_ErrorToString(err);
+
+ va_start(args, msg);
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s: ", progName);
+ vfprintf(out, msg, args);
+ if (errString != NULL && PORT_Strlen(errString) > 0)
+ fprintf(out, ": %s\n", errString);
+ else
+ fprintf(out, ": error %d\n", (int)err);
+
+ va_end(args);
+}
+
+void
+SECU_PrintError(const char *progName, const char *msg, ...)
+{
+ va_list args;
+ PRErrorCode err = PORT_GetError();
+ const char *errName = PR_ErrorToName(err);
+ const char *errString = PR_ErrorToString(err, 0);
+
+ va_start(args, msg);
+
+ fprintf(stderr, "%s: ", progName);
+ vfprintf(stderr, msg, args);
+
+ if (errName != NULL) {
+ fprintf(stderr, ": %s", errName);
+ } else {
+ fprintf(stderr, ": error %d", (int)err);
+ }
+
+ if (errString != NULL && PORT_Strlen(errString) > 0)
+ fprintf(stderr, ": %s\n", errString);
+
+ va_end(args);
+}
+
+void
+SECU_PrintSystemError(const char *progName, const char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ fprintf(stderr, "%s: ", progName);
+ vfprintf(stderr, msg, args);
+ fprintf(stderr, ": %s\n", strerror(errno));
+ va_end(args);
+}
+
+SECStatus
+secu_StdinToItem(SECItem *dst)
+{
+ unsigned char buf[1000];
+ PRInt32 numBytes;
+ PRBool notDone = PR_TRUE;
+
+ dst->len = 0;
+ dst->data = NULL;
+
+ while (notDone) {
+ numBytes = PR_Read(PR_STDIN, buf, sizeof(buf));
+
+ if (numBytes < 0) {
+ return SECFailure;
+ }
+
+ if (numBytes == 0)
+ break;
+
+ if (dst->data) {
+ unsigned char *p = dst->data;
+ dst->data = (unsigned char *)PORT_Realloc(p, dst->len + numBytes);
+ if (!dst->data) {
+ PORT_Free(p);
+ }
+ } else {
+ dst->data = (unsigned char *)PORT_Alloc(numBytes);
+ }
+ if (!dst->data) {
+ return SECFailure;
+ }
+ PORT_Memcpy(dst->data + dst->len, buf, numBytes);
+ dst->len += numBytes;
+ }
+
+ return SECSuccess;
+}
+
+SECStatus
+SECU_FileToItem(SECItem *dst, PRFileDesc *src)
+{
+ PRFileInfo info;
+ PRInt32 numBytes;
+ PRStatus prStatus;
+
+ if (src == PR_STDIN)
+ return secu_StdinToItem(dst);
+
+ prStatus = PR_GetOpenFileInfo(src, &info);
+
+ if (prStatus != PR_SUCCESS) {
+ PORT_SetError(SEC_ERROR_IO);
+ return SECFailure;
+ }
+
+ /* XXX workaround for 3.1, not all utils zero dst before sending */
+ dst->data = 0;
+ if (!SECITEM_AllocItem(NULL, dst, info.size))
+ goto loser;
+
+ numBytes = PR_Read(src, dst->data, info.size);
+ if (numBytes != info.size) {
+ PORT_SetError(SEC_ERROR_IO);
+ goto loser;
+ }
+
+ return SECSuccess;
+loser:
+ SECITEM_FreeItem(dst, PR_FALSE);
+ dst->data = NULL;
+ return SECFailure;
+}
+
+SECStatus
+SECU_TextFileToItem(SECItem *dst, PRFileDesc *src)
+{
+ PRFileInfo info;
+ PRInt32 numBytes;
+ PRStatus prStatus;
+ unsigned char *buf;
+
+ if (src == PR_STDIN)
+ return secu_StdinToItem(dst);
+
+ prStatus = PR_GetOpenFileInfo(src, &info);
+
+ if (prStatus != PR_SUCCESS) {
+ PORT_SetError(SEC_ERROR_IO);
+ return SECFailure;
+ }
+
+ buf = (unsigned char *)PORT_Alloc(info.size);
+ if (!buf)
+ return SECFailure;
+
+ numBytes = PR_Read(src, buf, info.size);
+ if (numBytes != info.size) {
+ PORT_SetError(SEC_ERROR_IO);
+ goto loser;
+ }
+
+ if (buf[numBytes - 1] == '\n')
+ numBytes--;
+#ifdef _WINDOWS
+ if (buf[numBytes - 1] == '\r')
+ numBytes--;
+#endif
+
+ /* XXX workaround for 3.1, not all utils zero dst before sending */
+ dst->data = 0;
+ if (!SECITEM_AllocItem(NULL, dst, numBytes))
+ goto loser;
+
+ memcpy(dst->data, buf, numBytes);
+
+ PORT_Free(buf);
+ return SECSuccess;
+loser:
+ PORT_Free(buf);
+ return SECFailure;
+}
+
+#define INDENT_MULT 4
+void
+SECU_Indent(FILE *out, int level)
+{
+ int i;
+
+ for (i = 0; i < level; i++) {
+ fprintf(out, " ");
+ }
+}
+
+void
+SECU_Newline(FILE *out)
+{
+ fprintf(out, "\n");
+}
+
+void
+SECU_PrintAsHex(FILE *out, const SECItem *data, const char *m, int level)
+{
+ unsigned i;
+ int column = 0;
+ PRBool isString = PR_TRUE;
+ PRBool isWhiteSpace = PR_TRUE;
+ PRBool printedHex = PR_FALSE;
+ unsigned int limit = 15;
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s:", m);
+ level++;
+ if (wrapEnabled)
+ fprintf(out, "\n");
+ }
+
+ if (wrapEnabled) {
+ SECU_Indent(out, level);
+ column = level * INDENT_MULT;
+ }
+ if (!data->len) {
+ fprintf(out, "(empty)\n");
+ return;
+ }
+ /* take a pass to see if it's all printable. */
+ for (i = 0; i < data->len; i++) {
+ unsigned char val = data->data[i];
+ if (!val || !isprint(val)) {
+ isString = PR_FALSE;
+ break;
+ }
+ if (isWhiteSpace && !isspace(val)) {
+ isWhiteSpace = PR_FALSE;
+ }
+ }
+
+ /* Short values, such as bit strings (which are printed with this
+ ** function) often look like strings, but we want to see the bits.
+ ** so this test assures that short values will be printed in hex,
+ ** perhaps in addition to being printed as strings.
+ ** The threshold size (4 bytes) is arbitrary.
+ */
+ if (!isString || data->len <= 4) {
+ for (i = 0; i < data->len; i++) {
+ if (i != data->len - 1) {
+ fprintf(out, "%02x:", data->data[i]);
+ column += 3;
+ } else {
+ fprintf(out, "%02x", data->data[i]);
+ column += 2;
+ break;
+ }
+ if (wrapEnabled &&
+ (column > 76 || (i % 16 == limit))) {
+ SECU_Newline(out);
+ SECU_Indent(out, level);
+ column = level * INDENT_MULT;
+ limit = i % 16;
+ }
+ }
+ printedHex = PR_TRUE;
+ }
+ if (isString && !isWhiteSpace) {
+ if (printedHex != PR_FALSE) {
+ SECU_Newline(out);
+ SECU_Indent(out, level);
+ column = level * INDENT_MULT;
+ }
+ for (i = 0; i < data->len; i++) {
+ unsigned char val = data->data[i];
+
+ if (val) {
+ fprintf(out, "%c", val);
+ column++;
+ } else {
+ column = 77;
+ }
+ if (wrapEnabled && column > 76) {
+ SECU_Newline(out);
+ SECU_Indent(out, level);
+ column = level * INDENT_MULT;
+ }
+ }
+ }
+
+ if (column != level * INDENT_MULT) {
+ SECU_Newline(out);
+ }
+}
+
+const char *hex = "0123456789abcdef";
+
+const char printable[257] = {
+ "................" /* 0x */
+ "................" /* 1x */
+ " !\"#$%&'()*+,-./" /* 2x */
+ "0123456789:;<=>?" /* 3x */
+ "@ABCDEFGHIJKLMNO" /* 4x */
+ "PQRSTUVWXYZ[\\]^_" /* 5x */
+ "`abcdefghijklmno" /* 6x */
+ "pqrstuvwxyz{|}~." /* 7x */
+ "................" /* 8x */
+ "................" /* 9x */
+ "................" /* ax */
+ "................" /* bx */
+ "................" /* cx */
+ "................" /* dx */
+ "................" /* ex */
+ "................" /* fx */
+};
+
+void
+SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len)
+{
+ const unsigned char *cp = (const unsigned char *)vp;
+ char buf[80];
+ char *bp;
+ char *ap;
+
+ fprintf(out, "%s [Len: %d]\n", msg, len);
+ memset(buf, ' ', sizeof buf);
+ bp = buf;
+ ap = buf + 50;
+ while (--len >= 0) {
+ unsigned char ch = *cp++;
+ *bp++ = hex[(ch >> 4) & 0xf];
+ *bp++ = hex[ch & 0xf];
+ *bp++ = ' ';
+ *ap++ = printable[ch];
+ if (ap - buf >= 66) {
+ *ap = 0;
+ fprintf(out, " %s\n", buf);
+ memset(buf, ' ', sizeof buf);
+ bp = buf;
+ ap = buf + 50;
+ }
+ }
+ if (bp > buf) {
+ *ap = 0;
+ fprintf(out, " %s\n", buf);
+ }
+}
+
+/* This expents i->data[0] to be the MSB of the integer.
+** if you want to print a DER-encoded integer (with the tag and length)
+** call SECU_PrintEncodedInteger();
+*/
+void
+SECU_PrintInteger(FILE *out, const SECItem *i, const char *m, int level)
+{
+ int iv;
+
+ if (!i || !i->len || !i->data) {
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: (null)\n", m);
+ } else {
+ fprintf(out, "(null)\n");
+ }
+ } else if (i->len > 4) {
+ SECU_PrintAsHex(out, i, m, level);
+ } else {
+ if (i->type == siUnsignedInteger && *i->data & 0x80) {
+ /* Make sure i->data has zero in the highest bite
+ * if i->data is an unsigned integer */
+ SECItem tmpI;
+ char data[] = { 0, 0, 0, 0, 0 };
+
+ PORT_Memcpy(data + 1, i->data, i->len);
+ tmpI.len = i->len + 1;
+ tmpI.data = (void *)data;
+
+ iv = DER_GetInteger(&tmpI);
+ } else {
+ iv = DER_GetInteger(i);
+ }
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: %d (0x%x)\n", m, iv, iv);
+ } else {
+ fprintf(out, "%d (0x%x)\n", iv, iv);
+ }
+ }
+}
+
+#if defined(DEBUG) || defined(FORCE_PR_ASSERT)
+/* Returns true iff a[i].flag has a duplicate in a[i+1 : count-1] */
+static PRBool
+HasShortDuplicate(int i, secuCommandFlag *a, int count)
+{
+ char target = a[i].flag;
+ int j;
+
+ /* duplicate '\0' flags are okay, they are used with long forms */
+ for (j = i + 1; j < count; j++) {
+ if (a[j].flag && a[j].flag == target) {
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+/* Returns true iff a[i].longform has a duplicate in a[i+1 : count-1] */
+static PRBool
+HasLongDuplicate(int i, secuCommandFlag *a, int count)
+{
+ int j;
+ char *target = a[i].longform;
+
+ if (!target)
+ return PR_FALSE;
+
+ for (j = i + 1; j < count; j++) {
+ if (a[j].longform && strcmp(a[j].longform, target) == 0) {
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+/* Returns true iff a has no short or long form duplicates
+ */
+PRBool
+HasNoDuplicates(secuCommandFlag *a, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (a[i].flag && HasShortDuplicate(i, a, count)) {
+ return PR_FALSE;
+ }
+ if (a[i].longform && HasLongDuplicate(i, a, count)) {
+ return PR_FALSE;
+ }
+ }
+ return PR_TRUE;
+}
+#endif
+
+SECStatus
+SECU_ParseCommandLine(int argc, char **argv, char *progName,
+ const secuCommand *cmd)
+{
+ PRBool found;
+ PLOptState *optstate;
+ PLOptStatus status;
+ char *optstring;
+ PLLongOpt *longopts = NULL;
+ int i, j;
+ int lcmd = 0, lopt = 0;
+
+ PR_ASSERT(HasNoDuplicates(cmd->commands, cmd->numCommands));
+ PR_ASSERT(HasNoDuplicates(cmd->options, cmd->numOptions));
+
+ optstring = (char *)PORT_Alloc(cmd->numCommands + 2 * cmd->numOptions + 1);
+ if (optstring == NULL)
+ return SECFailure;
+
+ j = 0;
+ for (i = 0; i < cmd->numCommands; i++) {
+ if (cmd->commands[i].flag) /* single character option ? */
+ optstring[j++] = cmd->commands[i].flag;
+ if (cmd->commands[i].longform)
+ lcmd++;
+ }
+ for (i = 0; i < cmd->numOptions; i++) {
+ if (cmd->options[i].flag) {
+ optstring[j++] = cmd->options[i].flag;
+ if (cmd->options[i].needsArg)
+ optstring[j++] = ':';
+ }
+ if (cmd->options[i].longform)
+ lopt++;
+ }
+
+ optstring[j] = '\0';
+
+ if (lcmd + lopt > 0) {
+ longopts = PORT_NewArray(PLLongOpt, lcmd + lopt + 1);
+ if (!longopts) {
+ PORT_Free(optstring);
+ return SECFailure;
+ }
+
+ j = 0;
+ for (i = 0; j < lcmd && i < cmd->numCommands; i++) {
+ if (cmd->commands[i].longform) {
+ longopts[j].longOptName = cmd->commands[i].longform;
+ longopts[j].longOption = 0;
+ longopts[j++].valueRequired = cmd->commands[i].needsArg;
+ }
+ }
+ lopt += lcmd;
+ for (i = 0; j < lopt && i < cmd->numOptions; i++) {
+ if (cmd->options[i].longform) {
+ longopts[j].longOptName = cmd->options[i].longform;
+ longopts[j].longOption = 0;
+ longopts[j++].valueRequired = cmd->options[i].needsArg;
+ }
+ }
+ longopts[j].longOptName = NULL;
+ }
+
+ optstate = PL_CreateLongOptState(argc, argv, optstring, longopts);
+ if (!optstate) {
+ PORT_Free(optstring);
+ PORT_Free(longopts);
+ return SECFailure;
+ }
+ /* Parse command line arguments */
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ const char *optstatelong;
+ char option = optstate->option;
+
+ /* positional parameter, single-char option or long opt? */
+ if (optstate->longOptIndex == -1) {
+ /* not a long opt */
+ if (option == '\0')
+ continue; /* it's a positional parameter */
+ optstatelong = "";
+ } else {
+ /* long opt */
+ if (option == '\0')
+ option = '\377'; /* force unequal with all flags */
+ optstatelong = longopts[optstate->longOptIndex].longOptName;
+ }
+
+ found = PR_FALSE;
+
+ for (i = 0; i < cmd->numCommands; i++) {
+ if (cmd->commands[i].flag == option ||
+ cmd->commands[i].longform == optstatelong) {
+ cmd->commands[i].activated = PR_TRUE;
+ if (optstate->value) {
+ cmd->commands[i].arg = (char *)optstate->value;
+ }
+ found = PR_TRUE;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ for (i = 0; i < cmd->numOptions; i++) {
+ if (cmd->options[i].flag == option ||
+ cmd->options[i].longform == optstatelong) {
+ cmd->options[i].activated = PR_TRUE;
+ if (optstate->value) {
+ cmd->options[i].arg = (char *)optstate->value;
+ } else if (cmd->options[i].needsArg) {
+ status = PL_OPT_BAD;
+ goto loser;
+ }
+ found = PR_TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ status = PL_OPT_BAD;
+ break;
+ }
+ }
+
+loser:
+ PL_DestroyOptState(optstate);
+ PORT_Free(optstring);
+ if (longopts)
+ PORT_Free(longopts);
+ if (status == PL_OPT_BAD)
+ return SECFailure;
+ return SECSuccess;
+}
+
+char *
+SECU_GetOptionArg(const secuCommand *cmd, int optionNum)
+{
+ if (optionNum < 0 || optionNum >= cmd->numOptions)
+ return NULL;
+ if (cmd->options[optionNum].activated)
+ return PL_strdup(cmd->options[optionNum].arg);
+ else
+ return NULL;
+}
+
+void
+SECU_PrintPRandOSError(const char *progName)
+{
+ char buffer[513];
+ PRInt32 errLen = PR_GetErrorTextLength();
+ if (errLen > 0 && errLen < sizeof buffer) {
+ PR_GetErrorText(buffer);
+ }
+ SECU_PrintError(progName, "function failed");
+ if (errLen > 0 && errLen < sizeof buffer) {
+ PR_fprintf(PR_STDERR, "\t%s\n", buffer);
+ }
+}
+
+SECOidTag
+SECU_StringToSignatureAlgTag(const char *alg)
+{
+ SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
+
+ if (alg) {
+ if (!PL_strcmp(alg, "MD2")) {
+ hashAlgTag = SEC_OID_MD2;
+ } else if (!PL_strcmp(alg, "MD4")) {
+ hashAlgTag = SEC_OID_MD4;
+ } else if (!PL_strcmp(alg, "MD5")) {
+ hashAlgTag = SEC_OID_MD5;
+ } else if (!PL_strcmp(alg, "SHA1")) {
+ hashAlgTag = SEC_OID_SHA1;
+ } else if (!PL_strcmp(alg, "SHA224")) {
+ hashAlgTag = SEC_OID_SHA224;
+ } else if (!PL_strcmp(alg, "SHA256")) {
+ hashAlgTag = SEC_OID_SHA256;
+ } else if (!PL_strcmp(alg, "SHA384")) {
+ hashAlgTag = SEC_OID_SHA384;
+ } else if (!PL_strcmp(alg, "SHA512")) {
+ hashAlgTag = SEC_OID_SHA512;
+ }
+ }
+ return hashAlgTag;
+}
+
+/* Caller ensures that dst is at least item->len*2+1 bytes long */
+void
+SECU_SECItemToHex(const SECItem *item, char *dst)
+{
+ if (dst && item && item->data) {
+ unsigned char *src = item->data;
+ unsigned int len = item->len;
+ for (; len > 0; --len, dst += 2) {
+ sprintf(dst, "%02x", *src++);
+ }
+ *dst = '\0';
+ }
+}
+
+static unsigned char
+nibble(char c)
+{
+ c = PORT_Tolower(c);
+ return (c >= '0' && c <= '9') ? c - '0' : (c >= 'a' && c <= 'f') ? c - 'a' + 10 : -1;
+}
+
+SECStatus
+SECU_SECItemHexStringToBinary(SECItem *srcdest)
+{
+ unsigned int i;
+
+ if (!srcdest) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ if (srcdest->len < 4 || (srcdest->len % 2)) {
+ /* too short to convert, or even number of characters */
+ PORT_SetError(SEC_ERROR_BAD_DATA);
+ return SECFailure;
+ }
+ if (PORT_Strncasecmp((const char *)srcdest->data, "0x", 2)) {
+ /* wrong prefix */
+ PORT_SetError(SEC_ERROR_BAD_DATA);
+ return SECFailure;
+ }
+
+ /* 1st pass to check for hex characters */
+ for (i = 2; i < srcdest->len; i++) {
+ char c = PORT_Tolower(srcdest->data[i]);
+ if (!((c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'f'))) {
+ PORT_SetError(SEC_ERROR_BAD_DATA);
+ return SECFailure;
+ }
+ }
+
+ /* 2nd pass to convert */
+ for (i = 2; i < srcdest->len; i += 2) {
+ srcdest->data[(i - 2) / 2] = (nibble(srcdest->data[i]) << 4) +
+ nibble(srcdest->data[i + 1]);
+ }
+
+ /* adjust length */
+ srcdest->len -= 2;
+ srcdest->len /= 2;
+ return SECSuccess;
+}
+
+SSLNamedGroup
+groupNameToNamedGroup(char *name)
+{
+ if (PL_strlen(name) == 4) {
+ if (!strncmp(name, "P256", 4)) {
+ return ssl_grp_ec_secp256r1;
+ }
+ if (!strncmp(name, "P384", 4)) {
+ return ssl_grp_ec_secp384r1;
+ }
+ if (!strncmp(name, "P521", 4)) {
+ return ssl_grp_ec_secp521r1;
+ }
+ }
+ if (PL_strlen(name) == 6) {
+ if (!strncmp(name, "x25519", 6)) {
+ return ssl_grp_ec_curve25519;
+ }
+ if (!strncmp(name, "FF2048", 6)) {
+ return ssl_grp_ffdhe_2048;
+ }
+ if (!strncmp(name, "FF3072", 6)) {
+ return ssl_grp_ffdhe_3072;
+ }
+ if (!strncmp(name, "FF4096", 6)) {
+ return ssl_grp_ffdhe_4096;
+ }
+ if (!strncmp(name, "FF6144", 6)) {
+ return ssl_grp_ffdhe_6144;
+ }
+ if (!strncmp(name, "FF8192", 6)) {
+ return ssl_grp_ffdhe_8192;
+ }
+ }
+
+ return ssl_grp_none;
+}
+
+SECStatus
+parseGroupList(const char *arg, SSLNamedGroup **enabledGroups,
+ unsigned int *enabledGroupsCount)
+{
+ SSLNamedGroup *groups;
+ char *str;
+ char *p;
+ unsigned int numValues = 0;
+ unsigned int count = 0;
+
+ /* Count the number of groups. */
+ str = PORT_Strdup(arg);
+ if (!str) {
+ return SECFailure;
+ }
+ p = strtok(str, ",");
+ while (p) {
+ ++numValues;
+ p = strtok(NULL, ",");
+ }
+ PORT_Free(str);
+ str = NULL;
+ groups = PORT_ZNewArray(SSLNamedGroup, numValues);
+ if (!groups) {
+ goto done;
+ }
+
+ /* Get group names. */
+ str = PORT_Strdup(arg);
+ if (!str) {
+ goto done;
+ }
+ p = strtok(str, ",");
+ while (p) {
+ SSLNamedGroup group = groupNameToNamedGroup(p);
+ if (group == ssl_grp_none) {
+ count = 0;
+ goto done;
+ }
+ groups[count++] = group;
+ p = strtok(NULL, ",");
+ }
+
+done:
+ if (str) {
+ PORT_Free(str);
+ }
+ if (!count) {
+ PORT_Free(groups);
+ return SECFailure;
+ }
+
+ *enabledGroupsCount = count;
+ *enabledGroups = groups;
+ return SECSuccess;
+}
diff --git a/security/nss/cmd/lib/basicutil.h b/security/nss/cmd/lib/basicutil.h
new file mode 100644
index 000000000..345fd91a4
--- /dev/null
+++ b/security/nss/cmd/lib/basicutil.h
@@ -0,0 +1,137 @@
+/* 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 _BASIC_UTILS_H_
+#define _BASIC_UTILS_H_
+
+#include "seccomon.h"
+#include "secitem.h"
+#include "secoid.h"
+#include "secoidt.h"
+#include "secport.h"
+#include "prerror.h"
+#include "base64.h"
+#include "secasn1.h"
+#include "secder.h"
+#include "sslt.h"
+#include <stdio.h>
+
+#ifdef SECUTIL_NEW
+typedef int (*SECU_PPFunc)(PRFileDesc *out, SECItem *item,
+ char *msg, int level);
+#else
+typedef int (*SECU_PPFunc)(FILE *out, SECItem *item, char *msg, int level);
+#endif
+
+/* print out an error message */
+extern void SECU_PrintError(const char *progName, const char *msg, ...);
+
+/* print out a system error message */
+extern void SECU_PrintSystemError(const char *progName, const char *msg, ...);
+
+/* print a formatted error message */
+extern void SECU_PrintErrMsg(FILE *out, int level, const char *progName,
+ const char *msg, ...);
+
+/* Read the contents of a file into a SECItem */
+extern SECStatus SECU_FileToItem(SECItem *dst, PRFileDesc *src);
+extern SECStatus SECU_TextFileToItem(SECItem *dst, PRFileDesc *src);
+
+/* Indent based on "level" */
+extern void SECU_Indent(FILE *out, int level);
+
+/* Print a newline to out */
+extern void SECU_Newline(FILE *out);
+
+/* Print integer value and hex */
+extern void SECU_PrintInteger(FILE *out, const SECItem *i, const char *m,
+ int level);
+
+/* Print SECItem as hex */
+extern void SECU_PrintAsHex(FILE *out, const SECItem *i, const char *m,
+ int level);
+
+/* dump a buffer in hex and ASCII */
+extern void SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len);
+
+#ifdef HAVE_EPV_TEMPLATE
+/* Dump contents of private key */
+extern int SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level);
+#endif
+
+/* Init PKCS11 stuff */
+extern SECStatus SECU_PKCS11Init(PRBool readOnly);
+
+/* Dump contents of signed data */
+extern int SECU_PrintSignedData(FILE *out, SECItem *der, const char *m,
+ int level, SECU_PPFunc inner);
+
+extern void SECU_PrintString(FILE *out, const SECItem *si, const char *m,
+ int level);
+extern void SECU_PrintAny(FILE *out, const SECItem *i, const char *m, int level);
+
+extern void SECU_PrintPRandOSError(const char *progName);
+
+/* Caller ensures that dst is at least item->len*2+1 bytes long */
+void
+SECU_SECItemToHex(const SECItem *item, char *dst);
+
+/* Requires 0x prefix. Case-insensitive. Will do in-place replacement if
+ * successful */
+SECStatus
+SECU_SECItemHexStringToBinary(SECItem *srcdest);
+
+/*
+ *
+ * Utilities for parsing security tools command lines
+ *
+ */
+
+/* A single command flag */
+typedef struct {
+ char flag;
+ PRBool needsArg;
+ char *arg;
+ PRBool activated;
+ char *longform;
+} secuCommandFlag;
+
+/* A full array of command/option flags */
+typedef struct
+{
+ int numCommands;
+ int numOptions;
+
+ secuCommandFlag *commands;
+ secuCommandFlag *options;
+} secuCommand;
+
+/* fill the "arg" and "activated" fields for each flag */
+SECStatus
+SECU_ParseCommandLine(int argc, char **argv, char *progName,
+ const secuCommand *cmd);
+char *
+SECU_GetOptionArg(const secuCommand *cmd, int optionNum);
+
+SECStatus parseGroupList(const char *arg, SSLNamedGroup **enabledGroups,
+ unsigned int *enabledGroupsCount);
+SSLNamedGroup groupNameToNamedGroup(char *name);
+
+/*
+ *
+ * Error messaging
+ *
+ */
+
+void printflags(char *trusts, unsigned int flags);
+
+#if !defined(XP_UNIX) && !defined(XP_OS2)
+extern int ffs(unsigned int i);
+#endif
+
+#include "secerr.h"
+
+extern const char *hex;
+extern const char printable[];
+
+#endif /* _BASIC_UTILS_H_ */
diff --git a/security/nss/cmd/lib/berparse.c b/security/nss/cmd/lib/berparse.c
new file mode 100644
index 000000000..8cd1ebae0
--- /dev/null
+++ b/security/nss/cmd/lib/berparse.c
@@ -0,0 +1,388 @@
+/* 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/. */
+#include "secutil.h"
+
+typedef enum {
+ tagDone,
+ lengthDone,
+ leafDone,
+ compositeDone,
+ notDone,
+ parseError,
+ parseComplete
+} ParseState;
+
+typedef unsigned char Byte;
+typedef void (*ParseProc)(BERParse *h, unsigned char **buf, int *len);
+typedef struct {
+ SECArb arb;
+ int pos; /* length from global start to item start */
+ SECArb *parent;
+} ParseStackElem;
+
+struct BERParseStr {
+ PLArenaPool *his;
+ PLArenaPool *mine;
+ ParseProc proc;
+ int stackDepth;
+ ParseStackElem *stackPtr;
+ ParseStackElem *stack;
+ int pending; /* bytes remaining to complete this part */
+ int pos; /* running length of consumed characters */
+ ParseState state;
+ PRBool keepLeaves;
+ PRBool derOnly;
+ BERFilterProc filter;
+ void *filterArg;
+ BERNotifyProc before;
+ void *beforeArg;
+ BERNotifyProc after;
+ void *afterArg;
+};
+
+#define UNKNOWN -1
+
+static unsigned char
+NextChar(BERParse *h, unsigned char **buf, int *len)
+{
+ unsigned char c = *(*buf)++;
+ (*len)--;
+ h->pos++;
+ if (h->filter)
+ (*h->filter)(h->filterArg, &c, 1);
+ return c;
+}
+
+static void
+ParseTag(BERParse *h, unsigned char **buf, int *len)
+{
+ SECArb *arb = &(h->stackPtr->arb);
+ arb->tag = NextChar(h, buf, len);
+
+ PORT_Assert(h->state == notDone);
+
+ /*
+ * NOTE: This does not handle the high-tag-number form
+ */
+ if ((arb->tag & DER_HIGH_TAG_NUMBER) == DER_HIGH_TAG_NUMBER) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return;
+ }
+
+ h->pending = UNKNOWN;
+ arb->length = UNKNOWN;
+ if (arb->tag & DER_CONSTRUCTED) {
+ arb->body.cons.numSubs = 0;
+ arb->body.cons.subs = NULL;
+ } else {
+ arb->body.item.len = UNKNOWN;
+ arb->body.item.data = NULL;
+ }
+
+ h->state = tagDone;
+}
+
+static void
+ParseLength(BERParse *h, unsigned char **buf, int *len)
+{
+ Byte b;
+ SECArb *arb = &(h->stackPtr->arb);
+
+ PORT_Assert(h->state == notDone);
+
+ if (h->pending == UNKNOWN) {
+ b = NextChar(h, buf, len);
+ if ((b & 0x80) == 0) { /* short form */
+ arb->length = b;
+ /*
+ * if the tag and the length are both zero bytes, then this
+ * should be the marker showing end of list for the
+ * indefinite length composite
+ */
+ if (arb->length == 0 && arb->tag == 0)
+ h->state = compositeDone;
+ else
+ h->state = lengthDone;
+ return;
+ }
+
+ h->pending = b & 0x7f;
+ /* 0 implies this is an indefinite length */
+ if (h->pending > 4) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return;
+ }
+ arb->length = 0;
+ }
+
+ while ((*len > 0) && (h->pending > 0)) {
+ b = NextChar(h, buf, len);
+ arb->length = (arb->length << 8) + b;
+ h->pending--;
+ }
+ if (h->pending == 0) {
+ if (h->derOnly && (arb->length == 0))
+ h->state = parseError;
+ else
+ h->state = lengthDone;
+ }
+ return;
+}
+
+static void
+ParseLeaf(BERParse *h, unsigned char **buf, int *len)
+{
+ int count;
+ SECArb *arb = &(h->stackPtr->arb);
+
+ PORT_Assert(h->state == notDone);
+ PORT_Assert(h->pending >= 0);
+
+ if (*len < h->pending)
+ count = *len;
+ else
+ count = h->pending;
+
+ if (h->keepLeaves)
+ memcpy(arb->body.item.data + arb->body.item.len, *buf, count);
+ if (h->filter)
+ (*h->filter)(h->filterArg, *buf, count);
+ *buf += count;
+ *len -= count;
+ arb->body.item.len += count;
+ h->pending -= count;
+ h->pos += count;
+ if (h->pending == 0) {
+ h->state = leafDone;
+ }
+ return;
+}
+
+static void
+CreateArbNode(BERParse *h)
+{
+ SECArb *arb = PORT_ArenaAlloc(h->his, sizeof(SECArb));
+
+ *arb = h->stackPtr->arb;
+
+ /*
+ * Special case closing the root
+ */
+ if (h->stackPtr == h->stack) {
+ PORT_Assert(arb->tag & DER_CONSTRUCTED);
+ h->state = parseComplete;
+ } else {
+ SECArb *parent = h->stackPtr->parent;
+ parent->body.cons.subs = DS_ArenaGrow(
+ h->his, parent->body.cons.subs,
+ (parent->body.cons.numSubs) * sizeof(SECArb *),
+ (parent->body.cons.numSubs + 1) * sizeof(SECArb *));
+ parent->body.cons.subs[parent->body.cons.numSubs] = arb;
+ parent->body.cons.numSubs++;
+ h->proc = ParseTag;
+ h->state = notDone;
+ h->pending = UNKNOWN;
+ }
+ if (h->after)
+ (*h->after)(h->afterArg, arb, h->stackPtr - h->stack, PR_FALSE);
+}
+
+SECStatus
+BER_ParseSome(BERParse *h, unsigned char *buf, int len)
+{
+ if (h->state == parseError)
+ return PR_TRUE;
+
+ while (len) {
+ (*h->proc)(h, &buf, &len);
+ if (h->state == parseComplete) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return PR_TRUE;
+ }
+ if (h->state == parseError)
+ return PR_TRUE;
+ PORT_Assert(h->state != parseComplete);
+
+ if (h->state <= compositeDone) {
+ if (h->proc == ParseTag) {
+ PORT_Assert(h->state == tagDone);
+ h->proc = ParseLength;
+ h->state = notDone;
+ } else if (h->proc == ParseLength) {
+ SECArb *arb = &(h->stackPtr->arb);
+ PORT_Assert(h->state == lengthDone || h->state == compositeDone);
+
+ if (h->before)
+ (*h->before)(h->beforeArg, arb,
+ h->stackPtr - h->stack, PR_TRUE);
+
+ /*
+ * Check to see if this is the end of an indefinite
+ * length composite
+ */
+ if (h->state == compositeDone) {
+ SECArb *parent = h->stackPtr->parent;
+ PORT_Assert(parent);
+ PORT_Assert(parent->tag & DER_CONSTRUCTED);
+ if (parent->length != 0) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return PR_TRUE;
+ }
+ /*
+ * NOTE: This does not check for an indefinite length
+ * composite being contained inside a definite length
+ * composite. It is not clear that is legal.
+ */
+ h->stackPtr--;
+ CreateArbNode(h);
+ } else {
+ h->stackPtr->pos = h->pos;
+
+ if (arb->tag & DER_CONSTRUCTED) {
+ SECArb *parent;
+ /*
+ * Make sure there is room on the stack before we
+ * stick anything else there.
+ */
+ PORT_Assert(h->stackPtr - h->stack < h->stackDepth);
+ if (h->stackPtr - h->stack == h->stackDepth - 1) {
+ int newDepth = h->stackDepth * 2;
+ h->stack = DS_ArenaGrow(h->mine, h->stack,
+ sizeof(ParseStackElem) *
+ h->stackDepth,
+ sizeof(ParseStackElem) *
+ newDepth);
+ h->stackPtr = h->stack + h->stackDepth + 1;
+ h->stackDepth = newDepth;
+ }
+ parent = &(h->stackPtr->arb);
+ h->stackPtr++;
+ h->stackPtr->parent = parent;
+ h->proc = ParseTag;
+ h->state = notDone;
+ h->pending = UNKNOWN;
+ } else {
+ if (arb->length < 0) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return PR_TRUE;
+ }
+ arb->body.item.len = 0;
+ if (arb->length > 0 && h->keepLeaves) {
+ arb->body.item.data =
+ PORT_ArenaAlloc(h->his, arb->length);
+ } else {
+ arb->body.item.data = NULL;
+ }
+ h->proc = ParseLeaf;
+ h->state = notDone;
+ h->pending = arb->length;
+ }
+ }
+ } else {
+ ParseStackElem *parent;
+ PORT_Assert(h->state = leafDone);
+ PORT_Assert(h->proc == ParseLeaf);
+
+ for (;;) {
+ CreateArbNode(h);
+ if (h->stackPtr == h->stack)
+ break;
+ parent = (h->stackPtr - 1);
+ PORT_Assert(parent->arb.tag & DER_CONSTRUCTED);
+ if (parent->arb.length == 0) /* need explicit end */
+ break;
+ if (parent->pos + parent->arb.length > h->pos)
+ break;
+ if (parent->pos + parent->arb.length < h->pos) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return PR_TRUE;
+ }
+ h->stackPtr = parent;
+ }
+ }
+ }
+ }
+ return PR_FALSE;
+}
+BERParse *
+BER_ParseInit(PLArenaPool *arena, PRBool derOnly)
+{
+ BERParse *h;
+ PLArenaPool *temp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (temp == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+ h = PORT_ArenaAlloc(temp, sizeof(BERParse));
+ if (h == NULL) {
+ PORT_FreeArena(temp, PR_FALSE);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+ h->his = arena;
+ h->mine = temp;
+ h->proc = ParseTag;
+ h->stackDepth = 20;
+ h->stack = PORT_ArenaZAlloc(h->mine,
+ sizeof(ParseStackElem) * h->stackDepth);
+ h->stackPtr = h->stack;
+ h->state = notDone;
+ h->pos = 0;
+ h->keepLeaves = PR_TRUE;
+ h->before = NULL;
+ h->after = NULL;
+ h->filter = NULL;
+ h->derOnly = derOnly;
+ return h;
+}
+
+SECArb *
+BER_ParseFini(BERParse *h)
+{
+ PLArenaPool *myArena = h->mine;
+ SECArb *arb;
+
+ if (h->state != parseComplete) {
+ arb = NULL;
+ } else {
+ arb = PORT_ArenaAlloc(h->his, sizeof(SECArb));
+ *arb = h->stackPtr->arb;
+ }
+
+ PORT_FreeArena(myArena, PR_FALSE);
+
+ return arb;
+}
+
+void
+BER_SetFilter(BERParse *h, BERFilterProc proc, void *instance)
+{
+ h->filter = proc;
+ h->filterArg = instance;
+}
+
+void
+BER_SetLeafStorage(BERParse *h, PRBool keep)
+{
+ h->keepLeaves = keep;
+}
+
+void
+BER_SetNotifyProc(BERParse *h, BERNotifyProc proc, void *instance,
+ PRBool beforeData)
+{
+ if (beforeData) {
+ h->before = proc;
+ h->beforeArg = instance;
+ } else {
+ h->after = proc;
+ h->afterArg = instance;
+ }
+}
diff --git a/security/nss/cmd/lib/config.mk b/security/nss/cmd/lib/config.mk
new file mode 100644
index 000000000..b8c03de79
--- /dev/null
+++ b/security/nss/cmd/lib/config.mk
@@ -0,0 +1,15 @@
+#
+# 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/.
+
+#
+# Override TARGETS variable so that only static libraries
+# are specifed as dependencies within rules.mk.
+#
+
+TARGETS = $(LIBRARY)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+PROGRAM =
+
diff --git a/security/nss/cmd/lib/derprint.c b/security/nss/cmd/lib/derprint.c
new file mode 100644
index 000000000..08ef66d08
--- /dev/null
+++ b/security/nss/cmd/lib/derprint.c
@@ -0,0 +1,594 @@
+/* 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/. */
+#include "secutil.h"
+#include "secoid.h"
+
+#ifdef __sun
+extern int fprintf(FILE *strm, const char *format, ... /* args */);
+extern int fflush(FILE *stream);
+#endif
+
+#define RIGHT_MARGIN 24
+/*#define RAW_BYTES 1 */
+
+static int prettyColumn = 0;
+
+static int
+getInteger256(const unsigned char *data, unsigned int nb)
+{
+ int val;
+
+ switch (nb) {
+ case 1:
+ val = data[0];
+ break;
+ case 2:
+ val = (data[0] << 8) | data[1];
+ break;
+ case 3:
+ val = (data[0] << 16) | (data[1] << 8) | data[2];
+ break;
+ case 4:
+ /* If the most significant bit of data[0] is 1, val would be negative.
+ * Treat it as an error.
+ */
+ if (data[0] & 0x80) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+ val = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ return val;
+}
+
+static int
+prettyNewline(FILE *out)
+{
+ int rv;
+
+ if (prettyColumn != -1) {
+ rv = fprintf(out, "\n");
+ prettyColumn = -1;
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ }
+ return 0;
+}
+
+static int
+prettyIndent(FILE *out, unsigned level)
+{
+ unsigned int i;
+ int rv;
+
+ if (prettyColumn == -1) {
+ prettyColumn = level;
+ for (i = 0; i < level; i++) {
+ rv = fprintf(out, " ");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
+prettyPrintByte(FILE *out, unsigned char item, unsigned int level)
+{
+ int rv;
+
+ rv = prettyIndent(out, level);
+ if (rv < 0)
+ return rv;
+
+ rv = fprintf(out, "%02x ", item);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ prettyColumn++;
+ if (prettyColumn >= RIGHT_MARGIN) {
+ return prettyNewline(out);
+ }
+
+ return 0;
+}
+
+static int
+prettyPrintLeaf(FILE *out, const unsigned char *data,
+ unsigned int len, unsigned int lv)
+{
+ unsigned int i;
+ int rv;
+
+ for (i = 0; i < len; i++) {
+ rv = prettyPrintByte(out, *data++, lv);
+ if (rv < 0)
+ return rv;
+ }
+ return prettyNewline(out);
+}
+
+static int
+prettyPrintStringStart(FILE *out, const unsigned char *str,
+ unsigned int len, unsigned int level)
+{
+#define BUF_SIZE 100
+ unsigned char buf[BUF_SIZE];
+ int rv;
+
+ if (len >= BUF_SIZE)
+ len = BUF_SIZE - 1;
+
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+
+ rv = prettyIndent(out, level);
+ if (rv < 0)
+ return rv;
+
+ memcpy(buf, str, len);
+ buf[len] = '\000';
+
+ rv = fprintf(out, "\"%s\"", buf);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ return 0;
+#undef BUF_SIZE
+}
+
+static int
+prettyPrintString(FILE *out, const unsigned char *str,
+ unsigned int len, unsigned int level, PRBool raw)
+{
+ int rv;
+
+ rv = prettyPrintStringStart(out, str, len, level);
+ if (rv < 0)
+ return rv;
+
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+
+ if (raw) {
+ rv = prettyPrintLeaf(out, str, len, level);
+ if (rv < 0)
+ return rv;
+ }
+
+ return 0;
+}
+
+static int
+prettyPrintTime(FILE *out, const unsigned char *str,
+ unsigned int len, unsigned int level, PRBool raw, PRBool utc)
+{
+ SECItem time_item;
+ int rv;
+
+ rv = prettyPrintStringStart(out, str, len, level);
+ if (rv < 0)
+ return rv;
+
+ time_item.data = (unsigned char *)str;
+ time_item.len = len;
+
+ rv = fprintf(out, " (");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ if (utc)
+ SECU_PrintUTCTime(out, &time_item, NULL, 0);
+ else
+ SECU_PrintGeneralizedTime(out, &time_item, NULL, 0);
+
+ rv = fprintf(out, ")");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+
+ if (raw) {
+ rv = prettyPrintLeaf(out, str, len, level);
+ if (rv < 0)
+ return rv;
+ }
+
+ return 0;
+}
+
+static int
+prettyPrintObjectID(FILE *out, const unsigned char *data,
+ unsigned int len, unsigned int level, PRBool raw)
+{
+ SECOidData *oiddata;
+ SECItem oiditem;
+ unsigned int i;
+ unsigned long val;
+ int rv;
+
+ /*
+ * First print the Object Id in numeric format
+ */
+
+ rv = prettyIndent(out, level);
+ if (rv < 0)
+ return rv;
+
+ if (len == 0) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+ val = data[0];
+ i = val % 40;
+ val = val / 40;
+ rv = fprintf(out, "%lu %u ", val, i);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ val = 0;
+ for (i = 1; i < len; ++i) {
+ unsigned long j;
+
+ j = data[i];
+ val = (val << 7) | (j & 0x7f);
+ if (j & 0x80)
+ continue;
+ rv = fprintf(out, "%lu ", val);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ val = 0;
+ }
+
+ /*
+ * Now try to look it up and print a symbolic version.
+ */
+ oiditem.data = (unsigned char *)data;
+ oiditem.len = len;
+ oiddata = SECOID_FindOID(&oiditem);
+ if (oiddata != NULL) {
+ i = PORT_Strlen(oiddata->desc);
+ if ((prettyColumn + 1 + (i / 3)) > RIGHT_MARGIN) {
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+ }
+
+ rv = prettyIndent(out, level);
+ if (rv < 0)
+ return rv;
+
+ rv = fprintf(out, "(%s)", oiddata->desc);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ }
+
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+
+ if (raw) {
+ rv = prettyPrintLeaf(out, data, len, level);
+ if (rv < 0)
+ return rv;
+ }
+
+ return 0;
+}
+
+static char *prettyTagType[32] = {
+ "End of Contents",
+ "Boolean",
+ "Integer",
+ "Bit String",
+ "Octet String",
+ "NULL",
+ "Object Identifier",
+ "0x07",
+ "0x08",
+ "0x09",
+ "Enumerated",
+ "0x0B",
+ "UTF8 String",
+ "0x0D",
+ "0x0E",
+ "0x0F",
+ "Sequence",
+ "Set",
+ "0x12",
+ "Printable String",
+ "T61 String",
+ "0x15",
+ "IA5 String",
+ "UTC Time",
+ "Generalized Time",
+ "0x19",
+ "Visible String",
+ "0x1B",
+ "Universal String",
+ "0x1D",
+ "BMP String",
+ "High-Tag-Number"
+};
+
+static int
+prettyPrintTag(FILE *out, const unsigned char *src, const unsigned char *end,
+ unsigned char *codep, unsigned int level, PRBool raw)
+{
+ int rv;
+ unsigned char code, tagnum;
+
+ if (src >= end) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ code = *src;
+ tagnum = code & SEC_ASN1_TAGNUM_MASK;
+
+ /*
+ * NOTE: This code does not (yet) handle the high-tag-number form!
+ */
+ if (tagnum == SEC_ASN1_HIGH_TAG_NUMBER) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ if (raw)
+ rv = prettyPrintByte(out, code, level);
+ else
+ rv = prettyIndent(out, level);
+
+ if (rv < 0)
+ return rv;
+
+ if (code & SEC_ASN1_CONSTRUCTED) {
+ rv = fprintf(out, "C-");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ }
+
+ switch (code & SEC_ASN1_CLASS_MASK) {
+ case SEC_ASN1_UNIVERSAL:
+ rv = fprintf(out, "%s ", prettyTagType[tagnum]);
+ break;
+ case SEC_ASN1_APPLICATION:
+ rv = fprintf(out, "Application: %d ", tagnum);
+ break;
+ case SEC_ASN1_CONTEXT_SPECIFIC:
+ rv = fprintf(out, "[%d] ", tagnum);
+ break;
+ case SEC_ASN1_PRIVATE:
+ rv = fprintf(out, "Private: %d ", tagnum);
+ break;
+ }
+
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ *codep = code;
+
+ return 1;
+}
+
+static int
+prettyPrintLength(FILE *out, const unsigned char *data, const unsigned char *end,
+ int *lenp, PRBool *indefinitep, unsigned int lv, PRBool raw)
+{
+ unsigned char lbyte;
+ int lenLen;
+ int rv;
+
+ if (data >= end) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ rv = fprintf(out, " ");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ *indefinitep = PR_FALSE;
+
+ lbyte = *data++;
+ lenLen = 1;
+ if (lbyte >= 0x80) {
+ /* Multibyte length */
+ unsigned nb = (unsigned)(lbyte & 0x7f);
+ if (nb > 4) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+ if (nb > 0) {
+ int il;
+
+ if ((data + nb) > end) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+ il = getInteger256(data, nb);
+ if (il < 0)
+ return -1;
+ *lenp = (unsigned)il;
+ } else {
+ *lenp = 0;
+ *indefinitep = PR_TRUE;
+ }
+ lenLen += nb;
+ if (raw) {
+ unsigned int i;
+
+ rv = prettyPrintByte(out, lbyte, lv);
+ if (rv < 0)
+ return rv;
+ for (i = 0; i < nb; i++) {
+ rv = prettyPrintByte(out, data[i], lv);
+ if (rv < 0)
+ return rv;
+ }
+ }
+ } else {
+ *lenp = lbyte;
+ if (raw) {
+ rv = prettyPrintByte(out, lbyte, lv);
+ if (rv < 0)
+ return rv;
+ }
+ }
+ if (*indefinitep)
+ rv = fprintf(out, "(indefinite)\n");
+ else
+ rv = fprintf(out, "(%d)\n", *lenp);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ prettyColumn = -1;
+ return lenLen;
+}
+
+static int
+prettyPrintItem(FILE *out, const unsigned char *data, const unsigned char *end,
+ unsigned int lv, PRBool raw)
+{
+ int slen;
+ int lenLen;
+ const unsigned char *orig = data;
+ int rv;
+
+ while (data < end) {
+ unsigned char code;
+ PRBool indefinite;
+
+ slen = prettyPrintTag(out, data, end, &code, lv, raw);
+ if (slen < 0)
+ return slen;
+ data += slen;
+
+ lenLen = prettyPrintLength(out, data, end, &slen, &indefinite, lv, raw);
+ if (lenLen < 0)
+ return lenLen;
+ data += lenLen;
+
+ /*
+ * Just quit now if slen more bytes puts us off the end.
+ */
+ if ((data + slen) > end) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ if (code & SEC_ASN1_CONSTRUCTED) {
+ if (slen > 0 || indefinite) {
+ slen = prettyPrintItem(out, data,
+ slen == 0 ? end : data + slen,
+ lv + 1, raw);
+ if (slen < 0)
+ return slen;
+ data += slen;
+ }
+ } else if (code == 0) {
+ if (slen != 0 || lenLen != 1) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+ break;
+ } else {
+ switch (code) {
+ case SEC_ASN1_PRINTABLE_STRING:
+ case SEC_ASN1_IA5_STRING:
+ case SEC_ASN1_VISIBLE_STRING:
+ rv = prettyPrintString(out, data, slen, lv + 1, raw);
+ if (rv < 0)
+ return rv;
+ break;
+ case SEC_ASN1_UTC_TIME:
+ rv = prettyPrintTime(out, data, slen, lv + 1, raw, PR_TRUE);
+ if (rv < 0)
+ return rv;
+ break;
+ case SEC_ASN1_GENERALIZED_TIME:
+ rv = prettyPrintTime(out, data, slen, lv + 1, raw, PR_FALSE);
+ if (rv < 0)
+ return rv;
+ break;
+ case SEC_ASN1_OBJECT_ID:
+ rv = prettyPrintObjectID(out, data, slen, lv + 1, raw);
+ if (rv < 0)
+ return rv;
+ break;
+ case SEC_ASN1_BOOLEAN: /* could do nicer job */
+ case SEC_ASN1_INTEGER: /* could do nicer job */
+ case SEC_ASN1_BIT_STRING: /* could do nicer job */
+ case SEC_ASN1_OCTET_STRING:
+ case SEC_ASN1_NULL:
+ case SEC_ASN1_ENUMERATED: /* could do nicer job, as INTEGER */
+ case SEC_ASN1_UTF8_STRING:
+ case SEC_ASN1_T61_STRING: /* print as printable string? */
+ case SEC_ASN1_UNIVERSAL_STRING:
+ case SEC_ASN1_BMP_STRING:
+ default:
+ rv = prettyPrintLeaf(out, data, slen, lv + 1);
+ if (rv < 0)
+ return rv;
+ break;
+ }
+ data += slen;
+ }
+ }
+
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+
+ return data - orig;
+}
+
+SECStatus
+DER_PrettyPrint(FILE *out, const SECItem *it, PRBool raw)
+{
+ int rv;
+
+ prettyColumn = -1;
+
+ rv = prettyPrintItem(out, it->data, it->data + it->len, 0, raw);
+ if (rv < 0)
+ return SECFailure;
+ return SECSuccess;
+}
diff --git a/security/nss/cmd/lib/exports.gyp b/security/nss/cmd/lib/exports.gyp
new file mode 100644
index 000000000..f6b469397
--- /dev/null
+++ b/security/nss/cmd/lib/exports.gyp
@@ -0,0 +1,27 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'cmd_lib_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'basicutil.h',
+ 'pk11table.h',
+ 'secutil.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/cmd/lib/ffs.c b/security/nss/cmd/lib/ffs.c
new file mode 100644
index 000000000..d1cbf67e2
--- /dev/null
+++ b/security/nss/cmd/lib/ffs.c
@@ -0,0 +1,21 @@
+/* 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/. */
+#if !defined(XP_UNIX) && !defined(XP_OS2)
+
+int
+ffs(unsigned int i)
+{
+ int rv = 1;
+
+ if (!i)
+ return 0;
+
+ while (!(i & 1)) {
+ i >>= 1;
+ ++rv;
+ }
+
+ return rv;
+}
+#endif
diff --git a/security/nss/cmd/lib/lib.gyp b/security/nss/cmd/lib/lib.gyp
new file mode 100644
index 000000000..6b7da5810
--- /dev/null
+++ b/security/nss/cmd/lib/lib.gyp
@@ -0,0 +1,36 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'sectool',
+ 'type': 'static_library',
+ 'standalone_static_library': 1,
+ 'sources': [
+ 'basicutil.c',
+ 'derprint.c',
+ 'ffs.c',
+ 'moreoids.c',
+ 'pk11table.c',
+ 'pppolicy.c',
+ 'secpwd.c',
+ 'secutil.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/lib/manifest.mn b/security/nss/cmd/lib/manifest.mn
new file mode 100644
index 000000000..87440c052
--- /dev/null
+++ b/security/nss/cmd/lib/manifest.mn
@@ -0,0 +1,39 @@
+#
+# 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/.
+CORE_DEPTH = ../..
+
+LIBRARY_NAME = sectool
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+DEFINES = -DNSPR20
+
+ifdef NSS_BUILD_SOFTOKEN_ONLY
+PRIVATE_EXPORTS = basicutil.h \
+ pk11table.h \
+ $(NULL)
+
+CSRCS = basicutil.c \
+ pk11table.c \
+ $(NULL)
+else
+PRIVATE_EXPORTS = basicutil.h \
+ secutil.h \
+ pk11table.h \
+ $(NULL)
+
+CSRCS = basicutil.c \
+ secutil.c \
+ secpwd.c \
+ derprint.c \
+ moreoids.c \
+ pppolicy.c \
+ ffs.c \
+ pk11table.c \
+ $(NULL)
+endif
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/lib/moreoids.c b/security/nss/cmd/lib/moreoids.c
new file mode 100644
index 000000000..ed5022cef
--- /dev/null
+++ b/security/nss/cmd/lib/moreoids.c
@@ -0,0 +1,167 @@
+/* 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/. */
+
+#include "secoid.h"
+#include "secmodt.h" /* for CKM_INVALID_MECHANISM */
+
+#define OI(x) \
+ { \
+ siDEROID, (unsigned char *)x, sizeof x \
+ }
+#define OD(oid, tag, desc, mech, ext) \
+ { \
+ OI(oid) \
+ , tag, desc, mech, ext \
+ }
+#define ODN(oid, desc) \
+ { \
+ OI(oid) \
+ , 0, desc, CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION \
+ }
+
+#define OIDT static const unsigned char
+
+/* OIW Security Special Interest Group defined algorithms. */
+#define OIWSSIG 0x2B, 13, 3, 2
+
+OIDT oiwMD5RSA[] = { OIWSSIG, 3 };
+OIDT oiwDESCBC[] = { OIWSSIG, 7 };
+OIDT oiwRSAsig[] = { OIWSSIG, 11 };
+OIDT oiwDSA[] = { OIWSSIG, 12 };
+OIDT oiwMD5RSAsig[] = { OIWSSIG, 25 };
+OIDT oiwSHA1[] = { OIWSSIG, 26 };
+OIDT oiwDSASHA1[] = { OIWSSIG, 27 };
+OIDT oiwDSASHA1param[] = { OIWSSIG, 28 };
+OIDT oiwSHA1RSA[] = { OIWSSIG, 29 };
+
+/* Microsoft OIDs. (1 3 6 1 4 1 311 ... ) */
+#define MICROSOFT 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37
+
+OIDT mCTL[] = { MICROSOFT, 10, 3, 1 }; /* Cert Trust List signing */
+OIDT mTSS[] = { MICROSOFT, 10, 3, 2 }; /* Time Stamp Signing */
+OIDT mSGC[] = { MICROSOFT, 10, 3, 3 }; /* Server gated cryptography */
+OIDT mEFS[] = { MICROSOFT, 10, 3, 4 }; /* Encrypted File System */
+OIDT mSMIME[] = { MICROSOFT, 16, 4 }; /* SMIME encryption key prefs */
+
+OIDT mECRTT[] = { MICROSOFT, 20, 2 }; /* Enrollment cert type xtn */
+OIDT mEAGNT[] = { MICROSOFT, 20, 2, 1 }; /* Enrollment Agent */
+OIDT mKPSCL[] = { MICROSOFT, 20, 2, 2 }; /* KP SmartCard Logon */
+OIDT mNTPN[] = { MICROSOFT, 20, 2, 3 }; /* NT Principal Name */
+OIDT mCASRV[] = { MICROSOFT, 21, 1 }; /* CertServ CA version */
+
+/* AOL OIDs (1 3 6 1 4 1 1066 ... ) */
+#define AOL 0x2B, 0x06, 0x01, 0x04, 0x01, 0x88, 0x2A
+
+/* PKIX IDs (1 3 6 1 5 5 7 ...) */
+#define ID_PKIX 0x2B, 6, 1, 5, 5, 7
+/* PKIX Access Descriptors (methods for Authority Info Access Extns) */
+#define ID_AD ID_PKIX, 48
+
+OIDT padOCSP[] = { ID_AD, 1 }; /* OCSP method */
+OIDT padCAissuer[] = { ID_AD, 2 }; /* URI (for CRL ?) */
+OIDT padTimeStamp[] = { ID_AD, 3 }; /* time stamping */
+
+/* ISO Cert Extension type OIDs (id-ce) (2 5 29 ...) */
+#define X500 0x55
+#define X520_ATTRIBUTE_TYPE X500, 0x04
+#define X500_ALG X500, 0x08
+#define X500_ALG_ENCRYPTION X500_ALG, 0x01
+#define ID_CE X500, 29
+
+OIDT cePlcyObs[] = { ID_CE, 3 }; /* Cert policies, obsolete. */
+OIDT cePlcyCns[] = { ID_CE, 36 }; /* Cert policy constraints. */
+
+/* US Company arc (2 16 840 1 ...) */
+#define USCOM 0x60, 0x86, 0x48, 0x01
+#define USGOV USCOM, 0x65
+#define USDOD USGOV, 2
+#define ID_INFOSEC USDOD, 1
+
+/* Verisign PKI OIDs (2 16 840 1 113733 1 ...) */
+#define VERISIGN_PKI USCOM, 0x86, 0xf8, 0x45, 1
+#define VERISIGN_XTN VERISIGN_PKI, 6
+#define VERISIGN_POL VERISIGN_PKI, 7 /* Cert policies */
+#define VERISIGN_TNET VERISIGN_POL, 23 /* Verisign Trust Network */
+
+OIDT vcx7[] = { VERISIGN_XTN, 7 }; /* Cert Extension 7 (?) */
+OIDT vcp1[] = { VERISIGN_TNET, 1 }; /* class 1 cert policy */
+OIDT vcp2[] = { VERISIGN_TNET, 2 }; /* class 2 cert policy */
+OIDT vcp3[] = { VERISIGN_TNET, 3 }; /* class 3 cert policy */
+OIDT vcp4[] = { VERISIGN_TNET, 4 }; /* class 4 cert policy */
+
+/* ------------------------------------------------------------------- */
+static const SECOidData oids[] = {
+ /* OIW Security Special Interest Group OIDs */
+ ODN(oiwMD5RSA, "OIWSecSIG MD5 with RSA"),
+ ODN(oiwDESCBC, "OIWSecSIG DES CBC"),
+ ODN(oiwRSAsig, "OIWSecSIG RSA signature"),
+ ODN(oiwDSA, "OIWSecSIG DSA"),
+ ODN(oiwMD5RSAsig, "OIWSecSIG MD5 with RSA signature"),
+ ODN(oiwSHA1, "OIWSecSIG SHA1"),
+ ODN(oiwDSASHA1, "OIWSecSIG DSA with SHA1"),
+ ODN(oiwDSASHA1param, "OIWSecSIG DSA with SHA1 with params"),
+ ODN(oiwSHA1RSA, "OIWSecSIG MD5 with RSA"),
+
+ /* Microsoft OIDs */
+ ODN(mCTL, "Microsoft Cert Trust List signing"),
+ ODN(mTSS, "Microsoft Time Stamp signing"),
+ ODN(mSGC, "Microsoft SGC SSL server"),
+ ODN(mEFS, "Microsoft Encrypted File System"),
+ ODN(mSMIME, "Microsoft SMIME preferences"),
+ ODN(mECRTT, "Microsoft Enrollment Cert Type Extension"),
+ ODN(mEAGNT, "Microsoft Enrollment Agent"),
+ ODN(mKPSCL, "Microsoft KP SmartCard Logon"),
+ ODN(mNTPN, "Microsoft NT Principal Name"),
+ ODN(mCASRV, "Microsoft CertServ CA version"),
+
+ /* PKIX OIDs */
+ ODN(padOCSP, "PKIX OCSP method"),
+ ODN(padCAissuer, "PKIX CA Issuer method"),
+ ODN(padTimeStamp, "PKIX Time Stamping method"),
+
+ /* ID_CE OIDs. */
+ ODN(cePlcyObs, "Certificate Policies (Obsolete)"),
+ ODN(cePlcyCns, "Certificate Policy Constraints"),
+
+ /* Verisign OIDs. */
+ ODN(vcx7, "Verisign Cert Extension 7 (?)"),
+ ODN(vcp1, "Verisign Class 1 Certificate Policy"),
+ ODN(vcp2, "Verisign Class 2 Certificate Policy"),
+ ODN(vcp3, "Verisign Class 3 Certificate Policy"),
+ ODN(vcp4, "Verisign Class 4 Certificate Policy"),
+
+};
+
+static const unsigned int numOids = (sizeof oids) / (sizeof oids[0]);
+
+/* Fetch and register an oid if it hasn't been done already */
+void
+SECU_cert_fetchOID(SECOidTag *data, const SECOidData *src)
+{
+ if (*data == SEC_OID_UNKNOWN) {
+ /* AddEntry does the right thing if someone else has already
+ * added the oid. (that is return that oid tag) */
+ *data = SECOID_AddEntry(src);
+ }
+}
+
+SECStatus
+SECU_RegisterDynamicOids(void)
+{
+ unsigned int i;
+ SECStatus rv = SECSuccess;
+
+ for (i = 0; i < numOids; ++i) {
+ SECOidTag tag = SECOID_AddEntry(&oids[i]);
+ if (tag == SEC_OID_UNKNOWN) {
+ rv = SECFailure;
+#ifdef DEBUG_DYN_OIDS
+ fprintf(stderr, "Add OID[%d] failed\n", i);
+ } else {
+ fprintf(stderr, "Add OID[%d] returned tag %d\n", i, tag);
+#endif
+ }
+ }
+ return rv;
+}
diff --git a/security/nss/cmd/lib/pk11table.c b/security/nss/cmd/lib/pk11table.c
new file mode 100644
index 000000000..15c0a8d1e
--- /dev/null
+++ b/security/nss/cmd/lib/pk11table.c
@@ -0,0 +1,1517 @@
+/* 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/. */
+
+#include "pk11table.h"
+
+const char *_valueString[] = {
+ "None",
+ "Variable",
+ "CK_ULONG",
+ "Data",
+ "UTF8",
+ "CK_INFO",
+ "CK_SLOT_INFO",
+ "CK_TOKEN_INFO",
+ "CK_SESSION_INFO",
+ "CK_ATTRIBUTE",
+ "CK_MECHANISM",
+ "CK_MECHANISM_INFO",
+ "CK_C_INITIALIZE_ARGS",
+ "CK_FUNCTION_LIST"
+};
+
+const char **valueString = &_valueString[0];
+const int valueCount = sizeof(_valueString) / sizeof(_valueString[0]);
+
+const char *_constTypeString[] = {
+ "None",
+ "Bool",
+ "InfoFlags",
+ "SlotFlags",
+ "TokenFlags",
+ "SessionFlags",
+ "MechanismFlags",
+ "InitializeFlags",
+ "Users",
+ "SessionState",
+ "Object",
+ "Hardware",
+ "KeyType",
+ "CertificateType",
+ "Attribute",
+ "Mechanism",
+ "Result",
+ "Trust",
+ "AvailableSizes",
+ "CurrentSize"
+};
+
+const char **constTypeString = &_constTypeString[0];
+const int constTypeCount = sizeof(_constTypeString) / sizeof(_constTypeString[0]);
+
+#define mkEntry(x, t) \
+ { \
+ #x, x, Const##t, ConstNone \
+ }
+#define mkEntry2(x, t, t2) \
+ { \
+ #x, x, Const##t, Const##t2 \
+ }
+
+const Constant _consts[] = {
+ mkEntry(CK_FALSE, Bool),
+ mkEntry(CK_TRUE, Bool),
+
+ mkEntry(CKF_TOKEN_PRESENT, SlotFlags),
+ mkEntry(CKF_REMOVABLE_DEVICE, SlotFlags),
+ mkEntry(CKF_HW_SLOT, SlotFlags),
+
+ mkEntry(CKF_RNG, TokenFlags),
+ mkEntry(CKF_WRITE_PROTECTED, TokenFlags),
+ mkEntry(CKF_LOGIN_REQUIRED, TokenFlags),
+ mkEntry(CKF_USER_PIN_INITIALIZED, TokenFlags),
+ mkEntry(CKF_RESTORE_KEY_NOT_NEEDED, TokenFlags),
+ mkEntry(CKF_CLOCK_ON_TOKEN, TokenFlags),
+ mkEntry(CKF_PROTECTED_AUTHENTICATION_PATH, TokenFlags),
+ mkEntry(CKF_DUAL_CRYPTO_OPERATIONS, TokenFlags),
+ mkEntry(CKF_TOKEN_INITIALIZED, TokenFlags),
+ mkEntry(CKF_SECONDARY_AUTHENTICATION, TokenFlags),
+ mkEntry(CKF_USER_PIN_COUNT_LOW, TokenFlags),
+ mkEntry(CKF_USER_PIN_FINAL_TRY, TokenFlags),
+ mkEntry(CKF_USER_PIN_LOCKED, TokenFlags),
+ mkEntry(CKF_USER_PIN_TO_BE_CHANGED, TokenFlags),
+ mkEntry(CKF_SO_PIN_COUNT_LOW, TokenFlags),
+ mkEntry(CKF_SO_PIN_FINAL_TRY, TokenFlags),
+ mkEntry(CKF_SO_PIN_LOCKED, TokenFlags),
+ mkEntry(CKF_SO_PIN_TO_BE_CHANGED, TokenFlags),
+
+ mkEntry(CKF_RW_SESSION, SessionFlags),
+ mkEntry(CKF_SERIAL_SESSION, SessionFlags),
+
+ mkEntry(CKF_HW, MechanismFlags),
+ mkEntry(CKF_ENCRYPT, MechanismFlags),
+ mkEntry(CKF_DECRYPT, MechanismFlags),
+ mkEntry(CKF_DIGEST, MechanismFlags),
+ mkEntry(CKF_SIGN, MechanismFlags),
+ mkEntry(CKF_SIGN_RECOVER, MechanismFlags),
+ mkEntry(CKF_VERIFY, MechanismFlags),
+ mkEntry(CKF_VERIFY_RECOVER, MechanismFlags),
+ mkEntry(CKF_GENERATE, MechanismFlags),
+ mkEntry(CKF_GENERATE_KEY_PAIR, MechanismFlags),
+ mkEntry(CKF_WRAP, MechanismFlags),
+ mkEntry(CKF_UNWRAP, MechanismFlags),
+ mkEntry(CKF_DERIVE, MechanismFlags),
+ mkEntry(CKF_EC_FP, MechanismFlags),
+ mkEntry(CKF_EC_F_2M, MechanismFlags),
+ mkEntry(CKF_EC_ECPARAMETERS, MechanismFlags),
+ mkEntry(CKF_EC_NAMEDCURVE, MechanismFlags),
+ mkEntry(CKF_EC_UNCOMPRESS, MechanismFlags),
+ mkEntry(CKF_EC_COMPRESS, MechanismFlags),
+
+ mkEntry(CKF_LIBRARY_CANT_CREATE_OS_THREADS, InitializeFlags),
+ mkEntry(CKF_OS_LOCKING_OK, InitializeFlags),
+
+ mkEntry(CKU_SO, Users),
+ mkEntry(CKU_USER, Users),
+
+ mkEntry(CKS_RO_PUBLIC_SESSION, SessionState),
+ mkEntry(CKS_RO_USER_FUNCTIONS, SessionState),
+ mkEntry(CKS_RW_PUBLIC_SESSION, SessionState),
+ mkEntry(CKS_RW_USER_FUNCTIONS, SessionState),
+ mkEntry(CKS_RW_SO_FUNCTIONS, SessionState),
+
+ mkEntry(CKO_DATA, Object),
+ mkEntry(CKO_CERTIFICATE, Object),
+ mkEntry(CKO_PUBLIC_KEY, Object),
+ mkEntry(CKO_PRIVATE_KEY, Object),
+ mkEntry(CKO_SECRET_KEY, Object),
+ mkEntry(CKO_HW_FEATURE, Object),
+ mkEntry(CKO_DOMAIN_PARAMETERS, Object),
+ mkEntry(CKO_KG_PARAMETERS, Object),
+ mkEntry(CKO_NSS_CRL, Object),
+ mkEntry(CKO_NSS_SMIME, Object),
+ mkEntry(CKO_NSS_TRUST, Object),
+ mkEntry(CKO_NSS_BUILTIN_ROOT_LIST, Object),
+
+ mkEntry(CKH_MONOTONIC_COUNTER, Hardware),
+ mkEntry(CKH_CLOCK, Hardware),
+
+ mkEntry(CKK_RSA, KeyType),
+ mkEntry(CKK_DSA, KeyType),
+ mkEntry(CKK_DH, KeyType),
+ mkEntry(CKK_ECDSA, KeyType),
+ mkEntry(CKK_EC, KeyType),
+ mkEntry(CKK_X9_42_DH, KeyType),
+ mkEntry(CKK_KEA, KeyType),
+ mkEntry(CKK_GENERIC_SECRET, KeyType),
+ mkEntry(CKK_RC2, KeyType),
+ mkEntry(CKK_RC4, KeyType),
+ mkEntry(CKK_DES, KeyType),
+ mkEntry(CKK_DES2, KeyType),
+ mkEntry(CKK_DES3, KeyType),
+ mkEntry(CKK_CAST, KeyType),
+ mkEntry(CKK_CAST3, KeyType),
+ mkEntry(CKK_CAST5, KeyType),
+ mkEntry(CKK_CAST128, KeyType),
+ mkEntry(CKK_RC5, KeyType),
+ mkEntry(CKK_IDEA, KeyType),
+ mkEntry(CKK_SKIPJACK, KeyType),
+ mkEntry(CKK_BATON, KeyType),
+ mkEntry(CKK_JUNIPER, KeyType),
+ mkEntry(CKK_CDMF, KeyType),
+ mkEntry(CKK_AES, KeyType),
+ mkEntry(CKK_CAMELLIA, KeyType),
+ mkEntry(CKK_NSS_PKCS8, KeyType),
+
+ mkEntry(CKC_X_509, CertType),
+ mkEntry(CKC_X_509_ATTR_CERT, CertType),
+
+ mkEntry2(CKA_CLASS, Attribute, Object),
+ mkEntry2(CKA_TOKEN, Attribute, Bool),
+ mkEntry2(CKA_PRIVATE, Attribute, Bool),
+ mkEntry2(CKA_LABEL, Attribute, None),
+ mkEntry2(CKA_APPLICATION, Attribute, None),
+ mkEntry2(CKA_VALUE, Attribute, None),
+ mkEntry2(CKA_OBJECT_ID, Attribute, None),
+ mkEntry2(CKA_CERTIFICATE_TYPE, Attribute, CertType),
+ mkEntry2(CKA_ISSUER, Attribute, None),
+ mkEntry2(CKA_SERIAL_NUMBER, Attribute, None),
+ mkEntry2(CKA_AC_ISSUER, Attribute, None),
+ mkEntry2(CKA_OWNER, Attribute, None),
+ mkEntry2(CKA_ATTR_TYPES, Attribute, None),
+ mkEntry2(CKA_TRUSTED, Attribute, Bool),
+ mkEntry2(CKA_KEY_TYPE, Attribute, KeyType),
+ mkEntry2(CKA_SUBJECT, Attribute, None),
+ mkEntry2(CKA_ID, Attribute, None),
+ mkEntry2(CKA_SENSITIVE, Attribute, Bool),
+ mkEntry2(CKA_ENCRYPT, Attribute, Bool),
+ mkEntry2(CKA_DECRYPT, Attribute, Bool),
+ mkEntry2(CKA_WRAP, Attribute, Bool),
+ mkEntry2(CKA_UNWRAP, Attribute, Bool),
+ mkEntry2(CKA_SIGN, Attribute, Bool),
+ mkEntry2(CKA_SIGN_RECOVER, Attribute, Bool),
+ mkEntry2(CKA_VERIFY, Attribute, Bool),
+ mkEntry2(CKA_VERIFY_RECOVER, Attribute, Bool),
+ mkEntry2(CKA_DERIVE, Attribute, Bool),
+ mkEntry2(CKA_START_DATE, Attribute, None),
+ mkEntry2(CKA_END_DATE, Attribute, None),
+ mkEntry2(CKA_MODULUS, Attribute, None),
+ mkEntry2(CKA_MODULUS_BITS, Attribute, None),
+ mkEntry2(CKA_PUBLIC_EXPONENT, Attribute, None),
+ mkEntry2(CKA_PRIVATE_EXPONENT, Attribute, None),
+ mkEntry2(CKA_PRIME_1, Attribute, None),
+ mkEntry2(CKA_PRIME_2, Attribute, None),
+ mkEntry2(CKA_EXPONENT_1, Attribute, None),
+ mkEntry2(CKA_EXPONENT_2, Attribute, None),
+ mkEntry2(CKA_COEFFICIENT, Attribute, None),
+ mkEntry2(CKA_PRIME, Attribute, None),
+ mkEntry2(CKA_SUBPRIME, Attribute, None),
+ mkEntry2(CKA_BASE, Attribute, None),
+ mkEntry2(CKA_PRIME_BITS, Attribute, None),
+ mkEntry2(CKA_SUB_PRIME_BITS, Attribute, None),
+ mkEntry2(CKA_VALUE_BITS, Attribute, None),
+ mkEntry2(CKA_VALUE_LEN, Attribute, None),
+ mkEntry2(CKA_EXTRACTABLE, Attribute, Bool),
+ mkEntry2(CKA_LOCAL, Attribute, Bool),
+ mkEntry2(CKA_NEVER_EXTRACTABLE, Attribute, Bool),
+ mkEntry2(CKA_ALWAYS_SENSITIVE, Attribute, Bool),
+ mkEntry2(CKA_KEY_GEN_MECHANISM, Attribute, Mechanism),
+ mkEntry2(CKA_MODIFIABLE, Attribute, Bool),
+ mkEntry2(CKA_ECDSA_PARAMS, Attribute, None),
+ mkEntry2(CKA_EC_PARAMS, Attribute, None),
+ mkEntry2(CKA_EC_POINT, Attribute, None),
+ mkEntry2(CKA_SECONDARY_AUTH, Attribute, None),
+ mkEntry2(CKA_AUTH_PIN_FLAGS, Attribute, None),
+ mkEntry2(CKA_HW_FEATURE_TYPE, Attribute, Hardware),
+ mkEntry2(CKA_RESET_ON_INIT, Attribute, Bool),
+ mkEntry2(CKA_HAS_RESET, Attribute, Bool),
+ mkEntry2(CKA_NSS_URL, Attribute, None),
+ mkEntry2(CKA_NSS_EMAIL, Attribute, None),
+ mkEntry2(CKA_NSS_SMIME_INFO, Attribute, None),
+ mkEntry2(CKA_NSS_SMIME_TIMESTAMP, Attribute, None),
+ mkEntry2(CKA_NSS_PKCS8_SALT, Attribute, None),
+ mkEntry2(CKA_NSS_PASSWORD_CHECK, Attribute, None),
+ mkEntry2(CKA_NSS_EXPIRES, Attribute, None),
+ mkEntry2(CKA_NSS_KRL, Attribute, None),
+ mkEntry2(CKA_NSS_PQG_COUNTER, Attribute, None),
+ mkEntry2(CKA_NSS_PQG_SEED, Attribute, None),
+ mkEntry2(CKA_NSS_PQG_H, Attribute, None),
+ mkEntry2(CKA_NSS_PQG_SEED_BITS, Attribute, None),
+ mkEntry2(CKA_TRUST_DIGITAL_SIGNATURE, Attribute, Trust),
+ mkEntry2(CKA_TRUST_NON_REPUDIATION, Attribute, Trust),
+ mkEntry2(CKA_TRUST_KEY_ENCIPHERMENT, Attribute, Trust),
+ mkEntry2(CKA_TRUST_DATA_ENCIPHERMENT, Attribute, Trust),
+ mkEntry2(CKA_TRUST_KEY_AGREEMENT, Attribute, Trust),
+ mkEntry2(CKA_TRUST_KEY_CERT_SIGN, Attribute, Trust),
+ mkEntry2(CKA_TRUST_CRL_SIGN, Attribute, Trust),
+ mkEntry2(CKA_TRUST_SERVER_AUTH, Attribute, Trust),
+ mkEntry2(CKA_TRUST_CLIENT_AUTH, Attribute, Trust),
+ mkEntry2(CKA_TRUST_CODE_SIGNING, Attribute, Trust),
+ mkEntry2(CKA_TRUST_EMAIL_PROTECTION, Attribute, Trust),
+ mkEntry2(CKA_TRUST_IPSEC_END_SYSTEM, Attribute, Trust),
+ mkEntry2(CKA_TRUST_IPSEC_TUNNEL, Attribute, Trust),
+ mkEntry2(CKA_TRUST_IPSEC_USER, Attribute, Trust),
+ mkEntry2(CKA_TRUST_TIME_STAMPING, Attribute, Trust),
+ mkEntry2(CKA_CERT_SHA1_HASH, Attribute, None),
+ mkEntry2(CKA_CERT_MD5_HASH, Attribute, None),
+ mkEntry2(CKA_NETSCAPE_DB, Attribute, None),
+ mkEntry2(CKA_NETSCAPE_TRUST, Attribute, Trust),
+
+ mkEntry(CKM_RSA_PKCS, Mechanism),
+ mkEntry(CKM_RSA_9796, Mechanism),
+ mkEntry(CKM_RSA_X_509, Mechanism),
+ mkEntry(CKM_RSA_PKCS_KEY_PAIR_GEN, Mechanism),
+ mkEntry(CKM_MD2_RSA_PKCS, Mechanism),
+ mkEntry(CKM_MD5_RSA_PKCS, Mechanism),
+ mkEntry(CKM_SHA1_RSA_PKCS, Mechanism),
+ mkEntry(CKM_RIPEMD128_RSA_PKCS, Mechanism),
+ mkEntry(CKM_RIPEMD160_RSA_PKCS, Mechanism),
+ mkEntry(CKM_RSA_PKCS_OAEP, Mechanism),
+ mkEntry(CKM_RSA_X9_31_KEY_PAIR_GEN, Mechanism),
+ mkEntry(CKM_RSA_X9_31, Mechanism),
+ mkEntry(CKM_SHA1_RSA_X9_31, Mechanism),
+ mkEntry(CKM_DSA_KEY_PAIR_GEN, Mechanism),
+ mkEntry(CKM_DSA, Mechanism),
+ mkEntry(CKM_DSA_SHA1, Mechanism),
+ mkEntry(CKM_DH_PKCS_KEY_PAIR_GEN, Mechanism),
+ mkEntry(CKM_DH_PKCS_DERIVE, Mechanism),
+ mkEntry(CKM_X9_42_DH_DERIVE, Mechanism),
+ mkEntry(CKM_X9_42_DH_HYBRID_DERIVE, Mechanism),
+ mkEntry(CKM_X9_42_MQV_DERIVE, Mechanism),
+ mkEntry(CKM_SHA256_RSA_PKCS, Mechanism),
+ mkEntry(CKM_SHA384_RSA_PKCS, Mechanism),
+ mkEntry(CKM_SHA512_RSA_PKCS, Mechanism),
+ mkEntry(CKM_RC2_KEY_GEN, Mechanism),
+ mkEntry(CKM_RC2_ECB, Mechanism),
+ mkEntry(CKM_RC2_CBC, Mechanism),
+ mkEntry(CKM_RC2_MAC, Mechanism),
+ mkEntry(CKM_RC2_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_RC2_CBC_PAD, Mechanism),
+ mkEntry(CKM_RC4_KEY_GEN, Mechanism),
+ mkEntry(CKM_RC4, Mechanism),
+ mkEntry(CKM_DES_KEY_GEN, Mechanism),
+ mkEntry(CKM_DES_ECB, Mechanism),
+ mkEntry(CKM_DES_CBC, Mechanism),
+ mkEntry(CKM_DES_MAC, Mechanism),
+ mkEntry(CKM_DES_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_DES_CBC_PAD, Mechanism),
+ mkEntry(CKM_DES2_KEY_GEN, Mechanism),
+ mkEntry(CKM_DES3_KEY_GEN, Mechanism),
+ mkEntry(CKM_DES3_ECB, Mechanism),
+ mkEntry(CKM_DES3_CBC, Mechanism),
+ mkEntry(CKM_DES3_MAC, Mechanism),
+ mkEntry(CKM_DES3_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_DES3_CBC_PAD, Mechanism),
+ mkEntry(CKM_CDMF_KEY_GEN, Mechanism),
+ mkEntry(CKM_CDMF_ECB, Mechanism),
+ mkEntry(CKM_CDMF_CBC, Mechanism),
+ mkEntry(CKM_CDMF_MAC, Mechanism),
+ mkEntry(CKM_CDMF_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_CDMF_CBC_PAD, Mechanism),
+ mkEntry(CKM_MD2, Mechanism),
+ mkEntry(CKM_MD2_HMAC, Mechanism),
+ mkEntry(CKM_MD2_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_MD5, Mechanism),
+ mkEntry(CKM_MD5_HMAC, Mechanism),
+ mkEntry(CKM_MD5_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_SHA_1, Mechanism),
+ mkEntry(CKM_SHA_1_HMAC, Mechanism),
+ mkEntry(CKM_SHA_1_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_RIPEMD128, Mechanism),
+ mkEntry(CKM_RIPEMD128_HMAC, Mechanism),
+ mkEntry(CKM_RIPEMD128_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_RIPEMD160, Mechanism),
+ mkEntry(CKM_RIPEMD160_HMAC, Mechanism),
+ mkEntry(CKM_RIPEMD160_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_SHA256, Mechanism),
+ mkEntry(CKM_SHA256_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_SHA256_HMAC, Mechanism),
+ mkEntry(CKM_SHA384, Mechanism),
+ mkEntry(CKM_SHA384_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_SHA384_HMAC, Mechanism),
+ mkEntry(CKM_SHA512, Mechanism),
+ mkEntry(CKM_SHA512_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_SHA512_HMAC, Mechanism),
+ mkEntry(CKM_CAST_KEY_GEN, Mechanism),
+ mkEntry(CKM_CAST_ECB, Mechanism),
+ mkEntry(CKM_CAST_CBC, Mechanism),
+ mkEntry(CKM_CAST_MAC, Mechanism),
+ mkEntry(CKM_CAST_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_CAST_CBC_PAD, Mechanism),
+ mkEntry(CKM_CAST3_KEY_GEN, Mechanism),
+ mkEntry(CKM_CAST3_ECB, Mechanism),
+ mkEntry(CKM_CAST3_CBC, Mechanism),
+ mkEntry(CKM_CAST3_MAC, Mechanism),
+ mkEntry(CKM_CAST3_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_CAST3_CBC_PAD, Mechanism),
+ mkEntry(CKM_CAST5_KEY_GEN, Mechanism),
+ mkEntry(CKM_CAST128_KEY_GEN, Mechanism),
+ mkEntry(CKM_CAST5_ECB, Mechanism),
+ mkEntry(CKM_CAST128_ECB, Mechanism),
+ mkEntry(CKM_CAST5_CBC, Mechanism),
+ mkEntry(CKM_CAST128_CBC, Mechanism),
+ mkEntry(CKM_CAST5_MAC, Mechanism),
+ mkEntry(CKM_CAST128_MAC, Mechanism),
+ mkEntry(CKM_CAST5_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_CAST128_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_CAST5_CBC_PAD, Mechanism),
+ mkEntry(CKM_CAST128_CBC_PAD, Mechanism),
+ mkEntry(CKM_RC5_KEY_GEN, Mechanism),
+ mkEntry(CKM_RC5_ECB, Mechanism),
+ mkEntry(CKM_RC5_CBC, Mechanism),
+ mkEntry(CKM_RC5_MAC, Mechanism),
+ mkEntry(CKM_RC5_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_RC5_CBC_PAD, Mechanism),
+ mkEntry(CKM_IDEA_KEY_GEN, Mechanism),
+ mkEntry(CKM_IDEA_ECB, Mechanism),
+ mkEntry(CKM_IDEA_CBC, Mechanism),
+ mkEntry(CKM_IDEA_MAC, Mechanism),
+ mkEntry(CKM_IDEA_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_IDEA_CBC_PAD, Mechanism),
+ mkEntry(CKM_GENERIC_SECRET_KEY_GEN, Mechanism),
+ mkEntry(CKM_CONCATENATE_BASE_AND_KEY, Mechanism),
+ mkEntry(CKM_CONCATENATE_BASE_AND_DATA, Mechanism),
+ mkEntry(CKM_CONCATENATE_DATA_AND_BASE, Mechanism),
+ mkEntry(CKM_XOR_BASE_AND_DATA, Mechanism),
+ mkEntry(CKM_EXTRACT_KEY_FROM_KEY, Mechanism),
+ mkEntry(CKM_SSL3_PRE_MASTER_KEY_GEN, Mechanism),
+ mkEntry(CKM_SSL3_MASTER_KEY_DERIVE, Mechanism),
+ mkEntry(CKM_SSL3_KEY_AND_MAC_DERIVE, Mechanism),
+ mkEntry(CKM_SSL3_MASTER_KEY_DERIVE_DH, Mechanism),
+ mkEntry(CKM_TLS_PRE_MASTER_KEY_GEN, Mechanism),
+ mkEntry(CKM_TLS_MASTER_KEY_DERIVE, Mechanism),
+ mkEntry(CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256, Mechanism),
+ mkEntry(CKM_TLS_KEY_AND_MAC_DERIVE, Mechanism),
+ mkEntry(CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256, Mechanism),
+ mkEntry(CKM_TLS_MASTER_KEY_DERIVE_DH, Mechanism),
+ mkEntry(CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256, Mechanism),
+ mkEntry(CKM_SSL3_MD5_MAC, Mechanism),
+ mkEntry(CKM_SSL3_SHA1_MAC, Mechanism),
+ mkEntry(CKM_MD5_KEY_DERIVATION, Mechanism),
+ mkEntry(CKM_MD2_KEY_DERIVATION, Mechanism),
+ mkEntry(CKM_SHA1_KEY_DERIVATION, Mechanism),
+ mkEntry(CKM_SHA256_KEY_DERIVATION, Mechanism),
+ mkEntry(CKM_SHA384_KEY_DERIVATION, Mechanism),
+ mkEntry(CKM_SHA512_KEY_DERIVATION, Mechanism),
+ mkEntry(CKM_PBE_MD2_DES_CBC, Mechanism),
+ mkEntry(CKM_PBE_MD5_DES_CBC, Mechanism),
+ mkEntry(CKM_PBE_MD5_CAST_CBC, Mechanism),
+ mkEntry(CKM_PBE_MD5_CAST3_CBC, Mechanism),
+ mkEntry(CKM_PBE_MD5_CAST5_CBC, Mechanism),
+ mkEntry(CKM_PBE_MD5_CAST128_CBC, Mechanism),
+ mkEntry(CKM_PBE_SHA1_CAST5_CBC, Mechanism),
+ mkEntry(CKM_PBE_SHA1_CAST128_CBC, Mechanism),
+ mkEntry(CKM_PBE_SHA1_RC4_128, Mechanism),
+ mkEntry(CKM_PBE_SHA1_RC4_40, Mechanism),
+ mkEntry(CKM_PBE_SHA1_DES3_EDE_CBC, Mechanism),
+ mkEntry(CKM_PBE_SHA1_DES2_EDE_CBC, Mechanism),
+ mkEntry(CKM_PBE_SHA1_RC2_128_CBC, Mechanism),
+ mkEntry(CKM_PBE_SHA1_RC2_40_CBC, Mechanism),
+ mkEntry(CKM_PKCS5_PBKD2, Mechanism),
+ mkEntry(CKM_PBA_SHA1_WITH_SHA1_HMAC, Mechanism),
+ mkEntry(CKM_KEY_WRAP_LYNKS, Mechanism),
+ mkEntry(CKM_KEY_WRAP_SET_OAEP, Mechanism),
+ mkEntry(CKM_SKIPJACK_KEY_GEN, Mechanism),
+ mkEntry(CKM_SKIPJACK_ECB64, Mechanism),
+ mkEntry(CKM_SKIPJACK_CBC64, Mechanism),
+ mkEntry(CKM_SKIPJACK_OFB64, Mechanism),
+ mkEntry(CKM_SKIPJACK_CFB64, Mechanism),
+ mkEntry(CKM_SKIPJACK_CFB32, Mechanism),
+ mkEntry(CKM_SKIPJACK_CFB16, Mechanism),
+ mkEntry(CKM_SKIPJACK_CFB8, Mechanism),
+ mkEntry(CKM_SKIPJACK_WRAP, Mechanism),
+ mkEntry(CKM_SKIPJACK_PRIVATE_WRAP, Mechanism),
+ mkEntry(CKM_SKIPJACK_RELAYX, Mechanism),
+ mkEntry(CKM_KEA_KEY_PAIR_GEN, Mechanism),
+ mkEntry(CKM_KEA_KEY_DERIVE, Mechanism),
+ mkEntry(CKM_FORTEZZA_TIMESTAMP, Mechanism),
+ mkEntry(CKM_BATON_KEY_GEN, Mechanism),
+ mkEntry(CKM_BATON_ECB128, Mechanism),
+ mkEntry(CKM_BATON_ECB96, Mechanism),
+ mkEntry(CKM_BATON_CBC128, Mechanism),
+ mkEntry(CKM_BATON_COUNTER, Mechanism),
+ mkEntry(CKM_BATON_SHUFFLE, Mechanism),
+ mkEntry(CKM_BATON_WRAP, Mechanism),
+ mkEntry(CKM_ECDSA_KEY_PAIR_GEN, Mechanism),
+ mkEntry(CKM_EC_KEY_PAIR_GEN, Mechanism),
+ mkEntry(CKM_ECDSA, Mechanism),
+ mkEntry(CKM_ECDSA_SHA1, Mechanism),
+ mkEntry(CKM_ECDH1_DERIVE, Mechanism),
+ mkEntry(CKM_ECDH1_COFACTOR_DERIVE, Mechanism),
+ mkEntry(CKM_ECMQV_DERIVE, Mechanism),
+ mkEntry(CKM_JUNIPER_KEY_GEN, Mechanism),
+ mkEntry(CKM_JUNIPER_ECB128, Mechanism),
+ mkEntry(CKM_JUNIPER_CBC128, Mechanism),
+ mkEntry(CKM_JUNIPER_COUNTER, Mechanism),
+ mkEntry(CKM_JUNIPER_SHUFFLE, Mechanism),
+ mkEntry(CKM_JUNIPER_WRAP, Mechanism),
+ mkEntry(CKM_FASTHASH, Mechanism),
+ mkEntry(CKM_AES_KEY_GEN, Mechanism),
+ mkEntry(CKM_AES_ECB, Mechanism),
+ mkEntry(CKM_AES_CBC, Mechanism),
+ mkEntry(CKM_AES_MAC, Mechanism),
+ mkEntry(CKM_AES_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_AES_CBC_PAD, Mechanism),
+ mkEntry(CKM_CAMELLIA_KEY_GEN, Mechanism),
+ mkEntry(CKM_CAMELLIA_ECB, Mechanism),
+ mkEntry(CKM_CAMELLIA_CBC, Mechanism),
+ mkEntry(CKM_CAMELLIA_MAC, Mechanism),
+ mkEntry(CKM_CAMELLIA_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_CAMELLIA_CBC_PAD, Mechanism),
+ mkEntry(CKM_SEED_KEY_GEN, Mechanism),
+ mkEntry(CKM_SEED_ECB, Mechanism),
+ mkEntry(CKM_SEED_CBC, Mechanism),
+ mkEntry(CKM_SEED_MAC, Mechanism),
+ mkEntry(CKM_SEED_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_SEED_CBC_PAD, Mechanism),
+ mkEntry(CKM_SEED_ECB_ENCRYPT_DATA, Mechanism),
+ mkEntry(CKM_SEED_CBC_ENCRYPT_DATA, Mechanism),
+ mkEntry(CKM_DSA_PARAMETER_GEN, Mechanism),
+ mkEntry(CKM_DH_PKCS_PARAMETER_GEN, Mechanism),
+ mkEntry(CKM_NSS_AES_KEY_WRAP, Mechanism),
+ mkEntry(CKM_NSS_AES_KEY_WRAP_PAD, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_DES_CBC, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN, Mechanism),
+ mkEntry(CKM_TLS_PRF_GENERAL, Mechanism),
+ mkEntry(CKM_NSS_TLS_PRF_GENERAL_SHA256, Mechanism),
+
+ mkEntry(CKR_OK, Result),
+ mkEntry(CKR_CANCEL, Result),
+ mkEntry(CKR_HOST_MEMORY, Result),
+ mkEntry(CKR_SLOT_ID_INVALID, Result),
+ mkEntry(CKR_GENERAL_ERROR, Result),
+ mkEntry(CKR_FUNCTION_FAILED, Result),
+ mkEntry(CKR_ARGUMENTS_BAD, Result),
+ mkEntry(CKR_NO_EVENT, Result),
+ mkEntry(CKR_NEED_TO_CREATE_THREADS, Result),
+ mkEntry(CKR_CANT_LOCK, Result),
+ mkEntry(CKR_ATTRIBUTE_READ_ONLY, Result),
+ mkEntry(CKR_ATTRIBUTE_SENSITIVE, Result),
+ mkEntry(CKR_ATTRIBUTE_TYPE_INVALID, Result),
+ mkEntry(CKR_ATTRIBUTE_VALUE_INVALID, Result),
+ mkEntry(CKR_DATA_INVALID, Result),
+ mkEntry(CKR_DATA_LEN_RANGE, Result),
+ mkEntry(CKR_DEVICE_ERROR, Result),
+ mkEntry(CKR_DEVICE_MEMORY, Result),
+ mkEntry(CKR_DEVICE_REMOVED, Result),
+ mkEntry(CKR_ENCRYPTED_DATA_INVALID, Result),
+ mkEntry(CKR_ENCRYPTED_DATA_LEN_RANGE, Result),
+ mkEntry(CKR_FUNCTION_CANCELED, Result),
+ mkEntry(CKR_FUNCTION_NOT_PARALLEL, Result),
+ mkEntry(CKR_FUNCTION_NOT_SUPPORTED, Result),
+ mkEntry(CKR_KEY_HANDLE_INVALID, Result),
+ mkEntry(CKR_KEY_SIZE_RANGE, Result),
+ mkEntry(CKR_KEY_TYPE_INCONSISTENT, Result),
+ mkEntry(CKR_KEY_NOT_NEEDED, Result),
+ mkEntry(CKR_KEY_CHANGED, Result),
+ mkEntry(CKR_KEY_NEEDED, Result),
+ mkEntry(CKR_KEY_INDIGESTIBLE, Result),
+ mkEntry(CKR_KEY_FUNCTION_NOT_PERMITTED, Result),
+ mkEntry(CKR_KEY_NOT_WRAPPABLE, Result),
+ mkEntry(CKR_KEY_UNEXTRACTABLE, Result),
+ mkEntry(CKR_KEY_PARAMS_INVALID, Result),
+ mkEntry(CKR_MECHANISM_INVALID, Result),
+ mkEntry(CKR_MECHANISM_PARAM_INVALID, Result),
+ mkEntry(CKR_OBJECT_HANDLE_INVALID, Result),
+ mkEntry(CKR_OPERATION_ACTIVE, Result),
+ mkEntry(CKR_OPERATION_NOT_INITIALIZED, Result),
+ mkEntry(CKR_PIN_INCORRECT, Result),
+ mkEntry(CKR_PIN_INVALID, Result),
+ mkEntry(CKR_PIN_LEN_RANGE, Result),
+ mkEntry(CKR_PIN_EXPIRED, Result),
+ mkEntry(CKR_PIN_LOCKED, Result),
+ mkEntry(CKR_SESSION_CLOSED, Result),
+ mkEntry(CKR_SESSION_COUNT, Result),
+ mkEntry(CKR_SESSION_HANDLE_INVALID, Result),
+ mkEntry(CKR_SESSION_PARALLEL_NOT_SUPPORTED, Result),
+ mkEntry(CKR_SESSION_READ_ONLY, Result),
+ mkEntry(CKR_SESSION_EXISTS, Result),
+ mkEntry(CKR_SESSION_READ_ONLY_EXISTS, Result),
+ mkEntry(CKR_SESSION_READ_WRITE_SO_EXISTS, Result),
+ mkEntry(CKR_SIGNATURE_INVALID, Result),
+ mkEntry(CKR_SIGNATURE_LEN_RANGE, Result),
+ mkEntry(CKR_TEMPLATE_INCOMPLETE, Result),
+ mkEntry(CKR_TEMPLATE_INCONSISTENT, Result),
+ mkEntry(CKR_TOKEN_NOT_PRESENT, Result),
+ mkEntry(CKR_TOKEN_NOT_RECOGNIZED, Result),
+ mkEntry(CKR_TOKEN_WRITE_PROTECTED, Result),
+ mkEntry(CKR_UNWRAPPING_KEY_HANDLE_INVALID, Result),
+ mkEntry(CKR_UNWRAPPING_KEY_SIZE_RANGE, Result),
+ mkEntry(CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, Result),
+ mkEntry(CKR_USER_ALREADY_LOGGED_IN, Result),
+ mkEntry(CKR_USER_NOT_LOGGED_IN, Result),
+ mkEntry(CKR_USER_PIN_NOT_INITIALIZED, Result),
+ mkEntry(CKR_USER_TYPE_INVALID, Result),
+ mkEntry(CKR_USER_ANOTHER_ALREADY_LOGGED_IN, Result),
+ mkEntry(CKR_USER_TOO_MANY_TYPES, Result),
+ mkEntry(CKR_WRAPPED_KEY_INVALID, Result),
+ mkEntry(CKR_WRAPPED_KEY_LEN_RANGE, Result),
+ mkEntry(CKR_WRAPPING_KEY_HANDLE_INVALID, Result),
+ mkEntry(CKR_WRAPPING_KEY_SIZE_RANGE, Result),
+ mkEntry(CKR_WRAPPING_KEY_TYPE_INCONSISTENT, Result),
+ mkEntry(CKR_RANDOM_SEED_NOT_SUPPORTED, Result),
+ mkEntry(CKR_RANDOM_NO_RNG, Result),
+ mkEntry(CKR_DOMAIN_PARAMS_INVALID, Result),
+ mkEntry(CKR_BUFFER_TOO_SMALL, Result),
+ mkEntry(CKR_SAVED_STATE_INVALID, Result),
+ mkEntry(CKR_INFORMATION_SENSITIVE, Result),
+ mkEntry(CKR_STATE_UNSAVEABLE, Result),
+ mkEntry(CKR_CRYPTOKI_NOT_INITIALIZED, Result),
+ mkEntry(CKR_CRYPTOKI_ALREADY_INITIALIZED, Result),
+ mkEntry(CKR_MUTEX_BAD, Result),
+ mkEntry(CKR_MUTEX_NOT_LOCKED, Result),
+ mkEntry(CKR_VENDOR_DEFINED, Result),
+
+ mkEntry(CKT_NSS_TRUSTED, Trust),
+ mkEntry(CKT_NSS_TRUSTED_DELEGATOR, Trust),
+ mkEntry(CKT_NSS_NOT_TRUSTED, Trust),
+ mkEntry(CKT_NSS_MUST_VERIFY_TRUST, Trust),
+ mkEntry(CKT_NSS_TRUST_UNKNOWN, Trust),
+ mkEntry(CKT_NSS_VALID_DELEGATOR, Trust),
+
+ mkEntry(CK_EFFECTIVELY_INFINITE, AvailableSizes),
+ mkEntry(CK_UNAVAILABLE_INFORMATION, CurrentSize),
+};
+
+const Constant *consts = &_consts[0];
+const unsigned int constCount = sizeof(_consts) / sizeof(_consts[0]);
+
+const Commands _commands[] = {
+ { "C_Initialize",
+ F_C_Initialize,
+ "C_Initialize pInitArgs\n\n"
+ "C_Initialize initializes the PKCS #11 library.\n"
+ " pInitArgs if this is not NULL_PTR it gets cast to and dereferenced\n",
+ { ArgInitializeArgs, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "C_Finalize",
+ F_C_Finalize,
+ "C_Finalize pReserved\n\n"
+ "C_Finalize indicates that an application is done with the PKCS #11 library.\n"
+ " pReserved reserved. Should be NULL_PTR\n",
+ { ArgInitializeArgs, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "C_GetInfo",
+ F_C_GetInfo,
+ "C_GetInfo pInfo\n\n"
+ "C_GetInfo returns general information about PKCS #11.\n"
+ " pInfo location that receives information\n",
+ { ArgInfo | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "C_GetFunctionList",
+ F_C_GetFunctionList,
+ "C_GetFunctionList ppFunctionList\n\n"
+ "C_GetFunctionList returns the function list.\n"
+ " ppFunctionList receives pointer to function list\n",
+ { ArgFunctionList | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_GetSlotList",
+ F_C_GetSlotList,
+ "C_GetSlotList tokenPresent pSlotList pulCount\n\n"
+ "C_GetSlotList obtains a list of slots in the system.\n"
+ " tokenPresent only slots with tokens?\n"
+ " pSlotList receives array of slot IDs\n"
+ " pulCount receives number of slots\n",
+ { ArgULong, ArgULong | ArgArray | ArgOut, ArgULong | ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_GetSlotInfo",
+ F_C_GetSlotInfo,
+ "C_GetSlotInfo slotID pInfo\n\n"
+ "C_GetSlotInfo obtains information about a particular slot in the system.\n"
+ " slotID the ID of the slot\n"
+ " pInfo receives the slot information\n",
+ { ArgULong, ArgSlotInfo | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_GetTokenInfo",
+ F_C_GetTokenInfo,
+ "C_GetTokenInfo slotID pInfo\n\n"
+ "C_GetTokenInfo obtains information about a particular token in the system.\n"
+ " slotID ID of the token's slot\n"
+ " pInfo receives the token information\n",
+ { ArgULong, ArgTokenInfo | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_GetMechanismList",
+ F_C_GetMechanismList,
+ "C_GetMechanismList slotID pMechanismList pulCount\n\n"
+ "C_GetMechanismList obtains a list of mechanism types supported by a token.\n"
+ " slotID ID of token's slot\n"
+ " pMechanismList gets mech. array\n"
+ " pulCount gets # of mechs.\n",
+ { ArgULong, ArgULong | ArgArray | ArgOut, ArgULong | ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_GetMechanismInfo",
+ F_C_GetMechanismInfo,
+ "C_GetMechanismInfo slotID type pInfo\n\n"
+ "C_GetMechanismInfo obtains information about a particular mechanism possibly\n"
+ "supported by a token.\n"
+ " slotID ID of the token's slot\n"
+ " type type of mechanism\n"
+ " pInfo receives mechanism info\n",
+ { ArgULong, ArgULong, ArgMechanismInfo | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_InitToken",
+ F_C_InitToken,
+ "C_InitToken slotID pPin ulPinLen pLabel\n\n"
+ "C_InitToken initializes a token.\n"
+ " slotID ID of the token's slot\n"
+ " pPin the SO's initial PIN\n"
+ " ulPinLen length in bytes of the PIN\n"
+ " pLabel 32-byte token label (blank padded)\n",
+ { ArgULong, ArgUTF8, ArgULong, ArgUTF8, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "C_InitPIN",
+ F_C_InitPIN,
+ "C_InitPIN hSession pPin ulPinLen\n\n"
+ "C_InitPIN initializes the normal user's PIN.\n"
+ " hSession the session's handle\n"
+ " pPin the normal user's PIN\n"
+ " ulPinLen length in bytes of the PIN\n",
+ { ArgULong, ArgUTF8, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "C_SetPIN",
+ F_C_SetPIN,
+ "C_SetPIN hSession pOldPin ulOldLen pNewPin ulNewLen\n\n"
+ "C_SetPIN modifies the PIN of the user who is logged in.\n"
+ " hSession the session's handle\n"
+ " pOldPin the old PIN\n"
+ " ulOldLen length of the old PIN\n"
+ " pNewPin the new PIN\n"
+ " ulNewLen length of the new PIN\n",
+ { ArgULong, ArgUTF8, ArgULong, ArgUTF8, ArgULong, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "C_OpenSession",
+ F_C_OpenSession,
+ "C_OpenSession slotID flags phSession\n\n"
+ "C_OpenSession opens a session between an application and a token.\n"
+ " slotID the slot's ID\n"
+ " flags from\n"
+ " phSession gets session handle\n",
+ { ArgULong, ArgULong, ArgULong | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_CloseSession",
+ F_C_CloseSession,
+ "C_CloseSession hSession\n\n"
+ "C_CloseSession closes a session between an application and a token.\n"
+ " hSession the session's handle\n",
+ { ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "C_CloseAllSessions",
+ F_C_CloseAllSessions,
+ "C_CloseAllSessions slotID\n\n"
+ "C_CloseAllSessions closes all sessions with a token.\n"
+ " slotID the token's slot\n",
+ { ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "C_GetSessionInfo",
+ F_C_GetSessionInfo,
+ "C_GetSessionInfo hSession pInfo\n\n"
+ "C_GetSessionInfo obtains information about the session.\n"
+ " hSession the session's handle\n"
+ " pInfo receives session info\n",
+ { ArgULong, ArgSessionInfo | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_GetOperationState",
+ F_C_GetOperationState,
+ "C_GetOperationState hSession pOpState pulOpStateLen\n\n"
+ "C_GetOperationState obtains the state of the cryptographic operation in a\n"
+ "session.\n"
+ " hSession session's handle\n"
+ " pOpState gets state\n"
+ " pulOpStateLen gets state length\n",
+ { ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_SetOperationState",
+ F_C_SetOperationState,
+ "C_SetOperationState hSession pOpState ulOpStateLen hEncKey hAuthKey\n\n"
+ "C_SetOperationState restores the state of the cryptographic operation in a\n"
+ "session.\n"
+ " hSession session's handle\n"
+ " pOpState holds state\n"
+ " ulOpStateLen holds state length\n"
+ " hEncKey en/decryption key\n"
+ " hAuthnKey sign/verify key\n",
+ { ArgULong, ArgChar | ArgOut, ArgULong, ArgULong, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_Login",
+ F_C_Login,
+ "C_Login hSession userType pPin ulPinLen\n\n"
+ "C_Login logs a user into a token.\n"
+ " hSession the session's handle\n"
+ " userType the user type\n"
+ " pPin the user's PIN\n"
+ " ulPinLen the length of the PIN\n",
+ { ArgULong, ArgULong, ArgVar, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "C_Logout",
+ F_C_Logout,
+ "C_Logout hSession\n\n"
+ "C_Logout logs a user out from a token.\n"
+ " hSession the session's handle\n",
+ { ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "C_CreateObject",
+ F_C_CreateObject,
+ "C_CreateObject hSession pTemplate ulCount phObject\n\n"
+ "C_CreateObject creates a new object.\n"
+ " hSession the session's handle\n"
+ " pTemplate the object's template\n"
+ " ulCount attributes in template\n"
+ " phObject gets new object's handle.\n",
+ { ArgULong, ArgAttribute | ArgArray, ArgULong, ArgULong | ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_CopyObject",
+ F_C_CopyObject,
+ "C_CopyObject hSession hObject pTemplate ulCount phNewObject\n\n"
+ "C_CopyObject copies an object creating a new object for the copy.\n"
+ " hSession the session's handle\n"
+ " hObject the object's handle\n"
+ " pTemplate template for new object\n"
+ " ulCount attributes in template\n"
+ " phNewObject receives handle of copy\n",
+ { ArgULong, ArgULong, ArgAttribute | ArgArray, ArgULong, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_DestroyObject",
+ F_C_DestroyObject,
+ "C_DestroyObject hSession hObject\n\n"
+ "C_DestroyObject destroys an object.\n"
+ " hSession the session's handle\n"
+ " hObject the object's handle\n",
+ { ArgULong, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "C_GetObjectSize",
+ F_C_GetObjectSize,
+ "C_GetObjectSize hSession hObject pulSize\n\n"
+ "C_GetObjectSize gets the size of an object in bytes.\n"
+ " hSession the session's handle\n"
+ " hObject the object's handle\n"
+ " pulSize receives size of object\n",
+ { ArgULong, ArgULong, ArgULong | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_GetAttributeValue",
+ F_C_GetAttributeValue,
+ "C_GetAttributeValue hSession hObject pTemplate ulCount\n\n"
+ "C_GetAttributeValue obtains the value of one or more object attributes.\n"
+ " hSession the session's handle\n"
+ " hObject the object's handle\n"
+ " pTemplate specifies attrs; gets vals\n"
+ " ulCount attributes in template\n",
+ { ArgULong, ArgULong, ArgAttribute | ArgArray, ArgULong, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_SetAttributeValue",
+ F_C_SetAttributeValue,
+ "C_SetAttributeValue hSession hObject pTemplate ulCount\n\n"
+ "C_SetAttributeValue modifies the value of one or more object attributes\n"
+ " hSession the session's handle\n"
+ " hObject the object's handle\n"
+ " pTemplate specifies attrs and values\n"
+ " ulCount attributes in template\n",
+ { ArgULong, ArgULong, ArgAttribute | ArgArray, ArgULong, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_FindObjectsInit",
+ F_C_FindObjectsInit,
+ "C_FindObjectsInit hSession pTemplate ulCount\n\n"
+ "C_FindObjectsInit initializes a search for token and session objects that\n"
+ "match a template.\n"
+ " hSession the session's handle\n"
+ " pTemplate attribute values to match\n"
+ " ulCount attrs in search template\n",
+ { ArgULong, ArgAttribute | ArgArray, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_FindObjectsFinal",
+ F_C_FindObjectsFinal,
+ "C_FindObjectsFinal hSession\n\n"
+ "C_FindObjectsFinal finishes a search for token and session objects.\n"
+ " hSession the session's handle\n",
+ { ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "C_FindObjects",
+ F_C_FindObjects,
+ "C_FindObjects hSession phObject ulMaxObjectCount pulObjectCount\n\n"
+ "C_FindObjects continues a search for token and session objects that match\n"
+ "a template obtaining additional object handles.\n"
+ " hSession session's handle\n"
+ " phObject gets obj. handles\n"
+ " ulMaxObjectCount max handles to get\n"
+ " pulObjectCount actual # returned\n",
+ { ArgULong, ArgULong | ArgOut, ArgULong, ArgULong | ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_EncryptInit",
+ F_C_EncryptInit,
+ "C_EncryptInit hSession pMechanism hKey\n\n"
+ "C_EncryptInit initializes an encryption operation.\n"
+ " hSession the session's handle\n"
+ " pMechanism the encryption mechanism\n"
+ " hKey handle of encryption key\n",
+ { ArgULong, ArgMechanism, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "C_EncryptUpdate",
+ F_C_EncryptUpdate,
+ "C_EncryptUpdate hSession pPart ulPartLen pEncryptedPart pulEncryptedPartLen\n"
+ "\n"
+ "C_EncryptUpdate continues a multiple-part encryption operation.\n"
+ " hSession session's handle\n"
+ " pPart the plaintext data\n"
+ " ulPartLen plaintext data len\n"
+ " pEncryptedPart gets ciphertext\n"
+ " pulEncryptedPartLen gets c-text size\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_EncryptFinal",
+ F_C_EncryptFinal,
+ "C_EncryptFinal hSession pLastEncryptedPart pulLastEncryptedPartLen\n\n"
+ "C_EncryptFinal finishes a multiple-part encryption operation.\n"
+ " hSession session handle\n"
+ " pLastEncryptedPart last c-text\n"
+ " pulLastEncryptedPartLen gets last size\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_Encrypt",
+ F_C_Encrypt,
+ "C_Encrypt hSession pData ulDataLen pEncryptedData pulEncryptedDataLen\n\n"
+ "C_Encrypt encrypts single-part data.\n"
+ " hSession session's handle\n"
+ " pData the plaintext data\n"
+ " ulDataLen bytes of plaintext\n"
+ " pEncryptedData gets ciphertext\n"
+ " pulEncryptedDataLen gets c-text size\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_DecryptInit",
+ F_C_DecryptInit,
+ "C_DecryptInit hSession pMechanism hKey\n\n"
+ "C_DecryptInit initializes a decryption operation.\n"
+ " hSession the session's handle\n"
+ " pMechanism the decryption mechanism\n"
+ " hKey handle of decryption key\n",
+ { ArgULong, ArgMechanism, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "C_DecryptUpdate",
+ F_C_DecryptUpdate,
+ "C_DecryptUpdate hSession pEncryptedPart ulEncryptedPartLen pPart pulPartLen\n"
+ "\n"
+ "C_DecryptUpdate continues a multiple-part decryption operation.\n"
+ " hSession session's handle\n"
+ " pEncryptedPart encrypted data\n"
+ " ulEncryptedPartLen input length\n"
+ " pPart gets plaintext\n"
+ " pulPartLen p-text size\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_DecryptFinal",
+ F_C_DecryptFinal,
+ "C_DecryptFinal hSession pLastPart pulLastPartLen\n\n"
+ "C_DecryptFinal finishes a multiple-part decryption operation.\n"
+ " hSession the session's handle\n"
+ " pLastPart gets plaintext\n"
+ " pulLastPartLen p-text size\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_Decrypt",
+ F_C_Decrypt,
+ "C_Decrypt hSession pEncryptedData ulEncryptedDataLen pData pulDataLen\n\n"
+ "C_Decrypt decrypts encrypted data in a single part.\n"
+ " hSession session's handle\n"
+ " pEncryptedData ciphertext\n"
+ " ulEncryptedDataLen ciphertext length\n"
+ " pData gets plaintext\n"
+ " pulDataLen gets p-text size\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_DigestInit",
+ F_C_DigestInit,
+ "C_DigestInit hSession pMechanism\n\n"
+ "C_DigestInit initializes a message-digesting operation.\n"
+ " hSession the session's handle\n"
+ " pMechanism the digesting mechanism\n",
+ { ArgULong, ArgMechanism, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "C_DigestUpdate",
+ F_C_DigestUpdate,
+ "C_DigestUpdate hSession pPart ulPartLen\n\n"
+ "C_DigestUpdate continues a multiple-part message-digesting operation.\n"
+ " hSession the session's handle\n"
+ " pPart data to be digested\n"
+ " ulPartLen bytes of data to be digested\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_DigestKey",
+ F_C_DigestKey,
+ "C_DigestKey hSession hKey\n\n"
+ "C_DigestKey continues a multi-part message-digesting operation by digesting\n"
+ "the value of a secret key as part of the data already digested.\n"
+ " hSession the session's handle\n"
+ " hKey secret key to digest\n",
+ { ArgULong, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "C_DigestFinal",
+ F_C_DigestFinal,
+ "C_DigestFinal hSession pDigest pulDigestLen\n\n"
+ "C_DigestFinal finishes a multiple-part message-digesting operation.\n"
+ " hSession the session's handle\n"
+ " pDigest gets the message digest\n"
+ " pulDigestLen gets byte count of digest\n",
+ { ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_Digest",
+ F_C_Digest,
+ "C_Digest hSession pData ulDataLen pDigest pulDigestLen\n\n"
+ "C_Digest digests data in a single part.\n"
+ " hSession the session's handle\n"
+ " pData data to be digested\n"
+ " ulDataLen bytes of data to digest\n"
+ " pDigest gets the message digest\n"
+ " pulDigestLen gets digest length\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_SignInit",
+ F_C_SignInit,
+ "C_SignInit hSession pMechanism hKey\n\n"
+ "C_SignInit initializes a signature (private key encryption operation where\n"
+ "the signature is (will be) an appendix to the data and plaintext cannot be\n"
+ "recovered from the signature.\n"
+ " hSession the session's handle\n"
+ " pMechanism the signature mechanism\n"
+ " hKey handle of signature key\n",
+ { ArgULong, ArgMechanism, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "C_SignUpdate",
+ F_C_SignUpdate,
+ "C_SignUpdate hSession pPart ulPartLen\n\n"
+ "C_SignUpdate continues a multiple-part signature operation where the\n"
+ "signature is (will be) an appendix to the data and plaintext cannot be\n"
+ "recovered from the signature.\n"
+ " hSession the session's handle\n"
+ " pPart the data to sign\n"
+ " ulPartLen count of bytes to sign\n",
+ { ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_SignFinal",
+ F_C_SignFinal,
+ "C_SignFinal hSession pSignature pulSignatureLen\n\n"
+ "C_SignFinal finishes a multiple-part signature operation returning the\n"
+ "signature.\n"
+ " hSession the session's handle\n"
+ " pSignature gets the signature\n"
+ " pulSignatureLen gets signature length\n",
+ { ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_SignRecoverInit",
+ F_C_SignRecoverInit,
+ "C_SignRecoverInit hSession pMechanism hKey\n\n"
+ "C_SignRecoverInit initializes a signature operation where the data can be\n"
+ "recovered from the signature.\n"
+ " hSession the session's handle\n"
+ " pMechanism the signature mechanism\n"
+ " hKey handle of the signature key\n",
+ { ArgULong, ArgMechanism, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "C_SignRecover",
+ F_C_SignRecover,
+ "C_SignRecover hSession pData ulDataLen pSignature pulSignatureLen\n\n"
+ "C_SignRecover signs data in a single operation where the data can be\n"
+ "recovered from the signature.\n"
+ " hSession the session's handle\n"
+ " pData the data to sign\n"
+ " ulDataLen count of bytes to sign\n"
+ " pSignature gets the signature\n"
+ " pulSignatureLen gets signature length\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_Sign",
+ F_C_Sign,
+ "C_Sign hSession pData ulDataLen pSignature pulSignatureLen\n\n"
+ "C_Sign signs (encrypts with private key) data in a single part where the\n"
+ "signature is (will be) an appendix to the data and plaintext cannot be\n"
+ "recovered from the signature.\n"
+ " hSession the session's handle\n"
+ " pData the data to sign\n"
+ " ulDataLen count of bytes to sign\n"
+ " pSignature gets the signature\n"
+ " pulSignatureLen gets signature length\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_VerifyInit",
+ F_C_VerifyInit,
+ "C_VerifyInit hSession pMechanism hKey\n\n"
+ "C_VerifyInit initializes a verification operation where the signature is an\n"
+ "appendix to the data and plaintext cannot cannot be recovered from the\n"
+ "signature (e.g. DSA).\n"
+ " hSession the session's handle\n"
+ " pMechanism the verification mechanism\n"
+ " hKey verification key\n",
+ { ArgULong, ArgMechanism, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "C_VerifyUpdate",
+ F_C_VerifyUpdate,
+ "C_VerifyUpdate hSession pPart ulPartLen\n\n"
+ "C_VerifyUpdate continues a multiple-part verification operation where the\n"
+ "signature is an appendix to the data and plaintext cannot be recovered from\n"
+ "the signature.\n"
+ " hSession the session's handle\n"
+ " pPart signed data\n"
+ " ulPartLen length of signed data\n",
+ { ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_VerifyFinal",
+ F_C_VerifyFinal,
+ "C_VerifyFinal hSession pSignature ulSignatureLen\n\n"
+ "C_VerifyFinal finishes a multiple-part verification operation checking the\n"
+ "signature.\n"
+ " hSession the session's handle\n"
+ " pSignature signature to verify\n"
+ " ulSignatureLen signature length\n",
+ { ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "C_VerifyRecoverInit",
+ F_C_VerifyRecoverInit,
+ "C_VerifyRecoverInit hSession pMechanism hKey\n\n"
+ "C_VerifyRecoverInit initializes a signature verification operation where the\n"
+ "data is recovered from the signature.\n"
+ " hSession the session's handle\n"
+ " pMechanism the verification mechanism\n"
+ " hKey verification key\n",
+ { ArgULong, ArgMechanism, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "C_VerifyRecover",
+ F_C_VerifyRecover,
+ "C_VerifyRecover hSession pSignature ulSignatureLen pData pulDataLen\n\n"
+ "C_VerifyRecover verifies a signature in a single-part operation where the\n"
+ "data is recovered from the signature.\n"
+ " hSession the session's handle\n"
+ " pSignature signature to verify\n"
+ " ulSignatureLen signature length\n"
+ " pData gets signed data\n"
+ " pulDataLen gets signed data len\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_Verify",
+ F_C_Verify,
+ "C_Verify hSession pData ulDataLen pSignature ulSignatureLen\n\n"
+ "C_Verify verifies a signature in a single-part operation where the signature\n"
+ "is an appendix to the data and plaintext cannot be recovered from the\n"
+ "signature.\n"
+ " hSession the session's handle\n"
+ " pData signed data\n"
+ " ulDataLen length of signed data\n"
+ " pSignature signature\n"
+ " ulSignatureLen signature length*/\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_DigestEncryptUpdate",
+ F_C_DigestEncryptUpdate,
+ "C_DigestEncryptUpdate hSession pPart ulPartLen pEncryptedPart \\\n"
+ " pulEncryptedPartLen\n\n"
+ "C_DigestEncryptUpdate continues a multiple-part digesting and encryption\n"
+ "operation.\n"
+ " hSession session's handle\n"
+ " pPart the plaintext data\n"
+ " ulPartLen plaintext length\n"
+ " pEncryptedPart gets ciphertext\n"
+ " pulEncryptedPartLen gets c-text length\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_DecryptDigestUpdate",
+ F_C_DecryptDigestUpdate,
+ "C_DecryptDigestUpdate hSession pEncryptedPart ulEncryptedPartLen pPart \\\n"
+ " pulPartLen\n\n"
+ "C_DecryptDigestUpdate continues a multiple-part decryption and digesting\n"
+ "operation.\n"
+ " hSession session's handle\n"
+ " pEncryptedPart ciphertext\n"
+ " ulEncryptedPartLen ciphertext length\n"
+ " pPart gets plaintext\n"
+ " pulPartLen gets plaintext len\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_SignEncryptUpdate",
+ F_C_SignEncryptUpdate,
+ "C_SignEncryptUpdate hSession pPart ulPartLen pEncryptedPart \\\n"
+ " pulEncryptedPartLen\n\n"
+ "C_SignEncryptUpdate continues a multiple-part signing and encryption\n"
+ "operation.\n"
+ " hSession session's handle\n"
+ " pPart the plaintext data\n"
+ " ulPartLen plaintext length\n"
+ " pEncryptedPart gets ciphertext\n"
+ " pulEncryptedPartLen gets c-text length\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_DecryptVerifyUpdate",
+ F_C_DecryptVerifyUpdate,
+ "C_DecryptVerifyUpdate hSession pEncryptedPart ulEncryptedPartLen pPart \\\n"
+ " pulPartLen\n\n"
+ "C_DecryptVerifyUpdate continues a multiple-part decryption and verify\n"
+ "operation.\n"
+ " hSession session's handle\n"
+ " pEncryptedPart ciphertext\n"
+ " ulEncryptedPartLen ciphertext length\n"
+ " pPart gets plaintext\n"
+ " pulPartLen gets p-text length\n",
+ { ArgULong, ArgChar, ArgULong, ArgChar | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_GenerateKeyPair",
+ F_C_GenerateKeyPair,
+ "C_GenerateKeyPair hSession pMechanism pPublicKeyTemplate \\\n"
+ " ulPublicKeyAttributeCount pPrivateKeyTemplate ulPrivateKeyAttributeCount \\\n"
+ " phPublicKey phPrivateKey\n\n"
+ "C_GenerateKeyPair generates a public-key/private-key pair creating new key\n"
+ "objects.\n"
+ " hSession sessionhandle\n"
+ " pMechanism key-genmech.\n"
+ " pPublicKeyTemplate templatefor pub. key\n"
+ " ulPublicKeyAttributeCount # pub. attrs.\n"
+ " pPrivateKeyTemplate templatefor priv. key\n"
+ " ulPrivateKeyAttributeCount # priv. attrs.\n"
+ " phPublicKey gets pub. keyhandle\n"
+ " phPrivateKey getspriv. keyhandle\n",
+ { ArgULong, ArgMechanism, ArgAttribute | ArgArray, ArgULong,
+ ArgAttribute | ArgArray, ArgULong, ArgULong | ArgOut, ArgULong | ArgOut, ArgNone,
+ ArgNone } },
+ { "C_GenerateKey",
+ F_C_GenerateKey,
+ "C_GenerateKey hSession pMechanism pTemplate ulCount phKey\n\n"
+ "C_GenerateKey generates a secret key creating a new key object.\n"
+ " hSession the session's handle\n"
+ " pMechanism key generation mech.\n"
+ " pTemplate template for new key\n"
+ " ulCount # of attrs in template\n"
+ " phKey gets handle of new key\n",
+ { ArgULong, ArgMechanism, ArgAttribute | ArgArray, ArgULong, ArgULong | ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_WrapKey",
+ F_C_WrapKey,
+ "C_WrapKey hSession pMechanism hWrappingKey hKey pWrappedKey pulWrappedKeyLen\n\n"
+ "C_WrapKey wraps (i.e. encrypts) a key.\n"
+ " hSession the session's handle\n"
+ " pMechanism the wrapping mechanism\n"
+ " hWrappingKey wrapping key\n"
+ " hKey key to be wrapped\n"
+ " pWrappedKey gets wrapped key\n"
+ " pulWrappedKeyLen gets wrapped key size\n",
+ { ArgULong, ArgMechanism, ArgULong, ArgULong, ArgULong, ArgChar | ArgOut,
+ ArgULong | ArgOut, ArgNone, ArgNone, ArgNone } },
+ { "C_UnwrapKey",
+ F_C_UnwrapKey,
+ "C_UnwrapKey hSession pMechanism hUnwrappingKey pWrappedKey ulWrappedKeyLen \\\n"
+ " pTemplate ulAttributeCount phKey\n\n"
+ "C_UnwrapKey unwraps (decrypts) a wrapped key creating a new key object.\n"
+ " hSession session's handle\n"
+ " pMechanism unwrapping mech.\n"
+ " hUnwrappingKey unwrapping key\n"
+ " pWrappedKey the wrapped key\n"
+ " ulWrappedKeyLen wrapped key len\n"
+ " pTemplate new key template\n"
+ " ulAttributeCount template length\n"
+ " phKey gets new handle\n",
+ { ArgULong, ArgMechanism, ArgULong, ArgChar, ArgULong, ArgAttribute | ArgArray,
+ ArgULong, ArgULong | ArgOut, ArgNone, ArgNone } },
+ { "C_DeriveKey",
+ F_C_DeriveKey,
+ "C_DeriveKey hSession pMechanism hBaseKey pTemplate ulAttributeCount phKey\n\n"
+ "C_DeriveKey derives a key from a base key creating a new key object.\n"
+ " hSession session's handle\n"
+ " pMechanism key deriv. mech.\n"
+ " hBaseKey base key\n"
+ " pTemplate new key template\n"
+ " ulAttributeCount template length\n"
+ " phKey gets new handle\n",
+ { ArgULong, ArgMechanism, ArgULong, ArgAttribute | ArgArray, ArgULong,
+ ArgULong | ArgOut, ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "C_SeedRandom",
+ F_C_SeedRandom,
+ "C_SeedRandom hSession pSeed ulSeedLen\n\n"
+ "C_SeedRandom mixes additional seed material into the token's random number\n"
+ "generator.\n"
+ " hSession the session's handle\n"
+ " pSeed the seed material\n"
+ " ulSeedLen length of seed material\n",
+ { ArgULong, ArgChar, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "C_GenerateRandom",
+ F_C_GenerateRandom,
+ "C_GenerateRandom hSession RandomData ulRandomLen\n\n"
+ "C_GenerateRandom generates random data.\n"
+ " hSession the session's handle\n"
+ " RandomData receives the random data\n"
+ " ulRandomLen # of bytes to generate\n",
+ { ArgULong, ArgChar, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "C_GetFunctionStatus",
+ F_C_GetFunctionStatus,
+ "C_GetFunctionStatus hSession\n\n"
+ "C_GetFunctionStatus is a legacy function; it obtains an updated status of\n"
+ "a function running in parallel with an application.\n"
+ " hSession the session's handle\n",
+ { ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "C_CancelFunction",
+ F_C_CancelFunction,
+ "C_CancelFunction hSession\n\n"
+ "C_CancelFunction is a legacy function; it cancels a function running in\n"
+ "parallel.\n"
+ " hSession the session's handle\n",
+ { ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "C_WaitForSlotEvent",
+ F_C_WaitForSlotEvent,
+ "C_WaitForSlotEvent flags pSlot pRserved\n\n"
+ "C_WaitForSlotEvent waits for a slot event (token insertion removal etc.)\n"
+ "to occur.\n"
+ " flags blocking/nonblocking flag\n"
+ " pSlot location that receives the slot ID\n"
+ " pRserved reserved. Should be NULL_PTR\n",
+ { ArgULong, ArgULong | ArgArray, ArgVar, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "NewArray",
+ F_NewArray,
+ "NewArray varName varType array size\n\n"
+ "Creates a new array variable.\n"
+ " varName variable name of the new array\n"
+ " varType data type of the new array\n"
+ " size number of elements in the array\n",
+ { ArgVar | ArgNew, ArgVar, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "NewInitArg",
+ F_NewInitializeArgs,
+ "NewInitArg varName flags string\n\n"
+ "Creates a new init variable.\n"
+ " varName variable name of the new initArg\n"
+ " flags value to set the flags field\n"
+ " string string parameter for init arg\n",
+ { ArgVar | ArgNew, ArgULong, ArgVar | ArgNew, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "NewTemplate",
+ F_NewTemplate,
+ "NewTemplate varName attributeList\n\n"
+ "Create a new empty template and populate the attribute list\n"
+ " varName variable name of the new template\n"
+ " attributeList comma separated list of CKA_ATTRIBUTE types\n",
+ { ArgVar | ArgNew, ArgVar, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "NewMechanism",
+ F_NewMechanism,
+ "NewMechanism varName mechanismType\n\n"
+ "Create a new CK_MECHANISM object with type NULL parameters and specified type\n"
+ " varName variable name of the new mechansim\n"
+ " mechanismType CKM_ mechanism type value to set int the type field\n",
+ { ArgVar | ArgNew, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "BuildTemplate",
+ F_BuildTemplate,
+ "BuildTemplate template\n\n"
+ "Allocates space for the value in a template which has the sizes filled in,\n"
+ "but no values allocated yet.\n"
+ " template variable name of the template\n",
+ { ArgAttribute, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "SetTemplate",
+ F_SetTemplate,
+ "SetTemplate template index value\n\n"
+ "Sets a particular element of a template to a CK_ULONG\n"
+ " template variable name of the template\n"
+ " index index into the template to the element to change\n"
+ " value 32 bit value to set in the template\n",
+ { ArgAttribute, ArgULong, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "SetString",
+ F_SetStringVar,
+ "SetString varName string\n\n"
+ "Sets a particular variable to a string value\n"
+ " variable variable name of new string\n"
+ " string String to set the variable to\n",
+ { ArgVar | ArgNew, ArgVar, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "Set",
+ F_SetVar,
+ "Set varName value\n\n"
+ "Sets a particular variable to CK_ULONG\n"
+ " variable name of the new variable\n"
+ " value 32 bit value to set variable to\n",
+ { ArgVar | ArgNew, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "Print",
+ F_Print,
+ "Print varName\n\n"
+ "prints a variable\n"
+ " variable name of the variable to print\n",
+ { ArgVar, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "Delete",
+ F_Delete,
+ "Delete varName\n\n"
+ "delete a variable\n"
+ " variable name of the variable to delete\n",
+ { ArgVar | ArgNew, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "Load",
+ F_Load,
+ "load libraryName\n\n"
+ "load a pkcs #11 module\n"
+ " libraryName Name of a shared library\n",
+ { ArgVar, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "Save",
+ F_SaveVar,
+ "Save filename variable\n\n"
+ "Saves the binary value of 'variable' in file 'filename'\n"
+ " fileName target file to save the variable in\n"
+ " variable variable to save\n",
+ { ArgVar | ArgNew, ArgVar, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "Restore",
+ F_RestoreVar,
+ "Restore filename variable\n\n"
+ "Restores a variable from a file\n"
+ " fileName target file to restore the variable from\n"
+ " variable variable to restore\n",
+ { ArgVar | ArgNew, ArgVar, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "Increment",
+ F_Increment,
+ "Increment variable value\n\n"
+ "Increment a variable by value\n",
+ { ArgVar, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "Decrement",
+ F_Decrement,
+ "Decrement variable value\n\n"
+ "Decrement a variable by value\n",
+ { ArgVar, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "List",
+ F_List,
+ "List all the variables\n",
+ { ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "Unload",
+ F_Unload,
+ "Unload the currrently loaded PKCS #11 library\n",
+ { ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "Run",
+ F_Run,
+ "Run filename\n\n"
+ "reads filename as script of commands to execute\n",
+ { ArgVar | ArgNew, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "Time",
+ F_Time,
+ "Time pkcs11 command\n\n"
+ "Execute a pkcs #11 command and time the results\n",
+ { ArgVar | ArgFull, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "System",
+ F_System,
+ "Set System Flag",
+ { ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+ { "LoopRun",
+ F_Loop,
+ "LoopRun filename var start end step\n\n"
+ "Run in a loop. Loop exit if scrip does and explicit quit (Quit QuitIf etc.)",
+ { ArgVar | ArgNew, ArgVar | ArgNew, ArgULong, ArgULong, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone } },
+ { "Help",
+ F_Help,
+ "Help [command]\n\n"
+ "print general help, or help for a specific command\n",
+ { ArgVar | ArgOpt, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "QuitIf",
+ F_QuitIf,
+ "QuitIf arg1 comparator arg2\n\n"
+ "Exit from this program if Condition is valid, valid comparators:\n"
+ " < > <= >= = !=\n",
+ { ArgULong, ArgVar | ArgNew, ArgULong, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone } },
+ { "QuitIfString",
+ F_QuitIfString,
+ "QuitIfString arg1 comparator arg2\n\n"
+ "Exit from this program if Condition is valid, valid comparators:\n"
+ " = !=\n",
+ { ArgVar | ArgNew, ArgVar | ArgNew, ArgVar | ArgNew, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone } },
+ { "Quit",
+ F_Quit,
+ "Exit from this program",
+ { ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone } },
+};
+
+const Commands *commands = &_commands[0];
+const int commandCount = sizeof(_commands) / sizeof(_commands[0]);
+
+const Topics _topics[] = {
+ { "variables",
+ "Variables are random strings of characters. These should begin with alpha\n"
+ " characters, and should not contain any spaces, nor should they match any\n"
+ " built-in constants. There is some checking in the code for these things,\n"
+ " but it's not 100% and using invalid variable names can cause problems.\n"
+ " Variables are created by any 'OUT' parameter. If the variable does not\n"
+ " exist, it will be created. For in parameters variables must already exist.\n" },
+ { "constants",
+ "pk11util recognizes *lots* of constants. All CKA_, CKF_, CKO_, CKU_, CKS_,\n"
+ " CKC_, CKK_, CKH_, CKM_, CKT_ values from the PKCS #11 spec are recognized.\n"
+ " Constants can be specified with their fully qualified CK?_ value, or the\n"
+ " prefix can be dropped. Constants are matched case insensitve.\n" },
+ { "arrays",
+ "Arrays are special variables which represent 'C' arrays. Each array \n"
+ " variable can be referenced as a group (using just the name), or as \n"
+ " individual elements (with the [int] operator). Example:\n"
+ " print myArray # prints the full array.\n"
+ " print myArray[3] # prints the 3rd elemement of the array \n" },
+ { "sizes",
+ "Size operaters returns the size in bytes of a variable, or the number of\n"
+ " elements in an array.\n"
+ " size(var) and sizeof(var) return the size of var in bytes.\n"
+ " sizea(var) and sizeofarray(var) return the number of elements in var.\n"
+ " If var is not an array, sizea(var) returns 1.\n" },
+};
+
+const Topics *topics = &_topics[0];
+const int topicCount = sizeof(_topics) / sizeof(_topics[0]);
+
+const char *
+getName(CK_ULONG value, ConstType type)
+{
+ unsigned int i;
+
+ for (i = 0; i < constCount; i++) {
+ if (consts[i].type == type && consts[i].value == value) {
+ return consts[i].name;
+ }
+ if (type == ConstNone && consts[i].value == value) {
+ return consts[i].name;
+ }
+ }
+
+ return NULL;
+}
+
+const char *
+getNameFromAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ return getName(type, ConstAttribute);
+}
+
+unsigned int
+totalKnownType(ConstType type)
+{
+ unsigned int count = 0;
+ unsigned int i;
+
+ for (i = 0; i < constCount; i++) {
+ if (consts[i].type == type)
+ count++;
+ }
+ return count;
+}
diff --git a/security/nss/cmd/lib/pk11table.h b/security/nss/cmd/lib/pk11table.h
new file mode 100644
index 000000000..3dea8204d
--- /dev/null
+++ b/security/nss/cmd/lib/pk11table.h
@@ -0,0 +1,178 @@
+/* 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 _PK11_TABLE_H_
+#define _PK11_TABLE_H_
+
+/*
+ * Supported functions..
+ */
+#include <pkcs11.h>
+#include "nspr.h"
+#include "prtypes.h"
+
+typedef enum {
+ F_No_Function,
+#undef CK_NEED_ARG_LIST
+#define CK_PKCS11_FUNCTION_INFO(func) F_##func,
+#include "pkcs11f.h"
+#undef CK_NEED_ARG_LISt
+#undef CK_PKCS11_FUNCTION_INFO
+ F_SetVar,
+ F_SetStringVar,
+ F_NewArray,
+ F_NewInitializeArgs,
+ F_NewTemplate,
+ F_NewMechanism,
+ F_BuildTemplate,
+ F_SetTemplate,
+ F_Print,
+ F_SaveVar,
+ F_RestoreVar,
+ F_Increment,
+ F_Decrement,
+ F_Delete,
+ F_List,
+ F_Run,
+ F_Load,
+ F_Unload,
+ F_System,
+ F_Loop,
+ F_Time,
+ F_Help,
+ F_Quit,
+ F_QuitIf,
+ F_QuitIfString
+} FunctionType;
+
+/*
+ * Supported Argument Types
+ */
+typedef enum {
+ ArgNone,
+ ArgVar,
+ ArgULong,
+ ArgChar,
+ ArgUTF8,
+ ArgInfo,
+ ArgSlotInfo,
+ ArgTokenInfo,
+ ArgSessionInfo,
+ ArgAttribute,
+ ArgMechanism,
+ ArgMechanismInfo,
+ ArgInitializeArgs,
+ ArgFunctionList,
+ /* Modifier Flags */
+ ArgMask = 0xff,
+ ArgOut = 0x100,
+ ArgArray = 0x200,
+ ArgNew = 0x400,
+ ArgFile = 0x800,
+ ArgStatic = 0x1000,
+ ArgOpt = 0x2000,
+ ArgFull = 0x4000
+} ArgType;
+
+typedef enum _constType {
+ ConstNone,
+ ConstBool,
+ ConstInfoFlags,
+ ConstSlotFlags,
+ ConstTokenFlags,
+ ConstSessionFlags,
+ ConstMechanismFlags,
+ ConstInitializeFlags,
+ ConstUsers,
+ ConstSessionState,
+ ConstObject,
+ ConstHardware,
+ ConstKeyType,
+ ConstCertType,
+ ConstAttribute,
+ ConstMechanism,
+ ConstResult,
+ ConstTrust,
+ ConstAvailableSizes,
+ ConstCurrentSize
+} ConstType;
+
+typedef struct _constant {
+ const char *name;
+ CK_ULONG value;
+ ConstType type;
+ ConstType attrType;
+} Constant;
+
+/*
+ * Values structures.
+ */
+typedef struct _values {
+ ArgType type;
+ ConstType constType;
+ int size;
+ char *filename;
+ void *data;
+ int reference;
+ int arraySize;
+} Value;
+
+/*
+ * Variables
+ */
+typedef struct _variable Variable;
+struct _variable {
+ Variable *next;
+ char *vname;
+ Value *value;
+};
+
+/* NOTE: if you change MAX_ARGS, you need to change the commands array
+ * below as well.
+ */
+
+#define MAX_ARGS 10
+/*
+ * structure for master command array
+ */
+typedef struct _commands {
+ char *fname;
+ FunctionType fType;
+ char *helpString;
+ ArgType args[MAX_ARGS];
+} Commands;
+
+typedef struct _module {
+ PRLibrary *library;
+ CK_FUNCTION_LIST *functionList;
+} Module;
+
+typedef struct _topics {
+ char *name;
+ char *helpString;
+} Topics;
+
+/*
+ * the command array itself. Make name to function and it's arguments
+ */
+
+extern const char **valueString;
+extern const int valueCount;
+extern const char **constTypeString;
+extern const int constTypeCount;
+extern const Constant *consts;
+extern const unsigned int constCount;
+extern const Commands *commands;
+extern const int commandCount;
+extern const Topics *topics;
+extern const int topicCount;
+
+extern const char *
+getName(CK_ULONG value, ConstType type);
+
+extern const char *
+getNameFromAttribute(CK_ATTRIBUTE_TYPE type);
+
+extern unsigned int totalKnownType(ConstType type);
+
+#endif /* _PK11_TABLE_H_ */
diff --git a/security/nss/cmd/lib/pppolicy.c b/security/nss/cmd/lib/pppolicy.c
new file mode 100644
index 000000000..aaf45599d
--- /dev/null
+++ b/security/nss/cmd/lib/pppolicy.c
@@ -0,0 +1,263 @@
+/* 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/. */
+
+/*
+ * Support for various policy related extensions
+ */
+
+#include "seccomon.h"
+#include "secport.h"
+#include "secder.h"
+#include "cert.h"
+#include "secoid.h"
+#include "secasn1.h"
+#include "secerr.h"
+#include "nspr.h"
+#include "secutil.h"
+
+/* This implementation is derived from the one in nss/lib/certdb/policyxtn.c .
+** The chief difference is the addition of the OPTIONAL flag to many
+** parts. The idea is to be able to parse and print as much of the
+** policy extension as possible, even if some parts are invalid.
+**
+** If this approach still is unable to decode policy extensions that
+** contain invalid parts, then the next approach will be to parse
+** the PolicyInfos as a SEQUENCE of ANYs, and then parse each of them
+** as PolicyInfos, with the PolicyQualifiers being ANYs, and finally
+** parse each of the PolicyQualifiers.
+*/
+
+static const SEC_ASN1Template secu_PolicyQualifierTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CERTPolicyQualifier) },
+ { SEC_ASN1_OBJECT_ID,
+ offsetof(CERTPolicyQualifier, qualifierID) },
+ { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
+ offsetof(CERTPolicyQualifier, qualifierValue) },
+ { 0 }
+};
+
+static const SEC_ASN1Template secu_PolicyInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CERTPolicyInfo) },
+ { SEC_ASN1_OBJECT_ID,
+ offsetof(CERTPolicyInfo, policyID) },
+ { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL,
+ offsetof(CERTPolicyInfo, policyQualifiers),
+ secu_PolicyQualifierTemplate },
+ { 0 }
+};
+
+static const SEC_ASN1Template secu_CertificatePoliciesTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF,
+ offsetof(CERTCertificatePolicies, policyInfos),
+ secu_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) }
+};
+
+static CERTCertificatePolicies *
+secu_DecodeCertificatePoliciesExtension(SECItem *extnValue)
+{
+ PLArenaPool *arena = NULL;
+ SECStatus rv;
+ CERTCertificatePolicies *policies;
+ CERTPolicyInfo **policyInfos, *policyInfo;
+ CERTPolicyQualifier **policyQualifiers, *policyQualifier;
+ SECItem newExtnValue;
+
+ /* make a new arena */
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!arena) {
+ goto loser;
+ }
+
+ /* allocate the certifiate policies structure */
+ policies = PORT_ArenaZNew(arena, CERTCertificatePolicies);
+ if (policies == NULL) {
+ goto loser;
+ }
+
+ policies->arena = arena;
+
+ /* copy the DER into the arena, since Quick DER returns data that points
+ into the DER input, which may get freed by the caller */
+ rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ /* decode the policy info */
+ rv = SEC_QuickDERDecodeItem(arena, policies,
+ secu_CertificatePoliciesTemplate,
+ &newExtnValue);
+
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ /* initialize the oid tags */
+ policyInfos = policies->policyInfos;
+ while (policyInfos != NULL && *policyInfos != NULL) {
+ policyInfo = *policyInfos;
+ policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID);
+ policyQualifiers = policyInfo->policyQualifiers;
+ while (policyQualifiers && *policyQualifiers != NULL) {
+ policyQualifier = *policyQualifiers;
+ policyQualifier->oid =
+ SECOID_FindOIDTag(&policyQualifier->qualifierID);
+ policyQualifiers++;
+ }
+ policyInfos++;
+ }
+
+ return (policies);
+
+loser:
+ if (arena != NULL) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return (NULL);
+}
+
+static char *
+itemToString(SECItem *item)
+{
+ char *string;
+
+ string = PORT_ZAlloc(item->len + 1);
+ if (string == NULL)
+ return NULL;
+ PORT_Memcpy(string, item->data, item->len);
+ string[item->len] = 0;
+ return string;
+}
+
+static SECStatus
+secu_PrintUserNoticeQualifier(FILE *out, SECItem *qualifierValue,
+ char *msg, int level)
+{
+ CERTUserNotice *userNotice = NULL;
+ if (qualifierValue)
+ userNotice = CERT_DecodeUserNotice(qualifierValue);
+ if (userNotice) {
+ if (userNotice->noticeReference.organization.len != 0) {
+ char *string =
+ itemToString(&userNotice->noticeReference.organization);
+ SECItem **itemList = userNotice->noticeReference.noticeNumbers;
+
+ while (itemList && *itemList) {
+ SECU_PrintInteger(out, *itemList, string, level + 1);
+ itemList++;
+ }
+ PORT_Free(string);
+ }
+ if (userNotice->displayText.len != 0) {
+ SECU_PrintString(out, &userNotice->displayText,
+ "Display Text", level + 1);
+ }
+ CERT_DestroyUserNotice(userNotice);
+ return SECSuccess;
+ }
+ return SECFailure; /* caller will print this value */
+}
+
+static SECStatus
+secu_PrintPolicyQualifier(FILE *out, CERTPolicyQualifier *policyQualifier,
+ char *msg, int level)
+{
+ SECStatus rv;
+ SECItem *qualifierValue = &policyQualifier->qualifierValue;
+
+ SECU_PrintObjectID(out, &policyQualifier->qualifierID,
+ "Policy Qualifier Name", level);
+ if (!qualifierValue->data) {
+ SECU_Indent(out, level);
+ fprintf(out, "Error: missing qualifier\n");
+ } else
+ switch (policyQualifier->oid) {
+ case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
+ rv = secu_PrintUserNoticeQualifier(out, qualifierValue, msg, level);
+ if (SECSuccess == rv)
+ break;
+ /* fall through on error */
+ case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
+ default:
+ SECU_PrintAny(out, qualifierValue, "Policy Qualifier Data", level);
+ break;
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+secu_PrintPolicyInfo(FILE *out, CERTPolicyInfo *policyInfo, char *msg, int level)
+{
+ CERTPolicyQualifier **policyQualifiers;
+
+ policyQualifiers = policyInfo->policyQualifiers;
+ SECU_PrintObjectID(out, &policyInfo->policyID, "Policy Name", level);
+
+ while (policyQualifiers && *policyQualifiers != NULL) {
+ secu_PrintPolicyQualifier(out, *policyQualifiers, "", level + 1);
+ policyQualifiers++;
+ }
+ return SECSuccess;
+}
+
+void
+SECU_PrintPolicy(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTCertificatePolicies *policies = NULL;
+ CERTPolicyInfo **policyInfos;
+
+ if (msg) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s: \n", msg);
+ level++;
+ }
+ policies = secu_DecodeCertificatePoliciesExtension(value);
+ if (policies == NULL) {
+ SECU_PrintAny(out, value, "Invalid Policy Data", level);
+ return;
+ }
+
+ policyInfos = policies->policyInfos;
+ while (policyInfos && *policyInfos != NULL) {
+ secu_PrintPolicyInfo(out, *policyInfos, "", level);
+ policyInfos++;
+ }
+
+ CERT_DestroyCertificatePoliciesExtension(policies);
+}
+
+void
+SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value,
+ char *msg, int level)
+{
+ CERTPrivKeyUsagePeriod *prd;
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!arena) {
+ goto loser;
+ }
+ prd = CERT_DecodePrivKeyUsagePeriodExtension(arena, value);
+ if (!prd) {
+ goto loser;
+ }
+ if (prd->notBefore.data) {
+ SECU_PrintGeneralizedTime(out, &prd->notBefore, "Not Before", level);
+ }
+ if (prd->notAfter.data) {
+ SECU_PrintGeneralizedTime(out, &prd->notAfter, "Not After ", level);
+ }
+ if (!prd->notBefore.data && !prd->notAfter.data) {
+ SECU_Indent(out, level);
+ fprintf(out, "Error: notBefore or notAfter MUST be present.\n");
+ loser:
+ SECU_PrintAny(out, value, msg, level);
+ }
+ if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+}
diff --git a/security/nss/cmd/lib/secpwd.c b/security/nss/cmd/lib/secpwd.c
new file mode 100644
index 000000000..7e99b2757
--- /dev/null
+++ b/security/nss/cmd/lib/secpwd.c
@@ -0,0 +1,168 @@
+/* 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/. */
+#include "secutil.h"
+
+/*
+ * NOTE: The contents of this file are NOT used by the client.
+ * (They are part of the security library as a whole, but they are
+ * NOT USED BY THE CLIENT.) Do not change things on behalf of the
+ * client (like localizing strings), or add things that are only
+ * for the client (put them elsewhere).
+ */
+
+#ifdef XP_UNIX
+#include <termios.h>
+#endif
+
+#if defined(XP_UNIX) || defined(XP_BEOS)
+#include <unistd.h> /* for isatty() */
+#endif
+
+#if defined(_WINDOWS)
+#include <conio.h>
+#include <io.h>
+#define QUIET_FGETS quiet_fgets
+static char *quiet_fgets(char *buf, int length, FILE *input);
+#else
+#define QUIET_FGETS fgets
+#endif
+
+static void
+echoOff(int fd)
+{
+#if defined(XP_UNIX)
+ if (isatty(fd)) {
+ struct termios tio;
+ tcgetattr(fd, &tio);
+ tio.c_lflag &= ~ECHO;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+ }
+#endif
+}
+
+static void
+echoOn(int fd)
+{
+#if defined(XP_UNIX)
+ if (isatty(fd)) {
+ struct termios tio;
+ tcgetattr(fd, &tio);
+ tio.c_lflag |= ECHO;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+ }
+#endif
+}
+
+char *
+SEC_GetPassword(FILE *input, FILE *output, char *prompt,
+ PRBool (*ok)(char *))
+{
+#if defined(_WINDOWS)
+ int isTTY = (input == stdin);
+#define echoOn(x)
+#define echoOff(x)
+#else
+ int infd = fileno(input);
+ int isTTY = isatty(infd);
+#endif
+ char phrase[200] = { '\0' }; /* ensure EOF doesn't return junk */
+
+ for (;;) {
+ /* Prompt for password */
+ if (isTTY) {
+ fprintf(output, "%s", prompt);
+ fflush(output);
+ echoOff(infd);
+ }
+
+ if (QUIET_FGETS(phrase, sizeof(phrase), input) == NULL) {
+ return NULL;
+ }
+
+ if (isTTY) {
+ fprintf(output, "\n");
+ echoOn(infd);
+ }
+
+ /* stomp on newline */
+ phrase[PORT_Strlen(phrase) - 1] = 0;
+
+ /* Validate password */
+ if (!(*ok)(phrase)) {
+ /* Not weird enough */
+ if (!isTTY)
+ return NULL;
+ fprintf(output, "Password must be at least 8 characters long with one or more\n");
+ fprintf(output, "non-alphabetic characters\n");
+ continue;
+ }
+ return (char *)PORT_Strdup(phrase);
+ }
+}
+
+PRBool
+SEC_CheckPassword(char *cp)
+{
+ int len;
+ char *end;
+
+ len = PORT_Strlen(cp);
+ if (len < 8) {
+ return PR_FALSE;
+ }
+ end = cp + len;
+ while (cp < end) {
+ unsigned char ch = *cp++;
+ if (!((ch >= 'A') && (ch <= 'Z')) &&
+ !((ch >= 'a') && (ch <= 'z'))) {
+ /* pass phrase has at least one non alphabetic in it */
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+PRBool
+SEC_BlindCheckPassword(char *cp)
+{
+ if (cp != NULL) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+/* Get a password from the input terminal, without echoing */
+
+#if defined(_WINDOWS)
+static char *
+quiet_fgets(char *buf, int length, FILE *input)
+{
+ int c;
+ char *end = buf;
+
+ /* fflush (input); */
+ memset(buf, 0, length);
+
+ if (!isatty(fileno(input))) {
+ return fgets(buf, length, input);
+ }
+
+ while (1) {
+ c = getch(); /* getch gets a character from the console */
+
+ if (c == '\b') {
+ if (end > buf)
+ end--;
+ }
+
+ else if (--length > 0)
+ *end++ = c;
+
+ if (!c || c == '\n' || c == '\r')
+ break;
+ }
+
+ return buf;
+}
+#endif
diff --git a/security/nss/cmd/lib/secutil.c b/security/nss/cmd/lib/secutil.c
new file mode 100644
index 000000000..f3c15d870
--- /dev/null
+++ b/security/nss/cmd/lib/secutil.c
@@ -0,0 +1,3877 @@
+/* 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/. */
+/*
+** secutil.c - various functions used by security stuff
+**
+*/
+
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+#include "prerror.h"
+#include "prprf.h"
+#include "plgetopt.h"
+#include "prenv.h"
+#include "prnetdb.h"
+
+#include "cryptohi.h"
+#include "secutil.h"
+#include "secpkcs7.h"
+#include "secpkcs5.h"
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#endif
+
+/* for SEC_TraverseNames */
+#include "cert.h"
+#include "certt.h"
+#include "certdb.h"
+
+/* #include "secmod.h" */
+#include "pk11func.h"
+#include "secoid.h"
+
+static char consoleName[] = {
+#ifdef XP_UNIX
+ "/dev/tty"
+#else
+#ifdef XP_OS2
+ "\\DEV\\CON"
+#else
+ "CON:"
+#endif
+#endif
+};
+
+#include "nssutil.h"
+#include "ssl.h"
+#include "sslproto.h"
+
+static PRBool utf8DisplayEnabled = PR_FALSE;
+
+void
+SECU_EnableUtf8Display(PRBool enable)
+{
+ utf8DisplayEnabled = enable;
+}
+
+PRBool
+SECU_GetUtf8DisplayEnabled(void)
+{
+ return utf8DisplayEnabled;
+}
+
+static void
+secu_ClearPassword(char *p)
+{
+ if (p) {
+ PORT_Memset(p, 0, PORT_Strlen(p));
+ PORT_Free(p);
+ }
+}
+
+char *
+SECU_GetPasswordString(void *arg, char *prompt)
+{
+#ifndef _WINDOWS
+ char *p = NULL;
+ FILE *input, *output;
+
+ /* open terminal */
+ input = fopen(consoleName, "r");
+ if (input == NULL) {
+ fprintf(stderr, "Error opening input terminal for read\n");
+ return NULL;
+ }
+
+ output = fopen(consoleName, "w");
+ if (output == NULL) {
+ fprintf(stderr, "Error opening output terminal for write\n");
+ fclose(input);
+ return NULL;
+ }
+
+ p = SEC_GetPassword(input, output, prompt, SEC_BlindCheckPassword);
+
+ fclose(input);
+ fclose(output);
+
+ return p;
+
+#else
+ /* Win32 version of above. opening the console may fail
+ on windows95, and certainly isn't necessary.. */
+
+ char *p = NULL;
+
+ p = SEC_GetPassword(stdin, stdout, prompt, SEC_BlindCheckPassword);
+ return p;
+
+#endif
+}
+
+/*
+ * p a s s w o r d _ h a r d c o d e
+ *
+ * A function to use the password passed in the -f(pwfile) argument
+ * of the command line.
+ * After use once, null it out otherwise PKCS11 calls us forever.?
+ *
+ */
+char *
+SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char *phrases, *phrase;
+ PRFileDesc *fd;
+ PRInt32 nb;
+ char *pwFile = arg;
+ int i;
+ const long maxPwdFileSize = 4096;
+ char *tokenName = NULL;
+ int tokenLen = 0;
+
+ if (!pwFile)
+ return 0;
+
+ if (retry) {
+ return 0; /* no good retrying - the files contents will be the same */
+ }
+
+ phrases = PORT_ZAlloc(maxPwdFileSize);
+
+ if (!phrases) {
+ return 0; /* out of memory */
+ }
+
+ fd = PR_Open(pwFile, PR_RDONLY, 0);
+ if (!fd) {
+ fprintf(stderr, "No password file \"%s\" exists.\n", pwFile);
+ PORT_Free(phrases);
+ return NULL;
+ }
+
+ nb = PR_Read(fd, phrases, maxPwdFileSize);
+
+ PR_Close(fd);
+
+ if (nb == 0) {
+ fprintf(stderr, "password file contains no data\n");
+ PORT_Free(phrases);
+ return NULL;
+ }
+
+ if (slot) {
+ tokenName = PK11_GetTokenName(slot);
+ if (tokenName) {
+ tokenLen = PORT_Strlen(tokenName);
+ }
+ }
+ i = 0;
+ do {
+ int startphrase = i;
+ int phraseLen;
+
+ /* handle the Windows EOL case */
+ while (phrases[i] != '\r' && phrases[i] != '\n' && i < nb)
+ i++;
+ /* terminate passphrase */
+ phrases[i++] = '\0';
+ /* clean up any EOL before the start of the next passphrase */
+ while ((i < nb) && (phrases[i] == '\r' || phrases[i] == '\n')) {
+ phrases[i++] = '\0';
+ }
+ /* now analyze the current passphrase */
+ phrase = &phrases[startphrase];
+ if (!tokenName)
+ break;
+ if (PORT_Strncmp(phrase, tokenName, tokenLen))
+ continue;
+ phraseLen = PORT_Strlen(phrase);
+ if (phraseLen < (tokenLen + 1))
+ continue;
+ if (phrase[tokenLen] != ':')
+ continue;
+ phrase = &phrase[tokenLen + 1];
+ break;
+
+ } while (i < nb);
+
+ phrase = PORT_Strdup((char *)phrase);
+ PORT_Free(phrases);
+ return phrase;
+}
+
+char *
+SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char prompt[255];
+ secuPWData *pwdata = (secuPWData *)arg;
+ secuPWData pwnull = { PW_NONE, 0 };
+ secuPWData pwxtrn = { PW_EXTERNAL, "external" };
+
+ if (pwdata == NULL)
+ pwdata = &pwnull;
+
+ if (PK11_ProtectedAuthenticationPath(slot)) {
+ pwdata = &pwxtrn;
+ }
+ if (retry && pwdata->source != PW_NONE) {
+ PR_fprintf(PR_STDERR, "Incorrect password/PIN entered.\n");
+ return NULL;
+ }
+
+ switch (pwdata->source) {
+ case PW_NONE:
+ sprintf(prompt, "Enter Password or Pin for \"%s\":",
+ PK11_GetTokenName(slot));
+ return SECU_GetPasswordString(NULL, prompt);
+ case PW_FROMFILE:
+ return SECU_FilePasswd(slot, retry, pwdata->data);
+ case PW_EXTERNAL:
+ sprintf(prompt,
+ "Press Enter, then enter PIN for \"%s\" on external device.\n",
+ PK11_GetTokenName(slot));
+ (void)SECU_GetPasswordString(NULL, prompt);
+ /* Fall Through */
+ case PW_PLAINTEXT:
+ return PL_strdup(pwdata->data);
+ default:
+ break;
+ }
+
+ PR_fprintf(PR_STDERR, "Password check failed: No password found.\n");
+ return NULL;
+}
+
+char *
+secu_InitSlotPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char *p0 = NULL;
+ char *p1 = NULL;
+ FILE *input, *output;
+ secuPWData *pwdata = arg;
+
+ if (pwdata->source == PW_FROMFILE) {
+ return SECU_FilePasswd(slot, retry, pwdata->data);
+ }
+ if (pwdata->source == PW_PLAINTEXT) {
+ return PL_strdup(pwdata->data);
+ }
+
+/* PW_NONE - get it from tty */
+/* open terminal */
+#ifdef _WINDOWS
+ input = stdin;
+#else
+ input = fopen(consoleName, "r");
+#endif
+ if (input == NULL) {
+ PR_fprintf(PR_STDERR, "Error opening input terminal for read\n");
+ return NULL;
+ }
+
+ /* we have no password, so initialize database with one */
+ PR_fprintf(PR_STDERR,
+ "Enter a password which will be used to encrypt your keys.\n"
+ "The password should be at least 8 characters long,\n"
+ "and should contain at least one non-alphabetic character.\n\n");
+
+ output = fopen(consoleName, "w");
+ if (output == NULL) {
+ PR_fprintf(PR_STDERR, "Error opening output terminal for write\n");
+#ifndef _WINDOWS
+ fclose(input);
+#endif
+ return NULL;
+ }
+
+ for (;;) {
+ if (p0)
+ PORT_Free(p0);
+ p0 = SEC_GetPassword(input, output, "Enter new password: ",
+ SEC_BlindCheckPassword);
+
+ if (p1)
+ PORT_Free(p1);
+ p1 = SEC_GetPassword(input, output, "Re-enter password: ",
+ SEC_BlindCheckPassword);
+ if (p0 && p1 && !PORT_Strcmp(p0, p1)) {
+ break;
+ }
+ PR_fprintf(PR_STDERR, "Passwords do not match. Try again.\n");
+ }
+
+ /* clear out the duplicate password string */
+ secu_ClearPassword(p1);
+
+ fclose(input);
+ fclose(output);
+
+ return p0;
+}
+
+SECStatus
+SECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile)
+{
+ return SECU_ChangePW2(slot, passwd, 0, pwFile, 0);
+}
+
+SECStatus
+SECU_ChangePW2(PK11SlotInfo *slot, char *oldPass, char *newPass,
+ char *oldPwFile, char *newPwFile)
+{
+ SECStatus rv;
+ secuPWData pwdata, newpwdata;
+ char *oldpw = NULL, *newpw = NULL;
+
+ if (oldPass) {
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = oldPass;
+ } else if (oldPwFile) {
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = oldPwFile;
+ } else {
+ pwdata.source = PW_NONE;
+ pwdata.data = NULL;
+ }
+
+ if (newPass) {
+ newpwdata.source = PW_PLAINTEXT;
+ newpwdata.data = newPass;
+ } else if (newPwFile) {
+ newpwdata.source = PW_FROMFILE;
+ newpwdata.data = newPwFile;
+ } else {
+ newpwdata.source = PW_NONE;
+ newpwdata.data = NULL;
+ }
+
+ if (PK11_NeedUserInit(slot)) {
+ newpw = secu_InitSlotPassword(slot, PR_FALSE, &pwdata);
+ rv = PK11_InitPin(slot, (char *)NULL, newpw);
+ goto done;
+ }
+
+ for (;;) {
+ oldpw = SECU_GetModulePassword(slot, PR_FALSE, &pwdata);
+
+ if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
+ if (pwdata.source == PW_NONE) {
+ PR_fprintf(PR_STDERR, "Invalid password. Try again.\n");
+ } else {
+ PR_fprintf(PR_STDERR, "Invalid password.\n");
+ PORT_Memset(oldpw, 0, PL_strlen(oldpw));
+ PORT_Free(oldpw);
+ rv = SECFailure;
+ goto done;
+ }
+ } else
+ break;
+
+ PORT_Free(oldpw);
+ }
+
+ newpw = secu_InitSlotPassword(slot, PR_FALSE, &newpwdata);
+
+ rv = PK11_ChangePW(slot, oldpw, newpw);
+ if (rv != SECSuccess) {
+ PR_fprintf(PR_STDERR, "Failed to change password.\n");
+ } else {
+ PR_fprintf(PR_STDOUT, "Password changed successfully.\n");
+ }
+
+ PORT_Memset(oldpw, 0, PL_strlen(oldpw));
+ PORT_Free(oldpw);
+
+done:
+ if (newpw) {
+ PORT_Memset(newpw, 0, PL_strlen(newpw));
+ PORT_Free(newpw);
+ }
+ return rv;
+}
+
+struct matchobj {
+ SECItem index;
+ char *nname;
+ PRBool found;
+};
+
+char *
+SECU_DefaultSSLDir(void)
+{
+ char *dir;
+ static char sslDir[1000];
+
+ dir = PR_GetEnvSecure("SSL_DIR");
+ if (!dir)
+ return NULL;
+
+ if (strlen(dir) >= PR_ARRAY_SIZE(sslDir)) {
+ return NULL;
+ }
+ sprintf(sslDir, "%s", dir);
+
+ if (sslDir[strlen(sslDir) - 1] == '/')
+ sslDir[strlen(sslDir) - 1] = 0;
+
+ return sslDir;
+}
+
+char *
+SECU_AppendFilenameToDir(char *dir, char *filename)
+{
+ static char path[1000];
+
+ if (dir[strlen(dir) - 1] == '/')
+ sprintf(path, "%s%s", dir, filename);
+ else
+ sprintf(path, "%s/%s", dir, filename);
+ return path;
+}
+
+char *
+SECU_ConfigDirectory(const char *base)
+{
+ static PRBool initted = PR_FALSE;
+ const char *dir = ".netscape";
+ char *home;
+ static char buf[1000];
+
+ if (initted)
+ return buf;
+
+ if (base == NULL || *base == 0) {
+ home = PR_GetEnvSecure("HOME");
+ if (!home)
+ home = "";
+
+ if (*home && home[strlen(home) - 1] == '/')
+ sprintf(buf, "%.900s%s", home, dir);
+ else
+ sprintf(buf, "%.900s/%s", home, dir);
+ } else {
+ sprintf(buf, "%.900s", base);
+ if (buf[strlen(buf) - 1] == '/')
+ buf[strlen(buf) - 1] = 0;
+ }
+
+ initted = PR_TRUE;
+ return buf;
+}
+
+/*Turn off SSL for now */
+/* This gets called by SSL when server wants our cert & key */
+int
+SECU_GetClientAuthData(void *arg, PRFileDesc *fd,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+ SECKEYPrivateKey *key;
+ CERTCertificate *cert;
+ int errsave;
+
+ if (arg == NULL) {
+ fprintf(stderr, "no key/cert name specified for client auth\n");
+ return -1;
+ }
+ cert = PK11_FindCertFromNickname(arg, NULL);
+ errsave = PORT_GetError();
+ if (!cert) {
+ if (errsave == SEC_ERROR_BAD_PASSWORD)
+ fprintf(stderr, "Bad password\n");
+ else if (errsave > 0)
+ fprintf(stderr, "Unable to read cert (error %d)\n", errsave);
+ else if (errsave == SEC_ERROR_BAD_DATABASE)
+ fprintf(stderr, "Unable to get cert from database (%d)\n", errsave);
+ else
+ fprintf(stderr, "SECKEY_FindKeyByName: internal error %d\n", errsave);
+ return -1;
+ }
+
+ key = PK11_FindKeyByAnyCert(arg, NULL);
+ if (!key) {
+ fprintf(stderr, "Unable to get key (%d)\n", PORT_GetError());
+ return -1;
+ }
+
+ *pRetCert = cert;
+ *pRetKey = key;
+
+ return 0;
+}
+
+SECStatus
+SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii,
+ PRBool warnOnPrivateKeyInAsciiFile)
+{
+ SECStatus rv;
+ if (ascii) {
+ /* First convert ascii to binary */
+ SECItem filedata;
+ char *asc, *body;
+
+ /* Read in ascii data */
+ rv = SECU_FileToItem(&filedata, inFile);
+ if (rv != SECSuccess)
+ return rv;
+ asc = (char *)filedata.data;
+ if (!asc) {
+ fprintf(stderr, "unable to read data from input file\n");
+ return SECFailure;
+ }
+
+ if (warnOnPrivateKeyInAsciiFile && strstr(asc, "PRIVATE KEY")) {
+ fprintf(stderr, "Warning: ignoring private key. Consider to use "
+ "pk12util.\n");
+ }
+
+ /* check for headers and trailers and remove them */
+ if ((body = strstr(asc, "-----BEGIN")) != NULL) {
+ char *trailer = NULL;
+ asc = body;
+ body = PORT_Strchr(body, '\n');
+ if (!body)
+ body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */
+ if (body)
+ trailer = strstr(++body, "-----END");
+ if (trailer != NULL) {
+ *trailer = '\0';
+ } else {
+ fprintf(stderr, "input has header but no trailer\n");
+ PORT_Free(filedata.data);
+ return SECFailure;
+ }
+ } else {
+ /* need one additional byte for zero terminator */
+ rv = SECITEM_ReallocItemV2(NULL, &filedata, filedata.len + 1);
+ if (rv != SECSuccess) {
+ PORT_Free(filedata.data);
+ return rv;
+ }
+ body = (char *)filedata.data;
+ body[filedata.len - 1] = '\0';
+ }
+
+ /* Convert to binary */
+ rv = ATOB_ConvertAsciiToItem(der, body);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "error converting ascii to binary (%s)\n",
+ SECU_Strerror(PORT_GetError()));
+ PORT_Free(filedata.data);
+ return SECFailure;
+ }
+
+ PORT_Free(filedata.data);
+ } else {
+ /* Read in binary der */
+ rv = SECU_FileToItem(der, inFile);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "error converting der (%s)\n",
+ SECU_Strerror(PORT_GetError()));
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+}
+
+#define INDENT_MULT 4
+
+SECStatus
+SECU_StripTagAndLength(SECItem *i)
+{
+ unsigned int start;
+
+ if (!i || !i->data || i->len < 2) { /* must be at least tag and length */
+ return SECFailure;
+ }
+ start = ((i->data[1] & 0x80) ? (i->data[1] & 0x7f) + 2 : 2);
+ if (i->len < start) {
+ return SECFailure;
+ }
+ i->data += start;
+ i->len -= start;
+ return SECSuccess;
+}
+
+static void
+secu_PrintRawStringQuotesOptional(FILE *out, SECItem *si, const char *m,
+ int level, PRBool quotes)
+{
+ int column;
+ unsigned int i;
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s: ", m);
+ column = (level * INDENT_MULT) + strlen(m) + 2;
+ level++;
+ } else {
+ SECU_Indent(out, level);
+ column = level * INDENT_MULT;
+ }
+ if (quotes) {
+ fprintf(out, "\"");
+ column++;
+ }
+
+ for (i = 0; i < si->len; i++) {
+ unsigned char val = si->data[i];
+ unsigned char c;
+ if (SECU_GetWrapEnabled() && column > 76) {
+ SECU_Newline(out);
+ SECU_Indent(out, level);
+ column = level * INDENT_MULT;
+ }
+
+ if (utf8DisplayEnabled) {
+ if (val < 32)
+ c = '.';
+ else
+ c = val;
+ } else {
+ c = printable[val];
+ }
+ fprintf(out, "%c", c);
+ column++;
+ }
+
+ if (quotes) {
+ fprintf(out, "\"");
+ column++;
+ }
+ if (SECU_GetWrapEnabled() &&
+ (column != level * INDENT_MULT || column > 76)) {
+ SECU_Newline(out);
+ }
+}
+
+static void
+secu_PrintRawString(FILE *out, SECItem *si, const char *m, int level)
+{
+ secu_PrintRawStringQuotesOptional(out, si, m, level, PR_TRUE);
+}
+
+void
+SECU_PrintString(FILE *out, const SECItem *si, const char *m, int level)
+{
+ SECItem my = *si;
+
+ if (SECSuccess != SECU_StripTagAndLength(&my) || !my.len)
+ return;
+ secu_PrintRawString(out, &my, m, level);
+}
+
+/* print an unencoded boolean */
+static void
+secu_PrintBoolean(FILE *out, SECItem *i, const char *m, int level)
+{
+ int val = 0;
+
+ if (i->data && i->len) {
+ val = i->data[0];
+ }
+
+ if (!m) {
+ m = "Boolean";
+ }
+ SECU_Indent(out, level);
+ fprintf(out, "%s: %s\n", m, (val ? "True" : "False"));
+}
+
+/*
+ * Format and print "time". If the tag message "m" is not NULL,
+ * do indent formatting based on "level" and add a newline afterward;
+ * otherwise just print the formatted time string only.
+ */
+static void
+secu_PrintTime(FILE *out, const PRTime time, const char *m, int level)
+{
+ PRExplodedTime printableTime;
+ char *timeString;
+
+ /* Convert to local time */
+ PR_ExplodeTime(time, PR_GMTParameters, &printableTime);
+
+ timeString = PORT_Alloc(256);
+ if (timeString == NULL)
+ return;
+
+ if (m != NULL) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s: ", m);
+ }
+
+ if (PR_FormatTime(timeString, 256, "%a %b %d %H:%M:%S %Y", &printableTime)) {
+ fputs(timeString, out);
+ }
+
+ if (m != NULL)
+ fprintf(out, "\n");
+
+ PORT_Free(timeString);
+}
+
+/*
+ * Format and print the UTC Time "t". If the tag message "m" is not NULL,
+ * do indent formatting based on "level" and add a newline afterward;
+ * otherwise just print the formatted time string only.
+ */
+void
+SECU_PrintUTCTime(FILE *out, const SECItem *t, const char *m, int level)
+{
+ PRTime time;
+ SECStatus rv;
+
+ rv = DER_UTCTimeToTime(&time, t);
+ if (rv != SECSuccess)
+ return;
+
+ secu_PrintTime(out, time, m, level);
+}
+
+/*
+ * Format and print the Generalized Time "t". If the tag message "m"
+ * is not NULL, * do indent formatting based on "level" and add a newline
+ * afterward; otherwise just print the formatted time string only.
+ */
+void
+SECU_PrintGeneralizedTime(FILE *out, const SECItem *t, const char *m, int level)
+{
+ PRTime time;
+ SECStatus rv;
+
+ rv = DER_GeneralizedTimeToTime(&time, t);
+ if (rv != SECSuccess)
+ return;
+
+ secu_PrintTime(out, time, m, level);
+}
+
+/*
+ * Format and print the UTC or Generalized Time "t". If the tag message
+ * "m" is not NULL, do indent formatting based on "level" and add a newline
+ * afterward; otherwise just print the formatted time string only.
+ */
+void
+SECU_PrintTimeChoice(FILE *out, const SECItem *t, const char *m, int level)
+{
+ switch (t->type) {
+ case siUTCTime:
+ SECU_PrintUTCTime(out, t, m, level);
+ break;
+
+ case siGeneralizedTime:
+ SECU_PrintGeneralizedTime(out, t, m, level);
+ break;
+
+ default:
+ PORT_Assert(0);
+ break;
+ }
+}
+
+/* This prints a SET or SEQUENCE */
+static void
+SECU_PrintSet(FILE *out, const SECItem *t, const char *m, int level)
+{
+ int type = t->data[0] & SEC_ASN1_TAGNUM_MASK;
+ int constructed = t->data[0] & SEC_ASN1_CONSTRUCTED;
+ const char *label;
+ SECItem my = *t;
+
+ if (!constructed) {
+ SECU_PrintAsHex(out, t, m, level);
+ return;
+ }
+ if (SECSuccess != SECU_StripTagAndLength(&my))
+ return;
+
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: ", m);
+ }
+
+ if (type == SEC_ASN1_SET)
+ label = "Set ";
+ else if (type == SEC_ASN1_SEQUENCE)
+ label = "Sequence ";
+ else
+ label = "";
+ fprintf(out, "%s{\n", label); /* } */
+
+ while (my.len >= 2) {
+ SECItem tmp = my;
+
+ if (tmp.data[1] & 0x80) {
+ unsigned int i;
+ unsigned int lenlen = tmp.data[1] & 0x7f;
+ if (lenlen > sizeof tmp.len)
+ break;
+ tmp.len = 0;
+ for (i = 0; i < lenlen; i++) {
+ tmp.len = (tmp.len << 8) | tmp.data[2 + i];
+ }
+ tmp.len += lenlen + 2;
+ } else {
+ tmp.len = tmp.data[1] + 2;
+ }
+ if (tmp.len > my.len) {
+ tmp.len = my.len;
+ }
+ my.data += tmp.len;
+ my.len -= tmp.len;
+ SECU_PrintAny(out, &tmp, NULL, level + 1);
+ }
+ SECU_Indent(out, level);
+ fprintf(out, /* { */ "}\n");
+}
+
+static void
+secu_PrintContextSpecific(FILE *out, const SECItem *i, const char *m, int level)
+{
+ int type = i->data[0] & SEC_ASN1_TAGNUM_MASK;
+ int constructed = i->data[0] & SEC_ASN1_CONSTRUCTED;
+ SECItem tmp;
+
+ if (constructed) {
+ char *m2;
+ if (!m)
+ m2 = PR_smprintf("[%d]", type);
+ else
+ m2 = PR_smprintf("%s: [%d]", m, type);
+ if (m2) {
+ SECU_PrintSet(out, i, m2, level);
+ PR_smprintf_free(m2);
+ }
+ return;
+ }
+
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: ", m);
+ }
+ fprintf(out, "[%d]\n", type);
+
+ tmp = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&tmp))
+ SECU_PrintAsHex(out, &tmp, m, level + 1);
+}
+
+static void
+secu_PrintOctetString(FILE *out, const SECItem *i, const char *m, int level)
+{
+ SECItem tmp = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&tmp))
+ SECU_PrintAsHex(out, &tmp, m, level);
+}
+
+static void
+secu_PrintBitString(FILE *out, const SECItem *i, const char *m, int level)
+{
+ int unused_bits;
+ SECItem tmp = *i;
+
+ if (SECSuccess != SECU_StripTagAndLength(&tmp) || tmp.len < 2)
+ return;
+
+ unused_bits = *tmp.data++;
+ tmp.len--;
+
+ SECU_PrintAsHex(out, &tmp, m, level);
+ if (unused_bits) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "(%d least significant bits unused)\n", unused_bits);
+ }
+}
+
+/* in a decoded bit string, the len member is a bit length. */
+static void
+secu_PrintDecodedBitString(FILE *out, const SECItem *i, const char *m, int level)
+{
+ int unused_bits;
+ SECItem tmp = *i;
+
+ unused_bits = (tmp.len & 0x7) ? 8 - (tmp.len & 7) : 0;
+ DER_ConvertBitString(&tmp); /* convert length to byte length */
+
+ SECU_PrintAsHex(out, &tmp, m, level);
+ if (unused_bits) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "(%d least significant bits unused)\n", unused_bits);
+ }
+}
+
+/* Print a DER encoded Boolean */
+void
+SECU_PrintEncodedBoolean(FILE *out, const SECItem *i, const char *m, int level)
+{
+ SECItem my = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&my))
+ secu_PrintBoolean(out, &my, m, level);
+}
+
+/* Print a DER encoded integer */
+void
+SECU_PrintEncodedInteger(FILE *out, const SECItem *i, const char *m, int level)
+{
+ SECItem my = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&my))
+ SECU_PrintInteger(out, &my, m, level);
+}
+
+/* Print a DER encoded OID */
+void
+SECU_PrintEncodedObjectID(FILE *out, const SECItem *i, const char *m, int level)
+{
+ SECItem my = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&my))
+ SECU_PrintObjectID(out, &my, m, level);
+}
+
+static void
+secu_PrintBMPString(FILE *out, const SECItem *i, const char *m, int level)
+{
+ unsigned char *s;
+ unsigned char *d;
+ int len;
+ SECItem tmp = { 0, 0, 0 };
+ SECItem my = *i;
+
+ if (SECSuccess != SECU_StripTagAndLength(&my))
+ goto loser;
+ if (my.len % 2)
+ goto loser;
+ len = (int)(my.len / 2);
+ tmp.data = (unsigned char *)PORT_Alloc(len);
+ if (!tmp.data)
+ goto loser;
+ tmp.len = len;
+ for (s = my.data, d = tmp.data; len > 0; len--) {
+ PRUint32 bmpChar = (s[0] << 8) | s[1];
+ s += 2;
+ if (!isprint(bmpChar))
+ goto loser;
+ *d++ = (unsigned char)bmpChar;
+ }
+ secu_PrintRawString(out, &tmp, m, level);
+ PORT_Free(tmp.data);
+ return;
+
+loser:
+ SECU_PrintAsHex(out, i, m, level);
+ if (tmp.data)
+ PORT_Free(tmp.data);
+}
+
+static void
+secu_PrintUniversalString(FILE *out, const SECItem *i, const char *m, int level)
+{
+ unsigned char *s;
+ unsigned char *d;
+ int len;
+ SECItem tmp = { 0, 0, 0 };
+ SECItem my = *i;
+
+ if (SECSuccess != SECU_StripTagAndLength(&my))
+ goto loser;
+ if (my.len % 4)
+ goto loser;
+ len = (int)(my.len / 4);
+ tmp.data = (unsigned char *)PORT_Alloc(len);
+ if (!tmp.data)
+ goto loser;
+ tmp.len = len;
+ for (s = my.data, d = tmp.data; len > 0; len--) {
+ PRUint32 bmpChar = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
+ s += 4;
+ if (!isprint(bmpChar))
+ goto loser;
+ *d++ = (unsigned char)bmpChar;
+ }
+ secu_PrintRawString(out, &tmp, m, level);
+ PORT_Free(tmp.data);
+ return;
+
+loser:
+ SECU_PrintAsHex(out, i, m, level);
+ if (tmp.data)
+ PORT_Free(tmp.data);
+}
+
+static void
+secu_PrintUniversal(FILE *out, const SECItem *i, const char *m, int level)
+{
+ switch (i->data[0] & SEC_ASN1_TAGNUM_MASK) {
+ case SEC_ASN1_ENUMERATED:
+ case SEC_ASN1_INTEGER:
+ SECU_PrintEncodedInteger(out, i, m, level);
+ break;
+ case SEC_ASN1_OBJECT_ID:
+ SECU_PrintEncodedObjectID(out, i, m, level);
+ break;
+ case SEC_ASN1_BOOLEAN:
+ SECU_PrintEncodedBoolean(out, i, m, level);
+ break;
+ case SEC_ASN1_UTF8_STRING:
+ case SEC_ASN1_PRINTABLE_STRING:
+ case SEC_ASN1_VISIBLE_STRING:
+ case SEC_ASN1_IA5_STRING:
+ case SEC_ASN1_T61_STRING:
+ SECU_PrintString(out, i, m, level);
+ break;
+ case SEC_ASN1_GENERALIZED_TIME:
+ SECU_PrintGeneralizedTime(out, i, m, level);
+ break;
+ case SEC_ASN1_UTC_TIME:
+ SECU_PrintUTCTime(out, i, m, level);
+ break;
+ case SEC_ASN1_NULL:
+ SECU_Indent(out, level);
+ if (m && m[0])
+ fprintf(out, "%s: NULL\n", m);
+ else
+ fprintf(out, "NULL\n");
+ break;
+ case SEC_ASN1_SET:
+ case SEC_ASN1_SEQUENCE:
+ SECU_PrintSet(out, i, m, level);
+ break;
+ case SEC_ASN1_OCTET_STRING:
+ secu_PrintOctetString(out, i, m, level);
+ break;
+ case SEC_ASN1_BIT_STRING:
+ secu_PrintBitString(out, i, m, level);
+ break;
+ case SEC_ASN1_BMP_STRING:
+ secu_PrintBMPString(out, i, m, level);
+ break;
+ case SEC_ASN1_UNIVERSAL_STRING:
+ secu_PrintUniversalString(out, i, m, level);
+ break;
+ default:
+ SECU_PrintAsHex(out, i, m, level);
+ break;
+ }
+}
+
+void
+SECU_PrintAny(FILE *out, const SECItem *i, const char *m, int level)
+{
+ if (i && i->len && i->data) {
+ switch (i->data[0] & SEC_ASN1_CLASS_MASK) {
+ case SEC_ASN1_CONTEXT_SPECIFIC:
+ secu_PrintContextSpecific(out, i, m, level);
+ break;
+ case SEC_ASN1_UNIVERSAL:
+ secu_PrintUniversal(out, i, m, level);
+ break;
+ default:
+ SECU_PrintAsHex(out, i, m, level);
+ break;
+ }
+ }
+}
+
+static int
+secu_PrintValidity(FILE *out, CERTValidity *v, char *m, int level)
+{
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintTimeChoice(out, &v->notBefore, "Not Before", level + 1);
+ SECU_PrintTimeChoice(out, &v->notAfter, "Not After ", level + 1);
+ return 0;
+}
+
+/* This function does NOT expect a DER type and length. */
+SECOidTag
+SECU_PrintObjectID(FILE *out, const SECItem *oid, const char *m, int level)
+{
+ SECOidData *oiddata;
+ char *oidString = NULL;
+
+ oiddata = SECOID_FindOID(oid);
+ if (oiddata != NULL) {
+ const char *name = oiddata->desc;
+ SECU_Indent(out, level);
+ if (m != NULL)
+ fprintf(out, "%s: ", m);
+ fprintf(out, "%s\n", name);
+ return oiddata->offset;
+ }
+ oidString = CERT_GetOidString(oid);
+ if (oidString) {
+ SECU_Indent(out, level);
+ if (m != NULL)
+ fprintf(out, "%s: ", m);
+ fprintf(out, "%s\n", oidString);
+ PR_smprintf_free(oidString);
+ return SEC_OID_UNKNOWN;
+ }
+ SECU_PrintAsHex(out, oid, m, level);
+ return SEC_OID_UNKNOWN;
+}
+
+typedef struct secuPBEParamsStr {
+ SECItem salt;
+ SECItem iterationCount;
+ SECItem keyLength;
+ SECAlgorithmID cipherAlg;
+ SECAlgorithmID kdfAlg;
+} secuPBEParams;
+
+SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
+
+/* SECOID_PKCS5_PBKDF2 */
+const SEC_ASN1Template secuKDF2Params[] =
+ {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
+ { SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
+ { SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
+ { SEC_ASN1_INTEGER, offsetof(secuPBEParams, keyLength) },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { 0 }
+ };
+
+/* PKCS5v1 & PKCS12 */
+const SEC_ASN1Template secuPBEParamsTemp[] =
+ {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
+ { SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
+ { SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
+ { 0 }
+ };
+
+/* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */
+const SEC_ASN1Template secuPBEV2Params[] =
+ {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, cipherAlg),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { 0 }
+ };
+
+void
+secu_PrintRSAPSSParams(FILE *out, SECItem *value, char *m, int level)
+{
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SECStatus rv;
+ SECKEYRSAPSSParams param;
+ SECAlgorithmID maskHashAlg;
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ }
+
+ if (!pool) {
+ SECU_Indent(out, level);
+ fprintf(out, "Out of memory\n");
+ return;
+ }
+
+ PORT_Memset(&param, 0, sizeof param);
+
+ rv = SEC_QuickDERDecodeItem(pool, &param,
+ SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate),
+ value);
+ if (rv == SECSuccess) {
+ if (!param.hashAlg) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Hash algorithm: default, SHA-1\n");
+ } else {
+ SECU_PrintObjectID(out, &param.hashAlg->algorithm,
+ "Hash algorithm", level + 1);
+ }
+ if (!param.maskAlg) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Mask algorithm: default, MGF1\n");
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Mask hash algorithm: default, SHA-1\n");
+ } else {
+ SECU_PrintObjectID(out, &param.maskAlg->algorithm,
+ "Mask algorithm", level + 1);
+ rv = SEC_QuickDERDecodeItem(pool, &maskHashAlg,
+ SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
+ &param.maskAlg->parameters);
+ if (rv == SECSuccess) {
+ SECU_PrintObjectID(out, &maskHashAlg.algorithm,
+ "Mask hash algorithm", level + 1);
+ } else {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Invalid mask generation algorithm parameters\n");
+ }
+ }
+ if (!param.saltLength.data) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Salt length: default, %i (0x%2X)\n", 20, 20);
+ } else {
+ SECU_PrintInteger(out, &param.saltLength, "Salt Length", level + 1);
+ }
+ } else {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Invalid RSA-PSS parameters\n");
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+void
+secu_PrintKDF2Params(FILE *out, SECItem *value, char *m, int level)
+{
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SECStatus rv;
+ secuPBEParams param;
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ }
+
+ if (!pool) {
+ SECU_Indent(out, level);
+ fprintf(out, "Out of memory\n");
+ return;
+ }
+
+ PORT_Memset(&param, 0, sizeof param);
+ rv = SEC_QuickDERDecodeItem(pool, &param, secuKDF2Params, value);
+ if (rv == SECSuccess) {
+ SECU_PrintAsHex(out, &param.salt, "Salt", level + 1);
+ SECU_PrintInteger(out, &param.iterationCount, "Iteration Count",
+ level + 1);
+ SECU_PrintInteger(out, &param.keyLength, "Key Length", level + 1);
+ SECU_PrintAlgorithmID(out, &param.kdfAlg, "KDF algorithm", level + 1);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+void
+secu_PrintPKCS5V2Params(FILE *out, SECItem *value, char *m, int level)
+{
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SECStatus rv;
+ secuPBEParams param;
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ }
+
+ if (!pool) {
+ SECU_Indent(out, level);
+ fprintf(out, "Out of memory\n");
+ return;
+ }
+
+ PORT_Memset(&param, 0, sizeof param);
+ rv = SEC_QuickDERDecodeItem(pool, &param, secuPBEV2Params, value);
+ if (rv == SECSuccess) {
+ SECU_PrintAlgorithmID(out, &param.kdfAlg, "KDF", level + 1);
+ SECU_PrintAlgorithmID(out, &param.cipherAlg, "Cipher", level + 1);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+void
+secu_PrintPBEParams(FILE *out, SECItem *value, char *m, int level)
+{
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SECStatus rv;
+ secuPBEParams param;
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ }
+
+ if (!pool) {
+ SECU_Indent(out, level);
+ fprintf(out, "Out of memory\n");
+ return;
+ }
+
+ PORT_Memset(&param, 0, sizeof(secuPBEParams));
+ rv = SEC_QuickDERDecodeItem(pool, &param, secuPBEParamsTemp, value);
+ if (rv == SECSuccess) {
+ SECU_PrintAsHex(out, &param.salt, "Salt", level + 1);
+ SECU_PrintInteger(out, &param.iterationCount, "Iteration Count",
+ level + 1);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+/* This function does NOT expect a DER type and length. */
+void
+SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m, int level)
+{
+ SECOidTag algtag;
+ SECU_PrintObjectID(out, &a->algorithm, m, level);
+
+ algtag = SECOID_GetAlgorithmTag(a);
+ if (SEC_PKCS5IsAlgorithmPBEAlgTag(algtag)) {
+ switch (algtag) {
+ case SEC_OID_PKCS5_PBKDF2:
+ secu_PrintKDF2Params(out, &a->parameters, "Parameters", level + 1);
+ break;
+ case SEC_OID_PKCS5_PBES2:
+ secu_PrintPKCS5V2Params(out, &a->parameters, "Encryption", level + 1);
+ break;
+ case SEC_OID_PKCS5_PBMAC1:
+ secu_PrintPKCS5V2Params(out, &a->parameters, "MAC", level + 1);
+ break;
+ default:
+ secu_PrintPBEParams(out, &a->parameters, "Parameters", level + 1);
+ break;
+ }
+ return;
+ }
+
+ if (algtag == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
+ secu_PrintRSAPSSParams(out, &a->parameters, "Parameters", level + 1);
+ return;
+ }
+
+ if (a->parameters.len == 0 ||
+ (a->parameters.len == 2 &&
+ PORT_Memcmp(a->parameters.data, "\005\000", 2) == 0)) {
+ /* No arguments or NULL argument */
+ } else {
+ /* Print args to algorithm */
+ SECU_PrintAsHex(out, &a->parameters, "Args", level + 1);
+ }
+}
+
+static void
+secu_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m, int level)
+{
+ SECItem *value;
+ int i;
+ char om[100];
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ }
+
+ /*
+ * Should make this smarter; look at the type field and then decode
+ * and print the value(s) appropriately!
+ */
+ SECU_PrintObjectID(out, &(attr->type), "Type", level + 1);
+ if (attr->values != NULL) {
+ i = 0;
+ while ((value = attr->values[i++]) != NULL) {
+ sprintf(om, "Value (%d)%s", i, attr->encoded ? " (encoded)" : "");
+ if (attr->encoded || attr->typeTag == NULL) {
+ SECU_PrintAny(out, value, om, level + 1);
+ } else {
+ switch (attr->typeTag->offset) {
+ default:
+ SECU_PrintAsHex(out, value, om, level + 1);
+ break;
+ case SEC_OID_PKCS9_CONTENT_TYPE:
+ SECU_PrintObjectID(out, value, om, level + 1);
+ break;
+ case SEC_OID_PKCS9_SIGNING_TIME:
+ SECU_PrintTimeChoice(out, value, om, level + 1);
+ break;
+ }
+ }
+ }
+ }
+}
+
+#ifndef NSS_DISABLE_ECC
+static void
+secu_PrintECPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
+{
+ SECItem curveOID = { siBuffer, NULL, 0 };
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &pk->u.ec.publicValue, "PublicValue", level + 1);
+ /* For named curves, the DEREncodedParams field contains an
+ * ASN Object ID (0x06 is SEC_ASN1_OBJECT_ID).
+ */
+ if ((pk->u.ec.DEREncodedParams.len > 2) &&
+ (pk->u.ec.DEREncodedParams.data[0] == 0x06)) {
+ curveOID.len = pk->u.ec.DEREncodedParams.data[1];
+ curveOID.data = pk->u.ec.DEREncodedParams.data + 2;
+ SECU_PrintObjectID(out, &curveOID, "Curve", level + 1);
+ }
+}
+#endif /* NSS_DISABLE_ECC */
+
+void
+SECU_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
+{
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &pk->u.rsa.modulus, "Modulus", level + 1);
+ SECU_PrintInteger(out, &pk->u.rsa.publicExponent, "Exponent", level + 1);
+ if (pk->u.rsa.publicExponent.len == 1 &&
+ pk->u.rsa.publicExponent.data[0] == 1) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Error: INVALID RSA KEY!\n");
+ }
+}
+
+void
+SECU_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
+{
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &pk->u.dsa.params.prime, "Prime", level + 1);
+ SECU_PrintInteger(out, &pk->u.dsa.params.subPrime, "Subprime", level + 1);
+ SECU_PrintInteger(out, &pk->u.dsa.params.base, "Base", level + 1);
+ SECU_PrintInteger(out, &pk->u.dsa.publicValue, "PublicValue", level + 1);
+}
+
+static void
+secu_PrintSubjectPublicKeyInfo(FILE *out, PLArenaPool *arena,
+ CERTSubjectPublicKeyInfo *i, char *msg, int level)
+{
+ SECKEYPublicKey *pk;
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", msg);
+ SECU_PrintAlgorithmID(out, &i->algorithm, "Public Key Algorithm", level + 1);
+
+ pk = SECKEY_ExtractPublicKey(i);
+ if (pk) {
+ switch (pk->keyType) {
+ case rsaKey:
+ SECU_PrintRSAPublicKey(out, pk, "RSA Public Key", level + 1);
+ break;
+
+ case dsaKey:
+ SECU_PrintDSAPublicKey(out, pk, "DSA Public Key", level + 1);
+ break;
+
+#ifndef NSS_DISABLE_ECC
+ case ecKey:
+ secu_PrintECPublicKey(out, pk, "EC Public Key", level + 1);
+ break;
+#endif
+
+ case dhKey:
+ case fortezzaKey:
+ case keaKey:
+ SECU_Indent(out, level);
+ fprintf(out, "unable to format this SPKI algorithm type\n");
+ goto loser;
+ default:
+ SECU_Indent(out, level);
+ fprintf(out, "unknown SPKI algorithm type\n");
+ goto loser;
+ }
+ PORT_FreeArena(pk->arena, PR_FALSE);
+ } else {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing public key");
+ loser:
+ if (i->subjectPublicKey.data) {
+ SECU_PrintAny(out, &i->subjectPublicKey, "Raw", level);
+ }
+ }
+}
+
+static void
+printStringWithoutCRLF(FILE *out, const char *str)
+{
+ const char *c = str;
+ while (*c) {
+ if (*c != '\r' && *c != '\n') {
+ fputc(*c, out);
+ }
+ ++c;
+ }
+}
+
+int
+SECU_PrintDumpDerIssuerAndSerial(FILE *out, SECItem *der, char *m,
+ int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCertificate *c;
+ int rv = SEC_ERROR_NO_MEMORY;
+ char *derIssuerB64;
+ char *derSerialB64;
+
+ if (!arena)
+ return rv;
+
+ /* Decode certificate */
+ c = PORT_ArenaZNew(arena, CERTCertificate);
+ if (!c)
+ goto loser;
+ c->arena = arena;
+ rv = SEC_ASN1DecodeItem(arena, c,
+ SEC_ASN1_GET(CERT_CertificateTemplate), der);
+ if (rv) {
+ SECU_PrintErrMsg(out, 0, "Error", "Parsing extension");
+ goto loser;
+ }
+
+ SECU_PrintName(out, &c->subject, "Subject", 0);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+ SECU_PrintName(out, &c->issuer, "Issuer", 0);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+ SECU_PrintInteger(out, &c->serialNumber, "Serial Number", 0);
+
+ derIssuerB64 = BTOA_ConvertItemToAscii(&c->derIssuer);
+ derSerialB64 = BTOA_ConvertItemToAscii(&c->serialNumber);
+
+ fprintf(out, "Issuer DER Base64:\n");
+ if (SECU_GetWrapEnabled()) {
+ fprintf(out, "%s\n", derIssuerB64);
+ } else {
+ printStringWithoutCRLF(out, derIssuerB64);
+ fputs("\n", out);
+ }
+
+ fprintf(out, "Serial DER Base64:\n");
+ if (SECU_GetWrapEnabled()) {
+ fprintf(out, "%s\n", derSerialB64);
+ } else {
+ printStringWithoutCRLF(out, derSerialB64);
+ fputs("\n", out);
+ }
+
+ PORT_Free(derIssuerB64);
+ PORT_Free(derSerialB64);
+
+ fprintf(out, "Serial DER as C source: \n{ %d, \"", c->serialNumber.len);
+
+ {
+ unsigned int i;
+ for (i = 0; i < c->serialNumber.len; ++i) {
+ unsigned char *chardata = (unsigned char *)(c->serialNumber.data);
+ unsigned char c = *(chardata + i);
+
+ fprintf(out, "\\x%02x", c);
+ }
+ fprintf(out, "\" }\n");
+ }
+
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+static SECStatus
+secu_PrintX509InvalidDate(FILE *out, SECItem *value, char *msg, int level)
+{
+ SECItem decodedValue;
+ SECStatus rv;
+ PRTime invalidTime;
+ char *formattedTime = NULL;
+
+ decodedValue.data = NULL;
+ rv = SEC_ASN1DecodeItem(NULL, &decodedValue,
+ SEC_ASN1_GET(SEC_GeneralizedTimeTemplate),
+ value);
+ if (rv == SECSuccess) {
+ rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue);
+ if (rv == SECSuccess) {
+ formattedTime = CERT_GenTime2FormattedAscii(invalidTime, "%a %b %d %H:%M:%S %Y");
+ SECU_Indent(out, level + 1);
+ fprintf(out, "%s: %s\n", msg, formattedTime);
+ PORT_Free(formattedTime);
+ }
+ }
+ PORT_Free(decodedValue.data);
+ return (rv);
+}
+
+static SECStatus
+PrintExtKeyUsageExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTOidSequence *os;
+ SECItem **op;
+
+ os = CERT_DecodeOidSequence(value);
+ if ((CERTOidSequence *)NULL == os) {
+ return SECFailure;
+ }
+
+ for (op = os->oids; *op; op++) {
+ SECU_PrintObjectID(out, *op, msg, level + 1);
+ }
+ CERT_DestroyOidSequence(os);
+ return SECSuccess;
+}
+
+static SECStatus
+secu_PrintBasicConstraints(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTBasicConstraints constraints;
+ SECStatus rv;
+
+ SECU_Indent(out, level);
+ if (msg) {
+ fprintf(out, "%s: ", msg);
+ }
+ rv = CERT_DecodeBasicConstraintValue(&constraints, value);
+ if (rv == SECSuccess && constraints.isCA) {
+ if (constraints.pathLenConstraint >= 0) {
+ fprintf(out, "Is a CA with a maximum path length of %d.\n",
+ constraints.pathLenConstraint);
+ } else {
+ fprintf(out, "Is a CA with no maximum path length.\n");
+ }
+ } else {
+ fprintf(out, "Is not a CA.\n");
+ }
+ return SECSuccess;
+}
+
+static const char *const nsTypeBits[] = {
+ "SSL Client",
+ "SSL Server",
+ "S/MIME",
+ "Object Signing",
+ "Reserved",
+ "SSL CA",
+ "S/MIME CA",
+ "ObjectSigning CA"
+};
+
+/* NSCertType is merely a bit string whose bits are displayed symbolically */
+static SECStatus
+secu_PrintNSCertType(FILE *out, SECItem *value, char *msg, int level)
+{
+ int unused;
+ int NS_Type;
+ int i;
+ int found = 0;
+ SECItem my = *value;
+
+ if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ SECU_PrintAny(out, value, "Data", level);
+ return SECSuccess;
+ }
+
+ unused = (my.len == 2) ? (my.data[0] & 0x0f) : 0;
+ NS_Type = my.data[1] & (0xff << unused);
+
+ SECU_Indent(out, level);
+ if (msg) {
+ fprintf(out, "%s: ", msg);
+ } else {
+ fprintf(out, "Netscape Certificate Type: ");
+ }
+ for (i = 0; i < 8; i++) {
+ if ((0x80 >> i) & NS_Type) {
+ fprintf(out, "%c%s", (found ? ',' : '<'), nsTypeBits[i]);
+ found = 1;
+ }
+ }
+ fprintf(out, (found ? ">\n" : "none\n"));
+ return SECSuccess;
+}
+
+static const char *const usageBits[] = {
+ "Digital Signature", /* 0x80 */
+ "Non-Repudiation", /* 0x40 */
+ "Key Encipherment", /* 0x20 */
+ "Data Encipherment", /* 0x10 */
+ "Key Agreement", /* 0x08 */
+ "Certificate Signing", /* 0x04 */
+ "CRL Signing", /* 0x02 */
+ "Encipher Only", /* 0x01 */
+ "Decipher Only", /* 0x0080 */
+ NULL
+};
+
+/* X509KeyUsage is merely a bit string whose bits are displayed symbolically */
+static void
+secu_PrintX509KeyUsage(FILE *out, SECItem *value, char *msg, int level)
+{
+ int unused;
+ int usage;
+ int i;
+ int found = 0;
+ SECItem my = *value;
+
+ if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ SECU_PrintAny(out, value, "Data", level);
+ return;
+ }
+
+ unused = (my.len >= 2) ? (my.data[0] & 0x0f) : 0;
+ usage = (my.len == 2) ? (my.data[1] & (0xff << unused)) << 8
+ : (my.data[1] << 8) |
+ (my.data[2] & (0xff << unused));
+
+ SECU_Indent(out, level);
+ fprintf(out, "Usages: ");
+ for (i = 0; usageBits[i]; i++) {
+ if ((0x8000 >> i) & usage) {
+ if (found)
+ SECU_Indent(out, level + 2);
+ fprintf(out, "%s\n", usageBits[i]);
+ found = 1;
+ }
+ }
+ if (!found) {
+ fprintf(out, "(none)\n");
+ }
+}
+
+static void
+secu_PrintIPAddress(FILE *out, SECItem *value, char *msg, int level)
+{
+ PRStatus st;
+ PRNetAddr addr;
+ char addrBuf[80];
+
+ memset(&addr, 0, sizeof addr);
+ if (value->len == 4) {
+ addr.inet.family = PR_AF_INET;
+ memcpy(&addr.inet.ip, value->data, value->len);
+ } else if (value->len == 16) {
+ addr.ipv6.family = PR_AF_INET6;
+ memcpy(addr.ipv6.ip.pr_s6_addr, value->data, value->len);
+ if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped)) {
+ /* convert to IPv4. */
+ addr.inet.family = PR_AF_INET;
+ memcpy(&addr.inet.ip, &addr.ipv6.ip.pr_s6_addr[12], 4);
+ memset(&addr.inet.pad[0], 0, sizeof addr.inet.pad);
+ }
+ } else {
+ goto loser;
+ }
+
+ st = PR_NetAddrToString(&addr, addrBuf, sizeof addrBuf);
+ if (st == PR_SUCCESS) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s: %s\n", msg, addrBuf);
+ } else {
+ loser:
+ SECU_PrintAsHex(out, value, msg, level);
+ }
+}
+
+static void
+secu_PrintGeneralName(FILE *out, CERTGeneralName *gname, char *msg, int level)
+{
+ char label[40];
+ if (msg && msg[0]) {
+ SECU_Indent(out, level++);
+ fprintf(out, "%s: \n", msg);
+ }
+ switch (gname->type) {
+ case certOtherName:
+ SECU_PrintAny(out, &gname->name.OthName.name, "Other Name", level);
+ SECU_PrintObjectID(out, &gname->name.OthName.oid, "OID", level + 1);
+ break;
+ case certDirectoryName:
+ SECU_PrintName(out, &gname->name.directoryName, "Directory Name", level);
+ break;
+ case certRFC822Name:
+ secu_PrintRawString(out, &gname->name.other, "RFC822 Name", level);
+ break;
+ case certDNSName:
+ secu_PrintRawString(out, &gname->name.other, "DNS name", level);
+ break;
+ case certURI:
+ secu_PrintRawString(out, &gname->name.other, "URI", level);
+ break;
+ case certIPAddress:
+ secu_PrintIPAddress(out, &gname->name.other, "IP Address", level);
+ break;
+ case certRegisterID:
+ SECU_PrintObjectID(out, &gname->name.other, "Registered ID", level);
+ break;
+ case certX400Address:
+ SECU_PrintAny(out, &gname->name.other, "X400 Address", level);
+ break;
+ case certEDIPartyName:
+ SECU_PrintAny(out, &gname->name.other, "EDI Party", level);
+ break;
+ default:
+ PR_snprintf(label, sizeof label, "unknown type [%d]",
+ (int)gname->type - 1);
+ SECU_PrintAsHex(out, &gname->name.other, label, level);
+ break;
+ }
+}
+
+static void
+secu_PrintGeneralNames(FILE *out, CERTGeneralName *gname, char *msg, int level)
+{
+ CERTGeneralName *name = gname;
+ do {
+ secu_PrintGeneralName(out, name, msg, level);
+ name = CERT_GetNextGeneralName(name);
+ } while (name && name != gname);
+}
+
+static void
+secu_PrintAuthKeyIDExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTAuthKeyID *kid = NULL;
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ kid = CERT_DecodeAuthKeyID(pool, value);
+ if (!kid) {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Data", level);
+ } else {
+ int keyIDPresent = (kid->keyID.data && kid->keyID.len);
+ int issuerPresent = kid->authCertIssuer != NULL;
+ int snPresent = (kid->authCertSerialNumber.data &&
+ kid->authCertSerialNumber.len);
+
+ if (keyIDPresent)
+ SECU_PrintAsHex(out, &kid->keyID, "Key ID", level);
+ if (issuerPresent)
+ secu_PrintGeneralName(out, kid->authCertIssuer, "Issuer", level);
+ if (snPresent)
+ SECU_PrintInteger(out, &kid->authCertSerialNumber,
+ "Serial Number", level);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+static void
+secu_PrintAltNameExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTGeneralName *nameList;
+ CERTGeneralName *current;
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ nameList = current = CERT_DecodeAltNameExtension(pool, value);
+ if (!current) {
+ if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) {
+ /* Decoder found empty sequence, which is invalid. */
+ PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
+ }
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Data", level);
+ } else {
+ do {
+ secu_PrintGeneralName(out, current, msg, level);
+ current = CERT_GetNextGeneralName(current);
+ } while (current != nameList);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+static void
+secu_PrintCRLDistPtsExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTCrlDistributionPoints *dPoints;
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ dPoints = CERT_DecodeCRLDistributionPoints(pool, value);
+ if (dPoints && dPoints->distPoints && dPoints->distPoints[0]) {
+ CRLDistributionPoint **pPoints = dPoints->distPoints;
+ CRLDistributionPoint *pPoint;
+ while (NULL != (pPoint = *pPoints++)) {
+ SECU_Indent(out, level);
+ fputs("Distribution point:\n", out);
+ if (pPoint->distPointType == generalName &&
+ pPoint->distPoint.fullName != NULL) {
+ secu_PrintGeneralNames(out, pPoint->distPoint.fullName, NULL,
+ level + 1);
+ } else if (pPoint->distPointType == relativeDistinguishedName &&
+ pPoint->distPoint.relativeName.avas) {
+ SECU_PrintRDN(out, &pPoint->distPoint.relativeName, "RDN",
+ level + 1);
+ } else if (pPoint->derDistPoint.data) {
+ SECU_PrintAny(out, &pPoint->derDistPoint, "Point", level + 1);
+ }
+ if (pPoint->reasons.data) {
+ secu_PrintDecodedBitString(out, &pPoint->reasons, "Reasons",
+ level + 1);
+ }
+ if (pPoint->crlIssuer) {
+ secu_PrintGeneralName(out, pPoint->crlIssuer, "CRL issuer",
+ level + 1);
+ }
+ }
+ } else {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Data", level);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+static void
+secu_PrintNameConstraintSubtree(FILE *out, CERTNameConstraint *value,
+ char *msg, int level)
+{
+ CERTNameConstraint *head = value;
+ SECU_Indent(out, level);
+ fprintf(out, "%s Subtree:\n", msg);
+ level++;
+ do {
+ secu_PrintGeneralName(out, &value->name, NULL, level);
+ if (value->min.data)
+ SECU_PrintInteger(out, &value->min, "Minimum", level + 1);
+ if (value->max.data)
+ SECU_PrintInteger(out, &value->max, "Maximum", level + 1);
+ value = CERT_GetNextNameConstraint(value);
+ } while (value != head);
+}
+
+static void
+secu_PrintNameConstraintsExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTNameConstraints *cnstrnts;
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ cnstrnts = CERT_DecodeNameConstraintsExtension(pool, value);
+ if (!cnstrnts) {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Raw", level);
+ } else {
+ if (cnstrnts->permited)
+ secu_PrintNameConstraintSubtree(out, cnstrnts->permited,
+ "Permitted", level);
+ if (cnstrnts->excluded)
+ secu_PrintNameConstraintSubtree(out, cnstrnts->excluded,
+ "Excluded", level);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+static void
+secu_PrintAuthorityInfoAcess(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTAuthInfoAccess **infos = NULL;
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ infos = CERT_DecodeAuthInfoAccessExtension(pool, value);
+ if (!infos) {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Raw", level);
+ } else {
+ CERTAuthInfoAccess *info;
+ while (NULL != (info = *infos++)) {
+ if (info->method.data) {
+ SECU_PrintObjectID(out, &info->method, "Method", level);
+ } else {
+ SECU_Indent(out, level);
+ fprintf(out, "Error: missing method\n");
+ }
+ if (info->location) {
+ secu_PrintGeneralName(out, info->location, "Location", level);
+ } else {
+ SECU_PrintAny(out, &info->derLocation, "Location", level);
+ }
+ }
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+void
+SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
+ char *msg, int level)
+{
+ SECOidTag oidTag;
+
+ if (extensions) {
+ if (msg && *msg) {
+ SECU_Indent(out, level++);
+ fprintf(out, "%s:\n", msg);
+ }
+
+ while (*extensions) {
+ SECItem *tmpitem;
+
+ tmpitem = &(*extensions)->id;
+ SECU_PrintObjectID(out, tmpitem, "Name", level);
+
+ tmpitem = &(*extensions)->critical;
+ if (tmpitem->len) {
+ secu_PrintBoolean(out, tmpitem, "Critical", level);
+ }
+
+ oidTag = SECOID_FindOIDTag(&((*extensions)->id));
+ tmpitem = &((*extensions)->value);
+
+ switch (oidTag) {
+ case SEC_OID_X509_INVALID_DATE:
+ case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
+ secu_PrintX509InvalidDate(out, tmpitem, "Date", level);
+ break;
+ case SEC_OID_X509_CERTIFICATE_POLICIES:
+ SECU_PrintPolicy(out, tmpitem, "Data", level);
+ break;
+ case SEC_OID_NS_CERT_EXT_BASE_URL:
+ case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
+ case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
+ case SEC_OID_NS_CERT_EXT_CA_CRL_URL:
+ case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
+ case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
+ case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
+ case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
+ case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
+ case SEC_OID_OCSP_RESPONDER:
+ SECU_PrintString(out, tmpitem, "URL", level);
+ break;
+ case SEC_OID_NS_CERT_EXT_COMMENT:
+ SECU_PrintString(out, tmpitem, "Comment", level);
+ break;
+ case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
+ SECU_PrintString(out, tmpitem, "ServerName", level);
+ break;
+ case SEC_OID_NS_CERT_EXT_CERT_TYPE:
+ secu_PrintNSCertType(out, tmpitem, "Data", level);
+ break;
+ case SEC_OID_X509_BASIC_CONSTRAINTS:
+ secu_PrintBasicConstraints(out, tmpitem, "Data", level);
+ break;
+ case SEC_OID_X509_EXT_KEY_USAGE:
+ PrintExtKeyUsageExtension(out, tmpitem, NULL, level);
+ break;
+ case SEC_OID_X509_KEY_USAGE:
+ secu_PrintX509KeyUsage(out, tmpitem, NULL, level);
+ break;
+ case SEC_OID_X509_AUTH_KEY_ID:
+ secu_PrintAuthKeyIDExtension(out, tmpitem, NULL, level);
+ break;
+ case SEC_OID_X509_SUBJECT_ALT_NAME:
+ case SEC_OID_X509_ISSUER_ALT_NAME:
+ secu_PrintAltNameExtension(out, tmpitem, NULL, level);
+ break;
+ case SEC_OID_X509_CRL_DIST_POINTS:
+ secu_PrintCRLDistPtsExtension(out, tmpitem, NULL, level);
+ break;
+ case SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD:
+ SECU_PrintPrivKeyUsagePeriodExtension(out, tmpitem, NULL,
+ level);
+ break;
+ case SEC_OID_X509_NAME_CONSTRAINTS:
+ secu_PrintNameConstraintsExtension(out, tmpitem, NULL, level);
+ break;
+ case SEC_OID_X509_AUTH_INFO_ACCESS:
+ secu_PrintAuthorityInfoAcess(out, tmpitem, NULL, level);
+ break;
+
+ case SEC_OID_X509_CRL_NUMBER:
+ case SEC_OID_X509_REASON_CODE:
+
+ /* PKIX OIDs */
+ case SEC_OID_PKIX_OCSP:
+ case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
+ case SEC_OID_PKIX_OCSP_NONCE:
+ case SEC_OID_PKIX_OCSP_CRL:
+ case SEC_OID_PKIX_OCSP_RESPONSE:
+ case SEC_OID_PKIX_OCSP_NO_CHECK:
+ case SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF:
+ case SEC_OID_PKIX_OCSP_SERVICE_LOCATOR:
+ case SEC_OID_PKIX_REGCTRL_REGTOKEN:
+ case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
+ case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
+ case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
+ case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
+ case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
+ case SEC_OID_PKIX_REGINFO_UTF8_PAIRS:
+ case SEC_OID_PKIX_REGINFO_CERT_REQUEST:
+
+ /* Netscape extension OIDs. */
+ case SEC_OID_NS_CERT_EXT_NETSCAPE_OK:
+ case SEC_OID_NS_CERT_EXT_ISSUER_LOGO:
+ case SEC_OID_NS_CERT_EXT_SUBJECT_LOGO:
+ case SEC_OID_NS_CERT_EXT_ENTITY_LOGO:
+ case SEC_OID_NS_CERT_EXT_USER_PICTURE:
+
+ /* x.509 v3 Extensions */
+ case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
+ case SEC_OID_X509_SUBJECT_KEY_ID:
+ case SEC_OID_X509_POLICY_MAPPINGS:
+ case SEC_OID_X509_POLICY_CONSTRAINTS:
+
+ default:
+ SECU_PrintAny(out, tmpitem, "Data", level);
+ break;
+ }
+
+ SECU_Newline(out);
+ extensions++;
+ }
+ }
+}
+
+/* An RDN is a subset of a DirectoryName, and we already know how to
+ * print those, so make a directory name out of the RDN, and print it.
+ */
+void
+SECU_PrintRDN(FILE *out, CERTRDN *rdn, const char *msg, int level)
+{
+ CERTName name;
+ CERTRDN *rdns[2];
+
+ name.arena = NULL;
+ name.rdns = rdns;
+ rdns[0] = rdn;
+ rdns[1] = NULL;
+ SECU_PrintName(out, &name, msg, level);
+}
+
+void
+SECU_PrintNameQuotesOptional(FILE *out, CERTName *name, const char *msg,
+ int level, PRBool quotes)
+{
+ char *nameStr = NULL;
+ char *str;
+ SECItem my;
+
+ if (!name) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return;
+ }
+ if (!name->rdns || !name->rdns[0]) {
+ str = "(empty)";
+ } else {
+ str = nameStr = CERT_NameToAscii(name);
+ }
+ if (!str) {
+ str = "!Invalid AVA!";
+ }
+ my.data = (unsigned char *)str;
+ my.len = PORT_Strlen(str);
+#if 1
+ secu_PrintRawStringQuotesOptional(out, &my, msg, level, quotes);
+#else
+ SECU_Indent(out, level);
+ fprintf(out, "%s: ", msg);
+ fprintf(out, str);
+ SECU_Newline(out);
+#endif
+ PORT_Free(nameStr);
+}
+
+void
+SECU_PrintName(FILE *out, CERTName *name, const char *msg, int level)
+{
+ SECU_PrintNameQuotesOptional(out, name, msg, level, PR_TRUE);
+}
+
+void
+printflags(char *trusts, unsigned int flags)
+{
+ if (flags & CERTDB_VALID_CA)
+ if (!(flags & CERTDB_TRUSTED_CA) &&
+ !(flags & CERTDB_TRUSTED_CLIENT_CA))
+ PORT_Strcat(trusts, "c");
+ if (flags & CERTDB_TERMINAL_RECORD)
+ if (!(flags & CERTDB_TRUSTED))
+ PORT_Strcat(trusts, "p");
+ if (flags & CERTDB_TRUSTED_CA)
+ PORT_Strcat(trusts, "C");
+ if (flags & CERTDB_TRUSTED_CLIENT_CA)
+ PORT_Strcat(trusts, "T");
+ if (flags & CERTDB_TRUSTED)
+ PORT_Strcat(trusts, "P");
+ if (flags & CERTDB_USER)
+ PORT_Strcat(trusts, "u");
+ if (flags & CERTDB_SEND_WARN)
+ PORT_Strcat(trusts, "w");
+ if (flags & CERTDB_INVISIBLE_CA)
+ PORT_Strcat(trusts, "I");
+ if (flags & CERTDB_GOVT_APPROVED_CA)
+ PORT_Strcat(trusts, "G");
+ return;
+}
+
+/* callback for listing certs through pkcs11 */
+SECStatus
+SECU_PrintCertNickname(CERTCertListNode *node, void *data)
+{
+ CERTCertTrust trust;
+ CERTCertificate *cert;
+ FILE *out;
+ char trusts[30];
+ char *name;
+
+ cert = node->cert;
+
+ PORT_Memset(trusts, 0, sizeof(trusts));
+ out = (FILE *)data;
+
+ name = node->appData;
+ if (!name || !name[0]) {
+ name = cert->nickname;
+ }
+ if (!name || !name[0]) {
+ name = cert->emailAddr;
+ }
+ if (!name || !name[0]) {
+ name = "(NULL)";
+ }
+
+ if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
+ printflags(trusts, trust.sslFlags);
+ PORT_Strcat(trusts, ",");
+ printflags(trusts, trust.emailFlags);
+ PORT_Strcat(trusts, ",");
+ printflags(trusts, trust.objectSigningFlags);
+ } else {
+ PORT_Memcpy(trusts, ",,", 3);
+ }
+ fprintf(out, "%-60s %-5s\n", name, trusts);
+
+ return (SECSuccess);
+}
+
+int
+SECU_DecodeAndPrintExtensions(FILE *out, SECItem *any, char *m, int level)
+{
+ CERTCertExtension **extensions = NULL;
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ int rv = 0;
+
+ if (!arena)
+ return SEC_ERROR_NO_MEMORY;
+
+ rv = SEC_QuickDERDecodeItem(arena, &extensions,
+ SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate), any);
+ if (!rv)
+ SECU_PrintExtensions(out, extensions, m, level);
+ else
+ SECU_PrintAny(out, any, m, level);
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+/* print a decoded SET OF or SEQUENCE OF Extensions */
+int
+SECU_PrintSetOfExtensions(FILE *out, SECItem **any, char *m, int level)
+{
+ int rv = 0;
+ if (m && *m) {
+ SECU_Indent(out, level++);
+ fprintf(out, "%s:\n", m);
+ }
+ while (any && any[0]) {
+ rv |= SECU_DecodeAndPrintExtensions(out, any[0], "", level);
+ any++;
+ }
+ return rv;
+}
+
+/* print a decoded SET OF or SEQUENCE OF "ANY" */
+int
+SECU_PrintSetOfAny(FILE *out, SECItem **any, char *m, int level)
+{
+ int rv = 0;
+ if (m && *m) {
+ SECU_Indent(out, level++);
+ fprintf(out, "%s:\n", m);
+ }
+ while (any && any[0]) {
+ SECU_PrintAny(out, any[0], "", level);
+ any++;
+ }
+ return rv;
+}
+
+int
+SECU_PrintCertAttribute(FILE *out, CERTAttribute *attr, char *m, int level)
+{
+ int rv = 0;
+ SECOidTag tag;
+ tag = SECU_PrintObjectID(out, &attr->attrType, "Attribute Type", level);
+ if (tag == SEC_OID_PKCS9_EXTENSION_REQUEST) {
+ rv = SECU_PrintSetOfExtensions(out, attr->attrValue, "Extensions", level);
+ } else {
+ rv = SECU_PrintSetOfAny(out, attr->attrValue, "Attribute Values", level);
+ }
+ return rv;
+}
+
+int
+SECU_PrintCertAttributes(FILE *out, CERTAttribute **attrs, char *m, int level)
+{
+ int rv = 0;
+ while (attrs[0]) {
+ rv |= SECU_PrintCertAttribute(out, attrs[0], m, level + 1);
+ attrs++;
+ }
+ return rv;
+}
+
+int /* sometimes a PRErrorCode, other times a SECStatus. Sigh. */
+ SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m, int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCertificateRequest *cr;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ /* Decode certificate request */
+ cr = PORT_ArenaZNew(arena, CERTCertificateRequest);
+ if (!cr)
+ goto loser;
+ cr->arena = arena;
+ rv = SEC_QuickDERDecodeItem(arena, cr,
+ SEC_ASN1_GET(CERT_CertificateRequestTemplate), der);
+ if (rv)
+ goto loser;
+
+ /* Pretty print it out */
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &cr->version, "Version", level + 1);
+ SECU_PrintName(out, &cr->subject, "Subject", level + 1);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+ secu_PrintSubjectPublicKeyInfo(out, arena, &cr->subjectPublicKeyInfo,
+ "Subject Public Key Info", level + 1);
+ if (cr->attributes)
+ SECU_PrintCertAttributes(out, cr->attributes, "Attributes", level + 1);
+ rv = 0;
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+int
+SECU_PrintCertificate(FILE *out, const SECItem *der, const char *m, int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCertificate *c;
+ int rv = SEC_ERROR_NO_MEMORY;
+ int iv;
+
+ if (!arena)
+ return rv;
+
+ /* Decode certificate */
+ c = PORT_ArenaZNew(arena, CERTCertificate);
+ if (!c)
+ goto loser;
+ c->arena = arena;
+ rv = SEC_ASN1DecodeItem(arena, c,
+ SEC_ASN1_GET(CERT_CertificateTemplate), der);
+ if (rv) {
+ SECU_Indent(out, level);
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, der, "Raw", level);
+ goto loser;
+ }
+ /* Pretty print it out */
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ iv = c->version.len ? DER_GetInteger(&c->version) : 0; /* version is optional */
+ SECU_Indent(out, level + 1);
+ fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
+
+ SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level + 1);
+ SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level + 1);
+ SECU_PrintName(out, &c->issuer, "Issuer", level + 1);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+ secu_PrintValidity(out, &c->validity, "Validity", level + 1);
+ SECU_PrintName(out, &c->subject, "Subject", level + 1);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+ secu_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo,
+ "Subject Public Key Info", level + 1);
+ if (c->issuerID.data)
+ secu_PrintDecodedBitString(out, &c->issuerID, "Issuer Unique ID", level + 1);
+ if (c->subjectID.data)
+ secu_PrintDecodedBitString(out, &c->subjectID, "Subject Unique ID", level + 1);
+ SECU_PrintExtensions(out, c->extensions, "Signed Extensions", level + 1);
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+int
+SECU_PrintCertificateBasicInfo(FILE *out, const SECItem *der, const char *m, int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCertificate *c;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ /* Decode certificate */
+ c = PORT_ArenaZNew(arena, CERTCertificate);
+ if (!c)
+ goto loser;
+ c->arena = arena;
+ rv = SEC_ASN1DecodeItem(arena, c,
+ SEC_ASN1_GET(CERT_CertificateTemplate), der);
+ if (rv) {
+ SECU_Indent(out, level);
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, der, "Raw", level);
+ goto loser;
+ }
+ /* Pretty print it out */
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level + 1);
+ SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level + 1);
+ SECU_PrintName(out, &c->issuer, "Issuer", level + 1);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+ secu_PrintValidity(out, &c->validity, "Validity", level + 1);
+ SECU_PrintName(out, &c->subject, "Subject", level + 1);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+int
+SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m, int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ int rv = SEC_ERROR_NO_MEMORY;
+ CERTSubjectPublicKeyInfo spki;
+
+ if (!arena)
+ return rv;
+
+ PORT_Memset(&spki, 0, sizeof spki);
+ rv = SEC_ASN1DecodeItem(arena, &spki,
+ SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate),
+ der);
+ if (!rv) {
+ if (m && *m) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ }
+ secu_PrintSubjectPublicKeyInfo(out, arena, &spki,
+ "Subject Public Key Info", level + 1);
+ }
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+#ifdef HAVE_EPV_TEMPLATE
+int
+SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SECKEYEncryptedPrivateKeyInfo key;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ PORT_Memset(&key, 0, sizeof(key));
+ rv = SEC_ASN1DecodeItem(arena, &key,
+ SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), der);
+ if (rv)
+ goto loser;
+
+ /* Pretty print it out */
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintAlgorithmID(out, &key.algorithm, "Encryption Algorithm",
+ level + 1);
+ SECU_PrintAsHex(out, &key.encryptedData, "Encrypted Data", level + 1);
+loser:
+ PORT_FreeArena(arena, PR_TRUE);
+ return rv;
+}
+#endif
+
+int
+SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
+{
+ unsigned char fingerprint[SHA256_LENGTH];
+ char *fpStr = NULL;
+ int err = PORT_GetError();
+ SECStatus rv;
+ SECItem fpItem;
+
+ /* Print SHA-256 fingerprint */
+ memset(fingerprint, 0, sizeof fingerprint);
+ rv = PK11_HashBuf(SEC_OID_SHA256, fingerprint, derCert->data, derCert->len);
+ fpItem.data = fingerprint;
+ fpItem.len = SHA256_LENGTH;
+ fpStr = CERT_Hexify(&fpItem, 1);
+ SECU_Indent(out, level);
+ fprintf(out, "%s (SHA-256):", m);
+ if (SECU_GetWrapEnabled()) {
+ fprintf(out, "\n");
+ SECU_Indent(out, level + 1);
+ } else {
+ fprintf(out, " ");
+ }
+ fprintf(out, "%s\n", fpStr);
+ PORT_Free(fpStr);
+ fpStr = NULL;
+ if (rv != SECSuccess && !err)
+ err = PORT_GetError();
+
+ /* print SHA1 fingerprint */
+ memset(fingerprint, 0, sizeof fingerprint);
+ rv = PK11_HashBuf(SEC_OID_SHA1, fingerprint, derCert->data, derCert->len);
+ fpItem.data = fingerprint;
+ fpItem.len = SHA1_LENGTH;
+ fpStr = CERT_Hexify(&fpItem, 1);
+ SECU_Indent(out, level);
+ fprintf(out, "%s (SHA1):", m);
+ if (SECU_GetWrapEnabled()) {
+ fprintf(out, "\n");
+ SECU_Indent(out, level + 1);
+ } else {
+ fprintf(out, " ");
+ }
+ fprintf(out, "%s\n", fpStr);
+ PORT_Free(fpStr);
+ if (SECU_GetWrapEnabled())
+ fprintf(out, "\n");
+
+ if (err)
+ PORT_SetError(err);
+ if (err || rv != SECSuccess)
+ return SECFailure;
+
+ return 0;
+}
+
+/*
+** PKCS7 Support
+*/
+
+/* forward declaration */
+static int
+secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *, int);
+
+/*
+** secu_PrintPKCS7EncContent
+** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
+*/
+static void
+secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
+ char *m, int level)
+{
+ if (src->contentTypeTag == NULL)
+ src->contentTypeTag = SECOID_FindOID(&(src->contentType));
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Content Type: %s\n",
+ (src->contentTypeTag != NULL) ? src->contentTypeTag->desc
+ : "Unknown");
+ SECU_PrintAlgorithmID(out, &(src->contentEncAlg),
+ "Content Encryption Algorithm", level + 1);
+ SECU_PrintAsHex(out, &(src->encContent),
+ "Encrypted Content", level + 1);
+}
+
+/*
+** secu_PrintRecipientInfo
+** Prints a PKCS7RecipientInfo type
+*/
+static void
+secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
+ int level)
+{
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(info->version), "Version", level + 1);
+
+ SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
+ level + 1);
+ SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
+ "Serial Number", level + 1);
+
+ /* Parse and display encrypted key */
+ SECU_PrintAlgorithmID(out, &(info->keyEncAlg),
+ "Key Encryption Algorithm", level + 1);
+ SECU_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1);
+}
+
+/*
+** secu_PrintSignerInfo
+** Prints a PKCS7SingerInfo type
+*/
+static void
+secu_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m, int level)
+{
+ SEC_PKCS7Attribute *attr;
+ int iv;
+ char om[100];
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(info->version), "Version", level + 1);
+
+ SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
+ level + 1);
+ SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
+ "Serial Number", level + 1);
+
+ SECU_PrintAlgorithmID(out, &(info->digestAlg), "Digest Algorithm",
+ level + 1);
+
+ if (info->authAttr != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Authenticated Attributes:\n");
+ iv = 0;
+ while ((attr = info->authAttr[iv++]) != NULL) {
+ sprintf(om, "Attribute (%d)", iv);
+ secu_PrintAttribute(out, attr, om, level + 2);
+ }
+ }
+
+ /* Parse and display signature */
+ SECU_PrintAlgorithmID(out, &(info->digestEncAlg),
+ "Digest Encryption Algorithm", level + 1);
+ SECU_PrintAsHex(out, &(info->encDigest), "Encrypted Digest", level + 1);
+
+ if (info->unAuthAttr != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Unauthenticated Attributes:\n");
+ iv = 0;
+ while ((attr = info->unAuthAttr[iv++]) != NULL) {
+ sprintf(om, "Attribute (%x)", iv);
+ secu_PrintAttribute(out, attr, om, level + 2);
+ }
+ }
+}
+
+/* callers of this function must make sure that the CERTSignedCrl
+ from which they are extracting the CERTCrl has been fully-decoded.
+ Otherwise it will not have the entries even though the CRL may have
+ some */
+
+void
+SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level)
+{
+ CERTCrlEntry *entry;
+ int iv;
+ char om[100];
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ /* version is optional */
+ iv = crl->version.len ? DER_GetInteger(&crl->version) : 0;
+ SECU_Indent(out, level + 1);
+ fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
+ SECU_PrintAlgorithmID(out, &(crl->signatureAlg), "Signature Algorithm",
+ level + 1);
+ SECU_PrintName(out, &(crl->name), "Issuer", level + 1);
+ SECU_PrintTimeChoice(out, &(crl->lastUpdate), "This Update", level + 1);
+ if (crl->nextUpdate.data && crl->nextUpdate.len) /* is optional */
+ SECU_PrintTimeChoice(out, &(crl->nextUpdate), "Next Update", level + 1);
+
+ if (crl->entries != NULL) {
+ iv = 0;
+ while ((entry = crl->entries[iv++]) != NULL) {
+ sprintf(om, "Entry %d (0x%x):\n", iv, iv);
+ SECU_Indent(out, level + 1);
+ fputs(om, out);
+ SECU_PrintInteger(out, &(entry->serialNumber), "Serial Number",
+ level + 2);
+ SECU_PrintTimeChoice(out, &(entry->revocationDate),
+ "Revocation Date", level + 2);
+ SECU_PrintExtensions(out, entry->extensions,
+ "Entry Extensions", level + 2);
+ }
+ }
+ SECU_PrintExtensions(out, crl->extensions, "CRL Extensions", level + 1);
+}
+
+/*
+** secu_PrintPKCS7Signed
+** Pretty print a PKCS7 signed data type (up to version 1).
+*/
+static int
+secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
+ const char *m, int level)
+{
+ SECAlgorithmID *digAlg; /* digest algorithms */
+ SECItem *aCert; /* certificate */
+ CERTSignedCrl *aCrl; /* certificate revocation list */
+ SEC_PKCS7SignerInfo *sigInfo; /* signer information */
+ int rv, iv;
+ char om[100];
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list digest algorithms (if any) */
+ if (src->digestAlgorithms != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Digest Algorithm List:\n");
+ iv = 0;
+ while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
+ sprintf(om, "Digest Algorithm (%x)", iv);
+ SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
+ }
+ }
+
+ /* Now for the content */
+ rv = secu_PrintPKCS7ContentInfo(out, &(src->contentInfo),
+ "Content Information", level + 1);
+ if (rv != 0)
+ return rv;
+
+ /* Parse and list certificates (if any) */
+ if (src->rawCerts != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Certificate List:\n");
+ iv = 0;
+ while ((aCert = src->rawCerts[iv++]) != NULL) {
+ sprintf(om, "Certificate (%x)", iv);
+ rv = SECU_PrintSignedData(out, aCert, om, level + 2,
+ (SECU_PPFunc)SECU_PrintCertificate);
+ if (rv)
+ return rv;
+ }
+ }
+
+ /* Parse and list CRL's (if any) */
+ if (src->crls != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signed Revocation Lists:\n");
+ iv = 0;
+ while ((aCrl = src->crls[iv++]) != NULL) {
+ sprintf(om, "Signed Revocation List (%x)", iv);
+ SECU_Indent(out, level + 2);
+ fprintf(out, "%s:\n", om);
+ SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
+ "Signature Algorithm", level + 3);
+ DER_ConvertBitString(&aCrl->signatureWrap.signature);
+ SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
+ level + 3);
+ SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
+ level + 3);
+ }
+ }
+
+ /* Parse and list signatures (if any) */
+ if (src->signerInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signer Information List:\n");
+ iv = 0;
+ while ((sigInfo = src->signerInfos[iv++]) != NULL) {
+ sprintf(om, "Signer Information (%x)", iv);
+ secu_PrintSignerInfo(out, sigInfo, om, level + 2);
+ }
+ }
+
+ return 0;
+}
+
+/*
+** secu_PrintPKCS7Enveloped
+** Pretty print a PKCS7 enveloped data type (up to version 1).
+*/
+static void
+secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
+ const char *m, int level)
+{
+ SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
+ int iv;
+ char om[100];
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list recipients (this is not optional) */
+ if (src->recipientInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Recipient Information List:\n");
+ iv = 0;
+ while ((recInfo = src->recipientInfos[iv++]) != NULL) {
+ sprintf(om, "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7SignedEnveloped
+** Pretty print a PKCS7 singed and enveloped data type (up to version 1).
+*/
+static int
+secu_PrintPKCS7SignedAndEnveloped(FILE *out,
+ SEC_PKCS7SignedAndEnvelopedData *src,
+ const char *m, int level)
+{
+ SECAlgorithmID *digAlg; /* pointer for digest algorithms */
+ SECItem *aCert; /* pointer for certificate */
+ CERTSignedCrl *aCrl; /* pointer for certificate revocation list */
+ SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */
+ SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */
+ int rv, iv;
+ char om[100];
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list recipients (this is not optional) */
+ if (src->recipientInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Recipient Information List:\n");
+ iv = 0;
+ while ((recInfo = src->recipientInfos[iv++]) != NULL) {
+ sprintf(om, "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ /* Parse and list digest algorithms (if any) */
+ if (src->digestAlgorithms != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Digest Algorithm List:\n");
+ iv = 0;
+ while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
+ sprintf(om, "Digest Algorithm (%x)", iv);
+ SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
+ }
+ }
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+
+ /* Parse and list certificates (if any) */
+ if (src->rawCerts != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Certificate List:\n");
+ iv = 0;
+ while ((aCert = src->rawCerts[iv++]) != NULL) {
+ sprintf(om, "Certificate (%x)", iv);
+ rv = SECU_PrintSignedData(out, aCert, om, level + 2,
+ (SECU_PPFunc)SECU_PrintCertificate);
+ if (rv)
+ return rv;
+ }
+ }
+
+ /* Parse and list CRL's (if any) */
+ if (src->crls != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signed Revocation Lists:\n");
+ iv = 0;
+ while ((aCrl = src->crls[iv++]) != NULL) {
+ sprintf(om, "Signed Revocation List (%x)", iv);
+ SECU_Indent(out, level + 2);
+ fprintf(out, "%s:\n", om);
+ SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
+ "Signature Algorithm", level + 3);
+ DER_ConvertBitString(&aCrl->signatureWrap.signature);
+ SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
+ level + 3);
+ SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
+ level + 3);
+ }
+ }
+
+ /* Parse and list signatures (if any) */
+ if (src->signerInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signer Information List:\n");
+ iv = 0;
+ while ((sigInfo = src->signerInfos[iv++]) != NULL) {
+ sprintf(om, "Signer Information (%x)", iv);
+ secu_PrintSignerInfo(out, sigInfo, om, level + 2);
+ }
+ }
+
+ return 0;
+}
+
+int
+SECU_PrintCrl(FILE *out, SECItem *der, char *m, int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCrl *c = NULL;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+ do {
+ /* Decode CRL */
+ c = PORT_ArenaZNew(arena, CERTCrl);
+ if (!c)
+ break;
+
+ rv = SEC_QuickDERDecodeItem(arena, c, SEC_ASN1_GET(CERT_CrlTemplate), der);
+ if (rv != SECSuccess)
+ break;
+ SECU_PrintCRLInfo(out, c, m, level);
+ } while (0);
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+/*
+** secu_PrintPKCS7Encrypted
+** Pretty print a PKCS7 encrypted data type (up to version 1).
+*/
+static void
+secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
+ const char *m, int level)
+{
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7Digested
+** Pretty print a PKCS7 digested data type (up to version 1).
+*/
+static void
+secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
+ const char *m, int level)
+{
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ SECU_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm",
+ level + 1);
+ secu_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information",
+ level + 1);
+ SECU_PrintAsHex(out, &src->digest, "Digest", level + 1);
+}
+
+/*
+** secu_PrintPKCS7ContentInfo
+** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
+** appropriate function
+*/
+static int
+secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
+ char *m, int level)
+{
+ const char *desc;
+ SECOidTag kind;
+ int rv;
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ level++;
+
+ if (src->contentTypeTag == NULL)
+ src->contentTypeTag = SECOID_FindOID(&(src->contentType));
+
+ if (src->contentTypeTag == NULL) {
+ desc = "Unknown";
+ kind = SEC_OID_PKCS7_DATA;
+ } else {
+ desc = src->contentTypeTag->desc;
+ kind = src->contentTypeTag->offset;
+ }
+
+ if (src->content.data == NULL) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", desc);
+ level++;
+ SECU_Indent(out, level);
+ fprintf(out, "<no content>\n");
+ return 0;
+ }
+
+ rv = 0;
+ switch (kind) {
+ case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
+ rv = secu_PrintPKCS7Signed(out, src->content.signedData, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
+ secu_PrintPKCS7Enveloped(out, src->content.envelopedData, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
+ rv = secu_PrintPKCS7SignedAndEnveloped(out,
+ src->content.signedAndEnvelopedData,
+ desc, level);
+ break;
+
+ case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
+ secu_PrintPKCS7Digested(out, src->content.digestedData, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
+ secu_PrintPKCS7Encrypted(out, src->content.encryptedData, desc, level);
+ break;
+
+ default:
+ SECU_PrintAsHex(out, src->content.data, desc, level);
+ break;
+ }
+
+ return rv;
+}
+
+/*
+** SECU_PrintPKCS7ContentInfo
+** Decode and print any major PKCS7 data type (up to version 1).
+*/
+int
+SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
+{
+ SEC_PKCS7ContentInfo *cinfo;
+ int rv;
+
+ cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ if (cinfo != NULL) {
+ /* Send it to recursive parsing and printing module */
+ rv = secu_PrintPKCS7ContentInfo(out, cinfo, m, level);
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ } else {
+ rv = -1;
+ }
+
+ return rv;
+}
+
+/*
+** End of PKCS7 functions
+*/
+
+void
+printFlags(FILE *out, unsigned int flags, int level)
+{
+ if (flags & CERTDB_TERMINAL_RECORD) {
+ SECU_Indent(out, level);
+ fprintf(out, "Terminal Record\n");
+ }
+ if (flags & CERTDB_TRUSTED) {
+ SECU_Indent(out, level);
+ fprintf(out, "Trusted\n");
+ }
+ if (flags & CERTDB_SEND_WARN) {
+ SECU_Indent(out, level);
+ fprintf(out, "Warn When Sending\n");
+ }
+ if (flags & CERTDB_VALID_CA) {
+ SECU_Indent(out, level);
+ fprintf(out, "Valid CA\n");
+ }
+ if (flags & CERTDB_TRUSTED_CA) {
+ SECU_Indent(out, level);
+ fprintf(out, "Trusted CA\n");
+ }
+ if (flags & CERTDB_NS_TRUSTED_CA) {
+ SECU_Indent(out, level);
+ fprintf(out, "Netscape Trusted CA\n");
+ }
+ if (flags & CERTDB_USER) {
+ SECU_Indent(out, level);
+ fprintf(out, "User\n");
+ }
+ if (flags & CERTDB_TRUSTED_CLIENT_CA) {
+ SECU_Indent(out, level);
+ fprintf(out, "Trusted Client CA\n");
+ }
+ if (flags & CERTDB_GOVT_APPROVED_CA) {
+ SECU_Indent(out, level);
+ fprintf(out, "Step-up\n");
+ }
+}
+
+void
+SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m, int level)
+{
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_Indent(out, level + 1);
+ fprintf(out, "SSL Flags:\n");
+ printFlags(out, trust->sslFlags, level + 2);
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Email Flags:\n");
+ printFlags(out, trust->emailFlags, level + 2);
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Object Signing Flags:\n");
+ printFlags(out, trust->objectSigningFlags, level + 2);
+}
+
+int
+SECU_PrintDERName(FILE *out, SECItem *der, const char *m, int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTName *name;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ name = PORT_ArenaZNew(arena, CERTName);
+ if (!name)
+ goto loser;
+
+ rv = SEC_ASN1DecodeItem(arena, name, SEC_ASN1_GET(CERT_NameTemplate), der);
+ if (rv)
+ goto loser;
+
+ SECU_PrintName(out, name, m, level);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+typedef enum {
+ noSignature = 0,
+ withSignature = 1
+} SignatureOptionType;
+
+static int
+secu_PrintSignedDataSigOpt(FILE *out, SECItem *der, const char *m,
+ int level, SECU_PPFunc inner,
+ SignatureOptionType withSignature)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTSignedData *sd;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ /* Strip off the signature */
+ sd = PORT_ArenaZNew(arena, CERTSignedData);
+ if (!sd)
+ goto loser;
+
+ rv = SEC_ASN1DecodeItem(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate),
+ der);
+ if (rv)
+ goto loser;
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ } else {
+ level -= 1;
+ }
+ rv = (*inner)(out, &sd->data, "Data", level + 1);
+
+ if (withSignature) {
+ SECU_PrintAlgorithmID(out, &sd->signatureAlgorithm, "Signature Algorithm",
+ level + 1);
+ DER_ConvertBitString(&sd->signature);
+ SECU_PrintAsHex(out, &sd->signature, "Signature", level + 1);
+ }
+ SECU_PrintFingerprints(out, der, "Fingerprint", level + 1);
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+int
+SECU_PrintSignedData(FILE *out, SECItem *der, const char *m,
+ int level, SECU_PPFunc inner)
+{
+ return secu_PrintSignedDataSigOpt(out, der, m, level, inner,
+ withSignature);
+}
+
+int
+SECU_PrintSignedContent(FILE *out, SECItem *der, char *m,
+ int level, SECU_PPFunc inner)
+{
+ return secu_PrintSignedDataSigOpt(out, der, m, level, inner,
+ noSignature);
+}
+
+SECStatus
+SEC_PrintCertificateAndTrust(CERTCertificate *cert,
+ const char *label,
+ CERTCertTrust *trust)
+{
+ SECStatus rv;
+ SECItem data;
+ CERTCertTrust certTrust;
+
+ data.data = cert->derCert.data;
+ data.len = cert->derCert.len;
+
+ rv = SECU_PrintSignedData(stdout, &data, label, 0,
+ (SECU_PPFunc)SECU_PrintCertificate);
+ if (rv) {
+ return (SECFailure);
+ }
+ if (trust) {
+ SECU_PrintTrustFlags(stdout, trust,
+ "Certificate Trust Flags", 1);
+ } else if (CERT_GetCertTrust(cert, &certTrust) == SECSuccess) {
+ SECU_PrintTrustFlags(stdout, &certTrust,
+ "Certificate Trust Flags", 1);
+ }
+
+ printf("\n");
+
+ return (SECSuccess);
+}
+
+static char *
+bestCertName(CERTCertificate *cert)
+{
+ if (cert->nickname) {
+ return cert->nickname;
+ }
+ if (cert->emailAddr && cert->emailAddr[0]) {
+ return cert->emailAddr;
+ }
+ return cert->subjectName;
+}
+
+void
+SECU_printCertProblemsOnDate(FILE *outfile, CERTCertDBHandle *handle,
+ CERTCertificate *cert, PRBool checksig,
+ SECCertificateUsage certUsage, void *pinArg, PRBool verbose,
+ PRTime datetime)
+{
+ CERTVerifyLog log;
+ CERTVerifyLogNode *node;
+
+ PRErrorCode err = PORT_GetError();
+
+ log.arena = PORT_NewArena(512);
+ log.head = log.tail = NULL;
+ log.count = 0;
+ CERT_VerifyCertificate(handle, cert, checksig, certUsage, datetime, pinArg, &log, NULL);
+
+ SECU_displayVerifyLog(outfile, &log, verbose);
+
+ for (node = log.head; node; node = node->next) {
+ if (node->cert)
+ CERT_DestroyCertificate(node->cert);
+ }
+ PORT_FreeArena(log.arena, PR_FALSE);
+
+ PORT_SetError(err); /* restore original error code */
+}
+
+void
+SECU_displayVerifyLog(FILE *outfile, CERTVerifyLog *log,
+ PRBool verbose)
+{
+ CERTVerifyLogNode *node = NULL;
+ unsigned int depth = (unsigned int)-1;
+ unsigned int flags = 0;
+ char *errstr = NULL;
+
+ if (log->count > 0) {
+ fprintf(outfile, "PROBLEM WITH THE CERT CHAIN:\n");
+ for (node = log->head; node; node = node->next) {
+ if (depth != node->depth) {
+ depth = node->depth;
+ fprintf(outfile, "CERT %d. %s %s:\n", depth,
+ bestCertName(node->cert),
+ depth ? "[Certificate Authority]" : "");
+ if (verbose) {
+ const char *emailAddr;
+ emailAddr = CERT_GetFirstEmailAddress(node->cert);
+ if (emailAddr) {
+ fprintf(outfile, "Email Address(es): ");
+ do {
+ fprintf(outfile, "%s\n", emailAddr);
+ emailAddr = CERT_GetNextEmailAddress(node->cert,
+ emailAddr);
+ } while (emailAddr);
+ }
+ }
+ }
+ fprintf(outfile, " ERROR %ld: %s\n", node->error,
+ SECU_Strerror(node->error));
+ errstr = NULL;
+ switch (node->error) {
+ case SEC_ERROR_INADEQUATE_KEY_USAGE:
+ flags = (unsigned int)((char *)node->arg - (char *)NULL);
+ switch (flags) {
+ case KU_DIGITAL_SIGNATURE:
+ errstr = "Cert cannot sign.";
+ break;
+ case KU_KEY_ENCIPHERMENT:
+ errstr = "Cert cannot encrypt.";
+ break;
+ case KU_KEY_CERT_SIGN:
+ errstr = "Cert cannot sign other certs.";
+ break;
+ default:
+ errstr = "[unknown usage].";
+ break;
+ }
+ break;
+ case SEC_ERROR_INADEQUATE_CERT_TYPE:
+ flags = (unsigned int)((char *)node->arg - (char *)NULL);
+ switch (flags) {
+ case NS_CERT_TYPE_SSL_CLIENT:
+ case NS_CERT_TYPE_SSL_SERVER:
+ errstr = "Cert cannot be used for SSL.";
+ break;
+ case NS_CERT_TYPE_SSL_CA:
+ errstr = "Cert cannot be used as an SSL CA.";
+ break;
+ case NS_CERT_TYPE_EMAIL:
+ errstr = "Cert cannot be used for SMIME.";
+ break;
+ case NS_CERT_TYPE_EMAIL_CA:
+ errstr = "Cert cannot be used as an SMIME CA.";
+ break;
+ case NS_CERT_TYPE_OBJECT_SIGNING:
+ errstr = "Cert cannot be used for object signing.";
+ break;
+ case NS_CERT_TYPE_OBJECT_SIGNING_CA:
+ errstr = "Cert cannot be used as an object signing CA.";
+ break;
+ default:
+ errstr = "[unknown usage].";
+ break;
+ }
+ break;
+ case SEC_ERROR_UNKNOWN_ISSUER:
+ case SEC_ERROR_UNTRUSTED_ISSUER:
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ errstr = node->cert->issuerName;
+ break;
+ default:
+ break;
+ }
+ if (errstr) {
+ fprintf(stderr, " %s\n", errstr);
+ }
+ }
+ }
+}
+
+void
+SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
+ CERTCertificate *cert, PRBool checksig,
+ SECCertificateUsage certUsage, void *pinArg, PRBool verbose)
+{
+ SECU_printCertProblemsOnDate(outfile, handle, cert, checksig,
+ certUsage, pinArg, verbose, PR_Now());
+}
+
+SECStatus
+SECU_StoreCRL(PK11SlotInfo *slot, SECItem *derCrl, PRFileDesc *outFile,
+ PRBool ascii, char *url)
+{
+ PORT_Assert(derCrl != NULL);
+ if (!derCrl) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (outFile != NULL) {
+ if (ascii) {
+ PR_fprintf(outFile, "%s\n%s\n%s\n", NS_CRL_HEADER,
+ BTOA_DataToAscii(derCrl->data, derCrl->len),
+ NS_CRL_TRAILER);
+ } else {
+ if (PR_Write(outFile, derCrl->data, derCrl->len) != derCrl->len) {
+ return SECFailure;
+ }
+ }
+ }
+ if (slot) {
+ CERTSignedCrl *newCrl = PK11_ImportCRL(slot, derCrl, url,
+ SEC_CRL_TYPE, NULL, 0, NULL, 0);
+ if (newCrl != NULL) {
+ SEC_DestroyCrl(newCrl);
+ return SECSuccess;
+ }
+ return SECFailure;
+ }
+ if (!outFile && !slot) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+SECU_SignAndEncodeCRL(CERTCertificate *issuer, CERTSignedCrl *signCrl,
+ SECOidTag hashAlgTag, SignAndEncodeFuncExitStat *resCode)
+{
+ SECItem der;
+ SECKEYPrivateKey *caPrivateKey = NULL;
+ SECStatus rv;
+ PLArenaPool *arena;
+ SECOidTag algID;
+ void *dummy;
+
+ PORT_Assert(issuer != NULL && signCrl != NULL);
+ if (!issuer || !signCrl) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ arena = signCrl->arena;
+
+ caPrivateKey = PK11_FindKeyByAnyCert(issuer, NULL);
+ if (caPrivateKey == NULL) {
+ *resCode = noKeyFound;
+ return SECFailure;
+ }
+
+ algID = SEC_GetSignatureAlgorithmOidTag(caPrivateKey->keyType, hashAlgTag);
+ if (algID == SEC_OID_UNKNOWN) {
+ *resCode = noSignatureMatch;
+ rv = SECFailure;
+ goto done;
+ }
+
+ if (!signCrl->crl.signatureAlg.parameters.data) {
+ rv = SECOID_SetAlgorithmID(arena, &signCrl->crl.signatureAlg, algID, 0);
+ if (rv != SECSuccess) {
+ *resCode = failToEncode;
+ goto done;
+ }
+ }
+
+ der.len = 0;
+ der.data = NULL;
+ dummy = SEC_ASN1EncodeItem(arena, &der, &signCrl->crl,
+ SEC_ASN1_GET(CERT_CrlTemplate));
+ if (!dummy) {
+ *resCode = failToEncode;
+ rv = SECFailure;
+ goto done;
+ }
+
+ rv = SECU_DerSignDataCRL(arena, &signCrl->signatureWrap,
+ der.data, der.len, caPrivateKey, algID);
+ if (rv != SECSuccess) {
+ *resCode = failToSign;
+ goto done;
+ }
+
+ signCrl->derCrl = PORT_ArenaZNew(arena, SECItem);
+ if (signCrl->derCrl == NULL) {
+ *resCode = noMem;
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ rv = SECFailure;
+ goto done;
+ }
+
+ signCrl->derCrl->len = 0;
+ signCrl->derCrl->data = NULL;
+ dummy = SEC_ASN1EncodeItem(arena, signCrl->derCrl, signCrl,
+ SEC_ASN1_GET(CERT_SignedCrlTemplate));
+ if (!dummy) {
+ *resCode = failToEncode;
+ rv = SECFailure;
+ goto done;
+ }
+
+done:
+ SECKEY_DestroyPrivateKey(caPrivateKey);
+ return rv;
+}
+
+SECStatus
+SECU_CopyCRL(PLArenaPool *destArena, CERTCrl *destCrl, CERTCrl *srcCrl)
+{
+ void *dummy;
+ SECStatus rv = SECSuccess;
+ SECItem der;
+
+ PORT_Assert(destArena && srcCrl && destCrl);
+ if (!destArena || !srcCrl || !destCrl) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ der.len = 0;
+ der.data = NULL;
+ dummy = SEC_ASN1EncodeItem(destArena, &der, srcCrl,
+ SEC_ASN1_GET(CERT_CrlTemplate));
+ if (!dummy) {
+ return SECFailure;
+ }
+
+ rv = SEC_QuickDERDecodeItem(destArena, destCrl,
+ SEC_ASN1_GET(CERT_CrlTemplate), &der);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+
+ destCrl->arena = destArena;
+
+ return rv;
+}
+
+SECStatus
+SECU_DerSignDataCRL(PLArenaPool *arena, CERTSignedData *sd,
+ unsigned char *buf, int len, SECKEYPrivateKey *pk,
+ SECOidTag algID)
+{
+ SECItem it;
+ SECStatus rv;
+
+ it.data = 0;
+
+ /* XXX We should probably have some asserts here to make sure the key type
+ * and algID match
+ */
+
+ /* Sign input buffer */
+ rv = SEC_SignData(&it, buf, len, pk, algID);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ /* Fill out SignedData object */
+ PORT_Memset(sd, 0, sizeof(*sd));
+ sd->data.data = buf;
+ sd->data.len = len;
+ rv = SECITEM_CopyItem(arena, &sd->signature, &it);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ sd->signature.len <<= 3; /* convert to bit string */
+ rv = SECOID_SetAlgorithmID(arena, &sd->signatureAlgorithm, algID, 0);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+loser:
+ PORT_Free(it.data);
+ return rv;
+}
+
+#if 0
+
+/* we need access to the private function cert_FindExtension for this code to work */
+
+CERTAuthKeyID *
+SECU_FindCRLAuthKeyIDExten (PLArenaPool *arena, CERTSignedCrl *scrl)
+{
+ SECItem encodedExtenValue;
+ SECStatus rv;
+ CERTAuthKeyID *ret;
+ CERTCrl* crl;
+
+ if (!scrl) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ crl = &scrl->crl;
+
+ encodedExtenValue.data = NULL;
+ encodedExtenValue.len = 0;
+
+ rv = cert_FindExtension(crl->extensions, SEC_OID_X509_AUTH_KEY_ID,
+ &encodedExtenValue);
+ if ( rv != SECSuccess ) {
+ return (NULL);
+ }
+
+ ret = CERT_DecodeAuthKeyID (arena, &encodedExtenValue);
+
+ PORT_Free(encodedExtenValue.data);
+ encodedExtenValue.data = NULL;
+
+ return(ret);
+}
+
+#endif
+
+/*
+ * Find the issuer of a Crl. Use the authorityKeyID if it exists.
+ */
+CERTCertificate *
+SECU_FindCrlIssuer(CERTCertDBHandle *dbhandle, SECItem *subject,
+ CERTAuthKeyID *authorityKeyID, PRTime validTime)
+{
+ CERTCertificate *issuerCert = NULL;
+ CERTCertList *certList = NULL;
+ CERTCertTrust trust;
+
+ if (!subject) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ certList =
+ CERT_CreateSubjectCertList(NULL, dbhandle, subject,
+ validTime, PR_TRUE);
+ if (certList) {
+ CERTCertListNode *node = CERT_LIST_HEAD(certList);
+
+ /* XXX and authoritykeyid in the future */
+ while (!CERT_LIST_END(node, certList)) {
+ CERTCertificate *cert = node->cert;
+ /* check cert CERTCertTrust data is allocated, check cert
+ usage extension, check that cert has pkey in db. Select
+ the first (newest) user cert */
+ if (CERT_GetCertTrust(cert, &trust) == SECSuccess &&
+ CERT_CheckCertUsage(cert, KU_CRL_SIGN) == SECSuccess &&
+ CERT_IsUserCert(cert)) {
+
+ issuerCert = CERT_DupCertificate(cert);
+ break;
+ }
+ node = CERT_LIST_NEXT(node);
+ }
+ CERT_DestroyCertList(certList);
+ }
+ return (issuerCert);
+}
+
+/* Encodes and adds extensions to the CRL or CRL entries. */
+SECStatus
+SECU_EncodeAndAddExtensionValue(PLArenaPool *arena, void *extHandle,
+ void *value, PRBool criticality, int extenType,
+ EXTEN_EXT_VALUE_ENCODER EncodeValueFn)
+{
+ SECItem encodedValue;
+ SECStatus rv;
+
+ encodedValue.data = NULL;
+ encodedValue.len = 0;
+ do {
+ rv = (*EncodeValueFn)(arena, value, &encodedValue);
+ if (rv != SECSuccess)
+ break;
+
+ rv = CERT_AddExtension(extHandle, extenType, &encodedValue,
+ criticality, PR_TRUE);
+ if (rv != SECSuccess)
+ break;
+ } while (0);
+
+ return (rv);
+}
+
+CERTCertificate *
+SECU_FindCertByNicknameOrFilename(CERTCertDBHandle *handle,
+ char *name, PRBool ascii,
+ void *pwarg)
+{
+ CERTCertificate *the_cert;
+ the_cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
+ if (the_cert) {
+ return the_cert;
+ }
+ the_cert = PK11_FindCertFromNickname(name, pwarg);
+ if (!the_cert) {
+ /* Don't have a cert with name "name" in the DB. Try to
+ * open a file with such name and get the cert from there.*/
+ SECStatus rv;
+ SECItem item = { 0, NULL, 0 };
+ PRFileDesc *fd = PR_Open(name, PR_RDONLY, 0777);
+ if (!fd) {
+ return NULL;
+ }
+ rv = SECU_ReadDERFromFile(&item, fd, ascii, PR_FALSE);
+ PR_Close(fd);
+ if (rv != SECSuccess || !item.len) {
+ PORT_Free(item.data);
+ return NULL;
+ }
+ the_cert = CERT_NewTempCertificate(handle, &item,
+ NULL /* nickname */,
+ PR_FALSE /* isPerm */,
+ PR_TRUE /* copyDER */);
+ PORT_Free(item.data);
+ }
+ return the_cert;
+}
+
+/* Convert a SSL/TLS protocol version string into the respective numeric value
+ * defined by the SSL_LIBRARY_VERSION_* constants,
+ * while accepting a flexible set of case-insensitive identifiers.
+ *
+ * Caller must specify bufLen, allowing the function to operate on substrings.
+ */
+static SECStatus
+SECU_GetSSLVersionFromName(const char *buf, size_t bufLen, PRUint16 *version)
+{
+ if (!buf || !version) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (!PL_strncasecmp(buf, "ssl3", bufLen)) {
+ *version = SSL_LIBRARY_VERSION_3_0;
+ return SECSuccess;
+ }
+ if (!PL_strncasecmp(buf, "tls1.0", bufLen)) {
+ *version = SSL_LIBRARY_VERSION_TLS_1_0;
+ return SECSuccess;
+ }
+ if (!PL_strncasecmp(buf, "tls1.1", bufLen)) {
+ *version = SSL_LIBRARY_VERSION_TLS_1_1;
+ return SECSuccess;
+ }
+ if (!PL_strncasecmp(buf, "tls1.2", bufLen)) {
+ *version = SSL_LIBRARY_VERSION_TLS_1_2;
+ return SECSuccess;
+ }
+
+ if (!PL_strncasecmp(buf, "tls1.3", bufLen)) {
+ *version = SSL_LIBRARY_VERSION_TLS_1_3;
+ return SECSuccess;
+ }
+
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+}
+
+SECStatus
+SECU_ParseSSLVersionRangeString(const char *input,
+ const SSLVersionRange defaultVersionRange,
+ SSLVersionRange *vrange)
+{
+ const char *colonPos;
+ size_t colonIndex;
+ const char *maxStr;
+
+ if (!input || !vrange) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ // We don't support SSL2 any longer.
+ if (defaultVersionRange.min < SSL_LIBRARY_VERSION_3_0 ||
+ defaultVersionRange.max < SSL_LIBRARY_VERSION_3_0) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (!strcmp(input, ":")) {
+ /* special value, use default */
+ *vrange = defaultVersionRange;
+ return SECSuccess;
+ }
+
+ colonPos = strchr(input, ':');
+ if (!colonPos) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ colonIndex = colonPos - input;
+ maxStr = colonPos + 1;
+
+ if (!colonIndex) {
+ /* colon was first character, min version is empty */
+ vrange->min = defaultVersionRange.min;
+ } else {
+ PRUint16 version;
+ /* colonIndex is equivalent to the length of the min version substring */
+ if (SECU_GetSSLVersionFromName(input, colonIndex, &version) != SECSuccess) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ vrange->min = version;
+ }
+
+ if (!*maxStr) {
+ vrange->max = defaultVersionRange.max;
+ } else {
+ PRUint16 version;
+ /* if max version is empty, then maxStr points to the string terminator */
+ if (SECU_GetSSLVersionFromName(maxStr, strlen(maxStr), &version) !=
+ SECSuccess) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ vrange->max = version;
+ }
+
+ if (vrange->min > vrange->max) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+SECItem *
+SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
+{
+ int i = 0;
+ int byteval = 0;
+ int tmp = PORT_Strlen(str);
+
+ PORT_Assert(arena);
+ PORT_Assert(item);
+
+ if ((tmp % 2) != 0) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ item = SECITEM_AllocItem(arena, item, tmp / 2);
+ if (item == NULL) {
+ return NULL;
+ }
+
+ while (str[i]) {
+ if ((str[i] >= '0') && (str[i] <= '9')) {
+ tmp = str[i] - '0';
+ } else if ((str[i] >= 'a') && (str[i] <= 'f')) {
+ tmp = str[i] - 'a' + 10;
+ } else if ((str[i] >= 'A') && (str[i] <= 'F')) {
+ tmp = str[i] - 'A' + 10;
+ } else {
+ /* item is in arena and gets freed by the caller */
+ return NULL;
+ }
+
+ byteval = byteval * 16 + tmp;
+ if ((i % 2) != 0) {
+ item->data[i / 2] = byteval;
+ byteval = 0;
+ }
+ i++;
+ }
+
+ return item;
+}
diff --git a/security/nss/cmd/lib/secutil.h b/security/nss/cmd/lib/secutil.h
new file mode 100644
index 000000000..571615daa
--- /dev/null
+++ b/security/nss/cmd/lib/secutil.h
@@ -0,0 +1,432 @@
+/* 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 _SEC_UTIL_H_
+#define _SEC_UTIL_H_
+
+#include "seccomon.h"
+#include "secitem.h"
+#include "secport.h"
+#include "prerror.h"
+#include "base64.h"
+#include "key.h"
+#include "secpkcs7.h"
+#include "secasn1.h"
+#include "secder.h"
+#include <stdio.h>
+
+#include "basicutil.h"
+#include "sslerr.h"
+#include "sslt.h"
+
+#define SEC_CT_PRIVATE_KEY "private-key"
+#define SEC_CT_PUBLIC_KEY "public-key"
+#define SEC_CT_CERTIFICATE "certificate"
+#define SEC_CT_CERTIFICATE_REQUEST "certificate-request"
+#define SEC_CT_CERTIFICATE_ID "certificate-identity"
+#define SEC_CT_PKCS7 "pkcs7"
+#define SEC_CT_CRL "crl"
+#define SEC_CT_NAME "name"
+
+#define NS_CERTREQ_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----"
+#define NS_CERTREQ_TRAILER "-----END NEW CERTIFICATE REQUEST-----"
+
+#define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----"
+#define NS_CERT_TRAILER "-----END CERTIFICATE-----"
+
+#define NS_CRL_HEADER "-----BEGIN CRL-----"
+#define NS_CRL_TRAILER "-----END CRL-----"
+
+#define SECU_Strerror PORT_ErrorToString
+
+typedef struct {
+ enum {
+ PW_NONE = 0,
+ PW_FROMFILE = 1,
+ PW_PLAINTEXT = 2,
+ PW_EXTERNAL = 3
+ } source;
+ char *data;
+} secuPWData;
+
+/*
+** Change a password on a token, or initialize a token with a password
+** if it does not already have one.
+** Use passwd to send the password in plaintext, pwFile to specify a
+** file containing the password, or NULL for both to prompt the user.
+*/
+SECStatus SECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile);
+
+/*
+** Change a password on a token, or initialize a token with a password
+** if it does not already have one.
+** In this function, you can specify both the old and new passwords
+** as either a string or file. NOTE: any you don't specify will
+** be prompted for
+*/
+SECStatus SECU_ChangePW2(PK11SlotInfo *slot, char *oldPass, char *newPass,
+ char *oldPwFile, char *newPwFile);
+
+/* These were stolen from the old sec.h... */
+/*
+** Check a password for legitimacy. Passwords must be at least 8
+** characters long and contain one non-alphabetic. Return DSTrue if the
+** password is ok, DSFalse otherwise.
+*/
+extern PRBool SEC_CheckPassword(char *password);
+
+/*
+** Blind check of a password. Complement to SEC_CheckPassword which
+** ignores length and content type, just retuning DSTrue is the password
+** exists, DSFalse if NULL
+*/
+extern PRBool SEC_BlindCheckPassword(char *password);
+
+/*
+** Get a password.
+** First prompt with "msg" on "out", then read the password from "in".
+** The password is then checked using "chkpw".
+*/
+extern char *SEC_GetPassword(FILE *in, FILE *out, char *msg,
+ PRBool (*chkpw)(char *));
+
+char *SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg);
+
+char *SECU_GetPasswordString(void *arg, char *prompt);
+
+/*
+** Write a dongle password.
+** Uses MD5 to hash constant system data (hostname, etc.), and then
+** creates RC4 key to encrypt a password "pw" into a file "fd".
+*/
+extern SECStatus SEC_WriteDongleFile(int fd, char *pw);
+
+/*
+** Get a dongle password.
+** Uses MD5 to hash constant system data (hostname, etc.), and then
+** creates RC4 key to decrypt and return a password from file "fd".
+*/
+extern char *SEC_ReadDongleFile(int fd);
+
+/* End stolen headers */
+
+/* Just sticks the two strings together with a / if needed */
+char *SECU_AppendFilenameToDir(char *dir, char *filename);
+
+/* Returns result of PR_GetEnvSecure("SSL_DIR") or NULL */
+extern char *SECU_DefaultSSLDir(void);
+
+/*
+** Should be called once during initialization to set the default
+** directory for looking for cert.db, key.db, and cert-nameidx.db files
+** Removes trailing '/' in 'base'
+** If 'base' is NULL, defaults to set to .netscape in home directory.
+*/
+extern char *SECU_ConfigDirectory(const char *base);
+
+/*
+** Basic callback function for SSL_GetClientAuthDataHook
+*/
+extern int
+SECU_GetClientAuthData(void *arg, PRFileDesc *fd,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey);
+
+extern PRBool SECU_GetWrapEnabled(void);
+extern void SECU_EnableWrap(PRBool enable);
+
+extern PRBool SECU_GetUtf8DisplayEnabled(void);
+extern void SECU_EnableUtf8Display(PRBool enable);
+
+/* revalidate the cert and print information about cert verification
+ * failure at time == now */
+extern void
+SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
+ CERTCertificate *cert, PRBool checksig,
+ SECCertificateUsage certUsage, void *pinArg, PRBool verbose);
+
+/* revalidate the cert and print information about cert verification
+ * failure at specified time */
+extern void
+SECU_printCertProblemsOnDate(FILE *outfile, CERTCertDBHandle *handle,
+ CERTCertificate *cert, PRBool checksig, SECCertificateUsage certUsage,
+ void *pinArg, PRBool verbose, PRTime datetime);
+
+/* print out CERTVerifyLog info. */
+extern void
+SECU_displayVerifyLog(FILE *outfile, CERTVerifyLog *log,
+ PRBool verbose);
+
+/* Read in a DER from a file, may be ascii */
+extern SECStatus
+SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii,
+ PRBool warnOnPrivateKeyInAsciiFile);
+
+/* Print integer value and hex */
+extern void SECU_PrintInteger(FILE *out, const SECItem *i, const char *m,
+ int level);
+
+/* Print ObjectIdentifier symbolically */
+extern SECOidTag SECU_PrintObjectID(FILE *out, const SECItem *oid,
+ const char *m, int level);
+
+/* Print AlgorithmIdentifier symbolically */
+extern void SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m,
+ int level);
+
+/*
+ * Format and print the UTC Time "t". If the tag message "m" is not NULL,
+ * do indent formatting based on "level" and add a newline afterward;
+ * otherwise just print the formatted time string only.
+ */
+extern void SECU_PrintUTCTime(FILE *out, const SECItem *t, const char *m,
+ int level);
+
+/*
+ * Format and print the Generalized Time "t". If the tag message "m"
+ * is not NULL, * do indent formatting based on "level" and add a newline
+ * afterward; otherwise just print the formatted time string only.
+ */
+extern void SECU_PrintGeneralizedTime(FILE *out, const SECItem *t,
+ const char *m, int level);
+
+/*
+ * Format and print the UTC or Generalized Time "t". If the tag message
+ * "m" is not NULL, do indent formatting based on "level" and add a newline
+ * afterward; otherwise just print the formatted time string only.
+ */
+extern void SECU_PrintTimeChoice(FILE *out, const SECItem *t, const char *m,
+ int level);
+
+/* callback for listing certs through pkcs11 */
+extern SECStatus SECU_PrintCertNickname(CERTCertListNode *cert, void *data);
+
+/* Dump all certificate nicknames in a database */
+extern SECStatus
+SECU_PrintCertificateNames(CERTCertDBHandle *handle, PRFileDesc *out,
+ PRBool sortByName, PRBool sortByTrust);
+
+/* See if nickname already in database. Return 1 true, 0 false, -1 error */
+int SECU_CheckCertNameExists(CERTCertDBHandle *handle, char *nickname);
+
+/* Dump contents of cert req */
+extern int SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m,
+ int level);
+
+/* Dump contents of certificate */
+extern int SECU_PrintCertificate(FILE *out, const SECItem *der, const char *m,
+ int level);
+
+extern int SECU_PrintCertificateBasicInfo(FILE *out, const SECItem *der, const char *m,
+ int level);
+
+extern int SECU_PrintDumpDerIssuerAndSerial(FILE *out, SECItem *der, char *m,
+ int level);
+
+/* Dump contents of a DER certificate name (issuer or subject) */
+extern int SECU_PrintDERName(FILE *out, SECItem *der, const char *m, int level);
+
+/* print trust flags on a cert */
+extern void SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m,
+ int level);
+
+extern int SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m,
+ int level);
+
+#ifdef HAVE_EPV_TEMPLATE
+/* Dump contents of private key */
+extern int SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level);
+#endif
+
+/* Dump contents of an RSA public key */
+extern void SECU_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level);
+
+/* Dump contents of a DSA public key */
+extern void SECU_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level);
+
+/* Print the MD5 and SHA1 fingerprints of a cert */
+extern int SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m,
+ int level);
+
+/* Pretty-print any PKCS7 thing */
+extern int SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m,
+ int level);
+
+/* Init PKCS11 stuff */
+extern SECStatus SECU_PKCS11Init(PRBool readOnly);
+
+/* Dump contents of signed data */
+extern int SECU_PrintSignedData(FILE *out, SECItem *der, const char *m,
+ int level, SECU_PPFunc inner);
+
+/* Dump contents of signed data, excluding the signature */
+extern int SECU_PrintSignedContent(FILE *out, SECItem *der, char *m, int level,
+ SECU_PPFunc inner);
+
+/* Print cert data and its trust flags */
+extern SECStatus SEC_PrintCertificateAndTrust(CERTCertificate *cert,
+ const char *label,
+ CERTCertTrust *trust);
+
+extern int SECU_PrintCrl(FILE *out, SECItem *der, char *m, int level);
+
+extern void
+SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level);
+
+extern void SECU_PrintString(FILE *out, const SECItem *si, const char *m,
+ int level);
+extern void SECU_PrintAny(FILE *out, const SECItem *i, const char *m, int level);
+
+extern void SECU_PrintPolicy(FILE *out, SECItem *value, char *msg, int level);
+extern void SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value,
+ char *msg, int level);
+
+extern void SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
+ char *msg, int level);
+
+extern void SECU_PrintNameQuotesOptional(FILE *out, CERTName *name,
+ const char *msg, int level,
+ PRBool quotes);
+extern void SECU_PrintName(FILE *out, CERTName *name, const char *msg,
+ int level);
+extern void SECU_PrintRDN(FILE *out, CERTRDN *rdn, const char *msg, int level);
+
+#ifdef SECU_GetPassword
+/* Convert a High public Key to a Low public Key */
+extern SECKEYLowPublicKey *SECU_ConvHighToLow(SECKEYPublicKey *pubHighKey);
+#endif
+
+extern char *SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg);
+
+extern SECStatus DER_PrettyPrint(FILE *out, const SECItem *it, PRBool raw);
+
+extern char *SECU_SECModDBName(void);
+
+/* Fetch and register an oid if it hasn't been done already */
+extern void SECU_cert_fetchOID(SECOidTag *data, const SECOidData *src);
+
+extern SECStatus SECU_RegisterDynamicOids(void);
+
+/* Identifies hash algorithm tag by its string representation. */
+extern SECOidTag SECU_StringToSignatureAlgTag(const char *alg);
+
+/* Store CRL in output file or pk11 db. Also
+ * encodes with base64 and exports to file if ascii flag is set
+ * and file is not NULL. */
+extern SECStatus SECU_StoreCRL(PK11SlotInfo *slot, SECItem *derCrl,
+ PRFileDesc *outFile, PRBool ascii, char *url);
+
+/*
+** DER sign a single block of data using private key encryption and the
+** MD5 hashing algorithm. This routine first computes a digital signature
+** using SEC_SignData, then wraps it with an CERTSignedData and then der
+** encodes the result.
+** "arena" is the memory arena to use to allocate data from
+** "sd" returned CERTSignedData
+** "result" the final der encoded data (memory is allocated)
+** "buf" the input data to sign
+** "len" the amount of data to sign
+** "pk" the private key to encrypt with
+*/
+extern SECStatus SECU_DerSignDataCRL(PLArenaPool *arena, CERTSignedData *sd,
+ unsigned char *buf, int len,
+ SECKEYPrivateKey *pk, SECOidTag algID);
+
+typedef enum {
+ noKeyFound = 1,
+ noSignatureMatch = 2,
+ failToEncode = 3,
+ failToSign = 4,
+ noMem = 5
+} SignAndEncodeFuncExitStat;
+
+extern SECStatus
+SECU_SignAndEncodeCRL(CERTCertificate *issuer, CERTSignedCrl *signCrl,
+ SECOidTag hashAlgTag, SignAndEncodeFuncExitStat *resCode);
+
+extern SECStatus
+SECU_CopyCRL(PLArenaPool *destArena, CERTCrl *destCrl, CERTCrl *srcCrl);
+
+/*
+** Finds the crl Authority Key Id extension. Returns NULL if no such extension
+** was found.
+*/
+CERTAuthKeyID *
+SECU_FindCRLAuthKeyIDExten(PLArenaPool *arena, CERTSignedCrl *crl);
+
+/*
+ * Find the issuer of a crl. Cert usage should be checked before signing a crl.
+ */
+CERTCertificate *
+SECU_FindCrlIssuer(CERTCertDBHandle *dbHandle, SECItem *subject,
+ CERTAuthKeyID *id, PRTime validTime);
+
+/* call back function used in encoding of an extension. Called from
+ * SECU_EncodeAndAddExtensionValue */
+typedef SECStatus (*EXTEN_EXT_VALUE_ENCODER)(PLArenaPool *extHandleArena,
+ void *value, SECItem *encodedValue);
+
+/* Encodes and adds extensions to the CRL or CRL entries. */
+SECStatus
+SECU_EncodeAndAddExtensionValue(PLArenaPool *arena, void *extHandle,
+ void *value, PRBool criticality, int extenType,
+ EXTEN_EXT_VALUE_ENCODER EncodeValueFn);
+
+/* Caller ensures that dst is at least item->len*2+1 bytes long */
+void
+SECU_SECItemToHex(const SECItem *item, char *dst);
+
+/* Requires 0x prefix. Case-insensitive. Will do in-place replacement if
+ * successful */
+SECStatus
+SECU_SECItemHexStringToBinary(SECItem *srcdest);
+
+/* Parse a version range string, with "min" and "max" version numbers,
+ * separated by colon (":"), and return the result in vr and v2.
+ *
+ * Both min and max values are optional.
+ * The following syntax is used to specify the enabled protocol versions:
+ * A string with only a max value is expected as ":{max}",
+ * and all implemented versions less than or equal to max will be enabled.
+ * A string with only a min value is expected as "{min}:",
+ * and all implemented versions greater than or equal to min will be enabled.
+ * A string consisting of a colon only means "all versions enabled".
+ *
+ * In order to avoid a link dependency from libsectool to libssl,
+ * the caller must provide the desired default values for the min/max values,
+ * by providing defaultVersionRange (which can be obtained from libssl by
+ * calling SSL_VersionRangeGetSupported).
+ */
+SECStatus
+SECU_ParseSSLVersionRangeString(const char *input,
+ const SSLVersionRange defaultVersionRange,
+ SSLVersionRange *vrange);
+/*
+** Read a hex string into a SecItem.
+*/
+extern SECItem *SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item,
+ const char *str);
+
+/*
+ *
+ * Error messaging
+ *
+ */
+
+void printflags(char *trusts, unsigned int flags);
+
+#if !defined(XP_UNIX) && !defined(XP_OS2)
+extern int ffs(unsigned int i);
+#endif
+
+/* Finds certificate by searching it in the DB or by examinig file
+ * in the local directory. */
+CERTCertificate *
+SECU_FindCertByNicknameOrFilename(CERTCertDBHandle *handle,
+ char *name, PRBool ascii,
+ void *pwarg);
+#include "secerr.h"
+#include "sslerr.h"
+
+#endif /* _SEC_UTIL_H_ */
diff --git a/security/nss/cmd/libpkix/Makefile b/security/nss/cmd/libpkix/Makefile
new file mode 100755
index 000000000..1de5ef269
--- /dev/null
+++ b/security/nss/cmd/libpkix/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
+
diff --git a/security/nss/cmd/libpkix/config.mk b/security/nss/cmd/libpkix/config.mk
new file mode 100644
index 000000000..672f6ff87
--- /dev/null
+++ b/security/nss/cmd/libpkix/config.mk
@@ -0,0 +1,9 @@
+#
+# 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/.
+
+TARGETS = $(LIBRARY)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+PROGRAM =
diff --git a/security/nss/cmd/libpkix/manifest.mn b/security/nss/cmd/libpkix/manifest.mn
new file mode 100755
index 000000000..4f232a510
--- /dev/null
+++ b/security/nss/cmd/libpkix/manifest.mn
@@ -0,0 +1,11 @@
+#
+# 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/.
+
+PKIX_DEPTH = .
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../..
+
+DIRS = testutil pkix_pl pkix sample_apps perf pkixutil \
+ $(NULL)
diff --git a/security/nss/cmd/libpkix/perf/Makefile b/security/nss/cmd/libpkix/perf/Makefile
new file mode 100755
index 000000000..b7241027d
--- /dev/null
+++ b/security/nss/cmd/libpkix/perf/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
+
diff --git a/security/nss/cmd/libpkix/perf/libpkix_buildthreads.c b/security/nss/cmd/libpkix/perf/libpkix_buildthreads.c
new file mode 100644
index 000000000..4b8d43811
--- /dev/null
+++ b/security/nss/cmd/libpkix/perf/libpkix_buildthreads.c
@@ -0,0 +1,337 @@
+/* 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/. */
+/*
+ * libpkixBuildThreads.c
+ *
+ * libpkix Builder Performance Evaluation application (multi-threaded)
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "secutil.h"
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "nss.h"
+
+#include "pkix.h"
+#include "pkix_tools.h"
+#include "pkix_pl_cert.h"
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+#undef pkixTempResult
+#define PERF_DECREF(obj) \
+ { \
+ PKIX_Error *pkixTempResult = NULL; \
+ if (obj) { \
+ pkixTempResult = PKIX_PL_Object_DecRef((PKIX_PL_Object *)(obj), plContext); \
+ obj = NULL; \
+ } \
+ }
+
+static void finish(char *message, int code);
+
+typedef struct ThreadDataStr tData;
+
+struct ThreadDataStr {
+ CERTCertificate *anchor;
+ char *eecertName;
+ PRIntervalTime duration;
+ CERTCertDBHandle *handle;
+ PRUint32 iterations;
+};
+
+#define PKIX_LOGGER_ON 1
+
+#ifdef PKIX_LOGGER_ON
+
+char *logLevels[] = {
+ "None",
+ "Fatal Error",
+ "Error",
+ "Warning",
+ "Debug",
+ "Trace"
+};
+
+static PKIX_Error *
+loggerCallback(
+ PKIX_Logger *logger,
+ PKIX_PL_String *message,
+ PKIX_UInt32 logLevel,
+ PKIX_ERRORCLASS logComponent,
+ void *plContext)
+{
+ char *msg = NULL;
+ static int callCount = 0;
+
+ msg = PKIX_String2ASCII(message, plContext);
+ printf("Logging %s (%s): %s\n",
+ logLevels[logLevel],
+ PKIX_ERRORCLASSNAMES[logComponent],
+ msg);
+ PR_Free((void *)msg);
+
+ return (NULL);
+}
+
+#endif /* PKIX_LOGGER_ON */
+
+static void
+ThreadEntry(void *data)
+{
+ tData *tdata = (tData *)data;
+ PRIntervalTime duration = tdata->duration;
+ PRIntervalTime start = PR_IntervalNow();
+
+ PKIX_List *anchors = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ CERTCertificate *nsseecert;
+ PKIX_PL_Cert *eeCert = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_List *certStores = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_PL_Date *nowDate = NULL;
+ void *state = NULL; /* only relevant with non-blocking I/O */
+ void *nbioContext = NULL; /* only relevant with non-blocking I/O */
+
+ PR_ASSERT(duration);
+ if (!duration) {
+ return;
+ }
+
+ do {
+
+ /* libpkix code */
+
+ /* keep more update time, testing cache */
+ PKIX_PL_Date_Create_UTCTime(NULL, &nowDate, plContext);
+
+ /* CertUsage is 0x10 and no NSS arena */
+ /* We haven't determined how we obtain the value of wincx */
+
+ nsseecert = CERT_FindCertByNicknameOrEmailAddr(tdata->handle,
+ tdata->eecertName);
+ if (!nsseecert)
+ finish("Unable to find eecert.\n", 1);
+
+ pkix_pl_Cert_CreateWithNSSCert(nsseecert, &eeCert, plContext);
+
+ PKIX_List_Create(&anchors, plContext);
+
+ /*
+ * This code is retired.
+ * pkix_pl_Cert_CreateWithNSSCert
+ * (tdata->anchor, &anchorCert, NULL);
+ * PKIX_TrustAnchor_CreateWithCert(anchorCert, &anchor, NULL);
+ * PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, NULL);
+ */
+
+ PKIX_ProcessingParams_Create(anchors, &procParams, plContext);
+
+ PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_TRUE, plContext);
+
+ PKIX_ProcessingParams_SetDate(procParams, nowDate, plContext);
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_ComCertSelParams_Create(&certSelParams, plContext);
+
+ PKIX_ComCertSelParams_SetCertificate(certSelParams, eeCert, plContext);
+
+ PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext);
+
+ PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext);
+
+ PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext);
+
+ PKIX_PL_Pk11CertStore_Create(&certStore, plContext);
+
+ PKIX_List_Create(&certStores, plContext);
+ PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore, plContext);
+ PKIX_ProcessingParams_SetCertStores(procParams, certStores, plContext);
+
+ PKIX_BuildChain(procParams,
+ &nbioContext,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+
+ /*
+ * As long as we use only CertStores with blocking I/O, we
+ * know we must be done at this point.
+ */
+
+ if (!buildResult) {
+ (void)fprintf(stderr, "libpkix BuildChain failed.\n");
+ PORT_Assert(0);
+ return;
+ }
+
+ tdata->iterations++;
+
+ PERF_DECREF(nowDate);
+ PERF_DECREF(anchors);
+ PERF_DECREF(procParams);
+ PERF_DECREF(buildResult);
+ PERF_DECREF(certStore);
+ PERF_DECREF(certStores);
+ PERF_DECREF(certSelParams);
+ PERF_DECREF(certSelector);
+ PERF_DECREF(eeCert);
+
+ } while ((PR_IntervalNow() - start) < duration);
+}
+
+static void
+Test(
+ CERTCertificate *anchor,
+ char *eecertName,
+ PRIntervalTime duration,
+ CERTCertDBHandle *handle,
+ PRUint32 threads)
+{
+ tData data;
+ tData **alldata;
+ PRIntervalTime starttime, endtime, elapsed;
+ PRUint32 msecs;
+ float total = 0;
+ PRThread **pthreads = NULL;
+ PRUint32 i = 0;
+
+ data.duration = duration;
+ data.anchor = anchor;
+ data.eecertName = eecertName;
+ data.handle = handle;
+
+ data.iterations = 0;
+
+ starttime = PR_IntervalNow();
+ pthreads = (PRThread **)PR_Malloc(threads * sizeof(PRThread *));
+ alldata = (tData **)PR_Malloc(threads * sizeof(tData *));
+ for (i = 0; i < threads; i++) {
+ alldata[i] = (tData *)PR_Malloc(sizeof(tData));
+ *alldata[i] = data;
+ pthreads[i] =
+ PR_CreateThread(PR_USER_THREAD,
+ ThreadEntry,
+ (void *)alldata[i],
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ }
+
+ for (i = 0; i < threads; i++) {
+ tData *args = alldata[i];
+ PR_JoinThread(pthreads[i]);
+ total += args->iterations;
+ PR_Free((void *)args);
+ }
+
+ PR_Free((void *)pthreads);
+ PR_Free((void *)alldata);
+ endtime = PR_IntervalNow();
+
+ endtime = PR_IntervalNow();
+ elapsed = endtime - starttime;
+ msecs = PR_IntervalToMilliseconds(elapsed);
+ total /= msecs;
+ total *= 1000;
+ (void)fprintf(stdout, "%f operations per second.\n", total);
+}
+
+static void
+finish(char *message, int code)
+{
+ (void)printf(message);
+ exit(code);
+}
+
+static void
+usage(char *progname)
+{
+ (void)printf("Usage : %s <-d certStoreDirectory> <duration> <threads> "
+ "<anchorNickname> <eecertNickname>\n\n",
+ progname);
+ finish("", 0);
+}
+
+int
+libpkix_buildthreads(int argc, char **argv)
+{
+ CERTCertDBHandle *handle = NULL;
+ CERTCertificate *eecert = NULL;
+ PRIntervalTime duration = PR_SecondsToInterval(1);
+ PRUint32 threads = 1;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ PKIX_Logger *logger = NULL;
+ void *wincx = NULL;
+
+ /* if (argc != 5) -- when TrustAnchor used to be on command line */
+ if (argc != 4) {
+ usage(argv[0]);
+ }
+ if (atoi(argv[1]) > 0) {
+ duration = PR_SecondsToInterval(atoi(argv[1]));
+ }
+ if (atoi(argv[2]) > 0) {
+ threads = atoi(argv[2]);
+ }
+
+ PKIX_PL_NssContext_Create(certificateUsageEmailSigner, PKIX_FALSE,
+ NULL, &plContext);
+
+ handle = CERT_GetDefaultCertDB();
+ PR_ASSERT(handle);
+
+#ifdef PKIX_LOGGER_ON
+
+ /* set logger to log trace and up */
+ PKIX_SetLoggers(NULL, plContext);
+ PKIX_Logger_Create(loggerCallback, NULL, &logger, plContext);
+ PKIX_Logger_SetMaxLoggingLevel(logger, PKIX_LOGGER_LEVEL_WARNING, plContext);
+ PKIX_AddLogger(logger, plContext);
+
+#endif /* PKIX_LOGGER_ON */
+
+ /*
+ * This code is retired
+ * anchor = CERT_FindCertByNicknameOrEmailAddr(handle, argv[3]);
+ * if (!anchor) finish("Unable to find anchor.\n", 1);
+ *
+ * eecert = CERT_FindCertByNicknameOrEmailAddr(handle, argv[4]);
+
+ * if (!eecert) finish("Unable to find eecert.\n", 1);
+ *
+ * Test(anchor, eecert, duration, threads);
+ */
+
+ Test(NULL, argv[3], duration, handle, threads);
+
+ PERF_DECREF(logger);
+
+ PKIX_Shutdown(plContext);
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/perf/manifest.mn b/security/nss/cmd/libpkix/perf/manifest.mn
new file mode 100755
index 000000000..005c96caa
--- /dev/null
+++ b/security/nss/cmd/libpkix/perf/manifest.mn
@@ -0,0 +1,21 @@
+#
+# 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/.
+
+PKIX_DEPTH = ..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = libpkix_buildthreads.c \
+ nss_threads.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixtoolperf
+
+SOURCE_LIB_DIR = $(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/perf/nss_threads.c b/security/nss/cmd/libpkix/perf/nss_threads.c
new file mode 100644
index 000000000..202f128b6
--- /dev/null
+++ b/security/nss/cmd/libpkix/perf/nss_threads.c
@@ -0,0 +1,158 @@
+/* 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/. */
+/*
+ * nssThreads.c
+ *
+ * NSS Performance Evaluation application (multi-threaded)
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "secutil.h"
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "nss.h"
+
+typedef struct ThreadDataStr tData;
+
+struct ThreadDataStr {
+ CERTCertificate* cert;
+ PRIntervalTime duration;
+ PRUint32 iterations;
+};
+
+static void
+ThreadEntry(void* data)
+{
+ tData* tdata = (tData*)data;
+ PRIntervalTime duration = tdata->duration;
+ PRTime now = PR_Now();
+ PRIntervalTime start = PR_IntervalNow();
+
+ PR_ASSERT(duration);
+ if (!duration) {
+ return;
+ }
+ do {
+ SECStatus rv = CERT_VerifyCertificate(CERT_GetDefaultCertDB(),
+ tdata->cert,
+ PR_TRUE,
+ certificateUsageEmailSigner,
+ now,
+ NULL,
+ NULL,
+ NULL);
+ if (rv != SECSuccess) {
+ (void)fprintf(stderr, "Validation failed.\n");
+ PORT_Assert(0);
+ return;
+ }
+ tdata->iterations++;
+ } while ((PR_IntervalNow() - start) < duration);
+}
+
+static void
+Test(CERTCertificate* cert, PRIntervalTime duration, PRUint32 threads)
+{
+ tData data;
+ tData** alldata;
+ PRIntervalTime starttime, endtime, elapsed;
+ PRUint32 msecs;
+ float total = 0;
+ PRThread** pthreads = NULL;
+ PRUint32 i = 0;
+
+ data.duration = duration;
+ data.cert = cert;
+ data.iterations = 0;
+
+ starttime = PR_IntervalNow();
+ pthreads = (PRThread**)PR_Malloc(threads * sizeof(PRThread*));
+ alldata = (tData**)PR_Malloc(threads * sizeof(tData*));
+ for (i = 0; i < threads; i++) {
+ alldata[i] = (tData*)PR_Malloc(sizeof(tData));
+ *alldata[i] = data;
+ pthreads[i] =
+ PR_CreateThread(PR_USER_THREAD,
+ ThreadEntry,
+ (void*)alldata[i],
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ }
+ for (i = 0; i < threads; i++) {
+ tData* args = alldata[i];
+ PR_JoinThread(pthreads[i]);
+ total += args->iterations;
+ PR_Free((void*)args);
+ }
+ PR_Free((void*)pthreads);
+ PR_Free((void*)alldata);
+ endtime = PR_IntervalNow();
+
+ endtime = PR_IntervalNow();
+ elapsed = endtime - starttime;
+ msecs = PR_IntervalToMilliseconds(elapsed);
+ total /= msecs;
+ total *= 1000;
+ (void)fprintf(stdout, "%f operations per second.\n", total);
+}
+
+static void
+finish(char* message, int code)
+{
+ (void)printf(message);
+ exit(code);
+}
+
+static void
+usage(char* progname)
+{
+ (void)printf("Usage : %s <duration> <threads> <certnickname>\n\n",
+ progname);
+ finish("", 0);
+}
+
+int
+nss_threads(int argc, char** argv)
+{
+ SECStatus rv = SECSuccess;
+ CERTCertDBHandle* handle = NULL;
+ CERTCertificate* cert = NULL;
+ PRIntervalTime duration = PR_SecondsToInterval(1);
+ PRUint32 threads = 1;
+ if (argc != 4) {
+ usage(argv[0]);
+ }
+ if (atoi(argv[1]) > 0) {
+ duration = PR_SecondsToInterval(atoi(argv[1]));
+ }
+ if (atoi(argv[2]) > 0) {
+ threads = atoi(argv[2]);
+ }
+
+ handle = CERT_GetDefaultCertDB();
+ PR_ASSERT(handle);
+ cert = CERT_FindCertByNicknameOrEmailAddr(handle, argv[3]);
+ if (!cert) {
+ finish("Unable to find certificate.\n", 1);
+ }
+ Test(cert, duration, threads);
+
+ CERT_DestroyCertificate(cert);
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/Makefile b/security/nss/cmd/libpkix/pkix/Makefile
new file mode 100755
index 000000000..ab4ffbda5
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
+
diff --git a/security/nss/cmd/libpkix/pkix/certsel/Makefile b/security/nss/cmd/libpkix/pkix/certsel/Makefile
new file mode 100755
index 000000000..09ca5f1c6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/certsel/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/security/nss/cmd/libpkix/pkix/certsel/manifest.mn b/security/nss/cmd/libpkix/pkix/certsel/manifest.mn
new file mode 100755
index 000000000..2e8198cb3
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/certsel/manifest.mn
@@ -0,0 +1,21 @@
+#
+# 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/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_certselector.c \
+ test_comcertselparams.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtoolcertsel
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/certsel/test_certselector.c b/security/nss/cmd/libpkix/pkix/certsel/test_certselector.c
new file mode 100644
index 000000000..cbe773779
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/certsel/test_certselector.c
@@ -0,0 +1,1683 @@
+/* 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/. */
+/*
+ * test_certselector.c
+ *
+ * Test Cert Selector
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TEST_CERTSELECTOR_KEYUSAGE_NUM_CERTS 5
+#define PKIX_TEST_CERTSELECTOR_EXTKEYUSAGE_NUM_CERTS 2
+#define PKIX_TEST_CERTSELECTOR_CERTVALID_NUM_CERTS 2
+#define PKIX_TEST_CERTSELECTOR_ISSUER_NUM_CERTS 4
+#define PKIX_TEST_CERTSELECTOR_SERIALNUMBER_NUM_CERTS 1
+
+static void *plContext = NULL;
+
+/*
+ * The first three certs are used to obtain policies to test
+ * policy matching. Changing the table could break tests.
+ */
+static char *certList[] = {
+#define POLICY1CERT 0
+ "GoodCACert.crt",
+#define ANYPOLICYCERT 1
+ "anyPolicyCACert.crt",
+#define POLICY2CERT 2
+ "PoliciesP12CACert.crt",
+#define SUBJECTCERT 3
+ "PoliciesP3CACert.crt",
+ "PoliciesP1234CACert.crt",
+ "pathLenConstraint0CACert.crt",
+ "pathLenConstraint1CACert.crt",
+ "pathLenConstraint6CACert.crt",
+ "TrustAnchorRootCertificate.crt",
+ "GoodsubCACert.crt",
+ "AnyPolicyTest14EE.crt",
+ "UserNoticeQualifierTest16EE.crt"
+};
+#define NUMCERTS (sizeof(certList) / sizeof(certList[0]))
+
+/*
+ * Following are Certs values for NameConstraints tests
+ *
+ * Cert0:nameConstraintsDN1subCA1Cert.crt:
+ * Subject:CN=nameConstraints DN1 subCA1,OU=permittedSubtree1,
+ * O=Test Certificates,C=US
+ * Permitted Name:(OU=permittedSubtree2,OU=permittedSubtree1,
+ * O=Test Certificates,C=US)
+ * Excluded Name: (EMPTY)
+ * Cert1:nameConstraintsDN3subCA2Cert.crt:
+ * Subject:CN=nameConstraints DN3 subCA2,O=Test Certificates,C=US
+ * Permitted Name:(O=Test Certificates,C=US)
+ * Excluded Name:(EMPTY)
+ * Cert2:nameConstraintsDN2CACert.crt
+ * Subject:CN=nameConstraints DN2 CA,O=Test Certificates,C=US
+ * Permitted Name:(OU=permittedSubtree1,O=Test Certificates,C=US,
+ * OU=permittedSubtree2,O=Test Certificates,C=US)
+ * Excluded Name:(EMPTY)
+ * Cert3:nameConstraintsDN3subCA1Cert.crt
+ * Subject:CN=nameConstraints DN3 subCA1,O=Test Certificates,C=US
+ * Permitted Name:(EMPTY)
+ * Excluded Name:(OU=excludedSubtree2,O=Test Certificates,C=US)
+ * Cert4:nameConstraintsDN4CACert.crt
+ * Subject:CN=nameConstraints DN4 CA,O=Test Certificates,C=US
+ * Permitted Name:(EMPTY)
+ * Excluded Name:(OU=excludedSubtree1,O=Test Certificates,C=US,
+ * OU=excludedSubtree2,O=Test Certificates,C=US)
+ * Cert5:nameConstraintsDN5CACert.crt
+ * Subject:CN=nameConstraints DN5 CA,O=Test Certificates,C=US
+ * Permitted Name:(OU=permittedSubtree1,O=Test Certificates,C=US)
+ * Excluded Name:(OU=excludedSubtree1,OU=permittedSubtree1,
+ * O=Test Certificates,C=US)
+ * Cert6:ValidDNnameConstraintsTest1EE.crt
+ * Subject:CN=Valid DN nameConstraints EE Certificate Test1,
+ * OU=permittedSubtree1,O=Test Certificates,C=US
+ *
+ */
+static char *ncCertList[] = {
+ "nameConstraintsDN1subCA1Cert.crt",
+ "nameConstraintsDN3subCA2Cert.crt",
+ "nameConstraintsDN2CACert.crt",
+ "nameConstraintsDN3subCA1Cert.crt",
+ "nameConstraintsDN4CACert.crt",
+ "nameConstraintsDN5CACert.crt",
+ "ValidDNnameConstraintsTest1EE.crt"
+};
+#define NUMNCCERTS (sizeof(ncCertList) / sizeof(ncCertList[0]))
+
+static char *sanCertList[] = {
+ "InvalidDNnameConstraintsTest3EE.crt",
+ "InvalidDNSnameConstraintsTest38EE.crt"
+};
+#define NUMSANCERTS (sizeof(sanCertList) / sizeof(sanCertList[0]))
+
+/*
+ * This function calls the CertSelector pointed to by "selector" for each
+ * cert in the List pointed to by "certs", and compares the results against
+ * the bit array given by the UInt32 "expectedResults". If the first cert is
+ * expected to pass, the lower-order bit of "expectedResults" should be 1.
+ * If the second cert is expected to pass, the second bit of "expectedResults"
+ * should be 1, and so on. If more than 32 certs are provided, only the first
+ * 32 will be checked. It is not an error to provide more bits than needed.
+ * (For example, if you expect every cert to pass, "expectedResult" can be
+ * set to 0xFFFFFFFF, even if the chain has fewer than 32 certs.)
+ */
+static void
+testSelector(
+ PKIX_CertSelector *selector,
+ PKIX_List *certs,
+ PKIX_UInt32 expectedResults)
+{
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 numCerts = 0;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_CertSelector_MatchCallback callback = NULL;
+ PKIX_Error *errReturn = NULL;
+ PKIX_Boolean result = PKIX_TRUE;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_GetMatchCallback(selector, &callback, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext));
+ if (numCerts > 32) {
+ numCerts = 32;
+ }
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, i, (PKIX_PL_Object **)&cert, plContext));
+ errReturn = callback(selector, cert, &result, plContext);
+
+ if (errReturn || result == PKIX_FALSE) {
+ if ((expectedResults & 1) == 1) {
+ testError("selector unexpectedly failed");
+ (void)printf(" processing cert:\t%d\n", i);
+ }
+ } else {
+ if ((expectedResults & 1) == 0) {
+ testError("selector unexpectedly passed");
+ (void)printf(" processing cert:\t%d\n", i);
+ }
+ }
+
+ expectedResults = expectedResults >> 1;
+ PKIX_TEST_DECREF_BC(cert);
+ PKIX_TEST_DECREF_BC(errReturn);
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(errReturn);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function gets a policy from the Cert pointed to by "cert", according
+ * to the index provided by "index", creates an immutable List containing the
+ * OID of that policy, and stores the result at "pPolicyList".
+ */
+static void
+testGetPolicyFromCert(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 index,
+ PKIX_List **pPolicyList)
+{
+ PKIX_List *policyInfo = NULL;
+ PKIX_PL_CertPolicyInfo *firstPolicy = NULL;
+ PKIX_PL_OID *policyOID = NULL;
+ PKIX_List *list = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(cert, &policyInfo, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(policyInfo,
+ index,
+ (PKIX_PL_Object **)&firstPolicy,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId(firstPolicy, &policyOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&list, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)policyOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetImmutable(list, plContext));
+
+ *pPolicyList = list;
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(policyInfo);
+ PKIX_TEST_DECREF_AC(firstPolicy);
+ PKIX_TEST_DECREF_AC(policyOID);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This custom matchCallback will pass any Certificate which has no
+ * CertificatePolicies extension and any Certificate whose Policies
+ * extension include a CertPolicyQualifier.
+ */
+static PKIX_Error *
+custom_CertSelector_MatchCallback(
+ PKIX_CertSelector *selector,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 numPolicies = 0;
+ PKIX_List *certPolicies = NULL;
+ PKIX_List *quals = NULL;
+ PKIX_PL_CertPolicyInfo *policy = NULL;
+ PKIX_Error *error = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ *pResult = PKIX_TRUE;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(cert, &certPolicies, plContext));
+
+ if (certPolicies) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certPolicies, &numPolicies, plContext));
+
+ for (i = 0; i < numPolicies; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certPolicies,
+ i,
+ (PKIX_PL_Object **)&policy,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(policy, &quals, plContext));
+ if (quals) {
+ goto cleanup;
+ }
+ PKIX_TEST_DECREF_BC(policy);
+ }
+ PKIX_TEST_DECREF_BC(certPolicies);
+ *pResult = PKIX_FALSE;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(PKIX_CERTSELECTOR_ERROR,
+ NULL,
+ NULL,
+ PKIX_TESTPOLICYEXTWITHNOPOLICYQUALIFIERS,
+ &error,
+ plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(certPolicies);
+ PKIX_TEST_DECREF_AC(policy);
+ PKIX_TEST_DECREF_AC(quals);
+
+ return (error);
+}
+
+/*
+ * This custom matchCallback will pass any Certificate whose
+ * CertificatePolicies extension asserts the Policy specified by
+ * the OID in the CertSelectorContext object.
+ */
+static PKIX_Error *
+custom_CertSelector_MatchOIDCallback(
+ PKIX_CertSelector *selector,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 numPolicies = 0;
+ PKIX_Boolean match = PKIX_FALSE;
+ PKIX_PL_Object *certSelectorContext = NULL;
+ PKIX_PL_OID *constraintOID = NULL;
+ PKIX_List *certPolicies = NULL;
+ PKIX_PL_CertPolicyInfo *policy = NULL;
+ PKIX_PL_OID *policyOID = NULL;
+ PKIX_PL_String *errorDesc = NULL;
+ PKIX_Error *error = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ *pResult = PKIX_TRUE;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_GetCertSelectorContext(selector, &certSelectorContext, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_CheckType(certSelectorContext, PKIX_OID_TYPE, plContext));
+
+ constraintOID = (PKIX_PL_OID *)certSelectorContext;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(cert, &certPolicies, plContext));
+
+ if (certPolicies) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certPolicies, &numPolicies, plContext));
+
+ for (i = 0; i < numPolicies; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certPolicies,
+ i,
+ (PKIX_PL_Object **)&policy,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId(policy, &policyOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)policyOID,
+ (PKIX_PL_Object *)constraintOID,
+ &match,
+ plContext));
+
+ if (match) {
+ goto cleanup;
+ }
+ PKIX_TEST_DECREF_BC(policy);
+ PKIX_TEST_DECREF_BC(policyOID);
+ }
+ }
+
+ PKIX_TEST_DECREF_BC(certSelectorContext);
+ PKIX_TEST_DECREF_BC(certPolicies);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(PKIX_CERTSELECTOR_ERROR,
+ NULL,
+ NULL,
+ PKIX_TESTNOMATCHINGPOLICY,
+ &error,
+ plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(certSelectorContext);
+ PKIX_TEST_DECREF_AC(certPolicies);
+ PKIX_TEST_DECREF_AC(policy);
+ PKIX_TEST_DECREF_AC(policyOID);
+ PKIX_TEST_DECREF_AC(errorDesc);
+
+ return (error);
+}
+
+static void
+testSubjectMatch(
+ PKIX_List *certs,
+ PKIX_PL_Cert *certNameToMatch)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *subjParams = NULL;
+ PKIX_PL_X500Name *subjectName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Subject name match");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&subjParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(certNameToMatch, &subjectName, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubject(subjParams, subjectName, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, subjParams, plContext));
+ testSelector(selector, certs, 0x008);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(subjParams);
+ PKIX_TEST_DECREF_AC(subjectName);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testBasicConstraintsMatch(
+ PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *bcParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Basic Constraints match");
+ subTest(" pathLenContraint = -2: pass only EE's");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&bcParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints(bcParams, -2, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, bcParams, plContext));
+ testSelector(selector, certs, 0xC00);
+
+ subTest(" pathLenContraint = -1: pass all certs");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints(bcParams, -1, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, bcParams, plContext));
+ testSelector(selector, certs, 0xFFF);
+
+ subTest(" pathLenContraint = 1: pass only certs with pathLen >= 1");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints(bcParams, 1, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, bcParams, plContext));
+ testSelector(selector, certs, 0x3DF);
+
+ subTest(" pathLenContraint = 2: pass only certs with pathLen >= 2");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints(bcParams, 2, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, bcParams, plContext));
+ testSelector(selector, certs, 0x39F);
+
+cleanup:
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(bcParams);
+
+ PKIX_TEST_RETURN();
+}
+
+static void testPolicyMatch(
+ PKIX_List *certs,
+ PKIX_PL_Cert *NIST1Cert, /* a source for policy NIST1 */
+ PKIX_PL_Cert *NIST2Cert, /* a source for policy NIST2 */
+ PKIX_PL_Cert *anyPolicyCert) /* a source for policy anyPolicy */
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_List *emptyList = NULL; /* no members */
+ PKIX_List *policy1List = NULL; /* OIDs */
+ PKIX_List *policy2List = NULL; /* OIDs */
+ PKIX_List *anyPolicyList = NULL; /* OIDs */
+ PKIX_ComCertSelParams *polParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Policy match");
+ testGetPolicyFromCert(NIST1Cert, 0, &policy1List);
+ testGetPolicyFromCert(NIST2Cert, 1, &policy2List);
+ testGetPolicyFromCert(anyPolicyCert, 0, &anyPolicyList);
+
+ subTest(" Pass certs with any CertificatePolicies extension");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&emptyList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&polParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPolicy(polParams, emptyList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, polParams, plContext));
+ testSelector(selector, certs, 0xEFF);
+ PKIX_TEST_DECREF_BC(polParams);
+
+ subTest(" Pass only certs with policy NIST1");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&polParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPolicy(polParams, policy1List, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, polParams, plContext));
+ testSelector(selector, certs, 0xEF5);
+ PKIX_TEST_DECREF_BC(polParams);
+
+ subTest(" Pass only certs with policy NIST2");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&polParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPolicy(polParams, policy2List, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, polParams, plContext));
+ testSelector(selector, certs, 0x814);
+ PKIX_TEST_DECREF_BC(polParams);
+
+ subTest(" Pass only certs with policy anyPolicy");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&polParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPolicy(polParams, anyPolicyList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, polParams, plContext));
+ testSelector(selector, certs, 0x002);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(emptyList);
+ PKIX_TEST_DECREF_AC(policy1List);
+ PKIX_TEST_DECREF_AC(policy2List);
+ PKIX_TEST_DECREF_AC(anyPolicyList);
+ PKIX_TEST_DECREF_AC(polParams);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCertificateMatch(
+ PKIX_List *certs,
+ PKIX_PL_Cert *certToMatch)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Certificate match");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&params, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate(params, certToMatch, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+ testSelector(selector, certs, 0x008);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(params);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testNameConstraintsMatch(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_CertNameConstraints *permitNameConstraints1 = NULL;
+ PKIX_PL_CertNameConstraints *permitNameConstraints2 = NULL;
+ PKIX_PL_CertNameConstraints *permitNameConstraints3 = NULL;
+ PKIX_PL_CertNameConstraints *excludeNameConstraints1 = NULL;
+ PKIX_PL_CertNameConstraints *excludeNameConstraints2 = NULL;
+ PKIX_PL_CertNameConstraints *excludeNameConstraints3 = NULL;
+ PKIX_UInt32 numCerts = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test NameConstraints Cert Selector");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ subTest(" PKIX_PL_Cert_GetNameConstraints <cert0-permitted>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, 0, (PKIX_PL_Object **)&cert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(cert, &permitNameConstraints1, plContext));
+ PKIX_TEST_DECREF_BC(cert);
+
+ subTest(" PKIX_PL_Cert_GetNameConstraints <cert1-permitted>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, 1, (PKIX_PL_Object **)&cert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(cert, &permitNameConstraints2, plContext));
+ PKIX_TEST_DECREF_BC(cert);
+
+ subTest(" PKIX_PL_Cert_GetNameConstraints <cert2-permitted>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, 2, (PKIX_PL_Object **)&cert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(cert, &permitNameConstraints3, plContext));
+ PKIX_TEST_DECREF_BC(cert);
+
+ subTest(" PKIX_PL_Cert_GetNameConstraints <cert3-excluded>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, 3, (PKIX_PL_Object **)&cert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(cert, &excludeNameConstraints1, plContext));
+ PKIX_TEST_DECREF_BC(cert);
+
+ subTest(" PKIX_PL_Cert_GetNameConstraints <cert4-excluded>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, 4, (PKIX_PL_Object **)&cert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(cert, &excludeNameConstraints2, plContext));
+ PKIX_TEST_DECREF_BC(cert);
+
+ subTest(" PKIX_PL_Cert_GetNameConstraints <cert5-excluded>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, 5, (PKIX_PL_Object **)&cert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(cert, &excludeNameConstraints3, plContext));
+ PKIX_TEST_DECREF_BC(cert);
+
+ subTest(" Create Selector and ComCertSelParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&params, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" CertNameConstraints testing permitted NONE");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, permitNameConstraints1, plContext));
+ testSelector(selector, certs, 0x0);
+
+ subTest(" PKIX_ComCertSelParams_SetNameConstraint Reset");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, NULL, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" CertNameConstraints testing permitted ALL");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, permitNameConstraints2, plContext));
+ testSelector(selector, certs, 0x07F);
+
+ subTest(" CertNameConstraints testing permitted TWO");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, permitNameConstraints3, plContext));
+ testSelector(selector, certs, 0x0041);
+
+ subTest(" PKIX_ComCertSelParams_SetNameConstraint Reset");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, NULL, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" CertNameConstraints testing excluded");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, excludeNameConstraints1, plContext));
+ testSelector(selector, certs, 0x07F);
+
+ subTest(" CertNameConstraints testing excluded");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, excludeNameConstraints2, plContext));
+ testSelector(selector, certs, 0x07F);
+
+ subTest(" CertNameConstraints testing excluded");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, excludeNameConstraints3, plContext));
+ testSelector(selector, certs, 0x41);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(permitNameConstraints1);
+ PKIX_TEST_DECREF_AC(permitNameConstraints2);
+ PKIX_TEST_DECREF_AC(permitNameConstraints3);
+ PKIX_TEST_DECREF_AC(excludeNameConstraints1);
+ PKIX_TEST_DECREF_AC(excludeNameConstraints2);
+ PKIX_TEST_DECREF_AC(excludeNameConstraints3);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testPathToNamesMatch(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_List *nameList = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test PathToName Cert Selector");
+
+ subTest(" PKIX_PL_GeneralName List create");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&nameList, plContext));
+
+ subTest(" Add directory name <O=NotATest Certificates,C=US>");
+ name = createGeneralName(PKIX_DIRECTORY_NAME,
+ "O=NotATest Certificates,C=US",
+ plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(nameList, (PKIX_PL_Object *)name, plContext));
+
+ subTest(" Create Selector and ComCertSelParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&params, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames(params, nameList, plContext));
+
+ subTest(" Permitting THREE");
+ testSelector(selector, certs, 0x58);
+
+ subTest(" Remove directory name <O=NotATest Certificates,C=US...>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(nameList, 0, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" PKIX_ComCertSelParams_SetPathToNames Reset");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames(params, NULL, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" Add directory name <OU=permittedSubtree1,O=Test...>");
+ name = createGeneralName(PKIX_DIRECTORY_NAME,
+ "OU=permittedSubtree1,O=Test Certificates,C=US",
+ plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(nameList, (PKIX_PL_Object *)name, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames(params, nameList, plContext));
+
+ subTest(" Permitting SIX");
+ testSelector(selector, certs, 0x5F);
+
+ subTest(" Remove directory name <OU=permittedSubtree1,O=Test...>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(nameList, 0, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" PKIX_ComCertSelParams_SetNameConstraint Reset");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames(params, NULL, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" Add directory name <O=Test Certificates,C=US...>");
+ name = createGeneralName(PKIX_DIRECTORY_NAME,
+ "O=Test Certificates,C=US",
+ plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(nameList, (PKIX_PL_Object *)name, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" PKIX_ComCertSelParams_SetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames(params, nameList, plContext));
+
+ subTest(" Permitting FOUR");
+ testSelector(selector, certs, 0x47);
+
+ subTest(" Only directory name <OU=permittedSubtree1,O=Test ...>");
+ name = createGeneralName(PKIX_DIRECTORY_NAME,
+ "OU=permittedSubtree1,O=Test Certificates,C=US",
+ plContext);
+
+ subTest(" PKIX_ComCertSelParams_AddPathToName");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_AddPathToName(params, name, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" Permitting FOUR");
+ testSelector(selector, certs, 0x47);
+
+ subTest(" PKIX_ComCertSelParams_SetNameConstraint Reset");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames(params, NULL, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+ PKIX_TEST_DECREF_BC(nameList);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&nameList, plContext));
+
+ subTest(" Add directory name <CN=Valid DN nameConstraints EE...>");
+ name = createGeneralName(PKIX_DIRECTORY_NAME, "CN=Valid DN nameConstraints EE "
+ "Certificate Test1,OU=permittedSubtree1,"
+ "O=Test Certificates,C=US",
+ plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(nameList, (PKIX_PL_Object *)name, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" PKIX_ComCertSelParams_SetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames(params, nameList, plContext));
+
+ subTest(" Permitting SIX");
+ testSelector(selector, certs, 0x7e);
+
+ subTest(" Add directory name <OU=permittedSubtree1,O=Test>");
+ name = createGeneralName(PKIX_DIRECTORY_NAME,
+ "OU=permittedSubtree1,O=Test",
+ plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(nameList, (PKIX_PL_Object *)name, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" PKIX_ComCertSelParams_SetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames(params, nameList, plContext));
+
+ subTest(" Permitting SIX");
+ testSelector(selector, certs, 0x58);
+
+ subTest(" Add directory name <O=Test Certificates,C=US>");
+ name = createGeneralName(PKIX_DIRECTORY_NAME, "O=Test Certificates,C=US", plContext);
+
+ subTest(" PKIX_ComCertSelParams_SetPathToNames Reset");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames(params, NULL, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_AddPathToName(params, name, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" Permitting FOUR");
+ testSelector(selector, certs, 0x47);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(nameList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testSubjAltNamesMatch(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_List *nameList = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test SubjAltNames Cert Selector");
+
+ subTest(" PKIX_PL_GeneralName List create");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&nameList, plContext));
+
+ subTest(" Create Selector and ComCertSelParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&params, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" Add directory name <CN=Invalid DN nameConstraints EE...>");
+ name = createGeneralName(PKIX_DIRECTORY_NAME,
+ "CN=Invalid DN nameConstraints EE Certificate Test3,"
+ "OU=excludedSubtree1,O=Test Certificates,C=US",
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(nameList, (PKIX_PL_Object *)name, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetSubjAltNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjAltNames(params, nameList, plContext));
+
+ PKIX_TEST_DECREF_BC(name);
+ PKIX_TEST_DECREF_BC(nameList);
+
+ subTest(" Permitting ONE");
+ testSelector(selector, certs, 0x1);
+
+ subTest(" Add DNS name <mytestcertificates.gov>");
+ name = createGeneralName(PKIX_DNS_NAME,
+ "mytestcertificates.gov",
+ plContext);
+
+ subTest(" PKIX_ComCertSelParams_AddSubjAltName");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_AddSubjAltName(params, name, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" Permitting NONE");
+ testSelector(selector, certs, 0x0);
+
+ subTest(" PKIX_ComCertSelParams_SetMatchAllSubjAltNames to FALSE");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetMatchAllSubjAltNames(params, PKIX_FALSE, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" Permitting TWO");
+ testSelector(selector, certs, 0x3);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(name);
+ PKIX_TEST_DECREF_AC(nameList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCertificateValidMatch(
+ PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_String *stringRep = NULL;
+ PKIX_PL_Date *testDate = NULL;
+ char *asciiRep = "050501000000Z";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("CertificateValid match");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&params, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, asciiRep, 0, &stringRep, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Date_Create_UTCTime(stringRep, &testDate, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificateValid(params, testDate, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+ testSelector(selector, certs, 0xFFFFFFFF);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(stringRep);
+ PKIX_TEST_DECREF_AC(testDate);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_customCallback1(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("custom matchCallback");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(custom_CertSelector_MatchCallback,
+ NULL,
+ &selector,
+ plContext));
+
+ testSelector(selector, certs, 0x900);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+
+ PKIX_TEST_RETURN();
+}
+
+static void test_customCallback2(PKIX_List *certs,
+ PKIX_PL_Cert *anyPolicyCert) /* a source for policy anyPolicy */
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_List *anyPolicyList = NULL; /* OIDs */
+ PKIX_PL_OID *policyOID = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("custom matchCallback with CertSelectorContext");
+
+ testGetPolicyFromCert(anyPolicyCert, 0, &anyPolicyList);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(anyPolicyList, 0, (PKIX_PL_Object **)&policyOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(custom_CertSelector_MatchOIDCallback,
+ (PKIX_PL_Object *)policyOID,
+ &selector,
+ plContext));
+
+ testSelector(selector, certs, (1 << ANYPOLICYCERT));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(anyPolicyList);
+ PKIX_TEST_DECREF_AC(policyOID);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testExtendedKeyUsageMatch(char *certDir)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_OID *ekuOid = NULL;
+ PKIX_List *ekuOidList = NULL;
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore_CertCallback certCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_UInt32 numCert = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test Extended KeyUsage Cert Selector");
+
+ subTest(" PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext));
+
+ subTest(" Create Extended Key Usage OID List");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&ekuOidList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create("1.3.6.1.5.5.7.3.2", &ekuOid, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(ekuOidList, (PKIX_PL_Object *)ekuOid, plContext));
+
+ PKIX_TEST_DECREF_BC(ekuOid);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create("1.3.6.1.5.5.7.3.3", &ekuOid, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(ekuOidList, (PKIX_PL_Object *)ekuOid, plContext));
+
+ PKIX_TEST_DECREF_BC(ekuOid);
+
+ subTest(" PKIX_ComCertSelParams_SetExtendedKeyUsage");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetExtendedKeyUsage(goodParams, ekuOidList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, certDir, 0, &dirString, plContext));
+
+ subTest(" PKIX_PL_CollectionCertStoreContext_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString, &certStore, plContext));
+
+ subTest(" PKIX_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, goodParams, plContext));
+
+ subTest(" PKIX_CertStore_GetCertCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &certCallback, NULL));
+
+ subTest(" Getting data from Cert Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(certCallback(certStore, certSelector, &nbioContext, &certList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList, &numCert, plContext));
+
+ if (numCert != PKIX_TEST_CERTSELECTOR_EXTKEYUSAGE_NUM_CERTS) {
+ pkixTestErrorMsg = "unexpected Cert number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(ekuOid);
+ PKIX_TEST_DECREF_AC(ekuOidList);
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(certList);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testKeyUsageMatch(char *certDir)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore_CertCallback certCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_UInt32 numCert = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test KeyUsage Cert Selector");
+
+ subTest(" PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetKeyUsage");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetKeyUsage(goodParams, PKIX_CRL_SIGN, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, certDir, 0, &dirString, plContext));
+
+ subTest(" PKIX_PL_CollectionCertStoreContext_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString, &certStore, plContext));
+
+ subTest(" PKIX_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, goodParams, plContext));
+
+ subTest(" PKIX_CertStore_GetCertCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &certCallback, NULL));
+
+ subTest(" Getting data from Cert Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(certCallback(certStore, certSelector, &nbioContext, &certList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList, &numCert, plContext));
+
+ if (numCert != PKIX_TEST_CERTSELECTOR_KEYUSAGE_NUM_CERTS) {
+ pkixTestErrorMsg = "unexpected Cert number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(certList);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCertValidMatch(char *certDir)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_Date *validDate = NULL;
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore_CertCallback certCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_UInt32 numCert = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test CertValid Cert Selector");
+
+ subTest(" PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext));
+
+ validDate = createDate("050601000000Z", plContext);
+
+ subTest(" PKIX_ComCertSelParams_SetCertificateValid");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificateValid(goodParams, validDate, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, certDir, 0, &dirString, plContext));
+
+ subTest(" PKIX_PL_CollectionCertStoreContext_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString, &certStore, plContext));
+
+ subTest(" PKIX_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, goodParams, plContext));
+
+ subTest(" PKIX_CertStore_GetCertCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &certCallback, NULL));
+
+ subTest(" Getting data from Cert Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(certCallback(certStore, certSelector, &nbioContext, &certList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList, &numCert, plContext));
+
+ if (numCert != PKIX_TEST_CERTSELECTOR_CERTVALID_NUM_CERTS) {
+ pkixTestErrorMsg = "unexpected Cert number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(validDate);
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(certList);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testIssuerMatch(char *certDir)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_X500Name *issuer = NULL;
+ PKIX_PL_String *issuerStr = NULL;
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore_CertCallback certCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ char *issuerName = "CN=science,O=mit,C=US";
+ PKIX_UInt32 numCert = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test Issuer Cert Selector");
+
+ subTest(" PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, issuerName, 0, &issuerStr, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create(issuerStr, &issuer, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetIssuer");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetIssuer(goodParams, issuer, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, certDir, 0, &dirString, plContext));
+
+ subTest(" PKIX_PL_CollectionCertStoreContext_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString, &certStore, plContext));
+
+ subTest(" PKIX_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, goodParams, plContext));
+
+ subTest(" PKIX_CertStore_GetCertCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &certCallback, NULL));
+
+ subTest(" Getting data from Cert Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(certCallback(certStore, certSelector, &nbioContext, &certList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList, &numCert, plContext));
+
+ if (numCert != PKIX_TEST_CERTSELECTOR_ISSUER_NUM_CERTS) {
+ pkixTestErrorMsg = "unexpected Cert number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(issuer);
+ PKIX_TEST_DECREF_AC(issuerStr);
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(certList);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testSerialNumberVersionMatch(char *certDir)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_BigInt *serialNumber = NULL;
+ PKIX_PL_String *serialNumberStr = NULL;
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore_CertCallback certCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_UInt32 numCert = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test Serial Number Cert Selector");
+
+ subTest(" PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, "01", 0, &serialNumberStr, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create(serialNumberStr, &serialNumber, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetSerialNumber");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSerialNumber(goodParams, serialNumber, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetVersion");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetVersion(goodParams, 0, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, certDir, 0, &dirString, plContext));
+
+ subTest(" PKIX_PL_CollectionCertStoreContext_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString, &certStore, plContext));
+
+ subTest(" PKIX_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, goodParams, plContext));
+
+ subTest(" PKIX_CertStore_GetCertCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &certCallback, NULL));
+
+ subTest(" Getting data from Cert Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(certCallback(certStore, certSelector, &nbioContext, &certList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList, &numCert, plContext));
+
+ PKIX_TEST_DECREF_BC(certList);
+
+ if (numCert != 0) {
+ pkixTestErrorMsg = "unexpected Version mismatch";
+ }
+
+ subTest(" PKIX_ComCertSelParams_SetVersion");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetVersion(goodParams, 2, plContext));
+
+ subTest(" Getting data from Cert Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(certCallback(certStore, certSelector, &nbioContext, &certList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList, &numCert, plContext));
+
+ if (numCert != PKIX_TEST_CERTSELECTOR_SERIALNUMBER_NUM_CERTS) {
+ pkixTestErrorMsg = "unexpected Serial Number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(serialNumber);
+ PKIX_TEST_DECREF_AC(serialNumberStr);
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(certList);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testSubjKeyIdMatch(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_ByteArray *selSubjKeyId = NULL;
+ PKIX_UInt32 item = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test Subject Key Id Cert Selector");
+
+ item = 2;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, item, (PKIX_PL_Object **)&cert, plContext));
+
+ subTest(" PKIX_PL_Cert_GetSubjectKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectKeyIdentifier(cert, &selSubjKeyId, plContext));
+
+ subTest(" Create Selector and ComCertSelParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&params, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetSubjKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjKeyIdentifier(params, selSubjKeyId, plContext));
+
+ subTest(" Select One");
+ testSelector(selector, certs, 1 << item);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selSubjKeyId);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(selector);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAuthKeyIdMatch(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_ByteArray *selAuthKeyId = NULL;
+ PKIX_UInt32 item = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test Auth Key Id Cert Selector");
+
+ item = 3;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, item, (PKIX_PL_Object **)&cert, plContext));
+
+ subTest(" PKIX_PL_Cert_GetAuthorityKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetAuthorityKeyIdentifier(cert, &selAuthKeyId, plContext));
+
+ subTest(" Create Selector and ComCertSelParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&params, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetAuthorityKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetAuthorityKeyIdentifier(params, selAuthKeyId, plContext));
+
+ subTest(" Select TWO");
+ testSelector(selector, certs, (1 << item) | (1 << 1));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selAuthKeyId);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(selector);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testSubjPKAlgIdMatch(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_OID *selAlgId = NULL;
+ PKIX_UInt32 item = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test Subject Public Key Algorithm Id Cert Selector");
+
+ item = 0;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, item, (PKIX_PL_Object **)&cert, plContext));
+
+ subTest(" PKIX_PL_Cert_GetSubjectPublicKeyAlgId");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKeyAlgId(cert, &selAlgId, plContext));
+
+ subTest(" Create Selector and ComCertSelParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&params, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetSubjPKAlgId");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjPKAlgId(params, selAlgId, plContext));
+
+ subTest(" Select All");
+ testSelector(selector, certs, 0x7F);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selAlgId);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(selector);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testSubjPublicKeyMatch(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_PublicKey *selPublicKey = NULL;
+ PKIX_UInt32 item = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test Subject Public Key Cert Selector");
+
+ item = 5;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, item, (PKIX_PL_Object **)&cert, plContext));
+
+ subTest(" PKIX_PL_Cert_GetSubjectPublicKey");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(cert, &selPublicKey, plContext));
+
+ subTest(" Create Selector and ComCertSelParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&params, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetSubjPubKey");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjPubKey(params, selPublicKey, plContext));
+
+ subTest(" Select ONE");
+ testSelector(selector, certs, 1 << item);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selPublicKey);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(selector);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_CertSelector_Duplicate(PKIX_CertSelector *selector)
+{
+ PKIX_Int32 goodBasicConstraints = 0;
+ PKIX_Int32 equalBasicConstraints = 0;
+ PKIX_CertSelector *dupSelector = NULL;
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_ComCertSelParams *equalParams = NULL;
+ PKIX_CertSelector_MatchCallback goodCallback = NULL;
+ PKIX_CertSelector_MatchCallback equalCallback = NULL;
+ PKIX_PL_X500Name *goodSubject = NULL;
+ PKIX_PL_X500Name *equalSubject = NULL;
+ PKIX_List *goodPolicy = NULL;
+ PKIX_List *equalPolicy = NULL;
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Date *goodDate = NULL;
+ PKIX_PL_Date *equalDate = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test_CertSelector_Duplicate");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate((PKIX_PL_Object *)selector,
+ (PKIX_PL_Object **)&dupSelector,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_GetCommonCertSelectorParams(selector, &goodParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_GetCommonCertSelectorParams(dupSelector, &equalParams, plContext));
+ /* There is no equals function, so look at components separately. */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubject(goodParams, &goodSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubject(equalParams, &equalSubject, plContext));
+ if (goodSubject && equalSubject) {
+ testEqualsHelper((PKIX_PL_Object *)goodSubject,
+ (PKIX_PL_Object *)equalSubject,
+ PKIX_TRUE,
+ plContext);
+ } else {
+ if
+ PKIX_EXACTLY_ONE_NULL(goodSubject, equalSubject)
+ {
+ pkixTestErrorMsg = "Subject Names are not equal!";
+ goto cleanup;
+ }
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetPolicy(goodParams, &goodPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetPolicy(equalParams, &equalPolicy, plContext));
+ if (goodPolicy && equalPolicy) {
+ testEqualsHelper((PKIX_PL_Object *)goodPolicy,
+ (PKIX_PL_Object *)equalPolicy,
+ PKIX_TRUE,
+ plContext);
+ } else {
+ if
+ PKIX_EXACTLY_ONE_NULL(goodPolicy, equalPolicy)
+ {
+ pkixTestErrorMsg = "Policy Lists are not equal!";
+ goto cleanup;
+ }
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificate(goodParams, &goodCert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificate(equalParams, &equalCert, plContext));
+ if (goodCert && equalCert) {
+ testEqualsHelper((PKIX_PL_Object *)goodCert,
+ (PKIX_PL_Object *)equalCert,
+ PKIX_TRUE,
+ plContext);
+ } else {
+ if
+ PKIX_EXACTLY_ONE_NULL(goodCert, equalCert)
+ {
+ pkixTestErrorMsg = "Cert Lists are not equal!";
+ goto cleanup;
+ }
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificateValid(goodParams, &goodDate, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificateValid(equalParams, &equalDate, plContext));
+ if (goodCert && equalCert) {
+ testEqualsHelper((PKIX_PL_Object *)goodDate,
+ (PKIX_PL_Object *)equalDate,
+ PKIX_TRUE,
+ plContext);
+ } else {
+ if
+ PKIX_EXACTLY_ONE_NULL(goodDate, equalDate)
+ {
+ pkixTestErrorMsg = "Date Lists are not equal!";
+ goto cleanup;
+ }
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetBasicConstraints(goodParams, &goodBasicConstraints, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetBasicConstraints(equalParams, &equalBasicConstraints, plContext));
+ if (goodBasicConstraints != equalBasicConstraints) {
+ pkixTestErrorMsg = "BasicConstraints are not equal!";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_GetMatchCallback(selector, &goodCallback, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_GetMatchCallback(dupSelector, &equalCallback, plContext));
+ if (goodCallback != equalCallback) {
+ pkixTestErrorMsg = "MatchCallbacks are not equal!";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dupSelector);
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(equalParams);
+ PKIX_TEST_DECREF_AC(goodSubject);
+ PKIX_TEST_DECREF_AC(equalSubject);
+ PKIX_TEST_DECREF_AC(goodPolicy);
+ PKIX_TEST_DECREF_AC(equalPolicy);
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(equalCert);
+ PKIX_TEST_DECREF_AC(goodDate);
+ PKIX_TEST_DECREF_AC(equalDate);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_certselector <NIST_FILES_DIR> <cert-dir>\n\n");
+}
+
+int
+test_certselector(int argc, char *argv[])
+{
+
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 actualMinorVersion;
+
+ PKIX_CertSelector *emptySelector = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_List *nameConstraintsCerts = NULL;
+ PKIX_List *subjAltNamesCerts = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_Cert *policy1Cert = NULL;
+ PKIX_PL_Cert *policy2Cert = NULL;
+ PKIX_PL_Cert *anyPolicyCert = NULL;
+ PKIX_PL_Cert *subjectCert = NULL;
+ PKIX_ComCertSelParams *selParams = NULL;
+ char *certDir = NULL;
+ char *dirName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("CertSelector");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 3) {
+ printUsage();
+ return (0);
+ }
+
+ dirName = argv[j + 1];
+ certDir = argv[j + 3];
+
+ /* Create a List of certs to use in testing the selector */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certs, plContext));
+
+ for (i = 0; i < NUMCERTS; i++) {
+
+ cert = createCert(dirName, certList[i], plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certs, (PKIX_PL_Object *)cert, plContext));
+ if (i == POLICY1CERT) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)cert, plContext));
+ policy1Cert = cert;
+ }
+ if (i == ANYPOLICYCERT) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)cert, plContext));
+ anyPolicyCert = cert;
+ }
+ if (i == POLICY2CERT) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)cert, plContext));
+ policy2Cert = cert;
+ }
+ if (i == SUBJECTCERT) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)cert, plContext));
+ subjectCert = cert;
+ }
+ PKIX_TEST_DECREF_BC(cert);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&nameConstraintsCerts, plContext));
+
+ for (i = 0; i < NUMNCCERTS; i++) {
+
+ cert = createCert(dirName, ncCertList[i], plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(nameConstraintsCerts,
+ (PKIX_PL_Object *)cert,
+ plContext));
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&subjAltNamesCerts, plContext));
+
+ for (i = 0; i < NUMSANCERTS; i++) {
+
+ cert = createCert(dirName, sanCertList[i], plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(subjAltNamesCerts,
+ (PKIX_PL_Object *)cert,
+ plContext));
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+
+ subTest("test_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &emptySelector, plContext));
+
+ subTest("Default Match, no parameters set");
+ testSelector(emptySelector, certs, 0xFFFFFFFF);
+
+ testSubjectMatch(certs, subjectCert);
+
+ testBasicConstraintsMatch(certs);
+
+ testPolicyMatch(certs, policy1Cert, policy2Cert, anyPolicyCert);
+
+ testCertificateMatch(certs, subjectCert);
+
+ testCertificateValidMatch(certs);
+
+ subTest("Combination: pass only EE certs that assert some policy");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&selParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints(selParams, -2, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(emptySelector, selParams, plContext));
+ testSelector(emptySelector, certs, 0xC00);
+
+ testNameConstraintsMatch(nameConstraintsCerts);
+
+ testPathToNamesMatch(nameConstraintsCerts);
+
+ testSubjAltNamesMatch(subjAltNamesCerts);
+
+ testExtendedKeyUsageMatch(certDir);
+
+ testKeyUsageMatch(certDir);
+
+ testIssuerMatch(certDir);
+
+ testSerialNumberVersionMatch(certDir);
+
+ testCertValidMatch(certDir);
+
+ testSubjKeyIdMatch(nameConstraintsCerts);
+
+ testAuthKeyIdMatch(nameConstraintsCerts);
+
+ testSubjPKAlgIdMatch(nameConstraintsCerts);
+
+ testSubjPublicKeyMatch(nameConstraintsCerts);
+
+ test_CertSelector_Duplicate(emptySelector);
+
+ test_customCallback1(certs);
+
+ test_customCallback2(certs, anyPolicyCert);
+
+ subTest("test_CertSelector_Destroy");
+
+ PKIX_TEST_DECREF_BC(emptySelector);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(emptySelector);
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(policy1Cert);
+ PKIX_TEST_DECREF_AC(policy2Cert);
+ PKIX_TEST_DECREF_AC(anyPolicyCert);
+ PKIX_TEST_DECREF_AC(subjectCert);
+ PKIX_TEST_DECREF_AC(selParams);
+ PKIX_TEST_DECREF_AC(nameConstraintsCerts);
+ PKIX_TEST_DECREF_AC(subjAltNamesCerts);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CertSelector");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/certsel/test_comcertselparams.c b/security/nss/cmd/libpkix/pkix/certsel/test_comcertselparams.c
new file mode 100644
index 000000000..57f192a42
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/certsel/test_comcertselparams.c
@@ -0,0 +1,800 @@
+/* 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/. */
+/*
+ * test_comcertselparams.c
+ *
+ * Test Common Cert Selector Params
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+test_CreateOIDList(PKIX_List *certPolicyInfos, PKIX_List **pPolicyOIDs)
+{
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 numInfos = 0;
+ PKIX_PL_CertPolicyInfo *certPolicyInfo = NULL;
+ PKIX_PL_OID *policyOID = NULL;
+ PKIX_List *certPolicies = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ /* Convert from List of CertPolicyInfos to List of OIDs */
+ if (certPolicyInfos) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certPolicyInfos, &numInfos, plContext));
+ }
+
+ if (numInfos > 0) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certPolicies, plContext));
+ }
+ for (i = 0; i < numInfos; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certPolicyInfos,
+ i,
+ (PKIX_PL_Object **)&certPolicyInfo,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId(certPolicyInfo, &policyOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certPolicies, (PKIX_PL_Object *)policyOID, plContext));
+ PKIX_TEST_DECREF_BC(certPolicyInfo);
+ PKIX_TEST_DECREF_BC(policyOID);
+ }
+
+ *pPolicyOIDs = certPolicies;
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(certPolicyInfo);
+ PKIX_TEST_DECREF_AC(policyOID);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_NameConstraints(char *dirName)
+{
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_CertNameConstraints *getNameConstraints = NULL;
+ PKIX_PL_CertNameConstraints *setNameConstraints = NULL;
+ PKIX_ComCertSelParams *goodParams = NULL;
+ char *expectedAscii =
+ "[\n"
+ "\t\tPermitted Name: (OU=permittedSubtree1,"
+ "O=Test Certificates,C=US, OU=permittedSubtree2,"
+ "O=Test Certificates,C=US)\n"
+ "\t\tExcluded Name: (EMPTY)\n"
+ "\t]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Create Cert for NameConstraints test");
+
+ goodCert = createCert(dirName, "nameConstraintsDN2CACert.crt", plContext);
+
+ subTest("PKIX_PL_Cert_GetNameConstraints");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(goodCert, &setNameConstraints, plContext));
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetNameConstraints");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(goodParams, setNameConstraints, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetNameConstraints");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetNameConstraints(goodParams, &getNameConstraints, plContext));
+
+ subTest("Compare NameConstraints");
+ testEqualsHelper((PKIX_PL_Object *)setNameConstraints,
+ (PKIX_PL_Object *)getNameConstraints,
+ PKIX_TRUE,
+ plContext);
+
+ subTest("Compare NameConstraints with canned string");
+ testToStringHelper((PKIX_PL_Object *)getNameConstraints,
+ expectedAscii,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(getNameConstraints);
+ PKIX_TEST_DECREF_AC(setNameConstraints);
+ PKIX_TEST_DECREF_AC(goodParams);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_PathToNames(void)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_List *setGenNames = NULL;
+ PKIX_List *getGenNames = NULL;
+ PKIX_PL_GeneralName *rfc822GenName = NULL;
+ PKIX_PL_GeneralName *dnsGenName = NULL;
+ PKIX_PL_GeneralName *dirGenName = NULL;
+ PKIX_PL_GeneralName *uriGenName = NULL;
+ PKIX_PL_GeneralName *oidGenName = NULL;
+ char *rfc822Name = "john.doe@labs.com";
+ char *dnsName = "comcast.net";
+ char *dirName = "cn=john, ou=labs, o=sun, c=us";
+ char *uriName = "http://comcast.net";
+ char *oidName = "1.2.840.11";
+ char *expectedAscii =
+ "(john.doe@labs.com, "
+ "comcast.net, "
+ "CN=john,OU=labs,O=sun,C=us, "
+ "http://comcast.net)";
+ char *expectedAsciiAll =
+ "(john.doe@labs.com, "
+ "comcast.net, "
+ "CN=john,OU=labs,O=sun,C=us, "
+ "http://comcast.net, "
+ "1.2.840.11)";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_GeneralName_Create");
+ dnsGenName = createGeneralName(PKIX_DNS_NAME, dnsName, plContext);
+ uriGenName = createGeneralName(PKIX_URI_NAME, uriName, plContext);
+ oidGenName = createGeneralName(PKIX_OID_NAME, oidName, plContext);
+ dirGenName = createGeneralName(PKIX_DIRECTORY_NAME, dirName, plContext);
+ rfc822GenName = createGeneralName(PKIX_RFC822_NAME,
+ rfc822Name,
+ plContext);
+
+ subTest("PKIX_PL_GeneralName List create and append");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&setGenNames, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setGenNames, (PKIX_PL_Object *)rfc822GenName, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setGenNames, (PKIX_PL_Object *)dnsGenName, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setGenNames, (PKIX_PL_Object *)dirGenName, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setGenNames, (PKIX_PL_Object *)uriGenName, plContext));
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames(goodParams, setGenNames, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetPathToNames(goodParams, &getGenNames, plContext));
+
+ subTest("Compare GeneralName List");
+ testEqualsHelper((PKIX_PL_Object *)setGenNames,
+ (PKIX_PL_Object *)getGenNames,
+ PKIX_TRUE,
+ plContext);
+
+ subTest("Compare GeneralName List with canned string");
+ testToStringHelper((PKIX_PL_Object *)getGenNames,
+ expectedAscii,
+ plContext);
+
+ subTest("PKIX_ComCertSelParams_AddPathToName");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_AddPathToName(goodParams, oidGenName, plContext));
+
+ PKIX_TEST_DECREF_BC(getGenNames);
+
+ subTest("PKIX_ComCertSelParams_GetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetPathToNames(goodParams, &getGenNames, plContext));
+
+ subTest("Compare GeneralName List with canned string");
+ testToStringHelper((PKIX_PL_Object *)getGenNames,
+ expectedAsciiAll,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(setGenNames);
+ PKIX_TEST_DECREF_AC(getGenNames);
+ PKIX_TEST_DECREF_AC(rfc822GenName);
+ PKIX_TEST_DECREF_AC(dnsGenName);
+ PKIX_TEST_DECREF_AC(dirGenName);
+ PKIX_TEST_DECREF_AC(uriGenName);
+ PKIX_TEST_DECREF_AC(oidGenName);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_SubjAltNames(void)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_List *setGenNames = NULL;
+ PKIX_List *getGenNames = NULL;
+ PKIX_PL_GeneralName *rfc822GenName = NULL;
+ PKIX_PL_GeneralName *dnsGenName = NULL;
+ PKIX_PL_GeneralName *dirGenName = NULL;
+ PKIX_PL_GeneralName *uriGenName = NULL;
+ PKIX_PL_GeneralName *oidGenName = NULL;
+ PKIX_Boolean matchAll = PKIX_TRUE;
+ char *rfc822Name = "john.doe@labs.com";
+ char *dnsName = "comcast.net";
+ char *dirName = "cn=john, ou=labs, o=sun, c=us";
+ char *uriName = "http://comcast.net";
+ char *oidName = "1.2.840.11";
+ char *expectedAscii =
+ "(john.doe@labs.com, "
+ "comcast.net, "
+ "CN=john,OU=labs,O=sun,C=us, "
+ "http://comcast.net)";
+ char *expectedAsciiAll =
+ "(john.doe@labs.com, "
+ "comcast.net, "
+ "CN=john,OU=labs,O=sun,C=us, "
+ "http://comcast.net, "
+ "1.2.840.11)";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_GeneralName_Create");
+ dnsGenName = createGeneralName(PKIX_DNS_NAME, dnsName, plContext);
+ uriGenName = createGeneralName(PKIX_URI_NAME, uriName, plContext);
+ oidGenName = createGeneralName(PKIX_OID_NAME, oidName, plContext);
+ dirGenName = createGeneralName(PKIX_DIRECTORY_NAME, dirName, plContext);
+ rfc822GenName = createGeneralName(PKIX_RFC822_NAME,
+ rfc822Name,
+ plContext);
+
+ subTest("PKIX_PL_GeneralName List create and append");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&setGenNames, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setGenNames, (PKIX_PL_Object *)rfc822GenName, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setGenNames, (PKIX_PL_Object *)dnsGenName, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setGenNames, (PKIX_PL_Object *)dirGenName, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setGenNames, (PKIX_PL_Object *)uriGenName, plContext));
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetSubjAltNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjAltNames(goodParams, setGenNames, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetSubjAltNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubjAltNames(goodParams, &getGenNames, plContext));
+
+ subTest("Compare GeneralName List");
+ testEqualsHelper((PKIX_PL_Object *)setGenNames,
+ (PKIX_PL_Object *)getGenNames,
+ PKIX_TRUE,
+ plContext);
+
+ subTest("Compare GeneralName List with canned string");
+ testToStringHelper((PKIX_PL_Object *)getGenNames,
+ expectedAscii,
+ plContext);
+
+ subTest("PKIX_ComCertSelParams_AddSubjAltName");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_AddSubjAltName(goodParams, oidGenName, plContext));
+
+ PKIX_TEST_DECREF_BC(getGenNames);
+
+ subTest("PKIX_ComCertSelParams_GetSubjAltNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubjAltNames(goodParams, &getGenNames, plContext));
+
+ subTest("Compare GeneralName List with canned string");
+ testToStringHelper((PKIX_PL_Object *)getGenNames,
+ expectedAsciiAll,
+ plContext);
+
+ subTest("PKIX_ComCertSelParams_GetMatchAllSubjAltNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetMatchAllSubjAltNames(goodParams, &matchAll, plContext));
+ if (matchAll != PKIX_TRUE) {
+ testError("unexpected mismatch <expect TRUE>");
+ }
+
+ subTest("PKIX_ComCertSelParams_SetMatchAllSubjAltNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetMatchAllSubjAltNames(goodParams, PKIX_FALSE, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetMatchAllSubjAltNames(goodParams, &matchAll, plContext));
+ if (matchAll != PKIX_FALSE) {
+ testError("unexpected mismatch <expect FALSE>");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(setGenNames);
+ PKIX_TEST_DECREF_AC(getGenNames);
+ PKIX_TEST_DECREF_AC(rfc822GenName);
+ PKIX_TEST_DECREF_AC(dnsGenName);
+ PKIX_TEST_DECREF_AC(dirGenName);
+ PKIX_TEST_DECREF_AC(uriGenName);
+ PKIX_TEST_DECREF_AC(oidGenName);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_KeyUsages(void)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_OID *ekuOid = NULL;
+ PKIX_List *setExtKeyUsage = NULL;
+ PKIX_List *getExtKeyUsage = NULL;
+ PKIX_UInt32 getKeyUsage = 0;
+ PKIX_UInt32 setKeyUsage = 0x1FF;
+ PKIX_Boolean isEqual = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetKeyUsage");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetKeyUsage(goodParams, setKeyUsage, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetKeyUsage");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetKeyUsage(goodParams, &getKeyUsage, plContext));
+
+ if (setKeyUsage != getKeyUsage) {
+ testError("unexpected KeyUsage mismatch <expect equal>");
+ }
+
+ subTest("PKIX_PL_OID List create and append");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&setExtKeyUsage, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create("1.3.6.1.5.5.7.3.1", &ekuOid, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setExtKeyUsage, (PKIX_PL_Object *)ekuOid, plContext));
+ PKIX_TEST_DECREF_BC(ekuOid);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create("1.3.6.1.5.5.7.3.8", &ekuOid, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setExtKeyUsage, (PKIX_PL_Object *)ekuOid, plContext));
+ PKIX_TEST_DECREF_BC(ekuOid);
+
+ subTest("PKIX_ComCertSelParams_SetExtendedKeyUsage");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetExtendedKeyUsage(goodParams, setExtKeyUsage, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetExtendedKeyUsage");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetExtendedKeyUsage(goodParams, &getExtKeyUsage, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)setExtKeyUsage,
+ (PKIX_PL_Object *)getExtKeyUsage,
+ &isEqual,
+ plContext));
+
+ if (isEqual == PKIX_FALSE) {
+ testError("unexpected ExtKeyUsage mismatch <expect equal>");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(ekuOid);
+ PKIX_TEST_DECREF_AC(setExtKeyUsage);
+ PKIX_TEST_DECREF_AC(getExtKeyUsage);
+ PKIX_TEST_DECREF_AC(goodParams);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_Version_Issuer_SerialNumber(void)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_UInt32 version = 0;
+ PKIX_PL_X500Name *setIssuer = NULL;
+ PKIX_PL_X500Name *getIssuer = NULL;
+ PKIX_PL_String *str = NULL;
+ PKIX_PL_BigInt *setSerialNumber = NULL;
+ PKIX_PL_BigInt *getSerialNumber = NULL;
+ PKIX_Boolean isEqual = PKIX_FALSE;
+ char *bigInt = "999999999999999999";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext));
+
+ /* Version */
+ subTest("PKIX_ComCertSelParams_SetVersion");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetVersion(goodParams, 2, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetVersion");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetVersion(goodParams, &version, plContext));
+
+ if (version != 2) {
+ testError("unexpected Version mismatch <expect 2>");
+ }
+
+ /* Issuer */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, "CN=Test,O=Sun,C=US", 0, &str, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create(str, &setIssuer, plContext));
+
+ PKIX_TEST_DECREF_BC(str);
+
+ subTest("PKIX_ComCertSelParams_SetIssuer");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetIssuer(goodParams, setIssuer, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetIssuer");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetIssuer(goodParams, &getIssuer, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)setIssuer,
+ (PKIX_PL_Object *)getIssuer,
+ &isEqual,
+ plContext));
+
+ if (isEqual == PKIX_FALSE) {
+ testError("unexpected Issuer mismatch <expect equal>");
+ }
+
+ /* Serial Number */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, bigInt, PL_strlen(bigInt), &str, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create(str, &setSerialNumber, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetSerialNumber");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSerialNumber(goodParams, setSerialNumber, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetSerialNumber");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSerialNumber(goodParams, &getSerialNumber, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)setSerialNumber,
+ (PKIX_PL_Object *)getSerialNumber,
+ &isEqual,
+ plContext));
+
+ if (isEqual == PKIX_FALSE) {
+ testError("unexpected Serial Number mismatch <expect equal>");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(str);
+ PKIX_TEST_DECREF_AC(setIssuer);
+ PKIX_TEST_DECREF_AC(getIssuer);
+ PKIX_TEST_DECREF_AC(setSerialNumber);
+ PKIX_TEST_DECREF_AC(getSerialNumber);
+ PKIX_TEST_DECREF_AC(goodParams);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_SubjKeyId_AuthKeyId(void)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_ByteArray *setKeyId = NULL;
+ PKIX_PL_ByteArray *getKeyId = NULL;
+ PKIX_Boolean isEqual = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ /* Subject Key Identifier */
+ subTest("PKIX_PL_ByteArray_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create((void *)"66099", 1, &setKeyId, plContext));
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetSubjectKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjKeyIdentifier(goodParams, setKeyId, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetSubjectKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubjKeyIdentifier(goodParams, &getKeyId, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)setKeyId,
+ (PKIX_PL_Object *)getKeyId,
+ &isEqual,
+ plContext));
+
+ if (isEqual == PKIX_FALSE) {
+ testError("unexpected Subject Key Id mismatch <expect equal>");
+ }
+
+ PKIX_TEST_DECREF_BC(setKeyId);
+ PKIX_TEST_DECREF_BC(getKeyId);
+
+ /* Authority Key Identifier */
+ subTest("PKIX_PL_ByteArray_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create((void *)"11022", 1, &setKeyId, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetAuthorityKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetAuthorityKeyIdentifier(goodParams, setKeyId, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetAuthorityKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetAuthorityKeyIdentifier(goodParams, &getKeyId, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)setKeyId,
+ (PKIX_PL_Object *)getKeyId,
+ &isEqual,
+ plContext));
+
+ if (isEqual == PKIX_FALSE) {
+ testError("unexpected Auth Key Id mismatch <expect equal>");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setKeyId);
+ PKIX_TEST_DECREF_AC(getKeyId);
+ PKIX_TEST_DECREF_AC(goodParams);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_SubjAlgId_SubjPublicKey(char *dirName)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_OID *setAlgId = NULL;
+ PKIX_PL_OID *getAlgId = NULL;
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_PublicKey *setPublicKey = NULL;
+ PKIX_PL_PublicKey *getPublicKey = NULL;
+ PKIX_Boolean isEqual = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ /* Subject Algorithm Identifier */
+ subTest("PKIX_PL_OID_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create("1.1.2.3", &setAlgId, plContext));
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetSubjPKAlgId");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjPKAlgId(goodParams, setAlgId, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetSubjPKAlgId");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubjPKAlgId(goodParams, &getAlgId, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)setAlgId,
+ (PKIX_PL_Object *)getAlgId,
+ &isEqual,
+ plContext));
+
+ if (isEqual == PKIX_FALSE) {
+ testError("unexpected Subject Public Key Alg mismatch "
+ "<expect equal>");
+ }
+
+ /* Subject Public Key */
+ subTest("Getting Cert for Subject Public Key");
+
+ goodCert = createCert(dirName, "nameConstraintsDN2CACert.crt", plContext);
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(goodCert, &setPublicKey, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetSubjPubKey");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjPubKey(goodParams, setPublicKey, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetSubjPubKey");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubjPubKey(goodParams, &getPublicKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)setPublicKey,
+ (PKIX_PL_Object *)getPublicKey,
+ &isEqual,
+ plContext));
+
+ if (isEqual == PKIX_FALSE) {
+ testError("unexpected Subject Public Key mismatch "
+ "<expect equal>");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setAlgId);
+ PKIX_TEST_DECREF_AC(getAlgId);
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(setPublicKey);
+ PKIX_TEST_DECREF_AC(getPublicKey);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_comcertselparams <NIST_FILES_DIR> \n\n");
+}
+
+int
+test_comcertselparams(int argc, char *argv[])
+{
+
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_PL_Cert *testCert = NULL;
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+ PKIX_PL_CertBasicConstraints *goodBasicConstraints = NULL;
+ PKIX_PL_CertBasicConstraints *diffBasicConstraints = NULL;
+ PKIX_List *testPolicyInfos = NULL; /* CertPolicyInfos */
+ PKIX_List *cert2PolicyInfos = NULL; /* CertPolicyInfos */
+
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_ComCertSelParams *equalParams = NULL;
+ PKIX_PL_X500Name *goodSubject = NULL;
+ PKIX_PL_X500Name *equalSubject = NULL;
+ PKIX_PL_X500Name *diffSubject = NULL;
+ PKIX_PL_X500Name *testSubject = NULL;
+ PKIX_Int32 goodMinPathLength = 0;
+ PKIX_Int32 equalMinPathLength = 0;
+ PKIX_Int32 diffMinPathLength = 0;
+ PKIX_Int32 testMinPathLength = 0;
+ PKIX_List *goodPolicies = NULL; /* OIDs */
+ PKIX_List *equalPolicies = NULL; /* OIDs */
+ PKIX_List *testPolicies = NULL; /* OIDs */
+ PKIX_List *cert2Policies = NULL; /* OIDs */
+
+ PKIX_PL_Date *testDate = NULL;
+ PKIX_PL_Date *goodDate = NULL;
+ PKIX_PL_Date *equalDate = NULL;
+ PKIX_PL_String *stringRep = NULL;
+ char *asciiRep = NULL;
+ char *dirName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 2) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("ComCertSelParams");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ dirName = argv[j + 1];
+
+ asciiRep = "050501000000Z";
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, asciiRep, 0, &stringRep, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Date_Create_UTCTime(stringRep, &testDate, plContext));
+
+ testCert = createCert(dirName, "PoliciesP1234CACert.crt", plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(testCert, &testSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetBasicConstraints(testCert, &goodBasicConstraints, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BasicConstraints_GetPathLenConstraint(goodBasicConstraints, &testMinPathLength, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(testCert, &testPolicyInfos, plContext));
+
+ /* Convert from List of CertPolicyInfos to List of OIDs */
+ test_CreateOIDList(testPolicyInfos, &testPolicies);
+
+ subTest("Create goodParams and set its fields");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubject(goodParams, testSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints(goodParams, testMinPathLength, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificateValid(goodParams, testDate, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPolicy(goodParams, testPolicies, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate(goodParams, testCert, plContext));
+
+ subTest("Duplicate goodParams and verify copy");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate((PKIX_PL_Object *)goodParams,
+ (PKIX_PL_Object **)&equalParams,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubject(goodParams, &goodSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetBasicConstraints(goodParams, &goodMinPathLength, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificate(goodParams, &goodCert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificateValid(goodParams, &goodDate, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetPolicy(goodParams, &goodPolicies, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubject(equalParams, &equalSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetBasicConstraints(equalParams, &equalMinPathLength, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetPolicy(equalParams, &equalPolicies, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificate(equalParams, &equalCert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificateValid(equalParams, &equalDate, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)goodSubject,
+ (PKIX_PL_Object *)equalSubject,
+ PKIX_TRUE,
+ plContext);
+
+ if (goodMinPathLength != equalMinPathLength) {
+ testError("unexpected mismatch");
+ (void)printf("goodMinPathLength:\t%d\n", goodMinPathLength);
+ (void)printf("equalMinPathLength:\t%d\n", equalMinPathLength);
+ }
+
+ testEqualsHelper((PKIX_PL_Object *)goodPolicies,
+ (PKIX_PL_Object *)equalPolicies,
+ PKIX_TRUE,
+ plContext);
+
+ testEqualsHelper((PKIX_PL_Object *)goodCert,
+ (PKIX_PL_Object *)equalCert,
+ PKIX_TRUE,
+ plContext);
+
+ testEqualsHelper((PKIX_PL_Object *)goodDate,
+ (PKIX_PL_Object *)equalDate,
+ PKIX_TRUE,
+ plContext);
+
+ PKIX_TEST_DECREF_BC(equalSubject);
+ PKIX_TEST_DECREF_BC(equalPolicies);
+ PKIX_TEST_DECREF_BC(equalCert);
+ PKIX_TEST_DECREF_AC(equalDate);
+
+ subTest("Set different values and verify differences");
+
+ diffCert = createCert(dirName, "pathLenConstraint6CACert.crt", plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(diffCert, &diffSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetBasicConstraints(diffCert, &diffBasicConstraints, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BasicConstraints_GetPathLenConstraint(diffBasicConstraints, &diffMinPathLength, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(diffCert, &cert2PolicyInfos, plContext));
+ test_CreateOIDList(cert2PolicyInfos, &cert2Policies);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubject(
+ equalParams, diffSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints(equalParams, diffMinPathLength, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPolicy(equalParams, cert2Policies, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubject(equalParams, &equalSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetBasicConstraints(equalParams, &equalMinPathLength, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetPolicy(equalParams, &equalPolicies, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)goodSubject,
+ (PKIX_PL_Object *)equalSubject,
+ PKIX_FALSE,
+ plContext);
+
+ if (goodMinPathLength == equalMinPathLength) {
+ testError("unexpected match");
+ (void)printf("goodMinPathLength:\t%d\n", goodMinPathLength);
+ (void)printf("equalMinPathLength:\t%d\n", equalMinPathLength);
+ }
+
+ testEqualsHelper((PKIX_PL_Object *)goodPolicies,
+ (PKIX_PL_Object *)equalPolicies,
+ PKIX_FALSE,
+ plContext);
+
+ test_NameConstraints(dirName);
+ test_PathToNames();
+ test_SubjAltNames();
+ test_KeyUsages();
+ test_Version_Issuer_SerialNumber();
+ test_SubjKeyId_AuthKeyId();
+ test_SubjAlgId_SubjPublicKey(dirName);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(testSubject);
+ PKIX_TEST_DECREF_AC(goodSubject);
+ PKIX_TEST_DECREF_AC(equalSubject);
+ PKIX_TEST_DECREF_AC(diffSubject);
+ PKIX_TEST_DECREF_AC(testSubject);
+ PKIX_TEST_DECREF_AC(goodPolicies);
+ PKIX_TEST_DECREF_AC(equalPolicies);
+ PKIX_TEST_DECREF_AC(testPolicies);
+ PKIX_TEST_DECREF_AC(cert2Policies);
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(equalParams);
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(diffCert);
+ PKIX_TEST_DECREF_AC(testCert);
+ PKIX_TEST_DECREF_AC(goodBasicConstraints);
+ PKIX_TEST_DECREF_AC(diffBasicConstraints);
+ PKIX_TEST_DECREF_AC(testPolicyInfos);
+ PKIX_TEST_DECREF_AC(cert2PolicyInfos);
+ PKIX_TEST_DECREF_AC(stringRep);
+ PKIX_TEST_DECREF_AC(testDate);
+ PKIX_TEST_DECREF_AC(goodDate);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ComCertSelParams");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/checker/Makefile b/security/nss/cmd/libpkix/pkix/checker/Makefile
new file mode 100755
index 000000000..09ca5f1c6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/checker/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/security/nss/cmd/libpkix/pkix/checker/manifest.mn b/security/nss/cmd/libpkix/pkix/checker/manifest.mn
new file mode 100755
index 000000000..3101e02e2
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/checker/manifest.mn
@@ -0,0 +1,19 @@
+#
+# 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/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_certchainchecker.c
+
+LIBRARY_NAME=pkixtoolchecker
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/checker/test_certchainchecker.c b/security/nss/cmd/libpkix/pkix/checker/test_certchainchecker.c
new file mode 100644
index 000000000..5fab3a692
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/checker/test_certchainchecker.c
@@ -0,0 +1,185 @@
+/* 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/. */
+/*
+ * test_certchainchecker.c
+ *
+ * Test Cert Chain Checker
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static PKIX_Error *
+dummyChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions,
+ void **pNBIOContext,
+ void *plContext)
+{
+ goto cleanup;
+
+cleanup:
+
+ return (NULL);
+}
+
+static void
+test_CertChainChecker_Duplicate(PKIX_CertChainChecker *original)
+{
+ PKIX_Boolean originalForward = PKIX_FALSE;
+ PKIX_Boolean copyForward = PKIX_FALSE;
+ PKIX_Boolean originalForwardDir = PKIX_FALSE;
+ PKIX_Boolean copyForwardDir = PKIX_FALSE;
+ PKIX_CertChainChecker *copy = NULL;
+ PKIX_CertChainChecker_CheckCallback originalCallback = NULL;
+ PKIX_CertChainChecker_CheckCallback copyCallback = NULL;
+ PKIX_PL_Object *originalState = NULL;
+ PKIX_PL_Object *copyState = NULL;
+ PKIX_List *originalList = NULL;
+ PKIX_List *copyList = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("CertChainChecker_Duplicate");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate((PKIX_PL_Object *)original,
+ (PKIX_PL_Object **)&copy,
+ plContext));
+
+ subTest("CertChainChecker_GetCheckCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetCheckCallback(original, &originalCallback, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetCheckCallback(copy, &copyCallback, plContext));
+ if (originalCallback != copyCallback) {
+ pkixTestErrorMsg = "CheckCallback functions are not equal!";
+ goto cleanup;
+ }
+
+ subTest("CertChainChecker_IsForwardCheckingSupported");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_IsForwardCheckingSupported(original, &originalForward, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_IsForwardCheckingSupported(copy, &copyForward, plContext));
+ if (originalForward != copyForward) {
+ pkixTestErrorMsg = "ForwardChecking booleans are not equal!";
+ goto cleanup;
+ }
+
+ subTest("CertChainChecker_IsForwardDirectionExpected");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_IsForwardDirectionExpected(original, &originalForwardDir, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_IsForwardDirectionExpected(copy, &copyForwardDir, plContext));
+ if (originalForwardDir != copyForwardDir) {
+ pkixTestErrorMsg = "ForwardDirection booleans are not equal!";
+ goto cleanup;
+ }
+
+ subTest("CertChainChecker_GetCertChainCheckerState");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetCertChainCheckerState(original, &originalState, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetCertChainCheckerState(copy, &copyState, plContext));
+ testEqualsHelper(originalState, copyState, PKIX_TRUE, plContext);
+
+ subTest("CertChainChecker_GetSupportedExtensions");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetSupportedExtensions(original, &originalList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetSupportedExtensions(copy, &copyList, plContext));
+ testEqualsHelper((PKIX_PL_Object *)originalList,
+ (PKIX_PL_Object *)copyList,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(copy);
+ PKIX_TEST_DECREF_AC(originalState);
+ PKIX_TEST_DECREF_AC(copyState);
+ PKIX_TEST_DECREF_AC(originalList);
+ PKIX_TEST_DECREF_AC(copyList);
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_certchainchecker(int argc, char *argv[])
+{
+
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_PL_OID *bcOID = NULL;
+ PKIX_PL_OID *ncOID = NULL;
+ PKIX_PL_OID *cpOID = NULL;
+ PKIX_PL_OID *pmOID = NULL;
+ PKIX_PL_OID *pcOID = NULL;
+ PKIX_PL_OID *iaOID = NULL;
+ PKIX_CertChainChecker *dummyChecker = NULL;
+ PKIX_List *supportedExtensions = NULL;
+ PKIX_PL_Object *initialState = NULL;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("CertChainChecker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&supportedExtensions, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(PKIX_BASICCONSTRAINTS_OID, &bcOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(supportedExtensions, (PKIX_PL_Object *)bcOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(PKIX_NAMECONSTRAINTS_OID, &ncOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(supportedExtensions, (PKIX_PL_Object *)ncOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(PKIX_CERTIFICATEPOLICIES_OID, &cpOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(supportedExtensions, (PKIX_PL_Object *)cpOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(PKIX_POLICYMAPPINGS_OID, &pmOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(supportedExtensions, (PKIX_PL_Object *)pmOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(PKIX_POLICYCONSTRAINTS_OID, &pcOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(supportedExtensions, (PKIX_PL_Object *)pcOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(PKIX_INHIBITANYPOLICY_OID, &iaOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(supportedExtensions, (PKIX_PL_Object *)iaOID, plContext));
+
+ PKIX_TEST_DECREF_BC(bcOID);
+ PKIX_TEST_DECREF_BC(ncOID);
+ PKIX_TEST_DECREF_BC(cpOID);
+ PKIX_TEST_DECREF_BC(pmOID);
+ PKIX_TEST_DECREF_BC(pcOID);
+ PKIX_TEST_DECREF_BC(iaOID);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)supportedExtensions, plContext));
+
+ initialState = (PKIX_PL_Object *)supportedExtensions;
+
+ subTest("CertChainChecker_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_Create(dummyChecker_Check, /* PKIX_CertChainChecker_CheckCallback */
+ PKIX_FALSE, /* forwardCheckingSupported */
+ PKIX_FALSE, /* forwardDirectionExpected */
+ supportedExtensions,
+ NULL, /* PKIX_PL_Object *initialState */
+ &dummyChecker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_SetCertChainCheckerState(dummyChecker, initialState, plContext));
+
+ test_CertChainChecker_Duplicate(dummyChecker);
+
+ subTest("CertChainChecker_Destroy");
+ PKIX_TEST_DECREF_BC(dummyChecker);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dummyChecker);
+ PKIX_TEST_DECREF_AC(initialState);
+ PKIX_TEST_DECREF_AC(supportedExtensions);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CertChainChecker");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/crlsel/Makefile b/security/nss/cmd/libpkix/pkix/crlsel/Makefile
new file mode 100755
index 000000000..09ca5f1c6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/crlsel/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/security/nss/cmd/libpkix/pkix/crlsel/manifest.mn b/security/nss/cmd/libpkix/pkix/crlsel/manifest.mn
new file mode 100755
index 000000000..dfac43bb5
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/crlsel/manifest.mn
@@ -0,0 +1,21 @@
+#
+# 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/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_crlselector.c \
+ test_comcrlselparams.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtoolcrlsel
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/crlsel/test_comcrlselparams.c b/security/nss/cmd/libpkix/pkix/crlsel/test_comcrlselparams.c
new file mode 100644
index 000000000..fcc5ef5a3
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/crlsel/test_comcrlselparams.c
@@ -0,0 +1,406 @@
+/* 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/. */
+/*
+ * test_comcrlselparams.c
+ *
+ * Test ComCRLSelParams Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testIssuer(PKIX_ComCRLSelParams *goodObject)
+{
+ PKIX_PL_String *issuer1String = NULL;
+ PKIX_PL_String *issuer2String = NULL;
+ PKIX_PL_String *issuer3String = NULL;
+ PKIX_PL_X500Name *issuerName1 = NULL;
+ PKIX_PL_X500Name *issuerName2 = NULL;
+ PKIX_PL_X500Name *issuerName3 = NULL;
+ PKIX_List *setIssuerList = NULL;
+ PKIX_List *getIssuerList = NULL;
+ PKIX_PL_String *issuerListString = NULL;
+ char *name1 = "CN=yassir,OU=bcn,OU=east,O=sun,C=us";
+ char *name2 = "CN=richard,OU=bcn,OU=east,O=sun,C=us";
+ char *name3 = "CN=hanfei,OU=bcn,OU=east,O=sun,C=us";
+ PKIX_Int32 length;
+ PKIX_Boolean result = PKIX_FALSE;
+ char *expectedAscii =
+ "(CN=yassir,OU=bcn,OU=east,O=sun,"
+ "C=us, CN=richard,OU=bcn,OU=east,O=sun,C=us, "
+ "CN=hanfei,OU=bcn,OU=east,O=sun,C=us)";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCRLSelParams Create Issuers");
+
+ length = PL_strlen(name1);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_UTF8,
+ name1,
+ length,
+ &issuer1String,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create(issuer1String,
+ &issuerName1,
+ plContext));
+
+ length = PL_strlen(name2);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_UTF8,
+ name2,
+ length,
+ &issuer2String,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create(issuer2String,
+ &issuerName2,
+ plContext));
+
+ length = PL_strlen(name3);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_UTF8,
+ name3,
+ length,
+ &issuer3String,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create(issuer3String,
+ &issuerName3,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&setIssuerList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setIssuerList,
+ (PKIX_PL_Object *)issuerName1,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setIssuerList,
+ (PKIX_PL_Object *)issuerName2,
+ plContext));
+
+ subTest("PKIX_ComCRLSelParams_AddIssuerName");
+
+ /* Test adding an issuer to an empty list */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_AddIssuerName(goodObject, issuerName3, plContext));
+
+ subTest("PKIX_ComCRLSelParams_GetIssuerNames");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_GetIssuerNames(goodObject, &getIssuerList, plContext));
+
+ /* DECREF for GetIssuerNames */
+ PKIX_TEST_DECREF_BC(getIssuerList);
+ /* DECREF for AddIssuerName so next SetIssuerName start clean */
+ PKIX_TEST_DECREF_BC(getIssuerList);
+
+ /* Test setting issuer names on the list */
+ subTest("PKIX_ComCRLSelParams_SetIssuerNames");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetIssuerNames(goodObject, setIssuerList, plContext));
+
+ subTest("PKIX_ComCRLSelParams_GetIssuerNames");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_GetIssuerNames(goodObject, &getIssuerList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)setIssuerList,
+ (PKIX_PL_Object *)getIssuerList,
+ &result,
+ plContext));
+
+ if (result != PKIX_TRUE) {
+ pkixTestErrorMsg = "unexpected Issuers mismatch";
+ }
+
+ /* Test adding an issuer to existing list */
+ subTest("PKIX_ComCRLSelParams_AddIssuerName");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_AddIssuerName(goodObject, issuerName3, plContext));
+
+ subTest("PKIX_ComCRLSelParams_GetIssuerNames");
+ PKIX_TEST_DECREF_BC(getIssuerList);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_GetIssuerNames(goodObject, &getIssuerList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)getIssuerList,
+ &issuerListString,
+ plContext));
+
+ testToStringHelper((PKIX_PL_Object *)getIssuerList,
+ expectedAscii, plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(issuer1String);
+ PKIX_TEST_DECREF_AC(issuer2String);
+ PKIX_TEST_DECREF_AC(issuer3String);
+ PKIX_TEST_DECREF_AC(issuerListString);
+ PKIX_TEST_DECREF_AC(issuerName1);
+ PKIX_TEST_DECREF_AC(issuerName2);
+ PKIX_TEST_DECREF_AC(issuerName3);
+ PKIX_TEST_DECREF_AC(setIssuerList);
+ PKIX_TEST_DECREF_AC(getIssuerList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCertificateChecking(
+ char *dataCentralDir,
+ char *goodInput,
+ PKIX_ComCRLSelParams *goodObject)
+{
+ PKIX_PL_Cert *setCert = NULL;
+ PKIX_PL_Cert *getCert = NULL;
+ PKIX_Boolean result = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Test CertificateChecking Cert Create");
+ setCert = createCert(dataCentralDir, goodInput, plContext);
+ if (setCert == NULL) {
+ pkixTestErrorMsg = "create certificate failed";
+ goto cleanup;
+ }
+
+ subTest("PKIX_ComCRLSelParams_SetCertificateChecking");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetCertificateChecking(goodObject, setCert, plContext));
+
+ subTest("PKIX_ComCRLSelParams_GetCertificateChecking");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_GetCertificateChecking(goodObject, &getCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)setCert,
+ (PKIX_PL_Object *)getCert,
+ &result, plContext));
+
+ if (result != PKIX_TRUE) {
+ pkixTestErrorMsg = "unexpected Cert mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setCert);
+ PKIX_TEST_DECREF_AC(getCert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDateAndTime(PKIX_ComCRLSelParams *goodObject)
+{
+
+ PKIX_PL_Date *setDate = NULL;
+ PKIX_PL_Date *getDate = NULL;
+ char *asciiDate = "040329134847Z";
+ PKIX_Boolean result = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCRLSelParams_Date Create");
+ setDate = createDate(asciiDate, plContext);
+
+ subTest("PKIX_ComCRLSelParams_SetDateAndTime");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetDateAndTime(goodObject, setDate, plContext));
+
+ subTest("PKIX_ComCRLSelParams_GetDateAndTime");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_GetDateAndTime(goodObject, &getDate, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)setDate,
+ (PKIX_PL_Object *)getDate,
+ &result, plContext));
+
+ if (result != PKIX_TRUE) {
+ pkixTestErrorMsg = "unexpected DateAndTime mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setDate);
+ PKIX_TEST_DECREF_AC(getDate);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testMaxMinCRLNumbers(PKIX_ComCRLSelParams *goodObject)
+{
+ PKIX_PL_BigInt *setMaxCrlNumber = NULL;
+ PKIX_PL_BigInt *getMaxCrlNumber = NULL;
+ PKIX_PL_BigInt *setMinCrlNumber = NULL;
+ PKIX_PL_BigInt *getMinCrlNumber = NULL;
+ char *asciiCrlNumber1 = "01";
+ char *asciiCrlNumber99999 = "0909090909";
+ PKIX_PL_String *crlNumber1String = NULL;
+ PKIX_PL_String *crlNumber99999String = NULL;
+
+ PKIX_Boolean result = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCRLSelParams_SetMinCRLNumber");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ asciiCrlNumber1,
+ PL_strlen(asciiCrlNumber1),
+ &crlNumber1String,
+ NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create(crlNumber1String, &setMinCrlNumber, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetMinCRLNumber(goodObject, setMinCrlNumber, NULL));
+
+ subTest("PKIX_ComCRLSelParams_GetMinCRLNumber");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_GetMinCRLNumber(goodObject, &getMinCrlNumber, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)setMinCrlNumber,
+ (PKIX_PL_Object *)getMinCrlNumber,
+ &result, NULL));
+
+ if (result != PKIX_TRUE) {
+ pkixTestErrorMsg = "unexpected Minimum CRL Number mismatch";
+ }
+
+ subTest("PKIX_ComCRLSelParams_SetMaxCRLNumber");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ asciiCrlNumber99999,
+ PL_strlen(asciiCrlNumber99999),
+ &crlNumber99999String,
+ NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create(crlNumber99999String, &setMaxCrlNumber, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetMaxCRLNumber(goodObject, setMaxCrlNumber, NULL));
+
+ subTest("PKIX_ComCRLSelParams_GetMaxCRLNumber");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_GetMaxCRLNumber(goodObject, &getMaxCrlNumber, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)setMaxCrlNumber,
+ (PKIX_PL_Object *)getMaxCrlNumber,
+ &result, NULL));
+
+ if (result != PKIX_TRUE) {
+ pkixTestErrorMsg = "unexpected Maximum CRL Number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setMaxCrlNumber);
+ PKIX_TEST_DECREF_AC(getMaxCrlNumber);
+ PKIX_TEST_DECREF_AC(setMinCrlNumber);
+ PKIX_TEST_DECREF_AC(getMinCrlNumber);
+ PKIX_TEST_DECREF_AC(crlNumber1String);
+ PKIX_TEST_DECREF_AC(crlNumber99999String);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDuplicate(PKIX_ComCRLSelParams *goodObject)
+{
+
+ PKIX_ComCRLSelParams *dupObject = NULL;
+ PKIX_Boolean result = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCRLSelParams_Duplicate");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate((PKIX_PL_Object *)goodObject,
+ (PKIX_PL_Object **)&dupObject,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)goodObject,
+ (PKIX_PL_Object *)dupObject,
+ &result, plContext));
+
+ if (result != PKIX_TRUE) {
+ pkixTestErrorMsg =
+ "unexpected Duplicate ComCRLSelParams mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dupObject);
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(char *pName)
+{
+ printf("\nUSAGE: %s <central-data-dir>\n\n", pName);
+}
+
+/* Functional tests for ComCRLSelParams public functions */
+
+int
+test_comcrlselparams(int argc, char *argv[])
+{
+
+ char *dataCentralDir = NULL;
+ char *goodInput = "yassir2yassir";
+ PKIX_ComCRLSelParams *goodObject = NULL;
+ PKIX_ComCRLSelParams *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("ComCRLSelParams");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 2) {
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ dataCentralDir = argv[j + 1];
+
+ subTest("PKIX_ComCRLSelParams_Create");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_Create(&goodObject,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_Create(&diffObject,
+ plContext));
+
+ testIssuer(goodObject);
+
+ testCertificateChecking(dataCentralDir, goodInput, goodObject);
+
+ testDateAndTime(goodObject);
+
+ testMaxMinCRLNumbers(goodObject);
+
+ testDuplicate(goodObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ goodObject,
+ diffObject,
+ NULL,
+ ComCRLSelParams,
+ PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodObject);
+ PKIX_TEST_DECREF_AC(diffObject);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ComCRLSelParams");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/crlsel/test_crlselector.c b/security/nss/cmd/libpkix/pkix/crlsel/test_crlselector.c
new file mode 100644
index 000000000..f17406be5
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/crlsel/test_crlselector.c
@@ -0,0 +1,168 @@
+/* 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/. */
+/*
+ * test_crlselector.c
+ *
+ * Test CRLSelector Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testGetMatchCallback(PKIX_CRLSelector *goodObject)
+{
+ PKIX_CRLSelector_MatchCallback mCallback = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("testGetMatchCallback");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_GetMatchCallback(goodObject, &mCallback, plContext));
+
+ if (mCallback == NULL) {
+ pkixTestErrorMsg = "MatchCallback is NULL";
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCRLSelectorContext(PKIX_CRLSelector *goodObject)
+{
+ PKIX_PL_Object *context = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("testGetCRLSelectorContext");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_GetCRLSelectorContext(goodObject, (void *)&context, plContext));
+
+ if (context == NULL) {
+ pkixTestErrorMsg = "CRLSelectorContext is NULL";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(context);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCommonCRLSelectorParams(PKIX_CRLSelector *goodObject)
+{
+ PKIX_ComCRLSelParams *setParams = NULL;
+ PKIX_ComCRLSelParams *getParams = NULL;
+ PKIX_PL_Date *setDate = NULL;
+ char *asciiDate = "040329134847Z";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCRLSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_Create(&setParams,
+ plContext));
+
+ subTest("PKIX_ComCRLSelParams_Date Create");
+
+ setDate = createDate(asciiDate, plContext);
+
+ subTest("PKIX_ComCRLSelParams_SetDateAndTime");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetDateAndTime(setParams, setDate, plContext));
+
+ subTest("PKIX_CRLSelector_SetCommonCRLSelectorParams");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_SetCommonCRLSelectorParams(
+ goodObject, setParams, plContext));
+
+ subTest("PKIX_CRLSelector_GetCommonCRLSelectorParams");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_GetCommonCRLSelectorParams(
+ goodObject, &getParams, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)setParams,
+ (PKIX_PL_Object *)getParams,
+ PKIX_TRUE,
+ plContext);
+
+ testHashcodeHelper((PKIX_PL_Object *)setParams,
+ (PKIX_PL_Object *)getParams,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setDate);
+ PKIX_TEST_DECREF_AC(setParams);
+ PKIX_TEST_DECREF_AC(getParams);
+
+ PKIX_TEST_RETURN();
+}
+
+/* Functional tests for CRLSelector public functions */
+
+int
+test_crlselector(int argc, char *argv[])
+{
+
+ PKIX_PL_Date *context = NULL;
+ PKIX_CRLSelector *goodObject = NULL;
+ PKIX_CRLSelector *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ char *asciiDate = "040329134847Z";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("CRLSelector");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ context = createDate(asciiDate, plContext);
+
+ subTest("PKIX_CRLSelector_Create");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_Create(NULL,
+ (PKIX_PL_Object *)context,
+ &goodObject,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_Create(NULL,
+ (PKIX_PL_Object *)context,
+ &diffObject,
+ plContext));
+
+ testGetMatchCallback(goodObject);
+
+ testGetCRLSelectorContext(goodObject);
+
+ testCommonCRLSelectorParams(goodObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ goodObject,
+ diffObject,
+ NULL,
+ CRLSelector,
+ PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodObject);
+ PKIX_TEST_DECREF_AC(diffObject);
+ PKIX_TEST_DECREF_AC(context);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CRLSelector");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/manifest.mn b/security/nss/cmd/libpkix/pkix/manifest.mn
new file mode 100755
index 000000000..895bf52b2
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/manifest.mn
@@ -0,0 +1,11 @@
+#
+# 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/.
+
+PKIX_DEPTH = ..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+DIRS = certsel checker crlsel params results store top util \
+ $(NULL)
diff --git a/security/nss/cmd/libpkix/pkix/params/Makefile b/security/nss/cmd/libpkix/pkix/params/Makefile
new file mode 100755
index 000000000..09ca5f1c6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/params/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/security/nss/cmd/libpkix/pkix/params/manifest.mn b/security/nss/cmd/libpkix/pkix/params/manifest.mn
new file mode 100755
index 000000000..a2e7e675b
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/params/manifest.mn
@@ -0,0 +1,23 @@
+#
+# 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/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_procparams.c \
+ test_trustanchor.c \
+ test_valparams.c \
+ test_resourcelimits.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtoolparams
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/params/test_procparams.c b/security/nss/cmd/libpkix/pkix/params/test_procparams.c
new file mode 100644
index 000000000..419322a1e
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/params/test_procparams.c
@@ -0,0 +1,478 @@
+/* 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/. */
+/*
+ * test_procparams.c
+ *
+ * Test ProcessingParams Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ProcessingParams_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetAnchors(
+ PKIX_ProcessingParams *goodObject,
+ PKIX_ProcessingParams *equalObject)
+{
+
+ PKIX_List *goodAnchors = NULL;
+ PKIX_List *equalAnchors = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_GetTrustAnchors");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetTrustAnchors(goodObject, &goodAnchors, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetTrustAnchors(equalObject, &equalAnchors, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)goodAnchors,
+ (PKIX_PL_Object *)equalAnchors,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodAnchors);
+ PKIX_TEST_DECREF_AC(equalAnchors);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSetDate(
+ PKIX_ProcessingParams *goodObject,
+ PKIX_ProcessingParams *equalObject)
+{
+
+ PKIX_PL_Date *setDate = NULL;
+ PKIX_PL_Date *getDate = NULL;
+ char *asciiDate = "040329134847Z";
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_Get/SetDate");
+
+ setDate = createDate(asciiDate, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetDate(goodObject, setDate, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetDate(goodObject, &getDate, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)setDate,
+ (PKIX_PL_Object *)getDate,
+ PKIX_TRUE,
+ plContext);
+
+ /* we want to make sure that goodObject and equalObject are "equal" */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetDate(equalObject, setDate, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setDate);
+ PKIX_TEST_DECREF_AC(getDate);
+
+ PKIX_TEST_RETURN();
+}
+
+static PKIX_Error *
+userChecker1cb(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions, /* list of PKIX_PL_OID */
+ void **pNBIOContext,
+ void *plContext)
+{
+ return (NULL);
+}
+
+static void
+testGetSetCertChainCheckers(
+ PKIX_ProcessingParams *goodObject,
+ PKIX_ProcessingParams *equalObject)
+{
+
+ PKIX_CertChainChecker *checker = NULL;
+ PKIX_List *setCheckersList = NULL;
+ PKIX_List *getCheckersList = NULL;
+ PKIX_PL_Date *date = NULL;
+ char *asciiDate = "040329134847Z";
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_Get/SetCertChainCheckers");
+
+ date = createDate(asciiDate, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_Create(userChecker1cb,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *)date,
+ &checker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&setCheckersList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setCheckersList, (PKIX_PL_Object *)checker, plContext));
+ PKIX_TEST_DECREF_BC(checker);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertChainCheckers(goodObject, setCheckersList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_Create(userChecker1cb,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *)date,
+ &checker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertChainChecker(goodObject, checker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetCertChainCheckers(goodObject, &getCheckersList, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setCheckersList);
+ PKIX_TEST_DECREF_AC(getCheckersList);
+ PKIX_TEST_DECREF_AC(date);
+ PKIX_TEST_DECREF_BC(checker);
+
+ PKIX_TEST_RETURN();
+}
+
+static PKIX_Error *
+userChecker2cb(
+ PKIX_RevocationChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 *pResult,
+ void *plContext)
+{
+ return (NULL);
+}
+
+static void
+testGetSetRevocationCheckers(
+ PKIX_ProcessingParams *goodObject,
+ PKIX_ProcessingParams *equalObject)
+{
+
+ PKIX_RevocationChecker *checker = NULL;
+ PKIX_List *setCheckersList = NULL;
+ PKIX_List *getCheckersList = NULL;
+ PKIX_PL_Date *date = NULL;
+ char *asciiDate = "040329134847Z";
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_Get/SetRevocationCheckers");
+
+ date = createDate(asciiDate, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_RevocationChecker_Create(userChecker2cb,
+ (PKIX_PL_Object *)date,
+ &checker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&setCheckersList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setCheckersList,
+ (PKIX_PL_Object *)checker,
+ plContext));
+ PKIX_TEST_DECREF_BC(checker);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers(goodObject, setCheckersList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_RevocationChecker_Create(userChecker2cb,
+ (PKIX_PL_Object *)date,
+ &checker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddRevocationChecker(goodObject, checker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetRevocationCheckers(goodObject, &getCheckersList, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setCheckersList);
+ PKIX_TEST_DECREF_AC(getCheckersList);
+ PKIX_TEST_DECREF_AC(date);
+ PKIX_TEST_DECREF_BC(checker);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSetResourceLimits(
+ PKIX_ProcessingParams *goodObject,
+ PKIX_ProcessingParams *equalObject)
+
+{
+ PKIX_ResourceLimits *resourceLimits1 = NULL;
+ PKIX_ResourceLimits *resourceLimits2 = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_Get/SetResourceLimits");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_Create(&resourceLimits1, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_Create(&resourceLimits2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout(resourceLimits1, 3, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth(resourceLimits1, 3, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxTime(resourceLimits1, 2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetResourceLimits(goodObject, resourceLimits1, plContext));
+
+ PKIX_TEST_DECREF_BC(resourceLimits2);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetResourceLimits(goodObject, &resourceLimits2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetResourceLimits(equalObject, resourceLimits2, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(resourceLimits1);
+ PKIX_TEST_DECREF_AC(resourceLimits2);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSetConstraints(PKIX_ProcessingParams *goodObject)
+{
+
+ PKIX_CertSelector *setConstraints = NULL;
+ PKIX_CertSelector *getConstraints = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_Get/SetTargetCertConstraints");
+
+ /*
+ * After createConstraints is implemented
+ * setConstraints = createConstraints();
+ */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(goodObject, setConstraints, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetTargetCertConstraints(goodObject, &getConstraints, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)setConstraints,
+ (PKIX_PL_Object *)getConstraints,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setConstraints);
+ PKIX_TEST_DECREF_AC(getConstraints);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSetInitialPolicies(
+ PKIX_ProcessingParams *goodObject,
+ char *asciiPolicyOID)
+{
+ PKIX_PL_OID *policyOID = NULL;
+ PKIX_List *setPolicyList = NULL;
+ PKIX_List *getPolicyList = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_Get/SetInitialPolicies");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(asciiPolicyOID, &policyOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&setPolicyList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(setPolicyList, (PKIX_PL_Object *)policyOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetImmutable(setPolicyList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetInitialPolicies(goodObject, setPolicyList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetInitialPolicies(goodObject, &getPolicyList, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)setPolicyList,
+ (PKIX_PL_Object *)getPolicyList,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+ PKIX_TEST_DECREF_AC(policyOID);
+ PKIX_TEST_DECREF_AC(setPolicyList);
+ PKIX_TEST_DECREF_AC(getPolicyList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSetPolicyQualifiersRejected(
+ PKIX_ProcessingParams *goodObject,
+ PKIX_Boolean rejected)
+{
+ PKIX_Boolean getRejected = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_Get/SetPolicyQualifiersRejected");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetPolicyQualifiersRejected(goodObject, rejected, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetPolicyQualifiersRejected(goodObject, &getRejected, plContext));
+
+ if (rejected != getRejected) {
+ testError("GetPolicyQualifiersRejected returned unexpected value");
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(char *pName)
+{
+ printf("\nUSAGE: %s <central-data-dir>\n\n", pName);
+}
+
+int
+test_procparams(int argc, char *argv[])
+{
+
+ PKIX_ProcessingParams *goodObject = NULL;
+ PKIX_ProcessingParams *equalObject = NULL;
+ PKIX_ProcessingParams *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ char *dataCentralDir = NULL;
+ PKIX_UInt32 j = 0;
+
+ char *oidAnyPolicy = PKIX_CERTIFICATEPOLICIES_ANYPOLICY_OID;
+ char *oidNist1Policy = "2.16.840.1.101.3.2.1.48.2";
+
+ char *goodInput = "yassir2yassir";
+ char *diffInput = "yassir2bcn";
+
+ char *expectedAscii =
+ "[\n"
+ "\tTrust Anchors: \n"
+ "\t********BEGIN LIST OF TRUST ANCHORS********\n"
+ "\t\t"
+ "([\n"
+ "\tTrusted CA Name: "
+ "CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tTrusted CA PublicKey: ANSI X9.57 DSA Signature\n"
+ "\tInitial Name Constraints:(null)\n"
+ "]\n"
+ ", [\n"
+ "\tTrusted CA Name: OU=bcn,OU=east,O=sun,C=us\n"
+ "\tTrusted CA PublicKey: ANSI X9.57 DSA Signature\n"
+ "\tInitial Name Constraints:(null)\n"
+ "]\n"
+ ")\n"
+ "\t********END LIST OF TRUST ANCHORS********\n"
+ "\tDate: \t\tMon Mar 29 08:48:47 2004\n"
+ "\tTarget Constraints: (null)\n"
+ "\tInitial Policies: (2.5.29.32.0)\n"
+ "\tQualifiers Rejected: FALSE\n"
+ "\tCert Stores: (EMPTY)\n"
+ "\tResource Limits: [\n"
+ "\tMaxTime: 2\n"
+ "\tMaxFanout: 3\n"
+ "\tMaxDepth: 3\n"
+ "]\n\n"
+ "\tCRL Checking Enabled: 0\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("ProcessingParams");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 2) {
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ dataCentralDir = argv[j + 1];
+
+ subTest("PKIX_ProcessingParams_Create");
+ goodObject = createProcessingParams(dataCentralDir,
+ goodInput,
+ diffInput,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ plContext);
+
+ equalObject = createProcessingParams(dataCentralDir,
+ goodInput,
+ diffInput,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ plContext);
+
+ diffObject = createProcessingParams(dataCentralDir,
+ diffInput,
+ goodInput,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ plContext);
+
+ testGetAnchors(goodObject, equalObject);
+ testGetSetDate(goodObject, equalObject);
+ testGetSetCertChainCheckers(goodObject, equalObject);
+ testGetSetRevocationCheckers(goodObject, equalObject);
+ testGetSetResourceLimits(goodObject, equalObject);
+
+ /*
+ * XXX testGetSetConstraints(goodObject);
+ */
+
+ testGetSetInitialPolicies(goodObject, oidAnyPolicy);
+ testGetSetInitialPolicies(equalObject, oidAnyPolicy);
+ testGetSetInitialPolicies(diffObject, oidNist1Policy);
+ testGetSetPolicyQualifiersRejected(goodObject, PKIX_FALSE);
+ testGetSetPolicyQualifiersRejected(equalObject, PKIX_FALSE);
+ testGetSetPolicyQualifiersRejected(diffObject, PKIX_TRUE);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ NULL, /* expectedAscii, */
+ ProcessingParams,
+ PKIX_FALSE);
+
+ testDestroy(goodObject, equalObject, diffObject);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ProcessingParams");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/params/test_resourcelimits.c b/security/nss/cmd/libpkix/pkix/params/test_resourcelimits.c
new file mode 100644
index 000000000..f52c3ef87
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/params/test_resourcelimits.c
@@ -0,0 +1,99 @@
+/* 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/. */
+/*
+ * test_resourcelimits.c
+ *
+ * Test ResourceLimits Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ResourceLimits_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_resourcelimits(int argc, char *argv[])
+{
+
+ PKIX_ResourceLimits *goodObject = NULL;
+ PKIX_ResourceLimits *equalObject = NULL;
+ PKIX_ResourceLimits *diffObject = NULL;
+ PKIX_UInt32 maxTime = 0;
+ PKIX_UInt32 maxFanout = 0;
+ PKIX_UInt32 maxDepth = 0;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ char *expectedAscii =
+ "[\n"
+ "\tMaxTime: 10\n"
+ "\tMaxFanout: 5\n"
+ "\tMaxDepth: 5\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("ResourceLimits");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_ResourceLimits_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_Create(&goodObject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_Create(&diffObject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_Create(&equalObject, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxTime(goodObject, 10, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_GetMaxTime(goodObject, &maxTime, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxTime(equalObject, maxTime, plContext));
+ maxTime++;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxTime(diffObject, maxTime, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout(goodObject, 5, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_GetMaxFanout(goodObject, &maxFanout, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout(equalObject, maxFanout, plContext));
+ maxFanout++;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout(diffObject, maxFanout, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth(goodObject, 5, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_GetMaxDepth(goodObject, &maxDepth, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth(equalObject, maxDepth, plContext));
+ maxDepth++;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth(diffObject, maxDepth, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ expectedAscii,
+ ResourceLimits,
+ PKIX_FALSE);
+
+ testDestroy(goodObject, equalObject, diffObject);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ResourceLimits");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/params/test_trustanchor.c b/security/nss/cmd/libpkix/pkix/params/test_trustanchor.c
new file mode 100644
index 000000000..4bd9d174c
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/params/test_trustanchor.c
@@ -0,0 +1,251 @@
+/* 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/. */
+/*
+ * test_trustanchor.c
+ *
+ * Test TrustAnchor Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createTrustAnchors(
+ char *dirName,
+ char *goodInput,
+ PKIX_TrustAnchor **goodObject,
+ PKIX_TrustAnchor **equalObject,
+ PKIX_TrustAnchor **diffObject)
+{
+ subTest("PKIX_TrustAnchor_CreateWithNameKeyPair <goodObject>");
+ *goodObject = createTrustAnchor(dirName, goodInput, PKIX_FALSE, plContext);
+
+ subTest("PKIX_TrustAnchor_CreateWithNameKeyPair <equalObject>");
+ *equalObject = createTrustAnchor(dirName, goodInput, PKIX_FALSE, plContext);
+
+ subTest("PKIX_TrustAnchor_CreateWithCert <diffObject>");
+ *diffObject = createTrustAnchor(dirName, goodInput, PKIX_TRUE, plContext);
+}
+
+static void
+testGetCAName(
+ PKIX_PL_Cert *diffCert,
+ PKIX_TrustAnchor *equalObject)
+{
+
+ PKIX_PL_X500Name *diffCAName = NULL;
+ PKIX_PL_X500Name *equalCAName = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_TrustAnchor_GetCAName");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(diffCert, &diffCAName, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_GetCAName(equalObject, &equalCAName, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)diffCAName,
+ (PKIX_PL_Object *)equalCAName,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(diffCAName);
+ PKIX_TEST_DECREF_AC(equalCAName);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCAPublicKey(
+ PKIX_PL_Cert *diffCert,
+ PKIX_TrustAnchor *equalObject)
+{
+
+ PKIX_PL_PublicKey *diffPubKey = NULL;
+ PKIX_PL_PublicKey *equalPubKey = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_TrustAnchor_GetCAPublicKey");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(diffCert, &diffPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_GetCAPublicKey(equalObject, &equalPubKey, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)diffPubKey,
+ (PKIX_PL_Object *)equalPubKey,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(diffPubKey);
+ PKIX_TEST_DECREF_AC(equalPubKey);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetNameConstraints(char *dirName)
+{
+ PKIX_TrustAnchor *goodObject = NULL;
+ PKIX_TrustAnchor *equalObject = NULL;
+ PKIX_TrustAnchor *diffObject = NULL;
+ PKIX_PL_Cert *diffCert;
+ PKIX_PL_CertNameConstraints *diffNC = NULL;
+ PKIX_PL_CertNameConstraints *equalNC = NULL;
+ char *goodInput = "nameConstraintsDN5CACert.crt";
+ char *expectedAscii =
+ "[\n"
+ "\tTrusted CA Name: CN=nameConstraints DN5 CA,"
+ "O=Test Certificates,C=US\n"
+ "\tTrusted CA PublicKey: PKCS #1 RSA Encryption\n"
+ "\tInitial Name Constraints:[\n"
+ "\t\tPermitted Name: (OU=permittedSubtree1,"
+ "O=Test Certificates,C=US)\n"
+ "\t\tExcluded Name: (OU=excludedSubtree1,"
+ "OU=permittedSubtree1,O=Test Certificates,C=US)\n"
+ "\t]\n"
+ "\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Create TrustAnchors and compare");
+
+ createTrustAnchors(dirName, goodInput, &goodObject, &equalObject, &diffObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ expectedAscii,
+ TrustAnchor,
+ PKIX_TRUE);
+
+ subTest("PKIX_TrustAnchor_GetTrustedCert");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_GetTrustedCert(diffObject, &diffCert, plContext));
+
+ subTest("PKIX_PL_Cert_GetNameConstraints");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(diffCert, &diffNC, plContext));
+
+ subTest("PKIX_TrustAnchor_GetNameConstraints");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_GetNameConstraints(equalObject, &equalNC, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)diffNC,
+ (PKIX_PL_Object *)equalNC,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(diffNC);
+ PKIX_TEST_DECREF_AC(equalNC);
+ PKIX_TEST_DECREF_BC(diffCert);
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_TrustAnchor_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_trustanchor <NIST_FILES_DIR> <central-data-dir>\n\n");
+}
+
+int
+test_trustanchor(int argc, char *argv[])
+{
+
+ PKIX_TrustAnchor *goodObject = NULL;
+ PKIX_TrustAnchor *equalObject = NULL;
+ PKIX_TrustAnchor *diffObject = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ char *goodInput = "yassir2yassir";
+ char *expectedAscii =
+ "[\n"
+ "\tTrusted CA Name: "
+ "CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tTrusted CA PublicKey: ANSI X9.57 DSA Signature\n"
+ "\tInitial Name Constraints:(null)\n"
+ "]\n";
+ char *dirName = NULL;
+ char *dataCentralDir = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("TrustAnchor");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 3) {
+ printUsage();
+ return (0);
+ }
+
+ dirName = argv[j + 1];
+ dataCentralDir = argv[j + 2];
+
+ createTrustAnchors(dataCentralDir,
+ goodInput,
+ &goodObject,
+ &equalObject,
+ &diffObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ expectedAscii,
+ TrustAnchor,
+ PKIX_TRUE);
+
+ subTest("PKIX_TrustAnchor_GetTrustedCert");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_GetTrustedCert(diffObject, &diffCert, plContext));
+
+ testGetCAName(diffCert, equalObject);
+ testGetCAPublicKey(diffCert, equalObject);
+
+ testGetNameConstraints(dirName);
+
+ testDestroy(goodObject, equalObject, diffObject);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(diffCert);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("TrustAnchor");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/params/test_valparams.c b/security/nss/cmd/libpkix/pkix/params/test_valparams.c
new file mode 100644
index 000000000..6419062c4
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/params/test_valparams.c
@@ -0,0 +1,261 @@
+/* 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/. */
+/*
+ * test_valparams.c
+ *
+ * Test ValidateParams Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ValidateParams_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetProcParams(
+ PKIX_ValidateParams *goodObject,
+ PKIX_ValidateParams *equalObject)
+{
+
+ PKIX_ProcessingParams *goodProcParams = NULL;
+ PKIX_ProcessingParams *equalProcParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ValidateParams_GetProcessingParams");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams(goodObject, &goodProcParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams(equalObject, &equalProcParams, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)goodProcParams,
+ (PKIX_PL_Object *)equalProcParams,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodProcParams);
+ PKIX_TEST_DECREF_AC(equalProcParams);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCertChain(
+ PKIX_ValidateParams *goodObject,
+ PKIX_ValidateParams *equalObject)
+{
+
+ PKIX_List *goodChain = NULL;
+ PKIX_List *equalChain = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ValidateParams_GetCertChain");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetCertChain(goodObject, &goodChain, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetCertChain(equalObject, &equalChain, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)goodChain,
+ (PKIX_PL_Object *)equalChain,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodChain);
+ PKIX_TEST_DECREF_AC(equalChain);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(char *pName)
+{
+ printf("\nUSAGE: %s <central-data-dir>\n\n", pName);
+}
+
+int
+test_valparams(int argc, char *argv[])
+{
+
+ PKIX_ValidateParams *goodObject = NULL;
+ PKIX_ValidateParams *equalObject = NULL;
+ PKIX_ValidateParams *diffObject = NULL;
+ PKIX_List *chain = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ char *dirName = NULL;
+
+ char *goodInput = "yassir2yassir";
+ char *diffInput = "yassir2bcn";
+
+ char *expectedAscii =
+ "[\n"
+ "\tProcessing Params: \n"
+ "\t********BEGIN PROCESSING PARAMS********\n"
+ "\t\t"
+ "[\n"
+ "\tTrust Anchors: \n"
+ "\t********BEGIN LIST OF TRUST ANCHORS********\n"
+ "\t\t"
+ "([\n"
+ "\tTrusted CA Name: "
+ "CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tTrusted CA PublicKey: ANSI X9.57 DSA Signature\n"
+ "\tInitial Name Constraints:(null)\n"
+ "]\n"
+ ", [\n"
+ "\tTrusted CA Name: OU=bcn,OU=east,O=sun,C=us\n"
+ "\tTrusted CA PublicKey: ANSI X9.57 DSA Signature\n"
+ "\tInitial Name Constraints:(null)\n"
+ "]\n"
+ ")\n"
+ "\t********END LIST OF TRUST ANCHORS********\n"
+ "\tDate: \t\t(null)\n"
+ "\tTarget Constraints: (null)\n"
+ "\tInitial Policies: (null)\n"
+ "\tQualifiers Rejected: FALSE\n"
+ "\tCert Stores: (EMPTY)\n"
+ "\tCRL Checking Enabled: 0\n"
+ "]\n"
+ "\n"
+ "\t********END PROCESSING PARAMS********\n"
+ "\tChain: \t\t"
+ "([\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 37bc66ec\n"
+ "\tIssuer: CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tSubject: OU=bcn,OU=east,O=sun,C=us\n"
+ "\tValidity: [From: Thu Aug 19 16:19:56 1999\n"
+ "\t To: Fri Aug 18 16:19:56 2000]\n"
+ "\tSubjectAltNames: (null)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (2.5.29.15, 2.5.29.19)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: CA(0)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "]\n"
+ ", [\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 37bc65af\n"
+ "\tIssuer: CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tSubject: CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tValidity: [From: Thu Aug 19 16:14:39 1999\n"
+ "\t To: Fri Aug 18 16:14:39 2000]\n"
+ "\tSubjectAltNames: (null)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (2.5.29.15, 2.5.29.19)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: CA(0)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "]\n"
+ ")\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("ValidateParams");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 2) {
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ dirName = argv[j + 1];
+
+ subTest("PKIX_ValidateParams_Create");
+ chain = createCertChain(dirName, diffInput, goodInput, plContext);
+ goodObject = createValidateParams(dirName,
+ goodInput,
+ diffInput,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+ equalObject = createValidateParams(dirName,
+ goodInput,
+ diffInput,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+ diffObject = createValidateParams(dirName,
+ diffInput,
+ goodInput,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ testGetProcParams(goodObject, equalObject);
+ testGetCertChain(goodObject, equalObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ NULL, /* expectedAscii, */
+ ValidateParams,
+ PKIX_FALSE);
+
+ testDestroy(goodObject, equalObject, diffObject);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(chain);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ValidateParams");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/results/Makefile b/security/nss/cmd/libpkix/pkix/results/Makefile
new file mode 100755
index 000000000..09ca5f1c6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/results/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/security/nss/cmd/libpkix/pkix/results/manifest.mn b/security/nss/cmd/libpkix/pkix/results/manifest.mn
new file mode 100755
index 000000000..5a8b93692
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/results/manifest.mn
@@ -0,0 +1,23 @@
+#
+# 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/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_buildresult.c \
+ test_policynode.c \
+ test_verifynode.c \
+ test_valresult.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtoolresults
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/results/test_buildresult.c b/security/nss/cmd/libpkix/pkix/results/test_buildresult.c
new file mode 100644
index 000000000..8b13e8eea
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/results/test_buildresult.c
@@ -0,0 +1,212 @@
+/* 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/. */
+/*
+ * test_buildresult.c
+ *
+ * Test BuildResult Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_BuildResult_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetValidateResult(
+ PKIX_BuildResult *goodObject,
+ PKIX_BuildResult *equalObject)
+{
+
+ PKIX_ValidateResult *goodValResult = NULL;
+ PKIX_ValidateResult *equalValResult = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_BuildResult_GetValidateResult");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetValidateResult(goodObject, &goodValResult, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetValidateResult(equalObject, &equalValResult, NULL));
+
+ testEqualsHelper((PKIX_PL_Object *)goodValResult,
+ (PKIX_PL_Object *)equalValResult,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodValResult);
+ PKIX_TEST_DECREF_AC(equalValResult);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCertChain(
+ PKIX_BuildResult *goodObject,
+ PKIX_BuildResult *equalObject)
+{
+
+ PKIX_List *goodChain = NULL;
+ PKIX_List *equalChain = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_BuildResult_GetCertChain");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetCertChain(goodObject, &goodChain, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetCertChain(equalObject, &equalChain, NULL));
+
+ testEqualsHelper((PKIX_PL_Object *)goodChain,
+ (PKIX_PL_Object *)equalChain,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodChain);
+ PKIX_TEST_DECREF_AC(equalChain);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(char *pName)
+{
+ printf("\nUSAGE: %s <central-data-dir>\n\n", pName);
+}
+
+int
+test_buildresult(int argc, char *argv[])
+{
+
+ PKIX_BuildResult *goodObject = NULL;
+ PKIX_BuildResult *equalObject = NULL;
+ PKIX_BuildResult *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ char *dirName = NULL;
+ PKIX_UInt32 j = 0;
+
+ char *goodInput = "yassir2yassir";
+ char *diffInput = "yassir2bcn";
+
+ char *expectedAscii =
+ "[\n"
+ "\tValidateResult: \t\t"
+ "[\n"
+ "\tTrustAnchor: \t\t"
+ "[\n"
+ "\tTrusted CA Name: "
+ "CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tTrusted CA PublicKey: ANSI X9.57 DSA Signature\n"
+ "\tInitial Name Constraints:(null)\n"
+ "]\n"
+ "\tPubKey: \t\t"
+ "ANSI X9.57 DSA Signature\n"
+ "\tPolicyTree: \t\t(null)\n"
+ "]\n"
+ "\tCertChain: \t\t("
+ "[\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 37bc65af\n"
+ "\tIssuer: CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tSubject: CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tValidity: [From: Thu Aug 19 16:14:39 1999\n"
+ "\t To: Fri Aug 18 16:14:39 2000]\n"
+ "\tSubjectAltNames: (null)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (2.5.29.15, 2.5.29.19)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: CA(0)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "]\n"
+ ", [\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 37bc66ec\n"
+ "\tIssuer: CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tSubject: OU=bcn,OU=east,O=sun,C=us\n"
+ "\tValidity: [From: Thu Aug 19 16:19:56 1999\n"
+ "\t To: Fri Aug 18 16:19:56 2000]\n"
+ "\tSubjectAltNames: (null)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (2.5.29.15, 2.5.29.19)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: CA(0)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "]\n"
+ ")\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("BuildResult");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 2) {
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ dirName = argv[j + 1];
+
+ subTest("pkix_BuildResult_Create");
+
+ goodObject = createBuildResult(dirName, goodInput, diffInput, goodInput, diffInput, plContext);
+ equalObject = createBuildResult(dirName, goodInput, diffInput, goodInput, diffInput, plContext);
+ diffObject = createBuildResult(dirName, diffInput, goodInput, diffInput, goodInput, plContext);
+
+ testGetValidateResult(goodObject, equalObject);
+ testGetCertChain(goodObject, equalObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ NULL, /* expectedAscii, */
+ BuildResult,
+ PKIX_FALSE);
+
+ testDestroy(goodObject, equalObject, diffObject);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("BuildResult");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/results/test_policynode.c b/security/nss/cmd/libpkix/pkix/results/test_policynode.c
new file mode 100644
index 000000000..38ac1d95e
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/results/test_policynode.c
@@ -0,0 +1,612 @@
+/* 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/. */
+/*
+ * test_policynode.c
+ *
+ * Test PolicyNode Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+test_GetChildren(
+ PKIX_PolicyNode *goodNode,
+ PKIX_PolicyNode *equalNode,
+ PKIX_PolicyNode *diffNode)
+{
+
+ /*
+ * Caution: be careful where you insert this test. PKIX_PolicyNode_GetChildren
+ * is required by the API to return an immutable List, and it does it by setting
+ * the List immutable. We don't make a copy because the assumption is that
+ * certificate and policy processing have been completed before the user gets at
+ * the public API. So subsequent tests of functions that modify the policy tree,
+ * such as Prune, will fail if called after the execution of this test.
+ */
+
+ PKIX_Boolean isImmutable = PKIX_FALSE;
+ PKIX_List *goodList = NULL;
+ PKIX_List *equalList = NULL;
+ PKIX_List *diffList = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PolicyNode_GetChildren");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetChildren(goodNode, &goodList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetChildren(equalNode, &equalList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetChildren(diffNode, &diffList, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodList, equalList, diffList, NULL, List, NULL);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsImmutable(goodList, &isImmutable, plContext));
+
+ if (isImmutable != PKIX_TRUE) {
+ testError("PKIX_PolicyNode_GetChildren returned a mutable List");
+ }
+
+cleanup:
+ PKIX_TEST_DECREF_AC(goodList);
+ PKIX_TEST_DECREF_AC(equalList);
+ PKIX_TEST_DECREF_AC(diffList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_GetParent(
+ PKIX_PolicyNode *goodNode,
+ PKIX_PolicyNode *equalNode,
+ PKIX_PolicyNode *diffNode,
+ char *expectedAscii)
+{
+ PKIX_PolicyNode *goodParent = NULL;
+ PKIX_PolicyNode *equalParent = NULL;
+ PKIX_PolicyNode *diffParent = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PolicyNode_GetParent");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetParent(goodNode, &goodParent, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetParent(equalNode, &equalParent, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetParent(diffNode, &diffParent, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodParent,
+ equalParent,
+ diffParent,
+ expectedAscii,
+ CertPolicyNode,
+ NULL);
+
+cleanup:
+ PKIX_TEST_DECREF_AC(goodParent);
+ PKIX_TEST_DECREF_AC(equalParent);
+ PKIX_TEST_DECREF_AC(diffParent);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This test is the same as testDuplicateHelper, except that it
+ * produces a more useful "Actual value" and "Expected value"
+ * in the case of an unexpected mismatch.
+ */
+static void
+test_DuplicateHelper(PKIX_PolicyNode *object, void *plContext)
+{
+ PKIX_PolicyNode *newObject = NULL;
+ PKIX_Boolean cmpResult;
+ PKIX_PL_String *original = NULL;
+ PKIX_PL_String *copy = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("testing pkix_PolicyNode_Duplicate");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate((PKIX_PL_Object *)object,
+ (PKIX_PL_Object **)&newObject,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)object,
+ (PKIX_PL_Object *)newObject,
+ &cmpResult,
+ plContext));
+
+ if (!cmpResult) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)object, &original, plContext));
+ testError("unexpected mismatch");
+ (void)printf("original value:\t%s\n", original->escAsciiString);
+
+ if (newObject) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)newObject, &copy, plContext));
+ (void)printf("copy value:\t%s\n", copy->escAsciiString);
+ } else {
+ (void)printf("copy value:\t(NULL)\n");
+ }
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(newObject);
+ PKIX_TEST_DECREF_AC(original);
+ PKIX_TEST_DECREF_AC(copy);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_GetValidPolicy(
+ PKIX_PolicyNode *goodNode,
+ PKIX_PolicyNode *equalNode,
+ PKIX_PolicyNode *diffNode,
+ char *expectedAscii)
+{
+ PKIX_PL_OID *goodPolicy = NULL;
+ PKIX_PL_OID *equalPolicy = NULL;
+ PKIX_PL_OID *diffPolicy = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PolicyNode_GetValidPolicy");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetValidPolicy(goodNode, &goodPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetValidPolicy(equalNode, &equalPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetValidPolicy(diffNode, &diffPolicy, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodPolicy, equalPolicy, diffPolicy, expectedAscii, OID, NULL);
+
+cleanup:
+ PKIX_TEST_DECREF_AC(goodPolicy);
+ PKIX_TEST_DECREF_AC(equalPolicy);
+ PKIX_TEST_DECREF_AC(diffPolicy);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_GetPolicyQualifiers(
+ PKIX_PolicyNode *goodNode,
+ PKIX_PolicyNode *equalNode,
+ PKIX_PolicyNode *diffNode,
+ char *expectedAscii)
+{
+ PKIX_Boolean isImmutable = PKIX_FALSE;
+ PKIX_List *goodList = NULL;
+ PKIX_List *equalList = NULL;
+ PKIX_List *diffList = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PolicyNode_GetPolicyQualifiers");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetPolicyQualifiers(goodNode, &goodList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetPolicyQualifiers(equalNode, &equalList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetPolicyQualifiers(diffNode, &diffList, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodList, equalList, diffList, expectedAscii, List, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsImmutable(goodList, &isImmutable, plContext));
+
+ if (isImmutable != PKIX_TRUE) {
+ testError("PKIX_PolicyNode_GetPolicyQualifiers returned a mutable List");
+ }
+cleanup:
+ PKIX_TEST_DECREF_AC(goodList);
+ PKIX_TEST_DECREF_AC(equalList);
+ PKIX_TEST_DECREF_AC(diffList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_GetExpectedPolicies(
+ PKIX_PolicyNode *goodNode,
+ PKIX_PolicyNode *equalNode,
+ PKIX_PolicyNode *diffNode,
+ char *expectedAscii)
+{
+ PKIX_Boolean isImmutable = PKIX_FALSE;
+ PKIX_List *goodList = NULL;
+ PKIX_List *equalList = NULL;
+ PKIX_List *diffList = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PolicyNode_GetExpectedPolicies");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetExpectedPolicies(goodNode, &goodList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetExpectedPolicies(equalNode, &equalList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetExpectedPolicies(diffNode, &diffList, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodList, equalList, diffList, expectedAscii, List, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsImmutable(goodList, &isImmutable, plContext));
+
+ if (isImmutable != PKIX_TRUE) {
+ testError("PKIX_PolicyNode_GetExpectedPolicies returned a mutable List");
+ }
+cleanup:
+ PKIX_TEST_DECREF_AC(goodList);
+ PKIX_TEST_DECREF_AC(equalList);
+ PKIX_TEST_DECREF_AC(diffList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_IsCritical(
+ PKIX_PolicyNode *goodNode,
+ PKIX_PolicyNode *equalNode,
+ PKIX_PolicyNode *diffNode)
+{
+ PKIX_Boolean goodBool = PKIX_FALSE;
+ PKIX_Boolean equalBool = PKIX_FALSE;
+ PKIX_Boolean diffBool = PKIX_FALSE;
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PolicyNode_IsCritical");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_IsCritical(goodNode, &goodBool, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_IsCritical(equalNode, &equalBool, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_IsCritical(diffNode, &diffBool, plContext));
+
+ if ((!goodBool) || (!equalBool) || (diffBool)) {
+ testError("IsCritical returned unexpected value");
+ }
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_GetDepth(
+ PKIX_PolicyNode *depth1Node,
+ PKIX_PolicyNode *depth2Node,
+ PKIX_PolicyNode *depth3Node)
+{
+ PKIX_UInt32 depth1 = 0;
+ PKIX_UInt32 depth2 = 0;
+ PKIX_UInt32 depth3 = 0;
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PolicyNode_GetDepth");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetDepth(depth1Node, &depth1, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetDepth(depth2Node, &depth2, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetDepth(depth3Node, &depth3, plContext));
+
+ if ((depth1 != 1) || (depth2 != 2) || (depth3 != 3)) {
+ testError("GetDepth returned unexpected value");
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_policynode <NIST_FILES_DIR> \n\n");
+}
+
+int
+test_policynode(int argc, char *argv[])
+{
+
+ /*
+ * Create a tree with parent = anyPolicy,
+ * child1 with Nist1+Nist2, child2 with Nist1.
+ * Give each child another child, with policies Nist2
+ * and Nist1, respectively. Pruning with a depth of two
+ * should have no effect. Give one of the children
+ * another child. Then pruning with a depth of three
+ * should reduce the tree to a single strand, as child1
+ * and child3 are removed.
+ *
+ * parent (anyPolicy)
+ * / \
+ * child1(Nist1+Nist2) child2(Nist1)
+ * | |
+ * child3(Nist2) child4(Nist1)
+ * |
+ * child5(Nist1)
+ *
+ */
+ char *asciiAnyPolicy = "2.5.29.32.0";
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_CertPolicyInfo *nist1Policy = NULL;
+ PKIX_PL_CertPolicyInfo *nist2Policy = NULL;
+ PKIX_List *policyQualifierList = NULL;
+ PKIX_PL_OID *oidAnyPolicy = NULL;
+ PKIX_PL_OID *oidNist1Policy = NULL;
+ PKIX_PL_OID *oidNist2Policy = NULL;
+ PKIX_List *expectedAnyList = NULL;
+ PKIX_List *expectedNist1List = NULL;
+ PKIX_List *expectedNist2List = NULL;
+ PKIX_List *expectedNist1Nist2List = NULL;
+ PKIX_List *emptyList = NULL;
+ PKIX_PolicyNode *parentNode = NULL;
+ PKIX_PolicyNode *childNode1 = NULL;
+ PKIX_PolicyNode *childNode2 = NULL;
+ PKIX_PolicyNode *childNode3 = NULL;
+ PKIX_PolicyNode *childNode4 = NULL;
+ PKIX_PolicyNode *childNode5 = NULL;
+ PKIX_PL_String *parentString = NULL;
+ PKIX_Boolean pDelete = PKIX_FALSE;
+ char *expectedParentAscii =
+ "{2.16.840.1.101.3.2.1.48.2,(1.3.6.1.5.5.7.2.2:[30 5C "
+ "1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 65"
+ " 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D 2"
+ "0 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 69 "
+ "73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 66"
+ " 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20 6"
+ "F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.1[(1.3"
+ ".6.1.5.5.7.2.2:[30 5C 1A 5A 71 31 3A 20 20 54 68 69 7"
+ "3 20 69 73 20 74 68 65 20 75 73 65 72 20 6E 6F 74 69 "
+ "63 65 20 66 72 6F 6D 20 71 75 61 6C 69 66 69 65 72 20"
+ " 31 2E 20 20 54 68 69 73 20 63 65 72 74 69 66 69 63 6"
+ "1 74 65 20 69 73 20 66 6F 72 20 74 65 73 74 20 70 75 "
+ "72 70 6F 73 65 73 20 6F 6E 6C 79])], 2.16.840.1.101.3"
+ ".2.1.48.2[(1.3.6.1.5.5.7.2.2:[30 5A 1A 58 71 32 3A 20"
+ " 20 54 68 69 73 20 69 73 20 74 68 65 20 75 73 65 72 2"
+ "0 6E 6F 74 69 63 65 20 66 72 6F 6D 20 71 75 61 6C 69 "
+ "66 69 65 72 20 32 2E 20 20 54 68 69 73 20 75 73 65 72"
+ " 20 6E 6F 74 69 63 65 20 73 68 6F 75 6C 64 20 6E 6F 7"
+ "4 20 62 65 20 64 69 73 70 6C 61 79 65 64])]),1}\n"
+ ". {2.16.840.1.101.3.2.1.48.2,(1.3.6.1.5.5.7.2.2:[30 5"
+ "C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 "
+ "65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D"
+ " 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 6"
+ "9 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 "
+ "66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20"
+ " 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.2),2}";
+ char *expectedValidAscii =
+ "2.16.840.1.101.3.2.1.48.2";
+ char *expectedQualifiersAscii =
+ /* "(1.3.6.1.5.5.7.2.2)"; */
+ "(1.3.6.1.5.5.7.2.2:[30 5C 1A 5A 71 31 3A 20 20 54 68 "
+ "69 73 20 69 73 20 74 68 65 20 75 73 65 72 20 6E 6F 74"
+ " 69 63 65 20 66 72 6F 6D 20 71 75 61 6C 69 66 69 65 7"
+ "2 20 31 2E 20 20 54 68 69 73 20 63 65 72 74 69 66 69 "
+ "63 61 74 65 20 69 73 20 66 6F 72 20 74 65 73 74 20 70"
+ " 75 72 70 6F 73 65 73 20 6F 6E 6C 79])";
+ char *expectedPoliciesAscii =
+ "(2.16.840.1.101.3.2.1.48.1)";
+ char *expectedTree =
+ "{2.5.29.32.0,{},Critical,(2.5.29.32.0),0}\n"
+ ". {2.16.840.1.101.3.2.1.48.2,(1.3.6.1.5.5.7.2.2:[30 5"
+ "C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 "
+ "65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D"
+ " 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 6"
+ "9 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 "
+ "66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20"
+ " 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.1[(1"
+ ".3.6.1.5.5.7.2.2:[30 5C 1A 5A 71 31 3A 20 20 54 68 69"
+ " 73 20 69 73 20 74 68 65 20 75 73 65 72 20 6E 6F 74 6"
+ "9 63 65 20 66 72 6F 6D 20 71 75 61 6C 69 66 69 65 72 "
+ "20 31 2E 20 20 54 68 69 73 20 63 65 72 74 69 66 69 63"
+ " 61 74 65 20 69 73 20 66 6F 72 20 74 65 73 74 20 70 7"
+ "5 72 70 6F 73 65 73 20 6F 6E 6C 79])], 2.16.840.1.101"
+ ".3.2.1.48.2[(1.3.6.1.5.5.7.2.2:[30 5A 1A 58 71 32 3A "
+ "20 20 54 68 69 73 20 69 73 20 74 68 65 20 75 73 65 72"
+ " 20 6E 6F 74 69 63 65 20 66 72 6F 6D 20 71 75 61 6C 6"
+ "9 66 69 65 72 20 32 2E 20 20 54 68 69 73 20 75 73 65 "
+ "72 20 6E 6F 74 69 63 65 20 73 68 6F 75 6C 64 20 6E 6F"
+ " 74 20 62 65 20 64 69 73 70 6C 61 79 65 64])]"
+ "),1}\n"
+ ". . {2.16.840.1.101.3.2.1.48.2,(1.3.6.1.5.5.7.2.2:[30"
+ " 5C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 6"
+ "8 65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F "
+ "6D 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68"
+ " 69 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 2"
+ "0 66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 "
+ "20 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.2)"
+ ",2}\n"
+ ". {2.16.840.1.101.3.2.1.48.1,(1.3.6.1.5.5.7.2.2:[30 5"
+ "C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 "
+ "65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D"
+ " 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 6"
+ "9 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 "
+ "66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20"
+ " 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.1),1}\n"
+ ". . {2.16.840.1.101.3.2.1.48.1,(EMPTY),Not Critical,"
+ "(2.16.840.1.101.3.2.1.48.1),2}\n"
+ ". . . {2.16.840.1.101.3.2.1.48.1,{},Critical,(2.16.84"
+ "0.1.101.3.2.1.48.1),3}";
+ char *expectedPrunedTree =
+ "{2.5.29.32.0,{},Critical,(2.5.29.32.0),0}\n"
+ ". {2.16.840.1.101.3.2.1.48.1,(1.3.6.1.5.5.7.2.2:[30 5"
+ "C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 "
+ "65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D"
+ " 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 6"
+ "9 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 "
+ "66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20"
+ " 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.1),1}\n"
+ ". . {2.16.840.1.101.3.2.1.48.1,(EMPTY),Not Critical,"
+ "(2.16.840.1.101.3.2.1.48.1),2}\n"
+ ". . . {2.16.840.1.101.3.2.1.48.1,{},Critical,(2.16.84"
+ "0.1.101.3.2.1.48.1),3}";
+
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ char *dirName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 2) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("PolicyNode");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ dirName = argv[j + 1];
+
+ subTest("Creating OID objects");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(asciiAnyPolicy, &oidAnyPolicy, plContext));
+
+ /* Read certificates to get real policies, qualifiers */
+
+ cert = createCert(dirName, "UserNoticeQualifierTest16EE.crt", plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(cert, &expectedNist1Nist2List, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(expectedNist1Nist2List,
+ 0,
+ (PKIX_PL_Object **)&nist1Policy,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(expectedNist1Nist2List,
+ 1,
+ (PKIX_PL_Object **)&nist2Policy,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(nist1Policy, &policyQualifierList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId(nist1Policy, &oidNist1Policy, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId(nist2Policy, &oidNist2Policy, plContext));
+
+ subTest("Creating expectedPolicy List objects");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&expectedAnyList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&expectedNist1List, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&expectedNist2List, plContext));
+
+ subTest("Populating expectedPolicy List objects");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(expectedAnyList, (PKIX_PL_Object *)oidAnyPolicy, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(expectedNist1List,
+ (PKIX_PL_Object *)oidNist1Policy,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(expectedNist2List,
+ (PKIX_PL_Object *)oidNist2Policy,
+ plContext));
+
+ subTest("Creating PolicyNode objects");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&emptyList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create(oidAnyPolicy,
+ NULL,
+ PKIX_TRUE,
+ expectedAnyList,
+ &parentNode,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create(oidNist2Policy,
+ policyQualifierList,
+ PKIX_TRUE,
+ expectedNist1Nist2List,
+ &childNode1,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create(oidNist1Policy,
+ policyQualifierList,
+ PKIX_TRUE,
+ expectedNist1List,
+ &childNode2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create(oidNist2Policy,
+ policyQualifierList,
+ PKIX_TRUE,
+ expectedNist2List,
+ &childNode3,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create(oidNist1Policy,
+ emptyList,
+ PKIX_FALSE,
+ expectedNist1List,
+ &childNode4,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create(oidNist1Policy,
+ NULL,
+ PKIX_TRUE,
+ expectedNist1List,
+ &childNode5,
+ plContext));
+
+ subTest("Creating the PolicyNode tree");
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent(parentNode, childNode1, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent(parentNode, childNode2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent(childNode1, childNode3, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent(childNode2, childNode4, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent(childNode4, childNode5, plContext));
+
+ subTest("Displaying PolicyNode objects");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)parentNode, &parentString, plContext));
+ (void)printf("parentNode is\n\t%s\n", parentString->escAsciiString);
+
+ testToStringHelper((PKIX_PL_Object *)parentNode, expectedTree, plContext);
+
+ test_DuplicateHelper(parentNode, plContext);
+
+ test_GetParent(childNode3, childNode3, childNode4, expectedParentAscii);
+ test_GetValidPolicy(childNode1, childNode3, parentNode, expectedValidAscii);
+ test_GetPolicyQualifiers(childNode1, childNode3, childNode4, expectedQualifiersAscii);
+ test_GetExpectedPolicies(childNode2, childNode4, childNode3, expectedPoliciesAscii);
+ test_IsCritical(childNode1, childNode2, childNode4);
+ test_GetDepth(childNode2, childNode4, childNode5);
+
+ subTest("pkix_PolicyNode_Prune");
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Prune(parentNode, 2, &pDelete, plContext));
+
+ testToStringHelper((PKIX_PL_Object *)parentNode, expectedTree, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Prune(parentNode, 3, &pDelete, plContext));
+
+ testToStringHelper((PKIX_PL_Object *)parentNode, expectedPrunedTree, plContext);
+
+ test_GetChildren(parentNode, parentNode, childNode2);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(nist1Policy);
+ PKIX_TEST_DECREF_AC(nist2Policy);
+ PKIX_TEST_DECREF_AC(policyQualifierList);
+ PKIX_TEST_DECREF_AC(oidAnyPolicy);
+ PKIX_TEST_DECREF_AC(oidNist1Policy);
+ PKIX_TEST_DECREF_AC(oidNist2Policy);
+ PKIX_TEST_DECREF_AC(expectedAnyList);
+ PKIX_TEST_DECREF_AC(expectedNist1List);
+ PKIX_TEST_DECREF_AC(expectedNist2List);
+ PKIX_TEST_DECREF_AC(expectedNist1Nist2List);
+ PKIX_TEST_DECREF_AC(emptyList);
+ PKIX_TEST_DECREF_AC(parentNode);
+ PKIX_TEST_DECREF_AC(childNode1);
+ PKIX_TEST_DECREF_AC(childNode2);
+ PKIX_TEST_DECREF_AC(childNode3);
+ PKIX_TEST_DECREF_AC(childNode4);
+ PKIX_TEST_DECREF_AC(childNode5);
+ PKIX_TEST_DECREF_AC(parentString);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("PolicyNode");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/results/test_valresult.c b/security/nss/cmd/libpkix/pkix/results/test_valresult.c
new file mode 100644
index 000000000..7760a431e
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/results/test_valresult.c
@@ -0,0 +1,199 @@
+/* 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/. */
+/*
+ * test_valresult.c
+ *
+ * Test ValidateResult Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ValidateResult_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetPublicKey(
+ PKIX_ValidateResult *goodObject,
+ PKIX_ValidateResult *equalObject)
+{
+
+ PKIX_PL_PublicKey *goodPubKey = NULL;
+ PKIX_PL_PublicKey *equalPubKey = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ValidateResult_GetPublicKey");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetPublicKey(goodObject, &goodPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetPublicKey(equalObject, &equalPubKey, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)goodPubKey,
+ (PKIX_PL_Object *)equalPubKey,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodPubKey);
+ PKIX_TEST_DECREF_AC(equalPubKey);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetTrustAnchor(
+ PKIX_ValidateResult *goodObject,
+ PKIX_ValidateResult *equalObject)
+{
+
+ PKIX_TrustAnchor *goodAnchor = NULL;
+ PKIX_TrustAnchor *equalAnchor = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ValidateResult_GetTrustAnchor");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetTrustAnchor(goodObject, &goodAnchor, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetTrustAnchor(equalObject, &equalAnchor, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)goodAnchor,
+ (PKIX_PL_Object *)equalAnchor,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodAnchor);
+ PKIX_TEST_DECREF_AC(equalAnchor);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetPolicyTree(
+ PKIX_ValidateResult *goodObject,
+ PKIX_ValidateResult *equalObject)
+{
+
+ PKIX_PolicyNode *goodTree = NULL;
+ PKIX_PolicyNode *equalTree = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ValidateResult_GetPolicyTree");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetPolicyTree(goodObject, &goodTree, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetPolicyTree(equalObject, &equalTree, plContext));
+
+ if (goodTree) {
+ testEqualsHelper((PKIX_PL_Object *)goodTree,
+ (PKIX_PL_Object *)equalTree,
+ PKIX_TRUE,
+ plContext);
+ } else if (equalTree) {
+ pkixTestErrorMsg = "Mismatch: NULL and non-NULL Policy Trees";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodTree);
+ PKIX_TEST_DECREF_AC(equalTree);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(char *pName)
+{
+ printf("\nUSAGE: %s <central-data-dir>\n\n", pName);
+}
+
+int
+test_valresult(int argc, char *argv[])
+{
+
+ PKIX_ValidateResult *goodObject = NULL;
+ PKIX_ValidateResult *equalObject = NULL;
+ PKIX_ValidateResult *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ char *goodInput = "yassir2yassir";
+ char *diffInput = "yassir2bcn";
+ char *dirName = NULL;
+
+ char *expectedAscii =
+ "[\n"
+ "\tTrustAnchor: \t\t"
+ "[\n"
+ "\tTrusted CA Name: "
+ "CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tTrusted CA PublicKey: ANSI X9.57 DSA Signature\n"
+ "\tInitial Name Constraints:(null)\n"
+ "]\n"
+ "\tPubKey: \t\t"
+ "ANSI X9.57 DSA Signature\n"
+ "\tPolicyTree: \t\t(null)\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("ValidateResult");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 2) {
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ dirName = argv[j + 1];
+
+ subTest("pkix_ValidateResult_Create");
+
+ goodObject = createValidateResult(dirName, goodInput, diffInput, plContext);
+ equalObject = createValidateResult(dirName, goodInput, diffInput, plContext);
+ diffObject = createValidateResult(dirName, diffInput, goodInput, plContext);
+
+ testGetPublicKey(goodObject, equalObject);
+ testGetTrustAnchor(goodObject, equalObject);
+ testGetPolicyTree(goodObject, equalObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ expectedAscii,
+ ValidateResult,
+ PKIX_FALSE);
+
+ testDestroy(goodObject, equalObject, diffObject);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ValidateResult");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/results/test_verifynode.c b/security/nss/cmd/libpkix/pkix/results/test_verifynode.c
new file mode 100644
index 000000000..21c61aa96
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/results/test_verifynode.c
@@ -0,0 +1,112 @@
+/* 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/. */
+/*
+ * test_verifynode.c
+ *
+ * Test VerifyNode Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_verifynode path cert1 cert2 cert3\n\n");
+}
+
+int
+test_verifynode(int argc, char *argv[])
+{
+
+ /*
+ * Create a tree with parent = cert1, child=cert2, grandchild=cert3
+ */
+ PKIX_PL_Cert *cert1 = NULL;
+ PKIX_PL_Cert *cert2 = NULL;
+ PKIX_PL_Cert *cert3 = NULL;
+ PKIX_VerifyNode *parentNode = NULL;
+ PKIX_VerifyNode *childNode = NULL;
+ PKIX_VerifyNode *grandChildNode = NULL;
+ PKIX_PL_String *parentString = NULL;
+
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ char *dirName = NULL;
+ char *twoNodeAscii = "CERT[Issuer:CN=Trust Anchor,O=Test Cert"
+ "ificates,C=US, Subject:CN=Trust Anchor,O=Test Certif"
+ "icates,C=US], depth=0, error=(null)\n. CERT[Issuer:C"
+ "N=Trust Anchor,O=Test Certificates,C=US, Subject:CN="
+ "Good CA,O=Test Certificates,C=US], depth=1, error=(null)";
+ char *threeNodeAscii = "CERT[Issuer:CN=Trust Anchor,O=Test Ce"
+ "rtificates,C=US, Subject:CN=Trust Anchor,O=Test Cert"
+ "ificates,C=US], depth=0, error=(null)\n. CERT[Issuer"
+ ":CN=Trust Anchor,O=Test Certificates,C=US, Subject:C"
+ "N=Good CA,O=Test Certificates,C=US], depth=1, error="
+ "(null)\n. . CERT[Issuer:CN=Good CA,O=Test Certificat"
+ "es,C=US, Subject:CN=Valid EE Certificate Test1,O=Tes"
+ "t Certificates,C=US], depth=2, error=(null)";
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 3) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("VerifyNode");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ dirName = argv[++j];
+
+ subTest("Creating Certs");
+
+ cert1 = createCert(dirName, argv[++j], plContext);
+
+ cert2 = createCert(dirName, argv[++j], plContext);
+
+ cert3 = createCert(dirName, argv[++j], plContext);
+
+ subTest("Creating VerifyNode objects");
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_VerifyNode_Create(cert1, 0, NULL, &parentNode, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_VerifyNode_Create(cert2, 1, NULL, &childNode, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_VerifyNode_Create(cert3, 2, NULL, &grandChildNode, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_VerifyNode_AddToChain(parentNode, childNode, plContext));
+
+ subTest("Creating VerifyNode ToString objects");
+
+ testToStringHelper((PKIX_PL_Object *)parentNode, twoNodeAscii, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_VerifyNode_AddToChain(parentNode, grandChildNode, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)parentNode, &parentString, plContext));
+ (void)printf("parentNode is\n\t%s\n", parentString->escAsciiString);
+
+ testToStringHelper((PKIX_PL_Object *)parentNode, threeNodeAscii, plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(cert1);
+ PKIX_TEST_DECREF_AC(cert2);
+ PKIX_TEST_DECREF_AC(parentNode);
+ PKIX_TEST_DECREF_AC(childNode);
+ PKIX_TEST_DECREF_AC(parentString);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("VerifyNode");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/store/Makefile b/security/nss/cmd/libpkix/pkix/store/Makefile
new file mode 100755
index 000000000..09ca5f1c6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/store/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/security/nss/cmd/libpkix/pkix/store/manifest.mn b/security/nss/cmd/libpkix/pkix/store/manifest.mn
new file mode 100755
index 000000000..566a34684
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/store/manifest.mn
@@ -0,0 +1,19 @@
+#
+# 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/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_store.c
+
+LIBRARY_NAME=pkixtoolstore
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/store/test_store.c b/security/nss/cmd/libpkix/pkix/store/test_store.c
new file mode 100644
index 000000000..59606b892
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/store/test_store.c
@@ -0,0 +1,194 @@
+/* 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/. */
+/*
+ * test_certstore.c
+ *
+ * Test CertStore Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static PKIX_Error *
+testCRLCallback(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrls, /* list of PKIX_PL_Crl */
+ void *plContext)
+{
+ return (0);
+}
+
+static PKIX_Error *
+testCRLContinue(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrls, /* list of PKIX_PL_Crl */
+ void *plContext)
+{
+ return (0);
+}
+
+static PKIX_Error *
+testCertCallback(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCerts, /* list of PKIX_PL_Cert */
+ void *plContext)
+{
+ return (0);
+}
+
+static PKIX_Error *
+testCertContinue(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCerts, /* list of PKIX_PL_Cert */
+ void *plContext)
+{
+ return (0);
+}
+
+static char *
+catDirName(char *platform, char *dir, void *plContext)
+{
+ char *pathName = NULL;
+ PKIX_UInt32 dirLen;
+ PKIX_UInt32 platformLen;
+
+ PKIX_TEST_STD_VARS();
+
+ dirLen = PL_strlen(dir);
+ platformLen = PL_strlen(platform);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc(platformLen +
+ dirLen +
+ 2,
+ (void **)&pathName, plContext));
+
+ PL_strcpy(pathName, platform);
+ PL_strcat(pathName, "/");
+ PL_strcat(pathName, dir);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (pathName);
+}
+
+static void
+testCertStore(char *crlDir)
+{
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_PL_Object *getCertStoreContext = NULL;
+ PKIX_CertStore_CertCallback certCallback = NULL;
+ PKIX_CertStore_CRLCallback crlCallback = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ crlDir,
+ 0,
+ &dirString,
+ plContext));
+
+ subTest("PKIX_CertStore_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_Create(testCertCallback,
+ testCRLCallback,
+ testCertContinue,
+ testCRLContinue,
+ NULL, /* trustCallback */
+ (PKIX_PL_Object *)dirString,
+ PKIX_TRUE, /* cacheFlag */
+ PKIX_TRUE, /* local */
+ &certStore,
+ plContext));
+
+ subTest("PKIX_CertStore_GetCertCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &certCallback, plContext));
+
+ if (certCallback != testCertCallback) {
+ testError("PKIX_CertStore_GetCertCallback unexpected mismatch");
+ }
+
+ subTest("PKIX_CertStore_GetCRLCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCRLCallback(certStore, &crlCallback, plContext));
+
+ if (crlCallback != testCRLCallback) {
+ testError("PKIX_CertStore_GetCRLCallback unexpected mismatch");
+ }
+
+ subTest("PKIX_CertStore_GetCertStoreContext");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertStoreContext(certStore, &getCertStoreContext, plContext));
+
+ if ((PKIX_PL_Object *)dirString != getCertStoreContext) {
+ testError("PKIX_CertStore_GetCertStoreContext unexpected mismatch");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(getCertStoreContext);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(char *pName)
+{
+ printf("\nUSAGE: %s testName <data-dir> <platform-dir>\n\n", pName);
+}
+
+/* Functional tests for CertStore public functions */
+
+int
+test_store(int argc, char *argv[])
+{
+
+ char *platformDir = NULL;
+ char *dataDir = NULL;
+ char *combinedDir = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < (3 + j)) {
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ startTests(argv[1 + j]);
+
+ dataDir = argv[2 + j];
+ platformDir = argv[3 + j];
+ combinedDir = catDirName(platformDir, dataDir, plContext);
+
+ testCertStore(combinedDir);
+
+cleanup:
+
+ pkixTestErrorResult = PKIX_PL_Free(combinedDir, plContext);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CertStore");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/Makefile b/security/nss/cmd/libpkix/pkix/top/Makefile
new file mode 100755
index 000000000..09ca5f1c6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/security/nss/cmd/libpkix/pkix/top/manifest.mn b/security/nss/cmd/libpkix/pkix/top/manifest.mn
new file mode 100755
index 000000000..a7d997dfb
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/manifest.mn
@@ -0,0 +1,33 @@
+#
+# 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/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_basicchecker.c \
+ test_basicconstraintschecker.c \
+ test_buildchain.c \
+ test_buildchain_uchecker.c \
+ test_buildchain_partialchain.c \
+ test_buildchain_resourcelimits.c \
+ test_customcrlchecker.c \
+ test_defaultcrlchecker2stores.c \
+ test_ocsp.c \
+ test_policychecker.c \
+ test_subjaltnamechecker.c \
+ test_validatechain.c \
+ test_validatechain_bc.c \
+ test_validatechain_NB.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtooltop
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/top/test_basicchecker.c b/security/nss/cmd/libpkix/pkix/top/test_basicchecker.c
new file mode 100644
index 000000000..658bf67be
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_basicchecker.c
@@ -0,0 +1,238 @@
+/* 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/. */
+/*
+ * test_basicchecker.c
+ *
+ * Test Basic Checking
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testPass(char *dirName, char *goodInput, char *diffInput, char *dateAscii)
+{
+
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Basic-Common-Fields <pass>");
+ /*
+ * Tests the Expiration, NameChaining, and Signature Checkers
+ */
+
+ chain = createCertChain(dirName, goodInput, diffInput, plContext);
+
+ valParams = createValidateParams(dirName,
+ goodInput,
+ diffInput,
+ dateAscii,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)verifyTree, &verifyString, plContext));
+ (void)printf("verifyTree is\n%s\n", verifyString->escAsciiString);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testNameChainingFail(
+ char *dirName,
+ char *goodInput,
+ char *diffInput,
+ char *dateAscii)
+{
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("NameChaining <fail>");
+
+ chain = createCertChain(dirName, diffInput, goodInput, plContext);
+
+ valParams = createValidateParams(dirName,
+ goodInput,
+ diffInput,
+ dateAscii,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDateFail(char *dirName, char *goodInput, char *diffInput)
+{
+
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ chain = createCertChain(dirName, goodInput, diffInput, plContext);
+
+ subTest("Expiration <fail>");
+ valParams = createValidateParams(dirName,
+ goodInput,
+ diffInput,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain(valParams, &valResult, NULL, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testSignatureFail(
+ char *dirName,
+ char *goodInput,
+ char *diffInput,
+ char *dateAscii)
+{
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Signature <fail>");
+
+ chain = createCertChain(dirName, diffInput, goodInput, plContext);
+
+ valParams = createValidateParams(dirName,
+ goodInput,
+ diffInput,
+ dateAscii,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain(valParams, &valResult, NULL, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(char *pName)
+{
+ printf("\nUSAGE: %s <central-data-dir>\n\n", pName);
+}
+
+int
+test_basicchecker(int argc, char *argv[])
+{
+
+ char *goodInput = "yassir2yassir";
+ char *diffInput = "yassir2bcn";
+ char *dateAscii = "991201000000Z";
+ char *dirName = NULL;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 actualMinorVersion;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("SignatureChecker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 2) {
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ dirName = argv[j + 1];
+
+ /* The NameChaining, Expiration, and Signature Checkers all pass */
+ testPass(dirName, goodInput, diffInput, dateAscii);
+
+ /* Individual Checkers fail */
+ testNameChainingFail(dirName, goodInput, diffInput, dateAscii);
+ testDateFail(dirName, goodInput, diffInput);
+
+/*
+ * XXX
+ * since the signature check is done last, we need to create
+ * certs whose name chaining passes, but their signatures fail;
+ * we currently don't have any such certs.
+ */
+/* testSignatureFail(goodInput, diffInput, dateAscii); */
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("SignatureChecker");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/test_basicconstraintschecker.c b/security/nss/cmd/libpkix/pkix/top/test_basicconstraintschecker.c
new file mode 100644
index 000000000..eba5153ac
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_basicconstraintschecker.c
@@ -0,0 +1,145 @@
+/* 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/. */
+/*
+ * test_basicconstraintschecker.c
+ *
+ * Test Basic Constraints Checking
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TEST_MAX_CERTS 10
+
+static void *plContext = NULL;
+
+static void
+printUsage1(char *pName)
+{
+ printf("\nUSAGE: %s test-name [ENE|EE] ", pName);
+ printf("cert [certs].\n");
+}
+
+static void
+printUsageMax(PKIX_UInt32 numCerts)
+{
+ printf("\nUSAGE ERROR: number of certs %d exceed maximum %d\n",
+ numCerts, PKIX_TEST_MAX_CERTS);
+}
+
+int
+test_basicconstraintschecker(int argc, char *argv[])
+{
+
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ char *certNames[PKIX_TEST_MAX_CERTS];
+ PKIX_PL_Cert *certs[PKIX_TEST_MAX_CERTS];
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean testValid = PKIX_FALSE;
+ char *dirName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 4) {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ startTests("BasicConstraintsChecker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2 + j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2 + j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ dirName = argv[3 + j];
+
+ chainLength = (argc - j) - 4;
+ if (chainLength > PKIX_TEST_MAX_CERTS) {
+ printUsageMax(chainLength);
+ }
+
+ for (i = 0; i < chainLength; i++) {
+ certNames[i] = argv[(4 + j) + i];
+ certs[i] = NULL;
+ }
+
+ subTest(argv[1 + j]);
+
+ subTest("Basic-Constraints - Create Cert Chain");
+
+ chain = createCertChainPlus(dirName, certNames, certs, chainLength, plContext);
+
+ /*
+ * Error occurs when creating Cert, this is critical and test
+ * should not continue. Since we expect error, we assume this
+ * error is the one that is expected, so undo the error count.
+ *
+ * This work needs future enhancement. We will introduce another
+ * flag ESE, in addition to the existing EE(expect validation
+ * error) and ENE(expect no validation error). ESE stands for
+ * "expect setup error". When running with ESE, if any of the setup
+ * calls such creating Cert Chain fails, the test can end and
+ * considered to be successful.
+ */
+ if (testValid == PKIX_FALSE && chain == NULL) {
+ testErrorUndo("Cert Error - Create failed");
+ goto cleanup;
+ }
+
+ subTest("Basic-Constraints - Create Params");
+
+ valParams = createValidateParams(dirName,
+ argv[4 +
+ j],
+ NULL,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ subTest("Basic-Constraints - Validate Chain");
+
+ if (testValid == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+ } else {
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("BasicConstraintsChecker");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/test_buildchain.c b/security/nss/cmd/libpkix/pkix/top/test_buildchain.c
new file mode 100644
index 000000000..5c9ec5968
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_buildchain.c
@@ -0,0 +1,418 @@
+/* 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/. */
+/*
+ * test_buildchain.c
+ *
+ * Test BuildChain function
+ *
+ */
+
+/* #define debuggingWithoutRevocation */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define LDAP_PORT 389
+static PKIX_Boolean usebind = PKIX_FALSE;
+static PKIX_Boolean useLDAP = PKIX_FALSE;
+static char buf[PR_NETDB_BUF_SIZE];
+static char *serverName = NULL;
+static char *sepPtr = NULL;
+static PRNetAddr netAddr;
+static PRHostEnt hostent;
+static PKIX_UInt32 portNum = 0;
+static PRIntn hostenum = 0;
+static PRStatus prstatus = PR_FAILURE;
+static void *ipaddr = NULL;
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_buildchain [-arenas] [usebind] "
+ "servername[:port] <testName> [ENE|EE]\n"
+ "\t <certStoreDirectory> <targetCert>"
+ " <intermediate Certs...> <trustedCert>\n\n");
+ (void)printf("Builds a chain of certificates from <targetCert> to <trustedCert>\n"
+ "using the certs and CRLs in <certStoreDirectory>. "
+ "servername[:port] gives\n"
+ "the address of an LDAP server. If port is not"
+ " specified, port 389 is used. \"-\" means no LDAP server.\n"
+ "If ENE is specified, then an Error is Not Expected. "
+ "EE indicates an Error is Expected.\n");
+}
+
+static PKIX_Error *
+createLdapCertStore(
+ char *hostname,
+ PRIntervalTime timeout,
+ PKIX_CertStore **pLdapCertStore,
+ void *plContext)
+{
+ PRIntn backlog = 0;
+
+ char *bindname = "";
+ char *auth = "";
+
+ LDAPBindAPI bindAPI;
+ LDAPBindAPI *bindPtr = NULL;
+ PKIX_PL_LdapDefaultClient *ldapClient = NULL;
+ PKIX_CertStore *ldapCertStore = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (usebind) {
+ bindPtr = &bindAPI;
+ bindAPI.selector = SIMPLE_AUTH;
+ bindAPI.chooser.simple.bindName = bindname;
+ bindAPI.chooser.simple.authentication = auth;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapDefaultClient_CreateByName(hostname, timeout, bindPtr, &ldapClient, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapCertStore_Create((PKIX_PL_LdapClient *)ldapClient,
+ &ldapCertStore,
+ plContext));
+
+ *pLdapCertStore = ldapCertStore;
+cleanup:
+
+ PKIX_TEST_DECREF_AC(ldapClient);
+
+ PKIX_TEST_RETURN();
+
+ return (pkixTestErrorResult);
+}
+
+int
+test_buildchain(int argc, char *argv[])
+{
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_PL_PublicKey *trustedPubKey = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ char *dirName = NULL;
+ PKIX_PL_String *dirNameString = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_UInt32 actualMinorVersion = 0;
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 k = 0;
+ PKIX_CertStore *ldapCertStore = NULL;
+ PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT; /* blocking */
+ /* PRIntervalTime timeout = PR_INTERVAL_NO_WAIT; =0 for non-blocking */
+ PKIX_CertStore *certStore = NULL;
+ PKIX_List *certStores = NULL;
+ PKIX_List *revCheckers = NULL;
+ char *asciiResult = NULL;
+ PKIX_Boolean result = PKIX_FALSE;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ PKIX_List *expectedCerts = NULL;
+ PKIX_PL_Cert *dirCert = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+ PKIX_PL_String *actualCertsString = NULL;
+ PKIX_PL_String *expectedCertsString = NULL;
+ void *state = NULL;
+ char *actualCertsAscii = NULL;
+ char *expectedCertsAscii = NULL;
+ PRPollDesc *pollDesc = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("BuildChain");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /*
+ * arguments:
+ * [optional] -arenas
+ * [optional] usebind
+ * servername or servername:port ( - for no server)
+ * testname
+ * EE or ENE
+ * cert directory
+ * target cert (end entity)
+ * intermediate certs
+ * trust anchor
+ */
+
+ /* optional argument "usebind" for Ldap CertStore */
+ if (argv[j + 1]) {
+ if (PORT_Strcmp(argv[j + 1], "usebind") == 0) {
+ usebind = PKIX_TRUE;
+ j++;
+ }
+ }
+
+ if (PORT_Strcmp(argv[++j], "-") == 0) {
+ useLDAP = PKIX_FALSE;
+ } else {
+ serverName = argv[j];
+ useLDAP = PKIX_TRUE;
+ }
+
+ subTest(argv[++j]);
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[++j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage();
+ return (0);
+ }
+
+ dirName = argv[++j];
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&expectedCerts, plContext));
+
+ for (k = ++j; k < (PKIX_UInt32)argc; k++) {
+
+ dirCert = createCert(dirName, argv[k], plContext);
+
+ if (k == (PKIX_UInt32)(argc - 1)) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)dirCert, plContext));
+ trustedCert = dirCert;
+ } else {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(expectedCerts,
+ (PKIX_PL_Object *)dirCert,
+ plContext));
+
+ if (k == j) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)dirCert, plContext));
+ targetCert = dirCert;
+ }
+ }
+
+ PKIX_TEST_DECREF_BC(dirCert);
+ }
+
+ /* create processing params with list of trust anchors */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert(trustedCert, &anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create(anchors, &procParams, plContext));
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate(certSelParams, targetCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));
+
+ /* create CertStores */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, dirName, 0, &dirNameString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certStores, plContext));
+
+ if (useLDAP == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(createLdapCertStore(serverName, timeout, &ldapCertStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certStores,
+ (PKIX_PL_Object *)ldapCertStore,
+ plContext));
+ } else {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirNameString, &certStore, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore, plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores(procParams, certStores, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(trustedCert, &trustedPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(expectedCerts, &numCerts, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_DefaultRevChecker_Initialize(certStores,
+ NULL, /* testDate, may be NULL */
+ trustedPubKey,
+ numCerts,
+ &revChecker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(revCheckers, (PKIX_PL_Object *)revChecker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers(procParams, revCheckers, plContext));
+
+#ifdef debuggingWithoutRevocation
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_FALSE, plContext));
+#endif
+
+ /* build cert chain using processing params and return buildResult */
+
+ pkixTestErrorResult = PKIX_BuildChain(procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ &verifyTree,
+ plContext);
+
+ while (pollDesc != NULL) {
+
+ if (PR_Poll(pollDesc, 1, 0) < 0) {
+ testError("PR_Poll failed");
+ }
+
+ pkixTestErrorResult = PKIX_BuildChain(procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ &verifyTree,
+ plContext);
+ }
+
+ if (pkixTestErrorResult) {
+ if (testValid == PKIX_FALSE) { /* EE */
+ (void)printf("EXPECTED ERROR RECEIVED!\n");
+ } else { /* ENE */
+ testError("UNEXPECTED ERROR RECEIVED");
+ }
+ } else {
+ if (testValid == PKIX_TRUE) { /* ENE */
+ (void)printf("EXPECTED NON-ERROR RECEIVED!\n");
+ } else { /* EE */
+ (void)printf("UNEXPECTED NON-ERROR RECEIVED!\n");
+ }
+ }
+
+ subTest("Displaying VerifyNode objects");
+
+ if (verifyTree == NULL) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, "(null)", 0, &verifyString, plContext));
+ } else {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)verifyTree, &verifyString, plContext));
+ }
+
+ (void)printf("verifyTree is\n%s\n", verifyString->escAsciiString);
+
+ if (pkixTestErrorResult) {
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ goto cleanup;
+ }
+
+ if (buildResult) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetCertChain(buildResult, &certs, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ printf("\n");
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs,
+ i,
+ (PKIX_PL_Object **)&cert,
+ plContext));
+
+ asciiResult = PKIX_Cert2ASCII(cert);
+
+ printf("CERT[%d]:\n%s\n", i, asciiResult);
+
+ /* PKIX_Cert2ASCII used PKIX_PL_Malloc(...,,NULL) */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, NULL));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)certs,
+ (PKIX_PL_Object *)expectedCerts,
+ &result,
+ plContext));
+
+ if (!result) {
+ testError("BUILT CERTCHAIN IS "
+ "NOT THE ONE THAT WAS EXPECTED");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)certs,
+ &actualCertsString,
+ plContext));
+
+ actualCertsAscii = PKIX_String2ASCII(actualCertsString, plContext);
+ if (actualCertsAscii == NULL) {
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)expectedCerts,
+ &expectedCertsString,
+ plContext));
+
+ expectedCertsAscii = PKIX_String2ASCII(expectedCertsString, plContext);
+ if (expectedCertsAscii == NULL) {
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ (void)printf("Actual value:\t%s\n", actualCertsAscii);
+ (void)printf("Expected value:\t%s\n",
+ expectedCertsAscii);
+ }
+ }
+
+cleanup:
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+
+ PKIX_PL_Free(asciiResult, NULL);
+ PKIX_PL_Free(actualCertsAscii, plContext);
+ PKIX_PL_Free(expectedCertsAscii, plContext);
+
+ PKIX_TEST_DECREF_AC(state);
+ PKIX_TEST_DECREF_AC(actualCertsString);
+ PKIX_TEST_DECREF_AC(expectedCertsString);
+ PKIX_TEST_DECREF_AC(expectedCerts);
+ PKIX_TEST_DECREF_AC(buildResult);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certStores);
+ PKIX_TEST_DECREF_AC(revCheckers);
+ PKIX_TEST_DECREF_AC(revChecker);
+ PKIX_TEST_DECREF_AC(ldapCertStore);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(dirNameString);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(trustedCert);
+ PKIX_TEST_DECREF_AC(trustedPubKey);
+
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(targetCert);
+
+ PKIX_TEST_RETURN();
+
+ PKIX_Shutdown(plContext);
+
+ endTests("BuildChain");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/test_buildchain_partialchain.c b/security/nss/cmd/libpkix/pkix/top/test_buildchain_partialchain.c
new file mode 100644
index 000000000..4861a8e32
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_buildchain_partialchain.c
@@ -0,0 +1,725 @@
+/* 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/. */
+/*
+ * test_buildchain_partialchain.c
+ *
+ * Test BuildChain function
+ *
+ */
+
+#define debuggingWithoutRevocation
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define LDAP_PORT 389
+static PKIX_Boolean usebind = PKIX_FALSE;
+static PKIX_Boolean useLDAP = PKIX_FALSE;
+static char buf[PR_NETDB_BUF_SIZE];
+static char *serverName = NULL;
+static char *sepPtr = NULL;
+static PRNetAddr netAddr;
+static PRHostEnt hostent;
+static PKIX_UInt32 portNum = 0;
+static PRIntn hostenum = 0;
+static PRStatus prstatus = PR_FAILURE;
+static void *ipaddr = NULL;
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_buildchain [-arenas] [usebind] "
+ "servername[:port] <testName> [ENE|EE]\n"
+ "\t <certStoreDirectory> <targetCert>"
+ " <intermediate Certs...> <trustedCert>\n\n");
+ (void)printf("Builds a chain of certificates from <targetCert> to <trustedCert>\n"
+ "using the certs and CRLs in <certStoreDirectory>. "
+ "servername[:port] gives\n"
+ "the address of an LDAP server. If port is not"
+ " specified, port 389 is used. \"-\" means no LDAP server.\n"
+ "If ENE is specified, then an Error is Not Expected. "
+ "EE indicates an Error is Expected.\n");
+}
+
+static PKIX_Error *
+createLdapCertStore(
+ char *hostname,
+ PRIntervalTime timeout,
+ PKIX_CertStore **pLdapCertStore,
+ void *plContext)
+{
+ PRIntn backlog = 0;
+
+ char *bindname = "";
+ char *auth = "";
+
+ LDAPBindAPI bindAPI;
+ LDAPBindAPI *bindPtr = NULL;
+ PKIX_PL_LdapDefaultClient *ldapClient = NULL;
+ PKIX_CertStore *ldapCertStore = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (usebind) {
+ bindPtr = &bindAPI;
+ bindAPI.selector = SIMPLE_AUTH;
+ bindAPI.chooser.simple.bindName = bindname;
+ bindAPI.chooser.simple.authentication = auth;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapDefaultClient_CreateByName(hostname, timeout, bindPtr, &ldapClient, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapCertStore_Create((PKIX_PL_LdapClient *)ldapClient,
+ &ldapCertStore,
+ plContext));
+
+ *pLdapCertStore = ldapCertStore;
+cleanup:
+
+ PKIX_TEST_DECREF_AC(ldapClient);
+
+ PKIX_TEST_RETURN();
+
+ return (pkixTestErrorResult);
+}
+
+/* Test with all Certs in the partial list, no leaf */
+static PKIX_Error *
+testWithNoLeaf(
+ PKIX_PL_Cert *trustedCert,
+ PKIX_List *listOfCerts,
+ PKIX_PL_Cert *targetCert,
+ PKIX_List *certStores,
+ PKIX_Boolean testValid,
+ void *plContext)
+{
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *hintCerts = NULL;
+ PKIX_List *revCheckers = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_PL_PublicKey *trustedPubKey = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ PRPollDesc *pollDesc = NULL;
+ void *state = NULL;
+ char *asciiResult = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ /* create processing params with list of trust anchors */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert(trustedCert, &anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create(anchors, &procParams, plContext));
+
+ /* create CertSelector with no target certificate in params */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));
+
+ /* create hintCerts */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate((PKIX_PL_Object *)listOfCerts,
+ (PKIX_PL_Object **)&hintCerts,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetHintCerts(procParams, hintCerts, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores(procParams, certStores, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(trustedCert, &trustedPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(listOfCerts, &numCerts, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_DefaultRevChecker_Initialize(certStores,
+ NULL, /* testDate, may be NULL */
+ trustedPubKey,
+ numCerts,
+ &revChecker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(revCheckers, (PKIX_PL_Object *)revChecker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers(procParams, revCheckers, plContext));
+
+#ifdef debuggingWithoutRevocation
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_FALSE, plContext));
+#endif
+
+ /* build cert chain using processing params and return buildResult */
+
+ pkixTestErrorResult = PKIX_BuildChain(procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+
+ while (pollDesc != NULL) {
+
+ if (PR_Poll(pollDesc, 1, 0) < 0) {
+ testError("PR_Poll failed");
+ }
+
+ pkixTestErrorResult = PKIX_BuildChain(procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+ }
+
+ if (pkixTestErrorResult) {
+ if (testValid == PKIX_FALSE) { /* EE */
+ (void)printf("EXPECTED ERROR RECEIVED!\n");
+ } else { /* ENE */
+ testError("UNEXPECTED ERROR RECEIVED");
+ }
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ goto cleanup;
+ }
+
+ if (testValid == PKIX_TRUE) { /* ENE */
+ (void)printf("EXPECTED NON-ERROR RECEIVED!\n");
+ } else { /* EE */
+ (void)printf("UNEXPECTED NON-ERROR RECEIVED!\n");
+ }
+
+ if (buildResult) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetCertChain(buildResult, &certs, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ printf("\n");
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs,
+ i,
+ (PKIX_PL_Object **)&cert,
+ plContext));
+
+ asciiResult = PKIX_Cert2ASCII(cert);
+
+ printf("CERT[%d]:\n%s\n", i, asciiResult);
+
+ /* PKIX_Cert2ASCII used PKIX_PL_Malloc(...,,NULL) */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, NULL));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+ }
+
+cleanup:
+ PKIX_PL_Free(asciiResult, NULL);
+
+ PKIX_TEST_DECREF_AC(state);
+ PKIX_TEST_DECREF_AC(buildResult);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(revCheckers);
+ PKIX_TEST_DECREF_AC(revChecker);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(hintCerts);
+ PKIX_TEST_DECREF_AC(trustedPubKey);
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_RETURN();
+
+ return (pkixTestErrorResult);
+}
+
+/* Test with all Certs in the partial list, leaf duplicates the first one */
+static PKIX_Error *
+testWithDuplicateLeaf(
+ PKIX_PL_Cert *trustedCert,
+ PKIX_List *listOfCerts,
+ PKIX_PL_Cert *targetCert,
+ PKIX_List *certStores,
+ PKIX_Boolean testValid,
+ void *plContext)
+{
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *hintCerts = NULL;
+ PKIX_List *revCheckers = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_PL_PublicKey *trustedPubKey = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ PRPollDesc *pollDesc = NULL;
+ void *state = NULL;
+ char *asciiResult = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ /* create processing params with list of trust anchors */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert(trustedCert, &anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create(anchors, &procParams, plContext));
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate(certSelParams, targetCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));
+
+ /* create hintCerts */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate((PKIX_PL_Object *)listOfCerts,
+ (PKIX_PL_Object **)&hintCerts,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetHintCerts(procParams, hintCerts, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores(procParams, certStores, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(trustedCert, &trustedPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(listOfCerts, &numCerts, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_DefaultRevChecker_Initialize(certStores,
+ NULL, /* testDate, may be NULL */
+ trustedPubKey,
+ numCerts,
+ &revChecker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(revCheckers, (PKIX_PL_Object *)revChecker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers(procParams, revCheckers, plContext));
+
+#ifdef debuggingWithoutRevocation
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_FALSE, plContext));
+#endif
+
+ /* build cert chain using processing params and return buildResult */
+
+ pkixTestErrorResult = PKIX_BuildChain(procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+
+ while (pollDesc != NULL) {
+
+ if (PR_Poll(pollDesc, 1, 0) < 0) {
+ testError("PR_Poll failed");
+ }
+
+ pkixTestErrorResult = PKIX_BuildChain(procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+ }
+
+ if (pkixTestErrorResult) {
+ if (testValid == PKIX_FALSE) { /* EE */
+ (void)printf("EXPECTED ERROR RECEIVED!\n");
+ } else { /* ENE */
+ testError("UNEXPECTED ERROR RECEIVED");
+ }
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ goto cleanup;
+ }
+
+ if (testValid == PKIX_TRUE) { /* ENE */
+ (void)printf("EXPECTED NON-ERROR RECEIVED!\n");
+ } else { /* EE */
+ (void)printf("UNEXPECTED NON-ERROR RECEIVED!\n");
+ }
+
+ if (buildResult) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetCertChain(buildResult, &certs, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ printf("\n");
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs,
+ i,
+ (PKIX_PL_Object **)&cert,
+ plContext));
+
+ asciiResult = PKIX_Cert2ASCII(cert);
+
+ printf("CERT[%d]:\n%s\n", i, asciiResult);
+
+ /* PKIX_Cert2ASCII used PKIX_PL_Malloc(...,,NULL) */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, NULL));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+ }
+
+cleanup:
+ PKIX_PL_Free(asciiResult, NULL);
+
+ PKIX_TEST_DECREF_AC(state);
+ PKIX_TEST_DECREF_AC(buildResult);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(revCheckers);
+ PKIX_TEST_DECREF_AC(revChecker);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(hintCerts);
+ PKIX_TEST_DECREF_AC(trustedPubKey);
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_RETURN();
+
+ return (pkixTestErrorResult);
+}
+
+/* Test with all Certs except the leaf in the partial list */
+static PKIX_Error *
+testWithLeafAndChain(
+ PKIX_PL_Cert *trustedCert,
+ PKIX_List *listOfCerts,
+ PKIX_PL_Cert *targetCert,
+ PKIX_List *certStores,
+ PKIX_Boolean testValid,
+ void *plContext)
+{
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *hintCerts = NULL;
+ PKIX_List *revCheckers = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_PL_PublicKey *trustedPubKey = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ PRPollDesc *pollDesc = NULL;
+ void *state = NULL;
+ char *asciiResult = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ /* create processing params with list of trust anchors */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert(trustedCert, &anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create(anchors, &procParams, plContext));
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate(certSelParams, targetCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));
+
+ /* create hintCerts */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate((PKIX_PL_Object *)listOfCerts,
+ (PKIX_PL_Object **)&hintCerts,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(hintCerts, 0, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetHintCerts(procParams, hintCerts, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores(procParams, certStores, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(trustedCert, &trustedPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(listOfCerts, &numCerts, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_DefaultRevChecker_Initialize(certStores,
+ NULL, /* testDate, may be NULL */
+ trustedPubKey,
+ numCerts,
+ &revChecker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(revCheckers, (PKIX_PL_Object *)revChecker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers(procParams, revCheckers, plContext));
+
+#ifdef debuggingWithoutRevocation
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_FALSE, plContext));
+#endif
+
+ /* build cert chain using processing params and return buildResult */
+
+ pkixTestErrorResult = PKIX_BuildChain(procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+
+ while (pollDesc != NULL) {
+
+ if (PR_Poll(pollDesc, 1, 0) < 0) {
+ testError("PR_Poll failed");
+ }
+
+ pkixTestErrorResult = PKIX_BuildChain(procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+ }
+
+ if (pkixTestErrorResult) {
+ if (testValid == PKIX_FALSE) { /* EE */
+ (void)printf("EXPECTED ERROR RECEIVED!\n");
+ } else { /* ENE */
+ testError("UNEXPECTED ERROR RECEIVED");
+ }
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ goto cleanup;
+ }
+
+ if (testValid == PKIX_TRUE) { /* ENE */
+ (void)printf("EXPECTED NON-ERROR RECEIVED!\n");
+ } else { /* EE */
+ (void)printf("UNEXPECTED NON-ERROR RECEIVED!\n");
+ }
+
+ if (buildResult) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetCertChain(buildResult, &certs, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ printf("\n");
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs,
+ i,
+ (PKIX_PL_Object **)&cert,
+ plContext));
+
+ asciiResult = PKIX_Cert2ASCII(cert);
+
+ printf("CERT[%d]:\n%s\n", i, asciiResult);
+
+ /* PKIX_Cert2ASCII used PKIX_PL_Malloc(...,,NULL) */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, NULL));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(state);
+ PKIX_TEST_DECREF_AC(buildResult);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(revCheckers);
+ PKIX_TEST_DECREF_AC(revChecker);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(hintCerts);
+ PKIX_TEST_DECREF_AC(trustedPubKey);
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+
+ PKIX_TEST_RETURN();
+
+ return (pkixTestErrorResult);
+}
+
+int
+test_buildchain_partialchain(int argc, char *argv[])
+{
+ PKIX_UInt32 actualMinorVersion = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 k = 0;
+ PKIX_Boolean ene = PKIX_TRUE; /* expect no error */
+ PKIX_List *listOfCerts = NULL;
+ PKIX_List *certStores = NULL;
+ PKIX_PL_Cert *dirCert = NULL;
+ PKIX_PL_Cert *trusted = NULL;
+ PKIX_PL_Cert *target = NULL;
+ PKIX_CertStore *ldapCertStore = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_PL_String *dirNameString = NULL;
+ char *dirName = NULL;
+
+ PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT; /* blocking */
+ /* PRIntervalTime timeout = PR_INTERVAL_NO_WAIT; =0 for non-blocking */
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("BuildChain");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /*
+ * arguments:
+ * [optional] -arenas
+ * [optional] usebind
+ * servername or servername:port ( - for no server)
+ * testname
+ * EE or ENE
+ * cert directory
+ * target cert (end entity)
+ * intermediate certs
+ * trust anchor
+ */
+
+ /* optional argument "usebind" for Ldap CertStore */
+ if (argv[j + 1]) {
+ if (PORT_Strcmp(argv[j + 1], "usebind") == 0) {
+ usebind = PKIX_TRUE;
+ j++;
+ }
+ }
+
+ if (PORT_Strcmp(argv[++j], "-") == 0) {
+ useLDAP = PKIX_FALSE;
+ } else {
+ serverName = argv[j];
+ useLDAP = PKIX_TRUE;
+ }
+
+ subTest(argv[++j]);
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[++j], "ENE") == 0) {
+ ene = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[j], "EE") == 0) {
+ ene = PKIX_FALSE;
+ } else {
+ printUsage();
+ return (0);
+ }
+
+ dirName = argv[++j];
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&listOfCerts, plContext));
+
+ for (k = ++j; k < ((PKIX_UInt32)argc); k++) {
+
+ dirCert = createCert(dirName, argv[k], plContext);
+
+ if (k == ((PKIX_UInt32)(argc - 1))) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)dirCert, plContext));
+ trusted = dirCert;
+ } else {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(listOfCerts,
+ (PKIX_PL_Object *)dirCert,
+ plContext));
+
+ if (k == j) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)dirCert, plContext));
+ target = dirCert;
+ }
+ }
+
+ PKIX_TEST_DECREF_BC(dirCert);
+ }
+
+ /* create CertStores */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, dirName, 0, &dirNameString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certStores, plContext));
+
+ if (useLDAP == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(createLdapCertStore(serverName, timeout, &ldapCertStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certStores,
+ (PKIX_PL_Object *)ldapCertStore,
+ plContext));
+ } else {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirNameString, &certStore, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore, plContext));
+ }
+
+ subTest("testWithNoLeaf");
+ PKIX_TEST_EXPECT_NO_ERROR(testWithNoLeaf(trusted, listOfCerts, target, certStores, ene, plContext));
+
+ subTest("testWithDuplicateLeaf");
+ PKIX_TEST_EXPECT_NO_ERROR(testWithDuplicateLeaf(trusted, listOfCerts, target, certStores, ene, plContext));
+
+ subTest("testWithLeafAndChain");
+ PKIX_TEST_EXPECT_NO_ERROR(testWithLeafAndChain(trusted, listOfCerts, target, certStores, ene, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(listOfCerts);
+ PKIX_TEST_DECREF_AC(certStores);
+ PKIX_TEST_DECREF_AC(ldapCertStore);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(dirNameString);
+ PKIX_TEST_DECREF_AC(trusted);
+ PKIX_TEST_DECREF_AC(target);
+
+ PKIX_TEST_RETURN();
+
+ PKIX_Shutdown(plContext);
+
+ endTests("BuildChain");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/test_buildchain_resourcelimits.c b/security/nss/cmd/libpkix/pkix/top/test_buildchain_resourcelimits.c
new file mode 100644
index 000000000..1b28435b0
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_buildchain_resourcelimits.c
@@ -0,0 +1,438 @@
+/* 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/. */
+/*
+ * test_buildchain_resourcelimits.c
+ *
+ * Test BuildChain function with constraints on resources
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TESTUSERCHECKER_TYPE (PKIX_NUMTYPES + 30)
+
+static void *plContext = NULL;
+static PKIX_Boolean usebind = PKIX_FALSE;
+static PKIX_Boolean useLDAP = PKIX_FALSE;
+static char buf[PR_NETDB_BUF_SIZE];
+static char *serverName = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_buildchain_resourcelimits [-arenas] "
+ "[usebind] servername[:port]\\\n\t\t<testName> [ENE|EE]"
+ " <certStoreDirectory>\\\n\t\t<targetCert>"
+ " <intermediate Certs...> <trustedCert>\n\n");
+ (void)printf("Builds a chain of certificates from <targetCert> to <trustedCert>\n"
+ "using the certs and CRLs in <certStoreDirectory>. "
+ "servername[:port] gives\n"
+ "the address of an LDAP server. If port is not"
+ " specified, port 389 is used.\n\"-\" means no LDAP server.\n\n"
+ "If ENE is specified, then an Error is Not Expected.\n"
+ "EE indicates an Error is Expected.\n");
+}
+
+static PKIX_Error *
+createLdapCertStore(
+ char *hostname,
+ PRIntervalTime timeout,
+ PKIX_CertStore **pLdapCertStore,
+ void *plContext)
+{
+ PRIntn backlog = 0;
+
+ char *bindname = "";
+ char *auth = "";
+
+ LDAPBindAPI bindAPI;
+ LDAPBindAPI *bindPtr = NULL;
+ PKIX_PL_LdapDefaultClient *ldapClient = NULL;
+ PKIX_CertStore *ldapCertStore = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (usebind) {
+ bindPtr = &bindAPI;
+ bindAPI.selector = SIMPLE_AUTH;
+ bindAPI.chooser.simple.bindName = bindname;
+ bindAPI.chooser.simple.authentication = auth;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapDefaultClient_CreateByName(hostname, timeout, bindPtr, &ldapClient, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapCertStore_Create((PKIX_PL_LdapClient *)ldapClient, &ldapCertStore, plContext));
+
+ *pLdapCertStore = ldapCertStore;
+cleanup:
+
+ PKIX_TEST_DECREF_AC(ldapClient);
+
+ PKIX_TEST_RETURN();
+
+ return (pkixTestErrorResult);
+}
+
+static void
+Test_BuildResult(
+ PKIX_ProcessingParams *procParams,
+ PKIX_Boolean testValid,
+ PKIX_List *expectedCerts,
+ void *plContext)
+{
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_PL_String *actualCertsString = NULL;
+ PKIX_PL_String *expectedCertsString = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_Boolean result;
+ PKIX_Boolean supportForward = PKIX_FALSE;
+ PKIX_UInt32 numCerts, i;
+ char *asciiResult = NULL;
+ char *actualCertsAscii = NULL;
+ char *expectedCertsAscii = NULL;
+ void *state = NULL;
+ PRPollDesc *pollDesc = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ pkixTestErrorResult = PKIX_BuildChain(procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+
+ while (pollDesc != NULL) {
+
+ if (PR_Poll(pollDesc, 1, 0) < 0) {
+ testError("PR_Poll failed");
+ }
+
+ pkixTestErrorResult = PKIX_BuildChain(procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+ }
+
+ if (pkixTestErrorResult) {
+ if (testValid == PKIX_FALSE) { /* EE */
+ (void)printf("EXPECTED ERROR RECEIVED!\n");
+ } else { /* ENE */
+ testError("UNEXPECTED ERROR RECEIVED!\n");
+ }
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ goto cleanup;
+ }
+
+ if (testValid == PKIX_TRUE) { /* ENE */
+ (void)printf("EXPECTED NON-ERROR RECEIVED!\n");
+ } else { /* EE */
+ testError("UNEXPECTED NON-ERROR RECEIVED!\n");
+ }
+
+ if (buildResult) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetCertChain(buildResult, &certs, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ printf("\n");
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs,
+ i,
+ (PKIX_PL_Object **)&cert,
+ plContext));
+
+ asciiResult = PKIX_Cert2ASCII(cert);
+
+ printf("CERT[%d]:\n%s\n", i, asciiResult);
+
+ /* PKIX_Cert2ASCII used PKIX_PL_Malloc(...,,NULL) */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, NULL));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)certs,
+ (PKIX_PL_Object *)expectedCerts,
+ &result,
+ plContext));
+
+ if (!result) {
+ testError("BUILT CERTCHAIN IS "
+ "NOT THE ONE THAT WAS EXPECTED");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)certs,
+ &actualCertsString,
+ plContext));
+
+ actualCertsAscii = PKIX_String2ASCII(actualCertsString, plContext);
+ if (actualCertsAscii == NULL) {
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)expectedCerts,
+ &expectedCertsString,
+ plContext));
+
+ expectedCertsAscii = PKIX_String2ASCII(expectedCertsString, plContext);
+ if (expectedCertsAscii == NULL) {
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ (void)printf("Actual value:\t%s\n", actualCertsAscii);
+ (void)printf("Expected value:\t%s\n",
+ expectedCertsAscii);
+ }
+ }
+
+cleanup:
+
+ PKIX_PL_Free(asciiResult, NULL);
+ PKIX_PL_Free(actualCertsAscii, plContext);
+ PKIX_PL_Free(expectedCertsAscii, plContext);
+ PKIX_TEST_DECREF_AC(state);
+ PKIX_TEST_DECREF_AC(buildResult);
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(actualCertsString);
+ PKIX_TEST_DECREF_AC(expectedCertsString);
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_buildchain_resourcelimits(int argc, char *argv[])
+{
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_CertChainChecker *checker = NULL;
+ PKIX_ResourceLimits *resourceLimits = NULL;
+ char *dirName = NULL;
+ PKIX_PL_String *dirNameString = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_PL_Cert *dirCert = NULL;
+ PKIX_UInt32 actualMinorVersion = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 k = 0;
+ PKIX_CertStore *ldapCertStore = NULL;
+ PRIntervalTime timeout = 0; /* 0 for non-blocking */
+ PKIX_CertStore *certStore = NULL;
+ PKIX_List *certStores = NULL;
+ PKIX_List *expectedCerts = NULL;
+ PKIX_Boolean testValid = PKIX_FALSE;
+ PKIX_Boolean usebind = PKIX_FALSE;
+ PKIX_Boolean useLDAP = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("BuildChain_ResourceLimits");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /*
+ * arguments:
+ * [optional] -arenas
+ * [optional] usebind
+ * servername or servername:port ( - for no server)
+ * testname
+ * EE or ENE
+ * cert directory
+ * target cert (end entity)
+ * intermediate certs
+ * trust anchor
+ */
+
+ /* optional argument "usebind" for Ldap CertStore */
+ if (argv[j + 1]) {
+ if (PORT_Strcmp(argv[j + 1], "usebind") == 0) {
+ usebind = PKIX_TRUE;
+ j++;
+ }
+ }
+
+ if (PORT_Strcmp(argv[++j], "-") == 0) {
+ useLDAP = PKIX_FALSE;
+ } else {
+ serverName = argv[j];
+ }
+
+ subTest(argv[++j]);
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[++j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage();
+ return (0);
+ }
+
+ dirName = argv[++j];
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&expectedCerts, plContext));
+
+ for (k = ++j; k < argc; k++) {
+
+ dirCert = createCert(dirName, argv[k], plContext);
+
+ if (k == (argc - 1)) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)dirCert, plContext));
+ trustedCert = dirCert;
+ } else {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(expectedCerts,
+ (PKIX_PL_Object *)dirCert,
+ plContext));
+
+ if (k == j) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)dirCert, plContext));
+ targetCert = dirCert;
+ }
+ }
+
+ PKIX_TEST_DECREF_BC(dirCert);
+ }
+
+ /* create processing params with list of trust anchors */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert(trustedCert, &anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create(anchors, &procParams, plContext));
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate(certSelParams, targetCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));
+
+ /* create CertStores */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ dirName,
+ 0,
+ &dirNameString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirNameString, &certStore, plContext));
+
+#if 0
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Pk11CertStore_Create
+ (&certStore, plContext));
+#endif
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certStores, plContext));
+
+ if (useLDAP == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(createLdapCertStore(serverName, timeout, &ldapCertStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certStores,
+ (PKIX_PL_Object *)ldapCertStore,
+ plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores(procParams, certStores, plContext));
+
+ /* set resource limits */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_Create(&resourceLimits, plContext));
+
+ /* need longer time when running dbx for memory leak checking */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxTime(resourceLimits, 60, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout(resourceLimits, 2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth(resourceLimits, 2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetResourceLimits(procParams, resourceLimits, plContext));
+
+ /* build cert chain using processing params and return buildResult */
+
+ subTest("Testing ResourceLimits MaxFanout & MaxDepth - <pass>");
+ Test_BuildResult(procParams,
+ testValid,
+ expectedCerts,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout(resourceLimits, 1, plContext));
+
+ subTest("Testing ResourceLimits MaxFanout - <fail>");
+ Test_BuildResult(procParams,
+ PKIX_FALSE,
+ expectedCerts,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout(resourceLimits, 2, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth(resourceLimits, 1, plContext));
+
+ subTest("Testing ResourceLimits MaxDepth - <fail>");
+ Test_BuildResult(procParams,
+ PKIX_FALSE,
+ expectedCerts,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout(resourceLimits, 0, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth(resourceLimits, 0, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxTime(resourceLimits, 0, plContext));
+
+ subTest("Testing ResourceLimits No checking - <pass>");
+ Test_BuildResult(procParams,
+ testValid,
+ expectedCerts,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(expectedCerts);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certStores);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(ldapCertStore);
+ PKIX_TEST_DECREF_AC(dirNameString);
+ PKIX_TEST_DECREF_AC(trustedCert);
+ PKIX_TEST_DECREF_AC(targetCert);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(checker);
+ PKIX_TEST_DECREF_AC(resourceLimits);
+
+ PKIX_TEST_RETURN();
+
+ PKIX_Shutdown(plContext);
+
+ endTests("BuildChain_UserChecker");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/test_buildchain_uchecker.c b/security/nss/cmd/libpkix/pkix/top/test_buildchain_uchecker.c
new file mode 100644
index 000000000..43f06ec2a
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_buildchain_uchecker.c
@@ -0,0 +1,327 @@
+/* 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/. */
+/*
+ * test_buildchain_uchecker.c
+ *
+ * Test BuildChain User Checker function
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+static PKIX_UInt32 numUserCheckerCalled = 0;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_buildchain_uchecker [ENE|EE] "
+ "[-|[F]<userOID>] "
+ "<trustedCert> <targetCert> <certStoreDirectory>\n\n");
+ (void)printf("Builds a chain of certificates between "
+ "<trustedCert> and <targetCert>\n"
+ "using the certs and CRLs in <certStoreDirectory>.\n"
+ "If <userOID> is not an empty string, its value is used as\n"
+ "user defined checker's critical extension OID.\n"
+ "A - for <userOID> is no OID and F is for supportingForward.\n"
+ "If ENE is specified, then an Error is Not Expected.\n"
+ "If EE is specified, an Error is Expected.\n");
+}
+
+static PKIX_Error *
+testUserChecker(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresExtOIDs,
+ void **pNBIOContext,
+ void *plContext)
+{
+ numUserCheckerCalled++;
+ return (0);
+}
+
+int
+test_buildchain_uchecker(int argc, char *argv[])
+{
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_CertChainChecker *checker = NULL;
+ char *dirName = NULL;
+ PKIX_PL_String *dirNameString = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 k = 0;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_List *certStores = NULL;
+ char *asciiResult = NULL;
+ PKIX_Boolean result;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ PKIX_Boolean supportForward = PKIX_FALSE;
+ PKIX_List *expectedCerts = NULL;
+ PKIX_List *userOIDs = NULL;
+ PKIX_PL_OID *oid = NULL;
+ PKIX_PL_Cert *dirCert = NULL;
+ PKIX_PL_String *actualCertsString = NULL;
+ PKIX_PL_String *expectedCertsString = NULL;
+ char *actualCertsAscii = NULL;
+ char *expectedCertsAscii = NULL;
+ char *oidString = NULL;
+ void *buildState = NULL; /* needed by pkix_build for non-blocking I/O */
+ void *nbioContext = NULL; /* needed by pkix_build for non-blocking I/O */
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("BuildChain_UserChecker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2 + j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2 + j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage();
+ return (0);
+ }
+
+ /* OID specified at argv[3+j] */
+
+ if (*argv[3 + j] != '-') {
+
+ if (*argv[3 + j] == 'F') {
+ supportForward = PKIX_TRUE;
+ oidString = argv[3 + j] + 1;
+ } else {
+ oidString = argv[3 + j];
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&userOIDs, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(oidString, &oid, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(userOIDs, (PKIX_PL_Object *)oid, plContext));
+ PKIX_TEST_DECREF_BC(oid);
+ }
+
+ subTest(argv[1 + j]);
+
+ dirName = argv[4 + j];
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&expectedCerts, plContext));
+
+ chainLength = argc - j - 5;
+
+ for (k = 0; k < chainLength; k++) {
+
+ dirCert = createCert(dirName, argv[5 + k + j], plContext);
+
+ if (k == (chainLength - 1)) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)dirCert, plContext));
+ trustedCert = dirCert;
+ } else {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(expectedCerts,
+ (PKIX_PL_Object *)dirCert,
+ plContext));
+
+ if (k == 0) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)dirCert,
+ plContext));
+ targetCert = dirCert;
+ }
+ }
+
+ PKIX_TEST_DECREF_BC(dirCert);
+ }
+
+ /* create processing params with list of trust anchors */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert(trustedCert, &anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create(anchors, &procParams, plContext));
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate(certSelParams, targetCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_Create(testUserChecker,
+ supportForward,
+ PKIX_FALSE,
+ userOIDs,
+ NULL,
+ &checker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertChainChecker(procParams, checker, plContext));
+
+ /* create CertStores */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ dirName,
+ 0,
+ &dirNameString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirNameString, &certStore, plContext));
+
+#if 0
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Pk11CertStore_Create
+ (&certStore, plContext));
+#endif
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certStores, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores(procParams, certStores, plContext));
+
+ /* build cert chain using processing params and return buildResult */
+
+ pkixTestErrorResult = PKIX_BuildChain(procParams,
+ &nbioContext,
+ &buildState,
+ &buildResult,
+ NULL,
+ plContext);
+
+ if (testValid == PKIX_TRUE) { /* ENE */
+ if (pkixTestErrorResult) {
+ (void)printf("UNEXPECTED RESULT RECEIVED!\n");
+ } else {
+ (void)printf("EXPECTED RESULT RECEIVED!\n");
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ }
+ } else { /* EE */
+ if (pkixTestErrorResult) {
+ (void)printf("EXPECTED RESULT RECEIVED!\n");
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ } else {
+ testError("UNEXPECTED RESULT RECEIVED");
+ }
+ }
+
+ if (buildResult) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetCertChain(buildResult, &certs, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ printf("\n");
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs,
+ i,
+ (PKIX_PL_Object **)&cert,
+ plContext));
+
+ asciiResult = PKIX_Cert2ASCII(cert);
+
+ printf("CERT[%d]:\n%s\n", i, asciiResult);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, plContext));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)certs,
+ (PKIX_PL_Object *)expectedCerts,
+ &result,
+ plContext));
+
+ if (!result) {
+ testError("BUILT CERTCHAIN IS "
+ "NOT THE ONE THAT WAS EXPECTED");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)certs,
+ &actualCertsString,
+ plContext));
+
+ actualCertsAscii = PKIX_String2ASCII(actualCertsString, plContext);
+ if (actualCertsAscii == NULL) {
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)expectedCerts,
+ &expectedCertsString,
+ plContext));
+
+ expectedCertsAscii = PKIX_String2ASCII(expectedCertsString, plContext);
+ if (expectedCertsAscii == NULL) {
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ (void)printf("Actual value:\t%s\n", actualCertsAscii);
+ (void)printf("Expected value:\t%s\n",
+ expectedCertsAscii);
+
+ if (chainLength - 1 != numUserCheckerCalled) {
+ pkixTestErrorMsg =
+ "PKIX user defined checker not called";
+ }
+
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ PKIX_PL_Free(asciiResult, plContext);
+ PKIX_PL_Free(actualCertsAscii, plContext);
+ PKIX_PL_Free(expectedCertsAscii, plContext);
+
+ PKIX_TEST_DECREF_AC(actualCertsString);
+ PKIX_TEST_DECREF_AC(expectedCertsString);
+ PKIX_TEST_DECREF_AC(expectedCerts);
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(certStores);
+ PKIX_TEST_DECREF_AC(dirNameString);
+ PKIX_TEST_DECREF_AC(trustedCert);
+ PKIX_TEST_DECREF_AC(targetCert);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(buildResult);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(userOIDs);
+ PKIX_TEST_DECREF_AC(checker);
+
+ PKIX_TEST_RETURN();
+
+ PKIX_Shutdown(plContext);
+
+ endTests("BuildChain_UserChecker");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/test_customcrlchecker.c b/security/nss/cmd/libpkix/pkix/top/test_customcrlchecker.c
new file mode 100644
index 000000000..d2c667ae7
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_customcrlchecker.c
@@ -0,0 +1,435 @@
+/* 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/. */
+/*
+ * test_customcrlchecker.c
+ *
+ * Test Custom CRL Checking
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TEST_MAX_CERTS 10
+#define PKIX_TEST_COLLECTIONCERTSTORE_NUM_CRLS 5
+
+static void *plContext = NULL;
+char *dirName = NULL; /* also used in callback */
+
+static void
+printUsage1(char *pName)
+{
+ printf("\nUSAGE: %s test-purpose [ENE|EE] ", pName);
+ printf("cert [certs].\n");
+}
+
+static void
+printUsageMax(PKIX_UInt32 numCerts)
+{
+ printf("\nUSAGE ERROR: number of certs %d exceed maximum %d\n",
+ numCerts, PKIX_TEST_MAX_CERTS);
+}
+
+static PKIX_Error *
+getCRLCallback(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *crlSelector,
+ void **pNBIOContext,
+ PKIX_List **pCrlList,
+ void *plContext)
+{
+ char *crlFileNames[] = { "chem.crl",
+ "phys.crl",
+ "prof.crl",
+ "sci.crl",
+ "test.crl",
+ 0 };
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_List *crlList = NULL;
+ PKIX_UInt32 i = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&crlList, plContext));
+
+ while (crlFileNames[i]) {
+
+ crl = createCRL(dirName, crlFileNames[i++], plContext);
+
+ if (crl != NULL) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(crlList, (PKIX_PL_Object *)crl, plContext));
+
+ PKIX_TEST_DECREF_BC(crl);
+ }
+ }
+
+ *pCrlList = crlList;
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (0); /* this function is called by libpkix */
+}
+
+static PKIX_Error *
+getCRLContinue(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *crlSelector,
+ void **pNBIOContext,
+ PKIX_List **pCrlList,
+ void *plContext)
+{
+ return (NULL);
+}
+
+static PKIX_Error *
+getCertCallback(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *certSelector,
+ void **pNBIOContext,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ return (NULL);
+}
+
+static PKIX_Error *
+getCertContinue(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *certSelector,
+ void **pNBIOContext,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ return (NULL);
+}
+
+static PKIX_Error *
+testCRLSelectorMatchCallback(
+ PKIX_CRLSelector *selector,
+ PKIX_PL_CRL *crl,
+ void *plContext)
+{
+ PKIX_ComCRLSelParams *comCrlSelParams = NULL;
+ PKIX_List *issuerList = NULL;
+ PKIX_PL_X500Name *issuer = NULL;
+ PKIX_PL_X500Name *crlIssuer = NULL;
+ PKIX_UInt32 numIssuers = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_Boolean result = PKIX_FALSE;
+ PKIX_Error *error = NULL;
+ char *errorText = "Not an error, CRL Select mismatch";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Custom_Selector_MatchCallback");
+
+ if (selector != NULL) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_GetCommonCRLSelectorParams(selector, &comCrlSelParams, plContext));
+ }
+
+ if (crl != NULL) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_GetIssuer(crl, &crlIssuer, plContext));
+ }
+
+ if (comCrlSelParams != NULL) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_GetIssuerNames(comCrlSelParams, &issuerList, plContext));
+ }
+
+ if (issuerList != NULL) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(issuerList, &numIssuers, plContext));
+
+ for (i = 0; i < numIssuers; i++) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(issuerList,
+ i, (PKIX_PL_Object **)&issuer,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)crlIssuer,
+ (PKIX_PL_Object *)issuer,
+ &result,
+ plContext));
+
+ if (result != PKIX_TRUE) {
+ break;
+ }
+
+ if (i == numIssuers - 1) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(0,
+ NULL,
+ NULL,
+ PKIX_TESTNOTANERRORCRLSELECTMISMATCH,
+ &error,
+ plContext));
+
+ PKIX_TEST_DECREF_AC(issuer);
+ issuer = NULL;
+ break;
+ }
+
+ PKIX_TEST_DECREF_AC(issuer);
+ }
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(comCrlSelParams);
+ PKIX_TEST_DECREF_AC(crlIssuer);
+ PKIX_TEST_DECREF_AC(issuer);
+ PKIX_TEST_DECREF_AC(issuerList);
+
+ PKIX_TEST_RETURN();
+
+ return (error);
+}
+
+static PKIX_Error *
+testAddIssuerName(PKIX_ComCRLSelParams *comCrlSelParams, char *issuerName)
+{
+ PKIX_PL_String *issuerString = NULL;
+ PKIX_PL_X500Name *issuer = NULL;
+ PKIX_UInt32 length = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCRLSelParams_AddIssuerName");
+
+ length = PL_strlen(issuerName);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_UTF8,
+ issuerName,
+ length,
+ &issuerString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create(issuerString,
+ &issuer,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_AddIssuerName(comCrlSelParams, issuer, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(issuerString);
+ PKIX_TEST_DECREF_AC(issuer);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+static PKIX_Error *
+testCustomCertStore(PKIX_ValidateParams *valParams)
+{
+ PKIX_CertStore_CRLCallback crlCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ char *issuerName1 = "cn=science,o=mit,c=us";
+ char *issuerName2 = "cn=physics,o=mit,c=us";
+ char *issuerName3 = "cn=prof noall,o=mit,c=us";
+ char *issuerName4 = "cn=testing CRL,o=test,c=us";
+ PKIX_ComCRLSelParams *comCrlSelParams = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+ PKIX_List *crlList = NULL;
+ PKIX_UInt32 numCrl = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CollectionCertStore_Create");
+
+ /* Create CRLSelector, link in CollectionCertStore */
+
+ subTest("PKIX_ComCRLSelParams_AddIssuerNames");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_Create(&comCrlSelParams, plContext));
+
+ testAddIssuerName(comCrlSelParams, issuerName1);
+ testAddIssuerName(comCrlSelParams, issuerName2);
+ testAddIssuerName(comCrlSelParams, issuerName3);
+ testAddIssuerName(comCrlSelParams, issuerName4);
+
+ subTest("PKIX_CRLSelector_SetCommonCRLSelectorParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_Create(testCRLSelectorMatchCallback,
+ NULL,
+ &crlSelector,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_SetCommonCRLSelectorParams(crlSelector, comCrlSelParams, plContext));
+
+ /* Create CertStore, link in CRLSelector */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams(valParams, &procParams, plContext));
+
+ subTest("PKIX_CertStore_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_Create(getCertCallback,
+ getCRLCallback,
+ getCertContinue,
+ getCRLContinue,
+ NULL, /* trustCallback */
+ (PKIX_PL_Object *)crlSelector, /* fake */
+ PKIX_FALSE, /* cacheFlag */
+ PKIX_TRUE, /* localFlag */
+ &certStore,
+ plContext));
+
+ subTest("PKIX_ProcessingParams_AddCertStore");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertStore(procParams, certStore, plContext));
+
+ subTest("PKIX_ProcessingParams_SetRevocationEnabled");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_TRUE, plContext));
+
+ subTest("PKIX_CertStore_GetCRLCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCRLCallback(certStore,
+ &crlCallback,
+ NULL));
+
+ subTest("Getting CRL by CRL Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(crlCallback(certStore,
+ crlSelector,
+ &nbioContext,
+ &crlList,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(crlList,
+ &numCrl,
+ plContext));
+
+ if (numCrl != PKIX_TEST_COLLECTIONCERTSTORE_NUM_CRLS) {
+ pkixTestErrorMsg = "unexpected CRL number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(crlList);
+ PKIX_TEST_DECREF_AC(comCrlSelParams);
+ PKIX_TEST_DECREF_AC(crlSelector);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+/*
+ * Validate Certificate Chain with Certificate Revocation List
+ * Certificate Chain is built based on input certs' sequence.
+ * CRL is fetched from the directory specified in CollectionCertStore.
+ * while CollectionCertStore is linked in CertStore Object which then
+ * linked in ProcessParam. During validation, CRLChecker will invoke
+ * the crlCallback (this test uses PKIX_PL_CollectionCertStore_GetCRL)
+ * to get CRL data for revocation check.
+ * This test set criteria in CRLSelector which is linked in
+ * CommonCRLSelectorParam. When CRL data is fetched into cache for
+ * revocation check, CRL's are filtered based on the criteria set.
+ */
+
+int
+test_customcrlchecker(int argc, char *argv[])
+{
+
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ char *certNames[PKIX_TEST_MAX_CERTS];
+ PKIX_PL_Cert *certs[PKIX_TEST_MAX_CERTS];
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ char *anchorName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ startTests("CRL Checker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2 + j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2 + j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ chainLength = (argc - j) - 5;
+ if (chainLength > PKIX_TEST_MAX_CERTS) {
+ printUsageMax(chainLength);
+ }
+
+ for (i = 0; i < chainLength; i++) {
+
+ certNames[i] = argv[(5 + j) + i];
+ certs[i] = NULL;
+ }
+
+ dirName = argv[3 + j];
+
+ subTest(argv[1 + j]);
+
+ subTest("Custom-CRL-Checker - Create Cert Chain");
+
+ chain = createCertChainPlus(dirName, certNames, certs, chainLength, plContext);
+
+ subTest("Custom-CRL-Checker - Create Params");
+
+ anchorName = argv[4 + j];
+
+ valParams = createValidateParams(dirName,
+ anchorName,
+ NULL,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ subTest("Custom-CRL-Checker - Set Processing Params for CertStore");
+
+ testCustomCertStore(valParams);
+
+ subTest("Custom-CRL-Checker - Validate Chain");
+
+ if (testValid == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+ } else {
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CRL Checker");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/test_defaultcrlchecker2stores.c b/security/nss/cmd/libpkix/pkix/top/test_defaultcrlchecker2stores.c
new file mode 100644
index 000000000..3ce451317
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_defaultcrlchecker2stores.c
@@ -0,0 +1,230 @@
+/* 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/. */
+/*
+ * test_defaultcrlchecker2stores.c
+ *
+ * Test Default CRL with multiple CertStore Checking
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TEST_MAX_CERTS 10
+
+static void *plContext = NULL;
+
+static void
+printUsage1(char *pName)
+{
+ printf("\nUSAGE: %s test-purpose [ENE|EE] ", pName);
+ printf("crl-directory cert [certs].\n");
+}
+
+static void
+printUsageMax(PKIX_UInt32 numCerts)
+{
+ printf("\nUSAGE ERROR: number of certs %d exceed maximum %d\n",
+ numCerts, PKIX_TEST_MAX_CERTS);
+}
+
+static PKIX_Error *
+getCertCallback(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *certSelector,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ return (NULL);
+}
+
+static PKIX_Error *
+testDefaultMultipleCertStores(PKIX_ValidateParams *valParams,
+ char *crlDir1,
+ char *crlDir2)
+{
+ PKIX_PL_String *dirString1 = NULL;
+ PKIX_PL_String *dirString2 = NULL;
+ PKIX_CertStore *certStore1 = NULL;
+ PKIX_CertStore *certStore2 = NULL;
+ PKIX_List *certStoreList = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CollectionCertStore_Create");
+
+ /* Create CollectionCertStore */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ crlDir1,
+ 0,
+ &dirString1,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString1,
+ &certStore1,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ crlDir2,
+ 0,
+ &dirString2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString2,
+ &certStore2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams(valParams, &procParams, plContext));
+
+ /* Add multiple CollectionCertStores */
+
+ subTest("PKIX_ProcessingParams_SetCertStores");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certStoreList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certStoreList, (PKIX_PL_Object *)certStore1, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores(procParams, certStoreList, plContext));
+
+ subTest("PKIX_ProcessingParams_AddCertStore");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertStore(procParams, certStore2, plContext));
+
+ subTest("PKIX_ProcessingParams_SetRevocationEnabled");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_TRUE, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dirString1);
+ PKIX_TEST_DECREF_AC(dirString2);
+ PKIX_TEST_DECREF_AC(certStore1);
+ PKIX_TEST_DECREF_AC(certStore2);
+ PKIX_TEST_DECREF_AC(certStoreList);
+ PKIX_TEST_DECREF_AC(procParams);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+/*
+ * Validate Certificate Chain with Certificate Revocation List
+ * Certificate Chain is build based on input certs' sequence.
+ * CRL is fetched from the directory specified in CollectionCertStore.
+ * while CollectionCertStore is linked in CertStore Object which then
+ * linked in ProcessParam. During validation, CRLChecker will invoke
+ * the crlCallback (this test uses PKIX_PL_CollectionCertStore_GetCRL)
+ * to get CRL data for revocation check.
+ * This test gets CRL's from two CertStores, each has a valid CRL
+ * required for revocation check to pass.
+ */
+
+int
+test_defaultcrlchecker2stores(int argc, char *argv[])
+{
+
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ char *certNames[PKIX_TEST_MAX_CERTS];
+ PKIX_PL_Cert *certs[PKIX_TEST_MAX_CERTS];
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ char *dirName = NULL;
+ char *anchorName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 6) {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ startTests("CRL Checker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2 + j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2 + j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ chainLength = (argc - j) - 7;
+ if (chainLength > PKIX_TEST_MAX_CERTS) {
+ printUsageMax(chainLength);
+ }
+
+ for (i = 0; i < chainLength; i++) {
+
+ certNames[i] = argv[(7 + j) + i];
+ certs[i] = NULL;
+ }
+
+ subTest(argv[1 + j]);
+
+ subTest("Default-CRL-Checker");
+
+ subTest("Default-CRL-Checker - Create Cert Chain");
+
+ dirName = argv[3 + j];
+
+ chain = createCertChainPlus(dirName, certNames, certs, chainLength, plContext);
+
+ subTest("Default-CRL-Checker - Create Params");
+
+ anchorName = argv[6 + j];
+
+ valParams = createValidateParams(dirName,
+ anchorName,
+ NULL,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ subTest("Multiple-CertStores");
+
+ testDefaultMultipleCertStores(valParams, argv[4 + j], argv[5 + j]);
+
+ subTest("Default-CRL-Checker - Validate Chain");
+
+ if (testValid == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+ } else {
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)verifyTree, &verifyString, plContext));
+ (void)printf("verifyTree is\n%s\n", verifyString->escAsciiString);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(chain);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CRL Checker");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/test_ocsp.c b/security/nss/cmd/libpkix/pkix/top/test_ocsp.c
new file mode 100644
index 000000000..e97e57096
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_ocsp.c
@@ -0,0 +1,288 @@
+/* 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/. */
+/*
+ * test_ocspchecker.c
+ *
+ * Test OcspChecker function
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\nOcspChecker -d <certStoreDirectory> TestName "
+ "[ENE|EE] <certLocationDirectory> <trustedCert> "
+ "<targetCert>\n\n");
+ (void)printf("Validates a chain of certificates between "
+ "<trustedCert> and <targetCert>\n"
+ "using the certs and CRLs in <certLocationDirectory> and "
+ "pkcs11 db from <certStoreDirectory>. "
+ "If ENE is specified,\n"
+ "then an Error is Not Expected. "
+ "If EE is specified, an Error is Expected.\n");
+}
+
+static char *
+createFullPathName(
+ char *dirName,
+ char *certFile,
+ void *plContext)
+{
+ PKIX_UInt32 certFileLen;
+ PKIX_UInt32 dirNameLen;
+ char *certPathName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certFileLen = PL_strlen(certFile);
+ dirNameLen = PL_strlen(dirName);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc(dirNameLen +
+ certFileLen +
+ 2,
+ (void **)&certPathName,
+ plContext));
+
+ PL_strcpy(certPathName, dirName);
+ PL_strcat(certPathName, "/");
+ PL_strcat(certPathName, certFile);
+ printf("certPathName = %s\n", certPathName);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (certPathName);
+}
+
+static PKIX_Error *
+testDefaultCertStore(PKIX_ValidateParams *valParams, char *crlDir)
+{
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_PL_Date *validity = NULL;
+ PKIX_List *revCheckers = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_PL_Object *revCheckerContext = NULL;
+ PKIX_OcspChecker *ocspChecker = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CollectionCertStoreContext_Create");
+
+ /* Create CollectionCertStore */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, crlDir, 0, &dirString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString, &certStore, plContext));
+
+ /* Create CertStore */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams(valParams, &procParams, plContext));
+
+ subTest("PKIX_ProcessingParams_AddCertStore");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertStore(procParams, certStore, plContext));
+
+ subTest("PKIX_ProcessingParams_SetRevocationEnabled");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_FALSE, plContext));
+
+ /* create current Date */
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Date_CreateFromPRTime(PR_Now(), &validity, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext));
+
+ /* create revChecker */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_OcspChecker_Initialize(validity,
+ NULL, /* pwArg */
+ NULL, /* Use default responder */
+ &revChecker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_RevocationChecker_GetRevCheckerContext(revChecker, &revCheckerContext, plContext));
+
+ /* Check that this object is a ocsp checker */
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_CheckType(revCheckerContext, PKIX_OCSPCHECKER_TYPE, plContext));
+
+ ocspChecker = (PKIX_OcspChecker *)revCheckerContext;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_OcspChecker_SetVerifyFcn(ocspChecker,
+ PKIX_PL_OcspResponse_UseBuildChain,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(revCheckers, (PKIX_PL_Object *)revChecker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers(procParams, revCheckers, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(revCheckers);
+ PKIX_TEST_DECREF_AC(revChecker);
+ PKIX_TEST_DECREF_AC(ocspChecker);
+ PKIX_TEST_DECREF_AC(validity);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+int
+test_ocsp(int argc, char *argv[])
+{
+
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 k = 0;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ PKIX_List *chainCerts = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+ PKIX_PL_Cert *dirCert = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ char *dirCertName = NULL;
+ char *anchorCertName = NULL;
+ char *dirName = NULL;
+ char *databaseDir = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("OcspChecker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2 + j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2 + j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage();
+ return (0);
+ }
+
+ subTest(argv[1 + j]);
+
+ dirName = argv[3 + j];
+
+ chainLength = argc - j - 5;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&chainCerts, plContext));
+
+ for (k = 0; k < chainLength; k++) {
+
+ dirCert = createCert(dirName, argv[5 + k + j], plContext);
+
+ if (k == 0) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)dirCert, plContext));
+ targetCert = dirCert;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(chainCerts, (PKIX_PL_Object *)dirCert, plContext));
+
+ PKIX_TEST_DECREF_BC(dirCert);
+ }
+
+ /* create processing params with list of trust anchors */
+
+ anchorCertName = argv[4 + j];
+ trustedCert = createCert(dirName, anchorCertName, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert(trustedCert, &anchor, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create(anchors, &procParams, plContext));
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate(certSelParams, targetCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_Create(procParams, chainCerts, &valParams, plContext));
+
+ testDefaultCertStore(valParams, dirName);
+
+ pkixTestErrorResult = PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext);
+
+ if (pkixTestErrorResult) {
+ if (testValid == PKIX_FALSE) { /* EE */
+ (void)printf("EXPECTED ERROR RECEIVED!\n");
+ } else { /* ENE */
+ testError("UNEXPECTED ERROR RECEIVED");
+ }
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ } else {
+ if (testValid == PKIX_TRUE) { /* ENE */
+ (void)printf("EXPECTED SUCCESSFUL VALIDATION!\n");
+ } else { /* EE */
+ (void)printf("UNEXPECTED SUCCESSFUL VALIDATION!\n");
+ }
+ }
+
+ subTest("Displaying VerifyTree");
+
+ if (verifyTree == NULL) {
+ (void)printf("VerifyTree is NULL\n");
+ } else {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)verifyTree, &verifyString, plContext));
+ (void)printf("verifyTree is\n%s\n",
+ verifyString->escAsciiString);
+ PKIX_TEST_DECREF_BC(verifyString);
+ PKIX_TEST_DECREF_BC(verifyTree);
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(chainCerts);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(trustedCert);
+ PKIX_TEST_DECREF_AC(targetCert);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("OcspChecker");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/test_policychecker.c b/security/nss/cmd/libpkix/pkix/top/test_policychecker.c
new file mode 100644
index 000000000..1318f13ba
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_policychecker.c
@@ -0,0 +1,535 @@
+/* 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/. */
+/*
+ * test_policychecker.c
+ *
+ * Test Policy Checking
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TEST_MAX_CERTS 10
+
+static void *plContext = NULL;
+
+static void
+printUsage(char *testname)
+{
+ char *fmt =
+ "USAGE: %s testname"
+ " [ENE|EE] \"{OID[:OID]*}\" [A|E|P] cert [cert]*\n"
+ "(The quotes are needed around the OID argument for dbx.)\n"
+ "(The optional arg A indicates initialAnyPolicyInhibit.)\n"
+ "(The optional arg E indicates initialExplicitPolicy.)\n"
+ "(The optional arg P indicates initialPolicyMappingInhibit.)\n";
+ printf(fmt, testname);
+}
+
+static void
+printUsageMax(PKIX_UInt32 numCerts)
+{
+ printf("\nUSAGE ERROR: number of certs %d exceed maximum %d\n",
+ numCerts, PKIX_TEST_MAX_CERTS);
+}
+
+static PKIX_List *
+policySetParse(char *policyString)
+{
+ char *p = NULL;
+ char *oid = NULL;
+ char c = '\0';
+ PKIX_Boolean validString = PKIX_FALSE;
+ PKIX_PL_OID *plOID = NULL;
+ PKIX_List *policySet = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ p = policyString;
+
+ /*
+ * There may or may not be quotes around the initial-policy-set
+ * string. If they are omitted, dbx will strip off the curly braces.
+ * If they are included, dbx will strip off the quotes, but if you
+ * are running directly from a script, without dbx, the quotes will
+ * not be stripped. We need to be able to handle both cases.
+ */
+ if (*p == '"') {
+ p++;
+ }
+
+ if ('{' != *p++) {
+ return (NULL);
+ }
+ oid = p;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&policySet, plContext));
+
+ /* scan to the end of policyString */
+ while (!validString) {
+ /* scan to the end of the current OID string */
+ c = *oid;
+ while ((c != '\0') && (c != ':') && (c != '}')) {
+ c = *++oid;
+ }
+
+ if ((c != ':') || (c != '}')) {
+ *oid = '\0'; /* store a null terminator */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(p, &plOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(policySet,
+ (PKIX_PL_Object *)plOID,
+ plContext));
+
+ PKIX_TEST_DECREF_BC(plOID);
+ plOID = NULL;
+ if (c == '}') {
+ /*
+ * Any exit but this one means
+ * we were given a badly-formed string.
+ */
+ validString = PKIX_TRUE;
+ }
+ p = ++oid;
+ }
+ }
+
+cleanup:
+ if (!validString) {
+ PKIX_TEST_DECREF_AC(plOID);
+ PKIX_TEST_DECREF_AC(policySet);
+ policySet = NULL;
+ }
+
+ PKIX_TEST_RETURN();
+
+ return (policySet);
+}
+
+/*
+ * FUNCTION: treeToStringHelper
+ * This function obtains the string representation of a PolicyNode
+ * Tree and compares it to the expected value.
+ * PARAMETERS:
+ * "parent" - a PolicyNode, the root of a PolicyNodeTree;
+ * must be non-NULL.
+ * "expected" - the desired string.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads can safely call this function without worrying
+ * about conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Nothing.
+ */
+static void
+treeToStringHelper(PKIX_PolicyNode *parent, char *expected)
+{
+ PKIX_PL_String *stringRep = NULL;
+ char *actual = NULL;
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)parent, &stringRep, plContext));
+
+ actual = PKIX_String2ASCII(stringRep, plContext);
+ if (actual == NULL) {
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ if (PL_strcmp(actual, expected) != 0) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%s\n", actual);
+ (void)printf("Expected value:\t%s\n", expected);
+ }
+
+cleanup:
+
+ PKIX_PL_Free(actual, plContext);
+
+ PKIX_TEST_DECREF_AC(stringRep);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testPass(char *dirName, char *goodInput, char *diffInput, char *dateAscii)
+{
+
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Basic-Common-Fields <pass>");
+ /*
+ * Tests the Expiration, NameChaining, and Signature Checkers
+ */
+
+ chain = createCertChain(dirName, goodInput, diffInput, plContext);
+
+ valParams = createValidateParams(dirName,
+ goodInput,
+ diffInput,
+ dateAscii,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, NULL, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testNistTest1(char *dirName)
+{
+#define PKIX_TEST_NUM_CERTS 2
+ char *trustAnchor =
+ "TrustAnchorRootCertificate.crt";
+ char *intermediateCert =
+ "GoodCACert.crt";
+ char *endEntityCert =
+ "ValidCertificatePathTest1EE.crt";
+ char *certNames[PKIX_TEST_NUM_CERTS];
+ char *asciiAnyPolicy = "2.5.29.32.0";
+ PKIX_PL_Cert *certs[PKIX_TEST_NUM_CERTS] = { NULL, NULL };
+
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_List *chain = NULL;
+ PKIX_PL_OID *anyPolicyOID = NULL;
+ PKIX_List *initialPolicies = NULL;
+ char *anchorName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("testNistTest1: Creating the cert chain");
+ /*
+ * Create a chain, but don't include the first certName.
+ * That's the anchor, and is supplied separately from
+ * the chain.
+ */
+ certNames[0] = intermediateCert;
+ certNames[1] = endEntityCert;
+ chain = createCertChainPlus(dirName, certNames, certs, PKIX_TEST_NUM_CERTS, plContext);
+
+ subTest("testNistTest1: Creating the Validate Parameters");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(asciiAnyPolicy, &anyPolicyOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&initialPolicies, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(initialPolicies, (PKIX_PL_Object *)anyPolicyOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetImmutable(initialPolicies, plContext));
+
+ valParams = createValidateParams(dirName,
+ trustAnchor,
+ NULL,
+ NULL,
+ initialPolicies,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ subTest("testNistTest1: Validating the chain");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, NULL, plContext));
+
+cleanup:
+
+ PKIX_PL_Free(anchorName, plContext);
+
+ PKIX_TEST_DECREF_AC(anyPolicyOID);
+ PKIX_TEST_DECREF_AC(initialPolicies);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(chain);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testNistTest2(char *dirName)
+{
+#define PKIX_TEST_NUM_CERTS 2
+ char *trustAnchor =
+ "TrustAnchorRootCertificate.crt";
+ char *intermediateCert =
+ "GoodCACert.crt";
+ char *endEntityCert =
+ "ValidCertificatePathTest1EE.crt";
+ char *certNames[PKIX_TEST_NUM_CERTS];
+ char *asciiNist1Policy = "2.16.840.1.101.3.2.1.48.1";
+ PKIX_PL_Cert *certs[PKIX_TEST_NUM_CERTS] = { NULL, NULL };
+
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_List *chain = NULL;
+ PKIX_PL_OID *Nist1PolicyOID = NULL;
+ PKIX_List *initialPolicies = NULL;
+ char *anchorName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("testNistTest2: Creating the cert chain");
+ /*
+ * Create a chain, but don't include the first certName.
+ * That's the anchor, and is supplied separately from
+ * the chain.
+ */
+ certNames[0] = intermediateCert;
+ certNames[1] = endEntityCert;
+ chain = createCertChainPlus(dirName, certNames, certs, PKIX_TEST_NUM_CERTS, plContext);
+
+ subTest("testNistTest2: Creating the Validate Parameters");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(asciiNist1Policy, &Nist1PolicyOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&initialPolicies, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(initialPolicies, (PKIX_PL_Object *)Nist1PolicyOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetImmutable(initialPolicies, plContext));
+
+ valParams = createValidateParams(dirName,
+ trustAnchor,
+ NULL,
+ NULL,
+ initialPolicies,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ subTest("testNistTest2: Validating the chain");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, NULL, plContext));
+
+cleanup:
+
+ PKIX_PL_Free(anchorName, plContext);
+
+ PKIX_TEST_DECREF_AC(Nist1PolicyOID);
+ PKIX_TEST_DECREF_AC(initialPolicies);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(chain);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printValidPolicyTree(PKIX_ValidateResult *valResult)
+{
+ PKIX_PolicyNode *validPolicyTree = NULL;
+ PKIX_PL_String *treeString = NULL;
+
+ PKIX_TEST_STD_VARS();
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetPolicyTree(valResult, &validPolicyTree, plContext));
+ if (validPolicyTree) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)validPolicyTree,
+ &treeString,
+ plContext));
+ (void)printf("validPolicyTree is\n\t%s\n",
+ treeString->escAsciiString);
+ } else {
+ (void)printf("validPolicyTree is NULL\n");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(validPolicyTree);
+ PKIX_TEST_DECREF_AC(treeString);
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_policychecker(int argc, char *argv[])
+{
+
+ PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
+ PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
+ PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
+ PKIX_Boolean expectedResult = PKIX_FALSE;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 initArgs = 0;
+ PKIX_UInt32 firstCert = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_Int32 j = 0;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_ProcessingParams *procParams = NULL;
+ char *firstTrustAnchor = "yassir2yassir";
+ char *secondTrustAnchor = "yassir2bcn";
+ char *dateAscii = "991201000000Z";
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_List *userInitialPolicySet = NULL; /* List of PKIX_PL_OID */
+ char *certNames[PKIX_TEST_MAX_CERTS];
+ PKIX_PL_Cert *certs[PKIX_TEST_MAX_CERTS];
+ PKIX_List *chain = NULL;
+ PKIX_Error *validationError = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+ char *dirName = NULL;
+ char *dataCentralDir = NULL;
+ char *anchorName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /*
+ * Perform hard-coded tests if no command line args.
+ * If command line args are provided, they must be:
+ * arg[1]: test name
+ * arg[2]: "ENE" or "EE", for "expect no error" or "expect error"
+ * arg[3]: directory for certificates
+ * arg[4]: user-initial-policy-set, consisting of braces
+ * containing zero or more OID sequences, separated by commas
+ * arg[5]: (optional) "E", indicating initialExplicitPolicy
+ * arg[firstCert]: the path and filename of the trust anchor certificate
+ * arg[firstCert+1..(n-1)]: successive certificates in the chain
+ * arg[n]: the end entity certificate
+ *
+ * Example: test_policychecker test1EE ENE
+ * {2.5.29.32.0,2.5.29.32.3.6} Anchor CA EndEntity
+ */
+
+ dirName = argv[3 + j];
+ dataCentralDir = argv[4 + j];
+
+ if (argc <= 5 || ((6 == argc) && (j))) {
+
+ testPass(dataCentralDir,
+ firstTrustAnchor,
+ secondTrustAnchor,
+ dateAscii);
+
+ testNistTest1(dirName);
+
+ testNistTest2(dirName);
+
+ goto cleanup;
+ }
+
+ if (argc < (7 + j)) {
+ printUsage(argv[0]);
+ pkixTestErrorMsg = "Invalid command line arguments.";
+ goto cleanup;
+ }
+
+ if (PORT_Strcmp(argv[2 + j], "ENE") == 0) {
+ expectedResult = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2 + j], "EE") == 0) {
+ expectedResult = PKIX_FALSE;
+ } else {
+ printUsage(argv[0]);
+ pkixTestErrorMsg = "Invalid command line arguments.";
+ goto cleanup;
+ }
+
+ userInitialPolicySet = policySetParse(argv[5 + j]);
+ if (!userInitialPolicySet) {
+ printUsage(argv[0]);
+ pkixTestErrorMsg = "Invalid command line arguments.";
+ goto cleanup;
+ }
+
+ for (initArgs = 0; initArgs < 3; initArgs++) {
+ if (PORT_Strcmp(argv[6 + j + initArgs], "A") == 0) {
+ initialAnyPolicyInhibit = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[6 + j + initArgs], "E") == 0) {
+ initialExplicitPolicy = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[6 + j + initArgs], "P") == 0) {
+ initialPolicyMappingInhibit = PKIX_TRUE;
+ } else {
+ break;
+ }
+ }
+
+ firstCert = initArgs + j + 6;
+ chainLength = argc - (firstCert + 1);
+ if (chainLength > PKIX_TEST_MAX_CERTS) {
+ printUsageMax(chainLength);
+ pkixTestErrorMsg = "Invalid command line arguments.";
+ goto cleanup;
+ }
+
+ /*
+ * Create a chain, but don't include the first certName.
+ * That's the anchor, and is supplied separately from
+ * the chain.
+ */
+ for (i = 0; i < chainLength; i++) {
+
+ certNames[i] = argv[i + (firstCert + 1)];
+ certs[i] = NULL;
+ }
+ chain = createCertChainPlus(dirName, certNames, certs, chainLength, plContext);
+
+ subTest(argv[1 + j]);
+
+ valParams = createValidateParams(dirName,
+ argv[firstCert],
+ NULL,
+ NULL,
+ userInitialPolicySet,
+ initialPolicyMappingInhibit,
+ initialAnyPolicyInhibit,
+ initialExplicitPolicy,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ if (expectedResult == PKIX_TRUE) {
+ subTest(" (expecting successful validation)");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+
+ printValidPolicyTree(valResult);
+
+ } else {
+ subTest(" (expecting validation to fail)");
+ validationError = PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext);
+ if (!validationError) {
+ printValidPolicyTree(valResult);
+ pkixTestErrorMsg = "Should have thrown an error here.";
+ }
+ PKIX_TEST_DECREF_BC(validationError);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)verifyTree, &verifyString, plContext));
+ (void)printf("verifyTree is\n%s\n", verifyString->escAsciiString);
+
+cleanup:
+
+ PKIX_PL_Free(anchorName, plContext);
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(userInitialPolicySet);
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(validationError);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("PolicyChecker");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/test_subjaltnamechecker.c b/security/nss/cmd/libpkix/pkix/top/test_subjaltnamechecker.c
new file mode 100644
index 000000000..3f9711e69
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_subjaltnamechecker.c
@@ -0,0 +1,261 @@
+/* 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/. */
+/*
+ * test_subjaltnamechecker.c
+ *
+ * Test Subject Alternative Name Checking
+ *
+ */
+
+/*
+ * There is no subjaltnamechecker. Instead, targetcertchecker is doing
+ * the job for checking subject alternative names' validity. For testing,
+ * in order to enter names with various type, we create this test excutable
+ * to parse different scenario.
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TEST_MAX_CERTS 10
+
+static void *plContext = NULL;
+
+static void
+printUsage1(char *pName)
+{
+ printf("\nUSAGE: %s test-name [ENE|EE] ", pName);
+ printf("cert [certs].\n");
+}
+
+static void
+printUsage2(char *name)
+{
+ printf("\ninvalid test-name syntax - %s", name);
+ printf("\ntest-name syntax: [01][DNORU]:<name>+...");
+ printf("\n [01] 1 - match all; 0 - match one");
+ printf("\n name - type can be specified as");
+ printf("\n [DNORU] D-Directory name");
+ printf("\n N-DNS name");
+ printf("\n O-OID name");
+ printf("\n R-RFC822 name");
+ printf("\n U-URI name");
+ printf("\n + separator for more names\n\n");
+}
+
+static void
+printUsageMax(PKIX_UInt32 numCerts)
+{
+ printf("\nUSAGE ERROR: number of certs %d exceed maximum %d\n",
+ numCerts, PKIX_TEST_MAX_CERTS);
+}
+
+static PKIX_UInt32
+getNameType(char *name)
+{
+ PKIX_UInt32 nameType;
+
+ PKIX_TEST_STD_VARS();
+
+ switch (*name) {
+ case 'D':
+ nameType = PKIX_DIRECTORY_NAME;
+ break;
+ case 'N':
+ nameType = PKIX_DNS_NAME;
+ break;
+ case 'O':
+ nameType = PKIX_OID_NAME;
+ break;
+ case 'R':
+ nameType = PKIX_RFC822_NAME;
+ break;
+ case 'U':
+ nameType = PKIX_URI_NAME;
+ break;
+ default:
+ printUsage2(name);
+ nameType = 0xFFFF;
+ }
+
+ goto cleanup;
+
+cleanup:
+ PKIX_TEST_RETURN();
+ return (nameType);
+}
+
+int
+test_subjaltnamechecker(int argc, char *argv[])
+{
+
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *selParams = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ char *certNames[PKIX_TEST_MAX_CERTS];
+ PKIX_PL_Cert *certs[PKIX_TEST_MAX_CERTS];
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ char *nameStr;
+ char *nameEnd;
+ char *names[PKIX_TEST_MAX_CERTS];
+ PKIX_UInt32 numNames = 0;
+ PKIX_UInt32 nameType;
+ PKIX_Boolean matchAll = PKIX_TRUE;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ char *dirName = NULL;
+ char *anchorName = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ startTests("SubjAltNameConstraintChecker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ j++; /* skip test-purpose string */
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2 + j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2 + j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ /* taking out leading and trailing ", if any */
+ nameStr = argv[1 + j];
+ subTest(nameStr);
+ if (*nameStr == '"') {
+ nameStr++;
+ nameEnd = nameStr;
+ while (*nameEnd != '"' && *nameEnd != '\0') {
+ nameEnd++;
+ }
+ *nameEnd = '\0';
+ }
+
+ /* extract first [0|1] inidcating matchAll or not */
+ matchAll = (*nameStr == '0') ? PKIX_FALSE : PKIX_TRUE;
+ nameStr++;
+
+ numNames = 0;
+ while (*nameStr != '\0') {
+ names[numNames++] = nameStr;
+ while (*nameStr != '+' && *nameStr != '\0') {
+ nameStr++;
+ }
+ if (*nameStr == '+') {
+ *nameStr = '\0';
+ nameStr++;
+ }
+ }
+
+ chainLength = (argc - j) - 4;
+ if (chainLength > PKIX_TEST_MAX_CERTS) {
+ printUsageMax(chainLength);
+ }
+
+ for (i = 0; i < chainLength; i++) {
+ certNames[i] = argv[(4 + j) + i];
+ certs[i] = NULL;
+ }
+
+ /* SubjAltName for validation */
+
+ subTest("Add Subject Alt Name for NameConstraint checking");
+
+ subTest("Create Selector and ComCertSelParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&selParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, selParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetMatchAllSubjAltNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetMatchAllSubjAltNames(selParams, matchAll, plContext));
+
+ subTest("PKIX_ComCertSelParams_AddSubjAltName(s)");
+ for (i = 0; i < numNames; i++) {
+ nameType = getNameType(names[i]);
+ if (nameType == 0xFFFF) {
+ return (0);
+ }
+ nameStr = names[i] + 2;
+ name = createGeneralName(nameType, nameStr, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_AddSubjAltName(selParams, name, plContext));
+ PKIX_TEST_DECREF_BC(name);
+ }
+
+ subTest("SubjAltName-Constraints - Create Cert Chain");
+
+ dirName = argv[3 + j];
+
+ chain = createCertChainPlus(dirName, certNames, certs, chainLength, plContext);
+
+ subTest("SubjAltName-Constraints - Create Params");
+
+ valParams = createValidateParams(dirName,
+ argv[4 +
+ j],
+ NULL,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ subTest("PKIX_ValidateParams_getProcessingParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams(valParams, &procParams, plContext));
+
+ subTest("PKIX_ProcessingParams_SetTargetCertConstraints");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, selector, plContext));
+
+ subTest("Subject Alt Name - Validate Chain");
+
+ if (testValid == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+ } else {
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+ }
+
+cleanup:
+
+ PKIX_PL_Free(anchorName, plContext);
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(selParams);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(name);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("SubjAltNameConstraintsChecker");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/test_validatechain.c b/security/nss/cmd/libpkix/pkix/top/test_validatechain.c
new file mode 100644
index 000000000..98cb7b018
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_validatechain.c
@@ -0,0 +1,221 @@
+/* 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/. */
+/*
+ * test_validatechain.c
+ *
+ * Test ValidateChain function
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\nvalidateChain TestName [ENE|EE] "
+ "<certStoreDirectory> <trustedCert> <targetCert>\n\n");
+ (void)printf("Validates a chain of certificates between "
+ "<trustedCert> and <targetCert>\n"
+ "using the certs and CRLs in <certStoreDirectory>. "
+ "If ENE is specified,\n"
+ "then an Error is Not Expected. "
+ "If EE is specified, an Error is Expected.\n");
+}
+
+static char *
+createFullPathName(
+ char *dirName,
+ char *certFile,
+ void *plContext)
+{
+ PKIX_UInt32 certFileLen;
+ PKIX_UInt32 dirNameLen;
+ char *certPathName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certFileLen = PL_strlen(certFile);
+ dirNameLen = PL_strlen(dirName);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc(dirNameLen +
+ certFileLen +
+ 2,
+ (void **)&certPathName,
+ plContext));
+
+ PL_strcpy(certPathName, dirName);
+ PL_strcat(certPathName, "/");
+ PL_strcat(certPathName, certFile);
+ printf("certPathName = %s\n", certPathName);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (certPathName);
+}
+
+static PKIX_Error *
+testDefaultCertStore(PKIX_ValidateParams *valParams, char *crlDir)
+{
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_PL_Date *validity = NULL;
+ PKIX_List *revCheckers = NULL;
+ PKIX_RevocationChecker *ocspChecker = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CollectionCertStoreContext_Create");
+
+ /* Create CollectionCertStore */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, crlDir, 0, &dirString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString, &certStore, plContext));
+
+ /* Create CertStore */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams(valParams, &procParams, plContext));
+
+ subTest("PKIX_ProcessingParams_AddCertStore");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertStore(procParams, certStore, plContext));
+
+ subTest("PKIX_ProcessingParams_SetRevocationEnabled");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_TRUE, plContext));
+
+ /* create current Date */
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Date_CreateFromPRTime(PR_Now(), &validity, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext));
+
+ /* create revChecker */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_OcspChecker_Initialize(validity,
+ NULL, /* pwArg */
+ NULL, /* Use default responder */
+ &ocspChecker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(revCheckers, (PKIX_PL_Object *)ocspChecker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers(procParams, revCheckers, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(revCheckers);
+ PKIX_TEST_DECREF_AC(ocspChecker);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+int
+test_validatechain(int argc, char *argv[])
+{
+
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 k = 0;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ PKIX_List *chainCerts = NULL;
+ PKIX_PL_Cert *dirCert = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+ char *dirCertName = NULL;
+ char *anchorCertName = NULL;
+ char *dirName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("ValidateChain");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2 + j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2 + j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage();
+ return (0);
+ }
+
+ subTest(argv[1 + j]);
+
+ dirName = argv[3 + j];
+
+ chainLength = argc - j - 5;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&chainCerts, plContext));
+
+ for (k = 0; k < chainLength; k++) {
+
+ dirCert = createCert(dirName, argv[5 + k + j], plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(chainCerts, (PKIX_PL_Object *)dirCert, plContext));
+
+ PKIX_TEST_DECREF_BC(dirCert);
+ }
+
+ valParams = createValidateParams(dirName,
+ argv[4 +
+ j],
+ NULL,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chainCerts,
+ plContext);
+
+ testDefaultCertStore(valParams, dirName);
+
+ if (testValid == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+ } else {
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+ }
+
+ subTest("Displaying VerifyNode objects");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)verifyTree, &verifyString, plContext));
+ (void)printf("verifyTree is\n%s\n", verifyString->escAsciiString);
+
+cleanup:
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+
+ PKIX_TEST_DECREF_AC(chainCerts);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ValidateChain");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/test_validatechain_NB.c b/security/nss/cmd/libpkix/pkix/top/test_validatechain_NB.c
new file mode 100644
index 000000000..ad73a5df7
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_validatechain_NB.c
@@ -0,0 +1,351 @@
+/* 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/. */
+/*
+ * test_validatechain_NB.c
+ *
+ * Test ValidateChain (nonblocking I/O) function
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ntest_validateChain_NB TestName [ENE|EE] "
+ "<certStoreDirectory> <trustedCert> <targetCert>\n\n");
+ (void)printf("Validates a chain of certificates between "
+ "<trustedCert> and <targetCert>\n"
+ "using the certs and CRLs in <certStoreDirectory>. "
+ "If ENE is specified,\n"
+ "then an Error is Not Expected. "
+ "If EE is specified, an Error is Expected.\n");
+}
+
+static char *
+createFullPathName(
+ char *dirName,
+ char *certFile,
+ void *plContext)
+{
+ PKIX_UInt32 certFileLen;
+ PKIX_UInt32 dirNameLen;
+ char *certPathName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certFileLen = PL_strlen(certFile);
+ dirNameLen = PL_strlen(dirName);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc(dirNameLen +
+ certFileLen +
+ 2,
+ (void **)&certPathName,
+ plContext));
+
+ PL_strcpy(certPathName, dirName);
+ PL_strcat(certPathName, "/");
+ PL_strcat(certPathName, certFile);
+ printf("certPathName = %s\n", certPathName);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (certPathName);
+}
+
+static PKIX_Error *
+testSetupCertStore(PKIX_ValidateParams *valParams, char *ldapName)
+{
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_PL_LdapDefaultClient *ldapClient = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CollectionCertStoreContext_Create");
+
+ /* Create LDAPCertStore */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapDefaultClient_CreateByName(ldapName,
+ 0, /* timeout */
+ NULL, /* bindPtr */
+ &ldapClient,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapCertStore_Create((PKIX_PL_LdapClient *)ldapClient,
+ &certStore,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams(valParams, &procParams, plContext));
+
+ subTest("PKIX_ProcessingParams_AddCertStore");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertStore(procParams, certStore, plContext));
+
+ subTest("PKIX_ProcessingParams_SetRevocationEnabled");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_TRUE, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(ldapClient);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+static char *levels[] = {
+ "None", "Fatal Error", "Error", "Warning", "Debug", "Trace"
+};
+
+static PKIX_Error *
+loggerCallback(
+ PKIX_Logger *logger,
+ PKIX_PL_String *message,
+ PKIX_UInt32 logLevel,
+ PKIX_ERRORCLASS logComponent,
+ void *plContext)
+{
+#define resultSize 150
+ char *msg = NULL;
+ char result[resultSize];
+
+ PKIX_TEST_STD_VARS();
+
+ msg = PKIX_String2ASCII(message, plContext);
+ PR_snprintf(result, resultSize,
+ "Logging %s (%s): %s",
+ levels[logLevel],
+ PKIX_ERRORCLASSNAMES[logComponent],
+ msg);
+ subTest(result);
+
+cleanup:
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(msg, plContext));
+ PKIX_TEST_RETURN();
+}
+
+static void
+testLogErrors(
+ PKIX_ERRORCLASS module,
+ PKIX_UInt32 loggingLevel,
+ PKIX_List *loggers,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+ PKIX_PL_String *component = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_Create(loggerCallback, NULL, &logger, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_SetLoggingComponent(logger, module, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_SetMaxLoggingLevel(logger, loggingLevel, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(loggers, (PKIX_PL_Object *)logger, plContext));
+
+cleanup:
+ PKIX_TEST_DECREF_AC(logger);
+ PKIX_TEST_DECREF_AC(component);
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_validatechain_NB(int argc, char *argv[])
+{
+
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 k = 0;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ PKIX_List *chainCerts = NULL;
+ PKIX_PL_Cert *dirCert = NULL;
+ char *dirCertName = NULL;
+ char *anchorCertName = NULL;
+ char *dirName = NULL;
+ PKIX_UInt32 certIndex = 0;
+ PKIX_UInt32 anchorIndex = 0;
+ PKIX_UInt32 checkerIndex = 0;
+ PKIX_Boolean revChecking = PKIX_FALSE;
+ PKIX_List *checkers = NULL;
+ PRPollDesc *pollDesc = NULL;
+ PRErrorCode errorCode = 0;
+ PKIX_PL_Socket *socket = NULL;
+ char *ldapName = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+
+ PKIX_List *loggers = NULL;
+ PKIX_Logger *logger = NULL;
+ char *logging = NULL;
+ PKIX_PL_String *component = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("ValidateChain_NB");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2 + j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2 + j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage();
+ return (0);
+ }
+
+ subTest(argv[1 + j]);
+
+ dirName = argv[3 + j];
+
+ chainLength = argc - j - 5;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&chainCerts, plContext));
+
+ for (k = 0; k < chainLength; k++) {
+
+ dirCert = createCert(dirName, argv[5 + k + j], plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(chainCerts, (PKIX_PL_Object *)dirCert, plContext));
+
+ PKIX_TEST_DECREF_BC(dirCert);
+ }
+
+ valParams = createValidateParams(dirName,
+ argv[4 +
+ j],
+ NULL,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chainCerts,
+ plContext);
+
+ ldapName = PR_GetEnvSecure("LDAP");
+ /* Is LDAP set in the environment? */
+ if ((ldapName == NULL) || (*ldapName == '\0')) {
+ testError("LDAP not set in environment");
+ goto cleanup;
+ }
+
+ pkixTestErrorResult = pkix_pl_Socket_CreateByName(PKIX_FALSE, /* isServer */
+ PR_SecondsToInterval(30), /* try 30 secs for connect */
+ ldapName,
+ &errorCode,
+ &socket,
+ plContext);
+
+ if (pkixTestErrorResult != NULL) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)pkixTestErrorResult, plContext);
+ pkixTestErrorResult = NULL;
+ testError("Unable to connect to LDAP Server");
+ goto cleanup;
+ }
+
+ PKIX_TEST_DECREF_BC(socket);
+
+ testSetupCertStore(valParams, ldapName);
+
+ logging = PR_GetEnvSecure("LOGGING");
+ /* Is LOGGING set in the environment? */
+ if ((logging != NULL) && (*logging != '\0')) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&loggers, plContext));
+
+ testLogErrors(PKIX_VALIDATE_ERROR, 2, loggers, plContext);
+ testLogErrors(PKIX_CERTCHAINCHECKER_ERROR, 2, loggers, plContext);
+ testLogErrors(PKIX_LDAPDEFAULTCLIENT_ERROR, 2, loggers, plContext);
+ testLogErrors(PKIX_CERTSTORE_ERROR, 2, loggers, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_SetLoggers(loggers, plContext));
+ }
+
+ pkixTestErrorResult = PKIX_ValidateChain_NB(valParams,
+ &certIndex,
+ &anchorIndex,
+ &checkerIndex,
+ &revChecking,
+ &checkers,
+ (void **)&pollDesc,
+ &valResult,
+ &verifyTree,
+ plContext);
+
+ while (pollDesc != NULL) {
+
+ if (PR_Poll(pollDesc, 1, 0) < 0) {
+ testError("PR_Poll failed");
+ }
+
+ pkixTestErrorResult = PKIX_ValidateChain_NB(valParams,
+ &certIndex,
+ &anchorIndex,
+ &checkerIndex,
+ &revChecking,
+ &checkers,
+ (void **)&pollDesc,
+ &valResult,
+ &verifyTree,
+ plContext);
+ }
+
+ if (pkixTestErrorResult) {
+ if (testValid == PKIX_FALSE) { /* EE */
+ (void)printf("EXPECTED ERROR RECEIVED!\n");
+ } else { /* ENE */
+ testError("UNEXPECTED ERROR RECEIVED");
+ }
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ } else {
+
+ if (testValid == PKIX_TRUE) { /* ENE */
+ (void)printf("EXPECTED NON-ERROR RECEIVED!\n");
+ } else { /* EE */
+ (void)printf("UNEXPECTED NON-ERROR RECEIVED!\n");
+ }
+ }
+
+cleanup:
+
+ if (verifyTree) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)verifyTree, &verifyString, plContext));
+ (void)printf("verifyTree is\n%s\n",
+ verifyString->escAsciiString);
+ }
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(checkers);
+ PKIX_TEST_DECREF_AC(chainCerts);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ValidateChain_NB");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/test_validatechain_bc.c b/security/nss/cmd/libpkix/pkix/top/test_validatechain_bc.c
new file mode 100644
index 000000000..480ec2643
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_validatechain_bc.c
@@ -0,0 +1,233 @@
+/* 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/. */
+/*
+ * validateChainBasicConstraints.c
+ *
+ * Tests Cert Chain Validation
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+
+#include "pkix_pl_generalname.h"
+#include "pkix_pl_cert.h"
+#include "pkix.h"
+#include "testutil.h"
+#include "prlong.h"
+#include "plstr.h"
+#include "prthread.h"
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "secitem.h"
+#include "keythi.h"
+#include "nss.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ printf("\nUSAGE: incorrect.\n");
+}
+
+static PKIX_PL_Cert *
+createCert(char *inFileName)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ void *buf = NULL;
+ PRFileDesc *inFile = NULL;
+ PKIX_UInt32 len;
+ SECItem certDER;
+ SECStatus rv;
+ /* default: NULL cert (failure case) */
+ PKIX_PL_Cert *cert = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certDER.data = NULL;
+
+ inFile = PR_Open(inFileName, PR_RDONLY, 0);
+
+ if (!inFile) {
+ pkixTestErrorMsg = "Unable to open cert file";
+ goto cleanup;
+ } else {
+ rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE, PR_FALSE);
+ if (!rv) {
+ buf = (void *)certDER.data;
+ len = certDER.len;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_Create(byteArray, &cert, plContext));
+
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ } else {
+ pkixTestErrorMsg = "Unable to read DER from cert file";
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ if (inFile) {
+ PR_Close(inFile);
+ }
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ }
+
+ PKIX_TEST_DECREF_AC(byteArray);
+
+ PKIX_TEST_RETURN();
+
+ return (cert);
+}
+
+int
+test_validatechain_bc(int argc, char *argv[])
+{
+
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_PL_X500Name *subject = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+
+ char *trustedCertFile = NULL;
+ char *chainCertFile = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *chainCert = NULL;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 3) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("ValidateChainBasicConstraints");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ chainLength = (argc - j) - 2;
+
+ /* create processing params with list of trust anchors */
+ trustedCertFile = argv[1 + j];
+ trustedCert = createCert(trustedCertFile);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(trustedCert, &subject, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints(certSelParams, -1, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext));
+
+ PKIX_TEST_DECREF_BC(subject);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert(trustedCert, &anchor, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create(anchors, &procParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_FALSE, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));
+
+ PKIX_TEST_DECREF_BC(certSelector);
+
+ /* create cert chain */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certs, plContext));
+ for (i = 0; i < chainLength; i++) {
+ chainCertFile = argv[i + (2 + j)];
+ chainCert = createCert(chainCertFile);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certs, (PKIX_PL_Object *)chainCert, plContext));
+
+ PKIX_TEST_DECREF_BC(chainCert);
+ }
+
+ /* create validate params with processing params and cert chain */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_Create(procParams, certs, &valParams, plContext));
+
+ /* validate cert chain using processing params and return valResult */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+
+ if (valResult != NULL) {
+ printf("SUCCESSFULLY VALIDATED with Basic Constraint ");
+ printf("Cert Selector minimum path length to be -1\n");
+ PKIX_TEST_DECREF_BC(valResult);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)verifyTree, &verifyString, plContext));
+ (void)printf("verifyTree is\n%s\n", verifyString->escAsciiString);
+ PKIX_TEST_DECREF_BC(verifyString);
+ PKIX_TEST_DECREF_BC(verifyTree);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints(certSelParams, 6, plContext));
+
+ /* validate cert chain using processing params and return valResult */
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+
+ if (valResult != NULL) {
+ printf("SUCCESSFULLY VALIDATED with Basic Constraint ");
+ printf("Cert Selector minimum path length to be 6\n");
+ }
+
+ PKIX_TEST_DECREF_BC(trustedCert);
+ PKIX_TEST_DECREF_BC(anchor);
+ PKIX_TEST_DECREF_BC(anchors);
+ PKIX_TEST_DECREF_BC(certs);
+ PKIX_TEST_DECREF_BC(procParams);
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ printf("FAILED TO VALIDATE\n");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)verifyTree, &verifyString, plContext));
+ (void)printf("verifyTree is\n%s\n", verifyString->escAsciiString);
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(valParams);
+
+ PKIX_TEST_RETURN();
+
+ PKIX_Shutdown(plContext);
+
+ endTests("ValidateChainBasicConstraints");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/util/Makefile b/security/nss/cmd/libpkix/pkix/util/Makefile
new file mode 100755
index 000000000..09ca5f1c6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/security/nss/cmd/libpkix/pkix/util/manifest.mn b/security/nss/cmd/libpkix/pkix/util/manifest.mn
new file mode 100755
index 000000000..7dbeb6d47
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/manifest.mn
@@ -0,0 +1,23 @@
+#
+# 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/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_error.c \
+ test_list.c \
+ test_list2.c \
+ test_logger.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtoolutil
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/util/test_error.c b/security/nss/cmd/libpkix/pkix/util/test_error.c
new file mode 100644
index 000000000..9cddecc82
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/test_error.c
@@ -0,0 +1,385 @@
+/* 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/. */
+/*
+ * test_error.c
+ *
+ * Tests Error Object Creation, ToString, Callbacks and Destroy
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createErrors(
+ PKIX_Error **error,
+ PKIX_Error **error2,
+ PKIX_Error **error3,
+ PKIX_Error **error5,
+ PKIX_Error **error6,
+ PKIX_Error **error7,
+ char *infoChar)
+
+{
+ PKIX_PL_String *infoString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ infoChar,
+ PL_strlen(infoChar),
+ &infoString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(PKIX_MEM_ERROR,
+ NULL,
+ NULL,
+ PKIX_TESTANOTHERERRORMESSAGE,
+ error2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(PKIX_OBJECT_ERROR,
+ *error2,
+ (PKIX_PL_Object *)infoString,
+ PKIX_TESTERRORMESSAGE,
+ error,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(PKIX_OBJECT_ERROR,
+ *error2,
+ (PKIX_PL_Object *)infoString,
+ PKIX_TESTERRORMESSAGE,
+ error3,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(PKIX_OBJECT_ERROR,
+ NULL,
+ (PKIX_PL_Object *)infoString,
+ 0,
+ error5,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(PKIX_MEM_ERROR,
+ *error5,
+ (PKIX_PL_Object *)infoString,
+ 0,
+ error6,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(PKIX_OBJECT_ERROR,
+ *error6,
+ (PKIX_PL_Object *)infoString,
+ 0,
+ error7,
+ plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(infoString);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetErrorClass(PKIX_Error *error, PKIX_Error *error2)
+{
+ PKIX_ERRORCLASS errClass;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetErrorClass(error, &errClass, plContext));
+
+ if (errClass != PKIX_OBJECT_ERROR) {
+ testError("Incorrect Class Returned");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetErrorClass(error2, &errClass, plContext));
+
+ if (errClass != PKIX_MEM_ERROR) {
+ testError("Incorrect Class Returned");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetErrorClass(PKIX_ALLOC_ERROR(),
+ &errClass, plContext));
+ if (errClass != PKIX_FATAL_ERROR) {
+ testError("Incorrect Class Returned");
+ }
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetDescription(
+ PKIX_Error *error,
+ PKIX_Error *error2,
+ PKIX_Error *error3,
+ char *descChar,
+ char *descChar2)
+{
+
+ PKIX_PL_String *targetString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetDescription(error, &targetString, plContext));
+ temp = PKIX_String2ASCII(targetString, plContext);
+ PKIX_TEST_DECREF_BC(targetString);
+
+ if (temp) {
+ if (PL_strcmp(temp, descChar) != 0) {
+ testError("Incorrect description returned");
+ }
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetDescription(error2, &targetString, plContext));
+ temp = PKIX_String2ASCII(targetString, plContext);
+ PKIX_TEST_DECREF_BC(targetString);
+
+ if (temp) {
+ if (PL_strcmp(temp, descChar2) != 0) {
+ testError("Incorrect description returned");
+ }
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetDescription(error3, &targetString, plContext));
+ temp = PKIX_String2ASCII(targetString, plContext);
+ PKIX_TEST_DECREF_BC(targetString);
+
+ if (temp) {
+ if (PL_strcmp(temp, descChar) != 0) {
+ testError("Incorrect description returned");
+ }
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCause(PKIX_Error *error, PKIX_Error *error2, PKIX_Error *error3)
+{
+
+ PKIX_Error *error4 = NULL;
+ PKIX_PL_String *targetString = NULL;
+ char *temp = NULL;
+ PKIX_Boolean boolResult;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetCause(error, &error4, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)error2,
+ (PKIX_PL_Object *)error4,
+ &boolResult, plContext));
+ if (!boolResult)
+ testError("Incorrect Cause returned");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)error4,
+ &targetString, plContext));
+
+ temp = PKIX_String2ASCII(targetString, plContext);
+ if (temp) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ PKIX_TEST_DECREF_BC(targetString);
+ PKIX_TEST_DECREF_BC(error4);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetCause(error3, &error4, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)error2,
+ (PKIX_PL_Object *)error4,
+ &boolResult, plContext));
+ if (!boolResult)
+ testError("Incorrect Cause returned");
+
+ PKIX_TEST_DECREF_BC(error4);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSupplementaryInfo(PKIX_Error *error, char *infoChar)
+{
+
+ PKIX_PL_Object *targetString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetSupplementaryInfo(error, &targetString, plContext));
+ temp = PKIX_String2ASCII((PKIX_PL_String *)targetString, plContext);
+ PKIX_TEST_DECREF_BC(targetString);
+
+ if (temp) {
+ if (PL_strcmp(temp, infoChar) != 0) {
+ testError("Incorrect info returned");
+ }
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testPrimitiveError(void)
+{
+ PKIX_PL_String *targetString = NULL;
+ PKIX_PL_String *targetStringCopy = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)PKIX_ALLOC_ERROR(),
+ &targetString, plContext));
+
+ temp = PKIX_String2ASCII(targetString, plContext);
+ if (temp) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ targetStringCopy = targetString;
+
+ PKIX_TEST_DECREF_BC(targetString);
+
+ /*
+ * We need to DECREF twice, b/c the PKIX_ALLOC_ERROR object
+ * which holds a cached copy of the stringRep can never be DECREF'd
+ */
+ PKIX_TEST_DECREF_BC(targetStringCopy);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testChaining(PKIX_Error *error7)
+{
+ PKIX_PL_String *targetString = NULL;
+ PKIX_Error *tempError = NULL;
+ char *temp = NULL;
+ PKIX_UInt32 i;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)error7,
+ &targetString, plContext));
+
+ temp = PKIX_String2ASCII(targetString, plContext);
+ if (temp) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ for (i = 0, tempError = error7; i < 2; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetCause(tempError, &tempError, plContext));
+ if (tempError == NULL) {
+ testError("Unexpected end to error chain");
+ break;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_DecRef((PKIX_PL_Object *)tempError, plContext));
+ }
+
+ PKIX_TEST_DECREF_BC(targetString);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(PKIX_Error *error)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(error);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_error(int argc, char *argv[])
+{
+
+ PKIX_Error *error, *error2, *error3, *error5, *error6, *error7;
+ char *descChar = "Error Message";
+ char *descChar2 = "Another Error Message";
+ char *infoChar = "Auxiliary Info";
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Errors");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_Error_Create");
+ createErrors(&error,
+ &error2,
+ &error3,
+ &error5,
+ &error6,
+ &error7,
+ infoChar);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(error,
+ error,
+ error2,
+ NULL,
+ Error,
+ PKIX_TRUE);
+
+ subTest("PKIX_Error_GetErrorClass");
+ testGetErrorClass(error, error2);
+
+ subTest("PKIX_Error_GetDescription");
+ testGetDescription(error, error2, error3, descChar, descChar2);
+
+ subTest("PKIX_Error_GetCause");
+ testGetCause(error, error2, error3);
+
+ subTest("PKIX_Error_GetSupplementaryInfo");
+ testGetSupplementaryInfo(error, infoChar);
+
+ subTest("Primitive Error Type");
+ testPrimitiveError();
+
+ subTest("Error Chaining");
+ testChaining(error7);
+
+ subTest("PKIX_Error_Destroy");
+ testDestroy(error);
+ testDestroy(error2);
+ testDestroy(error3);
+ testDestroy(error5);
+ testDestroy(error6);
+ testDestroy(error7);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Errors");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/util/test_list.c b/security/nss/cmd/libpkix/pkix/util/test_list.c
new file mode 100644
index 000000000..e5e6e507b
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/test_list.c
@@ -0,0 +1,765 @@
+/* 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/. */
+/*
+ * test_list.c
+ *
+ * Tests List Objects
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createLists(PKIX_List **list, PKIX_List **list2)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(list, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(list2, plContext));
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testReverseList(void)
+{
+ PKIX_List *firstList = NULL;
+ PKIX_List *reverseList = NULL;
+ PKIX_UInt32 length, i;
+ char *testItemString = "one";
+ char *testItemString2 = "two";
+ PKIX_PL_String *testItem = NULL;
+ PKIX_PL_String *testItem2 = NULL;
+ PKIX_PL_Object *retrievedItem1 = NULL;
+ PKIX_PL_Object *retrievedItem2 = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&firstList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_ReverseList(firstList, &reverseList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(reverseList, &length, plContext));
+ if (length != 0) {
+ testError("Incorrect Length returned");
+ }
+
+ PKIX_TEST_DECREF_BC(reverseList);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString,
+ 0,
+ &testItem,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString2,
+ 0,
+ &testItem2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(firstList,
+ (PKIX_PL_Object *)testItem,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_ReverseList(firstList, &reverseList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(reverseList, &length, plContext));
+ if (length != 1) {
+ testError("Incorrect Length returned");
+ }
+
+ PKIX_TEST_DECREF_BC(reverseList);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(firstList,
+ (PKIX_PL_Object *)testItem2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(firstList,
+ (PKIX_PL_Object *)testItem,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(firstList,
+ (PKIX_PL_Object *)testItem2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_ReverseList(firstList, &reverseList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(reverseList, &length, plContext));
+ if (length != 4) {
+ testError("Incorrect Length returned");
+ }
+
+ for (i = 0; i < length; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(firstList,
+ i,
+ &retrievedItem1,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(reverseList,
+ (length - 1) - i,
+ &retrievedItem2,
+ plContext));
+
+ testEqualsHelper(retrievedItem1, retrievedItem2, PKIX_TRUE, plContext);
+
+ PKIX_TEST_DECREF_BC(retrievedItem1);
+ PKIX_TEST_DECREF_BC(retrievedItem2);
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(firstList);
+ PKIX_TEST_DECREF_AC(reverseList);
+
+ PKIX_TEST_DECREF_AC(testItem);
+ PKIX_TEST_DECREF_AC(testItem2);
+
+ PKIX_TEST_DECREF_AC(retrievedItem1);
+ PKIX_TEST_DECREF_AC(retrievedItem2);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testZeroLengthList(PKIX_List *list)
+{
+ PKIX_UInt32 length;
+ PKIX_Boolean empty;
+ char *testItemString = "hello";
+ PKIX_PL_String *testItem = NULL;
+ PKIX_PL_String *retrievedItem = NULL;
+ PKIX_List *diffList = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&diffList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(list, &length, plContext));
+
+ if (length != 0) {
+ testError("Incorrect Length returned");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsEmpty(list, &empty, plContext));
+ if (!empty) {
+ testError("Incorrect result for PKIX_List_IsEmpty");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString,
+ 0,
+ &testItem,
+ plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_InsertItem(list, 0, (PKIX_PL_Object *)testItem, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_SetItem(list, 0, (PKIX_PL_Object *)testItem, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_GetItem(list,
+ 0,
+ (PKIX_PL_Object **)&retrievedItem,
+ plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_DeleteItem(list, 0, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(diffList,
+ (PKIX_PL_Object *)testItem,
+ plContext));
+
+ testDuplicateHelper((PKIX_PL_Object *)diffList, plContext);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(list, list, diffList, "(EMPTY)", List, PKIX_TRUE);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(diffList, &length, plContext));
+ if (length != 1) {
+ testError("Incorrect Length returned");
+ }
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_DeleteItem(list, 1, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(diffList, 0, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(diffList, &length, plContext));
+ if (length != 0) {
+ testError("Incorrect Length returned");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(testItem);
+ PKIX_TEST_DECREF_AC(diffList);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetLength(PKIX_List *list)
+{
+ PKIX_UInt32 length;
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(list, &length, plContext));
+
+ if (length != 3) {
+ testError("Incorrect Length returned");
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSetItem(
+ PKIX_List *list,
+ char *testItemString,
+ char *testItemString2,
+ char *testItemString3,
+ PKIX_PL_String **testItem,
+ PKIX_PL_String **testItem2,
+ PKIX_PL_String **testItem3)
+{
+ PKIX_PL_Object *tempItem = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString,
+ PL_strlen(testItemString),
+ testItem,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString2,
+ PL_strlen(testItemString2),
+ testItem2,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString3,
+ PL_strlen(testItemString3),
+ testItem3,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)*testItem, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)*testItem, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)*testItem, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, 0, (PKIX_PL_Object *)*testItem, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, 1, (PKIX_PL_Object *)*testItem2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, 2, (PKIX_PL_Object *)*testItem3, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, 0, &tempItem, plContext));
+
+ temp = PKIX_String2ASCII((PKIX_PL_String *)tempItem, plContext);
+ if (temp) {
+ if (PL_strcmp(testItemString, temp) != 0)
+ testError("GetItem from list is incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ PKIX_TEST_DECREF_BC(tempItem);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, 1, &tempItem, plContext));
+
+ temp = PKIX_String2ASCII((PKIX_PL_String *)tempItem, plContext);
+ if (temp) {
+ if (PL_strcmp(testItemString2, temp) != 0)
+ testError("GetItem from list is incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(tempItem);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, 2, &tempItem, plContext));
+
+ temp = PKIX_String2ASCII((PKIX_PL_String *)tempItem, plContext);
+ if (temp) {
+ if (PL_strcmp(testItemString3, temp) != 0)
+ testError("GetItem from list is incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(tempItem);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, 0, (PKIX_PL_Object *)*testItem3, plContext));
+ temp = PKIX_String2ASCII(*testItem3, plContext);
+ if (temp) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, 0, &tempItem, plContext));
+
+ temp = PKIX_String2ASCII((PKIX_PL_String *)tempItem, plContext);
+ if (temp) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ temp = PKIX_String2ASCII((PKIX_PL_String *)tempItem, plContext);
+ if (temp) {
+ if (PL_strcmp(testItemString3, temp) != 0)
+ testError("GetItem from list is incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(tempItem);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testInsertItem(
+ PKIX_List *list,
+ PKIX_PL_String *testItem,
+ char *testItemString)
+{
+ PKIX_PL_Object *tempItem = NULL;
+ PKIX_PL_String *outputString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_InsertItem(list, 0, (PKIX_PL_Object *)testItem, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, 0, &tempItem, plContext));
+
+ temp = PKIX_String2ASCII((PKIX_PL_String *)tempItem, plContext);
+ if (temp) {
+ if (PL_strcmp(testItemString, temp) != 0)
+ testError("GetItem from list is incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(tempItem);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, c, b, c)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ PKIX_TEST_DECREF_BC(outputString);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAppendItem(PKIX_List *list, PKIX_PL_String *testItem)
+{
+ PKIX_UInt32 length2;
+ PKIX_PL_String *outputString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(list, &length2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list,
+ (PKIX_PL_Object *)testItem,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, c, b, c, a)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ PKIX_TEST_DECREF_BC(outputString);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testNestedLists(
+ PKIX_List *list,
+ PKIX_List *list2,
+ PKIX_PL_String *testItem,
+ PKIX_PL_String *testItem2)
+{
+ PKIX_PL_String *outputString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list2, (PKIX_PL_Object *)testItem, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list2,
+ (PKIX_PL_Object *)NULL,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list2,
+ (PKIX_PL_Object *)testItem,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list2,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, (null), a)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_InsertItem(list, 1,
+ (PKIX_PL_Object *)list2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, (a, (null), a), c, b, c, a)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDeleteItem(
+ PKIX_List *list,
+ PKIX_List *list2,
+ PKIX_PL_String *testItem2,
+ PKIX_PL_String *testItem3)
+{
+ PKIX_PL_String *outputString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(list, 5, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, (a, (null), a), c, b, c)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(list, 1, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, c, b, c)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(list, 0, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(c, b, c)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(list2, 1, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list2,
+ &outputString,
+ plContext));
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, a)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list2,
+ (PKIX_PL_Object *)testItem2,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list2,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, a, b)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(list2, 2, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list2,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, a)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list2,
+ (PKIX_PL_Object *)testItem3,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list2,
+ &outputString,
+ plContext));
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, a, c)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_DECREF_BC(list2);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+#if testContainsFunction
+/* This test requires pkix_List_Contains to be in nss.def */
+static void
+testContains(void)
+{
+
+ PKIX_List *list;
+ PKIX_PL_String *testItem, *testItem2, *testItem3, *testItem4;
+ char *testItemString = "a";
+ char *testItemString2 = "b";
+ char *testItemString3 = "c";
+ char *testItemString4 = "d";
+ PKIX_Boolean found = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+ subTest("pkix_ListContains");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString,
+ PL_strlen(testItemString),
+ &testItem,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString2,
+ PL_strlen(testItemString2),
+ &testItem2,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString3,
+ PL_strlen(testItemString3),
+ &testItem3,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString4,
+ PL_strlen(testItemString4),
+ &testItem4,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&list, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)testItem, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)testItem2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)testItem3, plContext));
+
+ subTest("pkix_List_Contains <object missing>");
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_List_Contains(list, (PKIX_PL_Object *)testItem4, &found, plContext));
+
+ if (found) {
+ testError("Contains found item that wasn't there!");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)testItem4, plContext));
+
+ subTest("pkix_List_Contains <object present>");
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_List_Contains(list, (PKIX_PL_Object *)testItem4, &found, plContext));
+
+ if (!found) {
+ testError("Contains missed item that was present!");
+ }
+
+ PKIX_TEST_DECREF_BC(list);
+ PKIX_TEST_DECREF_BC(testItem);
+ PKIX_TEST_DECREF_BC(testItem2);
+ PKIX_TEST_DECREF_BC(testItem3);
+ PKIX_TEST_DECREF_BC(testItem4);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+#endif
+
+static void
+testErrorHandling(void)
+{
+ PKIX_List *emptylist = NULL;
+ PKIX_List *list = NULL;
+ PKIX_PL_Object *tempItem = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&list, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_GetItem(list, 4, &tempItem, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_GetItem(list, 1, NULL, plContext));
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_SetItem(list, 4, tempItem, plContext));
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_SetItem(NULL, 1, tempItem, plContext));
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_InsertItem(list, 4, tempItem, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_InsertItem(NULL, 1, tempItem, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_AppendItem(NULL, tempItem, plContext));
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_DeleteItem(list, 5, plContext));
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_DeleteItem(NULL, 1, plContext));
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_GetLength(list, NULL, plContext));
+
+ PKIX_TEST_DECREF_BC(list);
+ PKIX_TEST_DECREF_BC(emptylist);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(PKIX_List *list)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(list);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_list(int argc, char *argv[])
+{
+
+ PKIX_List *list, *list2;
+ PKIX_PL_String *testItem, *testItem2, *testItem3;
+ char *testItemString = "a";
+ char *testItemString2 = "b";
+ char *testItemString3 = "c";
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Lists");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_List_Create");
+ createLists(&list, &list2);
+
+ subTest("pkix_List_ReverseList");
+ testReverseList();
+
+ subTest("Zero-length List");
+ testZeroLengthList(list);
+
+ subTest("PKIX_List_Get/SetItem");
+ testGetSetItem(list,
+ testItemString,
+ testItemString2,
+ testItemString3,
+ &testItem,
+ &testItem2,
+ &testItem3);
+
+ subTest("PKIX_List_GetLength");
+ testGetLength(list);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(list,
+ list,
+ list2,
+ "(c, b, c)",
+ List,
+ PKIX_TRUE);
+
+ subTest("PKIX_List_InsertItem");
+ testInsertItem(list, testItem, testItemString);
+
+ subTest("PKIX_List_AppendItem");
+ testAppendItem(list, testItem);
+
+ subTest("Nested Lists");
+ testNestedLists(list, list2, testItem, testItem2);
+
+ subTest("PKIX_List_DeleteItem");
+ testDeleteItem(list, list2, testItem2, testItem3);
+
+ PKIX_TEST_DECREF_BC(testItem);
+ PKIX_TEST_DECREF_BC(testItem2);
+ PKIX_TEST_DECREF_BC(testItem3);
+
+#if testContainsFunction
+ /* This test requires pkix_List_Contains to be in nss.def */
+ testContains();
+#endif
+
+ subTest("PKIX_List Error Handling");
+ testErrorHandling();
+
+ subTest("PKIX_List_Destroy");
+ testDestroy(list);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Lists");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/util/test_list2.c b/security/nss/cmd/libpkix/pkix/util/test_list2.c
new file mode 100644
index 000000000..7e4114e52
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/test_list2.c
@@ -0,0 +1,120 @@
+/* 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/. */
+/*
+ * test_list2.c
+ *
+ * Performs an in-place sort on a list
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+int
+test_list2(int argc, char *argv[])
+{
+
+ PKIX_List *list;
+ char *temp;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_Int32 cmpResult;
+ PKIX_PL_OID *testOID;
+ PKIX_PL_String *testString;
+ PKIX_PL_Object *obj, *obj2;
+ PKIX_UInt32 size = 10;
+ char *testOIDString[10] = {
+ "2.9.999.1.20",
+ "1.2.3.4.5.6.7",
+ "0.1",
+ "1.2.3.5",
+ "0.39",
+ "1.2.3.4.7",
+ "1.2.3.4.6",
+ "0.39.1",
+ "1.2.3.4.5",
+ "0.39.1.300"
+ };
+ PKIX_UInt32 actualMinorVersion;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("List Sorting");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("Creating Unsorted Lists");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&list, plContext));
+ for (i = 0; i < size; i++) {
+ /* Create a new OID object */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(
+ testOIDString[i],
+ &testOID,
+ plContext));
+ /* Insert it into the list */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)testOID, plContext));
+ /* Decref the string object */
+ PKIX_TEST_DECREF_BC(testOID);
+ }
+
+ subTest("Outputting Unsorted List");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &testString,
+ plContext));
+ temp = PKIX_String2ASCII(testString, plContext);
+ if (temp) {
+ (void)printf("%s \n", temp);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(testString);
+
+ subTest("Performing Bubble Sort");
+
+ for (i = 0; i < size; i++)
+ for (j = 9; j > i; j--) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, j, &obj, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, j -
+ 1,
+ &obj2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare(obj, obj2, &cmpResult, plContext));
+ if (cmpResult < 0) {
+ /* Exchange the items */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, j, obj2, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, j -
+ 1,
+ obj, plContext));
+ }
+ /* DecRef objects */
+ PKIX_TEST_DECREF_BC(obj);
+ PKIX_TEST_DECREF_BC(obj2);
+ }
+
+ subTest("Outputting Sorted List");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &testString,
+ plContext));
+ temp = PKIX_String2ASCII(testString, plContext);
+ if (temp) {
+ (void)printf("%s \n", temp);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(testString);
+ PKIX_TEST_DECREF_AC(list);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("List Sorting");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/util/test_logger.c b/security/nss/cmd/libpkix/pkix/util/test_logger.c
new file mode 100644
index 000000000..3b7e5160a
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/test_logger.c
@@ -0,0 +1,314 @@
+/* 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/. */
+/*
+ * test_logger.c
+ *
+ * Tests Logger Objects
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static char *levels[] = {
+ "None",
+ "Fatal Error",
+ "Error",
+ "Warning",
+ "Debug",
+ "Trace"
+};
+
+static PKIX_Error *
+testLoggerCallback(
+ PKIX_Logger *logger,
+ PKIX_PL_String *message,
+ PKIX_UInt32 logLevel,
+ PKIX_ERRORCLASS logComponent,
+ void *plContext)
+{
+ char *comp = NULL;
+ char *msg = NULL;
+ char result[100];
+ static int callCount = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ msg = PKIX_String2ASCII(message, plContext);
+ PR_snprintf(result, 100, "Logging %s (%s): %s",
+ levels[logLevel], PKIX_ERRORCLASSNAMES[logComponent], msg);
+ subTest(result);
+
+ callCount++;
+ if (callCount > 1) {
+ testError("Incorrect number of Logger Callback <expect 1>");
+ }
+
+cleanup:
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(msg, plContext));
+ PKIX_TEST_RETURN();
+}
+
+static PKIX_Error *
+testLoggerCallback2(
+ PKIX_Logger *logger,
+ PKIX_PL_String *message,
+ PKIX_UInt32 logLevel,
+ PKIX_ERRORCLASS logComponent,
+ void *plContext)
+{
+ char *comp = NULL;
+ char *msg = NULL;
+ char result[100];
+
+ PKIX_TEST_STD_VARS();
+
+ msg = PKIX_String2ASCII(message, plContext);
+ PR_snprintf(result, 100, "Logging %s (%s): %s",
+ levels[logLevel], PKIX_ERRORCLASSNAMES[logComponent], msg);
+ subTest(result);
+
+cleanup:
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(msg, plContext));
+ PKIX_TEST_RETURN();
+}
+
+static void
+createLogger(PKIX_Logger **logger,
+ PKIX_PL_Object *context,
+ PKIX_Logger_LogCallback cb)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_Create(cb, context, logger, plContext));
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testContextCallback(PKIX_Logger *logger, PKIX_Logger *logger2)
+{
+ PKIX_Logger_LogCallback cb = NULL;
+ PKIX_PL_Object *context = NULL;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+ PKIX_UInt32 length;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_Logger_GetLoggerContext");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_GetLoggerContext(logger2, &context, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)logger, context, PKIX_TRUE, plContext);
+
+ subTest("PKIX_Logger_GetLogCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_GetLogCallback(logger, &cb, plContext));
+
+ if (cb != testLoggerCallback) {
+ testError("Incorrect Logger Callback returned");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(context);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testComponent(PKIX_Logger *logger)
+{
+ PKIX_ERRORCLASS compName = (PKIX_ERRORCLASS)NULL;
+ PKIX_ERRORCLASS compNameReturn = (PKIX_ERRORCLASS)NULL;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_Logger_GetLoggingComponent");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_GetLoggingComponent(logger, &compName, plContext));
+
+ if (compName != (PKIX_ERRORCLASS)NULL) {
+ testError("Incorrect Logger Component returned. expect <NULL>");
+ }
+
+ subTest("PKIX_Logger_SetLoggingComponent");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_SetLoggingComponent(logger, PKIX_LIST_ERROR, plContext));
+
+ subTest("PKIX_Logger_GetLoggingComponent");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_GetLoggingComponent(logger, &compNameReturn, plContext));
+
+ if (compNameReturn != PKIX_LIST_ERROR) {
+ testError("Incorrect Logger Component returned.");
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testMaxLoggingLevel(PKIX_Logger *logger)
+{
+ PKIX_UInt32 level = 0;
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_Logger_GetMaxLoggingLevel");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_GetMaxLoggingLevel(logger, &level, plContext));
+
+ if (level != 0) {
+ testError("Incorrect Logger MaxLoggingLevel returned");
+ }
+
+ subTest("PKIX_Logger_SetMaxLoggingLevel");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_SetMaxLoggingLevel(logger, 3, plContext));
+
+ subTest("PKIX_Logger_GetMaxLoggingLevel");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_GetMaxLoggingLevel(logger, &level, plContext));
+
+ if (level != 3) {
+ testError("Incorrect Logger MaxLoggingLevel returned");
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testLogger(PKIX_Logger *logger, PKIX_Logger *logger2)
+{
+ PKIX_List *loggerList = NULL;
+ PKIX_List *checkList = NULL;
+ PKIX_UInt32 length;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+ char *expectedAscii = "[\n"
+ "\tLogger: \n"
+ "\tContext: (null)\n"
+ "\tMaximum Level: 3\n"
+ "\tComponent Name: LIST\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_GetLoggers");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_GetLoggers(&loggerList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(loggerList, &length, plContext));
+ if (length != 0) {
+ testError("Incorrect Logger List returned");
+ }
+ PKIX_TEST_DECREF_BC(loggerList);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&loggerList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(loggerList, (PKIX_PL_Object *)logger, plContext));
+
+ subTest("PKIX_SetLoggers");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_SetLoggers(loggerList, plContext));
+
+ subTest("PKIX_Logger_SetLoggingComponent");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_SetLoggingComponent(logger2, PKIX_MUTEX_ERROR, plContext));
+
+ subTest("PKIX_Logger_SetMaxLoggingLevel");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_SetMaxLoggingLevel(logger2, 5, plContext));
+
+ subTest("PKIX_AddLogger");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_AddLogger(logger2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&checkList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(checkList, (PKIX_PL_Object *)logger, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(checkList, (PKIX_PL_Object *)logger2, plContext));
+
+ PKIX_TEST_DECREF_BC(loggerList);
+
+ subTest("PKIX_GetLoggers");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_GetLoggers(&loggerList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(loggerList, &length, plContext));
+
+ subTest("pkix_Loggers_Equals");
+ testEqualsHelper((PKIX_PL_Object *)loggerList,
+ (PKIX_PL_Object *)checkList,
+ PKIX_TRUE,
+ plContext);
+
+ subTest("pkix_Loggers_Duplicate");
+ testDuplicateHelper((PKIX_PL_Object *)logger, plContext);
+
+ subTest("pkix_Loggers_Hashcode");
+ testHashcodeHelper((PKIX_PL_Object *)logger,
+ (PKIX_PL_Object *)logger,
+ PKIX_TRUE,
+ plContext);
+
+ subTest("pkix_Loggers_ToString");
+ testToStringHelper((PKIX_PL_Object *)logger, expectedAscii, plContext);
+
+ subTest("PKIX Logger Callback");
+ subTest("Expect to have ***Fatal Error (List): Null argument*** once");
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_AppendItem(NULL, (PKIX_PL_Object *)NULL, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(loggerList);
+ PKIX_TEST_DECREF_AC(checkList);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(PKIX_Logger *logger)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(logger);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_logger(int argc, char *argv[])
+{
+
+ PKIX_Logger *logger, *logger2;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Loggers");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_Logger_Create");
+ createLogger(&logger, NULL, testLoggerCallback);
+ createLogger(&logger2, (PKIX_PL_Object *)logger, testLoggerCallback2);
+
+ subTest("Logger Context and Callback");
+ testContextCallback(logger, logger2);
+
+ subTest("Logger Component");
+ testComponent(logger);
+
+ subTest("Logger MaxLoggingLevel");
+ testMaxLoggingLevel(logger);
+
+ subTest("Logger List operations");
+ testLogger(logger, logger2);
+
+ subTest("PKIX_Logger_Destroy");
+ testDestroy(logger);
+ testDestroy(logger2);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Loggers");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/Makefile b/security/nss/cmd/libpkix/pkix_pl/Makefile
new file mode 100755
index 000000000..ab4ffbda5
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
+
diff --git a/security/nss/cmd/libpkix/pkix_pl/manifest.mn b/security/nss/cmd/libpkix/pkix_pl/manifest.mn
new file mode 100755
index 000000000..84997cbe6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/manifest.mn
@@ -0,0 +1,11 @@
+#
+# 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/.
+
+PKIX_DEPTH = ./..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+DIRS = module pki system \
+ $(NULL)
diff --git a/security/nss/cmd/libpkix/pkix_pl/module/Makefile b/security/nss/cmd/libpkix/pkix_pl/module/Makefile
new file mode 100755
index 000000000..09ca5f1c6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/security/nss/cmd/libpkix/pkix_pl/module/manifest.mn b/security/nss/cmd/libpkix/pkix_pl/module/manifest.mn
new file mode 100755
index 000000000..eedc93449
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/manifest.mn
@@ -0,0 +1,24 @@
+#
+# 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/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_colcertstore.c \
+ test_ekuchecker.c \
+ test_pk11certstore.c \
+ test_socket.c \
+ test_httpcertstore.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtoolmodule
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix_pl/module/test_colcertstore.c b/security/nss/cmd/libpkix/pkix_pl/module/test_colcertstore.c
new file mode 100644
index 000000000..37169d6ff
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/test_colcertstore.c
@@ -0,0 +1,247 @@
+/* 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/. */
+/*
+ * test_colcertstore.c
+ *
+ * Test CollectionCertStore Type
+ *
+ */
+
+#include "testutil.h"
+
+#include "testutil_nss.h"
+
+/* When CRL IDP is supported, change NUM_CRLS to 9 */
+#define PKIX_TEST_COLLECTIONCERTSTORE_NUM_CRLS 4
+#define PKIX_TEST_COLLECTIONCERTSTORE_NUM_CERTS 15
+
+static void *plContext = NULL;
+
+static PKIX_Error *
+testCRLSelectorMatchCallback(
+ PKIX_CRLSelector *selector,
+ PKIX_PL_CRL *crl,
+ PKIX_Boolean *pMatch,
+ void *plContext)
+{
+ *pMatch = PKIX_TRUE;
+
+ return (0);
+}
+
+static PKIX_Error *
+testCertSelectorMatchCallback(
+ PKIX_CertSelector *selector,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ *pResult = PKIX_TRUE;
+
+ return (0);
+}
+
+static PKIX_Error *
+getCertCallback(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *certSelector,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ return (0);
+}
+
+static char *
+catDirName(char *platform, char *dir, void *plContext)
+{
+ char *pathName = NULL;
+ PKIX_UInt32 dirLen;
+ PKIX_UInt32 platformLen;
+
+ PKIX_TEST_STD_VARS();
+
+ dirLen = PL_strlen(dir);
+ platformLen = PL_strlen(platform);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc(platformLen +
+ dirLen +
+ 2,
+ (void **)&pathName, plContext));
+
+ PL_strcpy(pathName, platform);
+ PL_strcat(pathName, "/");
+ PL_strcat(pathName, dir);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (pathName);
+}
+
+static void
+testGetCRL(char *crlDir)
+{
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore_CRLCallback crlCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+ PKIX_List *crlList = NULL;
+ PKIX_UInt32 numCrl = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ crlDir,
+ 0,
+ &dirString,
+ plContext));
+
+ subTest("PKIX_PL_CollectionCertStore_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString,
+ &certStore,
+ plContext));
+
+ subTest("PKIX_CRLSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_Create(testCRLSelectorMatchCallback,
+ NULL,
+ &crlSelector,
+ plContext));
+
+ subTest("PKIX_CertStore_GetCRLCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCRLCallback(certStore, &crlCallback, NULL));
+
+ subTest("Getting data from CRL Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(crlCallback(certStore,
+ crlSelector,
+ &nbioContext,
+ &crlList,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(crlList,
+ &numCrl,
+ plContext));
+
+ if (numCrl != PKIX_TEST_COLLECTIONCERTSTORE_NUM_CRLS) {
+ pkixTestErrorMsg = "unexpected CRL number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(crlList);
+ PKIX_TEST_DECREF_AC(crlSelector);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCert(char *certDir)
+{
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore_CertCallback certCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_UInt32 numCert = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ certDir,
+ 0,
+ &dirString,
+ plContext));
+
+ subTest("PKIX_PL_CollectionCertStore_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString,
+ &certStore,
+ plContext));
+
+ subTest("PKIX_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(testCertSelectorMatchCallback,
+ NULL,
+ &certSelector,
+ plContext));
+
+ subTest("PKIX_CertStore_GetCertCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &certCallback, NULL));
+
+ subTest("Getting data from Cert Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(certCallback(certStore,
+ certSelector,
+ &nbioContext,
+ &certList,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList,
+ &numCert,
+ plContext));
+
+ if (numCert != PKIX_TEST_COLLECTIONCERTSTORE_NUM_CERTS) {
+ pkixTestErrorMsg = "unexpected Cert number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(certList);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(char *pName)
+{
+ printf("\nUSAGE: %s test-purpose <data-dir> <platform-dir>\n\n", pName);
+}
+
+/* Functional tests for CollectionCertStore public functions */
+
+int
+test_colcertstore(int argc, char *argv[])
+{
+
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ char *platformDir = NULL;
+ char *dataDir = NULL;
+ char *combinedDir = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("CollectionCertStore");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < (3 + j)) {
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ dataDir = argv[2 + j];
+ platformDir = argv[3 + j];
+ combinedDir = catDirName(platformDir, dataDir, plContext);
+
+ testGetCRL(combinedDir);
+ testGetCert(combinedDir);
+
+cleanup:
+
+ pkixTestErrorResult = PKIX_PL_Free(combinedDir, plContext);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CollectionCertStore");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/module/test_ekuchecker.c b/security/nss/cmd/libpkix/pkix_pl/module/test_ekuchecker.c
new file mode 100644
index 000000000..ccd05a5bf
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/test_ekuchecker.c
@@ -0,0 +1,275 @@
+/* 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/. */
+/*
+ * test_ekuchecker.c
+ *
+ * Test Extend Key Usage Checker
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TEST_MAX_CERTS 10
+
+static void *plContext = NULL;
+
+static void
+printUsage1(char *pName)
+{
+ printf("\nUSAGE: %s test-purpose [ENE|EE] ", pName);
+ printf("[E]oid[,oid]* <data-dir> cert [certs].\n");
+}
+
+static void
+printUsageMax(PKIX_UInt32 numCerts)
+{
+ printf("\nUSAGE ERROR: number of certs %d exceed maximum %d\n",
+ numCerts, PKIX_TEST_MAX_CERTS);
+}
+
+static PKIX_Error *
+testCertSelectorMatchCallback(
+ PKIX_CertSelector *selector,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ *pResult = PKIX_TRUE;
+
+ return (0);
+}
+
+static PKIX_Error *
+testEkuSetup(
+ PKIX_ValidateParams *valParams,
+ char *ekuOidString,
+ PKIX_Boolean *only4EE)
+{
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_List *ekuList = NULL;
+ PKIX_PL_OID *ekuOid = NULL;
+ PKIX_ComCertSelParams *selParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_Boolean last_token = PKIX_FALSE;
+ PKIX_UInt32 i, tokeni;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ValidateParams_GetProcessingParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams(valParams, &procParams, plContext));
+
+ /* Get extended key usage OID(s) from command line, separated by "," */
+
+ if (ekuOidString[0] == '"') {
+ /* erase doble quotes, if any */
+ i = 1;
+ while (ekuOidString[i] != '"' && ekuOidString[i] != '\0') {
+ ekuOidString[i - 1] = ekuOidString[i];
+ i++;
+ }
+ ekuOidString[i - 1] = '\0';
+ }
+
+ if (ekuOidString[0] == '\0') {
+ ekuList = NULL;
+ } else {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&ekuList, plContext));
+
+ /* if OID string start with E, only check for last cert */
+ if (ekuOidString[0] == 'E') {
+ *only4EE = PKIX_TRUE;
+ tokeni = 2;
+ i = 1;
+ } else {
+ *only4EE = PKIX_FALSE;
+ tokeni = 1;
+ i = 0;
+ }
+
+ while (last_token != PKIX_TRUE) {
+ while (ekuOidString[tokeni] != ',' &&
+ ekuOidString[tokeni] != '\0') {
+ tokeni++;
+ }
+ if (ekuOidString[tokeni] == '\0') {
+ last_token = PKIX_TRUE;
+ } else {
+ ekuOidString[tokeni] = '\0';
+ tokeni++;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(&ekuOidString[i], &ekuOid, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(ekuList, (PKIX_PL_Object *)ekuOid, plContext));
+
+ PKIX_TEST_DECREF_BC(ekuOid);
+ i = tokeni;
+ }
+ }
+
+ /* Set extended key usage link to processing params */
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&selParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetExtendedKeyUsage");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetExtendedKeyUsage(selParams, ekuList, plContext));
+
+ subTest("PKIX_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(testCertSelectorMatchCallback,
+ NULL,
+ &certSelector,
+ plContext));
+
+ subTest("PKIX_CertSelector_SetCommonCertSelectorParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, selParams, plContext));
+
+ subTest("PKIX_ProcessingParams_SetTargetCertConstraints");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(ekuOid);
+ PKIX_TEST_DECREF_AC(ekuList);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+static PKIX_Error *
+testEkuChecker(
+ PKIX_ValidateParams *valParams,
+ PKIX_Boolean only4EE)
+{
+ PKIX_ProcessingParams *procParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams(valParams, &procParams, plContext));
+
+ subTest("PKIX_ProcessingParams_SetRevocationEnabled - disable");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_FALSE, plContext));
+
+ if (only4EE == PKIX_FALSE) {
+ subTest("PKIX_PL_EkuChecker_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_EkuChecker_Create(procParams, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(procParams);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+int
+test_ekuchecker(int argc, char *argv[])
+{
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ char *certNames[PKIX_TEST_MAX_CERTS];
+ char *dirName = NULL;
+ PKIX_PL_Cert *certs[PKIX_TEST_MAX_CERTS];
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean testValid = PKIX_FALSE;
+ PKIX_Boolean only4EE = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ startTests("EKU Checker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2 + j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2 + j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ dirName = argv[4 + j];
+
+ chainLength = (argc - j) - 6;
+ if (chainLength > PKIX_TEST_MAX_CERTS) {
+ printUsageMax(chainLength);
+ }
+
+ for (i = 0; i < chainLength; i++) {
+
+ certNames[i] = argv[6 + i + j];
+ certs[i] = NULL;
+ }
+
+ subTest(argv[1 + j]);
+
+ subTest("Extended-Key-Usage-Checker");
+
+ subTest("Extended-Key-Usage-Checker - Create Cert Chain");
+
+ chain = createCertChainPlus(dirName, certNames, certs, chainLength, plContext);
+
+ subTest("Extended-Key-Usage-Checker - Create Params");
+
+ valParams = createValidateParams(dirName,
+ argv[5 +
+ j],
+ NULL,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ subTest("Default CertStore");
+
+ testEkuSetup(valParams, argv[3 + j], &only4EE);
+
+ testEkuChecker(valParams, only4EE);
+
+ subTest("Extended-Key-Usage-Checker - Validate Chain");
+
+ if (testValid == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, NULL, plContext));
+ } else {
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain(valParams, &valResult, NULL, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("EKU Checker");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/module/test_httpcertstore.c b/security/nss/cmd/libpkix/pkix_pl/module/test_httpcertstore.c
new file mode 100644
index 000000000..62f86300a
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/test_httpcertstore.c
@@ -0,0 +1,300 @@
+/*
+ * test_httpcertstore.c
+ *
+ * Test Httpcertstore Type
+ *
+ * Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistribution of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
+ * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+ * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
+ * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
+ * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
+ * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
+ * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
+ * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
+ * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use in
+ * the design, construction, operation or maintenance of any nuclear facility.
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+#include "pkix_pl_common.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(char *testname)
+{
+ char *fmt =
+ "USAGE: %s [-arenas] certDir certName\n";
+ printf(fmt, "test_httpcertstore");
+}
+
+/* Functional tests for Socket public functions */
+static void
+do_other_work(void)
+{ /* while waiting for nonblocking I/O to complete */
+ (void)PR_Sleep(2 * 60);
+}
+
+PKIX_Error *
+PKIX_PL_HttpCertStore_Create(
+ PKIX_PL_HttpClient *client, /* if NULL, use default Client */
+ PKIX_PL_GeneralName *location,
+ PKIX_CertStore **pCertStore,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_HttpCertStore_CreateWithAsciiName(
+ PKIX_PL_HttpClient *client, /* if NULL, use default Client */
+ char *location,
+ PKIX_CertStore **pCertStore,
+ void *plContext);
+
+static PKIX_Error *
+getLocation(
+ PKIX_PL_Cert *certWithAia,
+ PKIX_PL_GeneralName **pLocation,
+ void *plContext)
+{
+ PKIX_List *aiaList = NULL;
+ PKIX_UInt32 size = 0;
+ PKIX_PL_InfoAccess *aia = NULL;
+ PKIX_UInt32 iaType = PKIX_INFOACCESS_LOCATION_UNKNOWN;
+ PKIX_PL_GeneralName *location = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Getting Authority Info Access");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetAuthorityInfoAccess(certWithAia, &aiaList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(aiaList, &size, plContext));
+
+ if (size != 1) {
+ pkixTestErrorMsg = "unexpected number of AIA";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(aiaList, 0, (PKIX_PL_Object **)&aia, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_InfoAccess_GetLocationType(aia, &iaType, plContext));
+
+ if (iaType != PKIX_INFOACCESS_LOCATION_HTTP) {
+ pkixTestErrorMsg = "unexpected location type in AIA";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_InfoAccess_GetLocation(aia, &location, plContext));
+
+ *pLocation = location;
+
+cleanup:
+ PKIX_TEST_DECREF_AC(aiaList);
+ PKIX_TEST_DECREF_AC(aia);
+
+ PKIX_TEST_RETURN();
+
+ return (NULL);
+}
+
+int
+test_httpcertstore(int argc, char *argv[])
+{
+
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 numCrls = 0;
+ int j = 0;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 length = 0;
+
+ char *certName = NULL;
+ char *certDir = NULL;
+ PKIX_PL_Cert *cmdLineCert = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertStore *crlStore = NULL;
+ PKIX_PL_GeneralName *location = NULL;
+ PKIX_CertStore_CertCallback getCerts = NULL;
+ PKIX_List *certs = NULL;
+ char *asciiResult = NULL;
+ void *nbio = NULL;
+
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+ char *crlLocation = "http://betty.nist.gov/pathdiscoverytestsuite/CRL"
+ "files/BasicHTTPURIPeer2CACRL.crl";
+ PKIX_CertStore_CRLCallback getCrls = NULL;
+ PKIX_List *crls = NULL;
+ PKIX_PL_String *crlString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("HttpCertStore");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc != (j + 3)) {
+ printUsage(argv[0]);
+ pkixTestErrorMsg = "Missing command line argument.";
+ goto cleanup;
+ }
+
+ certDir = argv[++j];
+ certName = argv[++j];
+
+ cmdLineCert = createCert(certDir, certName, plContext);
+ if (cmdLineCert == NULL) {
+ pkixTestErrorMsg = "Unable to create Cert";
+ goto cleanup;
+ }
+
+ /* muster arguments to create HttpCertStore */
+ PKIX_TEST_EXPECT_NO_ERROR(getLocation(cmdLineCert, &location, plContext));
+
+ if (location == NULL) {
+ pkixTestErrorMsg = "Give me a cert with an HTTP URI!";
+ goto cleanup;
+ }
+
+ /* create HttpCertStore */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HttpCertStore_Create(NULL, location, &certStore, plContext));
+
+ /* get the GetCerts callback */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &getCerts, plContext));
+
+ /* create a CertSelector */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ /* Get the certs */
+ PKIX_TEST_EXPECT_NO_ERROR(getCerts(certStore, certSelector, &nbio, &certs, plContext));
+
+ while (nbio != NULL) {
+ /* poll for a completion */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_CertContinue(certStore, certSelector, &nbio, &certs, plContext));
+ }
+
+ if (certs) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ if (numCerts == 0) {
+ printf("HttpCertStore returned an empty Cert list\n");
+ goto cleanup;
+ }
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs,
+ i,
+ (PKIX_PL_Object **)&cert,
+ plContext));
+
+ asciiResult = PKIX_Cert2ASCII(cert);
+
+ printf("CERT[%d]:\n%s\n", i, asciiResult);
+
+ /* PKIX_Cert2ASCII used PKIX_PL_Malloc(...,,NULL) */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, NULL));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+ } else {
+ printf("HttpCertStore returned a NULL Cert list\n");
+ }
+
+ /* create HttpCertStore */
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_HttpCertStore_CreateWithAsciiName(NULL, crlLocation, &crlStore, plContext));
+
+ /* get the GetCrls callback */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCRLCallback(crlStore, &getCrls, plContext));
+
+ /* create a CrlSelector */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_Create(NULL, NULL, &crlSelector, plContext));
+
+ /* Get the crls */
+ PKIX_TEST_EXPECT_NO_ERROR(getCrls(crlStore, crlSelector, &nbio, &crls, plContext));
+
+ while (nbio != NULL) {
+ /* poll for a completion */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_CrlContinue(crlStore, crlSelector, &nbio, &crls, plContext));
+ }
+
+ if (crls) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(crls, &numCrls, plContext));
+
+ if (numCrls == 0) {
+ printf("HttpCertStore returned an empty CRL list\n");
+ goto cleanup;
+ }
+
+ for (i = 0; i < numCrls; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(crls,
+ i,
+ (PKIX_PL_Object **)&crl,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString(
+ (PKIX_PL_Object *)crl,
+ &crlString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(crlString,
+ PKIX_ESCASCII,
+ (void **)&asciiResult,
+ &length,
+ plContext));
+
+ printf("CRL[%d]:\n%s\n", i, asciiResult);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, plContext));
+ PKIX_TEST_DECREF_BC(crlString);
+ PKIX_TEST_DECREF_BC(crl);
+ }
+ } else {
+ printf("HttpCertStore returned a NULL CRL list\n");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(cmdLineCert);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(crlStore);
+ PKIX_TEST_DECREF_AC(location);
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(crl);
+ PKIX_TEST_DECREF_AC(crlString);
+ PKIX_TEST_DECREF_AC(crls);
+
+ PKIX_TEST_RETURN();
+
+ endTests("HttpDefaultClient");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/module/test_pk11certstore.c b/security/nss/cmd/libpkix/pkix_pl/module/test_pk11certstore.c
new file mode 100644
index 000000000..58fceb14f
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/test_pk11certstore.c
@@ -0,0 +1,580 @@
+/* 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/. */
+/*
+ * test_pk11certstore.c
+ *
+ * Test Pk11CertStore Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+/*
+ * This function creates a certSelector with ComCertSelParams set up to
+ * select entries whose Subject Name matches that in the given Cert and
+ * whose validity window includes the Date specified by "validityDate".
+ */
+static void
+test_makeSubjectCertSelector(
+ PKIX_PL_Cert *certNameToMatch,
+ PKIX_PL_Date *validityDate,
+ PKIX_CertSelector **pSelector,
+ void *plContext)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *subjParams = NULL;
+ PKIX_PL_X500Name *subjectName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&subjParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(certNameToMatch, &subjectName, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubject(subjParams, subjectName, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificateValid(subjParams, validityDate, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, subjParams, plContext));
+ *pSelector = selector;
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(subjParams);
+ PKIX_TEST_DECREF_AC(subjectName);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function creates a certSelector with ComCertSelParams set up to
+ * select entries containing a Basic Constraints extension with a path
+ * length of at least the specified "minPathLength".
+ */
+static void
+test_makePathCertSelector(
+ PKIX_Int32 minPathLength,
+ PKIX_CertSelector **pSelector,
+ void *plContext)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *pathParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&pathParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints(pathParams, minPathLength, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, pathParams, plContext));
+ *pSelector = selector;
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(pathParams);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function reads a directory-file cert specified by "desiredSubjectCert",
+ * and decodes the SubjectName. It uses that name to set up the CertSelector
+ * for a Subject Name match, and then queries the database for matching entries.
+ * It is intended to test a "smart" database query.
+ */
+static void
+testMatchCertSubject(
+ char *crlDir,
+ char *desiredSubjectCert,
+ char *expectedAscii,
+ PKIX_PL_Date *validityDate,
+ void *plContext)
+{
+ PKIX_UInt32 numCert = 0;
+ PKIX_PL_Cert *certWithDesiredSubject = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_CertStore_CertCallback getCert = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certWithDesiredSubject = createCert(crlDir, desiredSubjectCert, plContext);
+
+ test_makeSubjectCertSelector(certWithDesiredSubject,
+ validityDate,
+ &certSelector,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Pk11CertStore_Create(&certStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &getCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(getCert(certStore,
+ certSelector,
+ &nbioContext,
+ &certList,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList, &numCert, plContext));
+
+ if (numCert > 0) {
+ /* List should be immutable */
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_DeleteItem(certList, 0, plContext));
+ }
+
+ if (expectedAscii) {
+ testToStringHelper((PKIX_PL_Object *)certList, expectedAscii, plContext);
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(certWithDesiredSubject);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certList);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function uses the minimum path length specified by "minPath" to set up
+ * a CertSelector for a BasicConstraints match, and then queries the database
+ * for matching entries. It is intended to test the case where there
+ * is no "smart" database query, so the database will be asked for all
+ * available certs and the filtering will be done by the interaction of the
+ * certstore and the selector.
+ */
+static void
+testMatchCertMinPath(
+ PKIX_Int32 minPath,
+ char *expectedAscii,
+ void *plContext)
+{
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_CertStore_CertCallback getCert = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Searching Certs for minPath");
+
+ test_makePathCertSelector(minPath, &certSelector, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Pk11CertStore_Create(&certStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &getCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(getCert(certStore,
+ certSelector,
+ &nbioContext,
+ &certList,
+ plContext));
+
+ if (expectedAscii) {
+ testToStringHelper((PKIX_PL_Object *)certList, expectedAscii, plContext);
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certList);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function creates a crlSelector with ComCrlSelParams set up to
+ * select entries whose Issuer Name matches that in the given Crl.
+ */
+static void
+test_makeIssuerCRLSelector(
+ PKIX_PL_CRL *crlNameToMatch,
+ PKIX_CRLSelector **pSelector,
+ void *plContext)
+{
+ PKIX_CRLSelector *selector = NULL;
+ PKIX_ComCRLSelParams *issuerParams = NULL;
+ PKIX_PL_X500Name *issuerName = NULL;
+ PKIX_List *names = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_Create(&issuerParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_GetIssuer(crlNameToMatch, &issuerName, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&names, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(names, (PKIX_PL_Object *)issuerName, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetIssuerNames(issuerParams, names, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_SetCommonCRLSelectorParams(selector, issuerParams, plContext));
+ *pSelector = selector;
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(issuerParams);
+ PKIX_TEST_DECREF_AC(issuerName);
+ PKIX_TEST_DECREF_AC(names);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function creates a crlSelector with ComCrlSelParams set up to
+ * select entries that would be valid at the Date specified by the Date
+ * criterion.
+ */
+static void
+test_makeDateCRLSelector(
+ PKIX_PL_Date *dateToMatch,
+ PKIX_CRLSelector **pSelector,
+ void *plContext)
+{
+ PKIX_CRLSelector *selector = NULL;
+ PKIX_ComCRLSelParams *dateParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_Create(&dateParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetDateAndTime(dateParams, dateToMatch, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_SetCommonCRLSelectorParams(selector, dateParams, plContext));
+ *pSelector = selector;
+
+cleanup:
+ PKIX_TEST_DECREF_AC(dateParams);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function reads a directory-file crl specified by "desiredIssuerCrl",
+ * and decodes the IssuerName. It uses that name to set up the CrlSelector
+ * for a Issuer Name match, and then queries the database for matching entries.
+ * It is intended to test the case of a "smart" database query.
+ */
+static void
+testMatchCrlIssuer(
+ char *crlDir,
+ char *desiredIssuerCrl,
+ char *expectedAscii,
+ void *plContext)
+{
+ PKIX_UInt32 numCrl = 0;
+ PKIX_PL_CRL *crlWithDesiredIssuer = NULL;
+ PKIX_CertStore *crlStore = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+ PKIX_List *crlList = NULL;
+ PKIX_CertStore_CRLCallback getCrl = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Searching CRLs for matching Issuer");
+
+ crlWithDesiredIssuer = createCRL(crlDir, desiredIssuerCrl, plContext);
+
+ test_makeIssuerCRLSelector(crlWithDesiredIssuer, &crlSelector, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Pk11CertStore_Create(&crlStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCRLCallback(crlStore, &getCrl, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(getCrl(crlStore,
+ crlSelector,
+ &nbioContext,
+ &crlList,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(crlList, &numCrl, plContext));
+
+ if (numCrl > 0) {
+ /* List should be immutable */
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_DeleteItem(crlList, 0, plContext));
+ }
+
+ if (expectedAscii) {
+ testToStringHelper((PKIX_PL_Object *)crlList, expectedAscii, plContext);
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(crlWithDesiredIssuer);
+ PKIX_TEST_DECREF_AC(crlStore);
+ PKIX_TEST_DECREF_AC(crlSelector);
+ PKIX_TEST_DECREF_AC(crlList);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function uses the date specified by "matchDate" to set up the
+ * CrlSelector for a Date match. It is intended to test the case where there
+ * is no "smart" database query, so the CertStore should throw an error
+ * rather than ask the database for all available CRLs and then filter the
+ * results using the selector.
+ */
+static void
+testMatchCrlDate(
+ char *dateMatch,
+ char *expectedAscii,
+ void *plContext)
+{
+ PKIX_PL_Date *dateCriterion = NULL;
+ PKIX_CertStore *crlStore = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+ PKIX_List *crlList = NULL;
+ PKIX_CertStore_CRLCallback getCrl = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Searching CRLs for matching Date");
+
+ dateCriterion = createDate(dateMatch, plContext);
+ test_makeDateCRLSelector(dateCriterion, &crlSelector, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Pk11CertStore_Create(&crlStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCRLCallback(crlStore, &getCrl, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(getCrl(crlStore, crlSelector, NULL, &crlList, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dateCriterion);
+ PKIX_TEST_DECREF_AC(crlStore);
+ PKIX_TEST_DECREF_AC(crlSelector);
+ PKIX_TEST_DECREF_AC(crlList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(char *pName)
+{
+ printf("\nUSAGE: %s <-d data-dir> <database-dir>\n\n", pName);
+}
+
+/* Functional tests for Pk11CertStore public functions */
+
+int
+test_pk11certstore(int argc, char *argv[])
+{
+
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_PL_Date *validityDate = NULL;
+ PKIX_PL_Date *betweenDate = NULL;
+ char *crlDir = NULL;
+ char *expectedProfAscii = "([\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 00ca\n"
+ "\tIssuer: CN=chemistry,O=mit,C=us\n"
+ "\tSubject: CN=prof noall,O=mit,C=us\n"
+ "\tValidity: [From: Fri Feb 11 14:14:06 2005\n"
+ "\t To: Mon Jan 18, 2105]\n"
+ "\tSubjectAltNames: (null)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (2.5.29.15, 2.5.29.19)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: CA(6)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "]\n"
+ ", [\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 03\n"
+ "\tIssuer: CN=physics,O=mit,C=us\n"
+ "\tSubject: CN=prof noall,O=mit,C=us\n"
+ "\tValidity: [From: Fri Feb 11 12:52:26 2005\n"
+ "\t To: Mon Jan 18, 2105]\n"
+ "\tSubjectAltNames: (null)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (2.5.29.15, 2.5.29.19)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: CA(0)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "]\n"
+ ")";
+ char *expectedValidityAscii = "([\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 03\n"
+ "\tIssuer: CN=physics,O=mit,C=us\n"
+ "\tSubject: CN=prof noall,O=mit,C=us\n"
+ "\tValidity: [From: Fri Feb 11 12:52:26 2005\n"
+ "\t To: Mon Jan 18, 2105]\n"
+ "\tSubjectAltNames: (null)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (2.5.29.15, 2.5.29.19)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: CA(0)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "]\n"
+ ")";
+ char *expectedMinPathAscii = "([\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 01\n"
+ "\tIssuer: CN=science,O=mit,C=us\n"
+ "\tSubject: CN=science,O=mit,C=us\n"
+ "\tValidity: [From: Fri Feb 11 12:47:58 2005\n"
+ "\t To: Mon Jan 18, 2105]\n"
+ "\tSubjectAltNames: (null)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (2.5.29.15, 2.5.29.19)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: CA(10)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "]\n"
+ ")";
+ char *expectedIssuerAscii = "([\n"
+ "\tVersion: v2\n"
+ "\tIssuer: CN=physics,O=mit,C=us\n"
+ "\tUpdate: [Last: Fri Feb 11 13:51:38 2005\n"
+ "\t Next: Mon Jan 18, 2105]\n"
+ "\tSignatureAlgId: 1.2.840.10040.4.3\n"
+ "\tCRL Number : (null)\n"
+ "\n"
+ "\tEntry List: (\n"
+ "\t[\n"
+ "\tSerialNumber: 67\n"
+ "\tReasonCode: 257\n"
+ "\tRevocationDate: Fri Feb 11 13:51:38 2005\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\t]\n"
+ "\t)\n"
+ "\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "]\n"
+ ")";
+ char *expectedDateAscii = "([\n"
+ "\tVersion: v2\n"
+ "\tIssuer: CN=science,O=mit,C=us\n"
+ "\tUpdate: [Last: Fri Feb 11 13:34:40 2005\n"
+ "\t Next: Mon Jan 18, 2105]\n"
+ "\tSignatureAlgId: 1.2.840.10040.4.3\n"
+ "\tCRL Number : (null)\n"
+ "\n"
+ "\tEntry List: (\n"
+ "\t[\n"
+ "\tSerialNumber: 65\n"
+ "\tReasonCode: 260\n"
+ "\tRevocationDate: Fri Feb 11 13:34:40 2005\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\t]\n"
+ "\t)\n"
+ "\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "]\n"
+ ", [\n"
+ "\tVersion: v2\n"
+ "\tIssuer: CN=testing CRL,O=test,C=us\n"
+ "\tUpdate: [Last: Fri Feb 11 13:14:38 2005\n"
+ "\t Next: Mon Jan 18, 2105]\n"
+ "\tSignatureAlgId: 1.2.840.10040.4.3\n"
+ "\tCRL Number : (null)\n"
+ "\n"
+ "\tEntry List: (\n"
+ "\t[\n"
+ "\tSerialNumber: 67\n"
+ "\tReasonCode: 258\n"
+ "\tRevocationDate: Fri Feb 11 13:14:38 2005\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\t]\n"
+ "\t)\n"
+ "\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "]\n"
+ ")";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Pk11CertStore");
+
+ if (argc < 3) {
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ crlDir = argv[j + 2];
+
+ /* Two certs for prof should be valid now */
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Date_CreateFromPRTime(PR_Now(), &validityDate, plContext));
+
+ subTest("Searching Certs for Subject");
+
+ testMatchCertSubject(crlDir,
+ "phy2prof.crt",
+ NULL, /* expectedProfAscii, */
+ validityDate,
+ plContext);
+
+ /* One of the certs was not yet valid at this time. */
+ betweenDate = createDate("050210184000Z", plContext);
+
+ subTest("Searching Certs for Subject and Validity");
+
+ testMatchCertSubject(crlDir,
+ "phy2prof.crt",
+ NULL, /* expectedValidityAscii, */
+ betweenDate,
+ plContext);
+
+ testMatchCertMinPath(9,
+ NULL, /* expectedMinPathAscii, */
+ plContext);
+
+ testMatchCrlIssuer(crlDir,
+ "phys.crl",
+ NULL, /* expectedIssuerAscii, */
+ plContext);
+
+ testMatchCrlDate("050211184000Z",
+ NULL, /* expectedDateAscii, */
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(validityDate);
+ PKIX_TEST_DECREF_AC(betweenDate);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Pk11CertStore");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/module/test_socket.c b/security/nss/cmd/libpkix/pkix_pl/module/test_socket.c
new file mode 100644
index 000000000..89400256d
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/test_socket.c
@@ -0,0 +1,571 @@
+/*
+ * test_socket.c
+ *
+ * Test Socket Type
+ *
+ * Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistribution of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
+ * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+ * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
+ * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
+ * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
+ * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
+ * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
+ * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
+ * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use in
+ * the design, construction, operation or maintenance of any nuclear facility.
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+#include "pkix_pl_common.h"
+
+#define LDAP_PORT 389
+
+static void *plContext = NULL;
+
+typedef enum {
+ SERVER_LISTENING,
+ SERVER_RECV1,
+ SERVER_POLL1,
+ SERVER_SEND2,
+ SERVER_POLL2,
+ SERVER_RECV3,
+ SERVER_POLL3,
+ SERVER_SEND4,
+ SERVER_POLL4,
+ SERVER_DONE,
+ SERVER_FAILED
+} SERVER_STATE;
+
+typedef enum {
+ CLIENT_WAITFORCONNECT,
+ CLIENT_SEND1,
+ CLIENT_POLL1,
+ CLIENT_RECV2,
+ CLIENT_POLL2,
+ CLIENT_SEND3,
+ CLIENT_POLL3,
+ CLIENT_RECV4,
+ CLIENT_POLL4,
+ CLIENT_DONE,
+ CLIENT_FAILED
+} CLIENT_STATE;
+
+SERVER_STATE serverState;
+CLIENT_STATE clientState;
+PKIX_PL_Socket *sSock = NULL;
+PKIX_PL_Socket *cSock = NULL;
+PKIX_PL_Socket *rendezvousSock = NULL;
+PKIX_PL_Socket_Callback *sCallbackList;
+PKIX_PL_Socket_Callback *cCallbackList;
+PKIX_PL_Socket_Callback *rvCallbackList;
+PRNetAddr serverNetAddr;
+PRNetAddr clientNetAddr;
+PRIntn backlog = 0;
+PRIntervalTime timeout = 0;
+char *sendBuf1 = "Hello, world!";
+char *sendBuf2 = "Ack";
+char *sendBuf3 = "What do you mean, \"Ack\"?";
+char *sendBuf4 = "What do you mean, \"What do you mean, \'Ack\'?\"?";
+char rcvBuf1[100];
+char rcvBuf2[100];
+
+static void
+printUsage(char *testname)
+{
+ char *fmt = "USAGE: %s [-arenas] server:port\n";
+ printf(fmt, testname);
+}
+
+/* Functional tests for Socket public functions */
+static void
+do_other_work(void)
+{ /* while waiting for nonblocking I/O to complete */
+ (void)PR_Sleep(2 * 60);
+}
+
+static PKIX_Boolean
+server()
+{
+ PKIX_Int32 bytesRead = 0;
+ PKIX_Int32 bytesWritten = 0;
+ PKIX_Boolean keepGoing = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ switch (serverState) {
+ case SERVER_LISTENING:
+ subTest("SERVER_LISTENING");
+ PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->acceptCallback(sSock, &rendezvousSock, plContext));
+ if (rendezvousSock) {
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(rendezvousSock, &rvCallbackList, plContext));
+
+ serverState = SERVER_RECV1;
+ }
+ break;
+ case SERVER_RECV1:
+ subTest("SERVER_RECV1");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->recvCallback(rendezvousSock,
+ rcvBuf1,
+ sizeof(rcvBuf1),
+ &bytesRead,
+ plContext));
+
+ if (bytesRead > 0) {
+ /* confirm that rcvBuf1 = sendBuf1 */
+ if ((bytesRead != (PRInt32)PL_strlen(sendBuf1) + 1) ||
+ (strncmp(sendBuf1, rcvBuf1, bytesRead) != 0)) {
+ testError("Receive buffer mismatch\n");
+ }
+
+ serverState = SERVER_SEND2;
+ keepGoing = PKIX_TRUE;
+ } else {
+ serverState = SERVER_POLL1;
+ }
+ break;
+ case SERVER_POLL1:
+ subTest("SERVER_POLL1");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, NULL, &bytesRead, plContext));
+
+ if (bytesRead > 0) {
+ /* confirm that rcvBuf1 = sendBuf1 */
+ if ((bytesRead != (PRInt32)PL_strlen(sendBuf1) + 1) ||
+ (strncmp(sendBuf1, rcvBuf1, bytesRead) != 0)) {
+ testError("Receive buffer mismatch\n");
+ }
+
+ serverState = SERVER_SEND2;
+ keepGoing = PKIX_TRUE;
+ }
+ break;
+ case SERVER_SEND2:
+ subTest("SERVER_SEND2");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->sendCallback(rendezvousSock,
+ sendBuf2,
+ strlen(sendBuf2) +
+ 1,
+ &bytesWritten,
+ plContext));
+ if (bytesWritten > 0) {
+ serverState = SERVER_RECV3;
+ } else {
+ serverState = SERVER_POLL2;
+ }
+ break;
+ case SERVER_POLL2:
+ subTest("SERVER_POLL2");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, &bytesWritten, NULL, plContext));
+ if (bytesWritten > 0) {
+ serverState = SERVER_RECV3;
+ }
+ break;
+ case SERVER_RECV3:
+ subTest("SERVER_RECV3");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->recvCallback(rendezvousSock,
+ rcvBuf1,
+ sizeof(rcvBuf1),
+ &bytesRead,
+ plContext));
+
+ if (bytesRead > 0) {
+ serverState = SERVER_SEND4;
+ keepGoing = PKIX_TRUE;
+ } else {
+ serverState = SERVER_POLL3;
+ }
+ break;
+ case SERVER_POLL3:
+ subTest("SERVER_POLL3");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, NULL, &bytesRead, plContext));
+ if (bytesRead > 0) {
+ serverState = SERVER_SEND4;
+ keepGoing = PKIX_TRUE;
+ }
+ break;
+ case SERVER_SEND4:
+ subTest("SERVER_SEND4");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->sendCallback(rendezvousSock,
+ sendBuf4,
+ strlen(sendBuf4) +
+ 1,
+ &bytesWritten,
+ plContext));
+
+ if (bytesWritten > 0) {
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->shutdownCallback(rendezvousSock, plContext));
+ PKIX_TEST_DECREF_BC(sSock);
+ PKIX_TEST_DECREF_BC(rendezvousSock);
+ serverState = SERVER_DONE;
+ } else {
+ serverState = SERVER_POLL4;
+ }
+ break;
+ case SERVER_POLL4:
+ subTest("SERVER_POLL4");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, &bytesWritten, NULL, plContext));
+ if (bytesWritten > 0) {
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->shutdownCallback(rendezvousSock, plContext));
+ PKIX_TEST_DECREF_BC(sSock);
+ PKIX_TEST_DECREF_BC(rendezvousSock);
+ serverState = SERVER_DONE;
+ }
+ break;
+ case SERVER_DONE:
+ default:
+ subTest("SERVER_DONE");
+ break;
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (keepGoing);
+}
+
+static PKIX_Boolean
+client()
+{
+ PKIX_Boolean keepGoing = PKIX_FALSE;
+ PKIX_Int32 bytesRead = 0;
+ PKIX_Int32 bytesWritten = 0;
+ PRErrorCode cStat = 0;
+
+ /* At 2 seconds each cycle, this should suffice! */
+ PKIX_UInt32 giveUpCount = 10;
+
+ PKIX_TEST_STD_VARS();
+
+ switch (clientState) {
+ case CLIENT_WAITFORCONNECT:
+ subTest("CLIENT_WAITFORCONNECT");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->connectcontinueCallback(cSock, &cStat, plContext));
+ if (cStat == 0) {
+ clientState = CLIENT_SEND1;
+ keepGoing = PKIX_TRUE;
+ } else {
+ clientState = CLIENT_WAITFORCONNECT;
+ if (--giveUpCount == 0) {
+ testError("Client unable to connect");
+ }
+ }
+ break;
+ case CLIENT_SEND1:
+ subTest("CLIENT_SEND1");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->sendCallback(cSock,
+ sendBuf1,
+ strlen(sendBuf1) +
+ 1,
+ &bytesWritten,
+ plContext));
+ if (bytesWritten > 0) {
+ clientState = CLIENT_RECV2;
+ } else {
+ clientState = CLIENT_POLL1;
+ }
+ break;
+ case CLIENT_POLL1:
+ subTest("CLIENT_POLL1");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, &bytesWritten, NULL, plContext));
+ if (bytesWritten > 0) {
+ clientState = CLIENT_RECV2;
+ } else {
+ clientState = CLIENT_POLL1;
+ }
+ break;
+ case CLIENT_RECV2:
+ subTest("CLIENT_RECV2");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->recvCallback(cSock,
+ rcvBuf2,
+ sizeof(rcvBuf2),
+ &bytesRead,
+ plContext));
+
+ if (bytesRead > 0) {
+ /* confirm that rcvBuf2 = sendBuf2 */
+ if ((bytesRead != (PRInt32)PL_strlen(sendBuf2) + 1) ||
+ (strncmp(sendBuf2, rcvBuf2, bytesRead) != 0)) {
+ testError("Receive buffer mismatch\n");
+ }
+ clientState = CLIENT_SEND3;
+ keepGoing = PKIX_TRUE;
+ } else {
+ clientState = CLIENT_POLL2;
+ }
+ break;
+ case CLIENT_POLL2:
+ subTest("CLIENT_POLL2");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, NULL, &bytesRead, plContext));
+ if (bytesRead > 0) {
+ /* confirm that rcvBuf2 = sendBuf2 */
+ if ((bytesRead != (PRInt32)PL_strlen(sendBuf2) + 1) ||
+ (strncmp(sendBuf2, rcvBuf2, bytesRead) != 0)) {
+ testError("Receive buffer mismatch\n");
+ }
+ clientState = CLIENT_SEND3;
+ } else {
+ clientState = CLIENT_POLL2;
+ }
+ break;
+ case CLIENT_SEND3:
+ subTest("CLIENT_SEND3");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->sendCallback(cSock,
+ sendBuf3,
+ strlen(sendBuf3) +
+ 1,
+ &bytesWritten,
+ plContext));
+
+ if (bytesWritten > 0) {
+ clientState = CLIENT_RECV4;
+ } else {
+ clientState = CLIENT_POLL3;
+ }
+ break;
+ case CLIENT_POLL3:
+ subTest("CLIENT_POLL3");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, &bytesWritten, NULL, plContext));
+ if (bytesWritten > 0) {
+ clientState = CLIENT_RECV4;
+ } else {
+ clientState = CLIENT_POLL3;
+ }
+ break;
+ case CLIENT_RECV4:
+ subTest("CLIENT_RECV4");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->recvCallback(cSock,
+ rcvBuf2,
+ sizeof(rcvBuf2),
+ &bytesRead,
+ plContext));
+
+ if (bytesRead > 0) {
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->shutdownCallback(cSock, plContext));
+ PKIX_TEST_DECREF_BC(cSock);
+ clientState = CLIENT_DONE;
+ } else {
+ clientState = CLIENT_POLL4;
+ }
+ break;
+ case CLIENT_POLL4:
+ subTest("CLIENT_POLL4");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, NULL, &bytesRead, plContext));
+ if (bytesRead > 0) {
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->shutdownCallback(cSock, plContext));
+ PKIX_TEST_DECREF_BC(cSock);
+ clientState = CLIENT_DONE;
+ } else {
+ clientState = CLIENT_POLL4;
+ }
+ break;
+ case CLIENT_DONE:
+ default:
+ subTest("CLIENT_DONE");
+ break;
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (keepGoing);
+}
+
+static void
+dispatcher()
+{
+ PKIX_Boolean keepGoing = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ do {
+ if (serverState < SERVER_DONE) {
+ do {
+ keepGoing = server();
+ } while (keepGoing == PKIX_TRUE);
+ }
+ if (clientState < CLIENT_DONE) {
+ do {
+ keepGoing = client();
+ } while (keepGoing == PKIX_TRUE);
+ }
+ do_other_work();
+
+ } while ((serverState < SERVER_DONE) || (clientState < CLIENT_DONE));
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_socket(int argc, char *argv[])
+{
+
+ int j = 0;
+ PKIX_UInt32 actualMinorVersion;
+ char buf[PR_NETDB_BUF_SIZE];
+ char *serverName = NULL;
+ char *sepPtr = NULL;
+ PRHostEnt hostent;
+ PRUint16 portNum = 0;
+ PRStatus prstatus = PR_FAILURE;
+ PRErrorCode cStat = 0;
+ void *ipaddr = NULL;
+ PKIX_Error *bindError = NULL;
+ PRIntn hostenum;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Socket");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc != (j + 2)) {
+ printUsage(argv[0]);
+ pkixTestErrorMsg = "Missing command line argument.";
+ goto cleanup;
+ }
+
+ serverName = argv[j + 1];
+
+ subTest("Using pkix_pl_Socket_CreateByName");
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_CreateByName(PKIX_TRUE, timeout, serverName, &cStat, &sSock, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(sSock, &sCallbackList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->listenCallback(sSock, backlog, plContext));
+
+ serverState = SERVER_LISTENING;
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_CreateByName(PKIX_FALSE, timeout, serverName, &cStat, &cSock, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(cSock, &cCallbackList, plContext));
+
+ if ((timeout == 0) && (cStat == PR_IN_PROGRESS_ERROR)) {
+ clientState = CLIENT_WAITFORCONNECT;
+ } else {
+ clientState = CLIENT_SEND1;
+ }
+
+ dispatcher();
+
+ subTest("Using pkix_pl_Socket_Create");
+
+ sepPtr = strchr(serverName, ':');
+ /* First strip off the portnum, if present, from the end of the name */
+ if (sepPtr) {
+ *sepPtr++ = '\0';
+ portNum = (PRUint16)atoi(sepPtr);
+ } else {
+ portNum = (PRUint16)LDAP_PORT;
+ }
+ /*
+ * The hostname may be a fully-qualified name. Just
+ * use the leftmost component in our lookup.
+ */
+ sepPtr = strchr(serverName, '.');
+ if (sepPtr) {
+ *sepPtr++ = '\0';
+ }
+ prstatus = PR_GetHostByName(serverName, buf, sizeof(buf), &hostent);
+
+ if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) {
+ printUsage(argv[0]);
+ pkixTestErrorMsg =
+ "PR_GetHostByName rejects command line argument.";
+ goto cleanup;
+ }
+
+ serverNetAddr.inet.family = PR_AF_INET;
+ serverNetAddr.inet.port = PR_htons(portNum);
+ serverNetAddr.inet.ip = PR_INADDR_ANY;
+
+ hostenum = PR_EnumerateHostEnt(0, &hostent, portNum, &clientNetAddr);
+ if (hostenum == -1) {
+ pkixTestErrorMsg =
+ "PR_EnumerateHostEnt failed.";
+ goto cleanup;
+ }
+
+ backlog = 5;
+
+ /* timeout = PR_INTERVAL_NO_TIMEOUT; */
+ /* timeout = 0; nonblocking */
+ timeout = 0;
+
+ bindError = pkix_pl_Socket_Create(PKIX_TRUE, timeout, &serverNetAddr, &cStat, &sSock, plContext);
+
+ /* If PR_Bind can't handle INADDR_ANY, try it with the real name */
+ if (bindError) {
+ PKIX_TEST_DECREF_BC(bindError);
+ serverNetAddr.inet.ip = PR_htonl(*(PRUint32 *)ipaddr);
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_Create(PKIX_TRUE,
+ timeout,
+ &serverNetAddr,
+ &cStat,
+ &sSock,
+ plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(sSock, &sCallbackList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->listenCallback(sSock, backlog, plContext));
+
+ serverState = SERVER_LISTENING;
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_Create(PKIX_FALSE, timeout, &clientNetAddr, &cStat, &cSock, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(cSock, &cCallbackList, plContext));
+
+ if ((timeout == 0) && (cStat == PR_IN_PROGRESS_ERROR)) {
+ clientState = CLIENT_WAITFORCONNECT;
+ } else {
+ clientState = CLIENT_SEND1;
+ }
+
+ dispatcher();
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(sSock);
+ PKIX_TEST_DECREF_AC(cSock);
+ PKIX_TEST_DECREF_AC(rendezvousSock);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Socket");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/Makefile b/security/nss/cmd/libpkix/pkix_pl/pki/Makefile
new file mode 100755
index 000000000..09ca5f1c6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/manifest.mn b/security/nss/cmd/libpkix/pkix_pl/pki/manifest.mn
new file mode 100755
index 000000000..7c6e0a76d
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/manifest.mn
@@ -0,0 +1,28 @@
+#
+# 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/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_cert.c \
+ test_crl.c \
+ test_crlentry.c \
+ test_date.c \
+ test_generalname.c \
+ test_nameconstraints.c \
+ test_x500name.c \
+ test_authorityinfoaccess.c \
+ test_subjectinfoaccess.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtoolpki
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_authorityinfoaccess.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_authorityinfoaccess.c
new file mode 100644
index 000000000..156b440f9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_authorityinfoaccess.c
@@ -0,0 +1,105 @@
+/* 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/. */
+/*
+ * test_authorityinfoaccess.c
+ *
+ * Test Authority InfoAccess Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+int
+test_authorityinfoaccess(int argc, char *argv[])
+{
+
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_Cert *certDiff = NULL;
+ PKIX_List *aiaList = NULL;
+ PKIX_List *siaList = NULL;
+ PKIX_PL_InfoAccess *aia = NULL;
+ PKIX_PL_InfoAccess *aiaDup = NULL;
+ PKIX_PL_InfoAccess *aiaDiff = NULL;
+ char *certPathName = NULL;
+ char *dirName = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 size, i;
+ PKIX_UInt32 j = 0;
+ char *expectedAscii = "[method:caIssuers, location:ldap:"
+ "//betty.nist.gov/cn=CA,ou=Basic%20LDAP%20URI%20OU1,"
+ "o=Test%20Certificates,c=US?cACertificate;binary,"
+ "crossCertificatePair;binary]";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("AuthorityInfoAccess");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 5 + j) {
+ printf("Usage: %s <test-purpose> <cert> <diff-cert>\n", argv[0]);
+ }
+
+ dirName = argv[2 + j];
+ certPathName = argv[3 + j];
+
+ subTest("Creating Cert with Authority Info Access");
+ cert = createCert(dirName, certPathName, plContext);
+
+ certPathName = argv[4 + j];
+
+ subTest("Creating Cert with Subject Info Access");
+ certDiff = createCert(dirName, certPathName, plContext);
+
+ subTest("Getting Authority Info Access");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetAuthorityInfoAccess(cert, &aiaList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(aiaList, &size, plContext));
+
+ if (size != 1) {
+ pkixTestErrorMsg = "unexpected number of AIA";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(aiaList, 0, (PKIX_PL_Object **)&aia, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(aiaList, 0, (PKIX_PL_Object **)&aiaDup, plContext));
+
+ subTest("Getting Subject Info Access as difference comparison");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectInfoAccess(certDiff, &siaList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(siaList, &size, plContext));
+
+ if (size != 1) {
+ pkixTestErrorMsg = "unexpected number of AIA";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(siaList, 0, (PKIX_PL_Object **)&aiaDiff, plContext));
+
+ subTest("Checking: Equal, Hash and ToString");
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(aia, aiaDup, aiaDiff, expectedAscii, InfoAccess, PKIX_FALSE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(aia);
+ PKIX_TEST_DECREF_AC(aiaDup);
+ PKIX_TEST_DECREF_AC(aiaDiff);
+ PKIX_TEST_DECREF_AC(aiaList);
+ PKIX_TEST_DECREF_AC(siaList);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(certDiff);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Authorityinfoaccess");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_cert.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_cert.c
new file mode 100644
index 000000000..274f818ab
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_cert.c
@@ -0,0 +1,2088 @@
+/* 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/. */
+/*
+ * test_cert.c
+ *
+ * Test Cert Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static PKIX_PL_Cert *altNameNoneCert = NULL;
+static PKIX_PL_Cert *altNameOtherCert = NULL;
+static PKIX_PL_Cert *altNameOtherCert_diff = NULL;
+static PKIX_PL_Cert *altNameRfc822Cert = NULL;
+static PKIX_PL_Cert *altNameRfc822Cert_diff = NULL;
+static PKIX_PL_Cert *altNameDnsCert = NULL;
+static PKIX_PL_Cert *altNameDnsCert_diff = NULL;
+static PKIX_PL_Cert *altNameX400Cert = NULL;
+static PKIX_PL_Cert *altNameX400Cert_diff = NULL;
+static PKIX_PL_Cert *altNameDnCert = NULL;
+static PKIX_PL_Cert *altNameDnCert_diff = NULL;
+static PKIX_PL_Cert *altNameEdiCert = NULL;
+static PKIX_PL_Cert *altNameEdiCert_diff = NULL;
+static PKIX_PL_Cert *altNameUriCert = NULL;
+static PKIX_PL_Cert *altNameUriCert_diff = NULL;
+static PKIX_PL_Cert *altNameIpCert = NULL;
+static PKIX_PL_Cert *altNameIpCert_diff = NULL;
+static PKIX_PL_Cert *altNameOidCert = NULL;
+static PKIX_PL_Cert *altNameOidCert_diff = NULL;
+static PKIX_PL_Cert *altNameMultipleCert = NULL;
+
+static void *plContext = NULL;
+
+static void
+createCerts(
+ char *dataCentralDir,
+ char *goodInput,
+ char *diffInput,
+ PKIX_PL_Cert **goodObject,
+ PKIX_PL_Cert **equalObject,
+ PKIX_PL_Cert **diffObject)
+{
+ subTest("PKIX_PL_Cert_Create <goodObject>");
+ *goodObject = createCert(dataCentralDir, goodInput, plContext);
+
+ subTest("PKIX_PL_Cert_Create <equalObject>");
+ *equalObject = createCert(dataCentralDir, goodInput, plContext);
+
+ subTest("PKIX_PL_Cert_Create <diffObject>");
+ *diffObject = createCert(dataCentralDir, diffInput, plContext);
+}
+
+static void
+createCertsWithSubjectAltNames(char *dataCentralDir)
+{
+ subTest("PKIX_PL_Cert_Create <altNameDNS>");
+ altNameDnsCert = createCert(dataCentralDir, "generalName/altNameDnsCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameDNS_diff>");
+ altNameDnsCert_diff = createCert(dataCentralDir, "generalName/altNameDnsCert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameRFC822>");
+ altNameRfc822Cert = createCert(dataCentralDir, "generalName/altNameRfc822Cert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameRFC822_diff>");
+ altNameRfc822Cert_diff = createCert(dataCentralDir, "generalName/altNameRfc822Cert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameX400Cert>");
+ altNameX400Cert = createCert(dataCentralDir, "generalName/altNameX400Cert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameX400_diff>");
+ altNameX400Cert_diff = createCert(dataCentralDir, "generalName/altNameX400Cert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameDN>");
+ altNameDnCert = createCert(dataCentralDir, "generalName/altNameDnCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameDN_diff>");
+ altNameDnCert_diff = createCert(dataCentralDir, "generalName/altNameDnCert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameEdiCert>");
+ altNameEdiCert = createCert(dataCentralDir, "generalName/altNameEdiCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameEdi_diff>");
+ altNameEdiCert_diff = createCert(dataCentralDir, "generalName/altNameEdiCert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameURI>");
+ altNameUriCert = createCert(dataCentralDir, "generalName/altNameUriCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameURI_diff>");
+ altNameUriCert_diff = createCert(dataCentralDir, "generalName/altNameUriCert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameIP>");
+ altNameIpCert = createCert(dataCentralDir, "generalName/altNameIpCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameIP_diff>");
+ altNameIpCert_diff = createCert(dataCentralDir, "generalName/altNameIpCert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameOID>");
+ altNameOidCert = createCert(dataCentralDir, "generalName/altNameOidCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameOID_diff>");
+ altNameOidCert_diff = createCert(dataCentralDir, "generalName/altNameOidCert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameOther>");
+ altNameOtherCert = createCert(dataCentralDir, "generalName/altNameOtherCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameOther_diff>");
+ altNameOtherCert_diff = createCert(dataCentralDir, "generalName/altNameOtherCert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameNone>");
+ altNameNoneCert = createCert(dataCentralDir, "generalName/altNameNoneCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameMultiple>");
+ altNameMultipleCert = createCert(dataCentralDir, "generalName/altNameRfc822DnsCert", plContext);
+}
+
+static void
+testGetVersion(
+ PKIX_PL_Cert *goodObject)
+{
+ PKIX_UInt32 goodVersion;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetVersion");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetVersion(goodObject, &goodVersion, plContext));
+
+ if (goodVersion != 2) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", goodVersion);
+ (void)printf("Expected value:\t2\n");
+ goto cleanup;
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSerialNumber(
+ PKIX_PL_Cert *goodObject,
+ PKIX_PL_Cert *equalObject,
+ PKIX_PL_Cert *diffObject)
+{
+ PKIX_PL_BigInt *goodSN = NULL;
+ PKIX_PL_BigInt *equalSN = NULL;
+ PKIX_PL_BigInt *diffSN = NULL;
+ char *expectedAscii = "37bc66ec";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetSerialNumber");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSerialNumber(goodObject, &goodSN, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSerialNumber(equalObject, &equalSN, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSerialNumber(diffObject, &diffSN, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodSN, equalSN, diffSN, expectedAscii, BigInt, PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodSN);
+ PKIX_TEST_DECREF_AC(equalSN);
+ PKIX_TEST_DECREF_AC(diffSN);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSubject(
+ PKIX_PL_Cert *goodObject,
+ PKIX_PL_Cert *equalObject,
+ PKIX_PL_Cert *diffObject)
+{
+ PKIX_PL_X500Name *goodSubject = NULL;
+ PKIX_PL_X500Name *equalSubject = NULL;
+ PKIX_PL_X500Name *diffSubject = NULL;
+ char *expectedAscii = "OU=bcn,OU=east,O=sun,C=us";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetSubject");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(goodObject, &goodSubject, plContext));
+
+ if (!goodSubject) {
+ testError("Certificate Subject should not be NULL");
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(equalObject, &equalSubject, plContext));
+
+ if (!equalSubject) {
+ testError("Certificate Subject should not be NULL");
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(diffObject, &diffSubject, plContext));
+
+ if (!diffSubject) {
+ testError("Certificate Subject should not be NULL");
+ goto cleanup;
+ }
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodSubject,
+ equalSubject,
+ diffSubject,
+ expectedAscii,
+ X500Name,
+ PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodSubject);
+ PKIX_TEST_DECREF_AC(equalSubject);
+ PKIX_TEST_DECREF_AC(diffSubject);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetIssuer(
+ PKIX_PL_Cert *goodObject,
+ PKIX_PL_Cert *equalObject,
+ PKIX_PL_Cert *diffObject)
+{
+ PKIX_PL_X500Name *goodIssuer = NULL;
+ PKIX_PL_X500Name *equalIssuer = NULL;
+ PKIX_PL_X500Name *diffIssuer = NULL;
+ char *expectedAscii = "CN=yassir,OU=bcn,OU=east,O=sun,C=us";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetIssuer");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetIssuer(goodObject, &goodIssuer, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetIssuer(equalObject, &equalIssuer, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetIssuer(diffObject, &diffIssuer, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodIssuer,
+ equalIssuer,
+ diffIssuer,
+ expectedAscii,
+ X500Name,
+ PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodIssuer);
+ PKIX_TEST_DECREF_AC(equalIssuer);
+ PKIX_TEST_DECREF_AC(diffIssuer);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAltNames(
+ PKIX_PL_Cert *goodCert,
+ PKIX_PL_Cert *diffCert,
+ char *expectedAscii)
+{
+ PKIX_List *goodAltNames = NULL;
+ PKIX_List *diffAltNames = NULL;
+ PKIX_PL_GeneralName *goodAltName = NULL;
+ PKIX_PL_GeneralName *diffAltName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectAltNames(goodCert, &goodAltNames, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodAltNames,
+ 0,
+ (PKIX_PL_Object **)&goodAltName,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectAltNames(diffCert, &diffAltNames, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffAltNames,
+ 0,
+ (PKIX_PL_Object **)&diffAltName,
+ plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodAltName, goodAltName, diffAltName,
+ expectedAscii, GeneralName, PKIX_TRUE);
+
+cleanup:
+ PKIX_TEST_DECREF_AC(goodAltNames);
+ PKIX_TEST_DECREF_AC(goodAltName);
+ PKIX_TEST_DECREF_AC(diffAltNames);
+ PKIX_TEST_DECREF_AC(diffAltName);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAltNamesNone(PKIX_PL_Cert *cert)
+{
+
+ PKIX_List *altNames = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectAltNames(cert, &altNames, plContext));
+
+ if (altNames != NULL) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%p\n", (void *)altNames);
+ (void)printf("Expected value:\tNULL\n");
+ goto cleanup;
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(altNames);
+ PKIX_TEST_RETURN();
+}
+static void
+testAltNamesMultiple()
+{
+ PKIX_List *altNames = NULL;
+ PKIX_PL_GeneralName *firstAltName = NULL;
+ PKIX_Int32 firstExpectedType = PKIX_RFC822_NAME;
+ PKIX_PL_GeneralName *secondAltName = NULL;
+ PKIX_Int32 secondExpectedType = PKIX_DNS_NAME;
+
+ char *expectedAscii =
+ "[\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 2d\n"
+ "\tIssuer: OU=labs,O=sun,C=us\n"
+ "\tSubject: CN=yassir,OU=labs,O=sun,C=us\n"
+ "\tValidity: [From: Mon Feb 09, 2004\n"
+ /* "\tValidity: [From: Mon Feb 09 14:43:52 2004\n" */
+ "\t To: Mon Feb 09, 2004]\n"
+ /* "\t To: Mon Feb 09 14:43:52 2004]\n" */
+ "\tSubjectAltNames: (yassir@sun.com, sunray.sun.com)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: (null)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "\tAuthorityInfoAccess: (null)\n"
+ "\tSubjectInfoAccess: (null)\n"
+ "\tCacheFlag: 0\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ testToStringHelper((PKIX_PL_Object *)altNameMultipleCert,
+ expectedAscii,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectAltNames(altNameMultipleCert, &altNames, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(altNames, 0, (PKIX_PL_Object **)&firstAltName, plContext));
+
+ if (firstAltName->type != firstExpectedType) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", firstAltName->type);
+ (void)printf("Expected value:\t%d\n", firstExpectedType);
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(altNames, 1, (PKIX_PL_Object **)&secondAltName, plContext));
+
+ if (secondAltName->type != secondExpectedType) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", secondAltName->type);
+ (void)printf("Expected value:\t%d\n", secondExpectedType);
+ goto cleanup;
+ }
+
+cleanup:
+ PKIX_TEST_DECREF_AC(altNames);
+ PKIX_TEST_DECREF_AC(firstAltName);
+ PKIX_TEST_DECREF_AC(secondAltName);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSubjectAltNames(char *dataCentralDir)
+{
+
+ char *expectedAscii = NULL;
+
+ createCertsWithSubjectAltNames(dataCentralDir);
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <DNS>");
+ expectedAscii = "east.sun.com";
+ testAltNames(altNameDnsCert, altNameDnsCert_diff, expectedAscii);
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <RFC822>");
+ expectedAscii = "alice.barnes@bcn.east.sun.com";
+ testAltNames(altNameRfc822Cert, altNameRfc822Cert_diff, expectedAscii);
+
+ /*
+ *this should work once bugzilla bug #233586 is fixed.
+ *subTest("PKIX_PL_Cert_GetSubjectAltNames <X400Address>");
+ *expectedAscii = "X400Address: <DER-encoded value>";
+ *testAltNames(altNameX400Cert, altNameX400Cert_diff, expectedAscii);
+ */
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <DN>");
+ expectedAscii = "CN=elley,OU=labs,O=sun,C=us";
+ testAltNames(altNameDnCert, altNameDnCert_diff, expectedAscii);
+
+ /*
+ * this should work once bugzilla bug #233586 is fixed.
+ * subTest("PKIX_PL_Cert_GetSubjectAltNames <EdiPartyName>");
+ * expectedAscii = "EDIPartyName: <DER-encoded value>";
+ * testAltNames(altNameEdiCert, altNameEdiCert_diff, expectedAscii);
+ */
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <URI>");
+ expectedAscii = "http://www.sun.com";
+ testAltNames(altNameUriCert, altNameUriCert_diff, expectedAscii);
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <IP>");
+ expectedAscii = "1.2.3.4";
+ testAltNames(altNameIpCert, altNameIpCert_diff, expectedAscii);
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <OID>");
+ expectedAscii = "1.2.39";
+ testAltNames(altNameOidCert, altNameOidCert_diff, expectedAscii);
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <Other>");
+ expectedAscii = "1.7.26.97";
+ testAltNames(altNameOtherCert, altNameOtherCert_diff, expectedAscii);
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <none>");
+ testAltNamesNone(altNameNoneCert);
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <Multiple>");
+ testAltNamesMultiple();
+}
+
+static void
+testGetSubjectPublicKey(
+ PKIX_PL_Cert *goodObject,
+ PKIX_PL_Cert *equalObject,
+ PKIX_PL_Cert *diffObject)
+{
+ PKIX_PL_PublicKey *goodPubKey = NULL;
+ PKIX_PL_PublicKey *equalPubKey = NULL;
+ PKIX_PL_PublicKey *diffPubKey = NULL;
+ char *expectedAscii = "ANSI X9.57 DSA Signature";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(goodObject, &goodPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(equalObject, &equalPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(diffObject, &diffPubKey, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodPubKey, equalPubKey, diffPubKey,
+ expectedAscii, PublicKey, PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodPubKey);
+ PKIX_TEST_DECREF_AC(equalPubKey);
+ PKIX_TEST_DECREF_AC(diffPubKey);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSubjectPublicKeyAlgId(PKIX_PL_Cert *goodObject)
+{
+ PKIX_PL_OID *pkixPubKeyOID = NULL;
+ char *expectedAscii = "1.2.840.10040.4.1";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKeyAlgId");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKeyAlgId(goodObject, &pkixPubKeyOID, plContext));
+
+ testToStringHelper((PKIX_PL_Object *)pkixPubKeyOID, expectedAscii, plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(pkixPubKeyOID);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCritExtensionsPresent(PKIX_PL_Cert *cert)
+{
+ PKIX_List *critOIDList = NULL;
+ char *firstOIDAscii = "2.5.29.15";
+ PKIX_PL_OID *firstOID = NULL;
+ char *secondOIDAscii = "2.5.29.19";
+ PKIX_PL_OID *secondOID = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetCriticalExtensionOIDs(cert, &critOIDList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(critOIDList, 0, (PKIX_PL_Object **)&firstOID, plContext));
+ testToStringHelper((PKIX_PL_Object *)firstOID, firstOIDAscii, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(critOIDList, 1, (PKIX_PL_Object **)&secondOID, plContext));
+
+ testToStringHelper((PKIX_PL_Object *)secondOID, secondOIDAscii, plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(critOIDList);
+ PKIX_TEST_DECREF_AC(firstOID);
+ PKIX_TEST_DECREF_AC(secondOID);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCritExtensionsAbsent(PKIX_PL_Cert *cert)
+{
+ PKIX_List *oidList = NULL;
+ PKIX_Boolean empty;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetCriticalExtensionOIDs(cert, &oidList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsEmpty(oidList, &empty, plContext));
+
+ if (!empty) {
+ pkixTestErrorMsg = "unexpected mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(oidList);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAllExtensionsAbsent(char *dataCentralDir)
+{
+ PKIX_List *oidList = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_Boolean empty;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Create <noExtensionsCert>");
+ cert = createCert(dataCentralDir, "noExtensionsCert", plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetCriticalExtensionOIDs(cert, &oidList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsEmpty(oidList, &empty, plContext));
+
+ if (!empty) {
+ pkixTestErrorMsg = "unexpected mismatch";
+ }
+
+cleanup:
+ PKIX_TEST_DECREF_AC(oidList);
+ PKIX_TEST_DECREF_AC(cert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCriticalExtensionOIDs(char *dataCentralDir, PKIX_PL_Cert *goodObject)
+{
+ subTest("PKIX_PL_Cert_GetCriticalExtensionOIDs "
+ "<CritExtensionsPresent>");
+ testCritExtensionsPresent(goodObject);
+
+ subTest("PKIX_PL_Cert_GetCriticalExtensionOIDs "
+ "<CritExtensionsAbsent>");
+ testCritExtensionsAbsent(altNameOidCert);
+
+ subTest("PKIX_PL_Cert_GetCriticalExtensionOIDs "
+ "<AllExtensionsAbsent>");
+ testAllExtensionsAbsent(dataCentralDir);
+}
+
+static void
+testKeyIdentifiersMatching(char *dataCentralDir)
+{
+ PKIX_PL_Cert *subjKeyIDCert = NULL;
+ PKIX_PL_Cert *authKeyIDCert = NULL;
+ PKIX_PL_ByteArray *subjKeyID = NULL;
+ PKIX_PL_ByteArray *authKeyID = NULL;
+ PKIX_PL_ByteArray *subjKeyID_diff = NULL;
+
+ char *expectedAscii =
+ "[116, 021, 213, 036, 028, 189, 094, 101, 136, 031, 225,"
+ " 139, 009, 126, 127, 234, 025, 072, 078, 097]";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Create <subjKeyIDCert>");
+ subjKeyIDCert = createCert(dataCentralDir, "keyIdentifier/subjKeyIDCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <authKeyIDCert>");
+ authKeyIDCert = createCert(dataCentralDir, "keyIdentifier/authKeyIDCert", plContext);
+
+ subTest("PKIX_PL_Cert_GetSubjectKeyIdentifier <good>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectKeyIdentifier(subjKeyIDCert, &subjKeyID, plContext));
+
+ subTest("PKIX_PL_Cert_GetAuthorityKeyIdentifier <equal>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetAuthorityKeyIdentifier(authKeyIDCert, &authKeyID, plContext));
+
+ subTest("PKIX_PL_Cert_GetSubjectKeyIdentifier <diff>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectKeyIdentifier(authKeyIDCert, &subjKeyID_diff, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(subjKeyID,
+ authKeyID,
+ subjKeyID_diff,
+ expectedAscii,
+ ByteArray,
+ PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(subjKeyIDCert);
+ PKIX_TEST_DECREF_AC(authKeyIDCert);
+ PKIX_TEST_DECREF_AC(subjKeyID);
+ PKIX_TEST_DECREF_AC(authKeyID);
+ PKIX_TEST_DECREF_AC(subjKeyID_diff);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testKeyIdentifierAbsent(PKIX_PL_Cert *cert)
+{
+ PKIX_PL_ByteArray *subjKeyID = NULL;
+ PKIX_PL_ByteArray *authKeyID = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectKeyIdentifier(cert, &subjKeyID, plContext));
+
+ if (subjKeyID != NULL) {
+ pkixTestErrorMsg = "unexpected mismatch";
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetAuthorityKeyIdentifier(cert, &authKeyID, plContext));
+
+ if (authKeyID != NULL) {
+ pkixTestErrorMsg = "unexpected mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(subjKeyID);
+ PKIX_TEST_DECREF_AC(authKeyID);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetKeyIdentifiers(char *dataCentralDir, PKIX_PL_Cert *goodObject)
+{
+ testKeyIdentifiersMatching(dataCentralDir);
+ testKeyIdentifierAbsent(goodObject);
+}
+
+static void
+testVerifyKeyUsage(
+ char *dataCentralDir,
+ char *dataDir,
+ PKIX_PL_Cert *multiKeyUsagesCert)
+{
+ PKIX_PL_Cert *encipherOnlyCert = NULL;
+ PKIX_PL_Cert *decipherOnlyCert = NULL;
+ PKIX_PL_Cert *noKeyUsagesCert = NULL;
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Create <encipherOnlyCert>");
+ encipherOnlyCert = createCert(dataCentralDir, "keyUsage/encipherOnlyCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <decipherOnlyCert>");
+ decipherOnlyCert = createCert(dataCentralDir, "keyUsage/decipherOnlyCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <noKeyUsagesCert>");
+ noKeyUsagesCert = createCert(dataCentralDir, "keyUsage/noKeyUsagesCert", plContext);
+
+ subTest("PKIX_PL_Cert_VerifyKeyUsage <key_cert_sign>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_VerifyKeyUsage(multiKeyUsagesCert, PKIX_KEY_CERT_SIGN, plContext));
+
+ subTest("PKIX_PL_Cert_VerifyKeyUsage <multiKeyUsages>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_VerifyKeyUsage(multiKeyUsagesCert,
+ PKIX_KEY_CERT_SIGN |
+ PKIX_DIGITAL_SIGNATURE,
+ plContext));
+
+ subTest("PKIX_PL_Cert_VerifyKeyUsage <encipher_only>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_VerifyKeyUsage(encipherOnlyCert, PKIX_ENCIPHER_ONLY, plContext));
+
+ subTest("PKIX_PL_Cert_VerifyKeyUsage <noKeyUsages>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_VerifyKeyUsage(noKeyUsagesCert, PKIX_ENCIPHER_ONLY, plContext));
+
+ subTest("PKIX_PL_Cert_VerifyKeyUsage <decipher_only>");
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_VerifyKeyUsage(decipherOnlyCert, PKIX_DECIPHER_ONLY, plContext));
+
+cleanup:
+ PKIX_TEST_DECREF_AC(encipherOnlyCert);
+ PKIX_TEST_DECREF_AC(decipherOnlyCert);
+ PKIX_TEST_DECREF_AC(noKeyUsagesCert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetExtendedKeyUsage(char *dataCentralDir)
+{
+
+ PKIX_PL_Cert *codeSigningEKUCert = NULL;
+ PKIX_PL_Cert *multiEKUCert = NULL;
+ PKIX_PL_Cert *noEKUCert = NULL;
+ PKIX_List *firstExtKeyUsage = NULL;
+ PKIX_List *secondExtKeyUsage = NULL;
+ PKIX_List *thirdExtKeyUsage = NULL;
+ PKIX_PL_OID *firstOID = NULL;
+ char *oidAscii = "1.3.6.1.5.5.7.3.3";
+ PKIX_PL_OID *secondOID = NULL;
+ char *secondOIDAscii = "1.3.6.1.5.5.7.3.1";
+ PKIX_PL_OID *thirdOID = NULL;
+ char *thirdOIDAscii = "1.3.6.1.5.5.7.3.2";
+ PKIX_PL_OID *fourthOID = NULL;
+ PKIX_UInt32 length = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Create <codeSigningEKUCert>");
+ codeSigningEKUCert = createCert(dataCentralDir, "extKeyUsage/codeSigningEKUCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <multiEKUCert>");
+ multiEKUCert = createCert(dataCentralDir, "extKeyUsage/multiEKUCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <noEKUCert>");
+ noEKUCert = createCert(dataCentralDir, "extKeyUsage/noEKUCert", plContext);
+
+ subTest("PKIX_PL_Cert_ExtendedKeyUsage <codeSigningEKU>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetExtendedKeyUsage(codeSigningEKUCert, &firstExtKeyUsage, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(firstExtKeyUsage, 0, (PKIX_PL_Object **)&firstOID, plContext));
+ testToStringHelper((PKIX_PL_Object *)firstOID, oidAscii, plContext);
+
+ subTest("PKIX_PL_Cert_ExtendedKeyUsage <multiEKU>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetExtendedKeyUsage(multiEKUCert, &secondExtKeyUsage, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(secondExtKeyUsage, &length, plContext));
+
+ if (length != 3) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", length);
+ (void)printf("Expected value:\t3\n");
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(secondExtKeyUsage,
+ 0,
+ (PKIX_PL_Object **)&secondOID,
+ plContext));
+
+ testToStringHelper((PKIX_PL_Object *)secondOID, oidAscii, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(secondExtKeyUsage,
+ 1,
+ (PKIX_PL_Object **)&thirdOID,
+ plContext));
+
+ testToStringHelper((PKIX_PL_Object *)thirdOID, secondOIDAscii, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(secondExtKeyUsage,
+ 2,
+ (PKIX_PL_Object **)&fourthOID,
+ plContext));
+
+ testToStringHelper((PKIX_PL_Object *)fourthOID, thirdOIDAscii, plContext);
+
+ subTest("PKIX_PL_Cert_ExtendedKeyUsage <noEKU>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetExtendedKeyUsage(noEKUCert, &thirdExtKeyUsage, plContext));
+
+ if (thirdExtKeyUsage != NULL) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%p\n", (void *)thirdExtKeyUsage);
+ (void)printf("Expected value:\tNULL\n");
+ goto cleanup;
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(firstOID);
+ PKIX_TEST_DECREF_AC(secondOID);
+ PKIX_TEST_DECREF_AC(thirdOID);
+ PKIX_TEST_DECREF_AC(fourthOID);
+
+ PKIX_TEST_DECREF_AC(firstExtKeyUsage);
+ PKIX_TEST_DECREF_AC(secondExtKeyUsage);
+ PKIX_TEST_DECREF_AC(thirdExtKeyUsage);
+
+ PKIX_TEST_DECREF_AC(codeSigningEKUCert);
+ PKIX_TEST_DECREF_AC(multiEKUCert);
+ PKIX_TEST_DECREF_AC(noEKUCert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testMakeInheritedDSAPublicKey(char *dataCentralDir)
+{
+ PKIX_PL_PublicKey *firstKey = NULL;
+ PKIX_PL_PublicKey *secondKey = NULL;
+ PKIX_PL_PublicKey *resultKeyPositive = NULL;
+ PKIX_PL_PublicKey *resultKeyNegative = NULL;
+ PKIX_PL_Cert *firstCert = NULL;
+ PKIX_PL_Cert *secondCert = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Create <dsaWithoutParams>");
+ firstCert = createCert(dataCentralDir, "publicKey/dsaWithoutParams", plContext);
+
+ subTest("PKIX_PL_Cert_Create <dsaWithParams>");
+ secondCert = createCert(dataCentralDir, "publicKey/dsaWithParams", plContext);
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey <firstKey>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(firstCert, &firstKey, plContext));
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey <secondKey>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(secondCert, &secondKey, plContext));
+
+ subTest("PKIX_PL_PublicKey_MakeInheritedDSAPublicKey <positive>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_PublicKey_MakeInheritedDSAPublicKey(firstKey, secondKey, &resultKeyPositive, plContext));
+
+ if (resultKeyPositive == NULL) {
+ testError("PKIX_PL_PublicKey_MakeInheritedDSAPublicKey failed");
+ }
+
+ subTest("PKIX_PL_PublicKey_MakeInheritedDSAPublicKey <negative>");
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_PublicKey_MakeInheritedDSAPublicKey(firstKey, firstKey, &resultKeyNegative, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(firstCert);
+ PKIX_TEST_DECREF_AC(secondCert);
+
+ PKIX_TEST_DECREF_AC(firstKey);
+ PKIX_TEST_DECREF_AC(secondKey);
+ PKIX_TEST_DECREF_AC(resultKeyPositive);
+ PKIX_TEST_DECREF_AC(resultKeyNegative);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testVerifySignature(char *dataCentralDir)
+{
+ PKIX_PL_Cert *firstCert = NULL;
+ PKIX_PL_Cert *secondCert = NULL;
+ PKIX_PL_PublicKey *firstPubKey = NULL;
+ PKIX_PL_PublicKey *secondPubKey = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Create <labs2yassir>");
+ firstCert = createCert(dataCentralDir, "publicKey/labs2yassir", plContext);
+
+ subTest("PKIX_PL_Cert_Create <yassir2labs>");
+ secondCert = createCert(dataCentralDir, "publicKey/yassir2labs", plContext);
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey <labs2yassir>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(firstCert, &firstPubKey, plContext));
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey <yassir2labs>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(secondCert, &secondPubKey, plContext));
+
+ subTest("PKIX_PL_Cert_VerifySignature <positive>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_VerifySignature(secondCert, firstPubKey, plContext));
+
+ subTest("PKIX_PL_Cert_VerifySignature <negative>");
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_VerifySignature(secondCert, secondPubKey, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(firstCert);
+ PKIX_TEST_DECREF_AC(secondCert);
+ PKIX_TEST_DECREF_AC(firstPubKey);
+ PKIX_TEST_DECREF_AC(secondPubKey);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCheckValidity(
+ PKIX_PL_Cert *olderCert,
+ PKIX_PL_Cert *newerCert)
+{
+ /*
+ * olderCert has the following Validity:
+ * notBefore = August 19, 1999: 20:19:56 GMT
+ * notAfter = August 18, 2000: 20:19:56 GMT
+ *
+ * newerCert has the following Validity:
+ * notBefore = November 13, 2003: 16:46:03 GMT
+ * notAfter = February 13, 2009: 16:46:03 GMT
+ */
+
+ /* olderDateAscii = March 29, 2000: 13:48:47 GMT */
+ char *olderAscii = "000329134847Z";
+ PKIX_PL_String *olderString = NULL;
+ PKIX_PL_Date *olderDate = NULL;
+
+ /* newerDateAscii = March 29, 2004: 13:48:47 GMT */
+ char *newerAscii = "040329134847Z";
+ PKIX_PL_String *newerString = NULL;
+ PKIX_PL_Date *newerDate = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_CheckValidity <creating Dates>");
+
+ /* create newer date when newer cert is valid but older cert is not */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, newerAscii, 0, &newerString, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Date_Create_UTCTime(newerString, &newerDate, plContext));
+
+ /* create older date when older cert is valid but newer cert is not */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, olderAscii, 0, &olderString, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Date_Create_UTCTime(olderString, &olderDate, plContext));
+
+ /* check validity of both certificates using olderDate */
+ subTest("PKIX_PL_Cert_CheckValidity <olderDate:positive>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_CheckValidity(olderCert, olderDate, plContext));
+
+ subTest("PKIX_PL_Cert_CheckValidity <olderDate:negative>");
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_CheckValidity(newerCert, olderDate, plContext));
+
+ /* check validity of both certificates using newerDate */
+ subTest("PKIX_PL_Cert_CheckValidity <newerDate:positive>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_CheckValidity(newerCert, newerDate, plContext));
+
+ subTest("PKIX_PL_Cert_CheckValidity <newerDate:negative>");
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_CheckValidity(olderCert, newerDate, plContext));
+
+ /*
+ * check validity of both certificates using current time
+ * NOTE: these "now" tests will not work when the current
+ * time is after newerCert.notAfter (~ February 13, 2009)
+ */
+ subTest("PKIX_PL_Cert_CheckValidity <now:positive>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_CheckValidity(newerCert, NULL, plContext));
+
+ subTest("PKIX_PL_Cert_CheckValidity <now:negative>");
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_CheckValidity(olderCert, NULL, plContext));
+
+cleanup:
+ PKIX_TEST_DECREF_AC(olderString);
+ PKIX_TEST_DECREF_AC(newerString);
+ PKIX_TEST_DECREF_AC(olderDate);
+ PKIX_TEST_DECREF_AC(newerDate);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+readCertBasicConstraints(
+ char *dataDir,
+ char *goodCertName,
+ char *diffCertName,
+ PKIX_PL_CertBasicConstraints **goodBasicConstraints,
+ PKIX_PL_CertBasicConstraints **equalBasicConstraints,
+ PKIX_PL_CertBasicConstraints **diffBasicConstraints)
+{
+
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ createCerts(dataDir, goodCertName, diffCertName,
+ &goodCert, &equalCert, &diffCert);
+ /*
+ * Warning: pointer will be NULL if BasicConstraints
+ * extension is not present in the certificate. */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetBasicConstraints(goodCert, goodBasicConstraints, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetBasicConstraints(equalCert, equalBasicConstraints, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetBasicConstraints(diffCert, diffBasicConstraints, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(equalCert);
+ PKIX_TEST_DECREF_AC(diffCert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testBasicConstraintsHelper(
+ char *dataDir,
+ char *goodCertName,
+ char *diffCertName,
+ char *expectedAscii)
+{
+ PKIX_PL_CertBasicConstraints *goodBasicConstraints = NULL;
+ PKIX_PL_CertBasicConstraints *equalBasicConstraints = NULL;
+ PKIX_PL_CertBasicConstraints *diffBasicConstraints = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ readCertBasicConstraints(dataDir,
+ goodCertName,
+ diffCertName,
+ &goodBasicConstraints,
+ &equalBasicConstraints,
+ &diffBasicConstraints);
+
+ /*
+ * The standard test macro is applicable only
+ * if BasicConstraint extension is present
+ * in the certificate. Otherwise some
+ * pointers will be null.
+ */
+ if ((goodBasicConstraints) &&
+ (equalBasicConstraints) &&
+ (diffBasicConstraints)) {
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodBasicConstraints,
+ equalBasicConstraints,
+ diffBasicConstraints,
+ expectedAscii,
+ BasicConstraints,
+ PKIX_TRUE);
+ } else {
+ /* Test what we can */
+ if (goodBasicConstraints) {
+ if (!equalBasicConstraints) {
+ testError("Unexpected NULL value of equalBasicConstraints");
+ goto cleanup;
+ }
+ subTest("PKIX_PL_BasicConstraints_Equals <match>");
+ testEqualsHelper((PKIX_PL_Object *)(goodBasicConstraints),
+ (PKIX_PL_Object *)(equalBasicConstraints),
+ PKIX_TRUE,
+ plContext);
+ subTest("PKIX_PL_BasicConstraints_Hashcode <match>");
+ testHashcodeHelper((PKIX_PL_Object *)(goodBasicConstraints),
+ (PKIX_PL_Object *)(equalBasicConstraints),
+ PKIX_TRUE,
+ plContext);
+ if (diffBasicConstraints) {
+ subTest("PKIX_PL_BasicConstraints_Equals <non-match>");
+ testEqualsHelper((PKIX_PL_Object *)(goodBasicConstraints),
+ (PKIX_PL_Object *)(diffBasicConstraints),
+ PKIX_FALSE,
+ plContext);
+ subTest("PKIX_PL_BasicConstraints_Hashcode <non-match>");
+ testHashcodeHelper((PKIX_PL_Object *)(goodBasicConstraints),
+ (PKIX_PL_Object *)(diffBasicConstraints),
+ PKIX_FALSE,
+ plContext);
+ }
+ subTest("PKIX_PL_BasicConstraints_Duplicate");
+ testDuplicateHelper((PKIX_PL_Object *)goodBasicConstraints, plContext);
+ }
+ if (expectedAscii) {
+ subTest("PKIX_PL_BasicConstraints_ToString");
+ testToStringHelper((PKIX_PL_Object *)(goodBasicConstraints),
+ expectedAscii,
+ plContext);
+ }
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodBasicConstraints);
+ PKIX_TEST_DECREF_AC(equalBasicConstraints);
+ PKIX_TEST_DECREF_AC(diffBasicConstraints);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testBasicConstraints_GetCAFlag(char *dataCentralDir)
+{
+ /*
+ * XXX When we have a certificate with a non-null Basic
+ * Constraints field and a value of FALSE for CAFlag,
+ * this test should be modified to use that
+ * certificate for diffCertName, and to verify that
+ * GetCAFlag returns a FALSE value. But our certificates for
+ * non-CAs are created with no BasicConstraints extension.
+ */
+ PKIX_PL_CertBasicConstraints *goodBasicConstraints = NULL;
+ PKIX_PL_CertBasicConstraints *equalBasicConstraints = NULL;
+ PKIX_PL_CertBasicConstraints *diffBasicConstraints = NULL;
+ char *goodCertName = "yassir2yassir";
+ char *diffCertName = "nss2alice";
+ PKIX_Boolean goodCAFlag = PKIX_FALSE;
+ PKIX_Boolean diffCAFlag = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_BasicConstraints_GetCAFlag");
+
+ readCertBasicConstraints(dataCentralDir,
+ goodCertName,
+ diffCertName,
+ &goodBasicConstraints,
+ &equalBasicConstraints,
+ &diffBasicConstraints);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BasicConstraints_GetCAFlag(goodBasicConstraints, &goodCAFlag, plContext));
+ if (!goodCAFlag) {
+ testError("BasicConstraint CAFlag unexpectedly FALSE");
+ goto cleanup;
+ }
+
+ if (diffBasicConstraints) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BasicConstraints_GetCAFlag(diffBasicConstraints, &diffCAFlag, plContext));
+ if (diffCAFlag) {
+ testError("BasicConstraint CAFlag unexpectedly TRUE");
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodBasicConstraints);
+ PKIX_TEST_DECREF_AC(equalBasicConstraints);
+ PKIX_TEST_DECREF_AC(diffBasicConstraints);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testBasicConstraints_GetPathLenConstraint(char *dataCentralDir)
+{
+ PKIX_PL_CertBasicConstraints *goodBasicConstraints = NULL;
+ PKIX_PL_CertBasicConstraints *equalBasicConstraints = NULL;
+ PKIX_PL_CertBasicConstraints *diffBasicConstraints = NULL;
+ char *goodCertName = "yassir2yassir";
+ char *diffCertName = "sun2sun";
+ PKIX_Int32 goodPathLen = 0;
+ PKIX_Int32 diffPathLen = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_BasicConstraints_GetPathLenConstraint");
+
+ readCertBasicConstraints(dataCentralDir,
+ goodCertName,
+ diffCertName,
+ &goodBasicConstraints,
+ &equalBasicConstraints,
+ &diffBasicConstraints);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BasicConstraints_GetPathLenConstraint(goodBasicConstraints, &goodPathLen, plContext));
+ if (0 != goodPathLen) {
+ testError("unexpected basicConstraint pathLen");
+ (void)printf("Actual value:\t%d\n", goodPathLen);
+ (void)printf("Expected value:\t0\n");
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BasicConstraints_GetPathLenConstraint(diffBasicConstraints, &diffPathLen, plContext));
+ if (1 != diffPathLen) {
+ testError("unexpected basicConstraint pathLen");
+ (void)printf("Actual value:\t%d\n", diffPathLen);
+ (void)printf("Expected value:\t1\n");
+ goto cleanup;
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodBasicConstraints);
+ PKIX_TEST_DECREF_AC(equalBasicConstraints);
+ PKIX_TEST_DECREF_AC(diffBasicConstraints);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetBasicConstraints(char *dataCentralDir)
+{
+ char *goodCertName = NULL;
+ char *diffCertName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetBasicConstraints <CA(0) and non-CA>");
+ goodCertName = "yassir2yassir";
+ diffCertName = "nss2alice";
+ testBasicConstraintsHelper(dataCentralDir, goodCertName, diffCertName, "CA(0)");
+
+ subTest("PKIX_PL_Cert_GetBasicConstraints <non-CA and CA(1)>");
+ goodCertName = "nss2alice";
+ diffCertName = "sun2sun";
+ testBasicConstraintsHelper(dataCentralDir, goodCertName, diffCertName, NULL);
+
+ subTest("PKIX_PL_Cert_GetBasicConstraints <CA(0) and CA(1)>");
+ goodCertName = "yassir2bcn";
+ diffCertName = "sun2sun";
+ testBasicConstraintsHelper(dataCentralDir, goodCertName, diffCertName, "CA(0)");
+
+ subTest("PKIX_PL_Cert_GetBasicConstraints <CA(-1) and CA(1)>");
+ goodCertName = "anchor2dsa";
+ diffCertName = "sun2sun";
+ testBasicConstraintsHelper(dataCentralDir, goodCertName, diffCertName, "CA(-1)");
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetPolicyInformation(char *dataDir)
+{
+
+ char *goodCertName =
+ "UserNoticeQualifierTest15EE.crt";
+ char *equalCertName =
+ "UserNoticeQualifierTest15EE.crt";
+ char *diffCertName =
+ "UserNoticeQualifierTest17EE.crt";
+ PKIX_Boolean isImmutable = PKIX_FALSE;
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+ PKIX_List *goodPolicyInfo = NULL;
+ PKIX_List *equalPolicyInfo = NULL;
+ PKIX_List *diffPolicyInfo = NULL;
+ PKIX_PL_CertPolicyInfo *goodPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *equalPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *diffPolicy = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_PL_Cert_GetPolicyInformation");
+
+ /*
+ * Get the cert, then the list of policyInfos.
+ * Take the first policyInfo from the list.
+ */
+
+ /* Get the PolicyInfo objects */
+ goodCert = createCert(dataDir, goodCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(goodCert, &goodPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodPolicyInfo, 0, (PKIX_PL_Object **)&goodPolicy, plContext));
+
+ equalCert = createCert(dataDir, equalCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(equalCert, &equalPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(equalPolicyInfo,
+ 0,
+ (PKIX_PL_Object **)&equalPolicy,
+ plContext));
+
+ diffCert = createCert(dataDir, diffCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(diffCert, &diffPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffPolicyInfo, 0, (PKIX_PL_Object **)&diffPolicy, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodPolicy,
+ equalPolicy,
+ diffPolicy,
+ NULL,
+ CertPolicyInfo,
+ PKIX_FALSE);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsImmutable(goodPolicyInfo, &isImmutable, plContext));
+
+ if (isImmutable != PKIX_TRUE) {
+ testError("PolicyInfo List is not immutable");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodPolicy);
+ PKIX_TEST_DECREF_AC(equalPolicy);
+ PKIX_TEST_DECREF_AC(diffPolicy);
+ PKIX_TEST_DECREF_AC(goodPolicyInfo);
+ PKIX_TEST_DECREF_AC(equalPolicyInfo);
+ PKIX_TEST_DECREF_AC(diffPolicyInfo);
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(equalCert);
+ PKIX_TEST_DECREF_AC(diffCert);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCertPolicy_GetPolicyId(char *dataDir)
+{
+ char *goodCertName =
+ "UserNoticeQualifierTest15EE.crt";
+ char *equalCertName =
+ "UserNoticeQualifierTest16EE.crt";
+ char *diffCertName =
+ "UserNoticeQualifierTest17EE.crt";
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+ PKIX_List *goodPolicyInfo = NULL;
+ PKIX_List *equalPolicyInfo = NULL;
+ PKIX_List *diffPolicyInfo = NULL;
+ PKIX_PL_CertPolicyInfo *goodPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *equalPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *diffPolicy = NULL;
+ PKIX_PL_OID *goodID = NULL;
+ PKIX_PL_OID *equalID = NULL;
+ PKIX_PL_OID *diffID = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_PL_CertPolicyInfo_GetPolicyId");
+
+ /*
+ * Get the cert, then the list of policyInfos.
+ * Take the first policyInfo from the list.
+ * Finally, get the policyInfo's ID.
+ */
+
+ /* Get the PolicyInfo objects */
+ goodCert = createCert(dataDir, goodCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(goodCert, &goodPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodPolicyInfo, 0, (PKIX_PL_Object **)&goodPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId(goodPolicy, &goodID, plContext));
+
+ equalCert = createCert(dataDir, equalCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(equalCert, &equalPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(equalPolicyInfo,
+ 0,
+ (PKIX_PL_Object **)&equalPolicy,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId(equalPolicy, &equalID, plContext));
+
+ diffCert = createCert(dataDir, diffCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(diffCert, &diffPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffPolicyInfo, 0, (PKIX_PL_Object **)&diffPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId(diffPolicy, &diffID, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodID, equalID, diffID, NULL, OID, PKIX_FALSE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodID);
+ PKIX_TEST_DECREF_AC(equalID);
+ PKIX_TEST_DECREF_AC(diffID);
+ PKIX_TEST_DECREF_AC(goodPolicy);
+ PKIX_TEST_DECREF_AC(equalPolicy);
+ PKIX_TEST_DECREF_AC(diffPolicy);
+ PKIX_TEST_DECREF_AC(goodPolicyInfo);
+ PKIX_TEST_DECREF_AC(equalPolicyInfo);
+ PKIX_TEST_DECREF_AC(diffPolicyInfo);
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(equalCert);
+ PKIX_TEST_DECREF_AC(diffCert);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCertPolicy_GetPolQualifiers(char *dataDir)
+{
+ char *goodCertName =
+ "UserNoticeQualifierTest15EE.crt";
+ char *equalCertName =
+ "UserNoticeQualifierTest16EE.crt";
+ char *diffCertName =
+ "UserNoticeQualifierTest18EE.crt";
+ PKIX_Boolean isImmutable = PKIX_FALSE;
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+ PKIX_List *goodPolicyInfo = NULL;
+ PKIX_List *equalPolicyInfo = NULL;
+ PKIX_List *diffPolicyInfo = NULL;
+ PKIX_PL_CertPolicyInfo *goodPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *equalPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *diffPolicy = NULL;
+ PKIX_List *goodQuals = NULL;
+ PKIX_List *equalQuals = NULL;
+ PKIX_List *diffQuals = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_PL_CertPolicyInfo_GetPolQualifiers");
+
+ /*
+ * Get the cert, then the list of policyInfos.
+ * Take the first policyInfo from the list.
+ * Get its list of PolicyQualifiers.
+ */
+
+ /* Get the PolicyInfo objects */
+ goodCert = createCert(dataDir, goodCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(goodCert, &goodPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodPolicyInfo, 0, (PKIX_PL_Object **)&goodPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(goodPolicy, &goodQuals, plContext));
+
+ equalCert = createCert(dataDir, equalCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(equalCert, &equalPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(equalPolicyInfo,
+ 0,
+ (PKIX_PL_Object **)&equalPolicy,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(equalPolicy, &equalQuals, plContext));
+
+ diffCert = createCert(dataDir, diffCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(diffCert, &diffPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffPolicyInfo, 0, (PKIX_PL_Object **)&diffPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(diffPolicy, &diffQuals, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodQuals,
+ equalQuals,
+ diffQuals,
+ NULL,
+ List,
+ PKIX_FALSE);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsImmutable(goodQuals, &isImmutable, plContext));
+
+ if (isImmutable != PKIX_TRUE) {
+ testError("PolicyQualifier List is not immutable");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(goodPolicyInfo);
+ PKIX_TEST_DECREF_AC(goodPolicy);
+ PKIX_TEST_DECREF_AC(goodQuals);
+ PKIX_TEST_DECREF_AC(equalCert);
+ PKIX_TEST_DECREF_AC(equalPolicyInfo);
+ PKIX_TEST_DECREF_AC(equalQuals);
+ PKIX_TEST_DECREF_AC(equalPolicy);
+ PKIX_TEST_DECREF_AC(diffCert);
+ PKIX_TEST_DECREF_AC(diffPolicyInfo);
+ PKIX_TEST_DECREF_AC(diffPolicy);
+ PKIX_TEST_DECREF_AC(diffQuals);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testPolicyQualifier_GetQualifier(char *dataDir)
+{
+ char *goodCertName =
+ "UserNoticeQualifierTest15EE.crt";
+ char *equalCertName =
+ "UserNoticeQualifierTest16EE.crt";
+ char *diffCertName =
+ "UserNoticeQualifierTest18EE.crt";
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+ PKIX_List *goodPolicyInfo = NULL;
+ PKIX_List *equalPolicyInfo = NULL;
+ PKIX_List *diffPolicyInfo = NULL;
+ PKIX_PL_CertPolicyInfo *goodPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *equalPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *diffPolicy = NULL;
+ PKIX_List *goodQuals = NULL;
+ PKIX_List *equalQuals = NULL;
+ PKIX_List *diffQuals = NULL;
+ PKIX_PL_CertPolicyQualifier *goodPolQualifier = NULL;
+ PKIX_PL_CertPolicyQualifier *equalPolQualifier = NULL;
+ PKIX_PL_CertPolicyQualifier *diffPolQualifier = NULL;
+ PKIX_PL_ByteArray *goodArray = NULL;
+ PKIX_PL_ByteArray *equalArray = NULL;
+ PKIX_PL_ByteArray *diffArray = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_PL_PolicyQualifier_GetQualifier");
+
+ /*
+ * Get the cert, then the list of policyInfos.
+ * Take the first policyInfo from the list.
+ * Get its list of PolicyQualifiers.
+ * Take the first policyQualifier from the list.
+ * Finally, get the policyQualifier's ByteArray.
+ */
+
+ /* Get the PolicyInfo objects */
+ goodCert = createCert(dataDir, goodCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(goodCert, &goodPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodPolicyInfo, 0, (PKIX_PL_Object **)&goodPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(goodPolicy, &goodQuals, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodQuals,
+ 0,
+ (PKIX_PL_Object **)&goodPolQualifier,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_PolicyQualifier_GetQualifier(goodPolQualifier, &goodArray, plContext));
+
+ equalCert = createCert(dataDir, equalCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(equalCert, &equalPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(equalPolicyInfo,
+ 0,
+ (PKIX_PL_Object **)&equalPolicy,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(equalPolicy, &equalQuals, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(equalQuals,
+ 0,
+ (PKIX_PL_Object **)&equalPolQualifier,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_PolicyQualifier_GetQualifier(equalPolQualifier, &equalArray, plContext));
+
+ diffCert = createCert(dataDir, diffCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(diffCert, &diffPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffPolicyInfo, 0, (PKIX_PL_Object **)&diffPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(diffPolicy, &diffQuals, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffQuals,
+ 0,
+ (PKIX_PL_Object **)&diffPolQualifier,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_PolicyQualifier_GetQualifier(diffPolQualifier, &diffArray, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodArray, equalArray, diffArray, NULL, ByteArray, PKIX_FALSE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodArray);
+ PKIX_TEST_DECREF_AC(equalArray);
+ PKIX_TEST_DECREF_AC(diffArray);
+ PKIX_TEST_DECREF_AC(goodPolQualifier);
+ PKIX_TEST_DECREF_AC(equalPolQualifier);
+ PKIX_TEST_DECREF_AC(diffPolQualifier);
+ PKIX_TEST_DECREF_AC(goodQuals);
+ PKIX_TEST_DECREF_AC(equalQuals);
+ PKIX_TEST_DECREF_AC(diffQuals);
+ PKIX_TEST_DECREF_AC(goodPolicy);
+ PKIX_TEST_DECREF_AC(equalPolicy);
+ PKIX_TEST_DECREF_AC(diffPolicy);
+ PKIX_TEST_DECREF_AC(goodPolicyInfo);
+ PKIX_TEST_DECREF_AC(equalPolicyInfo);
+ PKIX_TEST_DECREF_AC(diffPolicyInfo);
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(equalCert);
+ PKIX_TEST_DECREF_AC(diffCert);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testPolicyQualifier_GetPolicyQualifierId(char *dataDir)
+{
+ char *goodCertName =
+ "UserNoticeQualifierTest15EE.crt";
+ char *equalCertName =
+ "UserNoticeQualifierTest16EE.crt";
+ char *diffCertName =
+ "CPSPointerQualifierTest20EE.crt";
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+ PKIX_List *goodPolicyInfo = NULL;
+ PKIX_List *equalPolicyInfo = NULL;
+ PKIX_List *diffPolicyInfo = NULL;
+ PKIX_PL_CertPolicyInfo *goodPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *equalPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *diffPolicy = NULL;
+ PKIX_List *goodQuals = NULL;
+ PKIX_List *equalQuals = NULL;
+ PKIX_List *diffQuals = NULL;
+ PKIX_PL_CertPolicyQualifier *goodPolQualifier = NULL;
+ PKIX_PL_CertPolicyQualifier *equalPolQualifier = NULL;
+ PKIX_PL_CertPolicyQualifier *diffPolQualifier = NULL;
+ PKIX_PL_OID *goodID = NULL;
+ PKIX_PL_OID *equalID = NULL;
+ PKIX_PL_OID *diffID = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_PL_PolicyQualifier_GetPolicyQualifierId");
+
+ /*
+ * Get the cert, then the list of policyInfos.
+ * Take the first policyInfo from the list.
+ * Get its list of PolicyQualifiers.
+ * Take the first policyQualifier from the list.
+ * Finally, get the policyQualifier's ID.
+ */
+
+ /* Get the PolicyQualifier objects */
+ goodCert = createCert(dataDir, goodCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(goodCert, &goodPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodPolicyInfo, 0, (PKIX_PL_Object **)&goodPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(goodPolicy, &goodQuals, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodQuals,
+ 0,
+ (PKIX_PL_Object **)&goodPolQualifier,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_PolicyQualifier_GetPolicyQualifierId(goodPolQualifier, &goodID, plContext));
+
+ equalCert = createCert(dataDir, equalCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(equalCert, &equalPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(equalPolicyInfo,
+ 0,
+ (PKIX_PL_Object **)&equalPolicy,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(equalPolicy, &equalQuals, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(equalQuals,
+ 0,
+ (PKIX_PL_Object **)&equalPolQualifier,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_PolicyQualifier_GetPolicyQualifierId(equalPolQualifier, &equalID, plContext));
+
+ diffCert = createCert(dataDir, diffCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(diffCert, &diffPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffPolicyInfo, 0, (PKIX_PL_Object **)&diffPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(diffPolicy, &diffQuals, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffQuals,
+ 0,
+ (PKIX_PL_Object **)&diffPolQualifier,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_PolicyQualifier_GetPolicyQualifierId(diffPolQualifier, &diffID, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodID, equalID, diffID, NULL, OID, PKIX_FALSE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodID);
+ PKIX_TEST_DECREF_AC(equalID);
+ PKIX_TEST_DECREF_AC(diffID);
+ PKIX_TEST_DECREF_AC(goodPolQualifier);
+ PKIX_TEST_DECREF_AC(equalPolQualifier);
+ PKIX_TEST_DECREF_AC(diffPolQualifier);
+ PKIX_TEST_DECREF_AC(goodQuals);
+ PKIX_TEST_DECREF_AC(equalQuals);
+ PKIX_TEST_DECREF_AC(diffQuals);
+ PKIX_TEST_DECREF_AC(goodPolicy);
+ PKIX_TEST_DECREF_AC(equalPolicy);
+ PKIX_TEST_DECREF_AC(diffPolicy);
+ PKIX_TEST_DECREF_AC(goodPolicyInfo);
+ PKIX_TEST_DECREF_AC(equalPolicyInfo);
+ PKIX_TEST_DECREF_AC(diffPolicyInfo);
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(equalCert);
+ PKIX_TEST_DECREF_AC(diffCert);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAreCertPoliciesCritical(char *dataCentralDir, char *dataDir)
+{
+
+ char *trueCertName = "CertificatePoliciesCritical.crt";
+ char *falseCertName = "UserNoticeQualifierTest15EE.crt";
+ PKIX_PL_Cert *trueCert = NULL;
+ PKIX_PL_Cert *falseCert = NULL;
+ PKIX_Boolean trueVal = PKIX_FALSE;
+ PKIX_Boolean falseVal = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_PL_Cert_AreCertPoliciesCritical - <true>");
+
+ trueCert = createCert(dataCentralDir, trueCertName, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_AreCertPoliciesCritical(trueCert, &trueVal, plContext));
+
+ if (trueVal != PKIX_TRUE) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", trueVal);
+ (void)printf("Expected value:\t1\n");
+ goto cleanup;
+ }
+
+ subTest("PKIX_PL_Cert_AreCertPoliciesCritical - <false>");
+
+ falseCert = createCert(dataDir, falseCertName, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_AreCertPoliciesCritical(falseCert, &falseVal, plContext));
+
+ if (falseVal != PKIX_FALSE) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", falseVal);
+ (void)printf("Expected value:\t0\n");
+ goto cleanup;
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(trueCert);
+ PKIX_TEST_DECREF_AC(falseCert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCertPolicyConstraints(char *dataDir)
+{
+ char *requireExplicitPolicy2CertName =
+ "requireExplicitPolicy2CACert.crt";
+ char *inhibitPolicyMapping5CertName =
+ "inhibitPolicyMapping5CACert.crt";
+ char *inhibitAnyPolicy5CertName =
+ "inhibitAnyPolicy5CACert.crt";
+ char *inhibitAnyPolicy0CertName =
+ "inhibitAnyPolicy0CACert.crt";
+ PKIX_PL_Cert *requireExplicitPolicy2Cert = NULL;
+ PKIX_PL_Cert *inhibitPolicyMapping5Cert = NULL;
+ PKIX_PL_Cert *inhibitAnyPolicy5Cert = NULL;
+ PKIX_PL_Cert *inhibitAnyPolicy0Cert = NULL;
+ PKIX_Int32 skipCerts = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetRequireExplicitPolicy");
+ requireExplicitPolicy2Cert = createCert(dataDir, requireExplicitPolicy2CertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetRequireExplicitPolicy(requireExplicitPolicy2Cert, &skipCerts, NULL));
+ PR_ASSERT(skipCerts == 2);
+
+ subTest("PKIX_PL_Cert_GetPolicyMappingInhibited");
+ inhibitPolicyMapping5Cert = createCert(dataDir, inhibitPolicyMapping5CertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyMappingInhibited(inhibitPolicyMapping5Cert, &skipCerts, NULL));
+ PR_ASSERT(skipCerts == 5);
+
+ subTest("PKIX_PL_Cert_GetInhibitAnyPolicy");
+ inhibitAnyPolicy5Cert = createCert(dataDir, inhibitAnyPolicy5CertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetInhibitAnyPolicy(inhibitAnyPolicy5Cert, &skipCerts, NULL));
+ PR_ASSERT(skipCerts == 5);
+
+ inhibitAnyPolicy0Cert = createCert(dataDir, inhibitAnyPolicy0CertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetInhibitAnyPolicy(inhibitAnyPolicy0Cert, &skipCerts, NULL));
+ PR_ASSERT(skipCerts == 0);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(requireExplicitPolicy2Cert);
+ PKIX_TEST_DECREF_AC(inhibitPolicyMapping5Cert);
+ PKIX_TEST_DECREF_AC(inhibitAnyPolicy5Cert);
+ PKIX_TEST_DECREF_AC(inhibitAnyPolicy0Cert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCertPolicyMaps(char *dataDir)
+{
+ char *policyMappingsCertName =
+ "P1Mapping1to234CACert.crt";
+ char *expectedAscii =
+ "2.16.840.1.101.3.2.1.48.1=>2.16.840.1.101.3.2.1.48.2";
+
+ PKIX_PL_Cert *policyMappingsCert = NULL;
+ PKIX_List *mappings = NULL;
+ PKIX_PL_CertPolicyMap *goodMap = NULL;
+ PKIX_PL_CertPolicyMap *equalMap = NULL;
+ PKIX_PL_CertPolicyMap *diffMap = NULL;
+ PKIX_PL_OID *goodOID = NULL;
+ PKIX_PL_OID *equalOID = NULL;
+ PKIX_PL_OID *diffOID = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetPolicyMappings");
+
+ policyMappingsCert = createCert(dataDir, policyMappingsCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyMappings(policyMappingsCert, &mappings, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(mappings, 0, (PKIX_PL_Object **)&goodMap, NULL));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(mappings, 0, (PKIX_PL_Object **)&equalMap, NULL));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(mappings, 2, (PKIX_PL_Object **)&diffMap, NULL));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodMap,
+ equalMap,
+ diffMap,
+ expectedAscii,
+ CertPolicyMap,
+ PKIX_TRUE);
+
+ subTest("PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy(goodMap, &goodOID, NULL));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy(diffMap, &equalOID, NULL));
+ subTest("PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy(diffMap, &diffOID, NULL));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodOID,
+ equalOID,
+ diffOID,
+ "2.16.840.1.101.3.2.1.48.1",
+ OID,
+ PKIX_FALSE);
+
+ subTest("pkix_pl_CertPolicyMap_Destroy");
+ PKIX_TEST_DECREF_BC(goodMap);
+ PKIX_TEST_DECREF_BC(equalMap);
+ PKIX_TEST_DECREF_BC(diffMap);
+
+cleanup:
+ PKIX_TEST_DECREF_AC(policyMappingsCert);
+ PKIX_TEST_DECREF_AC(mappings);
+ PKIX_TEST_DECREF_AC(goodOID);
+ PKIX_TEST_DECREF_AC(equalOID);
+ PKIX_TEST_DECREF_AC(diffOID);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testNameConstraints(char *dataDir)
+{
+ char *firstPname = "nameConstraintsDN3subCA2Cert.crt";
+ char *secondPname = "nameConstraintsDN4CACert.crt";
+ char *thirdPname = "nameConstraintsDN5CACert.crt";
+ char *lastPname = "InvalidDNnameConstraintsTest3EE.crt";
+ PKIX_PL_Cert *firstCert = NULL;
+ PKIX_PL_Cert *secondCert = NULL;
+ PKIX_PL_Cert *thirdCert = NULL;
+ PKIX_PL_Cert *lastCert = NULL;
+ PKIX_PL_CertNameConstraints *firstNC = NULL;
+ PKIX_PL_CertNameConstraints *secondNC = NULL;
+ PKIX_PL_CertNameConstraints *thirdNC = NULL;
+ PKIX_PL_CertNameConstraints *firstMergedNC = NULL;
+ PKIX_PL_CertNameConstraints *secondMergedNC = NULL;
+ char *firstExpectedAscii =
+ "[\n"
+ "\t\tPermitted Name: (O=Test Certificates,C=US)\n"
+ "\t\tExcluded Name: (OU=excludedSubtree1,O=Test Certificates,"
+ "C=US, OU=excludedSubtree2,O=Test Certificates,C=US)\n"
+ "\t]\n";
+ char *secondExpectedAscii =
+ "[\n"
+ "\t\tPermitted Name: (O=Test Certificates,C=US, "
+ "OU=permittedSubtree1,O=Test Certificates,C=US)\n"
+ "\t\tExcluded Name: (OU=excludedSubtree1,"
+ "O=Test Certificates,"
+ "C=US, OU=excludedSubtree2,O=Test Certificates,C=US, "
+ "OU=excludedSubtree1,OU=permittedSubtree1,"
+ "O=Test Certificates,C=US)\n"
+ "\t]\n";
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_PL_CertNameConstraints");
+
+ firstCert = createCert(dataDir, firstPname, plContext);
+ secondCert = createCert(dataDir, secondPname, plContext);
+ thirdCert = createCert(dataDir, thirdPname, plContext);
+ lastCert = createCert(dataDir, lastPname, plContext);
+
+ subTest("PKIX_PL_Cert_GetNameConstraints <total=3>");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(firstCert, &firstNC, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(secondCert, &secondNC, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(thirdCert, &thirdNC, NULL));
+
+ subTest("PKIX_PL_Cert_MergeNameConstraints <1st and 2nd>");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_MergeNameConstraints(firstNC, secondNC, &firstMergedNC, NULL));
+
+ subTest("PKIX_PL_Cert_MergeNameConstraints <1st+2nd and 3rd>");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_MergeNameConstraints(firstMergedNC, thirdNC, &secondMergedNC, NULL));
+
+ testToStringHelper((PKIX_PL_Object *)firstMergedNC,
+ firstExpectedAscii,
+ plContext);
+
+ testToStringHelper((PKIX_PL_Object *)secondMergedNC,
+ secondExpectedAscii,
+ plContext);
+
+ subTest("PKIX_PL_Cert_CheckNameConstraints <permitted>");
+
+ /* Subject: CN=nameConstraints DN3 subCA2,O=Test Certificates,C=US */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_CheckNameConstraints(firstCert, firstMergedNC, NULL));
+
+ subTest("PKIX_PL_Cert_CheckNameConstraints <OU in excluded>");
+
+ /*
+ * Subject: CN=Invalid DN nameConstraints EE Certificate Test3,
+ * OU=permittedSubtree1,O=Test Certificates,C=US
+ */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_CheckNameConstraints(lastCert, secondMergedNC, NULL));
+
+ subTest("PKIX_PL_Cert_CheckNameConstraints <excluded>");
+
+ /*
+ * Subject: CN=Invalid DN nameConstraints EE Certificate Test3,
+ * OU=permittedSubtree1,O=Test Certificates,C=US
+ * SubjectAltNames: CN=Invalid DN nameConstraints EE Certificate
+ * Test3,OU=excludedSubtree1,O=Test Certificates,C=US
+ */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_CheckNameConstraints(lastCert, firstMergedNC, NULL));
+
+ subTest("PKIX_PL_Cert_CheckNameConstraints <excluded>");
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_CheckNameConstraints(firstCert, secondMergedNC, NULL));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(firstCert);
+ PKIX_TEST_DECREF_AC(secondCert);
+ PKIX_TEST_DECREF_AC(thirdCert);
+ PKIX_TEST_DECREF_AC(lastCert);
+ PKIX_TEST_DECREF_AC(firstNC);
+ PKIX_TEST_DECREF_AC(secondNC);
+ PKIX_TEST_DECREF_AC(thirdNC);
+ PKIX_TEST_DECREF_AC(firstMergedNC);
+ PKIX_TEST_DECREF_AC(secondMergedNC);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+ PKIX_TEST_DECREF_BC(altNameNoneCert);
+ PKIX_TEST_DECREF_BC(altNameOtherCert);
+ PKIX_TEST_DECREF_BC(altNameOtherCert_diff);
+ PKIX_TEST_DECREF_BC(altNameRfc822Cert);
+ PKIX_TEST_DECREF_BC(altNameRfc822Cert_diff);
+ PKIX_TEST_DECREF_BC(altNameDnsCert);
+ PKIX_TEST_DECREF_BC(altNameDnsCert_diff);
+ PKIX_TEST_DECREF_BC(altNameX400Cert);
+ PKIX_TEST_DECREF_BC(altNameX400Cert_diff);
+ PKIX_TEST_DECREF_BC(altNameDnCert);
+ PKIX_TEST_DECREF_BC(altNameDnCert_diff);
+ PKIX_TEST_DECREF_BC(altNameEdiCert);
+ PKIX_TEST_DECREF_BC(altNameEdiCert_diff);
+ PKIX_TEST_DECREF_BC(altNameUriCert);
+ PKIX_TEST_DECREF_BC(altNameUriCert_diff);
+ PKIX_TEST_DECREF_BC(altNameIpCert);
+ PKIX_TEST_DECREF_BC(altNameIpCert_diff);
+ PKIX_TEST_DECREF_BC(altNameOidCert);
+ PKIX_TEST_DECREF_BC(altNameOidCert_diff);
+ PKIX_TEST_DECREF_BC(altNameMultipleCert);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_cert <test-purpose> <data-central-dir> <data-dir>\n\n");
+}
+
+int
+test_cert(int argc, char *argv[])
+{
+
+ PKIX_PL_Cert *goodObject = NULL;
+ PKIX_PL_Cert *equalObject = NULL;
+ PKIX_PL_Cert *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ char *dataCentralDir = NULL;
+ char *dataDir = NULL;
+ char *goodInput = "yassir2bcn";
+ char *diffInput = "nss2alice";
+
+ char *expectedAscii =
+ "[\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 37bc66ec\n"
+ "\tIssuer: CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tSubject: OU=bcn,OU=east,O=sun,C=us\n"
+ "\tValidity: [From: Thu Aug 19, 1999\n"
+ /* "\tValidity: [From: Thu Aug 19 16:19:56 1999\n" */
+ "\t To: Fri Aug 18, 2000]\n"
+ /* "\t To: Fri Aug 18 16:19:56 2000]\n" */
+ "\tSubjectAltNames: (null)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (2.5.29.15, 2.5.29.19)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: CA(0)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "\tAuthorityInfoAccess: (null)\n"
+ "\tSubjectInfoAccess: (null)\n"
+ "\tCacheFlag: 0\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Cert");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 3 + j) {
+ printUsage();
+ return (0);
+ }
+
+ dataCentralDir = argv[2 + j];
+ dataDir = argv[3 + j];
+
+ createCerts(dataCentralDir,
+ goodInput,
+ diffInput,
+ &goodObject,
+ &equalObject,
+ &diffObject);
+
+ testToStringHelper((PKIX_PL_Object *)goodObject, expectedAscii, plContext);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ expectedAscii,
+ Cert,
+ PKIX_TRUE);
+
+ testVerifyKeyUsage(dataCentralDir, dataDir, goodObject);
+
+ testGetExtendedKeyUsage(dataCentralDir);
+ testGetKeyIdentifiers(dataCentralDir, goodObject);
+
+ testGetVersion(goodObject);
+ testGetSerialNumber(goodObject, equalObject, diffObject);
+
+ testGetSubject(goodObject, equalObject, diffObject);
+ testGetIssuer(goodObject, equalObject, diffObject);
+
+ testGetSubjectAltNames(dataCentralDir);
+ testGetCriticalExtensionOIDs(dataCentralDir, goodObject);
+
+ testGetSubjectPublicKey(goodObject, equalObject, diffObject);
+ testGetSubjectPublicKeyAlgId(goodObject);
+ testMakeInheritedDSAPublicKey(dataCentralDir);
+
+ testCheckValidity(goodObject, diffObject);
+
+ testBasicConstraints_GetCAFlag(dataCentralDir);
+ testBasicConstraints_GetPathLenConstraint(dataCentralDir);
+ testGetBasicConstraints(dataCentralDir);
+
+ /* Basic Policy Processing */
+ testGetPolicyInformation(dataDir);
+ testCertPolicy_GetPolicyId(dataDir);
+ testCertPolicy_GetPolQualifiers(dataDir);
+ testPolicyQualifier_GetPolicyQualifierId(dataDir);
+ testPolicyQualifier_GetQualifier(dataDir);
+ testAreCertPoliciesCritical(dataCentralDir, dataDir);
+
+ /* Advanced Policy Processing */
+ testCertPolicyConstraints(dataDir);
+ testCertPolicyMaps(dataDir);
+
+ testNameConstraints(dataDir);
+
+ testVerifySignature(dataCentralDir);
+
+ testDestroy(goodObject, equalObject, diffObject);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Cert");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_crl.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_crl.c
new file mode 100644
index 000000000..6372c7a37
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_crl.c
@@ -0,0 +1,302 @@
+/* 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/. */
+/*
+ * test_crl.c
+ *
+ * Test CRL Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createCRLs(
+ char *dataDir,
+ char *goodInput,
+ char *diffInput,
+ PKIX_PL_CRL **goodObject,
+ PKIX_PL_CRL **equalObject,
+ PKIX_PL_CRL **diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CRL_Create <goodObject>");
+ *goodObject = createCRL(dataDir, goodInput, plContext);
+
+ subTest("PKIX_PL_CRL_Create <equalObject>");
+ *equalObject = createCRL(dataDir, goodInput, plContext);
+
+ subTest("PKIX_PL_CRL_Create <diffObject>");
+ *diffObject = createCRL(dataDir, diffInput, plContext);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCRLEntryForSerialNumber(
+ PKIX_PL_CRL *goodObject)
+{
+ PKIX_PL_BigInt *bigInt;
+ PKIX_PL_String *bigIntString = NULL;
+ PKIX_PL_CRLEntry *crlEntry = NULL;
+ PKIX_PL_String *crlEntryString = NULL;
+ char *snAscii = "3039";
+ char *expectedAscii =
+ "\n\t[\n"
+ "\tSerialNumber: 3039\n"
+ "\tReasonCode: 257\n"
+ "\tRevocationDate: Fri Jan 07, 2005\n"
+ /* "\tRevocationDate: Fri Jan 07 15:09:10 2005\n" */
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\t]\n\t";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CRL_GetCRLEntryForSerialNumber");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ snAscii,
+ PL_strlen(snAscii),
+ &bigIntString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create(
+ bigIntString,
+ &bigInt,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_GetCRLEntryForSerialNumber(
+ goodObject, bigInt, &crlEntry, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString(
+ (PKIX_PL_Object *)crlEntry,
+ &crlEntryString,
+ plContext));
+
+ testToStringHelper((PKIX_PL_Object *)crlEntryString,
+ expectedAscii, plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(bigIntString);
+ PKIX_TEST_DECREF_AC(bigInt);
+ PKIX_TEST_DECREF_AC(crlEntryString);
+ PKIX_TEST_DECREF_AC(crlEntry);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetIssuer(
+ PKIX_PL_CRL *goodObject,
+ PKIX_PL_CRL *equalObject,
+ PKIX_PL_CRL *diffObject)
+{
+ PKIX_PL_X500Name *goodIssuer = NULL;
+ PKIX_PL_X500Name *equalIssuer = NULL;
+ PKIX_PL_X500Name *diffIssuer = NULL;
+ char *expectedAscii = "CN=hanfeiyu,O=sun,C=us";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CRL_GetIssuer");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_CRL_GetIssuer(goodObject, &goodIssuer, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_CRL_GetIssuer(equalObject, &equalIssuer, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_CRL_GetIssuer(diffObject, &diffIssuer, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodIssuer,
+ equalIssuer,
+ diffIssuer,
+ expectedAscii,
+ X500Name,
+ PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodIssuer);
+ PKIX_TEST_DECREF_AC(equalIssuer);
+ PKIX_TEST_DECREF_AC(diffIssuer);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCritExtensionsAbsent(PKIX_PL_CRL *crl)
+{
+ PKIX_List *oidList = NULL;
+ PKIX_UInt32 numOids = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_GetCriticalExtensionOIDs(crl, &oidList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(oidList, &numOids, plContext));
+ if (numOids != 0) {
+ pkixTestErrorMsg = "unexpected mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(oidList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCriticalExtensionOIDs(PKIX_PL_CRL *goodObject)
+{
+ subTest("PKIX_PL_CRL_GetCriticalExtensionOIDs "
+ "<0 element>");
+ testCritExtensionsAbsent(goodObject);
+}
+
+static void
+testVerifySignature(char *dataCentralDir, PKIX_PL_CRL *crl)
+{
+ PKIX_PL_Cert *firstCert = NULL;
+ PKIX_PL_Cert *secondCert = NULL;
+ PKIX_PL_PublicKey *firstPubKey = NULL;
+ PKIX_PL_PublicKey *secondPubKey = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Create <hanfeiyu2hanfeiyu>");
+ firstCert = createCert(dataCentralDir, "hanfeiyu2hanfeiyu", plContext);
+
+ subTest("PKIX_PL_Cert_Create <hy2hy-bc0>");
+ secondCert = createCert(dataCentralDir, "hy2hy-bc0", plContext);
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey <hanfeiyu2hanfeiyu>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(firstCert, &firstPubKey, plContext));
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey <hanfei2hanfei>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(secondCert, &secondPubKey, plContext));
+
+ subTest("PKIX_PL_CRL_VerifySignature <positive>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_VerifySignature(crl, firstPubKey, plContext));
+
+ subTest("PKIX_PL_CRL_VerifySignature <negative>");
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_CRL_VerifySignature(crl, secondPubKey, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(firstCert);
+ PKIX_TEST_DECREF_AC(secondCert);
+ PKIX_TEST_DECREF_AC(firstPubKey);
+ PKIX_TEST_DECREF_AC(secondPubKey);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_crl <test-purpose> <data-central-dir>\n\n");
+}
+
+/* Functional tests for CRL public functions */
+
+int
+test_crl(int argc, char *argv[])
+{
+ PKIX_PL_CRL *goodObject = NULL;
+ PKIX_PL_CRL *equalObject = NULL;
+ PKIX_PL_CRL *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ char *dataCentralDir = NULL;
+ char *goodInput = "crlgood.crl";
+ char *diffInput = "crldiff.crl";
+ char *expectedAscii =
+ "[\n"
+ "\tVersion: v2\n"
+ "\tIssuer: CN=hanfeiyu,O=sun,C=us\n"
+ "\tUpdate: [Last: Fri Jan 07, 2005\n"
+ /* "\tUpdate: [Last: Fri Jan 07 15:09:10 2005\n" */
+ "\t Next: Sat Jan 07, 2006]\n"
+ /* "\t Next: Sat Jan 07 15:09:10 2006]\n" */
+ "\tSignatureAlgId: 1.2.840.10040.4.3\n"
+ "\tCRL Number : (null)\n"
+ "\n\tEntry List: (\n"
+ "\t[\n"
+ "\tSerialNumber: 010932\n"
+ "\tReasonCode: 260\n"
+ "\tRevocationDate: Fri Jan 07, 2005\n"
+ /* "\tRevocationDate: Fri Jan 07 15:09:10 2005\n" */
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\t]\n\t"
+ ", "
+ "\n\t[\n"
+ "\tSerialNumber: 3039\n"
+ "\tReasonCode: 257\n"
+ "\tRevocationDate: Fri Jan 07, 2005\n"
+ /* "\tRevocationDate: Fri Jan 07 15:09:10 2005\n" */
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\t]\n\t"
+ ")"
+ "\n\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "]\n";
+ /* Note XXX serialnumber and reasoncode need debug */
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("CRL");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 3 + j) {
+ printUsage();
+ return (0);
+ }
+
+ dataCentralDir = argv[2 + j];
+
+ createCRLs(dataCentralDir,
+ goodInput,
+ diffInput,
+ &goodObject,
+ &equalObject,
+ &diffObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ expectedAscii,
+ CRL,
+ PKIX_TRUE);
+
+ testGetIssuer(goodObject, equalObject, diffObject);
+
+ testGetCriticalExtensionOIDs(goodObject);
+
+ testGetCRLEntryForSerialNumber(goodObject);
+
+ testVerifySignature(dataCentralDir, goodObject);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodObject);
+ PKIX_TEST_DECREF_AC(equalObject);
+ PKIX_TEST_DECREF_AC(diffObject);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CRL");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_crlentry.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_crlentry.c
new file mode 100644
index 000000000..30a008b4c
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_crlentry.c
@@ -0,0 +1,208 @@
+/* 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/. */
+/*
+ * test_crlentry.c
+ *
+ * Test CRLENTRY Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createCRLEntries(
+ char *dataDir,
+ char *crlInput,
+ PKIX_PL_CRL **pCrl,
+ PKIX_PL_CRLEntry **goodObject,
+ PKIX_PL_CRLEntry **equalObject,
+ PKIX_PL_CRLEntry **diffObject)
+{
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_PL_BigInt *firstSNBigInt = NULL;
+ PKIX_PL_BigInt *secondSNBigInt = NULL;
+ PKIX_PL_String *firstSNString = NULL;
+ PKIX_PL_String *secondSNString = NULL;
+ char *firstSNAscii = "010932";
+ char *secondSNAscii = "3039";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CRL_Create <crl>");
+ crl = createCRL(dataDir, crlInput, plContext);
+
+ subTest("PKIX_PL_CRL_GetCRLEntryForSerialNumber");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ firstSNAscii,
+ PL_strlen(firstSNAscii),
+ &firstSNString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create(
+ firstSNString,
+ &firstSNBigInt,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_GetCRLEntryForSerialNumber(
+ crl, firstSNBigInt, goodObject, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_GetCRLEntryForSerialNumber(
+ crl, firstSNBigInt, equalObject, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ secondSNAscii,
+ PL_strlen(secondSNAscii),
+ &secondSNString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create(
+ secondSNString,
+ &secondSNBigInt,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_GetCRLEntryForSerialNumber(
+ crl, secondSNBigInt, diffObject, plContext));
+
+ *pCrl = crl;
+
+cleanup:
+ PKIX_TEST_DECREF_AC(firstSNBigInt);
+ PKIX_TEST_DECREF_AC(secondSNBigInt);
+ PKIX_TEST_DECREF_AC(firstSNString);
+ PKIX_TEST_DECREF_AC(secondSNString);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetReasonCode(
+ PKIX_PL_CRLEntry *goodObject)
+{
+ PKIX_Int32 reasonCode = 0;
+ PKIX_Int32 expectedReasonCode = 260;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CRLEntry_GetCRLEntryReasonCode");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRLEntry_GetCRLEntryReasonCode(
+ goodObject, &reasonCode, plContext));
+
+ if (reasonCode != expectedReasonCode) {
+ testError("unexpected value of CRL Entry Reason Code");
+ (void)printf("Actual value:\t%d\n", reasonCode);
+ (void)printf("Expected value:\t%d\n", expectedReasonCode);
+ goto cleanup;
+ }
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCritExtensionsAbsent(PKIX_PL_CRLEntry *crlEntry)
+{
+ PKIX_List *oidList = NULL;
+ PKIX_UInt32 numOids = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRLEntry_GetCriticalExtensionOIDs(crlEntry, &oidList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(oidList, &numOids, plContext));
+ if (numOids != 0) {
+ pkixTestErrorMsg = "unexpected mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(oidList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCriticalExtensionOIDs(PKIX_PL_CRLEntry *goodObject)
+{
+ subTest("PKIX_PL_CRL_GetCriticalExtensionOIDs "
+ "<CritExtensionsAbsent>");
+ testCritExtensionsAbsent(goodObject);
+}
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_crlentry <data-dir>\n\n");
+}
+
+/* Functional tests for CRLENTRY public functions */
+
+int
+test_crlentry(int argc, char *argv[])
+{
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_PL_CRLEntry *goodObject = NULL;
+ PKIX_PL_CRLEntry *equalObject = NULL;
+ PKIX_PL_CRLEntry *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ char *dataDir = NULL;
+ char *goodInput = "crlgood.crl";
+ char *expectedAscii =
+ "\n\t[\n"
+ "\tSerialNumber: 010932\n"
+ "\tReasonCode: 260\n"
+ "\tRevocationDate: Fri Jan 07 15:09:10 2005\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\t]\n\t";
+
+ /* Note XXX serialnumber and reasoncode need debug */
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("CRLEntry");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 1 + j) {
+ printUsage();
+ return (0);
+ }
+
+ dataDir = argv[1 + j];
+
+ createCRLEntries(dataDir, goodInput, &crl, &goodObject, &equalObject, &diffObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ NULL, /* expectedAscii, */
+ CRLENTRY,
+ PKIX_TRUE);
+
+ testGetReasonCode(goodObject);
+
+ testGetCriticalExtensionOIDs(goodObject);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(crl);
+ PKIX_TEST_DECREF_AC(goodObject);
+ PKIX_TEST_DECREF_AC(equalObject);
+ PKIX_TEST_DECREF_AC(diffObject);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CRLEntry");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_date.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_date.c
new file mode 100644
index 000000000..4fb3718c1
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_date.c
@@ -0,0 +1,106 @@
+/* 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/. */
+/*
+ * test_date.c
+ *
+ * Test Date Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createDates(char *goodInput, char *diffInput,
+ PKIX_PL_Date **goodDate,
+ PKIX_PL_Date **equalDate,
+ PKIX_PL_Date **diffDate)
+{
+
+ subTest("PKIX_PL_Date_Create <goodDate>");
+ *goodDate = createDate(goodInput, plContext);
+
+ subTest("PKIX_PL_Date_Create <equalDate>");
+ *equalDate = createDate(goodInput, plContext);
+
+ subTest("PKIX_PL_Date_Create <diffDate>");
+ *diffDate = createDate(diffInput, plContext);
+}
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Date_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDate(char *goodInput, char *diffInput)
+{
+
+ PKIX_PL_Date *goodDate = NULL;
+ PKIX_PL_Date *equalDate = NULL;
+ PKIX_PL_Date *diffDate = NULL;
+
+ /*
+ * The ASCII rep of the date will vary by platform and locale
+ * This particular string was generated on a SPARC running Solaris 9
+ * in an English locale
+ */
+ /* char *expectedAscii = "Mon Mar 29 08:48:47 2004"; */
+ char *expectedAscii = "Mon Mar 29, 2004";
+
+ PKIX_TEST_STD_VARS();
+
+ createDates(goodInput, diffInput,
+ &goodDate, &equalDate, &diffDate);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodDate, equalDate, diffDate, expectedAscii, Date, PKIX_TRUE);
+
+ testDestroy(goodDate, equalDate, diffDate);
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_date(int argc, char *argv[])
+{
+
+ char *goodInput = NULL;
+ char *diffInput = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Date");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ goodInput = "040329134847Z";
+ diffInput = "050329135847Z";
+ testDate(goodInput, diffInput);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Date");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_generalname.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_generalname.c
new file mode 100644
index 000000000..9719cd99c
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_generalname.c
@@ -0,0 +1,123 @@
+/* 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/. */
+/*
+ * test_generalname.c
+ *
+ * Test GeneralName Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createGeneralNames(PKIX_UInt32 nameType, char *goodInput, char *diffInput,
+ PKIX_PL_GeneralName **goodName,
+ PKIX_PL_GeneralName **equalName,
+ PKIX_PL_GeneralName **diffName)
+{
+
+ subTest("PKIX_PL_GeneralName_Create <goodName>");
+ *goodName = createGeneralName(nameType, goodInput, plContext);
+
+ subTest("PKIX_PL_GeneralName_Create <equalName>");
+ *equalName = createGeneralName(nameType, goodInput, plContext);
+
+ subTest("PKIX_PL_GeneralName_Create <diffName>");
+ *diffName = createGeneralName(nameType, diffInput, plContext);
+}
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_GeneralName_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testNameType(PKIX_UInt32 nameType, char *goodInput, char *diffInput, char *expectedAscii)
+{
+
+ PKIX_PL_GeneralName *goodName = NULL;
+ PKIX_PL_GeneralName *equalName = NULL;
+ PKIX_PL_GeneralName *diffName = NULL;
+
+ createGeneralNames(nameType, goodInput, diffInput,
+ &goodName, &equalName, &diffName);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodName,
+ equalName,
+ diffName,
+ expectedAscii,
+ GeneralName,
+ PKIX_TRUE);
+
+ testDestroy(goodName, equalName, diffName);
+}
+
+int
+test_generalname(int argc, char *argv[])
+{
+
+ char *goodInput = NULL;
+ char *diffInput = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("GeneralName");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ goodInput = "john@sun.com";
+ diffInput = "john@labs.com";
+ testNameType(PKIX_RFC822_NAME, goodInput, diffInput, goodInput);
+
+ goodInput = "example1.com";
+ diffInput = "ex2.net";
+ testNameType(PKIX_DNS_NAME, goodInput, diffInput, goodInput);
+
+ goodInput = "cn=yassir, ou=labs, o=sun, c=us";
+ diffInput = "cn=alice, ou=labs, o=sun, c=us";
+ testNameType(PKIX_DIRECTORY_NAME,
+ goodInput,
+ diffInput,
+ "CN=yassir,OU=labs,O=sun,C=us");
+
+ goodInput = "http://example1.com";
+ diffInput = "http://ex2.net";
+ testNameType(PKIX_URI_NAME, goodInput, diffInput, goodInput);
+
+ goodInput = "1.2.840.11";
+ diffInput = "1.2.840.115349";
+ testNameType(PKIX_OID_NAME, goodInput, diffInput, goodInput);
+
+/*
+ * We don't support creating PKIX_EDIPARTY_NAME,
+ * PKIX_IP_NAME, OTHER_NAME, X400_ADDRESS from strings
+ */
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("GeneralName");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_nameconstraints.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_nameconstraints.c
new file mode 100644
index 000000000..636ba3ead
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_nameconstraints.c
@@ -0,0 +1,127 @@
+/* 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/. */
+/*
+ * test_nameconstraints.c
+ *
+ * Test CERT Name Constraints Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static char *
+catDirName(char *platform, char *dir, void *plContext)
+{
+ char *pathName = NULL;
+ PKIX_UInt32 dirLen;
+ PKIX_UInt32 platformLen;
+
+ PKIX_TEST_STD_VARS();
+
+ dirLen = PL_strlen(dir);
+ platformLen = PL_strlen(platform);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc(platformLen +
+ dirLen +
+ 2,
+ (void **)&pathName, plContext));
+
+ PL_strcpy(pathName, platform);
+ PL_strcat(pathName, "/");
+ PL_strcat(pathName, dir);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (pathName);
+}
+
+static void
+testNameConstraints(char *dataDir)
+{
+ char *goodPname = "nameConstraintsDN5CACert.crt";
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_CertNameConstraints *goodNC = NULL;
+ char *expectedAscii =
+ "[\n"
+ "\t\tPermitted Name: (OU=permittedSubtree1,"
+ "O=Test Certificates,C=US)\n"
+ "\t\tExcluded Name: (OU=excludedSubtree1,"
+ "OU=permittedSubtree1,O=Test Certificates,C=US)\n"
+ "\t]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CertNameConstraints");
+
+ goodCert = createCert(dataDir, goodPname, plContext);
+
+ subTest("PKIX_PL_Cert_GetNameConstraints");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(goodCert, &goodNC, plContext));
+
+ testToStringHelper((PKIX_PL_Object *)goodNC, expectedAscii, plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodNC);
+ PKIX_TEST_DECREF_AC(goodCert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_nameconstraints <test-purpose>"
+ " <data-dir> <platform-prefix>\n\n");
+}
+
+/* Functional tests for CRL public functions */
+
+int
+test_nameconstraints(int argc, char *argv[])
+{
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ char *platformDir = NULL;
+ char *dataDir = NULL;
+ char *combinedDir = NULL;
+
+ /* Note XXX serialnumber and reasoncode need debug */
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("NameConstraints");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 3 + j) {
+ printUsage();
+ return (0);
+ }
+
+ dataDir = argv[2 + j];
+ platformDir = argv[3 + j];
+ combinedDir = catDirName(platformDir, dataDir, plContext);
+
+ testNameConstraints(combinedDir);
+
+cleanup:
+
+ pkixTestErrorResult = PKIX_PL_Free(combinedDir, plContext);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("NameConstraints");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_subjectinfoaccess.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_subjectinfoaccess.c
new file mode 100644
index 000000000..8f2ff9ec7
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_subjectinfoaccess.c
@@ -0,0 +1,121 @@
+/* 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/. */
+/*
+ * test_subjectinfoaccess.c
+ *
+ * Test Subject InfoAccess Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+int
+test_subjectinfoaccess(int argc, char *argv[])
+{
+
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_Cert *certDiff = NULL;
+ PKIX_List *aiaList = NULL;
+ PKIX_List *siaList = NULL;
+ PKIX_PL_InfoAccess *sia = NULL;
+ PKIX_PL_InfoAccess *siaDup = NULL;
+ PKIX_PL_InfoAccess *siaDiff = NULL;
+ PKIX_PL_GeneralName *location = NULL;
+ char *certPathName = NULL;
+ char *dirName = NULL;
+ PKIX_UInt32 method = 0;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 size, i;
+ PKIX_UInt32 j = 0;
+ char *expectedAscii = "[method:caRepository, "
+ "location:http://betty.nist.gov/pathdiscoverytestsuite/"
+ "p7cfiles/IssuedByTrustAnchor1.p7c]";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("SubjectInfoAccess");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 5 + j) {
+ printf("Usage: %s <test-purpose> <cert> <diff-cert>\n", argv[0]);
+ }
+
+ dirName = argv[2 + j];
+ certPathName = argv[3 + j];
+
+ subTest("Creating Cert with Subject Info Access");
+ cert = createCert(dirName, certPathName, plContext);
+
+ certPathName = argv[4 + j];
+
+ subTest("Creating Cert with Subject Info Access");
+ certDiff = createCert(dirName, certPathName, plContext);
+
+ subTest("Getting Subject Info Access");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectInfoAccess(cert, &siaList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(siaList, &size, plContext));
+
+ if (size != 1) {
+ pkixTestErrorMsg = "unexpected number of AIA";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(siaList, 0, (PKIX_PL_Object **)&sia, plContext));
+
+ subTest("PKIX_PL_InfoAccess_GetMethod");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_InfoAccess_GetMethod(sia, &method, plContext));
+ if (method != PKIX_INFOACCESS_CA_REPOSITORY) {
+ pkixTestErrorMsg = "unexpected method of AIA";
+ goto cleanup;
+ }
+
+ subTest("PKIX_PL_InfoAccess_GetLocation");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_InfoAccess_GetLocation(sia, &location, plContext));
+ if (!location) {
+ pkixTestErrorMsg = "Cannot get AIA location";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(siaList, 0, (PKIX_PL_Object **)&siaDup, plContext));
+
+ subTest("Getting Authority Info Access as difference comparison");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetAuthorityInfoAccess(certDiff, &aiaList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(aiaList, &size, plContext));
+
+ if (size != 1) {
+ pkixTestErrorMsg = "unexpected number of AIA";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(aiaList, 0, (PKIX_PL_Object **)&siaDiff, plContext));
+
+ subTest("Checking: Equal, Hash and ToString");
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(sia, siaDup, siaDiff, expectedAscii, InfoAccess, PKIX_FALSE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(location);
+ PKIX_TEST_DECREF_AC(sia);
+ PKIX_TEST_DECREF_AC(siaDup);
+ PKIX_TEST_DECREF_AC(siaDiff);
+ PKIX_TEST_DECREF_AC(aiaList);
+ PKIX_TEST_DECREF_AC(siaList);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(certDiff);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Subjectinfoaccess");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_x500name.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_x500name.c
new file mode 100644
index 000000000..91ff63fd0
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_x500name.c
@@ -0,0 +1,169 @@
+/* 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/. */
+/*
+ * test_x500name.c
+ *
+ * Test X500Name Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static PKIX_PL_X500Name *
+createX500Name(char *asciiName, PKIX_Boolean expectedToPass)
+{
+
+ PKIX_PL_X500Name *x500Name = NULL;
+ PKIX_PL_String *plString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, asciiName, 0, &plString, plContext));
+
+ if (expectedToPass) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create(plString, &x500Name, plContext));
+ } else {
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_X500Name_Create(plString, &x500Name, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(plString);
+
+ PKIX_TEST_RETURN();
+
+ return (x500Name);
+}
+
+static void
+createX500Names(char *goodInput, char *diffInput, char *diffInputMatch,
+ PKIX_PL_X500Name **goodObject,
+ PKIX_PL_X500Name **equalObject,
+ PKIX_PL_X500Name **diffObject,
+ PKIX_PL_X500Name **diffObjectMatch)
+{
+ char *badAscii = "cn=yas#sir,ou=labs,o=sun,c=us";
+ PKIX_PL_X500Name *badObject = NULL;
+
+ subTest("PKIX_PL_X500Name_Create <goodObject>");
+ *goodObject = createX500Name(goodInput, PKIX_TRUE);
+
+ subTest("PKIX_PL_X500Name_Create <equalObject>");
+ *equalObject = createX500Name(goodInput, PKIX_TRUE);
+
+ subTest("PKIX_PL_X500Name_Create <diffObject>");
+ *diffObject = createX500Name(diffInput, PKIX_TRUE);
+
+ subTest("PKIX_PL_X500Name_Create <diffObjectMatch>");
+ *diffObjectMatch = createX500Name(diffInputMatch, PKIX_TRUE);
+
+ subTest("PKIX_PL_X500Name_Create <negative>");
+ badObject = createX500Name(badAscii, PKIX_FALSE);
+}
+
+static void
+testMatchHelper(PKIX_PL_X500Name *goodName, PKIX_PL_X500Name *otherName, PKIX_Boolean match)
+{
+ PKIX_Boolean cmpResult;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Match(goodName,
+ otherName,
+ &cmpResult,
+ plContext));
+
+ if ((match && !cmpResult) || (!match && cmpResult)) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", cmpResult);
+ (void)printf("Expected value:\t%d\n", match);
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testMatch(void *goodObject, void *diffObject, void *diffObjectMatch)
+{
+ subTest("PKIX_PL_X500Name_Match <match>");
+ testMatchHelper((PKIX_PL_X500Name *)diffObject,
+ (PKIX_PL_X500Name *)diffObjectMatch,
+ PKIX_TRUE);
+
+ subTest("PKIX_PL_X500Name_Match <non-match>");
+ testMatchHelper((PKIX_PL_X500Name *)goodObject,
+ (PKIX_PL_X500Name *)diffObject,
+ PKIX_FALSE);
+}
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject, void *diffObjectMatch)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_X500Name_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+ PKIX_TEST_DECREF_BC(diffObjectMatch);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_x500name(int argc, char *argv[])
+{
+
+ PKIX_PL_X500Name *goodObject = NULL;
+ PKIX_PL_X500Name *equalObject = NULL;
+ PKIX_PL_X500Name *diffObject = NULL;
+ PKIX_PL_X500Name *diffObjectMatch = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ /* goodInput is encoded in PKIX_ESCASCII */
+ char *goodInput = "cn=Strau&#x00Df;,ou=labs,o=sun,c=us";
+ char *diffInput = "cn=steve,ou=labs,o=sun,c=us";
+ char *diffInputMatch = "Cn=SteVe,Ou=lABs,o=SUn,c=uS";
+ char *expectedAscii = "CN=Strau&#x00DF;,OU=labs,O=sun,C=us";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("X500Name");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ createX500Names(goodInput, diffInput, diffInputMatch,
+ &goodObject, &equalObject, &diffObject, &diffObjectMatch);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ expectedAscii,
+ X500Name,
+ PKIX_TRUE);
+
+ testMatch(goodObject, diffObject, diffObjectMatch);
+
+ testDestroy(goodObject, equalObject, diffObject, diffObjectMatch);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("X500Name");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/Makefile b/security/nss/cmd/libpkix/pkix_pl/system/Makefile
new file mode 100755
index 000000000..09ca5f1c6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/manifest.mn b/security/nss/cmd/libpkix/pkix_pl/system/manifest.mn
new file mode 100755
index 000000000..edbf0cda8
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/manifest.mn
@@ -0,0 +1,38 @@
+#
+# 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/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# test_rwlock.c is taken out, need to link to libpkix internals
+#
+# The test is using LIBPKIX PL call directly, which violates our
+# code convention.
+#
+CSRCS = test_bigint.c \
+ test_bytearray.c \
+ test_hashtable.c \
+ test_mem.c \
+ test_mutex.c \
+ test_mutex2.c \
+ test_mutex3.c \
+ test_monitorlock.c \
+ test_object.c \
+ test_oid.c \
+ stress_test.c \
+ test_string.c \
+ test_string2.c \
+ $(NULL)
+
+
+LIBRARY_NAME=pkixtoolsys
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/stress_test.c b/security/nss/cmd/libpkix/pkix_pl/system/stress_test.c
new file mode 100644
index 000000000..839dc068d
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/stress_test.c
@@ -0,0 +1,146 @@
+/* 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/. */
+/*
+ * stress_test.c
+ *
+ * Creates and deletes many objects
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+int
+stress_test(int argc, char *argv[])
+{
+
+ PKIX_UInt32 i, k, length, hashcode;
+ PKIX_UInt32 size = 17576;
+ char temp[4];
+ PKIX_Boolean result;
+ PKIX_PL_String *strings[17576], *tempString;
+ PKIX_PL_String *utf16strings[17576];
+ PKIX_PL_ByteArray *byteArrays[17576];
+ void *dest;
+ PKIX_PL_HashTable *ht = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Stress Test");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ---------------------------- */
+ subTest("Create every three letter String");
+
+ for (i = 0; i < 26; i++)
+ for (j = 0; j < 26; j++)
+ for (k = 0; k < 26; k++) {
+ temp[0] = (char)('a' + i);
+ temp[1] = (char)('a' + j);
+ temp[2] = (char)('a' + k);
+ temp[3] = 0;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, temp, 3,
+ &strings[26 * (i * 26 + j) + k],
+ plContext));
+ }
+
+ /* ---------------------------- */
+ subTest("Create a bytearray from each string's UTF-16 encoding");
+ for (i = 0; i < size; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(strings[i],
+ PKIX_UTF16,
+ &dest,
+ &length,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create(dest, length, &byteArrays[i], plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ }
+
+ /* ---------------------------- */
+ subTest("Create a copy string from each bytearray");
+ for (i = 0; i < size; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_UTF16, *(void **)byteArrays[i], 6,
+ &utf16strings[i], plContext));
+ }
+
+ /* ---------------------------- */
+ subTest("Compare each original string with the copy");
+ for (i = 0; i < size; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)strings[i],
+ (PKIX_PL_Object *)utf16strings[i],
+ &result,
+ plContext));
+ if (result == 0)
+ testError("Strings do not match");
+ }
+
+ /* ---------------------------- */
+ subTest("Put each string into a Hashtable");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Create(size /
+ 2,
+ 0, &ht, plContext));
+
+ for (i = 0; i < size; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Hashcode((PKIX_PL_Object *)strings[i],
+ &hashcode,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht,
+ (void *)&hashcode,
+ (void *)strings[i],
+ plContext));
+ }
+
+ /* ---------------------------- */
+ subTest("Compare each copy string with the hashtable entries ");
+ for (i = 0; i < size; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Hashcode((PKIX_PL_Object *)utf16strings[i],
+ &hashcode,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht,
+ (void *)&hashcode,
+ (PKIX_PL_Object **)&tempString,
+ plContext));
+
+ if (tempString == NULL)
+ testError("String not found in hashtable");
+ else {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)tempString,
+ (PKIX_PL_Object *)utf16strings[i],
+ &result,
+ plContext));
+ if (result == 0)
+ testError("Strings do not match");
+ PKIX_TEST_DECREF_BC(tempString);
+ }
+ }
+
+cleanup:
+
+ /* ---------------------------- */
+ subTest("Destroy All Objects");
+
+ PKIX_TEST_DECREF_AC(ht);
+
+ for (i = 0; i < size; i++) {
+ PKIX_TEST_DECREF_AC(strings[i]);
+ PKIX_TEST_DECREF_AC(utf16strings[i]);
+ PKIX_TEST_DECREF_AC(byteArrays[i]);
+ }
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Stress Test");
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_bigint.c b/security/nss/cmd/libpkix/pkix_pl/system/test_bigint.c
new file mode 100644
index 000000000..85b98eee3
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_bigint.c
@@ -0,0 +1,190 @@
+/* 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/. */
+/*
+ * test_bigint.c
+ *
+ * Tests BigInt Types
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createBigInt(
+ PKIX_PL_BigInt **bigInts,
+ char *bigIntAscii,
+ PKIX_Boolean errorHandling)
+{
+ PKIX_PL_String *bigIntString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ bigIntAscii,
+ PL_strlen(bigIntAscii),
+ &bigIntString,
+ plContext));
+
+ if (errorHandling) {
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_BigInt_Create(bigIntString,
+ bigInts,
+ plContext));
+ } else {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create(bigIntString,
+ bigInts,
+ plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(bigIntString);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testToString(
+ PKIX_PL_BigInt *bigInt,
+ char *expAscii)
+{
+ PKIX_PL_String *bigIntString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)bigInt,
+ &bigIntString, plContext));
+
+ temp = PKIX_String2ASCII(bigIntString, plContext);
+ if (temp == plContext) {
+ testError("PKIX_String2Ascii failed");
+ goto cleanup;
+ }
+
+ if (PL_strcmp(temp, expAscii) != 0) {
+ (void)printf("\tBigInt ToString: %s %s\n", temp, expAscii);
+ testError("Output string does not match source");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(bigIntString);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCompare(
+ PKIX_PL_BigInt *firstBigInt,
+ PKIX_PL_BigInt *secondBigInt,
+ PKIX_Int32 *cmpResult)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare((PKIX_PL_Object *)firstBigInt,
+ (PKIX_PL_Object *)secondBigInt,
+ cmpResult, plContext));
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_BigInt *bigInt)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(bigInt);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_bigint(int argc, char *argv[])
+{
+
+ PKIX_UInt32 size = 4, badSize = 3, i = 0;
+ PKIX_PL_BigInt *testBigInt[4] = { NULL };
+ PKIX_Int32 cmpResult;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ char *bigIntValue[4] =
+ {
+ "03",
+ "ff",
+ "1010101010101010101010101010101010101010",
+ "1010101010101010101010101010101010101010",
+ };
+
+ char *badValue[3] = { "00ff", "fff", "-ff" };
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("BigInts");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ for (i = 0; i < badSize; i++) {
+ subTest("PKIX_PL_BigInt_Create <error_handling>");
+ createBigInt(&testBigInt[i], badValue[i], PKIX_TRUE);
+ }
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_BigInt_Create");
+ createBigInt(&testBigInt[i], bigIntValue[i], PKIX_FALSE);
+ }
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(testBigInt[2],
+ testBigInt[3],
+ testBigInt[1],
+ bigIntValue[2],
+ BigInt,
+ PKIX_TRUE);
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_BigInt_ToString");
+ testToString(testBigInt[i], bigIntValue[i]);
+ }
+
+ subTest("PKIX_PL_BigInt_Compare <gt>");
+ testCompare(testBigInt[2], testBigInt[1], &cmpResult);
+ if (cmpResult <= 0) {
+ testError("Invalid Result from String Compare");
+ }
+
+ subTest("PKIX_PL_BigInt_Compare <lt>");
+ testCompare(testBigInt[1], testBigInt[2], &cmpResult);
+ if (cmpResult >= 0) {
+ testError("Invalid Result from String Compare");
+ }
+
+ subTest("PKIX_PL_BigInt_Compare <eq>");
+ testCompare(testBigInt[2], testBigInt[3], &cmpResult);
+ if (cmpResult != 0) {
+ testError("Invalid Result from String Compare");
+ }
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_BigInt_Destroy");
+ testDestroy(testBigInt[i]);
+ }
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ endTests("BigInt");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_bytearray.c b/security/nss/cmd/libpkix/pkix_pl/system/test_bytearray.c
new file mode 100644
index 000000000..402685b59
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_bytearray.c
@@ -0,0 +1,231 @@
+/* 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/. */
+/*
+ * test_bytearray.c
+ *
+ * Tests ByteArray types.
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createByteArray(
+ PKIX_PL_ByteArray **byteArray,
+ char *bytes,
+ PKIX_UInt32 length)
+{
+ PKIX_TEST_STD_VARS();
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create((void *)bytes,
+ length,
+ byteArray,
+ plContext));
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testZeroLength(void)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ void *array = NULL;
+ PKIX_UInt32 length = 2;
+
+ PKIX_TEST_STD_VARS();
+
+ createByteArray(&byteArray, NULL, 0);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_GetLength(byteArray, &length, plContext));
+ if (length != 0) {
+ testError("Length should be zero");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_GetPointer(byteArray, &array, plContext));
+ if (array) {
+ testError("Array should be NULL");
+ }
+
+ testToStringHelper((PKIX_PL_Object *)byteArray, "[]", plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(byteArray);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testToString(
+ PKIX_PL_ByteArray *byteArray,
+ char *expAscii)
+{
+ PKIX_PL_String *string = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)byteArray,
+ &string, plContext));
+
+ temp = PKIX_String2ASCII(string, plContext);
+ if (temp == NULL) {
+ testError("PKIX_String2Ascii failed");
+ goto cleanup;
+ }
+
+ if (PL_strcmp(temp, expAscii) != 0) {
+ (void)printf("\tByteArray ToString: %s %s\n", temp, expAscii);
+ testError("Output string does not match source");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(string);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetLength(
+ PKIX_PL_ByteArray *byteArray,
+ PKIX_UInt32 expLength)
+{
+ PKIX_UInt32 arrayLength;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_GetLength(byteArray, &arrayLength, plContext));
+
+ if (arrayLength != expLength) {
+ (void)printf("\tByteArray GetLength: %d %d\n",
+ arrayLength, expLength);
+ testError("Incorrect Array Length returned");
+ }
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetPointer(
+ PKIX_PL_ByteArray *byteArray,
+ char *expBytes,
+ PKIX_UInt32 arrayLength)
+{
+ char *temp = NULL;
+ PKIX_UInt32 j;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_GetPointer(byteArray, (void **)&temp, plContext));
+
+ for (j = 0; j < arrayLength; j++) {
+ if (temp[j] != expBytes[j]) {
+ testError("Incorrect Byte Array Contents");
+ }
+ }
+
+cleanup:
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ PKIX_TEST_RETURN();
+}
+
+void
+testDestroy(
+ PKIX_PL_ByteArray *byteArray)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(byteArray);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_bytearray(int argc, char *argv[])
+{
+
+ PKIX_PL_ByteArray *testByteArray[4];
+
+ PKIX_UInt32 i, size = 4;
+ PKIX_UInt32 lengths[4] = { 5, 6, 1, 5 };
+ char dArray0[5] = { 1, 2, 3, 4, 5 };
+ unsigned char dArray1[6] = { 127, 128, 129, 254, 255, 0 };
+ char dArray2[1] = { 100 };
+ char dArray3[5] = { 1, 2, 3, 4, 5 };
+
+ char *expected[4] = {
+ "[001, 002, 003, 004, 005]",
+ "[127, 128, 129, 254, 255, 000]",
+ "[100]",
+ "[001, 002, 003, 004, 005]"
+ };
+
+ char *dummyArray[4];
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ dummyArray[0] = dArray0;
+ dummyArray[1] = (char *)dArray1;
+ dummyArray[2] = dArray2;
+ dummyArray[3] = dArray3;
+
+ startTests("ByteArrays");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_ByteArray_Create <zero length>");
+ testZeroLength();
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_ByteArray_Create");
+ createByteArray(&testByteArray[i], dummyArray[i], lengths[i]);
+ }
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(testByteArray[0],
+ testByteArray[3],
+ testByteArray[1],
+ "[001, 002, 003, 004, 005]",
+ ByteArray,
+ PKIX_TRUE);
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_ByteArray_ToString");
+ testToString(testByteArray[i], expected[i]);
+ }
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_ByteArray_GetLength");
+ testGetLength(testByteArray[i], lengths[i]);
+ }
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_ByteArray_GetPointer");
+ testGetPointer(testByteArray[i], dummyArray[i], lengths[i]);
+ }
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_ByteArray_Destroy");
+ testDestroy(testByteArray[i]);
+ }
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ endTests("ByteArray");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_hashtable.c b/security/nss/cmd/libpkix/pkix_pl/system/test_hashtable.c
new file mode 100644
index 000000000..663bfc9fa
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_hashtable.c
@@ -0,0 +1,380 @@
+/* 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/. */
+/*
+ * test_hashtable.c
+ *
+ * Tests Hashtables
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createHashTables(
+ PKIX_PL_HashTable **ht,
+ PKIX_PL_HashTable **ht2,
+ PKIX_PL_HashTable **ht3,
+ PKIX_PL_HashTable **ht4)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Create(1, 0, ht, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Create(5, 0, ht2, plContext));
+
+ /* at most two entries per bucket */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Create(1, 2, ht4, plContext));
+
+ *ht3 = *ht;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)*ht3, plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAdd(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_HashTable *ht2,
+ PKIX_PL_String **testString,
+ PKIX_PL_String **testString2,
+ PKIX_PL_String **testString3,
+ PKIX_PL_OID **testOID)
+{
+ char *dummyString = "test string 1";
+ char *dummyString2 = "test string 2";
+ char *dummyString3 = "test string 3";
+ char *dummyOID = "2.11.22222.33333";
+
+ PKIX_TEST_STD_VARS();
+
+ /* Make some dummy objects */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ dummyString,
+ PL_strlen(dummyString),
+ testString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ dummyString2,
+ PL_strlen(dummyString2),
+ testString2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ dummyString3,
+ PL_strlen(dummyString3),
+ testString3,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(dummyOID, testOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht,
+ (PKIX_PL_Object *)*testString,
+ (PKIX_PL_Object *)*testString2,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht2,
+ (PKIX_PL_Object *)*testString,
+ (PKIX_PL_Object *)*testString2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht,
+ (PKIX_PL_Object *)*testString2,
+ (PKIX_PL_Object *)*testString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht2,
+ (PKIX_PL_Object *)*testString2,
+ (PKIX_PL_Object *)*testString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht,
+ (PKIX_PL_Object *)*testOID,
+ (PKIX_PL_Object *)*testOID,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht2,
+ (PKIX_PL_Object *)*testOID,
+ (PKIX_PL_Object *)*testOID,
+ plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAddFIFO(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_String **testString,
+ PKIX_PL_String **testString2,
+ PKIX_PL_String **testString3)
+{
+ PKIX_PL_String *targetString = NULL;
+ PKIX_Boolean cmpResult;
+
+ PKIX_TEST_STD_VARS();
+
+ /*
+ * ht is created as one bucket, two entries per bucket. Since we add
+ * three items to the ht, we expect the first one to be deleted.
+ */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht,
+ (PKIX_PL_Object *)*testString,
+ (PKIX_PL_Object *)*testString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht,
+ (PKIX_PL_Object *)*testString2,
+ (PKIX_PL_Object *)*testString2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht,
+ (PKIX_PL_Object *)*testString3,
+ (PKIX_PL_Object *)*testString3,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht,
+ (PKIX_PL_Object *)*testString,
+ (PKIX_PL_Object **)&targetString,
+ plContext));
+ if (targetString != NULL) {
+ testError("HashTable_Lookup retrieved a supposed deleted item");
+ PKIX_TEST_DECREF_BC(targetString);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht,
+ (PKIX_PL_Object *)*testString3,
+ (PKIX_PL_Object **)&targetString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(
+ (PKIX_PL_Object *)targetString,
+ (PKIX_PL_Object *)*testString3,
+ &cmpResult,
+ plContext));
+ if (cmpResult != PKIX_TRUE) {
+ testError("HashTable_Lookup failed");
+ }
+ PKIX_TEST_DECREF_BC(targetString);
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testLookup(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_HashTable *ht2,
+ PKIX_PL_String *testString,
+ PKIX_PL_String *testString2,
+ PKIX_PL_String *testString3,
+ PKIX_PL_OID *testOID)
+{
+ PKIX_PL_String *targetString = NULL;
+ PKIX_PL_String *targetOID = NULL;
+ PKIX_Boolean cmpResult;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht,
+ (PKIX_PL_Object *)testString,
+ (PKIX_PL_Object **)&targetString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(
+ (PKIX_PL_Object *)targetString,
+ (PKIX_PL_Object *)testString2,
+ &cmpResult,
+ plContext));
+ if (cmpResult != PKIX_TRUE) {
+ testError("HashTable_Lookup failed");
+ }
+ PKIX_TEST_DECREF_BC(targetString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht2,
+ (PKIX_PL_Object *)testString,
+ (PKIX_PL_Object **)&targetString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(
+ (PKIX_PL_Object *)targetString,
+ (PKIX_PL_Object *)testString2,
+ &cmpResult,
+ plContext));
+ if (cmpResult != PKIX_TRUE) {
+ testError("HashTable_Lookup failed");
+ }
+ PKIX_TEST_DECREF_BC(targetString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht2,
+ (PKIX_PL_Object *)testString2,
+ (PKIX_PL_Object **)&targetString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(
+ (PKIX_PL_Object *)targetString,
+ (PKIX_PL_Object *)testString,
+ &cmpResult,
+ plContext));
+ if (cmpResult != PKIX_TRUE) {
+ testError("HashTable_Lookup failed");
+ }
+ PKIX_TEST_DECREF_BC(targetString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht,
+ (PKIX_PL_Object *)testOID,
+ (PKIX_PL_Object **)&targetOID,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)targetOID, &targetString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(
+ (PKIX_PL_Object *)targetOID,
+ (PKIX_PL_Object *)testOID,
+ &cmpResult,
+ plContext));
+ if (cmpResult != PKIX_TRUE) {
+ testError("HashTable_Lookup failed");
+ }
+ PKIX_TEST_DECREF_BC(targetString);
+ PKIX_TEST_DECREF_BC(targetOID);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht2,
+ (PKIX_PL_Object *)testOID,
+ (PKIX_PL_Object **)&targetOID,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)targetOID, &targetString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(
+ (PKIX_PL_Object *)targetOID,
+ (PKIX_PL_Object *)testOID,
+ &cmpResult,
+ plContext));
+ if (cmpResult != PKIX_TRUE) {
+ testError("HashTable_Lookup failed");
+ }
+ PKIX_TEST_DECREF_BC(targetString);
+ PKIX_TEST_DECREF_BC(targetOID);
+
+ (void)printf("Looking up item not in HashTable.\n");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht,
+ (PKIX_PL_Object *)testString3,
+ (PKIX_PL_Object **)&targetString,
+ plContext));
+ if (targetString == NULL)
+ (void)printf("\tCorrectly returned NULL.\n");
+ else
+ testError("Hashtable did not return NULL value as expected");
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testRemove(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_HashTable *ht2,
+ PKIX_PL_String *testString,
+ PKIX_PL_String *testString2,
+ PKIX_PL_OID *testOID)
+{
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Remove(ht,
+ (PKIX_PL_Object *)testString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Remove(ht,
+ (PKIX_PL_Object *)testOID,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Remove(ht2,
+ (PKIX_PL_Object *)testString2,
+ plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_HashTable_Remove(ht,
+ (PKIX_PL_Object *)testString,
+ plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_HashTable *ht2,
+ PKIX_PL_HashTable *ht3,
+ PKIX_PL_HashTable *ht4)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(ht);
+ PKIX_TEST_DECREF_BC(ht2);
+ PKIX_TEST_DECREF_BC(ht3);
+ PKIX_TEST_DECREF_BC(ht4);
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+int
+test_hashtable(int argc, char *argv[])
+{
+
+ PKIX_PL_HashTable *ht, *ht2, *ht3, *ht4;
+ PKIX_PL_String *testString, *testString2, *testString3;
+ PKIX_PL_OID *testOID;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("HashTables");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_HashTable_Create");
+ createHashTables(&ht, &ht2, &ht3, &ht4);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(ht,
+ ht3,
+ ht2,
+ NULL,
+ HashTable,
+ PKIX_FALSE);
+
+ subTest("PKIX_PL_HashTable_Add");
+ testAdd(ht, ht2, &testString, &testString2, &testString3, &testOID);
+
+ subTest("PKIX_PL_HashTable_ADD - with Bucket Size limit");
+ testAddFIFO(ht4, &testString, &testString2, &testString3);
+
+ subTest("PKIX_PL_HashTable_Lookup");
+ testLookup(ht, ht2, testString, testString2, testString3, testOID);
+
+ subTest("PKIX_PL_HashTable_Remove");
+ testRemove(ht, ht2, testString, testString2, testOID);
+
+ PKIX_TEST_DECREF_BC(testString);
+ PKIX_TEST_DECREF_BC(testString2);
+ PKIX_TEST_DECREF_BC(testString3);
+ PKIX_TEST_DECREF_BC(testOID);
+
+ subTest("PKIX_PL_HashTable_Destroy");
+ testDestroy(ht, ht2, ht3, ht4);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ endTests("BigInt");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_mem.c b/security/nss/cmd/libpkix/pkix_pl/system/test_mem.c
new file mode 100644
index 000000000..3a4e5f713
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_mem.c
@@ -0,0 +1,133 @@
+/* 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/. */
+/*
+ * test_mem.c
+ *
+ * Tests Malloc, Realloc and Free
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testMalloc(PKIX_UInt32 **array)
+{
+ PKIX_UInt32 i, arraySize = 10;
+ PKIX_TEST_STD_VARS();
+
+ /* Create an integer array of size 10 */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc(
+ (PKIX_UInt32)(arraySize * sizeof(unsigned int)),
+ (void **)array, plContext));
+
+ /* Fill in some values */
+ (void)printf("Setting array[i] = i...\n");
+ for (i = 0; i < arraySize; i++) {
+ (*array)[i] = i;
+ if ((*array)[i] != i)
+ testError("Array has incorrect contents");
+ }
+
+ /* Memory now reflects changes */
+ (void)printf("\tArray: a[0] = %d, a[5] = %d, a[7] = %d.\n",
+ (*array[0]), (*array)[5], (*array)[7]);
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testRealloc(PKIX_UInt32 **array)
+{
+ PKIX_UInt32 i, arraySize = 20;
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Realloc(*array,
+ (PKIX_UInt32)(arraySize *
+ sizeof(unsigned int)),
+ (void **)array, plContext));
+
+ /* Fill in the new elements */
+ (void)printf("Setting new portion of array to a[i] = i...\n");
+ for (i = arraySize / 2; i < arraySize; i++) {
+ (*array)[i] = i;
+ if ((*array)[i] != i)
+ testError("Array has incorrect contents");
+ }
+
+ /* New elements should be reflected. The old should be the same */
+ (void)printf("\tArray: a[0] = %d, a[15] = %d, a[17] = %d.\n",
+ (*array)[0], (*array)[15], (*array)[17]);
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testFree(PKIX_UInt32 *array)
+{
+
+ PKIX_TEST_STD_VARS();
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(array, plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+int
+test_mem(int argc, char *argv[])
+{
+
+ unsigned int *array = NULL;
+ int arraySize = 10;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Memory Allocation");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_Malloc");
+ testMalloc(&array);
+
+ subTest("PKIX_PL_Realloc");
+ testRealloc(&array);
+
+ subTest("PKIX_PL_Free");
+ testFree(array);
+
+ /* --Negative Test Cases------------------- */
+ /* Create an integer array of size 10 */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc(
+ (PKIX_UInt32)(arraySize * sizeof(unsigned int)),
+ (void **)&array, plContext));
+
+ (void)printf("Attempting to reallocate 0 sized memory...\n");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Realloc(array, 0, (void **)&array, plContext));
+
+ (void)printf("Attempting to allocate to null pointer...\n");
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Malloc(10, NULL, plContext));
+
+ (void)printf("Attempting to reallocate to null pointer...\n");
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Realloc(NULL, 10, NULL, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(array, plContext));
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ endTests("Memory Allocation");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_monitorlock.c b/security/nss/cmd/libpkix/pkix_pl/system/test_monitorlock.c
new file mode 100644
index 000000000..21974258f
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_monitorlock.c
@@ -0,0 +1,104 @@
+/* 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/. */
+/*
+ * test_monitorlock.c
+ *
+ * Tests basic MonitorLock object functionality. No multi-threading.
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createMonitorLockes(
+ PKIX_PL_MonitorLock **monitorLock,
+ PKIX_PL_MonitorLock **monitorLock2,
+ PKIX_PL_MonitorLock **monitorLock3)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_MonitorLock_Create(monitorLock, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_MonitorLock_Create(monitorLock2, plContext));
+
+ *monitorLock3 = *monitorLock;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)*monitorLock3, plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testLock(PKIX_PL_MonitorLock *monitorLock)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_MonitorLock_Enter(monitorLock, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_MonitorLock_Enter(monitorLock, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_MonitorLock_Exit(monitorLock, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_MonitorLock_Exit(monitorLock, plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_MonitorLock *monitorLock,
+ PKIX_PL_MonitorLock *monitorLock2,
+ PKIX_PL_MonitorLock *monitorLock3)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(monitorLock);
+ PKIX_TEST_DECREF_BC(monitorLock2);
+ PKIX_TEST_DECREF_BC(monitorLock3);
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+int
+test_monitorlock(int argc, char *argv[])
+{
+
+ PKIX_PL_MonitorLock *monitorLock, *monitorLock2, *monitorLock3;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("MonitorLocks");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_MonitorLock_Create");
+ createMonitorLockes(&monitorLock, &monitorLock2, &monitorLock3);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(monitorLock,
+ monitorLock3,
+ monitorLock2,
+ NULL,
+ MonitorLock,
+ PKIX_FALSE);
+
+ subTest("PKIX_PL_MonitorLock_Lock/Unlock");
+ testLock(monitorLock);
+
+ subTest("PKIX_PL_MonitorLock_Destroy");
+ testDestroy(monitorLock, monitorLock2, monitorLock3);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("MonitorLockes");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_mutex.c b/security/nss/cmd/libpkix/pkix_pl/system/test_mutex.c
new file mode 100644
index 000000000..bb0e7a024
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_mutex.c
@@ -0,0 +1,102 @@
+/* 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/. */
+/*
+ * test_mutex.c
+ *
+ * Tests basic mutex object functionality. No multi-threading.
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createMutexes(
+ PKIX_PL_Mutex **mutex,
+ PKIX_PL_Mutex **mutex2,
+ PKIX_PL_Mutex **mutex3)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Mutex_Create(mutex, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Mutex_Create(mutex2, plContext));
+
+ *mutex3 = *mutex;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)*mutex3, plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testLock(PKIX_PL_Mutex *mutex)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Mutex_Lock(mutex, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Mutex_Unlock(mutex, plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_Mutex *mutex,
+ PKIX_PL_Mutex *mutex2,
+ PKIX_PL_Mutex *mutex3)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(mutex);
+ PKIX_TEST_DECREF_BC(mutex2);
+ PKIX_TEST_DECREF_BC(mutex3);
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+int
+test_mutex(int argc, char *argv[])
+{
+
+ PKIX_PL_Mutex *mutex, *mutex2, *mutex3;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Mutexes");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_Mutex_Create");
+ createMutexes(&mutex, &mutex2, &mutex3);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(mutex,
+ mutex3,
+ mutex2,
+ NULL,
+ Mutex,
+ PKIX_FALSE);
+
+ subTest("PKIX_PL_Mutex_Lock/Unlock");
+ testLock(mutex);
+
+ subTest("PKIX_PL_Mutex_Destroy");
+ testDestroy(mutex, mutex2, mutex3);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Mutexes");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_mutex2.c b/security/nss/cmd/libpkix/pkix_pl/system/test_mutex2.c
new file mode 100644
index 000000000..197eba2b4
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_mutex2.c
@@ -0,0 +1,166 @@
+/* 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/. */
+/*
+ * test_mutex2.c
+ *
+ * Tests multi-threaded functionality of Mutex
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static int box1 = 0, box2 = 0, box3 = 0;
+static PKIX_PL_Mutex *mutex;
+static PRCondVar *cv;
+static void *plContext = NULL;
+
+static void
+consumer(/* ARGSUSED */ void *arg)
+{
+ PRStatus status = PR_SUCCESS;
+ PKIX_Error *errorResult;
+ int i = 0;
+ for (i = 0; i < 5; i++) {
+ (void)PKIX_PL_Mutex_Lock(mutex, plContext);
+ while (((box1 == 0) ||
+ (box2 == 0) ||
+ (box3 == 0)) &&
+ (status == PR_SUCCESS))
+ status = PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
+
+ (void)printf("\tConsumer got Box1 = %d ", box1);
+ box1 = 0;
+ (void)printf("Box2 = %d ", box2);
+ box2 = 0;
+ (void)printf("Box3 = %d\n", box3);
+ box3 = 0;
+
+ status = PR_NotifyAllCondVar(cv);
+ if (status == PR_FAILURE)
+ (void)printf("Consumer error while notifying condvar\n");
+ errorResult = PKIX_PL_Mutex_Unlock(mutex, plContext);
+ if (errorResult)
+ testError("PKIX_PL_Mutex_Unlock failed");
+ }
+ (void)printf("Consumer exiting...\n");
+}
+
+static void
+producer(void *arg)
+{
+ PRStatus status = PR_SUCCESS;
+ int value = *(int *)arg;
+ int i = 0;
+ int *box;
+ PKIX_Error *errorResult;
+ if (value == 10)
+ box = &box1;
+ else if (value == 20)
+ box = &box2;
+ else if (value == 30)
+ box = &box3;
+
+ for (i = 0; i < 5; i++) {
+ (void)PKIX_PL_Mutex_Lock(mutex, plContext);
+ while ((*box != 0) && (status == PR_SUCCESS))
+ status = PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
+
+ *box = i + 1;
+ (void)printf("\tProducer %d put value: %d\n", value, *box);
+
+ status = PR_NotifyAllCondVar(cv);
+ if (status == PR_FAILURE)
+ (void)printf("Producer %d error while notifying condvar\n",
+ value);
+ errorResult = PKIX_PL_Mutex_Unlock(mutex, plContext);
+ if (errorResult)
+ testError("PKIX_PL_Mutex_Unlock failed");
+ }
+}
+
+int
+test_mutex2(int argc, char *argv[])
+{
+
+ PRThread *consThread, *prodThread, *prodThread2, *prodThread3;
+ int x = 10, y = 20, z = 30;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Mutex and Threads");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ (void)printf("Attempting to create new mutex...\n");
+ subTest("Mutex Creation");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Mutex_Create(&mutex, plContext));
+
+ cv = PR_NewCondVar(*(PRLock **)mutex);
+
+ subTest("Starting consumer thread");
+ consThread = PR_CreateThread(PR_USER_THREAD,
+ consumer,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ subTest("Starting producer thread 1");
+ prodThread = PR_CreateThread(PR_USER_THREAD,
+ producer,
+ &x,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ subTest("Starting producer thread 2");
+ prodThread2 = PR_CreateThread(PR_USER_THREAD,
+ producer,
+ &y,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ subTest("Starting producer thread 3");
+ prodThread3 = PR_CreateThread(PR_USER_THREAD,
+ producer,
+ &z,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ PR_JoinThread(consThread);
+
+ (void)PR_DestroyCondVar(cv);
+ PKIX_TEST_DECREF_BC(mutex);
+
+ /*
+ * Note: we should also be freeing each thread's stack, but we
+ * don't have access to the prodThread->stack variable (since
+ * it is not exported). As a result, we have 120 bytes of memory
+ * leakage.
+ */
+
+ PR_Free(prodThread);
+ PR_Free(prodThread2);
+ PR_Free(prodThread3);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Mutex and Threads");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_mutex3.c b/security/nss/cmd/libpkix/pkix_pl/system/test_mutex3.c
new file mode 100644
index 000000000..9f42f629b
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_mutex3.c
@@ -0,0 +1,104 @@
+/* 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/. */
+/*
+ * test_mutex3.c
+ *
+ * Tests multi-threaded functionality of Mutex
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static PKIX_PL_Mutex *mutex;
+static void *plContext = NULL;
+
+static void
+t1(/* ARGSUSED */ void *arg)
+{
+ PKIX_Error *errorResult;
+
+ (void)printf("t1 acquiring lock...\n");
+ errorResult = PKIX_PL_Mutex_Lock(mutex, plContext);
+ if (errorResult)
+ testError("PKIX_PL_Mutex_Lock failed");
+
+ (void)printf("t1 sleeplng for 3 seconds\n");
+ PR_Sleep(PR_SecondsToInterval(3));
+ (void)printf("t1 releasing lock...\n");
+
+ errorResult = PKIX_PL_Mutex_Unlock(mutex, plContext);
+ if (errorResult)
+ testError("PKIX_PL_Mutex_Unlock failed");
+
+ (void)printf("t1 exiting...\n");
+}
+
+static void
+t2(/* ARGSUSED */ void *arg)
+{
+ PKIX_Error *errorResult;
+
+ (void)printf("t2 acquiring lock...\n");
+ errorResult = PKIX_PL_Mutex_Lock(mutex, plContext);
+ if (errorResult)
+ testError("PKIX_PL_Mutex_Lock failed");
+
+ (void)printf("t2 releasing lock...\n");
+ errorResult = PKIX_PL_Mutex_Unlock(mutex, plContext);
+ if (errorResult)
+ testError("PKIX_PL_Mutex_Unlock failed");
+
+ (void)printf("t2 exiting...\n");
+}
+
+int
+test_mutex3(int argc, char *argv[])
+{
+ PRThread *thread, *thread2;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Mutex and Threads");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("Mutex Creation");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Mutex_Create(&mutex, plContext));
+
+ subTest("Starting thread");
+ thread = PR_CreateThread(PR_USER_THREAD,
+ t1,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ thread2 = PR_CreateThread(PR_USER_THREAD,
+ t2,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ PR_JoinThread(thread2);
+ PR_JoinThread(thread);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(mutex);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Mutex and Threads");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_object.c b/security/nss/cmd/libpkix/pkix_pl/system/test_object.c
new file mode 100644
index 000000000..ebb691ba6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_object.c
@@ -0,0 +1,281 @@
+/* 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/. */
+/*
+ * test_object.c
+ *
+ * Test Object Allocation, toString, Equals, Destruction
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static PKIX_Error *
+destructor(
+ /* ARGSUSED */ PKIX_PL_Object *object,
+ /* ARGSUSED */ void *plContext)
+{
+ (void)printf("\tUser defined destructor called\n");
+ return (NULL);
+}
+
+static PKIX_Error *
+toStringCallback(
+ PKIX_PL_Object *obj,
+ PKIX_PL_String **pString,
+ /* ARGSUSED */ void *plContext)
+{
+
+ PKIX_Error *errorResult;
+ PKIX_UInt32 type;
+ char *format = "(addr: %x, type: %d)";
+ PKIX_PL_String *formatString = NULL;
+
+ errorResult = PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ format,
+ PL_strlen(format),
+ &formatString,
+ plContext);
+ if (errorResult)
+ testError("PKIX_PL_String_Create failed");
+
+ if (pString == plContext)
+ testError("Null String");
+
+ type = (unsigned int)0;
+
+ (void)PKIX_PL_Object_GetType(obj, &type, plContext);
+
+ errorResult = PKIX_PL_Sprintf(pString, plContext,
+ formatString,
+ (int)obj, type);
+ if (errorResult)
+ testError("PKIX_PL_Sprintf failed");
+
+ errorResult = PKIX_PL_Object_DecRef((PKIX_PL_Object *)formatString,
+ plContext);
+ if (errorResult)
+ testError("PKIX_PL_Object_DecRef failed");
+
+ return (NULL);
+}
+
+static PKIX_Error *
+comparator(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Int32 *pValue,
+ /* ARGSUSED */ void *plContext)
+{
+ if (*(char *)first > *(char *)second)
+ *pValue = 1;
+ else if (*(char *)first < *(char *)second)
+ *pValue = -1;
+ else
+ *pValue = 0;
+ return (NULL);
+}
+
+static PKIX_Error *
+hashcodeCallback(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pValue,
+ /* ARGSUSED */ void *plContext)
+{
+ *pValue = 123456789;
+ return (NULL);
+}
+
+static PKIX_Error *
+equalsCallback(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *result,
+ void *plContext)
+{
+
+ PKIX_UInt32 firstType = 0, secondType = 0;
+
+ if ((first == plContext) || (second == plContext))
+ testError("Null Object");
+
+ (void)PKIX_PL_Object_GetType(first, &firstType, plContext);
+
+ (void)PKIX_PL_Object_GetType(second, &secondType, plContext);
+
+ *result = (firstType == secondType) ? PKIX_TRUE : PKIX_FALSE;
+
+ return (NULL);
+}
+
+static void
+createObjects(
+ PKIX_PL_Object **obj,
+ PKIX_PL_Object **obj2,
+ PKIX_PL_Object **obj3,
+ PKIX_PL_Object **obj4)
+{
+ PKIX_TEST_STD_VARS();
+
+#ifdef PKIX_USER_OBJECT_TYPE
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_RegisterType(1000, /* type */
+ "thousand", /* description */
+ NULL, /* destructor */
+ NULL, /* equals */
+ (PKIX_PL_HashcodeCallback)hashcodeCallback,
+ NULL, /* toString */
+ NULL, /* Comparator */
+ NULL,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Alloc(1000, /* type */
+ 12, /* size */
+ obj,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_RegisterType(2000, /* type */
+ "two thousand" /* description */,
+ (PKIX_PL_DestructorCallback)destructor,
+ (PKIX_PL_EqualsCallback)equalsCallback,
+ NULL, /* hashcode */
+ (PKIX_PL_ToStringCallback)toStringCallback,
+ (PKIX_PL_ComparatorCallback)comparator,
+ NULL,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Alloc(2000, /* type */
+ 1, /* size */
+ obj2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Alloc(2000, /* type */
+ 1, /* size */
+ obj4,
+ plContext));
+
+ *obj3 = *obj;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef(*obj3, plContext));
+
+cleanup:
+#endif /* PKIX_USER_OBJECT_TYPE */
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetType(
+ PKIX_PL_Object *obj,
+ PKIX_PL_Object *obj2,
+ PKIX_PL_Object *obj3)
+{
+ PKIX_UInt32 testType;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_GetType(obj, &testType, plContext));
+
+ if (testType != 1000)
+ testError("Object 1 returned the wrong type");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_GetType(obj2, &testType, plContext));
+ if (testType != 2000)
+ testError("Object 2 returned the wrong type");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_GetType(obj3, &testType, plContext));
+ if (testType != 1000)
+ testError("Object 3 returned the wrong type");
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCompare(
+ PKIX_PL_Object *obj2,
+ PKIX_PL_Object *obj4)
+{
+ PKIX_Int32 cmpResult;
+ PKIX_TEST_STD_VARS();
+
+ *(char *)obj2 = 0x20;
+ *(char *)obj4 = 0x10;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare(obj2, obj4, &cmpResult, plContext));
+ if (cmpResult <= 0)
+ testError("Invalid Result from Object Compare");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare(obj4, obj2, &cmpResult, plContext));
+ if (cmpResult >= 0)
+ testError("Invalid Result from Object Compare");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare(obj4, obj4, &cmpResult, plContext));
+
+ *(char *)obj2 = 0x10;
+ if (cmpResult != 0)
+ testError("Invalid Result from Object Compare");
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_Object *obj,
+ PKIX_PL_Object *obj2,
+ PKIX_PL_Object *obj3,
+ PKIX_PL_Object *obj4)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(obj);
+ PKIX_TEST_DECREF_BC(obj2);
+ PKIX_TEST_DECREF_BC(obj3);
+ PKIX_TEST_DECREF_BC(obj4);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_object(int argc, char *argv[])
+{
+
+#ifdef PKIX_USER_OBJECT_TYPE
+ PKIX_PL_Object *obj, *obj2, *obj3, *obj4;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Objects");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_Object_Create");
+ createObjects(&obj, &obj2, &obj3, &obj4);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(obj, obj3, obj2, NULL, Object, PKIX_FALSE);
+
+ subTest("PKIX_PL_Object_GetType");
+ testGetType(obj, obj2, obj3);
+
+ subTest("PKIX_PL_Object_Compare");
+ testCompare(obj2, obj4);
+
+ subTest("PKIX_PL_Object_Destroy");
+ testDestroy(obj, obj2, obj3, obj4);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ endTests("Objects");
+#endif /* PKIX_USER_OBJECT_TYPE */
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_oid.c b/security/nss/cmd/libpkix/pkix_pl/system/test_oid.c
new file mode 100644
index 000000000..09cddaeea
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_oid.c
@@ -0,0 +1,212 @@
+/* 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/. */
+/*
+ * test_oid.c
+ *
+ * Test OID Types
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createOID(
+ PKIX_PL_OID **testOID,
+ char *oidAscii,
+ PKIX_Boolean errorHandling)
+{
+ PKIX_TEST_STD_VARS();
+
+ if (errorHandling) {
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_OID_Create(oidAscii, testOID, plContext));
+ } else {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(oidAscii, testOID, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testToString(
+ PKIX_PL_OID *oid,
+ char *expAscii)
+{
+ PKIX_PL_String *oidString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)oid,
+ &oidString, plContext));
+
+ temp = PKIX_String2ASCII(oidString, plContext);
+ if (temp == NULL) {
+ testError("PKIX_String2Ascii failed");
+ goto cleanup;
+ }
+
+ if (PL_strcmp(temp, expAscii) != 0) {
+ (void)printf("\tOid ToString: %s %s\n", temp, expAscii);
+ testError("Output string does not match source");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(oidString);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCompare(
+ PKIX_PL_OID *oid0,
+ PKIX_PL_OID *oid1,
+ PKIX_PL_OID *oid2,
+ PKIX_PL_OID *oid3)
+{
+ PKIX_Int32 cmpResult;
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare((PKIX_PL_Object *)oid0,
+ (PKIX_PL_Object *)oid1,
+ &cmpResult, plContext));
+ if (cmpResult <= 0)
+ testError("Invalid Result from OID Compare");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare((PKIX_PL_Object *)oid1,
+ (PKIX_PL_Object *)oid0,
+ &cmpResult, plContext));
+ if (cmpResult >= 0)
+ testError("Invalid Result from OID Compare");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare((PKIX_PL_Object *)oid1,
+ (PKIX_PL_Object *)oid2,
+ &cmpResult, plContext));
+ if (cmpResult >= 0)
+ testError("Invalid Result from OID Compare");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare((PKIX_PL_Object *)oid2,
+ (PKIX_PL_Object *)oid1,
+ &cmpResult, plContext));
+ if (cmpResult <= 0)
+ testError("Invalid Result from OID Compare");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare((PKIX_PL_Object *)oid1,
+ (PKIX_PL_Object *)oid3,
+ &cmpResult, plContext));
+ if (cmpResult != 0)
+ testError("Invalid Result from OID Compare");
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_OID *oid)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(oid);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_oid(int argc, char *argv[])
+{
+
+ PKIX_PL_OID *testOID[6] = { NULL };
+ PKIX_PL_OID *badTestOID = NULL;
+ PKIX_UInt32 i, size = 6;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ char *validOID[6] = {
+ "2.11.22222.33333",
+ "1.2.3.004.5.6.7",
+ "2.11.22222.33333",
+ "1.2.3.4.5.6.7",
+ "1.2.3",
+ "2.39.3"
+ };
+
+ char *expected[6] = {
+ "2.11.22222.33333",
+ "1.2.3.4.5.6.7",
+ "2.11.22222.33333",
+ "1.2.3.4.5.6.7",
+ "1.2.3",
+ "2.39.3"
+ };
+
+ char *badOID[11] = {
+ "1.2.4294967299",
+ "this. is. a. bad. oid",
+ "00a1000.002b",
+ "100.-5.10",
+ "1.2..3",
+ ".1.2.3",
+ "1.2.3.",
+ "00010.1.2.3",
+ "1.000041.2.3",
+ "000000000000000000000000000000000000000010.3.2",
+ "1"
+ };
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("OIDs");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_OID_Create");
+ createOID(&testOID[i], validOID[i], PKIX_FALSE);
+ }
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(testOID[0],
+ testOID[2],
+ testOID[1],
+ NULL,
+ OID,
+ PKIX_FALSE);
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_OID_ToString");
+ testToString(testOID[i], expected[i]);
+ }
+
+ subTest("PKIX_PL_OID_Compare");
+ testCompare(testOID[0], testOID[1], testOID[2], testOID[3]);
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_OID_Destroy");
+ testDestroy(testOID[i]);
+ }
+
+ for (i = 0; i < 11; i++) {
+ subTest("PKIX_PL_OID Error Handling");
+ createOID(&badTestOID, badOID[i], PKIX_TRUE);
+ }
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ endTests("OIDs");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_rwlock.c b/security/nss/cmd/libpkix/pkix_pl/system/test_rwlock.c
new file mode 100644
index 000000000..9c09d6479
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_rwlock.c
@@ -0,0 +1,204 @@
+/* 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/. */
+/*
+ * test_rwlock.c
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static PKIX_PL_RWLock *rwlock = NULL, *rwlock2 = NULL, *rwlock3 = NULL;
+static PRThread *thread = NULL, *thread2 = NULL, *thread3 = NULL;
+static void *plContext = NULL;
+
+static void
+reader(void)
+{
+ PKIX_Error *errorResult;
+
+ errorResult = PKIX_PL_AcquireReaderLock(rwlock, NULL);
+ if (errorResult)
+ testError("PKIX_PL_AcquireReaderLock failed");
+
+ (void)printf("\t[Thread #1 Read Lock #1.]\n");
+ (void)printf("\t[Thread #1 Sleeplng for 1 seconds.]\n");
+ PR_Sleep(PR_SecondsToInterval(1));
+ PKIX_PL_ReleaseReaderLock(rwlock, NULL);
+ if (errorResult)
+ testError("PKIX_PL_ReleaseReaderLock failed");
+ (void)printf("\t[Thread #1 Read UNLock #1.]\n");
+}
+
+static void
+writer(void)
+{
+ PKIX_Error *errorResult;
+ /* This thread should stick here until lock 1 is released */
+ PKIX_PL_AcquireWriterLock(rwlock, NULL);
+ if (errorResult)
+ testError("PKIX_PL_AcquireWriterLock failed");
+
+ (void)printf("\t[Thread #2 Write Lock #1.]\n");
+
+ PKIX_PL_AcquireWriterLock(rwlock2, NULL);
+ if (errorResult)
+ testError("PKIX_PL_AcquireWriterLock failed");
+ (void)printf("\t[Thread #2 Write Lock #2.]\n");
+
+ (void)printf("\t[Thread #2 Sleeplng for 1 seconds.]\n");
+ PR_Sleep(PR_SecondsToInterval(1));
+
+ PKIX_PL_ReleaseWriterLock(rwlock2, NULL);
+ if (errorResult)
+ testError("PKIX_PL_ReleaseWriterLock failed");
+ (void)printf("\t[Thread #2 Write UNLock #2.]\n");
+
+ (void)printf("\t[Thread #2 Sleeplng for 1 seconds.]\n");
+ PR_Sleep(PR_SecondsToInterval(1));
+
+ PKIX_PL_ReleaseWriterLock(rwlock, NULL);
+ if (errorResult)
+ testError("PKIX_PL_ReleaseWriterLock failed");
+ (void)printf("\t[Thread #2 Write UNLock #1.]\n");
+
+ PR_JoinThread(thread3);
+}
+
+static void
+reader2(void)
+{
+ PKIX_Error *errorResult;
+ /* Reader 2 should yield here until the writer is done */
+
+ PKIX_PL_AcquireReaderLock(rwlock2, NULL);
+ if (errorResult)
+ testError("PKIX_PL_AcquireReaderLock failed");
+
+ (void)printf("\t[Thread #3 Read Lock #2.]\n");
+
+ PKIX_PL_AcquireReaderLock(rwlock3, NULL);
+ if (errorResult)
+ testError("PKIX_PL_AcquireReaderLock failed");
+ (void)printf("\t[Thread #3 Read Lock #3.]\n");
+
+ (void)printf("\t[Thread #3 Sleeplng for 1 seconds.]\n");
+ PR_Sleep(PR_SecondsToInterval(1));
+
+ PKIX_PL_ReleaseReaderLock(rwlock3, NULL);
+ if (errorResult)
+ testError("PKIX_PL_ReleaseReaderLock failed");
+ (void)printf("\t[Thread #3 Read UNLock #3.]\n");
+
+ (void)printf("\t[Thread #3 Sleeplng for 1 seconds.]\n");
+ PR_Sleep(PR_SecondsToInterval(1));
+
+ PKIX_PL_ReleaseReaderLock(rwlock2, NULL);
+ if (errorResult)
+ testError("PKIX_PL_ReleaseReaderLock failed");
+ (void)printf("\t[Thread #3 Read UNLock #2.]\n");
+}
+
+int
+test_rwlock()
+{
+ PKIX_PL_String *outputString = NULL;
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean bool;
+ PKIX_UInt32 actualMinorVersion;
+
+ PKIX_TEST_STD_VARS();
+ startTests("RWLocks");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ (void)printf("Attempting to create new rwlock...\n");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_RWLock_Create(&rwlock, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_RWLock_Create(&rwlock2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_RWLock_Create(&rwlock3, plContext));
+
+ /* Test toString functionality */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)rwlock, &outputString, plContext));
+
+ (void)printf("Testing RWLock toString: %s\n",
+ PKIX_String2ASCII(outputString));
+
+ PKIX_TEST_DECREF_BC(outputString);
+
+ /* Call Equals on two different objects */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)rwlock,
+ (PKIX_PL_Object *)rwlock2,
+ &bool,
+ plContext));
+
+ (void)printf("Testing RWLock Equals: %d (should be 0)\n", bool);
+
+ if (bool != 0)
+ testError("Error in RWLock_Equals");
+
+ /* Call Equals on two equal objects */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)rwlock,
+ (PKIX_PL_Object *)rwlock, &bool, plContext));
+
+ (void)printf("Testing RWLock Equals: %d (should be 1)\n", bool);
+ if (bool != 1)
+ testError("Error in RWLock_Equals");
+
+ subTest("Multi-Thread Read/Write Lock Testing");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_AcquireReaderLock(rwlock, plContext));
+ (void)printf("\t[Main Thread Read Lock #1.]\n");
+
+ thread = PR_CreateThread(PR_USER_THREAD,
+ reader,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ thread2 = PR_CreateThread(PR_USER_THREAD,
+ writer,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ thread3 = PR_CreateThread(PR_USER_THREAD,
+ reader2,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ PR_JoinThread(thread);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ReleaseReaderLock(rwlock, plContext));
+ (void)printf("\t[Main Thread Read Unlock #1.]\n");
+
+ PR_JoinThread(thread2);
+
+cleanup:
+
+ /* Test destructor */
+ subTest("Testing destructor...");
+ PKIX_TEST_DECREF_AC(rwlock);
+ PKIX_TEST_DECREF_AC(rwlock2);
+ PKIX_TEST_DECREF_AC(rwlock3);
+
+ pkixTestTempResult = PKIX_Shutdown(plContext);
+ if (pkixTestTempResult)
+ pkixTestErrorResult = pkixTestTempResult;
+
+ PKIX_TEST_RETURN();
+
+ endTests("RWLocks");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_string.c b/security/nss/cmd/libpkix/pkix_pl/system/test_string.c
new file mode 100644
index 000000000..9b84f94d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_string.c
@@ -0,0 +1,434 @@
+/* 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/. */
+/*
+ * test_string.c
+ *
+ * Tests Strings.
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createString(
+ PKIX_PL_String **testString,
+ PKIX_UInt32 format,
+ char *stringAscii,
+ PKIX_UInt32 length)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(format, stringAscii, length, testString, plContext));
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+createStringOther(
+ PKIX_PL_String **testEscAscii,
+ PKIX_PL_String **testUtf16,
+ PKIX_PL_String **ampString,
+ PKIX_PL_String **testDebugAscii,
+ PKIX_PL_String **testNullString,
+ PKIX_UInt32 *utf16data)
+{
+ char *nullText = "Hi&#x0000; there!";
+
+ char *escAsciiString =
+ "&#x00A1;&#x00010000;&#x0FFF;&#x00100001;";
+
+ char *debugAsciiString =
+ "string with&#x000A;newlines and&#x0009;tabs";
+
+ char *utfAmp = "\x00&";
+
+ PKIX_TEST_STD_VARS();
+
+ createString(testEscAscii,
+ PKIX_ESCASCII,
+ escAsciiString,
+ PL_strlen(escAsciiString));
+
+ createString(testUtf16, PKIX_UTF16, (char *)utf16data, 12);
+
+ createString(ampString, PKIX_UTF16, utfAmp, 2);
+
+ createString(testDebugAscii,
+ PKIX_ESCASCII_DEBUG,
+ debugAsciiString,
+ PL_strlen(debugAsciiString));
+
+ createString(testNullString,
+ PKIX_ESCASCII_DEBUG,
+ nullText,
+ PL_strlen(nullText));
+
+ goto cleanup;
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetEncoded(
+ PKIX_PL_String *testEscAscii,
+ PKIX_PL_String *testString0,
+ PKIX_PL_String *testDebugAscii,
+ PKIX_PL_String *testNullString,
+ PKIX_UInt32 *utf16data)
+{
+ char *temp = NULL;
+ void *dest = NULL;
+ void *dest2 = NULL;
+ char *plainText = "string with\nnewlines and\ttabs";
+ PKIX_UInt32 length, length2, i;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(testEscAscii,
+ PKIX_UTF16,
+ &dest,
+ &length,
+ plContext));
+ for (i = 0; i < length; i++) {
+ if (((char *)dest)[i] != ((char *)utf16data)[i]) {
+ testError("UTF-16 Data Differs from Source");
+ printf("%d-th char is different -%c-%c-\n", i,
+ ((char *)dest)[i], ((char *)utf16data)[i]);
+ }
+ }
+
+ length = 0;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(testNullString,
+ PKIX_UTF16,
+ &dest,
+ &length,
+ plContext));
+
+ length = 0;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(testString0,
+ PKIX_ESCASCII_DEBUG,
+ &dest,
+ &length,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(testDebugAscii,
+ PKIX_ESCASCII_DEBUG,
+ &dest2,
+ &length2,
+ plContext));
+
+ for (i = 0; (i < length) && (i < length2); i++)
+ if (((char *)dest)[i] != ((char *)dest2)[i]) {
+ testError("Equivalent strings are unequal");
+ break;
+ }
+
+ length = 0;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ length2 = 0;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest2, plContext));
+
+ temp = PKIX_String2ASCII(testDebugAscii, plContext);
+ if (temp) {
+ if (PL_strcmp(plainText, temp) != 0)
+ testError("Debugged ASCII does not match "
+ "equivalent EscAscii");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testSprintf(void)
+{
+ PKIX_Int32 x = 0xCAFE;
+ PKIX_Int32 y = -12345;
+ PKIX_PL_String *testString = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *sprintfString = NULL;
+ char *plainText = "Testing Sprintf";
+ char *format = "%s %x %u %d";
+ char *convertedFormat = "%s %lx %lu %ld";
+ char *temp = NULL;
+ char *temp2 = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ plainText,
+ PL_strlen(plainText),
+ &testString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ format,
+ 11,
+ &formatString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Sprintf(&sprintfString,
+ plContext,
+ formatString,
+ testString, x, y, y));
+ PKIX_TEST_DECREF_BC(testString);
+
+ temp = PR_smprintf(convertedFormat, plainText, x, y, y);
+ temp2 = PKIX_String2ASCII(sprintfString, plContext);
+
+ if (PL_strcmp(temp, temp2) != 0)
+ testError("Sprintf produced incorrect output");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp2, plContext));
+
+ PKIX_TEST_DECREF_BC(sprintfString);
+
+ PKIX_TEST_DECREF_BC(formatString);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testErrorHandling(void)
+{
+ char *debugAsciiString =
+ "string with&#x000A;newlines and&#x0009;tabs";
+
+ PKIX_PL_String *testString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ NULL,
+ 50,
+ &testString,
+ plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ "blah", 4, NULL, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Sprintf(&testString, plContext, NULL));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_GetString(0, NULL, &testString, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_GetString(0, "blah", 0, plContext));
+
+ /* ---------------------------- */
+ subTest("Unicode Error Handling");
+
+ /* &#x must be followed by 4 hexadecimal digits */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "&#x003k;",
+ 7,
+ &testString,
+ plContext));
+
+ /* &#x must be followed by 4 hexadecimal digits */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "abc&#x00",
+ 8,
+ &testString,
+ plContext));
+
+ /* &#x must be between 00010000-0010FFFF */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "&#x00200101;",
+ 11,
+ &testString,
+ plContext));
+
+ /* &#x must be followed by 8 hexadecimal digits */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "&#x001000",
+ 10,
+ &testString,
+ plContext));
+
+ /* &#x must be followed by 8 hexadecimal digits */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "&#x0010m00;",
+ 10,
+ &testString,
+ plContext));
+
+ /* Byte values D800-DFFF are reserved */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "&#xD800;",
+ 7,
+ &testString,
+ plContext));
+
+ /* Can't use &#x for regular characters */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "&#x0032;",
+ 7,
+ &testString,
+ plContext));
+
+ /* Can't use non-printable characters */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "\xA1",
+ 1,
+ &testString,
+ plContext));
+
+ /* Only legal \\ characters are \\, u and U */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "&blah",
+ 5,
+ &testString,
+ plContext));
+
+ /* Surrogate pairs must be legal */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_UTF16,
+ "\xd8\x00\x0\x66",
+ 4,
+ &testString,
+ plContext));
+
+ /* Debugged EscASCII should not be accepted as EscASCII */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ debugAsciiString,
+ PL_strlen(debugAsciiString),
+ &testString,
+ plContext));
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_String *string)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(string);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_string(int argc, char *argv[])
+{
+
+ PKIX_PL_String *testString[6] = { NULL };
+ PKIX_PL_String *testNullString = NULL;
+ PKIX_PL_String *testDebugAscii = NULL;
+ PKIX_PL_String *testEscAscii = NULL;
+ PKIX_PL_String *testUtf16 = NULL;
+ PKIX_PL_String *ampString = NULL;
+ unsigned char utf16Data[] = { 0x00, 0xA1, 0xD8, 0x00,
+ 0xDC, 0x00, 0x0F, 0xFF,
+ 0xDB, 0xC0, 0xDC, 0x01 };
+ PKIX_UInt32 i, size = 6;
+
+ char *plainText[6] = {
+ "string with\nnewlines and\ttabs",
+ "Not an escaped char: &amp;#x0012;",
+ "Encode &amp; with &amp;amp; in ASCII",
+ "&#x00A1;",
+ "&amp;",
+ "string with\nnewlines and\ttabs"
+ };
+
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Strings");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_String_Create <ascii format>");
+ for (i = 0; i < size; i++) {
+ testString[i] = NULL;
+ createString(&testString[i],
+ PKIX_ESCASCII,
+ plainText[i],
+ PL_strlen(plainText[i]));
+ }
+
+ subTest("PKIX_PL_String_Create <other formats>");
+ createStringOther(&testEscAscii,
+ &testUtf16,
+ &ampString,
+ &testDebugAscii,
+ &testNullString,
+ (PKIX_UInt32 *)utf16Data);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(testString[0],
+ testString[5],
+ testString[1],
+ plainText[0],
+ String,
+ PKIX_TRUE);
+
+ subTest("PKIX_PL_String_GetEncoded");
+ testGetEncoded(testEscAscii,
+ testString[0],
+ testDebugAscii,
+ testNullString,
+ (PKIX_UInt32 *)utf16Data);
+
+ subTest("PKIX_PL_Sprintf");
+ testSprintf();
+
+ subTest("PKIX_PL_String_Create <error_handling>");
+ testErrorHandling();
+
+ subTest("PKIX_PL_String_Destroy");
+ for (i = 0; i < size; i++) {
+ testDestroy(testString[i]);
+ }
+ testDestroy(testEscAscii);
+ testDestroy(testUtf16);
+ testDestroy(ampString);
+ testDestroy(testDebugAscii);
+ testDestroy(testNullString);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("String");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_string2.c b/security/nss/cmd/libpkix/pkix_pl/system/test_string2.c
new file mode 100644
index 000000000..c76d1e9ac
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_string2.c
@@ -0,0 +1,337 @@
+/* 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/. */
+/*
+ * test_string2.c
+ *
+ * Tests International Strings
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createString(
+ PKIX_PL_String **vivaEspanaString,
+ PKIX_PL_String **straussString,
+ PKIX_PL_String **gorbachevString,
+ PKIX_PL_String **testUTF16String,
+ PKIX_PL_String **chineseString,
+ PKIX_PL_String **jeanRenoString)
+{
+ /* this is meant to fail - it highlights bug 0002 */
+ unsigned char utf16String[4] = { 0xF8, 0x60,
+ 0xFC, 0x60 };
+
+ unsigned char chinese[16] = { 0xe7, 0xab, 0xa0,
+ 0xe5, 0xad, 0x90,
+ 0xe6, 0x80, 0xa1,
+ 0x20,
+ 0xe4, 0xb8, 0xad,
+ 0xe5, 0x9b, 0xbd };
+
+ char *jeanReno = "Jean R\303\251no is an actor.";
+ char *gorbachev = /* This is the name "Gorbachev" in cyrllic */
+ "\xd0\x93\xd0\xbe\xd1\x80\xd0\xb1\xd0\xb0\xd1\x87\xd1\x91\xd0\xb2";
+
+ char *vivaEspana =
+ "&#x00A1;Viva Espa&#x00f1;a!";
+
+ char *strauss =
+ "Strau&#x00Df; was born in &#x00D6;sterreich";
+
+ PKIX_TEST_STD_VARS();
+
+ /* ---------------------------- */
+ subTest("String Creation");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ vivaEspana,
+ PL_strlen(vivaEspana),
+ vivaEspanaString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ strauss,
+ PL_strlen(strauss),
+ straussString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_UTF8,
+ gorbachev,
+ PL_strlen(gorbachev),
+ gorbachevString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_UTF16,
+ utf16String,
+ 4,
+ testUTF16String,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_UTF8,
+ chinese,
+ 16,
+ chineseString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_UTF8,
+ jeanReno,
+ PL_strlen(jeanReno),
+ jeanRenoString,
+ plContext));
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetEncoded(PKIX_PL_String *string, PKIX_UInt32 format)
+{
+ void *dest = NULL;
+ PKIX_UInt32 length;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(string,
+ format,
+ &dest,
+ &length,
+ plContext));
+
+ if (dest) {
+ (void)printf("\tResult: %s\n", (char *)dest);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ }
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testHTMLOutput(
+ PKIX_PL_String *vivaEspanaString,
+ PKIX_PL_String *straussString,
+ PKIX_PL_String *gorbachevString,
+ PKIX_PL_String *testUTF16String,
+ PKIX_PL_String *chineseString,
+ PKIX_PL_String *jeanRenoString)
+{
+ void *dest = NULL;
+ PKIX_UInt32 length;
+
+ FILE *htmlFile = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ /* Opening a file for output */
+ htmlFile = fopen("utf8.html", "w");
+
+ if (htmlFile != plContext) {
+ (void)fprintf(htmlFile, "<html><head>\n");
+ (void)fprintf(htmlFile, "<meta http-equiv=\"Content-Type\"");
+ (void)fprintf(htmlFile,
+ "content = \"text/html; charset = UTF-8\">\n");
+ (void)fprintf(htmlFile, "</head><body>\n");
+ (void)fprintf(htmlFile, "<font size =\"+2\">\n");
+ } else
+ (void)printf("Could not open HTML file\n");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(testUTF16String,
+ PKIX_UTF8,
+ &dest,
+ &length,
+ plContext));
+ if (htmlFile != plContext) {
+ (void)printf("%d bytes written to HTML file\n",
+ fwrite(dest, length, 1, htmlFile));
+ (void)fprintf(htmlFile, "<BR>\n");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ dest = NULL;
+ length = 0;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(chineseString,
+ PKIX_UTF8,
+ &dest,
+ &length,
+ plContext));
+ if (htmlFile != plContext) {
+ (void)printf("%d bytes written to HTML file\n",
+ fwrite(dest, length, 1, htmlFile));
+ (void)fprintf(htmlFile, "<BR>\n");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ dest = NULL;
+ length = 0;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(jeanRenoString,
+ PKIX_UTF8,
+ &dest,
+ &length,
+ plContext));
+ if (htmlFile != plContext) {
+ (void)printf("%d bytes written to HTML file\n",
+ fwrite(dest, length, 1, htmlFile));
+ (void)fprintf(htmlFile, "<BR>\n");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ dest = NULL;
+ length = 0;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(vivaEspanaString,
+ PKIX_UTF8,
+ &dest,
+ &length,
+ plContext));
+ if (htmlFile != plContext) {
+ (void)printf("%d bytes written to HTML file\n",
+ fwrite(dest, length, 1, htmlFile));
+ (void)fprintf(htmlFile, "<BR>\n");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ dest = NULL;
+ length = 0;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(straussString,
+ PKIX_UTF8,
+ &dest,
+ &length,
+ plContext));
+ if (htmlFile != plContext) {
+ (void)printf("%d bytes written to HTML file\n",
+ fwrite(dest, length, 1, htmlFile));
+ (void)fprintf(htmlFile, "<BR>\n");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ dest = NULL;
+ length = 0;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(straussString,
+ PKIX_UTF8,
+ &dest,
+ &length,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ dest = NULL;
+ length = 0;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(gorbachevString,
+ PKIX_UTF8,
+ &dest,
+ &length,
+ plContext));
+ if (htmlFile != plContext) {
+ (void)printf("%d bytes written to HTML file\n",
+ fwrite(dest, length, 1, htmlFile));
+ (void)fprintf(htmlFile, "<BR>\n");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ dest = NULL;
+ length = 0;
+
+ if (htmlFile != plContext) {
+ (void)fprintf(htmlFile, "</font>\n");
+ (void)fprintf(htmlFile, "</body></html>\n");
+ (void)fclose(htmlFile);
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_String *string)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(string);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_string2(int argc, char *argv[])
+{
+
+ PKIX_PL_String *vivaEspanaString, *straussString, *testUTF16String;
+ PKIX_PL_String *chineseString, *jeanRenoString, *gorbachevString;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Unicode Strings");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_String_Create");
+ createString(&vivaEspanaString,
+ &straussString,
+ &gorbachevString,
+ &testUTF16String,
+ &chineseString,
+ &jeanRenoString);
+
+ subTest("Converting UTF-16 to EscASCII");
+ testGetEncoded(testUTF16String, PKIX_ESCASCII);
+
+ subTest("Converting UTF-8 to EscASCII");
+ testGetEncoded(chineseString, PKIX_ESCASCII);
+
+ subTest("Converting UTF-8 to EscASCII");
+ testGetEncoded(jeanRenoString, PKIX_ESCASCII);
+
+ subTest("Converting EscASCII to UTF-16");
+ testGetEncoded(vivaEspanaString, PKIX_UTF16);
+
+ subTest("Converting UTF-8 to UTF-16");
+ testGetEncoded(chineseString, PKIX_UTF16);
+
+ subTest("Creating HTML Output File \'utf8.html\'");
+ testHTMLOutput(vivaEspanaString,
+ straussString,
+ gorbachevString,
+ testUTF16String,
+ chineseString,
+ jeanRenoString);
+
+ subTest("Unicode Destructors");
+ testDestroy(testUTF16String);
+ testDestroy(chineseString);
+ testDestroy(jeanRenoString);
+ testDestroy(vivaEspanaString);
+ testDestroy(straussString);
+ testDestroy(gorbachevString);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Unicode Strings");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkixlibs.mk b/security/nss/cmd/libpkix/pkixlibs.mk
new file mode 100755
index 000000000..2e1eb154f
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkixlibs.mk
@@ -0,0 +1,27 @@
+#
+# 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/.
+
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+
+ifdef NS_USE_GCC
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib \
+ -lpkixutil \
+ $(NULL)
+else # ! NS_USE_GCC
+EXTRA_SHARED_LIBS += \
+ $(DIST)/lib/pkixutil.lib \
+ $(NULL)
+endif # NS_USE_GCC
+
+else
+
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib/ \
+ -lpkixutil \
+ $(NULL)
+
+endif
+
diff --git a/security/nss/cmd/libpkix/pkixrules.mk b/security/nss/cmd/libpkix/pkixrules.mk
new file mode 100755
index 000000000..bbaf85c56
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkixrules.mk
@@ -0,0 +1,7 @@
+#
+# 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/.
+
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
diff --git a/security/nss/cmd/libpkix/pkixutil/Makefile b/security/nss/cmd/libpkix/pkixutil/Makefile
new file mode 100644
index 000000000..a2cfa73bd
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkixutil/Makefile
@@ -0,0 +1,43 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/security/nss/cmd/libpkix/pkixutil/manifest.mn b/security/nss/cmd/libpkix/pkixutil/manifest.mn
new file mode 100644
index 000000000..180e995aa
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkixutil/manifest.mn
@@ -0,0 +1,41 @@
+#
+# 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/.
+
+PKIX_DEPTH = ..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ pkixutil.c \
+ $(NULL)
+
+PROGRAM = pkixutil
+
+TOOLS_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+EXTRA_LIBS += \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolperf.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolcertsel.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolparams.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolmodule.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolpki.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolsys.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolresults.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolstore.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtooltop.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolutil.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolsmplapps.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolchecker.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolcrlsel.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtooltestutil.$(LIB_SUFFIX) \
+ $(NULL)
+
+NO_MD_RELEASE = 1
+
+USE_STATIC_LIBS = 1
+
diff --git a/security/nss/cmd/libpkix/pkixutil/pkixutil.c b/security/nss/cmd/libpkix/pkixutil/pkixutil.c
new file mode 100644
index 000000000..158f45895
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkixutil/pkixutil.c
@@ -0,0 +1,299 @@
+/* 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/. */
+/*
+ * testwrapper.c
+ *
+ * Wrpper programm for libpkix tests.
+ *
+ */
+
+#include <stdio.h>
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+#include "nss.h"
+#include "secport.h"
+
+typedef int (*mainTestFn)(int argc, char *argv[]);
+
+extern int libpkix_buildthreads(int argc, char *argv[]);
+extern int nss_threads(int argc, char *argv[]);
+extern int test_certselector(int argc, char *argv[]);
+extern int test_comcertselparams(int argc, char *argv[]);
+extern int test_certchainchecker(int argc, char *argv[]);
+extern int test_comcrlselparams(int argc, char *argv[]);
+extern int test_crlselector(int argc, char *argv[]);
+
+extern int test_procparams(int argc, char *argv[]);
+extern int test_resourcelimits(int argc, char *argv[]);
+extern int test_trustanchor(int argc, char *argv[]);
+extern int test_valparams(int argc, char *argv[]);
+extern int test_buildresult(int argc, char *argv[]);
+extern int test_policynode(int argc, char *argv[]);
+extern int test_valresult(int argc, char *argv[]);
+extern int test_verifynode(int argc, char *argv[]);
+extern int test_store(int argc, char *argv[]);
+extern int test_basicchecker(int argc, char *argv[]);
+extern int test_basicconstraintschecker(int argc, char *argv[]);
+extern int test_buildchain(int argc, char *argv[]);
+extern int test_buildchain_partialchain(int argc, char *argv[]);
+extern int test_buildchain_resourcelimits(int argc, char *argv[]);
+extern int test_buildchain_uchecker(int argc, char *argv[]);
+extern int test_customcrlchecker(int argc, char *argv[]);
+extern int test_defaultcrlchecker2stores(int argc, char *argv[]);
+extern int test_ocsp(int argc, char *argv[]);
+extern int test_policychecker(int argc, char *argv[]);
+extern int test_subjaltnamechecker(int argc, char *argv[]);
+extern int test_validatechain(int argc, char *argv[]);
+extern int test_validatechain_NB(int argc, char *argv[]);
+extern int test_validatechain_bc(int argc, char *argv[]);
+extern int test_error(int argc, char *argv[]);
+extern int test_list(int argc, char *argv[]);
+extern int test_list2(int argc, char *argv[]);
+extern int test_logger(int argc, char *argv[]);
+extern int test_colcertstore(int argc, char *argv[]);
+extern int test_ekuchecker(int argc, char *argv[]);
+extern int test_httpcertstore(int argc, char *argv[]);
+extern int test_pk11certstore(int argc, char *argv[]);
+extern int test_socket(int argc, char *argv[]);
+extern int test_authorityinfoaccess(int argc, char *argv[]);
+extern int test_cert(int argc, char *argv[]);
+extern int test_crl(int argc, char *argv[]);
+extern int test_crlentry(int argc, char *argv[]);
+extern int test_date(int argc, char *argv[]);
+extern int test_generalname(int argc, char *argv[]);
+extern int test_nameconstraints(int argc, char *argv[]);
+extern int test_subjectinfoaccess(int argc, char *argv[]);
+extern int test_x500name(int argc, char *argv[]);
+extern int stress_test(int argc, char *argv[]);
+extern int test_bigint(int argc, char *argv[]);
+extern int test_bytearray(int argc, char *argv[]);
+extern int test_hashtable(int argc, char *argv[]);
+extern int test_mem(int argc, char *argv[]);
+extern int test_monitorlock(int argc, char *argv[]);
+extern int test_mutex(int argc, char *argv[]);
+extern int test_mutex2(int argc, char *argv[]);
+extern int test_mutex3(int argc, char *argv[]);
+extern int test_object(int argc, char *argv[]);
+extern int test_oid(int argc, char *argv[]);
+
+/* Taken out. Problem with build */
+/* extern int test_rwlock(int argc, char *argv[]); */
+extern int test_string(int argc, char *argv[]);
+extern int test_string2(int argc, char *argv[]);
+extern int build_chain(int argc, char *argv[]);
+extern int dumpcert(int argc, char *argv[]);
+extern int dumpcrl(int argc, char *argv[]);
+extern int validate_chain(int argc, char *argv[]);
+
+typedef struct {
+ char *fnName;
+ mainTestFn fnPointer;
+} testFunctionRef;
+
+testFunctionRef testFnRefTable[] = {
+ { "libpkix_buildthreads", libpkix_buildthreads },
+ { "nss_threads", nss_threads },
+ { "test_certselector", test_certselector },
+ { "test_comcertselparams", test_comcertselparams },
+ { "test_certchainchecker", test_certchainchecker },
+ { "test_comcrlselparams", test_comcrlselparams },
+ { "test_crlselector", test_crlselector },
+ { "test_procparams", test_procparams },
+ { "test_resourcelimits", test_resourcelimits },
+ { "test_trustanchor", test_trustanchor },
+ { "test_valparams", test_valparams },
+ { "test_buildresult", test_buildresult },
+ { "test_policynode", test_policynode },
+ { "test_valresult", test_valresult },
+ { "test_verifynode", test_verifynode },
+ { "test_store", test_store },
+ { "test_basicchecker", test_basicchecker },
+ { "test_basicconstraintschecker", test_basicconstraintschecker },
+ { "test_buildchain", test_buildchain },
+ { "test_buildchain_partialchain", test_buildchain_partialchain },
+ { "test_buildchain_resourcelimits", test_buildchain_resourcelimits },
+ { "test_buildchain_uchecker", test_buildchain_uchecker },
+ { "test_customcrlchecker", test_customcrlchecker },
+ { "test_defaultcrlchecker2stores", test_defaultcrlchecker2stores },
+ { "test_ocsp", test_ocsp },
+ { "test_policychecker", test_policychecker },
+ { "test_subjaltnamechecker", test_subjaltnamechecker },
+ { "test_validatechain", test_validatechain },
+ { "test_validatechain_NB", test_validatechain_NB },
+ { "test_validatechain_bc", test_validatechain_bc },
+ { "test_error", test_error },
+ { "test_list", test_list },
+ { "test_list2", test_list2 },
+ { "test_logger", test_logger },
+ { "test_colcertstore", test_colcertstore },
+ { "test_ekuchecker", test_ekuchecker },
+ { "test_httpcertstore", test_httpcertstore },
+ { "test_pk11certstore", test_pk11certstore },
+ { "test_socket", test_socket },
+ { "test_authorityinfoaccess", test_authorityinfoaccess },
+ { "test_cert", test_cert },
+ { "test_crl", test_crl },
+ { "test_crlentry", test_crlentry },
+ { "test_date", test_date },
+ { "test_generalname", test_generalname },
+ { "test_nameconstraints", test_nameconstraints },
+ { "test_subjectinfoaccess", test_subjectinfoaccess },
+ { "test_x500name", test_x500name },
+ { "stress_test", stress_test },
+ { "test_bigint", test_bigint },
+ { "test_bytearray", test_bytearray },
+ { "test_hashtable", test_hashtable },
+ { "test_mem", test_mem },
+ { "test_monitorlock", test_monitorlock },
+ { "test_mutex", test_mutex },
+ { "test_mutex2", test_mutex2 },
+ { "test_mutex3", test_mutex3 },
+ { "test_object", test_object },
+ { "test_oid", test_oid },
+ /* {"test_rwlock", test_rwlock }*/
+ { "test_string", test_string },
+ { "test_string2", test_string2 },
+ { "build_chain", build_chain },
+ { "dumpcert", dumpcert },
+ { "dumpcrl", dumpcrl },
+ { "validate_chain", validate_chain },
+ { NULL, NULL },
+};
+
+static void
+printUsage(char *cmdName)
+{
+ int fnCounter = 0;
+
+ fprintf(stderr, "Usage: %s [test name] [arg1]...[argN]\n\n", cmdName);
+ fprintf(stderr, "List of possible names for the tests:");
+ while (testFnRefTable[fnCounter].fnName != NULL) {
+ if (fnCounter % 2 == 0) {
+ fprintf(stderr, "\n");
+ }
+ fprintf(stderr, " %-35s ", testFnRefTable[fnCounter].fnName);
+ fnCounter += 1;
+ }
+ fprintf(stderr, "\n");
+}
+
+static SECStatus
+getTestArguments(int argc,
+ char **argv,
+ mainTestFn *ptestFn,
+ char **pdbPath,
+ int *pargc,
+ char ***pargv)
+{
+ PLOptState *optstate = NULL;
+ PLOptStatus status;
+ mainTestFn testFunction = NULL;
+ char **wArgv = NULL;
+ char *dbPath = NULL;
+ char *fnName = NULL;
+ int wArgc = 0;
+ int fnCounter = 0;
+
+ if (argc < 2) {
+ printf("ERROR: insufficient number of arguments: %s.\n", fnName);
+ return SECFailure;
+ }
+
+ fnName = argv[1];
+ while (testFnRefTable[fnCounter].fnName != NULL) {
+ if (!PORT_Strcmp(fnName, testFnRefTable[fnCounter].fnName)) {
+ testFunction = testFnRefTable[fnCounter].fnPointer;
+ break;
+ }
+ fnCounter += 1;
+ }
+ if (!testFunction) {
+ printf("ERROR: unknown name of the test: %s.\n", fnName);
+ return SECFailure;
+ }
+
+ wArgv = PORT_ZNewArray(char *, argc);
+ if (!wArgv) {
+ return SECFailure;
+ }
+
+ /* set name of the function as a first arg and increment arg count. */
+ wArgv[0] = fnName;
+ wArgc += 1;
+
+ optstate = PL_CreateOptState(argc - 1, argv + 1, "d:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'd':
+ dbPath = (char *)optstate->value;
+ break;
+
+ default:
+ wArgv[wArgc] = (char *)optstate->value;
+ wArgc += 1;
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+
+ *ptestFn = testFunction;
+ *pdbPath = dbPath;
+ *pargc = wArgc;
+ *pargv = wArgv;
+
+ return SECSuccess;
+}
+
+static int
+runCmd(mainTestFn fnPointer,
+ int argc,
+ char **argv,
+ char *dbPath)
+{
+ int retStat = 0;
+
+ /* Initialize NSPR and NSS. */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ /* if using databases, use NSS_Init and not NSS_NoDB_Init */
+ if (dbPath && PORT_Strlen(dbPath) != 0) {
+ if (NSS_Init(dbPath) != SECSuccess)
+ return SECFailure;
+ } else {
+ if (NSS_NoDB_Init(NULL) != 0)
+ return SECFailure;
+ }
+ retStat = fnPointer(argc, argv);
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ PR_Cleanup();
+ return retStat;
+}
+
+int
+main(int argc, char **argv)
+{
+ mainTestFn testFunction = NULL;
+ char *dbPath = NULL;
+ char **testArgv = NULL;
+ int testArgc = 0;
+ int rv = 0;
+
+ rv = getTestArguments(argc, argv, &testFunction, &dbPath,
+ &testArgc, &testArgv);
+ if (rv != SECSuccess) {
+ printUsage(argv[0]);
+ return 1;
+ }
+
+ rv = runCmd(testFunction, testArgc, testArgv, dbPath);
+
+ PORT_Free(testArgv);
+
+ return rv;
+}
diff --git a/security/nss/cmd/libpkix/sample_apps/Makefile b/security/nss/cmd/libpkix/sample_apps/Makefile
new file mode 100755
index 000000000..daa876577
--- /dev/null
+++ b/security/nss/cmd/libpkix/sample_apps/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/security/nss/cmd/libpkix/sample_apps/build_chain.c b/security/nss/cmd/libpkix/sample_apps/build_chain.c
new file mode 100644
index 000000000..38bf1d9f3
--- /dev/null
+++ b/security/nss/cmd/libpkix/sample_apps/build_chain.c
@@ -0,0 +1,242 @@
+/* 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/. */
+/*
+ * buildChain.c
+ *
+ * Tests Cert Chain Building
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+
+#include "pkix_pl_generalname.h"
+#include "pkix_pl_cert.h"
+#include "pkix.h"
+#include "testutil.h"
+#include "prlong.h"
+#include "plstr.h"
+#include "prthread.h"
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "secitem.h"
+#include "keythi.h"
+#include "nss.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\tbuildChain "
+ "<trustedCert> <targetCert> <certStoreDirectory>\n\n");
+ (void)printf("Builds a chain of certificates between "
+ "<trustedCert> and <targetCert>\n"
+ "using the certs and CRLs in <certStoreDirectory>.\n");
+}
+
+static PKIX_PL_Cert *
+createCert(char *inFileName)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ void *buf = NULL;
+ PRFileDesc *inFile = NULL;
+ PKIX_UInt32 len;
+ SECItem certDER;
+ SECStatus rv;
+ /* default: NULL cert (failure case) */
+ PKIX_PL_Cert *cert = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certDER.data = NULL;
+
+ inFile = PR_Open(inFileName, PR_RDONLY, 0);
+
+ if (!inFile) {
+ pkixTestErrorMsg = "Unable to open cert file";
+ goto cleanup;
+ } else {
+ rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE, PR_FALSE);
+ if (!rv) {
+ buf = (void *)certDER.data;
+ len = certDER.len;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_Create(byteArray, &cert, plContext));
+
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ } else {
+ pkixTestErrorMsg = "Unable to read DER from cert file";
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ if (inFile) {
+ PR_Close(inFile);
+ }
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ }
+
+ PKIX_TEST_DECREF_AC(byteArray);
+
+ PKIX_TEST_RETURN();
+
+ return (cert);
+}
+
+int
+build_chain(int argc, char *argv[])
+{
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ char *trustedCertFile = NULL;
+ char *targetCertFile = NULL;
+ char *storeDirAscii = NULL;
+ PKIX_PL_String *storeDirString = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_UInt32 actualMinorVersion, numCerts, i;
+ PKIX_UInt32 j = 0;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_List *certStores = NULL;
+ char *asciiResult = NULL;
+ PKIX_Boolean useArenas = PKIX_FALSE;
+ void *buildState = NULL; /* needed by pkix_build for non-blocking I/O */
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 4) {
+ printUsage();
+ return (0);
+ }
+
+ useArenas = PKIX_TEST_ARENAS_ARG(argv[1]);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Initialize(PKIX_TRUE, /* nssInitNeeded */
+ useArenas,
+ PKIX_MAJOR_VERSION,
+ PKIX_MINOR_VERSION,
+ PKIX_MINOR_VERSION,
+ &actualMinorVersion,
+ &plContext));
+
+ /* create processing params with list of trust anchors */
+ trustedCertFile = argv[j + 1];
+ trustedCert = createCert(trustedCertFile);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert(trustedCert, &anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create(anchors, &procParams, plContext));
+
+ /* create CertSelector with target certificate in params */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+ targetCertFile = argv[j + 2];
+ targetCert = createCert(targetCertFile);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate(certSelParams, targetCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));
+
+ /* create CertStores */
+
+ storeDirAscii = argv[j + 3];
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, storeDirAscii, 0, &storeDirString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(storeDirString, &certStore, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certStores, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores(procParams, certStores, plContext));
+
+ /* build cert chain using processing params and return buildResult */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildChain(procParams,
+ &nbioContext,
+ &buildState,
+ &buildResult,
+ NULL,
+ plContext));
+
+ /*
+ * As long as we use only CertStores with blocking I/O, we can omit
+ * checking for completion with nbioContext.
+ */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetCertChain(buildResult, &certs, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ printf("\n");
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, i, (PKIX_PL_Object **)&cert, plContext));
+
+ asciiResult = PKIX_Cert2ASCII(cert);
+
+ printf("CERT[%d]:\n%s\n", i, asciiResult);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, plContext));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ (void)printf("FAILED TO BUILD CHAIN\n");
+ } else {
+ (void)printf("SUCCESSFULLY BUILT CHAIN\n");
+ }
+
+ PKIX_PL_Free(asciiResult, plContext);
+
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(certStores);
+ PKIX_TEST_DECREF_AC(storeDirString);
+ PKIX_TEST_DECREF_AC(trustedCert);
+ PKIX_TEST_DECREF_AC(targetCert);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(buildResult);
+
+ PKIX_TEST_RETURN();
+
+ PKIX_Shutdown(plContext);
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/sample_apps/dumpcert.c b/security/nss/cmd/libpkix/sample_apps/dumpcert.c
new file mode 100644
index 000000000..6ff5f8377
--- /dev/null
+++ b/security/nss/cmd/libpkix/sample_apps/dumpcert.c
@@ -0,0 +1,182 @@
+/* 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/. */
+/*
+ * dumpcert.c
+ *
+ * dump certificate sample application
+ *
+ */
+
+#include <stdio.h>
+
+#include "pkix.h"
+#include "testutil.h"
+#include "prlong.h"
+#include "plstr.h"
+#include "prthread.h"
+#include "plarena.h"
+#include "seccomon.h"
+#include "secdert.h"
+#include "secasn1t.h"
+#include "certt.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\tdumpcert <certFile>\n");
+ (void)printf("\tParses a certificate located at <certFile> "
+ "and displays it.\n");
+}
+
+static void
+printFailure(char *msg)
+{
+ (void)printf("FAILURE: %s\n", msg);
+}
+
+static PKIX_PL_Cert *
+createCert(char *inFileName)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_Error *error = NULL;
+ PRFileDesc *inFile = NULL;
+ SECItem certDER;
+ void *buf = NULL;
+ PKIX_UInt32 len;
+ SECStatus rv = SECFailure;
+
+ certDER.data = NULL;
+
+ inFile = PR_Open(inFileName, PR_RDONLY, 0);
+
+ if (!inFile) {
+ printFailure("Unable to open cert file");
+ goto cleanup;
+ } else {
+ rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE, PR_FALSE);
+ if (!rv) {
+ buf = (void *)certDER.data;
+ len = certDER.len;
+
+ error = PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext);
+
+ if (error) {
+ printFailure("PKIX_PL_ByteArray_Create failed");
+ goto cleanup;
+ }
+
+ error = PKIX_PL_Cert_Create(byteArray, &cert, plContext);
+
+ if (error) {
+ printFailure("PKIX_PL_Cert_Create failed");
+ goto cleanup;
+ }
+ } else {
+ printFailure("Unable to read DER from cert file");
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ if (inFile) {
+ PR_Close(inFile);
+ }
+
+ if (rv == SECSuccess) {
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ }
+
+ if (byteArray) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(byteArray), plContext);
+ }
+
+ return (cert);
+}
+
+int
+dumpcert(int argc, char *argv[])
+{
+
+ PKIX_PL_String *string = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_Error *error = NULL;
+ char *ascii = NULL;
+ PKIX_UInt32 length = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean useArenas = PKIX_FALSE;
+ PKIX_UInt32 actualMinorVersion;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc == 1) {
+ printUsage();
+ return (0);
+ }
+
+ useArenas = PKIX_TEST_ARENAS_ARG(argv[1]);
+
+ PKIX_Initialize(PKIX_TRUE, /* nssInitNeeded */
+ useArenas,
+ PKIX_MAJOR_VERSION,
+ PKIX_MINOR_VERSION,
+ PKIX_MINOR_VERSION,
+ &actualMinorVersion,
+ &plContext);
+
+ cert = createCert(argv[1 + j]);
+
+ if (cert) {
+
+ error = PKIX_PL_Object_ToString((PKIX_PL_Object *)cert, &string, plContext);
+
+ if (error) {
+ printFailure("Unable to get string representation "
+ "of cert");
+ goto cleanup;
+ }
+
+ error = PKIX_PL_String_GetEncoded(string,
+ PKIX_ESCASCII,
+ (void **)&ascii,
+ &length,
+ plContext);
+
+ if (error || !ascii) {
+ printFailure("Unable to get ASCII encoding of string");
+ goto cleanup;
+ }
+
+ (void)printf("OUTPUT:\n%s\n", ascii);
+
+ } else {
+ printFailure("Unable to create certificate");
+ goto cleanup;
+ }
+
+cleanup:
+
+ if (cert) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(cert), plContext);
+ }
+
+ if (string) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(string), plContext);
+ }
+
+ if (ascii) {
+ PKIX_PL_Free((PKIX_PL_Object *)(ascii), plContext);
+ }
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("DUMPCERT");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/sample_apps/dumpcrl.c b/security/nss/cmd/libpkix/sample_apps/dumpcrl.c
new file mode 100644
index 000000000..642601409
--- /dev/null
+++ b/security/nss/cmd/libpkix/sample_apps/dumpcrl.c
@@ -0,0 +1,186 @@
+/* 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/. */
+/*
+ * dumpcrl.c
+ *
+ * dump CRL sample application
+ *
+ */
+
+#include <stdio.h>
+
+#include "pkix.h"
+#include "testutil.h"
+#include "prlong.h"
+#include "plstr.h"
+#include "prthread.h"
+#include "plarena.h"
+#include "seccomon.h"
+#include "secdert.h"
+#include "secasn1t.h"
+#include "certt.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\tdumpcrl <crlFile>\n");
+ (void)printf("\tParses a CRL located at <crlFile> "
+ "and displays it.\n");
+}
+
+static void
+printFailure(char *msg)
+{
+ (void)printf("FAILURE: %s\n", msg);
+}
+
+static PKIX_PL_CRL *
+createCRL(char *inFileName)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_Error *error = NULL;
+ PRFileDesc *inFile = NULL;
+ SECItem crlDER;
+ void *buf = NULL;
+ PKIX_UInt32 len;
+ SECStatus rv;
+
+ PKIX_TEST_STD_VARS();
+
+ crlDER.data = NULL;
+
+ inFile = PR_Open(inFileName, PR_RDONLY, 0);
+
+ if (!inFile) {
+ printFailure("Unable to open crl file");
+ goto cleanup;
+ } else {
+ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
+ if (!rv) {
+ buf = (void *)crlDER.data;
+ len = crlDER.len;
+
+ error = PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext);
+
+ if (error) {
+ printFailure("PKIX_PL_ByteArray_Create failed");
+ goto cleanup;
+ }
+
+ error = PKIX_PL_CRL_Create(byteArray, &crl, plContext);
+ if (error) {
+ printFailure("PKIX_PL_CRL_Create failed");
+ goto cleanup;
+ }
+
+ SECITEM_FreeItem(&crlDER, PR_FALSE);
+ } else {
+ printFailure("Unable to read DER from crl file");
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ if (inFile) {
+ PR_Close(inFile);
+ }
+
+ if (error) {
+ SECITEM_FreeItem(&crlDER, PR_FALSE);
+ }
+
+ if (byteArray) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(byteArray), plContext);
+ }
+
+ PKIX_TEST_RETURN();
+
+ return (crl);
+}
+
+int
+dumpcrl(int argc, char *argv[])
+{
+
+ PKIX_PL_String *string = NULL;
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_Error *error = NULL;
+ char *ascii = NULL;
+ PKIX_UInt32 length;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean useArenas = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc == 1) {
+ printUsage();
+ return (0);
+ }
+
+ useArenas = PKIX_TEST_ARENAS_ARG(argv[1]);
+
+ PKIX_Initialize(PKIX_TRUE, /* nssInitNeeded */
+ useArenas,
+ PKIX_MAJOR_VERSION,
+ PKIX_MINOR_VERSION,
+ PKIX_MINOR_VERSION,
+ &actualMinorVersion,
+ &plContext);
+
+ crl = createCRL(argv[j + 1]);
+
+ if (crl) {
+
+ error = PKIX_PL_Object_ToString((PKIX_PL_Object *)crl, &string, plContext);
+
+ if (error) {
+ printFailure("Unable to get string representation "
+ "of crl");
+ goto cleanup;
+ }
+
+ error = PKIX_PL_String_GetEncoded(string,
+ PKIX_ESCASCII,
+ (void **)&ascii,
+ &length,
+ plContext);
+ if (error || !ascii) {
+ printFailure("Unable to get ASCII encoding of string");
+ goto cleanup;
+ }
+
+ (void)printf("OUTPUT:\n%s\n", ascii);
+
+ } else {
+ printFailure("Unable to create CRL");
+ goto cleanup;
+ }
+
+cleanup:
+
+ if (crl) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(crl), plContext);
+ }
+
+ if (string) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(string), plContext);
+ }
+
+ if (ascii) {
+ PKIX_PL_Free((PKIX_PL_Object *)(ascii), plContext);
+ }
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("DUMPCRL");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/sample_apps/manifest.mn b/security/nss/cmd/libpkix/sample_apps/manifest.mn
new file mode 100755
index 000000000..32926cc1b
--- /dev/null
+++ b/security/nss/cmd/libpkix/sample_apps/manifest.mn
@@ -0,0 +1,23 @@
+#
+# 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/.
+
+PKIX_DEPTH = ..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = dumpcert.c \
+ dumpcrl.c \
+ validate_chain.c \
+ build_chain.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtoolsmplapps
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/sample_apps/validate_chain.c b/security/nss/cmd/libpkix/sample_apps/validate_chain.c
new file mode 100644
index 000000000..1ccf364e0
--- /dev/null
+++ b/security/nss/cmd/libpkix/sample_apps/validate_chain.c
@@ -0,0 +1,220 @@
+/* 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/. */
+/*
+ * validateChain.c
+ *
+ * Tests Cert Chain Validation
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+
+#include "pkix_pl_generalname.h"
+#include "pkix_pl_cert.h"
+#include "pkix.h"
+#include "testutil.h"
+#include "prlong.h"
+#include "plstr.h"
+#include "prthread.h"
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "secitem.h"
+#include "keythi.h"
+#include "nss.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\tvalidateChain <trustedCert> "
+ "<cert_1> <cert_2> ... <cert_n>\n");
+ (void)printf("\tValidates a chain of n certificates "
+ "using the given trust anchor.\n");
+}
+
+static PKIX_PL_Cert *
+createCert(char *inFileName)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ void *buf = NULL;
+ PRFileDesc *inFile = NULL;
+ PKIX_UInt32 len;
+ SECItem certDER;
+ SECStatus rv;
+ /* default: NULL cert (failure case) */
+ PKIX_PL_Cert *cert = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certDER.data = NULL;
+
+ inFile = PR_Open(inFileName, PR_RDONLY, 0);
+
+ if (!inFile) {
+ pkixTestErrorMsg = "Unable to open cert file";
+ goto cleanup;
+ } else {
+ rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE, PR_FALSE);
+ if (!rv) {
+ buf = (void *)certDER.data;
+ len = certDER.len;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_Create(byteArray, &cert, plContext));
+
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ } else {
+ pkixTestErrorMsg = "Unable to read DER from cert file";
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ if (inFile) {
+ PR_Close(inFile);
+ }
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ }
+
+ PKIX_TEST_DECREF_AC(byteArray);
+
+ PKIX_TEST_RETURN();
+
+ return (cert);
+}
+
+int
+validate_chain(int argc, char *argv[])
+{
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_PL_X500Name *subject = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+
+ char *trustedCertFile = NULL;
+ char *chainCertFile = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *chainCert = NULL;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 actualMinorVersion;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 3) {
+ printUsage();
+ return (0);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ chainLength = (argc - j) - 2;
+
+ /* create processing params with list of trust anchors */
+ trustedCertFile = argv[1 + j];
+ trustedCert = createCert(trustedCertFile);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(trustedCert, &subject, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+#if 0
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubject
+ (certSelParams, subject, plContext));
+#endif
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext));
+
+ PKIX_TEST_DECREF_BC(subject);
+ PKIX_TEST_DECREF_BC(certSelParams);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert(trustedCert, &anchor, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create(anchors, &procParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));
+
+ PKIX_TEST_DECREF_BC(certSelector);
+
+ /* create cert chain */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certs, plContext));
+ for (i = 0; i < chainLength; i++) {
+ chainCertFile = argv[(i + j) + 2];
+ chainCert = createCert(chainCertFile);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certs,
+ (PKIX_PL_Object *)chainCert,
+ plContext));
+
+ PKIX_TEST_DECREF_BC(chainCert);
+ chainCert = NULL;
+ }
+ /* create validate params with processing params and cert chain */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_Create(procParams, certs, &valParams, plContext));
+
+ PKIX_TEST_DECREF_BC(trustedCert);
+ trustedCert = NULL;
+ PKIX_TEST_DECREF_BC(anchor);
+ anchor = NULL;
+ PKIX_TEST_DECREF_BC(anchors);
+ anchors = NULL;
+ PKIX_TEST_DECREF_BC(certs);
+ certs = NULL;
+ PKIX_TEST_DECREF_BC(procParams);
+ procParams = NULL;
+
+ /* validate cert chain using processing params and return valResult */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+
+ if (valResult != NULL) {
+ (void)printf("SUCCESSFULLY VALIDATED\n");
+ }
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ (void)printf("FAILED TO VALIDATE\n");
+ (void)PKIX_PL_Object_ToString((PKIX_PL_Object *)verifyTree, &verifyString, plContext);
+ (void)printf("verifyTree is\n%s\n", verifyString->escAsciiString);
+ PKIX_TEST_DECREF_AC(verifyString);
+ }
+
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(valParams);
+
+ PKIX_TEST_RETURN();
+
+ PKIX_Shutdown(plContext);
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/testutil/Makefile b/security/nss/cmd/libpkix/testutil/Makefile
new file mode 100755
index 000000000..859aedd7d
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/Makefile
@@ -0,0 +1,51 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include $(PLAT_DEPTH)/platrules.mk
+
+export:: private_export
+
diff --git a/security/nss/cmd/libpkix/testutil/config.mk b/security/nss/cmd/libpkix/testutil/config.mk
new file mode 100644
index 000000000..820dbb2d4
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/config.mk
@@ -0,0 +1,15 @@
+#
+# 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/.
+
+# don't build the static library
+LIBRARY =
+
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+
+# don't want the 32 in the shared library name
+SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
+IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX)
+
+endif
diff --git a/security/nss/cmd/libpkix/testutil/manifest.mn b/security/nss/cmd/libpkix/testutil/manifest.mn
new file mode 100755
index 000000000..2f831fcd6
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/manifest.mn
@@ -0,0 +1,26 @@
+#
+# 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/.
+
+PKIX_DEPTH = ..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+
+MODULE = nss
+
+PRIVATE_EXPORTS = \
+ testutil_nss.h \
+ testutil.h \
+ $(NULL)
+
+CSRCS = \
+ testutil_nss.c \
+ testutil.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixtooltestutil
+
+SOURCE_LIB_DIR = $(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/testutil/pkixutil.def b/security/nss/cmd/libpkix/testutil/pkixutil.def
new file mode 100644
index 000000000..407d40a31
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/pkixutil.def
@@ -0,0 +1,48 @@
+;+#
+;+# 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/.
+;+#
+;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
+;+# 1. For all unix platforms, the string ";-" means "remove this line"
+;+# 2. For all unix platforms, the string " DATA " will be removed from any
+;+# line on which it occurs.
+;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
+;+# On AIX, lines containing ";+" will be removed.
+;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
+;+# 5. For all unix platforms, after the above processing has taken place,
+;+# all characters after the first ";" on the line will be removed.
+;+# And for AIX, the first ";" will also be removed.
+;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
+;+# directives are hidden behind ";", ";+", and ";-"
+;+
+;+NSS_3.12 { # NSS 3.12 release
+;+ global:
+LIBRARY pkixutil ;-
+EXPORTS ;-
+createBuildResult;
+createCRL;
+createCert;
+createCertChain;
+createCertChainPlus;
+createDate;
+createGeneralName;
+createProcessingParams;
+createTrustAnchor;
+createValidateParams;
+createValidateResult;
+endTests;
+startTests;
+subTest;
+testDuplicateHelper;
+testEqualsHelper;
+testError;
+testErrorUndo;
+testHashcodeHelper;
+testToStringHelper;
+PKIX_Cert2ASCII;
+PKIX_Error2ASCII;
+PKIX_String2ASCII;
+;+ local:
+;+ *;
+;+};
diff --git a/security/nss/cmd/libpkix/testutil/testutil.c b/security/nss/cmd/libpkix/testutil/testutil.c
new file mode 100644
index 000000000..0f438ba43
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/testutil.c
@@ -0,0 +1,576 @@
+/* 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/. */
+/*
+ * testutil.c
+ *
+ * Utility error handling functions
+ *
+ */
+
+#include "testutil.h"
+
+/*
+ * static global variable to keep track of total number of errors for
+ * a particular test suite (eg. all the OID tests)
+ */
+static int errCount = 0;
+
+/*
+ * FUNCTION: startTests
+ * DESCRIPTION:
+ *
+ * Prints standard message for starting the test suite with the name pointed
+ * to by "testName". This function should be called in the beginning of every
+ * test suite.
+ *
+ * PARAMETERS:
+ * "testName"
+ * Address of string representing name of test suite.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "errCount"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+startTests(char *testName)
+{
+ (void)printf("*START OF TESTS FOR %s:\n", testName);
+ errCount = 0;
+}
+
+/*
+ * FUNCTION: endTests
+ * DESCRIPTION:
+ *
+ * Prints standard message for ending the test suite with the name pointed
+ * to by "testName", followed by a success/failure message. This function
+ * should be called at the end of every test suite.
+ *
+ * PARAMETERS:
+ * "testName"
+ * Address of string representing name of test suite.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "errCount"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+endTests(char *testName)
+{
+ char plural = ' ';
+
+ (void)printf("*END OF TESTS FOR %s: ", testName);
+ if (errCount > 0) {
+ if (errCount > 1)
+ plural = 's';
+ (void)printf("%d SUBTEST%c FAILED.\n\n", errCount, plural);
+ } else {
+ (void)printf("ALL TESTS COMPLETED SUCCESSFULLY.\n\n");
+ }
+}
+
+/*
+ * FUNCTION: subTest
+ * DESCRIPTION:
+ *
+ * Prints standard message for starting the subtest with the name pointed to
+ * by "subTestName". This function should be called at the beginning of each
+ * subtest.
+ *
+ * PARAMETERS:
+ * "subTestName"
+ * Address of string representing name of subTest.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+subTest(char *subTestName)
+{
+ (void)printf("TESTING: %s ...\n", subTestName);
+}
+
+/*
+ * FUNCTION: testErrorUndo
+ * DESCRIPTION:
+ *
+ * Decrements the global variable "errCount" and prints a test failure
+ * expected message followed by the string pointed to by "msg". This function
+ * should be called when an expected error condition is encountered in the
+ * tests. Calling this function *correct* the previous errCount increment.
+ * It should only be called ONCE per subtest.
+ *
+ * PARAMETERS:
+ * "msg"
+ * Address of text of error message.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "errCount"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+testErrorUndo(char *msg)
+{
+ --errCount;
+ (void)printf("TEST FAILURE *** EXPECTED *** :%s\n", msg);
+}
+
+/*
+ * FUNCTION: testError
+ * DESCRIPTION:
+ *
+ * Increments the global variable "errCount" and prints a standard test
+ * failure message followed by the string pointed to by "msg". This function
+ * should be called when an unexpected error condition is encountered in the
+ * tests. It should only be called ONCE per subtest.
+ *
+ * PARAMETERS:
+ * "msg"
+ * Address of text of error message.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "errCount"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+testError(char *msg)
+{
+ ++errCount;
+ (void)printf("TEST FAILURE: %s\n", msg);
+}
+
+/*
+ * FUNCTION: PKIX_String2ASCII
+ * DESCRIPTION:
+ *
+ * Converts String object pointed to by "string" to its ASCII representation
+ * and returns the converted value. Returns NULL upon failure.
+ *
+ * XXX Might want to use ESCASCII_DEBUG to show control characters, etc.
+ *
+ * PARAMETERS:
+ * "string"
+ * Address of String to be converted to ASCII. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns the ASCII representation of "string" upon success;
+ * NULL upon failure.
+ */
+char *
+PKIX_String2ASCII(PKIX_PL_String *string, void *plContext)
+{
+ PKIX_UInt32 length;
+ char *asciiString = NULL;
+ PKIX_Error *errorResult;
+
+ errorResult = PKIX_PL_String_GetEncoded(string,
+ PKIX_ESCASCII,
+ (void **)&asciiString,
+ &length,
+ plContext);
+
+ if (errorResult)
+ goto cleanup;
+
+cleanup:
+
+ if (errorResult) {
+ return (NULL);
+ }
+
+ return (asciiString);
+}
+
+/*
+ * FUNCTION: PKIX_Error2ASCII
+ * DESCRIPTION:
+ *
+ * Converts Error pointed to by "error" to its ASCII representation and
+ * returns the converted value. Returns NULL upon failure.
+ *
+ * PARAMETERS:
+ * "error"
+ * Address of Error to be converted to ASCII. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns the ASCII representation of "error" upon success;
+ * NULL upon failure.
+ */
+char *
+PKIX_Error2ASCII(PKIX_Error *error, void *plContext)
+{
+ PKIX_UInt32 length;
+ char *asciiString = NULL;
+ PKIX_PL_String *pkixString = NULL;
+ PKIX_Error *errorResult = NULL;
+
+ errorResult = PKIX_PL_Object_ToString((PKIX_PL_Object *)error, &pkixString, plContext);
+ if (errorResult)
+ goto cleanup;
+
+ errorResult = PKIX_PL_String_GetEncoded(pkixString,
+ PKIX_ESCASCII,
+ (void **)&asciiString,
+ &length,
+ plContext);
+
+cleanup:
+
+ if (pkixString) {
+ if (PKIX_PL_Object_DecRef((PKIX_PL_Object *)pkixString, plContext)) {
+ return (NULL);
+ }
+ }
+
+ if (errorResult) {
+ return (NULL);
+ }
+
+ return (asciiString);
+}
+
+/*
+ * FUNCTION: PKIX_Object2ASCII
+ * DESCRIPTION:
+ *
+ * Converts Object pointed to by "object" to its ASCII representation and
+ * returns the converted value. Returns NULL upon failure.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object to be converted to ASCII. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns the ASCII representation of "object" upon success;
+ * NULL upon failure.
+ */
+char *
+PKIX_Object2ASCII(PKIX_PL_Object *object)
+{
+ PKIX_UInt32 length;
+ char *asciiString = NULL;
+ PKIX_PL_String *pkixString = NULL;
+ PKIX_Error *errorResult = NULL;
+
+ errorResult = PKIX_PL_Object_ToString(object, &pkixString, NULL);
+ if (errorResult)
+ goto cleanup;
+
+ errorResult = PKIX_PL_String_GetEncoded(pkixString, PKIX_ESCASCII, (void **)&asciiString, &length, NULL);
+
+cleanup:
+
+ if (pkixString) {
+ if (PKIX_PL_Object_DecRef((PKIX_PL_Object *)pkixString, NULL)) {
+ return (NULL);
+ }
+ }
+
+ if (errorResult) {
+ return (NULL);
+ }
+
+ return (asciiString);
+}
+
+/*
+ * FUNCTION: PKIX_Cert2ASCII
+ * DESCRIPTION:
+ *
+ * Converts Cert pointed to by "cert" to its partial ASCII representation and
+ * returns the converted value. Returns NULL upon failure.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert to be converted to ASCII. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns the partial ASCII representation of "cert" upon success;
+ * NULL upon failure.
+ */
+char *
+PKIX_Cert2ASCII(PKIX_PL_Cert *cert)
+{
+ PKIX_PL_X500Name *issuer = NULL;
+ void *issuerAscii = NULL;
+ PKIX_PL_X500Name *subject = NULL;
+ void *subjectAscii = NULL;
+ void *asciiString = NULL;
+ PKIX_Error *errorResult = NULL;
+ PKIX_UInt32 numChars;
+
+ /* Issuer */
+ errorResult = PKIX_PL_Cert_GetIssuer(cert, &issuer, NULL);
+ if (errorResult)
+ goto cleanup;
+
+ issuerAscii = PKIX_Object2ASCII((PKIX_PL_Object *)issuer);
+
+ /* Subject */
+ errorResult = PKIX_PL_Cert_GetSubject(cert, &subject, NULL);
+ if (errorResult)
+ goto cleanup;
+
+ if (subject) {
+ subjectAscii = PKIX_Object2ASCII((PKIX_PL_Object *)subject);
+ }
+
+ errorResult = PKIX_PL_Malloc(200, &asciiString, NULL);
+ if (errorResult)
+ goto cleanup;
+
+ numChars =
+ PR_snprintf(asciiString,
+ 200,
+ "Issuer=%s\nSubject=%s\n",
+ issuerAscii,
+ subjectAscii);
+
+ if (!numChars)
+ goto cleanup;
+
+cleanup:
+
+ if (issuer) {
+ if (PKIX_PL_Object_DecRef((PKIX_PL_Object *)issuer, NULL)) {
+ return (NULL);
+ }
+ }
+
+ if (subject) {
+ if (PKIX_PL_Object_DecRef((PKIX_PL_Object *)subject, NULL)) {
+ return (NULL);
+ }
+ }
+
+ if (PKIX_PL_Free((PKIX_PL_Object *)issuerAscii, NULL)) {
+ return (NULL);
+ }
+
+ if (PKIX_PL_Free((PKIX_PL_Object *)subjectAscii, NULL)) {
+ return (NULL);
+ }
+
+ if (errorResult) {
+ return (NULL);
+ }
+
+ return (asciiString);
+}
+
+/*
+ * FUNCTION: testHashcodeHelper
+ * DESCRIPTION:
+ *
+ * Computes the hashcode of the Object pointed to by "goodObject" and the
+ * Object pointed to by "otherObject" and compares them. If the result of the
+ * comparison is not the desired match as specified by "match", an error
+ * message is generated.
+ *
+ * PARAMETERS:
+ * "goodObject"
+ * Address of an object. Must be non-NULL.
+ * "otherObject"
+ * Address of another object. Must be non-NULL.
+ * "match"
+ * Boolean value representing the desired comparison result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+testHashcodeHelper(
+ PKIX_PL_Object *goodObject,
+ PKIX_PL_Object *otherObject,
+ PKIX_Boolean match,
+ void *plContext)
+{
+
+ PKIX_UInt32 goodHash;
+ PKIX_UInt32 otherHash;
+ PKIX_Boolean cmpResult;
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Hashcode((PKIX_PL_Object *)goodObject, &goodHash, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Hashcode((PKIX_PL_Object *)otherObject, &otherHash, plContext));
+
+ cmpResult = (goodHash == otherHash);
+
+ if ((match && !cmpResult) || (!match && cmpResult)) {
+ testError("unexpected mismatch");
+ (void)printf("Hash1:\t%d\n", goodHash);
+ (void)printf("Hash2:\t%d\n", otherHash);
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * FUNCTION: testToStringHelper
+ * DESCRIPTION:
+ *
+ * Calls toString on the Object pointed to by "goodObject" and compares the
+ * result to the string pointed to by "expected". If the results are not
+ * equal, an error message is generated.
+ *
+ * PARAMETERS:
+ * "goodObject"
+ * Address of Object. Must be non-NULL.
+ * "expected"
+ * Address of the desired string.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+testToStringHelper(
+ PKIX_PL_Object *goodObject,
+ char *expected,
+ void *plContext)
+{
+ PKIX_PL_String *stringRep = NULL;
+ char *actual = NULL;
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString(goodObject, &stringRep, plContext));
+
+ actual = PKIX_String2ASCII(stringRep, plContext);
+ if (actual == NULL) {
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ /*
+ * If you are having trouble matching the string, uncomment the
+ * PL_strstr function to figure out what's going on.
+ */
+
+ /*
+ if (PL_strstr(actual, expected) == NULL){
+ testError("PL_strstr failed");
+ }
+ */
+
+ if (PL_strcmp(actual, expected) != 0) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%s\n", actual);
+ (void)printf("Expected value:\t%s\n", expected);
+ }
+
+cleanup:
+
+ PKIX_PL_Free(actual, plContext);
+
+ PKIX_TEST_DECREF_AC(stringRep);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * FUNCTION: testEqualsHelper
+ * DESCRIPTION:
+ *
+ * Checks if the Object pointed to by "goodObject" is Equal to the Object
+ * pointed to by "otherObject". If the result of the check is not the desired
+ * match as specified by "match", an error message is generated.
+ *
+ * PARAMETERS:
+ * "goodObject"
+ * Address of an Object. Must be non-NULL.
+ * "otherObject"
+ * Address of another Object. Must be non-NULL.
+ * "match"
+ * Boolean value representing the desired comparison result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+testEqualsHelper(
+ PKIX_PL_Object *goodObject,
+ PKIX_PL_Object *otherObject,
+ PKIX_Boolean match,
+ void *plContext)
+{
+
+ PKIX_Boolean cmpResult;
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(goodObject, otherObject, &cmpResult, plContext));
+
+ if ((match && !cmpResult) || (!match && cmpResult)) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", cmpResult);
+ (void)printf("Expected value:\t%d\n", match);
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * FUNCTION: testDuplicateHelper
+ * DESCRIPTION:
+ * Checks if the Object pointed to by "object" is equal to its duplicate.
+ * If the result of the check is not equality, an error message is generated.
+ * PARAMETERS:
+ * "object"
+ * Address of Object. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+testDuplicateHelper(PKIX_PL_Object *object, void *plContext)
+{
+ PKIX_PL_Object *newObject = NULL;
+ PKIX_Boolean cmpResult;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate(object, &newObject, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(object, newObject, &cmpResult, plContext));
+
+ if (!cmpResult) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", cmpResult);
+ (void)printf("Expected value:\t%d\n", PKIX_TRUE);
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(newObject);
+
+ PKIX_TEST_RETURN();
+}
diff --git a/security/nss/cmd/libpkix/testutil/testutil.h b/security/nss/cmd/libpkix/testutil/testutil.h
new file mode 100644
index 000000000..9c594fa03
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/testutil.h
@@ -0,0 +1,292 @@
+/* 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/. */
+/*
+ * testutil.h
+ *
+ * Utility functions for handling test errors
+ *
+ */
+
+#ifndef _TESTUTIL_H
+#define _TESTUTIL_H
+
+#include "pkix.h"
+#include "plstr.h"
+#include "prprf.h"
+#include "prlong.h"
+#include "pkix_pl_common.h"
+#include "secutil.h"
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * In order to have a consistent format for displaying test information,
+ * all tests are REQUIRED to use the functions provided by this library
+ * (libtestutil.a) for displaying their information.
+ *
+ * A test using this library begins with a call to startTests with the test
+ * name as the arg (which is used only for formatting). Before the first
+ * subtest, a call to subTest should be made with the subtest name as the arg
+ * (again, for formatting). If the subTest is successful, then no action
+ * is needed. However, if the subTest is not successful, then a call
+ * to testError should be made with a descriptive error message as the arg.
+ * Note that a subTest MUST NOT call testError more than once.
+ * Finally, a call to endTests is made with the test name as the arg (for
+ * formatting). Note that most of these macros assume that a variable named
+ * "plContext" of type (void *) has been defined by the test. As such, it
+ * is essential that the test satisfy this condition.
+ */
+
+/*
+ * PKIX_TEST_STD_VARS should be called at the beginning of every function
+ * that uses PKIX_TEST_RETURN (e.g. subTests), but it should be called only
+ * AFTER declaring local variables (so we don't get compiler warnings about
+ * declarations after statements). PKIX_TEST_STD_VARS declares and initializes
+ * several variables needed by the other test macros.
+ */
+#define PKIX_TEST_STD_VARS() \
+ PKIX_Error *pkixTestErrorResult = NULL; \
+ char *pkixTestErrorMsg = NULL;
+
+/*
+ * PKIX_TEST_EXPECT_NO_ERROR should be used to wrap a standard PKIX function
+ * call (one which returns a pointer to PKIX_Error) that is expected to return
+ * NULL (i.e. to succeed). If "pkixTestErrorResult" is not NULL,
+ * "goto cleanup" is executed, where a testError call is made if there were
+ * unexpected results. This macro MUST NOT be called after the "cleanup" label.
+ *
+ * Example Usage: PKIX_TEST_EXPECT_NO_ERROR(pkixFunc_expected_to_succeed(...));
+ */
+
+#define PKIX_TEST_EXPECT_NO_ERROR(func) \
+ do { \
+ pkixTestErrorResult = (func); \
+ if (pkixTestErrorResult) { \
+ goto cleanup; \
+ } \
+ } while (0)
+
+/*
+ * PKIX_TEST_EXPECT_ERROR should be used to wrap a standard PKIX function call
+ * (one which returns a pointer to PKIX_Error) that is expected to return
+ * a non-NULL value (i.e. to fail). If "pkixTestErrorResult" is NULL,
+ * "pkixTestErrorMsg" is set to a standard string and "goto cleanup"
+ * is executed, where a testError call is made if there were unexpected
+ * results. This macro MUST NOT be called after the "cleanup" label.
+ *
+ * Example Usage: PKIX_TEST_EXPECT_ERROR(pkixFunc_expected_to_fail(...));
+ */
+
+#define PKIX_TEST_EXPECT_ERROR(func) \
+ do { \
+ pkixTestErrorResult = (func); \
+ if (!pkixTestErrorResult) { \
+ pkixTestErrorMsg = \
+ "Should have thrown an error here."; \
+ goto cleanup; \
+ } \
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult); \
+ } while (0)
+
+/*
+ * PKIX_TEST_DECREF_BC is a convenience macro which should only be called
+ * BEFORE the "cleanup" label ("BC"). If the input parameter is non-NULL, it
+ * DecRefs the input parameter and wraps the function with
+ * PKIX_TEST_EXPECT_NO_ERROR, which executes "goto cleanup" upon error.
+ * This macro MUST NOT be called after the "cleanup" label.
+ */
+
+#define PKIX_TEST_DECREF_BC(obj) \
+ do { \
+ if (obj) { \
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_DecRef((PKIX_PL_Object *)(obj), plContext)); \
+ obj = NULL; \
+ } \
+ } while (0)
+
+/*
+ * PKIX_TEST_DECREF_AC is a convenience macro which should only be called
+ * AFTER the "cleanup" label ("AC"). If the input parameter is non-NULL, it
+ * DecRefs the input parameter. A pkixTestTempResult variable is used to prevent
+ * incorrectly overwriting pkixTestErrorResult with NULL.
+ * In the case DecRef succeeds, pkixTestTempResult will be NULL, and we won't
+ * overwrite a previously set pkixTestErrorResult (if any). If DecRef fails,
+ * then we do want to overwrite a previously set pkixTestErrorResult since a
+ * DecRef failure is fatal and may be indicative of memory corruption.
+ */
+
+#define PKIX_TEST_DECREF_AC(obj) \
+ do { \
+ if (obj) { \
+ PKIX_Error *pkixTestTempResult = NULL; \
+ pkixTestTempResult = \
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(obj), plContext); \
+ if (pkixTestTempResult) \
+ pkixTestErrorResult = pkixTestTempResult; \
+ obj = NULL; \
+ } \
+ } while (0)
+
+/*
+ * PKIX_TEST_RETURN must always be AFTER the "cleanup" label. It does nothing
+ * if everything went as expected. However, if there were unexpected results,
+ * PKIX_TEST_RETURN calls testError, which displays a standard failure message
+ * and increments the number of subtests that have failed. In the case
+ * of an unexpected error, testError is called using the error's description
+ * as an input and the error is DecRef'd. In the case of unexpected success
+ * testError is called with a standard string.
+ */
+#define PKIX_TEST_RETURN() \
+ { \
+ if (pkixTestErrorMsg) { \
+ testError(pkixTestErrorMsg); \
+ } else if (pkixTestErrorResult) { \
+ pkixTestErrorMsg = \
+ PKIX_Error2ASCII(pkixTestErrorResult, plContext); \
+ if (pkixTestErrorMsg) { \
+ testError(pkixTestErrorMsg); \
+ PKIX_PL_Free((PKIX_PL_Object *)pkixTestErrorMsg, \
+ plContext); \
+ } else { \
+ testError("PKIX_Error2ASCII Failed"); \
+ } \
+ if (pkixTestErrorResult != PKIX_ALLOC_ERROR()) { \
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)pkixTestErrorResult, \
+ plContext); \
+ pkixTestErrorResult = NULL; \
+ } \
+ } \
+ }
+
+/*
+ * PKIX_TEST_EQ_HASH_TOSTR_DUP is a convenience macro which executes the
+ * standard set of operations that test the Equals, Hashcode, ToString, and
+ * Duplicate functions of an object type. The goodObj, equalObj, and diffObj
+ * are as the names suggest. The expAscii parameter is the expected result of
+ * calling ToString on the goodObj. If expAscii is NULL, then ToString will
+ * not be called on the goodObj. The checkDuplicate parameter is treated as
+ * a Boolean to indicate whether the Duplicate function should be tested. If
+ * checkDuplicate is NULL, then Duplicate will not be called on the goodObj.
+ * The type is the name of the function's family. For example, if the type is
+ * Cert, this macro will call PKIX_PL_Cert_Equals, PKIX_PL_Cert_Hashcode, and
+ * PKIX_PL_Cert_ToString.
+ *
+ * Note: If goodObj uses the default Equals and Hashcode functions, then
+ * for goodObj and equalObj to be equal, they must have the same pointer value.
+ */
+#define PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObj, equalObj, diffObj, \
+ expAscii, type, checkDuplicate) \
+ do { \
+ subTest("PKIX_PL_" #type "_Equals <match>"); \
+ testEqualsHelper((PKIX_PL_Object *)(goodObj), \
+ (PKIX_PL_Object *)(equalObj), \
+ PKIX_TRUE, \
+ plContext); \
+ subTest("PKIX_PL_" #type "_Hashcode <match>"); \
+ testHashcodeHelper((PKIX_PL_Object *)(goodObj), \
+ (PKIX_PL_Object *)(equalObj), \
+ PKIX_TRUE, \
+ plContext); \
+ subTest("PKIX_PL_" #type "_Equals <non-match>"); \
+ testEqualsHelper((PKIX_PL_Object *)(goodObj), \
+ (PKIX_PL_Object *)(diffObj), \
+ PKIX_FALSE, \
+ plContext); \
+ subTest("PKIX_PL_" #type "_Hashcode <non-match>"); \
+ testHashcodeHelper((PKIX_PL_Object *)(goodObj), \
+ (PKIX_PL_Object *)(diffObj), \
+ PKIX_FALSE, \
+ plContext); \
+ if (expAscii) { \
+ subTest("PKIX_PL_" #type "_ToString"); \
+ testToStringHelper((PKIX_PL_Object *)(goodObj), \
+ (expAscii), \
+ plContext); \
+ } \
+ if (checkDuplicate) { \
+ subTest("PKIX_PL_" #type "_Duplicate"); \
+ testDuplicateHelper((PKIX_PL_Object *)goodObj, plContext); \
+ } \
+ } while (0)
+
+/*
+ * PKIX_TEST_DECREF_BC is a convenience macro which should only be called
+ * BEFORE the "cleanup" label ("BC"). If the input parameter is non-NULL, it
+ * DecRefs the input parameter and wraps the function with
+ * PKIX_TEST_EXPECT_NO_ERROR, which executes "goto cleanup" upon error.
+ * This macro MUST NOT be called after the "cleanup" label.
+ */
+
+#define PKIX_TEST_ABORT_ON_NULL(obj) \
+ do { \
+ if (!obj) { \
+ goto cleanup; \
+ } \
+ } while (0)
+
+#define PKIX_TEST_ARENAS_ARG(arena) \
+ (arena ? (PORT_Strcmp(arena, "arenas") ? PKIX_FALSE : (j++, PKIX_TRUE)) : PKIX_FALSE)
+
+#define PKIX_TEST_ERROR_RECEIVED (pkixTestErrorMsg || pkixTestErrorResult)
+
+/* see source file for function documentation */
+
+void startTests(char *testName);
+
+void endTests(char *testName);
+
+void subTest(char *subTestName);
+
+void testError(char *msg);
+
+extern PKIX_Error *
+_ErrorCheck(PKIX_Error *errorResult);
+
+extern PKIX_Error *
+_OutputError(PKIX_Error *errorResult);
+
+char *PKIX_String2ASCII(PKIX_PL_String *string, void *plContext);
+
+char *PKIX_Error2ASCII(PKIX_Error *error, void *plContext);
+
+char *PKIX_Object2ASCII(PKIX_PL_Object *object);
+
+char *PKIX_Cert2ASCII(PKIX_PL_Cert *cert);
+
+void
+testHashcodeHelper(
+ PKIX_PL_Object *goodObject,
+ PKIX_PL_Object *otherObject,
+ PKIX_Boolean match,
+ void *plContext);
+
+void
+testToStringHelper(
+ PKIX_PL_Object *goodObject,
+ char *expected,
+ void *plContext);
+
+void
+testEqualsHelper(
+ PKIX_PL_Object *goodObject,
+ PKIX_PL_Object *otherObject,
+ PKIX_Boolean match,
+ void *plContext);
+
+void
+testDuplicateHelper(
+ PKIX_PL_Object *object,
+ void *plContext);
+void
+testErrorUndo(char *msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TESTUTIL_H */
diff --git a/security/nss/cmd/libpkix/testutil/testutil_nss.c b/security/nss/cmd/libpkix/testutil/testutil_nss.c
new file mode 100644
index 000000000..3417d0ab7
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/testutil_nss.c
@@ -0,0 +1,579 @@
+/* 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/. */
+/*
+ * testutil_nss.c
+ *
+ * NSS-specific utility functions for handling test errors
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+
+#include "pkix_pl_generalname.h"
+#include "pkix_pl_cert.h"
+#include "pkix.h"
+#include "testutil.h"
+#include "prlong.h"
+#include "plstr.h"
+#include "prthread.h"
+#include "secutil.h"
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "secitem.h"
+#include "keythi.h"
+#include "nss.h"
+
+static char *
+catDirName(char *dir, char *name, void *plContext)
+{
+ char *pathName = NULL;
+ PKIX_UInt32 nameLen;
+ PKIX_UInt32 dirLen;
+
+ PKIX_TEST_STD_VARS();
+
+ nameLen = PL_strlen(name);
+ dirLen = PL_strlen(dir);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc(dirLen + nameLen + 2,
+ (void **)&pathName,
+ plContext));
+
+ PL_strcpy(pathName, dir);
+ PL_strcat(pathName, "/");
+ PL_strcat(pathName, name);
+ printf("pathName = %s\n", pathName);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (pathName);
+}
+
+PKIX_PL_Cert *
+createCert(
+ char *dirName,
+ char *certFileName,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ void *buf = NULL;
+ PRFileDesc *certFile = NULL;
+ PKIX_UInt32 len;
+ SECItem certDER;
+ SECStatus rv;
+ /* default: NULL cert (failure case) */
+ PKIX_PL_Cert *cert = NULL;
+ char *pathName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certDER.data = NULL;
+
+ pathName = catDirName(dirName, certFileName, plContext);
+ certFile = PR_Open(pathName, PR_RDONLY, 0);
+
+ if (!certFile) {
+ pkixTestErrorMsg = "Unable to open cert file";
+ goto cleanup;
+ } else {
+ rv = SECU_ReadDERFromFile(&certDER, certFile, PR_FALSE, PR_FALSE);
+ if (!rv) {
+ buf = (void *)certDER.data;
+ len = certDER.len;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_Create(byteArray, &cert, plContext));
+
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ } else {
+ pkixTestErrorMsg = "Unable to read DER from cert file";
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ pkixTestErrorResult = PKIX_PL_Free(pathName, plContext);
+
+ if (certFile) {
+ PR_Close(certFile);
+ }
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ }
+
+ PKIX_TEST_DECREF_AC(byteArray);
+
+ PKIX_TEST_RETURN();
+
+ return (cert);
+}
+
+PKIX_PL_CRL *
+createCRL(
+ char *dirName,
+ char *crlFileName,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_Error *error = NULL;
+ PRFileDesc *inFile = NULL;
+ SECItem crlDER;
+ void *buf = NULL;
+ PKIX_UInt32 len;
+ SECStatus rv;
+ char *pathName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ crlDER.data = NULL;
+
+ pathName = catDirName(dirName, crlFileName, plContext);
+ inFile = PR_Open(pathName, PR_RDONLY, 0);
+
+ if (!inFile) {
+ pkixTestErrorMsg = "Unable to open crl file";
+ goto cleanup;
+ } else {
+ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
+ if (!rv) {
+ buf = (void *)crlDER.data;
+ len = crlDER.len;
+
+ error = PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext);
+
+ if (error) {
+ pkixTestErrorMsg =
+ "PKIX_PL_ByteArray_Create failed";
+ goto cleanup;
+ }
+
+ error = PKIX_PL_CRL_Create(byteArray, &crl, plContext);
+ if (error) {
+ pkixTestErrorMsg = "PKIX_PL_Crl_Create failed";
+ goto cleanup;
+ }
+
+ SECITEM_FreeItem(&crlDER, PR_FALSE);
+ } else {
+ pkixTestErrorMsg = "Unable to read DER from crl file";
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(pathName, plContext));
+
+ if (inFile) {
+ PR_Close(inFile);
+ }
+
+ if (error) {
+ SECITEM_FreeItem(&crlDER, PR_FALSE);
+ }
+
+ PKIX_TEST_DECREF_AC(byteArray);
+
+ PKIX_TEST_RETURN();
+
+ return (crl);
+}
+
+PKIX_TrustAnchor *
+createTrustAnchor(
+ char *dirName,
+ char *certFileName,
+ PKIX_Boolean useCert,
+ void *plContext)
+{
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_X500Name *name = NULL;
+ PKIX_PL_PublicKey *pubKey = NULL;
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ cert = createCert(dirName, certFileName, plContext);
+
+ if (useCert) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert(cert, &anchor, plContext));
+ } else {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(cert, &name, plContext));
+
+ if (name == NULL) {
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(cert, &pubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(cert, &nameConstraints, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithNameKeyPair(name, pubKey, nameConstraints, &anchor, plContext));
+ }
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ PKIX_TEST_DECREF_AC(anchor);
+ }
+
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(name);
+ PKIX_TEST_DECREF_AC(pubKey);
+ PKIX_TEST_DECREF_AC(nameConstraints);
+
+ PKIX_TEST_RETURN();
+
+ return (anchor);
+}
+
+PKIX_List *
+createCertChain(
+ char *dirName,
+ char *firstCertFileName,
+ char *secondCertFileName,
+ void *plContext)
+{
+ PKIX_PL_Cert *firstCert = NULL;
+ PKIX_PL_Cert *secondCert = NULL;
+ PKIX_List *certList = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certList, plContext));
+
+ firstCert = createCert(dirName, firstCertFileName, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certList, (PKIX_PL_Object *)firstCert, plContext));
+
+ if (secondCertFileName) {
+ secondCert = createCert(dirName, secondCertFileName, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certList, (PKIX_PL_Object *)secondCert, plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetImmutable(certList, plContext));
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ PKIX_TEST_DECREF_AC(certList);
+ }
+
+ PKIX_TEST_DECREF_AC(firstCert);
+ PKIX_TEST_DECREF_AC(secondCert);
+
+ PKIX_TEST_RETURN();
+
+ return (certList);
+}
+
+PKIX_List *
+createCertChainPlus(
+ char *dirName,
+ char *certNames[],
+ PKIX_PL_Cert *certs[],
+ PKIX_UInt32 numCerts,
+ void *plContext)
+{
+ PKIX_List *certList = NULL;
+ PKIX_UInt32 i;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certList, plContext));
+
+ for (i = 0; i < numCerts; i++) {
+
+ certs[i] = createCert(dirName, certNames[i], plContext);
+
+ /* Create Cert may fail */
+ if (certs[i] == NULL) {
+ PKIX_TEST_DECREF_BC(certList);
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certList,
+ (PKIX_PL_Object *)certs[i],
+ plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetImmutable(certList, plContext));
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ PKIX_TEST_DECREF_AC(certList);
+ }
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_DECREF_AC(certs[i]);
+ }
+
+ PKIX_TEST_RETURN();
+
+ return (certList);
+}
+
+PKIX_PL_Date *
+createDate(
+ char *asciiDate,
+ void *plContext)
+{
+ PKIX_PL_Date *date = NULL;
+ PKIX_PL_String *plString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, asciiDate, 0, &plString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Date_Create_UTCTime(plString, &date, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(plString);
+
+ PKIX_TEST_RETURN();
+
+ return (date);
+}
+
+PKIX_ProcessingParams *
+createProcessingParams(
+ char *dirName,
+ char *firstAnchorFileName,
+ char *secondAnchorFileName,
+ char *dateAscii,
+ PKIX_List *initialPolicies, /* List of PKIX_PL_OID */
+ PKIX_Boolean isCrlEnabled,
+ void *plContext)
+{
+
+ PKIX_TrustAnchor *firstAnchor = NULL;
+ PKIX_TrustAnchor *secondAnchor = NULL;
+ PKIX_List *anchorsList = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_PL_String *dateString = NULL;
+ PKIX_PL_Date *testDate = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchorsList, plContext));
+
+ firstAnchor = createTrustAnchor(dirName, firstAnchorFileName, PKIX_FALSE, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchorsList,
+ (PKIX_PL_Object *)firstAnchor,
+ plContext));
+
+ if (secondAnchorFileName) {
+ secondAnchor =
+ createTrustAnchor(dirName, secondAnchorFileName, PKIX_FALSE, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchorsList,
+ (PKIX_PL_Object *)secondAnchor,
+ plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create(anchorsList, &procParams, plContext));
+
+ if (dateAscii) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ dateAscii,
+ 0,
+ &dateString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Date_Create_UTCTime(dateString, &testDate, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetDate(procParams, testDate, plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetInitialPolicies(procParams, initialPolicies, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, isCrlEnabled, plContext));
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ PKIX_TEST_DECREF_AC(procParams);
+ }
+
+ PKIX_TEST_DECREF_AC(dateString);
+ PKIX_TEST_DECREF_AC(testDate);
+ PKIX_TEST_DECREF_AC(anchorsList);
+ PKIX_TEST_DECREF_AC(firstAnchor);
+ PKIX_TEST_DECREF_AC(secondAnchor);
+
+ PKIX_TEST_RETURN();
+
+ return (procParams);
+}
+
+PKIX_ValidateParams *
+createValidateParams(
+ char *dirName,
+ char *firstAnchorFileName,
+ char *secondAnchorFileName,
+ char *dateAscii,
+ PKIX_List *initialPolicies, /* List of PKIX_PL_OID */
+ PKIX_Boolean initialPolicyMappingInhibit,
+ PKIX_Boolean initialAnyPolicyInhibit,
+ PKIX_Boolean initialExplicitPolicy,
+ PKIX_Boolean isCrlEnabled,
+ PKIX_List *chain,
+ void *plContext)
+{
+
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ procParams =
+ createProcessingParams(dirName,
+ firstAnchorFileName,
+ secondAnchorFileName,
+ dateAscii,
+ NULL,
+ isCrlEnabled,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetInitialPolicies(procParams, initialPolicies, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetPolicyMappingInhibited(procParams, initialPolicyMappingInhibit, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetAnyPolicyInhibited(procParams, initialAnyPolicyInhibit, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetExplicitPolicyRequired(procParams, initialExplicitPolicy, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_Create(procParams, chain, &valParams, plContext));
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ PKIX_TEST_DECREF_AC(valParams);
+ }
+
+ PKIX_TEST_DECREF_AC(procParams);
+
+ PKIX_TEST_RETURN();
+
+ return (valParams);
+}
+
+PKIX_ValidateResult *
+createValidateResult(
+ char *dirName,
+ char *anchorFileName,
+ char *pubKeyCertFileName,
+ void *plContext)
+{
+
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_PublicKey *pubKey = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ anchor = createTrustAnchor(dirName, anchorFileName, PKIX_FALSE, plContext);
+ cert = createCert(dirName, pubKeyCertFileName, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(cert, &pubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_ValidateResult_Create(pubKey, anchor, NULL, &valResult, plContext));
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ PKIX_TEST_DECREF_AC(valResult);
+ }
+
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(pubKey);
+
+ PKIX_TEST_RETURN();
+
+ return (valResult);
+}
+
+PKIX_PL_GeneralName *
+createGeneralName(
+ PKIX_UInt32 nameType,
+ char *asciiName,
+ void *plContext)
+{
+
+ PKIX_PL_GeneralName *generalName = NULL;
+ PKIX_PL_String *plString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, asciiName, 0, &plString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_GeneralName_Create(nameType, plString, &generalName, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(plString);
+
+ PKIX_TEST_RETURN();
+
+ return (generalName);
+}
+
+PKIX_BuildResult *
+createBuildResult(
+ char *dirName,
+ char *anchorFileName,
+ char *pubKeyCertFileName,
+ char *firstChainCertFileName,
+ char *secondChainCertFileName,
+ void *plContext)
+{
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_List *certChain = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ valResult = createValidateResult(dirName, anchorFileName, pubKeyCertFileName, plContext);
+ certChain = createCertChain(dirName,
+ firstChainCertFileName,
+ secondChainCertFileName,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_BuildResult_Create(valResult, certChain, &buildResult, plContext));
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ PKIX_TEST_DECREF_AC(buildResult);
+ }
+
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(certChain);
+
+ PKIX_TEST_RETURN();
+
+ return (buildResult);
+}
diff --git a/security/nss/cmd/libpkix/testutil/testutil_nss.h b/security/nss/cmd/libpkix/testutil/testutil_nss.h
new file mode 100644
index 000000000..e1f24af89
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/testutil_nss.h
@@ -0,0 +1,119 @@
+/* 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/. */
+/*
+ * testutil_nss.h
+ *
+ * NSS-specific utility functions for handling test errors
+ *
+ */
+
+#ifndef _TESTUTIL_NSS_H
+#define _TESTUTIL_NSS_H
+
+#include "pkix_tools.h"
+#include "plstr.h"
+#include "prprf.h"
+#include "prlong.h"
+#include "secutil.h"
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "pkix_pl_generalname.h"
+
+/* see source file for function documentation */
+
+PKIX_PL_Cert *
+createCert(
+ char *dirName,
+ char *certFile,
+ void *plContext);
+
+PKIX_PL_CRL *
+createCRL(
+ char *dirName,
+ char *crlFileName,
+ void *plContext);
+
+PKIX_TrustAnchor *
+createTrustAnchor(
+ char *dirName,
+ char *taFileName,
+ PKIX_Boolean useCert,
+ void *plContext);
+
+PKIX_List *
+createCertChain(
+ char *dirName,
+ char *firstCertFileName,
+ char *secondCertFileName,
+ void *plContext);
+
+PKIX_List *
+createCertChainPlus(
+ char *dirName,
+ char *certNames[],
+ PKIX_PL_Cert *certs[],
+ PKIX_UInt32 numCerts,
+ void *plContext);
+
+PKIX_PL_Date *
+createDate(
+ char *asciiDate,
+ void *plContext);
+
+PKIX_ProcessingParams *
+createProcessingParams(
+ char *dirName,
+ char *firstAnchorFileName,
+ char *secondAnchorFileName,
+ char *dateAscii,
+ PKIX_List *initialPolicies, /* List of PKIX_PL_OID */
+ PKIX_Boolean isCrlEnabled,
+ void *plContext);
+
+PKIX_ValidateParams *
+createValidateParams(
+ char *dirName,
+ char *firstAnchorFileName,
+ char *secondAnchorFileName,
+ char *dateAscii,
+ PKIX_List *initialPolicies, /* List of PKIX_PL_OID */
+ PKIX_Boolean initialPolicyMappingInhibit,
+ PKIX_Boolean initialAnyPolicyInhibit,
+ PKIX_Boolean initialExplicitPolicy,
+ PKIX_Boolean isCrlEnabled,
+ PKIX_List *chain,
+ void *plContext);
+
+PKIX_ValidateResult *
+createValidateResult(
+ char *dirName,
+ char *anchorFileName,
+ char *pubKeyCertFileName,
+ void *plContext);
+
+PKIX_BuildResult *
+createBuildResult(
+ char *dirName,
+ char *anchorFileName,
+ char *pubKeyCertFileName,
+ char *firstChainCertFileName,
+ char *secondChainCertFileName,
+ void *plContext);
+
+PKIX_PL_GeneralName *
+createGeneralName(
+ PKIX_UInt32 nameType,
+ char *asciiName,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TESTUTIL_NSS_H */
diff --git a/security/nss/cmd/listsuites/Makefile b/security/nss/cmd/listsuites/Makefile
new file mode 100644
index 000000000..6e1d4ecdf
--- /dev/null
+++ b/security/nss/cmd/listsuites/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/listsuites/listsuites.c b/security/nss/cmd/listsuites/listsuites.c
new file mode 100644
index 000000000..458130e5e
--- /dev/null
+++ b/security/nss/cmd/listsuites/listsuites.c
@@ -0,0 +1,62 @@
+/* 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/. */
+
+/* This program demonstrates the use of SSL_GetCipherSuiteInfo to avoid
+ * all compiled-in knowledge of SSL cipher suites.
+ *
+ * Try: ./listsuites | grep -v : | sort -b +4rn -5 +1 -2 +2 -3 +3 -4 +5r -6
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include "secport.h"
+#include "ssl.h"
+
+int
+main(int argc, char **argv)
+{
+ const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
+ int i;
+ int errCount = 0;
+
+ fputs("This version of libSSL supports these cipher suites:\n\n", stdout);
+
+ /* disable all the SSL3 cipher suites */
+ for (i = 0; i < SSL_NumImplementedCiphers; i++) {
+ PRUint16 suite = cipherSuites[i];
+ SECStatus rv;
+ PRBool enabled;
+ PRErrorCode err;
+ SSLCipherSuiteInfo info;
+
+ rv = SSL_CipherPrefGetDefault(suite, &enabled);
+ if (rv != SECSuccess) {
+ err = PR_GetError();
+ ++errCount;
+ fprintf(stderr,
+ "SSL_CipherPrefGetDefault didn't like value 0x%04x (i = %d): %s\n",
+ suite, i, PORT_ErrorToString(err));
+ continue;
+ }
+ rv = SSL_GetCipherSuiteInfo(suite, &info, (int)(sizeof info));
+ if (rv != SECSuccess) {
+ err = PR_GetError();
+ ++errCount;
+ fprintf(stderr,
+ "SSL_GetCipherSuiteInfo didn't like value 0x%04x (i = %d): %s\n",
+ suite, i, PORT_ErrorToString(err));
+ continue;
+ }
+ fprintf(stdout,
+ "%s:\n" /* up to 37 spaces */
+ " 0x%04hx %-5s %-5s %-8s %3hd %-6s %-8s %-4s Domestic %-11s\n",
+ info.cipherSuiteName, info.cipherSuite,
+ info.keaTypeName, info.authAlgorithmName, info.symCipherName,
+ info.effectiveKeyBits, info.macAlgorithmName,
+ enabled ? "Enabled" : "Disabled",
+ info.isFIPS ? "FIPS" : "",
+ info.nonStandard ? "nonStandard" : "");
+ }
+ return errCount;
+}
diff --git a/security/nss/cmd/listsuites/listsuites.gyp b/security/nss/cmd/listsuites/listsuites.gyp
new file mode 100644
index 000000000..51f8d8f6e
--- /dev/null
+++ b/security/nss/cmd/listsuites/listsuites.gyp
@@ -0,0 +1,24 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'listsuites',
+ 'type': 'executable',
+ 'sources': [
+ 'listsuites.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/listsuites/manifest.mn b/security/nss/cmd/listsuites/manifest.mn
new file mode 100644
index 000000000..3e78dacee
--- /dev/null
+++ b/security/nss/cmd/listsuites/manifest.mn
@@ -0,0 +1,15 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+CSRCS = listsuites.c
+
+REQUIRES = seccmd
+
+PROGRAM = listsuites
+
diff --git a/security/nss/cmd/lowhashtest/Makefile b/security/nss/cmd/lowhashtest/Makefile
new file mode 100644
index 000000000..cfac7700a
--- /dev/null
+++ b/security/nss/cmd/lowhashtest/Makefile
@@ -0,0 +1,65 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+#MKPROG = purify -cache-dir=/u/mcgreer/pcache -best-effort \
+# -always-use-cache-dir $(CC)
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
+EXTRA_LIBS += \
+ $(DIST)/lib/$(LIB_PREFIX)sectool.$(LIB_SUFFIX) \
+ $(NULL)
+
+
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib \
+ -L$(NSSUTIL_LIB_DIR) \
+ -lnssutil3 \
+ -lfreebl3 \
+ -L$(NSPR_LIB_DIR) \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4 \
+ $(NULL)
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/security/nss/cmd/lowhashtest/lowhashtest.c b/security/nss/cmd/lowhashtest/lowhashtest.c
new file mode 100644
index 000000000..29d6ff4fd
--- /dev/null
+++ b/security/nss/cmd/lowhashtest/lowhashtest.c
@@ -0,0 +1,445 @@
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "nspr.h"
+
+/* nss headers */
+#include "prtypes.h"
+#include "plgetopt.h"
+#include "hasht.h"
+#include "nsslowhash.h"
+#include "secport.h"
+#include "hasht.h"
+#include "basicutil.h"
+
+static char *progName = NULL;
+
+static int
+test_long_message(NSSLOWInitContext *initCtx,
+ HASH_HashType algoType, unsigned int hashLen,
+ const PRUint8 expected[], PRUint8 results[])
+{
+ unsigned int len, i, rv = 0;
+ NSSLOWHASHContext *ctx;
+
+ /* The message is meant to be 'a' repeated 1,000,000 times.
+ * This is too much to allocate on the stack so we will use a 1,000 char
+ * buffer and call update 1,000 times.
+ */
+ unsigned char buf[1000];
+ (void)PORT_Memset(buf, 'a', sizeof(buf));
+
+ ctx = NSSLOWHASH_NewContext(initCtx, algoType);
+ if (ctx == NULL) {
+ SECU_PrintError(progName, "Couldn't get hash context\n");
+ return 1;
+ }
+
+ NSSLOWHASH_Begin(ctx);
+ for (i = 0; i < 1000; ++i) {
+ NSSLOWHASH_Update(ctx, buf, 1000);
+ }
+
+ NSSLOWHASH_End(ctx, results, &len, hashLen);
+ PR_ASSERT(len == hashLen);
+ PR_ASSERT(PORT_Memcmp(expected, results, hashLen) == 0);
+ if (PORT_Memcmp(expected, results, len) != 0) {
+ SECU_PrintError(progName, "Hash mismatch\n");
+ SECU_PrintBuf(stdout, "Expected: ", expected, hashLen);
+ SECU_PrintBuf(stdout, "Actual: ", results, len);
+ rv = 1;
+ }
+
+ NSSLOWHASH_Destroy(ctx);
+ NSSLOW_Shutdown(initCtx);
+
+ return rv;
+}
+
+static int
+test_long_message_sha1(NSSLOWInitContext *initCtx)
+{
+ PRUint8 results[SHA1_LENGTH];
+ /* Test vector from FIPS 180-2: appendix B.3. */
+
+ /* 34aa973c d4c4daa4 f61eeb2b dbad2731 6534016f. */
+ static const PRUint8 expected[SHA256_LENGTH] =
+ { 0x34, 0xaa, 0x97, 0x3c, 0xd4, 0xc4, 0xda, 0xa4, 0xf6, 0x1e, 0xeb, 0x2b,
+ 0xdb, 0xad, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6f };
+ unsigned char buf[1000];
+ (void)PORT_Memset(buf, 'a', sizeof(buf));
+ return test_long_message(initCtx, HASH_AlgSHA1,
+ SHA1_LENGTH, &expected[0], results);
+}
+
+static int
+test_long_message_sha256(NSSLOWInitContext *initCtx)
+{
+ PRUint8 results[SHA256_LENGTH];
+ /* cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0. */
+ static const PRUint8 expected[SHA256_LENGTH] =
+ { 0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, 0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67,
+ 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e, 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0 };
+ unsigned char buf[1000];
+ (void)PORT_Memset(buf, 'a', sizeof(buf));
+ return test_long_message(initCtx, HASH_AlgSHA256,
+ SHA256_LENGTH, &expected[0], results);
+}
+
+static int
+test_long_message_sha384(NSSLOWInitContext *initCtx)
+{
+ PRUint8 results[SHA384_LENGTH];
+ /* Test vector from FIPS 180-2: appendix B.3. */
+ /*
+ 9d0e1809716474cb
+ 086e834e310a4a1c
+ ed149e9c00f24852
+ 7972cec5704c2a5b
+ 07b8b3dc38ecc4eb
+ ae97ddd87f3d8985.
+ */
+ static const PRUint8 expected[SHA384_LENGTH] =
+ { 0x9d, 0x0e, 0x18, 0x09, 0x71, 0x64, 0x74, 0xcb,
+ 0x08, 0x6e, 0x83, 0x4e, 0x31, 0x0a, 0x4a, 0x1c,
+ 0xed, 0x14, 0x9e, 0x9c, 0x00, 0xf2, 0x48, 0x52,
+ 0x79, 0x72, 0xce, 0xc5, 0x70, 0x4c, 0x2a, 0x5b,
+ 0x07, 0xb8, 0xb3, 0xdc, 0x38, 0xec, 0xc4, 0xeb,
+ 0xae, 0x97, 0xdd, 0xd8, 0x7f, 0x3d, 0x89, 0x85 };
+ unsigned char buf[1000];
+ (void)PORT_Memset(buf, 'a', sizeof(buf));
+
+ return test_long_message(initCtx, HASH_AlgSHA384,
+ SHA384_LENGTH, &expected[0], results);
+}
+
+static int
+test_long_message_sha512(NSSLOWInitContext *initCtx)
+{
+ PRUint8 results[SHA512_LENGTH];
+ /* Test vector from FIPS 180-2: appendix B.3. */
+ static const PRUint8 expected[SHA512_LENGTH] =
+ { 0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64, 0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63,
+ 0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28, 0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb,
+ 0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a, 0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b,
+ 0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e, 0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b };
+ unsigned char buf[1000];
+ (void)PORT_Memset(buf, 'a', sizeof(buf));
+
+ return test_long_message(initCtx, HASH_AlgSHA512,
+ SHA512_LENGTH, &expected[0], results);
+}
+
+static int
+testMessageDigest(NSSLOWInitContext *initCtx,
+ HASH_HashType algoType, unsigned int hashLen,
+ const unsigned char *message,
+ const PRUint8 expected[], PRUint8 results[])
+{
+ NSSLOWHASHContext *ctx;
+ unsigned int len;
+ int rv = 0;
+
+ ctx = NSSLOWHASH_NewContext(initCtx, algoType);
+ if (ctx == NULL) {
+ SECU_PrintError(progName, "Couldn't get hash context\n");
+ return 1;
+ }
+
+ NSSLOWHASH_Begin(ctx);
+ NSSLOWHASH_Update(ctx, message, PORT_Strlen((const char *)message));
+ NSSLOWHASH_End(ctx, results, &len, hashLen);
+ PR_ASSERT(len == hashLen);
+ PR_ASSERT(PORT_Memcmp(expected, results, len) == 0);
+
+ if (PORT_Memcmp(expected, results, len) != 0) {
+ SECU_PrintError(progName, "Hash mismatch\n");
+ SECU_PrintBuf(stdout, "Expected: ", expected, hashLen);
+ SECU_PrintBuf(stdout, "Actual: ", results, len);
+ rv = 1;
+ }
+
+ NSSLOWHASH_Destroy(ctx);
+ NSSLOW_Shutdown(initCtx);
+
+ return rv;
+}
+
+static int
+testMD5(NSSLOWInitContext *initCtx)
+{
+ /* test vectors that glibc, our API main client, uses */
+
+ static const struct {
+ const unsigned char *input;
+ const PRUint8 result[MD5_LENGTH];
+ } md5tests[] = {
+ { (unsigned char *)"",
+ { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },
+ { (unsigned char *)"a",
+ { 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } },
+ { (unsigned char *)"abc",
+ { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } },
+ { (unsigned char *)"message digest",
+ { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } },
+ { (unsigned char *)"abcdefghijklmnopqrstuvwxyz",
+ { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } },
+ { (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } },
+ { (unsigned char *)"123456789012345678901234567890123456789012345678901234567890"
+ "12345678901234567890",
+ { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }
+ };
+ PRUint8 results[MD5_LENGTH];
+ int rv = 0, cnt, numTests;
+
+ numTests = sizeof(md5tests) / sizeof(md5tests[0]);
+ for (cnt = 0; cnt < numTests; cnt++) {
+ rv += testMessageDigest(initCtx, HASH_AlgMD5, MD5_LENGTH,
+ (const unsigned char *)md5tests[cnt].input,
+ md5tests[cnt].result, &results[0]);
+ }
+ return rv;
+}
+
+/*
+ * Tests with test vectors from FIPS 180-2 Appendixes B.1, B.2, B.3, C, and D
+ *
+ */
+
+static int
+testSHA1(NSSLOWInitContext *initCtx)
+{
+ static const struct {
+ const unsigned char *input;
+ const PRUint8 result[SHA1_LENGTH];
+ } sha1tests[] = {
+ /* one block messsage */
+ {
+ (const unsigned char *)"abc",
+ /* a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d. */
+
+ { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, /* a9993e36 4706816a */
+ 0xba, 0x3e, 0x25, 0x71, /* ba3e2571 */
+ 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d } /* 7850c26c 9cd0d89d */
+ },
+ { (const unsigned char *)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ /* 84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1. */
+ { 0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, 0xba, 0xae, 0x4a, 0xa1,
+ 0xf9, 0x51, 0x29, 0xe5, 0xe5, 0x46, 0x70, 0xf1 } }
+ };
+
+ PRUint8 results[SHA1_LENGTH];
+ int rv = 0, cnt, numTests;
+
+ numTests = sizeof(sha1tests) / sizeof(sha1tests[0]);
+ for (cnt = 0; cnt < numTests; cnt++) {
+ rv += testMessageDigest(initCtx, HASH_AlgSHA1, SHA1_LENGTH,
+ (const unsigned char *)sha1tests[cnt].input,
+ sha1tests[cnt].result, &results[0]);
+ }
+
+ rv += test_long_message_sha1(initCtx);
+ return rv;
+}
+
+static int
+testSHA224(NSSLOWInitContext *initCtx)
+{
+ static const struct {
+ const unsigned char *input;
+ const PRUint8 result[SHA224_LENGTH];
+ } sha224tests[] = {
+ /* one block messsage */
+ { (const unsigned char *)"abc",
+ { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
+ 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, 0xE3, 0x6C, 0x9D, 0xA7 } },
+ /* two block message */
+ { (const unsigned char *)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
+ 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, 0x52, 0x52, 0x25, 0x25 } }
+ };
+
+ PRUint8 results[SHA224_LENGTH];
+ int rv = 0, cnt, numTests;
+
+ numTests = sizeof(sha224tests) / sizeof(sha224tests[0]);
+ for (cnt = 0; cnt < numTests; cnt++) {
+ rv += testMessageDigest(initCtx, HASH_AlgSHA224, SHA224_LENGTH,
+ (const unsigned char *)sha224tests[cnt].input,
+ sha224tests[cnt].result, &results[0]);
+ }
+
+ return rv;
+}
+
+static int
+testSHA256(NSSLOWInitContext *initCtx)
+{
+ static const struct {
+ const unsigned char *input;
+ const PRUint8 result[SHA256_LENGTH];
+ } sha256tests[] = {
+ /* Test vectors from FIPS 180-2: appendix B.1. */
+ { (unsigned char *)"abc",
+ { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
+ 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } },
+ /* Test vectors from FIPS 180-2: appendix B.2. */
+ { (unsigned char *)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
+ 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } }
+ };
+
+ PRUint8 results[SHA256_LENGTH];
+ int rv = 0, cnt, numTests;
+
+ numTests = sizeof(sha256tests) / sizeof(sha256tests[0]);
+ for (cnt = 0; cnt < numTests; cnt++) {
+ rv += testMessageDigest(initCtx, HASH_AlgSHA256, SHA256_LENGTH,
+ (const unsigned char *)sha256tests[cnt].input,
+ sha256tests[cnt].result, &results[0]);
+ }
+
+ rv += test_long_message_sha256(initCtx);
+ return rv;
+}
+
+static int
+testSHA384(NSSLOWInitContext *initCtx)
+{
+ static const struct {
+ const unsigned char *input;
+ const PRUint8 result[SHA384_LENGTH];
+ } sha384tests[] = {
+ /* Test vector from FIPS 180-2: appendix D, single-block message. */
+ { (unsigned char *)"abc",
+ { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
+ 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
+ 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
+ 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
+ 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
+ 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 } },
+
+ /* Test vectors from FIPS 180-2: appendix D, multi-block message. */
+ { (unsigned char *)"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ /*
+ 09330c33f71147e8
+ 3d192fc782cd1b47
+ 53111b173b3b05d2
+ 2fa08086e3b0f712
+ fcc7c71a557e2db9
+ 66c3e9fa91746039.
+ */
+ { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
+ 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
+ 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
+ 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,
+ 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,
+ 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 } }
+ };
+
+ PRUint8 results[SHA384_LENGTH];
+ int rv = 0, cnt, numTests;
+
+ numTests = sizeof(sha384tests) / sizeof(sha384tests[0]);
+ for (cnt = 0; cnt < numTests; cnt++) {
+ rv += testMessageDigest(initCtx, HASH_AlgSHA384, SHA384_LENGTH,
+ (const unsigned char *)sha384tests[cnt].input,
+ sha384tests[cnt].result, &results[0]);
+ }
+ rv += test_long_message_sha384(initCtx);
+
+ return rv;
+}
+
+int
+testSHA512(NSSLOWInitContext *initCtx)
+{
+ static const struct {
+ const unsigned char *input;
+ const PRUint8 result[SHA512_LENGTH];
+ } sha512tests[] = {
+ /* Test vectors from FIPS 180-2: appendix C.1. */
+ { (unsigned char *)"abc",
+ { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
+ 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
+ 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
+ 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f } },
+ /* Test vectors from FIPS 180-2: appendix C.2. */
+ { (unsigned char *)"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
+ 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
+ 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
+ 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 } }
+ };
+
+ PRUint8 results[SHA512_LENGTH];
+ int rv = 0, cnt, numTests;
+
+ numTests = sizeof(sha512tests) / sizeof(sha512tests[0]);
+ for (cnt = 0; cnt < numTests; cnt++) {
+ rv = testMessageDigest(initCtx, HASH_AlgSHA512, SHA512_LENGTH,
+ (const unsigned char *)sha512tests[cnt].input,
+ sha512tests[cnt].result, &results[0]);
+ }
+ rv += test_long_message_sha512(initCtx);
+ return rv;
+}
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr, "Usage: %s [algorithm]\n",
+ progName);
+ fprintf(stderr, "algorithm must be one of %s\n",
+ "{ MD5 | SHA1 | SHA224 | SHA256 | SHA384 | SHA512 }");
+ fprintf(stderr, "default is to test all\n");
+ exit(-1);
+}
+
+int
+main(int argc, char **argv)
+{
+ NSSLOWInitContext *initCtx;
+ int rv = 0; /* counts the number of failures */
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ initCtx = NSSLOW_Init();
+ if (initCtx == NULL) {
+ SECU_PrintError(progName, "Couldn't initialize for hashing\n");
+ return 1;
+ }
+
+ if (argc || !argv[1] || strlen(argv[1]) == 0) {
+ rv += testMD5(initCtx);
+ rv += testSHA1(initCtx);
+ rv += testSHA224(initCtx);
+ rv += testSHA256(initCtx);
+ rv += testSHA384(initCtx);
+ rv += testSHA512(initCtx);
+ } else if (strcmp(argv[1], "MD5") == 0) {
+ rv += testMD5(initCtx);
+ } else if (strcmp(argv[1], "SHA1") == 0) {
+ rv += testSHA1(initCtx);
+ } else if (strcmp(argv[1], "SHA224") == 0) {
+ rv += testSHA224(initCtx);
+ } else if (strcmp(argv[1], "SHA226") == 0) {
+ rv += testSHA256(initCtx);
+ } else if (strcmp(argv[1], "SHA384") == 0) {
+ rv += testSHA384(initCtx);
+ } else if (strcmp(argv[1], "SHA512") == 0) {
+ rv += testSHA512(initCtx);
+ } else {
+ SECU_PrintError(progName, "Unsupported hash type %s\n", argv[0]);
+ Usage(progName);
+ }
+
+ NSSLOW_Shutdown(initCtx);
+
+ return (rv == 0) ? 0 : 1;
+}
diff --git a/security/nss/cmd/lowhashtest/lowhashtest.gyp b/security/nss/cmd/lowhashtest/lowhashtest.gyp
new file mode 100644
index 000000000..3b3e3c29c
--- /dev/null
+++ b/security/nss/cmd/lowhashtest/lowhashtest.gyp
@@ -0,0 +1,32 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lowhashtest',
+ 'type': 'executable',
+ 'sources': [
+ 'lowhashtest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports',
+ '<(DEPTH)/lib/freebl/freebl.gyp:freebl3',
+ '<(DEPTH)/cmd/lib/lib.gyp:sectool'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'include_dirs': [
+ '../../nss/lib/freebl'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/lowhashtest/manifest.mn b/security/nss/cmd/lowhashtest/manifest.mn
new file mode 100644
index 000000000..f493571e5
--- /dev/null
+++ b/security/nss/cmd/lowhashtest/manifest.mn
@@ -0,0 +1,24 @@
+#
+# 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/.
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+REQUIRES = seccmd dbm softoken
+
+INCLUDES += -I$(CORE_DEPTH)/nss/lib/freebl
+
+PROGRAM = lowhashtest
+
+EXPORTS = \
+ $(NULL)
+
+PRIVATE_EXPORTS = \
+ $(NULL)
+
+CSRCS = \
+ lowhashtest.c \
+ $(NULL)
+
diff --git a/security/nss/cmd/makepqg/Makefile b/security/nss/cmd/makepqg/Makefile
new file mode 100644
index 000000000..8b239d2f5
--- /dev/null
+++ b/security/nss/cmd/makepqg/Makefile
@@ -0,0 +1,49 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
+
diff --git a/security/nss/cmd/makepqg/makepqg.c b/security/nss/cmd/makepqg/makepqg.c
new file mode 100644
index 000000000..85f8218ff
--- /dev/null
+++ b/security/nss/cmd/makepqg/makepqg.c
@@ -0,0 +1,349 @@
+/* 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/. */
+
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+
+#include "nss.h"
+#include "secutil.h"
+#include "secitem.h"
+#include "pk11func.h"
+#include "pk11pqg.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "plgetopt.h"
+
+#define BPB 8 /* bits per byte. */
+
+char *progName;
+
+const SEC_ASN1Template seckey_PQGParamsTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, prime) },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, subPrime) },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, base) },
+ { 0 }
+};
+
+void
+Usage(void)
+{
+ fprintf(stderr, "Usage: %s\n", progName);
+ fprintf(stderr,
+ "-a Output DER-encoded PQG params, BTOA encoded.\n"
+ "-b Output DER-encoded PQG params in binary\n"
+ "-r Output P, Q and G in ASCII hexadecimal. \n"
+ " -l prime-length Length of prime in bits (1024 is default)\n"
+ " -n subprime-length Length of subprime in bits\n"
+ " -o file Output to this file (default is stdout)\n"
+ " -g bits Generate SEED this many bits long.\n");
+ exit(-1);
+}
+
+SECStatus
+outputPQGParams(PQGParams *pqgParams, PRBool output_binary, PRBool output_raw,
+ FILE *outFile)
+{
+ PLArenaPool *arena = NULL;
+ char *PQG;
+ SECItem *pItem;
+ int cc;
+ SECStatus rv;
+ SECItem encodedParams;
+
+ if (output_raw) {
+ SECItem item;
+
+ rv = PK11_PQG_GetPrimeFromParams(pqgParams, &item);
+ if (rv) {
+ SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
+ return rv;
+ }
+ SECU_PrintInteger(outFile, &item, "Prime", 1);
+ SECITEM_FreeItem(&item, PR_FALSE);
+
+ rv = PK11_PQG_GetSubPrimeFromParams(pqgParams, &item);
+ if (rv) {
+ SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
+ return rv;
+ }
+ SECU_PrintInteger(outFile, &item, "Subprime", 1);
+ SECITEM_FreeItem(&item, PR_FALSE);
+
+ rv = PK11_PQG_GetBaseFromParams(pqgParams, &item);
+ if (rv) {
+ SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
+ return rv;
+ }
+ SECU_PrintInteger(outFile, &item, "Base", 1);
+ SECITEM_FreeItem(&item, PR_FALSE);
+
+ fprintf(outFile, "\n");
+ return SECSuccess;
+ }
+
+ encodedParams.data = NULL;
+ encodedParams.len = 0;
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ SECU_PrintError(progName, "PORT_NewArena");
+ return SECFailure;
+ }
+ pItem = SEC_ASN1EncodeItem(arena, &encodedParams, pqgParams,
+ seckey_PQGParamsTemplate);
+ if (!pItem) {
+ SECU_PrintError(progName, "SEC_ASN1EncodeItem");
+ PORT_FreeArena(arena, PR_FALSE);
+ return SECFailure;
+ }
+ if (output_binary) {
+ size_t len;
+ len = fwrite(encodedParams.data, 1, encodedParams.len, outFile);
+ PORT_FreeArena(arena, PR_FALSE);
+ if (len != encodedParams.len) {
+ fprintf(stderr, "%s: fwrite failed\n", progName);
+ return SECFailure;
+ }
+ return SECSuccess;
+ }
+
+ /* must be output ASCII */
+ PQG = BTOA_DataToAscii(encodedParams.data, encodedParams.len);
+ PORT_FreeArena(arena, PR_FALSE);
+ if (!PQG) {
+ SECU_PrintError(progName, "BTOA_DataToAscii");
+ return SECFailure;
+ }
+
+ cc = fprintf(outFile, "%s\n", PQG);
+ PORT_Free(PQG);
+ if (cc <= 0) {
+ fprintf(stderr, "%s: fprintf failed\n", progName);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+outputPQGVerify(PQGVerify *pqgVerify, PRBool output_binary, PRBool output_raw,
+ FILE *outFile)
+{
+ SECStatus rv = SECSuccess;
+ if (output_raw) {
+ SECItem item;
+ unsigned int counter;
+
+ rv = PK11_PQG_GetHFromVerify(pqgVerify, &item);
+ if (rv) {
+ SECU_PrintError(progName, "PK11_PQG_GetHFromVerify");
+ return rv;
+ }
+ SECU_PrintInteger(outFile, &item, "h", 1);
+ SECITEM_FreeItem(&item, PR_FALSE);
+
+ rv = PK11_PQG_GetSeedFromVerify(pqgVerify, &item);
+ if (rv) {
+ SECU_PrintError(progName, "PK11_PQG_GetSeedFromVerify");
+ return rv;
+ }
+ SECU_PrintInteger(outFile, &item, "SEED", 1);
+ fprintf(outFile, " g: %d\n", item.len * BPB);
+ SECITEM_FreeItem(&item, PR_FALSE);
+
+ counter = PK11_PQG_GetCounterFromVerify(pqgVerify);
+ fprintf(outFile, " counter: %d\n", counter);
+ fprintf(outFile, "\n");
+ }
+ return rv;
+}
+
+int
+main(int argc, char **argv)
+{
+ FILE *outFile = NULL;
+ char *outFileName = NULL;
+ PQGParams *pqgParams = NULL;
+ PQGVerify *pqgVerify = NULL;
+ int keySizeInBits = 1024;
+ int j = 8;
+ int g = 0;
+ int gMax = 0;
+ int qSizeInBits = 0;
+ SECStatus rv = 0;
+ SECStatus passed = 0;
+ PRBool output_ascii = PR_FALSE;
+ PRBool output_binary = PR_FALSE;
+ PRBool output_raw = PR_FALSE;
+ PLOptState *optstate;
+ PLOptStatus status;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName + 1 : argv[0];
+
+ /* Parse command line arguments */
+ optstate = PL_CreateOptState(argc, argv, "?abg:l:n:o:r");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+
+ case 'l':
+ keySizeInBits = atoi(optstate->value);
+ break;
+
+ case 'n':
+ qSizeInBits = atoi(optstate->value);
+ break;
+
+ case 'a':
+ output_ascii = PR_TRUE;
+ break;
+
+ case 'b':
+ output_binary = PR_TRUE;
+ break;
+
+ case 'r':
+ output_raw = PR_TRUE;
+ break;
+
+ case 'o':
+ if (outFileName) {
+ PORT_Free(outFileName);
+ }
+ outFileName = PORT_Strdup(optstate->value);
+ if (!outFileName) {
+ rv = -1;
+ }
+ break;
+
+ case 'g':
+ g = atoi(optstate->value);
+ break;
+
+ default:
+ case '?':
+ Usage();
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+
+ if (status == PL_OPT_BAD) {
+ Usage();
+ }
+
+ /* exactly 1 of these options must be set. */
+ if (1 != ((output_ascii != PR_FALSE) +
+ (output_binary != PR_FALSE) +
+ (output_raw != PR_FALSE))) {
+ Usage();
+ }
+
+ gMax = 2 * keySizeInBits;
+ if (keySizeInBits < 1024) {
+ j = PQG_PBITS_TO_INDEX(keySizeInBits);
+ if (j < 0) {
+ fprintf(stderr, "%s: Illegal prime length, \n"
+ "\tacceptable values are between 512 and 1024,\n"
+ "\tand divisible by 64, or 2048 or 3072\n",
+ progName);
+ return 2;
+ }
+ gMax = 2048;
+ if ((qSizeInBits != 0) && (qSizeInBits != 160)) {
+ fprintf(stderr, "%s: Illegal subprime length, \n"
+ "\tonly 160 is acceptible for primes <= 1024\n",
+ progName);
+ return 2;
+ }
+ /* this forces keysizes less than 1024 into the DSA1 generation
+ * code. Whether 1024 uses DSA2 or not is triggered by qSizeInBits
+ * being non-zero. All larger keysizes will use DSA2.
+ */
+ qSizeInBits = 0;
+ }
+ if (g != 0 && (g < 160 || g >= gMax || g % 8 != 0)) {
+ fprintf(stderr, "%s: Illegal g bits, \n"
+ "\tacceptable values are between 160 and %d,\n"
+ "\tand divisible by 8\n",
+ progName, gMax);
+ return 3;
+ }
+
+ if (!rv && outFileName) {
+ outFile = fopen(outFileName, output_binary ? "wb" : "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, outFileName);
+ rv = -1;
+ }
+ }
+ if (outFileName) {
+ PORT_Free(outFileName);
+ }
+ if (rv != 0) {
+ return 1;
+ }
+
+ if (outFile == NULL) {
+ outFile = stdout;
+ }
+
+ NSS_NoDB_Init(NULL);
+
+ if (keySizeInBits > 1024 || qSizeInBits != 0) {
+ rv = PK11_PQG_ParamGenV2((unsigned)keySizeInBits,
+ (unsigned)qSizeInBits, (unsigned)(g /
+ 8),
+ &pqgParams, &pqgVerify);
+ } else if (g) {
+ rv = PK11_PQG_ParamGenSeedLen((unsigned)j, (unsigned)(g / 8),
+ &pqgParams, &pqgVerify);
+ } else {
+ rv = PK11_PQG_ParamGen((unsigned)j, &pqgParams, &pqgVerify);
+ }
+ /* below here, must go to loser */
+
+ if (rv != SECSuccess || pqgParams == NULL || pqgVerify == NULL) {
+ SECU_PrintError(progName, "PQG parameter generation failed.\n");
+ goto loser;
+ }
+ fprintf(stderr, "%s: PQG parameter generation completed.\n", progName);
+
+ rv = outputPQGParams(pqgParams, output_binary, output_raw, outFile);
+ if (rv) {
+ fprintf(stderr, "%s: failed to output PQG params.\n", progName);
+ goto loser;
+ }
+ rv = outputPQGVerify(pqgVerify, output_binary, output_raw, outFile);
+ if (rv) {
+ fprintf(stderr, "%s: failed to output PQG Verify.\n", progName);
+ goto loser;
+ }
+
+ rv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: PQG parameter verification aborted.\n", progName);
+ goto loser;
+ }
+ if (passed != SECSuccess) {
+ fprintf(stderr, "%s: PQG parameters failed verification.\n", progName);
+ goto loser;
+ }
+ fprintf(stderr, "%s: PQG parameters passed verification.\n", progName);
+
+ PK11_PQG_DestroyParams(pqgParams);
+ PK11_PQG_DestroyVerify(pqgVerify);
+ return 0;
+
+loser:
+ PK11_PQG_DestroyParams(pqgParams);
+ PK11_PQG_DestroyVerify(pqgVerify);
+ return 1;
+}
diff --git a/security/nss/cmd/makepqg/makepqg.gyp b/security/nss/cmd/makepqg/makepqg.gyp
new file mode 100644
index 000000000..3ddc34afe
--- /dev/null
+++ b/security/nss/cmd/makepqg/makepqg.gyp
@@ -0,0 +1,25 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'makepqg',
+ 'type': 'executable',
+ 'sources': [
+ 'makepqg.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/makepqg/manifest.mn b/security/nss/cmd/makepqg/manifest.mn
new file mode 100644
index 000000000..f424410bf
--- /dev/null
+++ b/security/nss/cmd/makepqg/manifest.mn
@@ -0,0 +1,19 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+REQUIRES = dbm
+
+# DIRS =
+
+CSRCS = makepqg.c
+
+PROGRAM = makepqg
+
+#USE_STATIC_LIBS = 1
+
diff --git a/security/nss/cmd/makepqg/testit.ksh b/security/nss/cmd/makepqg/testit.ksh
new file mode 100644
index 000000000..e2cdb028b
--- /dev/null
+++ b/security/nss/cmd/makepqg/testit.ksh
@@ -0,0 +1,13 @@
+#
+# 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/.
+
+COUNTER=75
+while [ $COUNTER -ge "1" ]
+do
+ COUNTER=$(eval expr $COUNTER - 1)
+ echo $COUNTER
+ */makepqg.exe -r -l 640 -g 160 || exit 1
+done
+
diff --git a/security/nss/cmd/manifest.mn b/security/nss/cmd/manifest.mn
new file mode 100644
index 000000000..153384ce1
--- /dev/null
+++ b/security/nss/cmd/manifest.mn
@@ -0,0 +1,108 @@
+#
+# 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/.
+
+DEPTH = ..
+# MODULE = seccmd
+
+SOFTOKEN_SRCDIRS=
+NSS_SRCDIRS=
+LIB_SRCDIRS=
+
+ifdef NSS_BUILD_UTIL_ONLY
+REQUIRES = nspr
+else
+REQUIRES = nss nspr libdbm
+LIB_SRCDIRS = \
+ lib \
+ $(NULL)
+endif
+
+ifndef NSS_BUILD_UTIL_ONLY
+SOFTOKEN_SRCDIRS = \
+ $(BLTEST_SRCDIR) \
+ $(ECPERF_SRCDIR) \
+ $(FREEBL_ECTEST_SRCDIR) \
+ $(FIPSTEST_SRCDIR) \
+ $(LOWHASHTEST_SRCDIR) \
+ $(SHLIBSIGN_SRCDIR) \
+ $(NULL)
+endif
+
+ifndef NSS_BUILD_SOFTOKEN_ONLY
+ifndef NSS_BUILD_UTIL_ONLY
+NSS_SRCDIRS = \
+ addbuiltin \
+ atob \
+ btoa \
+ certcgi \
+ certutil \
+ chktest \
+ crlutil \
+ crmftest \
+ dbtest \
+ derdump \
+ digest \
+ httpserv \
+ listsuites \
+ makepqg \
+ multinit \
+ ocspclnt \
+ ocspresp \
+ oidcalc \
+ p7content \
+ p7env \
+ p7sign \
+ p7verify \
+ pk12util \
+ pk11ectest \
+ pk11gcmtest \
+ pk11mode \
+ pk1sign \
+ pp \
+ pwdecrypt \
+ rsaperf \
+ sdrtest \
+ selfserv \
+ signtool \
+ signver \
+ smimetools \
+ ssltap \
+ strsclnt \
+ symkeyutil \
+ tests \
+ tstclnt \
+ vfychain \
+ vfyserv \
+ modutil \
+ $(NULL)
+
+ifndef NSS_DISABLE_LIBPKIX
+NSS_SRCDIRS += \
+ pkix-errcodes \
+ $(NULL)
+endif
+
+endif
+endif
+
+DIRS = \
+ $(LIB_SRCDIRS) \
+ $(SOFTOKEN_SRCDIRS) \
+ $(NSS_SRCDIRS)
+
+TEMPORARILY_DONT_BUILD = \
+ $(NULL)
+
+# rsaperf \
+#
+# needs to look at what needs to happen to make jar build in
+# the binary release environment.
+#
+# perror requires lib/strerror.c which requires the client code installed
+# to build (requires allxpstr.h)
+#
+DONT_BULD = jar \
+ perror \
+$(NULL)
diff --git a/security/nss/cmd/modutil/Makefile b/security/nss/cmd/modutil/Makefile
new file mode 100644
index 000000000..fc7b4b122
--- /dev/null
+++ b/security/nss/cmd/modutil/Makefile
@@ -0,0 +1,54 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+include $(CORE_DEPTH)/coreconf/zlib.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
+#
+# Cancel the built-in implicit yacc and lex rules.
+#
+
+%.c: %.y
+%.c: %.l
diff --git a/security/nss/cmd/modutil/README b/security/nss/cmd/modutil/README
new file mode 100644
index 000000000..12d192c9f
--- /dev/null
+++ b/security/nss/cmd/modutil/README
@@ -0,0 +1,7 @@
+ CRYPTOGRAPHIC MODULE UTILITY (modutil)
+ VERSION 1.0
+ ===============================================
+
+The file specification.html documentats the software.
+
+The file pk11jar.html documents the PKCS #11 JAR format.
diff --git a/security/nss/cmd/modutil/error.h b/security/nss/cmd/modutil/error.h
new file mode 100644
index 000000000..b328afebc
--- /dev/null
+++ b/security/nss/cmd/modutil/error.h
@@ -0,0 +1,139 @@
+/* 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 MODUTIL_ERROR_H
+#define MODUTIL_ERROR_H
+
+/*
+ * The values of these enumerated constants are immutable and must not be
+ * changed.
+ */
+typedef enum {
+ NO_ERR = 0,
+ INVALID_USAGE_ERR,
+ UNEXPECTED_ARG_ERR,
+ UNKNOWN_OPTION_ERR,
+ MULTIPLE_COMMAND_ERR,
+ OPTION_NEEDS_ARG_ERR,
+ DUPLICATE_OPTION_ERR,
+ MISSING_PARAM_ERR,
+ INVALID_FIPS_ARG,
+ NO_COMMAND_ERR,
+ NO_DBDIR_ERR,
+ FIPS_SWITCH_FAILED_ERR,
+ FIPS_ALREADY_ON_ERR,
+ FIPS_ALREADY_OFF_ERR,
+ FILE_ALREADY_EXISTS_ERR,
+ FILE_DOESNT_EXIST_ERR,
+ FILE_NOT_READABLE_ERR,
+ FILE_NOT_WRITEABLE_ERR,
+ DIR_DOESNT_EXIST_ERR,
+ DIR_NOT_READABLE_ERR,
+ DIR_NOT_WRITEABLE_ERR,
+ INVALID_CONSTANT_ERR,
+ ADD_MODULE_FAILED_ERR,
+ UNUSED_ERR, /* reserved for future use */
+ OUT_OF_MEM_ERR,
+ DELETE_INTERNAL_ERR,
+ DELETE_FAILED_ERR,
+ NO_LIST_LOCK_ERR,
+ NO_MODULE_LIST_ERR,
+ NO_SUCH_MODULE_ERR,
+ MOD_INFO_ERR,
+ SLOT_INFO_ERR,
+ TOKEN_INFO_ERR,
+ NO_SUCH_TOKEN_ERR,
+ CHANGEPW_FAILED_ERR,
+ BAD_PW_ERR,
+ DB_ACCESS_ERR,
+ AUTHENTICATION_FAILED_ERR,
+ NO_SUCH_SLOT_ERR,
+ ENABLE_FAILED_ERR,
+ UPDATE_MOD_FAILED_ERR,
+ DEFAULT_FAILED_ERR,
+ UNDEFAULT_FAILED_ERR,
+ STDIN_READ_ERR,
+ UNSPECIFIED_ERR,
+ NOCERTDB_MISUSE_ERR,
+ NSS_INITIALIZE_FAILED_ERR,
+
+ LAST_ERR /* must be last */
+} Error;
+#define SUCCESS NO_ERR
+
+/* !!! Should move this into its own .c and un-static it. */
+static char *errStrings[] = {
+ "Operation completed successfully.\n",
+ "ERROR: Invalid command line.\n",
+ "ERROR: Not expecting argument \"%s\".\n",
+ "ERROR: Unknown option: %s.\n",
+ "ERROR: %s: multiple commands are not allowed on the command line.\n",
+ "ERROR: %s: option needs an argument.\n",
+ "ERROR: %s: option cannot be given more than once.\n",
+ "ERROR: Command \"%s\" requires parameter \"%s\".\n",
+ "ERROR: Argument to -fips must be \"true\" or \"false\".\n",
+ "ERROR: No command was specified.\n",
+ "ERROR: Cannot determine database directory: use the -dbdir option.\n",
+ "ERROR: Unable to switch FIPS modes.\n",
+ "FIPS mode already enabled.\n",
+ "FIPS mode already disabled.\n",
+ "ERROR: File \"%s\" already exists.\n",
+ "ERROR: File \"%s\" does not exist.\n",
+ "ERROR: File \"%s\" is not readable.\n",
+ "ERROR: File \"%s\" is not writeable.\n",
+ "ERROR: Directory \"%s\" does not exist.\n",
+ "ERROR: Directory \"%s\" is not readable.\n",
+ "ERROR: Directory \"%s\" is not writeable.\n",
+ "\"%s\" is not a recognized value.\n",
+ "ERROR: Failed to add module \"%s\". Probable cause : \"%s\".\n",
+ "Unused error string",
+ "ERROR: Out of memory.\n",
+ "ERROR: Cannot delete internal module.\n",
+ "ERROR: Failed to delete module \"%s\".\n",
+ "ERROR: Unable to obtain lock on module list.\n",
+ "ERROR: Unable to obtain module list.\n",
+ "ERROR: Module \"%s\" not found in database.\n",
+ "ERROR: Unable to get information about module \"%s\".\n",
+ "ERROR: Unable to get information about slot \"%s\".\n",
+ "ERROR: Unable to get information about token \"%s\".\n",
+ "ERROR: Token \"%s\" not found.\n",
+ "ERROR: Unable to change password on token \"%s\".\n",
+ "ERROR: Incorrect password.\n",
+ "ERROR: Unable to access database \"%s\".\n",
+ "ERROR: Unable to authenticate to token \"%s\".\n",
+ "ERROR: Slot \"%s\" not found.\n",
+ "ERROR: Failed to %s slot \"%s\".\n",
+ "ERROR: Failed to update module \"%s\".\n",
+ "ERROR: Failed to change defaults.\n",
+ "ERROR: Failed to change default.\n",
+ "ERROR: Unable to read from standard input.\n",
+ "ERROR: Unknown error occurred.\n",
+ "ERROR: -nocertdb option can only be used with the -jar command.\n"
+ "ERROR: NSS_Initialize() failed.\n"
+};
+
+typedef enum {
+ FIPS_ENABLED_MSG = 0,
+ FIPS_DISABLED_MSG,
+ USING_DBDIR_MSG,
+ CREATING_DB_MSG,
+ ADD_MODULE_SUCCESS_MSG,
+ DELETE_SUCCESS_MSG,
+ CHANGEPW_SUCCESS_MSG,
+ BAD_PW_MSG,
+ PW_MATCH_MSG,
+ DONE_MSG,
+ ENABLE_SUCCESS_MSG,
+ DEFAULT_SUCCESS_MSG,
+ UNDEFAULT_SUCCESS_MSG,
+ BROWSER_RUNNING_MSG,
+ ABORTING_MSG,
+
+ LAST_MSG /* must be last */
+} Message;
+
+/* defined in modutil.c */
+extern char *msgStrings[];
+
+#endif /* MODUTIL_ERROR_H */
diff --git a/security/nss/cmd/modutil/install-ds.c b/security/nss/cmd/modutil/install-ds.c
new file mode 100644
index 000000000..c8fef7897
--- /dev/null
+++ b/security/nss/cmd/modutil/install-ds.c
@@ -0,0 +1,1525 @@
+/* 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/. */
+
+#include "install-ds.h"
+#include <prmem.h>
+#include <plstr.h>
+#include <prprf.h>
+#include <string.h>
+
+#define PORT_Strcasecmp PL_strcasecmp
+
+#define MODULE_FILE_STRING "ModuleFile"
+#define MODULE_NAME_STRING "ModuleName"
+#define MECH_FLAGS_STRING "DefaultMechanismFlags"
+#define CIPHER_FLAGS_STRING "DefaultCipherFlags"
+#define FILES_STRING "Files"
+#define FORWARD_COMPATIBLE_STRING "ForwardCompatible"
+#define PLATFORMS_STRING "Platforms"
+#define RELATIVE_DIR_STRING "RelativePath"
+#define ABSOLUTE_DIR_STRING "AbsolutePath"
+#define FILE_PERMISSIONS_STRING "FilePermissions"
+#define EQUIVALENT_PLATFORM_STRING "EquivalentPlatform"
+#define EXECUTABLE_STRING "Executable"
+
+#define DEFAULT_PERMISSIONS 0777
+
+#define PLATFORM_SEPARATOR_CHAR ':'
+
+/* Error codes */
+enum {
+ BOGUS_RELATIVE_DIR = 0,
+ BOGUS_ABSOLUTE_DIR,
+ BOGUS_FILE_PERMISSIONS,
+ NO_RELATIVE_DIR,
+ NO_ABSOLUTE_DIR,
+ EMPTY_PLATFORM_STRING,
+ BOGUS_PLATFORM_STRING,
+ REPEAT_MODULE_FILE,
+ REPEAT_MODULE_NAME,
+ BOGUS_MODULE_FILE,
+ BOGUS_MODULE_NAME,
+ REPEAT_MECH,
+ BOGUS_MECH_FLAGS,
+ REPEAT_CIPHER,
+ BOGUS_CIPHER_FLAGS,
+ REPEAT_FILES,
+ REPEAT_EQUIV,
+ BOGUS_EQUIV,
+ EQUIV_TOO_MUCH_INFO,
+ NO_FILES,
+ NO_MODULE_FILE,
+ NO_MODULE_NAME,
+ NO_PLATFORMS,
+ EQUIV_LOOP,
+ UNKNOWN_MODULE_FILE
+};
+
+/* Indexed by the above error codes */
+static const char* errString[] = {
+ "%s: Invalid relative directory",
+ "%s: Invalid absolute directory",
+ "%s: Invalid file permissions",
+ "%s: No relative directory specified",
+ "%s: No absolute directory specified",
+ "Empty string given for platform name",
+ "%s: invalid platform string",
+ "More than one ModuleFile entry given for platform %s",
+ "More than one ModuleName entry given for platform %s",
+ "Invalid ModuleFile specification for platform %s",
+ "Invalid ModuleName specification for platform %s",
+ "More than one DefaultMechanismFlags entry given for platform %s",
+ "Invalid DefaultMechanismFlags specification for platform %s",
+ "More than one DefaultCipherFlags entry given for platform %s",
+ "Invalid DefaultCipherFlags entry given for platform %s",
+ "More than one Files entry given for platform %s",
+ "More than one EquivalentPlatform entry given for platform %s",
+ "Invalid EquivalentPlatform specification for platform %s",
+ "Module %s uses an EquivalentPlatform but also specifies its own"
+ " information",
+ "No Files specification in module %s",
+ "No ModuleFile specification in module %s",
+ "No ModuleName specification in module %s",
+ "No Platforms specification in installer script",
+ "Platform %s has an equivalency loop",
+ "Module file \"%s\" in platform \"%s\" does not exist"
+};
+
+static char* PR_Strdup(const char* str);
+
+#define PAD(x) \
+ { \
+ int i; \
+ for (i = 0; i < x; i++) \
+ printf(" "); \
+ }
+#define PADINC 4
+
+Pk11Install_File*
+Pk11Install_File_new()
+{
+ Pk11Install_File* new_this;
+ new_this = (Pk11Install_File*)PR_Malloc(sizeof(Pk11Install_File));
+ Pk11Install_File_init(new_this);
+ return new_this;
+}
+
+void
+Pk11Install_File_init(Pk11Install_File* _this)
+{
+ _this->jarPath = NULL;
+ _this->relativePath = NULL;
+ _this->absolutePath = NULL;
+ _this->executable = PR_FALSE;
+ _this->permissions = 0;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: ~Pk11Install_File
+// Class: Pk11Install_File
+// Notes: Destructor.
+*/
+void
+Pk11Install_File_delete(Pk11Install_File* _this)
+{
+ Pk11Install_File_Cleanup(_this);
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Cleanup
+// Class: Pk11Install_File
+*/
+void
+Pk11Install_File_Cleanup(Pk11Install_File* _this)
+{
+ if (_this->jarPath) {
+ PR_Free(_this->jarPath);
+ _this->jarPath = NULL;
+ }
+ if (_this->relativePath) {
+ PR_Free(_this->relativePath);
+ _this->relativePath = NULL;
+ }
+ if (_this->absolutePath) {
+ PR_Free(_this->absolutePath);
+ _this->absolutePath = NULL;
+ }
+
+ _this->permissions = 0;
+ _this->executable = PR_FALSE;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Generate
+// Class: Pk11Install_File
+// Notes: Creates a file data structure from a syntax tree.
+// Returns: NULL for success, otherwise an error message.
+*/
+char*
+Pk11Install_File_Generate(Pk11Install_File* _this,
+ const Pk11Install_Pair* pair)
+{
+ Pk11Install_ListIter* iter;
+ Pk11Install_Value* val;
+ Pk11Install_Pair* subpair;
+ Pk11Install_ListIter* subiter;
+ Pk11Install_Value* subval;
+ char* errStr;
+ char* endp;
+ PRBool gotPerms;
+
+ iter = NULL;
+ subiter = NULL;
+ errStr = NULL;
+ gotPerms = PR_FALSE;
+
+ /* Clear out old values */
+ Pk11Install_File_Cleanup(_this);
+
+ _this->jarPath = PR_Strdup(pair->key);
+
+ /* Go through all the pairs under this file heading */
+ iter = Pk11Install_ListIter_new(pair->list);
+ for (; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) {
+ if (val->type == PAIR_VALUE) {
+ subpair = val->pair;
+
+ /* Relative directory */
+ if (!PORT_Strcasecmp(subpair->key, RELATIVE_DIR_STRING)) {
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if (!subval || (subval->type != STRING_VALUE)) {
+ errStr = PR_smprintf(errString[BOGUS_RELATIVE_DIR],
+ _this->jarPath);
+ goto loser;
+ }
+ _this->relativePath = PR_Strdup(subval->string);
+ Pk11Install_ListIter_delete(&subiter);
+
+ /* Absolute directory */
+ } else if (!PORT_Strcasecmp(subpair->key, ABSOLUTE_DIR_STRING)) {
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if (!subval || (subval->type != STRING_VALUE)) {
+ errStr = PR_smprintf(errString[BOGUS_ABSOLUTE_DIR],
+ _this->jarPath);
+ goto loser;
+ }
+ _this->absolutePath = PR_Strdup(subval->string);
+ Pk11Install_ListIter_delete(&subiter);
+
+ /* file permissions */
+ } else if (!PORT_Strcasecmp(subpair->key,
+ FILE_PERMISSIONS_STRING)) {
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if (!subval || (subval->type != STRING_VALUE) ||
+ !subval->string || !subval->string[0]) {
+ errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS],
+ _this->jarPath);
+ goto loser;
+ }
+ _this->permissions = (int)strtol(subval->string, &endp, 8);
+ if (*endp != '\0') {
+ errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS],
+ _this->jarPath);
+ goto loser;
+ }
+ gotPerms = PR_TRUE;
+ Pk11Install_ListIter_delete(&subiter);
+ }
+ } else {
+ if (!PORT_Strcasecmp(val->string, EXECUTABLE_STRING)) {
+ _this->executable = PR_TRUE;
+ }
+ }
+ }
+
+ /* Default permission value */
+ if (!gotPerms) {
+ _this->permissions = DEFAULT_PERMISSIONS;
+ }
+
+ /* Make sure we got all the information */
+ if (!_this->relativePath && !_this->absolutePath) {
+ errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath);
+ goto loser;
+ }
+#if 0
+ if(!_this->relativePath ) {
+ errStr = PR_smprintf(errString[NO_RELATIVE_DIR], _this->jarPath);
+ goto loser;
+ }
+ if(!_this->absolutePath) {
+ errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath);
+ goto loser;
+ }
+#endif
+
+loser:
+ if (iter) {
+ Pk11Install_ListIter_delete(&iter);
+ }
+ if (subiter) {
+ Pk11Install_ListIter_delete(&subiter);
+ }
+ return errStr;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Print
+// Class: Pk11Install_File
+*/
+void
+Pk11Install_File_Print(Pk11Install_File* _this, int pad)
+{
+ PAD(pad);
+ printf("jarPath: %s\n",
+ _this->jarPath ? _this->jarPath : "<NULL>");
+ PAD(pad);
+ printf("relativePath: %s\n",
+ _this->relativePath ? _this->relativePath : "<NULL>");
+ PAD(pad);
+ printf("absolutePath: %s\n",
+ _this->absolutePath ? _this->absolutePath : "<NULL>");
+ PAD(pad);
+ printf("permissions: %o\n", _this->permissions);
+}
+
+Pk11Install_PlatformName*
+Pk11Install_PlatformName_new()
+{
+ Pk11Install_PlatformName* new_this;
+ new_this = (Pk11Install_PlatformName*)
+ PR_Malloc(sizeof(Pk11Install_PlatformName));
+ Pk11Install_PlatformName_init(new_this);
+ return new_this;
+}
+
+void
+Pk11Install_PlatformName_init(Pk11Install_PlatformName* _this)
+{
+ _this->OS = NULL;
+ _this->verString = NULL;
+ _this->numDigits = 0;
+ _this->arch = NULL;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: ~Pk11Install_PlatformName
+// Class: Pk11Install_PlatformName
+*/
+void
+Pk11Install_PlatformName_delete(Pk11Install_PlatformName* _this)
+{
+ Pk11Install_PlatformName_Cleanup(_this);
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Cleanup
+// Class: Pk11Install_PlatformName
+*/
+void
+Pk11Install_PlatformName_Cleanup(Pk11Install_PlatformName* _this)
+{
+ if (_this->OS) {
+ PR_Free(_this->OS);
+ _this->OS = NULL;
+ }
+ if (_this->verString) {
+ int i;
+ for (i = 0; i < _this->numDigits; i++) {
+ PR_Free(_this->verString[i]);
+ }
+ PR_Free(_this->verString);
+ _this->verString = NULL;
+ }
+ if (_this->arch) {
+ PR_Free(_this->arch);
+ _this->arch = NULL;
+ }
+ _this->numDigits = 0;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Generate
+// Class: Pk11Install_PlatformName
+// Notes: Extracts the information from a platform string.
+*/
+char*
+Pk11Install_PlatformName_Generate(Pk11Install_PlatformName* _this,
+ const char* str)
+{
+ char* errStr;
+ char* copy;
+ char *end, *start; /* start and end of a section (OS, version, arch)*/
+ char *pend, *pstart; /* start and end of one portion of version*/
+ char* endp; /* used by strtol*/
+ int periods, i;
+
+ errStr = NULL;
+ copy = NULL;
+
+ if (!str) {
+ errStr = PR_smprintf(errString[EMPTY_PLATFORM_STRING]);
+ goto loser;
+ }
+ copy = PR_Strdup(str);
+
+ /*
+ // Get the OS
+ */
+ end = strchr(copy, PLATFORM_SEPARATOR_CHAR);
+ if (!end || end == copy) {
+ errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
+ goto loser;
+ }
+ *end = '\0';
+
+ _this->OS = PR_Strdup(copy);
+
+ /*
+ // Get the digits of the version of form: x.x.x (arbitrary number of digits)
+ */
+
+ start = end + 1;
+ end = strchr(start, PLATFORM_SEPARATOR_CHAR);
+ if (!end) {
+ errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
+ goto loser;
+ }
+ *end = '\0';
+
+ if (end != start) {
+ /* Find out how many periods*/
+ periods = 0;
+ pstart = start;
+ while ((pend = strchr(pstart, '.'))) {
+ periods++;
+ pstart = pend + 1;
+ }
+ _this->numDigits = 1 + periods;
+ _this->verString = (char**)PR_Malloc(sizeof(char*) * _this->numDigits);
+
+ pstart = start;
+ i = 0;
+ /* Get the digits before each period*/
+ while ((pend = strchr(pstart, '.'))) {
+ if (pend == pstart) {
+ errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
+ goto loser;
+ }
+ *pend = '\0';
+ _this->verString[i] = PR_Strdup(pstart);
+ endp = pend;
+ if (endp == pstart || (*endp != '\0')) {
+ errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
+ goto loser;
+ }
+ pstart = pend + 1;
+ i++;
+ }
+ /* Last digit comes after the last period*/
+ if (*pstart == '\0') {
+ errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
+ goto loser;
+ }
+ _this->verString[i] = PR_Strdup(pstart);
+ /*
+ if(endp==pstart || (*endp != '\0')) {
+ errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
+ goto loser;
+ }
+ */
+ } else {
+ _this->verString = NULL;
+ _this->numDigits = 0;
+ }
+
+ /*
+ // Get the architecture
+ */
+ start = end + 1;
+ if (strchr(start, PLATFORM_SEPARATOR_CHAR)) {
+ errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
+ goto loser;
+ }
+ _this->arch = PR_Strdup(start);
+
+ if (copy) {
+ PR_Free(copy);
+ }
+ return NULL;
+loser:
+ if (_this->OS) {
+ PR_Free(_this->OS);
+ _this->OS = NULL;
+ }
+ if (_this->verString) {
+ for (i = 0; i < _this->numDigits; i++) {
+ PR_Free(_this->verString[i]);
+ }
+ PR_Free(_this->verString);
+ _this->verString = NULL;
+ }
+ _this->numDigits = 0;
+ if (_this->arch) {
+ PR_Free(_this->arch);
+ _this->arch = NULL;
+ }
+ if (copy) {
+ PR_Free(copy);
+ }
+
+ return errStr;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: operator ==
+// Class: Pk11Install_PlatformName
+// Returns: PR_TRUE if the platform have the same OS, arch, and version
+*/
+PRBool
+Pk11Install_PlatformName_equal(Pk11Install_PlatformName* _this,
+ Pk11Install_PlatformName* cmp)
+{
+ int i;
+
+ if (!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) {
+ return PR_FALSE;
+ }
+
+ if (PORT_Strcasecmp(_this->OS, cmp->OS) ||
+ PORT_Strcasecmp(_this->arch, cmp->arch) ||
+ _this->numDigits != cmp->numDigits) {
+ return PR_FALSE;
+ }
+
+ for (i = 0; i < _this->numDigits; i++) {
+ if (PORT_Strcasecmp(_this->verString[i], cmp->verString[i])) {
+ return PR_FALSE;
+ }
+ }
+ return PR_TRUE;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: operator <=
+// Class: Pk11Install_PlatformName
+// Returns: PR_TRUE if the platform have the same OS and arch and a lower
+// or equal release.
+*/
+PRBool
+Pk11Install_PlatformName_lteq(Pk11Install_PlatformName* _this,
+ Pk11Install_PlatformName* cmp)
+{
+ return (Pk11Install_PlatformName_equal(_this, cmp) ||
+ Pk11Install_PlatformName_lt(_this, cmp))
+ ? PR_TRUE
+ : PR_FALSE;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: operator <
+// Class: Pk11Install_PlatformName
+// Returns: PR_TRUE if the platform have the same OS and arch and a greater
+// release.
+*/
+PRBool
+Pk11Install_PlatformName_lt(Pk11Install_PlatformName* _this,
+ Pk11Install_PlatformName* cmp)
+{
+ int i, scmp;
+
+ if (!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) {
+ return PR_FALSE;
+ }
+
+ if (PORT_Strcasecmp(_this->OS, cmp->OS)) {
+ return PR_FALSE;
+ }
+ if (PORT_Strcasecmp(_this->arch, cmp->arch)) {
+ return PR_FALSE;
+ }
+
+ for (i = 0; (i < _this->numDigits) && (i < cmp->numDigits); i++) {
+ scmp = PORT_Strcasecmp(_this->verString[i], cmp->verString[i]);
+ if (scmp > 0) {
+ return PR_FALSE;
+ } else if (scmp < 0) {
+ return PR_TRUE;
+ }
+ }
+ /* All the digits they have in common are the same. */
+ if (_this->numDigits < cmp->numDigits) {
+ return PR_TRUE;
+ }
+
+ return PR_FALSE;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: GetString
+// Class: Pk11Install_PlatformName
+// Returns: String composed of OS, release, and architecture separated
+// by the separator char. Memory is allocated by this function
+// but is the responsibility of the caller to de-allocate.
+*/
+char*
+Pk11Install_PlatformName_GetString(Pk11Install_PlatformName* _this)
+{
+ char* ret;
+ char* ver;
+ char* OS_;
+ char* arch_;
+
+ OS_ = NULL;
+ arch_ = NULL;
+
+ OS_ = _this->OS ? _this->OS : "";
+ arch_ = _this->arch ? _this->arch : "";
+
+ ver = Pk11Install_PlatformName_GetVerString(_this);
+ ret = PR_smprintf("%s%c%s%c%s", OS_, PLATFORM_SEPARATOR_CHAR, ver,
+ PLATFORM_SEPARATOR_CHAR, arch_);
+
+ PR_Free(ver);
+
+ return ret;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: GetVerString
+// Class: Pk11Install_PlatformName
+// Returns: The version string for this platform, in the form x.x.x with an
+// arbitrary number of digits. Memory allocated by function,
+// must be de-allocated by caller.
+*/
+char*
+Pk11Install_PlatformName_GetVerString(Pk11Install_PlatformName* _this)
+{
+ char* tmp;
+ char* ret;
+ int i;
+ char buf[80];
+
+ tmp = (char*)PR_Malloc(80 * _this->numDigits + 1);
+ tmp[0] = '\0';
+
+ for (i = 0; i < _this->numDigits - 1; i++) {
+ sprintf(buf, "%s.", _this->verString[i]);
+ strcat(tmp, buf);
+ }
+ if (i < _this->numDigits) {
+ sprintf(buf, "%s", _this->verString[i]);
+ strcat(tmp, buf);
+ }
+
+ ret = PR_Strdup(tmp);
+ free(tmp);
+
+ return ret;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Print
+// Class: Pk11Install_PlatformName
+*/
+void
+Pk11Install_PlatformName_Print(Pk11Install_PlatformName* _this, int pad)
+{
+ char* str = NULL;
+ PAD(pad);
+ printf("OS: %s\n", _this->OS ? _this->OS : "<NULL>");
+ PAD(pad);
+ printf("Digits: ");
+ if (_this->numDigits == 0) {
+ printf("None\n");
+ } else {
+ str = Pk11Install_PlatformName_GetVerString(_this);
+ printf("%s\n", str);
+ PR_Free(str);
+ }
+ PAD(pad);
+ printf("arch: %s\n", _this->arch ? _this->arch : "<NULL>");
+}
+
+Pk11Install_Platform*
+Pk11Install_Platform_new()
+{
+ Pk11Install_Platform* new_this;
+ new_this = (Pk11Install_Platform*)PR_Malloc(sizeof(Pk11Install_Platform));
+ Pk11Install_Platform_init(new_this);
+ return new_this;
+}
+
+void
+Pk11Install_Platform_init(Pk11Install_Platform* _this)
+{
+ Pk11Install_PlatformName_init(&_this->name);
+ Pk11Install_PlatformName_init(&_this->equivName);
+ _this->equiv = NULL;
+ _this->usesEquiv = PR_FALSE;
+ _this->moduleFile = NULL;
+ _this->moduleName = NULL;
+ _this->modFile = -1;
+ _this->mechFlags = 0;
+ _this->cipherFlags = 0;
+ _this->files = NULL;
+ _this->numFiles = 0;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: ~Pk11Install_Platform
+// Class: Pk11Install_Platform
+*/
+void
+Pk11Install_Platform_delete(Pk11Install_Platform* _this)
+{
+ Pk11Install_Platform_Cleanup(_this);
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Cleanup
+// Class: Pk11Install_Platform
+*/
+void
+Pk11Install_Platform_Cleanup(Pk11Install_Platform* _this)
+{
+ int i;
+ if (_this->moduleFile) {
+ PR_Free(_this->moduleFile);
+ _this->moduleFile = NULL;
+ }
+ if (_this->moduleName) {
+ PR_Free(_this->moduleName);
+ _this->moduleName = NULL;
+ }
+ if (_this->files) {
+ for (i = 0; i < _this->numFiles; i++) {
+ Pk11Install_File_delete(&_this->files[i]);
+ }
+ PR_Free(_this->files);
+ _this->files = NULL;
+ }
+ _this->equiv = NULL;
+ _this->usesEquiv = PR_FALSE;
+ _this->modFile = -1;
+ _this->numFiles = 0;
+ _this->mechFlags = _this->cipherFlags = 0;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Generate
+// Class: Pk11Install_Platform
+// Notes: Creates a platform data structure from a syntax tree.
+// Returns: NULL for success, otherwise an error message.
+*/
+char*
+Pk11Install_Platform_Generate(Pk11Install_Platform* _this,
+ const Pk11Install_Pair* pair)
+{
+ char* errStr;
+ char* endptr;
+ char* tmp;
+ int i;
+ Pk11Install_ListIter* iter;
+ Pk11Install_Value* val;
+ Pk11Install_Value* subval;
+ Pk11Install_Pair* subpair;
+ Pk11Install_ListIter* subiter;
+ PRBool gotModuleFile, gotModuleName, gotMech,
+ gotCipher, gotFiles, gotEquiv;
+
+ errStr = NULL;
+ iter = subiter = NULL;
+ val = subval = NULL;
+ subpair = NULL;
+ gotModuleFile = gotModuleName = gotMech = gotCipher = gotFiles = gotEquiv = PR_FALSE;
+ Pk11Install_Platform_Cleanup(_this);
+
+ errStr = Pk11Install_PlatformName_Generate(&_this->name, pair->key);
+ if (errStr) {
+ tmp = PR_smprintf("%s: %s", pair->key, errStr);
+ PR_smprintf_free(errStr);
+ errStr = tmp;
+ goto loser;
+ }
+
+ iter = Pk11Install_ListIter_new(pair->list);
+ for (; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) {
+ if (val->type == PAIR_VALUE) {
+ subpair = val->pair;
+
+ if (!PORT_Strcasecmp(subpair->key, MODULE_FILE_STRING)) {
+ if (gotModuleFile) {
+ errStr = PR_smprintf(errString[REPEAT_MODULE_FILE],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if (!subval || (subval->type != STRING_VALUE)) {
+ errStr = PR_smprintf(errString[BOGUS_MODULE_FILE],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ _this->moduleFile = PR_Strdup(subval->string);
+ Pk11Install_ListIter_delete(&subiter);
+ gotModuleFile = PR_TRUE;
+ } else if (!PORT_Strcasecmp(subpair->key, MODULE_NAME_STRING)) {
+ if (gotModuleName) {
+ errStr = PR_smprintf(errString[REPEAT_MODULE_NAME],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if (!subval || (subval->type != STRING_VALUE)) {
+ errStr = PR_smprintf(errString[BOGUS_MODULE_NAME],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ _this->moduleName = PR_Strdup(subval->string);
+ Pk11Install_ListIter_delete(&subiter);
+ gotModuleName = PR_TRUE;
+ } else if (!PORT_Strcasecmp(subpair->key, MECH_FLAGS_STRING)) {
+ endptr = NULL;
+
+ if (gotMech) {
+ errStr = PR_smprintf(errString[REPEAT_MECH],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if (!subval || (subval->type != STRING_VALUE)) {
+ errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ _this->mechFlags = strtol(subval->string, &endptr, 0);
+ if (*endptr != '\0' || (endptr == subval->string)) {
+ errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ Pk11Install_ListIter_delete(&subiter);
+ gotMech = PR_TRUE;
+ } else if (!PORT_Strcasecmp(subpair->key, CIPHER_FLAGS_STRING)) {
+ endptr = NULL;
+
+ if (gotCipher) {
+ errStr = PR_smprintf(errString[REPEAT_CIPHER],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if (!subval || (subval->type != STRING_VALUE)) {
+ errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ _this->cipherFlags = strtol(subval->string, &endptr, 0);
+ if (*endptr != '\0' || (endptr == subval->string)) {
+ errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ Pk11Install_ListIter_delete(&subiter);
+ gotCipher = PR_TRUE;
+ } else if (!PORT_Strcasecmp(subpair->key, FILES_STRING)) {
+ if (gotFiles) {
+ errStr = PR_smprintf(errString[REPEAT_FILES],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ _this->numFiles = subpair->list->numPairs;
+ _this->files = (Pk11Install_File*)
+ PR_Malloc(sizeof(Pk11Install_File) * _this->numFiles);
+ for (i = 0; i < _this->numFiles; i++,
+ Pk11Install_ListIter_nextItem(subiter)) {
+ Pk11Install_File_init(&_this->files[i]);
+ val = subiter->current;
+ if (val && (val->type == PAIR_VALUE)) {
+ errStr = Pk11Install_File_Generate(&_this->files[i], val->pair);
+ if (errStr) {
+ tmp = PR_smprintf("%s: %s",
+ Pk11Install_PlatformName_GetString(&_this->name), errStr);
+ PR_smprintf_free(errStr);
+ errStr = tmp;
+ goto loser;
+ }
+ }
+ }
+ gotFiles = PR_TRUE;
+ } else if (!PORT_Strcasecmp(subpair->key,
+ EQUIVALENT_PLATFORM_STRING)) {
+ if (gotEquiv) {
+ errStr = PR_smprintf(errString[REPEAT_EQUIV],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if (!subval || (subval->type != STRING_VALUE)) {
+ errStr = PR_smprintf(errString[BOGUS_EQUIV],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ errStr = Pk11Install_PlatformName_Generate(&_this->equivName,
+ subval->string);
+ if (errStr) {
+ tmp = PR_smprintf("%s: %s",
+ Pk11Install_PlatformName_GetString(&_this->name), errStr);
+ tmp = PR_smprintf("%s: %s",
+ Pk11Install_PlatformName_GetString(&_this->name), errStr);
+ PR_smprintf_free(errStr);
+ errStr = tmp;
+ goto loser;
+ }
+ _this->usesEquiv = PR_TRUE;
+ }
+ }
+ }
+
+ /* Make sure we either have an EquivalentPlatform or all the other info */
+ if (_this->usesEquiv &&
+ (gotFiles || gotModuleFile || gotModuleName || gotMech || gotCipher)) {
+ errStr = PR_smprintf(errString[EQUIV_TOO_MUCH_INFO],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ if (!gotFiles && !_this->usesEquiv) {
+ errStr = PR_smprintf(errString[NO_FILES],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ if (!gotModuleFile && !_this->usesEquiv) {
+ errStr = PR_smprintf(errString[NO_MODULE_FILE],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ if (!gotModuleName && !_this->usesEquiv) {
+ errStr = PR_smprintf(errString[NO_MODULE_NAME],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+
+ /* Point the modFile pointer to the correct file */
+ if (gotModuleFile) {
+ for (i = 0; i < _this->numFiles; i++) {
+ if (!PORT_Strcasecmp(_this->moduleFile, _this->files[i].jarPath)) {
+ _this->modFile = i;
+ break;
+ }
+ }
+ if (_this->modFile == -1) {
+ errStr = PR_smprintf(errString[UNKNOWN_MODULE_FILE],
+ _this->moduleFile,
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ }
+
+loser:
+ if (iter) {
+ PR_Free(iter);
+ }
+ if (subiter) {
+ PR_Free(subiter);
+ }
+ return errStr;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Print
+// Class: Pk11Install_Platform
+*/
+void
+Pk11Install_Platform_Print(Pk11Install_Platform* _this, int pad)
+{
+ int i;
+
+ PAD(pad);
+ printf("Name:\n");
+ Pk11Install_PlatformName_Print(&_this->name, pad + PADINC);
+ PAD(pad);
+ printf("equivName:\n");
+ Pk11Install_PlatformName_Print(&_this->equivName, pad + PADINC);
+ PAD(pad);
+ if (_this->usesEquiv) {
+ printf("Uses equiv, which points to:\n");
+ Pk11Install_Platform_Print(_this->equiv, pad + PADINC);
+ } else {
+ printf("Doesn't use equiv\n");
+ }
+ PAD(pad);
+ printf("Module File: %s\n", _this->moduleFile ? _this->moduleFile
+ : "<NULL>");
+ PAD(pad);
+ printf("mechFlags: %lx\n", _this->mechFlags);
+ PAD(pad);
+ printf("cipherFlags: %lx\n", _this->cipherFlags);
+ PAD(pad);
+ printf("Files:\n");
+ for (i = 0; i < _this->numFiles; i++) {
+ Pk11Install_File_Print(&_this->files[i], pad + PADINC);
+ PAD(pad);
+ printf("--------------------\n");
+ }
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Pk11Install_Info
+// Class: Pk11Install_Info
+*/
+Pk11Install_Info*
+Pk11Install_Info_new()
+{
+ Pk11Install_Info* new_this;
+ new_this = (Pk11Install_Info*)PR_Malloc(sizeof(Pk11Install_Info));
+ Pk11Install_Info_init(new_this);
+ return new_this;
+}
+
+void
+Pk11Install_Info_init(Pk11Install_Info* _this)
+{
+ _this->platforms = NULL;
+ _this->numPlatforms = 0;
+ _this->forwardCompatible = NULL;
+ _this->numForwardCompatible = 0;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: ~Pk11Install_Info
+// Class: Pk11Install_Info
+*/
+void
+Pk11Install_Info_delete(Pk11Install_Info* _this)
+{
+ Pk11Install_Info_Cleanup(_this);
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Cleanup
+// Class: Pk11Install_Info
+*/
+void
+Pk11Install_Info_Cleanup(Pk11Install_Info* _this)
+{
+ int i;
+ if (_this->platforms) {
+ for (i = 0; i < _this->numPlatforms; i++) {
+ Pk11Install_Platform_delete(&_this->platforms[i]);
+ }
+ PR_Free(&_this->platforms);
+ _this->platforms = NULL;
+ _this->numPlatforms = 0;
+ }
+
+ if (_this->forwardCompatible) {
+ for (i = 0; i < _this->numForwardCompatible; i++) {
+ Pk11Install_PlatformName_delete(&_this->forwardCompatible[i]);
+ }
+ PR_Free(&_this->forwardCompatible);
+ _this->numForwardCompatible = 0;
+ }
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Generate
+// Class: Pk11Install_Info
+// Takes: Pk11Install_ValueList *list, the top-level list
+// resulting from parsing an installer file.
+// Returns: char*, NULL if successful, otherwise an error string.
+// Caller is responsible for freeing memory.
+*/
+char*
+Pk11Install_Info_Generate(Pk11Install_Info* _this,
+ const Pk11Install_ValueList* list)
+{
+ char* errStr;
+ Pk11Install_ListIter* iter;
+ Pk11Install_Value* val;
+ Pk11Install_Pair* pair;
+ Pk11Install_ListIter* subiter;
+ Pk11Install_Value* subval;
+ Pk11Install_Platform *first, *second;
+ int i, j;
+
+ errStr = NULL;
+ iter = subiter = NULL;
+ Pk11Install_Info_Cleanup(_this);
+
+ iter = Pk11Install_ListIter_new(list);
+ for (; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) {
+ if (val->type == PAIR_VALUE) {
+ pair = val->pair;
+
+ if (!PORT_Strcasecmp(pair->key, FORWARD_COMPATIBLE_STRING)) {
+ subiter = Pk11Install_ListIter_new(pair->list);
+ _this->numForwardCompatible = pair->list->numStrings;
+ _this->forwardCompatible = (Pk11Install_PlatformName*)
+ PR_Malloc(sizeof(Pk11Install_PlatformName) *
+ _this->numForwardCompatible);
+ for (i = 0; i < _this->numForwardCompatible; i++,
+ Pk11Install_ListIter_nextItem(subiter)) {
+ subval = subiter->current;
+ if (subval->type == STRING_VALUE) {
+ errStr = Pk11Install_PlatformName_Generate(
+ &_this->forwardCompatible[i], subval->string);
+ if (errStr) {
+ goto loser;
+ }
+ }
+ }
+ Pk11Install_ListIter_delete(&subiter);
+ } else if (!PORT_Strcasecmp(pair->key, PLATFORMS_STRING)) {
+ subiter = Pk11Install_ListIter_new(pair->list);
+ _this->numPlatforms = pair->list->numPairs;
+ _this->platforms = (Pk11Install_Platform*)
+ PR_Malloc(sizeof(Pk11Install_Platform) *
+ _this->numPlatforms);
+ for (i = 0; i < _this->numPlatforms; i++,
+ Pk11Install_ListIter_nextItem(subiter)) {
+ Pk11Install_Platform_init(&_this->platforms[i]);
+ subval = subiter->current;
+ if (subval->type == PAIR_VALUE) {
+ errStr = Pk11Install_Platform_Generate(&_this->platforms[i], subval->pair);
+ if (errStr) {
+ goto loser;
+ }
+ }
+ }
+ Pk11Install_ListIter_delete(&subiter);
+ }
+ }
+ }
+
+ if (_this->numPlatforms == 0) {
+ errStr = PR_smprintf(errString[NO_PLATFORMS]);
+ goto loser;
+ }
+
+ /*
+ //
+ // Now process equivalent platforms
+ //
+
+ // First the naive pass
+ */
+ for (i = 0; i < _this->numPlatforms; i++) {
+ if (_this->platforms[i].usesEquiv) {
+ _this->platforms[i].equiv = NULL;
+ for (j = 0; j < _this->numPlatforms; j++) {
+ if (Pk11Install_PlatformName_equal(&_this->platforms[i].equivName,
+ &_this->platforms[j].name)) {
+ if (i == j) {
+ errStr = PR_smprintf(errString[EQUIV_LOOP],
+ Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
+ goto loser;
+ }
+ _this->platforms[i].equiv = &_this->platforms[j];
+ break;
+ }
+ }
+ if (_this->platforms[i].equiv == NULL) {
+ errStr = PR_smprintf(errString[BOGUS_EQUIV],
+ Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
+ goto loser;
+ }
+ }
+ }
+
+ /*
+ // Now the intelligent pass, which will also detect loops.
+ // We will send two pointers through the linked list of equivalent
+ // platforms. Both start with the current node. "first" traverses
+ // two nodes for each iteration. "second" lags behind, only traversing
+ // one node per iteration. Eventually one of two things will happen:
+ // first will hit the end of the list (a platform that doesn't use
+ // an equivalency), or first will equal second if there is a loop.
+ */
+ for (i = 0; i < _this->numPlatforms; i++) {
+ if (_this->platforms[i].usesEquiv) {
+ second = _this->platforms[i].equiv;
+ if (!second->usesEquiv) {
+ /* The first link is the terminal node */
+ continue;
+ }
+ first = second->equiv;
+ while (first->usesEquiv) {
+ if (first == second) {
+ errStr = PR_smprintf(errString[EQUIV_LOOP],
+ Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
+ goto loser;
+ }
+ first = first->equiv;
+ if (!first->usesEquiv) {
+ break;
+ }
+ if (first == second) {
+ errStr = PR_smprintf(errString[EQUIV_LOOP],
+ Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
+ goto loser;
+ }
+ second = second->equiv;
+ first = first->equiv;
+ }
+ _this->platforms[i].equiv = first;
+ }
+ }
+
+loser:
+ if (iter) {
+ Pk11Install_ListIter_delete(&iter);
+ }
+ if (subiter) {
+ Pk11Install_ListIter_delete(&subiter);
+ }
+ return errStr;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: GetBestPlatform
+// Class: Pk11Install_Info
+// Takes: char *myPlatform, the platform we are currently running
+// on.
+*/
+Pk11Install_Platform*
+Pk11Install_Info_GetBestPlatform(Pk11Install_Info* _this, char* myPlatform)
+{
+ Pk11Install_PlatformName plat;
+ char* errStr;
+ int i, j;
+
+ errStr = NULL;
+
+ Pk11Install_PlatformName_init(&plat);
+ if ((errStr = Pk11Install_PlatformName_Generate(&plat, myPlatform))) {
+ PR_smprintf_free(errStr);
+ return NULL;
+ }
+
+ /* First try real platforms */
+ for (i = 0; i < _this->numPlatforms; i++) {
+ if (Pk11Install_PlatformName_equal(&_this->platforms[i].name, &plat)) {
+ if (_this->platforms[i].equiv) {
+ return _this->platforms[i].equiv;
+ } else {
+ return &_this->platforms[i];
+ }
+ }
+ }
+
+ /* Now try forward compatible platforms */
+ for (i = 0; i < _this->numForwardCompatible; i++) {
+ if (Pk11Install_PlatformName_lteq(&_this->forwardCompatible[i], &plat)) {
+ break;
+ }
+ }
+ if (i == _this->numForwardCompatible) {
+ return NULL;
+ }
+
+ /* Got a forward compatible name, find the actual platform. */
+ for (j = 0; j < _this->numPlatforms; j++) {
+ if (Pk11Install_PlatformName_equal(&_this->platforms[j].name,
+ &_this->forwardCompatible[i])) {
+ if (_this->platforms[j].equiv) {
+ return _this->platforms[j].equiv;
+ } else {
+ return &_this->platforms[j];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Print
+// Class: Pk11Install_Info
+*/
+void
+Pk11Install_Info_Print(Pk11Install_Info* _this, int pad)
+{
+ int i;
+
+ PAD(pad);
+ printf("Forward Compatible:\n");
+ for (i = 0; i < _this->numForwardCompatible; i++) {
+ Pk11Install_PlatformName_Print(&_this->forwardCompatible[i], pad + PADINC);
+ PAD(pad);
+ printf("-------------------\n");
+ }
+ PAD(pad);
+ printf("Platforms:\n");
+ for (i = 0; i < _this->numPlatforms; i++) {
+ Pk11Install_Platform_Print(&_this->platforms[i], pad + PADINC);
+ PAD(pad);
+ printf("-------------------\n");
+ }
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+*/
+static char*
+PR_Strdup(const char* str)
+{
+ char* tmp;
+ tmp = (char*)PR_Malloc((unsigned int)(strlen(str) + 1));
+ strcpy(tmp, str);
+ return tmp;
+}
+
+/* The global value list, the top of the tree */
+Pk11Install_ValueList* Pk11Install_valueList = NULL;
+
+/****************************************************************************/
+void
+Pk11Install_ValueList_AddItem(Pk11Install_ValueList* _this,
+ Pk11Install_Value* item)
+{
+ _this->numItems++;
+ if (item->type == STRING_VALUE) {
+ _this->numStrings++;
+ } else {
+ _this->numPairs++;
+ }
+ item->next = _this->head;
+ _this->head = item;
+}
+
+/****************************************************************************/
+Pk11Install_ListIter*
+Pk11Install_ListIter_new_default()
+{
+ Pk11Install_ListIter* new_this;
+ new_this = (Pk11Install_ListIter*)
+ PR_Malloc(sizeof(Pk11Install_ListIter));
+ Pk11Install_ListIter_init(new_this);
+ return new_this;
+}
+
+/****************************************************************************/
+void
+Pk11Install_ListIter_init(Pk11Install_ListIter* _this)
+{
+ _this->list = NULL;
+ _this->current = NULL;
+}
+
+/****************************************************************************/
+Pk11Install_ListIter*
+Pk11Install_ListIter_new(const Pk11Install_ValueList* _list)
+{
+ Pk11Install_ListIter* new_this;
+ new_this = (Pk11Install_ListIter*)
+ PR_Malloc(sizeof(Pk11Install_ListIter));
+ new_this->list = _list;
+ new_this->current = _list->head;
+ return new_this;
+}
+
+/****************************************************************************/
+void
+Pk11Install_ListIter_delete(Pk11Install_ListIter** _this)
+{
+ (*_this)->list = NULL;
+ (*_this)->current = NULL;
+ PR_Free(*_this);
+ *_this = NULL;
+}
+
+/****************************************************************************/
+void
+Pk11Install_ListIter_reset(Pk11Install_ListIter* _this)
+{
+ if (_this->list) {
+ _this->current = _this->list->head;
+ }
+}
+
+/*************************************************************************/
+Pk11Install_Value*
+Pk11Install_ListIter_nextItem(Pk11Install_ListIter* _this)
+{
+ if (_this->current) {
+ _this->current = _this->current->next;
+ }
+
+ return _this->current;
+}
+
+/****************************************************************************/
+Pk11Install_ValueList*
+Pk11Install_ValueList_new()
+{
+ Pk11Install_ValueList* new_this;
+ new_this = (Pk11Install_ValueList*)
+ PR_Malloc(sizeof(Pk11Install_ValueList));
+ new_this->numItems = 0;
+ new_this->numPairs = 0;
+ new_this->numStrings = 0;
+ new_this->head = NULL;
+ return new_this;
+}
+
+/****************************************************************************/
+void
+Pk11Install_ValueList_delete(Pk11Install_ValueList* _this)
+{
+
+ Pk11Install_Value* tmp;
+ Pk11Install_Value* list;
+ list = _this->head;
+
+ while (list != NULL) {
+ tmp = list;
+ list = list->next;
+ PR_Free(tmp);
+ }
+ PR_Free(_this);
+}
+
+/****************************************************************************/
+Pk11Install_Value*
+Pk11Install_Value_new_default()
+{
+ Pk11Install_Value* new_this;
+ new_this = (Pk11Install_Value*)PR_Malloc(sizeof(Pk11Install_Value));
+ new_this->type = STRING_VALUE;
+ new_this->string = NULL;
+ new_this->pair = NULL;
+ new_this->next = NULL;
+ return new_this;
+}
+
+/****************************************************************************/
+Pk11Install_Value*
+Pk11Install_Value_new(ValueType _type, Pk11Install_Pointer ptr)
+{
+ Pk11Install_Value* new_this;
+ new_this = Pk11Install_Value_new_default();
+ new_this->type = _type;
+ if (_type == STRING_VALUE) {
+ new_this->pair = NULL;
+ new_this->string = ptr.string;
+ } else {
+ new_this->string = NULL;
+ new_this->pair = ptr.pair;
+ }
+ return new_this;
+}
+
+/****************************************************************************/
+void
+Pk11Install_Value_delete(Pk11Install_Value* _this)
+{
+ if (_this->type == STRING_VALUE) {
+ PR_Free(_this->string);
+ } else {
+ PR_Free(_this->pair);
+ }
+}
+
+/****************************************************************************/
+Pk11Install_Pair*
+Pk11Install_Pair_new_default()
+{
+ return Pk11Install_Pair_new(NULL, NULL);
+}
+
+/****************************************************************************/
+Pk11Install_Pair*
+Pk11Install_Pair_new(char* _key, Pk11Install_ValueList* _list)
+{
+ Pk11Install_Pair* new_this;
+ new_this = (Pk11Install_Pair*)PR_Malloc(sizeof(Pk11Install_Pair));
+ new_this->key = _key;
+ new_this->list = _list;
+ return new_this;
+}
+
+/****************************************************************************/
+void
+Pk11Install_Pair_delete(Pk11Install_Pair* _this)
+{
+ PR_Free(_this->key);
+ Pk11Install_ValueList_delete(_this->list);
+}
+
+/*************************************************************************/
+void
+Pk11Install_Pair_Print(Pk11Install_Pair* _this, int pad)
+{
+ while (_this) {
+ /*PAD(pad); printf("**Pair\n");
+ PAD(pad); printf("***Key====\n");*/
+ PAD(pad);
+ printf("%s {\n", _this->key);
+ /*PAD(pad); printf("====\n");*/
+ /*PAD(pad); printf("***ValueList\n");*/
+ Pk11Install_ValueList_Print(_this->list, pad + PADINC);
+ PAD(pad);
+ printf("}\n");
+ }
+}
+
+/*************************************************************************/
+void
+Pk11Install_ValueList_Print(Pk11Install_ValueList* _this, int pad)
+{
+ Pk11Install_Value* v;
+
+ /*PAD(pad);printf("**Value List**\n");*/
+ for (v = _this->head; v != NULL; v = v->next) {
+ Pk11Install_Value_Print(v, pad);
+ }
+}
+
+/*************************************************************************/
+void
+Pk11Install_Value_Print(Pk11Install_Value* _this, int pad)
+{
+ /*PAD(pad); printf("**Value, type=%s\n",
+ type==STRING_VALUE ? "string" : "pair");*/
+ if (_this->type == STRING_VALUE) {
+ /*PAD(pad+PADINC); printf("====\n");*/
+ PAD(pad);
+ printf("%s\n", _this->string);
+ /*PAD(pad+PADINC); printf("====\n");*/
+ } else {
+ Pk11Install_Pair_Print(_this->pair, pad + PADINC);
+ }
+}
diff --git a/security/nss/cmd/modutil/install-ds.h b/security/nss/cmd/modutil/install-ds.h
new file mode 100644
index 000000000..70813f603
--- /dev/null
+++ b/security/nss/cmd/modutil/install-ds.h
@@ -0,0 +1,260 @@
+/* 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 INSTALL_DS_H
+#define INSTALL_DS_H
+
+#include <stdio.h>
+#include <prio.h>
+#include <prmem.h>
+
+extern PRFileDesc* Pk11Install_FD;
+extern int Pk11Install_yylex();
+extern int Pk11Install_yylinenum;
+extern char* Pk11Install_yyerrstr;
+
+typedef enum { STRING_VALUE,
+ PAIR_VALUE } ValueType;
+
+typedef struct Pk11Install_Pair_str Pk11Install_Pair;
+typedef union Pk11Install_Pointer_str Pk11Install_Pointer;
+typedef struct Pk11Install_Value_str Pk11Install_Value;
+typedef struct Pk11Install_ValueList_str Pk11Install_ValueList;
+typedef struct Pk11Install_ListIter_str Pk11Install_ListIter;
+typedef struct Pk11Install_File_str Pk11Install_File;
+typedef struct Pk11Install_PlatformName_str Pk11Install_PlatformName;
+typedef struct Pk11Install_Platform_str Pk11Install_Platform;
+typedef struct Pk11Install_Info_str Pk11Install_Info;
+
+extern Pk11Install_Pointer Pk11Install_yylval;
+extern Pk11Install_ValueList* Pk11Install_valueList;
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Pk11Install_Pair
+//////////////////////////////////////////////////////////////////////////
+*/
+
+struct Pk11Install_Pair_str {
+ char* key;
+ Pk11Install_ValueList* list;
+};
+
+Pk11Install_Pair*
+Pk11Install_Pair_new_default();
+Pk11Install_Pair*
+Pk11Install_Pair_new(char* _key, Pk11Install_ValueList* _list);
+void
+Pk11Install_Pair_delete(Pk11Install_Pair* _this);
+void
+Pk11Install_Pair_Print(Pk11Install_Pair* _this, int pad);
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Pk11Install_Pointer
+//////////////////////////////////////////////////////////////////////////
+*/
+union Pk11Install_Pointer_str {
+ Pk11Install_ValueList* list;
+ Pk11Install_Value* value;
+ Pk11Install_Pair* pair;
+ char* string;
+};
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Pk11Install_Value
+//////////////////////////////////////////////////////////////////////////
+*/
+struct Pk11Install_Value_str {
+
+ ValueType type;
+ char* string;
+ Pk11Install_Pair* pair;
+ struct Pk11Install_Value_str* next;
+};
+
+Pk11Install_Value*
+Pk11Install_Value_new_default();
+Pk11Install_Value*
+Pk11Install_Value_new(ValueType _type, Pk11Install_Pointer ptr);
+void
+Pk11Install_Value_delete(Pk11Install_Value* _this);
+void
+Pk11Install_Value_Print(Pk11Install_Value* _this, int pad);
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Pk11Install_ValueList
+//////////////////////////////////////////////////////////////////////////
+*/
+struct Pk11Install_ValueList_str {
+ int numItems;
+ int numPairs;
+ int numStrings;
+ Pk11Install_Value* head;
+};
+
+Pk11Install_ValueList*
+Pk11Install_ValueList_new();
+void
+Pk11Install_ValueList_delete(Pk11Install_ValueList* _this);
+void
+Pk11Install_ValueList_AddItem(Pk11Install_ValueList* _this,
+ Pk11Install_Value* item);
+void
+Pk11Install_ValueList_Print(Pk11Install_ValueList* _this, int pad);
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Pk11Install_ListIter
+//////////////////////////////////////////////////////////////////////////
+*/
+struct Pk11Install_ListIter_str {
+ const Pk11Install_ValueList* list;
+ Pk11Install_Value* current;
+};
+
+Pk11Install_ListIter*
+Pk11Install_ListIter_new_default();
+void
+Pk11Install_ListIter_init(Pk11Install_ListIter* _this);
+Pk11Install_ListIter*
+Pk11Install_ListIter_new(const Pk11Install_ValueList* _list);
+void
+Pk11Install_ListIter_delete(Pk11Install_ListIter** _this);
+void
+Pk11Install_ListIter_reset(Pk11Install_ListIter* _this);
+Pk11Install_Value*
+Pk11Install_ListIter_nextItem(Pk11Install_ListIter* _this);
+
+/************************************************************************
+ *
+ * Pk11Install_File
+ */
+struct Pk11Install_File_str {
+ char* jarPath;
+ char* relativePath;
+ char* absolutePath;
+ PRBool executable;
+ int permissions;
+};
+
+Pk11Install_File*
+Pk11Install_File_new();
+void
+Pk11Install_File_init(Pk11Install_File* _this);
+void
+Pk11Install_file_delete(Pk11Install_File* _this);
+/*// Parses a syntax tree to obtain all attributes.
+// Returns NULL for success, error message if parse error.*/
+char*
+Pk11Install_File_Generate(Pk11Install_File* _this,
+ const Pk11Install_Pair* pair);
+void
+Pk11Install_File_Print(Pk11Install_File* _this, int pad);
+void
+Pk11Install_File_Cleanup(Pk11Install_File* _this);
+
+/************************************************************************
+ *
+ * Pk11Install_PlatformName
+ */
+struct Pk11Install_PlatformName_str {
+ char* OS;
+ char** verString;
+ int numDigits;
+ char* arch;
+};
+
+Pk11Install_PlatformName*
+Pk11Install_PlatformName_new();
+void
+Pk11Install_PlatformName_init(Pk11Install_PlatformName* _this);
+void
+Pk11Install_PlatformName_delete(Pk11Install_PlatformName* _this);
+char*
+Pk11Install_PlatformName_Generate(Pk11Install_PlatformName* _this,
+ const char* str);
+char*
+Pk11Install_PlatformName_GetString(Pk11Install_PlatformName* _this);
+char*
+Pk11Install_PlatformName_GetVerString(Pk11Install_PlatformName* _this);
+void
+Pk11Install_PlatformName_Print(Pk11Install_PlatformName* _this, int pad);
+void
+Pk11Install_PlatformName_Cleanup(Pk11Install_PlatformName* _this);
+PRBool
+Pk11Install_PlatformName_equal(Pk11Install_PlatformName* _this,
+ Pk11Install_PlatformName* cmp);
+PRBool
+Pk11Install_PlatformName_lteq(Pk11Install_PlatformName* _this,
+ Pk11Install_PlatformName* cmp);
+PRBool
+Pk11Install_PlatformName_lt(Pk11Install_PlatformName* _this,
+ Pk11Install_PlatformName* cmp);
+
+/************************************************************************
+ *
+ * Pk11Install_Platform
+ */
+struct Pk11Install_Platform_str {
+ Pk11Install_PlatformName name;
+ Pk11Install_PlatformName equivName;
+ struct Pk11Install_Platform_str* equiv;
+ PRBool usesEquiv;
+ char* moduleFile;
+ char* moduleName;
+ int modFile;
+ unsigned long mechFlags;
+ unsigned long cipherFlags;
+ Pk11Install_File* files;
+ int numFiles;
+};
+
+Pk11Install_Platform*
+Pk11Install_Platform_new();
+void
+Pk11Install_Platform_init(Pk11Install_Platform* _this);
+void
+Pk11Install_Platform_delete(Pk11Install_Platform* _this);
+/*// Returns NULL for success, error message if parse error.*/
+char*
+Pk11Install_Platform_Generate(Pk11Install_Platform* _this,
+ const Pk11Install_Pair* pair);
+void
+Pk11Install_Platform_Print(Pk11Install_Platform* _this, int pad);
+void
+Pk11Install_Platform_Cleanup(Pk11Install_Platform* _this);
+
+/************************************************************************
+ *
+ * Pk11Install_Info
+ */
+struct Pk11Install_Info_str {
+ Pk11Install_Platform* platforms;
+ int numPlatforms;
+ Pk11Install_PlatformName* forwardCompatible;
+ int numForwardCompatible;
+};
+
+Pk11Install_Info*
+Pk11Install_Info_new();
+void
+Pk11Install_Info_init(Pk11Install_Info* _this);
+void
+Pk11Install_Info_delete(Pk11Install_Info* _this);
+/*// Returns NULL for success, error message if parse error.*/
+char*
+Pk11Install_Info_Generate(Pk11Install_Info* _this,
+ const Pk11Install_ValueList* list);
+/*// Returns NULL if there is no matching platform*/
+Pk11Install_Platform*
+Pk11Install_Info_GetBestPlatform(Pk11Install_Info* _this, char* myPlatform);
+void
+Pk11Install_Info_Print(Pk11Install_Info* _this, int pad);
+void
+Pk11Install_Info_Cleanup(Pk11Install_Info* _this);
+
+#endif /* INSTALL_DS_H */
diff --git a/security/nss/cmd/modutil/install.c b/security/nss/cmd/modutil/install.c
new file mode 100644
index 000000000..ea4aeb77c
--- /dev/null
+++ b/security/nss/cmd/modutil/install.c
@@ -0,0 +1,959 @@
+/* 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/. */
+
+#include "install.h"
+#include "install-ds.h"
+#include <prerror.h>
+#include <prlock.h>
+#include <prio.h>
+#include <prmem.h>
+#include <prprf.h>
+#include <prsystem.h>
+#include <prproces.h>
+
+#ifdef XP_UNIX
+/* for chmod */
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+/*extern "C" {*/
+#include <jar.h>
+/*}*/
+
+extern /*"C"*/
+ int
+ Pk11Install_AddNewModule(char *moduleName, char *dllPath,
+ unsigned long defaultMechanismFlags,
+ unsigned long cipherEnableFlags);
+extern /*"C"*/
+ short
+ Pk11Install_UserVerifyJar(JAR *jar, PRFileDesc *out,
+ PRBool query);
+extern /*"C"*/
+ const char *
+ mySECU_ErrorString(PRErrorCode errnum);
+extern int Pk11Install_yyparse();
+
+#define INSTALL_METAINFO_TAG "Pkcs11_install_script"
+#define SCRIPT_TEMP_FILE "pkcs11inst.tmp"
+#define ROOT_MARKER "%root%"
+#define TEMP_MARKER "%temp%"
+#define PRINTF_ROOT_MARKER "%%root%%"
+#define TEMPORARY_DIRECTORY_NAME "pk11inst.dir"
+#define JAR_BASE_END (JAR_BASE + 100)
+
+static PRLock *errorHandlerLock = NULL;
+static Pk11Install_ErrorHandler errorHandler = NULL;
+static char *PR_Strdup(const char *str);
+static int rm_dash_r(char *path);
+static int make_dirs(char *path, int file_perms);
+static int dir_perms(int perms);
+
+static Pk11Install_Error DoInstall(JAR *jar, const char *installDir,
+ const char *tempDir, Pk11Install_Platform *platform,
+ PRFileDesc *feedback, PRBool noverify);
+
+static char *errorString[] = {
+ "Operation was successful", /* PK11_INSTALL_NO_ERROR */
+ "Directory \"%s\" does not exist", /* PK11_INSTALL_DIR_DOESNT_EXIST */
+ "File \"%s\" does not exist", /* PK11_INSTALL_FILE_DOESNT_EXIST */
+ "File \"%s\" is not readable", /* PK11_INSTALL_FILE_NOT_READABLE */
+ "%s", /* PK11_INSTALL_ERROR_STRING */
+ "Error in JAR file %s: %s", /* PK11_INSTALL_JAR_ERROR */
+ "No Pkcs11_install_script specified in JAR metainfo file",
+ /* PK11_INSTALL_NO_INSTALLER_SCRIPT */
+ "Could not delete temporary file \"%s\"",
+ /*PK11_INSTALL_DELETE_TEMP_FILE */
+ "Could not open temporary file \"%s\"", /*PK11_INSTALL_OPEN_SCRIPT_FILE*/
+ "%s: %s", /* PK11_INSTALL_SCRIPT_PARSE */
+ "Error in script: %s",
+ "Unable to obtain system platform information",
+ "Installer script has no information about the current platform (%s)",
+ "Relative directory \"%s\" does not contain " PRINTF_ROOT_MARKER,
+ "Module File \"%s\" not found",
+ "Error occurred installing module \"%s\" into database",
+ "Error extracting \"%s\" from JAR file: %s",
+ "Directory \"%s\" is not writeable",
+ "Could not create directory \"%s\"",
+ "Could not remove directory \"%s\"",
+ "Unable to execute \"%s\"",
+ "Unable to wait for process \"%s\"",
+ "\"%s\" returned error code %d",
+ "User aborted operation",
+ "Unspecified error"
+};
+
+enum {
+ INSTALLED_FILE_MSG = 0,
+ INSTALLED_MODULE_MSG,
+ INSTALLER_SCRIPT_NAME,
+ MY_PLATFORM_IS,
+ USING_PLATFORM,
+ PARSED_INSTALL_SCRIPT,
+ EXEC_FILE_MSG,
+ EXEC_SUCCESS,
+ INSTALLATION_COMPLETE_MSG,
+ USER_ABORT
+};
+
+static char *msgStrings[] = {
+ "Installed file %s to %s\n",
+ "Installed module \"%s\" into module database\n",
+ "Using installer script \"%s\"\n",
+ "Current platform is %s\n",
+ "Using installation parameters for platform %s\n",
+ "Successfully parsed installation script\n",
+ "Executing \"%s\"...\n",
+ "\"%s\" executed successfully\n",
+ "\nInstallation completed successfully\n",
+ "\nAborting...\n"
+};
+
+/**************************************************************************
+ * S t r i n g N o d e
+ */
+typedef struct StringNode_str {
+ char *str;
+ struct StringNode_str *next;
+} StringNode;
+
+StringNode *
+StringNode_new()
+{
+ StringNode *new_this;
+ new_this = (StringNode *)PR_Malloc(sizeof(StringNode));
+ PORT_Assert(new_this != NULL);
+ new_this->str = NULL;
+ new_this->next = NULL;
+ return new_this;
+}
+
+void
+StringNode_delete(StringNode *s)
+{
+ if (s->str) {
+ PR_Free(s->str);
+ s->str = NULL;
+ }
+}
+
+/*************************************************************************
+ * S t r i n g L i s t
+ */
+typedef struct StringList_str {
+ StringNode *head;
+ StringNode *tail;
+} StringList;
+
+void
+StringList_new(StringList *list)
+{
+ list->head = NULL;
+ list->tail = NULL;
+}
+
+void
+StringList_delete(StringList *list)
+{
+ StringNode *tmp;
+ while (list->head) {
+ tmp = list->head;
+ list->head = list->head->next;
+ StringNode_delete(tmp);
+ }
+}
+
+void
+StringList_Append(StringList *list, char *str)
+{
+ if (!str) {
+ return;
+ }
+
+ if (!list->tail) {
+ /* This is the first element */
+ list->head = list->tail = StringNode_new();
+ } else {
+ list->tail->next = StringNode_new();
+ list->tail = list->tail->next;
+ }
+
+ list->tail->str = PR_Strdup(str);
+ list->tail->next = NULL; /* just to be sure */
+}
+
+/**************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ S e t E r r o r H a n d l e r
+ *
+ * Sets the error handler to be used by the library. Returns the current
+ * error handler function.
+ */
+Pk11Install_ErrorHandler
+Pk11Install_SetErrorHandler(Pk11Install_ErrorHandler handler)
+{
+ Pk11Install_ErrorHandler old;
+
+ if (!errorHandlerLock) {
+ errorHandlerLock = PR_NewLock();
+ }
+
+ PR_Lock(errorHandlerLock);
+
+ old = errorHandler;
+ errorHandler = handler;
+
+ PR_Unlock(errorHandlerLock);
+
+ return old;
+}
+
+/**************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ I n i t
+ *
+ * Does initialization that otherwise would be done on the fly. Only
+ * needs to be called by multithreaded apps, before they make any calls
+ * to this library.
+ */
+void
+Pk11Install_Init()
+{
+ if (!errorHandlerLock) {
+ errorHandlerLock = PR_NewLock();
+ }
+}
+
+/**************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ R e l e a s e
+ *
+ * Releases static data structures used by the library. Don't use the
+ * library after calling this, unless you call Pk11Install_Init()
+ * first. This function doesn't have to be called at all unless you're
+ * really anal about freeing memory before your program exits.
+ */
+void
+Pk11Install_Release()
+{
+ if (errorHandlerLock) {
+ PR_Free(errorHandlerLock);
+ errorHandlerLock = NULL;
+ }
+}
+
+/*************************************************************************
+ *
+ * e r r o r
+ *
+ * Takes an error code and its arguments, creates the error string,
+ * and sends the string to the handler function if it exists.
+ */
+
+#ifdef OSF1
+/* stdarg has already been pulled in from NSPR */
+#undef va_start
+#undef va_end
+#undef va_arg
+#include <varargs.h>
+#else
+#include <stdarg.h>
+#endif
+
+#ifdef OSF1
+static void
+error(long va_alist, ...)
+#else
+static void
+error(PRErrorCode errcode, ...)
+#endif
+{
+
+ va_list ap;
+ char *errstr;
+ Pk11Install_ErrorHandler handler;
+
+ if (!errorHandlerLock) {
+ errorHandlerLock = PR_NewLock();
+ }
+
+ PR_Lock(errorHandlerLock);
+
+ handler = errorHandler;
+
+ PR_Unlock(errorHandlerLock);
+
+ if (handler) {
+#ifdef OSF1
+ va_start(ap);
+ errstr = PR_vsmprintf(errorString[va_arg(ap, Pk11Install_Error)], ap);
+#else
+ va_start(ap, errcode);
+ errstr = PR_vsmprintf(errorString[errcode], ap);
+#endif
+ handler(errstr);
+ PR_smprintf_free(errstr);
+ va_end(ap);
+ }
+}
+
+/*************************************************************************
+ *
+ * j a r _ c a l l b a c k
+ */
+static int
+jar_callback(int status, JAR *foo, const char *bar, char *pathname,
+ char *errortext)
+{
+ char *string;
+
+ string = PR_smprintf("JAR error %d: %s in file %s\n", status, errortext,
+ pathname);
+ error(PK11_INSTALL_ERROR_STRING, string);
+ PR_smprintf_free(string);
+ return 0;
+}
+
+/*************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ D o I n s t a l l
+ *
+ * jarFile is the path of a JAR in the PKCS #11 module JAR format.
+ * installDir is the directory relative to which files will be
+ * installed.
+ */
+Pk11Install_Error
+Pk11Install_DoInstall(char *jarFile, const char *installDir,
+ const char *tempDir, PRFileDesc *feedback, short force, PRBool noverify)
+{
+ JAR *jar;
+ char *installer;
+ unsigned long installer_len;
+ int status;
+ Pk11Install_Error ret;
+ PRBool made_temp_file;
+ Pk11Install_Info installInfo;
+ Pk11Install_Platform *platform;
+ char *errMsg;
+ char sysname[SYS_INFO_BUFFER_LENGTH], release[SYS_INFO_BUFFER_LENGTH],
+ arch[SYS_INFO_BUFFER_LENGTH];
+ char *myPlatform;
+
+ jar = NULL;
+ ret = PK11_INSTALL_UNSPECIFIED;
+ made_temp_file = PR_FALSE;
+ errMsg = NULL;
+ Pk11Install_Info_init(&installInfo);
+
+ /*
+ printf("Inside DoInstall, jarFile=%s, installDir=%s, tempDir=%s\n",
+ jarFile, installDir, tempDir);
+ */
+
+ /*
+ * Check out jarFile and installDir for validity
+ */
+ if (PR_Access(installDir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
+ error(PK11_INSTALL_DIR_DOESNT_EXIST, installDir);
+ return PK11_INSTALL_DIR_DOESNT_EXIST;
+ }
+ if (!tempDir) {
+ tempDir = ".";
+ }
+ if (PR_Access(tempDir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
+ error(PK11_INSTALL_DIR_DOESNT_EXIST, tempDir);
+ return PK11_INSTALL_DIR_DOESNT_EXIST;
+ }
+ if (PR_Access(tempDir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
+ error(PK11_INSTALL_DIR_NOT_WRITEABLE, tempDir);
+ return PK11_INSTALL_DIR_NOT_WRITEABLE;
+ }
+ if ((PR_Access(jarFile, PR_ACCESS_EXISTS) != PR_SUCCESS)) {
+ error(PK11_INSTALL_FILE_DOESNT_EXIST, jarFile);
+ return PK11_INSTALL_FILE_DOESNT_EXIST;
+ }
+ if (PR_Access(jarFile, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ error(PK11_INSTALL_FILE_NOT_READABLE, jarFile);
+ return PK11_INSTALL_FILE_NOT_READABLE;
+ }
+
+ /*
+ * Extract the JAR file
+ */
+ jar = JAR_new();
+ JAR_set_callback(JAR_CB_SIGNAL, jar, jar_callback);
+
+ if (noverify) {
+ status = JAR_pass_archive_unverified(jar, jarArchGuess, jarFile, "url");
+ } else {
+ status = JAR_pass_archive(jar, jarArchGuess, jarFile, "url");
+ }
+ if ((status < 0) || (jar->valid < 0)) {
+ if (status >= JAR_BASE && status <= JAR_BASE_END) {
+ error(PK11_INSTALL_JAR_ERROR, jarFile, JAR_get_error(status));
+ } else {
+ error(PK11_INSTALL_JAR_ERROR, jarFile,
+ mySECU_ErrorString(PORT_GetError()));
+ }
+ ret = PK11_INSTALL_JAR_ERROR;
+ goto loser;
+ }
+ /*printf("passed the archive\n");*/
+
+ /*
+ * Show the user security information, allow them to abort or continue
+ */
+ if (Pk11Install_UserVerifyJar(jar, PR_STDOUT,
+ force ? PR_FALSE
+ : PR_TRUE) &&
+ !force) {
+ if (feedback) {
+ PR_fprintf(feedback, msgStrings[USER_ABORT]);
+ }
+ ret = PK11_INSTALL_USER_ABORT;
+ goto loser;
+ }
+
+ /*
+ * Get the name of the installation file
+ */
+ if (JAR_get_metainfo(jar, NULL, INSTALL_METAINFO_TAG, (void **)&installer,
+ (unsigned long *)&installer_len)) {
+ error(PK11_INSTALL_NO_INSTALLER_SCRIPT);
+ ret = PK11_INSTALL_NO_INSTALLER_SCRIPT;
+ goto loser;
+ }
+ if (feedback) {
+ PR_fprintf(feedback, msgStrings[INSTALLER_SCRIPT_NAME], installer);
+ }
+
+ /*
+ * Extract the installation file
+ */
+ if (PR_Access(SCRIPT_TEMP_FILE, PR_ACCESS_EXISTS) == PR_SUCCESS) {
+ if (PR_Delete(SCRIPT_TEMP_FILE) != PR_SUCCESS) {
+ error(PK11_INSTALL_DELETE_TEMP_FILE, SCRIPT_TEMP_FILE);
+ ret = PK11_INSTALL_DELETE_TEMP_FILE;
+ goto loser;
+ }
+ }
+ if (noverify) {
+ status = JAR_extract(jar, installer, SCRIPT_TEMP_FILE);
+ } else {
+ status = JAR_verified_extract(jar, installer, SCRIPT_TEMP_FILE);
+ }
+ if (status) {
+ if (status >= JAR_BASE && status <= JAR_BASE_END) {
+ error(PK11_INSTALL_JAR_EXTRACT, installer, JAR_get_error(status));
+ } else {
+ error(PK11_INSTALL_JAR_EXTRACT, installer,
+ mySECU_ErrorString(PORT_GetError()));
+ }
+ ret = PK11_INSTALL_JAR_EXTRACT;
+ goto loser;
+ } else {
+ made_temp_file = PR_TRUE;
+ }
+
+ /*
+ * Parse the installation file into a syntax tree
+ */
+ Pk11Install_FD = PR_Open(SCRIPT_TEMP_FILE, PR_RDONLY, 0);
+ if (!Pk11Install_FD) {
+ error(PK11_INSTALL_OPEN_SCRIPT_FILE, SCRIPT_TEMP_FILE);
+ ret = PK11_INSTALL_OPEN_SCRIPT_FILE;
+ goto loser;
+ }
+ if (Pk11Install_yyparse()) {
+ error(PK11_INSTALL_SCRIPT_PARSE, installer,
+ Pk11Install_yyerrstr ? Pk11Install_yyerrstr : "");
+ ret = PK11_INSTALL_SCRIPT_PARSE;
+ goto loser;
+ }
+
+#if 0
+ /* for debugging */
+ Pk11Install_valueList->Print(0);
+#endif
+
+ /*
+ * From the syntax tree, build a semantic structure
+ */
+ errMsg = Pk11Install_Info_Generate(&installInfo, Pk11Install_valueList);
+ if (errMsg) {
+ error(PK11_INSTALL_SEMANTIC, errMsg);
+ ret = PK11_INSTALL_SEMANTIC;
+ goto loser;
+ }
+#if 0
+ installInfo.Print(0);
+#endif
+
+ if (feedback) {
+ PR_fprintf(feedback, msgStrings[PARSED_INSTALL_SCRIPT]);
+ }
+
+ /*
+ * Figure out which platform to use
+ */
+ {
+ sysname[0] = release[0] = arch[0] = '\0';
+
+ if ((PR_GetSystemInfo(PR_SI_SYSNAME, sysname, SYS_INFO_BUFFER_LENGTH) !=
+ PR_SUCCESS) ||
+ (PR_GetSystemInfo(PR_SI_RELEASE, release, SYS_INFO_BUFFER_LENGTH) !=
+ PR_SUCCESS) ||
+ (PR_GetSystemInfo(PR_SI_ARCHITECTURE, arch, SYS_INFO_BUFFER_LENGTH) !=
+ PR_SUCCESS)) {
+ error(PK11_INSTALL_SYSINFO);
+ ret = PK11_INSTALL_SYSINFO;
+ goto loser;
+ }
+ myPlatform = PR_smprintf("%s:%s:%s", sysname, release, arch);
+ platform = Pk11Install_Info_GetBestPlatform(&installInfo, myPlatform);
+ if (!platform) {
+ error(PK11_INSTALL_NO_PLATFORM, myPlatform);
+ PR_smprintf_free(myPlatform);
+ ret = PK11_INSTALL_NO_PLATFORM;
+ goto loser;
+ }
+ if (feedback) {
+ PR_fprintf(feedback, msgStrings[MY_PLATFORM_IS], myPlatform);
+ PR_fprintf(feedback, msgStrings[USING_PLATFORM],
+ Pk11Install_PlatformName_GetString(&platform->name));
+ }
+ PR_smprintf_free(myPlatform);
+ }
+
+ /* Run the install for that platform */
+ ret = DoInstall(jar, installDir, tempDir, platform, feedback, noverify);
+ if (ret) {
+ goto loser;
+ }
+
+ ret = PK11_INSTALL_SUCCESS;
+loser:
+ if (Pk11Install_valueList) {
+ Pk11Install_ValueList_delete(Pk11Install_valueList);
+ Pk11Install_valueList = NULL;
+ }
+ if (jar) {
+ JAR_destroy(jar);
+ }
+ if (made_temp_file) {
+ PR_Delete(SCRIPT_TEMP_FILE);
+ }
+ if (errMsg) {
+ PR_smprintf_free(errMsg);
+ }
+ return ret;
+}
+
+/*
+/////////////////////////////////////////////////////////////////////////
+// actually run the installation, copying files to and fro
+*/
+static Pk11Install_Error
+DoInstall(JAR *jar, const char *installDir, const char *tempDir,
+ Pk11Install_Platform *platform, PRFileDesc *feedback, PRBool noverify)
+{
+ Pk11Install_File *file;
+ Pk11Install_Error ret;
+ char *modDest;
+ char *cp;
+ int i;
+ int status;
+ char *tempname, *temp;
+ StringList executables;
+ StringNode *execNode;
+ PRProcessAttr *attr;
+ PRProcess *proc;
+ char *argv[2];
+ char *envp[1];
+ int errcode;
+
+ ret = PK11_INSTALL_UNSPECIFIED;
+ modDest = NULL;
+ tempname = NULL;
+
+ StringList_new(&executables);
+ /*
+ // Create Temporary directory
+ */
+ tempname = PR_smprintf("%s/%s", tempDir, TEMPORARY_DIRECTORY_NAME);
+ if (PR_Access(tempname, PR_ACCESS_EXISTS) == PR_SUCCESS) {
+ /* Left over from previous run? Delete it. */
+ rm_dash_r(tempname);
+ }
+ if (PR_MkDir(tempname, 0700) != PR_SUCCESS) {
+ error(PK11_INSTALL_CREATE_DIR, tempname);
+ ret = PK11_INSTALL_CREATE_DIR;
+ goto loser;
+ }
+
+ /*
+ // Install all the files
+ */
+ for (i = 0; i < platform->numFiles; i++) {
+ char *dest;
+ file = &platform->files[i];
+
+ if (file->relativePath) {
+ PRBool foundMarker = PR_FALSE;
+ char *reldir = PR_Strdup(file->relativePath);
+
+ if (!reldir) {
+ error(PK11_INSTALL_UNSPECIFIED);
+ goto loser;
+ }
+
+ /* Replace all the markers with the directories for which they stand */
+ while (1) {
+ if ((cp = PL_strcasestr(reldir, ROOT_MARKER))) {
+ /* Has a %root% marker */
+ *cp = '\0';
+ temp = PR_smprintf("%s%s%s", reldir, installDir,
+ cp + strlen(ROOT_MARKER));
+ PR_Free(reldir);
+ reldir = temp;
+ foundMarker = PR_TRUE;
+ } else if ((cp = PL_strcasestr(reldir, TEMP_MARKER))) {
+ /* Has a %temp% marker */
+ *cp = '\0';
+ temp = PR_smprintf("%s%s%s", reldir, tempname,
+ cp + strlen(TEMP_MARKER));
+ PR_Free(reldir);
+ reldir = temp;
+ foundMarker = PR_TRUE;
+ } else {
+ break;
+ }
+ }
+ if (!foundMarker) {
+ /* Has no markers...this isn't really a relative directory */
+ error(PK11_INSTALL_BOGUS_REL_DIR, file->relativePath);
+ ret = PK11_INSTALL_BOGUS_REL_DIR;
+ PR_Free(reldir);
+ goto loser;
+ }
+ dest = reldir;
+ } else if (file->absolutePath) {
+ dest = PR_Strdup(file->absolutePath);
+ } else {
+ error(PK11_INSTALL_UNSPECIFIED);
+ goto loser;
+ }
+
+ /* Remember if this is the module file, we'll need to add it later */
+ if (i == platform->modFile) {
+ modDest = PR_Strdup(dest);
+ }
+
+ /* Remember is this is an executable, we'll need to run it later */
+ if (file->executable) {
+ StringList_Append(&executables, dest);
+ /*executables.Append(dest);*/
+ }
+
+ /* Make sure the directory we are targetting exists */
+ if (make_dirs(dest, file->permissions)) {
+ ret = PK11_INSTALL_CREATE_DIR;
+ goto loser;
+ }
+
+ /* Actually extract the file onto the filesystem */
+ if (noverify) {
+ status = JAR_extract(jar, (char *)file->jarPath, dest);
+ } else {
+ status = JAR_verified_extract(jar, (char *)file->jarPath, dest);
+ }
+ if (status) {
+ if (status >= JAR_BASE && status <= JAR_BASE_END) {
+ error(PK11_INSTALL_JAR_EXTRACT, file->jarPath,
+ JAR_get_error(status));
+ } else {
+ error(PK11_INSTALL_JAR_EXTRACT, file->jarPath,
+ mySECU_ErrorString(PORT_GetError()));
+ }
+ ret = PK11_INSTALL_JAR_EXTRACT;
+ goto loser;
+ }
+ if (feedback) {
+ PR_fprintf(feedback, msgStrings[INSTALLED_FILE_MSG],
+ file->jarPath, dest);
+ }
+
+/* no NSPR command to change permissions? */
+#ifdef XP_UNIX
+ (void)chmod(dest, file->permissions);
+#endif
+
+ PR_Free(dest);
+ }
+ /* Make sure we found the module file */
+ if (!modDest) {
+ /* Internal problem here, since every platform is supposed to have
+ a module file */
+ error(PK11_INSTALL_NO_MOD_FILE, platform->moduleName);
+ ret = PK11_INSTALL_NO_MOD_FILE;
+ goto loser;
+ }
+
+ /*
+ // Execute any executable files
+ */
+ {
+ argv[1] = NULL;
+ envp[0] = NULL;
+ for (execNode = executables.head; execNode; execNode = execNode->next) {
+ attr = PR_NewProcessAttr();
+ argv[0] = PR_Strdup(execNode->str);
+
+ /* Announce our intentions */
+ if (feedback) {
+ PR_fprintf(feedback, msgStrings[EXEC_FILE_MSG], execNode->str);
+ }
+
+ /* start the process */
+ if (!(proc = PR_CreateProcess(execNode->str, argv, envp, attr))) {
+ PR_Free(argv[0]);
+ PR_DestroyProcessAttr(attr);
+ error(PK11_INSTALL_EXEC_FILE, execNode->str);
+ ret = PK11_INSTALL_EXEC_FILE;
+ goto loser;
+ }
+
+ /* wait for it to finish */
+ if (PR_WaitProcess(proc, &errcode) != PR_SUCCESS) {
+ PR_Free(argv[0]);
+ PR_DestroyProcessAttr(attr);
+ error(PK11_INSTALL_WAIT_PROCESS, execNode->str);
+ ret = PK11_INSTALL_WAIT_PROCESS;
+ goto loser;
+ }
+
+ /* What happened? */
+ if (errcode) {
+ /* process returned an error */
+ error(PK11_INSTALL_PROC_ERROR, execNode->str, errcode);
+ } else if (feedback) {
+ /* process ran successfully */
+ PR_fprintf(feedback, msgStrings[EXEC_SUCCESS], execNode->str);
+ }
+
+ PR_Free(argv[0]);
+ PR_DestroyProcessAttr(attr);
+ }
+ }
+
+ /*
+ // Add the module
+ */
+ status = Pk11Install_AddNewModule((char *)platform->moduleName,
+ (char *)modDest, platform->mechFlags, platform->cipherFlags);
+
+ if (status != SECSuccess) {
+ error(PK11_INSTALL_ADD_MODULE, platform->moduleName);
+ ret = PK11_INSTALL_ADD_MODULE;
+ goto loser;
+ }
+ if (feedback) {
+ PR_fprintf(feedback, msgStrings[INSTALLED_MODULE_MSG],
+ platform->moduleName);
+ }
+
+ if (feedback) {
+ PR_fprintf(feedback, msgStrings[INSTALLATION_COMPLETE_MSG]);
+ }
+
+ ret = PK11_INSTALL_SUCCESS;
+
+loser:
+ if (modDest) {
+ PR_Free(modDest);
+ }
+ if (tempname) {
+ PRFileInfo info;
+ if (PR_GetFileInfo(tempname, &info) == PR_SUCCESS) {
+ if (info.type == PR_FILE_DIRECTORY) {
+ /* Recursively remove temporary directory */
+ if (rm_dash_r(tempname)) {
+ error(PK11_INSTALL_REMOVE_DIR,
+ tempname);
+ ret = PK11_INSTALL_REMOVE_DIR;
+ }
+ }
+ }
+ PR_Free(tempname);
+ }
+ StringList_delete(&executables);
+ return ret;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+*/
+static char *
+PR_Strdup(const char *str)
+{
+ char *tmp = (char *)PR_Malloc(strlen(str) + 1);
+ strcpy(tmp, str);
+ return tmp;
+}
+
+/*
+ * r m _ d a s h _ r
+ *
+ * Remove a file, or a directory recursively.
+ *
+ */
+static int
+rm_dash_r(char *path)
+{
+ PRDir *dir;
+ PRDirEntry *entry;
+ PRFileInfo fileinfo;
+ char filename[240];
+
+ if (PR_GetFileInfo(path, &fileinfo) != PR_SUCCESS) {
+ /*fprintf(stderr, "Error: Unable to access %s\n", filename);*/
+ return -1;
+ }
+ if (fileinfo.type == PR_FILE_DIRECTORY) {
+
+ dir = PR_OpenDir(path);
+ if (!dir) {
+ return -1;
+ }
+
+ /* Recursively delete all entries in the directory */
+ while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) {
+ sprintf(filename, "%s/%s", path, entry->name);
+ if (rm_dash_r(filename)) {
+ PR_CloseDir(dir);
+ return -1;
+ }
+ }
+
+ if (PR_CloseDir(dir) != PR_SUCCESS) {
+ return -1;
+ }
+
+ /* Delete the directory itself */
+ if (PR_RmDir(path) != PR_SUCCESS) {
+ return -1;
+ }
+ } else {
+ if (PR_Delete(path) != PR_SUCCESS) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * m a k e _ d i r s
+ *
+ * Ensure that the directory portion of the path exists. This may require
+ * making the directory, and its parent, and its parent's parent, etc.
+ */
+static int
+make_dirs(char *path, int file_perms)
+{
+ char *Path;
+ char *start;
+ char *sep;
+ int ret = 0;
+ PRFileInfo info;
+
+ if (!path) {
+ return 0;
+ }
+
+ Path = PR_Strdup(path);
+ start = strpbrk(Path, "/\\");
+ if (!start) {
+ return 0;
+ }
+ start++; /* start right after first slash */
+
+ /* Each time through the loop add one more directory. */
+ while ((sep = strpbrk(start, "/\\"))) {
+ *sep = '\0';
+
+ if (PR_GetFileInfo(Path, &info) != PR_SUCCESS) {
+ /* No such dir, we have to create it */
+ if (PR_MkDir(Path, dir_perms(file_perms)) != PR_SUCCESS) {
+ error(PK11_INSTALL_CREATE_DIR, Path);
+ ret = PK11_INSTALL_CREATE_DIR;
+ goto loser;
+ }
+ } else {
+ /* something exists by this name, make sure it's a directory */
+ if (info.type != PR_FILE_DIRECTORY) {
+ error(PK11_INSTALL_CREATE_DIR, Path);
+ ret = PK11_INSTALL_CREATE_DIR;
+ goto loser;
+ }
+ }
+
+ /* If this is the lowest directory level, make sure it is writeable */
+ if (!strpbrk(sep + 1, "/\\")) {
+ if (PR_Access(Path, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
+ error(PK11_INSTALL_DIR_NOT_WRITEABLE, Path);
+ ret = PK11_INSTALL_DIR_NOT_WRITEABLE;
+ goto loser;
+ }
+ }
+
+ start = sep + 1; /* start after the next slash */
+ *sep = '/';
+ }
+
+loser:
+ PR_Free(Path);
+ return ret;
+}
+
+/*************************************************************************
+ * d i r _ p e r m s
+ *
+ * Guesses the desired permissions on a directory based on the permissions
+ * of a file that will be stored in it. Give read, write, and
+ * execute to the owner (so we can create the file), read and
+ * execute to anyone who has read permissions on the file, and write
+ * to anyone who has write permissions on the file.
+ */
+static int
+dir_perms(int perms)
+{
+ int ret = 0;
+
+ /* owner */
+ ret |= 0700;
+
+ /* group */
+ if (perms & 0040) {
+ /* read on the file -> read and execute on the directory */
+ ret |= 0050;
+ }
+ if (perms & 0020) {
+ /* write on the file -> write on the directory */
+ ret |= 0020;
+ }
+
+ /* others */
+ if (perms & 0004) {
+ /* read on the file -> read and execute on the directory */
+ ret |= 0005;
+ }
+ if (perms & 0002) {
+ /* write on the file -> write on the directory */
+ ret |= 0002;
+ }
+
+ return ret;
+}
diff --git a/security/nss/cmd/modutil/install.h b/security/nss/cmd/modutil/install.h
new file mode 100644
index 000000000..5d6d3eaba
--- /dev/null
+++ b/security/nss/cmd/modutil/install.h
@@ -0,0 +1,100 @@
+/* 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 PK11INSTALL_H
+#define PK11INSTALL_H
+
+#include <prio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*Pk11Install_ErrorHandler)(char *);
+
+typedef enum {
+ PK11_INSTALL_NO_ERROR = 0,
+ PK11_INSTALL_DIR_DOESNT_EXIST,
+ PK11_INSTALL_FILE_DOESNT_EXIST,
+ PK11_INSTALL_FILE_NOT_READABLE,
+ PK11_INSTALL_ERROR_STRING,
+ PK11_INSTALL_JAR_ERROR,
+ PK11_INSTALL_NO_INSTALLER_SCRIPT,
+ PK11_INSTALL_DELETE_TEMP_FILE,
+ PK11_INSTALL_OPEN_SCRIPT_FILE,
+ PK11_INSTALL_SCRIPT_PARSE,
+ PK11_INSTALL_SEMANTIC,
+ PK11_INSTALL_SYSINFO,
+ PK11_INSTALL_NO_PLATFORM,
+ PK11_INSTALL_BOGUS_REL_DIR,
+ PK11_INSTALL_NO_MOD_FILE,
+ PK11_INSTALL_ADD_MODULE,
+ PK11_INSTALL_JAR_EXTRACT,
+ PK11_INSTALL_DIR_NOT_WRITEABLE,
+ PK11_INSTALL_CREATE_DIR,
+ PK11_INSTALL_REMOVE_DIR,
+ PK11_INSTALL_EXEC_FILE,
+ PK11_INSTALL_WAIT_PROCESS,
+ PK11_INSTALL_PROC_ERROR,
+ PK11_INSTALL_USER_ABORT,
+ PK11_INSTALL_UNSPECIFIED
+} Pk11Install_Error;
+#define PK11_INSTALL_SUCCESS PK11_INSTALL_NO_ERROR
+
+/**************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ I n i t
+ *
+ * Does initialization that otherwise would be done on the fly. Only
+ * needs to be called by multithreaded apps, before they make any calls
+ * to this library.
+ */
+void
+Pk11Install_Init();
+
+/**************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ S e t E r r o r H a n d l e r
+ *
+ * Sets the error handler to be used by the library. Returns the current
+ * error handler function.
+ */
+Pk11Install_ErrorHandler
+Pk11Install_SetErrorHandler(Pk11Install_ErrorHandler handler);
+
+/**************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ R e l e a s e
+ *
+ * Releases static data structures used by the library. Don't use the
+ * library after calling this, unless you call Pk11Install_Init()
+ * first. This function doesn't have to be called at all unless you're
+ * really anal about freeing memory before your program exits.
+ */
+void
+Pk11Install_Release();
+
+/*************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ D o I n s t a l l
+ *
+ * jarFile is the path of a JAR in the PKCS #11 module JAR format.
+ * installDir is the directory relative to which files will be
+ * installed.
+ * feedback is a file descriptor to which to write informative (not error)
+ * status messages: what files are being installed, what modules are being
+ * installed. If feedback==NULL, no messages will be displayed.
+ * If force != 0, interactive prompts will be suppressed.
+ * If noverify == PR_TRUE, signatures won't be checked on the JAR file.
+ */
+Pk11Install_Error
+Pk11Install_DoInstall(char *jarFile, const char *installDir,
+ const char *tempDir, PRFileDesc *feedback, short force,
+ PRBool noverify);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*PK11INSTALL_H*/
diff --git a/security/nss/cmd/modutil/installparse.c b/security/nss/cmd/modutil/installparse.c
new file mode 100644
index 000000000..d35d048dd
--- /dev/null
+++ b/security/nss/cmd/modutil/installparse.c
@@ -0,0 +1,434 @@
+/* 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 lint
+char yysccsid[] = "@(#)yaccpar 1.4 (Berkeley) 02/25/90";
+#endif
+#line 37 "installparse.y"
+
+#define yyparse Pk11Install_yyparse
+#define yylex Pk11Install_yylex
+#define yyerror Pk11Install_yyerror
+#define yychar Pk11Install_yychar
+#define yyval Pk11Install_yyval
+#define yylval Pk11Install_yylval
+#define yydebug Pk11Install_yydebug
+#define yynerrs Pk11Install_yynerrs
+#define yyerrflag Pk11Install_yyerrflag
+#define yyss Pk11Install_yyss
+#define yyssp Pk11Install_yyssp
+#define yyvs Pk11Install_yyvs
+#define yyvsp Pk11Install_yyvsp
+#define yylhs Pk11Install_yylhs
+#define yylen Pk11Install_yylen
+#define yydefred Pk11Install_yydefred
+#define yydgoto Pk11Install_yydgoto
+#define yysindex Pk11Install_yysindex
+#define yyrindex Pk11Install_yyrindex
+#define yygindex Pk11Install_yygindex
+#define yytable Pk11Install_yytable
+#define yycheck Pk11Install_yycheck
+#define yyname Pk11Install_yyname
+#define yyrule Pk11Install_yyrule
+
+/* C Stuff */
+#include "install-ds.h"
+#include <prprf.h>
+
+#define YYSTYPE Pk11Install_Pointer
+extern char *Pk11Install_yytext;
+char *Pk11Install_yyerrstr = NULL;
+
+#line 40 "ytab.c"
+#define OPENBRACE 257
+#define CLOSEBRACE 258
+#define STRING 259
+#define YYERRCODE 256
+/* clang-format on */
+short yylhs[] = {
+ -1,
+ 0, 1, 1, 2, 2, 3, 4,
+};
+short yylen[] = {
+ 2,
+ 1, 2, 0, 1, 1, 4, 1,
+};
+short yydefred[] = {
+ 0,
+ 0, 0, 1, 0, 4, 0, 2, 0, 0, 6,
+};
+short yydgoto[] = {
+ 2,
+ 3, 4, 5, 6,
+};
+short yysindex[] = {
+ -257,
+ 0, 0, 0, -257, 0, -252, 0, -257, -251, 0,
+};
+short yyrindex[] = {
+ 6,
+ 1, 0, 0, 3, 0, 0, 0, -250, 0, 0,
+};
+short yygindex[] = {
+ 0,
+ -4, 0, 0, 0,
+};
+#define YYTABLESIZE 261
+short yytable[] = {
+ 7,
+ 5, 1, 3, 9, 8, 3, 10, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 7, 5, 5,
+ 3,
+};
+short yycheck[] = {
+ 4,
+ 0, 259, 0, 8, 257, 0, 258, 258, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 257, 258, 259,
+ 258,
+};
+/* clang-format on */
+#define YYFINAL 2
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 259
+#if YYDEBUG
+char *yyname[] = {
+ "end-of-file", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "OPENBRACE", "CLOSEBRACE", "STRING",
+};
+char *yyrule[] = {
+ "$accept : toplist",
+ "toplist : valuelist",
+ "valuelist : value valuelist",
+ "valuelist :",
+ "value : key_value_pair",
+ "value : STRING",
+ "key_value_pair : key OPENBRACE valuelist CLOSEBRACE",
+ "key : STRING",
+};
+#endif
+#ifndef YYSTYPE
+typedef int YYSTYPE;
+#endif
+#define yyclearin (yychar = (-1))
+#define yyerrok (yyerrflag = 0)
+#ifndef YYSTACKSIZE
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 300
+#endif
+#endif
+int yydebug;
+int yynerrs;
+int yyerrflag;
+int yychar;
+short *yyssp;
+YYSTYPE *yyvsp;
+YYSTYPE yyval;
+YYSTYPE yylval;
+#define yystacksize YYSTACKSIZE
+short yyss[YYSTACKSIZE];
+YYSTYPE yyvs[YYSTACKSIZE];
+#line 118 "installparse.y"
+/*----------------------- Program Section --------------------------------*/
+
+/*************************************************************************/
+void
+Pk11Install_yyerror(char *message)
+{
+ char *tmp;
+ if (Pk11Install_yyerrstr) {
+ tmp = PR_smprintf("%sline %d: %s\n", Pk11Install_yyerrstr,
+ Pk11Install_yylinenum, message);
+ PR_smprintf_free(Pk11Install_yyerrstr);
+ } else {
+ tmp = PR_smprintf("line %d: %s\n", Pk11Install_yylinenum, message);
+ }
+ Pk11Install_yyerrstr = tmp;
+}
+#line 191 "ytab.c"
+#define YYABORT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+int
+yyparse()
+{
+ register int yym, yyn, yystate;
+#if YYDEBUG
+ register char *yys;
+ extern char *PR_GetEnvSecure();
+
+ if ((yys = PR_GetEnvSecure("YYDEBUG")) != NULL) {
+ yyn = *yys;
+ if (yyn >= '0' && yyn <= '9')
+ yydebug = yyn - '0';
+ }
+#endif
+
+ yynerrs = 0;
+ yyerrflag = 0;
+ yychar = (-1);
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+ *yyssp = yystate = 0;
+
+yyloop:
+ if ((yyn = yydefred[yystate]) != 0)
+ goto yyreduce;
+ if (yychar < 0) {
+ if ((yychar = yylex()) < 0)
+ yychar = 0;
+#if YYDEBUG
+ if (yydebug) {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN)
+ yys = yyname[yychar];
+ if (!yys)
+ yys = "illegal-symbol";
+ printf("yydebug: state %d, reading %d (%s)\n", yystate,
+ yychar, yys);
+ }
+#endif
+ }
+ if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar) {
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: state %d, shifting to state %d\n",
+ yystate, yytable[yyn]);
+#endif
+ if (yyssp >= yyss + yystacksize - 1) {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate = yytable[yyn];
+ *++yyvsp = yylval;
+ yychar = (-1);
+ if (yyerrflag > 0)
+ --yyerrflag;
+ goto yyloop;
+ }
+ if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar) {
+ yyn = yytable[yyn];
+ goto yyreduce;
+ }
+ if (yyerrflag)
+ goto yyinrecovery;
+#ifdef lint
+ goto yynewerror;
+yynewerror:
+#endif
+ yyerror("syntax error");
+#ifdef lint
+ goto yyerrlab;
+yyerrlab:
+#endif
+ ++yynerrs;
+yyinrecovery:
+ if (yyerrflag < 3) {
+ yyerrflag = 3;
+ for (;;) {
+ if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) {
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: state %d, error recovery shifting\
+ to state %d\n",
+ *yyssp, yytable[yyn]);
+#endif
+ if (yyssp >= yyss + yystacksize - 1) {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate = yytable[yyn];
+ *++yyvsp = yylval;
+ goto yyloop;
+ } else {
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: error recovery discarding state %d\n",
+ *yyssp);
+#endif
+ if (yyssp <= yyss)
+ goto yyabort;
+ --yyssp;
+ --yyvsp;
+ }
+ }
+ } else {
+ if (yychar == 0)
+ goto yyabort;
+#if YYDEBUG
+ if (yydebug) {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN)
+ yys = yyname[yychar];
+ if (!yys)
+ yys = "illegal-symbol";
+ printf("yydebug: state %d, error recovery discards token %d (%s)\n",
+ yystate, yychar, yys);
+ }
+#endif
+ yychar = (-1);
+ goto yyloop;
+ }
+yyreduce:
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: state %d, reducing by rule %d (%s)\n",
+ yystate, yyn, yyrule[yyn]);
+#endif
+ yym = yylen[yyn];
+ yyval = yyvsp[1 - yym];
+ switch (yyn) {
+ case 1:
+#line 84 "installparse.y"
+ {
+ Pk11Install_valueList = yyvsp[0].list;
+ } break;
+ case 2:
+#line 89 "installparse.y"
+ {
+ Pk11Install_ValueList_AddItem(yyvsp[0].list, yyvsp[-1].value);
+ yyval.list = yyvsp[0].list;
+ } break;
+ case 3:
+#line 94 "installparse.y"
+ {
+ yyval.list = Pk11Install_ValueList_new();
+ } break;
+ case 4:
+#line 99 "installparse.y"
+ {
+ yyval.value = Pk11Install_Value_new(PAIR_VALUE, yyvsp[0]);
+ } break;
+ case 5:
+#line 103 "installparse.y"
+ {
+ yyval.value = Pk11Install_Value_new(STRING_VALUE, yyvsp[0]);
+ } break;
+ case 6:
+#line 108 "installparse.y"
+ {
+ yyval.pair = Pk11Install_Pair_new(yyvsp[-3].string, yyvsp[-1].list);
+ } break;
+ case 7:
+#line 113 "installparse.y"
+ {
+ yyval.string = yyvsp[0].string;
+ } break;
+#line 374 "ytab.c"
+ }
+ yyssp -= yym;
+ yystate = *yyssp;
+ yyvsp -= yym;
+ yym = yylhs[yyn];
+ if (yystate == 0 && yym == 0) {
+#ifdef YYDEBUG
+ if (yydebug)
+ printf("yydebug: after reduction, shifting from state 0 to\
+ state %d\n",
+ YYFINAL);
+#endif
+ yystate = YYFINAL;
+ *++yyssp = YYFINAL;
+ *++yyvsp = yyval;
+ if (yychar < 0) {
+ if ((yychar = yylex()) < 0)
+ yychar = 0;
+#if YYDEBUG
+ if (yydebug) {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN)
+ yys = yyname[yychar];
+ if (!yys)
+ yys = "illegal-symbol";
+ printf("yydebug: state %d, reading %d (%s)\n",
+ YYFINAL, yychar, yys);
+ }
+#endif
+ }
+ if (yychar == 0)
+ goto yyaccept;
+ goto yyloop;
+ }
+ if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
+ yystate = yytable[yyn];
+ else
+ yystate = yydgoto[yym];
+#ifdef YYDEBUG
+ if (yydebug)
+ printf("yydebug: after reduction, shifting from state %d \
+to state %d\n",
+ *yyssp, yystate);
+#endif
+ if (yyssp >= yyss + yystacksize - 1) {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate;
+ *++yyvsp = yyval;
+ goto yyloop;
+yyoverflow:
+ yyerror("yacc stack overflow");
+yyabort:
+ return (1);
+yyaccept:
+ return (0);
+}
diff --git a/security/nss/cmd/modutil/installparse.h b/security/nss/cmd/modutil/installparse.h
new file mode 100644
index 000000000..2c02b57b6
--- /dev/null
+++ b/security/nss/cmd/modutil/installparse.h
@@ -0,0 +1,7 @@
+/* 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/. */
+
+#define OPENBRACE 257
+#define CLOSEBRACE 258
+#define STRING 259
diff --git a/security/nss/cmd/modutil/installparse.l b/security/nss/cmd/modutil/installparse.l
new file mode 100644
index 000000000..71fb56101
--- /dev/null
+++ b/security/nss/cmd/modutil/installparse.l
@@ -0,0 +1,137 @@
+/* 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/. */
+
+
+/* lex file for analyzing PKCS #11 Module installation instructions */
+
+/*----------------------------- Definitions ---------------------------*/
+%{
+#include <string.h>
+
+#include "install-ds.h" /* defines tokens and data structures */
+#include "installparse.h" /* produced by yacc -d */
+#include <prprf.h>
+static char *putSimpleString(char*); /* return copy of string */
+static char *putComplexString(char*); /* strip out quotes, deal with */
+ /* escaped characters */
+
+void Pk11Install_yyerror(char *);
+
+/* Overrides to use NSPR */
+#define malloc PR_Malloc
+#define realloc PR_Realloc
+#define free PR_Free
+
+int Pk11Install_yylinenum=1;
+static char *err;
+
+#define YY_NEVER_INTERACTIVE 1
+#define yyunput Pkcs11Install_yyunput
+
+/* This is the default YY_INPUT modified for NSPR */
+#define YY_INPUT(buf,result,max_size) \
+ if ( yy_current_buffer->yy_is_interactive ) { \
+ char c; \
+ int n; \
+ for ( n = 0; n < max_size && \
+ PR_Read(Pk11Install_FD, &c, 1)==1 && c != '\n'; ++n ) { \
+ buf[n] = c; \
+ } \
+ if ( c == '\n' ) { \
+ buf[n++] = c; \
+ } \
+ result = n; \
+ } else { \
+ result = PR_Read(Pk11Install_FD, buf, max_size); \
+ }
+
+%}
+
+/*** Regular expression definitions ***/
+/* simple_string has no whitespace, quotes, or braces */
+simple_string [^ \t\r\n\""{""}"]+
+
+/* complex_string is enclosed in quotes. Inside the quotes, quotes and
+ backslashes must be backslash-escaped. No newlines or carriage returns
+ are allowed inside the quotes. Otherwise, anything goes. */
+complex_string \"([^\"\\\r\n]|(\\\")|(\\\\))+\"
+
+/* Standard whitespace */
+whitespace [ \t\r]+
+
+other .
+
+/*---------------------------- Actions --------------------------------*/
+%%
+
+"{" return OPENBRACE;
+"}" return CLOSEBRACE;
+{simple_string} {Pk11Install_yylval.string =
+ putSimpleString(Pk11Install_yytext);
+ return STRING;}
+{complex_string} {Pk11Install_yylval.string =
+ putComplexString(Pk11Install_yytext);
+ return STRING;}
+
+"\n" Pk11Install_yylinenum++;
+
+{whitespace} ;
+
+{other} {err = PR_smprintf("Invalid lexeme: %s",Pk11Install_yytext);
+ Pk11Install_yyerror(err);
+ PR_smprintf_free(err);
+ return 1;
+ }
+
+%%
+/*------------------------ Program Section ----------------------------*/
+
+PRFileDesc *Pk11Install_FD=NULL;
+
+/*************************************************************************/
+/* dummy function required by lex */
+int Pk11Install_yywrap(void) { return 1;}
+
+/*************************************************************************/
+/* Return a copy of the given string */
+static char*
+putSimpleString(char *str)
+{
+ char *tmp = (char*) PR_Malloc(strlen(str)+1);
+ strcpy(tmp, str);
+ return tmp;
+}
+
+/*************************************************************************/
+/* Strip out quotes, replace escaped characters with what they stand for.
+ This function assumes that what is passed in is actually a complex
+ string, so error checking is lax. */
+static char*
+putComplexString(char *str)
+{
+ int size, i,j;
+ char *tmp;
+
+ if(!str) {
+ return NULL;
+ }
+ size = strlen(str);
+
+ /* Allocate the new space. This string will actually be too big,
+ since quotes and backslashes will be stripped out. But that's ok. */
+ tmp = (char*) PR_Malloc(size+1);
+
+ /* Copy it over */
+ for(i=0, j=0; i < size; i++) {
+ if(str[i]=='\"') {
+ continue; /* skip un-escaped quotes */
+ } else if(str[i]=='\\') {
+ ++i; /* escaped character. skip the backslash */
+ }
+ tmp[j++] = str[i];
+ }
+ tmp[j] = '\0';
+
+ return tmp;
+}
diff --git a/security/nss/cmd/modutil/installparse.y b/security/nss/cmd/modutil/installparse.y
new file mode 100644
index 000000000..b6d701136
--- /dev/null
+++ b/security/nss/cmd/modutil/installparse.y
@@ -0,0 +1,104 @@
+/* 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/. */
+
+/* yacc file for parsing PKCS #11 module installation instructions */
+/*------------------------ Definition Section ---------------------------*/
+
+%{
+#define yyparse Pk11Install_yyparse
+#define yylex Pk11Install_yylex
+#define yyerror Pk11Install_yyerror
+#define yychar Pk11Install_yychar
+#define yyval Pk11Install_yyval
+#define yylval Pk11Install_yylval
+#define yydebug Pk11Install_yydebug
+#define yynerrs Pk11Install_yynerrs
+#define yyerrflag Pk11Install_yyerrflag
+#define yyss Pk11Install_yyss
+#define yyssp Pk11Install_yyssp
+#define yyvs Pk11Install_yyvs
+#define yyvsp Pk11Install_yyvsp
+#define yylhs Pk11Install_yylhs
+#define yylen Pk11Install_yylen
+#define yydefred Pk11Install_yydefred
+#define yydgoto Pk11Install_yydgoto
+#define yysindex Pk11Install_yysindex
+#define yyrindex Pk11Install_yyrindex
+#define yygindex Pk11Install_yygindex
+#define yytable Pk11Install_yytable
+#define yycheck Pk11Install_yycheck
+#define yyname Pk11Install_yyname
+#define yyrule Pk11Install_yyrule
+
+/* C Stuff */
+#include "install-ds.h"
+#include <prprf.h>
+
+#define YYSTYPE Pk11Install_Pointer
+extern char *Pk11Install_yytext;
+char *Pk11Install_yyerrstr=NULL;
+
+%}
+
+/* Tokens */
+%token OPENBRACE
+%token CLOSEBRACE
+%token STRING
+%start toplist
+
+%%
+
+/*--------------------------- Productions -------------------------------*/
+
+toplist : valuelist
+{
+ Pk11Install_valueList = $1.list;
+}
+
+valuelist : value valuelist
+{
+ Pk11Install_ValueList_AddItem($2.list,$1.value);
+ $$.list = $2.list;
+}
+|
+{
+ $$.list = Pk11Install_ValueList_new();
+};
+
+value : key_value_pair
+{
+ $$.value= Pk11Install_Value_new(PAIR_VALUE,$1);
+}
+| STRING
+{
+ $$.value= Pk11Install_Value_new(STRING_VALUE, $1);
+};
+
+key_value_pair : key OPENBRACE valuelist CLOSEBRACE
+{
+ $$.pair = Pk11Install_Pair_new($1.string,$3.list);
+};
+
+key : STRING
+{
+ $$.string = $1.string;
+};
+
+%%
+/*----------------------- Program Section --------------------------------*/
+
+/*************************************************************************/
+void
+Pk11Install_yyerror(char *message)
+{
+ char *tmp;
+ if(Pk11Install_yyerrstr) {
+ tmp=PR_smprintf("%sline %d: %s\n", Pk11Install_yyerrstr,
+ Pk11Install_yylinenum, message);
+ PR_smprintf_free(Pk11Install_yyerrstr);
+ } else {
+ tmp = PR_smprintf("line %d: %s\n", Pk11Install_yylinenum, message);
+ }
+ Pk11Install_yyerrstr=tmp;
+}
diff --git a/security/nss/cmd/modutil/instsec.c b/security/nss/cmd/modutil/instsec.c
new file mode 100644
index 000000000..95191e729
--- /dev/null
+++ b/security/nss/cmd/modutil/instsec.c
@@ -0,0 +1,153 @@
+/* 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/. */
+
+#include <plarena.h>
+#include <prerror.h>
+#include <prio.h>
+#include <prprf.h>
+#include <seccomon.h>
+#include <secmod.h>
+#include <jar.h>
+#include <secutil.h>
+
+/* These are installation functions that make calls to the security library.
+ * We don't want to include security include files in the C++ code too much.
+ */
+
+static char *PR_fgets(char *buf, int size, PRFileDesc *file);
+
+/***************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ A d d N e w M o d u l e
+ */
+int
+Pk11Install_AddNewModule(char *moduleName, char *dllPath,
+ unsigned long defaultMechanismFlags,
+ unsigned long cipherEnableFlags)
+{
+ return (SECMOD_AddNewModule(moduleName, dllPath,
+ SECMOD_PubMechFlagstoInternal(defaultMechanismFlags),
+ SECMOD_PubCipherFlagstoInternal(cipherEnableFlags)) == SECSuccess)
+ ? 0
+ : -1;
+}
+
+/*************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ U s e r V e r i f y J a r
+ *
+ * Gives the user feedback on the signatures of a JAR files, asks them
+ * whether they actually want to continue.
+ * Assumes the jar structure has already been created and is valid.
+ * Returns 0 if the user wants to continue the installation, nonzero
+ * if the user wishes to abort.
+ */
+short
+Pk11Install_UserVerifyJar(JAR *jar, PRFileDesc *out, PRBool query)
+{
+ JAR_Context *ctx;
+ JAR_Cert *fing;
+ JAR_Item *item;
+ char stdinbuf[80];
+ int count = 0;
+
+ CERTCertificate *cert, *prev = NULL;
+
+ PR_fprintf(out, "\nThis installation JAR file was signed by:\n");
+
+ ctx = JAR_find(jar, NULL, jarTypeSign);
+
+ while (JAR_find_next(ctx, &item) >= 0) {
+ fing = (JAR_Cert *)item->data;
+ cert = fing->cert;
+ if (cert == prev) {
+ continue;
+ }
+
+ count++;
+ PR_fprintf(out, "----------------------------------------------\n");
+ if (cert) {
+ if (cert->nickname) {
+ PR_fprintf(out, "**NICKNAME**\n%s\n", cert->nickname);
+ }
+ if (cert->subjectName) {
+ PR_fprintf(out, "**SUBJECT NAME**\n%s\n", cert->subjectName);
+ }
+ if (cert->issuerName) {
+ PR_fprintf(out, "**ISSUER NAME**\n%s\n", cert->issuerName);
+ }
+ } else {
+ PR_fprintf(out, "No matching certificate could be found.\n");
+ }
+ PR_fprintf(out, "----------------------------------------------\n\n");
+
+ prev = cert;
+ }
+
+ JAR_find_end(ctx);
+
+ if (count == 0) {
+ PR_fprintf(out, "No signatures found: JAR FILE IS UNSIGNED.\n");
+ }
+
+ if (query) {
+ PR_fprintf(out,
+ "Do you wish to continue this installation? (y/n) ");
+
+ if (PR_fgets(stdinbuf, 80, PR_STDIN) != NULL) {
+ char *response;
+
+ if ((response = strtok(stdinbuf, " \t\n\r"))) {
+ if (!PL_strcasecmp(response, "y") ||
+ !PL_strcasecmp(response, "yes")) {
+ return 0;
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+/**************************************************************************
+ *
+ * P R _ f g e t s
+ *
+ * fgets implemented with NSPR.
+ */
+static char *
+PR_fgets(char *buf, int size, PRFileDesc *file)
+{
+ int i;
+ int status;
+ char c;
+
+ i = 0;
+ while (i < size - 1) {
+ status = PR_Read(file, (void *)&c, 1);
+ if (status == -1) {
+ return NULL;
+ } else if (status == 0) {
+ break;
+ }
+ buf[i++] = c;
+ if (c == '\n') {
+ break;
+ }
+ }
+ buf[i] = '\0';
+
+ return buf;
+}
+
+/**************************************************************************
+ *
+ * m y S E C U _ E r r o r S t r i n g
+ *
+ */
+const char *
+mySECU_ErrorString(PRErrorCode errnum)
+{
+ return SECU_Strerror(errnum);
+}
diff --git a/security/nss/cmd/modutil/lex.Pk11Install_yy.c b/security/nss/cmd/modutil/lex.Pk11Install_yy.c
new file mode 100644
index 000000000..4fa3d766e
--- /dev/null
+++ b/security/nss/cmd/modutil/lex.Pk11Install_yy.c
@@ -0,0 +1,1607 @@
+/* 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/. */
+
+#define yy_create_buffer Pk11Install_yy_create_buffer
+#define yy_delete_buffer Pk11Install_yy_delete_buffer
+#define yy_scan_buffer Pk11Install_yy_scan_buffer
+#define yy_scan_string Pk11Install_yy_scan_string
+#define yy_scan_bytes Pk11Install_yy_scan_bytes
+#define yy_flex_debug Pk11Install_yy_flex_debug
+#define yy_init_buffer Pk11Install_yy_init_buffer
+#define yy_flush_buffer Pk11Install_yy_flush_buffer
+#define yy_load_buffer_state Pk11Install_yy_load_buffer_state
+#define yy_switch_to_buffer Pk11Install_yy_switch_to_buffer
+#define yyin Pk11Install_yyin
+#define yyleng Pk11Install_yyleng
+#define yylex Pk11Install_yylex
+#define yyout Pk11Install_yyout
+#define yyrestart Pk11Install_yyrestart
+#define yytext Pk11Install_yytext
+#define yywrap Pk11Install_yywrap
+
+#line 20 "lex.Pk11Install_yy.c"
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+//#include <unistd.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+#pragma warn - rch
+#pragma warn - use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int)(unsigned char)c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin)
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator). This
+ * avoids problems with code like:
+ *
+ * if ( condition_holds )
+ * yyless( 5 );
+ * else
+ * do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+ do { \
+ /* Undo effects of setting up yytext. */ \
+ *yy_cp = yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } while (0)
+
+#define unput(c) yyunput(c, yytext_ptr)
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+struct yy_buffer_state {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+/* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+};
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *)0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO((FILE * input_file));
+
+void yy_switch_to_buffer YY_PROTO((YY_BUFFER_STATE new_buffer));
+void yy_load_buffer_state YY_PROTO((void));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO((FILE * file, int size));
+void yy_delete_buffer YY_PROTO((YY_BUFFER_STATE b));
+void yy_init_buffer YY_PROTO((YY_BUFFER_STATE b, FILE *file));
+void yy_flush_buffer YY_PROTO((YY_BUFFER_STATE b));
+#define YY_FLUSH_BUFFER yy_flush_buffer(yy_current_buffer)
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO((char *base, yy_size_t size));
+YY_BUFFER_STATE yy_scan_string YY_PROTO((yyconst char *yy_str));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO((yyconst char *bytes, int len));
+
+static void *yy_flex_alloc YY_PROTO((yy_size_t));
+static void *yy_flex_realloc YY_PROTO((void *, yy_size_t));
+static void yy_flex_free YY_PROTO((void *));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if (!yy_current_buffer) \
+ yy_current_buffer = yy_create_buffer(yyin, YY_BUF_SIZE); \
+ yy_current_buffer->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if (!yy_current_buffer) \
+ yy_current_buffer = yy_create_buffer(yyin, YY_BUF_SIZE); \
+ yy_current_buffer->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *)0, *yyout = (FILE *)0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO((void));
+static yy_state_type yy_try_NUL_trans YY_PROTO((yy_state_type current_state));
+static int yy_get_next_buffer YY_PROTO((void));
+static void yy_fatal_error YY_PROTO((yyconst char msg[]));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yytext_ptr = yy_bp; \
+ yyleng = (int)(yy_cp - yy_bp); \
+ yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 8
+#define YY_END_OF_BUFFER 9
+static yyconst short int yy_accept[16] =
+ { 0,
+ 0, 0, 9, 3, 6, 5, 7, 1, 2, 3,
+ 6, 0, 0, 4, 0 };
+
+static yyconst int yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 5, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 6, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 7, 1, 8, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1 };
+
+static yyconst int yy_meta[9] =
+ { 0,
+ 1, 2, 3, 4, 3, 1, 5, 5 };
+
+static yyconst short int yy_base[19] =
+ { 0,
+ 0, 0, 19, 0, 0, 21, 12, 21, 21, 0,
+ 0, 4, 6, 21, 21, 13, 11, 15 };
+
+static yyconst short int yy_def[19] =
+ { 0,
+ 15, 1, 15, 16, 17, 15, 18, 15, 15, 16,
+ 17, 18, 15, 15, 0, 15, 15, 15 };
+
+static yyconst short int yy_nxt[30] =
+ { 0,
+ 4, 5, 6, 5, 7, 4, 8, 9, 14, 13,
+ 12, 12, 11, 10, 11, 12, 12, 13, 15, 12,
+ 3, 15, 15, 15, 15, 15, 15, 15, 15 };
+
+static yyconst short int yy_chk[30] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 12, 12,
+ 13, 13, 17, 16, 17, 18, 18, 7, 3, 18,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15 };
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "installparse.l"
+#define INITIAL 0
+/* lex file for analyzing PKCS #11 Module installation instructions */
+/*----------------------------- Definitions ---------------------------*/
+#line 5 "installparse.l"
+#include <string.h>
+
+#include "install-ds.h" /* defines tokens and data structures */
+#include "installparse.h" /* produced by yacc -d */
+#include <prprf.h>
+static char *putSimpleString(char *); /* return copy of string */
+static char *putComplexString(char *); /* strip out quotes, deal with */
+ /* escaped characters */
+
+void Pk11Install_yyerror(char *);
+
+/* Overrides to use NSPR */
+#define malloc PR_Malloc
+#define realloc PR_Realloc
+#define free PR_Free
+
+int Pk11Install_yylinenum = 1;
+static char *err;
+
+#define YY_NEVER_INTERACTIVE 1
+#define yyunput Pkcs11Install_yyunput
+
+/* This is the default YY_INPUT modified for NSPR */
+#define YY_INPUT(buf, result, max_size) \
+ if (yy_current_buffer->yy_is_interactive) { \
+ char c; \
+ int n; \
+ for (n = 0; n < max_size && \
+ PR_Read(Pk11Install_FD, &c, 1) == 1 && c != '\n'; \
+ ++n) { \
+ buf[n] = c; \
+ } \
+ if (c == '\n') { \
+ buf[n++] = c; \
+ } \
+ result = n; \
+ } else { \
+ result = PR_Read(Pk11Install_FD, buf, max_size); \
+ }
+
+/*** Regular expression definitions ***/
+/* simple_string has no whitespace, quotes, or braces */
+/* complex_string is enclosed in quotes. Inside the quotes, quotes and
+ backslashes must be backslash-escaped. Otherwise, anything goes. */
+/* Standard whitespace */
+/*---------------------------- Actions --------------------------------*/
+#line 437 "lex.Pk11Install_yy.cpp"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO((void));
+#else
+extern int yywrap YY_PROTO((void));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO((int c, char *buf_ptr));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO((char *, yyconst char *, int));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO((yyconst char *));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO((void));
+#else
+static int input YY_PROTO((void));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO((int new_state));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO((void));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO((void));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines. This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void)fwrite(yytext, yyleng, 1, yyout)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf, result, max_size) \
+ if (yy_current_buffer->yy_is_interactive) { \
+ int c = '*', n; \
+ for (n = 0; n < max_size && \
+ (c = getc(yyin)) != EOF && c != '\n'; \
+ ++n) \
+ buf[n] = (char)c; \
+ if (c == '\n') \
+ buf[n++] = (char)c; \
+ if (c == EOF && ferror(yyin)) \
+ YY_FATAL_ERROR("input in flex scanner failed"); \
+ result = n; \
+ } else if (((result = fread(buf, 1, max_size, yyin)) == 0) && \
+ ferror(yyin)) \
+ YY_FATAL_ERROR("input in flex scanner failed");
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error(msg)
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO((void))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 60 "installparse.l"
+
+#line 591 "lex.Pk11Install_yy.cpp"
+
+ if (yy_init) {
+ yy_init = 0;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if (!yy_start)
+ yy_start = 1; /* first start state */
+
+ if (!yyin)
+ yyin = stdin;
+
+ if (!yyout)
+ yyout = stdout;
+
+ if (!yy_current_buffer)
+ yy_current_buffer =
+ yy_create_buffer(yyin, YY_BUF_SIZE);
+
+ yy_load_buffer_state();
+ }
+
+ while (1) /* loops until end-of-file is reached */
+ {
+ yy_cp = yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yy_start;
+ yy_match:
+ do {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if (yy_accept[yy_current_state]) {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
+ yy_current_state = (int)yy_def[yy_current_state];
+ if (yy_current_state >= 16)
+ yy_c = yy_meta[(unsigned int)yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int)yy_c];
+ ++yy_cp;
+ } while (yy_base[yy_current_state] != 21);
+
+ yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if (yy_act == 0) { /* have to back up */
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+ do_action: /* This label is used only to access EOF actions. */
+
+ switch (yy_act) { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yy_hold_char;
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ goto yy_find_action;
+
+ case 1:
+ YY_RULE_SETUP
+#line 62 "installparse.l"
+ return OPENBRACE;
+ YY_BREAK
+ case 2:
+ YY_RULE_SETUP
+#line 63 "installparse.l"
+ return CLOSEBRACE;
+ YY_BREAK
+ case 3:
+ YY_RULE_SETUP
+#line 64 "installparse.l"
+ {
+ Pk11Install_yylval.string =
+ putSimpleString(Pk11Install_yytext);
+ return STRING;
+ }
+ YY_BREAK
+ case 4:
+ YY_RULE_SETUP
+#line 67 "installparse.l"
+ {
+ Pk11Install_yylval.string =
+ putComplexString(Pk11Install_yytext);
+ return STRING;
+ }
+ YY_BREAK
+ case 5:
+ YY_RULE_SETUP
+#line 71 "installparse.l"
+ Pk11Install_yylinenum++;
+ YY_BREAK
+ case 6:
+ YY_RULE_SETUP
+#line 73 "installparse.l"
+ ;
+ YY_BREAK
+ case 7:
+ YY_RULE_SETUP
+#line 75 "installparse.l"
+ {
+ err =
+ PR_smprintf("Invalid lexeme: %s", Pk11Install_yytext);
+ Pk11Install_yyerror(err);
+ PR_smprintf_free(err);
+ return 1;
+ }
+ YY_BREAK
+ case 8:
+ YY_RULE_SETUP
+#line 81 "installparse.l"
+ ECHO;
+ YY_BREAK
+#line 722 "lex.Pk11Install_yy.cpp"
+ case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER: {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int)(yy_cp - yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if (yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW) {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between yy_current_buffer and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yy_current_buffer->yy_input_file = yyin;
+ yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if (yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars]) { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans(yy_current_state);
+
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+ if (yy_next_state) {
+ /* Consume the NUL. */
+ yy_cp = ++yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else {
+ yy_cp = yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else
+ switch (yy_get_next_buffer()) {
+ case EOB_ACT_END_OF_FILE: {
+ yy_did_buffer_switch_on_eof = 0;
+
+ if (yywrap()) {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else {
+ if (!yy_did_buffer_switch_on_eof)
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p =
+ yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yy_c_buf_p =
+ &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found");
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int
+yy_get_next_buffer()
+{
+ register char *dest = yy_current_buffer->yy_ch_buf;
+ register char *source = yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if (yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1])
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed");
+
+ if (yy_current_buffer->yy_fill_buffer == 0) { /* Don't try to fill the buffer, so this is an EOF. */
+ if (yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1) {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int)(yy_c_buf_p - yytext_ptr) - 1;
+
+ for (i = 0; i < number_to_move; ++i)
+ *(dest++) = *(source++);
+
+ if (yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING)
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+ else {
+ int num_to_read =
+ yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+ while (num_to_read <= 0) { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+ YY_FATAL_ERROR(
+ "input buffer overflow, can't enlarge buffer because scanner uses REJECT");
+#else
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = yy_current_buffer;
+
+ int yy_c_buf_p_offset =
+ (int)(yy_c_buf_p - b->yy_ch_buf);
+
+ if (b->yy_is_our_buffer) {
+ int new_size = b->yy_buf_size * 2;
+
+ if (new_size <= 0)
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yy_flex_realloc((void *)b->yy_ch_buf,
+ b->yy_buf_size + 2);
+ } else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if (!b->yy_ch_buf)
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow");
+
+ yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = yy_current_buffer->yy_buf_size -
+ number_to_move - 1;
+#endif
+ }
+
+ if (num_to_read > YY_READ_BUF_SIZE)
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT((&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read);
+
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ if (yy_n_chars == 0) {
+ if (number_to_move == YY_MORE_ADJ) {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart(yyin);
+ }
+
+ else {
+ ret_val = EOB_ACT_LAST_MATCH;
+ yy_current_buffer->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yy_n_chars += number_to_move;
+ yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type
+yy_get_previous_state()
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = yy_start;
+
+ for (yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp) {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if (yy_accept[yy_current_state]) {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
+ yy_current_state = (int)yy_def[yy_current_state];
+ if (yy_current_state >= 16)
+ yy_c = yy_meta[(unsigned int)yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int)yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type
+yy_try_NUL_trans(yy_state_type yy_current_state)
+#else
+static yy_state_type yy_try_NUL_trans(yy_current_state)
+ yy_state_type yy_current_state;
+#endif
+{
+ register int yy_is_jam;
+ register char *yy_cp = yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if (yy_accept[yy_current_state]) {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
+ yy_current_state = (int)yy_def[yy_current_state];
+ if (yy_current_state >= 16)
+ yy_c = yy_meta[(unsigned int)yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int)yy_c];
+ yy_is_jam = (yy_current_state == 15);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void
+yyunput(int c, register char *yy_bp)
+#else
+static void yyunput(c, yy_bp) int c;
+register char *yy_bp;
+#endif
+{
+ register char *yy_cp = yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yy_hold_char;
+
+ if (yy_cp < yy_current_buffer->yy_ch_buf + 2) { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yy_n_chars + 2;
+ register char *dest = &yy_current_buffer->yy_ch_buf[yy_current_buffer->yy_buf_size +
+ 2];
+ register char *source =
+ &yy_current_buffer->yy_ch_buf[number_to_move];
+
+ while (source > yy_current_buffer->yy_ch_buf)
+ *--dest = *--source;
+
+ yy_cp += (int)(dest - source);
+ yy_bp += (int)(dest - source);
+ yy_current_buffer->yy_n_chars =
+ yy_n_chars = yy_current_buffer->yy_buf_size;
+
+ if (yy_cp < yy_current_buffer->yy_ch_buf + 2)
+ YY_FATAL_ERROR("flex scanner push-back overflow");
+ }
+
+ *--yy_cp = (char)c;
+
+ yytext_ptr = yy_bp;
+ yy_hold_char = *yy_cp;
+ yy_c_buf_p = yy_cp;
+}
+#endif /* ifndef YY_NO_UNPUT */
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int
+yyinput()
+#else
+static int
+input()
+#endif
+{
+ int c;
+
+ *yy_c_buf_p = yy_hold_char;
+
+ if (*yy_c_buf_p == YY_END_OF_BUFFER_CHAR) {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if (yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars])
+ /* This was really a NUL. */
+ *yy_c_buf_p = '\0';
+
+ else { /* need more input */
+ int offset = yy_c_buf_p - yytext_ptr;
+ ++yy_c_buf_p;
+
+ switch (yy_get_next_buffer()) {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart(yyin);
+
+ /* fall through */
+
+ case EOB_ACT_END_OF_FILE: {
+ if (yywrap())
+ return EOF;
+
+ if (!yy_did_buffer_switch_on_eof)
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *)yy_c_buf_p; /* cast for 8-bit char's */
+ *yy_c_buf_p = '\0'; /* preserve yytext */
+ yy_hold_char = *++yy_c_buf_p;
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+#ifdef YY_USE_PROTOS
+void
+yyrestart(FILE *input_file)
+#else
+void yyrestart(input_file)
+ FILE *input_file;
+#endif
+{
+ if (!yy_current_buffer)
+ yy_current_buffer = yy_create_buffer(yyin, YY_BUF_SIZE);
+
+ yy_init_buffer(yy_current_buffer, input_file);
+ yy_load_buffer_state();
+}
+
+#ifdef YY_USE_PROTOS
+void
+yy_switch_to_buffer(YY_BUFFER_STATE new_buffer)
+#else
+void yy_switch_to_buffer(new_buffer)
+ YY_BUFFER_STATE new_buffer;
+#endif
+{
+ if (yy_current_buffer == new_buffer)
+ return;
+
+ if (yy_current_buffer) {
+ /* Flush out information for old buffer. */
+ *yy_c_buf_p = yy_hold_char;
+ yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ yy_current_buffer = new_buffer;
+ yy_load_buffer_state();
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yy_did_buffer_switch_on_eof = 1;
+}
+
+#ifdef YY_USE_PROTOS
+void
+yy_load_buffer_state(void)
+#else
+void
+yy_load_buffer_state()
+#endif
+{
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+ yyin = yy_current_buffer->yy_input_file;
+ yy_hold_char = *yy_c_buf_p;
+}
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE
+yy_create_buffer(FILE *file, int size)
+#else
+YY_BUFFER_STATE yy_create_buffer(file, size)
+ FILE *file;
+int size;
+#endif
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE)yy_flex_alloc(sizeof(struct yy_buffer_state));
+ if (!b)
+ YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()");
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *)yy_flex_alloc(b->yy_buf_size + 2);
+ if (!b->yy_ch_buf)
+ YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()");
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer(b, file);
+
+ return b;
+}
+
+#ifdef YY_USE_PROTOS
+void
+yy_delete_buffer(YY_BUFFER_STATE b)
+#else
+void yy_delete_buffer(b)
+ YY_BUFFER_STATE b;
+#endif
+{
+ if (!b)
+ return;
+
+ if (b == yy_current_buffer)
+ yy_current_buffer = (YY_BUFFER_STATE)0;
+
+ if (b->yy_is_our_buffer)
+ yy_flex_free((void *)b->yy_ch_buf);
+
+ yy_flex_free((void *)b);
+}
+
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO((int));
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void
+yy_init_buffer(YY_BUFFER_STATE b, FILE *file)
+#else
+void yy_init_buffer(b, file)
+ YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+{
+ yy_flush_buffer(b);
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+ b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+ b->yy_is_interactive = 0;
+#else
+ b->yy_is_interactive = file ? (isatty(fileno(file)) > 0) : 0;
+#endif
+#endif
+}
+
+#ifdef YY_USE_PROTOS
+void
+yy_flush_buffer(YY_BUFFER_STATE b)
+#else
+void yy_flush_buffer(b)
+ YY_BUFFER_STATE b;
+#endif
+
+{
+ if (!b)
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if (b == yy_current_buffer)
+ yy_load_buffer_state();
+}
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE
+yy_scan_buffer(char *base, yy_size_t size)
+#else
+YY_BUFFER_STATE yy_scan_buffer(base, size) char *base;
+yy_size_t size;
+#endif
+{
+ YY_BUFFER_STATE b;
+
+ if (size < 2 ||
+ base[size - 2] != YY_END_OF_BUFFER_CHAR ||
+ base[size - 1] != YY_END_OF_BUFFER_CHAR)
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE)yy_flex_alloc(sizeof(struct yy_buffer_state));
+ if (!b)
+ YY_FATAL_ERROR("out of dynamic memory in yy_scan_buffer()");
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer(b);
+
+ return b;
+}
+#endif
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE
+yy_scan_string(yyconst char *yy_str)
+#else
+YY_BUFFER_STATE yy_scan_string(yy_str)
+ yyconst char *yy_str;
+#endif
+{
+ int len;
+ for (len = 0; yy_str[len]; ++len)
+ ;
+
+ return yy_scan_bytes(yy_str, len);
+}
+#endif
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE
+yy_scan_bytes(yyconst char *bytes, int len)
+#else
+YY_BUFFER_STATE yy_scan_bytes(bytes, len)
+ yyconst char *bytes;
+int len;
+#endif
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = len + 2;
+ buf = (char *)yy_flex_alloc(n);
+ if (!buf)
+ YY_FATAL_ERROR("out of dynamic memory in yy_scan_bytes()");
+
+ for (i = 0; i < len; ++i)
+ buf[i] = bytes[i];
+
+ buf[len] = buf[len + 1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer(buf, n);
+ if (!b)
+ YY_FATAL_ERROR("bad buffer in yy_scan_bytes()");
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+#endif
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void
+yy_push_state(int new_state)
+#else
+static void yy_push_state(new_state) int new_state;
+#endif
+{
+ if (yy_start_stack_ptr >= yy_start_stack_depth) {
+ yy_size_t new_size;
+
+ yy_start_stack_depth += YY_START_STACK_INCR;
+ new_size = yy_start_stack_depth * sizeof(int);
+
+ if (!yy_start_stack)
+ yy_start_stack = (int *)yy_flex_alloc(new_size);
+
+ else
+ yy_start_stack = (int *)yy_flex_realloc(
+ (void *)yy_start_stack, new_size);
+
+ if (!yy_start_stack)
+ YY_FATAL_ERROR(
+ "out of memory expanding start-condition stack");
+ }
+
+ yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+ BEGIN(new_state);
+}
+#endif
+
+#ifndef YY_NO_POP_STATE
+static void
+yy_pop_state()
+{
+ if (--yy_start_stack_ptr < 0)
+ YY_FATAL_ERROR("start-condition stack underflow");
+
+ BEGIN(yy_start_stack[yy_start_stack_ptr]);
+}
+#endif
+
+#ifndef YY_NO_TOP_STATE
+static int
+yy_top_state()
+{
+ return yy_start_stack[yy_start_stack_ptr - 1];
+}
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void
+yy_fatal_error(yyconst char msg[])
+#else
+static void yy_fatal_error(msg) char msg[];
+#endif
+{
+ (void)fprintf(stderr, "%s\n", msg);
+ exit(YY_EXIT_FAILURE);
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do { \
+ /* Undo effects of setting up yytext. */ \
+ yytext[yyleng] = yy_hold_char; \
+ yy_c_buf_p = yytext + n; \
+ yy_hold_char = *yy_c_buf_p; \
+ *yy_c_buf_p = '\0'; \
+ yyleng = n; \
+ } while (0)
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void
+yy_flex_strncpy(char *s1, yyconst char *s2, int n)
+#else
+static void yy_flex_strncpy(s1, s2, n) char *s1;
+yyconst char *s2;
+int n;
+#endif
+{
+ register int i;
+ for (i = 0; i < n; ++i)
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int
+yy_flex_strlen(yyconst char *s)
+#else
+static int yy_flex_strlen(s)
+ yyconst char *s;
+#endif
+{
+ register int n;
+ for (n = 0; s[n]; ++n)
+ ;
+
+ return n;
+}
+#endif
+
+#ifdef YY_USE_PROTOS
+static void *
+yy_flex_alloc(yy_size_t size)
+#else
+static void *yy_flex_alloc(size)
+ yy_size_t size;
+#endif
+{
+ return (void *)malloc(size);
+}
+
+#ifdef YY_USE_PROTOS
+static void *
+yy_flex_realloc(void *ptr, yy_size_t size)
+#else
+static void *yy_flex_realloc(ptr, size) void *ptr;
+yy_size_t size;
+#endif
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *)realloc((char *)ptr, size);
+}
+
+#ifdef YY_USE_PROTOS
+static void
+yy_flex_free(void *ptr)
+#else
+static void yy_flex_free(ptr) void *ptr;
+#endif
+{
+ free(ptr);
+}
+
+#if YY_MAIN
+int
+main()
+{
+ yylex();
+ return 0;
+}
+#endif
+#line 81 "installparse.l"
+
+/*------------------------ Program Section ----------------------------*/
+
+PRFileDesc *Pk11Install_FD = NULL;
+
+/*************************************************************************/
+/* dummy function required by lex */
+int
+Pk11Install_yywrap(void)
+{
+ return 1;
+}
+
+/*************************************************************************/
+/* Return a copy of the given string */
+static char *
+putSimpleString(char *str)
+{
+ char *tmp = (char *)PR_Malloc(strlen(str) + 1);
+ strcpy(tmp, str);
+ return tmp;
+}
+
+/*************************************************************************/
+/* Strip out quotes, replace escaped characters with what they stand for.
+ This function assumes that what is passed in is actually a complex
+ string, so error checking is lax. */
+static char *
+putComplexString(char *str)
+{
+ int size, i, j;
+ char *tmp;
+
+ if (!str) {
+ return NULL;
+ }
+ size = strlen(str);
+
+ /* Allocate the new space. This string will actually be too big,
+ since quotes and backslashes will be stripped out. But that's ok. */
+ tmp = (char *)PR_Malloc(size + 1);
+
+ /* Copy it over */
+ for (i = 0, j = 0; i < size; i++) {
+ if (str[i] == '\"') {
+ continue; /* skip un-escaped quotes */
+ } else if (str[i] == '\\') {
+ ++i; /* escaped character. skip the backslash */
+ }
+ tmp[j++] = str[i];
+ }
+ tmp[j] = '\0';
+
+ return tmp;
+}
diff --git a/security/nss/cmd/modutil/manifest.mn b/security/nss/cmd/modutil/manifest.mn
new file mode 100644
index 000000000..a92ca68c1
--- /dev/null
+++ b/security/nss/cmd/modutil/manifest.mn
@@ -0,0 +1,34 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = sectools
+
+EXPORTS =
+
+CSRCS = modutil.c \
+ pk11.c \
+ instsec.c \
+ install.c \
+ installparse.c \
+ install-ds.c \
+ lex.Pk11Install_yy.c \
+ $(NULL)
+
+CPPSRCS =
+
+PROGRAM = modutil
+
+REQUIRES = seccmd nss dbm
+
+DEFINES = -DNSPR20 -DYY_NO_UNPUT -DYY_NO_INPUT
+
+# sigh
+#INCLUDES += -I$(CORE_DEPTH)/nss/lib/pk11wrap
+
+# USE_STATIC_LIBS = 1
+
+EXTRA_LIBS = $(JAR_LIBS)
diff --git a/security/nss/cmd/modutil/modutil.c b/security/nss/cmd/modutil/modutil.c
new file mode 100644
index 000000000..02972f7b4
--- /dev/null
+++ b/security/nss/cmd/modutil/modutil.c
@@ -0,0 +1,970 @@
+/* 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/. */
+
+/* To edit this file, set TABSTOPS to 4 spaces.
+ * This is not the normal NSS convention.
+ */
+
+#include "modutil.h"
+#include "install.h"
+#include <plstr.h>
+#include "certdb.h" /* for CERT_DB_FILE_VERSION */
+#include "nss.h"
+
+static void install_error(char* message);
+static char* PR_fgets(char* buf, int size, PRFileDesc* file);
+static char* progName;
+
+/* This enum must be kept in sync with the commandNames list */
+typedef enum {
+ NO_COMMAND,
+ ADD_COMMAND,
+ CHANGEPW_COMMAND,
+ CREATE_COMMAND,
+ DEFAULT_COMMAND,
+ DELETE_COMMAND,
+ DISABLE_COMMAND,
+ ENABLE_COMMAND,
+ FIPS_COMMAND,
+ JAR_COMMAND,
+ LIST_COMMAND,
+ RAW_LIST_COMMAND,
+ RAW_ADD_COMMAND,
+ CHKFIPS_COMMAND,
+ UNDEFAULT_COMMAND
+} Command;
+
+/* This list must be kept in sync with the Command enum */
+static char* commandNames[] = {
+ "(no command)",
+ "-add",
+ "-changepw",
+ "-create",
+ "-default",
+ "-delete",
+ "-disable",
+ "-enable",
+ "-fips",
+ "-jar",
+ "-list",
+ "-rawlist",
+ "-rawadd",
+ "-chkfips",
+ "-undefault"
+};
+
+/* this enum must be kept in sync with the optionStrings list */
+typedef enum {
+ ADD_ARG = 0,
+ RAW_ADD_ARG,
+ CHANGEPW_ARG,
+ CIPHERS_ARG,
+ CREATE_ARG,
+ DBDIR_ARG,
+ DBPREFIX_ARG,
+ DEFAULT_ARG,
+ DELETE_ARG,
+ DISABLE_ARG,
+ ENABLE_ARG,
+ FIPS_ARG,
+ FORCE_ARG,
+ JAR_ARG,
+ LIBFILE_ARG,
+ LIST_ARG,
+ RAW_LIST_ARG,
+ MECHANISMS_ARG,
+ NEWPWFILE_ARG,
+ PWFILE_ARG,
+ SLOT_ARG,
+ UNDEFAULT_ARG,
+ INSTALLDIR_ARG,
+ TEMPDIR_ARG,
+ SECMOD_ARG,
+ NOCERTDB_ARG,
+ STRING_ARG,
+ CHKFIPS_ARG,
+
+ NUM_ARGS /* must be last */
+} Arg;
+
+/* This list must be kept in sync with the Arg enum */
+static char* optionStrings[] = {
+ "-add",
+ "-rawadd",
+ "-changepw",
+ "-ciphers",
+ "-create",
+ "-dbdir",
+ "-dbprefix",
+ "-default",
+ "-delete",
+ "-disable",
+ "-enable",
+ "-fips",
+ "-force",
+ "-jar",
+ "-libfile",
+ "-list",
+ "-rawlist",
+ "-mechanisms",
+ "-newpwfile",
+ "-pwfile",
+ "-slot",
+ "-undefault",
+ "-installdir",
+ "-tempdir",
+ "-secmod",
+ "-nocertdb",
+ "-string",
+ "-chkfips",
+};
+
+char* msgStrings[] = {
+ "FIPS mode enabled.\n",
+ "FIPS mode disabled.\n",
+ "Using database directory %s...\n",
+ "Creating \"%s\"...",
+ "Module \"%s\" added to database.\n",
+ "Module \"%s\" deleted from database.\n",
+ "Token \"%s\" password changed successfully.\n",
+ "Incorrect password, try again...\n",
+ "Passwords do not match, try again...\n",
+ "done.\n",
+ "Slot \"%s\" %s.\n",
+ "Successfully changed defaults.\n",
+ "Successfully changed defaults.\n",
+ "\nWARNING: Performing this operation while the browser is running could cause"
+ "\ncorruption of your security databases. If the browser is currently running,"
+ "\nyou should exit browser before continuing this operation. Type "
+ "\n'q <enter>' to abort, or <enter> to continue: ",
+ "\nAborting...\n"
+};
+
+/* Increment i if doing so would have i still be less than j. If you
+ are able to do this, return 0. Otherwise return 1. */
+#define TRY_INC(i, j) (((i + 1) < j) ? (++i, 0) : 1)
+
+/********************************************************************
+ *
+ * file-wide variables obtained from the command line
+ */
+static Command command = NO_COMMAND;
+static char* pwFile = NULL;
+static char* newpwFile = NULL;
+static char* moduleName = NULL;
+static char* moduleSpec = NULL;
+static char* slotName = NULL;
+static char* secmodName = NULL;
+static char* tokenName = NULL;
+static char* libFile = NULL;
+static char* dbdir = NULL;
+static char* dbprefix = "";
+static char* secmodString = NULL;
+static char* mechanisms = NULL;
+static char* ciphers = NULL;
+static char* fipsArg = NULL;
+static char* jarFile = NULL;
+static char* installDir = NULL;
+static char* tempDir = NULL;
+static short force = 0;
+static PRBool nocertdb = PR_FALSE;
+
+/*******************************************************************
+ *
+ * p a r s e _ a r g s
+ */
+static Error
+parse_args(int argc, char* argv[])
+{
+ int i;
+ char* arg;
+ int optionType;
+
+ /* Loop over all arguments */
+ for (i = 1; i < argc; i++) {
+ arg = argv[i];
+
+ /* Make sure this is an option and not some floating argument */
+ if (arg[0] != '-') {
+ PR_fprintf(PR_STDERR, errStrings[UNEXPECTED_ARG_ERR], argv[i]);
+ return UNEXPECTED_ARG_ERR;
+ }
+
+ /* Find which option this is */
+ for (optionType = 0; optionType < NUM_ARGS; optionType++) {
+ if (!strcmp(arg, optionStrings[optionType])) {
+ break;
+ }
+ }
+
+ /* Deal with this specific option */
+ switch (optionType) {
+ case NUM_ARGS:
+ default:
+ PR_fprintf(PR_STDERR, errStrings[UNKNOWN_OPTION_ERR], arg);
+ return UNKNOWN_OPTION_ERR;
+ break;
+ case ADD_ARG:
+ if (command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = ADD_COMMAND;
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ moduleName = argv[i];
+ break;
+ case CHANGEPW_ARG:
+ if (command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = CHANGEPW_COMMAND;
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ tokenName = argv[i];
+ break;
+ case CIPHERS_ARG:
+ if (ciphers != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ ciphers = argv[i];
+ break;
+ case CREATE_ARG:
+ if (command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = CREATE_COMMAND;
+ break;
+ case DBDIR_ARG:
+ if (dbdir != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ dbdir = argv[i];
+ break;
+ case DBPREFIX_ARG:
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ dbprefix = argv[i];
+ break;
+ case UNDEFAULT_ARG:
+ case DEFAULT_ARG:
+ if (command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ if (optionType == DEFAULT_ARG) {
+ command = DEFAULT_COMMAND;
+ } else {
+ command = UNDEFAULT_COMMAND;
+ }
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ moduleName = argv[i];
+ break;
+ case DELETE_ARG:
+ if (command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = DELETE_COMMAND;
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ moduleName = argv[i];
+ break;
+ case DISABLE_ARG:
+ if (command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = DISABLE_COMMAND;
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ moduleName = argv[i];
+ break;
+ case ENABLE_ARG:
+ if (command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = ENABLE_COMMAND;
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ moduleName = argv[i];
+ break;
+ case FIPS_ARG:
+ if (command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = FIPS_COMMAND;
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ fipsArg = argv[i];
+ break;
+ case CHKFIPS_ARG:
+ if (command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = CHKFIPS_COMMAND;
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ fipsArg = argv[i];
+ break;
+ case FORCE_ARG:
+ force = 1;
+ break;
+ case NOCERTDB_ARG:
+ nocertdb = PR_TRUE;
+ break;
+ case INSTALLDIR_ARG:
+ if (installDir != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ installDir = argv[i];
+ break;
+ case TEMPDIR_ARG:
+ if (tempDir != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ tempDir = argv[i];
+ break;
+ case JAR_ARG:
+ if (command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = JAR_COMMAND;
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ jarFile = argv[i];
+ break;
+ case LIBFILE_ARG:
+ if (libFile != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ libFile = argv[i];
+ break;
+ case LIST_ARG:
+ if (command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = LIST_COMMAND;
+ /* This option may or may not have an argument */
+ if ((i + 1 < argc) && (argv[i + 1][0] != '-')) {
+ moduleName = argv[++i];
+ }
+ break;
+ case RAW_LIST_ARG:
+ if (command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = RAW_LIST_COMMAND;
+ /* This option may or may not have an argument */
+ if ((i + 1 < argc) && (argv[i + 1][0] != '-')) {
+ moduleName = argv[++i];
+ }
+ break;
+ case RAW_ADD_ARG:
+ if (command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = RAW_ADD_COMMAND;
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ moduleSpec = argv[i];
+ break;
+ case MECHANISMS_ARG:
+ if (mechanisms != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ mechanisms = argv[i];
+ break;
+ case NEWPWFILE_ARG:
+ if (newpwFile != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ newpwFile = argv[i];
+ break;
+ case PWFILE_ARG:
+ if (pwFile != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ pwFile = argv[i];
+ break;
+ case SLOT_ARG:
+ if (slotName != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ slotName = argv[i];
+ break;
+ case SECMOD_ARG:
+ if (secmodName != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ secmodName = argv[i];
+ break;
+ case STRING_ARG:
+ if (secmodString != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if (TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ secmodString = argv[i];
+ break;
+ }
+ }
+ return SUCCESS;
+}
+
+/************************************************************************
+ *
+ * v e r i f y _ p a r a m s
+ */
+static Error
+verify_params()
+{
+ switch (command) {
+ case ADD_COMMAND:
+ if (libFile == NULL) {
+ PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
+ commandNames[ADD_COMMAND], optionStrings[LIBFILE_ARG]);
+ return MISSING_PARAM_ERR;
+ }
+ break;
+ case CHANGEPW_COMMAND:
+ break;
+ case CREATE_COMMAND:
+ break;
+ case DELETE_COMMAND:
+ break;
+ case DISABLE_COMMAND:
+ break;
+ case ENABLE_COMMAND:
+ break;
+ case FIPS_COMMAND:
+ case CHKFIPS_COMMAND:
+ if (PL_strcasecmp(fipsArg, "true") &&
+ PL_strcasecmp(fipsArg, "false")) {
+ PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
+ return INVALID_FIPS_ARG;
+ }
+ break;
+ case JAR_COMMAND:
+ if (installDir == NULL) {
+ PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
+ commandNames[JAR_COMMAND], optionStrings[INSTALLDIR_ARG]);
+ return MISSING_PARAM_ERR;
+ }
+ break;
+ case LIST_COMMAND:
+ case RAW_LIST_COMMAND:
+ break;
+ case RAW_ADD_COMMAND:
+ break;
+ case UNDEFAULT_COMMAND:
+ case DEFAULT_COMMAND:
+ if (mechanisms == NULL) {
+ PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
+ commandNames[command], optionStrings[MECHANISMS_ARG]);
+ return MISSING_PARAM_ERR;
+ }
+ break;
+ default:
+ /* Ignore this here */
+ break;
+ }
+
+ return SUCCESS;
+}
+
+/********************************************************************
+ *
+ * i n i t _ c r y p t o
+ *
+ * Does crypto initialization that all commands will require.
+ * If -nocertdb option is specified, don't open key or cert db (we don't
+ * need them if we aren't going to be verifying signatures). This is
+ * because serverland doesn't always have cert and key database files
+ * available.
+ *
+ * This function is ill advised. Names and locations of databases are
+ * private to NSS proper. Such functions only confuse other users.
+ *
+ */
+static Error
+check_crypto(PRBool create, PRBool readOnly)
+{
+ char* dir;
+ char* moddbname = NULL;
+ Error retval;
+ static const char multiaccess[] = { "multiaccess:" };
+
+ dir = SECU_ConfigDirectory(dbdir); /* dir is never NULL */
+ if (dir[0] == '\0') {
+ PR_fprintf(PR_STDERR, errStrings[NO_DBDIR_ERR]);
+ retval = NO_DBDIR_ERR;
+ goto loser;
+ }
+ if (strncmp(dir, multiaccess, sizeof multiaccess - 1) == 0) {
+ /* won't attempt to handle the multiaccess case. */
+ return SUCCESS;
+ }
+#ifdef notdef
+ /* Make sure db directory exists and is readable */
+ if (PR_Access(dir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dir);
+ retval = DIR_DOESNT_EXIST_ERR;
+ goto loser;
+ } else if (PR_Access(dir, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dir);
+ retval = DIR_NOT_READABLE_ERR;
+ goto loser;
+ }
+
+ if (secmodName == NULL) {
+ secmodName = "secmod.db";
+ }
+
+ moddbname = PR_smprintf("%s/%s", dir, secmodName);
+ if (!moddbname)
+ return OUT_OF_MEM_ERR;
+
+ /* Check for the proper permissions on databases */
+ if (create) {
+ /* Make sure dbs don't already exist, and the directory is
+ writeable */
+ if (PR_Access(moddbname, PR_ACCESS_EXISTS) == PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_ALREADY_EXISTS_ERR],
+ moddbname);
+ retval = FILE_ALREADY_EXISTS_ERR;
+ goto loser;
+ } else if (PR_Access(dir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dir);
+ retval = DIR_NOT_WRITEABLE_ERR;
+ goto loser;
+ }
+ } else {
+ /* Make sure dbs are readable and writeable */
+ if (PR_Access(moddbname, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR], moddbname);
+ retval = FILE_NOT_READABLE_ERR;
+ goto loser;
+ }
+
+ /* Check for write access if we'll be making changes */
+ if (!readOnly) {
+ if (PR_Access(moddbname, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
+ moddbname);
+ retval = FILE_NOT_WRITEABLE_ERR;
+ goto loser;
+ }
+ }
+ PR_fprintf(PR_STDOUT, msgStrings[USING_DBDIR_MSG],
+ SECU_ConfigDirectory(NULL));
+ }
+#endif
+ retval = SUCCESS;
+loser:
+ if (moddbname) {
+ PR_Free(moddbname);
+ }
+ return retval;
+}
+
+static Error
+init_crypto(PRBool create, PRBool readOnly)
+{
+
+ PRUint32 flags = 0;
+ SECStatus rv;
+ Error retval;
+ /* Open/create key database */
+
+ if (readOnly)
+ flags |= NSS_INIT_READONLY;
+ if (nocertdb)
+ flags |= NSS_INIT_NOCERTDB;
+ rv = NSS_Initialize(SECU_ConfigDirectory(NULL), dbprefix, dbprefix,
+ secmodName, flags);
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ retval = NSS_INITIALIZE_FAILED_ERR;
+ } else
+ retval = SUCCESS;
+
+ return retval;
+}
+
+/*************************************************************************
+ *
+ * u s a g e
+ */
+static void
+usage()
+{
+ PR_fprintf(PR_STDOUT,
+ "\nNetscape Cryptographic Module Utility\n"
+ "Usage: modutil [command] [options]\n\n"
+ " COMMANDS\n"
+ "---------------------------------------------------------------------------\n"
+ "-add MODULE_NAME Add the named module to the module database\n"
+ " -libfile LIBRARY_FILE The name of the file (.so or .dll)\n"
+ " containing the implementation of PKCS #11\n"
+ " [-ciphers CIPHER_LIST] Enable the given ciphers on this module\n"
+ " [-mechanisms MECHANISM_LIST] Make the module a default provider of the\n"
+ " given mechanisms\n"
+ " [-string CONFIG_STRING] Pass a configuration string to this module\n"
+ "-changepw TOKEN Change the password on the named token\n"
+ " [-pwfile FILE] The old password is in this file\n"
+ " [-newpwfile FILE] The new password is in this file\n"
+ "-chkfips [ true | false ] If true, verify FIPS mode. If false,\n"
+ " verify not FIPS mode\n"
+ "-create Create a new set of security databases\n"
+ "-default MODULE Make the given module a default provider\n"
+ " -mechanisms MECHANISM_LIST of the given mechanisms\n"
+ " [-slot SLOT] limit change to only the given slot\n"
+ "-delete MODULE Remove the named module from the module\n"
+ " database\n"
+ "-disable MODULE Disable the named module\n"
+ " [-slot SLOT] Disable only the named slot on the module\n"
+ "-enable MODULE Enable the named module\n"
+ " [-slot SLOT] Enable only the named slot on the module\n"
+ "-fips [ true | false ] If true, enable FIPS mode. If false,\n"
+ " disable FIPS mode\n"
+ "-force Do not run interactively\n"
+ "-jar JARFILE Install a PKCS #11 module from the given\n"
+ " JAR file in the PKCS #11 JAR format\n"
+ " -installdir DIR Use DIR as the root directory of the\n"
+ " installation\n"
+ " [-tempdir DIR] Use DIR as the temporary installation\n"
+ " directory. If not specified, the current\n"
+ " directory is used\n"
+ "-list [MODULE] Lists information about the specified module\n"
+ " or about all modules if none is specified\n"
+ "-rawadd MODULESPEC Add module spec string to secmod DB\n"
+ "-rawlist [MODULE] Display module spec(s) for one or all\n"
+ " loadable modules\n"
+ "-undefault MODULE The given module is NOT a default provider\n"
+ " -mechanisms MECHANISM_LIST of the listed mechanisms\n"
+ " [-slot SLOT] limit change to only the given slot\n"
+ "---------------------------------------------------------------------------\n"
+ "\n"
+ " OPTIONS\n"
+ "---------------------------------------------------------------------------\n"
+ "-dbdir DIR Directory DIR contains the security databases\n"
+ "-dbprefix prefix Prefix for the security databases\n"
+ "-nocertdb Do not load certificate or key databases. No\n"
+ " verification will be performed on JAR files.\n"
+ "-secmod secmodName Name of the security modules file\n"
+ "---------------------------------------------------------------------------\n"
+ "\n"
+ "Mechanism lists are colon-separated. The following mechanisms are recognized:\n"
+ "RSA, DSA, DH, RC2, RC4, RC5, AES, CAMELLIA, DES, MD2, MD5, SHA1, SHA256, SHA512,\n"
+ "SSL, TLS, RANDOM, and FRIENDLY\n"
+ "\n"
+ "Cipher lists are colon-separated. The following ciphers are recognized:\n"
+ "\n"
+ "\nQuestions or bug reports should be sent to modutil-support@netscape.com.\n");
+}
+
+/*************************************************************************
+ *
+ * m a i n
+ */
+int
+main(int argc, char* argv[])
+{
+ int errcode = SUCCESS;
+ PRBool createdb, readOnly;
+#define STDINBUF_SIZE 80
+ char stdinbuf[STDINBUF_SIZE];
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+
+ if (parse_args(argc, argv) != SUCCESS) {
+ usage();
+ errcode = INVALID_USAGE_ERR;
+ goto loser;
+ }
+
+ if (verify_params() != SUCCESS) {
+ usage();
+ errcode = INVALID_USAGE_ERR;
+ goto loser;
+ }
+
+ if (command == NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[NO_COMMAND_ERR]);
+ usage();
+ errcode = INVALID_USAGE_ERR;
+ goto loser;
+ }
+
+ /* Set up crypto stuff */
+ createdb = command == CREATE_COMMAND;
+ readOnly = ((command == LIST_COMMAND) ||
+ (command == CHKFIPS_COMMAND) ||
+ (command == RAW_LIST_COMMAND));
+
+ /* Make sure browser is not running if we're writing to a database */
+ /* Do this before initializing crypto */
+ if (!readOnly && !force) {
+ char* response;
+
+ PR_fprintf(PR_STDOUT, msgStrings[BROWSER_RUNNING_MSG]);
+ if (!PR_fgets(stdinbuf, STDINBUF_SIZE, PR_STDIN)) {
+ PR_fprintf(PR_STDERR, errStrings[STDIN_READ_ERR]);
+ errcode = STDIN_READ_ERR;
+ goto loser;
+ }
+ if ((response = strtok(stdinbuf, " \r\n\t"))) {
+ if (!PL_strcasecmp(response, "q")) {
+ PR_fprintf(PR_STDOUT, msgStrings[ABORTING_MSG]);
+ errcode = SUCCESS;
+ goto loser;
+ }
+ }
+ PR_fprintf(PR_STDOUT, "\n");
+ }
+
+ errcode = check_crypto(createdb, readOnly);
+ if (errcode != SUCCESS) {
+ goto loser;
+ }
+
+ if ((command == RAW_LIST_COMMAND) || (command == RAW_ADD_COMMAND)) {
+ if (!moduleName) {
+ char *readOnlyStr, *noCertDBStr, *sep;
+ if (!secmodName)
+ secmodName = "secmod.db";
+ if (!dbprefix)
+ dbprefix = "";
+ sep = ((command == RAW_LIST_COMMAND) && nocertdb) ? "," : " ";
+ readOnlyStr = (command == RAW_LIST_COMMAND) ? "readOnly" : "";
+ noCertDBStr = nocertdb ? "noCertDB" : "";
+ SECU_ConfigDirectory(dbdir);
+
+ moduleName = PR_smprintf(
+ "name=\"NSS default Module DB\" parameters=\"configdir=%s certPrefix=%s "
+ "keyPrefix=%s secmod=%s flags=%s%s%s\" NSS=\"flags=internal,moduleDB,"
+ "moduleDBOnly,critical\"",
+ SECU_ConfigDirectory(NULL), dbprefix, dbprefix,
+ secmodName, readOnlyStr, sep, noCertDBStr);
+ }
+ if (command == RAW_LIST_COMMAND) {
+ errcode = RawListModule(moduleName);
+ } else {
+ PORT_Assert(moduleSpec);
+ errcode = RawAddModule(moduleName, moduleSpec);
+ }
+ goto loser;
+ }
+
+ errcode = init_crypto(createdb, readOnly);
+ if (errcode != SUCCESS) {
+ goto loser;
+ }
+
+ errcode = LoadMechanismList();
+ if (errcode != SUCCESS) {
+ goto loser;
+ }
+
+ /* Execute the command */
+ switch (command) {
+ case ADD_COMMAND:
+ errcode = AddModule(moduleName, libFile, ciphers, mechanisms, secmodString);
+ break;
+ case CHANGEPW_COMMAND:
+ errcode = ChangePW(tokenName, pwFile, newpwFile);
+ break;
+ case CREATE_COMMAND:
+ /* The work was already done in init_crypto() */
+ break;
+ case DEFAULT_COMMAND:
+ errcode = SetDefaultModule(moduleName, slotName, mechanisms);
+ break;
+ case DELETE_COMMAND:
+ errcode = DeleteModule(moduleName);
+ break;
+ case DISABLE_COMMAND:
+ errcode = EnableModule(moduleName, slotName, PR_FALSE);
+ break;
+ case ENABLE_COMMAND:
+ errcode = EnableModule(moduleName, slotName, PR_TRUE);
+ break;
+ case FIPS_COMMAND:
+ errcode = FipsMode(fipsArg);
+ break;
+ case CHKFIPS_COMMAND:
+ errcode = ChkFipsMode(fipsArg);
+ break;
+ case JAR_COMMAND:
+ Pk11Install_SetErrorHandler(install_error);
+ errcode = Pk11Install_DoInstall(jarFile, installDir, tempDir,
+ PR_STDOUT, force, nocertdb);
+ break;
+ case LIST_COMMAND:
+ if (moduleName) {
+ errcode = ListModule(moduleName);
+ } else {
+ errcode = ListModules();
+ }
+ break;
+ case UNDEFAULT_COMMAND:
+ errcode = UnsetDefaultModule(moduleName, slotName, mechanisms);
+ break;
+ default:
+ PR_fprintf(PR_STDERR, "This command is not supported yet.\n");
+ errcode = INVALID_USAGE_ERR;
+ break;
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+loser:
+ PR_Cleanup();
+ return errcode;
+}
+
+/************************************************************************
+ *
+ * i n s t a l l _ e r r o r
+ *
+ * Callback function to handle errors in PK11 JAR file installation.
+ */
+static void
+install_error(char* message)
+{
+ PR_fprintf(PR_STDERR, "Install error: %s\n", message);
+}
+
+/*************************************************************************
+ *
+ * o u t _ o f _ m e m o r y
+ */
+void
+out_of_memory(void)
+{
+ PR_fprintf(PR_STDERR, errStrings[OUT_OF_MEM_ERR]);
+ exit(OUT_OF_MEM_ERR);
+}
+
+/**************************************************************************
+ *
+ * P R _ f g e t s
+ *
+ * fgets implemented with NSPR.
+ */
+static char*
+PR_fgets(char* buf, int size, PRFileDesc* file)
+{
+ int i;
+ int status;
+ char c;
+
+ i = 0;
+ while (i < size - 1) {
+ status = PR_Read(file, (void*)&c, 1);
+ if (status == -1) {
+ return NULL;
+ } else if (status == 0) {
+ break;
+ }
+ buf[i++] = c;
+ if (c == '\n') {
+ break;
+ }
+ }
+ buf[i] = '\0';
+
+ return buf;
+}
diff --git a/security/nss/cmd/modutil/modutil.gyp b/security/nss/cmd/modutil/modutil.gyp
new file mode 100644
index 000000000..5d0f87a65
--- /dev/null
+++ b/security/nss/cmd/modutil/modutil.gyp
@@ -0,0 +1,44 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'modutil',
+ 'type': 'executable',
+ 'sources': [
+ 'install-ds.c',
+ 'install.c',
+ 'installparse.c',
+ 'instsec.c',
+ 'lex.Pk11Install_yy.c',
+ 'modutil.c',
+ 'pk11.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports',
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/lib/jar/jar.gyp:jar',
+ '<(DEPTH)/lib/zlib/zlib.gyp:nss_zlib'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'include_dirs': [
+ '<(nss_private_dist_dir)/nss',
+ '<(nss_private_dist_dir)/dbm'
+ ],
+ 'defines': [
+ 'NSPR20',
+ 'YY_NO_UNPUT',
+ 'YY_NO_INPUT'
+ ]
+ },
+ 'variables': {
+ 'module': 'sectools'
+ }
+}
diff --git a/security/nss/cmd/modutil/modutil.h b/security/nss/cmd/modutil/modutil.h
new file mode 100644
index 000000000..127d0d0da
--- /dev/null
+++ b/security/nss/cmd/modutil/modutil.h
@@ -0,0 +1,40 @@
+/* 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 MODUTIL_H
+#define MODUTIL_H
+
+#include <stdio.h>
+#include <string.h>
+
+#include <prio.h>
+#include <prprf.h>
+#include <prinit.h>
+#include <prlock.h>
+#include <prmem.h>
+#include <plarena.h>
+
+#include "seccomon.h"
+#include "secmod.h"
+#include "secutil.h"
+
+#include "error.h"
+
+Error LoadMechanismList(void);
+Error FipsMode(char *arg);
+Error ChkFipsMode(char *arg);
+Error AddModule(char *moduleName, char *libFile, char *ciphers,
+ char *mechanisms, char *modparms);
+Error DeleteModule(char *moduleName);
+Error ListModule(char *moduleName);
+Error ListModules();
+Error ChangePW(char *tokenName, char *pwFile, char *newpwFile);
+Error EnableModule(char *moduleName, char *slotName, PRBool enable);
+Error RawAddModule(char *dbmodulespec, char *modulespec);
+Error RawListModule(char *modulespec);
+Error SetDefaultModule(char *moduleName, char *slotName, char *mechanisms);
+Error UnsetDefaultModule(char *moduleName, char *slotName, char *mechanisms);
+void out_of_memory(void);
+
+#endif /*MODUTIL_H*/
diff --git a/security/nss/cmd/modutil/pk11.c b/security/nss/cmd/modutil/pk11.c
new file mode 100644
index 000000000..9c460ecd8
--- /dev/null
+++ b/security/nss/cmd/modutil/pk11.c
@@ -0,0 +1,960 @@
+/* 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/. */
+
+/* To edit this file, set TABSTOPS to 4 spaces.
+ * This is not the normal NSS convention.
+ */
+
+#include "modutil.h"
+#include "pk11func.h"
+
+/*************************************************************************
+ *
+ * F i p s M o d e
+ * If arg=="true", enable FIPS mode on the internal module. If arg=="false",
+ * disable FIPS mode on the internal module.
+ */
+Error
+FipsMode(char *arg)
+{
+ char *internal_name;
+
+ if (!PORT_Strcasecmp(arg, "true")) {
+ if (!PK11_IsFIPS()) {
+ internal_name = PR_smprintf("%s",
+ SECMOD_GetInternalModule()->commonName);
+ if (SECMOD_DeleteInternalModule(internal_name) != SECSuccess) {
+ PR_fprintf(PR_STDERR, "%s\n", SECU_Strerror(PORT_GetError()));
+ PR_smprintf_free(internal_name);
+ PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
+ return FIPS_SWITCH_FAILED_ERR;
+ }
+ PR_smprintf_free(internal_name);
+ if (!PK11_IsFIPS()) {
+ PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
+ return FIPS_SWITCH_FAILED_ERR;
+ }
+ PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]);
+ } else {
+ PR_fprintf(PR_STDERR, errStrings[FIPS_ALREADY_ON_ERR]);
+ return FIPS_ALREADY_ON_ERR;
+ }
+ } else if (!PORT_Strcasecmp(arg, "false")) {
+ if (PK11_IsFIPS()) {
+ internal_name = PR_smprintf("%s",
+ SECMOD_GetInternalModule()->commonName);
+ if (SECMOD_DeleteInternalModule(internal_name) != SECSuccess) {
+ PR_fprintf(PR_STDERR, "%s\n", SECU_Strerror(PORT_GetError()));
+ PR_smprintf_free(internal_name);
+ PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
+ return FIPS_SWITCH_FAILED_ERR;
+ }
+ PR_smprintf_free(internal_name);
+ if (PK11_IsFIPS()) {
+ PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
+ return FIPS_SWITCH_FAILED_ERR;
+ }
+ PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]);
+ } else {
+ PR_fprintf(PR_STDERR, errStrings[FIPS_ALREADY_OFF_ERR]);
+ return FIPS_ALREADY_OFF_ERR;
+ }
+ } else {
+ PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
+ return INVALID_FIPS_ARG;
+ }
+
+ return SUCCESS;
+}
+
+/*************************************************************************
+ *
+ * C h k F i p s M o d e
+ * If arg=="true", verify FIPS mode is enabled on the internal module.
+ * If arg=="false", verify FIPS mode is disabled on the internal module.
+ */
+Error
+ChkFipsMode(char *arg)
+{
+ if (!PORT_Strcasecmp(arg, "true")) {
+ if (PK11_IsFIPS()) {
+ PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]);
+ } else {
+ PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]);
+ return FIPS_SWITCH_FAILED_ERR;
+ }
+
+ } else if (!PORT_Strcasecmp(arg, "false")) {
+ if (!PK11_IsFIPS()) {
+ PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]);
+ } else {
+ PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]);
+ return FIPS_SWITCH_FAILED_ERR;
+ }
+ } else {
+ PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
+ return INVALID_FIPS_ARG;
+ }
+
+ return SUCCESS;
+}
+
+/************************************************************************
+ * Cipher and Mechanism name-bitmask translation tables
+ */
+
+typedef struct {
+ const char *name;
+ unsigned long mask;
+} MaskString;
+
+static const MaskString cipherStrings[] = {
+ { "FORTEZZA", PUBLIC_CIPHER_FORTEZZA_FLAG }
+};
+static const int numCipherStrings =
+ sizeof(cipherStrings) / sizeof(cipherStrings[0]);
+
+/* Initialized by LoadMechanismList */
+static MaskString *mechanismStrings = NULL;
+static int numMechanismStrings = 0;
+const static PK11DefaultArrayEntry *pk11_DefaultArray = NULL;
+static int pk11_DefaultArraySize = 0;
+
+/* Maximum length of a colon-separated list of all the strings in an
+ * array. */
+#define MAX_STRING_LIST_LEN 240 /* or less */
+
+Error
+LoadMechanismList(void)
+{
+ int i;
+
+ if (pk11_DefaultArray == NULL) {
+ pk11_DefaultArray = PK11_GetDefaultArray(&pk11_DefaultArraySize);
+ if (pk11_DefaultArray == NULL) {
+ /* should assert. This shouldn't happen */
+ return UNSPECIFIED_ERR;
+ }
+ }
+ if (mechanismStrings != NULL) {
+ return SUCCESS;
+ }
+
+ /* build the mechanismStrings array */
+ mechanismStrings = PORT_NewArray(MaskString, pk11_DefaultArraySize);
+ if (mechanismStrings == NULL) {
+ return OUT_OF_MEM_ERR;
+ }
+ numMechanismStrings = pk11_DefaultArraySize;
+ for (i = 0; i < numMechanismStrings; i++) {
+ const char *name = pk11_DefaultArray[i].name;
+ unsigned long flag = pk11_DefaultArray[i].flag;
+ /* map new name to old */
+ switch (flag) {
+ case SECMOD_FORTEZZA_FLAG:
+ name = "FORTEZZA";
+ break;
+ case SECMOD_SHA1_FLAG:
+ name = "SHA1";
+ break;
+ case SECMOD_CAMELLIA_FLAG:
+ name = "CAMELLIA";
+ break;
+ case SECMOD_RANDOM_FLAG:
+ name = "RANDOM";
+ break;
+ case SECMOD_FRIENDLY_FLAG:
+ name = "FRIENDLY";
+ break;
+ default:
+ break;
+ }
+ mechanismStrings[i].name = name;
+ mechanismStrings[i].mask = SECMOD_InternaltoPubMechFlags(flag);
+ }
+ return SUCCESS;
+}
+
+/************************************************************************
+ *
+ * g e t F l a g s F r o m S t r i n g
+ *
+ * Parses a mechanism list passed on the command line and converts it
+ * to an unsigned long bitmask.
+ * string is a colon-separated string of constants
+ * array is an array of MaskStrings.
+ * elements is the number of elements in array.
+ */
+static unsigned long
+getFlagsFromString(char *string, const MaskString array[], int elements)
+{
+ unsigned long ret = 0;
+ short i = 0;
+ char *cp;
+ char *buf;
+ char *end;
+
+ if (!string || !string[0]) {
+ return ret;
+ }
+
+ /* Make a temporary copy of the string */
+ buf = PR_Malloc(strlen(string) + 1);
+ if (!buf) {
+ out_of_memory();
+ }
+ strcpy(buf, string);
+
+ /* Look at each element of the list passed in */
+ for (cp = buf; cp && *cp; cp = (end ? end + 1 : NULL)) {
+ /* Look at the string up to the next colon */
+ end = strchr(cp, ':');
+ if (end) {
+ *end = '\0';
+ }
+
+ /* Find which element this is */
+ for (i = 0; i < elements; i++) {
+ if (!PORT_Strcasecmp(cp, array[i].name)) {
+ break;
+ }
+ }
+ if (i == elements) {
+ /* Skip a bogus string, but print a warning message */
+ PR_fprintf(PR_STDERR, errStrings[INVALID_CONSTANT_ERR], cp);
+ continue;
+ }
+ ret |= array[i].mask;
+ }
+
+ PR_Free(buf);
+ return ret;
+}
+
+/**********************************************************************
+ *
+ * g e t S t r i n g F r o m F l a g s
+ *
+ * The return string's memory is owned by this function. Copy it
+ * if you need it permanently or you want to change it.
+ */
+static char *
+getStringFromFlags(unsigned long flags, const MaskString array[], int elements)
+{
+ static char buf[MAX_STRING_LIST_LEN];
+ int i;
+ int count = 0;
+
+ buf[0] = '\0';
+ for (i = 0; i < elements; i++) {
+ if (flags & array[i].mask) {
+ ++count;
+ if (count != 1) {
+ strcat(buf, ":");
+ }
+ strcat(buf, array[i].name);
+ }
+ }
+ return buf;
+}
+
+/**********************************************************************
+ *
+ * A d d M o d u l e
+ *
+ * Add the named module, with the given library file, ciphers, and
+ * default mechanism flags
+ */
+Error
+AddModule(char *moduleName, char *libFile, char *cipherString,
+ char *mechanismString, char *modparms)
+{
+ unsigned long ciphers;
+ unsigned long mechanisms;
+ SECStatus status;
+
+ mechanisms =
+ getFlagsFromString(mechanismString, mechanismStrings,
+ numMechanismStrings);
+ ciphers =
+ getFlagsFromString(cipherString, cipherStrings, numCipherStrings);
+
+ status =
+ SECMOD_AddNewModuleEx(moduleName, libFile,
+ SECMOD_PubMechFlagstoInternal(mechanisms),
+ SECMOD_PubCipherFlagstoInternal(ciphers),
+ modparms, NULL);
+
+ if (status != SECSuccess) {
+ char *errtxt = NULL;
+ PRInt32 copied = 0;
+ if (PR_GetErrorTextLength()) {
+ errtxt = PR_Malloc(PR_GetErrorTextLength() + 1);
+ copied = PR_GetErrorText(errtxt);
+ }
+ if (copied && errtxt) {
+ PR_fprintf(PR_STDERR, errStrings[ADD_MODULE_FAILED_ERR],
+ moduleName, errtxt);
+ PR_Free(errtxt);
+ } else {
+ PR_fprintf(PR_STDERR, errStrings[ADD_MODULE_FAILED_ERR],
+ moduleName, SECU_Strerror(PORT_GetError()));
+ }
+ return ADD_MODULE_FAILED_ERR;
+ } else {
+ PR_fprintf(PR_STDOUT, msgStrings[ADD_MODULE_SUCCESS_MSG], moduleName);
+ return SUCCESS;
+ }
+}
+
+/***********************************************************************
+ *
+ * D e l e t e M o d u l e
+ *
+ * Deletes the named module from the database.
+ */
+Error
+DeleteModule(char *moduleName)
+{
+ SECStatus status;
+ int type;
+
+ status = SECMOD_DeleteModule(moduleName, &type);
+
+ if (status != SECSuccess) {
+ if (type == SECMOD_FIPS || type == SECMOD_INTERNAL) {
+ PR_fprintf(PR_STDERR, errStrings[DELETE_INTERNAL_ERR]);
+ return DELETE_INTERNAL_ERR;
+ } else {
+ PR_fprintf(PR_STDERR, errStrings[DELETE_FAILED_ERR], moduleName);
+ return DELETE_FAILED_ERR;
+ }
+ }
+
+ PR_fprintf(PR_STDOUT, msgStrings[DELETE_SUCCESS_MSG], moduleName);
+ return SUCCESS;
+}
+
+/************************************************************************
+ *
+ * R a w L i s t M o d u l e s
+ *
+ * Lists all the modules in the database, along with their slots and tokens.
+ */
+Error
+RawListModule(char *modulespec)
+{
+ SECMODModule *module;
+ char **moduleSpecList;
+
+ module = SECMOD_LoadModule(modulespec, NULL, PR_FALSE);
+ if (module == NULL) {
+ /* handle error */
+ return NO_SUCH_MODULE_ERR;
+ }
+
+ moduleSpecList = SECMOD_GetModuleSpecList(module);
+ if (!moduleSpecList || !moduleSpecList[0]) {
+ SECU_PrintError("modutil",
+ "no specs in secmod DB");
+ return NO_SUCH_MODULE_ERR;
+ }
+
+ for (; *moduleSpecList; moduleSpecList++) {
+ printf("%s\n\n", *moduleSpecList);
+ }
+
+ return SUCCESS;
+}
+
+Error
+RawAddModule(char *dbmodulespec, char *modulespec)
+{
+ SECMODModule *module;
+ SECMODModule *dbmodule;
+
+ dbmodule = SECMOD_LoadModule(dbmodulespec, NULL, PR_TRUE);
+ if (dbmodule == NULL) {
+ /* handle error */
+ return NO_SUCH_MODULE_ERR;
+ }
+
+ module = SECMOD_LoadModule(modulespec, dbmodule, PR_FALSE);
+ if (module == NULL) {
+ /* handle error */
+ return NO_SUCH_MODULE_ERR;
+ }
+
+ if (SECMOD_UpdateModule(module) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[UPDATE_MOD_FAILED_ERR], modulespec);
+ return UPDATE_MOD_FAILED_ERR;
+ }
+ return SUCCESS;
+}
+
+static void
+printModule(SECMODModule *module, int *count)
+{
+ int slotCount = module->loaded ? module->slotCount : 0;
+ int i;
+
+ if ((*count)++) {
+ PR_fprintf(PR_STDOUT, "\n");
+ }
+ PR_fprintf(PR_STDOUT, "%3d. %s\n", *count, module->commonName);
+
+ if (module->dllName) {
+ PR_fprintf(PR_STDOUT, "\tlibrary name: %s\n", module->dllName);
+ }
+
+ if (slotCount == 0) {
+ PR_fprintf(PR_STDOUT,
+ "\t slots: There are no slots attached to this module\n");
+ } else {
+ PR_fprintf(PR_STDOUT, "\t slots: %d slot%s attached\n",
+ slotCount, (slotCount == 1 ? "" : "s"));
+ }
+
+ if (module->loaded == 0) {
+ PR_fprintf(PR_STDOUT, "\tstatus: Not loaded\n");
+ } else {
+ PR_fprintf(PR_STDOUT, "\tstatus: loaded\n");
+ }
+
+ /* Print slot and token names */
+ for (i = 0; i < slotCount; i++) {
+ PK11SlotInfo *slot = module->slots[i];
+
+ PR_fprintf(PR_STDOUT, "\n");
+ PR_fprintf(PR_STDOUT, "\t slot: %s\n", PK11_GetSlotName(slot));
+ PR_fprintf(PR_STDOUT, "\ttoken: %s\n", PK11_GetTokenName(slot));
+ }
+ return;
+}
+
+/************************************************************************
+ *
+ * L i s t M o d u l e s
+ *
+ * Lists all the modules in the database, along with their slots and tokens.
+ */
+Error
+ListModules()
+{
+ SECMODListLock *lock;
+ SECMODModuleList *list;
+ SECMODModuleList *deadlist;
+ SECMODModuleList *mlp;
+ Error ret = UNSPECIFIED_ERR;
+ int count = 0;
+
+ lock = SECMOD_GetDefaultModuleListLock();
+ if (!lock) {
+ PR_fprintf(PR_STDERR, errStrings[NO_LIST_LOCK_ERR]);
+ return NO_LIST_LOCK_ERR;
+ }
+
+ SECMOD_GetReadLock(lock);
+
+ list = SECMOD_GetDefaultModuleList();
+ deadlist = SECMOD_GetDeadModuleList();
+ if (!list && !deadlist) {
+ PR_fprintf(PR_STDERR, errStrings[NO_MODULE_LIST_ERR]);
+ ret = NO_MODULE_LIST_ERR;
+ goto loser;
+ }
+
+ PR_fprintf(PR_STDOUT,
+ "\nListing of PKCS #11 Modules\n"
+ "-----------------------------------------------------------\n");
+
+ for (mlp = list; mlp != NULL; mlp = mlp->next) {
+ printModule(mlp->module, &count);
+ }
+ for (mlp = deadlist; mlp != NULL; mlp = mlp->next) {
+ printModule(mlp->module, &count);
+ }
+
+ PR_fprintf(PR_STDOUT,
+ "-----------------------------------------------------------\n");
+
+ ret = SUCCESS;
+
+loser:
+ SECMOD_ReleaseReadLock(lock);
+ return ret;
+}
+
+/* Strings describing PK11DisableReasons */
+static char *disableReasonStr[] = {
+ "no reason",
+ "user disabled",
+ "could not initialize token",
+ "could not verify token",
+ "token not present"
+};
+static int numDisableReasonStr =
+ sizeof(disableReasonStr) / sizeof(disableReasonStr[0]);
+
+/***********************************************************************
+ *
+ * L i s t M o d u l e
+ *
+ * Lists detailed information about the named module.
+ */
+Error
+ListModule(char *moduleName)
+{
+ SECMODModule *module = NULL;
+ PK11SlotInfo *slot;
+ int slotnum;
+ CK_INFO modinfo;
+ CK_SLOT_INFO slotinfo;
+ CK_TOKEN_INFO tokeninfo;
+ char *ciphers, *mechanisms;
+ PK11DisableReasons reason;
+ Error rv = SUCCESS;
+
+ if (!moduleName) {
+ return SUCCESS;
+ }
+
+ module = SECMOD_FindModule(moduleName);
+ if (!module) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
+ rv = NO_SUCH_MODULE_ERR;
+ goto loser;
+ }
+
+ if ((module->loaded) &&
+ (PK11_GetModInfo(module, &modinfo) != SECSuccess)) {
+ PR_fprintf(PR_STDERR, errStrings[MOD_INFO_ERR], moduleName);
+ rv = MOD_INFO_ERR;
+ goto loser;
+ }
+
+ /* Module info */
+ PR_fprintf(PR_STDOUT,
+ "\n-----------------------------------------------------------\n");
+ PR_fprintf(PR_STDOUT, "Name: %s\n", module->commonName);
+ if (module->internal || !module->dllName) {
+ PR_fprintf(PR_STDOUT, "Library file: **Internal ONLY module**\n");
+ } else {
+ PR_fprintf(PR_STDOUT, "Library file: %s\n", module->dllName);
+ }
+
+ if (module->loaded) {
+ PR_fprintf(PR_STDOUT, "Manufacturer: %.32s\n", modinfo.manufacturerID);
+ PR_fprintf(PR_STDOUT, "Description: %.32s\n", modinfo.libraryDescription);
+ PR_fprintf(PR_STDOUT, "PKCS #11 Version %d.%d\n",
+ modinfo.cryptokiVersion.major, modinfo.cryptokiVersion.minor);
+ PR_fprintf(PR_STDOUT, "Library Version: %d.%d\n",
+ modinfo.libraryVersion.major, modinfo.libraryVersion.minor);
+ } else {
+ PR_fprintf(PR_STDOUT, "* Module not loaded\n");
+ }
+ /* Get cipher and mechanism flags */
+ ciphers = getStringFromFlags(module->ssl[0], cipherStrings,
+ numCipherStrings);
+ if (ciphers[0] == '\0') {
+ ciphers = "None";
+ }
+ PR_fprintf(PR_STDOUT, "Cipher Enable Flags: %s\n", ciphers);
+ mechanisms = NULL;
+ if (module->slotCount > 0) {
+ mechanisms = getStringFromFlags(
+ PK11_GetDefaultFlags(module->slots[0]),
+ mechanismStrings, numMechanismStrings);
+ }
+ if ((mechanisms == NULL) || (mechanisms[0] == '\0')) {
+ mechanisms = "None";
+ }
+ PR_fprintf(PR_STDOUT, "Default Mechanism Flags: %s\n", mechanisms);
+
+#define PAD " "
+
+ /* Loop over each slot */
+ for (slotnum = 0; slotnum < module->slotCount; slotnum++) {
+ slot = module->slots[slotnum];
+ if (PK11_GetSlotInfo(slot, &slotinfo) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[SLOT_INFO_ERR],
+ PK11_GetSlotName(slot));
+ rv = SLOT_INFO_ERR;
+ continue;
+ }
+
+ /* Slot Info */
+ PR_fprintf(PR_STDOUT, "\n" PAD "Slot: %s\n", PK11_GetSlotName(slot));
+ mechanisms = getStringFromFlags(PK11_GetDefaultFlags(slot),
+ mechanismStrings, numMechanismStrings);
+ if (mechanisms[0] == '\0') {
+ mechanisms = "None";
+ }
+ PR_fprintf(PR_STDOUT, PAD "Slot Mechanism Flags: %s\n", mechanisms);
+ PR_fprintf(PR_STDOUT, PAD "Manufacturer: %.32s\n",
+ slotinfo.manufacturerID);
+ if (PK11_IsHW(slot)) {
+ PR_fprintf(PR_STDOUT, PAD "Type: Hardware\n");
+ } else {
+ PR_fprintf(PR_STDOUT, PAD "Type: Software\n");
+ }
+ PR_fprintf(PR_STDOUT, PAD "Version Number: %d.%d\n",
+ slotinfo.hardwareVersion.major, slotinfo.hardwareVersion.minor);
+ PR_fprintf(PR_STDOUT, PAD "Firmware Version: %d.%d\n",
+ slotinfo.firmwareVersion.major, slotinfo.firmwareVersion.minor);
+ if (PK11_IsDisabled(slot)) {
+ reason = PK11_GetDisabledReason(slot);
+ if (reason < numDisableReasonStr) {
+ PR_fprintf(PR_STDOUT, PAD "Status: DISABLED (%s)\n",
+ disableReasonStr[reason]);
+ } else {
+ PR_fprintf(PR_STDOUT, PAD "Status: DISABLED\n");
+ }
+ } else {
+ PR_fprintf(PR_STDOUT, PAD "Status: Enabled\n");
+ }
+
+ if (PK11_GetTokenInfo(slot, &tokeninfo) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[TOKEN_INFO_ERR],
+ PK11_GetTokenName(slot));
+ rv = TOKEN_INFO_ERR;
+ continue;
+ }
+
+ /* Token Info */
+ PR_fprintf(PR_STDOUT, PAD "Token Name: %.32s\n",
+ tokeninfo.label);
+ PR_fprintf(PR_STDOUT, PAD "Token Manufacturer: %.32s\n",
+ tokeninfo.manufacturerID);
+ PR_fprintf(PR_STDOUT, PAD "Token Model: %.16s\n", tokeninfo.model);
+ PR_fprintf(PR_STDOUT, PAD "Token Serial Number: %.16s\n",
+ tokeninfo.serialNumber);
+ PR_fprintf(PR_STDOUT, PAD "Token Version: %d.%d\n",
+ tokeninfo.hardwareVersion.major, tokeninfo.hardwareVersion.minor);
+ PR_fprintf(PR_STDOUT, PAD "Token Firmware Version: %d.%d\n",
+ tokeninfo.firmwareVersion.major, tokeninfo.firmwareVersion.minor);
+ if (tokeninfo.flags & CKF_WRITE_PROTECTED) {
+ PR_fprintf(PR_STDOUT, PAD "Access: Write Protected\n");
+ } else {
+ PR_fprintf(PR_STDOUT, PAD "Access: NOT Write Protected\n");
+ }
+ if (tokeninfo.flags & CKF_LOGIN_REQUIRED) {
+ PR_fprintf(PR_STDOUT, PAD "Login Type: Login required\n");
+ } else {
+ PR_fprintf(PR_STDOUT, PAD
+ "Login Type: Public (no login required)\n");
+ }
+ if (tokeninfo.flags & CKF_USER_PIN_INITIALIZED) {
+ PR_fprintf(PR_STDOUT, PAD "User Pin: Initialized\n");
+ } else {
+ PR_fprintf(PR_STDOUT, PAD "User Pin: NOT Initialized\n");
+ }
+ }
+ PR_fprintf(PR_STDOUT,
+ "\n-----------------------------------------------------------\n");
+loser:
+ if (module) {
+ SECMOD_DestroyModule(module);
+ }
+ return rv;
+}
+
+/************************************************************************
+ *
+ * C h a n g e P W
+ */
+Error
+ChangePW(char *tokenName, char *pwFile, char *newpwFile)
+{
+ char *oldpw = NULL, *newpw = NULL, *newpw2 = NULL;
+ PK11SlotInfo *slot;
+ Error ret = UNSPECIFIED_ERR;
+ PRBool matching;
+
+ slot = PK11_FindSlotByName(tokenName);
+ if (!slot) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_TOKEN_ERR], tokenName);
+ return NO_SUCH_TOKEN_ERR;
+ }
+
+ /* Get old password */
+ if (!PK11_NeedUserInit(slot)) {
+ if (pwFile) {
+ oldpw = SECU_FilePasswd(NULL, PR_FALSE, pwFile);
+ if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[BAD_PW_ERR]);
+ ret = BAD_PW_ERR;
+ goto loser;
+ }
+ } else {
+ for (matching = PR_FALSE; !matching;) {
+ oldpw = SECU_GetPasswordString(NULL, "Enter old password: ");
+ if (PK11_CheckUserPassword(slot, oldpw) == SECSuccess) {
+ matching = PR_TRUE;
+ } else {
+ PR_fprintf(PR_STDOUT, msgStrings[BAD_PW_MSG]);
+ }
+ }
+ }
+ }
+
+ /* Get new password */
+ if (newpwFile) {
+ newpw = SECU_FilePasswd(NULL, PR_FALSE, newpwFile);
+ } else {
+ for (matching = PR_FALSE; !matching;) {
+ newpw = SECU_GetPasswordString(NULL, "Enter new password: ");
+ newpw2 = SECU_GetPasswordString(NULL, "Re-enter new password: ");
+ if (strcmp(newpw, newpw2)) {
+ PR_fprintf(PR_STDOUT, msgStrings[PW_MATCH_MSG]);
+ PORT_ZFree(newpw, strlen(newpw));
+ PORT_ZFree(newpw2, strlen(newpw2));
+ } else {
+ matching = PR_TRUE;
+ }
+ }
+ }
+
+ /* Change the password */
+ if (PK11_NeedUserInit(slot)) {
+ if (PK11_InitPin(slot, NULL /*ssopw*/, newpw) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[CHANGEPW_FAILED_ERR], tokenName);
+ ret = CHANGEPW_FAILED_ERR;
+ goto loser;
+ }
+ } else {
+ if (PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[CHANGEPW_FAILED_ERR], tokenName);
+ ret = CHANGEPW_FAILED_ERR;
+ goto loser;
+ }
+ }
+
+ PR_fprintf(PR_STDOUT, msgStrings[CHANGEPW_SUCCESS_MSG], tokenName);
+ ret = SUCCESS;
+
+loser:
+ if (oldpw) {
+ PORT_ZFree(oldpw, strlen(oldpw));
+ }
+ if (newpw) {
+ PORT_ZFree(newpw, strlen(newpw));
+ }
+ if (newpw2) {
+ PORT_ZFree(newpw2, strlen(newpw2));
+ }
+ PK11_FreeSlot(slot);
+
+ return ret;
+}
+
+/***********************************************************************
+ *
+ * E n a b l e M o d u l e
+ *
+ * If enable==PR_TRUE, enables the module or slot.
+ * If enable==PR_FALSE, disables the module or slot.
+ * moduleName is the name of the module.
+ * slotName is the name of the slot. It is optional.
+ */
+Error
+EnableModule(char *moduleName, char *slotName, PRBool enable)
+{
+ int i;
+ SECMODModule *module = NULL;
+ PK11SlotInfo *slot = NULL;
+ PRBool found = PR_FALSE;
+ Error rv;
+
+ module = SECMOD_FindModule(moduleName);
+ if (!module) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
+ rv = NO_SUCH_MODULE_ERR;
+ goto loser;
+ }
+
+ for (i = 0; i < module->slotCount; i++) {
+ slot = module->slots[i];
+ if (slotName && strcmp(PK11_GetSlotName(slot), slotName)) {
+ /* Not the right slot */
+ continue;
+ }
+ if (enable) {
+ if (!PK11_UserEnableSlot(slot)) {
+ PR_fprintf(PR_STDERR, errStrings[ENABLE_FAILED_ERR],
+ "enable", PK11_GetSlotName(slot));
+ rv = ENABLE_FAILED_ERR;
+ goto loser;
+ } else {
+ found = PR_TRUE;
+ PR_fprintf(PR_STDOUT, msgStrings[ENABLE_SUCCESS_MSG],
+ PK11_GetSlotName(slot), "enabled");
+ }
+ } else {
+ if (!PK11_UserDisableSlot(slot)) {
+ PR_fprintf(PR_STDERR, errStrings[ENABLE_FAILED_ERR],
+ "disable", PK11_GetSlotName(slot));
+ rv = ENABLE_FAILED_ERR;
+ goto loser;
+ } else {
+ found = PR_TRUE;
+ PR_fprintf(PR_STDOUT, msgStrings[ENABLE_SUCCESS_MSG],
+ PK11_GetSlotName(slot), "disabled");
+ }
+ }
+ }
+
+ if (slotName && !found) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName);
+ rv = NO_SUCH_SLOT_ERR;
+ goto loser;
+ }
+
+ /* Delete and re-add module to save changes */
+ if (SECMOD_UpdateModule(module) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[UPDATE_MOD_FAILED_ERR], moduleName);
+ rv = UPDATE_MOD_FAILED_ERR;
+ goto loser;
+ }
+
+ rv = SUCCESS;
+loser:
+ if (module) {
+ SECMOD_DestroyModule(module);
+ }
+ return rv;
+}
+
+/*************************************************************************
+ *
+ * S e t D e f a u l t M o d u l e
+ *
+ */
+Error
+SetDefaultModule(char *moduleName, char *slotName, char *mechanisms)
+{
+ SECMODModule *module = NULL;
+ PK11SlotInfo *slot;
+ int s, i;
+ unsigned long mechFlags = getFlagsFromString(mechanisms, mechanismStrings,
+ numMechanismStrings);
+ PRBool found = PR_FALSE;
+ Error errcode = UNSPECIFIED_ERR;
+
+ mechFlags = SECMOD_PubMechFlagstoInternal(mechFlags);
+
+ module = SECMOD_FindModule(moduleName);
+ if (!module) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
+ errcode = NO_SUCH_MODULE_ERR;
+ goto loser;
+ }
+
+ /* Go through each slot */
+ for (s = 0; s < module->slotCount; s++) {
+ slot = module->slots[s];
+
+ if ((slotName != NULL) &&
+ !((strcmp(PK11_GetSlotName(slot), slotName) == 0) ||
+ (strcmp(PK11_GetTokenName(slot), slotName) == 0))) {
+ /* we are only interested in changing the one slot */
+ continue;
+ }
+
+ found = PR_TRUE;
+
+ /* Go through each mechanism */
+ for (i = 0; i < pk11_DefaultArraySize; i++) {
+ if (pk11_DefaultArray[i].flag & mechFlags) {
+ /* Enable this default mechanism */
+ PK11_UpdateSlotAttribute(slot, &(pk11_DefaultArray[i]),
+ PR_TRUE);
+ }
+ }
+ }
+ if (slotName && !found) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName);
+ errcode = NO_SUCH_SLOT_ERR;
+ goto loser;
+ }
+
+ /* Delete and re-add module to save changes */
+ if (SECMOD_UpdateModule(module) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[DEFAULT_FAILED_ERR],
+ moduleName);
+ errcode = DEFAULT_FAILED_ERR;
+ goto loser;
+ }
+
+ PR_fprintf(PR_STDOUT, msgStrings[DEFAULT_SUCCESS_MSG]);
+
+ errcode = SUCCESS;
+loser:
+ if (module) {
+ SECMOD_DestroyModule(module);
+ }
+ return errcode;
+}
+
+/************************************************************************
+ *
+ * U n s e t D e f a u l t M o d u l e
+ */
+Error
+UnsetDefaultModule(char *moduleName, char *slotName, char *mechanisms)
+{
+ SECMODModule *module = NULL;
+ PK11SlotInfo *slot;
+ int s, i;
+ unsigned long mechFlags = getFlagsFromString(mechanisms,
+ mechanismStrings, numMechanismStrings);
+ PRBool found = PR_FALSE;
+ Error rv;
+
+ mechFlags = SECMOD_PubMechFlagstoInternal(mechFlags);
+
+ module = SECMOD_FindModule(moduleName);
+ if (!module) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
+ rv = NO_SUCH_MODULE_ERR;
+ goto loser;
+ }
+
+ for (s = 0; s < module->slotCount; s++) {
+ slot = module->slots[s];
+ if ((slotName != NULL) &&
+ !((strcmp(PK11_GetSlotName(slot), slotName) == 0) ||
+ (strcmp(PK11_GetTokenName(slot), slotName) == 0))) {
+ /* we are only interested in changing the one slot */
+ continue;
+ }
+ for (i = 0; i < pk11_DefaultArraySize; i++) {
+ if (pk11_DefaultArray[i].flag & mechFlags) {
+ PK11_UpdateSlotAttribute(slot, &(pk11_DefaultArray[i]),
+ PR_FALSE);
+ }
+ }
+ }
+ if (slotName && !found) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName);
+ rv = NO_SUCH_SLOT_ERR;
+ goto loser;
+ }
+
+ /* Delete and re-add module to save changes */
+ if (SECMOD_UpdateModule(module) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[UNDEFAULT_FAILED_ERR],
+ moduleName);
+ rv = UNDEFAULT_FAILED_ERR;
+ goto loser;
+ }
+
+ PR_fprintf(PR_STDOUT, msgStrings[UNDEFAULT_SUCCESS_MSG]);
+ rv = SUCCESS;
+loser:
+ if (module) {
+ SECMOD_DestroyModule(module);
+ }
+ return rv;
+}
diff --git a/security/nss/cmd/modutil/pk11jar.html b/security/nss/cmd/modutil/pk11jar.html
new file mode 100644
index 000000000..bb50b8f3e
--- /dev/null
+++ b/security/nss/cmd/modutil/pk11jar.html
@@ -0,0 +1,279 @@
+<html>
+<!-- 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/. -->
+<head>
+<title>PKCS #11 JAR Format</title>
+</head>
+<body bgcolor=white text=black link=blue vlink=purple alink=red>
+<center><h1>PKCS #11 JAR Format</h1></center>
+
+<p>PKCS #11 modules can be packaged into JAR files that support automatic
+installation onto the filesystem and into the security module database.
+The JAR file should contain:
+<ul>
+<li>All files that will be installed onto the target machine. This will
+include at least the PKCS #11 module library file (.DLL or .so), and
+may also include any other file that should be installed (such as
+documentation).
+<li>A script to perform the installation.
+</ul>
+The script can be in one of two forms. If the JAR file is to be
+run by Communicator (or any program that interprets Javascript), the
+instructions will be in the form of a SmartUpdate script.
+<a href="http://devedge/library/documentation/security/jmpkcs/">Documentation
+</a> on creating this script can be found on DevEdge.
+
+<p>If the
+JAR file is to be run by a server, modutil, or any other program that
+doesn't interpret Javascript, a special information file must be included
+in the format described in this document.
+
+<h2>Declaring the Script in the Manifest File</h2>
+The script can have any name, but it must be declared in the manifest file
+of the JAR archive. The metainfo tag for this is
+<code>Pkcs11_install_script</code>. Meta-information is put in the manifest
+file by putting it in a file which is passed to
+<a href="http://developer.netscape.com/software/index_frame.html?content=signedobj/jarpack.html#signtool1.3">Signtool</a>. For example,
+suppose the PKCS #11 installer script is in the file <code>pk11install</code>.
+In Signtool's metainfo file, you would have a line like this:
+<blockquote><pre>
++ Pkcs11_install_script: pk11install
+</pre></blockquote>
+
+<h2>Sample Script File</h2>
+<blockquote><pre>
+ForwardCompatible { IRIX:6.2:mips Solaris:5.5.1:sparc }
+Platforms {
+ WINNT::x86 {
+ ModuleName { "Fortezza Module" }
+ ModuleFile { win32/fort32.dll }
+ DefaultMechanismFlags{0x0001}
+ DefaultCipherFlags{0x0001}
+ Files {
+ win32/setup.exe {
+ Executable
+ RelativePath { %temp%/setup.exe }
+ }
+ win32/setup.hlp {
+ RelativePath { %temp%/setup.hlp }
+ }
+ win32/setup.cab {
+ RelativePath { %temp%/setup.cab }
+ }
+ }
+ }
+ WIN95::x86 {
+ EquivalentPlatform {WINNT::x86}
+ }
+ Solaris:5.5.1:sparc {
+ ModuleName { "Fortezza UNIX Module" }
+ ModuleFile { unix/fort.so }
+ DefaultMechanismFlags{0x0001}
+ CipherEnableFlags{0x0001}
+ Files {
+ unix/fort.so {
+ RelativePath{%root%/lib/fort.so}
+ AbsolutePath{/usr/local/netscape/lib/fort.so}
+ FilePermissions{555}
+ }
+ xplat/instr.html {
+ RelativePath{%root%/docs/inst.html}
+ AbsolutePath{/usr/local/netscape/docs/inst.html}
+ FilePermissions{555}
+ }
+ }
+ }
+ IRIX:6.2:mips {
+ EquivalentPlatform { Solaris:5.5.1:sparc }
+ }
+}
+</pre></blockquote>
+
+<hr>
+
+<h2>Script File Grammar</h2>
+<blockquote><pre>
+--> <i>valuelist</i>
+
+<i>valuelist</i> --> <i>value</i> <i>valuelist</i>
+<i> </i> <i>&lt;null&gt;</i>
+
+<i>value</i> --> <i>key_value_pair</i>
+<i> </i> <i>string</i>
+
+<i>key_value_pair</i> --> <i>key</i> { <i>valuelist</i> }
+
+<i>key</i> --> <i>string</i>
+
+<i>string</i> --> <i>simple_string</i>
+<i> </i> "<i>complex_string</i>"
+
+<i>simple_string</i> --> [^ \t\n\""{""}"]+ <font size=-1><i>(no whitespace, quotes, or braces)</i></font>
+
+<i>complex_string</i> --> ([^\"\\\r\n]|(\\\")|(\\\\))+ <font size=-1><i>(quotes and backslashes must be escaped with a backslash, no newlines or carriage returns are allowed in the string)</i></font>
+</pre></blockquote>
+Outside of complex strings, all whitespace (space, tab, newline) is considered
+equal and is used only to delimit tokens.
+
+<hr>
+
+<h2>Keys</h2>
+Keys are case-insensitive.
+<h3>Global Keys</h3>
+<dl>
+<dt><code>ForwardCompatible</code>
+<dd>Gives a list of platforms that are forward compatible. If the current
+platform cannot be found in the list of supported platforms, then the
+ForwardCompatible list will be checked for any platforms that have the same
+OS and architecture and an earlier version. If one is found, its
+attributes will be used for the current platform.
+<dt><code>Platforms</code> (<i>required</i>)
+<dd>Gives a list of platforms. Each entry in the list is itself a key-value
+pair:
+the key is the name of the platform, and the valuelist contains various
+attributes of the platform. The ModuleName, ModuleFile, and Files attributes
+must be specified, unless an EquivalentPlatform attribute is specified.
+The platform string is in the following
+format: <u><i>system name</i></u>:<u><i>os release</i></u>:<u><i>architecture</i></u>. The installer
+will obtain these values from NSPR. <u><i>os release</i></u> is an empty
+string on non-UNIX operating systems. The following system names and platforms
+are currently defined by NSPR:<code>
+<ul>
+<li>AIX (rs6000)
+<li>BSDI (x86)
+<li>FREEBSD (x86)
+<li>HPUX (hppa1.1)
+<li>IRIX (mips)
+<li>LINUX (ppc, alpha, x86)
+<li>MacOS (PowerPC) </code>(<i>Note: NSPR actually defines the OS as
+"</i><code>Mac OS</code><i>". The
+space makes the name unsuitable for being embedded in identifiers. Until
+NSPR changes, you will have to add some special code to deal with this case.
+</i>)<code>
+<li>NCR (x86)
+<li>NEC (mips)
+<li>OS2 (x86)
+<li>OSF (alpha)
+<li>ReliantUNIX (mips)
+<li>SCO (x86)
+<li>SOLARIS (sparc)
+<li>SONY (mips)
+<li>SUNOS (sparc)
+<li>UnixWare (x86)
+<li>WIN95 (x86)
+<li>WINNT (x86)
+</ul>
+</code>
+Examples of valid platform strings: <code>IRIX:6.2:mips, Solaris:5.5.1:sparc,
+Linux:2.0.32:x86, WIN95::x86</code>.
+</dl>
+
+<h3>Per-Platform Keys</h3>
+These keys only have meaning within the value list of an entry in
+the <code>Platforms</code> list.
+<dl>
+<dt><code>ModuleName</code> (<i>required</i>)
+<dd>Gives the common name for the module. This name will be used to
+reference the module from Communicator, modutil, servers, or any other
+program that uses the Netscape security module database.
+<dt><code>ModuleFile</code> (<i>required</i>)
+<dd>Names the PKCS #11 module file (DLL or .so) for this platform. The name
+is given as the relative path of the file within the JAR archive.
+<dt><code>Files</code> (<i>required</i>)
+<dd>Lists the files that should be installed for this module. Each entry
+in the file list is a key-value pair: the key is the path of the file in
+the JAR archive, and
+the valuelist contains attributes of the file. At least RelativePath and
+AbsoluteDir must be specified in this valuelist.
+<dt><code>DefaultMechanismFlags</code>
+<dd>This key-value pair specifies
+of which mechanisms this module will be a default provider. It is a bitstring
+specified in hexadecimal (0x) format. It is constructed as a bitwise OR
+of the following constants. If the <code>DefaultMechanismFlags</code>
+entry is omitted, the value will default to 0x0.
+<blockquote><pre>
+RSA: 0x0000 0001
+DSA: 0x0000 0002
+RC2: 0x0000 0004
+RC4: 0x0000 0008
+DES: 0x0000 0010
+DH: 0x0000 0020
+FORTEZZA: 0x0000 0040
+RC5: 0x0000 0080
+SHA1: 0x0000 0100
+MD5: 0x0000 0200
+MD2: 0x0000 0400
+RANDOM: 0x0800 0000
+FRIENDLY: 0x1000 0000
+OWN_PW_DEFAULTS: 0x2000 0000
+DISABLE: 0x4000 0000
+</pre></blockquote>
+<dt><code>CipherEnableFlags</code>
+<dd>This key-value pair specifies
+which SSL ciphers will be enabled. It is a bitstring specified in
+hexadecimal (0x) format. It is constructed as a bitwise OR of the following
+constants. If the <code>CipherEnableFlags</code> entry is omitted, the
+value will default to 0x0.
+<blockquote><pre>
+FORTEZZA: 0x0000 0001
+</pre></blockquote>
+<dt><code>EquivalentPlatform</code>
+<dd>Specifies that the attributes of the named platform should also be used
+for the current platform. Saves typing when there is more than one platform
+that uses the same settings.
+</dl>
+
+<h3>Per-File Keys</h3>
+These keys only have meaning within the valuelist of an entry in a
+<code>Files</code> list. At least one of <code>RelativePath</code> and
+<code>AbsolutePath</code> must be specified. If both are specified, the
+relative path will be tried first and the absolute path used only if no
+relative root directory is provided by the installer program.
+<dl>
+<dt><code>RelativePath</code>
+<dd>Specifies the destination directory of the file, relative to some directory
+decided at install-time. Two variables can be used in the relative
+path, "%root%" and "%temp%". "%root%" will be replaced at run-time with
+the directory relative to which files should be installed; for
+example, it may be the server's root directory or Communicator's root
+directory. "%temp%" is a directory that will be created at the beginning
+of the installation and destroyed at the end of the installation. Its purpose
+is to hold executable files (such as setup programs), or files that are
+used by these programs. For example, a Windows installation might consist
+of a <code>setup.exe</code> installation program, a help file, and a .cab file
+containing compressed information. All these files could be installed into the
+temporary directory. Files destined for the temporary directory are guaranteed
+to be in place before any executable file is run, and will not be deleted
+until all executable files have finished.
+<dt><code>AbsoluteDir</code>
+<dd>Specifies the destination directory of the file as an absolute path.
+This will only be used if the installer is unable to determine a
+relative directory.
+<dt><code>Executable</code>
+<dd>This string specifies that the file is to be executed during the
+course of the
+installation. Typically this would be used for a setup program provided
+by a module vendor, such as a self-extracting <code>setup.exe</code>.
+More than one file can be specified as executable, in which case they will
+be run in the order they are specified in the script file.
+<dt><code>FilePermissions</code>
+<dd>This string is interpreted as a string of octal digits, according to the
+standard UNIX format. It is a bitwise OR of the following constants:
+<blockquote><pre>
+user read: 400
+user write: 200
+user execute: 100
+group read: 040
+group write: 020
+group execute: 010
+other read: 004
+other write: 002
+other execute: 001
+</pre></blockquote>
+Some platforms may not understand these permissions. They will only be
+applied insofar as makes sense for the current platform. If this attribute
+is omitted, a default of 777 is assumed.
+
+</body>
+</html>
diff --git a/security/nss/cmd/modutil/rules.mk b/security/nss/cmd/modutil/rules.mk
new file mode 100644
index 000000000..3ad6a97f1
--- /dev/null
+++ b/security/nss/cmd/modutil/rules.mk
@@ -0,0 +1,26 @@
+#
+# 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/.
+
+#
+# Some versions of yacc generate files that include platform-specific
+# system headers. For example, the yacc in Solaris 2.6 inserts
+# #include <values.h>
+# which does not exist on NT. For portability, always use Berkeley
+# yacc (such as the yacc in Linux) to generate files.
+#
+
+generate: installparse.c installparse.l
+
+installparse.c:
+ yacc -p Pk11Install_yy -d installparse.y
+ mv y.tab.c installparse.c
+ mv y.tab.h installparse.h
+
+installparse.l:
+ lex -olex.Pk11Install_yy.c -PPk11Install_yy installparse.l
+ @echo
+ @echo "**YOU MUST COMMENT OUT UNISTD.H FROM lex.Pk11Install_yy.cpp**"
+
+install.c: install-ds.h install.h
diff --git a/security/nss/cmd/modutil/specification.html b/security/nss/cmd/modutil/specification.html
new file mode 100644
index 000000000..6477a37ce
--- /dev/null
+++ b/security/nss/cmd/modutil/specification.html
@@ -0,0 +1,322 @@
+<html>
+<!-- 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/. -->
+<head>
+<title>Modutil Specification</title>
+</head>
+<body bgcolor=white fgcolor=black>
+<center><h1>PKCS #11 Module Management Utility
+<br><i>Specification</i></h1></center>
+
+<!---------------------------------------------------------------------->
+<!-------------------------- capabilities ------------------------------>
+<!---------------------------------------------------------------------->
+<h2>Capabilities</h2>
+<ul>
+<li>Add a PKCS #11 module, specifying a name and library file.
+(<a href="#add">-add</a>)
+<li>Add a PKCS #11 module from a server-formatted JAR file.
+(<a href="#jar">-jar</a>)
+<li>Change the password on or initialize a token.
+(<a href="#changepw">-changepw</a>)
+<li>Create databases (secmod[ule].db, key3.db, cert7.db) from scratch.
+(<a href="#create">-create</a>)
+<li>Switch to and from FIPS-140 compliant mode.
+(<a href="#fips">-fips</a>)
+<li>Delete a PKCS #11 module. (<a href="#delete">-delete</a>)
+<li>List installed PKCS #11 modules. (<a href="#list">-list</a>)
+<li>List detailed info on a particular module and its tokens, including
+whether needs login, is hardware, needs user init
+(<a href="#list">-list</a>)
+<li>Specify which modules should be the default provider of various
+cryptographic operations.(<a href="#default">-default</a>,
+<a href="#undefault">-undefault</a>)
+<li>Disable and enable slots, find out whether and why they are disabled.
+(<a href="#disable">-disable</a>, <a href="#enable">-enable</a>,
+<a href="#list">-list</a>)
+</ul>
+
+<hr>
+
+<!---------------------------------------------------------------------->
+<!-------------------------- Usage ------------------------------------->
+<!---------------------------------------------------------------------->
+<h2>Usage</h2>
+<code>modutil [<i>command</i>] [<i>options</i>]</code>
+<p>At most one command can be specified. With no arguments,
+<code>modutil</code> prints a usage message.
+<h3>Commands:</h3>
+<table border>
+<tr bgcolor="#cccccc">
+<th>Command</th><th>Description</th>
+</tr>
+
+<!---------------------------- -add ------------------------------>
+<tr>
+<td> <a name="add"></a>
+<code>-add <u><i>module name</i></u> -libfile <u><i>library file</i></u>
+ [-ciphers <u><i>cipher enable list</i></u>]
+ [-mechanisms <u><i>default mechanism list</i></u>]
+</code></td>
+<td>Adds a new module to the database with the given name.
+
+<p><u><i>library file</i></u> is the path of the DLL or other library file
+containing the module's implementation of the PKCS #11 interface.
+
+<p><u><i>cipher enable flags</i></u> is a colon-separated list of ciphers
+that will be enabled on this module. The list should be enclosed within quotes
+if necessary to prevent shell interpretation. The following ciphers are
+currently available:
+<ul>
+<li>FORTEZZA
+</ul>
+
+<p><u><i>default mechanism flags</i></u> is a colon-separated list of
+mechanisms for which this module should be the default provider. The
+list should be enclosed within quotes if necessary to prevent shell
+interpretation. <b>This
+list does not enable the mechanisms; it only specifies that this module
+will be a default provider for the listed mechanisms.</b> If more than
+one module claims to be a default provider for a given mechanism, it is
+undefined which will actually be chosen to provide that mechanism. The
+following mechanisms are currently available:
+<ul>
+<li>RSA
+<li>DSA
+<li>RC2
+<li>RC4
+<li>RC5
+<li>DES
+<li>DH
+<li>FORTEZZA
+<li>SHA1
+<li>MD5
+<li>MD2
+<li>RANDOM <i>(random number generation)</i>
+<li>FRIENDLY <i>(certificates are publicly-readable)</i>
+</ul>
+</td>
+</tr>
+
+<!-------------------------- -changepw ------------------------------------->
+<tr>
+<td><a name="changepw"></a><code>-changepw <u><i>token name</i></u>
+[-pwfile <u><i>old password file</i></u>]
+[-newpwfile <u><i>new password file</i></u>]</code></td>
+<td>Changes the password on the named token. If the token has not been
+initialized, this command will initialize the PIN.
+If a password file is given, the password will be read from that file;
+otherwise, the password will be obtained interactively.
+<b>Storing passwords in a file is much less secure than supplying them
+interactively.</b>
+<p>The password on the Netscape internal module cannot be changed if
+the <code>-nocertdb</code> option is specified.
+</td>
+</tr>
+
+<!-------------------------- -create ------------------------------------->
+<tr>
+<td><a name="create"></a><code>-create</code></td>
+<td>Creates a new secmod[ule].db, key3.db, and cert7.db in the directory
+specified with the
+<code>-dbdir</code> option, if one is specified. If no directory is
+specified, UNIX systems will use the user's .netscape directory, while other
+systems will return with an error message. If any of these databases already
+exist in the chosen directory, an error message is returned.
+<p>If used with <code>-nocertdb</code>, only secmod[ule].db will be created;
+cert7.db and key3.db will not be created.
+</td>
+</tr>
+
+<!------------------------------ -default -------------------------------->
+<tr>
+<td> <a name="default"></a> <code>-default <u><i>module name</i></u>
+-mechanisms <u><i>mechanism list</i></u></code>
+</td>
+<td>Specifies that the given module will be a default provider of the
+listed mechanisms. The mechanism list is the same as in the <code>-add</code>
+command.
+</td>
+</tr>
+
+<!-------------------------- -delete ------------------------------------->
+<tr>
+<td><a name="delete"></a><code>-delete <u><i>module name</i></u></code></td>
+<td>Deletes the named module from the database</td>
+</tr>
+
+<!-------------------------- -disable ------------------------------------->
+<tr>
+<td> <a name="disable"></a> <code>-disable <u><i>module name</i></u>
+[-slot <u><i>slot name</i></u>]</code></td>
+<td>Disables the named slot. If no slot is specified, all slots on
+the module are disabled.</td>
+</tr>
+
+<!-------------------------- -enable ------------------------------------->
+<tr>
+<td> <a name="enable"></a> <code>-enable <u><i>module name</i></u>
+[-slot <u><i>slot name</i></u>]</code></td>
+<td>Enables the named slot. If no slot is specified, all slots on
+the module are enabled.</td>
+</tr>
+
+<!-------------------------- -fips ------------------------------------->
+<tr>
+<td><a name="fips"></a><code>-fips [true | false]</code></td>
+<td>Enables or disables FIPS mode on the internal module. Passing
+<code>true</code> enables FIPS mode, passing <code>false</code> disables
+FIPS mode.</td>
+</tr>
+
+<!-------------------------- -force ------------------------------------->
+<tr>
+<td><a name="force"></a><code>-force</code></td>
+<td>Disables interactive prompts, so modutil can be run in a script.
+Should only be used by experts, since the prompts may relate to security
+or database integrity. Before using this option, test the command
+interactively once to see the warnings that are produced.</td>
+</tr>
+
+<!-------------------------- -jar ------------------------------------->
+<tr>
+<td><a name="jar"></a><code>-jar <u><i>JAR file</i></u>
+-installdir <u><i>root installation directory</i></u>
+[-tempdir <u><i>temporary directory</i></u>]</code></td>
+<td>Adds a new module from the given JAR file. The JAR file uses the
+server <a href="pk11jar.html">PKCS #11 JAR format</a> to describe the names of
+any files that need to be installed, the name of the module, mechanism flags,
+and cipher flags. The <u><i>root installation directory</i></u>
+is the directory relative to which files will be installed. This should be a
+ directory
+under which it would be natural to store dynamic library files, such as
+a server's root directory, or Communicator's root directory.
+The <u><i>temporary directory</i></u> is where temporary modutil files
+will be created in the course of the installation. If no temporary directory
+is specified, the current directory will be used.
+<p>If used with the <code>-nocertdb</code> option, the signatures on the JAR
+file will not be checked.</td>
+</tr>
+
+<!----------------------------- -list ------------------------------>
+<tr>
+<td><a name="list"></a><code>-list [<u><i>module name</i></u>]</code></td>
+<td>Without an argument, lists the PKCS #11 modules present in the module
+database.
+<blockquote>
+<pre>
+% <b>modutil -list</b>
+Using database directory /u/nicolson/.netscape...
+
+Listing of PKCS #11 Modules
+-----------------------------------------------------------
+ 1. Netscape Internal PKCS #11 Module
+ slots: 2 slots attached
+ status: loaded
+
+ slot: Communicator Internal Cryptographic Services Version 4.0
+ token: Communicator Generic Crypto Svcs
+
+ slot: Communicator User Private Key and Certificate Services
+ token: Communicator Certificate DB
+-----------------------------------------------------------
+</pre>
+</blockquote>
+<p>With an argument, provides a detailed description of the named module
+and its slots and tokens.
+<blockquote>
+<pre>
+% <b>modutil -list "Netscape Internal PKCS #11 Module"</b>
+Using database directory /u/nicolson/.netscape...
+
+-----------------------------------------------------------
+Name: Netscape Internal PKCS #11 Module
+Library file: **Internal ONLY module**
+Manufacturer: Netscape Communications Corp
+Description: Communicator Internal Crypto Svc
+PKCS #11 Version 2.0
+Library Version: 4.0
+Cipher Enable Flags: None
+Default Mechanism Flags: RSA:DSA:RC2:RC4:DES:SHA1:MD5:MD2
+
+ Slot: Communicator Internal Cryptographic Services Version 4.0
+ Manufacturer: Netscape Communications Corp
+ Type: Software
+ Version Number: 4.1
+ Firmware Version: 0.0
+ Status: Enabled
+ Token Name: Communicator Generic Crypto Svcs
+ Token Manufacturer: Netscape Communications Corp
+ Token Model: Libsec 4.0
+ Token Serial Number: 0000000000000000
+ Token Version: 4.0
+ Token Firmware Version: 0.0
+ Access: Write Protected
+ Login Type: Public (no login required)
+ User Pin: NOT Initialized
+
+ Slot: Communicator User Private Key and Certificate Services
+ Manufacturer: Netscape Communications Corp
+ Type: Software
+ Version Number: 3.0
+ Firmware Version: 0.0
+ Status: Enabled
+ Token Name: Communicator Certificate DB
+ Token Manufacturer: Netscape Communications Corp
+ Token Model: Libsec 4.0
+ Token Serial Number: 0000000000000000
+ Token Version: 7.0
+ Token Firmware Version: 0.0
+ Access: NOT Write Protected
+ Login Type: Login required
+ User Pin: Initialized
+
+-----------------------------------------------------------
+</pre>
+</blockquote>
+</td>
+</tr>
+
+<!------------------------------ Undefault ------------------------------->
+<tr>
+<td><a name="undefault"></a><code>-undefault <u><i>module name</i></u>
+-mechanisms <u><i>mechanism list</i></u></code></td>
+<td>Specifies that the given module will NOT be a default provider of
+the listed mechanisms. This command clears the default mechanism flags
+for the given module.</td>
+</tr>
+
+</table>
+
+<!------------------------------------------------------------------------>
+<!------------------------------ Options --------------------------------->
+<!------------------------------------------------------------------------>
+<h3>Options:</h3>
+<table border>
+<tr bgcolor="#cccccc"><th>Option</th><th>Description</th> </tr>
+
+<!------------------------------ -dbdir ---------------------------------->
+<tr>
+<td><code>-dbdir <u><i>directory</i></u></code></td>
+<td>Specifies which directory holds the module database. On UNIX systems,
+the user's netscape directory is the default. On other systems, there is
+no default, and this option must be used.</td>
+</tr>
+
+<!------------------------------ -dbdir ---------------------------------->
+<tr>
+<td><code>-nocertdb</code></td>
+<td>Do not open the certificate or key databases. This has several effects.
+With the <code>-create</code> command, this means that only a secmod.db file
+will be created; cert7.db and key3.db will not be created. With the
+<code>-jar</code> command, signatures on the JAR file will not be checked.
+With the <code>-changepw</code> command, the password on the Netscape internal
+module cannot be set or changed, since this password is stored in key3.db.
+</td>
+</tr>
+
+</table>
+
+</body>
+</html>
diff --git a/security/nss/cmd/mpitests/mpi-test.c b/security/nss/cmd/mpitests/mpi-test.c
new file mode 100644
index 000000000..3a1f5d6c2
--- /dev/null
+++ b/security/nss/cmd/mpitests/mpi-test.c
@@ -0,0 +1,2127 @@
+/*
+ * mpi-test.c
+ *
+ * This is a general test suite for the MPI library, which tests
+ * all the functions in the library with known values. The program
+ * exits with a zero (successful) status if the tests pass, or a
+ * nonzero status if the tests fail.
+ *
+ * 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/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <time.h>
+
+#include "mpi.h"
+#include "mpprime.h"
+
+#include "test-info.c"
+
+/* ZS means Zero Suppressed (no leading zeros) */
+#if MP_USE_LONG_DIGIT
+#define ZS_DIGIT_FMT "%lX"
+#elif MP_USE_LONG_LONG_DIGIT
+#define ZS_DIGIT_FMT "%llX"
+#elif MP_USE_UINT_DIGIT
+#define ZS_DIGIT_FMT "%X"
+#else
+#error "unknown type of digit"
+#endif
+
+/*
+ Test vectors
+
+ If you intend to change any of these values, you must also recompute
+ the corresponding solutions below. Basically, these are just hex
+ strings (for the big integers) or integer values (for the digits).
+
+ The comparison tests think they know what relationships hold between
+ these values. If you change that, you may have to adjust the code
+ for the comparison tests accordingly. Most of the other tests
+ should be fine as long as you re-compute the solutions, though.
+ */
+const char *mp1 = "639A868CDA0C569861B";
+const char *mp2 = "AAFC0A3FE45E5E09DBE2C29";
+const char *mp3 = "B55AA8DF8A7E83241F38AC7A9E479CAEF2E4D7C5";
+const char *mp4 = "-63DBC2265B88268DC801C10EA68476B7BDE0090F";
+const char *mp5 = "F595CB42";
+const char *mp5a = "-4B597E";
+const char *mp6 = "0";
+const char *mp7 = "EBFA7121CD838CE6439CC59DDB4CBEF3";
+const char *mp8 = "5";
+const char *mp9 = "F74A2876A1432698923B0767DA19DCF3D71795EE";
+const char *mp10 = "9184E72A000";
+const char *mp11 = "54D79A3557E8";
+const char *mp12 = "10000000000000000";
+const char *mp13 =
+ "34584F700C15A341E40BF7BFDD88A6630C8FF2B2067469372D391342BDAB6163963C"
+ "D5A5C79F708BDE26E0CCF2DB66CD6D6089E29A877C45F2B050D226E6DA88";
+const char *mp14 =
+ "AC3FA0EABAAC45724814D798942A1E28E14C81E0DE8055CED630E7689DA648683645DB6E"
+ "458D9F5338CC3D4E33A5D1C9BF42780133599E60DEE0049AFA8F9489501AE5C9AA2B8C13"
+ "FD21285A538B2CA87A626BB56E0A654C8707535E637FF4E39174157402BDE3AA30C9F134"
+ "0C1307BAA864B075A9CC828B6A5E2B2BF1AE406D920CC5E7657D7C0E697DEE5375773AF9"
+ "E200A1B8FAD7CD141F9EE47ABB55511FEB9A4D99EBA22F3A3FF6792FA7EE9E5DC0EE94F7"
+ "7A631EDF3D7DD7C2DAAAFDF234D60302AB63D5234CEAE941B9AF0ADDD9E6E3A940A94EE5"
+ "5DB45A7C66E61EDD0477419BBEFA44C325129601C4F45671C6A0E64665DF341D17FBC71F"
+ "77418BD9F4375DDB3B9D56126526D8E5E0F35A121FD4F347013DA880020A752324F31DDD"
+ "9BCDB13A3B86E207A2DE086825E6EEB87B3A64232CFD8205B799BC018634AAE193F19531"
+ "D6EBC19A75F27CFFAA03EB5974898F53FD569AA5CE60F431B53B0CDE715A5F382405C9C4"
+ "761A8E24888328F09F7BCE4E8D80C957DF177629C8421ACCD0C268C63C0DD47C3C0D954F"
+ "D79F7D7297C6788DF4B3E51381759864D880ACA246DF09533739B8BB6085EAF7AE8DC2D9"
+ "F224E6874926C8D24D34B457FD2C9A586C6B99582DC24F787A39E3942786CF1D494B6EB4"
+ "A513498CDA0B217C4E80BCE7DA1C704C35E071AC21E0DA9F57C27C3533F46A8D20B04137"
+ "C1B1384BE4B2EB46";
+const char *mp15 =
+ "39849CF7FD65AF2E3C4D87FE5526221103D90BA26A6642FFE3C3ECC0887BBBC57E011BF1"
+ "05D822A841653509C68F79EBE51C0099B8CBB04DEF31F36F5954208A3209AC122F0E11D8"
+ "4AE67A494D78336A2066D394D42E27EF6B03DDAF6D69F5112C93E714D27C94F82FC7EF77"
+ "445768C68EAE1C4A1407BE1B303243391D325090449764AE469CC53EC8012C4C02A72F37"
+ "07ED7275D2CC8D0A14B5BCC6BF264941520EBA97E3E6BAE4EE8BC87EE0DDA1F5611A6ECB"
+ "65F8AEF4F184E10CADBDFA5A2FEF828901D18C20785E5CC63473D638762DA80625003711"
+ "9E984AC43E707915B133543AF9D5522C3E7180DC58E1E5381C1FB7DC6A5F4198F3E88FA6"
+ "CBB6DFA8B2D1C763226B253E18BCCB79A29EE82D2DE735078C8AE3C3C86D476AAA08434C"
+ "09C274BDD40A1D8FDE38D6536C22F44E807EB73DE4FB36C9F51E0BC835DDBE3A8EFCF2FE"
+ "672B525769DC39230EE624D5EEDBD837C82A52E153F37378C3AD68A81A7ADBDF3345DBCE"
+ "8FA18CA1DE618EF94DF72EAD928D4F45B9E51632ACF158CF8332C51891D1D12C2A7E6684"
+ "360C4BF177C952579A9F442CFFEC8DAE4821A8E7A31C4861D8464CA9116C60866C5E72F7"
+ "434ADBED36D54ACDFDFF70A4EFB46E285131FE725F1C637D1C62115EDAD01C4189716327"
+ "BFAA79618B1656CBFA22C2C965687D0381CC2FE0245913C4D8D96108213680BD8E93E821"
+ "822AD9DDBFE4BD04";
+const char *mp16 = "4A724340668DB150339A70";
+const char *mp17 = "8ADB90F58";
+const char *mp18 = "C64C230AB20E5";
+const char *mp19 =
+ "F1C9DACDA287F2E3C88DCE2393B8F53DAAAC1196DC36510962B6B59454CFE64B";
+const char *mp20 =
+ "D445662C8B6FE394107B867797750C326E0F4A967E135FC430F6CD7207913AC7";
+const char *mp21 = "2";
+
+const mp_digit md1 = 0;
+const mp_digit md2 = 0x1;
+const mp_digit md3 = 0x80;
+const mp_digit md4 = 0x9C97;
+const mp_digit md5 = 0xF5BF;
+const mp_digit md6 = 0x14A0;
+const mp_digit md7 = 0x03E8;
+const mp_digit md8 = 0x0101;
+const mp_digit md9 = 0xA;
+
+/*
+ Solutions of the form x_mpABC, where:
+
+ x = (p)roduct, (s)um, (d)ifference, (q)uotient, (r)emainder, (g)cd,
+ (i)nverse, (e)xponent, square roo(t), (g)cd, (l)cm. A
+ leading 'm' indicates a modular operation, e.g. ms_mp12 is the
+ modular sum of operands 1 and 2
+
+ ABC are the operand numbers involved in the computation. If a 'd'
+ precedes the number, it is a digit operand; if a 'c' precedes it,
+ it is a constant; otherwise, it is a full integer.
+ */
+
+const char *p_mp12 = "4286AD72E095C9FE009938750743174ADDD7FD1E53";
+const char *p_mp34 = "-46BDBD66CA108C94A8CF46C325F7B6E2F2BA82D35"
+ "A1BFD6934C441EE369B60CA29BADC26845E918B";
+const char *p_mp57 = "E260C265A0A27C17AD5F4E59D6E0360217A2EBA6";
+const char *p_mp22 = "7233B5C1097FFC77CCF55928FDC3A5D31B712FDE7A1E91";
+const char *p_mp1d4 = "3CECEA2331F4220BEF68DED";
+const char *p_mp8d6 = "6720";
+const char *p_mp1113 =
+ "11590FC3831C8C3C51813142C88E566408DB04F9E27642F6471A1822E0100B12F7F1"
+ "5699A127C0FA9D26DCBFF458522661F30C6ADA4A07C8C90F9116893F6DBFBF24C3A2"
+ "4340";
+const char *p_mp1415 =
+ "26B36540DE8B3586699CCEAE218A2842C7D5A01590E70C4A26E789107FBCDB06AA2C"
+ "6DDC39E6FA18B16FCB2E934C9A5F844DAD60EE3B1EA82199EC5E9608F67F860FB965"
+ "736055DF0E8F2540EB28D07F47E309B5F5D7C94FF190AB9C83A6970160CA700B1081"
+ "F60518132AF28C6CEE6B7C473E461ABAC52C39CED50A08DD4E7EA8BA18DAD545126D"
+ "A388F6983C29B6BE3F9DCBC15766E8E6D626A92C5296A9C4653CAE5788350C0E2107"
+ "F57E5E8B6994C4847D727FF1A63A66A6CEF42B9C9E6BD04C92550B85D5527DE8A132"
+ "E6BE89341A9285C7CE7FB929D871BBCBD0ED2863B6B078B0DBB30FCA66D6C64284D6"
+ "57F394A0271E15B6EC7A9D530EBAC6CA262EF6F97E1A29FCE7749240E4AECA591ECF"
+ "272122BC587370F9371B67BB696B3CDC1BC8C5B64B6280994EBA00CDEB8EB0F5D06E"
+ "18F401D65FDCECF23DD7B9BB5B4C5458AEF2CCC09BA7F70EACB844750ACFD027521E"
+ "2E047DE8388B35F8512D3DA46FF1A12D4260213602BF7BFFDB6059439B1BD0676449"
+ "8D98C74F48FB3F548948D5BA0C8ECFCD054465132DC43466D6BBD59FBAF8D6D4E157"
+ "2D612B40A956C7D3E140F3B8562EF18568B24D335707D5BAC7495014DF2444172426"
+ "FD099DED560D30D1F945386604AFC85C64BD1E5F531F5C7840475FC0CF0F79810012"
+ "4572BAF5A9910CDBD02B27FFCC3C7E5E88EF59F3AE152476E33EDA696A4F751E0AE4"
+ "A3D2792DEA78E25B9110E12A19EFD09EA47FF9D6594DA445478BEB6901EAF8A35B2D"
+ "FD59BEE9BF7AA8535B7D326EFA5AA2121B5EBE04DD85827A3D43BD04F4AA6D7B62A2"
+ "B6D7A3077286A511A431E1EF75FCEBA3FAE9D5843A8ED17AA02BBB1B571F904699C5"
+ "A6073F87DDD012E2322AB3F41F2A61F428636FE86914148E19B8EF8314ED83332F2F"
+ "8C2ADE95071E792C0A68B903E060DD322A75FD0C2B992059FCCBB58AFA06B50D1634"
+ "BBD93F187FCE0566609FCC2BABB269C66CEB097598AA17957BB4FDA3E64A1B30402E"
+ "851CF9208E33D52E459A92C63FBB66435BB018E155E2C7F055E0B7AB82CD58FC4889"
+ "372ED9EEAC2A07E8E654AB445B9298D2830D6D4DFD117B9C8ABE3968927DC24B3633"
+ "BAD6E6466DB45DDAE87A0AB00336AC2CCCE176704F7214FCAB55743AB76C2B6CA231"
+ "7984610B27B5786DE55C184DDF556EDFEA79A3652831940DAD941E243F482DC17E50"
+ "284BC2FB1AD712A92542C573E55678878F02DFD9E3A863C7DF863227AEDE14B47AD3"
+ "957190124820ADC19F5353878EDB6BF7D0C77352A6E3BDB53EEB88F5AEF6226D6E68"
+ "756776A8FB49B77564147A641664C2A54F7E5B680CCC6A4D22D894E464DF20537094"
+ "548F1732452F9E7F810C0B4B430C073C0FBCE03F0D03F82630654BCE166AA772E1EE"
+ "DD0C08D3E3EBDF0AF54203B43AFDFC40D8FC79C97A4B0A4E1BEB14D8FCEFDDED8758"
+ "6ED65B18";
+const char *p_mp2121 = "4";
+const char *mp_mp345 = "B9B6D3A3";
+const char *mp_mp335 = "16609C2D";
+
+const char *s_mp13 = "B55AA8DF8A7E83241F38B2B446B06A4FB84E5DE0";
+const char *s_mp34 = "517EE6B92EF65C965736EB6BF7C325F73504CEB6";
+const char *s_mp46 = "-63DBC2265B88268DC801C10EA68476B7BDE0090F";
+const char *s_mp5d4 = "F59667D9";
+const char *s_mp2d5 = "AAFC0A3FE45E5E09DBF21E8";
+const char *s_mp1415 =
+ "E5C43DE2B811F4A084625F96E9504039E5258D8348E698CEB9F4D4292622042DB446"
+ "F75F4B65C1FB7A317257FA354BB5A45E789AEC254EAECE11F80A53E3B513822491DB"
+ "D9399DEC4807A2A3A10360129AC93F4A42388D3BF20B310DD0E9E9F4BE07FC88D53A"
+ "78A26091E0AB506A70813712CCBFBDD440A69A906E650EE090FDD6A42A95AC1A414D"
+ "317F1A9F781E6A30E9EE142ECDA45A1E3454A1417A7B9A613DA90831CF88EA1F2E82"
+ "41AE88CC4053220903C2E05BCDD42F02B8CF8868F84C64C5858BAD356143C5494607"
+ "EE22E11650148BAF65A985F6FC4CA540A55697F2B5AA95D6B8CF96EF638416DE1DD6"
+ "3BA9E2C09E22D03E75B60BE456C642F86B82A709253E5E087B507DE3A45F8392423F"
+ "4DBC284E8DC88C43CA77BC8DCEFB6129A59025F80F90FF978116DEBB9209E306FBB9"
+ "1B6111F8B8CFACB7C7C9BC12691C22EE88303E1713F1DFCEB622B8EA102F6365678B"
+ "C580ED87225467AA78E875868BD53B17574BA59305BC1AC666E4B7E9ED72FCFC200E"
+ "189D98FC8C5C7533739C53F52DDECDDFA5A8668BFBD40DABC9640F8FCAE58F532940"
+ "8162261320A25589E9FB51B50F80056471F24B7E1AEC35D1356FC2747FFC13A04B34"
+ "24FCECE10880BD9D97CA8CDEB2F5969BF4F30256EB5ED2BCD1DC64BDC2EE65217848"
+ "48A37FB13F84ED4FB7ACA18C4639EE64309BDD3D552AEB4AAF44295943DC1229A497"
+ "A84A";
+
+const char *ms_mp345 = "1E71E292";
+
+const char *d_mp12 = "-AAFBA6A55DD183FD854A60E";
+const char *d_mp34 = "119366B05E606A9B1E73A6D8944CC1366B0C4E0D4";
+const char *d_mp5d4 = "F5952EAB";
+const char *d_mp6d2 = "-1";
+const char *md_mp345 = "26596B86";
+
+const char *q_mp42 = "-95825A1FFA1A155D5";
+const char *r_mp42 = "-6312E99D7700A3DCB32ADF2";
+const char *q_mp45a = "15344CDA3D841F661D2B61B6EDF7828CE36";
+const char *r_mp45a = "-47C47B";
+const char *q_mp7c2 = "75FD3890E6C1C67321CE62CEEDA65F79";
+const char *q_mp3d6 = "8CAFD53C272BD6FE8B0847BDC3B539EFAB5C3";
+const char *r_mp3d6 = "1E5";
+const char *r_mp5d5 = "1257";
+const char *r_mp47 = "B3A9018D970281A90FB729A181D95CB8";
+const char *q_mp1404 =
+ "-1B994D869142D3EF6123A3CBBC3C0114FA071CFCEEF4B7D231D65591D32501AD80F"
+ "FF49AE4EC80514CC071EF6B42521C2508F4CB2FEAD69A2D2EF3934087DCAF88CC4C4"
+ "659F1CA8A7F4D36817D802F778F1392337FE36302D6865BF0D4645625DF8BB044E19"
+ "930635BE2609FAC8D99357D3A9F81F2578DE15A300964188292107DAC980E0A08CD7"
+ "E938A2135FAD45D50CB1D8C2D4C4E60C27AB98B9FBD7E4DBF752C57D2674520E4BB2"
+ "7E42324C0EFE84FB3E38CF6950E699E86FD45FE40D428400F2F94EDF7E94FAE10B45"
+ "89329E1BF61E5A378C7B31C9C6A234F8254D4C24823B84D0BF8D671D8BC9154DFAC9"
+ "49BD8ACABD6BD32DD4DC587F22C86153CB3954BDF7C2A890D623642492C482CF3E2C"
+ "776FC019C3BBC61688B485E6FD35D6376089C1E33F880E84C4E51E8ABEACE1B3FB70"
+ "3EAD0E28D2D44E7F1C0A859C840775E94F8C1369D985A3C5E8114B21D68B3CBB75D2"
+ "791C586153C85B90CAA483E57A40E2D97950AAB84920A4396C950C87C7FFFE748358"
+ "42A0BF65445B26D40F05BE164B822CA96321F41D85A289C5F5CD5F438A78704C9683"
+ "422299D21899A22F853B0C93081CC9925E350132A0717A611DD932A68A0ACC6E4C7F"
+ "7F685EF8C1F4910AEA5DC00BB5A36FCA07FFEAA490C547F6E14A08FE87041AB803E1"
+ "BD9E23E4D367A2C35762F209073DFF48F3";
+const char *r_mp1404 = "12FF98621ABF63144BFFC3207AC8FC10D8D1A09";
+
+const char *q_mp13c =
+ "34584F700C15A341E40BF7BFDD88A6630C8FF2B2067469372D391342"
+ "BDAB6163963CD5A5C79F708BDE26E0CCF2DB66CD6D6089E29A877C45";
+const char *r_mp13c = "F2B050D226E6DA88";
+const char *q_mp9c16 = "F74A2876A1432698923B0767DA19DCF3D71795E";
+const char *r_mp9c16 = "E";
+
+const char *e_mp5d9 = "A8FD7145E727A20E52E73D22990D35D158090307A"
+ "13A5215AAC4E9AB1E96BD34E531209E03310400";
+const char *e_mp78 = "AA5F72C737DFFD8CCD108008BFE7C79ADC01A819B"
+ "32B75FB82EC0FB8CA83311DA36D4063F1E57857A2"
+ "1AB226563D84A15BB63CE975FF1453BD6750C58D9"
+ "D113175764F5D0B3C89B262D4702F4D9640A3";
+const char *me_mp817 = "E504493ACB02F7F802B327AB13BF25";
+const char *me_mp5d47 = "1D45ED0D78F2778157992C951DD2734C";
+const char *me_mp1512 = "FB5B2A28D902B9D9";
+const char *me_mp161718 = "423C6AC6DBD74";
+const char *me_mp5114 =
+ "64F0F72807993578BBA3C7C36FFB184028F9EB9A810C92079E1498D8A80FC848E1F0"
+ "25F1DE43B7F6AC063F5CC29D8A7C2D7A66269D72BF5CDC327AF88AF8EF9E601DCB0A"
+ "3F35BFF3525FB1B61CE3A25182F17C0A0633B4089EA15BDC47664A43FEF639748AAC"
+ "19CF58E83D8FA32CD10661D2D4210CC84792937E6F36CB601851356622E63ADD4BD5"
+ "542412C2E0C4958E51FD2524AABDC7D60CFB5DB332EEC9DC84210F10FAE0BA2018F2"
+ "14C9D6867C9D6E49CF28C18D06CE009FD4D04BFC8837C3FAAA773F5CCF6DED1C22DE"
+ "181786AFE188540586F2D74BF312E595244E6936AE52E45742109BAA76C36F2692F5"
+ "CEF97AD462B138BE92721194B163254CBAAEE9B9864B21CCDD5375BCAD0D24132724"
+ "113D3374B4BCF9AA49BA5ACBC12288C0BCF46DCE6CB4A241A91BD559B130B6E9CD3D"
+ "D7A2C8B280C2A278BA9BF5D93244D563015C9484B86D9FEB602501DC16EEBC3EFF19"
+ "53D7999682BF1A1E3B2E7B21F4BDCA3C355039FEF55B9C0885F98DC355CA7A6D8ECF"
+ "5F7F1A6E11A764F2343C823B879B44616B56BF6AE3FA2ACF5483660E618882018E3F"
+ "C8459313BACFE1F93CECC37B2576A5C0B2714BD3EEDEEC22F0E7E3E77B11396B9B99"
+ "D683F2447A4004BBD4A57F6A616CDDFEC595C4FC19884CC2FC21CF5BF5B0B81E0F83"
+ "B9DDA0CF4DFF35BB8D31245912BF4497FD0BD95F0C604E26EA5A8EA4F5EAE870A5BD"
+ "FE8C";
+
+const char *e_mpc2d3 = "100000000000000000000000000000000";
+
+const char *t_mp9 = "FB9B6E32FF0452A34746";
+const char *i_mp27 = "B6AD8DCCDAF92B6FE57D062FFEE3A99";
+const char *i_mp2019 =
+ "BDF3D88DC373A63EED92903115B03FC8501910AF68297B4C41870AED3EA9F839";
+/* "15E3FE09E8AE5523AABA197BD2D16318D3CA148EDF4AE1C1C52FC96AFAF5680B"; */
+
+const char *t_mp15 =
+ "795853094E59B0008093BCA8DECF68587C64BDCA2F3F7F8963DABC12F1CFFFA9B8C4"
+ "365232FD4751870A0EF6CA619287C5D8B7F1747D95076AB19645EF309773E9EACEA0"
+ "975FA4AE16251A8DA5865349C3A903E3B8A2C0DEA3C0720B6020C7FED69AFF62BB72"
+ "10FAC443F9FFA2950776F949E819260C2AF8D94E8A1431A40F8C23C1973DE5D49AA2"
+ "0B3FF5DA5C1D5324E712A78FF33A9B1748F83FA529905924A31DF38643B3F693EF9B"
+ "58D846BB1AEAE4523ECC843FF551C1B300A130B65C1677402778F98C51C10813250E"
+ "2496882877B069E877B59740DC1226F18A5C0F66F64A5F59A9FAFC5E9FC45AEC0E7A"
+ "BEE244F7DD3AC268CF512A0E52E4F5BE5B94";
+
+const char *g_mp71 = "1";
+const char *g_mp25 = "7";
+const char *l_mp1011 = "C589E3D7D64A6942A000";
+
+/* mp9 in radices from 5 to 64 inclusive */
+#define LOW_RADIX 5
+#define HIGH_RADIX 64
+const char *v_mp9[] = {
+ "404041130042310320100141302000203430214122130002340212132414134210033",
+ "44515230120451152500101352430105520150025145320010504454125502",
+ "644641136612541136016610100564613624243140151310023515322",
+ "173512120732412062323044435407317550316717172705712756",
+ "265785018434285762514442046172754680368422060744852",
+ "1411774500397290569709059837552310354075408897518",
+ "184064268501499311A17746095910428222A241708032A",
+ "47706011B225950B02BB45602AA039893118A85950892",
+ "1A188C826B982353CB58422563AC602B783101671A86",
+ "105957B358B89B018958908A9114BC3DDC410B77982",
+ "CB7B3387E23452178846C55DD9D70C7CA9AEA78E8",
+ "F74A2876A1432698923B0767DA19DCF3D71795EE",
+ "17BF7C3673B76D7G7A5GA836277296F806E7453A",
+ "2EBG8HH3HFA6185D6H0596AH96G24C966DD3HG2",
+ "6G3HGBFEG8I3F25EAF61B904EIA40CFDH2124F",
+ "10AHC3D29EBHDF3HD97905CG0JA8061855C3FI",
+ "3BA5A55J5K699B2D09C38A4B237CH51IHA132",
+ "EDEA90DJ0B5CB3FGG1C8587FEB99D3C143CA",
+ "31M26JI1BBD56K3I028MML4EEDMAJK60LGLE",
+ "GGG5M3142FKKG82EJ28111D70EMHC241E4E",
+ "4446F4D5H10982023N297BF0DKBBHLLJB0I",
+ "12E9DEEOBMKAKEP0IM284MIP7FO1O521M46",
+ "85NN0HD48NN2FDDB1F5BMMKIB8CK20MDPK",
+ "2D882A7A0O0JPCJ4APDRIB77IABAKDGJP2",
+ "MFMCI0R7S27AAA3O3L2S8K44HKA7O02CN",
+ "7IGQS73FFSHC50NNH44B6PTTNLC3M6H78",
+ "2KLUB3U9850CSN6ANIDNIF1LB29MJ43LH",
+ "UT52GTL18CJ9H4HR0TJTK6ESUFBHF5FE",
+ "BTVL87QQBMUGF8PFWU4W3VU7U922QTMW",
+ "4OG10HW0MSWJBIDEE2PDH24GA7RIHIAA",
+ "1W8W9AX2DRUX48GXOLMK0PE42H0FEUWN",
+ "SVWI84VBH069WR15W1U2VTK06USY8Z2",
+ "CPTPNPDa5TYCPPNLALENT9IMX2GL0W2",
+ "5QU21UJMRaUYYYYYN6GHSMPOYOXEEUY",
+ "2O2Q7C6RPPB1SXJ9bR4035SPaQQ3H2W",
+ "18d994IbT4PHbD7cGIPCRP00bbQO0bc",
+ "NcDUEEWRO7XT76260WGeBHPVa72RdA",
+ "BbX2WCF9VfSB5LPdJAdeXKV1fd6LC2",
+ "60QDKW67P4JSQaTdQg7JE9ISafLaVU",
+ "33ba9XbDbRdNF4BeDB2XYMhAVDaBdA",
+ "1RIPZJA8gT5L5H7fTcaRhQ39geMMTc",
+ "d65j70fBATjcDiidPYXUGcaBVVLME",
+ "LKA9jhPabDG612TXWkhfT2gMXNIP2",
+ "BgNaYhjfT0G8PBcYRP8khJCR3C9QE",
+ "6Wk8RhJTAgDh10fYAiUVB1aM0HacG",
+ "3dOCjaf78kd5EQNViUZWj3AfFL90I",
+ "290VWkL3aiJoW4MBbHk0Z0bDo22Ni",
+ "1DbDZ1hpPZNUDBUp6UigcJllEdC26",
+ "dFSOLBUM7UZX8Vnc6qokGIOiFo1h",
+ "NcoUYJOg0HVmKI9fR2ag0S8R2hrK",
+ "EOpiJ5Te7oDe2pn8ZhAUKkhFHlZh",
+ "8nXK8rp8neV8LWta1WDgd1QnlWsU",
+ "5T3d6bcSBtHgrH9bCbu84tblaa7r",
+ "3PlUDIYUvMqOVCir7AtquK5dWanq",
+ "2A70gDPX2AtiicvIGGk9poiMtgvu",
+ "1MjiRxjk10J6SVAxFguv9kZiUnIc",
+ "rpre2vIDeb4h3sp50r1YBbtEx9L",
+ "ZHcoip0AglDAfibrsUcJ9M1C8fm",
+ "NHP18+eoe6uU54W49Kc6ZK7+bT2",
+ "FTAA7QXGoQOaZi7PzePtFFN5vNk"
+};
+
+const unsigned char b_mp4[] = {
+ 0x01,
+#if MP_DIGIT_MAX > MP_32BIT_MAX
+ 0x00, 0x00, 0x00, 0x00,
+#endif
+ 0x63, 0xDB, 0xC2, 0x26,
+ 0x5B, 0x88, 0x26, 0x8D,
+ 0xC8, 0x01, 0xC1, 0x0E,
+ 0xA6, 0x84, 0x76, 0xB7,
+ 0xBD, 0xE0, 0x09, 0x0F
+};
+
+/* Search for a test suite name in the names table */
+int find_name(char *name);
+void reason(char *fmt, ...);
+
+/*------------------------------------------------------------------------*/
+/*------------------------------------------------------------------------*/
+
+char g_intbuf[4096]; /* buffer for integer comparison */
+char a_intbuf[4096]; /* buffer for integer comparison */
+int g_verbose = 1; /* print out reasons for failure? */
+int res;
+
+#define IFOK(x) \
+ { \
+ if (MP_OKAY > (res = (x))) { \
+ reason("test %s failed: error %d\n", #x, res); \
+ return 1; \
+ } \
+ }
+
+int
+main(int argc, char *argv[])
+{
+ int which, res;
+
+ srand((unsigned int)time(NULL));
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s <test-suite> | list\n"
+ "Type '%s help' for assistance\n",
+ argv[0], argv[0]);
+ return 2;
+ } else if (argc > 2) {
+ if (strcmp(argv[2], "quiet") == 0)
+ g_verbose = 0;
+ }
+
+ if (strcmp(argv[1], "help") == 0) {
+ fprintf(stderr, "Help for mpi-test\n\n"
+ "This program is a test driver for the MPI library, which\n"
+ "tests all the various functions in the library to make sure\n"
+ "they are working correctly. The syntax is:\n"
+ " %s <suite-name>\n"
+ "...where <suite-name> is the name of the test you wish to\n"
+ "run. To get a list of the tests, use '%s list'.\n\n"
+ "The program exits with a status of zero if the test passes,\n"
+ "or non-zero if it fails. Ordinarily, failure is accompanied\n"
+ "by a diagnostic message to standard error. To suppress this\n"
+ "add the keyword 'quiet' after the suite-name on the command\n"
+ "line.\n\n",
+ argv[0], argv[0]);
+ return 0;
+ }
+
+ if ((which = find_name(argv[1])) < 0) {
+ fprintf(stderr, "%s: test suite '%s' is not known\n", argv[0], argv[1]);
+ return 2;
+ }
+
+ if ((res = (g_tests[which])()) < 0) {
+ fprintf(stderr, "%s: test suite not implemented yet\n", argv[0]);
+ return 2;
+ } else {
+ return res;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+find_name(char *name)
+{
+ int ix = 0;
+
+ while (ix < g_count) {
+ if (strcmp(name, g_names[ix]) == 0)
+ return ix;
+
+ ++ix;
+ }
+
+ return -1;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_list(void)
+{
+ int ix;
+
+ fprintf(stderr, "There are currently %d test suites available\n",
+ g_count);
+
+ for (ix = 1; ix < g_count; ix++)
+ fprintf(stdout, "%-20s %s\n", g_names[ix], g_descs[ix]);
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_copy(void)
+{
+ mp_int a, b;
+ int ix;
+
+ mp_init(&a);
+ mp_init(&b);
+
+ mp_read_radix(&a, mp3, 16);
+ mp_copy(&a, &b);
+
+ if (SIGN(&a) != SIGN(&b) || USED(&a) != USED(&b)) {
+ if (SIGN(&a) != SIGN(&b)) {
+ reason("error: sign of original is %d, sign of copy is %d\n",
+ SIGN(&a), SIGN(&b));
+ } else {
+ reason("error: original precision is %d, copy precision is %d\n",
+ USED(&a), USED(&b));
+ }
+ mp_clear(&a);
+ mp_clear(&b);
+ return 1;
+ }
+
+ for (ix = 0; ix < USED(&b); ix++) {
+ if (DIGIT(&a, ix) != DIGIT(&b, ix)) {
+ reason("error: digit %d " DIGIT_FMT " != " DIGIT_FMT "\n",
+ ix, DIGIT(&a, ix), DIGIT(&b, ix));
+ mp_clear(&a);
+ mp_clear(&b);
+ return 1;
+ }
+ }
+
+ mp_clear(&a);
+ mp_clear(&b);
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_exch(void)
+{
+ mp_int a, b;
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_read_radix(&a, mp7, 16);
+ mp_read_radix(&b, mp1, 16);
+
+ mp_exch(&a, &b);
+ mp_toradix(&a, g_intbuf, 16);
+
+ mp_clear(&a);
+ if (strcmp(g_intbuf, mp1) != 0) {
+ mp_clear(&b);
+ reason("error: exchange failed\n");
+ return 1;
+ }
+
+ mp_toradix(&b, g_intbuf, 16);
+
+ mp_clear(&b);
+ if (strcmp(g_intbuf, mp7) != 0) {
+ reason("error: exchange failed\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_zero(void)
+{
+ mp_int a;
+
+ mp_init(&a);
+ mp_read_radix(&a, mp7, 16);
+ mp_zero(&a);
+
+ if (USED(&a) != 1 || DIGIT(&a, 1) != 0) {
+ mp_toradix(&a, g_intbuf, 16);
+ reason("error: result is %s\n", g_intbuf);
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_clear(&a);
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_set(void)
+{
+ mp_int a;
+
+ /* Test single digit set */
+ mp_init(&a);
+ mp_set(&a, 5);
+ if (DIGIT(&a, 0) != 5) {
+ mp_toradix(&a, g_intbuf, 16);
+ reason("error: result is %s, expected 5\n", g_intbuf);
+ mp_clear(&a);
+ return 1;
+ }
+
+ /* Test integer set */
+ mp_set_int(&a, -4938110);
+ mp_toradix(&a, g_intbuf, 16);
+ mp_clear(&a);
+ if (strcmp(g_intbuf, mp5a) != 0) {
+ reason("error: result is %s, expected %s\n", g_intbuf, mp5a);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_abs(void)
+{
+ mp_int a;
+
+ mp_init(&a);
+ mp_read_radix(&a, mp4, 16);
+ mp_abs(&a, &a);
+
+ if (SIGN(&a) != ZPOS) {
+ reason("error: sign of result is negative\n");
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_clear(&a);
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_neg(void)
+{
+ mp_int a;
+ mp_sign s;
+
+ mp_init(&a);
+ mp_read_radix(&a, mp4, 16);
+
+ s = SIGN(&a);
+ mp_neg(&a, &a);
+ if (SIGN(&a) == s) {
+ reason("error: sign of result is same as sign of nonzero input\n");
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_clear(&a);
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_add_d(void)
+{
+ mp_int a;
+
+ mp_init(&a);
+
+ mp_read_radix(&a, mp5, 16);
+ mp_add_d(&a, md4, &a);
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, s_mp5d4) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, s_mp5d4);
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_read_radix(&a, mp2, 16);
+ mp_add_d(&a, md5, &a);
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, s_mp2d5) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, s_mp2d5);
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_clear(&a);
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_add(void)
+{
+ mp_int a, b;
+ int res = 0;
+
+ mp_init(&a);
+ mp_init(&b);
+
+ mp_read_radix(&a, mp1, 16);
+ mp_read_radix(&b, mp3, 16);
+ mp_add(&a, &b, &a);
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, s_mp13) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, s_mp13);
+ res = 1;
+ goto CLEANUP;
+ }
+
+ mp_read_radix(&a, mp4, 16);
+ mp_add(&a, &b, &a);
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, s_mp34) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, s_mp34);
+ res = 1;
+ goto CLEANUP;
+ }
+
+ mp_read_radix(&a, mp4, 16);
+ mp_read_radix(&b, mp6, 16);
+ mp_add(&a, &b, &a);
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, s_mp46) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, s_mp46);
+ res = 1;
+ goto CLEANUP;
+ }
+
+ mp_read_radix(&a, mp14, 16);
+ mp_read_radix(&b, mp15, 16);
+ mp_add(&a, &b, &a);
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, s_mp1415) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, s_mp1415);
+ res = 1;
+ }
+
+CLEANUP:
+ mp_clear(&a);
+ mp_clear(&b);
+ return res;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_sub_d(void)
+{
+ mp_int a;
+
+ mp_init(&a);
+ mp_read_radix(&a, mp5, 16);
+
+ mp_sub_d(&a, md4, &a);
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, d_mp5d4) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, d_mp5d4);
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_read_radix(&a, mp6, 16);
+
+ mp_sub_d(&a, md2, &a);
+ mp_toradix(&a, g_intbuf, 16);
+
+ mp_clear(&a);
+ if (strcmp(g_intbuf, d_mp6d2) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, d_mp6d2);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_sub(void)
+{
+ mp_int a, b;
+
+ mp_init(&a);
+ mp_init(&b);
+
+ mp_read_radix(&a, mp1, 16);
+ mp_read_radix(&b, mp2, 16);
+ mp_sub(&a, &b, &a);
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, d_mp12) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, d_mp12);
+ mp_clear(&a);
+ mp_clear(&b);
+ return 1;
+ }
+
+ mp_read_radix(&a, mp3, 16);
+ mp_read_radix(&b, mp4, 16);
+ mp_sub(&a, &b, &a);
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, d_mp34) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, d_mp34);
+ mp_clear(&a);
+ mp_clear(&b);
+ return 1;
+ }
+
+ mp_clear(&a);
+ mp_clear(&b);
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_mul_d(void)
+{
+ mp_int a;
+
+ mp_init(&a);
+ mp_read_radix(&a, mp1, 16);
+
+ IFOK(mp_mul_d(&a, md4, &a));
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, p_mp1d4) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, p_mp1d4);
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_read_radix(&a, mp8, 16);
+ IFOK(mp_mul_d(&a, md6, &a));
+ mp_toradix(&a, g_intbuf, 16);
+
+ mp_clear(&a);
+ if (strcmp(g_intbuf, p_mp8d6) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, p_mp8d6);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_mul(void)
+{
+ mp_int a, b;
+ int res = 0;
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_read_radix(&a, mp1, 16);
+ mp_read_radix(&b, mp2, 16);
+
+ IFOK(mp_mul(&a, &b, &a));
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, p_mp12) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, p_mp12);
+ res = 1;
+ goto CLEANUP;
+ }
+
+ mp_read_radix(&a, mp3, 16);
+ mp_read_radix(&b, mp4, 16);
+ IFOK(mp_mul(&a, &b, &a));
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, p_mp34) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, p_mp34);
+ res = 1;
+ goto CLEANUP;
+ }
+
+ mp_read_radix(&a, mp5, 16);
+ mp_read_radix(&b, mp7, 16);
+ IFOK(mp_mul(&a, &b, &a));
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, p_mp57) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, p_mp57);
+ res = 1;
+ goto CLEANUP;
+ }
+
+ mp_read_radix(&a, mp11, 16);
+ mp_read_radix(&b, mp13, 16);
+ IFOK(mp_mul(&a, &b, &a));
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, p_mp1113) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, p_mp1113);
+ res = 1;
+ goto CLEANUP;
+ }
+
+ mp_read_radix(&a, mp14, 16);
+ mp_read_radix(&b, mp15, 16);
+ IFOK(mp_mul(&a, &b, &a));
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, p_mp1415) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, p_mp1415);
+ res = 1;
+ }
+ mp_read_radix(&a, mp21, 10);
+ mp_read_radix(&b, mp21, 10);
+
+ IFOK(mp_mul(&a, &b, &a));
+ mp_toradix(&a, g_intbuf, 10);
+
+ if (strcmp(g_intbuf, p_mp2121) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, p_mp2121);
+ res = 1;
+ goto CLEANUP;
+ }
+
+CLEANUP:
+ mp_clear(&a);
+ mp_clear(&b);
+ return res;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_sqr(void)
+{
+ mp_int a;
+
+ mp_init(&a);
+ mp_read_radix(&a, mp2, 16);
+
+ mp_sqr(&a, &a);
+ mp_toradix(&a, g_intbuf, 16);
+
+ mp_clear(&a);
+ if (strcmp(g_intbuf, p_mp22) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, p_mp22);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_div_d(void)
+{
+ mp_int a, q;
+ mp_digit r;
+ int err = 0;
+
+ mp_init(&a);
+ mp_init(&q);
+ mp_read_radix(&a, mp3, 16);
+
+ IFOK(mp_div_d(&a, md6, &q, &r));
+ mp_toradix(&q, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, q_mp3d6) != 0) {
+ reason("error: computed q = %s, expected %s\n", g_intbuf, q_mp3d6);
+ ++err;
+ }
+
+ sprintf(g_intbuf, ZS_DIGIT_FMT, r);
+
+ if (strcmp(g_intbuf, r_mp3d6) != 0) {
+ reason("error: computed r = %s, expected %s\n", g_intbuf, r_mp3d6);
+ ++err;
+ }
+
+ mp_read_radix(&a, mp9, 16);
+ IFOK(mp_div_d(&a, 16, &q, &r));
+ mp_toradix(&q, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, q_mp9c16) != 0) {
+ reason("error: computed q = %s, expected %s\n", g_intbuf, q_mp9c16);
+ ++err;
+ }
+
+ sprintf(g_intbuf, ZS_DIGIT_FMT, r);
+
+ if (strcmp(g_intbuf, r_mp9c16) != 0) {
+ reason("error: computed r = %s, expected %s\n", g_intbuf, r_mp9c16);
+ ++err;
+ }
+
+ mp_clear(&a);
+ mp_clear(&q);
+ return err;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_div_2(void)
+{
+ mp_int a;
+
+ mp_init(&a);
+ mp_read_radix(&a, mp7, 16);
+ IFOK(mp_div_2(&a, &a));
+ mp_toradix(&a, g_intbuf, 16);
+
+ mp_clear(&a);
+ if (strcmp(g_intbuf, q_mp7c2) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, q_mp7c2);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_div_2d(void)
+{
+ mp_int a, q, r;
+
+ mp_init(&q);
+ mp_init(&r);
+ mp_init(&a);
+ mp_read_radix(&a, mp13, 16);
+
+ IFOK(mp_div_2d(&a, 64, &q, &r));
+ mp_clear(&a);
+
+ mp_toradix(&q, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, q_mp13c) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, q_mp13c);
+ mp_clear(&q);
+ mp_clear(&r);
+ return 1;
+ }
+
+ mp_clear(&q);
+
+ mp_toradix(&r, g_intbuf, 16);
+ if (strcmp(g_intbuf, r_mp13c) != 0) {
+ reason("error, computed %s, expected %s\n", g_intbuf, r_mp13c);
+ mp_clear(&r);
+ return 1;
+ }
+
+ mp_clear(&r);
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_div(void)
+{
+ mp_int a, b, r;
+ int err = 0;
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_init(&r);
+
+ mp_read_radix(&a, mp4, 16);
+ mp_read_radix(&b, mp2, 16);
+ IFOK(mp_div(&a, &b, &a, &r));
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, q_mp42) != 0) {
+ reason("error: test 1 computed quot %s, expected %s\n", g_intbuf, q_mp42);
+ ++err;
+ }
+
+ mp_toradix(&r, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, r_mp42) != 0) {
+ reason("error: test 1 computed rem %s, expected %s\n", g_intbuf, r_mp42);
+ ++err;
+ }
+
+ mp_read_radix(&a, mp4, 16);
+ mp_read_radix(&b, mp5a, 16);
+ IFOK(mp_div(&a, &b, &a, &r));
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, q_mp45a) != 0) {
+ reason("error: test 2 computed quot %s, expected %s\n", g_intbuf, q_mp45a);
+ ++err;
+ }
+
+ mp_toradix(&r, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, r_mp45a) != 0) {
+ reason("error: test 2 computed rem %s, expected %s\n", g_intbuf, r_mp45a);
+ ++err;
+ }
+
+ mp_read_radix(&a, mp14, 16);
+ mp_read_radix(&b, mp4, 16);
+ IFOK(mp_div(&a, &b, &a, &r));
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, q_mp1404) != 0) {
+ reason("error: test 3 computed quot %s, expected %s\n", g_intbuf, q_mp1404);
+ ++err;
+ }
+
+ mp_toradix(&r, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, r_mp1404) != 0) {
+ reason("error: test 3 computed rem %s, expected %s\n", g_intbuf, r_mp1404);
+ ++err;
+ }
+
+ mp_clear(&a);
+ mp_clear(&b);
+ mp_clear(&r);
+
+ return err;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_expt_d(void)
+{
+ mp_int a;
+
+ mp_init(&a);
+ mp_read_radix(&a, mp5, 16);
+ mp_expt_d(&a, md9, &a);
+ mp_toradix(&a, g_intbuf, 16);
+
+ mp_clear(&a);
+ if (strcmp(g_intbuf, e_mp5d9) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, e_mp5d9);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_expt(void)
+{
+ mp_int a, b;
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_read_radix(&a, mp7, 16);
+ mp_read_radix(&b, mp8, 16);
+
+ mp_expt(&a, &b, &a);
+ mp_toradix(&a, g_intbuf, 16);
+ mp_clear(&a);
+ mp_clear(&b);
+
+ if (strcmp(g_intbuf, e_mp78) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, e_mp78);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_2expt(void)
+{
+ mp_int a;
+
+ mp_init(&a);
+ mp_2expt(&a, md3);
+ mp_toradix(&a, g_intbuf, 16);
+ mp_clear(&a);
+
+ if (strcmp(g_intbuf, e_mpc2d3) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, e_mpc2d3);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_mod_d(void)
+{
+ mp_int a;
+ mp_digit r;
+
+ mp_init(&a);
+ mp_read_radix(&a, mp5, 16);
+ IFOK(mp_mod_d(&a, md5, &r));
+ sprintf(g_intbuf, ZS_DIGIT_FMT, r);
+ mp_clear(&a);
+
+ if (strcmp(g_intbuf, r_mp5d5) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, r_mp5d5);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_mod(void)
+{
+ mp_int a, m;
+
+ mp_init(&a);
+ mp_init(&m);
+ mp_read_radix(&a, mp4, 16);
+ mp_read_radix(&m, mp7, 16);
+ IFOK(mp_mod(&a, &m, &a));
+ mp_toradix(&a, g_intbuf, 16);
+ mp_clear(&a);
+ mp_clear(&m);
+
+ if (strcmp(g_intbuf, r_mp47) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, r_mp47);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_addmod(void)
+{
+ mp_int a, b, m;
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_init(&m);
+ mp_read_radix(&a, mp3, 16);
+ mp_read_radix(&b, mp4, 16);
+ mp_read_radix(&m, mp5, 16);
+
+ IFOK(mp_addmod(&a, &b, &m, &a));
+ mp_toradix(&a, g_intbuf, 16);
+ mp_clear(&a);
+ mp_clear(&b);
+ mp_clear(&m);
+
+ if (strcmp(g_intbuf, ms_mp345) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, ms_mp345);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_submod(void)
+{
+ mp_int a, b, m;
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_init(&m);
+ mp_read_radix(&a, mp3, 16);
+ mp_read_radix(&b, mp4, 16);
+ mp_read_radix(&m, mp5, 16);
+
+ IFOK(mp_submod(&a, &b, &m, &a));
+ mp_toradix(&a, g_intbuf, 16);
+ mp_clear(&a);
+ mp_clear(&b);
+ mp_clear(&m);
+
+ if (strcmp(g_intbuf, md_mp345) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, md_mp345);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_mulmod(void)
+{
+ mp_int a, b, m;
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_init(&m);
+ mp_read_radix(&a, mp3, 16);
+ mp_read_radix(&b, mp4, 16);
+ mp_read_radix(&m, mp5, 16);
+
+ IFOK(mp_mulmod(&a, &b, &m, &a));
+ mp_toradix(&a, g_intbuf, 16);
+ mp_clear(&a);
+ mp_clear(&b);
+ mp_clear(&m);
+
+ if (strcmp(g_intbuf, mp_mp345) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, mp_mp345);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_sqrmod(void)
+{
+ mp_int a, m;
+
+ mp_init(&a);
+ mp_init(&m);
+ mp_read_radix(&a, mp3, 16);
+ mp_read_radix(&m, mp5, 16);
+
+ IFOK(mp_sqrmod(&a, &m, &a));
+ mp_toradix(&a, g_intbuf, 16);
+ mp_clear(&a);
+ mp_clear(&m);
+
+ if (strcmp(g_intbuf, mp_mp335) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, mp_mp335);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_exptmod(void)
+{
+ mp_int a, b, m;
+ int res = 0;
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_init(&m);
+ mp_read_radix(&a, mp8, 16);
+ mp_read_radix(&b, mp1, 16);
+ mp_read_radix(&m, mp7, 16);
+
+ IFOK(mp_exptmod(&a, &b, &m, &a));
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, me_mp817) != 0) {
+ reason("case 1: error: computed %s, expected %s\n", g_intbuf, me_mp817);
+ res = 1;
+ goto CLEANUP;
+ }
+
+ mp_read_radix(&a, mp1, 16);
+ mp_read_radix(&b, mp5, 16);
+ mp_read_radix(&m, mp12, 16);
+
+ IFOK(mp_exptmod(&a, &b, &m, &a));
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, me_mp1512) != 0) {
+ reason("case 2: error: computed %s, expected %s\n", g_intbuf, me_mp1512);
+ res = 1;
+ goto CLEANUP;
+ }
+
+ mp_read_radix(&a, mp5, 16);
+ mp_read_radix(&b, mp1, 16);
+ mp_read_radix(&m, mp14, 16);
+
+ IFOK(mp_exptmod(&a, &b, &m, &a));
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, me_mp5114) != 0) {
+ reason("case 3: error: computed %s, expected %s\n", g_intbuf, me_mp5114);
+ res = 1;
+ }
+
+ mp_read_radix(&a, mp16, 16);
+ mp_read_radix(&b, mp17, 16);
+ mp_read_radix(&m, mp18, 16);
+
+ IFOK(mp_exptmod(&a, &b, &m, &a));
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, me_mp161718) != 0) {
+ reason("case 4: error: computed %s, expected %s\n", g_intbuf, me_mp161718);
+ res = 1;
+ }
+
+CLEANUP:
+ mp_clear(&a);
+ mp_clear(&b);
+ mp_clear(&m);
+ return res;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_exptmod_d(void)
+{
+ mp_int a, m;
+
+ mp_init(&a);
+ mp_init(&m);
+ mp_read_radix(&a, mp5, 16);
+ mp_read_radix(&m, mp7, 16);
+
+ IFOK(mp_exptmod_d(&a, md4, &m, &a));
+ mp_toradix(&a, g_intbuf, 16);
+ mp_clear(&a);
+ mp_clear(&m);
+
+ if (strcmp(g_intbuf, me_mp5d47) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, me_mp5d47);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_invmod(void)
+{
+ mp_int a, m, c;
+ mp_int p1, p2, p3, p4, p5;
+ mp_int t1, t2, t3, t4;
+ mp_err res;
+
+ /* 5 128-bit primes. */
+ static const char ivp1[] = { "AAD8A5A2A2BEF644BAEE7DB0CA643719" };
+ static const char ivp2[] = { "CB371AD2B79A90BCC88D0430663E40B9" };
+ static const char ivp3[] = { "C6C818D4DF2618406CA09280C0400099" };
+ static const char ivp4[] = { "CE949C04512E68918006B1F0D7E93F27" };
+ static const char ivp5[] = { "F8EE999B6416645040687440E0B89F51" };
+
+ mp_init(&a);
+ mp_init(&m);
+ mp_read_radix(&a, mp2, 16);
+ mp_read_radix(&m, mp7, 16);
+
+ IFOK(mp_invmod(&a, &m, &a));
+
+ mp_toradix(&a, g_intbuf, 16);
+ mp_clear(&a);
+ mp_clear(&m);
+
+ if (strcmp(g_intbuf, i_mp27) != 0) {
+ reason("error: invmod test 1 computed %s, expected %s\n", g_intbuf, i_mp27);
+ return 1;
+ }
+
+ mp_init(&a);
+ mp_init(&m);
+ mp_read_radix(&a, mp20, 16);
+ mp_read_radix(&m, mp19, 16);
+
+ IFOK(mp_invmod(&a, &m, &a));
+
+ mp_toradix(&a, g_intbuf, 16);
+ mp_clear(&a);
+ mp_clear(&m);
+
+ if (strcmp(g_intbuf, i_mp2019) != 0) {
+ reason("error: invmod test 2 computed %s, expected %s\n", g_intbuf, i_mp2019);
+ return 1;
+ }
+
+ /* Need the following test cases:
+ Odd modulus
+ - a is odd, relatively prime to m
+ - a is odd, not relatively prime to m
+ - a is even, relatively prime to m
+ - a is even, not relatively prime to m
+ Even modulus
+ - a is even (should fail)
+ - a is odd, not relatively prime to m
+ - a is odd, relatively prime to m,
+ m is not a power of 2
+ - m has factor 2**k, k < 32
+ - m has factor 2**k, k > 32
+ m is a power of 2, 2**k
+ - k < 32
+ - k > 32
+ */
+
+ mp_init(&a);
+ mp_init(&m);
+ mp_init(&c);
+ mp_init(&p1);
+ mp_init(&p2);
+ mp_init(&p3);
+ mp_init(&p4);
+ mp_init(&p5);
+ mp_init(&t1);
+ mp_init(&t2);
+ mp_init(&t3);
+ mp_init(&t4);
+
+ mp_read_radix(&p1, ivp1, 16);
+ mp_read_radix(&p2, ivp2, 16);
+ mp_read_radix(&p3, ivp3, 16);
+ mp_read_radix(&p4, ivp4, 16);
+ mp_read_radix(&p5, ivp5, 16);
+
+ IFOK(mp_2expt(&t2, 68)); /* t2 = 2**68 */
+ IFOK(mp_2expt(&t3, 128)); /* t3 = 2**128 */
+ IFOK(mp_2expt(&t4, 31)); /* t4 = 2**31 */
+
+ /* test 3: Odd modulus - a is odd, relatively prime to m */
+
+ IFOK(mp_mul(&p1, &p2, &a));
+ IFOK(mp_mul(&p3, &p4, &m));
+ IFOK(mp_invmod(&a, &m, &t1));
+ IFOK(mp_invmod_xgcd(&a, &m, &c));
+
+ if (mp_cmp(&t1, &c) != 0) {
+ mp_toradix(&t1, g_intbuf, 16);
+ mp_toradix(&c, a_intbuf, 16);
+ reason("error: invmod test 3 computed %s, expected %s\n",
+ g_intbuf, a_intbuf);
+ return 1;
+ }
+ mp_clear(&a);
+ mp_clear(&t1);
+ mp_clear(&c);
+ mp_init(&a);
+ mp_init(&t1);
+ mp_init(&c);
+
+ /* test 4: Odd modulus - a is odd, NOT relatively prime to m */
+
+ IFOK(mp_mul(&p1, &p3, &a));
+ /* reuse same m as before */
+
+ res = mp_invmod_xgcd(&a, &m, &c);
+ if (res != MP_UNDEF)
+ goto CLEANUP4;
+
+ res = mp_invmod(&a, &m, &t1); /* we expect this to fail. */
+ if (res != MP_UNDEF) {
+ CLEANUP4:
+ reason("error: invmod test 4 succeeded, should have failed.\n");
+ return 1;
+ }
+ mp_clear(&a);
+ mp_clear(&t1);
+ mp_clear(&c);
+ mp_init(&a);
+ mp_init(&t1);
+ mp_init(&c);
+
+ /* test 5: Odd modulus - a is even, relatively prime to m */
+
+ IFOK(mp_mul(&p1, &t2, &a));
+ /* reuse m */
+ IFOK(mp_invmod(&a, &m, &t1));
+ IFOK(mp_invmod_xgcd(&a, &m, &c));
+
+ if (mp_cmp(&t1, &c) != 0) {
+ mp_toradix(&t1, g_intbuf, 16);
+ mp_toradix(&c, a_intbuf, 16);
+ reason("error: invmod test 5 computed %s, expected %s\n",
+ g_intbuf, a_intbuf);
+ return 1;
+ }
+ mp_clear(&a);
+ mp_clear(&t1);
+ mp_clear(&c);
+ mp_init(&a);
+ mp_init(&t1);
+ mp_init(&c);
+
+ /* test 6: Odd modulus - a is odd, NOT relatively prime to m */
+
+ /* reuse t2 */
+ IFOK(mp_mul(&t2, &p3, &a));
+ /* reuse same m as before */
+
+ res = mp_invmod_xgcd(&a, &m, &c);
+ if (res != MP_UNDEF)
+ goto CLEANUP6;
+
+ res = mp_invmod(&a, &m, &t1); /* we expect this to fail. */
+ if (res != MP_UNDEF) {
+ CLEANUP6:
+ reason("error: invmod test 6 succeeded, should have failed.\n");
+ return 1;
+ }
+ mp_clear(&a);
+ mp_clear(&m);
+ mp_clear(&c);
+ mp_clear(&t1);
+ mp_init(&a);
+ mp_init(&m);
+ mp_init(&c);
+ mp_init(&t1);
+
+ /* test 7: Even modulus, even a, should fail */
+
+ IFOK(mp_mul(&p3, &t3, &m)); /* even m */
+ /* reuse t2 */
+ IFOK(mp_mul(&p1, &t2, &a)); /* even a */
+
+ res = mp_invmod_xgcd(&a, &m, &c);
+ if (res != MP_UNDEF)
+ goto CLEANUP7;
+
+ res = mp_invmod(&a, &m, &t1); /* we expect this to fail. */
+ if (res != MP_UNDEF) {
+ CLEANUP7:
+ reason("error: invmod test 7 succeeded, should have failed.\n");
+ return 1;
+ }
+ mp_clear(&a);
+ mp_clear(&c);
+ mp_clear(&t1);
+ mp_init(&a);
+ mp_init(&c);
+ mp_init(&t1);
+
+ /* test 8: Even modulus - a is odd, not relatively prime to m */
+
+ /* reuse m */
+ IFOK(mp_mul(&p3, &p1, &a)); /* even a */
+
+ res = mp_invmod_xgcd(&a, &m, &c);
+ if (res != MP_UNDEF)
+ goto CLEANUP8;
+
+ res = mp_invmod(&a, &m, &t1); /* we expect this to fail. */
+ if (res != MP_UNDEF) {
+ CLEANUP8:
+ reason("error: invmod test 8 succeeded, should have failed.\n");
+ return 1;
+ }
+ mp_clear(&a);
+ mp_clear(&m);
+ mp_clear(&c);
+ mp_clear(&t1);
+ mp_init(&a);
+ mp_init(&m);
+ mp_init(&c);
+ mp_init(&t1);
+
+ /* test 9: Even modulus - m has factor 2**k, k < 32
+ * - a is odd, relatively prime to m,
+ */
+ IFOK(mp_mul(&p3, &t4, &m)); /* even m */
+ IFOK(mp_mul(&p1, &p2, &a));
+ IFOK(mp_invmod(&a, &m, &t1));
+ IFOK(mp_invmod_xgcd(&a, &m, &c));
+
+ if (mp_cmp(&t1, &c) != 0) {
+ mp_toradix(&t1, g_intbuf, 16);
+ mp_toradix(&c, a_intbuf, 16);
+ reason("error: invmod test 9 computed %s, expected %s\n",
+ g_intbuf, a_intbuf);
+ return 1;
+ }
+ mp_clear(&m);
+ mp_clear(&t1);
+ mp_clear(&c);
+ mp_init(&m);
+ mp_init(&t1);
+ mp_init(&c);
+
+ /* test 10: Even modulus - m has factor 2**k, k > 32
+ * - a is odd, relatively prime to m,
+ */
+ IFOK(mp_mul(&p3, &t3, &m)); /* even m */
+ /* reuse a */
+ IFOK(mp_invmod(&a, &m, &t1));
+ IFOK(mp_invmod_xgcd(&a, &m, &c));
+
+ if (mp_cmp(&t1, &c) != 0) {
+ mp_toradix(&t1, g_intbuf, 16);
+ mp_toradix(&c, a_intbuf, 16);
+ reason("error: invmod test 10 computed %s, expected %s\n",
+ g_intbuf, a_intbuf);
+ return 1;
+ }
+ mp_clear(&t1);
+ mp_clear(&c);
+ mp_init(&t1);
+ mp_init(&c);
+
+ /* test 11: Even modulus - m is a power of 2, 2**k | k < 32
+ * - a is odd, relatively prime to m,
+ */
+ IFOK(mp_invmod(&a, &t4, &t1));
+ IFOK(mp_invmod_xgcd(&a, &t4, &c));
+
+ if (mp_cmp(&t1, &c) != 0) {
+ mp_toradix(&t1, g_intbuf, 16);
+ mp_toradix(&c, a_intbuf, 16);
+ reason("error: invmod test 11 computed %s, expected %s\n",
+ g_intbuf, a_intbuf);
+ return 1;
+ }
+ mp_clear(&t1);
+ mp_clear(&c);
+ mp_init(&t1);
+ mp_init(&c);
+
+ /* test 12: Even modulus - m is a power of 2, 2**k | k > 32
+ * - a is odd, relatively prime to m,
+ */
+ IFOK(mp_invmod(&a, &t3, &t1));
+ IFOK(mp_invmod_xgcd(&a, &t3, &c));
+
+ if (mp_cmp(&t1, &c) != 0) {
+ mp_toradix(&t1, g_intbuf, 16);
+ mp_toradix(&c, a_intbuf, 16);
+ reason("error: invmod test 12 computed %s, expected %s\n",
+ g_intbuf, a_intbuf);
+ return 1;
+ }
+
+ mp_clear(&a);
+ mp_clear(&m);
+ mp_clear(&c);
+ mp_clear(&t1);
+ mp_clear(&t2);
+ mp_clear(&t3);
+ mp_clear(&t4);
+ mp_clear(&p1);
+ mp_clear(&p2);
+ mp_clear(&p3);
+ mp_clear(&p4);
+ mp_clear(&p5);
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_cmp_d(void)
+{
+ mp_int a;
+
+ mp_init(&a);
+ mp_read_radix(&a, mp8, 16);
+
+ if (mp_cmp_d(&a, md8) >= 0) {
+ reason("error: %s >= " DIGIT_FMT "\n", mp8, md8);
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_read_radix(&a, mp5, 16);
+
+ if (mp_cmp_d(&a, md8) <= 0) {
+ reason("error: %s <= " DIGIT_FMT "\n", mp5, md8);
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_read_radix(&a, mp6, 16);
+
+ if (mp_cmp_d(&a, md1) != 0) {
+ reason("error: %s != " DIGIT_FMT "\n", mp6, md1);
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_clear(&a);
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_cmp_z(void)
+{
+ mp_int a;
+
+ mp_init(&a);
+ mp_read_radix(&a, mp6, 16);
+
+ if (mp_cmp_z(&a) != 0) {
+ reason("error: someone thinks a zero value is non-zero\n");
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_read_radix(&a, mp1, 16);
+
+ if (mp_cmp_z(&a) <= 0) {
+ reason("error: someone thinks a positive value is non-positive\n");
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_read_radix(&a, mp4, 16);
+
+ if (mp_cmp_z(&a) >= 0) {
+ reason("error: someone thinks a negative value is non-negative\n");
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_clear(&a);
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_cmp(void)
+{
+ mp_int a, b;
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_read_radix(&a, mp3, 16);
+ mp_read_radix(&b, mp4, 16);
+
+ if (mp_cmp(&a, &b) <= 0) {
+ reason("error: %s <= %s\n", mp3, mp4);
+ mp_clear(&a);
+ mp_clear(&b);
+ return 1;
+ }
+
+ mp_read_radix(&b, mp3, 16);
+ if (mp_cmp(&a, &b) != 0) {
+ reason("error: %s != %s\n", mp3, mp3);
+ mp_clear(&a);
+ mp_clear(&b);
+ return 1;
+ }
+
+ mp_read_radix(&a, mp5, 16);
+ if (mp_cmp(&a, &b) >= 0) {
+ reason("error: %s >= %s\n", mp5, mp3);
+ mp_clear(&a);
+ mp_clear(&b);
+ return 1;
+ }
+
+ mp_clear(&a);
+ mp_clear(&b);
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_cmp_mag(void)
+{
+ mp_int a, b;
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_read_radix(&a, mp5, 16);
+ mp_read_radix(&b, mp4, 16);
+
+ if (mp_cmp_mag(&a, &b) >= 0) {
+ reason("error: %s >= %s\n", mp5, mp4);
+ mp_clear(&a);
+ mp_clear(&b);
+ return 1;
+ }
+
+ mp_read_radix(&b, mp5, 16);
+ if (mp_cmp_mag(&a, &b) != 0) {
+ reason("error: %s != %s\n", mp5, mp5);
+ mp_clear(&a);
+ mp_clear(&b);
+ return 1;
+ }
+
+ mp_read_radix(&a, mp1, 16);
+ if (mp_cmp_mag(&b, &a) >= 0) {
+ reason("error: %s >= %s\n", mp5, mp1);
+ mp_clear(&a);
+ mp_clear(&b);
+ return 1;
+ }
+
+ mp_clear(&a);
+ mp_clear(&b);
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_parity(void)
+{
+ mp_int a;
+
+ mp_init(&a);
+ mp_read_radix(&a, mp1, 16);
+
+ if (!mp_isodd(&a)) {
+ reason("error: expected operand to be odd, but it isn't\n");
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_read_radix(&a, mp6, 16);
+
+ if (!mp_iseven(&a)) {
+ reason("error: expected operand to be even, but it isn't\n");
+ mp_clear(&a);
+ return 1;
+ }
+
+ mp_clear(&a);
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_gcd(void)
+{
+ mp_int a, b;
+ int out = 0;
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_read_radix(&a, mp7, 16);
+ mp_read_radix(&b, mp1, 16);
+
+ mp_gcd(&a, &b, &a);
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, g_mp71) != 0) {
+ reason("error: computed %s, expected %s\n", g_intbuf, g_mp71);
+ out = 1;
+ }
+
+ mp_clear(&a);
+ mp_clear(&b);
+ return out;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_lcm(void)
+{
+ mp_int a, b;
+ int out = 0;
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_read_radix(&a, mp10, 16);
+ mp_read_radix(&b, mp11, 16);
+
+ mp_lcm(&a, &b, &a);
+ mp_toradix(&a, g_intbuf, 16);
+
+ if (strcmp(g_intbuf, l_mp1011) != 0) {
+ reason("error: computed %s, expected%s\n", g_intbuf, l_mp1011);
+ out = 1;
+ }
+
+ mp_clear(&a);
+ mp_clear(&b);
+
+ return out;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_convert(void)
+{
+ int ix;
+ mp_int a;
+
+ mp_init(&a);
+ mp_read_radix(&a, mp9, 16);
+
+ for (ix = LOW_RADIX; ix <= HIGH_RADIX; ix++) {
+ mp_toradix(&a, g_intbuf, ix);
+
+ if (strcmp(g_intbuf, v_mp9[ix - LOW_RADIX]) != 0) {
+ reason("error: radix %d, computed %s, expected %s\n",
+ ix, g_intbuf, v_mp9[ix - LOW_RADIX]);
+ mp_clear(&a);
+ return 1;
+ }
+ }
+
+ mp_clear(&a);
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_raw(void)
+{
+ int len, out = 0;
+ mp_int a;
+ char *buf;
+
+ mp_init(&a);
+ mp_read_radix(&a, mp4, 16);
+
+ len = mp_raw_size(&a);
+ if (len != sizeof(b_mp4)) {
+ reason("error: test_raw: expected length %d, computed %d\n", sizeof(b_mp4),
+ len);
+ mp_clear(&a);
+ return 1;
+ }
+
+ buf = calloc(len, sizeof(char));
+ mp_toraw(&a, buf);
+
+ if (memcmp(buf, b_mp4, sizeof(b_mp4)) != 0) {
+ reason("error: test_raw: binary output does not match test vector\n");
+ out = 1;
+ }
+
+ free(buf);
+ mp_clear(&a);
+
+ return out;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_pprime(void)
+{
+ mp_int p;
+ int err = 0;
+ mp_err res;
+
+ mp_init(&p);
+ mp_read_radix(&p, mp7, 16);
+
+ if (mpp_pprime(&p, 5) != MP_YES) {
+ reason("error: %s failed Rabin-Miller test, but is prime\n", mp7);
+ err = 1;
+ }
+
+ IFOK(mp_set_int(&p, 9));
+ res = mpp_pprime(&p, 50);
+ if (res == MP_YES) {
+ reason("error: 9 is composite but passed Rabin-Miller test\n");
+ err = 1;
+ } else if (res != MP_NO) {
+ reason("test mpp_pprime(9, 50) failed: error %d\n", res);
+ err = 1;
+ }
+
+ IFOK(mp_set_int(&p, 15));
+ res = mpp_pprime(&p, 50);
+ if (res == MP_YES) {
+ reason("error: 15 is composite but passed Rabin-Miller test\n");
+ err = 1;
+ } else if (res != MP_NO) {
+ reason("test mpp_pprime(15, 50) failed: error %d\n", res);
+ err = 1;
+ }
+
+ mp_clear(&p);
+
+ return err;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_fermat(void)
+{
+ mp_int p;
+ mp_err res;
+ int err = 0;
+
+ mp_init(&p);
+ mp_read_radix(&p, mp7, 16);
+
+ if ((res = mpp_fermat(&p, 2)) != MP_YES) {
+ reason("error: %s failed Fermat test on 2: %s\n", mp7,
+ mp_strerror(res));
+ ++err;
+ }
+
+ if ((res = mpp_fermat(&p, 3)) != MP_YES) {
+ reason("error: %s failed Fermat test on 3: %s\n", mp7,
+ mp_strerror(res));
+ ++err;
+ }
+
+ mp_clear(&p);
+
+ return err;
+}
+
+/*------------------------------------------------------------------------*/
+/* Like fprintf(), but only if we are behaving in a verbose manner */
+
+void
+reason(char *fmt, ...)
+{
+ va_list ap;
+
+ if (!g_verbose)
+ return;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+/*------------------------------------------------------------------------*/
+/* HERE THERE BE DRAGONS */
diff --git a/security/nss/cmd/mpitests/mpitests.gyp b/security/nss/cmd/mpitests/mpitests.gyp
new file mode 100644
index 000000000..270b63ab8
--- /dev/null
+++ b/security/nss/cmd/mpitests/mpitests.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'mpi_tests',
+ 'type': 'executable',
+ 'sources': [
+ 'mpi-test.c',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/lib/freebl/freebl.gyp:<(freebl_name)',
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'include_dirs': [
+ '<(DEPTH)/lib/freebl/mpi',
+ '<(DEPTH)/lib/util',
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/cmd/mpitests/test-info.c b/security/nss/cmd/mpitests/test-info.c
new file mode 100644
index 000000000..66386ff5d
--- /dev/null
+++ b/security/nss/cmd/mpitests/test-info.c
@@ -0,0 +1,157 @@
+/*
+ * test-info.c
+ *
+ * Arbitrary precision integer arithmetic library
+ *
+ * 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/. */
+
+/* Table mapping test suite names to index numbers */
+const int g_count = 41;
+const char *g_names[] = {
+ "list", /* print out a list of the available test suites */
+ "copy", /* test assignment of mp-int structures */
+ "exchange", /* test exchange of mp-int structures */
+ "zero", /* test zeroing of an mp-int */
+ "set", /* test setting an mp-int to a small constant */
+ "absolute-value", /* test the absolute value function */
+ "negate", /* test the arithmetic negation function */
+ "add-digit", /* test digit addition */
+ "add", /* test full addition */
+ "subtract-digit", /* test digit subtraction */
+ "subtract", /* test full subtraction */
+ "multiply-digit", /* test digit multiplication */
+ "multiply", /* test full multiplication */
+ "square", /* test full squaring function */
+ "divide-digit", /* test digit division */
+ "divide-2", /* test division by two */
+ "divide-2d", /* test division & remainder by 2^d */
+ "divide", /* test full division */
+ "expt-digit", /* test digit exponentiation */
+ "expt", /* test full exponentiation */
+ "expt-2", /* test power-of-two exponentiation */
+ "modulo-digit", /* test digit modular reduction */
+ "modulo", /* test full modular reduction */
+ "mod-add", /* test modular addition */
+ "mod-subtract", /* test modular subtraction */
+ "mod-multiply", /* test modular multiplication */
+ "mod-square", /* test modular squaring function */
+ "mod-expt", /* test full modular exponentiation */
+ "mod-expt-digit", /* test digit modular exponentiation */
+ "mod-inverse", /* test modular inverse function */
+ "compare-digit", /* test digit comparison function */
+ "compare-zero", /* test zero comparison function */
+ "compare", /* test general signed comparison */
+ "compare-magnitude", /* test general magnitude comparison */
+ "parity", /* test parity comparison functions */
+ "gcd", /* test greatest common divisor functions */
+ "lcm", /* test least common multiple function */
+ "conversion", /* test general radix conversion facilities */
+ "binary", /* test raw output format */
+ "pprime", /* test probabilistic primality tester */
+ "fermat" /* test Fermat pseudoprimality tester */
+};
+
+/* Test function prototypes */
+int test_list(void);
+int test_copy(void);
+int test_exch(void);
+int test_zero(void);
+int test_set(void);
+int test_abs(void);
+int test_neg(void);
+int test_add_d(void);
+int test_add(void);
+int test_sub_d(void);
+int test_sub(void);
+int test_mul_d(void);
+int test_mul(void);
+int test_sqr(void);
+int test_div_d(void);
+int test_div_2(void);
+int test_div_2d(void);
+int test_div(void);
+int test_expt_d(void);
+int test_expt(void);
+int test_2expt(void);
+int test_mod_d(void);
+int test_mod(void);
+int test_addmod(void);
+int test_submod(void);
+int test_mulmod(void);
+int test_sqrmod(void);
+int test_exptmod(void);
+int test_exptmod_d(void);
+int test_invmod(void);
+int test_cmp_d(void);
+int test_cmp_z(void);
+int test_cmp(void);
+int test_cmp_mag(void);
+int test_parity(void);
+int test_gcd(void);
+int test_lcm(void);
+int test_convert(void);
+int test_raw(void);
+int test_pprime(void);
+int test_fermat(void);
+
+/* Table mapping index numbers to functions */
+int (*g_tests[])(void) = {
+ test_list, test_copy, test_exch, test_zero,
+ test_set, test_abs, test_neg, test_add_d,
+ test_add, test_sub_d, test_sub, test_mul_d,
+ test_mul, test_sqr, test_div_d, test_div_2,
+ test_div_2d, test_div, test_expt_d, test_expt,
+ test_2expt, test_mod_d, test_mod,
+ test_addmod, test_submod, test_mulmod, test_sqrmod,
+ test_exptmod, test_exptmod_d, test_invmod, test_cmp_d,
+ test_cmp_z, test_cmp, test_cmp_mag, test_parity,
+ test_gcd, test_lcm, test_convert, test_raw,
+ test_pprime, test_fermat
+};
+
+/* Table mapping index numbers to descriptions */
+const char *g_descs[] = {
+ "print out a list of the available test suites",
+ "test assignment of mp-int structures",
+ "test exchange of mp-int structures",
+ "test zeroing of an mp-int",
+ "test setting an mp-int to a small constant",
+ "test the absolute value function",
+ "test the arithmetic negation function",
+ "test digit addition",
+ "test full addition",
+ "test digit subtraction",
+ "test full subtraction",
+ "test digit multiplication",
+ "test full multiplication",
+ "test full squaring function",
+ "test digit division",
+ "test division by two",
+ "test division & remainder by 2^d",
+ "test full division",
+ "test digit exponentiation",
+ "test full exponentiation",
+ "test power-of-two exponentiation",
+ "test digit modular reduction",
+ "test full modular reduction",
+ "test modular addition",
+ "test modular subtraction",
+ "test modular multiplication",
+ "test modular squaring function",
+ "test full modular exponentiation",
+ "test digit modular exponentiation",
+ "test modular inverse function",
+ "test digit comparison function",
+ "test zero comparison function",
+ "test general signed comparison",
+ "test general magnitude comparison",
+ "test parity comparison functions",
+ "test greatest common divisor functions",
+ "test least common multiple function",
+ "test general radix conversion facilities",
+ "test raw output format",
+ "test probabilistic primality tester",
+ "test Fermat pseudoprimality tester"
+};
diff --git a/security/nss/cmd/multinit/Makefile b/security/nss/cmd/multinit/Makefile
new file mode 100644
index 000000000..6e1d4ecdf
--- /dev/null
+++ b/security/nss/cmd/multinit/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/multinit/manifest.mn b/security/nss/cmd/multinit/manifest.mn
new file mode 100644
index 000000000..a86adc8c8
--- /dev/null
+++ b/security/nss/cmd/multinit/manifest.mn
@@ -0,0 +1,13 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = multinit.c
+
+PROGRAM = multinit
diff --git a/security/nss/cmd/multinit/multinit.c b/security/nss/cmd/multinit/multinit.c
new file mode 100644
index 000000000..a57c4819f
--- /dev/null
+++ b/security/nss/cmd/multinit/multinit.c
@@ -0,0 +1,881 @@
+/* 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/. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "nss.h"
+#include "secutil.h"
+#include "pk11pub.h"
+#include "cert.h"
+
+typedef struct commandDescriptStr {
+ int required;
+ char *arg;
+ char *des;
+} commandDescript;
+
+enum optionNames {
+ opt_liborder = 0,
+ opt_mainDB,
+ opt_lib1DB,
+ opt_lib2DB,
+ opt_mainRO,
+ opt_lib1RO,
+ opt_lib2RO,
+ opt_mainCMD,
+ opt_lib1CMD,
+ opt_lib2CMD,
+ opt_mainTokNam,
+ opt_lib1TokNam,
+ opt_lib2TokNam,
+ opt_oldStyle,
+ opt_verbose,
+ opt_summary,
+ opt_help,
+ opt_last
+};
+
+static const secuCommandFlag options_init[] =
+ {
+ { /* opt_liborder */ 'o', PR_TRUE, "1M2zmi", PR_TRUE, "order" },
+ { /* opt_mainDB */ 'd', PR_TRUE, 0, PR_FALSE, "main_db" },
+ { /* opt_lib1DB */ '1', PR_TRUE, 0, PR_FALSE, "lib1_db" },
+ { /* opt_lib2DB */ '2', PR_TRUE, 0, PR_FALSE, "lib2_db" },
+ { /* opt_mainRO */ 'r', PR_FALSE, 0, PR_FALSE, "main_readonly" },
+ { /* opt_lib1RO */ 0, PR_FALSE, 0, PR_FALSE, "lib1_readonly" },
+ { /* opt_lib2RO */ 0, PR_FALSE, 0, PR_FALSE, "lib2_readonly" },
+ { /* opt_mainCMD */ 'c', PR_TRUE, 0, PR_FALSE, "main_command" },
+ { /* opt_lib1CMD */ 0, PR_TRUE, 0, PR_FALSE, "lib1_command" },
+ { /* opt_lib2CMD */ 0, PR_TRUE, 0, PR_FALSE, "lib2_command" },
+ { /* opt_mainTokNam */ 't', PR_TRUE, 0, PR_FALSE, "main_token_name" },
+ { /* opt_lib1TokNam */ 0, PR_TRUE, 0, PR_FALSE, "lib1_token_name" },
+ { /* opt_lib2TokNam */ 0, PR_TRUE, 0, PR_FALSE, "lib2_token_name" },
+ { /* opt_oldStype */ 's', PR_FALSE, 0, PR_FALSE, "oldStype" },
+ { /* opt_verbose */ 'v', PR_FALSE, 0, PR_FALSE, "verbose" },
+ { /* opt_summary */ 'z', PR_FALSE, 0, PR_FALSE, "summary" },
+ { /* opt_help */ 'h', PR_FALSE, 0, PR_FALSE, "help" }
+ };
+
+static const commandDescript options_des[] =
+ {
+ { /* opt_liborder */ PR_FALSE, "initOrder",
+ " Specifies the order of NSS initialization and shutdown. Order is\n"
+ " given as a string where each character represents either an init or\n"
+ " a shutdown of the main program or one of the 2 test libraries\n"
+ " (library 1 and library 2). The valid characters are as follows:\n"
+ " M Init the main program\n 1 Init library 1\n"
+ " 2 Init library 2\n"
+ " m Shutdown the main program\n i Shutdown library 1\n"
+ " z Shutdown library 2\n" },
+ { /* opt_mainDB */ PR_TRUE, "nss_db",
+ " Specified the directory to open the nss database for the main\n"
+ " program. Must be specified if \"M\" is given in the order string\n" },
+ { /* opt_lib1DB */ PR_FALSE, "nss_db",
+ " Specified the directory to open the nss database for library 1.\n"
+ " Must be specified if \"1\" is given in the order string\n" },
+ { /* opt_lib2DB */ PR_FALSE, "nss_db",
+ " Specified the directory to open the nss database for library 2.\n"
+ " Must be specified if \"2\" is given in the order string\n" },
+ { /* opt_mainRO */ PR_FALSE, NULL,
+ " Open the main program's database read only.\n" },
+ { /* opt_lib1RO */ PR_FALSE, NULL,
+ " Open library 1's database read only.\n" },
+ { /* opt_lib2RO */ PR_FALSE, NULL,
+ " Open library 2's database read only.\n" },
+ { /* opt_mainCMD */ PR_FALSE, "nss_command",
+ " Specifies the NSS command to execute in the main program.\n"
+ " Valid commands are: \n"
+ " key_slot, list_slots, list_certs, add_cert, none.\n"
+ " Default is \"none\".\n" },
+ { /* opt_lib1CMD */ PR_FALSE, "nss_command",
+ " Specifies the NSS command to execute in library 1.\n" },
+ { /* opt_lib2CMD */ PR_FALSE, "nss_command",
+ " Specifies the NSS command to execute in library 2.\n" },
+ { /* opt_mainTokNam */ PR_FALSE, "token_name",
+ " Specifies the name of PKCS11 token for the main program's "
+ "database.\n" },
+ { /* opt_lib1TokNam */ PR_FALSE, "token_name",
+ " Specifies the name of PKCS11 token for library 1's database.\n" },
+ { /* opt_lib2TokNam */ PR_FALSE, "token_name",
+ " Specifies the name of PKCS11 token for library 2's database.\n" },
+ { /* opt_oldStype */ PR_FALSE, NULL,
+ " Use NSS_Shutdown rather than NSS_ShutdownContext in the main\n"
+ " program.\n" },
+ { /* opt_verbose */ PR_FALSE, NULL,
+ " Noisily output status to standard error\n" },
+ { /* opt_summarize */ PR_FALSE, NULL,
+ "report a summary of the test results\n" },
+ { /* opt_help */ PR_FALSE, NULL, " give this message\n" }
+ };
+
+/*
+ * output our short help (table driven). (does not exit).
+ */
+static void
+short_help(const char *prog)
+{
+ int count = opt_last;
+ int i, words_found;
+
+ /* make sure all the tables are up to date before we allow compiles to
+ * succeed */
+ PR_STATIC_ASSERT(sizeof(options_init) / sizeof(secuCommandFlag) == opt_last);
+ PR_STATIC_ASSERT(sizeof(options_init) / sizeof(secuCommandFlag) ==
+ sizeof(options_des) / sizeof(commandDescript));
+
+ /* print the base usage */
+ fprintf(stderr, "usage: %s ", prog);
+ for (i = 0, words_found = 0; i < count; i++) {
+ if (!options_des[i].required) {
+ fprintf(stderr, "[");
+ }
+ if (options_init[i].longform) {
+ fprintf(stderr, "--%s", options_init[i].longform);
+ words_found++;
+ } else {
+ fprintf(stderr, "-%c", options_init[i].flag);
+ }
+ if (options_init[i].needsArg) {
+ if (options_des[i].arg) {
+ fprintf(stderr, " %s", options_des[i].arg);
+ } else {
+ fprintf(stderr, " arg");
+ }
+ words_found++;
+ }
+ if (!options_des[i].required) {
+ fprintf(stderr, "]");
+ }
+ if (i < count - 1) {
+ if (words_found >= 5) {
+ fprintf(stderr, "\n ");
+ words_found = 0;
+ } else {
+ fprintf(stderr, " ");
+ }
+ }
+ }
+ fprintf(stderr, "\n");
+}
+
+/*
+ * print out long help. like short_help, this does not exit
+ */
+static void
+long_help(const char *prog)
+{
+ int i;
+ int count = opt_last;
+
+ short_help(prog);
+ /* print the option descriptions */
+ fprintf(stderr, "\n");
+ for (i = 0; i < count; i++) {
+ fprintf(stderr, " ");
+ if (options_init[i].flag) {
+ fprintf(stderr, "-%c", options_init[i].flag);
+ if (options_init[i].longform) {
+ fprintf(stderr, ",");
+ }
+ }
+ if (options_init[i].longform) {
+ fprintf(stderr, "--%s", options_init[i].longform);
+ }
+ if (options_init[i].needsArg) {
+ if (options_des[i].arg) {
+ fprintf(stderr, " %s", options_des[i].arg);
+ } else {
+ fprintf(stderr, " arg");
+ }
+ if (options_init[i].arg) {
+ fprintf(stderr, " (default = \"%s\")", options_init[i].arg);
+ }
+ }
+ fprintf(stderr, "\n%s", options_des[i].des);
+ }
+}
+
+/*
+ * record summary data
+ */
+struct bufferData {
+ char *data; /* lowest address of the buffer */
+ char *next; /* pointer to the next element on the buffer */
+ int len; /* length of the buffer */
+};
+
+/* our actual buffer. If data is NULL, then all append ops
+ * except are noops */
+static struct bufferData buffer = { NULL, NULL, 0 };
+
+#define CHUNK_SIZE 1000
+
+/*
+ * get our initial data. and set the buffer variables up. on failure,
+ * just don't initialize the buffer.
+ */
+static void
+initBuffer(void)
+{
+ buffer.data = PORT_Alloc(CHUNK_SIZE);
+ if (!buffer.data) {
+ return;
+ }
+ buffer.next = buffer.data;
+ buffer.len = CHUNK_SIZE;
+}
+
+/*
+ * grow the buffer. If we can't get more data, record a 'D' in the second
+ * to last record and allow the rest of the data to overwrite the last
+ * element.
+ */
+static void
+growBuffer(void)
+{
+ char *new = PORT_Realloc(buffer.data, buffer.len + CHUNK_SIZE);
+ if (!new) {
+ buffer.data[buffer.len - 2] = 'D'; /* signal malloc failure in summary */
+ /* buffer must always point to good memory if it exists */
+ buffer.next = buffer.data + (buffer.len - 1);
+ return;
+ }
+ buffer.next = new + (buffer.next - buffer.data);
+ buffer.data = new;
+ buffer.len += CHUNK_SIZE;
+}
+
+/*
+ * append a label, doubles as appending a single character.
+ */
+static void
+appendLabel(char label)
+{
+ if (!buffer.data) {
+ return;
+ }
+
+ *buffer.next++ = label;
+ if (buffer.data + buffer.len >= buffer.next) {
+ growBuffer();
+ }
+}
+
+/*
+ * append a string onto the buffer. The result will be <string>
+ */
+static void
+appendString(char *string)
+{
+ if (!buffer.data) {
+ return;
+ }
+
+ appendLabel('<');
+ while (*string) {
+ appendLabel(*string++);
+ }
+ appendLabel('>');
+}
+
+/*
+ * append a bool, T= true, F=false
+ */
+static void
+appendBool(PRBool bool)
+{
+ if (!buffer.data) {
+ return;
+ }
+
+ if (bool) {
+ appendLabel('t');
+ } else {
+ appendLabel('f');
+ }
+}
+
+/*
+ * append a single hex nibble.
+ */
+static void
+appendHex(unsigned char nibble)
+{
+ if (nibble <= 9) {
+ appendLabel('0' + nibble);
+ } else {
+ appendLabel('a' + nibble - 10);
+ }
+}
+
+/*
+ * append a 32 bit integer (even on a 64 bit platform).
+ * for simplicity append it as a hex value, full extension with 0x prefix.
+ */
+static void
+appendInt(unsigned int value)
+{
+ int i;
+
+ if (!buffer.data) {
+ return;
+ }
+
+ appendLabel('0');
+ appendLabel('x');
+ value = value & 0xffffffff; /* only look at the buttom 8 bytes */
+ for (i = 0; i < 8; i++) {
+ appendHex(value >> 28);
+ value = value << 4;
+ }
+}
+
+/* append a trust flag */
+static void
+appendFlags(unsigned int flag)
+{
+ char trust[10];
+ char *cp = trust;
+
+ trust[0] = 0;
+ printflags(trust, flag);
+ while (*cp) {
+ appendLabel(*cp++);
+ }
+}
+
+/*
+ * dump our buffer out with a result= flag so we can find it easily.
+ * free the buffer as a side effect.
+ */
+static void
+dumpBuffer(void)
+{
+ if (!buffer.data) {
+ return;
+ }
+
+ appendLabel(0); /* terminate */
+ printf("\nresult=%s\n", buffer.data);
+ PORT_Free(buffer.data);
+ buffer.data = buffer.next = NULL;
+ buffer.len = 0;
+}
+
+/*
+ * usage, like traditional usage, automatically exit
+ */
+static void
+usage(const char *prog)
+{
+ short_help(prog);
+ dumpBuffer();
+ exit(1);
+}
+
+/*
+ * like usage, except prints the long version of help
+ */
+static void
+usage_long(const char *prog)
+{
+ long_help(prog);
+ dumpBuffer();
+ exit(1);
+}
+
+static const char *
+bool2String(PRBool bool)
+{
+ return bool ? "true" : "false";
+}
+
+/*
+ * print out interesting info about the given slot
+ */
+void
+print_slot(PK11SlotInfo *slot, int log)
+{
+ if (log) {
+ fprintf(stderr, "* Name=%s Token_Name=%s present=%s, ro=%s *\n",
+ PK11_GetSlotName(slot), PK11_GetTokenName(slot),
+ bool2String(PK11_IsPresent(slot)),
+ bool2String(PK11_IsReadOnly(slot)));
+ }
+ appendLabel('S');
+ appendString(PK11_GetTokenName(slot));
+ appendBool(PK11_IsPresent(slot));
+ appendBool(PK11_IsReadOnly(slot));
+}
+
+/*
+ * list all our slots
+ */
+void
+do_list_slots(const char *progName, int log)
+{
+ PK11SlotList *list;
+ PK11SlotListElement *le;
+
+ list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL);
+ if (list == NULL) {
+ fprintf(stderr, "ERROR: no tokens found %s\n",
+ SECU_Strerror(PORT_GetError()));
+ appendLabel('S');
+ appendString("none");
+ return;
+ }
+
+ for (le = PK11_GetFirstSafe(list); le;
+ le = PK11_GetNextSafe(list, le, PR_TRUE)) {
+ print_slot(le->slot, log);
+ }
+ PK11_FreeSlotList(list);
+}
+
+static PRBool
+sort_CN(CERTCertificate *certa, CERTCertificate *certb, void *arg)
+{
+ char *commonNameA, *commonNameB;
+ int ret;
+
+ commonNameA = CERT_GetCommonName(&certa->subject);
+ commonNameB = CERT_GetCommonName(&certb->subject);
+
+ if (commonNameA == NULL) {
+ PORT_Free(commonNameB);
+ return PR_TRUE;
+ }
+ if (commonNameB == NULL) {
+ PORT_Free(commonNameA);
+ return PR_FALSE;
+ }
+ ret = PORT_Strcmp(commonNameA, commonNameB);
+ PORT_Free(commonNameA);
+ PORT_Free(commonNameB);
+ return (ret < 0) ? PR_TRUE : PR_FALSE;
+}
+
+/*
+ * list all the certs
+ */
+void
+do_list_certs(const char *progName, int log)
+{
+ CERTCertList *list;
+ CERTCertList *sorted;
+ CERTCertListNode *node;
+ CERTCertTrust trust;
+ unsigned int i;
+
+ list = PK11_ListCerts(PK11CertListUnique, NULL);
+ if (list == NULL) {
+ fprintf(stderr, "ERROR: no certs found %s\n",
+ SECU_Strerror(PORT_GetError()));
+ appendLabel('C');
+ appendString("none");
+ return;
+ }
+
+ sorted = CERT_NewCertList();
+ if (sorted == NULL) {
+ fprintf(stderr, "ERROR: no certs found %s\n",
+ SECU_Strerror(PORT_GetError()));
+ appendLabel('C');
+ appendLabel('E');
+ appendInt(PORT_GetError());
+ return;
+ }
+
+ /* sort the list */
+ for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
+ node = CERT_LIST_NEXT(node)) {
+ CERT_AddCertToListSorted(sorted, node->cert, sort_CN, NULL);
+ }
+
+ for (node = CERT_LIST_HEAD(sorted); !CERT_LIST_END(node, sorted);
+ node = CERT_LIST_NEXT(node)) {
+ CERTCertificate *cert = node->cert;
+ char *commonName;
+
+ SECU_PrintCertNickname(node, stderr);
+ if (log) {
+ fprintf(stderr, "* Slot=%s*\n", cert->slot ? PK11_GetTokenName(cert->slot)
+ : "none");
+ fprintf(stderr, "* Nickname=%s*\n", cert->nickname);
+ fprintf(stderr, "* Subject=<%s>*\n", cert->subjectName);
+ fprintf(stderr, "* Issuer=<%s>*\n", cert->issuerName);
+ fprintf(stderr, "* SN=");
+ for (i = 0; i < cert->serialNumber.len; i++) {
+ if (i != 0)
+ fprintf(stderr, ":");
+ fprintf(stderr, "%02x", cert->serialNumber.data[0]);
+ }
+ fprintf(stderr, " *\n");
+ }
+ appendLabel('C');
+ commonName = CERT_GetCommonName(&cert->subject);
+ appendString(commonName ? commonName : "*NoName*");
+ PORT_Free(commonName);
+ if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
+ appendFlags(trust.sslFlags);
+ appendFlags(trust.emailFlags);
+ appendFlags(trust.objectSigningFlags);
+ }
+ }
+ CERT_DestroyCertList(list);
+}
+
+/*
+ * need to implement yet... try to add a new certificate
+ */
+void
+do_add_cert(const char *progName, int log)
+{
+ PORT_Assert(/* do_add_cert not implemented */ 0);
+}
+
+/*
+ * display the current key slot
+ */
+void
+do_key_slot(const char *progName, int log)
+{
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot();
+ if (!slot) {
+ fprintf(stderr, "ERROR: no internal key slot found %s\n",
+ SECU_Strerror(PORT_GetError()));
+ appendLabel('K');
+ appendLabel('S');
+ appendString("none");
+ }
+ print_slot(slot, log);
+ PK11_FreeSlot(slot);
+}
+
+/*
+ * execute some NSS command.
+ */
+void
+do_command(const char *label, int initialized, secuCommandFlag *command,
+ const char *progName, int log)
+{
+ char *command_string;
+ if (!initialized) {
+ return;
+ }
+
+ if (command->activated) {
+ command_string = command->arg;
+ } else {
+ command_string = "none";
+ }
+
+ if (log) {
+ fprintf(stderr, "*Executing nss command \"%s\" for %s*\n",
+ command_string, label);
+ }
+
+ /* do something */
+ if (PORT_Strcasecmp(command_string, "list_slots") == 0) {
+ do_list_slots(progName, log);
+ } else if (PORT_Strcasecmp(command_string, "list_certs") == 0) {
+ do_list_certs(progName, log);
+ } else if (PORT_Strcasecmp(command_string, "add_cert") == 0) {
+ do_add_cert(progName, log);
+ } else if (PORT_Strcasecmp(command_string, "key_slot") == 0) {
+ do_key_slot(progName, log);
+ } else if (PORT_Strcasecmp(command_string, "none") != 0) {
+ fprintf(stderr, ">> Unknown command (%s)\n", command_string);
+ appendLabel('E');
+ appendString("bc");
+ usage_long(progName);
+ }
+}
+
+/*
+ * functions do handle
+ * different library initializations.
+ */
+static int main_initialized;
+static int lib1_initialized;
+static int lib2_initialized;
+
+void
+main_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
+ int readOnly, const char *progName, int log)
+{
+ SECStatus rv;
+ if (log) {
+ fprintf(stderr, "*NSS_Init for the main program*\n");
+ }
+ appendLabel('M');
+ if (!db->activated) {
+ fprintf(stderr, ">> No main_db has been specified\n");
+ usage(progName);
+ }
+ if (main_initialized) {
+ fprintf(stderr, "Warning: Second initialization of Main\n");
+ appendLabel('E');
+ appendString("2M");
+ }
+ if (tokNam->activated) {
+ PK11_ConfigurePKCS11(NULL, NULL, NULL, tokNam->arg,
+ NULL, NULL, NULL, NULL, 0, 0);
+ }
+ rv = NSS_Initialize(db->arg, "", "", "",
+ NSS_INIT_NOROOTINIT |
+ (readOnly ? NSS_INIT_READONLY : 0));
+ if (rv != SECSuccess) {
+ appendLabel('E');
+ appendInt(PORT_GetError());
+ fprintf(stderr, ">> %s\n", SECU_Strerror(PORT_GetError()));
+ dumpBuffer();
+ exit(1);
+ }
+ main_initialized = 1;
+}
+
+void
+main_Do(secuCommandFlag *command, const char *progName, int log)
+{
+ do_command("main", main_initialized, command, progName, log);
+}
+
+void
+main_Shutdown(int old_style, const char *progName, int log)
+{
+ SECStatus rv;
+ appendLabel('N');
+ if (log) {
+ fprintf(stderr, "*NSS_Shutdown for the main program*\n");
+ }
+ if (!main_initialized) {
+ fprintf(stderr, "Warning: Main shutdown without corresponding init\n");
+ }
+ if (old_style) {
+ rv = NSS_Shutdown();
+ } else {
+ rv = NSS_ShutdownContext(NULL);
+ }
+ fprintf(stderr, "Shutdown main state = %d\n", rv);
+ if (rv != SECSuccess) {
+ appendLabel('E');
+ appendInt(PORT_GetError());
+ fprintf(stderr, "ERROR: %s\n", SECU_Strerror(PORT_GetError()));
+ }
+ main_initialized = 0;
+}
+
+/* common library init */
+NSSInitContext *
+lib_Init(const char *lableString, char label, int initialized,
+ secuCommandFlag *db, secuCommandFlag *tokNam, int readonly,
+ const char *progName, int log)
+{
+ NSSInitContext *ctxt;
+ NSSInitParameters initStrings;
+ NSSInitParameters *initStringPtr = NULL;
+
+ appendLabel(label);
+ if (log) {
+ fprintf(stderr, "*NSS_Init for %s*\n", lableString);
+ }
+
+ if (!db->activated) {
+ fprintf(stderr, ">> No %s_db has been specified\n", lableString);
+ usage(progName);
+ }
+ if (initialized) {
+ fprintf(stderr, "Warning: Second initialization of %s\n", lableString);
+ }
+ if (tokNam->activated) {
+ PORT_Memset(&initStrings, 0, sizeof(initStrings));
+ initStrings.length = sizeof(initStrings);
+ initStrings.dbTokenDescription = tokNam->arg;
+ initStringPtr = &initStrings;
+ }
+ ctxt = NSS_InitContext(db->arg, "", "", "", initStringPtr,
+ NSS_INIT_NOROOTINIT |
+ (readonly ? NSS_INIT_READONLY : 0));
+ if (ctxt == NULL) {
+ appendLabel('E');
+ appendInt(PORT_GetError());
+ fprintf(stderr, ">> %s\n", SECU_Strerror(PORT_GetError()));
+ dumpBuffer();
+ exit(1);
+ }
+ return ctxt;
+}
+
+/* common library shutdown */
+void
+lib_Shutdown(const char *labelString, char label, NSSInitContext *ctx,
+ int initialize, const char *progName, int log)
+{
+ SECStatus rv;
+ appendLabel(label);
+ if (log) {
+ fprintf(stderr, "*NSS_Shutdown for %s\n*", labelString);
+ }
+ if (!initialize) {
+ fprintf(stderr, "Warning: %s shutdown without corresponding init\n",
+ labelString);
+ }
+ rv = NSS_ShutdownContext(ctx);
+ fprintf(stderr, "Shutdown %s state = %d\n", labelString, rv);
+ if (rv != SECSuccess) {
+ appendLabel('E');
+ appendInt(PORT_GetError());
+ fprintf(stderr, "ERROR: %s\n", SECU_Strerror(PORT_GetError()));
+ }
+}
+
+static NSSInitContext *lib1_context;
+static NSSInitContext *lib2_context;
+void
+lib1_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
+ int readOnly, const char *progName, int log)
+{
+ lib1_context = lib_Init("lib1", '1', lib1_initialized, db, tokNam,
+ readOnly, progName, log);
+ lib1_initialized = 1;
+}
+
+void
+lib2_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
+ int readOnly, const char *progName, int log)
+{
+ lib2_context = lib_Init("lib2", '2', lib2_initialized,
+ db, tokNam, readOnly, progName, log);
+ lib2_initialized = 1;
+}
+
+void
+lib1_Do(secuCommandFlag *command, const char *progName, int log)
+{
+ do_command("lib1", lib1_initialized, command, progName, log);
+}
+
+void
+lib2_Do(secuCommandFlag *command, const char *progName, int log)
+{
+ do_command("lib2", lib2_initialized, command, progName, log);
+}
+
+void
+lib1_Shutdown(const char *progName, int log)
+{
+ lib_Shutdown("lib1", 'I', lib1_context, lib1_initialized, progName, log);
+ lib1_initialized = 0;
+ /* don't clear lib1_Context, so we can test multiple attempts to close
+ * the same context produces correct errors*/
+}
+
+void
+lib2_Shutdown(const char *progName, int log)
+{
+ lib_Shutdown("lib2", 'Z', lib2_context, lib2_initialized, progName, log);
+ lib2_initialized = 0;
+ /* don't clear lib2_Context, so we can test multiple attempts to close
+ * the same context produces correct errors*/
+}
+
+int
+main(int argc, char **argv)
+{
+ SECStatus rv;
+ secuCommand libinit;
+ char *progName;
+ char *order;
+ secuCommandFlag *options;
+ int log = 0;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ libinit.numCommands = 0;
+ libinit.commands = 0;
+ libinit.numOptions = opt_last;
+ options = (secuCommandFlag *)PORT_Alloc(sizeof(options_init));
+ if (options == NULL) {
+ fprintf(stderr, ">> %s:Not enough free memory to run command\n",
+ progName);
+ exit(1);
+ }
+ PORT_Memcpy(options, options_init, sizeof(options_init));
+ libinit.options = options;
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &libinit);
+ if (rv != SECSuccess) {
+ usage(progName);
+ }
+
+ if (libinit.options[opt_help].activated) {
+ long_help(progName);
+ exit(0);
+ }
+
+ log = libinit.options[opt_verbose].activated;
+ if (libinit.options[opt_summary].activated) {
+ initBuffer();
+ }
+
+ order = libinit.options[opt_liborder].arg;
+ if (!order) {
+ usage(progName);
+ }
+
+ if (log) {
+ fprintf(stderr, "* initializing with order \"%s\"*\n", order);
+ }
+
+ for (; *order; order++) {
+ switch (*order) {
+ case 'M':
+ main_Init(&libinit.options[opt_mainDB],
+ &libinit.options[opt_mainTokNam],
+ libinit.options[opt_mainRO].activated,
+ progName, log);
+ break;
+ case '1':
+ lib1_Init(&libinit.options[opt_lib1DB],
+ &libinit.options[opt_lib1TokNam],
+ libinit.options[opt_lib1RO].activated,
+ progName, log);
+ break;
+ case '2':
+ lib2_Init(&libinit.options[opt_lib2DB],
+ &libinit.options[opt_lib2TokNam],
+ libinit.options[opt_lib2RO].activated,
+ progName, log);
+ break;
+ case 'm':
+ main_Shutdown(libinit.options[opt_oldStyle].activated,
+ progName, log);
+ break;
+ case 'i':
+ lib1_Shutdown(progName, log);
+ break;
+ case 'z':
+ lib2_Shutdown(progName, log);
+ break;
+ default:
+ fprintf(stderr, ">> Unknown init/shutdown command \"%c\"", *order);
+ usage_long(progName);
+ }
+ main_Do(&libinit.options[opt_mainCMD], progName, log);
+ lib1_Do(&libinit.options[opt_lib1CMD], progName, log);
+ lib2_Do(&libinit.options[opt_lib2CMD], progName, log);
+ }
+
+ if (NSS_IsInitialized()) {
+ appendLabel('X');
+ fprintf(stderr, "Warning: NSS is initialized\n");
+ }
+ dumpBuffer();
+
+ exit(0);
+}
diff --git a/security/nss/cmd/multinit/multinit.gyp b/security/nss/cmd/multinit/multinit.gyp
new file mode 100644
index 000000000..b99c01843
--- /dev/null
+++ b/security/nss/cmd/multinit/multinit.gyp
@@ -0,0 +1,24 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'multinit',
+ 'type': 'executable',
+ 'sources': [
+ 'multinit.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/ocspclnt/Makefile b/security/nss/cmd/ocspclnt/Makefile
new file mode 100644
index 000000000..265ea5601
--- /dev/null
+++ b/security/nss/cmd/ocspclnt/Makefile
@@ -0,0 +1,45 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
diff --git a/security/nss/cmd/ocspclnt/manifest.mn b/security/nss/cmd/ocspclnt/manifest.mn
new file mode 100644
index 000000000..a2794a383
--- /dev/null
+++ b/security/nss/cmd/ocspclnt/manifest.mn
@@ -0,0 +1,24 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ ocspclnt.c \
+ $(NULL)
+
+# headers for the MODULE (defined above) are implicitly required.
+REQUIRES = dbm seccmd
+
+# WINNT uses EXTRA_LIBS as the list of libs to link in.
+# Unix uses OS_LIBS for that purpose.
+# We can solve this via conditional makefile code, but
+# can't do this in manifest.mn because OS_ARCH isn't defined there.
+# So, look in the local Makefile for the defines for the list of libs.
+
+PROGRAM = ocspclnt
diff --git a/security/nss/cmd/ocspclnt/ocspclnt.c b/security/nss/cmd/ocspclnt/ocspclnt.c
new file mode 100644
index 000000000..afcb7e13f
--- /dev/null
+++ b/security/nss/cmd/ocspclnt/ocspclnt.c
@@ -0,0 +1,1243 @@
+/* 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/. */
+
+/*
+ * Test program for client-side OCSP.
+ */
+
+#include "secutil.h"
+#include "nspr.h"
+#include "plgetopt.h"
+#include "nss.h"
+#include "cert.h"
+#include "ocsp.h"
+#include "xconst.h" /*
+ * XXX internal header file; needed to get at
+ * cert_DecodeAuthInfoAccessExtension -- would be
+ * nice to not need this, but that would require
+ * better/different APIs.
+ */
+
+#ifndef NO_PP /* \
+ * Compile with this every once in a while to be \
+ * sure that no dependencies on it get added \
+ * outside of the pretty-printing routines. \
+ */
+#include "ocspti.h" /* internals for pretty-printing routines *only* */
+#endif /* NO_PP */
+
+#if defined(_WIN32)
+#include "fcntl.h"
+#include "io.h"
+#endif
+
+#define DEFAULT_DB_DIR "~/.netscape"
+
+/* global */
+char *program_name;
+
+static void
+synopsis(char *program_name)
+{
+ PRFileDesc *pr_stderr;
+
+ pr_stderr = PR_STDERR;
+ PR_fprintf(pr_stderr, "Usage:");
+ PR_fprintf(pr_stderr,
+ "\t%s -p [-d <dir>]\n",
+ program_name);
+ PR_fprintf(pr_stderr,
+ "\t%s -P [-d <dir>]\n",
+ program_name);
+ PR_fprintf(pr_stderr,
+ "\t%s -r <name> [-a] [-L] [-s <name>] [-d <dir>]\n",
+ program_name);
+ PR_fprintf(pr_stderr,
+ "\t%s -R <name> [-a] [-l <location>] [-s <name>] [-d <dir>]\n",
+ program_name);
+ PR_fprintf(pr_stderr,
+ "\t%s -S <name> [-a] [-l <location> -t <name>]\n",
+ program_name);
+ PR_fprintf(pr_stderr,
+ "\t\t [-s <name>] [-w <time>] [-d <dir>]\n");
+ PR_fprintf(pr_stderr,
+ "\t%s -V <name> [-a] -u <usage> [-l <location> -t <name>]\n",
+ program_name);
+ PR_fprintf(pr_stderr,
+ "\t\t [-s <name>] [-w <time>] [-d <dir>]\n");
+}
+
+static void
+short_usage(char *program_name)
+{
+ PR_fprintf(PR_STDERR,
+ "Type %s -H for more detailed descriptions\n",
+ program_name);
+ synopsis(program_name);
+}
+
+static void
+long_usage(char *program_name)
+{
+ PRFileDesc *pr_stderr;
+
+ pr_stderr = PR_STDERR;
+ synopsis(program_name);
+ PR_fprintf(pr_stderr, "\nCommands (must specify exactly one):\n");
+ PR_fprintf(pr_stderr,
+ " %-13s Pretty-print a binary request read from stdin\n",
+ "-p");
+ PR_fprintf(pr_stderr,
+ " %-13s Pretty-print a binary response read from stdin\n",
+ "-P");
+ PR_fprintf(pr_stderr,
+ " %-13s Create a request for cert \"nickname\" on stdout\n",
+ "-r nickname");
+ PR_fprintf(pr_stderr,
+ " %-13s Get response for cert \"nickname\", dump to stdout\n",
+ "-R nickname");
+ PR_fprintf(pr_stderr,
+ " %-13s Get status for cert \"nickname\"\n",
+ "-S nickname");
+ PR_fprintf(pr_stderr,
+ " %-13s Fully verify cert \"nickname\", w/ status check\n",
+ "-V nickname");
+ PR_fprintf(pr_stderr,
+ "\n %-10s also can be the name of the file with DER or\n"
+ " %-13s PEM(use -a option) cert encoding\n",
+ "nickname", "");
+ PR_fprintf(pr_stderr, "Options:\n");
+ PR_fprintf(pr_stderr,
+ " %-13s Decode input cert from PEM format. DER is default\n",
+ "-a");
+ PR_fprintf(pr_stderr,
+ " %-13s Add the service locator extension to the request\n",
+ "-L");
+ PR_fprintf(pr_stderr,
+ " %-13s Find security databases in \"dbdir\" (default %s)\n",
+ "-d dbdir", DEFAULT_DB_DIR);
+ PR_fprintf(pr_stderr,
+ " %-13s Use \"location\" as URL of responder\n",
+ "-l location");
+ PR_fprintf(pr_stderr,
+ " %-13s Trust cert \"nickname\" as response signer\n",
+ "-t nickname");
+ PR_fprintf(pr_stderr,
+ " %-13s Sign requests with cert \"nickname\"\n",
+ "-s nickname");
+ PR_fprintf(pr_stderr,
+ " %-13s Type of certificate usage for verification:\n",
+ "-u usage");
+ PR_fprintf(pr_stderr,
+ "%-17s c SSL Client\n", "");
+ PR_fprintf(pr_stderr,
+ "%-17s s SSL Server\n", "");
+ PR_fprintf(pr_stderr,
+ "%-17s e Email Recipient\n", "");
+ PR_fprintf(pr_stderr,
+ "%-17s E Email Signer\n", "");
+ PR_fprintf(pr_stderr,
+ "%-17s S Object Signer\n", "");
+ PR_fprintf(pr_stderr,
+ "%-17s C CA\n", "");
+ PR_fprintf(pr_stderr,
+ " %-13s Validity time (default current time), one of:\n",
+ "-w time");
+ PR_fprintf(pr_stderr,
+ "%-17s %-25s (GMT)\n", "", "YYMMDDhhmm[ss]Z");
+ PR_fprintf(pr_stderr,
+ "%-17s %-25s (later than GMT)\n", "", "YYMMDDhhmm[ss]+hhmm");
+ PR_fprintf(pr_stderr,
+ "%-17s %-25s (earlier than GMT)\n", "", "YYMMDDhhmm[ss]-hhmm");
+}
+
+#if defined(WIN32)
+/* We're going to write binary data to stdout, or read binary from stdin.
+ * We must put stdout or stdin into O_BINARY mode or else
+ outgoing \n's will become \r\n's, and incoming \r\n's will become \n's.
+*/
+static SECStatus
+make_file_binary(FILE *binfile)
+{
+ int smrv = _setmode(_fileno(binfile), _O_BINARY);
+ if (smrv == -1) {
+ fprintf(stderr, "%s: Cannot change stdout to binary mode.\n",
+ program_name);
+ }
+ return smrv;
+}
+#define MAKE_FILE_BINARY make_file_binary
+#else
+#define MAKE_FILE_BINARY(file)
+#endif
+
+/*
+ * XXX This is a generic function that would probably make a good
+ * replacement for SECU_DER_Read (which is not at all specific to DER,
+ * despite its name), but that requires fixing all of the tools...
+ * Still, it should be done, whenenver I/somebody has the time.
+ * (Also, consider whether this actually belongs in the security
+ * library itself, not just in the command library.)
+ *
+ * This function takes an open file (a PRFileDesc *) and reads the
+ * entire file into a SECItem. (Obviously, the file is intended to
+ * be small enough that such a thing is advisable.) Both the SECItem
+ * and the buffer it points to are allocated from the heap; the caller
+ * is expected to free them. ("SECITEM_FreeItem(item, PR_TRUE)")
+ */
+static SECItem *
+read_file_into_item(PRFileDesc *in_file, SECItemType si_type)
+{
+ PRStatus prv;
+ SECItem *item;
+ PRFileInfo file_info;
+ PRInt32 bytes_read;
+
+ prv = PR_GetOpenFileInfo(in_file, &file_info);
+ if (prv != PR_SUCCESS)
+ return NULL;
+
+ if (file_info.size == 0) {
+ /* XXX Need a better error; just grabbed this one for expediency. */
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ return NULL;
+ }
+
+ if (file_info.size > 0xffff) { /* I think this is too big. */
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+
+ item = PORT_Alloc(sizeof(SECItem));
+ if (item == NULL)
+ return NULL;
+
+ item->type = si_type;
+ item->len = (unsigned int)file_info.size;
+ item->data = PORT_Alloc((size_t)item->len);
+ if (item->data == NULL)
+ goto loser;
+
+ bytes_read = PR_Read(in_file, item->data, (PRInt32)item->len);
+ if (bytes_read < 0) {
+ /* Something went wrong; error is already set for us. */
+ goto loser;
+ } else if (bytes_read == 0) {
+ /* Something went wrong; we read nothing. But no system/nspr error. */
+ /* XXX Need to set an error here. */
+ goto loser;
+ } else if (item->len != (unsigned int)bytes_read) {
+ /* Something went wrong; we read less (or more!?) than we expected. */
+ /* XXX Need to set an error here. */
+ goto loser;
+ }
+
+ return item;
+
+loser:
+ SECITEM_FreeItem(item, PR_TRUE);
+ return NULL;
+}
+
+/*
+ * Create a DER-encoded OCSP request (for the certificate whose nickname
+ * is "name") and dump it out.
+ */
+static SECStatus
+create_request(FILE *out_file, CERTCertDBHandle *handle, CERTCertificate *cert,
+ PRBool add_service_locator, PRBool add_acceptable_responses)
+{
+ CERTCertList *certs = NULL;
+ CERTCertificate *myCert = NULL;
+ CERTOCSPRequest *request = NULL;
+ PRTime now = PR_Now();
+ SECItem *encoding = NULL;
+ SECStatus rv = SECFailure;
+
+ if (handle == NULL || cert == NULL)
+ return rv;
+
+ myCert = CERT_DupCertificate(cert);
+ if (myCert == NULL)
+ goto loser;
+
+ /*
+ * We need to create a list of one.
+ */
+ certs = CERT_NewCertList();
+ if (certs == NULL)
+ goto loser;
+
+ if (CERT_AddCertToListTail(certs, myCert) != SECSuccess)
+ goto loser;
+
+ /*
+ * Now that cert is included in the list, we need to be careful
+ * that we do not try to destroy it twice. This will prevent that.
+ */
+ myCert = NULL;
+
+ request = CERT_CreateOCSPRequest(certs, now, add_service_locator, NULL);
+ if (request == NULL)
+ goto loser;
+
+ if (add_acceptable_responses) {
+ rv = CERT_AddOCSPAcceptableResponses(request,
+ SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
+ if (rv != SECSuccess)
+ goto loser;
+ }
+
+ encoding = CERT_EncodeOCSPRequest(NULL, request, NULL);
+ if (encoding == NULL)
+ goto loser;
+
+ MAKE_FILE_BINARY(out_file);
+ if (fwrite(encoding->data, encoding->len, 1, out_file) != 1)
+ goto loser;
+
+ rv = SECSuccess;
+
+loser:
+ if (encoding != NULL)
+ SECITEM_FreeItem(encoding, PR_TRUE);
+ if (request != NULL)
+ CERT_DestroyOCSPRequest(request);
+ if (certs != NULL)
+ CERT_DestroyCertList(certs);
+ if (myCert != NULL)
+ CERT_DestroyCertificate(myCert);
+
+ return rv;
+}
+
+/*
+ * Create a DER-encoded OCSP request (for the certificate whose nickname is
+ * "cert_name"), then get and dump a corresponding response. The responder
+ * location is either specified explicitly (as "responder_url") or found
+ * via the AuthorityInfoAccess URL in the cert.
+ */
+static SECStatus
+dump_response(FILE *out_file, CERTCertDBHandle *handle, CERTCertificate *cert,
+ const char *responder_url)
+{
+ CERTCertList *certs = NULL;
+ CERTCertificate *myCert = NULL;
+ char *loc = NULL;
+ PRTime now = PR_Now();
+ SECItem *response = NULL;
+ SECStatus rv = SECFailure;
+ PRBool includeServiceLocator;
+
+ if (handle == NULL || cert == NULL)
+ return rv;
+
+ myCert = CERT_DupCertificate(cert);
+ if (myCert == NULL)
+ goto loser;
+
+ if (responder_url != NULL) {
+ loc = (char *)responder_url;
+ includeServiceLocator = PR_TRUE;
+ } else {
+ loc = CERT_GetOCSPAuthorityInfoAccessLocation(cert);
+ if (loc == NULL)
+ goto loser;
+ includeServiceLocator = PR_FALSE;
+ }
+
+ /*
+ * We need to create a list of one.
+ */
+ certs = CERT_NewCertList();
+ if (certs == NULL)
+ goto loser;
+
+ if (CERT_AddCertToListTail(certs, myCert) != SECSuccess)
+ goto loser;
+
+ /*
+ * Now that cert is included in the list, we need to be careful
+ * that we do not try to destroy it twice. This will prevent that.
+ */
+ myCert = NULL;
+
+ response = CERT_GetEncodedOCSPResponse(NULL, certs, loc, now,
+ includeServiceLocator,
+ NULL, NULL, NULL);
+ if (response == NULL)
+ goto loser;
+
+ MAKE_FILE_BINARY(out_file);
+ if (fwrite(response->data, response->len, 1, out_file) != 1)
+ goto loser;
+
+ rv = SECSuccess;
+
+loser:
+ if (response != NULL)
+ SECITEM_FreeItem(response, PR_TRUE);
+ if (certs != NULL)
+ CERT_DestroyCertList(certs);
+ if (myCert != NULL)
+ CERT_DestroyCertificate(myCert);
+ if (loc != NULL && loc != responder_url)
+ PORT_Free(loc);
+
+ return rv;
+}
+
+/*
+ * Get the status for the specified certificate (whose nickname is "cert_name").
+ * Directly use the OCSP function rather than doing a full verification.
+ */
+static SECStatus
+get_cert_status(FILE *out_file, CERTCertDBHandle *handle,
+ CERTCertificate *cert, const char *cert_name,
+ PRTime verify_time)
+{
+ SECStatus rv = SECFailure;
+
+ if (handle == NULL || cert == NULL)
+ goto loser;
+
+ rv = CERT_CheckOCSPStatus(handle, cert, verify_time, NULL);
+
+ fprintf(out_file, "Check of certificate \"%s\" ", cert_name);
+ if (rv == SECSuccess) {
+ fprintf(out_file, "succeeded.\n");
+ } else {
+ const char *error_string = SECU_Strerror(PORT_GetError());
+ fprintf(out_file, "failed. Reason:\n");
+ if (error_string != NULL && PORT_Strlen(error_string) > 0)
+ fprintf(out_file, "%s\n", error_string);
+ else
+ fprintf(out_file, "Unknown\n");
+ }
+
+ rv = SECSuccess;
+
+loser:
+
+ return rv;
+}
+
+/*
+ * Verify the specified certificate (whose nickname is "cert_name").
+ * OCSP is already turned on, so we just need to call the standard
+ * certificate verification API and let it do all the work.
+ */
+static SECStatus
+verify_cert(FILE *out_file, CERTCertDBHandle *handle, CERTCertificate *cert,
+ const char *cert_name, SECCertUsage cert_usage, PRTime verify_time)
+{
+ SECStatus rv = SECFailure;
+
+ if (handle == NULL || cert == NULL)
+ return rv;
+
+ rv = CERT_VerifyCert(handle, cert, PR_TRUE, cert_usage, verify_time,
+ NULL, NULL);
+
+ fprintf(out_file, "Verification of certificate \"%s\" ", cert_name);
+ if (rv == SECSuccess) {
+ fprintf(out_file, "succeeded.\n");
+ } else {
+ const char *error_string = SECU_Strerror(PORT_GetError());
+ fprintf(out_file, "failed. Reason:\n");
+ if (error_string != NULL && PORT_Strlen(error_string) > 0)
+ fprintf(out_file, "%s\n", error_string);
+ else
+ fprintf(out_file, "Unknown\n");
+ }
+
+ rv = SECSuccess;
+
+ return rv;
+}
+
+CERTCertificate *
+find_certificate(CERTCertDBHandle *handle, const char *name, PRBool ascii)
+{
+ CERTCertificate *cert = NULL;
+ SECItem der;
+ PRFileDesc *certFile;
+
+ if (handle == NULL || name == NULL)
+ return NULL;
+
+ if (ascii == PR_FALSE) {
+ /* by default need to check if there is cert nick is given */
+ cert = CERT_FindCertByNicknameOrEmailAddr(handle, (char *)name);
+ if (cert != NULL)
+ return cert;
+ }
+
+ certFile = PR_Open(name, PR_RDONLY, 0);
+ if (certFile == NULL) {
+ return NULL;
+ }
+
+ if (SECU_ReadDERFromFile(&der, certFile, ascii, PR_FALSE) == SECSuccess) {
+ cert = CERT_DecodeCertFromPackage((char *)der.data, der.len);
+ SECITEM_FreeItem(&der, PR_FALSE);
+ }
+ PR_Close(certFile);
+
+ return cert;
+}
+
+#ifdef NO_PP
+
+static SECStatus
+print_request(FILE *out_file, SECItem *data)
+{
+ fprintf(out_file, "Cannot pretty-print request compiled with NO_PP.\n");
+ return SECSuccess;
+}
+
+static SECStatus
+print_response(FILE *out_file, SECItem *data, CERTCertDBHandle *handle)
+{
+ fprintf(out_file, "Cannot pretty-print response compiled with NO_PP.\n");
+ return SECSuccess;
+}
+
+#else /* NO_PP */
+
+static void
+print_ocsp_version(FILE *out_file, SECItem *version, int level)
+{
+ if (version->len > 0) {
+ SECU_PrintInteger(out_file, version, "Version", level);
+ } else {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Version: DEFAULT\n");
+ }
+}
+
+static void
+print_ocsp_cert_id(FILE *out_file, CERTOCSPCertID *cert_id, int level)
+{
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Cert ID:\n");
+ level++;
+
+ SECU_PrintAlgorithmID(out_file, &(cert_id->hashAlgorithm),
+ "Hash Algorithm", level);
+ SECU_PrintAsHex(out_file, &(cert_id->issuerNameHash),
+ "Issuer Name Hash", level);
+ SECU_PrintAsHex(out_file, &(cert_id->issuerKeyHash),
+ "Issuer Key Hash", level);
+ SECU_PrintInteger(out_file, &(cert_id->serialNumber),
+ "Serial Number", level);
+ /* XXX lookup the cert; if found, print something nice (nickname?) */
+}
+
+static void
+print_raw_certificates(FILE *out_file, SECItem **raw_certs, int level)
+{
+ SECItem *raw_cert;
+ int i = 0;
+ char cert_label[50];
+
+ SECU_Indent(out_file, level);
+
+ if (raw_certs == NULL) {
+ fprintf(out_file, "No Certificates.\n");
+ return;
+ }
+
+ fprintf(out_file, "Certificate List:\n");
+ while ((raw_cert = raw_certs[i++]) != NULL) {
+ sprintf(cert_label, "Certificate (%d)", i);
+ (void)SECU_PrintSignedData(out_file, raw_cert, cert_label, level + 1,
+ (SECU_PPFunc)SECU_PrintCertificate);
+ }
+}
+
+static void
+print_ocsp_extensions(FILE *out_file, CERTCertExtension **extensions,
+ char *msg, int level)
+{
+ if (extensions) {
+ SECU_PrintExtensions(out_file, extensions, msg, level);
+ } else {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "No %s\n", msg);
+ }
+}
+
+static void
+print_single_request(FILE *out_file, ocspSingleRequest *single, int level)
+{
+ print_ocsp_cert_id(out_file, single->reqCert, level);
+ print_ocsp_extensions(out_file, single->singleRequestExtensions,
+ "Single Request Extensions", level);
+}
+
+/*
+ * Decode the DER/BER-encoded item "data" as an OCSP request
+ * and pretty-print the subfields.
+ */
+static SECStatus
+print_request(FILE *out_file, SECItem *data)
+{
+ CERTOCSPRequest *request;
+ ocspTBSRequest *tbsRequest;
+ int level = 0;
+
+ PORT_Assert(out_file != NULL);
+ PORT_Assert(data != NULL);
+ if (out_file == NULL || data == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ request = CERT_DecodeOCSPRequest(data);
+ if (request == NULL || request->tbsRequest == NULL)
+ return SECFailure;
+
+ tbsRequest = request->tbsRequest;
+
+ fprintf(out_file, "TBS Request:\n");
+ level++;
+
+ print_ocsp_version(out_file, &(tbsRequest->version), level);
+
+ /*
+ * XXX Probably should be an interface to get the signer name
+ * without looking inside the tbsRequest at all.
+ */
+ if (tbsRequest->requestorName != NULL) {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "XXX print the requestorName\n");
+ } else {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "No Requestor Name.\n");
+ }
+
+ if (tbsRequest->requestList != NULL) {
+ int i;
+
+ for (i = 0; tbsRequest->requestList[i] != NULL; i++) {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Request %d:\n", i);
+ print_single_request(out_file, tbsRequest->requestList[i],
+ level + 1);
+ }
+ } else {
+ fprintf(out_file, "Request list is empty.\n");
+ }
+
+ print_ocsp_extensions(out_file, tbsRequest->requestExtensions,
+ "Request Extensions", level);
+
+ if (request->optionalSignature != NULL) {
+ ocspSignature *whole_sig;
+ SECItem rawsig;
+
+ fprintf(out_file, "Signature:\n");
+
+ whole_sig = request->optionalSignature;
+ SECU_PrintAlgorithmID(out_file, &(whole_sig->signatureAlgorithm),
+ "Signature Algorithm", level);
+
+ rawsig = whole_sig->signature;
+ DER_ConvertBitString(&rawsig);
+ SECU_PrintAsHex(out_file, &rawsig, "Signature", level);
+
+ print_raw_certificates(out_file, whole_sig->derCerts, level);
+
+ fprintf(out_file, "XXX verify the sig and print result\n");
+ } else {
+ fprintf(out_file, "No Signature\n");
+ }
+
+ CERT_DestroyOCSPRequest(request);
+ return SECSuccess;
+}
+
+static void
+print_revoked_info(FILE *out_file, ocspRevokedInfo *revoked_info, int level)
+{
+ SECU_PrintGeneralizedTime(out_file, &(revoked_info->revocationTime),
+ "Revocation Time", level);
+
+ if (revoked_info->revocationReason != NULL) {
+ SECU_PrintAsHex(out_file, revoked_info->revocationReason,
+ "Revocation Reason", level);
+ } else {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "No Revocation Reason.\n");
+ }
+}
+
+static void
+print_cert_status(FILE *out_file, ocspCertStatus *status, int level)
+{
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Status: ");
+
+ switch (status->certStatusType) {
+ case ocspCertStatus_good:
+ fprintf(out_file, "Cert is good.\n");
+ break;
+ case ocspCertStatus_revoked:
+ fprintf(out_file, "Cert has been revoked.\n");
+ print_revoked_info(out_file, status->certStatusInfo.revokedInfo,
+ level + 1);
+ break;
+ case ocspCertStatus_unknown:
+ fprintf(out_file, "Cert is unknown to responder.\n");
+ break;
+ default:
+ fprintf(out_file, "Unrecognized status.\n");
+ break;
+ }
+}
+
+static void
+print_single_response(FILE *out_file, CERTOCSPSingleResponse *single,
+ int level)
+{
+ print_ocsp_cert_id(out_file, single->certID, level);
+
+ print_cert_status(out_file, single->certStatus, level);
+
+ SECU_PrintGeneralizedTime(out_file, &(single->thisUpdate),
+ "This Update", level);
+
+ if (single->nextUpdate != NULL) {
+ SECU_PrintGeneralizedTime(out_file, single->nextUpdate,
+ "Next Update", level);
+ } else {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "No Next Update\n");
+ }
+
+ print_ocsp_extensions(out_file, single->singleExtensions,
+ "Single Response Extensions", level);
+}
+
+static void
+print_responder_id(FILE *out_file, ocspResponderID *responderID, int level)
+{
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Responder ID ");
+
+ switch (responderID->responderIDType) {
+ case ocspResponderID_byName:
+ fprintf(out_file, "(byName):\n");
+ SECU_PrintName(out_file, &(responderID->responderIDValue.name),
+ "Name", level + 1);
+ break;
+ case ocspResponderID_byKey:
+ fprintf(out_file, "(byKey):\n");
+ SECU_PrintAsHex(out_file, &(responderID->responderIDValue.keyHash),
+ "Key Hash", level + 1);
+ break;
+ default:
+ fprintf(out_file, "Unrecognized Responder ID Type\n");
+ break;
+ }
+}
+
+static void
+print_response_data(FILE *out_file, ocspResponseData *responseData, int level)
+{
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Response Data:\n");
+ level++;
+
+ print_ocsp_version(out_file, &(responseData->version), level);
+
+ print_responder_id(out_file, responseData->responderID, level);
+
+ SECU_PrintGeneralizedTime(out_file, &(responseData->producedAt),
+ "Produced At", level);
+
+ if (responseData->responses != NULL) {
+ int i;
+
+ for (i = 0; responseData->responses[i] != NULL; i++) {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Response %d:\n", i);
+ print_single_response(out_file, responseData->responses[i],
+ level + 1);
+ }
+ } else {
+ fprintf(out_file, "Response list is empty.\n");
+ }
+
+ print_ocsp_extensions(out_file, responseData->responseExtensions,
+ "Response Extensions", level);
+}
+
+static void
+print_basic_response(FILE *out_file, ocspBasicOCSPResponse *basic, int level)
+{
+ SECItem rawsig;
+
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Basic OCSP Response:\n");
+ level++;
+
+ print_response_data(out_file, basic->tbsResponseData, level);
+
+ SECU_PrintAlgorithmID(out_file,
+ &(basic->responseSignature.signatureAlgorithm),
+ "Signature Algorithm", level);
+
+ rawsig = basic->responseSignature.signature;
+ DER_ConvertBitString(&rawsig);
+ SECU_PrintAsHex(out_file, &rawsig, "Signature", level);
+
+ print_raw_certificates(out_file, basic->responseSignature.derCerts, level);
+}
+
+/*
+ * Note this must match (exactly) the enumeration ocspResponseStatus.
+ */
+static char *responseStatusNames[] = {
+ "successful (Response has valid confirmations)",
+ "malformedRequest (Illegal confirmation request)",
+ "internalError (Internal error in issuer)",
+ "tryLater (Try again later)",
+ "unused ((4) is not used)",
+ "sigRequired (Must sign the request)",
+ "unauthorized (Request unauthorized)"
+};
+
+/*
+ * Decode the DER/BER-encoded item "data" as an OCSP response
+ * and pretty-print the subfields.
+ */
+static SECStatus
+print_response(FILE *out_file, SECItem *data, CERTCertDBHandle *handle)
+{
+ CERTOCSPResponse *response;
+ int level = 0;
+
+ PORT_Assert(out_file != NULL);
+ PORT_Assert(data != NULL);
+ if (out_file == NULL || data == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ response = CERT_DecodeOCSPResponse(data);
+ if (response == NULL)
+ return SECFailure;
+
+ if (response->statusValue >= ocspResponse_min &&
+ response->statusValue <= ocspResponse_max) {
+ fprintf(out_file, "Response Status: %s\n",
+ responseStatusNames[response->statusValue]);
+ } else {
+ fprintf(out_file,
+ "Response Status: other (Status value %d out of defined range)\n",
+ (int)response->statusValue);
+ }
+
+ if (response->statusValue == ocspResponse_successful) {
+ ocspResponseBytes *responseBytes = response->responseBytes;
+ SECStatus sigStatus;
+ CERTCertificate *signerCert = NULL;
+
+ PORT_Assert(responseBytes != NULL);
+
+ level++;
+ fprintf(out_file, "Response Bytes:\n");
+ SECU_PrintObjectID(out_file, &(responseBytes->responseType),
+ "Response Type", level);
+ switch (response->responseBytes->responseTypeTag) {
+ case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
+ print_basic_response(out_file,
+ responseBytes->decodedResponse.basic,
+ level);
+ break;
+ default:
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Unknown response syntax\n");
+ break;
+ }
+
+ sigStatus = CERT_VerifyOCSPResponseSignature(response, handle,
+ NULL, &signerCert, NULL);
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Signature verification ");
+ if (sigStatus != SECSuccess) {
+ fprintf(out_file, "failed: %s\n", SECU_Strerror(PORT_GetError()));
+ } else {
+ fprintf(out_file, "succeeded.\n");
+ if (signerCert != NULL) {
+ SECU_PrintName(out_file, &signerCert->subject, "Signer",
+ level);
+ CERT_DestroyCertificate(signerCert);
+ } else {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "No signer cert returned?\n");
+ }
+ }
+ } else {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Unsuccessful response, no more information.\n");
+ }
+
+ CERT_DestroyOCSPResponse(response);
+ return SECSuccess;
+}
+
+#endif /* NO_PP */
+
+static SECStatus
+cert_usage_from_char(const char *cert_usage_str, SECCertUsage *cert_usage)
+{
+ PORT_Assert(cert_usage_str != NULL);
+ PORT_Assert(cert_usage != NULL);
+
+ if (PORT_Strlen(cert_usage_str) != 1)
+ return SECFailure;
+
+ switch (*cert_usage_str) {
+ case 'c':
+ *cert_usage = certUsageSSLClient;
+ break;
+ case 's':
+ *cert_usage = certUsageSSLServer;
+ break;
+ case 'e':
+ *cert_usage = certUsageEmailRecipient;
+ break;
+ case 'E':
+ *cert_usage = certUsageEmailSigner;
+ break;
+ case 'S':
+ *cert_usage = certUsageObjectSigner;
+ break;
+ case 'C':
+ *cert_usage = certUsageVerifyCA;
+ break;
+ default:
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+int
+main(int argc, char **argv)
+{
+ int retval;
+ PRFileDesc *in_file;
+ FILE *out_file; /* not PRFileDesc until SECU accepts it */
+ int crequest, dresponse;
+ int prequest, presponse;
+ int ccert, vcert;
+ const char *db_dir, *date_str, *cert_usage_str, *name;
+ const char *responder_name, *responder_url, *signer_name;
+ PRBool add_acceptable_responses, add_service_locator;
+ SECItem *data = NULL;
+ PLOptState *optstate;
+ SECStatus rv;
+ CERTCertDBHandle *handle = NULL;
+ SECCertUsage cert_usage = certUsageSSLClient;
+ PRTime verify_time;
+ CERTCertificate *cert = NULL;
+ PRBool ascii = PR_FALSE;
+
+ retval = -1; /* what we return/exit with on error */
+
+ program_name = PL_strrchr(argv[0], '/');
+ program_name = program_name ? (program_name + 1) : argv[0];
+
+ in_file = PR_STDIN;
+ out_file = stdout;
+
+ crequest = 0;
+ dresponse = 0;
+ prequest = 0;
+ presponse = 0;
+ ccert = 0;
+ vcert = 0;
+
+ db_dir = NULL;
+ date_str = NULL;
+ cert_usage_str = NULL;
+ name = NULL;
+ responder_name = NULL;
+ responder_url = NULL;
+ signer_name = NULL;
+
+ add_acceptable_responses = PR_FALSE;
+ add_service_locator = PR_FALSE;
+
+ optstate = PL_CreateOptState(argc, argv, "AHLPR:S:V:d:l:pr:s:t:u:w:");
+ if (optstate == NULL) {
+ SECU_PrintError(program_name, "PL_CreateOptState failed");
+ return retval;
+ }
+
+ while (PL_GetNextOpt(optstate) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ short_usage(program_name);
+ return retval;
+
+ case 'A':
+ add_acceptable_responses = PR_TRUE;
+ break;
+
+ case 'H':
+ long_usage(program_name);
+ return retval;
+
+ case 'L':
+ add_service_locator = PR_TRUE;
+ break;
+
+ case 'P':
+ presponse = 1;
+ break;
+
+ case 'R':
+ dresponse = 1;
+ name = optstate->value;
+ break;
+
+ case 'S':
+ ccert = 1;
+ name = optstate->value;
+ break;
+
+ case 'V':
+ vcert = 1;
+ name = optstate->value;
+ break;
+
+ case 'a':
+ ascii = PR_TRUE;
+ break;
+
+ case 'd':
+ db_dir = optstate->value;
+ break;
+
+ case 'l':
+ responder_url = optstate->value;
+ break;
+
+ case 'p':
+ prequest = 1;
+ break;
+
+ case 'r':
+ crequest = 1;
+ name = optstate->value;
+ break;
+
+ case 's':
+ signer_name = optstate->value;
+ break;
+
+ case 't':
+ responder_name = optstate->value;
+ break;
+
+ case 'u':
+ cert_usage_str = optstate->value;
+ break;
+
+ case 'w':
+ date_str = optstate->value;
+ break;
+ }
+ }
+
+ PL_DestroyOptState(optstate);
+
+ if ((crequest + dresponse + prequest + presponse + ccert + vcert) != 1) {
+ PR_fprintf(PR_STDERR, "%s: must specify exactly one command\n\n",
+ program_name);
+ short_usage(program_name);
+ return retval;
+ }
+
+ if (vcert) {
+ if (cert_usage_str == NULL) {
+ PR_fprintf(PR_STDERR, "%s: verification requires cert usage\n\n",
+ program_name);
+ short_usage(program_name);
+ return retval;
+ }
+
+ rv = cert_usage_from_char(cert_usage_str, &cert_usage);
+ if (rv != SECSuccess) {
+ PR_fprintf(PR_STDERR, "%s: invalid cert usage (\"%s\")\n\n",
+ program_name, cert_usage_str);
+ long_usage(program_name);
+ return retval;
+ }
+ }
+
+ if (ccert + vcert) {
+ if (responder_url != NULL || responder_name != NULL) {
+ /*
+ * To do a full status check, both the URL and the cert name
+ * of the responder must be specified if either one is.
+ */
+ if (responder_url == NULL || responder_name == NULL) {
+ if (responder_url == NULL)
+ PR_fprintf(PR_STDERR,
+ "%s: must also specify responder location\n\n",
+ program_name);
+ else
+ PR_fprintf(PR_STDERR,
+ "%s: must also specify responder name\n\n",
+ program_name);
+ short_usage(program_name);
+ return retval;
+ }
+ }
+
+ if (date_str != NULL) {
+ rv = DER_AsciiToTime(&verify_time, (char *)date_str);
+ if (rv != SECSuccess) {
+ SECU_PrintError(program_name, "error converting time string");
+ PR_fprintf(PR_STDERR, "\n");
+ long_usage(program_name);
+ return retval;
+ }
+ } else {
+ verify_time = PR_Now();
+ }
+ }
+
+ retval = -2; /* errors change from usage to runtime */
+
+ /*
+ * Initialize the NSPR and Security libraries.
+ */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ db_dir = SECU_ConfigDirectory(db_dir);
+ rv = NSS_Init(db_dir);
+ if (rv != SECSuccess) {
+ SECU_PrintError(program_name, "NSS_Init failed");
+ goto prdone;
+ }
+ SECU_RegisterDynamicOids();
+
+ if (prequest + presponse) {
+ MAKE_FILE_BINARY(stdin);
+ data = read_file_into_item(in_file, siBuffer);
+ if (data == NULL) {
+ SECU_PrintError(program_name, "problem reading input");
+ goto nssdone;
+ }
+ }
+
+ if (crequest + dresponse + presponse + ccert + vcert) {
+ handle = CERT_GetDefaultCertDB();
+ if (handle == NULL) {
+ SECU_PrintError(program_name, "problem getting certdb handle");
+ goto nssdone;
+ }
+
+ /*
+ * It would be fine to do the enable for all of these commands,
+ * but this way we check that everything but an overall verify
+ * can be done without it. That is, that the individual pieces
+ * work on their own.
+ */
+ if (vcert) {
+ rv = CERT_EnableOCSPChecking(handle);
+ if (rv != SECSuccess) {
+ SECU_PrintError(program_name, "error enabling OCSP checking");
+ goto nssdone;
+ }
+ }
+
+ if ((ccert + vcert) && (responder_name != NULL)) {
+ rv = CERT_SetOCSPDefaultResponder(handle, responder_url,
+ responder_name);
+ if (rv != SECSuccess) {
+ SECU_PrintError(program_name,
+ "error setting default responder");
+ goto nssdone;
+ }
+
+ rv = CERT_EnableOCSPDefaultResponder(handle);
+ if (rv != SECSuccess) {
+ SECU_PrintError(program_name,
+ "error enabling default responder");
+ goto nssdone;
+ }
+ }
+ }
+
+#define NOTYET(opt) \
+ { \
+ PR_fprintf(PR_STDERR, "%s not yet working\n", opt); \
+ exit(-1); \
+ }
+
+ if (name) {
+ cert = find_certificate(handle, name, ascii);
+ }
+
+ if (crequest) {
+ if (signer_name != NULL) {
+ NOTYET("-s");
+ }
+ rv = create_request(out_file, handle, cert, add_service_locator,
+ add_acceptable_responses);
+ } else if (dresponse) {
+ if (signer_name != NULL) {
+ NOTYET("-s");
+ }
+ rv = dump_response(out_file, handle, cert, responder_url);
+ } else if (prequest) {
+ rv = print_request(out_file, data);
+ } else if (presponse) {
+ rv = print_response(out_file, data, handle);
+ } else if (ccert) {
+ if (signer_name != NULL) {
+ NOTYET("-s");
+ }
+ rv = get_cert_status(out_file, handle, cert, name, verify_time);
+ } else if (vcert) {
+ if (signer_name != NULL) {
+ NOTYET("-s");
+ }
+ rv = verify_cert(out_file, handle, cert, name, cert_usage, verify_time);
+ }
+
+ if (rv != SECSuccess)
+ SECU_PrintError(program_name, "error performing requested operation");
+ else
+ retval = 0;
+
+nssdone:
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+
+ if (data != NULL) {
+ SECITEM_FreeItem(data, PR_TRUE);
+ }
+
+ if (handle != NULL) {
+ CERT_DisableOCSPDefaultResponder(handle);
+ CERT_DisableOCSPChecking(handle);
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ retval = 1;
+ }
+
+prdone:
+ PR_Cleanup();
+ return retval;
+}
diff --git a/security/nss/cmd/ocspclnt/ocspclnt.gyp b/security/nss/cmd/ocspclnt/ocspclnt.gyp
new file mode 100644
index 000000000..4ab7c5e36
--- /dev/null
+++ b/security/nss/cmd/ocspclnt/ocspclnt.gyp
@@ -0,0 +1,25 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'ocspclnt',
+ 'type': 'executable',
+ 'sources': [
+ 'ocspclnt.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/ocspresp/Makefile b/security/nss/cmd/ocspresp/Makefile
new file mode 100644
index 000000000..6e1d4ecdf
--- /dev/null
+++ b/security/nss/cmd/ocspresp/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/ocspresp/manifest.mn b/security/nss/cmd/ocspresp/manifest.mn
new file mode 100644
index 000000000..3608623b8
--- /dev/null
+++ b/security/nss/cmd/ocspresp/manifest.mn
@@ -0,0 +1,15 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+CSRCS = ocspresp.c
+
+REQUIRES = seccmd
+
+PROGRAM = ocspresp
+
diff --git a/security/nss/cmd/ocspresp/ocspresp.c b/security/nss/cmd/ocspresp/ocspresp.c
new file mode 100644
index 000000000..632623c97
--- /dev/null
+++ b/security/nss/cmd/ocspresp/ocspresp.c
@@ -0,0 +1,251 @@
+/* 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/. */
+
+/*
+ * ocspresp - self test for OCSP response creation
+ */
+
+#include "nspr.h"
+#include "secutil.h"
+#include "secpkcs7.h"
+#include "cert.h"
+#include "certdb.h"
+#include "nss.h"
+#include "pk11func.h"
+#include "cryptohi.h"
+#include "ocsp.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+secuPWData pwdata = { PW_NONE, 0 };
+
+static PRBool
+getCaAndSubjectCert(CERTCertDBHandle *certHandle,
+ const char *caNick, const char *eeNick,
+ CERTCertificate **outCA, CERTCertificate **outCert)
+{
+ *outCA = CERT_FindCertByNickname(certHandle, caNick);
+ *outCert = CERT_FindCertByNickname(certHandle, eeNick);
+ return *outCA && *outCert;
+}
+
+static SECItem *
+encode(PLArenaPool *arena, CERTOCSPCertID *cid, CERTCertificate *ca)
+{
+ SECItem *response;
+ PRTime now = PR_Now();
+ PRTime nextUpdate;
+ CERTOCSPSingleResponse **responses;
+ CERTOCSPSingleResponse *sr;
+
+ if (!arena)
+ return NULL;
+
+ nextUpdate = now + 10 * PR_USEC_PER_SEC; /* in the future */
+
+ sr = CERT_CreateOCSPSingleResponseGood(arena, cid, now, &nextUpdate);
+
+ /* meaning of value 2: one entry + one end marker */
+ responses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse *, 2);
+ if (responses == NULL)
+ return NULL;
+
+ responses[0] = sr;
+ responses[1] = NULL;
+
+ response = CERT_CreateEncodedOCSPSuccessResponse(
+ arena, ca, ocspResponderID_byName, now, responses, &pwdata);
+
+ return response;
+}
+
+static SECItem *
+encodeRevoked(PLArenaPool *arena, CERTOCSPCertID *cid, CERTCertificate *ca)
+{
+ SECItem *response;
+ PRTime now = PR_Now();
+ PRTime revocationTime;
+ CERTOCSPSingleResponse **responses;
+ CERTOCSPSingleResponse *sr;
+
+ if (!arena)
+ return NULL;
+
+ revocationTime = now - 10 * PR_USEC_PER_SEC; /* in the past */
+
+ sr = CERT_CreateOCSPSingleResponseRevoked(arena, cid, now, NULL,
+ revocationTime, NULL);
+
+ /* meaning of value 2: one entry + one end marker */
+ responses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse *, 2);
+ if (responses == NULL)
+ return NULL;
+
+ responses[0] = sr;
+ responses[1] = NULL;
+
+ response = CERT_CreateEncodedOCSPSuccessResponse(
+ arena, ca, ocspResponderID_byName, now, responses, &pwdata);
+
+ return response;
+}
+
+int
+Usage(void)
+{
+ PRFileDesc *pr_stderr = PR_STDERR;
+ PR_fprintf(pr_stderr, "ocspresp runs an internal selftest for OCSP response creation");
+ PR_fprintf(pr_stderr, "Usage:");
+ PR_fprintf(pr_stderr,
+ "\tocspresp <dbdir> <CA-nick> <EE-nick> [-p <pass>] [-f <file>]\n");
+ PR_fprintf(pr_stderr,
+ "\tdbdir: Find security databases in \"dbdir\"\n");
+ PR_fprintf(pr_stderr,
+ "\tCA-nick: nickname of a trusted CA certificate with private key\n");
+ PR_fprintf(pr_stderr,
+ "\tEE-nick: nickname of a entity cert issued by CA\n");
+ PR_fprintf(pr_stderr,
+ "\t-p: a password for db\n");
+ PR_fprintf(pr_stderr,
+ "\t-f: a filename containing the password for db\n");
+ return -1;
+}
+
+int
+main(int argc, char **argv)
+{
+ SECStatus rv;
+ int retval = -1;
+ CERTCertDBHandle *certHandle = NULL;
+ CERTCertificate *caCert = NULL, *cert = NULL;
+ CERTOCSPCertID *cid = NULL;
+ PLArenaPool *arena = NULL;
+ PRTime now = PR_Now();
+
+ SECItem *encoded = NULL;
+ CERTOCSPResponse *decoded = NULL;
+
+ SECItem *encodedRev = NULL;
+ CERTOCSPResponse *decodedRev = NULL;
+
+ SECItem *encodedFail = NULL;
+ CERTOCSPResponse *decodedFail = NULL;
+
+ CERTCertificate *obtainedSignerCert = NULL;
+
+ if (argc != 4 && argc != 6) {
+ return Usage();
+ }
+
+ if (argc == 6) {
+ if (!strcmp(argv[4], "-p")) {
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = PORT_Strdup(argv[5]);
+ } else if (!strcmp(argv[4], "-f")) {
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = PORT_Strdup(argv[5]);
+ } else
+ return Usage();
+ }
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ /*rv = NSS_Init(SECU_ConfigDirectory(NULL));*/
+ rv = NSS_Init(argv[1]);
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(argv[0]);
+ goto loser;
+ }
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ certHandle = CERT_GetDefaultCertDB();
+ if (!certHandle)
+ goto loser;
+
+ if (!getCaAndSubjectCert(certHandle, argv[2], argv[3], &caCert, &cert))
+ goto loser;
+
+ cid = CERT_CreateOCSPCertID(cert, now);
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ encoded = encode(arena, cid, caCert);
+ PORT_Assert(encoded);
+ decoded = CERT_DecodeOCSPResponse(encoded);
+ PORT_CheckSuccess(CERT_GetOCSPResponseStatus(decoded));
+
+ PORT_CheckSuccess(CERT_VerifyOCSPResponseSignature(decoded, certHandle, &pwdata,
+ &obtainedSignerCert, caCert));
+ PORT_CheckSuccess(CERT_GetOCSPStatusForCertID(certHandle, decoded, cid,
+ obtainedSignerCert, now));
+ CERT_DestroyCertificate(obtainedSignerCert);
+
+ encodedRev = encodeRevoked(arena, cid, caCert);
+ PORT_Assert(encodedRev);
+ decodedRev = CERT_DecodeOCSPResponse(encodedRev);
+ PORT_CheckSuccess(CERT_GetOCSPResponseStatus(decodedRev));
+
+ PORT_CheckSuccess(CERT_VerifyOCSPResponseSignature(decodedRev, certHandle, &pwdata,
+ &obtainedSignerCert, caCert));
+#ifdef DEBUG
+ {
+ SECStatus rv = CERT_GetOCSPStatusForCertID(certHandle, decodedRev, cid,
+ obtainedSignerCert, now);
+ PORT_Assert(rv == SECFailure);
+ PORT_Assert(PORT_GetError() == SEC_ERROR_REVOKED_CERTIFICATE);
+ }
+#else
+ (void)CERT_GetOCSPStatusForCertID(certHandle, decodedRev, cid,
+ obtainedSignerCert, now);
+#endif
+ CERT_DestroyCertificate(obtainedSignerCert);
+
+ encodedFail = CERT_CreateEncodedOCSPErrorResponse(
+ arena, SEC_ERROR_OCSP_TRY_SERVER_LATER);
+ PORT_Assert(encodedFail);
+ decodedFail = CERT_DecodeOCSPResponse(encodedFail);
+#ifdef DEBUG
+ {
+ SECStatus rv = CERT_GetOCSPResponseStatus(decodedFail);
+ PORT_Assert(rv == SECFailure);
+ PORT_Assert(PORT_GetError() == SEC_ERROR_OCSP_TRY_SERVER_LATER);
+ }
+#else
+ (void)CERT_GetOCSPResponseStatus(decodedFail);
+#endif
+ retval = 0;
+loser:
+ if (retval != 0)
+ SECU_PrintError(argv[0], "tests failed");
+
+ if (cid)
+ CERT_DestroyOCSPCertID(cid);
+ if (cert)
+ CERT_DestroyCertificate(cert);
+ if (caCert)
+ CERT_DestroyCertificate(caCert);
+ if (arena)
+ PORT_FreeArena(arena, PR_FALSE);
+ if (decoded)
+ CERT_DestroyOCSPResponse(decoded);
+ if (decodedRev)
+ CERT_DestroyOCSPResponse(decodedRev);
+ if (decodedFail)
+ CERT_DestroyOCSPResponse(decodedFail);
+ if (pwdata.data) {
+ PORT_Free(pwdata.data);
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ SECU_PrintError(argv[0], "NSS shutdown:");
+ if (retval == 0)
+ retval = -2;
+ }
+
+ return retval;
+}
diff --git a/security/nss/cmd/ocspresp/ocspresp.gyp b/security/nss/cmd/ocspresp/ocspresp.gyp
new file mode 100644
index 000000000..81f02dfe8
--- /dev/null
+++ b/security/nss/cmd/ocspresp/ocspresp.gyp
@@ -0,0 +1,24 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'ocspresp',
+ 'type': 'executable',
+ 'sources': [
+ 'ocspresp.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/oidcalc/Makefile b/security/nss/cmd/oidcalc/Makefile
new file mode 100644
index 000000000..d7c879aec
--- /dev/null
+++ b/security/nss/cmd/oidcalc/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/oidcalc/manifest.mn b/security/nss/cmd/oidcalc/manifest.mn
new file mode 100644
index 000000000..e7976c661
--- /dev/null
+++ b/security/nss/cmd/oidcalc/manifest.mn
@@ -0,0 +1,19 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = oidcalc.c
+
+PROGRAM = oidcalc
diff --git a/security/nss/cmd/oidcalc/oidcalc.c b/security/nss/cmd/oidcalc/oidcalc.c
new file mode 100644
index 000000000..46ef56c41
--- /dev/null
+++ b/security/nss/cmd/oidcalc/oidcalc.c
@@ -0,0 +1,86 @@
+/* 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/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+main(int argc, char **argv)
+{
+ char *curstr;
+ char *nextstr;
+ unsigned int firstval;
+ unsigned int secondval;
+ unsigned int val;
+ unsigned char buf[5];
+ int count;
+
+ if (argc != 2) {
+ fprintf(stderr, "wrong number of args\n");
+ exit(-1);
+ }
+
+ curstr = argv[1];
+
+ nextstr = strchr(curstr, '.');
+
+ if (nextstr == NULL) {
+ fprintf(stderr, "only one component\n");
+ exit(-1);
+ }
+
+ *nextstr = '\0';
+ firstval = atoi(curstr);
+
+ curstr = nextstr + 1;
+
+ nextstr = strchr(curstr, '.');
+
+ if (nextstr) {
+ *nextstr = '\0';
+ }
+
+ secondval = atoi(curstr);
+
+ if (firstval > 2) {
+ fprintf(stderr, "first component out of range\n");
+ exit(-1);
+ }
+
+ if (secondval > 39) {
+ fprintf(stderr, "second component out of range\n");
+ exit(-1);
+ }
+
+ printf("0x%x, ", (firstval * 40) + secondval);
+ while (nextstr) {
+ curstr = nextstr + 1;
+
+ nextstr = strchr(curstr, '.');
+
+ if (nextstr) {
+ *nextstr = '\0';
+ }
+
+ memset(buf, 0, sizeof(buf));
+ val = atoi(curstr);
+ count = 0;
+ while (val) {
+ buf[count] = (val & 0x7f);
+ val = val >> 7;
+ count++;
+ }
+
+ while (count--) {
+ if (count) {
+ printf("0x%x, ", buf[count] | 0x80);
+ } else {
+ printf("0x%x, ", buf[count]);
+ }
+ }
+ }
+ printf("\n");
+ return 0;
+}
diff --git a/security/nss/cmd/oidcalc/oidcalc.gyp b/security/nss/cmd/oidcalc/oidcalc.gyp
new file mode 100644
index 000000000..b02ab8721
--- /dev/null
+++ b/security/nss/cmd/oidcalc/oidcalc.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'oidcalc',
+ 'type': 'executable',
+ 'sources': [
+ 'oidcalc.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/p7content/Makefile b/security/nss/cmd/p7content/Makefile
new file mode 100644
index 000000000..6e1d4ecdf
--- /dev/null
+++ b/security/nss/cmd/p7content/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/p7content/manifest.mn b/security/nss/cmd/p7content/manifest.mn
new file mode 100644
index 000000000..6fa632f55
--- /dev/null
+++ b/security/nss/cmd/p7content/manifest.mn
@@ -0,0 +1,15 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+CSRCS = p7content.c
+
+REQUIRES = seccmd
+
+PROGRAM = p7content
+
diff --git a/security/nss/cmd/p7content/p7content.c b/security/nss/cmd/p7content/p7content.c
new file mode 100644
index 000000000..d8c4d6524
--- /dev/null
+++ b/security/nss/cmd/p7content/p7content.c
@@ -0,0 +1,269 @@
+/* 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/. */
+
+/*
+ * p7content -- A command to display pkcs7 content.
+ */
+
+#include "nspr.h"
+#include "secutil.h"
+#include "plgetopt.h"
+#include "secpkcs7.h"
+#include "cert.h"
+#include "certdb.h"
+#include "nss.h"
+#include "pk11pub.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
+extern int fwrite(char *, size_t, size_t, FILE *);
+extern int fprintf(FILE *, char *, ...);
+#endif
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-d dbdir] [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr,
+ "%-20s Key/Cert database directory (default is ~/.netscape)\n",
+ "-d dbdir");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+static PRBool saw_content;
+static secuPWData pwdata = { PW_NONE, 0 };
+
+static void
+PrintBytes(void *arg, const char *buf, unsigned long len)
+{
+ FILE *out;
+
+ out = arg;
+ fwrite(buf, len, 1, out);
+
+ saw_content = PR_TRUE;
+}
+
+/*
+ * XXX Someday we may want to do real policy stuff here. This allows
+ * anything to be decrypted, which is okay for a test program but does
+ * not set an example of how a real client with a real policy would
+ * need to do it.
+ */
+static PRBool
+decryption_allowed(SECAlgorithmID *algid, PK11SymKey *key)
+{
+ return PR_TRUE;
+}
+
+int
+DecodeAndPrintFile(FILE *out, PRFileDesc *in, char *progName)
+{
+ SECItem derdata;
+ SEC_PKCS7ContentInfo *cinfo = NULL;
+ SEC_PKCS7DecoderContext *dcx;
+
+ if (SECU_ReadDERFromFile(&derdata, in, PR_FALSE, PR_FALSE)) {
+ SECU_PrintError(progName, "error converting der");
+ return -1;
+ }
+
+ fprintf(out,
+ "Content printed between bars (newline added before second bar):");
+ fprintf(out, "\n---------------------------------------------\n");
+
+ saw_content = PR_FALSE;
+ dcx = SEC_PKCS7DecoderStart(PrintBytes, out, NULL, &pwdata,
+ NULL, NULL, decryption_allowed);
+ if (dcx != NULL) {
+#if 0 /* Test that decoder works when data is really streaming in. */
+ {
+ unsigned long i;
+ for (i = 0; i < derdata.len; i++)
+ SEC_PKCS7DecoderUpdate(dcx, derdata.data + i, 1);
+ }
+#else
+ SEC_PKCS7DecoderUpdate(dcx, (char *)derdata.data, derdata.len);
+#endif
+ cinfo = SEC_PKCS7DecoderFinish(dcx);
+ }
+
+ fprintf(out, "\n---------------------------------------------\n");
+
+ if (cinfo == NULL)
+ return -1;
+
+ fprintf(out, "Content was%s encrypted.\n",
+ SEC_PKCS7ContentIsEncrypted(cinfo) ? "" : " not");
+
+ if (SEC_PKCS7ContentIsSigned(cinfo)) {
+ char *signer_cname, *signer_ename;
+ SECItem *signing_time;
+
+ if (saw_content) {
+ fprintf(out, "Signature is ");
+ PORT_SetError(0);
+ if (SEC_PKCS7VerifySignature(cinfo, certUsageEmailSigner, PR_FALSE))
+ fprintf(out, "valid.\n");
+ else
+ fprintf(out, "invalid (Reason: %s).\n",
+ SECU_Strerror(PORT_GetError()));
+ } else {
+ fprintf(out,
+ "Content is detached; signature cannot be verified.\n");
+ }
+
+ signer_cname = SEC_PKCS7GetSignerCommonName(cinfo);
+ if (signer_cname != NULL) {
+ fprintf(out, "The signer's common name is %s\n", signer_cname);
+ PORT_Free(signer_cname);
+ } else {
+ fprintf(out, "No signer common name.\n");
+ }
+
+ signer_ename = SEC_PKCS7GetSignerEmailAddress(cinfo);
+ if (signer_ename != NULL) {
+ fprintf(out, "The signer's email address is %s\n", signer_ename);
+ PORT_Free(signer_ename);
+ } else {
+ fprintf(out, "No signer email address.\n");
+ }
+
+ signing_time = SEC_PKCS7GetSigningTime(cinfo);
+ if (signing_time != NULL) {
+ SECU_PrintTimeChoice(out, signing_time, "Signing time", 0);
+ } else {
+ fprintf(out, "No signing time included.\n");
+ }
+ } else {
+ fprintf(out, "Content was not signed.\n");
+ }
+
+ fprintf(out, "There were%s certs or crls included.\n",
+ SEC_PKCS7ContainsCertsOrCrls(cinfo) ? "" : " no");
+
+ SECITEM_FreeItem(&derdata, PR_FALSE);
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ return 0;
+}
+
+/*
+ * Print the contents of a PKCS7 message, indicating signatures, etc.
+ */
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ FILE *outFile;
+ PRFileDesc *inFile;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus rv;
+ int error = 0;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ inFile = NULL;
+ outFile = NULL;
+
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv, "d:i:o:p:f:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'i':
+ inFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ error = -1;
+ goto done;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ error = -1;
+ goto done;
+ }
+ break;
+
+ case 'p':
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
+
+ case 'f':
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
+
+ default:
+ Usage(progName);
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+
+ if (status == PL_OPT_BAD)
+ Usage(progName);
+
+ if (!inFile)
+ inFile = PR_STDIN;
+ if (!outFile)
+ outFile = stdout;
+
+ /* Call the initialization routines */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_Init(SECU_ConfigDirectory(NULL));
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ error = -1;
+ goto done;
+ }
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ if (DecodeAndPrintFile(outFile, inFile, progName)) {
+ SECU_PrintError(progName, "problem decoding data");
+ error = -1;
+ goto done;
+ }
+
+done:
+ if (inFile && inFile != PR_STDIN) {
+ PR_Close(inFile);
+ }
+ if (outFile && outFile != stdout) {
+ fclose(outFile);
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ error = -1;
+ }
+
+ return error;
+}
diff --git a/security/nss/cmd/p7content/p7content.gyp b/security/nss/cmd/p7content/p7content.gyp
new file mode 100644
index 000000000..7380dfae1
--- /dev/null
+++ b/security/nss/cmd/p7content/p7content.gyp
@@ -0,0 +1,24 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'p7content',
+ 'type': 'executable',
+ 'sources': [
+ 'p7content.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/p7env/Makefile b/security/nss/cmd/p7env/Makefile
new file mode 100644
index 000000000..6e1d4ecdf
--- /dev/null
+++ b/security/nss/cmd/p7env/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/p7env/manifest.mn b/security/nss/cmd/p7env/manifest.mn
new file mode 100644
index 000000000..db385b208
--- /dev/null
+++ b/security/nss/cmd/p7env/manifest.mn
@@ -0,0 +1,15 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+CSRCS = p7env.c
+
+REQUIRES = seccmd
+
+PROGRAM = p7env
+
diff --git a/security/nss/cmd/p7env/p7env.c b/security/nss/cmd/p7env/p7env.c
new file mode 100644
index 000000000..b35bf9a98
--- /dev/null
+++ b/security/nss/cmd/p7env/p7env.c
@@ -0,0 +1,261 @@
+/* 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/. */
+
+/*
+ * p7env -- A command to create a pkcs7 enveloped data.
+ */
+
+#include "nspr.h"
+#include "secutil.h"
+#include "plgetopt.h"
+#include "secpkcs7.h"
+#include "cert.h"
+#include "certdb.h"
+#include "nss.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
+extern int fread(char *, size_t, size_t, FILE *);
+extern int fwrite(char *, size_t, size_t, FILE *);
+extern int fprintf(FILE *, char *, ...);
+#endif
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s -r recipient [-d dbdir] [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s Nickname of cert to use for encryption\n",
+ "-r recipient");
+ fprintf(stderr, "%-20s Cert database directory (default is ~/.netscape)\n",
+ "-d dbdir");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+struct recipient {
+ struct recipient *next;
+ char *nickname;
+ CERTCertificate *cert;
+};
+
+static void
+EncryptOut(void *arg, const char *buf, unsigned long len)
+{
+ FILE *out;
+
+ out = arg;
+ fwrite(buf, len, 1, out);
+}
+
+static int
+EncryptFile(FILE *outFile, FILE *inFile, struct recipient *recipients,
+ char *progName)
+{
+ SEC_PKCS7ContentInfo *cinfo;
+ SEC_PKCS7EncoderContext *ecx;
+ struct recipient *rcpt;
+ SECStatus rv;
+
+ if (outFile == NULL || inFile == NULL || recipients == NULL)
+ return -1;
+
+ /* XXX Need a better way to handle that certUsage stuff! */
+ /* XXX keysize? */
+ cinfo = SEC_PKCS7CreateEnvelopedData(recipients->cert,
+ certUsageEmailRecipient,
+ NULL, SEC_OID_DES_EDE3_CBC, 0,
+ NULL, NULL);
+ if (cinfo == NULL)
+ return -1;
+
+ for (rcpt = recipients->next; rcpt != NULL; rcpt = rcpt->next) {
+ rv = SEC_PKCS7AddRecipient(cinfo, rcpt->cert, certUsageEmailRecipient,
+ NULL);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error adding recipient \"%s\"",
+ rcpt->nickname);
+ return -1;
+ }
+ }
+
+ ecx = SEC_PKCS7EncoderStart(cinfo, EncryptOut, outFile, NULL);
+ if (ecx == NULL)
+ return -1;
+
+ for (;;) {
+ char ibuf[1024];
+ int nb;
+
+ if (feof(inFile))
+ break;
+ nb = fread(ibuf, 1, sizeof(ibuf), inFile);
+ if (nb == 0) {
+ if (ferror(inFile)) {
+ PORT_SetError(SEC_ERROR_IO);
+ rv = SECFailure;
+ }
+ break;
+ }
+ rv = SEC_PKCS7EncoderUpdate(ecx, ibuf, nb);
+ if (rv != SECSuccess)
+ break;
+ }
+
+ if (SEC_PKCS7EncoderFinish(ecx, NULL, NULL) != SECSuccess)
+ rv = SECFailure;
+
+ SEC_PKCS7DestroyContentInfo(cinfo);
+
+ if (rv != SECSuccess)
+ return -1;
+
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ FILE *inFile, *outFile;
+ CERTCertDBHandle *certHandle;
+ struct recipient *recipients, *rcpt;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus rv;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ inFile = NULL;
+ outFile = NULL;
+ recipients = NULL;
+ rcpt = NULL;
+
+ /*
+ * Parse command line arguments
+ * XXX This needs to be enhanced to allow selection of algorithms
+ * and key sizes (or to look up algorithms and key sizes for each
+ * recipient in the magic database).
+ */
+ optstate = PL_CreateOptState(argc, argv, "d:i:o:r:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'i':
+ inFile = fopen(optstate->value, "r");
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "wb");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'r':
+ if (rcpt == NULL) {
+ recipients = rcpt = PORT_Alloc(sizeof(struct recipient));
+ } else {
+ rcpt->next = PORT_Alloc(sizeof(struct recipient));
+ rcpt = rcpt->next;
+ }
+ if (rcpt == NULL) {
+ fprintf(stderr, "%s: unable to allocate recipient struct\n",
+ progName);
+ return -1;
+ }
+ rcpt->nickname = PORT_Strdup(optstate->value);
+ rcpt->cert = NULL;
+ rcpt->next = NULL;
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+
+ if (!recipients)
+ Usage(progName);
+
+ if (!inFile)
+ inFile = stdin;
+ if (!outFile)
+ outFile = stdout;
+
+ /* Call the NSS initialization routines */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_Init(SECU_ConfigDirectory(NULL));
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+
+ /* open cert database */
+ certHandle = CERT_GetDefaultCertDB();
+ if (certHandle == NULL) {
+ return -1;
+ }
+
+ /* find certs */
+ for (rcpt = recipients; rcpt != NULL; rcpt = rcpt->next) {
+ rcpt->cert = CERT_FindCertByNickname(certHandle, rcpt->nickname);
+ if (rcpt->cert == NULL) {
+ SECU_PrintError(progName,
+ "the cert for name \"%s\" not found in database",
+ rcpt->nickname);
+ return -1;
+ }
+ }
+
+ if (EncryptFile(outFile, inFile, recipients, progName)) {
+ SECU_PrintError(progName, "problem encrypting data");
+ return -1;
+ }
+
+ /* free certs */
+ for (rcpt = recipients; rcpt != NULL;) {
+ struct recipient *next = rcpt->next;
+ CERT_DestroyCertificate(rcpt->cert);
+ PORT_Free(rcpt->nickname);
+ PORT_Free(rcpt);
+ rcpt = next;
+ }
+
+ if (inFile && inFile != stdin) {
+ fclose(inFile);
+ }
+ if (outFile && outFile != stdout) {
+ fclose(outFile);
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ SECU_PrintError(progName, "NSS shutdown:");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/security/nss/cmd/p7env/p7env.gyp b/security/nss/cmd/p7env/p7env.gyp
new file mode 100644
index 000000000..e84eaabee
--- /dev/null
+++ b/security/nss/cmd/p7env/p7env.gyp
@@ -0,0 +1,24 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'p7env',
+ 'type': 'executable',
+ 'sources': [
+ 'p7env.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/p7sign/Makefile b/security/nss/cmd/p7sign/Makefile
new file mode 100644
index 000000000..6e1d4ecdf
--- /dev/null
+++ b/security/nss/cmd/p7sign/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/p7sign/manifest.mn b/security/nss/cmd/p7sign/manifest.mn
new file mode 100644
index 000000000..1f32e3954
--- /dev/null
+++ b/security/nss/cmd/p7sign/manifest.mn
@@ -0,0 +1,15 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+CSRCS = p7sign.c
+
+REQUIRES = seccmd
+
+PROGRAM = p7sign
+
diff --git a/security/nss/cmd/p7sign/p7sign.c b/security/nss/cmd/p7sign/p7sign.c
new file mode 100644
index 000000000..3ac462006
--- /dev/null
+++ b/security/nss/cmd/p7sign/p7sign.c
@@ -0,0 +1,281 @@
+/* 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/. */
+
+/*
+ * p7sign -- A command to create a *detached* pkcs7 signature (over a given
+ * input file).
+ */
+
+#include "nspr.h"
+#include "plgetopt.h"
+#include "secutil.h"
+#include "secpkcs7.h"
+#include "cert.h"
+#include "certdb.h"
+#include "sechash.h" /* for HASH_GetHashObject() */
+#include "nss.h"
+#include "pk11func.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
+extern int fread(char *, size_t, size_t, FILE *);
+extern int fwrite(char *, size_t, size_t, FILE *);
+extern int fprintf(FILE *, char *, ...);
+#endif
+
+static secuPWData pwdata = { PW_NONE, 0 };
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s -k keyname [-d keydir] [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s Nickname of key to use for signature\n",
+ "-k keyname");
+ fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
+ "-d keydir");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ fprintf(stderr, "%-20s Encapsulate content in signature message\n",
+ "-e");
+ fprintf(stderr, "%-20s Password to the key databse\n", "-p");
+ fprintf(stderr, "%-20s password file\n", "-f");
+ exit(-1);
+}
+
+static void
+SignOut(void *arg, const char *buf, unsigned long len)
+{
+ FILE *out;
+
+ out = (FILE *)arg;
+ fwrite(buf, len, 1, out);
+}
+
+static int
+CreateDigest(SECItem *data, char *digestdata, unsigned int *len, unsigned int maxlen)
+{
+ const SECHashObject *hashObj;
+ void *hashcx;
+
+ /* XXX probably want to extend interface to allow other hash algorithms */
+ hashObj = HASH_GetHashObject(HASH_AlgSHA1);
+
+ hashcx = (*hashObj->create)();
+ if (hashcx == NULL)
+ return -1;
+
+ (*hashObj->begin)(hashcx);
+ (*hashObj->update)(hashcx, data->data, data->len);
+ (*hashObj->end)(hashcx, (unsigned char *)digestdata, len, maxlen);
+ (*hashObj->destroy)(hashcx, PR_TRUE);
+ return 0;
+}
+
+static int
+SignFile(FILE *outFile, PRFileDesc *inFile, CERTCertificate *cert,
+ PRBool encapsulated)
+{
+ char digestdata[32];
+ unsigned int len;
+ SECItem digest, data2sign;
+ SEC_PKCS7ContentInfo *cinfo;
+ SECStatus rv;
+
+ if (outFile == NULL || inFile == NULL || cert == NULL)
+ return -1;
+
+ /* suck the file in */
+ if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE,
+ PR_FALSE) != SECSuccess)
+ return -1;
+
+ if (!encapsulated) {
+ /* unfortunately, we must create the digest ourselves */
+ /* SEC_PKCS7CreateSignedData should have a flag to not include */
+ /* the content for non-encapsulated content at encode time, but */
+ /* should always compute the hash itself */
+ if (CreateDigest(&data2sign, digestdata, &len, 32) < 0)
+ return -1;
+ digest.data = (unsigned char *)digestdata;
+ digest.len = len;
+ }
+
+ /* XXX Need a better way to handle that usage stuff! */
+ cinfo = SEC_PKCS7CreateSignedData(cert, certUsageEmailSigner, NULL,
+ SEC_OID_SHA1,
+ encapsulated ? NULL : &digest,
+ NULL, NULL);
+ if (cinfo == NULL)
+ return -1;
+
+ if (encapsulated) {
+ SEC_PKCS7SetContent(cinfo, (char *)data2sign.data, data2sign.len);
+ }
+
+ rv = SEC_PKCS7IncludeCertChain(cinfo, NULL);
+ if (rv != SECSuccess) {
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ return -1;
+ }
+
+ rv = SEC_PKCS7Encode(cinfo, SignOut, outFile, NULL,
+ NULL, &pwdata);
+
+ SECITEM_FreeItem(&data2sign, PR_FALSE);
+ SEC_PKCS7DestroyContentInfo(cinfo);
+
+ if (rv != SECSuccess)
+ return -1;
+
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ FILE *outFile;
+ PRFileDesc *inFile;
+ char *keyName = NULL;
+ CERTCertDBHandle *certHandle;
+ CERTCertificate *cert = NULL;
+ PRBool encapsulated = PR_FALSE;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus rv;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ inFile = NULL;
+ outFile = NULL;
+ keyName = NULL;
+
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv, "ed:k:i:o:p:f:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'e':
+ /* create a message with the signed content encapsulated */
+ encapsulated = PR_TRUE;
+ break;
+
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'i':
+ inFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'k':
+ keyName = strdup(optstate->value);
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "wb");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+ case 'p':
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = strdup(optstate->value);
+ break;
+
+ case 'f':
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+
+ if (!keyName)
+ Usage(progName);
+
+ if (!inFile)
+ inFile = PR_STDIN;
+ if (!outFile)
+ outFile = stdout;
+
+ /* Call the initialization routines */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_Init(SECU_ConfigDirectory(NULL));
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ goto loser;
+ }
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ /* open cert database */
+ certHandle = CERT_GetDefaultCertDB();
+ if (certHandle == NULL) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ /* find cert */
+ cert = CERT_FindCertByNickname(certHandle, keyName);
+ if (cert == NULL) {
+ SECU_PrintError(progName,
+ "the corresponding cert for key \"%s\" does not exist",
+ keyName);
+ rv = SECFailure;
+ goto loser;
+ }
+
+ if (SignFile(outFile, inFile, cert, encapsulated)) {
+ SECU_PrintError(progName, "problem signing data");
+ rv = SECFailure;
+ goto loser;
+ }
+
+loser:
+ if (pwdata.data) {
+ PORT_Free(pwdata.data);
+ }
+ if (keyName) {
+ PORT_Free(keyName);
+ }
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+ if (inFile && inFile != PR_STDIN) {
+ PR_Close(inFile);
+ }
+ if (outFile && outFile != stdout) {
+ fclose(outFile);
+ }
+ if (NSS_Shutdown() != SECSuccess) {
+ SECU_PrintError(progName, "NSS shutdown:");
+ exit(1);
+ }
+
+ return (rv != SECSuccess);
+}
diff --git a/security/nss/cmd/p7sign/p7sign.gyp b/security/nss/cmd/p7sign/p7sign.gyp
new file mode 100644
index 000000000..c2c672d7e
--- /dev/null
+++ b/security/nss/cmd/p7sign/p7sign.gyp
@@ -0,0 +1,24 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'p7sign',
+ 'type': 'executable',
+ 'sources': [
+ 'p7sign.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/p7verify/Makefile b/security/nss/cmd/p7verify/Makefile
new file mode 100644
index 000000000..6e1d4ecdf
--- /dev/null
+++ b/security/nss/cmd/p7verify/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/p7verify/manifest.mn b/security/nss/cmd/p7verify/manifest.mn
new file mode 100644
index 000000000..565c74bc2
--- /dev/null
+++ b/security/nss/cmd/p7verify/manifest.mn
@@ -0,0 +1,15 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+CSRCS = p7verify.c
+
+REQUIRES = seccmd
+
+PROGRAM = p7verify
+
diff --git a/security/nss/cmd/p7verify/p7verify.c b/security/nss/cmd/p7verify/p7verify.c
new file mode 100644
index 000000000..ba38e1158
--- /dev/null
+++ b/security/nss/cmd/p7verify/p7verify.c
@@ -0,0 +1,283 @@
+/* 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/. */
+
+/*
+ * p7verify -- A command to do a verification of a *detached* pkcs7 signature.
+ */
+
+#include "nspr.h"
+#include "secutil.h"
+#include "plgetopt.h"
+#include "secpkcs7.h"
+#include "cert.h"
+#include "certdb.h"
+#include "secoid.h"
+#include "sechash.h" /* for HASH_GetHashObject() */
+#include "nss.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
+extern int fread(char *, size_t, size_t, FILE *);
+extern int fprintf(FILE *, char *, ...);
+#endif
+
+static HASH_HashType
+AlgorithmToHashType(SECAlgorithmID *digestAlgorithms)
+{
+
+ SECOidTag tag;
+
+ tag = SECOID_GetAlgorithmTag(digestAlgorithms);
+
+ switch (tag) {
+ case SEC_OID_MD2:
+ return HASH_AlgMD2;
+ case SEC_OID_MD5:
+ return HASH_AlgMD5;
+ case SEC_OID_SHA1:
+ return HASH_AlgSHA1;
+ default:
+ fprintf(stderr, "should never get here\n");
+ return HASH_AlgNULL;
+ }
+}
+
+static int
+DigestFile(unsigned char *digest, unsigned int *len, unsigned int maxLen,
+ FILE *inFile, HASH_HashType hashType)
+{
+ int nb;
+ unsigned char ibuf[4096];
+ const SECHashObject *hashObj;
+ void *hashcx;
+
+ hashObj = HASH_GetHashObject(hashType);
+
+ hashcx = (*hashObj->create)();
+ if (hashcx == NULL)
+ return -1;
+
+ (*hashObj->begin)(hashcx);
+
+ for (;;) {
+ if (feof(inFile))
+ break;
+ nb = fread(ibuf, 1, sizeof(ibuf), inFile);
+ if (nb != sizeof(ibuf)) {
+ if (nb == 0) {
+ if (ferror(inFile)) {
+ PORT_SetError(SEC_ERROR_IO);
+ (*hashObj->destroy)(hashcx, PR_TRUE);
+ return -1;
+ }
+ /* eof */
+ break;
+ }
+ }
+ (*hashObj->update)(hashcx, ibuf, nb);
+ }
+
+ (*hashObj->end)(hashcx, digest, len, maxLen);
+ (*hashObj->destroy)(hashcx, PR_TRUE);
+
+ return 0;
+}
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s -c content -s signature [-d dbdir] [-u certusage]\n",
+ progName);
+ fprintf(stderr, "%-20s content file that was signed\n",
+ "-c content");
+ fprintf(stderr, "%-20s file containing signature for that content\n",
+ "-s signature");
+ fprintf(stderr,
+ "%-20s Key/Cert database directory (default is ~/.netscape)\n",
+ "-d dbdir");
+ fprintf(stderr, "%-20s Define the type of certificate usage (default is certUsageEmailSigner)\n",
+ "-u certusage");
+ fprintf(stderr, "%-25s 0 - certUsageSSLClient\n", " ");
+ fprintf(stderr, "%-25s 1 - certUsageSSLServer\n", " ");
+ fprintf(stderr, "%-25s 2 - certUsageSSLServerWithStepUp\n", " ");
+ fprintf(stderr, "%-25s 3 - certUsageSSLCA\n", " ");
+ fprintf(stderr, "%-25s 4 - certUsageEmailSigner\n", " ");
+ fprintf(stderr, "%-25s 5 - certUsageEmailRecipient\n", " ");
+ fprintf(stderr, "%-25s 6 - certUsageObjectSigner\n", " ");
+ fprintf(stderr, "%-25s 7 - certUsageUserCertImport\n", " ");
+ fprintf(stderr, "%-25s 8 - certUsageVerifyCA\n", " ");
+ fprintf(stderr, "%-25s 9 - certUsageProtectedObjectSigner\n", " ");
+ fprintf(stderr, "%-25s 10 - certUsageStatusResponder\n", " ");
+ fprintf(stderr, "%-25s 11 - certUsageAnyCA\n", " ");
+
+ exit(-1);
+}
+
+static int
+HashDecodeAndVerify(FILE *out, FILE *content, PRFileDesc *signature,
+ SECCertUsage usage, char *progName)
+{
+ SECItem derdata;
+ SEC_PKCS7ContentInfo *cinfo;
+ SEC_PKCS7SignedData *signedData;
+ HASH_HashType digestType;
+ SECItem digest;
+ unsigned char buffer[32];
+
+ if (SECU_ReadDERFromFile(&derdata, signature, PR_FALSE,
+ PR_FALSE) != SECSuccess) {
+ SECU_PrintError(progName, "error reading signature file");
+ return -1;
+ }
+
+ cinfo = SEC_PKCS7DecodeItem(&derdata, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if (cinfo == NULL)
+ return -1;
+
+ if (!SEC_PKCS7ContentIsSigned(cinfo)) {
+ fprintf(out, "Signature file is pkcs7 data, but not signed.\n");
+ return -1;
+ }
+
+ signedData = cinfo->content.signedData;
+
+ /* assume that there is only one digest algorithm for now */
+ digestType = AlgorithmToHashType(signedData->digestAlgorithms[0]);
+ if (digestType == HASH_AlgNULL) {
+ fprintf(out, "Invalid hash algorithmID\n");
+ return -1;
+ }
+
+ digest.data = buffer;
+ if (DigestFile(digest.data, &digest.len, 32, content, digestType)) {
+ SECU_PrintError(progName, "problem computing message digest");
+ return -1;
+ }
+
+ fprintf(out, "Signature is ");
+ if (SEC_PKCS7VerifyDetachedSignature(cinfo, usage, &digest, digestType,
+ PR_FALSE))
+ fprintf(out, "valid.\n");
+ else
+ fprintf(out, "invalid (Reason: %s).\n",
+ SECU_Strerror(PORT_GetError()));
+
+ SECITEM_FreeItem(&derdata, PR_FALSE);
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ FILE *contentFile, *outFile;
+ PRFileDesc *signatureFile;
+ SECCertUsage certUsage = certUsageEmailSigner;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus rv;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ contentFile = NULL;
+ signatureFile = NULL;
+ outFile = NULL;
+
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv, "c:d:o:s:u:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'c':
+ contentFile = fopen(optstate->value, "r");
+ if (!contentFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 's':
+ signatureFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!signatureFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'u': {
+ int usageType;
+
+ usageType = atoi(strdup(optstate->value));
+ if (usageType < certUsageSSLClient || usageType > certUsageAnyCA)
+ return -1;
+ certUsage = (SECCertUsage)usageType;
+ break;
+ }
+ }
+ }
+ PL_DestroyOptState(optstate);
+
+ if (!contentFile)
+ Usage(progName);
+ if (!signatureFile)
+ Usage(progName);
+ if (!outFile)
+ outFile = stdout;
+
+ /* Call the NSS initialization routines */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_Init(SECU_ConfigDirectory(NULL));
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+
+ if (HashDecodeAndVerify(outFile, contentFile, signatureFile,
+ certUsage, progName)) {
+ SECU_PrintError(progName, "problem decoding/verifying signature");
+ return -1;
+ }
+
+ fclose(contentFile);
+ PR_Close(signatureFile);
+ if (outFile && outFile != stdout) {
+ fclose(outFile);
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/security/nss/cmd/p7verify/p7verify.gyp b/security/nss/cmd/p7verify/p7verify.gyp
new file mode 100644
index 000000000..220a72a42
--- /dev/null
+++ b/security/nss/cmd/p7verify/p7verify.gyp
@@ -0,0 +1,24 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'p7verify',
+ 'type': 'executable',
+ 'sources': [
+ 'p7verify.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/pk11ectest/Makefile b/security/nss/cmd/pk11ectest/Makefile
new file mode 100644
index 000000000..d20daa4b7
--- /dev/null
+++ b/security/nss/cmd/pk11ectest/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/pk11ectest/manifest.mn b/security/nss/cmd/pk11ectest/manifest.mn
new file mode 100644
index 000000000..af814b581
--- /dev/null
+++ b/security/nss/cmd/pk11ectest/manifest.mn
@@ -0,0 +1,16 @@
+#
+# 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/.
+
+DEPTH = ../..
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = pk11ectest.c
+
+PROGRAM = pk11ectest
+
+USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/pk11ectest/pk11ectest.c b/security/nss/cmd/pk11ectest/pk11ectest.c
new file mode 100644
index 000000000..ca6e2d0d1
--- /dev/null
+++ b/security/nss/cmd/pk11ectest/pk11ectest.c
@@ -0,0 +1,171 @@
+/* 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/. */
+
+#include "blapi.h"
+#include "nss.h"
+#include "secutil.h"
+#include "secitem.h"
+#include "nspr.h"
+#include "pk11pub.h"
+#include <stdio.h>
+
+void
+printBuf(const SECItem *item)
+{
+ int i;
+ if (!item || !item->len) {
+ printf("(null)\n");
+ return;
+ }
+
+ for (i = 0; i < item->len; i++) {
+ printf("%02x", item->data[i]);
+ }
+ printf("\n");
+}
+
+void
+PrintKey(PK11SymKey *symKey)
+{
+ char *name = PK11_GetSymKeyNickname(symKey);
+ int len = PK11_GetKeyLength(symKey);
+ int strength = PK11_GetKeyStrength(symKey, NULL);
+ SECItem *value = NULL;
+ CK_KEY_TYPE type = PK11_GetSymKeyType(symKey);
+ (void)PK11_ExtractKeyValue(symKey);
+
+ value = PK11_GetKeyData(symKey);
+ printf("%s %3d %4d %s ", name ? name : "no-name", len, strength,
+ type == CKK_GENERIC_SECRET ? "generic" : "ERROR! UNKNOWN KEY TYPE");
+ printBuf(value);
+
+ PORT_Free(name);
+}
+
+SECStatus
+ectest_curve_pkcs11(SECOidTag oid)
+{
+ SECKEYECParams pk_11_ecParams = { siBuffer, NULL, 0 };
+ SECKEYPublicKey *pubKey = NULL;
+ SECKEYPrivateKey *privKey = NULL;
+ SECOidData *oidData = NULL;
+ CK_MECHANISM_TYPE target = CKM_TLS12_MASTER_KEY_DERIVE_DH;
+ PK11SymKey *symKey = NULL;
+ SECStatus rv = SECFailure;
+
+ oidData = SECOID_FindOIDByTag(oid);
+ if (oidData == NULL) {
+ printf(" >>> SECOID_FindOIDByTag failed.\n");
+ goto cleanup;
+ }
+ PORT_Assert(oidData->oid.len < 256);
+ SECITEM_AllocItem(NULL, &pk_11_ecParams, (2 + oidData->oid.len));
+ pk_11_ecParams.data[0] = SEC_ASN1_OBJECT_ID; /* we have to prepend 0x06 */
+ pk_11_ecParams.data[1] = oidData->oid.len;
+ memcpy(pk_11_ecParams.data + 2, oidData->oid.data, oidData->oid.len);
+
+ privKey = SECKEY_CreateECPrivateKey(&pk_11_ecParams, &pubKey, NULL);
+ if (!privKey || !pubKey) {
+ printf(" >>> SECKEY_CreateECPrivateKey failed.\n");
+ goto cleanup;
+ }
+
+ symKey = PK11_PubDeriveWithKDF(privKey, pubKey, PR_FALSE, NULL, NULL,
+ CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
+ CKD_NULL, NULL, NULL);
+ if (!symKey) {
+ printf(" >>> PK11_PubDeriveWithKDF failed.\n");
+ goto cleanup;
+ }
+ PrintKey(symKey);
+ rv = SECSuccess;
+
+cleanup:
+ if (privKey) {
+ SECKEY_DestroyPrivateKey(privKey);
+ }
+ if (pubKey) {
+ SECKEY_DestroyPublicKey(pubKey);
+ }
+ if (symKey) {
+ PK11_FreeSymKey(symKey);
+ }
+ SECITEM_FreeItem(&pk_11_ecParams, PR_FALSE);
+
+ return rv;
+}
+
+void
+printUsage(char *prog)
+{
+ printf("Usage: %s [-fp] [-nd]\n"
+ "\t-n: NIST curves\n"
+ "\t-d: non-NIST curves\n"
+ "You have to specify at at least one of n or d.\n"
+ "By default no tests are executed.\n",
+ prog);
+}
+
+/* Performs tests of elliptic curve cryptography over prime fields If
+ * tests fail, then it prints an error message, aborts, and returns an
+ * error code. Otherwise, returns 0. */
+int
+main(int argv, char **argc)
+{
+ SECStatus rv = SECSuccess;
+ int i = 0;
+ int nist = 0;
+ int nonnist = 0;
+ SECOidTag nistOids[3] = { SEC_OID_SECG_EC_SECP256R1,
+ SEC_OID_SECG_EC_SECP384R1,
+ SEC_OID_SECG_EC_SECP521R1 };
+
+ for (i = 1; i < argv; i++) {
+ if (PL_strcasecmp(argc[i], "-n") == 0) {
+ nist = 1;
+ } else if (PL_strcasecmp(argc[i], "-d") == 0) {
+ nonnist = 1;
+ } else {
+ printUsage(argc[0]);
+ return 1;
+ }
+ }
+ if (!nist && !nonnist) {
+ printUsage(argc[0]);
+ return 1;
+ }
+
+ rv = NSS_NoDB_Init(NULL);
+ if (rv != SECSuccess) {
+ SECU_PrintError("Error:", "NSS_NoDB_Init");
+ goto cleanup;
+ }
+
+ if (nonnist) {
+ if (ectest_curve_pkcs11(SEC_OID_CURVE25519) != SECSuccess) {
+ printf("not okay (OID %d) - PK11 test\n", SEC_OID_CURVE25519);
+ rv = SECFailure;
+ } else {
+ printf("okay (OID %d) - PK11 test\n", SEC_OID_CURVE25519);
+ }
+ }
+ if (nist) {
+ for (i = 0; i < 3; ++i) {
+ if (ectest_curve_pkcs11(nistOids[i]) != SECSuccess) {
+ printf("not okay (OID %d) - PK11 test\n", nistOids[i]);
+ rv = SECFailure;
+ } else {
+ printf("okay (OID %d) - PK11 test\n", nistOids[i]);
+ }
+ }
+ }
+
+cleanup:
+ rv |= NSS_Shutdown();
+
+ if (rv != SECSuccess) {
+ printf("Error: exiting with error value\n");
+ }
+ return rv;
+}
diff --git a/security/nss/cmd/pk11ectest/pk11ectest.gyp b/security/nss/cmd/pk11ectest/pk11ectest.gyp
new file mode 100644
index 000000000..584bc0741
--- /dev/null
+++ b/security/nss/cmd/pk11ectest/pk11ectest.gyp
@@ -0,0 +1,31 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pk11ectest',
+ 'type': 'executable',
+ 'sources': [
+ 'pk11ectest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports',
+ '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSS_USE_STATIC_LIBS'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss',
+ 'use_static_libs': 1
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/pk11gcmtest/Makefile b/security/nss/cmd/pk11gcmtest/Makefile
new file mode 100755
index 000000000..3ffa38747
--- /dev/null
+++ b/security/nss/cmd/pk11gcmtest/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/security/nss/cmd/pk11gcmtest/manifest.mn b/security/nss/cmd/pk11gcmtest/manifest.mn
new file mode 100644
index 000000000..f5bc0ece0
--- /dev/null
+++ b/security/nss/cmd/pk11gcmtest/manifest.mn
@@ -0,0 +1,20 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+PROGRAM = pk11gcmtest
+
+EXPORTS = \
+ $(NULL)
+
+PRIVATE_EXPORTS = \
+ $(NULL)
+
+CSRCS = \
+ pk11gcmtest.c \
+ $(NULL)
diff --git a/security/nss/cmd/pk11gcmtest/pk11gcmtest.c b/security/nss/cmd/pk11gcmtest/pk11gcmtest.c
new file mode 100644
index 000000000..1b8bff5e4
--- /dev/null
+++ b/security/nss/cmd/pk11gcmtest/pk11gcmtest.c
@@ -0,0 +1,460 @@
+/* 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/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "pk11pub.h"
+#include "secerr.h"
+#include "nss.h"
+
+static SECStatus
+hex_to_byteval(const char *c2, unsigned char *byteval)
+{
+ int i;
+ unsigned char offset;
+ *byteval = 0;
+ for (i = 0; i < 2; i++) {
+ if (c2[i] >= '0' && c2[i] <= '9') {
+ offset = c2[i] - '0';
+ *byteval |= offset << 4 * (1 - i);
+ } else if (c2[i] >= 'a' && c2[i] <= 'f') {
+ offset = c2[i] - 'a';
+ *byteval |= (offset + 10) << 4 * (1 - i);
+ } else if (c2[i] >= 'A' && c2[i] <= 'F') {
+ offset = c2[i] - 'A';
+ *byteval |= (offset + 10) << 4 * (1 - i);
+ } else {
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+aes_encrypt_buf(
+ const unsigned char *key, unsigned int keysize,
+ const unsigned char *iv, unsigned int ivsize,
+ unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
+ const unsigned char *input, unsigned int inputlen,
+ const unsigned char *aad, unsigned int aadlen, unsigned int tagsize)
+{
+ SECStatus rv = SECFailure;
+ SECItem key_item;
+ PK11SlotInfo *slot = NULL;
+ PK11SymKey *symKey = NULL;
+ CK_GCM_PARAMS gcm_params;
+ SECItem param;
+
+ /* Import key into NSS. */
+ key_item.type = siBuffer;
+ key_item.data = (unsigned char *)key; /* const cast */
+ key_item.len = keysize;
+ slot = PK11_GetInternalSlot();
+ symKey = PK11_ImportSymKey(slot, CKM_AES_GCM, PK11_OriginUnwrap,
+ CKA_ENCRYPT, &key_item, NULL);
+ PK11_FreeSlot(slot);
+ slot = NULL;
+ if (!symKey) {
+ fprintf(stderr, "PK11_ImportSymKey failed\n");
+ goto loser;
+ }
+
+ gcm_params.pIv = (unsigned char *)iv; /* const cast */
+ gcm_params.ulIvLen = ivsize;
+ gcm_params.pAAD = (unsigned char *)aad; /* const cast */
+ gcm_params.ulAADLen = aadlen;
+ gcm_params.ulTagBits = tagsize * 8;
+
+ param.type = siBuffer;
+ param.data = (unsigned char *)&gcm_params;
+ param.len = sizeof(gcm_params);
+
+ if (PK11_Encrypt(symKey, CKM_AES_GCM, &param,
+ output, outputlen, maxoutputlen,
+ input, inputlen) != SECSuccess) {
+ fprintf(stderr, "PK11_Encrypt failed\n");
+ goto loser;
+ }
+
+ rv = SECSuccess;
+
+loser:
+ if (symKey != NULL) {
+ PK11_FreeSymKey(symKey);
+ }
+ return rv;
+}
+
+static SECStatus
+aes_decrypt_buf(
+ const unsigned char *key, unsigned int keysize,
+ const unsigned char *iv, unsigned int ivsize,
+ unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
+ const unsigned char *input, unsigned int inputlen,
+ const unsigned char *aad, unsigned int aadlen,
+ const unsigned char *tag, unsigned int tagsize)
+{
+ SECStatus rv = SECFailure;
+ unsigned char concatenated[11 * 16]; /* 1 to 11 blocks */
+ SECItem key_item;
+ PK11SlotInfo *slot = NULL;
+ PK11SymKey *symKey = NULL;
+ CK_GCM_PARAMS gcm_params;
+ SECItem param;
+
+ if (inputlen + tagsize > sizeof(concatenated)) {
+ fprintf(stderr, "aes_decrypt_buf: local buffer too small\n");
+ goto loser;
+ }
+ memcpy(concatenated, input, inputlen);
+ memcpy(concatenated + inputlen, tag, tagsize);
+
+ /* Import key into NSS. */
+ key_item.type = siBuffer;
+ key_item.data = (unsigned char *)key; /* const cast */
+ key_item.len = keysize;
+ slot = PK11_GetInternalSlot();
+ symKey = PK11_ImportSymKey(slot, CKM_AES_GCM, PK11_OriginUnwrap,
+ CKA_DECRYPT, &key_item, NULL);
+ PK11_FreeSlot(slot);
+ slot = NULL;
+ if (!symKey) {
+ fprintf(stderr, "PK11_ImportSymKey failed\n");
+ goto loser;
+ }
+
+ gcm_params.pIv = (unsigned char *)iv;
+ gcm_params.ulIvLen = ivsize;
+ gcm_params.pAAD = (unsigned char *)aad;
+ gcm_params.ulAADLen = aadlen;
+ gcm_params.ulTagBits = tagsize * 8;
+
+ param.type = siBuffer;
+ param.data = (unsigned char *)&gcm_params;
+ param.len = sizeof(gcm_params);
+
+ if (PK11_Decrypt(symKey, CKM_AES_GCM, &param,
+ output, outputlen, maxoutputlen,
+ concatenated, inputlen + tagsize) != SECSuccess) {
+ goto loser;
+ }
+
+ rv = SECSuccess;
+
+loser:
+ if (symKey != NULL) {
+ PK11_FreeSymKey(symKey);
+ }
+ return rv;
+}
+
+/*
+ * Perform the AES Known Answer Test (KAT) in Galois Counter Mode (GCM).
+ *
+ * respfn is the pathname of the RESPONSE file.
+ */
+static void
+aes_gcm_kat(const char *respfn)
+{
+ char buf[512]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "CIPHERTEXT = <320 hex digits>\n".
+ */
+ FILE *aesresp; /* input stream from the RESPONSE file */
+ int i, j;
+ unsigned int test_group = 0;
+ unsigned int num_tests = 0;
+ PRBool is_encrypt;
+ unsigned char key[32]; /* 128, 192, or 256 bits */
+ unsigned int keysize = 16;
+ unsigned char iv[10 * 16]; /* 1 to 10 blocks */
+ unsigned int ivsize = 12;
+ unsigned char plaintext[10 * 16]; /* 1 to 10 blocks */
+ unsigned int plaintextlen = 0;
+ unsigned char aad[10 * 16]; /* 1 to 10 blocks */
+ unsigned int aadlen = 0;
+ unsigned char ciphertext[10 * 16]; /* 1 to 10 blocks */
+ unsigned int ciphertextlen = 0;
+ unsigned char tag[16];
+ unsigned int tagsize = 16;
+ unsigned char output[10 * 16]; /* 1 to 10 blocks */
+ unsigned int outputlen = 0;
+
+ unsigned int expected_keylen = 0;
+ unsigned int expected_ivlen = 0;
+ unsigned int expected_ptlen = 0;
+ unsigned int expected_aadlen = 0;
+ unsigned int expected_taglen = 0;
+ SECStatus rv;
+
+ if (strstr(respfn, "Encrypt") != NULL) {
+ is_encrypt = PR_TRUE;
+ } else if (strstr(respfn, "Decrypt") != NULL) {
+ is_encrypt = PR_FALSE;
+ } else {
+ fprintf(stderr, "Input file name must contain Encrypt or Decrypt\n");
+ exit(1);
+ }
+ aesresp = fopen(respfn, "r");
+ if (aesresp == NULL) {
+ fprintf(stderr, "Cannot open input file %s\n", respfn);
+ exit(1);
+ }
+ while (fgets(buf, sizeof buf, aesresp) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ continue;
+ }
+ /* [Keylen = ...], [IVlen = ...], etc. */
+ if (buf[0] == '[') {
+ if (strncmp(&buf[1], "Keylen = ", 9) == 0) {
+ expected_keylen = atoi(&buf[10]);
+ } else if (strncmp(&buf[1], "IVlen = ", 8) == 0) {
+ expected_ivlen = atoi(&buf[9]);
+ } else if (strncmp(&buf[1], "PTlen = ", 8) == 0) {
+ expected_ptlen = atoi(&buf[9]);
+ } else if (strncmp(&buf[1], "AADlen = ", 9) == 0) {
+ expected_aadlen = atoi(&buf[10]);
+ } else if (strncmp(&buf[1], "Taglen = ", 9) == 0) {
+ expected_taglen = atoi(&buf[10]);
+
+ test_group++;
+ if (test_group > 1) {
+ /* Report num_tests for the previous test group. */
+ printf("%u tests\n", num_tests);
+ }
+ num_tests = 0;
+ printf("Keylen = %u, IVlen = %u, PTlen = %u, AADlen = %u, "
+ "Taglen = %u: ",
+ expected_keylen, expected_ivlen,
+ expected_ptlen, expected_aadlen, expected_taglen);
+ /* Convert lengths in bits to lengths in bytes. */
+ PORT_Assert(expected_keylen % 8 == 0);
+ expected_keylen /= 8;
+ PORT_Assert(expected_ivlen % 8 == 0);
+ expected_ivlen /= 8;
+ PORT_Assert(expected_ptlen % 8 == 0);
+ expected_ptlen /= 8;
+ PORT_Assert(expected_aadlen % 8 == 0);
+ expected_aadlen /= 8;
+ PORT_Assert(expected_taglen % 8 == 0);
+ expected_taglen /= 8;
+ } else {
+ fprintf(stderr, "Unexpected input line: %s\n", buf);
+ exit(1);
+ }
+ continue;
+ }
+ /* "Count = x" begins a new data set */
+ if (strncmp(buf, "Count", 5) == 0) {
+ /* zeroize the variables for the test with this data set */
+ memset(key, 0, sizeof key);
+ keysize = 0;
+ memset(iv, 0, sizeof iv);
+ ivsize = 0;
+ memset(plaintext, 0, sizeof plaintext);
+ plaintextlen = 0;
+ memset(aad, 0, sizeof aad);
+ aadlen = 0;
+ memset(ciphertext, 0, sizeof ciphertext);
+ ciphertextlen = 0;
+ memset(output, 0, sizeof output);
+ outputlen = 0;
+ num_tests++;
+ continue;
+ }
+ /* Key = ... */
+ if (strncmp(buf, "Key", 3) == 0) {
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ keysize = j;
+ if (keysize != expected_keylen) {
+ fprintf(stderr, "Unexpected key length: %u vs. %u\n",
+ keysize, expected_keylen);
+ exit(1);
+ }
+ continue;
+ }
+ /* IV = ... */
+ if (strncmp(buf, "IV", 2) == 0) {
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &iv[j]);
+ }
+ ivsize = j;
+ if (ivsize != expected_ivlen) {
+ fprintf(stderr, "Unexpected IV length: %u vs. %u\n",
+ ivsize, expected_ivlen);
+ exit(1);
+ }
+ continue;
+ }
+ /* PT = ... */
+ if (strncmp(buf, "PT", 2) == 0) {
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &plaintext[j]);
+ }
+ plaintextlen = j;
+ if (plaintextlen != expected_ptlen) {
+ fprintf(stderr, "Unexpected PT length: %u vs. %u\n",
+ plaintextlen, expected_ptlen);
+ exit(1);
+ }
+
+ if (!is_encrypt) {
+ rv = aes_decrypt_buf(key, keysize, iv, ivsize,
+ output, &outputlen, sizeof output,
+ ciphertext, ciphertextlen, aad, aadlen, tag, tagsize);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "aes_decrypt_buf failed\n");
+ goto loser;
+ }
+ if (outputlen != plaintextlen) {
+ fprintf(stderr, "aes_decrypt_buf: wrong output size\n");
+ goto loser;
+ }
+ if (memcmp(output, plaintext, plaintextlen) != 0) {
+ fprintf(stderr, "aes_decrypt_buf: wrong plaintext\n");
+ goto loser;
+ }
+ }
+ continue;
+ }
+ /* FAIL */
+ if (strncmp(buf, "FAIL", 4) == 0) {
+ plaintextlen = 0;
+
+ PORT_Assert(!is_encrypt);
+ rv = aes_decrypt_buf(key, keysize, iv, ivsize,
+ output, &outputlen, sizeof output,
+ ciphertext, ciphertextlen, aad, aadlen, tag, tagsize);
+ if (rv != SECFailure) {
+ fprintf(stderr, "aes_decrypt_buf succeeded unexpectedly\n");
+ goto loser;
+ }
+ if (PORT_GetError() != SEC_ERROR_BAD_DATA) {
+ fprintf(stderr, "aes_decrypt_buf failed with incorrect "
+ "error code\n");
+ goto loser;
+ }
+ continue;
+ }
+ /* AAD = ... */
+ if (strncmp(buf, "AAD", 3) == 0) {
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &aad[j]);
+ }
+ aadlen = j;
+ if (aadlen != expected_aadlen) {
+ fprintf(stderr, "Unexpected AAD length: %u vs. %u\n",
+ aadlen, expected_aadlen);
+ exit(1);
+ }
+ continue;
+ }
+ /* CT = ... */
+ if (strncmp(buf, "CT", 2) == 0) {
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &ciphertext[j]);
+ }
+ ciphertextlen = j;
+ if (ciphertextlen != expected_ptlen) {
+ fprintf(stderr, "Unexpected CT length: %u vs. %u\n",
+ ciphertextlen, expected_ptlen);
+ exit(1);
+ }
+ continue;
+ }
+ /* Tag = ... */
+ if (strncmp(buf, "Tag", 3) == 0) {
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; isxdigit(buf[i]); i += 2, j++) {
+ hex_to_byteval(&buf[i], &tag[j]);
+ }
+ tagsize = j;
+ if (tagsize != expected_taglen) {
+ fprintf(stderr, "Unexpected tag length: %u vs. %u\n",
+ tagsize, expected_taglen);
+ exit(1);
+ }
+
+ if (is_encrypt) {
+ rv = aes_encrypt_buf(key, keysize, iv, ivsize,
+ output, &outputlen, sizeof output,
+ plaintext, plaintextlen, aad, aadlen, tagsize);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "aes_encrypt_buf failed\n");
+ goto loser;
+ }
+ if (outputlen != plaintextlen + tagsize) {
+ fprintf(stderr, "aes_encrypt_buf: wrong output size\n");
+ goto loser;
+ }
+ if (memcmp(output, ciphertext, plaintextlen) != 0) {
+ fprintf(stderr, "aes_encrypt_buf: wrong ciphertext\n");
+ goto loser;
+ }
+ if (memcmp(output + plaintextlen, tag, tagsize) != 0) {
+ fprintf(stderr, "aes_encrypt_buf: wrong tag\n");
+ goto loser;
+ }
+ }
+ continue;
+ }
+ }
+ /* Report num_tests for the last test group. */
+ printf("%u tests\n", num_tests);
+ printf("%u test groups\n", test_group);
+ printf("PASS\n");
+loser:
+ fclose(aesresp);
+}
+
+int
+main(int argc, char **argv)
+{
+ if (argc < 2)
+ exit(1);
+
+ NSS_NoDB_Init(NULL);
+
+ /*************/
+ /* AES */
+ /*************/
+ if (strcmp(argv[1], "aes") == 0) {
+ /* argv[2]=kat argv[3]=gcm argv[4]=<test name>.rsp */
+ if (strcmp(argv[2], "kat") == 0) {
+ /* Known Answer Test (KAT) */
+ aes_gcm_kat(argv[4]);
+ }
+ }
+
+ NSS_Shutdown();
+ return 0;
+}
diff --git a/security/nss/cmd/pk11gcmtest/pk11gcmtest.gyp b/security/nss/cmd/pk11gcmtest/pk11gcmtest.gyp
new file mode 100644
index 000000000..fff80f8e8
--- /dev/null
+++ b/security/nss/cmd/pk11gcmtest/pk11gcmtest.gyp
@@ -0,0 +1,24 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pk11gcmtest',
+ 'type': 'executable',
+ 'sources': [
+ 'pk11gcmtest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/pk11gcmtest/tests/README b/security/nss/cmd/pk11gcmtest/tests/README
new file mode 100644
index 000000000..9131b5231
--- /dev/null
+++ b/security/nss/cmd/pk11gcmtest/tests/README
@@ -0,0 +1,14 @@
+The GCM test vectors in this directory were downloaded from the NIST
+Cryptographic Algorithm Validation Program (CAVP) website
+(http://csrc.nist.gov/groups/STM/cavp/) on Mar 29, 2013 using the URL
+http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip.
+
+The original test files are about 3 MB each, which are too big to
+include in the NSS source tree. I observed the following patterns in
+the test vectors:
+1. Taglen changes in a cycle of 7: 128, 120, 112, 104, 96, 64, 32.
+2. Then, AADlen changes in a cycle of 5: 0, 128, 160, 384, 720.
+
+To reduce the number of test vectors, I kept Taglen = 128, 96 from
+each cycle of 7, and kept AADlen = 0, 720, 160 from each two cycles
+of 10.
diff --git a/security/nss/cmd/pk11gcmtest/tests/gcmDecrypt128.rsp b/security/nss/cmd/pk11gcmtest/tests/gcmDecrypt128.rsp
new file mode 100644
index 000000000..49f264fd5
--- /dev/null
+++ b/security/nss/cmd/pk11gcmtest/tests/gcmDecrypt128.rsp
@@ -0,0 +1,1016 @@
+# CAVS 14.0
+# GCM Decrypt with keysize 128 test information
+# Generated on Fri Aug 31 11:28:04 2012
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = cf063a34d4a9a76c2c86787d3f96db71
+IV = 113b9785971864c83b01c787
+CT =
+AAD =
+Tag = 72ac8493e3a5228b5d130a69d2510e42
+PT =
+
+Count = 1
+Key = a49a5e26a2f8cb63d05546c2a62f5343
+IV = 907763b19b9b4ab6bd4f0281
+CT =
+AAD =
+Tag = a2be08210d8c470a8df6e8fbd79ec5cf
+FAIL
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 4c5a02440befba5820539ccf74b40355
+IV = 3852fd7da7a375a2a2227e9c
+CT =
+AAD =
+Tag = 9f45b723d14708dad1edd831
+FAIL
+
+Count = 1
+Key = d4e885208426247f27428ede3b318e68
+IV = 5513f9ec35e2e72be3470f57
+CT =
+AAD =
+Tag = 48d716f0f94ac7fbc291932e
+PT =
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = c1e007d318d0e5c87d28fd890dfb04ba
+IV = d7bc58d494491ff57639b60b
+CT =
+AAD = 10c68681c6d700ffc72ea9a790cdc9ddc1904c7e886e23ca166dbfa364a4c5f95205bdd1f22eeebefbbb9375f1a416ec7faed6cfdf706085f8fd2632c7a261a78875811f17fba19baf905f0aa623e67175f2158cda313a5047e3
+Tag = 2f1ede16f025bc8c5421854b5f0109d1
+FAIL
+
+Count = 1
+Key = 8dc7a59a71cd76499de67feac53c786a
+IV = beb45b75ea5b7750e69a409d
+CT =
+AAD = 8bade18807ac5fe59cfd34d7eed8ae33dfeeb960d2a15693837f22dd98f68715079d358a49a04a7b231d486ae45f4cd6c0fe3cde6c0d967ce8d84bbf2e4be2db793afb72ea83c7b21a73f65742c214768f7e6133e3814059efb6
+Tag = 46e8457d8d409f2a0690e6502f8b7a87
+PT =
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = e6121ca9c088109b2e06459b42f5a495
+IV = dee4fad3a3f9c9bfe6fef753
+CT =
+AAD = 2a47d75ac2059be2b810e87240b09ca712aa819ec9c31ffb6dee5c2a828a8e735c3552d25e6edba53278a8d744cc97600967c75f9c8c96df22a724231661f085dac3cdfd15a9bda24f721805683699b3b369e1035e224604dcd2
+Tag = 3f577c08bb955e40dfd59b1b
+FAIL
+
+Count = 1
+Key = 3b7717cf63d8f5074507212006910ebc
+IV = 5e8a852f062eef137b46e3d6
+CT =
+AAD = 33db774fef0358cc960d6344b791c514ce22b1931137a7a8afd308180549591208f183bc0557dbfe92deda9d0d4664cf6761fe7f03729bb29b213da1216ed0a30fbfa0a27e8fe5d7706fd9a6369d4ee3906ab6cdaf567d0346f4
+Tag = 2378397900d520970a0eadc2
+FAIL
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 4cf56dd7eb109452d7445e79bcad4f86
+IV = 5f3724b27c345ed5d1757e9e
+CT = 2d0581c040f4e2bb74423682113b818c
+AAD = 20fe2aa2641db7318aa5e339b1e303f952b05dc8
+Tag = f090c0cba2151af2e78ef407720233db
+FAIL
+
+Count = 1
+Key = d9529840200e1c17725ab52c9c927637
+IV = 6e9a639d4aecc25530a8ad75
+CT = 6c779895e78179783c51ade1926436b9
+AAD = 472a6f4e7771ca391e42065030db3ff418f3b636
+Tag = 4522bfdef4a635a38db5784b27d43661
+PT = 8ae823895ee4e7f08bc8bad04d63c220
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = a3020781d65fdc52ec13e8b38b5a9b37
+IV = 0c2879b8eaf5eef2a7700b96
+CT = 7f09589798ef2d198bc2f1fb7ab7609b
+AAD = 5dd3790c90b2632a6dd17b38082e5af15a4f8dc1
+Tag = 255a58f831e20812216e6ed2
+PT = 122da596d16a1a712ce69b7daf2db61a
+
+Count = 1
+Key = a0b4ba9f4b25d88b6d0b8e91beb686c2
+IV = 2c43f69a965f3ec1ad8df71b
+CT = 7ae02928e1aa2ff5af40309a910dd71c
+AAD = 668fc634fbfb6c217472020b90f9ff461eee9cb7
+Tag = 705568949e8df86420bdd22e
+FAIL
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 387218b246c1a8257748b56980e50c94
+IV = dd7e014198672be39f95b69d
+CT = cdba9e73eaf3d38eceb2b04a8d
+AAD =
+Tag = ecf90f4a47c9c626d6fb2c765d201556
+PT = 48f5b426baca03064554cc2b30
+
+Count = 1
+Key = 294de463721e359863887c820524b3d4
+IV = 3338b35c9d57a5d28190e8c9
+CT = 2f46634e74b8e4c89812ac83b9
+AAD =
+Tag = dabd506764e68b82a7e720aa18da0abe
+PT = 46a2e55c8e264df211bd112685
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 033ba96828eebb768454d2d225b7fac1
+IV = 8383c62761a3e886e5fcaa66
+CT = 6945831a7b5d69fc15b426ee47
+AAD =
+Tag = 79d53fc98ab158957ee4b8f1
+PT = d44a350ff32bd4107541dba3bb
+
+Count = 1
+Key = 1b35e62ce6ff1483824a0c24364a649c
+IV = f945d4dc672cff48fa5ac9d2
+CT = 2e5d8fa49b501c95b405dcb5cb
+AAD =
+Tag = fd6dac7b4840bcd955507ded
+PT = d9e0a171da3fab6fd2182790ca
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 3eeaa3b5aa99f6902d1d58421b53ddb1
+IV = 71240c996af69d590ccc8e8d
+CT = 9a50a33a9438f485e7c89caba7
+AAD = b1176b9e28794cb627c5cb3743846e6d11339ce6d0ce69789833b9f344e92e5360a0eb61b173687f74eae3184ef641f1c42c5b180014ca7e6b0edb00fbc35f2efa7aac7111dd8ec70e851a3ef2e2436ee07e4fba213425b1a8e4
+Tag = e2865b861f8d5e0af25757905dd0653d
+FAIL
+
+Count = 1
+Key = 9dbb962de535a9e77108cd049dea0481
+IV = 72d607c6dbc4fbbfeacb042a
+CT = 3c8ebab6a3c4ecdb1ed807c962
+AAD = 9127cb0deed0e5b43ea153b1c17b484225a49c13a5f5995f86ef28a65f9f82397dffb34d4191c3db60492473d5df839e234a537b5a1cce9dcba1b1d205c92c4b4daea01186737cef6d42829ef07f0b6b2920baf998f6ad0d384c
+Tag = 9f8dc7e66cea95d7915281301913d3d5
+FAIL
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 4f64f175ff74efbdf887a53d8d125896
+IV = d7e20930f58d330c305b345f
+CT = 945b94e983082adf44eaa43d15
+AAD = 2f3da0238114f702872505d8e124190ebd0fba662ac3336bfac5611828426ed4f3fcaedf71a2707822cb197d4fbcd07f5dee436e9bc7a4e39a3975b782fe828b0df4ecb8c2971747cc666f00a277600d6b54d4194f17d2183afe
+Tag = 50eaeb33e26053695397380f
+PT = 9dd4c24c799e62db4481f1d2d3
+
+Count = 1
+Key = 5bff7a77a6e200ceadc19defa7216023
+IV = 25a85521c14cd2e6c437279b
+CT = 596de174a18b9345f2167caabe
+AAD = d7664828e9adbdfa5d96fa31b214c8574fda239538531c85f74573dd9f8665f7fc678b825b3e9c35d34edc4eaa43ddd01f18581f43487568de65e199f9b35767f6766bfb359add68b8010d4c7e52559c558d87fad6b1a987df03
+Tag = c4f0f7491c5f0645a4985ace
+FAIL
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = f3e60720c7eff3af96a0e7b2a359c322
+IV = 8c9cb6af794f8c0fc4c8c06e
+CT = 73e308d968ead96cefc9337dea6952ac3afbe39d7d14d063b9f59ab89c3f6acc
+AAD = 5d15b60acc008f9308731ea0a3098644866fa862
+Tag = 658e311f9c9816dbf2567f811e905ab8
+PT = 7e299a25404311ee29eee9349f1e7f876dca42ba81f44295bb9b3a152a27a2af
+
+Count = 1
+Key = 4ea997187ee51b478f5e1ba48b57f0f8
+IV = bb6fed9776ed61ca321ecdad
+CT = d4d67723dc367cb453c5b8ede795ad2b7affcf9f42650c0ea1df91e23175a7cd
+AAD = abeeb5850efb796979bb55a1d255350d9faae4d8
+Tag = def8ab2eda15fe03abee6b2dc9f6e805
+PT = 87e9f743a7bdf04a2d97c4a6c5d243666bfb2bc80c9610bdb079792a3f724e04
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 2f180d97a4c471b4bdf0ea37651b6363
+IV = e76d1c1a2f0cac6dda3209c6
+CT = 7309f33afaffd896b44ee011434bc4fcaa732e3e0b54d11117ef8c008fab4491
+AAD = b1298aec2531450b6389e7d33d1c63e7e71097a9
+Tag = 148b6b1c62bd95144a9d589e
+PT = 8870797cad1aad60dc637b5dd1767ee50bfecc6aa6d2a495d8213f24e9b40970
+
+Count = 1
+Key = 52c00432fa454c4fbf2c9c9aae25cdff
+IV = 3a7090399b39c4e146f5ddcb
+CT = c4ffe026586bdd0a3726964f3d515ef76dafdbc9892aa15a9232a520aece014c
+AAD = 33723750df42614e72d495f468ed8ea8fc4d18a9
+Tag = fccd8b9fa0db8da5ea15e411
+FAIL
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = f3c4c058c7f0965a0328f0f011a128e0
+IV = e96098c39d9aa83522119355
+CT = b42c25155820564b41c525c6aa8ff4363c7c511917772b9bcd574b0be1f6b4ca2153869ddf0c4f76dfad3aef0a76ce056582f9
+AAD =
+Tag = 44331e39b8a66a81591ed155d7d32372
+FAIL
+
+Count = 1
+Key = 93ae114052b7985d409a39a40df8c7ee
+IV = 8ad733a4a9b8330690238c42
+CT = bbb5b672a479afca2b11adb0a4c762b698dd565908fee1d101f6a01d63332c91b85d7f03ac48a477897d512b4572f9042cb7ea
+AAD =
+Tag = 4d78bdcb1366fcba02fdccee57e1ff44
+PT = 3f3bb0644eac878b97d990d257f5b36e1793490dbc13fea4efe9822cebba7444cce4dee5a7f5dfdf285f96785792812200c279
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 6e32be23764748c31d22c03ef4e83636
+IV = db0182c451ce6aa166a58cdb
+CT = ed0aba935e577300cfa7c3ba0b63542a1b3da7360cd1dee2cb3ded6524a1d879485d828a88eaf79db824489e796c8c4f9c12d2
+AAD =
+Tag = 103aad7626a2cb3ac74a80b0
+PT = 39851eab7ad6d708459bf0a1934f647b1fc3e1ee087316c51c3a8b808a95d7520104b2e842b85e197023109542ebdb8209e0ef
+
+Count = 1
+Key = 1023ab3b22d4dae2da53186595ab7faa
+IV = 210d0bf6d788ef1e39a5ab48
+CT = 491b76db8ac7da576f46d8ae749c0a4a5ecfda5e491b98e900f2de624c1cbf6510051731af973cabcab477af2cb63dd131139c
+AAD =
+Tag = 15700bb55610cd6ec67ce3ee
+PT = c050fa3ef997d89ae4db7c4432c8d4bcab1d46e614fb708ed876bd11afd89e7d975d9a5e5647286b56065dc4d508d003604565
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = da2bb7d581493d692380c77105590201
+IV = 44aa3e7856ca279d2eb020c6
+CT = 9290d430c9e89c37f0446dbd620c9a6b34b1274aeb6f911f75867efcf95b6feda69f1af4ee16c761b3c9aeac3da03aa9889c88
+AAD = 4cd171b23bddb3a53cdf959d5c1710b481eb3785a90eb20a2345ee00d0bb7868c367ab12e6f4dd1dee72af4eee1d197777d1d6499cc541f34edbf45cda6ef90b3c024f9272d72ec1909fb8fba7db88a4d6f7d3d925980f9f9f72
+Tag = 9e3ac938d3eb0cadd6f5c9e35d22ba38
+PT = 9bbf4c1a2742f6ac80cb4e8a052e4a8f4f07c43602361355b717381edf9fabd4cb7e3ad65dbd1378b196ac270588dd0621f642
+
+Count = 1
+Key = d74e4958717a9d5c0e235b76a926cae8
+IV = 0b7471141e0c70b1995fd7b1
+CT = e701c57d2330bf066f9ff8cf3ca4343cafe4894651cd199bdaaa681ba486b4a65c5a22b0f1420be29ea547d42c713bc6af66aa
+AAD = 4a42b7aae8c245c6f1598a395316e4b8484dbd6e64648d5e302021b1d3fa0a38f46e22bd9c8080b863dc0016482538a8562a4bd0ba84edbe2697c76fd039527ac179ec5506cf34a6039312774cedebf4961f3978b14a26509f96
+Tag = e192c23cb036f0b31592989119eed55d
+PT = 840d9fb95e32559fb3602e48590280a172ca36d9b49ab69510f5bd552bfab7a306f85ff0a34bc305b88b804c60b90add594a17
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = f92632dd22b3300fbb498b5a6d62f86f
+IV = b51ce06f5ea5fc4b6f048899
+CT = 983713a7252e8bd37b06d489d33ddf1c323bac20f09a1e6459346a70a335d4d0e4833d62830ac0fb75e3ef459cea4f875855d6
+AAD = f3eb475f763b4e2de876fe8ef5c59387c28a6660533e575e8e32bdc363e8b9af8fc6c2daf067088031292d360f96755eb7b10cc6f37f0f97b03c4c05f20998592c6dde06e2b8d10996194fc882b235fd0c0d9840d060eb8af3f4
+Tag = 272eeb52b7e04803d954f493
+FAIL
+
+Count = 1
+Key = cd69b998a36aeba7feef6ac7d2c7c996
+IV = bd03275e41ebf178733ad44f
+CT = 2ac4239ca0be41e7b3d7678ec62624d29109c70128df0023a86993c961c39df24959ea1d55ee809fb097d324554560fc709885
+AAD = 8cf2e3102e6ecded3ee7dcf543ce7141930730d8b3017087e495b02d7f975aa11ed63ceb3a12c52793bae36bd0df3302ff1a431ee10a88963e2e621ee56e74bed0f9e0ec69351743340b76bf9cea0e6164c95f2447c3baef5a9b
+Tag = e5bf3fe77e916de794b037e0
+PT = 24411afa3527fe12543939a099c6cd7c906ccd81547d57581491a8d05ea6b3bd9fe4fd21b19c2bef2c6db6f1c49ff715e79b39
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 0]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 408f5edd36d7684ad7b5909ac3c04de0
+IV = 8b
+CT =
+AAD = 48a4bb10a14255792c5edb39bdb056f4333b3cd1
+Tag = 5c34609612faca9ec1e60852f1bd7bb1
+FAIL
+
+Count = 1
+Key = 4015eb0551b8430139997bf0ec21449e
+IV = de
+CT =
+AAD = d1c4c57dce37a40dbef0e79db870e3c063eeed6a
+Tag = 23b3df54453afaeb9659e1ff7b3f7810
+PT =
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 0]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 42168f5168e4164493227ac0ee9342c8
+IV = 12
+CT =
+AAD = 3bbb688e5014d822a9e930c8f1194073d99b1164
+Tag = 7ba600b43586bdaffe21f9ec
+PT =
+
+Count = 1
+Key = 7a1bb047557818fc36bd0c16ad0a301b
+IV = 38
+CT =
+AAD = 5ac690c013fa47f1f145d0af35dcb59c818c57d4
+Tag = 4a045119cbfb4d290273539b
+PT =
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 475ad3a0ae4b9f5b475eede95cadc9a6
+IV = f1
+CT = 1f9e03adc858959ab2259e3f44d88d58
+AAD =
+Tag = 3aa732fb202126c5f5ad56bf8bc59d38
+FAIL
+
+Count = 1
+Key = ef5185a3840e78fc0bfb258b49a1f69f
+IV = 82
+CT = 8f9763c61d758247deaa20c735fba84c
+AAD =
+Tag = ab393cbf298503dc093e8936a41a5dff
+FAIL
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = d57564e8ffbee63c7aac30d4d68622cf
+IV = c9
+CT = 6f10924b9e76dbabeea8a140df7928a6
+AAD =
+Tag = 2c1e95d96b653d28f8c762a3
+PT = 0a5015494ee77fb565e09fc1c8207803
+
+Count = 1
+Key = a630a0b8ef16257689f3e0e56320ddd7
+IV = a3
+CT = e7cf55c9768e621e4fa2b87c5dc42b6d
+AAD =
+Tag = b8ba771ff17da4bc1fe60490
+FAIL
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 6b069c72fa5ab9f5f866e7a7b5d5069f
+IV = e9
+CT = 9561fdf67f3a160cd870d23674e86b0f
+AAD = 2be3fcc3f5a6659a6388826c4c904865a27e5d6b10f9f49bb9062c7a61d3a93f7367d1d04c1b9fd2d40d470e30c269d1e1ab81e9968862025eb8de0fc77d69d0f12ff4be23bad2d65943b500f19f02d97cff6c52d43c8c74f138
+Tag = b1874feae9a5fd3eb53d4e78007d6a45
+FAIL
+
+Count = 1
+Key = af18b65a1fd2a785903396aa7aa1b379
+IV = 17
+CT = a59baff3abc5871c1404f97d3fd35d72
+AAD = 4083e67ad2154adeec549bc4a105295d3656c528b6701e634b209a9decd09a2311cf6d275be52fee85aa38a4b2d524042c08d6e93e8479ad59226cbf7c7b72ad95ce1857af7c76cdbfd76f2426faddcd289fee76677c0494007d
+Tag = 8bf65e804ef240abb2c9e7238efcebe0
+PT = e506442671808c472bdf628be14b8500
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 0ea24ef6f8afde2eeb30cb2fd3e0aeda
+IV = ee
+CT = ee3eb76c7f3694c9ba61fdada617b552
+AAD = 1b6471d408c220195e910a7abc3546e24c59b3647f4d6fab3969cfb370efc071c12aaa17fbca500c5b0fb125962bf118fac1eb4607d6a0052511e67976cc4c42f90f6530bd5bb382afc3bd1ebb8ceb7d30b64cf073d53f813762
+Tag = f601230f3320eb38b7efb534
+PT = e1cc925abc55b8683a24f52a8dcee6b6
+
+Count = 1
+Key = 76436c607e69d0edaec22653872157a3
+IV = ea
+CT = 28b3f779d552bad3bb415865e06b1565
+AAD = db1f000d7bd44ac4757ea58b2e11828a000906e0449639d5472efbe82f278481121dfc3c7cc148f7bd9f9fb328f82ec8f274a698eb8076a2b1bcb9f04f3dead219bd5b1455cf1e656749531ca7f71cf8185508889353b5a49b4d
+Tag = a815e11c0673cfc367ff5c79
+PT = 0b1a482dde1f887d579f4d1ba8152c77
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 104]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = c90352c76b2d866fce51d209e441123f
+IV = 69
+CT = 99f01fb7f3f26dc2bfb838d715
+AAD = 2dd35bf7263390a86eddc0b1e693833bf49e835b
+Tag = cc67d27f63b7e9f8aa86122a5b6a6b17
+PT = c52a881d4467b44da233a76813
+
+Count = 1
+Key = 593302c520bf71263cd8c14b288c4e9a
+IV = 9a
+CT = 7339082a97c2c9793e0a9a1d3e
+AAD = b8dae0f244b799ce231310d4b2e3d07117cefc30
+Tag = 558ac93567be75df6f44de10e1bc48fe
+FAIL
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 104]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = ea5d372c66bbc0aaed9633f600a133b0
+IV = cb
+CT = e1fb6161c43145f6f91158648a
+AAD = 4a962b3a4e60c72406f14bf7ef4b26b605571892
+Tag = 5d270484ffa7e06431d0048b
+FAIL
+
+Count = 1
+Key = a9b206e48114b6aba83f267dc8b12270
+IV = 99
+CT = 49263c0674ccfbc9aa8294a44f
+AAD = 076104c07d9d62513c13479c3e44464376c1671e
+Tag = 3093c0135142273f7352f370
+FAIL
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 591e1b505e38fdd64e7019b049222ee8
+IV = bc
+CT = f5bdb5aed557e17be48a7afa3f64e35eb10dd08b88e01bc1d6036fbf08965452
+AAD =
+Tag = 9027f3d3e90745c7ca3ae16211b176d1
+PT = 2093f75ec698204f94a571bd938629dd6b053b69fe89999750127dbb00edde33
+
+Count = 1
+Key = e8d2960b4db3ae1df79198de63b943fd
+IV = b0
+CT = a76f5160fd1e716455fec00901e80296e55a0fef8367baf0b59455279078e687
+AAD =
+Tag = 7603dc3a1eba1f5d7e748b9b28ec16c3
+FAIL
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 64fc6bcb2736a15bcda0b059d553f855
+IV = 16
+CT = 403a56c954ca4e58dc9f402e2698dc66aeaa04368c1c3943bbd41e542a3be9be
+AAD =
+Tag = 1027ea2730243a8fca26e605
+FAIL
+
+Count = 1
+Key = 18ad3c1b96c66d3775a5f0cf2e51e7ed
+IV = c5
+CT = c1aa8059c3eeb71cbdba4570855440b68c95cfcc7327ece4d56a6422fb864089
+AAD =
+Tag = 6cfc1adbfd4dfd9bca0543da
+FAIL
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 200062755f9375072c72d3f4f36548e5
+IV = 94
+CT = 3ca7d9b392ea99073151e87527eaf439be824db5c1c9cc9c8394e7fd5d93648c
+AAD = bba497a9a4b74fcc9bc84b8effc5f5ff452f7777c21c2dece9fce2c5da1730821bdeeadee066ab4d474bcfb66a4c1f14c99a574a1023544ef1f85667f14487d2b2af82baefa81c9f3647c44e0279f7878b1ce68edba3d7bcd5c9
+Tag = 2620a07160e8eb486d63e389d371235e
+PT = 596b0b9f877201ba6d37cc001e4105e357a5cb9c41dc9adf2686c4c2cbcfa1c4
+
+Count = 1
+Key = ea00ab0c01c9f8930fd1dd09fe639d15
+IV = 54
+CT = 5f637603bf4f5d612d21cc3a79fea4faaef5b392f5669a6bea923df7c03fbe14
+AAD = 21e988c607bbc9ae3b797f1fcdc1c4476854bf4eb36ba2f4fd411148e0318fcb570ef66d780288fed1b19a88790c4cf07d21e33c129be5861d9e4eb668143df3410cb3a9197604ca82890abb00bb4d91a39bac9a62bd0d0d98cd
+Tag = fab0836fb5402c9cb2651ee8acd3c265
+PT = 8662a9ea34cfb3372b73aa0bf072b2eb03dcc5de82f71713499fb3dc3f867eca
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 1fd614d59bf7ccf46f07f1e229779977
+IV = 51
+CT = ff2c59d1494d476cb3188d8b9e0bee2bfd6fe6cfaac15961ed47180877a67b05
+AAD = 329cfef1a6a58e6f769ab1a8bcc7a42307b1f60c4da380b027ca7723772ebd13e2ee7c4a757ae5bf0af84af8083fe8429a7adf14ad8fa2e2e144c0a70d872de4dd1fa6f2ce5605a816436bd2b7c2bfd2be6882d1a20e957b84a5
+Tag = be8f454fe84cc88963d09aba
+PT = f79aa0dda8eebb70fb7cc4a31f830535896a3889062cd5b473603502a7583056
+
+Count = 1
+Key = 5949c2a5cf3343a29f30ad6de7483b46
+IV = a9
+CT = b2103bd5f226a71af62033a4b613aed0cd44de17c7de9e0ed054745e8f993c91
+AAD = 7a6fbc13757e8a1f07a34a502838d3b368c66d1b068a303a54c7703314e83b4a096e79e0223db29c9339c95d820dc20d2880a938e357ec3ddcc42f547db54140f17376431ff72dcbdf3460ae93bb3661db1b9c90040588c1d64a
+Tag = 0c3c301b99d2275d5e2c178d
+PT = a7c76fe049598a6ac49d11f1fba44cb05acaf79831161514c4f85ce59c46d611
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 408]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = b13f7e2d59a9ef4c77f5582efe936dc1
+IV = 8e
+CT = 8ba6bf238db4f90f9437691d78eb713410b0413908560fc8960c8b0f4d32423f8ba4d349e0f24566892a19df8f1ff6823584a9
+AAD = b1c8f38fb4f7546c213dc3d3502a8d7682ecd1a8
+Tag = 5f9257e938c9fb2137c1a15ada4822da
+FAIL
+
+Count = 1
+Key = d1c691eb3f0a5f302002d19bca6c5752
+IV = 2a
+CT = d2097c5443d0d31a1a8b1f71c2eaa590aaf6a20f9b8f7a09b270e0a2169804d30a936c3c2f25d3bef801e5357f00321547a405
+AAD = aabf99e8b334609c72f6c58f4a51cae13d48be45
+Tag = 99d7b28a928596769fe792d949a6e45f
+FAIL
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 408]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = e282bf130aa9d88b486f40c5d7d6b753
+IV = 1c
+CT = a14557e6ac2793fce4c76be30787085ec711162133fdd58a13bc7f718d8294db54c5833e883eff9e510cc3949f2c37da87f35d
+AAD = 44188b2f9726498f7a5059f30f6005fbd78f511a
+Tag = 1821c2dbaaf94a7d9480f8e3
+PT = 2d563231997a3d395a4468b7d1f0244bb4343e5070b3657a3be7f16c49874e0cc3975c6cec7b74df5d17576aeeb877a5551038
+
+Count = 1
+Key = d90e672f6b074262bff40acbe9e9bbf3
+IV = 0b
+CT = e230d1ec1ab2ae6f95d84b9bd773738b4e130a01211d50e5d85bc7914d78f3f15512822d06f4b6e173a18f34f957b9f73a6e24
+AAD = 9b425a15d2f69a0877a49c500878a7ff1f76ef0a
+Tag = ac05cd716ba5caf7e3619fae
+FAIL
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 2698eba4fb3a0f82434707b357f6f101
+IV = 19557bdaed00a43b536340d1bf9fb8a47522a2bc4bc53b008c9cfc570fcca3d8282292c5b55c4a2ccb94058aa3685dca772fee74b6236b733cacb0772717ea07002a6a50ed6ad17678f8ff00fb172e14a717af278211f55345e49eb68b12175d4ad1ba74e44bc06272f14a27ae1b1f89fa8bfd4851a90250c762fc0343f87494
+CT =
+AAD =
+Tag = abd6606a82f5ac876caab5150007aa49
+FAIL
+
+Count = 1
+Key = 86ca97ede9ab63b934f4b20896c22d74
+IV = 0fd1e4e0cf2724cda5242094826bd699d8ac2e58d39cef5cf0fa894ea45e0c95336b622f8a2eb4969c0564f2aede2eb1a5ffca9f7b0dd6bccec1770bd6c845d88e2a4143a73cf71ca7dcac4e4cd76f1c4ddc35ed0037a96b0d567d32dbe8805ad6fd3344e7fc9384e1a5d1eacbc8914f39179aff2170b0ca2d384a3e731f55be
+CT =
+AAD =
+Tag = a3e579d3a8f1d6eeb7854f55207ff863
+FAIL
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = b04804854da168cb2a9ee94c76b8d91c
+IV = 45a3d8c773235c001fadaaddfb9092984d745656dcc51b3e1898835c852e41e9fb371c74cb8eef5e6c4a6969c8bcf078f44caebce301cb16f08a1d14f2970aabaf78fa7c69bd3644147e17390d6f4f46a15ca6f85a436655a531aba19d30c4f08a16168f6dcf78d8526cfcb9df83082131f0b47ee582b8809260e7345dc90e72
+CT =
+AAD =
+Tag = 4e7442d97e58a2c9feb3dd19
+FAIL
+
+Count = 1
+Key = d9b009bf1a80b138d4a6c414faa645fc
+IV = 7e251808785b8c70dc2fa99339a8f082949a4f89ed8e941a177fe861ffba2d3b061cd8da8ed258c60db57f993f8353af3aa8489f5f61b88b72df5c8aae0f467fa0d431948248b5988fcf6c7e03a9f7db88fb13fa641972940d2f65270b5d0c405d0963e7009791ff0fd6fbe9547f00c12313cdf3dc18e6438644d63612953820
+CT =
+AAD =
+Tag = 415298a59afb0f719d8d7928
+FAIL
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 751bdbf1e0d207963ab8b786e02d19cf
+IV = 26a7c80ad370ff7a851526c7924f7c1b03d165be182cd17c5a8c779b134d9974b82b95df3c54377cb11015a16940d52fa741aec80236302f22aade01f0913cfba2fc5c0ef19099e3f01a590dee02e797b01e90a6d9f906caac020148d2013f61cbe16ed049778a44ca343dbc188b0a57482fd070008bb825a8b9d66979a8ead5
+CT =
+AAD = 9f79b7cb90a13607f6b42c5d2a427fb1d6e14fe707ec9d6c5eb8efeb8a970bbe6bd4a0be70f6c17b9821d8c275fd4259843d1f6b23df0bbaf4b03f75e72d6326a81d4459e7ae97271fb5478944e2d507fb85f7006195d29ec03d
+Tag = ad4467d419b918756b940dcecf4570fe
+FAIL
+
+Count = 1
+Key = 65eae4340e30a5799e047cca4b490336
+IV = 8710f6e261af606afca727cf60cc3a9c55ac82329ff63427303c9a72b731b1bacfc05819b8ab905c56779065fb46f95943f1f09deb7aea30d18d663bbd79f67bf9964eee1c264dbfb97cd80da9169f04efbc60814d87eba3ca637d7658f12aeabd6ce8acbf36fb8eb4a13859051b7613a2672c3ba8ff486b90cedc86f2df73a9
+CT =
+AAD = ff932fc948dd72b49bec6e539700dde1e600b2c256bdd714f0c26e9ec51456676297f828e31f75991ae174860e8ab33a082299272fd666458f4ef451594e1b9c1e4063bb0e3278eee09562621b425d4253dc207b766e71fac188
+Tag = 82ccd60156286c311bf97e7dcd5ed978
+FAIL
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 4d869dbd8ad8fe130df1612ce5524ca9
+IV = 57f728b1ba040c5bdb7dd191edbb4f7a678d86bce95ff4d2c424a818d1617a9a087cec3ace22d070748cb09bd3e13215608359f4bf90b27c3fceb1501ca78314c3138d05a10f3fda8fb7ebbe8968e6d59893c840b81f72241847f5b9ef0c97a52d0f5fe90374f043a28e6e33b1fb40775691ada7f1667daada1390b36a55878f
+CT =
+AAD = 614cb9e1f6a526c97ddd750d8c665739cfd88bc59a087f28dda230c2c0f6e8bf4ed17ed0f387bd0514803f225f1fb52c4dffd69c4492b0eac301318885954a93d9dd3bbc7f6ad46b467d84083ffcb9a19c6bc82145f7e5a42509
+Tag = 757976e87ace9c58904fb50c
+PT =
+
+Count = 1
+Key = 28bbbeaf17a174ed68273507fa459097
+IV = 249b6d805e8cf2c1f83f47d14b8e53673c6977f0a0fd8b4a8611f034aa1dcb634600116253d1eb9581050faa64339799e71e1ae86f04ae667e515c5811179eea6256738bf3c2f370881a805916242e9cf489ca953bee1444fd39030b0f676574763b799e3c67d263e86fa8fa5e6cf016d6e96f4c273ad875905b6241f54098d2
+CT =
+AAD = 6ac473f84d30b521ac5b5837de9c8ce63fb90a6db62c72ca21481311b652bb7b85a435b16b9cd4c9a4a51cd2c76f00e5f12da9c3f2912a013d9d20d73742be65f76c4ccfb3ac6394cc2d99bd2a8cac7d328126cf3a5d88912842
+Tag = ae7cd481cd4b1220cba198fd
+PT =
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = a52d0b98373071bdd795131cb584012f
+IV = ffdfa77372d73f75ec83529abe544cf48c4a98120d0f1cf913fdd3b7f628f85a16c30c3400486aa3a0ec0709b07f837cd747bc8d320fde5a0cac23d7ad53ddf849b23202e61f982ced39f523e1f11c9bcf7d783202e8ed7522dca4b1bcff78abe73d7de80314cf5f531a9b114eebbee27fc473157231b51d34f2dc6a5975e745
+CT = 4702702a0c03e798b29cbd89d6389106
+AAD = 69e3ccaef1a3325d55079614de99d66edf373a55
+Tag = 097d479b92824d417d01640289465a32
+FAIL
+
+Count = 1
+Key = 4a263926fb8898b707eb29f0822817d8
+IV = 5e26bca7e93566089e52e562ab87bfaa6b614a9750726e3d260f6ba7dfc96cf3d5f28d39395cd197eef76d0d87d6e9e976050562c55d6c20d147a447d52285b5fa2a6a240814a2f3cc7d3be451540493ee8c1addb827953ccbf9d6a3378ece3a6eff69362e1a5d2fe9f7b7f6a0ebe10b767a042e0d67eb7c3dbbf6aa941a182a
+CT = 2a8cfc4f58fe5b3dea3f3119eeaaa7e9
+AAD = c70148fa3c7219532fc07799e06927f08bc1d2f7
+Tag = 9b4f038cff3f70908f7f265a8c66e5ad
+FAIL
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 52c2b29fc9b47007c511f3b9fd814614
+IV = 811954546d570ff79051e04722addd135685960cc55b6a03c8a17d21c4fd40be3c3ff2e571f1aea4543d7a052c9c67ff18b0ff9aac7d8819c337c0e06a6104ae59d8b226af33f025fc97bf12c5f84f2a6c169caf75f5e736798ab664c0f589c0827d6a591bb2bafdad90410fdc12de401db764fe851eae5dc913918049d9e225
+CT = fe181ade5c03a94ff1999c9b1e915747
+AAD = 22e4875cdab4e47e46ceab73fe04294127f97743
+Tag = 6a7b1a3b508e66ddc65f110c
+FAIL
+
+Count = 1
+Key = 9a786ff733a8cd324162592e397cb64d
+IV = 73a3fffe30f961ee553ab6fbadef4cb6d71c34f61081fce314cb66685133c46effc9e3c665ae16192792ba689771dd55359c3aefa0c1a947e0a7abaadcbf7422b1a9c541d868bc62246d49ec780cbac23fe22d554092bc881b9baea21f266943a19c5b8b597a4dc52cb34839f1bfcc6d88ac94c3085ce4364f85d49ab9e75c31
+CT = 85b35b99ddd3b669c39cffeb112f1185
+AAD = b107672c794233e9ebe6866388201381b769ed82
+Tag = 530458769b8570a1848f9a31
+FAIL
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = de7b6af1a2d0a92f8f5bed0ed2a4c3a5
+IV = 7c648aa92cbe2467abc4aa77d9936cdc720b3ed607d88244adf2a96abcee5d925050355656115e7fae5ef64a5f3a70cbd103853b5b9a93223ecc947bfab2b3b33f0bcebfc1cac46f3ea4b87f1344171ab276feb5ab5cff7d3af059b11d0ddda90fa6e45300b46d702d6a2bc4994d87f013052059210565e87194daf86b0c1ff3
+CT = fecd59b042fe86d2069efc2531
+AAD =
+Tag = b5e8a287aaa1545ef43cf5d1f6b8e8b2
+PT = 6b392c43cfb074ff6cbb92ef96
+
+Count = 1
+Key = f1bd519342c172af750d3f0922165bcb
+IV = d3ed68092b3cda7f4eaad71941b309cccca11fc42041f52eda959512e3fe0b7094d99e3f7ca4a675491d38f2b1c4f28c2f789d6bff3481d68a365159486e822384321a45e026c2a1bfecd0b8852f1895e09a213ee63ea5032ee22830d78ba990cbc60450435fcd97b501377d702f90d470ec566c883c2c979f815fc8da237cef
+CT = be5375072610b9999293113564
+AAD =
+Tag = 52df8b8c7e5db92b3d7875b97b6a7cdc
+PT = 660982e7b79a100df1066f1560
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 546a49f3da4d0895ec41b8cb5a7ae115
+IV = 721bb8cce428ecf78e50db3f3152388a6df6210fa1723693d526e4ddd5dcf0f7f478f63729b02414a4e58778e97306083f4d01bfd564f2b2ec9b3f30cc1d51d079c6c08f6cf3c045c406c02d75863bbc1458286fedb40088e30601cc5f68871e5265359752fb23d817d53e109abbf6db00226c833a7921efd719a783cc89f989
+CT = 4aa1bb6e198c3b5a6a7992febf
+AAD =
+Tag = 2fdb588edd95b285abb5a775
+PT = b326079a44d686343aa8abdf63
+
+Count = 1
+Key = 3ebd80d5c8b464424b90f587c42976d1
+IV = 5741462741f113fc99a3dadfed99578396102587128cdce9ed676781864d5b169dae6916c0fce5b13e7879e96b2538045d8b7471d96da1e12c880c5c6e25a2622f06c1faa983ae80446957ac2f4748565b7c88a6403d96f0e3186a53840cd2e237eeef8bcdddcad7eba02fd85c60f8fa1798c61a93537e022ab4bc2ca484ffd5
+CT = f6ba47edcc745d861464d589dc
+AAD =
+Tag = 9d125cbdc491e497e06ca706
+FAIL
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = ed1022a97541386191d7f497fc028afe
+IV = ee42968bb03b625b46ea4519a0c793dce51f30f1f843b17dbf910c3bd5ac3935e18515e7c162ff5a7eda471469038bbe4ae597b5ac4e09dae2ad98b92b827ff2511427a38a1cf1ebe388bbd7ca9dd85c15fb464ae1d49babb1eb6577ed4210a77b37ba9a87d883721505222a37b0edd4c6f9a519da58becea04426dfb4ffd9de
+CT = dc51cec91f803f73655c23e2b7
+AAD = 2fdff5599ff34063d25610098df45a8d69fcba22deabc28085355a4fa420ec2702daead93e3b8fcbad5867f8287973cef3e4a323968302021182b5e3fe5d77413e2e36202477a62f9a7e64e78beaeaef8e575511d5b25e409aeb
+Tag = 502a4d8cdad446e96d7e5b4b04ac5bb7
+PT = d2720de7f3cc84f02e241b4e2d
+
+Count = 1
+Key = b4fb230481ade2a486061c93edc8e59b
+IV = 68bd51d2808567936d7d7947390e12b607b3ed4d2500da4b34c76a087d07a00de7292fe01f7a4472e2813d41fe2aa5db22a4197c7826bdf1f524ecb22163f58e45023b1a83c7bb70f57d83bf0475a65a3f64bd65662a0b0bbabe649153746a5581970f3e6426bc794fbcdb89db594f3e67356136b3a18309ca3137951da56fee
+CT = 26f7b519bd175f41bdbb78b3cb
+AAD = 479a584aad752e7755f7df00476ca202f97cabf79244229a916fa3438c7d4e1a57adccd6ef909f5b60b1a54e979ed367296b056dc90d680d2b2adc90709e3da858afe0417765b51a132e85f53c78e5708cdcb8fd8f5e1d318df3
+Tag = afe604d281b86dcee49d6efc9ed1207f
+FAIL
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 561e3bf46c3165a919f1505d229b3cd0
+IV = a767f94c56efae306bd1bd14f05f21963b7a643bd0cba88380d11f725e4e0ca45f1cf5e7ba710ac3bc1b8ba2d982d9007056f9ff59e0445148ce6c7e199a7996433f7c9758bde89ef2617f6979c83ef9afa6fa4f6198814f987ea010c9ff3aa792a27acace43e4bfbd3bd056a2aa9e66d95bc1e603bd9347c394384c8d878328
+CT = f89bf03b8c506e4fbf074c7a36
+AAD = 68277db43f4be6a2266ec8e4531c3a58bea4a183a869e4102826f97177756146db10cf36ca7987b1f93e4bed4bf5c794018ffc3b4e417da296c2b86a4da67fdf03998ec96fdfa289164fc56de0a00de3cd6488234f768ccab1b2
+Tag = 939226a74826e064e272071d
+PT = 19d495ff77475b9fa7afbe93fa
+
+Count = 1
+Key = a61139dd7554906d7c57e5ed7dfeb158
+IV = 851e54bc56cd28f64319d8bd643613257e31517481962f5bf021c58672e4255db27b308f5cf273fb2e70c14cf73479d7809089600c9ff3be7a2d81fb1b94908db6413ae58eecc4b399561ddc280117c0a8ec13c2d2fc0f99fe2553dd1cb67616515e60224af353864ef33bda2a63bc2cdce9389bd05bbc996f879866cdad19ac
+CT = b080e9fb5a6858d2e02ad4dc03
+AAD = 9c547e2d0bf65edd3136be3a7435a608c3e0ef64a809e8b2bd22088383f2b830530145b3d984822d18448b471b3a26c2963c008b6de4c6543a841d9ad94d53c6e657d2289823182ffcada496a5f02e831e4d4ea40dff2598ad0a
+Tag = 7156a22a93cd10369008bfc2
+PT = ef59b510a9d348c5cc1ab74114
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = f77c0a52984b31f839c2bdbc2cacbe2f
+IV = fe91dbf9568e8dd4f175762e36b4a28c198d4f2ff59ee7ef2c6a681c5618cf23fee9a5eefd693b54d167ad17f78efd8cf87af63d725b10fe88e71eed77274d999afeb1441585aca35f42e960cacc77a9a0d7fec9b30eb50d7b71d3724306e1b29cb1926b0602b3934908ff322ca0ec12f590999af1646b27c3266362d3ad5d97
+CT = 11f8a917d77eb1d14c14e821dc52afd0b1321eaf70704c24646f457a5b7f4f8e
+AAD = aa4ce8424831b72c15d21d857bae40c9400da2c0
+Tag = 670f962a59e390957cd944a43f287e46
+FAIL
+
+Count = 1
+Key = 9017d2c52253eb635452fcda24bf8e84
+IV = e8b24af11e7c39ecd0f8c5a523acba6f155782b0112fc91479f4dbec74406b7fe2d9eb974cba46be6afe57f53258cb98c44c26bdee22d97b9cc03fc6244f8aa183458f10f8707ca1e7f67c040394773006eef283fee4c6ca325c41f99a2f1fc06fb4b926b296084eb4f129ab197f78a36bb10dc446bff8262f95d9c940f569fa
+CT = 4408458f6df032957c80bbade4aebc11a6dca45652bee57580084913b884735f
+AAD = e5670d66b59cb7a03bbfe9b06674576c3639c876
+Tag = f7106b15615eecc5d436b56c9ef10bf0
+FAIL
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = d11f75f30d5bffc0cb9c2777b8e0a063
+IV = 8621d6e0fab3bd6ae4cb990bc7b6e79c7f3cd0f26540d5fd8ba416bf2a7bf31f6e715493a40635c0bc360a4c34ef3d5bb9fad552244f205b4780a8e9475233813b34611c6c41a26cd519ea89e24b1fa38eaed74e40d5cdc8a8cb37a33163b108f009448bb29325c3231c1fe79464ee74e3ab52bab0e736d38df38984c78cff2f
+CT = 9e96d1122881e720887c1a6b38a36d6c114c1c053c6ae0250c9cbd1b07096e9e
+AAD = b43e16e8da6d8a9532df8dfec1f333c0dcce1df3
+Tag = 8aab945cc54339f5799181e4
+FAIL
+
+Count = 1
+Key = d1f35ffab57b0ec7dbef22facea8ca99
+IV = 722b405af49a318ba3a2af9fed51208cb998d2e571e811e3d68614edf62b584c48434ced5371e67eacde22fa2c605cfc9e9f6d5c1ea903c4ab627ea47e0979f046698224f21e6478ff20dfb4183c2c4e53376fe6131dfbb014b9f49460e9ffbd7326e09d469ef63b216db27911d81ac5519672b3dab52736bef87018698af9b3
+CT = 031a69f6efe747a4b805313abf13e4f0c9094793544df3a078656061740c9a82
+AAD = e01ebb5cfba0fc6ed01618929f1c34851f4b46b0
+Tag = 85afd6bd8ce46c892a2c921c
+FAIL
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 24168b48b45759c8d4f9b061f0cbc16a
+IV = b8e5ede75254cc4542191c7e7b0319ad81651451b639caf81c81c98301a4a0af70e291a4e35b448917be1e400fc64a22edf32913162558c2591ee3e80f397d73dfbc68b82da49bda9bcbb6aaf26919e21c1773cf51f6c5b71784f47978cc0d593b4be0259ab22b0b48de733a884c50a8c148c495973a8f5f84f2e93755666bf5
+CT = be19c7e3d3e63f73d833c967d8d62f388ab9617a2adebe5abd99b5ec64599c46bc28bc62770e08995b0bbf27089e3e17b80424
+AAD =
+Tag = 4aec633d4daed9ce76d697c11f66f34e
+PT = cb7f10bda7da8a2569ed1f3b667127a1e0fb197283aa16ab8cddd43186bd126b118e671cab3e325877fe0e79f1863f89122c8f
+
+Count = 1
+Key = 123e6d0e7a13ef97da011db953ec8675
+IV = e863681a4a672bdfefcd6689f9cab2eddee4d729ada28090a87ab2d9125e65e19cefbed73c7c2b1c81dd44e90a39ea0f17a498f89b50e3b305da66bcc4cb92433953f4e56a07d5cf866d850992fb6bc86af1e24cf292ca815e30272df7db7c64273fcf5be652b627271685a7ce6940e24f80f459132e4abbf1f17232f9b1bd1c
+CT = a76ce6b5feb1173f585117fea7988d51c71bcae1b19d9d083e67db988ac581a3a28db7ffc243719b73796d7c76a3efd75b16c8
+AAD =
+Tag = 96e6f800457221aefb0764635c090c75
+FAIL
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 5d5a6980aba78c4c0197e2420ac58a9a
+IV = b83e10baa5c23984c861bdc60e53dd26c99a63d6c1a19a15fb2de3423f62d2c75577727859982c7d92a19e69f419f3a6247c719818254c7620793366d1b4b38fcbdd7f2546e3f281c5433c89a506eb4f2fabfdacfc801dbfc733ca3d161fd27a3da5a7c84da4e10282b14240266dccb4cfece933521385900bc4778c8a5ccc2e
+CT = 8788b68ed5b601fee7fd6f7ed16b31953ef5a7ec2505282707374ec9de8f9b388e35ad2c6ad987c62dc4ccca5fc134844e2aff
+AAD =
+Tag = 93de86c6c80df02f09b19eeb
+FAIL
+
+Count = 1
+Key = e3a9aab8735f784cdc12d4a41aa7be4f
+IV = 3bb213adc907e2c7a71c6767380ad43a7257273f26c4c9887a2869dcfab5cc8bbd7b39bb2589fefba8afcec16266fa43b38bc4813f95bd613e1e7625b49e8fdb1929fd45cce41cf504a8e66cac81c80c8f1090a2dd09a02218df3756687efc2e594f0c30842ecd645cbb36e6c9a2e0b0414adf0bcfdc6bf7b6a7899b0a544eff
+CT = c0c1ea9364957655a2e555656ba36cb021289221d14ae8b1e65ff2535cae684143093653fc61825b31f4f286af47e8b1adcfd2
+AAD =
+Tag = f516d379dbfc772dab40346e
+PT = feb05b4566a6be307f8373483492da1cc5c5486c08b19f0e34ace45e9bcc00a97f17d357cdcf5faedf53b4167ad4247e04308e
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = e9b0139be8b50b85dab4fc69186c520d
+IV = 047fa684f5e40b795d77aa204eba377ea6150165298252c953f48f010b7735691fcba74e7d9614f5d77741213300790303be2894d936b2a92cd3cc61b0e9d06cac3ef999e0aecad451fb7eb41a4cdcc757fb756fe8846598b699aed8aa067ba01c8d8dae91d4d8414f73ff8311a3e5255facba2f28a2fa2cf3a5340a2f1bd2b7
+CT = b31815639dc0f31436cd86434edb3fb38a831a5defc961279f3a423ab88908cced42c7e7231f79eafaadd8602aa6ba262dd645
+AAD = 7307226192d65dd58d17a000dfe6ed31a3c3463d444799e85569e6d0a8375f739e279c1f3e138a2eec64808a4beaa8e4cf6757a4091f34b6619fb4220c6d95770a21bb46ad9a32799453d36012b293d96ccb990fecff7bf5d326
+Tag = 4912ca9aa5b64c28918a4873eafc4925
+FAIL
+
+Count = 1
+Key = bc4c6e73acaad3efa1ee296fd11bacf5
+IV = 451d09540aee27418bf5c5e50c09c4fa4175ba73c51381ba70bc9ef4bae6571d6d5a73dfb348449192f7e470adbe11967164aa9d786e241852d90867ad38dac02e314046d57846ac3d1eba25d9f2c15a6640b942a8eedb135241c96e05851709feace5432494c6da5b79346ca3ebf0daf7b1a3d7555722add362447538d2a708
+CT = f16ca460f87fd066482f08b5e97e6aaba3b26bc0f105c5e1fe7fe2eb6709fb4f2b435a3a3c7e8f8e9546c1150f0c517ef47e90
+AAD = 943c196e89253832d90531aaafb7f14bf79332b8b1537d98e7bec893c75f21707994d0289265132228d88c9ef4be167e2ede50b6761c793ba10ddafc736c3c9ca82c3e3d02b3bcf04fdf63335d49f773d3892aa879eed14c2ec7
+Tag = fb03752c5fab7379fcb7d92054700fa0
+FAIL
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 3826b8a041da1bcf36f8cc3e04699f38
+IV = 998d1aa03f08fafb987984c04bd4ab38bd018aacf520fa1d78e9b450b2abf8aed2cea6894f64f5ac55fa9f1831a00197ec72b09eb339bf2b427d14b99c6ec7ae35188aae6067cee43393b3b8683cbcf835d5821c48b3d121073038160ef7a40a97ee397a16993e5236be48de74634091022ac0550f3e647bea9aa578d6c53d70
+CT = c15477cf0e1c4c6eef6b64063e891cded0c736985b4b01957156da9c32f394b9371ead2fc86622f6f7d4ba5b5a5e01dfcc3e4d
+AAD = c7314b536efb7f8a9e1063f4ea574a2640d2a60bb1a711ef0b41d7ecb977dc7eab9f8cefa12a07050778c3df84e6f95c02a6461ace36b8e5d6153f17cfb9d6399c2528ab0b71902dddabeb03c2cfce122c01f2587db5988c9180
+Tag = e54937deb8b547426515b608
+FAIL
+
+Count = 1
+Key = 0ee3d77868dfc10fb9d683a6c70ae47c
+IV = 08ef5026d810526a274f6f3c6668f6dc535789888b49a5605627a26dc8c1fb6fc196d0a75128b85b15a3e7fd5aba13c81368026d4123b1fa190791cb014efbc1cf1e8b60aa1e897a8b13645cb4b8fbf7c9b223487ceb10b406fc2e7fcc1916b75e8e616da6f8e424915d876e9824f6a1c365ba8cac39d426ad4d22c451086c3f
+CT = 1b06f30d2f87225a3d819521b03455437ce4986251866a5f85f5772e70694c0e4b60e1b672bc3ce9001ae38f5538f37a66350d
+AAD = 18bf637f94688d9cd3b96174d8bbcb6628eb3c04dbcbab53eeff7c618733a015eddcfe38dc4d2c6df7c7898bdd1ecabec3b78d5013bd3fe796155c61e1960d3871bde8ea7648f60d2aefbf012e8b1da124abb871e96aa0c8ca0a
+Tag = 427721503327ba2a08f4da89
+PT = 2463c81cdf2f265689310aad786870e0898458da3f214430eb09bef5abdf00a9eed5f46c3d245c916bbb8b5f29fff3746badbd
+
diff --git a/security/nss/cmd/pk11gcmtest/tests/gcmDecrypt192.rsp b/security/nss/cmd/pk11gcmtest/tests/gcmDecrypt192.rsp
new file mode 100644
index 000000000..860167036
--- /dev/null
+++ b/security/nss/cmd/pk11gcmtest/tests/gcmDecrypt192.rsp
@@ -0,0 +1,1016 @@
+# CAVS 14.0
+# GCM Decrypt with keysize 192 test information
+# Generated on Fri Aug 31 11:29:44 2012
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 0e5d6e68f82f32bea3f0b69498c1a31ef6d955cd3d27a2a8
+IV = caf72ee1e62e1001e8cfbc63
+CT =
+AAD =
+Tag = db1a74ffb5f7de26f5742e0942b1b9cb
+PT =
+
+Count = 1
+Key = f780e4089a6224b9db576b368149fc4f58e6c8f7061814e2
+IV = ae84a7ac9f89a70c92d566ec
+CT =
+AAD =
+Tag = cd65b48665146066b92b34b38ec3415e
+FAIL
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 30b6bd8bed8df0251c8c1e24318f4bf4dce7ecf636752b77
+IV = efbead2ccfe79bc4340227ce
+CT =
+AAD =
+Tag = 8b567322ec301d635f032420
+PT =
+
+Count = 1
+Key = 9338ba6fb2309c9c94ce4658624c5e849811e993736ac309
+IV = ab574ab3a346b9b2d4183bc7
+CT =
+AAD =
+Tag = 80a127273fb9411096d046b6
+PT =
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 0e08f05f4486ccd670514f4307d410ff313e250dc93ffca9
+IV = a990d1ea4d789072c1881ef9
+CT =
+AAD = 66beb7044f4b32827834630d879a8a8d4e9d7b80bec3e93d937ec42a0f5ffc1a9801eb86e3db4852e09616b2312c5afc7eb1e39bcd92dce37e27c50b0d80e6ab7311e984acad89fd376e828062c018b82e7eb0c804b198d869ce
+Tag = caec2a7ab51dd049b08a024b92e28d76
+FAIL
+
+Count = 1
+Key = 25e97433491df9c8381eea524daab5a092db259edc34e4f9
+IV = 95ce1179ed9bd916acb7f7e9
+CT =
+AAD = 411d77aec39759114b2adb69d2aacfcd639b321b74e99e47d0e3bb0565167ec44cbd5f7b86444174cb0a2231698e5089105698c9e2dfa3954f73a9db1e6831ff31f0edb43a621e59597d1407e19e0f4315fcbb3870b87a9729c4
+Tag = 83d0a4c8dcf476d294d3de882f09ff5c
+FAIL
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 99e1b7c9b574c5f0224fbd597b2b19626c425ec32398885e
+IV = 1cfd6fe618dd6a0007fd43d4
+CT =
+AAD = a57dcde37ec42e1a0b9a169eb26425ae4ce1d98faaaf303f95b4f54295ae4ba77ebdf7fbee424dfc5b85607dc1eeeba210705ef017b94eeeb904368e48882722d16cbfac5e0c744dc746f6912896b6879ff663ee484b53a76311
+Tag = 954a9d6a7784520ae263a475
+PT =
+
+Count = 1
+Key = a0692d8ac9191e50227aca7e66bfa62e6f9913390f4aebc8
+IV = a82d8a18f624392c34691539
+CT =
+AAD = 3e0e9d0b83db49935ed0155909f7a6f6e4ce7fcba2ed7fa42a6ffc283945dca68c0e87fd1d61be60df6119bf6312eed60ade9d6e51156f0cb0bfc00ac86c9beff82621cef32bf34b83135ba58f0e4542ba4859718d9ca102e4e9
+Tag = 331bb460647e51ea147cec80
+PT =
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = f4a35894f2aa76fb6d240dd93d3dfe99cea32cfac897c4c5
+IV = 5c2b8b3213dbfd79224086a0
+CT = edb662fbaebbea0381f60084b98585ee
+AAD = 6cf6ff50fbd7dfd2a0d9893bbd5baec626d185e5
+Tag = 84fd782b6e4de54badbecc1332d17465
+FAIL
+
+Count = 1
+Key = 7af6699f566e8e9892b349f2c72a32a5c94653348b25d3f4
+IV = b682ea9dc20528fdb9985a72
+CT = 7542cbb76464a9f3a1338e8ecf4b6ee8
+AAD = 4f3c752a024d47416a5213815bdc3449deb82a74
+Tag = ae837b07ddb51085bf99463d3faa5d20
+FAIL
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 2bc9e7b3893243492436ebdd74a0503c11e1497fab0bc793
+IV = c0a8883740ca3f55f133ca3e
+CT = e9b29b921a20fd9ef2faa9af1318b151
+AAD = 12c23f7c98a3b61bc1dc188d4cf97dd792e90cce
+Tag = 0c47605f8c429aa38b115f38
+FAIL
+
+Count = 1
+Key = e2743368ff0b18e2c49c624b3fe92c7c848c143df71308fe
+IV = 6ffae5d1b3c9f5d8ee88b090
+CT = 257892a519da5735f8157e811431f82d
+AAD = c3186b7b4040d1516bf9e5cfefb699066d3998cc
+Tag = afa15daf61d2c4540c08df2a
+FAIL
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 692dd36f933612bf3cc489d67a23e124d9b653278e2ff1c7
+IV = f09cb5f7d3ba81bb3bdc006b
+CT = f136f262e800c7ef2ddc33efbb
+AAD =
+Tag = 4c1a4602965578460d6bc61e5ee81925
+PT = 7bac3bcf984a9f556f8d7e9fd9
+
+Count = 1
+Key = 8749302dfde89262edb67d36e7f5779e2d4eb4731ed48f33
+IV = 822c65d171b4ccfa00f86c62
+CT = 2e068703421318120945be4645
+AAD =
+Tag = fd805bfefea01ae3713bb4b53449fecb
+FAIL
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = fa34d0b54e3d8f6dbebeb42f330e0fe54a65a2316acb8990
+IV = f4bd6e8a4aa6b1f2ac7df8ef
+CT = fbbec752927736a98c026eb089
+AAD =
+Tag = ce02db92469bc5f4ffa9a6ab
+FAIL
+
+Count = 1
+Key = a220fdd9544b84244c767cf2794b0777e291ace05bfdab5e
+IV = fa50867e72d39dc4371b7651
+CT = 15737959a2622b783955ab15fb
+AAD =
+Tag = 4b608d500aae04c740076810
+PT = eddd451d140e5fe46c150c6c91
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 519ddbcfb3411c7539df0b61ff2b3e3d2b6ad8f030cddcc2
+IV = 78ec3873bd8846ac42ff3a9b
+CT = f1fb8df28f5a8649d930b477e6
+AAD = 7b4d412302f3319653cced7dc6d7d845cf1071d3802cf09bcd2bf3077609a1dae1bf64e78820f368862b2c0daa17ff9b33d1a7e4f627507c5a916a800e6d349f72a45f8f76b01e63dfcb44f00a225741d172371eb96f964987eb
+Tag = f71b0198aee970e0cb9f835b4ee9f433
+PT = 16eaadec26204a644e2f24b1ee
+
+Count = 1
+Key = 93d02ef0f9360e965fb711e728cfcc7c323918df291f625c
+IV = 1652153b54951b0180af5863
+CT = 37b428d03edbed106587742f19
+AAD = 03d2918d0f23ded3cd793b9c00184fe1cf4c4546c0f6c83d1ec025c83777f93250b632d06cc5e96ec7d7c36240f7e3055bf1cddd0608d92a437be72738bf3e9c4958fe70a8672669fddddc5028181aaa04984509e1bb7bec2869
+Tag = 2055377cc020f111e49a7a3076331072
+PT = f52f71dcae794100222cc14278
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 4bbeace710677b723e15e2c619045be3631b392bc1c291d5
+IV = 15d2161c6d01e9328c7aa601
+CT = b9417e118d30058d097e9b8dfd
+AAD = 820ed107e867ebdf9861088e546452d6eaee06d1c7c116a07cba2a72b9a2fc974485a842e6c891ba2b08a3b773f3c92f56f97b934ec9e14c928f9ea040c0390535309cf49477b3a76cec40b6875238dfef2f4c86415e05220740
+Tag = 1187cb806d5e58af5ba9e914
+FAIL
+
+Count = 1
+Key = f9f4686a4a9519f903a1d63f0ae0d450414aaff622c6d3fd
+IV = bf048a6dd8070f9ec33e77cc
+CT = 2766c42019885def889f3d4e2b
+AAD = 54c4859b710dd15178b24c74e5825bb27c9acd0573fd2049aafc921676520f28e9cfbe211f8f7c855b9bcb02f5afa9f7c02581e30aacefb19d31246b82a187eda5e0f4ccef3717366c977d2cedbfbd5276a9559a60916ac053d8
+Tag = 92025305e06ffa9f05e2f18d
+PT = 7942b575fcbacbb11c3656327f
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = f78b20a748d3dd00b78df86efda81e495b42a1750b98b7f3
+IV = ea8dd7b69521b27b2e4ba9b6
+CT = 12062587ecd5b89d72030cfbddf8e13ede8c02c178885df2a41392e62014b9a4
+AAD = bc2de46f29deb1ad59260b7ba90f0c8ddbcaff0d
+Tag = 5fa0c38d6deee5ad5e8e3e88a26b1be7
+FAIL
+
+Count = 1
+Key = 147a68d29beba153067c66fa805ebda184d153db72cc1495
+IV = 0beb22c66583920822023fe3
+CT = 52a5da707ed72f194b82a22e502844820cdd3da737454842ed37bc1aed1493c8
+AAD = aa6e807af408f349918868afd9af9a16c6ecad5c
+Tag = c689653218b24320e5a3db5e591099f5
+FAIL
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 18309574c65df0b78da93285dbd43d11e1c988db97ca2bb8
+IV = 563af7bf4d35c531ec3561fe
+CT = c132c3a750c27ddf0196dd1c6606d51865663afa4ad2746bc558b97a7e99e164
+AAD = 676298c64bf4116f010fddde84a84c87067ad013
+Tag = 5d0ebb9c1e61676b76373f61
+FAIL
+
+Count = 1
+Key = f3da884d7536c33db74cd0e06d878bc7bd17c5b439761359
+IV = 1ecd1c1441d52a206a2c446b
+CT = d2673121cf14f9ec6945469ac177a5ffe91bc7a0beb3fde59b3722f15e67a3db
+AAD = 6003f684e04109eb54ca7dd26163ea139567861e
+Tag = b6b4f3b517a5694d5f470fdf
+PT = fe14ffc321da3def6dc638ff225025d99fa8a006eb3f5dd2e777d343c86c0d8e
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 117c607e01badcb6be05340ca91ba8031f30d7df206c70df
+IV = 17817f2823679496258868e2
+CT = 75ee0bd6fbc735d7a5c60fe2796ca9f14471955cdc260b61536ba475359dae522a3dff8095cb0ad61928ab91613bc1042457b4
+AAD =
+Tag = 1d2509a73b0f3477a6e3730bcc3e5325
+FAIL
+
+Count = 1
+Key = de0d93038d219e7f97fc0b288984bfcfe4878acf59f2f599
+IV = 483751b037c6dca1ff6d4ff8
+CT = af691f13f645a14d42de6273d160ca44fb8a3bed24ff87257e463446e04f31432cc36c0603412adab063283c14e4ee78ab309b
+AAD =
+Tag = fbfedfa8d93e1594457723bd50bcf63e
+PT = c7e167999d65346207016351ea0d862110d0609606db9d90fca8bf228059b7cf589378a5dbdb07310d7d09cb13816df00444bf
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 04b375376c88372a04406a184c0d51b78a7b6eba7561c399
+IV = d76f71b405311986e617067a
+CT = 79223102aba3412459e6a3a1ef6043ca0191585776fa41f4419841f090929d367953d13164c7922ec787586e1915f9486939e7
+AAD =
+Tag = f055cc9dfa6bf5e542e28288
+PT = e24b989ad314f5da96df3c797fc28fd4427c2993f1b4b16bf4abae633bce44772e3aebdaefb4319fa8a1a092c0259a41b74a9a
+
+Count = 1
+Key = ea85fcb5853fea0df4a94fcde80c292c22e171418327d619
+IV = 2091688493235e018041b172
+CT = 27715d5408ecac994f4c812e738c155a36687b9f1afe127dbe3285b5d22966db7c554e80b8c6d0020f67c4cf34b4009d3137b7
+AAD =
+Tag = 89b5ccfb0a01300249be9a2f
+PT = 660e459d33b0d7be3fac3a2c27c9be30775ccfb4284b2fa2787cc33662dc3d281eccec1170c7c059b9a45ff40da97b2c221d44
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 58b4c1ceb6e22434d86ff3ade5a654196318734612bb9bd7
+IV = 8928e4bb85f50941fec31453
+CT = 1d5ee768d791921000ebe0b9c3c85f1070fcc2c473c5ddf58a3e86aa2bff382f9d47d7f4023aa1017218e6fdd7dd6bb0a2ba79
+AAD = f99039c812d3522f81f8ec09ed79fa0dbdafeccaf0814cb8cea346d5928c245735285890b65c32e1591b811eae8cd261608da6cc8c3a0d1eb1b261f748fc0881f05dcc6b40f38711cbb084c0c30f7cb4ad4dbefe574b414b3454
+Tag = 36e0bacc9ec6f6ea386f1fe997011347
+PT = b0597cba878e78d7372b4938b25716a3c98fdc11ed12accd393d80a35a6be1d6efe40622217b384e15b57f006c9c47e0d31a4c
+
+Count = 1
+Key = 620eeff77dfb66e3160171115d86d140b4f463004983fd02
+IV = bae5528715e7d6023752d98f
+CT = a36515b7d4afa95e8d391f54556f6d0ab6e02f220eaf755d77de1d9f89f8f69728b0b85d28b9d948bee66aad9c526fdd6f461f
+AAD = df501e0630e27ad1dd8fa6288fd3109d8a416274f8cc31e4b9d3d58e14fe214b954c1e9aab1110e47cb2948a5ce958ebda33f405a425922c5b857af53beaaddd2cf0c0de29770536b6321e9bf59335583a88804749edc34eeaaf
+Tag = 394cacf0863f98234e90b887cff9e4dc
+PT = fde943daba34d2951ea9a73af6f213c46285b32c038b23420536a13280a237df0e6b67e5a7a62e282b4d6cc2df23a7fc7238d7
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 42a8d8ab84980e9adf0e0f4e74ef5a6f4b2a135b5e85e17f
+IV = 1d0ffb7628a16c8f173dbc2b
+CT = 9b3460f3d4f8257e8b47c2e1da2bfe40e4a0cf40ca1d50b8c3b2876dc2caf624e161aafbd5b268b1753cdff3b5346c9e74ff7f
+AAD = 4e1c1f2996a51fc445a56dc72e8c8685a89c4a316b89b4b83164e8c9975ac189f70ebe23a64f8a7b7049b26a6c1834eb3b9284b7eeb6926deb5c6d74f05935befb6fbe1de5301fd296127903466bb035577d9635dad41424c8f7
+Tag = b103bb7e9ff886d616a08e38
+FAIL
+
+Count = 1
+Key = 0be62bfe9db2d8282161730f940bdf400c8ccf03090251f3
+IV = 6243f382c59c5f2826b91b29
+CT = 0a4a2d736571d97a070b577abb8b3dc62eaa6300fb7ff5c92fc2abeacccff62280558946c79d6bb4e98c9069524d979c06cb66
+AAD = 2b5579b91e5a5d85ccfff3a58deeb35308a6c821d4459a48cc6ced6feaf2e2b2458682d5216ef9062a7ffd6050fa1322b4a6c428c094d1f9b11e323379370d8b96a5e2525c199fb51887a156e348f2ec6bb75ee1c787230897d5
+Tag = cdb3fdef84a963eb6b1bff11
+PT = d096c9d8de72011acbc9dcf1848ee328bcc5f73e9420adade41cb65f09e0ac0c478f8e3d56da696387df34932c5cb0dae94cd4
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 0]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 282bd6dff9f572026101bf3f4515051f5540cf17ca029b0d
+IV = d5
+CT =
+AAD = 9f5c16f01b727650ced263865b2645dcfbb01535
+Tag = 6471fdec52c26404ba1e7dc2eff0e418
+FAIL
+
+Count = 1
+Key = 217cf34ae67599fc106645e7de80f64014af97e02bf9443b
+IV = f8
+CT =
+AAD = eb31f104bfda2b58d69a9e94cc5fd6e0d3812086
+Tag = 2e7f05cdd31decf127540d53108fb3b4
+FAIL
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 0]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 9bf81228dd4c5a6242b1c45692461a4de3d8ce585abd6cfb
+IV = da
+CT =
+AAD = 4546f07aee0d078dfecf1f31847bdbb2ce05a511
+Tag = 5620f3e98d80cbde78c0cc90
+FAIL
+
+Count = 1
+Key = 55173d57bd1468ee30ca7071eaa119a81053bc0696038933
+IV = ab
+CT =
+AAD = a323144ba5c1d276d8f45a5a2f40afa6f9451bbd
+Tag = 25a869de10750961337c9427
+PT =
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = d81df540d2ab3aad0c676bef2dc44246a1658d73d7060829
+IV = 7e
+CT = 24e2cd3f9bce737add2667326c884173
+AAD =
+Tag = 5ae2508b3f269eea124e0248f9a0f2fa
+FAIL
+
+Count = 1
+Key = 3417d5f215536f8f4418ea6ee9a82d3a732c8fe8c1eca2b6
+IV = 60
+CT = c357b89ce02030db4ea09e5013db22b7
+AAD =
+Tag = c2ddaa1cdfc8aa34baf9b69e1bf3b13e
+FAIL
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 041e136646a1ba3a7302ee54a84170da1158a55b2007e1d3
+IV = 75
+CT = bc864251987d297fe463f78674609607
+AAD =
+Tag = dc2ab79d51b0d7af8ba9e04c
+FAIL
+
+Count = 1
+Key = 4176970dcbf581902383ea0cccdf665ae3c39e04d250eb82
+IV = 06
+CT = 755ab8ec9c0adfe70d3aa3bdaac790c3
+AAD =
+Tag = 05e495f65af8b2cd3fa3299a
+PT = ad46bd041064efece5105478927cf23c
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = eefe79e261cf81df9d5bca29b87c61ba99dc626b4dbccba2
+IV = eb
+CT = 3126a5146f65849fa507a28f1736f548
+AAD = e0b6d6c03444084b0fe3646fd36b2b5527bc57ed783f238e584ae84283b21cc0074d6fd468d720953eb64a93341ad78cf13f82716f39a5faf1ae06a8a0651d8ccbcbe675c8b497d5f0012543c4f5ec9f1ed004cf64bc86edd75f
+Tag = c06bc2dbc668e5efdfffd42e12b59761
+FAIL
+
+Count = 1
+Key = 4baf5c20e789cbe16ba6518a3eb3db67068ade6079710860
+IV = 21
+CT = d17a16b9f59a8af1fae202527bac33ec
+AAD = efd143f001d7ec6434ceb65f0550c5ba20476488f8cd9399f644a1ee1a197a0b43a91c889a42a5466e6719f2bea779ab2b459650245bc1ea5eacd0365fe102c2f47aed839565ec69d7130ab65dff374c77651942dfc25cdcd376
+Tag = e8334fba87df3783881b5026802d6eba
+PT = 50990d4a64651871b61935f0469e7e96
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 7ef3287353497dbaa76b495702233538e6ffd159aa2d0b1c
+IV = 85
+CT = c3b77ded27aa90fff1bda9e89fc4cc31
+AAD = 9965479713a1e7434bdeb494f5681cebf21c01776aa92531fdedded229d05e58727fe76156cf4d06fcb6850ba883b1775b21cdbc5074edba8a31b2335e970c847ea5d58b4d6f5a3851cfc94014fb7147d0d76c657c8acc110e2a
+Tag = 2bbacee87e7789a49ffea5ce
+FAIL
+
+Count = 1
+Key = 7cef46408715eb1e1911286103f05e162724d5c9ee337043
+IV = 2a
+CT = 1965684b2b7954013f5f5446c96c1260
+AAD = 17787994ac497b42a465ab80adb06e944356466d53337a9ea6e1bbabf896f143da89f8fe21e4a351d9d6f9b768c2b10f5d4df1ca76a64c84943139f7c809187589ffeb382ddbcc3178a648b76953fc9ff8bae093331a56e2e764
+Tag = 69872e7c5b802c85c4f0b297
+FAIL
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 104]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 9ef5f29246647bb8576bfce2ef9f79a4ac9cec41937d119e
+IV = 0b
+CT = 121aa0b1be4e6766c202e4581a
+AAD = fb2c8792b79ab71c5032698ae39ad7434ece209d
+Tag = d54184f59168322357152dba099b634c
+PT = 292d1ac83d35f24c0b4f1b2bfb
+
+Count = 1
+Key = 815764a65132ea32c09e5426690b724d6bba9ff126dcfe81
+IV = 7d
+CT = 17e3000a3e380fbbf9b8fd7c42
+AAD = eeaedd13531eaa43b21316c041901f33ef316132
+Tag = 1550427350600a88f9e30d58a6a404cd
+FAIL
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 104]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = bb190c3b263a22cf0adff570ac9dbb7ed651a7a87ecf41be
+IV = 11
+CT = 89c047653feb0e32a71fdccab8
+AAD = 25a0546df41315a4c4f28709cbaa854f6762d413
+Tag = 217b4ff1244cad461c72c6e6
+PT = b1fd5da56a78b6305d42b47556
+
+Count = 1
+Key = beb7dc40237e5ea711e4f9ed3e524aa471ca789f46ff2aa0
+IV = d0
+CT = fa4acd2d5ef13236046d15f53a
+AAD = 286a61b9ac003ee7931f29978ea99c102559a8a9
+Tag = e5562dfc79cf86500ea15b22
+PT = 1df6aa2a90d48d78de7c663521
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 4928855392175e60fafd1872fba5b03b0ae2e5676e17f728
+IV = 34
+CT = a52d6ca81c0aa81fa5a31e47e7b1593cc85103c5fb1efb78ad2381ebc486b9b8
+AAD =
+Tag = d07f250f984dcb0a58500f2d8991807e
+FAIL
+
+Count = 1
+Key = b13f5ba0ad5518a72bcd5627ddf74116f8141db915207395
+IV = bd
+CT = c32272c4985d8a6750be630aa3dd2717533d2896d0969fce780272becfdd8ac0
+AAD =
+Tag = ec37e484d0d70b7567784c21cac01949
+PT = e2232d880799a4fff19ffac9eefca51b999b63bed5f7c7d57cef1b1cd2ef1484
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 814fa6960499ef272e6cfe5dce092e5feaf6cb82603715e8
+IV = 7d
+CT = e75c36699a964fad74fba8d69b8c6ca1cfa079fcfecf39c63dc3b5110ffeb245
+AAD =
+Tag = ef8eef3b36226787288e1f7a
+PT = 689db3fb4cdb15618ed9e8f00583c7b9d2b61c7ff2fc99db5eb57cf1a4ae22cd
+
+Count = 1
+Key = 827b1732cb26ac82cefc9928746ab0a97d1a6b73e25bde69
+IV = 6c
+CT = 8b1c8da95d06fac734b3ff03f5c14964895f082f62cb3c002a4924b793837b14
+AAD =
+Tag = 40d33b739227a4e282ceb290
+FAIL
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = c621098da9c0e9386e1e33d5b32b3ff677c0c2937ff24c29
+IV = 63
+CT = c9a475d570711f5774070d2f56042c09eefd2dfdfd8c0a7ed71aa5b62d2fc59f
+AAD = 6089d9b6fb5bbc2ba659ea25c52e4be743fe409d43a46555c52c4a6ab84b291f461f9c9fa18153b7dd30bdfa1ea4c64f14539efc0daf7f4720d341884a8dd008cfe7191ad706e571e452f9e15d34630f6fd9d5cb4f287061ade2
+Tag = 05f75f1333a8de721cad8d94ff564af8
+PT = 2d93c2f0ac37b2dcd7c034b843b8201be4c843e82c8f73cab4a232ca3f012c49
+
+Count = 1
+Key = d4381faf602b088dce355140c1e26eb6967b473aa0564d01
+IV = b1
+CT = 1c622ba1e1e10d7ed888ccb0ea4c407ae4c0645b9705927db59d3d04e0324463
+AAD = 519c145350e84f794433219ba1034d7306ebcd9f800af5ece139f3fba6b84b7ad5e9872dc6ba3ee37a54077f416a0d07421bf389ca4d9347d5ad89146b6d8d3fb8d7e52eb37c1394b385659fc27fe83a7cc3ec3f6cb74f39477b
+Tag = d139ae297c59a092a6e8d69425cdeaa3
+FAIL
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 6f058a93977fcebbf59d1969f4f199dcda536b3b30a4adbc
+IV = 43
+CT = bae112edaa6da5c7def45787e768362cca6eb9519fe94ade2283e1b4e46773e2
+AAD = 2f4891ec813536d271a9381bb2ca7dcd5dbaba1259d4f3c0e48dfa6a108a7c3003946a5b0d534f13a726cd91fac2519db0c63e796a625afc5e43af844d0a9d584c5ec04c54a3becdc8c9d75b8a17b0ee7b6cc4af0d4a29d840d7
+Tag = b238c72b20d80fb0a17cf7c7
+FAIL
+
+Count = 1
+Key = fde925cb4f198784998ab759276ea7f9f184161250a4bc9e
+IV = 95
+CT = bff8e471382f68d08d73509fd5e815e017bbd0256d1862601bd674ddd4c9dc1a
+AAD = 6819dd682c6798b7808b174b5c71ebf8c748e5ed95d456653d9218c13f894e36098687e7653da8f58cf0e3eefa40ea9afacb6ef0f83f25f6061ddd6dd589ec24c4a8fe68b7072eeab6216566e79f3bbb5a5790cc53aa35beba6f
+Tag = 8c695f084f0a0bde98445290
+FAIL
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 408]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = c7045b21450d74d28a220ec8671474f8dce28c9e584565b6
+IV = fb
+CT = 4f3053f9d0c172b4c11cd96956c66f91c500493344e924c506fc2b1f6f21024800558b07f99b448a496536dba62da661c5c93a
+AAD = 8640b9cc220d39a141412ec4181be7879d885144
+Tag = 78bbb2c81d7b319eb98c3031c3770f6c
+FAIL
+
+Count = 1
+Key = e951f4397ec4525683e845e12eb6003c156a3c9318a99e14
+IV = 09
+CT = e2d6282da935d8af6223319492ef71b845d19e21fccc515d9dcee98f9577a66fee107e2cb06923b0522c32e3de0f2ed7afe886
+AAD = 1ce33f28c7fb8cb28b4f64899ab7d32ebe72160b
+Tag = f82b3f0062909af8cdbb7a6aeb7e1cc1
+FAIL
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 408]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 382a27263547c4509db760e9915591fb3fca56f339edf8be
+IV = 74
+CT = cac98df2dfff7545b93ad5b57be290f750d7da2cc318a0736621d6af9fadc5f02237422a01228d6973e17ac710a32f76229832
+AAD = 2e6a2619b048d42b42e6fe2b9b58ea7ba7db303b
+Tag = a8f22caf10f9248c792020ee
+PT = 209cc24230dbe07b57b433538e65d0724c54ecde11eb716086075cce21ed0dd644dd9f2559c679e3362b6a2759a1fd99fddf34
+
+Count = 1
+Key = 9103743f080d9cb83b2e14521729fc2c29be43a5803ac832
+IV = 4d
+CT = 58e624e49d0e35239f191499ecc0e547215ba70321b34686f79d4e47fcb289c606bffab56b946b6cfdcf96ea01bad889a735bc
+AAD = 5d783d191d51147a215a46d4fee72dc5c72ead96
+Tag = 35d75d28ed3b26f1aa537c9b
+FAIL
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 89bb644ba7ef882d3f2bfa309e640c16cc378164c5a903f8
+IV = 1e8a0c46b3c581cb5d11e91b123af3a7878c9b9f6b8ff400c432bad8f1564f71dfe4caced06308d7967580cd930378aec11dcc641eda1ed37cb1129d65be141d30048c0347d634f4f142571f4a5bcd21db8dffd5b71f785adef344803def95bf0f8f6219e020d4f3b54783f3832ab3cc270412f7c5d00c8162c72dd3ebb60ad2
+CT =
+AAD =
+Tag = c30769bde1a45b3ab0a2a4ab7267ecf6
+FAIL
+
+Count = 1
+Key = 29b93cb8242387c8fb0393f3ebdd6d48fac61ce46d9cf83b
+IV = 5b3b08a6e2e3994619ee7e08d866e86a5f76dc6dae0f998d4ba61bf8d5daec636123fada73567c38966fe159f2d5fff16a7173239349f7df705630eafc597e07462c04f01f9440b5f9d19b200518e525b6b60117f5408fc560c85a0e2b5e13bd27c02c938288e25489adf9adecf13cc0dfc8b6ce55780527d3296118a1e21818
+CT =
+AAD =
+Tag = 68bfe2e12c62f574c857faa8a360ee43
+FAIL
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 1d583c6520a1164c74e218e669a3462e3ed59ef23db213c1
+IV = df7573622579733a45383fd52821490e27aaf06c93a969c17c0d2c67bc4e518f85970a1c443d929873be83b6b9cf6e7396704c4ae8c6d4ac55e334adbffcec2a02030c158c5b9941ed4759e2a6e79ef2718a8fc07e3892859ac2aba0a41686e0bb198bbaf8676d752f0e43c1622559d1eea0572081f81b567d141ccce05ecda0
+CT =
+AAD =
+Tag = 31b68bebd9cd93268c5a2938
+PT =
+
+Count = 1
+Key = 18a5e8671e7c11cbbccfb2df340038f3aeadbe5a8bd6b4c8
+IV = f7f9d84791fd6480d98dd3c675b2e14a6acbe4f0699ea923eeab4dc5d68da21a1498b59068c49aec372787a922cfc649afacda1d73e7b9c41e3cc3774543ddda3b6839a88e9aa86787a6af078eefe506b7827c534ddd53763cf12643edc967512a8b1b3de714ca1da56830c9079b5345b940b2e5fd3ed1e2777f5a4c8f06e8bc
+CT =
+AAD =
+Tag = c9d5c3437aad1e7887ac8483
+FAIL
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 6d90cb45d5a1cb2c548066a49830b9160e3122ea2b36938d
+IV = 6ca69e8e4a65455211a3447c3e2b8eb396bd24cf43504425daba105b350b596f7a4865adedc12aaefcda5699af3a8301372dacacf62bc137f96e4a0add7b8644839546d263ec136dae3e87f8ec6f178041751bb78629a5f6b4f816f5750211bfbcb395eca883873c9bedb443320b3aa56ea84f2bc7678b8cefaa40e337e86c6b
+CT =
+AAD = b7d5f9060a89d3e4c996aa061467ca57e8cb02eba0e5af9b35bdf900b210a7fc3252fdd94332e03f88568ce97fa14316baa7ac2893a51705216446b7d85cc704386b7e898729894c25095cbeab49e7ab0a2357f0ee462f206cdd
+Tag = d4f49c64ed18ab7495e4f5c9d312e4f6
+PT =
+
+Count = 1
+Key = b4743c209c9f473f7ddc7722d3aa5e2627997bf6f4f6fa93
+IV = dd363ab51f476ff5a3e9f7e88b6f5e62fb54e8230a5b04d42090fb5272a0bb1eda0b17d8fce2f19fa544c48a0e0121abe8f5fccb725013d4d6d429ff2a6311fabb6bfa6bde9ee101590d9835249ff69a0541db296a3aa3258e7a435007a97b8e0808500191a2d2074fb0309f7a5ae45bfae276a81e6d1d4bc1de7f3559abdb2d
+CT =
+AAD = 031288db3ffcaa33de04979003d1602fe81e7dfb43b9bd6edab4776bdb8b4bd7e7386d90050ecc1d78abc8655207bdfdb4570d0a40d66edd43b580f7393879ee01ff8a9cb5ce876d8cb0a32029ed1abffddbba5daf8bfe3638db
+Tag = faf00b97fc982fcf6570f016dd5a4770
+PT =
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = da3d38ae1aeb9b7002f823920c09785db0c368d4b0f1a28c
+IV = f9a8d10d13347076ae1906c0c4014991ecbd982006c9aa71b6ee7aeafe627a322ad2b5f8e1ca22c81e8cc55309d9c17ab427c74cc96ee20cd6c1154761772c1b1057aac3b33c46f758c53060676fbf2e709a829a33e56ca6710d48c2e274a63234c911b28ec8b0aba47492e2782f8314d068e3dc6feaca1aff5399bc5d6a4234
+CT =
+AAD = 0e2501b3d56115ceca1aaaf6f311dff8f09029922e88dc6e74a4e53bd3359d4c49acfdb72d73e5c357092b195785714a18cf158fc47ea20bb898eb2090af9ba44d7daee12afe7709820c8b0403cd28be80ef3f2d2168153fd937
+Tag = e67d90b1de432367654b8fc3
+PT =
+
+Count = 1
+Key = fcdb9f33eb662d85b05e0519e692165b595d1da031430232
+IV = 15eebfa475af1ec10e72a3a7a95f103557476e55598e7e2186edd106021cf1d8f833541b2f173aab541343fb11f8f17fb28e726e046281160c6315261b9a25dbf2c6e682876f85708c8042b3dafec6659144ee231c2e46a8cd81d6561e1b03d6293ef7fe2e72eef841c642f5ea6d444e8307b5539af66c80e19e360d58bee556
+CT =
+AAD = d23b14d66326fa95509270d9c817e777c5f1b81af887150e929b934dc7c9f0c3e5a87237dd7a01bf70c29d3dbc1deb6e3578a7823b554b8b7928d13e7a578ac22db686e517337ebc8a6a9962ce77b2b52697f67b17ae39feaf20
+Tag = 483e32c3e57f6ddd2e8e75cd
+PT =
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 8a7a758ca57900825d3c6b66bd66097bd3465ff22a82f5a8
+IV = e721f1425f7014e0ff1d4d2d11505633c3fe6d0f642bf05ce9dea381613db36283441d5c480d4f88d403d8fc3526806fa61b3ecd0ab625b818ffdb05c2339ee4f7b79d2880115576519d55cfe31454c857ee540a92c59860e59e023d8b9e9e4be0d3b98a0cf1bf695472025bb645ddd7aadcadecefdd31e78daa8a658679d7fc
+CT = 5b31e389d98f3b39539e49724e1db4ea
+AAD = 3e65e5ef4c93156d4911d722fcc4272425444def
+Tag = edbd5da8702b677b6b8f4f893fcd5a5c
+FAIL
+
+Count = 1
+Key = deaf504e7f15c70c087cfa0fbd85f47a6de53d6b88bdcfaa
+IV = 54a1cd229fdfa0c14a28af8c616424f9dcbbd249d98aca615e53f57fa11181d53b8a77b6dc489a59183b5a7a6027f3d070e967cbcb03063130b00bd10e0f6e185b8f76121572008585adc26865e856ffbc1d92095f07899db2e6789ac26b418f743879695b5172a1b2a79575e39918d5a17c9cfdb3ae39b3a9c94632f0164807
+CT = 1d5e7c3a2477762a38d8fe7001748d37
+AAD = 1d4b73494d5248abf6941202b7413e4cff834cd1
+Tag = 016797ab44ef3bac283b192c0152d3fe
+FAIL
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 116fbef23a421d43110cf2ec2043a566ae01899724d48278
+IV = 586461f3bcf481bfa217ef0de106954483fed320eb415752d942963372731ad1fb2fb34aa3b40528fb6429ddb6a68b731a52f6e266c180b8b44e0909e1df81352d5281c15adb42edba413997614eca770eb0535ef991ef3bf7b3f75ee716b4d6c2620d0d897f5a00b630ac47282324a4caedceb1badc1108d49018d4d6f77ab9
+CT = 7c735121485165ddac8cbced8e869f66
+AAD = 101534cd0f9659bd81fae85e32c20831f1882ab4
+Tag = c7559c654f0c12eb42f5d074
+PT = 22eafee87341bb35ef8cf4448560c55d
+
+Count = 1
+Key = b59d3ffa7b11fa4dc39c69137af868e46b0745237cd13859
+IV = f44ba806033f27c6ced41fa73fa5f67bd79b8d3314036646e665a1c3bc6e69d09bd43bfd1b36a97d21d4870de6199540caaa02d9ac50ca77ed531934611f223983a5b80ca84e69088f0152411e09fd849e41555fd703a4dc9a0e297d10159e986424bb9db41dc816e4ed1fa03554f7dc81955c2ac0b55bbd47056cc8b9993898
+CT = e48e3c08cc5a7b09aad661526497334d
+AAD = 067ec49df158a103287003f71619f85a9c18864f
+Tag = 01428510eb9055555fd0a2f1
+FAIL
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 17c4df25cbf30a72ec6009addc5370aa13a04b407dc06064
+IV = c0d7c5fa0479b4bd9d8167ba75ea3d8b3dde7abf5432fdf868c7259a4df1bec702f0f6672f02f43e14a3724a31549e783d70eb5de0f0cf97ef046d61c58993adc7e673b8c6d983875a7d81e3704e42bf38899b8a5bfc17d5ab1c90468d0e519f347424ae5c575516e9af09a73246167504f28873c98afd0f2947c36f3c164a98
+CT = 1de45ae519150aa6a7cf99d12e
+AAD =
+Tag = 1f4abdd369617e44dcc1d2d6ed57f779
+FAIL
+
+Count = 1
+Key = 743a916fd7ffe4a51b8be441ad7f8dd9df6023116df96954
+IV = 2f6ef13cbfa341cf553554fb137d756b161bab0ce0095c314ff7f2e8e1a494033ae66d99affb8f7974f09aba8298e62233578f63381b460be5bdaf6d52ba6e12939405312a00ca96ef81572b4c96b845aa61b349a1a2816bf20779a7c3faa81bee83347e807a42fda7005a9ce5a766f4bf40bbfc04c371dfb3731317924d9ea2
+CT = 9c179bf1a62b72bb99fe085927
+AAD =
+Tag = 73175e58c09eda41f74333492244f810
+PT = 6daf295712e7e4d1f68885634e
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 526ae9a2035c671774b2f56c3da190bbfa710bc2ad85dc35
+IV = 3a6dd49a7caed1c4807c08cf39272228ee052fe034217bf11bef1433b9e90377ae72e848b3fda3d574564fea6df343e183a8bad8a3f4ffef8740919d1af0146dc693f4af8c7d98b908d50d203286d09b7ff9ab4ca5806a63512d5d77a42fe865b77a950252055f4da39832289626e01b7e7af740f062ecc721984f1ee6e252cb
+CT = f9cba21e9b0b2a6e31a4b6d82c
+AAD =
+Tag = ca5dd4dde32a7d2267e6c4a5
+FAIL
+
+Count = 1
+Key = 5eb40a9cd4ab8e39853fdd60b83053c485050edba22fa1d0
+IV = 3c99c1a6a26f247d5e88589b1691765f91ae2a1015dcb8e07d87e0357805c2b8bf1bacf6eb67bf92ed43bdff6c3704f176b4215424fe7e23ccc49f55568d22eb5115e4445d1db9b249464c2b26e797335171e04f58623236cbf3d361c1d1a48a9f1f788f322c4eaf70394dfef35f727d3773c52f2874a7c755ef5ce0a2c15700
+CT = d8b1dfd1f2d875ac4d8cdf9688
+AAD =
+Tag = f26b1c355c0e15ac7be37aaa
+PT = 16e33d92f4bb2604703b2cd32c
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 0ee4a60e925fb0bd7518b6e16e6d3f18135bebb867691587
+IV = 4d6d93f0a012d0e23dc6e7a2a66b66a511893ad3c410e50a94265cbb7c7afdb132d4df5d727848dbd9e4f456df9ddab892d29be9a2ed5ace4a521039f9669d0e762331ef7f3cc4d02b6983303b4d286a45ee8248fcb645652e10add7e07bebd3a4e5d2701c1a88bb4677cf18d34e3a9211d94d41b58e54cfd7c8f941777b7aee
+CT = 2fc3e10615885c56faec216208
+AAD = 7cc5b70275c66608a09ecc2d685cecd948f649fc34c3e1faef2685fe52de2103ca090084cf1cf3ed754ecdf5df0ac738af2bf676e562ee271490b1aa719b40736e95ed41739c1ad23ef0931fb30aee20a5ee1e307507affb7eab
+Tag = bd17fcfd0592205b8302711c78bb4376
+PT = 6d7cd93f7557af8b8ac6a8f01f
+
+Count = 1
+Key = 1b685f3587ae2e04b0d6d92593efe8d6e585e452d5ddbbfb
+IV = 27f3d9121f70c41b4f0ba166ffe1198041d78adb5975649f30ea7ebdb1ca86b8390e6d74e40432be3037b6e06432a1d37e57b3d1b867bffa01bc1b65fd1441093e09d5bf116a1b607a8df3833e6d51b6f8ba0999fbbaa98d3770f3e9d034053712c2e53bcde8e196bac797a3ec32c342816b97fcd7ad64a049bc50426ee0bfc7
+CT = b89ac3eca91e250fdaf17eddba
+AAD = 0b4ced65ea3ce50c6d124d98559aea03cc75803acba4c6182d5efbe556d77a098dfa24e820ec4a86f42e609b052f81a29439e8d8a0860b673d7ed4d60c2428e49e363164410504e76d9fa08bd86cfe02b5af911df15ebf58dd61
+Tag = 498dbcf337017d0463cae0441dfa1e6f
+FAIL
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 9298e2685ae2f3f880245ba78eaf5897496d00ef9690836c
+IV = a10fd52e70f8c84536beb798e18ad502cad1d22a4a63af9353faf02a05d1b11676171c6eb974e60b302e7a7bf0b7fb32d1f6c4ef3f3c038cd2700a617d16a62421165a6b339db897c3b3a9a9becbbca93338c309eb5810798b7837dc1e31c296b508df0d646f6b89bc6b75ad5f9def686064fd6e4a5b4e7ed583da01e95d68c5
+CT = c1f8d6f438b31ee1ce384278e4
+AAD = 5e005c01043360f039e6c1e24ad7e0a7be4499909c338e11f402c161f7abd385dcd0f1f7c464ce817a81aca61f7bd65ab6b6d1323ea701e7cb1e6ce02da1f300eccbce1a558aa9b15094ec32c195aadd3dc26fcb825a2cc07f1c
+Tag = dcdcc774e08370ade84e6d35
+PT = 0c9e410903b51b187c942224a8
+
+Count = 1
+Key = d14095ef7f54967bb13e400f044bc015e257f25e11e3561e
+IV = 44b01c8283d1dbc8817e0dbf01eb01b70bad8c583ef435979fe2401cf2f8b8ba9fb883d6af732416c9611f5481c34c1dde8db303e2be296c4fa2e5b3f28ab4753a4d35400ac7aac25634861227e6dbc9eb703734a6185776d1615b82f7728ae122db77faf475061a7cdd4d07d84fc5667912f8041108e362ec2bfc475e944bc9
+CT = ae1c5878c4bf35c866efad56b1
+AAD = 9a069c996dcd838f7a35644a362bb5aff932cf2855aeb2f1541d985a50f49f7e2c1d9e1668072865c85ff605d6080655c5f15fe5ba51339891e9fd355798b5060c5fa287babe3f975fb6ed2a8f75bf3d9c711c205cc2e3566829
+Tag = 5060971b8066a7b21f84399e
+FAIL
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 4bb714384bb40a193edb0a3662167a74f9fefbd974e231f8
+IV = b0bf5a9c2e32bfc4ef1b78336188d2aa1ba385d74a98d3ecdc8aae8fee1b76c65fcea2cfe0d8a70e63b7c16d287ce72b296a703b2a96ad5055b01d909a280adb6b9b461ab6b256b48740422d906eca0c25f763a336ebc04d00ad66a06e5340a53c9adc89475a1f8eea22554f25a04729f196ce1beb32244d531a0d3681f0a6fe
+CT = 4603c0f306298ca4d00d6ebc91455863e39955100ac625ee486057f13be57f74
+AAD = 15e75f7e0943dc621b93080bfc43f4ee7ec3f905
+Tag = 33c25cd8bddb47a1bd75479321c97a33
+PT = 84209f0f5032615996567613927077a0991150d0023cfda9e0e422fea5bdd486
+
+Count = 1
+Key = db13fe00dbf96cf77fa14556d173ebfc120324b9be35f8c5
+IV = 4f9f78178d1edad494d562b98a0e8152381e9e22f30f55c9fced5da6d35bf6a93d69f5ed50644563186f706ca0184d6cca0c1eff78b9071e798d5b9852402beab1cdd6031ff20acf8aaa1dff9b056a2b937adc609dcc34a3cd4560b2d2ff14cef58577fd79a5f724ef4adefdf8a0bf8696ab251da1c9d1ab0927f25276734d02
+CT = 4a5c13be2eaa67a5d62d16e52174cdc5e88c06401bd04baf7a5f7dd39b280cce
+AAD = ca68c1ce081d4357ec96262ed9e477329d1dc8d3
+Tag = 8c3d5f7c7f0a0f202558d0e51f3268ca
+FAIL
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 05ae5a7db4ebb55f2f445f234ec2bcacee0dede265c44c1b
+IV = acaaeaed17807a25c898cc657e951fc690ea91fb6bfec56ca8ab1a1f17ee93666cef72cbc5487e5778596434be8342decd64f18c5d8bf736115597bbc3df0c404d9537ddb52bd124f8430e6059c3bc48b2bc23a937396f0bad92d9966fd130462eb28bc7076ab107160714c21b29932b8fca29760eea0e8826fde7400e29d42b
+CT = f6c2c18addf8806ab136fc8c7280db25182d3852461425a78a9d430f8dba6db8
+AAD = a224cc3858fc7c51ee2141d00a4c2b1fccead0aa
+Tag = 9c4213fbcf453cc4fa249a59
+PT = 578ee6368ea924a0ab7f358697aa2a15771f43d4449e8edcc99189de4c7bc2a3
+
+Count = 1
+Key = e6d93ac7ce0ed433c5e0c1968b2502826cdf30410c7f13ed
+IV = 07627d40494dc5a9e4d64422639bd1023a5de3a64a4bc625638c5b90fa867c73b389e3d22bb5f164052218b48ddbe38063979336a575c1af98e172b1f180594e559eeb1dd22aa0dfa8554f93c061538b00801639a82ee1b4299cc116b9bcb55feb655dbbdc4162f95fbe4a7d6b51a6952cd89c810212c7d8b53392f51e4ded4d
+CT = 1ef9edb205f2370670da08e90e02dddb1fe03669883f1c0efe527498a9a7c23c
+AAD = 2fd8c823b19fc656048922af8385e0e1eb212cd5
+Tag = f8eecae8f06a0410ae3f883e
+PT = 2c44ff0bb14139c78ed280b252e5b6ed97cb5411ede0dd0f42436b0080f459e2
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 31b26efaf37ef4dcd95111955de944e6930db5ec089b00f9
+IV = b8098a4f5261be16e86fd652d1c0148266d3f7bf629612fc5e3e2619dab083ff484089223a83f961d112a4a88e6f90cfd13c0b48da5233411d6daa3b9b897b2ff900ad99e8f812b1bef7920f33308a3db32d67db10d219b414734c98b9256816b73327af9b044661d3d6c77d241da4da47588245294408d4b3548be9f74c741d
+CT = a02f54a533bf8c38ad3de4441c73bf7b5b1ee4276521403feb11b2dc124f70cdb5b7cd7c7b77ea5ca3746f046b3497cd9480f3
+AAD =
+Tag = c4d17efeb1ea25219f1c3ee7ee1243d0
+PT = 64e43eea6fe24fe3ce62e028bb955989e8630d505ce5534ca4998e96fe4e0a8a2d8ad8f942a8af0e21229aa455e7f8130bee57
+
+Count = 1
+Key = a0d421ab37a80783e75d608a29ee9258ef6c0efcd5db3c8d
+IV = 09451cb8e2c6e35cc0cc06859e746e83302cf96648656559a696f492ab03ea6a512e1977c2da0d3ae2d34617963f8c839a010a77a0499002a2294638c8f1fefe4f0c4235e20010db9221f563a3f61afd514ee3ee0a93c3bb6d1832e59c5fb5009750545886ed30f9a663672dbcc8f92533a083fe03e2a5680fad4727c7f55941
+CT = 8e2b6a874233353ac793ba1c78f3f72456c4379cca9587093de9e08f5e5e0787d9b6b8facf05fb8c2ae2f8d709db2192c54809
+AAD =
+Tag = 92c7ad3ca0c9f27a2b14f9da17556cab
+FAIL
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = d0327c62c42bf50e0ce96dc2f6663c03ebb5a8c411a6df10
+IV = 1e069fa5a005c147e9bd6a9ddc579c7bccb5169dd4edec81a02235f46ecc03a68d086b54d2a320de46b0baafc7693b2007a598561ca44d99cd6e0618024d7aa3faaf751ccc28dad9160283a57474038f036bb410f508e59bca860c95885fcee311b8e38fdb91ac3c02051645fa54342ed8e1a811733b0cb84696b7bbe1c2de1a
+CT = b0f58bcb2bc49373febfedfd6c5e0bafc6a2b51244ab7e7efe5dcb35608682082829d27a45520018a4dc34f5b812a15dd9722f
+AAD =
+Tag = f79ecf8ea7e7866641b4d889
+PT = 9d05dcd834a7ffd165b1929e054f223b440e818d59e83709ab45dca571a6eed268d56f514de14c95cceccd5632d72f2f35355e
+
+Count = 1
+Key = 6f6afe9610cf1dcff5c8aaaa3b7a65294e4df642a486de09
+IV = 698ac8463514d1a7629ae2e66e6a0c2641db56ff30894b0bba50a574bb5e243a84b74594c4d6ba929ed6b5566df53a3d87218096a501ace2f15c2e7823b38fb3184c4127c54ced9bb8cd1a23a5125cb5fcd6cc5bacad4120c4edf40161024639c3f74ffab44f331f62ba730d90b4f184be8d888c115e78202be10536f21f2f3c
+CT = e1c7973300ded352c7d2dbd8a66633aa0ec027e492a292f38027749ca829bb570be5f141b3470c93a649ae356439306322b477
+AAD =
+Tag = b5e5b0d881eb2da7fc6c1125
+PT = 094cd39bc84ef79165ea9c65068d3a59f0bcc145fb27c240e734772b34002eec7eca02bbf6dc583bf9650a9a2a979bf0cad238
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 74de63663fc428de3dfc1e90b121a4621bafe1c15fb78fe0
+IV = 3f83a4c5c163401d17c100b480524cdf1b9bbbdd35b2e9dae3b44daed778cc07cdc8c83147a9b73c5596d665f1e9b8045c5c1a450f3d3b1d98b359e256d294788bc5d14495871d939b9678a07c21f961922453e2751336b1e48873a1de9a4303e0febe08e046dd28615f7fcca069c99cdf652c52e26ff774605338e39bbc0ae7
+CT = dc7f7fd95af9eadbc795d15a4cf577e9561a43be790730d5ab136eaae94575d7b62f665e0ba676aaf18b34084a4e07108d8edd
+AAD = db90ef50ab01602f9594e023bc54e337c8d8b8d191f9fce05292e15877048b47de5be43b99c3408b9e7c8ea8a33c89192fd6be8506dd1ab06adc6e4c59f3de1f5449707a24ccba1004d2b9a0ce3197b0b52a5394b62caef06b84
+Tag = 0021d04e48b35732d89e10be08bd7aa4
+PT = 975b9861b00073a967d45083e4623662a26c9b87ce6436b072377d30ef6071bf8bc640fc1dd8bfd1e6094dc3f41084a80aa36a
+
+Count = 1
+Key = 2ab61d79d69ef2f67c50f1ac08eca6f09f7d6806ef425977
+IV = 83ae75f356cbe34e2edcf1c791a65c61361a0d797d4e1f40622be08fd677dc5edab70c066ef8c32d932ff4331dc25d7b1fbd77b566b918ae383cc61487851fd6a7fcd37a90bd8a17b24ac369d027cb8cce53ae9040ab22c5d1e498f9a7d61429f5c9c2af085710a56f0f474da2b63c91a4ab67658cf9296b896efec5fe89e383
+CT = afb627ab83bedd280ffdb9e08c70c8dbcb3fac772fe492dfe2a7e45f52a160361d5467ee9c52c678d102882a74f57b8cde94a6
+AAD = b1859cc11137c6e60729a6faef581832bca1483044d3bd4ff89881067571dba72ab3c425dc5fc3c717a864032741cf741be1c8bcfca9ced647433208c7dfe6bebfa71031a986155b8b591ebb2c04638e54e5506fa01ff0249333
+Tag = d6313a822e0463a8290048dac5e40208
+PT = a6259d2e3fce99b62d75bb8bca1b137794b92247492bffed4cae5bfaccd325fbed7b0ee10794dae732b071f49ebd9bd180db1c
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 73fd178cd562796f4d6e1ff755b7ed160beeb916c7bec22f
+IV = af793d93370dfa94428f84cbe9f80ecda00f610a8665bcaca57e9e23953822b9def350319a893d0928f4beda2501ba3588df29ac59341465d8b3341e32261103f360c7611c3f348f046a7bc80c4c1703f3a4ba4dc15155c033620adab1a91f4c88dd09cce6ec22386368666a76efdb2d2bca77a4b723dd26d00aea8dde21cd5d
+CT = a22663aa32e19676aa77b3ddf95bb2405a41bd5750367ccb58693ec364a5688fb4ed19453d8010841f40eab4e14d5df932b824
+AAD = f18aaee427ec51eda65dc72c80822ce80656a586fe10b9f84bafcaa59f996b3f1c27f4a5d42fea1b57ef61ab0463990f69b8f174e353a31997c78ac120c0b3bfbe6bde0846539e1eaac80b8acb6124aec6f3046dbfb947cc0b0b
+Tag = 5a73fa19e58a2ad64b96deaf
+FAIL
+
+Count = 1
+Key = ffb587200caa4bd650235fd2917d5cc4f4e2d7c396a45fb6
+IV = 1496480a264be1dbb4379739cdddb8d8e2dce2a2c94c5c2228b3bc07d12f64cd4e4e6bbf51a1349fe3a41f7ee94ddef60e137bee2c2beb06ca075777f96fc784e780a942a9dee0f9f67caf49984b31168cec7334063f0cfb9ae2f1daf290532b0f3d4ac2fb48eec5af390d2e07c06f368e6f404de84ed0b3ed4992a4fd02d092
+CT = a2dbd1a9876b8913047cfc28b705bec2eefa4e929bf35cf1d52a7d6339b44be4d3821ad092a9f51ac544e60450169eb9575866
+AAD = 4037993eaae236155e1446db421101b79e0b5f144c9977ddce2113fa9e8144c74bbf98e604785a24308e28a6cfdceb489595d62ccb3bf94812f6300a8b6cbd99fd94e39ef28aff3f74152e7f93599c211196f1831dc0e12da4d2
+Tag = cf9c5bc8d7a9cff1cd336535
+PT = 8b4c6487eec16b628fb55bb7c8d08aa4845336fb290ca5caf35ed2c9a3eb70d74f2c433783150917294bb7786ab19fc9689337
+
diff --git a/security/nss/cmd/pk11gcmtest/tests/gcmDecrypt256.rsp b/security/nss/cmd/pk11gcmtest/tests/gcmDecrypt256.rsp
new file mode 100644
index 000000000..7406a3556
--- /dev/null
+++ b/security/nss/cmd/pk11gcmtest/tests/gcmDecrypt256.rsp
@@ -0,0 +1,1016 @@
+# CAVS 14.0
+# GCM Decrypt with keysize 256 test information
+# Generated on Fri Aug 31 11:31:25 2012
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = f5a2b27c74355872eb3ef6c5feafaa740e6ae990d9d48c3bd9bb8235e589f010
+IV = 58d2240f580a31c1d24948e9
+CT =
+AAD =
+Tag = 15e051a5e4a5f5da6cea92e2ebee5bac
+PT =
+
+Count = 1
+Key = e5a8123f2e2e007d4e379ba114a2fb66e6613f57c72d4e4f024964053028a831
+IV = 51e43385bf533e168427e1ad
+CT =
+AAD =
+Tag = 38fe845c66e66bdd884c2aecafd280e6
+FAIL
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 96ad13bf2492f4675340e65b455bd0b884574f5b6c4fea774462496b8a0925ad
+IV = 2ddf6aa50c2ea9106ce0a951
+CT =
+AAD =
+Tag = 10a471540cc7bae14273f2e2
+FAIL
+
+Count = 1
+Key = b1599e78f21b175a3038aacde9141f7198c301ff80276020c1974342baad1e55
+IV = abdd25c66d7821fde6ec0b76
+CT =
+AAD =
+Tag = ab077a703bfb6646d5aef26b
+FAIL
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = a4851117328a93bf528382f22f35ac94688259fd2f517e4fd27ee9cf9b8c8a2c
+IV = 44395ca4943aca24875a281a
+CT =
+AAD = b9a63c85bd7cb93c9d2543572099ac0a0b1ab4dddbea4c75bacfab9755ae763cb1062a594dda9ca860134c74776752ad357cfda32d1c20e896370dac5808c147061ed1545a2a6ff26fe2e0e2e38ec887c1e210cecad4a8c9a86d
+Tag = 1b13e6132415fd70d9092e32ff2759be
+PT =
+
+Count = 1
+Key = eb49e7065fd7f9b49d198b43d40653a20656fc44b304a716f4c5f9fb586ef073
+IV = 1301a9d18481ba7841d9ccce
+CT =
+AAD = 71693a9e655ea0dc084a7bc9ae91a98743adcd77fa9185bd0adcb4c18e67ff752b6a476e8100bded46c7ac2327cf3e804cda520e535bc62ffe19f5f46b866d70cf99e8ce3dbbfd9f40c755859b48bdf2d967a501a58f1c739974
+Tag = 5be6d5030b8afb923e3f8ef2767f4e93
+FAIL
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 646b4641fceffe86b727cc530c49674fe5c797dc9f42ca75fd400168ee3e4a2d
+IV = 51da35627f1d60c21ee5df1f
+CT =
+AAD = 5984910515db99bc8c6eb83cef7d9f8944a78c663a2bb64e3ab7c566e79fc499c3f4923424b201934d2f9a731087812df61b8157e94a14ce69fff15187892f5c7a3e239e52462e5b6d0d872cd8e762b45dcc129d3dd4ea3e9db7
+Tag = dec7cb53d0d5fc5603790a56
+FAIL
+
+Count = 1
+Key = df49b0461a01acf9e88304f437d426a9c75d2276c9ee8798cf1b03544ee55ee7
+IV = 52f88f518dc752fc73475dce
+CT =
+AAD = 9ef85f9c82d575bfbd06ed2cd0ecef0413675fd9ee318dff60075f12488163f930b51b99b53bf5ccaf8e58f1284fba658762ad53b481608cf4481aadc2204175430ab1f38df50cebc74ab0370b6c4b563bb7fe122720ceda6480
+Tag = 9693d477780f6151ee36cfc6
+FAIL
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = aef220035cbb9e47ce605698aa28e3b0ba50b4ffcd473bb8da2017889b38055f
+IV = cde7af095360ea827778761d
+CT = bb1cdf25717445e5a77444d488387aee
+AAD = f269837306abbcee2da1722f28be35163e3d8567
+Tag = e72340deabc1589125e9e4a2755512c7
+PT = 9775db638e5d964fc9c70b5fe456ec14
+
+Count = 1
+Key = c4a274efbec1c6818e7e0ce44e4fe6ca4815cd2435995dd80ff0ac855eb612ac
+IV = 687305b573a5f56ce9d83a0a
+CT = 392bd3b883ac0705c5b33a43ebd911f2
+AAD = 9459fce3860b4823a1c20b98e7f4f46fcdc0fc1d
+Tag = 399ca7f1f6bb603c615378f9fe16e1e0
+PT = 87fe6e3efc6314bd99f56f84b11a01aa
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 1ec8d789f145854b60d7fcf35a1e0afbb3a7f1fc92595fecf71660732e044ab3
+IV = 70fcd19c5fa43155b57e51d9
+CT = ad531a60f128f0937455de379b406e4c
+AAD = 7550090bed33019135106e51984e4404226d1b14
+Tag = 7a37fd6a70a78f1a4617388a
+PT = 081ab5fd6715c606b1a9651312b8f7ea
+
+Count = 1
+Key = c6dc6e4c060f1a88aa0318c35d5c7d9c8cf1fb9f56aa114ccad47b568432b3d8
+IV = 5fbc321724e02a06065a95e0
+CT = 229aa9f49200802b63c67057d2706e6f
+AAD = bf15f99658290dbde9a32fed1c749775edb515f3
+Tag = 9bf0e07c5020f50ea6f7e418
+FAIL
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 8b37c4b8cf634704920059866ad96c49e9da502c63fca4a3a7a4dcec74cb0610
+IV = cb59344d2b06c4ae57cd0ea4
+CT = 66ab935c93555e786b775637a3
+AAD =
+Tag = d8733acbb564d8afaa99d7ca2e2f92a9
+FAIL
+
+Count = 1
+Key = a71dac1377a3bf5d7fb1b5e36bee70d2e01de2a84a1c1009ba7448f7f26131dc
+IV = c5b60dda3f333b1146e9da7c
+CT = 43af49ec1ae3738a20755034d6
+AAD =
+Tag = 6f80b6ef2d8830a55eb63680a8dff9e0
+PT = 5b87141335f2becac1a559e05f
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = f402d8b816da96a635a304b2c9310b6df8100065b631b83d188d4a1ee1efc13a
+IV = fc3a03f0740eae3e494e4330
+CT = 26c1454478bed05059e3583d93
+AAD =
+Tag = d7c6a3d3487ee42c4f02fb47
+FAIL
+
+Count = 1
+Key = db8fded42d11e66bfdb3b1472aa8403c81bb9f16152b29cf72b4a947f7dd847b
+IV = ecba3e8e8756a6c8860cd8f1
+CT = f240980cf0847cc80e2151b808
+AAD =
+Tag = cada5065cfd165ec8071cdf1
+FAIL
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 886bff628eea3114ed1c62301414327d7d565fc1a39fd27cc92560ed42911144
+IV = 147bdedaff607fc47e2309cf
+CT = 736f72611e2d132e6e1e5223a9
+AAD = 217e54b1416c1f4ac698272ba5fb95bf2e28ddfa809a4f774629db920336bbfdd9b926ad37547056ff3d8c73f0f930e658dd483b6a2265c92c594e9fd0964fa0da6d0211601387ce5def855c032370562e6c2b385cf5b9ae3364
+Tag = 5ada94656899a456638dbe120d741da6
+PT = 86a560da8d85631c31f979d250
+
+Count = 1
+Key = e7e85f27fbb7fb98b18827a475d9e436a232cb884448e6dc88fa91e7e62143d4
+IV = 53182059b753f2b8cd65d835
+CT = 63053970ac794cdcb541137bb0
+AAD = cd5b88000f5fa6ee680eb1f5a58f4b9e29b2b4447473abaee46c0100bcf47a932edfe5b06af570856e22f0eecd03e564bfd9b0e76aa7a0af7ec06670904d3788bbfad522cb2942d56298c0920844c72a49c01a383337acddce38
+Tag = d227696559f40986538278761db8e874
+FAIL
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 81f41f3d436f32f00612d6fc643ae7e629d39e07d284ea2ecbeb38394b8adbb0
+IV = c003949fec83247b4b81ea03
+CT = df1aaf1e657154f8907318a610
+AAD = 20027bcce2213e14fdc6930a941ca36622514da84ec61494cd56cb09101d40837328e701e3985452f10365849421865335a5044646309967223815fa1b663adace483166a71bc1b86324438b00bf5292b83e0a0caedf3e451676
+Tag = 71de80b9135827fa60fef4c6
+PT = 1486e6e649f98529df4127c1c8
+
+Count = 1
+Key = ba31584d7f4c722826bfcaa4d70d23fbea5435f68afe64a3dada2c641bce1a36
+IV = 7ff0475540399f032b9bd99e
+CT = f527c8627b075faa6cf13880d5
+AAD = 393ba973f51ccbf58a1324323aee15e67c8b275c3c598edd62b2f65b76c7317dbeb0161f442f8908eb8fb661ef1f2b2d2ca01779d91d8c0220a9cf5fb54fe01f5f4f901237cf12a24aed0417ee53f384a579be1f0c9d2d076d31
+Tag = 2fe6eb759df968a56b582ae0
+FAIL
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = c70fcbba915478f66315a15ffc3b11d92c24cbf213cc858f8740713ed9493182
+IV = 5b413f5dbfccc6a7c65ff5c4
+CT = 2ab2d676861b2281d3f740f637c997e25569ec7352e1767ce4c4c9ed5a6ab15a
+AAD = ee7b3521f1363c1fcbbb24c2c65f7ecee99d457c
+Tag = 9a4a3febec6413d461f26364b51237f3
+PT = f135e924c57ca538f72c700fb0c9c103a70fc1935797cfe08024397f1c1a8277
+
+Count = 1
+Key = c444d2bc6b0f14b306d7afbf9b0c84d9f2fcd2730df6d656402a184143a4eeb1
+IV = 89a840f9fede6fb08cce158e
+CT = ff15d0cdaf9b5390018a881a759183ae5cf702b9550cac2de78ad2c6d0da5af1
+AAD = aaade9efaed6435e3130b9c36d8a82d201cce2a8
+Tag = 8655bd8d3213f0873d530c326a2fc15c
+FAIL
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 7524e685058a2724365b4bcc34fb543ad6c312269aad9f636acb01a8f2f33073
+IV = 78eb27945f4466633e7520c6
+CT = 7593749905507d82598b565d57ef925aeb5be75e6c882b13ffd7b169daf07ccd
+AAD = 0a2d383fb4d57cbe75fbadf654552e8fddb89841
+Tag = 14d9657fc3e99371faa46aa9
+FAIL
+
+Count = 1
+Key = 2bcd503525b4603500e76cf0ffd22722a3dc2f963d6ba88c885c336ea0767968
+IV = 93c95c28ec095d974ec10205
+CT = d7b2e5be6922d01a5c74cfde35963240c7a5918cec61e91c6e3eeb677d4b2356
+AAD = cdb1d59ca2c2e0e63238385cfcb8651e4b58669a
+Tag = a3765f16fc46cb255e9b5760
+FAIL
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 4433db5fe066960bdd4e1d4d418b641c14bfcef9d574e29dcd0995352850f1eb
+IV = 0e396446655582838f27f72f
+CT = b0d254abe43bdb563ead669192c1e57e9a85c51dba0f1c8501d1ce92273f1ce7e140dcfac94757fabb128caad16912cead0607
+AAD =
+Tag = ffd0b02c92dbfcfbe9d58f7ff9e6f506
+PT = d602c06b947abe06cf6aa2c5c1562e29062ad6220da9bc9c25d66a60bd85a80d4fbcc1fb4919b6566be35af9819aba836b8b47
+
+Count = 1
+Key = 28ae911ee685872d906de12d7696351df8ef2234a74a95efa4ea15b327338fe0
+IV = 2fe6a815d4865181fade5fac
+CT = 1168442ef64656ef6577fb42c1919c84aae856388e4db9945bb8c9b8412bbe6458bc400444d5d2bf2630f83468f66f9e46e790
+AAD =
+Tag = b75f616fd1a3d6563b62b899e5a7e522
+FAIL
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = bd851828af0a4eae981654c3720828ca0a50d651bf028a6cd711819cfa75f4de
+IV = 7c72d4e59014721d4db74103
+CT = e4e814f0de98bcef0b0d0878a8aee9ac9fb57c00bbe26b9b4f4e641fe5f0cfa598c8cbc98e6657e417d95aa9a4062b3bf50846
+AAD =
+Tag = 83749ffe2d740f5275221cf4
+PT = f71ae49ed7acdb91b55eff7efeb3f303942425a837a56728cb773a22c7b1d3e30771cf9b4d77cc347fc3689a766c3d5af3f7b5
+
+Count = 1
+Key = e10e77757d0e9d1e9e1a6972500b915191ba28a04581a3fe77e35f905a16ec0a
+IV = 700e3d03ca4d9a94ae2a3250
+CT = 8b1ef89c3e652ad8a77f20337c38cd65d7d23c6ca419d635297176c131abfb8985a05ee4a9d55ec3c141a065c0c410d79d61bc
+AAD =
+Tag = 4d45e2fe715216f38f9d825c
+FAIL
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = e36aca93414b13f5313e76a7244588ee116551d1f34c32859166f2eb0ac1a9b7
+IV = e9e701b1ccef6bddd03391d8
+CT = 5b059ac6733b6de0e8cf5b88b7301c02c993426f71bb12abf692e9deeacfac1ff1644c87d4df130028f515f0feda636309a24d
+AAD = 6a08fe6e55a08f283cec4c4b37676e770f402af6102f548ad473ec6236da764f7076ffd41bbd9611b439362d899682b7b0f839fc5a68d9df54afd1e2b3c4e7d072454ee27111d52193d28b9c4f925d2a8b451675af39191a2cba
+Tag = 43c7c9c93cc265fc8e192000e0417b5b
+FAIL
+
+Count = 1
+Key = 8ce43539dc92ac0cae5333d1a672fdc15cff4e5b82c7571c9ae57d90b5f10bd3
+IV = 4db5773306c66e2be6c2e689
+CT = 83751e2ad6cc0c6ffb9cd5a09b2c4985cc8c29def9c51708d4b008b25719ee3db38ed8c775e0a58ec6611355520a55b6379ca8
+AAD = 944c4ac629c39e4ec21e497f46477cdcb092952cd9f7a86b499962a8aa1a246007a9f1d4cf7bdf9f477bccc226a2056b63785f397b74e8b816beb86fda7bf5a354c6caca4c97d606d463fb5cc486792069a625bdefa065b430e9
+Tag = c1cffde06139c4b356ec35b563bfd7b7
+FAIL
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 6965539ccdca3e97f17ad8eb9bb039544dfa5fee73556cdbfc6b8e0ce87dff9c
+IV = 41924fba540425003cf2ae92
+CT = 18a7635ba09868bee44a6502fd122c816f05a424f75f5b4c0cbc159523ab50484a97f013847fc5fc47e7591acc3dfce9bb08c5
+AAD = 270fd58d7f8b78ade72da1b07d196f90db853c62f4447b9b866854e2570d5c4c2dc0f17c52ce8e236ba96bfd82a8afcb97dc0c07140d5e0545cfdaa29a25f50ec11fff31c765409cec82acdbab2f5a7b30d06e85a065ad3d11b6
+Tag = 3ac26d6e1d8842a24796fc04
+PT = b118fb4b586bfa7c88ba4f8087593fb800efba76e7fdf6ca76cb9c7b5823d31cb4c882a2b658ec8ad29a3ad9e34b9c0b51f146
+
+Count = 1
+Key = 2fc63df4fa4ba9bfdb22959cc75ddcc9356c5d3e63a67ce00d054b60be33647e
+IV = 6eb3731207a1d277db7f91d6
+CT = 6c18f75cc2f98c2d1be13640a5a7bc6e6c0038a9e684bbe52425516e4c0c3cdfd4a698891495ebd18e53179388bccd58dc96ff
+AAD = 011e50ef514f7b8fa8f983fbe145dfc959e5a6ace112e016dd158ed75d63008bfd6fd323194154228634c45af9f8593dd429afefb01145a6c98b78869827c055763cdc93c47b1a47d9704e97cd70a7733174ca7d04502bf96a67
+Tag = 42ae7593632d2600d96e6b5d
+FAIL
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 0]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 3f776ff1a7c27ee003d88644754c762667371e9aae00dffd0ad0d27538ab2bbc
+IV = 5d
+CT =
+AAD = 194799ce3d54ec524cab8a41afe8cd5c2f2b4018
+Tag = 8576ddb273bae6519f83a00126c6e514
+PT =
+
+Count = 1
+Key = 9626b6ab95ee4a158ac7e4a01c06883b5810d0ee18ef7ff7894b2ee45a829358
+IV = bf
+CT =
+AAD = f3e9597246eb8557f33b83845844ce70c18b84be
+Tag = da8c8410f94b68028b69371232703e51
+PT =
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 0]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 42582276c66b7bcf2deb654c9f6b16db093a8963ef6ef196e064f36c3b09d207
+IV = 6b
+CT =
+AAD = abb9198450f4f47be941775b3295f3e452b28212
+Tag = fa6d06623d558696bc5e3774
+PT =
+
+Count = 1
+Key = 315e2572834cdc1c9784a7746f4fd119d02bd36622fd2daab2ca725b70acf232
+IV = 54
+CT =
+AAD = e19433dfe11e725cfcebcb1c12c734ed145895d5
+Tag = 446a3986b1fbf8b494a80b60
+FAIL
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = c825ebe0188d645df9044b6e7ad0bd2e7d7979f66fe1079129bac89a3ef1e00c
+IV = be
+CT = f066b20f8f3112c22aaade13fa5d2130
+AAD =
+Tag = 34b862a08c53aa8938bc3fd5ddfd5ea0
+FAIL
+
+Count = 1
+Key = be676f4f9507e719d5489d36fb65ab7f3f73db18a7124ddfc4c82ac7af18e128
+IV = 74
+CT = 8ef69c8f7114eb49e17ec3cac4c7988f
+AAD =
+Tag = 4b1385fffed281cc946ad075c9939514
+PT = aabc367c582bd72df9107ef8b85cdcd0
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 4001b994dad4f75ba93bfe268cc996337eb1dc2082cdc9b376b15d0bb6dddf34
+IV = 90
+CT = ceb9076b98f0178efabf6bb36d1c3aa3
+AAD =
+Tag = d449d75ee5b56c91f8d7f7cf
+PT = aca4c8891b86caa5bcb05f6692f15488
+
+Count = 1
+Key = 2edba3fc276d3a856b2b9d4cb613454fef1223295078b670a52a874efad49e23
+IV = e9
+CT = 5bbd4b34329e9be2351149b5652d2d0e
+AAD =
+Tag = f38f9d84f2eb06159ec58523
+PT = d27b19d14ccb114affe88fb0629131d8
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 12a66e875a13e2e3ffe5b4271bd99618e98497b1a205e984ee5baa4bb31d007d
+IV = 58
+CT = a3c37616204fc161a8958f41e470ac80
+AAD = 6dbba1ef08503b809bcd68a19117c022988db9e2893600714f576e226efcfe4e1292d973ac4d738776fbe1d7885320b130f5468594ba525b509153d4ef6ec010c2a33cb1fc1aa1cf3fb1b0ec4d8beb182f9649aeed4ef198be40
+Tag = 39840879d0d9c233fcb220b10072d24d
+PT = fc2aa0162ec9b7f43585be5a8b5ddfe5
+
+Count = 1
+Key = bcf72ef101ca082fc3be63843064b48ca2fa613472b6161e23a9604a27694f3a
+IV = 9e
+CT = fafa047fab9c960a5c636b7570e180ff
+AAD = 7ac7daf7bce96a9f114fdd79924536890b11a57373c7029dc4c44865f0c95ebf979aea534923bd896a3c6cc57d3506bc49936349d354768b3ce6e1ee4306620862431a68af9fd8d44e73c4aa224ec69472f40bd0299f223205fc
+Tag = a9aadee87bef634da9486ea6766e7028
+FAIL
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 40b16434b9b6f6a665165b525203d0597d592e12ecae0abc09cb43be19cdeb95
+IV = 18
+CT = 5f80456370c25926aca9942a56c178ca
+AAD = 126d2b78f45ccbdeecacf15cda512161fe3267219eb893e2698586a30eaefc9fb98d2c298747b509e10fe2aa8d6fd7ee254543687823d86363e63188e9fda32cc0205033c319891b3de3d0cdf124bc712fb8a734ffcefc9b2f78
+Tag = 4a19c7ab1a75af2d0e0e1cb5
+FAIL
+
+Count = 1
+Key = b390f8a5eba8d1b2ae831f48b5b8ea8b2d54133e295f57801e0becb6f1957e6d
+IV = eb
+CT = d7f2502cbed1b5644dddc23a7796381f
+AAD = 4d90314abbb6abff60f38e9b29c27001997479ba43690f896eb06569b20c0fb001e04dd1f04ac0080afa681b16192057c1b8e3012abdc520d53f22a2262990215a3ee954e37d311b312a94bad3ddea5cb41ffa83ea53c8dd7f65
+Tag = 286eff8d4ead86b419fdb81b
+FAIL
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 104]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = f8a131cf0544a39cc0c82b93ace7a09377619fe91d73b8eec79f6ebccd7b6b71
+IV = f4
+CT = d84adac8b41906144899f360ac
+AAD = 1d582097e33cd54ee6b94be5af2b3d5d3ea354c8
+Tag = 9aa549f16afdd3bf556ad26d44197a53
+PT = 0f572ae50368c95caa3abd9cf8
+
+Count = 1
+Key = c7260179792734b209fcf7a17df921d9c09d9ec80dc5141aff7865f2fb174a36
+IV = 6d
+CT = 9d1427960aea1789139bb9bbc7
+AAD = c10ac2e50db6f027965c636c79cc94c5996b4068
+Tag = 3deb7c2b813dc1470278ac30eb3c0596
+FAIL
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 104]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = c3694a62a3dcd9a1befbaeaef4e353b91c768da746a171ba821533d7442c50d2
+IV = 43
+CT = aa6009ca040fce6ce2bb6700a7
+AAD = 0b94bf672df1d940bb661fdef56ef44652695628
+Tag = daa8ad83391541c4903926a7
+PT = 52c3f2bab3c73d324e17aa131e
+
+Count = 1
+Key = a72814a99c3a0f9577260d8e4f2d74817726c180c742058b1c63d8c0d76b6821
+IV = f8
+CT = d4270342460893967319033583
+AAD = 5182c3ad2d31600685e69cbb3082873cafce218a
+Tag = 71a570a7660be8efa69f1ab7
+PT = 421c56c6c75fd8cfdd4f8f51ee
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 6b0e0486fcafad208bc5c7e91e36f5667c35bc5ab4b593cf3bc182d928583c2e
+IV = 3c
+CT = d9b46d4ebae93a3a2f28dc643357676e752252ea13fd57807b2e7a8b581e4712
+AAD =
+Tag = 5a484bcf56b75db1df505af1d0d73845
+PT = 8e9d2a27e989f7dfa232f7781dd2774528886e16fc1a69030415cd19cbb73831
+
+Count = 1
+Key = ee38f85a00776133b4b1d6ec881c4ed0cddd25e40353b1757cba4d64da035eae
+IV = 77
+CT = d0b46eaf797b95a3baaa96f85d583419ff46380fc4d2b59fb669e5842bcc9f9f
+AAD =
+Tag = 6a99431d1d667c3aaee0b783e0e1d2b2
+FAIL
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 731a9de8dc00f42e091c58d5a2540b15d68552cf98258d17d357c4b4eba81796
+IV = 0c
+CT = 4692b8d3ed38ff5fb24a3d471bcf95f8d82c63391e7e5f81e0a19e8b767fdf60
+AAD =
+Tag = aca211825f91f62255697622
+FAIL
+
+Count = 1
+Key = b6089a0871cd890b5bb22b867aa883d5bcee76749489db554f0297c934cc3186
+IV = 54
+CT = 4891582cb107a2a50a0561928fe86376657062b6dc9e44910162fe11e5156cce
+AAD =
+Tag = 8e2c111780ad59ea5ddc3723
+PT = feea762e85da23317ee181ecf116c5a4e3a57d2e3c7e1e7ec49911180b8d2582
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = e0058c8ad1ac1cf7d4f20f51726bb3fcafca418fcc604fe8c93d3ca4ac23f607
+IV = 9a
+CT = dfbd22cd1061760419f1a8b700fa62c844eb10225a0e89d00a85e69e2dad46d9
+AAD = 1e9c794eb424842a4033141c751aad3914eefc98ee24550d92bc19eb7fc00fabd7233e63ad0097a20b584759ac607109de91ae1d2c5799e0ef9fa8ad43878462a9fe2dc14597760fbfea405646ead051d96740320abec79050bf
+Tag = ca7bbdfbc8b11b5198a038d518a5e294
+FAIL
+
+Count = 1
+Key = 5481e93ed1f68552fb47829b7a1129112cc0159d312f7ce522a08806a9373341
+IV = c4
+CT = 421abd8f5296c2ca44ea65a486c370b1ddf3d241ec250681261ed1f53f93fb08
+AAD = e527b6dfcc482e21365e007c4365c9763b7fd27f6ddf80f80a7d3253761a74849233d9df542f48a1383078f77228f1922768627f533d41da58b6f7e3e0d194c6859cf4c3fab6461a816abf10b2bea655152c5a3bcad19164f5fb
+Tag = 81b2ac3e24342faba9f68677988e2387
+FAIL
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 2209436bf83afd89fabb4e57622e50c29bffe50d752ce775306445e9c7d135eb
+IV = 78
+CT = 2c4c04c8a6cd65a56b47740cb795ce448c6be3a715060db0d169c9c57d5d242c
+AAD = d87fb0ada67532525f1d01f57173ccadadca7c3bfed3a618f0d59568e8d71b54ebb77eed9c2c15816d5286b2c764df0b390b97817f11f4c804423f883eb18d36d2ab9c365820bff39eb9cd9ca174dd509a8306b74b6ebe0de424
+Tag = 5ae40aeb2daa2e4b1c5048f3
+FAIL
+
+Count = 1
+Key = 0c2453d855cfb0291d0abf2a7e2fcd11a3b82f504dbe9e75da2b29f418b7bfbf
+IV = 28
+CT = 1f6cccab0dac90719986845092fcc01eeece2c4c61c785066346bdf6a6dff28d
+AAD = 5bde8b2a74bd32cd882aa885612974c824663501b281c9d8e6c4b760419706648c8ff825bf06edd7a3651ad2cec87fdadc0fa9257401f5c3aa581891fb1c2cdeae95718ddc8eb26bf3e3f81d54bbdc5967112815cc0041d80d4b
+Tag = 18c8fd2a383a76ec8ee43689
+FAIL
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 408]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = e0ad3e02ac344794dd68ce6738e760317e8e7c79e7ed751d68c126af7de05a71
+IV = a8
+CT = 927b0fb4f7238130e624a14ec411ca2da4d6dcf340caa64146ba9a23495ff9bd219f159832d6ef243e5d91cd64f16bb9cbc0e1
+AAD = 5ef5481fb1e605dde2515bf240e7a4e9ee2bdb63
+Tag = 8d88d96c2f5c95cb0885363a76e0331d
+FAIL
+
+Count = 1
+Key = 440d6ae5be5906c4c018661f546be718f1f269b6b5f01069e630e0a1d635d680
+IV = 6c
+CT = b185ba5409e7f35b3f6ba967bbefff4aa7d38f89eda5579c06063154b4f4e0f4ad714495ef123cc9528169aca24d9dc6d0a5df
+AAD = 1ffaad771256d61f3999980472dced52796af49b
+Tag = 7acc38bbe3c74b58006ba61dccf6c666
+FAIL
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 408]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 4152bd95c23d155804e11f0eb0ff0ab19e7ba2f28fbb480371d36c0b6143472f
+IV = 15
+CT = e60a3a7499a9ac9fb6a6d691af10cf252df1dc4088d55f246cb4726c53d2cc3a2ecda7f508321a855c2530e1a5b52f381d1246
+AAD = 44491a493748be854d4079dc127584b886e877d6
+Tag = dd46e1225a7b25b7c00e4ea5
+PT = f296860cb23a7c5f250f26d1dfd884bf6435066ab0ab04b6bd859a04b07115a779b5a2da2c59e69c762d48f7329a5d108e7f05
+
+Count = 1
+Key = 3358615bf36514855d9a454e7836fc4c5f914913f727d60d6b78d34237c1ee62
+IV = 68
+CT = 50dfd9731f9a1038c496519d9a5cd7c1aeb3c806bdaadd7950282f546965d969063442eddf73249f9559b5610bed5b0f40055e
+AAD = 7f34c89fd7bec45c876c9230d8caa1bca7fd34ca
+Tag = fdc5f0e9cc159f450f2212f2
+FAIL
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = d8889a3eb919d0d45d4c6b16a31957c2aa7c6c8c3aa704709b52e3552146cd90
+IV = ee69050b106bb38dc2262ecdef82ac5954860de6d6e4086cd1f72e5a9964af5d06e21fdaeceab1cb0c404b1adbc01da583ac077cef03fc6488d7162f7d02c217265352f493a77d9637940fd0a694be8bd9322d76d301c2733c4ea23113a93722b97e5a554cc0bb30a94c09e5ebf8b46de2e8be52c81463dda7cac44385a3f73b
+CT =
+AAD =
+Tag = 53f9b45aade7fecbf759c740b4167d8e
+FAIL
+
+Count = 1
+Key = 19c1058a587b6856aa897b226701eb3ce3fad5ae288a785e393274adc55fecc9
+IV = 8f6ebfb5e76f8c09222c2950e70eaa3324de28a6fbc5ba2ae49470665d9c665da5a98288cf442c5a05a2d932efec48b02304050ef306eda20f17442d67737c8774205906d40abcbde27af644ed3b1a080007a34516d28f50afebd156642eeb2187b4c044516d2e04264f3ea0fface9488d83e5123363245d7f4cf5cae0ecd95f
+CT =
+AAD =
+Tag = 76881360934e46c36e87eb40970a0776
+PT =
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 6c663f093c7298eb54418e93c37cdc7858611eb12e5fbb82bd9a57598ca44932
+IV = a03bf161e18b628ca49f5b8712833d702e1d1619473b5eb5562f13fc95628319f092b142caa4bde3022abb67d0ec4bf10590a14627193862985e4abb22a9ae2a3f8e0fc7442eecb745ebebcc86a14b068eaf1da3a752d9ddec7f09f6aad7faf89c5deac5234f69a2da3af67497c0081d748b6c8abb6888dc7aa951c17a9a3554
+CT =
+AAD =
+Tag = 7afc1bbcc1e427f0e77f8d98
+FAIL
+
+Count = 1
+Key = fdf326903976d3031fc5eadaf319376289782384cbaeb917e2e261c8cbb044dd
+IV = b9674050a15d7f8efdc2e18f84a47ac7bd039e80c1389959361264b6b39f724813cc67de431d8198e07c83ec74354d73aa379ef463f6213b6d7001c84b2e5a91b14668fa1095e8afe1207bcf2c62a63175c73ee25b4fd869a542367d8cdb9a1c8a88f5325b09c941ef08d20ed90a2426f7e36753c094e8c93156920d5dde9a26
+CT =
+AAD =
+Tag = 0dd221d4f6b22308ed916675
+PT =
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 24070ed39091c53fc012b33c700387fad697187dea43dd9d51f3b360daa7bdcb
+IV = 1f0b9935cfa74861e93555a7fa69f99418cc531bd893ae50690469077ffa1de7820c63c01fd293515e901bd9cf7489bc5fdf3baf254e75f68f3d645b5b435f0380b37660498a7849dcb3c619357961dc0383521a93e888314913731744a6af85cc37c9ff4cabea0a2c1e6fe76afa1cae0f0fbee42095910db17e134280f2bdd8
+CT =
+AAD = 5d66fdc98f3f7a7c1b5a50f0d2be85f97adc81b4a267dd15bab41e8d3a13a2d28598b7e9ca0e250c7dde74b9d1d5c72c022db1d76def66e66410afb62e50bd1c000c1fdad67a4abdf99c19e0879790b722a13a5a141725a619a5
+Tag = ab5de5d42c724791a294e8815bff97c7
+PT =
+
+Count = 1
+Key = 88a1deb30ab64c0b0895dc718aed864ad4e082269e1a0c8ba283e8aa30070d9a
+IV = 72568eac0736ddaed81c03d9ca30b584aa3b5cb65269b606a98edcfb5984406499dbf8d2a7db3cc853f1bfafce2f0e9a7d8f5c7790a4c584169ead385af1987e8980d8a71c1690c3b44d767eb0783504c737e31ec4ea86ce7ce1ff82242f6612f4ababadf891dfd0151b50dc615588668cb29e857474f2050af6bc86d9a81d73
+CT =
+AAD = e63ff92df73673f1e4438240ad5594baecf595ffe23b0346217c8e144a68fb80337e9d918269c53fb057626ac99706ddfebdc32fb4577daee62744aeb524c04d1041a284e21562e64eb5312bdfefd85a6ba5a43eacbe11155aef
+Tag = 159d7235a01f9c2bce9abe5da9c258a6
+PT =
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 706422ba143c5397dfefe3c990fa6c549a517f9d0d21a1e727d0404a330d8d09
+IV = 40dbc0fdb6e533a982056402ed75d252153baa942261afbe7deb9f43ec94bd58246dcc082760cea888f764c0497adc0560c1fefdf89256b3a4729c62dba995851d98559ee77e06881f983810c6ec853fae3973b34591c29a7a8ac39919c66031e559cbee826be1b66ac73b11c0089b376ea0e9fd349539be311ead17ab90435d
+CT =
+AAD = b14821a83dca736f542f13bbc434c0c1838a0969274d00165cd316254d45f0b1256d0b3a6c7b31d5910386e79b7ddf815b260101000446287e787fe2a8942b12c295c48f3c7f61743bba6cf3ecb1afe2d504cb6ce904f28f1c19
+Tag = 9f4e8b225c79c1ac37d56b2c
+FAIL
+
+Count = 1
+Key = e1ddd19a5bbfe9a024252fcc009279d0d657a50efe6053c670a01091b3ed5451
+IV = 392729e24a538a6dc5021b917d19c257e0cd07b1c8959fe499f2989cbd72b609ffbbaca2a4779a0d51cc38f1794f646394668eb4155947b60c518ac0dc8d1735c74608c9b3e058eebd637f1f24eccddbb846ce31ce5252ba5eccaf6451aea17ee406dbd99dfd57d888bb4a737fa9a37b06049ac8a2d84f8d753d901cbdc5b569
+CT =
+AAD = a504e71499fe66a8c0b182b8e7be437d01a731b0420aa94d946edbef58489dabf8e6a02f6edd2e1e5441b3dc9aa83379ad8b01895caac50164251fc0ca09270870496180008eae483997027cd4b842d63237a593e9bc298715b5
+Tag = 8a6805c119cab92e8c3f6737
+FAIL
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = a2f35d1f987369c69b195ba34bc06fe560935d3501de61f0778ca2ee754b23c9
+IV = ef5a30a64314a79627659ed40d9f3de54047739e9a07b098b8a492ec5ad1ac3e09edecfd512bf0b593142eea287e663568bca6551ad8583b2a08a780f68c6eee5ff331bf415d3dca547fe9493cdcee0186550bb2c8614e16ebd81694d39702df09d7e31c927d17d4c79633c566f06ea1ea59e07aaec4becd206de480adedb8bd
+CT = 6e888304b8d6085abbcb8e9083b71e89
+AAD = e105fe7a4ead5ef5b28ae19f123e3e2543a8c82d
+Tag = 51327b208dcf074e0f52a00029f1c603
+FAIL
+
+Count = 1
+Key = e5174600d7eedb75c5a3b5e8be62b2347441d04bd6588b84e47918609aef8883
+IV = 49d5138d0571178de7b239c56a3549eb18483b1df92d1bd5d267ce0ee51b15820d8a24559d7ced06fba62a2c6005e7fd96772d527047239ef278b1b140697dd16b7c3befcd4b15211305827f38aa64ade811e152634765b542a65040d85c6885f6a472da26594c1356f95a8fd1af0c883626bed4f9023b716f5c1e38be210445
+CT = 10765210f9066bbf141eed5b2654ea0a
+AAD = cc546788a6bd048711a93aa693cef2d9f74f9940
+Tag = 6337b8f0295d8539b9d746632ad2940c
+FAIL
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 30f3d2ba0b4c8259a6f900eaad2afbb283aa3cfda2ad7a1d80a4009fe1e18bb6
+IV = 80adfec2d4d8fd8ec4cb8deac3b2201d243614eadd43c18b289e99dd69a13cd811b660dfe8ef5cadda57763e4fa3a6ea5af29c898cb18da31a10c6aee2bd54f5aa9dc40db9d80c4be8693898e3cd9c1b8cd2180370d862ca094db9bf927aa97aa3995df4c966d5e29076747f501867b6a543b75318212e10d22a6e17d4ae1a30
+CT = 030ec395d19d9cae7b64ab93421c89b1
+AAD = d6109bbb723e2d896c82afe66a2db52b76d7d4f1
+Tag = 54c33117ad594bb792a956f0
+FAIL
+
+Count = 1
+Key = 27af2dd86f21db66f31a00d7726e9a64f5852bdf846f8acd1c15a6fd0a5c5f8a
+IV = 851acf249daf38a4f705bc053ac63eae37be1c8cdb820d2eba1eb7dc900db3237f7ea583a925c113969a137c7f20c755d31a73f8b3e758b52aa7dc56acd199607638059d666d7f1bb9c1a1d770859b064572d7b17221c08d920e5e3f3e14d1425cf34e128d4ed4306d8c8f37bc28f965f29160a368ecad9035162e125bc99be8
+CT = 177b99c6038854ed540afd313b9e04cb
+AAD = 1a83e839285d1b6cb48021d645bedc94d58d8d3f
+Tag = b29830271385283dc6ad8891
+PT = e62579bee002bc2e368b511f90fc2158
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 437b8739a582f162f558a947a30b0f0964cc742462e4d54d9fc3188f524f2e1a
+IV = c6916d0b98c5b036be2d26ecccee4f83698ea188bb9addc0909f0eaa1362de71afe6f0dbb2e830bdd5ceaf3506fd7997622a702896a815d842a1e38c47d8e7efda283921f96dcbbf593cfaeda4adf76fbdd9a9c1c181406da7c8bf64196b2f24a5587bc81303eeabcea54e1205c0899c7fbd80249afb86a788f11797d45b770a
+CT = 806f04fde04c24eeffcca79db7
+AAD =
+Tag = 1be4dd6c4b0dc496f5b520066ac092ef
+FAIL
+
+Count = 1
+Key = 60c01a94489d0b197c3eddddbc3827f3745963c0ac3924d6f3f0521aa553012a
+IV = 8fb710642df085b938fa55d90c6d9fc9fbc9759cd0013707d4b81ffbfd34e948b95b478dc9769711f519eaeef959fe7ec95d089e7d6e4234d945cdc7ca6bfea9b87aeb5d065b3ae95997970f273e3ef3a8cd23e1f2439302148be425da6e936771534eb26f7dd32dde2f72beaa3bd3d0f853a459887c3f226d372f283dfd4533
+CT = fac5f71f800ebe4aca4d06a539
+AAD =
+Tag = 63b121a9efc76792d41550457f5aa2d7
+FAIL
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = cafe97430cf59ebf0445987fd1ccd152ab8df7cc5be169e77812181d7cc3b0c7
+IV = b7e5f323f84df4a094194a2c6331b25542d5ce36b199d5e54decc7b155907a6dea622cdfa3d19359581525a9bec7a9d58a2ce9a2149fd61f1633062da83a88a368ee16d2ce8c5554cb3192867c46738ed0917c712ea88b0554dc816deb5a0a02a09287a04f98293871e0517f67e5d35726646110b03b8df3d36904fcdfc759f7
+CT = 0f6751b5fa29c70b848306fc9f
+AAD =
+Tag = 19e3a9bd3d97ac6f27e587a3
+FAIL
+
+Count = 1
+Key = 6ee4af89a08ea0f360e87a953cd5a67f2dc2a37fc52b756784e09ca2a581fc04
+IV = 0fcf4ed9ae002eeb8b93cc09df647b5f88a80b3c1bfb86a7ada87d348e23401cf725a3897654df85941c06165c782f2f01fbed4643f07116c3689dc3160be98976691ced253e066472dd7ff0308c06a4d114030002b66e8ab18fdf389feed212d63c67153879edec4d75a4fb5c1df26084cf07f3651177155a0728a7363ec4f3
+CT = 7f9b4717827d517ea978e24897
+AAD =
+Tag = 72eff58a805947fb59527ed9
+FAIL
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 252af4cc7b1fcadd3d7cf447f56c65661783eb84058c1e19424590b53d76112b
+IV = 172f5fc3f7b4ed7f905db3ea934a8fdeb398c8807bf5d804eda55cdde29d88ceede0dd00e198c59548ff5f6e551476cede090f27c873bc7204bebe69db7009336f112c37b91a9f955233aabf2d0e4c5463167bea3cddd4b79b36c1abdf71e38c09e70f952ee138a854cab3897f294d54408866d925e855a108f28ed1b74232d8
+CT = dc534a48719af2ecd0849cfd27
+AAD = e1f4d8794624df8f5af5f80d1276283163dd2fe711792c5e361d42dbd543029c098a9c06f2fcf8015a1659ae32ba88c4ec5405a2632b260971bf0c89d3f3dc24ec7a31530126bb66fd2b1964ac0043fc13b38dbb84fc0b523794
+Tag = 6aebb466d5d4bc53db23bb68e4269aad
+PT = 731df3c7179b75495d6c2fa457
+
+Count = 1
+Key = ea3e43c7eea572f2a1d8152970724deea0b5c5caffe54632f58d50e8e75a314e
+IV = b01bd5f10855d76b03afc274a495d1f693b51d84dded9279a4a12990c30a66e3be9869910f1c3c579967a50ebadf51d7011907f2317e813c857bdb29dfc4c78cd60ac4cd6d56820e2819c0ae0066c6788d78bac8ef3e2c65daa2d27b41809bb25ce173764f16895b48692bf2d329b26adafd72d684eaae4f486f507f07a8812c
+CT = a37b77fb9cfc80f4573b5ea0b2
+AAD = 3d8b232ccaf8e4eb547ffca7edba77b84f0f3a1cf29cc1f311a7eb636a550daded231299ac023b0cc32073d777c0fd1895a4eac29569bd400ec997a6ed34e6b9eb15ffcd27070e84d0ba7248216b371c83a93dd48c9f6c7795fb
+Tag = 7ef16e4e0387151be5ab87082fd41a58
+PT = c53ff02d0f1618186b94568cf5
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 72b6371844ed784c7635eb2716a91ec5d1a0ff56d436a75a4541cc2fde91dd18
+IV = 02216e5fd7d679620793303dcb1bdc4bab145bbff07d5256e0ecd03e23659aa3d84a1d979d4e025aa6e67216b6812e9d53aa1bd8b2e10c6e2712a9371b27476f1948d82f4c00df4c4d0b837a9587c195163027dc534b13eb1919bcf7ca426ab698dbcebb224cab23308eb1592e194b814d9aaf2d9b311cd234f9618bc8d8a62b
+CT = e6f13a3966d5f67954041430c6
+AAD = 925715913fc78045febc8f5e13ab3581ba8a8bb7d63a9d90ad76c51c8254fdedb74cc4f81196a5aac0e384c8a6ae7a0f98cd3d5e4b14d58e3c3a65f54ff030b367935209da7e3e7d6de3bf2dda4f801c0b0ca263dd93327a9ce1
+Tag = 4bcd2c418c50d5f7b86a1c87
+PT = 46f2bf732507f52d766bbefab7
+
+Count = 1
+Key = eb37fffe28a709c69998862d774f1eaefb462d70ca724a75f1bc18524210b8a8
+IV = 40844e3e078cab390407157fc975490a683338c48ba313579784343cc3f586fc5e2acee36b59b67bfaee35f5980340c0f0c7cc8702389ec3f00f19373fa5aeaf8771f5a5371ef928745e603fa67ac6249d9898a4ff2283ccd01566d647ef77b343da75e6d35ed02e1c3134893e44636b8bf26d97441697cbc4b4f261b6de7be4
+CT = 6d3b7de3edbe5a4d2dce786026
+AAD = 3c21ec1fb8d71ce6874c90a2b2ad207dd08632da7e7d2c934c8f05d8e3b65b3cc8825dc32b1890f9b586f9a3cf06781a1f577fda48f036d56e0588c643a39c987dc50c2bf6d5c7e92f5806ec72cf7ead18e7a02945b8e15e4043
+Tag = f5e12b6302a5280c93cbeb06
+FAIL
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 655c77f205c07b92bdbd8f085d652c9d4ba825dc5bb62eb0093fafd149ea6ae3
+IV = edf94065be8e25b8c59ac9112348da44817135d2db46d011709913718b784c800ef48267ab8193ef30c933fec20479ab018014b2e9a0300ff5bcc1070fb78f4bbd54cabf5f0bf096ece45f30e210ee4805de26c286f6b155432d2a88eab58898bfea15a64d72dfe76bbbe068d64e9ecb8c2b6463b595ab3deba79f21658bc609
+CT = fe2427aef5a420dc1ee37798007b59cb9d0a838df1af86b2e96f2d3451d4dddc
+AAD = 1104f621608787d8d0f65cdab10333eb597f1461
+Tag = 27eb72580097f5aad0fa91f50ba6f5f1
+FAIL
+
+Count = 1
+Key = 8307e3c68c0761e3ac4df14bd9166d44bd8ebc2fef255a61534f1e9df5278d93
+IV = 492669cb7099e340c31353faa1a96f1d43ffb39932c9370f5d119f4f5083b00ad2212e2a031a6e3ae23e98c5794b62741b9110eb85730e3c2e2ba1c2a3dfac490f18d498f466d0d793b8cbb5a5e8e9d140a89f1a2afb44afc7cbeff37d77e85852e51f84f9b2335a5243c835bea7adde286c4af0a90b6a553ae10e978e5d9b8b
+CT = 335875922c6cd3a84946ea961a06e90cbe74413a30fe5657a6bc845b25e91c44
+AAD = 17100c6e20d07f69fe1b3778c473417e299b4e7f
+Tag = 687a12d577694b096d81a68f49d6271e
+PT = e9b40cb4446bfa11f0f24c014cfea23c71e5f87c413e44d433777f33b30ebbad
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 9648ed8388ab79fb328edb50d7a4f433677c395b5d40bd186cdbf52d9e153fd8
+IV = 3c7ab72888991252c3eb78d48c4ac6cecd1def6fabbca666bf3abdee30d71688356ecf9a40d5e62c9bbfeefab6f7f539a0de07fa31372423e0f8097d0d49cf7387cdba0dcc247d2279bf564a0f313c72d9ea503d5df6054a95c6584ff4bb9fb4e0a8ba03dfefc85ac782b7920e598292016d2b576e8038fc564065619dfbd6c2
+CT = 25e66caba006543164858f03adaa9a0bf273659c9ae20bc7ad800ab9367a7d6c
+AAD = 763c19f15de186da96bd517124dc012792eee267
+Tag = 7e221eb78bff1a3acf2ccc18
+FAIL
+
+Count = 1
+Key = 1da1b0ff950abf7e68bb15c2a8aea3add33fed93e170c09b17632189ab9db031
+IV = e2fefb6f3c258598415748b2165ce187f96a7bbc04a3445b619ca2361c1604e88c921f1d209b2a57422686c2caace123f01ab65a9edefc304ac50911dca79c5419effe9151df78228f223f087d4449e4de63bda10b28553d5e968a033334e716c575442289b6dd077f40494ce5767517f7043a71b4030a110f4a53d1073a320a
+CT = c90a0e9f2d498a0856dca24c4acbdc8774b79643677d644ea1e135d8101fce33
+AAD = 2ea4746d16cb9088aba6cfd2beb26ca49c9551f3
+Tag = 5513db7d90ad3e77f8b21204
+PT = 7298e7e9ac4fbb933db72d996a2cb490deaba35433e14a584a9980fb9a439eb2
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = ab2e6a474f948e0f80de2b2342d89c39518f05308c4b4b5e87cd9c6642153773
+IV = 01be55437efa82c9036c797978b747469ef6b4abd5b495ca5aa817d76c7f55f4bf360a11042a3d17e8624cd48d9ef6bc9b2db3034fbcc2b6bb208dc6876c9afc2119b8d346d38ce3fe61cd1d119c25cac8173a1cc4053456420a8a56f9c1a752a0fb23b386b8267d411603568dfb7e254244b5b901b84cc212a0d4a79d95fb53
+CT = 97ce2f1d4e450d791a30d36e9f9df190d5cf9714b01c3d0562edbc35d7a6cff2f8758260426fc993fe58bd3b92d2040f187331
+AAD =
+Tag = 4ff61cb030c0af3a2415ba5da07c0fcc
+FAIL
+
+Count = 1
+Key = 94ccf0279dd20f5a292f0aa1ac58e4821c408bfe5d362d81bbe42ba4d586aeb5
+IV = 3b76749d090d983ac602a56a7b845e755b2e7713f8bea102921c3d5644105dcdd4c44d6d7fd4118555ca25dfc4516a9a43a33edc309d8c3a94c6e2014780daae6ab4be4208f2d86bdad3d533d07bae383073be27f235e624fc75ea9ea38868390ae9775254d9a6a3e7e82c7f7f945c3820c696c08ea7155845630a751d2757d1
+CT = 141251168ec7cc64a84816eb390c436cf54a9fb1958436077f3ca58695041c28a32c51cd0099a2b59159645e319cf8b2a3a348
+AAD =
+Tag = 7854686148d36addbbfe24b752aca26a
+PT = 0f7962ee0b74fd2f759be781dd399845ff7337dc690286d86d5d80f66261aaf9bafce9e86012f49ec44b20f3bca064247d1d03
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = f4a29f6d975f2ce0cca4e9a82a40e695a7793883e103f639ebe2e070d780f35d
+IV = 63366ff8a10805a158e02a91885507a3b4afe61b578231ba04bb1614498c83edb82f888258f241dba4d4339a99d17d854275ad446a76cb67a7426bd32a8bd1ad1f060c4a2407b50c585373c57ef227a067ef7d74382f411ff903c0a728b2503d9de2e7cda0900f3dd47ad2265fd54d947fd679beb60a698631a61320ca64eb60
+CT = abf2625f90886df52e7d851e735e5b31ed1720aca3bd80273f666956a59e320bc975a37fa3fae24bfd807301d08a672e9047fd
+AAD =
+Tag = 53b7bfd200a6088c01feeb57
+PT = 08a2fe8d970c5789bf010779fffd5cbdc2819386ab5af5189d5ab5d41b10372347fb2108fa3de883b13cbe4eda0972804bcad2
+
+Count = 1
+Key = 2d5d46727cb754321d46d5dcc4b7ab20e6c870ee58c7be1403b6238615f41c3b
+IV = df376c1a1f4d1dddc66feb9572b39d9e9fa4c57b9bbea6072282662f3327489142564ce4656b9fd91d2f78d091707bd3042b9f6f9f833990501d57abd23a8b0e29a427d6ce368d673b7c4fc7a9c8a2ba6e7e22bae5def376d8a2c5ac974f2845c3116bf619f385f57082ea624df17c690b69aa74666b34e3dd1b3d14408ed4f9
+CT = 23d45d59069441e2a26dcfb0cea4d1a158226c1e4d8389313277f2e9aebf6a178790d6e1589a12235190a28b67fb4b79b707f7
+AAD =
+Tag = c78945c9e1fa6598fcbd82a4
+FAIL
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 871ad37eebc6847944f7e42fff5a65ae62c50854486f63c08f6080f83c08d66a
+IV = f91b2d31617e9a52042044f57037b096477d90e6e9d6f40f6762ea48fac5a182502ef940d3d4c86a48f7e7c2c8d6ba55ddb32769dcc31010c044a80fa44f201cd8726270d6f70ed01378abe1d934d483536ba608e72381fd15234ad14c5c2cf083c0d070228342968ff5f66d6f23951c54c7f79c82e236e5517f264eaac093c5
+CT = 02101f8482052cb7706800e8310f5d444d672b6559de0b8792d7c64cb1bc587dedd631592ff6e9c8fa28895d36859b973a7224
+AAD = d5f7c1f68965d913abc6bb01b33d35a317a7fbe7ba2e53c73d6c44abe1c2160d545d2624f25450ad7513b2d32ffa8578c30e96d7ba49b3634d99a15ebfb37decd0f8efc32aab40a0594beba0dac6f8daa3ace91bd09549a1f5e1
+Tag = cc4d950b8c3330f048e3aa3e3cfbce21
+PT = 9089425f0d9d17516465990049f01a2e8e5f91c2faea8468973606c12b507ca072818b4fe2d611709638d21e034dbcdf47cf59
+
+Count = 1
+Key = 30d75f15b73361f062bbdb12a584b004b740e2fea40e49ea9686fa9c7605d139
+IV = 8ae19b2e82dc6ad1d07f31cc7cbf14c508e493253e86d649cf2d0048076cf2c59f1a769aa2de652aed8072d816ba6604a24f6be134c0d858728f8088b2a04337c103456c805e4b8efb1fd988fb66252ce2f0daed849b2d871560227c319bcf88446565781dda789f5c65460288c10e94dc0bf4ded61dfb19b331764845b362e3
+CT = 2cf0db85fc93bc584da1a4d95e30bb0e7ae5caa8f309f61d4ca4c759ee260777240855478fdd91ff859613077ed6e0f8235018
+AAD = 9b51b73e0c027725380c2e92dbbb30726c1cfa5ed8673382cb00c455b066f19d99c08002cad02734760ea3dcbbc08af59bf0884ede09e864aa5b35237c9dc9e57e367c4e247a136b4332a9958fd3ce103ab17fed5e76facc8c31
+Tag = 468c4129010a2d8164e75d957f518248
+PT = 7634ce717396d24cc5a6e3568310afb47b8b613f856c095672a598b72ba7b4204d1d886e99be78e42adf39c84e91b433437d4d
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = f74e8cc15bbc6002a47764bdb2c8a689c0fef784c83bf20db5b6e98f67c96023
+IV = 93574c8364c7553bb798ad6fadb689dd8d05fc251d8957e9fb37b7ed515540ee28406c1e34be4a35ad51170bacbcd524d466345af6f2ed7cc05bdd3649f7f30690a6f20447c464c4871d8de57e73fcb5b65dd89ad062b51010c453776b629d2f8cffb1547637de4407e7db20b2a9d2a363d2f4f3612d7bbd7df8f5622542800e
+CT = 6c969bf473b092e714ce384391ba9945cd513284743af384a7ff772e61c3067a3b2f64b366f73723b9263f9d30458a5acd9ef0
+AAD = 3f7c839a5e148ee440c55918ddc63b875c3a44e1df37abf8921188af269530afbce5fbf4a334ea5e71d428f2296d0742f1290fa2565fb3d7e8fdb78ca5954cb942492f1c617ef3539cf45bdb5830f3c7d0c95adf0a054f810e8e
+Tag = 02fcd9d624b3c6a3d2e709be
+FAIL
+
+Count = 1
+Key = 55680523b7056ac2c365393b9c7bdff3df75528e73baf67ffa615323b9e84543
+IV = 9369d44147e81bf35716e813702f67435d05901a16ff3540767c33db4bc6645fa3e3b144d7ff04beb2c086fff6b09190f101c5abae2bfb34abf893bceb2f621d29618e7a98f1ff53bc7033cac9f02eb84a5c9e91cff333448e8c4dde6b35327acf8c9675be03dde136ab1d91d02012af5c53b73c3a75c9e4c0e535bcc86a4ac6
+CT = 950931ba46c6c29ffd54f49eec850a5ce88a6b97a8d16ee36ffa2dd7b632250d140f4c2c265e06efed3c2a282d60cfb8158f31
+AAD = 78b8d7d0c2a6f368fc28e274054f65e08fbc1208233f461aa61bae6952952c0e730cb756c7d07d175a8aa58ca97e54a28f0d881e39f3d4c01f5c586f14254ba1bb2c9f829fbad1a4b270bb4f5a18fe0d8764d01bda85c6438d72
+Tag = 8aaa9e6b012f5ca26dd237a1
+FAIL
+
diff --git a/security/nss/cmd/pk11gcmtest/tests/gcmEncryptExtIV128.rsp b/security/nss/cmd/pk11gcmtest/tests/gcmEncryptExtIV128.rsp
new file mode 100644
index 000000000..e5ccc3eeb
--- /dev/null
+++ b/security/nss/cmd/pk11gcmtest/tests/gcmEncryptExtIV128.rsp
@@ -0,0 +1,1016 @@
+# CAVS 14.0
+# GCM Encrypt with keysize 128 test information
+# Generated on Fri Aug 31 11:23:06 2012
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 11754cd72aec309bf52f7687212e8957
+IV = 3c819d9a9bed087615030b65
+PT =
+AAD =
+CT =
+Tag = 250327c674aaf477aef2675748cf6971
+
+Count = 1
+Key = ca47248ac0b6f8372a97ac43508308ed
+IV = ffd2b598feabc9019262d2be
+PT =
+AAD =
+CT =
+Tag = 60d20404af527d248d893ae495707d1a
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = b01e45cc3088aaba9fa43d81d481823f
+IV = 5a2c4a66468713456a4bd5e1
+PT =
+AAD =
+CT =
+Tag = 014280f944f53c681164b2ff
+
+Count = 1
+Key = 6bc071acca8545c4f9e033e328bc1534
+IV = 068757f06776662b59afaf35
+PT =
+AAD =
+CT =
+Tag = 9f44db9be016de5138534d32
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 20b5b6b854e187b058a84d57bc1538b6
+IV = 94c1935afc061cbf254b936f
+PT =
+AAD = ca418e71dbf810038174eaa3719b3fcb80531c7110ad9192d105eeaafa15b819ac005668752b344ed1b22faf77048baf03dbddb3b47d6b00e95c4f005e0cc9b7627ccafd3f21b3312aa8d91d3fa0893fe5bff7d44ca46f23afe0
+CT =
+Tag = b37286ebaf4a54e0ffc2a1deafc9f6db
+
+Count = 1
+Key = 7aa53188a9c597126a10d248603ebb62
+IV = aa45ca5dac41a825c45d36bf
+PT =
+AAD = 417fd5147d56de0c74329597824ec2788a344fb60b403edf0187afa12e72a05009bb70f83ccad11efa487c1965cf84feac067c1ffdbf531fca97c554f875c4a1a1d3ab3c53c8a74ef3ee9415a87e231699c82d764debeda18132
+CT =
+Tag = 997bf84654bb9616c0cc9b45f82c7673
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = d3da4c1b8a0da47207ee9384ce85d123
+IV = 02e07988f6e899465e64413a
+PT =
+AAD = 5ac3c5f477a5486ade9619937c0b94b4567a6810f37481f08070cc7f6c6b83887b3f3b67511ecb01e94833648f9afcc7be1d30e75733f158e34611c95fa735678e3e20ddbef118375d25ac8f5abcf14329289ca5b8be04e051e7
+CT =
+Tag = 0463ea5b69c9029fa48de21a
+
+Count = 1
+Key = bfe5bee51771729a8d947bd26bcfeb30
+IV = d9960803dca431e61bb10a5c
+PT =
+AAD = 6a958607ed379337eb88689b31b24d2d2981dfd020f8d5c4e264aa79137bda9d393e5b520ccb658d5c77478a87e343cdbc0f4b5561331427758eec6d186016a901b047e0640978e8433313a856d00680f77398faf4300a26a769
+CT =
+Tag = 84bf81b96e54321df209250a
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = d4a22488f8dd1d5c6c19a7d6ca17964c
+IV = f3d5837f22ac1a0425e0d1d5
+PT = 7b43016a16896497fb457be6d2a54122
+AAD = f1c5d424b83f96c6ad8cb28ca0d20e475e023b5a
+CT = c2bd67eef5e95cac27e3b06e3031d0a8
+Tag = f23eacf9d1cdf8737726c58648826e9c
+
+Count = 1
+Key = e8899345e4d89b76f7695ddf2a24bb3c
+IV = 9dfaeb5d73372ceb06ca7bbe
+PT = c2807e403e9babf645268c92bc9d1de6
+AAD = fed0b45a9a7b07c6da5474907f5890e317e74a42
+CT = 8e44bf07454255aa9e36eb34cdfd0036
+Tag = 2f501e5249aa595a53e1985e90346a22
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 90bf5dc928e91cc2f05f8c55dc1ffbc0
+IV = db658c4362e7d6a03faa8492
+PT = 99eac872b13b623f255bcdc0eeb1c529
+AAD = ee192a6b71e57f3f2b27efc9b1cb385d6c1be0c4
+CT = 93d95389595d76131b8b763e50a5fe79
+Tag = 0c37dd797b78bdecceb9c2a7
+
+Count = 1
+Key = 2c71838088181a6e222bd24da34d812d
+IV = 2fff9e8249fec06b9540653b
+PT = 559af4c059e9f676b2c7374328783d09
+AAD = a8306774375070242d5dae26c8af46a82dea2320
+CT = 3072e185e4b18114c8b7ff2f0c61daf8
+Tag = 128bc57c445789b46d93ee59
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = fe9bb47deb3a61e423c2231841cfd1fb
+IV = 4d328eb776f500a2f7fb47aa
+PT = f1cc3818e421876bb6b8bbd6c9
+AAD =
+CT = b88c5c1977b35b517b0aeae967
+Tag = 43fd4727fe5cdb4b5b42818dea7ef8c9
+
+Count = 1
+Key = 6703df3701a7f54911ca72e24dca046a
+IV = 12823ab601c350ea4bc2488c
+PT = 793cd125b0b84a043e3ac67717
+AAD =
+CT = b2051c80014f42f08735a7b0cd
+Tag = 38e6bcd29962e5f2c13626b85a877101
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 60f2c7ebe9d736763e58b4a33411bd1b
+IV = 75528a49a96a2e889d18d2fe
+PT = d64aeb92c924c4621577e0ae7c
+AAD =
+CT = 441ff603ae77d1d6147aabf179
+Tag = 934b415f82e8b80bc83a9d8a
+
+Count = 1
+Key = 73777be1bb0e5af52c05aaa1244f3ffa
+IV = 43ca61d808da919290b1db88
+PT = 28879adf3396b98615c1e9d993
+AAD =
+CT = be519fd784b7374e811be76bc4
+Tag = 1904a842b644425ee3d96a55
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = e5b1e7a94e9e1fda0873571eec713429
+IV = 5ddde829a81713346af8e5b7
+PT = 850069e5ed768b5dc9ed7ad485
+AAD = b0ce75da427fba93da6d3455b2b440a877599a6d8d6d2d66ee90b5cf9a33baaa8329a9ffaac290e8e33f2af2548c2a8a181b3d4d9f8fac860cc26b0d26b9cc53bc9f405afa73605ebeb376f2d1d7fcb065bab92f20f295556ade
+CT = c211d9079d5562659db01e17d1
+Tag = 884893fb035d3d7237d47c363de62bb3
+
+Count = 1
+Key = 1b96a8699f84058591f28590a5e63c0e
+IV = d437b28673240ddc63d22d2b
+PT = 802192b9c2d78e1df9ac223598
+AAD = 0f985a66d350c153a4882d0a4fc6e1b8b8450cd0825182358521b1be5fc734338af72a48170fde7512a8a92ac81d12e3a7fdcf7d98933732a9893d92d9435fcaee6033b726d28f73c5f76fd6b93d13bc8904d11cd4a713cd353f
+CT = 8c13cded61d08c1f2db878378e
+Tag = 43ee877c121d4a329e81e51d68a9d845
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 0ef21489e942ae5240e41749346a86a2
+IV = 431ae3f1a702cc34b55b90bf
+PT = 882deb960fd0f8c98c707ade59
+AAD = d6d20f982bdad4b70213bbc5f3921f068e7784c30070ffe5c06f0daa8019b6ed95b95ba294630c21008d749eb71e83e847fb6ca797aaa3035e714cdb13a867ad90b2ebaa652d50a5b6adc84e34afc1985449f45eed08cac3cb34
+CT = ec8fdf5f4afb96ebe0e845dc3b
+Tag = 45d4b03158be4e07953767ee
+
+Count = 1
+Key = 5aede6f412af376fa8f7772b478f8832
+IV = 1fc118659cf45fb2d175fd92
+PT = 3a27c27f50574f46816c518235
+AAD = 3a06bd01e85343e5951c5168dd69a741c736778da474adbc2709fa140b934ada6493b2c649778ae5bdf23507e5f2f55ae15c2906331cd94eba9811439920fc6298d3011a465083a6e96e411393f368cacee553cdeee8770120db
+CT = e9436a5dfff5c79044a68106dc
+Tag = 8e989c4b567fb918928b75ad
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = fedc7155192d00b23cdd98750db9ebba
+IV = a76b74f55c1a1756a08338b1
+PT = 6831435b8857daf1c513b148820d13b5a72cc490bda79a98a6f520d8763c39d1
+AAD = 2ad206c4176e7e552aa08836886816fafa77e759
+CT = 15823805da89a1923bfc1d6f87784d56bad1128b4dffdbdeefbb2fa562c35e68
+Tag = d23dc455ced49887c717e8eabeec2984
+
+Count = 1
+Key = 8bdec458a733c52cd994b7c2a37947d9
+IV = bf8d954df5f1ee51fc3f1890
+PT = 9d5f1c905df900111f2052a60913d8a9d83cd40e43ba88203b05e3dbf0e37fbe
+AAD = ffe26874a54bd38a026c5c729e2852a748457412
+CT = f056cf8ea6c4f353f08d54c27a8ef3324ab927a641563f9f5dc5f02c3b2204b1
+Tag = 2f8b9351426363f09f5d17f634a381a9
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = b4ad9a826ac50d244102f1f8ca9142c2
+IV = d7dd062d0981faf163f5e1e1
+PT = 06dbb7f7e3162f1014d1f63e02fd0240c87d7735229e5e4ca21d26335254ad2f
+AAD = bdbee42acbbc5efc021dbea63f7df5271763a75a
+CT = 3fdb1e150bcfaefdf74a30713d0842eadeab1e80149313fcc5ffda703c1ed4cf
+Tag = 5b1cf40cd64ea5a49893f7ff
+
+Count = 1
+Key = 53fc4bb58a5be78e3f4e13542b9fc757
+IV = 6a3a5ab3c572ee0ba1891971
+PT = caf1792e54e89a103c2504ad99340ac945a5e9166a959751e7663bcab590633d
+AAD = bac7adf6b4e8271aa7f870b06b1b46443ec01df0
+CT = 522ab5f721045cbc65a6523f766aee97090bf7020ca3c269e79353ea15b04732
+Tag = 62a00bc0b2ef3a17884a44af
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 594157ec4693202b030f33798b07176d
+IV = 49b12054082660803a1df3df
+PT = 3feef98a976a1bd634f364ac428bb59cd51fb159ec1789946918dbd50ea6c9d594a3a31a5269b0da6936c29d063a5fa2cc8a1c
+AAD =
+CT = c1b7a46a335f23d65b8db4008a49796906e225474f4fe7d39e55bf2efd97fd82d4167de082ae30fa01e465a601235d8d68bc69
+Tag = ba92d3661ce8b04687e8788d55417dc2
+
+Count = 1
+Key = 7e6a5b6d296ac7a7494b72c93bad15ce
+IV = 5225c255bc82949a1cdb86c8
+PT = 8bd452633f9dae0639fe0e67e36401adf65b3edf6799ff9eec80d85c13c85e0ee09491d4f5acaf8ae920281801a2f5d12c9370
+AAD =
+CT = 2348f512a3a8501be9eaa41d8a127fcd8f0368d5053981a5626f85405363d218af7ba52a2bdb87a1ff07329f21792f4c64fc39
+Tag = 8753cee020ac668e9e1a37f63231543e
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 9aa701eaf1146ae9a8aa14f36294e8e0
+IV = fd78280e023ff4cdcaab5e67
+PT = 806f21e96bcd6c8ec1b7f688978c0ffd24492cd38eb62361fd73eeffbee4d9f9d7ad32d408ffc6706647bc723c620c83020f06
+AAD =
+CT = 010428fc5b03162f7e001fd2f4f2d1a8ab13ce97063c82cfe62e7cd5b26551b03a55358857159959ab021e7015f370b6fc1f16
+Tag = 87b981bdd2c37fcc6ff734a9
+
+Count = 1
+Key = cd02e8d9a48ff796b463ab3e770d2b25
+IV = 53704bfc548f3615141d7320
+PT = 90ba42f27c1aa89b07fc59788e13ab813c9d85c9232c1c68b486b9862db8111c2517e546218a259497866722ee818ce813ca6e
+AAD =
+CT = fd956ba6be92cad86a7cddc5f9633a50baf53a53f6674e578dc36a8dc5bcbf2e32e28f7aa83b4f9a59b1dea60ad8796b37f460
+Tag = 77c940abfd23724fa816015b
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 2c1f21cf0f6fb3661943155c3e3d8492
+IV = 23cb5ff362e22426984d1907
+PT = 42f758836986954db44bf37c6ef5e4ac0adaf38f27252a1b82d02ea949c8a1a2dbc0d68b5615ba7c1220ff6510e259f06655d8
+AAD = 5d3624879d35e46849953e45a32a624d6a6c536ed9857c613b572b0333e701557a713e3f010ecdf9a6bd6c9e3e44b065208645aff4aabee611b391528514170084ccf587177f4488f33cfb5e979e42b6e1cfc0a60238982a7aec
+CT = 81824f0e0d523db30d3da369fdc0d60894c7a0a20646dd015073ad2732bd989b14a222b6ad57af43e1895df9dca2a5344a62cc
+Tag = 57a3ee28136e94c74838997ae9823f3a
+
+Count = 1
+Key = d9f7d2411091f947b4d6f1e2d1f0fb2e
+IV = e1934f5db57cc983e6b180e7
+PT = 73ed042327f70fe9c572a61545eda8b2a0c6e1d6c291ef19248e973aee6c312012f490c2c6f6166f4a59431e182663fcaea05a
+AAD = 0a8a18a7150e940c3d87b38e73baee9a5c049ee21795663e264b694a949822b639092d0e67015e86363583fcf0ca645af9f43375f05fdb4ce84f411dcbca73c2220dea03a20115d2e51398344b16bee1ed7c499b353d6c597af8
+CT = aaadbd5c92e9151ce3db7210b8714126b73e43436d242677afa50384f2149b831f1d573c7891c2a91fbc48db29967ec9542b23
+Tag = 21b51ca862cb637cdd03b99a0f93b134
+
+[Keylen = 128]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = ba607083a97b28d010e125bf11fd8222
+IV = a0613a75204fb40e36857f06
+PT = 27d87b349fa6c97c2658bb9f6ede0c6a5daa04f792546a27b25db925dae3cbb063fd937bad99c4d3ac36f44b5719019b9001b7
+AAD = 978420ddb8a95a2327e8af9243663f76e1f71badcd0b08a4bc6d05d2cb8c3c5aac500cc058dc134d58d2e2c979d769c43c092fadbb0a04291bf73f5507cfd7c981d821c57fdd208e9eacdacf85a63a04cf32446f899d18257df4
+CT = b31b1dee3aaf30d835ed50c10a64226f3cf97cdb4e4be4424fdb4455dd0684842558bc05cdfe8b9ba1ea2862014741605f0f1f
+Tag = a71bb977f4ff23034dbf7a62
+
+Count = 1
+Key = 8e2185b535c7290d176f942d75880695
+IV = db10a0a2d0bd6ec4f16ea4fd
+PT = 9e768023dbe0c02633aac2f4cc5d9126a717bb89d9679d0b6e108fc3e2efe8a5f6fe9227e9c879e8e9ff56f3c5fa3618de9be9
+AAD = 4b3e0cfd3064aca2d16d722abdab83bdb3538300af0a25bca6f8969ac2f30163938948d2c0ea47142c88ef1ed4fe6a459837c1d0f059c7c59e3ddeb8fa34709ee97ef24712297daa84c9e13f9af631cee5943831c3453c8a2dc9
+CT = 65ea620ba97f92d05cfed7ea3adc38f8c0205afcf6734045237c3ff0f915cbe8be325e07f0839d5e929a54b7ff2d66aa418d97
+Tag = 17653f1431298150cc3dc26a
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 0]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 3a087944c5803b9153c6646aa9a8a8c8
+IV = c3
+PT =
+AAD = 55fe72708217df916429f1412c65e1f7b0613c10
+CT =
+Tag = de5397caefb946bae7371ef46e7409d6
+
+Count = 1
+Key = 1f78771bd4b1dbc28f4f58ac9029e895
+IV = 3e
+PT =
+AAD = 088d63f29fd4796714d43b720b35ad5b98a6f8f7
+CT =
+Tag = dd3f1a398af192f6a614ea01880103dc
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 0]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 1e6d615b0ec87aa56ebadee379f1f91d
+IV = 9a
+PT =
+AAD = e461e797e255a51cf95dd8590aed9750cddf2bc0
+CT =
+Tag = c97be0d79341ef6588961def
+
+Count = 1
+Key = 364c60fe22affbc7bf300eb28c2cea3f
+IV = 6d
+PT =
+AAD = 1ad485e28ae31ef5eb7c28abac7224dcf4499787
+CT =
+Tag = 2e74623478a42efa95d504ef
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 15b2d414826453f9e1c7dd0b69d8d1eb
+IV = b6
+PT = 8cfa255530c6fbc19d51bd4aeb39c91b
+AAD =
+CT = 4822cb98bd5f5d921ee19285c9032375
+Tag = 8a40670ebac98cf4e9cc1bf8f803167d
+
+Count = 1
+Key = 681587d2e2760cc7d3f1a1043a8ba2f2
+IV = 1d
+PT = 9e04a8f52e8d5c41c890a9cdaf7ec304
+AAD =
+CT = 59b4e8151db527408d0c8494e86738ea
+Tag = 17295fcdc04abc7b68a6f2bf3a8d92f1
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 09664b34329537736de91b5038cb3494
+IV = 82
+PT = 5cdb11d15b927c59b9ee09bde8a08187
+AAD =
+CT = ca7dda0ccb04c810833c5223e8596603
+Tag = fd35a123e31985065a49f256
+
+Count = 1
+Key = 79d93a6c7055d1c07c342ceae57a980b
+IV = 2a
+PT = eb7f45604e045b5fec5ac95f2b7c1bf3
+AAD =
+CT = 784864b425c3eda0d816ab905238b77f
+Tag = 324eb3b291fcd29e54c06c9c
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = fa8c946ca8194795f4c41675f8711a6f
+IV = d8
+PT = 204fdb9e281a7032bf059ef8fb0a812c
+AAD = 01a35f9018178feb6979d68c8b156a9df8b66bb9f8e2ae1a3d8bedbcecbda35f28b46a05c1de802d4f8516494af23af710bc41d916d527d019a0ab72b542e12d7ae1636a70d3ca0f98f78c1acd490a6fb51d1ceb0c9c7210b687
+CT = c5cbab590a3bf2109609c5bb82271ef5
+Tag = fa40b8a8e5752498c63a4a59fd491c08
+
+Count = 1
+Key = 43675d215370c3f2c5da0aa58a41a92c
+IV = 31
+PT = 24c25202dfe9c4650d2ea34f789d975a
+AAD = 3aa2d547bb035bb412a493008853d4969c905f052dc0eea9a722936d5d37b5aa6378db0b77829e131b3546fee253eb36c22ae97e65f541f8a94d2decb1cf1a587a1b23beee95bcdf5617ce8712f4bf820a7bf1372f80f1987dd9
+CT = 1f4723cad96d3ffc09bd209e2bc54cd5
+Tag = 09856700b811f31bb9b3f65177d3e9bb
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = bc365f9fc37cf63e3675b3ed3d1d5fc4
+IV = a6
+PT = 40c0cd7b5ae0ce1b6bba336c95870075
+AAD = 57df4a58c3f626950148634e6e11e298615df621052aff83e0b4591d5205d0beeebbfb25ed297e6544036dace11429b1a7eaec6d6142922162f969fc2c7725b564d87c427e138fa8776dc4e1ff26ab0a90c04aa2fe7e6a133784
+CT = b70dba50eba7e400c68a7f78d07208e4
+Tag = 97093a1ee915b6764db72de7
+
+Count = 1
+Key = ae009a6de56ecdcede5f473e4ea8930d
+IV = 17
+PT = d1308a6109a1a2b33d9a6832c60ec5ed
+AAD = 2ebc327df0c552b73992aa392e9c848a10da1b60487e06fd00834baa4e91c1ae8f144ecdcb31d85239ac0ea2bdfa4f8364b926e70404ff079688ed1e7bace25f4761d84e31765321a190f7a71ca66c3d3b6dc4939ea103199ed3
+CT = 4aeef2c2b9c0bd3bf05c32a8415550fc
+Tag = 66b702fb4019f4a2a67db354
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 104]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = a5a10d0f6d323ca2b39596036afcdf7d
+IV = 52
+PT = f85be0138fb4c19717633a5f37
+AAD = 1b5f6c949cc5be523ae4732d12bb189ffaeadd91
+CT = 4ed45067f32cc97836908c6925
+Tag = 80359250836667494cd27631de910bfa
+
+Count = 1
+Key = af9778662beb8d2e0e24353f874c6701
+IV = d6
+PT = 1b09e2e181e856a1614eb30c85
+AAD = e6974ff9fb6ffae4ddb9d2e2431931f227b3980a
+CT = 765ba42925df6463ead7f0b8bf
+Tag = ab192e9d7ce36dd10979f367840f7b1e
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 104]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 857796ea4e589a9d3997ac369e0ccf77
+IV = 02
+PT = f7c2847119291b513ea4ad02d7
+AAD = 2649e6a7a7c0e34ab3e255f44ffd422af9e97ae7
+CT = 2fe17d995b0a1e151421cbe585
+Tag = df685996f0cf4ae8c57ecadc
+
+Count = 1
+Key = e1a2c198812132a881afe9084a34429e
+IV = a6
+PT = 181f2dd4511caf61389e89f0e9
+AAD = 21b0a3688ad96c636f7b1f0f016b7dbed87610b5
+CT = 116081788ad021d1ab87959944
+Tag = 49f2fce7163e7babd64eefa7
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 0d2d48af1de12eae099ad1de2351a603
+IV = 60
+PT = 7980e625031e4d769d4ae90727e65f58945fb72f04013cf1556ebf4b5123f523
+AAD =
+CT = d45d35a8e3497c0aaa3ffcf361ec000c81b4dcc26ad2b0b16a176150abf4ca7f
+Tag = dda4b1d6d28b7c7d9c231710d77a27f9
+
+Count = 1
+Key = f74c65d66bd2b691b68065bcbc7a9b1e
+IV = b8
+PT = 7a7c0b416e4aab2ec0aa317994147960fdad68428d760c3fa1fb4b7d0cbab2d1
+AAD =
+CT = 7f1895b667ec2f5ccbf8b8a67eb077e09b5f0325918da2246db9fbc067308bb2
+Tag = 6d1e52fba568ba416d694ff048be911e
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 3b1f852e6bfc788f32cbfd2859eebaf0
+IV = 57
+PT = d05f033b263ff2f797e5cd571f4341404f8c8700ea1ed77eb5d161c3222c4598
+AAD =
+CT = a5053bc560ced2b677dc7f82e0c1cce3c7da3155b9ab6d9527856c0ce73353ef
+Tag = 17e6ede2c7a292b7d7d0c10e
+
+Count = 1
+Key = bea7c099f37a98b3df12162c4e38d9f4
+IV = 51
+PT = 91ed5aed5397a4d1b471db8331a3d7e7849b0aba593013c5ba8a57bf6e98205d
+AAD =
+CT = a40419306306d3593f923625412cf5d3bf3abc49547e3f837b3ea74ebc23f75e
+Tag = dd6858c01aefea78f5868c8a
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = bce96a9991e1d9b4b9899063453a7877
+IV = d9
+PT = d7b3207aecb89ff38d84c023ace05ea5320e754f585b8cc56acd06b55a0f6fba
+AAD = 7690deec4091150ec040dbc1896e142f799f4a498c103c259d9b859c126af8db145dc5597bb528f03d8537a33eb9dd74a6f1fdb33cf4ff165552290a1f4c1f3272fe66d083bc7d5829fb7237a16dc3957180d88e75775d0f684b
+CT = 78629b55e76195c08a84f78485a04f27e957892ff31625b18f9baf57b6de0837
+Tag = d37805d9a9ed62f18efd7432e3d35fc6
+
+Count = 1
+Key = ac518a3541994768130fa8d83b0a961d
+IV = 2f
+PT = d86e36201581c23e1c270b7a30778a8aeb0e30370fc0e74efe129473e05b2a40
+AAD = b314f36c3f18ca53277790202615268a3c6639be60990ad8c1789508d80b0fd830f36d9c5f449c9ab24da526b1ee51359f871d47aa10338cf62890621671bdfd4ccaa4c69d134cde5b53ec9c7d036a5e06d44981ae807bb4d13a
+CT = bf6d9a617edff397210d5dc53654c9b4d6b5713c0a21a424b1f01c4b69cf24fd
+Tag = af802322b7cf41c805ca85f44dfe148c
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = a7bee2097d1d34b49386eeb8fae11278
+IV = f8
+PT = c1ff3b192e29eba2f84c137974859c7871f9e3d45e3b00f2e031fb51e8225e4e
+AAD = 6d1fa332ae15a3b63ab65b85fe5079dbdfd349d14453fd2978ffd552c5c7b40dd188dd103d60e1634025ddc420142f63f100a4b8d1bbbf884f417c9e7f71d70a75d654dd1aea1be4aa4f8ff9a13fd2a17de908ee5eb0e4b98bda
+CT = b82f93685e07319b02c90c04c5566c577805d73d4863a913caeb64ce6060849d
+Tag = eb4889a503017c1e4f78229c
+
+Count = 1
+Key = df9777614661141c5519c0ad76f179d9
+IV = 26
+PT = b10455cb31cc0b8bb1eec18a212110e50786ac931d57f72826c004d383c7aaa9
+AAD = f378fc7dfd37ff1646081ba4f04ee37bee206b37963ef5b92977625db4a9ae4e650eaf41c16cf070c3aeb354290bd6d1eae2356f20854a804d399b4c059d5ed8c4e14e310d320d20848cc1bb2c41e320355aa6554e0f79615fab
+CT = 829bc684090f5bd087a6b91bb3cd146fec217dbe8921ed0dd35bfb3e8650bf28
+Tag = 213629774dba79b7367781ae
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 408]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = f51cc8fac3fd1f633f40a0e1257065ef
+IV = 04
+PT = 5324b6cd24d40977f0db1ce4f66bb9353d57cb231b61e2c6cfea55d7a15717bf407c09511df414656aa7d5c014bf6dce5d1d6f
+AAD = 6289b938982b5273190ee6efdbd139f63d3d302a
+CT = 727a9e9cb895a37b6f50e0715fec00c4df0d509d97c2dabb1271324e882678facbddbf06ca14015b2a44be110daa9ed96b7651
+Tag = 3b9c859dc422f6338ad6c402b88793c1
+
+Count = 1
+Key = 7efa93fbe39969d5189b3688af64fe7c
+IV = 04
+PT = b3ff41c6a3d69a150054d1aab1fcb01c1f69fdc9b4cd756e103b3a4724296dd9402dbd382b0efb77d86028f33a39ff0178f16e
+AAD = 58d17f5985b680cec4cc0e86440f922d2544f577
+CT = 0c4e9daa242cfca43b46921a58abbf90798ed4211a3a6f540659399423fc06e47274d81dda294d7d6a4b71d12349fd2090ad2e
+Tag = 02cb2c35da2e837816474e88d197093d
+
+[Keylen = 128]
+[IVlen = 8]
+[PTlen = 408]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 7a393c4e7ebb0323457c829640f76dc7
+IV = ac
+PT = e215439f824cbe1274618bf54ba24fd99cfe652758620216c3331068a585750e2373a349610a1a6d038bcdff5d1584b1daf251
+AAD = 6fbc9f61f0cfaf5807ded36f185f7a6e6bc9a587
+CT = e8089296c6a697070370fecae4e2286009c12cda24abcbf02b1fc2a79c5bbad84af30bbdd1415f0f82c2f471acd3858ebbafed
+Tag = 42bdbaba272e19ce612e373f
+
+Count = 1
+Key = 7741a37346e46ae797710c8ead30008d
+IV = 49
+PT = 4ab973799c4f3cac7d5c4554d4fe7e3f169717d2651249328a021df258229934373044bb79b3c0ac1fb36753ad38ae76e42b5f
+AAD = 90afe1db67a4da0822a9c88877eaf14e7c020ef2
+CT = 0c2e360d855f8f1a9b5a31a6e06bad90aa70f7e51363290f4eadf7c60a0ce97be4adf2712a219dc596670987c01b88db58abbd
+Tag = 49371d01ea39042257391bc6
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = d0f1f4defa1e8c08b4b26d576392027c
+IV = 42b4f01eb9f5a1ea5b1eb73b0fb0baed54f387ecaa0393c7d7dffc6af50146ecc021abf7eb9038d4303d91f8d741a11743166c0860208bcc02c6258fd9511a2fa626f96d60b72fcff773af4e88e7a923506e4916ecbd814651e9f445adef4ad6a6b6c7290cc13b956130eef5b837c939fcac0cbbcc9656cd75b13823ee5acdac
+PT =
+AAD =
+CT =
+Tag = 7ab49b57ddf5f62c427950111c5c4f0d
+
+Count = 1
+Key = 81d898349f3571891f10ff6f89497283
+IV = 33fbf5041554a778ed9f1a35d6d1049e3ca4c81c6adf0a4c22a8ccd3c4147f8b7314f05df65721f497a0bea27bbf28ec2a282e23642f7088bc7cb42fa4a4221412439801cbf54a93259e03fb85a3f1ffcd7030e33b383ea9e7b20ac6edd36cc22fd3f2f3db315e0ee7a444e332138aa4bb960d9080a7a89067ea155c8c609948
+PT =
+AAD =
+CT =
+Tag = 2b1f4f4c75ea66914754f4a129b6edf1
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 4df2b84fbaac9a696398bd00fb4e0ef4
+IV = 06781fdab6e66d0b995be011e86c06f618ee3fe401a483645079bc483f435ef5e63b369ccb75a0179b4f497105e0129e5eb67fb8510771c758bebbe00018a18421ba9878083529cfae8d54913ce0029c33655021c5b4f04399a050dbd5997847cffe9b3cfde040fc0a19f50243b4b0e69d86579adb3dd3d5381b6a72f9e6404a
+PT =
+AAD =
+CT =
+Tag = 86cdf6c393312e5e0becac9e
+
+Count = 1
+Key = 96e225d81e3ed5a69f1b9350002e2b03
+IV = a33828273c5ab2886c801ea0fd5e63c2c9b77fab541e00c6bb11e67ed5a4baeb227d49da9174906aa238ef3cebeb362ce55dfda5aa513ea1497b2a7da083b349d4809d5704241e0d48efbcdb488e9bac672977dd9336432fe3bcdd0433e2ae23417769391b847dabef7eca1f3f2a353e3e639602c93427a095e1943ccbc64220
+PT =
+AAD =
+CT =
+Tag = c92cc1443006852d719af7c7
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 67debc1559c528df51728174d31798a5
+IV = 34777c1e5b8f9041069efea4654b59019669c5de0eab8944dbaa0cf3dec64348cd5c98c17dd93ba51b495c0fc0776b0ff37cbbe667bddde5b241158c113b6311eafe9314e33acdc7ba9014e1ce2aa99af75593e2dfdf00513e1cec83341fd27c437723d52fa191caf526fa926cf95ecdc0a26691744a5ea97e06d276f6ad8bf2
+PT =
+AAD = 8d34d688111eb7e13f3b03ef1fb81b9441a7f6622a004e13965366c951a0152ab62c394504b2f3889c745d7676f8641f490f6c15445ef0f9b9ca7479da9ae9d35c581936fa400d28f828f1f08eb8187a5ef16734885a4a4d42e7
+CT =
+Tag = 3c125dad456ab0a5830fba027690c68b
+
+Count = 1
+Key = 72a8998427aeef22855631bad2f4ef35
+IV = 6eb5effb95b901369e9813f78d00b0e84e6dca7082c93e59ce0a3aaa0250c5690eba3be464b06eea105f031f4de607eeb236a562c6b92ba2d9b70faad30e5d9b9d623fe48040d26805560915fe3d3742341e5504da195f5d73f57f0c5f5f035c1236050b5baef6bb391ec332be526069fc9d9339e09942eda2b90f1a4a0c153c
+PT =
+AAD = e74208fe7b5f3a58e8928583ee00a59b57f9cc0dc47dcfe30133611f870d0e5ad6b43684b85be855051d11d74bfa79f8f0e71e40e310bf590d85abe62d8f71d8a55d6cb0630cd820ea8049c03931dcedfcb170694e87256808e9
+CT =
+Tag = 84bf1eabae6b99f3216c97aa82f80504
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 3598d89be149e6f48a5449fd3ad9a1c7
+IV = 945fb7f9f2a97a1c0ccffab420f3da62eeb38fa97519d5fed3374ec0f7d39a986fec8ecd48e4f7d2a91951ec265d7a149b56e83e9381e61d9354a073d651a142279ae67a74b6b0b6c86c3703704db9b3ea8d15bfe05fa1323391918fdd6ce7caa616696620666054cf71ef78f6927616072a485718d27cfb5c3ca297ec02ee75
+PT =
+AAD = 37cd1b81b2e953364b6c7535e612bdc02ddbe7ebf94d68e1f29373655e9bffa6fd7e967947b49e606c3bad4b7d3e838f81a42216c8ee7b938000d190bd1a398af41038ed70204c19e1e41c4fc4562622e3d0da866503cb57918a
+CT =
+Tag = 034c20acb4ed77a299938a1b
+
+Count = 1
+Key = 8b263a7a94b0a7e86791d7bc03e6e52c
+IV = 33d71715a0f9b238da30b312b66ecf688fa08b306b1e7b98d47b43de24c186e2234498c21d60c520e491bb0c06f868ea1d352ba33795fd283a31721f3ca8006738dfb6cb95908664b08afab336354248a9fa58f4b19b0c3b78557f895cc6e7a2b295fc9b72572137c9f12c8b15260043f8f2381bb1c55e59765228097f194a47
+PT =
+AAD = 27078f44bd46a606e433d9ece7f08b4282fe3ecbf86589cbbfd85328d36682d3efe1f886897d5813fe7e45d42b2f6c6e02195b185da3c34ac38ee750d5c4b25122c7bc5d2f56a95ae9a21d897a27ce27c605802af80c1f6fb79a
+CT =
+Tag = 038cc9cd7f99f595abc328ee
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = f43378edf8b810602b753d647a40ccea
+IV = ab59967fc21429d7f4fa5dbc1ade96e7d3ea347c87f15b604b395ea78feb1872ba245c591e270d93d3d806e29eb9ed723399f5b382e96ac0f2c53fa64663eb2701fc39fd4433eed05fc3f55fabd30ca4161b296913ecb32fdac9272a20206c846fed470173ae1b2d45b9c4fc76b0ff1a5d35ae1906ae65963f66c2d3f9f1a771
+PT = 8d15a1eacb0790c032ff7adcffc77046
+AAD = a6984e7895dce7746d79c97aab83aa6de7b2efaa
+CT = f7c16036cf00fb3016561c5e01391446
+Tag = 66f0e9f65356cc789cc32919b168dff1
+
+Count = 1
+Key = e9bcb3fb2f7560cc6459b1b3e799354d
+IV = 9823edaf9f9a7bdea8b14f33303fe4536ab0d13be44f03d4c93209bf5a84dc53c119114c6b975ab8ea383c5932049570b3cc6ea3699c0afe951110d112fe5a78d05cf9de9aa28b7c887b388343a3f3bd2a20dcd18156769b82b9ad384c0c4c1b28bf9a60e7cd8a1f3e9c1181367e81908568a0c5b6d5787dd2990c1bbac4c4d9
+PT = e2607e6b8e40a9205f64ee9a64c13ba9
+AAD = f8793a271a3ce73865fbc9fe6d3dfb2d1e700cd7
+CT = 2ec146750592ad852c72a7333ade44af
+Tag = eaa35f90e107240ef3c746f53fa0038b
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = d41e1817fe18a1fd948280689a9a51aa
+IV = d349484c264f53326c560ab8aaab8966b7a711c80f95186f5838fedb7522f41c02c7808f2160fb3a31d6f7a1f14c1ca4dabc001f1a694f8ca1fcfa02262fcb76a8669fd57c3d9a61b344d1a03905395cc45cb368f4f76e87a92d2aeefd2671e3fd2215435152de5ccc23016c3213d500b3bfa8ff6c10890afaacfa02cb08e761
+PT = 84632e8c1910c7a869da609b53802137
+AAD = 5838374694f279458e45b8cdda527719f500e4ca
+CT = e8113f17ef8090c8e3d239cb18021df4
+Tag = 3df00b2774a4b7d0c338404b
+
+Count = 1
+Key = 30f45a09ff11908bc6ba0fa3fb06f530
+IV = 8d0623a4fdbcae68a2a5d140a5486945660222c6850bde2ef5644379cee190f6cf8c2c62fd7b3aaa0ac3ada5a94311fdcebe749eefb4d45ae718c39b7dae47f5e3c898ae19124501de587e6bd9542422d27d4a52f95f0ed0412d7ced32f3b8723ff03eb716fecd89e083652df095ed97dd21a19b81db4ad64b539f2cd6feea95
+PT = 138eb24c51143fb8db406d9e7fd39069
+AAD = cd57e709e9b24e4a9072d2f3d6b9a3d6d6cb9343
+CT = 2f22a2e1d880c40f00cd2ca280cb83ad
+Tag = 0e190a4e515964d0b94dc87a
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 7cc48990da9aa2afae8db0508c197701
+IV = 871144e7fa1e3b33544822707c86c9aa286ecbc588c1e6cb40ef4545ce524602c1c6242638e945cd5ea7e3ec68ed3949eeb7e230b0865f1e914410a9a31b855b51fdce9c43acf713089e2b441a980f6fd79a61cec3a23f01161c2dc78b3e536a798b3df75af37a68ea364a60793f4153dc54d7c3dddc83b5afa8621ce44ef9d8
+PT = 99284284bc26f2eb69d4815e58
+AAD =
+CT = d44966f882183f954c756d90b0
+Tag = 832e618200ab496b35d5dbdc301e7eab
+
+Count = 1
+Key = a5f50ed6a1d7a45b1d6a58b53b725156
+IV = 725a6b2b5f2977f234beea242c53042eed7bfb97b58ba8b9a0e950a8fb6a1d58396090d4ff7cde0f71d902f25c812c3dfa2a25fdb7062cef2c66a090ec10517f7ff3bb2f47f2e32e07847cb70d0145f3c3cf25ea4afcdd54a54ea30752415b2182cd0f1f51d963a7f7ec1238dcc52f77bb7eba221fde93dab873a67132ac67fb
+PT = 5ff0c6d4fea494f9d59395d3f1
+AAD =
+CT = 8d7e976bf7e1832b993879c50b
+Tag = dc1be5529513c62af82eca5fdaf8aae8
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = d3b2aaf7f9578208a9632a1ab3a91432
+IV = 96e1fd58e40b4c693a79e2d5dbba94797d1b7526f18213e87571796fb517f4fe4dc7e8f414c3ac04efb64660f338ca848493c5a50fe95a9cbd193d35416534ffe456193e7fbb33fba124a13ce1054f4e8b3b6625b7c84ba987b510a3750d08403b615097c671aedc836beaf9635af43fca064e30e1ea6419d99f90d17ba38c6d
+PT = c98d71abbd8e446e74ceb70d21
+AAD =
+CT = 8961bce20b103520120dafda53
+Tag = 2e505da4c84892ba10562e44
+
+Count = 1
+Key = 4cf973d6a9b51b60ae79116cc9b8aae5
+IV = 8b43c8d30a42d5ad4cc094bdb218f4a614d179c5ff4dd713215f05c8b5ce57752bbe9e3fb6884ea30d39e3aca941cc42327516cf285f6f2e03dbf2d1813c7e67e79ca5bf81856e9b0dab05c75c1629560b78620281e0e4c9958b03ba74086193256fc4fc8d89566207ce3132c400323b27d3e3291050c3ca9bc3f13842e803bd
+PT = fc6208970ba0f2076ac0cc5367
+AAD =
+CT = 4b338c27eae84f1fac666d59df
+Tag = 0069a28ea11c35c4614ab4a7
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 059b008bdc461943e486bd1800dd6eaf
+IV = ddde5e8bd48974bba74290fd8be30be0d7071d37f344fb9dbe7542dbcf1d44eec6a0c25674bff71e8307bf10a3b54f4acaf4e90d6e8a227506db53c6af77a4d9821bd55ca048c837a746fdfabfba1962bb95cb4f2b9e652e6ab06efc583cf9427ce61109e54c1bb2ea461837915cad3bee909e9cf2625c3d593feea8acf6be72
+PT = 4f9c13d39131a6c50092afe30b
+AAD = 191cb9c9509272ba0cc3613a9ee60b907ecbacc23c9a461e2aa1b460912930fcce6df11b658bd512b1586041f4f6fe0c9bed6270b4ecb510b72783678b7e81fadc006d442c6dfcb867b5c7281323e65e06b581d7027a1bc57b99
+CT = 5b2e0e36b812c9a8149d47bade
+Tag = 5834c34d07d7da7cb24e6f55e209de1d
+
+Count = 1
+Key = 3d5d729b45483d6a510dc8138f790161
+IV = 523212330f91b637686f6937b67bdb23d7f4c8af61c99d2a8a71398cf4c8049ae8883d73bb8c5041f9625e9e2c816285f2659621a1c695c2f1ec14ea2836ea657c7f96374513290a03dbb3e95683a7b1c9f30c3d175034a52a670a073909f923691627a7b449e89de51160d451ad4878e941d47a40f43378691ecf6ab98363cc
+PT = fa2ad1895f2a29d0abfcc41349
+AAD = 2e839c5e7be918d50c13b0714821cb00126723e19ab121aef592951c4de6136c10d20fd2336229a673b338e88b1fdd2dccfb92d1ba806137ad2202e4fb04a874524b71b95aa8dd7378bd92926b71186ce3c9f06903cb30a422c0
+CT = 94d4865440660400fad2e42658
+Tag = 424e2f311abe4f0745823509c1f245aa
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = aa56ecfa49a22d9ef0644c03378a93c1
+IV = 32e1811c8aa4bda36589eed3a6851c6a6948c31f2c4472857caebeba6907256bfac5555b4723683452428e9d5734e8baaf45273760b37908deb7b1aaf5401f75b4e24328ac56a018ebc575bf42402e6d6b8c281cafa485f4be68514c9ec6ed17c684bc22c7a12fd74ae87aa332870771ab6c5944b1131b40608487c5877cfce6
+PT = b7787fc32d97d70c6eed0cf35a
+AAD = fd07c12e57d34a062ffb0b30aed05b0ae7d82fb912796a4dd110b4767047663740eefba4c78456c072626206470202d2b1ed7c3f2e9c9fe8482c2e92c7aeaa85279156b2aa6dcbcb636c27eec79e34dcea65e5604978f33d4391
+CT = fe9a359709194e942b6004ce1b
+Tag = ecc851adde2dabe858dd7ce4
+
+Count = 1
+Key = cd9e83838940275fcf5fb2fb72069a6e
+IV = a807f34841cb4bbc17bf8e3539327b376f5cb7a5cd231079583ef24709fd03ec1f4aab3fe3b0c6b35ddb8782c2b3b99f3cf0a5a84ded74d38558b7e1ad5aec3e42a2ef06edfa5d1dad0aae54bab4ee5eaa29c580bde8db913b5387aa2c4e1cde6b3e579a67fa1fe15c848c0290d5c1319d37b1c27399de478be2881fe7afd9a5
+PT = d43f7f3cf8deca46d7fdfe26e7
+AAD = 50d26b4ee6a495b8a9e50dbca6ff60aca0d8dbe83bf2325f37c809f63057a57f471751d8540ede64684e5c0b8454fa6a2baad917e851a6743b8fcbc8a0b3763d6a98e81df94cafc94e964b16df89d9b23be559c6e1c374065d54
+CT = 62819817013e1aa0feb4f7a1b9
+Tag = efe6b2aedbbef2e5888a13ed
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 709aa4857ed67b465981770fe053d968
+IV = 08fd6a21f9f5815ba5d2785c27bfad3f6d697aa8d1d7557c5b590c9373ee43e05a4c9ffafaab7d3b91e95e01b17e04a013e5fb5a629c1864d4a680a34f7a6452e24a597ad06c4a374e192b756d1ecd9ab1a2ca24068258bedb01fd6e0a02050ac9f1f18f829bab91c9612e2fd9fe6f7c5ecfd0198c145d291906328b7743ce43
+PT = 1bbf8f33801d83d3de1c1c358c83987033342078b62c332a34e71d2970bdc7dc
+AAD = 36fe569aae9b339440ec8ea8c846dd22d47037f7
+CT = eae0a6f3f717ffb7a8f4f647c7b129feebdc047a29428492b43bc3092d0c51c9
+Tag = 0354c2903d4a3a0bc08b597a46dabb94
+
+Count = 1
+Key = aa198d0e6d5d9cee230095d83a80f83a
+IV = f630ddca297a961cae2f478b8735a1eb2d91f52dc74c7ca08a39c8e1430aaac518cf03ecb35de5100b599297380e8a9cbb99c2774c9ed8c2f607ab05db4aea81363facad340171dfdb52c106528cd8fd38d771dff07339b19c63e8310d393b9da3364ed02d68218cbb5af78e732423e9486bd32bff16ecce2ca3eafe63f6933a
+PT = f8b7af366937ad04134e00990c42eac88010d8d4204991d0a41fa11f890365de
+AAD = ce842d66f1d04de0bfe093c330a5939d2db96288
+CT = 322d65fbf574ae04019109171d545d833bda13ec51fbc19bb565cc7cbde1c06f
+Tag = d5cd64cfe9a6d2bb9118a78774a35535
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 8abd543675438a0fc7114ab81e5e96d7
+IV = 453904127e2ce4ccd3551f07362f7f2567045cb4468387942efc524680714faa09b77c23807d7eb9a37d886a1b70be8072ade83a51ed101f2739cfe77f5b5c8735582b109c4a9b0ff848f3296152d705a42e19790048af10e6dd0ec2aea81e065f36d9a67b1524eee4706bef2933a776166062d08d27c33cd1256f0a3dc1e6fc
+PT = b36a57460592ab94b89514fcb675978cf343c75c242cf1c0971072cccb1d9062
+AAD = 974fddc8c013c089e6bea6ca390a18a9565532f1
+CT = 4160795a1404e4dc4f99e092775d76a0afe9a8844ddb3c111ad3ed06dffb14b4
+Tag = 6379aa2f15187ac6a87e7e2c
+
+Count = 1
+Key = d95e15ab77accaf65382383f662f5eb1
+IV = 556f87a90666c913b509fb3c3492f505cd2095f6c7a28f2b459702ad9d969cb58b4e4871c69024f29156f70ea59df193b9405cac77ce81820f9e72714fc7cd3079ab06299c28ca0dfa92e42e5b9b5f164bcfe43900194d46406e9bb7d10026e3d7694ffeba8c548429d442303185c8c90583b5a43480c8b6f1fe6e53e280299a
+PT = 1d0fec20154fabb952cc4ab280777c61103b695d2a12e7ec59a1f99dd8a8a7a5
+AAD = 797d8c8923ed24be66bc7ccb0d159c642554d3a1
+CT = c1e64d16734b94f344f88700fb243c3d420cd1e3e41b818fdcbfd7f451fafd37
+Tag = 2935f85e7074cd90bcd52442
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 705f69e89bcaba68c4c26a9f7bf6944c
+IV = 15b3bea26780db690eb2f78354207209c6c6f70a1d18cb5ed654a81a6da3300d653cfb54b5ce8c324f5e78474d80de9380ca77a8037c2a7a160ff38a8b23a20a688fd8a5d1ffce5af7ba371e94de38b6658471d2ccaf684fad7aeae8b80df1a0956b1c767de3d686ef56ab7741b5f15bbf7bb0024b362ea97940d69378a9b1e4
+PT = 6a0006a35f11510d13fee5822bda908576ee9743b95eea9eaba2c457a8a5838e56f6ea6b85d332849dc66a02dec292556428af
+AAD =
+CT = 8cfaaf97ff27aa73fdbabd03879b937f668dba79ed9d73c7ca46317516617c9b384d9338b1a087b2688765a0dde6387f6350c0
+Tag = 17cf37639932f4ce0e42df066353756c
+
+Count = 1
+Key = 54043f9804b0398127128e51f3b5922f
+IV = 76351b77e6d50b43671953b684d0ed4ce52a4c027f8cc0a18316f68673f704476461eabf4d41e652e15818a1b153fa5e4dd63f6afeea0c898c7db7e9375af458d727a8691bdd1cdb59caef53f7b63b48ac290d2541a5aba8b8ff28adb1aa798791bb997a3eee7a079ce74faaa47124f12df9e9cefbe006b7a17adf08531b1e68
+PT = e2e217ec7c6de831e73b05f026a9164845640fc93eb802599d0fc0b398fd224011384ed5d0a92a8cebc7a837b117473dfad34a
+AAD =
+CT = fd6068e17e889f2e679e3bf1a3b1c40098625c6393afeface2b74f84a2bf7bbfd1dabeed517c4adc487bbcada01059665335d6
+Tag = a913b38aa1d1334d29ce48607975ad60
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 4134e4e0ccae23b736c2fdd7b5c86bd8
+IV = f4fcf751567f346d409c7575c63adc6789aded52a7776693505d3fa28889ffd98e7fa02690b6bec5f1a0c2e1ebd58ac20ab283c24edbb79bab023634be4054895ed24146bc10a31fe3aa7bb410a417b7c4442fa14a0d35b7b9b033b57c5880a4834bbddddcb88e92063afe5d52bc1fcf36de4f7845f627ae81b8249fac05c280
+PT = 9d60485713e7e0d51f06ab0f644456f2a9ad87f5f1d54d2324913ae52cac8d6556573c2954e59f949078683285e577b872b0ec
+AAD =
+CT = 85ef2bbedcd06a7cc2a4646afc333ec9915944b572409c5db73140c24e453567d8d0cc7a82663b5bb28cfa48d53cdaed836f7e
+Tag = c6328218155ce81c65ee9112
+
+Count = 1
+Key = 8391af81760f12a7dfe5863c6d7ad878
+IV = d8c891dfd36f22b5a1fce0d148b9b8ef4b312f7e4fd7849ea8bca334dcba4c395f9b4996e783d5674fa3dd13ad0b337910aaea5af63555dfe7a07bf008ca4986adec40b482206e2c7610d52fbd3d8768958eee9873ea42e432b544720c7dce40c9d4f6117983211c816f6aa251e1fc681a0467b019535b8c8fcd9cf268530408
+PT = 9985ff9f3fe8c2afc5dcfccef9404561ef4ce372dbd02d4ea6c1150020fb3bbfd31d6214710a88f054330a93015c9fe7cc5692
+AAD =
+CT = d4de8ef19524eb3d01bf4d7d3be59f6b14e98f687e1b19c9e8ab8164e531869e0403e3408b54d3c7e03c9ae8b30e5047ab67b9
+Tag = 77cb5cc5063b6cdf182e6e3c
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = c7d9358af0fd737b118dbf4347fd252a
+IV = 83de9fa52280522b55290ebe3b067286d87690560179554153cb3341a04e15c5f35390602fa07e5b5f16dc38cf082b11ad6dd3fab8552d2bf8d9c8981bbfc5f3b57e5e3066e3df23f078fa25bce63d3d6f86ce9fbc2c679655b958b09a991392eb93b453ba6e7bf8242f8f61329e3afe75d0f8536aa7e507d75891e540fb1d7e
+PT = 422f46223fddff25fc7a6a897d20dc8af6cc8a37828c90bd95fa9b943f460eb0a26f29ffc483592efb64835774160a1bb5c0cd
+AAD = 5d2b9a4f994ffaa03000149956c8932e85b1a167294514e388b73b10808f509ea73c075ecbf43cecfec13c202afed62110dabf8026d237f4e765853bc078f3afe081d0a1f8d8f7556b8e42acc3cce888262185048d67c55b2df1
+CT = 86eba4911578ac72ac30c25fe424da9ab625f29b5c00e36d2c24a2733dc40123dc57a8c9f17a24a26c09c73ad4efbcba3bab5b
+Tag = 492305190344618cab8b40f006a57186
+
+Count = 1
+Key = c4f397611fb798a5f508e2fcaa329a87
+IV = 86c87ef3f41c25df9eed5207a11aa5e620dcf371e8d337525fb3ab2a6751f4afffe9aa864952337095fbaa7e683a7770eea343d0decd7d338debfde65f3c857528f0d1bf82e5364b3156c60ef39ca3bde8d32efcd997835ecbe5d1076296b51a575a0d68331b1a192441caf1197f9f686e2ba9ac62be8495eaa8dd67ed086ced
+PT = 58d82337ff0d3d0cc2f23db1cbdafda5a1788d7026c3f075b046103bd2e4566913c2d0ea782aeb5b49aa8640055007007bc746
+AAD = 5de8c0e7c18d05469e4ab368230cc9c34dd293622bcf47cc0542ca88445d7f56e36154439c5deb987b2cf1ce7ae9cab49db5fd691d3827a7757ad8ab64b37e25e41f3e7fe5e8442b69196fadeadeb3881a1dac3b7de909d36561
+CT = 20da5c0890893eb2a4b00751db0138eaefc0bc80f20a0851146cbb79e862becf733da3073939c2419c58b293d3d1475c5cebdc
+Tag = c730a942740866a16b129e28e9f8575a
+
+[Keylen = 128]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 2301a2bba4f569826ca3cee802f53a7c
+IV = bed48d86e1ff4bff37286a5c428c719130200dce04011edb967f5aaff6a9fb4ad0fcf0dd474e12dcfbcca7fa1ff9bb66b2624aaf1a90f33ed2bab0ee5b465174a722eaa3353bcb354165a1a852468ece974a31429c6e1de7a34e6392f24225d539eaa6b8c1183bfb37627eb16dcd81bba9d65051ff84bd63ee814bea0e1c34d2
+PT = 6081f9455583c4a35ed9400799e209fb7e75a7887868aa4bb0c9f7b78f67125678e03c618e615bfad03ab077315b7787418f50
+AAD = a481e81c70e65eeb94cdf4e25b0a225a4f48b58b12cde148a3a9aa4db0d2988da27591d65827eed39ad6933f267e486c31dc586c36ebaa0c349b9c12ed33221a463737695743cebb456f0705a9895a5aac720f8a53981a231fde
+CT = 18eca8d7ec92b6209c8d3c82d10c876047b470e22b74346ad609f44cc338b38c881103636fd056634907c28e32efb32dcddb23
+Tag = de01691b9b99851636c7c8d5
+
+Count = 1
+Key = 4fa1ddc4914c1897957c3a79ce41890e
+IV = 3c3841febeef650e18d4cd427b8bf489ec0ea4c585fc081c7048a9bbaaccf949155cef3ec55d9eba5121f796a9196e781e25a8c1f8b5751e603cdeaaaf486789adc087755de0732eae845bbfb6124948de1089c46ca616dd9c2d3496cf43e5749342e2716e7faa79f484868d4afd78622942391bea116a643e611dc00b644ecf
+PT = 9f537022843aecb290ff5c080f75a6d423ebe9cbbbd0e8d20c1b1a5fa156dd93a9d021670ba0cd7b4e60d9a15238ea4a619543
+AAD = 453291d49a9a9a9da429b4e2d0203e8fbcde86b632241060c12bdd017ddc531eb721be504eb7f084dc576694e6bab1af2495cc6e0e55899b0f558b05d2d4a873e384ad4bd5da5c12629feee1c880992ee21d39104321d26f69e9
+CT = e38d61f92ab28c3b3040cd9e2b1477484d43670fa643496d52b1290b6e52976322bada36a6a4e4c55d56afd798fed0c8f9690c
+Tag = d5ef5fd39f40bfe244383675
+
diff --git a/security/nss/cmd/pk11gcmtest/tests/gcmEncryptExtIV192.rsp b/security/nss/cmd/pk11gcmtest/tests/gcmEncryptExtIV192.rsp
new file mode 100644
index 000000000..cda212f68
--- /dev/null
+++ b/security/nss/cmd/pk11gcmtest/tests/gcmEncryptExtIV192.rsp
@@ -0,0 +1,1016 @@
+# CAVS 14.0
+# GCM Encrypt with keysize 192 test information
+# Generated on Fri Aug 31 11:24:46 2012
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539
+IV = ab2265b4c168955561f04315
+PT =
+AAD =
+CT =
+Tag = f149e2b5f0adaa9842ca5f45b768a8fc
+
+Count = 1
+Key = 1bb1d6a3bfc748786f3951e43c18054bfc8ce6ab3dc3d398
+IV = fea56a5ce5f7d4c81680195d
+PT =
+AAD =
+CT =
+Tag = 0b0bc0768b02f126a29bcb144abc6e4b
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 155c8e5ee1c79f8ad4ee08bfa274cba676b6b25d76426744
+IV = 849ccd0db8689347c72ed803
+PT =
+AAD =
+CT =
+Tag = 3f18a3a8014ee56f1ca69168
+
+Count = 1
+Key = f72029daeeb0cacb6db6f8e514310aedf02fa94de5d794b1
+IV = ea33cc69cfa5acbad62d8cf0
+PT =
+AAD =
+CT =
+Tag = a8ee413654de5aa628771afa
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = c25d347ffb5b7ba079be2279a0a7f220f19c74bb9c5a15b6
+IV = b35f142182fea65c642368ed
+PT =
+AAD = 1967a0bd80cf2c9c58e441e12cba788f9c072177e1ce02f30d58ae981ab37eac452c0d9f1c5f3485d7b16ae09366821d23d44479d52ccc4acd8fa6f5b9013845c629f69c612c9cbbcdca3bdf43855fa7c71bff458a7d4c019ad9
+CT =
+Tag = f5a0d64924aeab15a636c7ce4db52243
+
+Count = 1
+Key = cb000fddd67bf5a24b03c8b08965fc568962d7b2a0b4e68e
+IV = acadc8f822b837b8fcd5ac53
+PT =
+AAD = ce0e3e4e6ffeae66c535667e8a8cf12fca0e9dae6987835e8ec62fb95b38f31ec5e937bdfed5b55174834b038ba3322b4a2565ac413b6e204f88c3a93216b88106494eaa14a82068f00a3bf227b627075383682bd6bed6231eaf
+CT =
+Tag = 2c1cdfc8afb7569b877ba5ae13d6235b
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 892b248a648135388ee27757022741086c26edc08e7303d3
+IV = 4bdf644cf876f2d65805f531
+PT =
+AAD = c0f876f59850bcb852bd0d0b954177c7449646be8ad31cb8cf98ebf0c7d8a2cbb78bf1a5eba588ffd2516b13fd9e23bdbcae5048237d4789f3d23f0ef44559e521e89435ead89d3dd724cfb9af69b269304d0c6f965b8c8dff4d
+CT =
+Tag = 88da6c81be2a0299f7dc570e
+
+Count = 1
+Key = 4cc1a587fb4ff4e4b3875380870eb309734fa41644139355
+IV = 40803afc4ad216b0594ac2ed
+PT =
+AAD = d083d10da29551c8f63d5c30941bba4d7197a7d0e2372dfc0058039a232fc721185e7159ad5fabb90b0ed0d77cad354198e8de269dc4c1e9338db55cca2d3523c949ce1c36db992c92b88626628aa04238d40e6041ff407aebce
+CT =
+Tag = c6a64fb84c0d946d405884f3
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 95e5c8dcee4ef17571e1becc3f2d4ac8d5aa73e74b3f1115
+IV = e3b91649120f92b4f712644b
+PT = eca3606b9e2a0c7a1c6c4b765176f643
+AAD = 68b093733bd1e77448fe5687b74796834d1797cf
+CT = 0ff6d858cf0f5309c0f4b2747f6b551f
+Tag = 94d6ac2796a9b9901933a0f9e5377979
+
+Count = 1
+Key = 48b82b72fc81be86860f72065efa62186f9da596bdf95158
+IV = 24da67aef74be3338589ccb6
+PT = f86a57a30c06efb10ecbeb3d5a9d97b5
+AAD = c1f7f5c8f8cc5137a53991941f388ffd2b27f0dd
+CT = 4be58cd06378c03878d4f1659443c5d1
+Tag = 84dd00b8b03acb9219ec5116e3de7362
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 783e8302c2ec8e36f3caf5e14e8c61dcc20bd2bb90a01702
+IV = 625e5690395df430d2b9f1d5
+PT = 847f039af1e9a880181e92be5c63bae0
+AAD = 8473751fa178265600c7ebcd9254da67ddd47433
+CT = 020e94cbc9a041c750d8c19a48c9e0a3
+Tag = b922bab3f43c8f6ec85fafb7
+
+Count = 1
+Key = 20e7883dea0c89585e3c167fb86391fa9f49e2b4892bab6f
+IV = 86bd72569d27458c717185bd
+PT = 4f581f8b01f8e22d1485454134741b1c
+AAD = 3bb6dff478c5f8e8f5bebec27cbc64e44ccdf939
+CT = 10d7c954bc75b5d7a89383c7ddadd698
+Tag = 5f1c1d90ba706878e37cbfd8
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 60991b595b0271efc87f21a979d61ca8fb11ccfcc4726819
+IV = 0ed37872b369e4fdc3ea4090
+PT = 786fd2bc953160d5fd30e4e8cb
+AAD =
+CT = 685c7ebd80c7e2a5a586f10935
+Tag = f1712cc78b4b3ab7e79e7eda1efa2f72
+
+Count = 1
+Key = dac55319a3b7baccd67c84d6b8a40e69a3b275b5c87f1991
+IV = 14d586219807edfeb08218ee
+PT = b6b12ae71347924e073b95be15
+AAD =
+CT = 10eabb3b045cf56d7c3a81c182
+Tag = b74a572207e89e68078c2083982de970
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = d855ec64eea47bc827f034713bb1342cb5b615dc9509fdb7
+IV = d282ad5dfc33ba679918a12f
+PT = 003edf10af9dc6217b1ebdfa5d
+AAD =
+CT = 2a46856483646d494c2ec738fb
+Tag = dff5810e1b927d79cfc09566
+
+Count = 1
+Key = 83d11e19252800a50eebb51183725ff18bff68d43d639c6f
+IV = 22a76dc8ed4f53fda482bcd7
+PT = e7676e81e6a38ae1b94e5e838c
+AAD =
+CT = f1ec8767b3ebe2244b2ab171a3
+Tag = 95f65879aa7c8a13fb2b83b0
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = ea319c2f397022a0d1b011e59b6524dffc609a2970c39c21
+IV = f88c737fd24ad5804c468bbb
+PT = c02dcc36a608b2d5e95f93821d
+AAD = f8ef7628b75b405a37a78959fedc0bd7f8d0b38ec66f0cbd2aed154cb9240e2102909855f0ddaa3f6805cba53b53826acc49b8d9e66d6ba0df26506bfc1570dd9634a56448568dd57a0a087b6f45f1448d956d90b1d0eed8d271
+CT = 7c7dbe434a8463e2779b12e430
+Tag = 54d21140bd173e64f5932fbc3817654f
+
+Count = 1
+Key = f8ec3d87425b1a2050f8701eae0057ee21e41a7f9545ce6d
+IV = 63be167b73a59e8440dc6ff5
+PT = c02d51c5f60f66858265f083ef
+AAD = d702f8f12448ac1699ac493551db8eb513537b34287f2894a53b600e444dd90b12996b8704aa87e4e329a5018fa1da0699c6977d7b7e49168b8ff390f05ee37c5b2e7f2323fe884f27c708ce776a56a7771c6ac2f29f76d1bdc9
+CT = 38e52dbd1ee3dfa91e915486d3
+Tag = a49bbc775a57319317fad5abe5617cfe
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = fbc8e0b1eaffd4f414a1651851b0593c849b5338e999d0bf
+IV = 245f34db8db0b82feb877ead
+PT = 1a73b7f8c60b464248c1b151b1
+AAD = d8515f552dc44f31ed8925eee759336768e52a254cf481838d2389d53374cf20093351ca83efdd820f2f7f5d1f3f50c71e3648565cce6c4a66b1283893e15c4d318cd6e3597d66363b8751fcee59f5b61e7ffc9847e87dbc28c3
+CT = 0e903ec27a56dfefc59faaec42
+Tag = 440acd58ff48d3b11017efe2
+
+Count = 1
+Key = 766910f57cb6e5bfd0e17531459f8bcf2f32e2136c0d6f4a
+IV = 9c365287dadcfae22b9e6c40
+PT = 0adbad5ad2d8c92cae8421271d
+AAD = 2ed313c45c801ec29b053f0380b02b40e9426855ee86d1963b058d28c43c66ff510e11f5dada25bd0661098c167b361968c2ae9a69c35bd8a87c77991bba753edb3b502216896030daed087c9e9ce9a1a087157d318b5aa9a11d
+CT = a1c35164b7a8aa3e7816cd7ce1
+Tag = a49f216540cb09b96ebd5863
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 0f8877b56237ebca4685abddf394ce662a9c012d88eeeda1
+IV = 1817a5ca06e3432b2e015db6
+PT = 2fa4c38377f66842ad546c043c9ee81b33e6b4cd5a6647520fd5589cba20e366
+AAD = 0bb495977ba3ea02e8020293817ce5c5eaba0c5d
+CT = 7c03dad4c8ac7fdf40453b1484a4db42839a0a06b69951a573123a0d8032d6b3
+Tag = 3fc49f14bee122324aef236546b301d9
+
+Count = 1
+Key = ef0cc2c32c305abc1a206f33ed65f7c44319eeb8b8df79e3
+IV = 2c67c1f1abdbf03db5a251f5
+PT = 3d78d56fea1ffbc31656c54f9995b10c0de51ea11eb916458f453078de753674
+AAD = a441f88d2601e176920985e917cf31c97a9226e3
+CT = 13711a949ace619adcbf27ec65e32574a4ef7cd20263f0f454e66d63c9db85ff
+Tag = 4a2aadb31063e9954387f132ddc95919
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = c6320eccdc268622378195e3196375ef7fa760c4d7cd403e
+IV = 637b850ea3174252d31efc25
+PT = bee694e901ef80b18380616277496a4d7318e37f5565a3f9c40356565ac45ea1
+AAD = 6c71c2cbf373663bb61fd265afa7c8b8fdcd1c29
+CT = 0fb76b38017613447cb11e57f70b16cce4d42e16b10642f9516db2e05083a396
+Tag = a5b14f6a0e0549305db7a72b
+
+Count = 1
+Key = d03ef5b85bfda2f7f378100b318cdd4973fcc8c7ca2cb53b
+IV = 29798f8cd897b6e87161261e
+PT = 7038e3e2241f274a1abd51867c77223494e9c4184caa68acaf8ca73e2e654fa1
+AAD = 2cef713149c1c02f28656e85aeefb354777b4d1e
+CT = 4f7842334c7e358ed3e3c4adfdae1b40a4ba41be048ccdadd19d275042c72468
+Tag = 090bd9e6cc61846c5d886908
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = b33a0d6ecb0a2c4e4deab7e065227f7a5b056f96ecab3761
+IV = 464e4ea75b77e7a1fa330372
+PT = a8beff90519d7e537b0f95f97b9ebcd4d71fce3e59f87cc43cc4f7453319c973a4dd47cf4d7062b001e52828ee545a0ae27e46
+AAD =
+CT = a6f8564d9a4913fb366f83289ffebc7eeb3e240ac2f4030883a28e2778458894f7ad7d8f3e9a8ce32b27a0249f0c22454d7c0d
+Tag = d094b97785b7e0b09dc0008f4f0da9d7
+
+Count = 1
+Key = c9960d816f0e236ddfca65c767605678289ac9773f79fc33
+IV = 8b6ab5c9726761379c8daa5b
+PT = c6508c494f798af9b465c31cfa02851e5d9aba2d3af07c73f83fca27c3bbb46aef29ca772b69cc4ffa17a83d17b40cbe7c05fe
+AAD =
+CT = cfcc496b6a5fb0162b86bacca436f55f4268c37ddd9ff80d1ac11def67bc57add9950abfc36dfffba6f265b62889fd247a508c
+Tag = fce4b2fe11e85e89ea7e30c54241bff8
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = dadfc574aa966f80c7198490a9e98e69fa6633170e412ad9
+IV = bd1eda0b03ef9ef433b99431
+PT = feaddf879825c96f828cc3c2ecc73c387b0f0c8d5c95a284154011033195413d79d487f4acaca2a8d7426cbb87c3f0dd55f7b6
+AAD =
+CT = ddf55d027e2d63704c999638460f054aea29b456615ffc35081b52b8ec0d986069109dfe76f692087257dd427d11701c9c7b7a
+Tag = 9682008a019e73d3b6064af1
+
+Count = 1
+Key = 5114bfdbaeb09b72f7e0a952a59f086eb84d2ea0d7d9e029
+IV = 6ca1c99d7a07c3499cc2a97a
+PT = a728e2941389369e13457dcdb3dfbedacded9aaa1ed1f94406072a7550a1ccf05844b0dceb7fc1649d44a7a31576a59ce421b6
+AAD =
+CT = 2dc859ce6e3847b004750a3dce767a34971c408b662b5ccaf734deea6f333e5f7fa9298c920a80b00d87c18cf68e1438ab8e2c
+Tag = c6ac2c769bd38e5fb7b6cdb9
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 50f5cc5e33774f383235c64e77c502ca6c5d06ab0af6be04
+IV = 9d4c766490224946d91a99a7
+PT = 35df59329eb5fc30c28791164bf9b374df228d2be467414727f457a9dd0f079f7342e23adb06929ce0ad607116ee11718ce320
+AAD = 4feca4174889298e992b765dfa67d33219f9b23898f8e869b7f1fbf5d71d87b44edd963d1055618b9db7bffe96b7856f3197868d6ce5e755a6c751661773e1def403a4cf036151ecae67b35f2891285420956604ef31c9aab341
+CT = 77670f6520a34dfc05819a10f322b30e397473fe51f8274bfb105c2eec37e24951abaef11e73c3c425a8c4b2d8c3ffeb8ed924
+Tag = 5349ef7a70499f2760123c0d5dcf5a6d
+
+Count = 1
+Key = 9639bbb115b2523376926420bbf523f9650e03d56fe0de4a
+IV = ffffdd2aeab6163d02622171
+PT = e790cd4eab2aadcc854fe4683b957bf10f13ab4868bdeeefa5d427ca0c674ddef13244718ff2dd70d8071c161e53ddcc022198
+AAD = d38a465502b5a9f5d48e9f17c24dd9c1b80d2ee404afb5c408c0e6573ad04ec339ee2575407fb982e5ab539986c1f8f2a591171ed017f514ff0ffd48bdae03d9bb7f3f740049937a46e22466def4d56ea43e5a12e520d7867200
+CT = c54b6d577269588d9d3250f21da402eaae45b78bfebcc6e0dfd2f723771e7811eda192722af0aae843305a7f17f00f2a91ae60
+Tag = 20099e1c1481be5d5963ebf9249378f2
+
+[Keylen = 192]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = b69c5391a6cbbb675218c54977bb189a6ab922c24fb54427
+IV = 826ff82be6986c3b647199f2
+PT = d8a0c720c73d759cc6e9bc15ef96fcea23e47b03547d7bccc9e5daea70df4fb2975bde6684981ccf9999ba04f993f595c8a155
+AAD = 37541c7efd8704ce9101fe2ee6e3a56c3c0a25074c0b0675dcadcbbd39114c448601e0af057ef9b6f88b92e5b5c6a79963f3404e1281f0a53204edba9867fae9b78090a2c8c4d0a885a6eed03a2152f33c06623c6af94c09cfcc
+CT = 7600d4ad3a00cfa91248cdb899beba509de0daf32a363690ba1b160e3befd4aab7dc50db784da79a0795932d29048dc1ca5c98
+Tag = 378fba671e3555be2902819a
+
+Count = 1
+Key = 83d03b555e339cf35473092e1bacde0dd7f0887dc81c11da
+IV = 8a5c1f94423397881dbaf560
+PT = 914471759e614acd9b081f2089a2763927fe7a31bd806e9a694d4964aaf03b86018f88bba24630d482c8d66034850b51a28490
+AAD = 5d061328de764511092231392b39b6c6effb7c580424fb732ef3cfcc7fd44f6c3635098ab5d6e5c7e846dedaf013604112ae374a1f5541dee6c1b683f9f6549e2a673eccc6d0a1c48ce266d7756f73c05f402c44ffa8a4f9786d
+CT = fe48dc7e93335711932c2788e4fdc41f1a4bc27080e398e891f83761d9114d7a6484484944ed7b88397bb8b297ea9074f390a5
+Tag = 935268daf579ca50cc260862
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 0]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 80b9b8e919a62c42dcff342c68bc765ce27700b41d4ba753
+IV = 2f
+PT =
+AAD = cc4da3306a114cefdf8c0dfa15aa894d6fe66d64
+CT =
+Tag = e8a3a8b6beaf8e87810a3bef7ce3974e
+
+Count = 1
+Key = f099c36e5e098f6f47aecebdd4f48130cf90615642434ae4
+IV = 5c
+PT =
+AAD = 54203e9b489c70c263775407dc702a933f5374df
+CT =
+Tag = e22ae3c0392c120c5248ba215da37223
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 0]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 1bdbeb824b0b6c368a36423de93ac756aa5885c6cd8a51c2
+IV = 83
+PT =
+AAD = 9876f81a1d2fa1fc97eed3d629f8eb4f66322f5b
+CT =
+Tag = 16560fb18532f8cddb9356c1
+
+Count = 1
+Key = d241202fc886960b45b99b2a669008c054a91ea67b2af55c
+IV = 08
+PT =
+AAD = fc7cf85ece4a19aea636f7b49d2ee08664e58a4b
+CT =
+Tag = e4dc915d70568b84a81a80ae
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = d4ba70cb3e8d246aa66ebfafd26266b5f08ec3a88000e770
+IV = 13
+PT = 0616236190652619ff51ad2775f2826e
+AAD =
+CT = 52b5f106a01d1cef4c833099ce88a354
+Tag = d8acd529c97efbefb6102a4a9c3dafb2
+
+Count = 1
+Key = ad127ea7a80af4d011d9d3ec767f5c903983a3aab893e30d
+IV = ef
+PT = 1b5610cff4d5a3afa990b5a7ad6c6bbd
+AAD =
+CT = 10146871faba82e779d680d346036e67
+Tag = 64214a51af61c070686b8e957aa89b44
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 0204ed5e0b900e8fa8aaaa2051fcb70e0f906fdc16ded2fc
+IV = b7
+PT = 776f4649f5e8a9181382b0d8f42c4037
+AAD =
+CT = d78bbdd6dfe22123546f2e25dd5d32af
+Tag = dc1d336384a8514d80fe612e
+
+Count = 1
+Key = af9faa2419078c34615a9371fe6b73ad73ed7baaefd40774
+IV = 8f
+PT = 6868f28694c1e22e3c5e53965ce2a24d
+AAD =
+CT = cae03c9a3aab73b52212e281013eb768
+Tag = 53ba759177a3dd9d9c010997
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 23916395a159be56d8f5933aef9741b1cb1fe67fabb4a889
+IV = 07
+PT = ff740c06d161cb487e5c519a148ad7e0
+AAD = 890b5344b69d4b3842e9f34a13e176ce51cce65f35b81b992a8ae2ef977e08c8b1e5a1c81d2c921e8a6bce86c2c1175e5e5f4b964c946e163dd0d958b41196ca3634dfd4ec9d4a4ebef18392f2a931ba338868dab12cb1345193
+CT = 229fe65070951a9645e6c026259a348b
+Tag = db2ae3f6924d2702a1498645cd2ef011
+
+Count = 1
+Key = fc9513e4e6050e1943b87f4672753493dc32e68802aa2b7d
+IV = 25
+PT = 7ca1b667c77517256b5f818b013f3c72
+AAD = c8b6107fa2cdbce7d233008e6533fc1c4d85e5b295ad1218d0aca484d0f67de6499d053c476707b62a679e60bfa989b92b82d2e73bfc4058a8e420d090e66215e078a6e1dd758bd32e5a6a1725daee0a90025965f1ca7749dbc6
+CT = 7d832569b2f144db9881e031c65fe740
+Tag = e6ee37e46a86f7129f7cd7311b9bb66e
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 9918048e1bca6decb3430adace1acea31273835a95c1b7bf
+IV = 82
+PT = 52855c9038d1e92defcfc1147dd22d5e
+AAD = 84c78f77d9116db0af69cd50de4a8fda143089fc2cf2c1ceed99dacd03368e1e158412257dd83168d9652fc35a6062f9bf5acf01b54d5ce49baf75e38dbbd8bc528cbdeee5059ac95a462b77ec6c00c09bebb852ffb89f1a2f42
+CT = 37fdb08f2f8ef7361cac8088993a445b
+Tag = 8969ac140527a9e784617079
+
+Count = 1
+Key = a9287ea55180bee233d05ca5155d2469a7df9ba3739977eb
+IV = cf
+PT = 360eb72abd99943a9152d161402d50fa
+AAD = eda98bf625376e12618940cbf972121e1e2f140e374aa4d7c409240e43a07c054f349378978b6b23ca533a654c796fb0794c19a11639794198c9174b51dd98ccba6eee8f7c5d3f7c9e439b1ff3304529bbc2ef48541d663d4d05
+CT = 4ff7eac84f93421dbddf8cca0da6d599
+Tag = 80a3114f039229ea893098db
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 104]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = cc5099551cdb9897abd3f419f0b1a87ea102bb1f9e7def91
+IV = 36
+PT = 527571c910718afa58c7d23754
+AAD = a20026630e50c24eeb98e07d23367b8dbf98c629
+CT = f16aa704406b2506228873215d
+Tag = 96c2d4468390f2de32c970ae8643ce8c
+
+Count = 1
+Key = 8af1a8181f03f1a4e6b06ce4042abf33ad496d04d0a046be
+IV = 7f
+PT = 2c66ed6d4d79ab9a88417c86ae
+AAD = 98e0ff359c106b48f5db7b72089f811e76b5ad7a
+CT = 9168df34fea2d4984087a5c337
+Tag = 79e36dbbf38265113f54db5535990d6e
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 104]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 2a5a02843cfaaee9acefec808e91b4d1d02fcedd25b8f184
+IV = 7b
+PT = 86d946a9dc6c2a3387ac38bdbf
+AAD = 6c2db1a79211861a41b5d2b9e38236de50fb4199
+CT = de7b662f7bf7fd3c44932db90c
+Tag = 0fb93e76451120578d694d2e
+
+Count = 1
+Key = 0b4b7c71742a0775ff0a7077bec016017ca511208b52fd0b
+IV = 74
+PT = 92fa784ce2bf812bf03b6ba6d2
+AAD = 9cdfbe68494547ded35fd4ae84c877d129afb05e
+CT = 34ca2958e29631a1886827175b
+Tag = 40079028899e5c3f4b7b9256
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = ab7cecedcdfc4846923b550ac20548e01cf0fe2ed753ef05
+IV = 54
+PT = 5c24947d8844ebd8cada537f087d875c59c1097bcbb8efd09406b2a60199d06f
+AAD =
+CT = f20d35eae999e5fe9e1bca72531700d1a457733b61825832732b29065c8d77bc
+Tag = 68b0e5a6d127a0a782e09534be0f4d19
+
+Count = 1
+Key = 109a9dfda5917411055ddf9ec0e8b54db5d612caf50517a5
+IV = b4
+PT = 161a2b85051e014ceb29bc5beebcdf8eebcdfb549fb194f1bd0d31dd935ad5f7
+AAD =
+CT = 90c938c59e51f118be75234a51a0f7a410b0e00ab01b2c604b49faae9018b12a
+Tag = 01f28ad644fcac8a663693972284caaf
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 93f774b4ec6b64a44cd730f877804400df87bbe050ed6076
+IV = da
+PT = 3ef6f158bd1d2d877acda7bffb8fa80675fd3dbbc4cad448348245a7e6482b36
+AAD =
+CT = 01ed20a59a6cade446d11e41bb4e5ffceca069b219c3d5d36eb75be60f262b7f
+Tag = 75ecfc191857186398f6f3ba
+
+Count = 1
+Key = ff1d9d44d8b5945f5847630c50b97f0ad3dd396a79f80fd1
+IV = ca
+PT = 3d243353a6e9921924af392d31864a2703de5fc1941ad5983d8a73019f16cdfa
+AAD =
+CT = a969397cbbddaf7f2f3b26e4d2e88fbd9dc81d03b355f1a0434864c1d8c83290
+Tag = 69d8fba560a15ca76f468d0e
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 61139fe8f857cdbcb24d393b23ef4bd3239158d81a89c1dc
+IV = f2
+PT = affde43ef500b589799d52d11c487897526bb41726418658336f1b93764675a0
+AAD = 264eba27eb0e738d22f06e6510963694f8be2807060e823f250d1f96de632e58ea73bb8526a31fca82388de2eff227805e64095ec9dbb0fd6f00df97729960307a4ff7734cf75fbcf1959f6ecbdffc33d76070696a1d002309bf
+CT = 221a30aa31c77f0e11530c17f50147db6ad0f864574f6d5c79e376ce5ff00a90
+Tag = f372d72f0a70b9d8a0049bf655763409
+
+Count = 1
+Key = 326adfd8cc7c1e85ca1830afc5302303297392e9077e975c
+IV = d6
+PT = 909f3d3471eaeed20dfc94ce32521b9dc4aba90d1ad1fdbb216370778a6bce42
+AAD = fd92a80b73c0815e425ff777a020d5e103e1e804fa6db9c36fde456102b5b734e2ed73d0b0aa8c8c10c0327ce9b2be1f44af393bb1967744cb4224b9c8cce585c773bfae0e3863edbf5c33628f05f035718d91b5be37cc070adb
+CT = 504638d9711a21b8c5dd626f60ac199ba1160fc41e8e5ddf085a7c8b345bddda
+Tag = 12fdefb0f9ada2deeddf6a2a9fa0ed85
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 1c1702e13089c0d5d08973d2371c7072b18f7c88f705a57c
+IV = d0
+PT = ce25b36392bb630ea820d721037b6a04fc465227afe253ea20ebdac2e2dc122a
+AAD = 31c9a7e3bee0bab389a063e8bb627ae62853d1e3bf3d55cf819ce5f164e4b1cb42f8aaa626c582317570913e2fae936334b151dcf48cf484e66df3a20401b6057b085aaf98d589b57a3204dbb2c6f20ee241fe41c8b05237a9db
+CT = f836c4deb0fb2196dd9c945974f28352943bc984cb5f076e3605a90e7bb92ea3
+Tag = 4cf6bc443be97d270985b6eb
+
+Count = 1
+Key = e6971d922b3a0a22b85b58e76a27fa643d833b8f789327b4
+IV = f2
+PT = 8813a49b08a31b4142dc06f9353c9cb8ce6297b790539b2df540386b6182dd1e
+AAD = 2aea6e3062bd58bc67547d674347b1636e05c8c48eddb33ab237f631660fcb57031a993243bb4f6b3ccac3345d9b600cb07d95c9021b739cd203452ca7bc0d6f03ad02c65a418a11a8c8808cf20b89e1f5596294bee76f8b3d96
+CT = 9a2d35a0ec3d3acbf75729a282962589b8f573bfffef8f6ced5809e215b81d9a
+Tag = 09693f4b5c679c644a698006
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 408]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 5239df04663a1cad2db6eca280cfda6a592baf88c49725c4
+IV = 28
+PT = f577fef731dba70d2859ec2b3177b03c1855660a016632a9968983a917a335d33191ccba85dcd844009da10ab9411f11ce84ff
+AAD = e7139e5c3698f3dc5c67dd4ef16dd991c9d60b7e
+CT = ecffc2c4f2c6798bcd61205b18f4453d5fec4676cd465549fbe576b32dec9a1fa41d91b3738ca3b54755ce225f71ab61a96e91
+Tag = 926b3cdcdfe6fd285526c1e52da7f30e
+
+Count = 1
+Key = 3d1f4210ba31ef31ddd1c2597e85b75dfa807e74607b1bc2
+IV = c6
+PT = deba508b03bc472bc84673687a38c2cc98dc2babd08fd679907dc3d88b9298e161532f5f0493971dfc2b1872e1ee3e7273e8fa
+AAD = 9b83da236baac3fa53fe9cc6c00877ef1405f57e
+CT = df9b2b5d5caa9849af0e48832ea10ff1cdb60d1356a73cac21a04c243e22b87721e8255ae7cdffbd2b685e8f2df7dc825e0e64
+Tag = 1a8cddfdc64113c9f2f9d5c1161632e3
+
+[Keylen = 192]
+[IVlen = 8]
+[PTlen = 408]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = c1928b65261eea1aca85a9d2a4c3c051d26f41f9b93c591e
+IV = 13
+PT = 1b46b97bd1223dabf9267911d6d17cd76b69feae9dfdc6a844f9263dc4ac504a42028cb4cc4b2e41279c1c9e4f49b6baa271ea
+AAD = 46445875d05a85b8ebeaa79ac57854c80c9d329f
+CT = 03bcad72fd1649e3b5aa68dcedf71d4fb3a1b2af430ea9096828f699ad5bdb3f43e0d60858f6c8d9ae5fcb7b3847f6ec5bd9d8
+Tag = b431b9ddb996f7a5a71bd9e0
+
+Count = 1
+Key = d057ed90b0b15296ba75b27592e68af16c34501652049acd
+IV = 00
+PT = d66ff03bff29fd6f0f715d7a3e89789098a68d56f6815d3f8a1febd8368276414747b06d27a64c2f68c55e5e88b3c6d2e8f342
+AAD = e4f2225ad4f20cc55fdb6c7c2e5aac8a7687ac48
+CT = fed615cf0830418915bc2dc998549b4f9230ce4e7361c0322c318ffed85c3337f34d94cf4bb5cc349c58c3ed2ef1aa74b1312f
+Tag = d0b9ccb83eb4e9a10a8b5e9d
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = e2a1ea08eaa9a1916851e5fbb9e9d4628bd704a77d306b40
+IV = 626d60630abd857fff553543754e9f3f353fc83545c1f727e58a3dfb5ee1b5f17972a9fb1ed36053f3902d42d3fb01fca552ef8b56e2b9790c0705b86f6b386181dab5d04b02179bf86797b2a079fe851f7b4ce248df03e8c1b613baea10e1192d39104902649c6c9c2a396865f4ff46919ee81beacb9f5e9ea85bbc883b6a75
+PT =
+AAD =
+CT =
+Tag = 5848c439467188c8653e129ba86d96d8
+
+Count = 1
+Key = e0bb619b0cd5aea7ac51142e1f3a0c3082895fc6f018bdd8
+IV = b4194a138cabd880ec097e23aa579e48453f532b8a006bad9d66ca41cb64574652c6fddb04d9b0ffed141f9d34e34831e4f3cc2d7e98be030bb57ebdbe2a90496b65b8edbdb48c46b9a017fcc5f7136d425f36bc7f443599136094b7d323e64651b6d936ff55f782dfe912c8abd9a06f55bdc364f45cbd17b94c5e74a45b8ff4
+PT =
+AAD =
+CT =
+Tag = 0c524c45c8350ec100024b6fc2df0150
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = bf1107662c9d3d2032360301aaad2949e253850e6d85bdbb
+IV = a23cb98c19be0d4768b16cd77fa4bdbffd9ebac5ccd6c920c25c8c061c45374e73110b8f6c6147c8b446d6fd3aa5d03d946017c466a81c677292118b0b05466b9369c6f434a5db5de1cb1265ab77f0ef8bcf3b36ac695b91535485b0ee8df815ffb0bc09d317eae863a0e9debc52f34ecd7cbf38ef2f7fae5df8f0ec4de6d063
+PT =
+AAD =
+CT =
+Tag = b0f3ca0b16b1603a8873714c
+
+Count = 1
+Key = 6cc804e9a1a3fe6307d67a05bd5af859644056c64ffbdc50
+IV = 6bb46cf22eafccb74c2ad51e348b7436e1fab2a49674c0c2e7a6a9a43a4e53e9390e89d750620eca394b693cd858c81363bdb4b4ef783f197e0eefd70dc3d33195d1553ec50dfac00e4ee46b9853964631e295e3519d297a9a07772dbc082dd01a8a06094fd48d182e18a95e8e095d13b7c06665307256af8d2959d593bc2c02
+PT =
+AAD =
+CT =
+Tag = 8550c2809d5cfa70b0acf1ae
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = afea1210b8f606fad4443424a2ccb0a2880f711e12543870
+IV = cb5e27f1e1e0949a8437d2f3a5e80e073d1a0503771291553287d59d51ac5681522058d825ea56b076434a0bf8c5b0f03ca42d70224e6687b0ec95e1bebac5c4d2c5401326ce99f4a2f0d408a41bf7c77bc16cd835fca9aeda7608b3f8e0828570bebd6bcf99066e4a306bd1f429a676a16dee9f92e58cf49ace42e559292bba
+PT =
+AAD = ba03f799f15ff6f1787ae63597103c673e8fab3425f843a6e04f06a7b0ca0694cf2117aba3229ec284c2c8cbd1ef44915dda4738866c9b9867fc6523b0799f2c7115640405557a4aed7062d078e3f0bd81e11b930a6f6022b22d
+CT =
+Tag = d8d0bc127e6a35a53ce2313c2de2771e
+
+Count = 1
+Key = e25f8d19754871bc4425cd7905dd997d82bd3d32aa4f07b9
+IV = 5e07e7bc2e56df7075551704a96fa26b8ae13fefc7123da22875bce45d780b7411b11994a1b71e5ea5a032cb2268fc8535a6084e93b4af5d564dc0162c855a4daf0422647f805f3e71fd606f7cf9e0af55d610eee038a9b8a80f25fdff0765f5f850e7705e4d1246bc3f0baef6cbef8c1b3daa40a671d8343c4fa6f286d7b0fe
+PT =
+AAD = 64533cfb8842b0df6c6901df6f0e26a924de049aacf7543ea9632464390d832de38a72d34524f6037d193ea1008f172e528c9e6b578d6631f662594014c85a1f71a2f38ee0a68d1d5bad008ab43127820e3ba7352552825a6a18
+CT =
+Tag = 46e89fbaf516ad0e0f2dbb73f2e57c51
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 0ffe86fc130ae9daaa8adfba6435af803e7d87169b91a497
+IV = b75104fcbe6b8d292697a0132b2b5165dc2961ebdd34984b9d884ce69199ca52fafb159393c55e9f2f273ba49a9a94096be9f72931a7840d1d18224b6553606270169c693808d9765fc337f8f203c42f97174b65e813da9708bed0cca008b194173da1a0224727a5650e4555a32a6997168769ee05db135651e871e0e6261da2
+PT =
+AAD = 1ece3ab177d3e12535e17ef94b486ea96b808f0416327c3f0e8ef23d2987092440e3b86cc37690dd8876da6e858bed9a1ffd211473bc9f5105b702d5e75a49caf6ad532ce9b65028577e6f95e5898c366bcc20c482fb6047cd93
+CT =
+Tag = 6a52bdf0a184b5020e8bc4ab
+
+Count = 1
+Key = 41f14f23ffaf57f6e37b1dd64c4f36b3befac884d1f87273
+IV = 6d13c7213b8d1c962620f232d486577329d7ecffac4c893dfd809eb4bcd943a4c1037b84ea48a1e6e03b140cba9278f294d253eb6efc2f7be997b37c40d7eafae8dafd1f5d60c4755f22b2f76ace887e57560aab88b6262caf63d476f4d78e93ed4301b9ee9c3579943c773481564670b8f47e4179ab8e6aa1e0580e021622da
+PT =
+AAD = 3d148728396a46e1b2ae7ba8c5cdbecaed49af0e47f16ec57e2e48b9d5c2d8bc10bdf2d47e03b4b2ebd59a740286fe78255cd3899e241b492b1ad681f3416665f8656cb31759b1d72e842367167725b5580e5026fa035ee4a5bf
+CT =
+Tag = 7cecc4c65ba04f4f7511b60a
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 35ad467d420d512584e65c91d9230a357af61f5f0532ee5c
+IV = 21fa76492a603a90b14b6d43eed4cbdc66afdbbaa7cf5b0502184ac8af7cb9b02c9447c2c36e9ed131124144a6f07e5bdb3fe2195a48ed46495e5c5ce1e79d05e5b56b491535d05f07f83f3cfa8809d14e46a4571974b0fdb076f1ba9395360fc1ab7e9bd5672b67d0816e885e52bc13375fedc5b83e25a3318a5a9cfb960017
+PT = 65a86bf404221ec8c3bbb9a5e8a23473
+AAD = 73e5399c0275346f1d091ec0ffe151ff4a2e23ff
+CT = fda5498b95c8061e20469d83507cc466
+Tag = 59f376f641caa13eaccb108ca894c7d4
+
+Count = 1
+Key = 4a0d30d2db900a0d7674ca1223d75b2b6deaf28a26d8099e
+IV = f6331fb3517bba755884be9fd28134eaf2ab404e26ead74c5b74fa2eb62700bad2cc0b95f0eebcf0a116f3265a8dc4cc7a77dbf5f312e6092b3c17695e825923b0b7718ca9dd16885066dd6b3c17c0e0121a0ae8323d826597e0cb87c82595b154e07e29ff21d8ef2fe76e6051e5b3f8386289c7ed986d95a8a3960c494de9d3
+PT = 8136dcc2e28da27f1fbff5c8e0db39ab
+AAD = 7f41212f3195ae49e7297691b637945ca94e41aa
+CT = c0cc6628d00dde676907dc835f451d94
+Tag = 2fe5f224c32982610326f0c0147df5e2
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = ff5c4b14c3e0e2cd4131d3d38374f6dc6c88a69b31af3228
+IV = 08709ef9ae66c10aa63482bd2f9a53362bf2f16de46abab29b1c7227a0fe1a421a93dc0a2fd2d084f113e041519080f5c69e81ddd718e30647b7ba22234e358c5069430e5e3035c2d534828677f696a9e786270a00a1676393ac75bdd565de45dff3019f7ed7f318db78563de90bcb5172cbdd1d4e0429c8d298b1a24a627672
+PT = 529c0cc1b0fe42005f2e3c791086236c
+AAD = f58f5bc9e1ee1d8877265710cca6e1761d9b4787
+CT = abef1880aad86d50236b27c836368475
+Tag = 99faafee1306f767f80ecb8c
+
+Count = 1
+Key = 4af71e8331c1976e7a0f45e6833ceb97333da44ea0dcfce0
+IV = cd76a14d3708210049d50d81f11ba875709f2ce9c6e0622c03fff805f420cd36d661871e79b95cedb12cd1372a3d1e447ea2bb01874c158ead8fd53ec826cb7b5235f1a68a44db184047768b97a72ed4b8f8c3b2cee773035c6150559520142308b8fe94f654496f892e5c709fc2ba3d117882aeef939d6b78a95a3c86be17ca
+PT = fd43af8c7d7fc4467254af6d3c9fb11a
+AAD = 4f1912d4fbed7b636484c497712f2a43e11812ed
+CT = 73b388e2afcb13088a85b83e9036089c
+Tag = 73b4612018d2355c8ab723e0
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = d8a2c8bbac785f20003416804acaba3d51a293f41935641e
+IV = a13fd29fb79b4a078e1dd4568c67afe29003565cb864aa7e78b48765b98a4ffda3de8163de39e21fbf832f250f23d0e688f9afbc6fb16d89cfed8da4707b9bd2620fd4c4d0f2bbd1b38aa9e1e3d8148650bc746299e34d5f602f455c97213c777f50abb2c6aa500da5b5916a166f8050bb56a4922bb41a27bfd212792dd02bb7
+PT = 9413325bf2c0a3c23bbb70f547
+AAD =
+CT = 9589c64389826275ce2641e9e9
+Tag = b797881186afabc8ca1c778b8c98c83e
+
+Count = 1
+Key = 1c2038718deaefbb7f8c5a68a71fafb10976b9849989aca1
+IV = 75022e4eed66c7f85449f7172f104ce9c8dea213a45d3ed887781b052132533557b4e081e501203b0340fc126af43ce5eafb10847025267b1246dcf440d0d498b9ace5dc56e99c18457f88c3f5a3de91c288d544e2a125289a6a3e8e427fe13956efd0a806b5a5332b2a7f52f9f37cbf72774cb778d5dd0309570c2cf8fa38f8
+PT = b6ae24192726d4d7efaf83017e
+AAD =
+CT = f2966740d814c04af7274ec136
+Tag = 2398e809868ade75a653e0666b8159ee
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 74313bc39f67721c93d70f309ca70220888d72ed0ff7881e
+IV = a678dcfbd3c0fe13a1d42ccdb52b43a216b0d1bae77cc4f308eebdef82d41e6794e8dd3e7e9eb5bdf232ed92fd28c0d2f468cb7864284bfcbbd57308e7877061a2fe0c30c5167b8a431710d2b1aebd367891ce80198537fed3598dda9993147455dd08762aec3945cda7c92a1032935e998935c26619683b69b3251e5349a94b
+PT = 3cb0af03b36fc809bd9a53272f
+AAD =
+CT = 41e1d4021b5bba4a0f51db95c8
+Tag = 53bce7c8d7c77b862639acca
+
+Count = 1
+Key = efb8b5cfdf28e111574a41987906d52df41dcf295ff24838
+IV = 0d9c27ce31ec8e8c0b4f5d2c40c4d50ae35864b1462d31fabfcfc754cf13b475855f99a228d5ca44a5b63fc45f56994124d1fcc86991865b9902c9cdca5bf9fc561c5fd2c5286fb1078b58cd67aa95f7959a5a9b2fc6e51ebf3653888e6ad4d5d3a0b0a2e50f993e3c2a518c24e486860a43ac642e555e83a098f19d43c7aa52
+PT = f44d68d4027fea1f0abf51d320
+AAD =
+CT = cca2ff1abd31401a9570453d81
+Tag = 5689aa30537db65ba40d048f
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = c627afee48fe8ad98dc0aaaea2f5748e744bf811fbd70d79
+IV = 5f10f4b21d14dd1d0968118713220a7563f49a8da078721a57ca7f9205dba685458f2b108d302216ad51be03fe6c9da7b45de9b2b4122dfa97a9768bf1a05f0715e3f5503eafccd847c807a622aec5971c0738fc28691479424a41c50f118993b98fbe506db939512d6e97e5c540610ef64245815fe642d81edc303acf926ad1
+PT = e65af9e54a6cf6baeb15d4ed83
+AAD = 2bd7d3cd339460ddfc3563a8ca96a7913a4a97237d39b8850d39e0e5cf0f9522fa935ecfeba5f048cf77daa8970830e3e134aacac21698c1edb3e4d64b99c280f44afd49ef7e225d6e93d62ed4cee2ac4df28a0bdb01834401ca
+CT = 596068b16b580c8e67abc42d77
+Tag = ab8c04bf37eb1ffa6f846caae6d3256f
+
+Count = 1
+Key = 0206bc3fbe5b992bc2cc5cfcc3221e211fab814b4502623f
+IV = c43fdeadb42b470f8571e856fafc779e7ba769b301dd06caa58da8e66832e45d2b04c5241879d8d0408195694f052d7fc9463f6682520ad747dd6710284a006967afdec03dc494441b76bb1d8b9c646970ffabc143ac9652d6c10975018457f584ec2f5ca2c2f7a479dcb38adb5f9c6de55adda975527b93561e9ed478bf539d
+PT = a50529b69d8f5e7223e91408c7
+AAD = 467beeefa0f4e17f7fb5f530c3ffe48cb9fb8856d5e2faaf6e24265081653b8210d8023c1f010190ea62102255bc8f38242d2c7646d7cea27bda40018571733353cc9e0980c03000efbe199aaa68c55d191d42b733ec3d60e24a
+CT = a6ae169fbf992f93a67ba42c25
+Tag = a819feb82633a49ccfc4c0e1bf436060
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 77f631e41d5356a8313982802855376a2fc898cf553b57d2
+IV = 90ba972b0c868244a189642cae4f065100591db1faaf0c9485cca7c4c1d7ea0733984a83d5642cd581e6200f0b606b77152e4424959a3d61cbbbf1a8f05712e48edfd86475566cc04e592fd143c5aba6051bdfdbb5e44a3efedbad9dd35b246cfca22a73699e404f7770721d6c8fe40e1e1a8d3dd1c901308d23fe61f8c65a1f
+PT = 6c3c27ab3b6446101968cde87b
+AAD = d6b8e5c5b4d19a3e06028a8af2aea20bc0c94638af100a0289cbd5e54718b4f803d3da83edb415ed285ff8f39c57efe18b8e4e4cd02e86ff9187c3fc7bbaba03bb80a049638b2fd86006369ab48de3c45930b7b9ad780bf30695
+CT = 8fdc39969d24cf23b0c91caf48
+Tag = bf17fa3e070ba09250608d9f
+
+Count = 1
+Key = d0e6dbb1d302f0d96405db1b7660d9d0d4138087fbb2eb4f
+IV = 938c08f1c5423c7802e8e0425cfab47e891825492567e5ca0789ce871f2ea059db31fd8adfd225347244a20508f62c6da62a19bd5c5f1caa291aa0184caea7462a8fd3b443d95f87435b6df5b58acabaf196ad0f2a86253c6373ee36e8f0b5ed64a70c1185052c6aff332ec1e71ebff002c38946f1511abb92eedbd69b208671
+PT = a397565f1aa0dd09509039e7c7
+AAD = aae36ef18429798dd9a3dd177767a0dd37735a5014bed7612ab7a3b79f28e29270b066639e1a8c85411220c7ebc9be80bf7867d204c489fc85df1482aceda857b9d718a15ca1eeb2e1fd233bb2d2ade0afa0bb5b3087c354a3ef
+CT = ab07436a63bd6bf4647dd40a75
+Tag = bf95c460de66f3f799e4f08f
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 21083f3cf33e0e24ec60a2c3afdc45f92752bdb2cd450e35
+IV = f396349841fef65c7c9cff065999d783b9edf8b6ee839d98d9e413752e6986a896a964e93e3d68dd1c1aec1d31bf393e84a1d2df2cf22c29959f66345771148282322a9b47ed4d3a8038fe6d6a6ebc36880bf3abc336dee9394c920bc8b42a76667591e83d19ed715c23621568c8de81eb0d60531cb50d6358410d3c7ccb8d9b
+PT = fbdefe689a27a20132eefb256b6c3f63901357c4cd5c5d2067abfe998dab2564
+AAD = ebc7a472fa20ecec375c799fcb0fbd3ed9addf03
+CT = a08e95862ca659d992d20951096c04992a68cc7110f2da5b3bf5689ff4c9575b
+Tag = 9c387e0044f12f6a2746a177e5ea5d7a
+
+Count = 1
+Key = ab2c01521998679bac06355b45cde2b1d8cf69cd48483500
+IV = 923ed41f4bf087f341d78efe76019342fc83c0659eb6f2b8fa0668b527e3129525e5303b45b01d92eb0a27e52ccb680536554aa41ff41acbe8476cf03dee87363a9efbf910e50d2d141a7ef301161f13f143dcf4266068611b2aa2317df28e83b4f836268c1380c4c228d5f0cc0b161228caa360fbd2a01d9fceb33fe669dc83
+PT = 90ac6c25a77ec7ce019074f4a1607d3758a213e0e19c4f741a3ade5996a014e1
+AAD = 435b5fe83e006a35cf63c134bcc2497925bf4fbb
+CT = 9d6fee7c74888ab4f830301661dee8472027206cfa2efa243f6998a455b8eb54
+Tag = 4897a9e2029732d9b2afb26d7e2d260d
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 90a298de1164693511fa0c728eb519bdec83d29a74404f1b
+IV = 44ce332e34b5712cb35dbd0d35ca9b9b1fb5f26baaf51610a6d3f9d4f9dd1e21d6ed41a0ed7e929bfdb8771734f32385d9ec502608bddeb28dccf23d8b085e6b8aff95fcc671f80bf7b8bc2ece86ed92e0ad85ccdcd0b73d2e60b85f670f25abcf2b76b5f1098b540e7115af525ea731ec7dfdcc6d3f02a09bf29b885dc77392
+PT = b5d9e025ed538e795361e05339029c2da732c77e6cc1bd9426ffb467ef78d44c
+AAD = ff5cc7223bbc81e4ade756d156d92e653ae1ab37
+CT = 2b52bab5a26ac1f30acbc96dfc74d4e027d82917905da9017d7193dfa9207f40
+Tag = 6953de60cf69300babb08ad4
+
+Count = 1
+Key = 4ada4aa319ca480709f657ff8a1d21cdf7b75953c6fe75a2
+IV = 0abfee5f0b6d952e3287bd5cf13b8060ab26149f3d523aeb21387f2eb7c769bbf8a3da2e2f0fcdf78bddff582ee10656b015322376b28879e18023032eb553232ad87e1261c8f804ce500c2b2cfa9c896b26e66ae38e546e304ae9b11b15cf1ca456c7600b94571ac35c1b16c25fb835828c05a27d6424ab4c039f004e7c52d6
+PT = 7ac61800b6050d7bf74d000006c4912613812d69fc747378b473bb25fa3b9cbb
+AAD = d181d92fdd4192770bda8aec5f230df77e163019
+CT = 88f1cbf437427271b21686f1b03ff5f0015bb949399d194648b49f489310e92a
+Tag = e807dd76ce5c74c8b3e86ee7
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = cfac7149777aa3c7d0830c0c5e57177e6179810c0b0342a1
+IV = 33afa54bcfd3d860e21f39ae624e9341f13deb307333e0194379d3b5afc9c08a31a0f31d3cbb10cbf70fcb3a36958a341301a0626223955808ef22fd83f75eb85209c52eb61ea65fef26a2c22fbc50bd9750862370ebecde410218ee847aa5d39960f83079f660303f70cf2c6f243a362e4e54628b648b83fced420fe2ee136c
+PT = 691d74a228e2976e81e7c80d5b80f9a0d6c4cf2efac39bb26a124f0c4887736261209599dff61962937e51a0271d61ed2ff03c
+AAD =
+CT = 145beb0d35cff0e22aed593552476dc4a282b77ee3332eacc99909ff563eadf2c456ea130a1d112876cf32e331f6ed8d7be86a
+Tag = bb9211eb2591a5d0db729d5dda312a01
+
+Count = 1
+Key = d7e8f81fabee45e547ed9a0a5f4e98ba0da186e194445fdc
+IV = 20368cfa8af2ed9a66edf75b8392adb76de8b4bdbf025e6efd7cfeb8a1bfbc6551772a12242f018d6c8d302edf5146045a3f170ec6a24086e2c28f4d2378db618249a154640dd200cbe4bebf33693ff2063eaaf73a6682779b8c4ffb4e43228ccbee778c687f2597f480c8ffd66976421db783037706a97d631004648272b33a
+PT = 81bde22fe31cb78b989b2c4aff300e4800039b021bfc4f2c7e2e6c4650edf6197119517b902987af6efd2527268a554261cd92
+AAD =
+CT = 7744ed5adedfdf1dcbb84a33308a6b95592f333cd5b3375a072a97dda1e0375fb88a56f27c2f6f172fb895a1ccea9b13109428
+Tag = a570278048683ec498ca656458caf539
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 4a46966379d369a1139e110e13660c642de80f0f5b5fe64d
+IV = ab8431c880081cec58186d5c15d2e602dfae46089dde3c205b168ee12af2b0de52a0ff7ecb02ff5f1f332590aea64c5961f5dd3dbbb74475b4b1271b3ed5688bfbee2939af0f9a2865357d9c9c6212ae8c020a968aa50ed4ac0a037149634e892320c81af54c362c143dac06dfadaed532fd1dcfcc1f98ee2a2924d437e81dfc
+PT = c9f0386ce298995f479e2127ba66b253ae111b47d9375fa4140908edc9d2c3f9bbff64bad065af084755dac27b99f684850234
+AAD =
+CT = dfd7923f5af4593c70a507b606a6d9f786de7205abe4a04a4ebec37fc4ecbe539710103e645a55d4e9bd98a2318d090da0c9bf
+Tag = c221234d2c30a389c4ef427a
+
+Count = 1
+Key = 6c7469efbfca5f8d4dcd7d5fe4c968bc0ad6e2ee18da5375
+IV = 01042cb4554fad9494f60394e41850140259cb1528d3fe3bb82c6d1161373266920f98a895f227055931aa0f5d233f3306ac6820dd8a419a4d75014d355dd2fdc0aa21fb714cf9649cdd7f5c86c3e60401820b4bf8f7e3a5fdb945f505b4980015a5b990f15fdaeb6d1d1cfc55f482445fd6e3b90ce37a3a3359d6f83891f9a1
+PT = 490d288f8e94bb9a822d98a2d13c5b588b3bc52b2e3afcf1b2e3fc9f68a2734fa1ac07218ad33568e766e974a06a546c964a4b
+AAD =
+CT = 306c1a7a2dd0319997a2370b39b732d544dcf0d5af2e9c9f727244b46747b736b99a6150d86cb80b0846877a76f33cd0a04ad9
+Tag = 024a3fe589288487ab0db4a0
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 9dfffa5bcb2c5a5e9e2ca7e2dcaa474763ccc6978b0c2c17
+IV = 4407dd3b93339b7f67fbf0471b7da6870536e979b30e1b8dfc6f1d4620c842b885fc44f07e80bb3bf62ac6684fb989ab56246deeedd7607d7be12dc2f1f7b1e68e4e49560a9c297d58d9da241474c866164528ce022bd6e48ebe4f0c3a27824d269869d4579dd98263252167464bae1b2972c7f3f942578d6a2592083aa421b9
+PT = a39e9b9a53dde1751d54be6a0191eba32ab631b3b830b27e0ab2282c25769ea551dfab10133ac174a74e71b9a0ec8f2842c123
+AAD = b0a54df5cc522dbe273a7e4aa9c6fa6d01e2071418f596015b7c0252b54a039dfcb2424a37fe47b735d195f2ebfbb66e5695e4437eb07efdfb5162a688c0ce42345d29f64299fada69eef182d6d99f20b0825bcd88e318cf949c
+CT = 3d48d2551e0203bf9a9ee7ffc30bfd3f3043eb98476b5a349d469fc8105d8abed6f6256ddf15d8decfb60b63e3252474bf5e9f
+Tag = 897e580db5d905febaa0289276c82948
+
+Count = 1
+Key = b88d5bff0007ed8e7605ab63db5fd5019559fcca5ee1bd90
+IV = efe26a67f614e64db29e2bf0e4aa5c6641946a7a4fb680ca9bc745508f573393ba8e33c661e9e82cf6f695053056124d7065665f6451161782975d2439c45725aa23d9b1e6635127cd71cfbb8935c1a0e51b832c689b3ffac11d2f27829eb6bb1c3a362c1aa5a81975159b0c25a41ad69e466803db514b2c66f7125dd00d746e
+PT = 9deb9aa6a958ac1bcb602c1190c7099af003dbe6d68a17dcf9f825f528bb0fa827529109204697877cb6e18d9e89c55de76656
+AAD = 582f0c8353a67b3c8a6b630db3599d1e10e39407ba0fdb1152b7e031efc64ace179c2f04a2bec5cb89ea941c5d082e54ce991c3bb79a6506ea0e5a21ebfcae05e34004c2cc7113298721dea42732a32ac7fe8607eaa7ca288399
+CT = e97b930acd8c80c942602dc46b0f2417422a605938dce7c0b81e4423a7364641456ce0cdaccf8c29f846f902fe60adfae97d40
+Tag = 3dd41a503bcdc84cb3150d5f294eab25
+
+[Keylen = 192]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = d1a313e7fb5ef359bf15be1768a5115c438faea304a1f38e
+IV = 9982f5f37697c852e72bc5f35394a6dfe93f3c69a003f7bab79fc374eb468e895de9ff099daa67f0550b874d6751525257b30654d9a906fa7b6db3751ca644b76f9e69e840adb0c71e4d38ce3f6e30f4fa803b63ec01599cdc14302d8fcaf54955f5716d1cfc01eb56657c974a29db8216c387f26722884a2811bbd2150995e3
+PT = f58079099dd7daf50c4026ca1dcdd54516fa7f2a006c1a4304bfcb91c2e89640b770be994d6aad9354798813d6dfd94a34f6fd
+AAD = a0d218ea6a5b0d5c5b33eb14cae62f6dbaf1d7ab95febed797ff0b343fafbc1e2f7f5eb23ef9c49178eedcfc2dcd3257d3abc1a4acaad4cc1963e4ed88b29a3c63a093d8fa94b0e195487a5626c562ac25f99342894426e8fa11
+CT = ac1533fc24949acb34663130ef48bcdcd49d27970f5189afff1260b8956380ba2eb340c57cf333606bf2319d714c5bb642c29d
+Tag = d9a24547a8d0d0ca7831bd8a
+
+Count = 1
+Key = 307743ab87c72bb49e21b4caeeefef993fd9eb2022f3cf35
+IV = 808bf8e1cca359d981cae88061defc9bc1ec908094eddd215eb0d0d15572ddfc5a594373318a2942b92c09b059c04534a810e228cd12627e7448130a06639f0118aeac07fca7c6307c99a7c1d034a1d59bef214b594f6b872064230963042c7a21e69e9b3debce00e25c52a6dccb3c1bd2b0cc83c9f1a92f9787689b36e000aa
+PT = 3bfc3293e71fd528bb5c409d5033a728aab59ed928edfa27a1be82dc3c037d292697cbbecdf76179f43acca35e3726a1ccdd8f
+AAD = 2722174ead9b8e5af53a83e79eb4503d990351c9f97ec2b915ef37f39820b7e54616cc2c65c5980c8892950c8505c8cd9ce97cb8a41142605c3c22e432b3810f3e8b86d9527c02ed77ee0e541ddbb1aeb89834138a1d469ba36f
+CT = 9806371706c8d114edb6b09156213e45dac929bfc284b921f119a27b692cb55a3a7e38ba01f745d6a6b9bd2eccd36cf3db4389
+Tag = 3b9d490f661849542b360f00
+
diff --git a/security/nss/cmd/pk11gcmtest/tests/gcmEncryptExtIV256.rsp b/security/nss/cmd/pk11gcmtest/tests/gcmEncryptExtIV256.rsp
new file mode 100644
index 000000000..1b10fa886
--- /dev/null
+++ b/security/nss/cmd/pk11gcmtest/tests/gcmEncryptExtIV256.rsp
@@ -0,0 +1,1016 @@
+# CAVS 14.0
+# GCM Encrypt with keysize 256 test information
+# Generated on Fri Aug 31 11:26:26 2012
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = b52c505a37d78eda5dd34f20c22540ea1b58963cf8e5bf8ffa85f9f2492505b4
+IV = 516c33929df5a3284ff463d7
+PT =
+AAD =
+CT =
+Tag = bdc1ac884d332457a1d2664f168c76f0
+
+Count = 1
+Key = 5fe0861cdc2690ce69b3658c7f26f8458eec1c9243c5ba0845305d897e96ca0f
+IV = 770ac1a5a3d476d5d96944a1
+PT =
+AAD =
+CT =
+Tag = 196d691e1047093ca4b3d2ef4baba216
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 98ebf7a58db8b8371d9069171190063cc1fdc1927e49a3385f890d41a838619c
+IV = 3e6db953bd4e641de644e50a
+PT =
+AAD =
+CT =
+Tag = 2fb9c3e41fff24ef07437c47
+
+Count = 1
+Key = 01946bea150b705b889dd1673c195dcfb5d51d21b865e88d06db376b2346619c
+IV = e28c1b8a48d2c7b968e6492d
+PT =
+AAD =
+CT =
+Tag = 5950a325bb35de833f22fc2c
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 03ccb7dbc7b8425465c2c3fc39ed0593929ffd02a45ff583bd89b79c6f646fe9
+IV = fd119985533bd5520b301d12
+PT =
+AAD = 98e68c10bf4b5ae62d434928fc6405147c6301417303ef3a703dcfd2c0c339a4d0a89bd29fe61fecf1066ab06d7a5c31a48ffbfed22f749b17e9bd0dc1c6f8fbd6fd4587184db964d5456132106d782338c3f117ec05229b0899
+CT =
+Tag = cf54e7141349b66f248154427810c87a
+
+Count = 1
+Key = 57e112cd45f2c57ddb819ea651c206763163ef016ceead5c4eae40f2bbe0e4b4
+IV = 188022c2125d2b1fcf9e4769
+PT =
+AAD = 09c8f445ce5b71465695f838c4bb2b00624a1c9185a3d552546d9d2ee4870007aaf3007008f8ae9affb7588b88d09a90e58b457f88f1e3752e3fb949ce378670b67a95f8cf7f5c7ceb650efd735dbc652cae06e546a5dbd861bd
+CT =
+Tag = 9efcddfa0be21582a05749f4050d29fe
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 7cb746fbd70e929a8efa65d16b1aa8a37f5b4478edc686b3a9d31631d5bf114b
+IV = 2f007847f97273c353af2b18
+PT =
+AAD = 17e84902ef33808d450f6d19b19fb3f863ca6c5476fa44105ab09a34ad530b9e606ebd606529b6d088a513fdf8948ae78f44aff67b6f2429effc126d3c5de8cc2ca8b9bf7a5b4417c0a8a4f90742637d73acfbb615cde7352463
+CT =
+Tag = 44ecc2383ae85a8cbad1f1b0
+
+Count = 1
+Key = 1e421486993c6d187649e3a4437f24f128f8d542050e27489ecc7b96c40e2879
+IV = 8515ac5d1c518db2a9919917
+PT =
+AAD = bac577d3857524b2c06c69d5036aa08e93daba80d42b50ed6020bb1605980ebba87f10ff23e689d24d39baa91d032b063ad46858bb14e6d3c072dca252bfc8706232628e2d07d655c732fb19bf2d246565fecada410059e5dd6f
+CT =
+Tag = 4421837d371b1d66384e8e4d
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 83688deb4af8007f9b713b47cfa6c73e35ea7a3aa4ecdb414dded03bf7a0fd3a
+IV = 0b459724904e010a46901cf3
+PT = 33d893a2114ce06fc15d55e454cf90c3
+AAD = 794a14ccd178c8ebfd1379dc704c5e208f9d8424
+CT = cc66bee423e3fcd4c0865715e9586696
+Tag = 0fb291bd3dba94a1dfd8b286cfb97ac5
+
+Count = 1
+Key = 013f549af9ecc2ee0259d5fc2311059cb6f10f6cd6ced3b543babe7438a88251
+IV = e45e759a3bfe4b652dc66d5b
+PT = 79490d4d233ba594ece1142e310a9857
+AAD = b5fe530a5bafce7ae79b3c15471fa68334ab378e
+CT = 619443034e4437b893a45a4c89fad851
+Tag = 6da8a991b690ff6a442087a356f8e9e3
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 02168b4fdd00870a8f9f443e79ee379b676c3c383c60a027b435722ae41af284
+IV = 62bbebbc68e5423d27fe5d59
+PT = 08422dd3e9d87ef50a0c989a1088dc1e
+AAD = 4bcc4045752634c528fd9450e56c960ffafdc7fb
+CT = 9b46212802e81fe366efdb4e279bc9b7
+Tag = 7106445c3261652764102b1d
+
+Count = 1
+Key = 3b8b863e448d6bd3a35da4b0b22832c22aa1b3023ecce7e8c75c6361c99c71e9
+IV = f45d758aeee8462e062d1173
+PT = 9fca76a286d69c97cab27c5d3e206d17
+AAD = b86e829f9513f1074a274c7b1e87f17448924316
+CT = 1f29a7a5d1852db29a82cea6b9e9513e
+Tag = 9f83c34536fdeb6e1f856a06
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 82c4f12eeec3b2d3d157b0f992d292b237478d2cecc1d5f161389b97f999057a
+IV = 7b40b20f5f397177990ef2d1
+PT = 982a296ee1cd7086afad976945
+AAD =
+CT = ec8e05a0471d6b43a59ca5335f
+Tag = 113ddeafc62373cac2f5951bb9165249
+
+Count = 1
+Key = db4340af2f835a6c6d7ea0ca9d83ca81ba02c29b7410f221cb6071114e393240
+IV = 40e438357dd80a85cac3349e
+PT = 8ddb3397bd42853193cb0f80c9
+AAD =
+CT = b694118c85c41abf69e229cb0f
+Tag = c07f1b8aafbd152f697eb67f2a85fe45
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = ac046f942a82a9dd041e4aaf27ac23a0af57d5914b9fa00224fecf64342b3b55
+IV = 8aaeb1c35bfb3931d0e627cf
+PT = 77a0a4a594d8de616b86bab558
+AAD =
+CT = 178b93024040a2d2327b80c9b5
+Tag = 87a0dc4660668d217cd98b99
+
+Count = 1
+Key = 33e430677ad547f3724556617aeee86b2efa975a17d0ec841c2e482b8f07003e
+IV = f92a93991e00bc87926c237e
+PT = b7f03ee138c2f0eae63c57f5ad
+AAD =
+CT = 4d3e998ce18b64578d269f49aa
+Tag = e3bff83c3e4f8ab7369a36d6
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = ff9506b4d46ba54128876fadfcc673a4c927c618ea7d95cfcaa508cbc8f7fc66
+IV = 3742ad2208a0484345eee1be
+PT = 7fd0d6cadc92cad27bb2d7d8c8
+AAD = f1360a27fdc244be8739d85af6491c762a693aafe668c449515fdeeedb6a90aeee3891bbc8b69adc6a6426cb12fcdebc32c9f58c5259d128b91efa28620a3a9a0168b0ff5e76951cb41647ba4aa1f87fac0d97ac580e42cffc7e
+CT = bdb8346b28eb4d7226493611a6
+Tag = 7484d827b767647f44c7f94a39f8175c
+
+Count = 1
+Key = b65b7e27d552395f5f444f031d5118fb4fb226deb0ac4e82784b901accd43c51
+IV = 2493026855dd1c1da3af7b7e
+PT = 8adb36d2c2358e505b5d214ad0
+AAD = b78e31b1793c2b758494e9c8ae7d3cee6e3697d40ffba04d3c6cbe25e12eeea365d5a2e7b46c4245771b7b2eb2062a640e6090d9f81caf63207865bb4f2c4cf6af81898560e3aeaa521dcd2c336e0ec57faffef58683a72710b9
+CT = e9f19548d66ef3c16b711b89e2
+Tag = e7efc91bbf2026c3519010d65628e85f
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 512903e96ba584dbef3a6e702b0adb51fb3bb62e89d39fd5d2490ae6a4e80c88
+IV = 056ee9b8c34e3549661d36da
+PT = e13300959560f2aea376ab3e96
+AAD = 0918b88fc87e640212448e7a3574428f65ce7fb0ce77462ee1735b6d22cc6c7c06a39e04a0147faeaa46925092359032156a5a7105373692f7f8ace4e697d0c810092a3a584dfe43d35c94e22dafc169b5d931bba17e5eab3299
+CT = bc869e464531babc2d2e94fa1b
+Tag = e01c6c9c01c15efb9dbc6bfe
+
+Count = 1
+Key = 1c77b8523467066c955ab54fc0c6368fc8f006f10a0064eddf0461985fef5e48
+IV = 6f07f3e9a945bcf800f8aa73
+PT = 0de7ac05bc9bdb907801d5995f
+AAD = 0a7203c0015ee44b308a81f67fe9866ace543ab9cb8db6bd2ca649f9edea2ebdc9eb4c1a45658d3edd1a28cc489ceeb071f93f4936672ff249349e77e279a42ee2eced1945f997bd4e49c26d3b479a47f048db7fb2c177a5acb4
+CT = 31ec1a5171e552e3d4e86b75b5
+Tag = e96c680fe71c15fa0a890f8e
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 5853c020946b35f2c58ec427152b840420c40029636adcbb027471378cfdde0f
+IV = eec313dd07cc1b3e6b068a47
+PT = ce7458e56aef9061cb0c42ec2315565e6168f5a6249ffd31610b6d17ab64935e
+AAD = 1389b522c24a774181700553f0246bbabdd38d6f
+CT = eadc3b8766a77ded1a58cb727eca2a9790496c298654cda78febf0da16b6903b
+Tag = 3d49a5b32fde7eafcce90079217ffb57
+
+Count = 1
+Key = 5019ac0617fea10517a2a2714e6cd369c681be340c2a24611306edcd9d5c3928
+IV = fd1fa6b5cab9aa8d56418abb
+PT = 4349221f6647a906a47e64b5a7a1deb2f7caf5c3fef16f0b968d625bca363dca
+AAD = 953bcbd731a139c5de3a2b75e9ffa4f48018266a
+CT = dbce650508dab5f499767651ee734692f7b157341977692d2ca879799e8f54aa
+Tag = 20239e97e2db4985f07e271ba545bbbf
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = f1dbae7f4e6978de87ca7d950daf402e58155a325bd4dba03a2473307ba14ef0
+IV = 4c6d21dfdaad3e0888b0177a
+PT = a4bb48e22a91c52ec5e0f8df31abf7af2f2032b2e1dbc8ad73c32cbcb8ed47ee
+AAD = c9d79aba7ef84c2f726aba61bfd5d07d4fc2fb41
+CT = 36795e4a034c96d6f2009845ae8c20a6b5318b62b41634f26a9e96ded6ec6490
+Tag = 0158ce9cd418eac9239e2691
+
+Count = 1
+Key = c802e06537548a47961af80395e6b93507a77373dd1909f463ea96bbbec4387b
+IV = 3ebe1a5e536a75b62d0f3a5a
+PT = d223ab519246dcf030a702b94c7f0086de17157e2fc513f0187a846ee0de1bd9
+AAD = 9e1053cd270cf5f77acdb689ca3eca186b6c35d4
+CT = 2b164f137dae285b92d577fe97c7e9437314efbbcd826a0d7bb6495a30712d36
+Tag = d1a0339eef5c73d136a4547a
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 1fded32d5999de4a76e0f8082108823aef60417e1896cf4218a2fa90f632ec8a
+IV = 1f3afa4711e9474f32e70462
+PT = 06b2c75853df9aeb17befd33cea81c630b0fc53667ff45199c629c8e15dce41e530aa792f796b8138eeab2e86c7b7bee1d40b0
+AAD =
+CT = 91fbd061ddc5a7fcc9513fcdfdc9c3a7c5d4d64cedf6a9c24ab8a77c36eefbf1c5dc00bc50121b96456c8cd8b6ff1f8b3e480f
+Tag = 30096d340f3d5c42d82a6f475def23eb
+
+Count = 1
+Key = b405ac89724f8b555bfee1eaa369cd854003e9fae415f28c5a199d4d6efc83d6
+IV = cec71a13b14c4d9bd024ef29
+PT = ab4fd35bef66addfd2856b3881ff2c74fdc09c82abe339f49736d69b2bd0a71a6b4fe8fc53f50f8b7d6d6d6138ab442c7f653f
+AAD =
+CT = 69a079bca9a6a26707bbfa7fd83d5d091edc88a7f7ff08bd8656d8f2c92144ff23400fcb5c370b596ad6711f386e18f2629e76
+Tag = 6d2b7861a3c59ba5a3e3a11c92bb2b14
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 9b68ca2ae9e68c34442bcd965b9409e6de074149b50d3905455e5192594d2555
+IV = 00f6ebb531cae6d76f319aea
+PT = 9aa0d8f8f09dedb4698348649e00ef409a3593de90b419b05795faad3717aa02d2a9b0a0080f5dbc97bb48b1ae556b95bffbfe
+AAD =
+CT = 10fffecadb350845281380fdeeb27879567436a077580384b98f0c839be169588ecb67883137ef8cead0b7a7b6882891ea24a7
+Tag = a6e6694aa52b8cdd7d656d13
+
+Count = 1
+Key = 2fb35b38e56aebb73aa22bb40388032ff9a19b5b42c800a3901d428934c7c4fb
+IV = 58b60cb613a8d7b780bb7a3a
+PT = 075de076d096c216f2b8e7f633fb130dd0026dea1ce263571c6c4e1067e10eda418d84a48ba5a540a8d24eb25f1bc0a4fc7356
+AAD =
+CT = 3e90eab0c26cc0482362ab1ef46c9b27da387b73357be4bba16fef94c8513d8259eecaafef74f2bff7a0707078ebb08eb46f49
+Tag = fc71faf3f6dd8aec9435c2ab
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 148579a3cbca86d5520d66c0ec71ca5f7e41ba78e56dc6eebd566fed547fe691
+IV = b08a5ea1927499c6ecbfd4e0
+PT = 9d0b15fdf1bd595f91f8b3abc0f7dec927dfd4799935a1795d9ce00c9b879434420fe42c275a7cd7b39d638fb81ca52b49dc41
+AAD = e4f963f015ffbb99ee3349bbaf7e8e8e6c2a71c230a48f9d59860a29091d2747e01a5ca572347e247d25f56ba7ae8e05cde2be3c97931292c02370208ecd097ef692687fecf2f419d3200162a6480a57dad408a0dfeb492e2c5d
+CT = 2097e372950a5e9383c675e89eea1c314f999159f5611344b298cda45e62843716f215f82ee663919c64002a5c198d7878fd3f
+Tag = adbecdb0d5c2224d804d2886ff9a5760
+
+Count = 1
+Key = e49af19182faef0ebeeba9f2d3be044e77b1212358366e4ef59e008aebcd9788
+IV = e7f37d79a6a487a5a703edbb
+PT = 461cd0caf7427a3d44408d825ed719237272ecd503b9094d1f62c97d63ed83a0b50bdc804ffdd7991da7a5b6dcf48d4bcd2cbc
+AAD = 19a9a1cfc647346781bef51ed9070d05f99a0e0192a223c5cd2522dbdf97d9739dd39fb178ade3339e68774b058aa03e9a20a9a205bc05f32381df4d63396ef691fefd5a71b49a2ad82d5ea428778ca47ee1398792762413cff4
+CT = 32ca3588e3e56eb4c8301b009d8b84b8a900b2b88ca3c21944205e9dd7311757b51394ae90d8bb3807b471677614f4198af909
+Tag = 3e403d035c71d88f1be1a256c89ba6ad
+
+[Keylen = 256]
+[IVlen = 96]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 54a2e564d9796ba66e7e4f1456782f08a921b097dfb0f62302b02f0473c770ca
+IV = 9efca71be89b11b857c9cc80
+PT = 50205d7a3fcc71ebd386e48a421bcdaf3287cf78df1c10921fe85855ccc07a701623260d7992aa48103865402efa12b0cb8a71
+AAD = 3debc7ce4501dea63152206eb8ca2f8c41824a0d4e7f95488497eec76230bdab0663f22c0b94b17f077ae914d661710fe93756f48ac02d378abf49c129889fc4beb502f61cfd2374a76d979e45f4630fd2a3ca7d3fb3574c98b9
+CT = 4b41f4e02f7e71eab4dfd1b3b4457e0c0459a9581f550cb8766ebc2c30e26847d95ef3fc6cec5d1cf5cbe1720f6936307ed7b8
+Tag = ba9821b0d7f4327db5228640
+
+Count = 1
+Key = c90ca34c70d2a4107cd1d8bfad898a5098ae3b6b7cbc2ca328d929e8f89b7d6a
+IV = dd1173a2dd5b42307e4a2afb
+PT = a6af02602f3be4aa25a981b42b771fb0dc689670efa7d07f2de96cbf95b272b896de6e3e4d299c64b44c06d83d228a0cc2dcc5
+AAD = c6f7d27b4ddd0d590f7d8e870812f44b05679a306d28cc8eef3745420707058e137a0b27b74d43c27d6224660e65e02f44e1d82a727ec8c9b8839e3cb3a9b385c830bd3b3c3642e194d59bb0d060f23ae71c68db04a1bab8789e
+CT = 5183cce3f2e454ffdda54c0741af7049befc577ae302f7815c66718c4e47969490b1d15738879b11ddb967aa9593aadb7a47dc
+Tag = a19fd8aade208dab1aa60355
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 0]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 15a414466a7f90ea32bfd7f6e58bfa06e907fc416689d9603945d79454d42317
+IV = ab
+PT =
+AAD = 6114601190f6ef5e59235dc0428c09e3270b19ea
+CT =
+Tag = 196e0e010f0856f982b4089241d62484
+
+Count = 1
+Key = 4c0446f3aee1d362e79be6f3efd551e04e9fa9bd9f523abaebd769eb5e32838b
+IV = 3d
+PT =
+AAD = e7090e4176fb1cc97e41fb717cb48c857f6e816c
+CT =
+Tag = 59b6e2d9501ff685348de644f38db6e4
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 0]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = e3507fa3174b08c6928756d6a05024b934d4de7f3be2345d695f4cc698a9db9d
+IV = d4
+PT =
+AAD = 62916c2aecb81bb0a0a081050543f73e4a3bdc48
+CT =
+Tag = 0b48d5a739bf93e903a3e18d
+
+Count = 1
+Key = 7efb4419bbd839e0c20a485578c9702b26d84afcf869f0f15e106ee9a918f76b
+IV = d6
+PT =
+AAD = a56cc54933bd418e2ec68724ba2b00c259f5c437
+CT =
+Tag = fa9db7ad6fd8f2a5c917a4ba
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 9473c28f6e978eb15e1967b888282aa6b078d320034fe5f40f8bb68674f1ecda
+IV = 0a
+PT = 2d2e2798c10bcfcce742e92d3c390fef
+AAD =
+CT = c4e5ab2c6a4316e57c6c37d2c2acb42c
+Tag = 03337df7e1e68d77706abef9edaf5e07
+
+Count = 1
+Key = 5d0483b705f4274576dae512aa386684163c43a233b00dd5630d738b36740ab4
+IV = de
+PT = 3a2c9865f8bc51beac45831aa1dfc40f
+AAD =
+CT = cebeb4b572b32429b31d22108e3082f6
+Tag = 8fccb050a44b782a30629cd1e5360343
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 17c8b1da812da9d949f9e1148cc71a4c953a0123e815896cb99fc2eed77592ed
+IV = 72
+PT = becd302fa4af8f02ef37380304c3cf29
+AAD =
+CT = 1529417a4d85108e5a27d63f96653f7f
+Tag = 9f45c0a02f7e021e76d950b4
+
+Count = 1
+Key = bb6141d9c635d887ff2fe05b203ae169a61fde9be2374b0d0ae88c575e14ddb3
+IV = 65
+PT = 352e53c99cbee6e05f5c6b435a3be75e
+AAD =
+CT = eee20e9bf1ec9d8e088523f2346bfda6
+Tag = 1b263046df7af03856749976
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 36d59c857226d2cbc94c7087bf899be6087457cf7de9d526f18c60c9923909d4
+IV = 1a
+PT = 026bf225e7ba1c6843c5d457aa29fd3b
+AAD = 29551b354353a5c86a43d472a044aacc62f237e6a6a2f67c3f097822d69143a5af753e010b149cc1e0b98b2c6b1958a264f23110f4a4c7677971f4464508e7d8558f24f54a49aa66dad06f085f8b88a31238bc5de1753421dae4
+CT = acb208e476ebd8af21a227331325065f
+Tag = 07382df97d7b876e6088036f6caada93
+
+Count = 1
+Key = 4bc9afa3946764142dc0ada84ec54a0fed838ce8a583e79720025896c7f3f89a
+IV = 69
+PT = 1e23353ac08199341f0991ab1c4fcb1b
+AAD = ca888a8fed9c7514157b4925ab390f5e430869e796f5ea43f5ffbbadeccc044c086092ea903d7b1c5aff5ca874a19d31d6d7235aa9a9b95144a9fbc2b7578fe652ba254605dcc6e78d622eea659d30e2186d5530e9194591fa93
+CT = c7e76264fd0be05dd1882632fbec15af
+Tag = 65ceb846c56e3747dab3927543ed9112
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 128]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 4e804187d0269e07d544f7612334b83bd73fd56b0ece528c9a1a91a2859688de
+IV = 69
+PT = 17e84f04d4a3a04d52e143a204f25a66
+AAD = 877b0666701ddb706092cec4cd1a97279453e588c4b1178a8b1c51ecc16a093b58cd06e619a0f8bf291ab530e98b1222e0ef58d4350b9db89ba40e292529be6ebf528a37073c95cde63d3ffd07f77a7226182128649cc3f2b451
+CT = 484a8f015cf0e67d1363c90b664ebc49
+Tag = 3214d9cd4b325f5f2937ab08
+
+Count = 1
+Key = 684d485ebbd8a7fce6e2bf25b05fe094e3e19d2c9bba24c0fdc95663693734ec
+IV = d6
+PT = cc155f72a44423632cb2d648a8988655
+AAD = 46d1bfb7d3bb9112441b3498d318c24e0bb9f4c5c16a2161aa740d51640175f0dd5830b929181c06619c5f187bf211962e6131d0d4b1a84c391fc4b396ac8a310cd364856016458e171e4a0b00e21227d45bceaa0d1f27bf733c
+CT = 87cec29d8727c26b79c42d2c14826f14
+Tag = 32e7a44159eeee71fb0374d3
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 104]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = bfe5a8faf6791bda313a6026beb91d8e23274c79276e807e25d30aa00d440da7
+IV = 9d
+PT = 616dd54e73c0139712a0231788
+AAD = 6175a08f4c1604545ad9e6ec6354b69a63b034ee
+CT = 28032774bc8507df0226b8427b
+Tag = 1f8d71d8b66e9db9a7903d85e8fc113d
+
+Count = 1
+Key = b5217feca15d6fb24e83bf1894affb606461278b81aa116862cd2766209f91bb
+IV = 7b
+PT = 341e0cdf7a2dd4939e8b738fa1
+AAD = ee96b628b52c08946a448195dd358590d73b3a96
+CT = 42031cbdc3c44ba4d60f60c132
+Tag = ce2dba09bacbb58498b9e78bc301cea1
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 104]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = e19effe6d0b85106c7915ba4752dbf09c402e2e1bf884dbe36753c7213c01d2f
+IV = 11
+PT = 2c8d62fbffb609fdcca4588f1c
+AAD = 6b559301123c890a7a3b8ed17eb061de68027167
+CT = e8c87a07cd2448c8f1aceb60e7
+Tag = ca8a4ce354abcfb6622d9b65
+
+Count = 1
+Key = ad977d20322e802a90768a0778ee305ba0c3d0ff3f2691dbd8eab8fd5cbb8005
+IV = 91
+PT = 5ff217c0121ebca4cd0f97a4a2
+AAD = 0461f0a1e4fcda423f3804a860eb67c8f2497f9e
+CT = fcf1c6e3c41492f97822e7b72e
+Tag = 7a7ff132bed7dfde89a57eec
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = e9424e1a669d35d840654711977ee9e7019ac3594787b7d0d96c426b1f04d270
+IV = e9
+PT = e2b3a24d2daa6506c940787788e81840d440334aa4406ff3355535c72ec0bbcf
+AAD =
+CT = d517c37fc5fcedb3c0fc823c12d923f1169d1f82e2ed7f5206d30a39cc04002c
+Tag = b7ee2d91e7c03c39c5eb5ddfb47fbbc6
+
+Count = 1
+Key = 7a4d36a4aa7cd89ed1aa317c6f00b0578e4bcfa5e25717eb1b4d2e98e518c90d
+IV = d6
+PT = 2178a3735555ec8865943b48857ddc7f66af674f8c3f0d34391bdd07c62b7b51
+AAD =
+CT = ab806b78e8a545b9a12108626a13eb0907c869c30940a19befea4a5ce3a977e2
+Tag = 8a2402879bd775806a1f3ebb646af917
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 647f3ede88d1408d62756158a5ae78bb3636628b7c2c285bdf1b09c0f138db1b
+IV = 08
+PT = 9b2cf2a24b84b417840bb481460a65abe15546133c44f2029bdd05808fad481b
+AAD =
+CT = 9512a66c3ad612d2da3fa344be710da0ebad5443bb40f589eeed2d80a9597c20
+Tag = 079a3c15e6965a81d5608f80
+
+Count = 1
+Key = 2bb52734fe0d830b30f60aef362bdf6133041d51b593a4be4dff8acd2cdf9f80
+IV = 25
+PT = 53630759aef425c4d7419b9ee7362898bcd6b62fe400d950934151670236385b
+AAD =
+CT = 2ef4393051db7cd7663d151f3a81249c8f00ab44041732e571cca60c1a9fe387
+Tag = 4dee37251636fe8562dd9576
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 13fffb686c2bb85388cf72b416b2c8e335e3785cd838a1607d18d30bed302637
+IV = 40
+PT = fb4e75a21fc8ea570d1e63b64d49db3384693da83d72f0736611c329fad9df76
+AAD = 0b188bfd773dbe90470adf015a721bc4d78c870f9f3b2c7fd4182976cb6a29ce5075ad85da4df2aecc760d72eaf881d6b937b624edb94c9f303fee14ea8f07ef5ced8bd789989bf1e50d87598ca82e588e41e353845ab76388fa
+CT = bb093d01614046593bca8157731737386b80716a83dd9096763b1e435fe609ee
+Tag = 53b6680823f5f189756528d07f75cee8
+
+Count = 1
+Key = fab2d52c5a492beddb6897838c22bc87d772f92bb15a0648dfeaadd9b03250a5
+IV = 5f
+PT = e3b1687619175016f8bd12e90e3372729e2fe5a10196508d12728d8103541c3f
+AAD = aedc49fa3e96a9970e1e545187c7c00584304e360835f686b1c24e439935a2404a6e82428aa1e337bb972aa5091cbbfc9ed80747b13ed143eada99acceffd3bf2ead9bf9f50fa2f25f009b1fd8ff2ca52c47d11d451b11f227f7
+CT = 90eec63261822fc77d72b2fb353fb962b2a0e686705efd38b42108225c91ebde
+Tag = 649211b84e0339597f44b677990da87a
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 256]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 4889c5fbdfea46a1e409fb9f49aefe3eb6c62db82a5e010008860c619415ad95
+IV = dd
+PT = c60d33a9d24951e039393b3bdfa9896d321c61f06c67fad5a9817019e374a6ac
+AAD = 002ca3bf0674f66d79267112d8a634bdd577c93d93e8437296cfdc0efbf7229790c09020ff57f675c271e1d4b970e6f72a317ffcd73818946682956aae546a3d07ff89c079544a008ed3699a7cc905cf3a9cbbed58c9f982716d
+CT = f83c7f6b350ff2e8d74fd351de4f6458ef9d7e4a87fd718c6226c2560f0a0a34
+Tag = 56644b80bb5c77479d0c59a9
+
+Count = 1
+Key = 5446634d5b37000bb57cc0a10dc05ee95e5f3de49fff8d77a6322dc27a3845e8
+IV = 99
+PT = 397ebf84a7f6fff993fcfdaf6a9fd970bfea92903747cea3348eefa2f473250f
+AAD = 87e390806ae40df05e1dc29709e25aa341530376f59b2b57a70ebefaa3dc20bc3a5e119ac3d27b44c48157db59d923bcab7de0c5f9d92566902445f681ca7d17bdcecf6185635dd8a2833f57aac4b4587d718da3660699e9512b
+CT = d3c540a72fa0360bf56024e1d0c5dcf0b9b475468aa3562e18fd7265281dd320
+Tag = 525dee83aa8fc097610d2c76
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 408]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 05f714021372ae1c8d72c98e6307fbddb26ee27615860a9fb48ba4c3ea360a00
+IV = c0
+PT = ec3afbaa1447e47ce068bffb787bd0cadc9f0deceb11fa78e981271390578ae95891f26664b5e62d1fd5fd0d0767a54da5f86f
+AAD = faf9fa457a8e70ea709da28545f18f041351e8d5
+CT = c8c5816ba9e7e0d20820dc0064a519a277889f5ac9661c9882b5a9896fd12836c6721514e885b1d34f5e888d1d85abce8c2ebb
+Tag = 0856f211fade7d26d64478ca46025a3c
+
+Count = 1
+Key = 52ff61cdeea89e018cfd9ffa092bf6a6c65ae23068906197d5be812c3c528068
+IV = 19
+PT = 3fddaf6c6802762bc0fa6c1b9df695002bbdf6a58593bdc8769cba9613eaa278c8914890eeab538d841062dcbd9da8a914b240
+AAD = 92d03668ca836920c2f33b35ff1fbd4e75db37cd
+CT = 5e9402238bdef857d0f24557d7bf7dc510cfe829f9e531d47a412f6278db17910f5b3e5dd06349564cc0e5a594e5f8408950fc
+Tag = ebda8445616bbd86e0bb417129f37c4d
+
+[Keylen = 256]
+[IVlen = 8]
+[PTlen = 408]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 3748a659f137394eec71eaa99f430337a3564be6cb9f0cd5411e52e2ca3dcdd4
+IV = a1
+PT = c5339b37eae811c3542d1b4dce361ad1a713f31ef03b4f7dc7abb8e65c482c2f5418aa00a7630bab9725361ab5f2a92291dc27
+AAD = 20d51f379d1da2bad92c183ee5f2c0feca985761
+CT = e620061d01a5b4ad8004da6bb6ad101317c2964b30af8a94255fc7c72a988db3160acd64ba887229e8eeb5efcadc4fac9207dc
+Tag = 0258a8602b1183d2226d881d
+
+Count = 1
+Key = c353e766dbd82177a2a6757f453f6064a29487e696166be2c189611472e429d9
+IV = a3
+PT = e25497f7a6cec20d50e1c47fb731da72e7254adcb3bf15f3955daed35b5d556ed0d8cf5ff09d2067e17018c97bd99da756f34f
+AAD = 54b20969a0de9731e7bf0817f10ab78e9f460143
+CT = 700b7f74b177ec88f891a45e216f1bfea17eb2510a822e1f14ba2def2270884c0e60c9e541d11cdcea68d4d0033dc31bc43997
+Tag = 6cb266212f9ec4ec3afdeef7
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 88768354df414ce4097f4d357837116685beee0d93aab343576b893088256260
+IV = f649d375e4e896397a8a96cbb847fbf45cb54132c76baf814f4e35e9f7737f16d5cd710370f143612b46724bbdded2a26264b90a91f5ed425d08d317f49a56828fcfeb9ebe1bc53117bb4156c2e99d70b238dd9166cc05906719818022c75957d25ad9c36c93ce2626248c783e0207c35db74996f47d096c3cafe701a38154ce
+PT =
+AAD =
+CT =
+Tag = 905b22cd3fe77645e6a217dd1f993ec4
+
+Count = 1
+Key = 612955ff2036dbfda8adbfaf9f2e005059bd447d7075dfbcd7045a9bf00c85fd
+IV = 0bbf745774e2d189e9bad6e7e4d2c7e8bfeece9b4eb95646d24611eed4337279ebb82006a5f4d893e7d2dab0a36f947e545b3c352c696c33d5be38e9bd21d86b65e9e7080f7aec65d9c33d0495b1535263eafb436de129559ed43767d2dd9472a7be3734d75694f92b86aa27b1427639666ccf74999dfb8f1358609ab22b44ac
+PT =
+AAD =
+CT =
+Tag = e62310999f2bf9c2c147f824d94842d4
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 86257e34d3ad89c5193748d70b48b52f689c1d51aadf16da7a50cee4af23d2db
+IV = fb76508ac2b5d9213ced37300d9c314eb282d56765b86bf71bb40f8d26396c4c6f2d4534e007a2fd522042f84572262ac6147172ef616b56dea10708b3e0435ff298860c66755d1f29a56c999d34598597a86803e8a55e79a6bdf96febe03527a1c36d8a1462dfece3dc42bdac7e886d545841b5ce5ad69d9f7a3116eba2b75a
+PT =
+AAD =
+CT =
+Tag = 4bc88ea39369606b4be682d9
+
+Count = 1
+Key = d6bda4783d126e522902b6def6e57b532885f43680437776ab1bbc9d05effe93
+IV = 30cf59bacc784cef70002a89850cbcd602d6f7a2020d9dbe5e98cd943f52e069936086bb79da4fc07030cac4263ed61a48f66c84174796d8e3157812c7e6848bfe37200de1944203abbf3aa7518be10e9baef09808dec73175a8a2b8d9b4e4478feb0267a94b7fa66775d3a41c7c1aab88651e78a91655a30a54d18bd4620f01
+PT =
+AAD =
+CT =
+Tag = 43cf52565a8c60de783c9eac
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 48da1e2727bf6b0340965729d6dd40c4372ad42cca4abb56620e828db8cc9c9f
+IV = 8c3e8bac3f74310ea0621052c8cb0dcabc0c359d0f99dd7fe2e377a2b96379636180bf034ab3e253034db6200fcb4b8faa226573cb8c21a47560f1ae54de0d41f8582d340c1625c0dfdf67f8b2b47ce7dd9cc6bdc5763b8fefb5e974672498c52ba29d86ce4c97aae826d26abed823a8c4b0256e0aa7ec8ce76cee1962cd9407
+PT =
+AAD = ac4f0dcfb9f238749799b856abcd240f9474b6a751aad3a7a68c1b0d6f46c5405a1a86eb5d1d2cc48f050ce0b0ff612603806165bb0d10905c9a83f68db9ead74de1fa7a8df31e835b8c7dfa4c582dc63ff4c341a34d46c12a49
+CT =
+Tag = e33be1793ffd98e7e848026f2acb5ce6
+
+Count = 1
+Key = 36993103c028fce6a0265bf1b08e90180c395b18152175a5ceb49a0671aa16a9
+IV = daea82201d2cd6052237aa1f0e6b805c6c50309ca42fdbc898d2fb9ab6fabbfe93b97227f37cefc68645466ab73f8864c4f5d44a1827973aaacc4ae1af33a0d630f870b885b49dc4d342243541fd68bfb1d6669ad7e3c4853817c7a2b79698b68bf2c089b5c264b519ae4b24bfe68ca4317ffc880d477347ea1b0037ecd8a34b
+PT =
+AAD = b8a37d98f8b0e8feb3f10f7a6b25abed25ebcc11639202ab58a6c8190b3515ef5a75f121152bca539c1375100d094bb9564753fb067d43c6006877d9355252697fd4de9e61ce4978b49ce4a7c29488f6d23488e5d972e1f1f334
+CT =
+Tag = c283c76b44f45856d4523b2e4ba24cb7
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 0]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 47cdb45916328e904e72d58c1ba70f70f6e723b706baf347d0ec51d578a7a1c5
+IV = 489ba0fced23d3e5c2b34345c15e7e8baabe8f8555edf470f31fa6b524c35cfdb3c2b3473c1fa598ed1a3355e1d167cd20715421d2645b373c148310f89bd18f7061fd3e43b9f519e1716c6767dcad1497b70b10ff168f4061bb261f2788ea389c776b9beb6bd239c83dec34e25bed8ede5b7bca152eb2ee88679b8ac28d061f
+PT =
+AAD = 99a5fe00e12cf8d41a3b9e6f02aa37ddf47ce9269ee3a126263518dd2d21e9c8eef18fd959d8accd14524b9132b6bfad30e9d7b5bcf9fd8f974690a8d011b62a66decc1e93abdb964859dac0b900cf2afc438f4df5dc8206b3b5
+CT =
+Tag = bcaeac4b465b664ed70037d7
+
+Count = 1
+Key = 2abd350a67ed0a76e1ff8d495a8541298b303c167fec8fccb53634819283446d
+IV = b4c3276db1d5dddaf457458bc7ebaf5bdf7c46021e97a22b3456f94e18d8904b1f724a5b2f75ca1a2a63eaf3ecfc60386f3340a9babc574e8994e5a1b4d5b13294e28d4cca064f968571a189cd93fbd1ff0868c85a68279096fb1f71350affccf6fb745ccadd0dca8ce74e251cbe5cd45f978841ba453c8cc02d1fdecd2e17ee
+PT =
+AAD = 60669cdec7231b0aa6034580ef0a3005102c12afcb39313958bb4fcfcfebb795f783e55aed5995ae1799bb8c9e0ac2d4a265cc80c99609927136947c8928ea738a0d2bc4ee90b9bab9cb2a3f6ff40778ca28e7b5941f3a23d81f
+CT =
+Tag = f9c2b3b1cde2781d4b8db6f3
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 5dd8dba0e10083f034744fc78e2206174c7f4ba6141a2e2cd2cc161566f2146a
+IV = d9a8a708f3876e0f4c1a6debe5f07cfdf473eedaa83309cdcc6eba7582555b0c3901743e1bc226df7f82ccd878000b41119eb5dc7a56018c3145f58b0e24464eaa87a349476d1670a4d61ee1772400680cdced958a82b50dbb1c738a2253d546716e84199d5be025e892f5ad28c5ff70c00cf10429767bd0a8eac20dfe0fd047
+PT = 1f8db298fe8f5e87d07f7931666dfe0e
+AAD = a483fa97fbc5ff6e067faeaafc599d234e5430fa
+CT = 5c21a4c4302687d0d0cbc5e0e416ea48
+Tag = 611b5761f702322573f7ea669c09c915
+
+Count = 1
+Key = 97f01c55117c54e2abcb765c238ed58d1f9be9dc8f4bbcfbd7a5033ca8bfe0fa
+IV = 5e4295e99b99f908123fe869f262c180b183b5e9557e2c0831e24e7e3e80f56e2cbfae20f27d98f2f17e174befcdad4c2069b4d1a06c60a4ed6d84382f766094a333a05a7a3b944bd76a353223e9a54f5f8b371b5af7ef7c029e14b5108f1da256aea0d0cc11f16bede864bf713bd7351c5515c2e152ca3209ad9541eacf5b76
+PT = 3ed7316ddf5c09020b3ba0a672ec782b
+AAD = 57dbf4feb780bd47697708338339d21e1459d550
+CT = 080cd471f2ca88c1a6192ee7c09068d2
+Tag = e21d381c492898ac5f9585e79b94545c
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 128]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = 912a41b56aa5b576f030ab577116625fd531d9504ae58af8c3012977be4d782b
+IV = 0a3a3016309cab76034d79d21ee4a1eff74041306625c4e9531427107a5a8529c8a0a36badc7560fb10c6eaa8e73b63b5d1a1caaabbb0bd1b5901bc2d0e87478567a4db3255fdca0f734d4fcd007e2af8efaa475a9150c5d5b36e2d6140f1886be7f2bf449567318b07a732b059e078280282f535b6954906540017ebec62200
+PT = 4492f2314ebb91fbf4975a9e9d6725be
+AAD = 33e78263d53cd12d2ced5089a285beeed497e8b7
+CT = 69611143b4687989d56ee2b7e1c25ec2
+Tag = a84c74ba96c5da1d28b19322
+
+Count = 1
+Key = 58d79336c6e6d202c861b2feb5773283c599558cf229194b39068317c242f662
+IV = 5c5a5eaf97742e6b23516ebf6adb7612659d8d252b21e5883e75d871affd74fdd0d3ceefcae03772390def5d4e36eb2858ac5142fe6b225e942190c94160ec5cb56f04347cef8c9c4b5eb5c3fc04686fdce97807ce8aa34fc8b1aa6d6848ccbfc31c75a0e923de4f97a8db0570de4479c779db2c434cf5698a9efd65782098db
+PT = ffca23b7fc15b3d11adc8cff7e4bc72f
+AAD = 6f535ec49cb57178221f7e89fe88d5214c6b6472
+CT = 379b8ea2b39863499ab74772d88d234d
+Tag = be9d0b43d1fd3bf7816d9f27
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 3e15864a469f71587b27b21992db5e08c903e953849cc0b1bde55aad26544d65
+IV = a267a71a7c8e9d4b9bb987c40bea4603a5fa6defe45d6ebffa6ed5591ebe370605f087b5c9527b44276fde31cf4b13c31af7c07667a9a5a3d48f73785f638cd1a3aac6feb9be7e553539a37b0fd15297aa6cb50d298abae46af61e658038a710c5331824705edd41093d6d8a45b07f77030714b1c9b0f10faaa3d1017ac9eefd
+PT = 348cc1ee9335c5ba599ff433fc
+AAD =
+CT = ecc16152c2e414a54f4b04df08
+Tag = 3990d6c836f9b373d57527afeca26f25
+
+Count = 1
+Key = 99c64392f2c03e7af0d9d6420dba62909d78ef2b411948e723204b107bbcaef0
+IV = 5df34c3b42a118c077f2d1c0ce1e30378b022cbc64803f25f98cb546af2b3deaaaf4df414f03a83d3aa060da9cd231753b304f3b5aa861c3bbc955ccfc3f01783d48b47f52c8139959ea1a75967d12228414f9d5781560acafbcb880676b06b9d2087f4cd91b0f9b642da10b7e28e47c974634b55438cced705e2c7e6d6edb39
+PT = 7919ab9a581eefc954eb9ca8cb
+AAD =
+CT = d90dd76109c1070cbec418e37c
+Tag = c4e08d020a7304f8705c03f3f3b4c5e7
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = ebbd24d9f41d6cf8113cc0a9721f7b3f743d42981b278c817e4087e582b76871
+IV = e072d944c85afed3581ae90d0ad88a87526a21709960419158151cd4d22bb08572c41327d91c71c2c2c5d312f4dcbe3021e4314a44bedc41aae83327b4edd5d390bd9a578b52fd0e00622bbfb28d306a3f7ffd1b19ed901ff8acfe15cbaf2911901c360dce23f65bb7e92d10b15aad043a53aed9a83d18a79b0d9fa58c8b65b1
+PT = b5c487e38fc82e97c1bdf6565e
+AAD =
+CT = 1e10ad3d3f37452506461ddb14
+Tag = 7adcefced869e6549b34e797
+
+Count = 1
+Key = 1adeff752457447dc3e77c3c16020ac9a3ea3dc54bfeb34f01f2da8b2eff35e8
+IV = 449d907c4b93f5fbf247461551b40a4a4339d83ee13278cd121454c5b6b5287532a904ed2628eb0356a8880b19536639d072abb40018f433a6191b7d65e48eb8122407a5a4a7a0260bf89b0ffc3f9cbda01783493689d0500dfc0942554ad4982e302ca8e539a171b1986692492fad0f5abcfc3dbf6d136e436761985d0246a2
+PT = a38da1661112803f6f38a8b20c
+AAD =
+CT = 005f7a27f0329eacb32e03d3eb
+Tag = 17f6356f9167a9856a4d505f
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = e6857b9f9743a4ec1593d2bbc2b7ee0e370bef76f1da3b2bf5bcc53e5446832f
+IV = cf71f928e74343043dfd56f9121072fb12ba9ea73580384f99357eab690d16254e4cee2e8447959d16bbece8e2a0696de90ea7f3da1d6e8a436d04cdf51006fedcb76d8566af25788c3af2f9f57ac64b5a67c12ffc2e0ffd339256361a2f8fe3d4e12f7c79ae647f5272b2089c34e19fbf1860ed133f8e5dbde5b68982729b6c
+PT = fcbcaf2defeca871815ad7b842
+AAD = 527c1059da318d5f9c555cb47d7ec21492397fde2486f65ad20e6cbeec50b234ce5dddf8a2c7adc637e214e3c7fe8a5754ebdfc913ed6a24d5e1bce495af18bc4aca0377d0ce60bcc8d4c9a49b72cfff53e14e3dbf02229027e6
+CT = 905b3ac1ab9c4c1aadb2b14924
+Tag = bd13e616d5f08632ee066936ae7f064a
+
+Count = 1
+Key = 42df96cb9aac2e4a4842dd158010c64a4a94af844f739884b5e9c4beb86776fa
+IV = 9ee2b9d35cdc3bc1f23c1e9544c676a938b4ccb2e07dc183c6ad1f8e077cf58360787f0dcfe0b57ba1ba721ed154c3ef72106f0485c98198395676e60d7772af01c4daff556467cfd59951ece48de37b50ae42214cf1affaf3fccfbe32027777c4a5cf5ad588fd91b9de4de2d3d21c501a56878f418bff8f3fb797cc33ee0887
+PT = 0f09b13a8eb5b8ad006b2b2907
+AAD = 0cece2c2a74aa9c24ed7b17eba8c2628bebbb6bc77852760ecf9828fcdd414d103da6cc27ec7f60d167293ca44cd85ff47d004b0940846ea9a9c45edd2e46fbabe196a9eeded3cc27f86e75a7349665c5033c20da72489c42dfd
+CT = a18711585bf70b4c536cdbaf01
+Tag = 6549b35eaac2fd0294393630b040f471
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 104]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 6b663811d439b70c7d3e3a107c9a3fa540b541d9e40c38efef8f848cd5405155
+IV = 92357a6b5a5aa9823cb2cc01d56c2d41cf4fa55ba633358856edd32c1033a8e1f253e1a12c7bf23b4c450b75fac148602ebebc8f04fc0d9a14542e71253ae8c2592fbd3629d5ad6826c99147c2bd838be1997eb111faab3e64fd4a3a62ac314b175732e87fb769f3079d9340644c45b9cf7b4739b79d81fb1f301930ce313287
+PT = b8e50f3b715f897a77980defb3
+AAD = f3ecb53267e0ecf16f705bc0ea3ca43608a3d0bbee999f89a06f0492e01af184aaa83ef4f215654a3b474ee49f2feec8bdb49c7e5b90d568cbc94ece6ee5536e08c9cffc2478a199a8866714d9b25bce244c52d3a784151850de
+CT = f1b802d8db8cd5665b89f436b3
+Tag = e52e1edfda323636e22fcd8d
+
+Count = 1
+Key = 110f5ababaaa9034fe11f20877abde6418a3f40231434cc1bfcddf3f2d324aa9
+IV = 2bf6feb5331ea09b1fac1615d19f784bc0c71ae9e06eda2d2ecd2a42f6fc84ba092da28b5551b233cd3751aae31e4f04965936f9754e69e7c8a5d31b016b7d67f3eb6708821e8e83102e84f8b3bfd402685f79f023af3caad984df5e0a17f8962f974d2510d659f65340b4a566eec6b295aa01cd1fdb01f9566509ae74212da4
+PT = ace48b684f6d72ac75ad31d447
+AAD = b1d30c9e0e0f2d1161623341e499ae2fabbafbcd314fb95b88223063db082796954829504d118a17220fb07be2cd13e88b1aa7689960cf4ac1f53f70cd9df3d7879b178a12135ddfa1f2b42af8d9fb16302037e257431ceb77c7
+CT = 53c8d8fe5d96c0c33919d3f3d3
+Tag = b5b848627797ce1733b542c9
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 128]
+
+Count = 0
+Key = 60faa64f4d9d51c3bad34a88a9d9ac1dc7845f2bd812ac769aa41fecb308364b
+IV = 0594cdab53529f6660a29945d6293e0038b54aa4e4cb93419776ba05b81d1c40288919511a48e08b9881ab01f79131d2f529da22c1e84b3a2ad2c2c74224cd5cfb18528f935df0b89e1c86c66aaa0c5c4aeb3b92ee578a2cd33c0d7d1b894f6b8ff4e5a52feadf32259d38b0f96be015ab974f79361ee507e1801716bbb51ec6
+PT = dd582e9bcc0c011ef6ae8ff92ed6f256d22cf8f4ef36fd92d0038b992b7fbd0a
+AAD = f3bf508d3e8782d5440a395324760686dfb02b11
+CT = ec354a69fb7f6c82e8a927774e914059bf6d702a578bc7acce8e9135d9308ccc
+Tag = ede691d21ed2da19dd0f049dd65ef741
+
+Count = 1
+Key = 6d28663c8e64a6862cab8891e17c1550fd90072d529559e6aeeb5008d3ae1538
+IV = 06f6f610407c055022c65f3fded31d8ad0fa4632f10cf53acb98ed4e3c422d7ea2f5820393783af736e4c814d47491e23cffefc01a24e285352162f95659a9a46fb0ae4a949c24bc0134c6cb715452c635614cf5d066d992f5874b305cd8e5fd6f01e91c7c2fd8820802e4c02f4e9c2a3b8545a1c7bb767709f2548c62632f1f
+PT = a611fa7c52dcb5fcb45df4e8105d441c19fd251e82229330e599391b70e20910
+AAD = 9d0b84c48a67df3f6b4c03c50245d56761f52b3d
+CT = 056de51a59ea543647ad345b87007826f35a559c18f450e6fc2b97d17028c170
+Tag = 819462412a1f1d90c0c3e4cb938eeb20
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 256]
+[AADlen = 160]
+[Taglen = 96]
+
+Count = 0
+Key = f845afd1e1227d9d347d72a22a858a5f406fdac07d63c44695ed8bbe0049785d
+IV = af69ee4adc06c33a85c1bb064c1687ad350fb49ca0a631cf4952364f9c8372f4eef93ddc068ad48c67113836064c3a6ee63a07ed8bd9482160375c3230d741c57a566100a423b4e20b625eb9304cad4616caeb14720f1ea9fdad92bd8057503e1d5c053f59f2bd327402c931129e3d35a4458bd03ac29a6e2d4fc373fe484b4d
+PT = ccfdb0d5d23009c53dc8e1ebd396410fa49175538d8c75f33452875c31b63896
+AAD = 7ccceb075a5a3074244898721f5cb341357a9380
+CT = 9991dbf2f99b429e51840250872a30ec8ece2cd2daaef32bcca2bd3f3ada9b3b
+Tag = 4f2d69d839445335024b877d
+
+Count = 1
+Key = 905cbf9cc91724e3e748d316adc2d1e33d3214a73c82156625e660c9f521fa18
+IV = 481cbcccc7132fd20c85bdc32f9e90c4c72735b32f56c4cc77f6a31327f992f60898149e2760eedd837c88c7441291bc4544d03f990a777ead6502f016970c99a82944eb4814cc3116336b8464e2547a2f66c347c9ccb1e84403538dbec7822417cb2c356e8609e41262d91ff6cdb9000dba28edb857b7bfc501e93e4abf2391
+PT = f01fe7bd439c6386ff4ca74d98d39424cc65ac071b79a422802528f02fe403fb
+AAD = d26ec1985da6172aa29d010981f6ca8e4b250a40
+CT = 32469f1189261e54e3040252813ed6df1cf9a7b059b410b9bac3a20b96423c7f
+Tag = 05e015e47dc4983a2725868f
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 128]
+
+Count = 0
+Key = 816458a5bdf7f937653d1bc1c79699c0e3291f03b3f6be8c76cfb92fd544d227
+IV = ee87abc85bc736b6e59b02eb36955c05cb2a0ffcc5d34091843a54ca0abedcb59ed215ca3ae3835fc42c3832cc6623dc6d07cb48198366d471a3a06f4ce93ebec04e2f0ea6aa92f07c4b21624b3aa3202279b95c19e94c3c3ec79a8310e7401e5b4548bd2a1e69b948f2c3b34c9c4e1154f4f0d287aeeab8388097a0cb9b1104
+PT = 61645d5f857d11756fc43f5fd7bdd003079a58a42287345e7c744dd88faf25154d02911f2b22e61408732ab4bdbec2e9b9d942
+AAD =
+CT = 213cccac331229abd621eef68d632cb09bff705f8b02173d24a5038d89d287520ff26619a2ddccdca89fc254aa17856c27cb26
+Tag = 814dcb36d10ba5803c311a54d34735f6
+
+Count = 1
+Key = d4c4e275fd0b49c4871f5f121b12285bac6fe3e3244e526692efb4716284a252
+IV = cab8883fda9e546de3cc902303b7baab2ad4b928c6db226860183a0ff1c17578e2126b26f2e8e2534247a393284eba75b8b88d7b17d5b3aa7de213ea032ed52ebb8f3a35089dd69b1172b89af54df51337f4762c874d85988ec15fface23fb267dab17996a70fbb22c7a768d9f90af382639f8f40856ca92bd7d50e54821b669
+PT = 4f9ec23520b8a70e5d2edbabd0702bcd8aa3e5fcf99117ea50739309bae248bdb48c1bc65aa3d0225a76b561ea5ad28f85c6ea
+AAD =
+CT = 4948fb1aefa17f56965778e65ddca703eaa6104cd9b6a8af176fcec5d73c8cf30d4653155c6c0bf7a17f3cf7ce7d4195e8b4db
+Tag = e980633d6f986ff59f9836c22e5c0d29
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 0]
+[Taglen = 96]
+
+Count = 0
+Key = 8c814a3705493e84583f1606717ef947f4e4497d5b4edd005887f25e64166655
+IV = 75b1b4df237efdff9af9b357c10728bd3cd163b21afdb09a8e3b993544b617b91e4b296d8a1dc6a979fb644c0cffa1c992371e7d3a9d5171fbb812ae056b82b7eb4746d4278981554b45b0a1c408793b50a88d02d088a2655a1aba830ce7392356725b65d8232e2678fdb08c6e60de46b3cf264dca8e1b1bd2f9cce287d0ca31
+PT = f454dafcf1af7db02b8abbcd02c08e90e93260f0c25079cd85270d5b8f6361bcbc495a35c8d12609130406b3db210dcfe2281e
+AAD =
+CT = dcd6032609f10db88b1d5873ca1e9c8f53813bc236775811cb916fee3429fe6ae14b739ee47bd5f188a74f2c24603208ac190c
+Tag = 0fea60a5171d4c5e63807d68
+
+Count = 1
+Key = c8209f0cb2faf8f3b916203acb69601edc18e0457c0ee60fb04751daa34965dd
+IV = a66cfa1f52091d288927f579f8b7682b3b2792ef12379f389751ccfad0ec2b31bb41fa1188f9ef8994eb532a5d8ec86a66aefa58fe7a696569473e9526439498f12e5c9b3de1c16ae8509f6c08655d70077c17a4aad724726cb72c6878e0dc23b9f4c54d7a60e4ae436980736d0b8ff0c6c99a03141edc30b6116a0c0148a1bf
+PT = ee4e601b8b6319d73cf20b15b90cfb74c4552ee164c9e66ff0f4b2d617e006ee55ce02dadad54809e431d12a2b6c6e24f0fc80
+AAD =
+CT = 99413cc2c04e0916e6ca79cd0a4ee4d9cb4d9427ecb9621569bbb7598834494309b0c30805de239075ff5f3b160ee53b2f78ef
+Tag = a001127ef0668e23d231e747
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 128]
+
+Count = 0
+Key = 65b7171b55b22edd711a076f2eb6a125e873993e8d54564cd62d03c665cd6374
+IV = 54d118d32a56138f04212684b1e47c5d6808c128996e1d6ebf739ef9ff138aac1181fcde820a5f68749e1fed791314c73c54169aee5556bf206998d95432719fc9ffe22fbbc4925f32774d31e075393c0907e27c3f40da02c424b402eff596f6300b881b8f561d5ae4535a1fa9d4bafe86dd6751b0da245ae7b74ddcc3f5033c
+PT = 0521e41d827d6104ecdab1f8e7fb70cd8abca87500ecd36e65906194327b1b61014fd310f4e1bf7d5bf356a5d731c0d0d47c7e
+AAD = 4a3b04decbec0a549666e87036e78433b896270792e7932810c38eb063139ade6a4befd4dfdb38d53cdb95accbdee7ad5478c3bc55a21226c2b0fa79fe7c30262fa5383de3d3b45e951d7ef955f3a18b9689783898bedb66f0b8
+CT = 2ecf7a3a35abb50d212588c2ef50880212b53c052738767c9ea215709208afae6e94acd68980207bf63382495be1acde784b92
+Tag = 49563e12797eefbee2fd75a1e844869b
+
+Count = 1
+Key = e175c46cb437fd92fbb91ef33b9c92545368a3068ab22ae48e97cb05c84231f5
+IV = 9ecac402b7342c2d55849b1068562ac78b2626e3346393b6587372afbac81cd7c13cf6dc3a479d61b9fc530b243ad80dd5516ea9b0c550b61fec571712cde93fa5265fb9a7f92eba7f846940e053a62324f002118867173490ccdbb04df41ca8e2c2c79f5ced7a815ab60e2b058f98e26c2a57424c02b923bea76bca75fc0d3a
+PT = d115a6e65ba9fb4435c059e675bedb73e28447e315727390f38c618e434e7056d2b92a53822e6b04dd3c71c274c1c00360f887
+AAD = 89d72ae1054e1b863d7188f462325d04d3a4afb2839a6c1d292d61c60980744b654fa2ac384cea33cdc5736395a606bc5be4e6ee9c0cb6c3e7b21eee8f599d773881ecce3c6ecca395cfbf226e3f36629f01d7fced0152dceec9
+CT = c66a5c6900a9c132b2375129841df87238c88f1c59278c22126f1a59c0018f6526d1745dce387d23aebfa66aab1c153d3d0e1d
+Tag = b56663e0d82c0363b999864ea3d65bc4
+
+[Keylen = 256]
+[IVlen = 1024]
+[PTlen = 408]
+[AADlen = 720]
+[Taglen = 96]
+
+Count = 0
+Key = 5f99cb75b5ee893151124c3c7c84311634c3f7b6af54a7acae102d960e993fc3
+IV = c8172405064313e1b584b468f045b487de1ed8174977b210f5d0b108752fa7b1b9adbd9f4df16b2a5b71f3c08a8e52fca080a70a5346f028911c5c3b9ca575ae2a1085a7dbe29b1e916bb0f48ecb61cca2c5525bef4e47931aac6782a09c9636f782a843a54d3ad8ab94b9535d67452e6f62abd8cf100c35d3cae8de9813a753
+PT = b1d2930b1540edd6bd0cb0df6e3250ea256b7539d6f47edf3a39f884aff850fc57571122e8278c1bdd5d56afa6f6747c09bedc
+AAD = e54240d7849a9f25741e899ae5526fc7fb8c8d66240cca78fbed553f9acb25344776e21f181dac6ea040ec3db31baf8791c74de0ca1cabbcf2ce087c26a61eec02371ef664fc179debae153b0f0778891a86ad09bf0e5fce641b
+CT = 0d73e28b9a1e27ed98f91b3a92b56531b0ece1db8ae2da4bad0e5bfb57867f27e66a510e3319bc0435b02cb563d8b041e7c836
+Tag = 5c6f64fea8c5cc7ef0fefd22
+
+Count = 1
+Key = bd8aec99ac04efe8ad86cf568e7a04c30a40bc675592aaba600f7a81884fad90
+IV = d6dea1c6f60a97423cef9c0151bcbff106b97aeaf5b1a5cfe93064cf1837386fbf18c1db9db5a6ebe77ac439ed5a3bfd5a7e7c75fe34371f37d5fdcc951c4d88186bea008f59e25f57d2ca403a3f3f5a76a4dc26fff56eaba58f36c62767250e384ecda4d2ee343e73d3584026177fdacff165db3f646e4df3b8c7f8930d05a5
+PT = 43776395457cd567f3694c8fb85a277d279062e84b7482b0addce541fd7e20afd16b2eb6ce84c9553e24c1b79c59f0b3288a7a
+AAD = d8dd2239b5f1baf7c25a88f3d33621dbd45827d80984c399e7a3042b4f665c454cdace7cfa084c333de5b520069cc1055d6050e955ce94f9afdc92ff5b9c3d183b406b179aa5800bc703879092a0160e8d8518636d05c07bec25
+CT = 108ff952eed143c439b7aba5dcf835f2386b54c80dd6c53c3e88fc07773a67b782115dab9f8356090fb1036c3e87102852f633
+Tag = 025b98721a1d31a1e55fdab0
+
diff --git a/security/nss/cmd/pk11mode/Makefile b/security/nss/cmd/pk11mode/Makefile
new file mode 100755
index 000000000..e9cbcac40
--- /dev/null
+++ b/security/nss/cmd/pk11mode/Makefile
@@ -0,0 +1,65 @@
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+ifeq ($(OS_ARCH), WINNT)
+
+EXTRA_LIBS += \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.$(LIB_SUFFIX) \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.$(LIB_SUFFIX) \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.$(LIB_SUFFIX) \
+ $(NULL)
+
+else
+
+EXTRA_SHARED_LIBS += \
+ -L$(NSPR_LIB_DIR) \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4 \
+ $(NULL)
+
+endif
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/pk11mode/manifest.mn b/security/nss/cmd/pk11mode/manifest.mn
new file mode 100644
index 000000000..ed205cded
--- /dev/null
+++ b/security/nss/cmd/pk11mode/manifest.mn
@@ -0,0 +1,16 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+EXPORTS =
+
+CSRCS = pk11mode.c
+
+PROGRAM = pk11mode
+
+REQUIRES = seccmd
diff --git a/security/nss/cmd/pk11mode/pk11mode.c b/security/nss/cmd/pk11mode/pk11mode.c
new file mode 100644
index 000000000..2f1fa374e
--- /dev/null
+++ b/security/nss/cmd/pk11mode/pk11mode.c
@@ -0,0 +1,5387 @@
+/*
+ * pk11mode.c - Test FIPS or NONFIPS Modes for the NSS PKCS11 api.
+ * The goal of this program is to test every function
+ * entry point of the PKCS11 api at least once.
+ * To test in FIPS mode: pk11mode
+ * To test in NONFIPS mode: pk11mode -n
+ * usage: pk11mode -h
+ *
+ * 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/. */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#if defined(XP_UNIX) && !defined(NO_FORK_CHECK)
+#include <unistd.h>
+#include <sys/wait.h>
+#else
+#ifndef NO_FORK_CHECK
+#define NO_FORK_CHECK
+#endif
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#define LIB_NAME "softokn3.dll"
+#endif
+#include "prlink.h"
+#include "prprf.h"
+#include "plgetopt.h"
+#include "prenv.h"
+
+#include "pk11table.h"
+
+#define NUM_ELEM(array) (sizeof(array) / sizeof(array[0]))
+
+#ifndef NULL_PTR
+#define NULL_PTR 0
+#endif
+
+/* Returns constant error string for "CRV".
+ * Returns "unknown error" if errNum is unknown.
+ */
+const char *
+PKM_CK_RVtoStr(CK_RV errNum)
+{
+ const char *err;
+
+ err = getName(errNum, ConstResult);
+
+ if (err)
+ return err;
+
+ return "unknown error";
+}
+
+#include "pkcs11p.h"
+
+typedef struct CK_C_INITIALIZE_ARGS_NSS {
+ CK_CREATEMUTEX CreateMutex;
+ CK_DESTROYMUTEX DestroyMutex;
+ CK_LOCKMUTEX LockMutex;
+ CK_UNLOCKMUTEX UnlockMutex;
+ CK_FLAGS flags;
+ /* The official PKCS #11 spec does not have a 'LibraryParameters' field, but
+ * a reserved field. NSS needs a way to pass instance-specific information
+ * to the library (like where to find its config files, etc). This
+ * information is usually provided by the installer and passed uninterpreted
+ * by NSS to the library, though NSS does know the specifics of the softoken
+ * version of this parameter. Most compliant PKCS#11 modules expect this
+ * parameter to be NULL, and will return CKR_ARGUMENTS_BAD from
+ * C_Initialize if Library parameters is supplied. */
+ CK_CHAR_PTR *LibraryParameters;
+ /* This field is only present if the LibraryParameters is not NULL. It must
+ * be NULL in all cases */
+ CK_VOID_PTR pReserved;
+} CK_C_INITIALIZE_ARGS_NSS;
+
+#include "pkcs11u.h"
+
+#define MAX_SIG_SZ 128
+#define MAX_CIPHER_SZ 128
+#define MAX_DATA_SZ 64
+#define MAX_DIGEST_SZ 64
+#define HMAC_MAX_LENGTH 64
+#define FIPSMODE 0
+#define NONFIPSMODE 1
+#define HYBRIDMODE 2
+#define NOMODE 3
+int MODE = FIPSMODE;
+
+CK_BBOOL true = CK_TRUE;
+CK_BBOOL false = CK_FALSE;
+static const CK_BYTE PLAINTEXT[] = { "Firefox Rules!" };
+static const CK_BYTE PLAINTEXT_PAD[] =
+ { "Firefox and thunderbird rule the world!" };
+CK_ULONG NUMTESTS = 0;
+
+static const char *slotFlagName[] = {
+ "CKF_TOKEN_PRESENT",
+ "CKF_REMOVABLE_DEVICE",
+ "CKF_HW_SLOT",
+ "unknown token flag 0x00000008",
+ "unknown token flag 0x00000010",
+ "unknown token flag 0x00000020",
+ "unknown token flag 0x00000040",
+ "unknown token flag 0x00000080",
+ "unknown token flag 0x00000100",
+ "unknown token flag 0x00000200",
+ "unknown token flag 0x00000400",
+ "unknown token flag 0x00000800",
+ "unknown token flag 0x00001000",
+ "unknown token flag 0x00002000",
+ "unknown token flag 0x00004000",
+ "unknown token flag 0x00008000"
+ "unknown token flag 0x00010000",
+ "unknown token flag 0x00020000",
+ "unknown token flag 0x00040000",
+ "unknown token flag 0x00080000",
+ "unknown token flag 0x00100000",
+ "unknown token flag 0x00200000",
+ "unknown token flag 0x00400000",
+ "unknown token flag 0x00800000"
+ "unknown token flag 0x01000000",
+ "unknown token flag 0x02000000",
+ "unknown token flag 0x04000000",
+ "unknown token flag 0x08000000",
+ "unknown token flag 0x10000000",
+ "unknown token flag 0x20000000",
+ "unknown token flag 0x40000000",
+ "unknown token flag 0x80000000"
+};
+
+static const char *tokenFlagName[] = {
+ "CKF_PKM_RNG",
+ "CKF_WRITE_PROTECTED",
+ "CKF_LOGIN_REQUIRED",
+ "CKF_USER_PIN_INITIALIZED",
+ "unknown token flag 0x00000010",
+ "CKF_RESTORE_KEY_NOT_NEEDED",
+ "CKF_CLOCK_ON_TOKEN",
+ "unknown token flag 0x00000080",
+ "CKF_PROTECTED_AUTHENTICATION_PATH",
+ "CKF_DUAL_CRYPTO_OPERATIONS",
+ "CKF_TOKEN_INITIALIZED",
+ "CKF_SECONDARY_AUTHENTICATION",
+ "unknown token flag 0x00001000",
+ "unknown token flag 0x00002000",
+ "unknown token flag 0x00004000",
+ "unknown token flag 0x00008000",
+ "CKF_USER_PIN_COUNT_LOW",
+ "CKF_USER_PIN_FINAL_TRY",
+ "CKF_USER_PIN_LOCKED",
+ "CKF_USER_PIN_TO_BE_CHANGED",
+ "CKF_SO_PIN_COUNT_LOW",
+ "CKF_SO_PIN_FINAL_TRY",
+ "CKF_SO_PIN_LOCKED",
+ "CKF_SO_PIN_TO_BE_CHANGED",
+ "unknown token flag 0x01000000",
+ "unknown token flag 0x02000000",
+ "unknown token flag 0x04000000",
+ "unknown token flag 0x08000000",
+ "unknown token flag 0x10000000",
+ "unknown token flag 0x20000000",
+ "unknown token flag 0x40000000",
+ "unknown token flag 0x80000000"
+};
+
+static const unsigned char TLSClientRandom[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0d, 0x90, 0xbb, 0x5e, 0xc6, 0xe1, 0x3f, 0x71,
+ 0x0a, 0xa2, 0x70, 0x5a, 0x4f, 0xbc, 0x3f, 0x0d
+};
+static const unsigned char TLSServerRandom[] = {
+ 0x00, 0x00, 0x1d, 0x4a, 0x7a, 0x0a, 0xa5, 0x01,
+ 0x8e, 0x79, 0x72, 0xde, 0x9e, 0x2f, 0x8a, 0x0d,
+ 0xed, 0xb2, 0x5d, 0xf1, 0x14, 0xc2, 0xc6, 0x66,
+ 0x95, 0x86, 0xb0, 0x0d, 0x87, 0x2a, 0x2a, 0xc9
+};
+
+typedef enum {
+ CORRECT,
+ BOGUS_CLIENT_RANDOM,
+ BOGUS_CLIENT_RANDOM_LEN,
+ BOGUS_SERVER_RANDOM,
+ BOGUS_SERVER_RANDOM_LEN
+} enum_random_t;
+
+void
+dumpToHash64(const unsigned char *buf, unsigned int bufLen)
+{
+ unsigned int i;
+ for (i = 0; i < bufLen; i += 8) {
+ if (i % 32 == 0)
+ printf("\n");
+ printf(" 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,",
+ buf[i], buf[i + 1], buf[i + 2], buf[i + 3],
+ buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]);
+ }
+ printf("\n");
+}
+
+#ifdef _WIN32
+HMODULE hModule;
+#else
+PRLibrary *lib;
+#endif
+
+/*
+* All api that belongs to pk11mode.c layer start with the prefix PKM_
+*/
+void PKM_LogIt(const char *fmt, ...);
+void PKM_Error(const char *fmt, ...);
+CK_SLOT_ID *PKM_GetSlotList(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_ULONG slotID);
+CK_RV PKM_ShowInfo(CK_FUNCTION_LIST_PTR pFunctionList, CK_ULONG slotID);
+CK_RV PKM_InitPWforDB(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
+CK_RV PKM_Mechanism(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID);
+CK_RV PKM_RNG(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID *pSlotList,
+ CK_ULONG slotID);
+CK_RV PKM_SessionLogin(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
+CK_RV PKM_SecretKey(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID *pSlotList,
+ CK_ULONG slotID, CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
+CK_RV PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID *pSlotList,
+ CK_ULONG slotID, CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
+CK_RV PKM_HybridMode(CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen,
+ CK_C_INITIALIZE_ARGS_NSS *initArgs);
+CK_RV PKM_FindAllObjects(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
+CK_RV PKM_MultiObjectManagement(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
+CK_RV PKM_OperationalState(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
+CK_RV PKM_LegacyFunctions(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
+CK_RV PKM_AttributeCheck(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_PTR expected_attrs,
+ CK_ULONG expected_attrs_count);
+CK_RV PKM_MechCheck(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hSession, CK_MECHANISM_TYPE mechType,
+ CK_FLAGS flags, CK_BBOOL check_sizes,
+ CK_ULONG minkeysize, CK_ULONG maxkeysize);
+CK_RV PKM_TLSKeyAndMacDerive(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen,
+ CK_MECHANISM_TYPE mechType, enum_random_t rnd);
+CK_RV PKM_TLSMasterKeyDerive(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen,
+ CK_MECHANISM_TYPE mechType,
+ enum_random_t rnd);
+CK_RV PKM_KeyTests(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
+CK_RV PKM_DualFuncSign(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hRwSession,
+ CK_OBJECT_HANDLE publicKey, CK_OBJECT_HANDLE privateKey,
+ CK_MECHANISM *sigMech, CK_OBJECT_HANDLE secretKey,
+ CK_MECHANISM *cryptMech,
+ const CK_BYTE *pData, CK_ULONG pDataLen);
+CK_RV PKM_DualFuncDigest(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hSecKey, CK_MECHANISM *cryptMech,
+ CK_OBJECT_HANDLE hSecKeyDigest,
+ CK_MECHANISM *digestMech,
+ const CK_BYTE *pData, CK_ULONG pDataLen);
+CK_RV PKM_PubKeySign(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hRwSession,
+ CK_OBJECT_HANDLE hPubKey, CK_OBJECT_HANDLE hPrivKey,
+ CK_MECHANISM *signMech, const CK_BYTE *pData,
+ CK_ULONG dataLen);
+CK_RV PKM_SecKeyCrypt(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hSymKey, CK_MECHANISM *cryptMech,
+ const CK_BYTE *pData, CK_ULONG dataLen);
+CK_RV PKM_Hmac(CK_FUNCTION_LIST_PTR pFunctionList, CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE sKey, CK_MECHANISM *hmacMech,
+ const CK_BYTE *pData, CK_ULONG pDataLen);
+CK_RV PKM_Digest(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hRwSession,
+ CK_MECHANISM *digestMech, CK_OBJECT_HANDLE hSecretKey,
+ const CK_BYTE *pData, CK_ULONG pDataLen);
+CK_RV PKM_wrapUnwrap(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hPublicKey,
+ CK_OBJECT_HANDLE hPrivateKey,
+ CK_MECHANISM *wrapMechanism,
+ CK_OBJECT_HANDLE hSecretKey,
+ CK_ATTRIBUTE *sKeyTemplate,
+ CK_ULONG skeyTempSize);
+CK_RV PKM_RecoverFunctions(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hPubKey, CK_OBJECT_HANDLE hPrivKey,
+ CK_MECHANISM *signMech, const CK_BYTE *pData,
+ CK_ULONG pDataLen);
+CK_RV PKM_ForkCheck(int expected, CK_FUNCTION_LIST_PTR fList,
+ PRBool forkAssert, CK_C_INITIALIZE_ARGS_NSS *initArgs);
+
+void PKM_Help();
+void PKM_CheckPath(char *string);
+char *PKM_FilePasswd(char *pwFile);
+static PRBool verbose = PR_FALSE;
+
+int
+main(int argc, char **argv)
+{
+ CK_C_GetFunctionList pC_GetFunctionList;
+ CK_FUNCTION_LIST_PTR pFunctionList;
+ CK_RV crv = CKR_OK;
+ CK_C_INITIALIZE_ARGS_NSS initArgs;
+ CK_SLOT_ID *pSlotList = NULL;
+ CK_TOKEN_INFO tokenInfo;
+ CK_ULONG slotID = 0; /* slotID == 0 for FIPSMODE */
+
+ CK_UTF8CHAR *pwd = NULL;
+ CK_ULONG pwdLen = 0;
+ char *moduleSpec = NULL;
+ char *configDir = NULL;
+ char *dbPrefix = NULL;
+ char *disableUnload = NULL;
+ PRBool doForkTests = PR_TRUE;
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "nvhf:Fd:p:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
+ if (PL_OPT_BAD == os)
+ continue;
+ switch (opt->option) {
+ case 'F': /* disable fork tests */
+ doForkTests = PR_FALSE;
+ break;
+ case 'n': /* non fips mode */
+ MODE = NONFIPSMODE;
+ slotID = 1;
+ break;
+ case 'f': /* password file */
+ pwd = (CK_UTF8CHAR *)PKM_FilePasswd((char *)opt->value);
+ if (!pwd)
+ PKM_Help();
+ break;
+ case 'd': /* opt_CertDir */
+ if (!opt->value)
+ PKM_Help();
+ configDir = strdup(opt->value);
+ PKM_CheckPath(configDir);
+ break;
+ case 'p': /* opt_DBPrefix */
+ if (!opt->value)
+ PKM_Help();
+ dbPrefix = strdup(opt->value);
+ break;
+ case 'v':
+ verbose = PR_TRUE;
+ break;
+ case 'h': /* help message */
+ default:
+ PKM_Help();
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (!pwd) {
+ pwd = (CK_UTF8CHAR *)strdup("1Mozilla");
+ }
+ pwdLen = strlen((const char *)pwd);
+ if (!configDir) {
+ configDir = strdup(".");
+ }
+ if (!dbPrefix) {
+ dbPrefix = strdup("");
+ }
+
+ if (doForkTests) {
+ /* first, try to fork without softoken loaded to make sure
+ * everything is OK */
+ crv = PKM_ForkCheck(123, NULL, PR_FALSE, NULL);
+ if (crv != CKR_OK)
+ goto cleanup;
+ }
+
+#ifdef _WIN32
+ hModule = LoadLibrary(LIB_NAME);
+ if (hModule == NULL) {
+ PKM_Error("cannot load %s\n", LIB_NAME);
+ goto cleanup;
+ }
+ if (MODE == FIPSMODE) {
+ /* FIPS mode == FC_GetFunctionList */
+ pC_GetFunctionList = (CK_C_GetFunctionList)
+ GetProcAddress(hModule, "FC_GetFunctionList");
+ } else {
+ /* NON FIPS mode == C_GetFunctionList */
+ pC_GetFunctionList = (CK_C_GetFunctionList)
+ GetProcAddress(hModule, "C_GetFunctionList");
+ }
+ if (pC_GetFunctionList == NULL) {
+ PKM_Error("cannot load %s\n", LIB_NAME);
+ goto cleanup;
+ }
+#else
+ {
+ char *libname = NULL;
+ /* Get the platform-dependent library name of the NSS cryptographic module */
+ libname = PR_GetLibraryName(NULL, "softokn3");
+ assert(libname != NULL);
+ lib = PR_LoadLibrary(libname);
+ assert(lib != NULL);
+ PR_FreeLibraryName(libname);
+ }
+ if (MODE == FIPSMODE) {
+ pC_GetFunctionList = (CK_C_GetFunctionList)PR_FindFunctionSymbol(lib,
+ "FC_GetFunctionList");
+ assert(pC_GetFunctionList != NULL);
+ slotID = 0;
+ } else {
+ pC_GetFunctionList = (CK_C_GetFunctionList)PR_FindFunctionSymbol(lib,
+ "C_GetFunctionList");
+ assert(pC_GetFunctionList != NULL);
+ slotID = 1;
+ }
+#endif
+
+ if (MODE == FIPSMODE) {
+ printf("Loaded FC_GetFunctionList for FIPS MODE; slotID %d \n",
+ (int)slotID);
+ } else {
+ printf("loaded C_GetFunctionList for NON FIPS MODE; slotID %d \n",
+ (int)slotID);
+ }
+
+ crv = (*pC_GetFunctionList)(&pFunctionList);
+ assert(crv == CKR_OK);
+
+ if (doForkTests) {
+ /* now, try to fork with softoken loaded, but not initialized */
+ crv = PKM_ForkCheck(CKR_CRYPTOKI_NOT_INITIALIZED, pFunctionList,
+ PR_TRUE, NULL);
+ if (crv != CKR_OK)
+ goto cleanup;
+ }
+
+ initArgs.CreateMutex = NULL;
+ initArgs.DestroyMutex = NULL;
+ initArgs.LockMutex = NULL;
+ initArgs.UnlockMutex = NULL;
+ initArgs.flags = CKF_OS_LOCKING_OK;
+ moduleSpec = PR_smprintf("configdir='%s' certPrefix='%s' "
+ "keyPrefix='%s' secmod='secmod.db' flags= ",
+ configDir, dbPrefix, dbPrefix);
+ initArgs.LibraryParameters = (CK_CHAR_PTR *)moduleSpec;
+ initArgs.pReserved = NULL;
+
+ /*DebugBreak();*/
+ /* FIPSMODE invokes FC_Initialize as pFunctionList->C_Initialize */
+ /* NSS cryptographic module library initialization for the FIPS */
+ /* Approved mode when FC_Initialize is envoked will perfom */
+ /* software integrity test, and power-up self-tests before */
+ /* FC_Initialize returns */
+ crv = pFunctionList->C_Initialize(&initArgs);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Initialize succeeded\n");
+ } else {
+ PKM_Error("C_Initialize failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+
+ if (doForkTests) {
+ /* Disable core on fork for this test, since we are testing the
+ * pathological case, and if enabled, the child process would dump
+ * core in C_GetTokenInfo .
+ * We can still differentiate the correct from incorrect behavior
+ * by the PKCS#11 return code.
+ */
+ /* try to fork with softoken both loaded and initialized */
+ crv = PKM_ForkCheck(CKR_DEVICE_ERROR, pFunctionList, PR_FALSE, NULL);
+ if (crv != CKR_OK)
+ goto cleanup;
+ }
+
+ if (doForkTests) {
+ /* In this next test, we fork and try to re-initialize softoken in
+ * the child. This should now work because softoken has the ability
+ * to hard reset.
+ */
+ /* try to fork with softoken both loaded and initialized */
+ crv = PKM_ForkCheck(CKR_OK, pFunctionList, PR_TRUE, &initArgs);
+ if (crv != CKR_OK)
+ goto cleanup;
+ }
+
+ crv = PKM_ShowInfo(pFunctionList, slotID);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_ShowInfo succeeded\n");
+ } else {
+ PKM_Error("PKM_ShowInfo failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+ pSlotList = PKM_GetSlotList(pFunctionList, slotID);
+ if (pSlotList == NULL) {
+ PKM_Error("PKM_GetSlotList failed with \n");
+ goto cleanup;
+ }
+ crv = pFunctionList->C_GetTokenInfo(pSlotList[slotID], &tokenInfo);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GetTokenInfo succeeded\n\n");
+ } else {
+ PKM_Error("C_GetTokenInfo failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+
+ if (!(tokenInfo.flags & CKF_USER_PIN_INITIALIZED)) {
+ PKM_LogIt("Initing PW for DB\n");
+ crv = PKM_InitPWforDB(pFunctionList, pSlotList, slotID,
+ pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_InitPWforDB succeeded\n\n");
+ } else {
+ PKM_Error("PKM_InitPWforDB failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+ } else {
+ PKM_LogIt("using existing DB\n");
+ }
+
+ /* general mechanism by token */
+ crv = PKM_Mechanism(pFunctionList, pSlotList, slotID);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_Mechanism succeeded\n\n");
+ } else {
+ PKM_Error("PKM_Mechanism failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+ /* RNG example without Login */
+ crv = PKM_RNG(pFunctionList, pSlotList, slotID);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_RNG succeeded\n\n");
+ } else {
+ PKM_Error("PKM_RNG failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+
+ crv = PKM_SessionLogin(pFunctionList, pSlotList, slotID,
+ pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_SessionLogin succeeded\n\n");
+ } else {
+ PKM_Error("PKM_SessionLogin failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+
+ /*
+ * PKM_KeyTest creates RSA,DSA public keys
+ * and AES, DES3 secret keys.
+ * then does digest, hmac, encrypt/decrypt, signing operations.
+ */
+ crv = PKM_KeyTests(pFunctionList, pSlotList, slotID,
+ pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_KeyTests succeeded\n\n");
+ } else {
+ PKM_Error("PKM_KeyTest failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+
+ crv = PKM_SecretKey(pFunctionList, pSlotList, slotID, pwd,
+ pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_SecretKey succeeded\n\n");
+ } else {
+ PKM_Error("PKM_SecretKey failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+
+ crv = PKM_PublicKey(pFunctionList, pSlotList, slotID,
+ pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_PublicKey succeeded\n\n");
+ } else {
+ PKM_Error("PKM_PublicKey failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+ crv = PKM_OperationalState(pFunctionList, pSlotList, slotID,
+ pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_OperationalState succeeded\n\n");
+ } else {
+ PKM_Error("PKM_OperationalState failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+ crv = PKM_MultiObjectManagement(pFunctionList, pSlotList, slotID,
+ pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_MultiObjectManagement succeeded\n\n");
+ } else {
+ PKM_Error("PKM_MultiObjectManagement failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+ crv = PKM_LegacyFunctions(pFunctionList, pSlotList, slotID,
+ pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_LegacyFunctions succeeded\n\n");
+ } else {
+ PKM_Error("PKM_LegacyFunctions failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+ crv = PKM_TLSKeyAndMacDerive(pFunctionList, pSlotList, slotID,
+ pwd, pwdLen,
+ CKM_TLS_KEY_AND_MAC_DERIVE, CORRECT);
+
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_TLSKeyAndMacDerive succeeded\n\n");
+ } else {
+ PKM_Error("PKM_TLSKeyAndMacDerive failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+ crv = PKM_TLSMasterKeyDerive(pFunctionList, pSlotList, slotID,
+ pwd, pwdLen,
+ CKM_TLS_MASTER_KEY_DERIVE,
+ CORRECT);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_TLSMasterKeyDerive succeeded\n\n");
+ } else {
+ PKM_Error("PKM_TLSMasterKeyDerive failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+ crv = PKM_TLSMasterKeyDerive(pFunctionList, pSlotList, slotID,
+ pwd, pwdLen,
+ CKM_TLS_MASTER_KEY_DERIVE_DH,
+ CORRECT);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_TLSMasterKeyDerive succeeded\n\n");
+ } else {
+ PKM_Error("PKM_TLSMasterKeyDerive failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+ crv = PKM_FindAllObjects(pFunctionList, pSlotList, slotID,
+ pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_FindAllObjects succeeded\n\n");
+ } else {
+ PKM_Error("PKM_FindAllObjects failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+ crv = pFunctionList->C_Finalize(NULL);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Finalize succeeded\n");
+ } else {
+ PKM_Error("C_Finalize failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+
+ if (doForkTests) {
+ /* try to fork with softoken still loaded, but de-initialized */
+ crv = PKM_ForkCheck(CKR_CRYPTOKI_NOT_INITIALIZED, pFunctionList,
+ PR_TRUE, NULL);
+ if (crv != CKR_OK)
+ goto cleanup;
+ }
+
+ free(pSlotList);
+
+ /* demonstrate how an application can be in Hybrid mode */
+ /* PKM_HybridMode shows how to switch between NONFIPS */
+ /* mode to FIPS mode */
+
+ PKM_LogIt("Testing Hybrid mode \n");
+ crv = PKM_HybridMode(pwd, pwdLen, &initArgs);
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_HybridMode succeeded\n");
+ } else {
+ PKM_Error("PKM_HybridMode failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+
+ if (doForkTests) {
+ /* testing one more C_Initialize / C_Finalize to exercise getpid()
+ * fork check code */
+ crv = pFunctionList->C_Initialize(&initArgs);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Initialize succeeded\n");
+ } else {
+ PKM_Error("C_Initialize failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+ crv = pFunctionList->C_Finalize(NULL);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Finalize succeeded\n");
+ } else {
+ PKM_Error("C_Finalize failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ goto cleanup;
+ }
+ /* try to C_Initialize / C_Finalize in child. This should succeed */
+ crv = PKM_ForkCheck(CKR_OK, pFunctionList, PR_TRUE, &initArgs);
+ }
+
+ PKM_LogIt("unloading NSS PKCS # 11 softoken and exiting\n");
+
+cleanup:
+
+ if (pwd) {
+ free(pwd);
+ }
+ if (configDir) {
+ free(configDir);
+ }
+ if (dbPrefix) {
+ free(dbPrefix);
+ }
+ if (moduleSpec) {
+ PR_smprintf_free(moduleSpec);
+ }
+
+#ifdef _WIN32
+ FreeLibrary(hModule);
+#else
+ disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
+ if (!disableUnload) {
+ PR_UnloadLibrary(lib);
+ }
+#endif
+ if (CKR_OK == crv && doForkTests && !disableUnload) {
+ /* try to fork with softoken both de-initialized and unloaded */
+ crv = PKM_ForkCheck(123, NULL, PR_TRUE, NULL);
+ }
+
+ printf("**** Total number of TESTS ran in %s is %d. ****\n",
+ ((MODE == FIPSMODE) ? "FIPS MODE" : "NON FIPS MODE"), (int)NUMTESTS);
+ if (CKR_OK == crv) {
+ printf("**** ALL TESTS PASSED ****\n");
+ }
+
+ return crv;
+}
+
+/*
+* PKM_KeyTests
+*
+*
+*/
+
+CK_RV
+PKM_KeyTests(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
+{
+ CK_SESSION_HANDLE hRwSession;
+
+ CK_RV crv = CKR_OK;
+
+ /*** DSA Key ***/
+ CK_MECHANISM dsaParamGenMech;
+ CK_ULONG primeBits = 1024;
+ CK_ATTRIBUTE dsaParamGenTemplate[1];
+ CK_OBJECT_HANDLE hDsaParams = CK_INVALID_HANDLE;
+ CK_BYTE DSA_P[128];
+ CK_BYTE DSA_Q[20];
+ CK_BYTE DSA_G[128];
+ CK_MECHANISM dsaKeyPairGenMech;
+ CK_ATTRIBUTE dsaPubKeyTemplate[5];
+ CK_ATTRIBUTE dsaPrivKeyTemplate[5];
+ CK_OBJECT_HANDLE hDSApubKey = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hDSAprivKey = CK_INVALID_HANDLE;
+
+ /**** RSA Key ***/
+ CK_KEY_TYPE rsatype = CKK_RSA;
+ CK_MECHANISM rsaKeyPairGenMech;
+ CK_BYTE subject[] = { "RSA Private Key" };
+ CK_ULONG modulusBits = 1024;
+ CK_BYTE publicExponent[] = { 0x01, 0x00, 0x01 };
+ CK_BYTE id[] = { "RSA123" };
+ CK_ATTRIBUTE rsaPubKeyTemplate[9];
+ CK_ATTRIBUTE rsaPrivKeyTemplate[11];
+ CK_OBJECT_HANDLE hRSApubKey = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hRSAprivKey = CK_INVALID_HANDLE;
+
+ /*** AES Key ***/
+ CK_MECHANISM sAESKeyMech = {
+ CKM_AES_KEY_GEN, NULL, 0
+ };
+ CK_OBJECT_CLASS class = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyAESType = CKK_AES;
+ CK_UTF8CHAR AESlabel[] = "An AES secret key object";
+ CK_ULONG AESvalueLen = 32;
+ CK_ATTRIBUTE sAESKeyTemplate[9];
+ CK_OBJECT_HANDLE hAESSecKey;
+
+ /*** DES3 Key ***/
+ CK_KEY_TYPE keyDES3Type = CKK_DES3;
+ CK_UTF8CHAR DES3label[] = "An Triple DES secret key object";
+ CK_ULONG DES3valueLen = 56;
+ CK_MECHANISM sDES3KeyGenMechanism = {
+ CKM_DES3_KEY_GEN, NULL, 0
+ };
+ CK_ATTRIBUTE sDES3KeyTemplate[9];
+ CK_OBJECT_HANDLE hDES3SecKey;
+
+ CK_MECHANISM dsaWithSha1Mech = {
+ CKM_DSA_SHA1, NULL, 0
+ };
+
+ CK_BYTE IV[16];
+ CK_MECHANISM mech_DES3_CBC;
+ CK_MECHANISM mech_DES3_CBC_PAD;
+ CK_MECHANISM mech_AES_CBC_PAD;
+ CK_MECHANISM mech_AES_CBC;
+ struct mech_str {
+ CK_ULONG mechanism;
+ const char *mechanismStr;
+ };
+
+ typedef struct mech_str mech_str;
+
+ mech_str digestMechs[] = {
+ { CKM_SHA_1, "CKM_SHA_1 " },
+ { CKM_SHA224, "CKM_SHA224" },
+ { CKM_SHA256, "CKM_SHA256" },
+ { CKM_SHA384, "CKM_SHA384" },
+ { CKM_SHA512, "CKM_SHA512" }
+ };
+ mech_str hmacMechs[] = {
+ { CKM_SHA_1_HMAC, "CKM_SHA_1_HMAC" },
+ { CKM_SHA224_HMAC, "CKM_SHA224_HMAC" },
+ { CKM_SHA256_HMAC, "CKM_SHA256_HMAC" },
+ { CKM_SHA384_HMAC, "CKM_SHA384_HMAC" },
+ { CKM_SHA512_HMAC, "CKM_SHA512_HMAC" }
+ };
+ mech_str sigRSAMechs[] = {
+ { CKM_SHA1_RSA_PKCS, "CKM_SHA1_RSA_PKCS" },
+ { CKM_SHA224_RSA_PKCS, "CKM_SHA224_RSA_PKCS" },
+ { CKM_SHA256_RSA_PKCS, "CKM_SHA256_RSA_PKCS" },
+ { CKM_SHA384_RSA_PKCS, "CKM_SHA384_RSA_PKCS" },
+ { CKM_SHA512_RSA_PKCS, "CKM_SHA512_RSA_PKCS" }
+ };
+
+ CK_ULONG digestMechsSZ = NUM_ELEM(digestMechs);
+ CK_ULONG sigRSAMechsSZ = NUM_ELEM(sigRSAMechs);
+ CK_ULONG hmacMechsSZ = NUM_ELEM(hmacMechs);
+ CK_MECHANISM mech;
+
+ unsigned int i;
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ /* DSA key init */
+ dsaParamGenMech.mechanism = CKM_DSA_PARAMETER_GEN;
+ dsaParamGenMech.pParameter = NULL_PTR;
+ dsaParamGenMech.ulParameterLen = 0;
+ dsaParamGenTemplate[0].type = CKA_PRIME_BITS;
+ dsaParamGenTemplate[0].pValue = &primeBits;
+ dsaParamGenTemplate[0].ulValueLen = sizeof(primeBits);
+ dsaPubKeyTemplate[0].type = CKA_PRIME;
+ dsaPubKeyTemplate[0].pValue = DSA_P;
+ dsaPubKeyTemplate[0].ulValueLen = sizeof(DSA_P);
+ dsaPubKeyTemplate[1].type = CKA_SUBPRIME;
+ dsaPubKeyTemplate[1].pValue = DSA_Q;
+ dsaPubKeyTemplate[1].ulValueLen = sizeof(DSA_Q);
+ dsaPubKeyTemplate[2].type = CKA_BASE;
+ dsaPubKeyTemplate[2].pValue = DSA_G;
+ dsaPubKeyTemplate[2].ulValueLen = sizeof(DSA_G);
+ dsaPubKeyTemplate[3].type = CKA_TOKEN;
+ dsaPubKeyTemplate[3].pValue = &true;
+ dsaPubKeyTemplate[3].ulValueLen = sizeof(true);
+ dsaPubKeyTemplate[4].type = CKA_VERIFY;
+ dsaPubKeyTemplate[4].pValue = &true;
+ dsaPubKeyTemplate[4].ulValueLen = sizeof(true);
+ dsaKeyPairGenMech.mechanism = CKM_DSA_KEY_PAIR_GEN;
+ dsaKeyPairGenMech.pParameter = NULL_PTR;
+ dsaKeyPairGenMech.ulParameterLen = 0;
+ dsaPrivKeyTemplate[0].type = CKA_TOKEN;
+ dsaPrivKeyTemplate[0].pValue = &true;
+ dsaPrivKeyTemplate[0].ulValueLen = sizeof(true);
+ dsaPrivKeyTemplate[1].type = CKA_PRIVATE;
+ dsaPrivKeyTemplate[1].pValue = &true;
+ dsaPrivKeyTemplate[1].ulValueLen = sizeof(true);
+ dsaPrivKeyTemplate[2].type = CKA_SENSITIVE;
+ dsaPrivKeyTemplate[2].pValue = &true;
+ dsaPrivKeyTemplate[2].ulValueLen = sizeof(true);
+ dsaPrivKeyTemplate[3].type = CKA_SIGN,
+ dsaPrivKeyTemplate[3].pValue = &true;
+ dsaPrivKeyTemplate[3].ulValueLen = sizeof(true);
+ dsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE;
+ dsaPrivKeyTemplate[4].pValue = &true;
+ dsaPrivKeyTemplate[4].ulValueLen = sizeof(true);
+
+ /* RSA key init */
+ rsaKeyPairGenMech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
+ rsaKeyPairGenMech.pParameter = NULL_PTR;
+ rsaKeyPairGenMech.ulParameterLen = 0;
+
+ rsaPubKeyTemplate[0].type = CKA_KEY_TYPE;
+ rsaPubKeyTemplate[0].pValue = &rsatype;
+ rsaPubKeyTemplate[0].ulValueLen = sizeof(rsatype);
+ rsaPubKeyTemplate[1].type = CKA_PRIVATE;
+ rsaPubKeyTemplate[1].pValue = &true;
+ rsaPubKeyTemplate[1].ulValueLen = sizeof(true);
+ rsaPubKeyTemplate[2].type = CKA_ENCRYPT;
+ rsaPubKeyTemplate[2].pValue = &true;
+ rsaPubKeyTemplate[2].ulValueLen = sizeof(true);
+ rsaPubKeyTemplate[3].type = CKA_DECRYPT;
+ rsaPubKeyTemplate[3].pValue = &true;
+ rsaPubKeyTemplate[3].ulValueLen = sizeof(true);
+ rsaPubKeyTemplate[4].type = CKA_VERIFY;
+ rsaPubKeyTemplate[4].pValue = &true;
+ rsaPubKeyTemplate[4].ulValueLen = sizeof(true);
+ rsaPubKeyTemplate[5].type = CKA_SIGN;
+ rsaPubKeyTemplate[5].pValue = &true;
+ rsaPubKeyTemplate[5].ulValueLen = sizeof(true);
+ rsaPubKeyTemplate[6].type = CKA_WRAP;
+ rsaPubKeyTemplate[6].pValue = &true;
+ rsaPubKeyTemplate[6].ulValueLen = sizeof(true);
+ rsaPubKeyTemplate[7].type = CKA_MODULUS_BITS;
+ rsaPubKeyTemplate[7].pValue = &modulusBits;
+ rsaPubKeyTemplate[7].ulValueLen = sizeof(modulusBits);
+ rsaPubKeyTemplate[8].type = CKA_PUBLIC_EXPONENT;
+ rsaPubKeyTemplate[8].pValue = publicExponent;
+ rsaPubKeyTemplate[8].ulValueLen = sizeof(publicExponent);
+
+ rsaPrivKeyTemplate[0].type = CKA_KEY_TYPE;
+ rsaPrivKeyTemplate[0].pValue = &rsatype;
+ rsaPrivKeyTemplate[0].ulValueLen = sizeof(rsatype);
+ rsaPrivKeyTemplate[1].type = CKA_TOKEN;
+ rsaPrivKeyTemplate[1].pValue = &true;
+ rsaPrivKeyTemplate[1].ulValueLen = sizeof(true);
+ rsaPrivKeyTemplate[2].type = CKA_PRIVATE;
+ rsaPrivKeyTemplate[2].pValue = &true;
+ rsaPrivKeyTemplate[2].ulValueLen = sizeof(true);
+ rsaPrivKeyTemplate[3].type = CKA_SUBJECT;
+ rsaPrivKeyTemplate[3].pValue = subject;
+ rsaPrivKeyTemplate[3].ulValueLen = sizeof(subject);
+ rsaPrivKeyTemplate[4].type = CKA_ID;
+ rsaPrivKeyTemplate[4].pValue = id;
+ rsaPrivKeyTemplate[4].ulValueLen = sizeof(id);
+ rsaPrivKeyTemplate[5].type = CKA_SENSITIVE;
+ rsaPrivKeyTemplate[5].pValue = &true;
+ rsaPrivKeyTemplate[5].ulValueLen = sizeof(true);
+ rsaPrivKeyTemplate[6].type = CKA_ENCRYPT;
+ rsaPrivKeyTemplate[6].pValue = &true;
+ rsaPrivKeyTemplate[6].ulValueLen = sizeof(true);
+ rsaPrivKeyTemplate[7].type = CKA_DECRYPT;
+ rsaPrivKeyTemplate[7].pValue = &true;
+ rsaPrivKeyTemplate[7].ulValueLen = sizeof(true);
+ rsaPrivKeyTemplate[8].type = CKA_VERIFY;
+ rsaPrivKeyTemplate[8].pValue = &true;
+ rsaPrivKeyTemplate[8].ulValueLen = sizeof(true);
+ rsaPrivKeyTemplate[9].type = CKA_SIGN;
+ rsaPrivKeyTemplate[9].pValue = &true;
+ rsaPrivKeyTemplate[9].ulValueLen = sizeof(true);
+ rsaPrivKeyTemplate[10].type = CKA_UNWRAP;
+ rsaPrivKeyTemplate[10].pValue = &true;
+ rsaPrivKeyTemplate[10].ulValueLen = sizeof(true);
+
+ /* AES key template */
+ sAESKeyTemplate[0].type = CKA_CLASS;
+ sAESKeyTemplate[0].pValue = &class;
+ sAESKeyTemplate[0].ulValueLen = sizeof(class);
+ sAESKeyTemplate[1].type = CKA_KEY_TYPE;
+ sAESKeyTemplate[1].pValue = &keyAESType;
+ sAESKeyTemplate[1].ulValueLen = sizeof(keyAESType);
+ sAESKeyTemplate[2].type = CKA_LABEL;
+ sAESKeyTemplate[2].pValue = AESlabel;
+ sAESKeyTemplate[2].ulValueLen = sizeof(AESlabel) - 1;
+ sAESKeyTemplate[3].type = CKA_ENCRYPT;
+ sAESKeyTemplate[3].pValue = &true;
+ sAESKeyTemplate[3].ulValueLen = sizeof(true);
+ sAESKeyTemplate[4].type = CKA_DECRYPT;
+ sAESKeyTemplate[4].pValue = &true;
+ sAESKeyTemplate[4].ulValueLen = sizeof(true);
+ sAESKeyTemplate[5].type = CKA_SIGN;
+ sAESKeyTemplate[5].pValue = &true;
+ sAESKeyTemplate[5].ulValueLen = sizeof(true);
+ sAESKeyTemplate[6].type = CKA_VERIFY;
+ sAESKeyTemplate[6].pValue = &true;
+ sAESKeyTemplate[6].ulValueLen = sizeof(true);
+ sAESKeyTemplate[7].type = CKA_UNWRAP;
+ sAESKeyTemplate[7].pValue = &true;
+ sAESKeyTemplate[7].ulValueLen = sizeof(true);
+ sAESKeyTemplate[8].type = CKA_VALUE_LEN;
+ sAESKeyTemplate[8].pValue = &AESvalueLen;
+ sAESKeyTemplate[8].ulValueLen = sizeof(AESvalueLen);
+
+ /* DES3 key template */
+ sDES3KeyTemplate[0].type = CKA_CLASS;
+ sDES3KeyTemplate[0].pValue = &class;
+ sDES3KeyTemplate[0].ulValueLen = sizeof(class);
+ sDES3KeyTemplate[1].type = CKA_KEY_TYPE;
+ sDES3KeyTemplate[1].pValue = &keyDES3Type;
+ sDES3KeyTemplate[1].ulValueLen = sizeof(keyDES3Type);
+ sDES3KeyTemplate[2].type = CKA_LABEL;
+ sDES3KeyTemplate[2].pValue = DES3label;
+ sDES3KeyTemplate[2].ulValueLen = sizeof(DES3label) - 1;
+ sDES3KeyTemplate[3].type = CKA_ENCRYPT;
+ sDES3KeyTemplate[3].pValue = &true;
+ sDES3KeyTemplate[3].ulValueLen = sizeof(true);
+ sDES3KeyTemplate[4].type = CKA_DECRYPT;
+ sDES3KeyTemplate[4].pValue = &true;
+ sDES3KeyTemplate[4].ulValueLen = sizeof(true);
+ sDES3KeyTemplate[5].type = CKA_UNWRAP;
+ sDES3KeyTemplate[5].pValue = &true;
+ sDES3KeyTemplate[5].ulValueLen = sizeof(true);
+ sDES3KeyTemplate[6].type = CKA_SIGN,
+ sDES3KeyTemplate[6].pValue = &true;
+ sDES3KeyTemplate[6].ulValueLen = sizeof(true);
+ sDES3KeyTemplate[7].type = CKA_VERIFY;
+ sDES3KeyTemplate[7].pValue = &true;
+ sDES3KeyTemplate[7].ulValueLen = sizeof(true);
+ sDES3KeyTemplate[8].type = CKA_VALUE_LEN;
+ sDES3KeyTemplate[8].pValue = &DES3valueLen;
+ sDES3KeyTemplate[8].ulValueLen = sizeof(DES3valueLen);
+
+ /* mech init */
+ memset(IV, 0x01, sizeof(IV));
+ mech_DES3_CBC.mechanism = CKM_DES3_CBC;
+ mech_DES3_CBC.pParameter = IV;
+ mech_DES3_CBC.ulParameterLen = sizeof(IV);
+ mech_DES3_CBC_PAD.mechanism = CKM_DES3_CBC_PAD;
+ mech_DES3_CBC_PAD.pParameter = IV;
+ mech_DES3_CBC_PAD.ulParameterLen = sizeof(IV);
+ mech_AES_CBC.mechanism = CKM_AES_CBC;
+ mech_AES_CBC.pParameter = IV;
+ mech_AES_CBC.ulParameterLen = sizeof(IV);
+ mech_AES_CBC_PAD.mechanism = CKM_AES_CBC_PAD;
+ mech_AES_CBC_PAD.pParameter = IV;
+ mech_AES_CBC_PAD.ulParameterLen = sizeof(IV);
+
+ crv = pFunctionList->C_OpenSession(pSlotList[slotID],
+ CKF_RW_SESSION | CKF_SERIAL_SESSION,
+ NULL, NULL, &hRwSession);
+ if (crv == CKR_OK) {
+ PKM_LogIt("Opening a read/write session succeeded\n");
+ } else {
+ PKM_Error("Opening a read/write session failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ if (MODE == FIPSMODE) {
+ crv = pFunctionList->C_GenerateKey(hRwSession, &sAESKeyMech,
+ sAESKeyTemplate,
+ NUM_ELEM(sAESKeyTemplate),
+ &hAESSecKey);
+ if (crv == CKR_OK) {
+ PKM_Error("C_GenerateKey succeeded when not logged in.\n");
+ return CKR_GENERAL_ERROR;
+ } else {
+ PKM_LogIt("C_GenerateKey returned as EXPECTED with 0x%08X, %-26s\n"
+ "since not logged in\n",
+ crv, PKM_CK_RVtoStr(crv));
+ }
+ crv = pFunctionList->C_GenerateKeyPair(hRwSession, &rsaKeyPairGenMech,
+ rsaPubKeyTemplate,
+ NUM_ELEM(rsaPubKeyTemplate),
+ rsaPrivKeyTemplate,
+ NUM_ELEM(rsaPrivKeyTemplate),
+ &hRSApubKey, &hRSAprivKey);
+ if (crv == CKR_OK) {
+ PKM_Error("C_GenerateKeyPair succeeded when not logged in.\n");
+ return CKR_GENERAL_ERROR;
+ } else {
+ PKM_LogIt("C_GenerateKeyPair returned as EXPECTED with 0x%08X, "
+ "%-26s\n since not logged in\n",
+ crv,
+ PKM_CK_RVtoStr(crv));
+ }
+ }
+
+ crv = pFunctionList->C_Login(hRwSession, CKU_USER, pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Login with correct password succeeded\n");
+ } else {
+ PKM_Error("C_Login with correct password failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt("Generate an AES key ... \n");
+ /* generate an AES Secret Key */
+ crv = pFunctionList->C_GenerateKey(hRwSession, &sAESKeyMech,
+ sAESKeyTemplate,
+ NUM_ELEM(sAESKeyTemplate),
+ &hAESSecKey);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GenerateKey AES succeeded\n");
+ } else {
+ PKM_Error("C_GenerateKey AES failed with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt("Generate an 3DES key ...\n");
+ /* generate an 3DES Secret Key */
+ crv = pFunctionList->C_GenerateKey(hRwSession, &sDES3KeyGenMechanism,
+ sDES3KeyTemplate,
+ NUM_ELEM(sDES3KeyTemplate),
+ &hDES3SecKey);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GenerateKey DES3 succeeded\n");
+ } else {
+ PKM_Error("C_GenerateKey failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt("Generate DSA PQG domain parameters ... \n");
+ /* Generate DSA domain parameters PQG */
+ crv = pFunctionList->C_GenerateKey(hRwSession, &dsaParamGenMech,
+ dsaParamGenTemplate,
+ 1,
+ &hDsaParams);
+ if (crv == CKR_OK) {
+ PKM_LogIt("DSA domain parameter generation succeeded\n");
+ } else {
+ PKM_Error("DSA domain parameter generation failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_GetAttributeValue(hRwSession, hDsaParams,
+ dsaPubKeyTemplate, 3);
+ if (crv == CKR_OK) {
+ PKM_LogIt("Getting DSA domain parameters succeeded\n");
+ } else {
+ PKM_Error("Getting DSA domain parameters failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_DestroyObject(hRwSession, hDsaParams);
+ if (crv == CKR_OK) {
+ PKM_LogIt("Destroying DSA domain parameters succeeded\n");
+ } else {
+ PKM_Error("Destroying DSA domain parameters failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt("Generate a DSA key pair ... \n");
+ /* Generate a persistent DSA key pair */
+ crv = pFunctionList->C_GenerateKeyPair(hRwSession, &dsaKeyPairGenMech,
+ dsaPubKeyTemplate,
+ NUM_ELEM(dsaPubKeyTemplate),
+ dsaPrivKeyTemplate,
+ NUM_ELEM(dsaPrivKeyTemplate),
+ &hDSApubKey, &hDSAprivKey);
+ if (crv == CKR_OK) {
+ PKM_LogIt("DSA key pair generation succeeded\n");
+ } else {
+ PKM_Error("DSA key pair generation failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt("Generate a RSA key pair ... \n");
+ /*** GEN RSA Key ***/
+ crv = pFunctionList->C_GenerateKeyPair(hRwSession, &rsaKeyPairGenMech,
+ rsaPubKeyTemplate,
+ NUM_ELEM(rsaPubKeyTemplate),
+ rsaPrivKeyTemplate,
+ NUM_ELEM(rsaPrivKeyTemplate),
+ &hRSApubKey, &hRSAprivKey);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GenerateKeyPair created an RSA key pair. \n");
+ } else {
+ PKM_Error("C_GenerateKeyPair failed to create an RSA key pair.\n"
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt("**** Generation of keys completed ***** \n");
+
+ mech.mechanism = CKM_RSA_PKCS;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ crv = PKM_wrapUnwrap(pFunctionList,
+ hRwSession,
+ hRSApubKey, hRSAprivKey,
+ &mech,
+ hAESSecKey,
+ sAESKeyTemplate,
+ NUM_ELEM(sAESKeyTemplate));
+
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_wrapUnwrap using RSA keypair to wrap AES key "
+ "succeeded\n\n");
+ } else {
+ PKM_Error("PKM_wrapUnwrap using RSA keypair to wrap AES key failed "
+ "with 0x%08X, %-26s\n",
+ crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = PKM_wrapUnwrap(pFunctionList,
+ hRwSession,
+ hRSApubKey, hRSAprivKey,
+ &mech,
+ hDES3SecKey,
+ sDES3KeyTemplate,
+ NUM_ELEM(sDES3KeyTemplate));
+
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_wrapUnwrap using RSA keypair to wrap DES3 key "
+ "succeeded\n\n");
+ } else {
+ PKM_Error("PKM_wrapUnwrap using RSA keypair to wrap DES3 key "
+ "failed with 0x%08X, %-26s\n",
+ crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = PKM_SecKeyCrypt(pFunctionList, hRwSession,
+ hAESSecKey, &mech_AES_CBC_PAD,
+ PLAINTEXT_PAD, sizeof(PLAINTEXT_PAD));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_SecKeyCrypt succeeded \n\n");
+ } else {
+ PKM_Error("PKM_SecKeyCrypt failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = PKM_SecKeyCrypt(pFunctionList, hRwSession,
+ hAESSecKey, &mech_AES_CBC,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_SecKeyCrypt AES succeeded \n\n");
+ } else {
+ PKM_Error("PKM_SecKeyCrypt failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = PKM_SecKeyCrypt(pFunctionList, hRwSession,
+ hDES3SecKey, &mech_DES3_CBC,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_SecKeyCrypt DES3 succeeded \n");
+ } else {
+ PKM_Error("PKM_SecKeyCrypt DES3 failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = PKM_SecKeyCrypt(pFunctionList, hRwSession,
+ hDES3SecKey, &mech_DES3_CBC_PAD,
+ PLAINTEXT_PAD, sizeof(PLAINTEXT_PAD));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_SecKeyCrypt DES3 succeeded \n\n");
+ } else {
+ PKM_Error("PKM_SecKeyCrypt DES3 failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ mech.mechanism = CKM_RSA_PKCS;
+ crv = PKM_RecoverFunctions(pFunctionList, hRwSession,
+ hRSApubKey, hRSAprivKey,
+ &mech,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_RecoverFunctions for CKM_RSA_PKCS succeeded\n\n");
+ } else {
+ PKM_Error("PKM_RecoverFunctions failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ for (i = 0; i < sigRSAMechsSZ; i++) {
+
+ mech.mechanism = sigRSAMechs[i].mechanism;
+
+ crv = PKM_PubKeySign(pFunctionList, hRwSession,
+ hRSApubKey, hRSAprivKey,
+ &mech,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_PubKeySign succeeded for %-10s\n\n",
+ sigRSAMechs[i].mechanismStr);
+ } else {
+ PKM_Error("PKM_PubKeySign failed for %-10s "
+ "with 0x%08X, %-26s\n",
+ sigRSAMechs[i].mechanismStr, crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = PKM_DualFuncSign(pFunctionList, hRwSession,
+ hRSApubKey, hRSAprivKey,
+ &mech,
+ hAESSecKey, &mech_AES_CBC,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_DualFuncSign with AES secret key succeeded "
+ "for %-10s\n\n",
+ sigRSAMechs[i].mechanismStr);
+ } else {
+ PKM_Error("PKM_DualFuncSign with AES secret key failed "
+ "for %-10s "
+ "with 0x%08X, %-26s\n",
+ sigRSAMechs[i].mechanismStr, crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = PKM_DualFuncSign(pFunctionList, hRwSession,
+ hRSApubKey, hRSAprivKey,
+ &mech,
+ hDES3SecKey, &mech_DES3_CBC,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_DualFuncSign with DES3 secret key succeeded "
+ "for %-10s\n\n",
+ sigRSAMechs[i].mechanismStr);
+ } else {
+ PKM_Error("PKM_DualFuncSign with DES3 secret key failed "
+ "for %-10s "
+ "with 0x%08X, %-26s\n",
+ sigRSAMechs[i].mechanismStr, crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = PKM_DualFuncSign(pFunctionList, hRwSession,
+ hRSApubKey, hRSAprivKey,
+ &mech,
+ hAESSecKey, &mech_AES_CBC_PAD,
+ PLAINTEXT_PAD, sizeof(PLAINTEXT_PAD));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_DualFuncSign with AES secret key CBC_PAD "
+ "succeeded for %-10s\n\n",
+ sigRSAMechs[i].mechanismStr);
+ } else {
+ PKM_Error("PKM_DualFuncSign with AES secret key CBC_PAD "
+ "failed for %-10s "
+ "with 0x%08X, %-26s\n",
+ sigRSAMechs[i].mechanismStr, crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = PKM_DualFuncSign(pFunctionList, hRwSession,
+ hRSApubKey, hRSAprivKey,
+ &mech,
+ hDES3SecKey, &mech_DES3_CBC_PAD,
+ PLAINTEXT_PAD, sizeof(PLAINTEXT_PAD));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_DualFuncSign with DES3 secret key CBC_PAD "
+ "succeeded for %-10s\n\n",
+ sigRSAMechs[i].mechanismStr);
+ } else {
+ PKM_Error("PKM_DualFuncSign with DES3 secret key CBC_PAD "
+ "failed for %-10s "
+ "with 0x%08X, %-26s\n",
+ sigRSAMechs[i].mechanismStr, crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ } /* end of RSA for loop */
+
+ crv = PKM_PubKeySign(pFunctionList, hRwSession,
+ hDSApubKey, hDSAprivKey,
+ &dsaWithSha1Mech, PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_PubKeySign for DSAwithSHA1 succeeded \n\n");
+ } else {
+ PKM_Error("PKM_PubKeySign failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = PKM_DualFuncSign(pFunctionList, hRwSession,
+ hDSApubKey, hDSAprivKey,
+ &dsaWithSha1Mech,
+ hAESSecKey, &mech_AES_CBC,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_DualFuncSign with AES secret key succeeded "
+ "for DSAWithSHA1\n\n");
+ } else {
+ PKM_Error("PKM_DualFuncSign with AES secret key failed "
+ "for DSAWithSHA1 with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = PKM_DualFuncSign(pFunctionList, hRwSession,
+ hDSApubKey, hDSAprivKey,
+ &dsaWithSha1Mech,
+ hDES3SecKey, &mech_DES3_CBC,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_DualFuncSign with DES3 secret key succeeded "
+ "for DSAWithSHA1\n\n");
+ } else {
+ PKM_Error("PKM_DualFuncSign with DES3 secret key failed "
+ "for DSAWithSHA1 with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = PKM_DualFuncSign(pFunctionList, hRwSession,
+ hDSApubKey, hDSAprivKey,
+ &dsaWithSha1Mech,
+ hAESSecKey, &mech_AES_CBC_PAD,
+ PLAINTEXT_PAD, sizeof(PLAINTEXT_PAD));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_DualFuncSign with AES secret key CBC_PAD succeeded "
+ "for DSAWithSHA1\n\n");
+ } else {
+ PKM_Error("PKM_DualFuncSign with AES secret key CBC_PAD failed "
+ "for DSAWithSHA1 with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = PKM_DualFuncSign(pFunctionList, hRwSession,
+ hDSApubKey, hDSAprivKey,
+ &dsaWithSha1Mech,
+ hDES3SecKey, &mech_DES3_CBC_PAD,
+ PLAINTEXT_PAD, sizeof(PLAINTEXT_PAD));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_DualFuncSign with DES3 secret key CBC_PAD succeeded "
+ "for DSAWithSHA1\n\n");
+ } else {
+ PKM_Error("PKM_DualFuncSign with DES3 secret key CBC_PAD failed "
+ "for DSAWithSHA1 with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ for (i = 0; i < digestMechsSZ; i++) {
+ mech.mechanism = digestMechs[i].mechanism;
+ crv = PKM_Digest(pFunctionList, hRwSession,
+ &mech, hAESSecKey,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_Digest with AES secret key succeeded for %-10s\n\n",
+ digestMechs[i].mechanismStr);
+ } else {
+ PKM_Error("PKM_Digest with AES secret key failed for "
+ "%-10s with 0x%08X, %-26s\n",
+ digestMechs[i].mechanismStr, crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = PKM_DualFuncDigest(pFunctionList, hRwSession,
+ hAESSecKey, &mech_AES_CBC,
+ 0, &mech,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_DualFuncDigest with AES secret key succeeded\n\n");
+ } else {
+ PKM_Error("PKM_DualFuncDigest with AES secret key "
+ "failed with 0x%08X, %-26s\n",
+ crv,
+ PKM_CK_RVtoStr(crv));
+ }
+
+ crv = PKM_Digest(pFunctionList, hRwSession,
+ &mech, hDES3SecKey,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_Digest with DES3 secret key succeeded for %-10s\n\n",
+ digestMechs[i].mechanismStr);
+ } else {
+ PKM_Error("PKM_Digest with DES3 secret key failed for "
+ "%-10s with 0x%08X, %-26s\n",
+ digestMechs[i].mechanismStr, crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = PKM_DualFuncDigest(pFunctionList, hRwSession,
+ hDES3SecKey, &mech_DES3_CBC,
+ 0, &mech,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_DualFuncDigest DES3 secret key succeeded\n\n");
+ } else {
+ PKM_Error("PKM_DualFuncDigest DES3 secret key "
+ "failed with 0x%08X, %-26s\n",
+ crv,
+ PKM_CK_RVtoStr(crv));
+ }
+
+ crv = PKM_Digest(pFunctionList, hRwSession,
+ &mech, 0,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_Digest with no secret key succeeded for %-10s\n\n",
+ digestMechs[i].mechanismStr);
+ } else {
+ PKM_Error("PKM_Digest with no secret key failed for %-10s "
+ "with 0x%08X, %-26s\n",
+ digestMechs[i].mechanismStr, crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ } /* end of digest loop */
+
+ for (i = 0; i < hmacMechsSZ; i++) {
+ mech.mechanism = hmacMechs[i].mechanism;
+ crv = PKM_Hmac(pFunctionList, hRwSession,
+ hAESSecKey, &mech,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_Hmac with AES secret key succeeded for %-10s\n\n",
+ hmacMechs[i].mechanismStr);
+ } else {
+ PKM_Error("PKM_Hmac with AES secret key failed for %-10s "
+ "with 0x%08X, %-26s\n",
+ hmacMechs[i].mechanismStr, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ if ((MODE == FIPSMODE) && (mech.mechanism == CKM_SHA512_HMAC))
+ break;
+ crv = PKM_Hmac(pFunctionList, hRwSession,
+ hDES3SecKey, &mech,
+ PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_Hmac with DES3 secret key succeeded for %-10s\n\n",
+ hmacMechs[i].mechanismStr);
+ } else {
+ PKM_Error("PKM_Hmac with DES3 secret key failed for %-10s "
+ "with 0x%08X, %-26s\n",
+ hmacMechs[i].mechanismStr, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ } /* end of hmac loop */
+
+ crv = pFunctionList->C_Logout(hRwSession);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Logout succeeded\n");
+ } else {
+ PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_CloseSession(hRwSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ return crv;
+}
+
+void
+PKM_LogIt(const char *fmt, ...)
+{
+ va_list args;
+
+ if (verbose) {
+ va_start(args, fmt);
+ if (MODE == FIPSMODE) {
+ printf("FIPS MODE: ");
+ } else if (MODE == NONFIPSMODE) {
+ printf("NON FIPS MODE: ");
+ } else if (MODE == HYBRIDMODE) {
+ printf("Hybrid MODE: ");
+ }
+ vprintf(fmt, args);
+ va_end(args);
+ }
+}
+
+void
+PKM_Error(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ if (MODE == FIPSMODE) {
+ fprintf(stderr, "\nFIPS MODE PKM_Error: ");
+ } else if (MODE == NONFIPSMODE) {
+ fprintf(stderr, "NON FIPS MODE PKM_Error: ");
+ } else if (MODE == HYBRIDMODE) {
+ fprintf(stderr, "Hybrid MODE PKM_Error: ");
+ } else
+ fprintf(stderr, "NOMODE PKM_Error: ");
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+}
+CK_SLOT_ID *
+PKM_GetSlotList(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_ULONG slotID)
+{
+ CK_RV crv = CKR_OK;
+ CK_SLOT_ID *pSlotList = NULL;
+ CK_ULONG slotCount;
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ /* Get slot list */
+ crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */,
+ NULL, &slotCount);
+ if (crv != CKR_OK) {
+ PKM_Error("C_GetSlotList failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return NULL;
+ }
+ PKM_LogIt("C_GetSlotList reported there are %lu slots\n", slotCount);
+ pSlotList = (CK_SLOT_ID *)malloc(slotCount * sizeof(CK_SLOT_ID));
+ if (!pSlotList) {
+ PKM_Error("failed to allocate slot list\n");
+ return NULL;
+ }
+ crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */,
+ pSlotList, &slotCount);
+ if (crv != CKR_OK) {
+ PKM_Error("C_GetSlotList failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ if (pSlotList)
+ free(pSlotList);
+ return NULL;
+ }
+ return pSlotList;
+}
+
+CK_RV
+PKM_InitPWforDB(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
+{
+ CK_RV crv = CKR_OK;
+ CK_SESSION_HANDLE hSession;
+ static const CK_UTF8CHAR testPin[] = { "0Mozilla" };
+ static const CK_UTF8CHAR weakPin[] = { "mozilla" };
+
+ crv = pFunctionList->C_OpenSession(pSlotList[slotID],
+ CKF_RW_SESSION | CKF_SERIAL_SESSION,
+ NULL, NULL, &hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ PKM_LogIt("CKU_USER 0x%08X \n", CKU_USER);
+
+ crv = pFunctionList->C_Login(hSession, CKU_SO, NULL, 0);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Login failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ if (MODE == FIPSMODE) {
+ crv = pFunctionList->C_InitPIN(hSession, (CK_UTF8CHAR *)weakPin,
+ strlen((char *)weakPin));
+ if (crv == CKR_OK) {
+ PKM_Error("C_InitPIN with a weak password succeeded\n");
+ return crv;
+ } else {
+ PKM_LogIt("C_InitPIN with a weak password failed with "
+ "0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ }
+ }
+ crv = pFunctionList->C_InitPIN(hSession, (CK_UTF8CHAR *)testPin,
+ strlen((char *)testPin));
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_InitPIN succeeded\n");
+ } else {
+ PKM_Error("C_InitPIN failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_Logout(hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_CloseSession(hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_OpenSession(pSlotList[slotID],
+ CKF_RW_SESSION | CKF_SERIAL_SESSION,
+ NULL, NULL, &hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt("CKU_USER 0x%08X \n", CKU_USER);
+
+ crv = pFunctionList->C_Login(hSession, CKU_USER, (CK_UTF8CHAR *)testPin,
+ strlen((const char *)testPin));
+ if (crv != CKR_OK) {
+ PKM_Error("C_Login failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ if (MODE == FIPSMODE) {
+ crv = pFunctionList->C_SetPIN(
+ hSession, (CK_UTF8CHAR *)testPin,
+ strlen((const char *)testPin),
+ (CK_UTF8CHAR *)weakPin,
+ strlen((const char *)weakPin));
+ if (crv == CKR_OK) {
+ PKM_Error("C_SetPIN with a weak password succeeded\n");
+ return crv;
+ } else {
+ PKM_LogIt("C_SetPIN with a weak password returned with "
+ "0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ }
+ }
+ crv = pFunctionList->C_SetPIN(
+ hSession, (CK_UTF8CHAR *)testPin,
+ strlen((const char *)testPin),
+ pwd, pwdLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_CSetPin failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_Logout(hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_CloseSession(hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ return crv;
+}
+
+CK_RV
+PKM_ShowInfo(CK_FUNCTION_LIST_PTR pFunctionList, CK_ULONG slotID)
+{
+ CK_RV crv = CKR_OK;
+ CK_INFO info;
+ CK_SLOT_ID *pSlotList = NULL;
+ unsigned i;
+
+ CK_SLOT_INFO slotInfo;
+ CK_TOKEN_INFO tokenInfo;
+ CK_FLAGS bitflag;
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ crv = pFunctionList->C_GetInfo(&info);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GetInfo succeeded\n");
+ } else {
+ PKM_Error("C_GetInfo failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ PKM_LogIt("General information about the PKCS #11 library:\n");
+ PKM_LogIt(" PKCS #11 version: %d.%d\n",
+ (int)info.cryptokiVersion.major,
+ (int)info.cryptokiVersion.minor);
+ PKM_LogIt(" manufacturer ID: %.32s\n", info.manufacturerID);
+ PKM_LogIt(" flags: 0x%08lX\n", info.flags);
+ PKM_LogIt(" library description: %.32s\n", info.libraryDescription);
+ PKM_LogIt(" library version: %d.%d\n",
+ (int)info.libraryVersion.major, (int)info.libraryVersion.minor);
+ PKM_LogIt("\n");
+
+ /* Get slot list */
+ pSlotList = PKM_GetSlotList(pFunctionList, slotID);
+ if (pSlotList == NULL) {
+ PKM_Error("PKM_GetSlotList failed with \n");
+ return crv;
+ }
+ crv = pFunctionList->C_GetSlotInfo(pSlotList[slotID], &slotInfo);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GetSlotInfo succeeded\n");
+ } else {
+ PKM_Error("C_GetSlotInfo failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ PKM_LogIt("Information about slot %lu:\n", pSlotList[slotID]);
+ PKM_LogIt(" slot description: %.64s\n", slotInfo.slotDescription);
+ PKM_LogIt(" slot manufacturer ID: %.32s\n", slotInfo.manufacturerID);
+ PKM_LogIt(" flags: 0x%08lX\n", slotInfo.flags);
+ bitflag = 1;
+ for (i = 0; i < sizeof(slotFlagName) / sizeof(slotFlagName[0]); i++) {
+ if (slotInfo.flags & bitflag) {
+ PKM_LogIt(" %s\n", slotFlagName[i]);
+ }
+ bitflag <<= 1;
+ }
+ PKM_LogIt(" slot's hardware version number: %d.%d\n",
+ (int)slotInfo.hardwareVersion.major,
+ (int)slotInfo.hardwareVersion.minor);
+ PKM_LogIt(" slot's firmware version number: %d.%d\n",
+ (int)slotInfo.firmwareVersion.major,
+ (int)slotInfo.firmwareVersion.minor);
+ PKM_LogIt("\n");
+
+ crv = pFunctionList->C_GetTokenInfo(pSlotList[slotID], &tokenInfo);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GetTokenInfo succeeded\n");
+ } else {
+ PKM_Error("C_GetTokenInfo failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ PKM_LogIt("Information about the token in slot %lu:\n",
+ pSlotList[slotID]);
+ PKM_LogIt(" label: %.32s\n", tokenInfo.label);
+ PKM_LogIt(" device manufacturer ID: %.32s\n",
+ tokenInfo.manufacturerID);
+ PKM_LogIt(" device model: %.16s\n", tokenInfo.model);
+ PKM_LogIt(" device serial number: %.16s\n", tokenInfo.serialNumber);
+ PKM_LogIt(" flags: 0x%08lX\n", tokenInfo.flags);
+ bitflag = 1;
+ for (i = 0; i < sizeof(tokenFlagName) / sizeof(tokenFlagName[0]); i++) {
+ if (tokenInfo.flags & bitflag) {
+ PKM_LogIt(" %s\n", tokenFlagName[i]);
+ }
+ bitflag <<= 1;
+ }
+ PKM_LogIt(" maximum session count: %lu\n",
+ tokenInfo.ulMaxSessionCount);
+ PKM_LogIt(" session count: %lu\n", tokenInfo.ulSessionCount);
+ PKM_LogIt(" maximum read/write session count: %lu\n",
+ tokenInfo.ulMaxRwSessionCount);
+ PKM_LogIt(" read/write session count: %lu\n",
+ tokenInfo.ulRwSessionCount);
+ PKM_LogIt(" maximum PIN length: %lu\n", tokenInfo.ulMaxPinLen);
+ PKM_LogIt(" minimum PIN length: %lu\n", tokenInfo.ulMinPinLen);
+ PKM_LogIt(" total public memory: %lu\n",
+ tokenInfo.ulTotalPublicMemory);
+ PKM_LogIt(" free public memory: %lu\n",
+ tokenInfo.ulFreePublicMemory);
+ PKM_LogIt(" total private memory: %lu\n",
+ tokenInfo.ulTotalPrivateMemory);
+ PKM_LogIt(" free private memory: %lu\n",
+ tokenInfo.ulFreePrivateMemory);
+ PKM_LogIt(" hardware version number: %d.%d\n",
+ (int)tokenInfo.hardwareVersion.major,
+ (int)tokenInfo.hardwareVersion.minor);
+ PKM_LogIt(" firmware version number: %d.%d\n",
+ (int)tokenInfo.firmwareVersion.major,
+ (int)tokenInfo.firmwareVersion.minor);
+ if (tokenInfo.flags & CKF_CLOCK_ON_TOKEN) {
+ PKM_LogIt(" current time: %.16s\n", tokenInfo.utcTime);
+ }
+ PKM_LogIt("PKM_ShowInfo done \n\n");
+ free(pSlotList);
+ return crv;
+}
+
+/* PKM_HybridMode */
+/* The NSS cryptographic module has two modes of operation: FIPS Approved */
+/* mode and NONFIPS Approved mode. The two modes of operation are */
+/* independent of each other -- they have their own copies of data */
+/* structures and they are even allowed to be active at the same time. */
+/* The module is FIPS 140-2 compliant only when the NONFIPS mode */
+/* is inactive. */
+/* PKM_HybridMode demostrates how an application can switch between the */
+/* two modes: FIPS Approved mode and NONFIPS mode. */
+CK_RV
+PKM_HybridMode(CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen,
+ CK_C_INITIALIZE_ARGS_NSS *initArgs)
+{
+
+ CK_C_GetFunctionList pC_GetFunctionList; /* NONFIPSMode */
+ CK_FUNCTION_LIST_PTR pC_FunctionList;
+ CK_SLOT_ID *pC_SlotList = NULL;
+ CK_ULONG slotID_C = 1;
+ CK_C_GetFunctionList pFC_GetFunctionList; /* FIPSMode */
+ CK_FUNCTION_LIST_PTR pFC_FunctionList;
+ CK_SLOT_ID *pFC_SlotList = NULL;
+ CK_ULONG slotID_FC = 0;
+ CK_RV crv = CKR_OK;
+ CK_SESSION_HANDLE hSession;
+ int origMode = MODE; /* remember the orginal MODE value */
+
+ NUMTESTS++; /* increment NUMTESTS */
+ MODE = NONFIPSMODE;
+#ifdef _WIN32
+ /* NON FIPS mode == C_GetFunctionList */
+ pC_GetFunctionList = (CK_C_GetFunctionList)
+ GetProcAddress(hModule, "C_GetFunctionList");
+ if (pC_GetFunctionList == NULL) {
+ PKM_Error("cannot load %s\n", LIB_NAME);
+ return crv;
+ }
+#else
+ pC_GetFunctionList = (CK_C_GetFunctionList)PR_FindFunctionSymbol(lib,
+ "C_GetFunctionList");
+ assert(pC_GetFunctionList != NULL);
+#endif
+ PKM_LogIt("loading C_GetFunctionList for Non FIPS Mode; slotID %d \n",
+ slotID_C);
+ crv = (*pC_GetFunctionList)(&pC_FunctionList);
+ assert(crv == CKR_OK);
+
+ /* invoke C_Initialize as pC_FunctionList->C_Initialize */
+ crv = pC_FunctionList->C_Initialize(initArgs);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Initialize succeeded\n");
+ } else {
+ PKM_Error("C_Initialize failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ pC_SlotList = PKM_GetSlotList(pC_FunctionList, slotID_C);
+ if (pC_SlotList == NULL) {
+ PKM_Error("PKM_GetSlotList failed with \n");
+ return crv;
+ }
+ crv = pC_FunctionList->C_OpenSession(pC_SlotList[slotID_C],
+ CKF_SERIAL_SESSION,
+ NULL, NULL, &hSession);
+ if (crv == CKR_OK) {
+ PKM_LogIt("NONFIPS C_OpenSession succeeded\n");
+ } else {
+ PKM_Error("C_OpenSession failed for NONFIPS token "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pC_FunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("able to login in NONFIPS token\n");
+ } else {
+ PKM_Error("Unable to login in to NONFIPS token "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pC_FunctionList->C_Logout(hSession);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Logout succeeded\n");
+ } else {
+ PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_ShowInfo(pC_FunctionList, slotID_C);
+ MODE = HYBRIDMODE;
+
+ /* Now load the FIPS token */
+ /* FIPS mode == FC_GetFunctionList */
+ pFC_GetFunctionList = NULL;
+#ifdef _WIN32
+ pFC_GetFunctionList = (CK_C_GetFunctionList)
+ GetProcAddress(hModule, "FC_GetFunctionList");
+#else
+ pFC_GetFunctionList = (CK_C_GetFunctionList)PR_FindFunctionSymbol(lib,
+ "FC_GetFunctionList");
+ assert(pFC_GetFunctionList != NULL);
+#endif
+
+ PKM_LogIt("loading FC_GetFunctionList for FIPS Mode; slotID %d \n",
+ slotID_FC);
+ PKM_LogIt("pFC_FunctionList->C_Foo == pFC_FunctionList->FC_Foo\n");
+ if (pFC_GetFunctionList == NULL) {
+ PKM_Error("unable to load pFC_GetFunctionList\n");
+ return crv;
+ }
+
+ crv = (*pFC_GetFunctionList)(&pFC_FunctionList);
+ assert(crv == CKR_OK);
+
+ /* invoke FC_Initialize as pFunctionList->C_Initialize */
+ crv = pFC_FunctionList->C_Initialize(initArgs);
+ if (crv == CKR_OK) {
+ PKM_LogIt("FC_Initialize succeeded\n");
+ } else {
+ PKM_Error("FC_Initialize failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ PKM_ShowInfo(pFC_FunctionList, slotID_FC);
+
+ pFC_SlotList = PKM_GetSlotList(pFC_FunctionList, slotID_FC);
+ if (pFC_SlotList == NULL) {
+ PKM_Error("PKM_GetSlotList failed with \n");
+ return crv;
+ }
+
+ crv = pC_FunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
+ if (crv != CKR_OK) {
+ PKM_LogIt("NONFIPS token cannot log in when FIPS token is loaded\n");
+ } else {
+ PKM_Error("Able to login in to NONFIPS token\n");
+ return crv;
+ }
+ crv = pC_FunctionList->C_CloseSession(hSession);
+ if (crv == CKR_OK) {
+ PKM_LogIt("NONFIPS pC_CloseSession succeeded\n");
+ } else {
+ PKM_Error("pC_CloseSession failed for NONFIPS token "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt("The module is FIPS 140-2 compliant\n"
+ "only when the NONFIPS Approved mode is inactive by \n"
+ "calling C_Finalize on the NONFIPS token.\n");
+
+ /* to go in FIPSMODE you must Finalize the NONFIPS mode pointer */
+ crv = pC_FunctionList->C_Finalize(NULL);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Finalize of NONFIPS Token succeeded\n");
+ MODE = FIPSMODE;
+ } else {
+ PKM_Error("C_Finalize of NONFIPS Token failed with "
+ "0x%08X, %-26s\n",
+ crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt("*** In FIPS mode! ***\n");
+
+ /* could do some operations in FIPS MODE */
+
+ crv = pFC_FunctionList->C_Finalize(NULL);
+ if (crv == CKR_OK) {
+ PKM_LogIt("Exiting FIPSMODE by caling FC_Finalize.\n");
+ MODE = NOMODE;
+ } else {
+ PKM_Error("FC_Finalize failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ if (pC_SlotList)
+ free(pC_SlotList);
+ if (pFC_SlotList)
+ free(pFC_SlotList);
+
+ MODE = origMode; /* set the mode back to the orginal Mode value */
+ PKM_LogIt("PKM_HybridMode test Completed\n\n");
+ return crv;
+}
+
+CK_RV
+PKM_Mechanism(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID)
+{
+
+ CK_RV crv = CKR_OK;
+ CK_MECHANISM_TYPE *pMechanismList;
+ CK_ULONG mechanismCount;
+ CK_ULONG i;
+ const char *mechName = NULL;
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ /* Get the mechanism list */
+ crv = pFunctionList->C_GetMechanismList(pSlotList[slotID],
+ NULL, &mechanismCount);
+ if (crv != CKR_OK) {
+ PKM_Error("C_GetMechanismList failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ PKM_LogIt("C_GetMechanismList reported there are %lu mechanisms\n",
+ mechanismCount);
+ pMechanismList = (CK_MECHANISM_TYPE *)
+ malloc(mechanismCount * sizeof(CK_MECHANISM_TYPE));
+ if (!pMechanismList) {
+ PKM_Error("failed to allocate mechanism list\n");
+ return crv;
+ }
+ crv = pFunctionList->C_GetMechanismList(pSlotList[slotID],
+ pMechanismList, &mechanismCount);
+ if (crv != CKR_OK) {
+ PKM_Error("C_GetMechanismList failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ PKM_LogIt("C_GetMechanismList returned the mechanism types:\n");
+ if (verbose) {
+ for (i = 0; i < mechanismCount; i++) {
+ mechName = getName(pMechanismList[(i)], ConstMechanism);
+
+ /* output two mechanism name on each line */
+ /* currently the longest known mechansim name length is 37 */
+ if (mechName) {
+ printf("%-40s", mechName);
+ } else {
+ printf("Unknown mechanism: 0x%08lX ", pMechanismList[i]);
+ }
+ if ((i % 2) == 1)
+ printf("\n");
+ }
+ printf("\n\n");
+ }
+
+ for (i = 0; i < mechanismCount; i++) {
+ CK_MECHANISM_INFO minfo;
+
+ memset(&minfo, 0, sizeof(CK_MECHANISM_INFO));
+ crv = pFunctionList->C_GetMechanismInfo(pSlotList[slotID],
+ pMechanismList[i], &minfo);
+ if (CKR_OK != crv) {
+ PKM_Error("C_GetMechanismInfo(%lu, %lu) returned 0x%08X, %-26s\n",
+ pSlotList[slotID], pMechanismList[i], crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ mechName = getName(pMechanismList[i], ConstMechanism);
+ if (!mechName)
+ mechName = "Unknown mechanism";
+ PKM_LogIt(" [%lu]: CK_MECHANISM_TYPE = %s 0x%08lX\n", (i + 1),
+ mechName,
+ pMechanismList[i]);
+ PKM_LogIt(" ulMinKeySize = %lu\n", minfo.ulMinKeySize);
+ PKM_LogIt(" ulMaxKeySize = %lu\n", minfo.ulMaxKeySize);
+ PKM_LogIt(" flags = 0x%08x\n", minfo.flags);
+ PKM_LogIt(" -> HW = %s\n", minfo.flags & CKF_HW ? "TRUE"
+ : "FALSE");
+ PKM_LogIt(" -> ENCRYPT = %s\n", minfo.flags & CKF_ENCRYPT ? "TRUE"
+ : "FALSE");
+ PKM_LogIt(" -> DECRYPT = %s\n", minfo.flags & CKF_DECRYPT ? "TRUE"
+ : "FALSE");
+ PKM_LogIt(" -> DIGEST = %s\n", minfo.flags & CKF_DIGEST ? "TRUE"
+ : "FALSE");
+ PKM_LogIt(" -> SIGN = %s\n", minfo.flags & CKF_SIGN ? "TRUE"
+ : "FALSE");
+ PKM_LogIt(" -> SIGN_RECOVER = %s\n", minfo.flags &
+ CKF_SIGN_RECOVER
+ ? "TRUE"
+ : "FALSE");
+ PKM_LogIt(" -> VERIFY = %s\n", minfo.flags & CKF_VERIFY ? "TRUE"
+ : "FALSE");
+ PKM_LogIt(" -> VERIFY_RECOVER = %s\n",
+ minfo.flags & CKF_VERIFY_RECOVER ? "TRUE" : "FALSE");
+ PKM_LogIt(" -> GENERATE = %s\n", minfo.flags & CKF_GENERATE ? "TRUE"
+ : "FALSE");
+ PKM_LogIt(" -> GENERATE_KEY_PAIR = %s\n",
+ minfo.flags & CKF_GENERATE_KEY_PAIR ? "TRUE" : "FALSE");
+ PKM_LogIt(" -> WRAP = %s\n", minfo.flags & CKF_WRAP ? "TRUE"
+ : "FALSE");
+ PKM_LogIt(" -> UNWRAP = %s\n", minfo.flags & CKF_UNWRAP ? "TRUE"
+ : "FALSE");
+ PKM_LogIt(" -> DERIVE = %s\n", minfo.flags & CKF_DERIVE ? "TRUE"
+ : "FALSE");
+ PKM_LogIt(" -> EXTENSION = %s\n", minfo.flags & CKF_EXTENSION ? "TRUE"
+ : "FALSE");
+
+ PKM_LogIt("\n");
+ }
+
+ return crv;
+}
+
+CK_RV
+PKM_RNG(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID *pSlotList,
+ CK_ULONG slotID)
+{
+ CK_SESSION_HANDLE hSession;
+ CK_RV crv = CKR_OK;
+ CK_BYTE randomData[16];
+ CK_BYTE seed[] = { 0x01, 0x03, 0x35, 0x55, 0xFF };
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
+ NULL, NULL, &hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_GenerateRandom(hSession,
+ randomData, sizeof randomData);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GenerateRandom without login succeeded\n");
+ } else {
+ PKM_Error("C_GenerateRandom without login failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_SeedRandom(hSession, seed, sizeof(seed));
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_SeedRandom without login succeeded\n");
+ } else {
+ PKM_Error("C_SeedRandom without login failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_GenerateRandom(hSession,
+ randomData, sizeof randomData);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GenerateRandom without login succeeded\n");
+ } else {
+ PKM_Error("C_GenerateRandom without login failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_CloseSession(hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ return crv;
+}
+
+CK_RV
+PKM_SessionLogin(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
+{
+ CK_SESSION_HANDLE hSession;
+ CK_RV crv = CKR_OK;
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
+ NULL, NULL, &hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_Login(hSession, CKU_USER, (unsigned char *)"netscape", 8);
+ if (crv == CKR_OK) {
+ PKM_Error("C_Login with wrong password succeeded\n");
+ return CKR_FUNCTION_FAILED;
+ } else {
+ PKM_LogIt("As expected C_Login with wrong password returned 0x%08X, "
+ "%-26s.\n ",
+ crv, PKM_CK_RVtoStr(crv));
+ }
+ crv = pFunctionList->C_Login(hSession, CKU_USER, (unsigned char *)"red hat", 7);
+ if (crv == CKR_OK) {
+ PKM_Error("C_Login with wrong password succeeded\n");
+ return CKR_FUNCTION_FAILED;
+ } else {
+ PKM_LogIt("As expected C_Login with wrong password returned 0x%08X, "
+ "%-26s.\n ",
+ crv, PKM_CK_RVtoStr(crv));
+ }
+ crv = pFunctionList->C_Login(hSession, CKU_USER,
+ (unsigned char *)"sun", 3);
+ if (crv == CKR_OK) {
+ PKM_Error("C_Login with wrong password succeeded\n");
+ return CKR_FUNCTION_FAILED;
+ } else {
+ PKM_LogIt("As expected C_Login with wrong password returned 0x%08X, "
+ "%-26s.\n ",
+ crv, PKM_CK_RVtoStr(crv));
+ }
+ crv = pFunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Login with correct password succeeded\n");
+ } else {
+ PKM_Error("C_Login with correct password failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_Logout(hSession);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Logout succeeded\n");
+ } else {
+ PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_CloseSession(hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ return crv;
+}
+
+/*
+* PKM_LegacyFunctions
+*
+* Legacyfunctions exist only for backwards compatibility.
+* C_GetFunctionStatus and C_CancelFunction functions were
+* meant for managing parallel execution of cryptographic functions.
+*
+* C_GetFunctionStatus is a legacy function which should simply return
+* the value CKR_FUNCTION_NOT_PARALLEL.
+*
+* C_CancelFunction is a legacy function which should simply return the
+* value CKR_FUNCTION_NOT_PARALLEL.
+*
+*/
+CK_RV
+PKM_LegacyFunctions(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
+{
+ CK_SESSION_HANDLE hSession;
+ CK_RV crv = CKR_OK;
+ NUMTESTS++; /* increment NUMTESTS */
+
+ crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
+ NULL, NULL, &hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Login with correct password succeeded\n");
+ } else {
+ PKM_Error("C_Login with correct password failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_GetFunctionStatus(hSession);
+ if (crv == CKR_FUNCTION_NOT_PARALLEL) {
+ PKM_LogIt("C_GetFunctionStatus correctly"
+ "returned CKR_FUNCTION_NOT_PARALLEL \n");
+ } else {
+ PKM_Error("C_GetFunctionStatus failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_CancelFunction(hSession);
+ if (crv == CKR_FUNCTION_NOT_PARALLEL) {
+ PKM_LogIt("C_CancelFunction correctly "
+ "returned CKR_FUNCTION_NOT_PARALLEL \n");
+ } else {
+ PKM_Error("C_CancelFunction failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_Logout(hSession);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Logout succeeded\n");
+ } else {
+ PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_CloseSession(hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ return crv;
+}
+
+/*
+* PKM_DualFuncDigest - demostrates the Dual-function
+* cryptograpic functions:
+*
+* C_DigestEncryptUpdate - multi-part Digest and Encrypt
+* C_DecryptDigestUpdate - multi-part Decrypt and Digest
+*
+*
+*/
+
+CK_RV
+PKM_DualFuncDigest(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hSecKey, CK_MECHANISM *cryptMech,
+ CK_OBJECT_HANDLE hSecKeyDigest,
+ CK_MECHANISM *digestMech,
+ const CK_BYTE *pData, CK_ULONG pDataLen)
+{
+ CK_RV crv = CKR_OK;
+ CK_BYTE eDigest[MAX_DIGEST_SZ];
+ CK_BYTE dDigest[MAX_DIGEST_SZ];
+ CK_ULONG ulDigestLen;
+ CK_BYTE ciphertext[MAX_CIPHER_SZ];
+ CK_ULONG ciphertextLen, lastLen;
+ CK_BYTE plaintext[MAX_DATA_SZ];
+ CK_ULONG plaintextLen;
+ unsigned int i;
+
+ memset(eDigest, 0, sizeof(eDigest));
+ memset(dDigest, 0, sizeof(dDigest));
+ memset(ciphertext, 0, sizeof(ciphertext));
+ memset(plaintext, 0, sizeof(plaintext));
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ /*
+ * First init the Digest and Ecrypt operations
+ */
+ crv = pFunctionList->C_EncryptInit(hSession, cryptMech, hSecKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_EncryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_DigestInit(hSession, digestMech);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ ciphertextLen = sizeof(ciphertext);
+ crv = pFunctionList->C_DigestEncryptUpdate(hSession, (CK_BYTE *)pData,
+ pDataLen,
+ ciphertext, &ciphertextLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestEncryptUpdate failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ ulDigestLen = sizeof(eDigest);
+ crv = pFunctionList->C_DigestFinal(hSession, eDigest, &ulDigestLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* get the last piece of ciphertext (length should be 0 */
+ lastLen = sizeof(ciphertext) - ciphertextLen;
+ crv = pFunctionList->C_EncryptFinal(hSession,
+ (CK_BYTE *)&ciphertext[ciphertextLen],
+ &lastLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_EncryptFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ ciphertextLen = ciphertextLen + lastLen;
+ if (verbose) {
+ printf("ciphertext = ");
+ for (i = 0; i < ciphertextLen; i++) {
+ printf("%02x", (unsigned)ciphertext[i]);
+ }
+ printf("\n");
+ printf("eDigest = ");
+ for (i = 0; i < ulDigestLen; i++) {
+ printf("%02x", (unsigned)eDigest[i]);
+ }
+ printf("\n");
+ }
+
+ /* Decrypt the text */
+ crv = pFunctionList->C_DecryptInit(hSession, cryptMech, hSecKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_DigestInit(hSession, digestMech);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ plaintextLen = sizeof(plaintext);
+ crv = pFunctionList->C_DecryptDigestUpdate(hSession, ciphertext,
+ ciphertextLen,
+ plaintext,
+ &plaintextLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptDigestUpdate failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ lastLen = sizeof(plaintext) - plaintextLen;
+
+ crv = pFunctionList->C_DecryptFinal(hSession,
+ (CK_BYTE *)&plaintext[plaintextLen],
+ &lastLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ plaintextLen = plaintextLen + lastLen;
+
+ ulDigestLen = sizeof(dDigest);
+ crv = pFunctionList->C_DigestFinal(hSession, dDigest, &ulDigestLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ if (plaintextLen != pDataLen) {
+ PKM_Error("plaintextLen is %lu\n", plaintextLen);
+ return crv;
+ }
+
+ if (verbose) {
+ printf("plaintext = ");
+ for (i = 0; i < plaintextLen; i++) {
+ printf("%02x", (unsigned)plaintext[i]);
+ }
+ printf("\n");
+ printf("dDigest = ");
+ for (i = 0; i < ulDigestLen; i++) {
+ printf("%02x", (unsigned)dDigest[i]);
+ }
+ printf("\n");
+ }
+
+ if (memcmp(eDigest, dDigest, ulDigestLen) == 0) {
+ PKM_LogIt("Encrypted Digest equals Decrypted Digest\n");
+ } else {
+ PKM_Error("Digests don't match\n");
+ }
+
+ if ((plaintextLen == pDataLen) &&
+ (memcmp(plaintext, pData, pDataLen)) == 0) {
+ PKM_LogIt("DualFuncDigest decrypt test case passed\n");
+ } else {
+ PKM_Error("DualFuncDigest derypt test case failed\n");
+ }
+
+ return crv;
+}
+
+/*
+* PKM_SecKeyCrypt - Symmetric key encrypt/decyprt
+*
+*/
+
+CK_RV
+PKM_SecKeyCrypt(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hSymKey, CK_MECHANISM *cryptMech,
+ const CK_BYTE *pData, CK_ULONG dataLen)
+{
+ CK_RV crv = CKR_OK;
+
+ CK_BYTE cipher1[MAX_CIPHER_SZ];
+ CK_BYTE cipher2[MAX_CIPHER_SZ];
+ CK_BYTE data1[MAX_DATA_SZ];
+ CK_BYTE data2[MAX_DATA_SZ];
+ CK_ULONG cipher1Len = 0, cipher2Len = 0, lastLen = 0;
+ CK_ULONG data1Len = 0, data2Len = 0;
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ memset(cipher1, 0, sizeof(cipher1));
+ memset(cipher2, 0, sizeof(cipher2));
+ memset(data1, 0, sizeof(data1));
+ memset(data2, 0, sizeof(data2));
+
+ /* C_Encrypt */
+ crv = pFunctionList->C_EncryptInit(hSession, cryptMech, hSymKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_EncryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ cipher1Len = sizeof(cipher1);
+ crv = pFunctionList->C_Encrypt(hSession, (CK_BYTE *)pData, dataLen,
+ cipher1, &cipher1Len);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Encrypt failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* C_EncryptUpdate */
+ crv = pFunctionList->C_EncryptInit(hSession, cryptMech, hSymKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_EncryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ cipher2Len = sizeof(cipher2);
+ crv = pFunctionList->C_EncryptUpdate(hSession, (CK_BYTE *)pData,
+ dataLen,
+ cipher2, &cipher2Len);
+ if (crv != CKR_OK) {
+ PKM_Error("C_EncryptUpdate failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ lastLen = sizeof(cipher2) - cipher2Len;
+
+ crv = pFunctionList->C_EncryptFinal(hSession,
+ (CK_BYTE *)&cipher2[cipher2Len],
+ &lastLen);
+ cipher2Len = cipher2Len + lastLen;
+
+ if ((cipher1Len == cipher2Len) &&
+ (memcmp(cipher1, cipher2, sizeof(cipher1Len)) == 0)) {
+ PKM_LogIt("encrypt test case passed\n");
+ } else {
+ PKM_Error("encrypt test case failed\n");
+ return CKR_GENERAL_ERROR;
+ }
+
+ /* C_Decrypt */
+ crv = pFunctionList->C_DecryptInit(hSession, cryptMech, hSymKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ data1Len = sizeof(data1);
+ crv = pFunctionList->C_Decrypt(hSession, cipher1, cipher1Len,
+ data1, &data1Len);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ /* now use C_DecryptUpdate the text */
+ crv = pFunctionList->C_DecryptInit(hSession, cryptMech, hSymKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ data2Len = sizeof(data2);
+ crv = pFunctionList->C_DecryptUpdate(hSession, cipher2,
+ cipher2Len,
+ data2, &data2Len);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptUpdate failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ lastLen = sizeof(data2) - data2Len;
+ crv = pFunctionList->C_DecryptFinal(hSession,
+ (CK_BYTE *)&data2[data2Len],
+ &lastLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ data2Len = data2Len + lastLen;
+
+ /* Comparison of Decrypt data */
+
+ if ((data1Len == data2Len) && (dataLen == data1Len) &&
+ (memcmp(data1, pData, dataLen) == 0) &&
+ (memcmp(data2, pData, dataLen) == 0)) {
+ PKM_LogIt("decrypt test case passed\n");
+ } else {
+ PKM_Error("derypt test case failed\n");
+ }
+
+ return crv;
+}
+
+CK_RV
+PKM_SecretKey(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
+{
+ CK_SESSION_HANDLE hSession;
+ CK_RV crv = CKR_OK;
+ CK_MECHANISM sAESKeyMech = {
+ CKM_AES_KEY_GEN, NULL, 0
+ };
+ CK_OBJECT_CLASS class = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyAESType = CKK_AES;
+ CK_UTF8CHAR AESlabel[] = "An AES secret key object";
+ CK_ULONG AESvalueLen = 16;
+ CK_ATTRIBUTE sAESKeyTemplate[9];
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+
+ CK_BYTE KEY[16];
+ CK_BYTE IV[16];
+ static const CK_BYTE CIPHERTEXT[] = {
+ 0x7e, 0x6a, 0x3f, 0x3b, 0x39, 0x3c, 0xf2, 0x4b,
+ 0xce, 0xcc, 0x23, 0x6d, 0x80, 0xfd, 0xe0, 0xff
+ };
+ CK_BYTE ciphertext[64];
+ CK_BYTE ciphertext2[64];
+ CK_ULONG ciphertextLen, ciphertext2Len, lastLen;
+ CK_BYTE plaintext[32];
+ CK_BYTE plaintext2[32];
+ CK_ULONG plaintextLen, plaintext2Len;
+ CK_BYTE wrappedKey[16];
+ CK_ULONG wrappedKeyLen;
+ CK_MECHANISM aesEcbMech = {
+ CKM_AES_ECB, NULL, 0
+ };
+ CK_OBJECT_HANDLE hTestKey;
+ CK_MECHANISM mech_AES_CBC;
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ memset(ciphertext, 0, sizeof(ciphertext));
+ memset(ciphertext2, 0, sizeof(ciphertext2));
+ memset(IV, 0x00, sizeof(IV));
+ memset(KEY, 0x00, sizeof(KEY));
+
+ mech_AES_CBC.mechanism = CKM_AES_CBC;
+ mech_AES_CBC.pParameter = IV;
+ mech_AES_CBC.ulParameterLen = sizeof(IV);
+
+ /* AES key template */
+ sAESKeyTemplate[0].type = CKA_CLASS;
+ sAESKeyTemplate[0].pValue = &class;
+ sAESKeyTemplate[0].ulValueLen = sizeof(class);
+ sAESKeyTemplate[1].type = CKA_KEY_TYPE;
+ sAESKeyTemplate[1].pValue = &keyAESType;
+ sAESKeyTemplate[1].ulValueLen = sizeof(keyAESType);
+ sAESKeyTemplate[2].type = CKA_LABEL;
+ sAESKeyTemplate[2].pValue = AESlabel;
+ sAESKeyTemplate[2].ulValueLen = sizeof(AESlabel) - 1;
+ sAESKeyTemplate[3].type = CKA_ENCRYPT;
+ sAESKeyTemplate[3].pValue = &true;
+ sAESKeyTemplate[3].ulValueLen = sizeof(true);
+ sAESKeyTemplate[4].type = CKA_DECRYPT;
+ sAESKeyTemplate[4].pValue = &true;
+ sAESKeyTemplate[4].ulValueLen = sizeof(true);
+ sAESKeyTemplate[5].type = CKA_SIGN;
+ sAESKeyTemplate[5].pValue = &true;
+ sAESKeyTemplate[5].ulValueLen = sizeof(true);
+ sAESKeyTemplate[6].type = CKA_VERIFY;
+ sAESKeyTemplate[6].pValue = &true;
+ sAESKeyTemplate[6].ulValueLen = sizeof(true);
+ sAESKeyTemplate[7].type = CKA_UNWRAP;
+ sAESKeyTemplate[7].pValue = &true;
+ sAESKeyTemplate[7].ulValueLen = sizeof(true);
+ sAESKeyTemplate[8].type = CKA_VALUE_LEN;
+ sAESKeyTemplate[8].pValue = &AESvalueLen;
+ sAESKeyTemplate[8].ulValueLen = sizeof(AESvalueLen);
+
+ crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
+ NULL, NULL, &hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Login with correct password succeeded\n");
+ } else {
+ PKM_Error("C_Login with correct password failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt("Generate an AES key ... \n");
+ /* generate an AES Secret Key */
+ crv = pFunctionList->C_GenerateKey(hSession, &sAESKeyMech,
+ sAESKeyTemplate,
+ NUM_ELEM(sAESKeyTemplate),
+ &hKey);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GenerateKey AES succeeded\n");
+ } else {
+ PKM_Error("C_GenerateKey AES failed with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_EncryptInit(hSession, &aesEcbMech, hKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_EncryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ wrappedKeyLen = sizeof(wrappedKey);
+ crv = pFunctionList->C_Encrypt(hSession, KEY, sizeof(KEY),
+ wrappedKey, &wrappedKeyLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Encrypt failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ if (wrappedKeyLen != sizeof(wrappedKey)) {
+ PKM_Error("wrappedKeyLen is %lu\n", wrappedKeyLen);
+ return crv;
+ }
+ /* Import an encrypted key */
+ crv = pFunctionList->C_UnwrapKey(hSession, &aesEcbMech, hKey,
+ wrappedKey, wrappedKeyLen,
+ sAESKeyTemplate,
+ NUM_ELEM(sAESKeyTemplate),
+ &hTestKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_UnwraPKey failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ /* AES Encrypt the text */
+ crv = pFunctionList->C_EncryptInit(hSession, &mech_AES_CBC, hTestKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_EncryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ ciphertextLen = sizeof(ciphertext);
+ crv = pFunctionList->C_Encrypt(hSession, (CK_BYTE *)PLAINTEXT,
+ sizeof(PLAINTEXT),
+ ciphertext, &ciphertextLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Encrypt failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ if ((ciphertextLen == sizeof(CIPHERTEXT)) &&
+ (memcmp(ciphertext, CIPHERTEXT, ciphertextLen) == 0)) {
+ PKM_LogIt("AES CBCVarKey128 encrypt test case 1 passed\n");
+ } else {
+ PKM_Error("AES CBCVarKey128 encrypt test case 1 failed\n");
+ return crv;
+ }
+
+ /* now use EncryptUpdate the text */
+ crv = pFunctionList->C_EncryptInit(hSession, &mech_AES_CBC, hTestKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_EncryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ ciphertext2Len = sizeof(ciphertext2);
+ crv = pFunctionList->C_EncryptUpdate(hSession, (CK_BYTE *)PLAINTEXT,
+ sizeof(PLAINTEXT),
+ ciphertext2, &ciphertext2Len);
+ if (crv != CKR_OK) {
+ PKM_Error("C_EncryptUpdate failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ lastLen = sizeof(ciphertext2) - ciphertext2Len;
+
+ crv = pFunctionList->C_EncryptFinal(hSession,
+ (CK_BYTE *)&ciphertext2[ciphertext2Len],
+ &lastLen);
+ ciphertext2Len = ciphertext2Len + lastLen;
+
+ if ((ciphertextLen == ciphertext2Len) &&
+ (memcmp(ciphertext, ciphertext2, sizeof(CIPHERTEXT)) == 0) &&
+ (memcmp(ciphertext2, CIPHERTEXT, sizeof(CIPHERTEXT)) == 0)) {
+ PKM_LogIt("AES CBCVarKey128 encrypt test case 2 passed\n");
+ } else {
+ PKM_Error("AES CBCVarKey128 encrypt test case 2 failed\n");
+ return CKR_GENERAL_ERROR;
+ }
+
+ /* AES CBC Decrypt the text */
+ crv = pFunctionList->C_DecryptInit(hSession, &mech_AES_CBC, hTestKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ plaintextLen = sizeof(plaintext);
+ crv = pFunctionList->C_Decrypt(hSession, ciphertext, ciphertextLen,
+ plaintext, &plaintextLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ if ((plaintextLen == sizeof(PLAINTEXT)) &&
+ (memcmp(plaintext, PLAINTEXT, plaintextLen) == 0)) {
+ PKM_LogIt("AES CBCVarKey128 decrypt test case 1 passed\n");
+ } else {
+ PKM_Error("AES CBCVarKey128 derypt test case 1 failed\n");
+ }
+ /* now use DecryptUpdate the text */
+ crv = pFunctionList->C_DecryptInit(hSession, &mech_AES_CBC, hTestKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ plaintext2Len = sizeof(plaintext2);
+ crv = pFunctionList->C_DecryptUpdate(hSession, ciphertext2,
+ ciphertext2Len,
+ plaintext2, &plaintext2Len);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptUpdate failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ lastLen = sizeof(plaintext2) - plaintext2Len;
+ crv = pFunctionList->C_DecryptFinal(hSession,
+ (CK_BYTE *)&plaintext2[plaintext2Len],
+ &lastLen);
+ plaintext2Len = plaintext2Len + lastLen;
+
+ if ((plaintextLen == plaintext2Len) &&
+ (memcmp(plaintext, plaintext2, plaintext2Len) == 0) &&
+ (memcmp(plaintext2, PLAINTEXT, sizeof(PLAINTEXT)) == 0)) {
+ PKM_LogIt("AES CBCVarKey128 decrypt test case 2 passed\n");
+ } else {
+ PKM_Error("AES CBCVarKey128 decrypt test case 2 failed\n");
+ return CKR_GENERAL_ERROR;
+ }
+
+ crv = pFunctionList->C_Logout(hSession);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Logout succeeded\n");
+ } else {
+ PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_CloseSession(hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ return crv;
+}
+
+CK_RV
+PKM_PubKeySign(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hRwSession,
+ CK_OBJECT_HANDLE hPubKey, CK_OBJECT_HANDLE hPrivKey,
+ CK_MECHANISM *signMech, const CK_BYTE *pData,
+ CK_ULONG pDataLen)
+{
+ CK_RV crv = CKR_OK;
+ CK_BYTE sig[MAX_SIG_SZ];
+ CK_ULONG sigLen = 0;
+
+ NUMTESTS++; /* increment NUMTESTS */
+ memset(sig, 0, sizeof(sig));
+
+ /* C_Sign */
+ crv = pFunctionList->C_SignInit(hRwSession, signMech, hPrivKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ sigLen = sizeof(sig);
+ crv = pFunctionList->C_Sign(hRwSession, (CK_BYTE *)pData, pDataLen,
+ sig, &sigLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Sign failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* C_Verify the signature */
+ crv = pFunctionList->C_VerifyInit(hRwSession, signMech, hPubKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_Verify(hRwSession, (CK_BYTE *)pData, pDataLen,
+ sig, sigLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Verify succeeded\n");
+ } else {
+ PKM_Error("C_Verify failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* Check that the mechanism is Multi-part */
+ if (signMech->mechanism == CKM_DSA ||
+ signMech->mechanism == CKM_RSA_PKCS) {
+ return crv;
+ }
+
+ memset(sig, 0, sizeof(sig));
+ /* SignUpdate */
+ crv = pFunctionList->C_SignInit(hRwSession, signMech, hPrivKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_SignInit failed with 0x%08lX %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_SignUpdate(hRwSession, (CK_BYTE *)pData, pDataLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Sign failed with 0x%08lX %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ sigLen = sizeof(sig);
+ crv = pFunctionList->C_SignFinal(hRwSession, sig, &sigLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Sign failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* C_VerifyUpdate the signature */
+ crv = pFunctionList->C_VerifyInit(hRwSession, signMech,
+ hPubKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_VerifyUpdate(hRwSession, (CK_BYTE *)pData,
+ pDataLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_VerifyUpdate failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_VerifyFinal(hRwSession, sig, sigLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_VerifyFinal succeeded\n");
+ } else {
+ PKM_Error("C_VerifyFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ return crv;
+}
+
+CK_RV
+PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList,
+ CK_ULONG slotID, CK_UTF8CHAR_PTR pwd,
+ CK_ULONG pwdLen)
+{
+ CK_SESSION_HANDLE hSession;
+ CK_RV crv = CKR_OK;
+
+ /*** DSA Key ***/
+ CK_MECHANISM dsaParamGenMech;
+ CK_ULONG primeBits = 1024;
+ CK_ATTRIBUTE dsaParamGenTemplate[1];
+ CK_OBJECT_HANDLE hDsaParams = CK_INVALID_HANDLE;
+ CK_BYTE DSA_P[128];
+ CK_BYTE DSA_Q[20];
+ CK_BYTE DSA_G[128];
+ CK_MECHANISM dsaKeyPairGenMech;
+ CK_ATTRIBUTE dsaPubKeyTemplate[5];
+ CK_ATTRIBUTE dsaPrivKeyTemplate[5];
+ CK_OBJECT_HANDLE hDSApubKey = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hDSAprivKey = CK_INVALID_HANDLE;
+
+ /* From SHA1ShortMsg.req, Len = 136 */
+ CK_BYTE MSG[] = {
+ 0xba, 0x33, 0x95, 0xfb,
+ 0x5a, 0xfa, 0x8e, 0x6a,
+ 0x43, 0xdf, 0x41, 0x6b,
+ 0x32, 0x7b, 0x74, 0xfa,
+ 0x44
+ };
+ CK_BYTE MD[] = {
+ 0xf7, 0x5d, 0x92, 0xa4,
+ 0xbb, 0x4d, 0xec, 0xc3,
+ 0x7c, 0x5c, 0x72, 0xfa,
+ 0x04, 0x75, 0x71, 0x0a,
+ 0x06, 0x75, 0x8c, 0x1d
+ };
+
+ CK_BYTE sha1Digest[20];
+ CK_ULONG sha1DigestLen;
+ CK_BYTE dsaSig[40];
+ CK_ULONG dsaSigLen;
+ CK_MECHANISM sha1Mech = {
+ CKM_SHA_1, NULL, 0
+ };
+ CK_MECHANISM dsaMech = {
+ CKM_DSA, NULL, 0
+ };
+ CK_MECHANISM dsaWithSha1Mech = {
+ CKM_DSA_SHA1, NULL, 0
+ };
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ /* DSA key init */
+ dsaParamGenMech.mechanism = CKM_DSA_PARAMETER_GEN;
+ dsaParamGenMech.pParameter = NULL_PTR;
+ dsaParamGenMech.ulParameterLen = 0;
+ dsaParamGenTemplate[0].type = CKA_PRIME_BITS;
+ dsaParamGenTemplate[0].pValue = &primeBits;
+ dsaParamGenTemplate[0].ulValueLen = sizeof(primeBits);
+ dsaPubKeyTemplate[0].type = CKA_PRIME;
+ dsaPubKeyTemplate[0].pValue = DSA_P;
+ dsaPubKeyTemplate[0].ulValueLen = sizeof(DSA_P);
+ dsaPubKeyTemplate[1].type = CKA_SUBPRIME;
+ dsaPubKeyTemplate[1].pValue = DSA_Q;
+ dsaPubKeyTemplate[1].ulValueLen = sizeof(DSA_Q);
+ dsaPubKeyTemplate[2].type = CKA_BASE;
+ dsaPubKeyTemplate[2].pValue = DSA_G;
+ dsaPubKeyTemplate[2].ulValueLen = sizeof(DSA_G);
+ dsaPubKeyTemplate[3].type = CKA_TOKEN;
+ dsaPubKeyTemplate[3].pValue = &true;
+ dsaPubKeyTemplate[3].ulValueLen = sizeof(true);
+ dsaPubKeyTemplate[4].type = CKA_VERIFY;
+ dsaPubKeyTemplate[4].pValue = &true;
+ dsaPubKeyTemplate[4].ulValueLen = sizeof(true);
+ dsaKeyPairGenMech.mechanism = CKM_DSA_KEY_PAIR_GEN;
+ dsaKeyPairGenMech.pParameter = NULL_PTR;
+ dsaKeyPairGenMech.ulParameterLen = 0;
+ dsaPrivKeyTemplate[0].type = CKA_TOKEN;
+ dsaPrivKeyTemplate[0].pValue = &true;
+ dsaPrivKeyTemplate[0].ulValueLen = sizeof(true);
+ dsaPrivKeyTemplate[1].type = CKA_PRIVATE;
+ dsaPrivKeyTemplate[1].pValue = &true;
+ dsaPrivKeyTemplate[1].ulValueLen = sizeof(true);
+ dsaPrivKeyTemplate[2].type = CKA_SENSITIVE;
+ dsaPrivKeyTemplate[2].pValue = &true;
+ dsaPrivKeyTemplate[2].ulValueLen = sizeof(true);
+ dsaPrivKeyTemplate[3].type = CKA_SIGN,
+ dsaPrivKeyTemplate[3].pValue = &true;
+ dsaPrivKeyTemplate[3].ulValueLen = sizeof(true);
+ dsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE;
+ dsaPrivKeyTemplate[4].pValue = &true;
+ dsaPrivKeyTemplate[4].ulValueLen = sizeof(true);
+
+ crv = pFunctionList->C_OpenSession(pSlotList[slotID],
+ CKF_RW_SESSION | CKF_SERIAL_SESSION,
+ NULL, NULL, &hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Login with correct password succeeded\n");
+ } else {
+ PKM_Error("C_Login with correct password failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt("Generate DSA PQG domain parameters ... \n");
+ /* Generate DSA domain parameters PQG */
+ crv = pFunctionList->C_GenerateKey(hSession, &dsaParamGenMech,
+ dsaParamGenTemplate,
+ 1,
+ &hDsaParams);
+ if (crv == CKR_OK) {
+ PKM_LogIt("DSA domain parameter generation succeeded\n");
+ } else {
+ PKM_Error("DSA domain parameter generation failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_GetAttributeValue(hSession, hDsaParams,
+ dsaPubKeyTemplate, 3);
+ if (crv == CKR_OK) {
+ PKM_LogIt("Getting DSA domain parameters succeeded\n");
+ } else {
+ PKM_Error("Getting DSA domain parameters failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_DestroyObject(hSession, hDsaParams);
+ if (crv == CKR_OK) {
+ PKM_LogIt("Destroying DSA domain parameters succeeded\n");
+ } else {
+ PKM_Error("Destroying DSA domain parameters failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt("Generate a DSA key pair ... \n");
+ /* Generate a persistent DSA key pair */
+ crv = pFunctionList->C_GenerateKeyPair(hSession, &dsaKeyPairGenMech,
+ dsaPubKeyTemplate,
+ NUM_ELEM(dsaPubKeyTemplate),
+ dsaPrivKeyTemplate,
+ NUM_ELEM(dsaPrivKeyTemplate),
+ &hDSApubKey, &hDSAprivKey);
+ if (crv == CKR_OK) {
+ PKM_LogIt("DSA key pair generation succeeded\n");
+ } else {
+ PKM_Error("DSA key pair generation failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* Compute SHA-1 digest */
+ crv = pFunctionList->C_DigestInit(hSession, &sha1Mech);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ sha1DigestLen = sizeof(sha1Digest);
+ crv = pFunctionList->C_Digest(hSession, MSG, sizeof(MSG),
+ sha1Digest, &sha1DigestLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Digest failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ if (sha1DigestLen != sizeof(sha1Digest)) {
+ PKM_Error("sha1DigestLen is %lu\n", sha1DigestLen);
+ return crv;
+ }
+
+ if (memcmp(sha1Digest, MD, sizeof(MD)) == 0) {
+ PKM_LogIt("SHA-1 SHA1ShortMsg test case Len = 136 passed\n");
+ } else {
+ PKM_Error("SHA-1 SHA1ShortMsg test case Len = 136 failed\n");
+ }
+
+ crv = PKM_PubKeySign(pFunctionList, hSession,
+ hDSApubKey, hDSAprivKey,
+ &dsaMech, sha1Digest, sizeof(sha1Digest));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_PubKeySign CKM_DSA succeeded \n");
+ } else {
+ PKM_Error("PKM_PubKeySign failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = PKM_PubKeySign(pFunctionList, hSession,
+ hDSApubKey, hDSAprivKey,
+ &dsaWithSha1Mech, PLAINTEXT, sizeof(PLAINTEXT));
+ if (crv == CKR_OK) {
+ PKM_LogIt("PKM_PubKeySign CKM_DSA_SHA1 succeeded \n");
+ } else {
+ PKM_Error("PKM_PubKeySign failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* Sign with DSA */
+ crv = pFunctionList->C_SignInit(hSession, &dsaMech, hDSAprivKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ dsaSigLen = sizeof(dsaSig);
+ crv = pFunctionList->C_Sign(hSession, sha1Digest, sha1DigestLen,
+ dsaSig, &dsaSigLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Sign failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* Verify the DSA signature */
+ crv = pFunctionList->C_VerifyInit(hSession, &dsaMech, hDSApubKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_Verify(hSession, sha1Digest, sha1DigestLen,
+ dsaSig, dsaSigLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Verify succeeded\n");
+ } else {
+ PKM_Error("C_Verify failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* Verify the signature in a different way */
+ crv = pFunctionList->C_VerifyInit(hSession, &dsaWithSha1Mech,
+ hDSApubKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_VerifyUpdate(hSession, MSG, 1);
+ if (crv != CKR_OK) {
+ PKM_Error("C_VerifyUpdate failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_VerifyUpdate(hSession, MSG + 1, sizeof(MSG) - 1);
+ if (crv != CKR_OK) {
+ PKM_Error("C_VerifyUpdate failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_VerifyFinal(hSession, dsaSig, dsaSigLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_VerifyFinal succeeded\n");
+ } else {
+ PKM_Error("C_VerifyFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* Verify the signature in a different way */
+ crv = pFunctionList->C_VerifyInit(hSession, &dsaWithSha1Mech,
+ hDSApubKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_VerifyUpdate(hSession, MSG, 1);
+ if (crv != CKR_OK) {
+ PKM_Error("C_VerifyUpdate failed with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_VerifyUpdate(hSession, MSG + 1, sizeof(MSG) - 1);
+ if (crv != CKR_OK) {
+ PKM_Error("C_VerifyUpdate failed with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_VerifyFinal(hSession, dsaSig, dsaSigLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_VerifyFinal of multi update succeeded.\n");
+ } else {
+ PKM_Error("C_VerifyFinal of multi update failed with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ /* Now modify the data */
+ MSG[0] += 1;
+ /* Compute SHA-1 digest */
+ crv = pFunctionList->C_DigestInit(hSession, &sha1Mech);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ sha1DigestLen = sizeof(sha1Digest);
+ crv = pFunctionList->C_Digest(hSession, MSG, sizeof(MSG),
+ sha1Digest, &sha1DigestLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Digest failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_VerifyInit(hSession, &dsaMech, hDSApubKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_Verify(hSession, sha1Digest, sha1DigestLen,
+ dsaSig, dsaSigLen);
+ if (crv != CKR_SIGNATURE_INVALID) {
+ PKM_Error("C_Verify of modified data succeeded\n");
+ return crv;
+ } else {
+ PKM_LogIt("C_Verify of modified data returned as EXPECTED "
+ " with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ }
+
+ crv = pFunctionList->C_Logout(hSession);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Logout succeeded\n");
+ } else {
+ PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_CloseSession(hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ return crv;
+}
+
+CK_RV
+PKM_Hmac(CK_FUNCTION_LIST_PTR pFunctionList, CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE sKey, CK_MECHANISM *hmacMech,
+ const CK_BYTE *pData, CK_ULONG pDataLen)
+{
+
+ CK_RV crv = CKR_OK;
+
+ CK_BYTE hmac1[HMAC_MAX_LENGTH];
+ CK_ULONG hmac1Len = 0;
+ CK_BYTE hmac2[HMAC_MAX_LENGTH];
+ CK_ULONG hmac2Len = 0;
+
+ memset(hmac1, 0, sizeof(hmac1));
+ memset(hmac2, 0, sizeof(hmac2));
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ crv = pFunctionList->C_SignInit(hSession, hmacMech, sKey);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_SignInit succeeded\n");
+ } else {
+ PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ hmac1Len = sizeof(hmac1);
+ crv = pFunctionList->C_Sign(hSession, (CK_BYTE *)pData,
+ pDataLen,
+ (CK_BYTE *)hmac1, &hmac1Len);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Sign succeeded\n");
+ } else {
+ PKM_Error("C_Sign failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_SignInit(hSession, hmacMech, sKey);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_SignInit succeeded\n");
+ } else {
+ PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_SignUpdate(hSession, (CK_BYTE *)pData,
+ pDataLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_SignUpdate succeeded\n");
+ } else {
+ PKM_Error("C_SignUpdate failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ hmac2Len = sizeof(hmac2);
+ crv = pFunctionList->C_SignFinal(hSession, (CK_BYTE *)hmac2, &hmac2Len);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_SignFinal succeeded\n");
+ } else {
+ PKM_Error("C_SignFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ if ((hmac1Len == hmac2Len) && (memcmp(hmac1, hmac2, hmac1Len) == 0)) {
+ PKM_LogIt("hmacs are equal!\n");
+ } else {
+ PKM_Error("hmacs are not equal!\n");
+ }
+ crv = pFunctionList->C_VerifyInit(hSession, hmacMech, sKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_Verify(hSession, (CK_BYTE *)pData,
+ pDataLen,
+ (CK_BYTE *)hmac2, hmac2Len);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Verify of hmac succeeded\n");
+ } else {
+ PKM_Error("C_Verify failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_VerifyInit(hSession, hmacMech, sKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_VerifyUpdate(hSession, (CK_BYTE *)pData,
+ pDataLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_VerifyUpdate of hmac succeeded\n");
+ } else {
+ PKM_Error("C_VerifyUpdate failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_VerifyFinal(hSession, (CK_BYTE *)hmac1,
+ hmac1Len);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_VerifyFinal of hmac succeeded\n");
+ } else {
+ PKM_Error("C_VerifyFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ return crv;
+}
+
+CK_RV
+PKM_FindAllObjects(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
+{
+ CK_RV crv = CKR_OK;
+
+ CK_SESSION_HANDLE h = (CK_SESSION_HANDLE)0;
+ CK_SESSION_INFO sinfo;
+ CK_ATTRIBUTE_PTR pTemplate;
+ CK_ULONG tnObjects = 0;
+ int curMode;
+ unsigned int i;
+ unsigned int number_of_all_known_attribute_types = totalKnownType(ConstAttribute);
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
+ NULL, NULL, &h);
+ if (CKR_OK != crv) {
+ PKM_Error("C_OpenSession(%lu, CKF_SERIAL_SESSION, , )"
+ "returned 0x%08X, %-26s\n",
+ pSlotList[slotID], crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt(" Opened a session: handle = 0x%08x\n", h);
+
+ (void)memset(&sinfo, 0, sizeof(CK_SESSION_INFO));
+ crv = pFunctionList->C_GetSessionInfo(h, &sinfo);
+ if (CKR_OK != crv) {
+ PKM_LogIt("C_GetSessionInfo(%lu, ) returned 0x%08X, %-26s\n", h, crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt(" SESSION INFO:\n");
+ PKM_LogIt(" slotID = %lu\n", sinfo.slotID);
+ PKM_LogIt(" state = %lu\n", sinfo.state);
+ PKM_LogIt(" flags = 0x%08x\n", sinfo.flags);
+#ifdef CKF_EXCLUSIVE_SESSION
+ PKM_LogIt(" -> EXCLUSIVE SESSION = %s\n", sinfo.flags &
+ CKF_EXCLUSIVE_SESSION
+ ? "TRUE"
+ : "FALSE");
+#endif /* CKF_EXCLUSIVE_SESSION */
+ PKM_LogIt(" -> RW SESSION = %s\n", sinfo.flags &
+ CKF_RW_SESSION
+ ? "TRUE"
+ : "FALSE");
+ PKM_LogIt(" -> SERIAL SESSION = %s\n", sinfo.flags &
+ CKF_SERIAL_SESSION
+ ? "TRUE"
+ : "FALSE");
+#ifdef CKF_INSERTION_CALLBACK
+ PKM_LogIt(" -> INSERTION CALLBACK = %s\n", sinfo.flags &
+ CKF_INSERTION_CALLBACK
+ ? "TRUE"
+ : "FALSE");
+#endif /* CKF_INSERTION_CALLBACK */
+ PKM_LogIt(" ulDeviceError = %lu\n", sinfo.ulDeviceError);
+ PKM_LogIt("\n");
+
+ crv = pFunctionList->C_FindObjectsInit(h, NULL, 0);
+ if (CKR_OK != crv) {
+ PKM_LogIt("C_FindObjectsInit(%lu, NULL, 0) returned "
+ "0x%08X, %-26s\n",
+ h, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ pTemplate = (CK_ATTRIBUTE_PTR)calloc(number_of_all_known_attribute_types,
+ sizeof(CK_ATTRIBUTE));
+ if ((CK_ATTRIBUTE_PTR)NULL == pTemplate) {
+ PKM_Error("[pTemplate memory allocation of %lu bytes failed]\n",
+ number_of_all_known_attribute_types *
+ sizeof(CK_ATTRIBUTE));
+ return crv;
+ }
+
+ PKM_LogIt(" All objects:\n");
+ /* Printing table set to NOMODE */
+ curMode = MODE;
+ MODE = NOMODE;
+
+ while (1) {
+ CK_OBJECT_HANDLE o = (CK_OBJECT_HANDLE)0;
+ CK_ULONG nObjects = 0;
+ CK_ULONG k;
+ CK_ULONG nAttributes = 0;
+ CK_ATTRIBUTE_PTR pT2;
+ CK_ULONG l;
+ const char *attName = NULL;
+
+ crv = pFunctionList->C_FindObjects(h, &o, 1, &nObjects);
+ if (CKR_OK != crv) {
+ PKM_Error("C_FindObjects(%lu, , 1, ) returned 0x%08X, %-26s\n",
+ h, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ if (0 == nObjects) {
+ PKM_LogIt("\n");
+ break;
+ }
+
+ tnObjects++;
+
+ PKM_LogIt(" OBJECT HANDLE %lu:\n", o);
+
+ k = 0;
+ for (i = 0; i < constCount; i++) {
+ if (consts[i].type == ConstAttribute) {
+ pTemplate[k].type = consts[i].value;
+ pTemplate[k].pValue = (CK_VOID_PTR)NULL;
+ pTemplate[k].ulValueLen = 0;
+ k++;
+ }
+ assert(k <= number_of_all_known_attribute_types);
+ }
+
+ crv = pFunctionList->C_GetAttributeValue(h, o, pTemplate,
+ number_of_all_known_attribute_types);
+ switch (crv) {
+ case CKR_OK:
+ case CKR_ATTRIBUTE_SENSITIVE:
+ case CKR_ATTRIBUTE_TYPE_INVALID:
+ case CKR_BUFFER_TOO_SMALL:
+ break;
+ default:
+ PKM_Error("C_GetAtributeValue(%lu, %lu, {all attribute types},"
+ "%lu) returned 0x%08X, %-26s\n",
+ h, o, number_of_all_known_attribute_types, crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ for (k = 0; k < (CK_ULONG)number_of_all_known_attribute_types; k++) {
+ if (-1 != (CK_LONG)pTemplate[k].ulValueLen) {
+ nAttributes++;
+ }
+ }
+
+ PKM_LogIt(" %lu attributes:\n", nAttributes);
+ for (k = 0; k < (CK_ULONG)number_of_all_known_attribute_types;
+ k++) {
+ if (-1 != (CK_LONG)pTemplate[k].ulValueLen) {
+ attName = getNameFromAttribute(pTemplate[k].type);
+ if (!attName) {
+ PKM_Error("Unable to find attribute name update pk11table.c\n");
+ }
+ PKM_LogIt(" %s 0x%08x (len = %lu)\n",
+ attName,
+ pTemplate[k].type,
+ pTemplate[k].ulValueLen);
+ }
+ }
+ PKM_LogIt("\n");
+
+ pT2 = (CK_ATTRIBUTE_PTR)calloc(nAttributes, sizeof(CK_ATTRIBUTE));
+ if ((CK_ATTRIBUTE_PTR)NULL == pT2) {
+ PKM_Error("[pT2 memory allocation of %lu bytes failed]\n",
+ nAttributes * sizeof(CK_ATTRIBUTE));
+ return crv;
+ }
+
+ /* allocate memory for the attribute values */
+ for (l = 0, k = 0; k < (CK_ULONG)number_of_all_known_attribute_types;
+ k++) {
+ if (-1 != (CK_LONG)pTemplate[k].ulValueLen) {
+ pT2[l].type = pTemplate[k].type;
+ pT2[l].ulValueLen = pTemplate[k].ulValueLen;
+ if (pT2[l].ulValueLen > 0) {
+ pT2[l].pValue = (CK_VOID_PTR)malloc(pT2[l].ulValueLen);
+ if ((CK_VOID_PTR)NULL == pT2[l].pValue) {
+ PKM_Error("pValue memory allocation of %lu bytes failed]\n",
+ pT2[l].ulValueLen);
+ return crv;
+ }
+ } else
+ pT2[l].pValue = (CK_VOID_PTR)NULL;
+ l++;
+ }
+ }
+
+ assert(l == nAttributes);
+
+ crv = pFunctionList->C_GetAttributeValue(h, o, pT2, nAttributes);
+ switch (crv) {
+ case CKR_OK:
+ case CKR_ATTRIBUTE_SENSITIVE:
+ case CKR_ATTRIBUTE_TYPE_INVALID:
+ case CKR_BUFFER_TOO_SMALL:
+ break;
+ default:
+ PKM_Error("C_GetAtributeValue(%lu, %lu, {existent attribute"
+ " types}, %lu) returned 0x%08X, %-26s\n",
+ h, o, nAttributes, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ for (l = 0; l < nAttributes; l++) {
+ attName = getNameFromAttribute(pT2[l].type);
+ if (!attName)
+ attName = "unknown attribute";
+ PKM_LogIt(" type = %s len = %ld",
+ attName, (CK_LONG)pT2[l].ulValueLen);
+
+ if (-1 == (CK_LONG)pT2[l].ulValueLen) {
+ ;
+ } else {
+ CK_ULONG m;
+
+ if (pT2[l].ulValueLen <= 8) {
+ PKM_LogIt(", value = ");
+ } else {
+ PKM_LogIt(", value = \n ");
+ }
+
+ for (m = 0; (m < pT2[l].ulValueLen) && (m < 20); m++) {
+ PKM_LogIt("%02x", (CK_ULONG)(0xff &
+ ((CK_CHAR_PTR)pT2[l].pValue)[m]));
+ }
+
+ PKM_LogIt(" ");
+
+ for (m = 0; (m < pT2[l].ulValueLen) && (m < 20); m++) {
+ CK_CHAR c = ((CK_CHAR_PTR)pT2[l].pValue)[m];
+ if ((c < 0x20) || (c >= 0x7f)) {
+ c = '.';
+ }
+ PKM_LogIt("%c", c);
+ }
+ }
+
+ PKM_LogIt("\n");
+ }
+
+ PKM_LogIt("\n");
+
+ for (l = 0; l < nAttributes; l++) {
+ if (pT2[l].pValue) {
+ free(pT2[l].pValue);
+ }
+ }
+ free(pT2);
+ } /* while(1) */
+
+ MODE = curMode; /* reset the logging MODE */
+
+ crv = pFunctionList->C_FindObjectsFinal(h);
+ if (CKR_OK != crv) {
+ PKM_Error("C_FindObjectsFinal(%lu) returned 0x%08X, %-26s\n", h, crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt(" (%lu objects total)\n", tnObjects);
+
+ crv = pFunctionList->C_CloseSession(h);
+ if (CKR_OK != crv) {
+ PKM_Error("C_CloseSession(%lu) returned 0x%08X, %-26s\n", h, crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ return crv;
+}
+/* session to create, find, and delete a couple session objects */
+CK_RV
+PKM_MultiObjectManagement(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
+{
+
+ CK_RV crv = CKR_OK;
+
+ CK_SESSION_HANDLE h = (CK_SESSION_HANDLE)0;
+ CK_SESSION_HANDLE h2 = (CK_SESSION_HANDLE)0;
+ CK_ATTRIBUTE one[7], two[7], three[7], delta[1], mask[1];
+ CK_OBJECT_CLASS cko_data = CKO_DATA;
+ char *key = "TEST PROGRAM";
+ CK_ULONG key_len = 0;
+ CK_OBJECT_HANDLE hOneIn = (CK_OBJECT_HANDLE)0;
+ CK_OBJECT_HANDLE hTwoIn = (CK_OBJECT_HANDLE)0;
+ CK_OBJECT_HANDLE hThreeIn = (CK_OBJECT_HANDLE)0;
+ CK_OBJECT_HANDLE hDeltaIn = (CK_OBJECT_HANDLE)0;
+ CK_OBJECT_HANDLE found[10];
+ CK_ULONG nFound;
+ CK_ULONG hDeltaLen, hThreeLen = 0;
+
+ CK_TOKEN_INFO tinfo;
+
+ NUMTESTS++; /* increment NUMTESTS */
+ key_len = sizeof(key);
+ crv = pFunctionList->C_OpenSession(pSlotList[slotID],
+ CKF_SERIAL_SESSION, NULL, NULL, &h);
+ if (CKR_OK != crv) {
+ PKM_Error("C_OpenSession(%lu, CKF_SERIAL_SESSION, , )"
+ "returned 0x%08X, %-26s\n",
+ pSlotList[slotID], crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_Login(h, CKU_USER, pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Login with correct password succeeded\n");
+ } else {
+ PKM_Error("C_Login with correct password failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ (void)memset(&tinfo, 0, sizeof(CK_TOKEN_INFO));
+ crv = pFunctionList->C_GetTokenInfo(pSlotList[slotID], &tinfo);
+ if (CKR_OK != crv) {
+ PKM_Error("C_GetTokenInfo(%lu, ) returned 0x%08X, %-26s\n",
+ pSlotList[slotID], crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt(" Opened a session: handle = 0x%08x\n", h);
+
+ one[0].type = CKA_CLASS;
+ one[0].pValue = &cko_data;
+ one[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
+ one[1].type = CKA_TOKEN;
+ one[1].pValue = &false;
+ one[1].ulValueLen = sizeof(CK_BBOOL);
+ one[2].type = CKA_PRIVATE;
+ one[2].pValue = &false;
+ one[2].ulValueLen = sizeof(CK_BBOOL);
+ one[3].type = CKA_MODIFIABLE;
+ one[3].pValue = &true;
+ one[3].ulValueLen = sizeof(CK_BBOOL);
+ one[4].type = CKA_LABEL;
+ one[4].pValue = "Test data object one";
+ one[4].ulValueLen = strlen(one[4].pValue);
+ one[5].type = CKA_APPLICATION;
+ one[5].pValue = key;
+ one[5].ulValueLen = key_len;
+ one[6].type = CKA_VALUE;
+ one[6].pValue = "Object one";
+ one[6].ulValueLen = strlen(one[6].pValue);
+
+ two[0].type = CKA_CLASS;
+ two[0].pValue = &cko_data;
+ two[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
+ two[1].type = CKA_TOKEN;
+ two[1].pValue = &false;
+ two[1].ulValueLen = sizeof(CK_BBOOL);
+ two[2].type = CKA_PRIVATE;
+ two[2].pValue = &false;
+ two[2].ulValueLen = sizeof(CK_BBOOL);
+ two[3].type = CKA_MODIFIABLE;
+ two[3].pValue = &true;
+ two[3].ulValueLen = sizeof(CK_BBOOL);
+ two[4].type = CKA_LABEL;
+ two[4].pValue = "Test data object two";
+ two[4].ulValueLen = strlen(two[4].pValue);
+ two[5].type = CKA_APPLICATION;
+ two[5].pValue = key;
+ two[5].ulValueLen = key_len;
+ two[6].type = CKA_VALUE;
+ two[6].pValue = "Object two";
+ two[6].ulValueLen = strlen(two[6].pValue);
+
+ three[0].type = CKA_CLASS;
+ three[0].pValue = &cko_data;
+ three[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
+ three[1].type = CKA_TOKEN;
+ three[1].pValue = &false;
+ three[1].ulValueLen = sizeof(CK_BBOOL);
+ three[2].type = CKA_PRIVATE;
+ three[2].pValue = &false;
+ three[2].ulValueLen = sizeof(CK_BBOOL);
+ three[3].type = CKA_MODIFIABLE;
+ three[3].pValue = &true;
+ three[3].ulValueLen = sizeof(CK_BBOOL);
+ three[4].type = CKA_LABEL;
+ three[4].pValue = "Test data object three";
+ three[4].ulValueLen = strlen(three[4].pValue);
+ three[5].type = CKA_APPLICATION;
+ three[5].pValue = key;
+ three[5].ulValueLen = key_len;
+ three[6].type = CKA_VALUE;
+ three[6].pValue = "Object three";
+ three[6].ulValueLen = strlen(three[6].pValue);
+
+ crv = pFunctionList->C_CreateObject(h, one, 7, &hOneIn);
+ if (CKR_OK != crv) {
+ PKM_Error("C_CreateObject(%lu, one, 7, ) returned 0x%08X, %-26s\n",
+ h, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt(" Created object one: handle = %lu\n", hOneIn);
+
+ crv = pFunctionList->C_CreateObject(h, two, 7, &hTwoIn);
+ if (CKR_OK != crv) {
+ PKM_Error("C_CreateObject(%lu, two, 7, ) returned 0x%08X, %-26s\n",
+ h, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt(" Created object two: handle = %lu\n", hTwoIn);
+
+ crv = pFunctionList->C_CreateObject(h, three, 7, &hThreeIn);
+ if (CKR_OK != crv) {
+ PKM_Error("C_CreateObject(%lu, three, 7, ) returned 0x%08x\n",
+ h, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_GetObjectSize(h, hThreeIn, &hThreeLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GetObjectSize succeeded\n");
+ } else {
+ PKM_Error("C_GetObjectSize failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt(" Created object three: handle = %lu\n", hThreeIn);
+
+ delta[0].type = CKA_VALUE;
+ delta[0].pValue = "Copied object";
+ delta[0].ulValueLen = strlen(delta[0].pValue);
+
+ crv = pFunctionList->C_CopyObject(h, hThreeIn, delta, 1, &hDeltaIn);
+ if (CKR_OK != crv) {
+ PKM_Error("C_CopyObject(%lu, %lu, delta, 1, ) returned "
+ "0x%08X, %-26s\n",
+ h, hThreeIn, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_GetObjectSize(h, hDeltaIn, &hDeltaLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GetObjectSize succeeded\n");
+ } else {
+ PKM_Error("C_GetObjectSize failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ if (hThreeLen == hDeltaLen) {
+ PKM_LogIt("Copied object size same as orginal\n");
+ } else {
+ PKM_Error("Copied object different from original\n");
+ return CKR_DEVICE_ERROR;
+ }
+
+ PKM_LogIt(" Copied object three: new handle = %lu\n", hDeltaIn);
+
+ mask[0].type = CKA_APPLICATION;
+ mask[0].pValue = key;
+ mask[0].ulValueLen = key_len;
+
+ crv = pFunctionList->C_FindObjectsInit(h, mask, 1);
+ if (CKR_OK != crv) {
+ PKM_Error("C_FindObjectsInit(%lu, mask, 1) returned 0x%08X, %-26s\n",
+ h, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ (void)memset(&found, 0, sizeof(found));
+ nFound = 0;
+ crv = pFunctionList->C_FindObjects(h, found, 10, &nFound);
+ if (CKR_OK != crv) {
+ PKM_Error("C_FindObjects(%lu,, 10, ) returned 0x%08X, %-26s\n",
+ h, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ if (4 != nFound) {
+ PKM_Error("Found %lu objects, not 4.\n", nFound);
+ return crv;
+ }
+
+ PKM_LogIt(" Found 4 objects: %lu, %lu, %lu, %lu\n",
+ found[0], found[1], found[2], found[3]);
+
+ crv = pFunctionList->C_FindObjectsFinal(h);
+ if (CKR_OK != crv) {
+ PKM_Error("C_FindObjectsFinal(%lu) returned 0x%08X, %-26s\n",
+ h, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_DestroyObject(h, hThreeIn);
+ if (CKR_OK != crv) {
+ PKM_Error("C_DestroyObject(%lu, %lu) returned 0x%08X, %-26s\n", h,
+ hThreeIn, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt(" Destroyed object three (handle = %lu)\n", hThreeIn);
+
+ delta[0].type = CKA_APPLICATION;
+ delta[0].pValue = "Changed application";
+ delta[0].ulValueLen = strlen(delta[0].pValue);
+
+ crv = pFunctionList->C_SetAttributeValue(h, hTwoIn, delta, 1);
+ if (CKR_OK != crv) {
+ PKM_Error("C_SetAttributeValue(%lu, %lu, delta, 1) returned "
+ "0x%08X, %-26s\n",
+ h, hTwoIn, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt(" Changed object two (handle = %lu).\n", hTwoIn);
+
+ /* Can another session find these session objects? */
+
+ crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
+ NULL, NULL, &h2);
+ if (CKR_OK != crv) {
+ PKM_Error("C_OpenSession(%lu, CKF_SERIAL_SESSION, , )"
+ " returned 0x%08X, %-26s\n",
+ pSlotList[slotID], crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ PKM_LogIt(" Opened a second session: handle = 0x%08x\n", h2);
+
+ /* mask is still the same */
+
+ crv = pFunctionList->C_FindObjectsInit(h2, mask, 1);
+ if (CKR_OK != crv) {
+ PKM_Error("C_FindObjectsInit(%lu, mask, 1) returned 0x%08X, %-26s\n",
+ h2, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ (void)memset(&found, 0, sizeof(found));
+ nFound = 0;
+ crv = pFunctionList->C_FindObjects(h2, found, 10, &nFound);
+ if (CKR_OK != crv) {
+ PKM_Error("C_FindObjects(%lu,, 10, ) returned 0x%08X, %-26s\n",
+ h2, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ if (2 != nFound) {
+ PKM_Error("Found %lu objects, not 2.\n", nFound);
+ return crv;
+ }
+
+ PKM_LogIt(" Found 2 objects: %lu, %lu\n",
+ found[0], found[1]);
+
+ crv = pFunctionList->C_FindObjectsFinal(h2);
+ if (CKR_OK != crv) {
+ PKM_Error("C_FindObjectsFinal(%lu) returned 0x%08X, %-26s\n", h2, crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_Logout(h);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Logout succeeded\n");
+ } else {
+ PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_CloseAllSessions(pSlotList[slotID]);
+ if (CKR_OK != crv) {
+ PKM_Error("C_CloseAllSessions(%lu) returned 0x%08X, %-26s\n",
+ pSlotList[slotID], crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt("\n");
+ return crv;
+}
+
+CK_RV
+PKM_OperationalState(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
+{
+ CK_SESSION_HANDLE hSession;
+ CK_RV crv = CKR_OK;
+ CK_MECHANISM sAESKeyMech = {
+ CKM_AES_KEY_GEN, NULL, 0
+ };
+ CK_OBJECT_CLASS class = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyAESType = CKK_AES;
+ CK_UTF8CHAR AESlabel[] = "An AES secret key object";
+ CK_ULONG AESvalueLen = 16;
+ CK_ATTRIBUTE sAESKeyTemplate[9];
+ CK_OBJECT_HANDLE sKey = CK_INVALID_HANDLE;
+ CK_BYTE_PTR pstate = NULL;
+ CK_ULONG statelen, digestlen, plainlen, plainlen_1, plainlen_2, slen;
+
+ static const CK_UTF8CHAR *plaintext = (CK_UTF8CHAR *)"Firefox rules.";
+ static const CK_UTF8CHAR *plaintext_1 = (CK_UTF8CHAR *)"Thunderbird rules.";
+ static const CK_UTF8CHAR *plaintext_2 = (CK_UTF8CHAR *)"Firefox and Thunderbird.";
+
+ char digest[MAX_DIGEST_SZ], digest_1[MAX_DIGEST_SZ];
+ char sign[MAX_SIG_SZ];
+ CK_MECHANISM signmech;
+ CK_MECHANISM digestmech;
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ /* AES key template */
+ sAESKeyTemplate[0].type = CKA_CLASS;
+ sAESKeyTemplate[0].pValue = &class;
+ sAESKeyTemplate[0].ulValueLen = sizeof(class);
+ sAESKeyTemplate[1].type = CKA_KEY_TYPE;
+ sAESKeyTemplate[1].pValue = &keyAESType;
+ sAESKeyTemplate[1].ulValueLen = sizeof(keyAESType);
+ sAESKeyTemplate[2].type = CKA_LABEL;
+ sAESKeyTemplate[2].pValue = AESlabel;
+ sAESKeyTemplate[2].ulValueLen = sizeof(AESlabel) - 1;
+ sAESKeyTemplate[3].type = CKA_ENCRYPT;
+ sAESKeyTemplate[3].pValue = &true;
+ sAESKeyTemplate[3].ulValueLen = sizeof(true);
+ sAESKeyTemplate[4].type = CKA_DECRYPT;
+ sAESKeyTemplate[4].pValue = &true;
+ sAESKeyTemplate[4].ulValueLen = sizeof(true);
+ sAESKeyTemplate[5].type = CKA_SIGN;
+ sAESKeyTemplate[5].pValue = &true;
+ sAESKeyTemplate[5].ulValueLen = sizeof(true);
+ sAESKeyTemplate[6].type = CKA_VERIFY;
+ sAESKeyTemplate[6].pValue = &true;
+ sAESKeyTemplate[6].ulValueLen = sizeof(true);
+ sAESKeyTemplate[7].type = CKA_UNWRAP;
+ sAESKeyTemplate[7].pValue = &true;
+ sAESKeyTemplate[7].ulValueLen = sizeof(true);
+ sAESKeyTemplate[8].type = CKA_VALUE_LEN;
+ sAESKeyTemplate[8].pValue = &AESvalueLen;
+ sAESKeyTemplate[8].ulValueLen = sizeof(AESvalueLen);
+
+ signmech.mechanism = CKM_SHA_1_HMAC;
+ signmech.pParameter = NULL;
+ signmech.ulParameterLen = 0;
+ digestmech.mechanism = CKM_SHA256;
+ digestmech.pParameter = NULL;
+ digestmech.ulParameterLen = 0;
+
+ plainlen = strlen((char *)plaintext);
+ plainlen_1 = strlen((char *)plaintext_1);
+ plainlen_2 = strlen((char *)plaintext_2);
+ digestlen = MAX_DIGEST_SZ;
+
+ crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
+ NULL, NULL, &hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Login with correct password succeeded\n");
+ } else {
+ PKM_Error("C_Login with correct password failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ PKM_LogIt("Generate an AES key ...\n");
+ /* generate an AES Secret Key */
+ crv = pFunctionList->C_GenerateKey(hSession, &sAESKeyMech,
+ sAESKeyTemplate,
+ NUM_ELEM(sAESKeyTemplate),
+ &sKey);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GenerateKey AES succeeded\n");
+ } else {
+ PKM_Error("C_GenerateKey AES failed with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_SignInit(hSession, &signmech, sKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_SignInit failed returned 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ slen = sizeof(sign);
+ crv = pFunctionList->C_Sign(hSession, (CK_BYTE_PTR)plaintext, plainlen,
+ (CK_BYTE_PTR)sign, &slen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Sign failed returned 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_DestroyObject(hSession, sKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DestroyObject failed returned 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ digestlen = MAX_DIGEST_SZ;
+ crv = pFunctionList->C_DigestInit(hSession, &digestmech);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestInit failed returned 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_DigestUpdate(hSession, (CK_BYTE_PTR)plaintext,
+ plainlen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestUpdate failed returned 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_GetOperationState(hSession, NULL, &statelen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_GetOperationState failed returned 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ pstate = (CK_BYTE_PTR)malloc(statelen * sizeof(CK_BYTE_PTR));
+ crv = pFunctionList->C_GetOperationState(hSession, pstate, &statelen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_GetOperationState failed returned 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_DigestUpdate(hSession, (CK_BYTE_PTR)plaintext_1,
+ plainlen_1);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestUpdate failed returned 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_DigestUpdate(hSession, (CK_BYTE_PTR)plaintext_2,
+ plainlen_2);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestUpdate failed returned 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /*
+ * This will override/negate the above 2 digest_update
+ * operations
+ */
+ crv = pFunctionList->C_SetOperationState(hSession, pstate, statelen,
+ 0, 0);
+ if (crv != CKR_OK) {
+ PKM_Error("C_SetOperationState failed returned 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_DigestFinal(hSession, (CK_BYTE_PTR)digest,
+ &digestlen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestFinal failed returned 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ digestlen = MAX_DIGEST_SZ;
+ crv = pFunctionList->C_DigestInit(hSession, &digestmech);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestInit failed returned 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_Digest(hSession, (CK_BYTE_PTR)plaintext, plainlen,
+ (CK_BYTE_PTR)digest_1, &digestlen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Digest failed returned 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ if (memcmp(digest, digest_1, digestlen) == 0) {
+ PKM_LogIt("Digest and digest_1 are equal!\n");
+ } else {
+ PKM_Error("Digest and digest_1 are not equal!\n");
+ }
+ crv = pFunctionList->C_Logout(hSession);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Logout succeeded\n");
+ } else {
+ PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_CloseSession(hSession);
+ if (CKR_OK != crv) {
+ PKM_Error("C_CloseSession(%lu) returned 0x%08X, %-26s\n",
+ hSession, crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ return crv;
+}
+
+/*
+* Recover Functions
+*/
+CK_RV
+PKM_RecoverFunctions(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hPubKey, CK_OBJECT_HANDLE hPrivKey,
+ CK_MECHANISM *signMech, const CK_BYTE *pData,
+ CK_ULONG pDataLen)
+{
+ CK_RV crv = CKR_OK;
+ CK_BYTE sig[MAX_SIG_SZ];
+ CK_ULONG sigLen = MAX_SIG_SZ;
+ CK_BYTE recover[MAX_SIG_SZ];
+ CK_ULONG recoverLen = MAX_SIG_SZ;
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ /* initializes a signature operation,
+ * where the data can be recovered from the signature
+ */
+ crv = pFunctionList->C_SignRecoverInit(hSession, signMech,
+ hPrivKey);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_SignRecoverInit succeeded. \n");
+ } else {
+ PKM_Error("C_SignRecoverInit failed.\n"
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* signs single-part data,
+ * where the data can be recovered from the signature
+ */
+ crv = pFunctionList->C_SignRecover(hSession, (CK_BYTE *)pData,
+ pDataLen,
+ (CK_BYTE *)sig, &sigLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_SignRecover succeeded. \n");
+ } else {
+ PKM_Error("C_SignRecoverInit failed to create an RSA key pair.\n"
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /*
+ * initializes a verification operation
+ *where the data is recovered from the signature
+ */
+ crv = pFunctionList->C_VerifyRecoverInit(hSession, signMech,
+ hPubKey);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_VerifyRecoverInit succeeded. \n");
+ } else {
+ PKM_Error("C_VerifyRecoverInit failed.\n"
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /*
+ * verifies a signature on single-part data,
+ * where the data is recovered from the signature
+ */
+ crv = pFunctionList->C_VerifyRecover(hSession, (CK_BYTE *)sig,
+ sigLen,
+ (CK_BYTE *)recover, &recoverLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_VerifyRecover succeeded. \n");
+ } else {
+ PKM_Error("C_VerifyRecover failed.\n"
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ if ((recoverLen == pDataLen) &&
+ (memcmp(recover, pData, pDataLen) == 0)) {
+ PKM_LogIt("VerifyRecover test case passed\n");
+ } else {
+ PKM_Error("VerifyRecover test case failed\n");
+ }
+
+ return crv;
+}
+/*
+* wrapUnwrap
+* wrap the secretkey with the public key.
+* unwrap the secretkey with the private key.
+*/
+CK_RV
+PKM_wrapUnwrap(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hPublicKey,
+ CK_OBJECT_HANDLE hPrivateKey,
+ CK_MECHANISM *wrapMechanism,
+ CK_OBJECT_HANDLE hSecretKey,
+ CK_ATTRIBUTE *sKeyTemplate,
+ CK_ULONG skeyTempSize)
+{
+ CK_RV crv = CKR_OK;
+ CK_OBJECT_HANDLE hSecretKeyUnwrapped = CK_INVALID_HANDLE;
+ CK_BYTE wrappedKey[128];
+ CK_ULONG ulWrappedKeyLen = 0;
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ ulWrappedKeyLen = sizeof(wrappedKey);
+ crv = pFunctionList->C_WrapKey(
+ hSession, wrapMechanism,
+ hPublicKey, hSecretKey,
+ wrappedKey, &ulWrappedKeyLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_WrapKey succeeded\n");
+ } else {
+ PKM_Error("C_WrapKey failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_UnwrapKey(
+ hSession, wrapMechanism, hPrivateKey,
+ wrappedKey, ulWrappedKeyLen, sKeyTemplate,
+ skeyTempSize,
+ &hSecretKeyUnwrapped);
+ if ((crv == CKR_OK) && (hSecretKeyUnwrapped != CK_INVALID_HANDLE)) {
+ PKM_LogIt("C_UnwrapKey succeeded\n");
+ } else {
+ PKM_Error("C_UnwrapKey failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ return crv;
+}
+
+/*
+ * Tests if the object's attributes match the expected_attrs
+ */
+CK_RV
+PKM_AttributeCheck(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_PTR expected_attrs,
+ CK_ULONG expected_attrs_count)
+{
+ CK_RV crv;
+ CK_ATTRIBUTE_PTR tmp_attrs;
+ unsigned int i;
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ /* First duplicate the themplate */
+ tmp_attrs = malloc(expected_attrs_count * sizeof(CK_ATTRIBUTE));
+
+ if (tmp_attrs == NULL) {
+ PKM_Error("Internal test memory failure\n");
+ return (CKR_HOST_MEMORY);
+ }
+
+ for (i = 0; i < expected_attrs_count; i++) {
+ tmp_attrs[i].type = expected_attrs[i].type;
+ tmp_attrs[i].ulValueLen = expected_attrs[i].ulValueLen;
+
+ /* Don't give away the expected one. just zeros */
+ tmp_attrs[i].pValue = calloc(expected_attrs[i].ulValueLen, 1);
+
+ if (tmp_attrs[i].pValue == NULL) {
+ unsigned int j;
+ for (j = 0; j < i; j++)
+ free(tmp_attrs[j].pValue);
+
+ free(tmp_attrs);
+ printf("Internal test memory failure\n");
+ return (CKR_HOST_MEMORY);
+ }
+ }
+
+ /* then get the attributes from the object */
+ crv = pFunctionList->C_GetAttributeValue(hSession, obj, tmp_attrs,
+ expected_attrs_count);
+ if (crv != CKR_OK) {
+ PKM_Error("C_GetAttributeValue failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ crv = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+
+ /* Finally compare with the expected ones */
+ for (i = 0; i < expected_attrs_count; i++) {
+
+ if (memcmp(tmp_attrs[i].pValue, expected_attrs[i].pValue,
+ expected_attrs[i].ulValueLen) != 0) {
+ PKM_LogIt("comparing attribute type 0x%x with expected 0x%x\n",
+ tmp_attrs[i].type, expected_attrs[i].type);
+ PKM_LogIt("comparing attribute type value 0x%x with expected 0x%x\n",
+ tmp_attrs[i].pValue, expected_attrs[i].pValue);
+ /* don't report error at this time */
+ }
+ }
+
+out:
+ for (i = 0; i < expected_attrs_count; i++)
+ free(tmp_attrs[i].pValue);
+ free(tmp_attrs);
+ return (crv);
+}
+
+/*
+ * Check the validity of a mech
+ */
+CK_RV
+PKM_MechCheck(CK_FUNCTION_LIST_PTR pFunctionList, CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_TYPE mechType, CK_FLAGS flags,
+ CK_BBOOL check_sizes, CK_ULONG minkeysize, CK_ULONG maxkeysize)
+{
+ CK_SESSION_INFO sess_info;
+ CK_MECHANISM_INFO mech_info;
+ CK_RV crv;
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ if ((crv = pFunctionList->C_GetSessionInfo(hSession, &sess_info)) !=
+ CKR_OK) {
+ PKM_Error("C_GetSessionInfo failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return (CKR_FUNCTION_FAILED);
+ }
+
+ crv = pFunctionList->C_GetMechanismInfo(0, mechType,
+ &mech_info);
+
+ crv = pFunctionList->C_GetMechanismInfo(sess_info.slotID, mechType,
+ &mech_info);
+
+ if (crv != CKR_OK) {
+ PKM_Error("C_GetMechanismInfo failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return (CKR_FUNCTION_FAILED);
+ }
+
+ if ((mech_info.flags & flags) == 0) {
+ PKM_Error("0x%x flag missing from mech\n", flags);
+ return (CKR_MECHANISM_INVALID);
+ }
+ if (!check_sizes)
+ return (CKR_OK);
+
+ if (mech_info.ulMinKeySize != minkeysize) {
+ PKM_Error("Bad MinKeySize %d expected %d\n", mech_info.ulMinKeySize,
+ minkeysize);
+ return (CKR_MECHANISM_INVALID);
+ }
+ if (mech_info.ulMaxKeySize != maxkeysize) {
+ PKM_Error("Bad MaxKeySize %d expected %d\n", mech_info.ulMaxKeySize,
+ maxkeysize);
+ return (CKR_MECHANISM_INVALID);
+ }
+ return (CKR_OK);
+}
+
+/*
+ * Can be called with a non-null premaster_key_len for the
+ * *_DH mechanisms. In that case, no checking for the matching of
+ * the expected results is done.
+ * The rnd argument tells which correct/bogus randomInfo to use.
+ */
+CK_RV
+PKM_TLSMasterKeyDerive(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen,
+ CK_MECHANISM_TYPE mechType,
+ enum_random_t rnd)
+{
+ CK_SESSION_HANDLE hSession;
+ CK_RV crv;
+ CK_MECHANISM mk_mech;
+ CK_VERSION version;
+ CK_OBJECT_CLASS class = CKO_SECRET_KEY;
+ CK_KEY_TYPE type = CKK_GENERIC_SECRET;
+ CK_BBOOL derive_bool = true;
+ CK_ATTRIBUTE attrs[4];
+ CK_ULONG attrs_count = 4;
+ CK_OBJECT_HANDLE pmk_obj = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE mk_obj = CK_INVALID_HANDLE;
+ CK_SSL3_MASTER_KEY_DERIVE_PARAMS mkd_params;
+ CK_MECHANISM skmd_mech;
+
+ CK_BBOOL isDH = false;
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ attrs[0].type = CKA_CLASS;
+ attrs[0].pValue = &class;
+ attrs[0].ulValueLen = sizeof(class);
+ attrs[1].type = CKA_KEY_TYPE;
+ attrs[1].pValue = &type;
+ attrs[1].ulValueLen = sizeof(type);
+ attrs[2].type = CKA_DERIVE;
+ attrs[2].pValue = &derive_bool;
+ attrs[2].ulValueLen = sizeof(derive_bool);
+ attrs[3].type = CKA_VALUE;
+ attrs[3].pValue = NULL;
+ attrs[3].ulValueLen = 0;
+
+ crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
+ NULL, NULL, &hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Login with correct password succeeded\n");
+ } else {
+ PKM_Error("C_Login with correct password failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* Before all, check if the mechanism is supported correctly */
+ if (MODE == FIPSMODE) {
+ crv = PKM_MechCheck(pFunctionList, hSession, mechType, CKF_DERIVE, false,
+ 0, 0);
+ if (crv != CKR_OK) {
+ PKM_Error("PKM_MechCheck failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return (crv);
+ }
+ }
+
+ mk_mech.mechanism = mechType;
+ mk_mech.pParameter = &mkd_params;
+ mk_mech.ulParameterLen = sizeof(mkd_params);
+
+ switch (mechType) {
+ case CKM_TLS_MASTER_KEY_DERIVE_DH:
+ isDH = true;
+ /* FALLTHRU */
+ case CKM_TLS_MASTER_KEY_DERIVE:
+ attrs[3].pValue = NULL;
+ attrs[3].ulValueLen = 0;
+
+ mkd_params.RandomInfo.pClientRandom = (unsigned char *)TLSClientRandom;
+ mkd_params.RandomInfo.ulClientRandomLen =
+ sizeof(TLSClientRandom);
+ mkd_params.RandomInfo.pServerRandom = (unsigned char *)TLSServerRandom;
+ mkd_params.RandomInfo.ulServerRandomLen =
+ sizeof(TLSServerRandom);
+ break;
+ }
+ mkd_params.pVersion = (!isDH) ? &version : NULL;
+
+ /* First create the pre-master secret key */
+
+ skmd_mech.mechanism = CKM_SSL3_PRE_MASTER_KEY_GEN;
+ skmd_mech.pParameter = &mkd_params;
+ skmd_mech.ulParameterLen = sizeof(mkd_params);
+
+ crv = pFunctionList->C_GenerateKey(hSession, &skmd_mech,
+ attrs,
+ attrs_count,
+ &pmk_obj);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GenerateKey succeeded\n");
+ } else {
+ PKM_Error("C_GenerateKey failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ /* Test the bad cases */
+ switch (rnd) {
+ case CORRECT:
+ goto correct;
+
+ case BOGUS_CLIENT_RANDOM:
+ mkd_params.RandomInfo.pClientRandom = NULL;
+ break;
+
+ case BOGUS_CLIENT_RANDOM_LEN:
+ mkd_params.RandomInfo.ulClientRandomLen = 0;
+ break;
+
+ case BOGUS_SERVER_RANDOM:
+ mkd_params.RandomInfo.pServerRandom = NULL;
+ break;
+
+ case BOGUS_SERVER_RANDOM_LEN:
+ mkd_params.RandomInfo.ulServerRandomLen = 0;
+ break;
+ }
+ crv = pFunctionList->C_DeriveKey(hSession, &mk_mech, pmk_obj, NULL, 0,
+ &mk_obj);
+ if (crv != CKR_MECHANISM_PARAM_INVALID) {
+ PKM_LogIt("C_DeriveKey returned as EXPECTED with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ } else {
+ PKM_Error("C_DeriveKey did not fail with bad data \n");
+ }
+ goto out;
+
+correct:
+ /* Now derive the master secret key */
+ crv = pFunctionList->C_DeriveKey(hSession, &mk_mech, pmk_obj, NULL, 0,
+ &mk_obj);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_DeriveKey succeeded\n");
+ } else {
+ PKM_Error("C_DeriveKey failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+out:
+ if (pmk_obj != CK_INVALID_HANDLE)
+ (void)pFunctionList->C_DestroyObject(hSession, pmk_obj);
+ if (mk_obj != CK_INVALID_HANDLE)
+ (void)pFunctionList->C_DestroyObject(hSession, mk_obj);
+ crv = pFunctionList->C_Logout(hSession);
+
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Logout succeeded\n");
+ } else {
+ PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_CloseSession(hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ return (crv);
+}
+
+CK_RV
+PKM_TLSKeyAndMacDerive(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SLOT_ID *pSlotList, CK_ULONG slotID,
+ CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen,
+ CK_MECHANISM_TYPE mechType, enum_random_t rnd)
+{
+ CK_SESSION_HANDLE hSession;
+ CK_RV crv;
+ CK_MECHANISM kmd_mech;
+ CK_MECHANISM skmd_mech;
+ CK_OBJECT_CLASS class = CKO_SECRET_KEY;
+ CK_KEY_TYPE type = CKK_GENERIC_SECRET;
+ CK_BBOOL derive_bool = true;
+ CK_BBOOL sign_bool = true, verify_bool = true;
+ CK_BBOOL encrypt_bool = true, decrypt_bool = true;
+ CK_ULONG value_len;
+
+ /*
+ * We arrange this template so that:
+ * . Attributes 0-6 are good for a MAC key comparison template.
+ * . Attributes 2-5 are good for the master key creation template.
+ * . Attributes 3-8 are good for a cipher key comparison template.
+ */
+ CK_ATTRIBUTE attrs[9];
+
+ CK_OBJECT_HANDLE mk_obj = CK_INVALID_HANDLE;
+ CK_SSL3_KEY_MAT_PARAMS km_params;
+ CK_SSL3_KEY_MAT_OUT kmo;
+ CK_BYTE IVClient[8];
+ CK_BYTE IVServer[8];
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ attrs[0].type = CKA_SIGN;
+ attrs[0].pValue = &sign_bool;
+ attrs[0].ulValueLen = sizeof(sign_bool);
+ attrs[1].type = CKA_VERIFY;
+ attrs[1].pValue = &verify_bool;
+ attrs[1].ulValueLen = sizeof(verify_bool);
+ attrs[2].type = CKA_KEY_TYPE;
+ attrs[2].pValue = &type;
+ attrs[2].ulValueLen = sizeof(type);
+ attrs[3].type = CKA_CLASS;
+ attrs[3].pValue = &class;
+ attrs[3].ulValueLen = sizeof(class);
+ attrs[4].type = CKA_DERIVE;
+ attrs[4].pValue = &derive_bool;
+ attrs[4].ulValueLen = sizeof(derive_bool);
+ attrs[5].type = CKA_VALUE;
+ attrs[5].pValue = NULL;
+ attrs[5].ulValueLen = 0;
+ attrs[6].type = CKA_VALUE_LEN;
+ attrs[6].pValue = &value_len;
+ attrs[6].ulValueLen = sizeof(value_len);
+ attrs[7].type = CKA_ENCRYPT;
+ attrs[7].pValue = &encrypt_bool;
+ attrs[7].ulValueLen = sizeof(encrypt_bool);
+ attrs[8].type = CKA_DECRYPT;
+ attrs[8].pValue = &decrypt_bool;
+ attrs[8].ulValueLen = sizeof(decrypt_bool);
+
+ crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
+ NULL, NULL, &hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Login with correct password succeeded\n");
+ } else {
+ PKM_Error("C_Login with correct password failed "
+ "with 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* Before all, check if the mechanism is supported correctly */
+ if (MODE == FIPSMODE) {
+ crv = PKM_MechCheck(pFunctionList, hSession, mechType, CKF_DERIVE,
+ CK_TRUE, 48, 48);
+
+ if (crv != CKR_OK) {
+ PKM_Error("PKM_MechCheck failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return (crv);
+ }
+ }
+ kmd_mech.mechanism = mechType;
+ kmd_mech.pParameter = &km_params;
+ kmd_mech.ulParameterLen = sizeof(km_params);
+
+ km_params.ulMacSizeInBits = 128; /* an MD5 based MAC */
+ km_params.ulKeySizeInBits = 192; /* 3DES key size */
+ km_params.ulIVSizeInBits = 64; /* 3DES block size */
+ km_params.pReturnedKeyMaterial = &kmo;
+ km_params.bIsExport = false;
+ kmo.hClientMacSecret = CK_INVALID_HANDLE;
+ kmo.hServerMacSecret = CK_INVALID_HANDLE;
+ kmo.hClientKey = CK_INVALID_HANDLE;
+ kmo.hServerKey = CK_INVALID_HANDLE;
+ kmo.pIVClient = IVClient;
+ kmo.pIVServer = IVServer;
+
+ skmd_mech.mechanism = CKM_SSL3_PRE_MASTER_KEY_GEN;
+ skmd_mech.pParameter = &km_params;
+ skmd_mech.ulParameterLen = sizeof(km_params);
+
+ crv = pFunctionList->C_GenerateKey(hSession, &skmd_mech,
+ &attrs[2],
+ 4,
+ &mk_obj);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_GenerateKey succeeded\n");
+ } else {
+ PKM_Error("C_GenerateKey failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ attrs[5].pValue = NULL;
+ attrs[5].ulValueLen = 0;
+
+ km_params.RandomInfo.pClientRandom = (unsigned char *)TLSClientRandom;
+ km_params.RandomInfo.ulClientRandomLen =
+ sizeof(TLSClientRandom);
+ km_params.RandomInfo.pServerRandom = (unsigned char *)TLSServerRandom;
+ km_params.RandomInfo.ulServerRandomLen =
+ sizeof(TLSServerRandom);
+
+ /* Test the bad cases */
+ switch (rnd) {
+ case CORRECT:
+ goto correct;
+
+ case BOGUS_CLIENT_RANDOM:
+ km_params.RandomInfo.pClientRandom = NULL;
+ break;
+
+ case BOGUS_CLIENT_RANDOM_LEN:
+ km_params.RandomInfo.ulClientRandomLen = 0;
+ break;
+
+ case BOGUS_SERVER_RANDOM:
+ km_params.RandomInfo.pServerRandom = NULL;
+ break;
+
+ case BOGUS_SERVER_RANDOM_LEN:
+ km_params.RandomInfo.ulServerRandomLen = 0;
+ break;
+ }
+ crv = pFunctionList->C_DeriveKey(hSession, &kmd_mech, mk_obj, NULL, 0,
+ NULL);
+ if (crv != CKR_MECHANISM_PARAM_INVALID) {
+ PKM_Error("key materials derivation returned unexpected "
+ "error 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ (void)pFunctionList->C_DestroyObject(hSession, mk_obj);
+ return (CKR_FUNCTION_FAILED);
+ }
+ return (CKR_OK);
+
+correct:
+ /*
+ * Then use the master key and the client 'n server random data to
+ * derive the key materials
+ */
+ crv = pFunctionList->C_DeriveKey(hSession, &kmd_mech, mk_obj, NULL, 0,
+ NULL);
+ if (crv != CKR_OK) {
+ PKM_Error("Cannot derive the key materials, crv 0x%08X, %-26s\n",
+ crv, PKM_CK_RVtoStr(crv));
+ (void)pFunctionList->C_DestroyObject(hSession, mk_obj);
+ return (crv);
+ }
+
+ if (mk_obj != CK_INVALID_HANDLE)
+ (void)pFunctionList->C_DestroyObject(hSession, mk_obj);
+ if (kmo.hClientMacSecret != CK_INVALID_HANDLE)
+ (void)pFunctionList->C_DestroyObject(hSession, kmo.hClientMacSecret);
+ if (kmo.hServerMacSecret != CK_INVALID_HANDLE)
+ (void)pFunctionList->C_DestroyObject(hSession, kmo.hServerMacSecret);
+ if (kmo.hClientKey != CK_INVALID_HANDLE)
+ (void)pFunctionList->C_DestroyObject(hSession, kmo.hClientKey);
+ if (kmo.hServerKey != CK_INVALID_HANDLE)
+ (void)pFunctionList->C_DestroyObject(hSession, kmo.hServerKey);
+
+ crv = pFunctionList->C_Logout(hSession);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_Logout succeeded\n");
+ } else {
+ PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_CloseSession(hSession);
+ if (crv != CKR_OK) {
+ PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ return (crv);
+}
+
+CK_RV
+PKM_DualFuncSign(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hRwSession,
+ CK_OBJECT_HANDLE publicKey, CK_OBJECT_HANDLE privateKey,
+ CK_MECHANISM *sigMech,
+ CK_OBJECT_HANDLE secretKey, CK_MECHANISM *cryptMech,
+ const CK_BYTE *pData, CK_ULONG pDataLen)
+{
+
+ CK_RV crv = CKR_OK;
+ CK_BYTE encryptedData[MAX_CIPHER_SZ];
+ CK_ULONG ulEncryptedDataLen = 0;
+ CK_ULONG ulLastUpdateSize = 0;
+ CK_BYTE sig[MAX_SIG_SZ];
+ CK_ULONG ulSigLen = 0;
+ CK_BYTE data[MAX_DATA_SZ];
+ CK_ULONG ulDataLen = 0;
+
+ memset(encryptedData, 0, sizeof(encryptedData));
+ memset(sig, 0, sizeof(sig));
+ memset(data, 0, sizeof(data));
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ /* Check that the mechanism is Multi-part */
+ if (sigMech->mechanism == CKM_DSA || sigMech->mechanism == CKM_RSA_PKCS) {
+ PKM_Error("PKM_DualFuncSign must be called with a Multi-part "
+ "operation mechanism\n");
+ return CKR_DEVICE_ERROR;
+ }
+
+ /* Sign and Encrypt */
+ if (privateKey == 0 && publicKey == 0) {
+ crv = pFunctionList->C_SignInit(hRwSession, sigMech, secretKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ } else {
+ crv = pFunctionList->C_SignInit(hRwSession, sigMech, privateKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ }
+ crv = pFunctionList->C_EncryptInit(hRwSession, cryptMech, secretKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_EncryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ ulEncryptedDataLen = sizeof(encryptedData);
+ crv = pFunctionList->C_SignEncryptUpdate(hRwSession, (CK_BYTE *)pData,
+ pDataLen,
+ encryptedData,
+ &ulEncryptedDataLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Sign failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ ulLastUpdateSize = sizeof(encryptedData) - ulEncryptedDataLen;
+ crv = pFunctionList->C_EncryptFinal(hRwSession,
+ (CK_BYTE *)&encryptedData[ulEncryptedDataLen], &ulLastUpdateSize);
+ if (crv != CKR_OK) {
+ PKM_Error("C_EncryptFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ ulEncryptedDataLen = ulEncryptedDataLen + ulLastUpdateSize;
+ ulSigLen = sizeof(sig);
+ crv = pFunctionList->C_SignFinal(hRwSession, sig, &ulSigLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_SignFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* Decrypt and Verify */
+
+ crv = pFunctionList->C_DecryptInit(hRwSession, cryptMech, secretKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ crv = pFunctionList->C_VerifyInit(hRwSession, sigMech,
+ publicKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ ulDataLen = sizeof(data);
+ crv = pFunctionList->C_DecryptVerifyUpdate(hRwSession,
+ encryptedData,
+ ulEncryptedDataLen,
+ data, &ulDataLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptVerifyUpdate failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ ulLastUpdateSize = sizeof(data) - ulDataLen;
+ /* Get last little piece of plaintext. Should have length 0 */
+ crv = pFunctionList->C_DecryptFinal(hRwSession, &data[ulDataLen],
+ &ulLastUpdateSize);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ if (ulLastUpdateSize != 0) {
+ crv = pFunctionList->C_VerifyUpdate(hRwSession, &data[ulDataLen],
+ ulLastUpdateSize);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DecryptFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ }
+ ulDataLen = ulDataLen + ulLastUpdateSize;
+
+ /* input for the verify operation is the decrypted data */
+ crv = pFunctionList->C_VerifyFinal(hRwSession, sig, ulSigLen);
+ if (crv == CKR_OK) {
+ PKM_LogIt("C_VerifyFinal succeeded\n");
+ } else {
+ PKM_Error("C_VerifyFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* Comparison of Decrypted data with inputed data */
+ if ((ulDataLen == pDataLen) &&
+ (memcmp(data, pData, pDataLen) == 0)) {
+ PKM_LogIt("PKM_DualFuncSign decrypt test case passed\n");
+ } else {
+ PKM_Error("PKM_DualFuncSign derypt test case failed\n");
+ }
+
+ return crv;
+}
+
+CK_RV
+PKM_Digest(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM *digestMech, CK_OBJECT_HANDLE hSecretKey,
+ const CK_BYTE *pData, CK_ULONG pDataLen)
+{
+ CK_RV crv = CKR_OK;
+ CK_BYTE digest1[MAX_DIGEST_SZ];
+ CK_ULONG digest1Len = 0;
+ CK_BYTE digest2[MAX_DIGEST_SZ];
+ CK_ULONG digest2Len = 0;
+
+ /* Tested with CKM_SHA_1, CKM_SHA224, CKM_SHA256, CKM_SHA384, CKM_SHA512 */
+
+ memset(digest1, 0, sizeof(digest1));
+ memset(digest2, 0, sizeof(digest2));
+
+ NUMTESTS++; /* increment NUMTESTS */
+
+ crv = pFunctionList->C_DigestInit(hSession, digestMech);
+ if (crv != CKR_OK) {
+ PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ digest1Len = sizeof(digest1);
+ crv = pFunctionList->C_Digest(hSession, (CK_BYTE *)pData, pDataLen,
+ digest1, &digest1Len);
+ if (crv != CKR_OK) {
+ PKM_Error("C_Sign failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_DigestInit(hSession, digestMech);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestInit failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ crv = pFunctionList->C_DigestUpdate(hSession, (CK_BYTE *)pData, pDataLen);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestUpdate failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ /* C_DigestKey continues a multiple-part message-digesting operation by*/
+ /* digesting the value of a secret key. (only used with C_DigestUpdate)*/
+ if (hSecretKey != 0) {
+ crv = pFunctionList->C_DigestKey(hSession, hSecretKey);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestKey failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+ }
+
+ digest2Len = sizeof(digest2);
+ crv = pFunctionList->C_DigestFinal(hSession, digest2, &digest2Len);
+ if (crv != CKR_OK) {
+ PKM_Error("C_DigestFinal failed with 0x%08X, %-26s\n", crv,
+ PKM_CK_RVtoStr(crv));
+ return crv;
+ }
+
+ if (hSecretKey == 0) {
+ /* did not digest a secret key so digests should equal */
+ if ((digest1Len == digest2Len) &&
+ (memcmp(digest1, digest2, digest1Len) == 0)) {
+ PKM_LogIt("Single and Multiple-part message digest "
+ "operations successful\n");
+ } else {
+ PKM_Error("Single and Multiple-part message digest "
+ "operations failed\n");
+ }
+ } else {
+ if (digest1Len == digest2Len) {
+ PKM_LogIt("PKM_Digest Single and Multiple-part message digest "
+ "operations successful\n");
+ } else {
+ PKM_Error("PKM_Digest Single and Multiple-part message digest "
+ "operations failed\n");
+ }
+ }
+
+ return crv;
+}
+
+char *
+PKM_FilePasswd(char *pwFile)
+{
+ unsigned char phrase[200];
+ PRFileDesc *fd;
+ PRInt32 nb;
+ int i;
+
+ if (!pwFile)
+ return 0;
+
+ fd = PR_Open(pwFile, PR_RDONLY, 0);
+ if (!fd) {
+ fprintf(stderr, "No password file \"%s\" exists.\n", pwFile);
+ return NULL;
+ }
+
+ nb = PR_Read(fd, phrase, sizeof(phrase));
+
+ PR_Close(fd);
+ /* handle the Windows EOL case */
+ i = 0;
+ while (phrase[i] != '\r' && phrase[i] != '\n' && i < nb)
+ i++;
+ phrase[i] = '\0';
+ if (nb == 0) {
+ fprintf(stderr, "password file contains no data\n");
+ return NULL;
+ }
+ return (char *)strdup((char *)phrase);
+}
+
+void
+PKM_Help()
+{
+ PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
+ PR_fprintf(debug_out, "pk11mode test program usage:\n");
+ PR_fprintf(debug_out, "\t-f <file> Password File : echo pw > file \n");
+ PR_fprintf(debug_out, "\t-F Disable Unix fork tests\n");
+ PR_fprintf(debug_out, "\t-n Non Fips Mode \n");
+ PR_fprintf(debug_out, "\t-d <path> Database path location\n");
+ PR_fprintf(debug_out, "\t-p <prefix> DataBase prefix\n");
+ PR_fprintf(debug_out, "\t-v verbose\n");
+ PR_fprintf(debug_out, "\t-h this help message\n");
+ exit(1);
+}
+
+void
+PKM_CheckPath(char *string)
+{
+ char *src;
+ char *dest;
+
+ /*
+ * windows support convert any back slashes to
+ * forward slashes.
+ */
+ for (src = string, dest = string; *src; src++, dest++) {
+ if (*src == '\\') {
+ *dest = '/';
+ }
+ }
+ dest--;
+ /* if the last char is a / set it to 0 */
+ if (*dest == '/')
+ *dest = 0;
+}
+
+CK_RV
+PKM_ForkCheck(int expected, CK_FUNCTION_LIST_PTR fList,
+ PRBool forkAssert, CK_C_INITIALIZE_ARGS_NSS *initArgs)
+{
+ CK_RV crv = CKR_OK;
+#ifndef NO_FORK_CHECK
+ int rc = -1;
+ pid_t child, ret;
+ NUMTESTS++; /* increment NUMTESTS */
+ if (forkAssert) {
+ putenv("NSS_STRICT_NOFORK=1");
+ } else {
+ putenv("NSS_STRICT_NOFORK=0");
+ }
+ child = fork();
+ switch (child) {
+ case -1:
+ PKM_Error("Fork failed.\n");
+ crv = CKR_DEVICE_ERROR;
+ break;
+ case 0:
+ if (fList) {
+ if (!initArgs) {
+ /* If softoken is loaded, make a PKCS#11 call to C_GetTokenInfo
+ * in the child. This call should always fail.
+ * If softoken is uninitialized,
+ * it fails with CKR_CRYPTOKI_NOT_INITIALIZED.
+ * If it was initialized in the parent, the fork check should
+ * kick in, and make it return CKR_DEVICE_ERROR.
+ */
+ CK_RV child_crv = fList->C_GetTokenInfo(0, NULL);
+ exit(child_crv & 255);
+ } else {
+ /* If softoken is loaded, make a PKCS#11 call to C_Initialize
+ * in the child. This call should always fail.
+ * If softoken is uninitialized, this should succeed.
+ * If it was initialized in the parent, the fork check should
+ * kick in, and make it return CKR_DEVICE_ERROR.
+ */
+ CK_RV child_crv = fList->C_Initialize(initArgs);
+ if (CKR_OK == child_crv) {
+ child_crv = fList->C_Finalize(NULL);
+ }
+ exit(child_crv & 255);
+ }
+ }
+ exit(expected & 255);
+ default:
+ PKM_LogIt("Fork succeeded.\n");
+ ret = wait(&rc);
+ if (ret != child || (!WIFEXITED(rc)) ||
+ ((expected & 255) != (WEXITSTATUS(rc) & 255))) {
+ int retStatus = -1;
+ if (WIFEXITED(rc)) {
+ retStatus = WEXITSTATUS(rc);
+ }
+ PKM_Error("Child misbehaved.\n");
+ printf("Child return status : %d.\n", retStatus & 255);
+ crv = CKR_DEVICE_ERROR;
+ }
+ break;
+ }
+#endif
+ return crv;
+}
diff --git a/security/nss/cmd/pk11mode/pk11mode.gyp b/security/nss/cmd/pk11mode/pk11mode.gyp
new file mode 100644
index 000000000..ed042c183
--- /dev/null
+++ b/security/nss/cmd/pk11mode/pk11mode.gyp
@@ -0,0 +1,24 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pk11mode',
+ 'type': 'executable',
+ 'sources': [
+ 'pk11mode.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/pk11util/Makefile b/security/nss/cmd/pk11util/Makefile
new file mode 100644
index 000000000..74ae20020
--- /dev/null
+++ b/security/nss/cmd/pk11util/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/pk11util/manifest.mn b/security/nss/cmd/pk11util/manifest.mn
new file mode 100644
index 000000000..ca818aad4
--- /dev/null
+++ b/security/nss/cmd/pk11util/manifest.mn
@@ -0,0 +1,23 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = pk11util.c
+#CSRCS = symkeytest.c
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd
+
+PROGRAM = pk11util
+#PROGRAM = symkeytest
+
+#USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/pk11util/pk11util.c b/security/nss/cmd/pk11util/pk11util.c
new file mode 100644
index 000000000..bd1ea2bcd
--- /dev/null
+++ b/security/nss/cmd/pk11util/pk11util.c
@@ -0,0 +1,2240 @@
+/* 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/. */
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(WIN32)
+#undef __STDC__
+#include "fcntl.h"
+#include "io.h"
+#include <fcntl.h>
+#else
+#include <unistd.h>
+#include <fcntl.h>
+#endif
+
+#include "secutil.h"
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+#include "prinrval.h"
+#include "prenv.h"
+
+#include "pkcs11.h"
+
+#include "pk11table.h"
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+CK_ULONG systemFlags;
+#define FLAG_NEGATE 0x80000000
+#define FLAG_Verify 0x00000001
+#define FLAG_VerifyFile 0x00000002
+#define CKR_QUIT 0x80000000
+
+int ArgSize(ArgType type);
+const char *constLookup(const char *bp, CK_ULONG *value, ConstType *type);
+
+int
+isNum(char c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+int
+isConst(const char *c)
+{
+ CK_ULONG value;
+ ConstType type;
+
+ constLookup(c, &value, &type);
+ return type != ConstNone;
+}
+
+/*
+ * see if the variable is really a 'size' function. This
+ * function may modify var if it is a size function.
+ */
+char *
+isSize(char *var, int *isArray)
+{
+ char *ptr = NULL;
+ char *end;
+ int array = 0;
+
+ if (PL_strncasecmp(var, "sizeof(", /*)*/ 7) == 0) {
+ ptr = var + 7;
+ } else if (PL_strncasecmp(var, "size(", /*)*/ 5) == 0) {
+ ptr = var + 5;
+ } else if (PL_strncasecmp(var, "sizeofarray(", /*)*/ 12) == 0) {
+ ptr = var + 12;
+ array = 1;
+ } else if (PL_strncasecmp(var, "sizea(", /*)*/ 6) == 0) {
+ ptr = var + 6;
+ array = 1;
+ } else {
+ return NULL;
+ }
+ end = strchr(ptr, /*(*/ ')');
+ if (end == NULL) {
+ return NULL;
+ }
+ if (isArray)
+ *isArray = array;
+ *end = 0;
+ return ptr;
+}
+
+void
+printConst(CK_ULONG value, ConstType type, int newLine)
+{
+ int i;
+
+ for (i = 0; i < constCount; i++) {
+ if (consts[i].type == type && consts[i].value == value) {
+ printf("%s", consts[i].name);
+ break;
+ }
+ if (type == ConstNone && consts[i].value == value) {
+ printf("%s", consts[i].name);
+ break;
+ }
+ }
+ if (i == constCount) {
+ if ((type == ConstAvailableSizes) || (type == ConstCurrentSize)) {
+ printf("%lu", value);
+ } else {
+ printf("Unknown %s (%lu:0x%lx)", constTypeString[type], value, value);
+ }
+ }
+ if (newLine) {
+ printf("\n");
+ }
+}
+
+ConstType
+getConstFromAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ int i;
+
+ for (i = 0; i < constCount; i++) {
+ if (consts[i].type == ConstAttribute && consts[i].value == type) {
+ return consts[i].attrType;
+ }
+ }
+ return ConstNone;
+}
+
+void
+printChars(const char *name, CK_ULONG size)
+{
+ CK_ULONG i;
+ for (i = 0; i < size; i++) {
+ if (name[i] == 0) {
+ break;
+ }
+ printf("%c", name[i]);
+ }
+ printf("\n");
+}
+
+#define DUMP_LEN 16
+void
+printDump(const unsigned char *buf, int size)
+{
+ int i, j;
+
+ for (i = 0; i < size; i += DUMP_LEN) {
+ printf(" ");
+ for (j = 0; j < DUMP_LEN; j++) {
+ if (i + j < size) {
+ printf("%02x ", buf[i + j]);
+ } else {
+ printf(" ");
+ }
+ }
+ for (j = 0; j < DUMP_LEN; j++) {
+ if (i + j < size) {
+ if (buf[i + j] < ' ' || buf[i + j] >= 0x7f) {
+ printf(".");
+ } else {
+ printf("%c", buf[i + j]);
+ }
+ } else {
+ printf(" ");
+ }
+ }
+ printf("\n");
+ }
+}
+
+/*
+ * free an argument structure
+ */
+void
+argFreeData(Value *arg)
+{
+ if (arg->data && ((arg->type & ArgStatic) == 0)) {
+ if ((arg->type & ArgMask) == ArgAttribute) {
+ int i;
+ CK_ATTRIBUTE *template = (CK_ATTRIBUTE *)arg->data;
+
+ for (i = 0; i < arg->arraySize; i++) {
+ free(template[i].pValue);
+ }
+ }
+ if ((arg->type & ArgMask) == ArgInitializeArgs) {
+ CK_C_INITIALIZE_ARGS *init = (CK_C_INITIALIZE_ARGS *)arg->data;
+ if (init->LibraryParameters) {
+ free(init->LibraryParameters);
+ }
+ }
+ free(arg->data);
+ }
+ arg->type &= ~ArgStatic;
+ arg->data = NULL;
+}
+
+void
+argFree(Value *arg)
+{
+ if (arg == NULL)
+ return;
+
+ arg->reference--;
+ if (arg->reference == 0) {
+ if (arg->type & ArgFile) {
+ free(arg->filename);
+ }
+ argFreeData(arg);
+ free(arg);
+ }
+}
+
+/*
+ * free and argument list
+ */
+void
+parseFree(Value **ap)
+{
+ int i;
+ for (i = 0; i < MAX_ARGS; i++) {
+ argFree(ap[i]);
+ }
+}
+
+/*
+ * getEnd: how for to the end of this argmument list?
+ */
+int
+getEnd(const char *bp)
+{
+ int count = 0;
+
+ while (*bp) {
+ if (*bp == ' ' || *bp == '\t' || *bp == '\n')
+ return count;
+ count++;
+ bp++;
+ }
+ return (count);
+}
+
+/*
+ * strip: return the first none white space character
+ */
+const char *
+strip(const char *bp)
+{
+ while (*bp && (*bp == ' ' || *bp == '\t' || *bp == '\n'))
+ bp++;
+ return bp;
+}
+
+/*
+ * read in the next argument into dp ... don't overflow
+ */
+const char *
+readChars(const char *bp, char *dp, int max)
+{
+ int count = 1;
+ while (*bp) {
+ if (*bp == ' ' || *bp == '\t' || *bp == '\n') {
+ *dp = 0;
+ return bp;
+ }
+ *dp++ = *bp++;
+ if (++count == max)
+ break;
+ }
+ while (*bp && (*bp != ' ' && *bp != '\t' && *bp != '\n'))
+ bp++;
+ *dp = 0;
+ return (bp);
+}
+
+Value *varLookup(const char *bp, char *vname, int max, int *error);
+
+CK_ULONG
+getValue(const char *v, int *error)
+{
+ Value *varVal = NULL;
+ CK_ULONG retVal = 0;
+ ConstType type;
+ char tvar[512];
+
+ *error = 0;
+
+ varVal = varLookup(v, tvar, sizeof(tvar), error);
+
+ if (varVal) {
+ if ((varVal->type & ArgMask) == ArgULong) {
+ retVal = *(CK_ULONG *)varVal->data;
+ } else {
+ fprintf(stderr, "%s: is not a ulong\n", v);
+ *error = 1;
+ }
+ argFree(varVal);
+ return retVal;
+ }
+ constLookup(v, &retVal, &type);
+ return retVal;
+}
+
+Value *
+NewValue(ArgType type, CK_ULONG arraySize)
+{
+ Value *value;
+
+ value = (Value *)malloc(sizeof(Value));
+ if (!value)
+ return NULL;
+ value->size = ArgSize(type) * arraySize;
+ value->type = type;
+ value->filename = NULL;
+ value->constType = ConstNone;
+ value->data = (void *)malloc(value->size);
+ if (!value->data) {
+ free(value);
+ return NULL;
+ }
+ value->reference = 1;
+ value->arraySize = (type == ArgChar) ? 1 : arraySize;
+
+ memset(value->data, 0, value->size);
+ return value;
+}
+
+#define INVALID_INDEX 0xffffffff
+
+CK_ULONG
+handleArray(char *vname, int *error)
+{
+ char *bracket;
+ CK_ULONG index = INVALID_INDEX;
+
+ if ((bracket = strchr(vname, '[')) != 0) {
+ char *tmpv = bracket + 1;
+ *bracket = 0;
+ bracket = strchr(tmpv, ']');
+
+ if (bracket == 0) {
+ fprintf(stderr, "%s: missing closing brace\n", vname);
+ return INVALID_INDEX;
+ }
+ *bracket = 0;
+
+ index = getValue(tmpv, error);
+ if (*error == 1) {
+ return INVALID_INDEX;
+ } else if (index == INVALID_INDEX) {
+ fprintf(stderr, "%s: 0x%lx is an invalid index\n", vname, index);
+ *error = 1;
+ }
+ }
+ return index;
+}
+
+void *
+makeArrayTarget(const char *vname, const Value *value, CK_ULONG index)
+{
+ char *target;
+ CK_ULONG elementSize;
+
+ if (index >= (CK_ULONG)value->arraySize) {
+ fprintf(stderr, "%s[%lu]: index larger than array size (%d)\n",
+ vname, index, value->arraySize);
+ return NULL;
+ }
+
+ target = (char *)value->data;
+ elementSize = value->size / value->arraySize;
+ target += index * elementSize;
+ return target;
+}
+
+/*
+ * look up a variable from the variable chain
+ */
+static Variable *varHead = NULL;
+Value *
+varLookup(const char *bp, char *vname, int max, int *error)
+{
+ Variable *current;
+ CK_ULONG index = INVALID_INDEX;
+ int isArray = 0;
+ char *ptr;
+ *error = 0;
+
+ if (bp != NULL) {
+ readChars(bp, vname, max);
+ }
+
+ /* don't make numbers into variables */
+ if (isNum(vname[0])) {
+ return NULL;
+ }
+ /* nor consts */
+ if (isConst(vname)) {
+ return NULL;
+ }
+ /* handle sizeof() */
+ if ((ptr = isSize(vname, &isArray)) != NULL) {
+ CK_ULONG size;
+ Value *targetValue = NULL;
+ Value *sourceValue = varLookup(NULL, ptr, 0, error);
+ if (!sourceValue) {
+ if (*error == 0) {
+ /* just didn't find it */
+ *error = 1;
+ fprintf(stderr, "Couldn't find variable %s to take size of\n",
+ ptr);
+ return NULL;
+ }
+ }
+ size = isArray ? sourceValue->arraySize : sourceValue->size;
+ targetValue = NewValue(ArgULong, 1);
+ memcpy(targetValue->data, &size, sizeof(size));
+
+ return targetValue;
+ }
+
+ /* modifies vname */
+ index = handleArray(vname, error);
+ if (*error == 1) {
+ return NULL;
+ }
+
+ for (current = varHead; current; current = current->next) {
+ if (PL_strcasecmp(current->vname, vname) == 0) {
+ char *target;
+ if (index == INVALID_INDEX) {
+ (current->value->reference)++;
+ return current->value;
+ }
+ target = makeArrayTarget(vname, current->value, index);
+ if (target) {
+ Value *element = NewValue(current->value->type, 1);
+ if (!element) {
+ fprintf(stderr, "MEMORY ERROR!\n");
+ *error = 1;
+ }
+ argFreeData(element);
+ element->data = target;
+ element->type |= ArgStatic;
+ return element;
+ }
+ *error = 1;
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+static CK_RV
+list(void)
+{
+ Variable *current;
+
+ if (varHead) {
+ printf(" %10s\t%16s\t%8s\tSize\tElements\n", "Name", "Type", "Const");
+ } else {
+ printf(" no variables set\n");
+ }
+
+ for (current = varHead; current; current = current->next) {
+ printf(" %10s\t%16s\t%8s\t%d\t%d\n", current->vname,
+ valueString[current->value->type & ArgMask],
+ constTypeString[current->value->constType],
+ current->value->size, current->value->arraySize);
+ }
+ return CKR_OK;
+}
+
+CK_RV
+printFlags(const char *s, CK_ULONG flags, ConstType type)
+{
+ CK_ULONG i;
+ int needComma = 0;
+
+ printf("%s", s);
+ for (i = 1; i; i = i << 1) {
+ if (flags & i) {
+ printf("%s", needComma ? "," : "");
+ printConst(i, type, 0);
+ needComma = 1;
+ }
+ }
+ if (!needComma) {
+ printf("Empty");
+ }
+ printf("\n");
+ return CKR_OK;
+}
+
+/*
+ * add a new variable to the chain
+ */
+const char *
+AddVariable(const char *bp, Value **ptr)
+{
+ char vname[512];
+ Variable *current;
+ int index = INVALID_INDEX;
+ int size;
+ int error = 0;
+
+ bp = readChars(bp, vname, sizeof(vname));
+
+ /* don't make numbers into variables */
+ if (isNum(vname[0])) {
+ return bp;
+ }
+ /* or consts */
+ if (isConst(vname)) {
+ return bp;
+ }
+ /* or NULLs */
+ if (vname[0] == 0) {
+ return bp;
+ }
+ /* or sizeof */
+ if (isSize(vname, NULL)) {
+ return bp;
+ }
+ /* arrays values should be written back to the original */
+ index = handleArray(vname, &error);
+ if (error == 1) {
+ return bp;
+ }
+
+ for (current = varHead; current; current = current->next) {
+ if (PL_strcasecmp(current->vname, vname) == 0) {
+ char *target;
+ /* found a complete object, return the found one */
+ if (index == INVALID_INDEX) {
+ argFree(*ptr);
+ *ptr = current->value;
+ return bp;
+ }
+ /* found an array, update the array element */
+ target = makeArrayTarget(vname, current->value, index);
+ if (target) {
+ memcpy(target, (*ptr)->data, (*ptr)->size);
+ argFreeData(*ptr);
+ (*ptr)->data = target;
+ (*ptr)->type |= ArgStatic;
+ }
+ return bp;
+ }
+ }
+
+ /* we are looking for an array and didn't find one */
+ if (index != INVALID_INDEX) {
+ return bp;
+ }
+
+ current = (Variable *)malloc(sizeof(Variable));
+ size = strlen(vname);
+ current->vname = (char *)malloc(size + 1);
+ strcpy(current->vname, vname);
+ current->value = *ptr;
+ (*ptr)->reference++;
+
+ current->next = varHead;
+ varHead = current;
+ return bp;
+}
+
+ArgType
+FindTypeByName(const char *typeName)
+{
+ int i;
+
+ for (i = 0; i < valueCount; i++) {
+ if (PL_strcasecmp(typeName, valueString[i]) == 0) {
+ return (ArgType)i;
+ }
+ if (valueString[i][0] == 'C' && valueString[i][1] == 'K' &&
+ valueString[i][2] == '_' &&
+ (PL_strcasecmp(typeName, &valueString[i][3]) == 0)) {
+ return (ArgType)i;
+ }
+ }
+ return ArgNone;
+}
+
+CK_RV
+ArrayVariable(const char *bp, const char *typeName, CK_ULONG count)
+{
+ ArgType type;
+ Value *value; /* new Value */
+
+ type = FindTypeByName(typeName);
+ if (type == ArgNone) {
+ fprintf(stderr, "Invalid type (%s)\n", typeName);
+ return CKR_FUNCTION_FAILED;
+ }
+ value = NewValue(type, count);
+ (void)AddVariable(bp, &value);
+ return CKR_OK;
+}
+
+#define MAX_TEMPLATE 25
+
+CK_RV
+ArrayTemplate(const char *bp, char *attributes)
+{
+ char aname[512];
+ CK_ULONG attributeTypes[MAX_TEMPLATE];
+ CK_ATTRIBUTE *template;
+ Value *value; /* new Value */
+ char *ap;
+ int i, count = 0;
+
+ memcpy(aname, attributes, strlen(attributes) + 1);
+
+ for (ap = aname, count = 0; ap && *ap && count < MAX_TEMPLATE; count++) {
+ char *cur = ap;
+ ConstType type;
+
+ ap = strchr(ap, ',');
+ if (ap) {
+ *ap++ = 0;
+ }
+
+ (void)constLookup(cur, &attributeTypes[count], &type);
+ if ((type != ConstAttribute) && (type != ConstNone)) {
+ fprintf(stderr, "Unknown Attribute %s\n", cur);
+ return CKR_FUNCTION_FAILED;
+ }
+ }
+
+ value = NewValue(ArgAttribute, count);
+
+ template = (CK_ATTRIBUTE *)value->data;
+ for (i = 0; i < count; i++) {
+ template[i].type = attributeTypes[i];
+ }
+ (void)AddVariable(bp, &value);
+ return CKR_OK;
+}
+
+CK_RV
+BuildTemplate(Value *vp)
+{
+ CK_ATTRIBUTE *template = (CK_ATTRIBUTE *)vp->data;
+ int i;
+
+ for (i = 0; i < vp->arraySize; i++) {
+ if (((signed long)template[i].ulValueLen) > 0) {
+ if (template[i].pValue)
+ free(template[i].pValue);
+ template[i].pValue = malloc(template[i].ulValueLen);
+ }
+ }
+ return CKR_OK;
+}
+
+CK_RV
+SetTemplate(Value *vp, CK_ULONG index, CK_ULONG value)
+{
+ CK_ATTRIBUTE *template = (CK_ATTRIBUTE *)vp->data;
+ int isbool = 0;
+ CK_ULONG len;
+ ConstType attrType;
+
+ if (index >= (CK_ULONG)vp->arraySize) {
+ fprintf(stderr, "index (%lu) greater than array (%d)\n",
+ index, vp->arraySize);
+ return CKR_ARGUMENTS_BAD;
+ }
+ attrType = getConstFromAttribute(template[index].type);
+
+ if (attrType == ConstNone) {
+ fprintf(stderr, "can't set index (%lu) because ", index);
+ printConst(template[index].type, ConstAttribute, 0);
+ fprintf(stderr, " is not a CK_BBOOL or CK_ULONG\n");
+ return CKR_ARGUMENTS_BAD;
+ }
+ isbool = (attrType == ConstBool);
+ len = isbool ? sizeof(CK_BBOOL) : sizeof(CK_ULONG);
+ if ((template[index].ulValueLen != len) || (template[index].pValue)) {
+ free(template[index].pValue);
+ template[index].pValue = malloc(len);
+ template[index].ulValueLen = len;
+ }
+ if (isbool) {
+ *(CK_BBOOL *)template[index].pValue = (CK_BBOOL)value;
+ } else {
+ *(CK_ULONG *)template[index].pValue = (CK_ULONG)value;
+ }
+ return CKR_OK;
+}
+
+CK_RV
+NewMechanism(const char *bp, CK_ULONG mechType)
+{
+ Value *value; /* new Value */
+ CK_MECHANISM *mechanism;
+
+ value = NewValue(ArgMechanism, 1);
+ mechanism = (CK_MECHANISM *)value->data;
+ mechanism->mechanism = mechType;
+ mechanism->pParameter = NULL;
+ mechanism->ulParameterLen = 0;
+ (void)AddVariable(bp, &value);
+ return CKR_OK;
+}
+
+CK_RV
+NewInitializeArgs(const char *bp, CK_ULONG flags, const char *param)
+{
+ Value *value; /* new Value */
+ CK_C_INITIALIZE_ARGS *init;
+
+ value = NewValue(ArgInitializeArgs, 1);
+ init = (CK_C_INITIALIZE_ARGS *)value->data;
+ init->flags = flags;
+ if (strcmp(param, "null") != 0) {
+ init->LibraryParameters = (CK_CHAR_PTR *)strdup(param);
+ }
+ (void)AddVariable(bp, &value);
+ return CKR_OK;
+}
+
+/*
+ * add a new variable to the chain
+ */
+CK_RV
+DeleteVariable(const char *bp)
+{
+ char vname[512];
+ Variable **current;
+
+ bp = readChars(bp, vname, sizeof(vname));
+
+ for (current = &varHead; *current; current = &(*current)->next) {
+ if (PL_strcasecmp((*current)->vname, vname) == 0) {
+ argFree((*current)->value);
+ *current = (*current)->next;
+ break;
+ }
+ }
+ return CKR_OK;
+}
+
+/*
+ * convert an octal value to integer
+ */
+CK_ULONG
+otoi(const char *o)
+{
+ CK_ULONG value = 0;
+
+ while (*o) {
+ if ((*o >= '0') && (*o <= '7')) {
+ value = (value << 3) | (unsigned)(*o - '0');
+ } else {
+ break;
+ }
+ }
+ return value;
+}
+
+/*
+ * convert a hex value to integer
+ */
+CK_ULONG
+htoi(const char *x)
+{
+ CK_ULONG value = 0;
+
+ while (*x) {
+ if ((*x >= '0') && (*x <= '9')) {
+ value = (value << 4) | (unsigned)(*x - '0');
+ } else if ((*x >= 'a') && (*x <= 'f')) {
+ value = (value << 4) | (unsigned)(*x - 'a');
+ } else if ((*x >= 'A') && (*x <= 'F')) {
+ value = (value << 4) | (unsigned)(*x - 'A');
+ } else {
+ break;
+ }
+ }
+ return value;
+}
+
+/*
+ * look up or decode a constant value
+ */
+const char *
+constLookup(const char *bp, CK_ULONG *value, ConstType *type)
+{
+ char vname[512];
+ int i;
+
+ bp = readChars(bp, vname, sizeof(vname));
+
+ for (i = 0; i < constCount; i++) {
+ if ((PL_strcasecmp(consts[i].name, vname) == 0) ||
+ PL_strcasecmp(consts[i].name + 5, vname) == 0) {
+ *value = consts[i].value;
+ *type = consts[i].type;
+ return bp;
+ }
+ }
+
+ *type = ConstNone;
+ if (vname[0] == '0' && vname[1] == 'X') {
+ *value = htoi(&vname[2]);
+ } else if (vname[0] == '0') {
+ *value = otoi(&vname[1]);
+ } else {
+ *value = atoi(vname);
+ }
+ return bp;
+}
+
+int
+ArgSize(ArgType type)
+{
+ int size = 0;
+ type &= ArgMask;
+
+ switch (type) {
+ case ArgNone:
+ size = 0;
+ break;
+ case ArgULong:
+ size = sizeof(CK_ULONG);
+ break;
+ case ArgVar:
+ size = 1; /* get's changed later */
+ break;
+ case ArgChar:
+ case ArgUTF8:
+ size = 1;
+ break;
+ case ArgInfo:
+ size = sizeof(CK_INFO);
+ break;
+ case ArgSlotInfo:
+ size = sizeof(CK_SLOT_INFO);
+ break;
+ case ArgTokenInfo:
+ size = sizeof(CK_TOKEN_INFO);
+ break;
+ case ArgSessionInfo:
+ size = sizeof(CK_SESSION_INFO);
+ break;
+ case ArgAttribute:
+ size = sizeof(CK_ATTRIBUTE);
+ break;
+ case ArgMechanism:
+ size = sizeof(CK_MECHANISM);
+ break;
+ case ArgMechanismInfo:
+ size = sizeof(CK_MECHANISM_INFO);
+ break;
+ case ArgInitializeArgs:
+ size = sizeof(CK_C_INITIALIZE_ARGS);
+ break;
+ case ArgFunctionList:
+ size = sizeof(CK_FUNCTION_LIST);
+ break;
+ default:
+ break;
+ }
+
+ return (size);
+}
+
+CK_RV
+restore(const char *filename, Value *ptr)
+{
+ int fd, size;
+
+ fd = open(filename, O_RDONLY | O_BINARY);
+ if (fd < 0) {
+ perror(filename);
+ return CKR_FUNCTION_FAILED;
+ }
+
+ size = read(fd, ptr->data, ptr->size);
+ if (systemFlags & FLAG_VerifyFile) {
+ printDump(ptr->data, ptr->size);
+ }
+ if (size < 0) {
+ perror(filename);
+ return CKR_FUNCTION_FAILED;
+ } else if (size != ptr->size) {
+ fprintf(stderr, "%s: only read %d bytes, needed to read %d bytes\n",
+ filename, size, ptr->size);
+ return CKR_FUNCTION_FAILED;
+ }
+ close(fd);
+ return CKR_OK;
+}
+
+CK_RV
+save(const char *filename, Value *ptr)
+{
+ int fd, size;
+
+ fd = open(filename, O_WRONLY | O_BINARY | O_CREAT, 0666);
+ if (fd < 0) {
+ perror(filename);
+ return CKR_FUNCTION_FAILED;
+ }
+
+ size = write(fd, ptr->data, ptr->size);
+ if (size < 0) {
+ perror(filename);
+ return CKR_FUNCTION_FAILED;
+ } else if (size != ptr->size) {
+ fprintf(stderr, "%s: only wrote %d bytes, need to write %d bytes\n",
+ filename, size, ptr->size);
+ return CKR_FUNCTION_FAILED;
+ }
+ close(fd);
+ return CKR_OK;
+}
+
+static CK_RV
+increment(Value *ptr, CK_ULONG value)
+{
+ if ((ptr->type & ArgMask) != ArgULong) {
+ return CKR_ARGUMENTS_BAD;
+ }
+ *(CK_ULONG *)ptr->data += value;
+ return CKR_OK;
+}
+
+static CK_RV
+decrement(Value *ptr, CK_ULONG value)
+{
+ if ((ptr->type & ArgMask) != ArgULong) {
+ return CKR_ARGUMENTS_BAD;
+ }
+ *(CK_ULONG *)ptr->data -= value;
+ return CKR_OK;
+}
+
+CK_RV
+printArg(Value *ptr, int arg_number)
+{
+ ArgType type = ptr->type & ArgMask;
+ CK_INFO *info;
+ CK_SLOT_INFO *slotInfo;
+ CK_TOKEN_INFO *tokenInfo;
+ CK_SESSION_INFO *sessionInfo;
+ CK_ATTRIBUTE *attribute;
+ CK_MECHANISM *mechanism;
+ CK_MECHANISM_INFO *mechanismInfo;
+ CK_C_INITIALIZE_ARGS *initArgs;
+ CK_FUNCTION_LIST *functionList;
+ CK_RV ckrv = CKR_OK;
+ ConstType constType;
+
+ if (arg_number) {
+ printf("Arg %d: \n", arg_number);
+ }
+ if (ptr->arraySize > 1) {
+ Value element;
+ int i;
+ int elementSize = ptr->size / ptr->arraySize;
+ char *dp = (char *)ptr->data;
+
+ /* build a temporary Value to hold a single element */
+ element.type = type;
+ element.constType = ptr->constType;
+ element.size = elementSize;
+ element.filename = ptr->filename;
+ element.reference = 1;
+ element.arraySize = 1;
+ for (i = 0; i < ptr->arraySize; i++) {
+ printf(" -----[ %d ] -----\n", i);
+ element.data = (void *)&dp[i * elementSize];
+ (void)printArg(&element, 0);
+ }
+ return ckrv;
+ }
+ if (ptr->data == NULL) {
+ printf(" NULL ptr to a %s\n", valueString[type]);
+ return ckrv;
+ }
+ switch (type) {
+ case ArgNone:
+ printf(" None\n");
+ break;
+ case ArgULong:
+ printf(" %lu (0x%lx)\n", *((CK_ULONG *)ptr->data),
+ *((CK_ULONG *)ptr->data));
+ if (ptr->constType != ConstNone) {
+ printf(" ");
+ printConst(*(CK_ULONG *)ptr->data, ptr->constType, 1);
+ }
+ break;
+ case ArgVar:
+ printf(" %s\n", (char *)ptr->data);
+ break;
+ case ArgUTF8:
+ printf(" %s\n", (char *)ptr->data);
+ break;
+ case ArgChar:
+ printDump(ptr->data, ptr->size);
+ break;
+ case ArgInfo:
+#define VERSION(x) (x).major, (x).minor
+ info = (CK_INFO *)ptr->data;
+ printf(" Cryptoki Version: %d.%02d\n",
+ VERSION(info->cryptokiVersion));
+ printf(" Manufacturer ID: ");
+ printChars((char *)info->manufacturerID,
+ sizeof(info->manufacturerID));
+ printFlags(" Flags: ", info->flags, ConstInfoFlags);
+ printf(" Library Description: ");
+ printChars((char *)info->libraryDescription,
+ sizeof(info->libraryDescription));
+ printf(" Library Version: %d.%02d\n",
+ VERSION(info->libraryVersion));
+ break;
+ case ArgSlotInfo:
+ slotInfo = (CK_SLOT_INFO *)ptr->data;
+ printf(" Slot Description: ");
+ printChars((char *)slotInfo->slotDescription,
+ sizeof(slotInfo->slotDescription));
+ printf(" Manufacturer ID: ");
+ printChars((char *)slotInfo->manufacturerID,
+ sizeof(slotInfo->manufacturerID));
+ printFlags(" Flags: ", slotInfo->flags, ConstSlotFlags);
+ printf(" Hardware Version: %d.%02d\n",
+ VERSION(slotInfo->hardwareVersion));
+ printf(" Firmware Version: %d.%02d\n",
+ VERSION(slotInfo->firmwareVersion));
+ break;
+ case ArgTokenInfo:
+ tokenInfo = (CK_TOKEN_INFO *)ptr->data;
+ printf(" Label: ");
+ printChars((char *)tokenInfo->label, sizeof(tokenInfo->label));
+ printf(" Manufacturer ID: ");
+ printChars((char *)tokenInfo->manufacturerID,
+ sizeof(tokenInfo->manufacturerID));
+ printf(" Model: ");
+ printChars((char *)tokenInfo->model, sizeof(tokenInfo->model));
+ printf(" Serial Number: ");
+ printChars((char *)tokenInfo->serialNumber,
+ sizeof(tokenInfo->serialNumber));
+ printFlags(" Flags: ", tokenInfo->flags, ConstTokenFlags);
+ printf(" Max Session Count: ");
+ printConst(tokenInfo->ulMaxSessionCount, ConstAvailableSizes, 1);
+ printf(" Session Count: ");
+ printConst(tokenInfo->ulSessionCount, ConstCurrentSize, 1);
+ printf(" RW Session Count: ");
+ printConst(tokenInfo->ulMaxRwSessionCount, ConstAvailableSizes, 1);
+ printf(" Max Pin Length : ");
+ printConst(tokenInfo->ulMaxPinLen, ConstCurrentSize, 1);
+ printf(" Min Pin Length : ");
+ printConst(tokenInfo->ulMinPinLen, ConstCurrentSize, 1);
+ printf(" Total Public Memory: ");
+ printConst(tokenInfo->ulTotalPublicMemory, ConstAvailableSizes, 1);
+ printf(" Free Public Memory: ");
+ printConst(tokenInfo->ulFreePublicMemory, ConstCurrentSize, 1);
+ printf(" Total Private Memory: ");
+ printConst(tokenInfo->ulTotalPrivateMemory, ConstAvailableSizes, 1);
+ printf(" Free Private Memory: ");
+ printConst(tokenInfo->ulFreePrivateMemory, ConstCurrentSize, 1);
+ printf(" Hardware Version: %d.%02d\n",
+ VERSION(tokenInfo->hardwareVersion));
+ printf(" Firmware Version: %d.%02d\n",
+ VERSION(tokenInfo->firmwareVersion));
+ printf(" UTC Time: ");
+ printChars((char *)tokenInfo->utcTime, sizeof(tokenInfo->utcTime));
+ break;
+ case ArgSessionInfo:
+ sessionInfo = (CK_SESSION_INFO *)ptr->data;
+ printf(" SlotID: 0x%08lx\n", sessionInfo->slotID);
+ printf(" State: ");
+ printConst(sessionInfo->state, ConstSessionState, 1);
+ printFlags(" Flags: ", sessionInfo->flags, ConstSessionFlags);
+ printf(" Device error: %lu 0x%08lx\n", sessionInfo->ulDeviceError,
+ sessionInfo->ulDeviceError);
+ break;
+ case ArgAttribute:
+ attribute = (CK_ATTRIBUTE *)ptr->data;
+ printf(" Attribute Type: ");
+ printConst(attribute->type, ConstAttribute, 1);
+ printf(" Attribute Data: ");
+ if (attribute->pValue == NULL) {
+ printf("NULL\n");
+ printf("Attribute Len: %lu\n", attribute->ulValueLen);
+ } else {
+ constType = getConstFromAttribute(attribute->type);
+ if (constType != ConstNone) {
+ CK_ULONG value = (constType == ConstBool) ? *(CK_BBOOL *)attribute->pValue
+ : *(CK_ULONG *)attribute->pValue;
+ printConst(value, constType, 1);
+ } else {
+ printf("\n");
+ printDump(attribute->pValue, attribute->ulValueLen);
+ }
+ }
+ break;
+ case ArgMechanism:
+ mechanism = (CK_MECHANISM *)ptr->data;
+ printf(" Mechanism Type: ");
+ printConst(mechanism->mechanism, ConstMechanism, 1);
+ printf(" Mechanism Data:\n");
+ printDump(mechanism->pParameter, mechanism->ulParameterLen);
+ break;
+ case ArgMechanismInfo:
+ mechanismInfo = (CK_MECHANISM_INFO *)ptr->data;
+ printf(" Minimum Key Size: %ld\n", mechanismInfo->ulMinKeySize);
+ printf(" Maximum Key Size: %ld\n", mechanismInfo->ulMaxKeySize);
+ printFlags(" Flags: ", mechanismInfo->flags, ConstMechanismFlags);
+ break;
+ case ArgInitializeArgs:
+ initArgs = (CK_C_INITIALIZE_ARGS *)ptr->data;
+ printFlags(" Flags: ", initArgs->flags, ConstInitializeFlags);
+ if (initArgs->LibraryParameters) {
+ printf("Params: %s\n", (char *)initArgs->LibraryParameters);
+ }
+ case ArgFunctionList:
+ functionList = (CK_FUNCTION_LIST *)ptr->data;
+ printf(" Version: %d.%02d\n", VERSION(functionList->version));
+#ifdef notdef
+#undef CK_NEED_ARG_LIST
+#define CK_PKCS11_FUNCTION_INFO(func) \
+ printf(" %s: 0x%08lx\n", #func, (unsigned long)functionList->func);
+#include "pkcs11f.h"
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+#endif
+ default:
+ ckrv = CKR_ARGUMENTS_BAD;
+ break;
+ }
+
+ return ckrv;
+}
+
+/*
+ * Feeling ambitious? turn this whole thing into lexx yacc parser
+ * with full expressions.
+ */
+Value **
+parseArgs(int index, const char *bp)
+{
+ const Commands *cp = &commands[index];
+ int size = strlen(cp->fname);
+ int i;
+ CK_ULONG value;
+ char vname[512];
+ Value **argList, *possible;
+ ConstType constType;
+
+ /*
+ * skip pass the command
+ */
+ if ((cp->fname[0] == 'C') && (cp->fname[1] == '_') && (bp[1] != '_')) {
+ size -= 2;
+ }
+ bp += size;
+
+ /*
+ * Initialize our argument list
+ */
+ argList = (Value **)malloc(sizeof(Value *) * MAX_ARGS);
+ for (i = 0; i < MAX_ARGS; i++) {
+ argList[i] = NULL;
+ }
+
+ /*
+ * Walk the argument list parsing it...
+ */
+ for (i = 0; i < MAX_ARGS; i++) {
+ ArgType type = cp->args[i] & ArgMask;
+ int error;
+
+ /* strip blanks */
+ bp = strip(bp);
+
+ /* if we hit ArgNone, we've nabbed all the arguments we need */
+ if (type == ArgNone) {
+ break;
+ }
+
+ /* if we run out of space in the line, we weren't given enough
+ * arguments... */
+ if (*bp == '\0') {
+ /* we're into optional arguments, ok to quit now */
+ if (cp->args[i] & ArgOpt) {
+ break;
+ }
+ fprintf(stderr, "%s: only %d args found,\n", cp->fname, i);
+ parseFree(argList);
+ return NULL;
+ }
+
+ /* collect all the rest of the command line and send
+ * it as a single argument */
+ if (cp->args[i] & ArgFull) {
+ int size = strlen(bp) + 1;
+ argList[i] = NewValue(type, size);
+ memcpy(argList[i]->data, bp, size);
+ break;
+ }
+
+ /*
+ * look up the argument in our variable list first... only
+ * exception is the new argument type for set...
+ */
+ error = 0;
+ if ((cp->args[i] != (ArgVar | ArgNew)) &&
+ (possible = varLookup(bp, vname, sizeof(vname), &error))) {
+ /* ints are only compatible with other ints... all other types
+ * are interchangeable... */
+ if (type != ArgVar) { /* ArgVar's match anyone */
+ if ((type == ArgULong) ^
+ ((possible->type & ArgMask) == ArgULong)) {
+ fprintf(stderr, "%s: Arg %d incompatible type with <%s>\n",
+ cp->fname, i + 1, vname);
+ argFree(possible);
+ parseFree(argList);
+ return NULL;
+ }
+ /*
+ * ... that is as long as they are big enough...
+ */
+ if (ArgSize(type) > possible->size) {
+ fprintf(stderr,
+ "%s: Arg %d %s is too small (%d bytes needs to be %d bytes)\n",
+ cp->fname, i + 1, vname, possible->size, ArgSize(type));
+ argFree(possible);
+ parseFree(argList);
+ return NULL;
+ }
+ }
+
+ /* everything looks kosher here, use it */
+ argList[i] = possible;
+
+ bp = readChars(bp, vname, sizeof(vname));
+ if (cp->args[i] & ArgOut) {
+ possible->type |= ArgOut;
+ }
+ continue;
+ }
+
+ if (error == 1) {
+ parseFree(argList);
+ return NULL;
+ }
+
+ /* create space for our argument */
+ argList[i] = NewValue(type, 1);
+
+ if ((PL_strncasecmp(bp, "null", 4) == 0) && ((bp[4] == 0) ||
+ (bp[4] ==
+ ' ') ||
+ (bp[4] ==
+ '\t') ||
+ (bp[4] == '\n'))) {
+ if (cp->args[i] == ArgULong) {
+ fprintf(stderr, "%s: Arg %d CK_ULONG can't be NULL\n",
+ cp->fname, i + 1);
+ parseFree(argList);
+ return NULL;
+ }
+ argFreeData(argList[i]);
+ argList[i]->data = NULL;
+ argList[i]->size = 0;
+ bp += 4;
+ if (*bp)
+ bp++;
+ continue;
+ }
+
+ /* if we're an output variable, we need to add it */
+ if (cp->args[i] & ArgOut) {
+ if (PL_strncasecmp(bp, "file(", 5) == 0 /* ) */) {
+ char filename[512];
+ bp = readChars(bp + 5, filename, sizeof(filename));
+ size = PL_strlen(filename);
+ if ((size > 0) && (/* ( */ filename[size - 1] == ')')) {
+ filename[size - 1] = 0;
+ }
+ filename[size] = 0;
+ argList[i]->filename = (char *)malloc(size + 1);
+
+ PL_strcpy(argList[i]->filename, filename);
+
+ argList[i]->type |= ArgOut | ArgFile;
+ break;
+ }
+ bp = AddVariable(bp, &argList[i]);
+ argList[i]->type |= ArgOut;
+ continue;
+ }
+
+ if (PL_strncasecmp(bp, "file(", 5) == 0 /* ) */) {
+ char filename[512];
+
+ bp = readChars(bp + 5, filename, sizeof(filename));
+ size = PL_strlen(filename);
+ if ((size > 0) && (/* ( */ filename[size - 1] == ')')) {
+ filename[size - 1] = 0;
+ }
+
+ if (restore(filename, argList[i]) != CKR_OK) {
+ parseFree(argList);
+ return NULL;
+ }
+ continue;
+ }
+
+ switch (type) {
+ case ArgULong:
+ bp = constLookup(bp, &value, &constType);
+ *(int *)argList[i]->data = value;
+ argList[i]->constType = constType;
+ break;
+ case ArgVar:
+ argFreeData(argList[i]);
+ size = getEnd(bp) + 1;
+ argList[i]->data = (void *)malloc(size);
+ argList[i]->size = size;
+ /* fall through */
+ case ArgInfo:
+ case ArgSlotInfo:
+ case ArgTokenInfo:
+ case ArgSessionInfo:
+ case ArgAttribute:
+ case ArgMechanism:
+ case ArgMechanismInfo:
+ case ArgInitializeArgs:
+ case ArgUTF8:
+ case ArgChar:
+ bp = readChars(bp, (char *)argList[i]->data, argList[i]->size);
+ case ArgNone:
+ default:
+ break;
+ }
+ }
+
+ return argList;
+}
+
+/* lookup the command in the array */
+int
+lookup(const char *buf)
+{
+ int size, i;
+ int buflen;
+
+ buflen = PL_strlen(buf);
+
+ for (i = 0; i < commandCount; i++) {
+ size = PL_strlen(commands[i].fname);
+
+ if (size <= buflen) {
+ if (PL_strncasecmp(buf, commands[i].fname, size) == 0) {
+ return i;
+ }
+ }
+ if (size - 2 <= buflen) {
+ if (commands[i].fname[0] == 'C' && commands[i].fname[1] == '_' &&
+ (PL_strncasecmp(buf, &commands[i].fname[2], size - 2) == 0)) {
+ return i;
+ }
+ }
+ }
+ fprintf(stderr, "Can't find command %s\n", buf);
+ return -1;
+}
+
+void
+putOutput(Value **ptr)
+{
+ int i;
+
+ for (i = 0; i < MAX_ARGS; i++) {
+ ArgType type;
+
+ if (ptr[i] == NULL)
+ break;
+
+ type = ptr[i]->type;
+
+ ptr[i]->type &= ~ArgOut;
+ if (type == ArgNone) {
+ break;
+ }
+ if (type & ArgOut) {
+ (void)printArg(ptr[i], i + 1);
+ }
+ if (type & ArgFile) {
+ save(ptr[i]->filename, ptr[i]);
+ free(ptr[i]->filename);
+ ptr[i]->filename = NULL; /* paranoia */
+ }
+ }
+}
+
+CK_RV
+unloadModule(Module *module)
+{
+ char *disableUnload = NULL;
+
+ disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
+
+ if (module->library && !disableUnload) {
+ PR_UnloadLibrary(module->library);
+ }
+
+ module->library = NULL;
+ module->functionList = NULL;
+
+ return CKR_OK;
+}
+
+CK_RV
+loadModule(Module *module, char *library)
+{
+ PRLibrary *newLibrary;
+ CK_C_GetFunctionList getFunctionList;
+ CK_FUNCTION_LIST *functionList;
+ CK_RV ckrv;
+
+ newLibrary = PR_LoadLibrary(library);
+ if (!newLibrary) {
+ fprintf(stderr, "Couldn't load library %s\n", library);
+ return CKR_FUNCTION_FAILED;
+ }
+ getFunctionList = (CK_C_GetFunctionList)
+ PR_FindSymbol(newLibrary, "C_GetFunctionList");
+ if (!getFunctionList) {
+ fprintf(stderr, "Couldn't find \"C_GetFunctionList\" in %s\n", library);
+ return CKR_FUNCTION_FAILED;
+ }
+
+ ckrv = (*getFunctionList)(&functionList);
+ if (ckrv != CKR_OK) {
+ return ckrv;
+ }
+
+ if (module->library) {
+ PR_UnloadLibrary(module->library);
+ }
+
+ module->library = newLibrary;
+ module->functionList = functionList;
+
+ return CKR_OK;
+}
+
+static void
+printHelp(int index, int full)
+{
+ int j;
+ printf(" %s", commands[index].fname);
+ for (j = 0; j < MAX_ARGS; j++) {
+ ArgType type = commands[index].args[j] & ArgMask;
+ if (type == ArgNone) {
+ break;
+ }
+ printf(" %s", valueString[type]);
+ }
+ printf("\n");
+ printf(" %s\n", commands[index].helpString);
+}
+
+/* add Topical help here ! */
+static CK_RV
+printTopicHelp(char *topic)
+{
+ int size, i;
+ int topicLen;
+
+ topicLen = PL_strlen(topic);
+
+ for (i = 0; i < topicCount; i++) {
+ size = PL_strlen(topics[i].name);
+
+ if (size <= topicLen) {
+ if (PL_strncasecmp(topic, topics[i].name, size) == 0) {
+ break;
+ }
+ }
+ }
+
+ if (i == topicCount) {
+ fprintf(stderr, "Can't find topic '%s'\n", topic);
+ return CKR_DATA_INVALID;
+ }
+
+ printf(" %s", topic);
+ printf("\n");
+ printf(" %s\n", topics[i].helpString);
+ return CKR_OK;
+}
+
+static CK_RV
+printGeneralHelp(void)
+{
+ int i;
+ printf(" To get help on commands, select from the list below:");
+ for (i = 0; i < commandCount; i++) {
+ if (i % 5 == 0)
+ printf("\n");
+ printf("%s,", commands[i].fname);
+ }
+ printf("\n");
+ /* print help topics */
+ printf(" To get help on a topic, select from the list below:");
+ for (i = 0; i < topicCount; i++) {
+ if (i % 5 == 0)
+ printf("\n");
+ printf("%s,", topics[i].name);
+ }
+ printf("\n");
+ return CKR_OK;
+}
+
+static CK_RV
+quitIf(CK_ULONG a, const char *cmp, CK_ULONG b)
+{
+ if (strcmp(cmp, "<") == 0) {
+ return (a < b) ? CKR_QUIT : CKR_OK;
+ } else if (strcmp(cmp, ">") == 0) {
+ return (a > b) ? CKR_QUIT : CKR_OK;
+ } else if (strcmp(cmp, "<=") == 0) {
+ return (a <= b) ? CKR_QUIT : CKR_OK;
+ } else if (strcmp(cmp, ">=") == 0) {
+ return (a >= b) ? CKR_QUIT : CKR_OK;
+ } else if (strcmp(cmp, "=") == 0) {
+ return (a == b) ? CKR_QUIT : CKR_OK;
+ } else if (strcmp(cmp, "!=") == 0) {
+ return (a != b) ? CKR_QUIT : CKR_OK;
+ }
+ printf("Unkown integer comparator: '%s'\n", cmp);
+ return CKR_ARGUMENTS_BAD;
+}
+
+static CK_RV
+quitIfString(const char *a, const char *cmp, const char *b)
+{
+
+ if (strcmp(cmp, "=") == 0) {
+ return (strcmp(a, b) == 0) ? CKR_QUIT : CKR_OK;
+ } else if (strcmp(cmp, "!=") == 0) {
+ return (strcmp(a, b) != 0) ? CKR_QUIT : CKR_OK;
+ }
+ printf("Unkown string comparator: '%s'\n", cmp);
+ return CKR_ARGUMENTS_BAD;
+}
+
+CK_RV run(const char *);
+CK_RV timeCommand(const char *);
+CK_RV loop(const char *filename, const char *var,
+ CK_ULONG start, CK_ULONG end, CK_ULONG step);
+
+/*
+ * Actually dispatch the function... Bad things happen
+ * if these don't match the commands array.
+ */
+CK_RV
+do_func(int index, Value **a)
+{
+ int value, helpIndex;
+ static Module module = { NULL, NULL };
+ CK_FUNCTION_LIST *func = module.functionList;
+
+ switch (commands[index].fType) {
+ case F_C_Initialize:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_Initialize((void *)a[0]->data);
+ case F_C_Finalize:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_Finalize((void *)a[0]->data);
+ case F_C_GetInfo:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_GetInfo((CK_INFO *)a[0]->data);
+ case F_C_GetFunctionList:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_GetFunctionList((CK_FUNCTION_LIST **)a[0]->data);
+ case F_C_GetSlotList:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_GetSlotList((CK_BBOOL) * (CK_ULONG *)a[0]->data,
+ (CK_SLOT_ID *)a[1]->data,
+ (CK_ULONG *)a[2]->data);
+ case F_C_GetSlotInfo:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_GetSlotInfo(*(CK_ULONG *)a[0]->data,
+ (CK_SLOT_INFO *)a[1]->data);
+ case F_C_GetTokenInfo:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_GetTokenInfo(*(CK_ULONG *)a[0]->data,
+ (CK_TOKEN_INFO *)a[1]->data);
+ case F_C_GetMechanismList:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ if (a[1]->data) {
+ a[1]->constType = ConstMechanism;
+ }
+ return func->C_GetMechanismList(*(CK_ULONG *)a[0]->data,
+ (CK_MECHANISM_TYPE *)a[1]->data,
+ (CK_ULONG *)a[2]->data);
+ case F_C_GetMechanismInfo:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_GetMechanismInfo(*(CK_ULONG *)a[0]->data,
+ *(CK_ULONG *)a[1]->data,
+ (CK_MECHANISM_INFO *)a[2]->data);
+ case F_C_InitToken:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_InitToken(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data);
+ case F_C_InitPIN:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_InitPIN(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+ case F_C_SetPIN:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_SetPIN(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ *(CK_ULONG *)a[4]->data);
+ case F_C_OpenSession:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_OpenSession(*(CK_ULONG *)a[0]->data,
+ *(CK_ULONG *)a[1]->data,
+ (void *)NULL,
+ (CK_NOTIFY)NULL,
+ (CK_ULONG *)a[2]->data);
+ case F_C_CloseSession:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_CloseSession(*(CK_ULONG *)a[0]->data);
+ case F_C_CloseAllSessions:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_CloseAllSessions(*(CK_ULONG *)a[0]->data);
+ case F_C_GetSessionInfo:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_GetSessionInfo(*(CK_ULONG *)a[0]->data,
+ (CK_SESSION_INFO *)a[1]->data);
+ case F_C_GetOperationState:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_GetOperationState(*(CK_ULONG *)a[0]->data,
+ (CK_BYTE *)a[1]->data,
+ (CK_ULONG *)a[2]->data);
+ case F_C_SetOperationState:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_SetOperationState(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ *(CK_ULONG *)a[3]->data,
+ *(CK_ULONG *)a[4]->data);
+ case F_C_Login:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_Login(*(CK_ULONG *)a[0]->data,
+ *(CK_ULONG *)a[1]->data,
+ (CK_CHAR *)a[2]->data,
+ *(CK_ULONG *)a[3]->data);
+ case F_C_Logout:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_Logout(*(CK_ULONG *)a[0]->data);
+ case F_C_CreateObject:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_CreateObject(*(CK_ULONG *)a[0]->data,
+ (CK_ATTRIBUTE *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_ULONG *)a[3]->data);
+ case F_C_CopyObject:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_CopyObject(*(CK_ULONG *)a[0]->data,
+ *(CK_ULONG *)a[0]->data,
+ (CK_ATTRIBUTE *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_ULONG *)a[3]->data);
+ case F_C_DestroyObject:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_DestroyObject(*(CK_ULONG *)a[0]->data,
+ *(CK_ULONG *)a[1]->data);
+ case F_C_GetObjectSize:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_GetObjectSize(*(CK_ULONG *)a[0]->data,
+ *(CK_ULONG *)a[1]->data,
+ (CK_ULONG *)a[2]->data);
+ case F_C_GetAttributeValue:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_GetAttributeValue(*(CK_ULONG *)a[0]->data,
+ *(CK_ULONG *)a[1]->data,
+ (CK_ATTRIBUTE *)a[2]->data,
+ *(CK_ULONG *)a[3]->data);
+ case F_C_SetAttributeValue:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_SetAttributeValue(*(CK_ULONG *)a[0]->data,
+ *(CK_ULONG *)a[1]->data,
+ (CK_ATTRIBUTE *)a[2]->data,
+ *(CK_ULONG *)a[3]->data);
+ case F_C_FindObjectsInit:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_FindObjectsInit(*(CK_ULONG *)a[0]->data,
+ (CK_ATTRIBUTE *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+ case F_C_FindObjects:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_FindObjects(*(CK_ULONG *)a[0]->data,
+ (CK_ULONG *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_ULONG *)a[3]->data);
+ case F_C_FindObjectsFinal:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_FindObjectsFinal(*(CK_ULONG *)a[0]->data);
+ case F_C_EncryptInit:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_EncryptInit(*(CK_ULONG *)a[0]->data,
+ (CK_MECHANISM *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+ case F_C_Encrypt:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_Encrypt(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ (CK_ULONG *)a[4]->data);
+ case F_C_EncryptUpdate:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_EncryptUpdate(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ (CK_ULONG *)a[4]->data);
+ case F_C_EncryptFinal:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_EncryptFinal(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ (CK_ULONG *)a[2]->data);
+ case F_C_DecryptInit:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_DecryptInit(*(CK_ULONG *)a[0]->data,
+ (CK_MECHANISM *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+ case F_C_Decrypt:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_Decrypt(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ (CK_ULONG *)a[4]->data);
+ case F_C_DecryptUpdate:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_DecryptUpdate(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ (CK_ULONG *)a[4]->data);
+ case F_C_DecryptFinal:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_DecryptFinal(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ (CK_ULONG *)a[2]->data);
+ case F_C_DigestInit:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_DigestInit(*(CK_ULONG *)a[0]->data,
+ (CK_MECHANISM *)a[1]->data);
+ case F_C_Digest:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_Digest(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ (CK_ULONG *)a[4]->data);
+ case F_C_DigestUpdate:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_DigestUpdate(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+ case F_C_DigestKey:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_DigestKey(*(CK_ULONG *)a[0]->data,
+ *(CK_ULONG *)a[1]->data);
+ case F_C_DigestFinal:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_DigestFinal(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ (CK_ULONG *)a[2]->data);
+ case F_C_SignInit:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_SignInit(*(CK_ULONG *)a[0]->data,
+ (CK_MECHANISM *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+ case F_C_Sign:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_Sign(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ (CK_ULONG *)a[4]->data);
+ case F_C_SignUpdate:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_SignUpdate(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+ case F_C_SignFinal:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_SignFinal(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ (CK_ULONG *)a[2]->data);
+
+ case F_C_SignRecoverInit:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_SignRecoverInit(*(CK_ULONG *)a[0]->data,
+ (CK_MECHANISM *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+ case F_C_SignRecover:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_SignRecover(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ (CK_ULONG *)a[4]->data);
+ case F_C_VerifyInit:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_VerifyInit(*(CK_ULONG *)a[0]->data,
+ (CK_MECHANISM *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+ case F_C_Verify:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_Verify(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ *(CK_ULONG *)a[4]->data);
+ case F_C_VerifyUpdate:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_VerifyUpdate(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+ case F_C_VerifyFinal:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_VerifyFinal(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+
+ case F_C_VerifyRecoverInit:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_VerifyRecoverInit(*(CK_ULONG *)a[0]->data,
+ (CK_MECHANISM *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+ case F_C_VerifyRecover:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_VerifyRecover(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ (CK_ULONG *)a[4]->data);
+ case F_C_DigestEncryptUpdate:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_DigestEncryptUpdate(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ (CK_ULONG *)a[4]->data);
+ case F_C_DecryptDigestUpdate:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_DecryptDigestUpdate(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ (CK_ULONG *)a[4]->data);
+ case F_C_SignEncryptUpdate:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_SignEncryptUpdate(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ (CK_ULONG *)a[4]->data);
+ case F_C_DecryptVerifyUpdate:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_DecryptVerifyUpdate(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ (CK_ULONG *)a[4]->data);
+ case F_C_GenerateKey:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_GenerateKey(*(CK_ULONG *)a[0]->data,
+ (CK_MECHANISM *)a[1]->data,
+ (CK_ATTRIBUTE *)a[2]->data,
+ *(CK_ULONG *)a[3]->data,
+ (CK_ULONG *)a[4]->data);
+ case F_C_GenerateKeyPair:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_GenerateKeyPair(*(CK_ULONG *)a[0]->data,
+ (CK_MECHANISM *)a[1]->data,
+ (CK_ATTRIBUTE *)a[2]->data,
+ *(CK_ULONG *)a[3]->data,
+ (CK_ATTRIBUTE *)a[4]->data,
+ *(CK_ULONG *)a[5]->data,
+ (CK_ULONG *)a[6]->data,
+ (CK_ULONG *)a[7]->data);
+ case F_C_WrapKey:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_WrapKey(*(CK_ULONG *)a[0]->data,
+ (CK_MECHANISM *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ *(CK_ULONG *)a[3]->data,
+ (CK_CHAR *)a[5]->data,
+ (CK_ULONG *)a[6]->data);
+ case F_C_UnwrapKey:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_UnwrapKey(*(CK_ULONG *)a[0]->data,
+ (CK_MECHANISM *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_CHAR *)a[3]->data,
+ *(CK_ULONG *)a[4]->data,
+ (CK_ATTRIBUTE *)a[5]->data,
+ *(CK_ULONG *)a[6]->data,
+ (CK_ULONG *)a[7]->data);
+ case F_C_DeriveKey:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_DeriveKey(*(CK_ULONG *)a[0]->data,
+ (CK_MECHANISM *)a[1]->data,
+ *(CK_ULONG *)a[2]->data,
+ (CK_ATTRIBUTE *)a[3]->data,
+ *(CK_ULONG *)a[4]->data,
+ (CK_ULONG *)a[5]->data);
+ case F_C_SeedRandom:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_SeedRandom(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+ case F_C_GenerateRandom:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_GenerateRandom(*(CK_ULONG *)a[0]->data,
+ (CK_CHAR *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+ case F_C_GetFunctionStatus:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_GetFunctionStatus(*(CK_ULONG *)a[0]->data);
+ case F_C_CancelFunction:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_CancelFunction(*(CK_ULONG *)a[0]->data);
+ case F_C_WaitForSlotEvent:
+ if (!func)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ return func->C_WaitForSlotEvent(*(CK_ULONG *)a[0]->data,
+ (CK_ULONG *)a[1]->data,
+ (void *)a[2]->data);
+ /* set a variable */
+ case F_SetVar:
+ case F_SetStringVar:
+ (void)DeleteVariable(a[0]->data);
+ (void)AddVariable(a[0]->data, &a[1]);
+ return CKR_OK;
+ /* print a value */
+ case F_Print:
+ return printArg(a[0], 0);
+ case F_SaveVar:
+ return save(a[0]->data, a[1]);
+ case F_RestoreVar:
+ return restore(a[0]->data, a[1]);
+ case F_Delete:
+ return DeleteVariable(a[0]->data);
+ case F_Increment:
+ return increment(a[0], *(CK_ULONG *)a[1]->data);
+ case F_Decrement:
+ return decrement(a[0], *(CK_ULONG *)a[1]->data);
+ case F_List:
+ return list();
+ case F_Run:
+ return run(a[0]->data);
+ case F_Time:
+ return timeCommand(a[0]->data);
+ case F_Load:
+ return loadModule(&module, a[0]->data);
+ case F_Unload:
+ return unloadModule(&module);
+ case F_NewArray:
+ (void)DeleteVariable(a[0]->data);
+ return ArrayVariable(a[0]->data, a[1]->data, *(CK_ULONG *)a[2]->data);
+ case F_NewTemplate:
+ (void)DeleteVariable(a[0]->data);
+ return ArrayTemplate(a[0]->data, a[1]->data);
+ case F_BuildTemplate:
+ return BuildTemplate(a[0]);
+ case F_SetTemplate:
+ return SetTemplate(a[0],
+ *(CK_ULONG *)a[1]->data,
+ *(CK_ULONG *)a[2]->data);
+ case F_NewMechanism:
+ (void)DeleteVariable(a[0]->data);
+ return NewMechanism(a[0]->data, *(CK_ULONG *)a[1]->data);
+ case F_NewInitializeArgs:
+ (void)DeleteVariable(a[0]->data);
+ return NewInitializeArgs(a[0]->data, *(CK_ULONG *)a[1]->data, a[2]->data);
+ case F_System:
+ value = *(int *)a[0]->data;
+ if (value & 0x80000000) {
+ systemFlags &= ~value;
+ } else {
+ systemFlags |= value;
+ }
+ return CKR_OK;
+ case F_Loop:
+ return loop(a[0]->data, a[1]->data, *(CK_ULONG *)a[2]->data,
+ *(CK_ULONG *)a[3]->data, *(CK_ULONG *)a[4]->data);
+ case F_Help:
+ if (a[0]) {
+ helpIndex = lookup(a[0]->data);
+ if (helpIndex < 0) {
+ return printTopicHelp(a[0]->data);
+ }
+ printHelp(helpIndex, 1);
+ return CKR_OK;
+ }
+ return printGeneralHelp();
+ case F_QuitIfString:
+ return quitIfString(a[0]->data, a[1]->data, a[2]->data);
+ case F_QuitIf:
+ return quitIf(*(CK_ULONG *)a[0]->data, a[1]->data, *(CK_ULONG *)a[2]->data);
+ case F_Quit:
+ return CKR_QUIT;
+ default:
+ fprintf(stderr,
+ "Function %s not yet supported\n", commands[index].fname);
+ return CKR_OK;
+ }
+ /* Not Reached */
+ return CKR_OK;
+}
+
+CK_RV
+processCommand(const char *buf)
+{
+ CK_RV error = CKR_OK;
+ int index;
+ const char *bp;
+ Value **arglist;
+
+ bp = strip(buf);
+ /* allow comments and blank lines in scripts */
+ if ((*bp == '#') || (*bp == 0) || (*bp == '\n')) {
+ return CKR_OK;
+ }
+
+ index = lookup(bp);
+
+ if (index < 0) {
+ return CKR_OK;
+ }
+
+ arglist = parseArgs(index, bp);
+ if (arglist == NULL) {
+ return CKR_OK;
+ }
+
+ error = do_func(index, arglist);
+ if (error == CKR_OK) {
+ putOutput(arglist);
+ } else if (error != CKR_QUIT) {
+ printf(">> Error : ");
+ printConst(error, ConstResult, 1);
+ }
+
+ parseFree(arglist);
+ return error;
+}
+
+CK_RV
+timeCommand(const char *command)
+{
+ CK_RV ckrv;
+ PRIntervalTime startTime = PR_IntervalNow();
+ PRIntervalTime endTime;
+ PRIntervalTime elapsedTime;
+
+ ckrv = processCommand(command);
+
+ endTime = PR_IntervalNow();
+ elapsedTime = endTime - startTime;
+ printf("Time -- %d msec \n",
+ PR_IntervalToMilliseconds(elapsedTime));
+
+ return ckrv;
+}
+
+CK_RV
+process(FILE *inFile, int user)
+{
+ char buf[2048];
+ CK_RV error;
+ CK_RV ckrv = CKR_OK;
+
+ if (user) {
+ printf("pkcs11> ");
+ fflush(stdout);
+ }
+
+ while (fgets(buf, 2048, inFile) != NULL) {
+
+ if (!user)
+ printf("* %s", buf);
+ error = processCommand(buf);
+ if (error == CKR_QUIT) {
+ break;
+ } else if (error != CKR_OK) {
+ ckrv = error;
+ }
+ if (user) {
+ printf("pkcs11> ");
+ fflush(stdout);
+ }
+ }
+ return ckrv;
+}
+
+CK_RV
+run(const char *filename)
+{
+ FILE *infile;
+ CK_RV ckrv;
+
+ infile = fopen(filename, "r");
+
+ if (infile == NULL) {
+ perror(filename);
+ return CKR_FUNCTION_FAILED;
+ }
+
+ ckrv = process(infile, 0);
+
+ fclose(infile);
+ return ckrv;
+}
+
+CK_RV
+loop(const char *filename, const char *var,
+ CK_ULONG start, CK_ULONG end, CK_ULONG step)
+{
+ CK_ULONG i = 0;
+ Value *value = 0;
+ CK_RV ckrv;
+
+ for (i = start; i < end; i += step) {
+ value = NewValue(ArgULong, 1);
+ *(CK_ULONG *)value->data = i;
+ DeleteVariable(var);
+ AddVariable(var, &value);
+ ckrv = run(filename);
+ argFree(value);
+ if (ckrv == CKR_QUIT) {
+ break;
+ }
+ }
+ return ckrv;
+}
+
+int
+main(int argc, char **argv)
+{
+ /* I suppose that some day we could parse some arguments */
+ (void)process(stdin, 1);
+ return 0;
+}
diff --git a/security/nss/cmd/pk11util/scripts/dosign b/security/nss/cmd/pk11util/scripts/dosign
new file mode 100644
index 000000000..33e761f0b
--- /dev/null
+++ b/security/nss/cmd/pk11util/scripts/dosign
@@ -0,0 +1,162 @@
+Load nsscapi.dll
+C_Initialize NULL
+C_GetSlotList false NULL slotCount
+NewArray slotList CK_ULONG slotCount
+C_GetSlotList false slotList slotCount
+#change the following to the appropriate slot id
+set slotID 1
+#set slotID slotList[0]
+C_GetSlotInfo slotID slotInfo
+C_GetTokenInfo slotID tokenInfo
+C_OpenSession slotID CKF_SERIAL_SESSION session
+#
+#uncomment the following line and include the correct password
+#C_Login session CKU_USER 0000 4
+#
+# build the search template
+#
+NewTemplate search CKA_CLASS
+SetTemplate search 0 CKO_CERTIFICATE
+NewArray certID CK_ULONG 10
+C_FindObjectsInit session search 1
+C_FindObjects session certID sizeA(certID) count
+C_FindObjectsFinal session
+#
+# now read the cert out
+#
+#NewTemplate derCert CKA_VALUE
+#NewTemplate certName CKA_LABEL,CKA_VALUE
+#C_GetAttributeValue session certID[0] certName sizeA(certName)
+#BuildTemplate certName
+#C_GetAttributeValue session certID[0] certName sizeA(certName)
+#print certName[0]
+Set countm1 count
+Decrement countm1 1
+LoopRun pLabel1 i 0 countm1 1
+Set i 1
+run pLabel1
+NewTemplate id CKA_CLASS,CKA_ID
+C_GetAttributeValue session certID[i] id sizeA(id)
+BuildTemplate id
+C_GetAttributeValue session certID[i] id sizeA(id)
+SetTemplate id 0 CKO_PRIVATE_KEY
+NewArray keyID CK_ULONG 10
+C_FindObjectsInit session id sizeA(id)
+C_FindObjects session keyID sizeA(keyID) count
+C_FindObjectsFinal session
+
+NewMechanism rsaParams CKM_RSA_PKCS
+NewArray sign data 256
+NewArray sdata data 36
+C_SignInit session rsaParams keyID[0]
+print sdata
+C_Sign session sdata sizeof(sdata) sign sizeof(sign)
+save signature sign
+save hash sdata
+NewTemplate privValue CKA_MODULUS,CKA_PUBLIC_EXPONENT
+C_GetAttributeValue session keyID[0] privValue sizeA(privValue)
+BuildTemplate privValue
+C_GetAttributeValue session keyID[0] privValue sizeA(privValue)
+print privValue[0]
+print privValue[1]
+
+# save the public key
+SetTemplate id 0 CKO_PUBLIC_KEY
+NewArray pubkeyID CK_ULONG 10
+C_FindObjectsInit session id sizeA(id)
+C_FindObjects session pubkeyID sizeA(pubkeyID) count
+C_FindObjectsFinal session
+NewTemplate pubkeyValue CKA_MODULUS,CKA_PUBLIC_EXPONENT
+C_GetAttributeValue session pubkeyID[0] pubkeyValue sizeA(pubkeyValue)
+BuildTemplate pubkeyValue
+C_GetAttributeValue session pubkeyID[0] pubkeyValue sizeA(pubkeyValue)
+print pubkeyValue[0]
+print pubkeyValue[1]
+
+
+C_Finalize null
+unload
+
+#
+# Now do the same for using softoken
+#
+load softokn3.dll
+NewInitArg init CKF_OS_LOCKING_OK configdir=./db
+C_Initialize init
+C_GetSlotList false NULL slotCount
+NewArray slotList CK_ULONG slotCount
+C_GetSlotList false slotList slotCount
+#change the following to the appropriate slot id
+set slotID slotList[1]
+#set slotID slotList[0]
+C_GetSlotInfo slotID slotInfo
+C_GetTokenInfo slotID tokenInfo
+C_OpenSession slotID CKF_SERIAL_SESSION session
+NewTemplate search CKA_CLASS
+SetTemplate search 0 CKO_CERTIFICATE
+NewArray certID CK_ULONG 10
+C_FindObjectsInit session search 1
+C_FindObjects session certID sizeA(certID) count
+C_FindObjectsFinal session
+#
+# now read the cert out
+#
+#NewTemplate derCert CKA_VALUE
+#NewTemplate certName CKA_LABEL,CKA_VALUE
+#C_GetAttributeValue session certID[0] certName sizeA(certName)
+#BuildTemplate certName
+#C_GetAttributeValue session certID[0] certName sizeA(certName)
+#print certName[0]
+#Set countm1 count
+#Decrement countm1 1
+#LoopRun pLabel1 i 0 countm1 1
+Set i 0
+run pLabel1
+NewTemplate id CKA_CLASS,CKA_ID
+C_GetAttributeValue session certID[i] id sizeA(id)
+BuildTemplate id
+C_GetAttributeValue session certID[i] id sizeA(id)
+SetTemplate id 0 CKO_PRIVATE_KEY
+NewArray keyID CK_ULONG 10
+C_FindObjectsInit session id sizeA(id)
+C_FindObjects session keyID sizeA(keyID) count
+C_FindObjectsFinal session
+
+NewMechanism rsaParams CKM_RSA_PKCS
+NewArray sign data 256
+NewArray sdata data 36
+C_SignInit session rsaParams keyID[0]
+C_Sign session sdata sizeof(sdata) sign sizeof(sign)
+save signature2 sign
+save hash2 sdata
+
+SetTemplate id 0 CKO_PUBLIC_KEY
+NewArray pubkeyID CK_ULONG 10
+C_FindObjectsInit session id sizeA(id)
+C_FindObjects session pubkeyID sizeA(pubkeyID) count
+C_FindObjectsFinal session
+
+#
+# OK now we use raw unwrap and see what we have...
+#
+NewMechanism rawRsaParams CKM_RSA_X_509
+NewArray vdata data 256
+C_VerifyRecoverInit session rawRsaParams pubkeyID[0]
+C_VerifyRecover session sign sizeof(sign) vdata sizeof(vdata)
+save verify2 vdata
+restore signature sign
+C_VerifyRecoverInit session rawRsaParams pubkeyID[0]
+C_VerifyRecover session sign sizeof(sign) vdata sizeof(vdata)
+save verify vdata
+
+NewTemplate pubkeyValue CKA_MODULUS,CKA_PUBLIC_EXPONENT
+C_GetAttributeValue session pubkeyID[0] pubkeyValue sizeA(pubkeyValue)
+BuildTemplate pubkeyValue
+C_GetAttributeValue session pubkeyID[0] pubkeyValue sizeA(pubkeyValue)
+print pubkeyValue[0]
+print pubkeyValue[1]
+
+
+C_Finalize null
+
+unload
diff --git a/security/nss/cmd/pk11util/scripts/hssign b/security/nss/cmd/pk11util/scripts/hssign
new file mode 100644
index 000000000..9bcf365cc
--- /dev/null
+++ b/security/nss/cmd/pk11util/scripts/hssign
@@ -0,0 +1,48 @@
+Load aolkeypk11.dll
+C_Initialize NULL
+C_GetSlotList false NULL slotCount
+NewArray slotList CK_ULONG slotCount
+C_GetSlotList false slotList slotCount
+#change the following to the appropriate slot id
+#set slotID slotList[0]
+set slotID 1
+C_GetSlotInfo slotID slotInfo
+C_GetTokenInfo slotID tokenInfo
+C_OpenSession slotID CK_SESSION_SERIAL session
+#
+#uncomment the following line and include the correct password
+#for authenticated tokens
+#C_Login session CKU_USER 0000 4
+#
+# build the search template
+#
+#NewTemplate search CKA_CLASS
+#SetTemplate search 0 CKO_CERTIFICATE
+#NewArray certID CK_ULONG 1
+#C_FindObjectsInit session search 1
+#C_FindObjects session certID 1 count
+#C_FindObjectsFinal session
+#
+# now read the cert out
+#
+#NewTemplate derCert CKA_VALUE
+#C_GetAttributeValue session certID derCert 1
+#BuildTemplate derCert
+#C_GetAttributeValue session certID derCert 1
+#
+# Do a signature
+#
+NewTemplate search CKA_CLASS
+SetTemplate search 0 CKO_PRIVATE_KEY
+NewArray privateKey CK_ULONG 1
+C_FindObjectsInit session search 1
+C_FindObjects session privateKey 1 count
+C_FindObjectsFinal session
+# sign
+NewMechanism rsaParams CKM_RSA_PKCS
+NewArray sign data 128
+NewArray sdata data 20
+C_SignInit session rsaParams privateKey
+C_Sign session sdata sizeof(sdata) sign sizeof(sign)
+#C_Logout session
+
diff --git a/security/nss/cmd/pk11util/scripts/lcert b/security/nss/cmd/pk11util/scripts/lcert
new file mode 100644
index 000000000..0f249c3b5
--- /dev/null
+++ b/security/nss/cmd/pk11util/scripts/lcert
@@ -0,0 +1,35 @@
+Load nsscapi.dll
+C_Initialize NULL
+C_GetSlotList false NULL slotCount
+NewArray slotList CK_ULONG slotCount
+C_GetSlotList false slotList slotCount
+#change the following to the appropriate slot id
+set slotID 1
+#set slotID slotList[0]
+C_GetSlotInfo slotID slotInfo
+C_GetTokenInfo slotID tokenInfo
+C_OpenSession slotID CKF_SERIAL_SESSION session
+#
+#uncomment the following line and include the correct password
+#C_Login session CKU_USER 0000 4
+#
+# build the search template
+#
+NewTemplate search CKA_CLASS
+SetTemplate search 0 CKO_CERTIFICATE
+NewArray certID CK_ULONG 10
+C_FindObjectsInit session search 1
+C_FindObjects session certID sizeA(certID) count
+C_FindObjectsFinal session
+#
+# now read the cert out
+#
+#NewTemplate derCert CKA_VALUE
+#NewTemplate certName CKA_LABEL,CKA_VALUE
+#C_GetAttributeValue session certID[0] certName sizeA(certName)
+#BuildTemplate certName
+#C_GetAttributeValue session certID[0] certName sizeA(certName)
+#print certName[0]
+Set countm1 count
+Decrement countm1 1
+LoopRun pLabel1 i 0 countm1 1
diff --git a/security/nss/cmd/pk11util/scripts/mechanisms b/security/nss/cmd/pk11util/scripts/mechanisms
new file mode 100644
index 000000000..d103a9c4f
--- /dev/null
+++ b/security/nss/cmd/pk11util/scripts/mechanisms
@@ -0,0 +1,11 @@
+Load nsscapi.dll
+C_Initialize NULL
+C_GetSlotList false NULL slotCount
+NewArray slotList CK_ULONG slotCount
+C_GetSlotList false slotList slotCount
+
+LoopRun pMechanisms i 0 slotCount 1
+
+#C_Finalize
+#Unload
+
diff --git a/security/nss/cmd/pk11util/scripts/pLabel1 b/security/nss/cmd/pk11util/scripts/pLabel1
new file mode 100644
index 000000000..0be909bb4
--- /dev/null
+++ b/security/nss/cmd/pk11util/scripts/pLabel1
@@ -0,0 +1,6 @@
+NewTemplate certName CKA_LABEL,CKA_VALUE
+C_GetAttributeValue session certID[i] certName sizeA(certName)
+BuildTemplate certName
+C_GetAttributeValue session certID[i] certName sizeA(certName)
+print i
+print certName[0]
diff --git a/security/nss/cmd/pk11util/scripts/pMechanisms b/security/nss/cmd/pk11util/scripts/pMechanisms
new file mode 100644
index 000000000..82e860258
--- /dev/null
+++ b/security/nss/cmd/pk11util/scripts/pMechanisms
@@ -0,0 +1,8 @@
+#
+# print the mechanism list for a given token
+#
+set slotID slotList[i]
+C_GetMechanismList slotID NULL mechCount
+NewArray mechanismList CK_ULONG mechcount
+C_GetMechanismList slotID mechanismList mechCount
+print mechanismList
diff --git a/security/nss/cmd/pk11util/scripts/pcert b/security/nss/cmd/pk11util/scripts/pcert
new file mode 100644
index 000000000..c322a8bfe
--- /dev/null
+++ b/security/nss/cmd/pk11util/scripts/pcert
@@ -0,0 +1,30 @@
+Load aolkeypk11.dll
+C_Initialize NULL
+C_GetSlotList false NULL slotCount
+NewArray slotList CK_ULONG slotCount
+C_GetSlotList false slotList slotCount
+#change the following to the appropriate slot id
+set slotID 1
+#set slotID slotList[0]
+C_GetSlotInfo slotID slotInfo
+C_GetTokenInfo slotID tokenInfo
+C_OpenSession slotID CK_SESSION_SERIAL session
+#
+#uncomment the following line and include the correct password
+#C_Login session CKU_USER 0000 4
+#
+# build the search template
+#
+NewTemplate search CKA_CLASS
+SetTemplate search 0 CKO_CERTIFICATE
+NewArray certID CK_ULONG 1
+C_FindObjectsInit session search 1
+C_FindObjects session certID 1 count
+C_FindObjectsFinal session
+#
+# now read the cert out
+#
+NewTemplate derCert CKA_VALUE
+C_GetAttributeValue session certID derCert 1
+BuildTemplate derCert
+C_GetAttributeValue session certID derCert 1
diff --git a/security/nss/cmd/pk12util/Makefile b/security/nss/cmd/pk12util/Makefile
new file mode 100644
index 000000000..74ae20020
--- /dev/null
+++ b/security/nss/cmd/pk12util/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/pk12util/manifest.mn b/security/nss/cmd/pk12util/manifest.mn
new file mode 100644
index 000000000..5f7e0ab49
--- /dev/null
+++ b/security/nss/cmd/pk12util/manifest.mn
@@ -0,0 +1,23 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ pk12util.c \
+ $(NULL)
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = dbm seccmd
+
+PROGRAM = pk12util
+
+# USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/pk12util/pk12util.c b/security/nss/cmd/pk12util/pk12util.c
new file mode 100644
index 000000000..cca27cbf6
--- /dev/null
+++ b/security/nss/cmd/pk12util/pk12util.c
@@ -0,0 +1,1104 @@
+/* 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/. */
+
+#ifdef _CRTDBG_MAP_ALLOC
+#include <stdlib.h>
+#include <crtdbg.h>
+#endif
+
+#include "nspr.h"
+#include "secutil.h"
+#include "pk11func.h"
+#include "pkcs12.h"
+#include "p12plcy.h"
+#include "pk12util.h"
+#include "nss.h"
+#include "secport.h"
+#include "secpkcs5.h"
+#include "certdb.h"
+
+#define PKCS12_IN_BUFFER_SIZE 200
+
+static char *progName;
+PRBool pk12_debugging = PR_FALSE;
+PRBool dumpRawFile;
+
+PRIntn pk12uErrno = 0;
+
+static void
+Usage(char *progName)
+{
+#define FPS PR_fprintf(PR_STDERR,
+ FPS "Usage: %s -i importfile [-d certdir] [-P dbprefix] [-h tokenname]\n",
+ progName);
+ FPS "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n");
+ FPS "\t\t [-v]\n");
+
+ FPS "Usage: %s -l listfile [-d certdir] [-P dbprefix] [-h tokenname]\n",
+ progName);
+ FPS "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n");
+ FPS "\t\t [-v]\n");
+
+ FPS "Usage: %s -o exportfile -n certname [-d certdir] [-P dbprefix]\n",
+ progName);
+ FPS "\t\t [-c key_cipher] [-C cert_cipher]\n"
+ "\t\t [-m | --key_len keyLen] [--cert_key_len certKeyLen] [-v]\n");
+ FPS "\t\t [-k slotpwfile | -K slotpw]\n"
+ "\t\t [-w p12filepwfile | -W p12filepw]\n");
+
+ exit(PK12UERR_USAGE);
+}
+
+static PRBool
+p12u_OpenFile(p12uContext *p12cxt, PRBool fileRead)
+{
+ if (!p12cxt || !p12cxt->filename) {
+ return PR_FALSE;
+ }
+
+ if (fileRead) {
+ p12cxt->file = PR_Open(p12cxt->filename,
+ PR_RDONLY, 0400);
+ } else {
+ p12cxt->file = PR_Open(p12cxt->filename,
+ PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE,
+ 0600);
+ }
+
+ if (!p12cxt->file) {
+ p12cxt->error = PR_TRUE;
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+static void
+p12u_DestroyContext(p12uContext **ppCtx, PRBool removeFile)
+{
+ if (!ppCtx || !(*ppCtx)) {
+ return;
+ }
+
+ if ((*ppCtx)->file != NULL) {
+ PR_Close((*ppCtx)->file);
+ }
+
+ if ((*ppCtx)->filename != NULL) {
+ if (removeFile) {
+ PR_Delete((*ppCtx)->filename);
+ }
+ PL_strfree((*ppCtx)->filename);
+ (*ppCtx)->filename = NULL;
+ }
+
+ PR_Free(*ppCtx);
+ *ppCtx = NULL;
+}
+
+static p12uContext *
+p12u_InitContext(PRBool fileImport, char *filename)
+{
+ p12uContext *p12cxt;
+
+ p12cxt = PORT_ZNew(p12uContext);
+ if (!p12cxt) {
+ return NULL;
+ }
+
+ p12cxt->error = PR_FALSE;
+ p12cxt->errorValue = 0;
+ p12cxt->filename = PL_strdup(filename);
+
+ if (!p12u_OpenFile(p12cxt, fileImport)) {
+ p12u_DestroyContext(&p12cxt, PR_FALSE);
+ return NULL;
+ }
+
+ return p12cxt;
+}
+
+SECItem *
+P12U_NicknameCollisionCallback(SECItem *old_nick, PRBool *cancel, void *wincx)
+{
+ char *nick = NULL;
+ SECItem *ret_nick = NULL;
+ CERTCertificate *cert = (CERTCertificate *)wincx;
+
+ if (!cancel || !cert) {
+ pk12uErrno = PK12UERR_USER_CANCELLED;
+ return NULL;
+ }
+
+ if (!old_nick)
+ fprintf(stdout, "pk12util: no nickname for cert in PKCS12 file.\n");
+
+#if 0
+ /* XXX not handled yet */
+ *cancel = PR_TRUE;
+ return NULL;
+
+#else
+
+ nick = CERT_MakeCANickname(cert);
+ if (!nick) {
+ return NULL;
+ }
+
+ if (old_nick && old_nick->data && old_nick->len &&
+ PORT_Strlen(nick) == old_nick->len &&
+ !PORT_Strncmp((char *)old_nick->data, nick, old_nick->len)) {
+ PORT_Free(nick);
+ PORT_SetError(SEC_ERROR_IO);
+ return NULL;
+ }
+
+ fprintf(stdout, "pk12util: using nickname: %s\n", nick);
+ ret_nick = PORT_ZNew(SECItem);
+ if (ret_nick == NULL) {
+ PORT_Free(nick);
+ return NULL;
+ }
+
+ ret_nick->data = (unsigned char *)nick;
+ ret_nick->len = PORT_Strlen(nick);
+
+ return ret_nick;
+#endif
+}
+
+static SECStatus
+p12u_SwapUnicodeBytes(SECItem *uniItem)
+{
+ unsigned int i;
+ unsigned char a;
+ if ((uniItem == NULL) || (uniItem->len % 2)) {
+ return SECFailure;
+ }
+ for (i = 0; i < uniItem->len; i += 2) {
+ a = uniItem->data[i];
+ uniItem->data[i] = uniItem->data[i + 1];
+ uniItem->data[i + 1] = a;
+ }
+ return SECSuccess;
+}
+
+static PRBool
+p12u_ucs2_ascii_conversion_function(PRBool toUnicode,
+ unsigned char *inBuf,
+ unsigned int inBufLen,
+ unsigned char *outBuf,
+ unsigned int maxOutBufLen,
+ unsigned int *outBufLen,
+ PRBool swapBytes)
+{
+ SECItem it = { 0 };
+ SECItem *dup = NULL;
+ PRBool ret;
+
+#ifdef DEBUG_CONVERSION
+ if (pk12_debugging) {
+ int i;
+ printf("Converted from:\n");
+ for (i = 0; i < inBufLen; i++) {
+ printf("%2x ", inBuf[i]);
+ /*if (i%60 == 0) printf("\n");*/
+ }
+ printf("\n");
+ }
+#endif
+ it.data = inBuf;
+ it.len = inBufLen;
+ dup = SECITEM_DupItem(&it);
+ if (!dup) {
+ return PR_FALSE;
+ }
+ /* If converting Unicode to ASCII, swap bytes before conversion
+ * as neccessary.
+ */
+ if (!toUnicode && swapBytes) {
+ if (p12u_SwapUnicodeBytes(dup) != SECSuccess) {
+ SECITEM_ZfreeItem(dup, PR_TRUE);
+ return PR_FALSE;
+ }
+ }
+ /* Perform the conversion. */
+ ret = PORT_UCS2_UTF8Conversion(toUnicode, dup->data, dup->len,
+ outBuf, maxOutBufLen, outBufLen);
+ SECITEM_ZfreeItem(dup, PR_TRUE);
+
+#ifdef DEBUG_CONVERSION
+ if (pk12_debugging) {
+ int i;
+ printf("Converted to:\n");
+ for (i = 0; i < *outBufLen; i++) {
+ printf("%2x ", outBuf[i]);
+ /*if (i%60 == 0) printf("\n");*/
+ }
+ printf("\n");
+ }
+#endif
+ return ret;
+}
+
+SECStatus
+P12U_UnicodeConversion(PLArenaPool *arena, SECItem *dest, SECItem *src,
+ PRBool toUnicode, PRBool swapBytes)
+{
+ unsigned int allocLen;
+ if (!dest || !src) {
+ return SECFailure;
+ }
+ allocLen = ((toUnicode) ? (src->len << 2) : src->len);
+ if (arena) {
+ dest->data = PORT_ArenaZAlloc(arena, allocLen);
+ } else {
+ dest->data = PORT_ZAlloc(allocLen);
+ }
+ if (PORT_UCS2_ASCIIConversion(toUnicode, src->data, src->len,
+ dest->data, allocLen, &dest->len,
+ swapBytes) == PR_FALSE) {
+ if (!arena) {
+ PORT_Free(dest->data);
+ }
+ dest->data = NULL;
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+/*
+ *
+ */
+SECItem *
+P12U_GetP12FilePassword(PRBool confirmPw, secuPWData *p12FilePw)
+{
+ char *p0 = NULL;
+ SECItem *pwItem = NULL;
+
+ if (p12FilePw == NULL || p12FilePw->source == PW_NONE) {
+ char *p1 = NULL;
+ int rc;
+ for (;;) {
+ p0 = SECU_GetPasswordString(NULL,
+ "Enter password for PKCS12 file: ");
+ if (!confirmPw || p0 == NULL)
+ break;
+ p1 = SECU_GetPasswordString(NULL, "Re-enter password: ");
+ if (p1 == NULL) {
+ PORT_ZFree(p0, PL_strlen(p0));
+ p0 = NULL;
+ break;
+ }
+ rc = PL_strcmp(p0, p1);
+ PORT_ZFree(p1, PL_strlen(p1));
+ if (rc == 0)
+ break;
+ PORT_ZFree(p0, PL_strlen(p0));
+ }
+ } else if (p12FilePw->source == PW_FROMFILE) {
+ p0 = SECU_FilePasswd(NULL, PR_FALSE, p12FilePw->data);
+ } else { /* Plaintext */
+ p0 = PORT_Strdup(p12FilePw->data);
+ }
+
+ if (p0 == NULL) {
+ return NULL;
+ }
+ pwItem = SECITEM_AllocItem(NULL, NULL, PL_strlen(p0) + 1);
+ memcpy(pwItem->data, p0, pwItem->len);
+
+ PORT_ZFree(p0, PL_strlen(p0));
+
+ return pwItem;
+}
+
+SECStatus
+P12U_InitSlot(PK11SlotInfo *slot, secuPWData *slotPw)
+{
+ SECStatus rv;
+
+ /* New databases, initialize keydb password. */
+ if (PK11_NeedUserInit(slot)) {
+ rv = SECU_ChangePW(slot,
+ (slotPw->source == PW_PLAINTEXT) ? slotPw->data : 0,
+ (slotPw->source == PW_FROMFILE) ? slotPw->data : 0);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Failed to initialize slot \"%s\"",
+ PK11_GetSlotName(slot));
+ return SECFailure;
+ }
+ }
+
+ if (PK11_Authenticate(slot, PR_TRUE, slotPw) != SECSuccess) {
+ SECU_PrintError(progName,
+ "Failed to authenticate to PKCS11 slot");
+ PORT_SetError(SEC_ERROR_USER_CANCELLED);
+ pk12uErrno = PK12UERR_USER_CANCELLED;
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+/* This routine takes care of getting the PKCS12 file password, then reading and
+ * verifying the file. It returns the decoder context and a filled in password.
+ * (The password is needed by P12U_ImportPKCS12Object() to import the private
+ * key.)
+ */
+SEC_PKCS12DecoderContext *
+p12U_ReadPKCS12File(SECItem *uniPwp, char *in_file, PK11SlotInfo *slot,
+ secuPWData *slotPw, secuPWData *p12FilePw)
+{
+ SEC_PKCS12DecoderContext *p12dcx = NULL;
+ p12uContext *p12cxt = NULL;
+ SECItem *pwitem = NULL;
+ SECItem p12file = { 0 };
+ SECStatus rv = SECFailure;
+ PRBool swapUnicode = PR_FALSE;
+ PRBool trypw;
+ int error;
+
+#ifdef IS_LITTLE_ENDIAN
+ swapUnicode = PR_TRUE;
+#endif
+
+ p12cxt = p12u_InitContext(PR_TRUE, in_file);
+ if (!p12cxt) {
+ SECU_PrintError(progName, "File Open failed: %s", in_file);
+ pk12uErrno = PK12UERR_INIT_FILE;
+ return NULL;
+ }
+
+ /* get the password */
+ pwitem = P12U_GetP12FilePassword(PR_FALSE, p12FilePw);
+ if (!pwitem) {
+ pk12uErrno = PK12UERR_USER_CANCELLED;
+ goto done;
+ }
+
+ if (P12U_UnicodeConversion(NULL, uniPwp, pwitem, PR_TRUE,
+ swapUnicode) != SECSuccess) {
+ SECU_PrintError(progName, "Unicode conversion failed");
+ pk12uErrno = PK12UERR_UNICODECONV;
+ goto done;
+ }
+ rv = SECU_FileToItem(&p12file, p12cxt->file);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Failed to read from import file");
+ goto done;
+ }
+
+ do {
+ trypw = PR_FALSE; /* normally we do this once */
+ rv = SECFailure;
+ /* init the decoder context */
+ p12dcx = SEC_PKCS12DecoderStart(uniPwp, slot, slotPw,
+ NULL, NULL, NULL, NULL, NULL);
+ if (!p12dcx) {
+ SECU_PrintError(progName, "PKCS12 decoder start failed");
+ pk12uErrno = PK12UERR_PK12DECODESTART;
+ break;
+ }
+
+ /* decode the item */
+ rv = SEC_PKCS12DecoderUpdate(p12dcx, p12file.data, p12file.len);
+
+ if (rv != SECSuccess) {
+ error = PR_GetError();
+ if (error == SEC_ERROR_DECRYPTION_DISALLOWED) {
+ PR_SetError(error, 0);
+ break;
+ }
+ SECU_PrintError(progName, "PKCS12 decoding failed");
+ pk12uErrno = PK12UERR_DECODE;
+ }
+
+ /* does the blob authenticate properly? */
+ rv = SEC_PKCS12DecoderVerify(p12dcx);
+ if (rv != SECSuccess) {
+ if (uniPwp->len == 2) {
+ /* this is a null PW, try once more with a zero-length PW
+ instead of a null string */
+ SEC_PKCS12DecoderFinish(p12dcx);
+ uniPwp->len = 0;
+ trypw = PR_TRUE;
+ } else {
+ SECU_PrintError(progName, "PKCS12 decode not verified");
+ pk12uErrno = PK12UERR_DECODEVERIFY;
+ break;
+ }
+ }
+ } while (trypw == PR_TRUE);
+/* rv has been set at this point */
+
+done:
+ if (rv != SECSuccess) {
+ if (p12dcx != NULL) {
+ SEC_PKCS12DecoderFinish(p12dcx);
+ p12dcx = NULL;
+ }
+ if (uniPwp->data) {
+ SECITEM_ZfreeItem(uniPwp, PR_FALSE);
+ uniPwp->data = NULL;
+ }
+ }
+ PR_Close(p12cxt->file);
+ p12cxt->file = NULL;
+ /* PK11_FreeSlot(slot); */
+ p12u_DestroyContext(&p12cxt, PR_FALSE);
+
+ if (pwitem) {
+ SECITEM_ZfreeItem(pwitem, PR_TRUE);
+ }
+ SECITEM_ZfreeItem(&p12file, PR_FALSE);
+ return p12dcx;
+}
+
+/*
+ * given a filename for pkcs12 file, imports certs and keys
+ *
+ * Change: altitude
+ * I've changed this function so that it takes the keydb and pkcs12 file
+ * passwords from files. The "pwdKeyDB" and "pwdP12File"
+ * variables have been added for this purpose.
+ */
+PRIntn
+P12U_ImportPKCS12Object(char *in_file, PK11SlotInfo *slot,
+ secuPWData *slotPw, secuPWData *p12FilePw)
+{
+ SEC_PKCS12DecoderContext *p12dcx = NULL;
+ SECItem uniPwitem = { 0 };
+ SECStatus rv = SECFailure;
+
+ rv = P12U_InitSlot(slot, slotPw);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Failed to authenticate to \"%s\"",
+ PK11_GetSlotName(slot));
+ pk12uErrno = PK12UERR_PK11GETSLOT;
+ return rv;
+ }
+
+ rv = SECFailure;
+ p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw, p12FilePw);
+
+ if (p12dcx == NULL) {
+ goto loser;
+ }
+
+ /* make sure the bags are okey dokey -- nicknames correct, etc. */
+ rv = SEC_PKCS12DecoderValidateBags(p12dcx, P12U_NicknameCollisionCallback);
+ if (rv != SECSuccess) {
+ if (PORT_GetError() == SEC_ERROR_PKCS12_DUPLICATE_DATA) {
+ pk12uErrno = PK12UERR_CERTALREADYEXISTS;
+ } else {
+ pk12uErrno = PK12UERR_DECODEVALIBAGS;
+ }
+ SECU_PrintError(progName, "PKCS12 decode validate bags failed");
+ goto loser;
+ }
+
+ /* stuff 'em in */
+ rv = SEC_PKCS12DecoderImportBags(p12dcx);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "PKCS12 decode import bags failed");
+ pk12uErrno = PK12UERR_DECODEIMPTBAGS;
+ goto loser;
+ }
+
+ fprintf(stdout, "%s: PKCS12 IMPORT SUCCESSFUL\n", progName);
+ rv = SECSuccess;
+
+loser:
+ if (p12dcx) {
+ SEC_PKCS12DecoderFinish(p12dcx);
+ }
+
+ if (uniPwitem.data) {
+ SECITEM_ZfreeItem(&uniPwitem, PR_FALSE);
+ }
+
+ return rv;
+}
+
+static void
+p12u_DoPKCS12ExportErrors()
+{
+ PRErrorCode error_value;
+
+ error_value = PORT_GetError();
+ if ((error_value == SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY) ||
+ (error_value == SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME) ||
+ (error_value == SEC_ERROR_PKCS12_UNABLE_TO_WRITE)) {
+ fputs(SECU_Strerror(error_value), stderr);
+ } else if (error_value == SEC_ERROR_USER_CANCELLED) {
+ ;
+ } else {
+ fputs(SECU_Strerror(SEC_ERROR_EXPORTING_CERTIFICATES), stderr);
+ }
+}
+
+static void
+p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
+{
+ p12uContext *p12cxt = arg;
+ int writeLen;
+
+ if (!p12cxt || (p12cxt->error == PR_TRUE)) {
+ return;
+ }
+
+ if (p12cxt->file == NULL) {
+ p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
+ p12cxt->error = PR_TRUE;
+ return;
+ }
+
+ writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (PRInt32)len);
+
+ if (writeLen != (int)len) {
+ PR_Close(p12cxt->file);
+ PL_strfree(p12cxt->filename);
+ p12cxt->filename = NULL;
+ p12cxt->file = NULL;
+ p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
+ p12cxt->error = PR_TRUE;
+ }
+}
+
+void
+P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
+ SECOidTag cipher, SECOidTag certCipher,
+ secuPWData *slotPw, secuPWData *p12FilePw)
+{
+ SEC_PKCS12ExportContext *p12ecx = NULL;
+ SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL;
+ SECItem *pwitem = NULL;
+ p12uContext *p12cxt = NULL;
+ CERTCertList *certlist = NULL;
+ CERTCertListNode *node = NULL;
+ PK11SlotInfo *slot = NULL;
+
+ if (P12U_InitSlot(inSlot, slotPw) != SECSuccess) {
+ SECU_PrintError(progName, "Failed to authenticate to \"%s\"",
+ PK11_GetSlotName(inSlot));
+ pk12uErrno = PK12UERR_PK11GETSLOT;
+ goto loser;
+ }
+ certlist = PK11_FindCertsFromNickname(nn, slotPw);
+ if (!certlist) {
+ SECU_PrintError(progName, "find user certs from nickname failed");
+ pk12uErrno = PK12UERR_FINDCERTBYNN;
+ return;
+ }
+
+ if ((SECSuccess != CERT_FilterCertListForUserCerts(certlist)) ||
+ CERT_LIST_EMPTY(certlist)) {
+ PR_fprintf(PR_STDERR, "%s: no user certs from given nickname\n",
+ progName);
+ pk12uErrno = PK12UERR_FINDCERTBYNN;
+ goto loser;
+ }
+
+ /* Password to use for PKCS12 file. */
+ pwitem = P12U_GetP12FilePassword(PR_TRUE, p12FilePw);
+ if (!pwitem) {
+ goto loser;
+ }
+
+ p12cxt = p12u_InitContext(PR_FALSE, outfile);
+ if (!p12cxt) {
+ SECU_PrintError(progName, "Initialization failed: %s", outfile);
+ pk12uErrno = PK12UERR_INIT_FILE;
+ goto loser;
+ }
+
+ if (certlist) {
+ CERTCertificate *cert = NULL;
+ node = CERT_LIST_HEAD(certlist);
+ if (node) {
+ cert = node->cert;
+ }
+ if (cert) {
+ slot = cert->slot; /* use the slot from the first matching
+ certificate to create the context . This is for keygen */
+ }
+ }
+ if (!slot) {
+ SECU_PrintError(progName, "cert does not have a slot");
+ pk12uErrno = PK12UERR_FINDCERTBYNN;
+ goto loser;
+ }
+ p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, slotPw);
+ if (!p12ecx) {
+ SECU_PrintError(progName, "export context creation failed");
+ pk12uErrno = PK12UERR_EXPORTCXCREATE;
+ goto loser;
+ }
+
+ if (SEC_PKCS12AddPasswordIntegrity(p12ecx, pwitem, SEC_OID_SHA1) !=
+ SECSuccess) {
+ SECU_PrintError(progName, "PKCS12 add password integrity failed");
+ pk12uErrno = PK12UERR_PK12ADDPWDINTEG;
+ goto loser;
+ }
+
+ for (node = CERT_LIST_HEAD(certlist);
+ !CERT_LIST_END(node, certlist);
+ node = CERT_LIST_NEXT(node)) {
+ CERTCertificate *cert = node->cert;
+ if (!cert->slot) {
+ SECU_PrintError(progName, "cert does not have a slot");
+ pk12uErrno = PK12UERR_FINDCERTBYNN;
+ goto loser;
+ }
+
+ keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
+ if (certCipher == SEC_OID_UNKNOWN) {
+ certSafe = keySafe;
+ } else {
+ certSafe =
+ SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem, certCipher);
+ }
+
+ if (!certSafe || !keySafe) {
+ SECU_PrintError(progName, "key or cert safe creation failed");
+ pk12uErrno = PK12UERR_CERTKEYSAFE;
+ goto loser;
+ }
+
+ if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
+ CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem, cipher) !=
+ SECSuccess) {
+ SECU_PrintError(progName, "add cert and key failed");
+ pk12uErrno = PK12UERR_ADDCERTKEY;
+ goto loser;
+ }
+ }
+
+ CERT_DestroyCertList(certlist);
+ certlist = NULL;
+
+ if (SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12cxt) !=
+ SECSuccess) {
+ SECU_PrintError(progName, "PKCS12 encode failed");
+ pk12uErrno = PK12UERR_ENCODE;
+ goto loser;
+ }
+
+ p12u_DestroyContext(&p12cxt, PR_FALSE);
+ SECITEM_ZfreeItem(pwitem, PR_TRUE);
+ fprintf(stdout, "%s: PKCS12 EXPORT SUCCESSFUL\n", progName);
+ SEC_PKCS12DestroyExportContext(p12ecx);
+
+ return;
+
+loser:
+ SEC_PKCS12DestroyExportContext(p12ecx);
+
+ if (certlist) {
+ CERT_DestroyCertList(certlist);
+ certlist = NULL;
+ }
+
+ p12u_DestroyContext(&p12cxt, PR_TRUE);
+ if (pwitem) {
+ SECITEM_ZfreeItem(pwitem, PR_TRUE);
+ }
+ p12u_DoPKCS12ExportErrors();
+ return;
+}
+
+PRIntn
+P12U_ListPKCS12File(char *in_file, PK11SlotInfo *slot,
+ secuPWData *slotPw, secuPWData *p12FilePw)
+{
+ SEC_PKCS12DecoderContext *p12dcx = NULL;
+ SECItem uniPwitem = { 0 };
+ SECStatus rv = SECFailure;
+ const SEC_PKCS12DecoderItem *dip;
+
+ p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw, p12FilePw);
+ /* did the blob authenticate properly? */
+ if (p12dcx == NULL) {
+ SECU_PrintError(progName, "PKCS12 decode not verified");
+ pk12uErrno = PK12UERR_DECODEVERIFY;
+ goto loser;
+ }
+ rv = SEC_PKCS12DecoderIterateInit(p12dcx);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "PKCS12 decode iterate bags failed");
+ pk12uErrno = PK12UERR_DECODEIMPTBAGS;
+ rv = SECFailure;
+ } else {
+ int fileCounter = 0;
+ while (SEC_PKCS12DecoderIterateNext(p12dcx, &dip) == SECSuccess) {
+ switch (dip->type) {
+ case SEC_OID_PKCS12_V1_CERT_BAG_ID:
+ printf("Certificate");
+ if (dumpRawFile) {
+ PRFileDesc *fd;
+ char fileName[20];
+ sprintf(fileName, "file%04d.der", ++fileCounter);
+ fd = PR_Open(fileName,
+ PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE,
+ 0600);
+ if (!fd) {
+ SECU_PrintError(progName,
+ "Cannot create output file");
+ } else {
+ PR_Write(fd, dip->der->data, dip->der->len);
+ PR_Close(fd);
+ }
+ } else if (SECU_PrintSignedData(stdout, dip->der,
+ (dip->hasKey) ? "(has private key)"
+ : "",
+ 0, (SECU_PPFunc)SECU_PrintCertificate) !=
+ 0) {
+ SECU_PrintError(progName, "PKCS12 print cert bag failed");
+ }
+ if (dip->friendlyName != NULL) {
+ printf(" Friendly Name: %s\n\n",
+ dip->friendlyName->data);
+ }
+ if (dip->shroudAlg) {
+ SECU_PrintAlgorithmID(stdout, dip->shroudAlg,
+ "Encryption algorithm", 1);
+ }
+ break;
+ case SEC_OID_PKCS12_V1_KEY_BAG_ID:
+ case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
+ printf("Key");
+ if (dip->type == SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID)
+ printf("(shrouded)");
+ printf(":\n");
+ if (dip->friendlyName != NULL) {
+ printf(" Friendly Name: %s\n\n",
+ dip->friendlyName->data);
+ }
+ if (dip->shroudAlg) {
+ SECU_PrintAlgorithmID(stdout, dip->shroudAlg,
+ "Encryption algorithm", 1);
+ }
+ break;
+ default:
+ printf("unknown bag type(%d): %s\n\n", dip->type,
+ SECOID_FindOIDTagDescription(dip->type));
+ break;
+ }
+ }
+ rv = SECSuccess;
+ }
+
+loser:
+
+ if (p12dcx) {
+ SEC_PKCS12DecoderFinish(p12dcx);
+ }
+
+ if (uniPwitem.data) {
+ SECITEM_ZfreeItem(&uniPwitem, PR_FALSE);
+ }
+
+ return rv;
+}
+
+/*
+ * use the oid table description to map a user input string to a particular
+ * oid.
+ */
+SECOidTag
+PKCS12U_MapCipherFromString(char *cipherString, int keyLen)
+{
+ SECOidTag tag;
+ SECOidData *oid;
+ SECOidTag cipher;
+
+ /* future enhancement: accept dotted oid spec? */
+
+ /* future enhancement: provide 'friendlier' typed in names for
+ * pbe mechanisms.
+ */
+
+ /* look for the oid tag by Description */
+ cipher = SEC_OID_UNKNOWN;
+ for (tag = 1; (oid = SECOID_FindOIDByTag(tag)) != NULL; tag++) {
+ /* only interested in oids that we actually understand */
+ if (oid->mechanism == CKM_INVALID_MECHANISM) {
+ continue;
+ }
+ if (PORT_Strcasecmp(oid->desc, cipherString) != 0) {
+ continue;
+ }
+ /* we found a match... get the PBE version of this
+ * cipher... */
+ if (!SEC_PKCS5IsAlgorithmPBEAlgTag(tag)) {
+ cipher = SEC_PKCS5GetPBEAlgorithm(tag, keyLen);
+ /* no eqivalent PKCS5/PKCS12 cipher, use the raw
+ * encryption tag we got and pass it directly in,
+ * pkcs12 will use the pkcsv5 mechanism */
+ if (cipher == SEC_OID_PKCS5_PBES2) {
+ cipher = tag;
+ } else if (cipher == SEC_OID_PKCS5_PBMAC1) {
+ /* make sure we have not macing ciphers here */
+ cipher = SEC_OID_UNKNOWN;
+ }
+ } else {
+ cipher = tag;
+ }
+ break;
+ }
+ return cipher;
+}
+
+static void
+p12u_EnableAllCiphers()
+{
+ SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
+ SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
+ SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
+ SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
+ SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
+ SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
+ SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
+}
+
+static PRUintn
+P12U_Init(char *dir, char *dbprefix, PRBool listonly)
+{
+ SECStatus rv;
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ if (listonly && NSS_NoDB_Init("") == SECSuccess) {
+ rv = SECSuccess;
+ } else {
+ rv = NSS_Initialize(dir, dbprefix, dbprefix, "secmod.db", 0);
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ exit(-1);
+ }
+
+ /* setup unicode callback functions */
+ PORT_SetUCS2_ASCIIConversionFunction(p12u_ucs2_ascii_conversion_function);
+ /* use the defaults for UCS4-UTF8 and UCS2-UTF8 */
+
+ p12u_EnableAllCiphers();
+
+ return 0;
+}
+
+enum {
+ opt_CertDir = 0,
+ opt_TokenName,
+ opt_Import,
+ opt_SlotPWFile,
+ opt_SlotPW,
+ opt_List,
+ opt_Nickname,
+ opt_Export,
+ opt_Raw,
+ opt_P12FilePWFile,
+ opt_P12FilePW,
+ opt_DBPrefix,
+ opt_Debug,
+ opt_Cipher,
+ opt_CertCipher,
+ opt_KeyLength,
+ opt_CertKeyLength
+};
+
+static secuCommandFlag pk12util_options[] =
+ {
+ { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Import */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_SlotPWFile */ 'k', PR_TRUE, 0, PR_FALSE },
+ { /* opt_SlotPW */ 'K', PR_TRUE, 0, PR_FALSE },
+ { /* opt_List */ 'l', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Export */ 'o', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Raw */ 'r', PR_FALSE, 0, PR_FALSE },
+ { /* opt_P12FilePWFile */ 'w', PR_TRUE, 0, PR_FALSE },
+ { /* opt_P12FilePW */ 'W', PR_TRUE, 0, PR_FALSE },
+ { /* opt_DBPrefix */ 'P', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Debug */ 'v', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Cipher */ 'c', PR_TRUE, 0, PR_FALSE },
+ { /* opt_CertCipher */ 'C', PR_TRUE, 0, PR_FALSE },
+ { /* opt_KeyLength */ 'm', PR_TRUE, 0, PR_FALSE, "key_len" },
+ { /* opt_CertKeyLength */ 0, PR_TRUE, 0, PR_FALSE, "cert_key_len" }
+ };
+
+int
+main(int argc, char **argv)
+{
+ secuPWData slotPw = { PW_NONE, NULL };
+ secuPWData p12FilePw = { PW_NONE, NULL };
+ PK11SlotInfo *slot;
+ char *slotname = NULL;
+ char *import_file = NULL;
+ char *export_file = NULL;
+ char *dbprefix = "";
+ SECStatus rv;
+ SECOidTag cipher =
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
+ SECOidTag certCipher;
+ int keyLen = 0;
+ int certKeyLen = 0;
+ secuCommand pk12util;
+
+#ifdef _CRTDBG_MAP_ALLOC
+ _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
+#endif
+
+ pk12util.numCommands = 0;
+ pk12util.commands = 0;
+ pk12util.numOptions = sizeof(pk12util_options) / sizeof(secuCommandFlag);
+ pk12util.options = pk12util_options;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &pk12util);
+
+ if (rv != SECSuccess)
+ Usage(progName);
+
+ pk12_debugging = pk12util.options[opt_Debug].activated;
+
+ if ((pk12util.options[opt_Import].activated +
+ pk12util.options[opt_Export].activated +
+ pk12util.options[opt_List].activated) != 1) {
+ Usage(progName);
+ }
+
+ if (pk12util.options[opt_Export].activated &&
+ !pk12util.options[opt_Nickname].activated) {
+ Usage(progName);
+ }
+
+ slotname = SECU_GetOptionArg(&pk12util, opt_TokenName);
+
+ import_file = (pk12util.options[opt_List].activated) ? SECU_GetOptionArg(&pk12util, opt_List)
+ : SECU_GetOptionArg(&pk12util, opt_Import);
+ export_file = SECU_GetOptionArg(&pk12util, opt_Export);
+
+ if (pk12util.options[opt_P12FilePWFile].activated) {
+ p12FilePw.source = PW_FROMFILE;
+ p12FilePw.data = PORT_Strdup(pk12util.options[opt_P12FilePWFile].arg);
+ }
+
+ if (pk12util.options[opt_P12FilePW].activated) {
+ p12FilePw.source = PW_PLAINTEXT;
+ p12FilePw.data = PORT_Strdup(pk12util.options[opt_P12FilePW].arg);
+ }
+
+ if (pk12util.options[opt_SlotPWFile].activated) {
+ slotPw.source = PW_FROMFILE;
+ slotPw.data = PORT_Strdup(pk12util.options[opt_SlotPWFile].arg);
+ }
+
+ if (pk12util.options[opt_SlotPW].activated) {
+ slotPw.source = PW_PLAINTEXT;
+ slotPw.data = PORT_Strdup(pk12util.options[opt_SlotPW].arg);
+ }
+
+ if (pk12util.options[opt_CertDir].activated) {
+ SECU_ConfigDirectory(pk12util.options[opt_CertDir].arg);
+ }
+ if (pk12util.options[opt_DBPrefix].activated) {
+ dbprefix = pk12util.options[opt_DBPrefix].arg;
+ }
+ if (pk12util.options[opt_Raw].activated) {
+ dumpRawFile = PR_TRUE;
+ }
+ if (pk12util.options[opt_KeyLength].activated) {
+ keyLen = atoi(pk12util.options[opt_KeyLength].arg);
+ }
+ if (pk12util.options[opt_CertKeyLength].activated) {
+ certKeyLen = atoi(pk12util.options[opt_CertKeyLength].arg);
+ }
+
+ P12U_Init(SECU_ConfigDirectory(NULL), dbprefix,
+ pk12util.options[opt_List].activated);
+
+ if (!slotname || PL_strcmp(slotname, "internal") == 0)
+ slot = PK11_GetInternalKeySlot();
+ else
+ slot = PK11_FindSlotByName(slotname);
+
+ if (!slot) {
+ SECU_PrintError(progName, "Invalid slot \"%s\"", slotname);
+ pk12uErrno = PK12UERR_PK11GETSLOT;
+ goto done;
+ }
+
+ if (pk12util.options[opt_Cipher].activated) {
+ char *cipherString = pk12util.options[opt_Cipher].arg;
+
+ cipher = PKCS12U_MapCipherFromString(cipherString, keyLen);
+ /* We only want encryption PBE's. make sure we don't have
+ * any MAC pbes */
+ if (cipher == SEC_OID_UNKNOWN) {
+ PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+ SECU_PrintError(progName, "Algorithm: \"%s\"", cipherString);
+ pk12uErrno = PK12UERR_INVALIDALGORITHM;
+ goto done;
+ }
+ }
+
+ certCipher = PK11_IsFIPS() ? SEC_OID_UNKNOWN : SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
+ if (pk12util.options[opt_CertCipher].activated) {
+ char *cipherString = pk12util.options[opt_CertCipher].arg;
+
+ if (PORT_Strcasecmp(cipherString, "none") == 0) {
+ certCipher = SEC_OID_UNKNOWN;
+ } else {
+ certCipher = PKCS12U_MapCipherFromString(cipherString, certKeyLen);
+ /* If the user requested a cipher and we didn't find it, then
+ * don't just silently not encrypt. */
+ if (cipher == SEC_OID_UNKNOWN) {
+ PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+ SECU_PrintError(progName, "Algorithm: \"%s\"", cipherString);
+ pk12uErrno = PK12UERR_INVALIDALGORITHM;
+ goto done;
+ }
+ }
+ }
+
+ if (pk12util.options[opt_Import].activated) {
+ P12U_ImportPKCS12Object(import_file, slot, &slotPw, &p12FilePw);
+
+ } else if (pk12util.options[opt_Export].activated) {
+ P12U_ExportPKCS12Object(pk12util.options[opt_Nickname].arg,
+ export_file, slot, cipher, certCipher,
+ &slotPw, &p12FilePw);
+
+ } else if (pk12util.options[opt_List].activated) {
+ P12U_ListPKCS12File(import_file, slot, &slotPw, &p12FilePw);
+
+ } else {
+ Usage(progName);
+ pk12uErrno = PK12UERR_USAGE;
+ }
+
+done:
+ if (import_file != NULL)
+ PORT_ZFree(import_file, PL_strlen(import_file));
+ if (export_file != NULL)
+ PORT_ZFree(export_file, PL_strlen(export_file));
+ if (slotPw.data != NULL)
+ PORT_ZFree(slotPw.data, PL_strlen(slotPw.data));
+ if (p12FilePw.data != NULL)
+ PORT_ZFree(p12FilePw.data, PL_strlen(p12FilePw.data));
+ if (slot)
+ PK11_FreeSlot(slot);
+ if (NSS_Shutdown() != SECSuccess) {
+ pk12uErrno = 1;
+ }
+ PL_ArenaFinish();
+ PR_Cleanup();
+ return pk12uErrno;
+}
diff --git a/security/nss/cmd/pk12util/pk12util.gyp b/security/nss/cmd/pk12util/pk12util.gyp
new file mode 100644
index 000000000..5eb59e04b
--- /dev/null
+++ b/security/nss/cmd/pk12util/pk12util.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pk12util',
+ 'type': 'executable',
+ 'sources': [
+ 'pk12util.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/pk12util/pk12util.h b/security/nss/cmd/pk12util/pk12util.h
new file mode 100644
index 000000000..d1588814e
--- /dev/null
+++ b/security/nss/cmd/pk12util/pk12util.h
@@ -0,0 +1,40 @@
+/* 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/. */
+
+/*
+ * ERROR codes in pk12util
+ * - should be organized better later
+ */
+#define PK12UERR_USER_CANCELLED 1
+#define PK12UERR_USAGE 2
+#define PK12UERR_CERTDB_OPEN 8
+#define PK12UERR_KEYDB_OPEN 9
+#define PK12UERR_INIT_FILE 10
+#define PK12UERR_UNICODECONV 11
+#define PK12UERR_TMPDIGCREATE 12
+#define PK12UERR_PK11GETSLOT 13
+#define PK12UERR_PK12DECODESTART 14
+#define PK12UERR_IMPORTFILEREAD 15
+#define PK12UERR_DECODE 16
+#define PK12UERR_DECODEVERIFY 17
+#define PK12UERR_DECODEVALIBAGS 18
+#define PK12UERR_DECODEIMPTBAGS 19
+#define PK12UERR_CERTALREADYEXISTS 20
+#define PK12UERR_PATCHDB 22
+#define PK12UERR_GETDEFCERTDB 23
+#define PK12UERR_FINDCERTBYNN 24
+#define PK12UERR_EXPORTCXCREATE 25
+#define PK12UERR_PK12ADDPWDINTEG 26
+#define PK12UERR_CERTKEYSAFE 27
+#define PK12UERR_ADDCERTKEY 28
+#define PK12UERR_ENCODE 29
+#define PK12UERR_INVALIDALGORITHM 30
+
+/* additions for importing and exporting PKCS 12 files */
+typedef struct p12uContextStr {
+ char *filename; /* name of file */
+ PRFileDesc *file; /* pointer to file */
+ PRBool error; /* error occurred? */
+ int errorValue; /* which error occurred? */
+} p12uContext;
diff --git a/security/nss/cmd/pk1sign/Makefile b/security/nss/cmd/pk1sign/Makefile
new file mode 100644
index 000000000..6e1d4ecdf
--- /dev/null
+++ b/security/nss/cmd/pk1sign/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/pk1sign/manifest.mn b/security/nss/cmd/pk1sign/manifest.mn
new file mode 100644
index 000000000..009461166
--- /dev/null
+++ b/security/nss/cmd/pk1sign/manifest.mn
@@ -0,0 +1,15 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+CSRCS = pk1sign.c
+
+REQUIRES = seccmd
+
+PROGRAM = pk1sign
+
diff --git a/security/nss/cmd/pk1sign/pk1sign.c b/security/nss/cmd/pk1sign/pk1sign.c
new file mode 100644
index 000000000..085aa1659
--- /dev/null
+++ b/security/nss/cmd/pk1sign/pk1sign.c
@@ -0,0 +1,318 @@
+/* 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/. */
+
+/*
+ * pk1sign
+ */
+
+#include "nspr.h"
+#include "plgetopt.h"
+#include "secutil.h"
+#include "secpkcs7.h"
+#include "cert.h"
+#include "certdb.h"
+#include "sechash.h" /* for HASH_GetHashObject() */
+#include "nss.h"
+#include "pk11func.h"
+#include "cryptohi.h"
+#include "plbase64.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
+extern int fread(char *, size_t, size_t, FILE *);
+extern int fwrite(char *, size_t, size_t, FILE *);
+extern int fprintf(FILE *, char *, ...);
+#endif
+
+static secuPWData pwdata = { PW_NONE, 0 };
+
+SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
+
+SEC_ASN1Template CERTSignatureDataTemplate[] =
+ {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CERTSignedData) },
+ { SEC_ASN1_INLINE,
+ offsetof(CERTSignedData, signatureAlgorithm),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { SEC_ASN1_BIT_STRING,
+ offsetof(CERTSignedData, signature) },
+ { 0 }
+ };
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s -k keyname [-d keydir] [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s Nickname of key to use for signature\n",
+ "-k keyname");
+ fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
+ "-d keydir");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ fprintf(stderr, "%-20s Password to the key databse\n", "-p");
+ fprintf(stderr, "%-20s password file\n", "-f");
+ exit(-1);
+}
+
+static int
+ExportPublicKey(FILE *outFile, CERTCertificate *cert)
+{
+ char *data;
+ SECKEYPublicKey *publicKey;
+ SECItem *item;
+
+ if (!cert)
+ return -1;
+
+ publicKey = CERT_ExtractPublicKey(cert);
+ if (!publicKey)
+ return -1;
+
+ item = SECKEY_EncodeDERSubjectPublicKeyInfo(publicKey);
+ SECKEY_DestroyPublicKey(publicKey);
+ if (!item)
+ return -1;
+
+ data = PL_Base64Encode((const char *)item->data, item->len, NULL);
+ SECITEM_FreeItem(item, PR_TRUE);
+ if (!data)
+ return -1;
+
+ fputs("pubkey:\n", outFile);
+ fputs(data, outFile);
+ fputs("\n", outFile);
+ PR_Free(data);
+
+ return 0;
+}
+
+static int
+SignFile(FILE *outFile, PRFileDesc *inFile, CERTCertificate *cert)
+{
+ SECItem data2sign;
+ SECStatus rv;
+ SECOidTag algID;
+ CERTSignedData sd;
+ SECKEYPrivateKey *privKey = NULL;
+ char *data = NULL;
+ PLArenaPool *arena = NULL;
+ SECItem *result = NULL;
+ int returnValue = 0;
+
+ if (outFile == NULL || inFile == NULL || cert == NULL) {
+ return -1;
+ }
+
+ /* suck the file in */
+ if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE,
+ PR_FALSE) != SECSuccess) {
+ return -1;
+ }
+
+ privKey = NULL;
+ privKey = PK11_FindKeyByAnyCert(cert, NULL);
+ if (!privKey) {
+ returnValue = -1;
+ goto loser;
+ }
+
+ algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, SEC_OID_SHA1);
+ if (algID == SEC_OID_UNKNOWN) {
+ returnValue = -1;
+ goto loser;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ PORT_Memset(&sd, 0, sizeof(CERTSignedData));
+
+ rv = SEC_SignData(&(sd.signature), data2sign.data, data2sign.len, privKey, algID);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "Could not sign.\n");
+ returnValue = -1;
+ goto loser;
+ }
+ sd.signature.len = sd.signature.len << 3;
+
+ rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algID, 0);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "Could not set alg id.\n");
+ returnValue = -1;
+ goto loser;
+ }
+
+ result = SEC_ASN1EncodeItem(arena, NULL, &sd, CERTSignatureDataTemplate);
+ SECITEM_FreeItem(&(sd.signature), PR_FALSE);
+
+ if (!result) {
+ fprintf(stderr, "Could not encode.\n");
+ returnValue = -1;
+ goto loser;
+ }
+
+ data = PL_Base64Encode((const char *)result->data, result->len, NULL);
+ if (!data) {
+ returnValue = -1;
+ goto loser;
+ }
+
+ fputs("signature:\n", outFile);
+ fputs(data, outFile);
+ fputs("\n", outFile);
+ ExportPublicKey(outFile, cert);
+
+loser:
+ if (privKey) {
+ SECKEY_DestroyPrivateKey(privKey);
+ }
+ if (data) {
+ PORT_Free(data);
+ }
+ PORT_FreeArena(arena, PR_FALSE);
+
+ return returnValue;
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ FILE *outFile;
+ PRFileDesc *inFile;
+ char *keyName = NULL;
+ CERTCertDBHandle *certHandle;
+ CERTCertificate *cert = NULL;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus rv;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ inFile = NULL;
+ outFile = NULL;
+ keyName = NULL;
+
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv, "ed:k:i:o:p:f:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'i':
+ inFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'k':
+ keyName = strdup(optstate->value);
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "wb");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+ case 'p':
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = strdup(optstate->value);
+ break;
+
+ case 'f':
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
+ }
+ }
+
+ if (!keyName)
+ Usage(progName);
+
+ if (!inFile)
+ inFile = PR_STDIN;
+ if (!outFile)
+ outFile = stdout;
+
+ /* Call the initialization routines */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_Init(SECU_ConfigDirectory(NULL));
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ goto loser;
+ }
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ /* open cert database */
+ certHandle = CERT_GetDefaultCertDB();
+ if (certHandle == NULL) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ /* find cert */
+ cert = CERT_FindCertByNickname(certHandle, keyName);
+ if (cert == NULL) {
+ SECU_PrintError(progName,
+ "the corresponding cert for key \"%s\" does not exist",
+ keyName);
+ rv = SECFailure;
+ goto loser;
+ }
+
+ if (SignFile(outFile, inFile, cert)) {
+ SECU_PrintError(progName, "problem signing data");
+ rv = SECFailure;
+ goto loser;
+ }
+
+loser:
+ if (pwdata.data) {
+ PORT_Free(pwdata.data);
+ }
+ if (keyName) {
+ PORT_Free(keyName);
+ }
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+ if (inFile && inFile != PR_STDIN) {
+ PR_Close(inFile);
+ }
+ if (outFile && outFile != stdout) {
+ fclose(outFile);
+ }
+ if (NSS_Shutdown() != SECSuccess) {
+ SECU_PrintError(progName, "NSS shutdown:");
+ exit(1);
+ }
+
+ return (rv != SECSuccess);
+}
diff --git a/security/nss/cmd/pk1sign/pk1sign.gyp b/security/nss/cmd/pk1sign/pk1sign.gyp
new file mode 100644
index 000000000..ff77c5575
--- /dev/null
+++ b/security/nss/cmd/pk1sign/pk1sign.gyp
@@ -0,0 +1,24 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pk1sign',
+ 'type': 'executable',
+ 'sources': [
+ 'pk1sign.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/pkix-errcodes/Makefile b/security/nss/cmd/pkix-errcodes/Makefile
new file mode 100644
index 000000000..6e1d4ecdf
--- /dev/null
+++ b/security/nss/cmd/pkix-errcodes/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/pkix-errcodes/manifest.mn b/security/nss/cmd/pkix-errcodes/manifest.mn
new file mode 100644
index 000000000..bef063692
--- /dev/null
+++ b/security/nss/cmd/pkix-errcodes/manifest.mn
@@ -0,0 +1,15 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+CSRCS = pkix-errcodes.c
+
+REQUIRES = seccmd
+
+PROGRAM = pkix-errcodes
+
diff --git a/security/nss/cmd/pkix-errcodes/pkix-errcodes.c b/security/nss/cmd/pkix-errcodes/pkix-errcodes.c
new file mode 100644
index 000000000..ceff098ac
--- /dev/null
+++ b/security/nss/cmd/pkix-errcodes/pkix-errcodes.c
@@ -0,0 +1,35 @@
+/* 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/. */
+/*
+ * dumpcert.c
+ *
+ * dump certificate sample application
+ *
+ */
+
+#include <stdio.h>
+
+#include "pkix.h"
+#include "pkixt.h"
+#include "pkix_error.h"
+
+#undef PKIX_ERRORENTRY
+#define PKIX_ERRORENTRY(name, desc, plerr) #name
+
+const char *const PKIX_ErrorNames[] =
+ {
+#include "pkix_errorstrings.h"
+ };
+
+#undef PKIX_ERRORENTRY
+
+int
+main(int argc, char **argv)
+{
+ int i = 0;
+ for (; i < PKIX_NUMERRORCODES; ++i) {
+ printf("code %d %s\n", i, PKIX_ErrorNames[i]);
+ }
+ return 0;
+}
diff --git a/security/nss/cmd/pkix-errcodes/pkix-errcodes.gyp b/security/nss/cmd/pkix-errcodes/pkix-errcodes.gyp
new file mode 100644
index 000000000..e305c07f8
--- /dev/null
+++ b/security/nss/cmd/pkix-errcodes/pkix-errcodes.gyp
@@ -0,0 +1,24 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkix-errcodes',
+ 'type': 'executable',
+ 'sources': [
+ 'pkix-errcodes.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/platlibs.gypi b/security/nss/cmd/platlibs.gypi
new file mode 100644
index 000000000..5c3cc34e2
--- /dev/null
+++ b/security/nss/cmd/platlibs.gypi
@@ -0,0 +1,78 @@
+# 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/.
+{
+ 'variables': {
+ 'use_static_libs%': 0,
+ },
+ 'target_defaults': {
+ 'dependencies': [
+ '<(DEPTH)/cmd/lib/lib.gyp:sectool',
+ ],
+ 'conditions': [
+ ['moz_fold_libs==0', {
+ 'dependencies': [
+ '<(DEPTH)/lib/util/util.gyp:nssutil3',
+ ],
+ }],
+ ['<(use_static_libs)==1', {
+ 'defines': ['NSS_USE_STATIC_LIBS'],
+ 'dependencies': [
+ '<(DEPTH)/lib/smime/smime.gyp:smime',
+ '<(DEPTH)/lib/ssl/ssl.gyp:ssl',
+ '<(DEPTH)/lib/nss/nss.gyp:nss_static',
+ '<(DEPTH)/lib/pkcs12/pkcs12.gyp:pkcs12',
+ '<(DEPTH)/lib/pkcs7/pkcs7.gyp:pkcs7',
+ '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
+ '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
+ '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap',
+ '<(DEPTH)/lib/softoken/softoken.gyp:softokn',
+ '<(DEPTH)/lib/certdb/certdb.gyp:certdb',
+ '<(DEPTH)/lib/pki/pki.gyp:nsspki',
+ '<(DEPTH)/lib/dev/dev.gyp:nssdev',
+ '<(DEPTH)/lib/base/base.gyp:nssb',
+ '<(DEPTH)/lib/freebl/freebl.gyp:freebl',
+ '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap',
+ '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
+ '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3',
+ ],
+ 'conditions': [
+ [ 'disable_dbm==0', {
+ 'dependencies': [
+ '<(DEPTH)/lib/dbm/src/src.gyp:dbm',
+ '<(DEPTH)/lib/softoken/legacydb/legacydb.gyp:nssdbm',
+ ],
+ }],
+ [ 'disable_libpkix==0', {
+ 'dependencies': [
+ '<(DEPTH)/lib/libpkix/pkix/certsel/certsel.gyp:pkixcertsel',
+ '<(DEPTH)/lib/libpkix/pkix/checker/checker.gyp:pkixchecker',
+ '<(DEPTH)/lib/libpkix/pkix/params/params.gyp:pkixparams',
+ '<(DEPTH)/lib/libpkix/pkix/results/results.gyp:pkixresults',
+ '<(DEPTH)/lib/libpkix/pkix/top/top.gyp:pkixtop',
+ '<(DEPTH)/lib/libpkix/pkix/util/util.gyp:pkixutil',
+ '<(DEPTH)/lib/libpkix/pkix/crlsel/crlsel.gyp:pkixcrlsel',
+ '<(DEPTH)/lib/libpkix/pkix/store/store.gyp:pkixstore',
+ '<(DEPTH)/lib/libpkix/pkix_pl_nss/pki/pki.gyp:pkixpki',
+ '<(DEPTH)/lib/libpkix/pkix_pl_nss/system/system.gyp:pkixsystem',
+ '<(DEPTH)/lib/libpkix/pkix_pl_nss/module/module.gyp:pkixmodule'
+ ],
+ }],
+ ]},{ # !use_static_libs
+ 'conditions': [
+ ['moz_fold_libs==0', {
+ 'dependencies': [
+ '<(DEPTH)/lib/ssl/ssl.gyp:ssl3',
+ '<(DEPTH)/lib/smime/smime.gyp:smime3',
+ '<(DEPTH)/lib/nss/nss.gyp:nss3',
+ ],
+ }, {
+ 'libraries': [
+ '<(moz_folded_library_name)',
+ ],
+ }]
+ ],
+ }],
+ ],
+ }
+}
diff --git a/security/nss/cmd/platlibs.mk b/security/nss/cmd/platlibs.mk
new file mode 100644
index 000000000..032eed07b
--- /dev/null
+++ b/security/nss/cmd/platlibs.mk
@@ -0,0 +1,262 @@
+#
+# 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/.
+
+ifeq ($(BUILD_SUN_PKG), 1)
+
+# set RPATH-type linker instructions here so they can be used in the shared
+# version and in the mixed (static nss libs/shared NSPR libs) version.
+
+ifeq ($(OS_ARCH), SunOS)
+ifeq ($(USE_64), 1)
+EXTRA_SHARED_LIBS += -R '$$ORIGIN/../lib:/usr/lib/mps/secv1/64:/usr/lib/mps/64'
+else
+EXTRA_SHARED_LIBS += -R '$$ORIGIN/../lib:/usr/lib/mps/secv1:/usr/lib/mps'
+endif
+endif
+
+ifeq ($(OS_ARCH), Linux)
+ifeq ($(USE_64), 1)
+EXTRA_SHARED_LIBS += -Wl,-rpath,'$$ORIGIN/../lib64:/opt/sun/private/lib64:$$ORIGIN/../lib'
+else
+EXTRA_SHARED_LIBS += -Wl,-rpath,'$$ORIGIN/../lib:/opt/sun/private/lib'
+endif
+endif
+
+endif # BUILD_SUN_PKG
+
+ifdef NSS_DISABLE_DBM
+DBMLIB = $(NULL)
+else
+DBMLIB = $(DIST)/lib/$(LIB_PREFIX)dbm.$(LIB_SUFFIX)
+endif
+
+ifdef USE_STATIC_LIBS
+
+DEFINES += -DNSS_USE_STATIC_LIBS
+# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
+ifndef NSS_USE_SYSTEM_FREEBL
+CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
+SOFTOKENLIB=$(DIST)/lib/$(LIB_PREFIX)softokn.$(LIB_SUFFIX)
+else
+# Use the system installed freebl static library and set softoken one to empty.
+# Some tools need to link statically with freebl but none with softoken. Only
+# the softoken shared library, not the static one, is installed in the system.
+CRYPTOLIB=$(FREEBL_LIB_DIR)/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
+SOFTOKENLIB=
+EXTRA_SHARED_LIBS += \
+ -L$(SOFTOKEN_LIB_DIR) \
+ -lsoftokn3 \
+ $(NULL)
+endif
+
+ifndef NSS_DISABLE_LIBPKIX
+ifndef NSS_BUILD_SOFTOKEN_ONLY
+PKIXLIB = \
+ $(DIST)/lib/$(LIB_PREFIX)pkixtop.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkixutil.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkixsystem.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkixcrlsel.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkixmodule.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkixstore.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkixparams.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkixchecker.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkixpki.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkixtop.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkixresults.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkixcertsel.$(LIB_SUFFIX)
+endif
+endif
+
+NSS_LIBS_1=
+SECTOOL_LIB=
+NSS_LIBS_2=
+NSS_LIBS_3=
+NSS_LIBS_4=
+
+ifneq ($(NSS_BUILD_UTIL_ONLY),1)
+SECTOOL_LIB = \
+ $(DIST)/lib/$(LIB_PREFIX)sectool.$(LIB_SUFFIX) \
+ $(NULL)
+else
+SECTOOL_LIB = \
+ $(NULL)
+endif
+
+ifneq ($(NSS_BUILD_SOFTOKEN_ONLY),1)
+ifeq ($(OS_ARCH), WINNT)
+# breakdown for windows
+NSS_LIBS_1 = \
+ $(DIST)/lib/$(LIB_PREFIX)smime.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)ssl.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nss.$(LIB_SUFFIX) \
+ $(NULL)
+NSS_LIBS_2 = \
+ $(DIST)/lib/$(LIB_PREFIX)pkcs12.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkcs7.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)certhi.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)cryptohi.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pk11wrap.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)certdb.$(LIB_SUFFIX) \
+ $(NULL)
+NSS_LIBS_3 = \
+ $(DIST)/lib/$(LIB_PREFIX)nsspki.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nssdev.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nssb.$(LIB_SUFFIX) \
+ $(PKIXLIB) \
+ $(DBMLIB) \
+ $(NULL)
+NSS_LIBS_4 = \
+ $(SQLITE_LIB_DIR)/$(LIB_PREFIX)$(SQLITE_LIB_NAME).$(LIB_SUFFIX) \
+ $(NSSUTIL_LIB_DIR)/$(LIB_PREFIX)nssutil3.$(LIB_SUFFIX) \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.$(LIB_SUFFIX) \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.$(LIB_SUFFIX) \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.$(LIB_SUFFIX) \
+ $(NULL)
+else
+# breakdown for others
+NSS_LIBS_1 = \
+ $(DIST)/lib/$(LIB_PREFIX)smime.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)ssl.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nss.$(LIB_SUFFIX) \
+ $(NULL)
+SECTOOL_LIB = \
+ $(DIST)/lib/$(LIB_PREFIX)sectool.$(LIB_SUFFIX) \
+ $(NULL)
+NSS_LIBS_2 = \
+ $(DIST)/lib/$(LIB_PREFIX)pkcs12.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkcs7.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)certhi.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)cryptohi.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pk11wrap.$(LIB_SUFFIX) \
+ $(NULL)
+NSS_LIBS_3 = \
+ $(DIST)/lib/$(LIB_PREFIX)certdb.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nsspki.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nssdev.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nssb.$(LIB_SUFFIX) \
+ $(NULL)
+NSS_LIBS_4 = \
+ $(DBMLIB) \
+ $(PKIXLIB) \
+ $(DIST)/lib/$(LIB_PREFIX)nss.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pk11wrap.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)certhi.$(LIB_SUFFIX) \
+ $(NULL)
+endif
+endif
+
+# can't do this in manifest.mn because OS_ARCH isn't defined there.
+ifeq ($(OS_ARCH), WINNT)
+
+EXTRA_LIBS += \
+ $(NSS_LIBS_1) \
+ $(SECTOOL_LIB) \
+ $(NSS_LIBS_2) \
+ $(SOFTOKENLIB) \
+ $(CRYPTOLIB) \
+ $(NSS_LIBS_3) \
+ $(NSS_LIBS_4) \
+ $(NULL)
+
+# $(PROGRAM) has NO explicit dependencies on $(OS_LIBS)
+#OS_LIBS += \
+ wsock32.lib \
+ winmm.lib \
+ $(NULL)
+else
+
+EXTRA_LIBS += \
+ $(NSS_LIBS_1) \
+ $(SECTOOL_LIB) \
+ $(NSS_LIBS_2) \
+ $(SOFTOKENLIB) \
+ $(NSS_LIBS_3) \
+ $(CRYPTOLIB) \
+ $(NSS_LIBS_4) \
+ $(NULL)
+
+ifeq ($(OS_ARCH), AIX)
+EXTRA_SHARED_LIBS += -brtl
+endif
+
+# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
+# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
+EXTRA_SHARED_LIBS += \
+ -L$(SQLITE_LIB_DIR) \
+ -l$(SQLITE_LIB_NAME) \
+ -L$(NSSUTIL_LIB_DIR) \
+ -lnssutil3 \
+ -L$(NSPR_LIB_DIR) \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4 \
+ $(NULL)
+endif
+
+else # USE_STATIC_LIBS
+# can't do this in manifest.mn because OS_ARCH isn't defined there.
+ifeq ($(OS_ARCH), WINNT)
+
+# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
+EXTRA_LIBS += \
+ $(DIST)/lib/$(LIB_PREFIX)sectool.$(LIB_SUFFIX) \
+ $(NSSUTIL_LIB_DIR)/$(IMPORT_LIB_PREFIX)nssutil3$(IMPORT_LIB_SUFFIX) \
+ $(DIST)/lib/$(IMPORT_LIB_PREFIX)smime3$(IMPORT_LIB_SUFFIX) \
+ $(DIST)/lib/$(IMPORT_LIB_PREFIX)ssl3$(IMPORT_LIB_SUFFIX) \
+ $(DIST)/lib/$(IMPORT_LIB_PREFIX)nss3$(IMPORT_LIB_SUFFIX) \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4$(IMPORT_LIB_SUFFIX) \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4$(IMPORT_LIB_SUFFIX) \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4$(IMPORT_LIB_SUFFIX) \
+ $(NULL)
+
+# $(PROGRAM) has NO explicit dependencies on $(OS_LIBS)
+#OS_LIBS += \
+ wsock32.lib \
+ winmm.lib \
+ $(NULL)
+else
+
+# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
+EXTRA_LIBS += \
+ $(DIST)/lib/$(LIB_PREFIX)sectool.$(LIB_SUFFIX) \
+ $(NULL)
+
+ifeq ($(OS_ARCH), AIX)
+EXTRA_SHARED_LIBS += -brtl
+endif
+
+# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
+# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib \
+ -lssl3 \
+ -lsmime3 \
+ -lnss3 \
+ -L$(NSSUTIL_LIB_DIR) \
+ -lnssutil3 \
+ -L$(NSPR_LIB_DIR) \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4 \
+ $(NULL)
+endif
+
+ifdef SOFTOKEN_LIB_DIR
+ifdef NSS_USE_SYSTEM_FREEBL
+EXTRA_SHARED_LIBS += -L$(SOFTOKEN_LIB_DIR) -lsoftokn3
+endif
+endif
+
+endif # USE_STATIC_LIBS
+
+# If a platform has a system freebl, set USE_SYSTEM_FREEBL to 1 and
+# FREEBL_LIBS to the linker command-line arguments for the system nss-util
+# (for example, -lfreebl3 on fedora) in the platform's config file in coreconf.
+ifdef NSS_USE_SYSTEM_FREEBL
+FREEBL_LIBS = $(FREEBL_LIB_DIR)/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
+EXTRA_LIBS += $(FREEBL_LIBS)
+endif
+
+JAR_LIBS = $(DIST)/lib/$(LIB_PREFIX)jar.$(LIB_SUFFIX)
diff --git a/security/nss/cmd/platrules.mk b/security/nss/cmd/platrules.mk
new file mode 100644
index 000000000..54586bfd8
--- /dev/null
+++ b/security/nss/cmd/platrules.mk
@@ -0,0 +1,19 @@
+#
+# 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/.
+
+show:
+ @echo "DEFINES = ${DEFINES}"
+ @echo "EXTRA_LIBS = >$(EXTRA_LIBS)<"
+ @echo "IMPORT_LIBRARY = $(IMPORT_LIBRARY)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "OBJS = $(OBJS)"
+ @echo "OS_ARCH = $(OS_ARCH)"
+ @echo "PROGRAM = >$(PROGRAM)<"
+ @echo "PROGRAMS = $(PROGRAMS)"
+ @echo "SHARED_LIBRARY = $(SHARED_LIBRARY)"
+ @echo "TARGETS = >$(TARGETS)<"
+
+showplatform:
+ @echo $(PLATFORM)
diff --git a/security/nss/cmd/pp/Makefile b/security/nss/cmd/pp/Makefile
new file mode 100644
index 000000000..6e1d4ecdf
--- /dev/null
+++ b/security/nss/cmd/pp/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/pp/manifest.mn b/security/nss/cmd/pp/manifest.mn
new file mode 100644
index 000000000..de6126ae4
--- /dev/null
+++ b/security/nss/cmd/pp/manifest.mn
@@ -0,0 +1,19 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = pp.c
+
+PROGRAM = pp
diff --git a/security/nss/cmd/pp/pp.c b/security/nss/cmd/pp/pp.c
new file mode 100644
index 000000000..9f33d10a4
--- /dev/null
+++ b/security/nss/cmd/pp/pp.c
@@ -0,0 +1,196 @@
+/* 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/. */
+
+/*
+ * Pretty-print some well-known BER or DER encoded data (e.g. certificates,
+ * keys, pkcs7)
+ */
+
+#include "secutil.h"
+
+#if defined(__sun) && !defined(SVR4)
+extern int fprintf(FILE *, char *, ...);
+#endif
+
+#include "plgetopt.h"
+
+#include "pk11func.h"
+#include "nspr.h"
+#include "nss.h"
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-t type] [-a] [-i input] [-o output] [-w] [-u]\n",
+ progName);
+ fprintf(stderr, "Pretty prints a file containing ASN.1 data in DER or ascii format.\n");
+ fprintf(stderr, "%-14s Specify input and display type:", "-t type");
+#ifdef HAVE_EPV_TEMPLATE
+ fprintf(stderr, " %s (sk),", SEC_CT_PRIVATE_KEY);
+#endif
+ fprintf(stderr, "\n");
+ fprintf(stderr, "%-14s %s (pk), %s (c), %s (cr),\n", "", SEC_CT_PUBLIC_KEY,
+ SEC_CT_CERTIFICATE, SEC_CT_CERTIFICATE_REQUEST);
+ fprintf(stderr, "%-14s %s (ci), %s (p7), %s or %s (n).\n", "", SEC_CT_CERTIFICATE_ID,
+ SEC_CT_PKCS7, SEC_CT_CRL, SEC_CT_NAME);
+ fprintf(stderr, "%-14s (Use either the long type name or the shortcut.)\n", "");
+ fprintf(stderr, "%-14s Input is in ascii encoded form (RFC1113)\n",
+ "-a");
+ fprintf(stderr, "%-14s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-14s Define an output file to use (default is stdout)\n",
+ "-o output");
+ fprintf(stderr, "%-14s Don't wrap long output lines\n",
+ "-w");
+ fprintf(stderr, "%-14s Use UTF-8 (default is to show non-ascii as .)\n",
+ "-u");
+ exit(-1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int rv, ascii;
+ char *progName;
+ FILE *outFile;
+ PRFileDesc *inFile;
+ SECItem der, data;
+ char *typeTag;
+ PLOptState *optstate;
+ PRBool wrap = PR_TRUE;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ ascii = 0;
+ inFile = 0;
+ outFile = 0;
+ typeTag = 0;
+ optstate = PL_CreateOptState(argc, argv, "at:i:o:uw");
+ while (PL_GetNextOpt(optstate) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'a':
+ ascii = 1;
+ break;
+
+ case 'i':
+ inFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 't':
+ typeTag = strdup(optstate->value);
+ break;
+
+ case 'u':
+ SECU_EnableUtf8Display(PR_TRUE);
+ break;
+
+ case 'w':
+ wrap = PR_FALSE;
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+ if (!typeTag)
+ Usage(progName);
+
+ if (!inFile)
+ inFile = PR_STDIN;
+ if (!outFile)
+ outFile = stdout;
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_NoDB_Init(NULL);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: NSS_NoDB_Init failed (%s)\n",
+ progName, SECU_Strerror(PORT_GetError()));
+ exit(1);
+ }
+ SECU_RegisterDynamicOids();
+
+ rv = SECU_ReadDERFromFile(&der, inFile, ascii, PR_FALSE);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: SECU_ReadDERFromFile failed\n", progName);
+ exit(1);
+ }
+
+ /* Data is untyped, using the specified type */
+ data.data = der.data;
+ data.len = der.len;
+
+ SECU_EnableWrap(wrap);
+
+ /* Pretty print it */
+ if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE) == 0 ||
+ PORT_Strcmp(typeTag, "c") == 0) {
+ rv = SECU_PrintSignedData(outFile, &data, "Certificate", 0,
+ (SECU_PPFunc)SECU_PrintCertificate);
+ } else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_ID) == 0 ||
+ PORT_Strcmp(typeTag, "ci") == 0) {
+ rv = SECU_PrintSignedContent(outFile, &data, 0, 0,
+ SECU_PrintDumpDerIssuerAndSerial);
+ } else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_REQUEST) == 0 ||
+ PORT_Strcmp(typeTag, "cr") == 0) {
+ rv = SECU_PrintSignedData(outFile, &data, "Certificate Request", 0,
+ SECU_PrintCertificateRequest);
+ } else if (PORT_Strcmp(typeTag, SEC_CT_CRL) == 0) {
+ rv = SECU_PrintSignedData(outFile, &data, "CRL", 0, SECU_PrintCrl);
+#ifdef HAVE_EPV_TEMPLATE
+ } else if (PORT_Strcmp(typeTag, SEC_CT_PRIVATE_KEY) == 0 ||
+ PORT_Strcmp(typeTag, "sk") == 0) {
+ rv = SECU_PrintPrivateKey(outFile, &data, "Private Key", 0);
+#endif
+ } else if (PORT_Strcmp(typeTag, SEC_CT_PUBLIC_KEY) == 0 ||
+ PORT_Strcmp(typeTag, "pk") == 0) {
+ rv = SECU_PrintSubjectPublicKeyInfo(outFile, &data, "Public Key", 0);
+ } else if (PORT_Strcmp(typeTag, SEC_CT_PKCS7) == 0 ||
+ PORT_Strcmp(typeTag, "p7") == 0) {
+ rv = SECU_PrintPKCS7ContentInfo(outFile, &data,
+ "PKCS #7 Content Info", 0);
+ } else if (PORT_Strcmp(typeTag, SEC_CT_NAME) == 0 ||
+ PORT_Strcmp(typeTag, "n") == 0) {
+ rv = SECU_PrintDERName(outFile, &data, "Name", 0);
+ } else {
+ fprintf(stderr, "%s: don't know how to print out '%s' files\n",
+ progName, typeTag);
+ SECU_PrintAny(outFile, &data, "File contains", 0);
+ return -1;
+ }
+
+ PORT_Free(typeTag);
+
+ if (inFile != PR_STDIN)
+ PR_Close(inFile);
+ PORT_Free(der.data);
+ if (rv) {
+ fprintf(stderr, "%s: problem converting data (%s)\n",
+ progName, SECU_Strerror(PORT_GetError()));
+ }
+ if (NSS_Shutdown() != SECSuccess) {
+ fprintf(stderr, "%s: NSS_Shutdown failed (%s)\n",
+ progName, SECU_Strerror(PORT_GetError()));
+ rv = SECFailure;
+ }
+ PR_Cleanup();
+ return rv;
+}
diff --git a/security/nss/cmd/pp/pp.gyp b/security/nss/cmd/pp/pp.gyp
new file mode 100644
index 000000000..c0fef6ac9
--- /dev/null
+++ b/security/nss/cmd/pp/pp.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pp',
+ 'type': 'executable',
+ 'sources': [
+ 'pp.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/ppcertdata/Makefile b/security/nss/cmd/ppcertdata/Makefile
new file mode 100644
index 000000000..2aaef8fe5
--- /dev/null
+++ b/security/nss/cmd/ppcertdata/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/ppcertdata/manifest.mn b/security/nss/cmd/ppcertdata/manifest.mn
new file mode 100644
index 000000000..142a773ca
--- /dev/null
+++ b/security/nss/cmd/ppcertdata/manifest.mn
@@ -0,0 +1,22 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd
+
+#DEFINES = -DNSPR20
+
+CSRCS = ppcertdata.c
+
+PROGRAM = ppcertdata
+
diff --git a/security/nss/cmd/ppcertdata/ppcertdata.c b/security/nss/cmd/ppcertdata/ppcertdata.c
new file mode 100644
index 000000000..be12e9354
--- /dev/null
+++ b/security/nss/cmd/ppcertdata/ppcertdata.c
@@ -0,0 +1,99 @@
+/* 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/. */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "secutil.h"
+#include "nss.h"
+
+unsigned char binary_line[64 * 1024];
+
+int
+main(int argc, const char** argv)
+{
+ int skip_count = 0;
+ int bytes_read;
+ char line[133];
+
+ if (argc > 1) {
+ skip_count = atoi(argv[1]);
+ }
+ if (argc > 2 || skip_count < 0) {
+ printf("Usage: %s [ skip_columns ] \n", argv[0]);
+ return 1;
+ }
+
+ NSS_NoDB_Init(NULL);
+
+ while (fgets(line, 132, stdin) && (bytes_read = strlen(line)) > 0) {
+ int bytes_written;
+ char* found;
+ char* in = line + skip_count;
+ int left = bytes_read - skip_count;
+ int is_cert;
+ int is_serial;
+ int is_name;
+ int is_hash;
+ int use_pp = 0;
+ int out = 0;
+ SECItem der = { siBuffer, NULL, 0 };
+
+ line[bytes_read] = 0;
+ if (bytes_read <= skip_count)
+ continue;
+ fwrite(in, 1, left, stdout);
+ found = strstr(in, "MULTILINE_OCTAL");
+ if (!found)
+ continue;
+ fflush(stdout);
+
+ is_cert = (NULL != strstr(in, "CKA_VALUE"));
+ is_serial = (NULL != strstr(in, "CKA_SERIAL_NUMBER"));
+ is_name = (NULL != strstr(in, "CKA_ISSUER")) ||
+ (NULL != strstr(in, "CKA_SUBJECT"));
+ is_hash = (NULL != strstr(in, "_HASH"));
+ while (fgets(line, 132, stdin) &&
+ (bytes_read = strlen(line)) > 0) {
+ in = line + skip_count;
+ left = bytes_read - skip_count;
+
+ if ((left >= 3) && !strncmp(in, "END", 3))
+ break;
+ while (left >= 4) {
+ if (in[0] == '\\' && isdigit(in[1]) &&
+ isdigit(in[2]) && isdigit(in[3])) {
+ left -= 4;
+ binary_line[out++] = ((in[1] - '0') << 6) |
+ ((in[2] - '0') << 3) |
+ (in[3] - '0');
+ in += 4;
+ } else
+ break;
+ }
+ }
+ der.data = binary_line;
+ der.len = out;
+ if (is_cert)
+ SECU_PrintSignedData(stdout, &der, "Certificate", 0,
+ SECU_PrintCertificate);
+ else if (is_name)
+ SECU_PrintDERName(stdout, &der, "Name", 0);
+ else if (is_serial) {
+ if (out > 2 && binary_line[0] == 2 &&
+ out == 2 + binary_line[1]) {
+ der.data += 2;
+ der.len -= 2;
+ SECU_PrintInteger(stdout, &der, "DER Serial Number", 0);
+ } else
+ SECU_PrintInteger(stdout, &der, "Raw Serial Number", 0);
+ } else if (is_hash)
+ SECU_PrintAsHex(stdout, &der, "Hash", 0);
+ else
+ SECU_PrintBuf(stdout, "Other", binary_line, out);
+ }
+ NSS_Shutdown();
+ return 0;
+}
diff --git a/security/nss/cmd/pwdecrypt/Makefile b/security/nss/cmd/pwdecrypt/Makefile
new file mode 100644
index 000000000..265ea5601
--- /dev/null
+++ b/security/nss/cmd/pwdecrypt/Makefile
@@ -0,0 +1,45 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
diff --git a/security/nss/cmd/pwdecrypt/manifest.mn b/security/nss/cmd/pwdecrypt/manifest.mn
new file mode 100644
index 000000000..51cb8c8f3
--- /dev/null
+++ b/security/nss/cmd/pwdecrypt/manifest.mn
@@ -0,0 +1,26 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ pwdecrypt.c \
+ $(NULL)
+
+# headers for the MODULE (defined above) are implicitly required.
+REQUIRES = dbm seccmd
+
+# WINNT uses EXTRA_LIBS as the list of libs to link in.
+# Unix uses OS_LIBS for that purpose.
+# We can solve this via conditional makefile code, but
+# can't do this in manifest.mn because OS_ARCH isn't defined there.
+# So, look in the local Makefile for the defines for the list of libs.
+
+PROGRAM = pwdecrypt
+
+#USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/pwdecrypt/pwdecrypt.c b/security/nss/cmd/pwdecrypt/pwdecrypt.c
new file mode 100644
index 000000000..02a676e54
--- /dev/null
+++ b/security/nss/cmd/pwdecrypt/pwdecrypt.c
@@ -0,0 +1,330 @@
+/* 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/. */
+
+/*
+ * Test program for SDR (Secret Decoder Ring) functions.
+ */
+
+#include "nspr.h"
+#include "string.h"
+#include "nss.h"
+#include "secutil.h"
+#include "cert.h"
+#include "pk11func.h"
+#include "nssb64.h"
+
+#include "plgetopt.h"
+#include "pk11sdr.h"
+
+#define DEFAULT_VALUE "Test"
+
+static void
+synopsis(char *program_name)
+{
+ PRFileDesc *pr_stderr;
+
+ pr_stderr = PR_STDERR;
+ PR_fprintf(pr_stderr,
+ "Usage:\t%s [-i <input-file>] [-o <output-file>] [-d <dir>]\n"
+ " \t[-l logfile] [-p pwd] [-f pwfile]\n",
+ program_name);
+}
+
+static void
+short_usage(char *program_name)
+{
+ PR_fprintf(PR_STDERR,
+ "Type %s -H for more detailed descriptions\n",
+ program_name);
+ synopsis(program_name);
+}
+
+static void
+long_usage(char *program_name)
+{
+ PRFileDesc *pr_stderr;
+
+ pr_stderr = PR_STDERR;
+ synopsis(program_name);
+ PR_fprintf(pr_stderr, "\nDecode encrypted passwords (and other data).\n");
+ PR_fprintf(pr_stderr,
+ "This program reads in standard configuration files looking\n"
+ "for base 64 encoded data. Data that looks like it's base 64 encode\n"
+ "is decoded an passed to the NSS SDR code. If the decode and decrypt\n"
+ "is successful, then decrypted data is outputted in place of the\n"
+ "original base 64 data. If the decode or decrypt fails, the original\n"
+ "data is written and the reason for failure is logged to the \n"
+ "optional logfile.\n");
+ PR_fprintf(pr_stderr,
+ " %-13s Read stream including encrypted data from "
+ "\"read_file\"\n",
+ "-i read_file");
+ PR_fprintf(pr_stderr,
+ " %-13s Write results to \"write_file\"\n",
+ "-o write_file");
+ PR_fprintf(pr_stderr,
+ " %-13s Find security databases in \"dbdir\"\n",
+ "-d dbdir");
+ PR_fprintf(pr_stderr,
+ " %-13s Log failed decrypt/decode attempts to \"log_file\"\n",
+ "-l log_file");
+ PR_fprintf(pr_stderr,
+ " %-13s Token password\n",
+ "-p pwd");
+ PR_fprintf(pr_stderr,
+ " %-13s Password file\n",
+ "-f pwfile");
+}
+
+/*
+ * base64 table only used to identify the end of a base64 string
+ */
+static unsigned char b64[256] = {
+ /* 00: */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 08: */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 10: */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 18: */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 20: */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 28: */ 0, 0, 0, 1, 0, 0, 0, 1,
+ /* 30: */ 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 38: */ 1, 1, 0, 0, 0, 0, 0, 0,
+ /* 40: */ 0, 1, 1, 1, 1, 1, 1, 1,
+ /* 48: */ 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 50: */ 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 58: */ 1, 1, 1, 0, 0, 0, 0, 0,
+ /* 60: */ 0, 1, 1, 1, 1, 1, 1, 1,
+ /* 68: */ 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 70: */ 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 78: */ 1, 1, 1, 0, 0, 0, 0, 0,
+};
+
+enum {
+ false = 0,
+ true = 1
+} bool;
+
+#define isatobchar(c) (b64[c])
+
+#define MAX_STRING 8192
+
+int
+isBase64(char *inString)
+{
+ unsigned int i;
+ unsigned char c;
+
+ for (i = 0; (c = inString[i]) != 0 && isatobchar(c); ++i)
+ ;
+ if (c == '=') {
+ while ((c = inString[++i]) == '=')
+ ; /* skip trailing '=' characters */
+ }
+ if (c && c != '\n' && c != '\r')
+ return false;
+ if (i == 0 || i % 4)
+ return false;
+ return true;
+}
+
+void
+doDecrypt(char *dataString, FILE *outFile, FILE *logFile, secuPWData *pwdata)
+{
+ int strLen = strlen(dataString);
+ SECItem *decoded = NSSBase64_DecodeBuffer(NULL, NULL, dataString, strLen);
+ SECStatus rv;
+ int err;
+ SECItem result = { siBuffer, NULL, 0 };
+
+ if ((decoded == NULL) || (decoded->len == 0)) {
+ if (logFile) {
+ err = PORT_GetError();
+ fprintf(logFile, "Base 64 decode failed on <%s>\n", dataString);
+ fprintf(logFile, " Error %d: %s\n", err, SECU_Strerror(err));
+ }
+ fputs(dataString, outFile);
+ if (decoded)
+ SECITEM_FreeItem(decoded, PR_TRUE);
+ return;
+ }
+
+ rv = PK11SDR_Decrypt(decoded, &result, pwdata);
+ SECITEM_ZfreeItem(decoded, PR_TRUE);
+ if (rv == SECSuccess) {
+ /* result buffer has no extra space for a NULL */
+ fprintf(outFile, "Decrypted: \"%.*s\"\n", result.len, result.data);
+ SECITEM_ZfreeItem(&result, PR_FALSE);
+ return;
+ }
+ /* Encryption failed. output raw input. */
+ if (logFile) {
+ err = PORT_GetError();
+ fprintf(logFile, "SDR decrypt failed on <%s>\n", dataString);
+ fprintf(logFile, " Error %d: %s\n", err, SECU_Strerror(err));
+ }
+ fputs(dataString, outFile);
+}
+
+void
+doDecode(char *dataString, FILE *outFile, FILE *logFile)
+{
+ int strLen = strlen(dataString + 1);
+ SECItem *decoded;
+
+ decoded = NSSBase64_DecodeBuffer(NULL, NULL, dataString + 1, strLen);
+ if ((decoded == NULL) || (decoded->len == 0)) {
+ if (logFile) {
+ int err = PORT_GetError();
+ fprintf(logFile, "Base 64 decode failed on <%s>\n", dataString + 1);
+ fprintf(logFile, " Error %d: %s\n", err, SECU_Strerror(err));
+ }
+ fputs(dataString, outFile);
+ if (decoded)
+ SECITEM_FreeItem(decoded, PR_TRUE);
+ return;
+ }
+ fprintf(outFile, "Decoded: \"%.*s\"\n", decoded->len, decoded->data);
+ SECITEM_ZfreeItem(decoded, PR_TRUE);
+}
+
+char dataString[MAX_STRING + 1];
+
+int
+main(int argc, char **argv)
+{
+ int retval = 0; /* 0 - test succeeded. -1 - test failed */
+ SECStatus rv;
+ PLOptState *optstate;
+ char *program_name;
+ char *input_file = NULL; /* read encrypted data from here (or create) */
+ char *output_file = NULL; /* write new encrypted data here */
+ char *log_file = NULL; /* write new encrypted data here */
+ FILE *inFile = stdin;
+ FILE *outFile = stdout;
+ FILE *logFile = NULL;
+ PLOptStatus optstatus;
+ secuPWData pwdata = { PW_NONE, NULL };
+
+ program_name = PL_strrchr(argv[0], '/');
+ program_name = program_name ? (program_name + 1) : argv[0];
+
+ optstate = PL_CreateOptState(argc, argv, "Hd:f:i:o:l:p:?");
+ if (optstate == NULL) {
+ SECU_PrintError(program_name, "PL_CreateOptState failed");
+ return 1;
+ }
+
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ short_usage(program_name);
+ return 1;
+
+ case 'H':
+ long_usage(program_name);
+ return 1;
+
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'i':
+ input_file = PL_strdup(optstate->value);
+ break;
+
+ case 'o':
+ output_file = PL_strdup(optstate->value);
+ break;
+
+ case 'l':
+ log_file = PL_strdup(optstate->value);
+ break;
+
+ case 'f':
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = PL_strdup(optstate->value);
+ break;
+
+ case 'p':
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = PL_strdup(optstate->value);
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+ if (optstatus == PL_OPT_BAD) {
+ short_usage(program_name);
+ return 1;
+ }
+
+ if (input_file) {
+ inFile = fopen(input_file, "r");
+ if (inFile == NULL) {
+ perror(input_file);
+ return 1;
+ }
+ PR_Free(input_file);
+ }
+ if (output_file) {
+ outFile = fopen(output_file, "w+");
+ if (outFile == NULL) {
+ perror(output_file);
+ return 1;
+ }
+ PR_Free(output_file);
+ }
+ if (log_file) {
+ if (log_file[0] == '-')
+ logFile = stderr;
+ else
+ logFile = fopen(log_file, "w+");
+ if (logFile == NULL) {
+ perror(log_file);
+ return 1;
+ }
+ PR_Free(log_file);
+ }
+
+ /*
+ * Initialize the Security libraries.
+ */
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+ rv = NSS_Init(SECU_ConfigDirectory(NULL));
+ if (rv != SECSuccess) {
+ SECU_PrintError(program_name, "NSS_Init failed");
+ retval = 1;
+ goto prdone;
+ }
+
+ /* Get the encrypted result, either from the input file
+ * or from encrypting the plaintext value
+ */
+ while (fgets(dataString, sizeof dataString, inFile)) {
+ unsigned char c = dataString[0];
+
+ if (c == 'M' && isBase64(dataString)) {
+ doDecrypt(dataString, outFile, logFile, &pwdata);
+ } else if (c == '~' && isBase64(dataString + 1)) {
+ doDecode(dataString, outFile, logFile);
+ } else {
+ fputs(dataString, outFile);
+ }
+ }
+ if (pwdata.data)
+ PR_Free(pwdata.data);
+
+ fclose(outFile);
+ fclose(inFile);
+ if (logFile && logFile != stderr) {
+ fclose(logFile);
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ SECU_PrintError(program_name, "NSS_Shutdown failed");
+ exit(1);
+ }
+
+prdone:
+ PR_Cleanup();
+ return retval;
+}
diff --git a/security/nss/cmd/pwdecrypt/pwdecrypt.gyp b/security/nss/cmd/pwdecrypt/pwdecrypt.gyp
new file mode 100644
index 000000000..c3ae8eeb9
--- /dev/null
+++ b/security/nss/cmd/pwdecrypt/pwdecrypt.gyp
@@ -0,0 +1,25 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pwdecrypt',
+ 'type': 'executable',
+ 'sources': [
+ 'pwdecrypt.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/rsaperf/Makefile b/security/nss/cmd/rsaperf/Makefile
new file mode 100644
index 000000000..7b74b369c
--- /dev/null
+++ b/security/nss/cmd/rsaperf/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/rsaperf/defkey.c b/security/nss/cmd/rsaperf/defkey.c
new file mode 100644
index 000000000..3ca366fa7
--- /dev/null
+++ b/security/nss/cmd/rsaperf/defkey.c
@@ -0,0 +1,293 @@
+/* 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/. */
+
+/* This key is the 1024-bit test key used for speed testing of RSA private
+** key ops.
+*/
+#include "seccomon.h"
+#include "secoidt.h"
+#include "lowkeyti.h"
+
+#undef CONST
+#define CONST
+
+static CONST unsigned char default_n1024[128] = {
+ 0xc2, 0xae, 0x96, 0x89, 0xaf, 0xce, 0xd0, 0x7b, 0x3b, 0x35, 0xfd, 0x0f, 0xb1, 0xf4, 0x7a, 0xd1,
+ 0x3c, 0x7d, 0xb5, 0x86, 0xf2, 0x68, 0x36, 0xc9, 0x97, 0xe6, 0x82, 0x94, 0x86, 0xaa, 0x05, 0x39,
+ 0xec, 0x11, 0x51, 0xcc, 0x5c, 0xa1, 0x59, 0xba, 0x29, 0x18, 0xf3, 0x28, 0xf1, 0x9d, 0xe3, 0xae,
+ 0x96, 0x5d, 0x6d, 0x87, 0x73, 0xf6, 0xf6, 0x1f, 0xd0, 0x2d, 0xfb, 0x2f, 0x7a, 0x13, 0x7f, 0xc8,
+ 0x0c, 0x7a, 0xe9, 0x85, 0xfb, 0xce, 0x74, 0x86, 0xf8, 0xef, 0x2f, 0x85, 0x37, 0x73, 0x0f, 0x62,
+ 0x4e, 0x93, 0x17, 0xb7, 0x7e, 0x84, 0x9a, 0x94, 0x11, 0x05, 0xca, 0x0d, 0x31, 0x4b, 0x2a, 0xc8,
+ 0xdf, 0xfe, 0xe9, 0x0c, 0x13, 0xc7, 0xf2, 0xad, 0x19, 0x64, 0x28, 0x3c, 0xb5, 0x6a, 0xc8, 0x4b,
+ 0x79, 0xea, 0x7c, 0xce, 0x75, 0x92, 0x45, 0x3e, 0xa3, 0x9d, 0x64, 0x6f, 0x04, 0x69, 0x19, 0x17
+};
+
+static CONST unsigned char default_e1024[3] = { 0x01, 0x00, 0x01 };
+
+static CONST unsigned char default_d1024[128] = {
+ 0x13, 0xcb, 0xbc, 0xf2, 0xf3, 0x35, 0x8c, 0x6d, 0x7b, 0x6f, 0xd9, 0xf3, 0xa6, 0x9c, 0xbd, 0x80,
+ 0x59, 0x2e, 0x4f, 0x2f, 0x11, 0xa7, 0x17, 0x2b, 0x18, 0x8f, 0x0f, 0xe8, 0x1a, 0x69, 0x5f, 0x6e,
+ 0xac, 0x5a, 0x76, 0x7e, 0xd9, 0x4c, 0x6e, 0xdb, 0x47, 0x22, 0x8a, 0x57, 0x37, 0x7a, 0x5e, 0x94,
+ 0x7a, 0x25, 0xb5, 0xe5, 0x78, 0x1d, 0x3c, 0x99, 0xaf, 0x89, 0x7d, 0x69, 0x2e, 0x78, 0x9d, 0x1d,
+ 0x84, 0xc8, 0xc1, 0xd7, 0x1a, 0xb2, 0x6d, 0x2d, 0x8a, 0xd9, 0xab, 0x6b, 0xce, 0xae, 0xb0, 0xa0,
+ 0x58, 0x55, 0xad, 0x5c, 0x40, 0x8a, 0xd6, 0x96, 0x08, 0x8a, 0xe8, 0x63, 0xe6, 0x3d, 0x6c, 0x20,
+ 0x49, 0xc7, 0xaf, 0x0f, 0x25, 0x73, 0xd3, 0x69, 0x43, 0x3b, 0xf2, 0x32, 0xf8, 0x3d, 0x5e, 0xee,
+ 0x7a, 0xca, 0xd6, 0x94, 0x55, 0xe5, 0xbd, 0x25, 0x34, 0x8d, 0x63, 0x40, 0xb5, 0x8a, 0xc3, 0x01
+};
+
+static CONST unsigned char default_p1024[64] = {
+ 0xf6, 0x3c, 0x3f, 0x56, 0x58, 0x4f, 0xb3, 0x82, 0x0c, 0xf0, 0x5b, 0x42, 0x36, 0x1c, 0x93, 0xde,
+ 0x9b, 0x32, 0x01, 0xb1, 0x48, 0xf8, 0x00, 0x57, 0x9b, 0xc1, 0xbe, 0x66, 0xc2, 0xbb, 0xea, 0x7c,
+ 0x75, 0x29, 0x2c, 0x22, 0xaa, 0x7c, 0xaf, 0xbd, 0x0d, 0x3f, 0xb0, 0x64, 0x97, 0xf0, 0x88, 0x25,
+ 0xcb, 0x8d, 0xc7, 0x19, 0x0a, 0x75, 0x44, 0xa4, 0x5a, 0xc3, 0xb5, 0xb9, 0x85, 0xea, 0x27, 0xa7
+};
+
+static CONST unsigned char default_q1024[64] = {
+ 0xca, 0x66, 0xfa, 0x18, 0x6a, 0x46, 0x36, 0x1c, 0x46, 0xfe, 0x47, 0xe9, 0x7e, 0x52, 0x83, 0x8a,
+ 0xbb, 0x72, 0x13, 0xcc, 0x83, 0x56, 0x3d, 0x64, 0x22, 0xdd, 0xfa, 0x7c, 0x61, 0x99, 0xea, 0xa4,
+ 0xb3, 0x0e, 0x8f, 0x79, 0x10, 0xab, 0xba, 0x4a, 0x73, 0xd1, 0x48, 0x40, 0x34, 0x34, 0xd3, 0xd2,
+ 0x54, 0x92, 0xbe, 0xf5, 0xc8, 0xc4, 0x60, 0x5f, 0xd3, 0xf7, 0xce, 0xbe, 0x60, 0x3e, 0xb1, 0x11
+};
+
+static CONST unsigned char default_dModP1024[64] = {
+ 0x8e, 0x80, 0xbf, 0x87, 0x11, 0x04, 0xcf, 0x36, 0x6c, 0x96, 0x8d, 0xb9, 0xfb, 0xe6, 0xfe, 0x0c,
+ 0xce, 0x74, 0x5a, 0x56, 0x67, 0x8c, 0x5f, 0x66, 0x54, 0x56, 0x04, 0x03, 0x24, 0x9f, 0xec, 0x4c,
+ 0xaa, 0xe1, 0x71, 0x11, 0x7e, 0xe9, 0x3a, 0x2b, 0x87, 0x07, 0x5c, 0xe6, 0x5a, 0xa8, 0x71, 0xa2,
+ 0xad, 0xf3, 0x17, 0x4e, 0x7e, 0xa6, 0xef, 0x5a, 0xce, 0xcc, 0x84, 0xd7, 0x21, 0x91, 0x29, 0xf1
+};
+
+static CONST unsigned char default_dModQ1024[64] = {
+ 0x87, 0x60, 0x1d, 0x02, 0xdb, 0x82, 0x1e, 0x8b, 0x07, 0x48, 0xe8, 0x5c, 0x59, 0xeb, 0x62, 0xa4,
+ 0x15, 0xff, 0x95, 0x12, 0x82, 0xfd, 0xd9, 0x8d, 0xf2, 0x6c, 0x3a, 0x2f, 0x9b, 0x30, 0x51, 0x6a,
+ 0xdb, 0x80, 0x6f, 0xa1, 0xef, 0xee, 0x8c, 0x69, 0x63, 0xd1, 0xa4, 0xdb, 0x9c, 0x8f, 0x80, 0xe5,
+ 0xfb, 0x3f, 0x33, 0x8e, 0x3d, 0x3c, 0x6b, 0xa1, 0x6c, 0xab, 0x20, 0x92, 0xe0, 0xd8, 0xcd, 0xa1
+};
+
+static CONST unsigned char default_qInvModP1024[64] = {
+ 0xce, 0xcf, 0x5a, 0xad, 0xc4, 0x8c, 0x44, 0x91, 0x3a, 0xbc, 0x7b, 0xf8, 0x80, 0xf8, 0x53, 0xf5,
+ 0x12, 0x84, 0x8c, 0x9c, 0x6b, 0x33, 0x93, 0x0d, 0xa1, 0x11, 0xea, 0xfa, 0x4a, 0xc1, 0xeb, 0x48,
+ 0xdc, 0x44, 0x86, 0x93, 0x1b, 0x98, 0xc7, 0x82, 0x22, 0x68, 0x30, 0x44, 0xd7, 0x62, 0x1b, 0x90,
+ 0x54, 0x07, 0x4b, 0x66, 0xa7, 0xc5, 0x75, 0x5a, 0x72, 0x77, 0x92, 0xdd, 0x6c, 0xf3, 0x37, 0xab
+};
+
+static CONST unsigned char default_n2048[256] = {
+ 0xb3, 0x9b, 0x57, 0x2c, 0x15, 0xdf, 0x6c, 0x6b, 0xfc, 0x04, 0x83, 0x02, 0xf5, 0xb3, 0x2c, 0x87,
+ 0x1b, 0x9c, 0xbf, 0x6c, 0x46, 0x1d, 0xdd, 0xe2, 0xc0, 0x6d, 0xfe, 0xf9, 0x00, 0xd1, 0x85, 0x91,
+ 0x17, 0x0d, 0x43, 0x67, 0xa1, 0x1f, 0x8b, 0xcd, 0x22, 0x8a, 0x93, 0xdc, 0x9f, 0xf0, 0x45, 0x9e,
+ 0x58, 0x0f, 0x99, 0x87, 0xe6, 0x60, 0xdf, 0x8c, 0x1a, 0xa3, 0x8f, 0xc3, 0x6c, 0xa0, 0x49, 0x3a,
+ 0xdb, 0x7f, 0xd0, 0xda, 0x48, 0x47, 0xe3, 0xd6, 0x1f, 0x29, 0xcb, 0xf2, 0x1d, 0xf3, 0x81, 0xd0,
+ 0x4d, 0xf1, 0x64, 0xcf, 0x42, 0x8e, 0x0f, 0xe0, 0x10, 0x18, 0x4c, 0x75, 0xce, 0x96, 0x09, 0x2e,
+ 0x52, 0xa6, 0x96, 0xa9, 0xe1, 0xab, 0x3e, 0x6f, 0xa5, 0xd3, 0xee, 0xd8, 0xb2, 0x4f, 0x17, 0x08,
+ 0x6d, 0x43, 0xd4, 0xb3, 0x1c, 0x8a, 0x4a, 0x43, 0x06, 0xb5, 0xab, 0xfb, 0xf4, 0x34, 0x2f, 0x2f,
+ 0xe1, 0x43, 0x7b, 0xe0, 0x93, 0xd0, 0xaa, 0x42, 0xa3, 0xb7, 0xb7, 0x43, 0x52, 0xeb, 0xf3, 0x64,
+ 0x9a, 0xbc, 0xa7, 0xf2, 0x39, 0xad, 0xe4, 0x62, 0x7d, 0xbc, 0x31, 0x8f, 0xbf, 0x59, 0x93, 0x62,
+ 0x88, 0xc5, 0xd1, 0x62, 0x2d, 0xe3, 0xc7, 0x75, 0xf9, 0xb8, 0x00, 0x96, 0xe0, 0x05, 0x87, 0x35,
+ 0x86, 0x5d, 0xeb, 0x7c, 0x20, 0xf6, 0xb2, 0xb1, 0x65, 0x1f, 0xdc, 0x74, 0xec, 0xf4, 0x0e, 0xd1,
+ 0xf2, 0x2d, 0x06, 0x47, 0x02, 0xc5, 0x18, 0xdb, 0x19, 0xb9, 0x1b, 0x40, 0x90, 0xc8, 0x74, 0x5c,
+ 0xf6, 0xe8, 0x17, 0x64, 0xf4, 0xcf, 0xd3, 0x17, 0xeb, 0xd6, 0x0d, 0x2b, 0xec, 0x2a, 0x9b, 0xcf,
+ 0xc4, 0xf5, 0xcc, 0x9a, 0xc3, 0x5c, 0x2e, 0xf1, 0x98, 0x25, 0x2b, 0xe4, 0x01, 0x02, 0x15, 0x36,
+ 0xe1, 0xe0, 0x2b, 0xbe, 0xdf, 0x23, 0xf1, 0xde, 0x2f, 0x1b, 0xbb, 0x44, 0xa7, 0x12, 0x2c, 0x9d
+};
+
+static CONST unsigned char default_e2048[3] = { 0x01, 0x00, 0x01 };
+
+static CONST unsigned char default_d2048[256] = {
+ 0x0f, 0x03, 0x3f, 0x08, 0x1a, 0x53, 0xf0, 0x96, 0x1e, 0x1c, 0xaa, 0x6e, 0xc6, 0xe6, 0xd1, 0x24,
+ 0x01, 0xf4, 0xda, 0x33, 0x4c, 0xb1, 0x16, 0x68, 0xeb, 0xb8, 0xc6, 0x05, 0x3e, 0x42, 0x45, 0x2d,
+ 0xd9, 0x85, 0x6c, 0x4a, 0xef, 0x36, 0xd9, 0xd2, 0xad, 0xbe, 0x73, 0x99, 0x8f, 0x6c, 0xe0, 0x04,
+ 0xda, 0x4b, 0x83, 0x83, 0xce, 0x87, 0xee, 0x67, 0xa1, 0x9a, 0x66, 0x5b, 0xe9, 0x6a, 0x84, 0x74,
+ 0x7d, 0x00, 0x74, 0x0e, 0xaa, 0xd8, 0x07, 0x7d, 0x50, 0x61, 0x88, 0x00, 0x96, 0xec, 0x51, 0xbf,
+ 0x7d, 0xa4, 0x5d, 0xce, 0xcd, 0x3b, 0x5e, 0xac, 0x55, 0xec, 0x12, 0x08, 0x0e, 0xda, 0x8f, 0xad,
+ 0xe5, 0x8e, 0xb3, 0x2d, 0x44, 0x05, 0xb2, 0x54, 0x56, 0xc2, 0x1e, 0x46, 0xd2, 0xb0, 0xb5, 0xb6,
+ 0x28, 0x9b, 0xf0, 0xdd, 0x7f, 0xd7, 0x37, 0x59, 0xde, 0xe7, 0xb4, 0x96, 0x7c, 0xd5, 0x17, 0xd4,
+ 0x7e, 0xe0, 0xcb, 0xb3, 0x3c, 0x5f, 0x72, 0x30, 0xbe, 0x3c, 0x81, 0x82, 0x8e, 0xb9, 0xc6, 0xa7,
+ 0x23, 0x71, 0xf5, 0x6f, 0xd7, 0x56, 0xe4, 0xee, 0x3b, 0x2d, 0x8f, 0x3e, 0x43, 0x98, 0xc8, 0xe8,
+ 0x95, 0xfd, 0xc3, 0x73, 0xd3, 0x8e, 0x38, 0x01, 0xa5, 0xc6, 0xbe, 0x0c, 0x6b, 0x6b, 0x4f, 0x13,
+ 0x2f, 0x66, 0x8b, 0x85, 0xe3, 0x9e, 0x12, 0xc0, 0x52, 0x60, 0xec, 0x4a, 0xcb, 0xfa, 0x7e, 0x7c,
+ 0x20, 0x9a, 0x11, 0x16, 0x1a, 0xb7, 0x96, 0xd6, 0x00, 0x7a, 0x04, 0x7b, 0x17, 0xcc, 0x4c, 0x43,
+ 0xdc, 0xd0, 0x64, 0x45, 0x45, 0xd3, 0x21, 0x06, 0x8b, 0xd6, 0xb0, 0xf0, 0xbf, 0x20, 0x56, 0xfd,
+ 0x11, 0x9c, 0x1d, 0x82, 0xcd, 0x34, 0x16, 0x75, 0x63, 0xac, 0x51, 0xd5, 0x55, 0xb4, 0x35, 0x0a,
+ 0xc3, 0x8c, 0x47, 0x01, 0x8e, 0x99, 0x95, 0xc5, 0x99, 0x21, 0x79, 0x66, 0x1a, 0xa6, 0xb0, 0xe9
+};
+
+static CONST unsigned char default_p2048[128] = {
+ 0xd7, 0xaa, 0xb4, 0x8d, 0xb1, 0x23, 0x67, 0x80, 0x7b, 0x98, 0xf7, 0xe6, 0xfd, 0x6d, 0x5c, 0x98,
+ 0x34, 0x89, 0x97, 0xbd, 0xa8, 0x88, 0xdd, 0xb3, 0xe6, 0xbc, 0x5f, 0xb8, 0xd6, 0xa5, 0x14, 0x00,
+ 0x4a, 0x54, 0x1a, 0xbf, 0x65, 0x64, 0x7d, 0x39, 0x55, 0xff, 0x27, 0x0f, 0x2f, 0x99, 0x57, 0xe6,
+ 0x69, 0x89, 0x1c, 0xc4, 0x89, 0xff, 0xe4, 0x1f, 0xa5, 0x47, 0xea, 0x1e, 0x47, 0x07, 0xf7, 0x46,
+ 0xa5, 0x3a, 0x25, 0x70, 0x9e, 0x6d, 0xe3, 0x83, 0xc1, 0x9d, 0x75, 0xf5, 0x67, 0xb5, 0x7f, 0x5c,
+ 0xf8, 0x24, 0xff, 0x85, 0x11, 0x53, 0xff, 0x0e, 0xbc, 0x57, 0x6f, 0xc7, 0x2a, 0x36, 0xbd, 0xdd,
+ 0x0b, 0xe5, 0x25, 0x04, 0x1f, 0x48, 0xbc, 0xdd, 0xd6, 0x13, 0xb8, 0xe9, 0xfd, 0x00, 0xba, 0x37,
+ 0x13, 0x63, 0xc2, 0xd4, 0x70, 0xf8, 0x4b, 0x09, 0x71, 0xa8, 0xbe, 0xca, 0x0d, 0x68, 0x16, 0x5f
+};
+
+static CONST unsigned char default_q2048[128] = {
+ 0xd5, 0x32, 0x38, 0x82, 0x14, 0xed, 0xd1, 0x90, 0x51, 0xef, 0x17, 0xa2, 0x9b, 0xc3, 0xb0, 0x45,
+ 0x86, 0x64, 0xbe, 0xce, 0x8f, 0x85, 0x78, 0x18, 0x7a, 0xf8, 0x3a, 0xb7, 0x17, 0x7b, 0x5d, 0xf3,
+ 0xe9, 0xd7, 0x9d, 0xb3, 0x2f, 0x96, 0x35, 0x96, 0x60, 0x38, 0xe7, 0x96, 0xc3, 0x08, 0xe6, 0xf1,
+ 0xb8, 0x16, 0xc0, 0x1d, 0xc9, 0x6f, 0xd3, 0x99, 0x14, 0x8e, 0xd3, 0x6a, 0x2b, 0x6c, 0x4d, 0xd1,
+ 0x71, 0x1c, 0x4c, 0x38, 0x72, 0x18, 0x23, 0xf9, 0xd1, 0x6c, 0xa2, 0x87, 0xfe, 0x33, 0xc2, 0x9d,
+ 0x6e, 0xd0, 0x80, 0x62, 0x44, 0x7b, 0x3a, 0x4d, 0x2f, 0xff, 0x5f, 0x73, 0xe5, 0x53, 0x32, 0x18,
+ 0x14, 0xb2, 0xdb, 0x6b, 0x25, 0x7b, 0xac, 0xb4, 0x3b, 0x1e, 0x5e, 0xcd, 0xec, 0x01, 0x99, 0xdb,
+ 0x0c, 0x1f, 0xc2, 0xa6, 0x50, 0x1d, 0x6d, 0x7b, 0x58, 0x75, 0x04, 0x89, 0x5d, 0x87, 0x86, 0x83
+};
+
+static CONST unsigned char default_dModP2048[128] = {
+ 0xc0, 0xba, 0x16, 0x1b, 0xc1, 0x3e, 0xc8, 0x51, 0xb3, 0x22, 0x21, 0xf7, 0x54, 0x66, 0x14, 0xa7,
+ 0x17, 0xdc, 0x15, 0xb4, 0x31, 0x16, 0x0e, 0x39, 0xa4, 0x6a, 0x96, 0x88, 0x11, 0x98, 0xf7, 0xe4,
+ 0xc2, 0x87, 0xa2, 0x57, 0x83, 0xfe, 0x67, 0x41, 0x83, 0xae, 0x3e, 0x73, 0x7d, 0xaf, 0xe5, 0x33,
+ 0x4d, 0x00, 0x70, 0xaa, 0xda, 0x3f, 0xc8, 0xd6, 0xd6, 0xd7, 0x0b, 0x4a, 0xff, 0x63, 0x09, 0x01,
+ 0x22, 0xca, 0x71, 0x86, 0xd0, 0xad, 0x96, 0xf1, 0xb9, 0x66, 0x43, 0x71, 0x88, 0xba, 0x53, 0x14,
+ 0xfb, 0xd3, 0xe4, 0x5c, 0x3f, 0xfd, 0xf6, 0x22, 0x6f, 0x01, 0x1c, 0x2c, 0xb9, 0x76, 0xad, 0xf9,
+ 0x09, 0x96, 0x3e, 0x9c, 0x0e, 0x70, 0xec, 0x06, 0xba, 0x36, 0x69, 0xbb, 0x00, 0x93, 0x53, 0xd5,
+ 0xc0, 0x08, 0x18, 0xa5, 0xcc, 0x46, 0xb6, 0x97, 0xbb, 0xf0, 0x76, 0x7f, 0x0d, 0xb8, 0x04, 0xb5
+};
+
+static CONST unsigned char default_dModQ2048[128] = {
+ 0xa9, 0x18, 0xfd, 0x43, 0x07, 0xf0, 0x9d, 0x50, 0x77, 0xfc, 0x48, 0xe5, 0xdb, 0xe0, 0x39, 0xd6,
+ 0xdb, 0x42, 0xdb, 0x28, 0xa1, 0x23, 0x7e, 0xdf, 0x03, 0xe2, 0x11, 0x48, 0x19, 0xa2, 0xeb, 0x21,
+ 0x44, 0xaf, 0x95, 0x50, 0x83, 0x85, 0x03, 0x99, 0xf3, 0x56, 0x0f, 0x32, 0x40, 0x1d, 0xb6, 0x77,
+ 0xb0, 0xc8, 0xb2, 0xb6, 0xad, 0x88, 0x39, 0xef, 0xe8, 0x23, 0x64, 0xc2, 0x88, 0x10, 0x8e, 0x24,
+ 0x7a, 0x2f, 0xb4, 0xb0, 0xec, 0xa6, 0x03, 0x1a, 0xe9, 0xa5, 0xdd, 0xc0, 0x39, 0xba, 0xba, 0x38,
+ 0xfe, 0xa4, 0xf7, 0xbf, 0x79, 0x8b, 0xb7, 0xf1, 0x73, 0x09, 0x7d, 0x9f, 0x42, 0x1c, 0x5b, 0xd6,
+ 0x47, 0xcc, 0x99, 0x46, 0x81, 0xe3, 0x77, 0x57, 0x38, 0xb0, 0xdd, 0x07, 0x3d, 0x93, 0x03, 0x82,
+ 0x7f, 0x3a, 0x4d, 0xbc, 0x76, 0x3c, 0xf1, 0x12, 0x6d, 0x55, 0xdb, 0x34, 0x4c, 0xef, 0xea, 0x9b
+};
+
+static CONST unsigned char default_qInvModP2048[128] = {
+ 0x77, 0xd9, 0x45, 0xd4, 0xd2, 0xd1, 0x46, 0xa8, 0xaf, 0x57, 0x8f, 0x5e, 0x4f, 0x6b, 0x24, 0x0f,
+ 0xb4, 0xaa, 0xff, 0x92, 0x86, 0x78, 0xa8, 0xc1, 0x69, 0x9c, 0x54, 0xe9, 0x81, 0xa1, 0x9c, 0x26,
+ 0x11, 0x5d, 0xfa, 0xff, 0x70, 0x9e, 0xa3, 0xf3, 0xe3, 0x78, 0x41, 0x2b, 0x31, 0x35, 0x09, 0xa2,
+ 0x5c, 0x5f, 0x6e, 0x4d, 0xad, 0xeb, 0x4a, 0xe0, 0xb1, 0xce, 0x2c, 0x22, 0x59, 0x72, 0x4c, 0x17,
+ 0xad, 0x71, 0x5c, 0x25, 0xca, 0x4f, 0x00, 0xc6, 0xee, 0x63, 0x10, 0x8e, 0xf7, 0xbe, 0xa4, 0x55,
+ 0x22, 0x0d, 0x2c, 0xb9, 0xe5, 0xa9, 0x72, 0x07, 0xa2, 0xb1, 0x29, 0xf2, 0x4a, 0x9f, 0xde, 0x70,
+ 0x0c, 0x28, 0xb7, 0x60, 0x12, 0x9d, 0x4b, 0x04, 0xd7, 0xe3, 0xd7, 0xc5, 0x71, 0xdf, 0x5c, 0xc0,
+ 0x65, 0x75, 0x6e, 0xfb, 0xc6, 0x3e, 0x61, 0x4c, 0xc2, 0xdf, 0xb3, 0xd3, 0xba, 0x17, 0x36, 0x24
+};
+
+static struct NSSLOWKEYPrivateKeyStr rsaPriv;
+
+NSSLOWKEYPrivateKey*
+getDefaultRSAPrivateKey(int keysize)
+{
+ if (rsaPriv.keyType != NSSLOWKEYRSAKey) {
+
+ /* leaving arena uninitialized. It isn't used in this test. */
+
+ rsaPriv.keyType = NSSLOWKEYRSAKey;
+
+ /* leaving arena uninitialized. It isn't used. */
+ /* leaving version uninitialized. It isn't used. */
+
+ if (keysize == 2048) {
+ rsaPriv.u.rsa.modulus.data = default_n2048;
+ rsaPriv.u.rsa.modulus.len = sizeof default_n2048;
+ rsaPriv.u.rsa.publicExponent.data = default_e2048;
+ rsaPriv.u.rsa.publicExponent.len = sizeof default_e2048;
+ rsaPriv.u.rsa.privateExponent.data = default_d2048;
+ rsaPriv.u.rsa.privateExponent.len = sizeof default_d2048;
+ rsaPriv.u.rsa.prime1.data = default_p2048;
+ rsaPriv.u.rsa.prime1.len = sizeof default_p2048;
+ rsaPriv.u.rsa.prime2.data = default_q2048;
+ rsaPriv.u.rsa.prime2.len = sizeof default_q2048;
+ rsaPriv.u.rsa.exponent1.data = default_dModP2048;
+ rsaPriv.u.rsa.exponent1.len = sizeof default_dModP2048;
+ rsaPriv.u.rsa.exponent2.data = default_dModQ2048;
+ rsaPriv.u.rsa.exponent2.len = sizeof default_dModQ2048;
+ rsaPriv.u.rsa.coefficient.data = default_qInvModP2048;
+ rsaPriv.u.rsa.coefficient.len = sizeof default_qInvModP2048;
+ } else {
+ rsaPriv.u.rsa.modulus.data = default_n1024;
+ rsaPriv.u.rsa.modulus.len = sizeof default_n1024;
+ rsaPriv.u.rsa.publicExponent.data = default_e1024;
+ rsaPriv.u.rsa.publicExponent.len = sizeof default_e1024;
+ rsaPriv.u.rsa.privateExponent.data = default_d1024;
+ rsaPriv.u.rsa.privateExponent.len = sizeof default_d1024;
+ rsaPriv.u.rsa.prime1.data = default_p1024;
+ rsaPriv.u.rsa.prime1.len = sizeof default_p1024;
+ rsaPriv.u.rsa.prime2.data = default_q1024;
+ rsaPriv.u.rsa.prime2.len = sizeof default_q1024;
+ rsaPriv.u.rsa.exponent1.data = default_dModP1024;
+ rsaPriv.u.rsa.exponent1.len = sizeof default_dModP1024;
+ rsaPriv.u.rsa.exponent2.data = default_dModQ1024;
+ rsaPriv.u.rsa.exponent2.len = sizeof default_dModQ1024;
+ rsaPriv.u.rsa.coefficient.data = default_qInvModP1024;
+ rsaPriv.u.rsa.coefficient.len = sizeof default_qInvModP1024;
+ }
+ }
+ return &rsaPriv;
+}
+
+static struct NSSLOWKEYPublicKeyStr rsaPub;
+
+NSSLOWKEYPublicKey*
+getDefaultRSAPublicKey(int keysize)
+{
+ if (rsaPub.keyType != NSSLOWKEYRSAKey) {
+
+ rsaPub.keyType = NSSLOWKEYRSAKey;
+
+ if (keysize == 2048) {
+ rsaPub.u.rsa.modulus.data = default_n2048;
+ rsaPub.u.rsa.modulus.len = sizeof default_n2048;
+
+ rsaPub.u.rsa.publicExponent.data = default_e2048;
+ rsaPub.u.rsa.publicExponent.len = sizeof default_e2048;
+ } else {
+ rsaPub.u.rsa.modulus.data = default_n1024;
+ rsaPub.u.rsa.modulus.len = sizeof default_n1024;
+
+ rsaPub.u.rsa.publicExponent.data = default_e1024;
+ rsaPub.u.rsa.publicExponent.len = sizeof default_e1024;
+ }
+ }
+ return &rsaPub;
+}
+
+/* modPop = 536, privPop = 531, ex1Pop = 261, ex2Pop = 257
+ * After 46 tries, found this key:
+ * Version: 0 (0x0)
+ * Modulus:
+ * c2:ae:96:89:af:ce:d0:7b:3b:35:fd:0f:b1:f4:7a:d1:3c:7d:b5:
+ * 86:f2:68:36:c9:97:e6:82:94:86:aa:05:39:ec:11:51:cc:5c:a1:
+ * 59:ba:29:18:f3:28:f1:9d:e3:ae:96:5d:6d:87:73:f6:f6:1f:d0:
+ * 2d:fb:2f:7a:13:7f:c8:0c:7a:e9:85:fb:ce:74:86:f8:ef:2f:85:
+ * 37:73:0f:62:4e:93:17:b7:7e:84:9a:94:11:05:ca:0d:31:4b:2a:
+ * c8:df:fe:e9:0c:13:c7:f2:ad:19:64:28:3c:b5:6a:c8:4b:79:ea:
+ * 7c:ce:75:92:45:3e:a3:9d:64:6f:04:69:19:17
+ * Public Exponent: 65537 (0x10001)
+ * Private Exponent:
+ * 13:cb:bc:f2:f3:35:8c:6d:7b:6f:d9:f3:a6:9c:bd:80:59:2e:4f:
+ * 2f:11:a7:17:2b:18:8f:0f:e8:1a:69:5f:6e:ac:5a:76:7e:d9:4c:
+ * 6e:db:47:22:8a:57:37:7a:5e:94:7a:25:b5:e5:78:1d:3c:99:af:
+ * 89:7d:69:2e:78:9d:1d:84:c8:c1:d7:1a:b2:6d:2d:8a:d9:ab:6b:
+ * ce:ae:b0:a0:58:55:ad:5c:40:8a:d6:96:08:8a:e8:63:e6:3d:6c:
+ * 20:49:c7:af:0f:25:73:d3:69:43:3b:f2:32:f8:3d:5e:ee:7a:ca:
+ * d6:94:55:e5:bd:25:34:8d:63:40:b5:8a:c3:01
+ * Prime 1:
+ * f6:3c:3f:56:58:4f:b3:82:0c:f0:5b:42:36:1c:93:de:9b:32:01:
+ * b1:48:f8:00:57:9b:c1:be:66:c2:bb:ea:7c:75:29:2c:22:aa:7c:
+ * af:bd:0d:3f:b0:64:97:f0:88:25:cb:8d:c7:19:0a:75:44:a4:5a:
+ * c3:b5:b9:85:ea:27:a7
+ * Prime 2:
+ * ca:66:fa:18:6a:46:36:1c:46:fe:47:e9:7e:52:83:8a:bb:72:13:
+ * cc:83:56:3d:64:22:dd:fa:7c:61:99:ea:a4:b3:0e:8f:79:10:ab:
+ * ba:4a:73:d1:48:40:34:34:d3:d2:54:92:be:f5:c8:c4:60:5f:d3:
+ * f7:ce:be:60:3e:b1:11
+ * Exponent 1:
+ * 8e:80:bf:87:11:04:cf:36:6c:96:8d:b9:fb:e6:fe:0c:ce:74:5a:
+ * 56:67:8c:5f:66:54:56:04:03:24:9f:ec:4c:aa:e1:71:11:7e:e9:
+ * 3a:2b:87:07:5c:e6:5a:a8:71:a2:ad:f3:17:4e:7e:a6:ef:5a:ce:
+ * cc:84:d7:21:91:29:f1
+ * Exponent 2:
+ * 87:60:1d:02:db:82:1e:8b:07:48:e8:5c:59:eb:62:a4:15:ff:95:
+ * 12:82:fd:d9:8d:f2:6c:3a:2f:9b:30:51:6a:db:80:6f:a1:ef:ee:
+ * 8c:69:63:d1:a4:db:9c:8f:80:e5:fb:3f:33:8e:3d:3c:6b:a1:6c:
+ * ab:20:92:e0:d8:cd:a1
+ * Coefficient:
+ * ce:cf:5a:ad:c4:8c:44:91:3a:bc:7b:f8:80:f8:53:f5:12:84:8c:
+ * 9c:6b:33:93:0d:a1:11:ea:fa:4a:c1:eb:48:dc:44:86:93:1b:98:
+ * c7:82:22:68:30:44:d7:62:1b:90:54:07:4b:66:a7:c5:75:5a:72:
+ * 77:92:dd:6c:f3:37:ab
+ */
diff --git a/security/nss/cmd/rsaperf/manifest.mn b/security/nss/cmd/rsaperf/manifest.mn
new file mode 100644
index 000000000..14fce7271
--- /dev/null
+++ b/security/nss/cmd/rsaperf/manifest.mn
@@ -0,0 +1,24 @@
+#
+# 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/.
+
+DEPTH = ../..
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+REQUIRES = dbm seccmd
+
+# DIRS =
+
+CSRCS = rsaperf.c defkey.c
+
+PROGRAM = rsaperf
+
+USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/rsaperf/rsaperf.c b/security/nss/cmd/rsaperf/rsaperf.c
new file mode 100644
index 000000000..556030f6a
--- /dev/null
+++ b/security/nss/cmd/rsaperf/rsaperf.c
@@ -0,0 +1,696 @@
+/* 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/. */
+
+#include "seccomon.h"
+#include "cert.h"
+#include "secutil.h"
+#include "nspr.h"
+#include "nss.h"
+#include "blapi.h"
+#include "plgetopt.h"
+#include "lowkeyi.h"
+#include "pk11pub.h"
+
+#define DEFAULT_ITERS 10
+#define DEFAULT_DURATION 10
+#define DEFAULT_KEY_BITS 1024
+#define MIN_KEY_BITS 512
+#define MAX_KEY_BITS 65536
+#define BUFFER_BYTES MAX_KEY_BITS / 8
+#define DEFAULT_THREADS 1
+#define DEFAULT_EXPONENT 0x10001
+
+extern NSSLOWKEYPrivateKey *getDefaultRSAPrivateKey(void);
+extern NSSLOWKEYPublicKey *getDefaultRSAPublicKey(void);
+
+secuPWData pwData = { PW_NONE, NULL };
+
+typedef struct TimingContextStr TimingContext;
+
+struct TimingContextStr {
+ PRTime start;
+ PRTime end;
+ PRTime interval;
+
+ long days;
+ int hours;
+ int minutes;
+ int seconds;
+ int millisecs;
+};
+
+TimingContext *
+CreateTimingContext(void)
+{
+ return PORT_Alloc(sizeof(TimingContext));
+}
+
+void
+DestroyTimingContext(TimingContext *ctx)
+{
+ PORT_Free(ctx);
+}
+
+void
+TimingBegin(TimingContext *ctx, PRTime begin)
+{
+ ctx->start = begin;
+}
+
+static void
+timingUpdate(TimingContext *ctx)
+{
+ PRInt64 tmp, remaining;
+ PRInt64 L1000, L60, L24;
+
+ LL_I2L(L1000, 1000);
+ LL_I2L(L60, 60);
+ LL_I2L(L24, 24);
+
+ LL_DIV(remaining, ctx->interval, L1000);
+ LL_MOD(tmp, remaining, L1000);
+ LL_L2I(ctx->millisecs, tmp);
+ LL_DIV(remaining, remaining, L1000);
+ LL_MOD(tmp, remaining, L60);
+ LL_L2I(ctx->seconds, tmp);
+ LL_DIV(remaining, remaining, L60);
+ LL_MOD(tmp, remaining, L60);
+ LL_L2I(ctx->minutes, tmp);
+ LL_DIV(remaining, remaining, L60);
+ LL_MOD(tmp, remaining, L24);
+ LL_L2I(ctx->hours, tmp);
+ LL_DIV(remaining, remaining, L24);
+ LL_L2I(ctx->days, remaining);
+}
+
+void
+TimingEnd(TimingContext *ctx, PRTime end)
+{
+ ctx->end = end;
+ LL_SUB(ctx->interval, ctx->end, ctx->start);
+ PORT_Assert(LL_GE_ZERO(ctx->interval));
+ timingUpdate(ctx);
+}
+
+void
+TimingDivide(TimingContext *ctx, int divisor)
+{
+ PRInt64 tmp;
+
+ LL_I2L(tmp, divisor);
+ LL_DIV(ctx->interval, ctx->interval, tmp);
+
+ timingUpdate(ctx);
+}
+
+char *
+TimingGenerateString(TimingContext *ctx)
+{
+ char *buf = NULL;
+
+ if (ctx->days != 0) {
+ buf = PR_sprintf_append(buf, "%d days", ctx->days);
+ }
+ if (ctx->hours != 0) {
+ if (buf != NULL)
+ buf = PR_sprintf_append(buf, ", ");
+ buf = PR_sprintf_append(buf, "%d hours", ctx->hours);
+ }
+ if (ctx->minutes != 0) {
+ if (buf != NULL)
+ buf = PR_sprintf_append(buf, ", ");
+ buf = PR_sprintf_append(buf, "%d minutes", ctx->minutes);
+ }
+ if (buf != NULL)
+ buf = PR_sprintf_append(buf, ", and ");
+ if (!buf && ctx->seconds == 0) {
+ int interval;
+ LL_L2I(interval, ctx->interval);
+ if (ctx->millisecs < 100)
+ buf = PR_sprintf_append(buf, "%d microseconds", interval);
+ else
+ buf = PR_sprintf_append(buf, "%d milliseconds", ctx->millisecs);
+ } else if (ctx->millisecs == 0) {
+ buf = PR_sprintf_append(buf, "%d seconds", ctx->seconds);
+ } else {
+ buf = PR_sprintf_append(buf, "%d.%03d seconds",
+ ctx->seconds, ctx->millisecs);
+ }
+ return buf;
+}
+
+void
+Usage(char *progName)
+{
+ fprintf(stderr, "Usage: %s [-s | -e] [-i iterations | -p period] "
+ "[-t threads]\n[-n none [-k keylength] [ [-g] -x exponent] |\n"
+ " -n token:nickname [-d certdir] [-w password] |\n"
+ " -h token [-d certdir] [-w password] [-g] [-k keylength] "
+ "[-x exponent] [-f pwfile]\n",
+ progName);
+ fprintf(stderr, "%-20s Cert database directory (default is ~/.netscape)\n",
+ "-d certdir");
+ fprintf(stderr, "%-20s How many operations to perform\n", "-i iterations");
+ fprintf(stderr, "%-20s How many seconds to run\n", "-p period");
+ fprintf(stderr, "%-20s Perform signing (private key) operations\n", "-s");
+ fprintf(stderr, "%-20s Perform encryption (public key) operations\n", "-e");
+ fprintf(stderr, "%-20s Nickname of certificate or key, prefixed "
+ "by optional token name\n",
+ "-n nickname");
+ fprintf(stderr, "%-20s PKCS#11 token to perform operation with.\n",
+ "-h token");
+ fprintf(stderr, "%-20s key size in bits, from %d to %d\n", "-k keylength",
+ MIN_KEY_BITS, MAX_KEY_BITS);
+ fprintf(stderr, "%-20s token password\n", "-w password");
+ fprintf(stderr, "%-20s temporary key generation. Not for token keys.\n",
+ "-g");
+ fprintf(stderr, "%-20s set public exponent for keygen\n", "-x");
+ fprintf(stderr, "%-20s Number of execution threads (default 1)\n",
+ "-t threads");
+ exit(-1);
+}
+
+static void
+dumpBytes(unsigned char *b, int l)
+{
+ int i;
+ if (l <= 0)
+ return;
+ for (i = 0; i < l; ++i) {
+ if (i % 16 == 0)
+ printf("\t");
+ printf(" %02x", b[i]);
+ if (i % 16 == 15)
+ printf("\n");
+ }
+ if ((i % 16) != 0)
+ printf("\n");
+}
+
+static void
+dumpItem(SECItem *item, const char *description)
+{
+ if (item->len & 1 && item->data[0] == 0) {
+ printf("%s: (%d bytes)\n", description, item->len - 1);
+ dumpBytes(item->data + 1, item->len - 1);
+ } else {
+ printf("%s: (%d bytes)\n", description, item->len);
+ dumpBytes(item->data, item->len);
+ }
+}
+
+void
+printPrivKey(NSSLOWKEYPrivateKey *privKey)
+{
+ RSAPrivateKey *rsa = &privKey->u.rsa;
+
+ dumpItem(&rsa->modulus, "n");
+ dumpItem(&rsa->publicExponent, "e");
+ dumpItem(&rsa->privateExponent, "d");
+ dumpItem(&rsa->prime1, "P");
+ dumpItem(&rsa->prime2, "Q");
+ dumpItem(&rsa->exponent1, "d % (P-1)");
+ dumpItem(&rsa->exponent2, "d % (Q-1)");
+ dumpItem(&rsa->coefficient, "(Q ** -1) % P");
+ puts("");
+}
+
+typedef SECStatus (*RSAOp)(void *key,
+ unsigned char *output,
+ unsigned char *input);
+
+typedef struct {
+ SECKEYPublicKey *pubKey;
+ SECKEYPrivateKey *privKey;
+} PK11Keys;
+
+SECStatus
+PK11_PublicKeyOp(SECKEYPublicKey *key,
+ unsigned char *output,
+ unsigned char *input)
+{
+ return PK11_PubEncryptRaw(key, output, input, key->u.rsa.modulus.len,
+ NULL);
+}
+
+SECStatus
+PK11_PrivateKeyOp(PK11Keys *keys,
+ unsigned char *output,
+ unsigned char *input)
+{
+ unsigned outLen = 0;
+ return PK11_PrivDecryptRaw(keys->privKey,
+ output, &outLen,
+ keys->pubKey->u.rsa.modulus.len, input,
+ keys->pubKey->u.rsa.modulus.len);
+}
+typedef struct ThreadRunDataStr ThreadRunData;
+
+struct ThreadRunDataStr {
+ const PRBool *doIters;
+ const void *rsaKey;
+ const unsigned char *buf;
+ RSAOp fn;
+ int seconds;
+ long iters;
+ long iterRes;
+ PRErrorCode errNum;
+ SECStatus status;
+};
+
+void
+ThreadExecFunction(void *data)
+{
+ ThreadRunData *tdata = (ThreadRunData *)data;
+ unsigned char buf2[BUFFER_BYTES];
+
+ tdata->status = SECSuccess;
+ if (*tdata->doIters) {
+ long i = tdata->iters;
+ tdata->iterRes = 0;
+ while (i--) {
+ SECStatus rv = tdata->fn((void *)tdata->rsaKey, buf2,
+ (unsigned char *)tdata->buf);
+ if (rv != SECSuccess) {
+ tdata->errNum = PORT_GetError();
+ tdata->status = rv;
+ break;
+ }
+ tdata->iterRes++;
+ }
+ } else {
+ PRIntervalTime total = PR_SecondsToInterval(tdata->seconds);
+ PRIntervalTime start = PR_IntervalNow();
+ tdata->iterRes = 0;
+ while (PR_IntervalNow() - start < total) {
+ SECStatus rv = tdata->fn((void *)tdata->rsaKey, buf2,
+ (unsigned char *)tdata->buf);
+ if (rv != SECSuccess) {
+ tdata->errNum = PORT_GetError();
+ tdata->status = rv;
+ break;
+ }
+ tdata->iterRes++;
+ }
+ }
+}
+
+#define INT_ARG(arg, def) atol(arg) > 0 ? atol(arg) : def
+
+int
+main(int argc, char **argv)
+{
+ TimingContext *timeCtx = NULL;
+ SECKEYPublicKey *pubHighKey = NULL;
+ SECKEYPrivateKey *privHighKey = NULL;
+ NSSLOWKEYPrivateKey *privKey = NULL;
+ NSSLOWKEYPublicKey *pubKey = NULL;
+ CERTCertificate *cert = NULL;
+ char *progName = NULL;
+ char *secDir = NULL;
+ char *nickname = NULL;
+ char *slotname = NULL;
+ long keybits = 0;
+ RSAOp fn;
+ void *rsaKey = NULL;
+ PLOptState *optstate;
+ PLOptStatus optstatus;
+ long iters = DEFAULT_ITERS;
+ int i;
+ PRBool doPriv = PR_FALSE;
+ PRBool doPub = PR_FALSE;
+ int rv;
+ unsigned char buf[BUFFER_BYTES];
+ unsigned char buf2[BUFFER_BYTES];
+ int seconds = DEFAULT_DURATION;
+ PRBool doIters = PR_FALSE;
+ PRBool doTime = PR_FALSE;
+ PRBool useTokenKey = PR_FALSE; /* use PKCS#11 token
+ object key */
+ PRBool useSessionKey = PR_FALSE; /* use PKCS#11 session
+ object key */
+ PRBool useBLKey = PR_FALSE; /* use freebl */
+ PK11SlotInfo *slot = NULL; /* slot for session
+ object key operations */
+ PRBool doKeyGen = PR_FALSE;
+ int publicExponent = DEFAULT_EXPONENT;
+ PK11Keys keys;
+ int peCount = 0;
+ CK_BYTE pubEx[4];
+ SECItem pe;
+ RSAPublicKey pubKeyStr;
+ int threadNum = DEFAULT_THREADS;
+ ThreadRunData **runDataArr = NULL;
+ PRThread **threadsArr = NULL;
+ int calcThreads = 0;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName + 1 : argv[0];
+
+ optstate = PL_CreateOptState(argc, argv, "d:ef:gh:i:k:n:p:st:w:x:");
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+ case 'd':
+ secDir = PORT_Strdup(optstate->value);
+ break;
+ case 'i':
+ iters = INT_ARG(optstate->value, DEFAULT_ITERS);
+ doIters = PR_TRUE;
+ break;
+ case 's':
+ doPriv = PR_TRUE;
+ break;
+ case 'e':
+ doPub = PR_TRUE;
+ break;
+ case 'g':
+ doKeyGen = PR_TRUE;
+ break;
+ case 'n':
+ nickname = PORT_Strdup(optstate->value);
+ /* for compatibility, nickname of "none" means go to freebl */
+ if (nickname && strcmp(nickname, "none")) {
+ useTokenKey = PR_TRUE;
+ } else {
+ useBLKey = PR_TRUE;
+ }
+ break;
+ case 'p':
+ seconds = INT_ARG(optstate->value, DEFAULT_DURATION);
+ doTime = PR_TRUE;
+ break;
+ case 'h':
+ slotname = PORT_Strdup(optstate->value);
+ useSessionKey = PR_TRUE;
+ break;
+ case 'k':
+ keybits = INT_ARG(optstate->value, DEFAULT_KEY_BITS);
+ break;
+ case 'w':
+ pwData.data = PORT_Strdup(optstate->value);
+ ;
+ pwData.source = PW_PLAINTEXT;
+ break;
+ case 'f':
+ pwData.data = PORT_Strdup(optstate->value);
+ pwData.source = PW_FROMFILE;
+ break;
+ case 'x':
+ /* -x public exponent (for RSA keygen) */
+ publicExponent = INT_ARG(optstate->value, DEFAULT_EXPONENT);
+ break;
+ case 't':
+ threadNum = INT_ARG(optstate->value, DEFAULT_THREADS);
+ break;
+ }
+ }
+ if (optstatus == PL_OPT_BAD)
+ Usage(progName);
+
+ if ((doPriv && doPub) || (doIters && doTime) ||
+ ((useTokenKey + useSessionKey + useBLKey) != PR_TRUE) ||
+ (useTokenKey && keybits) || (useTokenKey && doKeyGen) ||
+ (keybits && (keybits < MIN_KEY_BITS || keybits > MAX_KEY_BITS))) {
+ Usage(progName);
+ }
+
+ if (doIters && doTime)
+ Usage(progName);
+
+ if (!doTime) {
+ doIters = PR_TRUE;
+ }
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+ secDir = SECU_ConfigDirectory(secDir);
+
+ if (useTokenKey || useSessionKey) {
+ rv = NSS_Init(secDir);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "NSS_Init failed.\n");
+ exit(1);
+ }
+ } else {
+ rv = NSS_NoDB_Init(NULL);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "NSS_NoDB_Init failed.\n");
+ exit(1);
+ }
+ }
+
+ if (useTokenKey) {
+ CK_OBJECT_HANDLE kh = CK_INVALID_HANDLE;
+
+ cert = PK11_FindCertFromNickname(nickname, &pwData);
+ if (cert == NULL) {
+ fprintf(stderr,
+ "Can't find certificate by name \"%s\"\n", nickname);
+ exit(1);
+ }
+ pubHighKey = CERT_ExtractPublicKey(cert);
+ if (pubHighKey == NULL) {
+ fprintf(stderr, "Can't extract public key from certificate");
+ exit(1);
+ }
+
+ if (doPub) {
+ /* do public key ops */
+ fn = (RSAOp)PK11_PublicKeyOp;
+ rsaKey = (void *)pubHighKey;
+
+ kh = PK11_ImportPublicKey(cert->slot, pubHighKey, PR_FALSE);
+ if (CK_INVALID_HANDLE == kh) {
+ fprintf(stderr,
+ "Unable to import public key to certificate slot.");
+ exit(1);
+ }
+ pubHighKey->pkcs11Slot = PK11_ReferenceSlot(cert->slot);
+ pubHighKey->pkcs11ID = kh;
+ printf("Using PKCS#11 for RSA encryption with token %s.\n",
+ PK11_GetTokenName(cert->slot));
+ } else {
+ /* do private key ops */
+ privHighKey = PK11_FindKeyByAnyCert(cert, &pwData);
+ if (privHighKey == NULL) {
+ fprintf(stderr,
+ "Can't find private key by name \"%s\"\n", nickname);
+ exit(1);
+ }
+
+ SECKEY_CacheStaticFlags(privHighKey);
+ fn = (RSAOp)PK11_PrivateKeyOp;
+ keys.privKey = privHighKey;
+ keys.pubKey = pubHighKey;
+ rsaKey = (void *)&keys;
+ printf("Using PKCS#11 for RSA decryption with token %s.\n",
+ PK11_GetTokenName(privHighKey->pkcs11Slot));
+ }
+ } else
+
+ if (useSessionKey) {
+ /* use PKCS#11 session key objects */
+ PK11RSAGenParams rsaparams;
+ void *params;
+
+ slot = PK11_FindSlotByName(slotname); /* locate target slot */
+ if (!slot) {
+ fprintf(stderr, "Can't find slot \"%s\"\n", slotname);
+ exit(1);
+ }
+
+ /* do a temporary keygen in selected slot */
+ if (!keybits) {
+ keybits = DEFAULT_KEY_BITS;
+ }
+
+ printf("Using PKCS#11 with %ld bits session key in token %s.\n",
+ keybits, PK11_GetTokenName(slot));
+
+ rsaparams.keySizeInBits = keybits;
+ rsaparams.pe = publicExponent;
+ params = &rsaparams;
+
+ fprintf(stderr, "\nGenerating RSA key. This may take a few moments.\n");
+
+ privHighKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,
+ params, &pubHighKey, PR_FALSE,
+ PR_FALSE, (void *)&pwData);
+ if (!privHighKey) {
+ fprintf(stderr,
+ "Key generation failed in token \"%s\"\n",
+ PK11_GetTokenName(slot));
+ exit(1);
+ }
+
+ SECKEY_CacheStaticFlags(privHighKey);
+
+ fprintf(stderr, "Keygen completed.\n");
+
+ if (doPub) {
+ /* do public key operations */
+ fn = (RSAOp)PK11_PublicKeyOp;
+ rsaKey = (void *)pubHighKey;
+ } else {
+ /* do private key operations */
+ fn = (RSAOp)PK11_PrivateKeyOp;
+ keys.privKey = privHighKey;
+ keys.pubKey = pubHighKey;
+ rsaKey = (void *)&keys;
+ }
+ } else
+
+ {
+ /* use freebl directly */
+ if (!keybits) {
+ keybits = DEFAULT_KEY_BITS;
+ }
+ if (!doKeyGen) {
+ if (keybits != DEFAULT_KEY_BITS) {
+ doKeyGen = PR_TRUE;
+ }
+ }
+ printf("Using freebl with %ld bits key.\n", keybits);
+ if (doKeyGen) {
+ fprintf(stderr, "\nGenerating RSA key. "
+ "This may take a few moments.\n");
+ for (i = 0; i < 4; i++) {
+ if (peCount || (publicExponent & ((unsigned long)0xff000000L >>
+ (i * 8)))) {
+ pubEx[peCount] = (CK_BYTE)((publicExponent >>
+ (3 - i) * 8) &
+ 0xff);
+ peCount++;
+ }
+ }
+ pe.len = peCount;
+ pe.data = &pubEx[0];
+ pe.type = siBuffer;
+
+ rsaKey = RSA_NewKey(keybits, &pe);
+ fprintf(stderr, "Keygen completed.\n");
+ } else {
+ /* use a hardcoded key */
+ printf("Using hardcoded %ld bits key.\n", keybits);
+ if (doPub) {
+ pubKey = getDefaultRSAPublicKey();
+ } else {
+ privKey = getDefaultRSAPrivateKey();
+ }
+ }
+
+ if (doPub) {
+ /* do public key operations */
+ fn = (RSAOp)RSA_PublicKeyOp;
+ if (rsaKey) {
+ /* convert the RSAPrivateKey to RSAPublicKey */
+ pubKeyStr.arena = NULL;
+ pubKeyStr.modulus = ((RSAPrivateKey *)rsaKey)->modulus;
+ pubKeyStr.publicExponent =
+ ((RSAPrivateKey *)rsaKey)->publicExponent;
+ rsaKey = &pubKeyStr;
+ } else {
+ /* convert NSSLOWKeyPublicKey to RSAPublicKey */
+ rsaKey = (void *)(&pubKey->u.rsa);
+ }
+ PORT_Assert(rsaKey);
+ } else {
+ /* do private key operations */
+ fn = (RSAOp)RSA_PrivateKeyOp;
+ if (privKey) {
+ /* convert NSSLOWKeyPrivateKey to RSAPrivateKey */
+ rsaKey = (void *)(&privKey->u.rsa);
+ }
+ PORT_Assert(rsaKey);
+ }
+ }
+
+ memset(buf, 1, sizeof buf);
+ rv = fn(rsaKey, buf2, buf);
+ if (rv != SECSuccess) {
+ PRErrorCode errNum;
+ const char *errStr = NULL;
+
+ errNum = PORT_GetError();
+ if (errNum)
+ errStr = SECU_Strerror(errNum);
+ else
+ errNum = rv;
+ if (!errStr)
+ errStr = "(null)";
+ fprintf(stderr, "Error in RSA operation: %d : %s\n", errNum, errStr);
+ exit(1);
+ }
+
+ threadsArr = (PRThread **)PORT_Alloc(threadNum * sizeof(PRThread *));
+ runDataArr = (ThreadRunData **)PORT_Alloc(threadNum * sizeof(ThreadRunData *));
+ timeCtx = CreateTimingContext();
+ TimingBegin(timeCtx, PR_Now());
+ for (i = 0; i < threadNum; i++) {
+ runDataArr[i] = (ThreadRunData *)PORT_Alloc(sizeof(ThreadRunData));
+ runDataArr[i]->fn = fn;
+ runDataArr[i]->buf = buf;
+ runDataArr[i]->doIters = &doIters;
+ runDataArr[i]->rsaKey = rsaKey;
+ runDataArr[i]->seconds = seconds;
+ runDataArr[i]->iters = iters;
+ threadsArr[i] =
+ PR_CreateThread(PR_USER_THREAD,
+ ThreadExecFunction,
+ (void *)runDataArr[i],
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ }
+ iters = 0;
+ calcThreads = 0;
+ for (i = 0; i < threadNum; i++, calcThreads++) {
+ PR_JoinThread(threadsArr[i]);
+ if (runDataArr[i]->status != SECSuccess) {
+ const char *errStr = SECU_Strerror(runDataArr[i]->errNum);
+ fprintf(stderr, "Thread %d: Error in RSA operation: %d : %s\n",
+ i, runDataArr[i]->errNum, errStr);
+ calcThreads -= 1;
+ } else {
+ iters += runDataArr[i]->iterRes;
+ }
+ PORT_Free((void *)runDataArr[i]);
+ }
+ PORT_Free(runDataArr);
+ PORT_Free(threadsArr);
+
+ TimingEnd(timeCtx, PR_Now());
+
+ printf("%ld iterations in %s\n",
+ iters, TimingGenerateString(timeCtx));
+ printf("%.2f operations/s .\n", ((double)(iters) * (double)1000000.0) /
+ (double)timeCtx->interval);
+ TimingDivide(timeCtx, iters);
+ printf("one operation every %s\n", TimingGenerateString(timeCtx));
+
+ if (pubHighKey) {
+ SECKEY_DestroyPublicKey(pubHighKey);
+ }
+
+ if (privHighKey) {
+ SECKEY_DestroyPrivateKey(privHighKey);
+ }
+
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/security/nss/cmd/rsaperf/rsaperf.gyp b/security/nss/cmd/rsaperf/rsaperf.gyp
new file mode 100644
index 000000000..8ca4b4c50
--- /dev/null
+++ b/security/nss/cmd/rsaperf/rsaperf.gyp
@@ -0,0 +1,36 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'rsaperf',
+ 'type': 'executable',
+ 'sources': [
+ 'defkey.c',
+ 'rsaperf.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports',
+ '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'include_dirs': [
+ '../../nss/lib/softoken'
+ ],
+ 'defines': [
+ 'NSS_USE_STATIC_LIBS'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss',
+ 'use_static_libs': 1
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/rsapoptst/Makefile b/security/nss/cmd/rsapoptst/Makefile
new file mode 100644
index 000000000..a5e83efdf
--- /dev/null
+++ b/security/nss/cmd/rsapoptst/Makefile
@@ -0,0 +1,54 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+#MKPROG = purify -cache-dir=/u/mcgreer/pcache -best-effort \
+# -always-use-cache-dir $(CC)
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#EXTRA_SHARED_LIBS += \
+# -L/usr/lib \
+# -lposix4 \
+# $(NULL)
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/security/nss/cmd/rsapoptst/manifest.mn b/security/nss/cmd/rsapoptst/manifest.mn
new file mode 100644
index 000000000..18126cffc
--- /dev/null
+++ b/security/nss/cmd/rsapoptst/manifest.mn
@@ -0,0 +1,22 @@
+#
+# 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/.
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+REQUIRES = seccmd dbm softoken
+
+PROGRAM = rsapoptst
+
+EXPORTS = \
+ $(NULL)
+
+PRIVATE_EXPORTS = \
+ $(NULL)
+
+CSRCS = \
+ rsapoptst.c \
+ $(NULL)
+
diff --git a/security/nss/cmd/rsapoptst/rsapoptst.c b/security/nss/cmd/rsapoptst/rsapoptst.c
new file mode 100644
index 000000000..81ddcd6c4
--- /dev/null
+++ b/security/nss/cmd/rsapoptst/rsapoptst.c
@@ -0,0 +1,535 @@
+/* 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/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "plgetopt.h"
+#include "nss.h"
+#include "secutil.h"
+#include "pk11table.h"
+#include "secmodt.h"
+#include "pk11pub.h"
+
+struct test_args {
+ char *arg;
+ int mask_value;
+ char *description;
+};
+
+static const struct test_args test_array[] = {
+ { "all", 0x1f, "run all the tests" },
+ { "e_n_p", 0x01, "public exponent, modulus, prime1" },
+ { "d_n_q", 0x02, "private exponent, modulus, prime2" },
+ { "d_p_q", 0x04, "private exponent, prime1, prime2" },
+ { "e_d_q", 0x08, "public exponent, private exponent, prime2" },
+ { "e_d_n", 0x10, "public exponent, private exponent, moduls" }
+};
+static const int test_array_size =
+ (sizeof(test_array) / sizeof(struct test_args));
+
+static void
+Usage(char *progName)
+{
+ int i;
+#define PRINTUSAGE(subject, option, predicate) \
+ fprintf(stderr, "%10s %s\t%s\n", subject, option, predicate);
+ fprintf(stderr, "%s [-k keysize] [-e exp] [-r rounds] [-t tests]\n "
+ "Test creating RSA private keys from Partial components\n",
+ progName);
+ PRINTUSAGE("", "-k", "key size (in bit)");
+ PRINTUSAGE("", "-e", "rsa public exponent");
+ PRINTUSAGE("", "-r", "number times to repeat the test");
+ PRINTUSAGE("", "-t", "run the specified tests");
+ for (i = 0; i < test_array_size; i++) {
+ PRINTUSAGE("", test_array[i].arg, test_array[i].description);
+ }
+ fprintf(stderr, "\n");
+}
+
+/*
+ * Test the RSA populate command to see that it can really build
+ * keys from it's components.
+ */
+
+const static CK_ATTRIBUTE rsaTemplate[] = {
+ { CKA_CLASS, NULL, 0 },
+ { CKA_KEY_TYPE, NULL, 0 },
+ { CKA_TOKEN, NULL, 0 },
+ { CKA_SENSITIVE, NULL, 0 },
+ { CKA_PRIVATE, NULL, 0 },
+ { CKA_MODULUS, NULL, 0 },
+ { CKA_PUBLIC_EXPONENT, NULL, 0 },
+ { CKA_PRIVATE_EXPONENT, NULL, 0 },
+ { CKA_PRIME_1, NULL, 0 },
+ { CKA_PRIME_2, NULL, 0 },
+ { CKA_EXPONENT_1, NULL, 0 },
+ { CKA_EXPONENT_2, NULL, 0 },
+ { CKA_COEFFICIENT, NULL, 0 },
+};
+
+#define RSA_SIZE (sizeof(rsaTemplate))
+#define RSA_ATTRIBUTES (sizeof(rsaTemplate) / sizeof(CK_ATTRIBUTE))
+
+static void
+resetTemplate(CK_ATTRIBUTE *attribute, int start, int end)
+{
+ int i;
+ for (i = start; i < end; i++) {
+ if (attribute[i].pValue) {
+ PORT_Free(attribute[i].pValue);
+ }
+ attribute[i].pValue = NULL;
+ attribute[i].ulValueLen = 0;
+ }
+}
+
+static SECStatus
+copyAttribute(PK11ObjectType objType, void *object, CK_ATTRIBUTE *template,
+ int offset, CK_ATTRIBUTE_TYPE attrType)
+{
+ SECItem attributeItem = { 0, 0, 0 };
+ SECStatus rv;
+
+ rv = PK11_ReadRawAttribute(objType, object, attrType, &attributeItem);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ template[offset].type = attrType;
+ template[offset].pValue = attributeItem.data;
+ template[offset].ulValueLen = attributeItem.len;
+ return SECSuccess;
+}
+
+static SECStatus
+readKey(PK11ObjectType objType, void *object, CK_ATTRIBUTE *template,
+ int start, int end)
+{
+ int i;
+ SECStatus rv;
+
+ for (i = start; i < end; i++) {
+ rv = copyAttribute(objType, object, template, i, template[i].type);
+ if (rv != SECSuccess) {
+ goto fail;
+ }
+ }
+ return SECSuccess;
+
+fail:
+ resetTemplate(template, start, i);
+ return rv;
+}
+
+#define ATTR_STRING(x) getNameFromAttribute(x)
+
+void
+dumpTemplate(CK_ATTRIBUTE *template, int start, int end)
+{
+ int i, j;
+ for (i = 0; i < end; i++) {
+ unsigned char cval;
+ CK_ULONG ulval;
+ unsigned char *cpval;
+
+ fprintf(stderr, "%s:", ATTR_STRING(template[i].type));
+ switch (template[i].ulValueLen) {
+ case 1:
+ cval = *(unsigned char *)template[i].pValue;
+ switch (cval) {
+ case 0:
+ fprintf(stderr, " false");
+ break;
+ case 1:
+ fprintf(stderr, " true");
+ break;
+ default:
+ fprintf(stderr, " %d (=0x%02x,'%c')", cval, cval, cval);
+ break;
+ }
+ break;
+ case sizeof(CK_ULONG):
+ ulval = *(CK_ULONG *)template[i].pValue;
+ fprintf(stderr, " %ld (=0x%04lx)", ulval, ulval);
+ break;
+ default:
+ cpval = (unsigned char *)template[i].pValue;
+ for (j = 0; j < template[i].ulValueLen; j++) {
+ if ((j % 16) == 0)
+ fprintf(stderr, "\n ");
+ fprintf(stderr, " %02x", cpval[j]);
+ }
+ break;
+ }
+ fprintf(stderr, "\n");
+ }
+}
+
+PRBool
+rsaKeysAreEqual(PK11ObjectType srcType, void *src,
+ PK11ObjectType destType, void *dest)
+{
+
+ CK_ATTRIBUTE srcTemplate[RSA_ATTRIBUTES];
+ CK_ATTRIBUTE destTemplate[RSA_ATTRIBUTES];
+ PRBool areEqual = PR_TRUE;
+ SECStatus rv;
+ int i;
+
+ memcpy(srcTemplate, rsaTemplate, RSA_SIZE);
+ memcpy(destTemplate, rsaTemplate, RSA_SIZE);
+
+ rv = readKey(srcType, src, srcTemplate, 0, RSA_ATTRIBUTES);
+ if (rv != SECSuccess) {
+ printf("Could read source key\n");
+ return PR_FALSE;
+ }
+ readKey(destType, dest, destTemplate, 0, RSA_ATTRIBUTES);
+ if (rv != SECSuccess) {
+ printf("Could read dest key\n");
+ return PR_FALSE;
+ }
+
+ for (i = 0; i < RSA_ATTRIBUTES; i++) {
+ if (srcTemplate[i].ulValueLen != destTemplate[i].ulValueLen) {
+ printf("key->%s not equal src_len = %ld, dest_len=%ld\n",
+ ATTR_STRING(srcTemplate[i].type),
+ srcTemplate[i].ulValueLen, destTemplate[i].ulValueLen);
+ areEqual = 0;
+ } else if (memcmp(srcTemplate[i].pValue, destTemplate[i].pValue,
+ destTemplate[i].ulValueLen) != 0) {
+ printf("key->%s not equal.\n", ATTR_STRING(srcTemplate[i].type));
+ areEqual = 0;
+ }
+ }
+ if (!areEqual) {
+ fprintf(stderr, "original key:\n");
+ dumpTemplate(srcTemplate, 0, RSA_ATTRIBUTES);
+ fprintf(stderr, "created key:\n");
+ dumpTemplate(destTemplate, 0, RSA_ATTRIBUTES);
+ }
+ return areEqual;
+}
+
+static int exp_exp_prime_fail_count = 0;
+
+static int
+doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
+ int mask, void *pwarg)
+{
+ SECKEYPrivateKey *rsaPrivKey;
+ SECKEYPublicKey *rsaPubKey;
+ PK11GenericObject *tstPrivKey;
+ CK_ATTRIBUTE tstTemplate[RSA_ATTRIBUTES];
+ int tstHeaderCount;
+ PK11SlotInfo *slot = NULL;
+ PK11RSAGenParams rsaParams;
+ CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE key_type = CKK_RSA;
+ CK_BBOOL ck_false = CK_FALSE;
+ int failed = 0;
+
+ rsaParams.pe = exponent;
+ rsaParams.keySizeInBits = keySize;
+
+ slot = PK11_GetInternalSlot();
+ if (slot == NULL) {
+ fprintf(stderr, "Couldn't get the internal slot for the test \n");
+ return -1;
+ }
+
+ rsaPrivKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,
+ &rsaParams, &rsaPubKey, PR_FALSE,
+ PR_FALSE, pwarg);
+ if (rsaPrivKey == NULL) {
+ fprintf(stderr, "RSA Key Gen failed");
+ PK11_FreeSlot(slot);
+ return -1;
+ }
+
+ memcpy(tstTemplate, rsaTemplate, RSA_SIZE);
+
+ tstTemplate[0].pValue = &obj_class;
+ tstTemplate[0].ulValueLen = sizeof(obj_class);
+ tstTemplate[1].pValue = &key_type;
+ tstTemplate[1].ulValueLen = sizeof(key_type);
+ tstTemplate[2].pValue = &ck_false;
+ tstTemplate[2].ulValueLen = sizeof(ck_false);
+ tstTemplate[3].pValue = &ck_false;
+ tstTemplate[3].ulValueLen = sizeof(ck_false);
+ tstTemplate[4].pValue = &ck_false;
+ tstTemplate[4].ulValueLen = sizeof(ck_false);
+ tstHeaderCount = 5;
+
+ if (mask & 1) {
+ printf("%s\n", test_array[1].description);
+ resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount, CKA_PUBLIC_EXPONENT);
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount + 1, CKA_MODULUS);
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount + 2, CKA_PRIME_1);
+
+ tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
+ tstHeaderCount +
+ 3,
+ PR_FALSE);
+ if (tstPrivKey == NULL) {
+ fprintf(stderr, "RSA Populate failed: pubExp mod p\n");
+ failed = 1;
+ } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
+ PK11_TypeGeneric, tstPrivKey)) {
+ fprintf(stderr, "RSA Populate key mismatch: pubExp mod p\n");
+ failed = 1;
+ }
+ if (tstPrivKey)
+ PK11_DestroyGenericObject(tstPrivKey);
+ }
+ if (mask & 2) {
+ printf("%s\n", test_array[2].description);
+ /* test the basic2 case, public exponent, modulus, prime2 */
+ resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount, CKA_PUBLIC_EXPONENT);
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount + 1, CKA_MODULUS);
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount + 2, CKA_PRIME_2);
+ /* test with q in the prime1 position */
+ tstTemplate[tstHeaderCount + 2].type = CKA_PRIME_1;
+
+ tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
+ tstHeaderCount +
+ 3,
+ PR_FALSE);
+ if (tstPrivKey == NULL) {
+ fprintf(stderr, "RSA Populate failed: pubExp mod q\n");
+ failed = 1;
+ } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
+ PK11_TypeGeneric, tstPrivKey)) {
+ fprintf(stderr, "RSA Populate key mismatch: pubExp mod q\n");
+ failed = 1;
+ }
+ if (tstPrivKey)
+ PK11_DestroyGenericObject(tstPrivKey);
+ }
+ if (mask & 4) {
+ printf("%s\n", test_array[3].description);
+ /* test the medium case, private exponent, prime1, prime2 */
+ resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
+
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount, CKA_PRIVATE_EXPONENT);
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount + 1, CKA_PRIME_1);
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount + 2, CKA_PRIME_2);
+ /* test with p & q swapped. Underlying code should swap these back */
+ tstTemplate[tstHeaderCount + 2].type = CKA_PRIME_1;
+ tstTemplate[tstHeaderCount + 1].type = CKA_PRIME_2;
+
+ tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
+ tstHeaderCount +
+ 3,
+ PR_FALSE);
+ if (tstPrivKey == NULL) {
+ fprintf(stderr, "RSA Populate failed: privExp p q\n");
+ failed = 1;
+ } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
+ PK11_TypeGeneric, tstPrivKey)) {
+ fprintf(stderr, "RSA Populate key mismatch: privExp p q\n");
+ failed = 1;
+ }
+ if (tstPrivKey)
+ PK11_DestroyGenericObject(tstPrivKey);
+ }
+ if (mask & 8) {
+ printf("%s\n", test_array[4].description);
+ /* test the advanced case, public exponent, private exponent, prime2 */
+ resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount, CKA_PRIVATE_EXPONENT);
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount + 1, CKA_PUBLIC_EXPONENT);
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount + 2, CKA_PRIME_2);
+
+ tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
+ tstHeaderCount +
+ 3,
+ PR_FALSE);
+ if (tstPrivKey == NULL) {
+ fprintf(stderr, "RSA Populate failed: pubExp privExp q\n");
+ fprintf(stderr, " this is expected periodically. It means we\n");
+ fprintf(stderr, " had more than one key that meets the "
+ "specification\n");
+ exp_exp_prime_fail_count++;
+ } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
+ PK11_TypeGeneric, tstPrivKey)) {
+ fprintf(stderr, "RSA Populate key mismatch: pubExp privExp q\n");
+ failed = 1;
+ }
+ if (tstPrivKey)
+ PK11_DestroyGenericObject(tstPrivKey);
+ }
+ if (mask & 16) {
+ printf("%s\n", test_array[5].description);
+ /* test the advanced case2, public exponent, private exponent, modulus
+ */
+ resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
+
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount, CKA_PRIVATE_EXPONENT);
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount + 1, CKA_PUBLIC_EXPONENT);
+ copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
+ tstHeaderCount + 2, CKA_MODULUS);
+
+ tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
+ tstHeaderCount +
+ 3,
+ PR_FALSE);
+ if (tstPrivKey == NULL) {
+ fprintf(stderr, "RSA Populate failed: pubExp privExp mod\n");
+ failed = 1;
+ } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
+ PK11_TypeGeneric, tstPrivKey)) {
+ fprintf(stderr, "RSA Populate key mismatch: pubExp privExp mod\n");
+ failed = 1;
+ }
+ if (tstPrivKey)
+ PK11_DestroyGenericObject(tstPrivKey);
+ }
+
+ PK11_FreeSlot(slot);
+ return failed ? -1 : 0;
+}
+
+/* populate options */
+enum {
+ opt_Exponent = 0,
+ opt_KeySize,
+ opt_Repeat,
+ opt_Tests
+};
+
+static secuCommandFlag populate_options[] =
+ {
+ { /* opt_Exponent */ 'e', PR_TRUE, 0, PR_FALSE },
+ { /* opt_KeySize */ 'k', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Repeat */ 'r', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Tests */ 't', PR_TRUE, 0, PR_FALSE },
+ };
+
+int
+is_delimiter(char c)
+{
+ if ((c == '+') || (c == ',') || (c == '|')) {
+ return 1;
+ }
+ return 0;
+}
+
+int
+parse_tests(char *test_string)
+{
+ int mask = 0;
+ int i;
+
+ while (*test_string) {
+ if (is_delimiter(*test_string)) {
+ test_string++;
+ }
+ for (i = 0; i < test_array_size; i++) {
+ char *arg = test_array[i].arg;
+ int len = strlen(arg);
+ if (strncmp(test_string, arg, len) == 0) {
+ test_string += len;
+ mask |= test_array[i].mask_value;
+ break;
+ }
+ }
+ if (i == test_array_size) {
+ break;
+ }
+ }
+ return mask;
+}
+
+int
+main(int argc, char **argv)
+{
+ unsigned int keySize = 1024;
+ unsigned long exponent = 65537;
+ int i, repeat = 1, ret = 0;
+ SECStatus rv = SECFailure;
+ secuCommand populateArgs;
+ char *progName;
+ int mask = 0xff;
+
+ populateArgs.numCommands = 0;
+ populateArgs.numOptions = sizeof(populate_options) /
+ sizeof(secuCommandFlag);
+ populateArgs.commands = NULL;
+ populateArgs.options = populate_options;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName + 1 : argv[0];
+
+ rv = NSS_NoDB_Init(NULL);
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &populateArgs);
+ if (rv == SECFailure) {
+ fprintf(stderr, "%s: command line parsing error!\n", progName);
+ Usage(progName);
+ return -1;
+ }
+ rv = SECFailure;
+
+ if (populateArgs.options[opt_KeySize].activated) {
+ keySize = PORT_Atoi(populateArgs.options[opt_KeySize].arg);
+ }
+ if (populateArgs.options[opt_Repeat].activated) {
+ repeat = PORT_Atoi(populateArgs.options[opt_Repeat].arg);
+ }
+ if (populateArgs.options[opt_Exponent].activated) {
+ exponent = PORT_Atoi(populateArgs.options[opt_Exponent].arg);
+ }
+ if (populateArgs.options[opt_Tests].activated) {
+ char *test_string = populateArgs.options[opt_Tests].arg;
+ mask = PORT_Atoi(test_string);
+ if (mask == 0) {
+ mask = parse_tests(test_string);
+ }
+ if (mask == 0) {
+ Usage(progName);
+ return -1;
+ }
+ }
+
+ exp_exp_prime_fail_count = 0;
+ for (i = 0; i < repeat; i++) {
+ printf("Running RSA Populate test run %d\n", i);
+ ret = doRSAPopulateTest(keySize, exponent, mask, NULL);
+ if (ret != 0) {
+ i++;
+ break;
+ }
+ }
+ if (ret != 0) {
+ fprintf(stderr, "RSA Populate test round %d: FAILED\n", i);
+ }
+ if (repeat > 1) {
+ printf(" pub priv prime test: %d failures out of %d runs (%f %%)\n",
+ exp_exp_prime_fail_count, i,
+ (((double)exp_exp_prime_fail_count) * 100.0) / (double)i);
+ }
+ return ret;
+}
diff --git a/security/nss/cmd/samples/cert b/security/nss/cmd/samples/cert
new file mode 100644
index 000000000..3f8ec48df
--- /dev/null
+++ b/security/nss/cmd/samples/cert
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIIB7TCCAVYCAgMaMA0GCSqGSIb3DQEBBAUAMEcxCzAJBgNVBAYTAlVTMRAwDgYD
+VQQLEwdUZXN0IENBMSYwJAYDVQQKEx1OZXRzY2FwZSBDb21tdW5pY2F0aW9ucyBD
+b3JwLjAeFw05NTEyMDgwMjQwMjdaFw05NjAzMDcwMjQwMjdaMDgxFjAUBgNVBAMT
+DURhdmlkIGthcmx0b24xETAPBgNVBAoTCE5ldHNjYXBlMQswCQYDVQQGEwJVUzCB
+nTANBgkqhkiG9w0BAQEFAAOBiwAwgYcCgYEAltV2TH+QxqlgfUFk+UyiYAjByxrC
+dCSIa/FwRaPceLvE7ycD9L6AC4JA6k58E6ICsr/Y8TsXT4UmZhhLNc50VgSo8cGQ
+lajqIDvntq8M1uCXiVOnXmIAqoB6E8GiqW+9evOkgkumMksSwXiXAhMM7vJt3IU6
+b+FwdF5cRs0u1FUCAQMwDQYJKoZIhvcNAQEEBQADgYEAkFdr3ypcvI2+Xgwfp7+d
+YtN7w4UnQ7LR9FKmlnBauTVLmUtichn/O3WMT9cYTtZm5QQVRaE3qrGh0Nr6Ko1E
+nIHowd36TN45zkFraWoATfCV/f+P37WaADp20l2ryEY0Jpe4gnoeZ0+/ffoxyajC
+LZEJL6Dv2Ed83cebLjYxKsI=
+
+-----END CERTIFICATE-----
+
diff --git a/security/nss/cmd/samples/cert0 b/security/nss/cmd/samples/cert0
new file mode 100644
index 000000000..05cdc8553
--- /dev/null
+++ b/security/nss/cmd/samples/cert0
Binary files differ
diff --git a/security/nss/cmd/samples/cert1 b/security/nss/cmd/samples/cert1
new file mode 100644
index 000000000..38a7d299a
--- /dev/null
+++ b/security/nss/cmd/samples/cert1
Binary files differ
diff --git a/security/nss/cmd/samples/cert2 b/security/nss/cmd/samples/cert2
new file mode 100644
index 000000000..147c3eb9e
--- /dev/null
+++ b/security/nss/cmd/samples/cert2
Binary files differ
diff --git a/security/nss/cmd/samples/pkcs7.ber b/security/nss/cmd/samples/pkcs7.ber
new file mode 100644
index 000000000..6e3814c37
--- /dev/null
+++ b/security/nss/cmd/samples/pkcs7.ber
Binary files differ
diff --git a/security/nss/cmd/samples/pkcs7bday.ber b/security/nss/cmd/samples/pkcs7bday.ber
new file mode 100644
index 000000000..0ee6cfc13
--- /dev/null
+++ b/security/nss/cmd/samples/pkcs7bday.ber
Binary files differ
diff --git a/security/nss/cmd/samples/pkcs7cnet.ber b/security/nss/cmd/samples/pkcs7cnet.ber
new file mode 100644
index 000000000..df2bb2dd1
--- /dev/null
+++ b/security/nss/cmd/samples/pkcs7cnet.ber
Binary files differ
diff --git a/security/nss/cmd/samples/pkcs7news.ber b/security/nss/cmd/samples/pkcs7news.ber
new file mode 100644
index 000000000..c46a1786d
--- /dev/null
+++ b/security/nss/cmd/samples/pkcs7news.ber
Binary files differ
diff --git a/security/nss/cmd/samples/x509v3.der b/security/nss/cmd/samples/x509v3.der
new file mode 100644
index 000000000..1ada57c56
--- /dev/null
+++ b/security/nss/cmd/samples/x509v3.der
Binary files differ
diff --git a/security/nss/cmd/samples/x509v3.txt b/security/nss/cmd/samples/x509v3.txt
new file mode 100644
index 000000000..dde307697
--- /dev/null
+++ b/security/nss/cmd/samples/x509v3.txt
@@ -0,0 +1,10 @@
+MIIByzCCAXWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBLMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNVmVyaVNpZ24gSW5jLjEUMBIGA1UECxMLRW5naW5lZXJpbmcxDjAM
+BgNVBAMTBUphc29uMB4XDTk1MDgwODA3MDAwMFoXDTk2MDgwNzA3MDAwMFowSzEL
+MAkGA1UEBhMCVVMxFjAUBgNVBAoTDVZlcmlTaWduIEluYy4xFDASBgNVBAsTC0Vu
+Z2luZWVyaW5nMQ4wDAYDVQQDEwVKYXNvbjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgC
+QQCvpXRU9t3NPFXvxJz2vuxX4zI55AA+xY1PsAEadhwWEMF2EnpG8woF4EGTwLdx
+xrw3Eirzu5RAAhqegCN1aPVBAgMBAAGjRDBCMBQGA2FiYwEB/wQKZXh0ZW5zaW9u
+MTAUBgNkZWYBAf8ECmV4dGVuc2lvbjIwFAYDZ2hpAQH/BApleHRlbnNpb24zMA0G
+CSqGSIb3DQEBBAUAA0EAawLNWFSYMtywAqkSYJb1gejljqi9QAtLZIM2ui+RCTP2
+jEjW5bp4oU1RX2iBSfU+MdEZx9DpMNjqBLrgOy1Djw==
diff --git a/security/nss/cmd/sdrtest/Makefile b/security/nss/cmd/sdrtest/Makefile
new file mode 100644
index 000000000..265ea5601
--- /dev/null
+++ b/security/nss/cmd/sdrtest/Makefile
@@ -0,0 +1,45 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
diff --git a/security/nss/cmd/sdrtest/manifest.mn b/security/nss/cmd/sdrtest/manifest.mn
new file mode 100644
index 000000000..d0c67450f
--- /dev/null
+++ b/security/nss/cmd/sdrtest/manifest.mn
@@ -0,0 +1,26 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ sdrtest.c \
+ $(NULL)
+
+# headers for the MODULE (defined above) are implicitly required.
+REQUIRES = dbm seccmd
+
+# WINNT uses EXTRA_LIBS as the list of libs to link in.
+# Unix uses OS_LIBS for that purpose.
+# We can solve this via conditional makefile code, but
+# can't do this in manifest.mn because OS_ARCH isn't defined there.
+# So, look in the local Makefile for the defines for the list of libs.
+
+PROGRAM = sdrtest
+
+#USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/sdrtest/sdrtest.c b/security/nss/cmd/sdrtest/sdrtest.c
new file mode 100644
index 000000000..651c63b24
--- /dev/null
+++ b/security/nss/cmd/sdrtest/sdrtest.c
@@ -0,0 +1,427 @@
+/* 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/. */
+
+/*
+ * Test program for SDR (Secret Decoder Ring) functions.
+ */
+
+#include "nspr.h"
+#include "string.h"
+#include "nss.h"
+#include "secutil.h"
+#include "cert.h"
+#include "pk11func.h"
+
+#include "plgetopt.h"
+#include "pk11sdr.h"
+#include "nssb64.h"
+
+#define DEFAULT_VALUE "Test"
+static const char default_value[] = { DEFAULT_VALUE };
+
+PRFileDesc *pr_stderr;
+PRBool verbose = PR_FALSE;
+
+static void
+synopsis(char *program_name)
+{
+ PR_fprintf(pr_stderr,
+ "Usage: %s [<common>] -i <input-file>\n"
+ " %s [<common>] -o <output-file>\n"
+ " <common> [-d dir] [-v] [-t text] [-a] [-f pwfile | -p pwd]\n",
+ program_name, program_name);
+}
+
+static void
+short_usage(char *program_name)
+{
+ PR_fprintf(pr_stderr,
+ "Type %s -H for more detailed descriptions\n",
+ program_name);
+ synopsis(program_name);
+}
+
+static void
+long_usage(char *program_name)
+{
+ synopsis(program_name);
+ PR_fprintf(pr_stderr, "\nSecret Decoder Test:\n");
+ PR_fprintf(pr_stderr,
+ " %-13s Read encrypted data from \"file\"\n",
+ "-i file");
+ PR_fprintf(pr_stderr,
+ " %-13s Write newly generated encrypted data to \"file\"\n",
+ "-o file");
+ PR_fprintf(pr_stderr,
+ " %-13s Use \"text\" as the plaintext for encryption and verification\n",
+ "-t text");
+ PR_fprintf(pr_stderr,
+ " %-13s Find security databases in \"dbdir\"\n",
+ "-d dbdir");
+ PR_fprintf(pr_stderr,
+ " %-13s read the password from \"pwfile\"\n",
+ "-f pwfile");
+ PR_fprintf(pr_stderr,
+ " %-13s supply \"password\" on the command line\n",
+ "-p password");
+}
+
+int
+readStdin(SECItem *result)
+{
+ unsigned int bufsize = 0;
+ int cc;
+ unsigned int wanted = 8192U;
+
+ result->len = 0;
+ result->data = NULL;
+ do {
+ if (bufsize < wanted) {
+ unsigned char *tmpData = (unsigned char *)PR_Realloc(result->data, wanted);
+ if (!tmpData) {
+ if (verbose)
+ PR_fprintf(pr_stderr, "Allocation of buffer failed\n");
+ return -1;
+ }
+ result->data = tmpData;
+ bufsize = wanted;
+ }
+ cc = PR_Read(PR_STDIN, result->data + result->len, bufsize - result->len);
+ if (cc > 0) {
+ result->len += (unsigned)cc;
+ if (result->len >= wanted)
+ wanted *= 2;
+ }
+ } while (cc > 0);
+ return cc;
+}
+
+int
+readInputFile(const char *filename, SECItem *result)
+{
+ PRFileDesc *file /* = PR_OpenFile(input_file, 0) */;
+ PRFileInfo info;
+ PRStatus s;
+ PRInt32 count;
+ int retval = -1;
+
+ file = PR_Open(filename, PR_RDONLY, 0);
+ if (!file) {
+ if (verbose)
+ PR_fprintf(pr_stderr, "Open of file %s failed\n", filename);
+ goto loser;
+ }
+
+ s = PR_GetOpenFileInfo(file, &info);
+ if (s != PR_SUCCESS) {
+ if (verbose)
+ PR_fprintf(pr_stderr, "File info operation failed\n");
+ goto file_loser;
+ }
+
+ result->len = info.size;
+ result->data = (unsigned char *)PR_Malloc(result->len);
+ if (!result->data) {
+ if (verbose)
+ PR_fprintf(pr_stderr, "Allocation of buffer failed\n");
+ goto file_loser;
+ }
+
+ count = PR_Read(file, result->data, result->len);
+ if (count != result->len) {
+ if (verbose)
+ PR_fprintf(pr_stderr, "Read failed\n");
+ goto file_loser;
+ }
+ retval = 0;
+
+file_loser:
+ PR_Close(file);
+loser:
+ return retval;
+}
+
+int
+main(int argc, char **argv)
+{
+ int retval = 0; /* 0 - test succeeded. -1 - test failed */
+ SECStatus rv;
+ PLOptState *optstate;
+ PLOptStatus optstatus;
+ char *program_name;
+ const char *input_file = NULL; /* read encrypted data from here (or create) */
+ const char *output_file = NULL; /* write new encrypted data here */
+ const char *value = default_value; /* Use this for plaintext */
+ SECItem data;
+ SECItem result = { 0, 0, 0 };
+ SECItem text;
+ PRBool ascii = PR_FALSE;
+ secuPWData pwdata = { PW_NONE, 0 };
+
+ pr_stderr = PR_STDERR;
+ result.data = 0;
+ text.data = 0;
+ text.len = 0;
+
+ program_name = PL_strrchr(argv[0], '/');
+ program_name = program_name ? (program_name + 1) : argv[0];
+
+ optstate = PL_CreateOptState(argc, argv, "?Had:i:o:t:vf:p:");
+ if (optstate == NULL) {
+ SECU_PrintError(program_name, "PL_CreateOptState failed");
+ return -1;
+ }
+
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ short_usage(program_name);
+ return retval;
+
+ case 'H':
+ long_usage(program_name);
+ return retval;
+
+ case 'a':
+ ascii = PR_TRUE;
+ break;
+
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'i':
+ input_file = optstate->value;
+ break;
+
+ case 'o':
+ output_file = optstate->value;
+ break;
+
+ case 't':
+ value = optstate->value;
+ break;
+
+ case 'f':
+ if (pwdata.data) {
+ PORT_Free(pwdata.data);
+ short_usage(program_name);
+ return -1;
+ }
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
+
+ case 'p':
+ if (pwdata.data) {
+ PORT_Free(pwdata.data);
+ short_usage(program_name);
+ return -1;
+ }
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
+
+ case 'v':
+ verbose = PR_TRUE;
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+ if (optstatus == PL_OPT_BAD) {
+ short_usage(program_name);
+ return -1;
+ }
+ if (!output_file && !input_file && value == default_value) {
+ short_usage(program_name);
+ PR_fprintf(pr_stderr, "Must specify at least one of -t, -i or -o \n");
+ return -1;
+ }
+
+ /*
+ * Initialize the Security libraries.
+ */
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ if (output_file) {
+ rv = NSS_InitReadWrite(SECU_ConfigDirectory(NULL));
+ } else {
+ rv = NSS_Init(SECU_ConfigDirectory(NULL));
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintError(program_name, "NSS_Init failed");
+ retval = -1;
+ goto prdone;
+ }
+
+ /* Convert value into an item */
+ data.data = (unsigned char *)value;
+ data.len = strlen(value);
+
+ /* Get the encrypted result, either from the input file
+ * or from encrypting the plaintext value
+ */
+ if (input_file) {
+ if (verbose)
+ printf("Reading data from %s\n", input_file);
+
+ if (!strcmp(input_file, "-")) {
+ retval = readStdin(&result);
+ ascii = PR_TRUE;
+ } else {
+ retval = readInputFile(input_file, &result);
+ }
+ if (retval != 0)
+ goto loser;
+ if (ascii) {
+ /* input was base64 encoded. Decode it. */
+ SECItem newResult = { 0, 0, 0 };
+ SECItem *ok = NSSBase64_DecodeBuffer(NULL, &newResult,
+ (const char *)result.data, result.len);
+ if (!ok) {
+ SECU_PrintError(program_name, "Base 64 decode failed");
+ retval = -1;
+ goto loser;
+ }
+ SECITEM_ZfreeItem(&result, PR_FALSE);
+ result = *ok;
+ }
+ } else {
+ SECItem keyid = { 0, 0, 0 };
+ SECItem outBuf = { 0, 0, 0 };
+ PK11SlotInfo *slot = NULL;
+
+ /* sigh, initialize the key database */
+ slot = PK11_GetInternalKeySlot();
+ if (slot && PK11_NeedUserInit(slot)) {
+ switch (pwdata.source) {
+ case PW_FROMFILE:
+ rv = SECU_ChangePW(slot, 0, pwdata.data);
+ break;
+ case PW_PLAINTEXT:
+ rv = SECU_ChangePW(slot, pwdata.data, 0);
+ break;
+ default:
+ rv = SECU_ChangePW(slot, "", 0);
+ break;
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintError(program_name, "Failed to initialize slot \"%s\"",
+ PK11_GetSlotName(slot));
+ return SECFailure;
+ }
+ }
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+
+ rv = PK11SDR_Encrypt(&keyid, &data, &result, &pwdata);
+ if (rv != SECSuccess) {
+ if (verbose)
+ SECU_PrintError(program_name, "Encrypt operation failed\n");
+ retval = -1;
+ goto loser;
+ }
+
+ if (verbose)
+ printf("Encrypted result is %d bytes long\n", result.len);
+
+ if (!strcmp(output_file, "-")) {
+ ascii = PR_TRUE;
+ }
+
+ if (ascii) {
+ /* base64 encode output. */
+ char *newResult = NSSBase64_EncodeItem(NULL, NULL, 0, &result);
+ if (!newResult) {
+ SECU_PrintError(program_name, "Base 64 encode failed\n");
+ retval = -1;
+ goto loser;
+ }
+ outBuf.data = (unsigned char *)newResult;
+ outBuf.len = strlen(newResult);
+ if (verbose)
+ printf("Base 64 encoded result is %d bytes long\n", outBuf.len);
+ } else {
+ outBuf = result;
+ }
+
+ /* -v printf("Result is %.*s\n", text.len, text.data); */
+ if (output_file) {
+ PRFileDesc *file;
+ PRInt32 count;
+
+ if (verbose)
+ printf("Writing result to %s\n", output_file);
+ if (!strcmp(output_file, "-")) {
+ file = PR_STDOUT;
+ } else {
+ /* Write to file */
+ file = PR_Open(output_file, PR_CREATE_FILE | PR_WRONLY, 0666);
+ }
+ if (!file) {
+ if (verbose)
+ SECU_PrintError(program_name,
+ "Open of output file %s failed\n",
+ output_file);
+ retval = -1;
+ goto loser;
+ }
+
+ count = PR_Write(file, outBuf.data, outBuf.len);
+
+ if (file == PR_STDOUT) {
+ puts("");
+ } else {
+ PR_Close(file);
+ }
+
+ if (count != outBuf.len) {
+ if (verbose)
+ SECU_PrintError(program_name, "Write failed\n");
+ retval = -1;
+ goto loser;
+ }
+ if (ascii) {
+ free(outBuf.data);
+ }
+ }
+ }
+
+ /* Decrypt the value */
+ rv = PK11SDR_Decrypt(&result, &text, &pwdata);
+ if (rv != SECSuccess) {
+ if (verbose)
+ SECU_PrintError(program_name, "Decrypt operation failed\n");
+ retval = -1;
+ goto loser;
+ }
+
+ if (verbose)
+ printf("Decrypted result is \"%.*s\"\n", text.len, text.data);
+
+ /* Compare to required value */
+ if (text.len != data.len || memcmp(data.data, text.data, text.len) != 0) {
+ if (verbose)
+ PR_fprintf(pr_stderr, "Comparison failed\n");
+ retval = -1;
+ goto loser;
+ }
+
+loser:
+ if (text.data)
+ SECITEM_ZfreeItem(&text, PR_FALSE);
+ if (result.data)
+ SECITEM_ZfreeItem(&result, PR_FALSE);
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+prdone:
+ PR_Cleanup();
+ if (pwdata.data) {
+ PORT_Free(pwdata.data);
+ }
+ return retval;
+}
diff --git a/security/nss/cmd/sdrtest/sdrtest.gyp b/security/nss/cmd/sdrtest/sdrtest.gyp
new file mode 100644
index 000000000..c544e17d8
--- /dev/null
+++ b/security/nss/cmd/sdrtest/sdrtest.gyp
@@ -0,0 +1,25 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'sdrtest',
+ 'type': 'executable',
+ 'sources': [
+ 'sdrtest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/selfserv/Makefile b/security/nss/cmd/selfserv/Makefile
new file mode 100644
index 000000000..7b74b369c
--- /dev/null
+++ b/security/nss/cmd/selfserv/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/selfserv/manifest.mn b/security/nss/cmd/selfserv/manifest.mn
new file mode 100644
index 000000000..a170169c8
--- /dev/null
+++ b/security/nss/cmd/selfserv/manifest.mn
@@ -0,0 +1,20 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = selfserv.c
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+PROGRAM = selfserv
+
diff --git a/security/nss/cmd/selfserv/selfserv.c b/security/nss/cmd/selfserv/selfserv.c
new file mode 100644
index 000000000..f34af7d74
--- /dev/null
+++ b/security/nss/cmd/selfserv/selfserv.c
@@ -0,0 +1,2781 @@
+/* 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/. */
+
+/* -r flag is interepreted as follows:
+ * 1 -r means request, not require, on initial handshake.
+ * 2 -r's mean request and require, on initial handshake.
+ * 3 -r's mean request, not require, on second handshake.
+ * 4 -r's mean request and require, on second handshake.
+ */
+#include <stdio.h>
+#include <string.h>
+
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#if defined(_WINDOWS)
+#include <process.h> /* for getpid() */
+#endif
+
+#include <signal.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "nspr.h"
+#include "prio.h"
+#include "prerror.h"
+#include "prnetdb.h"
+#include "prclist.h"
+#include "plgetopt.h"
+#include "pk11func.h"
+#include "secitem.h"
+#include "nss.h"
+#include "ssl.h"
+#include "sslproto.h"
+#include "cert.h"
+#include "certt.h"
+#include "ocsp.h"
+
+#ifndef PORT_Sprintf
+#define PORT_Sprintf sprintf
+#endif
+
+#ifndef PORT_Strstr
+#define PORT_Strstr strstr
+#endif
+
+#ifndef PORT_Malloc
+#define PORT_Malloc PR_Malloc
+#endif
+
+int NumSidCacheEntries = 1024;
+
+static int handle_connection(PRFileDesc *, PRFileDesc *, int);
+
+static const char envVarName[] = { SSL_ENV_VAR_NAME };
+static const char inheritableSockName[] = { "SELFSERV_LISTEN_SOCKET" };
+
+#define MAX_VIRT_SERVER_NAME_ARRAY_INDEX 10
+#define MAX_CERT_NICKNAME_ARRAY_INDEX 10
+
+#define DEFAULT_BULK_TEST 16384
+#define MAX_BULK_TEST 1048576 /* 1 MB */
+static PRBool testBulk;
+static PRUint32 testBulkSize = DEFAULT_BULK_TEST;
+static PRInt32 testBulkTotal;
+static char *testBulkBuf;
+static PRDescIdentity log_layer_id = PR_INVALID_IO_LAYER;
+static PRFileDesc *loggingFD;
+static PRIOMethods loggingMethods;
+
+static PRBool logStats;
+static PRBool loggingLayer;
+static int logPeriod = 30;
+static PRInt32 loggerOps;
+static PRInt32 loggerBytes;
+static PRInt32 loggerBytesTCP;
+static PRInt32 bulkSentChunks;
+static enum ocspStaplingModeEnum {
+ osm_disabled, /* server doesn't support stapling */
+ osm_good, /* supply a signed good status */
+ osm_revoked, /* supply a signed revoked status */
+ osm_unknown, /* supply a signed unknown status */
+ osm_failure, /* supply a unsigned failure status, "try later" */
+ osm_badsig, /* supply a good status response with a bad signature */
+ osm_corrupted, /* supply a corrupted data block as the status */
+ osm_random, /* use a random response for each connection */
+ osm_ocsp /* retrieve ocsp status from external ocsp server,
+ use empty status if server is unavailable */
+} ocspStaplingMode = osm_disabled;
+typedef enum ocspStaplingModeEnum ocspStaplingModeType;
+static char *ocspStaplingCA = NULL;
+static SECItemArray *certStatus[MAX_CERT_NICKNAME_ARRAY_INDEX] = { NULL };
+
+const int ssl3CipherSuites[] = {
+ -1, /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
+ -1, /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA * b */
+ TLS_RSA_WITH_RC4_128_MD5, /* c */
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
+ TLS_RSA_WITH_DES_CBC_SHA, /* e */
+ -1, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 * f */
+ -1, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 * g */
+ -1, /* SSL_FORTEZZA_DMS_WITH_NULL_SHA * h */
+ TLS_RSA_WITH_NULL_MD5, /* i */
+ -1, /* SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA * j */
+ -1, /* SSL_RSA_FIPS_WITH_DES_CBC_SHA * k */
+ -1, /* TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA * l */
+ -1, /* TLS_RSA_EXPORT1024_WITH_RC4_56_SHA * m */
+ TLS_RSA_WITH_RC4_128_SHA, /* n */
+ TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */
+ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
+ TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
+ TLS_DHE_RSA_WITH_DES_CBC_SHA, /* r */
+ TLS_DHE_DSS_WITH_DES_CBC_SHA, /* s */
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* t */
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* u */
+ TLS_RSA_WITH_AES_128_CBC_SHA, /* v */
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* w */
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* x */
+ TLS_RSA_WITH_AES_256_CBC_SHA, /* y */
+ TLS_RSA_WITH_NULL_SHA, /* z */
+ 0
+};
+
+/* data and structures for shutdown */
+static int stopping;
+
+static PRBool noDelay;
+static int requestCert;
+static int verbose;
+static SECItem bigBuf;
+static int configureDHE = -1; /* -1: don't configure, 0 disable, >=1 enable*/
+static int configureReuseECDHE = -1; /* -1: don't configure, 0 refresh, >=1 reuse*/
+static int configureWeakDHE = -1; /* -1: don't configure, 0 disable, >=1 enable*/
+
+static PRThread *acceptorThread;
+
+static PRLogModuleInfo *lm;
+
+#define PRINTF \
+ if (verbose) \
+ printf
+#define FPRINTF \
+ if (verbose) \
+ fprintf
+#define FLUSH \
+ if (verbose) { \
+ fflush(stdout); \
+ fflush(stderr); \
+ }
+#define VLOG(arg) PR_LOG(lm, PR_LOG_DEBUG, arg)
+
+static void
+PrintUsageHeader(const char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s -n rsa_nickname -p port [-BDENRbjlmrsuvx] [-w password]\n"
+ " [-t threads] [-i pid_file] [-c ciphers] [-Y] [-d dbdir] [-g numblocks]\n"
+ " [-f password_file] [-L [seconds]] [-M maxProcs] [-P dbprefix]\n"
+ " [-V [min-version]:[max-version]] [-a sni_name]\n"
+ " [ T <good|revoked|unknown|badsig|corrupted|none|ocsp>] [-A ca]\n"
+ " [-C SSLCacheEntries] [-S dsa_nickname] -Q [-I groups]"
+#ifndef NSS_DISABLE_ECC
+ " [-e ec_nickname]"
+#endif /* NSS_DISABLE_ECC */
+ "\n"
+ " -U [0|1] -H [0|1|2] -W [0|1]\n",
+ progName);
+}
+
+static void
+PrintParameterUsage()
+{
+ fputs(
+ "-V [min]:[max] restricts the set of enabled SSL/TLS protocol versions.\n"
+ " All versions are enabled by default.\n"
+ " Possible values for min/max: ssl3 tls1.0 tls1.1 tls1.2\n"
+ " Example: \"-V ssl3:\" enables SSL 3 and newer.\n"
+ "-D means disable Nagle delays in TCP\n"
+ "-R means disable detection of rollback from TLS to SSL3\n"
+ "-a configure server for SNI.\n"
+ "-k expected name negotiated on server sockets\n"
+ "-b means try binding to the port and exit\n"
+ "-m means test the model-socket feature of SSL_ImportFD.\n"
+ "-r flag is interepreted as follows:\n"
+ " 1 -r means request, not require, cert on initial handshake.\n"
+ " 2 -r's mean request and require, cert on initial handshake.\n"
+ " 3 -r's mean request, not require, cert on second handshake.\n"
+ " 4 -r's mean request and require, cert on second handshake.\n"
+ "-s means disable SSL socket locking for performance\n"
+ "-u means enable Session Ticket extension for TLS.\n"
+ "-v means verbose output\n"
+ "-z means enable compression.\n"
+ "-L seconds means log statistics every 'seconds' seconds (default=30).\n"
+ "-M maxProcs tells how many processes to run in a multi-process server\n"
+ "-N means do NOT use the server session cache. Incompatible with -M.\n"
+ "-t threads -- specify the number of threads to use for connections.\n"
+ "-i pid_file file to write the process id of selfserve\n"
+ "-l means use local threads instead of global threads\n"
+ "-g numblocks means test throughput by sending total numblocks chunks\n"
+ " of size 16kb to the client, 0 means unlimited (default=0)\n"
+ "-j means measure TCP throughput (for use with -g option)\n"
+ "-C SSLCacheEntries sets the maximum number of entries in the SSL\n"
+ " session cache\n"
+ "-T <mode> enable OCSP stapling. Possible modes:\n"
+ " none: don't send cert status (default)\n"
+ " good, revoked, unknown: Include locally signed response. Requires: -A\n"
+ " failure: return a failure response (try later, unsigned)\n"
+ " badsig: use a good status but with an invalid signature\n"
+ " corrupted: stapled cert status is an invalid block of data\n"
+ " random: each connection uses a random status from this list:\n"
+ " good, revoked, unknown, failure, badsig, corrupted\n"
+ " ocsp: fetch from external OCSP server using AIA, or none\n"
+ "-A <ca> Nickname of a CA used to sign a stapled cert status\n"
+ "-U override default ECDHE ephemeral key reuse, 0: refresh, 1: reuse\n"
+ "-H override default DHE server support, 0: disable, 1: enable, "
+ " 2: require DH named groups\n"
+ "-W override default DHE server weak parameters support, 0: disable, 1: enable\n"
+ "-c Restrict ciphers\n"
+ "-Y prints cipher values allowed for parameter -c and exits\n"
+ "-G enables the extended master secret extension [RFC7627]\n"
+ "-Q enables ALPN for HTTP/1.1 [RFC7301]\n"
+ "-I comma separated list of enabled groups for TLS key exchange.\n"
+ " The following values are valid:\n"
+ " P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192\n",
+ stderr);
+}
+
+static void
+Usage(const char *progName)
+{
+ PrintUsageHeader(progName);
+ PrintParameterUsage();
+}
+
+static void
+PrintCipherUsage(const char *progName)
+{
+ PrintUsageHeader(progName);
+ fputs(
+ "-c ciphers Letter(s) chosen from the following list\n"
+ "c SSL3 RSA WITH RC4 128 MD5\n"
+ "d SSL3 RSA WITH 3DES EDE CBC SHA\n"
+ "e SSL3 RSA WITH DES CBC SHA\n"
+ "f SSL3 RSA EXPORT WITH RC4 40 MD5\n"
+ "g SSL3 RSA EXPORT WITH RC2 CBC 40 MD5\n"
+ "i SSL3 RSA WITH NULL MD5\n"
+ "j SSL3 RSA FIPS WITH 3DES EDE CBC SHA\n"
+ "k SSL3 RSA FIPS WITH DES CBC SHA\n"
+ "l SSL3 RSA EXPORT WITH DES CBC SHA\t(new)\n"
+ "m SSL3 RSA EXPORT WITH RC4 56 SHA\t(new)\n"
+ "n SSL3 RSA WITH RC4 128 SHA\n"
+ "o TLS_DHE_DSS_WITH_RC4_128_SHA\n"
+ "p TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA\n"
+ "q TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA\n"
+ "r TLS_DHE_RSA_WITH_DES_CBC_SHA\n"
+ "s TLS_DHE_DSS_WITH_DES_CBC_SHA\n"
+ "t TLS_DHE_DSS_WITH_AES_128_CBC_SHA\n"
+ "u TLS_DHE_RSA_WITH_AES_128_CBC_SHA\n"
+ "v SSL3 RSA WITH AES 128 CBC SHA\n"
+ "w TLS_DHE_DSS_WITH_AES_256_CBC_SHA\n"
+ "x TLS_DHE_RSA_WITH_AES_256_CBC_SHA\n"
+ "y SSL3 RSA WITH AES 256 CBC SHA\n"
+ "z SSL3 RSA WITH NULL SHA\n"
+ "\n"
+ ":WXYZ Use cipher with hex code { 0xWX , 0xYZ } in TLS\n",
+ stderr);
+}
+
+static const char *
+errWarn(char *funcString)
+{
+ PRErrorCode perr = PR_GetError();
+ const char *errString = SECU_Strerror(perr);
+
+ fprintf(stderr, "selfserv: %s returned error %d:\n%s\n",
+ funcString, perr, errString);
+ return errString;
+}
+
+static void
+errExit(char *funcString)
+{
+ errWarn(funcString);
+ exit(3);
+}
+
+/**************************************************************************
+**
+** Routines for disabling SSL ciphers.
+**
+**************************************************************************/
+
+/* disable all the SSL cipher suites */
+void
+disableAllSSLCiphers(void)
+{
+ const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
+ int i = SSL_NumImplementedCiphers;
+ SECStatus rv;
+
+ while (--i >= 0) {
+ PRUint16 suite = cipherSuites[i];
+ rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
+ if (rv != SECSuccess) {
+ printf("SSL_CipherPrefSetDefault rejected suite 0x%04x (i = %d)\n",
+ suite, i);
+ errWarn("SSL_CipherPrefSetDefault");
+ }
+ }
+}
+
+static SECStatus
+mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
+ PRBool isServer)
+{
+ SECStatus rv;
+ CERTCertificate *peerCert;
+
+ peerCert = SSL_PeerCertificate(fd);
+
+ if (peerCert) {
+ PRINTF("selfserv: Subject: %s\nselfserv: Issuer : %s\n",
+ peerCert->subjectName, peerCert->issuerName);
+ CERT_DestroyCertificate(peerCert);
+ }
+
+ rv = SSL_AuthCertificate(arg, fd, checkSig, isServer);
+
+ if (rv == SECSuccess) {
+ PRINTF("selfserv: -- SSL3: Certificate Validated.\n");
+ } else {
+ int err = PR_GetError();
+ FPRINTF(stderr, "selfserv: -- SSL3: Certificate Invalid, err %d.\n%s\n",
+ err, SECU_Strerror(err));
+ }
+ FLUSH;
+ return rv;
+}
+
+void
+printSSLStatistics()
+{
+ SSL3Statistics *ssl3stats = SSL_GetStatistics();
+
+ printf(
+ "selfserv: %ld cache hits; %ld cache misses, %ld cache not reusable\n"
+ " %ld stateless resumes, %ld ticket parse failures\n",
+ ssl3stats->hch_sid_cache_hits, ssl3stats->hch_sid_cache_misses,
+ ssl3stats->hch_sid_cache_not_ok, ssl3stats->hch_sid_stateless_resumes,
+ ssl3stats->hch_sid_ticket_parse_failures);
+}
+
+void
+printSecurityInfo(PRFileDesc *fd)
+{
+ CERTCertificate *cert = NULL;
+ SECStatus result;
+ SSLChannelInfo channel;
+ SSLCipherSuiteInfo suite;
+
+ if (verbose)
+ printSSLStatistics();
+
+ result = SSL_GetChannelInfo(fd, &channel, sizeof channel);
+ if (result == SECSuccess &&
+ channel.length == sizeof channel &&
+ channel.cipherSuite) {
+ result = SSL_GetCipherSuiteInfo(channel.cipherSuite,
+ &suite, sizeof suite);
+ if (result == SECSuccess) {
+ FPRINTF(stderr,
+ "selfserv: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
+ channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
+ suite.effectiveKeyBits, suite.symCipherName,
+ suite.macBits, suite.macAlgorithmName);
+ FPRINTF(stderr,
+ "selfserv: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n"
+ " Compression: %s, Extended Master Secret: %s\n",
+ channel.authKeyBits, suite.authAlgorithmName,
+ channel.keaKeyBits, suite.keaTypeName,
+ channel.compressionMethodName,
+ channel.extendedMasterSecretUsed ? "Yes" : "No");
+ }
+ }
+ if (verbose) {
+ SECItem *hostInfo = SSL_GetNegotiatedHostInfo(fd);
+ if (hostInfo) {
+ char namePref[] = "selfserv: Negotiated server name: ";
+
+ fprintf(stderr, "%s", namePref);
+ fwrite(hostInfo->data, hostInfo->len, 1, stderr);
+ SECITEM_FreeItem(hostInfo, PR_TRUE);
+ hostInfo = NULL;
+ fprintf(stderr, "\n");
+ }
+ }
+ if (requestCert)
+ cert = SSL_PeerCertificate(fd);
+ else
+ cert = SSL_LocalCertificate(fd);
+ if (cert) {
+ char *ip = CERT_NameToAscii(&cert->issuer);
+ char *sp = CERT_NameToAscii(&cert->subject);
+ if (sp) {
+ FPRINTF(stderr, "selfserv: subject DN: %s\n", sp);
+ PORT_Free(sp);
+ }
+ if (ip) {
+ FPRINTF(stderr, "selfserv: issuer DN: %s\n", ip);
+ PORT_Free(ip);
+ }
+ CERT_DestroyCertificate(cert);
+ cert = NULL;
+ }
+ FLUSH;
+}
+
+static int MakeCertOK;
+
+static SECStatus
+myBadCertHandler(void *arg, PRFileDesc *fd)
+{
+ int err = PR_GetError();
+ if (!MakeCertOK)
+ fprintf(stderr,
+ "selfserv: -- SSL: Client Certificate Invalid, err %d.\n%s\n",
+ err, SECU_Strerror(err));
+ return (MakeCertOK ? SECSuccess : SECFailure);
+}
+
+/* Simple SNI socket config function that does not use SSL_ReconfigFD.
+ * Only uses one server name but verifies that the names match. */
+PRInt32
+mySSLSNISocketConfig(PRFileDesc *fd, const SECItem *sniNameArr,
+ PRUint32 sniNameArrSize, void *arg)
+{
+ PRInt32 i = 0;
+ const SECItem *current = sniNameArr;
+ const char **nameArr = (const char **)arg;
+ secuPWData *pwdata;
+ CERTCertificate *cert = NULL;
+ SECKEYPrivateKey *privKey = NULL;
+
+ PORT_Assert(fd && sniNameArr);
+ if (!fd || !sniNameArr) {
+ return SSL_SNI_SEND_ALERT;
+ }
+
+ pwdata = SSL_RevealPinArg(fd);
+
+ for (; current && (PRUint32)i < sniNameArrSize; i++) {
+ unsigned int j = 0;
+ for (; j < MAX_VIRT_SERVER_NAME_ARRAY_INDEX && nameArr[j]; j++) {
+ if (!PORT_Strncmp(nameArr[j],
+ (const char *)current[i].data,
+ current[i].len) &&
+ PORT_Strlen(nameArr[j]) == current[i].len) {
+ const char *nickName = nameArr[j];
+ if (j == 0) {
+ /* default cert */
+ return 0;
+ }
+ /* if pwdata is NULL, then we would not get the key and
+ * return an error status. */
+ cert = PK11_FindCertFromNickname(nickName, &pwdata);
+ if (cert == NULL) {
+ goto loser; /* Send alert */
+ }
+ privKey = PK11_FindKeyByAnyCert(cert, &pwdata);
+ if (privKey == NULL) {
+ goto loser; /* Send alert */
+ }
+ if (SSL_ConfigServerCert(fd, cert, privKey, NULL, 0) != SECSuccess) {
+ goto loser; /* Send alert */
+ }
+ SECKEY_DestroyPrivateKey(privKey);
+ CERT_DestroyCertificate(cert);
+ return i;
+ }
+ }
+ }
+loser:
+ if (privKey) {
+ SECKEY_DestroyPrivateKey(privKey);
+ }
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+ return SSL_SNI_SEND_ALERT;
+}
+
+/**************************************************************************
+** Begin thread management routines and data.
+**************************************************************************/
+#define MIN_THREADS 3
+#define DEFAULT_THREADS 8
+#define MAX_THREADS 4096
+#define MAX_PROCS 25
+static int maxThreads = DEFAULT_THREADS;
+
+typedef struct jobStr {
+ PRCList link;
+ PRFileDesc *tcp_sock;
+ PRFileDesc *model_sock;
+ int requestCert;
+} JOB;
+
+static PZLock *qLock; /* this lock protects all data immediately below */
+static PRLock *lastLoadedCrlLock; /* this lock protects lastLoadedCrl variable */
+static PZCondVar *jobQNotEmptyCv;
+static PZCondVar *freeListNotEmptyCv;
+static PZCondVar *threadCountChangeCv;
+static int threadCount;
+static PRCList jobQ;
+static PRCList freeJobs;
+static JOB *jobTable;
+
+SECStatus
+setupJobs(int maxJobs)
+{
+ int i;
+
+ jobTable = (JOB *)PR_Calloc(maxJobs, sizeof(JOB));
+ if (!jobTable)
+ return SECFailure;
+
+ PR_INIT_CLIST(&jobQ);
+ PR_INIT_CLIST(&freeJobs);
+
+ for (i = 0; i < maxJobs; ++i) {
+ JOB *pJob = jobTable + i;
+ PR_APPEND_LINK(&pJob->link, &freeJobs);
+ }
+ return SECSuccess;
+}
+
+typedef int startFn(PRFileDesc *a, PRFileDesc *b, int c);
+
+typedef enum { rs_idle = 0,
+ rs_running = 1,
+ rs_zombie = 2 } runState;
+
+typedef struct perThreadStr {
+ PRFileDesc *a;
+ PRFileDesc *b;
+ int c;
+ int rv;
+ startFn *startFunc;
+ PRThread *prThread;
+ runState state;
+} perThread;
+
+static perThread *threads;
+
+void
+thread_wrapper(void *arg)
+{
+ perThread *slot = (perThread *)arg;
+
+ slot->rv = (*slot->startFunc)(slot->a, slot->b, slot->c);
+
+ /* notify the thread exit handler. */
+ PZ_Lock(qLock);
+ slot->state = rs_zombie;
+ --threadCount;
+ PZ_NotifyAllCondVar(threadCountChangeCv);
+ PZ_Unlock(qLock);
+}
+
+int
+jobLoop(PRFileDesc *a, PRFileDesc *b, int c)
+{
+ PRCList *myLink = 0;
+ JOB *myJob;
+
+ PZ_Lock(qLock);
+ do {
+ myLink = 0;
+ while (PR_CLIST_IS_EMPTY(&jobQ) && !stopping) {
+ PZ_WaitCondVar(jobQNotEmptyCv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ if (!PR_CLIST_IS_EMPTY(&jobQ)) {
+ myLink = PR_LIST_HEAD(&jobQ);
+ PR_REMOVE_AND_INIT_LINK(myLink);
+ }
+ PZ_Unlock(qLock);
+ myJob = (JOB *)myLink;
+ /* myJob will be null when stopping is true and jobQ is empty */
+ if (!myJob)
+ break;
+ handle_connection(myJob->tcp_sock, myJob->model_sock,
+ myJob->requestCert);
+ PZ_Lock(qLock);
+ PR_APPEND_LINK(myLink, &freeJobs);
+ PZ_NotifyCondVar(freeListNotEmptyCv);
+ } while (PR_TRUE);
+ return 0;
+}
+
+SECStatus
+launch_threads(
+ startFn *startFunc,
+ PRFileDesc *a,
+ PRFileDesc *b,
+ int c,
+ PRBool local)
+{
+ int i;
+ SECStatus rv = SECSuccess;
+
+ /* create the thread management serialization structs */
+ qLock = PZ_NewLock(nssILockSelfServ);
+ jobQNotEmptyCv = PZ_NewCondVar(qLock);
+ freeListNotEmptyCv = PZ_NewCondVar(qLock);
+ threadCountChangeCv = PZ_NewCondVar(qLock);
+
+ /* create monitor for crl reload procedure */
+ lastLoadedCrlLock = PR_NewLock();
+
+ /* allocate the array of thread slots */
+ threads = PR_Calloc(maxThreads, sizeof(perThread));
+ if (NULL == threads) {
+ fprintf(stderr, "Oh Drat! Can't allocate the perThread array\n");
+ return SECFailure;
+ }
+ /* 5 is a little extra, intended to keep the jobQ from underflowing.
+ ** That is, from going empty while not stopping and clients are still
+ ** trying to contact us.
+ */
+ rv = setupJobs(maxThreads + 5);
+ if (rv != SECSuccess)
+ return rv;
+
+ PZ_Lock(qLock);
+ for (i = 0; i < maxThreads; ++i) {
+ perThread *slot = threads + i;
+
+ slot->state = rs_running;
+ slot->a = a;
+ slot->b = b;
+ slot->c = c;
+ slot->startFunc = startFunc;
+ slot->prThread = PR_CreateThread(PR_USER_THREAD,
+ thread_wrapper, slot, PR_PRIORITY_NORMAL,
+ (PR_TRUE ==
+ local)
+ ? PR_LOCAL_THREAD
+ : PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD, 0);
+ if (slot->prThread == NULL) {
+ printf("selfserv: Failed to launch thread!\n");
+ slot->state = rs_idle;
+ rv = SECFailure;
+ break;
+ }
+
+ ++threadCount;
+ }
+ PZ_Unlock(qLock);
+
+ return rv;
+}
+
+#define DESTROY_CONDVAR(name) \
+ if (name) { \
+ PZ_DestroyCondVar(name); \
+ name = NULL; \
+ }
+#define DESTROY_LOCK(name) \
+ if (name) { \
+ PZ_DestroyLock(name); \
+ name = NULL; \
+ }
+
+void
+terminateWorkerThreads(void)
+{
+ int i;
+
+ VLOG(("selfserv: server_thread: waiting on stopping"));
+ PZ_Lock(qLock);
+ PZ_NotifyAllCondVar(jobQNotEmptyCv);
+ PZ_Unlock(qLock);
+
+ /* Wait for worker threads to terminate. */
+ for (i = 0; i < maxThreads; ++i) {
+ perThread *slot = threads + i;
+ if (slot->prThread) {
+ PR_JoinThread(slot->prThread);
+ }
+ }
+
+ /* The worker threads empty the jobQ before they terminate. */
+ PZ_Lock(qLock);
+ PORT_Assert(threadCount == 0);
+ PORT_Assert(PR_CLIST_IS_EMPTY(&jobQ));
+ PZ_Unlock(qLock);
+
+ DESTROY_CONDVAR(jobQNotEmptyCv);
+ DESTROY_CONDVAR(freeListNotEmptyCv);
+ DESTROY_CONDVAR(threadCountChangeCv);
+
+ PR_DestroyLock(lastLoadedCrlLock);
+ DESTROY_LOCK(qLock);
+ PR_Free(jobTable);
+ PR_Free(threads);
+}
+
+static void
+logger(void *arg)
+{
+ PRFloat64 seconds;
+ PRFloat64 opsPerSec;
+ PRIntervalTime period;
+ PRIntervalTime previousTime;
+ PRIntervalTime latestTime;
+ PRInt32 previousOps;
+ PRInt32 ops;
+ PRIntervalTime logPeriodTicks = PR_TicksPerSecond();
+ PRFloat64 secondsPerTick = 1.0 / (PRFloat64)logPeriodTicks;
+ int iterations = 0;
+ int secondsElapsed = 0;
+ static PRInt64 totalPeriodBytes = 0;
+ static PRInt64 totalPeriodBytesTCP = 0;
+
+ previousOps = loggerOps;
+ previousTime = PR_IntervalNow();
+
+ for (;;) {
+ /* OK, implementing a new sleep algorithm here... always sleep
+ * for 1 second but print out info at the user-specified interval.
+ * This way, we don't overflow all of our PR_Atomic* functions and
+ * we don't have to use locks.
+ */
+ PR_Sleep(logPeriodTicks);
+ secondsElapsed++;
+ totalPeriodBytes += PR_ATOMIC_SET(&loggerBytes, 0);
+ totalPeriodBytesTCP += PR_ATOMIC_SET(&loggerBytesTCP, 0);
+ if (secondsElapsed != logPeriod) {
+ continue;
+ }
+ /* when we reach the user-specified logging interval, print out all
+ * data
+ */
+ secondsElapsed = 0;
+ latestTime = PR_IntervalNow();
+ ops = loggerOps;
+ period = latestTime - previousTime;
+ seconds = (PRFloat64)period * secondsPerTick;
+ opsPerSec = (ops - previousOps) / seconds;
+
+ if (testBulk) {
+ if (iterations == 0) {
+ if (loggingLayer == PR_TRUE) {
+ printf("Conn.--------App Data--------TCP Data\n");
+ } else {
+ printf("Conn.--------App Data\n");
+ }
+ }
+ if (loggingLayer == PR_TRUE) {
+ printf("%4.d %5.3f MB/s %5.3f MB/s\n", ops,
+ totalPeriodBytes / (seconds * 1048576.0),
+ totalPeriodBytesTCP / (seconds * 1048576.0));
+ } else {
+ printf("%4.d %5.3f MB/s\n", ops,
+ totalPeriodBytes / (seconds * 1048576.0));
+ }
+ totalPeriodBytes = 0;
+ totalPeriodBytesTCP = 0;
+ /* Print the "legend" every 20 iterations */
+ iterations = (iterations + 1) % 20;
+ } else {
+ printf("%.2f ops/second, %d threads\n", opsPerSec, threadCount);
+ }
+
+ fflush(stdout);
+ previousOps = ops;
+ previousTime = latestTime;
+ if (stopping) {
+ break;
+ }
+ }
+}
+
+/**************************************************************************
+** End thread management routines.
+**************************************************************************/
+
+PRBool useModelSocket = PR_FALSE;
+static SSLVersionRange enabledVersions;
+PRBool disableRollBack = PR_FALSE;
+PRBool NoReuse = PR_FALSE;
+PRBool hasSidCache = PR_FALSE;
+PRBool disableLocking = PR_FALSE;
+PRBool enableSessionTickets = PR_FALSE;
+PRBool enableCompression = PR_FALSE;
+PRBool failedToNegotiateName = PR_FALSE;
+PRBool enableExtendedMasterSecret = PR_FALSE;
+PRBool zeroRTT = PR_FALSE;
+PRBool enableALPN = PR_FALSE;
+SSLNamedGroup *enabledGroups = NULL;
+unsigned int enabledGroupsCount = 0;
+
+static char *virtServerNameArray[MAX_VIRT_SERVER_NAME_ARRAY_INDEX];
+static int virtServerNameIndex = 1;
+
+static char *certNicknameArray[MAX_CERT_NICKNAME_ARRAY_INDEX];
+static int certNicknameIndex = 0;
+
+static const char stopCmd[] = { "GET /stop " };
+static const char getCmd[] = { "GET " };
+static const char EOFmsg[] = { "EOF\r\n\r\n\r\n" };
+static const char outHeader[] = {
+ "HTTP/1.0 200 OK\r\n"
+ "Server: Generic Web Server\r\n"
+ "Date: Tue, 26 Aug 1997 22:10:05 GMT\r\n"
+ "Content-type: text/plain\r\n"
+ "\r\n"
+};
+static const char crlCacheErr[] = { "CRL ReCache Error: " };
+
+PRUint16 cipherlist[100];
+int nciphers;
+
+void
+savecipher(int c)
+{
+ if (nciphers < sizeof cipherlist / sizeof(cipherlist[0]))
+ cipherlist[nciphers++] = (PRUint16)c;
+}
+
+#ifdef FULL_DUPLEX_CAPABLE
+
+struct lockedVarsStr {
+ PZLock *lock;
+ int count;
+ int waiters;
+ PZCondVar *condVar;
+};
+
+typedef struct lockedVarsStr lockedVars;
+
+void
+lockedVars_Init(lockedVars *lv)
+{
+ lv->count = 0;
+ lv->waiters = 0;
+ lv->lock = PZ_NewLock(nssILockSelfServ);
+ lv->condVar = PZ_NewCondVar(lv->lock);
+}
+
+void
+lockedVars_Destroy(lockedVars *lv)
+{
+ PZ_DestroyCondVar(lv->condVar);
+ lv->condVar = NULL;
+
+ PZ_DestroyLock(lv->lock);
+ lv->lock = NULL;
+}
+
+void
+lockedVars_WaitForDone(lockedVars *lv)
+{
+ PZ_Lock(lv->lock);
+ while (lv->count > 0) {
+ PZ_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PZ_Unlock(lv->lock);
+}
+
+int /* returns count */
+ lockedVars_AddToCount(lockedVars *lv, int addend)
+{
+ int rv;
+
+ PZ_Lock(lv->lock);
+ rv = lv->count += addend;
+ if (rv <= 0) {
+ PZ_NotifyCondVar(lv->condVar);
+ }
+ PZ_Unlock(lv->lock);
+ return rv;
+}
+
+int
+do_writes(
+ PRFileDesc *ssl_sock,
+ PRFileDesc *model_sock,
+ int requestCert)
+{
+ int sent = 0;
+ int count = 0;
+ lockedVars *lv = (lockedVars *)model_sock;
+
+ VLOG(("selfserv: do_writes: starting"));
+ while (sent < bigBuf.len) {
+
+ count = PR_Write(ssl_sock, bigBuf.data + sent, bigBuf.len - sent);
+ if (count < 0) {
+ errWarn("PR_Write bigBuf");
+ break;
+ }
+ FPRINTF(stderr, "selfserv: PR_Write wrote %d bytes from bigBuf\n", count);
+ sent += count;
+ }
+ if (count >= 0) { /* last write didn't fail. */
+ PR_Shutdown(ssl_sock, PR_SHUTDOWN_SEND);
+ }
+
+ /* notify the reader that we're done. */
+ lockedVars_AddToCount(lv, -1);
+ FLUSH;
+ VLOG(("selfserv: do_writes: exiting"));
+ return (sent < bigBuf.len) ? SECFailure : SECSuccess;
+}
+
+static int
+handle_fdx_connection(
+ PRFileDesc *tcp_sock,
+ PRFileDesc *model_sock,
+ int requestCert)
+{
+ PRFileDesc *ssl_sock = NULL;
+ SECStatus result;
+ int firstTime = 1;
+ lockedVars lv;
+ PRSocketOptionData opt;
+ char buf[10240];
+
+ VLOG(("selfserv: handle_fdx_connection: starting"));
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ PR_SetSocketOption(tcp_sock, &opt);
+
+ if (useModelSocket && model_sock) {
+ SECStatus rv;
+ ssl_sock = SSL_ImportFD(model_sock, tcp_sock);
+ if (!ssl_sock) {
+ errWarn("SSL_ImportFD with model");
+ goto cleanup;
+ }
+ rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 1);
+ if (rv != SECSuccess) {
+ errWarn("SSL_ResetHandshake");
+ goto cleanup;
+ }
+ } else {
+ ssl_sock = tcp_sock;
+ }
+
+ lockedVars_Init(&lv);
+ lockedVars_AddToCount(&lv, 1);
+
+ /* Attempt to launch the writer thread. */
+ result = launch_thread(do_writes, ssl_sock, (PRFileDesc *)&lv,
+ requestCert);
+
+ if (result == SECSuccess)
+ do {
+ /* do reads here. */
+ int count;
+ count = PR_Read(ssl_sock, buf, sizeof buf);
+ if (count < 0) {
+ errWarn("FDX PR_Read");
+ break;
+ }
+ FPRINTF(stderr, "selfserv: FDX PR_Read read %d bytes.\n", count);
+ if (firstTime) {
+ firstTime = 0;
+ printSecurityInfo(ssl_sock);
+ }
+ } while (lockedVars_AddToCount(&lv, 0) > 0);
+
+ /* Wait for writer to finish */
+ lockedVars_WaitForDone(&lv);
+ lockedVars_Destroy(&lv);
+ FLUSH;
+
+cleanup:
+ if (ssl_sock) {
+ PR_Close(ssl_sock);
+ } else if (tcp_sock) {
+ PR_Close(tcp_sock);
+ }
+
+ VLOG(("selfserv: handle_fdx_connection: exiting"));
+ return SECSuccess;
+}
+
+#endif
+
+static SECItem *lastLoadedCrl = NULL;
+
+static SECStatus
+reload_crl(PRFileDesc *crlFile)
+{
+ SECItem *crlDer;
+ CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
+ SECStatus rv;
+
+ /* Read in the entire file specified with the -f argument */
+ crlDer = PORT_Malloc(sizeof(SECItem));
+ if (!crlDer) {
+ errWarn("Can not allocate memory.");
+ return SECFailure;
+ }
+
+ rv = SECU_ReadDERFromFile(crlDer, crlFile, PR_FALSE, PR_FALSE);
+ if (rv != SECSuccess) {
+ errWarn("Unable to read input file.");
+ PORT_Free(crlDer);
+ return SECFailure;
+ }
+
+ PR_Lock(lastLoadedCrlLock);
+ rv = CERT_CacheCRL(certHandle, crlDer);
+ if (rv == SECSuccess) {
+ SECItem *tempItem = crlDer;
+ if (lastLoadedCrl != NULL) {
+ rv = CERT_UncacheCRL(certHandle, lastLoadedCrl);
+ if (rv != SECSuccess) {
+ errWarn("Unable to uncache crl.");
+ goto loser;
+ }
+ crlDer = lastLoadedCrl;
+ } else {
+ crlDer = NULL;
+ }
+ lastLoadedCrl = tempItem;
+ }
+
+loser:
+ PR_Unlock(lastLoadedCrlLock);
+ SECITEM_FreeItem(crlDer, PR_TRUE);
+ return rv;
+}
+
+void
+stop_server()
+{
+ stopping = 1;
+ PR_Interrupt(acceptorThread);
+ PZ_TraceFlush();
+}
+
+SECItemArray *
+makeTryLaterOCSPResponse(PLArenaPool *arena)
+{
+ SECItemArray *result = NULL;
+ SECItem *ocspResponse = NULL;
+
+ ocspResponse = CERT_CreateEncodedOCSPErrorResponse(arena,
+ SEC_ERROR_OCSP_TRY_SERVER_LATER);
+ if (!ocspResponse)
+ errExit("cannot created ocspResponse");
+
+ result = SECITEM_AllocArray(arena, NULL, 1);
+ if (!result)
+ errExit("cannot allocate multiOcspResponses");
+
+ result->items[0].data = ocspResponse->data;
+ result->items[0].len = ocspResponse->len;
+
+ return result;
+}
+
+SECItemArray *
+makeCorruptedOCSPResponse(PLArenaPool *arena)
+{
+ SECItemArray *result = NULL;
+ SECItem *ocspResponse = NULL;
+
+ ocspResponse = SECITEM_AllocItem(arena, NULL, 1);
+ if (!ocspResponse)
+ errExit("cannot created ocspResponse");
+
+ result = SECITEM_AllocArray(arena, NULL, 1);
+ if (!result)
+ errExit("cannot allocate multiOcspResponses");
+
+ result->items[0].data = ocspResponse->data;
+ result->items[0].len = ocspResponse->len;
+
+ return result;
+}
+
+SECItemArray *
+makeSignedOCSPResponse(PLArenaPool *arena, ocspStaplingModeType osm,
+ CERTCertificate *cert, secuPWData *pwdata)
+{
+ SECItemArray *result = NULL;
+ SECItem *ocspResponse = NULL;
+ CERTOCSPSingleResponse **singleResponses;
+ CERTOCSPSingleResponse *sr = NULL;
+ CERTOCSPCertID *cid = NULL;
+ CERTCertificate *ca;
+ PRTime now = PR_Now();
+ PRTime nextUpdate;
+
+ PORT_Assert(cert != NULL);
+
+ ca = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), ocspStaplingCA);
+ if (!ca)
+ errExit("cannot find CA");
+
+ cid = CERT_CreateOCSPCertID(cert, now);
+ if (!cid)
+ errExit("cannot created cid");
+
+ nextUpdate = now + (PRTime)60 * 60 * 24 * PR_USEC_PER_SEC; /* plus 1 day */
+
+ switch (osm) {
+ case osm_good:
+ case osm_badsig:
+ sr = CERT_CreateOCSPSingleResponseGood(arena, cid, now,
+ &nextUpdate);
+ break;
+ case osm_unknown:
+ sr = CERT_CreateOCSPSingleResponseUnknown(arena, cid, now,
+ &nextUpdate);
+ break;
+ case osm_revoked:
+ sr = CERT_CreateOCSPSingleResponseRevoked(arena, cid, now,
+ &nextUpdate,
+ now - (PRTime)60 * 60 * 24 * PR_USEC_PER_SEC, /* minus 1 day */
+ NULL);
+ break;
+ default:
+ PORT_Assert(0);
+ break;
+ }
+
+ if (!sr)
+ errExit("cannot create sr");
+
+ /* meaning of value 2: one entry + one end marker */
+ singleResponses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse *, 2);
+ if (singleResponses == NULL)
+ errExit("cannot allocate singleResponses");
+
+ singleResponses[0] = sr;
+ singleResponses[1] = NULL;
+
+ ocspResponse = CERT_CreateEncodedOCSPSuccessResponse(arena,
+ (osm == osm_badsig)
+ ? NULL
+ : ca,
+ ocspResponderID_byName, now, singleResponses,
+ &pwdata);
+ if (!ocspResponse)
+ errExit("cannot created ocspResponse");
+
+ CERT_DestroyCertificate(ca);
+ ca = NULL;
+
+ result = SECITEM_AllocArray(arena, NULL, 1);
+ if (!result)
+ errExit("cannot allocate multiOcspResponses");
+
+ result->items[0].data = ocspResponse->data;
+ result->items[0].len = ocspResponse->len;
+
+ CERT_DestroyOCSPCertID(cid);
+ cid = NULL;
+
+ return result;
+}
+
+void
+setupCertStatus(PLArenaPool *arena, enum ocspStaplingModeEnum ocspStaplingMode,
+ CERTCertificate *cert, int index, secuPWData *pwdata)
+{
+ if (ocspStaplingMode == osm_random) {
+ /* 6 different responses */
+ int r = rand() % 6;
+ switch (r) {
+ case 0:
+ ocspStaplingMode = osm_good;
+ break;
+ case 1:
+ ocspStaplingMode = osm_revoked;
+ break;
+ case 2:
+ ocspStaplingMode = osm_unknown;
+ break;
+ case 3:
+ ocspStaplingMode = osm_badsig;
+ break;
+ case 4:
+ ocspStaplingMode = osm_corrupted;
+ break;
+ case 5:
+ ocspStaplingMode = osm_failure;
+ break;
+ default:
+ PORT_Assert(0);
+ break;
+ }
+ }
+ if (ocspStaplingMode != osm_disabled) {
+ SECItemArray *multiOcspResponses = NULL;
+ switch (ocspStaplingMode) {
+ case osm_good:
+ case osm_revoked:
+ case osm_unknown:
+ case osm_badsig:
+ multiOcspResponses =
+ makeSignedOCSPResponse(arena, ocspStaplingMode, cert,
+ pwdata);
+ break;
+ case osm_corrupted:
+ multiOcspResponses = makeCorruptedOCSPResponse(arena);
+ break;
+ case osm_failure:
+ multiOcspResponses = makeTryLaterOCSPResponse(arena);
+ break;
+ case osm_ocsp:
+ errExit("stapling mode \"ocsp\" not implemented");
+ break;
+ break;
+ default:
+ break;
+ }
+ if (multiOcspResponses) {
+ certStatus[index] = multiOcspResponses;
+ }
+ }
+}
+
+int
+handle_connection(
+ PRFileDesc *tcp_sock,
+ PRFileDesc *model_sock,
+ int requestCert)
+{
+ PRFileDesc *ssl_sock = NULL;
+ PRFileDesc *local_file_fd = NULL;
+ char *post;
+ char *pBuf; /* unused space at end of buf */
+ const char *errString;
+ PRStatus status;
+ int bufRem; /* unused bytes at end of buf */
+ int bufDat; /* characters received in buf */
+ int newln = 0; /* # of consecutive newlns */
+ int firstTime = 1;
+ int reqLen;
+ int rv;
+ int numIOVs;
+ PRSocketOptionData opt;
+ PRIOVec iovs[16];
+ char msgBuf[160];
+ char buf[10240] = { 0 };
+ char fileName[513];
+ char proto[128];
+ PRDescIdentity aboveLayer = PR_INVALID_IO_LAYER;
+
+ pBuf = buf;
+ bufRem = sizeof buf;
+
+ VLOG(("selfserv: handle_connection: starting"));
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ PR_SetSocketOption(tcp_sock, &opt);
+
+ VLOG(("selfserv: handle_connection: starting\n"));
+ if (useModelSocket && model_sock) {
+ SECStatus rv;
+ ssl_sock = SSL_ImportFD(model_sock, tcp_sock);
+ if (!ssl_sock) {
+ errWarn("SSL_ImportFD with model");
+ goto cleanup;
+ }
+ rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 1);
+ if (rv != SECSuccess) {
+ errWarn("SSL_ResetHandshake");
+ goto cleanup;
+ }
+ } else {
+ ssl_sock = tcp_sock;
+ }
+
+ if (loggingLayer) {
+ /* find the layer where our new layer is to be pushed */
+ aboveLayer = PR_GetLayersIdentity(ssl_sock->lower);
+ if (aboveLayer == PR_INVALID_IO_LAYER) {
+ errExit("PRGetUniqueIdentity");
+ }
+ /* create the new layer - this is a very cheap operation */
+ loggingFD = PR_CreateIOLayerStub(log_layer_id, &loggingMethods);
+ if (!loggingFD)
+ errExit("PR_CreateIOLayerStub");
+ /* push the layer below ssl but above TCP */
+ rv = PR_PushIOLayer(ssl_sock, aboveLayer, loggingFD);
+ if (rv != PR_SUCCESS) {
+ errExit("PR_PushIOLayer");
+ }
+ }
+
+ if (noDelay) {
+ opt.option = PR_SockOpt_NoDelay;
+ opt.value.no_delay = PR_TRUE;
+ status = PR_SetSocketOption(ssl_sock, &opt);
+ if (status != PR_SUCCESS) {
+ errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)");
+ if (ssl_sock) {
+ PR_Close(ssl_sock);
+ }
+ return SECFailure;
+ }
+ }
+
+ while (1) {
+ newln = 0;
+ reqLen = 0;
+ rv = PR_Read(ssl_sock, pBuf, bufRem - 1);
+ if (rv == 0 ||
+ (rv < 0 && PR_END_OF_FILE_ERROR == PR_GetError())) {
+ if (verbose)
+ errWarn("HDX PR_Read hit EOF");
+ break;
+ }
+ if (rv < 0) {
+ errWarn("HDX PR_Read");
+ goto cleanup;
+ }
+ /* NULL termination */
+ pBuf[rv] = 0;
+ if (firstTime) {
+ firstTime = 0;
+ printSecurityInfo(ssl_sock);
+ }
+
+ pBuf += rv;
+ bufRem -= rv;
+ bufDat = pBuf - buf;
+ /* Parse the input, starting at the beginning of the buffer.
+ * Stop when we detect two consecutive \n's (or \r\n's)
+ * as this signifies the end of the GET or POST portion.
+ * The posted data follows.
+ */
+ while (reqLen < bufDat && newln < 2) {
+ int octet = buf[reqLen++];
+ if (octet == '\n') {
+ newln++;
+ } else if (octet != '\r') {
+ newln = 0;
+ }
+ }
+
+ /* came to the end of the buffer, or second newln
+ * If we didn't get an empty line (CRLFCRLF) then keep on reading.
+ */
+ if (newln < 2)
+ continue;
+
+ /* we're at the end of the HTTP request.
+ * If the request is a POST, then there will be one more
+ * line of data.
+ * This parsing is a hack, but ok for SSL test purposes.
+ */
+ post = PORT_Strstr(buf, "POST ");
+ if (!post || *post != 'P')
+ break;
+
+ /* It's a post, so look for the next and final CR/LF. */
+ /* We should parse content length here, but ... */
+ while (reqLen < bufDat && newln < 3) {
+ int octet = buf[reqLen++];
+ if (octet == '\n') {
+ newln++;
+ }
+ }
+ if (newln == 3)
+ break;
+ } /* read loop */
+
+ bufDat = pBuf - buf;
+ if (bufDat)
+ do { /* just close if no data */
+ /* Have either (a) a complete get, (b) a complete post, (c) EOF */
+ if (reqLen > 0 && !strncmp(buf, getCmd, sizeof getCmd - 1)) {
+ char *fnBegin = buf + 4;
+ char *fnEnd;
+ PRFileInfo info;
+ /* try to open the file named.
+ * If successful, then write it to the client.
+ */
+ fnEnd = strpbrk(fnBegin, " \r\n");
+ if (fnEnd) {
+ int fnLen = fnEnd - fnBegin;
+ if (fnLen < sizeof fileName) {
+ char *real_fileName = fileName;
+ char *protoEnd = NULL;
+ strncpy(fileName, fnBegin, fnLen);
+ fileName[fnLen] = 0; /* null terminate */
+ if ((protoEnd = strstr(fileName, "://")) != NULL) {
+ int protoLen = PR_MIN(protoEnd - fileName, sizeof(proto) - 1);
+ PL_strncpy(proto, fileName, protoLen);
+ proto[protoLen] = 0;
+ real_fileName = protoEnd + 3;
+ } else {
+ proto[0] = 0;
+ }
+ status = PR_GetFileInfo(real_fileName, &info);
+ if (status == PR_SUCCESS &&
+ info.type == PR_FILE_FILE &&
+ info.size >= 0) {
+ local_file_fd = PR_Open(real_fileName, PR_RDONLY, 0);
+ }
+ }
+ }
+ }
+ /* if user has requested client auth in a subsequent handshake,
+ * do it here.
+ */
+ if (requestCert > 2) { /* request cert was 3 or 4 */
+ CERTCertificate *cert = SSL_PeerCertificate(ssl_sock);
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ } else {
+ rv = SSL_OptionSet(ssl_sock, SSL_REQUEST_CERTIFICATE, 1);
+ if (rv < 0) {
+ errWarn("second SSL_OptionSet SSL_REQUEST_CERTIFICATE");
+ break;
+ }
+ rv = SSL_OptionSet(ssl_sock, SSL_REQUIRE_CERTIFICATE,
+ (requestCert == 4));
+ if (rv < 0) {
+ errWarn("second SSL_OptionSet SSL_REQUIRE_CERTIFICATE");
+ break;
+ }
+ rv = SSL_ReHandshake(ssl_sock, PR_TRUE);
+ if (rv != 0) {
+ errWarn("SSL_ReHandshake");
+ break;
+ }
+ rv = SSL_ForceHandshake(ssl_sock);
+ if (rv < 0) {
+ errWarn("SSL_ForceHandshake");
+ break;
+ }
+ }
+ }
+
+ numIOVs = 0;
+
+ iovs[numIOVs].iov_base = (char *)outHeader;
+ iovs[numIOVs].iov_len = (sizeof(outHeader)) - 1;
+ numIOVs++;
+
+ if (local_file_fd) {
+ PRInt32 bytes;
+ int errLen;
+ if (!PL_strlen(proto) || !PL_strcmp(proto, "file")) {
+ bytes = PR_TransmitFile(ssl_sock, local_file_fd, outHeader,
+ sizeof outHeader - 1,
+ PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytes >= 0) {
+ bytes -= sizeof outHeader - 1;
+ FPRINTF(stderr,
+ "selfserv: PR_TransmitFile wrote %d bytes from %s\n",
+ bytes, fileName);
+ break;
+ }
+ errString = errWarn("PR_TransmitFile");
+ errLen = PORT_Strlen(errString);
+ errLen = PR_MIN(errLen, sizeof msgBuf - 1);
+ PORT_Memcpy(msgBuf, errString, errLen);
+ msgBuf[errLen] = 0;
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ }
+ if (!PL_strcmp(proto, "crl")) {
+ if (reload_crl(local_file_fd) == SECFailure) {
+ errString = errWarn("CERT_CacheCRL");
+ if (!errString)
+ errString = "Unknow error";
+ PR_snprintf(msgBuf, sizeof(msgBuf), "%s%s ",
+ crlCacheErr, errString);
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ } else {
+ FPRINTF(stderr,
+ "selfserv: CRL %s reloaded.\n",
+ fileName);
+ break;
+ }
+ }
+ } else if (reqLen <= 0) { /* hit eof */
+ PORT_Sprintf(msgBuf, "Get or Post incomplete after %d bytes.\r\n",
+ bufDat);
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ } else if (reqLen < bufDat) {
+ PORT_Sprintf(msgBuf, "Discarded %d characters.\r\n",
+ bufDat - reqLen);
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ }
+
+ if (reqLen > 0) {
+ if (verbose > 1)
+ fwrite(buf, 1, reqLen, stdout); /* display it */
+
+ iovs[numIOVs].iov_base = buf;
+ iovs[numIOVs].iov_len = reqLen;
+ numIOVs++;
+ }
+
+ /* Don't add the EOF if we want to test bulk encryption */
+ if (!testBulk) {
+ iovs[numIOVs].iov_base = (char *)EOFmsg;
+ iovs[numIOVs].iov_len = sizeof EOFmsg - 1;
+ numIOVs++;
+ }
+
+ rv = PR_Writev(ssl_sock, iovs, numIOVs, PR_INTERVAL_NO_TIMEOUT);
+ if (rv < 0) {
+ errWarn("PR_Writev");
+ break;
+ }
+
+ /* Send testBulkTotal chunks to the client. Unlimited if 0. */
+ if (testBulk) {
+ while (0 < (rv = PR_Write(ssl_sock, testBulkBuf, testBulkSize))) {
+ PR_ATOMIC_ADD(&loggerBytes, rv);
+ PR_ATOMIC_INCREMENT(&bulkSentChunks);
+ if ((bulkSentChunks > testBulkTotal) && (testBulkTotal != 0))
+ break;
+ }
+
+ /* There was a write error, so close this connection. */
+ if (bulkSentChunks <= testBulkTotal) {
+ errWarn("PR_Write");
+ }
+ PR_ATOMIC_DECREMENT(&loggerOps);
+ break;
+ }
+ } while (0);
+
+cleanup:
+ if (ssl_sock) {
+ PR_Close(ssl_sock);
+ } else if (tcp_sock) {
+ PR_Close(tcp_sock);
+ }
+ if (local_file_fd)
+ PR_Close(local_file_fd);
+ VLOG(("selfserv: handle_connection: exiting\n"));
+
+ /* do a nice shutdown if asked. */
+ if (!strncmp(buf, stopCmd, sizeof stopCmd - 1)) {
+ VLOG(("selfserv: handle_connection: stop command"));
+ stop_server();
+ }
+ VLOG(("selfserv: handle_connection: exiting"));
+ return SECSuccess; /* success */
+}
+
+#ifdef XP_UNIX
+
+void
+sigusr1_handler(int sig)
+{
+ VLOG(("selfserv: sigusr1_handler: stop server"));
+ stop_server();
+}
+
+#endif
+
+SECStatus
+do_accepts(
+ PRFileDesc *listen_sock,
+ PRFileDesc *model_sock,
+ int requestCert)
+{
+ PRNetAddr addr;
+ PRErrorCode perr;
+#ifdef XP_UNIX
+ struct sigaction act;
+#endif
+
+ VLOG(("selfserv: do_accepts: starting"));
+ PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_HIGH);
+
+ acceptorThread = PR_GetCurrentThread();
+#ifdef XP_UNIX
+ /* set up the signal handler */
+ act.sa_handler = sigusr1_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ if (sigaction(SIGUSR1, &act, NULL)) {
+ fprintf(stderr, "Error installing signal handler.\n");
+ exit(1);
+ }
+#endif
+ while (!stopping) {
+ PRFileDesc *tcp_sock;
+ PRCList *myLink;
+
+ FPRINTF(stderr, "\n\n\nselfserv: About to call accept.\n");
+ tcp_sock = PR_Accept(listen_sock, &addr, PR_INTERVAL_NO_TIMEOUT);
+ if (tcp_sock == NULL) {
+ perr = PR_GetError();
+ if ((perr != PR_CONNECT_RESET_ERROR &&
+ perr != PR_PENDING_INTERRUPT_ERROR) ||
+ verbose) {
+ errWarn("PR_Accept");
+ }
+ if (perr == PR_CONNECT_RESET_ERROR) {
+ FPRINTF(stderr,
+ "Ignoring PR_CONNECT_RESET_ERROR error - continue\n");
+ continue;
+ }
+ stopping = 1;
+ break;
+ }
+
+ VLOG(("selfserv: do_accept: Got connection\n"));
+
+ if (logStats) {
+ PR_ATOMIC_INCREMENT(&loggerOps);
+ }
+
+ PZ_Lock(qLock);
+ while (PR_CLIST_IS_EMPTY(&freeJobs) && !stopping) {
+ PZ_WaitCondVar(freeListNotEmptyCv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ if (stopping) {
+ PZ_Unlock(qLock);
+ if (tcp_sock) {
+ PR_Close(tcp_sock);
+ }
+ break;
+ }
+ myLink = PR_LIST_HEAD(&freeJobs);
+ PR_REMOVE_AND_INIT_LINK(myLink);
+ /* could release qLock here and reaquire it 7 lines below, but
+ ** why bother for 4 assignment statements?
+ */
+ {
+ JOB *myJob = (JOB *)myLink;
+ myJob->tcp_sock = tcp_sock;
+ myJob->model_sock = model_sock;
+ myJob->requestCert = requestCert;
+ }
+
+ PR_APPEND_LINK(myLink, &jobQ);
+ PZ_NotifyCondVar(jobQNotEmptyCv);
+ PZ_Unlock(qLock);
+ }
+
+ FPRINTF(stderr, "selfserv: Closing listen socket.\n");
+ VLOG(("selfserv: do_accepts: exiting"));
+ if (listen_sock) {
+ PR_Close(listen_sock);
+ }
+ return SECSuccess;
+}
+
+PRFileDesc *
+getBoundListenSocket(unsigned short port)
+{
+ PRFileDesc *listen_sock;
+ int listenQueueDepth = 5 + (2 * maxThreads);
+ PRStatus prStatus;
+ PRNetAddr addr;
+ PRSocketOptionData opt;
+
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_INADDR_ANY;
+ addr.inet.port = PR_htons(port);
+
+ listen_sock = PR_NewTCPSocket();
+ if (listen_sock == NULL) {
+ errExit("PR_NewTCPSocket");
+ }
+
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ prStatus = PR_SetSocketOption(listen_sock, &opt);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_SetSocketOption(PR_SockOpt_Nonblocking)");
+ }
+
+ opt.option = PR_SockOpt_Reuseaddr;
+ opt.value.reuse_addr = PR_TRUE;
+ prStatus = PR_SetSocketOption(listen_sock, &opt);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_SetSocketOption(PR_SockOpt_Reuseaddr)");
+ }
+
+#ifndef WIN95
+ /* Set PR_SockOpt_Linger because it helps prevent a server bind issue
+ * after clean shutdown . See bug 331413 .
+ * Don't do it in the WIN95 build configuration because clean shutdown is
+ * not implemented, and PR_SockOpt_Linger causes a hang in ssl.sh .
+ * See bug 332348 */
+ opt.option = PR_SockOpt_Linger;
+ opt.value.linger.polarity = PR_TRUE;
+ opt.value.linger.linger = PR_SecondsToInterval(1);
+ prStatus = PR_SetSocketOption(listen_sock, &opt);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_SetSocketOption(PR_SockOpt_Linger)");
+ }
+#endif
+
+ prStatus = PR_Bind(listen_sock, &addr);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_Bind");
+ }
+
+ prStatus = PR_Listen(listen_sock, listenQueueDepth);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_Listen");
+ }
+ return listen_sock;
+}
+
+PRInt32 PR_CALLBACK
+logWritev(
+ PRFileDesc *fd,
+ const PRIOVec *iov,
+ PRInt32 size,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv = (fd->lower->methods->writev)(fd->lower, iov, size,
+ timeout);
+ /* Add the amount written, but not if there's an error */
+ if (rv > 0)
+ PR_ATOMIC_ADD(&loggerBytesTCP, rv);
+ return rv;
+}
+
+PRInt32 PR_CALLBACK
+logWrite(
+ PRFileDesc *fd,
+ const void *buf,
+ PRInt32 amount)
+{
+ PRInt32 rv = (fd->lower->methods->write)(fd->lower, buf, amount);
+ /* Add the amount written, but not if there's an error */
+ if (rv > 0)
+ PR_ATOMIC_ADD(&loggerBytesTCP, rv);
+
+ return rv;
+}
+
+PRInt32 PR_CALLBACK
+logSend(
+ PRFileDesc *fd,
+ const void *buf,
+ PRInt32 amount,
+ PRIntn flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv = (fd->lower->methods->send)(fd->lower, buf, amount,
+ flags, timeout);
+ /* Add the amount written, but not if there's an error */
+ if (rv > 0)
+ PR_ATOMIC_ADD(&loggerBytesTCP, rv);
+ return rv;
+}
+
+void
+initLoggingLayer(void)
+{
+ /* get a new layer ID */
+ log_layer_id = PR_GetUniqueIdentity("Selfserv Logging");
+ if (log_layer_id == PR_INVALID_IO_LAYER)
+ errExit("PR_GetUniqueIdentity");
+
+ /* setup the default IO methods with my custom write methods */
+ memcpy(&loggingMethods, PR_GetDefaultIOMethods(), sizeof(PRIOMethods));
+ loggingMethods.writev = logWritev;
+ loggingMethods.write = logWrite;
+ loggingMethods.send = logSend;
+}
+
+void
+handshakeCallback(PRFileDesc *fd, void *client_data)
+{
+ const char *handshakeName = (const char *)client_data;
+ if (handshakeName && !failedToNegotiateName) {
+ SECItem *hostInfo = SSL_GetNegotiatedHostInfo(fd);
+ if (!hostInfo || PORT_Strncmp(handshakeName, (char *)hostInfo->data,
+ hostInfo->len)) {
+ failedToNegotiateName = PR_TRUE;
+ }
+ if (hostInfo) {
+ SECITEM_FreeItem(hostInfo, PR_TRUE);
+ }
+ }
+}
+
+void
+server_main(
+ PRFileDesc *listen_sock,
+ int requestCert,
+ SECKEYPrivateKey **privKey,
+ CERTCertificate **cert,
+ const char *expectedHostNameVal)
+{
+ int i;
+ PRFileDesc *model_sock = NULL;
+ int rv;
+ SECStatus secStatus;
+
+ if (useModelSocket) {
+ model_sock = PR_NewTCPSocket();
+ if (model_sock == NULL) {
+ errExit("PR_NewTCPSocket on model socket");
+ }
+ model_sock = SSL_ImportFD(NULL, model_sock);
+ if (model_sock == NULL) {
+ errExit("SSL_ImportFD");
+ }
+ } else {
+ model_sock = listen_sock = SSL_ImportFD(NULL, listen_sock);
+ if (listen_sock == NULL) {
+ errExit("SSL_ImportFD");
+ }
+ }
+
+ /* do SSL configuration. */
+ rv = SSL_OptionSet(model_sock, SSL_SECURITY, enabledVersions.min != 0);
+ if (rv < 0) {
+ errExit("SSL_OptionSet SSL_SECURITY");
+ }
+
+ rv = SSL_VersionRangeSet(model_sock, &enabledVersions);
+ if (rv != SECSuccess) {
+ errExit("error setting SSL/TLS version range ");
+ }
+
+ rv = SSL_OptionSet(model_sock, SSL_ROLLBACK_DETECTION, !disableRollBack);
+ if (rv != SECSuccess) {
+ errExit("error enabling RollBack detection ");
+ }
+ if (disableLocking) {
+ rv = SSL_OptionSet(model_sock, SSL_NO_LOCKS, PR_TRUE);
+ if (rv != SECSuccess) {
+ errExit("error disabling SSL socket locking ");
+ }
+ }
+ if (enableSessionTickets) {
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
+ if (rv != SECSuccess) {
+ errExit("error enabling Session Ticket extension ");
+ }
+ }
+
+ if (enableCompression) {
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_DEFLATE, PR_TRUE);
+ if (rv != SECSuccess) {
+ errExit("error enabling compression ");
+ }
+ }
+
+ if (virtServerNameIndex > 1) {
+ rv = SSL_SNISocketConfigHook(model_sock, mySSLSNISocketConfig,
+ (void *)&virtServerNameArray);
+ if (rv != SECSuccess) {
+ errExit("error enabling SNI extension ");
+ }
+ }
+
+ if (configureDHE > -1) {
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_SERVER_DHE, (configureDHE > 0));
+ if (rv != SECSuccess) {
+ errExit("error configuring server side DHE support");
+ }
+ rv = SSL_OptionSet(model_sock, SSL_REQUIRE_DH_NAMED_GROUPS, (configureDHE > 1));
+ if (rv != SECSuccess) {
+ errExit("error configuring server side FFDHE support");
+ }
+ PORT_Assert(configureDHE <= 2);
+ }
+
+ if (configureReuseECDHE > -1) {
+ rv = SSL_OptionSet(model_sock, SSL_REUSE_SERVER_ECDHE_KEY, (configureReuseECDHE > 0));
+ if (rv != SECSuccess) {
+ errExit("error configuring server side reuse of ECDHE key");
+ }
+ }
+
+ if (configureWeakDHE > -1) {
+ rv = SSL_EnableWeakDHEPrimeGroup(model_sock, (configureWeakDHE > 0));
+ if (rv != SECSuccess) {
+ errExit("error configuring weak DHE prime group");
+ }
+ }
+
+ if (enableExtendedMasterSecret) {
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_EXTENDED_MASTER_SECRET, PR_TRUE);
+ if (rv != SECSuccess) {
+ errExit("error enabling extended master secret ");
+ }
+ }
+
+ /* This uses the legacy certificate API. See mySSLSNISocketConfig() for the
+ * new, prefered API. */
+ for (i = 0; i < certNicknameIndex; i++) {
+ if (cert[i] != NULL) {
+ const SSLExtraServerCertData ocspData = {
+ ssl_auth_null, NULL, certStatus[i], NULL
+ };
+
+ secStatus = SSL_ConfigServerCert(model_sock, cert[i],
+ privKey[i], &ocspData,
+ sizeof(ocspData));
+ if (secStatus != SECSuccess)
+ errExit("SSL_ConfigServerCert");
+ }
+ }
+
+ if (bigBuf.data) { /* doing FDX */
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_FDX, 1);
+ if (rv < 0) {
+ errExit("SSL_OptionSet SSL_ENABLE_FDX");
+ }
+ }
+
+ if (NoReuse) {
+ rv = SSL_OptionSet(model_sock, SSL_NO_CACHE, 1);
+ if (rv < 0) {
+ errExit("SSL_OptionSet SSL_NO_CACHE");
+ }
+ }
+
+ if (zeroRTT) {
+ if (enabledVersions.max < SSL_LIBRARY_VERSION_TLS_1_3) {
+ errExit("You tried enabling 0RTT without enabling TLS 1.3!");
+ }
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_0RTT_DATA, PR_TRUE);
+ if (rv != SECSuccess) {
+ errExit("error enabling 0RTT ");
+ }
+ }
+
+ if (enableALPN) {
+ PRUint8 alpnVal[] = { 0x08,
+ 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 };
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_ALPN, PR_TRUE);
+ if (rv != SECSuccess) {
+ errExit("error enabling ALPN");
+ }
+
+ rv = SSL_SetNextProtoNego(model_sock, alpnVal, sizeof(alpnVal));
+ if (rv != SECSuccess) {
+ errExit("error enabling ALPN");
+ }
+ }
+
+ if (enabledGroups) {
+ rv = SSL_NamedGroupConfig(model_sock, enabledGroups, enabledGroupsCount);
+ if (rv < 0) {
+ errExit("SSL_NamedGroupConfig failed");
+ }
+ }
+
+ /* This cipher is not on by default. The Acceptance test
+ * would like it to be. Turn this cipher on.
+ */
+
+ secStatus = SSL_CipherPrefSetDefault(TLS_RSA_WITH_NULL_MD5, PR_TRUE);
+ if (secStatus != SECSuccess) {
+ errExit("SSL_CipherPrefSetDefault:TLS_RSA_WITH_NULL_MD5");
+ }
+
+ if (expectedHostNameVal) {
+ SSL_HandshakeCallback(model_sock, handshakeCallback,
+ (void *)expectedHostNameVal);
+ }
+
+ if (requestCert) {
+ SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate,
+ (void *)CERT_GetDefaultCertDB());
+ if (requestCert <= 2) {
+ rv = SSL_OptionSet(model_sock, SSL_REQUEST_CERTIFICATE, 1);
+ if (rv < 0) {
+ errExit("first SSL_OptionSet SSL_REQUEST_CERTIFICATE");
+ }
+ rv = SSL_OptionSet(model_sock, SSL_REQUIRE_CERTIFICATE,
+ (requestCert == 2));
+ if (rv < 0) {
+ errExit("first SSL_OptionSet SSL_REQUIRE_CERTIFICATE");
+ }
+ }
+ }
+
+ if (MakeCertOK)
+ SSL_BadCertHook(model_sock, myBadCertHandler, NULL);
+
+ /* end of ssl configuration. */
+
+ /* Now, do the accepting, here in the main thread. */
+ rv = do_accepts(listen_sock, model_sock, requestCert);
+
+ terminateWorkerThreads();
+
+ if (useModelSocket && model_sock) {
+ if (model_sock) {
+ PR_Close(model_sock);
+ }
+ }
+}
+
+SECStatus
+readBigFile(const char *fileName)
+{
+ PRFileInfo info;
+ PRStatus status;
+ SECStatus rv = SECFailure;
+ int count;
+ int hdrLen;
+ PRFileDesc *local_file_fd = NULL;
+
+ status = PR_GetFileInfo(fileName, &info);
+
+ if (status == PR_SUCCESS &&
+ info.type == PR_FILE_FILE &&
+ info.size > 0 &&
+ NULL != (local_file_fd = PR_Open(fileName, PR_RDONLY, 0))) {
+
+ hdrLen = PORT_Strlen(outHeader);
+ bigBuf.len = hdrLen + info.size;
+ bigBuf.data = PORT_Malloc(bigBuf.len + 4095);
+ if (!bigBuf.data) {
+ errWarn("PORT_Malloc");
+ goto done;
+ }
+
+ PORT_Memcpy(bigBuf.data, outHeader, hdrLen);
+
+ count = PR_Read(local_file_fd, bigBuf.data + hdrLen, info.size);
+ if (count != info.size) {
+ errWarn("PR_Read local file");
+ goto done;
+ }
+ rv = SECSuccess;
+ done:
+ if (local_file_fd) {
+ PR_Close(local_file_fd);
+ }
+ }
+ return rv;
+}
+
+int numChildren;
+PRProcess *child[MAX_PROCS];
+
+PRProcess *
+haveAChild(int argc, char **argv, PRProcessAttr *attr)
+{
+ PRProcess *newProcess;
+
+ newProcess = PR_CreateProcess(argv[0], argv, NULL, attr);
+ if (!newProcess) {
+ errWarn("Can't create new process.");
+ } else {
+ child[numChildren++] = newProcess;
+ }
+ return newProcess;
+}
+
+void
+beAGoodParent(int argc, char **argv, int maxProcs, PRFileDesc *listen_sock)
+{
+ PRProcess *newProcess;
+ PRProcessAttr *attr;
+ int i;
+ PRInt32 exitCode;
+ PRStatus rv;
+
+ rv = PR_SetFDInheritable(listen_sock, PR_TRUE);
+ if (rv != PR_SUCCESS)
+ errExit("PR_SetFDInheritable");
+
+ attr = PR_NewProcessAttr();
+ if (!attr)
+ errExit("PR_NewProcessAttr");
+
+ rv = PR_ProcessAttrSetInheritableFD(attr, listen_sock, inheritableSockName);
+ if (rv != PR_SUCCESS)
+ errExit("PR_ProcessAttrSetInheritableFD");
+
+ for (i = 0; i < maxProcs; ++i) {
+ newProcess = haveAChild(argc, argv, attr);
+ if (!newProcess)
+ break;
+ }
+
+ rv = PR_SetFDInheritable(listen_sock, PR_FALSE);
+ if (rv != PR_SUCCESS)
+ errExit("PR_SetFDInheritable");
+
+ while (numChildren > 0) {
+ newProcess = child[numChildren - 1];
+ PR_WaitProcess(newProcess, &exitCode);
+ fprintf(stderr, "Child %d exited with exit code %x\n",
+ numChildren, exitCode);
+ numChildren--;
+ }
+ exit(0);
+}
+
+#define HEXCHAR_TO_INT(c, i) \
+ if (((c) >= '0') && ((c) <= '9')) { \
+ i = (c) - '0'; \
+ } else if (((c) >= 'a') && ((c) <= 'f')) { \
+ i = (c) - 'a' + 10; \
+ } else if (((c) >= 'A') && ((c) <= 'F')) { \
+ i = (c) - 'A' + 10; \
+ } else if ((c) == '\0') { \
+ fprintf(stderr, "Invalid length of cipher string (-c :WXYZ).\n"); \
+ exit(9); \
+ } else { \
+ fprintf(stderr, "Non-hex char in cipher string (-c :WXYZ).\n"); \
+ exit(9); \
+ }
+
+SECStatus
+enableOCSPStapling(const char *mode)
+{
+ if (!strcmp(mode, "good")) {
+ ocspStaplingMode = osm_good;
+ return SECSuccess;
+ }
+ if (!strcmp(mode, "unknown")) {
+ ocspStaplingMode = osm_unknown;
+ return SECSuccess;
+ }
+ if (!strcmp(mode, "revoked")) {
+ ocspStaplingMode = osm_revoked;
+ return SECSuccess;
+ }
+ if (!strcmp(mode, "badsig")) {
+ ocspStaplingMode = osm_badsig;
+ return SECSuccess;
+ }
+ if (!strcmp(mode, "corrupted")) {
+ ocspStaplingMode = osm_corrupted;
+ return SECSuccess;
+ }
+ if (!strcmp(mode, "failure")) {
+ ocspStaplingMode = osm_failure;
+ return SECSuccess;
+ }
+ if (!strcmp(mode, "random")) {
+ ocspStaplingMode = osm_random;
+ return SECSuccess;
+ }
+ if (!strcmp(mode, "ocsp")) {
+ ocspStaplingMode = osm_ocsp;
+ return SECSuccess;
+ }
+ return SECFailure;
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progName = NULL;
+ const char *fileName = NULL;
+ char *cipherString = NULL;
+ const char *dir = ".";
+ char *passwd = NULL;
+ char *pwfile = NULL;
+ const char *pidFile = NULL;
+ char *tmp;
+ char *envString;
+ PRFileDesc *listen_sock;
+ CERTCertificate *cert[MAX_CERT_NICKNAME_ARRAY_INDEX] = { NULL };
+ SECKEYPrivateKey *privKey[MAX_CERT_NICKNAME_ARRAY_INDEX] = { NULL };
+ int optionsFound = 0;
+ int maxProcs = 1;
+ unsigned short port = 0;
+ SECStatus rv = SECSuccess;
+ PRStatus prStatus;
+ PRBool bindOnly = PR_FALSE;
+ PRBool useLocalThreads = PR_FALSE;
+ PLOptState *optstate;
+ PLOptStatus status;
+ PRThread *loggerThread = NULL;
+ PRBool debugCache = PR_FALSE; /* bug 90518 */
+ char emptyString[] = { "" };
+ char *certPrefix = emptyString;
+ SSL3Statistics *ssl3stats;
+ PRUint32 i;
+ secuPWData pwdata = { PW_NONE, 0 };
+ char *expectedHostNameVal = NULL;
+ PLArenaPool *certStatusArena = NULL;
+
+ tmp = strrchr(argv[0], '/');
+ tmp = tmp ? tmp + 1 : argv[0];
+ progName = strrchr(tmp, '\\');
+ progName = progName ? progName + 1 : tmp;
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions);
+
+ /* please keep this list of options in ASCII collating sequence.
+ ** numbers, then capital letters, then lower case, alphabetical.
+ ** XXX: 'B', 'E', 'q', and 'x' were used in the past but removed
+ ** in 3.28, please leave some time before resuing those. */
+ optstate = PL_CreateOptState(argc, argv,
+ "2:A:C:DGH:I:L:M:NP:QRS:T:U:V:W:YZa:bc:d:e:f:g:hi:jk:lmn:op:rst:uvw:yz");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ ++optionsFound;
+ switch (optstate->option) {
+ case '2':
+ fileName = optstate->value;
+ break;
+
+ case 'A':
+ ocspStaplingCA = PORT_Strdup(optstate->value);
+ break;
+
+ case 'C':
+ if (optstate->value)
+ NumSidCacheEntries = PORT_Atoi(optstate->value);
+ break;
+
+ case 'D':
+ noDelay = PR_TRUE;
+ break;
+ case 'H':
+ configureDHE = (PORT_Atoi(optstate->value) != 0);
+ break;
+
+ case 'G':
+ enableExtendedMasterSecret = PR_TRUE;
+ break;
+
+ case 'L':
+ logStats = PR_TRUE;
+ if (optstate->value == NULL) {
+ logPeriod = 30;
+ } else {
+ logPeriod = PORT_Atoi(optstate->value);
+ if (logPeriod <= 0)
+ logPeriod = 30;
+ }
+ break;
+
+ case 'M':
+ maxProcs = PORT_Atoi(optstate->value);
+ if (maxProcs < 1)
+ maxProcs = 1;
+ if (maxProcs > MAX_PROCS)
+ maxProcs = MAX_PROCS;
+ break;
+
+ case 'N':
+ NoReuse = PR_TRUE;
+ break;
+
+ case 'R':
+ disableRollBack = PR_TRUE;
+ break;
+
+ case 'S':
+ if (certNicknameIndex >= MAX_CERT_NICKNAME_ARRAY_INDEX) {
+ Usage(progName);
+ break;
+ }
+ certNicknameArray[certNicknameIndex++] = PORT_Strdup(optstate->value);
+ break;
+
+ case 'T':
+ if (enableOCSPStapling(optstate->value) != SECSuccess) {
+ fprintf(stderr, "Invalid OCSP stapling mode.\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(53);
+ }
+ break;
+
+ case 'U':
+ configureReuseECDHE = (PORT_Atoi(optstate->value) != 0);
+ break;
+
+ case 'V':
+ if (SECU_ParseSSLVersionRangeString(optstate->value,
+ enabledVersions, &enabledVersions) !=
+ SECSuccess) {
+ Usage(progName);
+ }
+ break;
+
+ case 'W':
+ configureWeakDHE = (PORT_Atoi(optstate->value) != 0);
+ break;
+
+ case 'Y':
+ PrintCipherUsage(progName);
+ exit(0);
+ break;
+
+ case 'a':
+ if (virtServerNameIndex >= MAX_VIRT_SERVER_NAME_ARRAY_INDEX) {
+ Usage(progName);
+ break;
+ }
+ virtServerNameArray[virtServerNameIndex++] =
+ PORT_Strdup(optstate->value);
+ break;
+
+ case 'b':
+ bindOnly = PR_TRUE;
+ break;
+
+ case 'c':
+ cipherString = PORT_Strdup(optstate->value);
+ break;
+
+ case 'd':
+ dir = optstate->value;
+ break;
+
+#ifndef NSS_DISABLE_ECC
+ case 'e':
+ if (certNicknameIndex >= MAX_CERT_NICKNAME_ARRAY_INDEX) {
+ Usage(progName);
+ break;
+ }
+ certNicknameArray[certNicknameIndex++] = PORT_Strdup(optstate->value);
+ break;
+#endif /* NSS_DISABLE_ECC */
+
+ case 'f':
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = pwfile = PORT_Strdup(optstate->value);
+ break;
+
+ case 'g':
+ testBulk = PR_TRUE;
+ testBulkTotal = PORT_Atoi(optstate->value);
+ break;
+
+ case 'h':
+ Usage(progName);
+ exit(0);
+ break;
+
+ case 'i':
+ pidFile = optstate->value;
+ break;
+
+ case 'j':
+ initLoggingLayer();
+ loggingLayer = PR_TRUE;
+ break;
+
+ case 'k':
+ expectedHostNameVal = PORT_Strdup(optstate->value);
+ break;
+
+ case 'l':
+ useLocalThreads = PR_TRUE;
+ break;
+
+ case 'm':
+ useModelSocket = PR_TRUE;
+ break;
+
+ case 'n':
+ if (certNicknameIndex >= MAX_CERT_NICKNAME_ARRAY_INDEX) {
+ Usage(progName);
+ break;
+ }
+ certNicknameArray[certNicknameIndex++] = PORT_Strdup(optstate->value);
+ virtServerNameArray[0] = PORT_Strdup(optstate->value);
+ break;
+
+ case 'P':
+ certPrefix = PORT_Strdup(optstate->value);
+ break;
+
+ case 'o':
+ MakeCertOK = 1;
+ break;
+
+ case 'p':
+ port = PORT_Atoi(optstate->value);
+ break;
+
+ case 'r':
+ ++requestCert;
+ break;
+
+ case 's':
+ disableLocking = PR_TRUE;
+ break;
+
+ case 't':
+ maxThreads = PORT_Atoi(optstate->value);
+ if (maxThreads > MAX_THREADS)
+ maxThreads = MAX_THREADS;
+ if (maxThreads < MIN_THREADS)
+ maxThreads = MIN_THREADS;
+ break;
+
+ case 'u':
+ enableSessionTickets = PR_TRUE;
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ case 'w':
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = passwd = PORT_Strdup(optstate->value);
+ break;
+
+ case 'y':
+ debugCache = PR_TRUE;
+ break;
+
+ case 'z':
+ enableCompression = PR_TRUE;
+ break;
+
+ case 'Z':
+ zeroRTT = PR_TRUE;
+ break;
+
+ case 'Q':
+ enableALPN = PR_TRUE;
+ break;
+
+ case 'I':
+ rv = parseGroupList(optstate->value, &enabledGroups, &enabledGroupsCount);
+ if (rv != SECSuccess) {
+ PL_DestroyOptState(optstate);
+ fprintf(stderr, "Bad group specified.\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(5);
+ }
+ break;
+
+ default:
+ case '?':
+ fprintf(stderr, "Unrecognized or bad option specified.\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(4);
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+ if (status == PL_OPT_BAD) {
+ fprintf(stderr, "Unrecognized or bad option specified.\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(5);
+ }
+ if (!optionsFound) {
+ Usage(progName);
+ exit(51);
+ }
+ switch (ocspStaplingMode) {
+ case osm_good:
+ case osm_revoked:
+ case osm_unknown:
+ case osm_random:
+ if (!ocspStaplingCA) {
+ fprintf(stderr, "Selected stapling response requires the -A parameter.\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(52);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* The -b (bindOnly) option is only used by the ssl.sh test
+ * script on Linux to determine whether a previous selfserv
+ * process has fully died and freed the port. (Bug 129701)
+ */
+ if (bindOnly) {
+ listen_sock = getBoundListenSocket(port);
+ if (!listen_sock) {
+ exit(1);
+ }
+ if (listen_sock) {
+ PR_Close(listen_sock);
+ }
+ exit(0);
+ }
+
+ if (certNicknameIndex == 0) {
+ fprintf(stderr, "Must specify at least one certificate nickname using '-n' (RSA), '-S' (DSA), or 'e' (EC).\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(6);
+ }
+
+ if (port == 0) {
+ fprintf(stderr, "Required argument 'port' must be non-zero value\n");
+ exit(7);
+ }
+
+ if (NoReuse && maxProcs > 1) {
+ fprintf(stderr, "-M and -N options are mutually exclusive.\n");
+ exit(14);
+ }
+
+ if (pidFile) {
+ FILE *tmpfile = fopen(pidFile, "w+");
+
+ if (tmpfile) {
+ fprintf(tmpfile, "%d", getpid());
+ fclose(tmpfile);
+ }
+ }
+
+ /* allocate and initialize app data for bulk encryption testing */
+ if (testBulk) {
+ testBulkBuf = PORT_Malloc(testBulkSize);
+ if (testBulkBuf == NULL)
+ errExit("Out of memory: testBulkBuf");
+ for (i = 0; i < testBulkSize; i++)
+ testBulkBuf[i] = i;
+ }
+
+ envString = PR_GetEnvSecure(envVarName);
+ tmp = PR_GetEnvSecure("TMP");
+ if (!tmp)
+ tmp = PR_GetEnvSecure("TMPDIR");
+ if (!tmp)
+ tmp = PR_GetEnvSecure("TEMP");
+ if (envString) {
+ /* we're one of the children in a multi-process server. */
+ listen_sock = PR_GetInheritedFD(inheritableSockName);
+ if (!listen_sock)
+ errExit("PR_GetInheritedFD");
+#ifndef WINNT
+ /* we can't do this on NT because it breaks NSPR and
+ PR_Accept will fail on the socket in the child process if
+ the socket state is change to non inheritable
+ It is however a security issue to leave it accessible,
+ but it is OK for a test server such as selfserv.
+ NSPR should fix it eventually . see bugzilla 101617
+ and 102077
+ */
+ prStatus = PR_SetFDInheritable(listen_sock, PR_FALSE);
+ if (prStatus != PR_SUCCESS)
+ errExit("PR_SetFDInheritable");
+#endif
+ rv = SSL_InheritMPServerSIDCache(envString);
+ if (rv != SECSuccess)
+ errExit("SSL_InheritMPServerSIDCache");
+ hasSidCache = PR_TRUE;
+ } else if (maxProcs > 1) {
+ /* we're going to be the parent in a multi-process server. */
+ listen_sock = getBoundListenSocket(port);
+ rv = SSL_ConfigMPServerSIDCache(NumSidCacheEntries, 0, 0, tmp);
+ if (rv != SECSuccess)
+ errExit("SSL_ConfigMPServerSIDCache");
+ hasSidCache = PR_TRUE;
+ beAGoodParent(argc, argv, maxProcs, listen_sock);
+ exit(99); /* should never get here */
+ } else {
+ /* we're an ordinary single process server. */
+ listen_sock = getBoundListenSocket(port);
+ prStatus = PR_SetFDInheritable(listen_sock, PR_FALSE);
+ if (prStatus != PR_SUCCESS)
+ errExit("PR_SetFDInheritable");
+ if (!NoReuse) {
+ rv = SSL_ConfigServerSessionIDCache(NumSidCacheEntries,
+ 0, 0, tmp);
+ if (rv != SECSuccess)
+ errExit("SSL_ConfigServerSessionIDCache");
+ hasSidCache = PR_TRUE;
+ }
+ }
+
+ lm = PR_NewLogModule("TestCase");
+
+ if (fileName)
+ readBigFile(fileName);
+
+ /* set our password function */
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ /* Call the NSS initialization routines */
+ rv = NSS_Initialize(dir, certPrefix, certPrefix, SECMOD_DB, NSS_INIT_READONLY);
+ if (rv != SECSuccess) {
+ fputs("NSS_Init failed.\n", stderr);
+ exit(8);
+ }
+
+ /* all SSL3 cipher suites are enabled by default. */
+ if (cipherString) {
+ char *cstringSaved = cipherString;
+ int ndx;
+
+ /* disable all the ciphers, then enable the ones we want. */
+ disableAllSSLCiphers();
+
+ while (0 != (ndx = *cipherString++)) {
+ int cipher = 0;
+
+ if (ndx == ':') {
+ int ctmp;
+
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= (ctmp << 12);
+ cipherString++;
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= (ctmp << 8);
+ cipherString++;
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= (ctmp << 4);
+ cipherString++;
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= ctmp;
+ cipherString++;
+ } else {
+ if (!isalpha(ndx)) {
+ fprintf(stderr,
+ "Non-alphabetic char in cipher string (-c arg).\n");
+ exit(9);
+ }
+ ndx = tolower(ndx) - 'a';
+ if (ndx < PR_ARRAY_SIZE(ssl3CipherSuites)) {
+ cipher = ssl3CipherSuites[ndx];
+ }
+ }
+ if (cipher > 0) {
+ SECStatus status;
+ status = SSL_CipherPrefSetDefault(cipher, SSL_ALLOWED);
+ if (status != SECSuccess)
+ SECU_PrintError(progName, "SSL_CipherPrefSet()");
+ } else {
+ fprintf(stderr,
+ "Invalid cipher specification (-c arg).\n");
+ exit(9);
+ }
+ }
+ PORT_Free(cstringSaved);
+ }
+
+ certStatusArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!certStatusArena)
+ errExit("cannot allocate certStatusArena");
+
+ for (i = 0; i < certNicknameIndex; i++) {
+ cert[i] = PK11_FindCertFromNickname(certNicknameArray[i], &pwdata);
+ if (cert[i] == NULL) {
+ fprintf(stderr, "selfserv: Can't find certificate %s\n", certNicknameArray[i]);
+ exit(10);
+ }
+ privKey[i] = PK11_FindKeyByAnyCert(cert[i], &pwdata);
+ if (privKey[i] == NULL) {
+ fprintf(stderr, "selfserv: Can't find Private Key for cert %s\n",
+ certNicknameArray[i]);
+ exit(11);
+ }
+#ifdef NSS_DISABLE_ECC
+ if (privKey[i]->keyType != ecKey)
+#endif
+ setupCertStatus(certStatusArena, ocspStaplingMode, cert[i], i, &pwdata);
+ }
+
+ if (configureWeakDHE > 0) {
+ fprintf(stderr, "selfserv: Creating dynamic weak DH parameters\n");
+ rv = SSL_EnableWeakDHEPrimeGroup(NULL, PR_TRUE);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ fprintf(stderr, "selfserv: Done creating dynamic weak DH parameters\n");
+ }
+
+ /* allocate the array of thread slots, and launch the worker threads. */
+ rv = launch_threads(&jobLoop, 0, 0, requestCert, useLocalThreads);
+
+ if (rv == SECSuccess && logStats) {
+ loggerThread = PR_CreateThread(PR_SYSTEM_THREAD,
+ logger, NULL, PR_PRIORITY_NORMAL,
+ useLocalThreads ? PR_LOCAL_THREAD
+ : PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD, 0);
+ if (loggerThread == NULL) {
+ fprintf(stderr, "selfserv: Failed to launch logger thread!\n");
+ rv = SECFailure;
+ }
+ }
+
+ if (rv == SECSuccess) {
+ server_main(listen_sock, requestCert, privKey, cert,
+ expectedHostNameVal);
+ }
+
+ VLOG(("selfserv: server_thread: exiting"));
+
+cleanup:
+ printSSLStatistics();
+ ssl3stats = SSL_GetStatistics();
+ if (ssl3stats->hch_sid_ticket_parse_failures != 0) {
+ fprintf(stderr, "selfserv: Experienced ticket parse failure(s)\n");
+ exit(1);
+ }
+ if (failedToNegotiateName) {
+ fprintf(stderr, "selfserv: Failed properly negotiate server name\n");
+ exit(1);
+ }
+
+ {
+ int i;
+ for (i = 0; i < certNicknameIndex; i++) {
+ if (cert[i]) {
+ CERT_DestroyCertificate(cert[i]);
+ }
+ if (privKey[i]) {
+ SECKEY_DestroyPrivateKey(privKey[i]);
+ }
+ PORT_Free(certNicknameArray[i]);
+ }
+ for (i = 0; virtServerNameArray[i]; i++) {
+ PORT_Free(virtServerNameArray[i]);
+ }
+ }
+
+ if (debugCache) {
+ nss_DumpCertificateCacheInfo();
+ }
+ if (expectedHostNameVal) {
+ PORT_Free(expectedHostNameVal);
+ }
+ if (passwd) {
+ PORT_Free(passwd);
+ }
+ if (pwfile) {
+ PORT_Free(pwfile);
+ }
+ if (certPrefix && certPrefix != emptyString) {
+ PORT_Free(certPrefix);
+ }
+
+ if (hasSidCache) {
+ SSL_ShutdownServerSessionIDCache();
+ }
+ if (certStatusArena) {
+ PORT_FreeArena(certStatusArena, PR_FALSE);
+ }
+ if (enabledGroups) {
+ PORT_Free(enabledGroups);
+ }
+ if (NSS_Shutdown() != SECSuccess) {
+ SECU_PrintError(progName, "NSS_Shutdown");
+ if (loggerThread) {
+ PR_JoinThread(loggerThread);
+ }
+ PR_Cleanup();
+ exit(1);
+ }
+ PR_Cleanup();
+ printf("selfserv: normal termination\n");
+ return 0;
+}
diff --git a/security/nss/cmd/selfserv/selfserv.gyp b/security/nss/cmd/selfserv/selfserv.gyp
new file mode 100644
index 000000000..783be845e
--- /dev/null
+++ b/security/nss/cmd/selfserv/selfserv.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'selfserv',
+ 'type': 'executable',
+ 'sources': [
+ 'selfserv.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/shlibsign/Makefile b/security/nss/cmd/shlibsign/Makefile
new file mode 100644
index 000000000..83f90faa0
--- /dev/null
+++ b/security/nss/cmd/shlibsign/Makefile
@@ -0,0 +1,99 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+ifeq ($(OS_ARCH), WINNT)
+
+EXTRA_LIBS += \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.$(LIB_SUFFIX) \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.$(LIB_SUFFIX) \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.$(LIB_SUFFIX) \
+ $(NULL)
+
+else
+
+EXTRA_SHARED_LIBS += \
+ -L$(NSPR_LIB_DIR) \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4 \
+ $(NULL)
+
+endif
+
+
+# sign any and all shared libraries that contain the word freebl
+ifeq ($(NSS_BUILD_WITHOUT_SOFTOKEN),1)
+CHECKLIBS =
+CHECKLOC =
+else
+CHECKLIBS = $(DIST)/lib/$(DLL_PREFIX)softokn3.$(DLL_SUFFIX)
+CHECKLIBS += $(wildcard $(DIST)/lib/$(DLL_PREFIX)freebl*3.$(DLL_SUFFIX))
+ifndef NSS_DISABLE_DBM
+CHECKLIBS += $(DIST)/lib/$(DLL_PREFIX)nssdbm3.$(DLL_SUFFIX)
+endif
+CHECKLOC = $(CHECKLIBS:.$(DLL_SUFFIX)=.chk)
+
+MD_LIB_RELEASE_FILES = $(CHECKLOC)
+ALL_TRASH += $(CHECKLOC)
+endif
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
+SRCDIR = $(call core_abspath,.)
+
+%.chk: %.$(DLL_SUFFIX)
+ifeq ($(OS_TARGET), OS2)
+ cd $(OBJDIR) ; cmd.exe /c $(SRCDIR)/sign.cmd $(DIST) \
+ $(call core_abspath,$(OBJDIR)) $(OS_TARGET) \
+ $(call core_abspath,$(NSPR_LIB_DIR)) $(call core_abspath,$<)
+else
+ ifeq ($(CROSS_COMPILE),1)
+ # do nothing
+ else
+ cd $(OBJDIR) ; sh $(SRCDIR)/sign.sh $(call core_abspath,$(DIST)) \
+ $(call core_abspath,$(OBJDIR)) $(OS_TARGET) \
+ $(call core_abspath,$(NSPR_LIB_DIR)) $(call core_abspath,$<)
+ endif
+endif
+
+libs install :: $(CHECKLOC)
+
diff --git a/security/nss/cmd/shlibsign/mangle/Makefile b/security/nss/cmd/shlibsign/mangle/Makefile
new file mode 100644
index 000000000..b52243e01
--- /dev/null
+++ b/security/nss/cmd/shlibsign/mangle/Makefile
@@ -0,0 +1,65 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+ifeq ($(OS_ARCH), WINNT)
+
+EXTRA_LIBS += \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.$(LIB_SUFFIX) \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.$(LIB_SUFFIX) \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.$(LIB_SUFFIX) \
+ $(NULL)
+
+else
+
+EXTRA_SHARED_LIBS += \
+ -L$(NSPR_LIB_DIR) \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4 \
+ $(NULL)
+
+endif
+
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../../platrules.mk
+
diff --git a/security/nss/cmd/shlibsign/mangle/mangle.c b/security/nss/cmd/shlibsign/mangle/mangle.c
new file mode 100644
index 000000000..e58bbee41
--- /dev/null
+++ b/security/nss/cmd/shlibsign/mangle/mangle.c
@@ -0,0 +1,140 @@
+/* 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/. */
+
+/*
+ * Test program to mangle 1 bit in a binary
+ */
+
+#include "nspr.h"
+#include "plstr.h"
+#include "plgetopt.h"
+#include "prio.h"
+
+static PRFileDesc *pr_stderr;
+static void
+usage(char *program_name)
+{
+
+ PR_fprintf(pr_stderr, "Usage:");
+ PR_fprintf(pr_stderr, "%s -i shared_library_name -o byte_offset -b bit\n", program_name);
+}
+
+int
+main(int argc, char **argv)
+{
+ /* buffers and locals */
+ PLOptState *optstate;
+ char *programName;
+ char cbuf;
+
+ /* parameter set variables */
+ const char *libFile = NULL;
+ int bitOffset = -1;
+
+ /* return values */
+ int retval = 2; /* 0 - test succeeded.
+ * 1 - illegal args
+ * 2 - function failed */
+ PRFileDesc *fd = NULL;
+ int bytesRead;
+ int bytesWritten;
+ PROffset32 offset = -1;
+ PROffset32 pos;
+
+ programName = PL_strrchr(argv[0], '/');
+ programName = programName ? (programName + 1) : argv[0];
+
+ pr_stderr = PR_STDERR;
+
+ optstate = PL_CreateOptState(argc, argv, "i:o:b:");
+ if (optstate == NULL) {
+ return 1;
+ }
+
+ while (PL_GetNextOpt(optstate) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'i':
+ libFile = optstate->value;
+ break;
+
+ case 'o':
+ offset = atoi(optstate->value);
+ break;
+
+ case 'b':
+ bitOffset = atoi(optstate->value);
+ break;
+ }
+ }
+
+ if (libFile == NULL) {
+ usage(programName);
+ return 1;
+ }
+ if ((bitOffset >= 8) || (bitOffset < 0)) {
+ usage(programName);
+ return 1;
+ }
+
+ /* open the target signature file */
+ fd = PR_OpenFile(libFile, PR_RDWR, 0666);
+ if (fd == NULL) {
+ /* lperror(libFile); */
+ PR_fprintf(pr_stderr, "Couldn't Open %s\n", libFile);
+ goto loser;
+ }
+
+ if (offset < 0) { /* convert to positive offset */
+ pos = PR_Seek(fd, offset, PR_SEEK_END);
+ if (pos == -1) {
+ PR_fprintf(pr_stderr, "Seek for read on %s (to %d) failed\n",
+ libFile, offset);
+ goto loser;
+ }
+ offset = pos;
+ }
+
+ /* read the byte */
+ pos = PR_Seek(fd, offset, PR_SEEK_SET);
+ if (pos != offset) {
+ PR_fprintf(pr_stderr, "Seek for read on %s (to %d) failed\n",
+ libFile, offset);
+ goto loser;
+ }
+ bytesRead = PR_Read(fd, &cbuf, 1);
+ if (bytesRead != 1) {
+ PR_fprintf(pr_stderr, "Read on %s (to %d) failed\n", libFile, offset);
+ goto loser;
+ }
+
+ PR_fprintf(pr_stderr, "Changing byte 0x%08x (%d): from %02x (%d) to ",
+ offset, offset, (unsigned char)cbuf, (unsigned char)cbuf);
+ /* change it */
+ cbuf ^= 1 << bitOffset;
+ PR_fprintf(pr_stderr, "%02x (%d)\n",
+ (unsigned char)cbuf, (unsigned char)cbuf);
+
+ /* write it back out */
+ pos = PR_Seek(fd, offset, PR_SEEK_SET);
+ if (pos != offset) {
+ PR_fprintf(pr_stderr, "Seek for write on %s (to %d) failed\n",
+ libFile, offset);
+ goto loser;
+ }
+ bytesWritten = PR_Write(fd, &cbuf, 1);
+ if (bytesWritten != 1) {
+ PR_fprintf(pr_stderr, "Write on %s (to %d) failed\n", libFile, offset);
+ goto loser;
+ }
+
+ retval = 0;
+
+loser:
+ if (fd)
+ PR_Close(fd);
+ PR_Cleanup();
+ return retval;
+}
+
+/*#DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" */
diff --git a/security/nss/cmd/shlibsign/mangle/mangle.gyp b/security/nss/cmd/shlibsign/mangle/mangle.gyp
new file mode 100644
index 000000000..1dd5c10d7
--- /dev/null
+++ b/security/nss/cmd/shlibsign/mangle/mangle.gyp
@@ -0,0 +1,31 @@
+# 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/.
+{
+ 'includes': [
+ '../../../coreconf/config.gypi',
+ '../../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'mangle',
+ 'type': 'executable',
+ 'sources': [
+ 'mangle.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'SHLIB_SUFFIX=\"<(dll_suffix)\"',
+ 'SHLIB_PREFIX=\"<(dll_prefix)\"'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss',
+ 'use_static_libs': 1
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/shlibsign/mangle/manifest.mn b/security/nss/cmd/shlibsign/mangle/manifest.mn
new file mode 100644
index 000000000..40b4841cb
--- /dev/null
+++ b/security/nss/cmd/shlibsign/mangle/manifest.mn
@@ -0,0 +1,24 @@
+#
+# 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/.
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\"
+
+CSRCS = \
+ mangle.c \
+ $(NULL)
+
+
+# headers for the MODULE (defined above) are implicitly required.
+REQUIRES =
+
+PROGRAM = mangle
+
+USE_STATIC_LIBS = 1
+
diff --git a/security/nss/cmd/shlibsign/manifest.mn b/security/nss/cmd/shlibsign/manifest.mn
new file mode 100644
index 000000000..95f8765b3
--- /dev/null
+++ b/security/nss/cmd/shlibsign/manifest.mn
@@ -0,0 +1,27 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\"
+
+CSRCS = \
+ shlibsign.c \
+ $(NULL)
+
+# WINNT uses EXTRA_LIBS as the list of libs to link in.
+# Unix uses OS_LIBS for that purpose.
+# We can solve this via conditional makefile code, but
+# can't do this in manifest.mn because OS_ARCH isn't defined there.
+# So, look in the local Makefile for the defines for the list of libs.
+
+PROGRAM = shlibsign
+
+DIRS = mangle
+
+#USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/shlibsign/shlibsign.c b/security/nss/cmd/shlibsign/shlibsign.c
new file mode 100644
index 000000000..d93fc422d
--- /dev/null
+++ b/security/nss/cmd/shlibsign/shlibsign.c
@@ -0,0 +1,1332 @@
+/* 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/. */
+
+/*
+ * shlibsign creates the checksum (.chk) files for the NSS libraries,
+ * libsoftokn3/softokn3 and libfreebl/freebl (platforms can have
+ * multiple freebl variants), that contain the NSS cryptograhic boundary.
+ *
+ * The generated .chk files must be put in the same directory as
+ * the NSS libraries they were generated for.
+ *
+ * When in FIPS 140 mode, the NSS Internal FIPS PKCS #11 Module will
+ * compute the checksum for the NSS cryptographic boundary libraries
+ * and compare the checksum with the value in .chk file.
+ */
+
+#ifdef XP_UNIX
+#define USES_LINKS 1
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#ifdef USES_LINKS
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+/* nspr headers */
+#include "prlink.h"
+#include "prprf.h"
+#include "prenv.h"
+#include "plgetopt.h"
+#include "prinit.h"
+#include "prmem.h"
+#include "plstr.h"
+#include "prerror.h"
+
+/* softoken headers */
+#include "pkcs11.h"
+#include "pkcs11t.h"
+
+/* freebl headers */
+#include "shsign.h"
+
+#define NUM_ELEM(array) (sizeof(array) / sizeof(array[0]))
+CK_BBOOL true = CK_TRUE;
+CK_BBOOL false = CK_FALSE;
+static PRBool verbose = PR_FALSE;
+
+static void
+usage(const char *program_name)
+{
+ PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
+ PR_fprintf(debug_out,
+ "type %s -H for more detail information.\n", program_name);
+ PR_fprintf(debug_out,
+ "Usage: %s [-v] [-V] [-o outfile] [-d dbdir] [-f pwfile]\n"
+ " [-F] [-p pwd] -[P dbprefix ] "
+ "-i shared_library_name\n",
+ program_name);
+ exit(1);
+}
+
+static void
+long_usage(const char *program_name)
+{
+ PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
+ PR_fprintf(debug_out, "%s test program usage:\n", program_name);
+ PR_fprintf(debug_out, "\t-i <infile> shared_library_name to process\n");
+ PR_fprintf(debug_out, "\t-o <outfile> checksum outfile\n");
+ PR_fprintf(debug_out, "\t-d <path> database path location\n");
+ PR_fprintf(debug_out, "\t-P <prefix> database prefix\n");
+ PR_fprintf(debug_out, "\t-f <file> password File : echo pw > file \n");
+ PR_fprintf(debug_out, "\t-F FIPS mode\n");
+ PR_fprintf(debug_out, "\t-p <pwd> password\n");
+ PR_fprintf(debug_out, "\t-v verbose output\n");
+ PR_fprintf(debug_out, "\t-V perform Verify operations\n");
+ PR_fprintf(debug_out, "\t-? short help message\n");
+ PR_fprintf(debug_out, "\t-h short help message\n");
+ PR_fprintf(debug_out, "\t-H this help message\n");
+ PR_fprintf(debug_out, "\n\n\tNote: Use of FIPS mode requires your ");
+ PR_fprintf(debug_out, "library path is using \n");
+ PR_fprintf(debug_out, "\t pre-existing libraries with generated ");
+ PR_fprintf(debug_out, "checksum files\n");
+ PR_fprintf(debug_out, "\t and database in FIPS mode \n");
+ exit(1);
+}
+
+static char *
+mkoutput(const char *input)
+{
+ int in_len = strlen(input);
+ char *output = PR_Malloc(in_len + sizeof(SGN_SUFFIX));
+ int index = in_len + 1 - sizeof("." SHLIB_SUFFIX);
+
+ if ((index > 0) &&
+ (PL_strncmp(&input[index],
+ "." SHLIB_SUFFIX, sizeof("." SHLIB_SUFFIX)) == 0)) {
+ in_len = index;
+ }
+ memcpy(output, input, in_len);
+ memcpy(&output[in_len], SGN_SUFFIX, sizeof(SGN_SUFFIX));
+ return output;
+}
+
+static void
+lperror(const char *string)
+{
+ PRErrorCode errorcode;
+
+ errorcode = PR_GetError();
+ PR_fprintf(PR_STDERR, "%s: %d: %s\n", string, errorcode,
+ PR_ErrorToString(errorcode, PR_LANGUAGE_I_DEFAULT));
+}
+
+static void
+encodeInt(unsigned char *buf, int val)
+{
+ buf[3] = (val >> 0) & 0xff;
+ buf[2] = (val >> 8) & 0xff;
+ buf[1] = (val >> 16) & 0xff;
+ buf[0] = (val >> 24) & 0xff;
+ return;
+}
+
+static PRStatus
+writeItem(PRFileDesc *fd, CK_VOID_PTR pValue,
+ CK_ULONG ulValueLen, char *file)
+{
+ unsigned char buf[4];
+ int bytesWritten;
+ if (ulValueLen == 0) {
+ PR_fprintf(PR_STDERR, "call to writeItem with 0 bytes of data.\n");
+ return PR_FAILURE;
+ }
+
+ encodeInt(buf, ulValueLen);
+ bytesWritten = PR_Write(fd, buf, 4);
+ if (bytesWritten != 4) {
+ lperror(file);
+ return PR_FAILURE;
+ }
+ bytesWritten = PR_Write(fd, pValue, ulValueLen);
+ if (bytesWritten != ulValueLen) {
+ lperror(file);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+static const unsigned char prime[] = { 0x00,
+ 0x97, 0x44, 0x1d, 0xcc, 0x0d, 0x39, 0x0d, 0x8d,
+ 0xcb, 0x75, 0xdc, 0x24, 0x25, 0x6f, 0x01, 0x92,
+ 0xa1, 0x11, 0x07, 0x6b, 0x70, 0xac, 0x73, 0xd7,
+ 0x82, 0x28, 0xdf, 0xab, 0x82, 0x0c, 0x41, 0x0c,
+ 0x95, 0xb3, 0x3c, 0x3d, 0xea, 0x8a, 0xe6, 0x44,
+ 0x0a, 0xb8, 0xab, 0x90, 0x15, 0x41, 0x11, 0xe8,
+ 0x48, 0x7b, 0x8d, 0xb0, 0x9c, 0xd3, 0xf2, 0x69,
+ 0x66, 0xff, 0x66, 0x4b, 0x70, 0x2b, 0xbf, 0xfb,
+ 0xd6, 0x68, 0x85, 0x76, 0x1e, 0x34, 0xaa, 0xc5,
+ 0x57, 0x6e, 0x23, 0x02, 0x08, 0x60, 0x6e, 0xfd,
+ 0x67, 0x76, 0xe1, 0x7c, 0xc8, 0xcb, 0x51, 0x77,
+ 0xcf, 0xb1, 0x3b, 0x00, 0x2e, 0xfa, 0x21, 0xcd,
+ 0x34, 0x76, 0x75, 0x01, 0x19, 0xfe, 0xf8, 0x5d,
+ 0x43, 0xc5, 0x34, 0xf3, 0x7a, 0x95, 0xdc, 0xc2,
+ 0x58, 0x07, 0x19, 0x2f, 0x1d, 0x6f, 0x9a, 0x77,
+ 0x7e, 0x55, 0xaa, 0xe7, 0x5a, 0x50, 0x43, 0xd3 };
+
+static const unsigned char subprime[] = { 0x0,
+ 0xd8, 0x16, 0x23, 0x34, 0x8a, 0x9e, 0x3a, 0xf5,
+ 0xd9, 0x10, 0x13, 0x35, 0xaa, 0xf3, 0xf3, 0x54,
+ 0x0b, 0x31, 0x24, 0xf1 };
+
+static const unsigned char base[] = {
+ 0x03, 0x3a, 0xad, 0xfa, 0x3a, 0x0c, 0xea, 0x0a,
+ 0x4e, 0x43, 0x32, 0x92, 0xbb, 0x87, 0xf1, 0x11,
+ 0xc0, 0xad, 0x39, 0x38, 0x56, 0x1a, 0xdb, 0x23,
+ 0x66, 0xb1, 0x08, 0xda, 0xb6, 0x19, 0x51, 0x42,
+ 0x93, 0x4f, 0xc3, 0x44, 0x43, 0xa8, 0x05, 0xc1,
+ 0xf8, 0x71, 0x62, 0x6f, 0x3d, 0xe2, 0xab, 0x6f,
+ 0xd7, 0x80, 0x22, 0x6f, 0xca, 0x0d, 0xf6, 0x9f,
+ 0x45, 0x27, 0x83, 0xec, 0x86, 0x0c, 0xda, 0xaa,
+ 0xd6, 0xe0, 0xd0, 0x84, 0xfd, 0xb1, 0x4f, 0xdc,
+ 0x08, 0xcd, 0x68, 0x3a, 0x77, 0xc2, 0xc5, 0xf1,
+ 0x99, 0x0f, 0x15, 0x1b, 0x6a, 0x8c, 0x3d, 0x18,
+ 0x2b, 0x6f, 0xdc, 0x2b, 0xd8, 0xb5, 0x9b, 0xb8,
+ 0x2d, 0x57, 0x92, 0x1c, 0x46, 0x27, 0xaf, 0x6d,
+ 0xe1, 0x45, 0xcf, 0x0b, 0x3f, 0xfa, 0x07, 0xcc,
+ 0x14, 0x8e, 0xe7, 0xb8, 0xaa, 0xd5, 0xd1, 0x36,
+ 0x1d, 0x7e, 0x5e, 0x7d, 0xfa, 0x5b, 0x77, 0x1f
+};
+
+/*
+ * The constants h, seed, & counter aren't used in the code; they're provided
+ * here (commented-out) so that human readers can verify that our our PQG
+ * parameters were generated properly.
+static const unsigned char h[] = {
+ 0x41, 0x87, 0x47, 0x79, 0xd8, 0xba, 0x4e, 0xac,
+ 0x44, 0x4f, 0x6b, 0xd2, 0x16, 0x5e, 0x04, 0xc6,
+ 0xc2, 0x29, 0x93, 0x5e, 0xbd, 0xc7, 0xa9, 0x8f,
+ 0x23, 0xa1, 0xc8, 0xee, 0x80, 0x64, 0xd5, 0x67,
+ 0x3c, 0xba, 0x59, 0x9a, 0x06, 0x0c, 0xcc, 0x29,
+ 0x56, 0xc0, 0xb2, 0x21, 0xe0, 0x5b, 0x52, 0xcd,
+ 0x84, 0x73, 0x57, 0xfd, 0xd8, 0xc3, 0x5b, 0x13,
+ 0x54, 0xd7, 0x4a, 0x06, 0x86, 0x63, 0x09, 0xa5,
+ 0xb0, 0x59, 0xe2, 0x32, 0x9e, 0x09, 0xa3, 0x9f,
+ 0x49, 0x62, 0xcc, 0xa6, 0xf9, 0x54, 0xd5, 0xb2,
+ 0xc3, 0x08, 0x71, 0x7e, 0xe3, 0x37, 0x50, 0xd6,
+ 0x7b, 0xa7, 0xc2, 0x60, 0xc1, 0xeb, 0x51, 0x32,
+ 0xfa, 0xad, 0x35, 0x25, 0x17, 0xf0, 0x7f, 0x23,
+ 0xe5, 0xa8, 0x01, 0x52, 0xcf, 0x2f, 0xd9, 0xa9,
+ 0xf6, 0x00, 0x21, 0x15, 0xf1, 0xf7, 0x70, 0xb7,
+ 0x57, 0x8a, 0xd0, 0x59, 0x6a, 0x82, 0xdc, 0x9c };
+
+static const unsigned char seed[] = { 0x00,
+ 0xcc, 0x4c, 0x69, 0x74, 0xf6, 0x72, 0x24, 0x68,
+ 0x24, 0x4f, 0xd7, 0x50, 0x11, 0x40, 0x81, 0xed,
+ 0x19, 0x3c, 0x8a, 0x25, 0xbc, 0x78, 0x0a, 0x85,
+ 0x82, 0x53, 0x70, 0x20, 0xf6, 0x54, 0xa5, 0x1b,
+ 0xf4, 0x15, 0xcd, 0xff, 0xc4, 0x88, 0xa7, 0x9d,
+ 0xf3, 0x47, 0x1c, 0x0a, 0xbe, 0x10, 0x29, 0x83,
+ 0xb9, 0x0f, 0x4c, 0xdf, 0x90, 0x16, 0x83, 0xa2,
+ 0xb3, 0xe3, 0x2e, 0xc1, 0xc2, 0x24, 0x6a, 0xc4,
+ 0x9d, 0x57, 0xba, 0xcb, 0x0f, 0x18, 0x75, 0x00,
+ 0x33, 0x46, 0x82, 0xec, 0xd6, 0x94, 0x77, 0xc3,
+ 0x4f, 0x4c, 0x58, 0x1c, 0x7f, 0x61, 0x3c, 0x36,
+ 0xd5, 0x2f, 0xa5, 0x66, 0xd8, 0x2f, 0xce, 0x6e,
+ 0x8e, 0x20, 0x48, 0x4a, 0xbb, 0xe3, 0xe0, 0xb2,
+ 0x50, 0x33, 0x63, 0x8a, 0x5b, 0x2d, 0x6a, 0xbe,
+ 0x4c, 0x28, 0x81, 0x53, 0x5b, 0xe4, 0xf6, 0xfc,
+ 0x64, 0x06, 0x13, 0x51, 0xeb, 0x4a, 0x91, 0x9c };
+
+static const unsigned int counter=1496;
+ */
+
+static const unsigned char prime2[] = { 0x00,
+ 0xa4, 0xc2, 0x83, 0x4f, 0x36, 0xd3, 0x4f, 0xae,
+ 0xa0, 0xb1, 0x47, 0x43, 0xa8, 0x15, 0xee, 0xad,
+ 0xa3, 0x98, 0xa3, 0x29, 0x45, 0xae, 0x5c, 0xd9,
+ 0x12, 0x99, 0x09, 0xdc, 0xef, 0x05, 0xb4, 0x98,
+ 0x05, 0xaa, 0x07, 0xaa, 0x83, 0x89, 0xd7, 0xba,
+ 0xd1, 0x25, 0x56, 0x58, 0xd1, 0x73, 0x3c, 0xd0,
+ 0x91, 0x65, 0xbe, 0x27, 0x92, 0x94, 0x86, 0x95,
+ 0xdb, 0xcf, 0x07, 0x13, 0xa0, 0x85, 0xd6, 0xaa,
+ 0x6c, 0x1d, 0x63, 0xbf, 0xdd, 0xdf, 0xbc, 0x30,
+ 0xeb, 0x42, 0x2f, 0x52, 0x11, 0xec, 0x6e, 0x65,
+ 0xdf, 0x50, 0xbe, 0x28, 0x3d, 0xa4, 0xec, 0x45,
+ 0x19, 0x4c, 0x13, 0x0f, 0x59, 0x74, 0x57, 0x69,
+ 0x99, 0x4f, 0x4a, 0x74, 0x7f, 0x8c, 0x9e, 0xa2,
+ 0xe7, 0x94, 0xc9, 0x70, 0x70, 0xd0, 0xc4, 0xda,
+ 0x49, 0x5b, 0x7a, 0x7d, 0xd9, 0x71, 0x7c, 0x3b,
+ 0xdc, 0xd2, 0x8a, 0x74, 0x5f, 0xce, 0x09, 0xa2,
+ 0xdb, 0xec, 0xa4, 0xba, 0x75, 0xaa, 0x0a, 0x97,
+ 0xa6, 0x82, 0x25, 0x90, 0x90, 0x37, 0xe4, 0x40,
+ 0x05, 0x28, 0x8f, 0x98, 0x8e, 0x68, 0x01, 0xaf,
+ 0x9b, 0x08, 0x2a, 0x9b, 0xd5, 0xb9, 0x8c, 0x14,
+ 0xbf, 0xba, 0xcb, 0x5b, 0xda, 0x4c, 0x95, 0xb8,
+ 0xdf, 0x67, 0xa6, 0x6b, 0x76, 0x8c, 0xad, 0x4f,
+ 0xfd, 0x6a, 0xd6, 0xcc, 0x62, 0x71, 0x30, 0x30,
+ 0xc1, 0x29, 0x84, 0xe4, 0x8e, 0x32, 0x51, 0xb6,
+ 0xea, 0xfa, 0xba, 0x00, 0x99, 0x76, 0xea, 0x86,
+ 0x90, 0xab, 0x2d, 0xe9, 0xfd, 0x1e, 0x8c, 0xcc,
+ 0x3c, 0x2b, 0x5d, 0x13, 0x1b, 0x47, 0xb4, 0xf5,
+ 0x09, 0x74, 0x1d, 0xd4, 0x78, 0xb2, 0x42, 0x19,
+ 0xd6, 0x24, 0xd1, 0x68, 0xbf, 0x11, 0xf1, 0x38,
+ 0xa0, 0x44, 0x9c, 0xc6, 0x51, 0x33, 0xaa, 0x42,
+ 0x93, 0x9e, 0x30, 0x58, 0x9e, 0xc0, 0x70, 0xdf,
+ 0x7e, 0x64, 0xb1, 0xd8, 0x68, 0x75, 0x98, 0xa7 };
+
+static const unsigned char subprime2[] = { 0x00,
+ 0x8e, 0xab, 0xf4, 0xbe, 0x45, 0xeb, 0xa3, 0x58,
+ 0x4e, 0x60, 0x15, 0x66, 0x5a, 0x4b, 0x25, 0xcf,
+ 0x45, 0x77, 0x89, 0x3f, 0x73, 0x34, 0x4a, 0xe0,
+ 0x9e, 0xac, 0xfd, 0xdc, 0xff, 0x9c, 0x8d, 0xe7 };
+
+static const unsigned char base2[] = { 0x00,
+ 0x8d, 0x72, 0x32, 0x46, 0xa6, 0x5c, 0x80, 0xe3,
+ 0x43, 0x0a, 0x9e, 0x94, 0x35, 0x86, 0xd4, 0x58,
+ 0xa1, 0xca, 0x22, 0xb9, 0x73, 0x46, 0x0b, 0xfb,
+ 0x3e, 0x33, 0xf1, 0xd5, 0xd3, 0xb4, 0x26, 0xbf,
+ 0x50, 0xd7, 0xf2, 0x09, 0x33, 0x6e, 0xc0, 0x31,
+ 0x1b, 0x6d, 0x07, 0x70, 0x86, 0xca, 0x57, 0xf7,
+ 0x0b, 0x4a, 0x63, 0xf0, 0x6f, 0xc8, 0x8a, 0xed,
+ 0x50, 0x60, 0xf3, 0x11, 0xc7, 0x44, 0xf3, 0xce,
+ 0x4e, 0x50, 0x42, 0x2d, 0x85, 0x33, 0x54, 0x57,
+ 0x03, 0x8d, 0xdc, 0x66, 0x4d, 0x61, 0x83, 0x17,
+ 0x1c, 0x7b, 0x0d, 0x65, 0xbc, 0x8f, 0x2c, 0x19,
+ 0x86, 0xfc, 0xe2, 0x9f, 0x5d, 0x67, 0xfc, 0xd4,
+ 0xa5, 0xf8, 0x23, 0xa1, 0x1a, 0xa2, 0xe1, 0x11,
+ 0x15, 0x84, 0x32, 0x01, 0xee, 0x88, 0xf1, 0x55,
+ 0x30, 0xe9, 0x74, 0x3c, 0x1a, 0x2b, 0x54, 0x45,
+ 0x2e, 0x39, 0xb9, 0x77, 0xe1, 0x32, 0xaf, 0x2d,
+ 0x97, 0xe0, 0x21, 0xec, 0xf5, 0x58, 0xe1, 0xc7,
+ 0x2e, 0xe0, 0x71, 0x3d, 0x29, 0xa4, 0xd6, 0xe2,
+ 0x5f, 0x85, 0x9c, 0x05, 0x04, 0x46, 0x41, 0x89,
+ 0x03, 0x3c, 0xfa, 0xb2, 0xcf, 0xfa, 0xd5, 0x67,
+ 0xcc, 0xec, 0x68, 0xfc, 0x83, 0xd9, 0x1f, 0x2e,
+ 0x4e, 0x9a, 0x5e, 0x77, 0xa1, 0xff, 0xe6, 0x6f,
+ 0x04, 0x8b, 0xf9, 0x6b, 0x47, 0xc6, 0x49, 0xd2,
+ 0x88, 0x6e, 0x29, 0xa3, 0x1b, 0xae, 0xe0, 0x4f,
+ 0x72, 0x8a, 0x28, 0x94, 0x0c, 0x1d, 0x8c, 0x99,
+ 0xa2, 0x6f, 0xf8, 0xba, 0x99, 0x90, 0xc7, 0xe5,
+ 0xb1, 0x3c, 0x10, 0x34, 0x86, 0x6a, 0x6a, 0x1f,
+ 0x39, 0x63, 0x58, 0xe1, 0x5e, 0x97, 0x95, 0x45,
+ 0x40, 0x38, 0x45, 0x6f, 0x02, 0xb5, 0x86, 0x6e,
+ 0xae, 0x2f, 0x32, 0x7e, 0xa1, 0x3a, 0x34, 0x2c,
+ 0x1c, 0xd3, 0xff, 0x4e, 0x2c, 0x38, 0x1c, 0xaa,
+ 0x2e, 0x66, 0xbe, 0x32, 0x3e, 0x3c, 0x06, 0x5f };
+
+/*
+ * The constants h2, seed2, & counter2 aren't used in the code; they're provided
+ * here (commented-out) so that human readers can verify that our our PQG
+ * parameters were generated properly.
+static const unsigned char h2[] = {
+ 0x30, 0x91, 0xa1, 0x2e, 0x40, 0xa5, 0x7d, 0xf7,
+ 0xdc, 0xed, 0xee, 0x05, 0xc2, 0x31, 0x91, 0x37,
+ 0xda, 0xc5, 0xe3, 0x47, 0xb5, 0x35, 0x4b, 0xfd,
+ 0x18, 0xb2, 0x7e, 0x67, 0x1e, 0x92, 0x22, 0xe7,
+ 0xf5, 0x00, 0x71, 0xc0, 0x86, 0x8d, 0x90, 0x31,
+ 0x36, 0x3e, 0xd0, 0x94, 0x5d, 0x2f, 0x9a, 0x68,
+ 0xd2, 0xf8, 0x3d, 0x5e, 0x84, 0x42, 0x35, 0xda,
+ 0x75, 0xdd, 0x05, 0xf0, 0x03, 0x31, 0x39, 0xe5,
+ 0xfd, 0x2f, 0x5a, 0x7d, 0x56, 0xd8, 0x26, 0xa0,
+ 0x51, 0x5e, 0x32, 0xb4, 0xad, 0xee, 0xd4, 0x89,
+ 0xae, 0x01, 0x7f, 0xac, 0x86, 0x98, 0x77, 0x26,
+ 0x5c, 0x31, 0xd2, 0x5e, 0xbb, 0x7f, 0xf5, 0x4c,
+ 0x9b, 0xf0, 0xa6, 0x37, 0x34, 0x08, 0x86, 0x6b,
+ 0xce, 0xeb, 0x85, 0x66, 0x0a, 0x26, 0x8a, 0x14,
+ 0x92, 0x12, 0x74, 0xf4, 0xf0, 0xcb, 0xb5, 0xfc,
+ 0x38, 0xd5, 0x1e, 0xa1, 0x2f, 0x4a, 0x1a, 0xca,
+ 0x66, 0xde, 0x6e, 0xe6, 0x6e, 0x1c, 0xef, 0x50,
+ 0x41, 0x31, 0x09, 0xe7, 0x4a, 0xb8, 0xa3, 0xaa,
+ 0x5a, 0x22, 0xbd, 0x63, 0x0f, 0xe9, 0x0e, 0xdb,
+ 0xb3, 0xca, 0x7e, 0x8d, 0x40, 0xb3, 0x3e, 0x0b,
+ 0x12, 0x8b, 0xb0, 0x80, 0x4d, 0x6d, 0xb0, 0x54,
+ 0xbb, 0x4c, 0x1d, 0x6c, 0xa0, 0x5c, 0x9d, 0x91,
+ 0xb3, 0xbb, 0xd9, 0xfc, 0x60, 0xec, 0xc1, 0xbc,
+ 0xae, 0x72, 0x3f, 0xa5, 0x4f, 0x36, 0x2d, 0x2c,
+ 0x81, 0x03, 0x86, 0xa2, 0x03, 0x38, 0x36, 0x8e,
+ 0xad, 0x1d, 0x53, 0xc6, 0xc5, 0x9e, 0xda, 0x08,
+ 0x35, 0x4f, 0xb2, 0x78, 0xba, 0xd1, 0x22, 0xde,
+ 0xc4, 0x6b, 0xbe, 0x83, 0x71, 0x0f, 0xee, 0x38,
+ 0x4a, 0x9f, 0xda, 0x90, 0x93, 0x6b, 0x9a, 0xf2,
+ 0xeb, 0x23, 0xfe, 0x41, 0x3f, 0xf1, 0xfc, 0xee,
+ 0x7f, 0x67, 0xa7, 0xb8, 0xab, 0x29, 0xf4, 0x75,
+ 0x1c, 0xe9, 0xd1, 0x47, 0x7d, 0x86, 0x44, 0xe2 };
+
+static const unsigned char seed2[] = { 0x00,
+ 0xbc, 0xae, 0xc4, 0xea, 0x4e, 0xd2, 0xed, 0x1c,
+ 0x8d, 0x48, 0xed, 0xf2, 0xa5, 0xb4, 0x18, 0xba,
+ 0x00, 0xcb, 0x9c, 0x75, 0x8a, 0x39, 0x94, 0x3b,
+ 0xd0, 0xd6, 0x01, 0xf7, 0xc1, 0xf5, 0x9d, 0xe5,
+ 0xe3, 0xb4, 0x1d, 0xf5, 0x30, 0xfe, 0x99, 0xe4,
+ 0x01, 0xab, 0xc0, 0x88, 0x4e, 0x67, 0x8f, 0xc6,
+ 0x72, 0x39, 0x2e, 0xac, 0x51, 0xec, 0x91, 0x41,
+ 0x47, 0x71, 0x14, 0x8a, 0x1d, 0xca, 0x88, 0x15,
+ 0xea, 0xc9, 0x48, 0x9a, 0x71, 0x50, 0x19, 0x38,
+ 0xdb, 0x4e, 0x65, 0xd5, 0x13, 0xd8, 0x2a, 0xc4,
+ 0xcd, 0xfd, 0x0c, 0xe3, 0xc3, 0x60, 0xae, 0x6d,
+ 0x88, 0xf2, 0x3a, 0xd0, 0x64, 0x73, 0x32, 0x89,
+ 0xcd, 0x0b, 0xb8, 0xc7, 0xa5, 0x27, 0x84, 0xd5,
+ 0x83, 0x3f, 0x0e, 0x10, 0x63, 0x10, 0x78, 0xac,
+ 0x6b, 0x56, 0xb2, 0x62, 0x3a, 0x44, 0x56, 0xc0,
+ 0xe4, 0x33, 0xd7, 0x63, 0x4c, 0xc9, 0x6b, 0xae,
+ 0xfb, 0xe2, 0x9b, 0xf4, 0x96, 0xc7, 0xf0, 0x2a,
+ 0x50, 0xde, 0x86, 0x69, 0x4f, 0x42, 0x4b, 0x1c,
+ 0x7c, 0xa8, 0x6a, 0xfb, 0x54, 0x47, 0x1b, 0x41,
+ 0x31, 0x9e, 0x0a, 0xc6, 0xc0, 0xbc, 0x88, 0x7f,
+ 0x5a, 0x42, 0xa9, 0x82, 0x58, 0x32, 0xb3, 0xeb,
+ 0x54, 0x83, 0x84, 0x26, 0x92, 0xa6, 0xc0, 0x6e,
+ 0x2b, 0xa6, 0x82, 0x82, 0x43, 0x58, 0x84, 0x53,
+ 0x31, 0xcf, 0xd0, 0x0a, 0x11, 0x09, 0x44, 0xc8,
+ 0x11, 0x36, 0xe0, 0x04, 0x85, 0x2e, 0xd1, 0x29,
+ 0x6b, 0x7b, 0x00, 0x71, 0x5f, 0xef, 0x7b, 0x7a,
+ 0x2d, 0x91, 0xf9, 0x84, 0x45, 0x4d, 0xc7, 0xe1,
+ 0xee, 0xd4, 0xb8, 0x61, 0x3b, 0x13, 0xb7, 0xba,
+ 0x95, 0x39, 0xf6, 0x3d, 0x89, 0xbd, 0xa5, 0x80,
+ 0x93, 0xf7, 0xe5, 0x17, 0x05, 0xc5, 0x65, 0xb7,
+ 0xde, 0xc9, 0x9f, 0x04, 0x87, 0xcf, 0x4f, 0x86,
+ 0xc3, 0x29, 0x7d, 0xb7, 0x89, 0xbf, 0xe3, 0xde };
+
+static const unsigned int counter2=210;
+ */
+
+struct tuple_str {
+ CK_RV errNum;
+ const char *errString;
+};
+
+typedef struct tuple_str tuple_str;
+
+static const tuple_str errStrings[] = {
+ { CKR_OK, "CKR_OK " },
+ { CKR_CANCEL, "CKR_CANCEL " },
+ { CKR_HOST_MEMORY, "CKR_HOST_MEMORY " },
+ { CKR_SLOT_ID_INVALID, "CKR_SLOT_ID_INVALID " },
+ { CKR_GENERAL_ERROR, "CKR_GENERAL_ERROR " },
+ { CKR_FUNCTION_FAILED, "CKR_FUNCTION_FAILED " },
+ { CKR_ARGUMENTS_BAD, "CKR_ARGUMENTS_BAD " },
+ { CKR_NO_EVENT, "CKR_NO_EVENT " },
+ { CKR_NEED_TO_CREATE_THREADS, "CKR_NEED_TO_CREATE_THREADS " },
+ { CKR_CANT_LOCK, "CKR_CANT_LOCK " },
+ { CKR_ATTRIBUTE_READ_ONLY, "CKR_ATTRIBUTE_READ_ONLY " },
+ { CKR_ATTRIBUTE_SENSITIVE, "CKR_ATTRIBUTE_SENSITIVE " },
+ { CKR_ATTRIBUTE_TYPE_INVALID, "CKR_ATTRIBUTE_TYPE_INVALID " },
+ { CKR_ATTRIBUTE_VALUE_INVALID, "CKR_ATTRIBUTE_VALUE_INVALID " },
+ { CKR_DATA_INVALID, "CKR_DATA_INVALID " },
+ { CKR_DATA_LEN_RANGE, "CKR_DATA_LEN_RANGE " },
+ { CKR_DEVICE_ERROR, "CKR_DEVICE_ERROR " },
+ { CKR_DEVICE_MEMORY, "CKR_DEVICE_MEMORY " },
+ { CKR_DEVICE_REMOVED, "CKR_DEVICE_REMOVED " },
+ { CKR_ENCRYPTED_DATA_INVALID, "CKR_ENCRYPTED_DATA_INVALID " },
+ { CKR_ENCRYPTED_DATA_LEN_RANGE, "CKR_ENCRYPTED_DATA_LEN_RANGE " },
+ { CKR_FUNCTION_CANCELED, "CKR_FUNCTION_CANCELED " },
+ { CKR_FUNCTION_NOT_PARALLEL, "CKR_FUNCTION_NOT_PARALLEL " },
+ { CKR_FUNCTION_NOT_SUPPORTED, "CKR_FUNCTION_NOT_SUPPORTED " },
+ { CKR_KEY_HANDLE_INVALID, "CKR_KEY_HANDLE_INVALID " },
+ { CKR_KEY_SIZE_RANGE, "CKR_KEY_SIZE_RANGE " },
+ { CKR_KEY_TYPE_INCONSISTENT, "CKR_KEY_TYPE_INCONSISTENT " },
+ { CKR_KEY_NOT_NEEDED, "CKR_KEY_NOT_NEEDED " },
+ { CKR_KEY_CHANGED, "CKR_KEY_CHANGED " },
+ { CKR_KEY_NEEDED, "CKR_KEY_NEEDED " },
+ { CKR_KEY_INDIGESTIBLE, "CKR_KEY_INDIGESTIBLE " },
+ { CKR_KEY_FUNCTION_NOT_PERMITTED, "CKR_KEY_FUNCTION_NOT_PERMITTED " },
+ { CKR_KEY_NOT_WRAPPABLE, "CKR_KEY_NOT_WRAPPABLE " },
+ { CKR_KEY_UNEXTRACTABLE, "CKR_KEY_UNEXTRACTABLE " },
+ { CKR_MECHANISM_INVALID, "CKR_MECHANISM_INVALID " },
+ { CKR_MECHANISM_PARAM_INVALID, "CKR_MECHANISM_PARAM_INVALID " },
+ { CKR_OBJECT_HANDLE_INVALID, "CKR_OBJECT_HANDLE_INVALID " },
+ { CKR_OPERATION_ACTIVE, "CKR_OPERATION_ACTIVE " },
+ { CKR_OPERATION_NOT_INITIALIZED, "CKR_OPERATION_NOT_INITIALIZED " },
+ { CKR_PIN_INCORRECT, "CKR_PIN_INCORRECT " },
+ { CKR_PIN_INVALID, "CKR_PIN_INVALID " },
+ { CKR_PIN_LEN_RANGE, "CKR_PIN_LEN_RANGE " },
+ { CKR_PIN_EXPIRED, "CKR_PIN_EXPIRED " },
+ { CKR_PIN_LOCKED, "CKR_PIN_LOCKED " },
+ { CKR_SESSION_CLOSED, "CKR_SESSION_CLOSED " },
+ { CKR_SESSION_COUNT, "CKR_SESSION_COUNT " },
+ { CKR_SESSION_HANDLE_INVALID, "CKR_SESSION_HANDLE_INVALID " },
+ { CKR_SESSION_PARALLEL_NOT_SUPPORTED, "CKR_SESSION_PARALLEL_NOT_SUPPORTED " },
+ { CKR_SESSION_READ_ONLY, "CKR_SESSION_READ_ONLY " },
+ { CKR_SESSION_EXISTS, "CKR_SESSION_EXISTS " },
+ { CKR_SESSION_READ_ONLY_EXISTS, "CKR_SESSION_READ_ONLY_EXISTS " },
+ { CKR_SESSION_READ_WRITE_SO_EXISTS, "CKR_SESSION_READ_WRITE_SO_EXISTS " },
+ { CKR_SIGNATURE_INVALID, "CKR_SIGNATURE_INVALID " },
+ { CKR_SIGNATURE_LEN_RANGE, "CKR_SIGNATURE_LEN_RANGE " },
+ { CKR_TEMPLATE_INCOMPLETE, "CKR_TEMPLATE_INCOMPLETE " },
+ { CKR_TEMPLATE_INCONSISTENT, "CKR_TEMPLATE_INCONSISTENT " },
+ { CKR_TOKEN_NOT_PRESENT, "CKR_TOKEN_NOT_PRESENT " },
+ { CKR_TOKEN_NOT_RECOGNIZED, "CKR_TOKEN_NOT_RECOGNIZED " },
+ { CKR_TOKEN_WRITE_PROTECTED, "CKR_TOKEN_WRITE_PROTECTED " },
+ { CKR_UNWRAPPING_KEY_HANDLE_INVALID, "CKR_UNWRAPPING_KEY_HANDLE_INVALID " },
+ { CKR_UNWRAPPING_KEY_SIZE_RANGE, "CKR_UNWRAPPING_KEY_SIZE_RANGE " },
+ { CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT" },
+ { CKR_USER_ALREADY_LOGGED_IN, "CKR_USER_ALREADY_LOGGED_IN " },
+ { CKR_USER_NOT_LOGGED_IN, "CKR_USER_NOT_LOGGED_IN " },
+ { CKR_USER_PIN_NOT_INITIALIZED, "CKR_USER_PIN_NOT_INITIALIZED " },
+ { CKR_USER_TYPE_INVALID, "CKR_USER_TYPE_INVALID " },
+ { CKR_USER_ANOTHER_ALREADY_LOGGED_IN, "CKR_USER_ANOTHER_ALREADY_LOGGED_IN " },
+ { CKR_USER_TOO_MANY_TYPES, "CKR_USER_TOO_MANY_TYPES " },
+ { CKR_WRAPPED_KEY_INVALID, "CKR_WRAPPED_KEY_INVALID " },
+ { CKR_WRAPPED_KEY_LEN_RANGE, "CKR_WRAPPED_KEY_LEN_RANGE " },
+ { CKR_WRAPPING_KEY_HANDLE_INVALID, "CKR_WRAPPING_KEY_HANDLE_INVALID " },
+ { CKR_WRAPPING_KEY_SIZE_RANGE, "CKR_WRAPPING_KEY_SIZE_RANGE " },
+ { CKR_WRAPPING_KEY_TYPE_INCONSISTENT, "CKR_WRAPPING_KEY_TYPE_INCONSISTENT " },
+ { CKR_RANDOM_SEED_NOT_SUPPORTED, "CKR_RANDOM_SEED_NOT_SUPPORTED " },
+ { CKR_RANDOM_NO_RNG, "CKR_RANDOM_NO_RNG " },
+ { CKR_DOMAIN_PARAMS_INVALID, "CKR_DOMAIN_PARAMS_INVALID " },
+ { CKR_BUFFER_TOO_SMALL, "CKR_BUFFER_TOO_SMALL " },
+ { CKR_SAVED_STATE_INVALID, "CKR_SAVED_STATE_INVALID " },
+ { CKR_INFORMATION_SENSITIVE, "CKR_INFORMATION_SENSITIVE " },
+ { CKR_STATE_UNSAVEABLE, "CKR_STATE_UNSAVEABLE " },
+ { CKR_CRYPTOKI_NOT_INITIALIZED, "CKR_CRYPTOKI_NOT_INITIALIZED " },
+ { CKR_CRYPTOKI_ALREADY_INITIALIZED, "CKR_CRYPTOKI_ALREADY_INITIALIZED " },
+ { CKR_MUTEX_BAD, "CKR_MUTEX_BAD " },
+ { CKR_MUTEX_NOT_LOCKED, "CKR_MUTEX_NOT_LOCKED " },
+ { CKR_FUNCTION_REJECTED, "CKR_FUNCTION_REJECTED " },
+ { CKR_VENDOR_DEFINED, "CKR_VENDOR_DEFINED " },
+ { 0xCE534351, "CKR_NETSCAPE_CERTDB_FAILED " },
+ { 0xCE534352, "CKR_NETSCAPE_KEYDB_FAILED " }
+
+};
+
+static const CK_ULONG numStrings = sizeof(errStrings) / sizeof(tuple_str);
+
+/* Returns constant error string for "CRV".
+ * Returns "unknown error" if errNum is unknown.
+ */
+static const char *
+CK_RVtoStr(CK_RV errNum)
+{
+ CK_ULONG low = 1;
+ CK_ULONG high = numStrings - 1;
+ CK_ULONG i;
+ CK_RV num;
+ static int initDone;
+
+ /* make sure table is in ascending order.
+ * binary search depends on it.
+ */
+ if (!initDone) {
+ CK_RV lastNum = CKR_OK;
+ for (i = low; i <= high; ++i) {
+ num = errStrings[i].errNum;
+ if (num <= lastNum) {
+ PR_fprintf(PR_STDERR,
+ "sequence error in error strings at item %d\n"
+ "error %d (%s)\n"
+ "should come after \n"
+ "error %d (%s)\n",
+ (int)i, (int)lastNum, errStrings[i - 1].errString,
+ (int)num, errStrings[i].errString);
+ }
+ lastNum = num;
+ }
+ initDone = 1;
+ }
+
+ /* Do binary search of table. */
+ while (low + 1 < high) {
+ i = low + (high - low) / 2;
+ num = errStrings[i].errNum;
+ if (errNum == num)
+ return errStrings[i].errString;
+ if (errNum < num)
+ high = i;
+ else
+ low = i;
+ }
+ if (errNum == errStrings[low].errNum)
+ return errStrings[low].errString;
+ if (errNum == errStrings[high].errNum)
+ return errStrings[high].errString;
+ return "unknown error";
+}
+
+static void
+pk11error(const char *string, CK_RV crv)
+{
+ PRErrorCode errorcode;
+
+ PR_fprintf(PR_STDERR, "%s: 0x%08lX, %-26s\n", string, crv, CK_RVtoStr(crv));
+
+ errorcode = PR_GetError();
+ if (errorcode) {
+ PR_fprintf(PR_STDERR, "NSPR error code: %d: %s\n", errorcode,
+ PR_ErrorToString(errorcode, PR_LANGUAGE_I_DEFAULT));
+ }
+}
+
+static void
+logIt(const char *fmt, ...)
+{
+ va_list args;
+
+ if (verbose) {
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ }
+}
+
+static CK_RV
+softokn_Init(CK_FUNCTION_LIST_PTR pFunctionList, const char *configDir,
+ const char *dbPrefix)
+{
+
+ CK_RV crv = CKR_OK;
+ CK_C_INITIALIZE_ARGS initArgs;
+ char *moduleSpec = NULL;
+
+ initArgs.CreateMutex = NULL;
+ initArgs.DestroyMutex = NULL;
+ initArgs.LockMutex = NULL;
+ initArgs.UnlockMutex = NULL;
+ initArgs.flags = CKF_OS_LOCKING_OK;
+ if (configDir) {
+ moduleSpec = PR_smprintf("configdir='%s' certPrefix='%s' "
+ "keyPrefix='%s' secmod='secmod.db' flags=ReadOnly ",
+ configDir, dbPrefix, dbPrefix);
+ } else {
+ moduleSpec = PR_smprintf("configdir='' certPrefix='' keyPrefix='' "
+ "secmod='' flags=noCertDB, noModDB");
+ }
+ if (!moduleSpec) {
+ PR_fprintf(PR_STDERR, "softokn_Init: out of memory error\n");
+ return CKR_HOST_MEMORY;
+ }
+ logIt("moduleSpec %s\n", moduleSpec);
+ initArgs.LibraryParameters = (CK_CHAR_PTR *)moduleSpec;
+ initArgs.pReserved = NULL;
+
+ crv = pFunctionList->C_Initialize(&initArgs);
+ if (crv != CKR_OK) {
+ pk11error("C_Initialize failed", crv);
+ goto cleanup;
+ }
+
+cleanup:
+ if (moduleSpec) {
+ PR_smprintf_free(moduleSpec);
+ }
+
+ return crv;
+}
+
+static char *
+filePasswd(char *pwFile)
+{
+ unsigned char phrase[200];
+ PRFileDesc *fd;
+ PRInt32 nb;
+ int i;
+
+ if (!pwFile)
+ return 0;
+
+ fd = PR_Open(pwFile, PR_RDONLY, 0);
+ if (!fd) {
+ lperror(pwFile);
+ return NULL;
+ }
+
+ nb = PR_Read(fd, phrase, sizeof(phrase));
+
+ PR_Close(fd);
+ /* handle the Windows EOL case */
+ i = 0;
+ while (phrase[i] != '\r' && phrase[i] != '\n' && i < nb)
+ i++;
+ phrase[i] = '\0';
+ if (nb == 0) {
+ PR_fprintf(PR_STDERR, "password file contains no data\n");
+ return NULL;
+ }
+ return (char *)PL_strdup((char *)phrase);
+}
+
+static void
+checkPath(char *string)
+{
+ char *src;
+ char *dest;
+
+ /*
+ * windows support convert any back slashes to
+ * forward slashes.
+ */
+ for (src = string, dest = string; *src; src++, dest++) {
+ if (*src == '\\') {
+ *dest = '/';
+ }
+ }
+ dest--;
+ /* if the last char is a / set it to 0 */
+ if (*dest == '/')
+ *dest = 0;
+}
+
+static CK_SLOT_ID *
+getSlotList(CK_FUNCTION_LIST_PTR pFunctionList,
+ CK_ULONG slotIndex)
+{
+ CK_RV crv = CKR_OK;
+ CK_SLOT_ID *pSlotList = NULL;
+ CK_ULONG slotCount;
+
+ /* Get slot list */
+ crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */,
+ NULL, &slotCount);
+ if (crv != CKR_OK) {
+ pk11error("C_GetSlotList failed", crv);
+ return NULL;
+ }
+
+ if (slotIndex >= slotCount) {
+ PR_fprintf(PR_STDERR, "provided slotIndex is greater than the slot count.");
+ return NULL;
+ }
+
+ pSlotList = (CK_SLOT_ID *)PR_Malloc(slotCount * sizeof(CK_SLOT_ID));
+ if (!pSlotList) {
+ lperror("failed to allocate slot list");
+ return NULL;
+ }
+ crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */,
+ pSlotList, &slotCount);
+ if (crv != CKR_OK) {
+ pk11error("C_GetSlotList failed", crv);
+ if (pSlotList)
+ PR_Free(pSlotList);
+ return NULL;
+ }
+ return pSlotList;
+}
+
+int
+main(int argc, char **argv)
+{
+ PLOptState *optstate;
+ char *program_name;
+ char *libname = NULL;
+ PRLibrary *lib = NULL;
+ PRFileDesc *fd;
+ PRStatus rv = PR_SUCCESS;
+ const char *input_file = NULL; /* read/create encrypted data from here */
+ char *output_file = NULL; /* write new encrypted data here */
+ int bytesRead;
+ int bytesWritten;
+ unsigned char file_buf[512];
+ int count = 0;
+ unsigned int keySize = 0;
+ int i;
+ PRBool verify = PR_FALSE;
+ static PRBool FIPSMODE = PR_FALSE;
+ PRBool successful = PR_FALSE;
+
+#ifdef USES_LINKS
+ int ret;
+ struct stat stat_buf;
+ char link_buf[MAXPATHLEN + 1];
+ char *link_file = NULL;
+#endif
+
+ char *pwd = NULL;
+ char *configDir = NULL;
+ char *dbPrefix = NULL;
+ char *disableUnload = NULL;
+
+ CK_C_GetFunctionList pC_GetFunctionList;
+ CK_TOKEN_INFO tokenInfo;
+ CK_FUNCTION_LIST_PTR pFunctionList = NULL;
+ CK_RV crv = CKR_OK;
+ CK_SESSION_HANDLE hRwSession;
+ CK_SLOT_ID *pSlotList = NULL;
+ CK_ULONG slotIndex = 0;
+ CK_MECHANISM digestmech;
+ CK_ULONG digestLen = 0;
+ CK_BYTE digest[32]; /* SHA256_LENGTH */
+ CK_BYTE sign[64]; /* DSA SIGNATURE LENGTH */
+ CK_ULONG signLen = 0;
+ CK_MECHANISM signMech = {
+ CKM_DSA, NULL, 0
+ };
+
+ /*** DSA Key ***/
+
+ CK_MECHANISM dsaKeyPairGenMech;
+ CK_ATTRIBUTE dsaPubKeyTemplate[5];
+ CK_ATTRIBUTE dsaPrivKeyTemplate[5];
+ CK_OBJECT_HANDLE hDSApubKey = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hDSAprivKey = CK_INVALID_HANDLE;
+
+ CK_BYTE dsaPubKey[384];
+ CK_ATTRIBUTE dsaPubKeyValue;
+
+ program_name = strrchr(argv[0], '/');
+ program_name = program_name ? (program_name + 1) : argv[0];
+ optstate = PL_CreateOptState(argc, argv, "i:o:f:Fd:hH?k:p:P:vVs:");
+ if (optstate == NULL) {
+ lperror("PL_CreateOptState failed");
+ return 1;
+ }
+
+ while (PL_GetNextOpt(optstate) == PL_OPT_OK) {
+ switch (optstate->option) {
+
+ case 'd':
+ if (!optstate->value) {
+ PL_DestroyOptState(optstate);
+ usage(program_name);
+ }
+ configDir = PL_strdup(optstate->value);
+ checkPath(configDir);
+ break;
+
+ case 'i':
+ if (!optstate->value) {
+ PL_DestroyOptState(optstate);
+ usage(program_name);
+ }
+ input_file = optstate->value;
+ break;
+
+ case 'o':
+ if (!optstate->value) {
+ PL_DestroyOptState(optstate);
+ usage(program_name);
+ }
+ output_file = PL_strdup(optstate->value);
+ break;
+
+ case 'k':
+ if (!optstate->value) {
+ PL_DestroyOptState(optstate);
+ usage(program_name);
+ }
+ keySize = atoi(optstate->value);
+ break;
+
+ case 'f':
+ if (!optstate->value) {
+ PL_DestroyOptState(optstate);
+ usage(program_name);
+ }
+ pwd = filePasswd((char *)optstate->value);
+ if (!pwd)
+ usage(program_name);
+ break;
+
+ case 'F':
+ FIPSMODE = PR_TRUE;
+ break;
+
+ case 'p':
+ if (!optstate->value) {
+ PL_DestroyOptState(optstate);
+ usage(program_name);
+ }
+ pwd = PL_strdup(optstate->value);
+ break;
+
+ case 'P':
+ if (!optstate->value) {
+ PL_DestroyOptState(optstate);
+ usage(program_name);
+ }
+ dbPrefix = PL_strdup(optstate->value);
+ break;
+
+ case 'v':
+ verbose = PR_TRUE;
+ break;
+
+ case 'V':
+ verify = PR_TRUE;
+ break;
+
+ case 'H':
+ PL_DestroyOptState(optstate);
+ long_usage(program_name);
+ return 1;
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ PL_DestroyOptState(optstate);
+ usage(program_name);
+ return 1;
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+
+ if (!input_file) {
+ usage(program_name);
+ return 1;
+ }
+
+ /* Get the platform-dependent library name of the
+ * NSS cryptographic module.
+ */
+ libname = PR_GetLibraryName(NULL, "softokn3");
+ assert(libname != NULL);
+ if (!libname) {
+ PR_fprintf(PR_STDERR, "getting softokn3 failed");
+ goto cleanup;
+ }
+ lib = PR_LoadLibrary(libname);
+ assert(lib != NULL);
+ if (!lib) {
+ PR_fprintf(PR_STDERR, "loading softokn3 failed");
+ goto cleanup;
+ }
+ PR_FreeLibraryName(libname);
+
+ if (FIPSMODE) {
+ /* FIPSMODE == FC_GetFunctionList */
+ /* library path must be set to an already signed softokn3/freebl */
+ pC_GetFunctionList = (CK_C_GetFunctionList)
+ PR_FindFunctionSymbol(lib, "FC_GetFunctionList");
+ } else {
+ /* NON FIPS mode == C_GetFunctionList */
+ pC_GetFunctionList = (CK_C_GetFunctionList)
+ PR_FindFunctionSymbol(lib, "C_GetFunctionList");
+ }
+ assert(pC_GetFunctionList != NULL);
+ if (!pC_GetFunctionList) {
+ PR_fprintf(PR_STDERR, "getting function list failed");
+ goto cleanup;
+ }
+
+ crv = (*pC_GetFunctionList)(&pFunctionList);
+ assert(crv == CKR_OK);
+ if (crv != CKR_OK) {
+ PR_fprintf(PR_STDERR, "loading function list failed");
+ goto cleanup;
+ }
+
+ if (configDir) {
+ if (!dbPrefix) {
+ dbPrefix = PL_strdup("");
+ }
+ crv = softokn_Init(pFunctionList, configDir, dbPrefix);
+ if (crv != CKR_OK) {
+ logIt("Failed to use provided database directory "
+ "will just initialize the volatile certdb.\n");
+ crv = softokn_Init(pFunctionList, NULL, NULL); /* NoDB Init */
+ }
+ } else {
+ crv = softokn_Init(pFunctionList, NULL, NULL); /* NoDB Init */
+ }
+
+ if (crv != CKR_OK) {
+ pk11error("Initiailzing softoken failed", crv);
+ goto cleanup;
+ }
+
+ pSlotList = getSlotList(pFunctionList, slotIndex);
+ if (pSlotList == NULL) {
+ PR_fprintf(PR_STDERR, "getSlotList failed");
+ goto cleanup;
+ }
+
+ if ((keySize == 0) || (keySize > 1024)) {
+ CK_MECHANISM_INFO mechInfo;
+ crv = pFunctionList->C_GetMechanismInfo(pSlotList[slotIndex],
+ CKM_DSA, &mechInfo);
+ if (crv != CKR_OK) {
+ pk11error("Couldn't get mechanism info for DSA", crv);
+ goto cleanup;
+ }
+
+ if (keySize && (mechInfo.ulMaxKeySize < keySize)) {
+ PR_fprintf(PR_STDERR,
+ "token doesn't support DSA2 (Max key size=%d)\n",
+ mechInfo.ulMaxKeySize);
+ goto cleanup;
+ }
+
+ if ((keySize == 0) && mechInfo.ulMaxKeySize >= 2048) {
+ keySize = 2048;
+ } else {
+ keySize = 1024;
+ }
+ }
+
+ /* DSA key init */
+ if (keySize == 1024) {
+ dsaPubKeyTemplate[0].type = CKA_PRIME;
+ dsaPubKeyTemplate[0].pValue = (CK_VOID_PTR)&prime;
+ dsaPubKeyTemplate[0].ulValueLen = sizeof(prime);
+ dsaPubKeyTemplate[1].type = CKA_SUBPRIME;
+ dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR)&subprime;
+ dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime);
+ dsaPubKeyTemplate[2].type = CKA_BASE;
+ dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR)&base;
+ dsaPubKeyTemplate[2].ulValueLen = sizeof(base);
+ digestmech.mechanism = CKM_SHA_1;
+ digestmech.pParameter = NULL;
+ digestmech.ulParameterLen = 0;
+ } else if (keySize == 2048) {
+ dsaPubKeyTemplate[0].type = CKA_PRIME;
+ dsaPubKeyTemplate[0].pValue = (CK_VOID_PTR)&prime2;
+ dsaPubKeyTemplate[0].ulValueLen = sizeof(prime2);
+ dsaPubKeyTemplate[1].type = CKA_SUBPRIME;
+ dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR)&subprime2;
+ dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime2);
+ dsaPubKeyTemplate[2].type = CKA_BASE;
+ dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR)&base2;
+ dsaPubKeyTemplate[2].ulValueLen = sizeof(base2);
+ digestmech.mechanism = CKM_SHA256;
+ digestmech.pParameter = NULL;
+ digestmech.ulParameterLen = 0;
+ } else {
+ /* future - generate pqg */
+ PR_fprintf(PR_STDERR, "Only keysizes 1024 and 2048 are supported");
+ goto cleanup;
+ }
+ dsaPubKeyTemplate[3].type = CKA_TOKEN;
+ dsaPubKeyTemplate[3].pValue = &false; /* session object */
+ dsaPubKeyTemplate[3].ulValueLen = sizeof(false);
+ dsaPubKeyTemplate[4].type = CKA_VERIFY;
+ dsaPubKeyTemplate[4].pValue = &true;
+ dsaPubKeyTemplate[4].ulValueLen = sizeof(true);
+ dsaKeyPairGenMech.mechanism = CKM_DSA_KEY_PAIR_GEN;
+ dsaKeyPairGenMech.pParameter = NULL;
+ dsaKeyPairGenMech.ulParameterLen = 0;
+ dsaPrivKeyTemplate[0].type = CKA_TOKEN;
+ dsaPrivKeyTemplate[0].pValue = &false; /* session object */
+ dsaPrivKeyTemplate[0].ulValueLen = sizeof(false);
+ dsaPrivKeyTemplate[1].type = CKA_PRIVATE;
+ dsaPrivKeyTemplate[1].pValue = &true;
+ dsaPrivKeyTemplate[1].ulValueLen = sizeof(true);
+ dsaPrivKeyTemplate[2].type = CKA_SENSITIVE;
+ dsaPrivKeyTemplate[2].pValue = &true;
+ dsaPrivKeyTemplate[2].ulValueLen = sizeof(true);
+ dsaPrivKeyTemplate[3].type = CKA_SIGN,
+ dsaPrivKeyTemplate[3].pValue = &true;
+ dsaPrivKeyTemplate[3].ulValueLen = sizeof(true);
+ dsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE;
+ dsaPrivKeyTemplate[4].pValue = &false;
+ dsaPrivKeyTemplate[4].ulValueLen = sizeof(false);
+
+ crv = pFunctionList->C_OpenSession(pSlotList[slotIndex],
+ CKF_RW_SESSION | CKF_SERIAL_SESSION,
+ NULL, NULL, &hRwSession);
+ if (crv != CKR_OK) {
+ pk11error("Opening a read/write session failed", crv);
+ goto cleanup;
+ }
+
+ /* check if a password is needed */
+ crv = pFunctionList->C_GetTokenInfo(pSlotList[slotIndex], &tokenInfo);
+ if (crv != CKR_OK) {
+ pk11error("C_GetTokenInfo failed", crv);
+ goto cleanup;
+ }
+ if (tokenInfo.flags & CKF_LOGIN_REQUIRED) {
+ if (pwd) {
+ int pwdLen = strlen((const char *)pwd);
+ crv = pFunctionList->C_Login(hRwSession, CKU_USER,
+ (CK_UTF8CHAR_PTR)pwd, (CK_ULONG)pwdLen);
+ if (crv != CKR_OK) {
+ pk11error("C_Login failed", crv);
+ goto cleanup;
+ }
+ } else {
+ PR_fprintf(PR_STDERR, "Please provide the password for the token");
+ goto cleanup;
+ }
+ } else if (pwd) {
+ logIt("A password was provided but the password was not used.\n");
+ }
+
+ /* Generate a DSA key pair */
+ logIt("Generate a DSA key pair ... \n");
+ crv = pFunctionList->C_GenerateKeyPair(hRwSession, &dsaKeyPairGenMech,
+ dsaPubKeyTemplate,
+ NUM_ELEM(dsaPubKeyTemplate),
+ dsaPrivKeyTemplate,
+ NUM_ELEM(dsaPrivKeyTemplate),
+ &hDSApubKey, &hDSAprivKey);
+ if (crv != CKR_OK) {
+ pk11error("DSA key pair generation failed", crv);
+ goto cleanup;
+ }
+
+ /* open the shared library */
+ fd = PR_OpenFile(input_file, PR_RDONLY, 0);
+ if (fd == NULL) {
+ lperror(input_file);
+ goto cleanup;
+ }
+#ifdef USES_LINKS
+ ret = lstat(input_file, &stat_buf);
+ if (ret < 0) {
+ perror(input_file);
+ goto cleanup;
+ }
+ if (S_ISLNK(stat_buf.st_mode)) {
+ char *dirpath, *dirend;
+ ret = readlink(input_file, link_buf, sizeof(link_buf) - 1);
+ if (ret < 0) {
+ perror(input_file);
+ goto cleanup;
+ }
+ link_buf[ret] = 0;
+ link_file = mkoutput(input_file);
+ /* get the dirname of input_file */
+ dirpath = PL_strdup(input_file);
+ dirend = strrchr(dirpath, '/');
+ if (dirend) {
+ *dirend = '\0';
+ ret = chdir(dirpath);
+ if (ret < 0) {
+ perror(dirpath);
+ goto cleanup;
+ }
+ }
+ PL_strfree(dirpath);
+ input_file = link_buf;
+ /* get the basename of link_file */
+ dirend = strrchr(link_file, '/');
+ if (dirend) {
+ char *tmp_file = NULL;
+ tmp_file = PL_strdup(dirend + 1);
+ PL_strfree(link_file);
+ link_file = tmp_file;
+ }
+ }
+#endif
+ if (output_file == NULL) {
+ output_file = mkoutput(input_file);
+ }
+
+ /* compute the digest */
+ memset(digest, 0, sizeof(digest));
+ crv = pFunctionList->C_DigestInit(hRwSession, &digestmech);
+ if (crv != CKR_OK) {
+ pk11error("C_DigestInit failed", crv);
+ goto cleanup;
+ }
+
+ /* Digest the file */
+ while ((bytesRead = PR_Read(fd, file_buf, sizeof(file_buf))) > 0) {
+ crv = pFunctionList->C_DigestUpdate(hRwSession, (CK_BYTE_PTR)file_buf,
+ bytesRead);
+ if (crv != CKR_OK) {
+ pk11error("C_DigestUpdate failed", crv);
+ goto cleanup;
+ }
+ count += bytesRead;
+ }
+
+ /* close the input_File */
+ PR_Close(fd);
+ fd = NULL;
+ if (bytesRead < 0) {
+ lperror("0 bytes read from input file");
+ goto cleanup;
+ }
+
+ digestLen = sizeof(digest);
+ crv = pFunctionList->C_DigestFinal(hRwSession, (CK_BYTE_PTR)digest,
+ &digestLen);
+ if (crv != CKR_OK) {
+ pk11error("C_DigestFinal failed", crv);
+ goto cleanup;
+ }
+
+ if (digestLen != sizeof(digest)) {
+ PR_fprintf(PR_STDERR, "digestLen has incorrect length %lu "
+ "it should be %lu \n",
+ digestLen, sizeof(digest));
+ goto cleanup;
+ }
+
+ /* sign the hash */
+ memset(sign, 0, sizeof(sign));
+ /* SignUpdate */
+ crv = pFunctionList->C_SignInit(hRwSession, &signMech, hDSAprivKey);
+ if (crv != CKR_OK) {
+ pk11error("C_SignInit failed", crv);
+ goto cleanup;
+ }
+
+ signLen = sizeof(sign);
+ crv = pFunctionList->C_Sign(hRwSession, (CK_BYTE *)digest, digestLen,
+ sign, &signLen);
+ if (crv != CKR_OK) {
+ pk11error("C_Sign failed", crv);
+ goto cleanup;
+ }
+
+ if (signLen != sizeof(sign)) {
+ PR_fprintf(PR_STDERR, "signLen has incorrect length %lu "
+ "it should be %lu \n",
+ signLen, sizeof(sign));
+ goto cleanup;
+ }
+
+ if (verify) {
+ crv = pFunctionList->C_VerifyInit(hRwSession, &signMech, hDSApubKey);
+ if (crv != CKR_OK) {
+ pk11error("C_VerifyInit failed", crv);
+ goto cleanup;
+ }
+ crv = pFunctionList->C_Verify(hRwSession, digest, digestLen,
+ sign, signLen);
+ if (crv != CKR_OK) {
+ pk11error("C_Verify failed", crv);
+ goto cleanup;
+ }
+ }
+
+ if (verbose) {
+ int j;
+ PR_fprintf(PR_STDERR, "Library File: %s %d bytes\n", input_file, count);
+ PR_fprintf(PR_STDERR, "Check File: %s\n", output_file);
+#ifdef USES_LINKS
+ if (link_file) {
+ PR_fprintf(PR_STDERR, "Link: %s\n", link_file);
+ }
+#endif
+ PR_fprintf(PR_STDERR, " hash: %lu bytes\n", digestLen);
+#define STEP 10
+ for (i = 0; i < (int)digestLen; i += STEP) {
+ PR_fprintf(PR_STDERR, " ");
+ for (j = 0; j < STEP && (i + j) < (int)digestLen; j++) {
+ PR_fprintf(PR_STDERR, " %02x", digest[i + j]);
+ }
+ PR_fprintf(PR_STDERR, "\n");
+ }
+ PR_fprintf(PR_STDERR, " signature: %lu bytes\n", signLen);
+ for (i = 0; i < (int)signLen; i += STEP) {
+ PR_fprintf(PR_STDERR, " ");
+ for (j = 0; j < STEP && (i + j) < (int)signLen; j++) {
+ PR_fprintf(PR_STDERR, " %02x", sign[i + j]);
+ }
+ PR_fprintf(PR_STDERR, "\n");
+ }
+ }
+
+ /* open the target signature file */
+ fd = PR_Open(output_file, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0666);
+ if (fd == NULL) {
+ lperror(output_file);
+ goto cleanup;
+ }
+
+ /*
+ * we write the key out in a straight binary format because very
+ * low level libraries need to read an parse this file. Ideally we should
+ * just derEncode the public key (which would be pretty simple, and be
+ * more general), but then we'd need to link the ASN.1 decoder with the
+ * freebl libraries.
+ */
+
+ file_buf[0] = NSS_SIGN_CHK_MAGIC1;
+ file_buf[1] = NSS_SIGN_CHK_MAGIC2;
+ file_buf[2] = NSS_SIGN_CHK_MAJOR_VERSION;
+ file_buf[3] = NSS_SIGN_CHK_MINOR_VERSION;
+ encodeInt(&file_buf[4], 12); /* offset to data start */
+ encodeInt(&file_buf[8], CKK_DSA);
+ bytesWritten = PR_Write(fd, file_buf, 12);
+ if (bytesWritten != 12) {
+ lperror(output_file);
+ goto cleanup;
+ }
+
+ /* get DSA Public KeyValue */
+ memset(dsaPubKey, 0, sizeof(dsaPubKey));
+ dsaPubKeyValue.type = CKA_VALUE;
+ dsaPubKeyValue.pValue = (CK_VOID_PTR)&dsaPubKey;
+ dsaPubKeyValue.ulValueLen = sizeof(dsaPubKey);
+
+ crv = pFunctionList->C_GetAttributeValue(hRwSession, hDSApubKey,
+ &dsaPubKeyValue, 1);
+ if (crv != CKR_OK && crv != CKR_ATTRIBUTE_TYPE_INVALID) {
+ pk11error("C_GetAttributeValue failed", crv);
+ goto cleanup;
+ }
+
+ /* CKA_PRIME */
+ rv = writeItem(fd, dsaPubKeyTemplate[0].pValue,
+ dsaPubKeyTemplate[0].ulValueLen, output_file);
+ if (rv != PR_SUCCESS)
+ goto cleanup;
+ /* CKA_SUBPRIME */
+ rv = writeItem(fd, dsaPubKeyTemplate[1].pValue,
+ dsaPubKeyTemplate[1].ulValueLen, output_file);
+ if (rv != PR_SUCCESS)
+ goto cleanup;
+ /* CKA_BASE */
+ rv = writeItem(fd, dsaPubKeyTemplate[2].pValue,
+ dsaPubKeyTemplate[2].ulValueLen, output_file);
+ if (rv != PR_SUCCESS)
+ goto cleanup;
+ /* DSA Public Key value */
+ rv = writeItem(fd, dsaPubKeyValue.pValue,
+ dsaPubKeyValue.ulValueLen, output_file);
+ if (rv != PR_SUCCESS)
+ goto cleanup;
+ /* DSA SIGNATURE */
+ rv = writeItem(fd, &sign, signLen, output_file);
+ if (rv != PR_SUCCESS)
+ goto cleanup;
+ PR_Close(fd);
+
+#ifdef USES_LINKS
+ if (link_file) {
+ (void)unlink(link_file);
+ ret = symlink(output_file, link_file);
+ if (ret < 0) {
+ perror(link_file);
+ goto cleanup;
+ }
+ }
+#endif
+
+ successful = PR_TRUE;
+
+cleanup:
+ if (pFunctionList) {
+ /* C_Finalize will automatically logout, close session, */
+ /* and delete the temp objects on the token */
+ crv = pFunctionList->C_Finalize(NULL);
+ if (crv != CKR_OK) {
+ pk11error("C_Finalize failed", crv);
+ }
+ }
+ if (pSlotList) {
+ PR_Free(pSlotList);
+ }
+ if (pwd) {
+ PL_strfree(pwd);
+ }
+ if (configDir) {
+ PL_strfree(configDir);
+ }
+ if (dbPrefix) {
+ PL_strfree(dbPrefix);
+ }
+ if (output_file) { /* allocated by mkoutput function */
+ PL_strfree(output_file);
+ }
+#ifdef USES_LINKS
+ if (link_file) { /* allocated by mkoutput function */
+ PL_strfree(link_file);
+ }
+#endif
+
+ disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
+ if (!disableUnload && lib) {
+ PR_UnloadLibrary(lib);
+ }
+ PR_Cleanup();
+
+ if (crv != CKR_OK)
+ return crv;
+
+ return (successful) ? 0 : 1;
+}
diff --git a/security/nss/cmd/shlibsign/shlibsign.gyp b/security/nss/cmd/shlibsign/shlibsign.gyp
new file mode 100644
index 000000000..75612c07a
--- /dev/null
+++ b/security/nss/cmd/shlibsign/shlibsign.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'shlibsign',
+ 'type': 'executable',
+ 'sources': [
+ 'shlibsign.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'SHLIB_SUFFIX=\"<(dll_suffix)\"',
+ 'SHLIB_PREFIX=\"<(dll_prefix)\"'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/shlibsign/sign.cmd b/security/nss/cmd/shlibsign/sign.cmd
new file mode 100644
index 000000000..db37411af
--- /dev/null
+++ b/security/nss/cmd/shlibsign/sign.cmd
@@ -0,0 +1,25 @@
+rem This Source Code Form is subject to the terms of the Mozilla Public
+rem License, v. 2.0. If a copy of the MPL was not distributed with this
+rem file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/* Equivalent to sign.sh for OS/2 */
+PARSE ARG dist objdir os_target nspr_lib_dir therest
+dist=forwardtoback(dist);
+objdir=forwardtoback(objdir);
+nspr_lib_dir=forwardtoback(nspr_lib_dir);
+'echo 'dist
+'echo 'objdir
+'echo 'nspr_lib_dir
+'set BEGINLIBPATH='dist'\lib;'nspr_lib_dir';'dist'\bin;%BEGINLIBPATH%'
+'set LIBPATHSTRICT=T'
+objdir'\shlibsign -v -i 'therest
+exit
+
+forwardtoback: procedure
+ arg pathname
+ parse var pathname pathname'/'rest
+ do while (rest <> "")
+ pathname = pathname'\'rest
+ parse var pathname pathname'/'rest
+ end
+ return pathname
diff --git a/security/nss/cmd/shlibsign/sign.sh b/security/nss/cmd/shlibsign/sign.sh
new file mode 100644
index 000000000..d8bd837d6
--- /dev/null
+++ b/security/nss/cmd/shlibsign/sign.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+# 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/.
+
+# arguments:
+# 1: full path to DIST/OBJDIR (parent dir of "lib")
+# 2: full path to shlibsign executable (DIST/OBJDIR/bin)
+# 3: OS_TARGET
+# 4: full path to DIST/OBJDIR/lib
+# 5: full path to library that is to be signed
+
+case "${3}" in
+WIN*)
+ if echo "${PATH}" | grep -c \; >/dev/null; then
+ PATH=${1}/lib\;${1}/bin\;${4}\;${PATH}
+ else
+ # ARG1 is ${1} with the drive letter escaped.
+ if echo "${1}" | grep -c : >/dev/null; then
+ ARG1=`(cd ${1}; pwd)`
+ else
+ ARG1=${1}
+ fi
+ if echo "${4}" | grep -c : >/dev/null; then
+ ARG4=`(cd ${4}; pwd)`
+ else
+ ARG4=${4}
+ fi
+ PATH=${ARG1}/lib:${ARG1}/bin:${ARG4}:${PATH}
+ fi
+ export PATH
+ echo "${2}"/shlibsign -v -i "${5}"
+ "${2}"/shlibsign -v -i "${5}"
+ ;;
+*)
+ LIBPATH=`(cd "${1}"/lib; pwd)`:`(cd "${4}"; pwd)`:$LIBPATH
+ export LIBPATH
+ SHLIB_PATH=${1}/lib:${4}:$SHLIB_PATH
+ export SHLIB_PATH
+ LD_LIBRARY_PATH=${1}/lib:${4}:$LD_LIBRARY_PATH
+ export LD_LIBRARY_PATH
+ DYLD_LIBRARY_PATH=${1}/lib:${4}:$DYLD_LIBRARY_PATH
+ export DYLD_LIBRARY_PATH
+ LIBRARY_PATH=${1}/lib:${4}:$LIBRARY_PATH
+ export LIBRARY_PATH
+ ADDON_PATH=${1}/lib:${4}:$ADDON_PATH
+ export ADDON_PATH
+ echo "${2}"/shlibsign -v -i "${5}"
+ "${2}"/shlibsign -v -i "${5}"
+ ;;
+esac
diff --git a/security/nss/cmd/signtool/Makefile b/security/nss/cmd/signtool/Makefile
new file mode 100644
index 000000000..408ee6da4
--- /dev/null
+++ b/security/nss/cmd/signtool/Makefile
@@ -0,0 +1,44 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+include $(CORE_DEPTH)/coreconf/zlib.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/security/nss/cmd/signtool/README b/security/nss/cmd/signtool/README
new file mode 100644
index 000000000..100fb2778
--- /dev/null
+++ b/security/nss/cmd/signtool/README
@@ -0,0 +1,128 @@
+ Signing Tool (signtool)
+ 3.10 Release Notes
+ ========================================
+
+Documentation is provided online at mozilla.org
+
+Problems or questions not covered by the online documentation can be
+discussed in the DevEdge Security Newsgroup.
+
+=== New Features in 3.10
+=======================
+One new option (-X) has been added to create a Mozilla aware signed XPI archive.
+The option must be accompanied by the -Z option. This new option
+creates a JAR file with the META-INF/zigbert.rsa/dsa file as the first file in
+the archive instead of the default third to last. This will enable the archive
+to be seen as signed by products incorporating XPInstall. i.e. .xpi extensions
+for FireFox or Mozilla.
+
+=== New Features in 1.3
+=======================
+
+The security library components have been upgraded to utilize NSS_2_7_1_RTM.
+This means that the maximum RSA keysize now supported should be 4096 bits.
+
+=== Zigbert 0.6 Support
+=======================
+This program was previously named Zigbert. The last version of zigbert
+was Zigbert 0.6. Because all the functionality of Zigbert is maintained in
+signtool 1.2, Zigbert is no longer supported. If you have problems
+using Zigbert, please upgrade to signtool 1.2.
+
+=== New Features in 1.2
+=======================
+
+Certificate Generation Improvements
+-----------------------------------
+Two new options have been added to control generation of self-signed object
+signing certificates with the -G option. The -s option takes the size (in bits)
+of the generated RSA private key. The -t option takes the name of the PKCS #11
+token on which to generate the keypair and install the certificate. Both
+options are optional. By default, the private key is 1024 bits and is generated
+on the internal software token.
+
+
+=== New Features in 1.1
+=======================
+
+File I/O
+--------
+Signtool can now read its options from a command file specified with the -f
+option on the command line. The format for the file is described in the
+documentation.
+Error messages and informational output can be redirected to an output file
+by supplying the "--outfile" option on the command line or the "outfile="
+option in the command file.
+
+New Options
+-----------
+"--norecurse" tells Signtool not to recurse into subdirectories when signing
+directories or parsing HTML with the -J option.
+"--leavearc" tells Signtool not to delete the temporary .arc directories
+produced by the -J option. This can aid debugging.
+"--verbosity" tells Signtool how much information to display. 0 is the
+default. -1 suppresses most messages, except for errors.
+
+=== Bug Fixes in 1.1
+====================
+
+-J option revamped
+------------------
+The -J option, which parses HTML files, extracts Java and Javascript code,
+and stores them in signed JAR files, has been re-implemented. Several bugs
+have been fixed:
+- CODEBASE attribute is no longer ignored
+- CLASS and SRC attributes can be be paths ("xxx/xxx/x.class") rather than
+ just filenames ("x.class").
+- LINK tags are handled correctly
+- various HTML parsing bugs fixed
+- error messages are more informative
+
+No Password on Key Database
+---------------------------
+If you had not yet set a Communicator password (which locks key3.db, the
+key database), signtool would fail with a cryptic error message whenever it
+attempted to verify the password. Now this condition is detected at the
+beginning of the program, and a more informative message is displayed.
+
+-x and -e Options
+-----------------
+Previously, only one of each of these options could be specified on the command
+line. Now arbitrarily many can be specified. For example, to sign only files
+with .class or .js extensions, the arguments "-eclass -ejs" could both be
+specified. To exclude the directories "subdir1" and "subdir2" from signing,
+the arguments "-x subdir1 -x subdir2" could both be specified.
+
+New Features in 1.0
+===================
+
+Creation of JAR files
+----------------------
+The -Z option causes signtool to output a JAR file formed by storing the
+signed archive in ZIP format. This eliminates the need to use a separate ZIP
+utility. The -c option specifies the compression level of the resulting
+JAR file.
+
+Generation of Object-Signing Certificates and Keys
+--------------------------------------------------
+The -G option will create a new, self-signed object-signing certificate
+which can be used for testing purposes. The generated certificate and
+associated public and private keys will be installed in the cert7.db and
+key3.db files in the directory specified with the -d option (unless the key
+is generated on an external token using the -t option). On Unix systems,
+if no directory is specified, the user's Netscape directory (~/.netscape)
+will be used. In addition, the certificate is output in X509 format to the
+files x509.raw and x509.cacert in the current directory. x509.cacert can
+be published on a web page and imported into browsers that visit that page.
+
+Extraction and Signing of JavaScript from HTML
+----------------------------------------------
+The -J option activates the same functionality provided by the signpages
+Perl script. It will parse a directory of html files, creating archives
+of the JavaScript called from the HTML. These archives are then signed and
+made into JAR files.
+
+Enhanced Smart Card Support
+---------------------------
+Certificates that reside on smart cards are displayed when using the -L and
+-l options.
diff --git a/security/nss/cmd/signtool/certgen.c b/security/nss/cmd/signtool/certgen.c
new file mode 100644
index 000000000..e095a01fb
--- /dev/null
+++ b/security/nss/cmd/signtool/certgen.c
@@ -0,0 +1,713 @@
+/* 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/. */
+
+#include "signtool.h"
+
+#include "secoid.h"
+#include "cryptohi.h"
+#include "certdb.h"
+
+static char *GetSubjectFromUser(unsigned long serial);
+static CERTCertificate *GenerateSelfSignedObjectSigningCert(char *nickname,
+ CERTCertDBHandle *db, char *subject, unsigned long serial, int keysize,
+ char *token);
+static SECStatus ChangeTrustAttributes(CERTCertDBHandle *db,
+ CERTCertificate *cert, char *trusts);
+static SECStatus set_cert_type(CERTCertificate *cert, unsigned int type);
+static SECItem *sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk);
+static CERTCertificate *install_cert(CERTCertDBHandle *db, SECItem *derCert,
+ char *nickname);
+static SECStatus GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk,
+ SECKEYPrivateKey **privk, int keysize);
+static CERTCertificateRequest *make_cert_request(char *subject,
+ SECKEYPublicKey *pubk);
+static CERTCertificate *make_cert(CERTCertificateRequest *req,
+ unsigned long serial, CERTName *ca_subject);
+static void output_ca_cert(CERTCertificate *cert, CERTCertDBHandle *db);
+
+/***********************************************************************
+ *
+ * G e n e r a t e C e r t
+ *
+ * Runs the whole process of creating a new cert, getting info from the
+ * user, etc.
+ */
+int
+GenerateCert(char *nickname, int keysize, char *token)
+{
+ CERTCertDBHandle *db;
+ CERTCertificate *cert;
+ char *subject;
+ unsigned long serial;
+ char stdinbuf[160];
+
+ /* Print warning about having the browser open */
+ PR_fprintf(PR_STDOUT /*always go to console*/,
+ "\nWARNING: Performing this operation while the browser is running could cause"
+ "\ncorruption of your security databases. If the browser is currently running,"
+ "\nyou should exit the browser before continuing this operation. Enter "
+ "\n\"y\" to continue, or anything else to abort: ");
+ pr_fgets(stdinbuf, 160, PR_STDIN);
+ PR_fprintf(PR_STDOUT, "\n");
+ if (tolower(stdinbuf[0]) != 'y') {
+ PR_fprintf(errorFD, "Operation aborted at user's request.\n");
+ errorCount++;
+ return -1;
+ }
+
+ db = CERT_GetDefaultCertDB();
+ if (!db) {
+ FatalError("Unable to open certificate database");
+ }
+
+ if (PK11_FindCertFromNickname(nickname, &pwdata)) {
+ PR_fprintf(errorFD,
+ "ERROR: Certificate with nickname \"%s\" already exists in database. You\n"
+ "must choose a different nickname.\n",
+ nickname);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ LL_L2UI(serial, PR_Now());
+
+ subject = GetSubjectFromUser(serial);
+ if (!subject) {
+ FatalError("Unable to get subject from user");
+ }
+
+ cert = GenerateSelfSignedObjectSigningCert(nickname, db, subject,
+ serial, keysize, token);
+
+ if (cert) {
+ output_ca_cert(cert, db);
+ CERT_DestroyCertificate(cert);
+ }
+
+ PORT_Free(subject);
+ return 0;
+}
+
+#undef VERBOSE_PROMPTS
+
+/*********************************************************************8
+ * G e t S u b j e c t F r o m U s e r
+ *
+ * Construct the subject information line for a certificate by querying
+ * the user on stdin.
+ */
+static char *
+GetSubjectFromUser(unsigned long serial)
+{
+ char buf[STDIN_BUF_SIZE];
+ char common_name_buf[STDIN_BUF_SIZE];
+ char *common_name, *state, *orgunit, *country, *org, *locality;
+ char *email, *uid;
+ char *subject;
+ char *cp;
+ int subjectlen = 0;
+
+ common_name = state = orgunit = country = org = locality = email =
+ uid = subject = NULL;
+
+ /* Get subject information */
+ PR_fprintf(PR_STDOUT,
+ "\nEnter certificate information. All fields are optional. Acceptable\n"
+ "characters are numbers, letters, spaces, and apostrophes.\n");
+
+#ifdef VERBOSE_PROMPTS
+ PR_fprintf(PR_STDOUT, "\nCOMMON NAME\n"
+ "Enter the full name you want to give your certificate. (Example: Test-Only\n"
+ "Object Signing Certificate)\n"
+ "-->");
+#else
+ PR_fprintf(PR_STDOUT, "certificate common name: ");
+#endif
+ if (!fgets(buf, STDIN_BUF_SIZE, stdin)) {
+ return NULL;
+ }
+ cp = chop(buf);
+ if (*cp == '\0') {
+ sprintf(common_name_buf, "%s (%lu)", DEFAULT_COMMON_NAME,
+ serial);
+ cp = common_name_buf;
+ }
+ common_name = PORT_ZAlloc(strlen(cp) + 6);
+ if (!common_name) {
+ out_of_memory();
+ }
+ sprintf(common_name, "CN=%s, ", cp);
+ subjectlen += strlen(common_name);
+
+#ifdef VERBOSE_PROMPTS
+ PR_fprintf(PR_STDOUT, "\nORGANIZATION NAME\n"
+ "Enter the name of your organization. For example, this could be the name\n"
+ "of your company.\n"
+ "-->");
+#else
+ PR_fprintf(PR_STDOUT, "organization: ");
+#endif
+ if (!fgets(buf, STDIN_BUF_SIZE, stdin)) {
+ return NULL;
+ }
+ cp = chop(buf);
+ if (*cp != '\0') {
+ org = PORT_ZAlloc(strlen(cp) + 5);
+ if (!org) {
+ out_of_memory();
+ }
+ sprintf(org, "O=%s, ", cp);
+ subjectlen += strlen(org);
+ }
+
+#ifdef VERBOSE_PROMPTS
+ PR_fprintf(PR_STDOUT, "\nORGANIZATION UNIT\n"
+ "Enter the name of your organization unit. For example, this could be the\n"
+ "name of your department.\n"
+ "-->");
+#else
+ PR_fprintf(PR_STDOUT, "organization unit: ");
+#endif
+ if (!fgets(buf, STDIN_BUF_SIZE, stdin)) {
+ return NULL;
+ }
+ cp = chop(buf);
+ if (*cp != '\0') {
+ orgunit = PORT_ZAlloc(strlen(cp) + 6);
+ if (!orgunit) {
+ out_of_memory();
+ }
+ sprintf(orgunit, "OU=%s, ", cp);
+ subjectlen += strlen(orgunit);
+ }
+
+#ifdef VERBOSE_PROMPTS
+ PR_fprintf(PR_STDOUT, "\nSTATE\n"
+ "Enter the name of your state or province.\n"
+ "-->");
+#else
+ PR_fprintf(PR_STDOUT, "state or province: ");
+#endif
+ if (!fgets(buf, STDIN_BUF_SIZE, stdin)) {
+ return NULL;
+ }
+ cp = chop(buf);
+ if (*cp != '\0') {
+ state = PORT_ZAlloc(strlen(cp) + 6);
+ if (!state) {
+ out_of_memory();
+ }
+ sprintf(state, "ST=%s, ", cp);
+ subjectlen += strlen(state);
+ }
+
+#ifdef VERBOSE_PROMPTS
+ PR_fprintf(PR_STDOUT, "\nCOUNTRY\n"
+ "Enter the 2-character abbreviation for the name of your country.\n"
+ "-->");
+#else
+ PR_fprintf(PR_STDOUT, "country (must be exactly 2 characters): ");
+#endif
+ if (!fgets(buf, STDIN_BUF_SIZE, stdin)) {
+ return NULL;
+ }
+ cp = chop(cp);
+ if (strlen(cp) != 2) {
+ *cp = '\0'; /* country code must be 2 chars */
+ }
+ if (*cp != '\0') {
+ country = PORT_ZAlloc(strlen(cp) + 5);
+ if (!country) {
+ out_of_memory();
+ }
+ sprintf(country, "C=%s, ", cp);
+ subjectlen += strlen(country);
+ }
+
+#ifdef VERBOSE_PROMPTS
+ PR_fprintf(PR_STDOUT, "\nUSERNAME\n"
+ "Enter your system username or UID\n"
+ "-->");
+#else
+ PR_fprintf(PR_STDOUT, "username: ");
+#endif
+ if (!fgets(buf, STDIN_BUF_SIZE, stdin)) {
+ return NULL;
+ }
+ cp = chop(buf);
+ if (*cp != '\0') {
+ uid = PORT_ZAlloc(strlen(cp) + 7);
+ if (!uid) {
+ out_of_memory();
+ }
+ sprintf(uid, "UID=%s, ", cp);
+ subjectlen += strlen(uid);
+ }
+
+#ifdef VERBOSE_PROMPTS
+ PR_fprintf(PR_STDOUT, "\nEMAIL ADDRESS\n"
+ "Enter your email address.\n"
+ "-->");
+#else
+ PR_fprintf(PR_STDOUT, "email address: ");
+#endif
+ if (!fgets(buf, STDIN_BUF_SIZE, stdin)) {
+ return NULL;
+ }
+ cp = chop(buf);
+ if (*cp != '\0') {
+ email = PORT_ZAlloc(strlen(cp) + 5);
+ if (!email) {
+ out_of_memory();
+ }
+ sprintf(email, "E=%s,", cp);
+ subjectlen += strlen(email);
+ }
+
+ subjectlen++;
+
+ subject = PORT_ZAlloc(subjectlen);
+ if (!subject) {
+ out_of_memory();
+ }
+
+ sprintf(subject, "%s%s%s%s%s%s%s",
+ common_name ? common_name : "",
+ org ? org : "",
+ orgunit ? orgunit : "",
+ state ? state : "",
+ country ? country : "",
+ uid ? uid : "",
+ email ? email : "");
+ if ((strlen(subject) > 1) && (subject[strlen(subject) - 1] == ' ')) {
+ subject[strlen(subject) - 2] = '\0';
+ }
+
+ PORT_Free(common_name);
+ PORT_Free(org);
+ PORT_Free(orgunit);
+ PORT_Free(state);
+ PORT_Free(country);
+ PORT_Free(uid);
+ PORT_Free(email);
+
+ return subject;
+}
+
+/**************************************************************************
+ *
+ * G e n e r a t e S e l f S i g n e d O b j e c t S i g n i n g C e r t
+ * *phew*^
+ *
+ */
+static CERTCertificate *
+GenerateSelfSignedObjectSigningCert(char *nickname, CERTCertDBHandle *db,
+ char *subject, unsigned long serial, int keysize, char *token)
+{
+ CERTCertificate *cert, *temp_cert;
+ SECItem *derCert;
+ CERTCertificateRequest *req;
+
+ PK11SlotInfo *slot = NULL;
+ SECKEYPrivateKey *privk = NULL;
+ SECKEYPublicKey *pubk = NULL;
+
+ if (token) {
+ slot = PK11_FindSlotByName(token);
+ } else {
+ slot = PK11_GetInternalKeySlot();
+ }
+
+ if (slot == NULL) {
+ PR_fprintf(errorFD, "Can't find PKCS11 slot %s\n",
+ token ? token : "");
+ errorCount++;
+ exit(ERRX);
+ }
+
+ if (GenerateKeyPair(slot, &pubk, &privk, keysize) != SECSuccess) {
+ FatalError("Error generating keypair.");
+ }
+ req = make_cert_request(subject, pubk);
+ temp_cert = make_cert(req, serial, &req->subject);
+ if (set_cert_type(temp_cert,
+ NS_CERT_TYPE_OBJECT_SIGNING |
+ NS_CERT_TYPE_OBJECT_SIGNING_CA) !=
+ SECSuccess) {
+ FatalError("Unable to set cert type");
+ }
+
+ derCert = sign_cert(temp_cert, privk);
+ cert = install_cert(db, derCert, nickname);
+ if (ChangeTrustAttributes(db, cert, ",,uC") != SECSuccess) {
+ FatalError("Unable to change trust on generated certificate");
+ }
+
+ /* !!! Free memory ? !!! */
+ PK11_FreeSlot(slot);
+ SECKEY_DestroyPrivateKey(privk);
+ SECKEY_DestroyPublicKey(pubk);
+ CERT_DestroyCertificate(temp_cert);
+ CERT_DestroyCertificateRequest(req);
+
+ return cert;
+}
+
+/**************************************************************************
+ *
+ * C h a n g e T r u s t A t t r i b u t e s
+ */
+static SECStatus
+ChangeTrustAttributes(CERTCertDBHandle *db, CERTCertificate *cert, char *trusts)
+{
+
+ CERTCertTrust *trust;
+
+ if (!db || !cert || !trusts) {
+ PR_fprintf(errorFD, "ChangeTrustAttributes got incomplete arguments.\n");
+ errorCount++;
+ return SECFailure;
+ }
+
+ trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust));
+ if (!trust) {
+ PR_fprintf(errorFD, "ChangeTrustAttributes unable to allocate "
+ "CERTCertTrust\n");
+ errorCount++;
+ return SECFailure;
+ }
+
+ if (CERT_DecodeTrustString(trust, trusts)) {
+ return SECFailure;
+ }
+
+ if (CERT_ChangeCertTrust(db, cert, trust)) {
+ PR_fprintf(errorFD, "unable to modify trust attributes for cert %s\n",
+ cert->nickname ? cert->nickname : "");
+ errorCount++;
+ return SECFailure;
+ }
+
+ PORT_Free(trust);
+ return SECSuccess;
+}
+
+/*************************************************************************
+ *
+ * s e t _ c e r t _ t y p e
+ */
+static SECStatus
+set_cert_type(CERTCertificate *cert, unsigned int type)
+{
+ void *context;
+ SECStatus status = SECSuccess;
+ SECItem certType;
+ char ctype;
+
+ context = CERT_StartCertExtensions(cert);
+
+ certType.type = siBuffer;
+ certType.data = (unsigned char *)&ctype;
+ certType.len = 1;
+ ctype = (unsigned char)type;
+ if (CERT_EncodeAndAddBitStrExtension(context, SEC_OID_NS_CERT_EXT_CERT_TYPE,
+ &certType, PR_TRUE /*critical*/) !=
+ SECSuccess) {
+ status = SECFailure;
+ }
+
+ if (CERT_FinishExtensions(context) != SECSuccess) {
+ status = SECFailure;
+ }
+
+ return status;
+}
+
+/********************************************************************
+ *
+ * s i g n _ c e r t
+ */
+static SECItem *
+sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk)
+{
+ SECStatus rv;
+
+ SECItem der2;
+ SECItem *result2;
+
+ SECOidTag alg = SEC_OID_UNKNOWN;
+
+ alg = SEC_GetSignatureAlgorithmOidTag(privk->keyType, SEC_OID_UNKNOWN);
+ if (alg == SEC_OID_UNKNOWN) {
+ FatalError("Unknown key type");
+ }
+
+ rv = SECOID_SetAlgorithmID(cert->arena, &cert->signature, alg, 0);
+
+ if (rv != SECSuccess) {
+ PR_fprintf(errorFD, "%s: unable to set signature alg id\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ der2.len = 0;
+ der2.data = NULL;
+
+ (void)SEC_ASN1EncodeItem(cert->arena, &der2, cert, SEC_ASN1_GET(CERT_CertificateTemplate));
+
+ if (rv != SECSuccess) {
+ PR_fprintf(errorFD, "%s: error encoding cert\n", PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ result2 = (SECItem *)PORT_ArenaZAlloc(cert->arena, sizeof(SECItem));
+ if (result2 == NULL)
+ out_of_memory();
+
+ rv = SEC_DerSignData(cert->arena, result2, der2.data, der2.len, privk, alg);
+
+ if (rv != SECSuccess) {
+ PR_fprintf(errorFD, "can't sign encoded certificate data\n");
+ errorCount++;
+ exit(ERRX);
+ } else if (verbosity >= 0) {
+ PR_fprintf(outputFD, "certificate has been signed\n");
+ }
+
+ cert->derCert = *result2;
+
+ return result2;
+}
+
+/*********************************************************************
+ *
+ * i n s t a l l _ c e r t
+ *
+ * Installs the cert in the permanent database.
+ */
+static CERTCertificate *
+install_cert(CERTCertDBHandle *db, SECItem *derCert, char *nickname)
+{
+ CERTCertificate *newcert;
+ PK11SlotInfo *newSlot;
+
+ newSlot = PK11_ImportDERCertForKey(derCert, nickname, &pwdata);
+ if (newSlot == NULL) {
+ PR_fprintf(errorFD, "Unable to install certificate\n");
+ errorCount++;
+ exit(ERRX);
+ }
+
+ newcert = PK11_FindCertFromDERCertItem(newSlot, derCert, &pwdata);
+ PK11_FreeSlot(newSlot);
+ if (newcert == NULL) {
+ PR_fprintf(errorFD, "%s: can't find new certificate\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "certificate \"%s\" added to database\n",
+ nickname);
+ }
+
+ return newcert;
+}
+
+/******************************************************************
+ *
+ * G e n e r a t e K e y P a i r
+ */
+static SECStatus
+GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk,
+ SECKEYPrivateKey **privk, int keysize)
+{
+
+ PK11RSAGenParams rsaParams;
+
+ if (keysize == -1) {
+ rsaParams.keySizeInBits = DEFAULT_RSA_KEY_SIZE;
+ } else {
+ rsaParams.keySizeInBits = keysize;
+ }
+ rsaParams.pe = 0x10001;
+
+ if (PK11_Authenticate(slot, PR_FALSE /*loadCerts*/, &pwdata) !=
+ SECSuccess) {
+ SECU_PrintError(progName, "failure authenticating to key database.\n");
+ exit(ERRX);
+ }
+
+ *privk = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams,
+
+ pubk, PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/, &pwdata);
+
+ if (*privk != NULL && *pubk != NULL) {
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "generated public/private key pair\n");
+ }
+ } else {
+ SECU_PrintError(progName, "failure generating key pair\n");
+ exit(ERRX);
+ }
+
+ return SECSuccess;
+}
+
+/******************************************************************
+ *
+ * m a k e _ c e r t _ r e q u e s t
+ */
+static CERTCertificateRequest *
+make_cert_request(char *subject, SECKEYPublicKey *pubk)
+{
+ CERTName *subj;
+ CERTSubjectPublicKeyInfo *spki;
+
+ CERTCertificateRequest *req;
+
+ /* Create info about public key */
+ spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
+ if (!spki) {
+ SECU_PrintError(progName, "unable to create subject public key");
+ exit(ERRX);
+ }
+
+ subj = CERT_AsciiToName(subject);
+ if (subj == NULL) {
+ FatalError("Invalid data in certificate description");
+ }
+
+ /* Generate certificate request */
+ req = CERT_CreateCertificateRequest(subj, spki, 0);
+ if (!req) {
+ SECU_PrintError(progName, "unable to make certificate request");
+ exit(ERRX);
+ }
+
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+ CERT_DestroyName(subj);
+
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "certificate request generated\n");
+ }
+
+ return req;
+}
+
+/******************************************************************
+ *
+ * m a k e _ c e r t
+ */
+static CERTCertificate *
+make_cert(CERTCertificateRequest *req, unsigned long serial,
+ CERTName *ca_subject)
+{
+ CERTCertificate *cert;
+
+ CERTValidity *validity = NULL;
+
+ PRTime now, after;
+ PRExplodedTime printableTime;
+
+ now = PR_Now();
+ PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
+
+ printableTime.tm_month += 3;
+ after = PR_ImplodeTime(&printableTime);
+
+ validity = CERT_CreateValidity(now, after);
+
+ if (validity == NULL) {
+ PR_fprintf(errorFD, "%s: error creating certificate validity\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ cert = CERT_CreateCertificate(serial, ca_subject, validity, req);
+ CERT_DestroyValidity(validity);
+
+ if (cert == NULL) {
+ /* should probably be more precise here */
+ PR_fprintf(errorFD, "%s: error while generating certificate\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ return cert;
+}
+
+/*************************************************************************
+ *
+ * o u t p u t _ c a _ c e r t
+ */
+static void
+output_ca_cert(CERTCertificate *cert, CERTCertDBHandle *db)
+{
+ FILE *out;
+
+ SECItem *encodedCertChain;
+ SEC_PKCS7ContentInfo *certChain;
+ char *filename, *certData;
+
+ /* the raw */
+
+ filename = PORT_ZAlloc(strlen(DEFAULT_X509_BASENAME) + 8);
+ if (!filename)
+ out_of_memory();
+
+ sprintf(filename, "%s.raw", DEFAULT_X509_BASENAME);
+ if ((out = fopen(filename, "wb")) == NULL) {
+ PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME,
+ filename);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ certChain = SEC_PKCS7CreateCertsOnly(cert, PR_TRUE, db);
+ encodedCertChain =
+ SEC_PKCS7EncodeItem(NULL, NULL, certChain, NULL, NULL, NULL);
+ SEC_PKCS7DestroyContentInfo(certChain);
+
+ if (encodedCertChain) {
+ fprintf(out, "Content-type: application/x-x509-ca-cert\n\n");
+ fwrite(encodedCertChain->data, 1, encodedCertChain->len,
+ out);
+ SECITEM_FreeItem(encodedCertChain, PR_TRUE);
+ } else {
+ PR_fprintf(errorFD, "%s: Can't DER encode this certificate\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ fclose(out);
+
+ /* and the cooked */
+
+ sprintf(filename, "%s.cacert", DEFAULT_X509_BASENAME);
+ if ((out = fopen(filename, "wb")) == NULL) {
+ PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME,
+ filename);
+ errorCount++;
+ return;
+ }
+
+ certData = BTOA_DataToAscii(cert->derCert.data, cert->derCert.len);
+ fprintf(out, "%s\n%s\n%s\n", NS_CERT_HEADER, certData, NS_CERT_TRAILER);
+ PORT_Free(certData);
+
+ PORT_Free(filename);
+ fclose(out);
+
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "Exported certificate to %s.raw and %s.cacert.\n",
+ DEFAULT_X509_BASENAME, DEFAULT_X509_BASENAME);
+ }
+}
diff --git a/security/nss/cmd/signtool/javascript.c b/security/nss/cmd/signtool/javascript.c
new file mode 100644
index 000000000..746f724f8
--- /dev/null
+++ b/security/nss/cmd/signtool/javascript.c
@@ -0,0 +1,1817 @@
+/* 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/. */
+
+#include "signtool.h"
+#include <prmem.h>
+#include <prio.h>
+#include <prenv.h>
+
+static int javascript_fn(char *relpath, char *basedir, char *reldir,
+ char *filename, void *arg);
+static int extract_js(char *filename);
+static int copyinto(char *from, char *to);
+static PRStatus ensureExists(char *base, char *path);
+static int make_dirs(char *path, PRInt32 file_perms);
+
+static char *jartree = NULL;
+static int idOrdinal;
+static PRBool dumpParse = PR_FALSE;
+
+static char *event_handlers[] = {
+ "onAbort",
+ "onBlur",
+ "onChange",
+ "onClick",
+ "onDblClick",
+ "onDragDrop",
+ "onError",
+ "onFocus",
+ "onKeyDown",
+ "onKeyPress",
+ "onKeyUp",
+ "onLoad",
+ "onMouseDown",
+ "onMouseMove",
+ "onMouseOut",
+ "onMouseOver",
+ "onMouseUp",
+ "onMove",
+ "onReset",
+ "onResize",
+ "onSelect",
+ "onSubmit",
+ "onUnload"
+};
+
+static int num_handlers = 23;
+
+/*
+ * I n l i n e J a v a S c r i p t
+ *
+ * Javascript signing. Instead of passing an archive to signtool,
+ * a directory containing html files is given. Archives are created
+ * from the archive= and src= tag attributes inside the html,
+ * as appropriate. Then the archives are signed.
+ *
+ */
+int
+InlineJavaScript(char *dir, PRBool recurse)
+{
+ jartree = dir;
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "\nGenerating inline signatures from HTML files in: %s\n",
+ dir);
+ }
+ if (PR_GetEnvSecure("SIGNTOOL_DUMP_PARSE")) {
+ dumpParse = PR_TRUE;
+ }
+
+ return foreach (dir, "", javascript_fn, recurse, PR_FALSE /*include dirs*/,
+ (void *)NULL);
+}
+
+/************************************************************************
+ *
+ * j a v a s c r i p t _ f n
+ */
+static int
+javascript_fn(char *relpath, char *basedir, char *reldir, char *filename, void *arg)
+{
+ char fullname[FNSIZE];
+
+ /* only process inline scripts from .htm, .html, and .shtml*/
+
+ if (!(PL_strcaserstr(filename, ".htm") == filename + strlen(filename) - 4) &&
+ !(PL_strcaserstr(filename, ".html") == filename + strlen(filename) - 5) &&
+ !(PL_strcaserstr(filename, ".shtml") == filename + strlen(filename) - 6)) {
+ return 0;
+ }
+
+ /* don't process scripts that signtool has already
+ extracted (those that are inside .arc directories) */
+
+ if (PL_strcaserstr(filename, ".arc") == filename + strlen(filename) - 4)
+ return 0;
+
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "Processing HTML file: %s\n", relpath);
+ }
+
+ /* reset firstArchive at top of each HTML file */
+
+ /* skip directories that contain extracted scripts */
+
+ if (PL_strcaserstr(reldir, ".arc") == reldir + strlen(reldir) - 4)
+ return 0;
+
+ sprintf(fullname, "%s/%s", basedir, relpath);
+ return extract_js(fullname);
+}
+
+/*===========================================================================
+ =
+ = D A T A S T R U C T U R E S
+ =
+*/
+typedef enum {
+ TEXT_HTML_STATE = 0,
+ SCRIPT_HTML_STATE
+}
+
+HTML_STATE;
+
+typedef enum {
+ /* we start in the start state */
+ START_STATE,
+
+ /* We are looking for or reading in an attribute */
+ GET_ATT_STATE,
+
+ /* We're burning ws before finding an attribute */
+ PRE_ATT_WS_STATE,
+
+ /* We're burning ws after an attribute. Looking for an '='. */
+ POST_ATT_WS_STATE,
+
+ /* We're burning ws after an '=', waiting for a value */
+ PRE_VAL_WS_STATE,
+
+ /* We're reading in a value */
+ GET_VALUE_STATE,
+
+ /* We're reading in a value that's inside quotes */
+ GET_QUOTED_VAL_STATE,
+
+ /* We've encountered the closing '>' */
+ DONE_STATE,
+
+ /* Error state */
+ ERR_STATE
+}
+
+TAG_STATE;
+
+typedef struct AVPair_Str {
+ char *attribute;
+ char *value;
+ unsigned int valueLine; /* the line that the value ends on */
+ struct AVPair_Str *next;
+} AVPair;
+
+typedef enum {
+ APPLET_TAG,
+ SCRIPT_TAG,
+ LINK_TAG,
+ STYLE_TAG,
+ COMMENT_TAG,
+ OTHER_TAG
+}
+
+TAG_TYPE;
+
+typedef struct {
+ TAG_TYPE type;
+ AVPair *attList;
+ AVPair *attListTail;
+ char *text;
+} TagItem;
+
+typedef enum {
+ TAG_ITEM,
+ TEXT_ITEM
+}
+
+ITEM_TYPE;
+
+typedef struct HTMLItem_Str {
+ unsigned int startLine;
+ unsigned int endLine;
+ ITEM_TYPE type;
+ union {
+ TagItem *tag;
+ char *text;
+ } item;
+ struct HTMLItem_Str *next;
+} HTMLItem;
+
+typedef struct {
+ PRFileDesc *fd;
+ PRInt32 curIndex;
+ PRBool IsEOF;
+#define FILE_BUFFER_BUFSIZE 512
+ char buf[FILE_BUFFER_BUFSIZE];
+ PRInt32 startOffset;
+ PRInt32 maxIndex;
+ unsigned int lineNum;
+} FileBuffer;
+
+/*===========================================================================
+ =
+ = F U N C T I O N S
+ =
+*/
+static HTMLItem *CreateTextItem(char *text, unsigned int startline,
+ unsigned int endline);
+static HTMLItem *CreateTagItem(TagItem *ti, unsigned int startline,
+ unsigned int endline);
+static TagItem *ProcessTag(FileBuffer *fb, char **errStr);
+static void DestroyHTMLItem(HTMLItem *item);
+static void DestroyTagItem(TagItem *ti);
+static TAG_TYPE GetTagType(char *att);
+static FileBuffer *FB_Create(PRFileDesc *fd);
+static int FB_GetChar(FileBuffer *fb);
+static PRInt32 FB_GetPointer(FileBuffer *fb);
+static PRInt32 FB_GetRange(FileBuffer *fb, PRInt32 start, PRInt32 end,
+ char **buf);
+static unsigned int FB_GetLineNum(FileBuffer *fb);
+static void FB_Destroy(FileBuffer *fb);
+static void PrintTagItem(PRFileDesc *fd, TagItem *ti);
+static void PrintHTMLStream(PRFileDesc *fd, HTMLItem *head);
+
+/************************************************************************
+ *
+ * C r e a t e T e x t I t e m
+ */
+static HTMLItem *
+CreateTextItem(char *text, unsigned int startline, unsigned int endline)
+{
+ HTMLItem *item;
+
+ item = PR_Malloc(sizeof(HTMLItem));
+ if (!item) {
+ return NULL;
+ }
+
+ item->type = TEXT_ITEM;
+ item->item.text = text;
+ item->next = NULL;
+ item->startLine = startline;
+ item->endLine = endline;
+
+ return item;
+}
+
+/************************************************************************
+ *
+ * C r e a t e T a g I t e m
+ */
+static HTMLItem *
+CreateTagItem(TagItem *ti, unsigned int startline, unsigned int endline)
+{
+ HTMLItem *item;
+
+ item = PR_Malloc(sizeof(HTMLItem));
+ if (!item) {
+ return NULL;
+ }
+
+ item->type = TAG_ITEM;
+ item->item.tag = ti;
+ item->next = NULL;
+ item->startLine = startline;
+ item->endLine = endline;
+
+ return item;
+}
+
+static PRBool
+isAttChar(int c)
+{
+ return (isalnum(c) || c == '/' || c == '-');
+}
+
+/************************************************************************
+ *
+ * P r o c e s s T a g
+ */
+static TagItem *
+ProcessTag(FileBuffer *fb, char **errStr)
+{
+ TAG_STATE state;
+ PRInt32 startText, startID, curPos;
+ PRBool firstAtt;
+ int curchar;
+ TagItem *ti = NULL;
+ AVPair *curPair = NULL;
+ char quotechar = '\0';
+ unsigned int linenum;
+ unsigned int startline;
+
+ state = START_STATE;
+
+ startID = FB_GetPointer(fb);
+ startText = startID;
+ firstAtt = PR_TRUE;
+
+ ti = (TagItem *)PR_Malloc(sizeof(TagItem));
+ if (!ti)
+ out_of_memory();
+ ti->type = OTHER_TAG;
+ ti->attList = NULL;
+ ti->attListTail = NULL;
+ ti->text = NULL;
+
+ startline = FB_GetLineNum(fb);
+
+ while (state != DONE_STATE && state != ERR_STATE) {
+ linenum = FB_GetLineNum(fb);
+ curchar = FB_GetChar(fb);
+ if (curchar == EOF) {
+ *errStr = PR_smprintf(
+ "line %d: Unexpected end-of-file while parsing tag starting at line %d.\n",
+ linenum, startline);
+ state = ERR_STATE;
+ continue;
+ }
+
+ switch (state) {
+ case START_STATE:
+ if (curchar == '!') {
+ /*
+ * SGML tag or comment
+ * Here's the general rule for SGML tags. Everything from
+ * <! to > is the tag. Inside the tag, comments are
+ * delimited with --. So we are looking for the first '>'
+ * that is not commented out, that is, not inside a pair
+ * of --: <!DOCTYPE --this is a comment >(psyche!) -->
+ */
+
+ PRBool inComment = PR_FALSE;
+ short hyphenCount = 0; /* number of consecutive hyphens */
+
+ while (1) {
+ linenum = FB_GetLineNum(fb);
+ curchar = FB_GetChar(fb);
+ if (curchar == EOF) {
+ /* Uh oh, EOF inside comment */
+ *errStr = PR_smprintf(
+ "line %d: Unexpected end-of-file inside comment starting at line %d.\n",
+ linenum, startline);
+ state = ERR_STATE;
+ break;
+ }
+ if (curchar == '-') {
+ if (hyphenCount == 1) {
+ /* This is a comment delimiter */
+ inComment = !inComment;
+ hyphenCount = 0;
+ } else {
+ /* beginning of a comment delimiter? */
+ hyphenCount = 1;
+ }
+ } else if (curchar == '>') {
+ if (!inComment) {
+ /* This is the end of the tag */
+ state = DONE_STATE;
+ break;
+ } else {
+ /* The > is inside a comment, so it's not
+ * really the end of the tag */
+ hyphenCount = 0;
+ }
+ } else {
+ hyphenCount = 0;
+ }
+ }
+ ti->type = COMMENT_TAG;
+ break;
+ }
+ /* fall through */
+ case GET_ATT_STATE:
+ if (isspace(curchar) || curchar == '=' || curchar == '>') {
+ /* end of the current attribute */
+ curPos = FB_GetPointer(fb) - 2;
+ if (curPos >= startID) {
+ /* We have an attribute */
+ curPair = (AVPair *)PR_Malloc(sizeof(AVPair));
+ if (!curPair)
+ out_of_memory();
+ curPair->value = NULL;
+ curPair->next = NULL;
+ FB_GetRange(fb, startID, curPos,
+ &curPair->attribute);
+
+ /* Stick this attribute on the list */
+ if (ti->attListTail) {
+ ti->attListTail->next = curPair;
+ ti->attListTail = curPair;
+ } else {
+ ti->attList = ti->attListTail =
+ curPair;
+ }
+
+ /* If this is the first attribute, find the type of tag
+ * based on it. Also, start saving the text of the tag. */
+ if (firstAtt) {
+ ti->type = GetTagType(curPair->attribute);
+ startText = FB_GetPointer(fb) -
+ 1;
+ firstAtt = PR_FALSE;
+ }
+ } else {
+ if (curchar == '=') {
+ /* If we don't have any attribute but we do have an
+ * equal sign, that's an error */
+ *errStr = PR_smprintf("line %d: Malformed tag starting at line %d.\n",
+ linenum, startline);
+ state = ERR_STATE;
+ break;
+ }
+ }
+
+ /* Compute next state */
+ if (curchar == '=') {
+ startID = FB_GetPointer(fb);
+ state = PRE_VAL_WS_STATE;
+ } else if (curchar == '>') {
+ state = DONE_STATE;
+ } else if (curPair) {
+ state = POST_ATT_WS_STATE;
+ } else {
+ state = PRE_ATT_WS_STATE;
+ }
+ } else if (isAttChar(curchar)) {
+ /* Just another char in the attribute. Do nothing */
+ state = GET_ATT_STATE;
+ } else {
+ /* bogus char */
+ *errStr = PR_smprintf("line %d: Bogus chararacter '%c' in tag.\n",
+ linenum, curchar);
+ state = ERR_STATE;
+ break;
+ }
+ break;
+ case PRE_ATT_WS_STATE:
+ if (curchar == '>') {
+ state = DONE_STATE;
+ } else if (isspace(curchar)) {
+ /* more whitespace, do nothing */
+ } else if (isAttChar(curchar)) {
+ /* starting another attribute */
+ startID = FB_GetPointer(fb) - 1;
+ state = GET_ATT_STATE;
+ } else {
+ /* bogus char */
+ *errStr = PR_smprintf("line %d: Bogus character '%c' in tag.\n",
+ linenum, curchar);
+ state = ERR_STATE;
+ break;
+ }
+ break;
+ case POST_ATT_WS_STATE:
+ if (curchar == '>') {
+ state = DONE_STATE;
+ } else if (isspace(curchar)) {
+ /* more whitespace, do nothing */
+ } else if (isAttChar(curchar)) {
+ /* starting another attribute */
+ startID = FB_GetPointer(fb) - 1;
+ state = GET_ATT_STATE;
+ } else if (curchar == '=') {
+ /* there was whitespace between the attribute and its equal
+ * sign, which means there's a value coming up */
+ state = PRE_VAL_WS_STATE;
+ } else {
+ /* bogus char */
+ *errStr = PR_smprintf("line %d: Bogus character '%c' in tag.\n",
+ linenum, curchar);
+ state = ERR_STATE;
+ break;
+ }
+ break;
+ case PRE_VAL_WS_STATE:
+ if (curchar == '>') {
+ /* premature end-of-tag (sounds like a personal problem). */
+ *errStr = PR_smprintf(
+ "line %d: End of tag while waiting for value.\n",
+ linenum);
+ state = ERR_STATE;
+ break;
+ } else if (isspace(curchar)) {
+ /* more whitespace, do nothing */
+ break;
+ } else {
+ /* this must be some sort of value. Fall through
+ * to GET_VALUE_STATE */
+ startID = FB_GetPointer(fb) - 1;
+ state = GET_VALUE_STATE;
+ }
+ /* Fall through if we didn't break on '>' or whitespace */
+ case GET_VALUE_STATE:
+ if (isspace(curchar) || curchar == '>') {
+ /* end of value */
+ curPos = FB_GetPointer(fb) - 2;
+ if (curPos >= startID) {
+ /* Grab the value */
+ FB_GetRange(fb, startID, curPos,
+ &curPair->value);
+ curPair->valueLine = linenum;
+ } else {
+ /* empty value, leave as NULL */
+ }
+ if (isspace(curchar)) {
+ state = PRE_ATT_WS_STATE;
+ } else {
+ state = DONE_STATE;
+ }
+ } else if (curchar == '\"' || curchar == '\'') {
+ /* quoted value. Start recording the value inside the quote*/
+ startID = FB_GetPointer(fb);
+ state = GET_QUOTED_VAL_STATE;
+ PORT_Assert(quotechar == '\0');
+ quotechar = curchar; /* look for matching quote type */
+ } else {
+ /* just more value */
+ }
+ break;
+ case GET_QUOTED_VAL_STATE:
+ PORT_Assert(quotechar != '\0');
+ if (curchar == quotechar) {
+ /* end of quoted value */
+ curPos = FB_GetPointer(fb) - 2;
+ if (curPos >= startID) {
+ /* Grab the value */
+ FB_GetRange(fb, startID, curPos,
+ &curPair->value);
+ curPair->valueLine = linenum;
+ } else {
+ /* empty value, leave it as NULL */
+ }
+ state = GET_ATT_STATE;
+ quotechar = '\0';
+ startID = FB_GetPointer(fb);
+ } else {
+ /* more quoted value, continue */
+ }
+ break;
+ case DONE_STATE:
+ case ERR_STATE:
+ default:; /* should never get here */
+ }
+ }
+
+ if (state == DONE_STATE) {
+ /* Get the text of the tag */
+ curPos = FB_GetPointer(fb) - 1;
+ FB_GetRange(fb, startText, curPos, &ti->text);
+
+ /* Return the tag */
+ return ti;
+ }
+
+ /* Uh oh, an error. Kill the tag item*/
+ DestroyTagItem(ti);
+ return NULL;
+}
+
+/************************************************************************
+ *
+ * D e s t r o y H T M L I t e m
+ */
+static void
+DestroyHTMLItem(HTMLItem *item)
+{
+ if (item->type == TAG_ITEM) {
+ DestroyTagItem(item->item.tag);
+ } else {
+ if (item->item.text) {
+ PR_Free(item->item.text);
+ }
+ }
+}
+
+/************************************************************************
+ *
+ * D e s t r o y T a g I t e m
+ */
+static void
+DestroyTagItem(TagItem *ti)
+{
+ AVPair *temp;
+
+ if (ti->text) {
+ PR_Free(ti->text);
+ ti->text = NULL;
+ }
+
+ while (ti->attList) {
+ temp = ti->attList;
+ ti->attList = ti->attList->next;
+
+ if (temp->attribute) {
+ PR_Free(temp->attribute);
+ temp->attribute = NULL;
+ }
+ if (temp->value) {
+ PR_Free(temp->value);
+ temp->value = NULL;
+ }
+ PR_Free(temp);
+ }
+
+ PR_Free(ti);
+}
+
+/************************************************************************
+ *
+ * G e t T a g T y p e
+ */
+static TAG_TYPE
+GetTagType(char *att)
+{
+ if (!PORT_Strcasecmp(att, "APPLET")) {
+ return APPLET_TAG;
+ }
+ if (!PORT_Strcasecmp(att, "SCRIPT")) {
+ return SCRIPT_TAG;
+ }
+ if (!PORT_Strcasecmp(att, "LINK")) {
+ return LINK_TAG;
+ }
+ if (!PORT_Strcasecmp(att, "STYLE")) {
+ return STYLE_TAG;
+ }
+ return OTHER_TAG;
+}
+
+/************************************************************************
+ *
+ * F B _ C r e a t e
+ */
+static FileBuffer *
+FB_Create(PRFileDesc *fd)
+{
+ FileBuffer *fb;
+ PRInt32 amountRead;
+ PRInt32 storedOffset;
+
+ fb = (FileBuffer *)PR_Malloc(sizeof(FileBuffer));
+ fb->fd = fd;
+ storedOffset = PR_Seek(fd, 0, PR_SEEK_CUR);
+ PR_Seek(fd, 0, PR_SEEK_SET);
+ fb->startOffset = 0;
+ amountRead = PR_Read(fd, fb->buf, FILE_BUFFER_BUFSIZE);
+ if (amountRead == -1)
+ goto loser;
+ fb->maxIndex = amountRead - 1;
+ fb->curIndex = 0;
+ fb->IsEOF = (fb->curIndex > fb->maxIndex) ? PR_TRUE : PR_FALSE;
+ fb->lineNum = 1;
+
+ PR_Seek(fd, storedOffset, PR_SEEK_SET);
+ return fb;
+loser:
+ PR_Seek(fd, storedOffset, PR_SEEK_SET);
+ PR_Free(fb);
+ return NULL;
+}
+
+/************************************************************************
+ *
+ * F B _ G e t C h a r
+ */
+static int
+FB_GetChar(FileBuffer *fb)
+{
+ PRInt32 storedOffset;
+ PRInt32 amountRead;
+ int retval = -1;
+
+ if (fb->IsEOF) {
+ return EOF;
+ }
+
+ storedOffset = PR_Seek(fb->fd, 0, PR_SEEK_CUR);
+
+ retval = (unsigned char)fb->buf[fb->curIndex++];
+ if (retval == '\n')
+ fb->lineNum++;
+
+ if (fb->curIndex > fb->maxIndex) {
+ /* We're at the end of the buffer. Try to get some new data from the
+ * file */
+ fb->startOffset += fb->maxIndex + 1;
+ PR_Seek(fb->fd, fb->startOffset, PR_SEEK_SET);
+ amountRead = PR_Read(fb->fd, fb->buf, FILE_BUFFER_BUFSIZE);
+ if (amountRead == -1)
+ goto loser;
+ fb->maxIndex = amountRead - 1;
+ fb->curIndex = 0;
+ }
+
+ fb->IsEOF = (fb->curIndex > fb->maxIndex) ? PR_TRUE : PR_FALSE;
+
+loser:
+ PR_Seek(fb->fd, storedOffset, PR_SEEK_SET);
+ return retval;
+}
+
+/************************************************************************
+ *
+ * F B _ G e t L i n e N u m
+ *
+ */
+static unsigned int
+FB_GetLineNum(FileBuffer *fb)
+{
+ return fb->lineNum;
+}
+
+/************************************************************************
+ *
+ * F B _ G e t P o i n t e r
+ *
+ */
+static PRInt32
+FB_GetPointer(FileBuffer *fb)
+{
+ return fb->startOffset + fb->curIndex;
+}
+
+/************************************************************************
+ *
+ * F B _ G e t R a n g e
+ *
+ */
+static PRInt32
+FB_GetRange(FileBuffer *fb, PRInt32 start, PRInt32 end, char **buf)
+{
+ PRInt32 amountRead;
+ PRInt32 storedOffset;
+
+ *buf = PR_Malloc(end - start + 2);
+ if (*buf == NULL) {
+ return 0;
+ }
+
+ storedOffset = PR_Seek(fb->fd, 0, PR_SEEK_CUR);
+ PR_Seek(fb->fd, start, PR_SEEK_SET);
+ amountRead = PR_Read(fb->fd, *buf, end - start + 1);
+ PR_Seek(fb->fd, storedOffset, PR_SEEK_SET);
+ if (amountRead == -1) {
+ PR_Free(*buf);
+ *buf = NULL;
+ return 0;
+ }
+
+ (*buf)[end - start + 1] = '\0';
+ return amountRead;
+}
+
+/************************************************************************
+ *
+ * F B _ D e s t r o y
+ *
+ */
+static void
+FB_Destroy(FileBuffer *fb)
+{
+ if (fb) {
+ PR_Free(fb);
+ }
+}
+
+/************************************************************************
+ *
+ * P r i n t T a g I t e m
+ *
+ */
+static void
+PrintTagItem(PRFileDesc *fd, TagItem *ti)
+{
+ AVPair *pair;
+
+ PR_fprintf(fd, "TAG:\n----\nType: ");
+ switch (ti->type) {
+ case APPLET_TAG:
+ PR_fprintf(fd, "applet\n");
+ break;
+ case SCRIPT_TAG:
+ PR_fprintf(fd, "script\n");
+ break;
+ case LINK_TAG:
+ PR_fprintf(fd, "link\n");
+ break;
+ case STYLE_TAG:
+ PR_fprintf(fd, "style\n");
+ break;
+ case COMMENT_TAG:
+ PR_fprintf(fd, "comment\n");
+ break;
+ case OTHER_TAG:
+ default:
+ PR_fprintf(fd, "other\n");
+ break;
+ }
+
+ PR_fprintf(fd, "Attributes:\n");
+ for (pair = ti->attList; pair; pair = pair->next) {
+ PR_fprintf(fd, "\t%s=%s\n", pair->attribute,
+ pair->value ? pair->value : "");
+ }
+ PR_fprintf(fd, "Text:%s\n", ti->text ? ti->text : "");
+
+ PR_fprintf(fd, "---End of tag---\n");
+}
+
+/************************************************************************
+ *
+ * P r i n t H T M L S t r e a m
+ *
+ */
+static void
+PrintHTMLStream(PRFileDesc *fd, HTMLItem *head)
+{
+ while (head) {
+ if (head->type == TAG_ITEM) {
+ PrintTagItem(fd, head->item.tag);
+ } else {
+ PR_fprintf(fd, "\nTEXT:\n-----\n%s\n-----\n\n", head->item.text);
+ }
+ head = head->next;
+ }
+}
+
+/************************************************************************
+ *
+ * S a v e I n l i n e S c r i p t
+ *
+ */
+static int
+SaveInlineScript(char *text, char *id, char *basedir, char *archiveDir)
+{
+ char *filename = NULL;
+ PRFileDesc *fd = NULL;
+ int retval = -1;
+ PRInt32 writeLen;
+ char *ilDir = NULL;
+
+ if (!text || !id || !archiveDir) {
+ return -1;
+ }
+
+ if (dumpParse) {
+ PR_fprintf(outputFD, "SaveInlineScript: text=%s, id=%s, \n"
+ "basedir=%s, archiveDir=%s\n",
+ text, id, basedir, archiveDir);
+ }
+
+ /* Make sure the archive directory is around */
+ if (ensureExists(basedir, archiveDir) != PR_SUCCESS) {
+ PR_fprintf(errorFD,
+ "ERROR: Unable to create archive directory %s.\n", archiveDir);
+ errorCount++;
+ return -1;
+ }
+
+ /* Make sure the inline script directory is around */
+ ilDir = PR_smprintf("%s/inlineScripts", archiveDir);
+ scriptdir = "inlineScripts";
+ if (ensureExists(basedir, ilDir) != PR_SUCCESS) {
+ PR_fprintf(errorFD,
+ "ERROR: Unable to create directory %s.\n", ilDir);
+ errorCount++;
+ return -1;
+ }
+
+ filename = PR_smprintf("%s/%s/%s", basedir, ilDir, id);
+
+ /* If the file already exists, give a warning, then blow it away */
+ if (PR_Access(filename, PR_ACCESS_EXISTS) == PR_SUCCESS) {
+ PR_fprintf(errorFD,
+ "warning: file \"%s\" already exists--will overwrite.\n",
+ filename);
+ warningCount++;
+ if (rm_dash_r(filename)) {
+ PR_fprintf(errorFD, "ERROR: Unable to delete %s.\n", filename);
+ errorCount++;
+ goto finish;
+ }
+ }
+
+ /* Write text into file with name id */
+ fd = PR_Open(filename, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0777);
+ if (!fd) {
+ PR_fprintf(errorFD, "ERROR: Unable to create file \"%s\".\n",
+ filename);
+ errorCount++;
+ goto finish;
+ }
+ writeLen = strlen(text);
+ if (PR_Write(fd, text, writeLen) != writeLen) {
+ PR_fprintf(errorFD, "ERROR: Unable to write to file \"%s\".\n",
+ filename);
+ errorCount++;
+ goto finish;
+ }
+
+ retval = 0;
+finish:
+ if (filename) {
+ PR_smprintf_free(filename);
+ }
+ if (ilDir) {
+ PR_smprintf_free(ilDir);
+ }
+ if (fd) {
+ PR_Close(fd);
+ }
+ return retval;
+}
+
+/************************************************************************
+ *
+ * S a v e U n n a m a b l e S c r i p t
+ *
+ */
+static int
+SaveUnnamableScript(char *text, char *basedir, char *archiveDir,
+ char *HTMLfilename)
+{
+ char *id = NULL;
+ char *ext = NULL;
+ char *start = NULL;
+ int retval = -1;
+
+ if (!text || !archiveDir || !HTMLfilename) {
+ return -1;
+ }
+
+ if (dumpParse) {
+ PR_fprintf(outputFD, "SaveUnnamableScript: text=%s, basedir=%s,\n"
+ "archiveDir=%s, filename=%s\n",
+ text, basedir, archiveDir,
+ HTMLfilename);
+ }
+
+ /* Construct the filename */
+ ext = PL_strrchr(HTMLfilename, '.');
+ if (ext) {
+ *ext = '\0';
+ }
+ for (start = HTMLfilename; strpbrk(start, "/\\");
+ start = strpbrk(start, "/\\") + 1)
+ /* do nothing */;
+ if (*start == '\0')
+ start = HTMLfilename;
+ id = PR_smprintf("_%s%d", start, idOrdinal++);
+ if (ext) {
+ *ext = '.';
+ }
+
+ /* Now call SaveInlineScript to do the work */
+ retval = SaveInlineScript(text, id, basedir, archiveDir);
+
+ PR_Free(id);
+
+ return retval;
+}
+
+/************************************************************************
+ *
+ * S a v e S o u r c e
+ *
+ */
+static int
+SaveSource(char *src, char *codebase, char *basedir, char *archiveDir)
+{
+ char *from = NULL, *to = NULL;
+ int retval = -1;
+ char *arcDir = NULL;
+
+ if (!src || !archiveDir) {
+ return -1;
+ }
+
+ if (dumpParse) {
+ PR_fprintf(outputFD, "SaveSource: src=%s, codebase=%s, basedir=%s,\n"
+ "archiveDir=%s\n",
+ src, codebase, basedir, archiveDir);
+ }
+
+ if (codebase) {
+ arcDir = PR_smprintf("%s/%s/%s/", basedir, codebase, archiveDir);
+ } else {
+ arcDir = PR_smprintf("%s/%s/", basedir, archiveDir);
+ }
+
+ if (codebase) {
+ from = PR_smprintf("%s/%s/%s", basedir, codebase, src);
+ to = PR_smprintf("%s%s", arcDir, src);
+ } else {
+ from = PR_smprintf("%s/%s", basedir, src);
+ to = PR_smprintf("%s%s", arcDir, src);
+ }
+
+ if (make_dirs(to, 0777)) {
+ PR_fprintf(errorFD,
+ "ERROR: Unable to create archive directory %s.\n", archiveDir);
+ errorCount++;
+ goto finish;
+ }
+
+ retval = copyinto(from, to);
+finish:
+ if (from)
+ PR_Free(from);
+ if (to)
+ PR_Free(to);
+ if (arcDir)
+ PR_Free(arcDir);
+ return retval;
+}
+
+/************************************************************************
+ *
+ * T a g T y p e T o S t r i n g
+ *
+ */
+char *
+TagTypeToString(TAG_TYPE type)
+{
+ switch (type) {
+ case APPLET_TAG:
+ return "APPLET";
+ case SCRIPT_TAG:
+ return "SCRIPT";
+ case LINK_TAG:
+ return "LINK";
+ case STYLE_TAG:
+ return "STYLE";
+ default:
+ break;
+ }
+ return "unknown";
+}
+
+/************************************************************************
+ *
+ * e x t r a c t _ j s
+ *
+ */
+static int
+extract_js(char *filename)
+{
+ PRFileDesc *fd = NULL;
+ FileBuffer *fb = NULL;
+ HTMLItem *head = NULL;
+ HTMLItem *tail = NULL;
+ HTMLItem *curitem = NULL;
+ HTMLItem *styleList = NULL;
+ HTMLItem *styleListTail = NULL;
+ HTMLItem *entityList = NULL;
+ HTMLItem *entityListTail = NULL;
+ TagItem *tagp = NULL;
+ char *text = NULL;
+ char *tagerr = NULL;
+ char *archiveDir = NULL;
+ char *firstArchiveDir = NULL;
+ char *basedir = NULL;
+ PRInt32 textStart;
+ PRInt32 curOffset;
+ HTML_STATE state;
+ int curchar;
+ int retval = -1;
+ unsigned int linenum, startLine;
+
+ /* Initialize the implicit ID counter for each file */
+ idOrdinal = 0;
+
+ /*
+ * First, parse the HTML into a stream of tags and text.
+ */
+
+ fd = PR_Open(filename, PR_RDONLY, 0);
+ if (!fd) {
+ PR_fprintf(errorFD, "Unable to open %s for reading.\n", filename);
+ errorCount++;
+ return -1;
+ }
+
+ /* Construct base directory of filename. */
+ {
+ char *cp;
+
+ basedir = PL_strdup(filename);
+
+ /* Remove trailing slashes */
+ while ((cp = PL_strprbrk(basedir, "/\\")) ==
+ (basedir + strlen(basedir) - 1)) {
+ *cp = '\0';
+ }
+
+ /* Now remove everything from the last slash (which will be followed
+ * by a filename) to the end */
+ cp = PL_strprbrk(basedir, "/\\");
+ if (cp) {
+ *cp = '\0';
+ }
+ }
+
+ state = TEXT_HTML_STATE;
+
+ fb = FB_Create(fd);
+
+ textStart = 0;
+ startLine = 0;
+ while (linenum = FB_GetLineNum(fb), (curchar = FB_GetChar(fb)) !=
+ EOF) {
+ switch (state) {
+ case TEXT_HTML_STATE:
+ if (curchar == '<') {
+ /*
+ * Found a tag
+ */
+ /* Save the text so far to a new text item */
+ curOffset = FB_GetPointer(fb) - 2;
+ if (curOffset >= textStart) {
+ if (FB_GetRange(fb, textStart, curOffset,
+ &text) !=
+ curOffset - textStart + 1) {
+ PR_fprintf(errorFD,
+ "Unable to read from %s.\n",
+ filename);
+ errorCount++;
+ goto loser;
+ }
+ /* little fudge here. If the first character on a line
+ * is '<', meaning a new tag, the preceding text item
+ * actually ends on the previous line. In this case
+ * we will be saying that the text segment ends on the
+ * next line. I don't think this matters for text items. */
+ curitem = CreateTextItem(text, startLine,
+ linenum);
+ text = NULL;
+ if (tail == NULL) {
+ head = tail = curitem;
+ } else {
+ tail->next = curitem;
+ tail = curitem;
+ }
+ }
+
+ /* Process the tag */
+ tagp = ProcessTag(fb, &tagerr);
+ if (!tagp) {
+ if (tagerr) {
+ PR_fprintf(errorFD, "Error in file %s: %s\n",
+ filename, tagerr);
+ errorCount++;
+ } else {
+ PR_fprintf(errorFD,
+ "Error in file %s, in tag starting at line %d\n",
+ filename, linenum);
+ errorCount++;
+ }
+ goto loser;
+ }
+ /* Add the tag to the list */
+ curitem = CreateTagItem(tagp, linenum, FB_GetLineNum(fb));
+ if (tail == NULL) {
+ head = tail = curitem;
+ } else {
+ tail->next = curitem;
+ tail = curitem;
+ }
+
+ /* What's the next state */
+ if (tagp->type == SCRIPT_TAG) {
+ state = SCRIPT_HTML_STATE;
+ }
+
+ /* Start recording text from the new offset */
+ textStart = FB_GetPointer(fb);
+ startLine = FB_GetLineNum(fb);
+ } else {
+ /* regular character. Next! */
+ }
+ break;
+ case SCRIPT_HTML_STATE:
+ if (curchar == '<') {
+ char *cp;
+ /*
+ * If this is a </script> tag, then we're at the end of the
+ * script. Otherwise, ignore
+ */
+ curOffset = FB_GetPointer(fb) - 1;
+ cp = NULL;
+ if (FB_GetRange(fb, curOffset, curOffset + 8, &cp) != 9) {
+ if (cp) {
+ PR_Free(cp);
+ cp = NULL;
+ }
+ } else {
+ /* compare the strings */
+ if (!PORT_Strncasecmp(cp, "</script>", 9)) {
+ /* This is the end of the script. Record the text. */
+ curOffset--;
+ if (curOffset >= textStart) {
+ if (FB_GetRange(fb, textStart, curOffset, &text) !=
+ curOffset - textStart + 1) {
+ PR_fprintf(errorFD, "Unable to read from %s.\n",
+ filename);
+ errorCount++;
+ goto loser;
+ }
+ curitem = CreateTextItem(text, startLine, linenum);
+ text = NULL;
+ if (tail == NULL) {
+ head = tail = curitem;
+ } else {
+ tail->next = curitem;
+ tail = curitem;
+ }
+ }
+
+ /* Now parse the /script tag and put it on the list */
+ tagp = ProcessTag(fb, &tagerr);
+ if (!tagp) {
+ if (tagerr) {
+ PR_fprintf(errorFD, "Error in file %s: %s\n",
+ filename, tagerr);
+ } else {
+ PR_fprintf(errorFD,
+ "Error in file %s, in tag starting at"
+ " line %d\n",
+ filename, linenum);
+ }
+ errorCount++;
+ goto loser;
+ }
+ curitem = CreateTagItem(tagp, linenum,
+ FB_GetLineNum(fb));
+ if (tail == NULL) {
+ head = tail = curitem;
+ } else {
+ tail->next = curitem;
+ tail = curitem;
+ }
+
+ /* go back to text state */
+ state = TEXT_HTML_STATE;
+
+ textStart = FB_GetPointer(fb);
+ startLine = FB_GetLineNum(fb);
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ /* End of the file. Wrap up any remaining text */
+ if (state == SCRIPT_HTML_STATE) {
+ if (tail && tail->type == TAG_ITEM) {
+ PR_fprintf(errorFD, "ERROR: <SCRIPT> tag at %s:%d is not followed "
+ "by a </SCRIPT> tag.\n",
+ filename, tail->startLine);
+ } else {
+ PR_fprintf(errorFD, "ERROR: <SCRIPT> tag in file %s is not followed"
+ " by a </SCRIPT tag.\n",
+ filename);
+ }
+ errorCount++;
+ goto loser;
+ }
+ curOffset = FB_GetPointer(fb) - 1;
+ if (curOffset >= textStart) {
+ text = NULL;
+ if (FB_GetRange(fb, textStart, curOffset, &text) !=
+ curOffset - textStart + 1) {
+ PR_fprintf(errorFD, "Unable to read from %s.\n", filename);
+ errorCount++;
+ goto loser;
+ }
+ curitem = CreateTextItem(text, startLine, linenum);
+ text = NULL;
+ if (tail == NULL) {
+ head = tail = curitem;
+ } else {
+ tail->next = curitem;
+ tail = curitem;
+ }
+ }
+
+ if (dumpParse) {
+ PrintHTMLStream(outputFD, head);
+ }
+
+ /*
+ * Now we have a stream of tags and text. Go through and deal with each.
+ */
+ for (curitem = head; curitem; curitem = curitem->next) {
+ TagItem *tagp = NULL;
+ AVPair *pairp = NULL;
+ char *src = NULL, *id = NULL, *codebase = NULL;
+ PRBool hasEventHandler = PR_FALSE;
+ int i;
+
+ /* Reset archive directory for each tag */
+ if (archiveDir) {
+ PR_Free(archiveDir);
+ archiveDir = NULL;
+ }
+
+ /* We only analyze tags */
+ if (curitem->type != TAG_ITEM) {
+ continue;
+ }
+
+ tagp = curitem->item.tag;
+
+ /* go through the attributes to get information */
+ for (pairp = tagp->attList; pairp; pairp = pairp->next) {
+
+ /* ARCHIVE= */
+ if (!PL_strcasecmp(pairp->attribute, "archive")) {
+ if (archiveDir) {
+ /* Duplicate attribute. Print warning */
+ PR_fprintf(errorFD,
+ "warning: \"%s\" attribute overwrites previous attribute"
+ " in tag starting at %s:%d.\n",
+ pairp->attribute, filename, curitem->startLine);
+ warningCount++;
+ PR_Free(archiveDir);
+ }
+ archiveDir = PL_strdup(pairp->value);
+
+ /* Substiture ".arc" for ".jar" */
+ if ((PL_strlen(archiveDir) < 4) ||
+ PL_strcasecmp((archiveDir + strlen(archiveDir) - 4),
+ ".jar")) {
+ PR_fprintf(errorFD,
+ "warning: ARCHIVE attribute should end in \".jar\" in tag"
+ " starting on %s:%d.\n",
+ filename, curitem->startLine);
+ warningCount++;
+ PR_Free(archiveDir);
+ archiveDir = PR_smprintf("%s.arc", archiveDir);
+ } else {
+ PL_strcpy(archiveDir + strlen(archiveDir) - 4, ".arc");
+ }
+
+ /* Record the first archive. This will be used later if
+ * the archive is not specified */
+ if (firstArchiveDir == NULL) {
+ firstArchiveDir = PL_strdup(archiveDir);
+ }
+ }
+ /* CODEBASE= */
+ else if (!PL_strcasecmp(pairp->attribute, "codebase")) {
+ if (codebase) {
+ /* Duplicate attribute. Print warning */
+ PR_fprintf(errorFD,
+ "warning: \"%s\" attribute overwrites previous attribute"
+ " in tag staring at %s:%d.\n",
+ pairp->attribute, filename, curitem->startLine);
+ warningCount++;
+ }
+ codebase = pairp->value;
+ }
+ /* SRC= and HREF= */
+ else if (!PORT_Strcasecmp(pairp->attribute, "src") ||
+ !PORT_Strcasecmp(pairp->attribute, "href")) {
+ if (src) {
+ /* Duplicate attribute. Print warning */
+ PR_fprintf(errorFD,
+ "warning: \"%s\" attribute overwrites previous attribute"
+ " in tag staring at %s:%d.\n",
+ pairp->attribute, filename, curitem->startLine);
+ warningCount++;
+ }
+ src = pairp->value;
+ }
+ /* CODE= */
+ else if (!PORT_Strcasecmp(pairp->attribute, "code")) {
+ /*!!!XXX Change PORT to PL all over this code !!! */
+ if (src) {
+ /* Duplicate attribute. Print warning */
+ PR_fprintf(errorFD,
+ "warning: \"%s\" attribute overwrites previous attribute"
+ " ,in tag staring at %s:%d.\n",
+ pairp->attribute, filename, curitem->startLine);
+ warningCount++;
+ }
+ src = pairp->value;
+
+ /* Append a .class if one is not already present */
+ if ((PL_strlen(src) < 6) ||
+ PL_strcasecmp((src + PL_strlen(src) - 6), ".class")) {
+ src = PR_smprintf("%s.class", src);
+ /* Put this string back into the data structure so it
+ * will be deallocated properly */
+ PR_Free(pairp->value);
+ pairp->value = src;
+ }
+ }
+ /* ID= */
+ else if (!PL_strcasecmp(pairp->attribute, "id")) {
+ if (id) {
+ /* Duplicate attribute. Print warning */
+ PR_fprintf(errorFD,
+ "warning: \"%s\" attribute overwrites previous attribute"
+ " in tag staring at %s:%d.\n",
+ pairp->attribute, filename, curitem->startLine);
+ warningCount++;
+ }
+ id = pairp->value;
+ }
+
+ /* STYLE= */
+ /* style= attributes, along with JS entities, are stored into
+ * files with dynamically generated names. The filenames are
+ * based on the order in which the text is found in the file.
+ * All JS entities on all lines up to and including the line
+ * containing the end of the tag that has this style= attribute
+ * will be processed before this style=attribute. So we need
+ * to record the line that this _tag_ (not the attribute) ends on.
+ */
+ else if (!PL_strcasecmp(pairp->attribute, "style") && pairp->value) {
+ HTMLItem *styleItem;
+ /* Put this item on the style list */
+ styleItem = CreateTextItem(PL_strdup(pairp->value),
+ curitem->startLine, curitem->endLine);
+ if (styleListTail == NULL) {
+ styleList = styleListTail = styleItem;
+ } else {
+ styleListTail->next = styleItem;
+ styleListTail = styleItem;
+ }
+ }
+ /* Event handlers */
+ else {
+ for (i = 0; i < num_handlers; i++) {
+ if (!PL_strcasecmp(event_handlers[i], pairp->attribute)) {
+ hasEventHandler = PR_TRUE;
+ break;
+ }
+ }
+ }
+
+ /* JS Entity */
+ {
+ char *entityStart, *entityEnd;
+ HTMLItem *entityItem;
+
+ /* go through each JavaScript entity ( &{...}; ) and store it
+ * in the entityList. The important thing is to record what
+ * line number it's on, so we can get it in the right order
+ * in relation to style= attributes.
+ * Apparently, these can't flow across lines, so the start and
+ * end line will be the same. That helps matters.
+ */
+ entityEnd = pairp->value;
+ while (entityEnd &&
+ (entityStart = PL_strstr(entityEnd, "&{")) /*}*/ != NULL) {
+ entityStart += 2; /* point at beginning of actual entity */
+ entityEnd = PL_strchr(entityStart, '}');
+ if (entityEnd) {
+ /* Put this item on the entity list */
+ *entityEnd = '\0';
+ entityItem = CreateTextItem(PL_strdup(entityStart),
+ pairp->valueLine, pairp->valueLine);
+ *entityEnd = /* { */ '}';
+ if (entityListTail) {
+ entityListTail->next = entityItem;
+ entityListTail = entityItem;
+ } else {
+ entityList = entityListTail = entityItem;
+ }
+ }
+ }
+ }
+ }
+
+ /* If no archive was supplied, we use the first one of the file */
+ if (!archiveDir && firstArchiveDir) {
+ archiveDir = PL_strdup(firstArchiveDir);
+ }
+
+ /* If we have an event handler, we need to archive this tag */
+ if (hasEventHandler) {
+ if (!id) {
+ PR_fprintf(errorFD,
+ "warning: tag starting at %s:%d has event handler but"
+ " no ID attribute. The tag will not be signed.\n",
+ filename, curitem->startLine);
+ warningCount++;
+ } else if (!archiveDir) {
+ PR_fprintf(errorFD,
+ "warning: tag starting at %s:%d has event handler but"
+ " no ARCHIVE attribute. The tag will not be signed.\n",
+ filename, curitem->startLine);
+ warningCount++;
+ } else {
+ if (SaveInlineScript(tagp->text, id, basedir, archiveDir)) {
+ goto loser;
+ }
+ }
+ }
+
+ switch (tagp->type) {
+ case APPLET_TAG:
+ if (!src) {
+ PR_fprintf(errorFD,
+ "error: APPLET tag starting on %s:%d has no CODE "
+ "attribute.\n",
+ filename, curitem->startLine);
+ errorCount++;
+ goto loser;
+ } else if (!archiveDir) {
+ PR_fprintf(errorFD,
+ "error: APPLET tag starting on %s:%d has no ARCHIVE "
+ "attribute.\n",
+ filename, curitem->startLine);
+ errorCount++;
+ goto loser;
+ } else {
+ if (SaveSource(src, codebase, basedir, archiveDir)) {
+ goto loser;
+ }
+ }
+ break;
+ case SCRIPT_TAG:
+ case LINK_TAG:
+ case STYLE_TAG:
+ if (!archiveDir) {
+ PR_fprintf(errorFD,
+ "error: %s tag starting on %s:%d has no ARCHIVE "
+ "attribute.\n",
+ TagTypeToString(tagp->type),
+ filename, curitem->startLine);
+ errorCount++;
+ goto loser;
+ } else if (src) {
+ if (SaveSource(src, codebase, basedir, archiveDir)) {
+ goto loser;
+ }
+ } else if (id) {
+ /* Save the next text item */
+ if (!curitem->next || (curitem->next->type !=
+ TEXT_ITEM)) {
+ PR_fprintf(errorFD,
+ "warning: %s tag starting on %s:%d is not followed"
+ " by script text.\n",
+ TagTypeToString(tagp->type),
+ filename, curitem->startLine);
+ warningCount++;
+ /* just create empty file */
+ if (SaveInlineScript("", id, basedir, archiveDir)) {
+ goto loser;
+ }
+ } else {
+ curitem = curitem->next;
+ if (SaveInlineScript(curitem->item.text,
+ id, basedir,
+ archiveDir)) {
+ goto loser;
+ }
+ }
+ } else {
+ /* No src or id tag--warning */
+ PR_fprintf(errorFD,
+ "warning: %s tag starting on %s:%d has no SRC or"
+ " ID attributes. Will not sign.\n",
+ TagTypeToString(tagp->type), filename, curitem->startLine);
+ warningCount++;
+ }
+ break;
+ default:
+ /* do nothing for other tags */
+ break;
+ }
+ }
+
+ /* Now deal with all the unnamable scripts */
+ if (firstArchiveDir) {
+ HTMLItem *style, *entity;
+
+ /* Go through the lists of JS entities and style attributes. Do them
+ * in chronological order within a list. Pick the list with the lower
+ * endLine. In case of a tie, entities come first.
+ */
+ style = styleList;
+ entity = entityList;
+ while (style || entity) {
+ if (!entity || (style && (style->endLine < entity->endLine))) {
+ /* Process style */
+ SaveUnnamableScript(style->item.text, basedir, firstArchiveDir,
+ filename);
+ style = style->next;
+ } else {
+ /* Process entity */
+ SaveUnnamableScript(entity->item.text, basedir, firstArchiveDir,
+ filename);
+ entity = entity->next;
+ }
+ }
+ }
+
+ retval = 0;
+loser:
+ /* Blow away the stream */
+ while (head) {
+ curitem = head;
+ head = head->next;
+ DestroyHTMLItem(curitem);
+ }
+ while (styleList) {
+ curitem = styleList;
+ styleList = styleList->next;
+ DestroyHTMLItem(curitem);
+ }
+ while (entityList) {
+ curitem = entityList;
+ entityList = entityList->next;
+ DestroyHTMLItem(curitem);
+ }
+ if (text) {
+ PR_Free(text);
+ text = NULL;
+ }
+ if (fb) {
+ FB_Destroy(fb);
+ fb = NULL;
+ }
+ if (fd) {
+ PR_Close(fd);
+ }
+ if (tagerr) {
+ PR_smprintf_free(tagerr);
+ tagerr = NULL;
+ }
+ if (archiveDir) {
+ PR_Free(archiveDir);
+ archiveDir = NULL;
+ }
+ if (firstArchiveDir) {
+ PR_Free(firstArchiveDir);
+ firstArchiveDir = NULL;
+ }
+ if (entityListTail) {
+ PR_Free(entityListTail);
+ }
+ if (curitem) {
+ PR_Free(curitem);
+ }
+ if (basedir) {
+ PR_Free(basedir);
+ }
+ return retval;
+}
+
+/**********************************************************************
+ *
+ * e n s u r e E x i s t s
+ *
+ * Check for existence of indicated directory. If it doesn't exist,
+ * it will be created.
+ * Returns PR_SUCCESS if the directory is present, PR_FAILURE otherwise.
+ */
+static PRStatus
+ensureExists(char *base, char *path)
+{
+ char fn[FNSIZE];
+ PRDir *dir;
+ sprintf(fn, "%s/%s", base, path);
+
+ /*PR_fprintf(outputFD, "Trying to open directory %s.\n", fn);*/
+
+ if ((dir = PR_OpenDir(fn))) {
+ PR_CloseDir(dir);
+ return PR_SUCCESS;
+ }
+ return PR_MkDir(fn, 0777);
+}
+
+/***************************************************************************
+ *
+ * m a k e _ d i r s
+ *
+ * Ensure that the directory portion of the path exists. This may require
+ * making the directory, and its parent, and its parent's parent, etc.
+ */
+static int
+make_dirs(char *path, int file_perms)
+{
+ char *Path;
+ char *start;
+ char *sep;
+ int ret = 0;
+ PRFileInfo info;
+
+ if (!path) {
+ return 0;
+ }
+
+ Path = PL_strdup(path);
+ if (!Path) {
+ return 0;
+ }
+
+ start = strpbrk(Path, "/\\");
+ if (!start) {
+ goto loser;
+ }
+ start++; /* start right after first slash */
+
+ /* Each time through the loop add one more directory. */
+ while ((sep = strpbrk(start, "/\\"))) {
+ *sep = '\0';
+
+ if (PR_GetFileInfo(Path, &info) != PR_SUCCESS) {
+ /* No such dir, we have to create it */
+ if (PR_MkDir(Path, file_perms) != PR_SUCCESS) {
+ PR_fprintf(errorFD, "ERROR: Unable to create directory %s.\n",
+ Path);
+ errorCount++;
+ ret = -1;
+ goto loser;
+ }
+ } else {
+ /* something exists by this name, make sure it's a directory */
+ if (info.type != PR_FILE_DIRECTORY) {
+ PR_fprintf(errorFD, "ERROR: Unable to create directory %s.\n",
+ Path);
+ errorCount++;
+ ret = -1;
+ goto loser;
+ }
+ }
+
+ start = sep + 1; /* start after the next slash */
+ *sep = '/';
+ }
+
+loser:
+ PR_Free(Path);
+ return ret;
+}
+
+/*
+ * c o p y i n t o
+ *
+ * Function to copy file "from" to path "to".
+ *
+ */
+static int
+copyinto(char *from, char *to)
+{
+ PRInt32 num;
+ char buf[BUFSIZ];
+ PRFileDesc *infp = NULL, *outfp = NULL;
+ int retval = -1;
+
+ if ((infp = PR_Open(from, PR_RDONLY, 0777)) == NULL) {
+ PR_fprintf(errorFD, "ERROR: Unable to open \"%s\" for reading.\n",
+ from);
+ errorCount++;
+ goto finish;
+ }
+
+ /* If to already exists, print a warning before deleting it */
+ if (PR_Access(to, PR_ACCESS_EXISTS) == PR_SUCCESS) {
+ PR_fprintf(errorFD, "warning: %s already exists--will overwrite\n", to);
+ warningCount++;
+ if (rm_dash_r(to)) {
+ PR_fprintf(errorFD,
+ "ERROR: Unable to remove %s.\n", to);
+ errorCount++;
+ goto finish;
+ }
+ }
+
+ if ((outfp = PR_Open(to, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0777)) ==
+ NULL) {
+ char *errBuf = NULL;
+
+ errBuf = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_fprintf(errorFD, "ERROR: Unable to open \"%s\" for writing.\n", to);
+ if (PR_GetErrorText(errBuf)) {
+ PR_fprintf(errorFD, "Cause: %s\n", errBuf);
+ }
+ if (errBuf) {
+ PR_Free(errBuf);
+ }
+ errorCount++;
+ goto finish;
+ }
+
+ while ((num = PR_Read(infp, buf, BUFSIZ)) > 0) {
+ if (PR_Write(outfp, buf, num) != num) {
+ PR_fprintf(errorFD, "ERROR: Error writing to %s.\n", to);
+ errorCount++;
+ goto finish;
+ }
+ }
+
+ retval = 0;
+finish:
+ if (infp)
+ PR_Close(infp);
+ if (outfp)
+ PR_Close(outfp);
+
+ return retval;
+}
diff --git a/security/nss/cmd/signtool/list.c b/security/nss/cmd/signtool/list.c
new file mode 100644
index 000000000..70f62d2b1
--- /dev/null
+++ b/security/nss/cmd/signtool/list.c
@@ -0,0 +1,215 @@
+/* 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/. */
+
+#include "signtool.h"
+#include "pk11func.h"
+#include "certdb.h"
+
+static int num_trav_certs = 0;
+static SECStatus cert_trav_callback(CERTCertificate *cert, SECItem *k,
+ void *data);
+
+/*********************************************************************
+ *
+ * L i s t C e r t s
+ */
+int
+ListCerts(char *key, int list_certs)
+{
+ int failed = 0;
+ SECStatus rv;
+ char *ugly_list;
+ CERTCertDBHandle *db;
+
+ CERTCertificate *cert;
+ CERTVerifyLog errlog;
+
+ errlog.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (errlog.arena == NULL) {
+ out_of_memory();
+ }
+ errlog.head = NULL;
+ errlog.tail = NULL;
+ errlog.count = 0;
+
+ ugly_list = PORT_ZAlloc(16);
+
+ if (ugly_list == NULL) {
+ out_of_memory();
+ }
+
+ *ugly_list = 0;
+
+ db = CERT_GetDefaultCertDB();
+
+ if (list_certs == 2) {
+ PR_fprintf(outputFD, "\nS Certificates\n");
+ PR_fprintf(outputFD, "- ------------\n");
+ } else {
+ PR_fprintf(outputFD, "\nObject signing certificates\n");
+ PR_fprintf(outputFD, "---------------------------------------\n");
+ }
+
+ num_trav_certs = 0;
+
+ /* Traverse ALL tokens in all slots, authenticating to them all */
+ rv = PK11_TraverseSlotCerts(cert_trav_callback, (void *)&list_certs,
+ &pwdata);
+
+ if (rv) {
+ PR_fprintf(outputFD, "**Traverse of ALL slots & tokens failed**\n");
+ return -1;
+ }
+
+ if (num_trav_certs == 0) {
+ PR_fprintf(outputFD,
+ "You don't appear to have any object signing certificates.\n");
+ }
+
+ if (list_certs == 2) {
+ PR_fprintf(outputFD, "- ------------\n");
+ } else {
+ PR_fprintf(outputFD, "---------------------------------------\n");
+ }
+
+ if (list_certs == 1) {
+ PR_fprintf(outputFD,
+ "For a list including CA's, use \"%s -L\"\n", PROGRAM_NAME);
+ }
+
+ if (list_certs == 2) {
+ PR_fprintf(outputFD,
+ "Certificates that can be used to sign objects have *'s to "
+ "their left.\n");
+ }
+
+ if (key) {
+ /* Do an analysis of the given cert */
+
+ cert = PK11_FindCertFromNickname(key, &pwdata);
+
+ if (cert) {
+ PR_fprintf(outputFD,
+ "\nThe certificate with nickname \"%s\" was found:\n",
+ cert->nickname);
+ PR_fprintf(outputFD, "\tsubject name: %s\n", cert->subjectName);
+ PR_fprintf(outputFD, "\tissuer name: %s\n", cert->issuerName);
+
+ PR_fprintf(outputFD, "\n");
+
+ rv = CERT_CertTimesValid(cert);
+ if (rv != SECSuccess) {
+ PR_fprintf(outputFD, "**This certificate is expired**\n");
+ } else {
+ PR_fprintf(outputFD, "This certificate is not expired.\n");
+ }
+
+ rv = CERT_VerifyCert(db, cert, PR_TRUE,
+ certUsageObjectSigner, PR_Now(), &pwdata, &errlog);
+
+ if (rv != SECSuccess) {
+ failed = 1;
+ if (errlog.count > 0) {
+ PR_fprintf(outputFD,
+ "**Certificate validation failed for the "
+ "following reason(s):**\n");
+ } else {
+ PR_fprintf(outputFD, "**Certificate validation failed**");
+ }
+ } else {
+ PR_fprintf(outputFD, "This certificate is valid.\n");
+ }
+ displayVerifyLog(&errlog);
+
+ } else {
+ failed = 1;
+ PR_fprintf(outputFD,
+ "The certificate with nickname \"%s\" was NOT FOUND\n", key);
+ }
+ }
+
+ if (errlog.arena != NULL) {
+ PORT_FreeArena(errlog.arena, PR_FALSE);
+ }
+
+ if (failed) {
+ return -1;
+ }
+ return 0;
+}
+
+/********************************************************************
+ *
+ * c e r t _ t r a v _ c a l l b a c k
+ */
+static SECStatus
+cert_trav_callback(CERTCertificate *cert, SECItem *k, void *data)
+{
+ int list_certs = 1;
+ char *name;
+
+ if (data) {
+ list_certs = *((int *)data);
+ }
+
+#define LISTING_USER_SIGNING_CERTS (list_certs == 1)
+#define LISTING_ALL_CERTS (list_certs == 2)
+
+ name = cert->nickname;
+ if (name) {
+ int isSigningCert;
+
+ isSigningCert = cert->nsCertType & NS_CERT_TYPE_OBJECT_SIGNING;
+ if (!isSigningCert && LISTING_USER_SIGNING_CERTS)
+ return (SECSuccess);
+
+ /* Display this name or email address */
+ num_trav_certs++;
+
+ if (LISTING_ALL_CERTS) {
+ PR_fprintf(outputFD, "%s ", isSigningCert ? "*" : " ");
+ }
+ PR_fprintf(outputFD, "%s\n", name);
+
+ if (LISTING_USER_SIGNING_CERTS) {
+ int rv = SECFailure;
+ if (rv) {
+ CERTCertificate *issuerCert;
+ issuerCert = CERT_FindCertIssuer(cert, PR_Now(),
+ certUsageObjectSigner);
+ if (issuerCert) {
+ if (issuerCert->nickname && issuerCert->nickname[0]) {
+ PR_fprintf(outputFD, " Issued by: %s\n",
+ issuerCert->nickname);
+ rv = SECSuccess;
+ }
+ CERT_DestroyCertificate(issuerCert);
+ }
+ }
+ if (rv && cert->issuerName && cert->issuerName[0]) {
+ PR_fprintf(outputFD, " Issued by: %s \n", cert->issuerName);
+ }
+ {
+ char *expires;
+ expires = DER_TimeChoiceDayToAscii(&cert->validity.notAfter);
+ if (expires) {
+ PR_fprintf(outputFD, " Expires: %s\n", expires);
+ PORT_Free(expires);
+ }
+ }
+
+ rv = CERT_VerifyCertNow(cert->dbhandle, cert,
+ PR_TRUE, certUsageObjectSigner, &pwdata);
+
+ if (rv != SECSuccess) {
+ rv = PORT_GetError();
+ PR_fprintf(outputFD,
+ " ++ Error ++ THIS CERTIFICATE IS NOT VALID (%s)\n",
+ secErrorString(rv));
+ }
+ }
+ }
+
+ return (SECSuccess);
+}
diff --git a/security/nss/cmd/signtool/manifest.mn b/security/nss/cmd/signtool/manifest.mn
new file mode 100644
index 000000000..40be262db
--- /dev/null
+++ b/security/nss/cmd/signtool/manifest.mn
@@ -0,0 +1,25 @@
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+EXPORTS =
+
+CSRCS = signtool.c \
+ certgen.c \
+ javascript.c \
+ list.c \
+ sign.c \
+ util.c \
+ verify.c \
+ zip.c \
+ $(NULL)
+
+PROGRAM = signtool
+
+REQUIRES = seccmd
+
+EXTRA_LIBS = $(JAR_LIBS)
diff --git a/security/nss/cmd/signtool/sign.c b/security/nss/cmd/signtool/sign.c
new file mode 100644
index 000000000..6e776069a
--- /dev/null
+++ b/security/nss/cmd/signtool/sign.c
@@ -0,0 +1,834 @@
+/* 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/. */
+
+#include "signtool.h"
+#include "zip.h"
+#include "prmem.h"
+#include "blapi.h"
+#include "sechash.h" /* for HASH_GetHashObject() */
+
+static int create_pk7(char *dir, char *keyName, int *keyType);
+static int jar_find_key_type(CERTCertificate *cert);
+static int manifesto(char *dirname, char *install_script, PRBool recurse);
+static int manifesto_fn(char *relpath, char *basedir, char *reldir,
+ char *filename, void *arg);
+static int manifesto_xpi_fn(char *relpath, char *basedir, char *reldir,
+ char *filename, void *arg);
+static int sign_all_arc_fn(char *relpath, char *basedir, char *reldir,
+ char *filename, void *arg);
+static int add_meta(FILE *fp, char *name);
+static int SignFile(FILE *outFile, FILE *inFile, CERTCertificate *cert);
+static int generate_SF_file(char *manifile, char *who);
+static int calculate_MD5_range(FILE *fp, long r1, long r2,
+ JAR_Digest *dig);
+static void SignOut(void *arg, const char *buf, unsigned long len);
+
+static char *metafile = NULL;
+static int optimize = 0;
+static FILE *mf;
+static ZIPfile *zipfile = NULL;
+
+/*
+ * S i g n A r c h i v e
+ *
+ * Sign an individual archive tree. A directory
+ * called META-INF is created underneath this.
+ *
+ */
+int
+SignArchive(char *tree, char *keyName, char *zip_file, int javascript,
+ char *meta_file, char *install_script, int _optimize, PRBool recurse)
+{
+ int status;
+ char tempfn[FNSIZE], fullfn[FNSIZE];
+ int keyType = rsaKey;
+
+ metafile = meta_file;
+ optimize = _optimize;
+
+ /* To create XPI compatible Archive manifesto() must be run before
+ * the zipfile is opened. This is so the signed files are not added
+ * the archive before the crucial rsa/dsa file*/
+ if (xpi_arc) {
+ manifesto(tree, install_script, recurse);
+ }
+
+ if (zip_file) {
+ zipfile = JzipOpen(zip_file, NULL /*no comment*/);
+ }
+
+ /*Sign and add files to the archive normally with manifesto()*/
+ if (!xpi_arc) {
+ manifesto(tree, install_script, recurse);
+ }
+
+ if (keyName) {
+ status = create_pk7(tree, keyName, &keyType);
+ if (status < 0) {
+ PR_fprintf(errorFD, "the tree \"%s\" was NOT SUCCESSFULLY SIGNED\n",
+ tree);
+ errorCount++;
+ exit(ERRX);
+ }
+ }
+
+ /* Add the rsa/dsa file as the first file in the archive. This is crucial
+ * for a XPInstall compatible archive */
+ if (xpi_arc) {
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "%s \n", XPI_TEXT);
+ }
+
+ /* rsa/dsa to zip */
+ sprintf(tempfn, "META-INF/%s.%s", base, (keyType == dsaKey ? "dsa"
+ : "rsa"));
+ sprintf(fullfn, "%s/%s", tree, tempfn);
+ JzipAdd(fullfn, tempfn, zipfile, compression_level);
+
+ /* Loop through all files & subdirectories, add to archive */
+ foreach (tree, "", manifesto_xpi_fn, recurse, PR_FALSE /*include dirs */,
+ (void *)NULL)
+ ;
+ }
+ /* mf to zip */
+ strcpy(tempfn, "META-INF/manifest.mf");
+ sprintf(fullfn, "%s/%s", tree, tempfn);
+ JzipAdd(fullfn, tempfn, zipfile, compression_level);
+
+ /* sf to zip */
+ sprintf(tempfn, "META-INF/%s.sf", base);
+ sprintf(fullfn, "%s/%s", tree, tempfn);
+ JzipAdd(fullfn, tempfn, zipfile, compression_level);
+
+ /* Add the rsa/dsa file to the zip archive normally */
+ if (!xpi_arc) {
+ /* rsa/dsa to zip */
+ sprintf(tempfn, "META-INF/%s.%s", base, (keyType == dsaKey ? "dsa"
+ : "rsa"));
+ sprintf(fullfn, "%s/%s", tree, tempfn);
+ JzipAdd(fullfn, tempfn, zipfile, compression_level);
+ }
+
+ JzipClose(zipfile);
+
+ if (verbosity >= 0) {
+ if (javascript) {
+ PR_fprintf(outputFD, "jarfile \"%s\" signed successfully\n",
+ zip_file);
+ } else {
+ PR_fprintf(outputFD, "tree \"%s\" signed successfully\n",
+ tree);
+ }
+ }
+
+ return 0;
+}
+
+typedef struct {
+ char *keyName;
+ int javascript;
+ char *metafile;
+ char *install_script;
+ int optimize;
+} SignArcInfo;
+
+/*
+ * S i g n A l l A r c
+ *
+ * Javascript may generate multiple .arc directories, one
+ * for each jar archive needed. Sign them all.
+ *
+ */
+int
+SignAllArc(char *jartree, char *keyName, int javascript, char *metafile,
+ char *install_script, int optimize, PRBool recurse)
+{
+ SignArcInfo info;
+
+ info.keyName = keyName;
+ info.javascript = javascript;
+ info.metafile = metafile;
+ info.install_script = install_script;
+ info.optimize = optimize;
+
+ return foreach (jartree, "", sign_all_arc_fn, recurse,
+ PR_TRUE /*include dirs*/, (void *)&info);
+}
+
+static int
+sign_all_arc_fn(char *relpath, char *basedir, char *reldir, char *filename,
+ void *arg)
+{
+ char *zipfile = NULL;
+ char *arc = NULL, *archive = NULL;
+ int retval = 0;
+ SignArcInfo *infop = (SignArcInfo *)arg;
+
+ /* Make sure there is one and only one ".arc" in the relative path,
+ * and that it is at the end of the path (don't sign .arcs within .arcs) */
+ if ((PL_strcaserstr(relpath, ".arc") == relpath + strlen(relpath) - 4) &&
+ (PL_strcasestr(relpath, ".arc") == relpath + strlen(relpath) - 4)) {
+
+ if (!infop) {
+ PR_fprintf(errorFD, "%s: Internal failure\n", PROGRAM_NAME);
+ errorCount++;
+ retval = -1;
+ goto finish;
+ }
+ archive = PR_smprintf("%s/%s", basedir, relpath);
+
+ zipfile = PL_strdup(archive);
+ arc = PORT_Strrchr(zipfile, '.');
+
+ if (arc == NULL) {
+ PR_fprintf(errorFD, "%s: Internal failure\n", PROGRAM_NAME);
+ errorCount++;
+ retval = -1;
+ goto finish;
+ }
+
+ PL_strcpy(arc, ".jar");
+
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "\nsigning: %s\n", zipfile);
+ }
+ retval = SignArchive(archive, infop->keyName, zipfile,
+ infop->javascript, infop->metafile, infop->install_script,
+ infop->optimize, PR_TRUE /* recurse */);
+ }
+finish:
+ if (archive)
+ PR_Free(archive);
+ if (zipfile)
+ PR_Free(zipfile);
+
+ return retval;
+}
+
+/*********************************************************************
+ *
+ * c r e a t e _ p k 7
+ */
+static int
+create_pk7(char *dir, char *keyName, int *keyType)
+{
+ int status = 0;
+ char *file_ext;
+
+ CERTCertificate *cert;
+ CERTCertDBHandle *db;
+
+ FILE *in, *out;
+
+ char sf_file[FNSIZE];
+ char pk7_file[FNSIZE];
+
+ /* open cert database */
+ db = CERT_GetDefaultCertDB();
+
+ if (db == NULL)
+ return -1;
+
+ /* find cert */
+ /*cert = CERT_FindCertByNicknameOrEmailAddr(db, keyName);*/
+ cert = PK11_FindCertFromNickname(keyName, &pwdata);
+
+ if (cert == NULL) {
+ SECU_PrintError(PROGRAM_NAME,
+ "Cannot find the cert \"%s\"", keyName);
+ return -1;
+ }
+
+ /* determine the key type, which sets the extension for pkcs7 object */
+
+ *keyType = jar_find_key_type(cert);
+ file_ext = (*keyType == dsaKey) ? "dsa" : "rsa";
+
+ sprintf(sf_file, "%s/META-INF/%s.sf", dir, base);
+ sprintf(pk7_file, "%s/META-INF/%s.%s", dir, base, file_ext);
+
+ if ((in = fopen(sf_file, "rb")) == NULL) {
+ PR_fprintf(errorFD, "%s: Can't open %s for reading\n", PROGRAM_NAME,
+ sf_file);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ if ((out = fopen(pk7_file, "wb")) == NULL) {
+ PR_fprintf(errorFD, "%s: Can't open %s for writing\n", PROGRAM_NAME,
+ sf_file);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ status = SignFile(out, in, cert);
+
+ CERT_DestroyCertificate(cert);
+ fclose(in);
+ fclose(out);
+
+ if (status) {
+ PR_fprintf(errorFD, "%s: PROBLEM signing data (%s)\n",
+ PROGRAM_NAME, SECU_Strerror(PORT_GetError()));
+ errorCount++;
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * j a r _ f i n d _ k e y _ t y p e
+ *
+ * Determine the key type for a given cert, which
+ * should be rsaKey or dsaKey. Any error return 0.
+ *
+ */
+static int
+jar_find_key_type(CERTCertificate *cert)
+{
+ SECKEYPrivateKey *privk = NULL;
+ KeyType keyType;
+
+ /* determine its type */
+ privk = PK11_FindKeyByAnyCert(cert, &pwdata);
+ if (privk == NULL) {
+ PR_fprintf(errorFD, "warning - can't find private key for this cert\n");
+ warningCount++;
+ return 0;
+ }
+
+ keyType = privk->keyType;
+ SECKEY_DestroyPrivateKey(privk);
+ return keyType;
+}
+
+/*
+ * m a n i f e s t o
+ *
+ * Run once for every subdirectory in which a
+ * manifest is to be created -- usually exactly once.
+ *
+ */
+static int
+manifesto(char *dirname, char *install_script, PRBool recurse)
+{
+ char metadir[FNSIZE], sfname[FNSIZE];
+
+ /* Create the META-INF directory to hold signing info */
+
+ if (PR_Access(dirname, PR_ACCESS_READ_OK)) {
+ PR_fprintf(errorFD, "%s: unable to read your directory: %s\n",
+ PROGRAM_NAME, dirname);
+ errorCount++;
+ perror(dirname);
+ exit(ERRX);
+ }
+
+ if (PR_Access(dirname, PR_ACCESS_WRITE_OK)) {
+ PR_fprintf(errorFD, "%s: unable to write to your directory: %s\n",
+ PROGRAM_NAME, dirname);
+ errorCount++;
+ perror(dirname);
+ exit(ERRX);
+ }
+
+ sprintf(metadir, "%s/META-INF", dirname);
+
+ strcpy(sfname, metadir);
+
+ PR_MkDir(metadir, 0777);
+
+ strcat(metadir, "/");
+ strcat(metadir, MANIFEST);
+
+ if ((mf = fopen(metadir, "wb")) == NULL) {
+ perror(MANIFEST);
+ PR_fprintf(errorFD, "%s: Probably, the directory you are trying to"
+ " sign has\n",
+ PROGRAM_NAME);
+ PR_fprintf(errorFD, "%s: permissions problems or may not exist.\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "Generating %s file..\n", metadir);
+ }
+
+ fprintf(mf, "Manifest-Version: 1.0\n");
+ fprintf(mf, "Created-By: %s\n", CREATOR);
+ fprintf(mf, "Comments: %s\n", BREAKAGE);
+
+ if (scriptdir) {
+ fprintf(mf, "Comments: --\n");
+ fprintf(mf, "Comments: --\n");
+ fprintf(mf, "Comments: -- This archive signs Javascripts which may not necessarily\n");
+ fprintf(mf, "Comments: -- be included in the physical jar file.\n");
+ fprintf(mf, "Comments: --\n");
+ fprintf(mf, "Comments: --\n");
+ }
+
+ if (install_script)
+ fprintf(mf, "Install-Script: %s\n", install_script);
+
+ if (metafile)
+ add_meta(mf, "+");
+
+ /* Loop through all files & subdirectories */
+ foreach (dirname, "", manifesto_fn, recurse, PR_FALSE /*include dirs */,
+ (void *)NULL)
+ ;
+
+ fclose(mf);
+
+ strcat(sfname, "/");
+ strcat(sfname, base);
+ strcat(sfname, ".sf");
+
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "Generating %s.sf file..\n", base);
+ }
+ generate_SF_file(metadir, sfname);
+
+ return 0;
+}
+
+/*
+ * m a n i f e s t o _ x p i _ f n
+ *
+ * Called by pointer from SignArchive(), once for
+ * each file within the directory. This function
+ * is only used for adding to XPI compatible archive
+ *
+ */
+static int
+manifesto_xpi_fn(char *relpath, char *basedir, char *reldir, char *filename, void *arg)
+{
+ char fullname[FNSIZE];
+
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "--> %s\n", relpath);
+ }
+
+ /* extension matching */
+ if (extensionsGiven) {
+ char *ext = PL_strrchr(relpath, '.');
+ if (!ext)
+ return 0;
+ if (!PL_HashTableLookup(extensions, ext))
+ return 0;
+ }
+ sprintf(fullname, "%s/%s", basedir, relpath);
+ JzipAdd(fullname, relpath, zipfile, compression_level);
+
+ return 0;
+}
+
+/*
+ * m a n i f e s t o _ f n
+ *
+ * Called by pointer from manifesto(), once for
+ * each file within the directory.
+ *
+ */
+static int
+manifesto_fn(char *relpath, char *basedir, char *reldir, char *filename, void *arg)
+{
+ int use_js;
+ char *md5, *sha1;
+
+ JAR_Digest dig;
+ char fullname[FNSIZE];
+
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "--> %s\n", relpath);
+ }
+
+ /* extension matching */
+ if (extensionsGiven) {
+ char *ext = PL_strrchr(relpath, '.');
+ if (!ext)
+ return 0;
+ if (!PL_HashTableLookup(extensions, ext))
+ return 0;
+ }
+
+ sprintf(fullname, "%s/%s", basedir, relpath);
+
+ fprintf(mf, "\n");
+
+ use_js = 0;
+
+ if (scriptdir && !PORT_Strcmp(scriptdir, reldir))
+ use_js++;
+
+ /* sign non-.js files inside .arc directories using the javascript magic */
+
+ if ((PL_strcaserstr(filename, ".js") != filename + strlen(filename) - 3) &&
+ (PL_strcaserstr(reldir, ".arc") == reldir + strlen(filename) - 4))
+ use_js++;
+
+ if (use_js) {
+ fprintf(mf, "Name: %s\n", filename);
+ fprintf(mf, "Magic: javascript\n");
+
+ if (optimize == 0)
+ fprintf(mf, "javascript.id: %s\n", filename);
+
+ if (metafile)
+ add_meta(mf, filename);
+ } else {
+ fprintf(mf, "Name: %s\n", relpath);
+ if (metafile)
+ add_meta(mf, relpath);
+ }
+
+ JAR_digest_file(fullname, &dig);
+
+ if (optimize == 0) {
+ fprintf(mf, "Digest-Algorithms: MD5 SHA1\n");
+
+ md5 = BTOA_DataToAscii(dig.md5, MD5_LENGTH);
+ fprintf(mf, "MD5-Digest: %s\n", md5);
+ PORT_Free(md5);
+ }
+
+ sha1 = BTOA_DataToAscii(dig.sha1, SHA1_LENGTH);
+ fprintf(mf, "SHA1-Digest: %s\n", sha1);
+ PORT_Free(sha1);
+
+ if (!use_js) {
+ JzipAdd(fullname, relpath, zipfile, compression_level);
+ }
+
+ return 0;
+}
+
+/*
+ * a d d _ m e t a
+ *
+ * Parse the metainfo file, and add any details
+ * necessary to the manifest file. In most cases you
+ * should be using the -i option (ie, for SmartUpdate).
+ *
+ */
+static int
+add_meta(FILE *fp, char *name)
+{
+ FILE *met;
+ char buf[BUFSIZ];
+
+ int place;
+ char *pattern, *meta;
+
+ int num = 0;
+
+ if ((met = fopen(metafile, "r")) != NULL) {
+ while (fgets(buf, BUFSIZ, met)) {
+ char *s;
+
+ for (s = buf; *s && *s != '\n' && *s != '\r'; s++)
+ ;
+ *s = 0;
+
+ if (*buf == 0)
+ continue;
+
+ pattern = buf;
+
+ /* skip to whitespace */
+ for (s = buf; *s && *s != ' ' && *s != '\t'; s++)
+ ;
+
+ /* terminate pattern */
+ if (*s == ' ' || *s == '\t')
+ *s++ = 0;
+
+ /* eat through whitespace */
+ while (*s == ' ' || *s == '\t')
+ s++;
+
+ meta = s;
+
+ /* this will eventually be regexp matching */
+
+ place = 0;
+ if (!PORT_Strcmp(pattern, name))
+ place = 1;
+
+ if (place) {
+ num++;
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "[%s] %s\n", name, meta);
+ }
+ fprintf(fp, "%s\n", meta);
+ }
+ }
+ fclose(met);
+ } else {
+ PR_fprintf(errorFD, "%s: can't open metafile: %s\n", PROGRAM_NAME,
+ metafile);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ return num;
+}
+
+/**********************************************************************
+ *
+ * S i g n F i l e
+ */
+static int
+SignFile(FILE *outFile, FILE *inFile, CERTCertificate *cert)
+{
+ int nb;
+ char ibuf[4096], digestdata[32];
+ const SECHashObject *hashObj;
+ void *hashcx;
+ unsigned int len;
+
+ SECItem digest;
+ SEC_PKCS7ContentInfo *cinfo;
+ SECStatus rv;
+
+ if (outFile == NULL || inFile == NULL || cert == NULL)
+ return -1;
+
+ /* XXX probably want to extend interface to allow other hash algorithms */
+ hashObj = HASH_GetHashObject(HASH_AlgSHA1);
+
+ hashcx = (*hashObj->create)();
+ if (hashcx == NULL)
+ return -1;
+
+ (*hashObj->begin)(hashcx);
+
+ for (;;) {
+ if (feof(inFile))
+ break;
+ nb = fread(ibuf, 1, sizeof(ibuf), inFile);
+ if (nb == 0) {
+ if (ferror(inFile)) {
+ PORT_SetError(SEC_ERROR_IO);
+ (*hashObj->destroy)(hashcx, PR_TRUE);
+ return -1;
+ }
+ /* eof */
+ break;
+ }
+ (*hashObj->update)(hashcx, (unsigned char *)ibuf, nb);
+ }
+
+ (*hashObj->end)(hashcx, (unsigned char *)digestdata, &len, 32);
+ (*hashObj->destroy)(hashcx, PR_TRUE);
+
+ digest.data = (unsigned char *)digestdata;
+ digest.len = len;
+
+ cinfo = SEC_PKCS7CreateSignedData(cert, certUsageObjectSigner, NULL,
+ SEC_OID_SHA1, &digest, NULL, NULL);
+
+ if (cinfo == NULL)
+ return -1;
+
+ rv = SEC_PKCS7IncludeCertChain(cinfo, NULL);
+ if (rv != SECSuccess) {
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ return -1;
+ }
+
+ if (no_time == 0) {
+ rv = SEC_PKCS7AddSigningTime(cinfo);
+ if (rv != SECSuccess) {
+ /* don't check error */
+ }
+ }
+
+ rv = SEC_PKCS7Encode(cinfo, SignOut, outFile, NULL, NULL, &pwdata);
+
+ SEC_PKCS7DestroyContentInfo(cinfo);
+
+ if (rv != SECSuccess)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * g e n e r a t e _ S F _ f i l e
+ *
+ * From the supplied manifest file, calculates
+ * digests on the various sections, creating a .SF
+ * file in the process.
+ *
+ */
+static int
+generate_SF_file(char *manifile, char *who)
+{
+ FILE *sf;
+ FILE *mf;
+ long r1, r2, r3;
+ char whofile[FNSIZE];
+ char *buf, *name = NULL;
+ char *md5, *sha1;
+ JAR_Digest dig;
+ int line = 0;
+
+ strcpy(whofile, who);
+
+ if ((mf = fopen(manifile, "rb")) == NULL) {
+ perror(manifile);
+ exit(ERRX);
+ }
+
+ if ((sf = fopen(whofile, "wb")) == NULL) {
+ perror(who);
+ exit(ERRX);
+ }
+
+ buf = (char *)PORT_ZAlloc(BUFSIZ);
+
+ if (buf)
+ name = (char *)PORT_ZAlloc(BUFSIZ);
+
+ if (buf == NULL || name == NULL)
+ out_of_memory();
+
+ fprintf(sf, "Signature-Version: 1.0\n");
+ fprintf(sf, "Created-By: %s\n", CREATOR);
+ fprintf(sf, "Comments: %s\n", BREAKAGE);
+
+ if (fgets(buf, BUFSIZ, mf) == NULL) {
+ PR_fprintf(errorFD, "%s: empty manifest file!\n", PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ if (strncmp(buf, "Manifest-Version:", 17)) {
+ PR_fprintf(errorFD, "%s: not a manifest file!\n", PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ fseek(mf, 0L, SEEK_SET);
+
+ /* Process blocks of headers, and calculate their hashen */
+
+ while (1) {
+ /* Beginning range */
+ r1 = ftell(mf);
+
+ if (fgets(name, BUFSIZ, mf) == NULL)
+ break;
+
+ line++;
+
+ if (r1 != 0 && strncmp(name, "Name:", 5)) {
+ PR_fprintf(errorFD,
+ "warning: unexpected input in manifest file \"%s\" at line %d:\n",
+ manifile, line);
+ PR_fprintf(errorFD, "%s\n", name);
+ warningCount++;
+ }
+
+ r2 = r1;
+ while (fgets(buf, BUFSIZ, mf)) {
+ if (*buf == 0 || *buf == '\n' || *buf == '\r')
+ break;
+
+ line++;
+
+ /* Ending range for hashing */
+ r2 = ftell(mf);
+ }
+
+ r3 = ftell(mf);
+
+ if (r1) {
+ fprintf(sf, "\n");
+ fprintf(sf, "%s", name);
+ }
+
+ calculate_MD5_range(mf, r1, r2, &dig);
+
+ if (optimize == 0) {
+ fprintf(sf, "Digest-Algorithms: MD5 SHA1\n");
+
+ md5 = BTOA_DataToAscii(dig.md5, MD5_LENGTH);
+ fprintf(sf, "MD5-Digest: %s\n", md5);
+ PORT_Free(md5);
+ }
+
+ sha1 = BTOA_DataToAscii(dig.sha1, SHA1_LENGTH);
+ fprintf(sf, "SHA1-Digest: %s\n", sha1);
+ PORT_Free(sha1);
+
+ /* restore normalcy after changing offset position */
+ fseek(mf, r3, SEEK_SET);
+ }
+
+ PORT_Free(buf);
+ PORT_Free(name);
+
+ fclose(sf);
+ fclose(mf);
+
+ return 0;
+}
+
+/*
+ * c a l c u l a t e _ M D 5 _ r a n g e
+ *
+ * Calculate the MD5 digest on a range of bytes in
+ * the specified fopen'd file. Returns base64.
+ *
+ */
+static int
+calculate_MD5_range(FILE *fp, long r1, long r2, JAR_Digest *dig)
+{
+ int num;
+ int range;
+ unsigned char *buf;
+ SECStatus rv;
+
+ range = r2 - r1;
+
+ /* position to the beginning of range */
+ fseek(fp, r1, SEEK_SET);
+
+ buf = (unsigned char *)PORT_ZAlloc(range);
+ if (buf == NULL)
+ out_of_memory();
+
+ if ((num = fread(buf, 1, range, fp)) != range) {
+ PR_fprintf(errorFD, "%s: expected %d bytes, got %d\n", PROGRAM_NAME,
+ range, num);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ rv = PK11_HashBuf(SEC_OID_MD5, dig->md5, buf, range);
+ if (rv == SECSuccess) {
+ rv = PK11_HashBuf(SEC_OID_SHA1, dig->sha1, buf, range);
+ }
+ if (rv != SECSuccess) {
+ PR_fprintf(errorFD, "%s: can't generate digest context\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ PORT_Free(buf);
+
+ return 0;
+}
+
+static void
+SignOut(void *arg, const char *buf, unsigned long len)
+{
+ fwrite(buf, len, 1, (FILE *)arg);
+}
diff --git a/security/nss/cmd/signtool/signtool.c b/security/nss/cmd/signtool/signtool.c
new file mode 100644
index 000000000..51857d638
--- /dev/null
+++ b/security/nss/cmd/signtool/signtool.c
@@ -0,0 +1,1068 @@
+/* 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/. */
+
+/*
+ * SIGNTOOL
+ *
+ * A command line tool to create manifest files
+ * from a directory hierarchy. It is assumed that
+ * the tree will be equivalent to what resides
+ * or will reside in an archive.
+ *
+ *
+ */
+
+#include "nss.h"
+#include "signtool.h"
+#include "prmem.h"
+#include "prio.h"
+
+/***********************************************************************
+ * Global Variable Definitions
+ */
+char *progName; /* argv[0] */
+
+/* password data */
+secuPWData pwdata = { PW_NONE, 0 };
+
+/* directories or files to exclude in descent */
+PLHashTable *excludeDirs = NULL;
+static PRBool exclusionsGiven = PR_FALSE;
+
+/* zatharus is the man who knows no time, dies tragic death */
+int no_time = 0;
+
+/* -b basename of .rsa, .sf files */
+char *base = DEFAULT_BASE_NAME;
+
+/* Only sign files with this extension */
+PLHashTable *extensions = NULL;
+PRBool extensionsGiven = PR_FALSE;
+
+char *scriptdir = NULL;
+
+int verbosity = 0;
+
+PRFileDesc *outputFD = NULL, *errorFD = NULL;
+
+int errorCount = 0, warningCount = 0;
+
+int compression_level = DEFAULT_COMPRESSION_LEVEL;
+PRBool compression_level_specified = PR_FALSE;
+
+int xpi_arc = 0;
+
+/* Command-line arguments */
+static char *genkey = NULL;
+static char *verify = NULL;
+static char *zipfile = NULL;
+static char *cert_dir = NULL;
+static int javascript = 0;
+static char *jartree = NULL;
+static char *keyName = NULL;
+static char *metafile = NULL;
+static char *install_script = NULL;
+static int list_certs = 0;
+static int list_modules = 0;
+static int optimize = 0;
+static int enableOCSP = 0;
+static char *tell_who = NULL;
+static char *outfile = NULL;
+static char *cmdFile = NULL;
+static PRBool noRecurse = PR_FALSE;
+static PRBool leaveArc = PR_FALSE;
+static int keySize = -1;
+static char *token = NULL;
+
+typedef enum {
+ UNKNOWN_OPT,
+ HELP_OPT,
+ LONG_HELP_OPT,
+ BASE_OPT,
+ COMPRESSION_OPT,
+ CERT_DIR_OPT,
+ EXTENSION_OPT,
+ INSTALL_SCRIPT_OPT,
+ SCRIPTDIR_OPT,
+ CERTNAME_OPT,
+ LIST_OBJSIGN_CERTS_OPT,
+ LIST_ALL_CERTS_OPT,
+ METAFILE_OPT,
+ OPTIMIZE_OPT,
+ ENABLE_OCSP_OPT,
+ PASSWORD_OPT,
+ VERIFY_OPT,
+ WHO_OPT,
+ EXCLUDE_OPT,
+ NO_TIME_OPT,
+ JAVASCRIPT_OPT,
+ ZIPFILE_OPT,
+ GENKEY_OPT,
+ MODULES_OPT,
+ NORECURSE_OPT,
+ SIGNDIR_OPT,
+ OUTFILE_OPT,
+ COMMAND_FILE_OPT,
+ LEAVE_ARC_OPT,
+ VERBOSITY_OPT,
+ KEYSIZE_OPT,
+ TOKEN_OPT,
+ XPI_ARC_OPT
+}
+
+OPT_TYPE;
+
+typedef enum {
+ DUPLICATE_OPTION_ERR = 0,
+ OPTION_NEEDS_ARG_ERR
+}
+
+Error;
+
+static char *errStrings[] = {
+ "warning: %s option specified more than once.\n"
+ "Only last specification will be used.\n",
+ "ERROR: option \"%s\" requires an argument.\n"
+};
+
+static int ProcessOneOpt(OPT_TYPE type, char *arg);
+
+/*********************************************************************
+ *
+ * P r o c e s s C o m m a n d F i l e
+ */
+int
+ProcessCommandFile()
+{
+ PRFileDesc *fd;
+#define CMD_FILE_BUFSIZE 1024
+ char buf[CMD_FILE_BUFSIZE];
+ char *equals;
+ int linenum = 0;
+ int retval = -1;
+ OPT_TYPE type;
+
+ fd = PR_Open(cmdFile, PR_RDONLY, 0777);
+ if (!fd) {
+ PR_fprintf(errorFD, "ERROR: Unable to open command file %s.\n");
+ errorCount++;
+ return -1;
+ }
+
+ while (pr_fgets(buf, CMD_FILE_BUFSIZE, fd)) {
+ char *eol;
+ linenum++;
+
+ /* Chop off final newline */
+ eol = PL_strchr(buf, '\r');
+ if (!eol) {
+ eol = PL_strchr(buf, '\n');
+ }
+ if (eol)
+ *eol = '\0';
+
+ equals = PL_strchr(buf, '=');
+ if (!equals) {
+ continue;
+ }
+
+ *equals = '\0';
+ equals++;
+
+ /* Now buf points to the attribute, and equals points to the value. */
+
+ /* This is pretty straightforward, just deal with whatever attribute
+ * this is */
+ if (!PL_strcasecmp(buf, "basename")) {
+ type = BASE_OPT;
+ } else if (!PL_strcasecmp(buf, "compression")) {
+ type = COMPRESSION_OPT;
+ } else if (!PL_strcasecmp(buf, "certdir")) {
+ type = CERT_DIR_OPT;
+ } else if (!PL_strcasecmp(buf, "extension")) {
+ type = EXTENSION_OPT;
+ } else if (!PL_strcasecmp(buf, "generate")) {
+ type = GENKEY_OPT;
+ } else if (!PL_strcasecmp(buf, "installScript")) {
+ type = INSTALL_SCRIPT_OPT;
+ } else if (!PL_strcasecmp(buf, "javascriptdir")) {
+ type = SCRIPTDIR_OPT;
+ } else if (!PL_strcasecmp(buf, "htmldir")) {
+ type = JAVASCRIPT_OPT;
+ if (jartree) {
+ PR_fprintf(errorFD,
+ "warning: directory to be signed specified more than once."
+ " Only last specification will be used.\n");
+ warningCount++;
+ PR_Free(jartree);
+ jartree = NULL;
+ }
+ jartree = PL_strdup(equals);
+ } else if (!PL_strcasecmp(buf, "certname")) {
+ type = CERTNAME_OPT;
+ } else if (!PL_strcasecmp(buf, "signdir")) {
+ type = SIGNDIR_OPT;
+ } else if (!PL_strcasecmp(buf, "list")) {
+ type = LIST_OBJSIGN_CERTS_OPT;
+ } else if (!PL_strcasecmp(buf, "listall")) {
+ type = LIST_ALL_CERTS_OPT;
+ } else if (!PL_strcasecmp(buf, "metafile")) {
+ type = METAFILE_OPT;
+ } else if (!PL_strcasecmp(buf, "modules")) {
+ type = MODULES_OPT;
+ } else if (!PL_strcasecmp(buf, "optimize")) {
+ type = OPTIMIZE_OPT;
+ } else if (!PL_strcasecmp(buf, "ocsp")) {
+ type = ENABLE_OCSP_OPT;
+ } else if (!PL_strcasecmp(buf, "password")) {
+ type = PASSWORD_OPT;
+ } else if (!PL_strcasecmp(buf, "verify")) {
+ type = VERIFY_OPT;
+ } else if (!PL_strcasecmp(buf, "who")) {
+ type = WHO_OPT;
+ } else if (!PL_strcasecmp(buf, "exclude")) {
+ type = EXCLUDE_OPT;
+ } else if (!PL_strcasecmp(buf, "notime")) {
+ type = NO_TIME_OPT;
+ } else if (!PL_strcasecmp(buf, "jarfile")) {
+ type = ZIPFILE_OPT;
+ } else if (!PL_strcasecmp(buf, "outfile")) {
+ type = OUTFILE_OPT;
+ } else if (!PL_strcasecmp(buf, "leavearc")) {
+ type = LEAVE_ARC_OPT;
+ } else if (!PL_strcasecmp(buf, "verbosity")) {
+ type = VERBOSITY_OPT;
+ } else if (!PL_strcasecmp(buf, "keysize")) {
+ type = KEYSIZE_OPT;
+ } else if (!PL_strcasecmp(buf, "token")) {
+ type = TOKEN_OPT;
+ } else if (!PL_strcasecmp(buf, "xpi")) {
+ type = XPI_ARC_OPT;
+ } else {
+ PR_fprintf(errorFD,
+ "warning: unknown attribute \"%s\" in command file, line %d.\n",
+ buf, linenum);
+ warningCount++;
+ type = UNKNOWN_OPT;
+ }
+
+ /* Process the option, whatever it is */
+ if (type != UNKNOWN_OPT) {
+ if (ProcessOneOpt(type, equals) == -1) {
+ goto finish;
+ }
+ }
+ }
+
+ retval = 0;
+
+finish:
+ PR_Close(fd);
+ return retval;
+}
+
+/*********************************************************************
+ *
+ * p a r s e _ a r g s
+ */
+static int
+parse_args(int argc, char *argv[])
+{
+ char *opt;
+ char *arg;
+ int needsInc = 0;
+ int i;
+ OPT_TYPE type;
+
+ /* Loop over all arguments */
+ for (i = 1; i < argc; i++) {
+ opt = argv[i];
+ arg = NULL;
+
+ if (opt[0] == '-') {
+ if (opt[1] == '-') {
+ /* word option */
+ if (i < argc - 1) {
+ needsInc = 1;
+ arg = argv[i + 1];
+ } else {
+ arg = NULL;
+ }
+
+ if (!PL_strcasecmp(opt + 2, "norecurse")) {
+ type = NORECURSE_OPT;
+ } else if (!PL_strcasecmp(opt + 2, "leavearc")) {
+ type = LEAVE_ARC_OPT;
+ } else if (!PL_strcasecmp(opt + 2, "verbosity")) {
+ type = VERBOSITY_OPT;
+ } else if (!PL_strcasecmp(opt + 2, "outfile")) {
+ type = OUTFILE_OPT;
+ } else if (!PL_strcasecmp(opt + 2, "keysize")) {
+ type = KEYSIZE_OPT;
+ } else if (!PL_strcasecmp(opt + 2, "token")) {
+ type = TOKEN_OPT;
+ } else {
+ PR_fprintf(errorFD, "warning: unknown option: %s\n",
+ opt);
+ warningCount++;
+ type = UNKNOWN_OPT;
+ }
+ } else {
+ /* char option */
+ if (opt[2] != '\0') {
+ arg = opt + 2;
+ } else if (i < argc - 1) {
+ needsInc = 1;
+ arg = argv[i + 1];
+ } else {
+ arg = NULL;
+ }
+
+ switch (opt[1]) {
+ case 'b':
+ type = BASE_OPT;
+ break;
+ case 'c':
+ type = COMPRESSION_OPT;
+ break;
+ case 'd':
+ type = CERT_DIR_OPT;
+ break;
+ case 'e':
+ type = EXTENSION_OPT;
+ break;
+ case 'f':
+ type = COMMAND_FILE_OPT;
+ break;
+ case 'h':
+ type = HELP_OPT;
+ break;
+ case 'H':
+ type = LONG_HELP_OPT;
+ break;
+ case 'i':
+ type = INSTALL_SCRIPT_OPT;
+ break;
+ case 'j':
+ type = SCRIPTDIR_OPT;
+ break;
+ case 'k':
+ type = CERTNAME_OPT;
+ break;
+ case 'l':
+ type = LIST_OBJSIGN_CERTS_OPT;
+ break;
+ case 'L':
+ type = LIST_ALL_CERTS_OPT;
+ break;
+ case 'm':
+ type = METAFILE_OPT;
+ break;
+ case 'o':
+ type = OPTIMIZE_OPT;
+ break;
+ case 'O':
+ type = ENABLE_OCSP_OPT;
+ break;
+ case 'p':
+ type = PASSWORD_OPT;
+ break;
+ case 'v':
+ type = VERIFY_OPT;
+ break;
+ case 'w':
+ type = WHO_OPT;
+ break;
+ case 'x':
+ type = EXCLUDE_OPT;
+ break;
+ case 'X':
+ type = XPI_ARC_OPT;
+ break;
+ case 'z':
+ type = NO_TIME_OPT;
+ break;
+ case 'J':
+ type = JAVASCRIPT_OPT;
+ break;
+ case 'Z':
+ type = ZIPFILE_OPT;
+ break;
+ case 'G':
+ type = GENKEY_OPT;
+ break;
+ case 'M':
+ type = MODULES_OPT;
+ break;
+ case 's':
+ type = KEYSIZE_OPT;
+ break;
+ case 't':
+ type = TOKEN_OPT;
+ break;
+ default:
+ type = UNKNOWN_OPT;
+ PR_fprintf(errorFD, "warning: unrecognized option: -%c.\n",
+ opt[1]);
+ warningCount++;
+ break;
+ }
+ }
+ } else {
+ type = UNKNOWN_OPT;
+ if (i == argc - 1) {
+ if (jartree) {
+ PR_fprintf(errorFD,
+ "warning: directory to be signed specified more than once.\n"
+ " Only last specification will be used.\n");
+ warningCount++;
+ PR_Free(jartree);
+ jartree = NULL;
+ }
+ jartree = PL_strdup(opt);
+ } else {
+ PR_fprintf(errorFD, "warning: unrecognized option: %s\n", opt);
+ warningCount++;
+ }
+ }
+
+ if (type != UNKNOWN_OPT) {
+ short ateArg = ProcessOneOpt(type, arg);
+ if (ateArg == -1) {
+ /* error */
+ return -1;
+ }
+ if (ateArg && needsInc) {
+ i++;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*********************************************************************
+ *
+ * P r o c e s s O n e O p t
+ *
+ * Since options can come from different places (command file, word options,
+ * char options), this is a central function that is called to deal with
+ * them no matter where they come from.
+ *
+ * type is the type of option.
+ * arg is the argument to the option, possibly NULL.
+ * Returns 1 if the argument was eaten, 0 if it wasn't, and -1 for error.
+ */
+static int
+ProcessOneOpt(OPT_TYPE type, char *arg)
+{
+ int ate = 0;
+
+ switch (type) {
+ case HELP_OPT:
+ Usage();
+ break;
+ case LONG_HELP_OPT:
+ LongUsage();
+ break;
+ case BASE_OPT:
+ if (base) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-b");
+ warningCount++;
+ PR_Free(base);
+ base = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-b");
+ errorCount++;
+ goto loser;
+ }
+ base = PL_strdup(arg);
+ ate = 1;
+ break;
+ case COMPRESSION_OPT:
+ if (compression_level_specified) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-c");
+ warningCount++;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-c");
+ errorCount++;
+ goto loser;
+ }
+ compression_level = atoi(arg);
+ compression_level_specified = PR_TRUE;
+ ate = 1;
+ break;
+ case CERT_DIR_OPT:
+ if (cert_dir) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-d");
+ warningCount++;
+ PR_Free(cert_dir);
+ cert_dir = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-d");
+ errorCount++;
+ goto loser;
+ }
+ cert_dir = PL_strdup(arg);
+ ate = 1;
+ break;
+ case EXTENSION_OPT:
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "extension (-e)");
+ errorCount++;
+ goto loser;
+ }
+ PL_HashTableAdd(extensions, arg, arg);
+ extensionsGiven = PR_TRUE;
+ ate = 1;
+ break;
+ case INSTALL_SCRIPT_OPT:
+ if (install_script) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "installScript (-i)");
+ warningCount++;
+ PR_Free(install_script);
+ install_script = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "installScript (-i)");
+ errorCount++;
+ goto loser;
+ }
+ install_script = PL_strdup(arg);
+ ate = 1;
+ break;
+ case SCRIPTDIR_OPT:
+ if (scriptdir) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "javascriptdir (-j)");
+ warningCount++;
+ PR_Free(scriptdir);
+ scriptdir = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "javascriptdir (-j)");
+ errorCount++;
+ goto loser;
+ }
+ scriptdir = PL_strdup(arg);
+ ate = 1;
+ break;
+ case CERTNAME_OPT:
+ if (keyName) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "keyName (-k)");
+ warningCount++;
+ PR_Free(keyName);
+ keyName = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "keyName (-k)");
+ errorCount++;
+ goto loser;
+ }
+ keyName = PL_strdup(arg);
+ ate = 1;
+ break;
+ case LIST_OBJSIGN_CERTS_OPT:
+ case LIST_ALL_CERTS_OPT:
+ if (list_certs != 0) {
+ PR_fprintf(errorFD,
+ "warning: only one of -l and -L may be specified.\n");
+ warningCount++;
+ }
+ list_certs = (type == LIST_OBJSIGN_CERTS_OPT ? 1 : 2);
+ break;
+ case METAFILE_OPT:
+ if (metafile) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "metafile (-m)");
+ warningCount++;
+ PR_Free(metafile);
+ metafile = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "metafile (-m)");
+ errorCount++;
+ goto loser;
+ }
+ metafile = PL_strdup(arg);
+ ate = 1;
+ break;
+ case OPTIMIZE_OPT:
+ optimize = 1;
+ break;
+ case ENABLE_OCSP_OPT:
+ enableOCSP = 1;
+ break;
+ case PASSWORD_OPT:
+ if (pwdata.data) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "password (-p)");
+ warningCount++;
+ PR_Free(pwdata.data);
+ pwdata.data = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "password (-p)");
+ errorCount++;
+ goto loser;
+ }
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = PL_strdup(arg);
+ ate = 1;
+ break;
+ case VERIFY_OPT:
+ if (verify) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "verify (-v)");
+ warningCount++;
+ PR_Free(verify);
+ verify = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "verify (-v)");
+ errorCount++;
+ goto loser;
+ }
+ verify = PL_strdup(arg);
+ ate = 1;
+ break;
+ case WHO_OPT:
+ if (tell_who) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "who (-v)");
+ warningCount++;
+ PR_Free(tell_who);
+ tell_who = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "who (-w)");
+ errorCount++;
+ goto loser;
+ }
+ tell_who = PL_strdup(arg);
+ ate = 1;
+ break;
+ case EXCLUDE_OPT:
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "exclude (-x)");
+ errorCount++;
+ goto loser;
+ }
+ PL_HashTableAdd(excludeDirs, arg, arg);
+ exclusionsGiven = PR_TRUE;
+ ate = 1;
+ break;
+ case NO_TIME_OPT:
+ no_time = 1;
+ break;
+ case JAVASCRIPT_OPT:
+ javascript++;
+ break;
+ case ZIPFILE_OPT:
+ if (zipfile) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "jarfile (-Z)");
+ warningCount++;
+ PR_Free(zipfile);
+ zipfile = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "jarfile (-Z)");
+ errorCount++;
+ goto loser;
+ }
+ zipfile = PL_strdup(arg);
+ ate = 1;
+ break;
+ case GENKEY_OPT:
+ if (genkey) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "generate (-G)");
+ warningCount++;
+ PR_Free(genkey);
+ genkey = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "generate (-G)");
+ errorCount++;
+ goto loser;
+ }
+ genkey = PL_strdup(arg);
+ ate = 1;
+ break;
+ case MODULES_OPT:
+ list_modules++;
+ break;
+ case SIGNDIR_OPT:
+ if (jartree) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "signdir");
+ warningCount++;
+ PR_Free(jartree);
+ jartree = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "signdir");
+ errorCount++;
+ goto loser;
+ }
+ jartree = PL_strdup(arg);
+ ate = 1;
+ break;
+ case OUTFILE_OPT:
+ if (outfile) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "outfile");
+ warningCount++;
+ PR_Free(outfile);
+ outfile = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "outfile");
+ errorCount++;
+ goto loser;
+ }
+ outfile = PL_strdup(arg);
+ ate = 1;
+ break;
+ case COMMAND_FILE_OPT:
+ if (cmdFile) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "-f");
+ warningCount++;
+ PR_Free(cmdFile);
+ cmdFile = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "-f");
+ errorCount++;
+ goto loser;
+ }
+ cmdFile = PL_strdup(arg);
+ ate = 1;
+ break;
+ case NORECURSE_OPT:
+ noRecurse = PR_TRUE;
+ break;
+ case LEAVE_ARC_OPT:
+ leaveArc = PR_TRUE;
+ break;
+ case VERBOSITY_OPT:
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "--verbosity");
+ errorCount++;
+ goto loser;
+ }
+ verbosity = atoi(arg);
+ ate = 1;
+ break;
+ case KEYSIZE_OPT:
+ if (keySize != -1) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-s");
+ warningCount++;
+ }
+ keySize = atoi(arg);
+ ate = 1;
+ if (keySize < 1 || keySize > MAX_RSA_KEY_SIZE) {
+ PR_fprintf(errorFD, "Invalid key size: %d.\n", keySize);
+ errorCount++;
+ goto loser;
+ }
+ break;
+ case TOKEN_OPT:
+ if (token) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-t");
+ PR_Free(token);
+ token = NULL;
+ }
+ if (!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-t");
+ errorCount++;
+ goto loser;
+ }
+ token = PL_strdup(arg);
+ ate = 1;
+ break;
+ case XPI_ARC_OPT:
+ xpi_arc = 1;
+ break;
+ default:
+ PR_fprintf(errorFD, "warning: unknown option\n");
+ warningCount++;
+ break;
+ }
+
+ return ate;
+loser:
+ return -1;
+}
+
+/*********************************************************************
+ *
+ * m a i n
+ */
+int
+main(int argc, char *argv[])
+{
+ PRBool readOnly;
+ int retval = 0;
+
+ outputFD = PR_STDOUT;
+ errorFD = PR_STDERR;
+
+ progName = argv[0];
+
+ if (argc < 2) {
+ Usage();
+ }
+
+ excludeDirs = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
+ PL_CompareStrings, NULL, NULL);
+ extensions = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
+ PL_CompareStrings, NULL, NULL);
+
+ if (parse_args(argc, argv)) {
+ retval = -1;
+ goto cleanup;
+ }
+
+ /* Parse the command file if one was given */
+ if (cmdFile) {
+ if (ProcessCommandFile()) {
+ retval = -1;
+ goto cleanup;
+ }
+ }
+
+ /* Set up output redirection */
+ if (outfile) {
+ if (PR_Access(outfile, PR_ACCESS_EXISTS) == PR_SUCCESS) {
+ /* delete the file if it is already present */
+ PR_fprintf(errorFD,
+ "warning: %s already exists and will be overwritten.\n",
+ outfile);
+ warningCount++;
+ if (PR_Delete(outfile) != PR_SUCCESS) {
+ PR_fprintf(errorFD, "ERROR: unable to delete %s.\n", outfile);
+ errorCount++;
+ exit(ERRX);
+ }
+ }
+ outputFD = PR_Open(outfile,
+ PR_WRONLY |
+ PR_CREATE_FILE | PR_TRUNCATE,
+ 0777);
+ if (!outputFD) {
+ PR_fprintf(errorFD, "ERROR: Unable to create %s.\n",
+ outfile);
+ errorCount++;
+ exit(ERRX);
+ }
+ errorFD = outputFD;
+ }
+
+ /* This seems to be a fairly common user error */
+
+ if (verify && list_certs > 0) {
+ PR_fprintf(errorFD, "%s: Can't use -l and -v at the same time\n",
+ PROGRAM_NAME);
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+ /* -J assumes -Z now */
+
+ if (javascript && zipfile) {
+ PR_fprintf(errorFD, "%s: Can't use -J and -Z at the same time\n",
+ PROGRAM_NAME);
+ PR_fprintf(errorFD, "%s: -J option will create the jar files for you\n",
+ PROGRAM_NAME);
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+ /* -X needs -Z */
+
+ if (xpi_arc && !zipfile) {
+ PR_fprintf(errorFD, "%s: option XPI (-X) requires option jarfile (-Z)\n",
+ PROGRAM_NAME);
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+ /* Less common mixing of -L with various options */
+
+ if (list_certs > 0 &&
+ (tell_who || zipfile || javascript ||
+ scriptdir || extensionsGiven || exclusionsGiven || install_script)) {
+ PR_fprintf(errorFD, "%s: Can't use -l or -L with that option\n",
+ PROGRAM_NAME);
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+ if (!cert_dir)
+ cert_dir = get_default_cert_dir();
+
+ VerifyCertDir(cert_dir, keyName);
+
+ if (compression_level < MIN_COMPRESSION_LEVEL ||
+ compression_level > MAX_COMPRESSION_LEVEL) {
+ PR_fprintf(errorFD, "Compression level must be between %d and %d.\n",
+ MIN_COMPRESSION_LEVEL, MAX_COMPRESSION_LEVEL);
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+ if (jartree && !keyName) {
+ PR_fprintf(errorFD, "You must specify a key with which to sign.\n");
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+ readOnly = (genkey == NULL); /* only key generation requires write */
+ if (InitCrypto(cert_dir, readOnly)) {
+ PR_fprintf(errorFD, "ERROR: Cryptographic initialization failed.\n");
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+ if (enableOCSP) {
+ SECStatus rv = CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
+ if (rv != SECSuccess) {
+ PR_fprintf(errorFD, "ERROR: Attempt to enable OCSP Checking failed.\n");
+ errorCount++;
+ retval = -1;
+ }
+ }
+
+ if (verify) {
+ if (VerifyJar(verify)) {
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+ } else if (list_certs) {
+ if (ListCerts(keyName, list_certs)) {
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+ } else if (list_modules) {
+ JarListModules();
+ } else if (genkey) {
+ if (GenerateCert(genkey, keySize, token)) {
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+ } else if (tell_who) {
+ if (JarWho(tell_who)) {
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+ } else if (javascript && jartree) {
+ /* make sure directory exists */
+ PRDir *dir;
+ dir = PR_OpenDir(jartree);
+ if (!dir) {
+ PR_fprintf(errorFD, "ERROR: unable to open directory %s.\n",
+ jartree);
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ } else {
+ PR_CloseDir(dir);
+ }
+
+ /* undo junk from prior runs of signtool*/
+ if (RemoveAllArc(jartree)) {
+ PR_fprintf(errorFD, "Error removing archive directories under %s\n",
+ jartree);
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+ /* traverse all the htm|html files in the directory */
+ if (InlineJavaScript(jartree, !noRecurse)) {
+ retval = -1;
+ goto cleanup;
+ }
+
+ /* sign any resultant .arc directories created in above step */
+ if (SignAllArc(jartree, keyName, javascript, metafile, install_script,
+ optimize, !noRecurse)) {
+ retval = -1;
+ goto cleanup;
+ }
+
+ if (!leaveArc) {
+ RemoveAllArc(jartree);
+ }
+
+ if (errorCount > 0 || warningCount > 0) {
+ PR_fprintf(outputFD, "%d error%s, %d warning%s.\n",
+ errorCount,
+ errorCount == 1 ? "" : "s", warningCount, warningCount == 1
+ ? ""
+ : "s");
+ } else {
+ PR_fprintf(outputFD, "Directory %s signed successfully.\n",
+ jartree);
+ }
+ } else if (jartree) {
+ SignArchive(jartree, keyName, zipfile, javascript, metafile,
+ install_script, optimize, !noRecurse);
+ } else
+ Usage();
+
+cleanup:
+ if (extensions) {
+ PL_HashTableDestroy(extensions);
+ extensions = NULL;
+ }
+ if (excludeDirs) {
+ PL_HashTableDestroy(excludeDirs);
+ excludeDirs = NULL;
+ }
+ if (outputFD != PR_STDOUT) {
+ PR_Close(outputFD);
+ }
+ rm_dash_r(TMP_OUTPUT);
+ if (retval == 0) {
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ }
+ return retval;
+}
diff --git a/security/nss/cmd/signtool/signtool.gyp b/security/nss/cmd/signtool/signtool.gyp
new file mode 100644
index 000000000..53465ac63
--- /dev/null
+++ b/security/nss/cmd/signtool/signtool.gyp
@@ -0,0 +1,33 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'signtool',
+ 'type': 'executable',
+ 'sources': [
+ 'certgen.c',
+ 'javascript.c',
+ 'list.c',
+ 'sign.c',
+ 'signtool.c',
+ 'util.c',
+ 'verify.c',
+ 'zip.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports',
+ '<(DEPTH)/lib/jar/jar.gyp:jar',
+ '<(DEPTH)/lib/zlib/zlib.gyp:nss_zlib'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/cmd/signtool/signtool.h b/security/nss/cmd/signtool/signtool.h
new file mode 100644
index 000000000..bdb3b597c
--- /dev/null
+++ b/security/nss/cmd/signtool/signtool.h
@@ -0,0 +1,113 @@
+/* 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 SIGNTOOL_H
+#define SIGNTOOL_H
+
+#define DJN_TEST
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "prprf.h"
+#include "prio.h"
+#include "secutil.h"
+#include "ocsp.h"
+#include "jar.h"
+#include "jarfile.h"
+#include "secpkcs7.h"
+#include "pk11func.h"
+#include "secmod.h"
+#include "plhash.h"
+#include "nss.h"
+
+#ifdef _UNIX
+#include <unistd.h>
+#endif
+
+/**********************************************************************
+ * General Defines
+ */
+#define JAR_BASE_END JAR_BASE + 100
+#define ERRX (-1) /* the exit code used on failure */
+#define FNSIZE 256 /* the maximum length for filenames */
+#define MAX_RSA_KEY_SIZE 4096
+#define DEFAULT_RSA_KEY_SIZE 1024
+#define MANIFEST "manifest.mf"
+#define DEFAULT_X509_BASENAME "x509"
+#define DEFAULT_COMMON_NAME "Signtool " NSS_VERSION " Testing Certificate"
+#define CREATOR "Signtool (signtool " NSS_VERSION ")"
+#define BREAKAGE "PLEASE DO NOT EDIT THIS FILE. YOU WILL BREAK IT."
+#define MIN_COMPRESSION_LEVEL (-1)
+#define MAX_COMPRESSION_LEVEL 9
+#define DEFAULT_COMPRESSION_LEVEL (-1) /* zlib understands this to be default*/
+#define STDIN_BUF_SIZE 160
+#define PROGRAM_NAME "signtool"
+#define LONG_PROGRAM_NAME "Signing Tool"
+#define DEFAULT_BASE_NAME "zigbert"
+#define TMP_OUTPUT "signtool.tmp"
+#define XPI_TEXT "Creating XPI Compatible Archive"
+
+/***************************************************************
+ * Main Task Functions
+ */
+int GenerateCert(char *nickname, int keysize, char *token);
+int ListCerts(char *key, int list_certs);
+int VerifyJar(char *filename);
+int SignArchive(char *tree, char *keyName, char *zip_file, int javascript,
+ char *meta_file, char *install_script, int _optimize, PRBool recurse);
+int SignAllArc(char *jartree, char *keyName, int javascript, char *metafile,
+ char *install_script, int optimize, PRBool recurse);
+int InlineJavaScript(char *dir, PRBool recurse);
+int JarWho(char *filename);
+void JarListModules(void);
+
+/**************************************************************
+ * Utility Functions
+ */
+CERTCertDBHandle *OpenCertDB(PRBool readOnly);
+
+int RemoveAllArc(char *tree);
+void VerifyCertDir(char *dir, char *keyName);
+int InitCrypto(char *cert_dir, PRBool readOnly);
+int foreach (char *dirname, char *prefix,
+ int (*fn)(char *filename, char *dirname, char *basedir, char *base, void *arg),
+ PRBool recurse, PRBool includeDirs, void *arg);
+void print_error(int i);
+void give_help(int status);
+const char *secErrorString(long code);
+void displayVerifyLog(CERTVerifyLog *log);
+void Usage(void);
+void LongUsage(void);
+char *chop(char *);
+void out_of_memory(void);
+void FatalError(char *msg);
+char *get_default_cert_dir(void);
+SECItem *password_hardcode(void *arg, void *handle);
+char *pk11_password_hardcode(PK11SlotInfo *slot, PRBool retry, void *arg);
+int rm_dash_r(char *path);
+char *pr_fgets(char *buf, int size, PRFileDesc *file);
+
+/*****************************************************************
+ * Global Variables (*gag*)
+ */
+extern char *password; /* the password passed in on the command line */
+extern PLHashTable *excludeDirs; /* directory entry to skip while recursing */
+extern int no_time;
+extern int xpi_arc;
+extern char *base; /* basename of ".rsa" and ".sf" files */
+extern long *mozilla_event_queue;
+extern char *progName; /* argv[0] */
+extern PLHashTable *extensions; /* only sign files with this extension */
+extern PRBool extensionsGiven;
+extern char *scriptdir;
+extern int compression_level;
+extern PRFileDesc *outputFD, *errorFD;
+extern int verbosity;
+extern int errorCount;
+extern int warningCount;
+extern secuPWData pwdata;
+
+#endif /* SIGNTOOL_H */
diff --git a/security/nss/cmd/signtool/util.c b/security/nss/cmd/signtool/util.c
new file mode 100644
index 000000000..49b7f3b05
--- /dev/null
+++ b/security/nss/cmd/signtool/util.c
@@ -0,0 +1,1086 @@
+/* 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/. */
+
+#include "signtool.h"
+#include "prio.h"
+#include "prmem.h"
+#include "prenv.h"
+#include "nss.h"
+
+static int is_dir(char *filename);
+
+/***********************************************************
+ * Nasty hackish function definitions
+ */
+
+long *mozilla_event_queue = 0;
+
+#ifndef XP_WIN
+char *
+XP_GetString(int i)
+{
+ /* nasty hackish cast to avoid changing the signature of
+ * JAR_init_callbacks() */
+ return (char *)SECU_Strerror(i);
+}
+#endif
+
+void
+FE_SetPasswordEnabled()
+{
+}
+
+void /*MWContext*/ *
+FE_GetInitContext(void)
+{
+ return 0;
+}
+
+void /*MWContext*/ *
+XP_FindSomeContext()
+{
+ /* No windows context in command tools */
+ return NULL;
+}
+
+void
+ET_moz_CallFunction()
+{
+}
+
+/*
+ * R e m o v e A l l A r c
+ *
+ * Remove .arc directories that are lingering
+ * from a previous run of signtool.
+ *
+ */
+int
+RemoveAllArc(char *tree)
+{
+ PRDir *dir;
+ PRDirEntry *entry;
+ char *archive = NULL;
+ int retval = 0;
+
+ dir = PR_OpenDir(tree);
+ if (!dir)
+ return -1;
+
+ for (entry = PR_ReadDir(dir, 0); entry; entry = PR_ReadDir(dir,
+ 0)) {
+
+ if (entry->name[0] == '.') {
+ continue;
+ }
+
+ if (archive)
+ PR_Free(archive);
+ archive = PR_smprintf("%s/%s", tree, entry->name);
+
+ if (PL_strcaserstr(entry->name, ".arc") ==
+ (entry->name + strlen(entry->name) - 4)) {
+
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "removing: %s\n", archive);
+ }
+
+ if (rm_dash_r(archive)) {
+ PR_fprintf(errorFD, "Error removing %s\n", archive);
+ errorCount++;
+ retval = -1;
+ goto finish;
+ }
+ } else if (is_dir(archive)) {
+ if (RemoveAllArc(archive)) {
+ retval = -1;
+ goto finish;
+ }
+ }
+ }
+
+finish:
+ PR_CloseDir(dir);
+ if (archive)
+ PR_Free(archive);
+
+ return retval;
+}
+
+/*
+ * r m _ d a s h _ r
+ *
+ * Remove a file, or a directory recursively.
+ *
+ */
+int
+rm_dash_r(char *path)
+{
+ PRDir *dir;
+ PRDirEntry *entry;
+ PRFileInfo fileinfo;
+ char filename[FNSIZE];
+
+ if (PR_GetFileInfo(path, &fileinfo) != PR_SUCCESS) {
+ /*fprintf(stderr, "Error: Unable to access %s\n", filename);*/
+ return -1;
+ }
+ if (fileinfo.type == PR_FILE_DIRECTORY) {
+
+ dir = PR_OpenDir(path);
+ if (!dir) {
+ PR_fprintf(errorFD, "Error: Unable to open directory %s.\n", path);
+ errorCount++;
+ return -1;
+ }
+
+ /* Recursively delete all entries in the directory */
+ while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) {
+ sprintf(filename, "%s/%s", path, entry->name);
+ if (rm_dash_r(filename))
+ return -1;
+ }
+
+ if (PR_CloseDir(dir) != PR_SUCCESS) {
+ PR_fprintf(errorFD, "Error: Could not close %s.\n", path);
+ errorCount++;
+ return -1;
+ }
+
+ /* Delete the directory itself */
+ if (PR_RmDir(path) != PR_SUCCESS) {
+ PR_fprintf(errorFD, "Error: Unable to delete %s\n", path);
+ errorCount++;
+ return -1;
+ }
+ } else {
+ if (PR_Delete(path) != PR_SUCCESS) {
+ PR_fprintf(errorFD, "Error: Unable to delete %s\n", path);
+ errorCount++;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * u s a g e
+ *
+ * Print some useful help information
+ *
+ */
+
+void
+Usage(void)
+{
+#define FPS PR_fprintf(outputFD,
+ FPS "%s %s -a signing tool for jar files\n", LONG_PROGRAM_NAME,NSS_VERSION);
+ FPS "\n\nType %s -H for more detailed descriptions\n", PROGRAM_NAME);
+ FPS "\nUsage: %s -k keyName [-b basename] [-c Compression Level]\n"
+ "\t\t [-d cert-dir] [-i installer script] [-m metafile] [-x name]\n"
+ "\t\t [-e extension] [-o] [-z] [-X] [--outfile] [--verbose value]\n"
+ "\t\t [--norecurse] [--leavearc] [-j directory] [-Z jarfile] [-O]\n"
+ "\t\t [-p password] directory-tree\n", PROGRAM_NAME);
+ FPS "\t%s -J -k keyName [-b basename] [-c Compression Level]\n"
+ "\t\t [-d cert-dir][-i installer script] [-m metafile] [-x name]\n"
+ "\t\t [-e extension] [-o] [-z] [-X] [--outfile] [--verbose value]\n"
+ "\t\t [--norecurse] [--leavearc] [-j directory] [-p password] [-O] \n"
+ "\t\t directory-tree\n", PROGRAM_NAME);
+ FPS "\t%s -h \n", PROGRAM_NAME);
+ FPS "\t%s -H \n", PROGRAM_NAME);
+ FPS "\t%s -l [-k keyName] [-d cert-dir] [--outfile] [-O] \n", PROGRAM_NAME);
+ FPS "\t%s -L [-k keyName] [-d cert-dir] [--outfile] [-O] \n", PROGRAM_NAME);
+ FPS "\t%s -M [--outfile] [-O] \n", PROGRAM_NAME);
+ FPS "\t%s -v [-d cert-dir] [--outfile] [-O] archive\n", PROGRAM_NAME);
+ FPS "\t%s -w [--outfile] [-O] archive\n" , PROGRAM_NAME);
+ FPS "\t%s -G nickname [--keysize|-s size] [-t |--token tokenname]\n"
+ "\t\t [--outfile] [-O] \n", PROGRAM_NAME);
+ FPS "\t%s -f filename\n" , PROGRAM_NAME);
+ exit(ERRX);
+}
+
+void
+LongUsage(void)
+{
+ FPS "%s %s -a signing tool for jar files\n", LONG_PROGRAM_NAME,NSS_VERSION);
+ FPS "\n%-20s Signs the directory-tree\n",
+ "signtool directory-tree");
+ FPS "%-30s Nickname (key) of the certificate to sign with\n",
+ " -k keyname");
+ FPS "%-30s Base filename for the .rsa and.sf files in the\n",
+ " -b basename");
+ FPS "%-30s META-INF directory\n"," ");
+ FPS "%-30s Set the compression level. 0-9, 0=none\n",
+ " -c CompressionLevel");
+ FPS "%-30s Certificate database directory containing cert*db\n",
+ " -d certificate directory");
+ FPS "%-30s and key*db\n"," ");
+ FPS "%-30s Name of the installer script for SmartUpdate\n",
+ " -i installer script");
+ FPS "%-30s Name of a metadata control file\n",
+ " -m metafile");
+ FPS "%-30s For optimizing the archive for size.\n",
+ " -o");
+ FPS "%-30s Omit Optional Headers\n"," ");
+ FPS "%-30s Excludes the specified directory or file from\n",
+ " -x directory or file name");
+ FPS "%-30s signing\n"," ");
+ FPS "%-30s To not store the signing time in digital\n",
+ " -z directory or file name");
+ FPS "%-30s signature\n"," ");
+ FPS "%-30s Create XPI Compatible Archive. It requires -Z\n",
+ " -X directory or file name");
+ FPS "%-30s option\n"," ");
+ FPS "%-30s Sign only files with the given extension\n",
+ " -e");
+ FPS "%-30s Causes the specified directory to be signed and\n",
+ " -j");
+ FPS "%-30s tags its entries as inline JavaScript\n"," ");
+ FPS "%-30s Creates a JAR file with the specified name.\n",
+ " -Z");
+ FPS "%-30s -Z option cannot be used with -J option\n"," ");
+ FPS "%-30s Specifies a password for the private-key database\n",
+ " -p");
+ FPS "%-30s (insecure)\n"," ");
+ FPS "%-30s File to receive redirected output\n",
+ " --outfile filename");
+ FPS "%-30s Sets the quantity of information generated in\n",
+ " --verbosity value");
+ FPS "%-30s operation\n"," ");
+ FPS "%-30s Blocks recursion into subdirectories\n",
+ " --norecurse");
+ FPS "%-30s Retains the temporary .arc (archive) directories\n",
+ " --leavearc");
+ FPS "%-30s -J option creates\n"," ");
+
+ FPS "\n%-20s Signs a directory of HTML files containing JavaScript and\n",
+ "-J" );
+ FPS "%-20s creates as many archive files as are in the HTML tags.\n"," ");
+
+ FPS "%-20s The options are same as without any command option given\n"," ");
+ FPS "%-20s above. -Z and -J options are not allowed together\n"," ");
+
+ FPS "\n%-20s Generates a new private-public key pair and corresponding\n",
+ "-G nickname");
+ FPS "%-20s object-signing certificates with the given nickname\n"," ");
+ FPS "%-30s Specifies the size of the key for generated \n",
+ " --keysize|-s keysize");
+ FPS "%-30s certificate\n"," ");
+ FPS "%-30s Specifies which available token should generate\n",
+ " --token|-t token name ");
+ FPS "%-30s the key and receive the certificate\n"," ");
+ FPS "%-30s Specifies a file to receive redirected output\n",
+ " --outfile filename ");
+
+ FPS "\n%-20s Display signtool help\n",
+ "-h ");
+
+ FPS "\n%-20s Display signtool help(Detailed)\n",
+ "-H ");
+
+ FPS "\n%-20s Lists signing certificates, including issuing CAs\n",
+ "-l ");
+ FPS "%-30s Certificate database directory containing cert*db\n",
+ " -d certificate directory");
+ FPS "%-30s and key*db\n"," ");
+
+ FPS "%-30s Specifies a file to receive redirected output\n",
+ " --outfile filename ");
+ FPS "%-30s Specifies the nickname (key) of the certificate\n",
+ " -k keyname");
+
+ FPS "\n%-20s Lists the certificates in your database\n",
+ "-L ");
+ FPS "%-30s Certificate database directory containing cert*db\n",
+ " -d certificate directory");
+ FPS "%-30s and key*db\n"," ");
+
+ FPS "%-30s Specifies a file to receive redirected output\n",
+ " --outfile filename ");
+ FPS "%-30s Specifies the nickname (key) of the certificate\n",
+ " -k keyname");
+
+ FPS "\n%-20s Lists the PKCS #11 modules available to signtool\n",
+ "-M ");
+
+ FPS "\n%-20s Displays the contents of an archive and verifies\n",
+ "-v archive");
+ FPS "%-20s cryptographic integrity\n"," ");
+ FPS "%-30s Certificate database directory containing cert*db\n",
+ " -d certificate directory");
+ FPS "%-30s and key*db\n"," ");
+ FPS "%-30s Specifies a file to receive redirected output\n",
+ " --outfile filename ");
+
+ FPS "\n%-20s Displays the names of signers in the archive\n",
+ "-w archive");
+ FPS "%-30s Specifies a file to receive redirected output\n",
+ " --outfile filename ");
+
+ FPS "\n%-30s Common option to all the above.\n",
+ " -O");
+ FPS "%-30s Enable OCSP checking\n"," ");
+
+ FPS "\n%-20s Specifies a text file containing options and arguments in\n",
+ "-f command-file");
+ FPS "%-20s keyword=value format. Commands are taken from this file\n"," ");
+
+ FPS "\n\n\n");
+ FPS "Example:\n");
+ FPS "%-10s -d \"certificate directory\" -k \"certnickname\" \\",
+ PROGRAM_NAME);
+ FPS "\n%-10s -p \"password\" -X -Z \"file.xpi\" directory-tree\n"," " );
+ FPS "Common syntax to create an XPInstall compatible"
+ " signed archive\n\n"," ");
+ FPS "\nCommand File Keywords and Example:\n");
+ FPS "\nKeyword\t\tValue\n");
+ FPS "basename\tSame as -b option\n");
+ FPS "compression\tSame as -c option\n");
+ FPS "certdir\t\tSame as -d option\n");
+ FPS "extension\tSame as -e option\n");
+ FPS "generate\tSame as -G option\n");
+ FPS "installscript\tSame as -i option\n");
+ FPS "javascriptdir\tSame as -j option\n");
+ FPS "htmldir\t\tSame as -J option\n");
+ FPS "certname\tNickname of certificate, as with -k option\n");
+ FPS "signdir\t\tThe directory to be signed, as with -k option\n");
+ FPS "list\t\tSame as -l option. Value is ignored,\n"
+ " \t\tbut = sign must be present\n");
+ FPS "listall\t\tSame as -L option. Value is ignored\n"
+ " \t\tbut = sign must be present\n");
+ FPS "metafile\tSame as -m option\n");
+ FPS "modules\t\tSame as -M option. Value is ignored,\n"
+ " \t\tbut = sign must be present\n");
+ FPS "optimize\tSame as -o option. Value is ignored,\n"
+ " \tbut = sign must be present\n");
+ FPS "ocsp\t\tSame as -O option\n");
+ FPS "password\tSame as -p option\n");
+ FPS "verify\t\tSame as -v option\n");
+ FPS "who\t\tSame as -w option\n");
+ FPS "exclude\t\tSame as -x option\n");
+ FPS "notime\t\tSame as -z option. Value is ignored,\n"
+ " \t\tbut = sign must be present\n");
+ FPS "jarfile\t\tSame as -Z option\n");
+ FPS "outfile\t\tSame as --outfile option. The argument\n");
+ FPS " \t\tis the name of a file to which output\n");
+ FPS " \t\tof a file and error messages will be \n");
+ FPS " \t\tredirected\n");
+ FPS "leavearc\tSame as --leavearc option\n");
+ FPS "verbosity\tSame as --verbosity option\n");
+ FPS "keysize\t\tSame as -s option\n");
+ FPS "token\t\tSame as -t option\n");
+ FPS "xpi\t\tSame as -X option\n");
+ FPS "\n\n");
+ FPS "Here's an example of the use of the command file. The command\n\n");
+ FPS " signtool -d c:\\netscape\\users\\james -k mycert -Z myjar.jar \\\n"
+ " signdir > output.txt\n\n");
+ FPS "becomes\n\n");
+ FPS " signtool -f somefile\n\n");
+ FPS "where somefile contains the following lines:\n\n");
+ FPS " certdir=c:\\netscape\\users\\james\n"," ");
+ FPS " certname=mycert\n"," ");
+ FPS " jarfile=myjar.jar\n"," ");
+ FPS " signdir=signdir\n"," ");
+ FPS " outfile=output.txt\n"," ");
+ exit(ERRX);
+#undef FPS
+}
+
+/*
+ * p r i n t _ e r r o r
+ *
+ * For the undocumented -E function. If an older version
+ * of communicator gives you a numeric error, we can see what
+ * really happened without doing hex math.
+ *
+ */
+
+void
+print_error(int err)
+{
+ PR_fprintf(errorFD, "Error %d: %s\n", err, JAR_get_error(err));
+ errorCount++;
+ give_help(err);
+}
+
+/*
+ * o u t _ o f _ m e m o r y
+ *
+ * Out of memory, exit Signtool.
+ *
+ */
+void
+out_of_memory(void)
+{
+ PR_fprintf(errorFD, "%s: out of memory\n", PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+}
+
+/*
+ * V e r i f y C e r t D i r
+ *
+ * Validate that the specified directory
+ * contains a certificate database
+ *
+ */
+void
+VerifyCertDir(char *dir, char *keyName)
+{
+ char fn[FNSIZE];
+
+ /* don't try verifying if we don't have a local directory */
+ if (strncmp(dir, "multiaccess:", sizeof("multiaccess:") - 1) == 0) {
+ return;
+ }
+ /* this function is truly evil. Tools and applications should not have
+ * any knowledge of actual cert databases! */
+ return;
+
+ /* This code is really broken because it makes underlying assumptions about
+ * how the NSS profile directory is laid out, but these names can change
+ * from release to release. */
+ sprintf(fn, "%s/cert8.db", dir);
+
+ if (PR_Access(fn, PR_ACCESS_EXISTS)) {
+ PR_fprintf(errorFD, "%s: No certificate database in \"%s\"\n",
+ PROGRAM_NAME, dir);
+ PR_fprintf(errorFD, "%s: Check the -d arguments that you gave\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "using certificate directory: %s\n", dir);
+ }
+
+ if (keyName == NULL)
+ return;
+
+ /* if the user gave the -k key argument, verify that
+ a key database already exists */
+
+ sprintf(fn, "%s/key3.db", dir);
+
+ if (PR_Access(fn, PR_ACCESS_EXISTS)) {
+ PR_fprintf(errorFD, "%s: No private key database in \"%s\"\n",
+ PROGRAM_NAME,
+ dir);
+ PR_fprintf(errorFD, "%s: Check the -d arguments that you gave\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+}
+
+/*
+ * f o r e a c h
+ *
+ * A recursive function to loop through all names in
+ * the specified directory, as well as all subdirectories.
+ *
+ * FIX: Need to see if all platforms allow multiple
+ * opendir's to be called.
+ *
+ */
+
+int foreach (char *dirname, char *prefix,
+ int (*fn)(char *relpath, char *basedir, char *reldir, char *filename,
+ void *arg),
+ PRBool recurse, PRBool includeDirs, void *arg)
+{
+ char newdir[FNSIZE];
+ int retval = 0;
+
+ PRDir *dir;
+ PRDirEntry *entry;
+
+ strcpy(newdir, dirname);
+ if (*prefix) {
+ strcat(newdir, "/");
+ strcat(newdir, prefix);
+ }
+
+ dir = PR_OpenDir(newdir);
+ if (!dir)
+ return -1;
+
+ for (entry = PR_ReadDir(dir, 0); entry; entry = PR_ReadDir(dir, 0)) {
+ if (strcmp(entry->name, ".") == 0 ||
+ strcmp(entry->name, "..") == 0) {
+ /* no infinite recursion, please */
+ continue;
+ }
+
+ /* can't sign self */
+ if (!strcmp(entry->name, "META-INF"))
+ continue;
+
+ /* -x option */
+ if (PL_HashTableLookup(excludeDirs, entry->name))
+ continue;
+
+ strcpy(newdir, dirname);
+ if (*dirname)
+ strcat(newdir, "/");
+
+ if (*prefix) {
+ strcat(newdir, prefix);
+ strcat(newdir, "/");
+ }
+ strcat(newdir, entry->name);
+
+ if (!is_dir(newdir) || includeDirs) {
+ char newpath[FNSIZE];
+
+ strcpy(newpath, prefix);
+ if (*newpath)
+ strcat(newpath, "/");
+ strcat(newpath, entry->name);
+
+ if ((*fn)(newpath, dirname, prefix, (char *)entry->name,
+ arg)) {
+ retval = -1;
+ break;
+ }
+ }
+
+ if (is_dir(newdir)) {
+ if (recurse) {
+ char newprefix[FNSIZE];
+
+ strcpy(newprefix, prefix);
+ if (*newprefix) {
+ strcat(newprefix, "/");
+ }
+ strcat(newprefix, entry->name);
+
+ if (foreach (dirname, newprefix, fn, recurse,
+ includeDirs, arg)) {
+ retval = -1;
+ break;
+ }
+ }
+ }
+ }
+
+ PR_CloseDir(dir);
+
+ return retval;
+}
+
+/*
+ * i s _ d i r
+ *
+ * Return 1 if file is a directory.
+ * Wonder if this runs on a mac, trust not.
+ *
+ */
+static int
+is_dir(char *filename)
+{
+ PRFileInfo finfo;
+
+ if (PR_GetFileInfo(filename, &finfo) != PR_SUCCESS) {
+ printf("Unable to get information about %s\n", filename);
+ return 0;
+ }
+
+ return (finfo.type == PR_FILE_DIRECTORY);
+}
+
+/***************************************************************
+ *
+ * s e c E r r o r S t r i n g
+ *
+ * Returns an error string corresponding to the given error code.
+ * Doesn't cover all errors; returns a default for many.
+ * Returned string is only valid until the next call of this function.
+ */
+const char *
+secErrorString(long code)
+{
+ static char errstring[80]; /* dynamically constructed error string */
+ char *c; /* the returned string */
+
+ switch (code) {
+ case SEC_ERROR_IO:
+ c = "io error";
+ break;
+ case SEC_ERROR_LIBRARY_FAILURE:
+ c = "security library failure";
+ break;
+ case SEC_ERROR_BAD_DATA:
+ c = "bad data";
+ break;
+ case SEC_ERROR_OUTPUT_LEN:
+ c = "output length";
+ break;
+ case SEC_ERROR_INPUT_LEN:
+ c = "input length";
+ break;
+ case SEC_ERROR_INVALID_ARGS:
+ c = "invalid args";
+ break;
+ case SEC_ERROR_EXPIRED_CERTIFICATE:
+ c = "expired certificate";
+ break;
+ case SEC_ERROR_REVOKED_CERTIFICATE:
+ c = "revoked certificate";
+ break;
+ case SEC_ERROR_INADEQUATE_KEY_USAGE:
+ c = "inadequate key usage";
+ break;
+ case SEC_ERROR_INADEQUATE_CERT_TYPE:
+ c = "inadequate certificate type";
+ break;
+ case SEC_ERROR_UNTRUSTED_CERT:
+ c = "untrusted cert";
+ break;
+ case SEC_ERROR_NO_KRL:
+ c = "no key revocation list";
+ break;
+ case SEC_ERROR_KRL_BAD_SIGNATURE:
+ c = "key revocation list: bad signature";
+ break;
+ case SEC_ERROR_KRL_EXPIRED:
+ c = "key revocation list expired";
+ break;
+ case SEC_ERROR_REVOKED_KEY:
+ c = "revoked key";
+ break;
+ case SEC_ERROR_CRL_BAD_SIGNATURE:
+ c = "certificate revocation list: bad signature";
+ break;
+ case SEC_ERROR_CRL_EXPIRED:
+ c = "certificate revocation list expired";
+ break;
+ case SEC_ERROR_CRL_NOT_YET_VALID:
+ c = "certificate revocation list not yet valid";
+ break;
+ case SEC_ERROR_UNKNOWN_ISSUER:
+ c = "unknown issuer";
+ break;
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ c = "expired issuer certificate";
+ break;
+ case SEC_ERROR_BAD_SIGNATURE:
+ c = "bad signature";
+ break;
+ case SEC_ERROR_BAD_KEY:
+ c = "bad key";
+ break;
+ case SEC_ERROR_NOT_FORTEZZA_ISSUER:
+ c = "not fortezza issuer";
+ break;
+ case SEC_ERROR_CA_CERT_INVALID:
+ c = "Certificate Authority certificate invalid";
+ break;
+ case SEC_ERROR_EXTENSION_NOT_FOUND:
+ c = "extension not found";
+ break;
+ case SEC_ERROR_CERT_NOT_IN_NAME_SPACE:
+ c = "certificate not in name space";
+ break;
+ case SEC_ERROR_UNTRUSTED_ISSUER:
+ c = "untrusted issuer";
+ break;
+ default:
+ sprintf(errstring, "security error %ld", code);
+ c = errstring;
+ break;
+ }
+
+ return c;
+}
+
+/***************************************************************
+ *
+ * d i s p l a y V e r i f y L o g
+ *
+ * Prints the log of a cert verification.
+ */
+void
+displayVerifyLog(CERTVerifyLog *log)
+{
+ CERTVerifyLogNode *node;
+ CERTCertificate *cert;
+ char *name;
+
+ if (!log || (log->count <= 0)) {
+ return;
+ }
+
+ for (node = log->head; node != NULL; node = node->next) {
+
+ if (!(cert = node->cert)) {
+ continue;
+ }
+
+ /* Get a name for this cert */
+ if (cert->nickname != NULL) {
+ name = cert->nickname;
+ } else if (cert->emailAddr && cert->emailAddr[0]) {
+ name = cert->emailAddr;
+ } else {
+ name = cert->subjectName;
+ }
+
+ printf("%s%s:\n", name,
+ (node->depth > 0) ? " [Certificate Authority]" : "");
+
+ printf("\t%s\n", secErrorString(node->error));
+ }
+}
+
+/*
+ * J a r L i s t M o d u l e s
+ *
+ * Print a list of the PKCS11 modules that are
+ * available. This is useful for smartcard people to
+ * make sure they have the drivers loaded.
+ *
+ */
+void
+JarListModules(void)
+{
+ int i;
+ int count = 0;
+
+ SECMODModuleList *modules = NULL;
+ static SECMODListLock *moduleLock = NULL;
+
+ SECMODModuleList *mlp;
+
+ if ((moduleLock = SECMOD_GetDefaultModuleListLock()) == NULL) {
+ /* this is the wrong text */
+ PR_fprintf(errorFD, "%s: unable to acquire lock on module list\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ SECMOD_GetReadLock(moduleLock);
+
+ modules = SECMOD_GetDefaultModuleList();
+
+ if (modules == NULL) {
+ SECMOD_ReleaseReadLock(moduleLock);
+ PR_fprintf(errorFD, "%s: Can't get module list\n", PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ PR_fprintf(outputFD, "\nListing of PKCS11 modules\n");
+ PR_fprintf(outputFD, "-----------------------------------------------\n");
+
+ for (mlp = modules; mlp != NULL; mlp = mlp->next) {
+ count++;
+ PR_fprintf(outputFD, "%3d. %s\n", count, mlp->module->commonName);
+
+ if (mlp->module->internal)
+ PR_fprintf(outputFD, " (this module is internally loaded)\n");
+ else
+ PR_fprintf(outputFD, " (this is an external module)\n");
+
+ if (mlp->module->dllName)
+ PR_fprintf(outputFD, " DLL name: %s\n",
+ mlp->module->dllName);
+
+ if (mlp->module->slotCount == 0)
+ PR_fprintf(outputFD, " slots: There are no slots attached to this module\n");
+ else
+ PR_fprintf(outputFD, " slots: %d slots attached\n",
+ mlp->module->slotCount);
+
+ if (mlp->module->loaded == 0)
+ PR_fprintf(outputFD, " status: Not loaded\n");
+ else
+ PR_fprintf(outputFD, " status: loaded\n");
+
+ for (i = 0; i < mlp->module->slotCount; i++) {
+ PK11SlotInfo *slot = mlp->module->slots[i];
+
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, " slot: %s\n", PK11_GetSlotName(slot));
+ PR_fprintf(outputFD, " token: %s\n", PK11_GetTokenName(slot));
+ }
+ }
+
+ PR_fprintf(outputFD, "-----------------------------------------------\n");
+
+ if (count == 0)
+ PR_fprintf(outputFD,
+ "Warning: no modules were found (should have at least one)\n");
+
+ SECMOD_ReleaseReadLock(moduleLock);
+}
+
+/**********************************************************************
+ * c h o p
+ *
+ * Eliminates leading and trailing whitespace. Returns a pointer to the
+ * beginning of non-whitespace, or an empty string if it's all whitespace.
+ */
+char *
+chop(char *str)
+{
+ char *start, *end;
+
+ if (str) {
+ start = str;
+
+ /* Nip leading whitespace */
+ while (isspace(*start)) {
+ start++;
+ }
+
+ /* Nip trailing whitespace */
+ if (*start) {
+ end = start + strlen(start) - 1;
+ while (isspace(*end) && end > start) {
+ end--;
+ }
+ *(end + 1) = '\0';
+ }
+
+ return start;
+ } else {
+ return NULL;
+ }
+}
+
+/***********************************************************************
+ *
+ * F a t a l E r r o r
+ *
+ * Outputs an error message and bails out of the program.
+ */
+void
+FatalError(char *msg)
+{
+ if (!msg)
+ msg = "";
+
+ PR_fprintf(errorFD, "FATAL ERROR: %s\n", msg);
+ errorCount++;
+ exit(ERRX);
+}
+
+/*************************************************************************
+ *
+ * I n i t C r y p t o
+ */
+int
+InitCrypto(char *cert_dir, PRBool readOnly)
+{
+ SECStatus rv;
+ static int prior = 0;
+ PK11SlotInfo *slotinfo;
+
+ if (prior == 0) {
+ /* some functions such as OpenKeyDB expect this path to be
+ * implicitly set prior to calling */
+ if (readOnly) {
+ rv = NSS_Init(cert_dir);
+ } else {
+ rv = NSS_InitReadWrite(cert_dir);
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(PROGRAM_NAME);
+ exit(-1);
+ }
+
+ SECU_ConfigDirectory(cert_dir);
+
+ /* Been there done that */
+ prior++;
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ /* Must login to FIPS before you do anything else */
+ if (PK11_IsFIPS()) {
+ slotinfo = PK11_GetInternalSlot();
+ if (!slotinfo) {
+ fprintf(stderr, "%s: Unable to get PKCS #11 Internal Slot."
+ "\n",
+ PROGRAM_NAME);
+ return -1;
+ }
+ if (PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/,
+ &pwdata) != SECSuccess) {
+ fprintf(stderr, "%s: Unable to authenticate to %s.\n",
+ PROGRAM_NAME, PK11_GetSlotName(slotinfo));
+ PK11_FreeSlot(slotinfo);
+ return -1;
+ }
+ PK11_FreeSlot(slotinfo);
+ }
+
+ /* Make sure there is a password set on the internal key slot */
+ slotinfo = PK11_GetInternalKeySlot();
+ if (!slotinfo) {
+ fprintf(stderr, "%s: Unable to get PKCS #11 Internal Key Slot."
+ "\n",
+ PROGRAM_NAME);
+ return -1;
+ }
+ if (PK11_NeedUserInit(slotinfo)) {
+ PR_fprintf(errorFD,
+ "\nWARNING: No password set on internal key database. Most operations will fail."
+ "\nYou must create a password.\n");
+ warningCount++;
+ }
+
+ /* Make sure we can authenticate to the key slot in FIPS mode */
+ if (PK11_IsFIPS()) {
+ if (PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/,
+ &pwdata) != SECSuccess) {
+ fprintf(stderr, "%s: Unable to authenticate to %s.\n",
+ PROGRAM_NAME, PK11_GetSlotName(slotinfo));
+ PK11_FreeSlot(slotinfo);
+ return -1;
+ }
+ }
+ PK11_FreeSlot(slotinfo);
+ }
+
+ return 0;
+}
+
+/* Windows foolishness is now in the secutil lib */
+
+/*****************************************************************
+ * g e t _ d e f a u l t _ c e r t _ d i r
+ *
+ * Attempt to locate a certificate directory.
+ * Failing that, complain that the user needs to
+ * use the -d(irectory) parameter.
+ *
+ */
+char *
+get_default_cert_dir(void)
+{
+ char *home;
+
+ char *cd = NULL;
+ static char db[FNSIZE];
+
+#ifdef XP_UNIX
+ home = PR_GetEnvSecure("HOME");
+
+ if (home && *home) {
+ sprintf(db, "%s/.netscape", home);
+ cd = db;
+ }
+#endif
+
+#ifdef XP_PC
+ FILE *fp;
+
+ /* first check the environment override */
+
+ home = PR_GetEnvSecure("JAR_HOME");
+
+ if (home && *home) {
+ sprintf(db, "%s/cert7.db", home);
+
+ if ((fp = fopen(db, "r")) != NULL) {
+ fclose(fp);
+ cd = home;
+ }
+ }
+
+ /* try the old navigator directory */
+
+ if (cd == NULL) {
+ home = "c:/Program Files/Netscape/Navigator";
+
+ sprintf(db, "%s/cert7.db", home);
+
+ if ((fp = fopen(db, "r")) != NULL) {
+ fclose(fp);
+ cd = home;
+ }
+ }
+
+ /* Try the current directory, I wonder if this
+ is really a good idea. Remember, Windows only.. */
+
+ if (cd == NULL) {
+ home = ".";
+
+ sprintf(db, "%s/cert7.db", home);
+
+ if ((fp = fopen(db, "r")) != NULL) {
+ fclose(fp);
+ cd = home;
+ }
+ }
+
+#endif
+
+ if (!cd) {
+ PR_fprintf(errorFD,
+ "You must specify the location of your certificate directory\n");
+ PR_fprintf(errorFD,
+ "with the -d option. Example: -d ~/.netscape in many cases with Unix.\n");
+ errorCount++;
+ exit(ERRX);
+ }
+
+ return cd;
+}
+
+/************************************************************************
+ * g i v e _ h e l p
+ */
+void
+give_help(int status)
+{
+ if (status == SEC_ERROR_UNKNOWN_ISSUER) {
+ PR_fprintf(errorFD,
+ "The Certificate Authority (CA) for this certificate\n");
+ PR_fprintf(errorFD,
+ "does not appear to be in your database. You should contact\n");
+ PR_fprintf(errorFD,
+ "the organization which issued this certificate to obtain\n");
+ PR_fprintf(errorFD, "a copy of its CA Certificate.\n");
+ }
+}
+
+/**************************************************************************
+ *
+ * p r _ f g e t s
+ *
+ * fgets implemented with NSPR.
+ */
+char *
+pr_fgets(char *buf, int size, PRFileDesc *file)
+{
+ int i;
+ int status;
+ char c;
+
+ i = 0;
+ while (i < size - 1) {
+ status = PR_Read(file, &c, 1);
+ if (status == -1) {
+ return NULL;
+ } else if (status == 0) {
+ if (i == 0) {
+ return NULL;
+ }
+ break;
+ }
+ buf[i++] = c;
+ if (c == '\n') {
+ break;
+ }
+ }
+ buf[i] = '\0';
+
+ return buf;
+}
diff --git a/security/nss/cmd/signtool/verify.c b/security/nss/cmd/signtool/verify.c
new file mode 100644
index 000000000..41656a10f
--- /dev/null
+++ b/security/nss/cmd/signtool/verify.c
@@ -0,0 +1,337 @@
+/* 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/. */
+
+#include "signtool.h"
+
+static int jar_cb(int status, JAR *jar, const char *metafile,
+ char *pathname, char *errortext);
+static int verify_global(JAR *jar);
+
+/*************************************************************************
+ *
+ * V e r i f y J a r
+ */
+int
+VerifyJar(char *filename)
+{
+ FILE *fp;
+
+ int ret;
+ int status;
+ int failed = 0;
+ char *err;
+
+ JAR *jar;
+ JAR_Context *ctx;
+
+ JAR_Item *it;
+
+ jar = JAR_new();
+
+ if ((fp = fopen(filename, "r")) == NULL) {
+ perror(filename);
+ exit(ERRX);
+ } else
+ fclose(fp);
+
+ JAR_set_callback(JAR_CB_SIGNAL, jar, jar_cb);
+
+ status = JAR_pass_archive(jar, jarArchGuess, filename, "some-url");
+
+ if (status < 0 || jar->valid < 0) {
+ failed = 1;
+ PR_fprintf(outputFD,
+ "\nNOTE -- \"%s\" archive DID NOT PASS crypto verification.\n",
+ filename);
+ if (status < 0) {
+ const char *errtext;
+
+ if (status >= JAR_BASE && status <= JAR_BASE_END) {
+ errtext = JAR_get_error(status);
+ } else {
+ errtext = SECU_Strerror(PORT_GetError());
+ }
+
+ PR_fprintf(outputFD, " (reported reason: %s)\n\n",
+ errtext);
+
+ /* corrupt files should not have their contents listed */
+
+ if (status == JAR_ERR_CORRUPT)
+ return -1;
+ }
+ PR_fprintf(outputFD,
+ "entries shown below will have their digests checked only.\n");
+ jar->valid = 0;
+ } else
+ PR_fprintf(outputFD,
+ "archive \"%s\" has passed crypto verification.\n", filename);
+
+ if (verify_global(jar))
+ failed = 1;
+
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "%16s %s\n", "status", "path");
+ PR_fprintf(outputFD, "%16s %s\n", "------------", "-------------------");
+
+ ctx = JAR_find(jar, NULL, jarTypeMF);
+
+ while (JAR_find_next(ctx, &it) >= 0) {
+ if (it && it->pathname) {
+ rm_dash_r(TMP_OUTPUT);
+ ret = JAR_verified_extract(jar, it->pathname, TMP_OUTPUT);
+ /* if (ret < 0) printf ("error %d on %s\n", ret, it->pathname); */
+ if (ret < 0)
+ failed = 1;
+
+ if (ret == JAR_ERR_PNF)
+ err = "NOT PRESENT";
+ else if (ret == JAR_ERR_HASH)
+ err = "HASH FAILED";
+ else
+ err = "NOT VERIFIED";
+
+ PR_fprintf(outputFD, "%16s %s\n",
+ ret >= 0 ? "verified" : err, it->pathname);
+
+ if (ret != 0 && ret != JAR_ERR_PNF && ret != JAR_ERR_HASH)
+ PR_fprintf(outputFD, " (reason: %s)\n",
+ JAR_get_error(ret));
+ }
+ }
+
+ JAR_find_end(ctx);
+
+ if (status < 0 || jar->valid < 0) {
+ failed = 1;
+ PR_fprintf(outputFD,
+ "\nNOTE -- \"%s\" archive DID NOT PASS crypto verification.\n",
+ filename);
+ give_help(status);
+ }
+
+ JAR_destroy(jar);
+
+ if (failed)
+ return -1;
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * v e r i f y _ g l o b a l
+ */
+static int
+verify_global(JAR *jar)
+{
+ FILE *fp;
+ JAR_Context *ctx;
+ JAR_Item *it;
+ JAR_Digest *globaldig;
+ char *ext;
+ unsigned char *md5_digest, *sha1_digest;
+ unsigned int sha1_length, md5_length;
+ int retval = 0;
+ char buf[BUFSIZ];
+
+ ctx = JAR_find(jar, "*", jarTypePhy);
+
+ while (JAR_find_next(ctx, &it) >= 0) {
+ if (!PORT_Strncmp(it->pathname, "META-INF", 8)) {
+ for (ext = it->pathname; *ext; ext++)
+ ;
+ while (ext > it->pathname && *ext != '.')
+ ext--;
+
+ if (verbosity >= 0) {
+ if (!PORT_Strcasecmp(ext, ".rsa")) {
+ PR_fprintf(outputFD, "found a RSA signature file: %s\n",
+ it->pathname);
+ }
+
+ if (!PORT_Strcasecmp(ext, ".dsa")) {
+ PR_fprintf(outputFD, "found a DSA signature file: %s\n",
+ it->pathname);
+ }
+
+ if (!PORT_Strcasecmp(ext, ".mf")) {
+ PR_fprintf(outputFD,
+ "found a MF master manifest file: %s\n",
+ it->pathname);
+ }
+ }
+
+ if (!PORT_Strcasecmp(ext, ".sf")) {
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD,
+ "found a SF signature manifest file: %s\n",
+ it->pathname);
+ }
+
+ rm_dash_r(TMP_OUTPUT);
+ if (JAR_extract(jar, it->pathname, TMP_OUTPUT) < 0) {
+ PR_fprintf(errorFD, "%s: error extracting %s\n",
+ PROGRAM_NAME, it->pathname);
+ errorCount++;
+ retval = -1;
+ continue;
+ }
+
+ md5_digest = NULL;
+ sha1_digest = NULL;
+
+ if ((fp = fopen(TMP_OUTPUT, "rb")) != NULL) {
+ while (fgets(buf, BUFSIZ, fp)) {
+ char *s;
+
+ if (*buf == 0 || *buf == '\n' || *buf == '\r')
+ break;
+
+ for (s = buf; *s && *s != '\n' && *s != '\r'; s++)
+ ;
+ *s = 0;
+
+ if (!PORT_Strncmp(buf, "MD5-Digest: ", 12)) {
+ md5_digest =
+ ATOB_AsciiToData(buf + 12, &md5_length);
+ }
+ if (!PORT_Strncmp(buf, "SHA1-Digest: ", 13)) {
+ sha1_digest =
+ ATOB_AsciiToData(buf + 13, &sha1_length);
+ }
+ if (!PORT_Strncmp(buf, "SHA-Digest: ", 12)) {
+ sha1_digest =
+ ATOB_AsciiToData(buf + 12, &sha1_length);
+ }
+ }
+
+ globaldig = jar->globalmeta;
+
+ if (globaldig && md5_digest && verbosity >= 0) {
+ PR_fprintf(outputFD,
+ " md5 digest on global metainfo: %s\n",
+ PORT_Memcmp(md5_digest, globaldig->md5, MD5_LENGTH)
+ ? "no match"
+ : "match");
+ }
+
+ if (globaldig && sha1_digest && verbosity >= 0) {
+ PR_fprintf(outputFD,
+ " sha digest on global metainfo: %s\n",
+ PORT_Memcmp(sha1_digest, globaldig->sha1, SHA1_LENGTH)
+ ? "no match"
+ : "match");
+ }
+
+ if (globaldig == NULL && verbosity >= 0) {
+ PR_fprintf(outputFD,
+ "global metadigest is not available, strange.\n");
+ }
+
+ PORT_Free(md5_digest);
+ PORT_Free(sha1_digest);
+ fclose(fp);
+ }
+ }
+ }
+ }
+
+ JAR_find_end(ctx);
+
+ return retval;
+}
+
+/************************************************************************
+ *
+ * J a r W h o
+ */
+int
+JarWho(char *filename)
+{
+ FILE *fp;
+
+ JAR *jar;
+ JAR_Context *ctx;
+
+ int status;
+ int retval = 0;
+
+ JAR_Item *it;
+ JAR_Cert *fing;
+
+ CERTCertificate *cert, *prev = NULL;
+
+ jar = JAR_new();
+
+ if ((fp = fopen(filename, "r")) == NULL) {
+ perror(filename);
+ exit(ERRX);
+ }
+ fclose(fp);
+
+ status = JAR_pass_archive(jar, jarArchGuess, filename, "some-url");
+
+ if (status < 0 || jar->valid < 0) {
+ PR_fprintf(outputFD,
+ "NOTE -- \"%s\" archive DID NOT PASS crypto verification.\n",
+ filename);
+ retval = -1;
+ if (jar->valid < 0 || status != -1) {
+ const char *errtext;
+
+ if (status >= JAR_BASE && status <= JAR_BASE_END) {
+ errtext = JAR_get_error(status);
+ } else {
+ errtext = SECU_Strerror(PORT_GetError());
+ }
+
+ PR_fprintf(outputFD, " (reported reason: %s)\n\n", errtext);
+ }
+ }
+
+ PR_fprintf(outputFD, "\nSigner information:\n\n");
+
+ ctx = JAR_find(jar, NULL, jarTypeSign);
+
+ while (JAR_find_next(ctx, &it) >= 0) {
+ fing = (JAR_Cert *)it->data;
+ cert = fing->cert;
+
+ if (cert) {
+ if (prev == cert)
+ break;
+
+ if (cert->nickname)
+ PR_fprintf(outputFD, "nickname: %s\n", cert->nickname);
+ if (cert->subjectName)
+ PR_fprintf(outputFD, "subject name: %s\n",
+ cert->subjectName);
+ if (cert->issuerName)
+ PR_fprintf(outputFD, "issuer name: %s\n", cert->issuerName);
+ } else {
+ PR_fprintf(outputFD, "no certificate could be found\n");
+ retval = -1;
+ }
+
+ prev = cert;
+ }
+
+ JAR_find_end(ctx);
+
+ JAR_destroy(jar);
+ return retval;
+}
+
+/************************************************************************
+ * j a r _ c b
+ */
+static int
+jar_cb(int status, JAR *jar, const char *metafile,
+ char *pathname, char *errortext)
+{
+ PR_fprintf(errorFD, "error %d: %s IN FILE %s\n", status, errortext,
+ pathname);
+ errorCount++;
+ return 0;
+}
diff --git a/security/nss/cmd/signtool/zip.c b/security/nss/cmd/signtool/zip.c
new file mode 100644
index 000000000..35d5f5733
--- /dev/null
+++ b/security/nss/cmd/signtool/zip.c
@@ -0,0 +1,676 @@
+/* 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/. */
+
+#include "signtool.h"
+#include "zip.h"
+#include "zlib.h"
+#include "prmem.h"
+
+static void inttox(int in, char *out);
+static void longtox(long in, char *out);
+
+/****************************************************************
+ *
+ * J z i p O p e n
+ *
+ * Opens a new ZIP file and creates a new ZIPfile structure to
+ * control the process of installing files into a zip.
+ */
+ZIPfile *
+JzipOpen(char *filename, char *comment)
+{
+ ZIPfile *zipfile;
+ PRExplodedTime prtime;
+
+ zipfile = PORT_ZAlloc(sizeof(ZIPfile));
+ if (!zipfile)
+ out_of_memory();
+
+ /* Construct time and date */
+ PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &prtime);
+ zipfile->date = ((prtime.tm_year - 1980) << 9) |
+ ((prtime.tm_month + 1) << 5) |
+ prtime.tm_mday;
+ zipfile->time = (prtime.tm_hour << 11) |
+ (prtime.tm_min << 5) |
+ (prtime.tm_sec & 0x3f);
+
+ zipfile->fp = NULL;
+ if (filename &&
+ (zipfile->fp = PR_Open(filename,
+ PR_WRONLY |
+ PR_CREATE_FILE |
+ PR_TRUNCATE,
+ 0777)) == NULL) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "%s: can't open output jar, %s.%s\n",
+ PROGRAM_NAME,
+ filename, nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ zipfile->list = NULL;
+ if (filename) {
+ zipfile->filename = PORT_ZAlloc(strlen(filename) + 1);
+ if (!zipfile->filename)
+ out_of_memory();
+ PORT_Strcpy(zipfile->filename, filename);
+ }
+ if (comment) {
+ zipfile->comment = PORT_ZAlloc(strlen(comment) + 1);
+ if (!zipfile->comment)
+ out_of_memory();
+ PORT_Strcpy(zipfile->comment, comment);
+ }
+
+ return zipfile;
+}
+
+static void *
+my_alloc_func(void *opaque, uInt items, uInt size)
+{
+ return PORT_Alloc(items * size);
+}
+
+static void
+my_free_func(void *opaque, void *address)
+{
+ PORT_Free(address);
+}
+
+static void
+handle_zerror(int err, char *msg)
+{
+ if (!msg) {
+ msg = "";
+ }
+
+ errorCount++; /* unless Z_OK...see below */
+
+ switch (err) {
+ case Z_OK:
+ PR_fprintf(errorFD, "No error: %s\n", msg);
+ errorCount--; /* this was incremented above */
+ break;
+ case Z_MEM_ERROR:
+ PR_fprintf(errorFD, "Deflation ran out of memory: %s\n", msg);
+ break;
+ case Z_STREAM_ERROR:
+ PR_fprintf(errorFD, "Invalid compression level: %s\n", msg);
+ break;
+ case Z_VERSION_ERROR:
+ PR_fprintf(errorFD, "Incompatible compression library version: %s\n",
+ msg);
+ break;
+ case Z_DATA_ERROR:
+ PR_fprintf(errorFD, "Compression data error: %s\n", msg);
+ break;
+ default:
+ PR_fprintf(errorFD, "Unknown error in compression library: %s\n", msg);
+ break;
+ }
+}
+
+/****************************************************************
+ *
+ * J z i p A d d
+ *
+ * Adds a new file into a ZIP file. The ZIP file must have already
+ * been opened with JzipOpen.
+ */
+int
+JzipAdd(char *fullname, char *filename, ZIPfile *zipfile, int compression_level)
+{
+ ZIPentry *entry;
+ PRFileDesc *readfp;
+ PRFileDesc *zipfp;
+ unsigned long crc;
+ unsigned long local_size_pos;
+ int num;
+ int err;
+ int deflate_percent;
+ z_stream zstream;
+ Bytef inbuf[BUFSIZ];
+ Bytef outbuf[BUFSIZ];
+
+ if (!fullname || !filename || !zipfile) {
+ return -1;
+ }
+
+ zipfp = zipfile->fp;
+ if (!zipfp)
+ return -1;
+
+ if ((readfp = PR_Open(fullname, PR_RDONLY, 0777)) == NULL) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "%s: %s\n", fullname, nsprErr ? nsprErr : "");
+ errorCount++;
+ if (nsprErr)
+ PR_Free(nsprErr);
+ exit(ERRX);
+ }
+
+ /*
+ * Make sure the input file is not the output file.
+ * Add a few bytes to the end of the JAR file and see if the input file
+ * twitches
+ */
+ {
+ PRInt32 endOfJar;
+ PRInt32 inputSize;
+ PRBool isSame;
+
+ inputSize = PR_Available(readfp);
+
+ endOfJar = PR_Seek(zipfp, 0L, PR_SEEK_CUR);
+
+ if (PR_Write(zipfp, "abcde", 5) < 5) {
+ char *nsprErr;
+
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing to zip file: %s\n",
+ nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ isSame = (PR_Available(readfp) != inputSize);
+
+ PR_Seek(zipfp, endOfJar, PR_SEEK_SET);
+
+ if (isSame) {
+ /* It's the same file! Forget it! */
+ PR_Close(readfp);
+ return 0;
+ }
+ }
+
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "adding %s to %s...", fullname, zipfile->filename);
+ }
+
+ entry = PORT_ZAlloc(sizeof(ZIPentry));
+ if (!entry)
+ out_of_memory();
+
+ entry->filename = PORT_Strdup(filename);
+ entry->comment = NULL;
+
+ /* Set up local file header */
+ longtox(LSIG, entry->local.signature);
+ inttox(strlen(filename), entry->local.filename_len);
+ inttox(zipfile->time, entry->local.time);
+ inttox(zipfile->date, entry->local.date);
+ inttox(Z_DEFLATED, entry->local.method);
+
+ /* Set up central directory entry */
+ longtox(CSIG, entry->central.signature);
+ inttox(strlen(filename), entry->central.filename_len);
+ if (entry->comment) {
+ inttox(strlen(entry->comment), entry->central.commentfield_len);
+ }
+ longtox(PR_Seek(zipfile->fp, 0, PR_SEEK_CUR),
+ entry->central.localhdr_offset);
+ inttox(zipfile->time, entry->central.time);
+ inttox(zipfile->date, entry->central.date);
+ inttox(Z_DEFLATED, entry->central.method);
+
+ /* Compute crc. Too bad we have to process the whole file to do this*/
+ crc = crc32(0L, NULL, 0);
+ while ((num = PR_Read(readfp, inbuf, BUFSIZ)) > 0) {
+ crc = crc32(crc, inbuf, num);
+ }
+ PR_Seek(readfp, 0L, PR_SEEK_SET);
+
+ /* Store CRC */
+ longtox(crc, entry->local.crc32);
+ longtox(crc, entry->central.crc32);
+
+ /* Stick this entry onto the end of the list */
+ entry->next = NULL;
+ if (zipfile->list == NULL) {
+ /* First entry */
+ zipfile->list = entry;
+ } else {
+ ZIPentry *pe;
+
+ pe = zipfile->list;
+ while (pe->next != NULL) {
+ pe = pe->next;
+ }
+ pe->next = entry;
+ }
+
+ /*
+ * Start writing stuff out
+ */
+
+ local_size_pos = PR_Seek(zipfp, 0, PR_SEEK_CUR) + 18;
+ /* File header */
+ if (PR_Write(zipfp, &entry->local, sizeof(struct ZipLocal)) <
+ sizeof(struct ZipLocal)) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ /* File Name */
+ if (PR_Write(zipfp, filename, strlen(filename)) < strlen(filename)) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ /*
+ * File data
+ */
+ /* Initialize zstream */
+ zstream.zalloc = my_alloc_func;
+ zstream.zfree = my_free_func;
+ zstream.opaque = NULL;
+ zstream.next_in = inbuf;
+ zstream.avail_in = BUFSIZ;
+ zstream.next_out = outbuf;
+ zstream.avail_out = BUFSIZ;
+ /* Setting the windowBits to -MAX_WBITS is an undocumented feature of
+ * zlib (see deflate.c in zlib). It is the same thing that Java does
+ * when you specify the nowrap option for deflation in java.util.zip.
+ * It causes zlib to leave out its headers and footers, which don't
+ * work in PKZIP files.
+ */
+ err = deflateInit2(&zstream, compression_level, Z_DEFLATED,
+ -MAX_WBITS, 8 /*default*/, Z_DEFAULT_STRATEGY);
+ if (err != Z_OK) {
+ handle_zerror(err, zstream.msg);
+ exit(ERRX);
+ }
+
+ while ((zstream.avail_in = PR_Read(readfp, inbuf, BUFSIZ)) > 0) {
+ zstream.next_in = inbuf;
+ /* Process this chunk of data */
+ while (zstream.avail_in > 0) {
+ err = deflate(&zstream, Z_NO_FLUSH);
+ if (err != Z_OK) {
+ handle_zerror(err, zstream.msg);
+ exit(ERRX);
+ }
+ if (zstream.avail_out <= 0) {
+ if (PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ zstream.next_out = outbuf;
+ zstream.avail_out = BUFSIZ;
+ }
+ }
+ }
+
+ /* Now flush everything */
+ while (1) {
+ err = deflate(&zstream, Z_FINISH);
+ if (err == Z_STREAM_END) {
+ break;
+ } else if (err == Z_OK) {
+ /* output buffer full, repeat */
+ } else {
+ handle_zerror(err, zstream.msg);
+ exit(ERRX);
+ }
+ if (PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ zstream.avail_out = BUFSIZ;
+ zstream.next_out = outbuf;
+ }
+
+ /* If there's any output left, write it out. */
+ if (zstream.next_out != outbuf) {
+ if (PR_Write(zipfp, outbuf, zstream.next_out - outbuf) <
+ zstream.next_out - outbuf) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ zstream.avail_out = BUFSIZ;
+ zstream.next_out = outbuf;
+ }
+
+ /* Now that we know the compressed size, write this to the headers */
+ longtox(zstream.total_in, entry->local.orglen);
+ longtox(zstream.total_out, entry->local.size);
+ if (PR_Seek(zipfp, local_size_pos, PR_SEEK_SET) == -1) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Accessing zip file: %s\n", nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ if (PR_Write(zipfp, entry->local.size, 8) != 8) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ if (PR_Seek(zipfp, 0L, PR_SEEK_END) == -1) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Accessing zip file: %s\n",
+ nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ longtox(zstream.total_in, entry->central.orglen);
+ longtox(zstream.total_out, entry->central.size);
+
+ /* Close out the deflation operation */
+ err = deflateEnd(&zstream);
+ if (err != Z_OK) {
+ handle_zerror(err, zstream.msg);
+ exit(ERRX);
+ }
+
+ PR_Close(readfp);
+
+ if ((zstream.total_in > zstream.total_out) && (zstream.total_in > 0)) {
+ deflate_percent = (int)((zstream.total_in -
+ zstream.total_out) *
+ 100 / zstream.total_in);
+ } else {
+ deflate_percent = 0;
+ }
+ if (verbosity >= 0) {
+ PR_fprintf(outputFD, "(deflated %d%%)\n", deflate_percent);
+ }
+
+ return 0;
+}
+
+/********************************************************************
+ * J z i p C l o s e
+ *
+ * Finishes the ZipFile. ALSO DELETES THE ZIPFILE STRUCTURE PASSED IN!!
+ */
+int
+JzipClose(ZIPfile *zipfile)
+{
+ ZIPentry *pe, *dead;
+ PRFileDesc *zipfp;
+ struct ZipEnd zipend;
+ unsigned int entrycount = 0;
+
+ if (!zipfile) {
+ return -1;
+ }
+
+ if (!zipfile->filename) {
+ /* bogus */
+ return 0;
+ }
+
+ zipfp = zipfile->fp;
+ zipfile->central_start = PR_Seek(zipfp, 0L, PR_SEEK_CUR);
+
+ /* Write out all the central directories */
+ pe = zipfile->list;
+ while (pe) {
+ entrycount++;
+
+ /* Write central directory info */
+ if (PR_Write(zipfp, &pe->central, sizeof(struct ZipCentral)) <
+ sizeof(struct ZipCentral)) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ /* Write filename */
+ if (PR_Write(zipfp, pe->filename, strlen(pe->filename)) <
+ strlen(pe->filename)) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ /* Write file comment */
+ if (pe->comment) {
+ if (PR_Write(zipfp, pe->comment, strlen(pe->comment)) <
+ strlen(pe->comment)) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ }
+
+ /* Delete the structure */
+ dead = pe;
+ pe = pe->next;
+ if (dead->filename) {
+ PORT_Free(dead->filename);
+ }
+ if (dead->comment) {
+ PORT_Free(dead->comment);
+ }
+ PORT_Free(dead);
+ }
+ zipfile->central_end = PR_Seek(zipfile->fp, 0L, PR_SEEK_CUR);
+
+ /* Create the ZipEnd structure */
+ PORT_Memset(&zipend, 0, sizeof(zipend));
+ longtox(ESIG, zipend.signature);
+ inttox(entrycount, zipend.total_entries_disk);
+ inttox(entrycount, zipend.total_entries_archive);
+ longtox(zipfile->central_end - zipfile->central_start,
+ zipend.central_dir_size);
+ longtox(zipfile->central_start, zipend.offset_central_dir);
+ if (zipfile->comment) {
+ inttox(strlen(zipfile->comment), zipend.commentfield_len);
+ }
+
+ /* Write out ZipEnd xtructure */
+ if (PR_Write(zipfp, &zipend, sizeof(zipend)) < sizeof(zipend)) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ /* Write out Zipfile comment */
+ if (zipfile->comment) {
+ if (PR_Write(zipfp, zipfile->comment, strlen(zipfile->comment)) <
+ strlen(zipfile->comment)) {
+ char *nsprErr;
+ if (PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if (nsprErr)
+ PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ }
+
+ PR_Close(zipfp);
+
+ /* Free the memory of the zipfile structure */
+ if (zipfile->filename) {
+ PORT_Free(zipfile->filename);
+ }
+ if (zipfile->comment) {
+ PORT_Free(zipfile->comment);
+ }
+ PORT_Free(zipfile);
+
+ return 0;
+}
+
+/**********************************************
+ * i n t t o x
+ *
+ * Converts a two byte ugly endianed integer
+ * to our platform's integer.
+ *
+ */
+
+static void
+inttox(int in, char *out)
+{
+ out[0] = (in & 0xFF);
+ out[1] = (in & 0xFF00) >> 8;
+}
+
+/*********************************************
+ * l o n g t o x
+ *
+ * Converts a four byte ugly endianed integer
+ * to our platform's integer.
+ *
+ */
+
+static void
+longtox(long in, char *out)
+{
+ out[0] = (in & 0xFF);
+ out[1] = (in & 0xFF00) >> 8;
+ out[2] = (in & 0xFF0000) >> 16;
+ out[3] = (in & 0xFF000000) >> 24;
+}
diff --git a/security/nss/cmd/signtool/zip.h b/security/nss/cmd/signtool/zip.h
new file mode 100644
index 000000000..1c0076223
--- /dev/null
+++ b/security/nss/cmd/signtool/zip.h
@@ -0,0 +1,69 @@
+/* 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/. */
+
+/* zip.h
+ * Structures and functions for creating ZIP archives.
+ */
+#ifndef ZIP_H
+#define ZIP_H
+
+/* For general information on ZIP formats, you can look at jarfile.h
+ * in ns/security/lib/jar. Or look it up on the web...
+ */
+
+/* One entry in a ZIPfile. This corresponds to one file in the archive.
+ * We have to save this information because first all the files go into
+ * the archive with local headers; then at the end of the file we have to
+ * put the central directory entries for each file.
+ */
+typedef struct ZIPentry_s {
+ struct ZipLocal local; /* local header info */
+ struct ZipCentral central; /* central directory info */
+ char *filename; /* name of file */
+ char *comment; /* comment for this file -- optional */
+
+ struct ZIPentry_s *next;
+} ZIPentry;
+
+/* This structure contains the necessary data for putting a ZIP file
+ * together. Has some overall information and a list of ZIPentrys.
+ */
+typedef struct ZIPfile_s {
+ char *filename; /* ZIP file name */
+ char *comment; /* ZIP file comment -- may be NULL */
+ PRFileDesc *fp; /* ZIP file pointer */
+ ZIPentry *list; /* one entry for each file in the archive */
+ unsigned int time; /* the GMT time of creation, in DOS format */
+ unsigned int date; /* the GMT date of creation, in DOS format */
+ unsigned long central_start; /* starting offset of central directory */
+ unsigned long central_end; /*index right after the last byte of central*/
+} ZIPfile;
+
+/* Open a new ZIP file. Takes the name of the zip file and an optional
+ * comment to be included in the file. Returns a new ZIPfile structure
+ * which is used by JzipAdd and JzipClose
+ */
+ZIPfile *JzipOpen(char *filename, char *comment);
+
+/* Add a file to a ZIP archive. Fullname is the path relative to the
+ * current directory. Filename is what the name will be stored as in the
+ * archive, and thus what it will be restored as. zipfile is a structure
+ * returned from a previous call to JzipOpen.
+ *
+ * Non-zero return code means error (although usually the function will
+ * call exit() rather than return an error--gotta fix this).
+ */
+int JzipAdd(char *fullname, char *filename, ZIPfile *zipfile,
+ int compression_level);
+
+/* Finalize a ZIP archive. Adds all the footer information to the end of
+ * the file and closes it. Also DELETES THE ZIPFILE STRUCTURE that was
+ * passed in. So you never have to allocate or free a ZIPfile yourself.
+ *
+ * Non-zero return code means error (although usually the function will
+ * call exit() rather than return an error--gotta fix this).
+ */
+int JzipClose(ZIPfile *zipfile);
+
+#endif /* ZIP_H */
diff --git a/security/nss/cmd/signver/Makefile b/security/nss/cmd/signver/Makefile
new file mode 100644
index 000000000..fc8358d5a
--- /dev/null
+++ b/security/nss/cmd/signver/Makefile
@@ -0,0 +1,43 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/security/nss/cmd/signver/examples/1/form.pl b/security/nss/cmd/signver/examples/1/form.pl
new file mode 100755
index 000000000..f2cfddc69
--- /dev/null
+++ b/security/nss/cmd/signver/examples/1/form.pl
@@ -0,0 +1,22 @@
+#! /usr/bin/perl
+# 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/.
+
+
+print "Content-type: text/html\n\n";
+print "<B>Server Name:</B> ", $ENV{'SERVER_NAME'}, "<BR>", "\n";
+print "<B>Server Port:</B> ", $ENV{'SERVER_PORT'}, "<BR>", "\n";
+print "<B>Server Software:</B> ", $ENV{'SERVER_SOFTWARE'}, "<BR>", "\n";
+print "<B>Server Protocol:</B> ", $ENV{'SERVER_PROTOCOL'}, "<BR>", "\n";
+print "<B>CGI Revision:</B> ", $ENV{'GATEWAY_INTERFACE'}, "<BR>", "\n";
+print "<B>Browser:</B> ", $ENV{'HTTP_USER_AGENT'}, "<BR>", "\n";
+print "<B>Remote Address:</B> ", $ENV{'REMOTE_ADDR'}, "<BR>", "\n";
+print "<B>Remote Host:</B> ", $ENV{'REMOTE_HOST'}, "<BR>", "\n";
+print "<B>Remote User:</B> ", $ENV{'REMOTE_USER'}, "<BR>", "\n";
+print "You typed:\n";
+
+while( $_ = <STDIN>) {
+ print "$_";
+}
+
diff --git a/security/nss/cmd/signver/examples/1/signedForm.html b/security/nss/cmd/signver/examples/1/signedForm.html
new file mode 100644
index 000000000..ac48e3f1e
--- /dev/null
+++ b/security/nss/cmd/signver/examples/1/signedForm.html
@@ -0,0 +1,55 @@
+<html>
+<!-- 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/. -->
+<head>
+<title>Form to sign</title>
+<script language="javascript">
+<!--
+function submitSigned(form){
+ var signature = "";
+ var dataToSign = "";
+ var i;
+
+ form.action='signedForm.pl';
+ for (i = 0; i < form.length; i++)
+ if (form.elements[i].type == "text")
+ dataToSign += form.elements[i].value;
+
+ // alert("Data to sign:\n" + dataToSign);
+ signature = crypto.signText(dataToSign, "ask");
+ /* alert("You cannot see this alert");
+ alert("Data signature:\n" + signature); */
+
+ if (signature != "error:userCancel") {
+ for (i = 0; i < form.length; i++) {
+ if (form.elements[i].type == "hidden") {
+ if (form.elements[i].name == "dataToSign")
+ form.elements[i].value = dataToSign;
+ if (form.elements[i].name == "dataSignature")
+ form.elements[i].value = signature;
+ }
+ }
+ form.submit();
+ }
+}
+//-->
+</script>
+</head>
+
+<body>
+<form method=post Action="form.pl">
+<input type=hidden size=30 name=dataSignature>
+<input type=hidden size=30 name=dataToSign>
+<input type=text size=30 name=p>
+<BR>
+<input type=text size=30 name=q>
+<BR>
+<input type=text size=30 name=r>
+<BR>
+<input type=submit value="Submit Data">
+<input type=button value="Sign and Submit Data" onclick=submitSigned(this.form)>
+<input type=reset value=Reset>
+</form>
+</body>
+</html>
diff --git a/security/nss/cmd/signver/examples/1/signedForm.nt.html b/security/nss/cmd/signver/examples/1/signedForm.nt.html
new file mode 100644
index 000000000..1a126d2ff
--- /dev/null
+++ b/security/nss/cmd/signver/examples/1/signedForm.nt.html
@@ -0,0 +1,55 @@
+<html>
+<!-- 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/. -->
+<head>
+<title>Form to sign</title>
+<script language="javascript">
+<!--
+function submitSigned(form){
+ var signature = "";
+ var dataToSign = "";
+ var i;
+
+ form.action='cgi-bin/signedForm.pl';
+ for (i = 0; i < form.length; i++)
+ if (form.elements[i].type == "text")
+ dataToSign += form.elements[i].value;
+
+ // alert("Data to sign:\n" + dataToSign);
+ signature = crypto.signText(dataToSign, "ask");
+ /* alert("You cannot see this alert");
+ alert("Data signature:\n" + signature); */
+
+ if (signature != "error:userCancel") {
+ for (i = 0; i < form.length; i++) {
+ if (form.elements[i].type == "hidden") {
+ if (form.elements[i].name == "dataToSign")
+ form.elements[i].value = dataToSign;
+ if (form.elements[i].name == "dataSignature")
+ form.elements[i].value = signature;
+ }
+ }
+ form.submit();
+ }
+}
+//-->
+</script>
+</head>
+
+<body>
+<form method=post Action="cgi-bin/form.pl">
+<input type=hidden size=30 name=dataSignature>
+<input type=hidden size=30 name=dataToSign>
+<input type=text size=30 name=p>
+<BR>
+<input type=text size=30 name=q>
+<BR>
+<input type=text size=30 name=r>
+<BR>
+<input type=submit value="Submit Data">
+<input type=button value="Sign and Submit Data" onclick=submitSigned(this.form)>
+<input type=reset value=Reset>
+</form>
+</body>
+</html>
diff --git a/security/nss/cmd/signver/examples/1/signedForm.pl b/security/nss/cmd/signver/examples/1/signedForm.pl
new file mode 100755
index 000000000..847814c90
--- /dev/null
+++ b/security/nss/cmd/signver/examples/1/signedForm.pl
@@ -0,0 +1,60 @@
+#! /usr/bin/perl
+# 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/.
+
+
+
+sub decode {
+ read (STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
+ @pairs = split(/&/, $buffer);
+ foreach $pair (@pairs)
+ {
+ ($name, $value) = split(/=/, $pair);
+ $value =~tr/+/ /;
+ $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
+ $FORM{$name} = $value;
+# print "name=$name value=$value<BR>\n";
+ }
+}
+
+print "Content-type: text/html\n\n";
+
+&decode();
+
+$dataSignature = $FORM{'dataSignature'};
+$dataToSign = $FORM{'dataToSign'};
+
+unlink("signature");
+open(FILE1,">signature") || die("Cannot open file for writing\n");
+
+print FILE1 "$dataSignature";
+
+close(FILE1);
+
+
+unlink("data");
+open(FILE2,">data") || die("Cannot open file for writing\n");
+
+print FILE2 "$dataToSign";
+
+close(FILE2);
+
+
+print "<BR><B>Signed Data:</B><BR>", "$dataToSign", "<BR>";
+
+print "<BR><b>Verification Info:</b><BR>";
+
+$verInfo = `./signver -D . -s signature -d data -v`;
+print "<font color=red><b>$verInfo</b></font><BR>";
+
+print "<BR><B>Signature Data:</B><BR>", "$dataSignature", "<BR>";
+
+print "<BR><b>Signature Info:</b><BR>";
+
+foreach $line (`./signver -s signature -A`) {
+ print "$line<BR>\n";
+}
+
+print "<b>End of Info</b><BR>";
+
diff --git a/security/nss/cmd/signver/manifest.mn b/security/nss/cmd/signver/manifest.mn
new file mode 100644
index 000000000..7a1de149f
--- /dev/null
+++ b/security/nss/cmd/signver/manifest.mn
@@ -0,0 +1,24 @@
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+CSRCS = signver.c \
+ pk7print.c \
+ $(NULL)
+
+REQUIRES = dbm seccmd
+
+PROGRAM = signver
+
+PACKAGE_FILES = README.txt signedForm.html signedForm.pl form.pl
+ifeq ($(subst /,_,$(shell uname -s)),WINNT)
+PACKAGE_FILES += signedForm.nt.pl signver.exe
+else
+PACKAGE_FILES += signver
+endif
+
+ARCHIVE_NAME = signver
diff --git a/security/nss/cmd/signver/pk7print.c b/security/nss/cmd/signver/pk7print.c
new file mode 100644
index 000000000..deaaaf9e3
--- /dev/null
+++ b/security/nss/cmd/signver/pk7print.c
@@ -0,0 +1,872 @@
+/* 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/. */
+
+/*
+** secutil.c - various functions used by security stuff
+**
+*/
+
+/* pkcs #7 -related functions */
+
+#include "secutil.h"
+#include "secpkcs7.h"
+#include "secoid.h"
+#include <sys/stat.h>
+#include <stdarg.h>
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#endif
+
+/* for SEC_TraverseNames */
+#include "cert.h"
+#include "prtypes.h"
+#include "prtime.h"
+
+#include "prlong.h"
+#include "secmod.h"
+#include "pk11func.h"
+#include "prerror.h"
+
+/*
+** PKCS7 Support
+*/
+
+/* forward declaration */
+int
+sv_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *);
+
+void
+sv_PrintAsHex(FILE *out, SECItem *data, char *m)
+{
+ unsigned i;
+
+ if (m)
+ fprintf(out, "%s", m);
+
+ for (i = 0; i < data->len; i++) {
+ if (i < data->len - 1) {
+ fprintf(out, "%02x:", data->data[i]);
+ } else {
+ fprintf(out, "%02x\n", data->data[i]);
+ break;
+ }
+ }
+}
+
+void
+sv_PrintInteger(FILE *out, SECItem *i, char *m)
+{
+ int iv;
+
+ if (i->len > 4) {
+ sv_PrintAsHex(out, i, m);
+ } else {
+ iv = DER_GetInteger(i);
+ fprintf(out, "%s%d (0x%x)\n", m, iv, iv);
+ }
+}
+
+int
+sv_PrintTime(FILE *out, SECItem *t, char *m)
+{
+ PRExplodedTime printableTime;
+ PRTime time;
+ char *timeString;
+ int rv;
+
+ rv = DER_DecodeTimeChoice(&time, t);
+ if (rv)
+ return rv;
+
+ /* Convert to local time */
+ PR_ExplodeTime(time, PR_LocalTimeParameters, &printableTime);
+
+ timeString = (char *)PORT_Alloc(256);
+
+ if (timeString) {
+ if (PR_FormatTime(timeString, 256, "%a %b %d %H:%M:%S %Y", &printableTime)) {
+ fprintf(out, "%s%s\n", m, timeString);
+ }
+ PORT_Free(timeString);
+ return 0;
+ }
+ return SECFailure;
+}
+
+int
+sv_PrintValidity(FILE *out, CERTValidity *v, char *m)
+{
+ int rv;
+
+ fprintf(out, "%s", m);
+ rv = sv_PrintTime(out, &v->notBefore, "notBefore=");
+ if (rv)
+ return rv;
+ fprintf(out, "%s", m);
+ sv_PrintTime(out, &v->notAfter, "notAfter=");
+ return rv;
+}
+
+void
+sv_PrintObjectID(FILE *out, SECItem *oid, char *m)
+{
+ const char *name;
+ SECOidData *oiddata;
+
+ oiddata = SECOID_FindOID(oid);
+ if (oiddata == NULL) {
+ sv_PrintAsHex(out, oid, m);
+ return;
+ }
+ name = oiddata->desc;
+
+ if (m != NULL)
+ fprintf(out, "%s", m);
+ fprintf(out, "%s\n", name);
+}
+
+void
+sv_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m)
+{
+ sv_PrintObjectID(out, &a->algorithm, m);
+
+ if ((a->parameters.len != 2) ||
+ (PORT_Memcmp(a->parameters.data, "\005\000", 2) != 0)) {
+ /* Print args to algorithm */
+ sv_PrintAsHex(out, &a->parameters, "Args=");
+ }
+}
+
+void
+sv_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m)
+{
+ SECItem *value;
+ int i;
+ char om[100];
+
+ fprintf(out, "%s", m);
+
+ /*
+ * XXX Make this smarter; look at the type field and then decode
+ * and print the value(s) appropriately!
+ */
+ sv_PrintObjectID(out, &(attr->type), "type=");
+ if (attr->values != NULL) {
+ i = 0;
+ while ((value = attr->values[i]) != NULL) {
+ sprintf(om, "%svalue[%d]=%s", m, i++, attr->encoded ? "(encoded)" : "");
+ if (attr->encoded || attr->typeTag == NULL) {
+ sv_PrintAsHex(out, value, om);
+ } else {
+ switch (attr->typeTag->offset) {
+ default:
+ sv_PrintAsHex(out, value, om);
+ break;
+ case SEC_OID_PKCS9_CONTENT_TYPE:
+ sv_PrintObjectID(out, value, om);
+ break;
+ case SEC_OID_PKCS9_SIGNING_TIME:
+ sv_PrintTime(out, value, om);
+ break;
+ }
+ }
+ }
+ }
+}
+
+void
+sv_PrintName(FILE *out, CERTName *name, char *msg)
+{
+ char *str;
+
+ str = CERT_NameToAscii(name);
+ fprintf(out, "%s%s\n", msg, str);
+ PORT_Free(str);
+}
+
+#if 0
+/*
+** secu_PrintPKCS7EncContent
+** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
+*/
+void
+secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
+ char *m, int level)
+{
+ if (src->contentTypeTag == NULL)
+ src->contentTypeTag = SECOID_FindOID(&(src->contentType));
+
+ secu_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ secu_Indent(out, level + 1);
+ fprintf(out, "Content Type: %s\n",
+ (src->contentTypeTag != NULL) ? src->contentTypeTag->desc
+ : "Unknown");
+ sv_PrintAlgorithmID(out, &(src->contentEncAlg),
+ "Content Encryption Algorithm");
+ sv_PrintAsHex(out, &(src->encContent),
+ "Encrypted Content", level+1);
+}
+
+/*
+** secu_PrintRecipientInfo
+** Prints a PKCS7RecipientInfo type
+*/
+void
+secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
+ int level)
+{
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(info->version), "Version");
+
+ sv_PrintName(out, &(info->issuerAndSN->issuer), "Issuer");
+ sv_PrintInteger(out, &(info->issuerAndSN->serialNumber),
+ "Serial Number");
+
+ /* Parse and display encrypted key */
+ sv_PrintAlgorithmID(out, &(info->keyEncAlg),
+ "Key Encryption Algorithm");
+ sv_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1);
+}
+#endif
+
+/*
+** secu_PrintSignerInfo
+** Prints a PKCS7SingerInfo type
+*/
+void
+sv_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m)
+{
+ SEC_PKCS7Attribute *attr;
+ int iv;
+
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &(info->version), "version=");
+
+ fprintf(out, "%s", m);
+ sv_PrintName(out, &(info->issuerAndSN->issuer), "issuerName=");
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &(info->issuerAndSN->serialNumber),
+ "serialNumber=");
+
+ fprintf(out, "%s", m);
+ sv_PrintAlgorithmID(out, &(info->digestAlg), "digestAlgorithm=");
+
+ if (info->authAttr != NULL) {
+ char mm[120];
+
+ iv = 0;
+ while (info->authAttr[iv] != NULL)
+ iv++;
+ fprintf(out, "%sauthenticatedAttributes=%d\n", m, iv);
+ iv = 0;
+ while ((attr = info->authAttr[iv]) != NULL) {
+ sprintf(mm, "%sattribute[%d].", m, iv++);
+ sv_PrintAttribute(out, attr, mm);
+ }
+ }
+
+ /* Parse and display signature */
+ fprintf(out, "%s", m);
+ sv_PrintAlgorithmID(out, &(info->digestEncAlg), "digestEncryptionAlgorithm=");
+ fprintf(out, "%s", m);
+ sv_PrintAsHex(out, &(info->encDigest), "encryptedDigest=");
+
+ if (info->unAuthAttr != NULL) {
+ char mm[120];
+
+ iv = 0;
+ while (info->unAuthAttr[iv] != NULL)
+ iv++;
+ fprintf(out, "%sunauthenticatedAttributes=%d\n", m, iv);
+ iv = 0;
+ while ((attr = info->unAuthAttr[iv]) != NULL) {
+ sprintf(mm, "%sattribute[%d].", m, iv++);
+ sv_PrintAttribute(out, attr, mm);
+ }
+ }
+}
+
+void
+sv_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m)
+{
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &pk->u.rsa.modulus, "modulus=");
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &pk->u.rsa.publicExponent, "exponent=");
+}
+
+void
+sv_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m)
+{
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &pk->u.dsa.params.prime, "prime=");
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &pk->u.dsa.params.subPrime, "subprime=");
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &pk->u.dsa.params.base, "base=");
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &pk->u.dsa.publicValue, "publicValue=");
+}
+
+int
+sv_PrintSubjectPublicKeyInfo(FILE *out, PLArenaPool *arena,
+ CERTSubjectPublicKeyInfo *i, char *msg)
+{
+ SECKEYPublicKey *pk;
+ int rv;
+ char mm[200];
+
+ sprintf(mm, "%s.publicKeyAlgorithm=", msg);
+ sv_PrintAlgorithmID(out, &i->algorithm, mm);
+
+ pk = (SECKEYPublicKey *)PORT_ZAlloc(sizeof(SECKEYPublicKey));
+ if (!pk)
+ return PORT_GetError();
+
+ DER_ConvertBitString(&i->subjectPublicKey);
+ switch (SECOID_FindOIDTag(&i->algorithm.algorithm)) {
+ case SEC_OID_PKCS1_RSA_ENCRYPTION:
+ rv = SEC_ASN1DecodeItem(arena, pk,
+ SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate),
+ &i->subjectPublicKey);
+ if (rv)
+ return rv;
+ sprintf(mm, "%s.rsaPublicKey.", msg);
+ sv_PrintRSAPublicKey(out, pk, mm);
+ break;
+ case SEC_OID_ANSIX9_DSA_SIGNATURE:
+ rv = SEC_ASN1DecodeItem(arena, pk,
+ SEC_ASN1_GET(SECKEY_DSAPublicKeyTemplate),
+ &i->subjectPublicKey);
+ if (rv)
+ return rv;
+ sprintf(mm, "%s.dsaPublicKey.", msg);
+ sv_PrintDSAPublicKey(out, pk, mm);
+ break;
+ default:
+ fprintf(out, "%s=bad SPKI algorithm type\n", msg);
+ return 0;
+ }
+
+ return 0;
+}
+
+SECStatus
+sv_PrintInvalidDateExten(FILE *out, SECItem *value, char *msg)
+{
+ SECItem decodedValue;
+ SECStatus rv;
+ PRTime invalidTime;
+ char *formattedTime = NULL;
+
+ decodedValue.data = NULL;
+ rv = SEC_ASN1DecodeItem(NULL, &decodedValue,
+ SEC_ASN1_GET(SEC_GeneralizedTimeTemplate),
+ value);
+ if (rv == SECSuccess) {
+ rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue);
+ if (rv == SECSuccess) {
+ formattedTime = CERT_GenTime2FormattedAscii(invalidTime, "%a %b %d %H:%M:%S %Y");
+ fprintf(out, "%s: %s\n", msg, formattedTime);
+ PORT_Free(formattedTime);
+ }
+ }
+ PORT_Free(decodedValue.data);
+
+ return (rv);
+}
+
+int
+sv_PrintExtensions(FILE *out, CERTCertExtension **extensions, char *msg)
+{
+ SECOidTag oidTag;
+
+ if (extensions) {
+
+ while (*extensions) {
+ SECItem *tmpitem;
+
+ fprintf(out, "%sname=", msg);
+
+ tmpitem = &(*extensions)->id;
+ sv_PrintObjectID(out, tmpitem, NULL);
+
+ tmpitem = &(*extensions)->critical;
+ if (tmpitem->len)
+ fprintf(out, "%scritical=%s\n", msg,
+ (tmpitem->data && tmpitem->data[0]) ? "True" : "False");
+
+ oidTag = SECOID_FindOIDTag(&((*extensions)->id));
+
+ fprintf(out, "%s", msg);
+ tmpitem = &((*extensions)->value);
+ if (oidTag == SEC_OID_X509_INVALID_DATE)
+ sv_PrintInvalidDateExten(out, tmpitem, "invalidExt");
+ else
+ sv_PrintAsHex(out, tmpitem, "data=");
+
+ /*fprintf(out, "\n");*/
+ extensions++;
+ }
+ }
+
+ return 0;
+}
+
+/* callers of this function must make sure that the CERTSignedCrl
+ from which they are extracting the CERTCrl has been fully-decoded.
+ Otherwise it will not have the entries even though the CRL may have
+ some */
+void
+sv_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m)
+{
+ CERTCrlEntry *entry;
+ int iv;
+ char om[100];
+
+ fprintf(out, "%s", m);
+ sv_PrintAlgorithmID(out, &(crl->signatureAlg), "signatureAlgorithm=");
+ fprintf(out, "%s", m);
+ sv_PrintName(out, &(crl->name), "name=");
+ fprintf(out, "%s", m);
+ sv_PrintTime(out, &(crl->lastUpdate), "lastUpdate=");
+ fprintf(out, "%s", m);
+ sv_PrintTime(out, &(crl->nextUpdate), "nextUpdate=");
+
+ if (crl->entries != NULL) {
+ iv = 0;
+ while ((entry = crl->entries[iv]) != NULL) {
+ fprintf(out, "%sentry[%d].", m, iv);
+ sv_PrintInteger(out, &(entry->serialNumber), "serialNumber=");
+ fprintf(out, "%sentry[%d].", m, iv);
+ sv_PrintTime(out, &(entry->revocationDate), "revocationDate=");
+ sprintf(om, "%sentry[%d].signedCRLEntriesExtensions.", m, iv++);
+ sv_PrintExtensions(out, entry->extensions, om);
+ }
+ }
+ sprintf(om, "%ssignedCRLEntriesExtensions.", m);
+ sv_PrintExtensions(out, crl->extensions, om);
+}
+
+int
+sv_PrintCertificate(FILE *out, SECItem *der, char *m, int level)
+{
+ PLArenaPool *arena = NULL;
+ CERTCertificate *c;
+ int rv;
+ int iv;
+ char mm[200];
+
+ /* Decode certificate */
+ c = (CERTCertificate *)PORT_ZAlloc(sizeof(CERTCertificate));
+ if (!c)
+ return PORT_GetError();
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena)
+ return SEC_ERROR_NO_MEMORY;
+
+ rv = SEC_ASN1DecodeItem(arena, c, SEC_ASN1_GET(CERT_CertificateTemplate),
+ der);
+ if (rv) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+ }
+
+ /* Pretty print it out */
+ iv = DER_GetInteger(&c->version);
+ fprintf(out, "%sversion=%d (0x%x)\n", m, iv + 1, iv);
+ sprintf(mm, "%sserialNumber=", m);
+ sv_PrintInteger(out, &c->serialNumber, mm);
+ sprintf(mm, "%ssignatureAlgorithm=", m);
+ sv_PrintAlgorithmID(out, &c->signature, mm);
+ sprintf(mm, "%sissuerName=", m);
+ sv_PrintName(out, &c->issuer, mm);
+ sprintf(mm, "%svalidity.", m);
+ sv_PrintValidity(out, &c->validity, mm);
+ sprintf(mm, "%ssubject=", m);
+ sv_PrintName(out, &c->subject, mm);
+ sprintf(mm, "%ssubjectPublicKeyInfo", m);
+ rv = sv_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo, mm);
+ if (rv) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+ }
+ sprintf(mm, "%ssignedExtensions.", m);
+ sv_PrintExtensions(out, c->extensions, mm);
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return 0;
+}
+
+int
+sv_PrintSignedData(FILE *out, SECItem *der, char *m, SECU_PPFunc inner)
+{
+ PLArenaPool *arena = NULL;
+ CERTSignedData *sd;
+ int rv;
+
+ /* Strip off the signature */
+ sd = (CERTSignedData *)PORT_ZAlloc(sizeof(CERTSignedData));
+ if (!sd)
+ return PORT_GetError();
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena)
+ return SEC_ERROR_NO_MEMORY;
+
+ rv = SEC_ASN1DecodeItem(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate),
+ der);
+ if (rv) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+ }
+
+ /* fprintf(out, "%s:\n", m); */
+ PORT_Strcat(m, "data.");
+
+ rv = (*inner)(out, &sd->data, m, 0);
+ if (rv) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+ }
+
+ m[PORT_Strlen(m) - 5] = 0;
+ fprintf(out, "%s", m);
+ sv_PrintAlgorithmID(out, &sd->signatureAlgorithm, "signatureAlgorithm=");
+ DER_ConvertBitString(&sd->signature);
+ fprintf(out, "%s", m);
+ sv_PrintAsHex(out, &sd->signature, "signature=");
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return 0;
+}
+
+/*
+** secu_PrintPKCS7Signed
+** Pretty print a PKCS7 signed data type (up to version 1).
+*/
+int
+sv_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src)
+{
+ SECAlgorithmID *digAlg; /* digest algorithms */
+ SECItem *aCert; /* certificate */
+ CERTSignedCrl *aCrl; /* certificate revocation list */
+ SEC_PKCS7SignerInfo *sigInfo; /* signer information */
+ int rv, iv;
+ char om[120];
+
+ sv_PrintInteger(out, &(src->version), "pkcs7.version=");
+
+ /* Parse and list digest algorithms (if any) */
+ if (src->digestAlgorithms != NULL) {
+ iv = 0;
+ while (src->digestAlgorithms[iv] != NULL)
+ iv++;
+ fprintf(out, "pkcs7.digestAlgorithmListLength=%d\n", iv);
+ iv = 0;
+ while ((digAlg = src->digestAlgorithms[iv]) != NULL) {
+ sprintf(om, "pkcs7.digestAlgorithm[%d]=", iv++);
+ sv_PrintAlgorithmID(out, digAlg, om);
+ }
+ }
+
+ /* Now for the content */
+ rv = sv_PrintPKCS7ContentInfo(out, &(src->contentInfo),
+ "pkcs7.contentInformation=");
+ if (rv != 0)
+ return rv;
+
+ /* Parse and list certificates (if any) */
+ if (src->rawCerts != NULL) {
+ iv = 0;
+ while (src->rawCerts[iv] != NULL)
+ iv++;
+ fprintf(out, "pkcs7.certificateListLength=%d\n", iv);
+
+ iv = 0;
+ while ((aCert = src->rawCerts[iv]) != NULL) {
+ sprintf(om, "certificate[%d].", iv++);
+ rv = sv_PrintSignedData(out, aCert, om, sv_PrintCertificate);
+ if (rv)
+ return rv;
+ }
+ }
+
+ /* Parse and list CRL's (if any) */
+ if (src->crls != NULL) {
+ iv = 0;
+ while (src->crls[iv] != NULL)
+ iv++;
+ fprintf(out, "pkcs7.signedRevocationLists=%d\n", iv);
+ iv = 0;
+ while ((aCrl = src->crls[iv]) != NULL) {
+ sprintf(om, "signedRevocationList[%d].", iv);
+ fprintf(out, "%s", om);
+ sv_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
+ "signatureAlgorithm=");
+ DER_ConvertBitString(&aCrl->signatureWrap.signature);
+ fprintf(out, "%s", om);
+ sv_PrintAsHex(out, &aCrl->signatureWrap.signature, "signature=");
+ sprintf(om, "certificateRevocationList[%d].", iv);
+ sv_PrintCRLInfo(out, &aCrl->crl, om);
+ iv++;
+ }
+ }
+
+ /* Parse and list signatures (if any) */
+ if (src->signerInfos != NULL) {
+ iv = 0;
+ while (src->signerInfos[iv] != NULL)
+ iv++;
+ fprintf(out, "pkcs7.signerInformationListLength=%d\n", iv);
+ iv = 0;
+ while ((sigInfo = src->signerInfos[iv]) != NULL) {
+ sprintf(om, "signerInformation[%d].", iv++);
+ sv_PrintSignerInfo(out, sigInfo, om);
+ }
+ }
+
+ return 0;
+}
+
+#if 0
+/*
+** secu_PrintPKCS7Enveloped
+** Pretty print a PKCS7 enveloped data type (up to version 1).
+*/
+void
+secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
+ char *m, int level)
+{
+ SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
+ int iv;
+ char om[100];
+
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list recipients (this is not optional) */
+ if (src->recipientInfos != NULL) {
+ secu_Indent(out, level + 1);
+ fprintf(out, "Recipient Information List:\n");
+ iv = 0;
+ while ((recInfo = src->recipientInfos[iv++]) != NULL) {
+ sprintf(om, "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7SignedEnveloped
+** Pretty print a PKCS7 singed and enveloped data type (up to version 1).
+*/
+int
+secu_PrintPKCS7SignedAndEnveloped(FILE *out,
+ SEC_PKCS7SignedAndEnvelopedData *src,
+ char *m, int level)
+{
+ SECAlgorithmID *digAlg; /* pointer for digest algorithms */
+ SECItem *aCert; /* pointer for certificate */
+ CERTSignedCrl *aCrl; /* pointer for certificate revocation list */
+ SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */
+ SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */
+ int rv, iv;
+ char om[100];
+
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list recipients (this is not optional) */
+ if (src->recipientInfos != NULL) {
+ secu_Indent(out, level + 1);
+ fprintf(out, "Recipient Information List:\n");
+ iv = 0;
+ while ((recInfo = src->recipientInfos[iv++]) != NULL) {
+ sprintf(om, "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ /* Parse and list digest algorithms (if any) */
+ if (src->digestAlgorithms != NULL) {
+ secu_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
+ iv = 0;
+ while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
+ sprintf(om, "Digest Algorithm (%x)", iv);
+ sv_PrintAlgorithmID(out, digAlg, om);
+ }
+ }
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+
+ /* Parse and list certificates (if any) */
+ if (src->rawCerts != NULL) {
+ secu_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
+ iv = 0;
+ while ((aCert = src->rawCerts[iv++]) != NULL) {
+ sprintf(om, "Certificate (%x)", iv);
+ rv = SECU_PrintSignedData(out, aCert, om, level + 2,
+ SECU_PrintCertificate);
+ if (rv)
+ return rv;
+ }
+ }
+
+ /* Parse and list CRL's (if any) */
+ if (src->crls != NULL) {
+ secu_Indent(out, level + 1);
+ fprintf(out, "Signed Revocation Lists:\n");
+ iv = 0;
+ while ((aCrl = src->crls[iv++]) != NULL) {
+ sprintf(om, "Signed Revocation List (%x)", iv);
+ secu_Indent(out, level + 2); fprintf(out, "%s:\n", om);
+ sv_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
+ "Signature Algorithm");
+ DER_ConvertBitString(&aCrl->signatureWrap.signature);
+ sv_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
+ level+3);
+ SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
+ level + 3);
+ }
+ }
+
+ /* Parse and list signatures (if any) */
+ if (src->signerInfos != NULL) {
+ secu_Indent(out, level + 1);
+ fprintf(out, "Signer Information List:\n");
+ iv = 0;
+ while ((sigInfo = src->signerInfos[iv++]) != NULL) {
+ sprintf(om, "Signer Information (%x)", iv);
+ secu_PrintSignerInfo(out, sigInfo, om, level + 2);
+ }
+ }
+
+ return 0;
+}
+
+/*
+** secu_PrintPKCS7Encrypted
+** Pretty print a PKCS7 encrypted data type (up to version 1).
+*/
+void
+secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
+ char *m, int level)
+{
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7Digested
+** Pretty print a PKCS7 digested data type (up to version 1).
+*/
+void
+sv_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src)
+{
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ sv_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm");
+ sv_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information",
+ level + 1);
+ sv_PrintAsHex(out, &src->digest, "Digest", level + 1);
+}
+
+#endif
+
+/*
+** secu_PrintPKCS7ContentInfo
+** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
+** appropriate function
+*/
+int
+sv_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src, char *m)
+{
+ const char *desc;
+ SECOidTag kind;
+ int rv;
+
+ if (src->contentTypeTag == NULL)
+ src->contentTypeTag = SECOID_FindOID(&(src->contentType));
+
+ if (src->contentTypeTag == NULL) {
+ desc = "Unknown";
+ kind = SEC_OID_PKCS7_DATA;
+ } else {
+ desc = src->contentTypeTag->desc;
+ kind = src->contentTypeTag->offset;
+ }
+
+ fprintf(out, "%s%s\n", m, desc);
+
+ if (src->content.data == NULL) {
+ fprintf(out, "pkcs7.data=<no content>\n");
+ return 0;
+ }
+
+ rv = 0;
+ switch (kind) {
+ case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
+ rv = sv_PrintPKCS7Signed(out, src->content.signedData);
+ break;
+
+ case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
+ fprintf(out, "pkcs7EnvelopedData=<unsupported>\n");
+ /*sv_PrintPKCS7Enveloped(out, src->content.envelopedData);*/
+ break;
+
+ case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
+ fprintf(out, "pkcs7SignedEnvelopedData=<unsupported>\n");
+ /*rv = sv_PrintPKCS7SignedAndEnveloped(out,
+ src->content.signedAndEnvelopedData);*/
+ break;
+
+ case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
+ fprintf(out, "pkcs7DigestedData=<unsupported>\n");
+ /*sv_PrintPKCS7Digested(out, src->content.digestedData);*/
+ break;
+
+ case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
+ fprintf(out, "pkcs7EncryptedData=<unsupported>\n");
+ /*sv_PrintPKCS7Encrypted(out, src->content.encryptedData);*/
+ break;
+
+ default:
+ fprintf(out, "pkcs7UnknownData=<unsupported>\n");
+ /*sv_PrintAsHex(out, src->content.data);*/
+ break;
+ }
+
+ return rv;
+}
+
+int
+SV_PrintPKCS7ContentInfo(FILE *out, SECItem *der)
+{
+ SEC_PKCS7ContentInfo *cinfo;
+ int rv = -1;
+
+ cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ if (cinfo != NULL) {
+ rv = sv_PrintPKCS7ContentInfo(out, cinfo, "pkcs7.contentInfo=");
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ }
+
+ return rv;
+}
+/*
+** End of PKCS7 functions
+*/
diff --git a/security/nss/cmd/signver/signver.c b/security/nss/cmd/signver/signver.c
new file mode 100644
index 000000000..4e89e9d0e
--- /dev/null
+++ b/security/nss/cmd/signver/signver.c
@@ -0,0 +1,315 @@
+/* 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/. */
+
+#include "secutil.h"
+#include "secmod.h"
+#include "cert.h"
+#include "secoid.h"
+#include "nss.h"
+
+/* NSPR 2.0 header files */
+#include "prinit.h"
+#include "prprf.h"
+#include "prsystem.h"
+#include "prmem.h"
+/* Portable layer header files */
+#include "plstr.h"
+#include "sechash.h" /* for HASH_GetHashObject() */
+
+static PRBool debugInfo;
+static PRBool verbose;
+static PRBool doVerify;
+static PRBool displayAll;
+
+static const char *const usageInfo[] = {
+ "signver - verify a detached PKCS7 signature - Version " NSS_VERSION,
+ "Commands:",
+ " -A display all information from pkcs #7",
+ " -V verify the signed object and display result",
+ "Options:",
+ " -a signature file is ASCII",
+ " -d certdir directory containing cert database",
+ " -i dataFileName input file containing signed data (default stdin)",
+ " -o outputFileName output file name, default stdout",
+ " -s signatureFileName input file for signature (default stdin)",
+ " -v display verbose reason for failure"
+};
+static int nUsageInfo = sizeof(usageInfo) / sizeof(char *);
+
+extern int SV_PrintPKCS7ContentInfo(FILE *, SECItem *);
+
+static void
+Usage(char *progName, FILE *outFile)
+{
+ int i;
+ fprintf(outFile, "Usage: %s [ commands ] options\n", progName);
+ for (i = 0; i < nUsageInfo; i++)
+ fprintf(outFile, "%s\n", usageInfo[i]);
+ exit(-1);
+}
+
+static HASH_HashType
+AlgorithmToHashType(SECAlgorithmID *digestAlgorithms)
+{
+ SECOidTag tag = SECOID_GetAlgorithmTag(digestAlgorithms);
+ HASH_HashType hash = HASH_GetHashTypeByOidTag(tag);
+ return hash;
+}
+
+static SECStatus
+DigestContent(SECItem *digest, SECItem *content, HASH_HashType hashType)
+{
+ unsigned int maxLen = digest->len;
+ unsigned int len = HASH_ResultLen(hashType);
+ SECStatus rv;
+
+ if (len > maxLen) {
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ return SECFailure;
+ }
+
+ rv = HASH_HashBuf(hashType, digest->data, content->data, content->len);
+ if (rv == SECSuccess)
+ digest->len = len;
+ return rv;
+}
+
+enum {
+ cmd_DisplayAllPCKS7Info = 0,
+ cmd_VerifySignedObj
+};
+
+enum {
+ opt_ASCII,
+ opt_CertDir,
+ opt_InputDataFile,
+ opt_OutputFile,
+ opt_InputSigFile,
+ opt_PrintWhyFailure,
+ opt_DebugInfo
+};
+
+static secuCommandFlag signver_commands[] =
+ {
+ { /* cmd_DisplayAllPCKS7Info*/ 'A', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_VerifySignedObj */ 'V', PR_FALSE, 0, PR_FALSE }
+ };
+
+static secuCommandFlag signver_options[] =
+ {
+ { /* opt_ASCII */ 'a', PR_FALSE, 0, PR_FALSE },
+ { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_InputDataFile */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_OutputFile */ 'o', PR_TRUE, 0, PR_FALSE },
+ { /* opt_InputSigFile */ 's', PR_TRUE, 0, PR_FALSE },
+ { /* opt_PrintWhyFailure */ 'v', PR_FALSE, 0, PR_FALSE },
+ { /* opt_DebugInfo */ 0, PR_FALSE, 0, PR_FALSE, "debug" }
+ };
+
+int
+main(int argc, char **argv)
+{
+ PRFileDesc *contentFile = NULL;
+ PRFileDesc *signFile = PR_STDIN;
+ FILE *outFile = stdout;
+ char *progName;
+ SECStatus rv;
+ int result = 1;
+ SECItem pkcs7der, content;
+ secuCommand signver;
+
+ pkcs7der.data = NULL;
+ content.data = NULL;
+
+ signver.numCommands = sizeof(signver_commands) / sizeof(secuCommandFlag);
+ signver.numOptions = sizeof(signver_options) / sizeof(secuCommandFlag);
+ signver.commands = signver_commands;
+ signver.options = signver_options;
+
+#ifdef XP_PC
+ progName = strrchr(argv[0], '\\');
+#else
+ progName = strrchr(argv[0], '/');
+#endif
+ progName = progName ? progName + 1 : argv[0];
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &signver);
+ if (SECSuccess != rv) {
+ Usage(progName, outFile);
+ }
+ debugInfo = signver.options[opt_DebugInfo].activated;
+ verbose = signver.options[opt_PrintWhyFailure].activated;
+ doVerify = signver.commands[cmd_VerifySignedObj].activated;
+ displayAll = signver.commands[cmd_DisplayAllPCKS7Info].activated;
+ if (!doVerify && !displayAll)
+ doVerify = PR_TRUE;
+
+ /* Set the certdb directory (default is ~/.netscape) */
+ rv = NSS_Init(SECU_ConfigDirectory(signver.options[opt_CertDir].arg));
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return result;
+ }
+ /* below here, goto cleanup */
+ SECU_RegisterDynamicOids();
+
+ /* Open the input content file. */
+ if (signver.options[opt_InputDataFile].activated &&
+ signver.options[opt_InputDataFile].arg) {
+ if (PL_strcmp("-", signver.options[opt_InputDataFile].arg)) {
+ contentFile = PR_Open(signver.options[opt_InputDataFile].arg,
+ PR_RDONLY, 0);
+ if (!contentFile) {
+ PR_fprintf(PR_STDERR,
+ "%s: unable to open \"%s\" for reading.\n",
+ progName, signver.options[opt_InputDataFile].arg);
+ goto cleanup;
+ }
+ } else
+ contentFile = PR_STDIN;
+ }
+
+ /* Open the input signature file. */
+ if (signver.options[opt_InputSigFile].activated &&
+ signver.options[opt_InputSigFile].arg) {
+ if (PL_strcmp("-", signver.options[opt_InputSigFile].arg)) {
+ signFile = PR_Open(signver.options[opt_InputSigFile].arg,
+ PR_RDONLY, 0);
+ if (!signFile) {
+ PR_fprintf(PR_STDERR,
+ "%s: unable to open \"%s\" for reading.\n",
+ progName, signver.options[opt_InputSigFile].arg);
+ goto cleanup;
+ }
+ }
+ }
+
+ if (contentFile == PR_STDIN && signFile == PR_STDIN && doVerify) {
+ PR_fprintf(PR_STDERR,
+ "%s: cannot read both content and signature from standard input\n",
+ progName);
+ goto cleanup;
+ }
+
+ /* Open|Create the output file. */
+ if (signver.options[opt_OutputFile].activated) {
+ outFile = fopen(signver.options[opt_OutputFile].arg, "w");
+ if (!outFile) {
+ PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for writing.\n",
+ progName, signver.options[opt_OutputFile].arg);
+ goto cleanup;
+ }
+ }
+
+ /* read in the input files' contents */
+ rv = SECU_ReadDERFromFile(&pkcs7der, signFile,
+ signver.options[opt_ASCII].activated, PR_FALSE);
+ if (signFile != PR_STDIN)
+ PR_Close(signFile);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "problem reading PKCS7 input");
+ goto cleanup;
+ }
+ if (contentFile) {
+ rv = SECU_FileToItem(&content, contentFile);
+ if (contentFile != PR_STDIN)
+ PR_Close(contentFile);
+ if (rv != SECSuccess)
+ content.data = NULL;
+ }
+
+ /* Signature Verification */
+ if (doVerify) {
+ SEC_PKCS7ContentInfo *cinfo;
+ SEC_PKCS7SignedData *signedData;
+ HASH_HashType digestType;
+ PRBool contentIsSigned;
+
+ cinfo = SEC_PKCS7DecodeItem(&pkcs7der, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if (cinfo == NULL) {
+ PR_fprintf(PR_STDERR, "Unable to decode PKCS7 data\n");
+ goto cleanup;
+ }
+ /* below here, goto done */
+
+ contentIsSigned = SEC_PKCS7ContentIsSigned(cinfo);
+ if (debugInfo) {
+ PR_fprintf(PR_STDERR, "Content is%s encrypted.\n",
+ SEC_PKCS7ContentIsEncrypted(cinfo) ? "" : " not");
+ }
+ if (debugInfo || !contentIsSigned) {
+ PR_fprintf(PR_STDERR, "Content is%s signed.\n",
+ contentIsSigned ? "" : " not");
+ }
+
+ if (!contentIsSigned)
+ goto done;
+
+ signedData = cinfo->content.signedData;
+
+ /* assume that there is only one digest algorithm for now */
+ digestType = AlgorithmToHashType(signedData->digestAlgorithms[0]);
+ if (digestType == HASH_AlgNULL) {
+ PR_fprintf(PR_STDERR, "Invalid hash algorithmID\n");
+ goto done;
+ }
+ if (content.data) {
+ SECCertUsage usage = certUsageEmailSigner;
+ SECItem digest;
+ unsigned char digestBuffer[HASH_LENGTH_MAX];
+
+ if (debugInfo)
+ PR_fprintf(PR_STDERR, "contentToVerify=%s\n", content.data);
+
+ digest.data = digestBuffer;
+ digest.len = sizeof digestBuffer;
+
+ if (DigestContent(&digest, &content, digestType)) {
+ SECU_PrintError(progName, "Message digest computation failure");
+ goto done;
+ }
+
+ if (debugInfo) {
+ unsigned int i;
+ PR_fprintf(PR_STDERR, "Data Digest=:");
+ for (i = 0; i < digest.len; i++)
+ PR_fprintf(PR_STDERR, "%02x:", digest.data[i]);
+ PR_fprintf(PR_STDERR, "\n");
+ }
+
+ fprintf(outFile, "signatureValid=");
+ PORT_SetError(0);
+ if (SEC_PKCS7VerifyDetachedSignature(cinfo, usage,
+ &digest, digestType, PR_FALSE)) {
+ fprintf(outFile, "yes");
+ } else {
+ fprintf(outFile, "no");
+ if (verbose) {
+ fprintf(outFile, ":%s",
+ SECU_Strerror(PORT_GetError()));
+ }
+ }
+ fprintf(outFile, "\n");
+ result = 0;
+ }
+ done:
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ }
+
+ if (displayAll) {
+ if (SV_PrintPKCS7ContentInfo(outFile, &pkcs7der))
+ result = 1;
+ }
+
+cleanup:
+ SECITEM_FreeItem(&pkcs7der, PR_FALSE);
+ SECITEM_FreeItem(&content, PR_FALSE);
+
+ if (NSS_Shutdown() != SECSuccess) {
+ result = 1;
+ }
+
+ return result;
+}
diff --git a/security/nss/cmd/signver/signver.gyp b/security/nss/cmd/signver/signver.gyp
new file mode 100644
index 000000000..9aeb50459
--- /dev/null
+++ b/security/nss/cmd/signver/signver.gyp
@@ -0,0 +1,26 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'signver',
+ 'type': 'executable',
+ 'sources': [
+ 'pk7print.c',
+ 'signver.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/smimetools/Makefile b/security/nss/cmd/smimetools/Makefile
new file mode 100644
index 000000000..74139629f
--- /dev/null
+++ b/security/nss/cmd/smimetools/Makefile
@@ -0,0 +1,49 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+ifdef NISCC_TEST
+DEFINES += -DNISCC_TEST
+endif
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include rules.mk
+
+include ../platrules.mk
diff --git a/security/nss/cmd/smimetools/cmsutil.c b/security/nss/cmd/smimetools/cmsutil.c
new file mode 100644
index 000000000..f3587d016
--- /dev/null
+++ b/security/nss/cmd/smimetools/cmsutil.c
@@ -0,0 +1,1628 @@
+/* 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/. */
+
+/*
+ * cmsutil -- A command to work with CMS data
+ */
+
+#include "nspr.h"
+#include "secutil.h"
+#include "plgetopt.h"
+#include "secpkcs7.h"
+#include "cert.h"
+#include "certdb.h"
+#include "secoid.h"
+#include "cms.h"
+#include "nss.h"
+#include "smime.h"
+#include "pk11func.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#if defined(_WIN32)
+#include "fcntl.h"
+#include "io.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+char *progName = NULL;
+static int cms_verbose = 0;
+static secuPWData pwdata = { PW_NONE, 0 };
+static PK11PasswordFunc pwcb = NULL;
+static void *pwcb_arg = NULL;
+
+/* XXX stolen from cmsarray.c
+ * nss_CMSArray_Count - count number of elements in array
+ */
+int
+nss_CMSArray_Count(void **array)
+{
+ int n = 0;
+ if (array == NULL)
+ return 0;
+ while (*array++ != NULL)
+ n++;
+ return n;
+}
+
+static SECStatus
+DigestFile(PLArenaPool *poolp, SECItem ***digests, SECItem *input,
+ SECAlgorithmID **algids)
+{
+ NSSCMSDigestContext *digcx;
+ SECStatus rv;
+
+ digcx = NSS_CMSDigestContext_StartMultiple(algids);
+ if (digcx == NULL)
+ return SECFailure;
+
+ NSS_CMSDigestContext_Update(digcx, input->data, input->len);
+
+ rv = NSS_CMSDigestContext_FinishMultiple(digcx, poolp, digests);
+ return rv;
+}
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-C|-D|-E|-O|-S] [<options>] [-d dbdir] [-u certusage]\n"
+ " -C create a CMS encrypted data message\n"
+ " -D decode a CMS message\n"
+ " -b decode a batch of files named in infile\n"
+ " -c content use this detached content\n"
+ " -n suppress output of content\n"
+ " -h num display num levels of CMS message info as email headers\n"
+ " -k keep decoded encryption certs in perm cert db\n"
+ " -E create a CMS enveloped data message\n"
+ " -r id,... create envelope for these recipients,\n"
+ " where id can be a certificate nickname or email address\n"
+ " -S create a CMS signed data message\n"
+ " -G include a signing time attribute\n"
+ " -H hash use hash (default:SHA1)\n"
+ " -N nick use certificate named \"nick\" for signing\n"
+ " -P include a SMIMECapabilities attribute\n"
+ " -T do not include content in CMS message\n"
+ " -Y nick include a EncryptionKeyPreference attribute with cert\n"
+ " (use \"NONE\" to omit)\n"
+ " -O create a CMS signed message containing only certificates\n"
+ " General Options:\n"
+ " -d dbdir key/cert database directory (default: ~/.netscape)\n"
+ " -e envelope enveloped data message in this file is used for bulk key\n"
+ " -i infile use infile as source of data (default: stdin)\n"
+ " -o outfile use outfile as destination of data (default: stdout)\n"
+ " -p password use password as key db password (default: prompt)\n"
+ " -f pwfile use password file to set password on all PKCS#11 tokens)\n"
+ " -u certusage set type of certificate usage (default: certUsageEmailSigner)\n"
+ " -v print debugging information\n"
+ "\n"
+ "Cert usage codes:\n",
+ progName);
+ fprintf(stderr, "%-25s 0 - certUsageSSLClient\n", " ");
+ fprintf(stderr, "%-25s 1 - certUsageSSLServer\n", " ");
+ fprintf(stderr, "%-25s 2 - certUsageSSLServerWithStepUp\n", " ");
+ fprintf(stderr, "%-25s 3 - certUsageSSLCA\n", " ");
+ fprintf(stderr, "%-25s 4 - certUsageEmailSigner\n", " ");
+ fprintf(stderr, "%-25s 5 - certUsageEmailRecipient\n", " ");
+ fprintf(stderr, "%-25s 6 - certUsageObjectSigner\n", " ");
+ fprintf(stderr, "%-25s 7 - certUsageUserCertImport\n", " ");
+ fprintf(stderr, "%-25s 8 - certUsageVerifyCA\n", " ");
+ fprintf(stderr, "%-25s 9 - certUsageProtectedObjectSigner\n", " ");
+ fprintf(stderr, "%-25s 10 - certUsageStatusResponder\n", " ");
+ fprintf(stderr, "%-25s 11 - certUsageAnyCA\n", " ");
+
+ exit(-1);
+}
+
+struct optionsStr {
+ char *pwfile;
+ char *password;
+ SECCertUsage certUsage;
+ CERTCertDBHandle *certHandle;
+};
+
+struct decodeOptionsStr {
+ struct optionsStr *options;
+ SECItem content;
+ int headerLevel;
+ PRBool suppressContent;
+ NSSCMSGetDecryptKeyCallback dkcb;
+ PK11SymKey *bulkkey;
+ PRBool keepCerts;
+};
+
+struct signOptionsStr {
+ struct optionsStr *options;
+ char *nickname;
+ char *encryptionKeyPreferenceNick;
+ PRBool signingTime;
+ PRBool smimeProfile;
+ PRBool detached;
+ SECOidTag hashAlgTag;
+};
+
+struct envelopeOptionsStr {
+ struct optionsStr *options;
+ char **recipients;
+};
+
+struct certsonlyOptionsStr {
+ struct optionsStr *options;
+ char **recipients;
+};
+
+struct encryptOptionsStr {
+ struct optionsStr *options;
+ char **recipients;
+ NSSCMSMessage *envmsg;
+ SECItem *input;
+ FILE *outfile;
+ PRFileDesc *envFile;
+ PK11SymKey *bulkkey;
+ SECOidTag bulkalgtag;
+ int keysize;
+};
+
+static NSSCMSMessage *
+decode(FILE *out, SECItem *input, const struct decodeOptionsStr *decodeOptions)
+{
+ NSSCMSDecoderContext *dcx;
+ SECStatus rv;
+ NSSCMSMessage *cmsg;
+ int nlevels, i;
+ SECItem sitem = { 0, 0, 0 };
+
+ PORT_SetError(0);
+ dcx = NSS_CMSDecoder_Start(NULL,
+ NULL, NULL, /* content callback */
+ pwcb, pwcb_arg, /* password callback */
+ decodeOptions->dkcb, /* decrypt key callback */
+ decodeOptions->bulkkey);
+ if (dcx == NULL) {
+ fprintf(stderr, "%s: failed to set up message decoder.\n", progName);
+ return NULL;
+ }
+ rv = NSS_CMSDecoder_Update(dcx, (char *)input->data, input->len);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: failed to decode message.\n", progName);
+ NSS_CMSDecoder_Cancel(dcx);
+ return NULL;
+ }
+ cmsg = NSS_CMSDecoder_Finish(dcx);
+ if (cmsg == NULL) {
+ fprintf(stderr, "%s: failed to decode message.\n", progName);
+ return NULL;
+ }
+
+ if (decodeOptions->headerLevel >= 0) {
+ /*fprintf(out, "SMIME: ", decodeOptions->headerLevel, i);*/
+ fprintf(out, "SMIME: ");
+ }
+
+ nlevels = NSS_CMSMessage_ContentLevelCount(cmsg);
+ for (i = 0; i < nlevels; i++) {
+ NSSCMSContentInfo *cinfo;
+ SECOidTag typetag;
+
+ cinfo = NSS_CMSMessage_ContentLevel(cmsg, i);
+ typetag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
+
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "\tlevel=%d.%d; ", decodeOptions->headerLevel, nlevels - i);
+
+ switch (typetag) {
+ case SEC_OID_PKCS7_SIGNED_DATA: {
+ NSSCMSSignedData *sigd = NULL;
+ SECItem **digests;
+ int nsigners;
+ int j;
+
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "type=signedData; ");
+ sigd = (NSSCMSSignedData *)NSS_CMSContentInfo_GetContent(cinfo);
+ if (sigd == NULL) {
+ SECU_PrintError(progName, "signedData component missing");
+ goto loser;
+ }
+
+ /* if we have a content file, but no digests for this signedData */
+ if (decodeOptions->content.data != NULL &&
+ !NSS_CMSSignedData_HasDigests(sigd)) {
+ PLArenaPool *poolp;
+ SECAlgorithmID **digestalgs;
+
+ /* detached content: grab content file */
+ sitem = decodeOptions->content;
+
+ if ((poolp = PORT_NewArena(1024)) == NULL) {
+ fprintf(stderr, "cmsutil: Out of memory.\n");
+ goto loser;
+ }
+ digestalgs = NSS_CMSSignedData_GetDigestAlgs(sigd);
+ if (DigestFile(poolp, &digests, &sitem, digestalgs) !=
+ SECSuccess) {
+ SECU_PrintError(progName,
+ "problem computing message digest");
+ PORT_FreeArena(poolp, PR_FALSE);
+ goto loser;
+ }
+ if (NSS_CMSSignedData_SetDigests(sigd, digestalgs, digests) !=
+ SECSuccess) {
+ SECU_PrintError(progName,
+ "problem setting message digests");
+ PORT_FreeArena(poolp, PR_FALSE);
+ goto loser;
+ }
+ PORT_FreeArena(poolp, PR_FALSE);
+ }
+
+ /* import the certificates */
+ if (NSS_CMSSignedData_ImportCerts(sigd,
+ decodeOptions->options->certHandle,
+ decodeOptions->options->certUsage,
+ decodeOptions->keepCerts) !=
+ SECSuccess) {
+ SECU_PrintError(progName, "cert import failed");
+ goto loser;
+ }
+
+ /* find out about signers */
+ nsigners = NSS_CMSSignedData_SignerInfoCount(sigd);
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "nsigners=%d; ", nsigners);
+ if (nsigners == 0) {
+ /* Might be a cert transport message
+ ** or might be an invalid message, such as a QA test message
+ ** or a message from an attacker.
+ */
+ SECStatus rv;
+ rv = NSS_CMSSignedData_VerifyCertsOnly(sigd,
+ decodeOptions->options->certHandle,
+ decodeOptions->options->certUsage);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "cmsutil: Verify certs-only failed!\n");
+ goto loser;
+ }
+ return cmsg;
+ }
+
+ /* still no digests? */
+ if (!NSS_CMSSignedData_HasDigests(sigd)) {
+ SECU_PrintError(progName, "no message digests");
+ goto loser;
+ }
+
+ for (j = 0; j < nsigners; j++) {
+ const char *svs;
+ NSSCMSSignerInfo *si;
+ NSSCMSVerificationStatus vs;
+ SECStatus bad;
+
+ si = NSS_CMSSignedData_GetSignerInfo(sigd, j);
+ if (decodeOptions->headerLevel >= 0) {
+ char *signercn;
+ static char empty[] = { "" };
+
+ signercn = NSS_CMSSignerInfo_GetSignerCommonName(si);
+ if (signercn == NULL)
+ signercn = empty;
+ fprintf(out, "\n\t\tsigner%d.id=\"%s\"; ", j, signercn);
+ if (signercn != empty)
+ PORT_Free(signercn);
+ }
+ bad = NSS_CMSSignedData_VerifySignerInfo(sigd, j,
+ decodeOptions->options->certHandle,
+ decodeOptions->options->certUsage);
+ vs = NSS_CMSSignerInfo_GetVerificationStatus(si);
+ svs = NSS_CMSUtil_VerificationStatusToString(vs);
+ if (decodeOptions->headerLevel >= 0) {
+ fprintf(out, "signer%d.status=%s; ", j, svs);
+ /* goto loser ? */
+ } else if (bad && out) {
+ fprintf(stderr, "signer %d status = %s\n", j, svs);
+ goto loser;
+ }
+ }
+ } break;
+ case SEC_OID_PKCS7_ENVELOPED_DATA: {
+ NSSCMSEnvelopedData *envd;
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "type=envelopedData; ");
+ envd = (NSSCMSEnvelopedData *)NSS_CMSContentInfo_GetContent(cinfo);
+ if (envd == NULL) {
+ SECU_PrintError(progName, "envelopedData component missing");
+ goto loser;
+ }
+ } break;
+ case SEC_OID_PKCS7_ENCRYPTED_DATA: {
+ NSSCMSEncryptedData *encd;
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "type=encryptedData; ");
+ encd = (NSSCMSEncryptedData *)NSS_CMSContentInfo_GetContent(cinfo);
+ if (encd == NULL) {
+ SECU_PrintError(progName, "encryptedData component missing");
+ goto loser;
+ }
+ } break;
+ case SEC_OID_PKCS7_DATA:
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "type=data; ");
+ break;
+ default:
+ break;
+ }
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "\n");
+ }
+
+ if (!decodeOptions->suppressContent && out) {
+ SECItem *item = (sitem.data ? &sitem
+ : NSS_CMSMessage_GetContent(cmsg));
+ if (item && item->data && item->len) {
+ fwrite(item->data, item->len, 1, out);
+ }
+ }
+ return cmsg;
+
+loser:
+ if (cmsg)
+ NSS_CMSMessage_Destroy(cmsg);
+ return NULL;
+}
+
+/* example of a callback function to use with encoder */
+/*
+static void
+writeout(void *arg, const char *buf, unsigned long len)
+{
+ FILE *f = (FILE *)arg;
+
+ if (f != NULL && buf != NULL)
+ (void)fwrite(buf, len, 1, f);
+}
+*/
+
+static NSSCMSMessage *
+signed_data(struct signOptionsStr *signOptions)
+{
+ NSSCMSMessage *cmsg = NULL;
+ NSSCMSContentInfo *cinfo;
+ NSSCMSSignedData *sigd;
+ NSSCMSSignerInfo *signerinfo;
+ CERTCertificate *cert = NULL, *ekpcert = NULL;
+
+ if (cms_verbose) {
+ fprintf(stderr, "Input to signed_data:\n");
+ if (signOptions->options->password)
+ fprintf(stderr, "password [%s]\n", signOptions->options->password);
+ else if (signOptions->options->pwfile)
+ fprintf(stderr, "password file [%s]\n", signOptions->options->pwfile);
+ else
+ fprintf(stderr, "password [NULL]\n");
+ fprintf(stderr, "certUsage [%d]\n", signOptions->options->certUsage);
+ if (signOptions->options->certHandle)
+ fprintf(stderr, "certdb [%p]\n", signOptions->options->certHandle);
+ else
+ fprintf(stderr, "certdb [NULL]\n");
+ if (signOptions->nickname)
+ fprintf(stderr, "nickname [%s]\n", signOptions->nickname);
+ else
+ fprintf(stderr, "nickname [NULL]\n");
+ }
+ if (signOptions->nickname == NULL) {
+ fprintf(stderr,
+ "ERROR: please indicate the nickname of a certificate to sign with.\n");
+ return NULL;
+ }
+ if ((cert = CERT_FindUserCertByUsage(signOptions->options->certHandle,
+ signOptions->nickname,
+ signOptions->options->certUsage,
+ PR_FALSE,
+ &pwdata)) == NULL) {
+ SECU_PrintError(progName,
+ "the corresponding cert for key \"%s\" does not exist",
+ signOptions->nickname);
+ return NULL;
+ }
+ if (cms_verbose) {
+ fprintf(stderr, "Found certificate for %s\n", signOptions->nickname);
+ }
+ /*
+ * create the message object
+ */
+ cmsg = NSS_CMSMessage_Create(NULL); /* create a message on its own pool */
+ if (cmsg == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS message.\n");
+ return NULL;
+ }
+ /*
+ * build chain of objects: message->signedData->data
+ */
+ if ((sigd = NSS_CMSSignedData_Create(cmsg)) == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS signedData object.\n");
+ goto loser;
+ }
+ cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
+ if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd) !=
+ SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS signedData object.\n");
+ goto loser;
+ }
+ cinfo = NSS_CMSSignedData_GetContentInfo(sigd);
+ /* we're always passing data in and detaching optionally */
+ if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL,
+ signOptions->detached) !=
+ SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS data object.\n");
+ goto loser;
+ }
+ /*
+ * create & attach signer information
+ */
+ signerinfo = NSS_CMSSignerInfo_Create(cmsg, cert, signOptions->hashAlgTag);
+ if (signerinfo == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS signerInfo object.\n");
+ goto loser;
+ }
+ if (cms_verbose) {
+ fprintf(stderr,
+ "Created CMS message, added signed data w/ signerinfo\n");
+ }
+ signerinfo->cmsg->pwfn_arg = pwcb_arg;
+ /* we want the cert chain included for this one */
+ if (NSS_CMSSignerInfo_IncludeCerts(signerinfo, NSSCMSCM_CertChain,
+ signOptions->options->certUsage) !=
+ SECSuccess) {
+ fprintf(stderr, "ERROR: cannot find cert chain.\n");
+ goto loser;
+ }
+ if (cms_verbose) {
+ fprintf(stderr, "imported certificate\n");
+ }
+ if (signOptions->signingTime) {
+ if (NSS_CMSSignerInfo_AddSigningTime(signerinfo, PR_Now()) !=
+ SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add signingTime attribute.\n");
+ goto loser;
+ }
+ }
+ if (signOptions->smimeProfile) {
+ if (NSS_CMSSignerInfo_AddSMIMECaps(signerinfo) != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add SMIMECaps attribute.\n");
+ goto loser;
+ }
+ }
+
+ if (!signOptions->encryptionKeyPreferenceNick) {
+ /* check signing cert for fitness as encryption cert */
+ SECStatus FitForEncrypt = CERT_CheckCertUsage(cert,
+ certUsageEmailRecipient);
+
+ if (SECSuccess == FitForEncrypt) {
+ /* if yes, add signing cert as EncryptionKeyPreference */
+ if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, cert,
+ signOptions->options->certHandle) !=
+ SECSuccess) {
+ fprintf(stderr,
+ "ERROR: cannot add default SMIMEEncKeyPrefs attribute.\n");
+ goto loser;
+ }
+ if (NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs(signerinfo, cert,
+ signOptions->options->certHandle) !=
+ SECSuccess) {
+ fprintf(stderr,
+ "ERROR: cannot add default MS SMIMEEncKeyPrefs attribute.\n");
+ goto loser;
+ }
+ } else {
+ /* this is a dual-key cert case, we need to look for the encryption
+ certificate under the same nickname as the signing cert */
+ /* get the cert, add it to the message */
+ if ((ekpcert = CERT_FindUserCertByUsage(
+ signOptions->options->certHandle,
+ signOptions->nickname,
+ certUsageEmailRecipient,
+ PR_FALSE,
+ &pwdata)) == NULL) {
+ SECU_PrintError(progName,
+ "the corresponding cert for key \"%s\" does not exist",
+ signOptions->encryptionKeyPreferenceNick);
+ goto loser;
+ }
+ if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, ekpcert,
+ signOptions->options->certHandle) !=
+ SECSuccess) {
+ fprintf(stderr,
+ "ERROR: cannot add SMIMEEncKeyPrefs attribute.\n");
+ goto loser;
+ }
+ if (NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs(signerinfo, ekpcert,
+ signOptions->options->certHandle) !=
+ SECSuccess) {
+ fprintf(stderr,
+ "ERROR: cannot add MS SMIMEEncKeyPrefs attribute.\n");
+ goto loser;
+ }
+ if (NSS_CMSSignedData_AddCertificate(sigd, ekpcert) != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add encryption certificate.\n");
+ goto loser;
+ }
+ }
+ } else if (PL_strcmp(signOptions->encryptionKeyPreferenceNick, "NONE") == 0) {
+ /* No action */
+ } else {
+ /* get the cert, add it to the message */
+ if ((ekpcert = CERT_FindUserCertByUsage(
+ signOptions->options->certHandle,
+ signOptions->encryptionKeyPreferenceNick,
+ certUsageEmailRecipient, PR_FALSE, &pwdata)) ==
+ NULL) {
+ SECU_PrintError(progName,
+ "the corresponding cert for key \"%s\" does not exist",
+ signOptions->encryptionKeyPreferenceNick);
+ goto loser;
+ }
+ if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, ekpcert,
+ signOptions->options->certHandle) !=
+ SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add SMIMEEncKeyPrefs attribute.\n");
+ goto loser;
+ }
+ if (NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs(signerinfo, ekpcert,
+ signOptions->options->certHandle) !=
+ SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add MS SMIMEEncKeyPrefs attribute.\n");
+ goto loser;
+ }
+ if (NSS_CMSSignedData_AddCertificate(sigd, ekpcert) != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add encryption certificate.\n");
+ goto loser;
+ }
+ }
+
+ if (NSS_CMSSignedData_AddSignerInfo(sigd, signerinfo) != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add CMS signerInfo object.\n");
+ goto loser;
+ }
+ if (cms_verbose) {
+ fprintf(stderr, "created signed-data message\n");
+ }
+ if (ekpcert) {
+ CERT_DestroyCertificate(ekpcert);
+ }
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+ return cmsg;
+loser:
+ if (ekpcert) {
+ CERT_DestroyCertificate(ekpcert);
+ }
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+ NSS_CMSMessage_Destroy(cmsg);
+ return NULL;
+}
+
+static NSSCMSMessage *
+enveloped_data(struct envelopeOptionsStr *envelopeOptions)
+{
+ NSSCMSMessage *cmsg = NULL;
+ NSSCMSContentInfo *cinfo;
+ NSSCMSEnvelopedData *envd;
+ NSSCMSRecipientInfo *recipientinfo;
+ CERTCertificate **recipientcerts = NULL;
+ CERTCertDBHandle *dbhandle;
+ PLArenaPool *tmppoolp = NULL;
+ SECOidTag bulkalgtag;
+ int keysize, i = 0;
+ int cnt;
+ dbhandle = envelopeOptions->options->certHandle;
+ /* count the recipients */
+ if ((cnt = nss_CMSArray_Count((void **)envelopeOptions->recipients)) == 0) {
+ fprintf(stderr, "ERROR: please name at least one recipient.\n");
+ goto loser;
+ }
+ if ((tmppoolp = PORT_NewArena(1024)) == NULL) {
+ fprintf(stderr, "ERROR: out of memory.\n");
+ goto loser;
+ }
+ /* XXX find the recipient's certs by email address or nickname */
+ if ((recipientcerts =
+ (CERTCertificate **)PORT_ArenaZAlloc(tmppoolp,
+ (cnt + 1) * sizeof(CERTCertificate *))) ==
+ NULL) {
+ fprintf(stderr, "ERROR: out of memory.\n");
+ goto loser;
+ }
+ for (i = 0; envelopeOptions->recipients[i] != NULL; i++) {
+ if ((recipientcerts[i] =
+ CERT_FindCertByNicknameOrEmailAddr(dbhandle,
+ envelopeOptions->recipients[i])) ==
+ NULL) {
+ SECU_PrintError(progName, "cannot find certificate for \"%s\"",
+ envelopeOptions->recipients[i]);
+ i = 0;
+ goto loser;
+ }
+ }
+ recipientcerts[i] = NULL;
+ i = 0;
+ /* find a nice bulk algorithm */
+ if (NSS_SMIMEUtil_FindBulkAlgForRecipients(recipientcerts, &bulkalgtag,
+ &keysize) != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot find common bulk algorithm.\n");
+ goto loser;
+ }
+ /*
+ * create the message object
+ */
+ cmsg = NSS_CMSMessage_Create(NULL); /* create a message on its own pool */
+ if (cmsg == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS message.\n");
+ goto loser;
+ }
+ /*
+ * build chain of objects: message->envelopedData->data
+ */
+ if ((envd = NSS_CMSEnvelopedData_Create(cmsg, bulkalgtag, keysize)) ==
+ NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS envelopedData object.\n");
+ goto loser;
+ }
+ cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
+ if (NSS_CMSContentInfo_SetContent_EnvelopedData(cmsg, cinfo, envd) !=
+ SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS envelopedData object.\n");
+ goto loser;
+ }
+ cinfo = NSS_CMSEnvelopedData_GetContentInfo(envd);
+ /* we're always passing data in, so the content is NULL */
+ if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, PR_FALSE) !=
+ SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS data object.\n");
+ goto loser;
+ }
+ /*
+ * create & attach recipient information
+ */
+ for (i = 0; recipientcerts[i] != NULL; i++) {
+ if ((recipientinfo = NSS_CMSRecipientInfo_Create(cmsg,
+ recipientcerts[i])) ==
+ NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS recipientInfo object.\n");
+ goto loser;
+ }
+ if (NSS_CMSEnvelopedData_AddRecipient(envd, recipientinfo) !=
+ SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add CMS recipientInfo object.\n");
+ goto loser;
+ }
+ CERT_DestroyCertificate(recipientcerts[i]);
+ }
+ if (tmppoolp)
+ PORT_FreeArena(tmppoolp, PR_FALSE);
+ return cmsg;
+loser:
+ if (recipientcerts) {
+ for (; recipientcerts[i] != NULL; i++) {
+ CERT_DestroyCertificate(recipientcerts[i]);
+ }
+ }
+ if (cmsg)
+ NSS_CMSMessage_Destroy(cmsg);
+ if (tmppoolp)
+ PORT_FreeArena(tmppoolp, PR_FALSE);
+ return NULL;
+}
+
+PK11SymKey *
+dkcb(void *arg, SECAlgorithmID *algid)
+{
+ return (PK11SymKey *)arg;
+}
+
+static SECStatus
+get_enc_params(struct encryptOptionsStr *encryptOptions)
+{
+ struct envelopeOptionsStr envelopeOptions;
+ SECStatus rv = SECFailure;
+ NSSCMSMessage *env_cmsg;
+ NSSCMSContentInfo *cinfo;
+ int i, nlevels;
+ /*
+ * construct an enveloped data message to obtain bulk keys
+ */
+ if (encryptOptions->envmsg) {
+ env_cmsg = encryptOptions->envmsg; /* get it from an old message */
+ } else {
+ SECItem dummyOut = { 0, 0, 0 };
+ SECItem dummyIn = { 0, 0, 0 };
+ char str[] = "Hello!";
+ PLArenaPool *tmparena = PORT_NewArena(1024);
+ dummyIn.data = (unsigned char *)str;
+ dummyIn.len = strlen(str);
+ envelopeOptions.options = encryptOptions->options;
+ envelopeOptions.recipients = encryptOptions->recipients;
+ env_cmsg = enveloped_data(&envelopeOptions);
+ NSS_CMSDEREncode(env_cmsg, &dummyIn, &dummyOut, tmparena);
+ PR_Write(encryptOptions->envFile, dummyOut.data, dummyOut.len);
+ PORT_FreeArena(tmparena, PR_FALSE);
+ }
+ /*
+ * get the content info for the enveloped data
+ */
+ nlevels = NSS_CMSMessage_ContentLevelCount(env_cmsg);
+ for (i = 0; i < nlevels; i++) {
+ SECOidTag typetag;
+ cinfo = NSS_CMSMessage_ContentLevel(env_cmsg, i);
+ typetag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
+ if (typetag == SEC_OID_PKCS7_DATA) {
+ /*
+ * get the symmetric key
+ */
+ encryptOptions->bulkalgtag = NSS_CMSContentInfo_GetContentEncAlgTag(cinfo);
+ encryptOptions->keysize = NSS_CMSContentInfo_GetBulkKeySize(cinfo);
+ encryptOptions->bulkkey = NSS_CMSContentInfo_GetBulkKey(cinfo);
+ rv = SECSuccess;
+ break;
+ }
+ }
+ if (i == nlevels) {
+ fprintf(stderr, "%s: could not retrieve enveloped data.", progName);
+ }
+ if (env_cmsg)
+ NSS_CMSMessage_Destroy(env_cmsg);
+ return rv;
+}
+
+static NSSCMSMessage *
+encrypted_data(struct encryptOptionsStr *encryptOptions)
+{
+ SECStatus rv = SECFailure;
+ NSSCMSMessage *cmsg = NULL;
+ NSSCMSContentInfo *cinfo;
+ NSSCMSEncryptedData *encd;
+ NSSCMSEncoderContext *ecx = NULL;
+ PLArenaPool *tmppoolp = NULL;
+ SECItem derOut = { 0, 0, 0 };
+ /* arena for output */
+ tmppoolp = PORT_NewArena(1024);
+ if (!tmppoolp) {
+ fprintf(stderr, "%s: out of memory.\n", progName);
+ return NULL;
+ }
+ /*
+ * create the message object
+ */
+ cmsg = NSS_CMSMessage_Create(NULL);
+ if (cmsg == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS message.\n");
+ goto loser;
+ }
+ /*
+ * build chain of objects: message->encryptedData->data
+ */
+ if ((encd = NSS_CMSEncryptedData_Create(cmsg, encryptOptions->bulkalgtag,
+ encryptOptions->keysize)) ==
+ NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS encryptedData object.\n");
+ goto loser;
+ }
+ cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
+ if (NSS_CMSContentInfo_SetContent_EncryptedData(cmsg, cinfo, encd) !=
+ SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS encryptedData object.\n");
+ goto loser;
+ }
+ cinfo = NSS_CMSEncryptedData_GetContentInfo(encd);
+ /* we're always passing data in, so the content is NULL */
+ if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, PR_FALSE) !=
+ SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS data object.\n");
+ goto loser;
+ }
+ ecx = NSS_CMSEncoder_Start(cmsg, NULL, NULL, &derOut, tmppoolp, NULL, NULL,
+ dkcb, encryptOptions->bulkkey, NULL, NULL);
+ if (!ecx) {
+ fprintf(stderr, "%s: cannot create encoder context.\n", progName);
+ goto loser;
+ }
+ rv = NSS_CMSEncoder_Update(ecx, (char *)encryptOptions->input->data,
+ encryptOptions->input->len);
+ if (rv) {
+ fprintf(stderr, "%s: failed to add data to encoder.\n", progName);
+ goto loser;
+ }
+ rv = NSS_CMSEncoder_Finish(ecx);
+ if (rv) {
+ fprintf(stderr, "%s: failed to encrypt data.\n", progName);
+ goto loser;
+ }
+ fwrite(derOut.data, derOut.len, 1, encryptOptions->outfile);
+ /*
+ if (bulkkey)
+ PK11_FreeSymKey(bulkkey);
+ */
+ if (tmppoolp)
+ PORT_FreeArena(tmppoolp, PR_FALSE);
+ return cmsg;
+loser:
+ /*
+ if (bulkkey)
+ PK11_FreeSymKey(bulkkey);
+ */
+ if (tmppoolp)
+ PORT_FreeArena(tmppoolp, PR_FALSE);
+ if (cmsg)
+ NSS_CMSMessage_Destroy(cmsg);
+ return NULL;
+}
+
+static NSSCMSMessage *
+signed_data_certsonly(struct certsonlyOptionsStr *certsonlyOptions)
+{
+ NSSCMSMessage *cmsg = NULL;
+ NSSCMSContentInfo *cinfo;
+ NSSCMSSignedData *sigd;
+ CERTCertificate **certs = NULL;
+ CERTCertDBHandle *dbhandle;
+ PLArenaPool *tmppoolp = NULL;
+ int i = 0, cnt;
+ dbhandle = certsonlyOptions->options->certHandle;
+ if ((cnt = nss_CMSArray_Count((void **)certsonlyOptions->recipients)) == 0) {
+ fprintf(stderr,
+ "ERROR: please indicate the nickname of a certificate to sign with.\n");
+ goto loser;
+ }
+ if (!(tmppoolp = PORT_NewArena(1024))) {
+ fprintf(stderr, "ERROR: out of memory.\n");
+ goto loser;
+ }
+ if (!(certs = PORT_ArenaZNewArray(tmppoolp, CERTCertificate *, cnt + 1))) {
+ fprintf(stderr, "ERROR: out of memory.\n");
+ goto loser;
+ }
+ for (i = 0; certsonlyOptions->recipients[i] != NULL; i++) {
+ if ((certs[i] =
+ CERT_FindCertByNicknameOrEmailAddr(dbhandle,
+ certsonlyOptions->recipients[i])) ==
+ NULL) {
+ SECU_PrintError(progName, "cannot find certificate for \"%s\"",
+ certsonlyOptions->recipients[i]);
+ i = 0;
+ goto loser;
+ }
+ }
+ certs[i] = NULL;
+ i = 0;
+ /*
+ * create the message object
+ */
+ cmsg = NSS_CMSMessage_Create(NULL);
+ if (cmsg == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS message.\n");
+ goto loser;
+ }
+ /*
+ * build chain of objects: message->signedData->data
+ */
+ if ((sigd = NSS_CMSSignedData_CreateCertsOnly(cmsg, certs[0], PR_TRUE)) ==
+ NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS signedData object.\n");
+ goto loser;
+ }
+ CERT_DestroyCertificate(certs[0]);
+ for (i = 1; i < cnt; i++) {
+ if (NSS_CMSSignedData_AddCertChain(sigd, certs[i])) {
+ fprintf(stderr, "ERROR: cannot add cert chain for \"%s\".\n",
+ certsonlyOptions->recipients[i]);
+ goto loser;
+ }
+ CERT_DestroyCertificate(certs[i]);
+ }
+ cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
+ if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd) !=
+ SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS signedData object.\n");
+ goto loser;
+ }
+ cinfo = NSS_CMSSignedData_GetContentInfo(sigd);
+ if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, PR_FALSE) !=
+ SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS data object.\n");
+ goto loser;
+ }
+ if (tmppoolp)
+ PORT_FreeArena(tmppoolp, PR_FALSE);
+ return cmsg;
+loser:
+ if (certs) {
+ for (; i < cnt; i++) {
+ CERT_DestroyCertificate(certs[i]);
+ }
+ }
+ if (cmsg)
+ NSS_CMSMessage_Destroy(cmsg);
+ if (tmppoolp)
+ PORT_FreeArena(tmppoolp, PR_FALSE);
+ return NULL;
+}
+
+static char *
+pl_fgets(char *buf, int size, PRFileDesc *fd)
+{
+ char *bp = buf;
+ int nb = 0;
+ ;
+
+ while (size > 1) {
+ nb = PR_Read(fd, bp, 1);
+ if (nb < 0) {
+ /* deal with error */
+ return NULL;
+ } else if (nb == 0) {
+ /* deal with EOF */
+ return NULL;
+ } else if (*bp == '\n') {
+ /* deal with EOL */
+ ++bp; /* keep EOL character */
+ break;
+ } else {
+ /* ordinary character */
+ ++bp;
+ --size;
+ }
+ }
+ *bp = '\0';
+ return buf;
+}
+
+typedef enum { UNKNOWN,
+ DECODE,
+ SIGN,
+ ENCRYPT,
+ ENVELOPE,
+ CERTSONLY } Mode;
+
+static int
+doBatchDecode(FILE *outFile, PRFileDesc *batchFile,
+ const struct decodeOptionsStr *decodeOptions)
+{
+ char *str;
+ int exitStatus = 0;
+ char batchLine[512];
+
+ while (NULL != (str = pl_fgets(batchLine, sizeof batchLine, batchFile))) {
+ NSSCMSMessage *cmsg = NULL;
+ PRFileDesc *inFile;
+ int len = strlen(str);
+ SECStatus rv;
+ SECItem input = { 0, 0, 0 };
+ char cc;
+
+ while (len > 0 &&
+ ((cc = str[len - 1]) == '\n' || cc == '\r')) {
+ str[--len] = '\0';
+ }
+ if (!len) /* skip empty line */
+ continue;
+ if (str[0] == '#')
+ continue; /* skip comment line */
+ fprintf(outFile, "========== %s ==========\n", str);
+ inFile = PR_Open(str, PR_RDONLY, 00660);
+ if (inFile == NULL) {
+ fprintf(outFile, "%s: unable to open \"%s\" for reading\n",
+ progName, str);
+ exitStatus = 1;
+ continue;
+ }
+ rv = SECU_FileToItem(&input, inFile);
+ PR_Close(inFile);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to read infile");
+ exitStatus = 1;
+ continue;
+ }
+ cmsg = decode(outFile, &input, decodeOptions);
+ SECITEM_FreeItem(&input, PR_FALSE);
+ if (cmsg)
+ NSS_CMSMessage_Destroy(cmsg);
+ else {
+ SECU_PrintError(progName, "problem decoding");
+ exitStatus = 1;
+ }
+ }
+ return exitStatus;
+}
+
+int
+main(int argc, char **argv)
+{
+ FILE *outFile;
+ NSSCMSMessage *cmsg = NULL;
+ PRFileDesc *inFile;
+ PLOptState *optstate;
+ PLOptStatus status;
+ Mode mode = UNKNOWN;
+ struct decodeOptionsStr decodeOptions = { 0 };
+ struct signOptionsStr signOptions = { 0 };
+ struct envelopeOptionsStr envelopeOptions = { 0 };
+ struct certsonlyOptionsStr certsonlyOptions = { 0 };
+ struct encryptOptionsStr encryptOptions = { 0 };
+ struct optionsStr options = { 0 };
+ int exitstatus;
+ static char *ptrarray[128] = { 0 };
+ int nrecipients = 0;
+ char *str, *tok;
+ char *envFileName;
+ SECItem input = { 0, 0, 0 };
+ SECItem envmsg = { 0, 0, 0 };
+ SECStatus rv;
+ PRFileDesc *contentFile = NULL;
+ PRBool batch = PR_FALSE;
+
+#ifdef NISCC_TEST
+ const char *ev = PR_GetEnvSecure("NSS_DISABLE_ARENA_FREE_LIST");
+ PORT_Assert(ev);
+ ev = PR_GetEnvSecure("NSS_STRICT_SHUTDOWN");
+ PORT_Assert(ev);
+#endif
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName + 1 : argv[0];
+
+ inFile = PR_STDIN;
+ outFile = stdout;
+ envFileName = NULL;
+ mode = UNKNOWN;
+ decodeOptions.content.data = NULL;
+ decodeOptions.content.len = 0;
+ decodeOptions.suppressContent = PR_FALSE;
+ decodeOptions.headerLevel = -1;
+ decodeOptions.keepCerts = PR_FALSE;
+ options.certUsage = certUsageEmailSigner;
+ options.password = NULL;
+ options.pwfile = NULL;
+ signOptions.nickname = NULL;
+ signOptions.detached = PR_FALSE;
+ signOptions.signingTime = PR_FALSE;
+ signOptions.smimeProfile = PR_FALSE;
+ signOptions.encryptionKeyPreferenceNick = NULL;
+ signOptions.hashAlgTag = SEC_OID_SHA1;
+ envelopeOptions.recipients = NULL;
+ encryptOptions.recipients = NULL;
+ encryptOptions.envmsg = NULL;
+ encryptOptions.envFile = NULL;
+ encryptOptions.bulkalgtag = SEC_OID_UNKNOWN;
+ encryptOptions.bulkkey = NULL;
+ encryptOptions.keysize = -1;
+
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv,
+ "CDEGH:N:OPSTY:bc:d:e:f:h:i:kno:p:r:s:u:v");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'C':
+ mode = ENCRYPT;
+ break;
+ case 'D':
+ mode = DECODE;
+ break;
+ case 'E':
+ mode = ENVELOPE;
+ break;
+ case 'G':
+ if (mode != SIGN) {
+ fprintf(stderr,
+ "%s: option -G only supported with option -S.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ signOptions.signingTime = PR_TRUE;
+ break;
+ case 'H':
+ if (mode != SIGN) {
+ fprintf(stderr,
+ "%s: option -H only supported with option -S.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ decodeOptions.suppressContent = PR_TRUE;
+ if (!strcmp(optstate->value, "MD2"))
+ signOptions.hashAlgTag = SEC_OID_MD2;
+ else if (!strcmp(optstate->value, "MD4"))
+ signOptions.hashAlgTag = SEC_OID_MD4;
+ else if (!strcmp(optstate->value, "MD5"))
+ signOptions.hashAlgTag = SEC_OID_MD5;
+ else if (!strcmp(optstate->value, "SHA1"))
+ signOptions.hashAlgTag = SEC_OID_SHA1;
+ else if (!strcmp(optstate->value, "SHA256"))
+ signOptions.hashAlgTag = SEC_OID_SHA256;
+ else if (!strcmp(optstate->value, "SHA384"))
+ signOptions.hashAlgTag = SEC_OID_SHA384;
+ else if (!strcmp(optstate->value, "SHA512"))
+ signOptions.hashAlgTag = SEC_OID_SHA512;
+ else {
+ fprintf(stderr,
+ "%s: -H requires one of MD2,MD4,MD5,SHA1,SHA256,SHA384,SHA512\n",
+ progName);
+ exit(1);
+ }
+ break;
+ case 'N':
+ if (mode != SIGN) {
+ fprintf(stderr,
+ "%s: option -N only supported with option -S.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ signOptions.nickname = PORT_Strdup(optstate->value);
+ break;
+ case 'O':
+ mode = CERTSONLY;
+ break;
+ case 'P':
+ if (mode != SIGN) {
+ fprintf(stderr,
+ "%s: option -P only supported with option -S.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ signOptions.smimeProfile = PR_TRUE;
+ break;
+ case 'S':
+ mode = SIGN;
+ break;
+ case 'T':
+ if (mode != SIGN) {
+ fprintf(stderr,
+ "%s: option -T only supported with option -S.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ signOptions.detached = PR_TRUE;
+ break;
+ case 'Y':
+ if (mode != SIGN) {
+ fprintf(stderr,
+ "%s: option -Y only supported with option -S.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ signOptions.encryptionKeyPreferenceNick = strdup(optstate->value);
+ break;
+
+ case 'b':
+ if (mode != DECODE) {
+ fprintf(stderr,
+ "%s: option -b only supported with option -D.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ batch = PR_TRUE;
+ break;
+
+ case 'c':
+ if (mode != DECODE) {
+ fprintf(stderr,
+ "%s: option -c only supported with option -D.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ contentFile = PR_Open(optstate->value, PR_RDONLY, 006600);
+ if (contentFile == NULL) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading.\n",
+ progName, optstate->value);
+ exit(1);
+ }
+
+ rv = SECU_FileToItem(&decodeOptions.content, contentFile);
+ PR_Close(contentFile);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "problem reading content file");
+ exit(1);
+ }
+ if (!decodeOptions.content.data) {
+ /* file was zero length */
+ decodeOptions.content.data = (unsigned char *)PORT_Strdup("");
+ decodeOptions.content.len = 0;
+ }
+
+ break;
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+ case 'e':
+ envFileName = PORT_Strdup(optstate->value);
+ encryptOptions.envFile = PR_Open(envFileName, PR_RDONLY, 00660);
+ break;
+
+ case 'h':
+ if (mode != DECODE) {
+ fprintf(stderr,
+ "%s: option -h only supported with option -D.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ decodeOptions.headerLevel = atoi(optstate->value);
+ if (decodeOptions.headerLevel < 0) {
+ fprintf(stderr, "option -h cannot have a negative value.\n");
+ exit(1);
+ }
+ break;
+ case 'i':
+ if (!optstate->value) {
+ fprintf(stderr, "-i option requires filename argument\n");
+ exit(1);
+ }
+ inFile = PR_Open(optstate->value, PR_RDONLY, 00660);
+ if (inFile == NULL) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ exit(1);
+ }
+ break;
+
+ case 'k':
+ if (mode != DECODE) {
+ fprintf(stderr,
+ "%s: option -k only supported with option -D.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ decodeOptions.keepCerts = PR_TRUE;
+ break;
+
+ case 'n':
+ if (mode != DECODE) {
+ fprintf(stderr,
+ "%s: option -n only supported with option -D.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ decodeOptions.suppressContent = PR_TRUE;
+ break;
+ case 'o':
+ outFile = fopen(optstate->value, "wb");
+ if (outFile == NULL) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ exit(1);
+ }
+ break;
+ case 'p':
+ if (!optstate->value) {
+ fprintf(stderr, "%s: option -p must have a value.\n", progName);
+ Usage(progName);
+ exit(1);
+ }
+
+ options.password = strdup(optstate->value);
+ break;
+
+ case 'f':
+ if (!optstate->value) {
+ fprintf(stderr, "%s: option -f must have a value.\n", progName);
+ Usage(progName);
+ exit(1);
+ }
+
+ options.pwfile = strdup(optstate->value);
+ break;
+
+ case 'r':
+ if (!optstate->value) {
+ fprintf(stderr, "%s: option -r must have a value.\n", progName);
+ Usage(progName);
+ exit(1);
+ }
+ envelopeOptions.recipients = ptrarray;
+ str = (char *)optstate->value;
+ do {
+ tok = strchr(str, ',');
+ if (tok)
+ *tok = '\0';
+ envelopeOptions.recipients[nrecipients++] = strdup(str);
+ if (tok)
+ str = tok + 1;
+ } while (tok);
+ envelopeOptions.recipients[nrecipients] = NULL;
+ encryptOptions.recipients = envelopeOptions.recipients;
+ certsonlyOptions.recipients = envelopeOptions.recipients;
+ break;
+
+ case 'u': {
+ int usageType;
+
+ usageType = atoi(strdup(optstate->value));
+ if (usageType < certUsageSSLClient || usageType > certUsageAnyCA)
+ return -1;
+ options.certUsage = (SECCertUsage)usageType;
+ break;
+ }
+ case 'v':
+ cms_verbose = 1;
+ break;
+ }
+ }
+ if (status == PL_OPT_BAD)
+ Usage(progName);
+ PL_DestroyOptState(optstate);
+
+ if (mode == UNKNOWN)
+ Usage(progName);
+
+ if (mode != CERTSONLY && !batch) {
+ rv = SECU_FileToItem(&input, inFile);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to read infile");
+ exit(1);
+ }
+ }
+ if (cms_verbose) {
+ fprintf(stderr, "received commands\n");
+ }
+
+ /* Call the NSS initialization routines */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_InitReadWrite(SECU_ConfigDirectory(NULL));
+ if (SECSuccess != rv) {
+ SECU_PrintError(progName, "NSS_Init failed");
+ exit(1);
+ }
+ if (cms_verbose) {
+ fprintf(stderr, "NSS has been initialized.\n");
+ }
+ options.certHandle = CERT_GetDefaultCertDB();
+ if (!options.certHandle) {
+ SECU_PrintError(progName, "No default cert DB");
+ exit(1);
+ }
+ if (cms_verbose) {
+ fprintf(stderr, "Got default certdb\n");
+ }
+ if (options.password) {
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = options.password;
+ }
+ if (options.pwfile) {
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = options.pwfile;
+ }
+ pwcb = SECU_GetModulePassword;
+ pwcb_arg = (void *)&pwdata;
+
+ PK11_SetPasswordFunc(&SECU_GetModulePassword);
+
+#if defined(_WIN32)
+ if (outFile == stdout) {
+ /* If we're going to write binary data to stdout, we must put stdout
+ ** into O_BINARY mode or else outgoing \n's will become \r\n's.
+ */
+ int smrv = _setmode(_fileno(stdout), _O_BINARY);
+ if (smrv == -1) {
+ fprintf(stderr,
+ "%s: Cannot change stdout to binary mode. Use -o option instead.\n",
+ progName);
+ return smrv;
+ }
+ }
+#endif
+
+ exitstatus = 0;
+ switch (mode) {
+ case DECODE: /* -D */
+ decodeOptions.options = &options;
+ if (encryptOptions.envFile) {
+ /* Decoding encrypted-data, so get the bulkkey from an
+ * enveloped-data message.
+ */
+ SECU_FileToItem(&envmsg, encryptOptions.envFile);
+ decodeOptions.options = &options;
+ encryptOptions.envmsg = decode(NULL, &envmsg, &decodeOptions);
+ if (!encryptOptions.envmsg) {
+ SECU_PrintError(progName, "problem decoding env msg");
+ exitstatus = 1;
+ break;
+ }
+ rv = get_enc_params(&encryptOptions);
+ decodeOptions.dkcb = dkcb;
+ decodeOptions.bulkkey = encryptOptions.bulkkey;
+ }
+ if (!batch) {
+ cmsg = decode(outFile, &input, &decodeOptions);
+ if (!cmsg) {
+ SECU_PrintError(progName, "problem decoding");
+ exitstatus = 1;
+ }
+ } else {
+ exitstatus = doBatchDecode(outFile, inFile, &decodeOptions);
+ }
+ break;
+ case SIGN: /* -S */
+ signOptions.options = &options;
+ cmsg = signed_data(&signOptions);
+ if (!cmsg) {
+ SECU_PrintError(progName, "problem signing");
+ exitstatus = 1;
+ }
+ break;
+ case ENCRYPT: /* -C */
+ if (!envFileName) {
+ fprintf(stderr, "%s: you must specify an envelope file with -e.\n",
+ progName);
+ exit(1);
+ }
+ encryptOptions.options = &options;
+ encryptOptions.input = &input;
+ encryptOptions.outfile = outFile;
+ /* decode an enveloped-data message to get the bulkkey (create
+ * a new one if neccessary)
+ */
+ if (!encryptOptions.envFile) {
+ encryptOptions.envFile = PR_Open(envFileName,
+ PR_WRONLY | PR_CREATE_FILE, 00660);
+ if (!encryptOptions.envFile) {
+ fprintf(stderr, "%s: failed to create file %s.\n", progName,
+ envFileName);
+ exit(1);
+ }
+ } else {
+ SECU_FileToItem(&envmsg, encryptOptions.envFile);
+ decodeOptions.options = &options;
+ encryptOptions.envmsg = decode(NULL, &envmsg, &decodeOptions);
+ if (encryptOptions.envmsg == NULL) {
+ SECU_PrintError(progName, "problem decrypting env msg");
+ exitstatus = 1;
+ break;
+ }
+ }
+ rv = get_enc_params(&encryptOptions);
+ /* create the encrypted-data message */
+ cmsg = encrypted_data(&encryptOptions);
+ if (!cmsg) {
+ SECU_PrintError(progName, "problem encrypting");
+ exitstatus = 1;
+ }
+ if (encryptOptions.bulkkey) {
+ PK11_FreeSymKey(encryptOptions.bulkkey);
+ encryptOptions.bulkkey = NULL;
+ }
+ break;
+ case ENVELOPE: /* -E */
+ envelopeOptions.options = &options;
+ cmsg = enveloped_data(&envelopeOptions);
+ if (!cmsg) {
+ SECU_PrintError(progName, "problem enveloping");
+ exitstatus = 1;
+ }
+ break;
+ case CERTSONLY: /* -O */
+ certsonlyOptions.options = &options;
+ cmsg = signed_data_certsonly(&certsonlyOptions);
+ if (!cmsg) {
+ SECU_PrintError(progName, "problem with certs-only");
+ exitstatus = 1;
+ }
+ break;
+ default:
+ fprintf(stderr, "One of options -D, -S or -E must be set.\n");
+ Usage(progName);
+ exitstatus = 1;
+ }
+
+ if (signOptions.nickname) {
+ PORT_Free(signOptions.nickname);
+ }
+
+ if ((mode == SIGN || mode == ENVELOPE || mode == CERTSONLY) &&
+ (!exitstatus)) {
+ PLArenaPool *arena = PORT_NewArena(1024);
+ NSSCMSEncoderContext *ecx;
+ SECItem output = { 0, 0, 0 };
+
+ if (!arena) {
+ fprintf(stderr, "%s: out of memory.\n", progName);
+ exit(1);
+ }
+
+ if (cms_verbose) {
+ fprintf(stderr, "cmsg [%p]\n", cmsg);
+ fprintf(stderr, "arena [%p]\n", arena);
+ if (pwcb_arg && (PW_PLAINTEXT == ((secuPWData *)pwcb_arg)->source))
+ fprintf(stderr, "password [%s]\n",
+ ((secuPWData *)pwcb_arg)->data);
+ else
+ fprintf(stderr, "password [NULL]\n");
+ }
+ ecx = NSS_CMSEncoder_Start(cmsg,
+ NULL, NULL, /* DER output callback */
+ &output, arena, /* destination storage */
+ pwcb, pwcb_arg, /* password callback */
+ NULL, NULL, /* decrypt key callback */
+ NULL, NULL); /* detached digests */
+ if (!ecx) {
+ fprintf(stderr, "%s: cannot create encoder context.\n", progName);
+ exit(1);
+ }
+ if (cms_verbose) {
+ fprintf(stderr, "input len [%d]\n", input.len);
+ {
+ unsigned int j;
+ for (j = 0; j < input.len; j++)
+ fprintf(stderr, "%2x%c", input.data[j], (j > 0 &&
+ j % 35 == 0)
+ ? '\n'
+ : ' ');
+ }
+ }
+ if (input.len > 0) { /* skip if certs-only (or other zero content) */
+ rv = NSS_CMSEncoder_Update(ecx, (char *)input.data, input.len);
+ if (rv) {
+ fprintf(stderr,
+ "%s: failed to add data to encoder.\n", progName);
+ exit(1);
+ }
+ }
+ rv = NSS_CMSEncoder_Finish(ecx);
+ if (rv) {
+ SECU_PrintError(progName, "failed to encode data");
+ exit(1);
+ }
+
+ if (cms_verbose) {
+ fprintf(stderr, "encoding passed\n");
+ }
+ fwrite(output.data, output.len, 1, outFile);
+ if (cms_verbose) {
+ fprintf(stderr, "wrote to file\n");
+ }
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ if (cmsg)
+ NSS_CMSMessage_Destroy(cmsg);
+ if (outFile != stdout)
+ fclose(outFile);
+
+ if (inFile != PR_STDIN) {
+ PR_Close(inFile);
+ }
+ if (envFileName) {
+ PORT_Free(envFileName);
+ }
+ if (encryptOptions.envFile) {
+ PR_Close(encryptOptions.envFile);
+ }
+
+ SECITEM_FreeItem(&decodeOptions.content, PR_FALSE);
+ SECITEM_FreeItem(&envmsg, PR_FALSE);
+ SECITEM_FreeItem(&input, PR_FALSE);
+ if (NSS_Shutdown() != SECSuccess) {
+ SECU_PrintError(progName, "NSS_Shutdown failed");
+ exitstatus = 1;
+ }
+ PR_Cleanup();
+ return exitstatus;
+}
diff --git a/security/nss/cmd/smimetools/manifest.mn b/security/nss/cmd/smimetools/manifest.mn
new file mode 100644
index 000000000..0e20ed77c
--- /dev/null
+++ b/security/nss/cmd/smimetools/manifest.mn
@@ -0,0 +1,17 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+CSRCS = cmsutil.c
+
+MYLIB = $(DIST)/lib/libsmime.a
+
+REQUIRES = seccmd dbm
+
+PROGRAM = cmsutil
+SCRIPTS = smime
diff --git a/security/nss/cmd/smimetools/rules.mk b/security/nss/cmd/smimetools/rules.mk
new file mode 100644
index 000000000..1ed381ef3
--- /dev/null
+++ b/security/nss/cmd/smimetools/rules.mk
@@ -0,0 +1,7 @@
+#
+# 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/.
+
+install::
+ $(INSTALL) -m 755 $(SCRIPTS) $(SOURCE_BIN_DIR)
diff --git a/security/nss/cmd/smimetools/smime b/security/nss/cmd/smimetools/smime
new file mode 100755
index 000000000..634c3fbb4
--- /dev/null
+++ b/security/nss/cmd/smimetools/smime
@@ -0,0 +1,547 @@
+#!/usr/local/bin/perl
+
+# 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/.
+
+#
+# smime.pl - frontend for S/MIME message generation and parsing
+#
+
+use Getopt::Std;
+
+@boundarychars = ( "0" .. "9", "A" .. "F" );
+
+# path to cmsutil
+$cmsutilpath = "cmsutil";
+
+#
+# Thanks to Gisle Aas <gisle@aas.no> for the base64 functions
+# originally taken from MIME-Base64-2.11 at www.cpan.org
+#
+sub encode_base64($)
+{
+ my $res = "";
+ pos($_[0]) = 0; # ensure start at the beginning
+ while ($_[0] =~ /(.{1,45})/gs) {
+ $res .= substr(pack('u', $1), 1); # get rid of length byte after packing
+ chop($res);
+ }
+ $res =~ tr|` -_|AA-Za-z0-9+/|;
+ # fix padding at the end
+ my $padding = (3 - length($_[0]) % 3) % 3;
+ $res =~ s/.{$padding}$/'=' x $padding/e if $padding;
+ # break encoded string into lines of no more than 76 characters each
+ $res =~ s/(.{1,76})/$1\n/g;
+ $res;
+}
+
+sub decode_base64($)
+{
+ local($^W) = 0; # unpack("u",...) gives bogus warning in 5.00[123]
+
+ my $str = shift;
+ my $res = "";
+
+ $str =~ tr|A-Za-z0-9+=/||cd; # remove non-base64 chars
+ if (length($str) % 4) {
+ require Carp;
+ Carp::carp("Length of base64 data not a multiple of 4")
+ }
+ $str =~ s/=+$//; # remove padding
+ $str =~ tr|A-Za-z0-9+/| -_|; # convert to uuencoded format
+ while ($str =~ /(.{1,60})/gs) {
+ my $len = chr(32 + length($1)*3/4); # compute length byte
+ $res .= unpack("u", $len . $1 ); # uudecode
+ }
+ $res;
+}
+
+#
+# parse headers into a hash
+#
+# %headers = parseheaders($headertext);
+#
+sub parseheaders($)
+{
+ my ($headerdata) = @_;
+ my $hdr;
+ my %hdrhash;
+ my $hdrname;
+ my $hdrvalue;
+ my @hdrvalues;
+ my $subhdrname;
+ my $subhdrvalue;
+
+ # the expression in split() correctly handles continuation lines
+ foreach $hdr (split(/\n(?=\S)/, $headerdata)) {
+ $hdr =~ s/\r*\n\s+/ /g; # collapse continuation lines
+ ($hdrname, $hdrvalue) = $hdr =~ m/^(\S+):\s+(.*)$/;
+
+ # ignore non-headers (or should we die horribly?)
+ next unless (defined($hdrname));
+ $hdrname =~ tr/A-Z/a-z/; # lowercase the header name
+ @hdrvalues = split(/\s*;\s*/, $hdrvalue); # split header values (XXXX quoting)
+
+ # there is guaranteed to be at least one value
+ $hdrvalue = shift @hdrvalues;
+ if ($hdrvalue =~ /^\s*\"(.*)\"\s*$/) { # strip quotes if there
+ $hdrvalue = $1;
+ }
+
+ $hdrhash{$hdrname}{MAIN} = $hdrvalue;
+ # print "XXX $hdrname = $hdrvalue\n";
+
+ # deal with additional name-value pairs
+ foreach $hdrvalue (@hdrvalues) {
+ ($subhdrname, $subhdrvalue) = $hdrvalue =~ m/^(\S+)\s*=\s*(.*)$/;
+ # ignore non-name-value pairs (or should we die?)
+ next unless (defined($subhdrname));
+ $subhdrname =~ tr/A-Z/a-z/;
+ if ($subhdrvalue =~ /^\s*\"(.*)\"\s*$/) { # strip quotes if there
+ $subhdrvalue = $1;
+ }
+ $hdrhash{$hdrname}{$subhdrname} = $subhdrvalue;
+ }
+
+ }
+ return %hdrhash;
+}
+
+#
+# encryptentity($entity, $options) - encrypt an S/MIME entity,
+# creating a new application/pkcs7-smime entity
+#
+# entity - string containing entire S/MIME entity to encrypt
+# options - options for cmsutil
+#
+# this will generate and return a new application/pkcs7-smime entity containing
+# the enveloped input entity.
+#
+sub encryptentity($$)
+{
+ my ($entity, $cmsutiloptions) = @_;
+ my $out = "";
+ my $boundary;
+
+ $tmpencfile = "/tmp/encryptentity.$$";
+
+ #
+ # generate a random boundary string
+ #
+ $boundary = "------------ms" . join("", @boundarychars[map{rand @boundarychars }( 1 .. 24 )]);
+
+ #
+ # tell cmsutil to generate a enveloped CMS message using our data
+ #
+ open(CMS, "|$cmsutilpath -E $cmsutiloptions -o $tmpencfile") or die "ERROR: cannot pipe to cmsutil";
+ print CMS $entity;
+ unless (close(CMS)) {
+ print STDERR "ERROR: encryption failed.\n";
+ unlink($tmpsigfile);
+ exit 1;
+ }
+
+ $out = "Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m\n";
+ $out .= "Content-Transfer-Encoding: base64\n";
+ $out .= "Content-Disposition: attachment; filename=smime.p7m\n";
+ $out .= "\n"; # end of entity header
+
+ open (ENC, $tmpencfile) or die "ERROR: cannot find newly generated encrypted content";
+ local($/) = undef; # slurp whole file
+ $out .= encode_base64(<ENC>), "\n"; # entity body is base64-encoded CMS message
+ close(ENC);
+
+ unlink($tmpencfile);
+
+ $out;
+}
+
+#
+# signentity($entity, $options) - sign an S/MIME entity
+#
+# entity - string containing entire S/MIME entity to sign
+# options - options for cmsutil
+#
+# this will generate and return a new multipart/signed entity consisting
+# of the canonicalized original content, plus a signature block.
+#
+sub signentity($$)
+{
+ my ($entity, $cmsutiloptions) = @_;
+ my $out = "";
+ my $boundary;
+
+ $tmpsigfile = "/tmp/signentity.$$";
+
+ #
+ # generate a random boundary string
+ #
+ $boundary = "------------ms" . join("", @boundarychars[map{rand @boundarychars }( 1 .. 24 )]);
+
+ #
+ # tell cmsutil to generate a signed CMS message using the canonicalized data
+ # The signedData has detached content (-T) and includes a signing time attribute (-G)
+ #
+ # if we do not provide a password on the command line, here's where we would be asked for it
+ #
+ open(CMS, "|$cmsutilpath -S -T -G $cmsutiloptions -o $tmpsigfile") or die "ERROR: cannot pipe to cmsutil";
+ print CMS $entity;
+ unless (close(CMS)) {
+ print STDERR "ERROR: signature generation failed.\n";
+ unlink($tmpsigfile);
+ exit 1;
+ }
+
+ open (SIG, $tmpsigfile) or die "ERROR: cannot find newly generated signature";
+
+ #
+ # construct a new multipart/signed MIME entity consisting of the original content and
+ # the signature
+ #
+ # (we assume that cmsutil generates a SHA1 digest)
+ $out .= "Content-Type: multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=sha1; boundary=\"${boundary}\"\n";
+ $out .= "\n"; # end of entity header
+ $out .= "This is a cryptographically signed message in MIME format.\n"; # explanatory comment
+ $out .= "\n--${boundary}\n";
+ $out .= $entity;
+ $out .= "\n--${boundary}\n";
+ $out .= "Content-Type: application/pkcs7-signature; name=smime.p7s\n";
+ $out .= "Content-Transfer-Encoding: base64\n";
+ $out .= "Content-Disposition: attachment; filename=smime.p7s\n";
+ $out .= "Content-Description: S/MIME Cryptographic Signature\n";
+ $out .= "\n"; # end of signature subentity header
+
+ local($/) = undef; # slurp whole file
+ $out .= encode_base64(<SIG>); # append base64-encoded signature
+ $out .= "\n--${boundary}--\n";
+
+ close(SIG);
+ unlink($tmpsigfile);
+
+ $out;
+}
+
+sub usage {
+ print STDERR "usage: smime [options]\n";
+ print STDERR " options:\n";
+ print STDERR " -S nick generate signed message, use certificate named \"nick\"\n";
+ print STDERR " -p passwd use \"passwd\" as security module password\n";
+ print STDERR " -E rec1[,rec2...] generate encrypted message for recipients\n";
+ print STDERR " -D decode a S/MIME message\n";
+ print STDERR " -p passwd use \"passwd\" as security module password\n";
+ print STDERR " (required for decrypting only)\n";
+ print STDERR " -C pathname set pathname of \"cmsutil\"\n";
+ print STDERR " -d directory set directory containing certificate db\n";
+ print STDERR " (default: ~/.netscape)\n";
+ print STDERR "\nWith -S or -E, smime will take a regular RFC822 message or MIME entity\n";
+ print STDERR "on stdin and generate a signed or encrypted S/MIME message with the same\n";
+ print STDERR "headers and content from it. The output can be used as input to a MTA.\n";
+ print STDERR "-D causes smime to strip off all S/MIME layers if possible and output\n";
+ print STDERR "the \"inner\" message.\n";
+}
+
+#
+# start of main procedures
+#
+
+#
+# process command line options
+#
+unless (getopts('S:E:p:d:C:D')) {
+ usage();
+ exit 1;
+}
+
+unless (defined($opt_S) or defined($opt_E) or defined($opt_D)) {
+ print STDERR "ERROR: -S and/or -E, or -D must be specified.\n";
+ usage();
+ exit 1;
+}
+
+$signopts = "";
+$encryptopts = "";
+$decodeopts = "";
+
+# pass -d option along
+if (defined($opt_d)) {
+ $signopts .= "-d \"$opt_d\" ";
+ $encryptopts .= "-d \"$opt_d\" ";
+ $decodeopts .= "-d \"$opt_d\" ";
+}
+
+if (defined($opt_S)) {
+ $signopts .= "-N \"$opt_S\" ";
+}
+
+if (defined($opt_p)) {
+ $signopts .= "-p \"$opt_p\" ";
+ $decodeopts .= "-p \"$opt_p\" ";
+}
+
+if (defined($opt_E)) {
+ @recipients = split(",", $opt_E);
+ $encryptopts .= "-r ";
+ $encryptopts .= join (" -r ", @recipients);
+}
+
+if (defined($opt_C)) {
+ $cmsutilpath = $opt_C;
+}
+
+#
+# split headers into mime entity headers and RFC822 headers
+# The RFC822 headers are preserved and stay on the outer layer of the message
+#
+$rfc822headers = "";
+$mimeheaders = "";
+$mimebody = "";
+$skippedheaders = "";
+while (<STDIN>) {
+ last if (/^$/);
+ if (/^content-\S+: /i) {
+ $lastref = \$mimeheaders;
+ } elsif (/^mime-version: /i) {
+ $lastref = \$skippedheaders; # skip it
+ } elsif (/^\s/) {
+ ;
+ } else {
+ $lastref = \$rfc822headers;
+ }
+ $$lastref .= $_;
+}
+
+#
+# if there are no MIME entity headers, generate some default ones
+#
+if ($mimeheaders eq "") {
+ $mimeheaders .= "Content-Type: text/plain; charset=us-ascii\n";
+ $mimeheaders .= "Content-Transfer-Encoding: 7bit\n";
+}
+
+#
+# slurp in the entity body
+#
+$saveRS = $/;
+$/ = undef;
+$mimebody = <STDIN>;
+$/ = $saveRS;
+chomp($mimebody);
+
+if (defined $opt_D) {
+ #
+ # decode
+ #
+ # possible options would be:
+ # - strip off only one layer
+ # - strip off outer signature (if present)
+ # - just print information about the structure of the message
+ # - strip n layers, then dump DER of CMS message
+
+ $layercounter = 1;
+
+ while (1) {
+ %hdrhash = parseheaders($mimeheaders);
+ unless (exists($hdrhash{"content-type"}{MAIN})) {
+ print STDERR "ERROR: no content type header found in MIME entity\n";
+ last; # no content-type - we're done
+ }
+
+ $contenttype = $hdrhash{"content-type"}{MAIN};
+ if ($contenttype eq "application/pkcs7-mime") {
+ #
+ # opaque-signed or enveloped message
+ #
+ unless (exists($hdrhash{"content-type"}{"smime-type"})) {
+ print STDERR "ERROR: no smime-type attribute in application/pkcs7-smime entity.\n";
+ last;
+ }
+ $smimetype = $hdrhash{"content-type"}{"smime-type"};
+ if ($smimetype eq "signed-data" or $smimetype eq "enveloped-data") {
+ # it's verification or decryption time!
+
+ # can handle only base64 encoding for now
+ # all other encodings are treated as binary (8bit)
+ if ($hdrhash{"content-transfer-encoding"}{MAIN} eq "base64") {
+ $mimebody = decode_base64($mimebody);
+ }
+
+ # if we need to dump the DER, we would do it right here
+
+ # now write the DER
+ $tmpderfile = "/tmp/der.$$";
+ open(TMP, ">$tmpderfile") or die "ERROR: cannot write signature data to temporary file";
+ print TMP $mimebody;
+ unless (close(TMP)) {
+ print STDERR "ERROR: writing signature data to temporary file.\n";
+ unlink($tmpderfile);
+ exit 1;
+ }
+
+ $mimeheaders = "";
+ open(TMP, "$cmsutilpath -D $decodeopts -h $layercounter -i $tmpderfile |") or die "ERROR: cannot open pipe to cmsutil";
+ $layercounter++;
+ while (<TMP>) {
+ last if (/^\r?$/); # empty lines mark end of header
+ if (/^SMIME: /) { # add all SMIME info to the rfc822 hdrs
+ $lastref = \$rfc822headers;
+ } elsif (/^\s/) {
+ ; # continuation lines go to the last dest
+ } else {
+ $lastref = \$mimeheaders; # all other headers are mime headers
+ }
+ $$lastref .= $_;
+ }
+ # slurp in rest of the data to $mimebody
+ $saveRS = $/; $/ = undef; $mimebody = <TMP>; $/ = $saveRS;
+ close(TMP);
+
+ unlink($tmpderfile);
+
+ } else {
+ print STDERR "ERROR: unknown smime-type \"$smimetype\" in application/pkcs7-smime entity.\n";
+ last;
+ }
+ } elsif ($contenttype eq "multipart/signed") {
+ #
+ # clear signed message
+ #
+ unless (exists($hdrhash{"content-type"}{"protocol"})) {
+ print STDERR "ERROR: content type has no protocol attribute in multipart/signed entity.\n";
+ last;
+ }
+ if ($hdrhash{"content-type"}{"protocol"} ne "application/pkcs7-signature") {
+ # we cannot handle this guy
+ print STDERR "ERROR: unknown protocol \"", $hdrhash{"content-type"}{"protocol"},
+ "\" in multipart/signed entity.\n";
+ last;
+ }
+ unless (exists($hdrhash{"content-type"}{"boundary"})) {
+ print STDERR "ERROR: no boundary attribute in multipart/signed entity.\n";
+ last;
+ }
+ $boundary = $hdrhash{"content-type"}{"boundary"};
+
+ # split $mimebody along \n--$boundary\n - gets you four parts
+ # first (0), any comments the sending agent might have put in
+ # second (1), the message itself
+ # third (2), the signature as a mime entity
+ # fourth (3), trailing data (there shouldn't be any)
+
+ @multiparts = split(/\r?\n--$boundary(?:--)?\r?\n/, $mimebody);
+
+ #
+ # parse the signature headers
+ ($submimeheaders, $submimebody) = split(/^$/m, $multiparts[2]);
+ %sighdrhash = parseheaders($submimeheaders);
+ unless (exists($sighdrhash{"content-type"}{MAIN})) {
+ print STDERR "ERROR: signature entity has no content type.\n";
+ last;
+ }
+ if ($sighdrhash{"content-type"}{MAIN} ne "application/pkcs7-signature") {
+ # we cannot handle this guy
+ print STDERR "ERROR: unknown content type \"", $sighdrhash{"content-type"}{MAIN},
+ "\" in signature entity.\n";
+ last;
+ }
+ if ($sighdrhash{"content-transfer-encoding"}{MAIN} eq "base64") {
+ $submimebody = decode_base64($submimebody);
+ }
+
+ # we would dump the DER at this point
+
+ $tmpsigfile = "/tmp/sig.$$";
+ open(TMP, ">$tmpsigfile") or die "ERROR: cannot write signature data to temporary file";
+ print TMP $submimebody;
+ unless (close(TMP)) {
+ print STDERR "ERROR: writing signature data to temporary file.\n";
+ unlink($tmpsigfile);
+ exit 1;
+ }
+
+ $tmpmsgfile = "/tmp/msg.$$";
+ open(TMP, ">$tmpmsgfile") or die "ERROR: cannot write message data to temporary file";
+ print TMP $multiparts[1];
+ unless (close(TMP)) {
+ print STDERR "ERROR: writing message data to temporary file.\n";
+ unlink($tmpsigfile);
+ unlink($tmpmsgfile);
+ exit 1;
+ }
+
+ $mimeheaders = "";
+ open(TMP, "$cmsutilpath -D $decodeopts -h $layercounter -c $tmpmsgfile -i $tmpsigfile |") or die "ERROR: cannot open pipe to cmsutil";
+ $layercounter++;
+ while (<TMP>) {
+ last if (/^\r?$/);
+ if (/^SMIME: /) {
+ $lastref = \$rfc822headers;
+ } elsif (/^\s/) {
+ ;
+ } else {
+ $lastref = \$mimeheaders;
+ }
+ $$lastref .= $_;
+ }
+ $saveRS = $/; $/ = undef; $mimebody = <TMP>; $/ = $saveRS;
+ close(TMP);
+ unlink($tmpsigfile);
+ unlink($tmpmsgfile);
+
+ } else {
+
+ # not a content type we know - we're done
+ last;
+
+ }
+ }
+
+ # so now we have the S/MIME parsing information in rfc822headers
+ # and the first mime entity we could not handle in mimeheaders and mimebody.
+ # dump 'em out and we're done.
+ print $rfc822headers;
+ print $mimeheaders . "\n" . $mimebody;
+
+} else {
+
+ #
+ # encode (which is much easier than decode)
+ #
+
+ $mimeentity = $mimeheaders . "\n" . $mimebody;
+
+ #
+ # canonicalize inner entity (rudimentary yet)
+ # convert single LFs to CRLF
+ # if no Content-Transfer-Encoding header present:
+ # if 8 bit chars present, use Content-Transfer-Encoding: quoted-printable
+ # otherwise, use Content-Transfer-Encoding: 7bit
+ #
+ $mimeentity =~ s/\r*\n/\r\n/mg;
+
+ #
+ # now do the wrapping
+ # we sign first, then encrypt because that's what Communicator needs
+ #
+ if (defined($opt_S)) {
+ $mimeentity = signentity($mimeentity, $signopts);
+ }
+
+ if (defined($opt_E)) {
+ $mimeentity = encryptentity($mimeentity, $encryptopts);
+ }
+
+ #
+ # XXX sign again to do triple wrapping (RFC2634)
+ #
+
+ #
+ # now write out the RFC822 headers
+ # followed by the final $mimeentity
+ #
+ print $rfc822headers;
+ print "MIME-Version: 1.0 (NSS SMIME - http://www.mozilla.org/projects/security)\n"; # set up the flag
+ print $mimeentity;
+}
+
+exit 0;
diff --git a/security/nss/cmd/smimetools/smimetools.gyp b/security/nss/cmd/smimetools/smimetools.gyp
new file mode 100644
index 000000000..13d3679f3
--- /dev/null
+++ b/security/nss/cmd/smimetools/smimetools.gyp
@@ -0,0 +1,25 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'cmsutil',
+ 'type': 'executable',
+ 'sources': [
+ 'cmsutil.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/ssltap/Makefile b/security/nss/cmd/ssltap/Makefile
new file mode 100644
index 000000000..bc7d35df4
--- /dev/null
+++ b/security/nss/cmd/ssltap/Makefile
@@ -0,0 +1,51 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+# Since ssltap doesn't use any of NSS, we'll skip NSS's link libs,
+# and just link with NSPR.
+#
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
+-include ../platrules.mk
+
diff --git a/security/nss/cmd/ssltap/manifest.mn b/security/nss/cmd/ssltap/manifest.mn
new file mode 100644
index 000000000..0c09c17a3
--- /dev/null
+++ b/security/nss/cmd/ssltap/manifest.mn
@@ -0,0 +1,23 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+EXPORTS =
+
+CSRCS = ssltap.c \
+ $(NULL)
+
+PROGRAM = ssltap
+
+REQUIRES = seccmd dbm
+
+PACKAGE_FILES = ssltap-manual.html licence.doc ssltap.exe
+
+ARCHIVE_NAME = ssltap
+
diff --git a/security/nss/cmd/ssltap/ssltap-manual.html b/security/nss/cmd/ssltap/ssltap-manual.html
new file mode 100644
index 000000000..619c93f8c
--- /dev/null
+++ b/security/nss/cmd/ssltap/ssltap-manual.html
@@ -0,0 +1,170 @@
+<HTML>
+<!-- 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/. -->
+<HEAD>
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+ <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (WinNT; U) [Netscape]">
+ <META NAME="Author" CONTENT="Steve Parkinson">
+ <TITLE>SSLTap - manual</TITLE>
+</HEAD>
+<BODY>
+
+<H1>
+SSLTap Manual page</H1>
+
+<H3>
+Summary</H3>
+A command-line proxy which is SSL-aware. It snoops on TCP connections,
+and displays the data going by, including SSL records and handshaking&nbsp;
+if the connection is SSL.
+<H3>
+Synopsis</H3>
+<TT>ssltap [-vhfsxl] [-p port] hostname:port</TT>
+
+<P><TT>&nbsp;&nbsp; -v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [prints version string]</TT>
+<BR><TT>&nbsp;&nbsp; -h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [outputs hex instead
+of ASCII]</TT>
+<BR><TT>&nbsp;&nbsp; -f&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [turn on Fancy HTML
+coloring]</TT>
+<BR><TT>&nbsp;&nbsp; -s&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [turn on SSL decoding]</TT>
+<BR><TT>&nbsp;&nbsp; -x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [turn on extra SSL
+hex dumps]</TT>
+<BR><TT>&nbsp;&nbsp; -p port [specify rendezvous port (default 1924)]</TT>
+<BR><TT>&nbsp;&nbsp; -l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [loop - continue
+to wait for more connections]</TT>
+<H3>
+Description</H3>
+SSLTap opens a socket on a rendezvous port, and waits for an incoming connection
+(client side). Once this connection arrives, SSLTap makes another connection
+to hostname:port (server side). It passes any data sent by the client to
+the server, and vice versa. However, SSLTap will also display the data
+to the console. It can do this for plain HTTP connections, or any TCP protocol.
+However, SSLTap can also work with SSL streams, as detailed below.
+
+<P>Let's assume your development machine is called 'intercept'. The simplest
+usage of SSLTap is to run the command <TT>'ssltap www.netscape.com:80'</TT>
+on intercept. The program will wait for an incoming connection on port
+1924. Next you would want to go to your browser, and enter the URL http://intercept:1924.
+The page retrieved by the browser will actually be gotten from the server
+at www.netscape.com, but will go via SSLTap.
+
+<P>Data sent from the client to the server is surrounded by a '--> [ ]'
+symbol, and data sent from the server to the client, a '&lt;---[&nbsp;
+]' symbol.
+
+<P>You'll notice that the page retrieved with this example looks incomplete.
+This is because SSLTap by default closes down after the first connection
+is complete, so the browser is not able to load images. To make the SSLTap
+continue to accept connections, switch on looping mode with the -l option.
+
+<P>You can change the default rendezvous port to something else with the
+-p option.
+
+<P>The remaining options change the way the output is produced.
+
+<P>The -f option prints 'fancy' output - in colored HTML. Data sent from
+the client to the server is in blue. The server's reply is in red. This
+is designed so you can load the output up into a browser. When used with
+looping mode, the different connections are separated with horizontal lines.
+
+<P>-x will turn on HEX printing. Instead of being output as ascii, the
+data is shown as Hex, like this:
+<UL><TT>&lt;-- [</TT>
+<BR><TT>&nbsp;&nbsp; 0: 56 d5 16 3e&nbsp; a1 6b b1 4a&nbsp; 8f 67 c4 d7&nbsp;
+21 2f 6f dd&nbsp; | V..>.k.J.g..!/o.</TT>
+<BR><TT>&nbsp; 10: bb 22 c4 75&nbsp; 8c f4 ce 28&nbsp; 16 a6 20 aa&nbsp;
+fb 9a 59 a1&nbsp; | .".u...(.. ...Y.</TT>
+<BR><TT>&nbsp; 20: 51 91 14 d2&nbsp; fc 9f a7 ea&nbsp; 4d 9c f7 3a&nbsp;
+9d 83 62 4a&nbsp; | Q.......M..:..bJ</TT>
+<BR><TT>]</TT>
+<BR>&nbsp;</UL>
+
+<H4>
+SSL Parse mode</H4>
+The following options deal with SSL connections.
+<UL>-s will turn on SSL parsing. (SSLTap doesn't automatically detect SSL
+sessions.)
+<BR>-x will turn on extra SSL hexdumps. Mostly, if SSL can decode the data,
+it doesn't display the hex.</UL>
+The following SSL3 Data structures are parsed: Handshake, ClientHello,
+ServerHello, CertificateChain, Certificate. In addition, SSL2 ClientHello,
+ServerHello, ClientMasterKey are also partly parsed. NO DECRYPTION IS PERFORMED
+ON THE DATA. SSLTAP CANNOT DECRYPT the data.
+
+<P>If a certificate chain is detected, DER-encoded certificates will be
+saved into files in the current directory called 'cert.0x' where x is the
+sequence number of the certificate.
+<BR>&nbsp;
+<H3>
+Operation Hints</H3>
+Often, you'll find that the server certificate does not get transferred,
+or other parts of the handshake do not happen. This is because the browser
+is taking advantage of session-id-reuse (using the handshake results from
+a previous session). If you restart the browser, it'll clear the session
+id cache.
+
+<P>If you run the ssltap on a different machine that the ssl server you're
+trying to connect to, the browser will complain that the host name you're
+trying to connect to is different to the certificate, but it will still
+let you connect, after showing you a dialog.
+<H3>
+Bugs</H3>
+Please contact <A HREF="mailto:ssltap-support@netscape.com">ssltap-support@netscape.com</A>
+for bug reports.
+<H3>
+History</H3>
+2.1 - First public release (March 1998)
+<BR>&nbsp;
+<H3>
+Other</H3>
+For reference, here is a table of some well-known port numbers:
+<BR>&nbsp;
+<TABLE BORDER=2 >
+<TR>
+<TD>HTTP</TD>
+
+<TD>80</TD>
+</TR>
+
+<TR>
+<TD>SMTP</TD>
+
+<TD>25</TD>
+</TR>
+
+<TR>
+<TD>HTTPS</TD>
+
+<TD>443</TD>
+</TR>
+
+<TR>
+<TD>FTP</TD>
+
+<TD>21</TD>
+</TR>
+
+<TR>
+<TD>IMAPS</TD>
+
+<TD>993</TD>
+</TR>
+
+<TR>
+<TD>NNTP</TD>
+
+<TD>119</TD>
+</TR>
+
+<TR>
+<TD>NNTPS</TD>
+
+<TD>563</TD>
+</TR>
+</TABLE>
+&nbsp;
+
+<P>&nbsp;
+</BODY>
+</HTML>
diff --git a/security/nss/cmd/ssltap/ssltap.c b/security/nss/cmd/ssltap/ssltap.c
new file mode 100644
index 000000000..197b1942d
--- /dev/null
+++ b/security/nss/cmd/ssltap/ssltap.c
@@ -0,0 +1,2590 @@
+/* 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/. */
+
+/*
+ * ssltap.c
+ *
+ * Version 1.0 : Frederick Roeber : 11 June 1997
+ * Version 2.0 : Steve Parkinson : 13 November 1997
+ * Version 3.0 : Nelson Bolyard : 22 July 1998
+ * Version 3.1 : Nelson Bolyard : 24 May 1999
+ *
+ * changes in version 2.0:
+ * Uses NSPR20
+ * Shows structure of SSL negotiation, if enabled.
+ *
+ * This "proxies" a socket connection (like a socks tunnel), but displays the
+ * data is it flies by.
+ *
+ * In the code, the 'client' socket is the one on the client side of the
+ * proxy, and the server socket is on the server side.
+ *
+ */
+
+#include "nspr.h"
+#include "plstr.h"
+#include "secutil.h"
+#include <memory.h> /* for memcpy, etc. */
+#include <string.h>
+#include <time.h>
+
+#include "plgetopt.h"
+#include "nss.h"
+#include "cert.h"
+#include "sslproto.h"
+#include "ocsp.h"
+#include "ocspti.h" /* internals for pretty-printing routines *only* */
+
+struct _DataBufferList;
+struct _DataBuffer;
+
+typedef struct _DataBufferList {
+ struct _DataBuffer *first, *last;
+ unsigned int size;
+ int isEncrypted;
+ unsigned char *msgBuf;
+ unsigned int msgBufOffset;
+ unsigned int msgBufSize;
+ unsigned int hMACsize;
+} DataBufferList;
+
+typedef struct _DataBuffer {
+ unsigned char *buffer;
+ int length;
+ int offset; /* offset of first good byte */
+ struct _DataBuffer *next;
+} DataBuffer;
+
+struct sslhandshake {
+ PRUint8 type;
+ PRUint32 length;
+};
+
+typedef struct _SSLRecord {
+ PRUint8 type;
+ PRUint8 ver_maj, ver_min;
+
+ PRUint8 length[2];
+} SSLRecord;
+
+typedef struct _ClientHelloV2 {
+ PRUint8 length[2];
+ PRUint8 type;
+ PRUint8 version[2];
+ PRUint8 cslength[2];
+ PRUint8 sidlength[2];
+ PRUint8 rndlength[2];
+ PRUint8 csuites[1];
+} ClientHelloV2;
+
+typedef struct _ServerHelloV2 {
+ PRUint8 length[2];
+ PRUint8 type;
+ PRUint8 sidhit;
+ PRUint8 certtype;
+ PRUint8 version[2];
+ PRUint8 certlength[2];
+ PRUint8 cslength[2];
+ PRUint8 cidlength[2];
+} ServerHelloV2;
+
+typedef struct _ClientMasterKeyV2 {
+ PRUint8 length[2];
+ PRUint8 type;
+
+ PRUint8 cipherkind[3];
+ PRUint8 clearkey[2];
+ PRUint8 secretkey[2];
+
+} ClientMasterKeyV2;
+
+/* forward declaration */
+void showErr(const char *msg);
+
+#define TAPBUFSIZ 16384
+
+#define DEFPORT 1924
+#include <ctype.h>
+
+const char *progName;
+int hexparse = 0;
+int sslparse = 0;
+int sslhexparse = 0;
+int looparound = 0;
+int fancy = 0;
+int isV2Session = 0;
+int currentcipher = 0;
+DataBufferList clientstream, serverstream;
+
+#define PR_FPUTS(x) PR_fprintf(PR_STDOUT, x)
+
+#define GET_SHORT(x) ((PRUint16)(((PRUint16)((PRUint8 *)x)[0]) << 8) + ((PRUint16)((PRUint8 *)x)[1]))
+#define GET_24(x) ((PRUint32)( \
+ (((PRUint32)((PRUint8 *)x)[0]) << 16) + \
+ (((PRUint32)((PRUint8 *)x)[1]) << 8) + \
+ (((PRUint32)((PRUint8 *)x)[2]) << 0)))
+#define GET_32(x) ((PRUint32)( \
+ (((PRUint32)((PRUint8 *)x)[0]) << 24) + \
+ (((PRUint32)((PRUint8 *)x)[1]) << 16) + \
+ (((PRUint32)((PRUint8 *)x)[2]) << 8) + \
+ (((PRUint32)((PRUint8 *)x)[3]) << 0)))
+
+void print_hex(int amt, unsigned char *buf);
+void read_stream_bytes(unsigned char *d, DataBufferList *db, int length);
+
+void
+myhalt(int dblsize, int collectedsize)
+{
+
+ PR_fprintf(PR_STDERR, "HALTED\n");
+ PR_ASSERT(dblsize == collectedsize);
+ exit(13);
+}
+
+const char *
+get_error_text(int error)
+{
+ switch (error) {
+ case PR_IO_TIMEOUT_ERROR:
+ return "Timeout";
+ break;
+ case PR_CONNECT_REFUSED_ERROR:
+ return "Connection refused";
+ break;
+ case PR_NETWORK_UNREACHABLE_ERROR:
+ return "Network unreachable";
+ break;
+ case PR_BAD_ADDRESS_ERROR:
+ return "Bad address";
+ break;
+ case PR_CONNECT_RESET_ERROR:
+ return "Connection reset";
+ break;
+ case PR_PIPE_ERROR:
+ return "Pipe error";
+ break;
+ }
+
+ return "";
+}
+
+void
+check_integrity(DataBufferList *dbl)
+{
+ DataBuffer *db;
+ int i;
+
+ db = dbl->first;
+ i = 0;
+ while (db) {
+ i += db->length - db->offset;
+ db = db->next;
+ }
+ if (i != dbl->size) {
+ myhalt(dbl->size, i);
+ }
+}
+
+/* Free's the DataBuffer at the head of the list and returns the pointer
+ * to the new head of the list.
+ */
+DataBuffer *
+free_head(DataBufferList *dbl)
+{
+ DataBuffer *db = dbl->first;
+ PR_ASSERT(db->offset >= db->length);
+ if (db->offset >= db->length) {
+ dbl->first = db->next;
+ if (dbl->first == NULL) {
+ dbl->last = NULL;
+ }
+ PORT_Free(db->buffer);
+ PORT_Free(db);
+ db = dbl->first;
+ }
+ return db;
+}
+
+void
+read_stream_bytes(unsigned char *d, DataBufferList *dbl, int length)
+{
+ int copied = 0;
+ DataBuffer *db = dbl->first;
+
+ if (!db) {
+ PR_fprintf(PR_STDERR, "assert failed - dbl->first is null\n");
+ exit(8);
+ }
+ while (length) {
+ int toCopy;
+ /* find the number of bytes to copy from the head buffer */
+ /* if there's too many in this buffer, then only copy 'length' */
+ toCopy = PR_MIN(db->length - db->offset, length);
+
+ memcpy(d + copied, db->buffer + db->offset, toCopy);
+ copied += toCopy;
+ db->offset += toCopy;
+ length -= toCopy;
+ dbl->size -= toCopy;
+
+ /* if we emptied the head buffer */
+ if (db->offset >= db->length) {
+ db = free_head(dbl);
+ }
+ }
+
+ check_integrity(dbl);
+}
+
+void
+flush_stream(DataBufferList *dbl)
+{
+ DataBuffer *db = dbl->first;
+ check_integrity(dbl);
+ while (db) {
+ db->offset = db->length;
+ db = free_head(dbl);
+ }
+ dbl->size = 0;
+ check_integrity(dbl);
+ if (dbl->msgBuf) {
+ PORT_Free(dbl->msgBuf);
+ dbl->msgBuf = NULL;
+ }
+ dbl->msgBufOffset = 0;
+ dbl->msgBufSize = 0;
+ dbl->hMACsize = 0;
+}
+
+const char *
+V2CipherString(int cs_int)
+{
+ char *cs_str;
+ cs_str = NULL;
+ switch (cs_int) {
+
+ case 0x010080:
+ cs_str = "SSL2/RSA/RC4-128/MD5";
+ break;
+ case 0x020080:
+ cs_str = "SSL2/RSA/RC4-40/MD5";
+ break;
+ case 0x030080:
+ cs_str = "SSL2/RSA/RC2CBC128/MD5";
+ break;
+ case 0x040080:
+ cs_str = "SSL2/RSA/RC2CBC40/MD5";
+ break;
+ case 0x050080:
+ cs_str = "SSL2/RSA/IDEA128CBC/MD5";
+ break;
+ case 0x060040:
+ cs_str = "SSL2/RSA/DES56-CBC/MD5";
+ break;
+ case 0x0700C0:
+ cs_str = "SSL2/RSA/3DES192EDE-CBC/MD5";
+ break;
+
+ case 0x000001:
+ cs_str = "SSL3/RSA/NULL/MD5";
+ break;
+ case 0x000002:
+ cs_str = "SSL3/RSA/NULL/SHA";
+ break;
+ case 0x000003:
+ cs_str = "SSL3/RSA/RC4-40/MD5";
+ break;
+ case 0x000004:
+ cs_str = "SSL3/RSA/RC4-128/MD5";
+ break;
+ case 0x000005:
+ cs_str = "SSL3/RSA/RC4-128/SHA";
+ break;
+ case 0x000006:
+ cs_str = "SSL3/RSA/RC2CBC40/MD5";
+ break;
+ case 0x000007:
+ cs_str = "SSL3/RSA/IDEA128CBC/SHA";
+ break;
+ case 0x000008:
+ cs_str = "SSL3/RSA/DES40-CBC/SHA";
+ break;
+ case 0x000009:
+ cs_str = "SSL3/RSA/DES56-CBC/SHA";
+ break;
+ case 0x00000A:
+ cs_str = "SSL3/RSA/3DES192EDE-CBC/SHA";
+ break;
+
+ case 0x00000B:
+ cs_str = "SSL3/DH-DSS/DES40-CBC/SHA";
+ break;
+ case 0x00000C:
+ cs_str = "SSL3/DH-DSS/DES56-CBC/SHA";
+ break;
+ case 0x00000D:
+ cs_str = "SSL3/DH-DSS/DES192EDE3CBC/SHA";
+ break;
+ case 0x00000E:
+ cs_str = "SSL3/DH-RSA/DES40-CBC/SHA";
+ break;
+ case 0x00000F:
+ cs_str = "SSL3/DH-RSA/DES56-CBC/SHA";
+ break;
+ case 0x000010:
+ cs_str = "SSL3/DH-RSA/3DES192EDE-CBC/SHA";
+ break;
+
+ case 0x000011:
+ cs_str = "SSL3/DHE-DSS/DES40-CBC/SHA";
+ break;
+ case 0x000012:
+ cs_str = "SSL3/DHE-DSS/DES56-CBC/SHA";
+ break;
+ case 0x000013:
+ cs_str = "SSL3/DHE-DSS/DES192EDE3CBC/SHA";
+ break;
+ case 0x000014:
+ cs_str = "SSL3/DHE-RSA/DES40-CBC/SHA";
+ break;
+ case 0x000015:
+ cs_str = "SSL3/DHE-RSA/DES56-CBC/SHA";
+ break;
+ case 0x000016:
+ cs_str = "SSL3/DHE-RSA/3DES192EDE-CBC/SHA";
+ break;
+
+ case 0x000017:
+ cs_str = "SSL3/DH-anon/RC4-40/MD5";
+ break;
+ case 0x000018:
+ cs_str = "SSL3/DH-anon/RC4-128/MD5";
+ break;
+ case 0x000019:
+ cs_str = "SSL3/DH-anon/DES40-CBC/SHA";
+ break;
+ case 0x00001A:
+ cs_str = "SSL3/DH-anon/DES56-CBC/SHA";
+ break;
+ case 0x00001B:
+ cs_str = "SSL3/DH-anon/3DES192EDE-CBC/SHA";
+ break;
+
+ case 0x00001C:
+ cs_str = "SSL3/FORTEZZA-DMS/NULL/SHA";
+ break;
+ case 0x00001D:
+ cs_str = "SSL3/FORTEZZA-DMS/FORTEZZA-CBC/SHA";
+ break;
+ case 0x00001E:
+ cs_str = "SSL3/FORTEZZA-DMS/RC4-128/SHA";
+ break;
+
+ case 0x00002F:
+ cs_str = "TLS/RSA/AES128-CBC/SHA";
+ break;
+ case 0x000030:
+ cs_str = "TLS/DH-DSS/AES128-CBC/SHA";
+ break;
+ case 0x000031:
+ cs_str = "TLS/DH-RSA/AES128-CBC/SHA";
+ break;
+ case 0x000032:
+ cs_str = "TLS/DHE-DSS/AES128-CBC/SHA";
+ break;
+ case 0x000033:
+ cs_str = "TLS/DHE-RSA/AES128-CBC/SHA";
+ break;
+ case 0x000034:
+ cs_str = "TLS/DH-ANON/AES128-CBC/SHA";
+ break;
+
+ case 0x000035:
+ cs_str = "TLS/RSA/AES256-CBC/SHA";
+ break;
+ case 0x000036:
+ cs_str = "TLS/DH-DSS/AES256-CBC/SHA";
+ break;
+ case 0x000037:
+ cs_str = "TLS/DH-RSA/AES256-CBC/SHA";
+ break;
+ case 0x000038:
+ cs_str = "TLS/DHE-DSS/AES256-CBC/SHA";
+ break;
+ case 0x000039:
+ cs_str = "TLS/DHE-RSA/AES256-CBC/SHA";
+ break;
+ case 0x00003A:
+ cs_str = "TLS/DH-ANON/AES256-CBC/SHA";
+ break;
+
+ case 0x00003B:
+ cs_str = "TLS/RSA/NULL/SHA256";
+ break;
+ case 0x00003C:
+ cs_str = "TLS/RSA/AES128-CBC/SHA256";
+ break;
+ case 0x00003D:
+ cs_str = "TLS/RSA/AES256-CBC/SHA256";
+ break;
+ case 0x00003E:
+ cs_str = "TLS/DH-DSS/AES128-CBC/SHA256";
+ break;
+ case 0x00003F:
+ cs_str = "TLS/DH-RSA/AES128-CBC/SHA256";
+ break;
+ case 0x000040:
+ cs_str = "TLS/DHE-DSS/AES128-CBC/SHA256";
+ break;
+
+ case 0x000041:
+ cs_str = "TLS/RSA/CAMELLIA128-CBC/SHA";
+ break;
+ case 0x000042:
+ cs_str = "TLS/DH-DSS/CAMELLIA128-CBC/SHA";
+ break;
+ case 0x000043:
+ cs_str = "TLS/DH-RSA/CAMELLIA128-CBC/SHA";
+ break;
+ case 0x000044:
+ cs_str = "TLS/DHE-DSS/CAMELLIA128-CBC/SHA";
+ break;
+ case 0x000045:
+ cs_str = "TLS/DHE-RSA/CAMELLIA128-CBC/SHA";
+ break;
+ case 0x000046:
+ cs_str = "TLS/DH-ANON/CAMELLIA128-CBC/SHA";
+ break;
+
+ case 0x000060:
+ cs_str = "TLS/RSA-EXPORT1024/RC4-56/MD5";
+ break;
+ case 0x000061:
+ cs_str = "TLS/RSA-EXPORT1024/RC2CBC56/MD5";
+ break;
+ case 0x000062:
+ cs_str = "TLS/RSA-EXPORT1024/DES56-CBC/SHA";
+ break;
+ case 0x000064:
+ cs_str = "TLS/RSA-EXPORT1024/RC4-56/SHA";
+ break;
+ case 0x000063:
+ cs_str = "TLS/DHE-DSS_EXPORT1024/DES56-CBC/SHA";
+ break;
+ case 0x000065:
+ cs_str = "TLS/DHE-DSS_EXPORT1024/RC4-56/SHA";
+ break;
+ case 0x000066:
+ cs_str = "TLS/DHE-DSS/RC4-128/SHA";
+ break;
+
+ case 0x000067:
+ cs_str = "TLS/DHE-RSA/AES128-CBC/SHA256";
+ break;
+ case 0x000068:
+ cs_str = "TLS/DH-DSS/AES256-CBC/SHA256";
+ break;
+ case 0x000069:
+ cs_str = "TLS/DH-RSA/AES256-CBC/SHA256";
+ break;
+ case 0x00006A:
+ cs_str = "TLS/DHE-DSS/AES256-CBC/SHA256";
+ break;
+ case 0x00006B:
+ cs_str = "TLS/DHE-RSA/AES256-CBC/SHA256";
+ break;
+
+ case 0x000072:
+ cs_str = "TLS/DHE-DSS/3DESEDE-CBC/RMD160";
+ break;
+ case 0x000073:
+ cs_str = "TLS/DHE-DSS/AES128-CBC/RMD160";
+ break;
+ case 0x000074:
+ cs_str = "TLS/DHE-DSS/AES256-CBC/RMD160";
+ break;
+
+ case 0x000079:
+ cs_str = "TLS/DHE-RSA/AES256-CBC/RMD160";
+ break;
+
+ case 0x00007C:
+ cs_str = "TLS/RSA/3DESEDE-CBC/RMD160";
+ break;
+ case 0x00007D:
+ cs_str = "TLS/RSA/AES128-CBC/RMD160";
+ break;
+ case 0x00007E:
+ cs_str = "TLS/RSA/AES256-CBC/RMD160";
+ break;
+
+ case 0x000080:
+ cs_str = "TLS/GOST341094/GOST28147-OFB/GOST28147";
+ break;
+ case 0x000081:
+ cs_str = "TLS/GOST34102001/GOST28147-OFB/GOST28147";
+ break;
+ case 0x000082:
+ cs_str = "TLS/GOST341094/NULL/GOSTR3411";
+ break;
+ case 0x000083:
+ cs_str = "TLS/GOST34102001/NULL/GOSTR3411";
+ break;
+
+ case 0x000084:
+ cs_str = "TLS/RSA/CAMELLIA256-CBC/SHA";
+ break;
+ case 0x000085:
+ cs_str = "TLS/DH-DSS/CAMELLIA256-CBC/SHA";
+ break;
+ case 0x000086:
+ cs_str = "TLS/DH-RSA/CAMELLIA256-CBC/SHA";
+ break;
+ case 0x000087:
+ cs_str = "TLS/DHE-DSS/CAMELLIA256-CBC/SHA";
+ break;
+ case 0x000088:
+ cs_str = "TLS/DHE-RSA/CAMELLIA256-CBC/SHA";
+ break;
+ case 0x000089:
+ cs_str = "TLS/DH-ANON/CAMELLIA256-CBC/SHA";
+ break;
+ case 0x00008A:
+ cs_str = "TLS/PSK/RC4-128/SHA";
+ break;
+ case 0x00008B:
+ cs_str = "TLS/PSK/3DES-EDE-CBC/SHA";
+ break;
+ case 0x00008C:
+ cs_str = "TLS/PSK/AES128-CBC/SHA";
+ break;
+ case 0x00008D:
+ cs_str = "TLS/PSK/AES256-CBC/SHA";
+ break;
+ case 0x00008E:
+ cs_str = "TLS/DHE-PSK/RC4-128/SHA";
+ break;
+ case 0x00008F:
+ cs_str = "TLS/DHE-PSK/3DES-EDE-CBC/SHA";
+ break;
+ case 0x000090:
+ cs_str = "TLS/DHE-PSK/AES128-CBC/SHA";
+ break;
+ case 0x000091:
+ cs_str = "TLS/DHE-PSK/AES256-CBC/SHA";
+ break;
+ case 0x000092:
+ cs_str = "TLS/RSA-PSK/RC4-128/SHA";
+ break;
+ case 0x000093:
+ cs_str = "TLS/RSA-PSK/3DES-EDE-CBC/SHA";
+ break;
+ case 0x000094:
+ cs_str = "TLS/RSA-PSK/AES128-CBC/SHA";
+ break;
+ case 0x000095:
+ cs_str = "TLS/RSA-PSK/AES256-CBC/SHA";
+ break;
+ case 0x000096:
+ cs_str = "TLS/RSA/SEED-CBC/SHA";
+ break;
+ case 0x000097:
+ cs_str = "TLS/DH-DSS/SEED-CBC/SHA";
+ break;
+ case 0x000098:
+ cs_str = "TLS/DH-RSA/SEED-CBC/SHA";
+ break;
+ case 0x000099:
+ cs_str = "TLS/DHE-DSS/SEED-CBC/SHA";
+ break;
+ case 0x00009A:
+ cs_str = "TLS/DHE-RSA/SEED-CBC/SHA";
+ break;
+ case 0x00009B:
+ cs_str = "TLS/DH-ANON/SEED-CBC/SHA";
+ break;
+ case 0x00009C:
+ cs_str = "TLS/RSA/AES128-GCM/SHA256";
+ break;
+ case 0x00009E:
+ cs_str = "TLS/DHE-RSA/AES128-GCM/SHA256";
+ break;
+
+ case 0x0000FF:
+ cs_str = "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
+ break;
+ case 0x005600:
+ cs_str = "TLS_FALLBACK_SCSV";
+ break;
+
+ case 0x00C001:
+ cs_str = "TLS/ECDH-ECDSA/NULL/SHA";
+ break;
+ case 0x00C002:
+ cs_str = "TLS/ECDH-ECDSA/RC4-128/SHA";
+ break;
+ case 0x00C003:
+ cs_str = "TLS/ECDH-ECDSA/3DES-EDE-CBC/SHA";
+ break;
+ case 0x00C004:
+ cs_str = "TLS/ECDH-ECDSA/AES128-CBC/SHA";
+ break;
+ case 0x00C005:
+ cs_str = "TLS/ECDH-ECDSA/AES256-CBC/SHA";
+ break;
+ case 0x00C006:
+ cs_str = "TLS/ECDHE-ECDSA/NULL/SHA";
+ break;
+ case 0x00C007:
+ cs_str = "TLS/ECDHE-ECDSA/RC4-128/SHA";
+ break;
+ case 0x00C008:
+ cs_str = "TLS/ECDHE-ECDSA/3DES-EDE-CBC/SHA";
+ break;
+ case 0x00C009:
+ cs_str = "TLS/ECDHE-ECDSA/AES128-CBC/SHA";
+ break;
+ case 0x00C00A:
+ cs_str = "TLS/ECDHE-ECDSA/AES256-CBC/SHA";
+ break;
+ case 0x00C00B:
+ cs_str = "TLS/ECDH-RSA/NULL/SHA";
+ break;
+ case 0x00C00C:
+ cs_str = "TLS/ECDH-RSA/RC4-128/SHA";
+ break;
+ case 0x00C00D:
+ cs_str = "TLS/ECDH-RSA/3DES-EDE-CBC/SHA";
+ break;
+ case 0x00C00E:
+ cs_str = "TLS/ECDH-RSA/AES128-CBC/SHA";
+ break;
+ case 0x00C00F:
+ cs_str = "TLS/ECDH-RSA/AES256-CBC/SHA";
+ break;
+ case 0x00C010:
+ cs_str = "TLS/ECDHE-RSA/NULL/SHA";
+ break;
+ case 0x00C011:
+ cs_str = "TLS/ECDHE-RSA/RC4-128/SHA";
+ break;
+ case 0x00C012:
+ cs_str = "TLS/ECDHE-RSA/3DES-EDE-CBC/SHA";
+ break;
+ case 0x00C013:
+ cs_str = "TLS/ECDHE-RSA/AES128-CBC/SHA";
+ break;
+ case 0x00C014:
+ cs_str = "TLS/ECDHE-RSA/AES256-CBC/SHA";
+ break;
+ case 0x00C015:
+ cs_str = "TLS/ECDH-anon/NULL/SHA";
+ break;
+ case 0x00C016:
+ cs_str = "TLS/ECDH-anon/RC4-128/SHA";
+ break;
+ case 0x00C017:
+ cs_str = "TLS/ECDH-anon/3DES-EDE-CBC/SHA";
+ break;
+ case 0x00C018:
+ cs_str = "TLS/ECDH-anon/AES128-CBC/SHA";
+ break;
+ case 0x00C019:
+ cs_str = "TLS/ECDH-anon/AES256-CBC/SHA";
+ break;
+
+ case 0x00C023:
+ cs_str = "TLS/ECDHE-ECDSA/AES128-CBC/SHA256";
+ break;
+ case 0x00C024:
+ cs_str = "TLS/ECDHE-ECDSA/AES256-CBC/SHA384";
+ break;
+ case 0x00C025:
+ cs_str = "TLS/ECDH-ECDSA/AES128-CBC/SHA256";
+ break;
+ case 0x00C026:
+ cs_str = "TLS/ECDH-ECDSA/AES256-CBC/SHA384";
+ break;
+ case 0x00C027:
+ cs_str = "TLS/ECDHE-RSA/AES128-CBC/SHA256";
+ break;
+ case 0x00C028:
+ cs_str = "TLS/ECDHE-RSA/AES256-CBC/SHA384";
+ break;
+ case 0x00C029:
+ cs_str = "TLS/ECDH-RSA/AES128-CBC/SHA256";
+ break;
+ case 0x00C02A:
+ cs_str = "TLS/ECDH-RSA/AES256-CBC/SHA384";
+ break;
+ case 0x00C02B:
+ cs_str = "TLS/ECDHE-ECDSA/AES128-GCM/SHA256";
+ break;
+ case 0x00C02C:
+ cs_str = "TLS/ECDHE-ECDSA/AES256-GCM/SHA384";
+ break;
+ case 0x00C02F:
+ cs_str = "TLS/ECDHE-RSA/AES128-GCM/SHA256";
+ break;
+
+ case 0x00CCA8:
+ cs_str = "TLS/ECDHE-RSA/CHACHA20-POLY1305/SHA256";
+ break;
+ case 0x00CCA9:
+ cs_str = "TLS/ECDHE-ECDSA/CHACHA20-POLY1305/SHA256";
+ break;
+ case 0x00CCAA:
+ cs_str = "TLS/DHE-RSA/CHACHA20-POLY1305/SHA256";
+ break;
+
+ case 0x00FEFF:
+ cs_str = "SSL3/RSA-FIPS/3DESEDE-CBC/SHA";
+ break;
+ case 0x00FEFE:
+ cs_str = "SSL3/RSA-FIPS/DES-CBC/SHA";
+ break;
+ case 0x00FFE1:
+ cs_str = "SSL3/RSA-FIPS/DES56-CBC/SHA";
+ break;
+ case 0x00FFE0:
+ cs_str = "SSL3/RSA-FIPS/3DES192EDE-CBC/SHA";
+ break;
+
+ /* the string literal is broken up to avoid trigraphs */
+ default:
+ cs_str = "????"
+ "/????????"
+ "/?????????"
+ "/???";
+ break;
+ }
+
+ return cs_str;
+}
+
+const char *
+CompressionMethodString(int cm_int)
+{
+ char *cm_str;
+ cm_str = NULL;
+ switch (cm_int) {
+ case 0:
+ cm_str = "NULL";
+ break;
+ case 1:
+ cm_str = "DEFLATE";
+ break; /* RFC 3749 */
+ case 64:
+ cm_str = "LZS";
+ break; /* RFC 3943 */
+ default:
+ cm_str = "???";
+ break;
+ }
+
+ return cm_str;
+}
+
+const char *
+helloExtensionNameString(int ex_num)
+{
+ const char *ex_name = NULL;
+ static char buf[10];
+
+ switch (ex_num) {
+ case 0:
+ ex_name = "server_name";
+ break;
+ case 1:
+ ex_name = "max_fragment_length";
+ break;
+ case 2:
+ ex_name = "client_certificate_url";
+ break;
+ case 3:
+ ex_name = "trusted_ca_keys";
+ break;
+ case 4:
+ ex_name = "truncated_hmac";
+ break;
+ case 5:
+ ex_name = "status_request";
+ break;
+ case 10:
+ ex_name = "elliptic_curves";
+ break;
+ case 11:
+ ex_name = "ec_point_formats";
+ break;
+ case 13:
+ ex_name = "signature_algorithms";
+ break;
+ case 35:
+ ex_name = "session_ticket";
+ break;
+ case 0xff01:
+ ex_name = "renegotiation_info";
+ break;
+ default:
+ sprintf(buf, "%d", ex_num);
+ ex_name = (const char *)buf;
+ break;
+ }
+
+ return ex_name;
+}
+
+static int
+isNULLmac(int cs_int)
+{
+ return (cs_int == TLS_NULL_WITH_NULL_NULL);
+}
+
+static int
+isNULLcipher(int cs_int)
+{
+ return ((cs_int == TLS_RSA_WITH_NULL_MD5) ||
+ (cs_int == TLS_RSA_WITH_NULL_SHA) ||
+ (cs_int == SSL_FORTEZZA_DMS_WITH_NULL_SHA) ||
+ (cs_int == TLS_ECDH_ECDSA_WITH_NULL_SHA) ||
+ (cs_int == TLS_ECDHE_ECDSA_WITH_NULL_SHA) ||
+ (cs_int == TLS_ECDH_RSA_WITH_NULL_SHA) ||
+ (cs_int == TLS_ECDHE_RSA_WITH_NULL_SHA));
+}
+
+void
+partial_packet(int thispacket, int size, int needed)
+{
+ PR_fprintf(PR_STDOUT, "(%u bytes", thispacket);
+ if (thispacket < needed) {
+ PR_fprintf(PR_STDOUT, ", making %u", size);
+ }
+ PR_fprintf(PR_STDOUT, " of %u", needed);
+ if (size > needed) {
+ PR_fprintf(PR_STDOUT, ", with %u left over", size - needed);
+ }
+ PR_fprintf(PR_STDOUT, ")\n");
+}
+
+char *
+get_time_string(void)
+{
+ char *cp;
+ char *eol;
+ time_t tt;
+
+ time(&tt);
+ cp = ctime(&tt);
+ eol = strchr(cp, '\n');
+ if (eol)
+ *eol = 0;
+ return cp;
+}
+
+void
+print_sslv2(DataBufferList *s, unsigned char *recordBuf, unsigned int recordLen)
+{
+ ClientHelloV2 *chv2;
+ ServerHelloV2 *shv2;
+ unsigned char *pos;
+ unsigned int p;
+ unsigned int q;
+ PRUint32 len;
+
+ chv2 = (ClientHelloV2 *)recordBuf;
+ shv2 = (ServerHelloV2 *)recordBuf;
+ if (s->isEncrypted) {
+ PR_fprintf(PR_STDOUT, " [ssl2] Encrypted {...}\n");
+ return;
+ }
+ PR_fprintf(PR_STDOUT, " [%s]", get_time_string());
+ switch (chv2->type) {
+ case 1:
+ PR_fprintf(PR_STDOUT, " [ssl2] ClientHelloV2 {\n");
+ PR_fprintf(PR_STDOUT, " version = {0x%02x, 0x%02x}\n",
+ (PRUint32)chv2->version[0], (PRUint32)chv2->version[1]);
+ PR_fprintf(PR_STDOUT, " cipher-specs-length = %d (0x%02x)\n",
+ (PRUint32)(GET_SHORT((chv2->cslength))),
+ (PRUint32)(GET_SHORT((chv2->cslength))));
+ PR_fprintf(PR_STDOUT, " sid-length = %d (0x%02x)\n",
+ (PRUint32)(GET_SHORT((chv2->sidlength))),
+ (PRUint32)(GET_SHORT((chv2->sidlength))));
+ PR_fprintf(PR_STDOUT, " challenge-length = %d (0x%02x)\n",
+ (PRUint32)(GET_SHORT((chv2->rndlength))),
+ (PRUint32)(GET_SHORT((chv2->rndlength))));
+ PR_fprintf(PR_STDOUT, " cipher-suites = { \n");
+ for (p =
+ 0;
+ p < (PRUint32)GET_SHORT((chv2->cslength)); p += 3) {
+ PRUint32 cs_int = GET_24((&chv2->csuites[p]));
+ const char *cs_str =
+ V2CipherString(cs_int);
+
+ PR_fprintf(PR_STDOUT, " (0x%06x) %s\n",
+ cs_int, cs_str);
+ }
+ q = p;
+ PR_fprintf(PR_STDOUT, " }\n");
+ if (GET_SHORT((chv2->sidlength))) {
+ PR_fprintf(PR_STDOUT, " session-id = { ");
+ for (p = 0;
+ p < (PRUint32)GET_SHORT((chv2->sidlength)); p += 2) {
+ PR_fprintf(PR_STDOUT, "0x%04x ", (PRUint32)(GET_SHORT((&chv2->csuites[p + q]))));
+ }
+ }
+ q += p;
+ PR_fprintf(PR_STDOUT, "}\n");
+ if (GET_SHORT((chv2->rndlength))) {
+ PR_fprintf(PR_STDOUT, " challenge = { ");
+ for (p = 0;
+ p < (PRUint32)GET_SHORT((chv2->rndlength)); p += 2) {
+ PR_fprintf(PR_STDOUT, "0x%04x ", (PRUint32)(GET_SHORT((&chv2->csuites[p + q]))));
+ }
+ PR_fprintf(PR_STDOUT, "}\n");
+ }
+ PR_fprintf(PR_STDOUT, "}\n");
+ break;
+ /* end of V2 CLientHello Parsing */
+
+ case 2: /* Client Master Key */
+ {
+ const char *cs_str =
+ NULL;
+ PRUint32 cs_int =
+ 0;
+ ClientMasterKeyV2 *cmkv2;
+ cmkv2 = (ClientMasterKeyV2 *)chv2;
+ isV2Session = 1;
+
+ PR_fprintf(PR_STDOUT, " [ssl2] ClientMasterKeyV2 { \n");
+
+ cs_int = GET_24(&cmkv2->cipherkind[0]);
+ cs_str = V2CipherString(cs_int);
+ PR_fprintf(PR_STDOUT, " cipher-spec-chosen = (0x%06x) %s\n",
+ cs_int, cs_str);
+
+ PR_fprintf(PR_STDOUT, " clear-portion = %d bits\n",
+ 8 *
+ (PRUint32)(GET_SHORT((cmkv2->clearkey))));
+
+ PR_fprintf(PR_STDOUT, " }\n");
+ clientstream.isEncrypted = 1;
+ serverstream.isEncrypted = 1;
+ } break;
+
+ case 3:
+ PR_fprintf(PR_STDOUT, " [ssl2] Client Finished V2 {...}\n");
+ isV2Session = 1;
+ break;
+
+ case 4: /* V2 Server Hello */
+ isV2Session = 1;
+
+ PR_fprintf(PR_STDOUT, " [ssl2] ServerHelloV2 {\n");
+ PR_fprintf(PR_STDOUT, " sid hit = {0x%02x}\n",
+ (PRUintn)shv2->sidhit);
+ PR_fprintf(PR_STDOUT, " version = {0x%02x, 0x%02x}\n",
+ (PRUint32)shv2->version[0], (PRUint32)shv2->version[1]);
+ PR_fprintf(PR_STDOUT, " cipher-specs-length = %d (0x%02x)\n",
+ (PRUint32)(GET_SHORT((shv2->cslength))),
+ (PRUint32)(GET_SHORT((shv2->cslength))));
+ PR_fprintf(PR_STDOUT, " sid-length = %d (0x%02x)\n",
+ (PRUint32)(GET_SHORT((shv2->cidlength))),
+ (PRUint32)(GET_SHORT((shv2->cidlength))));
+
+ pos = (unsigned char *)shv2;
+ pos += 2; /* skip length header */
+ pos += 11; /* position pointer to Certificate data area */
+ q = GET_SHORT(&shv2->certlength);
+ if (q > recordLen) {
+ goto eosh;
+ }
+ pos += q; /* skip certificate */
+
+ PR_fprintf(PR_STDOUT, " cipher-suites = { ");
+ len = GET_SHORT((shv2->cslength));
+ for (p = 0; p < len; p += 3) {
+ PRUint32 cs_int = GET_24((pos + p));
+ const char *cs_str =
+ V2CipherString(cs_int);
+ PR_fprintf(PR_STDOUT, "\n ");
+ PR_fprintf(PR_STDOUT, "(0x%06x) %s", cs_int, cs_str);
+ }
+ pos += len;
+ PR_fprintf(PR_STDOUT, " }\n"); /* End of cipher suites */
+ len = (PRUint32)GET_SHORT((shv2->cidlength));
+ if (len) {
+ PR_fprintf(PR_STDOUT, " connection-id = { ");
+ for (p =
+ 0;
+ p < len; p += 2) {
+ PR_fprintf(PR_STDOUT, "0x%04x ", (PRUint32)(GET_SHORT((pos +
+ p))));
+ }
+ PR_fprintf(PR_STDOUT, " }\n"); /* End of connection id */
+ }
+ eosh:
+ PR_fprintf(PR_STDOUT, "\n }\n"); /* end of ServerHelloV2 */
+ if (shv2->sidhit) {
+ clientstream.isEncrypted =
+ 1;
+ serverstream.isEncrypted =
+ 1;
+ }
+ break;
+
+ case 5:
+ PR_fprintf(PR_STDOUT, " [ssl2] Server Verify V2 {...}\n");
+ isV2Session = 1;
+ break;
+
+ case 6:
+ PR_fprintf(PR_STDOUT, " [ssl2] Server Finished V2 {...}\n");
+ isV2Session = 1;
+ break;
+
+ case 7:
+ PR_fprintf(PR_STDOUT, " [ssl2] Request Certificate V2 {...}\n");
+ isV2Session = 1;
+ break;
+
+ case 8:
+ PR_fprintf(PR_STDOUT, " [ssl2] Client Certificate V2 {...}\n");
+ isV2Session = 1;
+ break;
+
+ default:
+ PR_fprintf(PR_STDOUT, " [ssl2] UnknownType 0x%02x {...}\n",
+ (PRUint32)chv2->type);
+ break;
+ }
+}
+
+unsigned int
+print_hello_extension(unsigned char *hsdata,
+ unsigned int length,
+ unsigned int pos)
+{
+ /* pretty print extensions, if any */
+ if (pos < length) {
+ int exListLen = GET_SHORT((hsdata + pos));
+ pos += 2;
+ PR_fprintf(PR_STDOUT,
+ " extensions[%d] = {\n", exListLen);
+ while (exListLen > 0 && pos < length) {
+ int exLen;
+ int exType = GET_SHORT((hsdata + pos));
+ pos += 2;
+ exLen = GET_SHORT((hsdata + pos));
+ pos += 2;
+ /* dump the extension */
+ PR_fprintf(PR_STDOUT,
+ " extension type %s, length [%d]",
+ helloExtensionNameString(exType), exLen);
+ if (exLen > 0) {
+ PR_fprintf(PR_STDOUT, " = {\n");
+ print_hex(exLen, hsdata + pos);
+ PR_fprintf(PR_STDOUT, " }\n");
+ } else {
+ PR_fprintf(PR_STDOUT, "\n");
+ }
+ pos += exLen;
+ exListLen -= 2 + exLen;
+ }
+ PR_fprintf(PR_STDOUT, " }\n");
+ }
+ return pos;
+}
+
+/*
+ * Note this must match (exactly) the enumeration ocspResponseStatus.
+ */
+static char *responseStatusNames[] = {
+ "successful (Response has valid confirmations)",
+ "malformedRequest (Illegal confirmation request)",
+ "internalError (Internal error in issuer)",
+ "tryLater (Try again later)",
+ "unused ((4) is not used)",
+ "sigRequired (Must sign the request)",
+ "unauthorized (Request unauthorized)",
+};
+
+static void
+print_ocsp_cert_id(FILE *out_file, CERTOCSPCertID *cert_id, int level)
+{
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Cert ID:\n");
+ level++;
+ /*
+ SECU_PrintAlgorithmID (out_file, &(cert_id->hashAlgorithm),
+ "Hash Algorithm", level);
+ SECU_PrintAsHex (out_file, &(cert_id->issuerNameHash),
+ "Issuer Name Hash", level);
+ SECU_PrintAsHex (out_file, &(cert_id->issuerKeyHash),
+ "Issuer Key Hash", level);
+*/
+ SECU_PrintInteger(out_file, &(cert_id->serialNumber),
+ "Serial Number", level);
+ /* XXX lookup the cert; if found, print something nice (nickname?) */
+}
+
+static void
+print_ocsp_version(FILE *out_file, SECItem *version, int level)
+{
+ if (version->len > 0) {
+ SECU_PrintInteger(out_file, version, "Version", level);
+ } else {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Version: DEFAULT\n");
+ }
+}
+
+static void
+print_responder_id(FILE *out_file, ocspResponderID *responderID, int level)
+{
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Responder ID ");
+
+ switch (responderID->responderIDType) {
+ case ocspResponderID_byName:
+ fprintf(out_file, "(byName):\n");
+ SECU_PrintName(out_file, &(responderID->responderIDValue.name),
+ "Name", level + 1);
+ break;
+ case ocspResponderID_byKey:
+ fprintf(out_file, "(byKey):\n");
+ SECU_PrintAsHex(out_file, &(responderID->responderIDValue.keyHash),
+ "Key Hash", level + 1);
+ break;
+ default:
+ fprintf(out_file, "Unrecognized Responder ID Type\n");
+ break;
+ }
+}
+
+static void
+print_ocsp_extensions(FILE *out_file, CERTCertExtension **extensions,
+ char *msg, int level)
+{
+ if (extensions) {
+ SECU_PrintExtensions(out_file, extensions, msg, level);
+ } else {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "No %s\n", msg);
+ }
+}
+
+static void
+print_revoked_info(FILE *out_file, ocspRevokedInfo *revoked_info, int level)
+{
+ SECU_PrintGeneralizedTime(out_file, &(revoked_info->revocationTime),
+ "Revocation Time", level);
+
+ if (revoked_info->revocationReason != NULL) {
+ SECU_PrintAsHex(out_file, revoked_info->revocationReason,
+ "Revocation Reason", level);
+ } else {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "No Revocation Reason.\n");
+ }
+}
+
+static void
+print_cert_status(FILE *out_file, ocspCertStatus *status, int level)
+{
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Status: ");
+
+ switch (status->certStatusType) {
+ case ocspCertStatus_good:
+ fprintf(out_file, "Cert is good.\n");
+ break;
+ case ocspCertStatus_revoked:
+ fprintf(out_file, "Cert has been revoked.\n");
+ print_revoked_info(out_file, status->certStatusInfo.revokedInfo,
+ level + 1);
+ break;
+ case ocspCertStatus_unknown:
+ fprintf(out_file, "Cert is unknown to responder.\n");
+ break;
+ default:
+ fprintf(out_file, "Unrecognized status.\n");
+ break;
+ }
+}
+
+static void
+print_single_response(FILE *out_file, CERTOCSPSingleResponse *single,
+ int level)
+{
+ print_ocsp_cert_id(out_file, single->certID, level);
+
+ print_cert_status(out_file, single->certStatus, level);
+
+ SECU_PrintGeneralizedTime(out_file, &(single->thisUpdate),
+ "This Update", level);
+
+ if (single->nextUpdate != NULL) {
+ SECU_PrintGeneralizedTime(out_file, single->nextUpdate,
+ "Next Update", level);
+ } else {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "No Next Update\n");
+ }
+
+ print_ocsp_extensions(out_file, single->singleExtensions,
+ "Single Response Extensions", level);
+}
+
+static void
+print_response_data(FILE *out_file, ocspResponseData *responseData, int level)
+{
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Response Data:\n");
+ level++;
+
+ print_ocsp_version(out_file, &(responseData->version), level);
+
+ print_responder_id(out_file, responseData->responderID, level);
+
+ SECU_PrintGeneralizedTime(out_file, &(responseData->producedAt),
+ "Produced At", level);
+
+ if (responseData->responses != NULL) {
+ int i;
+
+ for (i = 0; responseData->responses[i] != NULL; i++) {
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Response %d:\n", i);
+ print_single_response(out_file, responseData->responses[i],
+ level + 1);
+ }
+ } else {
+ fprintf(out_file, "Response list is empty.\n");
+ }
+
+ print_ocsp_extensions(out_file, responseData->responseExtensions,
+ "Response Extensions", level);
+}
+
+static void
+print_basic_response(FILE *out_file, ocspBasicOCSPResponse *basic, int level)
+{
+ SECU_Indent(out_file, level);
+ fprintf(out_file, "Basic OCSP Response:\n");
+ level++;
+
+ print_response_data(out_file, basic->tbsResponseData, level);
+}
+
+static void
+print_status_response(SECItem *data)
+{
+ int level = 2;
+ CERTOCSPResponse *response;
+ response = CERT_DecodeOCSPResponse(data);
+ if (!response) {
+ SECU_Indent(stdout, level);
+ fprintf(stdout, "unable to decode certificate_status\n");
+ return;
+ }
+
+ SECU_Indent(stdout, level);
+ if (response->statusValue >= ocspResponse_min &&
+ response->statusValue <= ocspResponse_max) {
+ fprintf(stdout, "Response Status: %s\n",
+ responseStatusNames[response->statusValue]);
+ } else {
+ fprintf(stdout,
+ "Response Status: other (Status value %d out of defined range)\n",
+ (int)response->statusValue);
+ }
+
+ if (response->statusValue == ocspResponse_successful) {
+ ocspResponseBytes *responseBytes = response->responseBytes;
+ PORT_Assert(responseBytes != NULL);
+
+ level++;
+ SECU_PrintObjectID(stdout, &(responseBytes->responseType),
+ "Response Type", level);
+ switch (response->responseBytes->responseTypeTag) {
+ case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
+ print_basic_response(stdout,
+ responseBytes->decodedResponse.basic,
+ level);
+ break;
+ default:
+ SECU_Indent(stdout, level);
+ fprintf(stdout, "Unknown response syntax\n");
+ break;
+ }
+ } else {
+ SECU_Indent(stdout, level);
+ fprintf(stdout, "Unsuccessful response, no more information.\n");
+ }
+
+ CERT_DestroyOCSPResponse(response);
+}
+
+/* In the case of renegotiation, handshakes that occur in an already MAC'ed
+ * channel, by the time of this call, the caller has already removed the MAC
+ * from input recordLen. The only MAC'ed record that will get here with its
+ * MAC intact (not removed) is the first Finished message on the connection.
+ */
+void
+print_ssl3_handshake(unsigned char *recordBuf,
+ unsigned int recordLen,
+ SSLRecord *sr,
+ DataBufferList *s)
+{
+ struct sslhandshake sslh;
+ unsigned char *hsdata;
+ unsigned int offset = 0;
+
+ PR_fprintf(PR_STDOUT, " handshake {\n");
+
+ if (s->msgBufOffset && s->msgBuf) {
+ /* append recordBuf to msgBuf, then use msgBuf */
+ if (s->msgBufOffset + recordLen > s->msgBufSize) {
+ int newSize = s->msgBufOffset + recordLen;
+ unsigned char *newBuf = PORT_Realloc(s->msgBuf, newSize);
+ if (!newBuf) {
+ PR_ASSERT(newBuf);
+ showErr("Realloc failed");
+ exit(10);
+ }
+ s->msgBuf = newBuf;
+ s->msgBufSize = newSize;
+ }
+ memcpy(s->msgBuf + s->msgBufOffset, recordBuf, recordLen);
+ s->msgBufOffset += recordLen;
+ recordLen = s->msgBufOffset;
+ recordBuf = s->msgBuf;
+ }
+ while (offset + 4 <= recordLen) {
+ sslh.type = recordBuf[offset];
+ sslh.length = GET_24(recordBuf + offset + 1);
+ if (offset + 4 + sslh.length > recordLen)
+ break;
+ /* finally have a complete message */
+ if (sslhexparse)
+ print_hex(4, recordBuf + offset);
+
+ hsdata = &recordBuf[offset + 4];
+
+ PR_fprintf(PR_STDOUT, " type = %d (", sslh.type);
+ switch (sslh.type) {
+ case 0:
+ PR_FPUTS("hello_request)\n");
+ break;
+ case 1:
+ PR_FPUTS("client_hello)\n");
+ break;
+ case 2:
+ PR_FPUTS("server_hello)\n");
+ break;
+ case 4:
+ PR_FPUTS("new_session_ticket)\n");
+ break;
+ case 11:
+ PR_FPUTS("certificate)\n");
+ break;
+ case 12:
+ PR_FPUTS("server_key_exchange)\n");
+ break;
+ case 13:
+ PR_FPUTS("certificate_request)\n");
+ break;
+ case 14:
+ PR_FPUTS("server_hello_done)\n");
+ break;
+ case 15:
+ PR_FPUTS("certificate_verify)\n");
+ break;
+ case 16:
+ PR_FPUTS("client_key_exchange)\n");
+ break;
+ case 20:
+ PR_FPUTS("finished)\n");
+ break;
+ case 22:
+ PR_FPUTS("certificate_status)\n");
+ break;
+ default:
+ PR_FPUTS("unknown)\n");
+ break;
+ }
+
+ PR_fprintf(PR_STDOUT, " length = %d (0x%06x)\n", sslh.length, sslh.length);
+ switch (sslh.type) {
+
+ case 0: /* hello_request */ /* not much to show here. */
+ break;
+
+ case 1: /* client hello */
+ switch (sr->ver_maj) {
+ case 3: /* ssl version 3 */
+ {
+ unsigned int pos;
+ int w;
+
+ PR_fprintf(PR_STDOUT, " ClientHelloV3 {\n");
+ PR_fprintf(PR_STDOUT, " client_version = {%d, %d}\n",
+ (PRUint8)hsdata[0], (PRUint8)hsdata[1]);
+ PR_fprintf(PR_STDOUT, " random = {...}\n");
+ if (sslhexparse)
+ print_hex(32, &hsdata[2]);
+
+ /* pretty print Session ID */
+ {
+ int sidlength =
+ (int)hsdata[2 + 32];
+ PR_fprintf(PR_STDOUT, " session ID = {\n");
+ PR_fprintf(PR_STDOUT, " length = %d\n", sidlength);
+ PR_fprintf(PR_STDOUT, " contents = {...}\n");
+ if (sslhexparse)
+ print_hex(sidlength, &hsdata[2 + 32 + 1]);
+ PR_fprintf(PR_STDOUT, " }\n");
+ pos =
+ 2 +
+ 32 +
+ 1 +
+ sidlength;
+ }
+
+ /* pretty print cipher suites */
+ {
+ int csuitelength =
+ GET_SHORT((hsdata + pos));
+ PR_fprintf(PR_STDOUT, " cipher_suites[%d] = {\n",
+ csuitelength /
+ 2);
+ if (csuitelength %
+ 2) {
+ PR_fprintf(PR_STDOUT,
+ "*error in protocol - csuitelength shouldn't be odd*\n");
+ }
+ for (w =
+ 0;
+ w <
+ csuitelength;
+ w += 2) {
+ PRUint32 cs_int =
+ GET_SHORT((hsdata + pos + 2 + w));
+ const char *cs_str =
+ V2CipherString(cs_int);
+ PR_fprintf(PR_STDOUT,
+ " (0x%04x) %s\n", cs_int, cs_str);
+ }
+ pos +=
+ 2 +
+ csuitelength;
+ PR_fprintf(PR_STDOUT, " }\n");
+ }
+
+ /* pretty print compression methods */
+ {
+ int complength =
+ hsdata[pos];
+ PR_fprintf(PR_STDOUT, " compression[%d] = {\n",
+ complength);
+ for (w =
+ 0;
+ w <
+ complength;
+ w++) {
+ PRUint32 cm_int =
+ hsdata[pos + 1 + w];
+ const char *cm_str =
+ CompressionMethodString(cm_int);
+ PR_fprintf(PR_STDOUT,
+ " (%02x) %s\n", cm_int, cm_str);
+ }
+ pos +=
+ 1 +
+ complength;
+ PR_fprintf(PR_STDOUT, " }\n");
+ }
+
+ /* pretty print extensions, if any */
+ pos =
+ print_hello_extension(hsdata, sslh.length, pos);
+
+ PR_fprintf(PR_STDOUT, " }\n");
+ } /* end of ssl version 3 */
+ break;
+ default:
+ PR_fprintf(PR_STDOUT, " UNDEFINED VERSION %d.%d {...}\n",
+ sr->ver_maj, sr->ver_min);
+ if (sslhexparse)
+ print_hex(sslh.length, hsdata);
+ break;
+ } /* end of switch sr->ver_maj */
+ break;
+
+ case 2: /* server hello */
+ {
+ unsigned int sidlength, pos;
+
+ PR_fprintf(PR_STDOUT, " ServerHello {\n");
+
+ PR_fprintf(PR_STDOUT, " server_version = {%d, %d}\n",
+ (PRUint8)hsdata[0], (PRUint8)hsdata[1]);
+ PR_fprintf(PR_STDOUT, " random = {...}\n");
+ if (sslhexparse)
+ print_hex(32, &hsdata[2]);
+ PR_fprintf(PR_STDOUT, " session ID = {\n");
+ sidlength = (int)hsdata[2 +
+ 32];
+ PR_fprintf(PR_STDOUT, " length = %d\n", sidlength);
+ PR_fprintf(PR_STDOUT, " contents = {...}\n");
+ if (sslhexparse)
+ print_hex(sidlength, &hsdata[2 + 32 + 1]);
+ PR_fprintf(PR_STDOUT, " }\n");
+ pos = 2 +
+ 32 + 1 +
+ sidlength;
+
+ /* pretty print chosen cipher suite */
+ {
+ PRUint32 cs_int = GET_SHORT((hsdata + pos));
+ const char *cs_str =
+ V2CipherString(cs_int);
+ PR_fprintf(PR_STDOUT, " cipher_suite = (0x%04x) %s\n",
+ cs_int, cs_str);
+ currentcipher =
+ cs_int;
+ pos +=
+ 2;
+ }
+ /* pretty print chosen compression method */
+ {
+ PRUint32 cm_int = hsdata[pos++];
+ const char *cm_str =
+ CompressionMethodString(cm_int);
+ PR_fprintf(PR_STDOUT, " compression method = (%02x) %s\n",
+ cm_int, cm_str);
+ }
+
+ /* pretty print extensions, if any */
+ pos = print_hello_extension(hsdata, sslh.length, pos);
+
+ PR_fprintf(PR_STDOUT, " }\n");
+ } break;
+
+ case 4: /* new session ticket */
+ {
+ PRUint32 lifetimehint;
+ PRUint16 ticketlength;
+ char lifetime[32];
+ lifetimehint = GET_32(hsdata);
+ if (lifetimehint) {
+ PRExplodedTime et;
+ PRTime t =
+ lifetimehint;
+ t *=
+ PR_USEC_PER_SEC;
+ PR_ExplodeTime(t, PR_GMTParameters, &et);
+ /* use HTTP Cookie header's date format */
+ PR_FormatTimeUSEnglish(lifetime, sizeof lifetime,
+ "%a, %d-%b-%Y %H:%M:%S GMT", &et);
+ } else {
+ /* 0 means the lifetime of the ticket is unspecified */
+ strcpy(lifetime, "unspecified");
+ }
+ ticketlength = GET_SHORT((hsdata +
+ 4));
+ PR_fprintf(PR_STDOUT, " NewSessionTicket {\n");
+ PR_fprintf(PR_STDOUT, " ticket_lifetime_hint = %s\n",
+ lifetime);
+ PR_fprintf(PR_STDOUT, " ticket = {\n");
+ PR_fprintf(PR_STDOUT, " length = %d\n", ticketlength);
+ PR_fprintf(PR_STDOUT, " contents = {...}\n");
+ if (sslhexparse)
+ print_hex(ticketlength, &hsdata[4 + 2]);
+ PR_fprintf(PR_STDOUT, " }\n");
+ PR_fprintf(PR_STDOUT, " }\n");
+ } break;
+
+ case 11: /* certificate */
+ {
+ PRFileDesc *cfd;
+ int pos;
+ int certslength;
+ int certlength;
+ int certbytesread = 0;
+ static int certFileNumber;
+ char certFileName[20];
+
+ PR_fprintf(PR_STDOUT, " CertificateChain {\n");
+ certslength = GET_24(hsdata);
+ PR_fprintf(PR_STDOUT, " chainlength = %d (0x%04x)\n",
+ certslength, certslength);
+ pos = 3;
+ while (certbytesread < certslength) {
+ certlength =
+ GET_24((hsdata + pos));
+ pos +=
+ 3;
+ PR_fprintf(PR_STDOUT, " Certificate {\n");
+ PR_fprintf(PR_STDOUT, " size = %d (0x%04x)\n",
+ certlength, certlength);
+ certbytesread +=
+ certlength + 3;
+ if (certbytesread <=
+ certslength) {
+ PR_snprintf(certFileName, sizeof certFileName, "cert.%03d",
+ ++certFileNumber);
+ cfd =
+ PR_Open(certFileName, PR_WRONLY |
+ PR_CREATE_FILE | PR_TRUNCATE,
+ 0664);
+ if (!cfd) {
+ PR_fprintf(PR_STDOUT,
+ " data = { couldn't save file '%s' }\n",
+ certFileName);
+ } else {
+ PR_Write(cfd, (hsdata +
+ pos),
+ certlength);
+ PR_fprintf(PR_STDOUT,
+ " data = { saved in file '%s' }\n",
+ certFileName);
+ PR_Close(cfd);
+ }
+ }
+
+ PR_fprintf(PR_STDOUT, " }\n");
+ pos += certlength;
+ }
+ PR_fprintf(PR_STDOUT, " }\n");
+ } break;
+
+ case 12: /* server_key_exchange */
+ if (sslhexparse)
+ print_hex(sslh.length, hsdata);
+ break;
+
+ case 13: /* certificate request */
+ {
+ unsigned int pos = 0;
+ int w, reqLength;
+
+ PR_fprintf(PR_STDOUT, " CertificateRequest {\n");
+
+ /* pretty print requested certificate types */
+ reqLength = hsdata[pos];
+ PR_fprintf(PR_STDOUT, " certificate types[%d] = {",
+ reqLength);
+ for (w =
+ 0;
+ w < reqLength; w++) {
+ PR_fprintf(PR_STDOUT, " %02x", hsdata[pos +
+ 1 + w]);
+ }
+ pos += 1 + reqLength;
+ PR_fprintf(PR_STDOUT, " }\n");
+
+ /* pretty print CA names, if any */
+ if (pos < sslh.length) {
+ int exListLen =
+ GET_SHORT((hsdata + pos));
+ pos += 2;
+ PR_fprintf(PR_STDOUT,
+ " certificate_authorities[%d] = {\n",
+ exListLen);
+ while (exListLen >
+ 0 &&
+ pos < sslh.length) {
+ char *ca_name;
+ SECItem it;
+ int dnLen = GET_SHORT((hsdata +
+ pos));
+ pos += 2;
+
+ /* dump the CA name */
+ it.type =
+ siBuffer;
+ it.data =
+ hsdata + pos;
+ it.len =
+ dnLen;
+ ca_name =
+ CERT_DerNameToAscii(&it);
+ if (ca_name) {
+ PR_fprintf(PR_STDOUT, " %s\n", ca_name);
+ PORT_Free(ca_name);
+ } else {
+ PR_fprintf(PR_STDOUT,
+ " distinguished name [%d]", dnLen);
+ if (dnLen >
+ 0 &&
+ sslhexparse) {
+ PR_fprintf(PR_STDOUT, " = {\n");
+ print_hex(dnLen, hsdata +
+ pos);
+ PR_fprintf(PR_STDOUT, " }\n");
+ } else {
+ PR_fprintf(PR_STDOUT, "\n");
+ }
+ }
+ pos +=
+ dnLen;
+ exListLen -=
+ 2 + dnLen;
+ }
+ PR_fprintf(PR_STDOUT, " }\n");
+ }
+
+ PR_fprintf(PR_STDOUT, " }\n");
+ } break;
+
+ case 14: /* server_hello_done */ /* not much to show here. */
+ break;
+
+ case 15: /* certificate_verify */
+ if (sslhexparse)
+ print_hex(sslh.length, hsdata);
+ break;
+
+ case 16: /* client key exchange */
+ {
+ PR_fprintf(PR_STDOUT, " ClientKeyExchange {\n");
+ PR_fprintf(PR_STDOUT, " message = {...}\n");
+ PR_fprintf(PR_STDOUT, " }\n");
+ } break;
+
+ case 20: /* finished */
+ PR_fprintf(PR_STDOUT, " Finished {\n");
+ PR_fprintf(PR_STDOUT, " verify_data = {...}\n");
+ if (sslhexparse)
+ print_hex(sslh.length, hsdata);
+ PR_fprintf(PR_STDOUT, " }\n");
+
+ if (!isNULLmac(currentcipher) &&
+ !s->hMACsize) {
+ /* To calculate the size of MAC, we subtract the number of known
+ * bytes of message from the number of remaining bytes in the
+ * record. This assumes that this is the first record on the
+ * connection to have a MAC, and that the sender has not put another
+ * message after the finished message in the handshake record.
+ * This is only correct for the first transition from unMACed to
+ * MACed. If the connection switches from one cipher suite to
+ * another one with a different MAC, this logic will not track that
+ * change correctly.
+ */
+ s->hMACsize =
+ recordLen - (sslh.length + 4);
+ sslh.length +=
+ s->hMACsize; /* skip over the MAC data */
+ }
+ break;
+
+ case 22: /* certificate_status */
+ {
+ SECItem data;
+ PRFileDesc *ofd;
+ static int ocspFileNumber;
+ char ocspFileName[20];
+
+ /* skip 4 bytes with handshake numbers, as in ssl3_HandleCertificateStatus */
+ data.type = siBuffer;
+ data.data = hsdata + 4;
+ data.len = sslh.length - 4;
+ print_status_response(&data);
+
+ PR_snprintf(ocspFileName, sizeof ocspFileName, "ocsp.%03d",
+ ++ocspFileNumber);
+ ofd = PR_Open(ocspFileName, PR_WRONLY |
+ PR_CREATE_FILE | PR_TRUNCATE,
+ 0664);
+ if (!ofd) {
+ PR_fprintf(PR_STDOUT,
+ " data = { couldn't save file '%s' }\n",
+ ocspFileName);
+ } else {
+ PR_Write(ofd, data.data, data.len);
+ PR_fprintf(PR_STDOUT,
+ " data = { saved in file '%s' }\n",
+ ocspFileName);
+ PR_Close(ofd);
+ }
+ } break;
+
+ default: {
+ PR_fprintf(PR_STDOUT, " UNKNOWN MESSAGE TYPE %d [%d] {\n",
+ sslh.type, sslh.length);
+ if (sslhexparse)
+ print_hex(sslh.length, hsdata);
+ PR_fprintf(PR_STDOUT, " }\n");
+ }
+ } /* end of switch sslh.type */
+ offset += sslh.length + 4;
+ } /* while */
+ if (offset < recordLen) { /* stuff left over */
+ unsigned int newMsgLen = recordLen - offset;
+ if (!s->msgBuf) {
+ s->msgBuf = PORT_Alloc(newMsgLen);
+ if (!s->msgBuf) {
+ PR_ASSERT(s->msgBuf);
+ showErr("Malloc failed");
+ exit(11);
+ }
+ s->msgBufSize = newMsgLen;
+ memcpy(s->msgBuf, recordBuf + offset, newMsgLen);
+ } else if (newMsgLen > s->msgBufSize) {
+ unsigned char *newBuf = PORT_Realloc(s->msgBuf, newMsgLen);
+ if (!newBuf) {
+ PR_ASSERT(newBuf);
+ showErr("Realloc failed");
+ exit(12);
+ }
+ s->msgBuf = newBuf;
+ s->msgBufSize = newMsgLen;
+ } else if (offset || s->msgBuf != recordBuf) {
+ memmove(s->msgBuf, recordBuf + offset, newMsgLen);
+ }
+ s->msgBufOffset = newMsgLen;
+ PR_fprintf(PR_STDOUT, " [incomplete handshake message]\n");
+ } else {
+ s->msgBufOffset = 0;
+ }
+ PR_fprintf(PR_STDOUT, " }\n");
+}
+
+void
+print_ssl(DataBufferList *s, int length, unsigned char *buffer)
+{
+ /* -------------------------------------------------------- */
+ /* first, create a new buffer object for this piece of data. */
+
+ DataBuffer *db;
+
+ if (s->size == 0 && length > 0 && buffer[0] >= 32 && buffer[0] < 128) {
+ /* Not an SSL record, treat entire buffer as plaintext */
+ PR_Write(PR_STDOUT, buffer, length);
+ return;
+ }
+
+ check_integrity(s);
+
+ db = PR_NEW(struct _DataBuffer);
+
+ if (!db) {
+ return;
+ }
+
+ db->buffer = (unsigned char *)PORT_Alloc(length);
+ db->length = length;
+ db->offset = 0;
+ memcpy(db->buffer, buffer, length);
+ db->next = NULL;
+
+ /* now, add it to the stream */
+
+ if (s->last != NULL)
+ s->last->next = db;
+ s->last = db;
+ s->size += length;
+ if (s->first == NULL)
+ s->first = db;
+
+ check_integrity(s);
+
+ /*------------------------------------------------------- */
+ /* now we look at the stream to see if we have enough data to
+ decode */
+
+ while (s->size > 0) {
+ unsigned char *recordBuf = NULL;
+
+ SSLRecord sr;
+ unsigned recordLen;
+ unsigned recordsize;
+
+ check_integrity(s);
+
+ if (s->first == NULL) {
+ PR_fprintf(PR_STDOUT, "ERROR: s->first is null\n");
+ exit(9);
+ }
+
+ /* in the case of an SSL 2 client-hello */
+ /* will have the high-bit set, whereas an SSL 3 client-hello will not */
+ /* SSL2 can also send records that begin with the high bit clear.
+ * This code will incorrectly handle them. XXX
+ */
+ if (isV2Session || s->first->buffer[s->first->offset] & 0x80) {
+ /* it's an SSL 2 packet */
+ unsigned char lenbuf[3];
+
+ /* first, we check if there's enough data for it to be an SSL2-type
+ * record. What a pain.*/
+ if (s->size < sizeof lenbuf) {
+ partial_packet(length, s->size, sizeof lenbuf);
+ return;
+ }
+
+ /* read the first two bytes off the stream. */
+ read_stream_bytes(lenbuf, s, sizeof(lenbuf));
+ recordLen = ((unsigned int)(lenbuf[0] & 0x7f) << 8) + lenbuf[1] +
+ ((lenbuf[0] & 0x80) ? 2 : 3);
+ PR_fprintf(PR_STDOUT, "recordLen = %u bytes\n", recordLen);
+
+ /* put 'em back on the head of the stream. */
+ db = PR_NEW(struct _DataBuffer);
+
+ db->length = sizeof lenbuf;
+ db->buffer = (unsigned char *)PORT_Alloc(db->length);
+ db->offset = 0;
+ memcpy(db->buffer, lenbuf, sizeof lenbuf);
+
+ db->next = s->first;
+ s->first = db;
+ if (s->last == NULL)
+ s->last = db;
+ s->size += db->length;
+
+ /* if there wasn't enough, go back for more. */
+ if (s->size < recordLen) {
+ check_integrity(s);
+ partial_packet(length, s->size, recordLen);
+ return;
+ }
+ partial_packet(length, s->size, recordLen);
+
+ /* read in the whole record. */
+ recordBuf = PORT_Alloc(recordLen);
+ read_stream_bytes(recordBuf, s, recordLen);
+
+ print_sslv2(s, recordBuf, recordLen);
+ PR_FREEIF(recordBuf);
+ check_integrity(s);
+
+ continue;
+ }
+
+ /***********************************************************/
+ /* It's SSL v3 */
+ /***********************************************************/
+ check_integrity(s);
+
+ if (s->size < sizeof sr) {
+ partial_packet(length, s->size, sizeof(SSLRecord));
+ return;
+ }
+
+ read_stream_bytes((unsigned char *)&sr, s, sizeof sr);
+
+ /* we have read the stream bytes. Look at the length of
+ the ssl record. If we don't have enough data to satisfy this
+ request, then put the bytes we just took back at the head
+ of the queue */
+ recordsize = GET_SHORT(sr.length);
+
+ if (recordsize > s->size) {
+ db = PR_NEW(struct _DataBuffer);
+
+ db->length = sizeof sr;
+ db->buffer = (unsigned char *)PORT_Alloc(db->length);
+ db->offset = 0;
+ memcpy(db->buffer, &sr, sizeof sr);
+ db->next = s->first;
+
+ /* now, add it back on to the head of the stream */
+
+ s->first = db;
+ if (s->last == NULL)
+ s->last = db;
+ s->size += db->length;
+
+ check_integrity(s);
+ partial_packet(length, s->size, recordsize);
+ return;
+ }
+ partial_packet(length, s->size, recordsize);
+
+ PR_fprintf(PR_STDOUT, "SSLRecord { [%s]\n", get_time_string());
+ if (sslhexparse) {
+ print_hex(5, (unsigned char *)&sr);
+ }
+
+ check_integrity(s);
+
+ PR_fprintf(PR_STDOUT, " type = %d (", sr.type);
+ switch (sr.type) {
+ case 20:
+ PR_fprintf(PR_STDOUT, "change_cipher_spec)\n");
+ break;
+ case 21:
+ PR_fprintf(PR_STDOUT, "alert)\n");
+ break;
+ case 22:
+ PR_fprintf(PR_STDOUT, "handshake)\n");
+ break;
+ case 23:
+ PR_fprintf(PR_STDOUT, "application_data)\n");
+ break;
+ default:
+ PR_fprintf(PR_STDOUT, "unknown)\n");
+ break;
+ }
+ PR_fprintf(PR_STDOUT, " version = { %d,%d }\n",
+ (PRUint32)sr.ver_maj, (PRUint32)sr.ver_min);
+ PR_fprintf(PR_STDOUT, " length = %d (0x%x)\n",
+ (PRUint32)GET_SHORT(sr.length), (PRUint32)GET_SHORT(sr.length));
+
+ recordLen = recordsize;
+ PR_ASSERT(s->size >= recordLen);
+ if (s->size >= recordLen) {
+ recordBuf = (unsigned char *)PORT_Alloc(recordLen);
+ read_stream_bytes(recordBuf, s, recordLen);
+
+ if (s->isEncrypted) {
+ PR_fprintf(PR_STDOUT, " < encrypted >\n");
+ } else { /* not encrypted */
+
+ switch (sr.type) {
+ case 20: /* change_cipher_spec */
+ if (sslhexparse)
+ print_hex(recordLen - s->hMACsize, recordBuf);
+ /* mark to say we can only dump hex form now on
+ * if it is not one on a null cipher */
+ s->isEncrypted =
+ isNULLcipher(currentcipher) ? 0 : 1;
+ break;
+
+ case 21: /* alert */
+ switch (recordBuf[0]) {
+ case 1:
+ PR_fprintf(PR_STDOUT, " warning: ");
+ break;
+ case 2:
+ PR_fprintf(PR_STDOUT, " fatal: ");
+ break;
+ default:
+ PR_fprintf(PR_STDOUT, " unknown level %d: ", recordBuf[0]);
+ break;
+ }
+
+ switch (recordBuf[1]) {
+ case 0:
+ PR_FPUTS("close_notify\n");
+ break;
+ case 10:
+ PR_FPUTS("unexpected_message\n");
+ break;
+ case 20:
+ PR_FPUTS("bad_record_mac\n");
+ break;
+ case 21:
+ PR_FPUTS("decryption_failed\n");
+ break;
+ case 22:
+ PR_FPUTS("record_overflow\n");
+ break;
+ case 30:
+ PR_FPUTS("decompression_failure\n");
+ break;
+ case 40:
+ PR_FPUTS("handshake_failure\n");
+ break;
+ case 41:
+ PR_FPUTS("no_certificate\n");
+ break;
+ case 42:
+ PR_FPUTS("bad_certificate\n");
+ break;
+ case 43:
+ PR_FPUTS("unsupported_certificate\n");
+ break;
+ case 44:
+ PR_FPUTS("certificate_revoked\n");
+ break;
+ case 45:
+ PR_FPUTS("certificate_expired\n");
+ break;
+ case 46:
+ PR_FPUTS("certificate_unknown\n");
+ break;
+ case 47:
+ PR_FPUTS("illegal_parameter\n");
+ break;
+ case 48:
+ PR_FPUTS("unknown_ca\n");
+ break;
+ case 49:
+ PR_FPUTS("access_denied\n");
+ break;
+ case 50:
+ PR_FPUTS("decode_error\n");
+ break;
+ case 51:
+ PR_FPUTS("decrypt_error\n");
+ break;
+ case 60:
+ PR_FPUTS("export_restriction\n");
+ break;
+ case 70:
+ PR_FPUTS("protocol_version\n");
+ break;
+ case 71:
+ PR_FPUTS("insufficient_security\n");
+ break;
+ case 80:
+ PR_FPUTS("internal_error\n");
+ break;
+ case 90:
+ PR_FPUTS("user_canceled\n");
+ break;
+ case 100:
+ PR_FPUTS("no_renegotiation\n");
+ break;
+ case 110:
+ PR_FPUTS("unsupported_extension\n");
+ break;
+ case 111:
+ PR_FPUTS("certificate_unobtainable\n");
+ break;
+ case 112:
+ PR_FPUTS("unrecognized_name\n");
+ break;
+ case 113:
+ PR_FPUTS("bad_certificate_status_response\n");
+ break;
+ case 114:
+ PR_FPUTS("bad_certificate_hash_value\n");
+ break;
+
+ default:
+ PR_fprintf(PR_STDOUT, "unknown alert %d\n", recordBuf[1]);
+ break;
+ }
+
+ if (sslhexparse)
+ print_hex(recordLen - s->hMACsize, recordBuf);
+ break;
+
+ case 22: /* handshake */
+ print_ssl3_handshake(recordBuf, recordLen -
+ s->hMACsize,
+ &sr, s);
+ break;
+
+ case 23: /* application data */
+ print_hex(recordLen -
+ s->hMACsize,
+ recordBuf);
+ break;
+
+ default:
+ print_hex(recordLen -
+ s->hMACsize,
+ recordBuf);
+ break;
+ }
+ if (s->hMACsize) {
+ PR_fprintf(PR_STDOUT, " MAC = {...}\n");
+ if (sslhexparse) {
+ unsigned char *offset =
+ recordBuf + (recordLen - s->hMACsize);
+ print_hex(s->hMACsize, offset);
+ }
+ }
+ } /* not encrypted */
+ }
+ PR_fprintf(PR_STDOUT, "}\n");
+ PR_FREEIF(recordBuf);
+ check_integrity(s);
+ }
+}
+
+void
+print_hex(int amt, unsigned char *buf)
+{
+ int i, j, k;
+ char t[20];
+ static char string[5000];
+
+ for (i = 0; i < amt; i++) {
+ t[1] = 0;
+
+ if (i % 16 == 0) { /* if we are at the beginning of a line */
+ PR_fprintf(PR_STDOUT, "%4x:", i); /* print the line number */
+ strcpy(string, "");
+ }
+
+ if (i % 4 == 0) {
+ PR_fprintf(PR_STDOUT, " ");
+ }
+
+ j = buf[i];
+
+ t[0] = (j >= 0x20 && j < 0x80) ? j : '.';
+
+ if (fancy) {
+ switch (t[0]) {
+ case '<':
+ strcpy(t, "&lt;");
+ break;
+ case '>':
+ strcpy(t, "&gt;");
+ break;
+ case '&':
+ strcpy(t, "&amp;");
+ break;
+ }
+ }
+ strcat(string, t);
+
+ PR_fprintf(PR_STDOUT, "%02x ", (PRUint8)buf[i]);
+
+ /* if we've reached the end of the line - add the string */
+ if (i % 16 == 15)
+ PR_fprintf(PR_STDOUT, " | %s\n", string);
+ }
+ /* we reached the end of the buffer,*/
+ /* do we have buffer left over? */
+ j = i % 16;
+ if (j > 0) {
+ for (k = 0; k < (16 -
+ j);
+ k++) {
+ /* print additional space after every four bytes */
+ if ((k + j) % 4 == 0) {
+ PR_fprintf(PR_STDOUT, " ");
+ }
+ PR_fprintf(PR_STDOUT, " ");
+ }
+ PR_fprintf(PR_STDOUT, " | %s\n", string);
+ }
+}
+
+void
+Usage(void)
+{
+ PR_fprintf(PR_STDERR, "SSLTAP (C) 1997, 1998 Netscape Communications Corporation.\n");
+ PR_fprintf(PR_STDERR, "Usage: ssltap [-vhfsxl] [-p port] hostname:port\n");
+ PR_fprintf(PR_STDERR, " -v [prints version string]\n");
+ PR_fprintf(PR_STDERR, " -h [outputs hex instead of ASCII]\n");
+ PR_fprintf(PR_STDERR, " -f [turn on Fancy HTML coloring]\n");
+ PR_fprintf(PR_STDERR, " -s [turn on SSL decoding]\n");
+ PR_fprintf(PR_STDERR, " -x [turn on extra SSL hex dumps]\n");
+ PR_fprintf(PR_STDERR, " -p port [specify rendezvous port (default 1924)]\n");
+ PR_fprintf(PR_STDERR, " -l [loop - continue to wait for more connections]\n");
+}
+
+void
+showErr(const char *msg)
+{
+ PRErrorCode err = PR_GetError();
+ const char *errString;
+
+ if (err == PR_UNKNOWN_ERROR)
+ err = PR_CONNECT_RESET_ERROR; /* bug in NSPR. */
+ errString = SECU_Strerror(err);
+
+ if (!errString)
+ errString = "(no text available)";
+ PR_fprintf(PR_STDERR, "%s: Error %d: %s: %s", progName, err, errString, msg);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *hostname = NULL;
+ PRUint16 rendport = DEFPORT, port;
+ PRAddrInfo *ai;
+ void *iter;
+ PRStatus r;
+ PRNetAddr na_client, na_server, na_rend;
+ PRFileDesc *s_server, *s_client, *s_rend; /*rendezvous */
+ int c_count = 0;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus rv;
+
+ progName = argv[0];
+ optstate = PL_CreateOptState(argc, argv, "fxhslp:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'f':
+ fancy++;
+ break;
+ case 'h':
+ hexparse++;
+ break;
+ case 's':
+ sslparse++;
+ break;
+ case 'x':
+ sslhexparse++;
+ break;
+ case 'l':
+ looparound++;
+ break;
+ case 'p':
+ rendport =
+ atoi(optstate->value);
+ break;
+ case '\0':
+ hostname =
+ PL_strdup(optstate->value);
+ }
+ }
+ if (status == PL_OPT_BAD)
+ Usage();
+
+ if (fancy) {
+ if (!hexparse && !sslparse) {
+ PR_fprintf(PR_STDERR,
+ "Note: use of -f without -s or -h not recommended, \n"
+ "as the output looks a little strange. It may be useful, however\n");
+ }
+ }
+
+ if (!hostname)
+ Usage(), exit(2);
+
+ {
+ char *colon = (char *)strchr(hostname, ':');
+ if (!colon) {
+ PR_fprintf(PR_STDERR,
+ "You must specify the host AND port you wish to connect to\n");
+ Usage(), exit(3);
+ }
+ port = atoi(&colon[1]);
+ *colon = '\0';
+
+ if (port == 0) {
+ PR_fprintf(PR_STDERR, "Port must be a nonzero number.\n");
+ exit(4);
+ }
+ }
+
+ /* find the 'server' IP address so we don't have to look it up later */
+
+ if (fancy) {
+ PR_fprintf(PR_STDOUT, "<HTML><HEAD><TITLE>SSLTAP output</TITLE></HEAD>\n");
+ PR_fprintf(PR_STDOUT, "<BODY><PRE>\n");
+ }
+ PR_fprintf(PR_STDERR, "Looking up \"%s\"...\n", hostname);
+ ai = PR_GetAddrInfoByName(hostname, PR_AF_UNSPEC, PR_AI_ADDRCONFIG);
+ if (!ai) {
+ showErr("Host Name lookup failed\n");
+ exit(5);
+ }
+
+ iter = NULL;
+ iter = PR_EnumerateAddrInfo(iter, ai, port, &na_server);
+ /* set up the port which the client will connect to */
+
+ r = PR_InitializeNetAddr(PR_IpAddrAny, rendport, &na_rend);
+ if (r == PR_FAILURE) {
+ PR_fprintf(PR_STDERR,
+ "PR_InitializeNetAddr(,%d,) failed with error %d\n", PR_GetError());
+ exit(0);
+ }
+
+ rv = NSS_NoDB_Init("");
+ if (rv != SECSuccess) {
+ PR_fprintf(PR_STDERR,
+ "NSS_NoDB_Init() failed with error %d\n", PR_GetError());
+ exit(5);
+ }
+
+ s_rend = PR_NewTCPSocket();
+ if (!s_rend) {
+ showErr("Couldn't create socket\n");
+ exit(6);
+ }
+
+ if (PR_Bind(s_rend, &na_rend)) {
+ PR_fprintf(PR_STDERR, "Couldn't bind to port %d (error %d)\n", rendport, PR_GetError());
+ exit(-1);
+ }
+
+ if (PR_Listen(s_rend, 5)) {
+ showErr("Couldn't listen\n");
+ exit(-1);
+ }
+
+ PR_fprintf(PR_STDERR, "Proxy socket ready and listening\n");
+ do { /* accept one connection and process it. */
+ PRPollDesc pds[2];
+
+ s_client = PR_Accept(s_rend, &na_client, PR_SecondsToInterval(3600));
+ if (s_client == NULL) {
+ showErr("accept timed out\n");
+ exit(7);
+ }
+
+ s_server = PR_OpenTCPSocket(na_server.raw.family);
+ if (s_server == NULL) {
+ showErr("couldn't open new socket to connect to server \n");
+ exit(8);
+ }
+
+ r = PR_Connect(s_server, &na_server, PR_SecondsToInterval(5));
+
+ if (r == PR_FAILURE) {
+ showErr("Couldn't connect\n");
+ return -1;
+ }
+
+ if (looparound) {
+ if (fancy)
+ PR_fprintf(PR_STDOUT, "<p><HR><H2>");
+ PR_fprintf(PR_STDOUT, "Connection #%d [%s]\n", c_count + 1,
+ get_time_string());
+ if (fancy)
+ PR_fprintf(PR_STDOUT, "</H2>");
+ }
+
+ PR_fprintf(PR_STDOUT, "Connected to %s:%d\n", hostname, port);
+
+#define PD_C 0
+#define PD_S 1
+
+ pds[PD_C].fd = s_client;
+ pds[PD_S].fd = s_server;
+ pds[PD_C].in_flags = PR_POLL_READ;
+ pds[PD_S].in_flags = PR_POLL_READ;
+
+ /* make sure the new connections don't start out encrypted. */
+ clientstream.isEncrypted = 0;
+ serverstream.isEncrypted = 0;
+ isV2Session = 0;
+
+ while ((pds[PD_C].in_flags & PR_POLL_READ) != 0 ||
+ (pds[PD_S].in_flags & PR_POLL_READ) != 0) { /* Handle all messages on the connection */
+ PRInt32 amt;
+ PRInt32 wrote;
+ unsigned char buffer[TAPBUFSIZ];
+
+ amt = PR_Poll(pds, 2, PR_INTERVAL_NO_TIMEOUT);
+ if (amt <= 0) {
+ if (amt)
+ showErr("PR_Poll failed.\n");
+ else
+ showErr("PR_Poll timed out.\n");
+ break;
+ }
+
+ if (pds[PD_C].out_flags & PR_POLL_EXCEPT) {
+ showErr("Exception on client-side socket.\n");
+ break;
+ }
+
+ if (pds[PD_S].out_flags & PR_POLL_EXCEPT) {
+ showErr("Exception on server-side socket.\n");
+ break;
+ }
+
+ /* read data, copy it to stdout, and write to other socket */
+
+ if ((pds[PD_C].in_flags & PR_POLL_READ) != 0 &&
+ (pds[PD_C].out_flags & PR_POLL_READ) != 0) {
+
+ amt = PR_Read(s_client, buffer, sizeof(buffer));
+
+ if (amt < 0) {
+ showErr("Client socket read failed.\n");
+ break;
+ }
+
+ if (amt == 0) {
+ PR_fprintf(PR_STDOUT, "Read EOF on Client socket. [%s]\n",
+ get_time_string());
+ pds[PD_C].in_flags &= ~PR_POLL_READ;
+ PR_Shutdown(s_server, PR_SHUTDOWN_SEND);
+ continue;
+ }
+
+ PR_fprintf(PR_STDOUT, "--> [\n");
+ if (fancy)
+ PR_fprintf(PR_STDOUT, "<font color=blue>");
+
+ if (hexparse)
+ print_hex(amt, buffer);
+ if (sslparse)
+ print_ssl(&clientstream, amt, buffer);
+ if (!hexparse && !sslparse)
+ PR_Write(PR_STDOUT, buffer, amt);
+ if (fancy)
+ PR_fprintf(PR_STDOUT, "</font>");
+ PR_fprintf(PR_STDOUT, "]\n");
+
+ wrote = PR_Write(s_server, buffer, amt);
+ if (wrote != amt) {
+ if (wrote < 0) {
+ showErr("Write to server socket failed.\n");
+ break;
+ } else {
+ PR_fprintf(PR_STDERR, "Short write to server socket!\n");
+ }
+ }
+ } /* end of read from client socket. */
+
+ /* read data, copy it to stdout, and write to other socket */
+ if ((pds[PD_S].in_flags & PR_POLL_READ) != 0 &&
+ (pds[PD_S].out_flags & PR_POLL_READ) != 0) {
+
+ amt = PR_Read(s_server, buffer, sizeof(buffer));
+
+ if (amt < 0) {
+ showErr("error on server-side socket.\n");
+ break;
+ }
+
+ if (amt == 0) {
+ PR_fprintf(PR_STDOUT, "Read EOF on Server socket. [%s]\n",
+ get_time_string());
+ pds[PD_S].in_flags &= ~PR_POLL_READ;
+ PR_Shutdown(s_client, PR_SHUTDOWN_SEND);
+ continue;
+ }
+
+ PR_fprintf(PR_STDOUT, "<-- [\n");
+ if (fancy)
+ PR_fprintf(PR_STDOUT, "<font color=red>");
+ if (hexparse)
+ print_hex(amt, (unsigned char *)buffer);
+ if (sslparse)
+ print_ssl(&serverstream, amt, (unsigned char *)buffer);
+ if (!hexparse && !sslparse)
+ PR_Write(PR_STDOUT, buffer, amt);
+ if (fancy)
+ PR_fprintf(PR_STDOUT, "</font>");
+ PR_fprintf(PR_STDOUT, "]\n");
+
+ wrote = PR_Write(s_client, buffer, amt);
+ if (wrote != amt) {
+ if (wrote < 0) {
+ showErr("Write to client socket failed.\n");
+ break;
+ } else {
+ PR_fprintf(PR_STDERR, "Short write to client socket!\n");
+ }
+ }
+
+ } /* end of read from server socket. */
+
+ /* Loop, handle next message. */
+
+ } /* handle messages during a connection loop */
+ PR_Close(s_client);
+ PR_Close(s_server);
+ flush_stream(&clientstream);
+ flush_stream(&serverstream);
+ /* Connection is closed, so reset the current cipher */
+ currentcipher = 0;
+ c_count++;
+ PR_fprintf(PR_STDERR, "Connection %d Complete [%s]\n", c_count,
+ get_time_string());
+ } while (looparound); /* accept connection and process it. */
+ PR_Close(s_rend);
+ NSS_Shutdown();
+ return 0;
+}
diff --git a/security/nss/cmd/ssltap/ssltap.gyp b/security/nss/cmd/ssltap/ssltap.gyp
new file mode 100644
index 000000000..9743ac262
--- /dev/null
+++ b/security/nss/cmd/ssltap/ssltap.gyp
@@ -0,0 +1,25 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'ssltap',
+ 'type': 'executable',
+ 'sources': [
+ 'ssltap.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/strsclnt/Makefile b/security/nss/cmd/strsclnt/Makefile
new file mode 100644
index 000000000..6e1d4ecdf
--- /dev/null
+++ b/security/nss/cmd/strsclnt/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/strsclnt/manifest.mn b/security/nss/cmd/strsclnt/manifest.mn
new file mode 100644
index 000000000..fc00b6922
--- /dev/null
+++ b/security/nss/cmd/strsclnt/manifest.mn
@@ -0,0 +1,19 @@
+#
+# 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/.
+CORE_DEPTH = ../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = strsclnt.c
+
+# the MODULE above is always implicitly REQUIREd
+REQUIRES = seccmd dbm
+
+PROGRAM = strsclnt
+# PROGRAM = ./$(OBJDIR)/strsclnt.exe
+
diff --git a/security/nss/cmd/strsclnt/strsclnt.c b/security/nss/cmd/strsclnt/strsclnt.c
new file mode 100644
index 000000000..209dcca96
--- /dev/null
+++ b/security/nss/cmd/strsclnt/strsclnt.c
@@ -0,0 +1,1553 @@
+/* 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/. */
+#include <stdio.h>
+#include <string.h>
+
+#include "secutil.h"
+#include "basicutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "plgetopt.h"
+
+#include "nspr.h"
+#include "prio.h"
+#include "prnetdb.h"
+#include "prerror.h"
+
+#include "pk11func.h"
+#include "secitem.h"
+#include "sslproto.h"
+#include "nss.h"
+#include "ssl.h"
+
+#ifndef PORT_Sprintf
+#define PORT_Sprintf sprintf
+#endif
+
+#ifndef PORT_Strstr
+#define PORT_Strstr strstr
+#endif
+
+#ifndef PORT_Malloc
+#define PORT_Malloc PR_Malloc
+#endif
+
+#define RD_BUF_SIZE (60 * 1024)
+
+/* Include these cipher suite arrays to re-use tstclnt's
+ * cipher selection code.
+ */
+
+int ssl3CipherSuites[] = {
+ -1, /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
+ -1, /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA * b */
+ TLS_RSA_WITH_RC4_128_MD5, /* c */
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
+ TLS_RSA_WITH_DES_CBC_SHA, /* e */
+ -1, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 * f */
+ -1, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 * g */
+ -1, /* SSL_FORTEZZA_DMS_WITH_NULL_SHA * h */
+ TLS_RSA_WITH_NULL_MD5, /* i */
+ -1, /* SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA * j */
+ -1, /* SSL_RSA_FIPS_WITH_DES_CBC_SHA * k */
+ -1, /* TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA * l */
+ -1, /* TLS_RSA_EXPORT1024_WITH_RC4_56_SHA * m */
+ TLS_RSA_WITH_RC4_128_SHA, /* n */
+ TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */
+ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
+ TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
+ TLS_DHE_RSA_WITH_DES_CBC_SHA, /* r */
+ TLS_DHE_DSS_WITH_DES_CBC_SHA, /* s */
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* t */
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* u */
+ TLS_RSA_WITH_AES_128_CBC_SHA, /* v */
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* w */
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* x */
+ TLS_RSA_WITH_AES_256_CBC_SHA, /* y */
+ TLS_RSA_WITH_NULL_SHA, /* z */
+ 0
+};
+
+#define NO_FULLHS_PERCENTAGE -1
+
+/* This global string is so that client main can see
+ * which ciphers to use.
+ */
+
+static const char *cipherString;
+
+static PRInt32 certsTested;
+static int MakeCertOK;
+static int NoReuse;
+static int fullhs = NO_FULLHS_PERCENTAGE; /* percentage of full handshakes to
+ ** perform */
+static PRInt32 globalconid = 0; /* atomically set */
+static int total_connections; /* total number of connections to perform */
+static int total_connections_rounded_down_to_hundreds;
+static int total_connections_modulo_100;
+
+static PRBool NoDelay;
+static PRBool QuitOnTimeout = PR_FALSE;
+static PRBool ThrottleUp = PR_FALSE;
+
+static PRLock *threadLock; /* protects the global variables below */
+static PRTime lastConnectFailure;
+static PRTime lastConnectSuccess;
+static PRTime lastThrottleUp;
+static PRInt32 remaining_connections; /* number of connections left */
+static int active_threads = 8; /* number of threads currently trying to
+ ** connect */
+static PRInt32 numUsed;
+/* end of variables protected by threadLock */
+
+static SSL3Statistics *ssl3stats;
+
+static int failed_already = 0;
+static SSLVersionRange enabledVersions;
+static PRBool disableLocking = PR_FALSE;
+static PRBool ignoreErrors = PR_FALSE;
+static PRBool enableSessionTickets = PR_FALSE;
+static PRBool enableCompression = PR_FALSE;
+static PRBool enableFalseStart = PR_FALSE;
+static PRBool enableCertStatus = PR_FALSE;
+
+PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT;
+
+char *progName;
+
+secuPWData pwdata = { PW_NONE, 0 };
+
+int stopping;
+int verbose;
+SECItem bigBuf;
+
+#define PRINTF \
+ if (verbose) \
+ printf
+#define FPRINTF \
+ if (verbose) \
+ fprintf
+
+static void
+Usage(const char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-n nickname] [-p port] [-d dbdir] [-c connections]\n"
+ " [-BDNovqs] [-f filename] [-N | -P percentage]\n"
+ " [-w dbpasswd] [-C cipher(s)] [-t threads] [-W pwfile]\n"
+ " [-V [min-version]:[max-version]] [-a sniHostName] hostname\n"
+ " where -v means verbose\n"
+ " -o flag is interpreted as follows:\n"
+ " 1 -o means override the result of server certificate validation.\n"
+ " 2 -o's mean skip server certificate validation altogether.\n"
+ " -D means no TCP delays\n"
+ " -q means quit when server gone (timeout rather than retry forever)\n"
+ " -s means disable SSL socket locking\n"
+ " -N means no session reuse\n"
+ " -P means do a specified percentage of full handshakes (0-100)\n"
+ " -V [min]:[max] restricts the set of enabled SSL/TLS protocols versions.\n"
+ " All versions are enabled by default.\n"
+ " Possible values for min/max: ssl3 tls1.0 tls1.1 tls1.2\n"
+ " Example: \"-V ssl3:\" enables SSL 3 and newer.\n"
+ " -U means enable throttling up threads\n"
+ " -T enable the cert_status extension (OCSP stapling)\n"
+ " -u enable TLS Session Ticket extension\n"
+ " -z enable compression\n"
+ " -g enable false start\n",
+ progName);
+ exit(1);
+}
+
+static void
+errWarn(char *funcString)
+{
+ PRErrorCode perr = PR_GetError();
+ PRInt32 oserr = PR_GetOSError();
+ const char *errString = SECU_Strerror(perr);
+
+ fprintf(stderr, "strsclnt: %s returned error %d, OS error %d: %s\n",
+ funcString, perr, oserr, errString);
+}
+
+static void
+errExit(char *funcString)
+{
+ errWarn(funcString);
+ exit(1);
+}
+
+/**************************************************************************
+**
+** Routines for disabling SSL ciphers.
+**
+**************************************************************************/
+
+void
+disableAllSSLCiphers(void)
+{
+ const PRUint16 *cipherSuites = SSL_GetImplementedCiphers();
+ int i = SSL_GetNumImplementedCiphers();
+ SECStatus rv;
+
+ /* disable all the SSL3 cipher suites */
+ while (--i >= 0) {
+ PRUint16 suite = cipherSuites[i];
+ rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
+ if (rv != SECSuccess) {
+ printf("SSL_CipherPrefSetDefault didn't like value 0x%04x (i = %d)\n",
+ suite, i);
+ errWarn("SSL_CipherPrefSetDefault");
+ exit(2);
+ }
+ }
+}
+
+/* This invokes the "default" AuthCert handler in libssl.
+** The only reason to use this one is that it prints out info as it goes.
+*/
+static SECStatus
+mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
+ PRBool isServer)
+{
+ SECStatus rv;
+ CERTCertificate *peerCert;
+ const SECItemArray *csa;
+
+ if (MakeCertOK >= 2) {
+ return SECSuccess;
+ }
+ peerCert = SSL_PeerCertificate(fd);
+
+ PRINTF("strsclnt: Subject: %s\nstrsclnt: Issuer : %s\n",
+ peerCert->subjectName, peerCert->issuerName);
+ csa = SSL_PeerStapledOCSPResponses(fd);
+ if (csa) {
+ PRINTF("Received %d Cert Status items (OCSP stapled data)\n",
+ csa->len);
+ }
+ /* invoke the "default" AuthCert handler. */
+ rv = SSL_AuthCertificate(arg, fd, checkSig, isServer);
+
+ PR_ATOMIC_INCREMENT(&certsTested);
+ if (rv == SECSuccess) {
+ fputs("strsclnt: -- SSL: Server Certificate Validated.\n", stderr);
+ }
+ CERT_DestroyCertificate(peerCert);
+ /* error, if any, will be displayed by the Bad Cert Handler. */
+ return rv;
+}
+
+static SECStatus
+myBadCertHandler(void *arg, PRFileDesc *fd)
+{
+ PRErrorCode err = PR_GetError();
+ if (!MakeCertOK)
+ fprintf(stderr,
+ "strsclnt: -- SSL: Server Certificate Invalid, err %d.\n%s\n",
+ err, SECU_Strerror(err));
+ return (MakeCertOK ? SECSuccess : SECFailure);
+}
+
+void
+printSecurityInfo(PRFileDesc *fd)
+{
+ CERTCertificate *cert = NULL;
+ SSL3Statistics *ssl3stats = SSL_GetStatistics();
+ SECStatus result;
+ SSLChannelInfo channel;
+ SSLCipherSuiteInfo suite;
+
+ static int only_once;
+
+ if (only_once && verbose < 2)
+ return;
+ only_once = 1;
+
+ result = SSL_GetChannelInfo(fd, &channel, sizeof channel);
+ if (result == SECSuccess &&
+ channel.length == sizeof channel &&
+ channel.cipherSuite) {
+ result = SSL_GetCipherSuiteInfo(channel.cipherSuite,
+ &suite, sizeof suite);
+ if (result == SECSuccess) {
+ FPRINTF(stderr,
+ "strsclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
+ channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
+ suite.effectiveKeyBits, suite.symCipherName,
+ suite.macBits, suite.macAlgorithmName);
+ FPRINTF(stderr,
+ "strsclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n"
+ " Compression: %s\n",
+ channel.authKeyBits, suite.authAlgorithmName,
+ channel.keaKeyBits, suite.keaTypeName,
+ channel.compressionMethodName);
+ }
+ }
+
+ cert = SSL_LocalCertificate(fd);
+ if (!cert)
+ cert = SSL_PeerCertificate(fd);
+
+ if (verbose && cert) {
+ char *ip = CERT_NameToAscii(&cert->issuer);
+ char *sp = CERT_NameToAscii(&cert->subject);
+ if (sp) {
+ fprintf(stderr, "strsclnt: subject DN: %s\n", sp);
+ PORT_Free(sp);
+ }
+ if (ip) {
+ fprintf(stderr, "strsclnt: issuer DN: %s\n", ip);
+ PORT_Free(ip);
+ }
+ }
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ cert = NULL;
+ }
+ fprintf(stderr,
+ "strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n"
+ " %ld stateless resumes\n",
+ ssl3stats->hsh_sid_cache_hits,
+ ssl3stats->hsh_sid_cache_misses,
+ ssl3stats->hsh_sid_cache_not_ok,
+ ssl3stats->hsh_sid_stateless_resumes);
+}
+
+/**************************************************************************
+** Begin thread management routines and data.
+**************************************************************************/
+
+#define MAX_THREADS 128
+
+typedef SECStatus startFn(void *a, void *b, int c);
+
+static PRInt32 numConnected;
+static int max_threads; /* peak threads allowed */
+
+typedef struct perThreadStr {
+ void *a;
+ void *b;
+ int tid;
+ int rv;
+ startFn *startFunc;
+ PRThread *prThread;
+ PRBool inUse;
+} perThread;
+
+perThread threads[MAX_THREADS];
+
+void
+thread_wrapper(void *arg)
+{
+ perThread *slot = (perThread *)arg;
+ PRBool done = PR_FALSE;
+
+ do {
+ PRBool doop = PR_FALSE;
+ PRBool dosleep = PR_FALSE;
+ PRTime now = PR_Now();
+
+ PR_Lock(threadLock);
+ if (!(slot->tid < active_threads)) {
+ /* this thread isn't supposed to be running */
+ if (!ThrottleUp) {
+ /* we'll never need this thread again, so abort it */
+ done = PR_TRUE;
+ } else if (remaining_connections > 0) {
+ /* we may still need this thread, so just sleep for 1s */
+ dosleep = PR_TRUE;
+ /* the conditions to trigger a throttle up are :
+ ** 1. last PR_Connect failure must have happened more than
+ ** 10s ago
+ ** 2. last throttling up must have happened more than 0.5s ago
+ ** 3. there must be a more recent PR_Connect success than
+ ** failure
+ */
+ if ((now - lastConnectFailure > 10 * PR_USEC_PER_SEC) &&
+ ((!lastThrottleUp) || ((now - lastThrottleUp) >=
+ (PR_USEC_PER_SEC / 2))) &&
+ (lastConnectSuccess > lastConnectFailure)) {
+ /* try throttling up by one thread */
+ active_threads = PR_MIN(max_threads, active_threads + 1);
+ fprintf(stderr, "active_threads set up to %d\n",
+ active_threads);
+ lastThrottleUp = PR_MAX(now, lastThrottleUp);
+ }
+ } else {
+ /* no more connections left, we are done */
+ done = PR_TRUE;
+ }
+ } else {
+ /* this thread should run */
+ if (--remaining_connections >= 0) { /* protected by threadLock */
+ doop = PR_TRUE;
+ } else {
+ done = PR_TRUE;
+ }
+ }
+ PR_Unlock(threadLock);
+ if (doop) {
+ slot->rv = (*slot->startFunc)(slot->a, slot->b, slot->tid);
+ PRINTF("strsclnt: Thread in slot %d returned %d\n",
+ slot->tid, slot->rv);
+ }
+ if (dosleep) {
+ PR_Sleep(PR_SecondsToInterval(1));
+ }
+ } while (!done && (!failed_already || ignoreErrors));
+}
+
+SECStatus
+launch_thread(
+ startFn *startFunc,
+ void *a,
+ void *b,
+ int tid)
+{
+ PRUint32 i;
+ perThread *slot;
+
+ PR_Lock(threadLock);
+
+ PORT_Assert(numUsed < MAX_THREADS);
+ if (!(numUsed < MAX_THREADS)) {
+ PR_Unlock(threadLock);
+ return SECFailure;
+ }
+
+ i = numUsed++;
+ slot = &threads[i];
+ slot->a = a;
+ slot->b = b;
+ slot->tid = tid;
+
+ slot->startFunc = startFunc;
+
+ slot->prThread = PR_CreateThread(PR_USER_THREAD,
+ thread_wrapper, slot,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD, 0);
+ if (slot->prThread == NULL) {
+ PR_Unlock(threadLock);
+ printf("strsclnt: Failed to launch thread!\n");
+ return SECFailure;
+ }
+
+ slot->inUse = 1;
+ PR_Unlock(threadLock);
+ PRINTF("strsclnt: Launched thread in slot %d \n", i);
+
+ return SECSuccess;
+}
+
+/* join all the threads */
+int
+reap_threads(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_THREADS; ++i) {
+ if (threads[i].prThread) {
+ PR_JoinThread(threads[i].prThread);
+ threads[i].prThread = NULL;
+ }
+ }
+ return 0;
+}
+
+void
+destroy_thread_data(void)
+{
+ PORT_Memset(threads, 0, sizeof threads);
+
+ if (threadLock) {
+ PR_DestroyLock(threadLock);
+ threadLock = NULL;
+ }
+}
+
+void
+init_thread_data(void)
+{
+ threadLock = PR_NewLock();
+}
+
+/**************************************************************************
+** End thread management routines.
+**************************************************************************/
+
+PRBool useModelSocket = PR_TRUE;
+
+static const char outHeader[] = {
+ "HTTP/1.0 200 OK\r\n"
+ "Server: Netscape-Enterprise/2.0a\r\n"
+ "Date: Tue, 26 Aug 1997 22:10:05 GMT\r\n"
+ "Content-type: text/plain\r\n"
+ "\r\n"
+};
+
+struct lockedVarsStr {
+ PRLock *lock;
+ int count;
+ int waiters;
+ PRCondVar *condVar;
+};
+
+typedef struct lockedVarsStr lockedVars;
+
+void
+lockedVars_Init(lockedVars *lv)
+{
+ lv->count = 0;
+ lv->waiters = 0;
+ lv->lock = PR_NewLock();
+ lv->condVar = PR_NewCondVar(lv->lock);
+}
+
+void
+lockedVars_Destroy(lockedVars *lv)
+{
+ PR_DestroyCondVar(lv->condVar);
+ lv->condVar = NULL;
+
+ PR_DestroyLock(lv->lock);
+ lv->lock = NULL;
+}
+
+void
+lockedVars_WaitForDone(lockedVars *lv)
+{
+ PR_Lock(lv->lock);
+ while (lv->count > 0) {
+ PR_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(lv->lock);
+}
+
+int /* returns count */
+ lockedVars_AddToCount(lockedVars *lv, int addend)
+{
+ int rv;
+
+ PR_Lock(lv->lock);
+ rv = lv->count += addend;
+ if (rv <= 0) {
+ PR_NotifyCondVar(lv->condVar);
+ }
+ PR_Unlock(lv->lock);
+ return rv;
+}
+
+SECStatus
+do_writes(
+ void *a,
+ void *b,
+ int c)
+{
+ PRFileDesc *ssl_sock = (PRFileDesc *)a;
+ lockedVars *lv = (lockedVars *)b;
+ unsigned int sent = 0;
+ int count = 0;
+
+ while (sent < bigBuf.len) {
+
+ count = PR_Send(ssl_sock, bigBuf.data + sent, bigBuf.len - sent,
+ 0, maxInterval);
+ if (count < 0) {
+ errWarn("PR_Send bigBuf");
+ break;
+ }
+ FPRINTF(stderr, "strsclnt: PR_Send wrote %d bytes from bigBuf\n",
+ count);
+ sent += count;
+ }
+ if (count >= 0) { /* last write didn't fail. */
+ PR_Shutdown(ssl_sock, PR_SHUTDOWN_SEND);
+ }
+
+ /* notify the reader that we're done. */
+ lockedVars_AddToCount(lv, -1);
+ return (sent < bigBuf.len) ? SECFailure : SECSuccess;
+}
+
+int
+handle_fdx_connection(PRFileDesc *ssl_sock, int connection)
+{
+ SECStatus result;
+ int firstTime = 1;
+ int countRead = 0;
+ lockedVars lv;
+ char *buf;
+
+ lockedVars_Init(&lv);
+ lockedVars_AddToCount(&lv, 1);
+
+ /* Attempt to launch the writer thread. */
+ result = launch_thread(do_writes, ssl_sock, &lv, connection);
+
+ if (result != SECSuccess)
+ goto cleanup;
+
+ buf = PR_Malloc(RD_BUF_SIZE);
+
+ if (buf) {
+ do {
+ /* do reads here. */
+ PRInt32 count;
+
+ count = PR_Recv(ssl_sock, buf, RD_BUF_SIZE, 0, maxInterval);
+ if (count < 0) {
+ errWarn("PR_Recv");
+ break;
+ }
+ countRead += count;
+ FPRINTF(stderr,
+ "strsclnt: connection %d read %d bytes (%d total).\n",
+ connection, count, countRead);
+ if (firstTime) {
+ firstTime = 0;
+ printSecurityInfo(ssl_sock);
+ }
+ } while (lockedVars_AddToCount(&lv, 0) > 0);
+ PR_Free(buf);
+ buf = 0;
+ }
+
+ /* Wait for writer to finish */
+ lockedVars_WaitForDone(&lv);
+ lockedVars_Destroy(&lv);
+
+ FPRINTF(stderr,
+ "strsclnt: connection %d read %d bytes total. -----------------------\n",
+ connection, countRead);
+
+cleanup:
+ /* Caller closes the socket. */
+
+ return SECSuccess;
+}
+
+const char request[] = { "GET /abc HTTP/1.0\r\n\r\n" };
+
+SECStatus
+handle_connection(PRFileDesc *ssl_sock, int tid)
+{
+ int countRead = 0;
+ PRInt32 rv;
+ char *buf;
+
+ buf = PR_Malloc(RD_BUF_SIZE);
+ if (!buf)
+ return SECFailure;
+
+ /* compose the http request here. */
+
+ rv = PR_Send(ssl_sock, request, strlen(request), 0, maxInterval);
+ if (rv <= 0) {
+ errWarn("PR_Send");
+ PR_Free(buf);
+ buf = 0;
+ failed_already = 1;
+ return SECFailure;
+ }
+ printSecurityInfo(ssl_sock);
+
+ /* read until EOF */
+ while (1) {
+ rv = PR_Recv(ssl_sock, buf, RD_BUF_SIZE, 0, maxInterval);
+ if (rv == 0) {
+ break; /* EOF */
+ }
+ if (rv < 0) {
+ errWarn("PR_Recv");
+ failed_already = 1;
+ break;
+ }
+
+ countRead += rv;
+ FPRINTF(stderr,
+ "strsclnt: connection on thread %d read %d bytes (%d total).\n",
+ tid, rv, countRead);
+ }
+ PR_Free(buf);
+ buf = 0;
+
+ /* Caller closes the socket. */
+
+ FPRINTF(stderr,
+ "strsclnt: connection on thread %d read %d bytes total. ---------\n",
+ tid, countRead);
+
+ return SECSuccess; /* success */
+}
+
+#define USE_SOCK_PEER_ID 1
+
+#ifdef USE_SOCK_PEER_ID
+
+PRInt32 lastFullHandshakePeerID;
+
+void
+myHandshakeCallback(PRFileDesc *socket, void *arg)
+{
+ PR_ATOMIC_SET(&lastFullHandshakePeerID, (PRInt32)((char *)arg - (char *)NULL));
+}
+
+#endif
+
+/* one copy of this function is launched in a separate thread for each
+** connection to be made.
+*/
+SECStatus
+do_connects(
+ void *a,
+ void *b,
+ int tid)
+{
+ PRNetAddr *addr = (PRNetAddr *)a;
+ PRFileDesc *model_sock = (PRFileDesc *)b;
+ PRFileDesc *ssl_sock = 0;
+ PRFileDesc *tcp_sock = 0;
+ PRStatus prStatus;
+ PRUint32 sleepInterval = 50; /* milliseconds */
+ SECStatus rv = SECSuccess;
+ PRSocketOptionData opt;
+
+retry:
+
+ tcp_sock = PR_OpenTCPSocket(addr->raw.family);
+ if (tcp_sock == NULL) {
+ errExit("PR_OpenTCPSocket");
+ }
+
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ prStatus = PR_SetSocketOption(tcp_sock, &opt);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_SetSocketOption(PR_SockOpt_Nonblocking, PR_FALSE)");
+ PR_Close(tcp_sock);
+ return SECSuccess;
+ }
+
+ if (NoDelay) {
+ opt.option = PR_SockOpt_NoDelay;
+ opt.value.no_delay = PR_TRUE;
+ prStatus = PR_SetSocketOption(tcp_sock, &opt);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)");
+ PR_Close(tcp_sock);
+ return SECSuccess;
+ }
+ }
+
+ prStatus = PR_Connect(tcp_sock, addr, PR_INTERVAL_NO_TIMEOUT);
+ if (prStatus != PR_SUCCESS) {
+ PRErrorCode err = PR_GetError(); /* save error code */
+ PRInt32 oserr = PR_GetOSError();
+ if (ThrottleUp) {
+ PRTime now = PR_Now();
+ PR_Lock(threadLock);
+ lastConnectFailure = PR_MAX(now, lastConnectFailure);
+ PR_Unlock(threadLock);
+ PR_SetError(err, oserr); /* restore error code */
+ }
+ if ((err == PR_CONNECT_REFUSED_ERROR) ||
+ (err == PR_CONNECT_RESET_ERROR)) {
+ int connections = numConnected;
+
+ PR_Close(tcp_sock);
+ PR_Lock(threadLock);
+ if (connections > 2 && active_threads >= connections) {
+ active_threads = connections - 1;
+ fprintf(stderr, "active_threads set down to %d\n",
+ active_threads);
+ }
+ PR_Unlock(threadLock);
+
+ if (QuitOnTimeout && sleepInterval > 40000) {
+ fprintf(stderr,
+ "strsclnt: Client timed out waiting for connection to server.\n");
+ exit(1);
+ }
+ PR_Sleep(PR_MillisecondsToInterval(sleepInterval));
+ sleepInterval <<= 1;
+ goto retry;
+ }
+ errWarn("PR_Connect");
+ goto done;
+ } else {
+ if (ThrottleUp) {
+ PRTime now = PR_Now();
+ PR_Lock(threadLock);
+ lastConnectSuccess = PR_MAX(now, lastConnectSuccess);
+ PR_Unlock(threadLock);
+ }
+ }
+
+ ssl_sock = SSL_ImportFD(model_sock, tcp_sock);
+ /* XXX if this import fails, close tcp_sock and return. */
+ if (!ssl_sock) {
+ PR_Close(tcp_sock);
+ return SECSuccess;
+ }
+ if (fullhs != NO_FULLHS_PERCENTAGE) {
+#ifdef USE_SOCK_PEER_ID
+ char sockPeerIDString[512];
+ static PRInt32 sockPeerID = 0; /* atomically incremented */
+ PRInt32 thisPeerID;
+#endif
+ PRInt32 savid = PR_ATOMIC_INCREMENT(&globalconid);
+ PRInt32 conid = 1 + (savid - 1) % 100;
+ /* don't change peer ID on the very first handshake, which is always
+ a full, so the session gets stored into the client cache */
+ if ((savid != 1) &&
+ (((savid <= total_connections_rounded_down_to_hundreds) &&
+ (conid <= fullhs)) ||
+ (conid * 100 <= total_connections_modulo_100 * fullhs)))
+#ifdef USE_SOCK_PEER_ID
+ {
+ /* force a full handshake by changing the socket peer ID */
+ thisPeerID = PR_ATOMIC_INCREMENT(&sockPeerID);
+ } else {
+ /* reuse previous sockPeerID for restart handhsake */
+ thisPeerID = lastFullHandshakePeerID;
+ }
+ PR_snprintf(sockPeerIDString, sizeof(sockPeerIDString), "ID%d",
+ thisPeerID);
+ SSL_SetSockPeerID(ssl_sock, sockPeerIDString);
+ SSL_HandshakeCallback(ssl_sock, myHandshakeCallback,
+ (char *)NULL + thisPeerID);
+#else
+ /* force a full handshake by setting the no cache option */
+ SSL_OptionSet(ssl_sock, SSL_NO_CACHE, 1);
+#endif
+ }
+ rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 0);
+ if (rv != SECSuccess) {
+ errWarn("SSL_ResetHandshake");
+ goto done;
+ }
+
+ PR_ATOMIC_INCREMENT(&numConnected);
+
+ if (bigBuf.data != NULL) {
+ (void)handle_fdx_connection(ssl_sock, tid);
+ } else {
+ (void)handle_connection(ssl_sock, tid);
+ }
+
+ PR_ATOMIC_DECREMENT(&numConnected);
+
+done:
+ if (ssl_sock) {
+ PR_Close(ssl_sock);
+ } else if (tcp_sock) {
+ PR_Close(tcp_sock);
+ }
+ return rv;
+}
+
+typedef struct {
+ PRLock *lock;
+ char *nickname;
+ CERTCertificate *cert;
+ SECKEYPrivateKey *key;
+ void *wincx;
+} cert_and_key;
+
+PRBool
+FindCertAndKey(cert_and_key *Cert_And_Key)
+{
+ if ((NULL == Cert_And_Key->nickname) || (0 == strcmp(Cert_And_Key->nickname, "none"))) {
+ return PR_TRUE;
+ }
+ Cert_And_Key->cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
+ Cert_And_Key->nickname, certUsageSSLClient,
+ PR_FALSE, Cert_And_Key->wincx);
+ if (Cert_And_Key->cert) {
+ Cert_And_Key->key = PK11_FindKeyByAnyCert(Cert_And_Key->cert, Cert_And_Key->wincx);
+ }
+ if (Cert_And_Key->cert && Cert_And_Key->key) {
+ return PR_TRUE;
+ } else {
+ return PR_FALSE;
+ }
+}
+
+PRBool
+LoggedIn(CERTCertificate *cert, SECKEYPrivateKey *key)
+{
+ if ((cert->slot) && (key->pkcs11Slot) &&
+ (PR_TRUE == PK11_IsLoggedIn(cert->slot, NULL)) &&
+ (PR_TRUE == PK11_IsLoggedIn(key->pkcs11Slot, NULL))) {
+ return PR_TRUE;
+ }
+
+ return PR_FALSE;
+}
+
+SECStatus
+StressClient_GetClientAuthData(void *arg,
+ PRFileDesc *socket,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+ cert_and_key *Cert_And_Key = (cert_and_key *)arg;
+
+ if (!pRetCert || !pRetKey) {
+ /* bad pointers, can't return a cert or key */
+ return SECFailure;
+ }
+
+ *pRetCert = NULL;
+ *pRetKey = NULL;
+
+ if (Cert_And_Key && Cert_And_Key->nickname) {
+ while (PR_TRUE) {
+ if (Cert_And_Key && Cert_And_Key->lock) {
+ int timeout = 0;
+ PR_Lock(Cert_And_Key->lock);
+
+ if (Cert_And_Key->cert) {
+ *pRetCert = CERT_DupCertificate(Cert_And_Key->cert);
+ }
+
+ if (Cert_And_Key->key) {
+ *pRetKey = SECKEY_CopyPrivateKey(Cert_And_Key->key);
+ }
+ PR_Unlock(Cert_And_Key->lock);
+ if (!*pRetCert || !*pRetKey) {
+ /* one or both of them failed to copy. Either the source was NULL, or there was
+ ** an out of memory condition. Free any allocated copy and fail */
+ if (*pRetCert) {
+ CERT_DestroyCertificate(*pRetCert);
+ *pRetCert = NULL;
+ }
+ if (*pRetKey) {
+ SECKEY_DestroyPrivateKey(*pRetKey);
+ *pRetKey = NULL;
+ }
+ break;
+ }
+ /* now check if those objects are valid */
+ if (PR_FALSE == LoggedIn(*pRetCert, *pRetKey)) {
+ /* token is no longer logged in, it was removed */
+
+ /* first, delete and clear our invalid local objects */
+ CERT_DestroyCertificate(*pRetCert);
+ SECKEY_DestroyPrivateKey(*pRetKey);
+ *pRetCert = NULL;
+ *pRetKey = NULL;
+
+ PR_Lock(Cert_And_Key->lock);
+ /* check if another thread already logged back in */
+ if (PR_TRUE == LoggedIn(Cert_And_Key->cert, Cert_And_Key->key)) {
+ /* yes : try again */
+ PR_Unlock(Cert_And_Key->lock);
+ continue;
+ }
+ /* this is the thread to retry */
+ CERT_DestroyCertificate(Cert_And_Key->cert);
+ SECKEY_DestroyPrivateKey(Cert_And_Key->key);
+ Cert_And_Key->cert = NULL;
+ Cert_And_Key->key = NULL;
+
+ /* now look up the cert and key again */
+ while (PR_FALSE == FindCertAndKey(Cert_And_Key)) {
+ PR_Sleep(PR_SecondsToInterval(1));
+ timeout++;
+ if (timeout >= 60) {
+ printf("\nToken pulled and not reinserted early enough : aborting.\n");
+ exit(1);
+ }
+ }
+ PR_Unlock(Cert_And_Key->lock);
+ continue;
+ /* try again to reduce code size */
+ }
+ return SECSuccess;
+ }
+ }
+ *pRetCert = NULL;
+ *pRetKey = NULL;
+ return SECFailure;
+ } else {
+ /* no cert configured, automatically find the right cert. */
+ CERTCertificate *cert = NULL;
+ SECKEYPrivateKey *privkey = NULL;
+ CERTCertNicknames *names;
+ int i;
+ void *proto_win = NULL;
+ SECStatus rv = SECFailure;
+
+ if (Cert_And_Key) {
+ proto_win = Cert_And_Key->wincx;
+ }
+
+ names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
+ SEC_CERT_NICKNAMES_USER, proto_win);
+ if (names != NULL) {
+ for (i = 0; i < names->numnicknames; i++) {
+ cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
+ names->nicknames[i], certUsageSSLClient,
+ PR_FALSE, proto_win);
+ if (!cert)
+ continue;
+ /* Only check unexpired certs */
+ if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE) !=
+ secCertTimeValid) {
+ CERT_DestroyCertificate(cert);
+ continue;
+ }
+ rv = NSS_CmpCertChainWCANames(cert, caNames);
+ if (rv == SECSuccess) {
+ privkey = PK11_FindKeyByAnyCert(cert, proto_win);
+ if (privkey)
+ break;
+ }
+ rv = SECFailure;
+ CERT_DestroyCertificate(cert);
+ }
+ CERT_FreeNicknames(names);
+ }
+ if (rv == SECSuccess) {
+ *pRetCert = cert;
+ *pRetKey = privkey;
+ }
+ return rv;
+ }
+}
+
+int
+hexchar_to_int(int c)
+{
+ if (((c) >= '0') && ((c) <= '9'))
+ return (c) - '0';
+ if (((c) >= 'a') && ((c) <= 'f'))
+ return (c) - 'a' + 10;
+ if (((c) >= 'A') && ((c) <= 'F'))
+ return (c) - 'A' + 10;
+ failed_already = 1;
+ return -1;
+}
+
+void
+client_main(
+ unsigned short port,
+ int connections,
+ cert_and_key *Cert_And_Key,
+ const char *hostName,
+ const char *sniHostName)
+{
+ PRFileDesc *model_sock = NULL;
+ int i;
+ int rv;
+ PRStatus status;
+ PRNetAddr addr;
+
+ status = PR_StringToNetAddr(hostName, &addr);
+ if (status == PR_SUCCESS) {
+ addr.inet.port = PR_htons(port);
+ } else {
+ /* Lookup host */
+ PRAddrInfo *addrInfo;
+ void *enumPtr = NULL;
+
+ addrInfo = PR_GetAddrInfoByName(hostName, PR_AF_UNSPEC,
+ PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME);
+ if (!addrInfo) {
+ SECU_PrintError(progName, "error looking up host");
+ return;
+ }
+ do {
+ enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, port, &addr);
+ } while (enumPtr != NULL &&
+ addr.raw.family != PR_AF_INET &&
+ addr.raw.family != PR_AF_INET6);
+ PR_FreeAddrInfo(addrInfo);
+ if (enumPtr == NULL) {
+ SECU_PrintError(progName, "error looking up host address");
+ return;
+ }
+ }
+
+ /* all suites except RSA_NULL_MD5 are enabled by Domestic Policy */
+ NSS_SetDomesticPolicy();
+
+ /* all SSL3 cipher suites are enabled by default. */
+ if (cipherString) {
+ int ndx;
+
+ /* disable all the ciphers, then enable the ones we want. */
+ disableAllSSLCiphers();
+
+ while (0 != (ndx = *cipherString)) {
+ const char *startCipher = cipherString++;
+ int cipher = 0;
+ SECStatus rv;
+
+ if (ndx == ':') {
+ cipher = hexchar_to_int(*cipherString++);
+ cipher <<= 4;
+ cipher |= hexchar_to_int(*cipherString++);
+ cipher <<= 4;
+ cipher |= hexchar_to_int(*cipherString++);
+ cipher <<= 4;
+ cipher |= hexchar_to_int(*cipherString++);
+ if (cipher <= 0) {
+ fprintf(stderr, "strsclnt: Invalid cipher value: %-5.5s\n",
+ startCipher);
+ failed_already = 1;
+ return;
+ }
+ } else {
+ if (isalpha(ndx)) {
+ ndx = tolower(ndx) - 'a';
+ if (ndx < PR_ARRAY_SIZE(ssl3CipherSuites)) {
+ cipher = ssl3CipherSuites[ndx];
+ }
+ }
+ if (cipher <= 0) {
+ fprintf(stderr, "strsclnt: Invalid cipher letter: %c\n",
+ *startCipher);
+ failed_already = 1;
+ return;
+ }
+ }
+ rv = SSL_CipherPrefSetDefault(cipher, PR_TRUE);
+ if (rv != SECSuccess) {
+ fprintf(stderr,
+ "strsclnt: SSL_CipherPrefSetDefault(0x%04x) failed\n",
+ cipher);
+ failed_already = 1;
+ return;
+ }
+ }
+ }
+
+ /* configure model SSL socket. */
+
+ model_sock = PR_OpenTCPSocket(addr.raw.family);
+ if (model_sock == NULL) {
+ errExit("PR_OpenTCPSocket for model socket");
+ }
+
+ model_sock = SSL_ImportFD(NULL, model_sock);
+ if (model_sock == NULL) {
+ errExit("SSL_ImportFD");
+ }
+
+ /* do SSL configuration. */
+
+ rv = SSL_OptionSet(model_sock, SSL_SECURITY, enabledVersions.min != 0);
+ if (rv < 0) {
+ errExit("SSL_OptionSet SSL_SECURITY");
+ }
+
+ rv = SSL_VersionRangeSet(model_sock, &enabledVersions);
+ if (rv != SECSuccess) {
+ errExit("error setting SSL/TLS version range ");
+ }
+
+ if (bigBuf.data) { /* doing FDX */
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_FDX, 1);
+ if (rv < 0) {
+ errExit("SSL_OptionSet SSL_ENABLE_FDX");
+ }
+ }
+
+ if (NoReuse) {
+ rv = SSL_OptionSet(model_sock, SSL_NO_CACHE, 1);
+ if (rv < 0) {
+ errExit("SSL_OptionSet SSL_NO_CACHE");
+ }
+ }
+
+ if (disableLocking) {
+ rv = SSL_OptionSet(model_sock, SSL_NO_LOCKS, 1);
+ if (rv < 0) {
+ errExit("SSL_OptionSet SSL_NO_LOCKS");
+ }
+ }
+
+ if (enableSessionTickets) {
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
+ if (rv != SECSuccess)
+ errExit("SSL_OptionSet SSL_ENABLE_SESSION_TICKETS");
+ }
+
+ if (enableCompression) {
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_DEFLATE, PR_TRUE);
+ if (rv != SECSuccess)
+ errExit("SSL_OptionSet SSL_ENABLE_DEFLATE");
+ }
+
+ if (enableFalseStart) {
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_FALSE_START, PR_TRUE);
+ if (rv != SECSuccess)
+ errExit("SSL_OptionSet SSL_ENABLE_FALSE_START");
+ }
+
+ if (enableCertStatus) {
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_OCSP_STAPLING, PR_TRUE);
+ if (rv != SECSuccess)
+ errExit("SSL_OptionSet SSL_ENABLE_OCSP_STAPLING");
+ }
+
+ SSL_SetPKCS11PinArg(model_sock, &pwdata);
+
+ SSL_SetURL(model_sock, hostName);
+
+ SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate,
+ (void *)CERT_GetDefaultCertDB());
+ SSL_BadCertHook(model_sock, myBadCertHandler, NULL);
+
+ SSL_GetClientAuthDataHook(model_sock, StressClient_GetClientAuthData, (void *)Cert_And_Key);
+
+ if (sniHostName) {
+ SSL_SetURL(model_sock, sniHostName);
+ }
+ /* I'm not going to set the HandshakeCallback function. */
+
+ /* end of ssl configuration. */
+
+ init_thread_data();
+
+ remaining_connections = total_connections = connections;
+ total_connections_modulo_100 = total_connections % 100;
+ total_connections_rounded_down_to_hundreds =
+ total_connections - total_connections_modulo_100;
+
+ if (!NoReuse) {
+ remaining_connections = 1;
+ launch_thread(do_connects, &addr, model_sock, 0);
+ /* wait for the first connection to terminate, then launch the rest. */
+ reap_threads();
+ remaining_connections = total_connections - 1;
+ }
+ if (remaining_connections > 0) {
+ active_threads = PR_MIN(active_threads, remaining_connections);
+ /* Start up the threads */
+ for (i = 0; i < active_threads; i++) {
+ launch_thread(do_connects, &addr, model_sock, i);
+ }
+ reap_threads();
+ }
+ destroy_thread_data();
+
+ PR_Close(model_sock);
+}
+
+SECStatus
+readBigFile(const char *fileName)
+{
+ PRFileInfo info;
+ PRStatus status;
+ SECStatus rv = SECFailure;
+ int count;
+ int hdrLen;
+ PRFileDesc *local_file_fd = NULL;
+
+ status = PR_GetFileInfo(fileName, &info);
+
+ if (status == PR_SUCCESS &&
+ info.type == PR_FILE_FILE &&
+ info.size > 0 &&
+ NULL != (local_file_fd = PR_Open(fileName, PR_RDONLY, 0))) {
+
+ hdrLen = PORT_Strlen(outHeader);
+ bigBuf.len = hdrLen + info.size;
+ bigBuf.data = PORT_Malloc(bigBuf.len + 4095);
+ if (!bigBuf.data) {
+ errWarn("PORT_Malloc");
+ goto done;
+ }
+
+ PORT_Memcpy(bigBuf.data, outHeader, hdrLen);
+
+ count = PR_Read(local_file_fd, bigBuf.data + hdrLen, info.size);
+ if (count != info.size) {
+ errWarn("PR_Read local file");
+ goto done;
+ }
+ rv = SECSuccess;
+ done:
+ PR_Close(local_file_fd);
+ }
+ return rv;
+}
+
+int
+main(int argc, char **argv)
+{
+ const char *dir = ".";
+ const char *fileName = NULL;
+ char *hostName = NULL;
+ char *nickName = NULL;
+ char *tmp = NULL;
+ int connections = 1;
+ int exitVal;
+ int tmpInt;
+ unsigned short port = 443;
+ SECStatus rv;
+ PLOptState *optstate;
+ PLOptStatus status;
+ cert_and_key Cert_And_Key;
+ char *sniHostName = NULL;
+
+ /* Call the NSPR initialization routines */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions);
+
+ tmp = strrchr(argv[0], '/');
+ tmp = tmp ? tmp + 1 : argv[0];
+ progName = strrchr(tmp, '\\');
+ progName = progName ? progName + 1 : tmp;
+
+ /* XXX: 'B' was used in the past but removed in 3.28,
+ * please leave some time before resuing it. */
+ optstate = PL_CreateOptState(argc, argv,
+ "C:DNP:TUV:W:a:c:d:f:gin:op:qst:uvw:z");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'C':
+ cipherString = optstate->value;
+ break;
+
+ case 'D':
+ NoDelay = PR_TRUE;
+ break;
+
+ case 'I': /* reserved for OCSP multi-stapling */
+ break;
+
+ case 'N':
+ NoReuse = 1;
+ break;
+
+ case 'P':
+ fullhs = PORT_Atoi(optstate->value);
+ break;
+
+ case 'T':
+ enableCertStatus = PR_TRUE;
+ break;
+
+ case 'U':
+ ThrottleUp = PR_TRUE;
+ break;
+
+ case 'V':
+ if (SECU_ParseSSLVersionRangeString(optstate->value,
+ enabledVersions, &enabledVersions) !=
+ SECSuccess) {
+ Usage(progName);
+ }
+ break;
+
+ case 'a':
+ sniHostName = PL_strdup(optstate->value);
+ break;
+
+ case 'c':
+ connections = PORT_Atoi(optstate->value);
+ break;
+
+ case 'd':
+ dir = optstate->value;
+ break;
+
+ case 'f':
+ fileName = optstate->value;
+ break;
+
+ case 'g':
+ enableFalseStart = PR_TRUE;
+ break;
+
+ case 'i':
+ ignoreErrors = PR_TRUE;
+ break;
+
+ case 'n':
+ nickName = PL_strdup(optstate->value);
+ break;
+
+ case 'o':
+ MakeCertOK++;
+ break;
+
+ case 'p':
+ port = PORT_Atoi(optstate->value);
+ break;
+
+ case 'q':
+ QuitOnTimeout = PR_TRUE;
+ break;
+
+ case 's':
+ disableLocking = PR_TRUE;
+ break;
+
+ case 't':
+ tmpInt = PORT_Atoi(optstate->value);
+ if (tmpInt > 0 && tmpInt < MAX_THREADS)
+ max_threads = active_threads = tmpInt;
+ break;
+
+ case 'u':
+ enableSessionTickets = PR_TRUE;
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ case 'w':
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = PL_strdup(optstate->value);
+ break;
+
+ case 'W':
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = PL_strdup(optstate->value);
+ break;
+
+ case 'z':
+ enableCompression = PR_TRUE;
+ break;
+
+ case 0: /* positional parameter */
+ if (hostName) {
+ Usage(progName);
+ }
+ hostName = PL_strdup(optstate->value);
+ break;
+
+ default:
+ case '?':
+ Usage(progName);
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+
+ if (!hostName || status == PL_OPT_BAD)
+ Usage(progName);
+
+ if (fullhs != NO_FULLHS_PERCENTAGE && (fullhs < 0 || fullhs > 100 || NoReuse))
+ Usage(progName);
+
+ if (port == 0)
+ Usage(progName);
+
+ if (fileName)
+ readBigFile(fileName);
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ tmp = PR_GetEnvSecure("NSS_DEBUG_TIMEOUT");
+ if (tmp && tmp[0]) {
+ int sec = PORT_Atoi(tmp);
+ if (sec > 0) {
+ maxInterval = PR_SecondsToInterval(sec);
+ }
+ }
+
+ /* Call the NSS initialization routines */
+ rv = NSS_Initialize(dir, "", "", SECMOD_DB, NSS_INIT_READONLY);
+ if (rv != SECSuccess) {
+ fputs("NSS_Init failed.\n", stderr);
+ exit(1);
+ }
+ ssl3stats = SSL_GetStatistics();
+ Cert_And_Key.lock = PR_NewLock();
+ Cert_And_Key.nickname = nickName;
+ Cert_And_Key.wincx = &pwdata;
+ Cert_And_Key.cert = NULL;
+ Cert_And_Key.key = NULL;
+
+ if (PR_FALSE == FindCertAndKey(&Cert_And_Key)) {
+
+ if (Cert_And_Key.cert == NULL) {
+ fprintf(stderr, "strsclnt: Can't find certificate %s\n", Cert_And_Key.nickname);
+ exit(1);
+ }
+
+ if (Cert_And_Key.key == NULL) {
+ fprintf(stderr, "strsclnt: Can't find Private Key for cert %s\n",
+ Cert_And_Key.nickname);
+ exit(1);
+ }
+ }
+
+ client_main(port, connections, &Cert_And_Key, hostName,
+ sniHostName);
+
+ /* clean up */
+ if (Cert_And_Key.cert) {
+ CERT_DestroyCertificate(Cert_And_Key.cert);
+ }
+ if (Cert_And_Key.key) {
+ SECKEY_DestroyPrivateKey(Cert_And_Key.key);
+ }
+
+ PR_DestroyLock(Cert_And_Key.lock);
+
+ if (pwdata.data) {
+ PL_strfree(pwdata.data);
+ }
+ if (Cert_And_Key.nickname) {
+ PL_strfree(Cert_And_Key.nickname);
+ }
+ if (sniHostName) {
+ PL_strfree(sniHostName);
+ }
+
+ PL_strfree(hostName);
+
+ /* some final stats. */
+ printf(
+ "strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n"
+ " %ld stateless resumes\n",
+ ssl3stats->hsh_sid_cache_hits,
+ ssl3stats->hsh_sid_cache_misses,
+ ssl3stats->hsh_sid_cache_not_ok,
+ ssl3stats->hsh_sid_stateless_resumes);
+
+ if (!NoReuse) {
+ if (enableSessionTickets)
+ exitVal = (ssl3stats->hsh_sid_stateless_resumes == 0);
+ else
+ exitVal = (ssl3stats->hsh_sid_cache_misses > 1) ||
+ (ssl3stats->hsh_sid_stateless_resumes != 0);
+ if (!exitVal)
+ exitVal = (ssl3stats->hsh_sid_cache_not_ok != 0) ||
+ (certsTested > 1);
+ } else {
+ printf("strsclnt: NoReuse - %d server certificates tested.\n",
+ certsTested);
+ exitVal = (ssl3stats->hsh_sid_cache_misses != connections) ||
+ (ssl3stats->hsh_sid_stateless_resumes != 0) ||
+ (certsTested != connections);
+ }
+
+ exitVal = (exitVal || failed_already);
+ SSL_ClearSessionCache();
+ if (NSS_Shutdown() != SECSuccess) {
+ printf("strsclnt: NSS_Shutdown() failed.\n");
+ exit(1);
+ }
+
+ PR_Cleanup();
+ return exitVal;
+}
diff --git a/security/nss/cmd/strsclnt/strsclnt.gyp b/security/nss/cmd/strsclnt/strsclnt.gyp
new file mode 100644
index 000000000..4093017bf
--- /dev/null
+++ b/security/nss/cmd/strsclnt/strsclnt.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'strsclnt',
+ 'type': 'executable',
+ 'sources': [
+ 'strsclnt.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/symkeyutil/Makefile b/security/nss/cmd/symkeyutil/Makefile
new file mode 100644
index 000000000..74ae20020
--- /dev/null
+++ b/security/nss/cmd/symkeyutil/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/symkeyutil/manifest.mn b/security/nss/cmd/symkeyutil/manifest.mn
new file mode 100644
index 000000000..f87480e44
--- /dev/null
+++ b/security/nss/cmd/symkeyutil/manifest.mn
@@ -0,0 +1,23 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = symkeyutil.c
+#CSRCS = symkeytest.c
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = dbm seccmd
+
+PROGRAM = symkeyutil
+#PROGRAM = symkeytest
+
+#USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/symkeyutil/symkey.man b/security/nss/cmd/symkeyutil/symkey.man
new file mode 100644
index 000000000..e3c2e4c6e
--- /dev/null
+++ b/security/nss/cmd/symkeyutil/symkey.man
@@ -0,0 +1,182 @@
+
+NAME
+ symkeyutil - manage fixed keys in the database
+
+SYNOPSIS
+ symkeyutil -H
+ symkeyutil -L [std_opts] [-r]
+ symkeyutil -K [-n name] -t type [-s size] [-i id |-j id_file] [std_opts]
+ symkeyutil -D <[-n name | -i id | -j id_file> [std_opts]
+ symkeyutil -I [-n name] [-t type] [-i id | -j id_file] -k data_file [std_opts]
+ symkeyutil -E <-nname | -i id | -j id_file> [-t type] -k data_file [-r] [std_opts]
+ symkeyutil -U [-n name] [-t type] [-i id | -j id_file] -k data_file <wrap_opts> [std_opts]
+ symkeyutil -W <-n name | -i id | -j id_file> [-t type] -k data_file [-r] <wrap_opts> [std_opts]
+ symkeyutil -M <-n name | -i id | -j id_file> -g target_token [std_opts]
+ std_opts -> [-d certdir] [-P dbprefix] [-p password] [-f passwordFile] [-h token]
+ wrap_opts -> <-w wrap_name | -x wrap_id | -y id_file>
+
+DESCRIPTION
+
+ NSS can store fixed keys as well as asymetric keys in the database. The
+ symkeyutil command can be used to manage these keys.
+
+ As with certutil, symkeyutil takes two types of arguments, commands and
+ options. Most commands fall into one of two catagories: commands which
+ create keys and commands which extract or destroy keys.
+
+ Exceptions to these catagories are listed first:
+
+ -H takes no additional options. It lists a more detailed help message.
+ -L takes the standard set of options. It lists all the keys in the
+ specified token (NSS Internal DB Token is the default). Only the
+ -L option accepts the all option for tokens to list all the fixed
+ keys.
+
+ Key Creation commands:
+ For these commands, the key type (-t) option is always required.
+ In addition, the -s option may be required for certain key types.
+ The standard set of options may be specified.
+
+ -K Create a new key using the token key gen function.
+ -I Import a new key from the raw data specified in the data file,
+ specified with the -k options (required). This command may fail on
+ some tokens that don't support direct import of key material.
+ -U Unwrap a new key from an encrypted data file specified with the -k
+ option. The -w, -x, or -y option specifies the unwrapping key.
+ The unwrapping algorithm is selected based on the type of the
+ unwrapping key.
+
+ Key extraction/destruction options:
+ For these keys, one and only of of the -n, -i, or -j options must be
+ specified. If more than one key matches the -n option, the 'first' key
+ matching will be used. The standard set of options may be specified.
+
+ -D Delete the key specified by the -n, -i, or -j options.
+ -E Export the key specified by the -n, -i, or -j options and store the
+ contents to a file specified by the -k file (required).
+ This command will seldom work on any token since most keys are
+ protected from export.
+ -W Wrap the key specified by the -n, -i, or -j options and store the
+ encrypted contents to a file specified by the -k file (required).
+ The -w, -x, or -y option specifies the key used to wrap the
+ target key.
+ -M Move the key specified by the -n, -i, or -j options to the token
+ specified by the -g option (required). The new key will have the
+ same attributes as the source key.
+
+OPTIONS
+
+ Standard options are those options that may be used by any command, and
+ whose meaning is the same for all commands.
+
+ -h token Specify the token which the command will operate on.
+ If -h is not specified the internal token is presumed. In
+ addition the special value 'all' may be used to specify
+ that all tokens should be used. This is only valid for
+ the '-L' command.
+ -d certdir Specify the location of the NSS databases. The default
+ value is platform dependent.
+ -P dbprefix Specify the prefix for the NSS database. The default value
+ is NULL.
+ -p password Specify the password for the token. On the command line.
+ The -p and -f options are mutually exclusive. If
+ neither option is specified, the password would be
+ prompted from the user.
+ -f passwordFile Specify a file that contains the password for the token.
+ This option is mutually exclusive to the -p option.
+
+ In addition to the standard options are the following command specific
+ options are.
+
+ -r Opens the NSS databases Read/Write. By default the -L,
+ -E, and -W commands open the database read only. Other
+ commands automatically opens the databases Read/Write and
+ igore this option if it is specified.
+
+ -n name Specifies the nickname for the key.
+
+ For the -K, -I, or -U options, name is the name for
+ the new key. If -n is not specified, no name is
+ assumed. There is not check for duplicate names.
+
+ For the -D, -E, -W, or -M, the name specifies the key to
+ operate on. In this case one andy only one of the -n, -i
+ or -j options should be specifed. It is possible that
+ the -n options specifies and ambiguous key. In that case
+ the 'first' valid key is used.
+
+ For the -M option, the nickname for the new key is copied
+ from it's original key, even if the original key is
+ specified using -i or -j.
+
+ -i key id
+ -j key id file These options are equivalent and mutually exclusive.
+ They specify the key id for the file. The -i option
+ specifies the key id on the command line using a hex
+ string. The -j specifies a file to read the raw key
+ id from.
+
+ For the -K, -I, or -U options, key id is the key id for
+ the new key. If -i or -j is not specified, no key id
+ is assumed. Some tokens may generate their own unique
+ id for the key in this case (but it is not guarrenteed).
+
+ For the -D, -E, -W, or -M, the key id specifies the key to
+ operate on. In this case one andy only one of the -n, -i
+ or -j options should be specifed.
+
+ -t type Specifies the key Type for the new key. This option is
+ required for the -K, -I, and -U commands. Valid values
+ are:
+ generic, rc2, rc4, des, des2, des3, cast, cast3,
+ cast5, cast128, rc5, idea, skipjack, baton, juniper,
+ cdmf, aes, camellia
+
+ Not all tokens support all key types. The generic key
+ type is usually used in MACing and key derivation
+ algorithms. Neither generic nor rc4 keys may be used
+ to wrap other keys. Fixed rc4 keys are dangerous since
+ multiple use of the same stream cipher key to encrypted
+ different data can compromise all data encrypted with
+ that key.
+
+ -s size Specifies the key size. For most situations the key size
+ is already known and need not be specified. For some
+ algorithms, however, it is necessary to specify the key
+ size when generation or unwrapping the key.
+
+ -k key file Specifies the name of a file that contains key data to
+ import or unwrap (-I or -U), or the location to store
+ key data or encrypted key data (-E or -W).
+
+ -g target token Specifies the target token when moving a key (-M). This
+ option is required for the -M command. It is invalid for
+ all other commands.
+
+
+
+ -w wrap name
+ -x wrap key id
+ -y wrap key id file Specifies the wrapping key used int the -U and -W
+ command. Exactly one of these must be specified for the
+ -U or -W commands. Same semantics as the -n, -i, and -j
+ options above.
+
+BUGS
+
+ There is no way display the key id of a key.
+
+ The -p and -f options only specifies one password. Multiple passwords may
+ be needed for the -L -h all command and the -M command.
+
+ Perhaps RC4 should not be supported as a key type. Use of these keys as
+ fixed keys is exceedingly dangerous.
+
+ The handling of multiple keys with the same nickname should be more
+ deterministic than 'the first one'
+
+ There is no way to specify, or display the operation flags of a key. The
+ operation flags are not copied with the -M option as they should be.
+
+ There is no way to change the attributes of a key (nickname, id, operation
+ flags).
diff --git a/security/nss/cmd/symkeyutil/symkeyutil.c b/security/nss/cmd/symkeyutil/symkeyutil.c
new file mode 100644
index 000000000..6170cc3c5
--- /dev/null
+++ b/security/nss/cmd/symkeyutil/symkeyutil.c
@@ -0,0 +1,1102 @@
+/* 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/. */
+
+/*
+** symkeyutil.c
+**
+** utility for managing symetric keys in the database or the token
+**
+*/
+
+/*
+ * Wish List for this utility:
+ * 1) Display and Set the CKA_ operation flags for the key.
+ * 2) Modify existing keys
+ * 3) Copy keys
+ * 4) Read CKA_ID and display for keys.
+ * 5) Option to store CKA_ID in a file on key creation.
+ * 6) Encrypt, Decrypt, Hash, and Mac with generated keys.
+ * 7) Use asymetric keys to wrap and unwrap keys.
+ * 8) Derive.
+ * 9) PBE keys.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "secutil.h"
+
+#include "nspr.h"
+
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "nss.h"
+
+typedef struct _KeyTypes {
+ CK_KEY_TYPE keyType;
+ CK_MECHANISM_TYPE mechType;
+ CK_MECHANISM_TYPE wrapMech;
+ char *label;
+} KeyTypes;
+
+static KeyTypes keyArray[] = {
+#ifdef RECOGNIZE_ASYMETRIC_TYPES
+ { CKK_RSA, CKM_RSA_PKCS, CKM_RSA_PKCS, "rsa" },
+ { CKK_DSA, CKM_DSA, CKM_INVALID_MECHANISM, "dsa" },
+ { CKK_DH, CKM_DH_PKCS_DERIVE, CKM_INVALID_MECHANISM, "dh" },
+ { CKK_EC, CKM_ECDSA, CKM_INVALID_MECHANISM, "ec" },
+ { CKK_X9_42_DH, CKM_X9_42_DH_DERIVE, CKM_INVALID_MECHANISM, "x9.42dh" },
+ { CKK_KEA, CKM_KEA_KEY_DERIVE, CKM_INVALID_MECHANISM, "kea" },
+#endif
+ { CKK_GENERIC_SECRET, CKM_SHA_1_HMAC, CKM_INVALID_MECHANISM, "generic" },
+ { CKK_RC2, CKM_RC2_CBC, CKM_RC2_ECB, "rc2" },
+ /* don't define a wrap mech for RC-4 since it's note really safe */
+ { CKK_RC4, CKM_RC4, CKM_INVALID_MECHANISM, "rc4" },
+ { CKK_DES, CKM_DES_CBC, CKM_DES_ECB, "des" },
+ { CKK_DES2, CKM_DES2_KEY_GEN, CKM_DES3_ECB, "des2" },
+ { CKK_DES3, CKM_DES3_KEY_GEN, CKM_DES3_ECB, "des3" },
+ { CKK_CAST, CKM_CAST_CBC, CKM_CAST_ECB, "cast" },
+ { CKK_CAST3, CKM_CAST3_CBC, CKM_CAST3_ECB, "cast3" },
+ { CKK_CAST5, CKM_CAST5_CBC, CKM_CAST5_ECB, "cast5" },
+ { CKK_CAST128, CKM_CAST128_CBC, CKM_CAST128_ECB, "cast128" },
+ { CKK_RC5, CKM_RC5_CBC, CKM_RC5_ECB, "rc5" },
+ { CKK_IDEA, CKM_IDEA_CBC, CKM_IDEA_ECB, "idea" },
+ { CKK_SKIPJACK, CKM_SKIPJACK_CBC64, CKM_SKIPJACK_WRAP, "skipjack" },
+ { CKK_BATON, CKM_BATON_CBC128, CKM_BATON_WRAP, "baton" },
+ { CKK_JUNIPER, CKM_JUNIPER_CBC128, CKM_JUNIPER_WRAP, "juniper" },
+ { CKK_CDMF, CKM_CDMF_CBC, CKM_CDMF_ECB, "cdmf" },
+ { CKK_AES, CKM_AES_CBC, CKM_AES_ECB, "aes" },
+ { CKK_CAMELLIA, CKM_CAMELLIA_CBC, CKM_CAMELLIA_ECB, "camellia" },
+};
+
+static int keyArraySize = sizeof(keyArray) / sizeof(keyArray[0]);
+
+int
+GetLen(PRFileDesc *fd)
+{
+ PRFileInfo info;
+
+ if (PR_SUCCESS != PR_GetOpenFileInfo(fd, &info)) {
+ return -1;
+ }
+
+ return info.size;
+}
+
+int
+ReadBuf(char *inFile, SECItem *item)
+{
+ int len;
+ int ret;
+ PRFileDesc *fd = PR_Open(inFile, PR_RDONLY, 0);
+ if (NULL == fd) {
+ SECU_PrintError("symkeyutil", "PR_Open failed");
+ return -1;
+ }
+
+ len = GetLen(fd);
+ if (len < 0) {
+ SECU_PrintError("symkeyutil", "PR_GetOpenFileInfo failed");
+ return -1;
+ }
+ item->data = (unsigned char *)PORT_Alloc(len);
+ if (item->data == NULL) {
+ fprintf(stderr, "Failed to allocate %d to read file %s\n", len, inFile);
+ return -1;
+ }
+
+ ret = PR_Read(fd, item->data, item->len);
+ if (ret < 0) {
+ SECU_PrintError("symkeyutil", "PR_Read failed");
+ PORT_Free(item->data);
+ item->data = NULL;
+ return -1;
+ }
+ PR_Close(fd);
+ item->len = len;
+ return 0;
+}
+
+int
+WriteBuf(char *inFile, SECItem *item)
+{
+ int ret;
+ PRFileDesc *fd = PR_Open(inFile, PR_WRONLY | PR_CREATE_FILE, 0x200);
+ if (NULL == fd) {
+ SECU_PrintError("symkeyutil", "PR_Open failed");
+ return -1;
+ }
+
+ ret = PR_Write(fd, item->data, item->len);
+ if (ret < 0) {
+ SECU_PrintError("symkeyutil", "PR_Write failed");
+ return -1;
+ }
+ PR_Close(fd);
+ return 0;
+}
+
+CK_KEY_TYPE
+GetKeyTypeFromString(const char *keyString)
+{
+ int i;
+ for (i = 0; i < keyArraySize; i++) {
+ if (PL_strcasecmp(keyString, keyArray[i].label) == 0) {
+ return keyArray[i].keyType;
+ }
+ }
+ return (CK_KEY_TYPE)-1;
+}
+
+CK_MECHANISM_TYPE
+GetKeyMechFromString(const char *keyString)
+{
+ int i;
+ for (i = 0; i < keyArraySize; i++) {
+ if (PL_strcasecmp(keyString, keyArray[i].label) == 0) {
+ return keyArray[i].mechType;
+ }
+ }
+ return (CK_MECHANISM_TYPE)-1;
+}
+
+const char *
+GetStringFromKeyType(CK_KEY_TYPE type)
+{
+ int i;
+ for (i = 0; i < keyArraySize; i++) {
+ if (keyArray[i].keyType == type) {
+ return keyArray[i].label;
+ }
+ }
+ return "unmatched";
+}
+
+CK_MECHANISM_TYPE
+GetWrapFromKeyType(CK_KEY_TYPE type)
+{
+ int i;
+ for (i = 0; i < keyArraySize; i++) {
+ if (keyArray[i].keyType == type) {
+ return keyArray[i].wrapMech;
+ }
+ }
+ return CKM_INVALID_MECHANISM;
+}
+
+CK_MECHANISM_TYPE
+GetWrapMechanism(PK11SymKey *symKey)
+{
+ CK_KEY_TYPE type = PK11_GetSymKeyType(symKey);
+
+ return GetWrapFromKeyType(type);
+}
+
+int
+GetDigit(char c)
+{
+ if (c == 0) {
+ return -1;
+ }
+ if (c <= '9' && c >= '0') {
+ return c - '0';
+ }
+ if (c <= 'f' && c >= 'a') {
+ return c - 'a' + 0xa;
+ }
+ if (c <= 'F' && c >= 'A') {
+ return c - 'A' + 0xa;
+ }
+ return -1;
+}
+
+char
+ToDigit(unsigned char c)
+{
+ c = c & 0xf;
+ if (c <= 9) {
+ return (char)(c + '0');
+ }
+ return (char)(c + 'a' - 0xa);
+}
+
+char *
+BufToHex(SECItem *outbuf)
+{
+ int len = outbuf->len * 2 + 1;
+ char *string, *ptr;
+ unsigned int i;
+
+ string = PORT_Alloc(len);
+
+ ptr = string;
+ for (i = 0; i < outbuf->len; i++) {
+ *ptr++ = ToDigit(outbuf->data[i] >> 4);
+ *ptr++ = ToDigit(outbuf->data[i] & 0xf);
+ }
+ *ptr = 0;
+ return string;
+}
+
+int
+HexToBuf(char *inString, SECItem *outbuf)
+{
+ int len = strlen(inString);
+ int outlen = len + 1 / 2;
+ int trueLen = 0;
+
+ outbuf->data = PORT_Alloc(outlen);
+ if (outbuf->data) {
+ return -1;
+ }
+
+ while (*inString) {
+ int digit1, digit2;
+ digit1 = GetDigit(*inString++);
+ digit2 = GetDigit(*inString++);
+ if ((digit1 == -1) || (digit2 == -1)) {
+ PORT_Free(outbuf->data);
+ outbuf->data = NULL;
+ return -1;
+ }
+ outbuf->data[trueLen++] = digit1 << 4 | digit2;
+ }
+ outbuf->len = trueLen;
+ return 0;
+}
+
+void
+printBuf(unsigned char *data, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ printf("%02x", data[i]);
+ }
+}
+
+void
+PrintKey(PK11SymKey *symKey)
+{
+ char *name = PK11_GetSymKeyNickname(symKey);
+ int len = PK11_GetKeyLength(symKey);
+ int strength = PK11_GetKeyStrength(symKey, NULL);
+ SECItem *value = NULL;
+ CK_KEY_TYPE type = PK11_GetSymKeyType(symKey);
+ (void)PK11_ExtractKeyValue(symKey);
+
+ value = PK11_GetKeyData(symKey);
+
+ printf("%-20s %3d %4d %10s ", name ? name : " ", len, strength,
+ GetStringFromKeyType(type));
+ if (value && value->data) {
+ printBuf(value->data, value->len);
+ } else {
+ printf("<restricted>");
+ }
+ printf("\n");
+}
+
+SECStatus
+ListKeys(PK11SlotInfo *slot, int *printLabel, void *pwd)
+{
+ PK11SymKey *keyList;
+ SECStatus rv = PK11_Authenticate(slot, PR_FALSE, pwd);
+ if (rv != SECSuccess) {
+ return rv;
+ ;
+ }
+
+ keyList = PK11_ListFixedKeysInSlot(slot, NULL, pwd);
+ if (keyList) {
+ if (*printLabel) {
+ printf(" Name Len Strength Type Data\n");
+ *printLabel = 0;
+ }
+ printf("%s:\n", PK11_GetTokenName(slot));
+ }
+ while (keyList) {
+ PK11SymKey *freeKey = keyList;
+ PrintKey(keyList);
+ keyList = PK11_GetNextSymKey(keyList);
+ PK11_FreeSymKey(freeKey);
+ }
+ return SECSuccess;
+}
+
+PK11SymKey *
+FindKey(PK11SlotInfo *slot, char *name, SECItem *id, void *pwd)
+{
+ PK11SymKey *key = NULL;
+ SECStatus rv = PK11_Authenticate(slot, PR_FALSE, pwd);
+
+ if (rv != SECSuccess) {
+ return NULL;
+ }
+
+ if (id->data) {
+ key = PK11_FindFixedKey(slot, CKM_INVALID_MECHANISM, id, pwd);
+ }
+ if (name && !key) {
+ key = PK11_ListFixedKeysInSlot(slot, name, pwd);
+ }
+
+ if (key) {
+ printf("Found a key\n");
+ PrintKey(key);
+ }
+ return key;
+}
+
+PRBool
+IsKeyList(PK11SymKey *symKey)
+{
+ return (PRBool)(PK11_GetNextSymKey(symKey) != NULL);
+}
+
+void
+FreeKeyList(PK11SymKey *symKey)
+{
+ PK11SymKey *next, *current;
+
+ for (current = symKey; current; current = next) {
+ next = PK11_GetNextSymKey(current);
+ PK11_FreeSymKey(current);
+ }
+ return;
+}
+
+static void
+Usage(char *progName)
+{
+#define FPS fprintf(stderr,
+ FPS "Type %s -H for more detailed descriptions\n", progName);
+ FPS "Usage:");
+ FPS "\t%s -L [std_opts] [-r]\n", progName);
+ FPS "\t%s -K [-n name] -t type [-s size] [-i id |-j id_file] [std_opts]\n", progName);
+ FPS "\t%s -D <[-n name | -i id | -j id_file> [std_opts]\n", progName);
+ FPS "\t%s -I [-n name] [-t type] [-i id | -j id_file] -k data_file [std_opts]\n", progName);
+ FPS "\t%s -E <-nname | -i id | -j id_file> [-t type] -k data_file [-r] [std_opts]\n", progName);
+ FPS "\t%s -U [-n name] [-t type] [-i id | -j id_file] -k data_file <wrap_opts> [std_opts]\n", progName);
+ FPS "\t%s -W <-n name | -i id | -j id_file> [-t type] -k data_file [-r] <wrap_opts> [std_opts]\n", progName);
+ FPS "\t%s -M <-n name | -i id | -j id_file> -g target_token [std_opts]\n", progName);
+ FPS "\t\t std_opts -> [-d certdir] [-P dbprefix] [-p password] [-f passwordFile] [-h token]\n");
+ FPS "\t\t wrap_opts -> <-w wrap_name | -x wrap_id | -y id_file>\n");
+ exit(1);
+}
+
+static void
+LongUsage(char *progName)
+{
+ int i;
+ FPS "%-15s List all the keys.\n", "-L");
+ FPS "%-15s Generate a new key.\n", "-K");
+ FPS "%-20s Specify the nickname of the new key\n",
+ " -n name");
+ FPS "%-20s Specify the id in hex of the new key\n",
+ " -i key id");
+ FPS "%-20s Specify a file to read the id of the new key\n",
+ " -j key id file");
+ FPS "%-20s Specify the keyType of the new key\n",
+ " -t type");
+ FPS "%-20s", " valid types: ");
+ for (i = 0; i < keyArraySize; i++) {
+ FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':',');
+ }
+ FPS "%-20s Specify the size of the new key in bytes (required by some types)\n",
+ " -s size");
+ FPS "%-15s Delete a key.\n", "-D");
+ FPS "%-20s Specify the nickname of the key to delete\n",
+ " -n name");
+ FPS "%-20s Specify the id in hex of the key to delete\n",
+ " -i key id");
+ FPS "%-20s Specify a file to read the id of the key to delete\n",
+ " -j key id file");
+ FPS "%-15s Import a new key from a data file.\n", "-I");
+ FPS "%-20s Specify the data file to read the key from.\n",
+ " -k key file");
+ FPS "%-20s Specify the nickname of the new key\n",
+ " -n name");
+ FPS "%-20s Specify the id in hex of the new key\n",
+ " -i key id");
+ FPS "%-20s Specify a file to read the id of the new key\n",
+ " -j key id file");
+ FPS "%-20s Specify the keyType of the new key\n",
+ " -t type");
+ FPS "%-20s", " valid types: ");
+ for (i = 0; i < keyArraySize; i++) {
+ FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':',');
+ }
+ FPS "%-15s Export a key to a data file.\n", "-E");
+ FPS "%-20s Specify the data file to write the key to.\n",
+ " -k key file");
+ FPS "%-20s Specify the nickname of the key to export\n",
+ " -n name");
+ FPS "%-20s Specify the id in hex of the key to export\n",
+ " -i key id");
+ FPS "%-20s Specify a file to read the id of the key to export\n",
+ " -j key id file");
+ FPS "%-15s Move a key to a new token.\n", "-M");
+ FPS "%-20s Specify the nickname of the key to move\n",
+ " -n name");
+ FPS "%-20s Specify the id in hex of the key to move\n",
+ " -i key id");
+ FPS "%-20s Specify a file to read the id of the key to move\n",
+ " -j key id file");
+ FPS "%-20s Specify the token to move the key to\n",
+ " -g target token");
+ FPS "%-15s Unwrap a new key from a data file.\n", "-U");
+ FPS "%-20s Specify the data file to read the encrypted key from.\n",
+ " -k key file");
+ FPS "%-20s Specify the nickname of the new key\n",
+ " -n name");
+ FPS "%-20s Specify the id in hex of the new key\n",
+ " -i key id");
+ FPS "%-20s Specify a file to read the id of the new key\n",
+ " -j key id file");
+ FPS "%-20s Specify the keyType of the new key\n",
+ " -t type");
+ FPS "%-20s", " valid types: ");
+ for (i = 0; i < keyArraySize; i++) {
+ FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':',');
+ }
+ FPS "%-20s Specify the nickname of the wrapping key\n",
+ " -w wrap name");
+ FPS "%-20s Specify the id in hex of the wrapping key\n",
+ " -x wrap key id");
+ FPS "%-20s Specify a file to read the id of the wrapping key\n",
+ " -y wrap key id file");
+ FPS "%-15s Wrap a new key to a data file. [not yet implemented]\n", "-W");
+ FPS "%-20s Specify the data file to write the encrypted key to.\n",
+ " -k key file");
+ FPS "%-20s Specify the nickname of the key to wrap\n",
+ " -n name");
+ FPS "%-20s Specify the id in hex of the key to wrap\n",
+ " -i key id");
+ FPS "%-20s Specify a file to read the id of the key to wrap\n",
+ " -j key id file");
+ FPS "%-20s Specify the nickname of the wrapping key\n",
+ " -w wrap name");
+ FPS "%-20s Specify the id in hex of the wrapping key\n",
+ " -x wrap key id");
+ FPS "%-20s Specify a file to read the id of the wrapping key\n",
+ " -y wrap key id file");
+ FPS "%-15s Options valid for all commands\n", "std_opts");
+ FPS "%-20s The directory where the NSS db's reside\n",
+ " -d certdir");
+ FPS "%-20s Prefix for the NSS db's\n",
+ " -P db prefix");
+ FPS "%-20s Specify password on the command line\n",
+ " -p password");
+ FPS "%-20s Specify password file on the command line\n",
+ " -f password file");
+ FPS "%-20s Specify token to act on\n",
+ " -h token");
+ exit(1);
+#undef FPS
+}
+
+/* Certutil commands */
+enum {
+ cmd_CreateNewKey = 0,
+ cmd_DeleteKey,
+ cmd_ImportKey,
+ cmd_ExportKey,
+ cmd_WrapKey,
+ cmd_UnwrapKey,
+ cmd_MoveKey,
+ cmd_ListKeys,
+ cmd_PrintHelp
+};
+
+/* Certutil options */
+enum {
+ opt_CertDir = 0,
+ opt_PasswordFile,
+ opt_TargetToken,
+ opt_TokenName,
+ opt_KeyID,
+ opt_KeyIDFile,
+ opt_KeyType,
+ opt_Nickname,
+ opt_KeyFile,
+ opt_Password,
+ opt_dbPrefix,
+ opt_RW,
+ opt_KeySize,
+ opt_WrapKeyName,
+ opt_WrapKeyID,
+ opt_WrapKeyIDFile,
+ opt_NoiseFile
+};
+
+static secuCommandFlag symKeyUtil_commands[] =
+ {
+ { /* cmd_CreateNewKey */ 'K', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_DeleteKey */ 'D', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ImportKey */ 'I', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ExportKey */ 'E', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_WrapKey */ 'W', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_UnwrapKey */ 'U', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_MoveKey */ 'M', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ListKeys */ 'L', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_PrintHelp */ 'H', PR_FALSE, 0, PR_FALSE },
+ };
+
+static secuCommandFlag symKeyUtil_options[] =
+ {
+ { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_PasswordFile */ 'f', PR_TRUE, 0, PR_FALSE },
+ { /* opt_TargetToken */ 'g', PR_TRUE, 0, PR_FALSE },
+ { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE },
+ { /* opt_KeyID */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_KeyIDFile */ 'j', PR_TRUE, 0, PR_FALSE },
+ { /* opt_KeyType */ 't', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE },
+ { /* opt_KeyFile */ 'k', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Password */ 'p', PR_TRUE, 0, PR_FALSE },
+ { /* opt_dbPrefix */ 'P', PR_TRUE, 0, PR_FALSE },
+ { /* opt_RW */ 'r', PR_FALSE, 0, PR_FALSE },
+ { /* opt_KeySize */ 's', PR_TRUE, 0, PR_FALSE },
+ { /* opt_WrapKeyName */ 'w', PR_TRUE, 0, PR_FALSE },
+ { /* opt_WrapKeyID */ 'x', PR_TRUE, 0, PR_FALSE },
+ { /* opt_WrapKeyIDFile */ 'y', PR_TRUE, 0, PR_FALSE },
+ { /* opt_NoiseFile */ 'z', PR_TRUE, 0, PR_FALSE },
+ };
+
+int
+main(int argc, char **argv)
+{
+ PK11SlotInfo *slot = NULL;
+ char *slotname = "internal";
+ char *certPrefix = "";
+ CK_MECHANISM_TYPE keyType = CKM_SHA_1_HMAC;
+ int keySize = 0;
+ char *name = NULL;
+ char *wrapName = NULL;
+ secuPWData pwdata = { PW_NONE, 0 };
+ PRBool readOnly = PR_FALSE;
+ SECItem key;
+ SECItem keyID;
+ SECItem wrapKeyID;
+ int commandsEntered = 0;
+ int commandToRun = 0;
+ char *progName;
+ int i;
+ SECStatus rv = SECFailure;
+
+ secuCommand symKeyUtil;
+ symKeyUtil.numCommands = sizeof(symKeyUtil_commands) / sizeof(secuCommandFlag);
+ symKeyUtil.numOptions = sizeof(symKeyUtil_options) / sizeof(secuCommandFlag);
+ symKeyUtil.commands = symKeyUtil_commands;
+ symKeyUtil.options = symKeyUtil_options;
+
+ key.data = NULL;
+ key.len = 0;
+ keyID.data = NULL;
+ keyID.len = 0;
+ wrapKeyID.data = NULL;
+ wrapKeyID.len = 0;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &symKeyUtil);
+
+ if (rv != SECSuccess)
+ Usage(progName);
+
+ rv = SECFailure;
+
+ /* -H print help */
+ if (symKeyUtil.commands[cmd_PrintHelp].activated)
+ LongUsage(progName);
+
+ /* -f password file, -p password */
+ if (symKeyUtil.options[opt_PasswordFile].arg) {
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = symKeyUtil.options[opt_PasswordFile].arg;
+ } else if (symKeyUtil.options[opt_Password].arg) {
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = symKeyUtil.options[opt_Password].arg;
+ }
+
+ /* -d directory */
+ if (symKeyUtil.options[opt_CertDir].activated)
+ SECU_ConfigDirectory(symKeyUtil.options[opt_CertDir].arg);
+
+ /* -s key size */
+ if (symKeyUtil.options[opt_KeySize].activated) {
+ keySize = PORT_Atoi(symKeyUtil.options[opt_KeySize].arg);
+ }
+
+ /* -h specify token name */
+ if (symKeyUtil.options[opt_TokenName].activated) {
+ if (PL_strcmp(symKeyUtil.options[opt_TokenName].arg, "all") == 0)
+ slotname = NULL;
+ else
+ slotname = PL_strdup(symKeyUtil.options[opt_TokenName].arg);
+ }
+
+ /* -t key type */
+ if (symKeyUtil.options[opt_KeyType].activated) {
+ keyType = GetKeyMechFromString(symKeyUtil.options[opt_KeyType].arg);
+ if (keyType == (CK_MECHANISM_TYPE)-1) {
+ PR_fprintf(PR_STDERR,
+ "%s unknown key type (%s).\n",
+ progName, symKeyUtil.options[opt_KeyType].arg);
+ return 255;
+ }
+ }
+
+ /* -k for import and unwrap, it specifies an input file to read from,
+ * for export and wrap it specifies an output file to write to */
+ if (symKeyUtil.options[opt_KeyFile].activated) {
+ if (symKeyUtil.commands[cmd_ImportKey].activated ||
+ symKeyUtil.commands[cmd_UnwrapKey].activated) {
+ int ret = ReadBuf(symKeyUtil.options[opt_KeyFile].arg, &key);
+ if (ret < 0) {
+ PR_fprintf(PR_STDERR,
+ "%s Couldn't read key file (%s).\n",
+ progName, symKeyUtil.options[opt_KeyFile].arg);
+ return 255;
+ }
+ }
+ }
+
+ /* -i specify the key ID */
+ if (symKeyUtil.options[opt_KeyID].activated) {
+ int ret = HexToBuf(symKeyUtil.options[opt_KeyID].arg, &keyID);
+ if (ret < 0) {
+ PR_fprintf(PR_STDERR,
+ "%s invalid key ID (%s).\n",
+ progName, symKeyUtil.options[opt_KeyID].arg);
+ return 255;
+ }
+ }
+
+ /* -i & -j are mutually exclusive */
+ if ((symKeyUtil.options[opt_KeyID].activated) &&
+ (symKeyUtil.options[opt_KeyIDFile].activated)) {
+ PR_fprintf(PR_STDERR,
+ "%s -i and -j options are mutually exclusive.\n", progName);
+ return 255;
+ }
+
+ /* -x specify the Wrap key ID */
+ if (symKeyUtil.options[opt_WrapKeyID].activated) {
+ int ret = HexToBuf(symKeyUtil.options[opt_WrapKeyID].arg, &wrapKeyID);
+ if (ret < 0) {
+ PR_fprintf(PR_STDERR,
+ "%s invalid key ID (%s).\n",
+ progName, symKeyUtil.options[opt_WrapKeyID].arg);
+ return 255;
+ }
+ }
+
+ /* -x & -y are mutually exclusive */
+ if ((symKeyUtil.options[opt_KeyID].activated) &&
+ (symKeyUtil.options[opt_KeyIDFile].activated)) {
+ PR_fprintf(PR_STDERR,
+ "%s -i and -j options are mutually exclusive.\n", progName);
+ return 255;
+ }
+
+ /* -y specify the key ID */
+ if (symKeyUtil.options[opt_WrapKeyIDFile].activated) {
+ int ret = ReadBuf(symKeyUtil.options[opt_WrapKeyIDFile].arg,
+ &wrapKeyID);
+ if (ret < 0) {
+ PR_fprintf(PR_STDERR,
+ "%s Couldn't read key ID file (%s).\n",
+ progName, symKeyUtil.options[opt_WrapKeyIDFile].arg);
+ return 255;
+ }
+ }
+
+ /* -P certdb name prefix */
+ if (symKeyUtil.options[opt_dbPrefix].activated)
+ certPrefix = symKeyUtil.options[opt_dbPrefix].arg;
+
+ /* Check number of commands entered. */
+ commandsEntered = 0;
+ for (i = 0; i < symKeyUtil.numCommands; i++) {
+ if (symKeyUtil.commands[i].activated) {
+ commandToRun = symKeyUtil.commands[i].flag;
+ commandsEntered++;
+ }
+ if (commandsEntered > 1)
+ break;
+ }
+ if (commandsEntered > 1) {
+ PR_fprintf(PR_STDERR, "%s: only one command at a time!\n", progName);
+ PR_fprintf(PR_STDERR, "You entered: ");
+ for (i = 0; i < symKeyUtil.numCommands; i++) {
+ if (symKeyUtil.commands[i].activated)
+ PR_fprintf(PR_STDERR, " -%c", symKeyUtil.commands[i].flag);
+ }
+ PR_fprintf(PR_STDERR, "\n");
+ return 255;
+ }
+ if (commandsEntered == 0) {
+ PR_fprintf(PR_STDERR, "%s: you must enter a command!\n", progName);
+ Usage(progName);
+ }
+
+ if (symKeyUtil.commands[cmd_ListKeys].activated ||
+ symKeyUtil.commands[cmd_PrintHelp].activated ||
+ symKeyUtil.commands[cmd_ExportKey].activated ||
+ symKeyUtil.commands[cmd_WrapKey].activated) {
+ readOnly = !symKeyUtil.options[opt_RW].activated;
+ }
+
+ if ((symKeyUtil.commands[cmd_ImportKey].activated ||
+ symKeyUtil.commands[cmd_ExportKey].activated ||
+ symKeyUtil.commands[cmd_WrapKey].activated ||
+ symKeyUtil.commands[cmd_UnwrapKey].activated) &&
+ !symKeyUtil.options[opt_KeyFile].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: keyfile is required for this command (-k).\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ /* -E, -D, -W, and all require -n, -i, or -j to identify the key */
+ if ((symKeyUtil.commands[cmd_ExportKey].activated ||
+ symKeyUtil.commands[cmd_DeleteKey].activated ||
+ symKeyUtil.commands[cmd_WrapKey].activated) &&
+ !(symKeyUtil.options[opt_Nickname].activated ||
+ symKeyUtil.options[opt_KeyID].activated ||
+ symKeyUtil.options[opt_KeyIDFile].activated)) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: nickname or id is required for this command (-n, -i, -j).\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ /* -W, -U, and all -w, -x, or -y to identify the wrapping key */
+ if ((symKeyUtil.commands[cmd_WrapKey].activated ||
+ symKeyUtil.commands[cmd_UnwrapKey].activated) &&
+ !(symKeyUtil.options[opt_WrapKeyName].activated ||
+ symKeyUtil.options[opt_WrapKeyID].activated ||
+ symKeyUtil.options[opt_WrapKeyIDFile].activated)) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: wrap key is required for this command (-w, -x, or -y).\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ /* -M needs the target slot (-g) */
+ if (symKeyUtil.commands[cmd_MoveKey].activated &&
+ !symKeyUtil.options[opt_TargetToken].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: target token is required for this command (-g).\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ /* Using slotname == NULL for listing keys and certs on all slots,
+ * but only that. */
+ if (!(symKeyUtil.commands[cmd_ListKeys].activated) && slotname == NULL) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: cannot use \"-h all\" for this command.\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ name = SECU_GetOptionArg(&symKeyUtil, opt_Nickname);
+ wrapName = SECU_GetOptionArg(&symKeyUtil, opt_WrapKeyName);
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ /* Initialize NSPR and NSS. */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_Initialize(SECU_ConfigDirectory(NULL), certPrefix, certPrefix,
+ "secmod.db", readOnly ? NSS_INIT_READONLY : 0);
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ goto shutdown;
+ }
+ rv = SECFailure;
+
+ if (PL_strcmp(slotname, "internal") == 0)
+ slot = PK11_GetInternalKeySlot();
+ else if (slotname != NULL)
+ slot = PK11_FindSlotByName(slotname);
+
+ /* generating a new key */
+ if (symKeyUtil.commands[cmd_CreateNewKey].activated) {
+ PK11SymKey *symKey;
+
+ symKey = PK11_TokenKeyGen(slot, keyType, NULL, keySize,
+ NULL, PR_TRUE, &pwdata);
+ if (!symKey) {
+ PR_fprintf(PR_STDERR, "%s: Token Key Gen Failed\n", progName);
+ goto shutdown;
+ }
+ if (symKeyUtil.options[opt_Nickname].activated) {
+ rv = PK11_SetSymKeyNickname(symKey, name);
+ if (rv != SECSuccess) {
+ PK11_DeleteTokenSymKey(symKey);
+ PK11_FreeSymKey(symKey);
+ PR_fprintf(PR_STDERR, "%s: Couldn't set nickname on key\n",
+ progName);
+ goto shutdown;
+ }
+ }
+ rv = SECSuccess;
+ PrintKey(symKey);
+ PK11_FreeSymKey(symKey);
+ }
+ if (symKeyUtil.commands[cmd_DeleteKey].activated) {
+ PK11SymKey *symKey = FindKey(slot, name, &keyID, &pwdata);
+
+ if (!symKey) {
+ char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name);
+ PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
+ progName, keyName, PK11_GetTokenName(slot));
+ PORT_Free(keyName);
+ goto shutdown;
+ }
+
+ rv = PK11_DeleteTokenSymKey(symKey);
+ FreeKeyList(symKey);
+ if (rv != SECSuccess) {
+ PR_fprintf(PR_STDERR, "%s: Couldn't Delete Key \n", progName);
+ goto shutdown;
+ }
+ }
+ if (symKeyUtil.commands[cmd_UnwrapKey].activated) {
+ PK11SymKey *wrapKey = FindKey(slot, wrapName, &wrapKeyID, &pwdata);
+ PK11SymKey *symKey;
+ CK_MECHANISM_TYPE mechanism;
+
+ if (!wrapKey) {
+ char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID)
+ : PORT_Strdup(wrapName);
+ PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
+ progName, keyName, PK11_GetTokenName(slot));
+ PORT_Free(keyName);
+ goto shutdown;
+ }
+ mechanism = GetWrapMechanism(wrapKey);
+ if (mechanism == CKM_INVALID_MECHANISM) {
+ char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID)
+ : PORT_Strdup(wrapName);
+ PR_fprintf(PR_STDERR, "%s: %s on %s is an invalid wrapping key\n",
+ progName, keyName, PK11_GetTokenName(slot));
+ PORT_Free(keyName);
+ PK11_FreeSymKey(wrapKey);
+ goto shutdown;
+ }
+
+ symKey = PK11_UnwrapSymKeyWithFlagsPerm(wrapKey, mechanism, NULL,
+ &key, keyType, CKA_ENCRYPT, keySize, 0, PR_TRUE);
+ PK11_FreeSymKey(wrapKey);
+ if (!symKey) {
+ PR_fprintf(PR_STDERR, "%s: Unwrap Key Failed\n", progName);
+ goto shutdown;
+ }
+
+ if (symKeyUtil.options[opt_Nickname].activated) {
+ rv = PK11_SetSymKeyNickname(symKey, name);
+ if (rv != SECSuccess) {
+ PR_fprintf(PR_STDERR, "%s: Couldn't set name on key\n",
+ progName);
+ PK11_DeleteTokenSymKey(symKey);
+ PK11_FreeSymKey(symKey);
+ goto shutdown;
+ }
+ }
+ rv = SECSuccess;
+ PrintKey(symKey);
+ PK11_FreeSymKey(symKey);
+ }
+
+#define MAX_KEY_SIZE 4098
+ if (symKeyUtil.commands[cmd_WrapKey].activated) {
+ PK11SymKey *symKey = FindKey(slot, name, &keyID, &pwdata);
+ PK11SymKey *wrapKey;
+ CK_MECHANISM_TYPE mechanism;
+ SECItem data;
+ unsigned char buf[MAX_KEY_SIZE];
+ int ret;
+
+ if (!symKey) {
+ char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name);
+ PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
+ progName, keyName, PK11_GetTokenName(slot));
+ PORT_Free(keyName);
+ goto shutdown;
+ }
+
+ wrapKey = FindKey(slot, wrapName, &wrapKeyID, &pwdata);
+ if (!wrapKey) {
+ char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID)
+ : PORT_Strdup(wrapName);
+ PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
+ progName, keyName, PK11_GetTokenName(slot));
+ PORT_Free(keyName);
+ PK11_FreeSymKey(symKey);
+ goto shutdown;
+ }
+
+ mechanism = GetWrapMechanism(wrapKey);
+ if (mechanism == CKM_INVALID_MECHANISM) {
+ char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID)
+ : PORT_Strdup(wrapName);
+ PR_fprintf(PR_STDERR, "%s: %s on %s is an invalid wrapping key\n",
+ progName, keyName, PK11_GetTokenName(slot));
+ PORT_Free(keyName);
+ PK11_FreeSymKey(symKey);
+ PK11_FreeSymKey(wrapKey);
+ goto shutdown;
+ }
+
+ data.data = buf;
+ data.len = sizeof(buf);
+ rv = PK11_WrapSymKey(mechanism, NULL, wrapKey, symKey, &data);
+ PK11_FreeSymKey(symKey);
+ PK11_FreeSymKey(wrapKey);
+ if (rv != SECSuccess) {
+ PR_fprintf(PR_STDERR, "%s: Couldn't wrap key\n", progName);
+ goto shutdown;
+ }
+
+ /* WriteBuf outputs it's own error using SECU_PrintError */
+ ret = WriteBuf(symKeyUtil.options[opt_KeyFile].arg, &data);
+ if (ret < 0) {
+ goto shutdown;
+ }
+ }
+
+ if (symKeyUtil.commands[cmd_ImportKey].activated) {
+ PK11SymKey *symKey = PK11_ImportSymKey(slot, keyType,
+ PK11_OriginUnwrap, CKA_ENCRYPT, &key, &pwdata);
+ if (!symKey) {
+ PR_fprintf(PR_STDERR, "%s: Import Key Failed\n", progName);
+ goto shutdown;
+ }
+ if (symKeyUtil.options[opt_Nickname].activated) {
+ rv = PK11_SetSymKeyNickname(symKey, name);
+ if (rv != SECSuccess) {
+ PR_fprintf(PR_STDERR, "%s: Couldn't set name on key\n",
+ progName);
+ PK11_DeleteTokenSymKey(symKey);
+ PK11_FreeSymKey(symKey);
+ goto shutdown;
+ }
+ }
+ rv = SECSuccess;
+ PrintKey(symKey);
+ PK11_FreeSymKey(symKey);
+ }
+
+ /* List certs (-L) */
+ if (symKeyUtil.commands[cmd_ListKeys].activated) {
+ int printLabel = 1;
+ if (slot) {
+ rv = ListKeys(slot, &printLabel, &pwdata);
+ } else {
+ /* loop over all the slots */
+ PK11SlotList *slotList = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
+ PR_FALSE, PR_FALSE, &pwdata);
+ if (slotList == NULL) {
+ PR_fprintf(PR_STDERR, "%s: No tokens found\n", progName);
+ } else {
+ PK11SlotListElement *se;
+ for (se = PK11_GetFirstSafe(slotList); se;
+ se = PK11_GetNextSafe(slotList, se, PR_FALSE)) {
+ rv = ListKeys(se->slot, &printLabel, &pwdata);
+ if (rv != SECSuccess) {
+ break;
+ }
+ }
+ if (se) {
+ PORT_CheckSuccess(PK11_FreeSlotListElement(slotList, se));
+ }
+ PK11_FreeSlotList(slotList);
+ }
+ }
+ }
+
+ /* Move key (-M) */
+ if (symKeyUtil.commands[cmd_MoveKey].activated) {
+ PK11SlotInfo *target;
+ char *targetName = symKeyUtil.options[opt_TargetToken].arg;
+ PK11SymKey *newKey;
+ PK11SymKey *symKey = FindKey(slot, name, &keyID, &pwdata);
+ char *keyName = PK11_GetSymKeyNickname(symKey);
+
+ if (!symKey) {
+ char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name);
+ PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
+ progName, keyName, PK11_GetTokenName(slot));
+ PORT_Free(keyName);
+ goto shutdown;
+ }
+ target = PK11_FindSlotByName(targetName);
+ if (!target) {
+ PR_fprintf(PR_STDERR, "%s: Couldn't find slot %s\n",
+ progName, targetName);
+ goto shutdown;
+ }
+ rv = PK11_Authenticate(target, PR_FALSE, &pwdata);
+ if (rv != SECSuccess) {
+ PR_fprintf(PR_STDERR, "%s: Failed to log into %s\n",
+ progName, targetName);
+ goto shutdown;
+ }
+ rv = SECFailure;
+ newKey = PK11_MoveSymKey(target, CKA_ENCRYPT, 0, PR_TRUE, symKey);
+ if (!newKey) {
+ PR_fprintf(PR_STDERR, "%s: Couldn't move the key \n", progName);
+ goto shutdown;
+ }
+ if (keyName) {
+ rv = PK11_SetSymKeyNickname(newKey, keyName);
+ if (rv != SECSuccess) {
+ PK11_DeleteTokenSymKey(newKey);
+ PK11_FreeSymKey(newKey);
+ PR_fprintf(PR_STDERR, "%s: Couldn't set nickname on key\n",
+ progName);
+ goto shutdown;
+ }
+ }
+ PK11_FreeSymKey(newKey);
+ rv = SECSuccess;
+ }
+
+shutdown:
+ if (rv != SECSuccess) {
+ PR_fprintf(PR_STDERR, "%s: %s\n", progName,
+ SECU_Strerror(PORT_GetError()));
+ }
+
+ if (key.data) {
+ PORT_Free(key.data);
+ }
+
+ if (keyID.data) {
+ PORT_Free(keyID.data);
+ }
+
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ if (rv == SECSuccess) {
+ return 0;
+ } else {
+ return 255;
+ }
+}
diff --git a/security/nss/cmd/symkeyutil/symkeyutil.gyp b/security/nss/cmd/symkeyutil/symkeyutil.gyp
new file mode 100644
index 000000000..c39be293e
--- /dev/null
+++ b/security/nss/cmd/symkeyutil/symkeyutil.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'symkeyutil',
+ 'type': 'executable',
+ 'sources': [
+ 'symkeyutil.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/tests/Makefile b/security/nss/cmd/tests/Makefile
new file mode 100644
index 000000000..a263d41aa
--- /dev/null
+++ b/security/nss/cmd/tests/Makefile
@@ -0,0 +1,45 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
diff --git a/security/nss/cmd/tests/baddbdir.c b/security/nss/cmd/tests/baddbdir.c
new file mode 100644
index 000000000..b2bb2d681
--- /dev/null
+++ b/security/nss/cmd/tests/baddbdir.c
@@ -0,0 +1,38 @@
+/* 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/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "nss.h"
+#include "secerr.h"
+
+/*
+ * Regression test for bug 495097.
+ *
+ * NSS_InitReadWrite("sql:<dbdir>") should fail with SEC_ERROR_BAD_DATABASE
+ * if the directory <dbdir> doesn't exist.
+ */
+
+int
+main()
+{
+ SECStatus status;
+ int error;
+
+ status = NSS_InitReadWrite("sql:/no/such/db/dir");
+ if (status == SECSuccess) {
+ fprintf(stderr, "NSS_InitReadWrite succeeded unexpectedly\n");
+ exit(1);
+ }
+ error = PORT_GetError();
+ if (error != SEC_ERROR_BAD_DATABASE) {
+ fprintf(stderr, "NSS_InitReadWrite failed with the wrong error code: "
+ "%d\n",
+ error);
+ exit(1);
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/security/nss/cmd/tests/conflict.c b/security/nss/cmd/tests/conflict.c
new file mode 100644
index 000000000..80a4ebb7a
--- /dev/null
+++ b/security/nss/cmd/tests/conflict.c
@@ -0,0 +1,27 @@
+/* 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/. */
+
+/*
+ * This test verifies that NSS public headers don't conflict with common
+ * identifier names.
+ */
+
+#include "nssilckt.h"
+
+/*
+ * Bug 455424: nssilckt.h used to define the enumeration constant 'Lock',
+ * which conflicts with C++ code that defines a Lock class. This is a
+ * reduced test case in C for that name conflict.
+ */
+typedef struct {
+ int dummy;
+} Lock;
+
+Lock lock;
+
+int
+main()
+{
+ return 0;
+}
diff --git a/security/nss/cmd/tests/dertimetest.c b/security/nss/cmd/tests/dertimetest.c
new file mode 100644
index 000000000..2deedbc06
--- /dev/null
+++ b/security/nss/cmd/tests/dertimetest.c
@@ -0,0 +1,102 @@
+/* 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/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "secder.h"
+#include "secerr.h"
+
+int
+main()
+{
+ SECItem badTime;
+ PRTime prtime;
+ SECStatus rv;
+ int error;
+ PRBool failed = PR_FALSE;
+
+ /* A UTCTime string with an embedded null. */
+ badTime.type = siBuffer;
+ badTime.data = (unsigned char *)"091219000000Z\0junkjunkjunkjunkjunkjunk";
+ badTime.len = 38;
+ rv = DER_UTCTimeToTime(&prtime, &badTime);
+ if (rv == SECSuccess) {
+ fprintf(stderr, "DER_UTCTimeToTime should have failed but "
+ "succeeded\n");
+ failed = PR_TRUE;
+ } else {
+ error = PORT_GetError();
+ if (error != SEC_ERROR_INVALID_TIME) {
+ fprintf(stderr, "DER_UTCTimeToTime failed with error %d, "
+ "expected error %d\n",
+ error, SEC_ERROR_INVALID_TIME);
+ failed = PR_TRUE;
+ }
+ }
+
+ /* A UTCTime string with junk after a valid date/time. */
+ badTime.type = siBuffer;
+ badTime.data = (unsigned char *)"091219000000Zjunk";
+ badTime.len = 17;
+ rv = DER_UTCTimeToTime(&prtime, &badTime);
+ if (rv == SECSuccess) {
+ fprintf(stderr, "DER_UTCTimeToTime should have failed but "
+ "succeeded\n");
+ failed = PR_TRUE;
+ } else {
+ error = PORT_GetError();
+ if (error != SEC_ERROR_INVALID_TIME) {
+ fprintf(stderr, "DER_UTCTimeToTime failed with error %d, "
+ "expected error %d\n",
+ error, SEC_ERROR_INVALID_TIME);
+ failed = PR_TRUE;
+ }
+ }
+
+ /* A GeneralizedTime string with an embedded null. */
+ badTime.type = siBuffer;
+ badTime.data = (unsigned char *)"20091219000000Z\0junkjunkjunkjunkjunkjunk";
+ badTime.len = 40;
+ rv = DER_GeneralizedTimeToTime(&prtime, &badTime);
+ if (rv == SECSuccess) {
+ fprintf(stderr, "DER_GeneralizedTimeToTime should have failed but "
+ "succeeded\n");
+ failed = PR_TRUE;
+ } else {
+ error = PORT_GetError();
+ if (error != SEC_ERROR_INVALID_TIME) {
+ fprintf(stderr, "DER_GeneralizedTimeToTime failed with error %d, "
+ "expected error %d\n",
+ error, SEC_ERROR_INVALID_TIME);
+ failed = PR_TRUE;
+ }
+ }
+
+ /* A GeneralizedTime string with junk after a valid date/time. */
+ badTime.type = siBuffer;
+ badTime.data = (unsigned char *)"20091219000000Zjunk";
+ badTime.len = 19;
+ rv = DER_GeneralizedTimeToTime(&prtime, &badTime);
+ if (rv == SECSuccess) {
+ fprintf(stderr, "DER_GeneralizedTimeToTime should have failed but "
+ "succeeded\n");
+ failed = PR_TRUE;
+ } else {
+ error = PORT_GetError();
+ if (error != SEC_ERROR_INVALID_TIME) {
+ fprintf(stderr, "DER_GeneralizedTimeToTime failed with error %d, "
+ "expected error %d\n",
+ error, SEC_ERROR_INVALID_TIME);
+ failed = PR_TRUE;
+ }
+ }
+
+ if (failed) {
+ fprintf(stderr, "FAIL\n");
+ return 1;
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/security/nss/cmd/tests/encodeinttest.c b/security/nss/cmd/tests/encodeinttest.c
new file mode 100644
index 000000000..f0062ea5e
--- /dev/null
+++ b/security/nss/cmd/tests/encodeinttest.c
@@ -0,0 +1,62 @@
+/* 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/. */
+
+#include <stdio.h>
+
+#include "secasn1.h"
+
+struct TestCase {
+ long value;
+ unsigned char data[5];
+ unsigned int len;
+};
+
+static struct TestCase testCase[] = {
+/* XXX NSS doesn't generate the shortest encoding for negative values. */
+#if 0
+ { -128, { 0x80 }, 1 },
+ { -129, { 0xFF, 0x7F }, 2 },
+#endif
+
+ { 0, { 0x00 }, 1 },
+ { 127, { 0x7F }, 1 },
+ { 128, { 0x00, 0x80 }, 2 },
+ { 256, { 0x01, 0x00 }, 2 },
+ { 32768, { 0x00, 0x80, 0x00 }, 3 }
+};
+
+int
+main()
+{
+ PRBool failed = PR_FALSE;
+ unsigned int i;
+ unsigned int j;
+
+ for (i = 0; i < sizeof(testCase) / sizeof(testCase[0]); i++) {
+ SECItem encoded;
+ if (SEC_ASN1EncodeInteger(NULL, &encoded, testCase[i].value) == NULL) {
+ fprintf(stderr, "SEC_ASN1EncodeInteger failed\n");
+ failed = PR_TRUE;
+ continue;
+ }
+ if (encoded.len != testCase[i].len ||
+ memcmp(encoded.data, testCase[i].data, encoded.len) != 0) {
+ fprintf(stderr, "Encoding of %ld is incorrect:",
+ testCase[i].value);
+ for (j = 0; j < encoded.len; j++) {
+ fprintf(stderr, " 0x%02X", (unsigned int)encoded.data[j]);
+ }
+ fputs("\n", stderr);
+ failed = PR_TRUE;
+ }
+ PORT_Free(encoded.data);
+ }
+
+ if (failed) {
+ fprintf(stderr, "FAIL\n");
+ return 1;
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/security/nss/cmd/tests/manifest.mn b/security/nss/cmd/tests/manifest.mn
new file mode 100644
index 000000000..88b834736
--- /dev/null
+++ b/security/nss/cmd/tests/manifest.mn
@@ -0,0 +1,29 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ baddbdir.c \
+ conflict.c \
+ dertimetest.c \
+ encodeinttest.c \
+ nonspr10.c \
+ remtest.c \
+ secmodtest.c \
+ $(NULL)
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+PROGRAMS = $(CSRCS:.c=)
+
+TARGETS = $(PROGRAMS)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/tests/nonspr10.c b/security/nss/cmd/tests/nonspr10.c
new file mode 100644
index 000000000..295484a1c
--- /dev/null
+++ b/security/nss/cmd/tests/nonspr10.c
@@ -0,0 +1,90 @@
+/* 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/. */
+
+/*
+ * This test verifies that NSS public headers can be compiled with no
+ * NSPR 1.0 support.
+ */
+
+#define NO_NSPR_10_SUPPORT 1
+
+#include "base64.h"
+#include "blapit.h"
+#include "cert.h"
+#include "certdb.h"
+#include "certt.h"
+#include "ciferfam.h"
+#include "cmmf.h"
+#include "cmmft.h"
+#include "cms.h"
+#include "cmsreclist.h"
+#include "cmst.h"
+#include "crmf.h"
+#include "crmft.h"
+#include "cryptohi.h"
+#include "cryptoht.h"
+#include "ecl-exp.h"
+#include "hasht.h"
+#include "key.h"
+#include "keyhi.h"
+#include "keyt.h"
+#include "keythi.h"
+#include "nss.h"
+#include "nssb64.h"
+#include "nssb64t.h"
+#include "nssbase.h"
+#include "nssbaset.h"
+#include "nssckbi.h"
+#include "nssilckt.h"
+#include "nssilock.h"
+#include "nsslocks.h"
+#include "nssrwlk.h"
+#include "nssrwlkt.h"
+#include "ocsp.h"
+#include "ocspt.h"
+#include "p12.h"
+#include "p12plcy.h"
+#include "p12t.h"
+#include "pk11func.h"
+#include "pk11pqg.h"
+#include "pk11priv.h"
+#include "pk11pub.h"
+#include "pk11sdr.h"
+#include "pkcs11.h"
+#include "pkcs11t.h"
+#include "pkcs12.h"
+#include "pkcs12t.h"
+#include "pkcs7t.h"
+#include "portreg.h"
+#include "preenc.h"
+#include "secasn1.h"
+#include "secasn1t.h"
+#include "seccomon.h"
+#include "secder.h"
+#include "secdert.h"
+#include "secdig.h"
+#include "secdigt.h"
+#include "secerr.h"
+#include "sechash.h"
+#include "secitem.h"
+#include "secmime.h"
+#include "secmod.h"
+#include "secmodt.h"
+#include "secoid.h"
+#include "secoidt.h"
+#include "secpkcs5.h"
+#include "secpkcs7.h"
+#include "secport.h"
+#include "shsign.h"
+#include "smime.h"
+#include "ssl.h"
+#include "sslerr.h"
+#include "sslproto.h"
+#include "sslt.h"
+
+int
+main()
+{
+ return 0;
+}
diff --git a/security/nss/cmd/tests/remtest.c b/security/nss/cmd/tests/remtest.c
new file mode 100644
index 000000000..175ba923c
--- /dev/null
+++ b/security/nss/cmd/tests/remtest.c
@@ -0,0 +1,136 @@
+/* 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/. */
+
+/*
+**
+** Sample client side test program that uses SSL and NSS
+**
+*/
+
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#else
+#include "ctype.h" /* for isalpha() */
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "nspr.h"
+#include "prio.h"
+#include "prnetdb.h"
+#include "nss.h"
+#include "pk11func.h"
+#include "plgetopt.h"
+
+void
+Usage(char *progName)
+{
+ fprintf(stderr, "usage: %s [-d profiledir] -t tokenName [-r]\n", progName);
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ char *certDir = NULL;
+ PLOptState *optstate;
+ PLOptStatus optstatus;
+ SECStatus rv;
+ char *tokenName = NULL;
+ PRBool cont = PR_TRUE;
+ PK11TokenEvent event = PK11TokenPresentEvent;
+ PK11TokenStatus status;
+ char *progName;
+ PK11SlotInfo *slot;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName + 1 : argv[0];
+
+ optstate = PL_CreateOptState(argc, argv, "rd:t:");
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+
+ case 'd':
+ certDir = strdup(optstate->value);
+ certDir = SECU_ConfigDirectory(certDir);
+ break;
+ case 't':
+ tokenName = strdup(optstate->value);
+ break;
+ case 'r':
+ event = PK11TokenRemovedOrChangedEvent;
+ break;
+ }
+ }
+ if (optstatus == PL_OPT_BAD)
+ Usage(progName);
+
+ if (tokenName == NULL) {
+ Usage(progName);
+ }
+
+ if (!certDir) {
+ certDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
+ certDir = SECU_ConfigDirectory(certDir); /* call even if it's NULL */
+ }
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ /* open the cert DB, the key DB, and the secmod DB. */
+ rv = NSS_Init(certDir);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to open cert database");
+ return 1;
+ }
+
+ printf("Looking up tokenNamed: <%s>\n", tokenName);
+ slot = PK11_FindSlotByName(tokenName);
+ if (slot == NULL) {
+ SECU_PrintError(progName, "unable to find token");
+ return 1;
+ }
+
+ do {
+ status =
+ PK11_WaitForTokenEvent(slot, event, PR_INTERVAL_NO_TIMEOUT, 0, 0);
+
+ switch (status) {
+ case PK11TokenNotRemovable:
+ cont = PR_FALSE;
+ printf("%s Token Not Removable\n", tokenName);
+ break;
+ case PK11TokenChanged:
+ event = PK11TokenRemovedOrChangedEvent;
+ printf("%s Token Changed\n", tokenName);
+ break;
+ case PK11TokenRemoved:
+ event = PK11TokenPresentEvent;
+ printf("%s Token Removed\n", tokenName);
+ break;
+ case PK11TokenPresent:
+ event = PK11TokenRemovedOrChangedEvent;
+ printf("%s Token Present\n", tokenName);
+ break;
+ }
+ } while (cont);
+
+ PK11_FreeSlot(slot);
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ PR_Cleanup();
+ return 0;
+}
diff --git a/security/nss/cmd/tests/secmodtest.c b/security/nss/cmd/tests/secmodtest.c
new file mode 100644
index 000000000..2896ccf94
--- /dev/null
+++ b/security/nss/cmd/tests/secmodtest.c
@@ -0,0 +1,126 @@
+/* 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/. */
+
+/*
+ * Regression test for bug 588269
+ *
+ * SECMOD_CloseUserDB should properly close the user DB, and it should
+ * be possible to later re-add that same user DB as a new slot
+ */
+
+#include "secutil.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "nspr.h"
+#include "nss.h"
+#include "secerr.h"
+#include "pk11pub.h"
+#include "plgetopt.h"
+
+void
+Usage(char *progName)
+{
+ fprintf(stderr, "Usage: %s -d dbDir\n", progName);
+ exit(1);
+}
+
+SECStatus
+TestOpenCloseUserDB(char *progName, char *configDir, char *tokenName)
+{
+ char *modspec = NULL;
+ SECStatus rv = SECSuccess;
+ PK11SlotInfo *userDbSlot = NULL;
+
+ printf("Loading database <%s> - %s\n", configDir, tokenName);
+ modspec = PR_smprintf("configDir='%s' tokenDescription='%s'",
+ configDir, tokenName);
+ if (!modspec) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ userDbSlot = SECMOD_OpenUserDB(modspec);
+ PR_smprintf_free(modspec);
+ if (!userDbSlot) {
+ SECU_PrintError(progName, "couldn't open database");
+ rv = SECFailure;
+ goto loser;
+ }
+
+ printf("Closing database\n");
+ rv = SECMOD_CloseUserDB(userDbSlot);
+
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "couldn't close database");
+ }
+
+ PK11_FreeSlot(userDbSlot);
+
+loser:
+ return rv;
+}
+
+int
+main(int argc, char **argv)
+{
+ PLOptState *optstate;
+ PLOptStatus optstatus;
+ SECStatus rv = SECFailure;
+ char *progName;
+ char *dbDir = NULL;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName) {
+ progName = strrchr(argv[0], '\\');
+ }
+ progName = progName ? progName + 1 : argv[0];
+
+ optstate = PL_CreateOptState(argc, argv, "d:");
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'd':
+ dbDir = strdup(optstate->value);
+ break;
+ }
+ }
+ if (optstatus == PL_OPT_BAD || dbDir == NULL) {
+ Usage(progName);
+ }
+
+ rv = NSS_NoDB_Init(NULL);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to initialize NSS");
+ goto loser;
+ }
+
+ printf("Open and Close Test 1\n");
+ rv = TestOpenCloseUserDB(progName, dbDir, "Test Slot 1");
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ printf("Open and Close Test 2\n");
+ rv = TestOpenCloseUserDB(progName, dbDir, "Test Slot 2");
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+loser:
+ if (dbDir)
+ free(dbDir);
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ PR_Cleanup();
+
+ if (rv != SECSuccess) {
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/security/nss/cmd/tests/tests.gyp b/security/nss/cmd/tests/tests.gyp
new file mode 100644
index 000000000..148bb250e
--- /dev/null
+++ b/security/nss/cmd/tests/tests.gyp
@@ -0,0 +1,91 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'baddbdir',
+ 'type': 'executable',
+ 'sources': [
+ 'baddbdir.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ },
+ {
+ 'target_name': 'conflict',
+ 'type': 'executable',
+ 'sources': [
+ 'conflict.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ },
+ {
+ 'target_name': 'dertimetest',
+ 'type': 'executable',
+ 'sources': [
+ 'dertimetest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ },
+ {
+ 'target_name': 'encodeinttest',
+ 'type': 'executable',
+ 'sources': [
+ 'encodeinttest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ },
+ {
+ 'target_name': 'nonspr10',
+ 'type': 'executable',
+ 'sources': [
+ 'nonspr10.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ },
+ {
+ 'target_name': 'remtest',
+ 'type': 'executable',
+ 'sources': [
+ 'remtest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ },
+ {
+ 'target_name': 'secmodtest',
+ 'type': 'executable',
+ 'sources': [
+ 'secmodtest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/tstclnt/Makefile b/security/nss/cmd/tstclnt/Makefile
new file mode 100644
index 000000000..a27a3ce97
--- /dev/null
+++ b/security/nss/cmd/tstclnt/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#include ../platlibs.mk
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/tstclnt/manifest.mn b/security/nss/cmd/tstclnt/manifest.mn
new file mode 100644
index 000000000..5c1e4f611
--- /dev/null
+++ b/security/nss/cmd/tstclnt/manifest.mn
@@ -0,0 +1,23 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+# DIRS =
+
+CSRCS = tstclnt.c
+DEFINES += -DDLL_PREFIX=\"$(DLL_PREFIX)\" -DDLL_SUFFIX=\"$(DLL_SUFFIX)\"
+
+PROGRAM = tstclnt
+
diff --git a/security/nss/cmd/tstclnt/tstclnt.c b/security/nss/cmd/tstclnt/tstclnt.c
new file mode 100644
index 000000000..eb114e935
--- /dev/null
+++ b/security/nss/cmd/tstclnt/tstclnt.c
@@ -0,0 +1,1900 @@
+/* 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/. */
+
+/*
+**
+** Sample client side test program that uses SSL and NSS
+**
+*/
+
+#include "secutil.h"
+#include "basicutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#else
+#include <ctype.h> /* for isalpha() */
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "nspr.h"
+#include "prio.h"
+#include "prnetdb.h"
+#include "nss.h"
+#include "ocsp.h"
+#include "ssl.h"
+#include "sslproto.h"
+#include "pk11func.h"
+#include "secmod.h"
+#include "plgetopt.h"
+#include "plstr.h"
+
+#if defined(WIN32)
+#include <fcntl.h>
+#include <io.h>
+#endif
+
+#define PRINTF \
+ if (verbose) \
+ printf
+#define FPRINTF \
+ if (verbose) \
+ fprintf
+
+#define MAX_WAIT_FOR_SERVER 600
+#define WAIT_INTERVAL 100
+
+#define EXIT_CODE_HANDSHAKE_FAILED 254
+
+#define EXIT_CODE_SIDECHANNELTEST_GOOD 0
+#define EXIT_CODE_SIDECHANNELTEST_BADCERT 1
+#define EXIT_CODE_SIDECHANNELTEST_NODATA 2
+#define EXIT_CODE_SIDECHANNELTEST_REVOKED 3
+
+PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT;
+
+int ssl3CipherSuites[] = {
+ -1, /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
+ -1, /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA * b */
+ TLS_RSA_WITH_RC4_128_MD5, /* c */
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
+ TLS_RSA_WITH_DES_CBC_SHA, /* e */
+ -1, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 * f */
+ -1, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 * g */
+ -1, /* SSL_FORTEZZA_DMS_WITH_NULL_SHA * h */
+ TLS_RSA_WITH_NULL_MD5, /* i */
+ -1, /* SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA * j */
+ -1, /* SSL_RSA_FIPS_WITH_DES_CBC_SHA * k */
+ -1, /* TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA * l */
+ -1, /* TLS_RSA_EXPORT1024_WITH_RC4_56_SHA * m */
+ TLS_RSA_WITH_RC4_128_SHA, /* n */
+ TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */
+ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
+ TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
+ TLS_DHE_RSA_WITH_DES_CBC_SHA, /* r */
+ TLS_DHE_DSS_WITH_DES_CBC_SHA, /* s */
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* t */
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* u */
+ TLS_RSA_WITH_AES_128_CBC_SHA, /* v */
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* w */
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* x */
+ TLS_RSA_WITH_AES_256_CBC_SHA, /* y */
+ TLS_RSA_WITH_NULL_SHA, /* z */
+ 0
+};
+
+unsigned long __cmp_umuls;
+PRBool verbose;
+int dumpServerChain = 0;
+int renegotiationsToDo = 0;
+int renegotiationsDone = 0;
+
+static char *progName;
+
+secuPWData pwdata = { PW_NONE, 0 };
+
+SSLNamedGroup *enabledGroups = NULL;
+unsigned int enabledGroupsCount = 0;
+
+void
+printSecurityInfo(PRFileDesc *fd)
+{
+ CERTCertificate *cert;
+ const SECItemArray *csa;
+ const SECItem *scts;
+ SSL3Statistics *ssl3stats = SSL_GetStatistics();
+ SECStatus result;
+ SSLChannelInfo channel;
+ SSLCipherSuiteInfo suite;
+
+ result = SSL_GetChannelInfo(fd, &channel, sizeof channel);
+ if (result == SECSuccess &&
+ channel.length == sizeof channel &&
+ channel.cipherSuite) {
+ result = SSL_GetCipherSuiteInfo(channel.cipherSuite,
+ &suite, sizeof suite);
+ if (result == SECSuccess) {
+ FPRINTF(stderr,
+ "tstclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
+ channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
+ suite.effectiveKeyBits, suite.symCipherName,
+ suite.macBits, suite.macAlgorithmName);
+ FPRINTF(stderr,
+ "tstclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n"
+ " Compression: %s, Extended Master Secret: %s\n",
+ channel.authKeyBits, suite.authAlgorithmName,
+ channel.keaKeyBits, suite.keaTypeName,
+ channel.compressionMethodName,
+ channel.extendedMasterSecretUsed ? "Yes" : "No");
+ }
+ }
+ cert = SSL_RevealCert(fd);
+ if (cert) {
+ char *ip = CERT_NameToAscii(&cert->issuer);
+ char *sp = CERT_NameToAscii(&cert->subject);
+ if (sp) {
+ fprintf(stderr, "subject DN: %s\n", sp);
+ PORT_Free(sp);
+ }
+ if (ip) {
+ fprintf(stderr, "issuer DN: %s\n", ip);
+ PORT_Free(ip);
+ }
+ CERT_DestroyCertificate(cert);
+ cert = NULL;
+ }
+ fprintf(stderr,
+ "%ld cache hits; %ld cache misses, %ld cache not reusable\n"
+ "%ld stateless resumes\n",
+ ssl3stats->hsh_sid_cache_hits, ssl3stats->hsh_sid_cache_misses,
+ ssl3stats->hsh_sid_cache_not_ok, ssl3stats->hsh_sid_stateless_resumes);
+
+ csa = SSL_PeerStapledOCSPResponses(fd);
+ if (csa) {
+ fprintf(stderr, "Received %d Cert Status items (OCSP stapled data)\n",
+ csa->len);
+ }
+ scts = SSL_PeerSignedCertTimestamps(fd);
+ if (scts && scts->len) {
+ fprintf(stderr, "Received a Signed Certificate Timestamp of length"
+ " %u\n",
+ scts->len);
+ }
+}
+
+void
+handshakeCallback(PRFileDesc *fd, void *client_data)
+{
+ const char *secondHandshakeName = (char *)client_data;
+ if (secondHandshakeName) {
+ SSL_SetURL(fd, secondHandshakeName);
+ }
+ printSecurityInfo(fd);
+ if (renegotiationsDone < renegotiationsToDo) {
+ SSL_ReHandshake(fd, (renegotiationsToDo < 2));
+ ++renegotiationsDone;
+ }
+}
+
+static void
+PrintUsageHeader(const char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s -h host [-a 1st_hs_name ] [-a 2nd_hs_name ] [-p port]\n"
+ "[-D | -d certdir] [-C] [-b | -R root-module] \n"
+ "[-n nickname] [-Bafosvx] [-c ciphers] [-Y] [-Z]\n"
+ "[-V [min-version]:[max-version]] [-K] [-T] [-U]\n"
+ "[-r N] [-w passwd] [-W pwfile] [-q [-t seconds]] [-I groups]\n"
+ "[-A requestfile] [-L totalconnections]",
+ progName);
+}
+
+static void
+PrintParameterUsage(void)
+{
+ fprintf(stderr, "%-20s Send different SNI name. 1st_hs_name - at first\n"
+ "%-20s handshake, 2nd_hs_name - at second handshake.\n"
+ "%-20s Default is host from the -h argument.\n",
+ "-a name",
+ "", "");
+ fprintf(stderr, "%-20s Hostname to connect with\n", "-h host");
+ fprintf(stderr, "%-20s Port number for SSL server\n", "-p port");
+ fprintf(stderr,
+ "%-20s Directory with cert database (default is ~/.netscape)\n",
+ "-d certdir");
+ fprintf(stderr, "%-20s Run without a cert database\n", "-D");
+ fprintf(stderr, "%-20s Load the default \"builtins\" root CA module\n", "-b");
+ fprintf(stderr, "%-20s Load the given root CA module\n", "-R");
+ fprintf(stderr, "%-20s Print certificate chain information\n", "-C");
+ fprintf(stderr, "%-20s (use -C twice to print more certificate details)\n", "");
+ fprintf(stderr, "%-20s (use -C three times to include PEM format certificate dumps)\n", "");
+ fprintf(stderr, "%-20s Nickname of key and cert for client auth\n",
+ "-n nickname");
+ fprintf(stderr,
+ "%-20s Restricts the set of enabled SSL/TLS protocols versions.\n"
+ "%-20s All versions are enabled by default.\n"
+ "%-20s Possible values for min/max: ssl3 tls1.0 tls1.1 tls1.2 tls1.3\n"
+ "%-20s Example: \"-V ssl3:\" enables SSL 3 and newer.\n",
+ "-V [min]:[max]", "", "", "");
+ fprintf(stderr, "%-20s Send TLS_FALLBACK_SCSV\n", "-K");
+ fprintf(stderr, "%-20s Prints only payload data. Skips HTTP header.\n", "-S");
+ fprintf(stderr, "%-20s Client speaks first. \n", "-f");
+ fprintf(stderr, "%-20s Use synchronous certificate validation\n", "-O");
+ fprintf(stderr, "%-20s Override bad server cert. Make it OK.\n", "-o");
+ fprintf(stderr, "%-20s Disable SSL socket locking.\n", "-s");
+ fprintf(stderr, "%-20s Verbose progress reporting.\n", "-v");
+ fprintf(stderr, "%-20s Ping the server and then exit.\n", "-q");
+ fprintf(stderr, "%-20s Timeout for server ping (default: no timeout).\n", "-t seconds");
+ fprintf(stderr, "%-20s Renegotiate N times (resuming session if N>1).\n", "-r N");
+ fprintf(stderr, "%-20s Enable the session ticket extension.\n", "-u");
+ fprintf(stderr, "%-20s Enable compression.\n", "-z");
+ fprintf(stderr, "%-20s Enable false start.\n", "-g");
+ fprintf(stderr, "%-20s Enable the cert_status extension (OCSP stapling).\n", "-T");
+ fprintf(stderr, "%-20s Enable the signed_certificate_timestamp extension.\n", "-U");
+ fprintf(stderr, "%-20s Require fresh revocation info from side channel.\n"
+ "%-20s -F once means: require for server cert only\n"
+ "%-20s -F twice means: require for intermediates, too\n"
+ "%-20s (Connect, handshake with server, disable dynamic download\n"
+ "%-20s of OCSP/CRL, verify cert using CERT_PKIXVerifyCert.)\n"
+ "%-20s Exit code:\n"
+ "%-20s 0: have fresh and valid revocation data, status good\n"
+ "%-20s 1: cert failed to verify, prior to revocation checking\n"
+ "%-20s 2: missing, old or invalid revocation data\n"
+ "%-20s 3: have fresh and valid revocation data, status revoked\n",
+ "-F", "", "", "", "", "", "", "", "", "");
+ fprintf(stderr, "%-20s Test -F allows 0=any (default), 1=only OCSP, 2=only CRL\n", "-M");
+ fprintf(stderr, "%-20s Restrict ciphers\n", "-c ciphers");
+ fprintf(stderr, "%-20s Print cipher values allowed for parameter -c and exit\n", "-Y");
+ fprintf(stderr, "%-20s Enforce using an IPv4 destination address\n", "-4");
+ fprintf(stderr, "%-20s Enforce using an IPv6 destination address\n", "-6");
+ fprintf(stderr, "%-20s (Options -4 and -6 cannot be combined.)\n", "");
+ fprintf(stderr, "%-20s Enable the extended master secret extension [RFC7627]\n", "-G");
+ fprintf(stderr, "%-20s Require the use of FFDHE supported groups "
+ "[I-D.ietf-tls-negotiated-ff-dhe]\n",
+ "-H");
+ fprintf(stderr, "%-20s Read from a file instead of stdin\n", "-A");
+ fprintf(stderr, "%-20s Allow 0-RTT data (TLS 1.3 only)\n", "-Z");
+ fprintf(stderr, "%-20s Disconnect and reconnect up to N times total\n", "-L");
+ fprintf(stderr, "%-20s Comma separated list of enabled groups for TLS key exchange.\n"
+ "%-20s The following values are valid:\n"
+ "%-20s P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192\n",
+ "-I", "", "");
+}
+
+static void
+Usage(const char *progName)
+{
+ PrintUsageHeader(progName);
+ PrintParameterUsage();
+ exit(1);
+}
+
+static void
+PrintCipherUsage(const char *progName)
+{
+ PrintUsageHeader(progName);
+ fprintf(stderr, "%-20s Letter(s) chosen from the following list\n",
+ "-c ciphers");
+ fprintf(stderr,
+ "c SSL3 RSA WITH RC4 128 MD5\n"
+ "d SSL3 RSA WITH 3DES EDE CBC SHA\n"
+ "e SSL3 RSA WITH DES CBC SHA\n"
+ "i SSL3 RSA WITH NULL MD5\n"
+ "n SSL3 RSA WITH RC4 128 SHA\n"
+ "o SSL3 DHE DSS WITH RC4 128 SHA\n"
+ "p SSL3 DHE RSA WITH 3DES EDE CBC SHA\n"
+ "q SSL3 DHE DSS WITH 3DES EDE CBC SHA\n"
+ "r SSL3 DHE RSA WITH DES CBC SHA\n"
+ "s SSL3 DHE DSS WITH DES CBC SHA\n"
+ "t SSL3 DHE DSS WITH AES 128 CBC SHA\n"
+ "u SSL3 DHE RSA WITH AES 128 CBC SHA\n"
+ "v SSL3 RSA WITH AES 128 CBC SHA\n"
+ "w SSL3 DHE DSS WITH AES 256 CBC SHA\n"
+ "x SSL3 DHE RSA WITH AES 256 CBC SHA\n"
+ "y SSL3 RSA WITH AES 256 CBC SHA\n"
+ "z SSL3 RSA WITH NULL SHA\n"
+ "\n"
+ ":WXYZ Use cipher with hex code { 0xWX , 0xYZ } in TLS\n");
+ exit(1);
+}
+
+void
+milliPause(PRUint32 milli)
+{
+ PRIntervalTime ticks = PR_MillisecondsToInterval(milli);
+ PR_Sleep(ticks);
+}
+
+void
+disableAllSSLCiphers(void)
+{
+ const PRUint16 *cipherSuites = SSL_GetImplementedCiphers();
+ int i = SSL_GetNumImplementedCiphers();
+ SECStatus rv;
+
+ /* disable all the SSL3 cipher suites */
+ while (--i >= 0) {
+ PRUint16 suite = cipherSuites[i];
+ rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
+ if (rv != SECSuccess) {
+ PRErrorCode err = PR_GetError();
+ fprintf(stderr,
+ "SSL_CipherPrefSet didn't like value 0x%04x (i = %d): %s\n",
+ suite, i, SECU_Strerror(err));
+ exit(2);
+ }
+ }
+}
+
+typedef struct
+{
+ PRBool shouldPause; /* PR_TRUE if we should use asynchronous peer cert
+ * authentication */
+ PRBool isPaused; /* PR_TRUE if libssl is waiting for us to validate the
+ * peer's certificate and restart the handshake. */
+ void *dbHandle; /* Certificate database handle to use while
+ * authenticating the peer's certificate. */
+ PRBool testFreshStatusFromSideChannel;
+ PRErrorCode sideChannelRevocationTestResultCode;
+ PRBool requireDataForIntermediates;
+ PRBool allowOCSPSideChannelData;
+ PRBool allowCRLSideChannelData;
+} ServerCertAuth;
+
+/*
+ * Callback is called when incoming certificate is not valid.
+ * Returns SECSuccess to accept the cert anyway, SECFailure to reject.
+ */
+static SECStatus
+ownBadCertHandler(void *arg, PRFileDesc *socket)
+{
+ PRErrorCode err = PR_GetError();
+ /* can log invalid cert here */
+ fprintf(stderr, "Bad server certificate: %d, %s\n", err,
+ SECU_Strerror(err));
+ return SECSuccess; /* override, say it's OK. */
+}
+
+#define EXIT_CODE_SIDECHANNELTEST_GOOD 0
+#define EXIT_CODE_SIDECHANNELTEST_BADCERT 1
+#define EXIT_CODE_SIDECHANNELTEST_NODATA 2
+#define EXIT_CODE_SIDECHANNELTEST_REVOKED 3
+
+static void
+verifyFromSideChannel(CERTCertificate *cert, ServerCertAuth *sca)
+{
+ PRUint64 revDoNotUse =
+ CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD;
+
+ PRUint64 revUseLocalOnlyAndSoftFail =
+ CERT_REV_M_TEST_USING_THIS_METHOD |
+ CERT_REV_M_FORBID_NETWORK_FETCHING |
+ CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE |
+ CERT_REV_M_IGNORE_MISSING_FRESH_INFO |
+ CERT_REV_M_STOP_TESTING_ON_FRESH_INFO;
+
+ PRUint64 revUseLocalOnlyAndHardFail =
+ CERT_REV_M_TEST_USING_THIS_METHOD |
+ CERT_REV_M_FORBID_NETWORK_FETCHING |
+ CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE |
+ CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO |
+ CERT_REV_M_STOP_TESTING_ON_FRESH_INFO;
+
+ PRUint64 methodFlagsDoNotUse[2];
+ PRUint64 methodFlagsCheckSoftFail[2];
+ PRUint64 methodFlagsCheckHardFail[2];
+ CERTRevocationTests revTestsDoNotCheck;
+ CERTRevocationTests revTestsOverallSoftFail;
+ CERTRevocationTests revTestsOverallHardFail;
+ CERTRevocationFlags rev;
+ CERTValInParam cvin[2];
+ CERTValOutParam cvout[1];
+ SECStatus rv;
+
+ methodFlagsDoNotUse[cert_revocation_method_crl] = revDoNotUse;
+ methodFlagsDoNotUse[cert_revocation_method_ocsp] = revDoNotUse;
+
+ methodFlagsCheckSoftFail[cert_revocation_method_crl] =
+ sca->allowCRLSideChannelData ? revUseLocalOnlyAndSoftFail : revDoNotUse;
+ methodFlagsCheckSoftFail[cert_revocation_method_ocsp] =
+ sca->allowOCSPSideChannelData ? revUseLocalOnlyAndSoftFail : revDoNotUse;
+
+ methodFlagsCheckHardFail[cert_revocation_method_crl] =
+ sca->allowCRLSideChannelData ? revUseLocalOnlyAndHardFail : revDoNotUse;
+ methodFlagsCheckHardFail[cert_revocation_method_ocsp] =
+ sca->allowOCSPSideChannelData ? revUseLocalOnlyAndHardFail : revDoNotUse;
+
+ revTestsDoNotCheck.cert_rev_flags_per_method = methodFlagsDoNotUse;
+ revTestsDoNotCheck.number_of_defined_methods = 2;
+ revTestsDoNotCheck.number_of_preferred_methods = 0;
+ revTestsDoNotCheck.cert_rev_method_independent_flags =
+ CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
+ CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT;
+
+ revTestsOverallSoftFail.cert_rev_flags_per_method = 0; /* must define later */
+ revTestsOverallSoftFail.number_of_defined_methods = 2;
+ revTestsOverallSoftFail.number_of_preferred_methods = 0;
+ revTestsOverallSoftFail.cert_rev_method_independent_flags =
+ CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
+ CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT;
+
+ revTestsOverallHardFail.cert_rev_flags_per_method = 0; /* must define later */
+ revTestsOverallHardFail.number_of_defined_methods = 2;
+ revTestsOverallHardFail.number_of_preferred_methods = 0;
+ revTestsOverallHardFail.cert_rev_method_independent_flags =
+ CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
+ CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
+
+ rev.chainTests = revTestsDoNotCheck;
+ rev.leafTests = revTestsDoNotCheck;
+
+ cvin[0].type = cert_pi_revocationFlags;
+ cvin[0].value.pointer.revocation = &rev;
+ cvin[1].type = cert_pi_end;
+
+ cvout[0].type = cert_po_end;
+
+ /* Strategy:
+ *
+ * Verify with revocation checking disabled.
+ * On failure return 1.
+ *
+ * if result if "good", then continue testing.
+ *
+ * Verify with CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO.
+ * If result is good, return 0.
+ *
+ * On failure continue testing, find out why it failed.
+ *
+ * Verify with CERT_REV_M_IGNORE_MISSING_FRESH_INFO
+ *
+ * If result is "good", then our previous test failed,
+ * because we don't have fresh revocation info, return 2.
+ *
+ * If result is still bad, we do have revocation info,
+ * and it says "revoked" or something equivalent, return 3.
+ */
+
+ /* revocation checking disabled */
+ rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer,
+ cvin, cvout, NULL);
+ if (rv != SECSuccess) {
+ sca->sideChannelRevocationTestResultCode =
+ EXIT_CODE_SIDECHANNELTEST_BADCERT;
+ return;
+ }
+
+ /* revocation checking, hard fail */
+ if (sca->allowOCSPSideChannelData && sca->allowCRLSideChannelData) {
+ /* any method is allowed. use soft fail on individual checks,
+ * but use hard fail on the overall check
+ */
+ revTestsOverallHardFail.cert_rev_flags_per_method = methodFlagsCheckSoftFail;
+ } else {
+ /* only one method is allowed. use hard fail on the individual checks.
+ * hard/soft fail is irrelevant on overall flags.
+ */
+ revTestsOverallHardFail.cert_rev_flags_per_method = methodFlagsCheckHardFail;
+ }
+ rev.leafTests = revTestsOverallHardFail;
+ rev.chainTests =
+ sca->requireDataForIntermediates ? revTestsOverallHardFail : revTestsDoNotCheck;
+ rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer,
+ cvin, cvout, NULL);
+ if (rv == SECSuccess) {
+ sca->sideChannelRevocationTestResultCode =
+ EXIT_CODE_SIDECHANNELTEST_GOOD;
+ return;
+ }
+
+ /* revocation checking, soft fail */
+ revTestsOverallSoftFail.cert_rev_flags_per_method = methodFlagsCheckSoftFail;
+ rev.leafTests = revTestsOverallSoftFail;
+ rev.chainTests =
+ sca->requireDataForIntermediates ? revTestsOverallSoftFail : revTestsDoNotCheck;
+ rv = CERT_PKIXVerifyCert(cert, certificateUsageSSLServer,
+ cvin, cvout, NULL);
+ if (rv == SECSuccess) {
+ sca->sideChannelRevocationTestResultCode =
+ EXIT_CODE_SIDECHANNELTEST_NODATA;
+ return;
+ }
+
+ sca->sideChannelRevocationTestResultCode =
+ EXIT_CODE_SIDECHANNELTEST_REVOKED;
+}
+
+static void
+dumpCertificatePEM(CERTCertificate *cert)
+{
+ SECItem data;
+ data.data = cert->derCert.data;
+ data.len = cert->derCert.len;
+ fprintf(stderr, "%s\n%s\n%s\n", NS_CERT_HEADER,
+ BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER);
+}
+
+static void
+dumpServerCertificateChain(PRFileDesc *fd)
+{
+ CERTCertList *peerCertChain = NULL;
+ CERTCertListNode *node = NULL;
+ CERTCertificate *peerCert = NULL;
+ CERTCertificateList *foundChain = NULL;
+ SECU_PPFunc dumpFunction = NULL;
+ PRBool dumpCertPEM = PR_FALSE;
+
+ if (!dumpServerChain) {
+ return;
+ } else if (dumpServerChain == 1) {
+ dumpFunction = (SECU_PPFunc)SECU_PrintCertificateBasicInfo;
+ } else {
+ dumpFunction = (SECU_PPFunc)SECU_PrintCertificate;
+ if (dumpServerChain > 2) {
+ dumpCertPEM = PR_TRUE;
+ }
+ }
+
+ SECU_EnableWrap(PR_FALSE);
+
+ fprintf(stderr, "==== certificate(s) sent by server: ====\n");
+ peerCertChain = SSL_PeerCertificateChain(fd);
+ if (peerCertChain) {
+ node = CERT_LIST_HEAD(peerCertChain);
+ while (!CERT_LIST_END(node, peerCertChain)) {
+ CERTCertificate *cert = node->cert;
+ SECU_PrintSignedContent(stderr, &cert->derCert, "Certificate", 0,
+ dumpFunction);
+ if (dumpCertPEM) {
+ dumpCertificatePEM(cert);
+ }
+ node = CERT_LIST_NEXT(node);
+ }
+ }
+
+ if (peerCertChain) {
+ peerCert = SSL_RevealCert(fd);
+ if (peerCert) {
+ foundChain = CERT_CertChainFromCert(peerCert, certificateUsageSSLServer,
+ PR_TRUE);
+ }
+ if (foundChain) {
+ unsigned int count = 0;
+ fprintf(stderr, "==== locally found issuer certificate(s): ====\n");
+ for (count = 0; count < (unsigned int)foundChain->len; count++) {
+ CERTCertificate *c;
+ PRBool wasSentByServer = PR_FALSE;
+ c = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &foundChain->certs[count]);
+
+ node = CERT_LIST_HEAD(peerCertChain);
+ while (!CERT_LIST_END(node, peerCertChain)) {
+ CERTCertificate *cert = node->cert;
+ if (CERT_CompareCerts(cert, c)) {
+ wasSentByServer = PR_TRUE;
+ break;
+ }
+ node = CERT_LIST_NEXT(node);
+ }
+
+ if (!wasSentByServer) {
+ SECU_PrintSignedContent(stderr, &c->derCert, "Certificate", 0,
+ dumpFunction);
+ if (dumpCertPEM) {
+ dumpCertificatePEM(c);
+ }
+ }
+ CERT_DestroyCertificate(c);
+ }
+ CERT_DestroyCertificateList(foundChain);
+ }
+ if (peerCert) {
+ CERT_DestroyCertificate(peerCert);
+ }
+
+ CERT_DestroyCertList(peerCertChain);
+ peerCertChain = NULL;
+ }
+
+ fprintf(stderr, "==== end of certificate chain information ====\n");
+ fflush(stderr);
+}
+
+static SECStatus
+ownAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
+ PRBool isServer)
+{
+ ServerCertAuth *serverCertAuth = (ServerCertAuth *)arg;
+
+ if (dumpServerChain) {
+ dumpServerCertificateChain(fd);
+ }
+
+ if (!serverCertAuth->shouldPause) {
+ CERTCertificate *cert;
+ unsigned int i;
+ const SECItemArray *csa;
+
+ if (!serverCertAuth->testFreshStatusFromSideChannel) {
+ return SSL_AuthCertificate(serverCertAuth->dbHandle,
+ fd, checkSig, isServer);
+ }
+
+ /* No verification attempt must have happened before now,
+ * to ensure revocation data has been actively retrieved yet,
+ * or our test will produce incorrect results.
+ */
+
+ cert = SSL_RevealCert(fd);
+ if (!cert) {
+ exit(254);
+ }
+
+ csa = SSL_PeerStapledOCSPResponses(fd);
+ if (csa) {
+ for (i = 0; i < csa->len; ++i) {
+ PORT_SetError(0);
+ if (CERT_CacheOCSPResponseFromSideChannel(
+ serverCertAuth->dbHandle, cert, PR_Now(),
+ &csa->items[i], arg) != SECSuccess) {
+ PORT_Assert(PR_GetError() != 0);
+ }
+ }
+ }
+
+ verifyFromSideChannel(cert, serverCertAuth);
+ CERT_DestroyCertificate(cert);
+ /* return success to ensure our caller will continue and we will
+ * reach the code that handles
+ * serverCertAuth->sideChannelRevocationTestResultCode
+ */
+ return SECSuccess;
+ }
+
+ FPRINTF(stderr, "%s: using asynchronous certificate validation\n",
+ progName);
+
+ PORT_Assert(!serverCertAuth->isPaused);
+ serverCertAuth->isPaused = PR_TRUE;
+ return SECWouldBlock;
+}
+
+SECStatus
+own_GetClientAuthData(void *arg,
+ PRFileDesc *socket,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+ if (verbose > 1) {
+ SECStatus rv;
+ fprintf(stderr, "Server requested Client Authentication\n");
+ if (caNames && caNames->nnames > 0) {
+ PLArenaPool *arena = caNames->arena;
+ if (!arena)
+ arena = PORT_NewArena(2048);
+ if (arena) {
+ int i;
+ for (i = 0; i < caNames->nnames; ++i) {
+ char *nameString;
+ CERTName dn;
+ rv = SEC_QuickDERDecodeItem(arena,
+ &dn,
+ SEC_ASN1_GET(CERT_NameTemplate),
+ caNames->names + i);
+ if (rv != SECSuccess)
+ continue;
+ nameString = CERT_NameToAscii(&dn);
+ if (!nameString)
+ continue;
+ fprintf(stderr, "CA[%d]: %s\n", i + 1, nameString);
+ PORT_Free(nameString);
+ }
+ if (!caNames->arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ }
+ }
+ rv = NSS_GetClientAuthData(arg, socket, caNames, pRetCert, pRetKey);
+ if (rv == SECSuccess && *pRetCert) {
+ char *nameString = CERT_NameToAscii(&((*pRetCert)->subject));
+ if (nameString) {
+ fprintf(stderr, "sent cert: %s\n", nameString);
+ PORT_Free(nameString);
+ }
+ } else {
+ fprintf(stderr, "send no cert\n");
+ }
+ return rv;
+ }
+ return NSS_GetClientAuthData(arg, socket, caNames, pRetCert, pRetKey);
+}
+
+#if defined(WIN32) || defined(OS2)
+void
+thread_main(void *arg)
+{
+ PRFileDesc *ps = (PRFileDesc *)arg;
+ PRFileDesc *std_in = PR_GetSpecialFD(PR_StandardInput);
+ int wc, rc;
+ char buf[256];
+
+#ifdef WIN32
+ {
+ /* Put stdin into O_BINARY mode
+ ** or else incoming \r\n's will become \n's.
+ */
+ int smrv = _setmode(_fileno(stdin), _O_BINARY);
+ if (smrv == -1) {
+ fprintf(stderr,
+ "%s: Cannot change stdin to binary mode. Use -i option instead.\n",
+ progName);
+ /* plow ahead anyway */
+ }
+ }
+#endif
+
+ do {
+ rc = PR_Read(std_in, buf, sizeof buf);
+ if (rc <= 0)
+ break;
+ wc = PR_Send(ps, buf, rc, 0, maxInterval);
+ } while (wc == rc);
+ PR_Close(ps);
+}
+
+#endif
+
+static void
+printHostNameAndAddr(const char *host, const PRNetAddr *addr)
+{
+ PRUint16 port = PR_NetAddrInetPort(addr);
+ char addrBuf[80];
+ PRStatus st = PR_NetAddrToString(addr, addrBuf, sizeof addrBuf);
+
+ if (st == PR_SUCCESS) {
+ port = PR_ntohs(port);
+ FPRINTF(stderr, "%s: connecting to %s:%hu (address=%s)\n",
+ progName, host, port, addrBuf);
+ }
+}
+
+/*
+ * Prints output according to skipProtoHeader flag. If skipProtoHeader
+ * is not set, prints without any changes, otherwise looking
+ * for \n\r\n(empty line sequence: HTTP header separator) and
+ * prints everything after it.
+ */
+static void
+separateReqHeader(const PRFileDesc *outFd, const char *buf, const int nb,
+ PRBool *wrStarted, int *ptrnMatched)
+{
+
+ /* it is sufficient to look for only "\n\r\n". Hopping that
+ * HTTP response format satisfies the standard */
+ char *ptrnStr = "\n\r\n";
+ char *resPtr;
+
+ if (nb == 0) {
+ return;
+ }
+
+ if (*ptrnMatched > 0) {
+ /* Get here only if previous separateReqHeader call found
+ * only a fragment of "\n\r\n" in previous buffer. */
+ PORT_Assert(*ptrnMatched < 3);
+
+ /* the size of fragment of "\n\r\n" what we want to find in this
+ * buffer is equal to *ptrnMatched */
+ if (*ptrnMatched <= nb) {
+ /* move the pointer to the beginning of the fragment */
+ int strSize = *ptrnMatched;
+ char *tmpPtrn = ptrnStr + (3 - strSize);
+ if (PL_strncmp(buf, tmpPtrn, strSize) == 0) {
+ /* print the rest of the buffer(without the fragment) */
+ PR_Write((void *)outFd, buf + strSize, nb - strSize);
+ *wrStarted = PR_TRUE;
+ return;
+ }
+ } else {
+ /* we are here only when nb == 1 && *ptrnMatched == 2 */
+ if (*buf == '\r') {
+ *ptrnMatched = 1;
+ } else {
+ *ptrnMatched = 0;
+ }
+ return;
+ }
+ }
+ resPtr = PL_strnstr(buf, ptrnStr, nb);
+ if (resPtr != NULL) {
+ /* if "\n\r\n" was found in the buffer, calculate offset
+ * and print the rest of the buffer */
+ int newBn = nb - (resPtr - buf + 3); /* 3 is the length of "\n\r\n" */
+
+ PR_Write((void *)outFd, resPtr + 3, newBn);
+ *wrStarted = PR_TRUE;
+ return;
+ } else {
+ /* try to find a fragment of "\n\r\n" at the end of the buffer.
+ * if found, set *ptrnMatched to the number of chars left to find
+ * in the next buffer.*/
+ int i;
+ for (i = 1; i < 3; i++) {
+ char *bufPrt;
+ int strSize = 3 - i;
+
+ if (strSize > nb) {
+ continue;
+ }
+ bufPrt = (char *)(buf + nb - strSize);
+
+ if (PL_strncmp(bufPrt, ptrnStr, strSize) == 0) {
+ *ptrnMatched = i;
+ return;
+ }
+ }
+ }
+}
+
+#define SSOCK_FD 0
+#define STDIN_FD 1
+
+#define HEXCHAR_TO_INT(c, i) \
+ if (((c) >= '0') && ((c) <= '9')) { \
+ i = (c) - '0'; \
+ } else if (((c) >= 'a') && ((c) <= 'f')) { \
+ i = (c) - 'a' + 10; \
+ } else if (((c) >= 'A') && ((c) <= 'F')) { \
+ i = (c) - 'A' + 10; \
+ } else { \
+ Usage(progName); \
+ }
+
+static SECStatus
+restartHandshakeAfterServerCertIfNeeded(PRFileDesc *fd,
+ ServerCertAuth *serverCertAuth,
+ PRBool override)
+{
+ SECStatus rv;
+ PRErrorCode error;
+
+ if (!serverCertAuth->isPaused)
+ return SECSuccess;
+
+ FPRINTF(stderr, "%s: handshake was paused by auth certificate hook\n",
+ progName);
+
+ serverCertAuth->isPaused = PR_FALSE;
+ rv = SSL_AuthCertificate(serverCertAuth->dbHandle, fd, PR_TRUE, PR_FALSE);
+ if (rv != SECSuccess) {
+ error = PR_GetError();
+ if (error == 0) {
+ PR_NOT_REACHED("SSL_AuthCertificate return SECFailure without "
+ "setting error code.");
+ error = PR_INVALID_STATE_ERROR;
+ } else if (override) {
+ rv = ownBadCertHandler(NULL, fd);
+ }
+ }
+ if (rv == SECSuccess) {
+ error = 0;
+ }
+
+ if (SSL_AuthCertificateComplete(fd, error) != SECSuccess) {
+ rv = SECFailure;
+ }
+
+ return rv;
+}
+
+char *host = NULL;
+char *nickname = NULL;
+char *cipherString = NULL;
+int multiplier = 0;
+SSLVersionRange enabledVersions;
+int disableLocking = 0;
+int enableSessionTickets = 0;
+int enableCompression = 0;
+int enableFalseStart = 0;
+int enableCertStatus = 0;
+int enableSignedCertTimestamps = 0;
+int forceFallbackSCSV = 0;
+int enableExtendedMasterSecret = 0;
+PRBool requireDHNamedGroups = 0;
+PRSocketOptionData opt;
+PRNetAddr addr;
+PRBool allowIPv4 = PR_TRUE;
+PRBool allowIPv6 = PR_TRUE;
+PRBool pingServerFirst = PR_FALSE;
+int pingTimeoutSeconds = -1;
+PRBool clientSpeaksFirst = PR_FALSE;
+PRBool skipProtoHeader = PR_FALSE;
+ServerCertAuth serverCertAuth;
+char *hs1SniHostName = NULL;
+char *hs2SniHostName = NULL;
+PRUint16 portno = 443;
+int override = 0;
+char *requestString = NULL;
+PRInt32 requestStringLen = 0;
+PRBool enableZeroRtt = PR_FALSE;
+
+static int
+writeBytesToServer(PRFileDesc *s, PRPollDesc *pollset, const char *buf, int nb)
+{
+ SECStatus rv;
+ const char *bufp = buf;
+
+ FPRINTF(stderr, "%s: Writing %d bytes to server\n",
+ progName, nb);
+ do {
+ PRInt32 cc = PR_Send(s, bufp, nb, 0, maxInterval);
+ if (cc < 0) {
+ PRErrorCode err = PR_GetError();
+ if (err != PR_WOULD_BLOCK_ERROR) {
+ SECU_PrintError(progName,
+ "write to SSL socket failed");
+ return 254;
+ }
+ cc = 0;
+ }
+ bufp += cc;
+ nb -= cc;
+ if (nb <= 0)
+ break;
+
+ rv = restartHandshakeAfterServerCertIfNeeded(s,
+ &serverCertAuth, override);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "authentication of server cert failed");
+ return EXIT_CODE_HANDSHAKE_FAILED;
+ }
+
+ pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ pollset[SSOCK_FD].out_flags = 0;
+ FPRINTF(stderr,
+ "%s: about to call PR_Poll on writable socket !\n",
+ progName);
+ cc = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (cc < 0) {
+ SECU_PrintError(progName,
+ "PR_Poll failed");
+ return -1;
+ }
+ FPRINTF(stderr,
+ "%s: PR_Poll returned with writable socket !\n",
+ progName);
+ } while (1);
+
+ return 0;
+}
+
+static int
+run_client(void)
+{
+ int headerSeparatorPtrnId = 0;
+ int error = 0;
+ SECStatus rv;
+ PRStatus status;
+ PRInt32 filesReady;
+ int npds;
+ PRFileDesc *s = NULL;
+ PRFileDesc *std_out;
+ PRPollDesc pollset[2];
+ PRBool wrStarted = PR_FALSE;
+ char *requestStringInt = requestString;
+
+ /* Create socket */
+ s = PR_OpenTCPSocket(addr.raw.family);
+ if (s == NULL) {
+ SECU_PrintError(progName, "error creating socket");
+ error = 1;
+ goto done;
+ }
+
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_TRUE; /* default */
+ if (serverCertAuth.testFreshStatusFromSideChannel) {
+ opt.value.non_blocking = PR_FALSE;
+ }
+ status = PR_SetSocketOption(s, &opt);
+ if (status != PR_SUCCESS) {
+ SECU_PrintError(progName, "error setting socket options");
+ error = 1;
+ goto done;
+ }
+
+ s = SSL_ImportFD(NULL, s);
+ if (s == NULL) {
+ SECU_PrintError(progName, "error importing socket");
+ error = 1;
+ goto done;
+ }
+
+ SSL_SetPKCS11PinArg(s, &pwdata);
+
+ rv = SSL_OptionSet(s, SSL_SECURITY, 1);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling socket");
+ error = 1;
+ goto done;
+ }
+
+ rv = SSL_OptionSet(s, SSL_HANDSHAKE_AS_CLIENT, 1);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling client handshake");
+ error = 1;
+ goto done;
+ }
+
+ /* all SSL3 cipher suites are enabled by default. */
+ if (cipherString) {
+ char *cstringSaved = cipherString;
+ int ndx;
+
+ while (0 != (ndx = *cipherString++)) {
+ int cipher = 0;
+
+ if (ndx == ':') {
+ int ctmp = 0;
+
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= (ctmp << 12);
+ cipherString++;
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= (ctmp << 8);
+ cipherString++;
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= (ctmp << 4);
+ cipherString++;
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= ctmp;
+ cipherString++;
+ } else {
+ if (!isalpha(ndx))
+ Usage(progName);
+ ndx = tolower(ndx) - 'a';
+ if (ndx < PR_ARRAY_SIZE(ssl3CipherSuites)) {
+ cipher = ssl3CipherSuites[ndx];
+ }
+ }
+ if (cipher > 0) {
+ SECStatus status;
+ status = SSL_CipherPrefSet(s, cipher, SSL_ALLOWED);
+ if (status != SECSuccess)
+ SECU_PrintError(progName, "SSL_CipherPrefSet()");
+ } else {
+ Usage(progName);
+ }
+ }
+ PORT_Free(cstringSaved);
+ }
+
+ rv = SSL_VersionRangeSet(s, &enabledVersions);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error setting SSL/TLS version range ");
+ error = 1;
+ goto done;
+ }
+
+ /* disable SSL socket locking */
+ rv = SSL_OptionSet(s, SSL_NO_LOCKS, disableLocking);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error disabling SSL socket locking");
+ error = 1;
+ goto done;
+ }
+
+ /* enable Session Ticket extension. */
+ rv = SSL_OptionSet(s, SSL_ENABLE_SESSION_TICKETS, enableSessionTickets);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling Session Ticket extension");
+ error = 1;
+ goto done;
+ }
+
+ /* enable compression. */
+ rv = SSL_OptionSet(s, SSL_ENABLE_DEFLATE, enableCompression);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling compression");
+ error = 1;
+ goto done;
+ }
+
+ /* enable false start. */
+ rv = SSL_OptionSet(s, SSL_ENABLE_FALSE_START, enableFalseStart);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling false start");
+ error = 1;
+ goto done;
+ }
+
+ if (forceFallbackSCSV) {
+ rv = SSL_OptionSet(s, SSL_ENABLE_FALLBACK_SCSV, PR_TRUE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error forcing fallback scsv");
+ error = 1;
+ goto done;
+ }
+ }
+
+ /* enable cert status (OCSP stapling). */
+ rv = SSL_OptionSet(s, SSL_ENABLE_OCSP_STAPLING, enableCertStatus);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling cert status (OCSP stapling)");
+ error = 1;
+ goto done;
+ }
+
+ /* enable extended master secret mode */
+ if (enableExtendedMasterSecret) {
+ rv = SSL_OptionSet(s, SSL_ENABLE_EXTENDED_MASTER_SECRET, PR_TRUE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling extended master secret");
+ error = 1;
+ goto done;
+ }
+ }
+
+ /* enable 0-RTT (TLS 1.3 only) */
+ if (enableZeroRtt) {
+ rv = SSL_OptionSet(s, SSL_ENABLE_0RTT_DATA, PR_TRUE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling 0-RTT");
+ error = 1;
+ goto done;
+ }
+ }
+
+ /* require the use of fixed finite-field DH groups */
+ if (requireDHNamedGroups) {
+ rv = SSL_OptionSet(s, SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error in requiring the use of fixed finite-field DH groups");
+ error = 1;
+ goto done;
+ }
+ }
+
+ /* enable Signed Certificate Timestamps. */
+ rv = SSL_OptionSet(s, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
+ enableSignedCertTimestamps);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling signed cert timestamps");
+ error = 1;
+ goto done;
+ }
+
+ if (enabledGroups) {
+ rv = SSL_NamedGroupConfig(s, enabledGroups, enabledGroupsCount);
+ if (rv < 0) {
+ SECU_PrintError(progName, "SSL_NamedGroupConfig failed");
+ error = 1;
+ goto done;
+ }
+ }
+
+ serverCertAuth.dbHandle = CERT_GetDefaultCertDB();
+
+ SSL_AuthCertificateHook(s, ownAuthCertificate, &serverCertAuth);
+ if (override) {
+ SSL_BadCertHook(s, ownBadCertHandler, NULL);
+ }
+ SSL_GetClientAuthDataHook(s, own_GetClientAuthData, (void *)nickname);
+ SSL_HandshakeCallback(s, handshakeCallback, hs2SniHostName);
+ if (hs1SniHostName) {
+ SSL_SetURL(s, hs1SniHostName);
+ } else {
+ SSL_SetURL(s, host);
+ }
+
+ /* Try to connect to the server */
+ status = PR_Connect(s, &addr, PR_INTERVAL_NO_TIMEOUT);
+ if (status != PR_SUCCESS) {
+ if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
+ if (verbose)
+ SECU_PrintError(progName, "connect");
+ milliPause(50 * multiplier);
+ pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ pollset[SSOCK_FD].out_flags = 0;
+ pollset[SSOCK_FD].fd = s;
+ while (1) {
+ FPRINTF(stderr,
+ "%s: about to call PR_Poll for connect completion!\n",
+ progName);
+ filesReady = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (filesReady < 0) {
+ SECU_PrintError(progName, "unable to connect (poll)");
+ error = 1;
+ goto done;
+ }
+ FPRINTF(stderr,
+ "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
+ progName, pollset[SSOCK_FD].out_flags);
+ if (filesReady == 0) { /* shouldn't happen! */
+ FPRINTF(stderr, "%s: PR_Poll returned zero!\n", progName);
+ error = 1;
+ goto done;
+ }
+ status = PR_GetConnectStatus(pollset);
+ if (status == PR_SUCCESS) {
+ break;
+ }
+ if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
+ SECU_PrintError(progName, "unable to connect (poll)");
+ error = 1;
+ goto done;
+ }
+ SECU_PrintError(progName, "poll");
+ milliPause(50 * multiplier);
+ }
+ } else {
+ SECU_PrintError(progName, "unable to connect");
+ error = 1;
+ goto done;
+ }
+ }
+
+ pollset[SSOCK_FD].fd = s;
+ pollset[SSOCK_FD].in_flags = PR_POLL_EXCEPT |
+ (clientSpeaksFirst ? 0 : PR_POLL_READ);
+ pollset[STDIN_FD].fd = PR_GetSpecialFD(PR_StandardInput);
+ if (!requestStringInt) {
+ pollset[STDIN_FD].in_flags = PR_POLL_READ;
+ npds = 2;
+ } else {
+ npds = 1;
+ }
+ std_out = PR_GetSpecialFD(PR_StandardOutput);
+
+#if defined(WIN32) || defined(OS2)
+ /* PR_Poll cannot be used with stdin on Windows or OS/2. (sigh).
+ ** But use of PR_Poll and non-blocking sockets is a major feature
+ ** of this program. So, we simulate a pollable stdin with a
+ ** TCP socket pair and a thread that reads stdin and writes to
+ ** that socket pair.
+ */
+ {
+ PRFileDesc *fds[2];
+ PRThread *thread;
+
+ int nspr_rv = PR_NewTCPSocketPair(fds);
+ if (nspr_rv != PR_SUCCESS) {
+ SECU_PrintError(progName, "PR_NewTCPSocketPair failed");
+ error = 1;
+ goto done;
+ }
+ pollset[STDIN_FD].fd = fds[1];
+
+ thread = PR_CreateThread(PR_USER_THREAD, thread_main, fds[0],
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (!thread) {
+ SECU_PrintError(progName, "PR_CreateThread failed");
+ error = 1;
+ goto done;
+ }
+ }
+#endif
+
+ if (serverCertAuth.testFreshStatusFromSideChannel) {
+ SSL_ForceHandshake(s);
+ error = serverCertAuth.sideChannelRevocationTestResultCode;
+ goto done;
+ }
+
+ /*
+ ** Select on stdin and on the socket. Write data from stdin to
+ ** socket, read data from socket and write to stdout.
+ */
+ FPRINTF(stderr, "%s: ready...\n", progName);
+ while ((pollset[SSOCK_FD].in_flags | pollset[STDIN_FD].in_flags) ||
+ requestStringInt) {
+ char buf[4000]; /* buffer for stdin */
+ int nb; /* num bytes read from stdin. */
+
+ rv = restartHandshakeAfterServerCertIfNeeded(s, &serverCertAuth,
+ override);
+ if (rv != SECSuccess) {
+ error = EXIT_CODE_HANDSHAKE_FAILED;
+ SECU_PrintError(progName, "authentication of server cert failed");
+ goto done;
+ }
+
+ pollset[SSOCK_FD].out_flags = 0;
+ pollset[STDIN_FD].out_flags = 0;
+
+ FPRINTF(stderr, "%s: about to call PR_Poll !\n", progName);
+ filesReady = PR_Poll(pollset, npds, PR_INTERVAL_NO_TIMEOUT);
+ if (filesReady < 0) {
+ SECU_PrintError(progName, "select failed");
+ error = 1;
+ goto done;
+ }
+ if (filesReady == 0) { /* shouldn't happen! */
+ FPRINTF(stderr, "%s: PR_Poll returned zero!\n", progName);
+ error = 1;
+ goto done;
+ }
+ FPRINTF(stderr, "%s: PR_Poll returned!\n", progName);
+ if (pollset[STDIN_FD].in_flags) {
+ FPRINTF(stderr,
+ "%s: PR_Poll returned 0x%02x for stdin out_flags.\n",
+ progName, pollset[STDIN_FD].out_flags);
+ }
+ if (pollset[SSOCK_FD].in_flags) {
+ FPRINTF(stderr,
+ "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
+ progName, pollset[SSOCK_FD].out_flags);
+ }
+ if (requestStringInt) {
+ error = writeBytesToServer(s, pollset,
+ requestStringInt, requestStringLen);
+ if (error) {
+ goto done;
+ }
+ requestStringInt = NULL;
+ pollset[SSOCK_FD].in_flags = PR_POLL_READ;
+ }
+ if (pollset[STDIN_FD].out_flags & PR_POLL_READ) {
+ /* Read from stdin and write to socket */
+ nb = PR_Read(pollset[STDIN_FD].fd, buf, sizeof(buf));
+ FPRINTF(stderr, "%s: stdin read %d bytes\n", progName, nb);
+ if (nb < 0) {
+ if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+ SECU_PrintError(progName, "read from stdin failed");
+ error = 1;
+ break;
+ }
+ } else if (nb == 0) {
+ /* EOF on stdin, stop polling stdin for read. */
+ pollset[STDIN_FD].in_flags = 0;
+ } else {
+ error = writeBytesToServer(s, pollset, buf, nb);
+ if (error) {
+ goto done;
+ }
+ pollset[SSOCK_FD].in_flags = PR_POLL_READ;
+ }
+ }
+
+ if (pollset[SSOCK_FD].in_flags) {
+ FPRINTF(stderr,
+ "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
+ progName, pollset[SSOCK_FD].out_flags);
+ }
+ if ((pollset[SSOCK_FD].out_flags & PR_POLL_READ) ||
+ (pollset[SSOCK_FD].out_flags & PR_POLL_ERR)
+#ifdef PR_POLL_HUP
+ || (pollset[SSOCK_FD].out_flags & PR_POLL_HUP)
+#endif
+ ) {
+ /* Read from socket and write to stdout */
+ nb = PR_Recv(pollset[SSOCK_FD].fd, buf, sizeof buf, 0, maxInterval);
+ FPRINTF(stderr, "%s: Read from server %d bytes\n", progName, nb);
+ if (nb < 0) {
+ if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+ SECU_PrintError(progName, "read from socket failed");
+ error = 1;
+ goto done;
+ }
+ } else if (nb == 0) {
+ /* EOF from socket... stop polling socket for read */
+ pollset[SSOCK_FD].in_flags = 0;
+ } else {
+ if (skipProtoHeader != PR_TRUE || wrStarted == PR_TRUE) {
+ PR_Write(std_out, buf, nb);
+ } else {
+ separateReqHeader(std_out, buf, nb, &wrStarted,
+ &headerSeparatorPtrnId);
+ }
+ if (verbose)
+ fputs("\n\n", stderr);
+ }
+ }
+ milliPause(50 * multiplier);
+ }
+
+done:
+ if (s) {
+ PR_Close(s);
+ }
+
+ return error;
+}
+
+PRInt32
+ReadFile(const char *filename, char **data)
+{
+ char *ret = NULL;
+ char buf[8192];
+ unsigned int len = 0;
+ PRStatus rv;
+
+ PRFileDesc *fd = PR_Open(filename, PR_RDONLY, 0);
+ if (!fd)
+ return -1;
+
+ for (;;) {
+ rv = PR_Read(fd, buf, sizeof(buf));
+ if (rv < 0) {
+ PR_Free(ret);
+ return rv;
+ }
+
+ if (!rv)
+ break;
+
+ ret = PR_Realloc(ret, len + rv);
+ if (!ret) {
+ return -1;
+ }
+ PORT_Memcpy(ret + len, buf, rv);
+ len += rv;
+ }
+
+ *data = ret;
+ return len;
+}
+
+int
+main(int argc, char **argv)
+{
+ PLOptState *optstate;
+ PLOptStatus optstatus;
+ PRStatus status;
+ PRStatus prStatus;
+ int error = 0;
+ char *tmp;
+ SECStatus rv;
+ char *certDir = NULL;
+ PRBool openDB = PR_TRUE;
+ PRBool loadDefaultRootCAs = PR_FALSE;
+ char *rootModule = NULL;
+ int numConnections = 1;
+ PRFileDesc *s = NULL;
+
+ serverCertAuth.shouldPause = PR_TRUE;
+ serverCertAuth.isPaused = PR_FALSE;
+ serverCertAuth.dbHandle = NULL;
+ serverCertAuth.testFreshStatusFromSideChannel = PR_FALSE;
+ serverCertAuth.sideChannelRevocationTestResultCode = EXIT_CODE_HANDSHAKE_FAILED;
+ serverCertAuth.requireDataForIntermediates = PR_FALSE;
+ serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
+ serverCertAuth.allowCRLSideChannelData = PR_TRUE;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName + 1 : argv[0];
+
+ tmp = PR_GetEnvSecure("NSS_DEBUG_TIMEOUT");
+ if (tmp && tmp[0]) {
+ int sec = PORT_Atoi(tmp);
+ if (sec > 0) {
+ maxInterval = PR_SecondsToInterval(sec);
+ }
+ }
+
+ SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions);
+
+ /* XXX: 'B' was used in the past but removed in 3.28,
+ * please leave some time before resuing it. */
+ optstate = PL_CreateOptState(argc, argv,
+ "46A:CDFGHI:KL:M:OR:STUV:WYZa:bc:d:fgh:m:n:op:qr:st:uvw:z");
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ default:
+ Usage(progName);
+ break;
+
+ case '4':
+ allowIPv6 = PR_FALSE;
+ if (!allowIPv4)
+ Usage(progName);
+ break;
+ case '6':
+ allowIPv4 = PR_FALSE;
+ if (!allowIPv6)
+ Usage(progName);
+ break;
+
+ case 'A':
+ requestStringLen = ReadFile(optstate->value, &requestString);
+ if (requestStringLen < 0) {
+ fprintf(stderr, "Couldn't read file %s\n", optstate->value);
+ exit(1);
+ }
+ break;
+
+ case 'C':
+ ++dumpServerChain;
+ break;
+
+ case 'D':
+ openDB = PR_FALSE;
+ break;
+
+ case 'F':
+ if (serverCertAuth.testFreshStatusFromSideChannel) {
+ /* parameter given twice or more */
+ serverCertAuth.requireDataForIntermediates = PR_TRUE;
+ }
+ serverCertAuth.testFreshStatusFromSideChannel = PR_TRUE;
+ break;
+
+ case 'G':
+ enableExtendedMasterSecret = PR_TRUE;
+ break;
+
+ case 'H':
+ requireDHNamedGroups = PR_TRUE;
+ break;
+
+ case 'O':
+ serverCertAuth.shouldPause = PR_FALSE;
+ break;
+
+ case 'K':
+ forceFallbackSCSV = PR_TRUE;
+ break;
+
+ case 'L':
+ numConnections = atoi(optstate->value);
+ break;
+
+ case 'M':
+ switch (atoi(optstate->value)) {
+ case 1:
+ serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
+ serverCertAuth.allowCRLSideChannelData = PR_FALSE;
+ break;
+ case 2:
+ serverCertAuth.allowOCSPSideChannelData = PR_FALSE;
+ serverCertAuth.allowCRLSideChannelData = PR_TRUE;
+ break;
+ case 0:
+ default:
+ serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
+ serverCertAuth.allowCRLSideChannelData = PR_TRUE;
+ break;
+ };
+ break;
+
+ case 'R':
+ rootModule = PORT_Strdup(optstate->value);
+ break;
+
+ case 'S':
+ skipProtoHeader = PR_TRUE;
+ break;
+
+ case 'T':
+ enableCertStatus = 1;
+ break;
+
+ case 'U':
+ enableSignedCertTimestamps = 1;
+ break;
+
+ case 'V':
+ if (SECU_ParseSSLVersionRangeString(optstate->value,
+ enabledVersions, &enabledVersions) !=
+ SECSuccess) {
+ Usage(progName);
+ }
+ break;
+
+ case 'Y':
+ PrintCipherUsage(progName);
+ exit(0);
+ break;
+
+ case 'Z':
+ enableZeroRtt = PR_TRUE;
+ break;
+
+ case 'a':
+ if (!hs1SniHostName) {
+ hs1SniHostName = PORT_Strdup(optstate->value);
+ } else if (!hs2SniHostName) {
+ hs2SniHostName = PORT_Strdup(optstate->value);
+ } else {
+ Usage(progName);
+ }
+ break;
+
+ case 'b':
+ loadDefaultRootCAs = PR_TRUE;
+ break;
+
+ case 'c':
+ cipherString = PORT_Strdup(optstate->value);
+ break;
+
+ case 'g':
+ enableFalseStart = 1;
+ break;
+
+ case 'd':
+ certDir = PORT_Strdup(optstate->value);
+ break;
+
+ case 'f':
+ clientSpeaksFirst = PR_TRUE;
+ break;
+
+ case 'h':
+ host = PORT_Strdup(optstate->value);
+ break;
+
+ case 'm':
+ multiplier = atoi(optstate->value);
+ if (multiplier < 0)
+ multiplier = 0;
+ break;
+
+ case 'n':
+ nickname = PORT_Strdup(optstate->value);
+ break;
+
+ case 'o':
+ override = 1;
+ break;
+
+ case 'p':
+ portno = (PRUint16)atoi(optstate->value);
+ break;
+
+ case 'q':
+ pingServerFirst = PR_TRUE;
+ break;
+
+ case 's':
+ disableLocking = 1;
+ break;
+
+ case 't':
+ pingTimeoutSeconds = atoi(optstate->value);
+ break;
+
+ case 'u':
+ enableSessionTickets = PR_TRUE;
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ case 'r':
+ renegotiationsToDo = atoi(optstate->value);
+ break;
+
+ case 'w':
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
+
+ case 'W':
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
+
+ case 'z':
+ enableCompression = 1;
+ break;
+
+ case 'I':
+ rv = parseGroupList(optstate->value, &enabledGroups, &enabledGroupsCount);
+ if (rv != SECSuccess) {
+ PL_DestroyOptState(optstate);
+ fprintf(stderr, "Bad group specified.\n");
+ Usage(progName);
+ }
+ break;
+ }
+ }
+
+ PL_DestroyOptState(optstate);
+
+ if (optstatus == PL_OPT_BAD) {
+ Usage(progName);
+ }
+
+ if (!host || !portno) {
+ fprintf(stderr, "%s: parameters -h and -p are mandatory\n", progName);
+ Usage(progName);
+ }
+
+ if (serverCertAuth.testFreshStatusFromSideChannel &&
+ serverCertAuth.shouldPause) {
+ fprintf(stderr, "%s: -F requires the use of -O\n", progName);
+ exit(1);
+ }
+
+ if (certDir && !openDB) {
+ fprintf(stderr, "%s: Cannot combine parameters -D and -d\n", progName);
+ exit(1);
+ }
+
+ if (rootModule && loadDefaultRootCAs) {
+ fprintf(stderr, "%s: Cannot combine parameters -b and -R\n", progName);
+ exit(1);
+ }
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ status = PR_StringToNetAddr(host, &addr);
+ if (status == PR_SUCCESS) {
+ addr.inet.port = PR_htons(portno);
+ } else {
+ /* Lookup host */
+ PRAddrInfo *addrInfo;
+ void *enumPtr = NULL;
+
+ addrInfo = PR_GetAddrInfoByName(host, PR_AF_UNSPEC,
+ PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME);
+ if (!addrInfo) {
+ SECU_PrintError(progName, "error looking up host");
+ error = 1;
+ goto done;
+ }
+ for (;;) {
+ enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, portno, &addr);
+ if (enumPtr == NULL)
+ break;
+ if (addr.raw.family == PR_AF_INET && allowIPv4)
+ break;
+ if (addr.raw.family == PR_AF_INET6 && allowIPv6)
+ break;
+ }
+ PR_FreeAddrInfo(addrInfo);
+ if (enumPtr == NULL) {
+ SECU_PrintError(progName, "error looking up host address");
+ error = 1;
+ goto done;
+ }
+ }
+
+ printHostNameAndAddr(host, &addr);
+
+ if (!certDir) {
+ certDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
+ certDir = SECU_ConfigDirectory(certDir);
+ } else {
+ char *certDirTmp = certDir;
+ certDir = SECU_ConfigDirectory(certDirTmp);
+ PORT_Free(certDirTmp);
+ }
+
+ if (pingServerFirst) {
+ int iter = 0;
+ PRErrorCode err;
+
+ int max_attempts = MAX_WAIT_FOR_SERVER;
+ if (pingTimeoutSeconds >= 0) {
+ /* If caller requested a timeout, let's try just twice. */
+ max_attempts = 2;
+ }
+ do {
+ PRIntervalTime timeoutInterval = PR_INTERVAL_NO_TIMEOUT;
+ s = PR_OpenTCPSocket(addr.raw.family);
+ if (s == NULL) {
+ SECU_PrintError(progName, "Failed to create a TCP socket");
+ error = 1;
+ goto done;
+ }
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ prStatus = PR_SetSocketOption(s, &opt);
+ if (prStatus != PR_SUCCESS) {
+ SECU_PrintError(progName,
+ "Failed to set blocking socket option");
+ error = 1;
+ goto done;
+ }
+ if (pingTimeoutSeconds >= 0) {
+ timeoutInterval = PR_SecondsToInterval(pingTimeoutSeconds);
+ }
+ prStatus = PR_Connect(s, &addr, timeoutInterval);
+ if (prStatus == PR_SUCCESS) {
+ PR_Shutdown(s, PR_SHUTDOWN_BOTH);
+ goto done;
+ }
+ err = PR_GetError();
+ if ((err != PR_CONNECT_REFUSED_ERROR) &&
+ (err != PR_CONNECT_RESET_ERROR)) {
+ SECU_PrintError(progName, "TCP Connection failed");
+ error = 1;
+ goto done;
+ }
+ PR_Close(s);
+ s = NULL;
+ PR_Sleep(PR_MillisecondsToInterval(WAIT_INTERVAL));
+ } while (++iter < max_attempts);
+ SECU_PrintError(progName,
+ "Client timed out while waiting for connection to server");
+ error = 1;
+ goto done;
+ }
+
+ /* open the cert DB, the key DB, and the secmod DB. */
+ if (openDB) {
+ rv = NSS_Init(certDir);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to open cert database");
+ error = 1;
+ goto done;
+ }
+ } else {
+ rv = NSS_NoDB_Init(NULL);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "failed to initialize NSS");
+ error = 1;
+ goto done;
+ }
+ }
+
+ if (loadDefaultRootCAs) {
+ SECMOD_AddNewModule("Builtins",
+ DLL_PREFIX "nssckbi." DLL_SUFFIX, 0, 0);
+ } else if (rootModule) {
+ SECMOD_AddNewModule("Builtins", rootModule, 0, 0);
+ }
+
+ /* all SSL3 cipher suites are enabled by default. */
+ if (cipherString) {
+ /* disable all the ciphers, then enable the ones we want. */
+ disableAllSSLCiphers();
+ }
+
+ while (numConnections--) {
+ error = run_client();
+ if (error) {
+ goto done;
+ }
+ }
+
+done:
+ if (s) {
+ PR_Close(s);
+ }
+
+ if (hs1SniHostName) {
+ PORT_Free(hs1SniHostName);
+ }
+ if (hs2SniHostName) {
+ PORT_Free(hs2SniHostName);
+ }
+ if (nickname) {
+ PORT_Free(nickname);
+ }
+ if (pwdata.data) {
+ PORT_Free(pwdata.data);
+ }
+ PORT_Free(host);
+ PORT_Free(requestString);
+
+ if (enabledGroups) {
+ PORT_Free(enabledGroups);
+ }
+ if (NSS_IsInitialized()) {
+ SSL_ClearSessionCache();
+ if (NSS_Shutdown() != SECSuccess) {
+ error = 1;
+ }
+ }
+
+ FPRINTF(stderr, "tstclnt: exiting with return code %d\n", error);
+ PR_Cleanup();
+ return error;
+}
diff --git a/security/nss/cmd/tstclnt/tstclnt.gyp b/security/nss/cmd/tstclnt/tstclnt.gyp
new file mode 100644
index 000000000..81cbff3ed
--- /dev/null
+++ b/security/nss/cmd/tstclnt/tstclnt.gyp
@@ -0,0 +1,31 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'tstclnt',
+ 'type': 'executable',
+ 'sources': [
+ 'tstclnt.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'DLL_PREFIX=\"<(dll_prefix)\"',
+ 'DLL_SUFFIX=\"<(dll_suffix)\"'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/vfychain/Makefile b/security/nss/cmd/vfychain/Makefile
new file mode 100644
index 000000000..a27a3ce97
--- /dev/null
+++ b/security/nss/cmd/vfychain/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#include ../platlibs.mk
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/vfychain/manifest.mn b/security/nss/cmd/vfychain/manifest.mn
new file mode 100644
index 000000000..5b2ae25e7
--- /dev/null
+++ b/security/nss/cmd/vfychain/manifest.mn
@@ -0,0 +1,23 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd
+
+# DIRS =
+
+CSRCS = vfychain.c
+DEFINES += -DDLL_PREFIX=\"$(DLL_PREFIX)\" -DDLL_SUFFIX=\"$(DLL_SUFFIX)\"
+
+PROGRAM = vfychain
+
diff --git a/security/nss/cmd/vfychain/vfychain.c b/security/nss/cmd/vfychain/vfychain.c
new file mode 100644
index 000000000..d42274c12
--- /dev/null
+++ b/security/nss/cmd/vfychain/vfychain.c
@@ -0,0 +1,820 @@
+/* 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/. */
+
+/****************************************************************************
+ * Read in a cert chain from one or more files, and verify the chain for
+ * some usage.
+ * *
+ * This code was modified from other code also kept in the NSS directory.
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "prerror.h"
+
+#include "pk11func.h"
+#include "seccomon.h"
+#include "secutil.h"
+#include "secmod.h"
+#include "secitem.h"
+#include "cert.h"
+#include "ocsp.h"
+
+/* #include <stdlib.h> */
+/* #include <errno.h> */
+/* #include <fcntl.h> */
+/* #include <stdarg.h> */
+
+#include "nspr.h"
+#include "plgetopt.h"
+#include "prio.h"
+#include "nss.h"
+
+/* #include "vfyutil.h" */
+
+#define RD_BUF_SIZE (60 * 1024)
+
+int verbose;
+
+secuPWData pwdata = { PW_NONE, 0 };
+
+static void
+Usage(const char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [options] [revocation options] certfile "
+ "[[options] certfile] ...\n"
+ "\tWhere options are:\n"
+ "\t-a\t\t Following certfile is base64 encoded\n"
+ "\t-b YYMMDDHHMMZ\t Validate date (default: now)\n"
+ "\t-d directory\t Database directory\n"
+ "\t-i number of consecutive verifications\n"
+ "\t-f \t\t Enable cert fetching from AIA URL\n"
+ "\t-o oid\t\t Set policy OID for cert validation(Format OID.1.2.3)\n"
+ "\t-p \t\t Use PKIX Library to validate certificate by calling:\n"
+ "\t\t\t * CERT_VerifyCertificate if specified once,\n"
+ "\t\t\t * CERT_PKIXVerifyCert if specified twice and more.\n"
+ "\t-r\t\t Following certfile is raw binary DER (default)\n"
+ "\t-t\t\t Following cert is explicitly trusted (overrides db trust).\n"
+ "\t-u usage \t 0=SSL client, 1=SSL server, 2=SSL StepUp, 3=SSL CA,\n"
+ "\t\t\t 4=Email signer, 5=Email recipient, 6=Object signer,\n"
+ "\t\t\t 9=ProtectedObjectSigner, 10=OCSP responder, 11=Any CA\n"
+ "\t-T\t\t Trust both explicit trust anchors (-t) and the database.\n"
+ "\t\t\t (Default is to only trust certificates marked -t, if there are any,\n"
+ "\t\t\t or to trust the database if there are certificates marked -t.)\n"
+ "\t-v\t\t Verbose mode. Prints root cert subject(double the\n"
+ "\t\t\t argument for whole root cert info)\n"
+ "\t-w password\t Database password.\n"
+ "\t-W pwfile\t Password file.\n\n"
+ "\tRevocation options for PKIX API(invoked with -pp options) is a\n"
+ "\tcollection of the following flags:\n"
+ "\t\t[-g type [-h flags] [-m type [-s flags]] ...] ...\n"
+ "\tWhere:\n"
+ "\t-g test type\t Sets status checking test type. Possible values\n"
+ "\t\t\tare \"leaf\" or \"chain\"\n"
+ "\t-h test flags\t Sets revocation flags for the test type it\n"
+ "\t\t\tfollows. Possible flags: \"testLocalInfoFirst\" and\n"
+ "\t\t\t\"requireFreshInfo\".\n"
+ "\t-m method type\t Sets method type for the test type it follows.\n"
+ "\t\t\tPossible types are \"crl\" and \"ocsp\".\n"
+ "\t-s method flags\t Sets revocation flags for the method it follows.\n"
+ "\t\t\tPossible types are \"doNotUse\", \"forbidFetching\",\n"
+ "\t\t\t\"ignoreDefaultSrc\", \"requireInfo\" and \"failIfNoInfo\".\n",
+ progName);
+ exit(1);
+}
+
+/**************************************************************************
+**
+** Error and information routines.
+**
+**************************************************************************/
+
+void
+errWarn(char *function)
+{
+ fprintf(stderr, "Error in function %s: %s\n",
+ function, SECU_Strerror(PR_GetError()));
+}
+
+void
+exitErr(char *function)
+{
+ errWarn(function);
+ /* Exit gracefully. */
+ /* ignoring return value of NSS_Shutdown as code exits with 1 anyway*/
+ (void)NSS_Shutdown();
+ PR_Cleanup();
+ exit(1);
+}
+
+typedef struct certMemStr {
+ struct certMemStr *next;
+ CERTCertificate *cert;
+} certMem;
+
+certMem *theCerts;
+CERTCertList *trustedCertList;
+
+void
+rememberCert(CERTCertificate *cert, PRBool trusted)
+{
+ if (trusted) {
+ if (!trustedCertList) {
+ trustedCertList = CERT_NewCertList();
+ }
+ CERT_AddCertToListTail(trustedCertList, cert);
+ } else {
+ certMem *newCertMem = PORT_ZNew(certMem);
+ if (newCertMem) {
+ newCertMem->next = theCerts;
+ newCertMem->cert = cert;
+ theCerts = newCertMem;
+ }
+ }
+}
+
+void
+forgetCerts(void)
+{
+ certMem *oldCertMem;
+ while (theCerts) {
+ oldCertMem = theCerts;
+ theCerts = theCerts->next;
+ CERT_DestroyCertificate(oldCertMem->cert);
+ PORT_Free(oldCertMem);
+ }
+ if (trustedCertList) {
+ CERT_DestroyCertList(trustedCertList);
+ }
+}
+
+CERTCertificate *
+getCert(const char *name, PRBool isAscii, const char *progName)
+{
+ CERTCertificate *cert;
+ CERTCertDBHandle *defaultDB;
+ PRFileDesc *fd;
+ SECStatus rv;
+ SECItem item = { 0, NULL, 0 };
+
+ defaultDB = CERT_GetDefaultCertDB();
+
+ /* First, let's try to find the cert in existing DB. */
+ cert = CERT_FindCertByNicknameOrEmailAddr(defaultDB, name);
+ if (cert) {
+ return cert;
+ }
+
+ /* Don't have a cert with name "name" in the DB. Try to
+ * open a file with such name and get the cert from there.*/
+ fd = PR_Open(name, PR_RDONLY, 0777);
+ if (!fd) {
+ PRErrorCode err = PR_GetError();
+ fprintf(stderr, "open of %s failed, %d = %s\n",
+ name, err, SECU_Strerror(err));
+ return cert;
+ }
+
+ rv = SECU_ReadDERFromFile(&item, fd, isAscii, PR_FALSE);
+ PR_Close(fd);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: SECU_ReadDERFromFile failed\n", progName);
+ return cert;
+ }
+
+ if (!item.len) { /* file was empty */
+ fprintf(stderr, "cert file %s was empty.\n", name);
+ return cert;
+ }
+
+ cert = CERT_NewTempCertificate(defaultDB, &item,
+ NULL /* nickname */,
+ PR_FALSE /* isPerm */,
+ PR_TRUE /* copyDER */);
+ if (!cert) {
+ PRErrorCode err = PR_GetError();
+ fprintf(stderr, "couldn't import %s, %d = %s\n",
+ name, err, SECU_Strerror(err));
+ }
+ PORT_Free(item.data);
+ return cert;
+}
+
+#define REVCONFIG_TEST_UNDEFINED 0
+#define REVCONFIG_TEST_LEAF 1
+#define REVCONFIG_TEST_CHAIN 2
+#define REVCONFIG_METHOD_CRL 1
+#define REVCONFIG_METHOD_OCSP 2
+
+#define REVCONFIG_TEST_LEAF_STR "leaf"
+#define REVCONFIG_TEST_CHAIN_STR "chain"
+#define REVCONFIG_METHOD_CRL_STR "crl"
+#define REVCONFIG_METHOD_OCSP_STR "ocsp"
+
+#define REVCONFIG_TEST_TESTLOCALINFOFIRST_STR "testLocalInfoFirst"
+#define REVCONFIG_TEST_REQUIREFRESHINFO_STR "requireFreshInfo"
+#define REVCONFIG_METHOD_DONOTUSEMETHOD_STR "doNotUse"
+#define REVCONFIG_METHOD_FORBIDNETWORKFETCHIN_STR "forbidFetching"
+#define REVCONFIG_METHOD_IGNOREDEFAULTSRC_STR "ignoreDefaultSrc"
+#define REVCONFIG_METHOD_REQUIREINFO_STR "requireInfo"
+#define REVCONFIG_METHOD_FAILIFNOINFO_STR "failIfNoInfo"
+
+#define REV_METHOD_INDEX_MAX 4
+
+typedef struct RevMethodsStruct {
+ unsigned int testType;
+ char *testTypeStr;
+ unsigned int testFlags;
+ char *testFlagsStr;
+ unsigned int methodType;
+ char *methodTypeStr;
+ unsigned int methodFlags;
+ char *methodFlagsStr;
+} RevMethods;
+
+RevMethods revMethodsData[REV_METHOD_INDEX_MAX];
+
+SECStatus
+parseRevMethodsAndFlags()
+{
+ int i;
+ unsigned int testType = 0;
+
+ for (i = 0; i < REV_METHOD_INDEX_MAX; i++) {
+ /* testType */
+ if (revMethodsData[i].testTypeStr) {
+ char *typeStr = revMethodsData[i].testTypeStr;
+
+ testType = 0;
+ if (!PORT_Strcmp(typeStr, REVCONFIG_TEST_LEAF_STR)) {
+ testType = REVCONFIG_TEST_LEAF;
+ } else if (!PORT_Strcmp(typeStr, REVCONFIG_TEST_CHAIN_STR)) {
+ testType = REVCONFIG_TEST_CHAIN;
+ }
+ }
+ if (!testType) {
+ return SECFailure;
+ }
+ revMethodsData[i].testType = testType;
+ /* testFlags */
+ if (revMethodsData[i].testFlagsStr) {
+ char *flagStr = revMethodsData[i].testFlagsStr;
+ unsigned int testFlags = 0;
+
+ if (PORT_Strstr(flagStr, REVCONFIG_TEST_TESTLOCALINFOFIRST_STR)) {
+ testFlags |= CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST;
+ }
+ if (PORT_Strstr(flagStr, REVCONFIG_TEST_REQUIREFRESHINFO_STR)) {
+ testFlags |= CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
+ }
+ revMethodsData[i].testFlags = testFlags;
+ }
+ /* method type */
+ if (revMethodsData[i].methodTypeStr) {
+ char *methodStr = revMethodsData[i].methodTypeStr;
+ unsigned int methodType = 0;
+
+ if (!PORT_Strcmp(methodStr, REVCONFIG_METHOD_CRL_STR)) {
+ methodType = REVCONFIG_METHOD_CRL;
+ } else if (!PORT_Strcmp(methodStr, REVCONFIG_METHOD_OCSP_STR)) {
+ methodType = REVCONFIG_METHOD_OCSP;
+ }
+ if (!methodType) {
+ return SECFailure;
+ }
+ revMethodsData[i].methodType = methodType;
+ }
+ if (!revMethodsData[i].methodType) {
+ revMethodsData[i].testType = REVCONFIG_TEST_UNDEFINED;
+ continue;
+ }
+ /* method flags */
+ if (revMethodsData[i].methodFlagsStr) {
+ char *flagStr = revMethodsData[i].methodFlagsStr;
+ unsigned int methodFlags = 0;
+
+ if (!PORT_Strstr(flagStr, REVCONFIG_METHOD_DONOTUSEMETHOD_STR)) {
+ methodFlags |= CERT_REV_M_TEST_USING_THIS_METHOD;
+ }
+ if (PORT_Strstr(flagStr,
+ REVCONFIG_METHOD_FORBIDNETWORKFETCHIN_STR)) {
+ methodFlags |= CERT_REV_M_FORBID_NETWORK_FETCHING;
+ }
+ if (PORT_Strstr(flagStr, REVCONFIG_METHOD_IGNOREDEFAULTSRC_STR)) {
+ methodFlags |= CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
+ }
+ if (PORT_Strstr(flagStr, REVCONFIG_METHOD_REQUIREINFO_STR)) {
+ methodFlags |= CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE;
+ }
+ if (PORT_Strstr(flagStr, REVCONFIG_METHOD_FAILIFNOINFO_STR)) {
+ methodFlags |= CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO;
+ }
+ revMethodsData[i].methodFlags = methodFlags;
+ } else {
+ revMethodsData[i].methodFlags |= CERT_REV_M_TEST_USING_THIS_METHOD;
+ }
+ }
+ return SECSuccess;
+}
+
+SECStatus
+configureRevocationParams(CERTRevocationFlags *flags)
+{
+ int i;
+ unsigned int testType = REVCONFIG_TEST_UNDEFINED;
+ static CERTRevocationTests *revTests = NULL;
+ PRUint64 *revFlags = NULL;
+
+ for (i = 0; i < REV_METHOD_INDEX_MAX; i++) {
+ if (revMethodsData[i].testType == REVCONFIG_TEST_UNDEFINED) {
+ continue;
+ }
+ if (revMethodsData[i].testType != testType) {
+ testType = revMethodsData[i].testType;
+ if (testType == REVCONFIG_TEST_CHAIN) {
+ revTests = &flags->chainTests;
+ } else {
+ revTests = &flags->leafTests;
+ }
+ revTests->number_of_preferred_methods = 0;
+ revTests->preferred_methods = 0;
+ revFlags = revTests->cert_rev_flags_per_method;
+ }
+ /* Set the number of the methods independently to the max number of
+ * methods. If method flags are not set it will be ignored due to
+ * default DO_NOT_USE flag. */
+ revTests->number_of_defined_methods = cert_revocation_method_count;
+ revTests->cert_rev_method_independent_flags |=
+ revMethodsData[i].testFlags;
+ if (revMethodsData[i].methodType == REVCONFIG_METHOD_CRL) {
+ revFlags[cert_revocation_method_crl] =
+ revMethodsData[i].methodFlags;
+ } else if (revMethodsData[i].methodType == REVCONFIG_METHOD_OCSP) {
+ revFlags[cert_revocation_method_ocsp] =
+ revMethodsData[i].methodFlags;
+ }
+ }
+ return SECSuccess;
+}
+
+void
+freeRevocationMethodData()
+{
+ int i = 0;
+ for (; i < REV_METHOD_INDEX_MAX; i++) {
+ if (revMethodsData[i].testTypeStr) {
+ PORT_Free(revMethodsData[i].testTypeStr);
+ }
+ if (revMethodsData[i].testFlagsStr) {
+ PORT_Free(revMethodsData[i].testFlagsStr);
+ }
+ if (revMethodsData[i].methodTypeStr) {
+ PORT_Free(revMethodsData[i].methodTypeStr);
+ }
+ if (revMethodsData[i].methodFlagsStr) {
+ PORT_Free(revMethodsData[i].methodFlagsStr);
+ }
+ }
+}
+
+PRBool
+isOCSPEnabled()
+{
+ int i;
+
+ for (i = 0; i < REV_METHOD_INDEX_MAX; i++) {
+ if (revMethodsData[i].methodType == REVCONFIG_METHOD_OCSP) {
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+int
+main(int argc, char *argv[], char *envp[])
+{
+ char *certDir = NULL;
+ char *progName = NULL;
+ char *oidStr = NULL;
+ CERTCertificate *cert;
+ CERTCertificate *firstCert = NULL;
+ CERTCertificate *issuerCert = NULL;
+ CERTCertDBHandle *defaultDB = NULL;
+ PRBool isAscii = PR_FALSE;
+ PRBool trusted = PR_FALSE;
+ SECStatus secStatus;
+ SECCertificateUsage certUsage = certificateUsageSSLServer;
+ PLOptState *optstate;
+ PRTime time = 0;
+ PLOptStatus status;
+ int usePkix = 0;
+ int rv = 1;
+ int usage;
+ CERTVerifyLog log;
+ CERTCertList *builtChain = NULL;
+ PRBool certFetching = PR_FALSE;
+ int revDataIndex = 0;
+ PRBool ocsp_fetchingFailureIsAFailure = PR_TRUE;
+ PRBool useDefaultRevFlags = PR_TRUE;
+ PRBool onlyTrustAnchors = PR_TRUE;
+ int vfyCounts = 1;
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ progName = PL_strdup(argv[0]);
+
+ optstate = PL_CreateOptState(argc, argv, "ab:c:d:efg:h:i:m:o:prs:tTu:vw:W:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 0: /* positional parameter */
+ goto breakout;
+ case 'a':
+ isAscii = PR_TRUE;
+ break;
+ case 'b':
+ secStatus = DER_AsciiToTime(&time, optstate->value);
+ if (secStatus != SECSuccess)
+ Usage(progName);
+ break;
+ case 'd':
+ certDir = PL_strdup(optstate->value);
+ break;
+ case 'e':
+ ocsp_fetchingFailureIsAFailure = PR_FALSE;
+ break;
+ case 'f':
+ certFetching = PR_TRUE;
+ break;
+ case 'g':
+ if (revMethodsData[revDataIndex].testTypeStr ||
+ revMethodsData[revDataIndex].methodTypeStr) {
+ revDataIndex += 1;
+ if (revDataIndex == REV_METHOD_INDEX_MAX) {
+ fprintf(stderr, "Invalid revocation configuration"
+ "specified.\n");
+ secStatus = SECFailure;
+ break;
+ }
+ }
+ useDefaultRevFlags = PR_FALSE;
+ revMethodsData[revDataIndex].testTypeStr =
+ PL_strdup(optstate->value);
+ break;
+ case 'h':
+ revMethodsData[revDataIndex].testFlagsStr =
+ PL_strdup(optstate->value);
+ break;
+ case 'i':
+ vfyCounts = PORT_Atoi(optstate->value);
+ break;
+ break;
+ case 'm':
+ if (revMethodsData[revDataIndex].methodTypeStr) {
+ revDataIndex += 1;
+ if (revDataIndex == REV_METHOD_INDEX_MAX) {
+ fprintf(stderr, "Invalid revocation configuration"
+ "specified.\n");
+ secStatus = SECFailure;
+ break;
+ }
+ }
+ useDefaultRevFlags = PR_FALSE;
+ revMethodsData[revDataIndex].methodTypeStr =
+ PL_strdup(optstate->value);
+ break;
+ case 'o':
+ oidStr = PL_strdup(optstate->value);
+ break;
+ case 'p':
+ usePkix += 1;
+ break;
+ case 'r':
+ isAscii = PR_FALSE;
+ break;
+ case 's':
+ revMethodsData[revDataIndex].methodFlagsStr =
+ PL_strdup(optstate->value);
+ break;
+ case 't':
+ trusted = PR_TRUE;
+ break;
+ case 'T':
+ onlyTrustAnchors = PR_FALSE;
+ break;
+ case 'u':
+ usage = PORT_Atoi(optstate->value);
+ if (usage < 0 || usage > 62)
+ Usage(progName);
+ certUsage = ((SECCertificateUsage)1) << usage;
+ if (certUsage > certificateUsageHighest)
+ Usage(progName);
+ break;
+ case 'w':
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
+
+ case 'W':
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ Usage(progName);
+ break;
+ }
+ }
+breakout:
+ if (status != PL_OPT_OK)
+ Usage(progName);
+
+ if (usePkix < 2) {
+ if (oidStr) {
+ fprintf(stderr, "Policy oid(-o) can be used only with"
+ " CERT_PKIXVerifyCert(-pp) function.\n");
+ Usage(progName);
+ }
+ if (trusted) {
+ fprintf(stderr, "Cert trust flag can be used only with"
+ " CERT_PKIXVerifyCert(-pp) function.\n");
+ Usage(progName);
+ }
+ if (!onlyTrustAnchors) {
+ fprintf(stderr, "Cert trust anchor exclusiveness can be"
+ " used only with CERT_PKIXVerifyCert(-pp)"
+ " function.\n");
+ }
+ }
+
+ if (!useDefaultRevFlags && parseRevMethodsAndFlags()) {
+ fprintf(stderr, "Invalid revocation configuration specified.\n");
+ goto punt;
+ }
+
+ /* Set our password function callback. */
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ /* Initialize the NSS libraries. */
+ if (certDir) {
+ secStatus = NSS_Init(certDir);
+ } else {
+ secStatus = NSS_NoDB_Init(NULL);
+
+ /* load the builtins */
+ SECMOD_AddNewModule("Builtins", DLL_PREFIX "nssckbi." DLL_SUFFIX, 0, 0);
+ }
+ if (secStatus != SECSuccess) {
+ exitErr("NSS_Init");
+ }
+ SECU_RegisterDynamicOids();
+ if (isOCSPEnabled()) {
+ CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
+ CERT_DisableOCSPDefaultResponder(CERT_GetDefaultCertDB());
+ if (!ocsp_fetchingFailureIsAFailure) {
+ CERT_SetOCSPFailureMode(ocspMode_FailureIsNotAVerificationFailure);
+ }
+ }
+
+ while (status == PL_OPT_OK) {
+ switch (optstate->option) {
+ default:
+ Usage(progName);
+ break;
+ case 'a':
+ isAscii = PR_TRUE;
+ break;
+ case 'r':
+ isAscii = PR_FALSE;
+ break;
+ case 't':
+ trusted = PR_TRUE;
+ break;
+ case 0: /* positional parameter */
+ if (usePkix < 2 && trusted) {
+ fprintf(stderr, "Cert trust flag can be used only with"
+ " CERT_PKIXVerifyCert(-pp) function.\n");
+ Usage(progName);
+ }
+ cert = getCert(optstate->value, isAscii, progName);
+ if (!cert)
+ goto punt;
+ rememberCert(cert, trusted);
+ if (!firstCert)
+ firstCert = cert;
+ trusted = PR_FALSE;
+ }
+ status = PL_GetNextOpt(optstate);
+ }
+ PL_DestroyOptState(optstate);
+ if (status == PL_OPT_BAD || !firstCert)
+ Usage(progName);
+
+ /* Initialize log structure */
+ log.arena = PORT_NewArena(512);
+ log.head = log.tail = NULL;
+ log.count = 0;
+
+ do {
+ if (usePkix < 2) {
+ /* NOW, verify the cert chain. */
+ if (usePkix) {
+ /* Use old API with libpkix validation lib */
+ CERT_SetUsePKIXForValidation(PR_TRUE);
+ }
+ if (!time)
+ time = PR_Now();
+
+ defaultDB = CERT_GetDefaultCertDB();
+ secStatus = CERT_VerifyCertificate(defaultDB, firstCert,
+ PR_TRUE /* check sig */,
+ certUsage,
+ time,
+ &pwdata, /* wincx */
+ &log, /* error log */
+ NULL); /* returned usages */
+ } else
+ do {
+ static CERTValOutParam cvout[4];
+ static CERTValInParam cvin[7];
+ SECOidTag oidTag;
+ int inParamIndex = 0;
+ static PRUint64 revFlagsLeaf[2];
+ static PRUint64 revFlagsChain[2];
+ static CERTRevocationFlags rev;
+
+ if (oidStr) {
+ PLArenaPool *arena;
+ SECOidData od;
+ memset(&od, 0, sizeof od);
+ od.offset = SEC_OID_UNKNOWN;
+ od.desc = "User Defined Policy OID";
+ od.mechanism = CKM_INVALID_MECHANISM;
+ od.supportedExtension = INVALID_CERT_EXTENSION;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ fprintf(stderr, "out of memory");
+ goto punt;
+ }
+
+ secStatus = SEC_StringToOID(arena, &od.oid, oidStr, 0);
+ if (secStatus != SECSuccess) {
+ PORT_FreeArena(arena, PR_FALSE);
+ fprintf(stderr, "Can not encode oid: %s(%s)\n", oidStr,
+ SECU_Strerror(PORT_GetError()));
+ break;
+ }
+
+ oidTag = SECOID_AddEntry(&od);
+ PORT_FreeArena(arena, PR_FALSE);
+ if (oidTag == SEC_OID_UNKNOWN) {
+ fprintf(stderr, "Can not add new oid to the dynamic "
+ "table: %s\n",
+ oidStr);
+ secStatus = SECFailure;
+ break;
+ }
+
+ cvin[inParamIndex].type = cert_pi_policyOID;
+ cvin[inParamIndex].value.arraySize = 1;
+ cvin[inParamIndex].value.array.oids = &oidTag;
+
+ inParamIndex++;
+ }
+
+ if (trustedCertList) {
+ cvin[inParamIndex].type = cert_pi_trustAnchors;
+ cvin[inParamIndex].value.pointer.chain = trustedCertList;
+
+ inParamIndex++;
+ }
+
+ cvin[inParamIndex].type = cert_pi_useAIACertFetch;
+ cvin[inParamIndex].value.scalar.b = certFetching;
+ inParamIndex++;
+
+ rev.leafTests.cert_rev_flags_per_method = revFlagsLeaf;
+ rev.chainTests.cert_rev_flags_per_method = revFlagsChain;
+ secStatus = configureRevocationParams(&rev);
+ if (secStatus) {
+ fprintf(stderr, "Can not config revocation parameters ");
+ break;
+ }
+
+ cvin[inParamIndex].type = cert_pi_revocationFlags;
+ cvin[inParamIndex].value.pointer.revocation = &rev;
+ inParamIndex++;
+
+ if (time) {
+ cvin[inParamIndex].type = cert_pi_date;
+ cvin[inParamIndex].value.scalar.time = time;
+ inParamIndex++;
+ }
+
+ if (!onlyTrustAnchors) {
+ cvin[inParamIndex].type = cert_pi_useOnlyTrustAnchors;
+ cvin[inParamIndex].value.scalar.b = onlyTrustAnchors;
+ inParamIndex++;
+ }
+
+ cvin[inParamIndex].type = cert_pi_end;
+
+ cvout[0].type = cert_po_trustAnchor;
+ cvout[0].value.pointer.cert = NULL;
+ cvout[1].type = cert_po_certList;
+ cvout[1].value.pointer.chain = NULL;
+
+ /* setting pointer to CERTVerifyLog. Initialized structure
+ * will be used CERT_PKIXVerifyCert */
+ cvout[2].type = cert_po_errorLog;
+ cvout[2].value.pointer.log = &log;
+
+ cvout[3].type = cert_po_end;
+
+ secStatus = CERT_PKIXVerifyCert(firstCert, certUsage,
+ cvin, cvout, &pwdata);
+ if (secStatus != SECSuccess) {
+ break;
+ }
+ issuerCert = cvout[0].value.pointer.cert;
+ builtChain = cvout[1].value.pointer.chain;
+ } while (0);
+
+ /* Display validation results */
+ if (secStatus != SECSuccess || log.count > 0) {
+ CERTVerifyLogNode *node = NULL;
+ fprintf(stderr, "Chain is bad!\n");
+
+ SECU_displayVerifyLog(stderr, &log, verbose);
+ /* Have cert refs in the log only in case of failure.
+ * Destroy them. */
+ for (node = log.head; node; node = node->next) {
+ if (node->cert)
+ CERT_DestroyCertificate(node->cert);
+ }
+ log.head = log.tail = NULL;
+ log.count = 0;
+ rv = 1;
+ } else {
+ fprintf(stderr, "Chain is good!\n");
+ if (issuerCert) {
+ if (verbose > 1) {
+ rv = SEC_PrintCertificateAndTrust(issuerCert, "Root Certificate",
+ NULL);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "problem printing certificate");
+ }
+ } else if (verbose > 0) {
+ SECU_PrintName(stdout, &issuerCert->subject, "Root "
+ "Certificate Subject:",
+ 0);
+ }
+ CERT_DestroyCertificate(issuerCert);
+ }
+ if (builtChain) {
+ CERTCertListNode *node;
+ int count = 0;
+ char buff[256];
+
+ if (verbose) {
+ for (node = CERT_LIST_HEAD(builtChain); !CERT_LIST_END(node, builtChain);
+ node = CERT_LIST_NEXT(node), count++) {
+ sprintf(buff, "Certificate %d Subject", count + 1);
+ SECU_PrintName(stdout, &node->cert->subject, buff, 0);
+ }
+ }
+ CERT_DestroyCertList(builtChain);
+ }
+ rv = 0;
+ }
+ } while (--vfyCounts > 0);
+
+ /* Need to destroy CERTVerifyLog arena at the end */
+ PORT_FreeArena(log.arena, PR_FALSE);
+
+punt:
+ forgetCerts();
+ if (NSS_Shutdown() != SECSuccess) {
+ SECU_PrintError(progName, "NSS_Shutdown");
+ rv = 1;
+ }
+ PORT_Free(progName);
+ PORT_Free(certDir);
+ PORT_Free(oidStr);
+ freeRevocationMethodData();
+ if (pwdata.data) {
+ PORT_Free(pwdata.data);
+ }
+ PL_ArenaFinish();
+ PR_Cleanup();
+ return rv;
+}
diff --git a/security/nss/cmd/vfychain/vfychain.gyp b/security/nss/cmd/vfychain/vfychain.gyp
new file mode 100644
index 000000000..775ba1f05
--- /dev/null
+++ b/security/nss/cmd/vfychain/vfychain.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'vfychain',
+ 'type': 'executable',
+ 'sources': [
+ 'vfychain.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'DLL_PREFIX=\"<(dll_prefix)\"',
+ 'DLL_SUFFIX=\"<(dll_suffix)\"'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/vfyserv/Makefile b/security/nss/cmd/vfyserv/Makefile
new file mode 100644
index 000000000..a27a3ce97
--- /dev/null
+++ b/security/nss/cmd/vfyserv/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#include ../platlibs.mk
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/vfyserv/manifest.mn b/security/nss/cmd/vfyserv/manifest.mn
new file mode 100644
index 000000000..c925be966
--- /dev/null
+++ b/security/nss/cmd/vfyserv/manifest.mn
@@ -0,0 +1,23 @@
+#
+# 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/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+# DIRS =
+
+CSRCS = vfyserv.c vfyutil.c
+DEFINES += -DDLL_PREFIX=\"$(DLL_PREFIX)\" -DDLL_SUFFIX=\"$(DLL_SUFFIX)\"
+
+PROGRAM = vfyserv
+
diff --git a/security/nss/cmd/vfyserv/vfyserv.c b/security/nss/cmd/vfyserv/vfyserv.c
new file mode 100644
index 000000000..aa648ad8c
--- /dev/null
+++ b/security/nss/cmd/vfyserv/vfyserv.c
@@ -0,0 +1,572 @@
+/* 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/. */
+
+/****************************************************************************
+ * SSL client program that tests a server for proper operation of SSL2, *
+ * SSL3, and TLS. Test propder certificate installation. *
+ * *
+ * This code was modified from the SSLSample code also kept in the NSS *
+ * directory. *
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "prerror.h"
+
+#include "pk11func.h"
+#include "secmod.h"
+#include "secitem.h"
+
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "nspr.h"
+#include "plgetopt.h"
+#include "prio.h"
+#include "prnetdb.h"
+#include "nss.h"
+#include "secutil.h"
+#include "ocsp.h"
+
+#include "vfyserv.h"
+
+#define RD_BUF_SIZE (60 * 1024)
+
+extern int ssl3CipherSuites[];
+extern int numSSL3CipherSuites;
+
+GlobalThreadMgr threadMGR;
+char *certNickname = NULL;
+char *hostName = NULL;
+secuPWData pwdata = { PW_NONE, 0 };
+unsigned short port = 0;
+PRBool dumpChain;
+
+static void
+Usage(const char *progName)
+{
+ PRFileDesc *pr_stderr;
+
+ pr_stderr = PR_STDERR;
+
+ PR_fprintf(pr_stderr, "Usage:\n"
+ " %s [-c ] [-o] [-p port] [-d dbdir] [-w password] [-f pwfile]\n"
+ " \t\t[-C cipher(s)] [-l <url> -t <nickname> ] hostname",
+ progName);
+ PR_fprintf(pr_stderr, "\nWhere:\n");
+ PR_fprintf(pr_stderr,
+ " %-13s dump server cert chain into files\n",
+ "-c");
+ PR_fprintf(pr_stderr,
+ " %-13s perform server cert OCSP check\n",
+ "-o");
+ PR_fprintf(pr_stderr,
+ " %-13s server port to be used\n",
+ "-p");
+ PR_fprintf(pr_stderr,
+ " %-13s use security databases in \"dbdir\"\n",
+ "-d dbdir");
+ PR_fprintf(pr_stderr,
+ " %-13s key database password\n",
+ "-w password");
+ PR_fprintf(pr_stderr,
+ " %-13s token password file\n",
+ "-f pwfile");
+ PR_fprintf(pr_stderr,
+ " %-13s communication cipher list\n",
+ "-C cipher(s)");
+ PR_fprintf(pr_stderr,
+ " %-13s OCSP responder location. This location is used to\n"
+ " %-13s check status of a server certificate. If not \n"
+ " %-13s specified, location will be taken from the AIA\n"
+ " %-13s server certificate extension.\n",
+ "-l url", "", "", "");
+ PR_fprintf(pr_stderr,
+ " %-13s OCSP Trusted Responder Cert nickname\n\n",
+ "-t nickname");
+
+ exit(1);
+}
+
+PRFileDesc *
+setupSSLSocket(PRNetAddr *addr)
+{
+ PRFileDesc *tcpSocket;
+ PRFileDesc *sslSocket;
+ PRSocketOptionData socketOption;
+ PRStatus prStatus;
+ SECStatus secStatus;
+
+ tcpSocket = PR_NewTCPSocket();
+ if (tcpSocket == NULL) {
+ errWarn("PR_NewTCPSocket");
+ }
+
+ /* Make the socket blocking. */
+ socketOption.option = PR_SockOpt_Nonblocking;
+ socketOption.value.non_blocking = PR_FALSE;
+
+ prStatus = PR_SetSocketOption(tcpSocket, &socketOption);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_SetSocketOption");
+ goto loser;
+ }
+
+ /* Import the socket into the SSL layer. */
+ sslSocket = SSL_ImportFD(NULL, tcpSocket);
+ if (!sslSocket) {
+ errWarn("SSL_ImportFD");
+ goto loser;
+ }
+
+ /* Set configuration options. */
+ secStatus = SSL_OptionSet(sslSocket, SSL_SECURITY, PR_TRUE);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_OptionSet:SSL_SECURITY");
+ goto loser;
+ }
+
+ secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_CLIENT");
+ goto loser;
+ }
+
+ /* Set SSL callback routines. */
+ secStatus = SSL_GetClientAuthDataHook(sslSocket,
+ (SSLGetClientAuthData)myGetClientAuthData,
+ (void *)certNickname);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_GetClientAuthDataHook");
+ goto loser;
+ }
+
+ secStatus = SSL_AuthCertificateHook(sslSocket,
+ (SSLAuthCertificate)myAuthCertificate,
+ (void *)CERT_GetDefaultCertDB());
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_AuthCertificateHook");
+ goto loser;
+ }
+
+ secStatus = SSL_BadCertHook(sslSocket,
+ (SSLBadCertHandler)myBadCertHandler, NULL);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_BadCertHook");
+ goto loser;
+ }
+
+ secStatus = SSL_HandshakeCallback(sslSocket,
+ myHandshakeCallback,
+ NULL);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_HandshakeCallback");
+ goto loser;
+ }
+
+ return sslSocket;
+
+loser:
+
+ PR_Close(tcpSocket);
+ return NULL;
+}
+
+const char requestString[] = { "GET /testfile HTTP/1.0\r\n\r\n" };
+
+SECStatus
+handle_connection(PRFileDesc *sslSocket, int connection)
+{
+ int countRead = 0;
+ PRInt32 numBytes;
+ char *readBuffer;
+
+ readBuffer = PORT_Alloc(RD_BUF_SIZE);
+ if (!readBuffer) {
+ exitErr("PORT_Alloc");
+ }
+
+ /* compose the http request here. */
+
+ numBytes = PR_Write(sslSocket, requestString, strlen(requestString));
+ if (numBytes <= 0) {
+ errWarn("PR_Write");
+ PR_Free(readBuffer);
+ readBuffer = NULL;
+ return SECFailure;
+ }
+
+ /* read until EOF */
+ while (PR_TRUE) {
+ numBytes = PR_Read(sslSocket, readBuffer, RD_BUF_SIZE);
+ if (numBytes == 0) {
+ break; /* EOF */
+ }
+ if (numBytes < 0) {
+ errWarn("PR_Read");
+ break;
+ }
+ countRead += numBytes;
+ }
+
+ printSecurityInfo(stderr, sslSocket);
+
+ PR_Free(readBuffer);
+ readBuffer = NULL;
+
+ /* Caller closes the socket. */
+
+ fprintf(stderr,
+ "***** Connection %d read %d bytes total.\n",
+ connection, countRead);
+
+ return SECSuccess; /* success */
+}
+
+#define BYTE(n, i) (((i) >> ((n)*8)) & 0xff)
+
+/* one copy of this function is launched in a separate thread for each
+** connection to be made.
+*/
+SECStatus
+do_connects(void *a, int connection)
+{
+ PRNetAddr *addr = (PRNetAddr *)a;
+ PRFileDesc *sslSocket;
+ PRHostEnt hostEntry;
+ char buffer[PR_NETDB_BUF_SIZE];
+ PRStatus prStatus;
+ PRIntn hostenum;
+ PRInt32 ip;
+ SECStatus secStatus;
+
+ /* Set up SSL secure socket. */
+ sslSocket = setupSSLSocket(addr);
+ if (sslSocket == NULL) {
+ errWarn("setupSSLSocket");
+ return SECFailure;
+ }
+
+ secStatus = SSL_SetPKCS11PinArg(sslSocket, &pwdata);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_SetPKCS11PinArg");
+ return secStatus;
+ }
+
+ secStatus = SSL_SetURL(sslSocket, hostName);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_SetURL");
+ return secStatus;
+ }
+
+ /* Prepare and setup network connection. */
+ prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_GetHostByName");
+ return SECFailure;
+ }
+
+ hostenum = PR_EnumerateHostEnt(0, &hostEntry, port, addr);
+ if (hostenum == -1) {
+ errWarn("PR_EnumerateHostEnt");
+ return SECFailure;
+ }
+
+ ip = PR_ntohl(addr->inet.ip);
+ fprintf(stderr,
+ "Connecting to host %s (addr %d.%d.%d.%d) on port %d\n",
+ hostName, BYTE(3, ip), BYTE(2, ip), BYTE(1, ip),
+ BYTE(0, ip), PR_ntohs(addr->inet.port));
+
+ prStatus = PR_Connect(sslSocket, addr, PR_INTERVAL_NO_TIMEOUT);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_Connect");
+ return SECFailure;
+ }
+
+/* Established SSL connection, ready to send data. */
+#if 0
+ secStatus = SSL_ForceHandshake(sslSocket);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_ForceHandshake");
+ return secStatus;
+ }
+#endif
+
+ secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_FALSE);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_ResetHandshake");
+ prStatus = PR_Close(sslSocket);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_Close");
+ }
+ return secStatus;
+ }
+
+ secStatus = handle_connection(sslSocket, connection);
+ if (secStatus != SECSuccess) {
+ /* error already printed out in handle_connection */
+ /* errWarn("handle_connection"); */
+ prStatus = PR_Close(sslSocket);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_Close");
+ }
+ return secStatus;
+ }
+
+ PR_Close(sslSocket);
+ return SECSuccess;
+}
+
+void
+client_main(unsigned short port,
+ int connections,
+ const char *hostName)
+{
+ int i;
+ SECStatus secStatus;
+ PRStatus prStatus;
+ PRInt32 rv;
+ PRNetAddr addr;
+ PRHostEnt hostEntry;
+ char buffer[PR_NETDB_BUF_SIZE];
+
+ /* Setup network connection. */
+ prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
+ if (prStatus != PR_SUCCESS) {
+ exitErr("PR_GetHostByName");
+ }
+
+ rv = PR_EnumerateHostEnt(0, &hostEntry, port, &addr);
+ if (rv < 0) {
+ exitErr("PR_EnumerateHostEnt");
+ }
+
+ secStatus = launch_thread(&threadMGR, do_connects, &addr, 1);
+ if (secStatus != SECSuccess) {
+ exitErr("launch_thread");
+ }
+
+ if (connections > 1) {
+ /* wait for the first connection to terminate, then launch the rest. */
+ reap_threads(&threadMGR);
+ /* Start up the connections */
+ for (i = 2; i <= connections; ++i) {
+ secStatus = launch_thread(&threadMGR, do_connects, &addr, i);
+ if (secStatus != SECSuccess) {
+ errWarn("launch_thread");
+ }
+ }
+ }
+
+ reap_threads(&threadMGR);
+ destroy_thread_data(&threadMGR);
+}
+
+#define HEXCHAR_TO_INT(c, i) \
+ if (((c) >= '0') && ((c) <= '9')) { \
+ i = (c) - '0'; \
+ } else if (((c) >= 'a') && ((c) <= 'f')) { \
+ i = (c) - 'a' + 10; \
+ } else if (((c) >= 'A') && ((c) <= 'F')) { \
+ i = (c) - 'A' + 10; \
+ } else { \
+ Usage(progName); \
+ }
+
+int
+main(int argc, char **argv)
+{
+ char *certDir = NULL;
+ char *progName = NULL;
+ int connections = 1;
+ char *cipherString = NULL;
+ char *respUrl = NULL;
+ char *respCertName = NULL;
+ SECStatus secStatus;
+ PLOptState *optstate;
+ PLOptStatus status;
+ PRBool doOcspCheck = PR_FALSE;
+
+ /* Call the NSPR initialization routines */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ progName = PORT_Strdup(argv[0]);
+
+ hostName = NULL;
+ optstate = PL_CreateOptState(argc, argv, "C:cd:f:l:n:p:ot:w:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'C':
+ cipherString = PL_strdup(optstate->value);
+ break;
+ case 'c':
+ dumpChain = PR_TRUE;
+ break;
+ case 'd':
+ certDir = PL_strdup(optstate->value);
+ break;
+ case 'l':
+ respUrl = PL_strdup(optstate->value);
+ break;
+ case 'p':
+ port = PORT_Atoi(optstate->value);
+ break;
+ case 'o':
+ doOcspCheck = PR_TRUE;
+ break;
+ case 't':
+ respCertName = PL_strdup(optstate->value);
+ break;
+ case 'w':
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
+
+ case 'f':
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = PORT_Strdup(optstate->value);
+ break;
+ case '\0':
+ hostName = PL_strdup(optstate->value);
+ break;
+ default:
+ Usage(progName);
+ }
+ }
+
+ if (port == 0) {
+ port = 443;
+ }
+
+ if (port == 0 || hostName == NULL)
+ Usage(progName);
+
+ if (doOcspCheck &&
+ ((respCertName != NULL && respUrl == NULL) ||
+ (respUrl != NULL && respCertName == NULL))) {
+ SECU_PrintError(progName, "options -l <url> and -t "
+ "<responder> must be used together");
+ Usage(progName);
+ }
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ /* Initialize the NSS libraries. */
+ if (certDir) {
+ secStatus = NSS_Init(certDir);
+ } else {
+ secStatus = NSS_NoDB_Init(NULL);
+
+ /* load the builtins */
+ SECMOD_AddNewModule("Builtins",
+ DLL_PREFIX "nssckbi." DLL_SUFFIX, 0, 0);
+ }
+ if (secStatus != SECSuccess) {
+ exitErr("NSS_Init");
+ }
+ SECU_RegisterDynamicOids();
+
+ if (doOcspCheck == PR_TRUE) {
+ SECStatus rv;
+ CERTCertDBHandle *handle = CERT_GetDefaultCertDB();
+ if (handle == NULL) {
+ SECU_PrintError(progName, "problem getting certdb handle");
+ goto cleanup;
+ }
+
+ rv = CERT_EnableOCSPChecking(handle);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling OCSP checking");
+ goto cleanup;
+ }
+
+ if (respUrl != NULL) {
+ rv = CERT_SetOCSPDefaultResponder(handle, respUrl,
+ respCertName);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName,
+ "error setting default responder");
+ goto cleanup;
+ }
+
+ rv = CERT_EnableOCSPDefaultResponder(handle);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName,
+ "error enabling default responder");
+ goto cleanup;
+ }
+ }
+ }
+
+ /* All cipher suites except RSA_NULL_MD5 are enabled by
+ * Domestic Policy. */
+ NSS_SetDomesticPolicy();
+ SSL_CipherPrefSetDefault(TLS_RSA_WITH_NULL_MD5, PR_TRUE);
+
+ /* all the SSL2 and SSL3 cipher suites are enabled by default. */
+ if (cipherString) {
+ int ndx;
+
+ /* disable all the ciphers, then enable the ones we want. */
+ disableAllSSLCiphers();
+
+ while (0 != (ndx = *cipherString++)) {
+ int cipher = 0;
+
+ if (ndx == ':') {
+ int ctmp = 0;
+
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= (ctmp << 12);
+ cipherString++;
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= (ctmp << 8);
+ cipherString++;
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= (ctmp << 4);
+ cipherString++;
+ HEXCHAR_TO_INT(*cipherString, ctmp)
+ cipher |= ctmp;
+ cipherString++;
+ } else {
+ if (!isalpha(ndx))
+ Usage(progName);
+ ndx = tolower(ndx) - 'a';
+ if (ndx < numSSL3CipherSuites) {
+ cipher = ssl3CipherSuites[ndx];
+ }
+ }
+ if (cipher > 0) {
+ SSL_CipherPrefSetDefault(cipher, PR_TRUE);
+ } else {
+ Usage(progName);
+ }
+ }
+ }
+
+ client_main(port, connections, hostName);
+
+cleanup:
+ if (doOcspCheck) {
+ CERTCertDBHandle *handle = CERT_GetDefaultCertDB();
+ CERT_DisableOCSPDefaultResponder(handle);
+ CERT_DisableOCSPChecking(handle);
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ PR_Cleanup();
+ PORT_Free(progName);
+ return 0;
+}
diff --git a/security/nss/cmd/vfyserv/vfyserv.gyp b/security/nss/cmd/vfyserv/vfyserv.gyp
new file mode 100644
index 000000000..85001a1ec
--- /dev/null
+++ b/security/nss/cmd/vfyserv/vfyserv.gyp
@@ -0,0 +1,32 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'vfyserv',
+ 'type': 'executable',
+ 'sources': [
+ 'vfyserv.c',
+ 'vfyutil.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'DLL_PREFIX=\"<(dll_prefix)\"',
+ 'DLL_SUFFIX=\"<(dll_suffix)\"'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/vfyserv/vfyserv.h b/security/nss/cmd/vfyserv/vfyserv.h
new file mode 100644
index 000000000..00afc8049
--- /dev/null
+++ b/security/nss/cmd/vfyserv/vfyserv.h
@@ -0,0 +1,138 @@
+/* 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 SSLSAMPLE_H
+#define SSLSAMPLE_H
+
+/* Generic header files */
+
+#include <stdio.h>
+#include <string.h>
+
+/* NSPR header files */
+
+#include "nspr.h"
+#include "prerror.h"
+#include "prnetdb.h"
+
+/* NSS header files */
+
+#include "pk11func.h"
+#include "secitem.h"
+#include "ssl.h"
+#include "certt.h"
+#include "nss.h"
+#include "secder.h"
+#include "key.h"
+#include "sslproto.h"
+
+/* Custom header files */
+
+/*
+#include "sslerror.h"
+*/
+
+#define BUFFER_SIZE 10240
+
+/* Declare SSL cipher suites. */
+
+extern int cipherSuites[];
+extern int ssl3CipherSuites[];
+
+/* Data buffer read from a socket. */
+typedef struct DataBufferStr {
+ char data[BUFFER_SIZE];
+ int index;
+ int remaining;
+ int dataStart;
+ int dataEnd;
+} DataBuffer;
+
+/* SSL callback routines. */
+
+char *myPasswd(PK11SlotInfo *info, PRBool retry, void *arg);
+
+SECStatus myAuthCertificate(void *arg, PRFileDesc *socket,
+ PRBool checksig, PRBool isServer);
+
+SECStatus myBadCertHandler(void *arg, PRFileDesc *socket);
+
+void myHandshakeCallback(PRFileDesc *socket, void *arg);
+
+SECStatus myGetClientAuthData(void *arg, PRFileDesc *socket,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey);
+
+/* Disable all v2/v3 SSL ciphers. */
+
+void disableAllSSLCiphers(void);
+
+/* Error and information utilities. */
+
+void errWarn(char *function);
+
+void exitErr(char *function);
+
+void printSecurityInfo(FILE *outfile, PRFileDesc *fd);
+
+/* Some simple thread management routines. */
+
+#define MAX_THREADS 32
+
+typedef SECStatus startFn(void *a, int b);
+
+typedef enum { rs_idle = 0,
+ rs_running = 1,
+ rs_zombie = 2 } runState;
+
+typedef struct perThreadStr {
+ PRFileDesc *a;
+ int b;
+ int rv;
+ startFn *startFunc;
+ PRThread *prThread;
+ PRBool inUse;
+ runState running;
+} perThread;
+
+typedef struct GlobalThreadMgrStr {
+ PRLock *threadLock;
+ PRCondVar *threadStartQ;
+ PRCondVar *threadEndQ;
+ perThread threads[MAX_THREADS];
+ int index;
+ int numUsed;
+ int numRunning;
+} GlobalThreadMgr;
+
+void thread_wrapper(void *arg);
+
+SECStatus launch_thread(GlobalThreadMgr *threadMGR,
+ startFn *startFunc, void *a, int b);
+
+SECStatus reap_threads(GlobalThreadMgr *threadMGR);
+
+void destroy_thread_data(GlobalThreadMgr *threadMGR);
+
+/* Management of locked variables. */
+
+struct lockedVarsStr {
+ PRLock *lock;
+ int count;
+ int waiters;
+ PRCondVar *condVar;
+};
+
+typedef struct lockedVarsStr lockedVars;
+
+void lockedVars_Init(lockedVars *lv);
+
+void lockedVars_Destroy(lockedVars *lv);
+
+void lockedVars_WaitForDone(lockedVars *lv);
+
+int lockedVars_AddToCount(lockedVars *lv, int addend);
+
+#endif
diff --git a/security/nss/cmd/vfyserv/vfyutil.c b/security/nss/cmd/vfyserv/vfyutil.c
new file mode 100644
index 000000000..2f1b53262
--- /dev/null
+++ b/security/nss/cmd/vfyserv/vfyutil.c
@@ -0,0 +1,620 @@
+/* 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/. */
+
+#include "vfyserv.h"
+#include "secerr.h"
+#include "sslerr.h"
+#include "nspr.h"
+#include "secutil.h"
+
+extern PRBool dumpChain;
+extern void dumpCertChain(CERTCertificate *, SECCertUsage);
+
+/* Declare SSL cipher suites. */
+
+int ssl3CipherSuites[] = {
+ -1, /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
+ -1, /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA * b */
+ TLS_RSA_WITH_RC4_128_MD5, /* c */
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
+ TLS_RSA_WITH_DES_CBC_SHA, /* e */
+ -1, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 * f */
+ -1, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 * g */
+ -1, /* SSL_FORTEZZA_DMS_WITH_NULL_SHA * h */
+ TLS_RSA_WITH_NULL_MD5, /* i */
+ -1, /* SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA * j */
+ -1, /* SSL_RSA_FIPS_WITH_DES_CBC_SHA * k */
+ -1, /* TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA * l */
+ -1, /* TLS_RSA_EXPORT1024_WITH_RC4_56_SHA * m */
+ TLS_RSA_WITH_RC4_128_SHA, /* n */
+ TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */
+ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
+ TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
+ TLS_DHE_RSA_WITH_DES_CBC_SHA, /* r */
+ TLS_DHE_DSS_WITH_DES_CBC_SHA, /* s */
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* t */
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* u */
+ TLS_RSA_WITH_AES_128_CBC_SHA, /* v */
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* w */
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* x */
+ TLS_RSA_WITH_AES_256_CBC_SHA, /* y */
+ TLS_RSA_WITH_NULL_SHA, /* z */
+ 0
+};
+int numSSL3CipherSuites = PR_ARRAY_SIZE(ssl3CipherSuites);
+
+/**************************************************************************
+**
+** SSL callback routines.
+**
+**************************************************************************/
+
+/* Function: char * myPasswd()
+ *
+ * Purpose: This function is our custom password handler that is called by
+ * SSL when retreiving private certs and keys from the database. Returns a
+ * pointer to a string that with a password for the database. Password pointer
+ * should point to dynamically allocated memory that will be freed later.
+ */
+char *
+myPasswd(PK11SlotInfo *info, PRBool retry, void *arg)
+{
+ char *passwd = NULL;
+
+ if ((!retry) && arg) {
+ passwd = PORT_Strdup((char *)arg);
+ }
+ return passwd;
+}
+
+/* Function: SECStatus myAuthCertificate()
+ *
+ * Purpose: This function is our custom certificate authentication handler.
+ *
+ * Note: This implementation is essentially the same as the default
+ * SSL_AuthCertificate().
+ */
+SECStatus
+myAuthCertificate(void *arg, PRFileDesc *socket,
+ PRBool checksig, PRBool isServer)
+{
+
+ SECCertificateUsage certUsage;
+ CERTCertificate *cert;
+ void *pinArg;
+ char *hostName;
+ SECStatus secStatus;
+
+ if (!arg || !socket) {
+ errWarn("myAuthCertificate");
+ return SECFailure;
+ }
+
+ /* Define how the cert is being used based upon the isServer flag. */
+
+ certUsage = isServer ? certificateUsageSSLClient : certificateUsageSSLServer;
+
+ cert = SSL_PeerCertificate(socket);
+
+ pinArg = SSL_RevealPinArg(socket);
+
+ if (dumpChain == PR_TRUE) {
+ dumpCertChain(cert, certUsage);
+ }
+
+ secStatus = CERT_VerifyCertificateNow((CERTCertDBHandle *)arg,
+ cert,
+ checksig,
+ certUsage,
+ pinArg,
+ NULL);
+
+ /* If this is a server, we're finished. */
+ if (isServer || secStatus != SECSuccess) {
+ SECU_printCertProblems(stderr, (CERTCertDBHandle *)arg, cert,
+ checksig, certUsage, pinArg, PR_FALSE);
+ CERT_DestroyCertificate(cert);
+ return secStatus;
+ }
+
+ /* Certificate is OK. Since this is the client side of an SSL
+ * connection, we need to verify that the name field in the cert
+ * matches the desired hostname. This is our defense against
+ * man-in-the-middle attacks.
+ */
+
+ /* SSL_RevealURL returns a hostName, not an URL. */
+ hostName = SSL_RevealURL(socket);
+
+ if (hostName && hostName[0]) {
+ secStatus = CERT_VerifyCertName(cert, hostName);
+ } else {
+ PR_SetError(SSL_ERROR_BAD_CERT_DOMAIN, 0);
+ secStatus = SECFailure;
+ }
+
+ if (hostName)
+ PR_Free(hostName);
+
+ CERT_DestroyCertificate(cert);
+ return secStatus;
+}
+
+/* Function: SECStatus myBadCertHandler()
+ *
+ * Purpose: This callback is called when the incoming certificate is not
+ * valid. We define a certain set of parameters that still cause the
+ * certificate to be "valid" for this session, and return SECSuccess to cause
+ * the server to continue processing the request when any of these conditions
+ * are met. Otherwise, SECFailure is return and the server rejects the
+ * request.
+ */
+SECStatus
+myBadCertHandler(void *arg, PRFileDesc *socket)
+{
+
+ SECStatus secStatus = SECFailure;
+ PRErrorCode err;
+
+ /* log invalid cert here */
+
+ if (!arg) {
+ return secStatus;
+ }
+
+ *(PRErrorCode *)arg = err = PORT_GetError();
+
+ /* If any of the cases in the switch are met, then we will proceed */
+ /* with the processing of the request anyway. Otherwise, the default */
+ /* case will be reached and we will reject the request. */
+
+ switch (err) {
+ case SEC_ERROR_INVALID_AVA:
+ case SEC_ERROR_INVALID_TIME:
+ case SEC_ERROR_BAD_SIGNATURE:
+ case SEC_ERROR_EXPIRED_CERTIFICATE:
+ case SEC_ERROR_UNKNOWN_ISSUER:
+ case SEC_ERROR_UNTRUSTED_CERT:
+ case SEC_ERROR_CERT_VALID:
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ case SEC_ERROR_CRL_EXPIRED:
+ case SEC_ERROR_CRL_BAD_SIGNATURE:
+ case SEC_ERROR_EXTENSION_VALUE_INVALID:
+ case SEC_ERROR_CA_CERT_INVALID:
+ case SEC_ERROR_CERT_USAGES_INVALID:
+ case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:
+ secStatus = SECSuccess;
+ break;
+ default:
+ secStatus = SECFailure;
+ break;
+ }
+
+ fprintf(stderr, "Bad certificate: %d, %s\n", err, SECU_Strerror(err));
+
+ return secStatus;
+}
+
+/* Function: SECStatus ownGetClientAuthData()
+ *
+ * Purpose: This callback is used by SSL to pull client certificate
+ * information upon server request.
+ */
+SECStatus
+myGetClientAuthData(void *arg,
+ PRFileDesc *socket,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+
+ CERTCertificate *cert;
+ SECKEYPrivateKey *privKey;
+ char *chosenNickName = (char *)arg;
+ void *proto_win = NULL;
+ SECStatus secStatus = SECFailure;
+
+ proto_win = SSL_RevealPinArg(socket);
+
+ if (chosenNickName) {
+ cert = PK11_FindCertFromNickname(chosenNickName, proto_win);
+ if (cert) {
+ privKey = PK11_FindKeyByAnyCert(cert, proto_win);
+ if (privKey) {
+ secStatus = SECSuccess;
+ } else {
+ CERT_DestroyCertificate(cert);
+ }
+ }
+ } else { /* no nickname given, automatically find the right cert */
+ CERTCertNicknames *names;
+ int i;
+
+ names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
+ SEC_CERT_NICKNAMES_USER, proto_win);
+
+ if (names != NULL) {
+ for (i = 0; i < names->numnicknames; i++) {
+
+ cert = PK11_FindCertFromNickname(names->nicknames[i],
+ proto_win);
+ if (!cert) {
+ continue;
+ }
+
+ /* Only check unexpired certs */
+ if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE) !=
+ secCertTimeValid) {
+ CERT_DestroyCertificate(cert);
+ continue;
+ }
+
+ secStatus = NSS_CmpCertChainWCANames(cert, caNames);
+ if (secStatus == SECSuccess) {
+ privKey = PK11_FindKeyByAnyCert(cert, proto_win);
+ if (privKey) {
+ break;
+ }
+ secStatus = SECFailure;
+ }
+ CERT_DestroyCertificate(cert);
+ } /* for loop */
+ CERT_FreeNicknames(names);
+ }
+ }
+
+ if (secStatus == SECSuccess) {
+ *pRetCert = cert;
+ *pRetKey = privKey;
+ }
+
+ return secStatus;
+}
+
+/* Function: void myHandshakeCallback()
+ *
+ * Purpose: Called by SSL to inform application that the handshake is
+ * complete. This function is mostly used on the server side of an SSL
+ * connection, although it is provided for a client as well.
+ * Useful when a non-blocking SSL_ReHandshake or SSL_ResetHandshake
+ * is used to initiate a handshake.
+ *
+ * A typical scenario would be:
+ *
+ * 1. Server accepts an SSL connection from the client without client auth.
+ * 2. Client sends a request.
+ * 3. Server determines that to service request it needs to authenticate the
+ * client and initiates another handshake requesting client auth.
+ * 4. While handshake is in progress, server can do other work or spin waiting
+ * for the handshake to complete.
+ * 5. Server is notified that handshake has been successfully completed by
+ * the custom handshake callback function and it can service the client's
+ * request.
+ *
+ * Note: This function is not implemented in this sample, as we are using
+ * blocking sockets.
+ */
+void
+myHandshakeCallback(PRFileDesc *socket, void *arg)
+{
+ fprintf(stderr, "Handshake Complete: SERVER CONFIGURED CORRECTLY\n");
+}
+
+/**************************************************************************
+**
+** Routines for disabling SSL ciphers.
+**
+**************************************************************************/
+
+void
+disableAllSSLCiphers(void)
+{
+ const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
+ int i = SSL_NumImplementedCiphers;
+ SECStatus rv;
+
+ /* disable all the SSL3 cipher suites */
+ while (--i >= 0) {
+ PRUint16 suite = cipherSuites[i];
+ rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
+ if (rv != SECSuccess) {
+ fprintf(stderr,
+ "SSL_CipherPrefSetDefault didn't like value 0x%04x (i = %d)\n",
+ suite, i);
+ errWarn("SSL_CipherPrefSetDefault");
+ exit(2);
+ }
+ }
+}
+
+/**************************************************************************
+**
+** Error and information routines.
+**
+**************************************************************************/
+
+void
+errWarn(char *function)
+{
+ PRErrorCode errorNumber = PR_GetError();
+ const char *errorString = SECU_Strerror(errorNumber);
+
+ fprintf(stderr, "Error in function %s: %d\n - %s\n",
+ function, errorNumber, errorString);
+}
+
+void
+exitErr(char *function)
+{
+ errWarn(function);
+ /* Exit gracefully. */
+ /* ignoring return value of NSS_Shutdown as code exits with 1 anyway*/
+ (void)NSS_Shutdown();
+ PR_Cleanup();
+ exit(1);
+}
+
+void
+printSecurityInfo(FILE *outfile, PRFileDesc *fd)
+{
+ char *cp; /* bulk cipher name */
+ char *ip; /* cert issuer DN */
+ char *sp; /* cert subject DN */
+ int op; /* High, Low, Off */
+ int kp0; /* total key bits */
+ int kp1; /* secret key bits */
+ int result;
+ SSL3Statistics *ssl3stats = SSL_GetStatistics();
+
+ if (!outfile) {
+ outfile = stdout;
+ }
+
+ result = SSL_SecurityStatus(fd, &op, &cp, &kp0, &kp1, &ip, &sp);
+ if (result != SECSuccess)
+ return;
+ fprintf(outfile,
+ " bulk cipher %s, %d secret key bits, %d key bits, status: %d\n"
+ " subject DN:\n %s\n"
+ " issuer DN:\n %s\n",
+ cp, kp1, kp0, op, sp, ip);
+ PR_Free(cp);
+ PR_Free(ip);
+ PR_Free(sp);
+
+ fprintf(outfile,
+ " %ld cache hits; %ld cache misses, %ld cache not reusable\n",
+ ssl3stats->hch_sid_cache_hits, ssl3stats->hch_sid_cache_misses,
+ ssl3stats->hch_sid_cache_not_ok);
+}
+
+/**************************************************************************
+** Begin thread management routines and data.
+**************************************************************************/
+
+void
+thread_wrapper(void *arg)
+{
+ GlobalThreadMgr *threadMGR = (GlobalThreadMgr *)arg;
+ perThread *slot = &threadMGR->threads[threadMGR->index];
+
+ /* wait for parent to finish launching us before proceeding. */
+ PR_Lock(threadMGR->threadLock);
+ PR_Unlock(threadMGR->threadLock);
+
+ slot->rv = (*slot->startFunc)(slot->a, slot->b);
+
+ PR_Lock(threadMGR->threadLock);
+ slot->running = rs_zombie;
+
+ /* notify the thread exit handler. */
+ PR_NotifyCondVar(threadMGR->threadEndQ);
+
+ PR_Unlock(threadMGR->threadLock);
+}
+
+SECStatus
+launch_thread(GlobalThreadMgr *threadMGR,
+ startFn *startFunc,
+ void *a,
+ int b)
+{
+ perThread *slot;
+ int i;
+
+ if (!threadMGR->threadStartQ) {
+ threadMGR->threadLock = PR_NewLock();
+ threadMGR->threadStartQ = PR_NewCondVar(threadMGR->threadLock);
+ threadMGR->threadEndQ = PR_NewCondVar(threadMGR->threadLock);
+ }
+ PR_Lock(threadMGR->threadLock);
+ while (threadMGR->numRunning >= MAX_THREADS) {
+ PR_WaitCondVar(threadMGR->threadStartQ, PR_INTERVAL_NO_TIMEOUT);
+ }
+ for (i = 0; i < threadMGR->numUsed; ++i) {
+ slot = &threadMGR->threads[i];
+ if (slot->running == rs_idle)
+ break;
+ }
+ if (i >= threadMGR->numUsed) {
+ if (i >= MAX_THREADS) {
+ /* something's really wrong here. */
+ PORT_Assert(i < MAX_THREADS);
+ PR_Unlock(threadMGR->threadLock);
+ return SECFailure;
+ }
+ ++(threadMGR->numUsed);
+ PORT_Assert(threadMGR->numUsed == i + 1);
+ slot = &threadMGR->threads[i];
+ }
+
+ slot->a = a;
+ slot->b = b;
+ slot->startFunc = startFunc;
+
+ threadMGR->index = i;
+
+ slot->prThread = PR_CreateThread(PR_USER_THREAD,
+ thread_wrapper, threadMGR,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD, 0);
+
+ if (slot->prThread == NULL) {
+ PR_Unlock(threadMGR->threadLock);
+ printf("Failed to launch thread!\n");
+ return SECFailure;
+ }
+
+ slot->inUse = 1;
+ slot->running = 1;
+ ++(threadMGR->numRunning);
+ PR_Unlock(threadMGR->threadLock);
+
+ return SECSuccess;
+}
+
+SECStatus
+reap_threads(GlobalThreadMgr *threadMGR)
+{
+ perThread *slot;
+ int i;
+
+ if (!threadMGR->threadLock)
+ return SECSuccess;
+ PR_Lock(threadMGR->threadLock);
+ while (threadMGR->numRunning > 0) {
+ PR_WaitCondVar(threadMGR->threadEndQ, PR_INTERVAL_NO_TIMEOUT);
+ for (i = 0; i < threadMGR->numUsed; ++i) {
+ slot = &threadMGR->threads[i];
+ if (slot->running == rs_zombie) {
+ /* Handle cleanup of thread here. */
+
+ /* Now make sure the thread has ended OK. */
+ PR_JoinThread(slot->prThread);
+ slot->running = rs_idle;
+ --threadMGR->numRunning;
+
+ /* notify the thread launcher. */
+ PR_NotifyCondVar(threadMGR->threadStartQ);
+ }
+ }
+ }
+
+ /* Safety Sam sez: make sure count is right. */
+ for (i = 0; i < threadMGR->numUsed; ++i) {
+ slot = &threadMGR->threads[i];
+ if (slot->running != rs_idle) {
+ fprintf(stderr, "Thread in slot %d is in state %d!\n",
+ i, slot->running);
+ }
+ }
+ PR_Unlock(threadMGR->threadLock);
+ return SECSuccess;
+}
+
+void
+destroy_thread_data(GlobalThreadMgr *threadMGR)
+{
+ PORT_Memset(threadMGR->threads, 0, sizeof(threadMGR->threads));
+
+ if (threadMGR->threadEndQ) {
+ PR_DestroyCondVar(threadMGR->threadEndQ);
+ threadMGR->threadEndQ = NULL;
+ }
+ if (threadMGR->threadStartQ) {
+ PR_DestroyCondVar(threadMGR->threadStartQ);
+ threadMGR->threadStartQ = NULL;
+ }
+ if (threadMGR->threadLock) {
+ PR_DestroyLock(threadMGR->threadLock);
+ threadMGR->threadLock = NULL;
+ }
+}
+
+/**************************************************************************
+** End thread management routines.
+**************************************************************************/
+
+void
+lockedVars_Init(lockedVars *lv)
+{
+ lv->count = 0;
+ lv->waiters = 0;
+ lv->lock = PR_NewLock();
+ lv->condVar = PR_NewCondVar(lv->lock);
+}
+
+void
+lockedVars_Destroy(lockedVars *lv)
+{
+ PR_DestroyCondVar(lv->condVar);
+ lv->condVar = NULL;
+
+ PR_DestroyLock(lv->lock);
+ lv->lock = NULL;
+}
+
+void
+lockedVars_WaitForDone(lockedVars *lv)
+{
+ PR_Lock(lv->lock);
+ while (lv->count > 0) {
+ PR_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(lv->lock);
+}
+
+int /* returns count */
+ lockedVars_AddToCount(lockedVars *lv, int addend)
+{
+ int rv;
+
+ PR_Lock(lv->lock);
+ rv = lv->count += addend;
+ if (rv <= 0) {
+ PR_NotifyCondVar(lv->condVar);
+ }
+ PR_Unlock(lv->lock);
+ return rv;
+}
+
+/*
+ * Dump cert chain in to cert.* files. This function is will
+ * create collisions while dumping cert chains if called from
+ * multiple treads. But it should not be a problem since we
+ * consider vfyserv to be single threaded(see bug 353477).
+ */
+
+void
+dumpCertChain(CERTCertificate *cert, SECCertUsage usage)
+{
+ CERTCertificateList *certList;
+ unsigned int count = 0;
+
+ certList = CERT_CertChainFromCert(cert, usage, PR_TRUE);
+ if (certList == NULL) {
+ errWarn("CERT_CertChainFromCert");
+ return;
+ }
+
+ for (count = 0; count < (unsigned int)certList->len; count++) {
+ char certFileName[16];
+ PRFileDesc *cfd;
+
+ PR_snprintf(certFileName, sizeof certFileName, "cert.%03d",
+ count);
+ cfd = PR_Open(certFileName, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0664);
+ if (!cfd) {
+ PR_fprintf(PR_STDOUT,
+ "Error: couldn't save cert der in file '%s'\n",
+ certFileName);
+ } else {
+ PR_Write(cfd, certList->certs[count].data, certList->certs[count].len);
+ PR_Close(cfd);
+ PR_fprintf(PR_STDOUT, "Cert file %s was created.\n", certFileName);
+ }
+ }
+ CERT_DestroyCertificateList(certList);
+}